大家好,欢迎来到IT知识分享网。
目录
详细教程请参考: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文档的基本流程如下:
- 定义文档指针xmlDocPtr 和节点指针xmlNodePtr;
- 调用xmlParseFile(),获取 xmlDocPtr 指针;
- 调用xmlDocGetRootElement()获取文档根节点,若无根节点则释放文档树并返回;
- 通过检查根节点名称,来判断文档正确性;
- pstXmlNode = pstXmlNode->xmlChildrenNode 获取子节点,并判断节点名;
- 调用 xmlGetProp() 获取节点属性;
- 遍历子节点内容,通过pstXmlNode = pstXmlNode->next不断向前遍历,直到pstXmlNode==NULL。查找找指定节点时使用 xmlStrcmp() 函数比较;
- 调用xmlFreeDoc()释放文档树指针;
2、结果测试
测试源代码:https://download.csdn.net/download/hinewcc/
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
打印结果:
测试过程如图:
三、注意点
1、libxml编程–内存泄漏问题
调用xmlGetProp()函数会返回一个xmlChar类型的指针,这里动态分配了内存,这个指针使用完成之后一定要使用xmlFree()手动释放,其它返回指针类型的函数,使用时都要注意。
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/111374.html
