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;
}
}
所以,doc对象释放时,会对所有已经连接进来的节点进行释放,所以不需要手动的去释放所new出来的东西。
但是,还需要注意,如果TiXmlDocument对象也是new出来的,则需要对TiXmlDocument对象执行delete,才可以触发析构函数被调用。
C++的XML解析器:TinyXML