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…

python17-Python的字符串格式化

Python提供了“%”对各种类型的数据进行格式化输出,例如如下代码。 # !/usr/bin/env python# -*- coding: utf-8 -*-# @Time : 2024/01# @Author : Laopiweight = 180print(老师傅的体重是 %s % weight) 上面程序就是格式化输出的关键代码,这行代码中的 print 函数包含三个部…

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…

mysql学习打卡day19

今日成果&#xff1a; update invoices set payment_total invoice_total *0.5,payment_date due_date where invoice_id 1; -- 更新单行记录 update orders set comments 金牌顾客 where customer_id in (select customer_id from customers where points > 3000); --…

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

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

如何将抖音API应用于抖音视频的录制和上传

抖音API允许开发者进行二次开发&#xff0c;使得第三方应用程序可以与抖音进行交互。要将抖音API应用于抖音视频的录制和上传&#xff0c;你需要遵循以下步骤&#xff1a; 获取抖音API密钥&#xff1a;首先&#xff0c;你需要从抖音官网注册一个开发者账号&#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 使用 …

TDengine 签约海博思创,助力储能运维平台数据管理

随着储能产业步入快速发展期&#xff0c;各类储能电站快速建设投产&#xff0c;规模各异&#xff0c;场景不同。为了实现储能电站的高效监控和运维管理&#xff0c;储能运维管理平台成为不可或缺的工具。通过高效的集中控制手段&#xff0c;这些平台能够有效解决储能电站运维成…

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

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

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

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

python18-Python的字符串序列相关方法

字符串本质上就是由多个字符组成的,因此程序允许通过索引来操作字符,比如获取指定索引处的字符,获取指定字符在字符串中的位置等。 Python字符串直接在方括号([])中使用索引即可获取对应的字符,字符串中第一个字符的索引为0、第二个字符的索引为1,后面各字符依此类推。 …

数据库管理-第138期 数据库国产化是Office换WPS么(20240124)

数据库管理138期 2024-01-24 第138期 数据库国产化是Office换WPS么&#xff08;20240124&#xff09;1 背景2 现实3 方法论总结 第138期 数据库国产化是Office换WPS么&#xff08;20240124&#xff09; 作者&#xff1a;胖头鱼的鱼缸&#xff08;尹海文&#xff09; Oracle ACE…

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

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

Python 一些常见的字符串操作

常见的字符串操作有&#xff1a; 创建字符串&#xff1a; # 使用单引号创建字符串 s1 Hello, World!# 使用双引号创建字符串 s2 "Python Programming"# 使用三引号创建多行字符串 s3 This is a multi-line string.访问字符串中的字符&#xff1a; s Hello, World…

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

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

业务逐字稿

1.WEB端旅游线路发布模块 旅游公司在Web端点击新增旅游线路按钮&#xff0c;浏览器请求发送到Nginx&#xff0c;Nginx反向代理到网关&#xff0c;网关去找微服务&#xff0c;微服务实现具体的旅游线路发布功能 旅游公司工作人员在Web端点击新增旅游线路按钮&#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;…