Consider the following schema, Root must contain the child nodes A,B,C and 0-n D's.
The child elements must appear in the order show.
ComplexTypeSample.xsd |
Copy Code
|
---|---|
<?xml version="1.0" encoding="utf-8" ?> <!--Created with Liquid Studio (https://www.liquid-technologies.com)--> <xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:element name="Order"> <xs:complexType> <xs:sequence> <xs:element name="CustomerID" type="xs:int" /> <xs:element name="BillingAddress" type="AddressType" /> <xs:element name="ShippingAddress" type="AddressType" /> </xs:sequence> </xs:complexType> </xs:element> <xs:complexType abstract="true" name="AddressType"> <xs:sequence> <xs:element name="Line1" type="xs:string" /> <xs:element name="Line2" type="xs:string" minOccurs="0" /> <xs:element name="Town" type="xs:string" /> </xs:sequence> <xs:attribute name="Name" type="xs:string" /> </xs:complexType> <xs:complexType name="UKAddressType"> <xs:complexContent> <xs:extension base="AddressType"> <xs:sequence> <xs:element name="County" type="xs:string" /> <xs:element name="Postcode" type="xs:string" /> </xs:sequence> </xs:extension> </xs:complexContent> </xs:complexType> <xs:complexType name="USAddressType"> <xs:complexContent> <xs:extension base="AddressType"> <xs:sequence> <xs:element name="State" type="xs:string" /> <xs:element name="Zipcode" type="xs:string" /> </xs:sequence> </xs:extension> </xs:complexContent> </xs:complexType> </xs:schema> |
The xs:element Order has 2 child xs:elements BillingAddress and ShippingAddress, which are both references to AddressType. This means that BillingAddress and ShippingAddress can contain content defined in any xs:complexType based on AddressType (i.e. AddressType, UsAddressType or UKAddressType). However because AddressType is marked as abstract, it can't be instantiated, so the content must be defined by UsAddressType or UKAddressType.
The following code is generated for the schema ComplexTypeSample.xsd.
Generated Code |
Copy Code
|
---|---|
public abstract partial class AddressTypeCt { public System.String Name { get; set; } public AddressTypeSeq Seq { get; set; } = new AddressTypeSeq(); public partial class AddressTypeSeq { public System.String Line1 { get; set; } = ""; public System.String Line2 { get; set; } public System.String Town { get; set; } = ""; } } public partial class UKAddressTypeCt : AddressTypeCt { public UKAddressTypeSeq Seq1 { get; set; } = new UKAddressTypeSeq(); public partial class UKAddressTypeSeq { public System.String County { get; set; } = ""; public System.String Postcode { get; set; } = ""; } } public partial class USAddressTypeCt : AddressTypeCt { public USAddressTypeSeq Seq1 { get; set; } = new USAddressTypeSeq(); public partial class USAddressTypeSeq { public System.String State { get; set; } = ""; public System.String Zipcode { get; set; } = ""; } } public partial class OrderElm { public OrderSeq Seq { get; set; } = new OrderSeq(); public partial class OrderSeq { public System.Int32 CustomerID { get; set; } public AddressTypeCt BillingAddress { get; set; } public AddressTypeCt ShippingAddress { get; set; } } } |
A class is created for each root xs:complexType within the XSD. The mapping between the XSD and generated code is quite straightforward when you look at the graphical view of the XSD.
Notice that the UKAddressTypeCt ends up with its own xs:sequence which is named Seq1.
Generating Seq and Seq1 may seem unnecessary, but the compositor in UKAddressType could be different (i.e. a xs:choice) or have different cardinality to that of the xs:seqeunce in the base AddressType type. Furthermore structured as it is changes to the schema have fewer ripples in the generated code, meaning less re-work if the schema changes.
We can use the following code to build an instance of the Order Element
Sample Code |
Copy Code
|
---|---|
LxSerializer<OrderElm> serializer = new LxSerializer<OrderElm>(); OrderElm order = new OrderElm(); order.Seq.CustomerID = 3127; UKAddressTypeCt ukAddress = new Ns.UKAddressTypeCt(); ukAddress.Name = "Acme Corp Admin"; ukAddress.Seq.Line1 = "Office 3a"; ukAddress.Seq.Line2 = "5 The Headrow"; ukAddress.Seq.Town = "Leeds"; ukAddress.Seq1.County = "West Yorkshire"; ukAddress.Seq1.Postcode = "LS5 8HP"; order.Seq.BillingAddress = ukAddress; USAddressTypeCt usAddress = new Ns.USAddressTypeCt(); usAddress.Name = "Acme Corp R&D"; usAddress.Seq.Line1 = "1630 Revello"; usAddress.Seq.Town = "Sunnydale"; usAddress.Seq1.State = "CA"; usAddress.Seq1.Zipcode = "56482"; order.Seq.ShippingAddress = usAddress; serializer.Serialize(@"..\..\Order_Output.xml", order); |
ComplexType_Output.xml |
Copy Code
|
---|---|
<?xml version="1.0" encoding="utf-8"?> <Order> <CustomerID>3127</CustomerID> <BillingAddress p2:type="UKAddressType" Name="Acme Corp Admin" xmlns:p2="http://www.w3.org/2001/XMLSchema-instance"> <Line1>Office 3a</Line1> <Line2>5 The Headrow</Line2> <Town>Leeds</Town> <County>West Yorkshire</County> <Postcode>LS5 8HP</Postcode> </BillingAddress> <ShippingAddress p2:type="USAddressType" Name="Acme Corp R&D" xmlns:p2="http://www.w3.org/2001/XMLSchema-instance"> <Line1>1630 Revello</Line1> <Town>Sunnydale</Town> <State>CA</State> <Zipcode>56482</Zipcode> </ShippingAddress> </Order> |
The following code will read back in the files created above.
Sample Code |
Copy Code
|
---|---|
LxSerializer<OrderElm> serializer = new LxSerializer<OrderElm>(); OrderElm order = serializer.Deserialize(@"..\..\Order_Output.xml"); Console.WriteLine($"Order"); Console.WriteLine($" Customer ID : {order.Seq.CustomerID}"); Console.WriteLine($" Billing Address"); WriteAddress(order.Seq.BillingAddress); Console.WriteLine($" Shipping Address"); WriteAddress(order.Seq.ShippingAddress); |
When the valid XML file ComplexType_Output.xml is read and produces an object model identical to the one serialized out in the code above.
Console Output |
Copy Code
|
---|---|
Order Customer ID : 3127 Billing Address Name : Acme Corp Admin Line 1 : Office 3a Line 2 : 5 The Headrow Town : Leeds County : West Yorkshire Postcode : LS5 8HP Shipping Address Name : Acme Corp R&D Line 1 : 1630 Revello Town : Sunnydale State : CA Zipcode : 56482 |