Ce document est une traduction de la recommandation XML Schema du W3C, datée du 2 mai 2001. Cette version traduite peut contenir des erreurs absentes de l'original, introduites par la traduction elle-même. La version originale en anglais, seule normative, se trouve à l'adresse http://www.w3.org/TR/2001/REC-xmlschema-0-20010502/.

Traduction :

Copyright © 1998 W3C (MIT, INRIA, Keio), tous droits réservés. Les règles du W3C sur la responsabilité, les marques commerciales, les droits des auteurs et les licences des logiciels sont applicables.

Remarque de la traduction: L'entité caractère nécessaire au "oe" ligaturé n'étant pas supportée par certains navigateurs, ce caractère sera écrit oe.



 

W3C

XML Schema tome 0 : Introduction

Recommandation du W3C du 2 Mai 2001

Cette version :
http://www.w3.org/TR/2001/REC-xmlschema-0-20010502/
Dernière version :
http://www.w3.org/TR/xmlschema-0/
Version précédente :
http://www.w3.org/TR/2001/PR-xmlschema-0-20010330/
Editeur :
David C. Fallside (IBM) fallside@us.ibm.com

Résumé

Le tome 0 de la spécification XML Schema n'est qu'une introduction et n'est pas un document normatif. Son objectif est de fournir un texte facilement compréhensible des fonctions offertes par XML Schema pour comprendre comment créer des schémas avec le langage XML Schema. Les documents normatifs XML Schema tome 1 : Structures et XML Schema tome 2 : Types de données contiennent une description complète et formelle de la norme. Dans cette introduction, les fonctions du langage sont décrites au travers d'un grand nombre d'exemples complétés par des renvois au texte normatif.

Statut de ce document

Ce chapitre décrit le statut de ce document au moment de sa publication. D'autres documents peuvent être plus récents que celui-ci. Le dernier statut en date de ce document est tenu à jour par le w3c.

Ce document a été contrôlé par les personnes concernées par le sujet, membres du W3C et autres, et a été validé par le directeur du W3C en tant que recommandation. Il s'agit donc d'un document stable qui peut être utilisé comme document de référence. Le rôle des recommandations du W3C est d'attirer l'attention sur la spécification et d'en promouvoir largement le déploiement. Cela dans le but d'améliorer le fonctionnement et l'interopérabilité du Web.

Ce document a été produit par le groupe de travail sur XML Schema au titre de l'activité XML du W3C. Les objectifs du langage XML Schema sont présentés dans le document de spécification de XML Schema. Les auteurs de ce document sont les membres du groupe de travail sur XML Schema. Les différents tomes ont chacun leurs propres éditeurs.

Cette version intègre les remarques correctives faites sur les versions antérieures.

Vous voudrez bien faire remonter les erreurs trouvées dans ce document à www-xml-schema-comments@w3.org (archive) (ou directement à la traduction française mentionnée en début de document) La liste des erreurs connues de la version anglaise de cette spécification est disponible à l'adresse http://www.w3.org/2001/05/xmlschema-errata.

La version anglaise de cette spécification est la seule version normative du présent document. Les informations concernant ses traductions sont disponibles à l'adresse http://www.w3.org/2001/05/xmlschema-translations.

Une liste complète des recommandations actuelles du W3C et d'autres documents techniques peuvent être trouvés à l'adresse http://www.w3.org/TR/.

Table des matières

1 Introduction
2 Concepts de base : un bon de commande
 2.1 Schéma d'un bon de commande
 2.2 Définitions de types complexes, les déclarations d'éléments et d'attributs
  2.2.1 Contraintes d'occurrence
  2.2.2 Eléments et attributs globaux
  2.2.3 Conflits de nommage
 2.3 Types simples
  2.3.1 Types de listes
  2.3.2 Types union
 2.4 Définition du type anonyme
 2.5 Contenu d'un élément
  2.5.1 Types complexes dérivés de types simples
  2.5.2 Contenu mixte
  2.5.3 Contenu vide
  2.5.4 Contenu libre
 2.6 Annotations
 2.7 Construction de modèles de contenu
 2.8 Groupes d'attributs
 2.9 Valeurs Nil
3 Concepts avancés I : espaces de noms, schémas et qualification
 3.1 Espaces de noms cibles et noms locaux non-qualifiés
 3.2 Noms locaux qualifiés
 3.3 Déclarations globales versus locales
 3.4 Espaces de noms cibles non-déclarés
4 Concepts avancés II : un bon de commande international
 4.1 Un schéma réparti entre plusieurs documents
 4.2 Dérivation de types par extension
 4.3 Utilisation de types dérivés dans des instances de documents
 4.4 Dérivation de types complexes par restriction
 4.5 Redéfinition de types et de groupes
 4.6 Groupes de substitution
 4.7 Eléments et types abstraits
 4.8 Contrôler la création et l'utilisation de types dérivés
5 Concepts avancés III : un rapport trimestriel
 5.1 Spécification d'unicité
 5.2 Définition des clés et de leurs références
 5.3 Contraintes de XML Schema versus les attributs ID de XML 1.0
 5.4 Importation de types
  5.4.1 Bibliothèques de types
 5.5 Eléments et attributs any
 5.6 attribut schemaLocation
 5.7 Conformité

Annexes

A Remerciements
B Types simples et leurs facettes
C Utilisation des entités
D Expressions régulières
E Index

1 Introduction

Ce document, XML Schema tome 0 : introduction, est une description simplifiée du langage de définition des schémas XML qui doit être utilisée parallèlement à la description formelle qui en est faite dans les tomes 1 (Structures) et 2 (Types de données). Les lecteurs supposés de ce document sont les développeurs d'applications amenés à écrire des programmes lisant ou écrivant des documents de type schéma ainsi que les auteurs de schémas qui ont besoin de connaître les fonctionnalités offertes par le langage, en particulier celles qui sont nouvelles par rapport à celles disponibles avec les DTD. Le texte suppose que vous ayez une connaissance de base de XML 1.0 et de XML-Namespaces. Chaque chapitre de cette introduction à XML Schema traite des nouvelles fonctionnalités du langage en s'appuyant sur des cas concrets.

Le chapitre 2 couvre les mécanismes de base de XML Schema. Il aborde les sujets suivants : la déclaration des éléments et des attributs destinés à être utilisés dans des documents XML, les différences entre les types simples et complexes, la manière de définir des types complexes, l'utilisation des types simples comme valeurs d'éléments et d'attributs, l'annotation des schémas, la présentation d'un mécanisme simple de réutilisation des définitions d'éléments et d'attributs et les valeurs nulles.

Le chapitre 3, le premier des chapitres avancés de cette introduction, concerne les concepts élémentaires régissant l'utilisation des espaces de noms dans les schémas XML et les documents. Ce chapitre est important pour comprendre la plupart des sujets qui sont abordés dans les chapitres avancés II et III.

Le chapitre 4, le deuxième des chapitres avancés de cette introduction, décrit les mécanismes de dérivation des types à partir des types fournis par XML Schema et de contrôle de ces dérivations. Le chapitre décrit aussi les mécanismes de fusion de fragments de schéma issus de plusieurs sources et de substitution d'éléments.

Le chapitre 5 couvre des mécanismes encore plus avancés, comprenant un mécanisme de spécification de l'unicité de certains attributs ou éléments, un mécanisme d'utilisation des types à travers plusieurs espaces de noms, un mécanisme d'extension des types basés sur les espaces de noms et une description du mécanisme de contrôle de la conformité des documents.

En plus des chapitres qui viennent d'être décrits, l'introduction contient un certain nombre d'annexes qui fournissent des informations de référence précises sur les types simples et le langage des expressions régulières.

L'introduction n'est pas un document normatif, ce qui signifie qu'elle n'est pas une spécification définitive du langage XML Schema (du point de vue du W3C). Les exemples et autres supports des explications fournies dans ce document sont fournis pour vous aider à comprendre XML Schema, mais peuvent ne pas fournir de réponse définitive à vos questions. Dans ce cas, vous aurez besoin de vous reporter à la spécification de XML Schema, et pour vous aider à le faire, nous fournissons de nombreux liens vers les parties concernées des tomes 1 et 2 de la spécification. Plus précisément, les items de XML Schema mentionnés dans cette introduction sont reliés à un index des noms d'éléments et d'attributs ainsi qu'à un tableau résumé des types de données, tous les deux étant physiquement dans cette introduction. Le tableau et l'index contiennent des liens aux parties concernées des parties 1 et 2 de la spécification XML Schema.

2 Concepts de base : un bon de commande

L'objet de ce schéma est de définir une classe de documents XML : le terme d'instance de document est souvent utilisé pour désigner un fichier contenant un document XML conforme à un schéma particulier. En fait, ni les instances ni les schémas n'ont besoin d'exister physiquement sous la forme de documents stockés dans des fichiers -- ils peuvent exister en tant que flots de données échangés entre deux applications, des champs d'une base de données ou comme des collections d'ensembles d'informations, des "granules d'informations" -- mais pour simplifier cette introduction, nous avons choisi de ne faire référence qu'à des instances et des schémas considérés sous la forme de documents et de fichiers.

Commençons par considérer une instance de document dans un fichier appelé po.xml. Elle contient la description d'un bon de commande émis par une personne privée et une application de facturation :

Le bon de commande, fichier po.xml
<?xml version="1.0"?>
<purchaseOrder orderDate="1999-10-20">
    <shipTo country="US">
        <name>Alice Smith</name>
        <street>123 Maple Street</street>
        <city>Mill Valley</city>
        <state>CA</state>
        <zip>90952</zip>
    </shipTo>
    <billTo country="US">
        <name>Robert Smith</name>
        <street>8 Oak Avenue</street>
        <city>Old Town</city>
        <state>PA</state>
        <zip>95819</zip>
    </billTo>
    <comment>Hurry, my lawn is going wild!</comment>
    <items>
        <item partNum="872-AA">
            <productName>Lawnmower</productName>
            <quantity>1</quantity>
            <USPrice>148.95</USPrice>
            <comment>Confirm this est electric</comment>
        </item>
        <item partNum="926-AA">
            <productName>Baby Monitor</productName>
            <quantity>1</quantity>
            <USPrice>39.98</USPrice>
            <shipDate>1999-05-21</shipDate>
        </item>
    </items>
</purchaseOrder>

Le bon de commande est constitué d'un élément principal, purchaseOrder, et des sous-éléments shipTo, billTo, comment et items. Ceux-là (à l'exception de l'élément comment) contiennent à leur tour d'autres sous-éléments, et ainsi de suite, jusqu'à ce qu'un sous-élément comme par exemple USPrice contienne un nombre plutôt qu'un sous-élément. On dit que les éléments qui contiennent des sous-éléments ou portent des attributs sont de type complexe, tandis que les éléments qui contiennent des nombres (ou des chaînes de caractères, des dates, etc.) sans autre sous-élément sont de type simple. Quelques éléments ont des attributs ; les attributs sont toujours de type simple.

