Qt之XML

简述

XML(EXtensible Markup Language - 可扩展标记语言)是一种用于记录多种数据类型的标记语言。使用 XML 可以将各类型的文档定义为容易读取的格式,便于用户读取。而且,在应用程序中使用 XML,可以轻松实现数据交换。

  • 简述
  • 使用 XML 模块
  • XML 的访问方式
    • DOM
    • SAX
      • SAX2 介绍
  • XML 流
    • QXmlStreamReader
    • QXmlStreamWriter
  • 使用哪种方式
  • 更多参考

使用 XML 模块

要链接到 XML 模块,需要在 qmake 项目文件 .pro 中添加:

QT += xml

包含模块中类的定义,使用:

#include <QtXml>

XML 的访问方式

Qt 提供了两种访问 XML 文档的方式:DOM 和 SAX。

  • DOM 方式:将 XML 文档转换为树形结构存储到内存中,再进行读取,消耗的内存比较多。此外,由于文档都已经存储到内存,所以需要频繁实现修改等操作时,使用起来比较方便。
  • SAX 方式:相比于 DOM,SAX 是一种速度更快,更有效的方法,它逐行扫描文档,一边扫描一边解析(由于应用程序只是在读取数据时检查数据,因此不需要将数据存储在内存中,这对于大型文档的解析是个巨大优势)。而且相比于 DOM,SAX 可以在解析文档的任意时刻停止解析。但操作复杂,很难修改 XML 数据。

DOM

DOM Level 2 是用于 XML 接口的一个 W3C 推荐标准,将 XML 文档的组成映射为一个树结构。DOM Level 2 的规范可以在 http://www.w3.org/DOM/ 上找到。

DOM 提供了一个访问和更改 XML 文件内容和结构的接口。它创建了一个文档的分层视图(树视图),因此,与 SAX2 接口相反,在解析之后,文档的对象模型常驻在内存中,这使得操作变得更加容易。
文档树中的所有 DOM 节点都是 QDomNode 的子类,文档本身由 QDomDocument 对象表示。

Qt 为 DOM 提供了用于操作 XML 的多种 C++类,均以 QDom 开头:

描述
QDomAttr 表示一个 QDomElement 的属性
QDomCDATASection 表示一个 XML CDATA 部分
QDomCharacterData 表示 DOM 中的一个通用字符串
QDomComment 表示一个 XML 注释
QDomDocument 表示一个 XML 文档
QDomDocumentFragment QDomNodes 树,通常不是一个完整的 QDomDocument
QDomDocumentType 表示文档树中的 DTD
QDomElement 表示 DOM 树中的一个元素
QDomEntity 代表一个 XML 实体
QDomEntityReference 代表一个 XML 实体引用
QDomImplementation DOM 实现的功能的信息
QDomNamedNodeMap 包含一个节点集合,节点可以通过名字来访问
QDomNode 一个 DOM 树中所有节点的基类
QDomNodeList QDomNode 对象列表
QDomNotation 代表一个 XML 表示法
QDomProcessingInstruction 代表 XML 处理指令
QDomText 表示解析的 XML 文档中的文本数据

QDom 类通常使用如下:

QDomDocument doc("mydocument");
QFile file("mydocument.xml");
if (!file.open(QIODevice::ReadOnly))
    return;
if (!doc.setContent(&file)) {
    file.close();
    return;
}
file.close();

// 打印出作为最外层元素的所有直接子元素的元素名称
QDomElement docElem = doc.documentElement();

QDomNode n = docElem.firstChild();
while(!n.isNull()) {
    QDomElement e = n.toElement(); // 尝试将节点转换为元素
    if(!e.isNull()) {
        cout << qPrintable(e.tagName()) << endl; // 节点真的是一个元素
    }
    n = n.nextSibling();
}

// 这里,我们在文档的末尾添加一个新元素
QDomElement elem = doc.createElement("img");
elem.setAttribute("src", "myimage.png");
docElem.appendChild(elem);

一旦 doc 和 elem 超出范围,代表 XML 文档的整个内部树被删除。

要使用 DOM 创建文档,请使用如下代码:

QDomDocument doc("MyML");
QDomElement root = doc.createElement("MyML");
doc.appendChild(root);

QDomElement tag = doc.createElement("Greeting");
root.appendChild(tag);

QDomText t = doc.createTextNode("Hello World");
tag.appendChild(t);

QString xml = doc.toString();

有关文档对象模型的更多信息,请参阅文档对象模型(DOM)Level 1evel 2 Core 核心规范。

SAX

SAX 是用于 XML 解析器的基于事件的标准接口。XML 类的设计遵循 SAX2 Java interface,名称适合 Qt 的命名约定。对于任何使用 SAX2 的人来说,使用 Qt XML 类应该非常容易。

SAX2 介绍

SAX2 接口是一种事件驱动的机制,能够为用户提供文档信息。这里提到的“事件”意味着解析器报告的东西。例如,它遇到了一个开始标记,或者结束标记等。

为了使它不那么抽象,考虑以下示例:

<quote>A quotation</quote>

在读取(SAX2 解析器通常被称为“读取器”)时,上述文档将触发三个事件:

  • 出现开始标记(<quote>)。
  • 找到字符数据(即文本)“A quotation”。
  • 解析结束标记(</ quote>)。

每次发生这样的事件时,解析器就会报告它,可以设置事件处理程序来响应这些事件。

虽然这是一种快速、简单地读取 XML 文档的方法,但是操作困难,因为数据不存储,而是串行处理并丢弃。DOM 接口读取并以树结构存储整个文档,这需要更多的内存,但更容易操作文档的结构。

Qt XML 模块提供了一个抽象类 QXmlReader,它定义了潜在的 SAX2 读取器的接口,它有一个简单的 XML 读取器的实现 - QXmlSimpleReader(目前只有这一个,在将来的版本中,可能有更多的具有不同属性的读取器。例如:验证解析器),通过子类化,很容易适应。

读取器通过特殊的 handler 类来报告解析事件:

Handler 类 描述
QXmlContentHandler 报告与文档内容相关的事件(例如:开始标签或字符)
QXmlDTDHandler 报告与 DTD 相关的事件(例如:符号声明)
QXmlErrorHandler 报告解析期间发生的错误或警告(QXmlParseException 用于向使用 QXmlErrorHandler 的接口报告错误)
QXmlEntityResolver 在解析期间报告外部实体,并允许用户解析外部实体本身,而不是将其留给读取器。
QXmlDeclHandler 报告进一步的 DTD 相关事件(例如:属性声明)
QXmlLexicalHandler 报告与文档的词法结构相关的事件(DTD 的开头、注释等)

由于处理程序类只描述接口,因此必须实现所有函数。Qt 提供了 QXmlDefaultHandler 类使之变得更容易:它实现所有函数的默认行为(不做任何操作),所以可以子类化它,只需要实现感兴趣的函数即可。

要读取输入的 XML 数据,需要使用特殊类 QXmlInputSource(QXmlReader 子类的输入数据)。

除了已经提到的,以下 SAX2 支持类还提供了其他有用的功能:

描述
QXmlAttributes 用于向来是元素事件中传递属性
QXmlLocator 用于获取事件的实际解析位置
QXmlNamespaceSupport 用于为读取器实现命名空间支持。注意:命名空间不会更改解析行为,它们只通过处理程序进行报告。

XML 流

从 4.3 版本开始,Qt 提供了两个新的类来读写 XML:QXmlStreamReader 和 QXmlStreamWriter。

流读取器将 XML 文档报告为标记流。这与 SAX 不同,因为 SAX 应用程序提供处理程序从解析器接收 XML 事件,而 QXmlStreamReader 驱动循环,在需要时从读取器中提取标记。这种拉取方法使得构建递归下降解析器成为可能,允许 XML 解析代码被拆分成不同的方法或类。

QXmlStreamReader 是一个格式良好的 XML 1.0 解析器,排除外部解析实体。因此,只要没有错误发生,应用程序代码就可以确保由 QXmlStreamReader 提供的数据满足 W3C 对于格式良好的 XML 的标准。否则,可以使用诸如 atEnd()、error() 和 hasError() 的函数来检查和查看错误。

QXmlStreamReader

应用程序中,QXmlStreamReader 类比用于 SAX 解析的 QXmlSimpleReader 类速度更快,且更好用。QXmlStreamReader 类用于读取数据,他可以通过 QIODevice 和 QByteArray 读取列数据。

一个典型的 QXmlStreamReader 循环:

QXmlStreamReader xml;
...
while (!xml.atEnd()) {
    xml.readNext();
    ... // 做处理
}
if (xml.hasError()) {
    ... // 做错误处理
}

QXmlStreamWriter

QXmlStreamWriter 类仅通过数据流写入 XML 数据,该类由成员函数 setDevice() 指定的 QIODevice 运行。

下面的简化代码片段,显示了该类用缩进编写格式化 XML 的基本用法:

QXmlStreamWriter stream(&output);
stream.setAutoFormatting(true);
stream.writeStartDocument();
...
stream.writeStartElement("bookmark");
stream.writeAttribute("href", "http://qt-project.org/");
stream.writeTextElement("title", "Qt Project");
stream.writeEndElement(); // bookmark
...
stream.writeEndDocument();

使用哪种方式

虽然 Qt XML 模块提供了 XML 对 SAX 和 DOM 标准的 C++ 实现,但是助手中有这么一句话:

The module is not actively maintained anymore. Please use the QXmlStreamReader and QXmlStreamWriter classes in Qt Core instead.

此模块不再进行积极地维护,请使用Qt Core 中的 QXmlStreamReader 和 QXmlStreamWriter 类代替。

也就是说,助手更建议我们使用 QXmlStreamReader 和 QXmlStreamWriter 类,而非 XML 模块。

更多参考

