C++讀取XML,tinyXml的使用


前言:

  最近在開發的過程中,有個需求是對xml進行格式轉化,從一種格式轉化到另外一種格式.因此,就需要讀取xml進行處理.原本打算寫成工具在linux下運行,不過后來考慮到和系統結合,最后也就使用了前台js轉了.反正都是讀取xml,什么技術轉不都是一樣的么?

  不過剛開始還是對要使用的技術做了一定的探究.c++要讀取xml有很多種方式.比較又名的有:

  rapidXML(這個是網上介紹的,沒用過)

  Xerces-C++ XML Parser:通常來說,讀取XML的方法都是將整個文本進行讀取,然后構建成DOM Tree,之后進行遍歷等操作.這個Parser除了支持構建DOM Tree的方式之外,還支持類似於回調函數的方式進行處理(SAX,SAX2).在讀到相應的節點然后調用函數進行處理.DOM Tree的方式好處是簡單,操作很方便,但是劣勢也是很明顯:需要把整個XML讀進之后才能做處理.如果XML很大,那內存就支撐不住了.SAX,SAX2的作用就在此.其可以支持很大的XML,因為其是相當於事件式的處理方式,不需要構建DOM Tree.不過就是比較麻煩.

  TinyXML: 這個就是接下來要介紹的庫了.取名Tiny,意在編寫一個輕量級的處理基本XML的工具.因此,其支持的特性有限.下面列出了其不支持的功能:

  TinyXML doesn't parse or use DTDs (Document Type Definitions) or XSLs (eXtensible Stylesheet Language.)

                                                           -------------------官方說明文檔

  其給出的理由也很明確:

  1. 支持這兩個特性使得庫更為龐大

  2. 使用更為復雜

  3. 學習曲線更曲折

  需要使用這些特性的可以考慮上面的xerces-C++ XML Parser.很強大.當然也復雜得多

 

TinyXml使用:

  前言說的已經夠多了,咱們就不廢話了,直接講解tinyXml的使用方法.

      安裝:

    TinyXml的安裝方法並不復雜,或者說沒有安裝這個步驟.

    1. 下載tinyXml ,下載tinyxml_2_6_2.zip

    2. 解壓unzip tinyxml_2_6_2.zip.(windows就直接解壓就可以了)

    

 

    對於有vs的朋友來說,直接打開tinyxml.sln就可以了.對於linux用戶來說,則需要拷貝上面全出來的6個文件.

    PS.順帶的,我覺得可以把它的Makefile也拷出來.寫得非常不錯.可以參考參考.

  使用:

    tinyxml的使用方法很簡單,只需要把拷出來的文件放在自己編寫的目錄下面,引用tinyxml.h,tinystr.h即可.

    簡單示例代碼:

    

 1 #include "tinyxml.h"
 2 #include "tinystr.h"
 3 #include <iostream>
 4 
 5 using namespace std;
 6 int main(int argc, char *argv[])
 7 {
 8         if(argc != 2)
 9         {
10                 cout << "usage: "<<argv[0] << " xmlfile" << endl;
11                 return 1;
12         }
13         TiXmlDocument doc(argv[1]);
14         bool loadOk = doc.LoadFile();
15         if (!loadOk)
16         {
17                 cout << "could load:" << doc.ErrorDesc() << endl;
18         }
19         TiXmlPrinter printer;//提供的工具類,目的是將xml的數據按格式輸出
20         doc.Accept(&printer);
21         cout  << printer.CStr() << endl;//輸出
22 
23         TiXmlElement*node = doc.FirstChildElement();//獲取第一個element節點
24         cout << node->Value() << endl;//輸出節點的值
25         string t;
26          node->QueryValueAttribute("type", &t);//獲取節點屬性
27          cout << t << endl;
28           
29                  doc.FirstChild()->NextSibling()->ToElement()->QueryStringAttribute("type", &t);//獲取第二個子節點的數據
30          cout << "2:" << t << endl;
31 
32         //使用遍歷的方式進行處理
33         TiXmlNode* child = NULL;
34         TiXmlElement* element = NULL;
35         TiXmlAttribute *attr = NULL;
36         int ct;
37         while(child = doc.FirstChild()->IterateChildren(child))
38         {
39                 cout << child->ValueStr() << "\t";
40                 ct = child->Type();
41                 cout << ct << "\t";
42                 //根據不同的節點類型做相應處理  
43                 switch(ct)
44                 {
45                         case TiXmlNode::TINYXML_TEXT:
46                                 break;
47                         case TiXmlNode::TINYXML_ELEMENT:
48                                 element = child->ToElement();
49                                 attr = element->FirstAttribute();
50                                 while(attr)
51                                 {
52                                         cout << attr->NameTStr() << "=" << attr->ValueStr() << '\t';
53                                         attr = attr->Next();
54                                 }
55                                 break;
56                 }
57         }
58 
59         return 0;
60 }    

 

