I am trying to deserialize xml into c# classes.
I followed some documentation and generated some c# classes using the commands xsd foo.xml & xsd foo.xsd /classes
one of the classess generated by commands. The only part that fails to bind is the getMLIstResult
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://schemas.xmlsoap.org/soap/envelope/")]
public partial class EnvelopeBodyGetMListResponse
{
private string[] getMListResultField;
/// <remarks/>
[System.Xml.Serialization.XmlArrayItemAttribute(IsNullable = false)]
public string[] GetMListResult
{
get
{
return this.getMListResultField;
}
set
{
this.getMListResultField = value;
}
}
}
the xml used to create the xsd
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<GetMListResponse xmlns="http://tempuri.org/">
<GetMListResult>
<string>string</string>
<string>string</string>
</GetListResult>
</GetListResponse>
</soap:Body>
</soap:Envelope>
xsd used to create the class
<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="Envelope" targetNamespace="http://schemas.xmlsoap.org/soap/envelope/" xmlns:mstns="http://schemas.xmlsoap.org/soap/envelope/" xmlns="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" attributeFormDefault="qualified" elementFormDefault="qualified" xmlns:app1="http://tempuri.org/">
<xs:import namespace="http://tempuri.org/" schemaLocation="Envelope_app1.xsd" />
<xs:element name="Envelope" msdata:IsDataSet="true" msdata:UseCurrentLocale="true" msdata:Prefix="soap">
<xs:complexType>
<xs:sequence>
<xs:element name="Body" msdata:Prefix="soap">
<xs:complexType>
<xs:sequence>
<xs:element name="GetMListResponse">
<xs:complexType>
<xs:sequence>
<xs:element name="GetMListResult">
<xs:complexType>
<xs:sequence>
<xs:element name="string" type="xs:string" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
a few things to note:
I am not able to change the way the xml is returned from an api I am trying to work with.
I also made a few changes to the xsd after it was generated.
serialization/deserialization works for the most part, but lists/arrays fail to bind
Related
I have a sample to read a xml schema set for a xml file which contains different namespaces. For this i can get different schema for each namespace as i explained below.
Sample File:
<?xml version="1.0" encoding="utf-8"?>
<data xmlns:d="http://sampleschema/dataservices" xmlns:m="http://sampleschema/dataservices/metadata">
<content>
<m:properties>
<d:CustomerID>ALFKI</d:CustomerID>
<d:CompanyName>Alfreds Futterkiste</d:CompanyName>
</m:properties>
</content>
</data>
Sample Code to get XML Schema Set:
strFileName = #"C:\Sample\Sample.xml";
XmlReader reader = XmlReader.Create(strFileName);
XmlSchemaInference schema = new XmlSchemaInference();
XmlSchemaSet schemaSet = schema.InferSchema(reader);
It gives three different types of schemas while using the above code. But my requirement will be i need a single schema for the entire xml file which contain any number of namespaces in it. I have checked with possibilities of codes in msdn and stack overflow. I can't find any proper solution for this.
The expected schema output will be like below.
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:element name="data">
<xs:complexType>
<xs:sequence>
<xs:element name="content">
<xs:complexType>
<xs:sequence>
<xs:element name="m:properties">
<xs:complexType>
<xs:sequence>
<xs:element name="d:CustomerID" type="xs:string"></xs:element>
<xs:element name="d:CompanyName" type="xs:string"></xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="xmlns:d" type="xs:string"></xs:attribute>
<xs:attribute name="xmlns:m" type="xs:string"></xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>
Any one can help to achieve this requirement.
Thanks in advance.
Try something like this :
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:m="http://www.w3.org/2001/XMLSchema" xmlns:d="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:element name="data">
<xs:complexType>
<xs:sequence>
<xs:element name="content">
<m:complexType>
<m:sequence>
<m:element name="properties">
<d:complexType>
<d:sequence>
<d:element name="CustomerID" type="xs:string"></d:element>
<d:element name="CompanyName" type="xs:string"></d:element>
</d:sequence>
</d:complexType>
</m:element>
</m:sequence>
</m:complexType>
</xs:element>
</xs:sequence>
<d:attribute name="xmlns_d" type="d:string"></d:attribute>
<m:attribute name="xmlns_m" type="d:string"></m:attribute>
</xs:complexType>
</xs:element>
</xs:schema>
Consider the following simple schema:
<xs:schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="MyRoot">
<xs:complexType>
<xs:sequence>
<xs:group ref="MyChoice" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:group name="MyChoice">
<xs:choice>
<xs:element name="a" type="xs:string"/>
<xs:element name="b" type="xs:string"/>
<xs:element name="c" type="xs:string"/>
</xs:choice>
</xs:group>
</xs:schema>
When turning this into C# code with xsd.exe (VS2017), I get the following output:
public partial class MyRoot {
private string[] aField;
private string[] bField;
private string[] cField;
// ... omitted for brevity ...
}
This code has a major problem: in the XSD/XML all of the sub-elements (a, b and c) were ordered.
This order is now lost in the C# class, since there are three different arrays for each of the sub elements.
Is xsd.exe doing it wrong? Or am I using it wrong? Or is the .xsd file flawed?
I want that users will write xml as this one:
<Root>
<Param>
<Int>134</Int>
</Param>
</Root>
or like this one:
<Root>
<Param>
<String>134</String>
</Param>
</Root>
AND, I want that the auto-generated C# code of this xsd (I use xsd.exe) will not generate new class for Param, but will simply use object.
First try
Now, when I write the xsd, I've started with this markup:
<?xml version="1.0" encoding="UTF-8" ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="Root">
<xs:complexType>
<xs:sequence>
<xs:choice>
<xs:element name="Int" type="xs:int"/>
<xs:element name="String" type="xs:string"/>
</xs:choice>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
which yield this good code
public partial class Root {
public object Item { get; set; }
}
BUT the xml will look like:
<Root>
<Int>134</Int>
</Root>
which is bad for my purposes.
Second try
So, I've tried to fix the xsd, and that what I have now:
<?xml version="1.0" encoding="UTF-8" ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="Root">
<xs:complexType>
<xs:sequence>
<xs:element name="Param">
<xs:complexType>
<xs:choice>
<xs:element name="Int" type="xs:int"/>
<xs:element name="String" type="xs:string"/>
</xs:choice>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
NOW, the xml is like i want (with "Param" element), BUT now the code is ugly:
public partial class Root {
public RootParam Param { get; set; }
}
public partial class RootParam {
public object Item { get; set; }
}
it creats unnessecery class (RootParam) that has in it only object. I would like to get code as beofre.
So...
How can I do it? How to force element in the XML, without creating stupid fake unnessecery class?
Is there any way to deserialize elements containing either simple text or subelement to a string with XmlSerializer?
Xml sample:
<Attribute>
<AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">thisistext</AttributeValue>
<AttributeValue>
<e:Authorities xmlns:e="urn:dummy">
<e:Authority>ORG_CHIEF</esia-encoder:Authority>
</e:Authorities>
</AttributeValue>
</Attribute>
C# property:
[XmlElement("AttributeValue", IsNullable = true)]
public string[] AttributeValue { get; set; }
Deserialization of the first AttributeValue succeed, but the next one fails. No wonder, beacause ReadElementString method expects simple or empty content. I'm looking for a way to tell to serializer "put content of this element to a string, whatever it contains".
Actually, the 2nd value you have in your XML is:
<e:Authorities xmlns:e="urn:dummy">
<e:Authority>ORG_CHIEF</esia-encoder:Authority>
</e:Authorities>
This is no valid string dataType which is expected because of:
public string[] AttributeValue {get; set;}
If you are able to define it in XSD, you can use XSD2Code or xsd.exe to create a class for the XSD to deserialize into.
What about this one?
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:element name="Attribute">
<xs:complexType>
<xs:sequence>
<xs:element name="AttributeValue" maxOccurs="unbounded">
<xs:complexType>
<xs:choice>
<xs:element name="AuthoritiesString" type="xs:string"/>
<xs:element name="AuthoritiesElement">
<xs:complexType>
<xs:sequence>
<xs:element name="Authority"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
I've been searching for an answer for quite some time without any luck.
I'm using NDbUnit for my test data and I want to be able to generate my XSD files automatically. I don't want to have to regenerate my XSD files each time I add a new property to my classes. So my plan is to automatically generate the XSD files using the XsdDataContractExporter class since some of my classes contain IList and I got some errors using the xml serializer.
this is the code I got so far:
XsdDataContractExporter exporter = new XsdDataContractExporter();
exporter.Export(typeof(Supplier));
//XmlQualifiedName xmlQualifiedName = exporter.GetRootElementName(typeof(Supplier));
foreach (XmlSchema schema in exporter.Schemas.Schemas()) {
XmlWriter writer = XmlWriter.Create(String.Format(#"..\..\data\{0}.xsd", GetSchemaName(schema)), new XmlWriterSettings() {
ConformanceLevel = ConformanceLevel.Auto,
Encoding = Encoding.UTF8,
Indent = true,
OmitXmlDeclaration = false
});
foreach (XmlSchemaObject include in schema.Includes) {
XmlSchemaImport importedSchema = include as XmlSchemaImport;
if (importedSchema != null) {
ArrayList lst = new ArrayList(exporter.Schemas.Schemas(importedSchema.Namespace));
XmlSchema actualImportedSchema = (XmlSchema)lst[0];
importedSchema.Schema = actualImportedSchema;
importedSchema.SchemaLocation = Path.GetFullPath(String.Format(#"..\..\data\{0}.xsd", GetSchemaName(actualImportedSchema)));
}
}
schema.Write(writer);
writer.Close();
}
DataSet ds = new DataSet();
ds.ReadXmlSchema(#"..\..\data\business.model.supplier.xsd");
the problem is that I get an error when reading the schema which is:
failed: System.InvalidOperationException : Nested table 'SupplierCategory' which inherits its namespace cannot have multiple parent tables in different namespaces.
The bottom line is, I want to use a dynamically generated XSD file from a type to use with NDBUnit to populate my database with test data. Is this the right approach ? This is the schema that are generated and that gives my the error:
Supplier:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:tns="http://schemas.datacontract.org/2004/07/Business.Model.Supplier" elementFormDefault="qualified" targetNamespace="http://schemas.datacontract.org/2004/07/Business.Model.Supplier" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:import schemaLocation="C:\dev\skeleton\branches\dev\src\testconsole\data\business.model.supplier.category.xsd" namespace="http://schemas.datacontract.org/2004/07/Business.Model.Supplier.Category" />
<xs:import schemaLocation="C:\dev\skeleton\branches\dev\src\testconsole\data\arrays.xsd" namespace="http://schemas.microsoft.com/2003/10/Serialization/Arrays" />
<xs:complexType name="Supplier">
<xs:sequence>
<xs:element minOccurs="0" name="Categories" nillable="true" xmlns:q1="http://schemas.datacontract.org/2004/07/Business.Model.Supplier.Category" type="q1:ArrayOfSupplierCategory" />
<xs:element minOccurs="0" name="Comments" nillable="true" xmlns:q2="http://schemas.microsoft.com/2003/10/Serialization/Arrays" type="q2:ArrayOfstring" />
<xs:element minOccurs="0" name="Description" nillable="true" type="xs:string" />
<xs:element minOccurs="0" name="Name" nillable="true" type="xs:string" />
</xs:sequence>
</xs:complexType>
<xs:element name="Supplier" nillable="true" type="tns:Supplier" />
</xs:schema>
SupplierCategory:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:tns="http://schemas.datacontract.org/2004/07/Business.Model.Supplier.Category" elementFormDefault="qualified" targetNamespace="http://schemas.datacontract.org/2004/07/Business.Model.Supplier.Category" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:complexType name="ArrayOfSupplierCategory">
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="unbounded" name="SupplierCategory" nillable="true" type="tns:SupplierCategory" />
</xs:sequence>
</xs:complexType>
<xs:element name="ArrayOfSupplierCategory" nillable="true" type="tns:ArrayOfSupplierCategory" />
<xs:complexType name="SupplierCategory">
<xs:sequence>
<xs:element minOccurs="0" name="Description" nillable="true" type="xs:string" />
</xs:sequence>
</xs:complexType>
<xs:element name="SupplierCategory" nillable="true" type="tns:SupplierCategory" />
</xs:schema>
Any advice would be great !
Thx,
Franck
See the list of suggestions in this post Getting XML Schema from MS SQL Database (specifically the top-voted answer) but also note my suggestion of using MyGeneration to achieve the same thing.
That's a problem I've also been facing quite a time later, as we were using NDbUnit for integration tests in our project – ended up with a custom library, which doesn't need a schema to be defined separately, it reads it from database on its own. Library is Reseed.