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不是一个选项,因为我正在开发一个通用的解析器.
我在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代码.但我认为这是更好地尝试联系其他图书馆在这里.
否则我猜你应该写一个特殊的解析器来删除脚本标签,并在里面处理单引号和双引号.
您是否尝试过将 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 文档继续解析(也许)。