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 张三