Mastering XML Schemas


The W3C XML Schema Language

Elliotte Rusty Harold

Software Development 2003 West

Wednesday, March 26, 2003

elharo@metalab.unc.edu

http://www.cafeconleche.org/


What are Schemas?


About Schemas


What's Wrong with DTDs?


greeting.xml

<?xml version="1.0"?>
<GREETING>
Hello XML!
</GREETING>

greeting.xsd

<?xml version="1.0"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
 
  <xsd:element name="GREETING" type="xsd:string"/>

</xsd:schema>

Attaching the schema to the document without namespaces


Validating the document with Xerces-J 2.1.0

D:\schemas\examples>java sax.Counter -v greeting2.xml
greeting2.xml: 701 ms (1 elems, 1 attrs, 0 spaces, 12 chars)

An Invalid Document

<?xml version="1.0"?>
<GREETING xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:noNamespaceSchemaLocation="greeting.xsd">
  <P>Hello XML!</P>
</GREETING>

Checking the Invalid Document

D:\speaking\Software Development 2003 West\schemas\examples>java sax.Counter -v greeting3.xml
[Error] greeting3.xml:4:6: Element type "P" must be declared.
[Error] greeting3.xml:5:13: Datatype error: In element 'GREETING' : Can not have
 element children within a simple type content.
greeting3.xml: 781 ms (2 elems, 1 attrs, 0 spaces, 14 chars)

Schema Aware Parsers


Complex vs. Simple Types


Four main schema elements:


A More Complex Document

<?xml version="1.0"?>
<SONG xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:noNamespaceSchemaLocation="simple_song.xsd">
  <TITLE>Hot Cop</TITLE>
  <COMPOSER>Jacques Morali</COMPOSER>
  <COMPOSER>Henri Belolo</COMPOSER>
  <COMPOSER>Victor Willis</COMPOSER>
  <PRODUCER>Jacques Morali</PRODUCER>
  <PUBLISHER>PolyGram Records</PUBLISHER>
  <LENGTH>6:20</LENGTH>
  <YEAR>1978</YEAR>
  <ARTIST>Village People</ARTIST>  
</SONG>

A More Complex Schema

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">

  <xsd:element name="SONG" type="SongType"/>
 
  <xsd:complexType name="SongType">
    <xsd:sequence>
      <xsd:element name="TITLE"     type="xsd:string"
        minOccurs="1" maxOccurs="1"/>
      <xsd:element name="COMPOSER"  type="xsd:string" 
        minOccurs="1" maxOccurs="unbounded"/>
      <xsd:element name="PRODUCER"  type="xsd:string" 
        minOccurs="0" maxOccurs="unbounded"/>
      <xsd:element name="PUBLISHER" type="xsd:string" 
        minOccurs="0" maxOccurs="1"/>
      <xsd:element name="LENGTH"    type="xsd:duration"
        minOccurs="1" maxOccurs="1"/>
      <xsd:element name="YEAR"      type="xsd:gYear"
        minOccurs="1" maxOccurs="1"/>
      <xsd:element name="ARTIST"    type="xsd:string" 
        minOccurs="1" maxOccurs="unbounded"/>
    </xsd:sequence>
  </xsd:complexType>
 
</xsd:schema>

Validating the Song Document

D:\speaking\Software Development 2003 West\schemas\examples>java sax.Counter -v original_hotcop.xml
[Error] original_hotcop.xml:10:25: Datatype error: In element 'LENGTH' : Value '6:20' is not legal value for current datatype. null. original_hotcop.xml: 1583 ms (10 elems, 2 attrs, 30 spaces, 98 chars)


Here's the problem:

<?xml version="1.0"?>
<SONG xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:noNamespaceSchemaLocation="simple_song.xsd">
  <TITLE>Hot Cop</TITLE>
  <COMPOSER>Jacques Morali</COMPOSER>
  <COMPOSER>Henri Belolo</COMPOSER>
  <COMPOSER>Victor Willis</COMPOSER>
  <PRODUCER>Jacques Morali</PRODUCER>
  <PUBLISHER>PolyGram Records</PUBLISHER>
  <LENGTH>6:20</LENGTH>
  <YEAR>1978</YEAR>
  <ARTIST>Village People</ARTIST>  
</SONG>

The LENGTH element not in the schema time duration format! which is ISO 8601 "PnYn MnDTnH nMnS, where nY represents the number of years, nM the number of months, nD the number of days, 'T' is the date/time separator, nH the number of hours, nM the number of minutes and nS the number of seconds. The number of seconds can include decimal digits to arbitrary precision. An optional preceding minus sign ('-') is allowed, to indicate a negative duration."


Fixed Hot Cop

<?xml version="1.0"?>
<SONG xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:noNamespaceSchemaLocation="simple_song.xsd">
  <TITLE>Hot Cop</TITLE>
  <COMPOSER>Jacques Morali</COMPOSER>
  <COMPOSER>Henri Belolo</COMPOSER>
  <COMPOSER>Victor Willis</COMPOSER>
  <PRODUCER>Jacques Morali</PRODUCER>
  <PUBLISHER>PolyGram Records</PUBLISHER>
  <LENGTH>P0YT6M20S</LENGTH>
  <YEAR>1978</YEAR>
  <ARTIST>Village People</ARTIST>