时间: 2024-12-03 21:44:25

Qt之XML的相关文章

Qt之XML(SAX)

简述 SAX(Simple API for XML)是用于 XML 解析器的基于事件的标准接口.XML 类的设计遵循 SAX2 Java interface,名称适合 Qt 的命名约定.对于任何使用 SAX2 的人来说,使用 Qt XML 类应该非常容易. SAX 不同于 DOM 解析,它逐行扫描文档,一边扫描一边解析.由于应用程序只是在读取数据时检查数据,因此不需要将数据存储在内存中,这对于大型文档的解析是个巨大优势. Qt XML 模块提供了一个抽象类 QXmlReader,它定义了潜在的

Qt之XML(DOM)

简述 DOM(Document Object Model - 文档对象模型)定义了访问和操作 XML 文档的标准方法. DOM 把 XML 文档作为树结构来查看,能够通过 DOM 树来访问所有元素.可以修改或删除它们的内容,并创建新的元素.元素及其文本.属性都被认为是节点. 简述 详细说明 使用 生成 解析 更多参考 详细说明 QDomDocument 类表示一个 XML 文档. QDomDocument 类表示整个 XML 文档.从概念上讲,它是文档树的根,并提供对文档数据的主要访问. 因为元

关于qt读取xml文件并作为excel文件表头

问题描述 关于qt读取xml文件并作为excel文件表头 新使用Qt,求大神指点:如何使用Qt读取xml文件,然后将其节点属性作为excel文件的表头输出呢? 解决方案 http://blog.csdn.net/liyuanbhu/article/details/44062479

[Qt教程] 第27篇 XML(一)使用DOM读取XML文档

[Qt教程] 第27篇 XML(一)使用DOM读取XML文档 楼主  发表于 2013-5-21 21:14:28 | 查看: 1001| 回复: 14 使用DOM读取XML文档 版权声明 该文章原创于作者yafeilinux,转载请注明出处! 导语 XML(ExtensibleMarkup Language,可扩展标记语言),是一种类似于HTML的标记语言,但它的设计目的是用来传输数据,而不是显示数据.XML的标签没有被预定义,用户需要在使用时自行进行定义.XML是W3C(万维网联盟)的推荐标

[Qt教程] 第30篇 XML(四)使用流读写XML

[Qt教程] 第30篇 XML(四)使用流读写XML 楼主  发表于 2013-5-22 13:03:33 | 查看: 611| 回复: 0 使用流读写XML 版权声明 该文章原创于作者yafeilinux,转载请注明出处! 导语        从Qt 4.3开始引入了两个新的类来读取和写入XML文档:QXmlStreamReader和QXmlStreamWriter. QXmlStreamReader类提供了一个快速的解析器通过一个简单的流API来读取格式良好的XML文档,它是作为Qt的SAX

Qt之解析XML(QXmlStreamReader)

简述 QXmlStreamReader 类提供了一个快速解析器,用于通过简单的流 API 读取格式良好的 XML.与之相对应的是 QXmlStreamWriter(写入 XML). 相比较 Qt 自己的 SAX 解析器(见 QXmlSimpleReader),QXmlStreamReader 更快,更方便.某些情况下,在使用 DOM 树(见 QDomDocument)的应用程序中,它也可能是一个更快,更方便的替代方案. QXmlStreamReader 可以从 QIODevice(见 setDe

Qt之生成XML(QXmlStreamWriter)

简述 QXmlStreamWriter 类提供了一个使用简单的流 API,用于写入 XML,与之相对应的是 QXmlStreamReader(读取 XML). 正如其相关类,它可以在 setDevice() 指定的 QIODevice 上操作.API 很简单明了:对于想要写的每个 XML 标签或事件,QXmlStreamWriter 都提供了一个专门的函数. 简述 详细介绍 使用 更多参考 详细介绍 元素标签使用 writeStartElement() 打开,紧随其后的是 writeAttrib

Qt之解析XML元素(QXmlStreamReader)

简述 对于 XML 的内容,通常情况下,我们只关心 XML 元素的解析.这时,可以通过 QXmlStreamReader 中的便利函数 readNextStartElement() 来实现. 简述 详细介绍 使用 更多参考 详细介绍 之前使用的方式主要使用 readNext() 来读取下一个标记,并返回对应的类型. QXmlStreamReader xml; ... while (!xml.atEnd()) { xml.readNext(); ... // 做处理 } if (xml.hasEr

《Qt 实战一二三》

简介 "我们来自Qt分享&&交流,我们来自Qt Quick分享&&交流",不管你是笑了,还是笑了,反正我们是认真的.我们就是要找寻一种Hold不住的状态,来开始每一天的点滴分享,我们是一个有激情,有态度的部队. 但是我们还是我们,我们只是多了一份责任.古语有云:"不积跬步无以至千里,不积小流无以成江海",所以每一个伟大事务的产生都不是一蹴而就的.现在我们要立足眼下,把第一站放在地球,"<Qt 实战一二三>&quo