15.2.  SAX Parsing

[ fromfile: xmlparsing.xml id: saxparsing ]

Example 15.4. src/xml/sax1/tagreader.cpp

#include "myhandler.h"
#include <QFile>
#include <QXmlInputSource>
#include <QXmlSimpleReader>
#include <QDebug>

int main( int argc, char **argv ) {
    if ( argc < 2 ) {
        qDebug() << QString("Usage: %1 <xmlfiles>").arg(argv[0]);
        return 1;
    }
    MyHandler handler; 
    QXmlSimpleReader reader;                1
    reader.setContentHandler( &handler );   2
    for ( int i=1; i < argc; ++i ) {
        QFile xmlFile( argv[i] );
        QXmlInputSource source( &xmlFile );
        reader.parse( source );             3
    }
    return 0;
}

1

The generic parser.

2

Hook the objects together.

3

Start parsing.


Figure 15.1.  Abstract and Concrete SAX Classes

Abstract and Concrete SAX Classes

Figure 15.2.  Plugin Component Architecture

Plugin Component Architecture

Example 15.5. src/xml/sax1/myhandler.h

[ . . . . ]
#include <QXmlDefaultHandler>
class QString;
class MyHandler : public QXmlDefaultHandler {
  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;
};
[ . . . . ]

[Important] ContentHandler or DefaultHandler?
  • QXmlContentHandler is an abstract class with many pure virtual functions, all of which must be overridden by any concrete derived class.

  • Qt has provided a concrete class named QXmlDefaultHandler that implements the base class pure virtual functions as empty, do-nothing bodies.

Example 15.6. src/xml/sax1/myhandler.cpp

[ . . . . ]
QTextStream cout(stdout);

bool MyHandler::startDocument() {
    indent = "";
    return TRUE;
}

bool MyHandler::characters(const QString& text) {
    QString t = text;
    cout << t.remove('\n');
    return TRUE;
}

bool MyHandler::startElement( const QString&, 1
                             const QString&, const QString& qName, 
                             const QXmlAttributes& atts) {
    QString str = QString("\n%1\\%2").arg(indent).arg(qName);
    cout << str;
    if (atts.length()>0) {
        QString fieldName = atts.qName(0);
        QString fieldValue = atts.value(0);
        cout << QString("(%2=%3)").arg(fieldName).arg(fieldValue);
    }
    cout << "{";
    indent += "    ";
    return TRUE;
}

bool MyHandler::endElement( const QString&,
    const QString& , const QString& ) {
    indent.remove( 0, 4 );
    cout << "}";
    return TRUE;
}
[ . . . . ]

1

We have omitted the names of the parameters that we don't use. This prevents the compiler from issuing "unused parameter" warnings.


Example 15.7. src/xml/sax1/tagreader-output.txt

\section(id=xmlintro){
    \title{ Intro to XML }
    \para{ This is a paragraph }
    \ul{
        \li{ This is an unordered list item. }
        \li(c=textbook){ This only shows up in the textbook }    }
    \p{ Look at this example code below: }
    \include(src=xmlsamplecode.cpp){}}