XSD Example


This section will demonstrate how to write an XML Schema. You will also learn different methods of writing a schema.


XML Document

Let's look at this XML document named "shiporder.xml":

<?xml version="1.0" encoding="ISO-8859-1"?>

<shiporder orderid="889923"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="shiporder.xsd">
  <orderperson>John Smith</orderperson>
  <shipto>
    <name>Ola Nordmann</name>
    <address>Langgt 23</address>
    <city>4000 Stavanger</city>
    <country>Norway</country>
  </shipto>
  <item>
    <title>Empire Burlesque</title>
    <note>Special Edition</note>
    <quantity>1</quantity>
    <price>10.90</price>
  </item>
  <item>
    <title>Hide your heart</title>
    <quantity>1</quantity>
    <price>9.90</price>
  </item>
</shiporder>

The XML document above includes the root element "shiporder", which contains a required attribute named "orderid". The "shiporder" element contains three different child elements: "orderperson", "shipto", and "item". The "item" element appears twice, and it contains a "title", an optional "note" element, a "quantity", and a "price" element.

The line above, xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance", tells the XML parser to validate this document against a schema. This line: xsi:noNamespaceSchemaLocation="shiporder.xsd" specifies the location of the schema (here, it is in the same folder as "shiporder.xml").


Create an XML Schema

Now, we need to create a schema for the XML document above.

We can start by opening a new file and naming it "shiporder.xsd". To create the schema, we simply need to follow the structure in the XML document and define each element we find. First, we begin by defining a standard XML declaration:

<?xml version="1.0" encoding="ISO-8859-1" ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
...
</xs:schema>

In the above schema, we used the standard namespace (xs). The URI associated with this namespace is the Schema language definition, and its standard value is http://www.w3.org/2001/XMLSchema.

Next, we need to define the "shiporder" element. This element has an attribute and contains other elements, so we identify it as a complex type. The child elements of the "shiporder" element are surrounded by the xs:sequence element, which defines the order of the child elements:

<xs:element name="shiporder">
  <xs:complexType>
    <xs:sequence>
      ...
    </xs:sequence>
  </xs:complexType>
</xs:element>

Then we need to define the "orderperson" element as a simple type (because it does not contain any attributes or other elements). The prefix of the type (xs:string) is specified by the namespace prefix, which is associated with the XML schema that indicates predefined schema data types:

<xs:element name="orderperson" type="xs:string"/>

Next, I need to define two elements as complex types: "shipto" and "item". We start by defining the "shipto" element:

<xs:element name="shipto">
  <xs:complexType>
    <xs:sequence>
      <xs:element name="name" type="xs:string"/>
      <xs:element name="address" type="xs:string"/>
      <xs:element name="city" type="xs:string"/>
      <xs:element name="country" type="xs:string"/>
    </xs:sequence>
  </xs:complexType>
</xs:element>

Through a schema, we can use the maxOccurs and minOccurs attributes to define how many times a particular element may appear. maxOccurs defines the maximum number of times an element may appear, while minOccurs defines the minimum number of times an element may appear. The default value for both maxOccurs and minOccurs is 1!

Now, we can define the "item" element. This element can appear multiple times inside the "shiporder" element. This is accomplished by setting the value of the maxOccurs attribute of the "item" element to "unbounded", so that the "item" element can appear as many times as the author wishes. Note that the "note" element is an optional element. We have set its minOccurs attribute to 0:

<xs:element name="item" maxOccurs="unbounded">
  <xs:complexType>
    <xs:sequence>
      <xs:element name="title" type="xs:string"/>
      <xs:element name="note" type="xs:string" minOccurs="0"/>
      <xs:element name="quantity" type="xs:positiveInteger"/>
      <xs:element name="price" type="xs:decimal"/>
    </xs:sequence>
  </xs:complexType>
</xs:element>

Now, we can declare the attribute of the "shiporder" element. Since this is a required attribute, we specify use="required".

Note:The declaration of this attribute must be placed at the end:

<xs:attribute name="orderid" type="xs:string" use="required"/>

This is the document listing of the schema file named "shiporder.xsd":

<?xml version="1.0" encoding="ISO-8859-1" ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

<xs:element name="shiporder">
  <xs:complexType>
    <xs:sequence>
      <xs:element name="orderperson" type="xs:string"/>
      <xs:element name="shipto">
        <xs:complexType>
          <xs:sequence>
            <xs:element name="name" type="xs:string"/>
            <xs:element name="address" type="xs:string"/>
            <xs:element name="city" type="xs:string"/>
            <xs:element name="country" type="xs:string"/>
          </xs:sequence>
        </xs:complexType>
      </xs:element>
      <xs:element name="item" maxOccurs="unbounded">
        <xs:complexType>
          <xs:sequence>
            <xs:element name="title" type="xs:string"/>
            <xs:element name="note" type="xs:string" minOccurs="0"/>
            <xs:element name="quantity" type="xs:positiveInteger"/>
            <xs:element name="price" type="xs:decimal"/>
          </xs:sequence>
        </xs:complexType>
      </xs:element>
    </xs:sequence>
    <xs:attribute name="orderid" type="xs:string" use="required"/>
  </xs:complexType>
