
DOMDocument 在解析包含未转义
domdocument 在解析包含未转义 `` 序列的 `<script>` 内容时会提前截断,因其将 `</` 误判为标签闭合;解决方法是预处理 javascript 中的 `</` 为 `<\/`,并确保输入为结构完整的 <a style="color:#f60; text-decoration:underline;" title= "html"href="https://m.php.cn/zt/15763.html" target="_blank">html5 文档。</script>
PHP 的 DOMDocument::loadHTML() 并非纯 HTML 解析器,而是基于宽松 XML/HTML 混合解析逻辑实现的。当它在 <script></script> 内容中遇到未转义的 (如 或 '+'ipt>),会错误地将其识别为 HTML 标签结束标记,从而提前终止脚本内容解析——这正是你观察到 '+'ipt> 消失的根本原因。
要可靠保留原始脚本逻辑,需满足两个前提条件:
-
提供完整 HTML 文档结构:避免传入孤立的
<script></script>片段。DOMDocument 在无、等根元素时会自动补全,但补全逻辑不稳定,易干扰内联脚本解析; -
转义脚本中的
序列:在 JavaScript 字符串或拼接表达式中,所有必须写为(注意斜杠前加反斜杠),这是 HTML 规范明确要求的<a href="https://www.php.cn/link/668426da67b63e07674ea8c2ff286289" rel="nofollow" target="_blank">安全转义方式</a>,可防止解析器误触发标签闭合。
以下为推荐的健壮处理方案(含自动转义与结构封装):
function safeLoadScriptHTML($rawScript) {
// 1. 封装为最小合法 HTML5 文档
$html =
<meta charset="utf-8">$rawScript
EOT;
// 2. 安全转义所有 <script> 内部的 </ 序列(仅作用于 script 标签内容)
$html = preg_replace_callback(
'/(<script[^>]*>)(.*?)(<\/script>)/is',
function ($matches) {
// 对 script 内容执行全局 </ → <\/ 转义(避开注释和字符串字面量更复杂,此处为通用安全基线)
$escapedContent = preg_replace('|</|', '<\/', $matches[2][0]);
return $matches[1][0] . $escapedContent . $matches[3][0];
},
$html
);
// 3. 加载并保存
$dom = new DOMDocument();
$dom->recover = true; // 启用容错模式
$dom->strictErrorChecking = false;
$dom->loadHTML($html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
return $dom->saveHTML();
}
// 使用示例
$html1 = "<script>document.write('<scr'+'ipt>alert(123);'+'ipt>')</script>";
$html2 = safeLoadScriptHTML($html1);
echo htmlspecialchars($html2); // 输出中可见已转义的
✅ 关键注意事项:
-
LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD标志可禁用 DOMDocument 自动注入/等隐式节点,减少意外结构污染; - 上述正则转义适用于大多数场景,但若脚本含多层嵌套引号、ES6 模板字符串或注释(如
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











