I am trying to check one concept of mixing Static moxy and Dynamic moxy.
I have two schemas.
One is the base schema(emp.xsd) which is not going to change often,so I used the static Moxy and generated classes for it, added those classes to classpath, and used these concrete types(e.g. SearchManager) in my program.
Another is the derived schema(Manager.xsd) which is going to change often, so I plan to use Dynamic Moxy to generate the dynamic types on the fly.I am facing some issues mentioned below.
Is this kind of mix of static and dynamic moxy possible?
code snippet:
emp.xsd(parent schema):
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:emp="Employee:2:0" targetNamespace="Employee:2:0"
elementFormDefault="unqualified" attributeFormDefault="unqualified"
version="2.0">
<xsd:element name="searchManager" type="emp:SearchManager" />
<xsd:complexType name="SearchManager">
<xsd:sequence>
<xsd:element name="CompanyName" type="xsd:string" />
<xsd:element name="objects" type="emp:Employee" minOccurs="0" maxOccurs="unbounded" />
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="Employee">
<xsd:complexContent>
<xsd:extension base="emp:Organization">
<xsd:sequence>
<xsd:element name="EmpId" type="xsd:string" minOccurs="0" />
</xsd:sequence>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
<xsd:complexType name="Projects">
<xsd:complexContent>
<xsd:extension base="emp:Organization"/>
</xsd:complexContent>
</xsd:complexType>
<xsd:complexType name="Organization">
<xsd:annotation>
<xsd:documentation>Abstract base class </xsd:documentation>
</xsd:annotation>
</xsd:complexType>
</xsd:schema>
manager.xsd (Child schema):
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema targetNamespace="Manager:1:0" xmlns:emp="Employee:2:0"
xmlns:manager="Manager:1:0" xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="unqualified" attributeFormDefault="unqualified"
version="1.0">
<!-- schema imports -->
<xs:import namespace="Employee:2:0" schemaLocation="emp.xsd" />
<xs:complexType name="Manager">
<xs:annotation>
<xs:documentation>
Definition of class Employee
</xs:documentation>
</xs:annotation>
<xs:complexContent>
<xs:extension base="emp:Employee">
<xs:sequence>
<xs:element name="teamSize" type="xsd:int" minOccurs="0" />
<xs:element name="project1" type="manager:Project1"
minOccurs="0" maxOccurs="unbounded" />
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="Project1">
<xs:complexContent>
<xs:extension base="manager:Developement">
<xs:sequence>
<xs:element name="type" type="xsd:int" minOccurs="0" />
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="Developement">
<xs:annotation>
<xs:documentation>
Abstract base class for an Development
</xs:documentation>
</xs:annotation>
<xs:complexContent>
<xs:extension base="emp:Projects"/>
</xs:complexContent>
</xs:complexType>
</xs:schema>
Java code for marshalling and unmarshalling:
public class XMLToJSONUsingBaseClasses {
public static void main(String[] args) {
FileInputStream xsdInputStream;
try {
xsdInputStream = new FileInputStream("Manager.xsd");
DynamicJAXBContext jaxbContext = DynamicJAXBContextFactory.createContextFromXSD(xsdInputStream, new MyEntityResolver(), null, null);
FileInputStream xmlInputStream = new FileInputStream("manager.xml");
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
SearchManager manager = (SearchManager) unmarshaller.unmarshal(xmlInputStream);
}catch (JAXBException e) {
e.printStackTrace();
}catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
manager.xml
<emp:searchManager xmlns:emp="Employee:2:0"
xmlns:manager="Manager:1:0">
<CompanyName>Test</CompanyName>
<objects xmlns:ns2="Manager:1:0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ns2:Manager">
<EmpId>123456</EmpId>
<teamSize>10</teamSize>
<project1>
<type>1</type>
</project1>
</objects>
</emp:searchManager>
exception.
Exception Description: An error occurred unmarshalling the document
Internal Exception: java.lang.ClassCastException: employee._2._0.SearchManager cannot be cast to org.eclipse.persistence.internal.dynamic.DynamicEntityImpl
at org.eclipse.persistence.exceptions.XMLMarshalException.unmarshalException(XMLMarshalException.java:114)
at org.eclipse.persistence.internal.oxm.record.SAXUnmarshaller.convertSAXException(SAXUnmarshaller.java:996)
at org.eclipse.persistence.internal.oxm.record.SAXUnmarshaller.unmarshal(SAXUnmarshaller.java:903)
at org.eclipse.persistence.oxm.XMLUnmarshaller.unmarshal(XMLUnmarshaller.java:659)
at org.eclipse.persistence.jaxb.JAXBUnmarshaller.unmarshal(JAXBUnmarshaller.java:585)
... 2 more
Caused by: java.lang.ClassCastException: employee._2._0.SearchManager cannot be cast to org.eclipse.persistence.internal.dynamic.DynamicEntityImpl
at org.eclipse.persistence.internal.dynamic.ValuesAccessor.setAttributeValueInObject(ValuesAccessor.java:60)
at org.eclipse.persistence.oxm.mappings.XMLDirectMapping.setAttributeValueInObject(XMLDirectMapping.java:408)
at org.eclipse.persistence.internal.oxm.record.ObjectUnmarshalContext.setAttributeValue(ObjectUnmarshalContext.java:41)
at org.eclipse.persistence.internal.oxm.record.UnmarshalRecordImpl.setAttributeValue(UnmarshalRecordImpl.java:1400)
at org.eclipse.persistence.internal.oxm.XMLDirectMappingNodeValue.endElement(XMLDirectMappingNodeValue.java:193)
at org.eclipse.persistence.internal.oxm.record.UnmarshalRecordImpl.endElement(UnmarshalRecordImpl.java:1026)
at org.eclipse.persistence.internal.oxm.record.XMLStreamReaderReader.parseEvent(XMLStreamReaderReader.java:154)
at org.eclipse.persistence.internal.oxm.record.XMLStreamReaderReader.parse(XMLStreamReaderReader.java:99)
at org.eclipse.persistence.internal.oxm.record.XMLStreamReaderReader.parse(XMLStreamReaderReader.java:86)
at org.eclipse.persistence.internal.oxm.record.SAXUnmarshaller.unmarshal(SAXUnmarshaller.java:895)
... 4 more
Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group.
We do not currently support mixing static and dynamic in that way. Could you please use the link below to enter an enhancement request for your use case:
https://bugs.eclipse.org/bugs/enter_bug.cgi?product=EclipseLink
Related
[com.sun.istack.SAXParseException2; lineNumber: 1; columnNumber: 1; unexpected element (uri:"http://service.example.com/", local:"custDetails"). Expected elements are <{http://schemas.xmlsoap.org/soap/envelope/}Body>,<{}Customer>,<{http://schemas.xmlsoap.org/soap/envelope/}Envelope>,<{http://schemas.xmlsoap.org/soap/envelope/}Fault>,<{http://schemas.xmlsoap.org/soap/envelope/}Header>]
Problem statement: Camel is not expecting to receive the custDetails (webmethod) and the namespace.
Expectation : to use camel-soap to unmarshal the payload to soapJaxb out of the box.
Generated JAXB classes using maven-jaxb2-plugin for the xsd below. Results produced three classes with annotations - Customer.java, ObjectFactory,java , Order.java.
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified"
attributeFormDefault="unqualified"
>
<xs:element name="Customer">
<xs:complexType >
<xs:sequence>
<xs:element name="Id" type="xs:string"/>
<xs:element name="Address" type="xs:string"/>
<xs:element name="ListOfOrders" type="order" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="order">
<xs:sequence>
<xs:element name="Id" type="xs:string"/>
<xs:element name="ProductName" type="xs:string"/>
<xs:element name="ListOfDevice" minOccurs="0" >
<xs:complexType>
<xs:sequence>
<xs:element name="DeviceName" type="xs:string"/>
<xs:element name="ManufactureDate" type="xs:date"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:schema>
Expose webservice custDetails(..) as follows using cxf endpoint with DataFormat set to PAYLOAD. [UPDATED with #Configuration]
#Configuration
public class WebServiceConfig {
#Autowired
private Bus bus;
#Bean
public CxfEndpoint getCustomerDetails() {
CxfEndpoint cxfEndpoint = new CxfEndpoint();
cxfEndpoint.setAddress("/customerProvide");
cxfEndpoint.setServiceClass(CustomerSvc.class);
cxfEndpoint.setBus(bus);
cxfEndpoint.setDataFormat(DataFormat.PAYLOAD);return cxfEndpoint ;}
#Webservice
public interface CustomerSvc {
#WebMethod
Customer custDetails ( #WebParam(name="Customer")Customer Customer ) ;}
// Simple route in Route class.
#Component
public class CustomerRoute extends RouteBuilder {
public void configure (){
SoapJaxbDataFormat soapDF
= new SoapJaxbDataFormat("com.example.service", new TypeNameStrategy());
from("cxf:bean:getCustomerDetails").unmarshal(soapDF)
.log("receive : ${body}")
}
Wsdl generated and imported to soapUI. sample SOAPUI request to test is as follows.
<soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ser="http://service.example.com/">
<soapenv:Header/>
<soapenv:Body>
<ser:custDetails>
<ser:Customer>
<Id>1-abc</Id>
<Address>23 Sydney Oxley road</Address>
<ListOfOrders>
<Id>P1344</Id>
<ProductName>DRAM</ProductName>
<ListOfDevice>
<DeviceName>20nm</DeviceName>
<ManufactureDate>15-8-2017</ManufactureDate>
</ListOfDevice>
</ListOfOrders>
</ser:Customer>
</ser:custDetails>
</soapenv:Body>
</soapenv:Envelope>
When I try to unmarshal PAYLOAD with soap dataformat, camel is throwing an error. It is the hitting namespace error. I am not sure why package-info class is not generated. Any help is greatly appreciated. Thank you.
UPDATE, wsdl given below.
<?xml version='1.0' encoding='UTF-8'?><wsdl:definitions xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://service.example.com/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:ns1="http://schemas.xmlsoap.org/soap/http" name="CustomerSvcService" targetNamespace="http://service.example.com/">
<wsdl:types>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://service.example.com/" attributeFormDefault="unqualified" elementFormDefault="unqualified" targetNamespace="http://service.example.com/">
<xs:element name="Customer">
<xs:complexType>
<xs:sequence>
<xs:element name="Id" type="xs:string"/>
<xs:element name="Address" type="xs:string"/>
<xs:element minOccurs="0" name="ListOfOrders" type="tns:order"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="order">
<xs:sequence>
<xs:element name="Id" type="xs:string"/>
<xs:element name="ProductName" type="xs:string"/>
<xs:element minOccurs="0" name="ListOfDevice">
<xs:complexType>
<xs:sequence>
<xs:element name="DeviceName" type="xs:string"/>
<xs:element name="ManufactureDate" type="xs:date"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
<xs:element name="custDetails" type="tns:custDetails"/>
<xs:complexType name="custDetails">
<xs:sequence>
<xs:element minOccurs="0" ref="tns:Customer"/>
</xs:sequence>
</xs:complexType>
<xs:element name="custDetailsResponse" type="tns:custDetailsResponse"/>
<xs:complexType name="custDetailsResponse">
<xs:sequence>
<xs:element minOccurs="0" ref="tns:Customer"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
</wsdl:types>
<wsdl:message name="custDetails">
<wsdl:part element="tns:custDetails" name="parameters">
</wsdl:part>
</wsdl:message>
<wsdl:message name="custDetailsResponse">
<wsdl:part element="tns:custDetailsResponse" name="parameters">
</wsdl:part>
</wsdl:message>
<wsdl:portType name="CustomerSvc">
<wsdl:operation name="custDetails">
<wsdl:input message="tns:custDetails" name="custDetails">
</wsdl:input>
<wsdl:output message="tns:custDetailsResponse" name="custDetailsResponse">
</wsdl:output>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="CustomerSvcServiceSoapBinding" type="tns:CustomerSvc">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="custDetails">
<soap:operation soapAction="" style="document"/>
<wsdl:input name="custDetails">
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output name="custDetailsResponse">
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="CustomerSvcService">
<wsdl:port binding="tns:CustomerSvcServiceSoapBinding" name="CustomerSvcPort">
<soap:address location="http://localhost:12000/services/customerProvide"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
EDIT due to updated question
You try to unmarshal the request payload with Jax-B based on the XML schema you posted at the top of your question.
But in this schema the element custDetails does not exist. It exists in the schema part of your WSDL, but not in the schema?!? Therefore the error unexpected element.
I need to save a generic dataset generated from SQL query result as XML. I'd like do add metadata to my resultset in order to make it reversible so anyone can create a DB table starting from the XML and load the data.
I was wondering if there is a standard XML format that can address this issue.
You did not mention your RDBMS. For SQL Server you might use FOR XML RAW together with XMLDATA or XMLSCHEMA:
DECLARE #Dummy TABLE(ID INT IDENTITY,SomeText VARCHAR(100) NOT NULL, SomeInt INT);
INSERT INTO #Dummy VALUES('row 1',1),('row 2',2);
Example XMLDATA
SELECT * FROM #Dummy FOR XML RAW,XMLDATA
<Schema name="Schema2" xmlns="urn:schemas-microsoft-com:xml-data" xmlns:dt="urn:schemas-microsoft-com:datatypes">
<ElementType name="row" content="empty" model="closed">
<AttributeType name="ID" dt:type="i4" />
<AttributeType name="SomeText" dt:type="string" />
<AttributeType name="SomeInt" dt:type="i4" />
<attribute type="ID" />
<attribute type="SomeText" />
<attribute type="SomeInt" />
</ElementType>
</Schema>
<row xmlns="x-schema:#Schema2" ID="1" SomeText="row 1" SomeInt="1" />
<row xmlns="x-schema:#Schema2" ID="2" SomeText="row 2" SomeInt="2" />
Example XMLSCHEMA (more details)
SELECT * FROM #Dummy FOR XML RAW,XMLSCHEMA
<xsd:schema targetNamespace="urn:schemas-microsoft-com:sql:SqlRowSet2" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:sqltypes="http://schemas.microsoft.com/sqlserver/2004/sqltypes" elementFormDefault="qualified">
<xsd:import namespace="http://schemas.microsoft.com/sqlserver/2004/sqltypes" schemaLocation="http://schemas.microsoft.com/sqlserver/2004/sqltypes/sqltypes.xsd" />
<xsd:element name="row">
<xsd:complexType>
<xsd:attribute name="ID" type="sqltypes:int" use="required" />
<xsd:attribute name="SomeText" use="required">
<xsd:simpleType>
<xsd:restriction base="sqltypes:varchar" sqltypes:localeId="1033" sqltypes:sqlCompareOptions="IgnoreCase IgnoreKanaType IgnoreWidth">
<xsd:maxLength value="100" />
</xsd:restriction>
</xsd:simpleType>
</xsd:attribute>
<xsd:attribute name="SomeInt" type="sqltypes:int" />
</xsd:complexType>
</xsd:element>
</xsd:schema>
<row xmlns="urn:schemas-microsoft-com:sql:SqlRowSet2" ID="1" SomeText="row 1" SomeInt="1" />
<row xmlns="urn:schemas-microsoft-com:sql:SqlRowSet2" ID="2" SomeText="row 2" SomeInt="2" />
Standard-Schema .Net
Following jdweng's comment this is an approach with C#:
var ds = new System.Data.DataSet("SomeName");
ds.Tables.Add("SomeTable");
ds.Tables.Add("OneMoreTable");
var t1 = ds.Tables["SomeTable"];
t1.Columns.Add("SomeInt", typeof(int));
t1.Columns.Add("SomeString", typeof(string));
var t2 = ds.Tables["OneMoreTable"];
t2.Columns.Add("SomeInt", typeof(int));
t2.Columns.Add("SomeDate", typeof(DateTime));
t1.Rows.Add(new object[] { 1, "test 1" });
t1.Rows.Add(new object[] { 2, "test 2" });
t1.Rows.Add(new object[] { 3, "test 3" });
t2.Rows.Add(new object[] { 1, DateTime.Now });
ds.WriteXml(#"c:\SomePath\test.dataset", XmlWriteMode.WriteSchema);
This is the written content (embedded schema and data)
<?xml version="1.0" standalone="yes"?>
<SomeName>
<xs:schema id="SomeName" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xs:element name="SomeName" msdata:IsDataSet="true" msdata:UseCurrentLocale="true">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="SomeTable">
<xs:complexType>
<xs:sequence>
<xs:element name="SomeInt" type="xs:int" minOccurs="0" />
<xs:element name="SomeString" type="xs:string" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="OneMoreTable">
<xs:complexType>
<xs:sequence>
<xs:element name="SomeInt" type="xs:int" minOccurs="0" />
<xs:element name="SomeDate" type="xs:dateTime" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>
<SomeTable>
<SomeInt>1</SomeInt>
<SomeString>test 1</SomeString>
</SomeTable>
<SomeTable>
<SomeInt>2</SomeInt>
<SomeString>test 2</SomeString>
</SomeTable>
<SomeTable>
<SomeInt>3</SomeInt>
<SomeString>test 3</SomeString>
</SomeTable>
<OneMoreTable>
<SomeInt>1</SomeInt>
<SomeDate>2017-02-02T10:23:39.2277162+01:00</SomeDate>
</OneMoreTable>
</SomeName>
I'm having a problem getting the soap 1.1 fault detail element using a .NET 4.5 WCF client for UPS RateWS service.
The issue is that while the faultcode and faultstring elements are coming back fine as .Code and .Message properties on the exception. The detail object is not being deserialized correctly and is always an empty array.
I'm generating the WCF client by unpacking the wsdl and xsds from the UPS Rating developer kit Rates_Pkg_Gnd.zip file SCHEMA-WSDLs directory and pointing Visual Studio 2013s Add Service Reference dialog at the RateWS.wsdl on my file system.
An actual wire soap fault message looks like this:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header />
<soapenv:Body>
<soapenv:Fault>
<faultcode>Client</faultcode>
<faultstring>An exception has been raised as a result of client data.</faultstring>
<detail>
<err:Errors xmlns:err="http://www.ups.com/XMLSchema/XOLTWS/Error/v1.1">
<err:ErrorDetail>
<err:Severity>Hard</err:Severity>
<err:PrimaryErrorCode>
<err:Code>111285</err:Code>
<err:Description>The postal code 21740 is invalid for AB Canada.</err:Description>
</err:PrimaryErrorCode>
</err:ErrorDetail>
</err:Errors>
</detail>
</soapenv:Fault>
</soapenv:Body>
</soapenv:Envelope>
I have tried catching System.ServiceModel.FaultException<UPS.RateService.ErrorDetailType[]> but the Detail property is always an array of UPS.RateService.ErrorDetailType[0] -- zero size.
Similarly catching a FaultException and calling .CreateMessageFault() to access .GetDetail<XmlElement>() yields an XML object containing an ArrayOfErrorDetailType element with nothing in it. The alternate approach of using .GetReaderAtDetailContents() to get an XmlReader yields the same bogus structure.
This is the error message xsd:
<?xml version="1.0" encoding="utf-8"?>
<xsd:schema xmlns:error="http://www.ups.com/XMLSchema/XOLTWS/Error/v1.1" elementFormDefault="qualified" targetNamespace="http://www.ups.com/XMLSchema/XOLTWS/Error/v1.1" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="Errors">
<xsd:complexType>
<xsd:sequence>
<xsd:element maxOccurs="unbounded" name="ErrorDetail" type="error:ErrorDetailType" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:complexType name="ErrorDetailType">
<xsd:sequence>
<xsd:element name="Severity" type="xsd:string" />
<xsd:element name="PrimaryErrorCode" type="error:CodeType" />
<xsd:element minOccurs="0" name="MinimumRetrySeconds" type="xsd:string" />
<xsd:element minOccurs="0" name="Location" type="error:LocationType" />
<xsd:element minOccurs="0" maxOccurs="unbounded" name="SubErrorCode" type="error:CodeType" />
<xsd:element minOccurs="0" maxOccurs="unbounded" name="AdditionalInformation" type="error:AdditionalInfoType" />
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CodeType">
<xsd:sequence>
<xsd:element name="Code" type="xsd:string" />
<xsd:element name="Description" type="xsd:string" />
<xsd:element minOccurs="0" name="Digest" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="AdditionalInfoType">
<xsd:sequence>
<xsd:element name="Type" type="xsd:string" />
<xsd:element maxOccurs="unbounded" name="Value" type="error:AdditionalCodeDescType" />
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="AdditionalCodeDescType">
<xsd:sequence>
<xsd:element name="Code" type="xsd:string" />
<xsd:element minOccurs="0" name="Description" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="LocationType">
<xsd:sequence>
<xsd:element minOccurs="0" name="LocationElementName" type="xsd:string" />
<xsd:element minOccurs="0" name="XPathOfElement" type="xsd:string" />
<xsd:element minOccurs="0" name="OriginalValue" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
I realise this is an old Q, but I found the solution on another question - FaultException.Detail coming back empty
Renaming the generated class from ErrorDetailType to ErrorDetail meant I could iterate the errors.
To get this to work I added a dummy element inside the sequence:
<xsd:element name="Errors">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="ErrorDetail" type="error:ErrorDetailType" maxOccurs="unbounded"/>
<xsd:element name="TestElement" type="xsd:string" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
For some reason that allows WCF to serialize the fault correctly. This forces WCF to generate a new class "Errors" that is passed in the fault contract. You could then catch the FaultException<Errors> exception and have access to the ErrorDetailType[].
Ultimately the solution I found was modify the WSDL so that the contents of the <detail /> element are not defined and use svcutil to generate the proxy classes. When I do this, I get access to the raw <err:Errors /> XML element:
var fault = ex.CreateMessageFault();
var faultXml = fault.GetDetail<XmlElement>();
This allows me to use XPath to get at the contents of the err:Description element. With the original WSDL, I get nothing.
I am getting info from a database and adding it to a dataset. Then I create a XML with this info. I would want to have the XML, but also the datatypes in the header. Is it possible?
Here my code to write the XML:
//Fill dataset with different datatable:
//first datatable
DataSet imports = new DataSet("import");
NpgsqlDataAdapter daImport = new NpgsqlDataAdapter("select field1, field2 field3 from table1", _connPg);
daImport.FillSchema(imports, SchemaType.Source, "table1");
daImport.Fill(imports, "table1");
//seconda datatable
NpgsqlDataAdapter daImport1 = new NpgsqlDataAdapter("select field1, field2 field3 from table2", _connPg);
daImport1.FillSchema(imports, SchemaType.Source, "table2");
daImport1.Fill(imports, "table2");
//insert relation
DataRelation relation = new DataRelation("rel_rel1", imports.Tables["table1"].Columns["field1"], imports.Tables["table2"].Columns["field2"], true);
relation.Nested = true;
imports.Relations.Add(relation);
//write xml
imports.WriteXml("dataImport.xml");
And this is my xml
<?xml version="1.0" standalone="yes"?>
<import>
<table1>
<field1>1
</field1>
<field2>name
</field2>
<field3>surname
</field3>
<table2>
<field1>somedata
</field1>
<field2>1
</field2>
<field3>otherdata
</field3>
</table2>
</table1>
</import>
What I want?
I would want to get this XML but with the types of the fields defined in the header.
Thanks!
If you want the schema to be serialized with the data, just change :
imports.WriteXml("dataImport.xml");
to :
imports.WriteXml("dataImport.xml", XmlWriteMode.WriteSchema);
It will produce the following XML :
<?xml version="1.0" standalone="yes"?>
<import>
<xs:schema id="import" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xs:element name="import" msdata:IsDataSet="true" msdata:UseCurrentLocale="true">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="table1">
<xs:complexType>
<xs:sequence>
<xs:element name="field1" type="xs:int" />
<xs:element name="field2" type="xs:string" minOccurs="0" />
<xs:element name="field3" type="xs:boolean" minOccurs="0" />
<xs:element name="table2" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="field1" type="xs:int" />
<xs:element name="field2" type="xs:int" minOccurs="0" />
<xs:element name="field3" type="xs:double" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
<xs:unique name="table2_Constraint1" msdata:ConstraintName="Constraint1" msdata:PrimaryKey="true">
<xs:selector xpath=".//table2" />
<xs:field xpath="field1" />
</xs:unique>
<xs:unique name="Constraint1" msdata:PrimaryKey="true">
<xs:selector xpath=".//table1" />
<xs:field xpath="field1" />
</xs:unique>
<xs:keyref name="FK_T1T2" refer="Constraint1" msdata:IsNested="true">
<xs:selector xpath=".//table2" />
<xs:field xpath="field2" />
</xs:keyref>
</xs:element>
</xs:schema>
<table1>
<field1>0</field1>
<field2>test</field2>
<field3>false</field3>
<table2>
<field1>0</field1>
<field2>0</field2>
<field3>0</field3>
</table2>
<table2>
<field1>1</field1>
<field2>0</field2>
<field3>1.25</field3>
</table2>
</table1>
<table1>
<field1>1</field1>
<field2>test 2</field2>
<field3>true</field3>
</table1>
<table1>
<field1>2</field1>
<field2>test 3</field2>
<field3>false</field3>
<table2>
<field1>2</field1>
<field2>2</field2>
<field3>2.66</field3>
</table2>
</table1>
</import>
In my XML schema I have an element being referenced tens of times by other elements but with different enumerated values for one of its attribute.
For now, instead of creating this element in global space and referencing it later, I am creating a new instance wherever it is needed. This approach has increased my schema size enormously because of repeated creation of almost same element many times. It also may have adverse effect on efficiency of the schema.
The only way that I see is to create element once and then reference it many times but my problem is: one of the attribute of this referenced element is required to have a different set of enumerations for each referencing element.
My question is:
Is it possible to to add an attribute to a "Referenced Element" in XML Schema?
Something like this:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.myDomain.com" xmlns="http://www.myDomain.com" elementFormDefault="qualified">
<xs:simpleType name="myValues1">
<xs:restriction base="xs:string">
<xs:enumeration value="value1" />
<xs:enumeration value="value2" />
</xs:restriction>
</xs:simpleType>
<xs:element name="myElement">
<xs:complexType mixed="true">
<xs:attribute name="attr1" type="xs:string" />
<xs:attribute name="attr2" type="xs:string" />
</xs:complexType>
</xs:element>
<xs:element name="MainElement1">
<xs:complexType>
<xs:sequence>
<xs:element ref="myElement">
<xs:complexType>
<xs:attribute name="myAtt" type="myValues1" />
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="mainAtt1" />
</xs:complexType>
</xs:element>
</xs:schema>
Or can we change type of an existing attribute of a "Referenced Element" in XML Schema?
something like this:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.myDomain.com" xmlns="http://www.myDomain.com" elementFormDefault="qualified">
<xs:simpleType name="myValues1">
<xs:restriction base="xs:string">
<xs:enumeration value="value1" />
<xs:enumeration value="value2" />
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="myValues2">
<xs:restriction base="xs:string">
<xs:enumeration value="value3" />
<xs:enumeration value="value4" />
</xs:restriction>
</xs:simpleType>
<xs:element name="myElement">
<xs:complexType mixed="true">
<xs:attribute name="attr1" type="xs:string" />
<xs:attribute name="attr2" type="xs:string" />
<xs:attribute name="myAtt" type="myValues1" />
</xs:complexType>
</xs:element>
<xs:element name="MainElement1">
<xs:complexType>
<xs:sequence>
<xs:element ref="myElement">
<xs:complexType>
<xs:attribute name="myAtt" type="myValues2" />
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="mainAtt1" />
</xs:complexType>
</xs:element>
</xs:schema>
You cannot override the content model of a referenced element. The point of the reference is that it points to exactly the same element every time.
If you really want the element to have different content, you are better off defining multiple global complex types and using them, rather than using an element reference:
<xs:complexType name="Type1" mixed="true">
<xs:attribute name="attr1" type="xs:string" />
<xs:attribute name="attr2" type="xs:string" />
<xs:attribute name="myAtt" type="myValues1" />
</xs:complexType>
<xs:complexType name="Type2" mixed="true">
<xs:complexContent>
<xs:extension base="Type1">
<xs:attribute name="myAtt2" type="myValues2" />
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:element name="MainElement1">
<xs:complexType>
<xs:sequence>
<xs:element name="myElement" type="Type1"/>
</xs:sequence>
</xs:complexType>
</xs:element>
I would not worry too much about performance. The reference to the global types will be resolved only once at schema load time.