从文本末尾删除未关闭的html元素

时间:2013-08-11 05:28:14

标签: php html regex

我想删除在内容结尾处未正确关闭的所有元素,例如在下面的测试中

commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea
voluptate velit esse quam nihil molestiae consequatur, 
vel illum qui dolorem eum fugiat quo voluptas nulla 
pariatur? <a rel="nofollow" class="underline"

我想删除

<a rel="nofollow" class="underline"

或没有结束标记的元素

<h2>sample text

或任何其他未在最后正确关闭的html元素。

1 个答案:

答案 0 :(得分:4)

我写了一个应该做你想做的功能。我们的想法是首先用####模式替换所有有效的标记序列。然后正则表达式将删除从第一个<到字符串结尾的所有内容。之后,有效的标签序列被放回缓冲区(如果该部分由于该部分之前的无效标签而未被删除)。

太糟糕了,我无法添加键盘,因为键盘使用的PHP版本似乎不支持递归正则表达式。我用PHP 5.3.5进行了测试。

<强> PHP

function StripUnclosedTags($input) {
    // Close <br> tags
    $buffer = str_ireplace("<br>", "<br/>", $input);
    // Find all matching open/close HTML tags (using recursion)
    $pattern = "/<([\w]+)([^>]*?) (([\s]*\/>)| (>((([^<]*?|<\!\-\-.*?\-\->)| (?R))*)<\/\\1[\s]*>))/ixsm";
    preg_match_all($pattern, $buffer, $matches, PREG_OFFSET_CAPTURE);
    // Mask matching open/close tag sequences in the buffer
    foreach ($matches[0] as $match) {
        $ofs = $match[1];
        for ($i = 0; $i < strlen($match[0]); $i++, $ofs++)
            $buffer[$ofs] = "#";
    }
    // Remove unclosed tags
    $buffer = preg_replace("/<.*$/", "", $buffer);
    // Put back content of matching open/close tag sequences to the buffer
    foreach ($matches[0] as $match) {
        $ofs = $match[1];
        for ($i = 0; $i < strlen($match[0]) && $ofs < strlen($buffer); $i++, $ofs++)
            $buffer[$ofs] = $match[0][$i];
    }
    return $buffer;
}

$str = 'commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate '
      .'velit esse<br> quam nihil molestiae consequatur,  vel illum qui dolorem eum '
      .'fugiat quo voluptas nulla  pariatur? '
      .'<a href="test">test<p></p></a><span>test<p></p>bla';

var_dump(StripUnclosedTags($str));

<强>输出

string 'commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea
voluptate velit esse<br/> quam nihil molestiae consequatur, 
vel illum qui dolorem eum fugiat quo voluptas nulla 
pariatur? <a href="test">test<p></p></a>' (length=226)