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

一、对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的对类进行序列化和反序列化】 二

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

金仓Kingbase客户端KStudio报OOM:Java heap space socketTimeout

找到Kingbase\ES\V8\KESRealPro\V008R006C006B0021\ClientTools\guitools\KStudio\KStudio.ini 修改JVM参数&#xff1a; 默认值&#xff1a; -Xms512m -Xmx1024m 改为&#xff1a; -Xms1024m -Xmx2048m -XX:MaxPermSize512m SQL查询报错&#xff1a;An I/O error occurred …

Redis--21--大Key问题解决方案

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言Redis--20--大Key问题解析 一、如何发现Redis大Key1. 使用Redis命令行工具**MEMORY USAGE****RANDOMKEY****DEBUG OBJECT****SCAN命令****redis-cli 工具&#…

【进程与线程】进程的状态

在操作系统中&#xff0c;进程是执行中的程序实例。进程在其生命周期中会经历不同的状态&#xff0c;操作系统根据进程的执行情况和资源调度&#xff0c;将进程划分为多个状态。 这些状态帮助操作系统更加高效地管理 CPU 和系统资源。 进程的状态&#xff1a;就绪态&#xff0…

K8S开启/关闭审计日志

K8S默认禁用审计 开启/关闭 k8s 审计日志 默认 Kubernetes 集群不会输出审计日志信息。通过以下配置&#xff0c;可以开启 Kubernetes 的审计日志功能。 准备审计日志的 Policy 文件配置 API 服务器&#xff0c;开启审计日志重启并验证 准备审计日志 Policy 文件 apiVersio…

nginx: [emerg] bind() to 0.0.0.0:80 failed 端口被占用

nginx: [emerg] bind() to 0.0.0.0:80 failed (10013: An attempt was made to access a socket in a way forbidden by its access permissions) 查看被占用的端口 被系统占用了 HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Services/HTTP 然后再进入nginx文件夹目录下…

vue2 web 多标签输入框 elinput是否当前焦点

又来分享一点点工作积累及解决方案 产品中需要用户输入一些文字后按下回车键生成标签来显示在页面上&#xff0c;经过尝试与改造完成如下&#xff1a; <template><div class"tags-view" click"beginInput"><el-tag :key"index" …

vLLM私有化部署大语言模型LLM

目录 一、vLLM介绍 二、安装vLLM 1、安装环境 2、安装步骤 三、运行vLLM 1、运行方式 2、切换模型下载源 3、运行本地已下载模型 四、通过http访问vLLM 一、vLLM介绍 vLLM&#xff08;官方网址&#xff1a;https://www.vllm.ai&#xff09;是一种用于大规模语言模型&#x…

STM32的集成开发环境STM32CubeIDE安装

STM32CubeIDE - STM32的集成开发环境 - 意法半导体STMicroelectronics

硬件学习笔记--31 IEC62053-21相关内容介绍

IEC 62053-21是一项由国际电工委员会&#xff08;International Electrotechnical Commission&#xff0c;简称IEC&#xff09;发布的国际标准&#xff0c;全称为《交流电能测量设备&#xff08;a.c.&#xff09;-特殊要求-第21部分&#xff1a;静止式有功能量计量表&#xff0…

C++类与对象(一)—学习记录

序言&#xff1a;要想开发一款成功的应用程序&#xff0c;其开发者必须充分了解并实现用户的需求。作为一个设计良好的类&#xff0c;既要有直观且易于使用的接口&#xff0c;也必须具备高效的实现过程。 一、类与对象基本概念 面向对象程序设计的主要特点为抽象、封装、继承与…

七大排序算法

文章目录 排序的概念及引用1.插入排序2.希尔排序(缩小增量排序)3.选择排序4.堆排序5.冒泡排序6.快速排序7.归并排序8.代码排序部分的测试9.代码加效果大致测试时间&#xff08;仅供参考&#xff09; 排序的概念及引用 排序:将数据按照特定的规律排成递增或递减的操作 稳定性:…

