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程式庫。
安裝完畢。
2、Libxml2中的資料型別和函式
一個函式庫中可能有幾百種資料型別以及幾千個函式,但是記住大師的話,90%的功能都是由30%的內容提供的。對於libxml2,我認為搞懂以下的資料型別和函式就足夠了。
2.1 內部字元型別xmlChar
xmlChar是Libxml2中的字元型別,庫中所有字元、字串都是基於這個資料型別。事實上它的定義是:xmlstring.h
typedef unsigned char xmlChar;
使用unsigned char作為內部字元格式是考慮到它能很好適應UTF-8編碼,而UTF-8編碼正是libxml2的內部編碼,其它格式的編碼要轉換為這個編碼才能在libxml2中使用。
還經常可以看到使用xmlChar*
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 char和char之間進行強制型別轉換是沒有問題的。
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;
};
可以看到,節點之間是以連結串列和樹兩種方式同時組織起來的,next和prev指標可以組成連結串列,而parent和children可以組織為樹。同時還有以下重要元素:
l 節點中的文字內容:content;
l 節點所屬文件:doc;
l 節點名字:name;
l 節點的namespace:ns;
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