目录
1.简介
PugiXML 是一个轻量级、高性能的 C++ XML 解析库,设计用于快速处理 XML 文档。它是由Arseny Kapoulkine 开发,它以速度快、内存占用小、跨平台支持、API简洁而闻名非常适合嵌入式系统、游戏开发或需要高效 XML 处理的项目。
核心特点:
1.高性能:解析速度快,内存占用低,适合处理大型 XML 文件。
解析速度快(零拷贝解析、SIMD加速、延迟解析),内存占用低(连续内存块存储节点、内存池),比DOM解析器(如TinyXML)更高效。
支持SAX风格解析(事件驱动(无需将整个文档加载到内存,而是逐行扫描并触发事件回调)),适合大文件处理。
2.简单 API:提供类似 jQuery 的节点选择器(如 XPath-like 表达式)。
3.跨平台:支持 Windows、Linux、macOS、iOS、Android 等。
4.单文件实现:仅需pugixml.hpp
和pugixml.cpp
两个文件。
5.完整功能:
- XML 解析(支持 SAX 和 DOM 模式)。
- XML 文档创建与修改。
- XPath 查询支持(有限但实用)。
- 错误处理与调试信息。
6.内存管理灵活:默认使用标准库(STL),但可禁用STL(PUGIXML_NO_STL) 以适应嵌入式环境(STL容器通常包括动态内存分配和额外的元数据,这些会增加内存占用。嵌入式环境内存有限通常是及KB~几MB。STL依赖标准库导致的环境的依赖性问题)。
7.无依赖: 不依赖第三方库(如 Boost、Qt),仅依赖C++标准库。
8.开源许可:MIT 许可证,可自由用于商业项目。
2.认识pugiXML库
2.1.下载pugiXML
下载地址:https://github.com/zeux/pugixml
源码包含3个文件:
2.2.使用pugiXML的前提
1.语言与编译器的支持
C++版本:需要支持C++11或更改标准的编译器(如GCC 4.8+、Clang 3.3+、MSVC 2013+)
2.必要的头文件包含
需包含PugiXML的核心头文件:
#include "pugixml.hpp" //主功能头文件
若需使用XPath查询,需包含:
#include "pugixml.hpp"
#include "pugixml.cpp" //仅在一个源文件中包含,用于链接XPath实现
3.编译与链接配置
Header-Only模式:
g++ -std=c++11 your_file.cpp -o your_program
XPath支持:
g++ -std=c++11 your_file.cpp path/to/pugixml/src/pugixml.cpp -o your_program
使用CMake集成:
# CMakeLists.txt
add_executable(your_program your_file.cpp)
target_include_directories(your_program PRIVATE path/to/pugixml/src)c)
4.可选配置
禁用STL(嵌入式环境)
#define PUGIXML_NO_STL // 禁用STL依赖
#include "pugixml.hpp"
禁用异常处理
#define PUGIXML_NO_EXCEPTIONS // 禁用异常
#include "pugixml.hpp"
禁用 XPath
#define PUGIXML_NO_XPATH // 禁用XPath支持(减少代码体积)
#include "pugixml.hpp"
5.内存管理注意事项
默认行为:使用标准库的内存分配器
嵌入式优化:通过PUGIXML_MEMORY_POOL宏配置内存池大小
#define PUGIXML_MEMOTY_POOL 16384 //设置16KB内存池
#include "pugixml.hpp"
6.错误处理
错误解析:通过 xml_parse_result 检查解析状态;
pugi::xml_document doc;
pugi::xml_parse_result result = doc.load_string("<root>...</root>");
if (!result)
{
std::cerr << "解析错误:" << result.description() << std::endl;
}
7.使用 PugiXML 最低要求
- 支持C++ 11的编译器
- 包含 pugixml.hpp 头文件
对于高级功能(如XPath)或特殊环境(如嵌入式系统),需额外配置宏定义或链接选项。
3.基本使用示例
1.解析 XML 文档
#include "pugixml.hpp"
#include <iostream>
int main() {
pugi::xml_document doc;
// 从文件加载XML
if (!doc.load_file("config.xml")) {
std::cerr << "无法加载XML文件" << std::endl;
return 1;
}
// 遍历节点
for (pugi::xml_node tool: doc.child("tools").children("tool")) {
std::cout << "工具: " << tool.attribute("name").value() << std::endl;
// 访问子节点
for (pugi::xml_node feature: tool.children("feature")) {
std::cout << " 特性: " << feature.child_value() << std::endl;
}
}
return 0;
}
2.创建 XML 文档
#include "pugixml.hpp"
#include <iostream>
int main() {
pugi::xml_document doc;
// 创建根节点
pugi::xml_node root = doc.append_child("config");
// 添加子节点和属性
pugi::xml_node network = root.append_child("network");
network.append_attribute("enabled") = true;
network.append_child("ip").text() = "192.168.1.1";
network.append_child("port").text() = 8080;
// 添加注释
root.prepend_child(pugi::node_comment).set_value("自动生成的配置文件");
// 保存到文件
doc.save_file("config.xml", " "); // 使用2个空格缩进
std::cout << "XML文件已生成" << std::endl;
return 0;
}
3.使用 XPath 查询
#include "pugixml.hpp"
#include <iostream>
int main() {
pugi::xml_document doc;
if (!doc.load_file("config.xml")) return 1;
// 使用XPath查询
pugi::xpath_node_set nodes = doc.select_nodes("//network/port");
for (pugi::xpath_node node: nodes) {
std::cout << "端口: " << node.node().text().as_int() << std::endl;
}
// 查询带属性的节点
pugi::xpath_node tool = doc.select_node("//tool[@name='editor']");
if (tool) {
std::cout << "找到编辑器工具" << std::endl;
}
return 0;
}
4.使用内存映射文件
pugi::xml_document doc;
pugi::xml_parse_result result = doc.load_buffer_inplace(buffer, size);
4.应用场景
- 配置文件解析:读取应用程序配置(如游戏配置、服务器设置)。
- 数据交换:处理 REST API 返回的 XML 数据。
- 嵌入式系统:在资源受限的设备上解析 XML。
- 游戏开发:加载游戏关卡数据、角色配置等。
- 需要高效 XML 处理的场景:替代复杂的 libxml2 或 xerces。
5.实际案例
minidocx库就使用了pugixml
通过CMake引入pugixml,CMakeList.txt如下:
cmake_minimum_required(VERSION 3.28)
project(minidocx-next VERSION 1.0.0 LANGUAGES C CXX)
option(BUILD_EXAMPLES "Build examples" ON)
option(BUILD_TESTS "Build tests" OFF)
option(WITH_STATIC_CRT "Use static C Runtime library" OFF)
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_DEBUG_POSTFIX d)
set(CMAKE_CONFIGURATION_TYPES Debug Release)
set(CMAKE_VS_DEBUGGER_WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}")
set(THIRD_PARTY_DIR "${CMAKE_CURRENT_SOURCE_DIR}/3rdparty" CACHE PATH "third-party")
set(MINIZ_DIR "${THIRD_PARTY_DIR}/miniz-3.0.2" CACHE PATH "miniz")
set(PUGIXML_DIR "${THIRD_PARTY_DIR}/pugixml-1.13" CACHE PATH "pugixml")
add_library(miniz INTERFACE)
set_target_properties(miniz PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${MINIZ_DIR}"
)
add_library(pugixml INTERFACE)
set_target_properties(pugixml PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${PUGIXML_DIR}"
INTERFACE_SOURCES "${PUGIXML_DIR}/pugixml.cpp"
)
include(cmake/util.cmake)
add_library(minidocx STATIC)
aux_inc_directory(include headers)
aux_src_directory(src sources)
source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}/include/minidocx" PREFIX "Header Files" FILES ${headers})
source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}/src" PREFIX "Source Files" FILES ${sources})
target_sources(minidocx PRIVATE ${headers} ${sources})
target_include_directories(minidocx PRIVATE include/minidocx)
target_include_directories(minidocx INTERFACE include)
target_compile_definitions(minidocx PRIVATE NAMESPACE=md)
target_link_libraries(minidocx PRIVATE miniz pugixml)
if(WITH_STATIC_CRT)
set_target_properties(minidocx PROPERTIES MSVC_RUNTIME_LIBRARY MultiThreaded$<$<CONFIG:Debug>:Debug>)
endif()
if(BUILD_EXAMPLES)
add_subdirectory(examples)
set_directory_properties(PROPERTIES VS_STARTUP_PROJECT myapp)
endif()
6.总结
优缺点总结:
优点 | 缺点 |
---|---|
高性能,解析速度快 | XPath 支持有限(不支持完整标准) |
单文件实现,无依赖 | 不支持 XML 命名空间(Namespace) |
简洁的 API,易于学习 | 高级功能(如 XSLT)需自行扩展 |
跨平台支持 | |
良好的错误处理 |
相关资源
- 官方仓库:https://github.com/zeux/pugixml
- 文档:仓库中的
readme.md
和docs/
目录提供详细 API 文档。 - 性能对比:官方文档包含与其他 XML 库的性能对比。
如果你的项目需要高效、轻量级的 XML 处理,PugiXML 是理想选择。对于需要完整 XPath 支持或复杂 XML 标准的场景,可能需要考虑 libxml2 等更全面的库。