之前写了个小程序,想要使用xml进行数据的收发,所以需要学习下XML的处理。
了解到对xml的处理有两种常见的库,libxml和tinyxml。
考虑到tinyxml是C++的api,而我使用纯C写的程序,所以放弃tinyxml,使用libxml来对XML进行操作。
主要变量
xmlChar
xmlstring.h : typedef unsigned char xmlChar;
该变量一般使用在xmlNodePtr->name等需要使用字符串的地方。
xmlDocPtr
该变量是一个结构体,可以简单理解为指向xml文档的文件描述符。
xmlNodePtr
该变量是一个结构体。
typedef struct _xmlNode xmlNode; typedef xmlNode *xmlNodePtr; struct _xmlNode { void *_private; // 应用数据 xmlElementType type; // 元素类型 const xmlChar *name; // 节点名称 struct _xmlNode *children; // 指向自己的第一个孩子节点 struct _xmlNode *last; // 指向自己的最后一个孩子节点 struct _xmlNode *parent; // 指向自己的父节点 struct _xmlNode *next; // 指向下一个兄弟节点 struct _xmlNode *prev; // 指向前一个兄弟节点 struct _xmlDoc *doc; // 包含文件 /* 以上是通用模块 */ xmlNs *ns; // 指向关联的命名空间 xmlChar *content; // 内容 struct _xmlAttr *properties;// 属性列表 xmlNs *nsDef; // 定义在该节点上的命名空间 void *psvi; // /PSVI 信息 unsigned short line; // 行数 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( )
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 * 类型。
举个栗子
File Name:b.xml <?xml version="1.0" encoding="UTF-8" ?> <html> <head> <title>Welcome to Nginx!</title> </head> <body bgcolor="white" text="black"> <center> <h1>Welcome to Nginx!</h1> </center> <a href = "link_MysqL.PHP"> <p>xusongqi</p> </a> </body> </html>
/* * Author: xusongqi@live.com * * Created Time: 2014年05月31日 星期六 11时21分55秒 * * FileName: xml_analyse.c * * Description: * */ #include <libgen.h> #include <libxml/parser.h> #include <libxml/tree.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> int main(void) { char * xml_filename; char n = 0; xmlDocPtr pdoc = NULL; xmlNodePtr proot = NULL,curNode = NULL; xml_filename = "b.xml"; xmlKeepBlanksDefault(0); pdoc = xmlReadFile(xml_filename,"UTF_8",XML_PARSE_RECOVER); if(pdoc == NULL) { printf("open file error\n"); exit(1); } proot = xmlDocGetRootElement(pdoc); if(proot == NULL) { printf("get element error\n"); exit(1); } if(xmlStrcmp(proot->name,BAD_CAST "html") != 0) { printf("file info error\n"); exit(1); }printf("root node : %s\n",proot->name); curNode = proot->xmlChildrenNode; while(curNode != NULL) { //if(xmlStrcmp(curNode->name,BAD_CAST "text") != 0) if(curNode->name) { printf("child node%d: %s : ",n++,curNode->name); printf("%s\n",xmlNodeGetContent(curNode)); } curNode = curNode->next; } xmlFreeDoc(pdoc); xmlCleanupParser(); return 0; }输出结果:
child node0: head : Welcome to Nginx!
child node1: body : Welcome to Nginx!xusongqi