Understanding XML Schema - Test Drive
(Page 11 of 12 )
Now that you've got the basics down, let's look at a couple of composite examples just to put everything in perspective. Consider the following two document instances, and then see if you can write appropriate schema definitions for each:
<?xml version="1.0"?>
<!-- id is a required attribute -->
<recipe id="3450">
<name>Chicken
Tikka</name>
<author>Mr. Cluck</author>
<date>1999-06-08</date>
<ingredients>
<!--
quantity is a required attribute, units is optional -->
<item quantity="2">Boneless
chicken breasts</item>
<item quantity="2">Chopped onions</item>
<item
quantity="1" units="tsp">Ginger</item>
<item quantity="1" units="tsp">Garlic</item>
<item
quantity="1" units="tsp">Red chili powder</item>
<item quantity="1" units="tsp">Coriander
seeds</item>
<item quantity="2" units="tbsp">Lime juice</item>
<item
quantity="2" units="tbsp">Butter</item>
</ingredients>
<process>
<step>Cut
chicken into cubes, wash and apply lime juice and salt</step>
<step>Add
ginger, garlic, chili, coriander and lime juice in a separate
bowl</step>
<step>Mix
well, and add chicken to marinate for 3-4 hours</step>
<step>Place chicken
pieces on skewers and barbeque</step>
<step>Remove, apply butter, and
barbeque again until meat is tender</step>
<step>Garnish with lemon and
chopped onions</step>
</process>
</recipe>
Here's the second one:
<?xml version="1.0"?>
<weather>
<!-- id is a required attribute -->
<city
id="52320">
<name>Boston</name>
<temperature>
<!-- units is
a required attribute, restricted to values "celsius" and
"fahrenheit" -->
<high
units="celsius">23</high>
<low units="celsius">5</low>
</temperature>
<!--
forecast may be any one of "rain", "sun", "snow" or "fog" -->
<forecast>snow</forecast>
</city>
<city
id="9010">
<name>New York</name>
<temperature>
<high units="celsius">11</high>
<low
units="celsius">-5</low>
</temperature>
<forecast>snow</forecast>
</city>
<city
id="8239">
<name>London</name>
<temperature>
<high units="celsius">27</high>
<low
units="celsius">12</low>
</temperature>
<forecast>sun</forecast>
</city>
</weather>
Here's a schema definition for the first one:
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:annotation>
<xsd:documentation>This
version uses references and anonymous
elements</xsd:documentation>
</xsd:annotation>
<xsd:element
name="step" type="xsd:string" />
<xsd:element name="name" type="xsd:string"
/>
<xsd:element name="author" type="xsd:string" />
<xsd:element name="date"
type="xsd:date" />
<xsd:attribute name="id" type="xsd:integer" />
<xsd:attribute
name="units" type="xsd:string" />
<xsd:attribute name="quantity" type="xsd:integer"
/>
<xsd:element name="process">
<xsd:complexType>
<xsd:sequence>
<xsd:element
ref="step" maxOccurs="unbounded" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element
name="item">
<xsd:complexType>
<xsd:simpleContent>
<xsd:restriction
base="xsd:string">
<xsd:attribute ref="quantity" use="required" />
<xsd:attribute
ref="units" use="optional" />
</xsd:restriction>
</xsd:simpleContent>
</xsd:complexType>
</xsd:element>
<xsd:element
name="ingredients">
<xsd:complexType>
<xsd:sequence>
<xsd:element
ref="item" maxOccurs="unbounded" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element
name="recipe">
<xsd:complexType>
<xsd:sequence>
<xsd:element
ref="name" />
<xsd:element ref="author" />
<xsd:element ref="date"
/>
<xsd:element ref="ingredients" />
<xsd:element ref="process"
/>
</xsd:sequence>
<xsd:attribute ref="id" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:schema>
This version first defines various elements and then references those definitions
to construct a schema. In case this doesn't work for you, you can derive and use named datatypes instead of references - here's an alternative version of the schema above:
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:annotation>
<xsd:documentation>This
version uses named datatypes</xsd:documentation>
</xsd:annotation>
<xsd:complexType
name="itemDType">
<xsd:simpleContent>
<xsd:restriction base="xsd:string">
<xsd:attribute
name="quantity" type="xsd:integer" use="required" />
<xsd:attribute name="units"
type="xsd:string" use="optional" />
</xsd:restriction>
</xsd:simpleContent>
</xsd:complexType>
<xsd:complexType
name="ingredientsDType">
<xsd:sequence>
<xsd:element name="item" type="itemDType"
maxOccurs="unbounded" />
</xsd:sequence>
</xsd:complexType>
<xsd:complexType
name="processDType">
<xsd:sequence>
<xsd:element name="step" type="xsd:string"
maxOccurs="unbounded" />
</xsd:sequence>
</xsd:complexType>
<xsd:complexType
name="recipeDType">
<xsd:sequence>
<xsd:element name="name" type="xsd:string"
/>
<xsd:element name="author" type="xsd:string" />
<xsd:element name="date"
type="xsd:date" />
<xsd:element name="ingredients" type="ingredientsDType"
/>
<xsd:element name="process" type="processDType" />
</xsd:sequence>
<xsd:attribute
name="id" type="xsd:integer" use="required" />
</xsd:complexType>
<!--
all type definitions done, now simply create an element of type
"recipe" -->
<xsd:element
name="recipe" type="recipeDType" />
</xsd:schema>
In a similar manner, you can create a schema for the weather forecast example,
using either references
<?xml version="1.0"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element
name="name" type="xsd:string"/>
<xsd:attribute name="id" type="xsd:integer"/>
<xsd:attribute
name="units">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:enumeration
value="fahrenheit"/>
<xsd:enumeration value="celsius"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:attribute>
<xsd:element
name="high">
<xsd:complexType>
<xsd:simpleContent>
<xsd:restriction
base="xsd:integer">
<xsd:maxInclusive value="150"/>
<xsd:minInclusive
value="-150"/>
<xsd:attribute ref="units" use="required"/>
</xsd:restriction>
</xsd:simpleContent>
</xsd:complexType>
</xsd:element>
<xsd:element
name="low">
<xsd:complexType>
<xsd:simpleContent>
<xsd:restriction
base="xsd:integer">
<xsd:maxInclusive value="150"/>
<xsd:minInclusive
value="-150"/>
<xsd:attribute ref="units" use="required"/>
</xsd:restriction>
</xsd:simpleContent>
</xsd:complexType>
</xsd:element>
<xsd:element
name="forecast">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:enumeration
value="fog"/>
<xsd:enumeration value="rain"/>
<xsd:enumeration value="sun"/>
<xsd:enumeration
value="snow"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
<xsd:element
name="temperature">
<xsd:complexType>
<xsd:sequence>
<xsd:element
ref="high"/>
<xsd:element ref="low"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element
name="city">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="name"/>
<xsd:element
ref="temperature"/>
<xsd:element ref="forecast"/>
</xsd:sequence>
<xsd:attribute
ref="id" use="required"/>
</xsd:complexType>
</xsd:element>
<xsd:element
name="weather">
<xsd:complexType>
<xsd:sequence>
<xsd:element
ref="city" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
or derived types.
<?xml version="1.0"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:simpleType
name="nameDType">
<xsd:restriction base="xsd:string"/>
</xsd:simpleType>
<xsd:simpleType
name="forecastDType">
<xsd:restriction base="xsd:string">
<xsd:enumeration
value="fog"/>
<xsd:enumeration value="rain"/>
<xsd:enumeration value="sun"/>
<xsd:enumeration
value="snow"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType
name="unitsDType">
<xsd:restriction base="xsd:string">
<xsd:enumeration
value="celsius"/>
<xsd:enumeration value="fahrenheit"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType
name="temperatureDType">
<xsd:simpleContent>
<xsd:restriction base="xsd:integer">
<xsd:maxInclusive
value="150"/>
<xsd:minInclusive value="-150"/>
<xsd:attribute name="units"
type="unitsDType" use="required"/>
</xsd:restriction>
</xsd:simpleContent>
</xsd:complexType>
<xsd:complexType
name="temperatureWrapperDType">
<xsd:sequence>
<xsd:element name="high"
type="temperatureDType"/>
<xsd:element name="low" type="temperatureDType"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType
name="cityDType">
<xsd:sequence>
<xsd:element name="name" type="nameDType"/>
<xsd:element
name="temperature" type="temperatureWrapperDType"/>
<xsd:element name="forecast"
type="forecastDType" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute
name="id" type="xsd:integer" use="required"/>
</xsd:complexType>
<xsd:complexType
name="weatherDType">
<xsd:sequence>
<xsd:element name="city" type="cityDType"
maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<!--
now simply declare an element of type "weather" -->
<xsd:element name="weather"
type="weatherDType"/>
</xsd:schema>
Of these two approaches, I've always found the derived types approach to be a
bit more flexible, not to mention more clearly-structured and logical - although it does take a bit of getting used to.
Next: The Next Step >>
More XML Articles
More By Harish Kamath, (c) Melonfire