tinyxml2是C++解析XML最轻量易用的选择:单头文件、无依赖、API简洁;需注意空指针检查、手动设置缩进格式化输出,简单配置场景优于pugixml。

用 tinyxml2 解析 XML 文件最省心
直接上结论:C++ 标准库不提供 XML 解析能力,tinyxml2 是目前最轻量、最易集成、文档最清晰的第三方选择。它头文件仅一个 tinyxml2.h,编译无依赖,适合嵌入式或命令行工具等对体积敏感的场景。
常见错误是试图手写正则匹配 XML 标签——XML 允许嵌套、属性含引号、CDATA、注释等,正则根本不可靠;也有人选 libxml2,但 C 风格 API 冗长,C++ 封装层又常带额外依赖(如 pkg-config、zlib)。
- 下载源码后,把
tinyxml2.h和tinyxml2.cpp加进工程即可使用 - 读取文件用
doc.LoadFile("config.xml"),返回tinyxml2::XML_SUCCESS才算成功 - 节点遍历推荐用
FirstChildElement("item")而非FirstChild(),避免误触文本节点或注释节点 - 获取属性值前务必检查指针是否为空:
if (elem && elem->Attribute("id")) { ... }
读取属性和文本内容时的空指针陷阱
tinyxml2 的所有查询接口(FirstChildElement、Attribute、GetText)都可能返回 nullptr 或空指针,不检查就解引用会直接 crash。
典型错误写法:const char* val = elem->FirstChildElement("name")->GetText(); —— 中间任意一环失败,整个链式调用就崩了。
立即学习“C++免费学习笔记(深入)”;
- 拆成多步并逐层判空:
auto nameElem = elem->FirstChildElement("name"); if (nameElem) { const char* text = nameElem->GetText(); } -
Attribute()返回const char*,但若属性不存在,返回的是nullptr,不是空字符串 -
GetText()对空白文本(如)返回nullptr,需用FirstChild()->ToText()+Value()组合判断是否为纯空白
修改 XML 并保存回文件的注意事项
tinyxml2 支持在内存中增删改节点,但保存时不会自动格式化(无缩进、无换行),生成的 XML 是单行紧凑格式,不利于人工查看或 diff。
如果你需要可读性输出,必须手动设置:
doc.InsertEndChild(doc.NewDeclaration());
doc.SetIndent(" "); // 每级缩进两个空格
doc.SaveFile("output.xml");
-
SetIndent()必须在SaveFile()前调用,且只对后续保存生效 - 新增节点要用
doc.NewElement()和doc.NewText()创建,不能用裸new - 删除节点调用
parent->DeleteChild(element),不要直接delete element - 中文文本写入前确保源文件编码是 UTF-8,且 XML 声明中包含
encoding="UTF-8"
不建议在生产环境用 pugixml 做简单解析
pugixml 功能更强(支持 XPath、更灵活的遍历),但对“读几个字段+存个配置”这类简单需求,反而容易踩坑:默认启用 DOM 缓存、内存分配策略较激进、错误提示模糊(比如 parse_error 不告诉你哪一行出错)。
如果你只是从 里取两个值,tinyxml2 5 行代码搞定,pugixml 要处理 xml_parse_result、区分 child_value() 和 text().get(),还容易漏掉 load_string() 的 length 参数。
真正需要 pugixml 的场景是:要查 //user[@active='1']/email 这类表达式,或解析超大 XML(百 MB 级)且对性能有硬要求——否则就是过度设计。











