XSD

XML Schema Definition, or W3C XML Schema (WXS), is XML-based. All its elements can have the 'id' attribute as well as other attributes. The name of an XSD file ends with ".xsd".

Instead of coding an XSD file from scratch, an XSD inference tool such as those in XMLSpy or OxygenXML can generate an XSD file from an XML file. Such a tool can also be found in Microsoft's XML Schema Definition Tool (XSD.exe), Apache's XMLBeans, Trang, xmlgrid.net, etc.

XSD 1.1 became a W3C Recommendation in April 2012, and remains the current version of XML Schema. It supersedes XSD 1.0 with features such as assertions and conditional type assignment (both covered below), and consists of two parts: Part 1: Structures and Part 2: Datatypes.

Basic Features

The following illustrates the basic features of XSD.

<?xml version="1.0"?>
<zoo xmlns="http://www.example.com"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://www.example.com zoo.xsd">
   <animal id="l123444">
      <name>Mighty</name>
      <type>lion</type>
      <kg>135</kg>
      <imported/>
   </animal>
   <animal id="b355345">
      <name>Lucky</name>
       <type>bear</type>
       <kg>205</kg>
   </animal>
</zoo>

<?xml version="1.0"?>
<xs:schema
               xmlns:xs="http://www.w3.org/2001/XMLSchema"
               targetNamespace="http://www.example.com"
               xmlns="http://www.example.com"
               elementFormDefault="qualified">
<xs:element name="zoo"><xs:complexType><xs:sequence>
   <xs:element name="animal" maxOccurs="unbounded">
      <xs:complexType>
         <xs:sequence>
            <xs:element name="name" type="xs:string"/>
            <xs:element name="type"><xs:simpleType>
               <xs:restriction base="xs:string">
                  <xs:enumeration value="lion"/>
                  <xs:enumeration value="bear"/>
                  <xs:enumeration value="tiger"/>
               </xs:restriction>
            </xs:simpleType></xs:element>
            <xs:element name="kg"><xs:simpleType>
               <xs:restriction base="xs:integer">
                  <xs:minInclusive value="10"/>
                  <xs:maxInclusive value="5000"/>
               </xs:restriction>
            </xs:simpleType></xs:element>
            <xs:element name="imported" minOccurs="0">
               <xs:complexType/>
            </xs:element>
         </xs:sequence>
         <xs:attribute name="id" type="xs:string"/>
      </xs:complexType>
   </xs:element>
</xs:sequence></xs:complexType></xs:element>
</xs:schema>
schema can have the following attributes: element and attribute can have the following attributes: attribute can additionally have: complexType can have the following attributes: If an attribute or element does not have the 'type' attribute, its type must be declared as its child element.

Multiple XSD files can be specified in the XML file, for example:
<ns1:root
  xmlns:ns1="http://example.com/1"
  xmlns:ns2="http://example.com/2"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://example.com/1 ns1.xsd
               http://example.com/2 ns2.xsd">
  <ns2:a/>
</ns1:root>

Each namespace used in the instance document is mapped to its own schema file in xsi:schemaLocation, given as pairs of namespace URI and schema location.


Elements Hierarchy (Simplified)

schema
    group, attributeGroup
    redefine
    notation
    import
    include
    element
        alternative
        simpleType
            union
            list
            restriction
                (assert)
                enumeration
                fractionDigits
                length
                {max|min}Exclusive
                {max|min}Inclusive
                {max|min}Length
                pattern
                totalDigits
                whiteSpace
        complexType
            openContent
            sequence, choice, all
                (element)
                (group)
                any
            attribute, anyAttribute
            (group), (attributeGroup)
            simpleContent, complexContent
                (restriction)
                    (assert)
                extension
                    (assert)
            assert
        unique, key, keyref
            selector
            field
annotation
    appinfo
    documentation

