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

news2024/9/22 19:37:40

参考:
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;
}


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

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

相关文章

Python中的列表、元组、字典

​​​​​​​列表是一种让程序员在代码中批量表示/保存数据的方式&#xff0c;元组和列表相比&#xff0c;是非常相似的&#xff0c;只是列表中放哪些元素可以修改调整&#xff0c;元组中放的元素是创建元组的时候就设定好的&#xff0c;不能修改调整。 列表和元组类似于其他…

SpringBoot 2-9-2 ServletAPI

使用27个解析器中 ServletRequestMethodArgumentResolver Step1 页面请求 注意RestController ResponseBody Controller Controller 将当前修饰的类注入SpringBoot IOC容器&#xff0c;使得从该类启动后就被实例化 ResponseBody 表示它会以Json字符串的形式返回给客户…

【日常系列】LeetCode《27·动态规划2》

数据规模->时间复杂度 <10^4 &#x1f62e;(n^2) <10^7:o(nlogn) <10^8:o(n) 10^8<:o(logn),o(1) 内容 1&#xff09;爬楼梯、打家劫舍问题 2&#xff09;0-1&#xff0c;多重&#xff0c;完全&#xff0c;二维被动背包问题 lc 70【剑指 10 - 2】【top100】&…

Maven仓库集成与使用

1.概念:Maven主要服务于基于java平台的项目构建(编译、测试、生成文档、打包、部署等)&#xff0c;依赖管理和项目信息管理。 2.四大特性: 2.1:依赖管理系统(jar包管理, jar 升级时修改配置文件即可) 依赖(Coordination):由groupId、artifactId、version组成 …

PHP MySQL 预处理语句

预处理语句对于防止 MySQL 注入是非常有用的。 预处理语句及绑定参数 预处理语句用于执行多个相同的 SQL 语句&#xff0c;并且执行效率更高。 预处理语句的工作原理如下&#xff1a; 预处理&#xff1a;创建 SQL 语句模板并发送到数据库。预留的值使用参数 "?" 标…

Python 实现 JSON 解析器

Json 解析 文章目录Json 解析Json 的组成对象结构数组结构词法分析逻辑性解析解析对象类型解析数组类型完整代码小结Json 的组成 JSON结构共有2种 对象结构数组结构 一个合法的JSON字符串可以包含这几种元素: 特殊符号,如"{" “}“表示一个JSON Object&#xff0…

将DataFrame进行转置的DataFrame.transpose()方法

