QT 使用XML保存操作记录

文章目录

  • 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 elementQDomElement root = document.createElement("baseConfig");// Making elements of algolistQDomElement 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 modelMapQDomElement 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 fileQFile 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();//algolistxmlWriter.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();//modelMapxmlWriter.writeEndElement(); // baseConfigxmlWriter.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 elementQXmlStreamReader::TokenType token = xmlReader.readNext();// If token is just StartDocument, we'll go to nextif (token == QXmlStreamReader::StartDocument) {continue;}// If token is StartElement - read itif (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.mzph.cn/news/655599.shtml

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

相关文章

【linux】-centos7版本前后-变化篇

1.centos7版本前后区别 首先文件系统变化&#xff0c;由EXT4&#xff0c;变为XFS格式。可支持容量500TB的文件&#xff0c;而6代仅能支持16TB。首个进程变为systemd, 替换了熟悉的init进程。它的特点是功能强大&#xff0c;体积也很强大。 systemd给我们带来了一个全家桶命令&…

【linux】磁盘空间不足-常用排查和处理命令

【linux】磁盘空间不足-常用排查和处理命令 1.通查一下 df -h #查看服务器磁盘空间情况 du -hs * 2>/dev/null #列出各目录所占空间大小 或 du -h -d 1 2>/dev/null #列出各目录所占空间大小 1.1情况一 df 磁盘空间和du 目录空间占用相等&#xff0c…

C# 二分搜索(Binary Search)

二分搜索概念 二分查找也称折半查找&#xff08;Binary Search&#xff09;它是一种效率较高的查找方法。但是&#xff0c;折半查找要求线性表必须采用顺序存储结构&#xff0c;而且表中元素按关键字有序排列。 二分搜索的背景 二分搜索法的概念和思想可以追溯到古代的中国和…

【python】求矩阵的特征值和特征向量

使用np.linalg.eig同时求特征值和特征向量 import numpy as np#输入矩阵 A np.array([[1, 1/2, 1/6, 1/9],[2, 1, 1/3, 1/5],[6, 3,1,1/2],[9, 5,2,1]])#求解特征值和其对应的特征向量 eigval,eigvec np.linalg.eig(A) for i in range(len(eigval)):print(f特征值&#xff1a…

STM32学习笔记一——初识STM32

目录 一、什么是ARM 二. Cortex 内核 三.什么是STM32 四.STM32核心板原理图&#xff1a; 五.STM32的内部结构&#xff1a; 六.stm32系统结构简化图 STM32基本原理分析&#xff1a; 七.典型型号——STM32F103ZET6 stm32——32位单片机&#xff08;数据总线是32位的&am…

文献速递:人工智能医学影像分割--- 深度学习分割骨盆骨骼:大规模CT数据集和基线模型

文献速递&#xff1a;人工智能医学影像分割— 深度学习分割骨盆骨骼&#xff1a;大规模CT数据集和基线模型 我们为大家带来人工智能技术在医学影像分割上的应用文献。 人工智能在医学影像分析中发挥着至关重要的作用&#xff0c;尤其体现在图像分割技术上。这项技术的目的是准…

Golang 流媒体服务器lalserver使用指南

目录 安装 使用 1.推流 2.播放 官方地址 安装 1.下载源码 wget https://github.com/q191201771/lal/releases/download/v0.36.7/lal_v0.36.7_linux.zipunzip lal_v0.36.7_linux.zip cd lal_v0.36.7_linux 2.启动 ./bin/lalserver -c ./conf/lalserver.conf.json 使用 …

浅谈直流电表在韩国充电桩生产厂家的应用

I.背景&#xff1a; 近几年为应对温室气体的排放导致的全球变暖、气候变化等问题,各大国纷纷对焦推进电动汽车&#xff0c;从而减少传统燃油汽车带来的大量温室气体排放。而推进新能源汽车的各项举措之中&#xff0c;充电桩的基础建设&#xff0c;又是其中的重中之重&#xff…

AR眼镜_ar智能眼镜显示方案|光学方案

AR眼镜是一种智能眼镜&#xff0c;能够将虚拟现实和现实世界相结合&#xff0c;使人们能够在日常生活中体验和参与虚拟现实。然而&#xff0c;AR智能眼镜的制造成本高&#xff0c;开发周期长。要实现AR眼镜的各项功能&#xff0c;需要良好的硬件条件&#xff0c;而AR智能眼镜的…

ssl证书更换步骤及更换后有效期没有更新问题

