linux下libxml2使用

在linux下有个很方便的操作xml文件的库——libxml2,它提供了一套创建和查询xml文件的C语言的接口。这篇博客主要介绍如何使用libxml2读取并解析xml文件。

下载并安装libxml2

下载地址:ftp://xmlsoft.org/libxml2/

下载最新的版本,我下载的是libxml2-2.9.1.tar.gz。下载后将文件解压到合适的位置,进入解压后的目录。

编译命令非常简单(注意:如果configure文件没有可执行权限,增加可执行权限):

./configure
make
make install

此时libxml2相关的头文件应该在/usr/local/include/libxml2目录下,libxml2相关的库文件应该在/usr/local/lib目录下。

解析XML文档的两种方式

       在使用libxml2进行XML文档的解析时,非常推荐使用XPath语言实现,如果把XML文件看作数据库的话,那么XPath就可被视为sql,我们只要构造一定格式的语句就可查询到相关结果,而在在libxml2中使用Xpath是非常简单的。当然我们也可以直接通过libxml2相关接口从跟节点出发,根据整个xml的父子节点关系定位到相关节点进行查询。下面我将分别对这两种方式进行介绍。

       我们使用下面的xml测试用例:

 




   	
      	Harry Potter
      	29.99
   	

   	
      	Learning XML
      	39.95
   	

 

直接使用libxml2接口解析XML文档

 

#include 
#include 
#include 
#include 

int main(int argc, char **argv) {
	xmlDocPtr pdoc = NULL;
	xmlNodePtr proot = NULL, pcur = NULL;
	/*****************打开xml文档********************/
	xmlKeepBlanksDefault(0);//必须加上,防止程序把元素前后的空白文本符号当作一个node
	pdoc = xmlReadFile("test.xml", "UTF-8", XML_PARSE_RECOVER);//libxml只能解析UTF-8格式数据
	
	if (pdoc == NULL) {
		printf ("error:can't open file!\n");
		exit(1);
	}
	
	/****************获取xml文档对象的根节对象********************/
	proot = xmlDocGetRootElement (pdoc);
	
	if (proot == NULL) {
		printf("error: file is empty!\n");
		exit(1);
	}
	
	/*****************查找书店中所有书籍的名称********************/
	pcur = proot->xmlChildrenNode;
	
	while (pcur != NULL) {
		//如同标准C中的char类型一样,xmlChar也有动态内存分配,字符串操作等 相关函数。
		//例如xmlMalloc是动态分配内存的函数;xmlFree是配套的释放内存函数;xmlStrcmp是字符串比较函数等。
		//对于char* ch="book", xmlChar* xch=BAD_CAST(ch)或者xmlChar* xch=(const xmlChar *)(ch)
		//对于xmlChar* xch=BAD_CAST("book"),char* ch=(char *)(xch)
		if (!xmlStrcmp(pcur->name, BAD_CAST("book"))) {
			xmlNodePtr nptr=pcur->xmlChildrenNode;
			while (pcur != NULL) {
				if (!xmlStrcmp(nptr->name, BAD_CAST("title"))) {
					//printf("title: %s\n",((char*)XML_GET_CONTENT(nptr->xmlChildrenNode))); 
					printf("title: %s\n",((char*)xmlNodeGetContent(nptr->xmlChildrenNode)));
					break;
				}
			}
			
		}
		pcur = pcur->next;
	}
	
	/*****************释放资源********************/
	xmlFreeDoc(pdoc);
	xmlCleanupParser();
	xmlMemoryDump();

	return 0;
}

 

具体流程我已经在代码中详细注释,这里就不单独拿出来解释。

 

使用XPath语言解析XML文档

       关于XPath的基础知识,可以访问http://www.w3school.com.cn/xpath/index.asp

 

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

