[Qt教程] 第29篇 XML(三)Qt中的SAX

前端之家收集整理的这篇文章主要介绍了[Qt教程] 第29篇 XML(三)Qt中的SAX前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
楼主
发表于 2013-5-21 22:27:59 |查看: 615 |回复: 5
Qt中的SAX

版权声明

文章原创于Qter开源社区(www.qter.org),作者yafeilinux,转载请注明出处!


导语

我们前面讲述了用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 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 文件,将其内容更改为:
  1. #ifndef MYSAX_H
  2. #define MYSAX_H

  3. #include <QXmlDefaultHandler>
  4. class QListWidget;
  5. class MySAX : public QXmlDefaultHandler
  6. {
  7. public:
  8. MySAX();
  9. ~MySAX();
  10. bool readFile(const QString &fileName);
  11. protected:
  12. bool startElement(const QString &namespaceURI,
  13. const QString &localName,serif; font-size:12px; line-height:1.8em"> const QString &qName,serif; font-size:12px; line-height:1.8em"> const QXmlAttributes &atts);
  14. bool endElement(const QString &namespaceURI,serif; font-size:12px; line-height:1.8em"> const QString &qName);
  15. bool characters(const QString &ch);
  16. bool fatalError(const QXmlParseException &exception);
  17. private:
  18. QListWidget *list;
  19. QString currentText;
  20. };
  21. #endif // MYSAX_H
复制代码
这里主要是重新声明了QXmlDefaultHandler类的startElement()、endElement()、characters()和fatalError()几个函数,readFile()函数用来读入XML文件,QListWidget部件用来显示解析后的XML文档内容,currentText字符串变量用于暂存字符数据。

6. 打开mysax.cpp 文件,将其内容修改如下:
  1. #include "mysax.h"
  2. #include <QtXml>
  3. #include <QListWidget>
  4. MySAX::MySAX()
  5. list = new QListWidget;
  6. list->show();
  7. }
  8. MySAX::~MySAX()
  9. delete list;
  10. bool MySAX::readFile(const QString &fileName)
  11. QFile file(fileName);

  12. // 读取文件内容
  13. QXmlInputSource inputSource(&file);
  14. // 建立QXmlSimpleReader对象
  15. QXmlSimpleReader reader;
  16. // 设置内容处理器
  17. reader.setContentHandler(this);
  18. // 设置错误处理器
  19. reader.setErrorHandler(this);
  20. // 解析文件
  21. return reader.parse(inputSource);
  22. // 已经解析完一个元素的起始标签
  23. bool MySAX::startElement(const QString &namespaceURI,serif; font-size:12px; line-height:1.8em"> const QString &qName,serif; font-size:12px; line-height:1.8em"> const QXmlAttributes &atts)
  24. if (qName == "library")
  25. list->addItem(qName);
  26. else if (qName == "book")
  27. list->addItem(" " + qName + atts.value("id"));
  28. return true;
  29. // 已经解析完一块字符数据
  30. bool MySAX::characters(const QString &ch)
  31. currentText = ch;
  32. // 已经解析完一个元素的结束标签
  33. bool MySAX::endElement(const QString &namespaceURI,serif; font-size:12px; line-height:1.8em"> const QString &qName)
  34. if (qName == "title" || qName == "author")
  35. list->addItem(" " + qName + " : " + currentText);
  36. // 错误处理
  37. bool MySAX::fatalError(const QXmlParseException &exception)
  38. qDebug() << exception.message();
  39. return false;
  40. 复制代码
这里添加了几个函数的定义。在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>
intmain(intargc,char*argv[])
{
QApplicationapp(argc,argv);
MySAXsax;
sax.readFile("../mySAX/my.xml");
returnapp.exec();
}

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



结语

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




涉及到的源码:mySAX.zip(2.09 KB,下载次数: 8)

猜你在找的XML相关文章