TinyXML2 的使用

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

 

posted @ 2018-05-16 16:01  程序员进阶笔记  阅读(3293)  评论(0编辑  收藏  举报