Qt的XML模块包含了两种处理xml的API,分别是SAX和DOM。SAX提供了一种低层的基于事件驱动的方式解析xml文件,而DOM提供了一种高层的接口用于解析xml文件。不同之处在于DOM受制于内存的大小,一次不能解析文件大小太大的xml文件,因为它将xml文件一次性地读入内存中。
SAX方式解析XML文件
SAX方式解析XML是基于事件方式编程的。执行的流程完全取决于读入的数据。使用该方式的主要步骤是创建一个XML读取器以及一个处理器,然后将两者关联起来,之后调用parse(),涉及的各方用类图表示如下:
代码示例如下:
myhandler.h
- #ifndef MYHANDLER_H
- #define MYHANDLER_H
- #include <QXmlDefaultHandler>
- class QString;
- class MyHandler : public QXmlDefaultHandler
- {
- public:
- explicit MyHandler();
- signals:
- public slots:
- public:
- bool startDocument();
- bool startElement( const QString & namespaceURI,
- const QString & localName,
- const QString & qName,
- const QXmlAttributes & atts);
- bool characters(const QString& text);
- bool endElement( const QString & namespaceURI,
- const QString & localName,
- const QString & qName );
- private:
- QString indent;
- };
- #endif // MYHANDLER_H
myhandler.cpp
- #include "myhandler.h"
- #include <QObject>
- #include <QTextStream>
- #include <QDebug>
- MyHandler::MyHandler():QXmlDefaultHandler()
- {
- }
- bool MyHandler::startDocument() {
- indent = "";
- return TRUE;
- }
- bool MyHandler::characters(const QString& text) {
- QString t = text;
- qDebug() << t.remove('\n');
- return TRUE;
- }
- bool MyHandler::startElement( const QString&,
- const QString&,
- const QString& qName,
- const QXmlAttributes& atts) {
- QString str = QString("\n%1\\%2").arg(indent).arg(qName);
- qDebug() << str;
- if (atts.length()>0) {
- QString fieldName = atts.qName(0);
- QString fieldValue = atts.value(0);
- qDebug() << QString("(%2=%3)").arg(fieldName).arg(fieldValue);
- }
- qDebug() << "{";
- indent += " ";
- return TRUE;
- }
- bool MyHandler::endElement( const QString&,
- const QString& ,
- const QString& ) {
- indent.remove( 0, 4 );
- qDebug() << "}";
- return TRUE;
- }
main.cpp
- #include <QApplication>
- #include <QFile>
- #include <QXmlInputSource>
- #include "myhandler.h"
- #include <QDebug>
- int main(int argc, char *argv[])
- {
- QApplication a(argc, argv);
- QFile xmlFile( ":/test.xml" );
- QXmlInputSource source( &xmlFile );
- if (!xmlFile.open(QFile::ReadOnly | QFile::Text)) {
- return -1;
- }
- MyHandler handler;
- QXmlSimpleReader reader;
- reader.setContentHandler( &handler );
- if( reader.parse( source ) )
- qDebug()<<"File loaded!";
- return a.exec();
- }
DOM方式解析XML文件
DOM方式只适合解析小的xml文件,它是基于SAX之上的一种高层解析XML方法。使用方式见如下代码所示:
- #include <QtCore/QCoreApplication>
- #include <QDomDocument>
- #include <QFile>
- #include <QDebug>
- void parseFolderElement(const QDomElement &element)
- {
- QDomElement child = element.firstChildElement();
- while (!child.isNull()) {
- if (child.tagName() == "folder") {
- parseFolderElement(child);
- } else if (child.tagName() == "bookmark") {
- QString title = child.firstChildElement("title").text();
- if (title.isEmpty())
- title = QObject::tr("Folder");
- qDebug()<<"title="<<title;
- } else if (child.tagName() == "separator") {
- qDebug()<<"processing separator";
- }
- child = child.nextSiblingElement();
- }
- }
- void parseXmlByDom(QIODevice *device)
- {
- QDomDocument domDocument;
- QString errorStr;
- int errorLine;
- int errorColumn;
- if (!domDocument.setContent(device, true, &errorStr, &errorLine,
- &errorColumn)) {
- qDebug()<<"Parse error at line "
- <<errorLine
- <<", column "
- << errorColumn
- <<":\n"
- <<errorStr;
- return;
- }
- QDomElement root = domDocument.documentElement();
- if (root.tagName() != "xbel") {
- qDebug()<<QString( "The file is not an XBEL file.");
- return;
- } else if (root.hasAttribute("version")
- && root.attribute("version") != "1.0") {
- qDebug()<<QString("The file is not an XBEL version 1.0 file.");
- return;
- }
- QDomElement child = root.firstChildElement("folder");
- while (!child.isNull()) {
- parseFolderElement(child);
- child = child.nextSiblingElement("folder");
- }
- }
- int main(int argc, char *argv[])
- {
- QCoreApplication a(argc, argv);
- QFile f("frank.xbel");
- if( ! f.open(QIODevice::ReadOnly) )
- {
- qDebug()<<"failed to open file";
- return -1;
- }
- parseXmlByDom(&f);
- return a.exec();
- }