3.2. Schema

As we have seen in the previous section, a DTD defines constraints on the order and nesting of elements in an XML file, but the type of constraints is limited and does not allow validation of the character content of elements, except for enumeration values and ID/IDREF. There are also other drawbacks: all element names in a DTD must be unique and thus combining separately developed DTDs can become quite cumbersome. Moreover, the DTD file is not a well-formed XML file, thus one cannot easily use an XML tool to create or process it. This is why XML Schema has been introduced with a comprehensive set of elementary types and a way to combine them to create new types. The concept of namespaces (presented in Section 2.1) is also used in order to facilitate the combination of independent files without name clashes.

A Schema is a well-formed XML file (usually with a .xsd extension) that defines types used to validate the elements of an XML file. In a way similar to variable declarations in a programming language, we can define types. We follow the Java convention of starting type identifiers with an upper case letter. Element identifiers start with a lower case letter. In a name comprising more than one word, each word starts with an uppercase letter. No underscore or dash are used. For most elements, we define a type having the same name as the element, but capitalized, instead of using inline definitions of embedded elements. In a Schema, there are two kinds of types: simple and complex. Simple types define constraints on the text content of an element which cannot contain any element. A complex type can contain nested elements.

There are many different ways of organizing a Schema as described by Van der Vlist [60]. One can either use a Russian doll approach in which a single element is defined with its nested elements defined internally. Another approach is to use a bottom-up approach in which the elements are defined before they are used in more complex elements. It is also possible to use a top-down approach that first defines the higher level elements before defining the lower level elements. All these styles of definitions are possible and we will sometimes use a mix of them in order to show some features of XML Schema.

Table 3.2 presents the XML elements we use in our example to define the types needed for the validation of our wine catalog and cellar book. Since a schema is itself an XML file, it is important to distinguish the elements defining the Schema from the elements being defined. This is ensured by using a different namespace for the defining element (definiens) such as xs: as prefix (xsd: is also commonly used). A defined element (definiendum) does not have a prefix, it is in the default namespace. Contrarily to a DTD, an XML Schema is a valid XML file and it can be validated using the XML Schema of XML Schemas, usually provided with in all XML editors.

Table 3.2. XML Schema syntax reminder

<xs:schema targetNameSpace="URI">
    xs:import* {xs:simpleType | xs:complexType | xs:element | xs:group}*
</xs:schema>
<xs:import nameSpace="URI"
    schemaLocation="URI"/>
<xs:simpleType name="NCName">
    xs:restriction
</xs:simpleType>
<xs:complexType name="NCName"
    mixed="true">
    {xs:choice | xs:sequence | xs:group}? xs:attribute*
</xs:complexType>
<xs:element name="QName"
    type="TName"/>
<xs:element name="QName"
    ref="EName"/>
<xs:element name="QName">
    {xs:simpleType | xs:complexType}?
    {xs:unique | xs:key | xs:keyref}*
</xs:element>
<xs:sequence {min|max}occurs="nonNegativeInteger|unbounded">
    {xs:element | xs:choice | xs:sequence | xs:group}*
</xs:sequence>
<xs:choice {min|max}occurs="nonNegativeInteger|unbounded">
    {xs:element | xs:choice | xs:sequence | xs:group}*
</xs:choice>
<xs:group name="NCName">
    {xs:choice | xs:sequence}*
</xs:group>
<xs:attribute name="NCName"
    type="TName"
    use="required"/>
<xs:restriction base="TName">
    <xs:{max|min}{in|ex}clusive value="anySimpleType"/>
    | <xs:{max|min}length value ="nonNegativeInteger"
    | <pattern value = "regExp"
    | <enumeration value = "anyValue"
</xs:restriction>
<xs:{unique|key} name="NCName">
    xs:selector xs:field+
</xs:{unique|key}>
<xs:keyref name="NCName"
    refer="NCName">
    xs:selector xs:field+
</xs:keyref>
<xs:{selector|field} xpath="XPathExpr"/>

