基于tinyXml2库封装的解析xml的通用类

来源:互联网 发布:数据库恢复模式设置 编辑:程序博客网 时间:2024/06/05 15:06

原博客地址:基于tinyXml2库封装的解析xml的通用类

目录(?)[-]

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

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


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用户名Vchar3-20YYPassword密码Char32YNGender性别Int1NNMobile电话Char11NNEmail电子邮箱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>...<DBUSER>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

从中可以看出,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);}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

创建结果:

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

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);}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57

创建结果:

<?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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

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;}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

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

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;}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

3.4修改xml文件的指定节点

//function:修改指定节点内容//param:xmlPath:xml文件路径;user:用户对象//return:boolbool 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;}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

验证代码:

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;}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

修改结果:

<?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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

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

//function:删除指定节点内容//param:xmlPath:xml文件路径;userName:用户名称//return:boolbool 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;}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

验证代码:

int main(int argc,char* argv[]){    //删除用户某些信息    if(deleteUserByName("./user.xml","lvlv"))        cout<<"delete successfully"<<endl;    else        cout<<"delete failed"<<endl;    return 0;}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

删除结果:

<?xml version="1.0" encoding="UTF-8" standalone="no"?><DBUSER>    <User Name="lvlv">        <Gender>10</Gender>        <Mobile>13995648666</Mobile></User></DBUSER>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

4.其它常见用例

4.1获取xml文件申明

//function:获取xml文件申明//param:xmlPath:xml文件路径;strDecl:xml申明//return:boolbool 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;}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

验证代码:

int main(int argc,char* argv[]){    //获取xml文件申明    string strDecl;    if(getXMLDeclaration("./user.xml",strDecl))    {        cout<<"declaration:"<<strDecl<<endl;    }    return 0;}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

验证结果:

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

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();}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

4.3 xml文件内容输出至内存

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

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


参考文献

[1]TinyXML2官方示例代码与文档

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 小米2a开不了机怎么办 红米4x屏幕失灵怎么办 红米4x外屏坏了怎么办 honor手机开不了机怎么办 honor黑屏开不了机怎么办 红米2开机停在mi怎么办 红米手机无法开机怎么办 小米手机帐号密码忘了怎么办 小米手机忘记小米账号密码怎么办 小米4账号密码忘了怎么办 小米2a触屏失灵怎么办 红米note5拍照不清晰怎么办 红米手机太卡怎么办 红米3x忘记密码怎么办 红米手机太卡了怎么办 红米手机太卡怎么办? 红米3老是死机怎么办 红米3s经常死机怎么办 红米4a进水了怎么办 魅族耳机声音小怎么办 魅蓝note6声音小怎么办 魅蓝3s锁定怎么办 红米1密码忘了怎么办 小米手环升级失败怎么办 红米4忘记密码怎么办 红米1代忘记密码怎么办 红米3s忘记密码怎么办 小米3卡槽卡住了怎么办 红米4手机信号不好怎么办 红米note3信号差怎么办 红米note3没信号怎么办 红米3运行慢怎么办 红米手机运行慢怎么办 红米手机忘记解锁图案怎么办 小米手机解锁图案忘了怎么办 红米2内屏坏了怎么办 红米密码忘记了怎么办 红米pro玩王者卡怎么办 红米note4不支持计步怎么办 红米pro玩游戏卡怎么办 红米手机费电快怎么办