代码编译运行环境:Linux 64bits + Debug + g++ -m64(-m 表示生成 64bits 的程序)

文章目录

  • 1.TinyXML2 概述
  • 2. TinyXML1 与 TinyXML2 对比
  • 3. TinyXML2 用法用例
    • 3.1 创建 XML 文件
    • 3.2 增加 XML 文件的节点
    • 3.3 查询 XML 文件的指定节点
    • 3.4 修改 XML 文件的指定节点
    • 3.5 删除 XML 文件的指定节点内容
  • 4.其它常见用例
    • 4.1 获取 XML 文件申明
    • 4.2 打印 XML 文件至标准输出
    • 4.3 XML 文件内容输出至内存
  • 参考文献

1.TinyXML2 概述

TinyXML2 是 simple、small、efficient 的开源 C++ XML 文件解析库,可以很方便地应用到现有的项目中。

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

2. TinyXML1 与 TinyXML2 对比

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

TinyXML1 开发已经停止,所有的开发都转移到了 TinyXML2。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><!-- This is a comment -->
<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 ="123456"><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;elsecout<<"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;elsecout<<"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

其它实例待以后用到再补充。


参考文献

TinyXML2 官网
leethomason github.TinyXML2

TinyXML2 入门教程相关推荐

  1. 【转】TinyXML2 入门教程

    转自:TinyXML2 入门教程_恋喵大鲤鱼的博客-CSDN博客_tinyxml2中文指南 代码编译运行环境:Linux 64bits + Debug + g++ -m64(-m 表示生成 64bit ...

  2. TinyXML2使用教程

    TinyXML2使用教程 原文转自 http://blog.csdn.net/K346K346/article/details/48750417 1.TinyXML2概述 TinyXML2是simpl ...

  3. Kafka入门教程与详解

    1 Kafka入门教程 1.1 消息队列(Message Queue) Message Queue消息传送系统提供传送服务.消息传送依赖于大量支持组件,这些组件负责处理连接服务.消息的路由和传送.持久 ...

  4. 【CV】Pytorch一小时入门教程-代码详解

    目录 一.关键部分代码分解 1.定义网络 2.损失函数(代价函数) 3.更新权值 二.训练完整的分类器 1.数据处理 2. 训练模型(代码详解) CPU训练 GPU训练 CPU版本与GPU版本代码区别 ...

  5. python tornado教程_Tornado 简单入门教程(零)——准备工作

    前言: 这两天在学着用Python + Tornado +MongoDB来做Web开发(哈哈哈这个词好高端).学的过程中查阅了无数资料,也收获了一些经验,所以希望总结出一份简易入门教程供初学者参考.完 ...

  6. python向量计算库教程_NumPy库入门教程:基础知识总结

    原标题:NumPy库入门教程:基础知识总结 视学算法 | 作者 知乎专栏 | 来源 numpy可以说是 Python运用于人工智能和科学计算的一个重要基础,近段时间恰好学习了numpy,pandas, ...

  7. mysql query browswer_MySQL数据库新特性之存储过程入门教程

    MySQL数据库新特性之存储过程入门教程 在MySQL 5中,终于引入了存储过程这一新特性,这将大大增强MYSQL的数据库处理能力.在本文中将指导读者快速掌握MySQL 5的存储过程的基本知识,带领用 ...

  8. python tensorflow教程_TensorFlow入门教程TensorFlow 基本使用T

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 TensorFlow入门教程 TensorFlow 基本使用 TensorFlow官方中文教程 TensorFlow 的特点: 使用图 (graph) 来 ...

  9. air调用java,AIR2.0入门教程:与Java应用交互

    在之前的一篇文章中,我介绍了如何使用AIR2.0新增的NativeProcess类与本地进程进行交互和通讯,在那个例子里面我们使用了C++ 的代码,实际上只要是基于命令行的标准输入输出,AIR2.0的 ...

最新文章

  1. 通过yum安装配置lamp
  2. SQL SERVER 性能优化四: 创建分区表
  3. 解决 Android 中出现依赖多个版本支持库的问题
  4. android compile使用方法,自己创建一个android studio在线依赖compile
  5. 攀钢告诉你:钢铁是怎样用AI炼成的?
  6. php从网页获得数据,php根据URL获得网页内容
  7. 对象指针与this指针
  8. 一大波DeepMind专利来袭,AI圈瑟瑟发抖:连RNN都是你家的?
  9. 中缀表达式转后缀表达式
  10. python选择哪个版本-Python学习,要选哪个版本?
  11. 渗透测试常用工具-端口扫描
  12. 踩坑指南!anaconda新建环境出错解决!又是猛男落泪的一天!
  13. 摄像头自建html直播,H5代码实现调用本地摄像头实现实时视频以及拍照功能
  14. 最简单的改变字体大小代码
  15. Pycharm下同一目录的py文件不能相互调用的原因分析
  16. php开发自己的composer包
  17. 研究生复试发邮件注意事项
  18. KendoUI组件基础(上)
  19. 服务器最高安全防御策略选择与差异
  20. 南土所褚海燕组综述微生物组学的技术和方法及其应用

热门文章

  1. 《应用软件安全编程指南》国标发布 奇安信代码卫士已全面支持
  2. Mozilla 修复已遭利用的两个火狐浏览器 0day
  3. url编码解码的三种方式
  4. 聊聊storm的CheckpointSpout
  5. 【转】HttpCompress
  6. 编译在arm版本的Valgrind-转
  7. 使用gdb调试运行时的程序小技巧 -转
  8. L3-025 那就别担心了 (30 分)-PAT 团体程序设计天梯赛 GPLT
  9. LeetCode 228. Summary Ranges
  10. 【操作系统】进程的异步性