Qt 学习(2)

Qt 的 QXmlStreamReader

在 Qt 应用程序中访问 XML 格式的文件数据,可以使用 [QXmlStreamReader][sreamreader] 对文件进行读取。关于 QXmlStreamReder 的使用,官方文档中有 QXmlStream Bookmarks Example 的示例可供参考。

常用的方法有:

  • TokenType readNext()

    读取下一个标记并返回它的类型
  • bool readNextStartElement()

    在当前元素内,读取到下一个开始元素,若找到开始元素,就返回真,否则返回假
  • QXmlStreamAttributes attributes()

    返回 StartElement 中的属性
  • QString name()

    返回标签名,比如读取标签 <html> 就会返回 html
  • void skipCurrentElement()

    读取到当前元素的结尾,跳过它的子节点
  • QString readElementText()

    读取元素中间的文本,比如 <p>test</p> 将会返回 test

对于一个自定义结构的 XML 文件,文件名为 test.xml,如下:

<?xml version="1.0" encoding="UTF-8"?>
<Instructions version="2.0">
<Instruct identifier="#" set="MSP">
<row type="Offset" value="OFFSET_MODE">
<reply type="String" enum="true">
<accept value="AUTO" />
<accept value="MANUAL" />
</reply>
</row> <row type="Buzzer" value="BUZZER" /> <row type="AC" value="SAG">
<reply type="Double" enum="false" bottom="0" />
</row> </Instruct>
</Instructions>

首先构造一个 XmlStreamReader,它的构造函数可以接受一个 QIODevice 的指针,一般可以传递一个 QFile 指针,对 xml 文件进行解析:

// void InstructParser::parse(const QString &filename, const QString &set) {
// 打开并读取指令文件
QFile file( filename );
bool opened = file.open( QIODevice::ReadOnly );
if( !opened ) {
qDebug() << "[parse] file not open" ;
return;
}
m_xmlReader = new QXmlStreamReader( &file ); // ![1]
readInstructions();
// ![1] file.close();
file.deleteLater();
delete m_xmlReader;
// }

构造了 XmlStreamReader 后,通过 readNext() 或者 readNextStartElement() 往下读取节点。

readNext 和 readNextStartElement 方法的使用有些差别,先来看看 readNext 方法:

// void  InstructParser::readInstructions()
while( !m_xmlReader->atEnd() ) {
m_xmlReader->readNext();
qDebug() << "[readNext] "<< QString( "%0 %1").arg( m_xmlReader->lineNumber() ).arg( m_xmlReader->tokenString() ) << m_xmlReader->name().toString();
}

输出结果:

可以看到,对于空白行, readNext 函数将会跳过该行,而对于第 3 行 Instruct 起始标签,在它的前面是有一个 tab 缩进的,这里会显示一个类型为 Characters 的元素,然而在第 18 行 </Instructions> 标签前面,其实并没有 tab 缩进,然而这里仍然会显示一个 Characters 元素,并且 17 行的反尖括号后面是没有输入字符的,不知道是不是 Windows 平台下的回车换行符当成一个元素来进行解析的。

接下来是 readNextElement 方法:

// void  InstructParser::readInstructions()
while( !m_xmlReader->atEnd() ) {
bool start = m_xmlReader->readNextStartElement();
qDebug() << "[readNextStartElement] "<< start
<< QString( "%0 %1").arg( m_xmlReader->lineNumber() ).arg( m_xmlReader->tokenString() )
<< m_xmlReader->name().toString();
}

输出结果:

可以看到,对于空白行,该方法仍然会忽略掉,但是这个方法不会再出现一些奇怪的 Characters 标签,所有打印出来的元素都是所需要的,当然最后读到文件尾会显示 Invalid 标记。这个方法比 readNext 方法更好用。但是需要注意的是在第 6 行,读取 <accept value="AUTO" /> 时,这里开始标签和结束标签是合并着写的,所以在读到结束标签时,该函数会返回 false,如果 while 循环的判断条件是 m_xmlReader->readNextStartElement(),那么当它遇到结束标签时,将会结束循环。

在读取 XML 文件时,不仅需要针对特定标签做处理,有时还需要注意各个标签之间的层级关系(常见的如 HTML 中 div 标签),如果像前面一样,直接判断 m_xmlReader 是不是到达文件底部,那么就没有办法找出标签之间的层级关系了。

为了找出某个标签中的子标签,就需要在进入标签后,继续用循环进行判断,比如对于上面的 XML 文件:在 InstructParser 中分别有四个方法读取四个标签:

private:
void readInstructions(const QString &set);
void readInstruct(const QString &set, const bool stillRead = false);
void readRow();
void readReply(Instruct *ins);

readInstructions 中使用 while 循环对 readInstruct 进行重复调用,在 readInstruct() 中使用 while 循环对 readRow() 进行重新调用……最后其实得到的是一个树状结构,在 readInstruct() 中:

    while( m_xmlReader->readNextStartElement() ) {
if( m_xmlReader->name() == "row" ) {
readRow();
}
else
m_xmlReader->skipCurrentElement();
}

在读取之前加上相应的输出语句:

qDebug() << "[reply]" << m_xmlReader->name() << m_attrib.value( "type" ) << m_xmlReader->tokenString();

可以得到以下输出:

这样就得到了所有的节点,有时 m_xmlReader->readNextStartElement() 会跳出循环,可以在 readRow 等函数的结尾加上,以便读取到当前父节点的结束标签:

