使用正则表达式和php匹配未关闭的html标签

时间:2015-11-24 20:32:03

标签: php regex

我使用php和regex在字符串中查找未关闭的html标签:

这是我的字符串:

$s="<div><h2>Hello world<h2><p>It's 7Am where I live<p><div>";

您可以看到此处的所有标记均未关闭。

我想找到所有未关闭的标签,但问题是我的正则表达式也匹配开始标签。

到目前为止,这是我的正则表达式

/<[^>]+>/i

这是我的preg_match_all()函数

preg_match_all("/<[^>]+>/i",$s,$v);

print_r($v);

我需要在正则表达式中更改哪些内容才能匹配未关闭的标记?

 <h2>
 <p>
 <div>

2 个答案:

答案 0 :(得分:11)

您可能不知道这一点,但DOMDocument可以帮助您修复HTML。

$html = "<div><h2>Hello world<h2><p>It's 7Am where I live<p><div>";
libxml_use_internal_errors(true);

$dom = new DOMDocument();
$dom->loadHTML('<root>' . $html . '</root>', LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
$xpath = new DOMXPath($dom);

foreach( $xpath->query('//*[not(node())]') as $node ) {
    $node->parentNode->removeChild($node);
}
echo substr($dom->saveHTML(), 6, -8);

请参阅IDEONE demo

结果:<div><h2>Hello world</h2><p>It's 7Am where I live</p></div>

请注意,基于XPath的空节点清理是必要的,因为在将HTML加载到DOM后,DOM包含空<h2></h2><p></p><div></div>标记。

在开头添加<root>元素,以确保我们获得根元素。之后,我们可以使用substr对其进行后期处理。

LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD标志是必要的,因此没有DTD和其他垃圾没有添加到DOM中。

答案 1 :(得分:2)

找到无法匹配的标签似乎从根本上说很难用正则表达式。您基本上需要将每个开始标记放到队列中,然后在看到结束标记时将其从队列中弹出。

建议您使用执行HTML验证的库。看到这些问题:

Remove unmatched HTML tags in a string

How to find the unclosed div tag

PHP get all unclosed HTML tags in string