</SONG>

A Smaller Schema

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">

  <xsd:element name="SONG" type="SongType"/>
 
  <xsd:complexType name="SongType">
    <xsd:sequence>
      <xsd:element name="TITLE"     type="xsd:string"/>
      <xsd:element name="COMPOSER"  type="xsd:string" 
        maxOccurs="unbounded"/>
      <xsd:element name="PRODUCER"  type="xsd:string" 
        minOccurs="0" maxOccurs="unbounded"/>
      <xsd:element name="PUBLISHER" type="xsd:string" 
        minOccurs="0"/>
      <xsd:element name="LENGTH"    type="xsd:duration"/>
      <xsd:element name="YEAR"      type="xsd:gYear"/>
      <xsd:element name="ARTIST"    type="xsd:string" 
        maxOccurs="unbounded"/>
    </xsd:sequence>
  </xsd:complexType>
 
</xsd:schema>

Anonymous Types

<?xml version="1.0"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">

  <xsd:element name="SONG">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element name="TITLE"     type="xsd:string"/>
        <xsd:element name="COMPOSER"  type="xsd:string" 
          minOccurs="1" maxOccurs="unbounded"/>
        <xsd:element name="PRODUCER"  type="xsd:string" 
          minOccurs="0" maxOccurs="unbounded"/>
        <xsd:element name="PUBLISHER" type="xsd:string" 
          minOccurs="0" maxOccurs="1"/>
        <xsd:element name="LENGTH"    type="xsd:duration"/>
        <xsd:element name="YEAR"      type="xsd:string"/>
        <xsd:element name="ARTIST"    type="xsd:string" 
          minOccurs="1" maxOccurs="unbounded"/>
      </xsd:sequence>
    </xsd:complexType>
  </xsd:element>
 
</xsd:schema>

Data Typing

Consider this document:

<foo>
    <value>45.67</value>
</foo>

What is the type of value?


Possible types

Other interpretations are doubtless possible, and even make sense in particular contexts. There's no guarantee that the string 45.67 in fact represents any particular type.


The PSVI


Primitive Data Types for Schemas


Numeric Data Types for Schemas

XML Schema Built-In Numeric Simple Types
Name Type Examples
float IEEE 754 32-bit floating point number -INF, -1E4, -0, 0, 12.78E-2, 12, INF, NaN
double IEEE 754 64-bit floating point number -INF, 1.401E-90, -1E4, -0, 0, 12.78E-2, 12, INF, NaN, 3.4E42
decimal arbitrary precision, decimal numbers -2.7E400, 5.7E-444, -3.1415292, 0, 7.8, 90200.76, 3.4E1024
integer an arbitrarily large or small integer -500000000000000000000000, -9223372036854775809, -126789, -1, 0, 1, 5, 23, 42, 126789, 9223372036854775808, 456734987324983264987362495809587095720978
nonPositiveInteger an integer less than or equal to zero 0, -1, -2, -3, -4, -5, ...
negativeInteger an integer strictly less than zero -1, -2, -3, -4, -5, ...
long an eight-byte two's complement integer such as Java's long type -9223372036854775808, -12678967543233, -1, 9223372036854775807
int an integer that can be represented as a four-byte, two's complement number such as Java's int type -2147483648, -1, 0, 1, 5, 23, 42, 2147483647
short an integer that can be represented as a two-byte, two's complement number such as Java's short type -32768, -1, 0, 1, 5, 23, 42, 32767
byte an integer that can be represented as a one-byte, two's complement number such as Java's byte type -128, -1, 0, 1, 5, 23, 42, 127
nonNegativeInteger an integer greater than or equal to zero 0, 1, 2, 3, 4, 5, ...
unsignedLong an eight-byte unsigned integer 0, 1, 2, 3, 4, 5, ...18446744073709551614, 18446744073709551615
unsignedInt a four-byte unsigned integer 0, 1, 2, 3, 4, 5, ...4294967294, 4294967295
unsignedShort a two-byte unsigned integer 0, 1, 2, 3, 4, 5, ...65534, 65535
unsignedByte a one-byte unsigned integer 0, 1, 2, 3, 4, 5, ...254, 255
positiveInteger an integer strictly greater than zero 1, 2, 3, 4, 5, 6, ...

Time Data Types for Schemas

XML Schema Built-In Time Simple Types
Name Type Examples
dateTime a particular moment in Coordinated Universal Time; up to an arbitrarily small fraction of a second 1999-05-31T13:20:00.000-05:00
gMonth A given month in a given year 2000-10
gYear a given year 2000
gMonthDay a date in no particular year, or rather in every year --10-31
gDay a day in no particular month, or rather in every mnonth ----31
duration a length of time, without fixed endpoints, to an arbitrary fraction of a second P2000Y10M31DT09H32M7.4312S
date a specific day in history 2000-10-31
time a specific time of day, that recurs every day 14:30:00.000, 09:30:00.000-05:00

XML Data Types for Schemas

XML Schema Built-In XML Simple Types
Name Type Examples
ID XML 1.0 ID attribute type any XML name that's unique among ID type attributes
IDREF XML 1.0 IDREF attribute type any XML name that's used as an ID type attribute elsewhere in the document
ENTITY XML 1.0 ENTITY attribute type any XML name that's declared as an unparsed entity in the DTD
NOTATION XML 1.0 NOTATION attribute type any XML name that's declared as a notation name in the DTD
language Permissible values for xml:lang as defined in XML 1.0 en-GB, en-US, fr
IDREFS XML 1.0 IDREFS attribute type a white space separated list of IDREF names
ENTITIES XML 1.0 ENTITIES attribute type a white space separated list of ENTITY names
NMTOKEN XML 1.0 NMTOKEN attribute type 12 are you ready
NMTOKENS XML 1.0 NMTOKENS attribute type a white space separated list of name tokens
Name An XML 1.0 Name set, title, rdf, math, math123, href
QName an optionally prefixed, namespace qualified name song:title
NCName a local name without any colons title

Assorted Data Types for Schemas

XML Schema Built-In Simple Types
Name Type Examples
string Parsed Character Data; #PCDATA Hot Cop
normalizedString A string whose normalized value does not contain any tabs, carriage returns, or linefeeds PIC1, PIC2, PIC3, cow_movie, MonaLisa, Hello World , Warhol, red green
token A string whose normalized value has no leading or trailing white space, no tabs, no linefeeds, and not more than one consecutive space p1 p2, ss123 45 6789, _92, red, green, NT Decl, seventeenp1, p2, 123 45 6789, ^*&^*&_92, red green blue, NT-Decl, seventeen; Mary had a little lamb, The love of money is the root of all Evil.
boolean C++'s bool type true, false, 1, 0
anyURI relative or absolute URI http://www.w3.org/TR/2000/WD-xmlschema-2-20000407/#duration, /javafaq/reports/JCE1.2.1.html
hexBinary Arbitrary binary data encoded in hexadecimal form A4E345EC54CC8D52198000FFEA6C
base64Binary Arbitrary binary data encoded in Base64 6jKpNnmkkWeArsn5Oeeg2njcz+nXdk0f9kZI892ddlR8Lg1aMhPeFTYuoq3I6neFlb BjWzuktNZKiXYBfKsSTB8U09dTiJo2ir3HJuY7eW/p89osKMfixPQsp9vQMgzph6Qa lY7j4MB7y5ROJYsTr1/fFwmj/yhkHwpbpzed1LE=

Derived Types


Deriving by restriction


Facets


Length Facets: length, minLength, maxLength


Facets for ordered items: minExclusive, maxExclusive, minInclusive, maxInclusive


whiteSpace


Facets for decimal numbers: totalDigits and fractionDigits


Enumeration


Adding a Price

<?xml version="1.0"?>
<SONG xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:noNamespaceSchemaLocation="priced_song.xsd">
  <TITLE>Hot Cop</TITLE>
  <COMPOSER>Jacques Morali</COMPOSER>
  <COMPOSER>Henri Belolo</COMPOSER>
  <COMPOSER>Victor Willis</COMPOSER>
  <PRODUCER>Jacques Morali</PRODUCER>
  <PUBLISHER>PolyGram Records</PUBLISHER>
  <YEAR>1978</YEAR>
  <ARTIST>Village People</ARTIST>  
  <PRICE>$1.35</PRICE>  
</SONG>

The pattern facet


Regular Expressions


The Price Schema

<?xml version="1.0"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
 
  <xsd:element name="SONG" type="SongType"/>

  <xsd:simpleType name="money">
    <xsd:restriction base="xsd:string">             
      <xsd:pattern value="\p{Sc}\p{Nd}+(\.\p{Nd}\p{Nd})?"/>
    <!-- 
       Regular Expression:
       \p{Sc}             Any Unicode currency indicator; e.g. $, &#xA5, &#xA3, &#A4, etc.
       \p{Nd}             A Unicode decimal digit character
       \p{Nd}+            One or more Unicode decimal digit characters
       \.                 The period character
       (\.\p{Nd}\p{Nd})
       (\.\p{Nd}\p{Nd})?  Zero or one strings of the form .35
       
       This works for any decimalized currency. 
       
    -->
    </xsd:restriction>
  </xsd:simpleType>

  <xsd:complexType name="SongType">
    <xsd:sequence>
      <xsd:element name="TITLE"     type="xsd:string"/>
      <xsd:element name="COMPOSER"  type="xsd:string" 
        maxOccurs="unbounded"/>
      <xsd:element name="PRODUCER"  type="xsd:string" 
        minOccurs="0" maxOccurs="unbounded"/>
      <xsd:element name="PUBLISHER" type="xsd:string" 
        minOccurs="0"/>
      <xsd:element name="YEAR"   type="xsd:gYear"/>
      <xsd:element name="ARTIST" type="xsd:string" 
        maxOccurs="unbounded"/>
      <xsd:element name="PRICE" type="money"/>      
     </xsd:sequence> 
  </xsd:complexType>
  
