39.Qt XML


1.使用QXmlStreamReader讀取XML,可以讀取內存中容納不了的特大文件,或者讀取在XML文檔中定制的文檔的內容。

xml文件(in1.xml)

<?xml version="1.0"?>
<bookindex>
    <entry term="sidebearings">
        <page>10</page>
        <page>34-35</page>
        <page>307-308</page>
    </entry>
    <entry term="subtraction">
        <entry term="of pictures">
            <page>115</page>
            <page>244</page>
        </entry>
        <entry term="of vectors">
            <page>9</page>
        </entry>
    </entry>
</bookindex>

main.cpp

 1 #include <QtGui>
 2 
 3 #include <iostream>
 4 #include "xmlstreamreader.h"
 5 
 6 int main(int argc, char *argv[])
 7 {
 8     //創建QApplication對象
 9     QApplication app(argc, argv);
10     QDir::setCurrent(app.applicationDirPath());//設置路徑為當前目錄
11     
12     //創建兩個標簽
13     QStringList labels;
14     labels << QObject::tr("Terms") << QObject::tr("Pages");
15 
16     //樹形控件窗口
17     QTreeWidget treeWidget;
18     //設置第一行
19     treeWidget.setHeaderLabels(labels);
20     //設置可以伸縮
21     treeWidget.header()->setResizeMode(QHeaderView::Stretch);
22     //設置窗口標題
23     treeWidget.setWindowTitle(QObject::tr("XML Stream Reader"));
24     //樹形控件顯示
25     treeWidget.show();
26 
27     //創建對象,對xml讀取
28     XmlStreamReader reader(&treeWidget);
29     
30     reader.readFile("in1.xml");
31 
32     return app.exec();
33 }

xmlstreamreader.h

 1 #ifndef XMLSTREAMREADER_H
 2 #define XMLSTREAMREADER_H
 3 
 4 #include <QXmlStreamReader>
 5 
 6 class QTreeWidget;
 7 class QTreeWidgetItem;
 8 
 9 class XmlStreamReader
10 {
11 public:
12     XmlStreamReader(QTreeWidget *tree);
13 
14     bool readFile(const QString &fileName);
15 
16 private:
17     //解析一個含有0或0個以上<entry>元素的<bookindex>...</bookindex>
18     void readBookindexElement();
19     //解析一個含有0個或0個以上<entry>元素的<entry>...</entry>元素
20     //以及嵌套任意層次的含有0或0個以上<entry>元素
21     void readEntryElement(QTreeWidgetItem *parent);
22     //解析一個<page>...</page>元素
23     void readPageElement(QTreeWidgetItem *parent);
24     //跳過不能識別的元素
25     void skipUnknownElement();
26 
27     //保存傳進來的treeWidget
28     QTreeWidget *treeWidget;
29     //讀取對象
30     QXmlStreamReader reader;
31 };
32 
33 #endif

