Qt C++ 解析和处理 XML 文件示例

使用 Qt C++ 解析和处理 XML 文件

以下是使用 Qt C++ 实现 XML 文件处理的几种方法,包括解析、创建和修改 XML 文件。

1. 使用 QXmlStreamReader (推荐方式)

#include <QFile>
#include <QXmlStreamReader>
#include <QDebug>void parseXmlWithStream(const QString &filePath) {QFile file(filePath);if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {qDebug() << "无法打开文件:" << filePath;return;}QXmlStreamReader xml(&file);while (!xml.atEnd()) {xml.readNext();if (xml.isStartElement()) {qDebug() << "开始元素:" << xml.name();// 打印所有属性for (const auto &attr : xml.attributes()) {qDebug() << "  属性:" << attr.name() << "=" << attr.value();}} else if (xml.isEndElement()) {qDebug() << "结束元素:" << xml.name();} else if (xml.isCharacters() && !xml.isWhitespace()) {qDebug() << "文本内容:" << xml.text().trimmed();}}if (xml.hasError()) {qDebug() << "XML 解析错误:" << xml.errorString();}file.close();
}// 使用示例
int main() {parseXmlWithStream("example.xml");return 0;
}

2. 使用 QDomDocument (DOM 方式)

#include <QDomDocument>
#include <QFile>
#include <QDebug>void parseXmlWithDom(const QString &filePath) {QFile file(filePath);if (!file.open(QIODevice::ReadOnly)) {qDebug() << "无法打开文件:" << filePath;return;}QDomDocument doc;if (!doc.setContent(&file)) {qDebug() << "无法解析 XML 文件";file.close();return;}file.close();QDomElement root = doc.documentElement();qDebug() << "根元素:" << root.tagName();// 递归遍历所有节点std::function<void(const QDomNode &, int)> traverseNode = [&traverseNode](const QDomNode &node, int indent) {QDomNode n = node;while (!n.isNull()) {qDebug().noquote() << QString(indent, ' ') << "节点:" << n.nodeName();if (n.isElement()) {QDomElement e = n.toElement();if (e.hasAttributes()) {QDomNamedNodeMap attrs = e.attributes();for (int i = 0; i < attrs.length(); ++i) {QDomNode attr = attrs.item(i);qDebug().noquote() << QString(indent+2, ' ') << "属性:" << attr.nodeName() << "=" << attr.nodeValue();}}}if (n.hasChildNodes()) {QDomNode child = n.firstChild();while (!child.isNull()) {if (child.isText()) {QString text = child.nodeValue().trimmed();if (!text.isEmpty()) {qDebug().noquote() << QString(indent+2, ' ') << "文本:" << text;}} else {traverseNode(child, indent+2);}child = child.nextSibling();}}n = n.nextSibling();}};traverseNode(root.firstChild(), 0);
}// 使用示例
int main() {parseXmlWithDom("example.xml");return 0;
}

3. 解析 Qt UI 文件示例

#include <QDomDocument>
#include <QFile>
#include <QDebug>void parseUiFile(const QString &uiFile) {QFile file(uiFile);if (!file.open(QIODevice::ReadOnly)) {qDebug() << "无法打开 UI 文件:" << uiFile;return;}QDomDocument doc;if (!doc.setContent(&file)) {qDebug() << "无法解析 UI 文件";file.close();return;}file.close();QDomElement root = doc.documentElement();// 查找所有 widget 元素QDomNodeList widgets = root.elementsByTagName("widget");qDebug() << "找到" << widgets.count() << "个 widget";for (int i = 0; i < widgets.count(); ++i) {QDomElement widget = widgets.at(i).toElement();QString name = widget.attribute("name");QString className = widget.attribute("class");qDebug() << "Widget" << i+1 << ":" << name << "(" << className << ")";}// 查找所有连接QDomNodeList connections = root.elementsByTagName("connection");qDebug() << "\n找到" << connections.count() << "个连接";for (int i = 0; i < connections.count(); ++i) {QDomElement connection = connections.at(i).toElement();QString sender = connection.firstChildElement("sender").text();QString signal = connection.firstChildElement("signal").text();QString receiver = connection.firstChildElement("receiver").text();QString slot = connection.firstChildElement("slot").text();qDebug() << "连接" << i+1 << ":" << sender << "." << signal << "->" << receiver << "." << slot;}
}// 使用示例
int main() {parseUiFile("mainwindow.ui");return 0;
}

