XMLDocument.LoadFromFile报“Invalid XML”主因是UTF-8 BOM与encoding声明冲突;写入乱码因未设Encoding:=‘UTF-8’且误用Node.Text;跨平台须弃用TXMLDocument改用TXMLParser或OmniXML。

XMLDocument.LoadFromFile 报“Invalid XML”但文件明明能用浏览器打开
Delphi 的 XMLDocument 默认使用 MSXML 解析器(Windows 平台),对编码声明和 BOM 敏感。常见错误是 XML 文件以 UTF-8 BOM 开头,但声明却是 <?xml version="1.0" encoding="UTF-8"?> —— MSXML 会认为 BOM 和声明冲突,直接报错。
实操建议:
- 用记事本或 VS Code 查看文件真实编码:右下角显示 “UTF-8 with BOM” 就要处理
- 保存为纯 UTF-8(无 BOM)再加载,或改用
LoadFromStream配合手动指定编码 - 更稳妥的做法:用
TStringList.LoadFromFile(..., TEncoding.UTF8)读入字符串,再调用XMLDocument.LoadFromXML - 避免依赖系统默认解析器:在设计时勾选
XMLDocument.Options → foNoNamespacePrefix和foIgnoreWhiteSpace,减少解析歧义
写入 XML 后中文乱码或被转义成 安全
根本原因不是 Delphi 编码问题,而是 XMLDocument 默认把所有非 ASCII 字符做字符实体编码(xxx;),且输出时不写 encoding 声明,导致外部工具按系统默认编码(如 GBK)解析失败。
实操建议:
- 写入前必须设置:
XMLDocument.Encoding := 'UTF-8'(注意大小写,写成'utf-8'无效) - 调用
XMLDocument.SaveToFile前,确保根节点的XMLDocument.XML.Text已含正确声明,例如:<?xml version="1.0" encoding="UTF-8"?> - 不要用
Node.Text := '中文'直接赋值,改用Node.NodeValue := '中文',避免自动转义 - 如果仍出现
...,检查是否误用了Node.InnerText—— 它会强制转义,Node.NodeValue才保留原始字符
遍历 TDOMNode 时 Access Violation 或节点数为 0
Delphi 的 XMLDocument 是基于 COM 的封装,节点对象生命周期依赖于文档实例。常见错误是提前释放文档、跨线程访问、或用错遍历方式(比如用 ChildNodes.Count 却忽略文本节点干扰)。
实操建议:
- 确保
XMLDocument.Active := True且未被Free或Destroy;若需长期持有节点,用Node.CloneNode(True) - 遍历子节点时别只看
ChildNodes.Count,先过滤掉空白文本节点:if Node.ChildNodes[i].NodeType = ntElementNode then ... - 避免在循环中修改
ChildNodes(如删除节点),改用倒序遍历:for i := Node.ChildNodes.Count - 1 downto 0 do - 调试时用
Node.XML查看实际结构,比依赖 IDE 对象查看器更可靠
在非 Windows 平台(macOS/Linux)用 TXMLDocument 编译失败
Delphi 的 TXMLDocument 组件底层绑定 MSXML(Windows-only),Linux/macOS 上编译会提示 Unit XMLDoc not found 或链接错误,不是配置问题,是平台限制。
实操建议:
- 跨平台项目必须弃用
TXMLDocument,改用TXMLParser+ 手动构建 DOM,或引入第三方库如OmniXML - 若坚持用原生方案:Windows 用
TXMLDocument,其他平台用TStringList+ 正则/字符串操作(仅限格式简单、无嵌套的配置场景) - 注意
XMLDoc单元在非 Windows 下不参与编译,条件编译不可靠,应在项目选项里直接排除该单元引用
XMLDocument 的坑大多藏在编码声明、节点生命周期和平台绑定这三处。写完记得用外部工具(如 Notepad++ 的“编码检测”或在线 XML 校验器)反向验证生成文件,比只信 Delphi 的 SaveToFile 更靠谱。