Dans une instance de document, les types complexes et une partie des types simples qui y sont utilisés sont définis dans le schéma associé. Les autres types simples sont ceux qui sont prédéfinis par XML Schema.

Avant d'aller plus en avant dans l'analyse du schéma des bons de commande, nous allons digresser momentanément pour parler de l'association entre une instance et le schéma du bon de commande. Comme vous pouvez vous en apercevoir en regardant une instance de document, le schéma du bon de commande n'est pas mentionné. Il n'est pas pour l'instant obligatoire que les instances référencent les schémas et même si cela sera fait dans de nombreux cas, nous avons choisi de simplifier ce premier chapitre et de considérer que n'importe quel programme de traitement de l'instance saura accéder au schéma correspondant sans avoir besoin que l'information soit écrite en dur dans l'instance. Dans les chapitres suivants, nous introduirons les mécanismes explicites qui permettent d'associer une instance à un schéma.

2.1 Schéma d'un bon de commande

Le schéma d'un bon de commande est contenu dans le fichier po.xsd:

Le schéma d'un bon de commande, po.xsd
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">

 <xsd:annotation>
  <xsd:documentation xml:lang="en">
   Purchase order schema Par exemple.com.
   Copyright 2000 exemple.com. All rights reserved.
  </xsd:documentation>
 </xsd:annotation>

 <xsd:element name="purchaseOrder" type="PurchaseOrderType"/>

 <xsd:element name="comment" type="xsd:string"/>

 <xsd:complexType name="PurchaseOrderType">
  <xsd:sequence>
   <xsd:element name="shipTo" type="USAddress"/>
   <xsd:element name="billTo" type="USAddress"/>
   <xsd:element ref="comment" minOccurs="0"/>
   <xsd:element name="items"  type="Items"/>
  </xsd:sequence>
  <xsd:attribute name="orderDate" type="xsd:date"/>
 </xsd:complexType>

 <xsd:complexType name="USAddress">
  <xsd:sequence>
   <xsd:element name="name"   type="xsd:string"/>
   <xsd:element name="street" type="xsd:string"/>
   <xsd:element name="city"   type="xsd:string"/>
   <xsd:element name="state"  type="xsd:string"/>
   <xsd:element name="zip"    type="xsd:decimal"/>
  </xsd:sequence>
  <xsd:attribute name="country" type="xsd:NMTOKEN"
     fixed="US"/>
 </xsd:complexType>

 <xsd:complexType name="Items">
  <xsd:sequence>
   <xsd:element name="item" minOccurs="0" maxOccurs="unbounded">
    <xsd:complexType>
     <xsd:sequence>
      <xsd:element name="productName" type="xsd:string"/>
      <xsd:element name="quantity">
       <xsd:simpleType>
        <xsd:restriction base="xsd:positiveInteger">
         <xsd:maxExclusive value="100"/>
        </xsd:restriction>
       </xsd:simpleType>
      </xsd:element>
      <xsd:element name="USPrice"  type="xsd:decimal"/>
      <xsd:element ref="comment"   minOccurs="0"/>
      <xsd:element name="shipDate" type="xsd:date" minOccurs="0"/>
     </xsd:sequence>
     <xsd:attribute name="partNum" type="SKU" use="required"/>
    </xsd:complexType>
   </xsd:element>
  </xsd:sequence>
 </xsd:complexType>

 <!-- Stock Keeping Unit, one code for identifying products -->
 <xsd:simpleType name="SKU">
  <xsd:restriction base="xsd:string">
   <xsd:pattern value="\d{3}-[A-Z]{2}"/>
  </xsd:restriction>
 </xsd:simpleType>

</xsd:schema>

Le schéma des bons de commande est constitué d'un élément schema et d'une variété de sous-éléments, les principaux étant element, complexType, et simpleType qui déterminent l'ordre d'apparition des éléments dans l'instance et leurs types de contenu.

Chacun des éléments du schéma est préfixé par xsd: associé à l'espace de noms du schéma XML utilisé par le biais de la déclaration xmlns:xsd="http://www.w3.org/2001/XMLSchema" qui est un attribut de l'élément schema. Le préfixe xsd: est couramment utilisé pour identifier l'espace de noms des schémas XML alors que n'importe quelle valeur de préfixe pourrait, en réalité, être utilisée. Le même préfixe et par conséquence la même association, apparaît également sur les noms des types simples préconstruits, par exemple xsd:string. Dans ce cas, le but de cette association est d'affirmer que les éléments et les types simples ainsi préfixés appartiennent au vocabulaire du langage XML Schema et non au vocabulaire particulier de l'auteur du schéma. Pour la lisibilité du texte, nous ne faisons que mentionner les noms des éléments et des types simples (par exemple simpleType) en omettant leur préfixe.

2.2 Définitions de types complexes, les déclarations d'éléments et d'attributs

Dans XML Schema, il y un une différence de base entre les éléments de type complexe qui peuvent contenir des sous-éléments et être qualifiés par des attributs et ceux de type simple qui ne peuvent contenir ni sous-éléments ni être qualifiés par des attributs. Il y un également une distinction majeure entre les définitions qui servent à créer de nouveaux types (qu'ils soient de type simple ou complexe) et les déclarations qui servent à spécifier les noms et les types des éléments et attributs qui pourront être utilisés dans les instances de documents. Dans ce chapitre, nous nous concentrons sur les définitions de types complexes et les déclarations d'éléments et d'attributs qu'elles contiennent.

Les nouveaux types complexes sont créés en utilisant l'élément complexType composé, dans la plupart des cas, d'une série de déclarations d'éléments et d'attributs et de références d'éléments. Les déclarations ne sont pas elles mêmes des types mais plutôt des associations faites entre un nom et des contraintes qui régissent les règles d'apparition de l'élément dans une instance de document correspondant au schéma. Les éléments sont déclarés en utilisant l'élément element et les attributs sont déclarés en utilisant l'élément attribute. Par exemple, l'élément USAddress est défini comme étant de type complexe et, à l'intérieur de sa définition, nous remarquons la présence de cinq déclarations d'éléments et d'une déclaration d'attribut :

Définition du type USAddress
 <xsd:complexType name="USAddress" >
  <xsd:sequence>
   <xsd:element name="name"   type="xsd:string"/>
   <xsd:element name="street" type="xsd:string"/>
   <xsd:element name="city"   type="xsd:string"/>
   <xsd:element name="state"  type="xsd:string"/>
   <xsd:element name="zip"    type="xsd:decimal"/>
  </xsd:sequence>
  <xsd:attribute name="country" type="xsd:NMTOKEN" fixed="US"/>
 </xsd:complexType>

La conséquence de cette définition est que toute instance de cet élément dans l'instance (par exemple shipTo du fichier po.xml) doit être constituée de cinq éléments et d'un attribut. Ces éléments doivent être appelés name, street, city, state et zip conformément à ce qui est spécifié par les différentes valeurs de l'attribut name des déclarations de l'exemple ci-dessus. Ces cinq éléments doivent apparaître dans le même ordre que celui dans lequel ils sont déclarés dans le schéma. Les quatre premiers contiendront chacun une chaîne de caractères tandis que le cinquième contiendra un nombre. Les éléments qui auront USAddress comme type déclaré pourront recevoir un attribut appelé country qui devra alors avoir comme seul et unique contenu la chaîne de caractère US.

La définition de USAddress ne contient que des déclarations impliquant des types simples : string, decimal et NMTOKEN. Par opposition, la définition de PurchaseOrderType contient des déclarations d'éléments impliquant des types complexes, par exemple USAddress. Remarquez toutefois que dans les deux cas, c'est le même attribut type qui est utilisé pour identifier le type, que ce dernier soit simple ou complexe.

Définition du type PurchaseOrderType
 <xsd:complexType name="PurchaseOrderType">
  <xsd:sequence>
   <xsd:element name="shipTo" type="USAddress"/>
   <xsd:element name="billTo" type="USAddress"/>
   <xsd:element ref="comment" minOccurs="0"/>
   <xsd:element name="items"  type="Items"/>
  </xsd:sequence>
  <xsd:attribute name="orderDate" type="xsd:date"/>
 </xsd:complexType>

Dans la définition de PurchaseOrderType, les déclarations des deux éléments shipTo et billTo s'appuient sur le même type complexe USAddress. La conséquence de cette définition est que tout élément d'une instance de document (telle que po.xml) dont le type déclaré est PurchaseOrderType doit contenir les éléments shipTo et billTo,chacun contenant à leur tour les cinq sous-éléments (name, street, city, state et zip) déclarés dans la définition de USAddress. Les éléments shipTo et billTo peuvent également recevoir l'attribut country qui fait partie de la définition de USAddress.

La définition de PurchaseOrderType contient la déclaration de l'attribut orderDate qui, comme ce fut le cas pour l'attribut country, utilise un type simple. En fait, toutes les déclarations d'attributs ne peuvent que référencer des types simples car, contrairement aux éléments, les attributs ne peuvent pas contenir eux-mêmes d'autres attributs ou éléments.

Les déclarations d'éléments dont nous avons parlé jusque ici sont toutes composées d'une association entre un nom et une définition de type existante. Quelquefois il est préférable d'utiliser un élément existant plutôt que d'en déclarer un nouveau, par exemple:

<xsd:element ref="comment" minOccurs="0"/>

Cette déclaration utilise un élément déjà défini par ailleurs dans le schéma des bons de commande dont le nom est comment. En général, la valeur de l'attribut ref doit être celle d'un élément global, c'est à dire un élément déclaré directement à l'intérieur de schema et non à l'intérieur d'une définition de type complexe. La conséquence est qu'un élément appelé comment peut être présent dans une instance de document et que son contenu doit être conforme à ce type d'élément, à savoir string.

2.2.1 Contraintes d'occurrence

Dans PurchaseOrderType, l'élément comment est défini comme étant optionnel par le biais de la valeur 0 de l'attribut minOccurs. En général, un élément est requis quand la valeur de minOccurs vaut 1 ou plus. Le nombre maximum de fois qu'un élément peut apparaître est déterminé dans sa déclaration par la valeur de l'attribut maxOccurs. Cette valeur peut être un entier positif comme par exemple 41, ou encore le mot unbounded qui signifie qu'il n'y a pas de valeur limite. La valeur par défaut dans les deux cas (minOccurs et maxOccurs) est 1. Par conséquent, quand l'élément comment est déclaré sans que l'attribut maxOccurs soit précisé, cela signifie qu'il ne peut pas apparaître plus d'une fois. Soyez certains que lorsque vous ne précisez que la valeur de l'attribut minOccurs, celle-là soit inférieur ou au plus égale à la valeur par défaut de maxOccurs, c'est à dire 0 ou 1. A contrario, si vous ne faites que spécifier une valeur pour le seul attribut maxOccurs, vous devez être certain que cette valeur soit supérieure ou au moins égale à la valeur par défaut de minOccurs, c'est à dire 1 ou plus. Si les deux attributs sont omis, l'élément doit apparaître exactement une seule fois.

Les attributs peuvent apparaître au maximum une fois et donc la syntaxe pour spécifier le nombre d'occurrences autorisées d'un attribut est différente de celle utilisée pour les éléments. En particulier, les attributs peuvent être déclarés avec l'attribut de spécification use qui permet d'en préciser la contrainte d'apparition, les valeurs possibles sont required (regardez par exemple la déclaration de l'attribut partNum dans po.xsd), optional, ou même prohibited.

