1

私は DOMDocument のファンではありません。なぜなら、DOMDocument は現実世界での使用にはあまり適していないと思うからです。しかし、現在のプロジェクトでは、ページ内のすべてのテキスト (ソース コードにアクセスできない) を他の文字列 (ある種の翻訳) に置き換える必要があります。だから私はそれを使う必要があります。

DOMDocument でこれを実行しようとしましたが、期待どおりの結果が得られませんでした。私が使用するコードは次のとおりです。

function Translate_DoHTML($body, $replaceArray){
    if ($replaceArray && is_array($replaceArray) && count($replaceArray) > 0){
        $body2 = mb_convert_encoding($body, 'HTML-ENTITIES', "UTF-8");
        $doc = new DOMDocument();
        $doc->resolveExternals = false;
        $doc->substituteEntities = false;
        $doc->strictErrorChecking = false;
        if (@$doc->loadHTML($body2)){
            Translate_DoHTML_Process($doc, $replaceArray);
            $body = $doc->saveHTML();
        }
    }
    return $body;
}

function Translate_DoHTML_Process($node, $replaceRules){
    if($node->hasChildNodes()) {
        $nodes = array();
        foreach ($node->childNodes as $childNode)
            $nodes[] = $childNode;
        foreach ($nodes as $childNode)
            if ($childNode instanceof DOMText) {
                if (trim($childNode->wholeText)){
                    $text = str_ireplace(array_keys($replaceRules), array_values($replaceRules), $childNode->wholeText);
                    $node->replaceChild(new DOMText($text),$childNode);
                }
            }else
                Translate_DoHTML_Process($childNode, $replaceRules);
    }
}

そして、ここに問題があります:

  • エスケープ属性: ファイルには、エスケープされる data-X 属性があります。これは大きな問題ではありませんが、この動作を無効にできれば素晴らしいことです。

DOM の前:

data-link-content="         <a class=&quot;submenuitem&quot; href=&quot

DOMの後:

data-link-content='         &lt;a class="submenuitem" href="
  • JavaScript での終了タグの削除: これは実際、ここでの主な問題です。世界のどのような理由で DOMDocument がこれらのタグを削除する必要があるかはわかりません。しかし、そうです。以下の例で明確にわかるように、java-script 文字列の終了タグを削除します。また、スクリプトの最後の部分を削除しました。DOMDocument が内部の java-script を解析しているようです。CDATAタグがないからでしょうか?しかし、いずれにしても HTML であり、HTML に CDDATA は必要ありません。CDATA は xHTML 用だと思いました。また、ここに CDDATA を追加する方法もありません。では、スクリプト タグを解析しないように指定できますか?

DOM の前:

<script type="text/javascript"> document.write('<video src="http://x.webm"><p>You will need to <a href="http://www.adobe.com/go/getflashplayer" target="_blank">Install</a> the latest Flash plugin to view this page properly.</p></video>');  </script>

DOMの後:

<script type="text/javascript"> document.write('<video src="http://x.webm"><p>You will need to <a href="http://www.adobe.com/go/getflashplayer" target="_blank">Install the latest Flash plugin to view this page properly.</script>

これらを防ぐ方法がない場合、このコードを SimpleHTMLDOM に移植する方法はありますか?

どうもありがとうございます。

4

2 に答える 2

0

私の検索に基づいて、2番目の問題の理由は、実際には「アレックス」がこの質問で私たちに言ったことです: <script> タグで HTML5 スタイルの </ を許可する DOM パーサー

しかし、彼らの調査によると、今日の HTML を理解できる優れたパーサーは存在しません。また、html5lib の最後の更新は 2 年前であり、私のテストに基づくと、実際の状況では機能しませんでした。

したがって、2番目の問題を解決する方法は1つしかありませんでした。正規表現。私が使用するコードは次のとおりです。

function Translate_DoHTML_GetScripts($body){
    $res = array();
    if (preg_match_all('/<script\b[^>]*>([\s\S]*?)<\/script>/m', $body, $matches) && is_array($matches) && isset($matches[0])){
        foreach ($matches[0] as $key => $match)
            $res["<!-- __SCRIPTBUGFIXER_PLACEHOLDER".$key."__ -->"] = $match;
        $body = str_ireplace(array_values($res), array_keys($res), $body);
    }
    return array('Body' => $body, 'Scripts' => $res);
}

function Translate_DoHTML_SetScripts($body, $scripts){
    return str_ireplace(array_keys($scripts), array_values($scripts), $body);
}

上記の 2 つの関数を使用して HTML からスクリプトを削除し、DomDocument を使用して自分の作業を実行できるようにします。最後に、元の場所に正確に追加します。

それでも、正規表現がこれに十分速いかどうかはわかりません。

また、HTML に RegEx を使用しないように言わないでください。HTML が通常の言語ではないことなどは知っています。しかし、自分で問題を読むと、同じアプローチを提案するでしょう。

于 2013-09-13T02:33:56.543 に答える