Libxml2 是一個xml c語言版的解析器,本來是為Gnome項目開發的工具,是一個基于MIT License的免費開源軟件。它除了支持c語言版以外,還支持c++、PHP、Pascal、Ruby、Tcl等語言的綁定,能在Windows、Linux、Solaris、MacOsX等平臺上運行。功能還是相當強大的,相信滿足一般用戶需求沒有任何問題。 本文主要簡單介紹一下libxml2在linux下的C++使用的基礎,操作系統為Ubuntu。
一、libxml2的安裝
1、下載libxml2
地址ftp://xmlsoft.org/libxml2/,這里選擇的是libxml2-2.8.0.tar.gz
2、解壓
- tar zxvf libxml2-2.8.0.tar.gz
3、配置安裝
- ./configure
- make
- sudo make install
4、安裝libxml-dev
- sudo apt-get install libxml2-dev
5、把libxml2下的libxml拷貝一份到libxml2所在的目錄
- sudo cp -r /usr/include/libxml2/libxml /usr/include/libxml
6、包含libxml2的測試程序在編譯的時候需要引用xml2庫,比如測試程序test.cpp,則在編譯的時候應該:
二、libxml2常用數據類型
xmlChar是libxml2中的字符類型,在庫中的所有字符,字符串都是基于這個數據類型的。
xmlChar*是指針類型,很多函數都會返回一個動態分配的內存的xmlChar*類型的變量,因此,在使用這類函數時要記得釋放內存,否則會導致內存泄漏,例如這樣的用法:
- xmlChar *name = xmlNodeGetContent(CurNode);
- strcpy(data.name, name);
- xmlFree(name);
xmlDoc
、 xmlDocPtr
//文檔對象結構體及指針 xmlNode、 xmlNodePtr //節點對象結構體及節點指針
xmlAttr、 xmlAttrPtr //節點屬性的結構體及其指針
xmlNs、 xmlNsPtr //節點命名空間的結構及指針
BAD_CAST //一個宏定義,事實上它即是xmlChar*類型
三、libxml2常用函數
int xmlKeepBlankDefault(int val); //設置是否忽略空白的節點,在解析之前一般要調用,默認值為0,最好設置成為1
xmlDocPtr xmlParseFile(const *filename); //分析一個xml文件,并返回一個xml文檔的對象指針
xmlReadFile //讀入一個帶有某種編碼的xml文檔,并返回一個文檔指針
xmlSaveFile //將文檔以默認方式保存
xmlSaveFormatFileEnc //可將文檔以某種編碼/格式的方式進行保存
xmlFreeDoc //釋放文檔指針 注意:當調用此函數時,該文檔所包含的所有節點內存都將被自動釋放。一般來說,一個文檔中所有的節點都應該動態分配然后加入文檔,然后調用xmlFreeDoc函數一次性的釋放所有節點動態分配的內存;但是當節點從文檔中移除時,就需要調用xmlFreeNode或者是xmlFreeNodeList。
2、根節點相關函數
xmlNodePtr xmlDocGetRootElement(xmlDocPtr doc); //獲得文檔的根節點
xmlNodePtr xmlDocSetRootElement(xmlDocPtr doc, xmlNodePtr root); //設置文檔的根節點
3、創建子節點相關函數
xmlNodePtr xmlNewNode(xmlNsPtr ns, const xmlChar *name); //創建一個新節點
xmlNodePtr xmlNewChild(xmlNodePtr parent, xmlNsPtr ns, const xmlChar *name, const xmlChar *content); // 創建一個新的字節點
xmlNodePtr xmlCopyNode(const xmlNodePtr curNode, int extended); //復制當前節點
xmlNodeSetContent //設置節點內容
xmlNodeGetContent //獲取節點內容
xmlNodeListGetString //獲取字符串
4、添加字節點相關函數
xmlNodePtr xmlAddChild(xmlNodePtr parent, xmlNodePtr curNode); //給指定的節點添加子節點
xmlNodePtr xmlAddNextSibling(xmlNodePtr curNode, xmlNodePtr brother); //添加兄弟節點到后面
xmlNodePtr xmlAddPrevSibling(xmlNodePtr curNode, xmlNodePtr brother); //添加兄弟節點到前面
xmlNodePtr xmlAddSibling(xmlNodePtr curNode, xmlNodePtr brother); //添加一個兄弟節點
5、屬性相關函數
xmlAttrPtr xmlNewProp(xmlNodePtr curNode, const xmlChar *name, const xmlChar *value);//創建新節點屬性
xmlAttrPtr xmlSetProp(xmlNodePtr curNode, const xmlChar *name, const xmlChar *value);//設置新節點屬性
xmlAttrPtr *xmlGetProp(xmlNodePtr curNode, const xmlChar *name, const xmlChar *value);//讀取節點屬性
6、使用XPATH查找xml文檔
使用XPATH的流程如下:
1、定義一個XPATH的上下文指針xmlXPathContextPtr context,并且使用函數xmlXPathNewContext來初始化該指針;
2、定義一個XPATH的對象指針xmlXPathObjectPtr obj,并使用函數xmlXPathEvalExpression來計算XPATH的表達式,得到查詢結果,將結果存入對象指針當中;
3、使用obj->nodesetval得到節點集合指針,在其中包含了所有查詢到的XPATH節點;
4、使用函數xmlXPathFreeContext來釋放上下文指針;
5、最后使用函數xmlXPathFreeObject釋放XPATH對象指針。
四、XML文件創建
- #include<iostream>
- #include<libxml/parser.h>
- #include<libxml/xpath.h>
- #include<libxml/tree.h>
-
- using namespace std;
-
- int main(){
- xmlDocPtr doc = xmlNewDoc(BAD_CAST"1.0");
- xmlNodePtr root_node = xmlNewNode(NULL,BAD_CAST"root");
- //set root node
- xmlDocSetRootElement(doc,root_node);
- //create nodes under root node
- xmlNewTextChild(root_node,NULL,BAD_CAST"IP",BAD_CAST"192.168.1.116");
- xmlNewTextChild(root_node,NULL,BAD_CAST"Port",BAD_CAST"65535");
- xmlNewTextChild(root_node,NULL,BAD_CAST"num",BAD_CAST"1000");
- //create a new node,set its content and attributes,then add it to root node
- xmlNodePtr node = xmlNewNode(NULL,BAD_CAST"node2");
- xmlNodePtr content = xmlNewText(BAD_CAST"NODE CONTENT");
- //add node to root node
- xmlAddChild(root_node,node);
- xmlAddChild(node,content);
- xmlNewProp(node,BAD_CAST"attribute",BAD_CAST"yes");
- //create a son node and a grandson one
- node = xmlNewNode(NULL,BAD_CAST"son");
- xmlAddChild(root_node,node);
- xmlNodePtr grandson = xmlNewNode(NULL,BAD_CAST"grandson");
- xmlAddChild(node,grandson);
- xmlAddChild(grandson,xmlNewText(BAD_CAST"This is a grandson node"));
- //save xml doc
- int ret = xmlSaveFile("create.xml",doc);
- if(ret != -1){
- cout<<"A xml doc is created;Write in "<<ret<<" bytes"<<endl;
- }
- xmlFreeDoc(doc);
- return 0;
- }
編譯:g++ build.cc -lxml2
運行:打開create.xml
- <?xml version="1.0"?>
- <root>
- <IP>192.168.1.116</IP>
- <Port>65535</Port>
- <num>1000</num>
- <node2 attribute="yes">NODE CONTENT</node2>
- <son>
- <grandson>This is a grandson node</grandson>
- <son>
- </root>
五、XML文件解析
xml文件
- <?xml version="1.0"?>
- <root>
- <IP>192.168.1.116</IP>
- <Port>65535</Port>
- <num>1000</num>
- <node2 attribute="yes">NODE CONTENT</node2>
- <son>
- <grandson>This is a grandson node</grandson>
- <son>
- </root>
解析代碼:
- #include<iostream>
- #include<libxml/parser.h>
- //#include<libxml/xmlmemory.h>
- #include<string>
-
- using namespace std;
-
- const char* xmlConfig="create.xml";
-
- int main(){
- xmlDocPtr doc;
- xmlNodePtr curNode;
- xmlChar* szKey;
-
- doc = xmlParseFile(xmlConfig);
- if(doc == NULL){
- cout<<"Document not parsed successfully!"<<endl;
- return -1;
- }
- //cout<<"Document parsed successfully!"<<endl;
- curNode = xmlDocGetRootElement(doc);
- if(curNode == NULL){
- cout<<"empty document.\n"<<endl;
- xmlFreeDoc(doc);
- return -1;
- }
- //cout<<"xmlDocGetRootElement OK.\n"<<endl;
- if(xmlStrcmp(curNode->name,BAD_CAST"root")){
- cerr<<"root node is not 'root'"<<endl;
- xmlFreeDoc(doc);
- return -1;
- }
- curNode = curNode->xmlChildrenNode;
- xmlNodePtr propNodePtr = curNode;
- while(NULL != curNode){
- if((!xmlStrcmp(curNode->name,(const xmlChar*)"IP"))){
- szKey = xmlNodeGetContent(curNode);
- cout<<"IP:"<<szKey<<endl;
- //string s((char*)szKey);
- xmlFree(szKey);
- //cout<<s<<endl;
- }else if((!xmlStrcmp(curNode->name,(const xmlChar*)"Port"))){
- szKey = xmlNodeGetContent(curNode);
- cout<<"Port:"<<szKey<<endl;
- xmlFree(szKey);
- }else if((!xmlStrcmp(curNode->name,(const xmlChar*)"num"))){
- szKey = xmlNodeGetContent(curNode);
- cout<<"num:"<<szKey<<endl;
- xmlFree(szKey);
- } else if((!xmlStrcmp(curNode->name,(const xmlChar*)"node2"))){
- szKey = xmlNodeGetContent(curNode);
- cout<<"node2:"<<szKey<<endl;
- xmlFree(szKey);
- // get attributes
- szKey = xmlGetProp(curNode,(const xmlChar*)"attribute");
- cout<<"node2->attribute:"<<szKey<<endl;
- xmlFree(szKey);
- }
- curNode= curNode->next;
- }
-
- return 0;
- }