4. 创建 Qt XML 文件

#include <QDomDocument>
#include <QFile>
#include <QTextStream>
#include <QDebug>void createQtXml(const QString &outputFile) {QDomDocument doc("QtConfig");// 创建处理指令QDomProcessingInstruction instr = doc.createProcessingInstruction("xml", "version=\"1.0\" encoding=\"UTF-8\"");doc.appendChild(instr);// 创建根元素QDomElement root = doc.createElement("QtSettings");root.setAttribute("version", "1.0");doc.appendChild(root);// 添加窗口设置QDomElement window = doc.createElement("Window");window.setAttribute("name", "MainWindow");root.appendChild(window);QDomElement width = doc.createElement("Width");width.appendChild(doc.createTextNode("800"));window.appendChild(width);QDomElement height = doc.createElement("Height");height.appendChild(doc.createTextNode("600"));window.appendChild(height);// 添加按钮设置QDomElement button = doc.createElement("Button");button.setAttribute("name", "btnOK");root.appendChild(button);QDomElement text = doc.createElement("Text");text.appendChild(doc.createTextNode("OK"));button.appendChild(text);// 保存到文件QFile file(outputFile);if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {qDebug() << "无法写入文件:" << outputFile;return;}QTextStream stream(&file);doc.save(stream, 2);  // 2 表示缩进空格数file.close();qDebug() << "已创建 Qt XML 文件:" << outputFile;
}// 使用示例
int main() {createQtXml("qt_config.xml");return 0;
}

5. 修改 Qt XML 文件

#include <QDomDocument>
#include <QFile>
#include <QTextStream>
#include <QDebug>void modifyQtXml(const QString &inputFile, const QString &outputFile) {QFile file(inputFile);if (!file.open(QIODevice::ReadOnly)) {qDebug() << "无法打开文件:" << inputFile;return;}QDomDocument doc;if (!doc.setContent(&file)) {qDebug() << "无法解析 XML 文件";file.close();return;}file.close();QDomElement root = doc.documentElement();// 修改所有 Button 元素的文本QDomNodeList buttons = root.elementsByTagName("Button");for (int i = 0; i < buttons.count(); ++i) {QDomElement button = buttons.at(i).toElement();QDomElement textElem = button.firstChildElement("Text");if (!textElem.isNull()) {QDomNode textNode = textElem.firstChild();textNode.setNodeValue("New Text");}}// 添加新元素QDomElement newButton = doc.createElement("Button");newButton.setAttribute("name", "btnCancel");QDomElement newText = doc.createElement("Text");newText.appendChild(doc.createTextNode("Cancel"));newButton.appendChild(newText);root.appendChild(newButton);// 保存修改QFile outFile(outputFile);if (!outFile.open(QIODevice::WriteOnly | QIODevice::Text)) {qDebug() << "无法写入文件:" << outputFile;return;}QTextStream stream(&outFile);doc.save(stream, 2);outFile.close();qDebug() << "已修改并保存到:" << outputFile;
}// 使用示例
int main() {modifyQtXml("qt_config.xml", "qt_config_modified.xml");return 0;
}

6. 使用 SAX 解析器 (QXmlSimpleReader)

