• Aucun résultat trouvé

5. Schémas XML

5.9. Restriction de types

</xsd:schema>

L'élément title est ajouté après le contenu du type Name qui est constitué des deux éléments firstname et lastname. Le document suivant est valide pour le schéma précédent.

<?xml version="1.0" encoding="iso-8859-1" standalone="no"?>

<names>

<fullname id="id40">

<firstname>Alexander III Alexandrovich</firstname>

<lastname>Romanov</lastname>

<title>Tsar of Russia</title>

</fullname>

<fullname id="id52">

<firstname>Elizabeth II Alexandra Mary</firstname>

<lastname>Windsor</lastname>

<title>Queen of England</title>

</fullname>

</names>

5.9. Restriction de types

La restriction est la deuxième façon d'obtenir un type dérivé à partir d'un type de base. L'idée générale de la restriction est de définir un nouveau type dont les contenus au sens large sont des contenus du type de base. Par contenus au sens large, on entend les contenus proprement dits ainsi que les valeurs des attributs. La restriction s'applique aux types simples et aux types complexes mais elle prend des formes différentes suivant les cas.

Schémas XML

La restriction d'un type est introduite par l'élément xsd:restriction dont l'attribut base donne le nom du type de base. Celui-ci peut être un type prédéfini ou un type défini dans le schéma. Le contenu de l'élément xsd:restriction explicite les restrictions au type de base. Dans le cas d'un type simple, l'élément xsd:restriction est enfant direct de l'élément xsd:simpleType. Dans le cas d'un type complexe, il est enfant d'un élément xsd:simpleContent ou xsd:complexContent, lui-même enfant de l'élément xsd:complexType.

5.9.1. Types simples

Les schémas définissent un certain nombre de types de base [Section 5.5.1]. Tous les autres types simples sont obtenus par restriction directe ou multiple de ces différents types de base. La restriction des types simples est effectuée par l'intermédiaire de facettes qui imposent des contraintes aux contenus. Toutes les facettes ne s'appliquent pas à tous les types simples. On donne d'abord quelques exemples de restrictions classiques à l'aide des principales facettes puis une liste exhaustive des facettes [Section 5.9.1.4].

5.9.1.1. Restriction par intervalle

Il est possible de restreindre les contenus en donnant une valeur minimale et/ou une valeur maximale avec les éléments xsd:minInclusive, xsd:minExclusive, xsd:maxInclusive et xsd:maxExclusive. Ces contraintes ne s'appliquent qu'aux types numériques pour lesquels elles ont un sens. Dans l'exemple suivant, le type donné à l'élément year est un entier entre 1970 et 2050 inclus. Le type utilisé dans cet exemple est un type anonyme.

<xsd:element name="year">

<xsd:simpleType>

<xsd:restriction base="xsd:integer">

<xsd:minInclusive value="1970"/>

<xsd:maxInclusive value="2050"/>

</xsd:restriction>

</xsd:simpleType>

</xsd:element>

La restriction par intervalle peut aussi s'appliquer aux dates et aux heures comme le montre l'exemple suivant.

<xsd:attribute name="date">

<xsd:simpleType>

<xsd:restriction base="xsd:date">

<!-- Date après le 1er janvier 2001 exclus -->

<xsd:minExclusive value="2001-01-01"/>

</xsd:restriction>

</xsd:simpleType>

</xsd:attribute>

5.9.1.2. Restriction par énumération

Il est possible de donner explicitement une liste des valeurs possibles d'un type prédéfini ou déjà défini avec l'élément xsd:enumeration. Dans l'exemple suivant, le type donné à l'élément language comprend uniquement les trois chaînes de caractères de, en et fr. Le type utilisé est un type nommé Language.

<xsd:element name="language" type="Language"/>

<xsd:simpleType name="Language">

<xsd:restriction base="xsd:language">

<xsd:enumeration value="de"/>

<xsd:enumeration value="en"/>

<xsd:enumeration value="fr"/>

</xsd:restriction>

</xsd:simpleType>

5.9.1.3. Restriction par motif

Schémas XML

Il est possible de restreindre les valeurs en donnant, avec l'élément xsd:pattern, une expression rationnelle [Section 5.15] qui décrit les valeurs possibles d'un type prédéfini ou déjà défini. Le contenu est valide s'il est conforme à l'expression rationnelle. Dans l'exemple suivant, le type ISBN décrit explicitement toutes les formes possibles des numéros ISBN.

<xsd:simpleType name="ISBN">

<xsd:restriction base="xsd:string">

<xsd:pattern value="\d-\d{2}-\d{6}-[\dX]"/>

<xsd:pattern value="\d-\d{3}-\d{5}-[\dX]"/>

<xsd:pattern value="\d-\d{4}-\d{4}-[\dX]"/>

<xsd:pattern value="\d-\d{5}-\d{3}-[\dX]"/>

</xsd:restriction>

</xsd:simpleType>

Le type suivant Identifier définit un type pour les noms XML [Section 2.2.3]. Il aurait aussi pu être décrit avec l'expression rationnelle \i\c*.

<xsd:simpleType name="Identifier">

<xsd:restriction base="xsd:string">

<xsd:pattern value="[:_A-Za-z][-.:_0-9A-Za-z]*"/>

</xsd:restriction>

</xsd:simpleType>

Pour que la contenu soit valide, il faut que le contenu, pris dans son intégralité, soit conforme à l'expression rationnelle. Il ne suffit pas qu'un fragment (une sous-chaîne) de celui-ci soit conforme. Le contenu abc123xyz n'est, par exemple, pas conforme à l'expression \d{3} bien que le fragment 123 le soit. Les ancres '^' et '$' [Section 6.3.4] sont implicitement ajoutées à l'expression. Pour avoir une expression qui accepte éventuellement un fragment du contenu, il suffit d'ajouter .* au début et à la fin de celle-ci. Le contenu abc123xyz est, par exemple, conforme à l'expression .*\d^{3}.*.

5.9.1.4. Liste des facettes

Il faut remarquer que les restrictions par énumération ou par motif se combinent avec un ou logique. Le contenu doit être une des valeurs énumérées ou il doit être décrit par un des motifs. Au contraire, les autres restrictions comme minInclusive et maxInclusive se combinent avec un et logique. Le contenu doit vérifier toutes les contraintes pour être valide.

La liste suivante décrit toutes les facettes. Pour chacune d'entre elles sont donnés les types sur lesquels elle peut s'appliquer.

xsd:enumeration

Cette facette permet d'énumérer explicitement les valeurs autorisées. Elle s'applique à tous les types simples y compris les types construits avec xsd:union [Section 5.6.5] et xsd:list [Section 5.6.6].

xsd:pattern

Cette facette permet de donner une expression rationnelle [Section 5.15] pour contraindre les valeurs. Elle ne s'applique pas uniquement aux types dérivés de xsd:string mais à tous les types simples y compris les types numériques et les types contruits avec xsd:union et xsd:list. L'utilisation avec xsd:decimal permet de restreindre, par exemple, aux nombres ayant 4 chiffres pour la partie entière et 2 pour la partie fractionnaire. Lorsque cette facette est appliquée à un type construit avec xsd:list, la contrainte porte sur les items de la liste et non sur la liste elle-même.

xsd:length, xsd:minLength et xsd:maxLength

Ces trois facettes donnent respectivement une longueur fixe ou des longueurs minimale et maximale.

Elle s'appliquent aux types dérivés de xsd:string [Section 5.5.1.2] ainsi qu'aux types construits avec l'opérateur xsd:list [Section 5.6.6].

Schémas XML

xsd:minInclusive, xsd:minExclusive, xsd:maxInclusive et xsd:maxExclusive

Ces quatre facettes donnent des valeurs minimale et maximale en incluant ou non la borne donnée. Ces facettes s'appliquent à tous les types numériques [Section 5.5.1.1] ainsi qu'à tous les types de date et d'heure [Section 5.5.1.3].

xsd:fractionDigits et xsd:totalDigits

Ces deux facettes fixent respectivement le nombre maximal de chiffres de la partie fractionnaire (à droite de la virgule) et le nombre maximal de chiffres en tout. Il s'agit de valeurs maximales. Il n'est pas possible de spécifier des valeurs minimales. De même, il n'est pas possible de spécifier le nombre maximal de chiffres de la partie entière (à gauche de la virgule). Ces deux facettes s'appliquent uniquement aux types numériques dérivés de xsd:decimal. Ceci inclut tous les types entiers mais exclut les types xsd:float et xsd:double.

xsd:whiteSpace

Cette facette est particulière. Elle ne restreint pas les valeurs valides mais elle modifie le traitement des caractères d'espacement [Section 2.2.2] à l'analyse lexicale. Cette facette peut prendre les trois valeurs preserve, replace et collapse qui correspondent à trois modes de fonctionnement de l'analyseur lexical.

preserve

Dans ce mode, les caractères d'espacement sont laissés inchangés par l'analyseur lexical.

replace

Dans ce mode, chaque caractère d'espacement est remplacé par un espace #x20. Le résultat est donc du type prédéfini xsd:normalizedString [Section 5.5.1.2].

collapse

Dans ce mode, le traitement du mode précédent replace est d'abord appliqué puis les espaces en début et en fin sont supprimés et les suites d'espaces consécutifs sont remplacées par un seul espace. Le résultat est donc du type prédéfini xsd:token [Section 5.5.1.2]

Cette facette ne s'applique qu'aux types dérivés de xsd:string. Une dérivation ne peut que renforcer le traitement des caractères d'espacement en passant d'un mode à un mode plus strict (preserve → replace

→ collapse). Les changements dans l'autre sens sont impossibles.

5.9.2. Types complexes à contenu simple

Les types complexes à contenu simple sont toujours obtenus par extension d'un type simple en lui ajoutant des attributs. La restriction d'un de ces types peut porter sur le type simple du contenu ou/et sur les attributs. Il est possible de remplacer le type du contenu par un type obtenu par restriction. Il est aussi possible de changer le type d'un attribut ou de modifier son utilisation. Un attribut optionnel peut, par exemple, devenir obligatoire. La restriction d'un type complexe à contenu simple donne toujours un type complexe à contenu simple.

Par défaut, le nouveau type complexe défini est identique au type de base. Pour modifier le type du contenu, l'élément xsd:restriction contient un élément xsd:simpleType qui donne explicitement le nouveau type du contenu. Ce type doit être obtenu par restriction du type qui définit le contenu du type de base.

Dans le schéma suivant, un type Base est défini par extension du type simple xsd:string en lui ajoutant un attribut format. Le type Derived est ensuite obtenu en restreignant le type du contenu aux chaînes d'au plus 32 caractères.

<?xml version="1.0" encoding="iso-8859-1"?>

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<!-- Type de base -->

<xsd:complexType name="Base">

<xsd:simpleContent>

<xsd:extension base="xsd:string">

<xsd:attribute name="format" type="xsd:string"/>

</xsd:extension>

Schémas XML

</xsd:simpleContent>

</xsd:complexType>

<!-- Restriction du type de base -->

<xsd:complexType name="Derived">

<xsd:simpleContent>

<xsd:restriction base="Base">

<!-- Nouveau type pour le contenu du type Derived -->

La restriction peut aussi changer les types des attributs et leur utilisation. Les attributs dont certaines propriétés changent sont redéclarés dans le nouveau type. Les autres restent implicitement inchangés. Le type d'un attribut peut être remplacé par un type obtenu par restriction. Ce type peut, bien sûr, être nommé ou anonyme. L'utilisation des attributs peut aussi être restreinte. Un attribut optionnel peut devenir interdit avec use="prohibited" ou obligatoire avec use="required". L'inverse est en revanche interdit. Il est également impossible d'ajouter de nouveaux attributs. Si un attribut possède une valeur par défaut ou une valeur fixe, celle-ci ne peut être ni modifiée ni supprimée.

