site de Fabien Torre


Cours sur l'écriture de XML Schémas

Comment définir un XML Schéma : types, modèles de contenu, éléments et imbrication, attributs, etc.

DTD versus XML Schéma

Les DTD :

  • types pauvres, peu de contraintes sur les contenus
  • nombre d'apparitions d'un élément à choisir entre 0 et 1
  • pas de gestion des espaces de noms
  • pas un format XML

Les schémas :

  • utilisation et définition de types, contraintes sur les contenus
  • possibilité de définir précisément le nombre d'apparitions d'un élément
  • espaces de noms supportés
  • format XML, parsable facilement

La base pratique

Le fichier XML :

<racine
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:noNamespaceSchemaLocation="monschema.xsd">
        .
        .
        .
</racine>

Le fichier contenant le schéma (.xsd) :

<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
        .
        .
        .
</xs:schema>

La validation avec xmllint par exemple :

xmllint --schema monschema.xsd undoc.xml

Modèles de contenu et types

On distingue deux familles de types :

  • les simples qui caractérisent le contenu d'un noeud textuel ou d'un attribut ;
  • les complexes sont utilisés pour décrire les autres formes de contenu.

Cela nous amène à distinguer différents modèles de contenu pour un élément selon la nature de ses noeuds fils autorisés :

  • vide : aucun noeud fils ;
  • simple : ne contient que des noeuds textuels ;
  • complexe : que des sous-éléments ;
  • mixte : à la fois du texte et des sous-éléments.

Dès qu'un élément possède un attribut, il est considéré comme étant de type complexe, même si son contenu est vide ou simple.

Les types simples prédéfinis

Consulter la recommandation du W3C pour avoir la liste exhaustive des types prédéfinis. Parmi ceux-ci, citons :

  • string
  • decimal, integer, positiveInteger, real
  • date, dateTime, duration
  • ID, IDREF, ENTITY, NMTOKEN, etc. (venant des DTD)

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 à un type de base, on distingue différents types de contraintes, appelés facettes, différents suivant le type qui subit la restriction.
  • Énumération pour les chaînes de caractères, nombres et dates
    <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>
    
  • longueur fixe, minimale ou maximale des chaînes de caractères
    <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="telephone">
      <xs:restriction base="xs:string">
        <xs:length value="10" />
      </xs:restriction>
    </xs:simpleType>
    
  • bornes sur les entiers et les dates
    <xs:simpleType name="temperature">
      <xs:restriction base="xs:integer">
        <xs:minInclusive value="-15" />
        <xs:maxInclusive value="+35" />
      </xs:restriction>
    </xs:simpleType>
    
    aussi minExclusive et maxExclusive
  • nombre de chiffres sur les nombre
    <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>
    
  • expressions régulières sur tous les types simples (?)
    <xs:simpleType name="mail">
      <xs:restriction base="xs:string">
        <xs:pattern value=".+@.+" />
      </xs:restriction>
    </xs:simpleType>
    

Définir un attribut

  • utilisation de la balise <xs:attribute /> ;
  • indiquer le nom de l'attribut avec l'attribut <xs:attribute name="score" /> ;
  • définir le type du contenu de l'élément en utilisant l'attribut type ;
  • préciser son caractère obligatoire ou optionnel (required ou optional) à l'aide de l'attribut use ;
  • éventuellement, indiquer une valeur par défaut avec l'attribut default.
<xs:attribute name="score" type="xs:integer" use="required" default="0" />

Définir un élément de type simple

  • utilisation de la balise <xs:element /> ;
  • indiquer le nom de l'élément avec l'attribut name ;
  • préciser le nombre d'apparition autorisé pour cet élément à l'aide des attributs minOccurs et maxOccurs ;
  • définir le type du contenu de l'élément en utilisant l'attribut type ;

Finalement :

<xs:element name="nom"    minOccurs="1" maxOccurs="1"          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éfinir un élément de type complexe

on définit les sous-éléments puis les attributs

contenu vide avec attribut

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

contenu simple avec attribut

extension ou restriction sur un type simple

<xs:element name="title">
  <xs:complexType>
    <xs:simpleContent>
      <xs:extension base="string">
        <xs:attribute name="lang" type="string" />
      </xs:extension>
    </xs:simpleContent>
  </xs:complexType>
</xs:element>

contenu complexe

Il s'agit à nouveau d'utiliser <xs:complexType> puis de lister les sous-éléments autorisés au sein de l'une de ces balises :

  • <xs:sequence> : les sous-éléments doivent tous apparaître, dans l'ordre ;
  • <xs:all> : les sous-éléments doivent tous apparaître, mais dans un ordre quelconque ;
  • <xs:choice> : seulement un des sous-éléments peut apparaître, au choix.
<xs:element name="auteur">
  <xs:complexType>
    <xs:sequence>
      <xs:element name="nom"    minOccurs="1" maxOccurs="1"          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

On définit pour cela un type complexe en précisant un attribut mixed, celui-ci indiquant que du texte peu se glisser entre tous les sous-éléments autorisés.

<xs:element name="p">
  <xs:complexType mixed="true">
    <xs:choice minOccurs="0" maxOccurs="unbounded">
      <xs:element name="em" type="xs:string" />
      <xs:element name="strong" type="xs:string" />
    </xs:choice>
  </xs:complexType>
</xs:element>

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

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 et IDREF des DTD mais c'est plus pauvre que le mécanisme offert par XML-Schémas. Celui-ci utilise (un sous-ensemble) des expressions XPath.

Unicité

<xs:element name="bibliotheque">
  <xs:complexType>
  ...
  </xs:complexType>
  <xs:unique name="uniquelivre">
    <xs:selector xpath="book" />
    <xs:field xpath="isbn" />
  </xs:unique>
</xs:element>

on peut mettre plusieurs fields

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>

pareil que unique avec présence obligatoire de la clé en plus.

Référence

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

Regroupements

Regrouper des attributs

<xs:attributeGroup name="attrs_photo">
    <xs:attribute name="source" type="nomfichier" />
    <xs:attribute name="alt" type="xs:string" />
</xs:attributeGroup>

<xs:element name="identite">
  <xs:complexType>
    <xs:attributeGroup ref="attrs_photo" />
    <xs:attribute name="personne" type="xs:string" />
  </xs:complexType>
</xs:element>

<xs:element name="paysage">
  <xs:complexType>
    <xs:attributeGroup ref="attrs_photo" />
    <xs:attribute name="lieu" type="xs:string" />
  </xs:complexType>
</xs:element>

Regrouper des éléments

regrouper par all, choice, ou sequence...

<xs:group name="elems_text">
  <xs:choice>
    <xs:element ref="refacteur" />
    <xs:element ref="film" />
    <xs:element ref="realisateur" />
    <xs:element ref="annee" />
  </xs:choice>
</xs:group>

<xs:element name="p">
  <xs:complexType mixed="true">
    <xs:choice minOccurs="0" maxOccurs="unbounded">
      <xs:group ref="elems_text" />
    </xs:choice>
  </xs:complexType>
</xs:element>

Fabien Torre Valid HTML5! Valid CSS!
Accueil > Enseignement > Cours > Documents numériques > XML > XML Schéma
(contenu mis à jour )
site de Fabien Torre, université de Lille

Description

Survoler un lien de navigation pour lire sa description ici...


Une photo au hasard

Week-end chevillais.

(le 10 mai 2008)

Azalée.