Pourquoi une DTD pour Ant ? Parcequ'un bon éditeur XML (comme
Emacs associé à
PSGML)
permet de faciliter la tâche lors de l'écriture des fichiers
build.xml si et seulement si l'on dispose d'une DTD
pour ces fichiers. Par exemple, le couple Emacs + PSGML indique
les éléments autorisés en un point du fichier, affiche une
invite (dans le minibuffer) pour compléter les attributs
obligatoires, etc. Bref, une DTD facilite la vie.
De plus, une DTD est obligatoire dans certains cas. Par
exemple lorsqu'on souhaite inclure un fichier A dans un
fichier B. Considérons le fichier suivant :
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE project PUBLIC "-//ANT//DTD project//EN" "project.dtd" [
<!ENTITY include SYSTEM "message.xml">
]>
<project name="test" default="task" basedir=".">
<target name="task">
<echo message="Hello"/>
&include;
</target>
</project>
Il importe, au moyen d'une entité dans la sous DTD interne,
le fichier message.xml que voici :
<echo message="World !"/>
Le résultat de l'appel de Ant est alors :
$ ant
Buildfile: build.xml
Project base dir set to: /home/casa/tmp/test
Executing Target: task
Hello
World !
Completed in 2 seconds
On constate que la tâche définie dans le fichier message.xml
a bien été importée dans le fichier build.xml et
exécutée par Ant.
Je me suis attelé à la tâche (longue et pénible) d'écrire cette
DTD, que l'on peut télécharger ici.
On peut cependant se demander comment il est possible de définir
une telle DTD alors que le jeu des éléments autorisés n'est pas
fixé (puisqu'il est possible de définir ses propres tâches
grâce à l'élément <taskdef>).
Pour contourner le problème, il existe deux solutions :
La première solution consiste à définir les éléments associés aux
tâches définies par l'utiisateur à l'aide de la sous DTD interne
(le fragment de DTD se trouvant dans l'élément DOCTYPE).
Par exemple, si on définit une tâche ayant la forme suivante :
On pourra ajouter dans le DOCTYPE le fragment suivant :
<!ENTITY % ext "| xt">
<!ELEMENT xt EMPTY>
<!ATTLIST xt
xml CDATA #REQUIRED
xsl CDATA #REQUIRED
out CDATA #REQUIRED>
Les rôles de <!ELEMENT> et de <!ATTLIST> sont évidents, par
contre, l'entité <!ENTITY % ext "| xt"> peut paraître plus
mystérieuse. Cette entité est collé à la définition de l'élément
target dans le fichier de la DTD, comme suit :
<!ELEMENT target (ant | ... | zip %ext;)*>
Le fragment | xt est donc ajouté à la définition
et permet alors d'intégrer des éléments <xt> dans un
élément <target>.
Pour qu'une extension soit disponible dans tous les fichiers
build.xml, on peut l'ajouter dans le fichier
project-ext.dtd qui a l'allure suivante :
<!ENTITY % ext "| xt">
<!ELEMENT xt EMPTY>
<!ATTLIST xt
xml CDATA #REQUIRED
xsl CDATA #REQUIRED
out CDATA #REQUIRED>
Le principe est le même que dans la méthode précédente, mais
ce fichier est inclus dans la DTD des projets de manière
permanente, à l'aide de :
<!ENTITY % ext-file SYSTEM "project-ext.dtd">
%ext-file;
Le choix de la méthode de définition des extensions
dépendra de la disponibiité souhaitée pour l'extension
(de la même manière que l'on peut inclure les classes
Java d'une extension dans un jar séparé ou dans celui
des classes de Ant, pour qu'elles soient toujours disponibles).