QT 使用XML保存操作记录

news2024/12/23 8:55:38

文章目录

  • 1 实现程序保存操作记录的思路
  • 2 XML文档基本结构
  • 3 QDomDocument实现XML读写
    • 3.1 QDomDocument实现生成XML文件
    • 3.2 QDomDocument实现读取XML文件
  • 4 QXmlStreamWriter实现读写
    • 4.1 QXmlStreamWriter实现生成XML
    • 4.2 QXmlStreamWriter实现读取XML

1 实现程序保存操作记录的思路

思路来源: 由于在一些绘图工具中,有些将操作的历史记录,缓存的操作配置保存在了json文件,也有的保存到了xml文件中,如下图所示。经过个人的对比发现xml的文件结构简单、文件的可读性强,节点和内容项之间关系层次清晰,能够实现简单、快速、清晰的内容缓存,非常适合做复杂数据类型的操作记录、工程操作文件记录、配置文件工具。

  • json 示例(来自一个友商的算法标注工具)
{
  "version": "4.5.6",
  "flags": {},
  "shapes": [
    {
      "description": null,
      "mask": null,
      "label": "7",
      "points": [
        [
          574.5679012345677,
          630.8641975308642
        ],
        [
          701.7283950617282,
          0.0
        ],
        [
          822.7160493827159,
          193.82716049382702
        ],
        [
          1091.8518518518517,
          169.1358024691358
        ]
      ],
      "group_id": null,
      "shape_type": "polygon",
      "flags": {}
    },
    {
      "description": null,
      "mask": null,
      "label": "7",
      "points": [
        [
          970.5472636815921,
          377.96019900497504
        ],
        [
          763.2246176524784,
          204.6395798783858
        ],
        [
          689.9502487562188,
          457.0646766169153
        ],
        [
          689.9502487562188,
          639.1542288557212
        ],
        [
          882.4875621890546,
          636.1691542288554
        ],
        [
          1222.7860696517412,
          583.9303482587063
        ]
      ],
      "group_id": null,
      "shape_type": "polygon",
      "flags": {}
    },
    {
      "description": null,
      "mask": null,
      "label": "7",
      "points": [
        [
          536.8694885361556,
          394.21340388007053
        ],
        [
          596.1287477954147,
          430.01587301587324
        ]
      ],
      "group_id": null,
      "shape_type": "circle",
      "flags": {}
    }
  ],
  "imagePath": "微信图片_20231027144505.png",
  "imageData": null,
  "imageHeight": 1080,
  "imageWidth": 1920
}
  • xml示例 (qdraw)
    在这里插入图片描述
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE qdraw>
<canvas width="800" height="600">
    <polyline rotate="0" x="469.004" y="326.484" z="0" width="394" height="289">
        <point x="-88.0041" y="20.5161"/>
        <point x="76.9959" y="144.516"/>
        <point x="196.996" y="65.5161"/>
        <point x="150.996" y="-144.484"/>
        <point x="-24.0041" y="-59.4839"/>
        <point x="-163.004" y="-63.4839"/>
        <point x="-197.004" y="53.5161"/>
        <point x="-116.004" y="56.5161"/>
        <point x="-150.004" y="11.5161"/>
    </polyline>
    <polyline rotate="0" x="164.945" y="321.008" z="0" width="218" height="134">
        <point x="-71.9446" y="26.9924"/>
        <point x="27.0554" y="66.9924"/>
        <point x="109.055" y="8.99239"/>
        <point x="-44.9446" y="-67.0076"/>
        <point x="-108.945" y="17.9924"/>
        <point x="-70.9446" y="25.9924"/>
    </polyline>
    <ellipse startAngle="40" spanAngle="400" rotate="0" x="155" y="125.5" z="0" width="174" height="125"/>
    <roundrect rx="0.1" ry="0.333333" rotate="0" x="357.5" y="461" z="0" width="141" height="108"/>
    <rect rotate="0" x="104" y="488.5" z="0" width="152" height="163"/>
</canvas>

2 XML文档基本结构

在这里插入图片描述

3 QDomDocument实现XML读写

原理说明: 和json文件处理发方式相同。根据节点、子节点、内容项的关系生成、加载XML文件的内容。
方案缺点: 生成的xml文档中的内容项的顺序是随机的,如下图所示。需要添加随机方法处理,参见文章Qt中使用QDomDocument生成XML文件元素属性随机乱序解决办法 、解决QDomDocument的setattribute乱序,这样能保证每行顺序都是一样的,但是也和自己生成顺序不同。该方法逐渐被淘汰,请参见下文,方法2QXmlStreamWriter实现。

