【转】TinyXML2 入门教程

转自:TinyXML2 入门教程_恋喵大鲤鱼的博客-CSDN博客_tinyxml2中文指南

代码编译运行环境: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用户名Vchar3-20YY
Password密码Char32YN
Gender性别Int1NN
Mobile电话Char11NN
Email电子邮箱Varchar1-50NN

对应 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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/435554.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

解决“A problem has been encountered while loading the setup components. Canceling setup.”的问题...

近来因为需要开发C的程序&#xff0c;所以要在Visual Studio 2008中添加C的开发组件&#xff0c;但是在添加组件的时候&#xff0c;弹出“A problem has been encountered while loading the setup components. Canceling setup.”的提示。无奈之下&#xff0c;只好卸载&#x…

【转】linux 查看动态库和可执行程序依赖库

转自&#xff1a;linux 查看动态库和可执行程序依赖库_帅的没朋友~的博客-CSDN博客_linux 查看动态库 目录 一:objdump二:readelf三:ldd四:进程是否依赖指定一:objdump # 查看依赖的库 objdump -x xxx.so | grep NEEDED# 查看可执行程序依赖的库 objdump -x ./testTime | gr…

WinCE下的GPIO中断的处理

在我所负责的音频驱动部分代码中,采用了PXA270的GPIO34来检测Headphone的插入与拔出.原驱动部分有个BUG,即当耳机插入以后,耳机和喇叭同时在响,很明显没有对耳机插入事件做出响应.所以我开始采用了检测GPIO信号拉高或者拉低和检测耳机的插入事件,但是这样做有个问题,就是会有延…

xvhfeng的工作回忆总结(第二年)阅读手记

xvhfeng 工作回忆总结&#xff08;第二年&#xff09; 上接工作第一年回忆总结,时间来到了工作第二年&#xff0c;我在PM的帮助下拿到了令自己满意的工资&#xff0c;又开始加入公司正常的工作。 上文说到有一个外省市&#xff08;以下称为A市&#xff09;的项目在做&#xff…

【转】详解JS的四种异步解决方案:回调函数、Promise、Generator、async/await

转自&#xff1a;详解JS的四种异步解决方案&#xff1a;回调函数、Promise、Generator、async/await 同步&异步的概念 在讲这四种异步方案之前&#xff0c;我们先来明确一下同步和异步的概念&#xff1a; 所谓同步(synchronization)&#xff0c;简单来说&#xff0c;就是…

S3C2440中断解析和基于WINCE操作系统的中断分析(整理于网络,用于按键中断使用)

在调试CAN总线的时候&#xff0c;遇到了操作系统的中断&#xff0c;为了彻底的弄清楚中断是怎么回事&#xff1f;我先从底层的中断开始研究&#xff0c;在这里我们只讨论外部中断&#xff0c;下面就结合S3C2440TEST测试程序来分析一下中断是怎么执行的&#xff1a;我们研究的是…

修改 MrBayes 3.2 源码解决不能恢复断点的问题

当数据量较大时&#xff0c;用MrBayes进行计算通常是旷日持久的事情&#xff0c;几天甚至几个月。中间如果断电死机什么的发生就很令人发狂了。于是 MrBayes 3.2 svn 版增加了一个断点保存的功能&#xff0c;死机后可以从保存的断点处继续计算。只要在mcmc命令中加入checkfreqn…

【转】ubuntu下为APT设置代理

转自&#xff1a;https://blog.csdn.net/lwbeyond/article/details/8431927 Ubuntu下为APT设置代理一.最简单的方法 图形界面方法&#xff1a;新立得软件包管理器-->设置-->首选项-->网络。 进行设置代理就可以了。二.编辑命令 方法1&#xff1a;验证通过 如果您 希望…

wince6.0 s5pv210 中断

1. 在smdkv210\src\oal\oallib\ksarm.h头文件里可以看到wince的中断定义。 设备中断的起始编号即wince预定义的设备中断ID的基值 SYSINTR_DEVICES EQU 8 一共支持64个设备中断 SYSINTR_MAX_DEVICES EQU 64 可用的设备…

Regular Expression

