3. Document Type Definition (DTD)

3.1. Attacher un document à une DTD

Une DTD est écrite dans un fichier texte. L’appartenance d’un document XML à une DTD particulière se fait par la déclaration suivante dans le fichier XML.

Exemple 7. Déclaration d’une DTD dans un fichier

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

 <!DOCTYPE web-app
  PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
         "http://java.sun.com/dtd/web-app_2_3.dtd">

 <web-app>
	...
 </webapp>

La déclaration d’un DTD se fait dans un élément XML particulier (qui n’en est pas un…), commençant par <!DOCTYPE et se terminant par >. Le premier mot se trouvant dans cet élément est le nom de la DTD, qui correspond au nom de l’élément racine : web-app dans notre cas. Suit une déclaration, qui indique où se trouve, physiquement, le fichier dans lequel la DTD se trouve. Ce fichier peut se trouver en trois endroits :
  • sur le système local, auquel cas cette déclaration commence par le mot-clé SYSTEM ;
  • sur un système délocalisé, accessible via http (par exemple), auquel cas on utilise le mot-clé PUBLIC (cas de notre exemple) ;
  • enfin la DTD peut être écrite directement dans le fichier, auquel cas on ne met rien.
Suit enfin la déclaration de notre DTD proprement dite : sous forme d’un nom de fichier sur le système local, d’une URL sur le web, ou la DTD elle-même.

3.2. Contenu d’une DTD

Une DTD est une suite de déclarations qui indique la hiérarchie des nœuds et des sous-nœuds de notre document XML. Prenons tout de suite un exemple, en écrivant une DTD à laquelle notre fichier XML se conforme.

