应使用 TinyXML-2 而非已停更的 TinyXML;安装需认准官方 tinyxml2 仓库,CMake 推荐 add_subdirectory 或 find_package,手动集成仅需 tinyxml2.h/.cpp;注意编码与链接选项,避免混用新旧版本;LoadFile() 必须检查返回值及 ErrorID()。

直接用 TinyXML-2,别碰原始的 TinyXML(已停止维护,API 设计陈旧,宽字符支持差)。
怎么装 TinyXML-2(不是 TinyXML)
很多人卡在第一步:下错库。官方 GitHub 仓库是 tinyxml2,不是 tinyxml。CMake 项目推荐直接 add_subdirectory 或用 find_package(tinyxml2);手动集成只需把 tinyxml2.h 和 tinyxml2.cpp 加进工程,无依赖。
- Windows 下若用 MSVC 编译出错,检查是否启用了
/utf-8或源文件保存为 UTF-8 with BOM(尤其含中文标签时) - Linux/macOS 默认没问题,但注意链接时加
-ltinyxml2(如果系统包管理安装) - 别把
tinyxml.h/tinyxml.cpp(老版)和tinyxml2混在一起,会符号冲突
读取 XML 文件并检查错误的最小安全写法
TinyXML-2 的 LoadFile() 不抛异常,全靠返回值和 ErrorID() 判断失败原因。跳过错误检查等于埋雷。
tinyxml2::XMLDocument doc;
auto result = doc.LoadFile("config.xml");
if (result != tinyxml2::XML_SUCCESS) {
std::cerr << "XML load failed: " << doc.ErrorName() << " at line " << doc.ErrorLineNum() << "\n";
return -1;
}
-
ErrorName()返回的是const char*,比如"XML_ERROR_PARSING_ELEMENT",不是字符串描述,别直接 printf -
ErrorLineNum()在文件有 BOM 或换行符不一致时可能不准,建议先用文本编辑器确认 XML 格式合法 - 如果路径含中文,Windows 下需用
doc.LoadFile(L"配置.xml")并确保传入XMLDocument构造时启用宽字符支持(默认不开启)
提取节点内容时最容易漏掉的空指针检查
几乎所有新手写的代码都少一层 nullptr 判定:从 FirstChildElement() 到 GetText() 链式调用中,任意一环为空都会导致崩溃。
立即学习“C++免费学习笔记(深入)”;
auto root = doc.FirstChildElement("app");
if (!root) { /* 处理根节点不存在 */ }
auto version = root->FirstChildElement("version");
if (version) {
const char* vstr = version->GetText(); // 这里 vstr 可能为 nullptr(元素存在但无文本)
if (vstr) {
std::string ver(vstr);
}
}
-
GetText()返回nullptr表示该元素没有子文本节点(比如或) - 用
QueryIntText()/QueryDoubleText()更安全,它们内部做了空指针判断并返回错误码 - 属性值用
Attribute("name")同样要判空,不能假设属性一定存在
修改后保存 XML 的注意事项
SaveFile() 默认不缩进、不换行,生成的 XML 是一行。需要格式化输出得手动设置:
doc.SetIndent(" "); // 两个空格缩进
doc.SaveFile("output.xml");
- 保存路径不存在目录时会静默失败(返回
XML_ERROR_FILE_COULD_NOT_BE_OPENED),需提前创建父目录 - UTF-8 内容保存正常,但若 XML 声明写了
encoding="GB2312",tinyxml2仍按 UTF-8 写出,不会转码——它不处理编码转换 - 频繁读写同一个文件时,注意 Windows 下文件被占用可能导致
SaveFile()失败,建议先remove()再保存
真正麻烦的从来不是怎么读,而是 XML 文件本身不规范:注释位置错乱、未闭合标签、非法字符(尤其是控制字符)、BOM 和编码声明不一致。解析前用在线校验工具过一遍,比写十层容错更有用。