Les valeurs par défaut des attributs comme des éléments sont déclarées en utilisant l'attribut default, bien que cette attribut ait des conséquences sensiblement différentes dans chaque cas de figure. Quand une valeur est déclarée par défaut pour un attribut en particulier, alors cela signifie que la valeur de l'attribut sera librement précisée dans l'instance ou, si aucune valeur n'est clairement précisée dans l'instance, alors le programme de traitement doit considérer que sa valeur est celle déclarée par défaut dans le schéma. Notez que les valeurs par défaut des attributs n'ont de sens que si les attributs eux-mêmes sont optionnels, c'est donc une erreur que de spécifier simultanément une valeur par défaut et une contrainte d'apparition autre que optional dans use.

Le programme de traitement du schéma traite les contenus d'éléments par défaut de manière sensiblement différente que pour les attributs. Quand un élément est déclaré comme ayant un contenu par défaut, le contenu de l'élément dans une instance de document sera celui qui s'y trouve mais si le contenu de l'élément dans l'instance n'est pas précisé, alors le programme de traitement du schéma devra considérer que le contenu par défaut s'applique, il sera alors constitué de l'élément dont le nom est égal à la valeur de l'attribut default. Toutefois, si l'élément n'apparaît pas du tout dans une instance de document, alors le programme de traitement du schéma ne doit pas chercher à intégrer son contenu par défaut. En résumé, les différences entre les valeurs par défaut des attributs et des éléments peuvent être ramenées à : les valeurs par défaut des attributs s'appliquent quand l'attribut est omis alors que les valeurs par défaut des éléments s'appliquent quand l'élément est vide.

L'attribut fixed est utilisé à la fois dans les déclarations d'éléments et les déclarations d'attributs pour s'assurer que que leurs valeurs soient mises à une valeur prédéfinie. Par exemple, po.xsd contient la déclaration de l'attribut country, déclaré avec une valeur de type fixed égale à US. Cette déclaration signifie que l'utilisation de l'attribut country dans une instance de document est optionnelle (la valeur par défaut de use est optional), mais, si cet attribut apparaît, alors sa valeur doit être US et, si l'attribut n'apparaît pas, alors le processeur devra considérer que l'attribut country est présent par défaut et que sa valeur est US. Remarquez que les concepts de valeur fixe et de valeur par défaut s'excluent mutuellement, c'est donc une erreur que d'utiliser les valeurs fixed et default dans la même déclaration d'attribut.

Les valeurs des attributs utilisées dans les déclarations d'éléments et d'attributs pour contraindre leurs règles d'utilisation dans les instances sont résumées dans le Tableau 1.

Tableau 1. Contraintes d'occurrence des éléments et des attributs
Eléments
(minOccurs, maxOccurs) fixed, default 
Attributs
use, fixed, default
Remarques
(1, 1) -, - required, -, - l'élément ou l'attribut doit apparaître une seule fois, il peut prendre n'importe quelle valeur
(1, 1) 37, - required, 37, - l'élément ou l'attribut doit apparaître une seule fois, sa valeur doit être 37
(2, unbounded) 37, - non applicable l'élément doit apparaître deux fois ou plus, sa valeur doit être 37; en général, les valeurs de minOccurs et maxOccurs sont des entiers positifs, mais maxOccurs peut également prendre la valeur "unbounded"
(0, 1) -, - optional, -, - l'élément ou l'attribut peut apparaître 0 ou une fois et peut prendre n'importe quelle valeur
(0, 1) 37, - optional, 37, - l'élément ou l'attribut peut apparaître 0 ou une fois; quand il apparaît, sa valeur doit être égale à 37; si l'attribut est omis, sa valeur est fixée à 37. Si l'élément est omis, le processeur ne lui impose pas une valeur particulière.
(0, 1) -, 37 optional, -, 37 l'élément ou l'attribut peut apparaître 0 ou une fois; quand il apparaît, sa valeur est libre; si l'attribut est omis, sa valeur par défaut est 37. Si l'élément est omis, sa valeur n'est pas imposée ; si l'élément est vide, sa valeur est alors 37.
(0, 2) -, 37 non applicable l'élément ou l'attribut peut apparaître 0, une ou deux fois; il n'y un pas de possibilité équivalente pour les attributs. la valeur du contenu de l'élément n'est pas fixée mais si l'élément est vide la valeur considérée par le processeur sera, par défaut, 37;
(0, 0) -, - prohibited, -, - l'élément ou l'attribut ne doit pas apparaître
Notez que ni minOccurs, maxOccurs, ni use ne peuvent apparaître dans les déclarations globales d'éléments ou d'attributs.

2.2.2 Les attributs et éléments globaux

Les éléments et les attributs globaux sont créés par des déclarations qui apparaissent directement à l'intérieur de l'élément schema. Une fois déclaré, un élément ou un attribut global peut être référencé dans une ou plusieurs déclarations en utilisant l'attribut ref, comme cela a déjà été vu plus haut. Une déclaration qui référence un élément global permet à l'élément référencé d'être utilisé dans une instance de document dans le contexte de la déclaration qui le référence. Aussi, par exemple, l'élément comment apparaît dans po.xml au même niveau que les éléments shipTo, billTo et items parce que la déclaration qui référence comment se trouve dans une définition de type complexe au même niveau que que les déclarations des trois autres éléments.

La déclaration d'un élément global permet aussi à l'élément d'être utilisé au plus haut niveau d'une instance de document, c'est à dire comme élément racine. Ainsi purchaseOrder, qui est déclaré comme élément global dans po.xsd, peut apparaître comme élément racine de po.xml. Remarquez que ce même raisonnement permettrait également à l'élément comment d'être utilisé à la racine de po.xml.

Il y a un certain nombre de pièges concernant l'utilisation des éléments et des attributs globaux. L'un d'eux est que les déclarations globales ne peuvent pas contenir de référence ; les déclarations globales doivent identifier des types simples ou complexes directement. Pour parler concrètement, les déclarations globales ne peuvent pas utiliser l'attribut ref, elles doivent uniquement utiliser l'attribut type (ou, comme nous le décrivons brièvement, être suivies d'une définition de type anonymous). Un deuxième piège est que les contraintes de cardinalité ne peuvent pas être posées sur des déclarations globales alors qu'elles peuvent être utilisées sur des déclarations locales référençant des déclarations globales. En d'autres termes, les déclarations globales ne peuvent pas faire appel aux attributs minOccurs, maxOccurs, ou use.

2.2.3 Conflits de nommage

Nous avons maintenant décrit la manière de définir de nouveaux types complexes (par exemple PurchaseOrderType), déclarer des éléments (par exemple purchaseOrder) et des attributs (par exemple orderDate). Ces actions, en général, impliquent de choisir des noms, et la question vient ainsi naturellement à être posée : qu'arrive-t-il si deux objets portent le même nom ? La réponse dépend de la nature des deux objets en question, en règle général évidemment, plus les deux objets seront similaires et plus leurs noms seront conflictuels.

Voici quelques exemples pour illustrer les cas où les noms posent problème. Si les deux objets sont du même type, par exemple, supposons qu'on ait défini un type complexe baptisé USStates et un type simple du même nom, il y a de facto un conflit. Si les deux objets sont de nature différente, par exemple un élément et un type, disons par exemple qu'on ait défini un type complexe appelé USAddress et un élément du même nom, il n'y aura pas de conflit. Si les deux objets sont déclarés à l'intérieur de types différents (c'est à dire qu'il ne s'agit pas d'éléments globaux), par exemple un élément appelé name à l'intérieur du type USAddress et un autre de même nom à l'intérieur du type Item, il n'y a pas de conflit de nom (ces déclarations sont parfois appelées déclarations d'éléments locaux). Finalement, si les deux objets sont des types dont l'un est défini par vous même et l'autre provienne de XML Schema, par exemple un type simple appelé decimal défini par vous même, il n'y a pas de conflit. La raison de l'apparente contradiction du dernier exemple est que les deux types appartiennent à des espaces de noms différents. Nous explorerons l'utilisation des espaces de noms dans les schémas dans l'un des chapitres qui suivent.

2.3 Types simples

Le schéma de notre bon de commande fait appel à plusieurs éléments et attributs de types simples. Quelques uns de ces types simples, tels que string et decimal, sont prédéfinis dans XML Schema tandis que d'autres sont dérivés de ces types pré-éxistants. Par exemple, l'attribut partNum a un type appelé SKU (comme "Stock Keeping Unit") dérivé de string. Les types simples prédéfinis, tout comme leurs dérivées, peuvent être utilisés dans toute déclaration d'éléments ou d'attributs. Le Tableau 2 liste tous les types simples prédéfinis de XML Schema, en association avec des exemples d'utilisation des différents types.

Tableau 2. Types simples prédéfinis de XML Schema
Type simple exemples (délimités par des virgules) Remarques
string Confirmez que ceci est électrique  
normalizedString Confirmez que ceci est électrique cf (3)
token Confirmez que ceci est électrique cf (4)
byte -1, 126 cf (2)
unsignedByte 0, 126 cf (2) 
base64Binary GpM7  
hexBinary 0FB7  
integer -126789, -1, 0, 1, 126789 cf (2)
positiveInteger 1, 126789 cf (2)
negativeInteger -126789, -1 cf (2)
nonNegativeInteger 0, 1, 126789 cf (2)
nonPositiveInteger -126789, -1, 0 cf (2)
int -1, 126789675 cf (2)
unsignedInt 0, 1267896754 cf (2)
long -1, 12678967543233 cf (2)
unsignedLong 0, 12678967543233 cf (2)
short -1, 12678 cf (2)
unsignedShort 0, 12678 cf (2)
decimal -1.23, 0, 123.4, 1000.00 cf (2)
float -INF, -1E4, -0, 0, 12.78E-2, 12, INF, NaN équivalent aux nombres flottants simple-précision sur 32-bit, NaN signifie "not un nombre", cf (2)
double -INF, -1E4, -0, 0, 12.78E-2, 12, INF, NaN équivalent aux nombres flottants double-précision sur 64-bit, cf (2)
boolean true, false
1, 0
 
