You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让DOMDocument加载含未知XML实体的XML且不破坏内容?

问题

为API响应实现XML签名时遇到以下问题:

  • XML包含未知XML实体(如ä等转换后的HTML字符),无法正常转换为DOMDocument,加载后documentElement未被设置,同时抛出实体相关警告
  • 尝试以HTML格式解析,即便传入LIBXML_HTML_NOIMPLIED标志,仍会被添加重复的<xml>和<p>标签
  • 使用LIBXML_DTDLOAD标志虽能正确解析,但会将XML实体文件内容直接输出到响应中,导致返回内容长度大幅增加

希望找到方法,让DOMDocument加载XML字符串时:

  1. 不因未知实体解析失败
  2. 不修改原XML字符串内容
  3. 或在不生成独立XML的情况下解析DTD

当前实现代码:

// 压缩后的XML字符串
$output = '<?xml version="1.0" standalone="no"?>
<!DOCTYPE api_result [
<!ELEMENT api_result (#PCDATA)>
<!ENTITY % xhtml-all SYSTEM "http://server.local/entities/xhtml-all.ent">
%xhtml-all;
]>
<api_result>&auml;</api_result>';

$xml = new DOMDocument();

// 必须保留空白字符
$xml->preserveWhiteSpace = true;
$xml->formatOutput = false;
$xml->strictErrorChecking = false;

$xml->loadXML($output);

// 规范化内容(排他性,不含注释)
if (!$xml->documentElement) { // 此处无法获取内容
    throw new XmlSignerException('Undefined document element');
}

解决方案

核心思路

让DOMDocument加载DTD以识别实体定义,但不解析外部实体的实际内容,同时抑制错误警告,确保documentElement正常初始化,且保存XML时完全保留原实体与结构。

修改后的代码

// 压缩后的XML字符串
$output = '<?xml version="1.0" standalone="no"?>
<!DOCTYPE api_result [
<!ELEMENT api_result (#PCDATA)>
<!ENTITY % xhtml-all SYSTEM "http://server.local/entities/xhtml-all.ent">
%xhtml-all;
]>
<api_result>&auml;</api_result>';

$xml = new DOMDocument();

// 保留原格式与空白字符
$xml->preserveWhiteSpace = true;
$xml->formatOutput = false;
$xml->strictErrorChecking = false;
// 关键配置:禁用外部实体内容解析,仅加载DTD结构
$xml->resolveExternals = false;

// 加载XML时启用DTD加载,并抑制错误警告
$loaded = $xml->loadXML($output, LIBXML_DTDLOAD | LIBXML_NOERROR | LIBXML_NOWARNING);

if (!$loaded || !$xml->documentElement) {
    throw new XmlSignerException('Undefined document element');
}

// 后续签名操作...
// 保存XML时会保留原实体与DOCTYPE结构,不会内联外部实体内容
// $signedXml = $xml->saveXML();

关键参数说明

  • LIBXML_DTDLOAD:加载文档中的DTD,让DOMDocument识别实体定义,避免因未知实体导致解析失败
  • LIBXML_NOERROR | LIBXML_NOWARNING:抑制实体相关的警告与错误,防止解析流程中断
  • $xml->resolveExternals = false:禁止DOMDocument加载外部实体文件的实际内容,避免响应中混入实体文件内容,同时保留原实体引用

额外建议

如果外部DTD访问存在性能或稳定性问题,建议将xhtml-all.ent下载到本地服务器,修改DOCTYPE中的SYSTEM路径为本地文件路径,进一步优化加载效率。

内容的提问来源于stack exchange,提问作者Randommm

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 02:22:09