1

我不是 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 脚本。也许是因为没有 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

试试这个,并替换行内容;

$body2 = mb_convert_encoding($body, 'HTML-ENTITIES', "UTF-8");

至 ;

$body2 = convertor($body);

并插入您的代码;

function convertor($ToConvert)
    {
        $FromConvert = html_entity_decode($ToConvert,ENT_QUOTES,'ISO-8859-1');
        $Convert = mb_convert_encoding($FromConvert, "ISO-8859-1", "UTF-8");
        return ltrim($Convert); 
    }

但是在上下文中使用正确的编码。

祝你今天过得愉快。

于 2013-09-12T23:30:19.927 回答
0

根据我的搜索,第二个问题的原因实际上是“Alex”在这个问题中告诉我们的:DOM parser that allowed HTML5-style </ in <script> tag

但是根据他们的研究,没有能够理解当今 HTML 的好的解析器。此外,html5lib 的最后一次更新是在 2 年前,根据我的测试,它无法在现实世界的情况下工作。

所以我只有一种方法来解决第二个问题。正则表达式。这是我使用的代码:

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);
}

使用上述两个函数,我将从 HTML 中删除任何脚本,以便我可以使用 DomDocument 来完成我的工作。然后在最后,我会将它们准确地添加回它们所在的位置。

但是我不确定正则表达式是否足够快。

并且不要告诉我不要将 RegEx 用于 HTML。我知道 HTML 不是常规语言等等;但是,如果您自己阅读问题,您会建议使用相同的方法。

于 2013-09-13T02:33:56.543 回答