轻量级TinyXml2的应用

news2025/2/19 14:43:07

TinyXml2库基本介绍

        TinyXML2 是 simple、small、efficient 的基于DOM (Document Object Model,文档对象模型) 的开源 C++ XML文件解析库,可以很方便地应用到现有的项目中 。目前,TinyXML1 开发已经停止,所有的开发都转移到了 TinyXML2。TinyXML2 适用于大部分 C/C++ 的项目,经得住考验,是最好的选择。较 TinyXML1 而言,TinyXML2 化繁为简,使用时只需要包含两个文件,而 TinyXML1 需要包含 6 个文件,一般生成静态链接库供项目使用。

        TinyXML2 使用了与 TinyXML1 相似的 API,并且拥有丰富的测试案例。但 TinyXML2 解析器相对 TinyXML1 在代码上是完全重写,它使用更少的内存,效率更高

        TinyXML2 无需 STL,也放弃了对 STL 支持。所有字符串查询均使用 C 风格字符串const char*来表示,省去 string 类型对象的构造,使代码更加简洁。

下载和使用

GitHub - leethomason/tinyxml2: TinyXML2 is a simple, small, efficient, C++ XML parser that can be easily integrated into other programs.

下载后只需要将将tinyxml2.h和tinyxml2.cpp引入项目即可,极为方便。

项目中使用示例

xmlHandle头文件

#pragma once

#include "TinyXml2/tinyxml2.h"
#include<string>
#include<map>

using namespace::tinyxml2;

namespace XmlHandle 
{
	int CreateXml(const char*xmlpath,const char*rootname);//创建
	int LoadXml(tinyxml2::XMLDocument&doc, const char*xmlpath);//从路径xmlpath加载
	int SaveXml(tinyxml2::XMLDocument&doc, const char*xmlpath);//保存xml文件到xmlpath
	//插入节点 可以携带属性
	XMLElement* InsertNode(tinyxml2::XMLDocument&doc, XMLElement*ParentRoot, const char*element, const char*value, const std::map<std::string, std::string>&AttributeMap = std::map<std::string, std::string>(), bool HasAttribute = false);

	//查询节点
	XMLElement* QueryNodeByName(tinyxml2::XMLDocument&doc, const char*NodeName, const char*Atttibute = nullptr, const char*AttributeValue = nullptr, bool hasAttribute = false);
	std::string QueryValueByName(XMLElement*node);
	std::string QueryAttByName(XMLElement*node,const char*attName);
	//删除节点
	int DeleteNode(tinyxml2::XMLDocument&doc, XMLElement*ParentRoot, const char*element, const char*Atttibute = nullptr, bool isAttribute = false);
	//更新节点值或属性
	XMLElement* UpdateNode(tinyxml2::XMLDocument&doc, XMLElement*Element, const char*element, const char*value, const char*Atttibute = nullptr, const char*AttributeValue = nullptr, bool HasAttribute = false);
	//序列化
	std::string DocToString(tinyxml2::XMLDocument&doc);
	//反序列化
	bool stringToDoc(const std::string&SmlStr, tinyxml2::XMLDocument&doc);

};

xmlHandle的实现文件

#include "XmlHandle.h"


int XmlHandle::CreateXml(const char*xmlpath,const char*rootname)
{
	const char*declartion = "<?xml version = \"1.0\" encoding = \"UTF-8\" ?>";
	XMLDocument doc;
	doc.Parse(declartion);//Parse an XML file from a character string. 覆盖
	XMLElement*root = doc.NewElement(rootname);//新增根节点
	doc.InsertEndChild(root);//InsertFirstChild InsertAfterChild InsertEndChild root下第一个 次于... 最后一个
	XMLError ErrorId = doc.SaveFile(xmlpath);
	return ErrorId;

}


int XmlHandle::LoadXml(XMLDocument&doc, const char*xmlpath)
{
	return doc.LoadFile(xmlpath);
}

int XmlHandle::SaveXml(tinyxml2::XMLDocument&doc, const char*xmlpath)
{
	return doc.SaveFile(xmlpath);
}

XMLElement* XmlHandle::InsertNode(tinyxml2::XMLDocument&doc, XMLElement*ParentRoot, const char*element, const char*value, const std::map<std::string, std::string>&AttributeMap, bool HasAttribute)
{
	XMLElement* Node = doc.NewElement(element);
	if (HasAttribute)
	{
		for (auto iter : AttributeMap)
		{
			Node->SetAttribute(iter.first.c_str(), iter.second.c_str());
		}
	}
	if (value != nullptr)//空则表示有子节点
	{
		Node->InsertEndChild(doc.NewText(value));
	}
	if (ParentRoot)
	{
		ParentRoot->InsertEndChild(Node);
	}
	else
	{
		doc.InsertEndChild(Node);
	}
	return  Node;
}