Dans le schéma suivant, le type de base Base possède plusieurs attributs dont le type dérivé Derived modifie l'utilisation.

<xsd:extension base="xsd:string">

<xsd:attribute name="decimal" type="xsd:decimal"/>

<xsd:attribute name="string" type="xsd:string"/>

<xsd:attribute name="optional" type="xsd:string"/>

<xsd:attribute name="required" type="xsd:string" use="required"/>

<xsd:attribute name="fixed" type="xsd:string" fixed="Fixed"/>

</xsd:extension>

</xsd:simpleContent>

</xsd:complexType>

<xsd:complexType name="Derived">

<xsd:simpleContent>

<xsd:restriction base="Base">

<!-- Restriction du type de l'attribut -->

<xsd:attribute name="decimal" type="xsd:integer"/>

<!-- Le nouveau type doit être dérivé du type initial -->

<xsd:attribute name="decimal" type="xsd:string"/>

<!-- Restriction du type de l'attribut avec un type anonyme -->

<xsd:attribute name="string">

<xsd:simpleType>

Schémas XML

<xsd:attribute name="optional" type="xsd:string" use="required"/>

<!-- Impossible d'étendre l'utilisation de l'attribut -->

<xsd:attribute name="required" type="xsd:string"/>

<!-- Impossible de changer ou supprimer la valeur fixe -->

<xsd:attribute name="fixed" type="xsd:string"/>

<!-- Impossible d'ajouter un nouvel attribut -->

<xsd:attribute name="newattr" type="xsd:string"/>

</xsd:restriction>

</xsd:simpleContent>

</xsd:complexType>

...

</xsd:schema>

Il est encore possible de changer simultanément le type du contenu et certaines propriétés des attributs. Dans le schéma suivant, le type est restreint au chaînes d'au plus 32 caractères et le type de l'attribut decimal est changé en le type xsd:integer.

<?xml version="1.0" encoding="iso-8859-1"?>

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<!-- Type de base -->

<xsd:complexType name="Base">

<xsd:simpleContent>

<xsd:extension base="xsd:string">

<xsd:attribute name="decimal" type="xsd:decimal"/>

<xsd:attribute name="unchanged" type="xsd:string"/>

</xsd:extension>

</xsd:simpleContent>

</xsd:complexType>

<xsd:complexType name="Derived">

<xsd:simpleContent>

<xsd:restriction base="Base">

<xsd:simpleType>

<!-- Nouveau type pour le contenu du type Derived -->

<xsd:restriction base="xsd:string">

<xsd:maxLength value="32"/>

</xsd:restriction>

</xsd:simpleType>

<!-- Restriction du type de l'attribut -->

<xsd:attribute name="decimal" type="xsd:integer"/>

<!-- Attribut unchanged inchangé -->

</xsd:restriction>

</xsd:simpleContent>

</xsd:complexType>

...

</xsd:schema>

5.9.3. Types complexes à contenu complexe

La restriction d'un type complexe permet d'imposer des contraintes aussi bien au contenu qu'aux attributs. La restriction doit rester fidèle au principe que tous les contenus possibles du type restreint doivent être valides pour le type de base. Il est, par exemple, possible de changer le type d'un élément en un type restreint ou de changer le nombre d'occurrences d'un éléments ou d'un bloc avec les attributs minOccurs et maxOccurs [Section 5.6.7].

Les restrictions portant sur les attributs sont identiques à celles possibles pour un type complexe à contenu simple.