因公司ssl证书到期&#xff0c;在阿里云申请免费证书更换后&#xff0c;查看证书有效期&#xff0c;发现有效期没有更新。 ssl证书更换步骤&#xff1a; 1.下载nginx证书文件 2.服务器上替换原有ssl证书&#xff08;操作前记得备份&#xff09; 3.更改nginx.conf文件中证书路径…

聚势合力 共创高峰”2023思腾合力成都客户答谢会

聚势合力 共创高峰”为主题的思腾合力成都答谢会&#xff0c;在成都都江堰皇冠假日酒店盛大举行&#xff0c;来自各地的客户齐聚于此&#xff0c;共同见证思腾合力的成长与突破&#xff0c;展望未来的合作与发展。 思腾合力总经理王伟热情洋溢的致辞拉开活动序幕。他表达了对所…

wsl-ubuntu 安装 nginx

wsl-ubuntu 安装 nginx 1. 安装 nginx2. 确认 nginx 启动状态3. 重启 nginx4. 停止 nginx 1. 安装 nginx sudo apt install nginx2. 确认 nginx 启动状态 systemctl status nginx3. 重启 nginx systemctl restart nginx4. 停止 nginx systemctl stop nginx完成&#xff01;…

pve宿主机更改网络导致没网,pve更改ip

一、问题描述 快过年了&#xff0c;我把那台一直在用的小型服务器&#xff0c;带回去了&#xff0c;导致网络发生了变更&#xff0c;需要对网络进行调整&#xff0c;否则连不上网&#xff0c;我这里改的是宿主机&#xff0c;不是pve虚拟机中的系统。 二、解决方法 pve用的是…

[GN] 设计模式——面向对象设计原则概述

文章目录 面向对象设计原则概述单一职责原则开闭原则里氏代换原则依赖倒转原则接口隔离原则合成复用原则迪米特法则 总结 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 面向对象设计原则概述 单一职责原则 一个类只负责一个功能领域中的相应职责 类…

蓝桥杯---加法变乘法

我们都知道:123 ….. 491225&#xff0c;现在要求你把其中两个不相邻的加号变成乘号,使得结果为2015 比如&#xff1a;123 ... 10*1112 ... 27*2829 ... 492015 就是符合要求的答案. 请你寻找另外一个可能的答案,并把位置靠前的那个乘号左边的数字提交(对于示例,就是 提交10)…

动手学深度学习(一)深度学习介绍1

目录 一、引言 1.日常生活中的机器学习&#xff1a; 2.机器学习中的关键组件&#xff1a; 2.1 数据&#xff1a; 2.2 模型&#xff1a; 2.3 目标函数&#xff1a; 2.4 优化算法&#xff1a; 3. 各种机器学习问题&#xff1a; 3.1 监督学习&#xff1a; 3.1.1 回归&…

MGRE实验报告二

实验要求&#xff1a; 实验预览图&#xff1a; 实验分析&#xff1a; 1、对R1-R5配置IP地址&#xff0c;同时R1-R5每个路由器各有一个环回 2.1、对R1、R3、R4路由器开启虚拟接口1&#xff0c;分别配置隧道IP、接口封装协议&#xff0c;接口类型、定义封装源、开启伪广播功能&…

cetos7.9 install kubeadmin

第 1 步&#xff1a;禁用 SELinux&#xff08;可选但推荐&#xff09; 如何在 CentOS 7 上查找 SELinux 状态 sestatus另一种选择是运行以下 cat 命令&#xff1a; vi /etc/selinux/config SELINUXdisabled rebootcentos7 linux 安装k8s前下面操作的作用是&#xff1f; cat…

JAVA双列集合Map的特点

一次存一对元素&#xff0c;分别是 键 和 值&#xff0c;他们是一 一对应的&#xff1a;其中&#xff1a;键不可以重复&#xff0c;值可以重复这一对数据叫键值对、键值对对象、或 Entry Map 的体系结构&#xff1a; Map的常见API&#xff1a; 方式的实现&#xff1a;注意 Map …

数据结构----链表介绍、模拟实现链表、链表的使用

文章目录 1. ArrayList存在的问题2. 链表定义2.1 链表的概念及结构2.2 链表的组合类型 3. 链表的实现3.1 单向、不带头、非循环链表的实现3.2 双向、不带头节点、非循环链表的实现 4.LinkedList的使用4.1 什么是LinkedList4.2 LinkedList的使用4.2.1. LinkedList的构造4.2.2. L…