原文转自 http://blog.csdn.net/K346K346/article/details/48750417

1.TinyXML2概述

TinyXML2是simple、small、efficient开源的C++ XML文件解析库,可以很方便的应用到现有的项目之中。非常适合存储简单数据,配置文件,对象序列化等数据量不是很大的操作。

TinyXML2详细介绍与源码获取方法详见:TinyXML2官网


2. TinyXML1与TinyXML2对比

TinyXML1与TinyXML2这两个著名的开源XML文件解析库均出自Lee Thomason之手,向这位满怀开源精神的大家致敬。

TinyXML2适用于大部分的C/C++项目开发,经得住考验,是最好的选择。较TinyXML1而言,TinyXML2化繁为简,使用时只需要包含两个文件,而TinyXML1需要6个文件,一般生成静态链接库供项目的使用。TinyXML1详细介绍与源码见:TinyXML1官网。TinyXML1用法用例可以参考博文:TinyXML快速入门

TinyXML2使用了与TinyXML1相似都可API,并且拥有丰富的测试案例。但TinyXML2解析器相对TinyXML1在代码上是完全重写,使其更适合于游戏开发中使用。它使用更少的内存,更快,并使用更少的内存分配。

TinyXML2无需STL,也放弃了对STL支持。所有字符串查询均使用C风格字符串“const char *”来表示,省去string类型对象的构造,并使代码更简单。

二者共同点: (1)都使用了简单易用的API。 (2)都是基于DOM(Document Object Model,文档对象模型)的解析器。 (3)都支持UTF-8编码。

TinyXML2的优点: (1)对大部分大部分的C/C++项目具有普适性。 (2)使用较少的内存(约TinyXML1的40%),速度变得更快。 (3)没有C++的STL的要求。 (4)更接近现代C++的特性,如使用了适当的命名空间。 (5)适当有效的处理了的空白字符(空格,TAB和回车)。

TinyXML1的优点: (1)可以报告分析错误的位置。 (2)提供一些C++ STL公约支持:流和字符串。 (3)拥有非常成熟和良好的调试代码库。


3. TinyXML2的用法用例

TinyXML2的网上教程并不多见,醍醐灌顶,受益匪浅的教程更是凤毛麟角。有的也是蜻蜓点水、参差不齐的泛泛而谈。最终,所能参考的资料也就是官网的文档和示例代码,但却有点晦涩难懂。因此,本文就为了解决这个尴尬的局面,结合官网的资料和网上资源,尽量详细的列出TinyXML2的常见用法用例,不足之处,请留言补充,后续增加修改。

xml文件本质就是小型的数据库,换个角度来说就是,对数据库有什么操作,那么对xml文件就应能实现什么操作。一般而言,对数据库的操作包括以下几种:新建数据库和对数据库增删查改。那么对应xml文件就是新建xml文件、增加xml文件的节点,删除xml文件的指定节点,查询xml文件指定节点的值,修改xml文件中节点的值。

使用方法:将tinyxml2.cpp和tinyxml2.h拷贝至项目目录,使用时包含#include “tinyxml2.h”和using namespace tinyxml2。

使用场景:存储用户信息。

用户数据表设计如下:

变量名 描述 类型 长度(字节) 不为空 主键
UserName 用户名 Vchar 3-20 Y Y
Password 密码 Char 32 Y N
Gender 性别 Int 1 N N
Mobile 电话 Char 11 N N
Email 电子邮箱 Varchar 1-50 N N

对应XML文件实现如下:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<DBUSER>
<User Name=”lvlv” Password =”123456”>
<Gender></Gender>
<Mobile ></ Mobile>
<Email ></ Email >
</User>
.
.
.
<DBUSER>

从中可以看出,XML由三大部分组成,分别是声明、根节点和其它节点。其中xml文件的声明包括三方面的内容:Version、Standalone和Encoding。下面将详细列出常见tinyxml2的用法。

注意:以下示例代码针对本人下载使用的TinyXML2,官网的TinyXML2在不断的完善和更新当中,最新的TinyXML2和本人的示例代码可能会有出入。本人使用的TinyXML2是2015.9.23从官网下载的,已上传至CSDN下载,见:TinyXML2

3.1创建XML文件

示例代码:

//function:create a xml file
//param:xmlPath:xml文件路径
//return:0,成功,非0,失败
int createXML(const char* xmlPath)
{
const char* declaration ="<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>";
XMLDocument doc;
doc.Parse(declaration);//会覆盖xml所有内容 //添加申明可以使用如下两行
//XMLDeclaration* declaration=doc.NewDeclaration();
//doc.InsertFirstChild(declaration); XMLElement* root=doc.NewElement("DBUSER");
doc.InsertEndChild(root); return doc.SaveFile(xmlPath);
}

创建结果:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<DBUSER/>

3.2增加xml文件的节点

示例代码:

//用户类
class User
{
public:
User(){
gender=0;
}; User(const string& userName, const string& password, int gender, const string& mobile, const string& email){
this->userName=userName;
this->password=password;
this->gender=gender;
this->mobile=mobile;
this->email=email;
}; string userName;
string password;
int gender;
string mobile;
string email;
}; //function:insert XML node
//param:xmlPath:xml文件路径; user:用户对象
//return:0:成功; 非0:失败
int insertXMLNode(const char* xmlPath,const User& user)
{
XMLDocument doc;
int res=doc.LoadFile(xmlPath);
if(res!=0)
{
cout<<"load xml file failed"<<endl;
return res;
}
XMLElement* root=doc.RootElement(); XMLElement* userNode = doc.NewElement("User");
userNode->SetAttribute("Name",user.userName.c_str());
userNode->SetAttribute("Password ",user.password.c_str());
root->InsertEndChild(userNode); XMLElement* gender = doc.NewElement("Gender");
XMLText* genderText=doc.NewText(itoa(user.gender));
gender->InsertEndChild(genderText);
userNode->InsertEndChild(gender); XMLElement* mobile = doc.NewElement("Mobile");
mobile->InsertEndChild(doc.NewText(user.mobile.c_str()));
userNode->InsertEndChild(mobile); XMLElement* email = doc.NewElement("Email");
email->InsertEndChild(doc.NewText(user.email.c_str()));
userNode->InsertEndChild(email); return doc.SaveFile(xmlPath);
}

创建结果:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<DBUSER>
<User Name="lvlv" Password ="12346">
<Gender>1</Gender>
<Mobile>15813354926</Mobile>
<Email>1589276509@qq.com</Email>
</User>
</DBUSER>

3.3查询xml文件的指定节点

Xml文件中,一个用户节点存储一个用户的信息。因此,对用户信息的增删查改,即无论查询节点、删除节点、修改节点和增加节点,都需要获取需要操作的节点。那么先实现一个根据用户名获取节点指针的函数:

//function:根据用户名获取用户节点
//param:root:xml文件根节点;userName:用户名
//return:用户节点
XMLElement* queryUserNodeByName(XMLElement* root,const string& userName)
{ XMLElement* userNode=root->FirstChildElement("User");
while(userNode!=NULL)
{
if(userNode->Attribute("Name")==userName)
break;
userNode=userNode->NextSiblingElement();//下一个兄弟节点
}
return userNode;
}

在以上函数的基础上,获取用户信息的函数:

User* queryUserByName(const char* xmlPath,const string& userName)
{
XMLDocument doc;
if(doc.LoadFile(xmlPath)!=0)
{
cout<<"load xml file failed"<<endl;
return NULL;
}
XMLElement* root=doc.RootElement();
XMLElement* userNode=queryUserNodeByName(root,userName); if(userNode!=NULL) //searched successfully
{
User* user=new User();
user->userName=userName;
user->password=userNode->Attribute("Password");
XMLElement* genderNode=userNode->FirstChildElement("Gender");
user->gender=atoi(genderNode->GetText());
XMLElement* mobileNode=userNode->FirstChildElement("Mobile");
user->mobile=mobileNode->GetText();
XMLElement* emailNode=userNode->FirstChildElement("Email");
user->email=emailNode->GetText();
return user;
}
return NULL;
}

3.4修改xml文件的指定节点

//function:修改指定节点内容
//param:xmlPath:xml文件路径;user:用户对象
//return:bool
bool updateUser(const char* xmlPath,User* user)
{
XMLDocument doc;
if(doc.LoadFile(xmlPath)!=0)
{
cout<<"load xml file failed"<<endl;
return false;
}
XMLElement* root=doc.RootElement();
XMLElement* userNode=queryUserNodeByName(root,user->userName); if(userNode!=NULL)
{
if(user->password!=userNode->Attribute("Password"))
{
userNode->SetAttribute("Password",user->password.c_str()); //修改属性
}
XMLElement* genderNode=userNode->FirstChildElement("Gender");
if(user->gender!=atoi(genderNode->GetText()))
{
genderNode->SetText(itoa(user->gender).c_str()); //修改节点内容
}
XMLElement* mobileNode=userNode->FirstChildElement("Mobile");
if(user->mobile!=mobileNode->GetText())
{
mobileNode->SetText(user->mobile.c_str());
}
XMLElement* emailNode=userNode->FirstChildElement("Email");
if(user->email!=emailNode->GetText())
{
emailNode->SetText(user->email.c_str());
}
if(doc.SaveFile(xmlPath)==0)
return true;
}
return false;
}

验证代码:

int main(int argc,char* argv[])
{
//修改用户信息
User user("lvlv","00001111",0,"13995648666","1586666@qq.com");
if(updateUser("./user.xml",&user))
cout<<"update successfully"<<endl;
else
cout<<"update failed"<<endl;
return 0;
}

修改结果:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<DBUSER>
<User Name="lvlv" Password="00001111">
<Gender>0</Gender>
<Mobile>13995648666</Mobile>
<Email>1586666@qq.com</Email>
</User>
</DBUSER>

3.5删除xml文件的指定节点的信息

//function:删除指定节点内容
//param:xmlPath:xml文件路径;userName:用户名称
//return:bool
bool deleteUserByName(const char* xmlPath,const string& userName)
{
XMLDocument doc;
if(doc.LoadFile(xmlPath)!=0)
{
cout<<"load xml file failed"<<endl;
return false;
}
XMLElement* root=doc.RootElement();
//doc.DeleteNode(root);//删除xml所有节点
XMLElement* userNode=queryUserNodeByName(root,userName);
if(userNode!=NULL)
{
userNode->DeleteAttribute("Password");//删除属性
XMLElement* emailNode=userNode->FirstChildElement("Email");
userNode->DeleteChild(emailNode); //删除指定节点
//userNode->DeleteChildren();//删除节点的所有孩子节点
if(doc.SaveFile(xmlPath)==0)
return true;
}
return false;
}

验证代码:

int main(int argc,char* argv[])
{
//删除用户某些信息
if(deleteUserByName("./user.xml","lvlv"))
cout<<"delete successfully"<<endl;
else
cout<<"delete failed"<<endl;
return 0;
}

删除结果:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<DBUSER>
<User Name="lvlv">
<Gender>10</Gender>
<Mobile>13995648666</Mobile>
</User>
</DBUSER>

4.其它常见用例

4.1获取xml文件申明

//function:获取xml文件申明
//param:xmlPath:xml文件路径;strDecl:xml申明
//return:bool
bool getXMLDeclaration(const char* xmlPath,string& strDecl)
{
XMLDocument doc;
if(doc.LoadFile(xmlPath)!=0)
{
cout<<"load xml file failed"<<endl;
return false;
}
XMLNode* decl=doc.FirstChild();
if (NULL!=decl)
{
XMLDeclaration* declaration =decl->ToDeclaration();
if (NULL!=declaration)
{
strDecl = declaration->Value();
return true;
}
}
return false;
}

验证代码:

int main(int argc,char* argv[])
{
//获取xml文件申明
string strDecl;
if(getXMLDeclaration("./user.xml",strDecl))
{
cout<<"declaration:"<<strDecl<<endl;
}
return 0;
}

验证结果:

declaration:xml version="1.0" encoding="UTF-8" standalone="no"

4.2打印xml文件至标准输出

//function:将xml文件内容输出到标准输出
//param:xmlPath:xml文件路径
void print(const char* xmlPath)
{
XMLDocument doc;
if(doc.LoadFile("./user.xml")!=0)
{
cout<<"load xml file failed"<<endl;
return;
}
doc.Print();
}

4.3 xml文件内容输出至内存

XMLPrinter printer;
doc.Print( &printer );
// printer.CStr() has a const char* to the XML

4.4如何解析xml格式的字符串信息,不是文件中的

采用tinyXML中的TiXmlDocument类的Parse方法即可。例如:
const char * xmlString = "<?xml version=\"1.0\" standalone=no>\n<!– Our to do list data –>\n<ToDo>\n<Item priority=\"1\"> <bold>Toy store!</bold>\n</Item>\n<Item priority=\"2\"> Do bills</Item>\n</ToDo> ";
XMLDocument *doc = new XMLDocument();
doc->Parse(xmlString);
 
XMLElement * rootElement = doc->RootElement();
const char * rootName = rootElement->Value();

