PHP DOMDocument:解析非转义字符串时出错

And*_*res 12 html php domdocument

我在使用PHP的DOMDocument解析HTML时遇到了问题.

我正在解析的HMTL具有以下脚本标记:

<script type="text/javascript">
    var showShareBarUI_params_e81 =
    {
        buttonWithCountTemplate: '<div class="sBtnWrap"><a href="#" onclick="$onClick"><div class="sBtn">$text<img src="$iconImg" /></div><div class="sCountBox">$count</div></a></div>',
    }
</script>
Run Code Online (Sandbox Code Playgroud)

这个片段有两个问题:

1)buttonWithCountTemplatevar中的HTML 不会被转义.DOMDocument正确地管理它,在解析时转义字符.不是问题.

2)接近结尾,有一个img标签带有未转义的结束标签:

<img src="$iconImg" />
Run Code Online (Sandbox Code Playgroud)

/>品牌的DOMDocument认为脚本执行完毕,但它缺少结束标记.如果使用getElementByTagName提取脚本,则会在此img标记处关闭标记,其余的将在HTML上显示为文本.

我的目标是删除此页面中的所有脚本,因此如果我执行removeChild()此标记,则会删除标记,但在呈现页面时,以下部分将显示为文本:

</div><div class="sCountBox">$count</div></a></div>',
        }
    </script>
Run Code Online (Sandbox Code Playgroud)

修复HTML不是一个解决方案,因为我正在开发一个通用的解析器,需要处理所有类型的HTML.

我的问题是,在将HTML提供给DOMDocument之前是否应该进行任何清理,或者是否有选项可以在DOMDocument上启用以避免触发此问题,或者即使我可以在加载HTML之前删除所有标记.

有任何想法吗?


编辑

经过一些研究,我发现了DOMDocument解析器的真正问题.请考虑以下HTML:

<div> <!-- Offending div without closing tag -->
<script type="text/javascript">
       var test = '</div>';
       // I should not appear on the result
</script>
Run Code Online (Sandbox Code Playgroud)

使用以下php代码删除脚本标记(基于Gholizadeh的答案):

<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);

$dom = new DOMDocument;
$dom->preserveWhiteSpace = false;
libxml_use_internal_errors(true);
$dom->loadHTML(file_get_contents('js.html'), LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
//@$dom->loadHTMLFile('script.html'); //fix tags if not exist

while($nodes = $dom->getElementsByTagName("script")) {
    if($nodes->length == 0) break;
    $script = $nodes->item(0);
    $script->parentNode->removeChild($script);
}

//return $dom->saveHTML();
$final = $dom->saveHTML();
echo $final;
Run Code Online (Sandbox Code Playgroud)

结果如下:

<div> <!-- Offending div without closing tag -->
<p>';
       // I should not appear on the result
</p></div>
Run Code Online (Sandbox Code Playgroud)

问题是第一个div标签没有关闭,似乎DOMDocument将JS字符串中的div标签作为html而不是简单的JS字符串.

我该怎么做才能解决这个问题?请记住,修改HTML不是一个选项,因为我正在开发一个通用的解析器.

Sae*_*.Gh 5

我在html文件上测试了以下代码,如下所示:

<p>some text 1</p>
<img src="http://www.example.com/images/some_image_1.jpg">
<p>some text 2</p>
<p>some text 3</p>
<img src="http://www.example.com/images/some_image_2.jpg">

<script type="text/javascript">
    var showShareBarUI_params_e81 =
    {
        buttonWithCountTemplate: '<div class="sBtnWrap"><a href="#" onclick="$onClick"><div class="sBtn">$text<img src="$iconImg" /></div><div class="sCountBox">$count</div></a></div>',
    }
</script>

<p>some text 4</p>
<p>some text 5</p>
<img src="http://www.example.com/images/some_image_3.jpg">
Run Code Online (Sandbox Code Playgroud)

php代码是:

<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);

    $dom = new DOMDocument;
    $dom->preserveWhiteSpace = false;
    @$dom->loadHTML(file_get_contents('script.html'), LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
    //@$dom->loadHTMLFile('script.html'); //fix tags if not exist 

    $nodes = $dom->getElementsByTagName("script");

    foreach($nodes as $i => $node){
        $script = $nodes->item($i);
        $script->parentNode->removeChild($script);
    }

    //return $dom->saveHTML();
    $dom->saveHtmlFile('script.html');
Run Code Online (Sandbox Code Playgroud)

它适用于给定的例子我认为你应该使用我在加载html代码时使用的选项.

根据上一个问题更新编辑:

实际上你不能用正则表达式解析[X] HTML(阅读此链接以获取更多信息),但如果你的唯一目的是删除脚本标记,你可以确保</script>它之间没有标记作为字符串.你可以使用这个正则表达式:

$html = mb_convert_encoding(file_get_contents('script2.html'), 'HTML-ENTITIES', 'UTF-8');
$new_html = preg_replace('/<script(.*?)>(.*?)<\/script>/si', '', $html);
file_put_contents('script-result.html', $new_html);
Run Code Online (Sandbox Code Playgroud)

坦白说,问题是你可能没有标准的HTML代码.但我认为这是更好地尝试联系其他图书馆在这里.

否则我猜你应该写一个特殊的解析器来删除脚本标签,并在里面处理单引号和双引号.


Tsc*_*cka 2

您是否尝试过将 libxml 设置为使用内部错误?

$use_errors = libxml_use_internal_errors(true);
// your parsing code here
libxml_clear_errors();
libxml_use_internal_errors($use_errors);
Run Code Online (Sandbox Code Playgroud)

它可能允许 dom 文档继续解析(也许)。

  • 这与“@”没有什么不同。它不会阻止 HTML 被错误解析。 (2认同)