QT開發(四十四)——流方法解析XML

QT開發(四十四)——流方法解析XML

1、流方法解析XML簡介

    QT 4.3開始,QT引入了兩個新的類來讀取和寫入XML文檔:QXmlStreamReaderQXmlStreamWriter 網絡

    QXmlStreamReader類提供了一個快速的解析器經過一個簡單的流API來讀取良構的XML文檔,是做爲QTSAX解析器的替代者出現的,比SAX解析器更快更方便。    QXmlStreamReader能夠從QIODeviceQByteArray中讀取數據。QXmlStreamReader以一種快速的基於流的方式訪問良格式XML文檔,特別適合於實現一次解析器(所謂「一次解析器」,即只需讀取文檔一次,而後像一個遍歷器從頭至尾一次性處理XML文檔,期間不會有反覆的狀況,只能順序訪問標籤)。ide

    QXmlStreamReader使用了遞增式的解析器,適合於在整個XML文檔中查找給定的標籤、讀入沒法放入內存的大文件以及處理XML的自定義數據。每次QXmlStreamReader的readNext()函數調用,解析器都會讀取下一個標記,按照返回的標記類型進行處理。函數

QXmlStreamWriter類提供了簡單流接口的XML寫入器,寫入XML文檔只須要調用相應的標記寫入函數來寫入相關數據。編碼

2、QXmlStreamReader

1QXmlStreamReader簡介

    QXmlStreamReader提供了一個經過流接口讀取良構XML文檔的快速解析器。QXmlStreamReaderQT自身的SAX解析器更快、更方便。在某些狀況下,做爲在應用程序中使用QXmlStreamReader解析器比使用DOM樹要更快、更方便。QXmlStreamReader能夠從QIODevice或者QByteArray中讀取數據。spa

    與SAX解析器類似,流讀取器的基本原理是XML文檔報告爲一個標記(tokens)流。QXmlStreamReaderSAX主要的不一樣在於這些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()函數調用,解析器都會讀取下一個標記,按照返回的元素類型進行處理。

wKioL1hCcJDRf3n2AABNsXlAIgc570.png

    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設備,你要鏈接QNetworkReplyreadyRead() 信號到自定義的槽函數。在槽函數中,你可使用readAll讀取全部的可用數據,使用addData()函數傳遞數據到XML流讀取器。到時調用自定義的從讀取器中讀取XML事件的解析函數。

    因爲不存儲整個文檔樹在內存中,QXmlStreamReader設計的比較節省內存。

2QXmlStreamReader成員函數

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

返回一個StartElementEndElement或是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

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

3、QXmlStreamWriter

1QXmlStreamWriter簡介

    QXmlStreamWriter類提供了簡單流接口的XML寫入器。

    QXmlStreamWriter操做由setDevice()函數指定的IO設備,API函數簡單而直接:對於要寫入的每一個XML標記或事件,寫入器都提供了具體的函數。

二、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)

若是enabletrue,打開自動格式化功能

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)

寫入文本

3QXmlStreamWriter實例

    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();
}
相關文章
相關標籤/搜索