<!-->自己期望的结果<!-->
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE algoConfig>
<baseConfig>
    <algolist>
        <algo algId="101001" algName="未戴安全帽" serverType="图片服务" depModel1="1030" depLable1="NO_HELMET" depModel2="" depLable2="" depModel3="" depLable3=""/>
        <algo algId="101002" algName="未穿长袖" serverType="图片服务" depModel1="1030" depLable1="PERSON" depModel2="" depLable2="" depModel3="" depLable3=""/>
</algolist>
    <modelMap>
        <model modelName="1303" reName="2303"/>
    </modelMap>
</baseConfig>
<!-->生成的结果<!-->
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE algoConfig>
<baseConfig>
    <algolist>
        <algo serverType="图片服务" algName="未戴安全帽" algId="101001"  depModel1="1030" depLable1="NO_HELMET" depModel2="" depLable2="" depModel3="" depLable3=""/>
        <algo serverType="图片服务" algName="未穿长袖" algId="101002"   depModel1="1030" depLable1="PERSON" depModel2="" depLable2="" depModel3="" depLable3=""/>
</algolist>
    <modelMap>
        <model modelName="1303" reName="2303"/>
    </modelMap>
</baseConfig>

3.1 QDomDocument实现生成XML文件

方法说明: 采用QDomDocument实现,方案传统优缺点。

#include <QDomDocument>
#include <QFile>
#include <QTextStream>

// Method to generate XML file
void generateXMLFile() {
    QDomDocument document;

    // Making the root element
    QDomElement root = document.createElement("baseConfig");

    // Making elements of algolist
    QDomElement algolist = document.createElement("algolist");

    QDomElement algo1 = document.createElement("algo");
    algo1.setAttribute("algId", "101001");
    algo1.setAttribute("algName", "未戴安全帽");
    algo1.setAttribute("serverType", "图片服务");
    algo1.setAttribute("depModel1", "1030");
    algo1.setAttribute("depLable1", "NO_HELMET");
    algolist.appendChild(algo1);

    QDomElement algo2 = document.createElement("algo");
    algo2.setAttribute("algId", "101002");
    algo2.setAttribute("algName", "未穿长袖");
    algo2.setAttribute("serverType", "图片服务");
    algo2.setAttribute("depModel1", "1030");
    algo2.setAttribute("depLable1", "PERSON");
    algolist.appendChild(algo2);

    root.appendChild(algolist);

    // Making elements of modelMap
    QDomElement modelMap = document.createElement("modelMap");

    QDomElement model = document.createElement("model");
    model.setAttribute("modelName", "1303");
    model.setAttribute("reName", "2303");
    modelMap.appendChild(model);

    root.appendChild(modelMap);

    document.appendChild(root);

    // Writing to a file
    QFile file("Config.xml");
    if(!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
        qDebug() << "Failed to open file for writing.";
        return;
    } else {
        QTextStream stream(&file);
        stream << document.toString();
        file.close();
        qDebug() << "File written.";
    }
}

3.2 QDomDocument实现读取XML文件

#include <QDomDocument>
void loadXMLFile() {
    QDomDocument document;
    QFile file("Config.xml");

    if(!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
        qDebug() << "Failed to open file for reading.";
        return;
    } else {
        if(!document.setContent(&file)) {
            qDebug() << "Failed to load document.";
            return;
        }
        file.close();
    }

    QDomElement root = document.firstChildElement();

    QDomNodeList algos = root.firstChildElement("algolist").elementsByTagName("algo");
    for(int i = 0; i < algos.count(); i++) {
        QDomNode algoNode = algos.at(i);
        if(algoNode.isElement()) {
            QDomElement algo = algoNode.toElement();
            qDebug() << "Algo ID: " << algo.attribute("algId");
            qDebug() << "Algo Name: " << algo.attribute("algName");
        }
    }

    QDomNodeList models = root.firstChildElement("modelMap").elementsByTagName("model");
    for(int i = 0; i < models.count(); i++) {
        QDomNode modelNode = models.at(i);
        if(modelNode.isElement()) {
            QDomElement model = modelNode.toElement();
            qDebug() << "Model Name: " << model.attribute("modelName");
            qDebug() << "Renamed as: " << model.attribute("reName");
        }
    }
}

4 QXmlStreamWriter实现读写

  • 使用QXmlStreamWriter方法,读写超级简单,实现容易快速。

4.1 QXmlStreamWriter实现生成XML

