TinyXML2因轻量(仅两文件)、可用(修复内存缺陷、现代API、UTF-8原生支持)、无依赖而被优选;需注意Windows路径编码、空指针检查、BOM处理及大小写敏感等关键细节。

为什么选 TinyXML2 而不是其他库?
TinyXML2 是 C++ 里少有能同时把「轻量」「可用」「不依赖」三点都做实的 XML 库。它没有外部依赖,头文件 + 源码一共就两个文件(TinyXML2.h 和 TinyXML2.cpp),编译进项目几乎不增加体积;相比原版 TinyXML,它修复了内存管理缺陷,API 更现代,也支持 UTF-8 原生读写。别碰 libxml2 —— 那玩意儿需要链接、配置编码、处理错误上下文,小项目里纯属给自己加戏。
- 不要试图用
std::regex或字符串拼接“手搓” XML:格式错一位(比如少个/或属性没引号),解析就静默失败或崩溃 -
pugixml性能略高,但默认启用 DOM + XPath,多数场景属于过度设计;TinyXML2 的XMLDocument构建/遍历足够快,10MB 以下文档基本无感 - Windows 下注意:确保编译器用的是多字节字符集(MBCS)或 Unicode,否则中文节点名/文本可能变成乱码——这不是 TinyXML2 的锅,是
fopen打开文件时没指定"rt, ccs=UTF-8"(MSVC)
解析 XML 文件时最常见的崩溃点
最常崩在没检查返回值:XMLDocument::LoadFile() 成功才返回 XML_SUCCESS,否则直接拿 FirstChildElement() 就是空指针解引用。
- 必须检查
doc.ErrorID(),不是所有错误都会让LoadFile()返回失败(比如注释里有非法字符) - 如果 XML 文件含 BOM,TinyXML2 能自动跳过;但若你用
std::ifstream读取后传入Parse(),得先去掉前三个字节(0xEF 0xBB 0xBF),否则解析会卡在开头 - 元素名区分大小写:
doc.FirstChildElement("Config")找不到<config></config>;属性同理,element->Attribute("ID")对不上id="123" - 示例片段:
XMLDocument doc; XMLError result = doc.LoadFile("config.xml"); if (result != XML_SUCCESS) { printf("Load failed: %s\n", doc.ErrorName()); // 别只打 "failed" return; } XMLElement* root = doc.FirstChildElement("Settings"); // 注意大小写 if (!root) return; // root 可能为空!
生成 XML 时怎么避免格式错乱和编码问题?
TinyXML2 默认输出不带缩进、无换行的紧凑 XML。想可读,得手动调用 XMLPrinter 并设置缩进;更关键的是:中文文本必须确保传入的是合法 UTF-8 字节数组,而不是本地编码(如 GBK)字符串。
- 直接给
XMLElement::SetText()传std::string没问题,但如果是std::wstring,必须先转 UTF-8(Windows 下用WideCharToMultiByte(CP_UTF8, ...)) - 不要用
XMLNode::LinkEndChild()往已插入的节点反复塞子节点——它只是链表操作,不会校验父子关系;重复调用会导致内存泄漏或后续SaveFile()崩溃 - 输出缩进示例:
XMLDocument doc; auto root = doc.NewElement("Root"); doc.InsertFirstChild(root); // ... 添加子元素 XMLPrinter printer; printer.SetIndent(" "); // 两个空格缩进 doc.Print(&printer); FILE* f = fopen("out.xml", "wb"); // 注意是 "wb",不是 "w"(Windows 下文本模式会改 \n) fwrite(printer.CStr(), 1, printer.Size(), f); fclose(f);
跨平台文件路径与中文路径的坑
TinyXML2 的 LoadFile() 和 SaveFile() 底层调用的是 C 标准库 fopen(),而 C 标准库在 Windows 上根本不支持宽字符路径(即 std::wstring 路径)。Linux/macOS 没这问题,但 Windows 下传入含中文的路径(如 "C:\用户\test.xml")大概率返回 XML_NO_ATTRIBUTE(其实是打开失败,但错误码被误映射)。
立即学习“C++免费学习笔记(深入)”;
- 解决方案只有两个:① 把路径转成 UTF-8 字符串再传给
LoadFile()(Windows 下需用WideCharToMultiByte);② 改用内存加载:用系统 API(CreateFileW+ReadFile)读取二进制内容,再调用doc.Parse(buffer) - macOS/Linux 下路径含中文一般没问题,但要注意文件权限:如果
SaveFile()失败且ErrorID() == XML_ERROR_FILE_COULD_NOT_BE_OPENED,八成是目录不可写,不是 XML 本身有问题 - 别依赖相对路径的“当前工作目录”——启动方式不同(IDE / 终端 / 双击),工作目录可能完全不同;建议用绝对路径或主动
chdir()到资源目录
TinyXML2 本身很稳,真正掉坑里,九成是因为没认真看错误码、没处理空指针、或者在 Windows 上对路径和编码睁一只眼闭一只眼。