xmlstreamreader.cpp

  1 #include <QtGui>
  2 #include <QtXml>
  3 #include <iostream>
  4 
  5 #include "xmlstreamreader.h"
  6 
  7 XmlStreamReader::XmlStreamReader(QTreeWidget *tree)
  8 {
  9     //初始化指針
 10     treeWidget = tree;
 11 }
 12 
 13 bool XmlStreamReader::readFile(const QString &fileName)
 14 {
 15     //嘗試打開文件
 16     QFile file(fileName);
 17     //只讀,文本方式打開。如果出錯,返回出錯信息。
 18     if (!file.open(QFile::ReadOnly | QFile::Text)) {
 19         std::cerr << "Error: Cannot read file " << qPrintable(fileName)
 20                   << ": " << qPrintable(file.errorString())
 21                   << std::endl;
 22         return false;
 23     }
 24 
 25     //如果成功,則將這個file設置為輸入設備,用於讀數據
 26     reader.setDevice(&file);
 27 
 28     //從流中讀取一個數據
 29     reader.readNext();
 30     //如果沒到文件末尾
 31     while (!reader.atEnd()) {
 32         //如果是開始標簽
 33         if (reader.isStartElement()) {
 34             if (reader.name() == "bookindex") {
 35                 //解析bookindex
 36                 readBookindexElement();
 37             }
 38             else
 39             {
 40                 //否則給出出錯信息
 41                 reader.raiseError(QObject::tr("Not a bookindex file"));
 42             }
 43         }
 44         else
 45         {
 46             //繼續讀下一個標簽
 47             reader.readNext();
 48         }
 49     }
 50 
 51     file.close();
 52     //如果處理出現錯誤就會返回
 53     //是否存在解析錯誤?
 54     if (reader.hasError()) {
 55         std::cerr << "Error: Failed to parse file "
 56                   << qPrintable(fileName) << ": "
 57                   << qPrintable(reader.errorString()) << std::endl;
 58         return false;
 59     }
 60     //是否存在文件錯誤?
 61     else if (file.error() != QFile::NoError)
 62     {
 63         std::cerr << "Error: Cannot read file " << qPrintable(fileName)
 64                   << ": " << qPrintable(file.errorString())
 65                   << std::endl;
 66         return false;
 67     }
 68     return true;
 69 }
 70 
 71 void XmlStreamReader::readBookindexElement()
 72 {
 73     //讀下一個標簽
 74     reader.readNext();
 75     while (!reader.atEnd()) {
 76         //如果到結束標簽,則結束while循環
 77         if (reader.isEndElement()) {
 78             reader.readNext();
 79             break;
 80         }
 81         
 82         
 83         //如果是開始標簽
 84         if (reader.isStartElement()) 
 85         {
 86             if (reader.name() == "entry") 
 87             {
 88                 //調用處理entry的函數
 89                 readEntryElement(treeWidget->invisibleRootItem());
 90             }
 91             else 
 92             {
 93                 //調用未知的處理函數
 94                 skipUnknownElement();
 95             }
 96         } 
 97         else
 98         {
 99             //如果不是開始標簽則讀取下一個
100             reader.readNext();
101         }
102     }
103 }
104 
105 //每當遇到<entry>開始標簽,就調用readEntryElement()函數
106 void XmlStreamReader::readEntryElement(QTreeWidgetItem *parent)
107 {
108     //遇到一個<entry>就在樹形控件中增加一個條目
109     QTreeWidgetItem *item = new QTreeWidgetItem(parent);
110     //設置第0個,為對應的term項所表示的值
111     item->setText(0, reader.attributes().value("term").toString());
112 
113     //讀下一個
114     reader.readNext();
115     while (!reader.atEnd()) {
116         //如果遇到關閉標簽,跳出循環
117         if (reader.isEndElement()) {
118             reader.readNext();
119             break;
120         }
121 
122         //如果遇到的是開始標簽
123         if (reader.isStartElement()) {
124             //如果是<entry>標簽
125             if (reader.name() == "entry") {
126                 //遞歸調用
127                 readEntryElement(item);
128             }
129             //如果是<page>標簽
130             else if (reader.name() == "page")
131             {
132                 readPageElement(item);
133             }
134             //未知標簽
135             else
136             {
137                 skipUnknownElement();
138             }
139         }
140         else
141         {
142             reader.readNext();
143         }
144     }
145 }
146 
147 //讀取頁面信息
148 void XmlStreamReader::readPageElement(QTreeWidgetItem *parent)
149 {
150     //讀標簽內容,調用reader.readElementText,reader會停留在結束標簽位置上,需要跳過
151     QString page = reader.readElementText();
152     //如果是結束標識,則跳到下一個進行讀取
153     if (reader.isEndElement())
154         reader.readNext();
155 
156     //第一個文本
157     QString allPages = parent->text(1);
158     //如果不為空加上,
159     if (!allPages.isEmpty())
160         allPages += ", ";
161     //加上標簽內容
162     allPages += page;
163     //設置
164     parent->setText(1, allPages);
165 }
166 
167 //如果遇到未知標簽也讀取,直到跳過該標簽的關閉標簽
168 void XmlStreamReader::skipUnknownElement()
169 {
170     //遇到未知的繼續讀取下一個標簽
171     reader.readNext();
172     //繼續讀下一個,如果沒到末尾
173     while (!reader.atEnd()) {
174         if (reader.isEndElement()) {
175             reader.readNext();
176             break;
177         }
178 
179         //如果是開始,繼續遞歸,直到遇到第一個未知的關閉標簽
180         if (reader.isStartElement()) {
181             skipUnknownElement();
182         } else {
183             reader.readNext();
184         }
185     }
186 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM