2. DTD (Document Type Definition)

La DTD (Document Type Definition) définit la structure légale d'un document XML : quels éléments peuvent exister, leurs attributs, leur ordre, et comment ils peuvent être imbriqués. C'est le premier mécanisme historique de validation d'un document XML.

Définition Une DTD est une grammaire qui décrit la structure d'une classe de documents XML. Elle spécifie les éléments autorisés, leurs attributs, leur cardinalité et leur organisation hiérarchique.

Les DTD présentent des avantages (simplicité, support universel) mais aussi des limitations (pas de typage de données, pas de namespaces, syntaxe non-XML). Pour ces raisons, XSD les a largement remplacées dans les applications modernes.

2.1 Déclaration DOCTYPE

Le DOCTYPE lie un document XML à sa DTD. Il existe trois façons de déclarer une DTD :

DTD Interne (dans le document)

La DTD est directement intégrée dans le document XML, entre crochets après DOCTYPE :

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE bibliotheque [
    <!-- Définition des éléments -->
    <!ELEMENT bibliotheque (livre+)>
    <!ELEMENT livre (titre, auteur+, annee?, prix)>
    <!ELEMENT titre (#PCDATA)>
    <!ELEMENT auteur (#PCDATA)>
    <!ELEMENT annee (#PCDATA)>
    <!ELEMENT prix (#PCDATA)>
    
    <!-- Définition des attributs -->
    <!ATTLIST livre isbn ID #REQUIRED>
    <!ATTLIST prix devise CDATA "EUR">
]>
<bibliotheque>
    <livre isbn="L001">
        <titre>Introduction XML</titre>
        <auteur>Jean Dupont</auteur>
        <prix devise="EUR">29.99</prix>
    </livre>
</bibliotheque>

DTD Externe SYSTEM (fichier local)

La DTD est dans un fichier externe référencé par chemin relatif ou absolu :

<!-- Référence à un fichier local -->
<!DOCTYPE bibliotheque SYSTEM "bibliotheque.dtd">

<!-- Référence à une URL -->
<!DOCTYPE bibliotheque SYSTEM "http://exemple.org/dtd/bibliotheque.dtd">

DTD Externe PUBLIC (DTD publique)

Pour les DTD standardisées avec un identifiant public (FPI - Formal Public Identifier) :

<!-- DTD XHTML -->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<!-- Structure FPI : "propriétaire//type titre//langue" -->
Point Examen

2.2 Déclaration ELEMENT

La déclaration <!ELEMENT> définit le contenu autorisé pour un élément.

Syntaxe Générale

<!ELEMENT nom_element (modele_de_contenu)>

Modèles de Contenu

ModèleSignificationExemple
(#PCDATA)Texte uniquement (Parsed Character Data)<!ELEMENT titre (#PCDATA)>
EMPTYÉlément vide (pas de contenu)<!ELEMENT br EMPTY>
ANYN'importe quel contenu (déconseillé)<!ELEMENT container ANY>
(a, b, c)Séquence ordonnée (a puis b puis c)<!ELEMENT livre (titre, auteur)>
(a | b | c)Choix exclusif (a OU b OU c)<!ELEMENT contact (tel | email)>

Exemples Commentés

<!-- Élément avec texte seulement -->
<!ELEMENT nom (#PCDATA)>
<!-- Usage: <nom>Jean Dupont</nom> -->

<!-- Élément vide (auto-fermant) -->
<!ELEMENT image EMPTY>
<!-- Usage: <image src="photo.jpg"/> -->

<!-- Séquence obligatoire -->
<!ELEMENT personne (nom, prenom, email)>
<!-- nom PUIS prenom PUIS email, dans cet ordre -->

<!-- Choix exclusif -->
<!ELEMENT paiement (carte | cheque | especes)>
<!-- UN SEUL parmi les trois -->

<!-- Combinaison séquence + choix -->
<!ELEMENT commande (client, (livraison | retrait), articles)>

2.3 Cardinalité (Quantificateurs)

Les quantificateurs définissent combien de fois un élément peut apparaître.

Indicateurs de Cardinalité DTD
SymboleCardinalitéÉquivalentExemple
elementExactement 11..1(titre) → obligatoire, une fois
element?0 ou 10..1(avis?) → optionnel
element+1 ou plus1..n(auteur+) → au moins un
element*0 ou plus0..n(commentaire*) → optionnel, répétable

Exemples avec Cardinalité

<!-- Une bibliothèque contient au moins un livre -->
<!ELEMENT bibliotheque (livre+)>

<!-- Un livre a un titre, 1+ auteurs, éditeur optionnel, résumé optionnel -->
<!ELEMENT livre (titre, auteur+, editeur?, resume?)>

<!-- Un catalogue peut être vide ou avoir des produits -->
<!ELEMENT catalogue (produit*)>

<!-- Groupe avec cardinalité -->
<!ELEMENT menu ((entree, plat, dessert)+)>
<!-- Un ou plusieurs groupes de (entrée + plat + dessert) -->
Piège Courant (a, b)* signifie "zéro ou plusieurs fois la séquence (a puis b)", pas "a optionnel et b optionnel".
Pour rendre a et b optionnels individuellement : (a?, b?)

2.4 Déclaration ATTLIST

La déclaration <!ATTLIST> définit les attributs d'un élément.

Syntaxe

<!ATTLIST nom_element
    nom_attribut TYPE VALEUR_PAR_DEFAUT
    nom_attribut2 TYPE VALEUR_PAR_DEFAUT
    ...
>

Types d'Attributs

TypeDescriptionExemple
CDATAChaîne de caractères (texte libre)nom CDATA
IDIdentifiant unique dans le documentid ID
IDREFRéférence à un ID existantref IDREF
IDREFSListe de références (séparées par espaces)refs IDREFS
(v1|v2|v3)Énumération de valeursstatut (actif|inactif)
NMTOKENToken XML (sans espaces)code NMTOKEN
NMTOKENSListe de tokenstags NMTOKENS

Valeurs par Défaut

Mot-cléSignificationExemple
#REQUIREDAttribut obligatoireid ID #REQUIRED
#IMPLIEDAttribut optionneltitre CDATA #IMPLIED
#FIXED "val"Valeur fixe (non modifiable)version CDATA #FIXED "1.0"
"valeur"Valeur par défaut si non spécifiélangue CDATA "fr"

Exemple Complet ATTLIST

<!-- Attributs pour élément livre -->
<!ATTLIST livre
    isbn ID #REQUIRED
    titre CDATA #IMPLIED
    langue (fr | en | de | es) "fr"
    disponible (oui | non) "oui"
    version CDATA #FIXED "2.0"
>

<!-- Utilisation correcte -->
<livre isbn="L001" langue="en" disponible="oui">...</livre>

<!-- ID et IDREF pour créer des relations -->
<!ATTLIST auteur id ID #REQUIRED>
<!ATTLIST livre auteur_ref IDREF #REQUIRED>

<auteur id="A001">Victor Hugo</auteur>
<livre isbn="L001" auteur_ref="A001">Les Misérables</livre>
Point Examen - ID/IDREF

2.5 Contenu Mixte

Le contenu mixte permet de mélanger du texte et des éléments enfants.

<!-- Définition contenu mixte -->
<!ELEMENT paragraphe (#PCDATA | gras | italique | lien)*>
<!ELEMENT gras (#PCDATA)>
<!ELEMENT italique (#PCDATA)>
<!ELEMENT lien (#PCDATA)>

<!-- Utilisation -->
<paragraphe>
    Ceci est un texte avec du <gras>texte en gras</gras> 
    et de l'<italique>italique</italique>, 
    plus un <lien>lien cliquable</lien>.
</paragraphe>
Règles du Contenu Mixte
  1. #PCDATA doit être en première position
  2. Utiliser uniquement le choix (|), pas la séquence
  3. Le groupe entier doit utiliser * (zéro ou plus)
  4. Syntaxe obligatoire : (#PCDATA | elem1 | elem2)*

2.6 Déclaration ENTITY

Les entités permettent de définir des raccourcis réutilisables ou d'inclure du contenu externe.

Entités Générales (utilisables dans le document)

<!-- Entité interne (texte de remplacement) -->
<!ENTITY auteur "Jean-Claude Dupont">
<!ENTITY copyright "© 2024 Tous droits réservés">

<!-- Utilisation dans le document -->
<livre>
    <ecrit_par>&auteur;</ecrit_par>
    <footer>&copyright;</footer>
</livre>

<!-- Entité externe (contenu d'un fichier) -->
<!ENTITY chapitre1 SYSTEM "chapitre1.xml">
<livre>&chapitre1;</livre>

Entités Paramétriques (utilisables dans la DTD)

<!-- Définition avec % -->
<!ENTITY % texte "(#PCDATA)">
<!ENTITY % elements_inline "gras | italique | code">

<!-- Utilisation dans la DTD avec %nom; -->
<!ELEMENT titre %texte;>
<!ELEMENT paragraphe (#PCDATA | %elements_inline;)*>
Point Examen - Entités

2.7 Exemple Complet Annoté

Voir l'exemple DTD complet (Système de Gare)
<!-- ================================ -->
<!-- DTD pour un système de gestion de gare -->
<!-- ================================ -->

<!-- Élément racine : une gare contient des trains et des usagers -->
<!ELEMENT gare (train+, usager+)>

<!-- Un train a des voitures et un commentaire optionnel -->
<!ELEMENT train (voiture+, commentaire?)>
<!ATTLIST train 
    numero ID #REQUIRED
    type CDATA #IMPLIED
    destination CDATA #REQUIRED>

<!-- Une voiture peut avoir des réservations OU être un bar -->
<!ELEMENT voiture (resa* | bar)>
<!ATTLIST voiture 
    numero CDATA #REQUIRED
    classe (1 | 2) "2">

<!-- Réservation : élément vide avec attributs -->
<!ELEMENT resa EMPTY>
<!ATTLIST resa 
    numero ID #REQUIRED
    usager_id IDREF #REQUIRED
    place CDATA #REQUIRED>

<!-- Bar : élément vide -->
<!ELEMENT bar EMPTY>
<!ATTLIST bar service (ouvert | ferme) "ouvert">

<!-- Commentaire : contenu mixte -->
<!ELEMENT commentaire (#PCDATA | important)*>
<!ELEMENT important (#PCDATA)>

<!-- Usager avec prénom et nom -->
<!ELEMENT usager (prenom, nom, email?)>
<!ATTLIST usager 
    id ID #REQUIRED
    type (abonne | occasionnel) "occasionnel">

<!ELEMENT prenom (#PCDATA)>
<!ELEMENT nom (#PCDATA)>
<!ELEMENT email (#PCDATA)>

2.8 DTD vs XSD - Comparaison

CritèreDTDXSD
SyntaxeSyntaxe propre (non-XML)Syntaxe XML
TypageLimité (CDATA, ID...)Riche (int, date, patterns...)
NamespacesNon supportésSupportés
HéritageNonExtension/Restriction de types
Cardinalité?, +, *minOccurs, maxOccurs précis
ComplexitéSimplePlus complexe

Quiz - Module 2 : DTD

Testez vos connaissances sur les DTD.

Q1. Quelle cardinalité signifie "1 ou plusieurs" ?

Q2. Pour un contenu mixte, où doit se trouver #PCDATA ?

Q3. Quel type d'attribut référence un ID existant ?

Q4. Que signifie #IMPLIED pour un attribut ?

Q5. Comment déclare-t-on une entité paramétrique ?

Q6. Dans (a, b)?, combien de fois peut apparaître la séquence ?