Friday, July 11, 2008

Validating co-constrains in XML Schema 1.1 using xs:alternative

Rather than mess around with loads of assertions to check your co-constraints, XML Schema 1.1 introduces the xs:alternative instruction which allows you to change the type used to validate the element based on some condition. Instead of defining one type and then adding assertions to check the variations, just define one type per variation, then assign that type based on the condition.

To do this you first have to define a default type, then define types for each variation by restricting that type. To choose between them, use xs:alternative as a child of xs:element. Here's an example of a co-constraint - this and that are allowed based on the value of the type attribute of node - and how to validate it:
<root>
<node type="A">
<this/>
</node>
<node type="B">
<that/>
</node>
</root>

Here's the schema:
<xs:schema 
xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified">

<xs:element name="root" type="root"/>
<xs:element name="node" type="node">
<xs:alternative type="node-type-A" test="@type = 'A'"/>
<xs:alternative type="node-type-B" test="@type = 'B'"/>
</xs:element>

<xs:element name="this"/>
<xs:element name="that"/>

<xs:complexType name="root">
<xs:sequence>
<xs:element ref="node" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>

<-- Base type -->
<xs:complexType name="node">
<xs:sequence>
<xs:any/>
</xs:sequence>
<xs:attribute name="type" type="allowed-node-types"/>
</xs:complexType>

<xs:simpleType name="allowed-node-types">
<xs:restriction base="xs:string">
<xs:enumeration value="A"/>
<xs:enumeration value="B"/>
</xs:restriction>
</xs:simpleType>

<-- Type A -->
<xs:complexType name="node-type-A">
<xs:complexContent>
<xs:restriction base="node">
<xs:sequence>
<xs:element ref="this"/>
</xs:sequence>
</xs:restriction>
</xs:complexContent>
</xs:complexType>

<-- Type B -->
<xs:complexType name="node-type-B">
<xs:complexContent>
<xs:restriction base="node">
<xs:sequence>
<xs:element ref="that"/>
</xs:sequence>
</xs:restriction>
</xs:complexContent>
</xs:complexType>
</xs:schema>

I really like this... schema 1.1 will be a joy to use.

No comments: