TinyXML是一個開源的解析XML的解析庫,能夠用於C++,能夠在Windows或Linux中編譯。這個解析庫的模型通過解析XML文件,然后在內存中生成DOM模型,從而讓我們很方便的遍歷這棵XML樹。
DOM模型即文檔對象模型,是將整個文檔分成多個元素(如書、章、節、段等),並利用樹型結構表示這些元素之間的順序關系以及嵌套包含關系。
在TinyXML中,根據XML的各種元素來定義了一些類:
XmlNode:對應於DOM結構中的節點的基類,定義了節點轉換,節點遍歷及節點操作(增,刪,查,改)
class XMLNode { //轉換接口 virtual XMLElement* ToElement(); virtual XMLText* ToText(); virtual XMLComment* ToComment(); virtual XMLDocument* ToDocument(); virtual XMLDeclaration* ToDeclaration(); virtual XMLUnknown* ToUnknown(); const char* Value() const; //獲取元素名稱 void SetValue( const char* val, bool staticMem=false ); //修改元素名稱 XMLNode* Parent(); bool NoChildren() const; XMLNode* FirstChild(); XMLNode* LastChild(); const XMLElement* FirstChildElement( const char* name = 0 ) const; const XMLElement* LastChildElement( const char* name = 0 ) const; XMLNode* PreviousSibling(); XMLNode* NextSibling(); const XMLElement* PreviousSiblingElement( const char* name = 0 ) const ; //獲取上一個元素 const XMLElement* NextSiblingElement( const char* name = 0 ) const; //獲取下一個元素 XMLNode* InsertEndChild( XMLNode* addThis ); XMLNode* InsertFirstChild( XMLNode* addThis ); XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis ); void DeleteChildren(); //刪除所有節點 void DeleteChild( XMLNode* node ); //刪除指定節點 }
XmlDeclaration:public XMLNode 對應於XML中的申明部分,即<?versiong="1.0" ?>
XmlDocument:public XMLNode 對應於XML的整個文檔,定義了XML文件(加載,保存)及創建元素(Declaration,Element,Comment,Text)的操作
class TINYXML2_LIB XMLDocument : public XMLNode { public: XMLError LoadFile( const char* filename ); XMLError SaveFile( const char* filename, bool compact = false ); bool HasBOM() const; //檢測是否含BOM void SetBOM( bool useBOM ); XMLElement* RootElement() // 獲取根結點元素
{ return FirstChildElement(); } //沒有提供XMLPrinter,則輸出至stdout,提供XMLPrinter則可以輸出至內存或文件(見XmlPrinter操作) void Print( XMLPrinter* streamer = 0 ) const; XMLElement* NewElement( const char* name ); XMLComment* NewComment( const char* comment ); XMLText* NewText( const char* text ); XMLDeclaration* NewDeclaration( const char* text=0 ); XMLUnknown* NewUnknown( const char* text ); }
XmlElement:public XMLNode 對應於XML的元素,封裝了對元素名稱和元素屬性及Text操作
class TINYXML2_LIB XMLElement : public XMLNode { public: const char* Name() const; //獲取元素名稱 void SetName( const char* str, bool staticMem=false );//設置元素名稱 const char* GetText() const; //獲取Text內容 void SetText( const T* text ); //設置Text內容 XMLError QueryTText( T* ival ) const; //以T類型的方式獲取Text內容 //屬性name存在則修改屬性值,不存在則增加屬性和值 const char* Attribute( const char* name, const char* value=0 ) const; T TAttribute( const char* name ) const; //以T類型的方式獲取屬性的值 XMLError QueryTAttribute( const char* name, T* value ) const; //以T類型的方式獲取屬性的值 T QueryAttribute( const char* name, T* value ) const; //以T類型的方式獲取屬性的值 void DeleteAttribute( const char* name ); //刪除屬性 const XMLAttribute* FirstAttribute() const; //獲取第一個屬性 const XMLAttribute* FindAttribute( const char* name ) const;//查找第一個屬性 }
XmlComment:public XMLNode 對應於XML中的注釋
XmlText:public XMLNode 對應於XML的文字部分
XmlAttribute 對應於XML中的元素的屬性,定義了屬性查詢和修改接口
class TINYXML2_LIB XMLAttribute { const char* Name() const; //獲取屬性名稱 const char* Value() const; //獲取屬性值 const XMLAttribute* Next() const; //獲取下一個屬性 int IntValue() const; //將屬性值轉換為int類型 unsigned UnsignedValue() const; bool BoolValue() const; double DoubleValue() const; float FloatValue() const; XMLError QueryIntValue( int* value ) const; //以指定的類型獲取屬性值 XMLError QueryUnsignedValue( unsigned int* value ) const; XMLError QueryBoolValue( bool* value ) const; XMLError QueryDoubleValue( double* value ) const; XMLError QueryFloatValue( float* value ) const; void SetAttribute( const char* value ); void SetAttribute( int value ); void SetAttribute( unsigned value ); void SetAttribute( bool value ); void SetAttribute( double value ); void SetAttribute( float value ); }
XmlUnknown 對應於XML的未知部分
XmlHandler 定義了針對XML節點指針判斷是否為nullptr操作
XMLPrinter 定義了XML打印操作,將XmlDocument內容打印到內存或文件,無需經XmlDocument構建簡單的XML文件
XmlPrinter功能: //1.打印到內存 XMLPrinter printer; doc.Print(&printer); SomeFunction(printer.CStr()); //2.打印輸出到文件 XMLPrinter printer(fp); doc.Print(&printer); //3.無需經XMLDocument創建一個簡單的XML XMLPrinter printer(fp); printer.OpenElement("foo"); printer.PushAttribute("foo", "bar"); printer.CloseElement();
例如:
<xml version="1.0" standalone=no> <!– Our to do list data –> <ToDo> <Item priority="1"> Go to the <bold>Toy store!</bold></Item> <Item priority="2"> Do bills</Item> </ToDo>
整個對象樹:
TiXmlDocument "demo.xml" TiXmlDeclaration "version=’1.0′" "standalone=no" TiXmlComment " Our to do list data" TiXmlElement "ToDo" TiXmlElement "Item" Attribtutes: priority = 1 TiXmlText "Go to the " TiXmlElement "bold" TiXmlText "Toy store!" TiXmlElement "Item" Attributes: priority=2 TiXmlText "Do bills"
舉例:
#include <iostream> #include <array> #include <vector> #include "tinyxml2.h" using namespace tinyxml2; void read_xml() { XMLDocument doc; doc.LoadFile("class.xml"); auto root_elec = doc.RootElement(); //等同於不指定參數的FirstChildElement() auto root_ele_attr = root_elec->FirstAttribute(); std::cout << root_ele_attr->Name() << ":" << root_ele_attr->Value() << std::endl; root_elec->SetAttribute("classid", "188"); //鍵相同則覆蓋,不同則增加 std::cout << root_ele_attr->Name() << ":" << root_ele_attr->Value() << std::endl; std::cout << "---------------------teacher-----------------------" << std::endl; auto child_elec = root_elec->FirstChildElement()->FirstChildElement(); while (child_elec) { std::cout << child_elec->Name() << ":" << child_elec->GetText(); auto sex = child_elec->IntAttribute("sex") ? "男" : "女"; auto super = child_elec->IntAttribute("super") ? "特級老師" : "普通老師"; std::cout << " " << sex << " " << super; std::cout << std::endl; child_elec = child_elec->NextSiblingElement(); } std::cout << "---------------------student-----------------------" << std::endl; auto student_elec = root_elec->FirstChildElement("student")->FirstChildElement(); while (student_elec) { auto server_ele_attr = student_elec->FirstAttribute(); while (server_ele_attr) { std::cout << server_ele_attr->Name() << ":" << server_ele_attr->Value() << " "; server_ele_attr = server_ele_attr->Next(); } std::cout << std::endl; auto score_elec = student_elec->FirstChildElement(); while (score_elec) { std::cout << score_elec->Name() << ":" << score_elec->GetText() << " "; score_elec = score_elec->NextSiblingElement(); } std::cout << std::endl; std::cout << "-----------------------------------------------" << std::endl; student_elec = student_elec->NextSiblingElement(); } //xmlhandler封裝了對節點指針判斷null的操作,可以安全的執行下面的操作 XMLHandle docHandle(&doc); auto node = doc.FirstChildElement()->FirstChildElement()->FirstChildElement(); std::cout << node->Name() << " " << node->GetText() << std::endl; } void write_xml() { XMLDocument doc; auto decl_elec = doc.NewDeclaration(); //不傳參會添加默認XML頭信息 doc.InsertFirstChild(decl_elec); auto class_elec = doc.NewElement("class"); doc.InsertAfterChild(decl_elec, class_elec); class_elec->SetAttribute("classid", 176); auto teacher_elec = doc.NewElement("teacher"); class_elec->InsertEndChild(teacher_elec); std::array<std::string, 2> elec_name = { "chinese", "math" }; std::array<std::string, 2> teacher_name = { "張三", "李四" }; std::array<std::string, 2> attr_name = { "sex", "super"}; for (int i = 0; i < elec_name.size(); i++) { auto elec = doc.NewElement(elec_name[i].c_str()); elec->SetText(teacher_name[i].c_str()); teacher_elec->InsertEndChild(elec); for (int m = 0; m < attr_name.size(); m++) { elec->SetAttribute(attr_name[i].c_str(), m); } } auto student_elec = doc.NewElement("student"); class_elec->InsertEndChild(student_elec); std::array<std::string, 3> stu_attr_name = { "name", "age", "address" }; std::vector<std::array<std::string, 3>> stu_attr_vec = {{ "張一", "15", "北京" },{ "王二", "17", "天津" },{ "譚三", "15", "河北" },{ "橫四", "16", "廣州" },{ "蔣五", "15", "北京" }}; std::vector<std::array<int, 2>> stu_score_vec = { {98, 88}, {56, 61}, {85, 76}, {91, 95}, {77, 64} }; for (int i = 0; i < 5; i++) { auto node_elec = doc.NewElement("node"); for (int m = 0; m < stu_attr_name.size(); m++) { node_elec->SetAttribute(stu_attr_name[m].c_str(), stu_attr_vec[i][m].c_str()); } for (int n = 0; n < stu_score_vec[0].size(); n++) { auto elec_name = n == 0 ? "chinese_score" : "math_score"; auto score_node_elec = doc.NewElement(elec_name); score_node_elec->SetText(stu_score_vec[i][n]); node_elec->InsertEndChild(score_node_elec); } student_elec->InsertEndChild(node_elec); } doc.SaveFile("class.xml"); } int main( int argc, const char ** argv ) { write_xml(); read_xml(); }
打印輸出為:
classid:176 classid:188 ---------------------teacher----------------------- chinese:張三 男 普通老師 math:李四 女 特級老師 ---------------------student----------------------- name:張一 age:15 address:北京 chinese_score:98 math_score:88 ----------------------------------------------- name:王二 age:17 address:天津 chinese_score:56 math_score:61 ----------------------------------------------- name:譚三 age:15 address:河北 chinese_score:85 math_score:76 ----------------------------------------------- name:橫四 age:16 address:廣州 chinese_score:91 math_score:95 ----------------------------------------------- name:蔣五 age:15 address:北京 chinese_score:77 math_score:64 ----------------------------------------------- chinese 張三