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. |
Copyright ©2001 W3C® (MIT, INRIA, Keio), All Rights Reserved. W3C liability, trademark, document use et software licensing rules apply.
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.
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/.
anyschemaLocationCe 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.
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 :
<?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.
Le schéma d'un bon de commande est contenu dans le fichier 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.
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 :
<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.
<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.
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. | ||
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.
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.
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 :
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":
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 :
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.
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).
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 :
<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).
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 :
<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.
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 :
<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.
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.
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.
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.
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.
<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.
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.
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.
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 :
<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 :
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 :
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
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 :
<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
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.
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.
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.
<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 :
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
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.
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:
<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 :
<?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:
<?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 :
<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 :
<?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>
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.
<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