Symfony Dom 抓取工具在模板中缺少结束标记

Symfony Dom Crawler missing closing tag in template

我使用 Symfony DOM 爬虫读取并保存包含模板的 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 使用 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);

Ouputs(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(): Unexpected end tag : div in Entity, line: 2

我也对这个错误进行了一些研究,发现它是 LibXML2 库中的一个相当老的错误,严格来说并不是 PHP 问题:

https://bugs.php.net/bug.php?id=52012

我在 PHP 7.0.6 上遇到了这个问题,所以我想它仍然根本没有解决。

一般来说,它看起来像是关于通过 libxml 库解析标记,因此您将不得不要么不使用 Crawler,要么不要将 HTML 模板放在脚本标记中。解决方案可能因您要实现的目标而异。