#include <QXmlSimpleReader>
#include <QXmlInputSource>
#include <QFile>
#include <QDebug>class MyXmlHandler : public QXmlDefaultHandler {
public:bool startElement(const QString &namespaceURI, const QString &localName,const QString &qName, const QXmlAttributes &attributes) override {qDebug() << "开始元素:" << qName;for (int i = 0; i < attributes.count(); ++i) {qDebug() << "  属性:" << attributes.qName(i) << "=" << attributes.value(i);}return true;}bool endElement(const QString &namespaceURI,const QString &localName,const QString &qName) override {qDebug() << "结束元素:" << qName;return true;}bool characters(const QString &ch) override {QString text = ch.trimmed();if (!text.isEmpty()) {qDebug() << "文本内容:" << text;}return true;}bool fatalError(const QXmlParseException &exception) override {qDebug() << "XML 解析错误:" << exception.message();return false;}
};void parseXmlWithSax(const QString &filePath) {QFile file(filePath);if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {qDebug() << "无法打开文件:" << filePath;return;}QXmlSimpleReader reader;MyXmlHandler handler;reader.setContentHandler(&handler);reader.setErrorHandler(&handler);QXmlInputSource source(&file);if (!reader.parse(&source)) {qDebug() << "解析失败";}file.close();
}// 使用示例
int main() {parseXmlWithSax("example.xml");return 0;
}

总结

  1. QXmlStreamReader - 流式解析器,内存效率高,适合大文件
  2. QDomDocument - DOM 解析器,适合小文件,便于随机访问和修改
  3. SAX 解析器 - 事件驱动模型,适合只需读取不需要修改的情况
  4. 对于 Qt UI 文件,可以使用上述任意方法解析

选择建议:

  • 大文件或只需顺序读取 → QXmlStreamReader
  • 需要频繁修改或随机访问 → QDomDocument
  • 特殊需求或性能关键 → SAX 解析器

from PyQt5.QtCore import QFile, QIODevice, QXmlStreamReaderdef parse_xml_with_stream(file_path):file = QFile(file_path)if not file.open(QIODevice.ReadOnly | QIODevice.Text):print(f"无法打开文件: {file_path}")returnxml = QXmlStreamReader(file)while not xml.atEnd():xml.readNext()if xml.isStartElement():print(f"开始元素: {xml.name()}")# 打印所有属性for attr in xml.attributes():print(f"  属性: {attr.name()} = {attr.value()}")elif xml.isEndElement():print(f"结束元素: {xml.name()}")elif xml.isCharacters() and not xml.isWhitespace():print(f"文本内容: {xml.text().strip()}")if xml.hasError():print(f"XML 解析错误: {xml.errorString()}")file.close()if __name__ == "__main__":# 替换为你的 XML 文件路径xml_file_path = r"D:\shawei\temp\jpbalance\temp\TaskTemplates\Shock Pulse.xml"parse_xml_with_stream(xml_file_path)
import xml.etree.ElementTree as ETdef parse_xml_with_et(file_path):try:tree = ET.parse(file_path)root = tree.getroot()# 命名空间处理ns = {'cm': 'http://www.pruftechnik.com/cm'}print("=== 任务模板 ===")print(f"版本: {root.get('version')}")print(f"任务ID: {root.get('task_id')}")print(f"名称: {root.get('name')}")print(f"来源: {root.get('source')}")meas_setup = root.find('cm:meas_setup', ns)print("\n=== 测量设置 ===")print(f"类型: {meas_setup.get('kind')}")spectrum = meas_setup.find('cm:spectrum', ns)print("\n=== 频谱配置 ===")print(f"名称: {spectrum.get('name')}")print(f"资源ID: {spectrum.get('res_id')}")print(f"量值: {spectrum.get('quant')}")print(f"线数: {spectrum.get('lines')}")print(f"窗函数: {spectrum.get('window')}")time_waveform = spectrum.find('cm:time_waveform_config', ns)print("\n=== 时域波形配置 ===")print(f"名称: {time_waveform.get('name')}")print(f"资源ID: {time_waveform.get('res_id')}")print(f"量值: {time_waveform.get('quant')}")average = spectrum.find('cm:average', ns)print("\n=== 平均设置 ===")print(f"平均次数: {average.get('num')}")print(f"重叠率: {average.get('overlap')}%")print(f"因子: {average.get('factor')}")print(f"类型: {average.get('type')}")freq_spectrum = spectrum.find('cm:freq_spectrum', ns)print("\n=== 频谱范围 ===")print(f"最大频率: {freq_spectrum.get('max')}Hz")print(f"最大类型: {freq_spectrum.get('max_type')}")print(f"最小频率: {freq_spectrum.get('min')}Hz")except ET.ParseError as e:print(f"XML 解析错误: {e}")except Exception as e:print(f"发生错误: {e}")if __name__ == "__main__":xml_file_path = r"D:\shawei\temp\jpbalance\temp\TaskTemplates\Shock Pulse.xml"parse_xml_with_et(xml_file_path)

<?xml version="1.0" encoding="UTF-8"?>
<task_template xmlns="http://www.xxxx.com/cm" version="4.0.0" task_id="00000000-0000-0000-0000-000000000003" name="Spec (a) 10Hz - 12800Hz" source="factory"><meas_setup kind="trending_spectrum_amplitude"><spectrum name="Spectrum Velocity" res_id="00000000-0000-0000-0000-000000000002" quant="acc" lines="51200" window="hanning"><time_waveform_config name="Time Waveform Velocity" res_id="00000000-0000-0000-0000-000000000001" quant="acc"/><average num="3" overlap="60" factor="0.5" type="lin"/><freq_spectrum max="12800" max_type="time_based" min="10"/></spectrum></meas_setup>
</task_template>
#include <QCoreApplication>
#include <QFile>
#include <QXmlStreamReader>
#include <QDebug>void parseTaskTemplateXml(const QString &filePath) {QFile file(filePath);if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {qDebug() << "无法打开文件:" << filePath;return;}QXmlStreamReader xml(&file);while (!xml.atEnd() && !xml.hasError()) {xml.readNext();if (xml.isStartElement()) {QString elementName = xml.name().toString();if (elementName == "task_template") {qDebug() << "=== 任务模板 ===";qDebug() << "命名空间:" << xml.namespaceUri();qDebug() << "版本:" << xml.attributes().value("version").toString();qDebug() << "任务ID:" << xml.attributes().value("task_id").toString();qDebug() << "名称:" << xml.attributes().value("name").toString();qDebug() << "来源:" << xml.attributes().value("source").toString();}else if (elementName == "meas_setup") {qDebug() << "\n=== 测量设置 ===";qDebug() << "类型:" << xml.attributes().value("kind").toString();}else if (elementName == "spectrum") {qDebug() << "\n=== 频谱配置 ===";qDebug() << "名称:" << xml.attributes().value("name").toString();qDebug() << "资源ID:" << xml.attributes().value("res_id").toString();qDebug() << "量值:" << xml.attributes().value("quant").toString();qDebug() << "线数:" << xml.attributes().value("lines").toString();qDebug() << "窗函数:" << xml.attributes().value("window").toString();}else if (elementName == "time_waveform_config") {qDebug() << "\n=== 时域波形配置 ===";qDebug() << "名称:" << xml.attributes().value("name").toString();qDebug() << "资源ID:" << xml.attributes().value("res_id").toString();qDebug() << "量值:" << xml.attributes().value("quant").toString();}else if (elementName == "average") {qDebug() << "\n=== 平均设置 ===";qDebug() << "平均次数:" << xml.attributes().value("num").toString();qDebug() << "重叠率:" << xml.attributes().value("overlap").toString() << "%";qDebug() << "因子:" << xml.attributes().value("factor").toString();qDebug() << "类型:" << xml.attributes().value("type").toString();}else if (elementName == "freq_spectrum") {qDebug() << "\n=== 频谱范围 ===";qDebug() << "最大频率:" << xml.attributes().value("max").toString() << "Hz";qDebug() << "最大类型:" << xml.attributes().value("max_type").toString();qDebug() << "最小频率:" << xml.attributes().value("min").toString() << "Hz";}}}if (xml.hasError()) {qDebug() << "XML 解析错误:" << xml.errorString();}file.close();
}int main(int argc, char *argv[]) {QCoreApplication a(argc, argv);parseTaskTemplateXml("task_template.xml");return a.exec();
}

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

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

相关文章

坐标上海,20~40K的面试强度

继续分享最新的面经&#xff0c;面试的岗位是上海某公司的Golang开发岗&#xff0c;给的薪资范围是20~40K&#xff0c;对mongodb要求熟练掌握&#xff0c;所以面试过程中对于mongodb也问的比较多。 下面是我整理好的面经&#xff08;去除了项目相关的问题&#xff09;&#xf…

B端管理系统:企业运营的智慧大脑,精准指挥

B端管理系统的定义与核心功能 B端管理系统&#xff08;Business Management System&#xff09;是专门设计用于支持企业内部运作和外部业务交互的一套软件工具。它集成了多种功能模块&#xff0c;包括但不限于客户关系管理(CRM)、供应链管理(SCM)、人力资源管理(HRM)以及财务管…

IDE中使用Spring Data Redis

步骤一&#xff1a;导入Spring Data Redis的maven坐标 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency> 步骤二&#xff1a;配置Redis数据源 步骤三&…

ARINC818协议的帧格式

SOFi:sof initiale;这个是第一个ADVB帧的SOF开始&#xff0c;一帧只有一个SOFi。 SOFn:sof normal;这个是非首个ADVB帧的SOF头的normal头。 Vsync为场同步&#xff0c;两个SOFi之间为Vsync信号&#xff0c;也就是一帧&#xff0c;也就是VS信号。 Hsync为行同步&#xff0c;如果…

Git核心命令

Git核心命令完全指南&#xff1a;从入门到高效协作 前言 在软件开发领域&#xff0c;Git已成为现代版本控制的代名词。据统计&#xff0c;全球超过90%的开发团队使用Git进行代码管理。然而&#xff0c;许多开发者仅停留在基础命令的机械使用层面&#xff0c;未能真正掌握Git命…

【计算机视觉】CV实战项目- Face-and-Emotion-Recognition 人脸情绪识别

Face-and-Emotion-Recognition 项目详细介绍 项目概述项目功能项目目录结构项目运行方式1. 环境准备2. 数据准备3. 模型训练4. 模型运行 常见问题及解决方法1. **安装依赖问题**2. **数据集问题**3. **模型训练问题**4. **模型运行问题** 项目实战建议项目参考文献 项目概述 F…

java lambda

案例1 lambda表达式看做成一个函数对象 方法引用 1.Math是类型&#xff0c;max是静态方法 2.Student是对象&#xff0c;getName是非静态方法 3.对象&#xff1a;&#xff1a;非静态方法 4.类型&#xff1a;&#xff1a;new关键字 练习1 假设已有对象 常见函数接口 predicate…

并发网路通信-套接字通信

套接字通信就是网络通信 在网络通信时,客户端和服务器的比例是N:1 服务器如何处理多个客户端的请求 并发处理方式 1.多线程并发处理->线程池并发处理,线程池可以对多个线程进行管理 2.多进程->进程池 3.io多路转接,使用select或者epoch进行处理,使用io转接函数…

AI当前状态:有哪些新技术

一、到目前为址AI领域出现的新技术 到目前为止&#xff0c;AI领域涌现了许多令人兴奋的新技术。以下是一些关键的进展&#xff0c;涵盖了从基础模型到实际应用的多个方面&#xff1a; 1. 更强大的大型语言模型 (LLMs): 性能提升: 新一代LLM&#xff0c;例如OpenAI的GPT-4o和…

AI与IT的共生

AI并非“职业终结者”&#xff0c;而是IT从业者的“认知杠杆”。通过工具化协作、技能升级与伦理治理&#xff0c;人类可释放创造力&#xff0c;探索量子计算、生物启发算法等深水区。未来的IT行业将呈现“AI赋能人类&#xff0c;人类定义AI边界”的共生格局。 一、AI如何改变…

swagger的简介及使用方法

Swagger 是一个用于描述、生成、文档化和测试 RESTful API 的开源工具集。它可以自动生成 API 文档&#xff0c;帮助开发者理解和使用 API。Swagger 由 Swagger.io 提供&#xff0c;并已经发展成了一套广泛应用于 API 设计和文档的标准。 Swagger 项目的历史可以追溯到 2010 年…

解决Flutter 2.10.5在升级Xcode 16后的各种报错

Flutter 环境 Flutter version 2.10.5Dart version 2.16.2DevTools version 2.9.2CocoaPods version 1.16.2Xcode 16.3 问题一&#xff1a;XCResult parsing error: Error: This command is deprecated and will be removed in a future release, --legacy flag is required t…

Vue + Spring Boot 整合全解析

一、引言 在当今的Web开发领域&#xff0c;前后端分离架构已成为主流。Vue.js作为一款流行的前端框架&#xff0c;以其简洁易用和高效的特点深受开发者喜爱&#xff1b;Spring Boot则是Java后端开发中快速构建应用的利器。将Vue和Spring Boot整合&#xff0c;能够充分发挥两者…

PDF.js 生态中如何处理“添加注释\添加批注”以及 annotations.contents 属性

我们来详细解释一下在 PDF.js 生态中如何处理“添加注释”以及 annotations.contents 属性。 核心要点&#xff1a;PDF.js 本身主要是阅读器&#xff0c;不是编辑器 首先&#xff0c;最重要的一点是&#xff1a;PDF.js 的核心库 (pdfjs-dist) 主要设计用于解析和渲染&#xf…

当HTTP遇到SQL注入:Java开发者的攻防实战手册

一、从HTTP请求到数据库查询:漏洞如何产生? 危险的参数拼接:Servlet中的经典错误 漏洞代码重现: public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {String category = request.getParameter("…

【grafana原生告警中心配置飞书机器人告警】

在grafana中的connect point中使用webhook的方式推送到飞书&#xff0c;始终无法触发告警&#xff0c;原因是grafana推送的格式飞书不识别&#xff0c;现有两种方式 1.使用中转服务 使用flask搭建一个服务&#xff0c;grafana告警先通过webhook发送到web服务中&#xff0c;格…

kafka集群认证

1、安装Kerberos(10.10.10.168) yum install krb5-server krb5-workstation krb5-libs -y ​ 查看版本 klist -V ​ Kerberos 5 version 1.20.1 ​ 编辑/etc/hosts 10.10.10.168 ms1 10.10.10.150 ms2 10.10.10.110 ms3 vim /etc/krb5.conf # Configuration snippets ma…

前端工程化之自动化测试

自动化测试 自动化测试为什么需要测试&#xff1f;什么时候需要考虑测试测试类型前端测试框架单元测试Jest 重点掌握项目示例package.jsonsrc/utils/math.tssrc/utils/math.test.ts进行测试jest.config.js覆盖率直观看覆盖率coverage/lcov-report/index.html src/main.test.tst…

分布式系统核心原理

CAP定理与权衡实践 CAP定理 一致性&#xff08;Consistency&#xff09; 强一致性&#xff1a;所有读写操作均基于最新数据&#xff08;如银行转账&#xff09;。 最终一致性&#xff1a;数据副本经过一段时间后达到一致&#xff08;如社交媒体的点赞数&#xff09;。 技术实现…

Step文件无法编辑怎么办?

Step文件无法编辑怎么办&#xff1f; 这里介绍两种方法&#xff0c; 1、 直接导入 准备step文件&#xff0c;solidworks导入后是这样&#xff0c;不能在上面直接编辑 图 1 点击右键&#xff0c;选择解除特征&#xff08;不同版本的可能不太一样&#xff0c;这里是solidworks2…