我使用Symfony DOM Crawler来读取和保存包含模板的HTML文档。但是模板中缺少关闭的HTML标记。这是一个例子:
<?php
$htmlString = <<<'HTML'
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>Title</h1>
<script id="my-template" type="text/template">
<div>{{ Name }}</div>
</script>
</body>
HTML;
$crawler = new Crawler($htmlString);
$output = join(
$crawler->filterXPath('//body')->each(
function (Crawler $node, $i) use ($htmlString) {
return $node->html();
}
)
);
我希望有类似的东西:
<h1>Title</h1>
<script id="my-template" type="text/template">
<p>Hello</p>
<div>{{ Name }}</div>
</script>
但我明白了:
<h1>Title</h1>
<script id="my-template" type="text/template">
<p>Hello
<div>{{ Name }}
</script>
您是否知道为什么DOM Crawler省略了结束标记?
答案 0 :(得分:2)
我已完成一些调试并使用以下代码隔离此问题(因为Crawler使用DOMElement
个对象):
$htmlString = <<<'HTML'
<script id="my-template" type="text/template">
<div> Name </div>;
</script>
HTML;
$el = new \DOMDocument();
libxml_use_internal_errors(true);
$el->loadHTML($htmlString);
echo $el->saveHTML($el);
自动添加了文件类型(doctype,html
和head
,但这里并不重要):
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html><head><script id="my-template" type="text/template">
<div> Name ;
</script></head></html>
正如您所看到的那样,script
内的结束标记也存在类似问题。
如果您发表评论libxml_use_internal_errors(true);
,那么您将收到错误消息:
DOMDocument :: loadHTML():意外的结束标记:实体中的div,行:2
我也对此错误进行了一些研究,发现它在LibXML2库中是一个很老的错误,而不是严格的PHP问题:
https://bugs.php.net/bug.php?id=52012
我在PHP 7.0.6上遇到了这个问题,所以我猜它还没有解决。
一般来说,看起来它是关于libxml库解析标记的,所以你必须要么不使用Crawler,要么不要在脚本标记中放置HTML模板。解决方案可能因您尝试实现的目标而异。