1. 程式人生 > >libxml2程式設計--C語言xml(1)

libxml2程式設計--C語言xml(1)

1、下載與安裝LIBXML2

Libxml2是一個C語言的XML程式庫,可以簡單方便的提供對XML文件的各種操作,並且支援XPATH查詢,以及部分的支援XSLT轉換等功能。Libxml2的下載地址是http://xmlsoft.org/,完全版的庫是開源的,並且帶有例子程式和說明文件。最好將這個庫先下載下來,因為這樣可以檢視其中的文件和例子。

由於我是在linux下用C語言進行開發的,所以我下載的是libxml2-2.6.20.tar.gz版本的原始碼包。

具體安裝步驟:

1、解壓:$tar zxvf libxml2-2.6.20.tar.gz

2、進入解壓後的安裝目錄:$cd libxml2-2.6.20

3、安裝三部曲:1$./configure

              2)$make

              3)$make install

在ubuntu上可以直接使用 sudo apt-get install libxml2 下載安裝libxml2程式庫。

安裝完畢。


2Libxml2中的資料型別和函式

一個函式庫中可能有幾百種資料型別以及幾千個函式,但是記住大師的話,90%的功能都是由30%的內容提供的。對於libxml2,我認為搞懂以下的資料型別和函式就足夠了。


2.1 內部字元型別xmlChar

xmlCharLibxml2中的字元型別,庫中所有字元、字串都是基於這個資料型別。事實上它的定義是:xmlstring.h

typedef unsigned char xmlChar;

使用unsigned char作為內部字元格式是考慮到它能很好適應UTF-8編碼,而UTF-8編碼正是libxml2的內部編碼格式的編碼要轉換為這個編碼才能在libxml2中使用

還經常可以看到使用xmlChar*

作為字串型別,很多函式會返回一個動態分配記憶體的xmlChar*變數,使用這樣的函式時記得要手動使用xmlFree函式刪除記憶體。


2.2 xmlChar相關函式

如同標準c中的char型別一樣,xmlChar也有動態記憶體分配、字串操作等相關函式。例如xmlMalloc是動態分配記憶體的函式;xmlFree是配套的釋放記憶體函式;xmlStrcmp是字串比較函式等等。

基本上xmlChar字串相關函式都在xmlstring.h中定義;而動態記憶體分配函式在xmlmemory.h中定義。


2.3 xmlChar*與其它型別之間的轉換

另外要注意,因為總是要在xmlChar*char*之間進行型別轉換,所以定義了一個巨集BAD_CAST,其定義如下:xmlstring.h

#define BAD_CAST (xmlChar *)

原則上來說,unsigned charchar之間進行強制型別轉換是沒有問題的。


2.4 文件型別xmlDoc、指標xmlDocPtr

xmlDoc是一個struct,儲存了一個xml的相關資訊,例如檔名、文件型別、子節點等等;xmlDocPtr等於xmlDoc *,它搞成這個樣子總讓人以為是智慧指標,其實不是,要手動刪除的。

    l   xmlNewDoc函式建立一個新的文件指標。

    l   xmlParseFile函式以預設方式讀入一個UTF-8格式的文件,並返回文件指標。

    l   xmlReadFile函式讀入一個帶有某種編碼的xml文件,並返回文件指標;細節見libxml2參考手冊。

    l   xmlFreeDoc釋放文件指標。特別注意,當你呼叫xmlFreeDoc時,該文件所有包含的節點記憶體都被釋放,所以一般來說不需要手動呼叫xmlFreeNode或者xmlFreeNodeList來釋放動態分配的節點記憶體,除非你把該節點從文件中移除了。一般來說,一個文件中所有節點都應該動態分配,然後加入文件,最後呼叫xmlFreeDoc一次釋放所有節點申請的動態記憶體,這也是為什麼我們很少看見xmlNodeFree的原因。

    l   xmlSaveFile將文件以預設方式存入一個檔案。

    l   xmlSaveFormatFileEnc可將文件以某種編碼/格式存入一個檔案中。


2.5 節點型別xmlNode、指標xmlNodePtr

節點應該是xml中最重要的元素了,xmlNode代表了xml文件中的一個節點,實現為一個struct,內容很豐富:tree.h

typedef struct _xmlNode xmlNode;

typedef xmlNode *xmlNodePtr;

struct _xmlNode {

    void          *_private;

    xmlElementTypetype;  

    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;

    unsigned short   line;  

    unsigned short   extra; 

};

可以看到,節點之間是以連結串列和樹兩種方式同時組織起來的nextprev指標可以組成連結串列,而parentchildren可以組織為樹。同時還有以下重要元素:

l   節點中的文字內容:content

l   節點所屬文件:doc

l   節點名字:name

l   節點的namespacens

l   節點屬性列表:properties

xml文件的操作其根本原理就是在節點之間移動、查詢節點的各項資訊,並進行增加、刪除、修改的操作。

xmlDocSetRootElement函式可以將一個節點設定為某個文件的根節點,這是將文件與節點連線起來的重要手段,當有了根結點以後,所有子節點就可以依次連線上根節點,從而組織成為一個xml樹。


2.6 節點集合型別xmlNodeSet、指標xmlNodeSetPtr

節點集合代表一個由節點組成的變數,節點集合只作為Xpath的查詢結果而出現XPATH的介紹見後面),因此被定義在xpath.h中,其定義如下:

 

typedef struct _xmlNodeSet xmlNodeSet;

typedef xmlNodeSet *xmlNodeSetPtr;

struct _xmlNodeSet {

    int nodeNr;         

    int nodeMax;     

    xmlNodePtr *nodeTab;

   

};

可以看出,節點集合有三個成員,分別是節點集合的節點數nodeNr最大可容納的節點數nodeMax,以及節點陣列頭指標nodeTab。對節點集合中各個節點的訪問方式很簡單,如下:

xmlNodeSetPtr nodeset = XPATH查詢結果;

for (int i = 0; i < nodeset->nodeNr; i++)

{

    nodeset->nodeTab[i];

}

注意,libxml2是一個c函式庫,因此其函式和資料型別都使用c語言的方式來處理。如果是c++,我想我寧願用STL中的vector來表示一個節點集合更好,而且沒有記憶體洩漏或者溢位的擔憂。


原文:http://blog.sina.com.cn/s/blog_6a1837e90100ns2q.html