将 LIBXML_HTML_NOIMPLIED 标志与 html 片段一起使用会生成不正确的标签:
$str = '<p>Lorem ipsum dolor sit amet.</p><p>Nunc vel vehicula ante.</p>';
$doc = new DOMDocument();
$doc->loadHTML($str, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
echo $doc->saveHTML();
输出:
<p>Lorem ipsum dolor sit amet.<p>Nunc vel vehicula ante.</p></p>
我发现了使用正则表达式来解决这个问题的技巧,但这违背了使用 DOM 的目的。我已经用几个版本的 libxml 和 php 测试了这个,最新的是 libxml 2.9.2,php 5.6.7 (Debian Jessy)。任何建议表示赞赏。
最佳答案
重新安排是由您使用的 LIBXML_HTML_NOIMPLIED
选项完成的。看起来它对你的情况来说不够稳定。
此外,出于可移植性原因,您可能不想使用它,例如,我手头有一个带有 Libxml 2.7.8 的 PHP 5.4.36,它不支持 LIBXML_HTML_NOIMPLIED
(Libxml >= 2.7 .7) 但稍后 LIBXML_HTML_NODEFDTD
(Libxml >= 2.7.8) 选项。
我知道这种处理方式。加载片段时,将其包装到 <div>
元素中:
$doc->loadHTML("<div>$str</div>");
这有助于在您想要的结构上引导 DOMDocument。
然后您可以从文档本身中提取此容器:
$container = $doc->getElementsByTagName('div')->item(0);
$container = $container->parentNode->removeChild($container);
然后从文档中删除所有子项:
while ($doc->firstChild) {
$doc->removeChild($doc->firstChild);
}
现在文档完全是空的,您现在可以再次追加子项。幸运的是,我们之前删除了 <div>
容器元素,因此我们可以从中添加:
while ($container->firstChild ) {
$doc->appendChild($container->firstChild);
}
然后可以使用已知的 saveHTML 方法检索片段:
echo $doc->saveHTML();
在您的场景中给出:
<p>Lorem ipsum dolor sit amet.</p><p>Nunc vel vehicula ante.</p>
此方法与网站上的现有 Material 略有不同(请参阅我在下面给出的引用资料),因此立即示例:
$str = '<p>Lorem ipsum dolor sit amet.</p><p>Nunc vel vehicula ante.</p>';
$doc = new DOMDocument();
$doc->loadHTML("<div>$str</div>");
$container = $doc->getElementsByTagName('div')->item(0);
$container = $container->parentNode->removeChild($container);
while ($doc->firstChild) {
$doc->removeChild($doc->firstChild);
}
while ($container->firstChild ) {
$doc->appendChild($container->firstChild);
}
echo $doc->saveHTML();
我也非常推荐关于How to saveHTML of DOMDocument without HTML wrapper? 的引用问题以进一步阅读以及关于 inner-html 的问题
引用资料
关于php - loadHTML LIBXML_HTML_NOIMPLIED 在 html 片段上生成不正确的标签,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29493678/