XML解析错误“实体未定义”是什么原因

XML解析报“实体未定义”错误是因为解析器遇到未声明的命名实体(如©),而XML仅默认支持5个内置实体;需预处理转义、启用DTD解析或改用数字字符引用。

为什么 XML 解析会报“实体未定义”错误

这个错误本质是 XML 解析器遇到了一个以 & 开头、以 ; 结尾的字符引用(比如  ©),但该名称在当前文档中没有被声明为合法实体。XML 默认只认识 5 个内置实体:&>"',其余如  ® 都属于 HTML 实体,在纯 XML 中不合法,除非你显式声明。

常见触发场景和错误写法

以下情况最

容易引发该错误:

  • 把 HTML 片段直接当 XML 解析(例如从网页抓取的含   的表格内容)
  • 手动生成 XML 字符串时,误用了 HTML 实体(如写 © 而非 ©©
  • 使用了 DTD 声明但路径错误或内容缺失,导致 等未生效
  • 某些库(如 Python 的 xml.etree.ElementTree)默认不加载 DTD,即使 XML 文件里写了 ..>,实体也不会被识别

如何安全处理带 HTML 实体的 XML 输入

最稳妥的方式是预处理,把非法实体转成 Unicode 字符或数字字符引用:

  • Python 可用 html.unescape() 先解码再解析(注意:仅适用于可信输入)
  • Java 中可用 StringEscapeUtils.unescapeHtml4()(Apache Commons Text)
  • Node.js 可用 he.unescape()he 包)
  • 若必须保留 XML 解析流程,可改用支持 DTD 的解析器(如 Python 的 lxml.etree 并启用 resolve_entities=True),但要确保 DTD 可访问且不含远程实体风险
from lxml import etree
parser = etree.XMLParser(resolve_entities=True, dtd_validation=False)
tree = etree.fromstring(xml_bytes, parser)

替代方案:避免实体,改用数字字符引用

数字字符引用( ©)始终被 XML 解析器支持,无需 DTD 声明。这是最兼容、最安全的写法:

  •   替代  
  • ©© 替代 ©
  • 替代

很多编辑器或模板引擎支持自动转换,关键是在生成 XML 阶段就避开命名实体,而不是依赖解析时补救。

真正麻烦的不是报错本身,而是有些系统一边悄悄替换掉非法实体,一边不报错——这种静默行为会让数据语义丢失,比明确报错更难排查。