I have XML like this:
<type>
<mainType>...</mainType>
<subtype>...<subtype>
</type>
The mainTypes are restricted xs:strings (a list of them). And each mainType has a list of possible subtypes. IE:
mainTypeA has possible subtypes of: subtype1, subtype2, subtype3
mainTypeB has possible subtyes of: subtype4, subtype5
How can I represent this in XSD so that each of subtype enumerations are linked specifically to their main type? Is there a better way to represent those 2 fields to make the XSD simpler? I am not opposed to changing the XML document structure.
(This would have been a additional comment in @hugh jadick's answer but was too long for such.)
You have two problems in your initial design which complicates the structure:
<subType>
can appear only when <mainType>
is present<type>
)<mainType>
)<subType>
elements).In XML Schema 1.0 there is no general method to make those features possible although they can be achieved in some cases and/or with some methods. One possible workaround for ambiguous type problem would be to use xsi:type
attribute in the instance document to determinate the used schema type (Example 1).
Instead of using some possible workarounds to solve those problems, I suggest that you follow @hugh jadick's answer and create elements with different names for all the main types which again will have different elements for different subtypes. If you don't like having the type name as the element name (or it is not a valid for an XML element name) you could put it in an attribute, possibly using a default or fixed value (<myType1 typeName="Type 1 name">
)(Example 2). If subtypes are mutually exclusive, you could put also them in an attribute (<myType1 subType="subType2">
). If you really want to have the type name in the element contents (<mainType1>Type 1 name</mainType1>
), then it is probably better to have the <subType>
elements as following siblings instead of children of <mainType1>
because that would result in mixed content which easily causes whitespace and text node position related problems (Example 3).
Yes, substitution groups could also be used with @hugh jadick's answer. You would have an abstract <mainType>
element and all main type element definitions had substitutionGroup="mainType"
attribute. You would still need to have different names for different main type elements because they allow different set of allowed elements/values. The type of these elements must be derived from the type of the abstract <mainType>
element that they substitute (Example 4).
<xs:element name="type">
<xs:complexType>
<xs:choice>
<xs:element name="mainType" type="mainType1"/>
<xs:element name="mainType" type="mainType2"/>
<xs:element name="mainType" type="mainType3"/>
</xs:choice>
</xs:complexType>
</xs:element>
<type>
<mainType xsi:type="mainType1"/>
</type>
<xs:element name="mainType1">
<xs:complexType>
<xs:choice>
<xs:element ref="subType1"/>
<xs:element ref="subType2"/>
<xs:element ref="subType3"/>
</xs:choice>
<xs:attribute name="typeName" type="xs:string"/>
</xs:complexType>
</xs:element>
<xs:element name="type">
<xs:complexType>
<xs:choice>
<xs:sequence>
<xs:element name="mainType" type="mainType1"/>
<xs:choice>
<xs:element ref="subType1"/>
<xs:element ref="subType2"/>
<xs:element ref="subType3"/>
</xs:choice>
</xs:sequence>
<!-- repeat similarily for other main types -->
<xs:sequence>
<!-- ... -->
</xs:sequence>
</xs:choice>
</xs:complexType>
</xs:element>
<xs:element name="type">
<xs:complexType>
<xs:sequence>
<xs:element ref="mainType"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="mainType" type="mainType" abstract="true"/>
<xs:element name="mainType1" type="typeForMainType1" substitutionGroup="mainType"/>
<xs:element name="mainType2" type="typeForMainType2" substitutionGroup="mainType"/>
<xs:complexType name="mainType">
<!-- definition for mainType -->
</xs:complexType>
<xs:complexType name="typeForMainType1">
<xs:complexContent>
<xs:restriction base="mainType">
<!-- definition for mainType1 -->
</xs:restriction>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="typeForMainType2">
<xs:complexContent>
<xs:restriction base="mainType">
<!-- definition for mainType1 -->
</xs:restriction>
</xs:complexContent>
</xs:complexType>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With