libxml2是C语言中最成熟、最常用的XML解析库,支持DOM和SAX两种方式,轻量稳定跨平台,被GNOME等大量开源项目采用。

libxml2 是 C 语言中最成熟、最常用的 XML 解析库,支持 DOM(树状结构)和 SAX(事件驱动)两种解析方式。它轻量、稳定、跨平台,被 GNOME、GTK、GIMP 等大量开源项目采用。下面以实用为导向,分步骤讲清楚怎么用 C + libxml2 解析 XML 文件。
安装与编译准备
在 Ubuntu/Debian 上:
sudo apt install libxml2-dev
在 macOS 上(使用 Homebrew):
立即学习“C语言免费学习笔记(深入)”;
brew install libxml2
编译时需链接 -lxml2,例如:
gcc parse.c -o parse `xml2-config --cflags --libs`
注意:不要手动写 -I/usr/include/libxml2 和 -L/usr/lib,用 xml2-config 更可靠,它会自动给出正确的头文件路径和链接参数。
基础 DOM 解析:读取并遍历节点
DOM 方式把整个 XML 加载进内存,生成一棵树,适合中小 XML 文件(几 MB 内)。核心流程是:初始化 → 读取文档 → 定位根节点 → 遍历子节点 → 清理。
本文档主要讲述的是使用JSON进行网络数据交换传输;JSON(JavaScript ObjectNotation)是一种轻量级的数据交换格式,易于阅读和编写,同时也易于机器解析和生成,非常适合于服务器与客户端的交互。JSON采用与编程语言无关的文本格式,但是也使用了类C语言的习惯,这些特性使JSON成为理想的数据交换格式。 和 XML 一样,JSON 也是基于纯文本的数据格式。由于 JSON 天生是为 JavaScript 准备的,因此,JSON的数据格式非常简单,您可以用 JSON 传输一个简单的 St
示例 XML(test.xml):
对应 C 代码关键片段:
- 调用 xmlKeepBlanksDefault(0) 忽略空白文本节点,避免遍历时多出无意义的 text 节点
- 用 xmlReadFile() 加载文件,返回 xmlDocPtr;失败时检查是否为 NULL
- 用 xmlDocGetRootElement() 获取根节点(xmlNodePtr),再用 xmlFirstElementChild 或 xmlNextElementSibling 遍历子元素
- 读取属性用 xmlGetProp(node, BAD_CAST "id"),返回 xmlChar*,记得用 xmlFree() 释放
- 读取文本内容用 xmlNodeGetContent(),同样要 xmlFree()
- 最后调用 xmlFreeDoc() 和 xmlCleanupParser()(可选,但推荐)释放资源
提取特定元素:用 XPath 快速定位
如果 XML 结构复杂,手动递归遍历容易出错。libxml2 内置 XPath 支持,能像 CSS 选择器一样精准取值。
- 包含头文件:#include
和 #include - 初始化 XPath 上下文:xmlXPathContextPtr ctx = xmlXPathNewContext(doc)
- 执行查询:xmlXPathObjectPtr obj = xmlXPathEvalExpression(BAD_CAST "//book/title", ctx)
- 遍历结果:obj->nodesetval->nodeTab[i] 是匹配到的 xmlNodePtr,再用 xmlNodeGetContent() 取文本
- 别忘了释放:xmlXPathFreeObject(obj)、xmlXPathFreeContext(ctx)
常见 XPath 表达式://book[@id='1']/author(带属性过滤)、/bookstore/book[1]/title(按位置取)。
错误处理与编码注意事项
libxml2 默认按 UTF-8 处理,若 XML 声明为 ,需提前设置:
xmlSetGenericErrorFunc(NULL, my_error_handler); // 自定义错误回调
xmlInitParser(); // 必须调用
实际开发中建议:
- 始终检查函数返回值(如 xmlDocPtr、xmlNodePtr 是否为 NULL)
- 用 xmlGetLastError() 获取最近错误详情,调试时很有用
- 字符串操作统一用 xmlChar*,转换为 C 字符串可用 xmlStrdup() + xmlStrlen(),或转成 char* 后用 strdup()
- 避免在循环中频繁调用 xmlNodeGetContent(),它每次分配新内存,记得及时 xmlFree()
不复杂但容易忽略:中文路径或含空格的文件名要用 xmlStrcat() 拼接,或先转成 UTF-8 编码再传给 xmlReadFile()。