time 13:20:00.000, 13:20:00.000-05:00 cf (2)
dateTime 1999-05-31T13:20:00.000-05:00 31 mai 1999 à 13h20 heure standard de l'Est qui a 5 heures de décalage avec le temps universel, cf (2)
duration P1Y2M3DT10H30M12.3S 1 an, 2 mois, 3 jours, 10 heures, 30 minutes, et 12.3 secondes
date 1999-05-31 cf (2)
gMonth --05-- Mai, cf (2) (5)
gYear 1999 1999, cf (2) (5)
gYearMonth 1999-02 le mois de février 1999, indépendamment du nombre de jours, cf (2) (5)
gDay ---31 le 31ième jour, cf (2) (5)
gMonthDay --05-31 chaque 31 mai, cf (2) (5)
Name shipTo Type nom de XML 1.0
QName po:USAddress Nom XML qualifié par un espace de nom
NCName USAddress Nom XML non qualifié ni par un espace de nom ni par le deux points.
anyURI http://www.example.com/, http://www.example.com/doc.html#ID5  
language en-GB, en-US, fr valeurs valides de xml:lang telles que définies dans XML 1.0
ID   attribut de type ID tel que défini par XML 1.0, cf (1)
IDREF   attribut de type IDREF tel que défini par XML 1.0, cf (1)
IDREFS   attribut de type IDREFS tel que défini par XML 1.0, cf (1)
ENTITY   attribut de type ENTITY tel que défini par XML 1.0, cf (1)
ENTITIES   attribut de type ENTITIES tel que défini par XML 1.0, cf (1)
NOTATION   attribut de type NOTATION tel que défini par XML 1.0, cf (1)
NMTOKEN US,
Brésil
attribut de type NMTOKEN tel que défini par XML 1.0, cf (1)
NMTOKENS US UK,
Brésil Canada Mexique
attribut de type NMTOKENS tel que défini par XML 1.0, il s'agit d'une suite de NMTOKEN séparés les uns des autres par un espace blanc, cf (1)
Remarques: (1) Pour conserver la compatibilité entre XML Schema et les DTD de la version 1.0 de XML, les types simples ID, IDREF, IDREFS, ENTITY, ENTITIES, NOTATION, NMTOKEN, NMTOKENS ne doivent être utilisés que pour des attributs. (2) Une valeur de ce type peut être représentée par plus d'une forme lexicale, par exemple 100 et 1.0E2 sont deux formats valides de représentation flottante du nombre cent. Toutefois, des règles ont été établies pour ce type qui défini une forme lexicale canonique, cf XML Schema Part 2. (3) Les caractères retour chariot, tabulation et changement de ligne du type normalizedString sont convertis en caractères de type espace avant le traitement du schéma. (4) Comme pour normalizedString, les séquences de caractères adjacents de type espace sont ramenés à un seul caractère espace, et les blancs de tête et de queue sont retirés. (5) Le préfixe "g" signale une référence temporelle au calendrier Grégorien.

Les nouveaux types simples sont définis par dérivation des types simples déjà existants (ceux qui sont prédéfinis comme ceux qui sont dérivés). En particulier, on peut dériver un nouveau type simple en réduisant un type simple existant, en d'autres termes, la fourchette des valeurs autorisées du nouveau type est un sous-ensemble du type original. Nous utilisons l'élément de type simpleType pour définir et nommer le nouveau type simple. Nous utilisons l'élément restriction pour indiquer quel est le type original (appelé type de base) et pour identifier les "facettes" qui restreignent la fourchette de valeurs. Une liste complète des facettes est fournie en Annexe B.

Supposez que nous souhaitions créer un nouveau type d'entier appelé myInteger dont la fourchette des valeurs autorisées est comprise entre 10000 et 99999 (inclus). Nous basons notre définition sur le type simple prédéfini integer, dont la fourchette de valeurs autorisées comprend, bien sûr, des valeurs inférieures à 10000 et supérieures à 99999. Pour définir myInteger, on restreint la fourchette des valeurs du type de base integer en appliquant deux facettes appelées minInclusive et maxInclusive :

Définition de myInteger dont les valeurs autorisées sont comprises entre 10000 et 99999
<xsd:simpleType name="myInteger">
  <xsd:restriction base="xsd:integer">
    <xsd:minInclusive value="10000"/>
    <xsd:maxInclusive value="99999"/>
  </xsd:restriction>
</xsd:simpleType>

L'exemple montre une combinaison particulière de l'utilisation d'un type de base et de deux facettes pour définir myInteger, mais un simple regard à la liste des types simples prédéfinis et de leurs facettes associées de l'annexe B montre d'autres possibilités de combinaisons pour un résultat identique.

Le schéma des bons de commande contient un autre exemple, plus sophistiqué, de définition de type simple. Un nouveau type simple appelé SKU est dérivé (par restriction) du type simple string. De plus, nous contraignons les valeurs de SKU en utilisant une facette appelée pattern combinée à l'application de l'expression régulière "\d{3}-[A-Z]{2}" ce qui se lit "trois chiffres suivis d'un trait d'union suivi de deux lettres majuscules comprises entre A et Z":

Définition du type simple SKU
<xsd:simpleType name="SKU">
  <xsd:restriction base="xsd:string">
    <xsd:pattern value="\d{3}-[A-Z]{2}"/>
  </xsd:restriction>
</xsd:simpleType>

Le langage des expressions régulières est décrit plus complètement en Annexe D.

XML Schema définit quinze facettes qui sont listées en Annexe B. Parmis celles-là, la facette enumeration est particulièrement utile et permet d'exprimer des contraintes pour pratiquement tous les types simples, à l'exception du type boolean. La facette enumeration limite un type simple à un ensemble de valeurs distinctes. Par exemple, nous pouvons utiliser la facette enumeration pour définir un nouveau type simple appelé USState, dérivé de string, dont la valeur telle que définie doit être l'une des abréviations officielles des états américains :

Utilisation de la facette enumeration :
<xsd:simpleType name="USState">
  <xsd:restriction base="xsd:string">
    <xsd:enumeration value="AK"/>
    <xsd:enumeration value="AL"/>
    <xsd:enumeration value="AR"/>
    <!-- et so on ... -->
  </xsd:restriction>
</xsd:simpleType>

USState est un bon candidat pour le remplacement du type string utilisé dans la déclaration de l'élément state. En faisant cette substitution, les valeurs légales de l'élément state, plus précisément les sous-éléments state de billTo et shipTo, seront limitées à l'une des valeurs AK, AL, AR, etc. Remarquez que les valeurs de l'énumération, spécifiées pour un certain type en particulier, doivent être uniques.

2.3.1 Types de listes

XML Schema offre les notions de typage de listes, en plus des si bien nommés types atomiques qui sont à la base de la plupart des cas de typage présentés dans le tableau 2. (les types atomique, liste et union décrits dans le chapitre suivant sont collectivement appelés des types simples). La valeur d'un type atomique est indivisible du point de vue de XML Schema. Par exemple, la valeur NMTOKEN US est indivisible dans ce sens qu'aucune partie de US, comme par exemple le caractère "S", n'a de sens intrinsèque propre. Par opposition, les types liste sont des séries de types atomique ce qui fait que chaque élément d'une telle séquence (les "atomes") est lui-même significatif du point de vue de son typage. Par exemple, NMTOKENS est un type liste constitué d'une série d'éléments de type NMTOKEN délimités par un espace blanc faisant office de séparateur, comme par exemple la suite "US UK FR". XML Schema a trois types de listes prédéfinis, il s'agit des types NMTOKENS, IDREFS et ENTITIES.

Pour compléter l'utilisation des types prédéfinis de listes, il est possible de créer de nouveaux types de listes par dérivation des types atomiques existant. (Vous ne pouvez créer de nouveaux types de listes ni à partir des types listes existant, ni à partir des types complexes).

Exemple, création d'une liste de myInteger
<xsd:simpleType name="listOfMyIntType">
  <xsd:list itemType="myInteger"/>
</xsd:simpleType>

Ce qui pourra donner lieu dans une instance de document à l'exemple suivant :

<listOfMyInt>20003 15037 95977 95945</listOfMyInt>

Plusieurs facettes peuvent être appliquées au type liste : length, minLength, maxLength, et enumeration. Par exemple, pour définir une liste d'exactement six états US (SixUSStates), nous commençons par définir un nouveau type liste appelé USStateList à partir du type USState que nous dérivons ensuite en SixUSStates par restriction de USStateList à seulement six items :

Exemple de définition d'un type liste composé de six états américains
<xsd:simpleType name="USStateList">
 <xsd:list itemType="USState"/>
</xsd:simpleType>

<xsd:simpleType name="SixUSStates">
 <xsd:restriction base="USStateList">
  <xsd:length value="6"/>
 </xsd:restriction>
</xsd:simpleType>

Les éléments dont le type est SixUSStates doivent avoir six items et chacun d'eux doit prendre l'une des valeurs atomiques du type énuméré USState, par exemple :

<sixStates>PA NY CA NY LA AK</sixStates>

Remarquez qu'il est possible de dériver un type liste à partir du type atomique string. Toutefois, un type string peut contenir des espaces blancs alors que ces mêmes espaces blancs servent à délimiter les items d'une liste, donc vous devez être prudents dans l'utilisation des types liste quand le type de base est string. Par exemple, supposons que nous ayons défini un type liste avec une facette length égale à 3 et un type de base string. La liste de trois items présentée ci-après est alors valide :

Asie Europe Afrique

Tandis que la liste de trois items présentée ci-après est illégale :

Asie Europe Amérique Latine

Même le terme "Amérique Latine" est légitime en tant que chaîne de caractères à l'extérieur de la liste, il provoque la création d'un quatrième item quand il est inclu dans la liste, l'espace blanc qu'il contient étant considéré comme séparateur. Cela rend le contenu de l'élément invalide par rapport à la contrainte définie dans son modèle (trois items maximum).

2.3.2 Types union

Les types atomique et liste permettent à un élément ou une valeur d'attribut d'être composés de une ou plusieurs instances d'un type atomique. Par contraste, un type union permet à un élément ou valeur d'attribut d'être composés d'une ou plusieurs instances d'un type résultant de l'union de plusieurs types atomique ou liste. Pour donner un exemple, nous allons créer un type union pour représenter les états américains par des bigrammes ou des listes de valeurs numériques. Le type union appelé dans notre exemple zipUnion est construit à partir d'un type atomique et d'un type liste :

Type union pour les Zipcodes
<xsd:simpleType name="zipUnion">
  <xsd:union memberTypes="USState listOfMyIntType"/>
</xsd:simpleType>

Quand nous définissons un type union, la valeur de l'attribut memberTypes est une liste de tous les types constituant l'union.