XMLElement* XmlHandle::QueryNodeByName(XMLDocument&doc, const char*NodeName, const char*Atttibute , const char*AttributeValue, bool hasAttribute)
{
	XMLElement*root = doc.RootElement();
	XMLElement* userNode = root->FirstChildElement(NodeName);
	while (!userNode)
	{
		if ((hasAttribute&&userNode->Attribute(Atttibute) == AttributeValue) || (!hasAttribute))
		{
			break;
		}
		userNode = userNode->NextSiblingElement();//下一个兄弟节点
	}
	return userNode;
}

std::string XmlHandle::QueryValueByName(XMLElement*node)
{
	if (node)
	{
		return node->GetText();
	}
	return std::string();
}

std::string XmlHandle::QueryAttByName(XMLElement*node, const char*attName)
{
	if (node)
	{
		return node->Attribute(attName);
	}
	return std::string();
}

int XmlHandle::DeleteNode(XMLDocument&doc, XMLElement*ParentRoot,const char*element, const char*Atttibute, bool HasAttribute)
{
	if (ParentRoot)
	{
		if (element)
		{
			ParentRoot->DeleteChild(ParentRoot->FirstChildElement(element));
		}
		if (HasAttribute)
		{
			ParentRoot->DeleteAttribute(Atttibute);
		}
		return 0;
	}
	return -1;
}

XMLElement* XmlHandle::UpdateNode(tinyxml2::XMLDocument&doc, XMLElement*Element, const char*element, const char*value, const char*Atttibute, const char*AttributeValue, bool HasAttribute)
{
	if (Element)
	{
		Element->SetText(value);
		if (HasAttribute)
		{
			Element->SetAttribute(Atttibute, AttributeValue);
		}
		return Element;
	}
	return nullptr;
}

std::string XmlHandle::DocToString(tinyxml2::XMLDocument&doc)
{
	XMLPrinter printer;
	doc.Print(&printer);
	return printer.CStr();
}


bool XmlHandle::stringToDoc(const std::string&SmlStr, tinyxml2::XMLDocument&doc)
{
	XMLError XmlErr = doc.Parse(SmlStr.c_str(), SmlStr.size());
	return XmlErr == XML_SUCCESS;
}

 xmlHandle的使用举例

void Qxmltest::TestXML()
{
	//创建
	using namespace XmlHandle;
	std::string path = QDir::currentPath().toStdString() + "/Test.xml";
	int ret = CreateXml(path.c_str(),"XmlDB");


	//增加节点
	tinyxml2:: XMLDocument doc;
	if (0 == LoadXml(doc, path.c_str()))
		//QueryNodeByName
	{
		using AttMap = std::map<std::string, std::string>;
		AttMap Attritubte;
		Attritubte.insert(std::make_pair("Name", "ZahngSan"));
		Attritubte.insert(std::make_pair("Gneder", "Men"));
		XMLElement*UserNode = InsertNode(doc, doc.RootElement(), "User", nullptr, Attritubte, true);
		if (UserNode)
		{
			InsertNode(doc,  UserNode, "hobby", "play games");
			InsertNode(doc,  UserNode, "Pet", "Dog");
			InsertNode(doc,  UserNode, "Language", "Chinese");
			InsertNode(doc,  UserNode, "height", "180");
			InsertNode(doc,  UserNode, "weight", "80");
		}

		Attritubte.clear();
		Attritubte.insert(std::make_pair("Name", "LiSi"));
		Attritubte.insert(std::make_pair("Gneder", "Men"));
		UserNode = InsertNode(doc,  doc.RootElement(), "User", nullptr, Attritubte, true);
		if (UserNode)
		{
			InsertNode(doc, UserNode, "hobby", "play ping-pang");
			InsertNode(doc, UserNode, "Pet", "Cat");
			InsertNode(doc, UserNode, "Language", "Chinese");
			InsertNode(doc, UserNode, "height", "181");

			AttMap weightAtt;
			weightAtt.insert(std::make_pair("WeightX", "Year"));
			weightAtt.insert(std::make_pair("WeightY", "WeightValue"));
			weightAtt.insert(std::make_pair("WeightZ", "UnKnown"));
 			XMLElement*WNode = InsertNode(doc,  UserNode, "weight", nullptr, weightAtt,true);
		
			AttMap att2020;
			att2020.insert(std::make_pair("Year?", "Yes"));
			att2020.insert(std::make_pair("Weight?", "No"));
			XMLElement*Node2020 = InsertNode(doc, WNode, "2020", "70", att2020, true);
			InsertNode(doc,  WNode, "2021", "73");
			InsertNode(doc,  WNode, "2022", "75");

			//修改
			UpdateNode(doc, Node2020, "2020", "69", "Weight", "Yes", true);

			//删除
			DeleteNode(doc, WNode, "2022", "WeightZ", true);
		}
		//查找
		QString Display;
		XMLElement*ZSNode =  QueryNodeByName(doc,"User","name","ZahngSan",true);
		if (ZSNode)
		{
			Display+=QString(QueryAttByName(ZSNode, "Gneder").c_str())+'\n';
		}

		QString xmlStr =QString::fromStdString(DocToString(doc));
		Display +=xmlStr;

		/*tinyxml2::XMLDocument doc2;
		if (stringToDoc(xmlStr.toStdString(), doc2))
		{
			XMLElement*ZSNode = QueryNodeByName(doc, "User", "name", "LiSi", true);
			if (ZSNode)
			{
				Display += QString(QueryAttByName(ZSNode, "Gneder").c_str()) + '\n';
			}
		}*/

		ui.textEdit_XML->setText(Display);
		SaveXml(doc,path.c_str());
	}
}

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

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

