We recently received a question in our XML Community Forum regarding using an xs:choice compositor with many items in an XML Schema and the generated C# source code from Liquid XML Objects.
The issue described a scenario of a Repair Shop where you would want many possible choices, each choice representing a possible Repair.
For example, we could construct a simple XSD as follows:
<?xml version="1.0" encoding="utf-8" ?> <!--Created with Liquid Studio 2020 (https://www.liquid-technologies.com)--> <xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:complexType name="RepairType"> <xs:choice> <xs:element name="RepairWheel" type="xs:string" /> <xs:element name="RepairWindscreen" type="xs:string" />
... many more items ...
</xs:choice> </xs:complexType> <xs:element name="RepairShop"> <xs:complexType> <xs:sequence minOccurs="0" maxOccurs="unbounded"> <xs:element name="Repair" type="RepairType" /> </xs:sequence> </xs:complexType> </xs:element> </xs:schema>
Note: for simplicity we are using xs:string, but in reality this would represent a ComplexType containing all of the information pertaining to the type of 'Repair'.
The C# source code generated by Liquid XML Objects code generator from this XSD would include a class representing the 'RepairType' ComplexType and would contain a property for each possible repair:
public class RepairTypeCt { public String RepairWheel { get; set; } public String RepairWindscreen { get; set; } ... many more items ...
}
Whilst this is perfectly correct C# source code, it is not ideal when checking which item of the choice has been set in code as we would need to check each item until we find the item which is not null.
Derivation by Extenion using xsi:type
One possible solution is to use xsi:type. In the following updated XSD we specify an abstract base type 'RepairType' and derive other types 'RepairWheel' and 'RepairWindscreen' from this using derivation by extension:
<?xml version="1.0" encoding="utf-8" ?> <!--Created with Liquid Studio 2020 (https://www.liquid-technologies.com)--> <xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:complexType abstract="true" name="RepairType" /> <xs:complexType name="RepairWheel"> <xs:complexContent> <xs:extension base="RepairType"> <xs:sequence> <xs:element name="WheelSize" type="xs:string" /> </xs:sequence> </xs:extension> </xs:complexContent> </xs:complexType> <xs:complexType name="RepairWindscreen"> <xs:complexContent> <xs:extension base="RepairType"> <xs:sequence> <xs:element name="WindscreenSize" type="xs:string" /> </xs:sequence> </xs:extension> </xs:complexContent> </xs:complexType> <xs:element name="RepairShop"> <xs:complexType> <xs:sequence minOccurs="0" maxOccurs="unbounded"> <xs:element name="Repair" type="RepairType" /> </xs:sequence> </xs:complexType> </xs:element> </xs:schema>
Now the generated C# source code contains 3 classes, a base class and 2 specialized derived classes:
public abstract class RepairTypeCt { } public class RepairWheelCt : RepairTypeCt { public String WheelSize { get; set; } = ""; } public class RepairWindscreenCt : RepairTypeCt { public String WindscreenSize { get; set; } = ""; }
We can now simply test the type of the repair and cast the value to the correct type in order to utilise the derived specialization as we would expect to in a polymorphic object model.
However, the XML document would need to change to refect the changes to the XSD in order for the XML processor to know which type of 'Repair' the element represents.
The original XML document would be as follows:
<?xml version="1.0" encoding="utf-8"?> <!-- Created with Liquid Studio 2020 (https://www.liquid-technologies.com)--> <RepairShop> <Repair> <RepairWheel>string</RepairWheel> </Repair> <Repair> <RepairWindscreen>string</RepairWindscreen> </Repair> </RepairShop>
Using the new XSD, we would need to change the XML document to use xsi:type attribute to specify the type of 'Repair':
<?xml version="1.0" encoding="utf-8"?> <!-- Created with Liquid Studio 2020 (https://www.liquid-technologies.com)--> <RepairShop xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <Repair xsi:type="RepairWheel"> <WheelSize>string</WheelSize> </Repair> <Repair xsi:type="RepairWindscreen"> <WindscreenSize>string</WindscreenSize> </Repair> </RepairShop>
In summary, xsi:type provides a mechanism to support polymorphism within our generated C# code making the code cleaner and the XML easier to read and utilise.
Further information can be found in our XML Tutorial.
XML Tools
Please download a Free Trial of Liquid Studio graphical XML editor and Liquid XML Objects code generator from our web site:
https://www.liquid-technologies.com/trial-download