39.Qt XML

Posted 喵小喵~

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 }

 

以上是关于39.Qt XML的主要内容,如果未能解决你的问题,请参考以下文章

xml Eclipse模板(代码片段)检查参数并最终抛出IllegalArgumentException

需要示例代码片段帮助

从 XML 声明片段获取 XML 编码:部分内容解析不支持 XmlDeclaration

创建片段而不从 java 代码实例化它

如何组合绑定片段而不将它们包装在 XML 文字中

我们可以在活动 xml 中编写 UI 以及在片段 xm 中编写 UI 吗?