DOM sur php.net
N'oubliez pas de consulter régulièrement
la page DOM de php.net, très utile : vous y trouverez toutes les classes. Leurs méthodes sont listées en premier, puis viennent leurs variables dans un tableau : autant d'informations indispensables !
Allez plus loin grâce à DOM
Si vous êtes un peu curieux, vous avez remarqué que mon parseur ne gère pas :
- les caractères accentués (é, à, ç, …) ;
- les smilies ;
- quelques balises zcode ;
- la balise <code>
;
- les erreurs de rédaction (balises mal fermées…).
Ce qui, au final, fait pas mal de choses !

Je n'ai pas abordé ces notions pour ne pas vous donner trop d'informations à mémoriser,
mais vous pouvez faire certaines choses par vous-mêmes ! Voici quelques pistes pour vous exercer et améliorer votre parseur.
Coloration du code
Vous allez pouvoir colorer votre code grâce à GeSHi (
consultez ce tuto pour découvrir GeSHi). Je vous recommande de vous entraîner avec ce parsage, cela va vous former.
Il faut d'abord que vous transformiez le contenu des nœuds
code en section
CDATA. Je vous laisse chercher comment faire. Puis il va falloir qu'à chaque nœud
code rencontré on récupère le contenu de la section
CDATA. À tout hasard, j'ajoute qu'une instance de
DOMNode a une variable qui renferme le premier nœud,
firstChild. Je précise aussi que pour récupérer le contenu d'une section
CDATA, on utilise la variable d'instance
data.
Je ne vous en dis pas plus, bon courage !
…
C'est bon ? Allez, je vous donne quelques pistes :
Secret (cliquez pour afficher)
Notez que c'est encore à améliorer, car le code ci-dessus ne parse pas tous les langages… cherchez du côté des attributs
type et de leur contenu.
Code : PHP | <?php
include_once('geshi.php');
function parsage_cdata($cdata, $type_code = 'php')
{
$geshi =& new GeSHi($cdata, $type_code);
$geshi->set_header_type(GESHI_HEADER_NONE);
$parse = $geshi->parse_code();
$resultat = '<span class="code">Code : '. $type_code .'</span><div class="code2 '. $type_code .'">'. $parse .'</div>';
return $resultat;
}
?>
|
Voici la fonction
parsage_cdata :
Code : PHP 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 | <?php
function parsage_enfant($noeud)// Fonction de parsage d'enfants
{
if(!isset($accumulation)) // Si c'est la première balise, on initialise $accumulation
{
$accumulation = '';
}
$enfants_niv1 = $noeud->childNodes; // Les enfants du nœud traité
foreach($enfants_niv1 as $enfant) // Pour chaque enfant, on vérifie…
{
if($enfant->nodeName == 'code')
{
$cdata = $enfant->firstChild->data;
$type_code = $enfant->attributes->getNamedItem('type')->nodeValue;
$resultat_html .= parsage_cdata($cdata, $type_code);
}
elseif($enfant->hasChildNodes() == true) // … s'il a lui-même des enfants
{
$accumulation .= parsage_enfant($enfant); // Dans ce cas, on revient sur parsage_enfant
}
else // ... s'il n'en a plus !
{
$accumulation .= parsage_normal($enfant); // On parse comme un nœud normal
}
}
return parsage_normal($noeud, $accumulation);
}
?>
|
La nouvelle fonction
parsage_enfant :
Remplacez les crochets par des chevrons ! J'ai dû effectuer ce changement pour éviter un bug du zcode, mais n'oubliez pas de faire cette modification, ou cela ne fonctionnera pas !
Code : PHP | <?php
$chaine = preg_replace("#[code(\stype="(.+)")](.+)[/code]#isU", "[code type="$2"]<![CDATA[$3]]>[/code]", $chaine);
?>
|
Pour transformer en
CDATA, insérez la Regex ci-dessous dans
parsage et modifiez un peu le code au besoin.
Vous voyez, ce n'était pas si difficile que ça.
Gestion des caractères accentués
Nous autres, pauvres Français, utilisons des accents dont nos confrères anglophones se moquent royalement.
Laissez-moi vous expliquer : les développeurs de DOM sont sûrement anglais ou n'ont pas voulu s'embêter à gérer les caractères accentués. On ne va pas leur en vouloir, mais c'est quand même un grave problème pour nous. Exemple :
CitationLe site du z@©&ro.
Avouons que ce n'est pas lisible. Bien que l'en-tête du document XML contienne l'encodage, DOM l'ignore (quel grincheux

) et code tout en
UTF-8, incompatible avec notre propre norme qui est, je le rappelle,
ISO-8859-1. Conclusion, nous allons
à la sortie du parsage décoder tout ce joyeux bazar pour obtenir du bon français, digne des plus grands auteurs classiques. La solution tient en un mot (ou en une fonction) :
utf8_decode, notre sauveur.
C'est donc la dernière ligne de la fonction
parsage($document) qu'il faut changer :
Code : PHP | <?php
return utf8_decode($resultat_html);
?>
|
Et voilà !
Je tiens à dire que le problème d'encodage n'est pas aussi simple que ce je viens d'expliquer sommairement. Il est tout à fait possible d'obtenir des caractères accentués en UTF-8, comme le fait le Site du Zéro. C'est, très grossièrement, une histoire de « rangement » et d'attribution de valeurs. Par exemple, la valeur 468 renvoie « é » en ISO-8859-1 mais « @ » en UTF-8 (ce sont des exemples non vérifiés). Ce dernier encodage est d'ailleurs censé être universel, c'est-à-dire que vous pouvez aussi bien écrire en grec qu'en chinois avec de l'UTF-8. Cependant, des manipulations sont nécessaires pour parvenir à afficher correctement les accents en UTF-8, ce qui n'est d'ailleurs pas dans l'intérêt de tous les sites.
Les « zForms » ou formulaires
Vous savez que la zForm du Site du Zéro propose deux aperçus : l'un se réalise en temps réel, l'autre génère l'affichage final. Le premier est codé en JavaScript, le second utilise AJAX — et donc le parseur PHP. Vous pouvez éventuellement réaliser sans trop de difficultés le second aperçu ; le premier devra quant à lui être retouché et adapté pour le JavaScript.
Améliorations diverses
Les
smilies. Faut pas les laisser tomber ceux-là, hein ? On peut les introduire dans notre parseur avec
str_replace ou des Regex, par exemple.
Essayez aussi de vous entraîner à utiliser DOM en tentant de parser les balises
<tableau>
; elles sont très intéressantes. Pensez également à la gestion de chaînes de caractères contenant le texte à parser, ou encore à un module de sauvegarde.
Et pour gérer les erreurs de syntaxe ?
Alors il faudrait parler des
DTD, ce qui serait trop long. Cependant, cela fera peut-être l'objet d'un futur tutoriel. Notez aussi que l'on peut parser en utilisant des feuilles de style XSLT, mais c'est encore une autre histoire.
N'hésitez pas non plus à créer des fonctions qui gèrent les « exceptions » — je parle ici de balises originales —, les erreurs, etc.
La sécurité avec DOM
J'ai vu dans de nombreux forums et dans les commentaires de ce tuto des interrogations quant à la
sécurité d'un tel système. Vous n'êtes pas sans savoir que la sécurité est quelque chose de très important en informatique ; se poser des questions à ce sujet est donc tout à fait justifié. Nous allons considérer le cas de tentatives de violation de sécurité simples.
EXEMPLE 1 : une des failles les plus connues consiste à insérer dans un formulaire du contenu JavaScript exécutable. Par exemple, dans un système non sécurisé, l'insertion du code ci-dessous affichera un message : « Mouahaha ton système n'est pas sécurisé ».
Code : JavaScript | <script type='text/javascript'>
alert('Mouahaha ton système n\'est pas sécurisé.');
</script>
|
Évidemment, par la suite, on pourrait exploiter la faille de manière bien plus nuisible.
Dans le cas d'un parseur XML, tout va pour le mieux. DOM interprète cet extrait de code comme un nœud normal et l'envoie donc à
parsage_normal. Dans la fonction
parsage_normal, on recherche pour chaque nom de nœud s'il correspond à une balise HTML quelconque (exemple :
<paragraphe>
correspond à
<p>
). Si ce n'est pas le cas, la balise et son contenu ne sont pas parsés (au sens qu'ils ne seront pas traduits en XHTML), car
$premiere_balise ne contient rien (
$balise_2 non plus). Quand on construit
$intermediaire, la variable ne contient que le contenu du nœud script, soit : «
alert('Mouahaha ton système n'est pas sécurisé.''); ». Et c'est d'ailleurs tout ce qui s'affichera à l'écran.
EXEMPLE 2 : on pourrait également introduire le code suivant.
Code : Autre1
| <meta http-equiv='refresh' content='0; url=http://hacker.php' /> |
Mais là, il n'y a absolument aucun danger. Si
<meta/>
ne fait pas partie du zCode (ou de votre langage), rien ne s'affichera.
On peut toujours rechercher des moyens de sécuriser davantage son système ; à vous de trouver les bons endroits où placer quelques fonctions intéressantes.
Comment intégrer intelligemment son parseur à son site ?
J'ai remarqué que beaucoup de personnes, notamment dans les commentaires, hésitaient sur la façon d'utiliser un parseur XML. Je vous propose un modèle parmi d'autres, en supposant que vous utilisez MySQL comme base de données. De plus, je considère que vous souhaitez que l'on puisse :
- écrire du contenu (dans les forums, les tutoriels, le livre d'or, que sais-je encore
) ;
- éditer n'importe quel contenu en zCode ;
- l'afficher correctement en XHTML, bien sûr ;
- exporter son contenu en zCode dans des fichiers XML.
Je vous propose ceci :
Comment bien intégrer un parseur XML à son site
Évidemment, à vous de déterminer quelle organisation vous correspond le mieux. Là, seuls le papier et le crayon seront vos compagnons, mais aussi vos plus sûrs alliés !
Erreurs de code
Autant vous le dire franchement, il est rare que cela fonctionne du premier coup, surtout si vous modifiez le code que je vous ai proposé.
C'est une gymnastique très surprenante au début, voilà pourquoi il est capital que vous maîtrisiez parfaitement les bases de DOM présentées ici. Voici les principales sources d'erreur que j'ai pu relever.
- Vérifiez votre version de PHP et sa configuration.
- Utilisez loadHTML au lieu de loadXML si vous chargez un document HTML.
- N'oubliez jamais (c'est la cause d'une erreur sur deux) de préciser l'encodage, dans le fichier XML ou bien dans votre code même.
- Vérifiez que votre document XML est correctement formé.
Le problème du code ci-dessus, c'est que les messages d'erreur indiquent rarement les bonnes lignes. N'hésitez pas non plus à tester les autres lignes en cas de
bugs.
Le choix de DOM
Ce tutoriel touche à sa fin. Vous avez maintenant une idée claire de ce qu'est le parsage XML, du moins dans ses grandes lignes. C'est donc maintenant que vous savez dans quoi vous vous lancez en décidant d'utiliser DOM plutôt que des Regex.
N'oubliez pas qu'on ne choisit pas un outil pour montrer ou dire qu'on l'utilise, mais seulement si cet outil s'avère utile pour son projet.
DOM a d'énormes avantages d'un point de vue structurel et organisationnel. En revanche, pour certains langages, les Regex seront bien plus rapides et adaptées. Le choix de l'une ou l'autre de ces technologies va avoir une influence très forte sur votre site entier. Dressez d'abord une liste de ce dont vous avez besoin et comparez les fonctionnalités proposées par DOM avec celles proposées par les Regex. Prenez celui qui ira le mieux, en faisant la balance entre court terme et long terme. DOM demande beaucoup d'investissement (intellectuel, bien sûr, pas financier

), ne vous lancez pas dedans à la légère.
Après ce petit conseil d'ami, passons au QCM !