Notes on the hierarchy above: schema is always the document root; annotation can be the child of any element; simpleType can be a child of attribute, element, list, restriction, schema, and union; complexType can be a child of element, redefine, and schema; attribute can be a child of attributeGroup, schema, complexType, restriction (both simpleContent and complexContent), and extension (both simpleContent and complexContent); anyAttribute can be a child of complexType, restriction (both simpleContent and complexContent), extension (both simpleContent and complexContent), and attributeGroup; group can be a child of schema, choice, sequence, all, complexType, restriction, and extension; attributeGroup can be a child of attributeGroup, complexType, schema, restriction, and extension; sequence and choice can be a child of group, choice, sequence, complexType, restriction, and extension; all can be a child of group, complexType, restriction, and extension; restriction can be a child of simpleType, simpleContent, and complexContent.

sequence means that the child elements must appear in the specified order, each occurring one time.
choice means that only one of the child elements can appear.
all means that the child elements can appear in any order, each occurring one time.

For element, sequence, choice, all, any, or group, the 'minOccurs' and 'maxOccurs' attributes dictate the minimum and maximum number of times an element (or group of elements) can appear.

Assertions

The following uses assertions to deny certain attribute and element values, as well as to validate the order of the attribute values.

<?xml version="1.0" encoding="UTF-8"?>
<Transactions
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:noNamespaceSchemaLocation="transactions.xsd">
   <Transaction OrderID="50">-1000</Transaction>
   <Transaction OrderID="60">1000</Transaction>
   <Transaction OrderID="70">3000</Transaction>
   <Transaction OrderID="300">2000</Transaction>
</Transactions>

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema
   xmlns:xs="http://www.w3.org/2001/XMLSchema">
   <xs:element name="Transactions">
      <xs:complexType>
         <xs:sequence>
            <xs:element name="Transaction"
                               maxOccurs="unbounded">
               <xs:complexType>
                  <xs:simpleContent>
                     <xs:extension base="xs:integer">
                        <xs:attribute name="OrderID"
                                             type="xs:integer"/>
                        <xs:assert test=
                               "empty(index-of((8,9,10),@OrderID))"/>
                        <xs:assert test=
                               "$value = (-3000 to 3000)"/>
                     </xs:extension>
                  </xs:simpleContent>
               </xs:complexType>
            </xs:element>
         </xs:sequence>
         <xs:assert test="every $x in Transaction satisfies
               (empty($x/preceding-sibling::*) or
               ($x/@OrderID gt
                             $x/preceding-sibling::*[1]/@OrderID))"/>
      </xs:complexType>
   </xs:element>
</xs:schema>
The value for the 'test' attribute in assert is an XPath expression.

Annotations, Groups, References, and Restrictions

The following illustrates how to use annotations, groups, references, and restrictions.

<?xml version="1.0"?>
<dictionary
   xmlns="http://www.example.com"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://www.example.com
                                   dictionary.xsd">
   <word id="w5445353" initial="b">
      <spelling>beautiful</spelling>
      <type>adjective</type>
   </word>
   <word id="w1222234" initial="t">
      <spelling>table</spelling>
      <type form="singular">noun</type>
   </word>
</dictionary>

<?xml version="1.0"?>
<!-- dictionary.xsd -->
<xs:schema
           xmlns:xs="http://www.w3.org/2001/XMLSchema"
           targetNamespace="http://www.example.com"
           xmlns="http://www.example.com"
           elementFormDefault="qualified">
<xs:include schemaLocation="dictDef.xsd"/>
<xs:element name="dictionary" type="dType"/>
</xs:schema>

<?xml version="1.0"?>
<!-- dictDef.xsd -->

<xs:schema
           xmlns:xs="http://www.w3.org/2001/XMLSchema"
           targetNamespace="http://www.example.com"
           xmlns="http://www.example.com"
           elementFormDefault="qualified">
