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>
整个文档,对应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; }
以上是关于C++ 使用TinyXML详解的主要内容,如果未能解决你的问题,请参考以下文章
当我想在 C++ Builder Starter 中链接静态库 TinyXML 2 的发布版本时,为啥会出现未解决的外部错误?