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>
整個文檔,對應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 }
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 }
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;
}
創建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文檔