Delphi和C++ Builder解析XML主要依赖IXMLDocument/TXMLDocument,底层用MSXML或libxml2;VCL内置支持轻量但不支持XPath 1.0全功能;需注意Active设置、编码声明、节点遍历方式及COM线程安全。

Delphi 和 C++ Builder 解析 XML 主要靠 IXMLDocument(Delphi)或 IXMLDocument / TXMLDocument(C++ Builder),底层依赖 MSXML(Windows)或开源库(如 libxml2,需手动集成)。默认安装的 VCL 框架已内置轻量级 XML 支持,够用但不支持 XPath 1.0 全功能或命名空间高级解析。
Delphi 中用 TXMLDocument 加载和遍历节点
推荐使用设计时组件 TXMLDocument(VCL)或运行时创建 IXMLDocument 接口。注意:必须设置 Active := True 才能加载内容,否则 DocumentElement 为 nil。
-
LoadFromFile()和LoadFromXML()都会触发解析,但前者要求文件存在且编码匹配(建议 UTF-8 + BOM) - 节点遍历优先用
ChildNodes而非FirstChild,避免忽略文本节点或注释 - 获取属性值用
Node.Attributes['attrname'],不是Node.AttributeNodes['attrname'].Text(后者在某些版本中返回空) - 中文内容乱码常见于未声明编码或 BOM 缺失 —— 在 XML 字符串开头加
var
XML: IXMLDocument;
Root, Node: IXMLNode;
begin
XML := LoadXMLData('- 你好
');
Root := XML.DocumentElement;
Node := Root.ChildNodes['item'];
if Node <> nil then
ShowMessage(Node.Text); // 输出:你好
ShowMessage(Node.Attributes['id']); // 输出:1
end;C++ Builder 中 TXMLDocument 的典型用法
C++ Builder 的 TXMLDocument 是封装类,比纯接口更易用,但需注意构造方式和内存管理。不能直接 new,应通过窗体设计器拖入或用 new TXMLDocument(NULL) 创建(Owner 为 NULL 时需手动 Free())。
- 调用
LoadFromFile()前必须设Active = false,否则抛异常 “XML document already active” -
DocumentElement->ChildNodes->Nodes[i]是访问子节点的常用路径,Nodes[]索引从 0 开始,不跳过空白文本节点 - 属性读取用
Node->Attributes->GetNodeValue("attr"),不是Node->GetAttribute("attr")(后者在较新版本中已弃用) - 若 XML 含命名空间(如
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"),默认解析器会忽略前缀,无法用ChildNodes['xsi:schemaLocation']直接访问
TXMLDocument* XML = new TXMLDocument(this);
XML->Active = false;
XML->LoadFromFile("data.xml");
XML->Active = true;
IXMLNode* Root = XML->DocumentElement;
IXMLNode* Item = Root->ChildNodes->Nodes[0];
if (Item)
Memo1->Lines->Add(Item->Text);
Memo1->Lines->Add(Item->Attributes->GetNodeValue("id"));遇到“Access violation”或“Interface not supported”错误怎么办
这类错误基本源于 COM 接口生命周期失控或线程误用。Delphi/C++ Builder 的 XML 组件基于 MSXML(Windows 平台),要求 COM 初始化(VCL 应用通常自动完成),但控制台程序或子线程中需手动调用 CoInitialize(nil)。
立即学习“C++免费学习笔记(深入)”;
- 在非主线程中使用
IXMLDocument前,必须先调用CoInitializeEx(NULL, COINIT_APARTMENTTHREADED) - 不要跨线程传递
IXMLNode指针 —— 接口引用计数在线程间不同步,极易崩溃 - 释放顺序:先置
Active = false,再Free或让接口变量离开作用域;重复Free或Release会导致 AV - 如果 XML 内容来自网络或不可信来源,务必用
try..except包裹LoadFromXML(),MSXML 对格式错误极其敏感(如未闭合标签、非法字符)
需要 XPath 或更健壮解析时怎么选
原生 TXMLDocument 不支持 XPath 查询(SelectNodes() 返回空),也不支持 DTD 验证或 XSLT。真有这些需求,别硬改,直接换:
- Windows 下可用
MSXML2.DOMDocument60COM 对象(需 import 类型库),支持完整 XPath 1.0 和命名空间前缀绑定 - 跨平台方案:集成
libxml2(C++ Builder 可用静态链接版),Delphi 有第三方封装如XmlParser(GitHub 开源) - 简单场景下,正则提取 +
StringReplace处理固定结构 XML,比引入大库更快更稳(仅限无嵌套、无转义、无 CDATA 的配置片段)
真正麻烦的从来不是“怎么解析”,而是“XML 本身是否规范”——比如服务端返回的响应混用了 实体但没声明 DTD,或者时间字段用了 2024-05-20T14:30:00+08:00 格式却漏了时区声明。这些细节不处理,接口再漂亮也白搭。










