libxml2是开源的XML处理库,提供了一系列C语言接口,支持XML 1.0标准,能够实现XML文档的解析、创建、修改、查询等功能,在C语言项目处理XML数据时应用十分广泛。

环境配置
在使用libxml2之前需要先完成环境配置,不同系统的配置方式略有区别:
- Linux系统:可以通过包管理器直接安装,比如Ubuntu系统执行
sudo apt-get install libxml2-dev即可安装开发依赖,编译时添加-lxml2参数链接库。 - Windows系统:可以到libxml2的官方发布页下载编译好的二进制包,配置好头文件路径和库文件路径,编译时链接对应的lib文件。
核心数据结构
libxml2中有几个常用的核心数据结构需要了解:
xmlDocPtr:表示整个XML文档的指针类型。xmlNodePtr:表示XML节点的指针类型,所有元素、属性、文本等都属于节点。xmlChar:libxml2自定义的字符类型,本质是unsigned char,用来存储XML中的字符数据。
解析XML文档示例
下面是一个解析简单XML文档的示例代码,XML内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<user>
<name>张三</name>
<age>25</age>
<email>test@ipipp.com</email>
</user>
解析该XML的C语言代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <libxml/parser.h>
#include <libxml/tree.h>
// 释放libxml2相关资源
void free_xml_resources(xmlDocPtr doc) {
if (doc != NULL) {
xmlFreeDoc(doc);
}
xmlCleanupParser();
}
int main() {
// 要解析的XML文件路径,也可以是内存中的XML字符串,使用xmlParseMemory函数
const char *xml_file = "test.xml";
xmlDocPtr doc = xmlReadFile(xml_file, NULL, 0);
if (doc == NULL) {
printf("解析XML文件失败n");
return 1;
}
// 获取根节点
xmlNodePtr root_node = xmlDocGetRootElement(doc);
if (root_node == NULL) {
printf("获取根节点失败n");
free_xml_resources(doc);
return 1;
}
// 遍历根节点的子节点
xmlNodePtr cur_node = root_node->children;
while (cur_node != NULL) {
// 只处理元素节点,跳过空白文本节点
if (cur_node->type == XML_ELEMENT_NODE) {
// 获取节点的内容
xmlChar *content = xmlNodeGetContent(cur_node);
printf("节点名称:%s,节点内容:%sn", cur_node->name, content);
xmlFree(content);
}
cur_node = cur_node->next;
}
free_xml_resources(doc);
return 0;
}
生成XML文档示例
下面是使用libxml2生成XML文档的示例代码:
#include <stdio.h>
#include <stdlib.h>
#include <libxml/parser.h>
#include <libxml/tree.h>
void free_xml_resources(xmlDocPtr doc) {
if (doc != NULL) {
xmlFreeDoc(doc);
}
xmlCleanupParser();
}
int main() {
// 创建新的XML文档
xmlDocPtr doc = xmlNewDoc(BAD_CAST "1.0");
// 创建根节点
xmlNodePtr root_node = xmlNewNode(NULL, BAD_CAST "user");
// 设置根节点到文档
xmlDocSetRootElement(doc, root_node);
// 创建子节点name
xmlNodePtr name_node = xmlNewChild(root_node, NULL, BAD_CAST "name", BAD_CAST "李四");
// 创建子节点age
xmlNodePtr age_node = xmlNewChild(root_node, NULL, BAD_CAST "age", BAD_CAST "30");
// 创建子节点email
xmlNodePtr email_node = xmlNewChild(root_node, NULL, BAD_CAST "email", BAD_CAST "demo@ipipp.com");
// 保存XML到文件
int ret = xmlSaveFormatFileEnc("output.xml", doc, "UTF-8", 1);
if (ret == -1) {
printf("保存XML文件失败n");
free_xml_resources(doc);
return 1;
}
printf("XML文件生成成功n");
free_xml_resources(doc);
return 0;
}
使用注意事项
- 所有通过libxml2分配的内存,都需要使用对应的xmlFree函数释放,避免内存泄漏。
- XML中的字符串操作尽量使用libxml2提供的函数,不要直接使用C语言标准库的字符串函数,避免字符编码问题。
- 解析XML时如果遇到错误,可以通过xmlGetLastError函数获取错误信息,方便排查问题。
- 编译程序时需要确保链接了libxml2库,否则会出现未定义的引用错误。