PHP 阻止 strip_tags 删除损坏的标签

PHP prevent strip_tags from removing broken tags

我和这个情况一样this guy

基本上 strip_tags 删除标签,包括损坏的标签(documentation 中使用的术语)。如果它不是 HTML 标签,是否有另一种不涉及删除 < 及其后的任何文本的方法?

我目前正在这样做:

$description = "&lt;p&gt;I am currently &lt;30 years old.&lt;/p&gt;";
$body = strip_tags(html_entity_decode($description, ENT_QUOTES, "UTF-8"), "<strong><em><u>");
echo $body;

但是上面的代码会破坏如下内容:

<p>I am currently <30 years old.</p>

进入:

I am currently

eval.in

这里有一个eval.in所以你们可以明白我的意思。

您输入的 HTML 无效。所以这需要修复。您可以先将所有未关闭的 < 替换为 &lt;,然后再执行 html_entity_decode after strip_tags:

$description = "<p>I am currently <30 years old.</p>";
$description = preg_replace("/<([^>]*(<|$))/", "&lt;", $description);
$body = html_entity_decode(strip_tags($description, "<strong><em><u>"),
                           ENT_NOQUOTES, "UTF-8");
echo $body;

eval.in

上查看

或者您可以使用 DOM 解析器,这在某些情况下可以提供更好的结果,但您仍然需要先应用修复程序:

$description = "<p>I am currently <30 years old.</p>";
$description = preg_replace("/<([^>]*(<|$))/", "&lt;", $description);
$doc = new DOMDocument();
$doc->loadHTML($description);
$body = $doc->documentElement->textContent;
echo $body;

eval.in

上查看

通常在使用小于和大于运算符时,您几乎总是会使用数字(尤其是在这里,因为您已经说过不涉及空格)。假设这是你的情况,你可以很容易地使用 preg_match 在 运行 之前通过 strip_tags:

对这种情况进行正则表达式
$description = "<p>I am currently <30 years old.</p>";
$description = preg_replace("/<([0-9]+)/", "&lt;", $description);
$body = strip_tags($description, "<strong><em><u>");
echo $body;