相关文章

DeepSeek正重构具身大模型和人形机器人赛道!

中国人工智能公司DeepSeek&#xff08;深度求索&#xff09;以“低成本、高效率、强开放”的研发范式横空出世&#xff0c;火遍并震撼全球科技圈&#xff1b;DeepSeek展现出来的核心竞争力&#xff0c;除了低成本及推理能力&#xff0c;更重要的是开源模型能力追赶上了最新的闭…

Linux库制作与原理:【静态库】【动态库】【目标文件】【ELF文件】【ELF从形成到假造轮廓】【理解链接和加载】

目录 一.什么是库 二.静态库 2.1创建静态库 我们在之前的路径下新建lib使用我们自己的库 2.2 使用makefile生成静态库 三.动态库 3.1动态库生成 3.2动态库使用 3.3库运行搜索路径 四.目标文件 五.ELF文件 六.ELF从形成到加载轮廓 6.1ELF形成可执行 6.2 ELF可执行文…

【ubuntu24.04】 强制重启导致大模型的磁盘挂载出错

挂载NTFS文件系统出错 各种模型放在了这个机械硬盘上&#xff0c;虽然速度慢&#xff0c;但是好在容量大。大模型在工作&#xff0c;但是程序看起来有问题&#xff0c;导致系统卡死了&#xff0c;然后我重启了&#xff0c;然后报错&#xff1a;wrong fs type bad option &…

Spring Boot(8)深入理解 @Autowired 注解:使用场景与实战示例

搞个引言 在 Spring 框架的开发中&#xff0c;依赖注入&#xff08;Dependency Injection&#xff0c;简称 DI&#xff09;是它的一个核心特性&#xff0c;它能够让代码更加模块化、可测试&#xff0c;并且易于维护。而 Autowired 注解作为 Spring 实现依赖注入的关键工具&…

【linux】在 Linux 服务器上部署 DeepSeek-r1:70b 并通过 Windows 远程可视化使用

【linux】在 Linux 服务器上部署 DeepSeek-r1:70b 并通过 Windows 远程可视化使用 【承接商业广告,如需商业合作请+v17740568442】 文章目录 【linux】在 Linux 服务器上部署 DeepSeek-r1:70b 并通过 Windows 远程可视化使用个人配置详情一、安装ollama二、下载deepseek版本…

【AI大模型】Ollama部署本地大模型DeepSeek-R1,交互界面Open-WebUI,RagFlow构建私有知识库

文章目录 DeepSeek介绍公司背景核心技术产品与服务应用场景优势与特点访问与体验各个DeepSeek-R系列模型的硬件需求和适用场景 Ollama主要特点优势应用场景安装和使用配置环境变量总结 安装open-webui下载和安装docker desktop配置镜像源安装open-webui运行和使用 RagFlow介绍主…

Unity 命令行设置运行在指定的显卡上

设置运行在指定的显卡上 -force-device-index

Visual Studio 使用 “Ctrl + /”键设置注释和取消注释

问题&#xff1a;在默认的Visual Studio中&#xff0c;选择单行代码后&#xff0c;按下Ctrl /键会将代码注释掉&#xff0c;但再次按下Ctrl /键时&#xff0c;会进行双重注释&#xff0c;这不是我们想要的。 实现效果&#xff1a;当按下Ctrl /键会将代码注释掉&#xff0c;…

教程:使用 Vue 3 和 arco 实现表格合并

1. 功能概述 本教程将介绍如何使用 Vue 3 和 arco 组件库实现表格合并功能。具体来说&#xff0c;我们会根据表格数据中的某个字段&#xff08;如 type&#xff09;对表格的某一列&#xff08;如入库类型列&#xff09;进行合并&#xff0c;同时将质检说明列合并为一列。 2. …

