Un parser HTML des plus léger

Eléphant du PHP | 121 Messages

16 août 2008, 03:13

Bonjour,

Dans le l'optique de l'amélioration perpétuelle, je viens de mettre un grand coup au moteur de publication de mon CMS. J'utilisais jusqu'à présent preg_match_callback() pour traiter les gabarits, ce qui était assez lourd, et surtout n'autorisait pas la moindre imbrication de même type...

Ce matin j'ai donc réfléchi très fort et j'ai pondu (aïe) un parser HTML des plus simple, léger et merveilleux.

Il prend un texte HTML (ou XML) et crée un arbre de nœuds _texte_ et _marqueur_. Il est possible de préciser un espace de noms pour ne récupérer que les marqueurs de l'espace de noms (ce qui me sert pour mon CMS). On peut également préciser l'encodage (utf-8 par défaut bien sûr), les valeurs des attributs des marqueurs étant _désachappées_ pour la plus grande joie des grands et des petits.

Vous trouverez tout ça sur mon blog : Un parser HTML des plus rapide et léger

Un piti exemple qui utilise l'espace de noms 'wdp:'

Code : Tout sélectionner

<wdp:articles limit="5"> <ul> <wdp:foreach> <li>{this.title}</li> </wdp:foreach> </ul> </wdp:articles>
<?php

$parser = new WdHTMLParser();

$tree = $parser->parse($template, 'wdp:');

echo '<pre>' . print_r($true, true) . '</pre>';

?>

Code : Tout sélectionner

Array ( [0] => Array ( [name] => articles [args] => Array ( [limit] => 5 ) [children] => Array ( [0] => <ul> [1] => Array ( [name] => foreach [args] => Array ( ) [children] => Array ( [0] => <li>{this.title}</li> ) ) [2] => </ul> ) ) )

ViPHP
ViPHP | 5924 Messages

16 août 2008, 11:31

C'est un parseur XML non ? Pourquoi ne pas simplement utiliser SimpleXML, il apporte quelquechose de plus ?

ViPHP
ViPHP | 4674 Messages

16 août 2008, 18:29

(J'ai écrit un commentaire sur ton site à propos de ton parseur, je le remets ici) :
Hey :),

C'est pas mal mais j'ai quelques questions :
1. pourquoi ne pas utiliser les fonctions de PHP qui sont appropriées (voir <http://php.net/xml>) ? ;
2. pourquoi ne pas utiliser même SimpleXml (voir <http://php.net/simplexml>), quitte à faire un wrapper ? ;
3. pourquoi ne gères-tu pas les CDATA ?

Pour les questions 1 et 2, tu gagnerais en rapidité. SimpleXML est totalement écrit en C, c'est donc plus rapide. D'autant qu'il permet la gestion du DOM, XPath, etc. De plus, SimpleXML est installé sur toutes les machines PHP 5 par défaut. Concernant les fonctions PHP pour la gestion des documents XML, elles sont également écrites en C (on l'aurait deviné ;-)) et sont même disponibles depuis PHP 4.
« Un handicap est le résultat d'une rencontre entre une déficience ou différence et une incapacité de la société à répondre à celle-ci. »

Hoa : http://hoa-project.net (sur @hoaproject).

Eléphant du PHP | 121 Messages

19 août 2008, 17:12

Comme le titre du post le laisse supposer, il s'agit d'un parser HTML et non XML. Évidement il digèrera très bien le XML mais c'est pour digérer du HTML lâche qu'il a été crée.

