Schémas XML
-
Le langage de DTD a des inconvénients: syntaxe différente de
XML, pas de notion d'espace de noms (d'où risque de collisions entre
symboles importés et symboles définis localement), ...
-
En remplacement, le consortium W3 a défini la notion de schéma,
qui utilise la notation XML. (le "draft" paru le 7 avril 2000 a été
remplacé à plusieurs reprises et la dernière recommandation
date du 2 mai 2001). Ce qui suit est basé sur cette dernière
recommandation.
-
Un schéma doit permettre de spécifier le même genre
d'information qu'une DTD, c'est-à-dire la syntaxe d'une classe de
documents XML, en définissant les éléments et attributs
ainsi que les contraintes sur les valeurs de ceux-ci.
-
Un schéma est contenu dans un élément du genre:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
...
</xsd:schema>note: dans cet exemple, xsd est un préfixe choisi arbitrairement et qui va permettre d'accéder, dans l'élément xsd:schema, à tous les symboles définis dans la syntaxe des schémas.
- Pour chaque balise que l'on voudra utiliser dans son document, il faut définir l'élément correspondant dans le schéma. Cette définition devra aussi inclure les éventuels attributs que la balise peut contenir.
Définitions d'éléments
-
Chaque élément déclaré dans un schéma
a un type associé qui définit le genre de contenu que
l'élément en question peut avoir:
<xsd:element name="LeNomDeMonElement" type="LeTypeDeContenuDeCetElement">
-
Un élément ne contenant pas de sous-élément
ni d'attribut est considéré comme étant de
type simple (p.ex. <auteur>Bertrand
Ibrahim</auteur>). Un élément contenant soit des
sous-éléments (p.ex. <titre>Un journaliste
<souligne>accuse</souligne>, ...</titre>), soit des
attributs, ou même les deux à la fois est
considéré de type complexe.
-
Il existe des types simples
prédéfinis (voir section "3 Built-in datatypes"
(version du
W3C, copie
locale) de la spécification XML Schema Part 2: Datatypes
(version du W3C,
copie locale). Les plus couramment
utilisés sont: string, boolean, float, decimal, integer,
nonPositiveInteger, negativeInteger, nonNegativeInteger, positiveInteger,
duration, instant, time, timePeriod, date, gDay, gMonth, gYear, anyURI, ID,
IDREF, ENTITY, NOTATION, QName, Name, etc.
- Le type prédéfini anyType correspond à un contenu quelconque, simple ou complexe, sans contrainte aucune sur son contenu.
Définitions de types simples
-
Si l'on veut définir un nouveau type simple dérivé d'un
autre type simple (p.ex. type prédéfini), on utilisera
l'élément prédéfini de schémas
<xsd:simpleType ...> avec un contenu qui définira les détails
de la dérivation. Voici deux exemples de types dérivés
du type prédéfini string (chaîne de
caractères) et un exemple de type dérivé du type
integer (nombre entier):
<xsd:simpleType name="JourDeSemaine">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="lundi" />
<xsd:enumeration value="mardi" />
<xsd:enumeration value="mercredi" />
<xsd:enumeration value="jeudi" />
<xsd:enumeration value="vendredi" />
<xsd:enumeration value="samedi" />
<xsd:enumeration value="dimanche" />
</xsd:restriction>
</xsd:simpleType><xsd:simpleType name="AbregeSemaine">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="lu" />
<xsd:enumeration value="ma" />
<xsd:enumeration value="me" />
<xsd:enumeration value="je" />
<xsd:enumeration value="ve" />
<xsd:enumeration value="sa" />
<xsd:enumeration value="di" />
</xsd:restriction>
</xsd:simpleType><xsd:simpleType name="CodePostalCH">
<xsd:restriction base="xsd:integer">
<xsd:minInclusive value="1000" />
<xsd:maxInclusive value="9999" />
</xsd:restriction>
</xsd:simpleType> -
Les principales catégories de dérivation (création d'un
nouveau type à partir d'un type existant) sont: l'extension, la
restriction, l'union, les listes
- L'union permet de définir un nouveau type incluant toutes les valeurs possibles d'un certain nombre d'autres types. Par exemple, le type JrSemaine ci-dessous est défini à partir des types JourDeSemaine et AbregeSemaine définis précédemment et correspond à une chaîne de caractères indiquant un jour de la semaine ou un abrégé de jour de la semaine:
-
<xsd:simpleType name="JrSemaine">
<xsd:union memberTypes="JourDeSemaine AbregeSemaine" />
</xsd:simpleType> - La liste permet de définir un nouveau type à partir d'un type de base, où une valeur du nouveau type correspond à plusieurs valeurs du type de base séparées par un espace. Exemple:
-
<xsd:simpleType name="JoursDOuverture">
<xsd:list itemType="JrSemaine" />
</xsd:simpleType> - Une restriction limite les valeurs possibles d'un type donné (appelé type de base) et est définie sur certaines propriétés du type de base, appelées facettes (longueur, valeur minimale, valeur maximale, etc.). Voir l'appendice B du XML Schema Part 0: Primer (copie locale du 2 mai 2001). Exemple:
-
<xsd:simpleType name="JourDuMois">
<xsd:restriction base="xsd:integer">
<xsd:minInclusive value="1" />
<xsd:maxInclusive value="31" />
</xsd:restriction>
</xsd:simpleType> - Une extension consiste à définir un nouveau type à partir d'un type existant en lui ajoutant éventuellement des sous-éléments et/ou des attributs. Une extension produit donc toujours un type complexe. On en verra des exemples plus loin.
-
Pour déclarer un élément que l'on pourra utiliser dans
son document, on utilise l'élément de schéma
<xsd:element name="BaliseAUtiliser"
type="IdentificateurDuType" />. Par exemple,
<xsd:element name="OuvertureMagasin" type="JoursDOuverture" />
permettra d'avoir, dans un document:
<OuvertureMagasin>ma me je vendredi</OuvertureMagasin>
La définition <xsd:element name="OuvertureMagasin" type="JoursDOuverture" /> associe explicitement le type JoursDOuverture à l'élément OuvertureMagasin, définissant ainsi le type de contenu que peut avoir l'élément OuvertureMagasin. Cette définition est beaucoup plus précise que ce que permet le formalisme de DTD.
-
L'intérêt de définir un type séparément
de la définition d'un élément est que l'on peur
réutiliser le même type pour plusieurs éléments:
<xsd:complextype name="AdressePostale">
...
</xsd:complextype>
<xsd:element name="Domicile" type="AdressePostale" />
<xsd:element name="AdresseProfessionnelle" type="AdressePostale" />
Définitions de types complexes
-
Un type complexe est défini à l'aide de l'élément
<xsd:complexType name="..."> qui pourra contenir, entre autres, une
séquence d'éléments, une série d'attributs, etc.
On définit d'abord les sous-éléments, puis les attributs.
-
Exemple de contenu composé uniquement de sous-éléments:
- déclaration du type:
-
<xsd:complexType name="EnteteType">
<xsd:sequence>
<xsd:element name="titre" type="xsd:string" />
<xsd:element name="auteur" type="xsd:string" />
<xsd:element name="date" type="xsd:string" />
<xsd:element name="lieu" type="xsd:string" />
</xsd:sequence>
</xsd:complexType> - déclaration d'un élément de ce type:
- <xsd:element name="entete" type="EnteteType" />
- utilisation de l'élément dans un document XML:
-
<entete>
<titre>...</titre>
<auteur>...</auteur>
...
</entete>
-
Exemple de contenu composé uniquement d'attributs (contenu vide):
- déclaration du type:
-
<xsd:complexType name="ImageType">
<xsd:attribute name="src" type="xsd:anyURI" />
</xsd:complexType> - déclaration d'un élément de ce type:
- <xsd:element name="image" type="ImageType" />
- utilisation de l'élément dans un document XML:
- <image src="... UneURL ..." />
-
Exemple de contenu composé d'un contenu simple (simple suite de
caractères, sans sous-éléments) et d'attributs:
- déclaration du type:
-
<xsd:simpleType name="NombreDeuxDecimales">
<xsd:restriction base="xsd:decimal">
<xsd:fractionDigits value="2" />
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="PrixType">
<xsd:simpleContent>
<xsd:extension base="NombreDeuxDecimales">
<xsd:attribute name="monaie" type="xsd:string" />
</xsd:extension>
</xsd:simpleContent>
</xsd:complexType> - déclaration d'un élément de ce type:
- <xsd:element name="prix" type="PrixType" />
- utilisation de l'élément dans un document XML:
- <prix monaie="CHF">3.50</prix>
-
Exemple de contenu composé de caractères et de
sous-éléments (utilisation de l'attribut
mixed="true"):
- déclaration du type:
-
<xsd:complexType name="TexteType"
mixed="true">
<xsd:sequence>
<xsd:element name="grand" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
</xsd:sequence>
</xsd:complexType> - déclaration d'un élément de ce type:
- <xsd:element name="texte" type="TexteType" />
- utilisation de l'élément dans un document XML:
-
<texte>
<grand>Un journaliste de la place accuse</grand>
les autorités ...
</texte>
De par l'attribut mixed de l'élément xsd:complexType, l'élément texte pourra contenir du texte aussi bien qu'un nombre indéterminé de sous-éléments grand et image. De par sa déclaration, l'élément grand ne peut contenir que du texte simple.
-
Exemple de contenu composé uniquement de sous-éléments:
-
Le concept de type anonyme permet un raccourci d'écriture: au lieu
de définir un type puis de déclarer un élément
basé sur ce type, on peut donner les détails de la structure
directement dans la déclaration de l'élément. Exemple:
- déclaration de l'élément:
-
<xsd:element name="image">
<xsd:complexType>
<xsd:attribute name="src" type="xsd:anyURI" />
</xsd:complexType>
</xsd:element> - utilisation dans un document XML:
- <image src="... UneURL ..." />
-
Les attributs minOccurs et maxOccurs servent à indiquer,
pour chaque sous-élément, le nombre minimum et maximum
d'occurrences autorisées dans le contexte de l'élément
englobant. En cas d'absence de l'un ou l'autre de ces attribut, la valeur
par défaut est 1.
-
Il existe trois constructeurs pour définir les sous-éléments
d'un élément ou d'un type complexe donné:
-
sequence: les sous-éléments
énumérés doivent être tous présents dans
l'ordre indiqué. Le nombre d'occurences de chacun est
déterminé par les attributs minOccurs et maxOccurs. Exemples:
<xsd:complexType name="IllustrationType">
<xsd:sequence>
<xsd:any />
<xsd:element name="legende" type="TexteType" minOccurs="0" />
</xsd:sequence>
</xsd:complexType><xsd:complexType name="NomType">
<xsd:sequence>
<xsd:element name="Prenom" type="xsd:string" />
<xsd:element name="Nom" type="xsd:string" />
</xsd:sequence>
</xsd:complexType> -
choice: un seul des sous-éléments
énumérés doit être présent (exclusion
mutuelle). Le nombre d'occurences de chaque alternative est déterminé
par les attributs minOccurs et maxOccurs de la déclaration de chaque
sous-élément. Le nombre d'alternatives est déterminé
par les attributs minOccurs et maxOccurs de la balise <xsd:choice>
<xsd:complexType name="EnfantsType">
<xsd:choice minOccurs="0" maxOccurs="unbounded" >
<xsd:element name="fils" type="PersonneType" />
<xsd:element name="fille" type="PersonneType" />
</xsd:choice>
</xsd:complexType><xsd:complexType name="MesureType">
<xsd:choice >
<xsd:element name="blanche" type="NoteType" minOccurs="1" maxOccurs="1" />
<xsd:element name="Noire" type="NoteType" minOccurs="2" maxOccurs="2" />
</xsd:choice>
</xsd:complexType> -
all: les sous-éléments énumérés
doivent être tous présents au plus une fois, dans n'importe
quel ordre. Les attributs minOccurs et maxOccurs doivent valoir 0 ou 1.
<xsd:complexType name="NomType">
<xsd:all>
<xsd:element name="Prenom" type="xsd:string" />
<xsd:element name="Nom" type="xsd:string" />
</xsd:all>
</xsd:complexType>
-
sequence: les sous-éléments
énumérés doivent être tous présents dans
l'ordre indiqué. Le nombre d'occurences de chacun est
déterminé par les attributs minOccurs et maxOccurs. Exemples:
-
Le mécanisme d'extension permet de réutiliser un type
déjà défini, en lui ajoutant de nouvelles composantes
(sous-éléments ou attributs). Nous pouvons ainsi compléter
l'exemple du type EnteteType défini
plus haut pour créer le type ArticleType qui contienne en
plus un sous-élément texte qui pourra éventuellement
contenir du texte simple, 0, 1 ou plusieurs éléments
grand et image. On commencera par reprendre le type
TexteType vu précédemment
pour inclure le sous-élément image en plus du
sous-élément grand en définissant le type
TexteImageType:
<xsd:complexType name="TexteImageType" mixed="true">
<xsd:complexContent>
<xsd:extension base="TexteType">
<xsd:sequence>
<xsd:element name="image" type="IllustrationType" minOccurs="0" />
</xsd:sequence>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
On aurait bien entendu directement déclaré quelque chose d'équivalent sans extension:
<xsd:complexType name="TexteImageType" mixed="true">
<xsd:choice minOccurs="0" maxOccurs="unbounded" >
<xsd:element name="grand" type="xsd:string" />
<xsd:element name="image" type="IllustrationType" />
</xsd:choice>
</xsd:complexType>On va maintenant utiliser le nouveau type TexteImageType pour étendre le type EnteteType afin de définir le nouveau type ArticleType:
<xsd:complexType name="ArticleType">
<xsd:complexContent>
<xsd:extension base="EnteteType">
<xsd:sequence>
<xsd:element name="texte" type="TexteImageType" />
</xsd:sequence>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>On peut alors définir un élément article basé sur le type ArticleType:
<xsd:element name="article" type="ArticleType" />
et l'utiliser dans un document:
<article>
<titre>...</titre>
<auteur>...</auteur>
<date> ... </date>
<lieu> ... </lieu>
<texte>
<grand>Un journaliste de la place accuse</grand>
les autorités ...
<image>
<html:img src="..." />
<legende>...
</legende>
</image>
</texte>
</article>On voit, dans cet exemple, que l'élément texte doit être présent exactement une fois dans l'élément article (minOccurs et maxOccurs étant absents, ils vallent 1).
L'élément image peut apparaître un nombre indéterminé de fois. Une alternative pour le définir à partir de la balise <img> de HTML pourrait être:
<xsd:element name="image" minOccurs="0" maxOccurs="unbounded"
xmlns:html="http://www.w3.org/Profiles/XHTML-transitional" >
<xsd:complexType>
<xsd:element ref="html:img" />
<xsd:element name="legende" type="xsd:string" minOccurs="0" />
</xsd:complexType>
</xsd:element>Son contenu fait référence à des symboles HTML (attribut xmlns) qui seront préfixés par "html". Il doit contenir un et un seul sous-élément html:img et optionnellement un élément legende. La notation ref="html:img" que l'on utilise ici correspond à la réutilisation d'un élément déjà défini ailleurs, en l'occurrence l'élément img du langage HTML.
Définitions d'attributs dans un type complexe
-
Pour illustrer la définition d'attributs, reprenons l'exemple (2)
du début de ce cours:
<article titre="Un journaliste accuse, un policier dément" auteur="Alain Connu" date="14 juin 1972" lieu="banquise">...</article>
Le schéma correspondant serait:
<xsd:element name="article" >
<xsd:complexType>
... <!-- les attributs doivent être déclaré après les sous-éléments -->
<xsd:attribute name="titre" type="xsd:string" />
<xsd:attribute name="auteur" type="xsd:string" use="required" />
<xsd:attribute name="date" type="xsd:date" use="required" />
<xsd:attribute name="lieu" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element> -
Dans une déclaration d'attribut, l'attribut use peut prendre
les valeurs suivantes
valeur de l'attribut use signification prohibited l'attribut ainsi défini ne doit pas apparaître optional l'attribut peut apparaître au plus une fois required l'attribut doit apparaître - Si l'attribut use n'est pas utilisé, la valeur par défaut est optional.
autres attributs signification fixed si l'attribut ainsi défini est présent dans la balise, il ne peut prendre que la valeur associée à fixed. Exemple: <xsd:attribute name="..." type="xsd:decimal" fixed="0" />
default l'attribut peut ne pas être défini, auquel cas il prendra une valeur par défaut. Exemple: <xsd:attribute name="..." type="xsd:decimal" default="10" />
- fixed et default ne peuvent pas être utilisés simultanément
Création d'instances d'un schéma
-
De la même façon qu'un document XML peut faire référence
à une DTD selon laquelle ce document est structuré, un document
XML peut faire référence à un (ou plusieurs) schéma(s)
selon le(s)quel(s) ce document est structuré. La référence
se fait d'une des façons suivantes (dans ces exemples, l'URL relative
"UnFichier.xsd" peut être bien entendu remplacée par une URL
absolue):
<ElementRacine xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="UnURISymbolisantLEspaceDeNom UnFichier.xsd">
...
</ElementRacine><ElementRacine xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="UnFichier.xsd">
...
</ElementRacine>On utilisera la première forme lorsque le scéma contient la mention explicite d'un espace de nom à l'aide de l'attribut targetNamespace:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="UnURISymbolisantLEspaceDeNom">
...
</xsd:schema>
La syntaxe des schémas offre encore bien d'autres possibilités ...
- Outil de validation en-ligne de syntaxe de schémas
- Outil de conversion DTD-Schema (en Perl)
- XML Schema Part 0: Primer - (copie locale du 2 mai 2001)
- XML Schema Part 1: Structures - (copie locale du 2 mai 2001)
- XML Schema Part 2: Datatypes - (copie locale du 2 mai 2001)
- Les schémas XML, par Grégory Chazalon et Joséphine Lemoine
- XML Schemas: Best Practice, par Roger L. Costello
- XML Schema Tutorial, par Roger L. Costello