<xs:annotation>
   <xs:appinfo source="http://example.com/info/">
      Example Note
   </xs:appinfo>
   <xs:documentation source="http://example.com/info/">
      A group, attribute group, or custom
      type may be reused multiple times.
   </xs:documentation>
</xs:annotation>
<xs:simpleType name="wType">
   <xs:restriction base="xs:string">
      <xs:enumeration value="noun"/>
      <xs:enumeration value="verb"/>
      <xs:enumeration value="adjective"/>
   </xs:restriction>
</xs:simpleType>

<xs:group name="wSequence">
   <xs:sequence>
      <xs:element name="spelling"><xs:simpleType>
         <xs:restriction base="xs:string">
            <xs:pattern value="[a-zA-Z ]+"/>
            <xs:maxLength  value="50"/>
            <xs:whiteSpace  value="collapse"/>
         </xs:restriction>
      </xs:simpleType></xs:element>
      <xs:element name="type">
         <xs:complexType><xs:simpleContent>
             <xs:extension base="wType">
                <xs:attribute name="form">
                   <xs:simpleType>
                      <xs:restriction base="xs:string">
                         <xs:enumeration value="singular"/>
                         <xs:enumeration value="plural"/>
                         <xs:enumeration value="present"/>
                         <xs:enumeration value="past"/>
                      </xs:restriction>
                   </xs:simpleType>
                </xs:attribute>
             </xs:extension>
         </xs:simpleContent></xs:complexType>
      </xs:element>
   </xs:sequence>
</xs:group>
<xs:attributeGroup name="wAttributes">
   <xs:attribute name="id" type="xs:ID" />
   <xs:attribute name="initial" type="xs:NMTOKEN" />
   <xs:anyAttribute/>
</xs:attributeGroup>
<xs:complexType name="dType"><xs:sequence>
   <xs:element name="word" maxOccurs="999999">
      <xs:complexType>
         <xs:group ref="wSequence"/>
         <xs:attributeGroup ref="wAttributes"/>
      </xs:complexType>
   </xs:element>
</xs:sequence></xs:complexType>
</xs:schema>
dictDef.xsd custom-defines a simple data type, a complex data type, a group of elements, and a group of attributes for reuse elsewhere in the schema. element and attribute can also carry the 'rel' attribute.

include adds an external XSD schema with the same target namespace. To add a schema with a different target namespace, use import instead:
<xs:import namespace="http://example.com/schema"/>
<xs:import schemaLocation="http://example.com/schema"/>

import brings in a schema with a different target namespace than the importing schema.

For restriction and extension, the base attribute must be specified, and can be either a built-in primitive data type or a custom data type.

complexType cannot include both a restriction and an extension. To restrict and declare an attribute for an element at the same time, first declare a restricted simpleType, and use that type as the base for the extension of the element.

anyAttribute allows the element to include attributes not declared by the schema.

complexContent contains an extension or a restriction for a complexType. simpleContent contains an extension or a restriction for a simpleType, or for a complexType containing text only.

Conditional Type Assignment

The following demonstrates conditional type assignment, in which the type of an element depends on one of its attributes. This also shows how to specify XSD versions for the validator, using the vc:minVersion and vc:maxVersion attributes from the XML Schema versioning namespace.

