QT开发技术 【基于TinyXml2的对类进行序列化和反序列化】一

embedded/2025/1/17 15:16:04/

一、对TinyXml2 进行封装 使用宏 实现序列化和反序列化

思路:
利用宏增加一个类函数,使用序列化器调用函数进行序列化

封装宏示例

#define XML_SERIALIZER_BEGIN(ClassName) \
public: \virtual void ToXml(XMLElement* parentElem, bool bSerialize = true) { \if (bSerialize) { \parentElem->SetName(#ClassName); \}\
#define XML_SERIALIZER_VAR(Name, Value) \if (bSerialize) { \CXmlImplement::WriteElement(parentElem, Name, Value); \} \else { \CXmlImplement::ReadElement(parentElem, Name, Value); \} \

#define XML_SERIALIZER_STL_VAR(Name, Value) \if (bSerialize) { \CXmlImplement::WriteSTLElement(parentElem, Name, Value); \} \else { \CXmlImplement::ReadSTLElement(parentElem, Name, Value); \} \

#define XML_SERIALIZER_ARRAY(Name, Object) \if (bSerialize) { \CXmlImplement::WriteElementObject(parentElem, Name, Object); \} \else { \CXmlImplement::ReadElementObject(parentElem, Name, Object); \} \

#define XML_SERIALIZER_END() \} \

目前只封装了简单使用的,需要其他自己可以增加

二、类使用宏

新建一个student 类 增加宏

class CStudent
{
public:CStudent(){std::cout << "Constructor CStudent" << std::endl;}~CStudent(){std::cout << "Destructor CStudent" << std::endl;}XML_SERIALIZER_BEGIN(CStudent)XML_SERIALIZER_VAR("学号", m_nStudentID)XML_SERIALIZER_VAR("姓名", m_strName)XML_SERIALIZER_VAR("年龄", m_nAge)XML_SERIALIZER_VAR("性别", m_nSex)XML_SERIALIZER_END()int m_nStudentID;std::string m_strName;int m_nAge;int m_nSex;
};  

这样一个类就增加了想要的序列化函数

三、实现序列化器

利用TinyXml2实现序列化器封装

3.1、TinyXml2介绍

TinyXML-2 是一个简单,小型,高效的 C ++ XML 解析器,可以轻松集成到其他程序中,直接引用源文件的话只需要包含两个文件(h 和 cpp,此外还有个测试文件里面带有 demo)。TinyXML-2 解析 XML 文档,并以此为基础构建可读取,修改和保存的文档对象模型(DOM)。文档说,在解释 XML 时仅使用 UTF-8 ,假定所有 XML 为 UTF-8 (看了下使用 MSVC 编译器时生成的 XML 文件文本编码使用的本地编码)。该库还支持打印到文件或内存,使用 XMLPrinter 类。GitHub 链接:[链接](https://github.com/leethomason/tinyxml2)

使用模板对TinyXml2 序列化进行封装

/*
**  File name:   XmlImplement.h
**  Author:      
**  Date:        2025-01-16
**  Brief:       xml序列化实现类
**  Copyright (C) 1392019713@qq.com All rights reserved.
*/#pragma once
#include <string>
#include <vector>
#include <iostream>
#include "tinyxml2.h"
#include "XmlSerializerExportLib.h"using namespace tinyxml2;class  CXmlImplement {
public:template <typename T>static void WriteElement(XMLElement* parentElem, const std::string& elementName, const T& value) {XMLElement* elem = parentElem->GetDocument()->NewElement(elementName.c_str());elem->SetText(value);parentElem->InsertEndChild(elem);}static void WriteElement(XMLElement* parentElem, const std::string& elementName, const std::string& value) {XMLElement* elem = parentElem->GetDocument()->NewElement(elementName.c_str());elem->SetText(value.c_str());parentElem->InsertEndChild(elem);}template <typename T>static void WriteSTLElement(XMLElement* parentElem, const std::string& elementName, const std::vector<T>& values) {XMLElement* vectorElem = parentElem->GetDocument()->NewElement(elementName.c_str());if (!vectorElem){return;}for (const auto& value : values) {WriteElement(vectorElem, elementName + "Item", value);}parentElem->InsertEndChild(vectorElem);}template <typename T>static void ReadElement(XMLElement* parentElem, const std::string& elementName, T& value) {XMLElement* elem = parentElem->FirstChildElement(elementName.c_str());if (elem) {value = std::stoi(elem->GetText());}}static void ReadElement(XMLElement* parentElem, const std::string& elementName, std::string& value) {XMLElement* elem = parentElem->FirstChildElement(elementName.c_str());if (elem) {value = elem->GetText();}}template <typename T>static void ReadSTLElement(XMLElement* parentElem, const std::string& elementName, std::vector<T>& values) {XMLElement* vectorElem = parentElem->FirstChildElement(elementName.c_str());if (!vectorElem){return;}for (XMLElement* elem = vectorElem->FirstChildElement(); elem; elem = elem->NextSiblingElement()){T value;ReadElement(elem, elem->Name(), value);values.push_back(value);}}template <typename T>static void WriteElementObject(XMLElement* parentElem, const std::string& elementName,  T* pT) {XMLElement* elem = parentElem->GetDocument()->NewElement(elementName.c_str());pT->ToXml(elem);parentElem->InsertEndChild(elem);}template <typename T>static void WriteElementObject(XMLElement* parentElem, const std::string& elementName, const std::vector<T*>& objects) {XMLElement* vectorElem = parentElem->GetDocument()->NewElement(elementName.c_str());for (const auto& object : objects) {WriteElementObject(vectorElem, elementName + "Item", object);}parentElem->InsertEndChild(vectorElem);}template <typename T>static void ReadElementObject(XMLElement* parentElem, const std::string& elementName, T* pT, bool array = false) {XMLElement* elem;if (array){elem = parentElem;}else{elem = parentElem->FirstChildElement(elementName.c_str());}if (elem) {pT->ToXml(elem, false);}}template <typename T>static void ReadElementObject(XMLElement* parentElem, const std::string& elementName, std::vector<T*>& vecObjs) {XMLElement* objectElem = parentElem->FirstChildElement(elementName.c_str());for (XMLElement* elem = objectElem->FirstChildElement(); elem; elem = elem->NextSiblingElement()){T* pT = new T();ReadElementObject(elem, elem->Name(), pT, true);vecObjs.push_back(pT);}}template <typename T>static bool Serialize(std::string& strXml, T* pT) {bool bRet = false;if (!pT){return bRet;}XMLDocument doc;XMLDeclaration* declaration = doc.NewDeclaration();declaration->SetValue("xml version=\"1.0\" encoding=\"GB2312\"");doc.InsertFirstChild(declaration);XMLElement* rootElem = doc.NewElement("Root");if (!rootElem){return bRet;}pT->ToXml(rootElem);doc.InsertEndChild(rootElem);XMLPrinter printer;doc.Accept(&printer);strXml = printer.CStr();return true;}template <typename T>static bool Deserialize(const std::string& xml, T* pT) {bool bRet = false;if (!pT){return bRet;}XMLDocument doc;XMLError result = doc.Parse(xml.c_str());if (result != XML_SUCCESS) {std::cerr << "Failed to parse XML: " << XMLDocument::ErrorIDToName(result) << std::endl;return bRet;}XMLElement* rootElem = doc.RootElement();if (rootElem) {pT->ToXml(rootElem, false);}return true;}
};

四、使用测试

增加2个类测试

#include <iostream>
#include <string>
#include <vector>
#include <fstream>
#include "../../XmlSerialize/Include/XmlSerializer.h"class CStudent
{
public:CStudent(){std::cout << "Constructor CStudent" << std::endl;}~CStudent(){std::cout << "Destructor CStudent" << std::endl;}XML_SERIALIZER_BEGIN(CStudent)XML_SERIALIZER_VAR("学号", m_nStudentID)XML_SERIALIZER_VAR("姓名", m_strName)XML_SERIALIZER_VAR("年龄", m_nAge)XML_SERIALIZER_VAR("性别", m_nSex)XML_SERIALIZER_END()int m_nStudentID;std::string m_strName;int m_nAge;int m_nSex;
};  class CClass //: public CXmlSerializer
{
public:CClass(){}~CClass(){for (auto itr = m_vecStudents.begin(); itr != m_vecStudents.end();){CStudent* pStudent = *itr;if (pStudent){std::cout << pStudent->m_nStudentID << " " << pStudent->m_strName << std::endl;delete pStudent;itr = m_vecStudents.erase(itr);}else{++itr;}}m_vecStudents.clear();}XML_SERIALIZER_BEGIN(CClass)XML_SERIALIZER_VAR("班级名称", m_strName)XML_SERIALIZER_VAR("班级ID", m_nClassID)XML_SERIALIZER_ARRAY("学生列表", m_vecStudents)XML_SERIALIZER_END()std::string m_strName;int m_nClassID;std::vector<CStudent*> m_vecStudents;
};void TestXml()
{{CStudent student;student.m_nStudentID = 1001;student.m_strName = "张三";student.m_nAge = 20;student.m_nSex = 1;std::string strXml;CXmlImplement::Serialize(strXml, &student);std::ofstream ofs("E:/Project/Inlib/Base/Examples/Bin/Debug/student.xml");ofs << strXml;CStudent student2;CXmlImplement::Deserialize(strXml, &student2);std::cout << student2.m_nStudentID << std::endl;std::cout << student2.m_strName << std::endl;student2.m_strName = "李四";student2.m_nStudentID = 1002;CClass class1;class1.m_strName = "1班";class1.m_nClassID = 101;class1.m_vecStudents.push_back(&student);class1.m_vecStudents.push_back(&student2);CXmlImplement::Serialize(strXml, &class1);std::ofstream ofs1("E:/Project/Inlib/Base/Examples/Bin/Debug/class.xml");ofs1 << strXml;}std::cout << "------class Begin--------------" << std::endl;std::ifstream ifs("E:/Project/Inlib/Base/Examples/Bin/Debug/class.xml");std::string strXml = std::string((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>());CClass class2;CXmlImplement::Deserialize(strXml, &class2);std::cout << class2.m_strName << std::endl;
}int main()
{TestXml();return 0;
}

生成结果

在这里插入图片描述

如果文章帮到你,动动小手点赞 (-_-)

下一篇文章链接 QT开发技术 【基于TinyXml2的对类进行序列化和反序列化】 二


http://www.ppmy.cn/embedded/154686.html

相关文章

3、C#基于.net framework的应用开发实战编程 - 实现(三、一) - 编程手把手系列文章...

三、 实现&#xff1b; 三&#xff0e;一、实现数据库操作&#xff1b; 对于数据库的操作&#xff0c;以前都是有ODBC的接口&#xff0c;通过Helper类库进行的操作。此文主要介绍例子里对数据库操作的实现。 1、 SQLiteHelper&#xff1b; SQLite主要是用C编写的&#xff0c;但…

【概率论与数理统计】第三章 多维随机变量及其分布(2)

定义7&#xff1a;若二维连续型随机变量 ( X , Y ) (X,Y) (X,Y)的概率密度为&#xff1a; f ( x , y ) 1 2 π σ 1 σ 2 1 − ρ 2 e − 1 2 ( 1 − ρ 2 ) [ ( x − μ 1 ) 2 σ 1 2 − 2 ρ ( x − μ 1 ) ( y − μ 2 ) σ 1 σ 2 ( y − μ 2 ) 2 σ 2 2 ] f(x,y) \fra…

(经过验证)在 Ubuntu 系统中为 VSCode、PyCharm 终端及 Jupyter Notebook 配置代理的完整方案

文章目录 1. 通过系统环境变量配置代理步骤一&#xff1a;打开终端步骤二&#xff1a;编辑 ~/.bashrc 文件步骤三&#xff1a;添加代理环境变量步骤四&#xff1a;保存并关闭文件步骤五&#xff1a;使配置生效步骤六&#xff1a;重启相关应用步骤七&#xff1a;使用代理函数 2.…

接口传参 data格式和json格式区别是什么

接口传参 data格式和json格式区别是什么 以下是接口传参 data 格式和 JSON 格式的区别&#xff1a; 定义和范围 Data 格式&#xff1a; 是一个较为宽泛的概念&#xff0c;它可以指代接口传递参数时所使用的任何数据的组织形式。包括但不限于 JSON、XML、Form 数据、纯文本、二进…

微信小程序在使用页面栈保存页面信息时,如何避免数据丢失?

微信小程序在使用页面栈保存页面信息时避免数据丢失的方法&#xff1a; 一、使用全局变量存储关键数据&#xff1a; 定义一个全局变量&#xff0c;例如在 app.js 中&#xff0c;用于存储页面的重要信息。在页面的 onHide 或 onUnload 生命周期中&#xff0c;将需要保存的数据…

【江西新能源科技职业学院主办 | JPCS(ISSN: 1742-6588)出版,快速见刊检索】2025年可再生能源与节能国际会议(REEC 2025)

2025年可再生能源与节能国际会议&#xff08;REEC 2025&#xff09; 2025 International Conference on Renewable Energy and Energy Conservation 2025年3月7-9日 中国江西新余 大会官网&#xff1a;www.icreec.org【参会投稿】 报名/截稿&#xff1a;见官网 提交收录&…

在eNSp上telnet一下吧

在上篇博客&#xff1a;DNS 我们提到了telnet和设备带外管理、带内管理&#xff0c;它确实是非常有趣的一个知识点哦&#xff0c;接下来我们一起来学习学习吧~ Telnet&#xff08;远程登陆协议&#xff09; Telnet基于TCP 23号端口&#xff0c;典型的C/S架构模式&#xff0c;是…

一文读懂单片机的串口

目录 串口通信的基本概念 串口通信的关键参数 单片机串口的硬件连接 单片机串口的工作原理 数据发送过程 数据接收过程 单片机串口的编程实现 以51单片机为例 硬件连接 初始化串口 发送数据 接收数据 串口中断服务函数 代码示例 单片机串口的应用实例 单片机与…