PHP DOMDocument saveHTML中断格式

时间:2016-09-13 22:36:28

标签: php dom

为什么会这样的代码:

$doc = new DOMDocument();
$doc->loadHTML($this->content, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
$imgNodes = $doc->getElementsByTagName('img');

if ($imgNodes->length > 0) {
    $inlineImage = new Image();
    $inlineImage->setPublicDir($publicDirPath);

    foreach ($imgNodes as $imgNode) {
        $inlineImage->setUri($imgNode->getAttribute('src'));
        $inlineImage->setName(basename($inlineImage->getUri()));

        if ($inlineImage->getUri() != $dstPath.$inlineImage->getName()) {
            $inlineImage->move($dstPath);

            $imgNode->setAttribute('src', $dstPath.'/'.$inlineImage->getName());                 
        }
    }

    $this->content = $doc->saveHtml();

}

在此代码上执行:

<p><img alt="fluid cat" src="/images/tmp/fluid-cat.jpg"></p><p><img alt="pandas" src="/images/tmp/pandas.jpg"></p>

导致此代码:

<p><img alt="fluid cat" src="/images/full/2016-09/fluid-cat.jpg"><p><img alt="pandas" src="/images/full/2016-09/pandas.jpg"></p></p>

为什么将两个img标签放在第一个p块中?

1 个答案:

答案 0 :(得分:5)

您的html示例没有包含所有内容的根元素。当LIBXML解析html以构建DOM树时,它假定第一个遇到的标记是根元素。结果,第一个标记</p>被视为孤儿结束标记(因为它后面有内容)并自动删除,最后添加</p>以关闭根元素

要在使用html部件(不是整个html文档)时避免这些自动修复,您需要添加一个假的根元素。最后,要生成结果字符串,您需要保存此伪根元素的每个子节点。例如:

$html = '<p><img alt="fluid cat" src="/images/tmp/fluid-cat.jpg"></p><p><img alt="pandas" src="/images/tmp/pandas.jpg"></p>';

$doc = new DOMDocument;
$doc->loadHTML( '<div>' . $html . '</div>', LIBXML_HTML_NODEFDTD | LIBXML_HTML_NOIMPLIED);
#               ^-----------------^----- fake root element
$root = $doc->documentElement;

$result = '';

foreach($root->childNodes as $childNode) {
    $result .= $doc->saveHTML($childNode);
}

echo $result;