是的,我知道,我知道,使用正则表达式解析HTML非常糟糕。但我正在处理遗留代码,该代码应该从html页面中提取所有link
和style
元素。我会更改它并使用dom
扩展名,但在正则表达式之后有一个巨大的代码块,它依赖于preg_match_all
返回匹配结果的方式。
脚本正在使用此正则表达式:
$pattern = '/<(link|style)(?=.+?(?:type="(text\/css)"|>))(?=.+?(?:media="(.*?)"|>))(?=.+?(?:href="(.*?)"|>))(?=.+?(?:rel="(.*?)"|>))[^>]+?\2[^>]+?(?:\/>|<\/style>)\s*/is';
preg_match_all($pattern, $htmlContent, $cssTags);
但它不起作用。没有元素匹配。不幸的是我真的很喜欢正则表达式,所以如果有人能帮助我,那就太棒了。
答案 0 :(得分:1)
我会把这个问题分解成几个较小的问题。它更容易编写,更易于维护。当然还有更多代码。一个巨大的正则表达式的问题在于存在一些问题,输入可能无效,难以在一个大模式中进行管理。
/<link([^>]+)>/
-> extract attributes:
/([\w]+)\s*=\s*"([^"]*)"/
/<style[^>]*>(.+?)</style>/
-> extract inline styles
最后将结果合并到一个数组中,就像preg_match_all生成它一样。
答案 1 :(得分:0)
如果我使用正则表达式执行此操作,例如因为你需要能够处理无效的HTML,这通常很难使用正确的解析器,我会使用单独的正则表达式。使用一个或两个正则表达式来获取style
和link
标记,并使用另一组正则表达式来获取每个标记的各种属性。
你的正则表达式试图通过使用lookahead重复扫描开始标记以获取所有元素来一次性完成所有操作。在一个正则表达式就是你可以使用的情况下,这是一个巧妙的技巧,但在编写自己的代码时没有被推荐的东西。
我对你的正则表达式做了一些改进。为了提高效率,我将.*?
和.+?
替换为否定字符类。你的正则表达式不起作用的原因是它没有正确地尝试匹配结束标记或正确处理没有结束标记的link
标记。我解决了这个问题。
正则表达式:
<(link|style)(?=[^<>]*?(?:type="(text/css)"|>))(?=[^<>]*?(?:media="([^<>"]*)"|>))(?=[^<>]*?(?:href="(.*?)"|>))(?=[^<>]*(?:rel="([^<>"]*)"|>))(?:.*?</\1>|[^<>]*>)
PHP:
$pattern = '%<(link|style)(?=[^<>]*?(?:type="(text/css)"|>))(?=[^<>]*?(?:media="([^<>"]*)"|>))(?=[^<>]*?(?:href="(.*?)"|>))(?=[^<>]*(?:rel="([^<>"]*)"|>))(?:.*?</\1>|[^<>]*>)%si'
答案 2 :(得分:0)
感谢您的回答,但我终于使用DOM扩展重写了这一点。这应该会让它变得更加强大。
答案 3 :(得分:0)
仅获取外部资源:
preg_match_all('#(<link\s(?:[^>]*rel="stylesheet")[^>]*>)\R?#is', $content, $matches, PREG_SET_ORDER)