模式匹配html标签

时间:2010-08-27 09:49:14

标签: php pattern-matching html

我是模式匹配的新手,终于弄明白了。我很难找到解决以下问题的方法。

如果存在任何数量的html标签,我需要返回一个匹配(使用php preg_match)。

<p></p>
<br>
<h1></h1>
<h2></h2>

否则不返回匹配。所以上面列表中没有的内容都会失败,例如:

<script></script>
<table></table>

ECT

...理想情况下,如果可能的话,我想操作一个白色的安全标签列表。

任何人都知道我可以使用/适应的模式吗?

3 个答案:

答案 0 :(得分:5)

即使这不是通常的“I want to parse HTML with regular expressions”情况,我仍然建议使用DOM解析器,遍历每个元素,如果它不在允许元素列表中则中止。

参见例如this question开始使用。

如果它支持:not选择器和多个标签名称,它可能会成为使用像phpQuery这样的DOM解析器扩展的单线程 - 我不知道,我自己从未使用它,但很容易找到。基本示例是here

答案 1 :(得分:2)

preg_match_all('/<([a-z]*)\b[^>]*>(.*?)</\1>/i'$html,$matches);

分解表达

第一个/是分隔符

<是标记的开头,即第一个<

([a-z]*)开始匹配标签名称,因此fir实例&lt;的

\b[^>]*说,一旦找到空格,继续寻找所有单词

>表示希望上一部分继续查看,直到找到第一个>

(.*?)说继续查看并收集(..)里面的字符串但是我们有一个?然后当你在结束括号后找到下一个字符时停止查看。

</\1>表示我想匹配但仅当内部的值与第一个匹配时相同时,这由\1完成,如匹配, the value of this would be what's found with([az] *)`。

然后你可以使用preg_match_all来查找包含内容的所有内容,数组输出就像是

array(
    0 > THE WHOLE TAG
    1 > TAG NAME
    2 > TAG VALUE
)

希望有所帮助:)

〔实施例

$allowed = array('b','strong','i','pre','code'); WHITELIST, never blacklist
foreach($matchas as $match)
{
    if(!in_array($match[1],$allowed))
    {
        echo sprintf('The tag %s is disallowed!',$match[1]);
    }
}

答案 2 :(得分:2)

正则表达式完全不适合检查HTML中的“安全”标记。不仅如此,HTML中还没有安全标签。可以为任何元素指定允许脚本注入的属性(例如onclickstyle - with-IE - expression() ...)。您必须检查每个属性以及每个元素。

当您的安全性受到威胁时,您绝对需要一个真正的HTML解析器(然后您过滤元素/属性并序列化结果)。有很多方法可以逃避基于正则表达式的检查,这甚至都不好笑。

您可以使用DOMDocument::loadHTML后跟DOM漫游来执行此操作,也可以使用现有的库,例如htmlpurifier