Maintenant, imaginez que nous ayons déclaré un élément appelé zips de type zipUnion, des instances valides de cet élément pourraient être :

<zips>CA</zips>
<zips>95630 95977 95945</zips>
<zips>AK</zips>

Deux facettes, pattern et enumeration, peuvent être appliquées à un type union.

2.4 Définitions du type anonyme

Les schémas peuvent être construits en définissant d'abord des ensembles de types nommés comme par exemple PurchaseOrderType puis en déclarant des éléments tels que purchaseOrder qui référencent les types en utilisant le constructeur type. Cette forme de construction de schéma est directe mais peut être non maniable, spécialement si vous définissez de nombreux types référencés seulement une fois et contenant très peu de contraintes. Dans ce cas, un type peut être plus efficacement défini sous la forme d'un type anonyme qui économise le travail de nommage explicite du type et de son référencement.

La définition du type Items dans po.xsd contient deux déclarations d'éléments qui utilisent des types anonymes (item et quantité). En général, vous pouvez identifier les types anonymes en notant l'absence de l'attribut type dans les déclarations d'éléments ou d'attributs, et par la présence d'une définition de type (simple ou complexe) sans nommage particulier :

Deux définitions de types anonymes
<xsd:complexType name="Items">
 <xsd:sequence>
  <xsd:element name="item" minOccurs="0" maxOccurs="unbounded">
   <xsd:complexType>
    <xsd:sequence>
     <xsd:element name="productName" type="xsd:string"/>
     <xsd:element name="quantity">
      <xsd:simpleType>
       <xsd:restriction base="xsd:positiveInteger">
        <xsd:maxExclusive value="100"/>
       </xsd:restriction>
      </xsd:simpleType>
     </xsd:element>
     <xsd:element name="USPrice"  type="xsd:decimal"/>
     <xsd:element ref="comment"   minOccurs="0"/>
     <xsd:element name="shipDate" type="xsd:date" minOccurs="0"/>
    </xsd:sequence>
    <xsd:attribute name="partNum" type="SKU" use="required"/>
   </xsd:complexType>
  </xsd:element>
 </xsd:sequence>
</xsd:complexType>

L'élément item a un type anonyme complexe constitué des éléments productName, quantité, USPrice, comment et shipDate et d'un attribut appelé partNum. L'élément quantity a un type anonyme simple dérivé du type integer dont la fourchette de valeurs est comprise entre 1 et 99.

2.5 Contenu d'un élément

Le schéma du bon de commande montre plusieurs cas de contenus : des éléments sans attribut dont le contenu est constitué de sous-éléments (par exemple items), des éléments avec attributs et un contenu formé de sous-éléments (par exemple shipTo) et enfin des éléments contenant seulement un type simple de valeurs (par exemple USPrice). Toutefois, nous n'avons vu ni élément ayant des attributs mais ne contenant qu'un type simple de valeurs, ni élément ayant un contenu mixte (c'est à dire pouvant contenir à la fois des caractères de données mélangés à des sous-éléments), ni élément vide (n'ayant aucun contenu du tout). Dans ce chapitre, nous allons examiner ces cas particuliers de modèles de contenu.

2.5.1 Types complexes dérivés de types simples

Tout d'abord, considérons la manière de déclarer un élément ayant un attribut et contenant une valeur simple. Dans une instance, un tel élément pourrait être écrit par exemple :

<internationalPrice currency="EUR">423.46</internationalPrice>

Pour la suite de notre explication, nous allons utiliser le cas de l'élément USPrice, déclaré comme suit dans le schéma du bon de commande :

<xsd:element name="USPrice" type="decimal"/>

Comment ajouter un attribut à cet élément ? Il est de type simple decimal et, comme nous l'avons dit plus haut, ces types ne peuvent avoir d'attribut. A partir de là, nous devons définir un type complexe pour incorporer la déclaration de l'attribut. Nous voulons aussi que le contenu de l'attribut soit de type decimal. Donc, notre question originale devient : Comment définit-on un type complexe basé sur le type simple decimal? La réponse est obtenue en dérivant un nouveau type complexe à partir du type simple decimal comme ceci :

 <xsd:element name="internationalPrice">
  <xsd:complexType>
   <xsd:simpleContent>
    <xsd:extension base="xsd:decimal">
     <xsd:attribute name="currency" type="xsd:string"/>
    </xsd:extension>
   </xsd:simpleContent>
  </xsd:complexType>
 </xsd:element>

Nous utilisons l'élément complexType pour commencer la définition du nouveau type (en l'occurrence, il s'agit d'un type anonyme). Pour indiquer que le modèle de contenu du nouveau type ne contient que des caractères de données et aucun élément, on utilise l'élément facette simpleContent. Finalement, nous dérivons le nouveau type en étendant le type simple decimal. L'extension consiste à rajouter un attribut currency en utilisant une déclaration d'attribut standard (les dérivations de types sont détaillées au chapitre 4). L'élément internationalPrice déclaré de la sorte apparaîtra dans l'instance tel que montré au début de ce chapitre.

2.5.2 Contenu mixte

La construction du schéma des bons de commande peut être caractérisée comme étant basée sur des éléments imbriqués, les plus profonds d'entre eux (les feuilles) ne contenant que des données textuelles. XML Schema fournit aussi la possibilité de construire des schémas dans lesquels les caractères de données peuvent apparaître au même niveau que des sous-éléments, n'étant pas ainsi confinés au niveau des feuilles de l'arborescence : nous parlons alors de contenu mixte.

Pour illustrer ce propos, on considère l'extrait suivant, provenant d'une lettre d'un client dans laquelle il utilise quelques éléments issus du bon de commande :

<letterBody>
<salutation>Dear Mr.<name>Robert Smith</name>.</salutation>
Your order of <quantity>1</quantity> <productName>Baby
Monitor</productName> shipped from our warehouse on
<shipDate>1999-05-21</shipDate>. ....
</letterBody>

Remarquez que dans l'élément salutation, du texte est mélangé à des éléments enfants. Plus précisément, du texte apparaît entre les éléments salutation, quantity, productName et shipDate qui sont tous des enfants de l'élément letterBody. L'extrait suivant est la partie du schéma où est déclaré letterBody:

<xsd:element name="letterBody">
 <xsd:complexType mixed="true">
  <xsd:sequence>
   <xsd:element name="salutation">
    <xsd:complexType mixed="true">
     <xsd:sequence>
      <xsd:element name="name" type="xsd:string"/>
     </xsd:sequence>
    </xsd:complexType>
   </xsd:element>
   <xsd:element name="quantity"    type="xsd:positiveInteger"/>
   <xsd:element name="productName" type="xsd:string"/>
   <xsd:element name="shipDate"    type="xsd:date" minOccurs="0"/>
   <!-- etc. -->
  </xsd:sequence>
 </xsd:complexType>
</xsd:element>

Les éléments qui apparaissent dans la lettre du client sont déclarés et leurs types sont définis par des montages faits à partir des éléments element et complexType, comme nous l'avons déjà vu. Pour autoriser que des caractères de données puissent être mélangés aux éléments enfants de letterBody, l'attribut mixed est positionné à true dans la définition du type.

Remarquez que le modèle mixed de XML Schema est fondamentalement différent de celui précédemment défini dans XML 1.0. Avec ce nouveau modèle, l'ordre et le nombre des éléments enfants de l'instance doivent être en conformité avec ceux spécifiés dans le modèle. Alors que dans XML 1.0, ils ne pouvaient être imposés. En résumé, XML Schema fournit une validation complète des modèles de contenu mixte contrastant avec la validation seulement partielle de XML 1.0.

2.5.3 Contenu vide

Maintenant, supposons que nous voulions que l'élément internationalPrice ait une unité monétaire et un prix sous la forme d'un attribut au lieu que cela soit sous la forme d'un contenu :

<internationalPrice currency="EUR" value="423.46"/>

Un tel élément n'a pas de contenu du tout ; son modèle de contenu est vide. Pour définir un type dont le contenu est vide, le principe est de définir un type ne permettant d'avoir que des sous-éléments comme contenu, sous-éléments qui ne seront jamais déclarés.

<xsd:element name="internationalPrice">
 <xsd:complexType>
  <xsd:complexContent>
   <xsd:restriction base="xsd:anyType">
    <xsd:attribute name="currency" type="xsd:string"/>
    <xsd:attribute name="value"    type="xsd:decimal"/>
   </xsd:restriction>
  </xsd:complexContent>
 </xsd:complexType>
</xsd:element>

Dans cet exemple, nous définissons un type anonyme ayant un contenu de type complexContent, c'est à dire uniquement constitué d'éléments. L'élément complexContent indique que nous avons l'intention de restreindre ou d'étendre le modèle de contenu et la restriction à anyType permet de déclarer deux attributs mais n'introduit aucun sous-élément (cf Chapitre 4.4 pour plus de détails sur les restrictions). L'élément internationalPrice ainsi déclaré peut légitimement apparaître dans une instance sous la forme montrée dans l'exemple ci-dessus.

La syntaxe précédemment utilisée pour déclarer un élément vide est relativement verbeuse et il est possible de déclarer l'élément internationalPrice d'une manière plus compacte.

Raccourci pour déclarer un type complexe vide
<xsd:element name="internationalPrice">
 <xsd:complexType>
  <xsd:attribute name="currency" type="xsd:string"/>
  <xsd:attribute name="value"    type="xsd:decimal"/>
 </xsd:complexType>
</xsd:element>

Cette syntaxe compacte marche parce que la définition d'un type complexe sans utilisation aucune de simpleContent ou complexContent est interprétée comme étant un raccourci pour définir un contenu complexe réduit à anyType.

2.5.4 Contenu libre

Le mot anyType représente une abstraction appelée ur-type qui est le type de base à partir duquel tous les types simples et complexes sont dérivés. Un type anyType ne contraint un contenu d'aucune manière. Il est possible d'utiliser anyType comme n'importe quel autre type, par exemple :

<xsd:element name="anything" type="xsd:anyType"/>

Le contenu de l'élément déclaré de cette manière n'est pas contraint, la valeur de l'élément peut donc être 423.46 comme n'importe quelle autre séquence de caractères, ou un mélange de caractères et de sous-éléments. En fait, anyType est le type par défaut quand aucun type n'est spécifié, aussi, l'exemple précédent pourrait s'écrire comme suit :

<xsd:element name="anything"/>

Si un contenu d'élément libre est nécessaire, par exemple dans le cas où il est nécessaire d'embarquer du balisage étranger dans un élément, alors la déclaration par défaut ou une forme légèrement restreinte peut être pratique. Le type text décrit au Chapitre 5.5 est un exemple d'un tel type.

2.6 Annotations