Le nouveau type est défini en écrivant sa définition comme s'il s'agissait d'une première définition. Dans le schéma suivant, le type Shortname est obtenu par restriction du type Name. La valeur de l'attribut maxOccurs pour l'élément firstname passe de unbounded à 1. L'attribut id devient obligatoire.

<?xml version="1.0" encoding="iso-8859-1"?>

Schémas XML

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<xsd:element name="names">

<xsd:complexType>

<xsd:choice maxOccurs="unbounded">

<xsd:element name="name" type="Name"/>

<xsd:element name="shortname" type="Shortname"/>

</xsd:choice>

<!-- Nombre illimité d'occurrences de l'élément firstname -->

<xsd:element name="firstname" type="xsd:string" maxOccurs="unbounded"/>

<xsd:element name="lastname" type="xsd:string"/>

</xsd:sequence>

<xsd:attribute name="id" type="xsd:ID"/>

</xsd:complexType>

<!-- Restriction du type Name -->

<xsd:complexType name="Shortname">

<xsd:complexContent>

<xsd:restriction base="Name">

<xsd:sequence>

<!-- Nombre limité d'occurrences de l'élément firstname -->

<xsd:element name="firstname" type="xsd:string" maxOccurs="1"/>

<xsd:element name="lastname" type="xsd:string"/>

</xsd:sequence>

<!-- Attribut id obligatoire -->

<xsd:attribute name="id" type="xsd:ID" use="required"/>

</xsd:restriction>

</xsd:complexContent>

</xsd:complexType>

</xsd:schema>

Le document suivant est valide pour le schéma précédent.

<?xml version="1.0" encoding="iso-8859-1"?>

<names xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

<name>

<firstname>Elizabeth II</firstname>

<firstname>Alexandra</firstname>

Il est aussi possible de restreindre un type complexe en remplaçant le type d'un élément par un type dérivé. Dans l'exemple suivant, le type de l'élément integer est xsd:integer dans le type Base. Ce type est remplacé par le type xsd:nonNegativeInteger dans le type Restriction.

<?xml version="1.0" encoding="iso-8859-1"?>

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<xsd:complexType name="Base">

<xsd:sequence>

<xsd:element name="integer" type="xsd:integer"/>

Schémas XML

</xsd:sequence>

</xsd:complexType>

<xsd:complexType name="Restriction">

<xsd:complexContent>

<xsd:restriction base="Base">

<xsd:sequence>

<xsd:element name="integer" type="xsd:nonNegativeInteger"/>

</xsd:sequence>

</xsd:restriction>

</xsd:complexContent>

</xsd:complexType>

...

</xsd:schema>

Une restriction d'un type complexe à contenu complexe peut aussi supprimer un des choix possibles dans un élément xsd:choice. Dans l'exemple suivant, le choix integer a été supprimé dans le type Float.

<?xml version="1.0" encoding="iso-8859-1"?>

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<!-- Type de base -->

<xsd:complexType name="Number">

<xsd:choice>

<xsd:element name="integer" type="xsd:integer"/>

<xsd:element name="float" type="xsd:float"/>

<xsd:element name="double" type="xsd:double"/>

</xsd:choice>

</xsd:complexType>

<!-- Restriction du type de base -->

<xsd:complexType name="Float">

<xsd:complexContent>

<xsd:restriction base="Number">

<xsd:choice>

<!-- Suppression de l'élément integer -->

<xsd:element name="float" type="xsd:float"/>

<xsd:element name="double" type="xsd:double"/>

</xsd:choice>

</xsd:restriction>

</xsd:complexContent>

</xsd:complexType>

...

</xsd:schema>

Le document suivant est valide pour le schéma précédent. Il utilise une substitution de type [Section 5.10.2] avec l'attribut xsi:type pour changer le type de l'élément number en Float.

<?xml version="1.0" encoding="iso-8859-1"?>

<numbers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

<number>

<integer>42</integer>

</number>

<number xsi:type="Float">

<!-- Élément integer impossible -->

<integer>42</integer>

<float>3.14</float>

</number>

</numbers>