Exemple 8. Une première DTD dans un en-tête de fichier XML

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

 <!DOCTYPE marin [
	<!ELEMENT marin (nom, prenom, remarque)>
	<!ELEMENT nom (#PCDATA)>
	<!ELEMENT prenom (#PCDATA)>
	<!ELEMENT remarque (#PCDATA)>
	<!ATTLIST remarque lang CDATA "FR">
]>

 <!-- suit le reste du fichier marin.xml -->
 <marin>
	...
 </marin>

Remarquons qu’il aurait été possible de ranger ce nouvel élément dans un fichier marin.dtd (par exemple), et de le référencer de la façon suivante :

Exemple 9. Référence à une DTD dans un fichier externe

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

 <!DOCTYPE marin SYSTEM "marin.dtd">

 <marin>
	...
 </marin>

Comme leur nom le laisse supposer, les éléments <!ELEMENT > permettent de définir des éléments XML. Cette DTD nous indique que le premier élément XML que l’on doit trouver est un élément marin. Suit dans cet élément <!ELEMENT > une définition du contenu de cet élément. Dans le cas de marin, on lit ( nom, prenom, commentaire). Cela signifie que notre élément marin doit nécessairement contenir trois sous-éléments qui ont pour nom nom, prenom et commentaire, dans cet ordre. Telles que les choses sont déclarées, la présence de ces trois sous-éléments n’est pas facultative, et il ne peut pas y en avoir plusieurs. Leur déclaration à cet endroit signifie que plus loin dans le document DTD, il doit se trouver trois autres <!ELEMENT >, chacun définissant les éléments nom, prenom et commentaire. Ce point est d'ailleurs bien respecté dans notre exemple. La déclaration de nom est différente : <!ELEMENT nom (#PCDATA)>. Elle indique que l’élément nom ne contient pas de sous-élément, mais qu’il contient du texte. Enfin la dernière déclaration, celle de remarque, est référencée par la déclaration d’un attribut : lang. Cet attribut est déclaré dans un élément <!ATTLIST >. Cet élément a pour premier argument le nom de l’élément dans lequel se trouve l’attribut, suivi du nom de l’attribut et de son type. En général le type d’un attribut est CDATA. La dernière déclaration "FR" permet de fixer une valeur par défaut à cet attribut. S’il n’est pas explicitement écrit dans un fichier XML, ou créé au niveau du DOM, il prendra la valeur par défaut FR.

3.2.1. Élément <!ELEMENT >

Cet élément modélise un élément XML. Il prend deux paramètres : le premier est le nom de l’élément, le second peut être son contenu, ou un nom de catégorie, à laquelle cet élément appartient. Si l’élément n’a pas de contenu, alors son contenu est déclaré par le mot-clé EMPTY. Le contenu est porté entre parenthèses. S’il est composé de sous-éléments, alors on en donne la liste, séparée par des virgules. Chacun de ces sous-éléments doit figurer dans la DTD dans une balise <!ELEMENT >. Enfin si un élément possède un contenu textuel, alors il est signalé par le code #PCDATA. On peut ajouter trois modificateurs à un sous-élément :
  • si le sous-élément doit se trouver une et une seule fois, alors il n’y a pas de modificateur à mettre ;
  • s’il doit se trouver 0 ou une fois, alors le modificateur est ? ;
  • s’il peut se trouver autant de fois, y compris aucune, alors le modificateur est * ;
  • s’il peut se trouver au moins une fois, alors le modificateur est +.
Prenons un exemple.

Exemple 10. Exemple de codage de sous-éléments dans une DTD

<!DOCTYPE bateau [
	<!ELEMENT bateau (capitaine, equipage, marchandises)>
	<!ELEMENT capitaine (nom, prenom, grade)>
	<!ELEMENT equipage (marin+)>
	<!ELEMENT marchandises (marchandise*)>
	...
]>

3.2.2. Élément <!ATTLIST >

Cet élément permet d’indiquer qu’un élément XML peut ou doit posséder un attribut. Il se compose de deux premiers paramètres. Le premier indique le nom de l’élément auquel appartient cet attribut. Le deuxième désigne le nom de l’attribut. Le nom de l’élément doit être déclaré dans un élément <!Element > de la DTD. La valeur de l’attribut peut être spécifiée de plusieurs façon :
  • on indique qu’il s’agit d’un texte libre par CDATA, suivi éventuellement d’une valeur par défaut entre double quotes ;
  • si l’attribut est facultatif, alors il est déclaré #IMPLIED, s’il est obligatoire, il est #REQUIRED ;
  • s’il doit toujours avoir la même valeur, alors il est déclaré #FIXED, suivi de cette valeur obligatoire entre double quotes ;
  • s’il doit prendre une valeur dans une liste prédéfinie, alors on porte cette liste entre parenthèses, suivie de l’éventuelle valeur que l’attribut prend par défaut.
Voyons quelques exemples.

Exemple 11. Exemple de codage d’attributs dans une DTD

<!DOCTYPE marin [
	<!ELEMENT marin (nom, prenom)>
	<!ATTLIST marin age #REQUIRED>
	<!ATTLIST marin type #FIXED "marin">
	<!ELEMENT commentaire (#PCDATA)>
	<!ATTLIST commentaire lang ("EN", "FR") "FR">
	...
]>
Il existe d’autres possibilités de spécifier des attributs, notamment par #ID, #IDREF etc… On pourra se reporter aux spécifications officielles pour plus de détails.

3.3. Exemple de DTD, analyse de web-app_2_3.dtd

Cette DTD spécifie le contenu des fichiers web.xml dans le cadre de la version 2.3 de l’API servlet. Ce document est téléchargeable sur l'URL http://java.sun.com/dtd/web-app_2_3.dtd. C’est là que les analyseurs XML validant vont aller le chercher, ce qui leur permettra de valider, ou non, que le fichier web.xml considéré est bien conformes aux spécifications. Il est important de savoir lire à l’œil ce genre de document, dans la mesure où c’est souvent le seul moyen de trouver la raison pour laquelle Tomcat refuse de charger une application web, pour cause de web.xml invalide. Ce document contient énormément de commentaires, le premier élément que l’on trouve est le suivant.

Exemple 12. Déclaration du contenu de web.xml dans web-app_2_3.dtd

<!ELEMENT  web-app  (
	 icon?,  display-name?,  description?,  distributable?,
	 context-param*, 
	 filter*,  filter-mapping*, 
	 listener*, 
	 servlet*,  servlet-mapping*, 
	 session-config?, 
	 mime-mapping*, 
	 welcome-file-list?,
	 error-page*, 
	 taglib*, 
	 resource-env-ref*,  resource-ref*, 
	 security-constraint*,  login-config?,  security-role*, 
	 env-entry*, 
	 ejb-ref*,   ejb-local-ref*)
>

Cet élément nous donne la liste de tous les sous-éléments que peut contenir l’élément web-app, l’ordre dans lequel on doit les trouver ainsi que leur cardinalité. Il apparaît donc que si l’on range l’élément listener, qui permet de poser des listeners sur l’ouverture et la fermeture des sessions, après les déclarations des servlets, le document XML ne sera plus valide, et Tomcat refusera de charger l’application web correspondante. L’élément listener est lui-même spécifié un peu plus loin dans ce document.

Exemple 13. Spécification de l’élément listener dans web-app_2_3.dtd

<!ELEMENT  listener  (listener-class)>
 <!ELEMENT  listener-class  (#PCDATA)>

API Java pour XML
Retour au blog Java le soir
Cours & Tutoriaux
Table des matières
Introduction
1. Un peu d'histoire
2. Les API Java pour XML
Un premier exemple
1. Introduction
2. Structure de base d’un fichier XML
2.1. Un fichier XML simple
2.2. Notion d’espaces de noms
3. Un premier code pour lire un fichier XML
3.1. Lecture avec Dom4J
Description d’un document XML
1. Introduction
2. Organisation d'un document XML
2.1. Introduction
2.2. Nœuds dans un document XML
2.3. Relations entre nœuds dans un document XML
2.4. Ordre dans un document
2.5. Valeurs atomiques dans un document XML
2.6. Notion de PCDATA et CDATA
3. Document Type Definition (DTD)
3.1. Attacher un document à une DTD
3.2. Contenu d’une DTD
3.3. Exemple de DTD, analyse de web-app_2_3.dtd
4. XML Schema
4.1. Introduction
4.2. Un premier schéma
4.3. Attacher un document XML à un schéma
4.4. Types simples
4.5. Attribut
4.6. Restriction sur une déclaration
4.7. Types complexes
4.8. Contraindre un contenu simple
Lire et écrire du XML
1. Introduction
2. Utilisation de DOM4J
2.1. Introduction
2.2. Un premier exemple simple
2.3. Organisation de l'API
2.4. Classe Namespace
2.5. Classe QName
2.6. Interface Node
2.7. Interface Branch
2.8. Interface Document
2.9. Interface Element
2.10. Interface Attribute
2.11. Interface Text
3. Utilisation de Xerces
3.1. Introduction
3.2. Présentation de SAX
3.3. Présentation de DOM
Analyseur SAX en Xerces
1. Introduction
2. Création d'un analyseur SAX
2.1. Introduction
2.2. Objet DefaultHandler
2.3. Exemple d'analyse d'un fichier
3. Présentation de l'API
3.1. Interface ContentHandler
3.2. Interface ErrorHandler
3.3. Interface DTDHandler
3.4. Interface EntityResolver
3.5. Interface LexicalHandler
Manipuler un DOM en Xerces
1. Introduction
2. Création d'un DOM
3. Présentation de l'API
3.1. Organisation de l'API
3.2. Interface Node
3.3. Interface NodeList
3.4. Interface Element
3.5. Interface Attr
3.6. Interface CharacterData
3.7. Interface Comment
3.8. Interface CDATASection
3.9. Interface Text
3.10. Interface Entity
3.11. Interface EntityReference
3.12. Interface ProcessingInstruction
3.13. Interface Document
3.14. Interface DocumentFragment
3.15. Interface DocumentType
Interroger un document en XPath
1. Introduction, notion de nœud XML
2. Une première requête XPath
2.1. Un premier document à interroger
2.2. Une première requête
2.3. Forme d'une requête XPath