uniapp - iconfont下载本地并且运用至项目上

1、项目中创建一个文件夹放置iconfont相关文件&#xff0c;例如src/assets/iconfont&#xff08;名称自己定义&#xff09; 2、在iconfont下载项目至本地 3、解压后把文件复制进1的文件夹中 4、修改src/assets/iconfont - iconfont.css里的font-face的src地址&#xff0c;修…

【前端】自己从头实现一个gpt聊天页面

预览 最小化功能点 主界面&#xff1a;侧边栏会话历史、聊天窗口发送和断开。侧边栏&#xff1a;展示会话列表&#xff0c;每个会话包含多条聊天记录&#xff0c; 通过localstorage本地储存和恢复&#xff0c;会话需要重命名和删除。聊天框&#xff1a;区分一下发送者和回答者…

数据结构——二叉树(2025.2.12)

目录 一、树 1.定义 &#xff08;1&#xff09;树的构成 &#xff08;2&#xff09;度 2.二叉树 &#xff08;1&#xff09;定义 &#xff08;2&#xff09;二叉树的遍历 &#xff08;3&#xff09;遍历特性 二、练习 1.二叉树 &#xff08;1&#xff09;创建二叉树…

Vulhub靶机 ActiveMQ任意 文件写入(CVE-2016-3088)(渗透测试详解)

一、开启vulhub环境 docker-compose up -d 启动 docker ps 查看开放的端口 漏洞版本&#xff1a;ActiveMQ在5.14.0之前的版本&#xff08;不包括5.14.0&#xff09; 二、访问靶机IP 8161端口 默认账户密码都是admin 1、利用bp抓包&#xff0c;修改为PUT方法并在fileserver…

跟着李沐老师学习深度学习(十一)

经典的卷积神经网络 在本次笔记中主要介绍一些经典的卷积神经网络模型&#xff0c;主要包含以下&#xff1a; LeNet&#xff1a;最早发布的卷积神经网络之一&#xff0c;目的是识别图像中的手写数字&#xff1b;AlexNet&#xff1a; 是第一个在大规模视觉竞赛中击败传统计算机…

【微软- Entra ID】Microsoft Entra ID

Microsoft Entra ID是微软提供的基于云的身份和访问管理服务。Microsoft Entra ID是一个全面的解决方案,用于管理身份、执行访问策略以及在云和本地保护您的应用程序和数据。 目录 一、查看 Microsoft Entra ID 微软Entra租户 微软Entra模式 二、比较Microsoft Entra ID与…

Halcon相机标定

1&#xff0c;前言。 相机的成像过程实质上是坐标系的转换。首先空间中的点由“世界坐标系”转换到“相机坐标系”&#xff0c;然后再将其投影到成像平面&#xff08;图像物理坐标系&#xff09;&#xff0c;最后再将成像的平面上的数据转换为图像像素坐标系。但是由于透镜的制…

Linux 配置 MySQL 定时自动备份到另一台服务器

Linux 配置 MySQL 定时自动备份到另一台服务器 前言1、配置服务器通信1.1&#xff1a;配置过程 2、编写自动备份sh脚本文件3&#xff1a;设置定时自动执行 前言 此方案可使一台服务器上的 MySQL 中的所有数据库每天 0 点自动转储为 .sql 文件&#xff0c;然后将文件同步到另一…

《安富莱嵌入式周报》第350期:Google开源Pebble智能手表,开源模块化机器人平台,开源万用表,支持10GHz HRTIM的单片机,开源CNC控制器

周报汇总地址&#xff1a;嵌入式周报 - uCOS & uCGUI & emWin & embOS & TouchGFX & ThreadX - 硬汉嵌入式论坛 - Powered by Discuz! 视频版&#xff1a; https://www.bilibili.com/video/BV1YPKEeyEeM/ 《安富莱嵌入式周报》第350期&#xff1a;Google开…

LabVIEW与小众设备集成

在LabVIEW开发中&#xff0c;当面临控制如布鲁克OPUS红外光谱仪这类小众专业设备的需求&#xff0c;而厂家虽然提供了配套软件&#xff0c;但由于系统中还需要控制其他设备且不能使用厂商的软件时&#xff0c;必须依赖特定方法通过LabVIEW实现设备的控制。开发过程中&#xff0…

无人机之无线传输技术!

一、Lightbridge和OcuSync图传技术 Lightbridge技术&#xff1a;这是大疆自主研发的一种专用通信链路技术&#xff0c;使用单向图像数据传输&#xff0c;类似于电视广播塔的数据传输形式。它主要采用2.4GHz频段进行传输&#xff0c;并且可以实现几乎“零延时”的720p高清图像传…