xmlXPathObjectPtr getNodeset(xmlDocPtr pdoc, const xmlChar *xpath) {
	xmlXPathContextPtr context = NULL;// XPath上下文指针
	xmlXPathObjectPtr result = NULL;  // XPath结果指针
	context = xmlXPathNewContext(pdoc);
	
	if (pdoc == NULL) {
		printf("pdoc is NULL\n");
		return NULL;
	}
	
	if (xpath) {
		if (context == NULL) {
			printf("context is NULL\n");
			return NULL;
		}
		
		result = xmlXPathEvalExpression(xpath, context);
		xmlXPathFreeContext(context); //释放上下文指针
		if (result == NULL) {
			printf("xmlXPathEvalExpression return NULL\n");
			return NULL;
		}
		
		if (xmlXPathNodeSetIsEmpty(result->nodesetval)) {
			xmlXPathFreeObject(result);
			printf("nodeset is empty\n");
			return NULL;
		}
	}
	
	return result;
}

int main (int argc , char **argv){
	xmlDocPtr pdoc = NULL;
	xmlNodePtr proot = NULL;
	
	/*****************打开xml文档********************/
	xmlKeepBlanksDefault(0);//必须加上,防止程序把元素前后的空白文本符号当作一个node
	pdoc = xmlReadFile ("test.xml", "UTF-8", XML_PARSE_RECOVER);//libxml只能解析UTF-8格式数据
	
	if (pdoc == NULL) {
		printf ("error:can't open file!\n");
		exit(1);
	}
	
	/*****************获取xml文档对象的根节对象********************/
	proot = xmlDocGetRootElement (pdoc);
	
	if (proot == NULL) {
		printf("error: file is empty!\n");
		exit(1);
	}
	
	/*****************查找书店中所有书籍的名称********************/
	xmlChar *xpath = BAD_CAST("//book"); //xpath语句
	xmlXPathObjectPtr result = getNodeset(pdoc, xpath); //查询XPath表达式,得到一个查询结果
	if (result == NULL) {
		printf("result is NULL\n");
		exit(1);
	}
	
	if (result) {
		xmlNodeSetPtr nodeset = result->nodesetval; //获取查询到的节点指针集合
		xmlNodePtr cur;
		
		//nodeset->nodeNr是集合元素总数
		for (int i=0; i < nodeset->nodeNr; i++) {
			cur = nodeset->nodeTab[i];
			cur = cur->xmlChildrenNode;
			
			while (cur != NULL) {
				//如同标准C中的char类型一样,xmlChar也有动态内存分配,字符串操作等 相关函数。
				//例如xmlMalloc是动态分配内存的函数;xmlFree是配套的释放内存函数;xmlStrcmp是字符串比较函数等。
				//对于char* ch="book", xmlChar* xch=BAD_CAST(ch)或者xmlChar* xch=(const xmlChar *)(ch)
				//对于xmlChar* xch=BAD_CAST("book"),char* ch=(char *)(xch)
				if (!xmlStrcmp(cur->name, BAD_CAST("title"))) {
					printf("title: %s\n",((char*)XML_GET_CONTENT(cur->xmlChildrenNode)));
					break;
				}
				
				cur = cur->next;
			}
		}
		
		xmlXPathFreeObject(result);//释放结果指针
	}
	
	/*****************释放资源********************/
	xmlFreeDoc(pdoc);
	xmlCleanupParser();
	xmlMemoryDump();
	
	return 0;
}

 

具体流程我已经在代码中详细注释,这里就不单独拿出来解释。

        更加详细的libxml2接口,可以访问http://xmlsoft.org/html/libxml-tree.html

编译程序并运行

编译上述程序

g++ search1.cpp -I/usr/local/include/libxml2 -L/usr/local/lib -lxml2 -o search1
g++ search2.cpp -I/usr/local/include/libxml2 -L/usr/local/lib -lxml2 -o search2

运行程序及运行结果

运行./search1

显示如下结果:

title: Harry Potter
title: Learning XML

 

运行./search2

显示如下结果:

title: Harry Potter
title: Learning XML

参考资料

 

         http://blog.csdn.net/l_h2010/article/details/38639143

         http://www.open-open.com/lib/view/open1422537148658.html

Enjoy it

你可能感兴趣的:(Linux,API)