編譯命令:

g++ -c tinyxmlparser.cpp -DTIXML_USE_STL
g++ -c tinyxmlerror.cpp -DTIXML_USE_STL
g++ -c tinystr.cpp -DTIXML_USE_STL
g++ -c tinyxml.cpp -DTIXML_USE_STL                                          
g++ -c xmltest.cpp -DTIXML_USE_STL
g++ -o xmltest xmltest.o tinyxmlparser.o tinyxmlerror.o tinystr.o tinyxml.o 

或者大家可以參考那個Makefile改改.

xml文件:

<xml>
    <tag1 type='1'/>
    <tag2 type='2'/>
</xml>

運行結果:

<xml>
    <tag1 type="1" />
    <tag2 type="2" />
</xml>

xml

1:
tag1    1       type=1  tag2    1       type=2 

   沒打回車顯得比較混亂,將就這看看.

詳細解釋:

    這部分僅僅是我的理解,可能有錯.有錯的話還請告知我下.

    tinyxml按照xml的規定,將所有結點做了區分.我們也可以看到類庫中有:

    TiXmlDocument:文檔中的根

    TiXmlNode: node為文檔中所有結點的父類型.其可以轉化為其他的結點類型.

    TiXmlElement: element結點.即我們平常所使用的,具有屬性,tagName的結點.

    TiXmlComment: 注釋

    TiXmlText: 文字結點.

    TiXmlDeclaration: xml的聲明(?xml version="1.0" standalone="yes"?>)

    TiXmlUnknown: 任何tinyXml不認的結點都將歸結為unknown,在重新寫回文件時,按照原樣輸出.

 

    一般我們的操作僅僅在於,取tagName,獲取屬性,獲取文字,迭代.這里就講下這些操作.

    tagName: 對於element來說,可以使用element->Value()或者element->ValueStr();//兩者區別僅僅在於返回值不同,后者返回string.

                          對於Value()函數來說,文檔上也解釋了,對於不同的結點,返回值不同.

		Document:	filename of the xml file
		Element:	name of the element
		Comment:	the comment text
		Unknown:	the tag contents
		Text:		the text string

    獲取屬性:獲取屬性有多種方式.最簡單的是采用const char* Attrubute(const char *),或者采用QueryValueAttribute (const std::string &name, T *outValue) const.還有獲取相應類型,如Int,double等的函數.可以自己查看手冊.有時候需要遍歷屬性時,可以這么寫

TiXmlAttribute *attr = NULL;
attr = element->FirstAttribute();
while(attr)
{
      cout << attr->NameTStr() << "=" << attr->ValueStr();
      attr = attr->Next();  
}

    獲取文字:element->GetText();

    迭代:

TiXmlNode *child = NULL;
while(child = parent->IterateChildren(child))
{
    cout << child->ValueStr() << endl;
}

 

總結:

  對於TinyXml的介紹大致到這.還有很多細節還沒敘述,不過可以看看文檔,下的源碼包里頭就有doc,很方便,講的也很詳細.

      有什么問題可以隨時討論.歡迎留言哈.

     

 

 

 


免責聲明!

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



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