Qt之XML
简述XML(EXtensible Markup Language - 可扩展标记语言)是一种用于记录多种数据类型的标记语言。使用 XML 可以将各类型的文档定义为容易读取的格式,便于用户读取。而且,在应用程序中使用 XML,可以轻松实现数据交换。
使用 XML 模块要链接到 XML 模块,需要在 qmake 项目文件 .pro 中添加: QT += xml
包含模块中类的定义,使用: #include <QtXml>
XML 的访问方式Qt 提供了两种访问 XML 文档的方式:DOM 和 SAX。
DOMDOM Level 2 是用于 XML 接口的一个 W3C 推荐标准,将 XML 文档的组成映射为一个树结构。DOM Level 2 的规范可以在 http://www.w3.org/DOM/ 上找到。 DOM 提供了一个访问和更改 XML 文件内容和结构的接口。它创建了一个文档的分层视图(树视图),因此,与 SAX2 接口相反,在解析之后,文档的对象模型常驻在内存中,这使得操作变得更加容易。 Qt 为 DOM 提供了用于操作 XML 的多种 C++类,均以 QDom 开头:
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 1 和 evel 2 Core 核心规范。 SAXSAX 是用于 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 类来报告解析事件:
由于处理程序类只描述接口,因此必须实现所有函数。Qt 提供了 QXmlDefaultHandler 类使之变得更容易:它实现所有函数的默认行为(不做任何操作),所以可以子类化它,只需要实现感兴趣的函数即可。 要读取输入的 XML 数据,需要使用特殊类 QXmlInputSource(QXmlReader 子类的输入数据)。 除了已经提到的,以下 SAX2 支持类还提供了其他有用的功能:
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()) {
... // 做错误处理
}
QXmlStreamWriterQXmlStreamWriter 类仅通过数据流写入 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++ 实现,但是助手中有这么一句话:
此模块不再进行积极地维护,请使用Qt Core 中的 QXmlStreamReader 和 QXmlStreamWriter 类代替。 也就是说,助手更建议我们使用 QXmlStreamReader 和 QXmlStreamWriter 类,而非 XML 模块。 更多参考
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |