3

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

4

1 回答 1

3

我已经使用以下代码进行了一些调试并隔离了这个问题(因为 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 模板放在脚本标签中。解决方案可能因您要实现的目标而异。

于 2017-02-21T12:59:11.787 回答