TinyXML2使用教程(转)的更多相关文章

  1. C++实现一个SOAP客户端

    目录 简介 实现客户端 准备xml文件 引入库文件 构建请求数据的xml 执行Http协议的POST方法 解析响应数据的xml 测试客户端 附件 简介 在C++中,一般使用gSOAP来实现客户端.服务 ...

  2. Angular2入门系列教程7-HTTP(一)-使用Angular2自带的http进行网络请求

    上一篇:Angular2入门系列教程6-路由(二)-使用多层级路由并在在路由中传递复杂参数 感觉这篇不是很好写,因为涉及到网络请求,如果采用真实的网络请求,这个例子大家拿到手估计还要自己写一个web ...

  3. Angular2入门系列教程6-路由(二)-使用多层级路由并在在路由中传递复杂参数

    上一篇:Angular2入门系列教程5-路由(一)-使用简单的路由并在在路由中传递参数 之前介绍了简单的路由以及传参,这篇文章我们将要学习复杂一些的路由以及传递其他附加参数.一个好的路由系统可以使我们 ...

  4. Angular2入门系列教程5-路由(一)-使用简单的路由并在在路由中传递参数

    上一篇:Angular2入门系列教程-服务 上一篇文章我们将Angular2的数据服务分离出来,学习了Angular2的依赖注入,这篇文章我们将要学习Angualr2的路由 为了编写样式方便,我们这篇 ...

  5. Angular2入门系列教程4-服务

    上一篇文章 Angular2入门系列教程-多个组件,主从关系 在编程中,我们通常会将数据提供单独分离出来,以免在编写程序的过程中反复复制粘贴数据请求的代码 Angular2中提供了依赖注入的概念,使得 ...

  6. Angular2入门系列教程1-使用Angular-cli搭建Angular2开发环境

    一直在学Angular2,百忙之中抽点时间来写个简单的教程. 2016年是前端飞速发展的一年,前端越来越形成了(web component)组件化的编程模式:以前Jquery通吃一切的田园时代一去不复 ...

  7. wepack+sass+vue 入门教程(三)

    十一.安装sass文件转换为css需要的相关依赖包 npm install --save-dev sass-loader style-loader css-loader loader的作用是辅助web ...

  8. wepack+sass+vue 入门教程(二)

    六.新建webpack配置文件 webpack.config.js 文件整体框架内容如下,后续会详细说明每个配置项的配置 webpack.config.js直接放在项目demo目录下 module.e ...

  9. wepack+sass+vue 入门教程(一)

    一.安装node.js node.js是基础,必须先安装.而且最新版的node.js,已经集成了npm. 下载地址 node安装,一路按默认即可. 二.全局安装webpack npm install ...

随机推荐

  1. Linux curl 详解

    Linux下载工具Curl也是Linux下不错的命令行下载工具,小巧.高速,唯一的缺点是不支持多线程下载.以下是他的安装和功能. 安装 $ tar zxvf curl-7.14.0.tar.gz $ ...

  2. VueX源码分析(2)

    VueX源码分析(2) 剩余内容 /module /plugins helpers.js store.js helpers要从底部开始分析比较好.也即先从辅助函数开始再分析那4个map函数mapSta ...

  3. MYSQL不能显示中文字,显示错误“ERROR 1366 (HY000): Incorrect string value: '\xE5\xBC\xA0\xE4\xB8\x89'”

    或者建表时带上编码utf8 CREATE TABLE `students`( `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY, `name` VARCHAR( ...

  4. 如何在 CentOS 7 上安装 Python 3

    当前最新的 CentOS 7.5 默认安装的是 Python 2.7.5,并且默认的官方 yum 源中不提供 Python 3 的安装包.这里主要介绍两种在 CentOS 7 中安装 Python 3 ...

  5. Survey lists 10 most innovative cities

    From China Daily Beijing and Shanghai are among the 10 most innovative cities in the world, based on ...

  6. German Collegiate Programming Contest 2015 计蒜课

    // Change of Scenery 1 #include <iostream> #include <cstdio> #include <algorithm> ...

  7. poj 1017 装箱子问题 贪心算法

    题意:有1*1到6*6的的东西,需要用6*6的箱子将它们装起来.问:至少需要多少个6*6箱子 思路: 一个瓶子怎么装东西最多?先装石头,在装沙子,然后装水. 同样放在本题就是先装6*6然后5*5... ...

  8. Hadoop4.2HDFS测试报告之四

    第二组:文件存储读过程记录 测试系统组成 存储类型 测试程序或命令 测试文件大小(Mb) 文件个数(个) 客户端并发数(个) 读速率 (M/s) NameNode:1 DataNode:1 本地存储 ...

  9. 光学字符识别OCR-4

    经过第一部分,我们已经较好地提取了图像的文本特征,下面进行文字定位. 主要过程分两步:         1.邻近搜索,目的是圈出单行文字:         2.文本切割,目的是将单行文本切割为单字. ...

  10. No identifier specified for entity: XXXX 错误

    在运行项目的时候报了下面的错误: by: org.hibernate.AnnotationException: No identifier specified for entity: com.exam ...