XML Schema fournit trois éléments dont l'objectif est de commenter les schémas de manière à ce que les commentaires puissent être lus aussi bien par des humains que par des applications. Dans le cas du schéma des bons de commande, nous mettons une description sommaire du schéma ainsi qu'une information de copyright à l'intérieur de l'élément documentation, ce qui est l'endroit recommandé pour les commentaires à destination des lecteurs. Nous recommandons d'utiliser l'attribut xml:lang avec tout élément documentation pour en préciser la langue d'écriture. Une autre manière de faire consiste à placer cet attribut sur l'élément de plus haut niveau, schema, pour indiquer que la langue précisée s'applique à tous les commentaires présents dans le schéma.

L'élément appInfo, que nous n'avons pas utilisé dans le schéma des bons de commande, peut être utilisé pour transmettre de l'information aux outils, feuilles de styles et autres applications qui en auraient besoin. Un exemple intéressant utilisant appInfo est le schéma décrivant les types simples de XML Schema (cf le tome 2). Les informations de description de ce schéma, faites à l'intérieur d'éléments appInfo, présentent les facettes applicables à des types simples en particulier, ont été reprises automatiquement par un programme pour produire le texte du tome 2 de XML Schema.

Les deux éléments documentation et appInfo apparaissent comme des sous-éléments de annotation, qui pourrait lui-même apparaître au début de bien des schémas. Pour illustrer ce propos, l'exemple suivant montre l'utilisation d'éléments annotation au début d'une déclaration d'élément et d'une définition d'un type complexe :

<xsd:element name="internationalPrice">
 <xsd:annotation>
  <xsd:documentation xml:lang="en">
      élément déclaré with anonymous type
  </xsd:documentation>
 </xsd:annotation>
 <xsd:complexType>
  <xsd:annotation>
   <xsd:documentation xml:lang="en">
       empty anonymous type with 2 attributs
   </xsd:documentation>
  </xsd:annotation>
  <xsd:complexContent>
   <xsd:restriction base="xsd:anyType">
    <xsd:attribute name="currency" type="xsd:string"/>
    <xsd:attribute name="value"    type="xsd:decimal"/>
   </xsd:restriction>
  </xsd:complexContent>
 </xsd:complexType>
</xsd:element>

L'élément annotation peut aussi apparaître au début d'autres structures de schémas telles que celles des éléments schema, simpleType, et attribute.

2.7 Construction de modèles de contenu

Dans le schéma des bons de commande, les types complexes sont tous définis avec des séquences d'éléments devant apparaître dans les instances. Les occurrences des éléments individuellement déclarés dans ces modèles peuvent être optionnelles, comme cela est le cas quand l'attribut minOccurs vaut 0 (par exemple dans comment) ou être contrainte de diverses manières en fonction des valeurs de minOccurs et maxOccurs. XML Schema permet aussi d'exprimer des contraintes s'appliquant aux groupes d'éléments des modèles de contenu. Ces contraintes reflètent celles disponibles avec XML 1.0 et les complètent par quelques restrictions supplémentaires. Remarquez que les contraintes ne s'appliquent pas aux attributs.

XML Schema permet de créer et de nommer des groupes d'éléments afin que les éléments puissent être utilisés pour construire les modèles de contenu de type complexe (singeant ainsi le mécanisme des entités paramètres de XML 1.0). Des groupes anonymes d'éléments peuvent également être définis qui, comme les éléments des groupes nommés, peuvent être contraints d'apparaître dans le même ordre (séquence) que leur ordre de déclaration. D'un autre côté, ils peuvent être contraints de manière à ne laisser qu'un seul de ces éléments apparaître dans une instance.

Pour donner un exemple, nous introduisons deux groupes dans la définition du type PurchaseOrderType du schéma des bons de commande de telle manière que les bons de commande puissent contenir au choix une ou deux adresses distinctes de facturation et de livraison :

Exemple de groupes de type choix et séquence imbriqués :
<xsd:complexType name="PurchaseOrderType">
 <xsd:sequence>
  <xsd:choice>
   <xsd:group   ref="shipAndBill"/>
   <xsd:element name="singleUSAddress" type="USAddress"/>
  </xsd:choice>
  <xsd:element ref="comment" minOccurs="0"/>
  <xsd:element name="items"  type="Items"/>
 </xsd:sequence>
 <xsd:attribute name="orderDate" type="xsd:date"/>
</xsd:complexType>

<xsd:group name="shipAndBill">
  <xsd:sequence>
    <xsd:element name="shipTo" type="USAddress"/>
    <xsd:element name="billTo" type="USAddress"/>
  </xsd:sequence>
</xsd:group>

Le groupe choice signifie qu'un seul de ses éléments enfants pourra apparaître dans l'instance. Le premier des enfants est défini via l'élément group qui référence le groupe nommé shipAndBill, lui-même formé des éléments shipTo et billTo dans cet ordre et le deuxième élément du groupe est singleUSAddress. Il s'ensuit que dans une instance de document conforme à ce schéma, l'élément purchaseOrder contiendra soit une suite composée des éléments shipTo et billTo soit le seul élément singleUSAddress. Le groupe choice est ensuite suivi par les deux déclarations des éléments comment et items et tous sont des enfants de l'élément sequence. L'effet de ces différentes imbrications de groupes est que tout élément address doit être suivi des éléments comment et items dans cet ordre.

Une troisième type de contrainte de groupe : tous les éléments du groupe peuvent apparaître une fois mais dans n'importe quel ordre. L'usage du groupe all (version simplifiée du connecteur SGML &) est limité au plus haut niveau de tout modèle de contenu. Les enfants du groupe doivent tous être des éléments individuels (pas de sous-groupe) et aucun élément du modèle de contenu ne peut apparaître plus d'une fois, c'est à dire que les seules valeurs autorisées de minOccurs et maxOccurs sont 0 et 1. Par exemple, pour permettre aux éléments enfants de purchaseOrder d'apparaître dans n'importe quel ordre, nous pourrions redéfinir PurchaseOrderType comme ceci :

Un groupe de type all
<xsd:complexType name="PurchaseOrderType">
  <xsd:all>
    <xsd:element name="shipTo" type="USAddress"/>
    <xsd:element name="billTo" type="USAddress"/>
    <xsd:element ref="comment" minOccurs="0"/>
    <xsd:element name="items"  type="Items"/>
  </xsd:all>
  <xsd:attribute name="orderDate" type="xsd:date"/>
</xsd:complexType>

Par cette définition, un élément comment peut apparaître dans purchaseOrder (sans toutefois être obligatoire) avant ou après n'importe lequel des autres éléments shipTo, billTo et items du modèle de contenu. Il ne pourra de toute façon n'apparaître qu'une seule fois. De plus, il est stipule que dans le cas du groupe all nous ne pouvons déclarer un élément tel que comment en dehors du groupe comme moyen de contournement pour lui permettre d'apparaître plus d'une fois. XML Schema stipule en effet qu'un groupe all doit apparaître comme seul et unique enfant de premier niveau d'un modèle de contenu. En d'autres termes, la forme suivante est interdite parce que le groupe all qu'elle contient n'est pas le seul et unique enfant de premier niveau de la définition du type PurchaseOrderType :

Exemple d'utilisation prohibée du groupe All :
<xsd:complexType name="PurchaseOrderType">
 <xsd:sequence>
  <xsd:all>
    <xsd:element name="shipTo" type="USAddress"/>
    <xsd:element name="billTo" type="USAddress"/>
    <xsd:element name="items"  type="Items"/>
  </xsd:all>
  <xsd:sequence>
   <xsd:element ref="comment" minOccurs="0" maxOccurs="unbounded"/>
  </xsd:sequence>
 </xsd:sequence>
 <xsd:attribute name="orderDate" type="xsd:date"/>
</xsd:complexType>

Finalement, les groupes nommés ou non qui apparaissent dans les modèles de contenu (représenté respectivement par group, choice, sequence, all) peuvent être porteurs des attributs minOccurs et maxOccurs. En combinant et en entrelaçant les différents types de groupes fournis par XML Schema et en fixant les valeurs de minOccurs et maxOccurs, il est possible de représenter tous les modèles de contenu envisageables avec les DTD de XML 1.0. De plus, le groupe all fournit une puissance d'expression supérieure.

Remarque de la traduction française :

Il semblerait que, pour être encore plus explicite, l'exemple ci-dessus devrait être :

<xsd:complexType name="PurchaseOrderType">
 <xsd:sequence>
  <xsd:all>
    <xsd:element name="shipTo" type="USAddress"/>
    <xsd:element name="billTo" type="USAddress"/>
    <xsd:element ref="comment" minOccurs="0"/>
    <xsd:element name="items"  type="Items"/>
  </xsd:all>
  <xsd:sequence>
   <xsd:element ref="comment" minOccurs="0" maxOccurs="unbounded"/>
  </xsd:sequence>
 </xsd:sequence>
 <xsd:attribute name="orderDate" type="xsd:date"/>
</xsd:complexType>

Tel que l'exemple est écrit ci-dessus, la déclaration de l'élément comment apparaît à la fois dans le groupe all et à l'extérieur. C'est là que se trouve le véritable problème de cette formulation qui, dans son application dans les instances de documents, est la cause de formes ambiguës que les programmes de validation ne savent pas "désambigüifier". Par exemple, cette formulation autorise d'écrire dans une instance de document :

<PurchaseOrder>
<billTo>adresse de facturation</billTo>
<comment>commentaire</comment>
</PurchaseOrder>

Fragment dont un programme de validation ne saurait déterminer si la balise <comment> appartient au groupe all ou à la séquence suivante et par conséquent ne saurait valider ce fragment.

Fin de la remarque fait par la traduction française

2.8 Groupes d'attributs

Supposez que nous voulions fournir plus d'informations sur les articles qui composent le bon de commande, comme par exemple leur poids et la méthode d'expédition demandée. Nous pouvons obtenir ce résultat en ajoutant les déclarations de deux attributs weightKg et shipBy à la définition (de type anonyme) de l'élément item :

<xsd:element name="Item" minOccurs="0" maxOccurs="unbounded">
  <xsd:complexType>
   <xsd:sequence>
    <xsd:element   name="productName" type="xsd:string"/>
    <xsd:element   name="quantity">
     <xsd:simpleType>
      <xsd:restriction base="xsd:positiveInteger">
       <xsd:maxExclusive value="100"/>
      </xsd:restriction>
     </xsd:simpleType>
    </xsd:element>
    <xsd:element name="USPrice"  type="xsd:decimal"/>
    <xsd:element ref="comment"   minOccurs="0"/>
    <xsd:element name="shipDate" type="xsd:date" minOccurs="0"/>
   </xsd:sequence>
   <xsd:attribute name="partNum"  type="SKU" use="required"/>
   <!-- add weightKg and shipBy attributs -->
   <xsd:attribute name="weightKg" type="xsd:decimal"/>
   <xsd:attribute name="shipBy">
    <xsd:simpleType>
     <xsd:restriction base="xsd:string">
      <xsd:enumeration value="air"/>
      <xsd:enumeration value="land"/>
      <xsd:enumeration value="any"/>
     </xsd:restriction>
    </xsd:simpleType>
   </xsd:attribute>
  </xsd:complexType>
