实用指南:QXmlStreamReader、QXmlStreamWriter和QDomElement区别

news/2025/11/23 9:38:31/文章来源:https://www.cnblogs.com/gccbuaa/p/19259516

Qt 框架中这三个用于处理 XML 的核心类:QXmlStreamReaderQXmlStreamWriterQDomElement。它们代表了两种截然不同的 XML 处理哲学。

核心区别概览

特性QXmlStreamReader / QXmlStreamWriterQDomElement
处理模型基于流(Push/Pull)基于树(DOM)
内存使用极低,一次只处理一个节点,整个 XML 文档被加载到内存树中
访问方式顺序、只读(Reader)随机访问,可任意读写节点
性能非常高,适合处理大文件较低,大文件会消耗大量内存和时间
易用性中等,需要手动控制读取状态,API 直观,类似操作树结构
修改 XML不能直接修改,需用 Writer 重新生成可以直接修改 节点内容、属性和结构

详细介绍

1. QXmlStreamReader(基于流的读取器)

哲学:像用望远镜读一个很长的卷轴,你一次只能看到当前的一小部分,但可以非常快地从头读到尾。

工作原理

  • 它逐个读取 XML 令牌,如 StartDocumentStartElementCharacters(文本)、EndElementEndDocument 等。
  • 你通过一个循环来驱动读取过程,并检查当前的 tokenType() 来决定如何处理。
  • 它是 只读单向 的,一旦读过某个节点,就无法再回去访问它(除非重新开始)。

核心优势

  • 内存效率极高:无论 XML 文件有多大(几个GB),它都只占用常量级别的内存,因为它不会在内存中构建整个文档的映像。
  • 速度快:没有构建树结构的开销。

典型使用场景

  • 解析从网络下载的大型 XML 数据(如 RSS 订阅、大型数据库导出文件)。
  • 读取配置文件(虽然 QSettings 更常用,但对于复杂结构,XML 是选择之一)。
  • 任何你只需要顺序读取并提取数据,而不需要随机访问或修改的场合。

代码示例

QFile file("data.xml");
file.open(QIODevice::ReadOnly);
QXmlStreamReader reader(&file);
while (!reader.atEnd()) {
QXmlStreamReader::TokenType type = reader.readNext();
if (type == QXmlStreamReader::StartElement) {
// 遇到开始标签
QString elementName = reader.name().toString();
if (elementName == "book") {
// 读取元素的属性
QString id = reader.attributes().value("id").toString();
qDebug() << "Found book with id:" << id;
} else if (elementName == "title") {
// 读取下一个令牌,它应该是文本内容
reader.readNext();
qDebug() << "Title is:" << reader.text().toString();
}
}
}
if (reader.hasError()) {
qDebug() << "XML error:" << reader.errorString();
}
file.close();

2. QXmlStreamWriter(基于流的写入器)

哲学:像一个抄写员,你告诉他“开始写一个元素,写属性,写文本,结束元素”,他按顺序一笔一划地写下去。

工作原理

  • 你通过调用一系列方法(如 writeStartElement(), writeAttribute(), writeTextElement(), writeEndElement())来按顺序生成 XML。
  • 它负责确保生成的 XML 格式良好(例如,正确关闭标签)。
  • 它不会修改已有的 XML,而是从头开始创建一个新的 XML 流。

核心优势

  • 内存效率高:和 Reader 一样,它在写入过程中不需要在内存中构建整个文档树。
  • 速度快:直接写入输出设备(如文件、网络套接字)。

典型使用场景

  • 导出大量数据为 XML 格式。
  • 生成要发送到网络服务的 XML 请求。
  • QXmlStreamReader 配对使用,用于转换或过滤 XML 数据。

代码示例

QFile file("output.xml");
file.open(QIODevice::WriteOnly);
QXmlStreamWriter writer(&file);
writer.setAutoFormatting(true); // 让输出的 XML 有缩进,更易读
writer.writeStartDocument();
writer.writeStartElement("library");
writer.writeStartElement("book");
writer.writeAttribute("id", "1");
writer.writeTextElement("title", "Qt Programming");
writer.writeTextElement("author", "Max Master");
writer.writeEndElement(); // 结束 book
writer.writeStartElement("book");
writer.writeAttribute("id", "2");
writer.writeTextElement("title", "Advanced C++");
writer.writeTextElement("author", "Alex Expert");
writer.writeEndElement(); // 结束 book
writer.writeEndElement(); // 结束 library
writer.writeEndDocument();
file.close();