A reminder of the subset of the XML Schema syntax used in Example 3.3 and Example 3.4. Names in italics refer to other elements. NCName (non-colonized name) is a name without a namespace prefix. Regular expressions syntax is given in Table B.1.


An XML Schema has an xs:schema element as root which can contain different kinds of definition elements.

In the rest of this section, we first give in Example 3.3 and Example 3.4 the XML Schemas that correspond respectively to the DTDs of Example 3.1 and Example 3.2. Figure 3.1 gives the overall structure of the XML Schema of Example 3.3. Figure 3.2 gives the overall structure of the Schema in Example 3.4. As we will see, the validation of the text content of the elements can be much more thorough with an XML Schema than with a DTD.

We will then explain the structure of the type system: first simple types (Section 3.2.1) and then complex types (Section 3.2.2).

Figure 3.1. Graphical view of the schema for the cellar book

Graphical view of the schema for the cellar book

A name in a rectangular box is an element name or, if preceded by @, an attribute name. A complex type name is preceded by a square and a simple type by a triangle. A sequence is shown with 4 dots horizontally aligned in an hexagon and a choice with 4 dots aligned vertically (see Figure 5.2 for an example). A + after a box indicates that further details have been omitted. Three small squares in front of an element name either indicates that its definition will be referred to somewhere else in the schema; the reference is indicated by a small arrow at the bottom right of the rectangle. This figure was produced by the <oXygen/> XML editor from the XML Schema file given in Example 3.3.


Example 3.3. [CellarBook.xsd] XML Schema for the cellar book, validation of the instance file in Example 2.2.

This file can be compared with the DTD shown in Example 3.1.

  1 <?xml version="1.0" encoding="UTF-8"?>
    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
        xmlns:cat="http://www.iro.umontreal.ca/lapalme/wine-catalog">
    
  5     <xs:import namespace="http://www.iro.umontreal.ca/lapalme/wine-catalog(1)"
            schemaLocation="WineCatalog.xsd"/>
    
        <xs:element name="cellar">                                       (2)
            <xs:complexType>
 10             <xs:sequence minOccurs="0" maxOccurs="unbounded">
                    <xs:element name="wine" type="Wine"/>                (3)
                </xs:sequence>
            </xs:complexType>
        </xs:element>
 15 
        <xs:complexType name="Wine">                                     (4)
            <xs:sequence>
                <xs:element name="purchaseDate" type="xs:date"/>         (5)
                <xs:element name="quantity" type="xs:nonNegativeInteger"/>
 20             <xs:element name="rating" minOccurs="0">
                    <xs:complexType>
                        <xs:attribute name="stars" type="xs:positiveInteger"/>(6)
                    </xs:complexType>
                </xs:element>
 25             <xs:element name="comment" type="cat:Comment" minOccurs="0"/>
            </xs:sequence>
            <xs:attribute name="code" type="xs:IDREF" use="required"/>        (7)
        </xs:complexType>
    
 30     
        <xs:element name="name">                                         (8)
            <xs:complexType>
                <xs:all>                                                 (9)
                    <xs:element name="first" type="xs:string" minOccurs="(10)0"/>
 35                 <xs:element name="family" type="xs:string" minOccurs="0"/>
                    <xs:element name="initial" type="xs:string" minOccurs="0"/>
                </xs:all>
            </xs:complexType>
        </xs:element>
 40 
    
        <xs:element name="cellar-book">                                  (11)
            <xs:complexType>
                <xs:sequence>
 45                 <xs:element ref="cat:wine-catalog"/>
                    <xs:element name="owner" type="Owner"/>
                    <xs:element name="location" minOccurs="0">
                        <xs:complexType>
                            <xs:group ref="address"/>
 50                     </xs:complexType>
                    </xs:element>
                    <xs:element ref="cellar"/>
                </xs:sequence>
            </xs:complexType>
 55     </xs:element>
    
        <xs:group name="address">                                        (12)
            <xs:sequence>
                <xs:element name="street" type="xs:string"/>
 60             <xs:element name="city" type="xs:string"/>
                <xs:element name="province" type="ProvinceCA"/>
                <xs:element name="postal-code" type="PostalCodeCA"/>     (13)
            </xs:sequence>
        </xs:group>
 65 
        <xs:simpleType name="ProvinceCA">
            <!-- http://www.canadapost.ca/tools/pg/manual/b03-e.asp#c012 -->
            <xs:restriction base="xs:string">
                <xs:enumeration value="AB"/>
 70             <xs:enumeration value="BC"/>
                <xs:enumeration value="MB"/>
                <xs:enumeration value="NB"/>                             (14)
                <xs:enumeration value="NL"/>
                <xs:enumeration value="NT"/>
 75             <xs:enumeration value="NS"/>
                <xs:enumeration value="NU"/>
                <xs:enumeration value="ON"/>
                <xs:enumeration value="QC"/>
                <xs:enumeration value="SK"/>
 80             <xs:enumeration value="YT"/>
            </xs:restriction>
        </xs:simpleType>
    
        <xs:complexType name="Owner">                                    (15)
 85         <xs:sequence>
                <xs:element ref="name"/>
                <xs:group ref="address"/>
            </xs:sequence>
        </xs:complexType>
 90 
        <xs:simpleType name="PostalCodeCA">                              (16)
            <xs:restriction base="xs:string">
                <xs:pattern value="[A-Z][0-9][A-Z] [0-9][A-Z][0-9]"/>
            </xs:restriction>
 95     </xs:simpleType>
    </xs:schema>
    

