UP | HOME

Le langage XML

Table of Contents

1 Un langage typé généralisant les parenthèses

  • Version 1 en 1998 (W3C) (en même temps que SOAP)
  • Représentation utilisant des parenthèses (les balises)
  • Langage typé : valeurs appelées documents, types appelés schémas

2 Documents XML

2.1 Prologue

<?xml version="1.0" encoding="UTF-8"?>

2.2 Caractères spéciaux

Cinq caractères spéciaux

< > & " '

échappement

X = &X;

< = &lt;
> = &gt;
& = &amp;
" = &quot;
' = &apos;

2.3 Commentaires

<!-- Voici le commentaire -->

2.4 Eléments et attributs

Un document XML est composé d'éléments et d'attributs, équivalents à des sous-éléments. Il possède un élément racine. Un élément possède un nom, peut contenir des attributs, d'autres éléments et une valeur alphanumérique (possiblement entrelacée avec les sous-éléments). Un attribut possède un nom et une valeur alphanumérique.

Elément défini par une balise X

<X>...</X>
  • Ouverture et fermeture (comme des parenthèses)
  • Cas particulier : élément vide <X/>
  • Contenu d'un élément : d'autres éléments, des attributs, du contenu alphanumérique

Attribut associé à un élément X

<X id=val>
  • id : nom de l'attribut associé à l'élément X
  • val : chaîne alphanumérique entre guillemets ("…") ou apostrophes ('…')

2.5 Espaces de nommage

Un espace de nommage sert à ranger des noms d'éléments, d'attributs ou de types. Le nom complet d'un élément ou d'un attribut est formé de celui de son espace, suivi de son nom propre. Ainsi les espaces de nommage permettent d'éviter les conflits de nommage, qui surviennent quand le même nom peut désigner plusieurs entités. Pour résoudre ces conflits, il suffit de placer les entités homonymes dans des espaces différents.

A chaque espace de nommage, le langage XML associe

  • une valeur, appelée l'identifiant de l'espace, donnée par une URI (pure convention, l'URI n'étant pas nécessairement associé à une ressource),
  • un ensemble d'entités définies dans un schéma.

Lorsque l'espace de nommage est utilisé, un nom d'usage (éventuellement vide) lui est aussi associé. Il est conseillé de ne pas utiliser un nom préfixé par xml (en minuscule ou en majuscule) pour éviter les conflits avec des noms réservés (comme xmlns). La définition du nom d'usage se fait à l'intérieur d'un élément, en utilisant un attribut appartenant à un espace de nommage prédéfini et nommé xmlns.

<A  xmlns:nom="URI1" >
    xmlns="URI2" <!-- nom vide --> >

Exemple

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
            jxb:version="2.0">

Le préfixe xmlns s'interprète comme une directive particulière.

xmlns = xml name space = espace de nommage xml

Le nom suivant les deux points sert de nom d'usage (cf. xsd et jxb), à l'intérieur de l'élément où la directive est placée : il peut alors servir de préfixe de noms d'éléments ou d'attributs. Les noms deviennent qualifiés.

Exemple : élément schema dans l'espace xsd et attribut version de l'espace jxb

xsd:schema 
jxb:version

L'URI qui termine la définition identifie l'espace de nommage.

Le nom d'usage vide ne peut être utilisé que pour des éléments. En pratique, on l'utilise pour simplifier l'écriture pour l'espace de nommage le plus utilisé dans un document.

En l'absence d'une définition xmlns=uri, les noms non qualifiés n'appartiennent à aucun espace de nommage : cette situation doit être distinguée de celle où un espace de nommage est utilisé anonymement (avec un nom vide), puisqu'il est alors possible d'associer un espace bien réel.

Pour définir et peupler de noms un espace de nommage, on utilise un schéma : voir ci-dessous.

3 Schémas

Un schéma représente un type pour des documents XML. Il est lui-même représenté sous la forme d'un document XML utilisant un espace de nommage prédéfini, http://www.w3.org/2001/XMLSchema.

Il comporte des définitions d'éléments et de types, ainsi que d'attributs. Ces définitions peuvent être globales ou locales. Il est toujours possible de traduire une définition locale en une globale, en utilisant une référence, et inversement. Les définitions globales permettent de factoriser des définitions tandis que les définitions locales permettent de masquer certaines définitions en limitant leur portée (cf. infra).

Cf. un guide abrégé de référence.

3.1 Validation d'un document

Il est possible de valider un document relativement à un schéma : on parlerait en programmation de vérification du typage.

L'algorithme peut être décrit ainsi.

  1. Programme principal :
    • recherche dans les définitions globales du schéma d'une déclaration pour l'élément racine
    • vérification de l'élément racine relativement à sa déclaration
  2. Sous-Programmes
    • vérification d'un élément relativement à sa déclaration
      • recherche du type du contenu à partir du nom du type, soit spécifié dans le document par l'attribut xsi:type de l'espace "http://www.w3.org/2001/XMLSchema-instance", qui doit avoir pour valeur un sous-type du type spécifié par la déclaration, soit en l'absence de cet attribut, spécifié directement par la déclaration de l'élément dans le schéma
    • vérification du contenu de l'élément relativement à la définition du type dans le schéma
      • décomposition (nécessairement unique) du contenu en une suite d'attributs, de valeurs alphanumériques et de sous-éléments en correspondance avec les déclarations définies dans le type
      • vérification des attributs, des valeurs alphanumériques et des sous-éléments relativement aux déclarations associées dans le type
    • vérification d'un attribut relativement à sa déclaration
      • vérification de la valeur relativement au type (simple) indiqué dans la déclaration
    • vérification d'une valeur alphanumérique relativement à sa déclaration

3.1.1 Exemple

Schéma

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
           elementFormDefault="qualified"
           attributeFormDefault="unqualified">

<xs:element name="personne" type="Personne"/>

<xs:complexType name="Personne">
  <xs:sequence>
    <xs:element name="nom" type="xs:string"/>
    <xs:element name="prenom" type="xs:string"/>
  </xs:sequence>
</xs:complexType>
</xs:schema>

Document

<personne>
  <nom>grall</nom>
  <prenom>hervé</prenom>
</personne>

Validation

  • recherche de la déclaration de l'élément personne dans le schéma
  • recherche du type de contenu : Personne
  • vérification du contenu <nom>grall</nom><prenom>hervé</prenom> relativement à la définition du type Personne
    • décomposition en deux sous-éléments <nom>grall</nom> et <prenom>hervé</prenom>, à vérifier relativement aux déclarations <xs:element name="nom" type="xs:string"/> et <xs:element name="prenom" type="xs:string"/>
  • vérification des contenus grall et hervé

3.1.2 Référence à un schéma pour la validation

Si l'on souhaite spécifier le schéma à utiliser pour la validation d'un document, on utilise l'attribut "schemaLocation" de l'espace de nommage "http://www.w3.org/2001/XMLSchema-instance".

<Racine
   xmlns="URI"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="URI_1 URL"
   xmlns:prefixe="URI_1"
>
  ...
</Racine>

Cas d'un schéma

  • localisé en URL (adresse d'un fichier .xsd),
  • déclarant un espace cible de nom URI_1 (avec une balise targetNamespace),
  • nommé localement prefixe.

En l'absence d'espace de nommage cible, utiliser noNamespaceSchemaLocation (espace cible, cf. infra).

3.2 Structure globale

Un schéma utilise l'espace de nommage prédéfini, http://www.w3.org/2001/XMLSchema. Il commence par une balise schema, et définit en utilisant l'attribut targetNamespace l'espace de nommage cible auquel appartiendront toutes les entités définies dans le schéma.

<?xml version="1.0"?>

<xs:schema 
   xmlns:xs="http://www.w3.org/2001/XMLSchema" <!-- espace de nommage prédéfini pour les schémas --> 
   targetNamespace="URI" <!-- espace de nommage cible pour les entités définies --> 
   ...
>
  ...
</xs:schema>

Très souvent, on utilise l'espace de nommage cible à l'intérieur du schéma, ce qui donne la structure suivante.

<schema xmlns="http://www.w3.org/2001/XMLSchema"
        xmlns:tns="URI"
        targetNamespace="URI"
        ...
>

L'espace cible reçoit ainsi tns pour nom d'usage.

Exemple : une école de type EPA, avec une tutelle et un nom

<schema xmlns="http://www.w3.org/2001/XMLSchema"
        xmlns:emn="http://www.mines-nantes.fr"
        targetNamespace="http://www.mines-nantes.fr"
>

  <element name="ecole" type="emn:EPA" />

  <complexType name="EPA">
    <sequence>
      <element name="tutelle" type="string" />
      <element name="nom" type="string" />
    </sequence>
  </complexType>

</schema>

3.3 Convention de nommage

Un schéma définit aussi une convention de nommage pour les éléments et les attributs. On utilise les attributs elementFormDefault et attributeFormDefault de l'élément schema, qui peuvent prendre la valeur qualified ou unqualified.

elementFormDefault="qualified"

Tous les éléments doivent être qualifiés.

elementFormDefault="unqualified"

Seuls les éléments globaux du schéma doivent être qualifiés. Les éléments locaux du schémas ne doivent pas être qualifiés.

attributeFormDefault="qualified"

Tous les attributs doivent être qualifiés.

attributeFormDefault="unqualified"

Seuls les attributs globaux du schéma doivent être qualifiés. Les attributs locaux du schémas ne doivent pas être qualifiés.

Par défaut, ces attributs valent unqualified.

Une bonne pratique est

  • de requérir la qualification de tous les éléments (ce qui permet de transformer des définitions locales en globales, et réciproquement, sans avoir à modifier les documents valides) et
  • de requérir la qualification des seuls attributs globaux.

    elementFormDefault="qualified"
    attributeFormDefault="unqualified"
    

Ainsi, si dans le document on utilise un espace de nommage anonyme (de nom d'usage vide), tout élément non qualifié appartient alors à cet espace de nommage et tout attribut non qualifié appartient à l'espace de nommage de l'élément le contenant.

3.4 Importation et inclusion

Un schéma est défini dans un seul fichier. Il est cependant possible d'inclure les définitions globales de schémas définis dans d'autres fichiers.

On utilise une directive d'inclusion si :

  • les entités définies dans le schéma importé appartiennent au même espace cible, ou
  • les entités définies dans le schéma importé n'appartiennent à aucun espace cible, ce qui a pour effet de les placer dans l'espace cible du schéma réalisant l'importation.

    <xs:schema ... >
      <xs:include schemaLocation="URL"/>
    

(URL est l'adresse du fichier .xsd définissant le schéma.)

Sinon, on doit utiliser une directive d'importation.

<xs:schema ... >
 <xs:import namespace="URI" schemaLocation="URL"/>

(URI est l'espace de nommage cible du schéma importé, URL est l'adresse du fichier .xsd définissant le schéma.)

3.5 Définitions globales et locales

Un schéma est composé de définitions globales, qui peuvent contenir des définitions locales. Toute définition locale peut contenir elle-même d'autres définitions locales. La portée d'une définition est celle de l'élément la contenant. Ainsi, les définitions globales, situées immédiatement sous l'élément schema ont pour portée l'ensemble du schéma. On peut s'y référer dans tout le schéma par une simple indirection :

  • pour les éléments ou les attributs, utiliser l'attribut ref,
  • pour les types, utiliser l'attribut type,

et à chaque fois, lui donner pour valeur le nom de l'entité globale réutilisée. Les définitions globales sont donc réutilisables. Les définitions locales ont une portée limitée et ne sont pas réutilisables. La limitation de la portée est utile lorsque des conflits de noms peuvent survenir. Typiquement, les attributs sont souvent définis localement plutôt que globalement.

Remarque : il est impossible de réutiliser une définition locale. C'est une limitation du langage des schémas. Une construction plus régulière aurait permis de factoriser à tous les niveaux, et pas seulement au niveau global. Cf. la construction let x = … in … des langages fonctionnels ML.

Exemple

<xs:schema ...>
  <!-- Définitions globales -->
  <xs:element name="classe" type="Personne"/> <!-- Référence à la définition globale du type-->
  <xs:complexType name="Personne">
    ...
  </xs:complexType>
  ...
      <xs:element ref="classe"/>  <!-- Référence à la définition globale de l'élément -->
  ...
</xs:schema>

Les définitions globales déclarent non seulement des éléments, des attributs et des types, mais aussi des groupes d'éléments, correspondant à des séquences, des ensembles ou des alternatives d'éléments (cf. infra, la définition d'un schéma), et des groupes d'attributs. L'élément racine d'un document XML doit être spécifié par une définition globale.

Exemple

<xs:schema ...>
  <!-- Définition globale d'un groupe d'éléments-->
  <xs:group name="collection">
    <xs:sequence>
      ... <!-- Séquence, ensemble ou alternative  -->
    </xs:sequence>
  </xs:group>

  <!-- Définition globale d'un groupe d'attributs -->
  <xs:attributeGroup name="attributs">
    <xs:attribute name="attribut_1" ... />
    ... <!-- Autres attributs -->
  </xs:attributeGroup>


  ...
      <xs:group ref="collection"/>  <!-- Référence à la définition globale -->
      ...
      <xs:attributeGroup ref="attributs"/> <!-- Référence à la définition globale -->
  ...
</xs:schema>

3.6 Définition d'un schéma

Forme générale d'un document : élément racine ayant un contenu

<racine>contenu</racine>

Notation :

  • ^* : répétition zéro ou plusieurs fois
  • ^+ : répétition une ou plusieurs fois
  • ? : optionnel
  • . : séquence
contenu ::= attributs.(texte | éléments | mélange | vide)
attributs ::= attribut^*
attribut ::= (id = "texte")
texte ::= Chaîne de caractères alphanumériques
éléments ::= élement^+
élement ::= (<Balise>contenu</Balise) (remarque : <Balise></Balise> noté aussi <Balise/>) 
mélange ::= (éléments.texte)^+.éléments? | (texte.éléments)^+.texte?
vide ::= Chaîne vide

(Par la suite, on interprétera les termes à gauche suivant l'expression à droite.)

Un schéma permet de représenter la structure commune d'un ensemble de documents construits suivant la grammaire précédente.

Dans la suite, on suppose que l'espace de nommage associé aux schémas, soit "http://www.w3.org/2001/XMLSchema", a pour nom xs.

On décrit les constituants principaux d'un schéma :

  • les éléments, qui ont un contenu typé,
  • les attributs, qui ont une valeur typée,
  • les types de valeur, des types simples, ou de contenu, soit des types simples, soit des types complexes.

3.6.1 Elément

La déclaration d'un élément définit le nom de la balise et le type de contenu.

Le type de contenu d'un élément peut être anonyme : il s'agit alors d'une définition locale. La déclaration s'écrit ainsi.

<xs:element name="balise">
  typeAnonyme <!-- Définition locale -->
<xs:element/>

Le type de contenu peut posséder un nom, ce qui permet de le réutiliser en de multiples endroits. Il est alors soit prédéfini, soit déclaré par l'utilisateur sous la forme d'une définition globale. Cf. infra les sections dédiées aux types prédéfinis et aux types déclarés par l'utilisateur.

Un type nommé est déclaré sous la forme d'une définition globale

<xs:schema ...>
  ...
  typeNommé <!-- Définition globale -->
  ...
</xs:schema>

typeNommé diffère de typeAnonyme par un attribut name, donnant le nom du type (par exemple typeContenu) et associé à l'élément racine de la définition du type, xs:simpleType ou xs:complexType.

typeNommé :

<xs:simpleType name="typeContenu">
  ...
</xs:simpleType>

typeAnonyme :

<xs:simpleType>
  ...
</xs:simpleType>

Les types nommés sont utilisés en recourant à la balise type.

<xs:element name="balise" type="typeContenu" />

Il est aussi possible de substituer un élément à un autre élément, uniquement lorsqu'ils sont définis globalement. Cette possibilité permet d'appliquer la règle de subsomption aux éléments, en plus de leurs contenus. Cf. infra l'entrée dédiée à la dérivation de types.

<element name="substituable" type="typeBase" />
<element name="substitut" type="typeDerive"
         substitutionGroup="substituable" />

Dans ce cas, il devient licite de remplacer dans le document un élément de nom substituable et de contenu de type typeBase par un élément de nom substitut et de contenu de type typeDerive, un type dérivant de typeBase.

3.6.2 Attribut

Un attribut appartient nécessairement à un élément et ressemble à un sous-élément de type particulier. Pour déclarer un attribut, utiliser la balise xs:attribute et procéder comme pour un élément de type simple.

Type :

<xs:attribute name="a1" type="typeSimple1"/> <!-- Type nommé -->
<xs:attribute name="a2"> <!-- Type anonyme -->
  <xs:simpleType>
    ...
  </xs:simpleType>
</xs:attribute>

Valeur :

<element a1="val1" a2='val2'> ...

(val1 et val2 valeurs de types simples, représentées par des textes entre guillemets ou apostrophes)

Un attribut est par défaut optionnel. Pour le rendre obligatoire, le qualifier de required :

<xs:attribute name="a1" use="required" .../>

On peut même spécifier la valeur attendue :

<xs:attribute name="a1" fixed="val" .../>

ou une valeur par défaut (s'il est optionnel) :

<xs:attribute name="a1" default="val" .../>

Pour interdire un attribut, le qualifier de prohibited :

<xs:attribute name="a1" use="prohibited" .../>

Cette option sert lorsqu'on souhaite restreindre un type : cf. l'entrée dédiée à la restriction des types simples.

3.7 Système de types

Voici un résumé de la grammaire décrivant les types utilisés dans les schémas. Nous la détaillons ci-dessous.

type ::= typePrédéfini | typeUtilisateur
typeUtilisateur ::= typeSimple | typeComplexe
typeSimple ::= Restriction^+(typePrédéfini) 
              | Liste(typeSimple) 
              | Union(typeSimple^+)
typeComplexe ::= typeContenuSimple | typeContenuComplexe
typeContenuSimple ::= Extension(attribut^+, typeSimple)) 
                    | Restriction(typeContenuSimple)
typeContenuComplexe ::= ElementVide(attribut^*)
                      | groupementElements
                      | contenuMixte      
                      | dérivation                  
groupementElements ::= séquence | ensemble | alternative
séquence ::= Séquence((élément | alternative)^+) 
ensemble ::= Ensemble(élément^+) 
alternative ::= Alternative((élement | groupementElements)^+)

3.7.1 Types prédéfinis

Il existe de nombreux types prédéfinis :

xs:string,
xs:decimal,
xs:integer,
xs:boolean,
xs:date,
xs:time,
etc.

Cf. http://www.w3.org/TR/xmlschema-2/#built-in-datatypes pour une description complète. Les types prédéfinis sont soit primitifs, soit dérivés, par restriction des types primitifs. La dérivation est décrite ci-dessous dans la section Type simple > Restriction : elle contraint les facettes décrites pour les différents types primitifs.

3.7.2 Type déclaré par l'utilisateur

Le type peut être anonyme ou non.

On distingue les types simples (pour les valeurs alphanumériques) et les types complexes (pour les contenus structurés).

3.7.2.1 Type simple

Schéma :

<xs:simpleType>
  ... <!-- Définition d'un type simple --> 
</xs:simpleType>

Valeur: chaîne de caractères alphanumériques, ni attributs, ni sous-éléments

Revue des définitions pour les types simples

Un type simple est :

  • une restriction d'un type simple,
  • une liste ou
  • une réunion.
3.7.2.1.1 Restriction d'un type simple

Schéma :

<xs:restriction base="typeSimple">
   ... <!-- contraintes sur les facettes -->
</xs:restriction>

Valeur : valeur respectant les contraintes

Le type simple servant de base est ou bien un type dérivé par restriction, ou bien un type primitif. Ainsi, à tout type dérivé par restriction, on peut associer un, et un seul, type primitif. Pour définir la restriction, on utilise alors les facettes définies pour ce type primitif.

Exemple : xs:length pour xs:string

Revue des facettes

3.7.2.1.1.1 Intervalles

Eléments xs:minInclusive, xs:minExclusive, xs:maxInclusive, xs:maxExclusive avec l'attribut value

Exemple

Schéma :

<xs:maxInclusive value="1976-10-03"/>

Valeur :

1976-10-02
1976-10-03
3.7.2.1.1.2 Enumération

Eléments xs:enumeration avec l'attribut value (répété)

Exemple

Schéma :

<xs:enumeration value="val_i"/> <!-- Une entrée par valeur -->

Valeur :

val_i
3.7.2.1.1.3 Longueur d'un élément

éléments xs:length, xs:minLength, xs:maxLength avec l'attribut value

Exemple

Schéma :

<xs:length value="7"/>

Valeur : chaîne de longueur 7

3.7.2.1.1.4 Filtrage (par expressions régulières)

élément xs:pattern avec l'attribut value

Exemple

Schéma :

<xs:pattern value="w:\d{3}"/>

Valeur : langage reconnu : w:xyzx, y et z sont trois chiffres (w:345 par exemple).

Grammaire pour les expressions régulières :

reg ::= x (un caractère) | . (tout caractère) 
      | \w (lettre ou chiffre) | \W (non lettre et non chiffre) 
      | \d (chiffre) | \D (non chiffre) 
      |  \s (espaces) | \S (non espaces) 
      | [Alphabet] (tout caractère de l'alphabet) 
      | [^Alphabet] (tout caractère hors de l'alphabet)  
      | reg* (reg 0 ou plusieurs fois) | reg? (reg 0 ou 1 fois) | reg+ (reg 1 ou plusieurs fois)
      | reg{n} (reg n fois) | reg{n, p} (reg entre n et p fois, p pouvant être omis)
      | (reg)(reg) (sequence, parenthèses pouvant être omises) | (reg '|' reg) (alternative notée |)

caractère d'échappement : \

Remarque

Le filtrage est impossible pour les noms des éléments. Pour pallier cet inconvénient, on remplace le nom d'un élément par un nom générique et un attribut particulier servant au nommage : on réalise alors le filtrage sur l'attribut.

3.7.2.1.1.5 Représentation numérique

éléments xs:totalDigits, xs:fractionDigits avec l'attribut value

Exemple

Schéma :

<xs:totalDigits value="6"/>
<xs:fractionDigits value="2"/>

Valeur :

100000.05
3.7.2.1.2 Liste de valeurs d'un type simple

Schéma

<xs:list itemType="typeSimple"/>

Valeur : liste décrite par une suite de chaînes textuelles, séparées par un espace. Chaque chaîne doit correspondre à une valeur du type "typeSimple" (et ne peut pas comporter d'espace).

Exemple

Schéma

<xs:list itemType="xs:string"/>

Valeur (liste de deux éléments) :

un deux

Remarque : si les éléments de la liste contiennent des espaces, on utilise plutôt une séquence d'éléments (cf. les types complexes).

3.7.2.1.3 Réunion de types simples

Schéma :

<xs:union memberTypes="typeSimple_1 ... typeSimple_n"/>

Valeur : tout élément appartenant à l'un des types membres (typeSimple_1, …, typeSimple_n).

Exemple

Schéma

<xs:union memberTypes="xs:string xs:integer"/>

Valeurs :

mot
7
3.7.2.2 Type complexe

Schéma

<xs:complexType>
  ... <!-- Définition du contenu -->
</xs:complexType>

Valeur : contenu avec au moins un attribut ou au moins un sous-élément ou contenu vide

Deux sortes de contenu pour un type complexe : simple ou complexe

3.7.2.2.1 Contenu simple

Définition : extension avec des attributs d'un type simple

Schéma :

<xs:simpleContent>
  ... <!-- Définition d'un contenu simple -->
</xs:simpleContent>

Valeur : attributs (au moins un) et chaîne de caractères alphanumériques

Revue des définitions des contenus simples

3.7.2.2.1.1 Extension d'un type au contenu simple

Schéma :

<xs:extension base="typeAuContenuSimple">
  ... <!-- déclaration d'au moins un attribut -->
</xs:extension>

Valeur : toute valeur du type simple associé au type de base typeAuContenuSimple (type complexe au contenu simple ou type simple) accompagnée des attributs du type de base ainsi que les nouveaux attributs de l'extension

Exemple

Schéma :

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
        xmlns:emn="http://www.mines-nantes.fr"
        targetNamespace="http://www.mines-nantes.fr"
        elementFormDefault="qualified"
        attributeFormDefault="unqualified">
<xs:element name="personne" type="emn:MatriculeDivisionSection"/>
<xs:complexType name="MatriculeDivision">
  <xs:simpleContent>
    <xs:extension base="xs:integer">
      <xs:attribute name="division" type="xs:string"/>
    </xs:extension>
  </xs:simpleContent>
</xs:complexType>
<xs:complexType name="MatriculeDivisionSection">
  <xs:simpleContent>
    <xs:extension base="emn:MatriculeDivision">
      <xs:attribute name="section" type="xs:string" use="required"/>
    </xs:extension>
  </xs:simpleContent>
</xs:complexType>
</xs:schema>

Valeur :

<personne division="c" section="S-234" xmlns="http://www.mines-nantes.fr">45</personne>
3.7.2.2.1.2 Restriction d'un type au contenu simple

Restriction portant sur les facettes du type simple sous-jacent et les attributs

Schéma :

<xs:restriction base="typeAuContenuSimple">
  ... <!-- Contraintes sur les facettes -->
  ... <!-- Restriction d'attributs -->
</xs:restriction>

(Les contraintes doivent restreindre le domaine de valeurs associé au type simple associé au type de base typeAuContenuSimple.)

Valeur : toute valeur du type simple associé au type de base typeAuContenuSimple vérifiant les contraintes (héritées et nouvelles) et accompagnée des attributs du type de base vérifiant les restrictions

Exemple

Schéma :

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
        xmlns:emn="http://www.mines-nantes.fr"
        targetNamespace="http://www.mines-nantes.fr"
        elementFormDefault="qualified"
        attributeFormDefault="unqualified">
<xs:element name="personne" type="emn:MatriculeDivisionSectionRestreint"/>
<xs:complexType name="MatriculeDivision">
  <xs:simpleContent>
    <xs:extension base="xs:integer">
      <xs:attribute name="division" type="xs:string"/>
    </xs:extension>
  </xs:simpleContent>
</xs:complexType>
<xs:complexType name="MatriculeDivisionSection">
  <xs:simpleContent>
    <xs:extension base="emn:MatriculeDivision">
      <xs:attribute name="section" type="xs:string" use="required"/>
    </xs:extension>
  </xs:simpleContent>
</xs:complexType>
<xs:complexType name="MatriculeDivisionSectionRestreint">
  <xs:simpleContent>    
    <xs:restriction base="emn:MatriculeDivisionSection">
      <xs:maxInclusive value="45"/>
      <xs:attribute name="division" use="prohibited"/>
    </xs:restriction>
  </xs:simpleContent>
</xs:complexType>
</xs:schema>

Valeur validée :

<personne section="S-234"
xmlns="http://www.mines-nantes.fr">45</personne>

Valeurs non validées (46 > max 45, division interdit) :

<personne section="S-234"
xmlns="http://www.mines-nantes.fr">46</personne>

<personne division="C" section="S-234"
xmlns="http://www.mines-nantes.fr">45</personne>
3.7.2.2.2 Contenu complexe

Contenu qui n'est pas simple : type complexe (au moins un attribut ou au moins un sous-élément ou contenu vide) et contenu non simple (non réduit à des attributs accompagnant un texte alpha-numérique)

  • attributs, sous-éléments (au moins un), textes : différentes variantes (mélange d'éléments et de textes, ou non)
  • élément vide, avec possiblement des attributs

Schéma :

<xs:complexContent>
  ... <!-- Définition du contenu complexe -->
</xs:complexContent>

Valeur : contenu formé d'éléments et de textes, accompagné d'attributs

Un type de contenu complexe est toujours défini par restriction du type maximal, obtenu par réunion de tous les autres types et appelé anyType (auquel appartiennent donc toutes les valeurs).

<xs:complexContent>
  <xs:restriction base="xs:anyType">
    ...
 </xs:restriction>
</xs:complexContent>

Cependant, ces deux déclarations peuvent être omises, ce qu'on fera par la suite.

3.7.2.2.2.1 Elément vide

Schéma :=

<xs:complexType name="elementVide">
  ... <!-- Déclaration des attributs (zéro ou plus) -->
</xs:complexType>

valeur : attributs accompagnant l'élément

Exemple

Schéma

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
        xmlns:emn="http://www.mines-nantes.fr"
        targetNamespace="http://www.mines-nantes.fr"
        elementFormDefault="qualified"
        attributeFormDefault="unqualified">
<xs:element name="personne" type="emn:DivisionSection"/>
<xs:complexType name="DivisionSection">
  <xs:attribute name="division" type="xs:string"/>
  <xs:attribute name="section" type="xs:string" use="required"/>
</xs:complexType>
</xs:schema>

Valeurs

<personne division="C" section="S-234" xmlns="http://www.mines-nantes.fr"/>

validé suivant le schéma précédent

<personne division="C" xmlns="http://www.mines-nantes.fr"/>

non validé suivant le schéma précédent

3.7.2.2.2.2 Groupement d'éléments

Attributs, groupement non vide de sous-éléments (ordonnée ou non) ou alternative non vide de sous-éléments, pas de texte

Contenu dit à éléments seulement

Grammaire simplifiée

groupementElements ::= séquence | ensemble | alternative
séquence ::= Séquence((élément | alternative)^+) 
ensemble ::= Ensemble(élément^+) 
alternative ::= Alternative((élement | groupementElements)^+)

Il est possible de spécifier dans un groupement un élément quelconque par la balise xs:any (dite joker, ou wildcard). On peut qualifier l'espace de nommage auquel il doit appartenir par l'attribut (optionnel) namespace. Dans ce cas, on peut caractériser la validation souhaitée par l'attribut optionnel processContents pour spécifier la validation :

  • strict (défaut) : validation contre le schéma associé à l'espace de nommage contenant l'élément
  • lax : comme strict si le schéma est trouvé, comme skip sinon
  • skip : pas de validation

Il est possible de définir globalement un groupement en utilisant la balise group. On peut ensuite utiliser cette définition en utilisant la même balise et en se référant à la définition globale par l'attribut ref.

3.7.2.2.2.2.1 Séquence

Suite d'éléments (l'ordre important)

<xs:complexType>
  <xs:sequence>
    <xs:element name="sousElement1" type="type1"/>
    <xs:element name="sousElement2" type="type2"/>
  </xs:sequence>
  ... <!-- déclaration des attributs (zéro ou plus) -->
</xs:complexType>

Exemple

Schéma

<xs:element name="personne">
  <xs:complexType>
    <xs:sequence>
      <xs:element name="nom" type="xs:string"/>
      <xs:element name="dateNaissance" type="xs:date"/>
    </xs:sequence>
  </xs:complexType>  
<xs:element/>

Valeur

<personne>
  <nom>toto</nom>
  <dateNaissance>1976-10-03</dateNaissance>
</personne>
3.7.2.2.2.2.2 Ensemble

Ensemble d'éléments (l'ordre n'important pas)

<xs:complexType>
  <xs:all>
    <xs:element name="sousElement1" type="type1"/>
    <xs:element name="sousElement2" type="type2"/>
  </xs:all>
  ... <!-- déclaration des attributs (zéro ou plus) -->
</xs:complexType>

Exemple

Schéma

<xs:element name="personne">
  <xs:complexType>
    <xs:all>
      <xs:element name="nom" type="xs:string"/>
      <xs:element name="dateNaissance" type="xs:date"/>
    </xs:all>
  </xs:complexType>  
<xs:element/>

Valeur

<personne>
  <dateNaissance>1976-10-03</dateNaissance>
  <nom>toto</nom>
</personne>
3.7.2.2.2.2.3 Alternative

Alternative entre éléments

<xs:complexType>
  <xs:choice>
    <xs:element name="sousElement1" type="type1"/>
    <xs:element name="sousElement2" type="type2"/>
  </xs:choice>
  ... <!-- déclaration des attributs (zéro ou plus) -->
</xs:complexType>

Exemple

Schéma :

<xs:element name="personne">
  <xs:complexType>
    <xs:choice>
      <xs:element name="nomComplet" type="xs:string"/>
      <xs:sequence>
        <xs:element name="nom" type="xs:string"/>
        <xs:element name="prenom" type="xs:string"/>
      </xs:sequence>
    </xs:choice>
  </xs:complexType>  
<xs:element/>

Valeur 1 :

<personne>
  <nomComplet>Hervé Grall</nomComplet>
</personne>

Valeur 2 :

<personne>
  <nom>Grall</nom>
  <prenom>Hervé</prenom>
</personne>
3.7.2.2.2.3 Contenu mixte

Texte alpha-numérique contenant des sous-éléments, possibles attributs

<xs:complexType name="typeMixte" mixed="true">
  ... <!-- déclaration d'un groupement -->       
  ... <!-- déclaration des attributs (zéro ou plus) -->
</xs:complexType>

Exemple

Schéma :

<xs:element name="personne">
  <xs:complexType mixed="true">
    <xs:choice>
      <xs:element name="nomComplet" type="xs:string"/>
      <xs:sequence>
        <xs:element name="nom" type="xs:string"/>
        <xs:element name="prenom" type="xs:string"/>
      </xs:sequence>
    </xs:choice>
  </xs:complexType>  
</xs:element>

Valeur 1 :

<personne>
  Je m'appelle <nomComplet>Hervé Grall</nomComplet>.
</personne>

Valeur 2 :

<personne>
  Mon nom est <nom>Grall</nom>, mon prénom 
  <prenom>Hervé</prenom>.
</personne>
3.7.2.2.2.4 Dérivation (par restriction ou extension)

On a déjà vu la dérivation par restriction ou par extension des types simples :

  1. on restreint un type simple en ajoutant des contraintes pour les facettes du type primitif associé,
  2. on étend un type simple en ajoutant das attributs pour obtenir un type complexe de contenu simple.

La dérivation s'applique également aux types complexes.

La restriction d'un type complexe a la même structure (en première approximation) que sa base : chaque élément ou attribut est cependant plus contraint.

L'extension d'un type complexe préserve la structure de sa base tout en l'étendant par des éléments ou des attributs.

Pour la restriction, il existe deux cas particuliers :

  • la restriction du type universel xs:anyType, qui est la construction initiale à partir de laquelle tout type complexe au contenu complexe dérive, construction qui peut être omise puisqu'elle est ajoutée par défaut,
  • la restriction du joker, qui peut se faire par un joker avec moins d'occurrences, ou un élément (et un seul sauf cas particuliers) avec moins d'occurrences (c'est une restriction inutile de la version 1.0 (2001-2004), apparemment corrigée dans la version 1.1 (2012), puisque logiquement le joker devrait pouvoir être restreint en un groupement d'éléments avec moins d'occurrences).

De manière générale, la dérivation à partir d'un type de base permet de définir un nouveau type inclus dans le type de base.

La restriction rajoute des contraintes : ainsi, toute valeur du type dérivé par restriction appartient aussi au type de base.

L'extension rajoute des attributs ou des sous-éléments : ainsi, toute valeur du type dérivé par extension peut être convertie en une valeur du type de base par projection, ce qui donne l'inclusion à une conversion près. Bien noter que la dérivation par extension est celle utilisée dans les langages à objets, pour les tables de champs et de méthodes associées à chaque objet.

A la relation de dérivation est associée une relation de sous-typage et la règle classique de subsomption, qui permet la conversion.

Restriction

contexte : 
  typeBase défini
  typeRestreint défini ainsi :
    <xs:complexType name="typeRestreint"> <!-- complexType ou simpleType -->
      <xs:restriction base="typeBase"> 
	...
      </xs:restriction>    
    </xs:complexType>

si contenu a pour type typeRestreint, 
alors contenu a aussi pour type typeBase. 

  contenu : typeRestreint
  -----------------------
    contenu : typeBase

Extension

contexte : 
  typeBase défini
  typeEtendu défini ainsi :
    <xs:complexType name="typeEtendu"> <!-- complexType ou simpleType -->
      <xs:extension base="typeBase"> 
	...
      </xs:extension>    
    </xs:complexType>

si contenu a pour type typeEtendu, 
alors contenu a aussi pour type typeBase. 

   contenu : typeEtendu
  ----------------------
    contenu : typeBase

Les restrictions et les extensions sont souvent combinées. Une combinaison particulière permet de modéliser des contenus extensibles.

  • Point de départ : une restriction du type xs:anyType ajoutant un joker avec un nombre quelconque d'occurrences
  • Extension : la restriction du joker par un élément particulier puis une extension par le même joker

Cf. exemples 3 et 4 ci-dessous.

3.7.2.2.2.4.1 Exemples

Outil en ligne pour la validation : cf. http://www.utilities-online.info/xsdvalidation/

Exemple 1 : restriction pour un type simple

Schéma

<xs:element name="personne" type="xs:string"/>
<xs:simpleType name="string2">
  <xs:restriction base="xs:string">
    <xs:minLength value="2"/>
  </xs:restriction>    
</xs:simpleType>

Valeurs 1 et 2 validées

<personne>toto</personne> <!-- le contenu toto a le type string -->
<personne>t</personne> <!-- le contenu t a le type string -->

Valeurs 1' et 2', utilisant une conversion explicite vers un sous-type de celui attendu

<!-- le contenu doit avoir pour type string2, sous type de string -->
<personne xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
          xsi:type="string2" 
>toto</personne> <!-- le contenu toto a le type string2 -->

<personne xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
          xsi:type="string2" 
>t</personne> <!-- le contenu t n'a pas le type string2 -->

toto validé, t non validé (longueur inférieure à 2)

Exemple 2 : extension universelle pour un type simple (par des attributs quelconques)

Schéma

<xs:element name="personne" type="stringAvecAttributs"/>
<xs:complexType name="stringAvecAttributs">
<xs:simpleContent>
  <xs:extension base="xs:string"> 
    <xs:anyAttribute processContents="lax"/> 
      <!-- extension par un nombre quelconque d'attributs -->
  </xs:extension> 
</xs:simpleContent>   
</xs:complexType>

Valeurs toutes validées

<personne nom="coco">titi</personne>
<personne nom="coco">titi</personne>
<personne nom="coco" prenom="toto">titi</personne>

Exemple 3 : restriction d'un joker

Point de départ : enregistrement universel

<xs:complexType name="EnregistrementUniversel">
  <xs:complexContent>
    <xs:restriction base="xs:anyType">
      <xs:sequence>
        <xs:any minOccurs="0" maxOccurs="unbounded"/>
      </xs:sequence>      
    </xs:restriction>
  </xs:complexContent>  
</xs:complexType>

ou plus simplement

<xs:complexType name="EnregistrementUniversel">
  <xs:sequence>
    <xs:any minOccurs="0" maxOccurs="unbounded" processContents="lax"/>
  </xs:sequence>      
</xs:complexType>

Restriction de l'enregistrement universel

<xs:complexType name="Nom">
  <xs:complexContent>
    <xs:restriction base="EnregistrementUniversel">
      <xs:sequence>
        <xs:element name="nom" type="xs:string"/>         
      </xs:sequence>      
    </xs:restriction>
  </xs:complexContent>  
</xs:complexType>  

<xs:element name="personne1" type="Nom"/>

Valeur validée

<personne1><nom>coco</nom></personne1>

Valeur non validée

<personne1><nom>coco</nom><prenom>titi</prenom></personne1>

Exemple 4 : extension par un joker

Schéma

<xs:complexType name="NomAuMoins">
  <xs:complexContent>
    <xs:extension base="Nom">
      <xs:sequence>
        <xs:any minOccurs="0" maxOccurs="unbounded" processContents="lax"/>
      </xs:sequence>      
    </xs:extension>
  </xs:complexContent>  
</xs:complexType>  

<xs:element name="personne2" type="NomAuMoins"/>

<xs:element name="personne3" substitutionGroup="personne1" type="NomAuMoins"/>

<xs:element name="essai">
  <xs:complexType>
    <xs:sequence>
      <xs:element ref="personne1"/>
    </xs:sequence>
  </xs:complexType>
</xs:element>

Valeurs validées

<personne2><nom>coco</nom></personne2>
<personne2><nom>coco</nom><prenom>titi</prenom></personne2>

Valeurs validées (personne3 se substituant à personne1)

<essai><personne1><nom>coco</nom></personne1></essai> : validé
<essai><personne3><nom>coco</nom><prenom>titi</prenom></personne3></essai> : validé

Valeur non validée (personne1 attendu)

<essai><personne2><nom>coco</nom></personne2></essai>

Author: Hervé Grall
Version history: v1: 2016-10-19; v2: 2018-02-08[*text]; v3: 2018-04-05[*text].
Comments or questions: Send a mail.
The webpage content is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.