Windows 蓝牙驱动开发-蓝牙设备栈

蓝牙设备栈 蓝牙驱动程序堆栈包含 Microsoft 为蓝牙协议提供支持的核心部分。 有了这个堆栈&#xff0c;已启用蓝牙的设备可以彼此定位并建立连接。 在此类连接中&#xff0c;设备可以通过各种应用程序交换数据并彼此交互。 下图显示了蓝牙驱动程序堆栈中的模块&#xff0c;以…

C# 获取PDF文档中的字体信息(字体名、大小、颜色、样式等

在设计和出版行业中&#xff0c;字体的选择和使用对最终作品的质量有着重要影响。然而&#xff0c;有时我们可能会遇到包含未知字体的PDF文件&#xff0c;这使得我们无法准确地复制或修改文档。获取PDF中的字体信息可以解决这个问题&#xff0c;让我们能够更好地处理这些文件。…

第十三章:数据库技术

文章目录&#xff1a; 一&#xff1a;基础 1.概念 2.特点 3.常见数据库品牌 4.数据库应⽤系统 4.1 C/S 4.2 B/S 5.数据模型的分类 6.名词解析 7.关系运算 二&#xff1a;Access 1.基础 2.操作 2.1 建立表 2.2 维护表 2.3 创建查询 2.4 创建窗体 2.5 创建报表…

目标检测新视野 | YOLO、SSD与Faster R-CNN三大目标检测模型深度对比分析

目录 引言 YOLO系列 网络结构 多尺度检测 损失函数 关键特性 SSD 锚框设计 损失函数 关键特性 Faster R-CNN 区域建议网络&#xff08;RPN&#xff09; 两阶段检测器 损失函数 差异分析 共同特点 基于深度学习 目标框预测 损失函数优化 支持多类别检测 应…

浏览器输入http形式网址后自动跳转https解决方法

一、问题描述 使用浏览器 网上冲浪 时会遇到一个情况&#xff1a; 在浏览器中输入“http域名”后会自动变成“https 域名”的形式&#xff0c;此时“https 域名”的网站可能已停止对外提供服务了&#xff0c;这时会出现如下不友好的网页提示&#xff1a; 二、处理方法&#x…

Unity2017 控制.abc格式的三维动画播放

首先需要导入插件Alembic&#xff0c;否则导入abc动画&#xff0c;Unity是不会识别的。 Unity2017版本及以下直接从我这儿下载&#xff1a;https://download.csdn.net/download/qq_41603955/90272382 高版本Unity&#xff0c;请移步AssetStore商店搜找。 导入abc之后&#x…

python管理工具:conda部署+使用

python管理工具&#xff1a;conda部署使用 一、安装部署 1、 下载 - 官网下载&#xff1a; https://repo.anaconda.com/archive/index.html - wget方式&#xff1a; wget -c https://repo.anaconda.com/archive/Anaconda3-2023.03-1-Linux-x86_64.sh2、 安装 在conda文件的…

挖掘机检测数据集,准确识别率91.0%,4327张原始图片,支持YOLO,COCO JSON,PASICAL VOC XML等多种格式标注

挖掘机检测数据集&#xff0c;准确识别率91.0%&#xff0c;4327张图片&#xff0c;支持YOLO&#xff0c;COCO JSON&#xff0c;PASICAL VOC XML等多种格式标注 数据集详情 数据集分割 训练组70&#xff05; 3022图片 有效集20&#xff05; 870图片 测试集10&…

vue 学习笔记 - 创建第一个项目 idea

1、安装Vue CLI 查看npm版本号 &#xff08;可跳过&#xff09; % npm -v 11.0.0安装Vue CLI % npm install -g vue/cli2、创建项目 进入工程文件目录 % cd /Users/ruizhifeng/work/aina-client查看vue 版本号 &#xff08;可跳过&#xff09; % vue --version vue/cli 5…