pugixml是一个轻量、高性能的C++ XML解析库,支持快速的XML文档加载、节点查询、内容修改和文件保存,内存占用低且解析速度快,非常适合在需要频繁处理XML数据的C++项目中应用。

pugixml库的安装与配置
首先需要从官方渠道获取pugixml的源码,解压后可以得到pugixml.hpp和pugixml.cpp两个核心文件,将这两个文件添加到你的C++项目源码目录中即可完成基础配置,不需要复杂的编译依赖。
如果是使用CMake管理项目,可以在CMakeLists.txt中添加如下配置:
# 添加pugixml源码
add_library(pugixml STATIC pugixml.cpp)
# 包含头文件目录
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
加载XML文档
pugixml使用pugi::xml_document类来表示一个XML文档对象,加载XML文件或字符串都通过这个类完成。
从文件加载XML
下面是加载本地XML文件的示例代码:
#include <iostream>
#include "pugixml.hpp"
int main() {
pugi::xml_document doc;
// 加载test.xml文件,返回加载结果
pugi::xml_parse_result result = doc.load_file("test.xml");
if (result) {
std::cout << "XML文件加载成功" << std::endl;
} else {
std::cout << "XML文件加载失败,错误描述:" << result.description() << std::endl;
}
return 0;
}
从字符串加载XML
如果需要解析内存中的XML字符串,可以使用load_string方法:
#include <iostream>
#include "pugixml.hpp"
int main() {
pugi::xml_document doc;
const char* xml_str = "<root><name>测试内容</name></root>";
pugi::xml_parse_result result = doc.load_string(xml_str);
if (result) {
std::cout << "XML字符串加载成功" << std::endl;
}
return 0;
}
遍历XML节点
XML文档加载完成后,可以通过节点遍历获取需要的内容,pugixml使用pugi::xml_node表示单个XML节点。
获取根节点与子节点
获取根节点使用document_element方法,获取子节点可以通过child方法按节点名查找,也可以通过迭代的方式遍历所有子节点:
#include <iostream>
#include "pugixml.hpp"
int main() {
pugi::xml_document doc;
doc.load_string("<root><user id="1">张三</user><user id="2">李四</user></root>");
// 获取根节点
pugi::xml_node root = doc.document_element();
std::cout << "根节点名称:" << root.name() << std::endl;
// 遍历所有user子节点
for (pugi::xml_node user_node : root.children("user")) {
// 获取节点的文本内容
std::cout << "用户名称:" << user_node.text().get() << std::endl;
// 获取节点的id属性值
std::cout << "用户ID:" << user_node.attribute("id").value() << std::endl;
}
return 0;
}
使用XPath查询节点
pugixml支持XPath语法,可以快速定位符合条件的节点,使用select_nodes方法执行XPath查询:
#include <iostream>
#include "pugixml.hpp"
int main() {
pugi::xml_document doc;
doc.load_string("<root><user id="1">张三</user><user id="2">李四</user></root>");
// 查询id为1的user节点
pugi::xpath_node_set nodes = doc.select_nodes("/root/user[@id='1']");
for (pugi::xpath_node node : nodes) {
std::cout << "查询结果:" << node.node().text().get() << std::endl;
}
return 0;
}
修改XML内容
pugixml支持对XML节点的内容和属性进行修改,也可以新增节点和属性。
修改节点文本和属性
#include <iostream>
#include "pugixml.hpp"
int main() {
pugi::xml_document doc;
doc.load_string("<root><name>旧内容</name></root>");
pugi::xml_node name_node = doc.child("root").child("name");
// 修改节点文本内容
name_node.text().set("新内容");
// 新增或修改属性
name_node.attribute("version").set_value("1.0");
// 输出修改后的XML
doc.save(std::cout);
return 0;
}
新增节点
使用append_child方法可以添加新的子节点:
#include <iostream>
#include "pugixml.hpp"
int main() {
pugi::xml_document doc;
doc.load_string("<root></root>");
pugi::xml_node root = doc.document_element();
// 新增user子节点
pugi::xml_node new_node = root.append_child("user");
// 设置节点文本
new_node.text().set("王五");
// 设置属性
new_node.append_attribute("id") = "3";
doc.save(std::cout);
return 0;
}
保存XML文件
修改完XML内容后,可以使用save_file方法将文档保存到本地文件,也可以输出到流中:
#include <iostream>
#include "pugixml.hpp"
int main() {
pugi::xml_document doc;
doc.load_string("<root><name>测试</name></root>");
// 保存到output.xml文件
bool save_result = doc.save_file("output.xml");
if (save_result) {
std::cout << "XML文件保存成功" << std::endl;
}
return 0;
}
常见问题说明
- pugixml默认解析时不校验XML的DTD约束,如果需要校验需要额外配置,大部分场景下默认配置即可满足需求
- 加载大文件时建议优先使用文件加载方式,避免将整个大文件内容先读到内存字符串中再解析,减少内存占用
- 节点的
text()方法返回的是xml_text对象,获取内容需要使用get方法,修改内容使用set方法