http://blog.csdn.net/liang19890820/article/details/52805902
简述
XML(EXtensible Markup Language - 可扩展标记语言)是一种用于记录多种数据类型的标记语言。使用 XML 可以将各类型的文档定义为容易读取的格式,便于用户读取。而且,在应用程序中使用 XML,可以轻松实现数据交换。
使用 XML 模块
要链接到 XML 模块,需要在 qmake 项目文件 .pro 中添加:
QT += xml
- 1
包含模块中类的定义,使用:
#include <QtXml>
- 1
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);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
一旦 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();
- 11
有关文档对象模型的更多信息,请参阅文档对象模型(DOM)Level 1和evel 2 Core核心规范。
SAX
SAX 是用于 XML 解析器的基于事件的标准接口。XML 类的设计遵循SAX2 Java interface,名称适合 Qt 的命名约定。对于任何使用 SAX2 的人来说,使用 Qt XML 类应该非常容易。
SAX2 介绍
SAX2 接口是一种事件驱动的机制,能够为用户提供文档信息。这里提到的“事件”意味着解析器报告的东西。例如,它遇到了一个开始标记,或者结束标记等。
为了使它不那么抽象,考虑以下示例:
<quote>A quotation</quote>
- 在读取(SAX2 解析器通常被称为“读取器”)时,上述文档将触发三个事件:
每次发生这样的事件时,解析器就会报告它,可以设置事件处理程序来响应这些事件。
虽然这是一种快速、简单地读取 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()) { ... // 做错误处理 }
- 9
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();
- 10
使用哪种方式
虽然 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 模块。
更多参考