Nous savons maintenant comment correctement définir la structure et le vocabulaire d'un document XML. Nous allons à présent nous intéresser à la définition d'une grammaire.
En effet il est intéressant de pouvoir contrôler la structure d'un document, ou la valeur d'un élément.
Si on prend l'exemple du message vu précédemment, un individu doit possèder un nom et un prénom. Les balises <nom> et <prenom> n'ont donc de sens que si elles sont définies à l'intérieur de la balise <individu>.

Différents mécanismes existent pour l'élaboration d'une grammaire : les deux principaux sont les DTD et les Schemas. Nous verrons tout d'abord les DTD. L'utilisation de ces mecanismes n'est pas obligatoire mais s'avère souvent utile.

Nous l'avons abordé dans la partie précédente, un document sera dit valide s'il rempli deux conditions :

 

Les DTD (Document Type Definition)

On peut définir une DTD de deux manières : interne (à l'intérieur même du fichier de données) et externe (dans un fichie séparé). Il est préférable d'utiliser une DTD externe; cela permettra notamment de pouvoir utiliser la même DTD pour plusieurs documents.

Dans tous les cas, la DTD doit être nommée. Le nommage de la DTD se fait dans le prologue du fichier de données à l'aide de la balise <!DOCTYPE ...>. La chaîne "!DOCTYPE" doit être suivi du nom de l'élémént racine du fichier de données (aux minuscules et majuscules près). D'autres données variables suivant la DTD utilisée peuvent être ajoutées ensuite.

Les DTD internes

Nous l'avons dit, la DTD interne est définie eu sein même du fichier de données. En reprenant notre exemple de message, on déclarerait un telle DTD de la façon suivante :

<?xml version="1.0" encoding="ISO-8859-1" standalone="yes"?>
<!DOCTYPE message [
  <!-- contenu DTD-->
]>
<message>
  <!-- contenu message-->
</message>


Les DTD externes

Les DTD externes sont définies dans un fichier externe au fichier de données. Le mot clé SYSTEM est utilisé pour indiquer l'URL de la DTD. On peut ainsi lier des fichiers de données à une quelconque DTD présente sur Internet.

La référence à ce fichier doit être faite dans le prologue du fichier de données :

<?xml version="1.0" encoding="ISO-8859-1" standalone="yes"?>
<!DOCTYPE message SYSTEM "fichier.dtd" [ ]>
<message>
  <!-- contenu message-->
</message>

On peut également utilisé des DTD publiques. Pour appeler une DTD publique on utilise un FPI (Formal Public Identifier).

<!DOCTYPE racineDoc PUBLIC "FPIDTD" "URIDTD">

"racineDoc" représente ici le nom de l'élément racine du document, l'identificateur public est optionnel et s'il est présent est de la forme préfixe//auteur//description//CodeLangue (par exemple "-//NomDTD//dtD//EN"), l'URI est obligatoire et doit fournir la localisation de la DTD.

La résolution d'un FPI se fait de la manière suivante :

  1. Recherche d'un fichier catalogue à partir d'une variable d'environnement (de type PATH)
  2. Recherche dans le fichier catalogue d'une entrée correspondante au FPI
  3. Récupération de l'URL associée à l'identificateur
  4. Si l'identificateur n'est pas trouvé, utilisation de l'URI par défaut.

L'utilisation de DTD publiques peut être utile pour définir la structure et le contrôle de données communément référencées (comme des livres par exemple). Des structures et des grammaires ont en effet déjà été élaborés pour ce type de données; on peut donc se servir de ces modèles pour notre propre utilisation.

Exemples de DTD publiques :
http://www.mutu-xml.org/xml-base/shared/MODELS-FR.html

Elaboration d'une règle au sein d'une DTD

Un fichier DTD doit avoir l'extension ".dtd". Il n'utilise pas la syntaxe XML. Il commence par le prologue d'un fichier XML mais sans l'attribut "standalone" et est suivi des contraintes sur chacun des éléments.

<?xml version="1.0" encoding="ISO-8859-1">
  <!-- ensemble des régles sur les éléments -->


Quelque soit le type de DTD utilisée, la définition de règles se fait de manière similaire.

Les règles sont définies dans des balises <!ELEMENT>. Ces balises ne sont pas fermées (les DTD n'utilisent pas la syntaxe XML).

A la suite du mot "ELEMENT" dans la balise <!ELEMENT> on met le nom de la balise à contrôler.

<!ELEMENT nom #PCDATA >

Les voici représentés dans un tableau. La globalité des types possibles est la suivante :

Attribut
Signification
CDATA
chaîne de caractères
ID
identifiant unique de l'lélément
IDREF
référence à un ID défini dans le document
NMTOKEN
un mot unique
ENTITY
entité
NOTATION
nom d'une notation

Il ne s'agit donc pas de types de données classiques (entier, booléen...).

<!ELEMENT individu (nom, prenom)>

On peut effectuer des contrôles plus précis sur l'imbrication d'éléments; En effet plusieurs caractères sont proposés afin de pouvoir jouer sur l'occurrence d'un tag ou bien pour exprimer un choix. Le tableau suivant reprend ces caractères en en fournissant la signification :

Caractère
Contrainte sur l'élément
Type
Utilisation
?
peut être présent ou non
occurence
prenom?
+
doit être présent au moins une fois
occurence
prenom+
*
peut apparaître un nombre indeterminé de fois
occurence
prenom*
,
Les éléments séparés par ce caractère doivent apparaîtres dans l'ordre défini.
connecteur
(définition de séquence)
|
choix entre deux alternatives d'éléments. L'un ou l'autre doivent être présents.
connecteur
(définition du OU logique)
prenom|nom
ANY
peut contenir n'importe quoi
occurence
EMPTY
doit être vide
occurence

 

Définition de la liste d'attributs

Un tag peut en plus de contenir des données ou des sous-entités, posséder des attributs. Si on cherche à valider un fichier de données dont des éléments possèdent des attributs, il est nécessaire de les définir dans la DTD.

Pour cela on utilise la balise <!ATTLIST>. Comme pour ELEMENT, on fait suivre le mot ATTLIST d'un nom d'élément (ici un qui possède des attributs) et on fait suivre ce nom des données descriptives de l'attribut.

Imaginons que nous ayons représenté dans notre message, un individu par :

<expediteur prenom="Guillaume" nom="Charpentier">

On définirait dans notre fichier :

<!ATTLIST expediteur
  prenom PCDATA
  nom PCDATA
>


On peut en plus préciser le niveau de nécessité de l'attribut en utilisant les mots clé suivant :

On peut ainsi effectuer des contrôles plus complexes. Imaginons que nous ayons un fichier de données référençant une discothèque. On pourra définir un contrôle du type :

<!ATTLIST disque
  IDdisque #REQUIRED
  type(K7|MiniDisc|Vinyl|CD)"CD"
>

Cela indique que l'entité nommée "disque" contient deux attributs. Un premier nommé "IDdisque" qui est obligatoire et un second nommé "type" qui contient une des 4 valeurs proposées, sachant que si aucune valeur n'est saisie c'est la dernière qui sera utilisée ("CD").

Nous allons à présent remanier l'exemple "message" jusqu'ici utilisé en y associant une DTD. Nous effectuerons la validation de notre document xml grâce au plugin eclipse XMLBuddy présenté précédemment.

<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?>
<!DOCTYPE message SYSTEM "message.dtd" [ ]>
<message>
  <expediteur>
  <identite>
  <prenom>Guillaume</prenom>
  <nom age="23" sexe="m">Charpentier</nom>
  <email>gcharpen@etudiant.univ-mlv.fr</email>
  </identite>
  </expediteur>
  <destinataire>
  <identite>
  <prenom>Gérard</prenom>
  <nom age="32" sexe="u">Dupont</nom>
  <email>gerarddupont@provider.com</email>
  </identite>
  </destinataire>
  <message>mon message</message>
</message>

Nous allons maintenant contrôler la structure du fichier et vérifier la validité des valeurs des éléments et des attributs dans une DTD. Pour les attributs de l'élément nom (age et sexe) nous imposons que le sexe soit défini et qu'il comporte soit la valeur "m" soit la valeur "f".

<?xml version="1.0" encoding="ISO-8859-1"?>
<!ELEMENT message (expediteur, destinataire, texte)>
<!ELEMENT expediteur (identite)>
<!ELEMENT destinataire (identite)>
<!ELEMENT identite (prenom, nom, email)>
<!ELEMENT nom (#PCDATA)>
<!ELEMENT prenom (#PCDATA)>
<!ELEMENT email ANY>
<!ELEMENT texte ANY>
<!ATTLIST nom
  age CDATA #IMPLIED
  sexe (m|f) #REQUIRED
>

Si on effectue une validation du fichier message sous le plugin eclipse il nous informe que l'attribut sexe ne peut pas contenir la valeur "u" saisie dans le fichier de données, en nous retournant le message d'erreur suivant :

On voit ici un des intérêt d'utiliser un logiciel de ce type. Cela permet d'avoir une validation à la volée de nos documents (aussi du fichier par rapport à sa DTD associée que la syntaxe de la DTD en elle-même). Cela offre également des possibilités supplémentaires, comme la généreration automatiquement de la structure de la DTD en fonction d'un fichier de données (ce qui s'avère très utile pour des structures de fichiers complexes) ou, inversement, la généreration automatique de l'ossature d'un fichier XML en fonction d'une DTD fournie.

 

Les DTD bien que très utiles, présentent plusieurs limites et inconvénients :

Pour ces raisons d'autres alternatives pour contrôler la grammaire d'un fichier XML ont été élaborées, notamment les Schémas XML que nous verrons par la suite.

 

<< Page Précédente
Analyseurs syntaxiques XML

Plan complet du site

Page Suivante > >
Les entités

-- ©
Guillaume Charpentier - Dernière mise à jour de cette page le 27/02/04 1:28 --