<?xml version="1.0" encoding="UTF-8"?>
<integer xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:noNamespaceSchemaLocation="file:///C:/Zend/Apache2/htdocs/xml/integer.xsd"
              kind="b">127</integer>

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
                 xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning"
                 elementFormDefault="qualified"
                 attributeFormDefault="unqualified"
                 vc:minVersion="1.1">
   <xs:complexType name="bInt">
      <xs:simpleContent>
         <xs:extension base="xs:byte">
            <xs:attribute name="kind" type="xs:string"/>
         </xs:extension>
      </xs:simpleContent>
   </xs:complexType>
   <xs:complexType name="sInt">
      <xs:simpleContent>
         <xs:extension base="xs:short">
            <xs:attribute name="kind" type="xs:string"/>
         </xs:extension>
      </xs:simpleContent>
   </xs:complexType>
   <xs:complexType name="iInt">
      <xs:simpleContent>
         <xs:extension base="xs:int">
            <xs:attribute name="kind" type="xs:string"/>
         </xs:extension>
      </xs:simpleContent>
   </xs:complexType>
   <xs:complexType name="lInt">
      <xs:simpleContent>
         <xs:extension base="xs:long">
            <xs:attribute name="kind" type="xs:string"/>
         </xs:extension>
      </xs:simpleContent>
   </xs:complexType>
   <xs:complexType name="gInt">
      <xs:simpleContent>
         <xs:extension base="xs:integer">
            <xs:attribute name="kind" type="xs:string"/>
         </xs:extension>
      </xs:simpleContent>
   </xs:complexType>
   <xs:element name="integer"
                      vc:minVersion="1.1" vc:maxVersion="3.0">
      <xs:alternative test="@kind='b'" type="bInt"/>
      <xs:alternative test="@kind='s'" type="sInt"/>
      <xs:alternative test="@kind='i'" type="iInt"/>
      <xs:alternative test="@kind='l'" type="lInt"/>
      <xs:alternative                          type="gInt"/>
   </xs:element>
</xs:schema>

Notation, List, Union, and Numeric Restrictions

The following illustrates notation, list, union, dateTime, and numeric restrictions.

<?xml version="1.0"?>
<dtList
   xmlns="http://www.example.com"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://www.example.com date.xsd">
   2013-03-02Z
   12:00:00+08:00
   2013-03-02T12:00:00+08:00
   123
   321.444
</dtList>

<?xml version="1.0"?>
<xs:schema
           xmlns:xs="http://www.w3.org/2001/XMLSchema"
           targetNamespace="http://www.example.com"
           xmlns="http://www.example.com"
           elementFormDefault="qualified">

<xs:notation name="jpeg"
                    public="image/jpeg" system="viewer.exe" />
<xs:simpleType name="numbers">
   <xs:restriction base="xs:decimal">
      <xs:totalDigits value="10"/>
      <xs:fractionDigits value="3"/>
   </xs:restriction>
</xs:simpleType>
<xs:simpleType name="dUnion">
   <xs:union memberTypes="xs:date
                                          xs:time
                                          xs:dateTime
                                          numbers"/>
</xs:simpleType>
<xs:element name="dtList">
   <xs:simpleType>
      <xs:list itemType="dUnion"/>
   </xs:simpleType>
</xs:element>

</xs:schema>
totalDigits specifies the maximum number of digits allowed. fractionDigits specifies the maximum number of digits allowed after the decimal point.

any, notation, and Mixed Content

The following shows how to declare any element, notation, and 'mixed' content. Here, <nameslist> must start with one single arbitrary element. An element named <description> must appear after another element named <name>, with any number of arbitrarily named elements in between.

<?xml version="1.0" encoding="UTF-8"?>
<nameslist
  xmlns="http://www.example.com"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.example.com
                                  nameslist.xsd">
<group>Famous People</group>

<person>
   <name>Bruce</name>
   <age>30</age>
   <description>He is a real <b>fighter</b>.</description>
</person>
<person>
   <name>Stephen</name>
   <sex>male</sex>
   <status>married</status>
   <description>He is a real <b>writer</b>.</description>
</person>
</nameslist>

