PHP DOMDocument按HTML id修改元素内容的标签转义、自动套标签及复杂HTML插入问题
PHP DOMDocument替换指定ID节点内容的问题修复
两个核心问题的对应解决方案
1. 插入HTML标签被转义为实体的问题
直接给nodeValue赋值时,DOMDocument会将传入内容判定为纯文本,自动转义所有特殊字符,无法解析为HTML结构。
正确处理方式是通过DOMDocumentFragment加载待插入的任意复杂度HTML片段,再追加到目标节点,支持多层嵌套的表格、任意标签结构:
- 第一步:循环删除目标节点下的所有原有子节点,清空内容
- 第二步:创建文档片段,加载待插入的HTML字符串
- 第三步:将片段追加到目标节点
示例代码:
// 获取目标节点 $targetNode = $html->getElementById('rechnung_div'); // 清空节点原有内容 while ($targetNode->hasChildNodes()) { $targetNode->removeChild($targetNode->firstChild); } // 创建片段加载复杂HTML $fragment = $html->createDocumentFragment(); // 直接传入任意嵌套结构的HTML字符串即可 $fragment->appendXML($rehnungTemplate); $targetNode->appendChild($fragment);
如果待插入内容包含 这类HTML实体导致appendXML报错,可以用临时文档加载节点后导入的方式兼容:
$fragment = $html->createDocumentFragment(); $tmpDoc = new DOMDocument(); libxml_use_internal_errors(true); $tmpDoc->loadHTML('<div>' . $rehnungTemplate . '</div>', LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD); // 导入临时文档里的所有子节点 foreach ($tmpDoc->getElementsByTagName('div')->item(0)->childNodes as $childNode) { $fragment->appendChild($html->importNode($childNode, true)); } $targetNode->appendChild($fragment);
2. 输出自动包裹<html>、<body>标签的问题
该问题是DOMDocument默认将传入内容识别为完整HTML文档,自动补全缺失的文档结构标签导致,修复方式:
- 加载HTML时传入两个配置flag,关闭自动补全逻辑:
LIBXML_HTML_NOIMPLIED(禁止自动添加隐含的文档结构标签)、LIBXML_HTML_NODEFDTD(禁止自动添加DOCTYPE声明) - 低版本PHP加flag后仍残留多余标签时,不要直接调用全局
saveHTML(),而是找到原始内容的根节点,传入saveHTML()单独输出该节点内容即可。
完整可运行示例代码
$html = new DOMDocument('1.0', 'UTF-8'); // 屏蔽HTML非规范内容的解析报错 libxml_use_internal_errors(true); // 加载HTML时传入flag,禁止自动补全文档结构 $html->loadHTML($codeText, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD); libxml_clear_errors(); // 替换second_head节点内容 $secondHead = $html->getElementById('second_head'); while ($secondHead->hasChildNodes()) { $secondHead->removeChild($secondHead->firstChild); } $frag1 = $html->createDocumentFragment(); $frag1->appendXML($leadAddressTemplate); $secondHead->appendChild($frag1); // 替换rechnung_div节点内容 $rechnungDiv = $html->getElementById('rechnung_div'); while ($rechnungDiv->hasChildNodes()) { $rechnungDiv->removeChild($rechnungDiv->firstChild); } $frag2 = $html->createDocumentFragment(); $frag2->appendXML($rehnungTemplate); $rechnungDiv->appendChild($frag2); // 输出最终结果 $res = $html->saveHTML();
内容的提问来源于stack exchange,提问作者Stas Lowert
相关产品推荐
相关产品推荐

