找回密码
 立即注册
Qt开源社区 门户 查看内容

第29篇Qt5之XML(三)Qt中的SAX

2019-3-11 06:01| 发布者: admin| 查看: 720| 评论: 0

摘要: 来源于微信公众号:yafeilinux和他的朋友们 导语 我们前面讲述了用DOM的方法对XML文档进行操作,DOM使用起来很灵活,但是这样也就使得编程变得复杂了些,而且前面也提到过,DOM需要预先把整个XML文档都读入内存, ...
来源于微信公众号:yafeilinux和他的朋友们



导语

     

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



环境

Windows 7 + Qt 5.8.0(包含Qt Creator 4.2.1)     



 解析流程   

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

<title>Qt</title>

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



使用SAX读取文档

     

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

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

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

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

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.exec();

}

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





结语

     

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

欢迎长按下图→识别图中二维码或者扫一扫关注我的公众号:




----------------------------------------------------------------------------------------------------------------------
我们尊重原创,也注重分享,文章来源于微信公众号:yafeilinux和他的朋友们,建议关注公众号查看原文。如若侵权请联系qter@qter.org。
----------------------------------------------------------------------------------------------------------------------

鲜花

握手

雷人

路过

鸡蛋

公告
可以关注我们的微信公众号yafeilinux_friends获取最新动态,或者加入QQ会员群进行交流:190741849、186601429(已满) 我知道了