</xs:element>

</xs:schema>


Divide the Schema

The previous design method is very easy, but when the document is complex, it is difficult to read and maintain.

The design method introduced next is based on first defining all elements and attributes, and then using the ref attribute to reference them.

Here is the schema file ("shiporder.xsd") designed using the new method:

<?xml version="1.0" encoding="ISO-8859-1" ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

<!-- definition of simple elements -->
<xs:element name="orderperson" type="xs:string"/>
<xs:element name="name" type="xs:string"/>
<xs:element name="address" type="xs:string"/>
<xs:element name="city" type="xs:string"/>
<xs:element name="country" type="xs:string"/>
<xs:element name="title" type="xs:string"/>
<xs:element name="note" type="xs:string"/>
<xs:element name="quantity" type="xs:positiveInteger"/>
<xs:element name="price" type="xs:decimal"/>

<!-- definition of attributes -->
<xs:attribute name="orderid" type="xs:string"/>

<!-- definition of complex elements -->
<xs:element name="shipto">
  <xs:complexType>
    <xs:sequence>
      <xs:element ref="name"/>
      <xs:element ref="address"/>
      <xs:element ref="city"/>
      <xs:element ref="country"/>
    </xs:sequence>
  </xs:complexType>
</xs:element>

<xs:element name="item">
  <xs:complexType>
    <xs:sequence>
      <xs:element ref="title"/>
      <xs:element ref="note" minOccurs="0"/>
      <xs:element ref="quantity"/>
      <xs:element ref="price"/>
    </xs:sequence>
  </xs:complexType>
</xs:element>

<xs:element name="shiporder">
  <xs:complexType>
    <xs:sequence>
      <xs:element ref="orderperson"/>
      <xs:element ref="shipto"/>
      <xs:element ref="item" maxOccurs="unbounded"/>
    </xs:sequence>
    <xs:attribute ref="orderid" use="required"/>
  </xs:complexType>
</xs:element>

</xs:schema>


Using Named Types

The third design method defines classes or types, giving us the ability to reuse element definitions. The specific approach is: first name the simple elements and complex elements, and then point to them through the element's type attribute.

Here is the schema file ("shiporder.xsd") designed using the third method:

<?xml version="1.0" encoding="ISO-8859-1" ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

<xs:simpleType name="stringtype">
  <xs:restriction base="xs:string"/>
</xs:simpleType>

<xs:simpleType name="inttype">
  <xs:restriction base="xs:positiveInteger"/>
</xs:simpleType>

<xs:simpleType name="dectype">
  <xs:restriction base="xs:decimal"/>
</xs:simpleType>

<xs:simpleType name="orderidtype">
  <xs:restriction base="xs:string">
    <xs:pattern value="[0-9]{6}"/>
  </xs:restriction>
</xs:simpleType>

<xs:complexType name="shiptotype">
  <xs:sequence>
    <xs:element name="name" type="stringtype"/>
    <xs:element name="address" type="stringtype"/>
    <xs:element name="city" type="stringtype"/>
    <xs:element name="country" type="stringtype"/>
  </xs:sequence>
</xs:complexType>

<xs:complexType name="itemtype">
  <xs:sequence>
    <xs:element name="title" type="stringtype"/>
    <xs:element name="note" type="stringtype" minOccurs="0"/>
    <xs:element name="quantity" type="inttype"/>
    <xs:element name="price" type="dectype"/>
  </xs:sequence>
</xs:complexType>

<xs:complexType name="shipordertype">
  <xs:sequence>
    <xs:element name="orderperson" type="stringtype"/>
    <xs:element name="shipto" type="shiptotype"/>
    <xs:element name="item" maxOccurs="unbounded" type="itemtype"/>
  </xs:sequence>
  <xs:attribute name="orderid" type="orderidtype" use="required"/>
</xs:complexType>

<xs:element name="shiporder" type="shipordertype"/>

</xs:schema>

The restriction element indicates that the data type is derived from a data type in the W3C XML Schema namespace. Therefore, the following fragment means that the value of the element or attribute must be a string type value:

<xs:restriction base="xs:string">

The restriction element is often used to impose restrictions on elements. Look at the following fragments from the above schema:

<xs:simpleType name="orderidtype">
  <xs:restriction base="xs:string">
    <xs:pattern value="[0-9]{6}"/>
  </xs:restriction>
</xs:simpleType>

This code indicates that the value of the element or attribute must be a string, and must be six consecutive characters, and these characters must be digits from 0-9.

Other Extensions