当前位置: 首页 > news >正文

使用libxml2解析XML文件

目录

一、XML文件格式

二、使用libxml2解析XML文件

1、代码介绍

2、结果测试

2.1 编译

2.2 运行

三、注意点

1、libxml编程--内存泄漏问题


详细教程请参考:XML 教程_w3cschool

一、XML文件格式

先简单介绍xml文件。

<?xml version="1.0" encoding="UTF-8"?>
<!--    root: 根节点
-->
<root><grade value="8"><class value="5"><student name="ZhangSan" age="15" sex="male"/><student name="LiSi" age="16" sex="female"/></class></grade>
</root>
  • XML的第一行为声明,包含版本号和字符编码,如:<?xml version="1.0" encoding="UTF\-8"?>
  • XML的注释方法:<!-- 注释内容(无其他注释符) -->
  • <root></root>是xml的一个节点,即xmlNode。而xmlNodePtr 表示指向xmlNode的指针--xmlNode*
  • <grade value="8"> 是 root的子节点,即 xmlNodePtr->xmlChildrenNode,value为节点的属性。
  • 同理,<class value="5"> 是 grade的子节点, student是class的子节点

二、使用libxml2解析XML文件

1、代码介绍

下面介绍怎么使用libxml2.so库,解析上面的xml文件,并存到 UNIT_T 结构体中。

typedef struct {char acName[64];            //名字int age;                    //年龄char acSex[8];              //性别
} STUDENT_T;#define STUDENT_NUM_MAX	2
typedef struct {int grade;                  //年纪int class;                  //班级int student_num;            //学生数量STUDENT_T stStudent[STUDENT_NUM_MAX];    //学生信息
} UNIT_T;

代码需要包含这两个头文件

#include <libxml/tree.h>  
#include <libxml/parser.h>  

 附上核心代码:

UNIT_T g_stUnit;
static int parse_student(xmlNodePtr _pstXmlNode, STUDENT_T *_pStudent);int xml_parse(const char *_pPath)
{xmlDocPtr pstXmlDoc = NULL;xmlNodePtr pstXmlNode = NULL;/* 判断传参的xml文件是否存在 */if (!file_isexist(_pPath)) {DEBUG_PRINTF("error: file is not exist!!!\n");return -1;}xmlKeepBlanksDefault(0);    //设置是否忽略空白节点,比如空格,默认值是0/* 1.获取树形结构 */pstXmlDoc =  xmlParseFile(_pPath);if (pstXmlDoc == NULL) {DEBUG_PRINTF("error: %s open fail \n", _pPath);return -1;}/* 2.获取根节点 */pstXmlNode = xmlDocGetRootElement(pstXmlDoc);if (pstXmlNode == NULL) {DEBUG_PRINTF("error: Root node check fail");xmlFreeDoc(pstXmlDoc);return -1;}/* 3.确定根节点名是否为"root",不是则返回 */if(xmlStrcmp(pstXmlNode->name, (const xmlChar *)"root")){DEBUG_PRINTF("error: root node != root");xmlFreeDoc(pstXmlDoc);return -1;}xmlChar *pTemp = NULL;pstXmlNode = pstXmlNode->xmlChildrenNode;						//获取子节点/* 4.读取"grade"节点 */if (!xmlStrcmp(pstXmlNode->name, (const xmlChar *)"grade")){pTemp = xmlGetProp(pstXmlNode, "value");                    //获取value属性if (pTemp != NULL) {g_stUnit.grade = atoi((const char *)pTemp);xmlFree(pTemp);}}/* 5.读取"class"节点 */pstXmlNode = pstXmlNode->xmlChildrenNode;						//获取子节点if (!xmlStrcmp(pstXmlNode->name, (const xmlChar *)"class")) {pTemp = xmlGetProp(pstXmlNode, "value");                    //获取value属性if (pTemp != NULL) {g_stUnit.class = atoi((const char *)pTemp);xmlFree(pTemp);}}pstXmlNode = pstXmlNode->xmlChildrenNode;						//获取子节点/* 6.遍历并解析 */g_stUnit.student_num = 0;while(pstXmlNode != NULL) {if (!xmlStrcmp(pstXmlNode->name, (const xmlChar *)"student")) {parse_student(pstXmlNode, &g_stUnit.stStudent[g_stUnit.student_num++]);}pstXmlNode = pstXmlNode->next;					/* 下一个子节点(同级) */}xmlFreeDoc(pstXmlDoc);             /* 释放文档树 */return 0;
}static int parse_student(xmlNodePtr _pstXmlNode, STUDENT_T *_pStudent)
{xmlChar *pTemp = NULL;pTemp = xmlGetProp(_pstXmlNode, (const xmlChar *)"name");    //获取name属性if (pTemp) {snprintf(_pStudent->acName, sizeof(_pStudent->acName), "%s", pTemp);xmlFree(pTemp);                                //释放pTemp = NULL;}pTemp = xmlGetProp(_pstXmlNode, (const xmlChar *)"age");    //获取age属性if (pTemp) {_pStudent->age = atoi((const char *)pTemp);xmlFree(pTemp);                                //释放pTemp = NULL;}	pTemp = xmlGetProp(_pstXmlNode, (const xmlChar *)"sex");    //获取sex属性if (pTemp) {snprintf(_pStudent->acSex, sizeof(_pStudent->acSex), "%s", pTemp);xmlFree(pTemp);                                //释放pTemp = NULL;}return 0;
}

解析XML文档的基本流程如下:

  1. 定义文档指针xmlDocPtr 和节点指针xmlNodePtr
  2. 调用xmlParseFile(),获取 xmlDocPtr 指针;
  3. 调用xmlDocGetRootElement()获取文档根节点,若无根节点则释放文档树并返回;
  4. 通过检查根节点名称,来判断文档正确性;
  5. pstXmlNode = pstXmlNode->xmlChildrenNode 获取子节点,并判断节点名;
  6. 调用 xmlGetProp() 获取节点属性;
  7. 遍历子节点内容,通过pstXmlNode = pstXmlNode->next不断向前遍历,直到pstXmlNode==NULL。查找找指定节点时使用 xmlStrcmp() 函数比较;
  8. 调用xmlFreeDoc()释放文档树指针;

2、结果测试

测试源代码:https://download.csdn.net/download/hinewcc/88908680

2.1 编译

$ gcc -o xml_parse xml_parse.c -I /usr/include/libxml2/ -L /usr/lib/x86_64-linux-gnu -lxml2

-I /usr/include/libxml2/ 原因:libxml/tree.h 和 libxml/parser.h 在 /usr/include/libxml2/ 下;

-L /usr/lib/x86_64-linux-gnu 原因:libxml2.so 在 /usr/lib/x86_64-linux-gnu 下;

编译后,生成 xml_parse 可执行程序。

2.2 运行

$ ./xml_parse file.xml

 打印结果:

grade : 8
class : 5
name : ZhangSan
age : 15
sex : male
name : LiSi
age : 16
sex : female

 测试过程如图:

三、注意点

1、libxml编程--内存泄漏问题

        调用xmlGetProp()函数会返回一个xmlChar类型的指针,这里动态分配了内存,这个指针使用完成之后一定要使用xmlFree()手动释放,其它返回指针类型的函数,使用时都要注意。

http://www.xdnf.cn/news/835669.html

相关文章:

  • 压箱底的8个网站,各种高效工具应有尽有
  • 计算机网络笔记整理(第七版)谢希仁
  • C++读写文件操作(fstream、ifstream、ofstream、seekg、seekp、tellg、tellp用法)
  • 析取范式和合取范式
  • 什么是延时电路?6种延时电路原理讲解
  • Python的类变量、实例变量
  • Java与JavaScript的区别与联系:有人的地方就有江湖,有浏览器的地方就有JavaScript
  • 5个实用的性能测试工具(软件测试工程师必备)_性能测试用例用什么软件
  • (八)面向对象的特征
  • OPNET入门1-第一个仿真例子(Small Internetworks)
  • ad603中文资料
  • 404 Not Found错误页面的解决方法和注意事项
  • iscsi常用命令
  • MonkeyRunner简介
  • sis最新地址获取方法_拳头最新FPS游戏VALORANT资格免费获取方法
  • 谈《黑社会之龙城岁月》中之大D
  • 密码学基础
  • ExploitDB漏洞库
  • ligerUI框架
  • 流量劫持是什么?常用方法有哪些?
  • 400 java web_"400 bad request"错误解决方案|springmvc接收参数时出现400 bad request
  • Linux命令大全(面试必备)
  • 【Linux】UNIX网络编程
  • 【JavaSE8 高级编程 集合框架】集合框架入门系列①框架概览 2019_8_29
  • 什么是堡垒机?为什么需要堡垒机?
  • 条形码类型及常见条形码介绍
  • 还在为复制粘贴烦恼吗?这5个工具帮你轻松搞定
  • 信号(signal)介绍
  • 网络根基之TCPUDP基础知识
  • GPIO的寄存器BSRR和BRR使用摘抄汇总