Introduction aux schémas XML

Rédaction : Fabien Torre, révision : Fred Mesnard.
Recommandations du W3C : intro, structure et types.

DTD versus schéma XML

Les DTD  :

Les schémas XML :

En pratique

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

Définitions de types, déclarations et modèles de contenu

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 :

Les types simples prédéfinis

Consulter :

Définir un nouveau type simple

Liste de valeurs d'un même type simple

<xs:simpleType name="telephone">
  <xs:list itemType="xs:integer" />
</xs:simpleType>

Union de types simples

<xs:simpleType name="contact">
  <xs:union memberTypes="adresse telephone" />
</xs:simpleType>

Restriction d'un type simple

consiste à ajouter des contraintes, appelées facettes, à un type de base, quelques exemples :

Déclarer un attribut

<xs:attribute name="score" type="xs:integer" use="required" default="0" />

Déclarer un élément simple

<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" />

Déclarer un élément complexe

contenu vide avec attribut

<xs:element name="br">
  <xs:complexType>
    <xs:attribute name="class" type="xs:string" />
  </xs:complexType>
</xs:element>

contenu simple avec attribut

<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>

contenu complexe

<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>

contenu mixte

<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>

Stratégies d'écriture d'un schéma

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.

Contraintes d'unicité et de clef

On peut toujours utiliser les ID, IDREF et IDREFS des DTD, mais aussi :

Unicité

<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.

Clés

<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é.

Référence

<xs:keyref name="refcleflivre" refer="cleflivre">
  <xs:selector xpath="livre"/>
  <xs:field xpath="ref"/>
</xs:keyref>

Exemple

<?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>

Commenter un schéma XML

    
<xs:annotation>
	<xs:documentation>
            Voici un schéma qui ...
        </xs:documentation>
        <xs:appinfo source="http://www.des-infos-supplementaires.org"/>
    </xs:annotation>

Valid XHTML 1.0 Strict