qt绘图模块初高级完整教程 (qt读xml实现流程)

导语

我们前面讲述了用DOM的方法对XML文档进行操作,DOM实现起来很灵活,但是这样也就使得编程变得复杂了些,而且我们前面也提到过,DOM需要预先把整个XML文档都读入内存,这样就使得它不适合处理较大的文件。下面我们讲述另一种读取XML文档的方法,即SAX 。是的,如果你只想读取并显示整个XML文档,那么SAX是很好的选择,因为它提供了比DOM更简单的接口,并且它不需要将整个XML文档一次性读入内存,这样便可以用来读取较大的文件。我们对SAX不再进行过多的介绍,因为不需要任何基础,你就可以掌握我们下面要讲的内容了。如果大家对SAX有兴趣,可以到网上查找相关资料。

环境:Windows Xp + Qt 4.8.4+QtCreator 2.6.2

目录

一、解析器解析流程

二、使用SAX读取文档

正文

【领QT开发教程学习资料,点击下方链接莬费领取↓↓,先码住不迷路~】

点击→领取「链接」

一、解析器解析流程

在Qt的 QtXml 模块中提供了一个 QXmlSimpleReader 的类,它便是基于SAX的XML解析器。这个解析器是基于事件的,但这些事件由它们自身进行关联,我们并不需要进行设置。我们只需知道,当解析器解析一个XML的元素时,就会执行相应的事件,我们只要重写这些事件处理函数,就能让它按照我们的想法进行解析。

比如要解析下面的元素:

<title>Qt</title>

解析器会依次调用如下事件处理函数: startElement() characters() endElement() 。我们可以在 startElement() 中获得元素名(如“title”)和属性,在 characters() 中获得元素中的文本(如“Qt”),在 endElement() 中进行一些结束读取该元素时想要进行的操作。而所有的这些事件处理函数我们都可以通过继承 QXmlDefaultHandler 类来重写。

二、使用SAX读取文档

1.新建其他项目分类中的空的Qt项目,项目名称为 mySAX

2.完成后向项目中添加新的C++类,类名为 MySAX ,基类填写 QXmlDefaultHandler

3.然后再添加一个 main.cpp 文件。

4.先打开 mySAX.pro 文件,添加一行代码: QT+= xml ,然后保存该文件。

5.打开 mysax.h 文件,将其内容更改为:

#ifndef MYSAX_H
#define MYSAX_H

#include <QXmlDefaultHandler>
class QListWidget;

class MySAX : public QXmlDefaultHandler
{
public:
    MySAX();
    ~MySAX();
    bool readFile(const QString &fileName);
protected:
bool startElement(const QString &namespaceURI, 
const QString &localName,
                          const QString &qName, 
const QXmlAttributes &atts);
bool endElement(const QString &namespaceURI, 
const QString &localName,
                    const QString &qName);
    bool characters(const QString &ch);
    bool fatalError(const QXmlParseException &exception);
private:
    QListWidget *list;
    QString currentText;
};

#endif // MYSAX_H

这里主要是重新声明了 QXmlDefaultHandler 类的 startElement() endElement() characters() fatalError() 几个函数, readFile() 函数用来读入XML文件, QListWidget 部件用来显示解析后的XML文档内容, currentText 字符串变量用于暂存字符数据。

6.打开 mysax.cpp 文件,将其内容修改如下:

#include "mysax.h"
#include <QtXml>
#include <QListWidget>

MySAX::MySAX()
{
    list = new QListWidget;
    list->show();
}

MySAX::~MySAX()
{
    delete list;
}

bool MySAX::readFile(const QString &fileName)
{
    QFile file(fileName);

    // 读取文件内容
    QXmlInputSource inputSource(&file);

    // 建立QXmlSimpleReader对象
    QXmlSimpleReader reader;

    // 设置内容处理器
    reader.setContentHandler(this);

    // 设置错误处理器
    reader.setErrorHandler(this);

    // 解析文件
    return reader.parse(inputSource);
}

// 已经解析完一个元素的起始标签
bool MySAX::startElement(const QString &namespaceURI, 
const QString &localName,
                         const QString &qName, 
const QXmlAttributes &atts)
{
    if (qName == "library")
        list->addItem(qName);
    else if (qName == "book")
        list->addItem("    " + qName + atts.value("id"));
    return true;
}

// 已经解析完一块字符数据
bool MySAX::characters(const QString &ch)
{
    currentText = ch;
    return true;
}

// 已经解析完一个元素的结束标签
bool MySAX::endElement(const QString &namespaceURI, 
const QString &localName,
                       const QString &qName)
{
    if (qName == "title" || qName == "author")
        list->addItem("        " + qName + " : " + currentText);
    return true;
}

// 错误处理
bool MySAX::fatalError(const QXmlParseException &exception)
{
    qDebug() << exception.message();
    return false;
}

这里添加了几个函数的定义。在 readFile() 函数中,我们设置了文件的解析过程。Qt中提供了一个简单的XML解析器 QXmlSimpleReader ,它是基于SAX的。该解析器需要 QXmlInputSource 为其提供数据, QXmlInputSource 会使用相应的编码来读取XML文档的数据。在进行解析之前,还需要使用 setContentHandler() 来设置事件处理器,使用 setErrorHandler() 来设置错误处理器,它们的参数使用了 this ,表明使用本类作为处理器,也就是在解析过程中出现的各种事件都会使用本类的 startElement() 等事件处理函数来进行处理,而出现错误时会使用本类的 fatalError() 函数来处理。最后,调用了 parse() 函数来进行解析,该函数会在解析成功时返回 true ,否则返回 false 。在后面的几个事件处理函数中,就是简单的将数据显示在 QListWidget 中。

7.最后打开 main.cpp 文件,添加如下内容:

#include "mysax.h"
#include <QApplication>
int main(int argc, char* argv[])
{    
      QApplication app(argc, argv);    
      MySAX sax;   
      sax.readFile("../mySAX/my.xml");    
      return app*ex.e**c();
}

8.将前面第27篇建立的 my.xml 文件复制到我们的源码目录中,然后运行程序,效果如下图所示。

qt入门教程100篇,qt快速入门系列教程

结语

可以看到使用SAX方法来解析XML文档比使用DOM方法要清晰很多,更重要的是它的效率要高很多,不过SAX方法只适用于读取XML文档。