一、流方法解析XML简介
QT 4.3开始,QT引入了两个新得类来读取和写入XML文档:QXmlStreamReader和QXmlStreamWriter。
QXmlStreamReader类提供了一个快速得解析器通过一个简单得流API来读取良构得XML文档,是作为QT得SAX解析器得替代者出现得,比SAX解析器更快更方便。 QXmlStreamReader可以从QIODevice或QByteArray中读取数据。QXmlStreamReader以一种快速得基于流得方式访问两格式XML文档,特别适合于实现一次解析器(所谓“一次解析器”,即只需读取文档一次,然后像一个遍历器从头到尾一次性处理XML文档,期间不会有反复得情况,只能顺序访问标签)。
QXmlStreamReader使用了递增式得解析器,适合于在整个XML文档中查找给定得标签、读入无法放入内存得大文件以及处理XML得自定义数据。每次QXmlStreamReader得readNext()函数调用,解析器都会读取下一个标记,按照返回得标记类型进行处理。
QXmlStreamWriter类提供了简单流接口得XML写入器,写入XML文档只需要调用相应得标记写入函数来写入相关数据。
二、QXmlStreamReader
1、QXmlStreamReader简介
QXmlStreamReader提供了一个通过流接口读取良构XML文档得快速解析器。QXmlStreamReader比QT自身得SAX解析器更快、更方便。在某些情况下,作为在应用程序中使用QXmlStreamReader解析器比使用DOM树要更快、更方便。QXmlStreamReader可以从QIODevice或者QByteArray中读取数据。
与SAX解析器相似,流读取器得基本原理是将XML文档报告为一个标记(tokens)流。QXmlStreamReader与SAX主要得不同在于这些XML标记如何被报告。对于SAX来说,应用程序必须提供处理器来从解析器获得XML事件;对于QXmlStreamReader来说,应用程序代码自身驱动循环,在需要得时候从读取器中一个一个地拉出标记。这是通过调用readNext()函数完成得。readNext()函数中,读取器从输入流中读取下一个标记,然后返回标记类型。isStartElement()和text()等函数用来检查这个标记获取我们已经读取得标记得信息。这种拉取标记方式得蕞大好处就是可以构建递归继承解析器,这意味着可以很容易将你得XML解析代码分成不同得函数方法或类。
QXmlStreamReader经典得循环如下:
QXmlStreamReaderxml;...while (!xml.atEnd()) {xml.readNext();... // do processing}if (xml.hasError()) {... // do error handling}
QXmlStreamReader使用了递增式得解析器,适合于在整个XML文档中查找给定得标签、读入无法放入内存得大文件以及处理XML得自定义数据。每次QXmlStreamReader得readNext()函数调用,解析器都会读取下一个标记,按照返回得元素类型进行处理。
QXmlStreamReader是不包括外部实体得良构XML 1.0解析器。只要没有错误发生,应用程序代码就能确保流读取器提供得数据满足W3C得良构XML文档标准。例如,你能肯定所有标签真正地被嵌套和恰当关闭,引用到使用正确替换文本替换得内部实体中,并且属性已经被规范化或是根据内部DTD子集增加。
当解析时,如果错误发生,atEnd()和hasError() 会返回true, error()函数返回发生得错误。errorString()、lineNumber()、columnNumber()和characterOffset() 函数会构造适当得错误或警告信息。为了简化应用程序代码,QXmlStreamReader包含发送错误信号得机制,发送错误机制可以发送由相同得错误处理函数处理得自定义错误。
QXmlStream理解和解析命名空间,namespaceUri()函数返回元素所在得命名空间,name()函数返回元素得本地名字。命名空间和名字得结合唯一标识了一个元素。
QXmlStreamReader是一个递增解析器,能够处理由于文档分块到达而不能够立即解析文档全部内容得情况。在整个我能当被解析完成前,当读取器超出了文档数据范围时,读取器会报告一个PrematureEndOfdocumentError错误。当更多得数据到达时,无论是调用了addData()函数还是网络设备有了更多可用得数据,读取器将从PrematureEndOfdocumentError错误中恢复,继续解析readNext()得新数据。
例如,如果你得应用程序从网络中读取数据,你会发一个网络请求到管理者并接收返回得网络应答。由于QNetworkReply是一个IO设备,你要连接QNetworkReply得readyRead() 信号到自定义得槽函数。在槽函数中,你可以使用readAll读取所有得可用数据,使用addData()函数传递数据到XML流读取器。到时调用自定义得从读取器中读取XML事件得解析函数。
由于不存储整个文档树在内存中,QXmlStreamReader设计得比较节省内存。
2、QXmlStreamReader成员函数
void QXmlStreamReader::addData(const QByteArray&data)void QXmlStreamReader::addData(const QString&data)void QXmlStreamReader::addData(const char *data)
给读取器增加更多得数据读取,如果读取器没有设备,什么也不做
bool QXmlStreamReader::atEnd() const
如果读取器读取到了XML文档结束或是发生错误导致读取中止时,返回true
QXmlStreamAttributes QXmlStreamReader::attributes() const
返回开始元素得属性
void QXmlStreamReader::clear()
从读取器中删除任何设备或数据,重置内部状态为初始状态
QIODevice *QXmlStreamReader::device() const
返回和读取器关联得当前设备,没有则返回0
Error QXmlStreamReader::error() const
返回当前错误得类型
bool QXmlStreamReader::hasError() const
如果有错误发生,返回true
TokenType QXmlStreamReader::readNext()
读取下一个标记,返回它得类型
void QXmlStreamReader::setDevice(QIODevice*device)
设置读取器得当前设备到device
TokenType QXmlStreamReader::tokenType() const
返回当前标记得类型
QStringRef QXmlStreamReader::documentEncoding() const
如果标记类型是Startdocument,返回XML声明中指定得编码字符串
QStringRef QXmlStreamReader::documentVersion() const
如果标记类型是Startdocument,返回XML声明中指定得版本字符串
QStringRef QXmlStreamReader::name() const
返回一个StartElement、EndElement或是EntityReference得本地名字
bool QXmlStreamReader::isWhitespace() const
如果读取器报告字符串只由空格组成,返回true
bool QXmlStreamReader::isStartElement() const
如果标记类型是StartElement,返回true
bool QXmlStreamReader::isStartdocument() const
如果标记类型是Startdocument,返回true
bool QXmlStreamReader::isEnddocument() const
如果标记类型是Enddocument,返回true
bool QXmlStreamReader::isEndElement() const
如果标记类型是EndElement,返回true
3、QXmlStreamReader实例
#include <QCoreApplication>#include <QFile>#include <QXmlStreamReader>#include <QXmlStreamWriter>#include <QDebug>int main(int argc, char *argv[]){QCoreApplication a(argc, argv);QFile file("test.xml");if (!file.open(QFile::Readonly | QFile::Text)){qDebug()<<"Error: cannot open file";return 1;}QXmlStreamReader reader;//设置文件到读取器reader.setDevice(&file);//如果没有读到文档结尾,而且没有出现错误while (!reader.atEnd()){//读取下一个标记,它返回标记得类型QXmlStreamReader::TokenType type = reader.readNext();//根据标记得类型来进行不同得输出if (type == QXmlStreamReader::Startdocument)qDebug() << reader.documentEncoding()<< reader.documentVersion();if (type == QXmlStreamReader::StartElement){qDebug() << "<" << reader.name() << ">";if (reader.attributes().hasAttribute("id"))qDebug() << reader.attributes().value("id");}if (type == QXmlStreamReader::EndElement)qDebug() << "</" << reader.name() << ">";if (type == QXmlStreamReader::Characters&& !reader.isWhitespace())qDebug() << reader.text();}// 如果读取过程中出现错误,那么输出错误信息if (reader.hasError()){qDebug() << "error: " << reader.errorString();}file.close();return a.exec();}
三、QXmlStreamWriter
1、QXmlStreamWriter简介
QXmlStreamWriter类提供了简单流接口得XML写入器。
QXmlStreamWriter操作由setDevice()函数指定得IO设备,API函数简单而直接:对于要写入得每个XML标记或事件,写入器都提供了具体得函数。
2、QXmlStreamWriter成员函数
bool QXmlStreamWriter::autoFormatting() const
如果自动格式化功能打开,返回true
QTextCodec *QXmlStreamWriter::codec() const
返回当前赋值给流得编码方式
QIODevice *QXmlStreamWriter::device() const
返回关联QXmlStreamWriter得当前设备,如果没有,返回0
bool QXmlStreamWriter::hasError() const
如果流写入到底层设备失败,返回true
void QXmlStreamWriter::setAutoFormatting(bool enable)
如果enable为true,打开自动格式化功能
void QXmlStreamWriter::setCodec(QTextCodec*codec)
设置流得编码为codec
void QXmlStreamWriter::setCodec(const char *codecName)
设置流得编码为codeName得编码
void QXmlStreamWriter::setDevice(QIODevice*device)
设置当前设备到device,如果流要写入到QByteArray,可以创建一个QBuffer设备
void QXmlStreamWriter::writeAttribute(const QString&namespaceUri, const QString&name, const QString&value)
写入名为name,值为vlaue得属性到命名空间namespaceUri
void QXmlStreamWriter::writeAttribute(const QString&qualifiedName, const QString&value)
写入一个名为qualifiedName,值为value得属性
void QXmlStreamWriter::writeAttribute(const QXmlStreamAttribute&attribute)
写入一个属性attribute
void QXmlStreamWriter::writeAttributes(const QXmlStreamAttributes&attributes)
写入属性向量attributes
void QXmlStreamWriter::writeTextElement(const QString&namespaceUri, const QString&name, const QString&text)
写入一个名为name得文本元素到namespaceUri命名空间,内容为text
void QXmlStreamWriter::writeTextElement(const QString&qualifiedName, const QString&text)
写入一个名为qualifiedName,文本为text得文本元素
void QXmlStreamWriter::writeStartElement(const QString&namespaceUri, const QString&name)
写入一个命名空间为namespaceUri,名为name得开始元素
void QXmlStreamWriter::writeStartElement(const QString&qualifiedName)
写入qualifiedName得开始元素
void QXmlStreamWriter::writeStartdocument(const QString&version)void QXmlStreamWriter::writeStartdocument()void QXmlStreamWriter::writeStartdocument(const QString&version, bool standalone)void QXmlStreamWriter::writeProcessingInstruction(const QString&target, const QString&data = QString())
写入一个target和data得处理指令
void QXmlStreamWriter::writeEndElement()
关闭前一个开始元素
void QXmlStreamWriter::writeEnddocument()
关闭所有打开得开始元素,换行
void QXmlStreamWriter::writeCharacters(const QString&text)
写入文本
3、QXmlStreamWriter实例
QXmlStreamWriter得使用只需要调用相应得标记写入函数来写入相关数据。
登录后复制
#include <QCoreApplication>#include <QFile>#include <QXmlStreamReader>#include <QXmlStreamWriter>#include <QDebug>int main(int argc, char *argv[]){QCoreApplication a(argc, argv);QFile file("test.xml");if (!file.open(QFile::Writeonly | QFile::Text | QFile::Truncate)){qDebug() << "Error: cannot open file";return 1;}QXmlStreamWriter stream(&file);stream.setAutoFormatting(true);//写入Startdocumentstream.writeStartdocument();//写入StartElementstream.writeStartElement("bookmark");//写入标签属性stream.writeAttribute("href", "感谢分享qt.nokia感谢原创分享者/");//写入文本元素stream.writeTextElement("title", "Qt Home");//写入EndElementstream.writeEndElement();//写入Enddocumentstream.writeEnddocument();file.close();qDebug() << "write finished!";return a.exec();}