</xsd:schema>

Complex Types


A Document with Attributes

<?xml version="1.0"?>
<SONG xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:noNamespaceSchemaLocation="attribute_song.xsd">
  <TITLE>Hot Cop</TITLE>
  <PHOTO ALT="Victor Willis in Cop Outfit" WIDTH="100" HEIGHT="200"/>
  <COMPOSER>Jacques Morali</COMPOSER>
  <COMPOSER>Henri Belolo</COMPOSER>
  <COMPOSER>Victor Willis</COMPOSER>
  <PRODUCER>Jacques Morali</PRODUCER>
  <PUBLISHER>PolyGram Records</PUBLISHER>
  <YEAR>1978</YEAR>
  <ARTIST>Village People</ARTIST>  
</SONG>

Declaring Attributes

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
 
  <xsd:element name="SONG" type="SongType"/>

  <!-- An empty element -->
  <xsd:complexType name="PhotoType">
    <xsd:complexContent>
       <xsd:restriction base="xsd:anyType">
         <xsd:attribute name="ALT"    type="xsd:string"/>
         <xsd:attribute name="WIDTH"  type="xsd:positiveInteger"/>
         <xsd:attribute name="HEIGHT" type="xsd:positiveInteger"/> 
      </xsd:restriction>
    </xsd:complexContent>
  </xsd:complexType>

  <xsd:complexType name="SongType">
    <xsd:sequence>
      <xsd:element name="TITLE"     type="xsd:string"/>
      <xsd:element name="PHOTO"     type="PhotoType"  
        minOccurs="0"/>
      <xsd:element name="COMPOSER"  type="xsd:string" 
        maxOccurs="unbounded"/>
      <xsd:element name="PRODUCER"  type="xsd:string" 
        minOccurs="0" maxOccurs="unbounded"/>
      <xsd:element name="PUBLISHER" type="xsd:string" 
        minOccurs="0"/>
      <xsd:element name="YEAR"   type="xsd:gYear"/>
      <xsd:element name="ARTIST" type="xsd:string" 
        maxOccurs="unbounded"/>
    </xsd:sequence>
  </xsd:complexType>

</xsd:schema>

Element Content

<?xml version="1.0"?>
<SONG xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:noNamespaceSchemaLocation="nested_song.xsd">
  <TITLE>Hot Cop</TITLE>
  <PHOTO ALT="Victor Willis in Cop Outfit" WIDTH="100" HEIGHT="200"/>
  <COMPOSER>
    <NAME>
      <GIVEN>Jacques</GIVEN>
      <FAMILY>Morali</FAMILY>
    </NAME>
  </COMPOSER>
  <COMPOSER>
    <NAME>
      <GIVEN>Henri</GIVEN>
      <FAMILY>Belolo</FAMILY>
    </NAME>
  </COMPOSER>
  <COMPOSER>
    <NAME>
      <GIVEN>Victor</GIVEN>
      <FAMILY>Willis</FAMILY>
    </NAME>
  </COMPOSER>
  <PRODUCER>
    <NAME>
      <GIVEN>Jacques</GIVEN>
      <FAMILY>Morali</FAMILY>
    </NAME>
  </PRODUCER>
  <PUBLISHER>PolyGram Records</PUBLISHER>
  <YEAR>1978</YEAR>
  <ARTIST>Village People</ARTIST>  
</SONG>

Declaring Complex Types

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
 
  <xsd:element name="SONG" type="SongType"/>

  <xsd:complexType name="ComposerType">
    <xsd:sequence>
      <xsd:element name="NAME">
        <xsd:complexType>
          <xsd:sequence>
             <xsd:element name="GIVEN"  type="xsd:string"/>
             <xsd:element name="FAMILY" type="xsd:string"/>  
          </xsd:sequence>    
        </xsd:complexType>
      </xsd:element>
    </xsd:sequence>
  </xsd:complexType>

  <xsd:complexType name="ProducerType">
    <xsd:sequence>
      <xsd:element name="NAME">
        <xsd:complexType>
          <xsd:sequence>
            <xsd:element name="GIVEN"  type="xsd:string"/>
            <xsd:element name="FAMILY" type="xsd:string"/>
          </xsd:sequence>      
        </xsd:complexType>
      </xsd:element>
    </xsd:sequence>
  </xsd:complexType>

  <xsd:complexType name="PhotoType">
    <xsd:complexContent>
       <xsd:restriction base="xsd:anyType">
         <xsd:attribute name="ALT"    type="xsd:string"/>
         <xsd:attribute name="WIDTH"  type="xsd:positiveInteger"/>
         <xsd:attribute name="HEIGHT" type="xsd:positiveInteger"/> 
      </xsd:restriction>
    </xsd:complexContent>
  </xsd:complexType>
  
  <xsd:complexType name="SongType">
    <xsd:sequence>
      <xsd:element name="TITLE"     type="xsd:string"/>
      <xsd:element name="PHOTO"     type="PhotoType"  
        minOccurs="0"/>
      <xsd:element name="COMPOSER"  type="ComposerType" 
        maxOccurs="unbounded"/>
      <xsd:element name="PRODUCER"  type="ProducerType" 
        minOccurs="0" maxOccurs="unbounded"/>
      <xsd:element name="PUBLISHER" type="xsd:string" 
        minOccurs="0"/>
      <xsd:element name="YEAR"   type="xsd:gYear"/>
      <xsd:element name="ARTIST" type="xsd:string" 
        maxOccurs="unbounded"/>
    </xsd:sequence>
  </xsd:complexType>

</xsd:schema>

Sharing Content Models

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
 
  <xsd:element name="SONG" type="SongType"/>

  <xsd:complexType name="PersonType">
    <xsd:sequence>
      <xsd:element name="NAME">
        <xsd:complexType>
          <xsd:sequence>
             <xsd:element name="GIVEN"  type="xsd:string"/>
             <xsd:element name="FAMILY" type="xsd:string"/>  
          </xsd:sequence>    
        </xsd:complexType>
      </xsd:element>
    </xsd:sequence>
  </xsd:complexType>

  <xsd:complexType name="SongType">
    <xsd:sequence>
      <xsd:element name="TITLE"     type="xsd:string"/>
      <xsd:element name="PHOTO"     type="PhotoType"  
        minOccurs="0"/>
      <xsd:element name="COMPOSER"  type="PersonType" 
        maxOccurs="unbounded"/>
      <xsd:element name="PRODUCER"  type="PersonType" 
        minOccurs="0" maxOccurs="unbounded"/>
      <xsd:element name="PUBLISHER" type="xsd:string" 
        minOccurs="0"/>
      <xsd:element name="YEAR"   type="xsd:gYear"/>
      <xsd:element name="ARTIST" type="xsd:string" 
        maxOccurs="unbounded"/>
    </xsd:sequence>
  </xsd:complexType>

  <xsd:complexType name="PhotoType">
    <xsd:complexContent>
       <xsd:restriction base="xsd:anyType">
         <xsd:attribute name="ALT"    type="xsd:string"/>
         <xsd:attribute name="WIDTH"  type="xsd:positiveInteger"/>
         <xsd:attribute name="HEIGHT" type="xsd:positiveInteger"/> 
      </xsd:restriction>
    </xsd:complexContent>
  </xsd:complexType>
  
</xsd:schema>

Mixed Content

<?xml version="1.0"?>
<SONG xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:noNamespaceSchemaLocation="mixed_song.xsd">
  <TITLE>Hot Cop</TITLE>
  <PHOTO ALT="Victor Willis in Cop Outfit" WIDTH="100" HEIGHT="200"/>
  <COMPOSER>
    <NAME>Mr. <GIVEN>Jacques</GIVEN> <FAMILY>Morali</FAMILY> Esq.</NAME>
  </COMPOSER>
  <COMPOSER>
    <NAME>Mr. <GIVEN>Henri</GIVEN> L. <FAMILY>Belolo</FAMILY>, M.D.</NAME>
  </COMPOSER>
  <COMPOSER>
    <NAME>Mr. <GIVEN>Victor</GIVEN> C. <FAMILY>Willis</FAMILY></NAME>
  </COMPOSER>
  <PRODUCER>
    <NAME>Mr. <GIVEN>Jacques</GIVEN> S. <FAMILY>Morali</FAMILY></NAME>
  </PRODUCER>
  <PUBLISHER>PolyGram Records</PUBLISHER>
  <YEAR>1978</YEAR>
  <ARTIST>Village People</ARTIST>  
</SONG>

Declaring Mixed Content

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
 
  <xsd:element name="SONG" type="SongType"/>

  <xsd:complexType name="PersonType">
    <xsd:sequence>
      <xsd:element name="NAME">
        <xsd:complexType mixed="true">
          <xsd:sequence>
            <xsd:element name="GIVEN"  type="xsd:string"/>
            <xsd:element name="FAMILY" type="xsd:string"/>
           </xsd:sequence>      
         </xsd:complexType>
      </xsd:element>
    </xsd:sequence>
  </xsd:complexType>

  <xsd:complexType name="SongType">
    <xsd:sequence>
      <xsd:element name="TITLE"     type="xsd:string"/>
      <xsd:element name="PHOTO"     type="PhotoType"  
        minOccurs="0"/>
      <xsd:element name="COMPOSER"  type="PersonType" 
        maxOccurs="unbounded"/>
      <xsd:element name="PRODUCER"  type="PersonType" 
        minOccurs="0" maxOccurs="unbounded"/>
      <xsd:element name="PUBLISHER" type="xsd:string" 
        minOccurs="0"/>
      <xsd:element name="YEAR"   type="xsd:gYear"/>
      <xsd:element name="ARTIST" type="xsd:string" 
        maxOccurs="unbounded"/>
    </xsd:sequence>
  </xsd:complexType>

  <xsd:complexType name="PhotoType">
    <xsd:complexContent>
       <xsd:restriction base="xsd:anyType">
         <xsd:attribute name="ALT"    type="xsd:string"/>
         <xsd:attribute name="WIDTH"  type="xsd:positiveInteger"/>
         <xsd:attribute name="HEIGHT" type="xsd:positiveInteger"/> 
      </xsd:restriction>
    </xsd:complexContent>
  </xsd:complexType>
  
