TinyXML是一个开源的解析XML的解析库,能够用于C++,能够在Windows或Linux中编译。这个解析库的模型通过解析XML文件,然后在内存中生成DOM模型,从而让我们很方便的遍历这棵XML树。
下面是该库的类的继承关系:
在TinyXML中,根据XML的各种元素来定义了一些类:
TiXmlBase:整个TinyXML模型的基类。
TiXmlAttribute:对应于XML中的元素的属性。
TiXmlNode:对应于DOM结构中的节点。
TiXmlComment:对应于XML中的注释
TiXmlDeclaration:对应于XML中的申明部分,即<?versiong="1.0" ?>。
TiXmlDocument:对应于XML的整个文档。
TiXmlElement:对应于XML的元素。
TiXmlText:对应于XML的文字部分
TiXmlUnknown:对应于XML的未知部分。
TiXmlHandler:定义了针对XML的一些操作。
Tinyxml使用了两种编译选择:使用标准C的char *类型或者使用STL中的std::string,其中使用预处理器TIXML_USE_STL进行控制,即添加了TIXML_USE_STL为使用std::string的。鉴于STL的广泛使用以及其强大功能,下面我以使用std::string的tinyxml说明。
下面是具体代码实例:
<span style="font-size:18px;">#include<string>
#include <iostream>
#include <exception>
#include "tinyxml.h"
#include "tinystr.h"
using namespace std;
#include <windows.h>
#include <atlstr.h>
CString GetAppPath(){
TCHAR modulePath[MAX_PATH];
GetModuleFileName(NULL,modulePath,MAX_PATH);
CString strModulePath(modulePath);
strModulePath=strModulePath.Left(strModulePath.ReverseFind('\\'));
return strModulePath;
}
bool createXMlFile(const string& fullPath){
try
{
//创建一个XML的文档对象。
TiXmlDocument *myDocument = new TiXmlDocument();
if (!myDocument)
{
return false;
}
//定义一个xml文件头部声明
TiXmlDeclaration *pDeclartion=new TiXmlDeclaration("1.0","UTF-8","yes");
if(!pDeclartion){
return false;
}
myDocument->LinkEndChild(pDeclartion);
//创建一个根元素并连接。
TiXmlElement *rootElement = new TiXmlElement("Persons");
if (!rootElement)
{
return false;
}
myDocument->LinkEndChild(rootElement);
//创建一个Person元素并连接
TiXmlElement *personElement=new TiXmlElement("person");
if (!personElement)
{
return false;
}
rootElement->LinkEndChild(personElement);
//设置person元素的属性
personElement->SetAttribute("ID","1");
//创建name元素,age元素并连接
TiXmlElement *nameElement=new TiXmlElement("name");
if (!nameElement)
{
return false;
}
TiXmlElement *ageElement=new TiXmlElement("age");
if (!ageElement)
{
return false;
}
personElement->LinkEndChild(nameElement);
personElement->LinkEndChild(ageElement);
//设置name元素和age元素内容
TiXmlText *nameContent=new TiXmlText("我是NO1");
if (!nameContent)
{
return false;
}
TiXmlText *ageContent=new TiXmlText("22");
if (!ageContent)
{
return false;
}
nameElement->LinkEndChild(nameContent);
ageElement->LinkEndChild(ageContent);
myDocument->SaveFile(fullPath.c_str());
delete myDocument;
}
catch (exception& e)
{
cout<<e.what()<<endl;
return false;
}
return true;
}
bool readXml(const string& fullPath){
try{
//创建一个xml文档对象
TiXmlDocument *myDocument=new TiXmlDocument(fullPath.c_str());
if (!myDocument)
{
return false;
}
myDocument->LoadFile();
//获取根元素,即Persons
TiXmlElement *rootElement=myDocument->RootElement();
//输出根元素名称
cout<<rootElement->Value()<<endl;
//获取第一个Person节点
TiXmlElement *firstElement=rootElement->FirstChildElement();
//获取第一个Person的name节点和age节点
TiXmlElement *nameElement=firstElement->FirstChildElement();
TiXmlElement *ageElement=nameElement->NextSiblingElement();
TiXmlAttribute *idAttribute=firstElement->FirstAttribute();
cout<<nameElement->FirstChild()->Value()<<endl;
cout<<ageElement->FirstChild()->Value()<<endl;
cout<<idAttribute->Value()<<endl;
delete myDocument;
}
catch (exception& e)
{
cout<<e.what()<<endl;
return false;
}
return true;
}
/*!
* /brief 打印xml文件。
*
* /param XmlFile xml文件全路径。
* /return 是否成功。true为成功,false表示失败。
*/
bool paintXml(std::string XmlFile)
{
// 定义一个TiXmlDocument类指针
TiXmlDocument *pDoc = new TiXmlDocument();
if (NULL==pDoc)
{
return false;
}
pDoc->LoadFile(XmlFile.c_str());
pDoc->Print();
delete pDoc;
return true;
}
int main(){
CString appPath=GetAppPath();
string fileName="xmlDemo.xml";
string seperator="\\";
string fullPath=appPath.GetBuffer(0)+seperator+fileName;
//创建
createXMlFile(fullPath);
//打印xml
paintXml(fullPath);
cout<<"读取信息如下:"<<endl;
//读取xml
readXml(fullPath);
system("pause");
return 0;
}</span>
具体代码可下载:
http://download.csdn.net/detail/woshizfs/7699843
关于TinyXMLDocument的撤销问题
自己写了一个xml读取写入的程序,new和delete本来成对使用,可是在调试过程中程序总是崩溃,出现内存泄漏问题,后来发现有个指针调用为空(C++中的陷阱就在于此)。
另一方面,却发现使用TinyXML过程中使用了好多new来创建节点。C++需要,自己管理内存。new创建的对象都保存在堆上,必须手动delete掉。可我也没做处理,开始迷惑了。
找了半天,从继承关系来看, 对于一个TinyXMLDocument对象,在析构时,会将其子节点都释放掉,它的子节点都是new出来的,也必须delete掉。但TinyXML的析构函数是空的,什么也没写,不要忘了,TinyXMLDocument是从TinyXMLNode继承而来,在TinyXMLNode的析构函数中,却清楚的写着
TiXmlNode::~TiXmlNode()
{
TiXmlNode* node = firstChild;
TiXmlNode* temp = 0;
while ( node )
{
temp = node;
node = node->next;
delete temp;
}
}
但是,还需要注意,如果TiXmlDocument对象也是new出来的,则需要对TiXmlDocument对象执行delete,才可以触发析构函数被调用。