La DTD est utilisée pour normaliser la structure d'un document XML. On y trouve des indications sur la façon dont les éléments vont s’emboiter les uns dans les autres. On y trouvera également des informations sur les attributs des éléments. La DTD c'est la loi XML… et l'ordre !
Premier point, où mettre une DTD ??? Et bien c'est très simple :
Ensuite concernant la DTD externe, on distingue là aussi 2 types de DTD :
Comme expliqué plus haut, la DTD est située dans le prologue du document XML, on la trouve entre la déclaration XML et le noeud racine.
La Déclaration de DTD est facile à repérer, elle commence par <!DOCTYPE…
Selon le type de DTD (Interne ou externe) la syntaxe est différente :
<?xml version="1.0" encoding="utf-8" ?> <!-- La DTD commence ICI --> <!DOCTYPE elementRacine [ <!-- Contenu de la DTD ICI --> ]> <!-- La DTD s'arrête là --> <elementRacine> </elementRacine>
<?xml version="1.0" encoding="utf-8" ?> <!-- La DTD commence ICI --> <!DOCTYPE elementRacine *PUBLIC/SYSTEM* "Infos DTD" "URL du fichier.dtd"> <elementRacine> </elementRacine>
Pour comprend ce qu'on a devans les yeux, prenons une DTD célébre :
<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
Vous l'avez reconnu, c'est le petit bout de texte à mettre en haut des pages HTML, vous allez enfin savoir d'où sa viens.
<!DOCTYPE : Ca on connait, ca veut dire qu'on a affaire à une DTDhtml : C'est le nom de l'élément racine, dans une page XHTML c'est la balise htmlPUBLIC : Indique que la DTD est public, on devrait trouver l'URL du fichier un peu plus loin."-W3C//DTD XHTML 1.0 Transitional//EN" : Alors cette chaîne c'est une sorte de numéro de série, en théorie elle se compose ainsi :
N°d'enregistrement//Propriétaire//Nom de la DTD//LangueDonc si on décompose, le numéro d'enregistrement c'est un tiret (Pas de numéro officiel), ensuite le propriétaire (W3C), le nom de la DTD (DTD XHTML 1.0 Transitional), et efin la langue (EN → Anglais).
Enfin vous pouvez "mixer" les 2, c'est à dire charger une DTD externe et la compléter en interne (pour y ajouter des entitées par exemple) :
<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE Racine SYSTEM "fichier.dtd" [ <!ENTITY auteur "Stéphane Bouvry"> ]> <Racine>&auteur;</Racine>
Et voici le contenu de la DTD :
<!ELEMENT Racine (#PCDATA)>
Nous aborderons le contenu plus précisément par la suite.
Voyons maintenant comment fixer les éléments autorisés dans un document XML.
La syntaxe se présente ainsi :
<!ELEMENT nomElement *type d'élément*>
La partie nomElement c'est le nom de la balise
Ensuite on va trouver le type d'élément : Texte, vide, une serie d'élément donnée ou un choix entre différents éléments.
Si notre élément contient du texte nous le préciserons ainsi :
<!ELEMENT nomElement (#PCDATA)>
#
Cette déclaration nous obligera a avoir un nœud comme ça :
<nomElement>Contenu texte uniquement</nomElement>
Pour imposer qu'un élément soit vide, vous devez utiliser le type EMPTY :
<!ELEMENT monElement EMPTY>
Ainsi le nœud devra avoir cette forme :
<monElement />
Les séquences d'éléments sont placées entre parenthèses (comme le #PCDATA), et les éléments enfants sont placés dans l'ordre d'apparition :
<!ELEMENT cours (titre, soustitre, partie)>
Dans cet exemple, l'élément cours devra obligatoirement contenir un élément titre, suivi d'un élément soustitre et enfin un élément partie :
<cours> <titre>...</titre> <soustitre>...</soustitre> <partie>...</partie> </cours>
Dans cet exemple vous devez également penser à déclarer les éléments titre, soustitre et partie :
<!ELEMENT cours (titre, soustitre, partie)> <!ELEMENT titre (#PCDATA)> <!ELEMENT soustitre (#PCDATA)> <!ELEMENT partie (#PCDATA)>
Vous pouvez enfin proposer un choix entre plusieurs éléments :
<!ELEMENT partie (introduction | developpement)>
Dans cet déclaration, l'élément partie devra contenir soit un élément introduction, soit un élément developpement, pas les 2, ni autre chose.
Les indicateurs d’occurrences s'utilisent avec les éléments de type Séquence ou Choix, leur but est simplement d'indiquer combien de fois vont apparaître les éléments.
Les indicateurs d'occurence :
| Symbole | Effet |
|---|---|
* | L'élément peut apparaître 0 à N fois |
? | L'élément peut apparaître 0 à 1 fois |
+ | L'élément doit apparaître au moins une fois |
Prenons cet exemple sans indicateur d'occurrence :
<!ELEMENT cours (introduction, explication, exemple, conclusion)>
Le cours contiendra une introduction, puis une seule explication, suivit d'un exemple, et enfin d'une conclusion.
Nous allons modifier la déclaration pour permettre à nos cours de contenir 1 ou plusieurs explication, suivit ou pas d'un exemple, et enfin une conclusion) :
<!ELEMENT cours (introduction, explication+, exemple?, conclusion)>
Les indicateurs d'occurrence peuvent également servir dans les éléments de type choix, imaginons un XML servant à décrire les différents niveaux d'un jeux vidéos. Le jeux contient 1 à plusieurs niveaux, et chaques niveaux peux contenir soit :
Le fichier pourrait ressembler à ça :
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE jeu [
<!-- Notre jeu contient 1 à X niveaux -->
<!ELEMENT jeu (niveau+)>
<!-- Le niveau contient soit des méchants, ou un boss -->
<!ELEMENT niveau (mechant* | boss)>
<!-- Sprite -->
<!ELEMENT mechant EMPTY>
<!ELEMENT boss (#PCDATA)>
]>
<jeu>
<niveau>
<mechant />
<mechant />
</niveau>
<niveau>
<mechant />
<mechant />
<mechant />
</niveau>
<niveau>
<boss>Gros BOSS !</boss>
</niveau>
</jeu>
Bon je ne l'ai jamais tester, mais le type freestyle permet de mettre dans l'élément tout les éléments déclaré dans le DTD, dans n'importe quel sens… n'importe comment… C'est le type L'ARACHE :P
<!ELEMENT grosBordel ANY>
Enfin, vous pouvez combiner ça dans tout les sens pour obtenir des structures XML précises. Et ce en utilisant les parenthèses.
Reprenons l'exemple des cours XML, nous allons définir une DTD de tel sorte que le cours ai :
Dans une section on aura :
Ce qui donne :
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!DOCTYPE cours [
<!ELEMENT cours (titre, description, introduction, section+, conclusion)>
<!ELEMENT titre (#PCDATA)>
<!ELEMENT description (#PCDATA)>
<!ELEMENT introduction (#PCDATA)>
<!ELEMENT section (titre, introduction?, (explication | exemple | note)*, conclusion?)>
<!ELEMENT explication (#PCDATA)>
<!ELEMENT exemple (#PCDATA)>
<!ELEMENT conclusion (#PCDATA)>
<!ELEMENT note (#PCDATA)>
]>
<cours>
<titre>Cours XML</titre>
<description>Découvrez le langage XML</description>
<introduction>A l'origine des temps...</introduction>
<section>
<titre>Type d'élément</titre>
<note>Note de section</note>
<explication>Mon explication</explication>
<exemple>Exemple 1</exemple>
<exemple>Exemple 2</exemple>
<explication>Explication</explication>
</section>
<conclusion>Pour finir...</conclusion>
</cours>
Nous venons de dégrossir le cas des éléments, nous allons pouvoir nous occuper des attributs. Un peu comme pour les types d'éléments, les attributs peuvent avoir un type spécifique, on peut également lui donner une valeur par défaut.
Pour la syntaxe, je vous rappelle que les attributs sont dépendants d'un élément, donc nous trouverons, le nom de l'élément, puis la liste de ces attributs avec leurs caractèristiques, ça aura cette tête là :
<!ATTLIST element
attribut1 TYPE ["Valeur par défaut"] CONTAINTE
attribut2 TYPE ["Valeur par défaut"] CONTRAINTE
>
Bon si vous n'avez qu'un seul attribut, rien ne vous empèche de tout écrire sur une seule ligne :
<!ATTLIST element attribut1 TYPE CONTAINTE>
L'important c'est d'arriver à se relire.
Une valeur de type Chaîne de caractère est représentée par le mot CDATA.
Voici un exemple de déclaration de type Chaîne :
<!ATTLIST cours auteur CDATA #IMPLIED >
Dans cet exemple, l'élément cours a un attribut facultatif1) auteur, cet attribut peu contenir n'importe quel texte.
Il existe 3 types de contrainte :
#IMPLIED : Indique que l'attribut est facultatif.#REQUIRED : L'attribut doit être présent dans l'élément.#FIXED : L'attribut doit être présent et a une valeur fixe.