</xsd:schema>

When Order Doesn't Matter

<?xml version="1.0"?>
<SONG xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:noNamespaceSchemaLocation="unordered_song.xsd">
  <TITLE>Hot Cop</TITLE>
  <PHOTO ALT="Victor Willis in Cop Outfit" WIDTH="100" HEIGHT="200"/>
  <COMPOSER>
    <NAME><FAMILY>Morali</FAMILY> <GIVEN>Jacques</GIVEN></NAME>
  </COMPOSER>
  <COMPOSER>
    <NAME><GIVEN>Henri</GIVEN> <FAMILY>Belolo</FAMILY></NAME>
  </COMPOSER>
  <COMPOSER>
    <NAME><FAMILY>Willis</FAMILY> <GIVEN>Victor</GIVEN></NAME>
  </COMPOSER>
  <PRODUCER>
    <NAME><GIVEN>Jacques</GIVEN> <FAMILY>Morali</FAMILY></NAME>
  </PRODUCER>
  <PUBLISHER>PolyGram Records</PUBLISHER>
  <YEAR>1978</YEAR>
  <ARTIST>Village People</ARTIST>  
</SONG>

The xsd:all Group

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
 
  <xsd:element name="SONG" type="SongType"/>

  <xsd:complexType name="PersonType">
    <xsd:sequence>
      <xsd:element name="NAME">
        <xsd:complexType>
          <xsd:all>
            <xsd:element name="GIVEN"  type="xsd:string"/>
            <xsd:element name="FAMILY" type="xsd:string"/> 
          </xsd:all>     
        </xsd:complexType>
      </xsd:element>
    </xsd:sequence>
  </xsd:complexType>

  <xsd:complexType name="SongType">
    <xsd:sequence>
      <xsd:element name="TITLE"     type="xsd:string"/>
      <xsd:element name="PHOTO"     type="PhotoType"  
        minOccurs="0"/>
      <xsd:element name="COMPOSER"  type="PersonType" 
        maxOccurs="unbounded"/>
      <xsd:element name="PRODUCER"  type="PersonType" 
        minOccurs="0" maxOccurs="unbounded"/>
      <xsd:element name="PUBLISHER" type="xsd:string" 
        minOccurs="0"/>
      <xsd:element name="YEAR"   type="xsd:gYear"/>
      <xsd:element name="ARTIST" type="xsd:string" 
        maxOccurs="unbounded"/>
    </xsd:sequence>
  </xsd:complexType>

  <!-- An empty element -->
  <xsd:complexType name="PhotoType" content="empty">
    <xsd:complexContent>
       <xsd:restriction base="xsd:anyType">
         <xsd:attribute name="ALT"    type="xsd:string"/>
         <xsd:attribute name="WIDTH"  type="xsd:positiveInteger"/>
         <xsd:attribute name="HEIGHT" type="xsd:positiveInteger"/> 
      </xsd:restriction>
    </xsd:complexContent>
  </xsd:complexType>
  
</xsd:schema>

Choices

<xsd:complexType name="SongType">
  <xsd:sequence>
    <xsd:element name="TITLE" type="xsd:string"/>
    <xsd:element name="COMPOSER" type="PersonType"/>
    <xsd:choice minOccurs="0" maxOccurs="unbounded">
      <xsd:element name="PRODUCER" type="PersonType"/>
      <xsd:element name="COMPOSER" type="PersonType"/>
      <xsd:element name="ARTIST"   type="xsd:string"/>
    </xsd:choice>
    <xsd:element name="ARTIST" type="xsd:string"/>
    <xsd:element name="PUBLISHER" type="xsd:string"
                 minOccurs="0"/>
    <xsd:element name="LENGTH" type="xsd:string"/>
    <xsd:element name="YEAR"   type="xsd:string"/>
    <xsd:element name="PRICE" type="xsd:string" minOccurs="0"/>
  </xsd:sequence>
</xsd:complexType>

Sequences


Schemas and Namespaces


Default Namespace

<?xml version="1.0"?>
<GREETING 
  xmlns="http://www.cafeconleche.org/schemas/greeting/"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.cafeconleche.org/schemas/greeting/
                      greeting_defaultNS.xsd">
  Hello XML!
</GREETING>

The targetNamespace attribute

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  targetNamespace="http://www.cafeconleche.org/schemas/greeting/"
>
 
  <xsd:element name="GREETING" type="xsd:string"/>

</xsd:schema>

A Song with a Namespace

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<SONG xmlns="http://www.cafeconleche.org/namespace/song"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation = 
       "http://www.cafeconleche.org/namespace/song namespace_song.xsd"
>
  <TITLE>Hot Cop</TITLE>
  <PHOTO ALT="Victor Willis in Cop Outfit" WIDTH="100" HEIGHT="200"/>
  <COMPOSER>Jacques Morali</COMPOSER>
  <COMPOSER>Henri Belolo</COMPOSER>
  <COMPOSER>Victor Willis</COMPOSER>
  <PRODUCER>Jacques Morali</PRODUCER>
  <PUBLISHER>PolyGram Records</PUBLISHER>
  <YEAR>1978</YEAR>
  <ARTIST>Village People</ARTIST>  
