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've been given a number of XSD files - they are HUGE - for an insurance pricing engine, so as you can imagine, contain lots of nested complex types. Person, Address, Vehicles, Car Alarm, Speeding Convictions etc etc. Here's a subset containing a single complex type:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<xs:complexType name="Vehicle">
<xs:choice maxOccurs="unbounded">
<xs:element name="ABICode" type="ABICode" minOccurs="0"/>
<xs:element name="ABSBrakes" type="ABSBrakes" minOccurs="0"/>
<xs:element name="AgedOver" type="AgedOver" minOccurs="0"/>
<xs:element name="AlarmSecurityFitted" type="AlarmSecurityFitted" minOccurs="0"/>
<xs:element name="AlarmSecurityMake" type="AlarmSecurityMake" minOccurs="0"/>
<xs:element name="AudioValue" type="AudioValue" minOccurs="0"/>
<xs:element name="CarPhoneValue" type="CarPhoneValue" minOccurs="0"/>
<xs:element name="Colour" type="Colour" minOccurs="0"/>
<xs:element name="CountryOfManufacture" type="CountryOfManufacture" minOccurs="0"/>
<xs:element name="CoverType" type="CoverType" minOccurs="0"/>
<xs:element name="CurrentMileage" type="CurrentMileage" minOccurs="0"/>
<xs:element name="Doors" type="Doors" minOccurs="0"/>
<xs:element name="EngineSize" type="EngineSize" minOccurs="0"/>
<xs:element name="EstimatedValue" type="EstimatedValue" minOccurs="0"/>
<xs:element name="Finish" type="Finish" minOccurs="0"/>
<xs:element name="FuelType" type="FuelType" minOccurs="0"/>
<xs:element name="HasSecurity" type="HasSecurity" minOccurs="0"/>
<xs:element name="ImmobSecurityFitted" type="ImmobSecurityFitted" minOccurs="0"/>
<xs:element name="ImmobSecurityMake" type="ImmobSecurityMake" minOccurs="0"/>
<xs:element name="Keeper" type="Keeper" minOccurs="0"/>
<xs:element name="Lhd" type="Lhd" minOccurs="0"/>
<xs:element name="Modified" type="Modified" minOccurs="0"/>
<xs:element name="NCBCountry" type="NCBCountry" minOccurs="0"/>
<xs:element name="NCBProtected" type="NCBProtected" minOccurs="0"/>
<xs:element name="NCBType" type="NCBType" minOccurs="0"/>
<xs:element name="NCBYears" type="NCBYears" minOccurs="0"/>
<xs:element name="NightLocation" type="NightLocation" minOccurs="0"/>
<xs:element name="Owner" type="Owner" minOccurs="0"/>
<xs:element name="OvernightPostCode" type="OvernightPostCode" minOccurs="0"/>
<xs:element name="PermittedDrivers" type="PermittedDrivers" minOccurs="0"/>
<xs:element name="PricePaid" type="PricePaid" minOccurs="0"/>
<xs:element name="PurchaseDate" type="PurchaseDate" minOccurs="0"/>
<xs:element name="Registration" type="Registration" minOccurs="0"/>
<xs:element name="Seats" type="Seats" minOccurs="0"/>
<xs:element name="TrackerSecurityFitted" type="TrackerSecurityFitted" minOccurs="0"/>
<xs:element name="TrackerSecurityMake" type="TrackerSecurityMake" minOccurs="0"/>
<xs:element name="Transmission" type="Transmission" minOccurs="0"/>
<xs:element name="Type" type="Type" minOccurs="0"/>
<xs:element name="Windscreen" type="Windscreen" minOccurs="0"/>
<xs:element name="YearManufacture" type="YearManufacture" minOccurs="0"/>
<xs:element name="Modification" type="Modification" minOccurs="0" maxOccurs="5"/>
</xs:choice>
</xs:complexType>
</xs:schema>
I've successfully used xsd.exe and xsd2code to generate classes based on the schema definiitions, however, the classes that have been produced are not strongly typed, and contain arrays of Objects such as this:
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.6.1064.2")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
public partial class Vehicle
{
private object[] _items;
private ItemsChoiceType4[] _itemsElementName;
[System.Xml.Serialization.XmlElementAttribute("ABICode", typeof(string))]
[System.Xml.Serialization.XmlElementAttribute("ABSBrakes", typeof(ABSBrakes))]
[System.Xml.Serialization.XmlElementAttribute("AgedOver", typeof(string))]
[System.Xml.Serialization.XmlElementAttribute("AlarmSecurityFitted", typeof(AlarmSecurityFitted))]
[System.Xml.Serialization.XmlElementAttribute("AlarmSecurityMake", typeof(AlarmSecurityMake))]
[System.Xml.Serialization.XmlElementAttribute("AudioValue", typeof(string))]
[System.Xml.Serialization.XmlElementAttribute("CarPhoneValue", typeof(string))]
[System.Xml.Serialization.XmlElementAttribute("Colour", typeof(Colour))]
[System.Xml.Serialization.XmlElementAttribute("CountryOfManufacture", typeof(CountryOfManufacture))]
[System.Xml.Serialization.XmlElementAttribute("CoverType", typeof(CoverType))]
[System.Xml.Serialization.XmlElementAttribute("CurrentMileage", typeof(string))]
[System.Xml.Serialization.XmlElementAttribute("Doors", typeof(string))]
[System.Xml.Serialization.XmlElementAttribute("EngineSize", typeof(string))]
[System.Xml.Serialization.XmlElementAttribute("EstimatedValue", typeof(string))]
[System.Xml.Serialization.XmlElementAttribute("Finish", typeof(Finish))]
[System.Xml.Serialization.XmlElementAttribute("FuelType", typeof(FuelType))]
[System.Xml.Serialization.XmlElementAttribute("HasSecurity", typeof(HasSecurity))]
[System.Xml.Serialization.XmlElementAttribute("ImmobSecurityFitted", typeof(ImmobSecurityFitted))]
[System.Xml.Serialization.XmlElementAttribute("ImmobSecurityMake", typeof(ImmobSecurityMake))]
[System.Xml.Serialization.XmlElementAttribute("Keeper", typeof(Keeper))]
[System.Xml.Serialization.XmlElementAttribute("Lhd", typeof(Lhd))]
[System.Xml.Serialization.XmlElementAttribute("Modification", typeof(Modification))]
[System.Xml.Serialization.XmlElementAttribute("Modified", typeof(Modified))]
[System.Xml.Serialization.XmlElementAttribute("NCBCountry", typeof(NCBCountry))]
[System.Xml.Serialization.XmlElementAttribute("NCBProtected", typeof(NCBProtected))]
[System.Xml.Serialization.XmlElementAttribute("NCBType", typeof(NCBType))]
[System.Xml.Serialization.XmlElementAttribute("NCBYears", typeof(string))]
[System.Xml.Serialization.XmlElementAttribute("NightLocation", typeof(NightLocation))]
[System.Xml.Serialization.XmlElementAttribute("OvernightPostCode", typeof(string))]
[System.Xml.Serialization.XmlElementAttribute("Owner", typeof(Owner))]
[System.Xml.Serialization.XmlElementAttribute("PermittedDrivers", typeof(PermittedDrivers))]
[System.Xml.Serialization.XmlElementAttribute("PricePaid", typeof(string))]
[System.Xml.Serialization.XmlElementAttribute("PurchaseDate", typeof(string))]
[System.Xml.Serialization.XmlElementAttribute("Registration", typeof(string))]
[System.Xml.Serialization.XmlElementAttribute("Seats", typeof(string))]
[System.Xml.Serialization.XmlElementAttribute("TrackerSecurityFitted", typeof(TrackerSecurityFitted))]
[System.Xml.Serialization.XmlElementAttribute("TrackerSecurityMake", typeof(TrackerSecurityMake))]
[System.Xml.Serialization.XmlElementAttribute("Transmission", typeof(Transmission))]
[System.Xml.Serialization.XmlElementAttribute("Type", typeof(string))]
[System.Xml.Serialization.XmlElementAttribute("Windscreen", typeof(Windscreen))]
[System.Xml.Serialization.XmlElementAttribute("YearManufacture", typeof(string))]
[System.Xml.Serialization.XmlChoiceIdentifierAttribute("ItemsElementName")]
public object[] Items
{
get
{
return this._items;
}
set
{
this._items = value;
}
}
Ideally I would like the Vehicle class to have a number of properties which are instances of other classes so that I can use automapper to map from my domain model to the request object, serialize to XML and send the request.
But the way these types have been created, I have lost any information about the structure of the request object I need to build. Everything will need to be mapped explicitly property by property. And yet despite fiddling with all the settings in xsd2code and switches of xsd.exe I can't seem to get it to generate anything like what I want.
Is there a way to do what I want, or do I need to change my approach?
I've done similar work and used xsd.exe, but in this case I believe the problem is the way the schema is laid out. The Vehicle node is an unbounded list of elements that could be any one of 40 different types of objects (ABSBrakes, AgedOver ... YearManufacture). The creator of the schema hasn't left you any options other than to map them property by property.
I realize it's not what you want to hear, but when you come across windscreen data, create a Windscreen object and add it to Vehicle.Items and continue for each property. When you serialize this, it should create valid XML matching the given schema.
Below is the valid and updated XML I was trying to consume:
<DataSet xmlns="http://tempuri.org/">
<xs:schema xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" id="NewDataSet">
<xs:element name="response">
<xs:complexType>
<xs:sequence>
<xs:element name="user" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute name="id" type="xs:string"/>
</xs:complexType>
</xs:element>
<xs:element name="status" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute name="code" type="xs:string"/>
<xs:attribute name="value" type="xs:string"/>
<xs:attribute name="description" type="xs:string"/>
</xs:complexType>
</xs:element>
<xs:element name="error" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute name="code" type="xs:string"/>
<xs:attribute name="message" type="xs:string"/>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="operation" type="xs:string"/>
<xs:attribute name="timestamp" type="xs:string"/>
</xs:complexType>
</xs:element>
<xs:element name="NewDataSet" msdata:IsDataSet="true" msdata:UseCurrentLocale="true">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element ref="response"/>
</xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>
<diffgr:diffgram xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1">
<NewDataSet xmlns="">
<response diffgr:id="response1" msdata:rowOrder="0" diffgr:hasChanges="inserted" operation="AUTHENTICATION" timestamp="2015-11-19 18:21:17.457" msdata:hiddenresponse_Id="0">
<user diffgr:id="user1" msdata:rowOrder="0" diffgr:hasChanges="inserted" id="blumaesnetwork" msdata:hiddenresponse_Id="0"/>
<status diffgr:id="status1" msdata:rowOrder="0" diffgr:hasChanges="inserted" code="315" value="FAILED" description="Authentication Failed. User ID Not Found" msdata:hiddenresponse_Id="0"/>
<error diffgr:id="error1" msdata:rowOrder="0" diffgr:hasChanges="inserted" code="-1" message="User Not Found" msdata:hiddenresponse_Id="0"/>
</response>
</NewDataSet>
</diffgr:diffgram>
</DataSet>
With the C# code below:
x.LoadXml(_xmlString);
XDocument x1 = new XDocument();
x1 = XDocument.Parse(_xmlString);
IEnumerable<responseStatus> ListRsts = (from e in x1.Descendants("responseStatus")
select new responseStatus
{
code = e.Element("code").Value,
value = e.Element("value").Value,
description = e.Element("description").Value
});
foreach (var br in ListRsts)
codeField = (br.code);
It keeps throwing error that i missed "diffgr".
What you get as a respsone XML is a saved DataSet. Instead of trying to decipher the diffgram it generates you better leverage the ReadXml method of that type. It is fully equipped to read the xml and gives you specified behavior on the Tables and Relationships.
var ds = new DataSet();
ds.ReadXml(File.Open(#"C:\temp\ds.xml", FileMode.Open));
var listOfStatus = from row in ds.Tables["response"].Rows.Cast<DataRow>()
from status in row.GetChildRows("response_status")
select new { code = status["code"],
value = status["value"],
description = status["description"] };
foreach(var stat in listOfStatus)
{
// do what ever you need to do with the Status record(s)
}
In the above code I read the rows in the table response and then fetch the childrows for the table status. For every status row an anonymous type is created with the three fields you seem to be interested in. You can process those by iterating over the IEnumerable of that anonymous type.
I have a datatable and I wanna export it to XML file. In my XML file, I want it have schema, as this format :
-<NewDataSet>
-<xs:schema xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="" id="NewDataSet">
-<xs:element msdata:UseCurrentLocale="true" msdata:IsDataSet="true" name="NewDataSet">
-<xs:complexType>
-<xs:choice maxOccurs="unbounded" minOccurs="0">
-<xs:element name="Table1">
-<xs:complexType>
-<xs:sequence>
<xs:element name="MA_NVGCS" minOccurs="0" type="xs:string"/>
<xs:element name="MA_KHANG" minOccurs="0" type="xs:string"/>
<xs:element name="MA_DDO" minOccurs="0" type="xs:string"/>
<xs:element name="MA_DVIQLY" minOccurs="0" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>
-<Table1>
<MA_NVGCS/>
<MA_KHANG>PC06LL0192456</MA_KHANG>
<MA_DDO>PC06LL0192456001</MA_DDO>
<MA_DVIQLY>PC06LL</MA_DVIQLY>
</Table1>
I'm using code :
ds.Tables[0].WriteXml(#"C:\Temp\text.xml");
But it just export to format :
-<NewDataSet>
-<Table>
<STATUS>Online</STATUS>
<MESH>false</MESH>
<NGAYGIO>2015-10-05T14:00:27+07:00</NGAYGIO>
<MA_DVIQLY>DSP</MA_DVIQLY>
</Table>
How can I export my XML with xs:schema
Thanks and sorry for my English.
I add XmlWriteMode.WriteSchema to my code ( ds.Tables[0].WriteXml(#"C:\Temp\text.xml", XmlWriteMode.WriteSchema); ) and the problem is solved. Thank to read my stupid question :D
I have an xml document that contains some html.
<begin-line>
<verse-num>6</verse-num>a mixed people<footnote id="f2">
Or <i>a foreign people</i>; Hebrew <i>a bastard</i>
</footnote> shall dwell in Ashdod,
</begin-line>
The verse-num element is the only element I wan't validated, the rest I want valideted to one large group of a string type, which can hold html, and also sometimes some more xml (like footnote).
Here is the schema I have right now which doesn't do the trick.
<xs:element maxOccurs="unbounded" name="begin-line">
<xs:complexType mixed="true">
<xs:sequence minOccurs="0">
<xs:choice maxOccurs="unbounded">
<xs:element name="verse-num">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:unsignedByte">
<xs:attribute name="begin-chapter" type="xs:unsignedByte" use="optional" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:sequence>
<xs:attribute name="class" type="xs:string" use="optional" />
</xs:complexType>
</xs:element>
I am using XSD.exe to generate a class that I can deserialize this junk into.
It is generating a begin-line object with a verse-num type below it, and also an array of text, which are split by the html/xml tags inside of .
What I need is an xsd that can be used by XSD.exe to generate a begin-line class that will give me a verse-num type, and then one string property that will contain the rest of the content (including text, i's, b's, footnotes, xml/html).
I did some research and it seems like processContents will do the trick, but I can't figure out where to put it.
When it comes down to it, I want to program against the object created by the XSD.exe like this.
var beginLine = new crosswaybiblePassageVerseunitBeginline();
Console.WriteLine((beginLine.Items[0] as crosswaybiblePassageVerseunitBeginlineVersenum).Value);
Console.Write(beginLine.Text);
or maybe even...
var beginLine = new crosswaybiblePassageVerseunitBeginline();
Console.WriteLine(beginLine.Versenum.Value);
Console.Write(beginLine.Text);
I'm not sure how to setup the schema such that it'll provide nice output from XSD.exe but you can specify "any number of elements with any name" in the output using a type with the definition:
<xs:complexType name="AnyChildren">
<xs:sequence>
<xs:any processContents="lax" minOccurs="0" maxOccurs="unbounded" namespace="##any"/>
</xs:sequence>
<xs:anyAttribute />
</xs:complexType>
For example to validate:
<Module>
<Title>Hello World</Title>
<ProviderType>xyz</ProviderType>
<Content />
<MoreContent />
</Module>
You could use:
<xs:complexType name="Module">
<xs:sequence>
<xs:element name="Title" type="xs:string" maxOccurs="1" />
<xs:element name="ProviderType" type="xs:string" minOccurs="1" nillable="false" />
<xs:any processContents="skip" minOccurs="0" maxOccurs="unbounded" namespace="##any"/>
</xs:sequence>
<xs:anyAttribute />
</xs:complexType>