FAQ XMLConsultez toutes les FAQ

Nombre d'auteurs : 5, nombre de questions : 65, dernière mise à jour : 26 novembre 2006 

 
OuvrirSommaireXML Schema

XSD (XML Schema Document) ou WXS ((W3C) XML Schemas) désignent la norme XML Schemas du W3C.
Il s'agit d'une norme XML qui est utilisée pour décrire une structure de documents XML.
Un XML Schema (ou XSD, en référence à l'extension qui leur est généralement attribuée), permet de définir une structure de document XML, un format de document XML.
Tout document XML respectant cette structure et référençant le XML Schema est alors déclaré valide.
La définition de la structure peut-être très fine, et très précise. De plus, les XSD sont des Documents XML, donc tous les outils de manipulations de documents XML peuvent y être appliqués.

Créé le 25 novembre 2006  par Mathieu Lemoine

Lien : La Norme XML Schema du W3C

Les "anciens" DocType (DTD : Document Type Definition) permettaient déjà de définir une structure pour un fichier XML, cependant, la norme XML Schema est destinée à les remplacer pour plusieurs raison :

  • Les XML Schemas sont des documents XML, de ce fait, tous les outils (validateurs, parseurs, processeurs, ...) mais également scripts et langages (XSLT, XPath, ...) qui permettent de travailler les Documents XML sont utilisables sur des XSD.
  • Les XML Schemas permettent des gestion beaucoup plus fines de la structure des documents : ordre (ou désordre) des éléments fils, nombre d'occurrences d'un élément, gestion très précise des types de données contenu par les éléments et les attributs (possibilité d'appliquer des expressions régulière sur les données, ou des types à fort valeur sémantiques tels que le type date), ...
  • Il est possible d'utiliser et de faire interagir très facilement des XSD entre eux.
Créé le 25 novembre 2006  par Mathieu Lemoine

Attacher un ou plusieurs XSD à un XML est plus complexe que pour un DTD. Dans un document XML, la partie d'un document qui est soumise à un XSD se nomme un Espace de Noms (NameSpace), en général, ils sont spécifiés sous la forme d'une URL. Les namespace sont déclarés avec l'attribut xmlns ou xmlns:* où "*" représente le préfixe associé au namespace... Une balise ou un attribut entre dans le cadre d'un namespace si son nom est précédé du préfixe associé au namespace suivi de ':', ou si le nom n'a pas de préfixe dans le cas du namespace par défaut (celui précisé avec xmlns). Ensuite l'attribut xsi:schemaLocation permet de spécifier le XSD associé à un namespace. Ensuite, chaque balise ou attribut spécifié comme étant dans ce namespace est soumis à la validation du XSD.

Voici un cas simple où il n'y a qu'un seul XSD entrant en jeu, et donc qu'un seul namespace :

 
Sélectionnez
<?xml version="1.0" ?>
<rootelement
   xmlns="http://www.example.com/MyXMLNS/"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://www.example.com/MyXMLNS/ http://www.example.com/MyXMLNS/XMLSchema.xsd"
>
   [...]
</rootelement>

Mais voici ensuite trois cas plus complexes et équivalents mettant en jeux le namespace XHTML... Comme vous pourrez le constater, un namespace existe pour la balise sur laquelle il est définit, et pour toutes les balises contenues dans celle-ci, à moins qu'une de ces balises ne définisse un nouveau namespace pour ce préfix (dans ce cas le schema se répète avec le nouveau namespace). De plus, on n'est pas obligé de spécifier un XSD pour un namespace. Bien entendu, le XSD du namespace http://www.example.com/MyXMLNS/ indique que son élément content doit contenir un élément div du namespace XHTML...

 
Sélectionnez
<?xml version="1.0" ?>
<rootelement
   xmlns="http://www.example.com/MyXMLNS/"
   xmlns:xhtml="http://www.w3.org/1999/xhtml"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://www.example.com/MyXMLNS/ http://www.example.com/MyXMLNS/XMLSchema.xsd"
>
   [...]
   <content>
		<xhtml:div>
			[...] <!-- namespace XHTML -->
		</xhtml:div>
   </content>
</rootelement>
 
Sélectionnez
<?xml version="1.0" ?>
<rootelement
   xmlns="http://www.example.com/MyXMLNS/"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://www.example.com/MyXMLNS/ http://www.example.com/MyXMLNS/XMLSchema.xsd"
>
   [...]
   <content>
		<xhtml:div xmlns:xhtml="http://www.w3.org/1999/xhtml">
			[...] <!-- namespace XHTML -->
		</xhtml:div>
   </content>
</rootelement>
 
Sélectionnez
<?xml version="1.0" ?>
<rootelement
   xmlns="http://www.example.com/MyXMLNS/"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://www.example.com/MyXMLNS/ http://www.example.com/MyXMLNS/XMLSchema.xsd"
>
   [...]
   <content>
		<div xmlns="http://www.w3.org/1999/xhtml">
			[...] <!-- namespace XHTML -->
		</div>
   </content>
</rootelement>
Créé le 25 novembre 2006  par Mathieu Lemoine

Ce n'est pas exactement possible comme on le faisait pour un DTD. Cependant, il existe deux solutions (recommandée par le W3C) qui permet de simuler ce comportement :
La première consiste a insérer un DTD contenant la dite entité au début du XML :

 
Sélectionnez
<?xml version="1.0" ?>
<!DOCTYPE root [
<!ENTITY eacute "&#xE9;">
<!ENTITY egrave "&#xE8;">
]>
<root xmlns="http://www.exemple.com/XMLNameSpace">
	<!-- etc... -->
		<town>Moll&eacute;g&eagrave;s</town>
	<!-- etc... -->
</root>

Bien sûr, ceci est un peu pénible car il faut le spécifier au début de chaque document XML.
D'où la deuxième solution, elle permet de simuler une entité en déclarant une balise à contenu fixe approprié :

 
Sélectionnez
<xsd:element name="eacute" type="xsd:token" fixed="&#xE9;"/>

Pour l'utiliser ensuite dans le document XML, il suffit de le faire ainsi (pour des raisons de lisibilité, nous avons préférer retrancher les pseudo-entitées dans un XSD séparé :

 
Sélectionnez
<?xml version="1.0" ?>
<root xmlns="http://www.exemple.com/XMLNameSpace" xmlns:E="http://www.exemple.com/Entites>
	<!-- etc... -->
		<town>Moll<E:eacute/>g<E:eagrave/>s</town>
	<!-- etc... -->
</root>
Créé le 25 novembre 2006  par Mathieu Lemoine

Lien : L'annexe sur les entités dans la norme XML Schema du W3C

Ce type permet de rendre annulable un type d'élément. Concrètement, ça permet de rendre une balise potentiellement vide, sans pour autant s'affranchir d'un type plus ou moins fort quand elle est remplie.
Cependant, la validation n'est pas effectuée quand la balise est simplement vide... C'est parce qu'il faut ajouter certaines spécificités pour le prendre en compte :

Dans le XSD
Sélectionnez
<xsd:element name="myElement" type="myType" nillable="true"/>
Dans le XML
Sélectionnez
<root xmlns="http://www.exemple.com/XMLNameSpace" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
	<!-- etc... -->
		<myElement xsi:nil="true"/>
	<!-- etc... -->
</root>

Cela permet de différencier une balise dont le contenu a été annulé (volontairement) d'une balise de valeur vide.
C'est assimilable à la différence entre un champ NULL et un champ contenant une chaîne vide pour les SGBD...

Créé le 25 novembre 2006  par Mathieu Lemoine, GrandFather

Il y a deux solutions, la première est d'utiliser nillable.
La seconde est de faire l'union du typage avec un type vide :

 
Sélectionnez
<xsd:element name="myElement">
	<xsd:simpleType>
		<xsd:union memberTypes="myType">
			<xsd:simpleType>
				<xsd:restriction base="xsd:string">
					<xsd:enumeration value=""/>
				</xsd:restriction>
			</xsd:simpleType>
		</xsd:union>
	</xsd:simpleType>
</xsd:element>
Créé le 12 juin 2006  par Mathieu Lemoine, GrandFather

Lien : Comment s'utilise l'attribut nillable ?

La méthode n'est pas aussi explicite que pour les éléments, cependant, il existe bien un moyen pour demander un choix entre plusieurs attributs :

Commencez par lister normalement tous les attributs que vous souhaitez proposer :

 
Sélectionnez
<xsd:attribute name="a" type="xsd:string"/>
<xsd:attribute name="b" type="xsd:string"/>

Ensuite, définissez une clé sur l'alternative entre les attributs que vous voulez rendre exclusifs :

 
Sélectionnez
<xsd:key name="att">
	<xsd:selector xpath="."/>
	<xsd:field xpath="@a|@b"/>
</xsd:key>

Voici un exemple complet :

 
Sélectionnez
<xsd:element name="myElement">
	<xsd:complexType>
		<xsd:simpleContent>
			<xsd:extension base="xsd:string">
				<xsd:attribute name="a" type="xsd:string"/>
				<xsd:attribute name="b" type="xsd:string"/>
				<xsd:attribute name="c" type="xsd:string"/>
			</xsd:extension>
		</xsd:simpleContent>
	</xsd:complexType>
	<xsd:key name="att">
		<xsd:selector xpath="."/>
		<xsd:field xpath="@a|@b"/>
	</xsd:key>
</xsd:element>

Concrètement, cet attribut doit avoir un attribut c et en plus un attribut a ou bien un attribut b.
Le xsd:key indique que l'élément myElement est identifié par une clé dont la valeur est son attribut a ou sont attribut b.
Si les deux sont présent, même avec des valeurs identiques, cela créera automatiquement deux valeurs pour la clé : ce qui est une situation invalide.
Les clés (xsd:key) doivent avoir une valeur, il faut donc qu'un des attributs soit présent, pour palier à ceci, vous pouvez utiliser xsd:unique à sa place.
Le xsd:selector est là pour assurer que la contrainte d'unicité de la valeur ainsi définie ne s'étende à d'autres éléments... ainsi chaque balise myElement ne sera répertoriée que par rapport à elle-même. Aucun risque que la contrainte d'unicité ne pose problème.

Créé le 14 juin 2006  par Mathieu Lemoine, GrandFather

Lien : La norme XSD sur les contraintes d'identité (clés, uniques, etc...)

Non, il n'existe aucun moyen de spécifier un ordre pour les attributs.

Créé le 25 novembre 2006  par Mathieu Lemoine

Il y a deux solutions, une avec xsd:all et une avec xsd:choice.

xsd:all implique que chacun des éléments/groupes d'éléments indiqués soient présents 1 ou 0 fois.

 
Sélectionnez
<xsd:all>
	<xsd:element name="myElement-1" minOccurs="1" [...]/>
	<xsd:element name="myElement-2" minOccurs="0" [...]/>
	<xsd:element name="myElement-3" minOccurs="1" [...]/>
</xsd:all>

L'attribut minOccurs ne peut prendre que les valeurs 0 ou 1 et maxOccurs ne peuvent prendre que la valeur 1 (s'il est définie).

xsd:choice avec les attributs minOccurs à 0 et maxOccurs à unbounded :

 
Sélectionnez
<xsd:choice minOccurs="0" maxOccurs="unbounded">
	<xsd:element name="tutu-1" [...]/>
	<xsd:element name="tutu-2" [...]/>
	<xsd:element name="tutu-3" [...]/>
</xsd:choice>

Mais on perd les occurrences de chaque éléments... Il n'y a pas, semble-t-il la possibilité de combiner les deux de manière triviale.

Créé le 25 novembre 2006  par Mathieu Lemoine, GrandFather

Lien : La Norme du W3C sur xsd:all et xsd:choice

NON...
Il est impossible de faire quelque chose qui forcerait une structure dans ce style :

 
Sélectionnez
<a b="1" c="1">
	<b>a</b>
	<c>a</c>
</a>
<a b="2" c="1">
	<b>a</b>
	<b>a</b>
	<c>a</c>
</a>
<a b="1" >
	<b>a</b>
</a>
Créé le 25 novembre 2006  par Mathieu Lemoine, Erwy

Par exemple, faire l'équivalent de :

 
Sélectionnez
<xsd:element name="myElement">
	<xsd:complexType>
		<xsd:choice>
			<xsd:sequence>
				<xsd:attribute name="a1" type="xsd:string" use="required"/>
				<xsd:attribute name="a2" type="xsd:string" use="required"/>
			</xsd:sequence>
			<xsd:sequence>
				<xsd:attribute name="b1" type="xsd:string" use="required"/>
				<xsd:attribute name="b2" type="xsd:string" use="required"/>
			</xsd:sequence>
		</xsd:choice>
	</xsd:complexType>
</xsd:element

Dans ce cas là, oui, c'est possible... Il y a deux options :
La première consiste à créer des clés (comme pour Existe-t-il un équivalent de xsd:choice pour les attributs ? ) forçant les relations entre les attributs... Pour ce type de choix, il suffit de faire le produits cartésien des deux séquences (chaque élément de l'une avec chaque élément de l'autre).

 
Sélectionnez
<xsd:element name="myElement"> 
	<xsd:complexType> 
		<xsd:attribute name="a1" type="xsd:string"/> 
		<xsd:attribute name="a2" type="xsd:string"/> 
		<xsd:attribute name="b1" type="xsd:string"/> 
	<xsd:attribute name="b2" type="xsd:string"/> 
	</xsd:complexType>
		<xsd:key name="c-1-1">
		<xsd:selector xpath="."/>
		<xsd:field xpath="@a1|@a1"/>
	</xsd:key> 
	<xsd:key name="c-1-2">
		<xsd:selector xpath="."/>
		<xsd:field xpath="@a1|@b2"/>
	</xsd:key> 
	<xsd:key name="c-2-1">
		<xsd:selector xpath="."/>
		<xsd:field xpath="@a2|@b1"/>
	</xsd:key> 
	<xsd:key name="c-2-2">
		<xsd:selector xpath="."/>
		<xsd:field xpath="@a2|@b2"/>
	</xsd:key> 
</xsd:element>

La seconde solution est d'utiliser un type abstrait possédant plusieurs alternatives au niveau des attributs (cf. Est-il possible de faire dépendre le contenu d'un élément de la valeur d'un attribut ?)
Dans le cas présent :

 
Sélectionnez
<xsd:complexType name="myElementType" abstract="true"/>
<xsd:complexType name="myElementType-a">
	<xsd:complexContent mixed="true">
		<xsd:extension base="myElementType">
			<xsd:attribute name="a1" type="xsd:string"/> 
			<xsd:attribute name="a2" type="xsd:string"/> 
		</xsd:extension>
	</xsd:complexContent>
</xsd:complexType>
<xsd:complexType name="myElementType-b">
	<xsd:complexContent mixed="true">
		<xsd:extension base="myElementType">
			<xsd:attribute name="b1" type="xsd:string"/> 
			<xsd:attribute name="b2" type="xsd:string"/> 
		</xsd:extension>
	</xsd:complexContent>
</xsd:complexType>
<xsd:element name="myElement" type="myElementType"/>
Créé le 25 novembre 2006  par Mathieu Lemoine

Lien : Existe-t-il un équivalent de xsd:choice pour les attributs ?
Lien : Est-il possible de faire dépendre le contenu d'un élément de la valeur d'un attribut ?

Ca dépend, dans le cas d'un nombre fini d'alternatives, oui, sinon non (exemple d'impossibilité : Est-il possible de faire dépendre le nombre d'élément [éventuellement d'un élément en particulier] dans les fils d'un éléments ?).
La solution repose sur les types abstraits et le XML NameSpace "XMLSchema-Instance" : on définie un type abstrait qui contient la structure commune de l'élément, puis on étend ce type pour chaque possibilité.
Ensuite, l'élément est déclaré comme étant du type abstrait. Un type abstrait ne pouvant être instancié, l'élément n'est pas validable si l'on ne spécifie pas un type concret, donc on va utiliser l'attribut xsi:type pour précisé un des types étendus.
La validation sera effective car l'élément respectera le type abstrait (puisqu'il sera d'un type étendu) et il respectera également le type étendu. C'est l'attribut xsi:type qui spécifie le type utilisé (et donc le contenu et les attributs à insérer). Il est impossible de reporter cette responsabilité sur un autre attribut !
Exemple :

XSD
Sélectionnez
<xsd:complexType name="myElementType" abstract="true"/>
<xsd:complexType name="myElementType-1">
	<xsd:complexContent mixed="true">
		<xsd:extension base="myElementType">
			<xsd:attribute name="att1" type="xsd:string"/> 
			<xsd:element name="elem1"/> 
		</xsd:extension>
	</xsd:complexContent>
</xsd:complexType>
<xsd:complexType name="myElementType-2">
	<xsd:complexContent mixed="true">
		<xsd:extension base="myElementType">
			<xsd:attribute name="att2" type="xsd:string"/> 
			<xsd:choice>
				<xsd:element name="elem2"/> 
				<xsd:element name="elem3"/>
			</xsd:choice>
		</xsd:extension>
	</xsd:complexContent>
</xsd:complexType>
<xsd:element name="myElement" type="myElementType"/>
XML
Sélectionnez
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.exemple.com/XMLNameSpace">
	<!-- etc... -->
		<myElement xsi:type="myElementType-1" att1="first">
			<elem1>2006-12-25</elem1>
		</myElement>
	<!-- etc... -->
		<myElement xsi:type="myElementType-2" att2="second">
			<elem3>boat</elem3>
		</myElement>
	<!-- etc... -->
</root>
Créé le 25 novembre 2006  par Mathieu Lemoine

Lien : Est-il possible de faire dépendre le nombre d'élément [éventuellement d'un élément en particulier] dans les fils d'un éléments ?

Oui, il suffit d'utiliser le type anyType, il accepte toute formation (attributs et contenu).

 
Sélectionnez
<xsd:element name="myElement" type="anyType"/>
Créé le 25 novembre 2006  par Mathieu Lemoine

Lien : Définition du xsd:anyType dans la norme XML Schema

  

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2006 Developpez Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.