【发布时间】:2017-04-03 20:28:24
【问题描述】:
我在使用 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>
这个sn-p有两个问题:
1) buttonWithCountTemplate 变量中的 HTML 没有被转义。 DOMDocument 正确管理它,在解析时转义字符。没问题。
2) 在接近结尾处,有一个带有未转义结束标签的 img 标签:
<img src="$iconImg" />
/> 使 DOMDocument 认为脚本已完成,但 它缺少结束标记。如果您使用 getElementByTagName 提取脚本,您将在此 img 标记处关闭标记,其余部分将显示为 HTML 上的文本。
我的目标是删除此页面中的所有脚本,因此如果我在此标记上执行removeChild(),则该标记将被删除,但以下部分在呈现页面时显示为文本:
</div><div class="sCountBox">$count</div></a></div>',
}
</script>
修复 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>
使用以下php代码删除脚本标签(based on Gholizadeh's answer):
<?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;
结果如下:
<div> <!-- Offending div without closing tag -->
<p>';
// I should not appear on the result
</p></div>
问题是第一个div标签没有关闭,似乎DOMDocument将JS字符串中的div标签作为html而不是简单的JS字符串。
我能做些什么来解决这个问题?请记住,修改 HTML 不是一种选择,因为我正在开发通用解析器。
【问题讨论】:
-
有趣的问题。我厌倦了反对旧的
<script type="text/javascript"><!--...//--></script>语法的拥护者声称“所有浏览器都理解 JavaScript”,这最多是对的。 -
真的是img元素的错吗?我的猜测是下面的
</div>,因为</的第一次出现会隐式地结束脚本元素的内容并关闭它。 // 恕我直言,您不能只让 DOM 解析器在任何损坏的 HTML 代码上松动,并期望得到正确的结果。如果您真的需要像这样解析混乱的 HTML,您可能需要在将其提供给 DOM 解析器之前对其进行一些“预处理” - 可能类似于 htmlpurifier.org -
@RafałR 使用 loadXML 不是解决方案。如果您的 HTML 不是 100% 有效,则不会加载任何节点。尝试加载我的编辑,您会看到结果为空。
标签: php html domdocument