1

Gets the types defined in the schema for the wine catalog, which uses a different namespace, the one identified by the cat prefix.

2

Element cellar is a possibly empty list of wine elements of type Wine defined at line line 16‑4.

3

Definition of element wine of type Wine.

4

The type Wine for the cellar-book defines a set of bottles; it is defined with their date of purchase, the number of bottles, an optional rating given as a number of stars and an optional comment whose type is defined in the catalog in a different namespace.

5

The purchase date is of the predefined XML type date.

6

The rating is an empty element with an attribute stars indicating the number of stars, which must be a number greater than 0.

7

This attribute is the link between the wines defined by the quantities in the cellar and their description in the catalog. Being of type IDREF, it must make reference to an existing ID in the catalog.

8

The element name is a list of elements comprising the first name, the family name and initial in any order.

10

Each component of a name is a string.

9

As all elements are optional (minOccurs="0"), we obtain the usual definition of a name, contrarily to what we had to do with a DTD line 12‑6 of Example 3.1.

11

A cellar book is a list of elements starting with the wine catalog, followed by the owner element, an optional address and finally the description of the cellar itself using the element defined at line 8‑2.

12

An address is sequence of four elements indicating the street address, city, the province in Canada and a Canadian postal code. An address is not an element but a group that can be used to define other elements. Here it is used within the location element of the cellar-book (line 42‑11) and in the Owner type (line 84‑15).

13

A postal code is a string matching a regular expression defined in the pattern element in the simple type defined at line 91‑16.

14

The province is indicated by a two-letter code chosen among a predefined list.

15

An owner is a name element followed by the content of the address group, defined at line 57‑12.

16

A Canadian postal code is composed of two groups of three characters alternating between a capital letter and a number. The two groups are separated by a space.


Figure 3.2. Graphical view of the schema for the wine catalog

Graphical view of the schema for the wine catalog

Graphical view of the schema for the wine catalog (Example 3.4). See the caption of Figure 3.1 for an explanation of the symbols used in the figure.


Example 3.4. [WineCatalog.xsd] XML Schema file to validate the instance document shown in Example 2.3.

This file can be compared with the DTD shown in Example 3.2.

  1 <?xml version="1.0" encoding="UTF-8"?>
    <xs:schema xmlns:xs='http://www.w3.org/2001/XMLSchema'               (1)
        elementFormDefault="qualified"                                   (2)
        attributeFormDefault="unqualified"                               (3)
  5     xmlns:cat      ="http://www.iro.umontreal.ca/lapalme/wine-catalog"
        targetNamespace="http://www.iro.umontreal.ca/lapalme/wine-catalog">(4)
     
        <!-- needed because this schema will be imported     -->
        <xs:import namespace="http://www.w3.org/XML/1998/namespace" 
 10         schemaLocation="http://www.w3.org/2001/xml.xsd"/>
    
        <xs:element name="wine-catalog">                                 (5)
            <xs:complexType>
                <xs:sequence minOccurs="0" maxOccurs="unbounded">
 15                 <xs:element name="wine" type="cat:Wine"/>
                </xs:sequence>
                <!-- needed because this schema will be imported...-->
                <xs:attribute ref="xml:base"/>
            </xs:complexType>
 20     </xs:element> 
        
        <xs:complexType name="Wine">                                     (6)
            <xs:sequence>
                <xs:element name="properties" type="cat:Properties"/>
 25             <xs:element name="origin" type="cat:Origin"/>
                <xs:choice minOccurs="0" maxOccurs="unbounded">
                    <xs:element name="tasting-note" 
                        type="cat:Comment" minOccurs="0"/>
                    <xs:element name="food-pairing" 
 30                     type="cat:Comment" minOccurs="0"/>
                    <xs:element name="comment" 
                        type="cat:Comment" minOccurs="0"/>
                </xs:choice>
                <xs:element name="price" type="xs:decimal" ></xs:element>
 35             <xs:element name="year" type="xs:gYear"/>
            </xs:sequence>
            <xs:attribute name="name" type="xs:string" use="required"/>
            <xs:attribute name="appellation" type="xs:string"/>
            <xs:attribute name="classification" type="xs:string"/>
 40         <xs:attribute name="code" type="xs:ID"/>                     (7)
            <xs:attribute name="format" type="cat:Format"/>
        </xs:complexType>
        
        <xs:complexType name="Properties">                               (8)
 45         <xs:sequence>
                <xs:element name="color" type="cat:Color"/>
                <xs:element name="alcoholic-strength" type="cat:Percentage"/>
                <xs:element name="nature" type="xs:string" minOccurs="0"/>
            </xs:sequence>
 50     </xs:complexType>
        
        <xs:complexType name="Origin">                                   (9)
            <xs:sequence>
                <xs:element name="country" type="xs:string"/>
 55             <xs:element name="region" type="xs:string"/>
                <xs:element name="producer" type="xs:string"/>
            </xs:sequence>
        </xs:complexType>
        
 60     <xs:simpleType name="Format">                                    (10)
            <xs:restriction base="xs:string">
                <xs:enumeration value="375ml"/>
                <xs:enumeration value="750ml"/>
                <xs:enumeration value="1l"/>
 65             <xs:enumeration value="magnum">
                    <xs:annotation>
                        <xs:documentation> 1.5 litres</xs:documentation>
                    </xs:annotation>
                </xs:enumeration>
 70             <xs:enumeration value="jeroboam">
                    <xs:annotation>
                        <xs:documentation> 3 litres</xs:documentation>
                    </xs:annotation>
                </xs:enumeration>
 75             <xs:enumeration value="rehoboam">
                    <xs:annotation>
                        <xs:documentation> 4.5 litres</xs:documentation>
                    </xs:annotation>
                </xs:enumeration>
 80             <xs:enumeration value="mathusalem">
                    <xs:annotation>
                        <xs:documentation> 6 litres</xs:documentation>
                    </xs:annotation>
                </xs:enumeration>
 85             <xs:enumeration value="salmanazar">
                    <xs:annotation>
                        <xs:documentation> 9 litres</xs:documentation>
                    </xs:annotation>
                </xs:enumeration>
 90             <xs:enumeration value="balthazar">
                    <xs:annotation>
                        <xs:documentation>12 litres</xs:documentation>
                    </xs:annotation>
                </xs:enumeration>
 95             <xs:enumeration value="nabuchodonosor">
                    <xs:annotation>
                        <xs:documentation>15 litres</xs:documentation>
                    </xs:annotation>
                </xs:enumeration>
100         </xs:restriction>
        </xs:simpleType>
        
        <xs:complexType name="Comment" mixed="true">                     (11)
            <xs:sequence minOccurs="0" maxOccurs="unbounded">
105             <xs:choice>
                    <xs:element name="emph" type="xs:string"/>
                    <xs:element name="bold" type="xs:string"/>
                </xs:choice>
            </xs:sequence>
110     </xs:complexType>
            
        <xs:simpleType name="Color">                                     (12)
            <xs:restriction base="xs:string">
                <xs:enumeration value="red"/>
115             <xs:enumeration value="white"/>
                <xs:enumeration value="rosé"/>
            </xs:restriction>
        </xs:simpleType>
        
120     <xs:simpleType name="Percentage">                                (13)
            <xs:restriction base="xs:decimal">
                <xs:minInclusive value="0"/>
                <xs:maxInclusive value="100"/>
                <xs:fractionDigits value="2"/>
125         </xs:restriction>
        </xs:simpleType>
    </xs:schema>

1

Start of the schema for the wine catalog giving xs prefix for the elements used in the definition of other elements.

2

If a schema has a target namespace such as in line 6‑4, qualified means that all defined elements in this schema will be created in the target namespace.

3

unqualified means that all attributes in this schema will belong to the same namespace as their carrying element.

4

Defines the namespace that will be used for the elements defined by this schema.

5

The wine catalog is a (possibly empty) sequence of wine definitions. In order that references to internal elements remain valid when the instance file validated by this schema is imported by another file, an xml:base attribute is added by the import process. This implies that this attribute must also be allowed in the schema.

6

A wine entry of the catalog is a list of properties: its origins followed by optional tasting notes, food pairing suggestions and comments, its price and its production year. Other information such as the name, the appellation, the classification, the code and the format are given as attribute strings.

7

A wine in the catalog is assigned a unique code of type ID. The validation process will ensure their uniqueness across the whole file. It will be references by the code attribute in the wine definition of the cellar.

8

Properties defines the color of the wine, its alcoholic content as a percentage defined by a type on line 120‑13. Finally, an optional nature can be given as a string.

9

Origin is defined by the country, the region and the producer.

10

Format is a string value taken within the values appearing in an xs:enumeration element within the xs:restriction element. The content of the xs:annotation is for structured comments without any impact on the type constraints but they are kept within the schema structure. This information can then be used in XML applications, for example it can be displayed in by XML editors.

11

The mixed attribute having a yes value indicates that enclosed elements can be interleaved with text nodes. In this case, it means that the content of a comment is text with embedded emph and bold elements.

12

colorcan be only be one of three most often encountered possibilities. Wine connoisseurs might be shocked that wines cannot take other colors such as yellow.

13

A percentage is a number between 0 and 100 that must include 2 digits after the decimal point.


3.2.1. Simple Types

Figure 3.3. Built-in datatypes for XML Schema

Built-in datatypes for XML Schema

Built-in datatypes for XML Schema. ur-types serve as root of the type hierarchy for all derivations. ur is the German prefix meaning ancestral such as in Ursprung (beginning). Figure taken from section 3 of XML Schema Part 2: Datatypes [9].


