Rédaction : Fabien Torre,
révision : Fred Mesnard.
Recommandations du W3C :
intro,
structure et
types.
Les DTD :
Les schémas XML :
Le fichier XML (mondoc.xml) :
<?xml version="1.0"?> <racine xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="monschema.xsd"> ... </racine>
Le fichier contenant le schéma (monschema.xsd) :
<?xml version="1.0"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> ... </xs:schema>
Exemple de validation : xmllint --schema monschema.xsd mondoc.xml
Les quatre constructions essentielles des schémas XML :
On distingue différents modèles de contenu pour un élément selon la nature de ses noeuds fils autorisés :
Consulter :
<xs:simpleType name="telephone"> <xs:list itemType="xs:integer" /> </xs:simpleType>
<xs:simpleType name="contact"> <xs:union memberTypes="adresse telephone" /> </xs:simpleType>
consiste à ajouter des contraintes, appelées facettes, à un type de base, quelques exemples :
<xs:simpleType name="jourSemaine"> <xs:restriction base="xs:string"> <xs:enumeration value="lundi" /> <xs:enumeration value="mardi" /> <xs:enumeration value="mercredi" /> <xs:enumeration value="jeudi" /> <xs:enumeration value="vendredi" /> <xs:enumeration value="samedi" /> <xs:enumeration value="dimanche" /> </xs:restriction> </xs:simpleType>
<xs:simpleType name="telephone"> <xs:restriction base="xs:string"> <xs:length value="10" /> </xs:restriction> </xs:simpleType>
<xs:simpleType name="motdepasse"> <xs:restriction base="xs:string"> <xs:minLength value="8" /> <xs:maxLength value="20" /> </xs:restriction> </xs:simpleType>
<xs:simpleType name="temperature"> <xs:restriction base="xs:integer"> <xs:minInclusive value="-15" /> <xs:maxInclusive value="+45" /> </xs:restriction> </xs:simpleType>
<xs:simpleType name="codepostal"> <xs:restriction base="xs:integer"> <xs:totalDigits value="5" /> </xs:restriction> </xs:simpleType>
<xs:simpleType name="prix"> <xs:restriction base="xs:decimal"> <xs:fractionDigits value="2" /> </xs:restriction> </xs:simpleType>
<xs:simpleType name="mail"> <xs:restriction base="xs:string"> <xs:pattern value=".+@.+" /> </xs:restriction> </xs:simpleType>
<xs:attribute name="score" type="xs:integer" use="required" default="0" />
<xs:element name="nom" type="xs:string" /> <xs:element name="prénom" minOccurs="1" maxOccurs="unbounded" type="xs:string" /> <xs:element name="surnom" minOccurs="0" maxOccurs="1" type="xs:string" />
<xs:element name="br"> <xs:complexType> <xs:attribute name="class" type="xs:string" /> </xs:complexType> </xs:element>
<xs:element name="title"> <xs:complexType> <xs:simpleContent> <xs:extension base="xs:string"> <xs:attribute name="lang" type="xs:language" use="required"/> </xs:extension> </xs:simpleContent> </xs:complexType> </xs:element>
Le type language
est prédéfini par le motif
([a-zA-Z]{1,8})(-[a-zA-Z0-9]{1,8})*
. La valeur de l'attribut
use
impose la présence de l'attribut lang
.
Les autres valeurs possibles sont optional
(par défaut) et prohibited
.
Voici une instance valide :
<title lang="en"> XML in easy steps <title>
<xs:element name="auteur"> <xs:complexType> <xs:sequence> <xs:element name="nom" type="xs:string" /> <xs:element name="prénom" minOccurs="1" maxOccurs="unbounded" type="xs:string" /> <xs:element name="surnom" minOccurs="0" maxOccurs="1" type="xs:string" /> </xs:sequence> </xs:complexType> </xs:element>
<xs:element name="p"> <xs:complexType mixed="true"> <xs:choice minOccurs="0" maxOccurs="unbounded"> <xs:element name="em" type="xs:string" /> <xs:element name="code" type="xs:string" /> </xs:choice> </xs:complexType> </xs:element>
Pour la DTD suivante :
<!ELEMENT CHAMPIONNAT (JOURNEE+)> <!ELEMENT JOURNEE (RENCONTRE+)> <!ELEMENT RENCONTRE EMPTY> <!ATTLIST CHAMPIONNAT DIVISION CDATA #REQUIRED SAISON CDATA #REQUIRED> <!ATTLIST JOURNEE NUMERO CDATA #REQUIRED DATE CDATA #REQUIRED> <!ATTLIST RENCONTRE DOMICILE CDATA #REQUIRED EXTERIEUR CDATA #REQUIRED SCORED CDATA #REQUIRED SCOREE CDATA #REQUIRED>
en suivant l'arborescence des documents :
<?xml version="1.0"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:element name="CHAMPIONNAT"> <xs:complexType> <xs:sequence> <xs:element name="JOURNEE" maxOccurs="38"> <xs:complexType> <xs:sequence> <xs:element name="RENCONTRE" maxOccurs="10"> <xs:complexType> <xs:attribute name="DOMICILE" type="xs:string" /> <xs:attribute name="EXTERIEUR" type="xs:string" /> <xs:attribute name="SCORED" type="xs:string" /> <xs:attribute name="SCOREE" type="xs:string" /> </xs:complexType> </xs:element> </xs:sequence> <xs:attribute name="NUMERO" type="xs:integer" /> <xs:attribute name="DATE" type="xs:string" /> </xs:complexType> </xs:element> </xs:sequence> <xs:attribute name="DIVISION" type="xs:integer" /> <xs:attribute name="SAISON" type="xs:string" /> </xs:complexType> </xs:element> </xs:schema>
ou à plat avec références aux éléments déjà définis :
<?xml version="1.0"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:attribute name="DOMICILE" type="xs:string" /> <xs:attribute name="EXTERIEUR" type="xs:string" /> <xs:attribute name="SCORED" type="xs:string" /> <xs:attribute name="SCOREE" type="xs:string" /> <xs:attribute name="NUMERO" type="xs:integer" /> <xs:attribute name="DATE" type="xs:string" /> <xs:attribute name="DIVISION" type="xs:integer" /> <xs:attribute name="SAISON" type="xs:string" /> <xs:element name="RENCONTRE"> <xs:complexType> <xs:attribute ref="DOMICILE" /> <xs:attribute ref="EXTERIEUR" /> <xs:attribute ref="SCORED" /> <xs:attribute ref="SCOREE" /> </xs:complexType> </xs:element> <xs:element name="JOURNEE"> <xs:complexType> <xs:sequence> <xs:element ref="RENCONTRE" maxOccurs="10" /> </xs:sequence> <xs:attribute ref="NUMERO" /> <xs:attribute ref="DATE" /> </xs:complexType> </xs:element> <xs:element name="CHAMPIONNAT"> <xs:complexType> <xs:sequence> <xs:element ref="JOURNEE" maxOccurs="38" /> </xs:sequence> <xs:attribute ref="DIVISION" /> <xs:attribute ref="SAISON" /> </xs:complexType> </xs:element> </xs:schema>
La première stratégie contraint l'élément racine, pas la seconde. La seconde est plus modulaire et permet de réutiliser des parties du schéma.
On peut toujours utiliser les ID, IDREF et IDREFS des DTD, mais aussi :
<xs:element name="bibliotheque"> <xs:complexType> ... </xs:complexType> <xs:unique name="uniquelivre"> <xs:selector xpath="livre" /> <xs:field xpath="isbn" /> </xs:unique> </xs:element>
Si l'élément isbn
est présent pour un livre, alors sa valeur est unique
parmi toutes les valeurs de l'élément isbn
des livres de la bibliothèque.
<xs:element name="bibliotheque"> <xs:complexType> ... </xs:complexType> <xs:key name="cleflivre"> <xs:selector xpath="livre" /> <xs:field xpath="isbn" /> </xs:key> </xs:element>
Idem unique
mais avec présence obligatoire de la clé.
<xs:keyref name="refcleflivre" refer="cleflivre"> <xs:selector xpath="livre"/> <xs:field xpath="ref"/> </xs:keyref>
<?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:element name="livre"> <xs:complexType> <xs:sequence> <xs:element name="titre" type="xs:string"/> <xs:element name="auteur" type="xs:string" maxOccurs="unbounded"/> <xs:element name="isbn" type="xs:string"/> <xs:element name="ref" type="xs:string" minOccurs="0"/> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="bibliotheque"> <xs:complexType> <xs:sequence> <xs:element ref="livre" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:key name="unique-isbn"> <xs:selector xpath="livre"/> <xs:field xpath="isbn"/> </xs:key> <xs:keyref refer="unique-isbn" name="ref-isbn"> <xs:selector xpath="livre"/> <xs:field xpath="ref"/> </xs:keyref> </xs:element> </xs:schema>
<xs:annotation> <xs:documentation> Voici un schéma qui ... </xs:documentation> <xs:appinfo source="http://www.des-infos-supplementaires.org"/> </xs:annotation>