Pour mon CMS j'ai besoin d'un parser basique qui se contente de lire les marqueurs (si possible ceux de l'espace de noms précisés) et de renvoyer un arbre. Il lit des gabarits qui sont des morceaux de HTML dedans, avec des marqueurs de contrôle spécifiques. Je ne trouvais pas mon bonheur, alors je l'ai crée.

J'ai abandonné très vite l'idée d'utiliser SimpleXML avec le genre de gabarits suivant :

Code : Tout sélectionner

<div id="respond"> <h2>Poster un commentaire</h2> <wdp:comments:form> <wdp:choose> <wdp:when test="this.ok"><p>Merci de votre contribution.</p></wdp:when> <wdp:when test="this.missing"><p>Merci de remplir les champs obligatoires qui sont marqués d'une astérixe&nbsp;:</p></wdp:when> <wdp:when test="this.spam"> <p>Avec un score de {this.spam}, votre message est considéré comme du spam, ce qui peut arriver s'il est trop court ou pénible. Essayez donc d'écrire quelque chose d'intéressant ;-)</p> <p>Si vous avez la chance d'être membre du site, connectez-vous. Vos messages seront toujours les bienvenus, même s'ils sont courts et pénibles.</p></wdp:when> </wdp:choose> <wdp:otherwise>{this.form}</wdp:otherwise> </wdp:comments:form> </div> <div id="comments"> <wdp:comments order="asc"> <wdp:foreach> <div id="respond-{this.id}" class="comment {_foreach.even}"> <h4> <var>{_foreach.position}</var> <wdp:choose> <wdp:when test="this.url"> <a href="{this.url}">{this.author.entities()}</a> </wdp:when> <wdp:otherwise>{this.author.entities()}</wdp:otherwise> </wdp:choose> a écrit&nbsp;: <small> {this.created.ftime('%A %d %B %Y', NULL, true)} à {this.created.ftime('%H:%M', NULL, true)} </small> </h4> {this.contents.textmark()} </div> </wdp:foreach> </wdp:comments> </div>
Modifié en dernier par Gofromiel le 20 août 2008, 15:14, modifié 1 fois.

ViPHP
ViPHP | 4674 Messages

19 août 2008, 22:46

Pourquoi abandonner SimpleXML au juste ?
« Un handicap est le résultat d'une rencontre entre une déficience ou différence et une incapacité de la société à répondre à celle-ci. »

Hoa : http://hoa-project.net (sur @hoaproject).

Mammouth du PHP | 1511 Messages

19 août 2008, 23:16

Pourquoi abandonner SimpleXML au juste ?
A cause du code HTML, certaines fois dégueulasse, qui serait refusé par SimpleXML...

ViPHP
ViPHP | 4674 Messages

20 août 2008, 01:58

Bah justement, c'est une sécurité de plus. C'est un peu bête comme argument :?, je dirais illogique en fait.

SimpleXML sait lire les DTD, plus facile pour faire ses propres espaces de nom pour son propre moteur de template non ? Et sous prétexte qu'un code serait mal écrit, il faut quand même le tolérer ? C'est ça que je trouve illogique …
« Un handicap est le résultat d'une rencontre entre une déficience ou différence et une incapacité de la société à répondre à celle-ci. »

Hoa : http://hoa-project.net (sur @hoaproject).

Eléphant du PHP | 121 Messages

20 août 2008, 15:09

Essaie de parser le bout de code que j'ai donné plus haut avec SimpleXML. Ça demande juste trop de temps et d'investissement pour obtenir quelque chose de tout simple (un arbre). Vu la dizaine de gabarits de ce type que mon CMS doit interpréter pour générer les sites, SimpleXML me parait pénible...

J'ai aussi besoin que *seul* les marqueurs dans l'espace de noms 'wdp:' soient collectés, et que les autres (HTML) soient traités comme du texte (ce qu'ils sont du point de vue du gabarit). Est-ce que SimpleXML me permet de réaliser cela facilement ? Déjà qu'il est exceptionnellement pénible avec tout ce qui est échappé (e.g. &nbsp;...)

ViPHP
ViPHP | 4674 Messages

20 août 2008, 15:25

Comme suggérer sur ton site en commentaire, tu peux faire un wrapper :).

Il faut comprendre que SimpleXML est très rapide face à PHP. C'est pour ça que j'insiste un peu. Et même utiliser SimpleXML + un wrapper serait plus rapide que PHP tout seul.
« Un handicap est le résultat d'une rencontre entre une déficience ou différence et une incapacité de la société à répondre à celle-ci. »

Hoa : http://hoa-project.net (sur @hoaproject).