m_xmlReader->readElementText();  // skip to end tag of reply

Qt 学习(2)的更多相关文章

  1. QT学习第1天

    QT学习第一天  坚持住!! 一 Qt概述 1.Qt发展历史 (1)1991年诞生(Haavard Nord/Eirik Chambe-Eng), (2)1994年创立Troll Tech(奇趣科技) ...

  2. 【转载】分享一些Qt学习资源,欢迎下载

    资源来源:http://bbs.csdn.net/topics/390358737 经过我一翻整理,把一些我收集到的Qt学习资源分享给大家,主要适合新手,老鸟可以直接忽略我.要说明一下,很多资源都是在 ...

  3. QT学习之路--创建一个对话框

    Q_OBJECT:这是一个宏,凡是定义信号槽的类都必须声明这个宏. 函数tr()全名是QObject::tr(),被他处理过的字符串可以使用工具提取出来翻译成其他语言,也就是做国际化使用. 对于QT学 ...

  4. 转载: Qt 学习之路 2归档

    Qt 学习之路 2归档 http://www.devbean.net/2012/08/qt-study-road-2-catelog/

  5. Qt 学习资料

    Qter开源社区http://www.qter.org/ [Qt教程], 作者yafeilinux [视频] QT学习之路:从入门到精通 <C++ Qt 编程视频教程>

  6. qt学习笔记(五) QGraphicsPixmapItem与QGraphicsScene的编程实例 图标拖动渐变效果

    应大家的要求,还是把完整的project文件贴出来,大家省点事:http://www.kuaipan.cn/file/id_48923272389086450.htm 先看看执行效果,我用的群创7寸屏 ...

  7. Qt学习博客推荐

    附录C Qt资源 C.1 Qt 官方资源 全 球各大公司以及独立开发人员每天都在加入 Qt 的开发社区.他们已经认识到了Qt 的架构本身便可加快应用程序开发进度.这些开发人员,无论是想开发单平台软件. ...

  8. qt学习教程1.qt开发环境搭建

    qt学习教程1.qt开发环境搭建 首先下载qt 下载地址:http://download.qt.io/archive/qt/ 此教程使用的版本为5.1.1 下载好后,打开安装包,然后点下一步 选择一个 ...

  9. QT学习教程

    原地址:http://www.devbean.NET/2012/08/qt-study-road-2-catelog/ 网上看到的不错的教程 本教程以qt5为主,部分地方会涉及qt4.据说非常适合qt ...

  10. Qt学习之路

      Qt学习之路_14(简易音乐播放器)   Qt学习之路_13(简易俄罗斯方块)   Qt学习之路_12(简易数据管理系统)   Qt学习之路_11(简易多文档编辑器)   Qt学习之路_10(Qt ...

随机推荐

  1. 【谁知道C#字段为什么用属性封装?】

    源地址:https://zhidao.baidu.com/question/1174413218458798139.html 我们知道,类成员包括变量和方法.如果希望其他类能够访问成员变量的值,就必须 ...

  2. SharePoint安装注意点

    在安装SharePoint之前需要注意的地方(整理如下:) 1.首先得先安装IIS服务器和ApplicationServer 2.然后要在运行setup.exe之前先运行prerequisiteins ...

  3. springboot mybatis自定义枚举enum转换

    原文链接:https://blog.csdn.net/u014527058/article/details/62883573 一.概述 在利用Spring进行Web后台开发时,经常会遇到枚举类型的绑定 ...

  4. 《图解HTTP》阅读笔记--第四章--HTTP状态码

    第四章.返回结果的HTTP状态码前言:状态码的职责是告诉用户服务器端描述返回的请求,以便用户判断服务器处理是否正常. 状态码由三位数字和原因短语组成,其中三位数字的首位指定了响应类别:---1xx 接 ...

  5. P3750 [六省联考2017]分手是祝愿 期望DP

    \(\color{#0066ff}{ 题目描述 }\) Zeit und Raum trennen dich und mich. 时空将你我分开. B 君在玩一个游戏,这个游戏由 \(n\) 个灯和 ...

  6. Vue中添加过渡效果

    最近在学习Vue这个框架,发现新的版本中,官网的文档里面说的过渡效果,如果直接粘贴官方的例子中的代码,发现并没有过渡的效果,经过反复测试之后终于知道怎么搞了,把测试的过程总结一下,以便以后回顾. 贴上 ...

  7. 黑马JavaScript学习一 BOM之Window对象定时器功能

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  8. HDU - 6416 :Rikka with Seam(DP & 前缀和 & 数学)

    pro:给定N*M的矩阵,现在让你在每一行删去一个位置,然后形成新N*(M-1)的矩阵,问有多少种不同的新的矩阵.需要满足相邻行删去的位置不大于K. (题目是01矩阵,其实任意矩阵都可以做,本题算法里 ...

  9. Python集合字典运算符

    1.集合2.字典3.运算符优先级 1.集合 创建:{} set([]) 注意:创建空的集合要用set()   特点:元素唯一,无序   运算: & 交集 | 并集 - 差集   方法:   s ...

  10. bash 中 trim 字符串(去除首尾空格) - grep 去空行

    在 bash 下如何去除一个字符串首尾的空格(也就是 trim)呢?其实有一个简单的办法: $ echo $STR 注 意 $STR 不要带引号.因为 $STR 展开后,会作为 echo 的参数.那么 ...