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(); }