QT 4.3开始,QT引入了两个新的类来读取和写入XML文档:QXmlStreamReader和QXmlStreamWriter。 网络
QXmlStreamReader类提供了一个快速的解析器经过一个简单的流API来读取良构的XML文档,是做为QT的SAX解析器的替代者出现的,比SAX解析器更快更方便。 QXmlStreamReader能够从QIODevice或QByteArray中读取数据。QXmlStreamReader以一种快速的基于流的方式访问良格式XML文档,特别适合于实现一次解析器(所谓“一次解析器”,即只需读取文档一次,而后像一个遍历器从头至尾一次性处理XML文档,期间不会有反复的状况,只能顺序访问标签)。ide
QXmlStreamReader使用了递增式的解析器,适合于在整个XML文档中查找给定的标签、读入没法放入内存的大文件以及处理XML的自定义数据。每次QXmlStreamReader的readNext()函数调用,解析器都会读取下一个标记,按照返回的标记类型进行处理。函数
QXmlStreamWriter类提供了简单流接口的XML写入器,写入XML文档只须要调用相应的标记写入函数来写入相关数据。编码
QXmlStreamReader提供了一个经过流接口读取良构XML文档的快速解析器。QXmlStreamReader比QT自身的SAX解析器更快、更方便。在某些状况下,做为在应用程序中使用QXmlStreamReader解析器比使用DOM树要更快、更方便。QXmlStreamReader能够从QIODevice或者QByteArray中读取数据。spa
与SAX解析器类似,流读取器的基本原理是将XML文档报告为一个标记(tokens)流。QXmlStreamReader与SAX主要的不一样在于这些XML标记如何被报告。对于SAX来讲,应用程序必须提供处理器来从解析器得到XML事件;对于QXmlStreamReader来讲,应用程序代码自身驱动循环,在须要的时候从读取器中一个一个地拉出标记。这是经过调用readNext()函数完成的。readNext()函数中,读取器从输入流中读取下一个标记,而后返回标记类型。isStartElement()和text()等函数用来检查这个标记获取咱们已经读取的标记的信息。这种拉取标记方式的最大好处就是能够构建递归继承解析器,这意味着能够很容易将你的XML解析代码分红不一样的函数方法或类。设计
QXmlStreamReader经典的循环以下:code
QXmlStreamReader xml;orm
...xml
while (!xml.atEnd()) {blog
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设计的比较节省内存。
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
#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类提供了简单流接口的XML写入器。
QXmlStreamWriter操做由setDevice()函数指定的IO设备,API函数简单而直接:对于要写入的每一个XML标记或事件,写入器都提供了具体的函数。
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)
写入文本
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); //写入StartDocument stream.writeStartDocument(); //写入StartElement stream.writeStartElement("bookmark"); //写入标签属性 stream.writeAttribute("href", "http://qt.nokia.com/"); //写入文本元素 stream.writeTextElement("title", "Qt Home"); //写入EndElement stream.writeEndElement(); //写入EndDocument stream.writeEndDocument(); file.close(); qDebug() << "write finished!"; return a.exec(); }