3. QDomElement(文档对象模型元素)

哲学:像把一个乐高模型整个拆开,把所有零件都摆在桌子上。你可以随意拿起、修改、移动或组合任何一个零件。

工作原理

  • 首先使用 QDomDocument 将整个 XML 文档加载到内存中,形成一个节点树。
  • QDomElement 是这棵树中的一个节点。你可以通过它来访问其父节点、子节点、兄弟节点、属性和文本。
  • 整个树结构都保留在内存中,允许你进行随机、全方位的访问和修改

核心优势

  • API 直观易用:操作方式非常符合人们对“文档树”的直觉。
  • 功能强大:可以轻松地进行复杂的查询、修改、插入和删除操作。

主要缺点

  • 内存消耗大:整个 XML 树都存储在内存中,对于大文件来说,这可能是个问题。
  • 解析速度慢:构建整个 DOM 树需要时间和内存。

典型使用场景

  • 处理小的、结构复杂的 XML 配置文件。
  • 需要频繁修改 XML 结构或内容的应用程序。
  • 需要随机访问文档中不同部分的场景(例如,根据 ID 查找特定元素)。
  • 对性能要求不苛刻,但追求开发效率的场合。

代码示例

QFile file("data.xml");
file.open(QIODevice::ReadOnly);
QDomDocument doc;
doc.setContent(&file); // 整个文档被解析并加载到内存树中
file.close();
// 获取根元素
QDomElement root = doc.documentElement();
// 查找所有 "book" 标签
QDomNodeList books = root.elementsByTagName("book");
for (int i = 0; i < books.count(); ++i) {
QDomElement book = books.at(i).toElement();
// 读取属性
QString id = book.attribute("id");
// 获取第一个 "title" 子元素的文本
QString title = book.firstChildElement("title").text();
qDebug() << "Book" << id << "title is:" << title;
// 修改:给每个 book 添加一个 price 元素
QDomElement priceElem = doc.createElement("price");
QDomText priceText = doc.createTextNode("29.99");
priceElem.appendChild(priceText);
book.appendChild(priceElem); // 直接修改内存中的树
}
// 将修改后的 DOM 树写回文件
file.open(QIODevice::WriteOnly);
QTextStream out(&file);
doc.save(out, 4); // 缩进为 4
file.close();

总结与如何选择

  • 追求性能和内存效率,处理大文件,只需读取?
    -> 选择 QXmlStreamReader

  • 需要生成(写入)大的 XML 文件?
    -> 选择 QXmlStreamWriter

  • 需要频繁、随机地修改 XML 的结构和内容,且文件不大?
    -> 选择 QDomElement(和 QDomDocument

  • 需要同时满足高性能和随机访问?

    • 可以考虑在 QXmlStreamReader 中只提取关键信息(如 ID)并建立索引,然后有选择地处理。
    • 或者考虑其他第三方库,如 SAX 解析器(Qt 的旧版 QXmlSimpleReader 也属于此类),但 StreamReader 通常是 Qt 中的首选流式解析器。

简单来说,QXmlStreamReader/Writer 是用于 I/O 密集型 任务的跑车,而 QDomElement 是用于复杂操作多功能工程车。根据你的任务需求选择合适的工具,是高效编程的关键。

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

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

相关文章

基础电气知识点梳理

2025/11/23电气基础知识点 交直流与安全 1. 交流电(AC) 电流特性:双向周期性变化 安全电压:36V(适配轻微潮湿环境)、42V(干燥环境上限,依据 GB/T 3805-2008) 摆脱电流:10mA(通用参考上限,成人男性均值约 1…

深入解析:缓存查询逻辑及问题解决

深入解析:缓存查询逻辑及问题解决2025-11-23 09:32 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !impo…

HTML 图片的放大和缩小

<!DOCTYPE html> <html><head><meta charset="utf-8"><title>童心少年</title></head><body><input type="text" onkeydown="keydown(e…

在Odoo中使用阿里云对象存储(OSS)

本章我们来看一下如何在odoo中使用阿里云对象存储(OSS)服务,将Odoo中的附件转存到阿里云对象存储上,以节省我们的服务器硬盘容量。 什么是对象存储 首先我们来了解一下什么是对象存储。 对象存储(Object Storage) 是…

数据科学团队领导指南-全-

数据科学团队领导指南(全)原文:zh.annas-archive.org/md5/0049e7ab941adb9b191a34ead7211805 译者:飞龙 协议:CC BY-NC-SA 4.0第一章:介绍 领导一个数据科学团队面临许多挑战。与组织的其他职能相比,数据科学往…

HTML 大写转小写

<!DOCTYPE html> <html><head><meta charset="utf-8"><title>童心少年</title><script>function asd(){var str=document.getElementById("fname");st…

图片3:字符串属性表

属性描述constructor 返回创建字符串属性的函数length 返回字符串的长度prototype 允许你向对象添加属性和方法

DC-01靶场渗透 - fish666

DC-01靶场渗透 首先,要将靶机和攻击机均设为NAT模式 kali IP 192.168.236.129 开始探寻靶机的ip 192.168.236.130 开启了 22 80 111的端口开始查询资料???111端口,rpcbind 记住一下 下一步,开始访问靶机…

图片2:字符串方法表

Method(方法)描述charAt() 返回指定索引位置的字符charCodeAt() 返回指定索引位置字符的Unicode值concat() 连接两个或多个字符串,返回连接后的字符串fromCharCode() 将指定的Unicode值转换为字符串indexOf() 返回字…

一种45度机翼的重力作用点和气流作用点合一的喷气式飞机

一种45度机翼的重力作用点和气流作用点合一的喷气式飞机 喷气式飞机以高灵活性,高速度而在各种类型的飞机中一枝独秀,要想使一个飞机具有超高速,必须具备大推力的涡扇发动机,以及优秀的外观气动布局。下面介绍一种…

反物质维持下的虫洞

反物质维持下的虫洞虫洞是爱因斯坦在广义相对论中提到的一个概念,又称爱因斯坦-罗森桥。它是指空间向外膨胀,向内塌陷,造成空间中相距很远的两点相互连接到一起。这就像苹果里面有一个虫洞,把苹果表面的两点连到了…

大模型基础(四):transformers库(上):pipline、模型、分词器 - 教程

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

快速上手大模型:深度学习1(初识、神经网络基础) - 详解

快速上手大模型:深度学习1(初识、神经网络基础) - 详解pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consola…

完整教程:【AI智能体】Coze 打造励志图文智能体应用实战操作详解

完整教程:【AI智能体】Coze 打造励志图文智能体应用实战操作详解2025-11-23 08:46 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !im…

11万回本计划

大家好,我是CodeShadow 博客终于搭建好了(已经反复多年...),那么第一篇文章就来说说我最近亏了11w大洋的故事吧... 事情的起因 最近重新打开加密货币交易软件欧意,忍不住玩了两把,损失1w大洋... 查看了下至今为止…

2025年比较好的温拌剂路面材料厂家最新用户好评榜

2025年比较好的温拌剂路面材料厂家最新用户好评榜行业背景与市场趋势随着中国基础设施建设的持续推进和环保要求的日益严格,温拌剂路面材料行业迎来了快速发展期。根据中国公路学会最新发布的《2024-2025年中国道路建…

2025年比较好的环轨通过式抛丸机最新TOP厂家排名

2025年环轨通过式抛丸机最新TOP厂家排名:专业分析与采购指南行业背景与市场趋势随着全球制造业的持续升级和表面处理技术的不断进步,环轨通过式抛丸机作为金属表面处理的关键设备,市场需求呈现稳定增长态势。根据《…

深入解析:【AUTOSAR以太网】EthSM简介

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

mac升级后正版SecureCRT崩了?别碰pyenv,3步救活

mac升级后正版SecureCRT崩了?别碰pyenv,3步救活2025-11-23 08:02 AlfredZhao 阅读(0) 评论(0) 收藏 举报极简方案:3步救活正版CRT(全程5分钟)周末翻出曾陪伴笔者早年间N年运维生涯的老电脑,本着“用物”的理…