Cette semaine, un article assez spécifique, dont l'enjeu est de tester une nouvelle fonctionnalité de php dans sa version 4.3.0.
La fonctionnalité en question porte sur la validation de DTD, d'un fichier XML, via l'extension DOM.

Les intérêts d'une telle validation sont nombreux dès que l'on se propose de manipuler du contenu XML est que l'on veut pouvoir garantir que la syntaxe et la grammaire sont bien conformes.
Cela peut en pratique s'appliquer sur des flux entrant provenant d'un serveur tiers, ou dans le même ordre d'idée avant de publier un flux XML vers l'extérieur.

Tout d'abord il est nécessaire d'installer php dans sa version 4.3.0. a l'heure où cet article est rédigé, la dernière version disponible est la 4.3.0 pre2, disponible ici.
Option de configuration minimales pour disposer du support DOM :

$ ./configure --with-dom --with-zlib 
$ make
# make install
Ensuite, nous allons prendre un exemple de fichier XML disposant d'une DTD connu :

<?xml version="1.0" encoding='ISO-8859-1'?>
<!DOCTYPE sect1 PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">

<sect1 id="test.dom-dtd">
 <strong>Test</strong>
 <para>
  Ce petit fichier XML, est juste là histoire d'avoir un contenu
  utilisant une DTD existante...
 </para>

</sect1>
Pour le besoin du test, le fichier doit être nommé test.xml, de plus je vous invite à disposer le tout dans un répertoire spécifique.
La fonction de php du support DOM permettant la validation d'un document est domxml_doc_validate.
Soit le code suivant, permettant à la fois de vérifier la validation en terme syntaxique du XML (Well-formed), ainsi que la validation par rapport à la DTD défini dans le document XML.

<?php

$error = array(); 

// chargement en mémoire du fichier xml
$dom = @xmldocfile('test.xml', DOMXML_LOAD_VALIDATING, $error);

// test pour voir si le document xml est 'well formed'
if(!is_object($dom)){
    echo("Le document XML n'est pas 'Well Formed' !\n");
    die(print_r($error));
}

// test pour voir si le document est conforme à sa DTD
if(!@domxml_doc_validate($dom, $error)){
    echo "Validation DTD n'est pas OK\n";
    print_r($error);
} else {
    echo "Validation OK\n";
}

?>
En utilisant, le code de test précedent, le retour doit être 'Validation OK'.
Néanmoins cette solution n'est que partiellement intéressante vu que le fichier de DTD se trouve en distant et que le temps de validation est de se fait très longue (plusieurs secondes sur de l'ADSL 1024Kb/s).

Il est donc préférable d'utiliser une DTD 'locale' pour valider le document, soit dans notre exemple :

- télécharger l'archive DocBook suivante.
- Puis la décompresser dans le répertoire courant.
- Et modifier le fichier test.xml en remplaçant la ligne DOCTYPE par la suivante :
<!DOCTYPE sect1 PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "docbookx.dtd">
Enfin, pour avoir un retour négatif en terme de validation, il suffit de modifier le fichier test.xml et de rajouter une balise imaginaire au vu de la DTD. Par exemple la balise n'existe pas en DocBook :)

<?xml version="1.0" encoding='ISO-8859-1'?>
<!DOCTYPE sect1 PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
"docbookx.dtd">

<sect1 id="test.dom-dtd">
 <strong>Test</strong>
 <para>
  Ce petit fichier XML, est juste là histoire d'avoir un contenu
  utilisant une DTD existante...
 </para>
 <pipo>
  celà ne va sûrement pas le faire... :)
 </pipo>
</sect1>