【学习笔记】解析XML文档--使用libxml

前端之家收集整理的这篇文章主要介绍了【学习笔记】解析XML文档--使用libxml前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

之前写了个小程序,想要使用xml进行数据的收发,所以需要学习下XML的处理。

了解到对xml的处理有两种常见的库,libxml和tinyxml。

考虑到tinyxml是C++的api,而我使用纯C写的程序,所以放弃tinyxml,使用libxml来对XML进行操作。


主要变量

xmlChar

xmlstring.h : typedef unsigned char xmlChar;

该变量一般使用在xmlNodePtr->name等需要使用字符串的地方。


xmlDocPtr

该变量是一个结构体,可以简单理解为指向xml文档的文件描述符。


xmlNodePtr

该变量是一个结构体。

  1. typedef struct _xmlNode xmlNode;
  2.  
  3. typedef xmlNode *xmlNodePtr;
  4.  
  5. struct _xmlNode {
  6. void *_private; // 应用数据
  7. xmlElementType type; // 元素类型
  8. const xmlChar *name; // 节点名称
  9. struct _xmlNode *children; // 指向自己的第一个孩子节点
  10. struct _xmlNode *last; // 指向自己的最后一个孩子节点
  11. struct _xmlNode *parent; // 指向自己的父节点
  12. struct _xmlNode *next; // 指向下一个兄弟节点
  13. struct _xmlNode *prev; // 指向前一个兄弟节点
  14. struct _xmlDoc *doc; // 包含文件
  15.  
  16. /* 以上是通用模块 */
  17.  
  18. xmlNs *ns; // 指向关联的命名空间
  19. xmlChar *content; // 内容
  20. struct _xmlAttr *properties;// 属性列表
  21. xmlNs *nsDef; // 定义在该节点上的命名空间
  22. void *psvi; // /PSVI 信息
  23. unsigned short line; // 行数
  24. unsigned short extra; // XPath/XSLT的额外信息


主要函数


xmlReadFile( )

【打开目标XML文档,并返回指向该文件的描述符】

xmlReadFile( char * xmlFileName,"UTF-8",XML_PARSER_RECOVER);

返回值为xmlDocPtr类型,为目标xml文档的文件描述符。


xmlParseMemory( )

获取内存中的xml信息,并返回指向该信息的描述符】

xmlParseMemory( const char * buffer,int size);

返回值为xmlDocOtr类型,为目标xml信息的描述符。


xmlDocGetRootElement( )

【返回XML文档的root节点】

xmlDocGetRootElement( xmlDocPtr )

参数是xmlReadFile函数获取的xml文件描述符,将root节点返回给一个xmlNodePtr类型。


xmlStrcmp( )

【XML字符串比较函数

xmlStrcmp(xmlNodePtr, BAD_CAST "nodeName" )

对一个xml节点的名字和字符串进行比较,如果相同,返回true;不同,返回false。

------------------------------------------------------------------------

【注意】:BAD_CAST用来做显示的转换。

libxml的api使用 const unsigned char* 。

而string literal 只能隐式转换到 const char*。

所以libxml提供一个BAD_CAST用来作显示转换。

——《libxml2中的"BAD_CAST"》 by dotnetsong


xmlNodeGetContent( )

获取节点的内容(message)】

xmlNodeGetContent( xmlNodePtr )

参数是xml的节点,返回值是该节点包含的信息。

------------------------------------------------------------------------

【注意】还有另外一个很相似的获取内容函数xmlNodeListGetString( ),两者的区别如下:

xmlNodeListGetString只取当前节点链表类型TEXT或者ENTITY_REF节点内容

xmlNodeGetContent获取子孙节点类型TEXT或者ENTITY_REF节点内容拼接字符串。


其他函数


xmlKeepBlankDefault(0) :解析xml时忽视空白行,不显示text空节点;

xmlFreeDoc( xmlDocPtr ):释放指向XML文档的描述符;

xmlCleanupParser( ):释放占用的系统资源;


常用宏命令


BAD_CAST

#define BAD_CAST (xmlChar *)

这个宏的作用是将字符串强制转换成xmlChar * 类型,也就是前面说到的unsigned char * 类型。


举个栗子

下面是一个目标XML文件
  1. File Nameb.xml
  2.  
  3. <?xml version="1.0" encoding="UTF-8" ?>
  4. <html>
  5. <head>
  6. <title>Welcome to Nginx!</title>
  7. </head>
  8. <body bgcolor="white" text="black">
  9. <center>
  10. <h1>Welcome to Nginx!</h1>
  11. </center>
  12. <a href = "link_MysqL.PHP">
  13. <p>xusongqi</p>
  14. </a>
  15. </body>
  16. </html>

如果我想提取这个xml文件中的一级孩子节点名称以及其包含的内容
那么我可以使用下面的代码实现:
  1. /*
  2. * Author: xusongqi@live.com
  3. *
  4. * Created Time: 2014年05月31日 星期六 11时21分55秒
  5. *
  6. * FileName: xml_analyse.c
  7. *
  8. * Description:
  9. *
  10. */
  11. #include <libgen.h>
  12. #include <libxml/parser.h>
  13. #include <libxml/tree.h>
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <unistd.h>
  17.  
  18. int main(void)
  19. {
  20. char * xml_filename;
  21. char n = 0;
  22. xmlDocPtr pdoc = NULL;
  23. xmlNodePtr proot = NULL,curNode = NULL;
  24.  
  25. xml_filename = "b.xml";
  26. xmlKeepBlanksDefault(0);
  27.  
  28. pdoc = xmlReadFile(xml_filename,"UTF_8",XML_PARSE_RECOVER);
  29. if(pdoc == NULL)
  30. {
  31. printf("open file error\n");
  32. exit(1);
  33. }
  34.  
  35. proot = xmlDocGetRootElement(pdoc);
  36. if(proot == NULL)
  37. {
  38. printf("get element error\n");
  39. exit(1);
  40. }
  41.  
  42. if(xmlStrcmp(proot->name,BAD_CAST "html") != 0)
  43. {
  44. printf("file info error\n");
  45. exit(1);
  46. }printf("root node : %s\n",proot->name);
  47.  
  48. curNode = proot->xmlChildrenNode;
  49. while(curNode != NULL)
  50. {
  51. //if(xmlStrcmp(curNode->name,BAD_CAST "text") != 0)
  52. if(curNode->name)
  53. {
  54. printf("child node%d: %s : ",n++,curNode->name);
  55. printf("%s\n",xmlNodeGetContent(curNode));
  56. }
  57. curNode = curNode->next;
  58. }
  59.  
  60. xmlFreeDoc(pdoc);
  61. xmlCleanupParser();
  62.  
  63. return 0;
  64. }
输出结果
root node : html
child node0: head : Welcome to Nginx!
child node1: body : Welcome to Nginx!xusongqi

参考资料

libxml -- 解析 XML 文档 //很棒的libxml上手资料
libxml主要函数说明 //另一份入门资料,包涵了直接从缓冲区读取xml的方法【赞!】
"libxml/parser.h: 没有那个文件或目录"解决方案 //安装libxml-dev之后,编译时找不到头文件解决办法

猜你在找的XML相关文章