</SONG>

A Schema for a Document that Uses the Default Namespace

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  targetNamespace="http://www.cafeconleche.org/namespace/song"
  elementFormDefault="qualified"
  attributeFormDefault="unqualified"
>
 
  <xsd:element name="SONG" type="SongType"/>

  <xsd:complexType name="SongType">
    <xsd:sequence>
      <xsd:element name="TITLE" type="xsd:string"/>
      <xsd:element name="PHOTO" type="PhotoType"  
        minOccurs="0"/>
      <xsd:element name="COMPOSER"  type="xsd:string" 
        maxOccurs="unbounded"/>
      <xsd:element name="PRODUCER"  type="xsd:string" 
        minOccurs="0" maxOccurs="unbounded"/>
      <xsd:element name="PUBLISHER" type="xsd:string" 
        minOccurs="0"/>    
      <xsd:element name="YEAR" type="xsd:gYear"/>
      <xsd:element name="ARTIST" type="xsd:string" 
        minOccurs="0" maxOccurs="unbounded"/>
    </xsd:sequence>
  </xsd:complexType>

  <xsd:complexType name="PhotoType">
    <xsd:complexContent>
       <xsd:restriction base="xsd:anyType">
         <xsd:attribute name="ALT"    type="xsd:string"/>
         <xsd:attribute name="WIDTH"  type="xsd:positiveInteger"/>
         <xsd:attribute name="HEIGHT" type="xsd:positiveInteger"/> 
      </xsd:restriction>
    </xsd:complexContent>
  </xsd:complexType>
  
</xsd:schema>

Multiple Namespaces, Multiple Schemas

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<SONG xmlns="http://www.cafeconleche.org/namespace/song"
      xmlns:xlink="http://www.w3.org/1999/xlink"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation = 
       "http://www.cafeconleche.org/namespace/song xlink_song.xsd
        http://www.w3.org/1999/xlink xlink.xsd"
>
  <TITLE>Hot Cop</TITLE>
  <PHOTO xlink:type="simple" xlink:href="hotcop.jpg"
         xlink:actuate="onLoad" xlink:show="embed"
    ALT="Victor Willis in Cop Outfit" WIDTH="100" HEIGHT="200"/>
  <COMPOSER>Jacques Morali</COMPOSER>
  <COMPOSER>Henri Belolo</COMPOSER>
  <COMPOSER>Victor Willis</COMPOSER>
  <PRODUCER>Jacques Morali</PRODUCER>
  <PUBLISHER>PolyGram Records</PUBLISHER>
  <YEAR>1978</YEAR>
  <ARTIST>Village People</ARTIST>  
</SONG>

XLink Schema

<?xml version="1.0"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  targetNamespace="http://www.w3.org/1999/xlink"
>

  <xsd:attribute name="type" type="xsd:string" 
                 fixed="simple" />
  <xsd:attribute name="href" type="xsd:anyURI" />
  <xsd:attribute name="actuate" type="xsd:string"
                 fixed="onLoad" />
  <xsd:attribute name="show" type="xsd:string"
                 fixed="embed" />

</xsd:schema>

Song Schema with XLink Support

<?xml version="1.0"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  xmlns:xlink="http://www.w3.org/1999/xlink"
  targetNamespace="http://www.cafeconleche.org/namespace/song"
  elementFormDefault="qualified"
>

  <xsd:import namespace="http://www.w3.org/1999/xlink"
              schemaLocation="xlink.xsd"/>

  <xsd:element name="SONG" type="SongType"/>

  <xsd:complexType name="PhotoType">
    <xsd:attribute name="WIDTH"  type="xsd:nonNegativeInteger"
                   use="required" />
    <xsd:attribute name="HEIGHT" type="xsd:nonNegativeInteger"
                   use="required" />
    <xsd:attribute name="ALT"    type="xsd:string"
                   use="required" />
    <xsd:attribute ref="xlink:type"/>
    <xsd:attribute ref="xlink:href" use="required"/>
    <xsd:attribute ref="xlink:actuate"/>
    <xsd:attribute ref="xlink:show"/>                 
  </xsd:complexType>

  <xsd:complexType name="SongType">
    <xsd:sequence>
      <xsd:element name="TITLE"     type="xsd:string"/>
      <xsd:element name="PHOTO"     type="PhotoType"/>
      <xsd:element name="COMPOSER"  type="xsd:string"
                   maxOccurs="unbounded"/>
      <xsd:element name="PRODUCER"  type="xsd:string"
                   minOccurs="0" maxOccurs="unbounded"/>
      <xsd:element name="PUBLISHER" type="xsd:string"
                   minOccurs="0"/>
      <xsd:element name="YEAR"      type="xsd:gYear"/>
      <xsd:element name="ARTIST"    type="xsd:string"
                   maxOccurs="unbounded"/>
    </xsd:sequence>
  </xsd:complexType>

