我是模式匹配的新手,终于弄明白了。我很难找到解决以下问题的方法。
如果存在任何数量的html标签,我需要返回一个匹配(使用php preg_match)。
<p></p>
<br>
<h1></h1>
<h2></h2>
否则不返回匹配。所以上面列表中没有的内容都会失败,例如:
<script></script>
<table></table>
ECT
...理想情况下,如果可能的话,我想操作一个白色的安全标签列表。
任何人都知道我可以使用/适应的模式吗?
答案 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中还没有安全标签。可以为任何元素指定允许脚本注入的属性(例如onclick
,style
- with-IE - expression()
...)。您必须检查每个属性以及每个元素。
当您的安全性受到威胁时,您绝对需要一个真正的HTML解析器(然后您过滤元素/属性并序列化结果)。有很多方法可以逃避基于正则表达式的检查,这甚至都不好笑。
您可以使用DOMDocument::loadHTML
后跟DOM漫游来执行此操作,也可以使用现有的库,例如htmlpurifier。