<?xml version="1.0"?>
<xs:schema
      xmlns:xs="http://www.w3.org/2001/XMLSchema"
      xmlns="http://www.example.com"
      targetNamespace="http://www.example.com"
      elementFormDefault="qualified">
   <xs:notation name="jpeg"
                       public="image/jpeg" system="viewer.exe" />
   <xs:element name="nameslist">
      <xs:complexType>
        <xs:sequence>
           <xs:any namespace="##any" processContents="lax"
                        notQName="name description person"/>
           <xs:element name="person" maxOccurs="10">
              <xs:complexType>
                 <xs:openContent>
                    <xs:any namespace="##any"
                                 processContents="lax"/>
	  </xs:openContent>
	  <xs:sequence>
	      <xs:element name="name" type="xs:string"/>
	      <xs:element name="description">
	         <xs:complexType mixed="true">
	            <xs:sequence>
                            <xs:element name="b" type="xs:string"/>
	            </xs:sequence>
	         </xs:complexType>
                    </xs:element>
                 </xs:sequence>
              </xs:complexType>
            </xs:element>
         </xs:sequence>
      </xs:complexType>
   </xs:element>
</xs:schema>
Group references are allowed in all model groups.

A notation describes the format of non-XML data.

A complexType or complexContent with the mixed attribute declared as 'true' can have text around its child elements, i.e. a mixture of elements and text.

openContent can have the 'mode' attribute, which can have a value of 'none', 'interleave', or 'suffix'. The default is 'interleave'.

any and anyAttribute can have the following attributes:

redefine

redefine allows simple and complex types, groups, and attribute groups to be redefined from an external schema. This construct is deprecated in XSD 1.1.

<?xml version="1.0"?>
<item
   xmlns="http://www.example.com"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://www.example.com item.xsd">
   <name>ruler</name>
   <price>1.00</price>
</item>

<?xml version="1.0"?>
<!-- item.xsd -->
<xs:schema
           xmlns:xs="http://www.w3.org/2001/XMLSchema"
           targetNamespace="http://www.example.com"
           xmlns="http://www.example.com"
           elementFormDefault="qualified">
<xs:redefine schemaLocation="item2.xsd">
  <xs:complexType name="iDetails">
    <xs:complexContent>
      <xs:extension base="iDetails">
        <xs:sequence>
          <xs:element name="price"/>
        </xs:sequence>
      </xs:extension>
    </xs:complexContent>
  </xs:complexType>
</xs:redefine>
<xs:element name="item" type="iDetails"/>
</xs:schema>

<?xml version="1.0"?>
<!-- item2.xsd -->
<xs:schema
           xmlns:xs="http://www.w3.org/2001/XMLSchema"
           targetNamespace="http://www.example.com"
           xmlns="http://www.example.com"
           elementFormDefault="qualified">
<xs:complexType name="iDetails">
  <xs:sequence>
    <xs:element name="name"/>
  </xs:sequence>
</xs:complexType>
</xs:schema>

override

override works in a similar way to redefine.

<?xml version="1.0"?>
<item
   xmlns="http://www.example.com"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://www.example.com item.xsd">
   <price>1.00</price>
</item>

<?xml version="1.0"?>
<!-- item.xsd -->
<xs:schema
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns="http://www.example.com"
    targetNamespace="http://www.example.com"
    elementFormDefault="qualified">
   <xs:override schemaLocation="item2.xsd">
      <xs:complexType name="iDetails">
         <xs:sequence>
            <xs:element name="price"/>
         </xs:sequence>
      </xs:complexType>
   </xs:override>
   <xs:element name="item" type="iDetails"/>
</xs:schema>

<?xml version="1.0"?>
<!-- item2.xsd -->
<xs:schema
        xmlns:xs="http://www.w3.org/2001/XMLSchema"
        xmlns="http://www.example.com"
        targetNamespace="http://www.example.com"
        elementFormDefault="qualified">
   <xs:complexType name="iDetails">
      <xs:sequence>
         <xs:element name="name"/>
      </xs:sequence>
   </xs:complexType>
</xs:schema>

Substitution Groups

The following demonstrates substitution. All three XML documents below are valid against the same schema.

<?xml version="1.0" ?>
<section
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:noNamespaceSchemaLocation="body.xsd">
   <p>Hello World!</p>
</section>

