转义预标记中的HTML字符


Escape HTML Chars In the Pre Tag

我安装了一个语法高亮器,但为了使其工作,标记必须写成&lt;&gt;。我需要做的是替换所有<'s与&lt;和>与&gt;,但仅在PRE标记内。

所以,简而言之,我想转义pre标记中的所有HTML字符。

提前谢谢。

tl;dr

您需要解析输入的HTML。使用DOMDocument类表示文档,解析输入,查找所有<pre>标记(使用findElementsByTagName)并转义其内容。

代码

不幸的是,DOM模型是非常低级的,它迫使您自己迭代<pre>标记的子节点,以对它们进行转义。如下所示:

function escapeRecursively($node) {
    if ($node instanceof DOMText)
        return $node->textContent;
    $children = $node->childNodes;
    $content = "<$node->nodeName>";
    for ($i = 0; $i < $children->length; $i += 1) {
        $child = $children->item($i);
        $content .= escapeRecursively($child);
    }
    return "$content</$node->nodeName>";
}

现在这个函数可以用来转义文档中的每个<pre>节点:

function escapePreformattedCode($html) {
    $doc = new DOMDocument();
    $doc->loadHTML($html);
    $pres = $doc->getElementsByTagName('pre');
    for ($i = 0; $i < $pres->length; $i += 1) {
        $node = $pres->item($i);
        $children = $node->childNodes;
        $content = '';
        for ($j = 0; $j < $children->length; $j += 1) {
            $child = $children->item($j);
            $content .= escapeRecursively($child);
        }
        $node->nodeValue = htmlspecialchars($content);
    }
    return $doc->saveHTML();
}

测试

$string = '<h1>Test</h1> <pre>Some <em>interesting</em> text</pre>';
echo escapePreformattedCode($string);

收益率:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html><body><h1>Test</h1> <pre>Some &lt;em&gt;interesting&lt;/em&gt; text</pre></body></html>

请注意,DOM始终表示完整的文档。因此,当DOM解析器获取文档片段时,它会填充缺失的信息。这使得输出可能与输入不同。