PHP DOMDocument saveHTML中断格式

Emi*_*mil 2 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();

}
Run Code Online (Sandbox Code Playgroud)

在这段代码上执行:

<p><img alt="fluid cat" src="/images/tmp/fluid-cat.jpg"></p><p><img alt="pandas" src="/images/tmp/pandas.jpg"></p>
Run Code Online (Sandbox Code Playgroud)

导致此代码:

<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>
Run Code Online (Sandbox Code Playgroud)

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

Cas*_*yte 6

您的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;
Run Code Online (Sandbox Code Playgroud)