</xsd:schema>

Annotations

<?xml version="1.0"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">

  <xsd:annotation>
    <xsd:documentation>
      Song schema example for XML Schemas tutorial
      Copyright 2001 Elliotte Rusty Harold. 
    </xsd:documentation>
  </xsd:annotation>
 
  <xsd:element name="SONG" type="SongType"/>

  <xsd:simpleType name="money">
    <xsd:restriction base="xsd:string">             
      <xsd:pattern value="\p{Sc}\p{Nd}+(\.\p{Nd}\p{Nd})?">
        <xsd:annotation>
          <xsd:documentation>
       \p{Sc}             Any Unicode currency indicator; e.g. $, &#xA5, &#xA3, &#A4, etc.
       \p{Nd}             A Unicode decimal digit character
       \p{Nd}+            One or more Unicode decimal digit characters
       \.                 The period character
       (\.\p{Nd}\p{Nd})
       (\.\p{Nd}\p{Nd})?  Zero or one strings of the form .35
       
       This works for any decimalized currency.           
          </xsd:documentation>
        </xsd:annotation>
      </xsd:pattern>
    </xsd:restriction>
  </xsd:simpleType>

  <xsd:complexType name="SongType">
    <xsd:sequence>
      <xsd:element name="TITLE"     type="xsd:string"/>
      <xsd:element name="COMPOSER"  type="xsd:string" 
        maxOccurs="unbounded"/>
      <xsd:element name="PRODUCER"  type="xsd:string" 
        minOccurs="0" maxOccurs="unbounded"/>
      <xsd:element name="PUBLISHER" type="xsd:string" 
        minOccurs="0"/>
      <xsd:element name="YEAR"   type="xsd:gYear"/>
      <xsd:element name="ARTIST" type="xsd:string" 
        maxOccurs="unbounded"/>
      <xsd:element name="PRICE" type="money"/>      
     </xsd:sequence> 
  </xsd:complexType>
  
</xsd:schema>

What Schemas don't do


W3C XML Schema Language Alternatives


Schematron


A Schematron schema for songs

<?xml version="1.0"?>
<schema xmlns="http://www.ascc.net/xml/schematron">
  <title>A Schematron Schema for Songs</title>
  <pattern>
    <rule context="SONG">
      <assert test="TITLE">
        A SONG must contain an initial TITLE element.
      </assert>
      <assert test="TITLE[position()=1]">
        The TITLE element must be the initial element of the SONG element.
      </assert>
      <assert test="COMPOSER">
        A SONG must contain at least one COMPOSER element.
      </assert>
      <assert test="ARTIST">
        A SONG must contain at least one ARTIST element.
      </assert>
    </rule>
  </pattern>
</schema>
 

RELAX NG


A RELAX-NG Song Schema

<?xml version="1.0"?>
<element name="SONG" xmlns="http://relaxng.org/ns/structure/1.0"
    datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
  <interleave>
  
    <element name="TITLE">
      <text/>
    </element>
    
    <zeroOrMore>
      <element name="COMPOSER">
        <text/>
      </element>
    </zeroOrMore>
    
    <zeroOrMore>
      <element name="PRODUCER">
        <text/>
      </element>
    </zeroOrMore>
    
    <optional>
      <element name="PUBLISHER">
        <text/>
      </element>
    </optional>

    <element name="LENGTH">
      <data type="duration"/>
    </element>

    <element name="YEAR">
      <data type="gYear"/>
    </element>

    <oneOrMore>
      <element name="ARTIST">
        <text/>
      </element>
    </oneOrMore>

    <optional>
      <element name="PRICE">
        <data type="string">
          <param name="pattern">\p{Sc}\p{Nd}+(\.\p{Nd}\p{Nd})?</param>
        </data>
      </element>
    </optional>
    
  </interleave>
</element>
 

Non-XML RELAX NG Syntax

element SONG {
  element TITLE { text }
  & element COMPOSER { text }*
  & element PRODUCER { text }*
  & element PUBLISHER { text }?
  & element LENGTH { xsd:duration }
  & element YEAR { xsd:gYear }
  & element ARTIST { text }+
  & element PRICE {
      xsd:string { pattern = "\p{Sc}\p{Nd}+(\.\p{Nd}\p{Nd})?" }
    }?
}
 

Hook


Examplotron

<?xml version="1.0"?>
<SONG xmlns:eg="http://examplotron.org/0/">
  <TITLE>Put title here</TITLE>
  <COMPOSER eg:occurs="+">Author of song</COMPOSER>
  <PRODUCER eg:occurs="*">Put producer here</PRODUCER>
  <PUBLISHER eg:occurs="?">Put publisher here</PUBLISHER>
  <LENGTH>Length of song</LENGTH>
  <YEAR>Year song was published</YEAR>
  <ARTIST eg:occurs="+">Singers and musicians</ARTIST>  
</SONG>

DTDs aren't Dead!


To Learn More


Index | Cafe con Leche

Copyright 2000-2003 Elliotte Rusty Harold
elharo@metalab.unc.edu
Last Modified January 16, 2003