#include <QXmlStreamReader>
void genConfForm::genXmlFile()
{
    QFile file("conf.xml");
    if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
        qDebug() << "Failed to open file for writing.";
        return;
    }

    QXmlStreamWriter xmlWriter(&file);
    xmlWriter.setAutoFormatting(true);
    xmlWriter.writeStartDocument();
    xmlWriter.writeDTD("<!DOCTYPE algoConfig>");
    xmlWriter.writeStartElement("baseConfig");

    xmlWriter.writeStartElement("algolist");

    int rows = ui->tableView_gc->model()->rowCount();
    for(int r = 0; r < rows; r++)
    {
        /*|0算法ID|1算法名称|2服务类型|3依赖模型1|4依赖label1|5依赖模型2|6依赖label2|7依赖模型3|8依赖label3|*/
        QString algId = ui->tableView_gc->model()->index(r,0).data().toString();
        QString algName = ui->tableView_gc->model()->index(r,1).data().toString();
        QString serverType = ui->tableView_gc->model()->index(r,2).data().toString();
        QString depModel1 = ui->tableView_gc->model()->index(r,3).data().toString();
        QString depLabel1 = ui->tableView_gc->model()->index(r,4).data().toString();
        QString depModel2 = ui->tableView_gc->model()->index(r,5).data().toString();
        QString depLabel2 = ui->tableView_gc->model()->index(r,6).data().toString();
        QString depModel3 = ui->tableView_gc->model()->index(r,7).data().toString();
        QString depLabel3 = ui->tableView_gc->model()->index(r,8).data().toString();

        xmlWriter.writeEmptyElement("algo");
        xmlWriter.writeAttribute("algId", algId);
        xmlWriter.writeAttribute("algName", algName);
        xmlWriter.writeAttribute("serverType", serverType);
        xmlWriter.writeAttribute("depModel1", depModel1);
        xmlWriter.writeAttribute("depLable1", depLabel1);
        xmlWriter.writeAttribute("depModel2", depModel2);
        xmlWriter.writeAttribute("depLable2", depLabel2);
        xmlWriter.writeAttribute("depModel3", depModel3);
        xmlWriter.writeAttribute("depLable3", depLabel3);
    }

    xmlWriter.writeEndElement();//algolist

    xmlWriter.writeStartElement("modelMap");

    for(auto& model:m_modelRename)
    {
        //第一次修改后的值,第二次修改前的值
        auto& modName = model.first;
        auto& reName = model.second;

        xmlWriter.writeEmptyElement("model");
        xmlWriter.writeAttribute("modelName", modName);
        xmlWriter.writeAttribute("reName", reName);
    }
    xmlWriter.writeEndElement();//modelMap

    xmlWriter.writeEndElement(); // baseConfig
    xmlWriter.writeEndDocument();

    file.close();
    qDebug() << "XML file generated successfully.";
}

4.2 QXmlStreamWriter实现读取XML

#include <QXmlStreamReader>
struct DepAllModelInfo{
    QString m_model1;
    QString m_label1;
    QString m_model2;
    QString m_label2;
    QString m_model3;
    QString m_label3;
};
using depModel = std::vector<DepModelInfo>;
struct algInfo{
    QString m_alg_name;
    QString m_server_type;
    DepAllModelInfo m_dep_model;
};
using algFullCapacity = std::map<QString,algInfo>;
/*以上是读取config.xml文件结构在程序中的数据结构*/
void genConfForm::loadXmlFile()
{
    algFullCapacity afc;
    QFile file("config.xml");
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
        qDebug() << "Failed to open file for reading.";
        return;
    }

    QXmlStreamReader xmlReader(&file);

    while (!xmlReader.atEnd() && !xmlReader.hasError()) {
        // Read next element
        QXmlStreamReader::TokenType token = xmlReader.readNext();
        // If token is just StartDocument, we'll go to next
        if (token == QXmlStreamReader::StartDocument) {
            continue;
        }
        // If token is StartElement - read it
        if (token == QXmlStreamReader::StartElement)
        {
            if (xmlReader.name() == "algo")
            {
                DepAllModelInfo dam;
                QXmlStreamAttributes attributes = xmlReader.attributes();
                QString algId = attributes.value("algId").toString();
                QString algName = attributes.value("algName").toString();
                QString serverType = attributes.value("serverType").toString();
                dam.m_model1 = attributes.value("depModel1").toString();
                dam.m_label1 = attributes.value("depLable1").toString();
                dam.m_model2 = attributes.value("depModel2").toString();
                dam.m_label2 = attributes.value("depLable2").toString();
                dam.m_model3 = attributes.value("depModel3").toString();
                dam.m_label3 = attributes.value("depLable3").toString();

                if(!algId.isEmpty() && !algName.isEmpty())
                {
                    afc.insert(std::pair<QString,algInfo>(algId, {algName,serverType,dam}));
                }
            }
            if (xmlReader.name() == "model")
            {
                QXmlStreamAttributes attributes = xmlReader.attributes();
                QString dbModelName = attributes.value("modelName").toString();
                QString modifyName = attributes.value("reName").toString();
                m_modelRename.insert(std::pair<QString,QString>(dbModelName,modifyName));
            }
        }
    }

    if(!afc.empty())
        slotAlgInfo(afc);

    if (xmlReader.hasError()) {
        qDebug() << "XML error: " << xmlReader.errorString();
    }

    file.close();
}

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

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

相关文章

(五)MySQL的备份及恢复

1、MySQL日志管理 在数据库保存数据时&#xff0c;有时候不可避免会出现数据丢失或者被破坏&#xff0c;这样情况下&#xff0c;我们必须保证数据的安全性和完整性&#xff0c;就需要使用日志来查看或者恢复数据了 数据库中数据丢失或被破坏可能原因&#xff1a; 误删除数据…

二进制安全虚拟机Protostar靶场(6)堆的简单介绍以及实战 heap1

前言 这是一个系列文章&#xff0c;之前已经介绍过一些二进制安全的基础知识&#xff0c;这里就不过多重复提及&#xff0c;不熟悉的同学可以去看看我之前写的文章 程序静态分析 https://exploit.education/protostar/heap-one/#include <stdlib.h> #include <unis…

笔记本键盘卸载或自动跳出字符故障或按键无效修复办法

首先&#xff0c;在Windows 10操作系统中&#xff0c;您可以在笔记本电脑桌面上找到"计算机"图标&#xff0c;并使用鼠标右键点击它。然后选择"属性"选项。 打开系统属性后&#xff0c;您会看到右上角有一个"设备管理器"选项。请点击它来打开设…

Vim实战:使用Vim实现图像分类任务(一)

文章目录 摘要安装包安装timm 数据增强Cutout和MixupEMA项目结构编译安装Vim环境环境安装过程安装库文件 计算mean和std生成数据集 摘要 论文&#xff1a;https://arxiv.org/pdf/2401.09417v1.pdf 翻译&#xff1a; 近年来&#xff0c;随着深度学习的发展&#xff0c;视觉模型…

适用于 Mac 的 9 款最佳数据恢复软件列表

查看 2024 年 Mac 最佳数据恢复软件的完整列表&#xff0c;并随时恢复您想要的任何类型的数据。 “我们只是人类&#xff0c;我们应该犯错误”。这句话适用于生活的各个方面。错误是会发生的&#xff0c;正是错误使你成为人。 您可以使用 Mac 在线传输内容、上网、工作、玩游…

在Mixamo网站上,下载的动画导入unity给自己的模型添加后出错怎么解决

在Mixamo网站上&#xff0c;下载的动画导入unity给自己的模型添加后出错 一、在Mixamo下载的模型可以正常使用二、在自己的模型和unity自带模型上就出错1.解决方法2.解决成功 注意 一、在Mixamo下载的模型可以正常使用 二、在自己的模型和unity自带模型上就出错 1.解决方法 选…

asp.net core监听本地ip地址

开发asp.net core的时候遇到一个问题我想提供访问供其他同事测试&#xff0c;但是默认都是localhost或者127.0.0.1。我想换成我的Ip地址访问但是不行&#xff0c;百度搜索需要更换监听的地址即修改launchSettings.json&#xff0c;修改为0.0.0.0:5248&#xff0c;这样不管local…

数据结构——用Java实现二分搜索树

目录 一、树 二、二分搜索树 1.二叉树 2.二分搜索树 三、代码实现 1.树的构建 2.获取树中结点的个数 3.添加元素 4.查找元素 &#xff08;1&#xff09;查找元素是否存在 &#xff08;2&#xff09;查找最小元素 &#xff08;3&#xff09;查找最大元素 5.二分搜索…

数字美妆技术:美颜SDK和动态贴纸技术的崭新时代

数字美妆的兴起标志着人们对于自身形象的追求不再局限于现实生活&#xff0c;而是延伸到了虚拟世界。同时&#xff0c;美颜SDK的动态贴纸技术也开始进入到大家的视野之中。 一、美颜SDK&#xff1a;技术之作 通过复杂的图像处理算法&#xff0c;美颜SDK能够实时检测人脸&…

Lua语法基本使用

&#x1f353; 简介&#xff1a;java系列技术分享(&#x1f449;持续更新中…&#x1f525;) &#x1f353; 初衷:一起学习、一起进步、坚持不懈 &#x1f353; 如果文章内容有误与您的想法不一致,欢迎大家在评论区指正&#x1f64f; &#x1f353; 希望这篇文章对你有所帮助,欢…

【网络基础】IP

IP协议报头 4位版本号(version): 指定IP协议的版本, 对于IPv4来说, 就是4.4位头部长度(header length): IP头部的长度是多少个32bit, 也就是 length * 4 的字节数. 4bit表示最大的数字是15, 因此IP头部最大长度是60字节. 8位服务类型(Type Of Service): 3位优先权字段(已经弃用…

网络空间搜索引擎

随着互联网、物联网、传感网、社交网络等信息系统所构成的泛在网络不断 发展&#xff0c;网络终端设备数量呈指数级上升。这为企业进行终端设备资产清点和统一 管控带来了巨大挑战&#xff0c;同时也引发了一系列安全问题&#xff0c;网络攻击与防御的博弈从 单边代码漏洞发展到…

SpringMVC 自动配置

SpringMVC 自动配置 一、WebMvcAutoConfiguration&#xff08;SpringMVC自动配置&#xff09;二、DisPatcherServletAutoConfiguration.class&#xff08;中央调度器自动配置&#xff09;三、WebMvcConfigurationSupport&#xff08;SpringMVC组件配置类&#xff09;四、Servle…

RHCE 搭建DNS域名解析服务器

目录 一、前述 1、BIND&#xff08;Berkeley Internet Name Domain&#xff09; 2、bind服务中三个关键文件 1&#xff09;主配置文件/etc/named.conf 2&#xff09;区域配置文件/etc/named.rfc1912.zones 正向解析 反向解析 3&#xff09;数据配置文件目录/var/named/…

STM32 1-5

目录 STM32简介 点亮PC13LED GPIO LED闪烁 LED流水灯 按键控制LED 光敏传感器控制蜂鸣器 OLED调试工具 OLED显示 EXTI外部中断 对射式红外传感器计次 旋转编码器计次 继续 STM32简介 点亮PC13LED main.c #include "stm32f10x.h" // D…

Hadoop-MapReduce-YarnChild启动篇

一、源码下载 下面是hadoop官方源码下载地址&#xff0c;我下载的是hadoop-3.2.4&#xff0c;那就一起来看下吧 Index of /dist/hadoop/core 二、上下文 在上一篇<Hadoop-MapReduce-MRAppMaster启动篇>中已经将到&#xff1a;MRAppMaster的启动&#xff0c;那么运行M…

如何让wordpress首页只显示某一篇文章全部内容?在您的主页显示选择

大多数WordPress站点首页默认都是显示最新发布的文章列表&#xff0c;不过有些站点比较特殊&#xff0c;只想显示某一篇文章的全部内容&#xff0c;那么应该怎么设置呢&#xff1f; 其实&#xff0c;WordPress后台 >> 设置 >> 阅读 >> 在“您的主页显示”中…

VS+QT 配置Eigen库

1、下载Eigen库&#xff0c;如下&#xff1a; 2、解压到项目目录下&#xff0c;如下&#xff1a; 3、 在C/C中包含文件&#xff0c;如下&#xff1a; 4、在头文件中加入如下代码&#xff1a; 5、测试代码&#xff1a; //.cpp文件 #include "testEigen.h"testEigen::…

【Python】03快速上手爬虫案例三:搞定药师帮

文章目录 前言1、破解验证码2、获取数据 前言 流程&#xff1a;通过用户名、密码、搞定验证码&#xff0c;登录进药师帮网站&#xff0c;然后抓取想要的数据。 爬取数据&#xff0c;最终效果图&#xff1a; 1、破解验证码 使用药师帮测试系统&#xff1a;https://dianrc.ysb…

快速入门存内计算—助力人工智能加速深度学习模型的训练和推理

存内计算&#xff1a;提高计算性能和能效的新技术 传统的计算机架构是将数据存储在存储器中&#xff0c;然后将数据传输到计算单元进行处理。这种架构存在一个性能瓶颈&#xff0c;即数据传输延迟。存内计算通过将计算单元集成到存储器中&#xff0c;消除了数据传输延迟&#…