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. Powershell Deploy Service Fabric Application To Local Cluster

    之前写过一篇用 Powershell 部署 Service Fabric Application 到本地集群的随笔,感觉过程有点复杂,这次将流程简化,只需要将应用程序打包,加上配置文件就可以了.   ...

  2. 百度地图 JS API开发Demo01

    百度地图DEMO     <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http: ...

  3. MPI编程指南

    MPI编程指南 一.     MPI概述 1.1  MPI的发展史 MPI标准化涉及到大约60个国家的人们,他们主要来自于美国和欧洲的40个组织,这包括并行计算机的多数主要生产商,还有来自大学.政府实 ...

  4. dedecms有缩略图则显示缩略图,没有则显示随机缩略图

    随着html5以及扁平化等新的设计概念的深入人心,缩略图功能则成了一般网页模版制作不可或缺的一个功能,dedecms默认的的缩略图调用标签[field:imglink/] 或者 [field:litp ...

  5. javascript小菜单—demo

    <!DOCTYPE html><html><head> <title></title></head><body>&l ...

  6. linux模式切换,进程切换

    内核态和用户态的切换: 用户态到内核态的转换:1.进行系统调用,2.异步中断,3.外部硬件中断 检查特权级别的变化:当异常发生在用户态,而异常处理函数则必须运行在内核态,则此时必须调用内核态的堆栈(系 ...

  7. 数据结构20:KMP算法(快速模式匹配算法)详解

    通过上一节的介绍,学习了串的普通模式匹配算法,大体思路是:模式串从主串的第一个字符开始匹配,每匹配失败,主串中记录匹配进度的指针 i 都要进行 i-j+1 的回退操作(这个过程称为“指针回溯”),同时 ...

  8. (转)ios学习--你会遇到的runtime面试题(详)

    1.了解runtime吗?是什么? 2.你怎么知道的? 3.对象如何找到对应方法去调用的 于是我总结了很多网上被问到的一些关于runtime的题目,并做了详细的回答,并在后面补充了我在学习runtim ...

  9. spring cloud 超时时间

    zuul.host.socket-timeout-millis=60000 #zuul socket连接超时zuul.host.connect-timeout-millis=60000 #zull 请 ...

  10. 使用windows服务修改CPU型号(重启依然有效)

    此项目基于.net framework 4.0 效果如下: 服务运行前: 服务运行后: 思路大概是这样: 通过修改注册表可以修改CPU型号,把服务设置成本地服务,并且开机自动启动,来实现开机自动修改处 ...