Symfony Dom Crawler在模板中缺少关闭标记

时间:2017-02-21 11:03:04

标签: php symfony domcrawler

我使用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省略了结束标记?

1 个答案:

答案 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,htmlhead,但这里并不重要):

  <!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模板。解决方案可能因您尝试实现的目标而异。