C++|读写xml文件开源库tingxml2的使用

  • Post author:
  • Post category:其他

参考:
TinyXML使用方法[通俗易懂]
https://cloud.tencent.com/developer/article/2037579
TinyXML2 入门教程(这篇写很好,本文侧重讲解使用不过做多介绍)
不了解xml的建议自行查阅,在此不赘述。
开源库github链接:https://github.com/leethomason/tinyxml2
使用git直接拉取还是下载zip包都可
在这里插入图片描述
tinyxml2相比tinyxml进行了简化,只需要一个.h和一个.cpp即可使用,我下载的zip,解压完成后将tinyxml2.h和tinyxml2.cpp复制进自己的项目中即可。
在这里插入图片描述
在使用的地方包含头文件和命名空间
在这里插入图片描述
创建一个空的xml文件:
在这里插入图片描述
插入节点:
在这里插入图片描述
查询节点:
在这里插入图片描述
修改节点内容:
在这里插入图片描述
删除指定节点,获取xml文件申明:
在这里插入图片描述
代码如下:

// TinyXmlUsing.cpp : Defines the entry point for the console application.
//

#include "tinyxml2.h"
#include <iostream>
#include <stdio.h>
#include <string>
using namespace tinyxml2;
using namespace std;

//用户类
struct 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:根据用户名获取用户节点
//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;
}

// 结合queryUserNodeByName使用返回节点所有信息
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;
}

//function:修改指定节点内容 也依赖queryUserNodeByName函数
//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())) {
			char * gender_char = new char[8];
			sprintf(gender_char, "%d", user->gender);
			genderNode->SetText(gender_char);   //修改节点内容
		}
		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;
}

//function:insert XML node 增加XML文件的节点 根据需求灵活修改
//param:xmlPath xml 文件路径; user 用户对象
//return:0 成功; 非 0 失败
int insertXMLNode(const char* xmlPath, const User& user) {
	XMLDocument doc;
	int res = doc.LoadFile(xmlPath);	// 加载xml文件
	if (res != 0)
	{
		//cout << "load xml file failed" << endl;
		cout << "加载xml文件失败!" << endl;
		return res;
	}

	XMLElement* root = doc.RootElement();	// 获取根节点

	XMLElement* userNode = doc.NewElement("User");	// 创建user节点
	userNode->SetAttribute("Name", user.userName.c_str());	// user节点下添加属性值
	userNode->SetAttribute("Password", user.password.c_str()); // user节点下添加属性值
	root->InsertEndChild(userNode);	// 根节点下插入user节点

	XMLElement* gender = doc.NewElement("Gender"); // 创建Gender节点
	char * gender_char = new char[8];
	// 将int转为char* 写入节点
	sprintf(gender_char, "%d" , user.gender);
	/* itoa的使用说明:
	int 转为char* 需要包含头文件<cstdlib> 第三个参数用于将数字转换成不同的进制
	还需要添加在预处理器添加_CRT_NONSTDC_NO_DEPRECATE _CRT_SECURE_NO_WARNINGS 
	故不在此使用 感兴趣请自行查阅
	*/
	//itoa(user.gender, gender_char,10);
	XMLText* genderText = doc.NewText(gender_char); 
	gender->InsertEndChild(genderText);
	userNode->InsertEndChild(gender); // user节点下插入Gender节点

	XMLElement* mobile = doc.NewElement("Mobile"); // 创建Mobile节点
	mobile->InsertEndChild(doc.NewText(user.mobile.c_str()));
	userNode->InsertEndChild(mobile); // user节点下插入Mobile节点

	XMLElement* email = doc.NewElement("Email"); // 创建Email节点
	email->InsertEndChild(doc.NewText(user.email.c_str()));
	userNode->InsertEndChild(email); // user节点下插入Email节点

	return doc.SaveFile(xmlPath);
}

//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;
}

//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;
}


//function:create a xml file 创建一个xml文件
//param:xmlPath:xml文件路径
//return:0,成功;非0,失败
int createXML(const char* xmlPath) {
	const char* declaration = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>";
	XMLDocument doc;
	doc.Parse(declaration);//会覆盖xml所有内容

	//修改or添加申明可以使用如下两行XMLDeclaration 相当于修改第一层节点
	//!切记不要和Parse一起使用 否则会添加两个申明
	//XMLDeclaration* new_dec = doc.NewDeclaration("xml version=\"1.0\" encoding=\"UTF-8\" addshenming = \"shenming\" ");
	//doc.InsertFirstChild(new_dec);
	
	XMLElement* root = doc.NewElement("DBUSER");	// 创建根节点
	doc.InsertEndChild(root);

	return doc.SaveFile(xmlPath);
}


int main()
{
	// 创建一个空的xml文件
	int flag = createXML("qtreetestxml.xml");
	//std::cout << flag;

	User oneUser;
	oneUser.userName = "张三";
	oneUser.password = "1";
	oneUser.gender = 0;
	oneUser.mobile = "110";
	oneUser.email = "1@qq.com";
	// 插入节点
	insertXMLNode("qtreetestxml.xml",oneUser);

	// 查询节点
	User* query_data = queryUserByName("qtreetestxml.xml", "张三");
	cout << query_data->userName <<":"<< query_data->mobile<<endl;

	// 修改节点内容 根据用户名字进行查找修改的所以名字得一样 可根据需求自由修改
	User oneUser1;
	oneUser1.userName = "张三";
	oneUser1.password = "7";
	oneUser1.gender = 1;
	oneUser1.mobile = "119";
	oneUser1.email = "1177@qq.com";
	bool updata_flag = updateUser("qtreetestxml.xml", &oneUser1);

	// 删除指定节点
	bool del_flage = deleteUserByName("qtreetestxml.xml", "张三");

	// 获取xml文件申明
	string strDecl;
	getXMLDeclaration("qtreetestxml.xml", strDecl);
	cout << strDecl << endl;

	system("pause");
    return 0;
}



版权声明:本文为weixin_42964413原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。