TinyXML2使用教程(转)
原文转自 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 |
电子邮箱 | 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使用教程(转)的更多相关文章
- C++实现一个SOAP客户端
目录 简介 实现客户端 准备xml文件 引入库文件 构建请求数据的xml 执行Http协议的POST方法 解析响应数据的xml 测试客户端 附件 简介 在C++中,一般使用gSOAP来实现客户端.服务 ...
- Angular2入门系列教程7-HTTP(一)-使用Angular2自带的http进行网络请求
上一篇:Angular2入门系列教程6-路由(二)-使用多层级路由并在在路由中传递复杂参数 感觉这篇不是很好写,因为涉及到网络请求,如果采用真实的网络请求,这个例子大家拿到手估计还要自己写一个web ...
- Angular2入门系列教程6-路由(二)-使用多层级路由并在在路由中传递复杂参数
上一篇:Angular2入门系列教程5-路由(一)-使用简单的路由并在在路由中传递参数 之前介绍了简单的路由以及传参,这篇文章我们将要学习复杂一些的路由以及传递其他附加参数.一个好的路由系统可以使我们 ...
- Angular2入门系列教程5-路由(一)-使用简单的路由并在在路由中传递参数
上一篇:Angular2入门系列教程-服务 上一篇文章我们将Angular2的数据服务分离出来,学习了Angular2的依赖注入,这篇文章我们将要学习Angualr2的路由 为了编写样式方便,我们这篇 ...
- Angular2入门系列教程4-服务
上一篇文章 Angular2入门系列教程-多个组件,主从关系 在编程中,我们通常会将数据提供单独分离出来,以免在编写程序的过程中反复复制粘贴数据请求的代码 Angular2中提供了依赖注入的概念,使得 ...
- Angular2入门系列教程1-使用Angular-cli搭建Angular2开发环境
一直在学Angular2,百忙之中抽点时间来写个简单的教程. 2016年是前端飞速发展的一年,前端越来越形成了(web component)组件化的编程模式:以前Jquery通吃一切的田园时代一去不复 ...
- wepack+sass+vue 入门教程(三)
十一.安装sass文件转换为css需要的相关依赖包 npm install --save-dev sass-loader style-loader css-loader loader的作用是辅助web ...
- wepack+sass+vue 入门教程(二)
六.新建webpack配置文件 webpack.config.js 文件整体框架内容如下,后续会详细说明每个配置项的配置 webpack.config.js直接放在项目demo目录下 module.e ...
- wepack+sass+vue 入门教程(一)
一.安装node.js node.js是基础,必须先安装.而且最新版的node.js,已经集成了npm. 下载地址 node安装,一路按默认即可. 二.全局安装webpack npm install ...
随机推荐
- Linux curl 详解
Linux下载工具Curl也是Linux下不错的命令行下载工具,小巧.高速,唯一的缺点是不支持多线程下载.以下是他的安装和功能. 安装 $ tar zxvf curl-7.14.0.tar.gz $ ...
- VueX源码分析(2)
VueX源码分析(2) 剩余内容 /module /plugins helpers.js store.js helpers要从底部开始分析比较好.也即先从辅助函数开始再分析那4个map函数mapSta ...
- 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( ...
- 如何在 CentOS 7 上安装 Python 3
当前最新的 CentOS 7.5 默认安装的是 Python 2.7.5,并且默认的官方 yum 源中不提供 Python 3 的安装包.这里主要介绍两种在 CentOS 7 中安装 Python 3 ...
- Survey lists 10 most innovative cities
From China Daily Beijing and Shanghai are among the 10 most innovative cities in the world, based on ...
- German Collegiate Programming Contest 2015 计蒜课
// Change of Scenery 1 #include <iostream> #include <cstdio> #include <algorithm> ...
- poj 1017 装箱子问题 贪心算法
题意:有1*1到6*6的的东西,需要用6*6的箱子将它们装起来.问:至少需要多少个6*6箱子 思路: 一个瓶子怎么装东西最多?先装石头,在装沙子,然后装水. 同样放在本题就是先装6*6然后5*5... ...
- Hadoop4.2HDFS测试报告之四
第二组:文件存储读过程记录 测试系统组成 存储类型 测试程序或命令 测试文件大小(Mb) 文件个数(个) 客户端并发数(个) 读速率 (M/s) NameNode:1 DataNode:1 本地存储 ...
- 光学字符识别OCR-4
经过第一部分,我们已经较好地提取了图像的文本特征,下面进行文字定位. 主要过程分两步: 1.邻近搜索,目的是圈出单行文字: 2.文本切割,目的是将单行文本切割为单字. ...
- No identifier specified for entity: XXXX 错误
在运行项目的时候报了下面的错误: by: org.hibernate.AnnotationException: No identifier specified for entity: com.exam ...