C++ 使用TinyXML詳解


1.介紹

  TinyXML是一個開源的解析XML的C++解析庫,能夠在Windows或Linux中編譯。這個解析庫的模型通過解析XML文件,然后在內存中生成DOM模型,從而讓我們很方便的遍歷這棵XML樹。

       下載地址:http://www.grinninglizard.com/tinyxml/

  解壓縮后使用TinyXML只需要將其中的6個文件拷貝到項目中就可以直接使用了,這六個文件是:tinyxml.h、tinystr.h、tinystr.cpp、tinyxml.cpp、tinyxmlerror.cpp、tinyxmlparser.cpp,添加頭文件#include "tinyxml.h"或#include <tinyxml>。

       看一下TinyXML類之間繼承關系:

 

  可以看到TinyXml中的注釋comment ,聲明declaration,元素element,文本等都是節點Node的子類,也就是說可以把XMl文件中的各個元素當做節點來處理。Node類型也有到各個子類之間的轉換方法,如ToElement()轉換成元素,ToDocument轉換成文檔等。

  1.各類之間的關系 

   TinyXml實現的是DOM訪問模型,因此提供了一系列的類對應XML文件中的各個節點。主要類間的關系如下:
   TiXmlBase:其他類的基類,是個抽象類
   TiXmlNode:表示一個節點,包含節點的一般方法,如訪問子節點、兄弟節點、編輯自身、編輯子節點
   TiXmlDocument:表示整個XML文檔,不對應其中某個特定的節點。
   TiXmlElement:表示元素節點,可以包含子節點和TiXmlAttribute
   TiXmlComment:表示注釋
   TiXmlDeclaration:表示聲明
   TiXmlText:表示文本節點
   TiXmlUnknown:表示未知節點,通常是出錯了
   TiXmlAttribute:表示一個元素的屬性

   通過一個例子說明一下各類:

1 <?xml version="1.0" encoding="utf-8" ?>
2 <!-This is only a sample-->
3 <Camera>
4    <name>Camera1</name>
5    <price unit=”RMB”>300</price>
6    <description>Some words…</description>
7 </ Camera>
View Code

    整個文檔,對應TiXmlDocument;Camera,name,price,description,都對應TiXmlElement;第一行對應一個TiXmlDeclaration;第二行對應一個TiXmlComment;“TinyXml How To”對應一個TiXmlText;unit則是price的一個TiXmlAttribute;這些類與XML文件中的相應元素都有很好的對應關系,因此相信參照TinyXml的文檔,可以很容易的掌握各個方法的使用。

  2.TinyXML節點類型

   TinyXML的節點類型types是一個枚舉類型,包含DOCUMENT, ELEMENT, COMMENT, UNKNOWN, TEXT 和 DECLARATION。

  3.使用時需注意問題 

   i.各類之間的轉換
    由於各個節點類都從TiXmlNode繼承,在使用時常常需要將TiXmlNode*類型的指針轉換為其派生類的指針,在進行這種轉換時,應該首先使用由TiXmlNode類提供的一系列轉換函數,如ToElement(void),而不是c++的dynamic_cast。
   ii.檢查返回值
    由於TinyXml是一個非校驗的解析器,因此當解析一個文件時,很可能文件並不包含我們預期的某個節點,在這種情況下,TinyXml將返回空指針。因此,必須要對返回值進行檢查,否則將很容易出現內存訪問的錯誤。
   iii.如何重頭建立一個XML文件
    先建立一個TiXmlDocument對象,然后,載入某個模板,或者直接插入一個節點作為根節點,接着就可以像打開一個已有的XML文件那樣對它進行操作了。
      iv.遍歷xml
    TinyXml中的每個節點都可能是另一個節點的父節點這個很重要,因此遍歷TinyXml文檔要用遞歸的方法。另外每個節點都可能具有屬性,文本等。

2.讀取XML.

<Persons>
    <Person ID = '1' other = 'info'>
        <name>Michael</name>
        <age>23</age>
    </Person>
</Persons>

讀取代碼:

 1 #include "tinyxml.h"
 2 #include <iostream>
 3 #include <string>
 4 
 5 using namespace std;
 6 
 7 enum SuccessEnum {FAILURE, SUCCESS};
 8 
 9 SuccessEnum loadXML(string& szFileName)
10 {
11     //獲取一個XML的文檔路徑
12     CString appPath = GetAppPath();
13     string seperator ="\\";
14     string fullPath = appPath.GetBuffer(0)+seperator+szFileName;
15     
16     //創建一個Doc對象
17     TiXmlDocument *myDocument =new TiXmlDocument(fullPath.c_str());
18     myDocument->LoadFile();
19     
20     //獲得根元素,即Persons。
21     TiXmlElement *RootElement = myDocument->RootElement();
22     
23     //輸出根元素名稱,即輸出Persons。
24     cout<< RootElement->Value()<<endl;
25     //獲得第一個Person節點。
26     TiXmlElement *FirstPerson = RootElement->FirstChildElement();
27     
28     //獲得第一個Person的name節點和age節點。
29     TiXmlElement *NameElement = FirstPerson->FirstChildElement();
30     TiXmlElement *AgeElement = NameElement->NextSiblingElement();
31     // 獲取第一個節點ID屬性
32     TiXmlAttribute *IDAttribute = FirstPerson->FirstAttribute();
33     
34     //輸出第一個Person的name內容,age內容,ID屬性,
35     cout<< NameElement->FirstChild()->Value()<<endl;
36     cout<< AgeElement->FirstChild()->Value()<<endl;
37     cout<< IDAttribute->Value()<<endl;
38 }
39 
40 int main(int argc, char* argv[])
41 {
42     if(loadXML("person.xml") == FAILURE)
43         return 1;
44     return 0;
45 }
View Code

XML作為字符串傳入,解析XML:

 1 bool ParseXML(std::string &szXML)
 2 {
 3     TiXmlDocument doc;
 4     doc.Parse(szXml.c_str());//解析xml字符串
 5     TiXmlElement *RootElement = doc.RootElement();
 6     std::string root = RootElement->Value();    // 獲取Persons
 7     
 8     TiXmlElement *person = RootElement->FirstChildElement("person");
 9     TiXmlAttribute *IDAttribute = FirstPerson->FirstAttribute();
10     
11     TiXmlElement *NameElement = FirstPerson->FirstChildElement();
12     TiXmlElement *AgeElement = NameElement->NextSiblingElement();    
13 }
View Code

 3.生成XML

生成代碼:

bool CreateXmlFile(string& szFileName)
{    //創建xml文件,szFilePath為文件保存的路徑,若創建成功返回true,否則false
    try
    {
        //創建一個XML的文檔對象。
        TiXmlDocument *myDocument =new TiXmlDocument();
        
        //創建一個根元素並連接。
        TiXmlElement *RootElement =new TiXmlElement("Persons");
        myDocument->LinkEndChild(RootElement);
        
        //創建一個Person元素並連接。
        TiXmlElement *PersonElement =new TiXmlElement("Person");
        RootElement->LinkEndChild(PersonElement);
        //設置Person元素的屬性。
        PersonElement->SetAttribute("ID","1");
        //創建name元素、age元素並連接。
        TiXmlElement *NameElement =new TiXmlElement("name");
        TiXmlElement *AgeElement =new TiXmlElement("age");
        PersonElement->LinkEndChild(NameElement);
        PersonElement->LinkEndChild(AgeElement);
        
        //設置name元素和age元素的內容並連接。
        TiXmlText *NameContent =new TiXmlText("Michael");
        TiXmlText *AgeContent =new TiXmlText("23");
        NameElement->LinkEndChild(NameContent);
        AgeElement->LinkEndChild(AgeContent);
        CString appPath = GetAppPath();
        string seperator ="\\";
        string fullPath = appPath.GetBuffer(0)+seperator+szFileName;
        myDocument->SaveFile(fullPath.c_str());//保存到文件
    }
    catch(string& e)
    {
        return false;
    }
    return true;
}
View Code

 創建xml,並以字符串返回:

std::string CreateXmlFile()
{    
    try
    {
        //創建一個XML的文檔對象。
        TiXmlDocument *myDocument =new TiXmlDocument();
        
        //創建一個根元素並連接。
        TiXmlElement *RootElement =new TiXmlElement("Persons");
        myDocument->LinkEndChild(RootElement);
        
        //創建一個Person元素並連接。
        TiXmlElement *PersonElement =new TiXmlElement("Person");
        RootElement->LinkEndChild(PersonElement);
        //設置Person元素的屬性。
        PersonElement->SetAttribute("ID","1");
        //創建name元素、age元素並連接。
        TiXmlElement *NameElement =new TiXmlElement("name");
        TiXmlElement *AgeElement =new TiXmlElement("age");
        PersonElement->LinkEndChild(NameElement);
        PersonElement->LinkEndChild(AgeElement);
        
        //設置name元素和age元素的內容並連接。
        TiXmlText *NameContent =new TiXmlText("Michael");
        TiXmlText *AgeContent =new TiXmlText("23");
        NameElement->LinkEndChild(NameContent);
        AgeElement->LinkEndChild(AgeContent);
        
        TiXmlPrinter printer;
        doc.Accept(&printer);
        std::string szXml(printer.CStr());
    }
    catch(string& e)
    {
        return e;
    }
    return szXml;
}

 4.常用函數說明

  (1) FirstChildElement(const char* value=0):獲取第一個值為value的子節點,value默認值為空,則返回第一個子節點。
  (2) NextSiblingElement( const char* _value=0 ) :獲得下一個(兄弟)節點。
  (3) LinkEndChild(XMLHandle *handle):添加一個子節點。元素或者文本
  (4) GetText() :返回一個元素標簽的內容
  (5) LoadFile():重載函數,加載一個xml文件
  (6) SaveFile():重載函數,保存一個xml文件
  (7) Parse():解析傳入字符串xml數據
  (8) RootElement():獲取根節點
  更多函數使用說明,直接參考TinyXML文檔


免責聲明!

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



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