</xsd:element>

Une alternative serait de créer un groupe d'attributs nommé contenant tous les attributs souhaités de l'élément item puis de référencer ce groupe dans la déclaration de l'élément item :

Rajout d'attributs par utilisation d'un groupe d'attributs
<xsd:element name="item" minOccurs="0" maxOccurs="unbounded">
 <xsd:complexType>
  <xsd:sequence>
   <xsd:element name="productName" type="xsd:string"/>
   <xsd:element name="quantity">
    <xsd:simpleType>
     <xsd:restriction base="xsd:positiveInteger">
      <xsd:maxExclusive value="100"/>
     </xsd:restriction>
    </xsd:simpleType>
   </xsd:element>
   <xsd:element name="USPrice"  type="xsd:decimal"/>
   <xsd:element ref="comment"   minOccurs="0"/>
   <xsd:element name="shipDate" type="xsd:date" minOccurs="0"/>
  </xsd:sequence>

  <!-- attributeGroup replaces individual declarations -->
  <xsd:attributeGroup ref="ItemDelivery"/>
 </xsd:complexType>
</xsd:element>

<xsd:attributeGroup name="ItemDelivery">
  <xsd:attribute name="partNum"  type="SKU" use="required"/>
  <xsd:attribute name="weightKg" type="xsd:decimal"/>
  <xsd:attribute name="shipBy">
    <xsd:simpleType>
     <xsd:restriction base="xsd:string">
      <xsd:enumeration value="air"/>
      <xsd:enumeration value="land"/>
      <xsd:enumeration value="any"/>
     </xsd:restriction>
    </xsd:simpleType>
  </xsd:attribute>
</xsd:attributeGroup>

Cette utilisation d'un groupe d'attributs peut améliorer la lisibilité des schémas et faciliter leurs mises à jour parce qu'un groupe d'attributs peut être édité et modifié en une seule fois et être référencé dans de multiples définitions et déclarations. Cette caractéristique des groupes d'attributs est comparable à celle des entités paramètres de XML 1.0. Remarquez qu'un groupe d'attributs peut contenir d'autres groupes d'attributs. Remarquez aussi que les déclarations d'attributs tout comme les références à des groupes d'attributs doivent apparaître à la fin des définitions de types complexes.

Remarque faite par la traduction française :

La mutualisation des déclarations d'attributs et d'éléments au moyen des groupes d'attributs référencés a des limites et la remarque faite ci-dessus sur les facilités de mise à jour peut en réalité se retourner contre l'auteur du schéma lorsque celui-là aura trop usé de cette technique et des possibilités d'imbrication des groupes. Il faut donc faire preuve de discernement dans la mutualisation des définitions. A trop utiliser les groupes, le risque existe réellement d'avoir des schémas peu lisibles. La mise à jour s'avère alors complexe voir impossible (impossibilité de mesurer le réel impact d'une mise à jour sur l'ensemble des déclarations du schéma).

Fin de la remarque faite par la traduction française

2.9 Valeurs nil

L'un des items listés dans le bon de commande du fichier po.xml, le Lawnmower, n'a pas d'élément shipDate. Dans le contexte de notre scénario, l'auteur du schéma peut avoir eu l'intention d'autoriser cette absence pour indiquer les articles dont l'expédition n'a pas encore été effectuée. Mais en général, l'absence d'un élément n'a pas de signification particulière : cela peut signifier au choix que l'information est inconnue, ou qu'elle est non applicable, ou que l'élément est absent pour une quelconque autre raison. Parfois il est souhaitable de pouvoir représenter un article non expédié, une information inconnue ou inapplicable par un élément explicitement, plutôt que par l'absence d'un élément. Par exemple, il peut être souhaitable de représenter par la présence explicite d'un élément une valeur "nulle" échangée avec une base de données. De tels cas peuvent être résolus en utilisant le mécanisme nil de XML Schema qui permet à un élément d'apparaître avec ou sans une valeur non-nulle.

Pour cela, le mécanisme nil met en jeu un signal nil indirect. En d'autres termes, il n'y a pas de valeur nil apparaissant explicitement au niveau du modèle de contenu. Au lieu de cela, un attribut sert à indiquer que le contenu de l'élément est nul. Pour donner un exemple, nous modifions la déclaration de l'élément shipDate de telle manière que la valeur nil puisse être marquée :

<xsd:element name="shipDate" type="xsd:date" nillable="true"/>

Et pour explicitement représenter que shipDate a une valeur nil dans une instance de document, il suffit de mettre la valeur de l'attribut nil à true :

<shipDate xsi:nil="true"></shipDate>

L'attribut nil provient de l'espace des noms de XML Schema applicables aux instances http://www.w3.org/2001/XMLSchema-instance, en conséquence de quoi il doit être préfixé dans une instance de document du préfixe (tel que xsi:) associé à cet espace de noms (comme pour le préfixe xsd:, le préfixe xsi: est utilisé seulement par convention). Remarquez que le mécanisme nil ne s'applique qu'aux contenus d'éléments et pas à la valeur de leurs attributs. Un élément porteur de la valeur xsi:nil="true" n'a aucun contenu mais peut porter d'autres attributs.

3. Concepts avancés I : espaces de noms, schémas et qualification

Un schéma peut être vu comme une collection (un vocabulaire) de définitions de types et déclarations d'éléments dont les noms appartiennent à un espace de noms particulier appelé espace de noms cible. lls nous permettent de distinguer les définitions et les déclarations appartenant à des vocabulaires différents. Par exemple, cela nous permet de faire la distinction entre la déclaration element du vocabulaire de XML Schema et celle du même mot element d'un vocabulaire qui serait spécifique à une application XML dans le domaine de la chimie. Le premier des deux mots fait partie de l'espace de noms cible http://www.w3.org/2001/XMLSchema et le deuxième ferait partie d'un autre espace de noms cible.

Quand nous voulons vérifier qu'une instance de document est conforme à un ou plusieurs schémas (au moyen d'un traitement appelé validation de schéma), le programme doit être capable de faire la différence entre les déclarations d'éléments et d'attributs et les définitions de types des différents schémas. L'espace de noms cible joue un rôle important dans le processus d'identification. Nous examinons le rôle de l'espace de noms cible au chapitre suivant.

L'auteur du schéma a aussi plusieurs options à sa disposition pour modifier la manière dont l'identité des éléments et des attributs est représentée dans les instances de documents. Plus précisément, l'auteur peut décider si l'écriture des éléments et des attributs déclarés localement doit être qualifiée par un espace de noms, soit via un préfixe explicite soit une valeur implicite par défaut. Le choix de l'auteur du schéma vis à vis de la qualification des éléments et des attributs locaux a un certain nombre d'impacts sur les structures des schémas et des instances et nous en examinons quelques uns dans les chapitres qui suivent.

3.1 Espaces de noms cibles et noms locaux non qualifiés

Dans une version différente du schéma des bons de commande, po1.xsd, nous déclarons explicitement un espace de nom cible et nous spécifions que les éléments et les attributs définis localement ne doivent pas être qualifiés. L'espace de noms cible de po1.xsd est http://www.example.com/PO1, valeur indiquée par l'attribut targetNamespace.

La qualification d'éléments et d'attributs locaux peut être spécifiée soit globalement via la paire d'attributs elementFormDefault et attributeFormDefault de l'élément schema soit individuellement au niveau de chaque déclaration via l'attribut form. Ces attributs peuvent prendre soit la valeur unqualified soit la valeur qualified pour spécifier si les éléments et attributs qui les portent doivent être qualifiés.

Dans po1.xsd nous spécifions globalement la qualification des éléments et des attributs en initialisant les valeurs des deux attributs elementFormDefault et attributeFormDefault à unqualified. Stricto senso, ces initialisations ne sont pas nécessaires parce que les valeurs utilisées sont celles par défaut; nous les mettons en évidence uniquement pour bien souligner la différence avec d'autres cas que nous verrons plus loin.

Schéma des bons de commande avec un espace de nom cible et noms locaux non qualifiés, po1.xsd
<schema xmlns="http://www.w3.org/2001/XMLSchema"
        xmlns:po="http://www.example.com/PO1"
        targetNamespace="http://www.example.com/PO1"
        elementFormDefault="unqualified"
        attributeFormDefault="unqualified">

 <element name="purchaseOrder" type="po:PurchaseOrderType"/>
 <element name="comment"       type="string"/>

 <complexType name="PurchaseOrderType">
  <sequence>
   <element name="shipTo"    type="po:USAddress"/>
   <element name="billTo"    type="po:USAddress"/>
   <element ref="po:comment" minOccurs="0"/>
   <!-- etc. -->
  </sequence>
  <!-- etc. -->
 </complexType>

 <complexType name="USAddress">
  <sequence>
   <element name="name"   type="string"/>
   <element name="street" type="string"/>
   <!-- etc. -->
  </sequence>
 </complexType>

 <!-- etc. -->

</schema>

Pour voir comment l'espace de noms cible de ce schéma est peuplé, nous allons examiner tour à tour les définitions de types et les déclarations d'éléments, en commençant par la fin du schéma. En premier lieu, nous définissons le type appelé USAddress qui comprend les éléments name, street, etc. Faisant cela, le type USAddress est inclus dans l'espace de noms cible du schéma. Ensuite, nous définissons le type appelé PurchaseOrderType qui comprend les éléments shipTo, billTo, comment, etc. PurchaseOrderType est également inclus dans l'espace de nom cible du schéma. Remarquez que les références de type dans les trois déclarations d'éléments sont préfixées : po:USAddress, po:USAddress et po:comment ont le préfixe po:, associé à l'espace de noms http://www.example.com/PO1, le même que l'espace de noms cible du schéma. Ainsi, un programme de traitement du schéma saura regarder à l'intérieur du schéma pour y trouver la définition du type USAddress ainsi que la déclaration de l'élément comment. Il est également possible de référencer des types provenant d'autres schémas en utilisant des espaces de noms cibles différents, permettant ainsi la réutilisation de déclarations et de définitions.

Au début du schéma po1.xsd se trouvent les déclarations des éléments purchaseOrder et comment. Ils sont inclus dans l'espace de noms cible du schéma. Le type de l'élément purchaseOrder est préfixé pour la même raison qui fait que le type USAddress est préfixé. A contrario, le type string de l'élément comment n'est pas préfixé. Le schéma po1.xsd contient une déclaration d'espace de noms par défaut et par conséquent les types et les éléments sans préfixe tels que string, element et complexType sont associés à l'espace de noms par défaut http://www.w3.org/2001/XMLSchema. En fait, cela est l'espace de noms cible de XML Schema lui-même, faisant ainsi qu'un programme de traitement de po1.xsd saura regarder à l'intérieur du schéma de XML Schema -- encore connu comme étant "le schéma des schémas" -- pour y trouver la définition du type string ainsi que la déclaration de l'élément appelé element.

