Parser xml et php ne font pas bon ménage
Par Laurentj le jeudi, janvier 6 2005, 11:33 - Technologies Web - Lien permanent
Beaucoup d'utilisateurs de Nvu demandent une meilleure prise en charge des balises php lors de l'édition d'un document HTML. Le problème est que PHP n'a pas été pensé pour être pris en compte de façon transparente lors d'un parsing d'un document HTML/XHTML. Et cela pose énormément de problèmes pour qu'un parser XML puisse interpreter correctement les balises PHP dans un source PHP.
Voici quelques explications.
Ainsi dans PHP, ?> n'indique pas forcément la fin d'un bloc PHP. On peut très bien avoir :
<p><?php echo "?>"; ?></p>
L'exécution de ce bout de code produisant <p>?></p>.
Or un parser xml lui, lors de l'analyse du fichier HTML verra les éléments suivants:
<p>(noeud élément)<?php echo "?>(noeud processing instruction)"; ?>(noeud texte)
On a le même problème avec les commentaires :
<p><?php echo "bla"; /* ?> */ ?></p>
Le parser xml verra :
<p>(noeud élément)<?php echo "bla"; /* ?>(noeud processing instruction)*/ ?>(noeud texte)
Pour un parser SGML (c'est le cas de Nvu dans lequel on ne peut éditer pour le moment que du HTML), s'ajoute le problème suivant :
<p><?php if($a > 12) echo 'foo'; ?></p>
En effet, pour lui, la fin d'une "processing instruction" est > et non pas ?> comme en xml. On obtient donc le DOM :
<p>(noeud élément)<?php if($a >(noeud processing instruction)12) echo 'foo'; ?>(noeud texte)
Bref, ces exemples montrent que l'on se retrouve avec des noeuds texte qui ne devraient pas exister. Ils apparaîtront donc en tant que texte lors de la visualisation du document.
Une solution serait alors de hacker le parser xml pour prendre en compte l'analyse de l'intérieur des balises php
- détecter le début d'un bloc php
- parser de la même manière que le parser du moteur PHP (c'est à dire, détection des chaînes PHP, des commentaires, des opérateurs etc...)
- détecter la fin d'un bloc php, en prenant en compte uniquement les
?>qui sont en dehors d'éléments PHP (chaînes et commentaires principalement)
C'est du boulot, ça rend le parser un plus lent, mais c'est faisable.
Malheureusement il existe un autre problème, que l'on ne peut résoudre. Voici un bout de code :
<p> <?php echo "</p>"; ?>
Un parser XML ralera car il ne trouve pas la balise de fermeture de <p> : le document n'est pas éditable. Il verra seulement une "processing instruction". Un parser SGML (donc HTML) ne ralera pas mais n'interpretera pas ça de la façon que l'on veut :
<p>(noeud element)<?php echo "</p>(noeud processing instruction)"; ?>(noeud texte)
Même problème (sinon pire) avec :
<?php echo "<p>"; ?> foo</p>
Bref, ces cas sont un véritable problème qu'il est impossible de résoudre dans un éditeur orienté balisage SGML/XML comme Nvu. C'est au développeur d'avoir un code PHP propre, où toutes les balises ouvertes/fermées en dehors des blocs PHP doivent être fermées/ouvertes en dehors des blocs PHP.
Reste le cas où les blocs PHP génèrent eux-mêmes à la fois les balises ouvrantes et fermantes :
<?php echo '<p>bla bla</p>';?>
Dans un éditeur wysiwyg, qui n'exécute pas par nature le code PHP, on ne verra jamais le paragraphe "bla bla". Finalement, éditer un fichier PHP dans un éditeur wysiwyg n'a pas toujours de sens, puisqu'on ne voit pas vraiment ce qu'on aura. Éditer un fichier PHP dans ce genre d'éditeur revient à faire du wysimwyg : What You See Is Maybe What You Get. Aucun intérêt.
Le mieux, dans une application PHP, serait d'utiliser un moteur de template dont le balisage n'a pas d'incidence sur l'interprétation du document brut. Et encore...
Commentaires
Salut Laurent !
Tidy ne se sort pas trop mal des cas que tu présentes, mélangeant (x)html et PHP même s'il ne peut pas résoudre le cas :
Sinon le résultat est intéressant, car il est aussi basé sur un parser qui: "The parser works top down, building a complete parse tree in memory."
J'espère que son code source pourra t'inspirer ou être utile :)
Je parlais des parsers en général. Il est en effet toujours possible de développer son propre parser qui limite les dégats. Mais bon, refaire expat (utilisé entre autre et en partie dans Mozilla)... :-) J'aurais préféré que PHP soit xml compliant :-) (cela voudrait dire que PHP soit presque un langage xml..)
De toute façon, les vrais développeurs n'éditent pas leurs pages PHP dans un editeur wysiwyg html. Ça n'a pas de sens :-p
Les vrais développeurs utilisent notepad (sous windows)
Les vrais développeurs n'utilisent pas Windows ;)
les vrais développeurs... ...ne devraient pas s'immaginer pouvoir éditer des documents php avec un éditeur wysiwyg html comme nvu. Au début, j'ai fait de l'asp avec frontpage. Quand aujourd'hui je dois reprend ces veilleries, je peste, car immanquablement la source html est de la bouillie. Pour travailler, maintenant je fais une maquette html avec un éditeur wysiwyg, pour bosser la présentation, puis je prend un éditeur de code pour ajouter le code php, et une fois qu'il y a du php, pas question de reprendre un wysiwyg. Et si je fait du xhtml strict, ce qui m'arrive parfois, ou du perl, je ne prend qu'un éditeur de texte (notepad++), et finalement je trouve que c'est plus efficace comme ça, le résultat est BEAUCOUP plus propre et maintenable.
Je comprend le cauchamard de D.Glazman, mais il me semble que ça ne vaut pas la peine de se battre pour ça.
Les vrais dévelopeurs utilisent perl.
http://perso.hirlimann.net/~ludo/blog/archives/000479.html
D'ailleurs pour démontrer à quel point les deux exemples présentés sont complexes à parser, PHP lui même ne sait pas le faire :-) (je viens de retester avec un php4 le 1er exemple) Je m'étais d'ailleurs arraché les cheveux il y a quelques années en écrivant un analyseur de code php en php, justement sur le cas du ?> mis dans un commentaire avant de m'appercevoir qu'ou que soit placée cette séquence (commentaire ou chaine) elle est interprétée comme la fin du code.
Correction le 1er exemple fonctionne correctement...
Pour le second cas dans un commentaire PHP3 avec quelques soucis avec.
A mon humble avis, la seule solution pour résoudre le problème des pages PHP sous NVU est de permettre à NVU d'appeler l'interpréteur PHP pour qu'il puisse ensuite parser le résultat de la "page / script".
C'est le seul moyen pour avoir un résultat sensé.
Cela nécessite cependant de prévoir aussi de pouvoir passer des paramètres au script voire d'enregistrer des cookies... Bref on est loin d'une solution simple.
La solution que j'utilise c'est d'avoir une maquette purement html avec dedans des balises du type [balise] :
<div>[contenu]</div>ou encore
<p id="machin" style="color:[colorMachin]">texte quelquonque</p>Ensuite un fichier php remplace toutes les balises par la valeur adékwate. mon code php et html sont completement séparés. C'est BEAUCOUP plus simple à gérer graphiquement et developpiquement.
En gros Bob, tu utilises un moteur de template ;-) exemple : smarty.
La séparation du code php et html est à mon avis une bonne chose. Personnelement je commence à utiliser le système de template phptal http://phptal.sourceforge.net et je le trouve très bien. Les ZPT de zope m'avaient beaucoup impressionné à l'époque et je suis content d'avoir un système similaire pour le développement php.
Houla j'irais pas jusque la. ma méthode est simplisime.
Pour ma part j'utilise un preparsing du code PHP/XHTML pour interpretter le code PHP s'y trouvant avant de parser le code XHTML qui en découle :
$callbackFunc = create_function('$string', 'ob_start();eval("$string[2];");$ret = ob_get_contents();ob_end_clean();return $ret;'); $content = preg_replace_callback("/(<\?php|<\?)(.*?)\?>/si", $callbackFunc, $content);ça marche bien pourvus que les blocks de code PHP n'ai pas besoin les uns des autres (puisqu'ici ils sont interprettés indépendament les uns des autres) et que le code XHTML résultant soit bien syntaxiquement correct.
Par contre le cas du
poserai autant problème...