Qt 学习(2)

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

原文地址:https://www.cnblogs.com/brifuture/p/9191165.html

时间: 2024-07-31 18:07:17

Qt 学习(2)的相关文章

Qt学习之路

  Qt学习之路_14(简易音乐播放器) Qt学习之路_13(简易俄罗斯方块) Qt学习之路_12(简易数据管理系统) Qt学习之路_11(简易多文档编辑器) Qt学习之路_10(Qt中statusBar,MessageBox和Timer的简单处理) Qt学习之路_9(Qt中Item Widget初步探索) Qt学习之路_8(Qt中与文件目录相关操作) Qt学习之路_7(线性布局和网格布局初步探索) Qt学习之路_6(Qt局域网聊天软件) Qt学习之路_5(Qt TCP的初步使用) Qt学习之路

QT学习之路(1):彩票绝对不中模拟器

//============================================//绝对不中,彩票开奖模拟器#include "mainwindow.h"#include "ui_mainwindow.h"#include <QHash>#include <QDebug>MainWindow::MainWindow(QWidget *parent) :    QMainWindow(parent),    ui(new Ui::M

qt学习(三):鼠标图标改变

qt学习 (三):鼠标图标改变 当你进入一个美好的qt软件场景,比如游戏,电脑的黑白图标会让程序逊色不少, 1改图标要加光标的头文件, 2 载入光标图, 3 再设置改光标就可以了 1在头文件中加 #include <QtGui>  //光标类的父类 //再在public成员中声明换的函数void keyPressEvent(QKeyEvent *k); //声明按键换图的函数         .h文件    --注意头文件和声明 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Qt学习总结-ui篇(二)

qccs定义圆角 border-radius:10px; 如果想给特定位置定义圆角,如: 左上角:border-left-top-radius:10px; 右下角色:border-right-bottom-rasius:10px; 半透明效果 只需要在css中使用rgba(100,100,100,40)这种形式来表示颜色即可. 为可执行文件添加图标 1.新建文件:finename.rc 文件名无所谓,只要后缀为rc就可以. 2.编辑新建的文件,输入以下内容: IDI_ICON1 ICON DIS

【qt学习005】搞不明白的布局

记录一下自己在布局这一章遇见的各种狗屎问题. 问题主要出现在布局最后一节:综合布局实例,类似于一个qq管理器的界面(见下图1).看见这个时,打算动手实现一下,于是开始写代码,写着写着发现不知道怎么写了,遇见一些无法解决的问题(问题中描述的布局类之间的关系见下图2): 1. 最底层应该使用哪一类? 2. 怎么将QListWidget加入到最底层? 3. 怎么往QStackWidget加入三个页面,每个页面代表不同的信息? 4. 怎么将QHBoxLayout中的CLOSE按钮连接到退出函数,要完整地

【Qt学习笔记】13.拖放技术:Drag & Drop

1.接受拖放 Drag & Drop 是一个界面操作,用于在两个窗口间传递数据. Drag Source: 拖放源窗口 Drag Target: 拖放目标窗口 拖放操作: 1.在源窗口:选中目标,按下鼠标,移动,拖至目标窗口(Drag) 2.在目标窗口:取消鼠标,到指定位置,松开鼠标(Drop) (按下ESC取消操作) MIME: MIME(Multipurpose Internet Mail Extensions)被传递的数据以MIME格式传送,它是多组type-data数据:(type0,

QT学习第1天

QT学习第一天  坚持住!! 一 Qt概述 1.Qt发展历史 (1)1991年诞生(Haavard Nord/Eirik Chambe-Eng), (2)1994年创立Troll Tech(奇趣科技) (3)2005年QT4.0 (4)2008年被Nokia收购 (5)2009年源代码开源 (6)2012年Nokia将全部QT业务和知识产权卖给Digia公司 (7)2013年QT5.0 QT5.1 QT5.2 (8)2014年Digia公司成立 The Qt Company子公司 2.Qt5.4

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

Q_OBJECT:这是一个宏,凡是定义信号槽的类都必须声明这个宏. 函数tr()全名是QObject::tr(),被他处理过的字符串可以使用工具提取出来翻译成其他语言,也就是做国际化使用. 对于QT学习之路:Qt学习之路(7):创建一个对话框(上)这个程序.编译出现 invalid use of incomplete type ‘class QPushButton’ findButton->setEnabled(!text.isEmpty()); ^ In file included from

qt学习(四)主窗选钮,显示新窗口。

游戏有选区这个习惯, 当然,我特指<冒险岛>了,有的时候就是打开一个主屏幕上五个按钮让你点击进入, 甚至有的时候进去了还要选哪个频道,游戏服务器都得分区,频道来完成功能.现在我们先进入想选的区,不需要的可以看以后的登陆窗口了. 这一次的主要功能是完成选区,选完进入输入账号界面. 这次用的是一个点完出啦一个所以需要两个窗口,在原有的基础上新建qt设计师界面类.选择dialogwithoutbutton. 把最后一个要显示的当作主界面, 其他的都可以选择dialog模板, 完成以后,画ui界面,

qt学习(一)qt三个文件函数的框架

学到点什么, 而不是复制着什么, 每天敲着别人给的代码,苦涩得改完bug, 就这样一天天的过去, 实质上并没有学到什么, 别人的思想只是拿来借鉴, 你的思想是好是坏都是你的, 不用急着抛弃自己. 从qt看看人家的思路. Qt编程思路: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~` 以下:xxx.h ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~