linux下使用libxml2實現對xml文件的讀取及查詢


  由於項目需要,這兩天在用C++做XML文件解析的工作。在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測試用例:

<?xml version="1.0" encoding="ISO-8859-1"?>

<bookstore>

<book>
<title lang="eng">Harry Potter</title>
<price>29.99</price>
</book>

<book>
<title lang="eng">Learning XML</title>
<price>39.95</price>
</book>

</bookstore>

 

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

#include <stdio.h>
#include <stdlib.h>
#include <libxml/parser.h>
#include <libxml/tree.h>


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)));
break;
}
}

}
pcur = pcur->next;
}

/*****************釋放資源********************/
xmlFreeDoc (pdoc);
xmlCleanupParser ();
xmlMemoryDump ();
return 0;
}


  具體流程我已經在代碼中詳細注釋,這里就不單獨拿出來解釋。


使用XPath語言解析XML文檔

        關於XPath的基礎知識,可以訪問http://www.w3school.com.cn/xpath/index.asp
#include <stdio.h>
#include <stdlib.h>
#include <libxml/parser.h>
#include <libxml/tree.h>
#include <libxml/xpath.h>
#include <libxml/xpathInternals.h>
#include <libxml/xmlmemory.h>
#include <libxml/xpointer.h>

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM