
Envoyé par
jerome14000
J'ai testé ton expression et elle supprime l'ensemble des balises td et th.
C'est normal, car <t[d|h] (qui s'écrit <t[dh], le pipe perd sa signification spéciale dans une classe de caractères) chope le premier <td ou <tr qu'il rencontre, puis (.|\n|\r)*, bien que muni d'un quantificateur non-gourmand avec l'option U, continue sa course jusqu'à trouver une éventuelle sous-chaîne my_attribute=. Le problème vient du . qui peut matcher n'importe quel caractère et notamment < ou >, ce qui autorise (.|\n|\r)* à "sortir d'une balise" et à rentrer dans une autre, jusqu'à ce que l'attribut (ou une chaîne qui lui ressemble) soit trouvé.
Il faut remplacer le point par une classe de caractère qui exclut >. On peut par exemple écrire:
$pattern = '~<t([dh])\s+(?>[^\s>]+\s+)*?my_attribute=[^<]++(?:<(?!/t\1>)[^<]+)*+</t\1>~i';
Mais même si cette pattern prend la précaution de ne pas sortir de la balise avant de rencontrer l'attribut et vérifie que les balises ouvrante et fermante correspondent, ça reste très hasardeux d'attaquer du code html avec des regex. Je pourrais te sortir mille et un exemples où cette pattern serait prise en défaut, voire causerait des catastrophes. Le html est un langage très flexible et sa syntaxe est bien plus complexe qu'il n'y parait. Donc la solution, c'est le DOM.
Partager