【小白从小学Python、C、Java】 【计算机等级考试500强双证书】 【Python-数据分析】 将DataFrame进行转置 DataFrame.transpose() 选择题 关于以下python代码说法错误的一项是? import pandas as pd dfpd.DataFrame({a:[a1,a2],b:[b1,b2]}) print("【显示】df:\n"…

高德地图红绿灯读秒是怎么实现的?(一)

关于这个读秒实现功能众说风云&#xff0c;目前有两种说法&#xff0c;一种说是靠大数据分析&#xff0c;一种说是靠交管部门数据。 我们先看一下官方的回应&#xff1a;可以自行去抖音看官方号的解释。 以下为原答&#xff1a; 有人说是接入了地方交管数据&#xff0c;其实政策…

2022年度 FinClip 扩展 SDK 推荐!

2022年&#xff0c;FinClip 团队进行了24个产品迭代&#xff0c;为了丰富FinClip 的平台能力&#xff0c;除了核心SDK之外&#xff0c;我们还为开发者们提供了扩展SDK&#xff0c;扩展SDK是一个依赖核心SDK的库&#xff0c;里面提供了核心SDK中所没有的各种小程序API。 官方希…

arduino和物联网云端平台系列---物模型之事件

事件&#xff0c;先下个简单的定义就是发生了什么事件 系列文章都是已经完成了基本的库安装和使用为前提 物模型之事件 基本的添加步骤不描述了&#xff0c;设置一个测试用例 事件我已经设定好了&#xff0c;输出参数代表的是在云端得到的输出&#xff0c;需要我们在设备进行…

【程序环境和预处理】C语言

前言&#xff1a; 到此节便是我们C语言学习的终章了&#xff0c;对C语言的学习便告一段落了&#xff0c;到学完这一章节我们便要进入下一个主题的学习了。 目录1. 程序的翻译环境和执行环境2. 详解编译链接2.1 翻译环境2.2 编译本身也分为几个阶段2.3 运行环境3. 预处理详解3.1…

ESP32设备驱动-L3GD20三轴角速率传感器驱动

L3GD20三轴角速率传感器驱动 1、L3GD20介绍 L3GD20 是一款低功耗三轴角速率传感器。 它包括一个传感元件和一个 I2C 接口,能够通过数字接口 (I2C/SPI) 向外部世界提供测量的角速率。传感元件采用意法半导体开发的专用微加工工艺制造,用于在硅晶片上生产惯性传感器和执行器。…

高通Qualcomm处理器的手机或设备进EDL 9008模式的办法

适用于变砖的设备 由于我们有很多基于 Qualcomm 的设备&#xff0c;其中一些设备可能会古怪地猜测如何进入 EDL 模式&#xff0c;或者如何正确进入。 例如&#xff0c;对于 Alcatel&#xff0c;您必须先按住两个音量键&#xff0c;然后再按住其中一个&#xff0c;对于 CAT B35…

DocPrompt代码实现细节

数据预处理阶段 PaddleOCR PP-Structure&#xff1a;这个库其实是用于版面分析的一个开源库&#xff0c;参见&#xff1a;github: Layout-Parser/layout-parserhttps://github.com/Layout-Parser/layout-parser 代码推理阶段 Paddle-Inferencehttps://paddle-inference.readt…

[JavaEE]定时器

专栏简介: JavaEE从入门到进阶 题目来源: leetcode,牛客,剑指offer. 创作目标: 记录学习JavaEE学习历程 希望在提升自己的同时,帮助他人,,与大家一起共同进步,互相成长. 学历代表过去,能力代表现在,学习能力代表未来! 目录: 1.定时器的概念 2.标准库中的定时器 3.实现定时…

团灭LeetCode跳跃游戏(相关话题:贪心,BFS)

目录 LeetCode55跳跃游戏 LeetCode45. 跳跃游戏 II LeetCode1306. 跳跃游戏 III LeetCode1345. 跳跃游戏 IV LeetCode55跳跃游戏 给定一个非负整数数组 nums &#xff0c;你最初位于数组的 第一个下标 。 数组中的每个元素代表你在该位置可以跳跃的最大长度。 判断你是否…

win32com操作word 第三集:Range精讲(一)

本课程《win32com操作word API精讲&项目实战》&#xff0c;本公众号以文字分享为主&#xff0c;B站与视频号则发布视频分享&#xff0c;ID均为&#xff1a;一灯编程 本集开始&#xff0c;将会深入Document接口。打开或创建一个文档都会产生一个Document对象&#xff0c;它代…

十大排序(Java版本)

排序分为比较排序和非比较排序两种&#xff0c;常见的排序为比较排序&#xff0c;共有七类&#xff1a;直接插入排序、希尔排序、选择排序、冒泡排序、堆排序、快速排序以及归并排序。另有三种非基于比较类的排序&#xff1a;计数排序、基数排序和桶排序。基于比较的排序直接插…

TreeMap和TreeSet的介绍

目录 1、认识 TreeMap 和 TreeSet 2、TreeMap 的主要成员变量 3、TreeMap 的主要构造方法 4、TreeMap 和 TreeSet 的元素必须可比较 5、TreeMap 和 TreeSet 关于 key 有序 6、TreeMap 和 TreeSet 的关系 7、总结 1、认识 TreeMap 和 TreeSet TreeMap 和 TreeSet 是Ja…

探索SpringMVC-组件之ViewResolver

前言 ViewResolver也就是视图解析器&#xff0c;他将是我们《探索SpringMVC》系列要介绍的最后一个常用的组件。其他组件&#xff1a;MultipartResolver、LocaleResolver、ThemeResolver、RequestToViewNameTranslator、FlashMapManager&#xff0c;相对简单&#xff0c;大家可…