Regardons maintenant comment l'espace de noms cible du schéma a des effets sur une instance de document conforme :

Un bon de commande avec des noms locaux non qualifiés, po1.xml
<?xml version="1.0"?>
<apo:purchaseOrder xmlns:apo="http://www.example.com/PO1"
                   orderDate="1999-10-20">
    <shipTo country="US">
        <name>Alice Smith</name>
        <street>123 Maple Street</street>
        <!-- etc. -->
    </shipTo>
    <billTo country="US">
        <name>Robert Smith</name>
        <street>8 Oak Avenue</street>
        <!-- etc. -->
    </billTo>
    <apo:comment>Hurry, my lawn is going wild!</apo:comment>
    <!-- etc. -->
</apo:purchaseOrder>

Cette instance déclare un espace de nom, http://www.example.com/PO1, et l'associe au préfixe apo: utilisé pour qualifier deux éléments du document, à savoir purchaseOrder et comment. L'espace de noms est identique à celui défini comme cible dans le schéma po1.xsd et un programme de traitement de l'instance sait qu'il y trouvera leurs déclarations respectives. En fait, le mot cible a été choisi à cause du sens dans lequel il existe une relation entre les éléments purchaseOrder et comment et l'espace de noms référencé (note de la rédaction française : le programme de validation part du nom de l'élément et remonte jusqu'à l'espace de noms cible associé au préfixe de l'élément). Il s'ensuit que les espaces de noms cibles du schéma contrôlent la validation des espaces de noms correspondant de l'instance.

Le préfixe apo: est appliqué aux éléments globaux purchaseOrder et comment. En plus, les attributs elementFormDefault et attributeFormDefault imdiquent que le préfixe n'est pas obligatoire sur les attributs et les éléments locaux tels que shipTo, billTo, name et street. Les éléments purchaseOrder et comment sont globaux parce qu'ils ont été déclarés dans le schéma de manière générique plutôt que dans le cadre restrictif d'un type particulier. Par exemple, dans po1.xsd, la déclaration de purchaseOrder est un enfant direct de l'élément schema alors que celle de shipTo est un enfant de l'élément complexType utilisé pour définir l'élément PurchaseOrderType.

Quand la qualification des éléments et des attributs locaux n'est pas requise, l'auteur d'une instance pourra avoir besoin de plus ou moins de connaissance sur le schéma pour écrire des documents valides. Plus précisément, si l'auteur peut être certain que seul l'élément racine (tel que purchaseOrder) est global, alors il est simple de n'avoir à qualifier que l'élément racine. Par contre, l'auteur peut savoir que tous les éléments ont été déclarés globalement et qu'ils sont donc tous susceptibles d'être qualifiés, au mieux en profitant d'une déclaration d'espace de noms par défaut pour simplifier la tâche (cette approche est analysée dans le chapitre 3.3). D'un autre côté, si il n'y a pas de motif uniforme entre les déclarations globales et locales, alors l'auteur aura besoin d'avoir une connaissance très précise du schéma pour pouvoir préfixer correctement les éléments et attributs globaux.

3.2 Noms locaux qualifiés

Les éléments et les attributs sont indépendants vis à vis des exigences de qualification bien que nous commencions par décrire la qualification des éléments locaux. Pour spécifier que tous les éléments déclarés localement dans un schéma doivent être qualifiés, on initialise la valeur de elementFormDefault à qualified:

Modifications de po1.xsdpour avoir des noms locaux qualifiés
<schema xmlns="http://www.w3.org/2001/XMLSchema"
        xmlns:po="http://www.example.com/PO1"
        targetNamespace="http://www.example.com/PO1"
        elementFormDefault="qualified"
        attributeFormDefault="unqualified">

 <element name="purchaseOrder" type="po:PurchaseOrderType"/>
 <element name="comment"       type="string"/>

 <complexType name="PurchaseOrderType">
  <!-- etc. -->
 </complexType>

 <!-- etc. -->

</schema>

Et dans cette instance de document conforme, nous qualifions tous les éléments explicitement :

Un bon de commande avec des noms locaux qualifiés explicitement  :
<?xml version="1.0"?>
<apo:purchaseOrder xmlns:apo="http://www.example.com/PO1"
                   orderDate="1999-10-20">
    <apo:shipTo country="US">
        <apo:name>Alice Smith</apo:name>
        <apo:street>123 Maple Street</apo:street>
        <!-- etc. -->
    </apo:shipTo>
    <apo:billTo country="US">
        <apo:name>Robert Smith</apo:name>
        <apo:street>8 Oak Avenue</apo:street>
        <!-- etc. -->
    </apo:billTo>
    <apo:comment>Hurry, my lawn is going wild!</apo:comment>
    <!-- etc. -->
</apo:purchaseOrder>

Alternativement, nous pouvons remplacer la qualification explicite de chaque élément par une qualification implicite fournie par un espace de noms par défaut, comme cela est montré ci-dessous dans po2.xml:

Un bon de commande avec des locaux qualifiés par défaut, po2.xml :
<?xml version="1.0"?>
<purchaseOrder xmlns="http://www.example.com/PO1"
               orderDate="1999-10-20">
    <shipTo country="US">
        <name>Alice Smith</name>
        <street>123 Maple Street</street>
        <!-- etc. -->
    </shipTo>
    <billTo country="US">
        <name>Robert Smith</name>
        <street>8 Oak Avenue</street>
        <!-- etc. -->
    </billTo>
    <comment>Hurry, my lawn is going wild!</comment>
    <!-- etc. -->
</purchaseOrder>

Dans po2.xml, tous les éléments de l'instance appartiennent au même espace de noms et la déclaration de l'espace de noms définit un espace de noms par défaut qui s'applique à tous les éléments de l'instance. A partir de là, il est inutile de préfixer explicitement un quelconque élément. Comme autre illustration de l'utilisation d'éléments qualifiés, les schémas du chapitre 5 exigent tous d'utiliser des éléments qualifiés.

La qualification des attributs est très similaire à celle des éléments. Les attributs qui doivent être qualifiés, soit parce qu'ils sont déclarés globalement soit parce que l'attribut attributeFormDefault est initialisé à qualified, sont préfixés dans les instances des documents. Un exemple d'attribut qualifié est l'attribut xsi:nil qui a été introduit au chapitre 2.9. En fait, les attributs qui doivent être qualifiés doivent être explicitement préfixés parce que la spécification XML-Namespaces ne fournit aucun mécanisme pour définir un espace de noms par défaut pour les attributs. Les attributs qui n'ont pas besoin d'être qualifiés apparaissent dans les instances de documents sans préfixe, ce qui est la cas classique.

Le mécanisme de qualification que nous avons décrit jusqu'à maintenant a permis de contrôler toutes les déclarations locales d'éléments et d'attributs à l'intérieur d'un espace de noms cible en particulier. Il est également possible de contrôler la qualification sur une déclaration bien précise en utilisant l'attribut form. Par exemple, pour exiger que l'attribut déclaré localement publicKey soit qualifié dans les instances, nous la déclarons de la manière suivante :

Demande de qualification sur un seul attribut :
<schema xmlns="http://www.w3.org/2001/XMLSchema"
        xmlns:po="http://www.example.com/PO1"
        targetNamespace="http://www.example.com/PO1"
        elementFormDefault="qualified"
        attributeFormDefault="unqualified">
 <!-- etc. -->
 <element name="secure">
  <complexType>
   <sequence>
    <!-- élément declarations -->
   </sequence>
   <attribute name="publicKey" type="base64Binary" form="qualified"/>
  </complexType>
 </element>
</schema>

Remarquez que la valeur de l'attribut form écrase la valeur par défaut de l'attribut attributeFormDefault mais uniquement pour l'attribut publicKey. L'attribut form peut tout aussi bien être appliqué à une déclaration d'élément. Une instance de document conforme à ce schéma est par exemple :

Instance ayant un attribut qualifié :
<?xml version="1.0"?>
<purchaseOrder xmlns="http://www.example.com/PO1"
               xmlns:po="http://www.example.com/PO1"
               orderDate="1999-10-20">
    <!-- etc. -->
    <secure po:publicKey="GpM7">
        <!-- etc. -->
    </secure>
</purchaseOrder>

3.3 Déclarations globales versus locales

Quand tous les noms d'éléments sont uniques à l'intérieur d'un espace de noms, les schémas faits à partir de cet espace de noms peuvent ne contenir que des éléments globaux. Cela est similaire dans les faits à l'utilisation de la carte <!ELEMENT> dans une DTD. Dans l'exemple ci-dessous, nous avons modifié la version originale de po1.xsd de telle manière que tous les éléments soient déclarés globalement. Remarquez que nous avons omis dans cet exemple les attributs elementFormDefault et attributeFormDefault pour mettre en valeur le fait que leurs valeurs sont sans intérêt dans ce type de schéma.

Schéma po1.xsd n'utilisant que des déclarations globales d'éléments
<schema xmlns="http://www.w3.org/2001/XMLSchema"
        xmlns:po="http://www.example.com/PO1"
        targetNamespace="http://www.example.com/PO1">

 <element name="purchaseOrder" type="po:PurchaseOrderType"/>

 <element name="shipTo"  type="po:USAddress"/>
 <element name="billTo"  type="po:USAddress"/>
 <element name="comment" type="string"/>
 
 <element name="name" type="string"/>
 <element name="street" type="string"/>

 <complexType name="PurchaseOrderType">
  <sequence>
   <element ref="po:shipTo"/>
   <element ref="po:billTo"/>
   <element ref="po:comment" minOccurs="0"/>
   <!-- etc. -->
  </sequence>
 </complexType>

 <complexType name="USAddress">
  <sequence>
   <element ref="po:name"/>
   <element ref="po:street"/>
   <!-- etc. -->
  </sequence>
 </complexType>

 <!-- etc. -->

</schema>

Cette version "globale" po1.xsd validera l'instance po2.xml qui est aussi, comme nous l'avons décrit précédemment, valide par rapport à la version "qualifiée" du schéma, à savoir po1.xsd. En d'autres termes, les deux approches permettent de valider le même document qui utiliserait un espace de noms par défaut. Dans ce sens, elles sont similaires, même si par ailleurs elles sont vraiment différentes. Plus particulièrement, quand tous les éléments sont déclarés globalement, il n'est pas possible de tirer partie des possibilités des noms locaux. Par exemple, vous ne pouvez déclarer qu'un seul élément global appelé title. Par contre, vous pouvez déclarer localement un sous-élément de book appelé title ayant un contenu de type string comme par exemple un deuxième élément title form