推荐tinyxml2:轻量、头文件即用、无依赖、全平台支持;需确保utf-8编码(无bom)、检查loadfile返回值、用firstchildelement替代rootelement、注意gettext返回空指针及空白字符、遍历用for循环避免死循环、savefile前调setindent美化输出。

用 tinyxml2 读 XML 文件最省事
直接上手推荐 tinyxml2,轻量、头文件即用、无依赖,比 libxml2 简单太多,也比 pugixml 更少隐式行为。Windows/Linux/macOS 全平台支持,C++11 起就能用。
- 下载
tinyxml2.h和tinyxml2.cpp,加到工程里(或用vcpkg install tinyxml2) - 确保 XML 文件编码是 UTF-8(含 BOM 会报错
XML_ERROR_PARSING_TEXT) - 必须检查
doc.LoadFile("config.xml") == tinyxml2::XML_SUCCESS,否则后续调用FirstChildElement()可能崩溃 - 别用
doc.RootElement()—— 空文档时返回nullptr,解引用就段错误;改用doc.FirstChildElement("root") -
XMLElement::GetText()返回裸指针,可能为nullptr;且默认不 trim 换行缩进,拿到的可能是"\n Alice\n",需手动处理
遍历同名子元素的正确写法
很多人写成 while (child = parent->FirstChildElement("item")) { child = child->NextSiblingElement("item"); },结果死循环——因为每次都在重置为第一个节点。
- 正确模式是“先取首节点,再在循环体内跳转”,推荐用
for: for (auto* item = root->FirstChildElement("item"); item != nullptr; item = item->NextSiblingElement("item"))- 传入
"item"参数可跳过中间非目标标签(比如夹着注释或文本节点也不影响) - 若 XML 结构不确定(可能压根没
item),FirstChildElement()返回nullptr,循环自动跳过,安全
写 XML 时格式难看?记得调 SetIndent()
tinyxml2 默认输出是单行紧凑格式,可读性差。要生成带缩进的 XML,必须显式设置:
- 调用
doc.SetIndent(" ")(两个空格)或doc.SetIndent("\t") - 这个设置只对后续
SaveFile()生效,不是全局默认 - 不设 indent 时,
SaveFile()输出类似:<root><item id="1">A</item><item id="2">B</item></root> - 设了 indent 后才输出换行+缩进,结构一目了然
为什么不用 pugixml?它强但容易踩坑
pugixml 性能高、支持 XPath,适合复杂查询场景,但对新手不够友好:
立即学习“C++免费学习笔记(深入)”;
- 加载失败时
doc.load_file()返回pugi::xml_parse_result,必须检查result.status == pugi::status_ok,否则doc.child("root")可能返回空节点而不报错 - 属性访问如
node.attribute("id").value(),若属性不存在会返回空字符串而非抛异常,容易掩盖逻辑错误 - UTF-16 支持好,但若误用宽字符接口处理 UTF-8 文件,可能解析乱码且无提示
- 没有像
tinyxml2::QueryIntAttribute()这类带类型安全转换的封装,数字解析得自己std::stoi并捕获异常
除非你真需要 XPath 或高频 DOM 修改,否则没必要为这点性能增加调试负担。











