извлекать таблицы стилей с помощью регулярных выражений - PullRequest
1 голос
/ 30 июня 2010

Да, я знаю, я знаю, синтаксический анализ HTML с регулярными выражениями очень плох.Но я работаю с устаревшим кодом, который должен извлечь все элементы link и style из html-страницы.Я бы изменил его и использовал вместо этого расширение dom, но после регулярного выражения возникает огромный блок кода, который полагается на то, как preg_match_all возвращает сопоставленные результаты.

Сценарий использует это регулярное выражение:

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

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

Но это не работает.Ни один элемент не соответствует.К сожалению, я действительно отстой в регулярных выражениях, поэтому, если кто-то может мне помочь, было бы здорово.

Ответы [ 4 ]

1 голос
/ 30 июня 2010

Я бы разбил эту проблему на несколько более мелких. Было бы легче написать, легче поддерживать. И немного больше строк кода, конечно. Проблема с одним огромным регулярным выражением состоит в том, что есть несколько ошибок, и ввод может быть недействительным, что трудно в одном большом шаблоне.

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

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

И, наконец, объединить результаты в массив, как если бы его создал preg_match_all.

0 голосов
/ 15 ноября 2016

Чтобы получить только внешние ресурсы:

preg_match_all('#(<link\s(?:[^>]*rel="stylesheet")[^>]*>)\R?#is', $content, $matches, PREG_SET_ORDER)
0 голосов
/ 06 июля 2010

Спасибо за ваши ответы, но я наконец переписал этот бит, используя расширение DOM. Это должно сделать его более надежным.

0 голосов
/ 04 июля 2010

Если бы я делал это с помощью регулярных выражений, например, потому что вам нужно иметь возможность обрабатывать недопустимый HTML, который часто затруднен при правильном парсере, я бы использовал отдельные регулярные выражения.Используйте одно или два регулярных выражения, чтобы получить теги style и link, и используйте другой набор регулярных выражений, чтобы получить различные атрибуты от каждого тега.

Ваше регулярное выражение пытается сделать все сразу, используясканируйте открывающий тег несколько раз, чтобы получить все элементы.Это хитрый трюк в ситуации, когда вы можете использовать только одно регулярное выражение, но не то, что рекомендуется при написании собственного кода.

Я внес некоторые улучшения в ваше регулярное выражение.Я заменил .*? и .+? на отрицательные классы символов, где это было возможно для эффективности.Причина, по которой ваше регулярное выражение не сработало, заключается в том, что он неправильно пытается сопоставить закрывающий тег или неправильно обрабатывает теги link, у которых нет закрывающего тега.Я исправил это.

Регулярное выражение:

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

PHP:

$pattern = '%<(link|style)(?=[^<>]*?(?:type="(text/css)"|>))(?=[^<>]*?(?:media="([^<>"]*)"|>))(?=[^<>]*?(?:href="(.*?)"|>))(?=[^<>]*(?:rel="([^<>"]*)"|>))(?:.*?</\1>|[^<>]*>)%si'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...