<?xml version="1.0" ?>
<body
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:noNamespaceSchemaLocation="body.xsd">
   <div>Hello World!</div>
</body>

<?xml version="1.0" ?>
<section
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:noNamespaceSchemaLocation="body.xsd">
   <div>Hello World!</div>
</section>

<xs:schema
      xmlns:xs="http://www.w3.org/2001/XMLSchema"
      elementFormDefault="qualified">
   <xs:complexType name="sContent">
      <xs:sequence>
         <xs:element ref="p"/>
      </xs:sequence>
   </xs:complexType>
   <xs:element name="section" type="sContent"/>
   <xs:element name="body" substitutionGroup="section"/>

   <xs:element name="p" type="xs:string"/>
   <xs:element name="span" type="xs:string"/>
   <xs:element name="div" substitutionGroup="p span"/>
</xs:schema>
element and complexType can have the following attributes:

Identity Constraints

The following example illustrates identity constraints. Each child of <items> must have a 'number' attribute whose value matches one of the unique product numbers. Each <product> element must have a <number> child whose value is unique.

<?xml version="1.0" ?>
<shipment
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:noNamespaceSchemaLocation="shipment.xsd">
  <number>987QWERTY</number>
  <items>
    <thermometer number="876">
      <quantity>1</quantity>
      <color value="blue"/>
    </thermometer>
    <thermometer number="876">
      <quantity>1</quantity>
      <color value="sage"/>
    </thermometer>
    <pump number="432">
      <quantity>1</quantity>
    </pump>
  </items>
  <products>
    <product>
      <number>876</number>
      <name>TM-902C K Type Digital Thermometer</name>
      <price currency="USD">14.99</price>
    </product>
    <product>
      <number>432</number>
      <name>3CFM 1/4HP Rotary Vane Vacuum Pump</name>
      <price currency="USD">59.99</price>
    </product>
  </products>
</shipment>

<xs:schema
           xmlns:xs="http://www.w3.org/2001/XMLSchema"
           elementFormDefault="qualified">
  <xs:element name="shipment" type="OrderType">
    <xs:keyref name="prodNumKeyRef" refer="prodNumKey">
      <xs:selector xpath="items/*"/>
      <xs:field xpath="@number"/>
    </xs:keyref>
    <xs:key name="prodNumKey">
      <xs:selector xpath=".//product"/>
      <xs:field xpath="number"/>
    </xs:key>
  </xs:element>
  <xs:complexType name="OrderType">
    <xs:sequence>
      <xs:element name="number" type="xs:string"/>
      <xs:element name="items" type="ItemsType"/>
      <xs:element name="products" type="ProductsType"/>
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="ItemsType">
    <xs:choice maxOccurs="unbounded">
      <xs:element name="thermometer"
                          type="ProductOrderType"/>
      <xs:element name="pump" type="ProductOrderType"/>
    </xs:choice>
  </xs:complexType>
  <xs:complexType name="ProductOrderType">
    <xs:sequence>
      <xs:element name="quantity" type="xs:integer"/>
      <xs:element name="color" type="ColorType"
                                              minOccurs="0"/>
    </xs:sequence>
    <xs:attribute name="number" type="xs:integer"/>
  </xs:complexType>
  <xs:complexType name="ProductsType">
    <xs:sequence>
      <xs:element name="product" type="ProductType"
                                                  maxOccurs="unbounded"/>
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="ProductType">
    <xs:sequence>
      <xs:element name="number" type="xs:integer"/>
      <xs:element name="name" type="xs:string"/>
      <xs:element name="price" type="PriceType"/>
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="ColorType">
    <xs:attribute name="value" type="xs:string"/>
  </xs:complexType>
  <xs:complexType name="PriceType">
    <xs:simpleContent>
      <xs:extension base="xs:decimal">
        <xs:attribute name="currency" type="xs:token"/>
      </xs:extension>
    </xs:simpleContent>
  </xs:complexType>
</xs:schema>