Reference: 正则表达式三十分钟入门&#xff1a; http://deerchao.net/tutorials/regex/regex.htm 在线测试工具&#xff1a; regexlib&#xff08;http://regexlib.com/default.aspx&#xff09; 吐血推荐&#xff0c;比较狠的一个工具&#xff1a; Expresso &…

【转】vsftp配置实例-虚拟用户锁定目录

转自&#xff1a; vsftp配置实例-虚拟用户锁定目录_jasonyang69的博客-CSDN博客_vsftpd锁定用户目录 快速解决 vsftpd nologin 虚拟用户 拒绝访问 无法登录_小飞飞飞鱼的博客-CSDN博客_vsftpd 拒绝访问 一、实验步骤 0、启用 nologin shell #vim /etc/shells /bin/sh /bi…

顺丰快递,果然不一般!

2010-06-03 18:27:03快件到达北京集散点 2010-06-03 19:15:41快件离开北京集散点 发往北京集散中心 2010-06-03 21:05:34快件到达北京集散中心 2010-06-03 21:06:12快件离开北京集散中心 发往深圳集散中心 2010-06-04 02:56:29快件到达深圳集散中心 2010-06-04 02:57:04快件离开…

windowsCE异常和中断服务程序初探(-)

1。中断/异常相量的装入和执行方式。 中断和异常都是异步发生的事件&#xff0c;当该事件发生&#xff0c;系统将停止目前正在执行的代码转而执行事件响应的服务程序。而事件服务程序的入口点就是中断/异常向量所在的位置。arm的中断向量可以是0x0开始的低地址向…

windowsCE异常和中断服务程序初探(=)

继续上次的内容&#xff0c;在上次的分析中我们已经对SWI,FIQ,IRQ的流程有了一个大概的认识&#xff0c;下面继续对DataAbort和PrefetchAbort以及公共分发程序CommonHandler进行一下认识&#xff0c;完整异常处理的流程。 2-4 DataAbort服务程序 由数据异常触发&…

【转】Linux中tty、pty和pts概念及区别

转自&#xff1a;Linux中tty、pty和pts概念及区别 - 知乎 基本概念 ①tty(终端设备的统称): tty一词源于Teletypes&#xff0c;或者teletypewriters&#xff0c;原来指的是电传打字机&#xff0c;是一种通过串行线连接键盘和打印机进行发送、阅读信息的设备&#xff0c;后来…

Microsoft Jet SQL 参考在线手册

http://www.weste.net/book/sql/转载于:https://www.cnblogs.com/cwfsoft/archive/2010/06/19/1760961.html

Windows CE下驱动程序开发基础

我想即使读者看过微软的关于驱动开发的培训教材和CE帮助文档中的驱动部分&#xff0c;头脑中仍然一片茫然。要想真正了解驱动程序必须结合一些驱动程序源码&#xff0c;在此我以串口驱动程序&#xff08;COM16550&#xff09;中初始化过程为线索简单讲一讲驱动开发的基础知识。…

【转】高端球管使用了哪些高科技?

转自&#xff1a;高端球管使用了哪些高科技&#xff1f; 本文来源&#xff1a;第三方维修平台 本文作者&#xff1a;RepairCT 随着人类发现X射线&#xff0c;这项技术不断应用到医学领域&#xff0c;比如X光机、DR、CT、乳腺钼靶等医疗设备&#xff0c;它们的主要核心均是利用…

关于代码组织的一些看法(上)

今天看了一个篇关于架构的文章&#xff0c;略有所感&#xff0c;记录一下。 软件的架构基本是从一个原始需求出发&#xff0c;逐步构建可维护、更灵活的开发框架的过程&#xff0c;在这个构建过程中可能会逐渐的增加代码的复杂度来满足灵活性的要求&#xff0c;从这个层面来讲&…

CE下基于Zylonite硬件平台的SD卡驱动开发

摘要&#xff1a;本文结合实际项目&#xff08;一款以WINCE为操作系统内核的GSM/PHS双模智能手机&#xff09;对嵌入式系统Windows CE5.0的底层驱动&#xff08;SD卡&#xff09;的架构进行了分析和研究&#xff0c;以MARVELL公司提供的基于INTEL Zylonite硬件平台的BSP为基础&…