1

シンタックス ハイライターをインストールしましたが、それを機能させるには、タグを と のように記述する必要があり&lt;ます&gt;。私がする必要があるのは、すべての <&lt;と > を&gt;PRE タグ内のみに置き換えることです。

つまり、要するに、pre タグ内のすべての HTML 文字をエスケープしたいということです。

前もって感謝します。

4

1 に答える 1

2

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 パーサーがドキュメント フラグメントを取得すると、欠落している情報が埋められます。これにより、出力が入力と異なる可能性があります。

于 2012-03-31T12:04:46.067 に答える