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 :
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. |
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/.
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.
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>
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.
<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>
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.
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 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>
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"/>
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. |
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.
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.
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 :
<xsd:simpleType name="myInteger"> <xsd:restriction base="xsd:integer"> <xsd:minInclusive value="10000"/> <xsd:maxInclusive value="99999"/> </xsd:restriction> </xsd:simpleType>
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":
<xsd:simpleType name="SKU"> <xsd:restriction base="xsd:string"> <xsd:pattern value="\d{3}-[A-Z]{2}"/> </xsd:restriction> </xsd:simpleType>
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 :
<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>
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).
<xsd:simpleType name="listOfMyIntType"> <xsd:list itemType="myInteger"/> </xsd:simpleType>
<listOfMyInt>20003 15037 95977 95945</listOfMyInt>
<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>
<sixStates>PA NY CA NY LA AK</sixStates>
Asie Europe Afrique
Asie Europe Amérique Latine
<xsd:simpleType name="zipUnion"> <xsd:union memberTypes="USState listOfMyIntType"/> </xsd:simpleType>
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>
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>
<internationalPrice currency="EUR">423.46</internationalPrice>
<xsd:element name="USPrice" type="decimal"/>
<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>
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>
<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>
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.
<internationalPrice currency="EUR" value="423.46"/>
<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>
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>
<xsd:element name="anything" type="xsd:anyType"/>
<xsd:element name="anything"/>
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>
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>
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 :
<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>
<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>
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>
<PurchaseOrder> <billTo>adresse de facturation</billTo> <comment>commentaire</comment> </PurchaseOrder>
Fin de la remarque fait par la traduction française
<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>
<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>
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
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"/>
<shipDate xsi:nil="true"></shipDate>
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.
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>
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 :
<?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>
Le préfixe apo: est appliqué aux éléments
globaux
purchaseOrder et comment. En plus, les attributs 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.
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 :
Dans le schéma po.xsd des bons
de commande, aucun espace de noms cible ni préfixe (comme po:
ci-dessus) n'ont été déclarés qui pourraient
nous permettre de faire des références à des types
et des éléments du schéma. La conséquence est
que les définitions et les déclarations de ce schéma,
comme par exemple
USAddress et purchaseOrder, sont référencées
sans qualification d'espace de noms. En d'autres termes, il n'y un ni préfixe
explicite sur les références ni espace de noms implicite
sur la référence par défaut. Ainsi, l'élément
purchaseOrder est déclaré, dans cet exemple, en
utilisant directement une référence non qualifiée
au type
PurchaseOrderType alors que tous les éléments
et les types issus de XML Schema sont explicitement qualifiés par
xsd:, préfixe associé à l'espace de noms
de XML Schema.
Quand un schéma est conçu sans espace de noms cible, il
est fortement recommandé que tous les éléments et
types en provenance de l'espace de noms de XML Schema soient explicitement
qualifiés par un préfixe tel que
xsd:. La raison
en est que, si cette association est faite par défaut, les références
aux types issus de XML Schema pourront ne pas être distinguées
de celles faisant référence aux types définis par
l'utilisateur.
Les déclarations d'éléments d'un schéma
n'ayant pas d'espace de noms cible sont celles utilisées pour valider
les éléments non qualifiés de l'instance de document.
Cela étant, elles valident des éléments pour lesquels
aucune qualification d'espace de noms n'est fournie ni directement via
un préfixe explicite ni indirectement via un préfixe par
défaut (xmlns:). Aussi, pour valider un document XML 1.0
qui, typiquement, n'utilise aucun espace de noms, vous devez fournir un
schéma n'ayant pas d'espace de noms cible. Comme c'est le cas de
la plupart des documents XML 1.0, il y aura beaucoup de schémas
écrits sans espace de noms cibles ; vous devez être sûrs
de donner à votre programme de traitement un schéma qui corresponde
au vocabulaire que vous souhaitez valider. Dans notre exemple, nous n'avons montré l'inclusion que d'un
seul document et dans un seul document récepteur. En pratique il
est possible d'une part d'inclure plusieurs documents en cumulant plusieurs
éléments include
et d'autre part d'imbriquer les inclusions, les documents inclus pouvant
à leur tour inclure d'autres documents et ainsi de suite. Toutefois,
l'imbrication de documents n'est légale que si la condition de base
de l'inclusion est vérifiée : toutes les parties incluses
du schéma doivent avoir le même espace de noms cible.
Les instances de documents conformes au schéma dont les définitions
sont réparties entre plusieurs documents schéma (ndlr : généralement
des fichiers contenant les différentes sous-parties constitutives
du schéma final) ont seulement besoin de référencer
le document schéma principal et l'espace de noms commun ; il est
ensuite laissé à la charge du programme de traitement de
savoir collecter toutes les définitions spécifiées
dans les différents documents schéma inclus. Dans l'exemple
ci-dessus, une instance de document
ipo.xml
(cf chapitre 4.3) référence
seulement l'espace de noms cible commun, à savoir http://www.example.com/IPO
et (par conséquence) le seul fichier schéma
http://www.example.com/schemas/ipo.xsd.
Le programme de traitement doit savoir retrouver le document schéma
address.xsd à partir du fichier
schéma de plus haut niveau.
Au chapitre 5.4, nous décrivons la manière
d'utiliser les schémas pour valider un contenu réparti dans
plusieurs espaces de noms. Nous définissons les deux nouveaux types complexes, USAddress
et UKAddress, en utilisant l'élément complexType.
De plus, nous indiquons que les modèles de contenu des nouveaux
types sont eux mêmes de type complexe en utilisant l'élément
complexContent (c'est à
dire que leurs contenus contiennent des sous-éléments) et
nous indiquons qu'il s'agit d'une extension du type de base Address
en utilisant l'attribut
base de
l'élément extension.
Quand un type complexe est étendu, son modèle de contenu
effectif est celui du type de base plus celui spécifié dans
la dérivation du type. De plus, les deux modèles de contenu
sont traités comme deux enfants d'un groupe séquentiel. Dans
le cas de UKAddress, le modèle de contenu de
UKAddress
est celui d'Address augmenté des déclarations de
l'élément postcode et de celles de l'attribut
exportCode.
Cela revient à définir UKAddress à partir
de rien comme suit :
XML Schema nous permet de définir les éléments
billTo
et shipTo comme étant de type
Address (cf ipo.xsd)
et d'utiliser des instances d'adresses internationales à la place
des instances d'Address. En d'autres termes, une instance de document
dont le contenu est conforme au type UKAddress sera valide si
ce contenu apparaît dans le document à un endroit où
le type Address était attendu (en supposant que le contenu
de UKAddress soit lui même valide). Pour faire marcher cette
fonction de XML Schema et pour identifier exactement quel type dérivé
est attendu, le type dérivé doit être identifié
dans une instance de document : cela se fait en utilisant l'attribut xsi:type
qui appartient à l'espace de noms instance de XML Schema. Dans l'exemple,
ipo.xml, l'utilisation des types dérivés
UKAddress
et USAddress est identifiée par le biais des valeurs assignées
à l'attribut xsi:type.
Par exemple, supposez que nous souhaitions mettre à jour notre
définition de la liste d'items du bon de commande international
de telle manière qu'elle doive contenir au moins un item
; le schéma de ipo.xsd permet pour
l'instant à l'élément items d'être
utilisé sans qu'aucun enfant
item soit mis à l'intérieur.
Pour créer notre nouveau type
ConfirmedItems, nous le définissons
de la manière habituelle sauf que nous indiquons qu'il est dérivé
par restriction à partir du type de base Items. Nous fixons
alors une valeur plus restrictive du nombre d'occurrences minimum du sous-élément
item. Remarquez que les types dérivés par restriction
reprennent obligatoirement tous les composants de leur définition
de base :
Pour expliquer encore plus la restriction, nous donnons dans le tableau
3 des exemples de la manière dont les déclarations d'éléments
et d'attributs peuvent être restreintes dans des déclarations
de type (le tableau montre des syntaxes de déclaration d'élément
quoique les trois premiers exemples puissent également s'appliquer
à des restrictions de déclarations d'attributs).
Pour illustrer le mécanisme redefine,
nous allons l'utiliser à la place du mécanisme include
dans le schéma des bons de commande internationaux, ipo.xsd
et cela dans le but de modifier la définition du type complexe Address
contenu dans address.xsd :
Maintenant que le type Address a été redéfini,
l'extension s'applique à tous les composants du schéma qui
utilisent le type
Address. Par exemple, address.xsd
contient les définitions de plusieurs variantes internationales
d'adresses dérivées du type
Address. Ces dérivations
reflètent le type redéfini
Address, comme cela est
montré dans l'extrait suivant :
L'existence d'un groupe de substitution n'exige pas d'utiliser un quelconque
des éléments de cette classe, ni ne présume de l'utilisation
de l'élément tête. Il fournit simplement un mécanisme
pour permettre aux éléments d'être interchangeables. Dans le groupe de substitution exemple que nous décrivions au
chapitre 4.6, il serait pratique d'interdire
spécifiquement l'utilisation de l'élément comment
pour imposer aux instances l'usage des éléments customerComment
et
shipComment. Pour déclarer que l'élément
comment est abstrait, nous modifions sa déclaration originale
dans le schéma des bons de commande internationaux, ipo.xsd,
comme suit :
Déclarer un élément comme étant abstrait
requiert l'utilisation d'un groupe de substitution. Déclarer un
type comme étant abstrait requiert simplement l'utilisation, dans
les instances de documents, d'un type qui lui soit dérivé
(alors identifié par l'attribut xsi:type).
Considérez la définition de schéma suivante :
XML Schema fournit un couple de mécanismes qui contrôle
la dérivation des types. L'un de ces mécanismes permet à
l'auteur du schéma de spécifier qu'un type complexe en particulier
ne peut faire l'objet de types dérivés, ni (a) par restriction,
ni (b) par extension, ou (c) du tout. Pour illustrer ce propos, supposons
que nous voulions interdire toute dérivation du type
Address
par restriction parce que nous avons l'intention de ne l'utiliser que comme
type de base que pour des types étendus tels que
USAddress
et UKAddress. Pour interdire ce mode de dérivation, nous
modifions légèrement la définition originale du type
Address
comme suit :
Un autre mécanisme de dérivation de
type permet de contrôler les facettes autorisées dans la dérivation
de nouveaux types simples. Quand un type simple est défini, l'attribut
fixed peut être appliqué
à n'importe laquelle de ses facettes pour en empêcher la modification
lors d'une dérivation. Par exemple, nous pouvons définir
un type simple
Postcode comme :
Remarquez que dans ce chapitre nous qualifions les éléments
dans le schéma et utilisons des éléments non qualifiés
dans les instances, en clair des espaces de noms par défaut (quand
cela est possible).
Nous pouvons aussi indiquer des combinaisons de champs qui doivent être
uniques. Pour illustrer ce propos, supposez que nous pouvons relâcher
la contrainte d'unicité sur les codes zip bien que nous souhaitions
conserver la contrainte d'unicité des produits par code zip. Nous
pourrions atteindre cet objectif en spécifiant qu'un couple formé
du code zip et du numéro de produit doit être unique. D'après
le document rapport 4Q99.xml, les valeurs
combinées du code zip et du numéro de produit seraient :
{95819 872-AA}, {95819 926-AA}, {95819 833-AA},
{95819 455-BX}, et {63143 455-BX}. En clair, ces couples
ne font pas la distinction entre les combinaisons des codes zip et des
numéros d'article obtenus à partir d'une ou plusieurs listes
de codes zip spécifiés et la présence d'un produit
vendu plus d'une fois pour un même code zip serait listée
de manière non équivoque (c'est à dire plusieurs fois).
En d'autres termes, un programme de traitement du schéma serait
capable de détecter les violations de la contrainte d'unicité.
Pour définir des combinaisons de valeurs, nous ajoutons simplement
des éléments field
pour identifier toutes les valeurs impliquées. Aussi, pour ajouter
le numéro d'article sans doublon à notre définition
actuelle, nous ajoutons un nouvel élément field
dont la valeur de l'attribut xpath
qui est part/@number. La définition résultante sélectionne
les élément zip enfants des éléments
regions différents pas leurs code puis les éléments
part enfants des éléments zip différents
par la valeur de leur attribut number :
Pour garantir que les couples pièce-quantité font référence
à des descriptions de pièces, nous spécifions que
l'attribut number (<field>@number</field>) est
une référence (keyref) à pNumKey
qui est une clé (key). Ainsi faite, la déclaration
de number signifie que lorsque cet attribut est utilisé
dans une instance de document, sa valeur doit être égale à
celle d'un pNumKey. La valeur de l'attribut clé (pNumKey)
doit être unique mais elle peut être référencée
par plusieurs attributs de type keyref comme par exemple
number.
(note de la traduction française : le mécanisme décrit
ici ne garantit pas que la référence faite à la description
soit la bonne).
Comme vous pouvez vous en douter par analogie avec l'élément
unique, il est possible de définir
des combinaisons des valeurs de key
et
keyref. En utilisant ce mécanisme,
nous pourrions assez facilement aller plus loin en exigeant que les numéros
d'articles soient égaux et en définissant une combinaison
de valeurs qui doivent être égales. Les valeurs dont on parle
peuvent être des combinaisons de plusieurs types de valeurs (string,
integer,
date, etc.) à condition que l'ordre
et le type des références de l'élément field
soient identiques dans les deux définitions de key
et de keyref. Pour importer le type SKU et l'utiliser
dans le schéma du rapport, nous déclarons l'espace de noms
dans lequel
SKU est défini et l'associons à un préfixe
à utiliser dans le schéma du rapport. Concrètement,
nous utilisons l'élément import
pour identifier l'espace de noms cible de SKU, http://www.example.com/IPO
et nous l'associons au préfixe xipo au moyen d'une déclaration
standard d'espace de noms. Le type simple SKU, défini dans
l'espace de noms http://www.example.com/IPO, peut ensuite être
référencé comme xipo:SKU dans toutes les
définitions et déclarations du schéma du rapport.
Dans notre exemple, nous importons un type simple à partir d'un
espace de noms externe et l'utilisons dans des déclarations d'attributs.
XML Schema permet d'importer plusieurs composants d'un schéma, issus
de plusieurs espaces de noms différents qui peuvent ensuite être
référencés à partir des définitions
et des déclarations. Par exemple dans report.xsd
nous pourrions réutiliser l'élément
comment
déclaré dans ipo.xsd en le
référençant à l'aide de la déclaration
suivante :
Les types peuvent aussi être importés et être utilisés
comme types de base pour dériver de nouveaux types. Seuls les types
complexes nommés peuvent être importés ; les types
locaux définis anonymement ne peuvent pas être importés.
Supposez que nous voulions inclure dans nos rapports le nom d'un analyste
et ses coordonnées pour le contacter. Nous pouvons réutiliser
le type complexe (défini globalement) USAddress de address.xsd
et l'étendre afin de définir un nouveau type appelé
Analyst qui contiendra les deux nouveaux éléments
phone et email :
Les auteurs de schémas voudront, à n'en pas douter, créer
leurs propres bibliothèques de types pour représenter par
exemple des monnaies, des unités de mesure, des listes d'adresses
professionnelles etc. Chaque bibliothèque peut consister en un schéma
contenant une ou plusieurs définitions, par exemple, celle d'un
type currency :
Pour illustrer ce propos, considérez une version du rapport trimestriel
4Q99html.xml,
dans laquelle nous avons embarqué une représentation HTML
des données XML des pièces. Le contenu HTML apparaît
comme contenu de l'élément htmlExemple et l'espace
de noms par défaut est changé pour l'élément
HTML de plus haut niveau (l'élément table) de telle
sorte que tous les éléments HTML appartiennent à l'espace
de noms de HTML,
http://www.w3.org/1999/xhtml:
Dans l'exemple suivant, nous définissons
un type
text similaire au type text défini dans
la présentation de la bibliothèque
de types de XML Schema (cf le chapitre 5.4.1) qui
convient pour du texte internationalisé lisible par un oeil humain.
Le nouveau type text permet d'avoir un mélange d'éléments
et de caractères de données sans restriction, de n'importe
quel espace de noms, comme par exemple des annotations Ruby,
parallèlement à l'utilisation de l'attribut optionnel xml:lang.
La valeur lax de l'attribut processContents
dit au programme de traitement de l'instance XML de valider le contenu
de l'élément sur la base d'un "peut-le-faire" : il validera
les éléments et les attributs pour lesquels il peut obtenir
l'information de schéma, mais il ne signalera pas d'erreur pour
ceux dont il ne peut pas obtenir une quelconque information de schéma.
En plus de l'élément any
qui autorise un contenu d'élément en fonction des espaces
de noms, il y a un élément correspondant anyAttribute
qui autorise les attributs d'apparaître dans des éléments.
Par exemple, nous pouvons permettre à tout attribut HTML d'apparaître
dans l'élément htmlExemple en rajoutant anyAttribute
à sa déclaration :
1. dans une instance de document, l'attribut xsi:schemaLocation
fournit une indication de l'auteur au programme de traitement concernant
l'emplacement des documents schéma. L'auteur garantit que les schéma
mentionnés sont corrects pour contrôler, espace de noms par
espace de noms, la validité du contenu du document. Par exemple,
nous pouvons indiquer l'emplacement du schéma du rapport à
un programme de traitement du rapport trimestriel :
Un schéma n'est pas obligé d'avoir un espace de noms (cf
chapitre 3.4). L'attribut noNamespaceSchemaLocation
sert alors à fournir aux programmes de traitement des informations
sur les emplacements des schémas qui n'ont pas d'espace de noms
cible.
2. Dans un schéma, l'élément include
a un attribut obligatoire,
schemaLocation,
dont la valeur est une URI de référence qui doit identifier
un document schéma. L'effet est de construire un schéma final
effectif en fusionnant les déclarations et les définitions
des schémas appelant et appelé. Par exemple, au chapitre
4, les définitions des types
Address, USAddress,
UKAddress,
USState (complétées de leurs
déclarations d'attributs et d'éléments locaux respectives)
du schéma address.xsd ont été
ajoutées aux déclarations d'éléments de purchaseOrder
et comment, et aux définitions de PurchaseOrderType,
Items et
SKU (aussi complétées de leurs
déclarations d'attributs et d'éléments locaux) de
ipo.xsd pour former un seul schéma.
3. Dans un schéma, l'élément import
a aussi des attributs optionnels
namespace
et schemaLocation. L'attribut
schemaLocation
a la même signification que l'attribut xsi:schemaLocation
expliqué en (1). Plus particulièrement, il fournit une recommandation
de l'auteur quant à l'emplacement du document schéma dont
l'auteur garantit qu'il fournit les composants requis pour l'espace de
noms identifié par l'attribut namespace.
Pour importer des composants qui sont dans aucun espace de noms cible,
l'élément import ,
avec ou sans attribut schemaLocation,
sera utilisé sans attribut namespace.
Les références aux composants importés de la sorte
sont non qualifiées.
Remarquez que l'attribut schemaLocation
ne fournit qu'un conseil et certains programmes de traitements et applications
auront raison de ne pas exploiter cette donnée. Par exemple, un
éditeur HTML peut avoir un schéma HTML intégré. L'auteur d'une instance de document, un bon de commande par exemple,
peut réclamer dans l'instance elle-même, qu'elle se conforme
aux règles d'un schéma en particulier. L'auteur le fait en
utilisant l'attribut schemaLocation
discuté ci-dessus. Mais indépendamment de la présence
ou non de l'attribut schemaLocation,
une application est libre de traiter un document au regard de n'importe
quel schéma. Par exemple, une application de gestion des achats
peut avoir comme politique d'utiliser toujours le même schéma
de bon de commande, cela indépendamment de toute valeur de l'attribut
schemaLocation.
Le contrôle de conformité peut être représenté
comme procédant étape par étape, contrôlant
en premier que l'élément racine du instance de document a
les bons contenus, puis contrôlant que chaque sous-élément
soit conforme à sa description dans un schéma et ainsi de
suite jusqu'à ce que tout le document soit vérifié.
Les programmes de traitement doivent rapporter ce que le contrôle
a permis de vérifier.
Pour contrôler la conformité d'un élément,
le programme de traitement commence par identifier la déclaration
de l'élément dans un schéma puis contrôle que
l'attribut targetNamespace
du schéma corresponde à l'URI de l'espace de noms de l'élément.
Une autre solution serait de déterminer que le schéma n'a
pas d'attribut targetNamespace
et que l'élément instancié n'est pas qualifié
par un préfixe d'espace de noms.
En supposant que les espaces de noms correspondent, le programme de
traitement examine ensuite le type de l'élément, soit tel
qu'il est donné par la déclaration qui se trouve dans le
schéma soit via la présence d'un attribut xsi:type
dans l'instance. Dans le dernier cas, le type instancié doit être
une substitution autorisée du type donné dans le schéma
; ce qui est autorisé dépend de l'attribut block
de la déclaration de l'élément. Arrivé à
ce stade, les valeurs par défaut et d'autres informations de contribution
sont appliquées.
Ensuite, le programme de traitement contrôle les attributs et
les contenus immédiats de l'élément, les comparant
avec les attributs et contenus autorisés par le type de l'élément.
Par exemple, considérons un élément
shipTo
identique à celui du chapitre 2.1, le programme
de traitement contrôle ce qui est autorisé par le modèle
Address, type de l'élément shipTo.
Si l'élément a un type simple, le programme de traitement
vérifie que l'élément n'a pas d'attribut et ne contient
pas lui même d'autres éléments et que les caractères
qu'il contient correspondent au règles du type simple concerné.
Cela implique parfois de contrôler la séquence de caractères
vis à vis d'expressions régulières ou d'énumérations
et aussi parfois de contrôler que la séquence de caractères
représente une valeur autorisée de la fourchette de valeurs
spécifiée.
Si l'élément a un type complexe, alors le programme de
traitement contrôle que les attributs obligatoires sont présents,
que leurs valeurs sont conformes aux exigences de leurs types. Il contrôle
aussi que tous les sous-éléments obligatoires sont présents
et que la séquence des sous-éléments (et tout contenu
mixte) est conforme au modèle de contenu déclaré du
type complexe concerné. En ce qui concerne les sous-éléments,
les schémas peuvent soit exiger qu'il y ait une correspondance exacte
des noms, soit autoriser la substitution par un élément équivalent
ou par tout élément autorisé suite à l'utilisation
de la particule 'any'.
A moins qu'un schéma n'indique le contraire (comme cela est possible
avec la particule 'any'), le contrôle de conformité
rentre ensuite dans les niveaux plus bas en s'intéressant aux sous-éléments,
l'un après l'autre, répétant pour chacun l'opération
décrite ci-dessus. Les facettes listées dans le tableau B1.b ne s'appliquent qu'à
des types simples ordonnés. Comme cela n'est pas applicable à
tous les types simples, ce deuxième tableau ne contient qu'un sous-ensemble
de la liste des types simples.
Supposez que nous voulions déclarer et utiliser un entité
dans une instance de document et que le document soit aussi contraint par
un schéma. Par exemple :
Nous pouvons aboutir à une approche similaire sans toutefois
être identique en déclarant dans le schéma un élément
dont le contenu sera défini de manière appropriée
comme suit :
Index des éléments de XML Schema. Chaque nom d'élément
est lié à une description XML formelle soit dans le tome
"Structures" soit dans le tome "Types de données"
de la spécification XML Schema. Les noms des éléments
sont suivis d'un plusieurs liens vers les exemples (identifiés par
les numéros de chapitre où ils se trouvent) de cette introduction.
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:
<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>
<?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>
<?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>
<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>
<?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.
<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>
3.4 Espaces de noms cibles non-déclarés
Au chapitre 2 nous avons expliqué les bases de
XML Schema en prenant l'exemple d'un schéma sans déclaration
de l'espace de noms cible et d'une instance de document sans déclaration
d'espace de noms. La question suivante vient donc naturellement à
être posée : Quel est l'espace de noms cible de ces exemples
et comment est-il référencé ?
4. Concepts avancés II : un bon de commande international
Le schéma des bons de commande décrit au chapitre
2 était contenu dans un seul et même document et la plupart
de ses constructions -- telles que les déclarations d'éléments
et les définitions de types -- furent bâties à partir
de rien. En réalité, les auteurs de schémas voudront,
pour créer de nouveaux types, pouvoir repartir de constructions
existantes, réparties dans plusieurs documents. Dans ce chapitre,
nous examinons les mécanismes qui le permettent.
4.1 Un schéma réparti entre
plusieurs documents
Au fur et à mesure que les schémas deviennent plus longs,
il est souvent préférable de les scinder en plusieurs petits
documents, pour en faciliter la maintenance et les conditions d'accès
et en augmenter la lisibilité. Pour ces raisons, nous avons isolé
les constructeurs des différents types d'adresses du schéma
po.xsd et les avons mis dans un nouveau
fichier appelé address.xsd.
Le schéma ainsi modifié des bons de commande est appelé
ipo.xsd:
<schema targetNamespace="http://www.example.com/IPO"
xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:ipo="http://www.example.com/IPO">
<annotation>
<documentation xml:lang="en">
schéma des bons de commande internationaux pour Exemple.com
Copyright 2000 Exemple.com. All rights reserved.
</documentation>
</annotation>
<!-- include address constructs -->
<include
schemaLocation="http://www.example.com/schemas/address.xsd"/>
<element name="purchaseOrder" type="ipo:PurchaseOrderType"/>
<element name="comment" type="string"/>
<complexType name="PurchaseOrderType">
<sequence>
<element name="shipTo" type="ipo:Address"/>
<element name="billTo" type="ipo:Address"/>
<element ref="ipo:comment" minOccurs="0"/>
<element name="items" type="ipo:Items"/>
</sequence>
<attribute name="orderDate" type="date"/>
</complexType>
<complexType name="Items">
<sequence>
<element name="item" minOccurs="0" maxOccurs="unbounded">
<complexType>
<sequence>
<element name="productName" type="string"/>
<element name="quantity">
<simpleType>
<restriction base="positiveInteger">
<maxExclusive value="100"/>
</restriction>
</simpleType>
</element>
<element name="USPrice" type="decimal"/>
<element ref="ipo:comment" minOccurs="0"/>
<element name="shipDate" type="date" minOccurs="0"/>
</sequence>
<attribute name="partNum" type="ipo:SKU" use="required"/>
</complexType>
</element>
</sequence>
</complexType>
<simpleType name="SKU">
<restriction base="string">
<pattern value="\d{3}-[A-Z]{2}"/>
</restriction>
</simpleType>
</schema>
<schema targetNamespace="http://www.example.com/IPO"
xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:ipo="http://www.example.com/IPO">
<annotation>
<documentation xml:lang="en">
adresses pour schéma des bons de commande internationaux
Copyright 2000 Exemple.com. All rights reserved.
</documentation>
</annotation>
<complexType name="Address">
<sequence>
<element name="name" type="string"/>
<element name="street" type="string"/>
<element name="city" type="string"/>
</sequence>
</complexType>
<complexType name="USAddress">
<complexContent>
<extension base="ipo:Address">
<sequence>
<element name="state" type="ipo:USState"/>
<element name="zip" type="positiveInteger"/>
</sequence>
</extension>
</complexContent>
</complexType>
<complexType name="UKAddress">
<complexContent>
<extension base="ipo:Address">
<sequence>
<element name="postcode" type="ipo:UKPostcode"/>
</sequence>
<attribute name="exportCode" type="positiveInteger" fixed="1"/>
</extension>
</complexContent>
</complexType>
<!-- other Address dérivations pour plus countries -->
<simpleType name="USState">
<restriction base="string">
<enumeration value="AK"/>
<enumeration value="AL"/>
<enumeration value="AR"/>
<!-- et so on ... -->
</restriction>
</simpleType>
<!-- type simple définition pour UKPostcode -->
</schema>
<include schemaLocation="http://www.example.com/schemas/address.xsd"/>
4.2 Dérivation de types par extension
Pour créer nos constructeurs d'adresses, nous avons commencé
par créer un type complexe appelé Address selon
la règle habituelle (cf
address.xsd)
et le type
Address contient les éléments de base
d'une adresse : nom, rue et ville (une telle définition ne marchera
pas pour tous les types d'adresses du monde entier mais elle sert le propos
de notre exemple). A partir de ce point de départ nous dérivons
deux nouveaux types complexes qui contiennent tous les éléments
du type original plus des éléments complémentaires
spécifiques aux adresses américaines et anglaises. La technique
que nous utilisons ici pour dériver ces nouveaux types complexes
d'adresses par extension d'un type existant et la même que celle
utilisée au chapitre 2.5.1 excepté
que notre type de base est ici un type complexe d'être un type simple.
<complexType name="UKAddress">
<sequence>
<!-- modèle de contenu de Address -->
<element name="name" type="string"/>
<element name="street" type="string"/>
<element name="city" type="string"/>
<!-- appended élément declaration -->
<element name="postcode" type="ipo:UKPostcode"/>
</sequence>
<!-- appended attribut declaration -->
<attribute name="exportCode" type="positiveInteger" fixed="1"/>
</complexType>
4.3 Utilisation de types dérivés
dans des instances de documents
Dans le scénario qui nous sert d'exemple, les bons de commande sont
générés en réponse aux ordres des clients qui
peuvent avoir des adresses d'expédition et de facturation différentes.
Le bon de commande international,
ipo.xml
ci-dessous, illustre ce cas où les produits sont expédiés
au Royaume-Uni et la facture aux Etats-Unis. Clairement, il serait mieux
que le schéma n'ait pas à lister toutes les combinaisons
possibles des différents cas d'adresses dans les différents
pays du monde et l'idéal serait de pouvoir créer de nouveaux
types complexes d'adresses par simple dérivation du type Address.
div class="exampleOuter">
<?xml version="1.0"?>
<ipo:purchaseOrder
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ipo="http://www.example.com/IPO"
orderDate="1999-12-01">
<shipTo exportCode="1" xsi:type="ipo:UKAddress">
<name>Helen Zoe</name>
<street>47 Eden Street</street>
<city>Cambridge</city>
<postcode>CB1 1JR</postcode>
</shipTo>
<billTo xsi:type="ipo:USAddress">
<name>Robert Smith</name>
<street>8 Oak Avenue</street>
<city>Old Town</city>
<state>PA</state>
<zip>95819</zip>
</billTo>
<items>
<item partNum="833-AA">
<productName>Lapis necklace</productName>
<quantity>1</quantity>
<USPrice>99.95</USPrice>
<ipo:comment>Want this pour the holidays!</ipo:comment>
<shipDate>1999-12-05</shipDate>
</item>
</items>
</ipo:purchaseOrder>
4.4 Dérivation de types complexes
par restriction
En plus de la dérivation par extension, la dérivation de
types complexes peut se faire par restriction des modèles de contenu.
La restriction de types complexes est conceptuellement la même que
celle des types simples et la différence est qu'elle implique l'utilisation
de déclarations de types alors qu'en ce qui concerne la restriction
des types simples, il s'agit le plus souvent de réduire la fourchette
des acceptables du contenu. Un type complexe dérivé par restriction
est très similaire à son type de base, excepté que
ses déclarations sont plus limitées que les déclarations
du type de base. En fait, les valeurs représentées par le
nouveau type sont un sous-ensemble des valeurs représentées
par le type de base (comme c'est le cas avec la restriction des types simples).
En d'autres termes, une application prévue pour l'ensemble des valeurs
du type de base s'exécutera sans difficultés sur les valeurs
du type restreint.
<complexType name="ConfirmedItems">
<complexContent>
<restriction base="ipo:Items">
<sequence>
<!-- item élément est different than in Items -->
<element name="item" minOccurs="1" maxOccurs="unbounded">
<!-- remainder de définition est same comme Items -->
<complexType>
<sequence>
<element name="productName" type="string"/>
<element name="quantity">
<simpleType>
<restriction base="positiveInteger">
<maxExclusive value="100"/>
</restriction>
</simpleType>
</element>
<element name="USPrice" type="decimal"/>
<element ref="ipo:comment" minOccurs="0"/>
<element name="shipDate" type="date" minOccurs="0"/>
</sequence>
<attribute name="partNum" type="ipo:SKU" use="required"/>
</complexType>
</element>
</sequence>
</restriction>
</complexContent>
</complexType>
Tableau 3. Exemples
de restriction
Base
Restriction
Remarques
default="1"
initialisation d'une valeur par défaut lorsque aucune était
précédemment donnée
fixed="100"
initialisation d'une valeur fixée lorsque aucune était
précédemment donnée
type="string"
spécification d'un type lorsque aucun n'était précédemment
donné
(minOccurs, maxOccurs)
(minOccurs, maxOccurs)
(0, 1)
(0, 0)
exclusion d'un composant optionnel ; cela peut aussi être réalisé
en omettant la déclaration du composant de la définition
du type réduit
(0, unbounded)
(0, 0) (0, 37)
(1, 9)
(1, 8) (2, 9) (4, 7) (3, 3)
(1, unbounded)
(1, 12) (3, unbounded) (6, 6)
(1, 1)
-
ne peut pas restreindre plus minOccurs
et maxOccurs dans ce cas là
4.5 Redéfinition de types et de groupes
Le chapitre 4.1 décrit la manière
d'inclure des définitions et des déclarations réparties
dans plusieurs fichiers de schémas mais ayant tous en commun le
même espace de noms cible. Le mécanisme include
permettait alors d'utiliser "tel-quel" les composants importés de
la sorte, en clair, sans aucune modification. Les chapitres suivant expliquaient
les dérivations de type par extension et par restriction. Le mécanisme
redefine auquel nous allons nous
intéresser dans ce chapitre permet combiner l'inclusion et la restriction
de manière à pouvoir redéfinir des types simples ou
complexes, des groupes et des groupes d'attributs issus de fichiers de
schémas externes. Comme pour
include,
le mécanisme redefine requiert
que les composants externes soient dans le même espace de noms cible
que le schéma les accueillant, cela étant dit, les composants
issus de schémas externes sans espace de noms attribué peuvent
également être redéfinis. Dans ce dernier cas, les
composants redéfinis font partie intégrante de l'espace de
noms cible du schéma les accueillant.
<schema targetNamespace="http://www.example.com/IPO"
xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:ipo="http://www.example.com/IPO">
<!-- bring in address constructs -->
<redefine
schemaLocation="http://www.example.com/schemas/address.xsd">
<!-- redéfinition de Address -->
<complexType name="Address">
<complexContent>
<extension base="ipo:Address">
<sequence>
<element name="country" type="string"/>
</sequence>
</extension>
</complexContent>
</complexType>
</redefine>
<!-- etc. -->
</schema>
....
<shipTo exportCode="1" xsi:type="ipo:UKAddress">
<name>Helen Zoe</name>
<street>47 Eden Street</street>
<city>Cambridge</city>
<!-- country was added to Address which est base type de UKAddress -->
<country>United Kingdom</country>
<!-- postcode was added comme part de UKAddress -->
<postcode>CB1 1JR</postcode>
</shipTo>
....
4.6 Groupes de substitution
XML Schema fournit un mécanisme, appelé
groupes de substitution, qui permet aux éléments d'être
substitués par d'autres. Plus précisément, des éléments
peuvent être regroupé et déclarés, au niveau
du groupe résultant, substituables par un élément
dont on précise le nom. Cet élément de substitution
est appelé élément de tête et doit être
un élément global. Pour illustrer ce propos, nous déclarons
deux éléments appelés
customerComment et
shipComment et on les rattache à un groupe de substitution
dont l'élément de tête est comment. De la
sorte, customerComment et shipComment deviennent substituables
à l'élément comment, en clair, ils peuvent
être utilisés à n'importe quel endroit où nous
pouvons utiliser
comment. Les éléments d'un groupe
de substitution doivent avoir le même type que l'élément
de tête ou être d'un type dérivé du type de l'élément
de tête. Pour déclarer ces deux nouveaux éléments
et pour les rendre substituable à l'élément comment,
nous utilisons la syntaxe suivante :
<element name="shipComment" type="string"
substitutionGroup="ipo:comment"/>
<element name="customerComment" type="string"
substitutionGroup="ipo:comment"/>
....
<items>
<item partNum="833-AA">
<productName>Lapis necklace</productName>
<quantity>1</quantity>
<USPrice>99.95</USPrice>
<ipo:shipComment>
Use gold wrap si possible
</ipo:shipComment>
<ipo:customerComment>
Want this pour the holidays!
</ipo:customerComment>
<shipDate>1999-12-05</shipDate>
</item>
</items>
....
4.7 Eléments et types abstraits
XML Schema fournit un mécanisme pour forcer
la substitution d'un élément ou d'un type en particulier.
Quand un élément ou un type est déclaré comme
étant "abstrait", il ne peut pas être utilisé dans
une instance de document. Quand un élément est abstrait,
un membre du groupe de substitution de cet élément doit apparaître
dans une instance de document. Quand la définition type correspondant
à un élément est déclarée abstraite,
toutes les instances de cet élément doivent utiliser le constructeur
xsi:type pour faire référence
à un type dérivé qui ne soit pas abstrait.
<element name="comment" type="string" abstrait="true"/>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://cars.example.com/schema"
xmlns:target="http://cars.example.com/schema">
<complexType name="Vehicle" abstrait="true"/>
<complexType name="Car">
<complexContent>
<extension base="target:Vehicle"/>
</complexContent>
</complexType>
<complexType name="Plane">
<complexContent>
<extension base="target:Vehicle"/>
</complexContent>
</complexType>
<element name="transport" type="target:Vehicle"/>
</schema>
<transport xmlns="http://cars.example.com/schema"/>
<transport xmlns="http://cars.example.com/schema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:type="Car"/>
4.8 Contrôler la création
et l'utilisation de types dérivés
Jusqu'à maintenant, nous avons été
capable de dériver de nouveaux types et de les utiliser dans les
instances de documents sans aucune restriction. En réalité,
les auteurs de schémas voudront parfois contrôler les dérivations
de certains types en particulier et l'utilisation de types dérivés
dans les instances.
<complexType name="Address" final="restriction">
<sequence>
<element name="name" type="string"/>
<element name="street" type="string"/>
<element name="city" type="string"/>
</sequence>
</complexType>
<simpleType name="Postcode">
<restriction base="string">
<length value="7" fixed="true"/>
</restriction>
</simpleType>
<simpleType name="UKPostcode">
<restriction base="ipo:Postcode">
<pattern value="[A-Z]{2}\d\s\d[A-Z]{2}"/>
</restriction>
</simpleType>
<simpleType name="UKPostcode">
<restriction base="ipo:Postcode">
<pattern value="[A-Z]{2}\d\d[A-Z]{2}"/>
<!-- illegal attempt to modify facet fixed in base type -->
<length value="6" fixed="true"/>
</restriction>
</simpleType>
<complexType name="Address" block="restriction">
<sequence>
<element name="name" type="string"/>
<element name="street" type="string"/>
<element name="city" type="string"/>
</sequence>
</complexType>
5. Concepts avancés III : un rapport
trimestriel
Les applications de dépôt de commande d'achat et de facturation
sont susceptibles de donner lieu à une production de rapports synthétisant
le nombre de produits vendus par région. Un exemple d'un tel rapport,
couvrant la période du quatrième trimestre de l'année
1999, se trouve dans le fichier
4Q99.xml.
<purchaseReport
xmlns="http://www.example.com/Report"
period="P3M" periodEnding="1999-12-31">
<regions>
<zip code="95819">
<part number="872-AA" quantity="1"/>
<part number="926-AA" quantity="1"/>
<part number="833-AA" quantity="1"/>
<part number="455-BX" quantity="1"/>
</zip>
<zip code="63143">
<part number="455-BX" quantité="4"/>
</zip>
</regions>
<parts>
<part number="872-AA">Lawnmower</part>
<part number="926-AA">Baby Monitor</part>
<part number="833-AA">Lapis Necklace</part>
<part number="455-BX">Sturdy Shelves</part>
</parts>
</purchaseReport>
<schema targetNamespace="http://www.example.com/Report"
xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:r="http://www.example.com/Report"
xmlns:xipo="http://www.example.com/IPO"
elementFormDefault="qualified">
<!-- pour SKU -->
<import namespace="http://www.example.com/IPO"/>
<annotation>
<documentation xml:lang="en">
Report schema for Example.com
Copyright 2000 Example.com. All rights reserved.
</documentation>
</annotation>
<element name="purchaseReport">
<complexType>
<sequence>
<element name="regions" type="r:RegionsType">
<keyref name="dummy2" refer="r:pNumKey">
<selector xpath="r:zip/r:part"/>
<field xpath="@number"/>
</keyref>
</element>
<element name="parts" type="r:PartsType"/>
</sequence>
<attribute name="period" type="duration"/>
<attribute name="periodEnding" type="date"/>
</complexType>
<unique name="dummy1">
<selector xpath="r:regions/r:zip"/>
<field xpath="@code"/>
</unique>
<key name="pNumKey">
<selector xpath="r:parts/r:part"/>
<field xpath="@number"/>
</key>
</element>
<complexType name="RegionsType">
<sequence>
<element name="zip" maxOccurs="unbounded">
<complexType>
<sequence>
<element name="part" maxOccurs="unbounded">
<complexType>
<complexContent>
<restriction base="anyType">
<attribute name="number" type="xipo:SKU"/>
<attribute name="quantity" type="positiveInteger"/>
</restriction>
</complexContent>
</complexType>
</element>
</sequence>
<attribute name="code" type="positiveInteger"/>
</complexType>
</element>
</sequence>
</complexType>
<complexType name="PartsType">
<sequence>
<element name="part" maxOccurs="unbounded">
<complexType>
<simpleContent>
<extension base="string">
<attribute name="number" type="xipo:SKU"/>
</extension>
</simpleContent>
</complexType>
</element>
</sequence>
</complexType>
</schema>
5.1 Spécification d'unicité
XML Schema permet de spécifier la contrainte
d'unicité de toute valeur d'attribut ou d'élément
à l'intérieur d'un périmètre défini.
Pour indiquer que la valeur d'un attribut ou d'un élément
en particulier est unique, nous utilisons l'élément unique.
Il permet d'une part de sélectionner un ensemble d'éléments
et ainsi de définir le périmètre d'applicabilité
de la contrainte d'unicité et d'autre part d'identifier le "champ"
de l'attribut ou de l'élément qui doit être unique
à l'intérieur du périmètre défini. Dans
le cas du schéma de notre rapport, report.xsd,
l'attribut xpath de l'élément
selector contient une expression
XPath qui est regions/zip qui retourne la liste de tous les éléments
zip
d'une instance du rapport. De même, l'attribut xpath
de l'élément field
contient une seconde expression XPath,
@code, qui spécifie
que les valeurs de l'attribut
code des éléments
retournés doivent être uniques. Remarquez comment les expressions
XPath limitent la portée de ce qui doit être unique. En effet,
le rapport peut contenir un autre attribut code mais cette valeur
ne sera pas prise en compte dans le calcul d'unicité puisqu'elle
réside à l'extérieur du périmètre défini
par la première expressions XPath. Remarquez aussi que les expressions
XPath que vous pouvez utiliser dans l'attribut xpath
sont limitées à un sous-ensemble
de l'ensemble du langage XPath défini dans XML
Path Language 1.0. (remarque de traduction : une version française
de cette recommandation existe également).
<unique name="dummy1">
<selector xpath="r:regions/r:zip"/>
<field xpath="@code"/>
<field xpath="r:part/@number"/>
</unique>
5.2 Définition des clés
et de leurs références
Dans le rapport des ventes trimestrielles de 1999,
la
description de chaque pièce facturée n'apparaît
qu'une fois. Nous pourrions renforcer cette contrainte en utilisant l'élément
unique mais nous souhaitons aussi
garantir la présence d'une description de pièce pour chaque
couple pièce-quantité listé sous un code zip. Nous
renforçons la contrainte en utilisant les éléments
key et keyref.
Le schéma du rapport, report.xsd,
montre que les constructions
key et
keyref sont appliquées en
utilisant presque la même syntaxe que unique.
L'élément clé s'applique à la valeur de l'attribut
number des éléments part, enfants de l'élément
parts. Le fait de déclarer que l'attribut number
est une clé signifie que sa valeur doit être unique et ne
peut pas être initialisée à nil (c'est à
dire qu'elle est forcément renseignée) et le nom associé
à la clé,
pNumKey, la rend référençable
de n'importe où.
5.3 Contraintes de XML Schema par
rapport aux attributs ID de XML 1.0
XML 1.0 fournit
un mécanisme de contrôle d'unicité via les attributs
de type ID, IDREF et IDREFS. Il existe aussi dans XML Schema au travers
des types simples ID, IDREF,
et
IDREFS qui permettent de déclarer
des attributs de type XML 1.0. Mais XML Schema introduit des mécanismes
complémentaires plus souples et plus puissants. Par exemple, les
règles d'unicité peuvent être appliquée à
tout contenu d'élément ou d'attribut, quelqu'en soit leurs
types. A l'inverse, ID est un type de la déclaration
attribute
et ne peut s'appliquer aux attributs (ndlr : la phrase semble être
une erreur mais c'est écrit tel quel dans le texte original anglais),
aux éléments ou à leurs contenus. XML Schema permet
de spécifier le périmètre de confinement de l'unicité
alors que celui d'un ID est toujours le document dans sa totalité.
Finalement, XML Schema permet de créer des types key
et keyref en relation avec le contenu
des éléments et des attributs alors que ID ne propose pas
ces facilités.
5.4 Importation de types
Le schéma du rapport, report.xsd,
fait appel au type simple appelé
xipo:SKU, défini
dans un autre schéma et dans un autre espace de noms cible. Nous
rappelons que nous avons utilisé include
pour que le schéma ipo.xsd intègre
les définitions et des déclarations de address.xsd.
Ici, nous ne pouvons pas utiliser include
puisque include ne s'applique qu'à
des schémas externes de même espace de noms cible. Il s'ensuit
que l'élément include
ne permet pas d'identifier des espaces de noms cibles spécifiques
(bien que ce mécanisme ait besoin d'un
schemaLocation).
Le mécanisme d'import que nous décrivons dans ce chapitre
est important car il permet aux composants de schémas issus de différents
espaces de noms cibles d'être utilisés ensemble. Cela offre
la possibilité de valider des contenus d'instances de documents
écrites avec des composants définis à travers plusieurs
espaces de noms.
<element ref="xipo:comment"/>
<element ref="xipo:shipTo"/>
<complexType name="Analyst">
<complexContent>
<extension base="xipo:USAddress">
<sequence>
<element name="phone" type="string"/>
<element name="email" type="string"/>
</sequence>
</extension>
</complexContent>
</complexType>
<purchaseReport
xmlns="http://www.example.com/Report"
period="P3M" periodEnding="1999-12-31">
<!-- regions et parts éléments omitted -->
<analyst>
<name>Wendy Uhro</name>
<street>10 Corporate Towers</street>
<city>San Jose</city>
<state>CA</state>
<zip>95113</zip>
<phone>408-271-3366</phone>
<email>uhro@exemple.com</email>
</analyst>
</purchaseReport>
5.4.1 Bibliothèques de types
Au fur et à mesure que XML schemas deviendra plus largement utilisé,
les auteurs de schémas voudront créer des types simples et
complexes qui puissent être partagés et utilisés entre
différents schemas. XML Schemas fournit déjà des types
qui jouent ce rôle, en particulier, les types décrits dans
l'annexe des types simples et dans la présentation
des bibliothèques
de types.
<schema targetNamespace="http://www.example.com/Currency"
xmlns:c="http://www.example.com/Currency"
xmlns="http://www.w3.org/2001/XMLSchema">
<annotation>
<documentation xml:lang="en">
Definition of Currency type based on ISO 4217
</documentation>
</annotation>
<complexType name="Currency">
<simpleContent>
<extension base="decimal">
<attribute name="name">
<simpleType>
<restriction base="string">
<enumeration value="AED">
<annotation>
<documentation xml:lang="en">
United Arab Emirates: Dirham (1 Dirham = 100 Fils)
</documentation>
</annotation>
</enumeration>
<enumeration value="AFA">
<annotation>
<documentation xml:lang="en">
Afghanistan: Afghani (1 Afghani = 100 Puls)
</documentation>
</annotation>
</enumeration>
<enumeration value="ALL">
<annotation>
<documentation xml:lang="en">
Albania, Lek (1 Lek = 100 Qindarka)
</documentation>
</annotation>
</enumeration>
<!-- et other currencies -->
</restriction>
</simpleType>
</attribute>
</extension>
</simpleContent>
</complexType>
</schema>
<convertFrom name="AFA">199.37</convertFrom>
5.5 Eléments et attributs any
Dans les chapitres précédents nous avons vu plusieurs mécanismes
permettant d'étendre les modèles de contenu des types complexes.
Par exemple, un modèle de contenu mixte peut contenir un mélange
de caractères de données et d'éléments mais
un modèle de contenu peut également contenir des éléments
dont les types sont issus d'espaces de noms externes. Ces mécanismes
offrent respectivement des contraintes très lâches ou très
strictes. Le but de ce chapitre est de décrire un mécanisme
souple qui permette aux modèles de contenu d'être étendus
par n'importe quel élément et attribut des espaces de noms
spécifiés.
<purchaseReport
xmlns="http://www.example.com/Report"
period="P3M" periodEnding="1999-12-31">
<regions>
<!-- part sales listed par zip code, data from 4Q99.xml -->
</regions>
<parts>
<!-- part descriptions from 4Q99.xml -->
</parts>
<htmlExemple>
<table xmlns="http://www.w3.org/1999/xhtml"
border="0" width="100%">
<tr>
<th align="left">Zip Code</th>
<th align="left">Part nombre</th>
<th align="left">quantité</th>
</tr>
<tr><td>95819</td><td> </td><td> </td></tr>
<tr><td> </td><td>872-AA</td><td>1</td></tr>
<tr><td> </td><td>926-AA</td><td>1</td></tr>
<tr><td> </td><td>833-AA</td><td>1</td></tr>
<tr><td> </td><td>455-BX</td><td>1</td></tr>
<tr><td>63143</td><td> </td><td> </td></tr>
<tr><td> </td><td>455-BX</td><td>4</td></tr>
</table>
</htmlExemple>
</purchaseReport>
<element name="purchaseReport">
<complexType>
<sequence>
<element name="regions" type="r:RegionsType"/>
<element name="parts" type="r:PartsType"/>
<element name="htmlExemple">
<complexType>
<sequence>
<any namespace="http://www.w3.org/1999/xhtml"
minOccurs="1" maxOccurs="unbounded"
processContents="skip"/>
</sequence>
</complexType>
</element>
</sequence>
<attribute name="period" type="duration"/>
<attribute name="periodEnding" type="date"/>
</complexType>
</element>
<xsd:complexType name="text">
<xsd:complexContent mixed="true">
<xsd:restriction base="xsd:anyType">
<xsd:sequence>
<xsd:any processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
<xsd:attribute ref="xml:lang"/>
</xsd:restriction>
</xsd:complexContent>
</xsd:complexType>
<element name="htmlExemple">
<complexType>
<sequence>
<any namespace="http://www.w3.org/1999/xhtml"
minOccurs="1" maxOccurs="unbounded"
processContents="skip"/>
</sequence>
<anyAttribute namespace="http://www.w3.org/1999/xhtml"/>
</complexType>
</element>
....
<htmlExemple xmlns:h="http://www.w3.org/1999/xhtml"
h:href="http://www.example.com/reports/4Q99.html">
<!-- HTML markup here -->
</htmlExemple>
....
5.6 attribut schemaLocation
XML Schema utilise les attributs schemaLocation
et xsi:schemaLocation
dans trois cas de figures.
<purchaseReport
xmlns="http://www.example.com/Report"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.example.com/Report
http://www.example.com/Report.xsd"
period="P3M" periodEnding="1999-12-31">
<!-- etc. -->
</purchaseReport>
5.7 Conformité
une instance de document peut être contrôlée vis à
vis d'un schéma pour vérifier si les règles qui y
sont spécifiées sont appliquées dans l'instance. Ce
traitement fait classiquement deux choses, (1) il contrôle la conformité
aux règles, processus appelé validation du schéma
et (2) il ajoute des informations supplémentaires qui ne sont pas
présentes originellement dans l'instance, comme par exemple des
types et des valeurs par défaut, et qui sont appelées informations
de contribution.
A Remerciements
Beaucoup de personnes ont contribué par des idées, de la
matière et des remarques à l'élaboration de ce document,
ce qui en a considérablement amélioré la qualité.
En particulier, l'éditeur met en exergue les apports de David Beech,
Paul Biron, Don Box, Allen Brown, David Cleary, Dan Connolly, Roger Costello,
Martin Dürst, Martin Gudgin, Dave Hollander, Joe Kesselman, John McCarthy,
Andrew Layman, Eve Maler, Ashok Malhotra, Noah Mendelsohn, Michael Sperberg-McQueen,
Henry Thompson, Misha Wolf, et Priscilla Walmsley pour la validation des
exemples cités.
B Types simples et leurs facettes
Les valeurs légales de chaque type simple peuvent être contraintes
par l'application d'une ou plusieurs facettes. Les tableaux B1.a et B1.b
listent tous les types simples pré-définis de XML Schema
et les facettes applicables à chacun. Les noms des types simples
et les facettes sont liées entre les tableaux et leurs descriptions
correspondantes dans XML
Schema Partie 2 : types de données
Tableau B1.a. Types simples et facettes applicables
Types simples
Facettes
length
minLength
maxLength
pattern
enumeration
whiteSpace
string
y
y
y
y
y
y
normalizedString
y
y
y
y
y
y
token
y
y
y
y
y
y
byte
y
y
y
unsignedByte
y
y
y
base64Binary
y
y
y
y
y
y
hexBinary
y
y
y
y
y
y
integer
y
y
y
positiveInteger
y
y
y
negativeInteger
y
y
y
nonNegativeInteger
y
y
y
nonPositiveInteger
y
y
y
int
y
y
y
unsignedInt
y
y
y
long
y
y
y
unsignedLong
y
y
y
short
y
y
y
unsignedShort
y
y
y
decimal
y
y
y
float
y
y
y
double
y
y
y
boolean
y
y
time
y
y
y
dateTime
y
y
y
duration
y
y
y
date
y
y
y
gMonth
y
y
y
gYear
y
y
y
gYearMonth
y
y
y
gDay
y
y
y
gMonthDay
y
y
y
Name
y
y
y
y
y
y
QName
y
y
y
y
y
y
NCName
y
y
y
y
y
y
anyURI
y
y
y
y
y
y
language
y
y
y
y
y
y
ID
y
y
y
y
y
y
IDREF
y
y
y
y
y
y
IDREFS
y
y
y
y
y
ENTITY
y
y
y
y
y
y
ENTITIES
y
y
y
y
y
NOTATION
y
y
y
y
y
y
NMTOKEN
y
y
y
y
y
y
NMTOKENS
y
y
y
y
y
Tableau B1.b. Types simples et facettes applicables
Simple Types
Facets
max
Inclusivemax
Exclusivemin
Inclusivemin
ExclusivetotalDigits
fractionDigits
byte
y
y
y
y
y
y
unsignedByte
y
y
y
y
y
y
integer
y
y
y
y
y
y
positiveInteger
y
y
y
y
y
y
negativeInteger
y
y
y
y
y
y
nonNegativeInteger
y
y
y
y
y
y
nonPositiveInteger
y
y
y
y
y
y
int
y
y
y
y
y
y
unsignedInt
y
y
y
y
y
y
long
y
y
y
y
y
y
unsignedLong
y
y
y
y
y
y
short
y
y
y
y
y
y
unsignedShort
y
y
y
y
y
y
decimal
y
y
y
y
y
y
float
y
y
y
y
double
y
y
y
y
time
y
y
y
y
dateTime
y
y
y
y
duration
y
y
y
y
date
y
y
y
y
gMonth
y
y
y
y
gYear
y
y
y
y
gYearMonth
y
y
y
y
gDay
y
y
y
y
gMonthDay
y
y
y
y
C Utilisation des entités
XML 1.0 fournit différents types d'entités qui sont des fragments
de contenu étiquetés qui peuvent être utilisé
tant pour l'écriture de DTD (les entités paramètre)
que les instances de documents. Au chapitre 2.7,
nous expliquons comment des groupes nommés offrent une fonctionnalité
voisine de celle offerte par les entités paramètres. Dans
ce chapitre nous montrons comment les entités peuvent être
déclarées dans les instances de documents et comment les
équivalents fonctionnels des entités peuvent être déclarés
dans les schémas.
<?xml version="1.0" ?>
<!DOCTYPE PurchaseOrder [
<!ENTITY eacute "é">
]>
<purchaseOrder xmlns="http://www.example.com/PO1"
orderDate="1999-10-20>
<!-- etc. -->
<city>Montréal</city>
<!-- etc. -->
</purchaseOrder>
<xsd:element name="eacute" type="xsd:token" fixed="é"/>
<?xml version="1.0" ?>
<purchaseOrder xmlns="http://www.example.com/PO1"
xmlns:c="http://www.example.com/characterLes éléments"
orderDate="1999-10-20>
<!-- etc. -->
<city>Montr<c:eacute/>al</city>
<!-- etc. -->
</purchaseOrder>
D Expressions régulières
La facette pattern de XML Schema
utilise le langage des expressions régulières qui supporte
Unicode.
Il est totalement décrit dans XML
Schema tome 2. Le langage est similaire à celui utilisé
dans le langage
de programmation Perl, bien que les expressions soient mises en correspondance
avec une représentation lexicale complète plutôt qu'au
travers d'une représentation du niveau utilisateur comme c'est le
cas par exemple avec les notions de ligne et de paragraphe. Pour cette
raison, le langage d'expression ne contient pas les métacaractères
^ et $, bien que ^ soit utilisé pour exprimer les exclusions, par
exemple [^0-9]x.
Table D1. Exemples
d'expressions régulières
Expression
Exemples de correspondance(s)
chapitre \d
chapitre 0, chapitre 1, chapitre 2 ....
chapitre\s\d
chapitre suivi par un seul caractère espace blanc (espace, tabulation,
retour à la ligne, etc.) suivi par un seul chiffre
chapitre\s\w
chapitre suivi par un seul caractère espace blanc (espace, tabulation,
retour à la ligne, etc.), suivi par un caractère de mot (Chiffre
ou lettre tel que défini dans XML 1.0)
Espanñola
Española
\p{Lu}
tout caractère majuscule, la valeur de \p{} (par exemple
"Lu") est défini par Unicode
\p{IsGreek}
tout caractère grec, la forme 'Is' peut être
appliquée à tout nom (par exemple "Greek") tel que défini
par Unicode
\P{IsGreek}
tout caractère non grec, la forme 'Is' peut être
appliqué à tout nom (par exemple "Greek") tel que défini
par Unicode
a*x
x, ax, aax, aaax ....
a?x
ax, x
a+x
ax, aax, aaax ....
(a|b)+x
ax, bx, aax, abx, bax, bbx, aaax, aabx, abax, abbx, baax, babx,
bbax, bbbx, aaaax ....
[abcde]x
ax, bx, cx, dx, ex
[a-e]x
ax, bx, cx, dx, ex
[-ae]x
-x, ax, ex
[ae-]x
ax, ex, -x
[^0-9]x
tout caractère autre qu'un chiffre suivi du caractère
x
\Dx
tout caractère autre qu'un chiffre suivi du caractère
x
.x
tout caractère suivi du caractère x
.*abc.*
1x2abc, abc1x2, z3456abchooray ....
ab{2}x
abbx
ab{2,4}x
abbx, abbbx, abbbbx
ab{2,}x
abbx, abbbx, abbbbx....
(ab){2}x
ababx
E Index
Index des attributs de XML Schema. Chaque nom d'attribut est suivi
par une ou plusieurs paires de références. Chacune est composée
d'un lien vers un des exemples de ce tome et d'un lien vers la description
XML formelle se trouvant soit dans le tome "Structures" soit le
tome "Types de données"(Datatypes) de la spécification
XML Schema.
Les types simples de XML Schema sont décrits dans le tableau
2.