A simple type is a primitive datatype, roughly corresponding to PCDATA in DTD, such as xs:string, xs:decimal, xs:double, xs:date (XML has 19 of them, shown in Figure 3.3) or a derivation of a primitive datatype. A derivation is a restriction on the original type such as constraining the maximum length of a string, giving a list of acceptable values, or requiring that the value matches a regular expression. Figure 3.3 shows a number of built-in derived types and types that are derived from them (i.e. appear under them). We can see uses of simple types in Example 3.3: stars (line 22‑6) which must not only be an integer but a positive one, first (line 34‑10) which is a string (essentially the same thing as a #PCDATA in a DTD).

Users can also define their own simple types, which cannot have any internal element, using the xs:simpleType element. A simple type definition can constrain a string to be one of many choices (ProvinceCA on line 72‑14) or to match a regular expression (PostalCodeCA on line 91‑16).

A new simple type can also be created using a list (allowing a series of primitive type values) or a union (allowing one of many primitive types). It is thus possible to define a whole gamut of types. These are quite straightforward, although the the devil is in the details described in [45] and [9].

3.2.2. Complex Types

Unlike a simple type, a complex type can contain element declarations, element references and attributes declarations. We will illustrate some of these possibilities with Example 3.3.

An element declaration is done with an xs:element specifying the name of the element and its type, which can either be defined as the value of the element, such as cellar (line 8‑2), or by indicating the type with the type attribute such as in wine (line 11‑3) or purchaseDate (line 18‑5).

A complex type is defined either by a sequence of elements contained in an xs:sequence element (see cellar on line 8‑2) or by a choice between many elements contained in an xs:choice element such as within name (line 31‑8). Attributes are defined after the definitions of the elements in sequence or in choice even though they appear in the start-tag (see code as attribute of wine, line 27‑7).

xs:choice and xs:sequence can be nested. For example, name (line 31‑8) indicates a choice between three elements of type string first, family and initial, which can be repeated any number of times. Indeed, because an element only occurs once by default (i.e. minOccurs="1") and that maxOccurs="unbounded", each element can appear as often as we wish.

An existing element can also be referred to using the ref attribute like name used in Owner (line 84‑15). But be aware that, in this case, if you had mistakenly used the name attribute instead of ref, you would have named a new element with no connection with the one you wished to have referenced; this can lead to errors that are difficult to track down (I learned this the hard way!!!).

In Example 3.4, the mixed="true" attribute in the definition of a type (see Comment, line 103‑11) means that character data can also appear between the elements described by the content of the type. In this case, character data can thus be interspersed with any number of emph and bold elements.

3.2.3. Namespaces in Schemas

We have introduced namespaces for instance documents in Section 2.1, but they only show their full power during the validation process in which the combination of element names and namespaces must correspond between the instance and the schema. Of course, namespaces must be properly combined during file inclusion and details can become quite intricate.

We will illustrate a simple but quite frequent case with Example 3.3 and Example 3.4 . These schemas both define a wine element, but with meanings and contents which must be distinguished. This is achieved with namespace declarations. A similar name clash occurs when we must define an element called type or sequence that is already used in the schema vocabulary. This is why we define a namespace (usually xs or xsd) for the element names of an XML Schema.

By default, names without prefixes are defined in the empty namespace or the namespace assigned to the xmlns attribute. To create elements in a specific namespace (and not the empty one), we set a value for the attribute as it is done for element targetNamespace in Example 3.4 (line 6‑4). The same namespace is also assigned to the prefix cat. elementFormDefault is set to qualified (line 3‑2 of Example 3.4) so that global elements and types of an included file are visible in the including file. The attributeFormDefault is set to unqualified to ensure that the attributes are in the same namespace as the containing element.

The import of elements from an external schema file along with its namespaces is done using xs:import (line 5‑1 of Example 3.3) indicating the namespace used in this file for the target namespace of the imported file (here we keep the same one) and the location of the file to be imported. The imported namespace must be given a prefix definition with an xmlns declaration, see the root tag of Example 3.3. Because the name associated with the target namespace of the imported file is the same as the one associated with the cat prefix, we use cat:wine to refer to the wine element of Example 3.4. Namespace and importation of RELAX NG schemas, described in the next section, are similar in principle to what we have shown for the importation of XML Schema.

We now better understand how namespaces are used in the instance documents and how they are linked to their schemas. For example, the first lines of Example 2.3 define the namespace associated with the null prefix (i.e. only the element name) as the value of the xmlns attribute. We also indicate the namespace and the location of the Schema to be used for validation as the value of the xsi:schemaLocation. The xsi prefix must also be defined by an attribute starting with xmlns:. Because all elements defined in this file are in the same package, to which we have assigned the null prefix, no namespace prefix is used in this file.

3.2.4. Overview of the XML Schemas

Example 2.1 (page ) shows the outline of our XML instance files validated by the two XML Schemas described in this section. Their outline is shown in Example 3.5. The instance file of the wine catalog is included in the one of the cellar book. So it was natural and convenient to have a similar organization for the corresponding schemas even though this is not always the case. In this case, the wine catalog schema is included in the cellar book schema. Note the use of the namespace prefixes in both the XML instance and the corresponding XML Schema files. The part in bold characters in Example 2.1 and Example 3.5 belong to different namespaces. Here, we kept the same name for the namespaces in both the instance file of the wine catalog and the corresponding schema. In Example 3.5, we see that references to lines in bold need to use the namespace prefix cat for the SAQ-code type (line 37‑9) and the wine-catalogelement (line 43‑11) .

These examples show another interesting use of namespaces: to make sure that relative references are kept, an xml:base attribute (line 19‑4) is added to the root element (line 14‑3) by when an instance file is included into another. In order that the resulting instance file remains valid, xml:base must be added as an attribute in the WineCatalog.xsd schema. xml:base is itself a special XML type whose definition must also be imported (line 11‑2 of Example 3.5).

Example 3.5. Outline of CellarBook.xsd importing Example 3.4 (shown in italics) in a different namespace.

  1 <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
        xmlns:cat="http://www.iro.umontreal.ca/lapalme/wine-catalog">
        
        <xs:schema 
  5         xmlns:xs='http://www.w3.org/2001/XMLSchema'
            elementFormDefault="qualified" 
            attributeFormDefault="unqualified"
            xmlns:cat      ="http://www.iro.umontreal.ca/lapalme/wine-catalog"
          targetNamespace="http://www.iro.umontreal.ca/lapalme/wine-catalog"> (1)
 10         
            <xs:import namespace="http://www.w3.org/XML/1998/namespace"  (2)
                schemaLocation="http://www.w3.org/2001/03/xml.xsd"/>
                
                <xs:element name="wine-catalog">                         (3)
 15                 <xs:complexType>
                        <xs:sequence minOccurs="0" maxOccurs="unbounded">
                            <xs:element name="wine" type="cat:Wine"/>
                        </xs:sequence>
                        <xs:attribute ref="xml:base"/>                   (4)
 20                 </xs:complexType>
                </xs:element> 
                
                <xs:complexType name="Wine">...</xs:complexType>         (5)
                ...
 25     </xs:schema>
            
        <xs:element name="cellar">                                       (6)
            <xs:complexType>
                <xs:sequence minOccurs="0" maxOccurs="unbounded">
 30                 <xs:element name="wine" type="Wine"/>                (7)
                </xs:sequence>
            </xs:complexType>
        </xs:element>
        
 35     <xs:complexType name="Wine">                                     (8)
          <xs:sequence>...</xs:sequence>
          <xs:attribute name="code" type="xs:IDREF" use="required"/>     (9)
        </xs:complexType>
        
 40     <xs:element name="cellar-book">                                  (10)
            <xs:complexType>
                <xs:sequence>
                    <xs:element ref="cat:wine-catalog"/>                 (11)
                    <xs:element name="owner" type="Owner"/>
 45                 <xs:element name="location" minOccurs="0">...</xs:element>
                    <xs:element ref="cellar"/>
                </xs:sequence>
            </xs:complexType>
        </xs:element>
 50     ...
    </xs:schema>

1

The target namespace of the imported schema is the one specified by the cat prefix.

2

Imports another schema whose content is shown here in italics.

3

The wine catalog is a list of wine descriptions.

4

Ensures that the base attribute added by the import process is properly defined.

5

Type for the wine description in the catalog.

6

Definition of the cellar in the top-level schema.

7

wine elements in the cellar refer to the Wine type definition of the cellar.

8

Type for the wine description in the cellar.

9

Reference to the imported type for the wine code.

10

Top-level element of the cellar.

11

Reference to the imported type for the wine-catalog (line 14‑3).