【学习笔记】解析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

该变量是一个结构体。

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( )

获取节点的内容(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文件
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>

如果我想提取这个xml文件中的一级孩子节点名称以及其包含的内容
那么我可以使用下面的代码实现:
/* 
* 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;
}
输出结果
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之后,编译时找不到头文件解决办法

相关文章

引言 NOKIA 有句著名的广告语:“科技以人为本”。任何技术都是为了满足人的生产生活需要而产生的。具体...
Writer:BYSocket(泥沙砖瓦浆木匠) 微博:BYSocket 豆瓣:BYSocket Reprint it anywhere u want. 文章...
Writer:BYSocket(泥沙砖瓦浆木匠) 微博:BYSocket 豆瓣:BYSocket Reprint it anywhere u want. 文章...
http://blog.jobbole.com/79252/ 引言 NOKIA 有句著名的广告语:“科技以人为本”。任何技术都是为了满...
(点击上方公众号,可快速关注) 公众号:smart_android 作者:耿广龙|loonggg 点击“阅读原文”,可查看...
一、xml与xslt 相信所有人对xml都不陌生,其被广泛的应用于数据数据传输、保存与序列化中,是一种极为强...