使用Qt中的QXmlStreamReader讀取XML文件

前文我們介紹過通過QDomDocument的方法可以容易解析一個XML文件,QDomDocument的每一個子對象和XML的每一個子節點對應,保留了相同的層次結構,能夠做到隨機訪問XML中的節點。但它的缺點是需要將整個XML文件加載到內存中,不適合處理較大的文件。

今天要介紹的是QXmlStreamReader,就是按順序讀取XML的方式,每讀取一個節點,應用就對當前節點做相應的處理(忽略或保存)。那麼這種方式是SAX麼?不是!
SAX的處理方式雖然也是按節點順序讀取,但是對讀取節點的處理方法不一樣。SAX在碰到一個節點後,會去調用用戶已經寫好的回調函數,該回調函數是基類實現的虛函數,不能改變它的名字,只能根據傳入的參數實現不同處理,代碼會比較複雜。但StreamReader的實現方式是由開發者通過readNext()讀入一個節點,然後判斷節點內容,由開發者決定用什麼函數去處理,對應不同節點層次實現不同函數,可維護性比較好。

具體流程是:
1. 創建一個QXmlStreamReader的類對象
2. 通過setDevice()設置好要處理的XML文件
3. 通過readNext()挨個讀入節點,
4.a 通過isStartElement()和isEndElement()判斷是節點的開始和結束
4.b 可以通過name()得到當前節點名字
4.c 可以通過readElementText()訪問當前節點的內容

下面,來看看我處理rss2代碼的例子,通過該類我讀取了rss2裏每個文件的標題。
因爲需要實現自己的處理功能,我們用一個類RssRader繼承自QXmlStreamReader
class RssReader : public QXmlStreamReader{…}
下面就可以使用該類了
RssReader reader;
reader.read(&file); //參數是QIODevice指針,file是QFile類型,
read是我在子類裏實現的函數名,可以是其它名字,看看read()的實現
bool RssReader::read(QIODevice *device)
{
setDevice(device);//這是基類的函數,用於將XML傳入解析器

while (!atEnd()) {
readNext(); //這個是關鍵函數,挨個讀取節點

if (isStartElement()) {
if (name() == “rss”){
//我的實現,對rss作了處理,其它節點忽略
//read_rss()管理剩下的節點,碰到rss節點結束時返回
read_rss();
}
}
}

return !error();
}

//read_rss的實現,主要關心名爲channel的節點,其他節點忽略
//XML的節點是對稱的,有開始必有結束,判斷的標誌就是
//isStartElement()和isEndElement()
void RssReader::read_rss(){
qDebug()<<”read rss info”;
while (!atEnd()) {
readNext();
if (isStartElement()) {
if (name() == “channel”){
read_channel();
}
}
if (isEndElement()) {
if (name() == “rss”){
qDebug()<<”end read rss info”;
break;
}
}
}
}

//讀取節點內容的函數是readElementText(),由基類實現
void RssReader::read_item(){
while (!atEnd()) {
readNext();

if (isStartElement()) {
if (name() == “title”){
qDebug()<<”Title:”<<readElementText();
}
}

if (isEndElement()) {
if (name() == “item”){
break;
}
}

}
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章