2010-06-30 6 views
1

Oui, je sais, je sais, l'analyse HTML avec des expressions régulières est très mauvaise. Mais je travaille avec du code hérité supposé extraire tous les éléments link et style d'une page html. Je voudrais le changer et utiliser l'extension dom à la place, mais après la regex il y a un énorme bloc de code qui repose sur la façon dont preg_match_all renvoie les résultats correspondants.extraire des feuilles de style via regex

Le script utilise cette regex:

$pattern = '/<(link|style)(?=.+?(?:type="(text\/css)"|>))(?=.+?(?:media="(.*?)"|>))(?=.+?(?:href="(.*?)"|>))(?=.+?(?:rel="(.*?)"|>))[^>]+?\2[^>]+?(?:\/>|<\/style>)\s*/is'; 

preg_match_all($pattern, $htmlContent, $cssTags); 

Mais cela ne fonctionne pas. Aucun élément ne correspond. Malheureusement, je craque vraiment pour regex, donc si quelqu'un pouvait m'aider, ce serait génial.

+0

tous les matches sont utilisés? Je veux dire le type, les médias, etc.? – galambalazs

+0

@galambalazs Oui, pour autant que je puisse voir c'est le cas. – Max

+0

* Le bloc de code énorme * semble être un bon candidat pour un refactoring. Jetez-le pour une solution DOM appropriée. – Gordon

Répondre

0

Merci à tous pour vos réponses, mais je réécris enfin que peu en utilisant l'extension DOM. Cela devrait le rendre plus robuste.

1

Je voudrais casser ce problème en un plus petit. Il serait plus facile d'écrire, plus facile à maintenir. Et un peu plus de lignes de code bien sûr. Le problème avec une énorme regex est qu'il y a beaucoup de gotchas et l'entrée peut être invalide, ce qui est difficile à gérer dans un grand pattern.

/<link([^>]+)>/ 
-> extract attributes: 
    /([\w]+)\s*=\s*"([^"]*)"/ 

/<style[^>]*>(.+?)</style>/ 
-> extract inline styles 

Et enfin fusionner les résultats dans un tableau comme si preg_match_all l'avait produit.

0

Si je le faisais avec des expressions régulières, par ex. Parce que vous devez être capable de gérer du HTML invalide, ce qui est souvent difficile avec un analyseur approprié, j'utiliserais des expressions régulières séparées. Utilisez une ou deux regexes pour obtenir les tags style et link, et utilisez un autre jeu d'expressions rationnelles pour obtenir les différents attributs de chaque tag.

Votre regex essaie de tout faire en même temps en utilisant lookahead pour analyser la balise d'ouverture à plusieurs reprises pour obtenir tous les éléments. C'est une astuce dans une situation où une seule regex est tout ce que vous pouvez utiliser, mais pas quelque chose à recommander lors de l'écriture de votre propre code.

J'ai apporté quelques améliorations à votre regex. J'ai remplacé le .*? et .+? avec des classes de caractères niés si possible pour l'efficacité. La raison pour laquelle votre regex n'a pas fonctionné est qu'il n'essaie pas correctement de faire correspondre la balise de fermeture ou de gérer correctement les balises link qui n'ont pas de balise de fermeture. J'ai réparé ça.

Le regex:

<(link|style)(?=[^<>]*?(?:type="(text/css)"|>))(?=[^<>]*?(?:media="([^<>"]*)"|>))(?=[^<>]*?(?:href="(.*?)"|>))(?=[^<>]*(?:rel="([^<>"]*)"|>))(?:.*?</\1>|[^<>]*>) 

PHP:

$pattern = '%<(link|style)(?=[^<>]*?(?:type="(text/css)"|>))(?=[^<>]*?(?:media="([^<>"]*)"|>))(?=[^<>]*?(?:href="(.*?)"|>))(?=[^<>]*(?:rel="([^<>"]*)"|>))(?:.*?</\1>|[^<>]*>)%si' 
0

Pour saisir les ressources externes:

preg_match_all('#(<link\s(?:[^>]*rel="stylesheet")[^>]*>)\R?#is', $content, $matches, PREG_SET_ORDER) 
Questions connexes