Derived types and substitution groups in XML
Derived types and substitution groups in XML
I was asked recently a question about XML schema. The questioner was trying to create an element in an XML schema that has several attributes. Part of the problem was that they had an attribute which, if missing, should be replaced by a different attribute. Was there something like <xsd:choice/> that could be used for attributes?
So I dutifully bashed away in XML Spy and came up with a piece of test XML....
<?xml version="1.0" encoding="UTF-8"?> <fruits xmlns="xxx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <fruit colour="yellow" xsi:type="bananatype" curvature="3"/> <fruit colour="green" xsi:type="appletype" pips="4" /> </fruits>
.... that I could validate against the following schema.
<?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xxx="xxx" targetNamespace="xxx" elementFormDefault="qualified" attributeFormDefault="unqualified"> <xs:element name="fruits"> <xs:complexType> <xs:sequence> <xs:element ref="xxx:fruit" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="fruit" type="xxx:fruittype"/> <xs:complexType name="fruittype"> <xs:attribute name="colour" type="xs:string"/> </xs:complexType> <xs:complexType name="bananatype"> <xs:complexContent> <xs:extension base="xxx:fruittype"> <xs:attribute name="curvature" type="xs:integer"/> </xs:extension> </xs:complexContent> </xs:complexType> <xs:complexType name="appletype"> <xs:complexContent> <xs:extension base="xxx:fruittype"> <xs:attribute name="pips" type="xs:integer"/> </xs:extension> </xs:complexContent> </xs:complexType> <xs:element name="banana" type="xxx:bananatype" substitutionGroup="xxx:fruit"/> <xs:element name="apple" type="xxx:appletype" substitutionGroup="xxx:fruit"/> </xs:schema>
Well, actually, the first snippet of XML would validate perfectly fine if the definitions of banana and apple weren't there. "bananatype" and "appletype" are derived from "fruittype" so as long as you specify the sub-type using the xsi:type attribute, then it's valid.
What the substitutionGroup attributes on the definitions of the <banana/> and <apple/> elements, give you is the ability to put them anywhere you could have put a <fruit/>, and without the need for all that messy xsi:type stuff.
<?xml version="1.0" encoding="UTF-8"?> <fruits xmlns="xxx"> <banana colour="yellow" curvature="3"/> <apple colour="green" pips="4" /> </fruits>When you'd use one technique or another is a matter for your specific design.

