C++ 使用TinyXML详解

Posted wanlu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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;
}

 

 

 

 

 

以上是关于C++ 使用TinyXML详解的主要内容,如果未能解决你的问题,请参考以下文章

C++使用TinyXml(开源库)读取*.XMl文件

C++解析XML(Win10-x64+VS2015)

TinyXML:一个优秀的C++ XML解析器

当我想在 C++ Builder Starter 中链接静态库 TinyXML 2 的发布版本时,为啥会出现未解决的外部错误?

UE4 C++解析与构建 XML 数据,XmlParser 与 tinyxml

TinyXML2的快速实践