首先想想XML文件,它具有自己的格式。用纯粹的C++文件流来读写XML似乎显得不太科学。
TinyXML是一个简单的、很小的C++XML文件解析集,它能够被容易的整合到程序中。有较好的专门性的东西,那咱们就拿来用用,体会一下其思想也好撒。先不管TinyXML对于咱开发换进VS2010来说是什么,下载之后再进一步定论。
下载地址:http://www.grinninglizard.com/tinyxml/
解压后一看是源代码,心想又要用VS编译了。编译就很可能会出问题呀。VS2010这个东东编译许多包前期都是问题多多叫人难以解决的样子。
然后从编译开始就惹了不少麻烦,什么编译时候的错误呀,编译过后加载进项目的外部无法解析链接错误等。都打算重新编译了,然后好像tinyXML官网手册之上的“using and installing”部分介绍讲到makefile是给linux用的,在windows之上可以用visual C++打开.dsw(如今都是.sln)进行编译整个tinyXML,然后运行xmltest测试是否可用。是不是可以不进行编译就可以使用呢。
看到"touse inan application"部分,看可不可以先用用再说:
[1]将下载的tinyXML解压,将以下六个文件复制到您的工程项目文件(跟您的cpp文件在一个目录下 )中
tinyxml.cpp,
tinyxml.h,
tinyxmlerror.cpp,
tinyxmlparser.cpp,
tinystr.cpp,
tinystr.h
[2]根据VS的特性还得做一点更改
以上拷贝的cpp文件中加入#include "stdafx.h"语句,在要使用tinyXML的地方包含
#include"tinyxml.h"
#include"tinystr.h"
两个头文件。
好了,可以用TinyXML集合了。从解压到配置VS2010这个过程来看,TinyXML就是一个代码集合,里面封装了类和接口,供咱们直接调用的。赶明儿咱应该也写一个,也拥有一个官网。^-^
起码可以参考tinyXML手册来写代码了。哎,不像我,还苦苦编译了tinyXML半天,要是将tinyXML的配置文档跟tinyXML附在一起就好了(还有诸如windows sdk,boost,ACE等库的配置文档都可以跟源库放在一起的,鄙人认为)。
在线手册is here:http://www.grinninglizard.com/tinyxmldocs/tutorial0.html
tinyXML类结构
在http://www.grinninglizard.com/tinyxmldocs/index.html
的左上角电机classes-->class Hierarchy即可得到tinyXML的整个类结构,然后点开TiXmlBase看各个类之间的关系及每个类的作用
TinyXML集合的类结构继承关系
可先大致瞄一眼被命名为TinyXML的类结构,供以后不时之需。
调用这些类的成员函数就就可以创建指定名的XML文件,在XML文件中生成结点,然后指定每个结点的属性,所以根据上图的类结构简单的描述一下每个类的大体作用。
类名 | 描述 |
TiXmlBase: | 是TinyXML中的基类,它的功能很少,只包含打印功能和一些工具函数。主要的结点类型还在文档和声明类中。 |
TiXmlAttribute: | 继承于TiXmlBase类,实现名“字-值”对。 |
TiXmlNode: | 是整个XML文档对象的父类。文档、声明类及其它类都是结点。 |
TiXmlComment: | 用于在XML文件中的注释。 |
TiXmlDeclaration: | 在XML文件中的第一行内容由此类指定。 |
TiXmlDocument: | 时常是XML的第一个结点。它可以绑定XMLL中的其它结点,它可以被保存、载入及被打印到屏幕之上。一个文档类的值就是XML的文件名。 |
TiXmlElement: | 这是一个容器类。它包含值、元素名,还可以包含其它的元素、文本、注释及其它内容。一个元素对象内可以包含任意个其它的元素。 |
TiXmlText: | 用来实现在XML文件中的文本。 |
TiXmlUnknown: | 实现收集XML不认识的东西。 |
凡事都有一个开始,像封装的类这种东西不会有72般的变化,入门会用了,然后就会用了。先用TinyXML类创建一个XML文件。我也将TinyXML集合拿来用的时候封装了一个类:
class MyTinyXML
{
private:
TiXmlDocument *pDoc;
TiXmlDeclaration *pDeclaration;
TiXmlElement *pRootNode;
TiXmlElement *pName;
TiXmlElement *pAdd;
TiXmlText *pNameVaule;
TiXmlText *pAddVaule;
……
public:
MyTinyXML();
~MyTinyXML();
bool create_xml();
…...
}
一看到私有成员里面有指针,赶快想想会不会有内存泄露的嫌疑,赶快为内存泄露这块某略一下。还是用以下朴实的策略:
new-delete成对出现的办法(delete的时候会考虑delete的顺序等因素)
//构造函数
MyTinyXML::MyTinyXML():pDoc(NULL),pDeclaration(NULL),pRootNode(NULL),pName(NULL),pAdd(NULL),pNameVaule(NULL),pAddVaule(NULL)
{
}
//析构函数
MyTinyXML::~MyTinyXML()
{
//释放各new指针的堆内存块
if ( pAddVaule )
{
delete pAddVaule;
}
……
}
即在指针被定义后,在使用前都将其赋值为NULL,不管指针使用的过程怎么样,最后释放指针的时候判断以下是否为空(释放后也可以继续将指针赋值为NULL,只是这里类完了也不会再用到指针了,所以不用再将其赋值为NULL),若为空则不执行delete语句。delete一个没有指向内存块的指针也是危险的,所以这种办法想想看还是蛮有用的。
这种意识是好的,不过在TinyXML类里面,如果将delete子元素或者子元素的TiXMLText、TiXmlElement语句房放在局部函数(如成员函数内)都会发生break错误。所以,以上做法是对的~^~ |
//创建一个XML文件
bool MyTinyXML::create_xml()
{
//定义TiXmlDocument 指针
pDoc = new TiXmlDocument;
if ( !pDoc )
{
return false;
}
//定义一个xml文件头部声明
pDeclaration = new TiXmlDeclaration( "1.0", "UTF-8", "yes" );
if ( !pDeclaration )
{
return false;
}
pDoc->LinkEndChild( pDeclaration );
//根节点
pRootNode = new TiXmlElement( "ChildStation" );
if ( !pRootNode )
{
return false;
}
pDoc->LinkEndChild( pRootNode );
//子节点1
pName = new TiXmlElement( "Name" );
if ( !pName )
{
return false;
}
pRootNode->LinkEndChild( pName );
//子节点2
pAdd = new TiXmlElement( "Add" );
if ( !pAdd )
{
return false;
}
pRootNode->LinkEndChild( pAdd );
//设置name节点的值
pNameVaule = new TiXmlText( "STM100" );
pName->LinkEndChild(pNameVaule);
pAddVaule = new TiXmlText( "0001" );
pAdd->LinkEndChild( pAddVaule );
pDoc->SaveFile( "ChildStation.xml" );
return true;
}
[1]函数的第一句TiXmlDocument *pDoc = new TiXmlDocument;表示声明一个XML文件指针对象,今后会利用这个指针对象调用成员函数来实现某些功能。对应最后一句pDoc->SaveFile( "ChildStation.xml");是将此次文档命名为ChildStation.xml
[2]运行此函数后,会生成一个XML文件,用打开XML文件的工具将此文件打开:
以下内容用图示说明XML中各个节点与TinyXML代码的对应关系:
生成的XML文件与TinyXML代码的对应关系
可见,TiXmlDeclaration声明XML的第一条语句内容,跟XML文件声明处于同一个等级的结点是接下来创建的根节点“ChildStation”,在XML文件中以"<>"开始,以">"结束。“
”与"Station>"之间可以有多个TiXmlElement。
[3]创建子结点
在ChildStation下的子结点也是TiXmlElement类来完成,并且可以指定每个结点的value。见上图。
创建TinyXML的一个简单应用。
此次笔记记录完毕。