src/xml/sax/qxml.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/xml/sax/qxml.cpp	Mon Jan 11 14:00:40 2010 +0000
@@ -0,0 +1,8132 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtXml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qxml.h"
+#include "qtextcodec.h"
+#include "qbuffer.h"
+#include "qregexp.h"
+#include "qmap.h"
+#include "qstack.h"
+#include <qdebug.h>
+
+
+#ifdef Q_CC_BOR // borland 6 finds bogus warnings when building this file in uic3
+#    pragma warn -8080
+#endif
+
+//#define QT_QXML_DEBUG
+
+// Error strings for the XML reader
+#define XMLERR_OK                         QT_TRANSLATE_NOOP("QXml", "no error occurred")
+#define XMLERR_ERRORBYCONSUMER            QT_TRANSLATE_NOOP("QXml", "error triggered by consumer")
+#define XMLERR_UNEXPECTEDEOF              QT_TRANSLATE_NOOP("QXml", "unexpected end of file")
+#define XMLERR_MORETHANONEDOCTYPE         QT_TRANSLATE_NOOP("QXml", "more than one document type definition")
+#define XMLERR_ERRORPARSINGELEMENT        QT_TRANSLATE_NOOP("QXml", "error occurred while parsing element")
+#define XMLERR_TAGMISMATCH                QT_TRANSLATE_NOOP("QXml", "tag mismatch")
+#define XMLERR_ERRORPARSINGCONTENT        QT_TRANSLATE_NOOP("QXml", "error occurred while parsing content")
+#define XMLERR_UNEXPECTEDCHARACTER        QT_TRANSLATE_NOOP("QXml", "unexpected character")
+#define XMLERR_INVALIDNAMEFORPI           QT_TRANSLATE_NOOP("QXml", "invalid name for processing instruction")
+#define XMLERR_VERSIONEXPECTED            QT_TRANSLATE_NOOP("QXml", "version expected while reading the XML declaration")
+#define XMLERR_WRONGVALUEFORSDECL         QT_TRANSLATE_NOOP("QXml", "wrong value for standalone declaration")
+#define XMLERR_EDECLORSDDECLEXPECTED      QT_TRANSLATE_NOOP("QXml", "encoding declaration or standalone declaration expected while reading the XML declaration")
+#define XMLERR_SDDECLEXPECTED             QT_TRANSLATE_NOOP("QXml", "standalone declaration expected while reading the XML declaration")
+#define XMLERR_ERRORPARSINGDOCTYPE        QT_TRANSLATE_NOOP("QXml", "error occurred while parsing document type definition")
+#define XMLERR_LETTEREXPECTED             QT_TRANSLATE_NOOP("QXml", "letter is expected")
+#define XMLERR_ERRORPARSINGCOMMENT        QT_TRANSLATE_NOOP("QXml", "error occurred while parsing comment")
+#define XMLERR_ERRORPARSINGREFERENCE      QT_TRANSLATE_NOOP("QXml", "error occurred while parsing reference")
+#define XMLERR_INTERNALGENERALENTITYINDTD QT_TRANSLATE_NOOP("QXml", "internal general entity reference not allowed in DTD")
+#define XMLERR_EXTERNALGENERALENTITYINAV  QT_TRANSLATE_NOOP("QXml", "external parsed general entity reference not allowed in attribute value")
+#define XMLERR_EXTERNALGENERALENTITYINDTD QT_TRANSLATE_NOOP("QXml", "external parsed general entity reference not allowed in DTD")
+#define XMLERR_UNPARSEDENTITYREFERENCE    QT_TRANSLATE_NOOP("QXml", "unparsed entity reference in wrong context")
+#define XMLERR_RECURSIVEENTITIES          QT_TRANSLATE_NOOP("QXml", "recursive entities")
+#define XMLERR_ERRORINTEXTDECL            QT_TRANSLATE_NOOP("QXml", "error in the text declaration of an external entity")
+
+QT_BEGIN_NAMESPACE
+
+// the constants for the lookup table
+static const signed char cltWS      =  0; // white space
+static const signed char cltPer     =  1; // %
+static const signed char cltAmp     =  2; // &
+static const signed char cltGt      =  3; // >
+static const signed char cltLt      =  4; // <
+static const signed char cltSlash   =  5; // /
+static const signed char cltQm      =  6; // ?
+static const signed char cltEm      =  7; // !
+static const signed char cltDash    =  8; // -
+static const signed char cltCB      =  9; // ]
+static const signed char cltOB      = 10; // [
+static const signed char cltEq      = 11; // =
+static const signed char cltDq      = 12; // "
+static const signed char cltSq      = 13; // '
+static const signed char cltUnknown = 14;
+
+// Hack for letting QDom know where the skipped entity occurred
+// ### Qt5: the use of this variable means the code isn't reentrant.
+bool qt_xml_skipped_entity_in_content;
+
+// character lookup table
+static const signed char charLookupTable[256]={
+    cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x00 - 0x07
+    cltUnknown, // 0x08
+    cltWS,      // 0x09 \t
+    cltWS,      // 0x0A \n
+    cltUnknown, // 0x0B
+    cltUnknown, // 0x0C
+    cltWS,      // 0x0D \r
+    cltUnknown, // 0x0E
+    cltUnknown, // 0x0F
+    cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x17 - 0x16
+    cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x18 - 0x1F
+    cltWS,      // 0x20 Space
+    cltEm,      // 0x21 !
+    cltDq,      // 0x22 "
+    cltUnknown, // 0x23
+    cltUnknown, // 0x24
+    cltPer,     // 0x25 %
+    cltAmp,     // 0x26 &
+    cltSq,      // 0x27 '
+    cltUnknown, // 0x28
+    cltUnknown, // 0x29
+    cltUnknown, // 0x2A
+    cltUnknown, // 0x2B
+    cltUnknown, // 0x2C
+    cltDash,    // 0x2D -
+    cltUnknown, // 0x2E
+    cltSlash,   // 0x2F /
+    cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x30 - 0x37
+    cltUnknown, // 0x38
+    cltUnknown, // 0x39
+    cltUnknown, // 0x3A
+    cltUnknown, // 0x3B
+    cltLt,      // 0x3C <
+    cltEq,      // 0x3D =
+    cltGt,      // 0x3E >
+    cltQm,      // 0x3F ?
+    cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x40 - 0x47
+    cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x48 - 0x4F
+    cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x50 - 0x57
+    cltUnknown, // 0x58
+    cltUnknown, // 0x59
+    cltUnknown, // 0x5A
+    cltOB,      // 0x5B [
+    cltUnknown, // 0x5C
+    cltCB,      // 0x5D]
+    cltUnknown, // 0x5E
+    cltUnknown, // 0x5F
+    cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x60 - 0x67
+    cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x68 - 0x6F
+    cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x70 - 0x77
+    cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x78 - 0x7F
+    cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x80 - 0x87
+    cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x88 - 0x8F
+    cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x90 - 0x97
+    cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x98 - 0x9F
+    cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xA0 - 0xA7
+    cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xA8 - 0xAF
+    cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xB0 - 0xB7
+    cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xB8 - 0xBF
+    cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xC0 - 0xC7
+    cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xC8 - 0xCF
+    cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xD0 - 0xD7
+    cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xD8 - 0xDF
+    cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xE0 - 0xE7
+    cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xE8 - 0xEF
+    cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xF0 - 0xF7
+    cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown  // 0xF8 - 0xFF
+};
+
+//
+// local helper functions
+//
+
+/*
+  This function strips the TextDecl [77] ("<?xml ...?>") from the string \a
+  str. The stripped version is stored in \a str. If this function finds an
+  invalid TextDecl, it returns false, otherwise true.
+
+  This function is used for external entities since those can include an
+  TextDecl that must be stripped before inserting the entity.
+*/
+static bool stripTextDecl(QString& str)
+{
+    QString textDeclStart(QLatin1String("<?xml"));
+    if (str.startsWith(textDeclStart)) {
+        QRegExp textDecl(QString::fromLatin1(
+            "^<\\?xml\\s+"
+            "(version\\s*=\\s*((['\"])[-a-zA-Z0-9_.:]+\\3))?"
+            "\\s*"
+            "(encoding\\s*=\\s*((['\"])[A-Za-z][-a-zA-Z0-9_.]*\\6))?"
+            "\\s*\\?>"
+       ));
+        QString strTmp = str.replace(textDecl, QLatin1String(""));
+        if (strTmp.length() != str.length())
+            return false; // external entity has wrong TextDecl
+        str = strTmp;
+    }
+    return true;
+}
+
+
+class QXmlAttributesPrivate
+{
+};
+
+/* \class QXmlInputSourcePrivate
+    \internal
+
+  There's a slight misdesign in this class that can
+  be worth to keep in mind: the `str' member is
+  a buffer which QXmlInputSource::next() returns from,
+  and which is populated from the input device or input
+  stream. However, when the input is a QString(the user called
+  QXmlInputSource::setData()), `str' has two roles: it's the
+  buffer, but also the source. This /seems/ to be no problem
+  because in the case of having no device or stream, the QString
+  is read in one go.
+ */
+class QXmlInputSourcePrivate
+{
+public:
+    QIODevice *inputDevice;
+    QTextStream *inputStream;
+
+    QString str;
+    const QChar *unicode;
+    int pos;
+    int length;
+    bool nextReturnedEndOfData;
+#ifndef QT_NO_TEXTCODEC
+    QTextDecoder *encMapper;
+#endif
+
+    QByteArray encodingDeclBytes;
+    QString encodingDeclChars;
+    bool lookingForEncodingDecl;
+};
+class QXmlParseExceptionPrivate
+{
+public:
+    QXmlParseExceptionPrivate()
+        : column(-1), line(-1)
+    {
+    }
+    QXmlParseExceptionPrivate(const QXmlParseExceptionPrivate &other)
+        : msg(other.msg), column(other.column), line(other.line),
+          pub(other.pub), sys(other.sys)
+    {
+    }
+
+    QString msg;
+    int column;
+    int line;
+    QString pub;
+    QString sys;
+
+};
+
+class QXmlLocatorPrivate
+{
+};
+
+class QXmlDefaultHandlerPrivate
+{
+};
+
+class QXmlSimpleReaderPrivate
+{
+public:
+    ~QXmlSimpleReaderPrivate();
+private:
+    // functions
+    QXmlSimpleReaderPrivate(QXmlSimpleReader *reader);
+    void initIncrementalParsing();
+
+    // used to determine if elements are correctly nested
+    QStack<QString> tags;
+
+    // used by parseReference() and parsePEReference()
+    enum EntityRecognitionContext { InContent, InAttributeValue, InEntityValue, InDTD };
+
+    // used for entity declarations
+    struct ExternParameterEntity
+    {
+        ExternParameterEntity() {}
+        ExternParameterEntity(const QString &p, const QString &s)
+            : publicId(p), systemId(s) {}
+        QString publicId;
+        QString systemId;
+
+        Q_DUMMY_COMPARISON_OPERATOR(ExternParameterEntity)
+    };
+    struct ExternEntity
+    {
+        ExternEntity() {}
+        ExternEntity(const QString &p, const QString &s, const QString &n)
+            : publicId(p), systemId(s), notation(n) {}
+        QString publicId;
+        QString systemId;
+        QString notation;
+        Q_DUMMY_COMPARISON_OPERATOR(ExternEntity)
+    };
+    QMap<QString,ExternParameterEntity> externParameterEntities;
+    QMap<QString,QString> parameterEntities;
+    QMap<QString,ExternEntity> externEntities;
+    QMap<QString,QString> entities;
+
+    // used for parsing of entity references
+    struct XmlRef {
+        XmlRef()
+            : index(0) {}
+        XmlRef(const QString &_name, const QString &_value)
+            : name(_name), value(_value), index(0) {}
+        bool isEmpty() const { return index == value.length(); }
+        QChar next() { return value.at(index++); }
+        QString name;
+        QString value;
+        int index;
+    };
+    QStack<XmlRef> xmlRefStack;
+
+    // used for standalone declaration
+    enum Standalone { Yes, No, Unknown };
+
+    QString doctype; // only used for the doctype
+    QString xmlVersion; // only used to store the version information
+    QString encoding; // only used to store the encoding
+    Standalone standalone; // used to store the value of the standalone declaration
+
+    QString publicId; // used by parseExternalID() to store the public ID
+    QString systemId; // used by parseExternalID() to store the system ID
+
+    // Since publicId/systemId is used as temporary variables by parseExternalID(), it
+    // might overwrite the PUBLIC/SYSTEM for the document we're parsing. In effect, we would
+    // possibly send off an QXmlParseException that has the PUBLIC/SYSTEM of a entity declaration
+    // instead of those of the current document.
+    // Hence we have these two variables for storing the document's data.
+    QString thisPublicId;
+    QString thisSystemId;
+
+    QString attDeclEName; // use by parseAttlistDecl()
+    QString attDeclAName; // use by parseAttlistDecl()
+
+    // flags for some features support
+    bool useNamespaces;
+    bool useNamespacePrefixes;
+    bool reportWhitespaceCharData;
+    bool reportEntities;
+
+    // used to build the attribute list
+    QXmlAttributes attList;
+
+    // used in QXmlSimpleReader::parseContent() to decide whether character
+    // data was read
+    bool contentCharDataRead;
+
+    // helper classes
+    QScopedPointer<QXmlLocator> locator;
+    QXmlNamespaceSupport namespaceSupport;
+
+    // error string
+    QString error;
+
+    // arguments for parse functions (this is needed to allow incremental
+    // parsing)
+    bool parsePI_xmldecl;
+    bool parseName_useRef;
+    bool parseReference_charDataRead;
+    EntityRecognitionContext parseReference_context;
+    bool parseExternalID_allowPublicID;
+    EntityRecognitionContext parsePEReference_context;
+    QString parseString_s;
+
+    // for incremental parsing
+    struct ParseState {
+        typedef bool (QXmlSimpleReaderPrivate::*ParseFunction)();
+        ParseFunction function;
+        int state;
+    };
+    QStack<ParseState> *parseStack;
+
+    // used in parseProlog()
+    bool xmldecl_possible;
+    bool doctype_read;
+
+    // used in parseDoctype()
+    bool startDTDwasReported;
+
+    // used in parseString()
+    signed char Done;
+
+
+    // variables
+    QXmlContentHandler *contentHnd;
+    QXmlErrorHandler   *errorHnd;
+    QXmlDTDHandler     *dtdHnd;
+    QXmlEntityResolver *entityRes;
+    QXmlLexicalHandler *lexicalHnd;
+    QXmlDeclHandler    *declHnd;
+
+    QXmlInputSource *inputSource;
+
+    QChar c; // the character at reading position
+    int   lineNr; // number of line
+    int   columnNr; // position in line
+
+    QChar   nameArray[256]; // only used for names
+    QString nameValue; // only used for names
+    int     nameArrayPos;
+    int     nameValueLen;
+    QChar   refArray[256]; // only used for references
+    QString refValue; // only used for references
+    int     refArrayPos;
+    int     refValueLen;
+    QChar   stringArray[256]; // used for any other strings that are parsed
+    QString stringValue; // used for any other strings that are parsed
+    int     stringArrayPos;
+    int     stringValueLen;
+    QString emptyStr;
+
+    const QString &string();
+    void stringClear();
+    void stringAddC(QChar);
+    inline void stringAddC() { stringAddC(c); }
+    const QString &name();
+    void nameClear();
+    void nameAddC(QChar);
+    inline void nameAddC() { nameAddC(c); }
+    const QString &ref();
+    void refClear();
+    void refAddC(QChar);
+    inline void refAddC() { refAddC(c); }
+
+    // private functions
+    bool eat_ws();
+    bool next_eat_ws();
+
+    void QT_FASTCALL next();
+    bool atEnd();
+
+    void init(const QXmlInputSource* i);
+    void initData();
+
+    bool entityExist(const QString&) const;
+
+    bool parseBeginOrContinue(int state, bool incremental);
+
+    bool parseProlog();
+    bool parseElement();
+    bool processElementEmptyTag();
+    bool processElementETagBegin2();
+    bool processElementAttribute();
+    bool parseMisc();
+    bool parseContent();
+
+    bool parsePI();
+    bool parseDoctype();
+    bool parseComment();
+
+    bool parseName();
+    bool parseNmtoken();
+    bool parseAttribute();
+    bool parseReference();
+    bool processReference();
+
+    bool parseExternalID();
+    bool parsePEReference();
+    bool parseMarkupdecl();
+    bool parseAttlistDecl();
+    bool parseAttType();
+    bool parseAttValue();
+    bool parseElementDecl();
+    bool parseNotationDecl();
+    bool parseChoiceSeq();
+    bool parseEntityDecl();
+    bool parseEntityValue();
+
+    bool parseString();
+
+    bool insertXmlRef(const QString&, const QString&, bool);
+
+    bool reportEndEntities();
+    void reportParseError(const QString& error);
+
+    typedef bool (QXmlSimpleReaderPrivate::*ParseFunction) ();
+    void unexpectedEof(ParseFunction where, int state);
+    void parseFailed(ParseFunction where, int state);
+    void pushParseState(ParseFunction function, int state);
+
+    Q_DECLARE_PUBLIC(QXmlSimpleReader)
+    QXmlSimpleReader *q_ptr;
+
+    friend class QXmlSimpleReaderLocator;
+};
+
+/*!
+    \class QXmlParseException
+    \reentrant
+    \brief The QXmlParseException class is used to report errors with
+    the QXmlErrorHandler interface.
+
+    \inmodule QtXml
+    \ingroup xml-tools
+
+    The XML subsystem constructs an instance of this class when it
+    detects an error. You can retrieve the place where the error
+    occurred using systemId(), publicId(), lineNumber() and
+    columnNumber(), along with the error message(). The possible error
+    messages are:
+
+
+    \list
+        \o "no error occurred"
+        \o "error triggered by consumer"
+        \o "unexpected end of file"
+        \o "more than one document type definition"
+        \o "error occurred while parsing element"
+        \o "tag mismatch"
+        \o "error occurred while parsing content"
+        \o "unexpected character"
+        \o "invalid name for processing instruction"
+        \o "version expected while reading the XML declaration"
+        \o "wrong value for standalone declaration"
+        \o "encoding declaration or standalone declaration expected while reading the XML declaration"
+        \o "standalone declaration expected while reading the XML declaration"
+        \o "error occurred while parsing document type definition"
+        \o "letter is expected"
+        \o "error occurred while parsing comment"
+        \o "error occurred while parsing reference"
+        \o "internal general entity reference not allowed in DTD"
+        \o "external parsed general entity reference not allowed in attribute value"
+        \o "external parsed general entity reference not allowed in DTD"
+        \o "unparsed entity reference n wrong context"
+        \o "recursive entities"
+        \o "error in the text declaration of an external entity"
+    \endlist
+
+    Note that, if you want to display these error messages to your
+    application's users, they will be displayed in English unless
+    they are explicitly translated.
+
+    \sa QXmlErrorHandler, QXmlReader
+*/
+
+/*!
+    Constructs a parse exception with the error string \a name for
+    column \a c and line \a l for the public identifier \a p and the
+    system identifier \a s.
+*/
+
+QXmlParseException::QXmlParseException(const QString& name, int c, int l,
+                                       const QString& p, const QString& s)
+    : d(new QXmlParseExceptionPrivate)
+{
+    d->msg = name;
+    d->column = c;
+    d->line = l;
+    d->pub = p;
+    d->sys = s;
+}
+
+/*!
+    Creates a copy of \a other.
+*/
+QXmlParseException::QXmlParseException(const QXmlParseException& other) :
+     d(new QXmlParseExceptionPrivate(*other.d))
+{
+
+}
+
+/*!
+    Destroys the QXmlParseException.
+*/
+QXmlParseException::~QXmlParseException()
+{
+}
+
+/*!
+    Returns the error message.
+*/
+QString QXmlParseException::message() const
+{
+    return d->msg;
+}
+/*!
+    Returns the column number where the error occurred.
+*/
+int QXmlParseException::columnNumber() const
+{
+    return d->column;
+}
+/*!
+    Returns the line number where the error occurred.
+*/
+int QXmlParseException::lineNumber() const
+{
+    return d->line;
+}
+/*!
+    Returns the public identifier where the error occurred.
+*/
+QString QXmlParseException::publicId() const
+{
+    return d->pub;
+}
+/*!
+    Returns the system identifier where the error occurred.
+*/
+QString QXmlParseException::systemId() const
+{
+    return d->sys;
+}
+
+
+/*!
+    \class QXmlLocator
+    \reentrant
+    \brief The QXmlLocator class provides the XML handler classes with
+    information about the parsing position within a file.
+
+    \inmodule QtXml
+    \ingroup xml-tools
+
+    The reader reports a QXmlLocator to the content handler before it
+    starts to parse the document. This is done with the
+    QXmlContentHandler::setDocumentLocator() function. The handler
+    classes can now use this locator to get the position (lineNumber()
+    and columnNumber()) that the reader has reached.
+*/
+
+/*!
+    Constructor.
+*/
+QXmlLocator::QXmlLocator()
+{
+}
+
+/*!
+    Destructor.
+*/
+QXmlLocator::~QXmlLocator()
+{
+}
+
+/*!
+    \fn int QXmlLocator::columnNumber() const
+
+    Returns the column number (starting at 1) or -1 if there is no
+    column number available.
+*/
+
+/*!
+    \fn int QXmlLocator::lineNumber() const
+
+    Returns the line number (starting at 1) or -1 if there is no line
+    number available.
+*/
+
+class QXmlSimpleReaderLocator : public QXmlLocator
+{
+public:
+    QXmlSimpleReaderLocator(QXmlSimpleReader* parent)
+    {
+        reader = parent;
+    }
+    ~QXmlSimpleReaderLocator()
+    {
+    }
+
+    int columnNumber() const
+    {
+        return (reader->d_ptr->columnNr == -1 ? -1 : reader->d_ptr->columnNr + 1);
+    }
+    int lineNumber() const
+    {
+        return (reader->d_ptr->lineNr == -1 ? -1 : reader->d_ptr->lineNr + 1);
+    }
+//    QString getPublicId()
+//    QString getSystemId()
+
+private:
+    QXmlSimpleReader *reader;
+};
+
+/*********************************************
+ *
+ * QXmlNamespaceSupport
+ *
+ *********************************************/
+
+typedef QMap<QString, QString> NamespaceMap;
+
+class QXmlNamespaceSupportPrivate
+{
+public:
+    QXmlNamespaceSupportPrivate()
+    {
+        ns.insert(QLatin1String("xml"), QLatin1String("http://www.w3.org/XML/1998/namespace")); // the XML namespace
+    }
+
+    ~QXmlNamespaceSupportPrivate()
+    {
+    }
+
+    QStack<NamespaceMap> nsStack;
+    NamespaceMap ns;
+};
+
+/*!
+    \class QXmlNamespaceSupport
+    \since 4.4
+    \reentrant
+    \brief The QXmlNamespaceSupport class is a helper class for XML
+    readers which want to include namespace support.
+
+    \inmodule QtXml
+    \ingroup xml-tools
+
+    You can set the prefix for the current namespace with setPrefix(),
+    and get the list of current prefixes (or those for a given URI)
+    with prefixes(). The namespace URI is available from uri(). Use
+    pushContext() to start a new namespace context, and popContext()
+    to return to the previous namespace context. Use splitName() or
+    processName() to split a name into its prefix and local name.
+
+    \sa {Namespace Support via Features}
+*/
+
+/*!
+    Constructs a QXmlNamespaceSupport.
+*/
+QXmlNamespaceSupport::QXmlNamespaceSupport()
+{
+    d = new QXmlNamespaceSupportPrivate;
+}
+
+/*!
+    Destroys a QXmlNamespaceSupport.
+*/
+QXmlNamespaceSupport::~QXmlNamespaceSupport()
+{
+    delete d;
+}
+
+/*!
+    This function declares a prefix \a pre in the current namespace
+    context to be the namespace URI \a uri. The prefix remains in
+    force until this context is popped, unless it is shadowed in a
+    descendant context.
+
+    Note that there is an asymmetry in this library. prefix() does not
+    return the default "" prefix, even if you have declared one; to
+    check for a default prefix, you must look it up explicitly using
+    uri(). This asymmetry exists to make it easier to look up prefixes
+    for attribute names, where the default prefix is not allowed.
+*/
+void QXmlNamespaceSupport::setPrefix(const QString& pre, const QString& uri)
+{
+    if(pre.isNull()) {
+        d->ns.insert(QLatin1String(""), uri);
+    } else {
+        d->ns.insert(pre, uri);
+    }
+}
+
+/*!
+    Returns one of the prefixes mapped to the namespace URI \a uri.
+
+    If more than one prefix is currently mapped to the same URI, this
+    function makes an arbitrary selection; if you want all of the
+    prefixes, use prefixes() instead.
+
+    Note: to check for a default prefix, use the uri() function with
+    an argument of "".
+*/
+QString QXmlNamespaceSupport::prefix(const QString& uri) const
+{
+    NamespaceMap::const_iterator itc, it = d->ns.constBegin();
+    while ((itc=it) != d->ns.constEnd()) {
+        ++it;
+        if (*itc == uri && !itc.key().isEmpty())
+            return itc.key();
+    }
+    return QLatin1String("");
+}
+
+/*!
+    Looks up the prefix \a prefix in the current context and returns
+    the currently-mapped namespace URI. Use the empty string ("") for
+    the default namespace.
+*/
+QString QXmlNamespaceSupport::uri(const QString& prefix) const
+{
+    return d->ns[prefix];
+}
+
+/*!
+    Splits the name \a qname at the ':' and returns the prefix in \a
+    prefix and the local name in \a localname.
+
+    \sa processName()
+*/
+void QXmlNamespaceSupport::splitName(const QString& qname, QString& prefix,
+                                     QString& localname) const
+{
+    int pos = qname.indexOf(QLatin1Char(':'));
+    if (pos == -1)
+        pos = qname.size();
+
+    prefix = qname.left(pos);
+    localname = qname.mid(pos+1);
+}
+
+/*!
+    Processes a raw XML 1.0 name in the current context by removing
+    the prefix and looking it up among the prefixes currently
+    declared.
+
+    \a qname is the raw XML 1.0 name to be processed. \a isAttribute
+    is true if the name is an attribute name.
+
+    This function stores the namespace URI in \a nsuri (which will be
+    set to an empty string if the raw name has an undeclared prefix),
+    and stores the local name (without prefix) in \a localname (which
+    will be set to an empty string if no namespace is in use).
+
+    Note that attribute names are processed differently than element
+    names: an unprefixed element name gets the default namespace (if
+    any), while an unprefixed attribute name does not.
+*/
+void QXmlNamespaceSupport::processName(const QString& qname,
+        bool isAttribute,
+        QString& nsuri, QString& localname) const
+{
+    int len = qname.size();
+    const QChar *data = qname.constData();
+    for (int pos = 0; pos < len; ++pos) {
+        if (data[pos] == QLatin1Char(':')) {
+            nsuri = uri(qname.left(pos));
+            localname = qname.mid(pos + 1);
+            return;
+        }
+    }
+
+    // there was no ':'
+    nsuri.clear();
+    // attributes don't take default namespace
+    if (!isAttribute && !d->ns.isEmpty()) {
+	/*
+	    We want to access d->ns.value(""), but as an optimization
+	    we use the fact that "" compares less than any other
+	    string, so it's either first in the map or not there.
+	*/
+        NamespaceMap::const_iterator first = d->ns.constBegin();
+        if (first.key().isEmpty())
+            nsuri = first.value(); // get default namespace
+    }
+    localname = qname;
+}
+
+/*!
+    Returns a list of all the prefixes currently declared.
+
+    If there is a default prefix, this function does not return it in
+    the list; check for the default prefix using uri() with an
+    argument of "".
+*/
+QStringList QXmlNamespaceSupport::prefixes() const
+{
+    QStringList list;
+
+    NamespaceMap::const_iterator itc, it = d->ns.constBegin();
+    while ((itc=it) != d->ns.constEnd()) {
+        ++it;
+        if (!itc.key().isEmpty())
+            list.append(itc.key());
+    }
+    return list;
+}
+
+/*!
+    \overload
+
+    Returns a list of all prefixes currently declared for the
+    namespace URI \a uri.
+
+    The "xml:" prefix is included. If you only want one prefix that is
+    mapped to the namespace URI, and you don't care which one you get,
+    use the prefix() function instead.
+
+    Note: The empty (default) prefix is never included in this list;
+    to check for the presence of a default namespace, call uri() with
+    "" as the argument.
+*/
+QStringList QXmlNamespaceSupport::prefixes(const QString& uri) const
+{
+    QStringList list;
+
+    NamespaceMap::const_iterator itc, it = d->ns.constBegin();
+    while ((itc=it) != d->ns.constEnd()) {
+        ++it;
+        if (*itc == uri && !itc.key().isEmpty())
+            list.append(itc.key());
+    }
+    return list;
+}
+
+/*!
+    Starts a new namespace context.
+
+    Normally, you should push a new context at the beginning of each
+    XML element: the new context automatically inherits the
+    declarations of its parent context, and it also keeps track of
+    which declarations were made within this context.
+
+    \sa popContext()
+*/
+void QXmlNamespaceSupport::pushContext()
+{
+    d->nsStack.push(d->ns);
+}
+
+/*!
+    Reverts to the previous namespace context.
+
+    Normally, you should pop the context at the end of each XML
+    element. After popping the context, all namespace prefix mappings
+    that were previously in force are restored.
+
+    \sa pushContext()
+*/
+void QXmlNamespaceSupport::popContext()
+{
+    d->ns.clear();
+    if(!d->nsStack.isEmpty())
+        d->ns = d->nsStack.pop();
+}
+
+/*!
+    Resets this namespace support object ready for reuse.
+*/
+void QXmlNamespaceSupport::reset()
+{
+    QXmlNamespaceSupportPrivate *newD = new QXmlNamespaceSupportPrivate;
+    delete d;
+    d = newD;
+}
+
+
+
+/*********************************************
+ *
+ * QXmlAttributes
+ *
+ *********************************************/
+
+/*!
+    \class QXmlAttributes
+    \reentrant
+    \brief The QXmlAttributes class provides XML attributes.
+
+    \inmodule QtXml
+    \ingroup xml-tools
+
+    If attributes are reported by QXmlContentHandler::startElement()
+    this class is used to pass the attribute values.
+
+    Use index() to locate the position of an attribute in the list,
+    count() to retrieve the number of attributes, and clear() to
+    remove the attributes. New attributes can be added with append().
+    Use type() to get an attribute's type and value() to get its
+    value. The attribute's name is available from localName() or
+    qName(), and its namespace URI from uri().
+
+*/
+
+/*!
+    \fn QXmlAttributes::QXmlAttributes()
+
+    Constructs an empty attribute list.
+*/
+
+/*!
+    \fn QXmlAttributes::~QXmlAttributes()
+
+    Destroys the attributes object.
+*/
+
+/*!
+    Looks up the index of an attribute by the qualified name \a qName.
+
+    Returns the index of the attribute or -1 if it wasn't found.
+
+    \sa {Namespace Support via Features}
+*/
+int QXmlAttributes::index(const QString& qName) const
+{
+    for (int i = 0; i < attList.size(); ++i) {
+        if (attList.at(i).qname == qName)
+            return i;
+    }
+    return -1;
+}
+
+/*! \overload
+  */
+int QXmlAttributes::index(const QLatin1String& qName) const
+{
+    for (int i = 0; i < attList.size(); ++i) {
+        if (attList.at(i).qname == qName)
+            return i;
+    }
+    return -1;
+}
+
+/*!
+    \overload
+
+    Looks up the index of an attribute by a namespace name.
+
+    \a uri specifies the namespace URI, or an empty string if the name
+    has no namespace URI. \a localPart specifies the attribute's local
+    name.
+
+    Returns the index of the attribute, or -1 if it wasn't found.
+
+    \sa {Namespace Support via Features}
+*/
+int QXmlAttributes::index(const QString& uri, const QString& localPart) const
+{
+    for (int i = 0; i < attList.size(); ++i) {
+        const Attribute &att = attList.at(i);
+        if (att.uri == uri && att.localname == localPart)
+            return i;
+    }
+    return -1;
+}
+
+/*!
+    Returns the number of attributes in the list.
+
+    \sa count()
+*/
+int QXmlAttributes::length() const
+{
+    return attList.count();
+}
+
+/*!
+    \fn int QXmlAttributes::count() const
+
+    Returns the number of attributes in the list. This function is
+    equivalent to length().
+*/
+
+/*!
+    Looks up an attribute's local name for the attribute at position
+    \a index. If no namespace processing is done, the local name is
+    an empty string.
+
+    \sa {Namespace Support via Features}
+*/
+QString QXmlAttributes::localName(int index) const
+{
+    return attList.at(index).localname;
+}
+
+/*!
+    Looks up an attribute's XML 1.0 qualified name for the attribute
+    at position \a index.
+
+    \sa {Namespace Support via Features}
+*/
+QString QXmlAttributes::qName(int index) const
+{
+    return attList.at(index).qname;
+}
+
+/*!
+    Looks up an attribute's namespace URI for the attribute at
+    position \a index. If no namespace processing is done or if the
+    attribute has no namespace, the namespace URI is an empty string.
+
+    \sa {Namespace Support via Features}
+*/
+QString QXmlAttributes::uri(int index) const
+{
+    return attList.at(index).uri;
+}
+
+/*!
+    Looks up an attribute's type for the attribute at position \a
+    index.
+
+    Currently only "CDATA" is returned.
+*/
+QString QXmlAttributes::type(int) const
+{
+    return QLatin1String("CDATA");
+}
+
+/*!
+    \overload
+
+    Looks up an attribute's type for the qualified name \a qName.
+
+    Currently only "CDATA" is returned.
+*/
+QString QXmlAttributes::type(const QString&) const
+{
+    return QLatin1String("CDATA");
+}
+
+/*!
+    \overload
+
+    Looks up an attribute's type by namespace name.
+
+    \a uri specifies the namespace URI and \a localName specifies the
+    local name. If the name has no namespace URI, use an empty string
+    for \a uri.
+
+    Currently only "CDATA" is returned.
+*/
+QString QXmlAttributes::type(const QString&, const QString&) const
+{
+    return QLatin1String("CDATA");
+}
+
+/*!
+    Returns an attribute's value for the attribute at position \a
+    index. The index must be a valid position
+    (i.e., 0 <= \a index < count()).
+*/
+QString QXmlAttributes::value(int index) const
+{
+    return attList.at(index).value;
+}
+
+/*!
+    \overload
+
+    Returns an attribute's value for the qualified name \a qName, or an
+    empty string if no attribute exists for the name given.
+
+    \sa {Namespace Support via Features}
+*/
+QString QXmlAttributes::value(const QString& qName) const
+{
+    int i = index(qName);
+    if (i == -1)
+        return QString();
+    return attList.at(i).value;
+}
+
+/*!
+    \overload
+
+    Returns an attribute's value for the qualified name \a qName, or an
+    empty string if no attribute exists for the name given.
+
+    \sa {Namespace Support via Features}
+*/
+QString QXmlAttributes::value(const QLatin1String& qName) const
+{
+    int i = index(qName);
+    if (i == -1)
+        return QString();
+    return attList.at(i).value;
+}
+
+/*!
+    \overload
+
+    Returns an attribute's value by namespace name.
+
+    \a uri specifies the namespace URI, or an empty string if the name
+    has no namespace URI. \a localName specifies the attribute's local
+    name.
+*/
+QString QXmlAttributes::value(const QString& uri, const QString& localName) const
+{
+    int i = index(uri, localName);
+    if (i == -1)
+        return QString();
+    return attList.at(i).value;
+}
+
+/*!
+    Clears the list of attributes.
+
+    \sa append()
+*/
+void QXmlAttributes::clear()
+{
+    attList.clear();
+}
+
+/*!
+    Appends a new attribute entry to the list of attributes. The
+    qualified name of the attribute is \a qName, the namespace URI is
+    \a uri and the local name is \a localPart. The value of the
+    attribute is \a value.
+
+    \sa qName() uri() localName() value()
+*/
+void QXmlAttributes::append(const QString &qName, const QString &uri, const QString &localPart, const QString &value)
+{
+    Attribute att;
+    att.qname = qName;
+    att.uri = uri;
+    att.localname = localPart;
+    att.value = value;
+
+    attList.append(att);
+}
+
+
+/*********************************************
+ *
+ * QXmlInputSource
+ *
+ *********************************************/
+
+/*!
+    \class QXmlInputSource
+    \reentrant
+    \brief The QXmlInputSource class provides the input data for the
+    QXmlReader subclasses.
+
+    \inmodule QtXml
+    \ingroup xml-tools
+
+    All subclasses of QXmlReader read the input XML document from this
+    class.
+
+    This class recognizes the encoding of the data by reading the
+    encoding declaration in the XML file if it finds one, and reading
+    the data using the corresponding encoding. If it does not find an
+    encoding declaration, then it assumes that the data is either in
+    UTF-8 or UTF-16, depending on whether it can find a byte-order
+    mark.
+
+    There are two ways to populate the input source with data: you can
+    construct it with a QIODevice* so that the input source reads the
+    data from that device. Or you can set the data explicitly with one
+    of the setData() functions.
+
+    Usually you either construct a QXmlInputSource that works on a
+    QIODevice* or you construct an empty QXmlInputSource and set the
+    data with setData(). There are only rare occasions where you would
+    want to mix both methods.
+
+    The QXmlReader subclasses use the next() function to read the
+    input character by character. If you want to start from the
+    beginning again, use reset().
+
+    The functions data() and fetchData() are useful if you want to do
+    something with the data other than parsing, e.g. displaying the
+    raw XML file. The benefit of using the QXmlInputClass in such
+    cases is that it tries to use the correct encoding.
+
+    \sa QXmlReader QXmlSimpleReader
+*/
+
+// the following two are guaranteed not to be a character
+const ushort QXmlInputSource::EndOfData = 0xfffe;
+const ushort QXmlInputSource::EndOfDocument = 0xffff;
+
+/*
+    Common part of the constructors.
+*/
+void QXmlInputSource::init()
+{
+    d = new QXmlInputSourcePrivate;
+
+    QT_TRY {
+        d->inputDevice = 0;
+        d->inputStream = 0;
+
+        setData(QString());
+#ifndef QT_NO_TEXTCODEC
+        d->encMapper = 0;
+#endif
+        d->nextReturnedEndOfData = true; // first call to next() will call fetchData()
+
+        d->encodingDeclBytes.clear();
+        d->encodingDeclChars.clear();
+        d->lookingForEncodingDecl = true;
+    } QT_CATCH(...) {
+        delete(d);
+        QT_RETHROW;
+    }
+}
+
+/*!
+    Constructs an input source which contains no data.
+
+    \sa setData()
+*/
+QXmlInputSource::QXmlInputSource()
+{
+    init();
+}
+
+/*!
+    Constructs an input source and gets the data from device \a dev.
+    If \a dev is not open, it is opened in read-only mode. If \a dev
+    is 0 or it is not possible to read from the device, the input
+    source will contain no data.
+
+    \sa setData() fetchData() QIODevice
+*/
+QXmlInputSource::QXmlInputSource(QIODevice *dev)
+{
+    init();
+    d->inputDevice = dev;
+    d->inputDevice->setTextModeEnabled(false);
+}
+
+#ifdef QT3_SUPPORT
+/*!
+    Use the QXmlInputSource(QIODevice *) constructor instead, with
+    the device used by \a stream.
+
+    \sa QTextStream::device()
+*/
+QXmlInputSource::QXmlInputSource(QTextStream& stream)
+{
+    init();
+    d->inputStream = &stream;
+}
+
+/*!
+    Use QXmlInputSource(&\a file) instead.
+*/
+QXmlInputSource::QXmlInputSource(QFile& file)
+{
+    init();
+    d->inputDevice = &file;
+}
+#endif
+
+/*!
+    Destructor.
+*/
+QXmlInputSource::~QXmlInputSource()
+{
+    // ### Qt 5: close the input device. See task 153111
+#ifndef QT_NO_TEXTCODEC
+    delete d->encMapper;
+#endif
+    delete d;
+}
+
+/*!
+Returns the next character of the input source. If this function
+reaches the end of available data, it returns
+QXmlInputSource::EndOfData. If you call next() after that, it
+tries to fetch more data by calling fetchData(). If the
+fetchData() call results in new data, this function returns the
+first character of that data; otherwise it returns
+QXmlInputSource::EndOfDocument.
+
+Readers, such as QXmlSimpleReader, will assume that the end of
+the XML document has been reached if the this function returns
+QXmlInputSource::EndOfDocument, and will check that the
+supplied input is well-formed. Therefore, when reimplementing
+this function, it is important to ensure that this behavior is
+duplicated.
+
+\sa reset() fetchData() QXmlSimpleReader::parse() QXmlSimpleReader::parseContinue()
+*/
+QChar QXmlInputSource::next()
+{
+    if (d->pos >= d->length) {
+        if (d->nextReturnedEndOfData) {
+            d->nextReturnedEndOfData = false;
+            fetchData();
+            if (d->pos >= d->length) {
+                return EndOfDocument;
+            }
+            return next();
+        }
+        d->nextReturnedEndOfData = true;
+        return EndOfData;
+    }
+
+    // QXmlInputSource has no way to signal encoding errors. The best we can do
+    // is return EndOfDocument. We do *not* return EndOfData, because the reader
+    // will then just call this function again to get the next char.
+    QChar c = d->unicode[d->pos++];
+    if (c.unicode() == EndOfData)
+        c = EndOfDocument;
+    return c;
+}
+
+/*!
+    This function sets the position used by next() to the beginning of
+    the data returned by data(). This is useful if you want to use the
+    input source for more than one parse.
+
+    \note In the case that the underlying data source is a QIODevice,
+    the current position in the device is not automatically set to the
+    start of input. Call QIODevice::seek(0) on the device to do this.
+
+    \sa next()
+*/
+void QXmlInputSource::reset()
+{
+    d->nextReturnedEndOfData = false;
+    d->pos = 0;
+}
+
+/*!
+    Returns the data the input source contains or an empty string if the
+    input source does not contain any data.
+
+    \sa setData() QXmlInputSource() fetchData()
+*/
+QString QXmlInputSource::data() const
+{
+    if (d->nextReturnedEndOfData) {
+        QXmlInputSource *that = const_cast<QXmlInputSource*>(this);
+        that->d->nextReturnedEndOfData = false;
+        that->fetchData();
+    }
+    return d->str;
+}
+
+/*!
+    Sets the data of the input source to \a dat.
+
+    If the input source already contains data, this function deletes
+    that data first.
+
+    \sa data()
+*/
+void QXmlInputSource::setData(const QString& dat)
+{
+    d->str = dat;
+    d->unicode = dat.unicode();
+    d->pos = 0;
+    d->length = d->str.length();
+    d->nextReturnedEndOfData = false;
+}
+
+/*!
+    \overload
+
+    The data \a dat is passed through the correct text-codec, before
+    it is set.
+*/
+void QXmlInputSource::setData(const QByteArray& dat)
+{
+    setData(fromRawData(dat));
+}
+
+/*!
+    This function reads more data from the device that was set during
+    construction. If the input source already contained data, this
+    function deletes that data first.
+
+    This object contains no data after a call to this function if the
+    object was constructed without a device to read data from or if
+    this function was not able to get more data from the device.
+
+    There are two occasions where a fetch is done implicitly by
+    another function call: during construction (so that the object
+    starts out with some initial data where available), and during a
+    call to next() (if the data had run out).
+
+    You don't normally need to use this function if you use next().
+
+    \sa data() next() QXmlInputSource()
+*/
+
+void QXmlInputSource::fetchData()
+{
+    enum
+    {
+        BufferSize = 1024
+    };
+
+    QByteArray rawData;
+
+    if (d->inputDevice || d->inputStream) {
+        QIODevice *device = d->inputDevice ? d->inputDevice : d->inputStream->device();
+
+        if (!device) {
+            if (d->inputStream && d->inputStream->string()) {
+                QString *s = d->inputStream->string();
+                rawData = QByteArray((const char *) s->constData(), s->size() * sizeof(QChar));
+            }
+        } else if (device->isOpen() || device->open(QIODevice::ReadOnly)) {
+            rawData.resize(BufferSize);
+            qint64 size = device->read(rawData.data(), BufferSize);
+
+            if (size != -1) {
+                // We don't want to give fromRawData() less than four bytes if we can avoid it.
+                while (size < 4) {
+                    if (!device->waitForReadyRead(-1))
+                        break;
+                    int ret = device->read(rawData.data() + size, BufferSize - size);
+                    if (ret <= 0)
+                        break;
+                    size += ret;
+                }
+            }
+
+            rawData.resize(qMax(qint64(0), size));
+        }
+
+        /* We do this inside the "if (d->inputDevice ..." scope
+         * because if we're not using a stream or device, that is,
+         * the user set a QString manually, we don't want to set
+         * d->str. */
+        setData(fromRawData(rawData));
+    }
+}
+
+#ifndef QT_NO_TEXTCODEC
+static QString extractEncodingDecl(const QString &text, bool *needMoreText)
+{
+    *needMoreText = false;
+
+    int l = text.length();
+    QString snip = QString::fromLatin1("<?xml").left(l);
+    if (l > 0 && !text.startsWith(snip))
+        return QString();
+
+    int endPos = text.indexOf(QLatin1Char('>'));
+    if (endPos == -1) {
+        *needMoreText = l < 255; // we won't look forever
+        return QString();
+    }
+
+    int pos = text.indexOf(QLatin1String("encoding"));
+    if (pos == -1 || pos >= endPos)
+        return QString();
+
+    while (pos < endPos) {
+        ushort uc = text.at(pos).unicode();
+        if (uc == '\'' || uc == '"')
+            break;
+        ++pos;
+    }
+
+    if (pos == endPos)
+        return QString();
+
+    QString encoding;
+    ++pos;
+    while (pos < endPos) {
+        ushort uc = text.at(pos).unicode();
+        if (uc == '\'' || uc == '"')
+            break;
+        encoding.append(uc);
+        ++pos;
+    }
+
+    return encoding;
+}
+#endif // QT_NO_TEXTCODEC
+
+/*!
+    This function reads the XML file from \a data and tries to
+    recognize the encoding. It converts the raw data \a data into a
+    QString and returns it. It tries its best to get the correct
+    encoding for the XML file.
+
+    If \a beginning is true, this function assumes that the data
+    starts at the beginning of a new XML document and looks for an
+    encoding declaration. If \a beginning is false, it converts the
+    raw data using the encoding determined from prior calls.
+*/
+QString QXmlInputSource::fromRawData(const QByteArray &data, bool beginning)
+{
+#ifdef QT_NO_TEXTCODEC
+    Q_UNUSED(beginning);
+    return QString::fromAscii(data.constData(), data.size());
+#else
+    if (data.size() == 0)
+        return QString();
+    if (beginning) {
+        delete d->encMapper;
+        d->encMapper = 0;
+    }
+
+    int mib = 106; // UTF-8
+
+    // This is the initial UTF codec we will read the encoding declaration with
+    if (d->encMapper == 0) {
+        d->encodingDeclBytes.clear();
+        d->encodingDeclChars.clear();
+        d->lookingForEncodingDecl = true;
+
+        // look for byte order mark and read the first 5 characters
+        if (data.size() >= 4) {
+            uchar ch1 = data.at(0);
+            uchar ch2 = data.at(1);
+            uchar ch3 = data.at(2);
+            uchar ch4 = data.at(3);
+
+            if ((ch1 == 0 && ch2 == 0 && ch3 == 0xfe && ch4 == 0xff) ||
+                (ch1 == 0xff && ch2 == 0xfe && ch3 == 0 && ch4 == 0))
+                mib = 1017; // UTF-32 with byte order mark
+            else if (ch1 == 0x3c && ch2 == 0x00 && ch3 == 0x00 && ch4 == 0x00)
+                mib = 1019; // UTF-32LE
+            else if (ch1 == 0x00 && ch2 == 0x00 && ch3 == 0x00 && ch4 == 0x3c)
+                mib = 1018; // UTF-32BE
+        }
+        if (mib == 106 && data.size() >= 2) {
+            uchar ch1 = data.at(0);
+            uchar ch2 = data.at(1);
+
+            if ((ch1 == 0xfe && ch2 == 0xff) || (ch1 == 0xff && ch2 == 0xfe))
+                mib = 1015; // UTF-16 with byte order mark
+            else if (ch1 == 0x3c && ch2 == 0x00)
+                mib = 1014; // UTF-16LE
+            else if (ch1 == 0x00 && ch2 == 0x3c)
+                mib = 1013; // UTF-16BE
+        }
+
+        QTextCodec *codec = QTextCodec::codecForMib(mib);
+        Q_ASSERT(codec);
+
+        d->encMapper = codec->makeDecoder();
+    }
+
+    QString input = d->encMapper->toUnicode(data, data.size());
+
+    if (d->lookingForEncodingDecl) {
+        d->encodingDeclChars += input;
+
+        bool needMoreText;
+        QString encoding = extractEncodingDecl(d->encodingDeclChars, &needMoreText);
+
+        if (!encoding.isEmpty()) {
+            if (QTextCodec *codec = QTextCodec::codecForName(encoding.toLatin1())) {
+                /* If the encoding is the same, we don't have to do toUnicode() all over again. */
+                if(codec->mibEnum() != mib) {
+                    delete d->encMapper;
+                    d->encMapper = codec->makeDecoder();
+
+                    /* The variable input can potentially be large, so we deallocate
+                     * it before calling toUnicode() in order to avoid having two
+                     * large QStrings in memory simultaneously. */
+                    input.clear();
+
+                    // prime the decoder with the data so far
+                    d->encMapper->toUnicode(d->encodingDeclBytes, d->encodingDeclBytes.size());
+                    // now feed it the new data
+                    input = d->encMapper->toUnicode(data, data.size());
+                }
+            }
+        }
+
+        d->encodingDeclBytes += data;
+        d->lookingForEncodingDecl = needMoreText;
+    }
+
+    return input;
+#endif
+}
+
+
+/*********************************************
+ *
+ * QXmlDefaultHandler
+ *
+ *********************************************/
+
+/*!
+    \class QXmlContentHandler
+    \reentrant
+    \brief The QXmlContentHandler class provides an interface to
+    report the logical content of XML data.
+
+    \inmodule QtXml
+    \ingroup xml-tools
+
+    If the application needs to be informed of basic parsing events,
+    it can implement this interface and activate it using
+    QXmlReader::setContentHandler(). The reader can then report basic
+    document-related events like the start and end of elements and
+    character data through this interface.
+
+    The order of events in this interface is very important, and
+    mirrors the order of information in the document itself. For
+    example, all of an element's content (character data, processing
+    instructions, and sub-elements) appears, in order, between the
+    startElement() event and the corresponding endElement() event.
+
+    The class QXmlDefaultHandler provides a default implementation for
+    this interface; subclassing from the QXmlDefaultHandler class is
+    very convenient if you only want to be informed of some parsing
+    events.
+
+    The startDocument() function is called at the start of the
+    document, and endDocument() is called at the end. Before parsing
+    begins setDocumentLocator() is called. For each element
+    startElement() is called, with endElement() being called at the
+    end of each element. The characters() function is called with
+    chunks of character data; ignorableWhitespace() is called with
+    chunks of whitespace and processingInstruction() is called with
+    processing instructions. If an entity is skipped skippedEntity()
+    is called. At the beginning of prefix-URI scopes
+    startPrefixMapping() is called.
+
+    \sa QXmlDTDHandler, QXmlDeclHandler, QXmlEntityResolver, QXmlErrorHandler,
+        QXmlLexicalHandler, {Introduction to SAX2}
+*/
+
+/*!
+    \fn QXmlContentHandler::~QXmlContentHandler()
+
+    Destroys the content handler.
+*/
+
+/*!
+    \fn void QXmlContentHandler::setDocumentLocator(QXmlLocator* locator)
+
+    The reader calls this function before it starts parsing the
+    document. The argument \a locator is a pointer to a QXmlLocator
+    which allows the application to get the parsing position within
+    the document.
+
+    Do not destroy the \a locator; it is destroyed when the reader is
+    destroyed. (Do not use the \a locator after the reader is
+    destroyed).
+*/
+
+/*!
+    \fn bool QXmlContentHandler::startDocument()
+
+    The reader calls this function when it starts parsing the
+    document. The reader calls this function just once, after the call
+    to setDocumentLocator(), and before any other functions in this
+    class or in the QXmlDTDHandler class are called.
+
+    If this function returns false the reader stops parsing and
+    reports an error. The reader uses the function errorString() to
+    get the error message.
+
+    \sa endDocument()
+*/
+
+/*!
+    \fn bool QXmlContentHandler::endDocument()
+
+    The reader calls this function after it has finished parsing. It
+    is called just once, and is the last handler function called. It
+    is called after the reader has read all input or has abandoned
+    parsing because of a fatal error.
+
+    If this function returns false the reader stops parsing and
+    reports an error. The reader uses the function errorString() to
+    get the error message.
+
+    \sa startDocument()
+*/
+
+/*!
+    \fn bool QXmlContentHandler::startPrefixMapping(const QString& prefix, const QString& uri)
+
+    The reader calls this function to signal the begin of a prefix-URI
+    namespace mapping scope. This information is not necessary for
+    normal namespace processing since the reader automatically
+    replaces prefixes for element and attribute names.
+
+    Note that startPrefixMapping() and endPrefixMapping() calls are
+    not guaranteed to be properly nested relative to each other: all
+    startPrefixMapping() events occur before the corresponding
+    startElement() event, and all endPrefixMapping() events occur
+    after the corresponding endElement() event, but their order is not
+    otherwise guaranteed.
+
+    The argument \a prefix is the namespace prefix being declared and
+    the argument \a uri is the namespace URI the prefix is mapped to.
+
+    If this function returns false the reader stops parsing and
+    reports an error. The reader uses the function errorString() to
+    get the error message.
+
+    \sa endPrefixMapping(), {Namespace Support via Features}
+*/
+
+/*!
+    \fn bool QXmlContentHandler::endPrefixMapping(const QString& prefix)
+
+    The reader calls this function to signal the end of a prefix
+    mapping for the prefix \a prefix.
+
+    If this function returns false the reader stops parsing and
+    reports an error. The reader uses the function errorString() to
+    get the error message.
+
+    \sa startPrefixMapping(), {Namespace Support via Features}
+*/
+
+/*!
+    \fn bool QXmlContentHandler::startElement(const QString& namespaceURI, const QString& localName, const QString& qName, const QXmlAttributes& atts)
+
+    The reader calls this function when it has parsed a start element
+    tag.
+
+    There is a corresponding endElement() call when the corresponding
+    end element tag is read. The startElement() and endElement() calls
+    are always nested correctly. Empty element tags (e.g. \c{<x/>})
+    cause a startElement() call to be immediately followed by an
+    endElement() call.
+
+    The attribute list provided only contains attributes with explicit
+    values. The attribute list contains attributes used for namespace
+    declaration (i.e. attributes starting with xmlns) only if the
+    namespace-prefix property of the reader is true.
+
+    The argument \a namespaceURI is the namespace URI, or
+    an empty string if the element has no namespace URI or if no
+    namespace processing is done. \a localName is the local name
+    (without prefix), or an empty string if no namespace processing is
+    done, \a qName is the qualified name (with prefix) and \a atts are
+    the attributes attached to the element. If there are no
+    attributes, \a atts is an empty attributes object.
+
+    If this function returns false the reader stops parsing and
+    reports an error. The reader uses the function errorString() to
+    get the error message.
+
+    \sa endElement(), {Namespace Support via Features}
+*/
+
+/*!
+    \fn bool QXmlContentHandler::endElement(const QString& namespaceURI, const QString& localName, const QString& qName)
+
+    The reader calls this function when it has parsed an end element
+    tag with the qualified name \a qName, the local name \a localName
+    and the namespace URI \a namespaceURI.
+
+    If this function returns false the reader stops parsing and
+    reports an error. The reader uses the function errorString() to
+    get the error message.
+
+    \sa startElement(), {Namespace Support via Features}
+*/
+
+/*!
+    \fn bool QXmlContentHandler::characters(const QString& ch)
+
+    The reader calls this function when it has parsed a chunk of
+    character data (either normal character data or character data
+    inside a CDATA section; if you need to distinguish between those
+    two types you must use QXmlLexicalHandler::startCDATA() and
+    QXmlLexicalHandler::endCDATA()). The character data is reported in
+    \a ch.
+
+    Some readers report whitespace in element content using the
+    ignorableWhitespace() function rather than using this one.
+
+    A reader may report the character data of an element in more than
+    one chunk; e.g. a reader might want to report "a\<b" in three
+    characters() events ("a ", "\<" and " b").
+
+    If this function returns false the reader stops parsing and
+    reports an error. The reader uses the function errorString() to
+    get the error message.
+*/
+
+/*!
+    \fn bool QXmlContentHandler::ignorableWhitespace(const QString& ch)
+
+    Some readers may use this function to report each chunk of
+    whitespace in element content. The whitespace is reported in \a ch.
+
+    If this function returns false the reader stops parsing and
+    reports an error. The reader uses the function errorString() to
+    get the error message.
+*/
+
+/*!
+    \fn bool QXmlContentHandler::processingInstruction(const QString& target, const QString& data)
+
+    The reader calls this function when it has parsed a processing
+    instruction.
+
+    \a target is the target name of the processing instruction and \a
+    data is the data in the processing instruction.
+
+    If this function returns false the reader stops parsing and
+    reports an error. The reader uses the function errorString() to
+    get the error message.
+*/
+
+/*!
+    \fn bool QXmlContentHandler::skippedEntity(const QString& name)
+
+    Some readers may skip entities if they have not seen the
+    declarations (e.g. because they are in an external DTD). If they
+    do so they report that they skipped the entity called \a name by
+    calling this function.
+
+    If this function returns false the reader stops parsing and
+    reports an error. The reader uses the function errorString() to
+    get the error message.
+*/
+
+/*!
+    \fn QString QXmlContentHandler::errorString() const
+
+    The reader calls this function to get an error string, e.g. if any
+    of the handler functions returns false.
+*/
+
+
+/*!
+    \class QXmlErrorHandler
+    \reentrant
+    \brief The QXmlErrorHandler class provides an interface to report
+    errors in XML data.
+
+    \inmodule QtXml
+    \ingroup xml-tools
+
+    If you want your application to report errors to the user or to
+    perform customized error handling, you should subclass this class.
+
+    You can set the error handler with QXmlReader::setErrorHandler().
+
+    Errors can be reported using warning(), error() and fatalError(),
+    with the error text being reported with errorString().
+
+    \sa QXmlDTDHandler, QXmlDeclHandler, QXmlContentHandler, QXmlEntityResolver,
+        QXmlLexicalHandler, {Introduction to SAX2}
+*/
+
+/*!
+    \fn QXmlErrorHandler::~QXmlErrorHandler()
+
+    Destroys the error handler.
+*/
+
+/*!
+    \fn bool QXmlErrorHandler::warning(const QXmlParseException& exception)
+
+    A reader might use this function to report a warning. Warnings are
+    conditions that are not errors or fatal errors as defined by the
+    XML 1.0 specification. Details of the warning are stored in \a
+    exception.
+
+    If this function returns false the reader stops parsing and
+    reports an error. The reader uses the function errorString() to
+    get the error message.
+*/
+
+/*!
+    \fn bool QXmlErrorHandler::error(const QXmlParseException& exception)
+
+    A reader might use this function to report a recoverable error. A
+    recoverable error corresponds to the definiton of "error" in
+    section 1.2 of the XML 1.0 specification. Details of the error are
+    stored in \a exception.
+
+    The reader must continue to provide normal parsing events after
+    invoking this function.
+
+    If this function returns false the reader stops parsing and
+    reports an error. The reader uses the function errorString() to
+    get the error message.
+*/
+
+/*!
+\fn bool QXmlErrorHandler::fatalError(const QXmlParseException& exception)
+
+A reader must use this function to report a non-recoverable error.
+Details of the error are stored in \a exception.
+
+If this function returns true the reader might try to go on
+parsing and reporting further errors, but no regular parsing
+events are reported.
+*/
+
+/*!
+    \fn QString QXmlErrorHandler::errorString() const
+
+    The reader calls this function to get an error string if any of
+    the handler functions returns false.
+*/
+
+
+/*!
+    \class QXmlDTDHandler
+    \reentrant
+    \brief The QXmlDTDHandler class provides an interface to report
+    DTD content of XML data.
+
+    \inmodule QtXml
+    \ingroup xml-tools
+
+    If an application needs information about notations and unparsed
+    entities, it can implement this interface and register an instance
+    with QXmlReader::setDTDHandler().
+
+    Note that this interface includes only those DTD events that the
+    XML recommendation requires processors to report, i.e. notation
+    and unparsed entity declarations using notationDecl() and
+    unparsedEntityDecl() respectively.
+
+    \sa QXmlDeclHandler, QXmlContentHandler, QXmlEntityResolver, QXmlErrorHandler,
+        QXmlLexicalHandler, {Introduction to SAX2}
+*/
+
+/*!
+    \fn QXmlDTDHandler::~QXmlDTDHandler()
+
+    Destroys the DTD handler.
+*/
+
+/*!
+    \fn bool QXmlDTDHandler::notationDecl(const QString& name, const QString& publicId, const QString& systemId)
+
+    The reader calls this function when it has parsed a notation
+    declaration.
+
+    The argument \a name is the notation name, \a publicId is the
+    notation's public identifier and \a systemId is the notation's
+    system identifier.
+
+    If this function returns false the reader stops parsing and
+    reports an error. The reader uses the function errorString() to
+    get the error message.
+*/
+
+/*!
+    \fn bool QXmlDTDHandler::unparsedEntityDecl(const QString& name, const QString& publicId, const QString& systemId, const QString& notationName)
+
+    The reader calls this function when it finds an unparsed entity
+    declaration.
+
+    The argument \a name is the unparsed entity's name, \a publicId is
+    the entity's public identifier, \a systemId is the entity's system
+    identifier and \a notationName is the name of the associated
+    notation.
+
+    If this function returns false the reader stops parsing and
+    reports an error. The reader uses the function errorString() to
+    get the error message.
+*/
+
+/*!
+    \fn QString QXmlDTDHandler::errorString() const
+
+    The reader calls this function to get an error string if any of
+    the handler functions returns false.
+*/
+
+
+/*!
+    \class QXmlEntityResolver
+    \reentrant
+    \brief The QXmlEntityResolver class provides an interface to
+    resolve external entities contained in XML data.
+
+    \inmodule QtXml
+    \ingroup xml-tools
+
+    If an application needs to implement customized handling for
+    external entities, it must implement this interface, i.e.
+    resolveEntity(), and register it with
+    QXmlReader::setEntityResolver().
+
+    \sa QXmlDTDHandler, QXmlDeclHandler, QXmlContentHandler, QXmlErrorHandler,
+        QXmlLexicalHandler, {Introduction to SAX2}
+*/
+
+/*!
+    \fn QXmlEntityResolver::~QXmlEntityResolver()
+
+    Destroys the entity resolver.
+*/
+
+/*!
+    \fn bool QXmlEntityResolver::resolveEntity(const QString& publicId, const QString& systemId, QXmlInputSource*& ret)
+
+    The reader calls this function before it opens any external
+    entity, except the top-level document entity. The application may
+    request the reader to resolve the entity itself (\a ret is 0) or
+    to use an entirely different input source (\a ret points to the
+    input source).
+
+    The reader deletes the input source \a ret when it no longer needs
+    it, so you should allocate it on the heap with \c new.
+
+    The argument \a publicId is the public identifier of the external
+    entity, \a systemId is the system identifier of the external
+    entity and \a ret is the return value of this function. If \a ret
+    is 0 the reader should resolve the entity itself, if it is
+    non-zero it must point to an input source which the reader uses
+    instead.
+
+    If this function returns false the reader stops parsing and
+    reports an error. The reader uses the function errorString() to
+    get the error message.
+*/
+
+/*!
+    \fn QString QXmlEntityResolver::errorString() const
+
+    The reader calls this function to get an error string if any of
+    the handler functions returns false.
+*/
+
+
+/*!
+    \class QXmlLexicalHandler
+    \reentrant
+    \brief The QXmlLexicalHandler class provides an interface to
+    report the lexical content of XML data.
+
+    \inmodule QtXml
+    \ingroup xml-tools
+
+    The events in the lexical handler apply to the entire document,
+    not just to the document element, and all lexical handler events
+    appear between the content handler's startDocument and endDocument
+    events.
+
+    You can set the lexical handler with
+    QXmlReader::setLexicalHandler().
+
+    This interface's design is based on the SAX2 extension
+    LexicalHandler.
+
+    The interface provides the startDTD(), endDTD(), startEntity(),
+    endEntity(), startCDATA(), endCDATA() and comment() functions.
+
+    \sa QXmlDTDHandler, QXmlDeclHandler, QXmlContentHandler, QXmlEntityResolver,
+        QXmlErrorHandler, {Introduction to SAX2}
+*/
+
+/*!
+    \fn QXmlLexicalHandler::~QXmlLexicalHandler()
+
+    Destroys the lexical handler.
+*/
+
+/*!
+    \fn bool QXmlLexicalHandler::startDTD(const QString& name, const QString& publicId, const QString& systemId)
+
+    The reader calls this function to report the start of a DTD
+    declaration, if any. It reports the name of the document type in
+    \a name, the public identifier in \a publicId and the system
+    identifier in \a systemId.
+
+    If the public identifier is missing, \a publicId is set to
+    an empty string. If the system identifier is missing, \a systemId is
+    set to an empty string. Note that it is not valid XML to have a
+    public identifier but no system identifier; in such cases a parse
+    error will occur.
+
+    All declarations reported through QXmlDTDHandler or
+    QXmlDeclHandler appear between the startDTD() and endDTD() calls.
+
+    If this function returns false the reader stops parsing and
+    reports an error. The reader uses the function errorString() to
+    get the error message.
+
+    \sa endDTD()
+*/
+
+/*!
+    \fn bool QXmlLexicalHandler::endDTD()
+
+    The reader calls this function to report the end of a DTD
+    declaration, if any.
+
+    If this function returns false the reader stops parsing and
+    reports an error. The reader uses the function errorString() to
+    get the error message.
+
+    \sa startDTD()
+*/
+
+/*!
+    \fn bool QXmlLexicalHandler::startEntity(const QString& name)
+
+    The reader calls this function to report the start of an entity
+    called \a name.
+
+    Note that if the entity is unknown, the reader reports it through
+    QXmlContentHandler::skippedEntity() and not through this
+    function.
+
+    If this function returns false the reader stops parsing and
+    reports an error. The reader uses the function errorString() to
+    get the error message.
+
+    \sa endEntity(), QXmlSimpleReader::setFeature()
+*/
+
+/*!
+    \fn bool QXmlLexicalHandler::endEntity(const QString& name)
+
+    The reader calls this function to report the end of an entity
+    called \a name.
+
+    For every startEntity() call, there is a corresponding endEntity()
+    call. The calls to startEntity() and endEntity() are properly
+    nested.
+
+    If this function returns false the reader stops parsing and
+    reports an error. The reader uses the function errorString() to
+    get the error message.
+
+    \sa startEntity(), QXmlContentHandler::skippedEntity(), QXmlSimpleReader::setFeature()
+*/
+
+/*!
+    \fn bool QXmlLexicalHandler::startCDATA()
+
+    The reader calls this function to report the start of a CDATA
+    section. The content of the CDATA section is reported through the
+    QXmlContentHandler::characters() function. This function is
+    intended only to report the boundary.
+
+    If this function returns false the reader stops parsing and
+    reports an error. The reader uses the function errorString() to
+    get the error message.
+
+    \sa endCDATA()
+*/
+
+/*!
+    \fn bool QXmlLexicalHandler::endCDATA()
+
+    The reader calls this function to report the end of a CDATA
+    section.
+
+    If this function returns false the reader stops parsing and reports
+    an error. The reader uses the function errorString() to get the error
+    message.
+
+    \sa startCDATA(), QXmlContentHandler::characters()
+*/
+
+/*!
+    \fn bool QXmlLexicalHandler::comment(const QString& ch)
+
+    The reader calls this function to report an XML comment anywhere
+    in the document. It reports the text of the comment in \a ch.
+
+    If this function returns false the reader stops parsing and
+    reports an error. The reader uses the function errorString() to
+    get the error message.
+*/
+
+/*!
+    \fn QString QXmlLexicalHandler::errorString() const
+
+    The reader calls this function to get an error string if any of
+    the handler functions returns false.
+*/
+
+
+/*!
+    \class QXmlDeclHandler
+    \reentrant
+    \brief The QXmlDeclHandler class provides an interface to report declaration
+    content of XML data.
+
+    \inmodule QtXml
+    \ingroup xml-tools
+
+    You can set the declaration handler with
+    QXmlReader::setDeclHandler().
+
+    This interface is based on the SAX2 extension DeclHandler.
+
+    The interface provides attributeDecl(), internalEntityDecl() and
+    externalEntityDecl() functions.
+
+    \sa QXmlDTDHandler, QXmlContentHandler, QXmlEntityResolver, QXmlErrorHandler,
+        QXmlLexicalHandler, {Introduction to SAX2}
+*/
+
+/*!
+    \fn QXmlDeclHandler::~QXmlDeclHandler()
+
+    Destroys the declaration handler.
+*/
+
+/*!
+    \fn bool QXmlDeclHandler::attributeDecl(const QString& eName, const QString& aName, const QString& type, const QString& valueDefault, const QString& value)
+
+    The reader calls this function to report an attribute type
+    declaration. Only the effective (first) declaration for an
+    attribute is reported.
+
+    The reader passes the name of the associated element in \a eName
+    and the name of the attribute in \a aName. It passes a string that
+    represents the attribute type in \a type and a string that
+    represents the attribute default in \a valueDefault. This string
+    is one of "#IMPLIED", "#REQUIRED", "#FIXED" or an empty string (if
+    none of the others applies). The reader passes the attribute's
+    default value in \a value. If no default value is specified in the
+    XML file, \a value is an empty string.
+
+    If this function returns false the reader stops parsing and
+    reports an error. The reader uses the function errorString() to
+    get the error message.
+*/
+
+/*!
+    \fn bool QXmlDeclHandler::internalEntityDecl(const QString& name, const QString& value)
+
+    The reader calls this function to report an internal entity
+    declaration. Only the effective (first) declaration is reported.
+
+    The reader passes the name of the entity in \a name and the value
+    of the entity in \a value.
+
+    If this function returns false the reader stops parsing and
+    reports an error. The reader uses the function errorString() to
+    get the error message.
+*/
+
+/*!
+    \fn bool QXmlDeclHandler::externalEntityDecl(const QString& name, const QString& publicId, const QString& systemId)
+
+    The reader calls this function to report a parsed external entity
+    declaration. Only the effective (first) declaration for each
+    entity is reported.
+
+    The reader passes the name of the entity in \a name, the public
+    identifier in \a publicId and the system identifier in \a
+    systemId. If there is no public identifier specified, it passes
+    an empty string in \a publicId.
+
+    If this function returns false the reader stops parsing and
+    reports an error. The reader uses the function errorString() to
+    get the error message.
+*/
+
+/*!
+    \fn QString QXmlDeclHandler::errorString() const
+
+    The reader calls this function to get an error string if any of
+    the handler functions returns false.
+*/
+
+
+/*!
+    \class QXmlDefaultHandler
+    \reentrant
+    \brief The QXmlDefaultHandler class provides a default implementation of all
+    the XML handler classes.
+
+    \inmodule QtXml
+    \ingroup xml-tools
+
+    This class gathers together the features of
+    the specialized handler classes, making it a convenient
+    starting point when implementing custom handlers for
+    subclasses of QXmlReader, particularly QXmlSimpleReader.
+    The virtual functions from each of the base classes are
+    reimplemented in this class, providing sensible default behavior
+    for many common cases. By subclassing this class, and
+    overriding these functions, you can concentrate
+    on implementing the parts of the handler relevant to your
+    application.
+
+    The XML reader must be told which handler to use for different
+    kinds of events during parsing. This means that, although
+    QXmlDefaultHandler provides default implementations of functions
+    inherited from all its base classes, we can still use specialized
+    handlers for particular kinds of events.
+
+    For example, QXmlDefaultHandler subclasses both
+    QXmlContentHandler and QXmlErrorHandler, so by subclassing
+    it we can use the same handler for both of the following
+    reader functions:
+
+    \snippet doc/src/snippets/xml/rsslisting/rsslisting.cpp 0
+
+    Since the reader will inform the handler of parsing errors, it is
+    necessary to reimplement QXmlErrorHandler::fatalError() if, for
+    example, we want to stop parsing when such an error occurs:
+
+    \snippet doc/src/snippets/xml/rsslisting/handler.cpp 0
+
+    The above function returns false, which tells the reader to stop
+    parsing. To continue to use the same reader,
+    it is necessary to create a new handler instance, and set up the
+    reader to use it in the manner described above.
+
+    It is useful to examine some of the functions inherited by
+    QXmlDefaultHandler, and consider why they might be
+    reimplemented in a custom handler.
+    Custom handlers will typically reimplement
+    QXmlContentHandler::startDocument() to prepare the handler for
+    new content. Document elements and the text within them can be
+    processed by reimplementing QXmlContentHandler::startElement(),
+    QXmlContentHandler::endElement(), and
+    QXmlContentHandler::characters().
+    You may want to reimplement QXmlContentHandler::endDocument()
+    to perform some finalization or validation on the content once the
+    document has been read completely.
+
+    \sa QXmlDTDHandler, QXmlDeclHandler, QXmlContentHandler, QXmlEntityResolver,
+        QXmlErrorHandler, QXmlLexicalHandler, {Introduction to SAX2}
+*/
+
+/*!
+    \fn QXmlDefaultHandler::QXmlDefaultHandler()
+
+    Constructs a handler for use with subclasses of QXmlReader.
+*/
+/*!
+    \fn QXmlDefaultHandler::~QXmlDefaultHandler()
+
+    Destroys the handler.
+*/
+
+/*!
+    \reimp
+
+    This reimplementation does nothing.
+*/
+void QXmlDefaultHandler::setDocumentLocator(QXmlLocator*)
+{
+}
+
+/*!
+    \reimp
+
+    This reimplementation does nothing.
+*/
+bool QXmlDefaultHandler::startDocument()
+{
+    return true;
+}
+
+/*!
+    \reimp
+
+    This reimplementation does nothing.
+*/
+bool QXmlDefaultHandler::endDocument()
+{
+    return true;
+}
+
+/*!
+    \reimp
+
+    This reimplementation does nothing.
+*/
+bool QXmlDefaultHandler::startPrefixMapping(const QString&, const QString&)
+{
+    return true;
+}
+
+/*!
+    \reimp
+
+    This reimplementation does nothing.
+*/
+bool QXmlDefaultHandler::endPrefixMapping(const QString&)
+{
+    return true;
+}
+
+/*!
+    \reimp
+
+    This reimplementation does nothing.
+*/
+bool QXmlDefaultHandler::startElement(const QString&, const QString&,
+        const QString&, const QXmlAttributes&)
+{
+    return true;
+}
+
+/*!
+    \reimp
+
+    This reimplementation does nothing.
+*/
+bool QXmlDefaultHandler::endElement(const QString&, const QString&,
+        const QString&)
+{
+    return true;
+}
+
+/*!
+    \reimp
+
+    This reimplementation does nothing.
+*/
+bool QXmlDefaultHandler::characters(const QString&)
+{
+    return true;
+}
+
+/*!
+    \reimp
+
+    This reimplementation does nothing.
+*/
+bool QXmlDefaultHandler::ignorableWhitespace(const QString&)
+{
+    return true;
+}
+
+/*!
+    \reimp
+
+    This reimplementation does nothing.
+*/
+bool QXmlDefaultHandler::processingInstruction(const QString&,
+        const QString&)
+{
+    return true;
+}
+
+/*!
+    \reimp
+
+    This reimplementation does nothing.
+*/
+bool QXmlDefaultHandler::skippedEntity(const QString&)
+{
+    return true;
+}
+
+/*!
+    \reimp
+
+    This reimplementation does nothing.
+*/
+bool QXmlDefaultHandler::warning(const QXmlParseException&)
+{
+    return true;
+}
+
+/*!
+    \reimp
+
+    This reimplementation does nothing.
+*/
+bool QXmlDefaultHandler::error(const QXmlParseException&)
+{
+    return true;
+}
+
+/*!
+    \reimp
+
+    This reimplementation does nothing.
+*/
+bool QXmlDefaultHandler::fatalError(const QXmlParseException&)
+{
+    return true;
+}
+
+/*!
+    \reimp
+
+    This reimplementation does nothing.
+*/
+bool QXmlDefaultHandler::notationDecl(const QString&, const QString&,
+        const QString&)
+{
+    return true;
+}
+
+/*!
+    \reimp
+
+    This reimplementation does nothing.
+*/
+bool QXmlDefaultHandler::unparsedEntityDecl(const QString&, const QString&,
+        const QString&, const QString&)
+{
+    return true;
+}
+
+/*!
+    \reimp
+
+    Sets \a ret to 0, so that the reader uses the system identifier
+    provided in the XML document.
+*/
+bool QXmlDefaultHandler::resolveEntity(const QString&, const QString&,
+        QXmlInputSource*& ret)
+{
+    ret = 0;
+    return true;
+}
+
+/*!
+    \reimp
+
+    Returns the default error string.
+*/
+QString QXmlDefaultHandler::errorString() const
+{
+    return QString::fromLatin1(XMLERR_ERRORBYCONSUMER);
+}
+
+/*!
+    \reimp
+
+    This reimplementation does nothing.
+*/
+bool QXmlDefaultHandler::startDTD(const QString&, const QString&, const QString&)
+{
+    return true;
+}
+
+/*!
+    \reimp
+
+    This reimplementation does nothing.
+*/
+bool QXmlDefaultHandler::endDTD()
+{
+    return true;
+}
+
+/*!
+    \reimp
+
+    This reimplementation does nothing.
+*/
+bool QXmlDefaultHandler::startEntity(const QString&)
+{
+    return true;
+}
+
+/*!
+    \reimp
+
+    This reimplementation does nothing.
+*/
+bool QXmlDefaultHandler::endEntity(const QString&)
+{
+    return true;
+}
+
+/*!
+    \reimp
+
+    This reimplementation does nothing.
+*/
+bool QXmlDefaultHandler::startCDATA()
+{
+    return true;
+}
+
+/*!
+    \reimp
+
+    This reimplementation does nothing.
+*/
+bool QXmlDefaultHandler::endCDATA()
+{
+    return true;
+}
+
+/*!
+    \reimp
+
+    This reimplementation does nothing.
+*/
+bool QXmlDefaultHandler::comment(const QString&)
+{
+    return true;
+}
+
+/*!
+    \reimp
+
+    This reimplementation does nothing.
+*/
+bool QXmlDefaultHandler::attributeDecl(const QString&, const QString&, const QString&, const QString&, const QString&)
+{
+    return true;
+}
+
+/*!
+    \reimp
+
+    This reimplementation does nothing.
+*/
+bool QXmlDefaultHandler::internalEntityDecl(const QString&, const QString&)
+{
+    return true;
+}
+
+/*!
+    \reimp
+
+    This reimplementation does nothing.
+*/
+bool QXmlDefaultHandler::externalEntityDecl(const QString&, const QString&, const QString&)
+{
+    return true;
+}
+
+
+/*********************************************
+ *
+ * QXmlSimpleReaderPrivate
+ *
+ *********************************************/
+
+inline bool QXmlSimpleReaderPrivate::atEnd()
+{
+    return (c.unicode()|0x0001) == 0xffff;
+}
+
+inline void QXmlSimpleReaderPrivate::stringClear()
+{
+    stringValueLen = 0; stringArrayPos = 0;
+}
+inline void QXmlSimpleReaderPrivate::nameClear()
+{
+    nameValueLen = 0; nameArrayPos = 0;
+}
+
+inline void QXmlSimpleReaderPrivate::refClear()
+{
+    refValueLen = 0; refArrayPos = 0;
+}
+
+QXmlSimpleReaderPrivate::QXmlSimpleReaderPrivate(QXmlSimpleReader *reader)
+{
+    q_ptr = reader;
+    parseStack = 0;
+
+    locator.reset(new QXmlSimpleReaderLocator(reader));
+    entityRes  = 0;
+    dtdHnd     = 0;
+    contentHnd = 0;
+    errorHnd   = 0;
+    lexicalHnd = 0;
+    declHnd    = 0;
+
+    // default feature settings
+    useNamespaces = true;
+    useNamespacePrefixes = false;
+    reportWhitespaceCharData = true;
+    reportEntities = false;
+}
+
+QXmlSimpleReaderPrivate::~QXmlSimpleReaderPrivate()
+{
+    delete parseStack;
+}
+
+void QXmlSimpleReaderPrivate::initIncrementalParsing()
+{
+    if(parseStack)
+        parseStack->clear();
+    else
+        parseStack = new QStack<ParseState>;
+}
+
+/*********************************************
+ *
+ * QXmlSimpleReader
+ *
+ *********************************************/
+
+/*!
+    \class QXmlReader
+    \reentrant
+    \brief The QXmlReader class provides an interface for XML readers (i.e.
+    parsers).
+
+    \inmodule QtXml
+    \ingroup xml-tools
+
+    This abstract class provides an interface for all of Qt's XML
+    readers. Currently there is only one implementation of a reader
+    included in Qt's XML module: QXmlSimpleReader. In future releases
+    there might be more readers with different properties available
+    (e.g. a validating parser).
+
+    The design of the XML classes follows the \link
+    http://www.saxproject.org/ SAX2 Java interface\endlink, with
+    the names adapted to fit Qt naming conventions. It should be very
+    easy for anybody who has worked with SAX2 to get started with the
+    Qt XML classes.
+
+    All readers use the class QXmlInputSource to read the input
+    document. Since you are normally interested in particular content
+    in the XML document, the reader reports the content through
+    special handler classes (QXmlDTDHandler, QXmlDeclHandler,
+    QXmlContentHandler, QXmlEntityResolver, QXmlErrorHandler and
+    QXmlLexicalHandler), which you must subclass, if you want to
+    process the contents.
+
+    Since the handler classes only describe interfaces you must
+    implement all the functions. We provide the QXmlDefaultHandler
+    class to make this easier: it implements a default behavior (do
+    nothing) for all functions, so you can subclass it and just
+    implement the functions you are interested in.
+
+    Features and properties of the reader can be set with setFeature()
+    and setProperty() respectively. You can set the reader to use your
+    own subclasses with setEntityResolver(), setDTDHandler(),
+    setContentHandler(), setErrorHandler(), setLexicalHandler() and
+    setDeclHandler(). The parse itself is started with a call to
+    parse().
+
+    \sa QXmlSimpleReader
+*/
+
+/*!
+    \fn QXmlReader::~QXmlReader()
+
+    Destroys the reader.
+*/
+
+/*!
+    \fn bool QXmlReader::feature(const QString& name, bool *ok) const
+
+    If the reader has the feature called \a name, the feature's value
+    is returned. If no such feature exists the return value is
+    undefined.
+
+    If \a ok is not 0: \c{*}\a{ok}  is set to true if the reader has the
+    feature called \a name; otherwise \c{*}\a{ok} is set to false.
+
+    \sa setFeature(), hasFeature()
+*/
+
+/*!
+    \fn void QXmlReader::setFeature(const QString& name, bool value)
+
+    Sets the feature called \a name to the given \a value. If the
+    reader doesn't have the feature nothing happens.
+
+    \sa feature(), hasFeature()
+*/
+
+/*!
+    \fn bool QXmlReader::hasFeature(const QString& name) const
+
+    Returns \c true if the reader has the feature called \a name;
+    otherwise returns false.
+
+    \sa feature(), setFeature()
+*/
+
+/*!
+    \fn void* QXmlReader::property(const QString& name, bool *ok) const
+
+    If the reader has the property \a name, this function returns the
+    value of the property; otherwise the return value is undefined.
+
+    If \a ok is not 0: if the reader has the \a name property
+    \c{*}\a{ok} is set to true; otherwise \c{*}\a{ok} is set to false.
+
+    \sa setProperty(), hasProperty()
+*/
+
+/*!
+    \fn void QXmlReader::setProperty(const QString& name, void* value)
+
+    Sets the property \a name to \a value. If the reader doesn't have
+    the property nothing happens.
+
+    \sa property(), hasProperty()
+*/
+
+/*!
+    \fn bool QXmlReader::hasProperty(const QString& name) const
+
+    Returns true if the reader has the property \a name; otherwise
+    returns false.
+
+    \sa property(), setProperty()
+*/
+
+/*!
+    \fn void QXmlReader::setEntityResolver(QXmlEntityResolver* handler)
+
+    Sets the entity resolver to \a handler.
+
+    \sa entityResolver()
+*/
+
+/*!
+    \fn QXmlEntityResolver* QXmlReader::entityResolver() const
+
+    Returns the entity resolver or 0 if none was set.
+
+    \sa setEntityResolver()
+*/
+
+/*!
+    \fn void QXmlReader::setDTDHandler(QXmlDTDHandler* handler)
+
+    Sets the DTD handler to \a handler.
+
+    \sa DTDHandler()
+*/
+
+/*!
+    \fn QXmlDTDHandler* QXmlReader::DTDHandler() const
+
+    Returns the DTD handler or 0 if none was set.
+
+    \sa setDTDHandler()
+*/
+
+/*!
+    \fn void QXmlReader::setContentHandler(QXmlContentHandler* handler)
+
+    Sets the content handler to \a handler.
+
+    \sa contentHandler()
+*/
+
+/*!
+    \fn QXmlContentHandler* QXmlReader::contentHandler() const
+
+    Returns the content handler or 0 if none was set.
+
+    \sa setContentHandler()
+*/
+
+/*!
+    \fn void QXmlReader::setErrorHandler(QXmlErrorHandler* handler)
+
+    Sets the error handler to \a handler. Clears the error handler if
+    \a handler is 0.
+
+    \sa errorHandler()
+*/
+
+/*!
+    \fn QXmlErrorHandler* QXmlReader::errorHandler() const
+
+    Returns the error handler or 0 if none is set.
+
+    \sa setErrorHandler()
+*/
+
+/*!
+    \fn void QXmlReader::setLexicalHandler(QXmlLexicalHandler* handler)
+
+    Sets the lexical handler to \a handler.
+
+    \sa lexicalHandler()
+*/
+
+/*!
+    \fn QXmlLexicalHandler* QXmlReader::lexicalHandler() const
+
+    Returns the lexical handler or 0 if none was set.
+
+    \sa setLexicalHandler()
+*/
+
+/*!
+    \fn void QXmlReader::setDeclHandler(QXmlDeclHandler* handler)
+
+    Sets the declaration handler to \a handler.
+
+    \sa declHandler()
+*/
+
+/*!
+    \fn QXmlDeclHandler* QXmlReader::declHandler() const
+
+    Returns the declaration handler or 0 if none was set.
+
+    \sa setDeclHandler()
+*/
+
+/*!
+  \fn bool QXmlReader::parse(const QXmlInputSource &input)
+
+  \obsolete
+
+  Parses the given \a input.
+*/
+
+/*!
+    \fn bool QXmlReader::parse(const QXmlInputSource *input)
+
+    Reads an XML document from \a input and parses it. Returns true if
+    the parsing was successful; otherwise returns false.
+*/
+
+
+/*!
+    \class QXmlSimpleReader
+    \nonreentrant
+    \brief The QXmlSimpleReader class provides an implementation of a
+    simple XML parser.
+
+    \inmodule QtXml
+    \ingroup xml-tools
+
+
+    This XML reader is suitable for a wide range of applications. It
+    is able to parse well-formed XML and can report the namespaces of
+    elements to a content handler; however, it does not parse any
+    external entities. For historical reasons, Attribute Value
+    Normalization and End-of-Line Handling as described in the XML 1.0
+    specification is not performed.
+
+    The easiest pattern of use for this class is to create a reader
+    instance, define an input source, specify the handlers to be used
+    by the reader, and parse the data.
+
+    For example, we could use a QFile to supply the input. Here, we
+    create a reader, and define an input source to be used by the
+    reader:
+
+    \snippet doc/src/snippets/xml/simpleparse/main.cpp 0
+
+    A handler lets us perform actions when the reader encounters
+    certain types of content, or if errors in the input are found. The
+    reader must be told which handler to use for each type of
+    event. For many common applications, we can create a custom
+    handler by subclassing QXmlDefaultHandler, and use this to handle
+    both error and content events:
+
+    \snippet doc/src/snippets/xml/simpleparse/main.cpp 1
+
+    If you don't set at least the content and error handlers, the
+    parser will fall back on its default behavior---and will do
+    nothing.
+
+    The most convenient way to handle the input is to read it in a
+    single pass using the parse() function with an argument that
+    specifies the input source:
+
+    \snippet doc/src/snippets/xml/simpleparse/main.cpp 2
+
+    If you can't parse the entire input in one go (for example, it is
+    huge, or is being delivered over a network connection), data can
+    be fed to the parser in pieces. This is achieved by telling
+    parse() to work incrementally, and making subsequent calls to the
+    parseContinue() function, until all the data has been processed.
+
+    A common way to perform incremental parsing is to connect the \c
+    readyRead() signal of a \l{QNetworkReply} {network reply} a slot,
+    and handle the incoming data there. See QNetworkAccessManager.
+    
+    Aspects of the parsing behavior can be adapted using setFeature()
+    and setProperty().
+    
+    QXmlSimpleReader is not reentrant. If you want to use the class
+    in threaded code, lock the code using QXmlSimpleReader with a
+    locking mechanism, such as a QMutex.
+
+    \snippet doc/src/snippets/code/src_xml_sax_qxml.cpp 0
+*/
+
+static inline bool is_S(QChar ch)
+{
+    ushort uc = ch.unicode();
+    return (uc == ' ' || uc == '\t' || uc == '\n' || uc == '\r');
+}
+
+enum NameChar { NameBeginning, NameNotBeginning, NotName };
+
+static const char Begi = (char)NameBeginning;
+static const char NtBg = (char)NameNotBeginning;
+static const char NotN = (char)NotName;
+
+static const char nameCharTable[128] =
+{
+// 0x00
+    NotN, NotN, NotN, NotN, NotN, NotN, NotN, NotN,
+    NotN, NotN, NotN, NotN, NotN, NotN, NotN, NotN,
+// 0x10
+    NotN, NotN, NotN, NotN, NotN, NotN, NotN, NotN,
+    NotN, NotN, NotN, NotN, NotN, NotN, NotN, NotN,
+// 0x20 (0x2D is '-', 0x2E is '.')
+    NotN, NotN, NotN, NotN, NotN, NotN, NotN, NotN,
+    NotN, NotN, NotN, NotN, NotN, NtBg, NtBg, NotN,
+// 0x30 (0x30..0x39 are '0'..'9', 0x3A is ':')
+    NtBg, NtBg, NtBg, NtBg, NtBg, NtBg, NtBg, NtBg,
+    NtBg, NtBg, Begi, NotN, NotN, NotN, NotN, NotN,
+// 0x40 (0x41..0x5A are 'A'..'Z')
+    NotN, Begi, Begi, Begi, Begi, Begi, Begi, Begi,
+    Begi, Begi, Begi, Begi, Begi, Begi, Begi, Begi,
+// 0x50 (0x5F is '_')
+    Begi, Begi, Begi, Begi, Begi, Begi, Begi, Begi,
+    Begi, Begi, Begi, NotN, NotN, NotN, NotN, Begi,
+// 0x60 (0x61..0x7A are 'a'..'z')
+    NotN, Begi, Begi, Begi, Begi, Begi, Begi, Begi,
+    Begi, Begi, Begi, Begi, Begi, Begi, Begi, Begi,
+// 0x70
+    Begi, Begi, Begi, Begi, Begi, Begi, Begi, Begi,
+    Begi, Begi, Begi, NotN, NotN, NotN, NotN, NotN
+};
+
+static inline NameChar fastDetermineNameChar(QChar ch)
+{
+    ushort uc = ch.unicode();
+    if (!(uc & ~0x7f)) // uc < 128
+        return (NameChar)nameCharTable[uc];
+
+    QChar::Category cat = ch.category();
+    // ### some these categories might be slightly wrong
+    if ((cat >= QChar::Letter_Uppercase && cat <= QChar::Letter_Other)
+        || cat == QChar::Number_Letter)
+        return NameBeginning;
+    if ((cat >= QChar::Number_DecimalDigit && cat <= QChar::Number_Other)
+                || (cat >= QChar::Mark_NonSpacing && cat <= QChar::Mark_Enclosing))
+        return NameNotBeginning;
+    return NotName;
+}
+
+static NameChar determineNameChar(QChar ch)
+{
+    return fastDetermineNameChar(ch);
+}
+
+/*!
+    Constructs a simple XML reader.
+
+*/
+QXmlSimpleReader::QXmlSimpleReader()
+    : d_ptr(new QXmlSimpleReaderPrivate(this))
+{
+}
+
+/*!
+    Destroys the simple XML reader.
+*/
+QXmlSimpleReader::~QXmlSimpleReader()
+{
+}
+
+/*!
+    \reimp
+*/
+bool QXmlSimpleReader::feature(const QString& name, bool *ok) const
+{
+    const QXmlSimpleReaderPrivate *d = d_func();
+
+    // Qt5 ###: Change these strings to qt.nokia.com
+    if (ok != 0)
+        *ok = true;
+    if (name == QLatin1String("http://xml.org/sax/features/namespaces")) {
+        return d->useNamespaces;
+    } else if (name == QLatin1String("http://xml.org/sax/features/namespace-prefixes")) {
+        return d->useNamespacePrefixes;
+    } else if (name == QLatin1String("http://trolltech.com/xml/features/report-whitespace-only-CharData")) { // Shouldn't change in Qt 4
+        return d->reportWhitespaceCharData;
+    } else if (name == QLatin1String("http://trolltech.com/xml/features/report-start-end-entity")) { // Shouldn't change in Qt 4
+        return d->reportEntities;
+    } else {
+        qWarning("Unknown feature %s", name.toLatin1().data());
+        if (ok != 0)
+            *ok = false;
+    }
+    return false;
+}
+
+/*!
+    Turns on the feature \a name if \a enable is true; otherwise turns it off.
+
+    The \a name parameter must be one of the following strings:
+    \table
+    \header \i Feature \i Default \i Notes
+    \row \i \e http://xml.org/sax/features/namespaces
+         \i true
+         \i If enabled, namespaces are reported to the content handler.
+    \row \i \e http://xml.org/sax/features/namespace-prefixes
+         \i false
+         \i If enabled, the original prefixed names
+            and attributes used for namespace declarations are
+            reported.
+    \row \i \e http://trolltech.com/xml/features/report-whitespace-only-CharData
+         \i true
+         \i If enabled, CharData that consist of
+            only whitespace characters are reported
+            using QXmlContentHandler::characters(). If disabled, whitespace is silently
+            discarded.
+    \row \i \e http://trolltech.com/xml/features/report-start-end-entity
+         \i false
+         \i If enabled, the parser reports
+            QXmlContentHandler::startEntity() and
+            QXmlContentHandler::endEntity() events, so character data
+            might be reported in chunks.
+            If disabled, the parser does not report these events, but
+            silently substitutes the entities, and reports the character
+            data in one chunk.
+    \endtable
+
+    \sa feature(), hasFeature(), {SAX2 Features}
+*/
+void QXmlSimpleReader::setFeature(const QString& name, bool enable)
+{
+    Q_D(QXmlSimpleReader);
+    // Qt5 ###: Change these strings to qt.nokia.com
+    if (name == QLatin1String("http://xml.org/sax/features/namespaces")) {
+        d->useNamespaces = enable;
+    } else if (name == QLatin1String("http://xml.org/sax/features/namespace-prefixes")) {
+        d->useNamespacePrefixes = enable;
+    } else if (name == QLatin1String("http://trolltech.com/xml/features/report-whitespace-only-CharData")) { // Shouldn't change in Qt 4
+        d->reportWhitespaceCharData = enable;
+    } else if (name == QLatin1String("http://trolltech.com/xml/features/report-start-end-entity")) { // Shouldn't change in Qt 4
+        d->reportEntities = enable;
+    } else {
+        qWarning("Unknown feature %s", name.toLatin1().data());
+    }
+}
+
+/*! \reimp
+*/
+bool QXmlSimpleReader::hasFeature(const QString& name) const
+{
+    // Qt5 ###: Change these strings to qt.nokia.com
+    if (name == QLatin1String("http://xml.org/sax/features/namespaces")
+        || name == QLatin1String("http://xml.org/sax/features/namespace-prefixes")
+        || name == QLatin1String("http://trolltech.com/xml/features/report-whitespace-only-CharData") // Shouldn't change in Qt 4
+        || name == QLatin1String("http://trolltech.com/xml/features/report-start-end-entity")) { // Shouldn't change in Qt 4
+        return true;
+    } else {
+        return false;
+    }
+}
+
+/*! \reimp
+*/
+void* QXmlSimpleReader::property(const QString&, bool *ok) const
+{
+    if (ok != 0)
+        *ok = false;
+    return 0;
+}
+
+/*! \reimp
+*/
+void QXmlSimpleReader::setProperty(const QString&, void*)
+{
+}
+
+/*!
+    \reimp
+*/
+bool QXmlSimpleReader::hasProperty(const QString&) const
+{
+    return false;
+}
+
+/*!
+    \reimp
+*/
+void QXmlSimpleReader::setEntityResolver(QXmlEntityResolver* handler)
+{
+    Q_D(QXmlSimpleReader);
+    d->entityRes = handler;
+}
+
+/*!
+    \reimp
+*/
+QXmlEntityResolver* QXmlSimpleReader::entityResolver() const
+{
+    const QXmlSimpleReaderPrivate *d = d_func();
+    return d->entityRes;
+}
+
+/*!
+    \reimp
+*/
+void QXmlSimpleReader::setDTDHandler(QXmlDTDHandler* handler)
+{
+    Q_D(QXmlSimpleReader);
+    d->dtdHnd = handler;
+}
+
+/*!
+    \reimp
+*/
+QXmlDTDHandler* QXmlSimpleReader::DTDHandler() const
+{
+    const QXmlSimpleReaderPrivate *d = d_func();
+    return d->dtdHnd;
+}
+
+/*!
+    \reimp
+*/
+void QXmlSimpleReader::setContentHandler(QXmlContentHandler* handler)
+{
+    Q_D(QXmlSimpleReader);
+    d->contentHnd = handler;
+}
+
+/*!
+    \reimp
+*/
+QXmlContentHandler* QXmlSimpleReader::contentHandler() const
+{
+    const QXmlSimpleReaderPrivate *d = d_func();
+    return d->contentHnd;
+}
+
+/*!
+    \reimp
+*/
+void QXmlSimpleReader::setErrorHandler(QXmlErrorHandler* handler)
+{
+    Q_D(QXmlSimpleReader);
+    d->errorHnd = handler;
+}
+
+/*!
+    \reimp
+*/
+QXmlErrorHandler* QXmlSimpleReader::errorHandler() const
+{
+    const QXmlSimpleReaderPrivate *d = d_func();
+    return d->errorHnd;
+}
+
+/*!
+    \reimp
+*/
+void QXmlSimpleReader::setLexicalHandler(QXmlLexicalHandler* handler)
+{
+    Q_D(QXmlSimpleReader);
+    d->lexicalHnd = handler;
+}
+
+/*!
+    \reimp
+*/
+QXmlLexicalHandler* QXmlSimpleReader::lexicalHandler() const
+{
+    const QXmlSimpleReaderPrivate *d = d_func();
+    return d->lexicalHnd;
+}
+
+/*!
+    \reimp
+*/
+void QXmlSimpleReader::setDeclHandler(QXmlDeclHandler* handler)
+{
+    Q_D(QXmlSimpleReader);
+    d->declHnd = handler;
+}
+
+/*!
+    \reimp
+*/
+QXmlDeclHandler* QXmlSimpleReader::declHandler() const
+{
+    const QXmlSimpleReaderPrivate *d = d_func();
+    return d->declHnd;
+}
+
+
+
+/*!
+    \reimp
+*/
+bool QXmlSimpleReader::parse(const QXmlInputSource& input)
+{
+    return parse(&input, false);
+}
+
+/*!
+    Reads an XML document from \a input and parses it in one pass (non-incrementally).
+    Returns true if the parsing was successful; otherwise returns false.
+*/
+bool QXmlSimpleReader::parse(const QXmlInputSource* input)
+{
+    return parse(input, false);
+}
+
+/*!
+    Reads an XML document from \a input and parses it. Returns true
+    if the parsing is completed successfully; otherwise returns false,
+    indicating that an error occurred.
+
+    If \a incremental is false, this function will return false if the XML
+    file is not read completely. The parsing cannot be continued in this
+    case.
+
+    If \a incremental is true, the parser does not return false if
+    it reaches the end of the \a input before reaching the end
+    of the XML file. Instead, it stores the state of the parser so that
+    parsing can be continued later when more data is available.
+    In such a case, you can use the function parseContinue() to
+    continue with parsing. This class stores a pointer to the input
+    source \a input and the parseContinue() function tries to read from
+    that input source. Therefore, you should not delete the input
+    source \a input until you no longer need to call parseContinue().
+
+    If this function is called with \a incremental set to true
+    while an incremental parse is in progress, a new parsing
+    session will be started, and the previous session will be lost.
+
+    \sa parseContinue(), QTcpSocket
+*/
+bool QXmlSimpleReader::parse(const QXmlInputSource *input, bool incremental)
+{
+    Q_D(QXmlSimpleReader);
+
+    if (incremental) {
+        d->initIncrementalParsing();
+    } else {
+        delete d->parseStack;
+        d->parseStack = 0;
+    }
+    d->init(input);
+
+    // call the handler
+    if (d->contentHnd) {
+        d->contentHnd->setDocumentLocator(d->locator.data());
+        if (!d->contentHnd->startDocument()) {
+            d->reportParseError(d->contentHnd->errorString());
+            d->tags.clear();
+            return false;
+        }
+    }
+    qt_xml_skipped_entity_in_content = false;
+    return d->parseBeginOrContinue(0, incremental);
+}
+
+/*!
+    Continues incremental parsing, taking input from the
+    QXmlInputSource that was specified with the most recent
+    call to parse(). To use this function, you \e must have called
+    parse() with the incremental argument set to true.
+
+    Returns false if a parsing error occurs; otherwise returns true,
+    even if the end of the XML file has not been reached. You can
+    continue parsing at a later stage by calling this function again
+    when there is more data available to parse.
+
+    Calling this function when there is no data available in the input
+    source indicates to the reader that the end of the XML file has
+    been reached. If the input supplied up to this point was
+    not well-formed then a parsing error occurs, and false is returned.
+    If the input supplied was well-formed, true is returned.
+    It is important to end the input in this way because it allows you
+    to reuse the reader to parse other XML files.
+
+    Calling this function after the end of file has been reached, but
+    without available data will cause false to be returned whether the
+    previous input was well-formed or not.
+
+    \sa parse(), QXmlInputSource::data(), QXmlInputSource::next()
+*/
+bool QXmlSimpleReader::parseContinue()
+{
+    Q_D(QXmlSimpleReader);
+    if (d->parseStack == 0 || d->parseStack->isEmpty())
+        return false;
+    d->initData();
+    int state = d->parseStack->pop().state;
+    return d->parseBeginOrContinue(state, true);
+}
+
+/*
+  Common part of parse() and parseContinue()
+*/
+bool QXmlSimpleReaderPrivate::parseBeginOrContinue(int state, bool incremental)
+{
+    bool atEndOrig = atEnd();
+
+    if (state==0) {
+        if (!parseProlog()) {
+            if (incremental && error.isNull()) {
+                pushParseState(0, 0);
+                return true;
+            } else {
+                tags.clear();
+                return false;
+            }
+        }
+        state = 1;
+    }
+    if (state==1) {
+        if (!parseElement()) {
+            if (incremental && error.isNull()) {
+                pushParseState(0, 1);
+                return true;
+            } else {
+                tags.clear();
+                return false;
+            }
+        }
+        state = 2;
+    }
+    // parse Misc*
+    while (!atEnd()) {
+        if (!parseMisc()) {
+            if (incremental && error.isNull()) {
+                pushParseState(0, 2);
+                return true;
+            } else {
+                tags.clear();
+                return false;
+            }
+        }
+    }
+    if (!atEndOrig && incremental) {
+        // we parsed something at all, so be prepared to come back later
+        pushParseState(0, 2);
+        return true;
+    }
+    // is stack empty?
+    if (!tags.isEmpty() && !error.isNull()) {
+        reportParseError(QLatin1String(XMLERR_UNEXPECTEDEOF));
+        tags.clear();
+        return false;
+    }
+    // call the handler
+    if (contentHnd) {
+        delete parseStack;
+        parseStack = 0;
+        if (!contentHnd->endDocument()) {
+            reportParseError(contentHnd->errorString());
+            return false;
+        }
+    }
+    return true;
+}
+
+//
+// The following private parse functions have another semantics for the return
+// value: They return true iff parsing has finished successfully (i.e. the end
+// of the XML file must be reached!). If one of these functions return false,
+// there is only an error when d->error.isNULL() is also false.
+//
+
+/*
+  For the incremental parsing, it is very important that the parse...()
+  functions have a certain structure. Since it might be hard to understand how
+  they work, here is a description of the layout of these functions:
+
+    bool QXmlSimpleReader::parse...()
+    {
+(1)        const signed char Init             = 0;
+        ...
+
+(2)        const signed char Inp...           = 0;
+        ...
+
+(3)        static const signed char table[3][2] = {
+        ...
+        };
+        signed char state;
+        signed char input;
+
+(4)        if (d->parseStack == 0 || d->parseStack->isEmpty()) {
+(4a)        ...
+        } else {
+(4b)        ...
+        }
+
+        for (; ;) {
+(5)            switch (state) {
+            ...
+            }
+
+(6)
+(6a)            if (atEnd()) {
+                unexpectedEof(&QXmlSimpleReader::parseNmtoken, state);
+                return false;
+            }
+(6b)            if (determineNameChar(c) != NotName) {
+            ...
+            }
+(7)            state = table[state][input];
+
+(8)            switch (state) {
+            ...
+            }
+        }
+    }
+
+  Explanation:
+  ad 1: constants for the states (used in the transition table)
+  ad 2: constants for the input (used in the transition table)
+  ad 3: the transition table for the state machine
+  ad 4: test if we are in a parseContinue() step
+        a) if no, do inititalizations
+        b) if yes, restore the state and call parse functions recursively
+  ad 5: Do some actions according to the state; from the logical execution
+        order, this code belongs after 8 (see there for an explanation)
+  ad 6: Check the character that is at the actual "cursor" position:
+        a) If we reached the EOF, report either error or push the state (in the
+           case of incremental parsing).
+        b) Otherwise, set the input character constant for the transition
+           table.
+  ad 7: Get the new state according to the input that was read.
+  ad 8: Do some actions according to the state. The last line in every case
+        statement reads new data (i.e. it move the cursor). This can also be
+        done by calling another parse...() function. If you need processing for
+        this state after that, you have to put it into the switch statement 5.
+        This ensures that you have a well defined re-entry point, when you ran
+        out of data.
+*/
+
+/*
+  Parses the prolog [22].
+*/
+
+bool QXmlSimpleReaderPrivate::parseProlog()
+{
+    const signed char Init             = 0;
+    const signed char EatWS            = 1; // eat white spaces
+    const signed char Lt               = 2; // '<' read
+    const signed char Em               = 3; // '!' read
+    const signed char DocType          = 4; // read doctype
+    const signed char Comment          = 5; // read comment
+    const signed char CommentR         = 6; // same as Comment, but already reported
+    const signed char PInstr           = 7; // read PI
+    const signed char PInstrR          = 8; // same as PInstr, but already reported
+    const signed char Done             = 9;
+
+    const signed char InpWs            = 0;
+    const signed char InpLt            = 1; // <
+    const signed char InpQm            = 2; // ?
+    const signed char InpEm            = 3; // !
+    const signed char InpD             = 4; // D
+    const signed char InpDash          = 5; // -
+    const signed char InpUnknown       = 6;
+
+    static const signed char table[9][7] = {
+     /*  InpWs   InpLt  InpQm  InpEm  InpD      InpDash  InpUnknown */
+        { EatWS,  Lt,    -1,    -1,    -1,       -1,       -1      }, // Init
+        { -1,     Lt,    -1,    -1,    -1,       -1,       -1      }, // EatWS
+        { -1,     -1,    PInstr,Em,    Done,     -1,       Done    }, // Lt
+        { -1,     -1,    -1,    -1,    DocType,  Comment,  -1      }, // Em
+        { EatWS,  Lt,    -1,    -1,    -1,       -1,       -1      }, // DocType
+        { EatWS,  Lt,    -1,    -1,    -1,       -1,       -1      }, // Comment
+        { EatWS,  Lt,    -1,    -1,    -1,       -1,       -1      }, // CommentR
+        { EatWS,  Lt,    -1,    -1,    -1,       -1,       -1      }, // PInstr
+        { EatWS,  Lt,    -1,    -1,    -1,       -1,       -1      }  // PInstrR
+    };
+    signed char state;
+    signed char input;
+
+    if (parseStack == 0 || parseStack->isEmpty()) {
+        xmldecl_possible = true;
+        doctype_read = false;
+        state = Init;
+    } else {
+        state = parseStack->pop().state;
+#if defined(QT_QXML_DEBUG)
+        qDebug("QXmlSimpleReader: parseProlog (cont) in state %d", state);
+#endif
+        if (!parseStack->isEmpty()) {
+            ParseFunction function = parseStack->top().function;
+            if (function == &QXmlSimpleReaderPrivate::eat_ws) {
+                parseStack->pop();
+#if defined(QT_QXML_DEBUG)
+                qDebug("QXmlSimpleReader: eat_ws (cont)");
+#endif
+            }
+            if (!(this->*function)()) {
+                parseFailed(&QXmlSimpleReaderPrivate::parseProlog, state);
+                return false;
+            }
+        }
+    }
+
+    for (;;) {
+        switch (state) {
+            case DocType:
+                if (doctype_read) {
+                    reportParseError(QLatin1String(XMLERR_MORETHANONEDOCTYPE));
+                    return false;
+                } else {
+                    doctype_read = false;
+                }
+                break;
+            case Comment:
+                if (lexicalHnd) {
+                    if (!lexicalHnd->comment(string())) {
+                        reportParseError(lexicalHnd->errorString());
+                        return false;
+                    }
+                }
+                state = CommentR;
+                break;
+            case PInstr:
+                // call the handler
+                if (contentHnd) {
+                    if (xmldecl_possible && !xmlVersion.isEmpty()) {
+                        QString value(QLatin1String("version='"));
+                        value += xmlVersion;
+                        value += QLatin1Char('\'');
+                        if (!encoding.isEmpty()) {
+                            value += QLatin1String(" encoding='");
+                            value += encoding;
+                            value += QLatin1Char('\'');
+                        }
+                        if (standalone == QXmlSimpleReaderPrivate::Yes) {
+                            value += QLatin1String(" standalone='yes'");
+                        } else if (standalone == QXmlSimpleReaderPrivate::No) {
+                            value += QLatin1String(" standalone='no'");
+                        }
+                        if (!contentHnd->processingInstruction(QLatin1String("xml"), value)) {
+                            reportParseError(contentHnd->errorString());
+                            return false;
+                        }
+                    } else {
+                        if (!contentHnd->processingInstruction(name(), string())) {
+                            reportParseError(contentHnd->errorString());
+                            return false;
+                        }
+                    }
+                }
+                // XML declaration only on first position possible
+                xmldecl_possible = false;
+                state = PInstrR;
+                break;
+            case Done:
+                return true;
+            case -1:
+                reportParseError(QLatin1String(XMLERR_ERRORPARSINGELEMENT));
+                return false;
+        }
+
+        if (atEnd()) {
+            unexpectedEof(&QXmlSimpleReaderPrivate::parseProlog, state);
+            return false;
+        }
+        if (is_S(c)) {
+            input = InpWs;
+        } else if (c == QLatin1Char('<')) {
+            input = InpLt;
+        } else if (c == QLatin1Char('?')) {
+            input = InpQm;
+        } else if (c == QLatin1Char('!')) {
+            input = InpEm;
+        } else if (c == QLatin1Char('D')) {
+            input = InpD;
+        } else if (c == QLatin1Char('-')) {
+            input = InpDash;
+        } else {
+            input = InpUnknown;
+        }
+        state = table[state][input];
+
+        switch (state) {
+            case EatWS:
+                // XML declaration only on first position possible
+                xmldecl_possible = false;
+                if (!eat_ws()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseProlog, state);
+                    return false;
+                }
+                break;
+            case Lt:
+                next();
+                break;
+            case Em:
+                // XML declaration only on first position possible
+                xmldecl_possible = false;
+                next();
+                break;
+            case DocType:
+                if (!parseDoctype()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseProlog, state);
+                    return false;
+                }
+                break;
+            case Comment:
+            case CommentR:
+                if (!parseComment()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseProlog, state);
+                    return false;
+                }
+                break;
+            case PInstr:
+            case PInstrR:
+                parsePI_xmldecl = xmldecl_possible;
+                if (!parsePI()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseProlog, state);
+                    return false;
+                }
+                break;
+        }
+    }
+    return false;
+}
+
+/*
+  Parse an element [39].
+
+  Precondition: the opening '<' is already read.
+*/
+bool QXmlSimpleReaderPrivate::parseElement()
+{
+    const int Init             =  0;
+    const int ReadName         =  1;
+    const int Ws1              =  2;
+    const int STagEnd          =  3;
+    const int STagEnd2         =  4;
+    const int ETagBegin        =  5;
+    const int ETagBegin2       =  6;
+    const int Ws2              =  7;
+    const int EmptyTag         =  8;
+    const int Attrib           =  9;
+    const int AttribPro        = 10; // like Attrib, but processAttribute was already called
+    const int Ws3              = 11;
+    const int Done             = 12;
+
+    const int InpWs            = 0; // whitespace
+    const int InpNameBe        = 1; // NameBeginning
+    const int InpGt            = 2; // >
+    const int InpSlash         = 3; // /
+    const int InpUnknown       = 4;
+
+    static const int table[12][5] = {
+     /*  InpWs      InpNameBe    InpGt        InpSlash     InpUnknown */
+        { -1,        ReadName,    -1,          -1,          -1        }, // Init
+        { Ws1,       Attrib,      STagEnd,     EmptyTag,    -1        }, // ReadName
+        { -1,        Attrib,      STagEnd,     EmptyTag,    -1        }, // Ws1
+        { STagEnd2,  STagEnd2,    STagEnd2,    STagEnd2,    STagEnd2  }, // STagEnd
+        { -1,        -1,          -1,          ETagBegin,   -1        }, // STagEnd2
+        { -1,        ETagBegin2,  -1,          -1,          -1        }, // ETagBegin
+        { Ws2,       -1,          Done,        -1,          -1        }, // ETagBegin2
+        { -1,        -1,          Done,        -1,          -1        }, // Ws2
+        { -1,        -1,          Done,        -1,          -1        }, // EmptyTag
+        { Ws3,       Attrib,      STagEnd,     EmptyTag,    -1        }, // Attrib
+        { Ws3,       Attrib,      STagEnd,     EmptyTag,    -1        }, // AttribPro
+        { -1,        Attrib,      STagEnd,     EmptyTag,    -1        }  // Ws3
+    };
+    int state;
+    int input;
+
+    if (parseStack == 0 || parseStack->isEmpty()) {
+        state = Init;
+    } else {
+        state = parseStack->pop().state;
+#if defined(QT_QXML_DEBUG)
+        qDebug("QXmlSimpleReader: parseElement (cont) in state %d", state);
+#endif
+        if (!parseStack->isEmpty()) {
+            ParseFunction function = parseStack->top().function;
+            if (function == &QXmlSimpleReaderPrivate::eat_ws) {
+                parseStack->pop();
+#if defined(QT_QXML_DEBUG)
+                qDebug("QXmlSimpleReader: eat_ws (cont)");
+#endif
+            }
+            if (!(this->*function)()) {
+                parseFailed(&QXmlSimpleReaderPrivate::parseElement, state);
+                return false;
+            }
+        }
+    }
+
+    for (;;) {
+        switch (state) {
+            case ReadName:
+                // store it on the stack
+                tags.push(name());
+                // empty the attributes
+                attList.clear();
+                if (useNamespaces)
+                    namespaceSupport.pushContext();
+                break;
+            case ETagBegin2:
+                if (!processElementETagBegin2())
+                    return false;
+                break;
+            case Attrib:
+                if (!processElementAttribute())
+                    return false;
+                state = AttribPro;
+                break;
+            case Done:
+                return true;
+            case -1:
+                reportParseError(QLatin1String(XMLERR_ERRORPARSINGELEMENT));
+                return false;
+        }
+
+        if (atEnd()) {
+            unexpectedEof(&QXmlSimpleReaderPrivate::parseElement, state);
+            return false;
+        }
+        if (fastDetermineNameChar(c) == NameBeginning) {
+            input = InpNameBe;
+        } else if (c == QLatin1Char('>')) {
+            input = InpGt;
+        } else if (is_S(c)) {
+            input = InpWs;
+        } else if (c == QLatin1Char('/')) {
+            input = InpSlash;
+        } else {
+            input = InpUnknown;
+        }
+        state = table[state][input];
+
+        switch (state) {
+            case ReadName:
+                parseName_useRef = false;
+                if (!parseName()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseElement, state);
+                    return false;
+                }
+                break;
+            case Ws1:
+            case Ws2:
+            case Ws3:
+                if (!eat_ws()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseElement, state);
+                    return false;
+                }
+                break;
+            case STagEnd:
+                // call the handler
+                if (contentHnd) {
+                    const QString &tagsTop = tags.top();
+                    if (useNamespaces) {
+                        QString uri, lname;
+                        namespaceSupport.processName(tagsTop, false, uri, lname);
+                        if (!contentHnd->startElement(uri, lname, tagsTop, attList)) {
+                            reportParseError(contentHnd->errorString());
+                            return false;
+                        }
+                    } else {
+                        if (!contentHnd->startElement(QString(), QString(), tagsTop, attList)) {
+                            reportParseError(contentHnd->errorString());
+                            return false;
+                        }
+                    }
+                }
+                next();
+                break;
+            case STagEnd2:
+                if (!parseContent()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseElement, state);
+                    return false;
+                }
+                break;
+            case ETagBegin:
+                next();
+                break;
+            case ETagBegin2:
+                // get the name of the tag
+                parseName_useRef = false;
+                if (!parseName()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseElement, state);
+                    return false;
+                }
+                break;
+            case EmptyTag:
+                if  (tags.isEmpty()) {
+                    reportParseError(QLatin1String(XMLERR_TAGMISMATCH));
+                    return false;
+                }
+                if (!processElementEmptyTag())
+                    return false;
+                next();
+                break;
+            case Attrib:
+            case AttribPro:
+                // get name and value of attribute
+                if (!parseAttribute()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseElement, state);
+                    return false;
+                }
+                break;
+            case Done:
+                next();
+                break;
+        }
+    }
+    return false;
+}
+
+/*
+  Helper to break down the size of the code in the case statement.
+  Return false on error, otherwise true.
+*/
+bool QXmlSimpleReaderPrivate::processElementEmptyTag()
+{
+    QString uri, lname;
+    // pop the stack and call the handler
+    if (contentHnd) {
+        if (useNamespaces) {
+            // report startElement first...
+            namespaceSupport.processName(tags.top(), false, uri, lname);
+            if (!contentHnd->startElement(uri, lname, tags.top(), attList)) {
+                reportParseError(contentHnd->errorString());
+                return false;
+            }
+            // ... followed by endElement...
+            if (!contentHnd->endElement(uri, lname, tags.pop())) {
+                reportParseError(contentHnd->errorString());
+                return false;
+            }
+            // ... followed by endPrefixMapping
+            QStringList prefixesBefore, prefixesAfter;
+            if (contentHnd) {
+                prefixesBefore = namespaceSupport.prefixes();
+            }
+            namespaceSupport.popContext();
+            // call the handler for prefix mapping
+            prefixesAfter = namespaceSupport.prefixes();
+            for (QStringList::Iterator it = prefixesBefore.begin(); it != prefixesBefore.end(); ++it) {
+                if (!prefixesAfter.contains(*it)) {
+                    if (!contentHnd->endPrefixMapping(*it)) {
+                        reportParseError(contentHnd->errorString());
+                        return false;
+                    }
+                }
+            }
+        } else {
+            // report startElement first...
+            if (!contentHnd->startElement(QString(), QString(), tags.top(), attList)) {
+                reportParseError(contentHnd->errorString());
+                return false;
+            }
+            // ... followed by endElement
+            if (!contentHnd->endElement(QString(), QString(), tags.pop())) {
+                reportParseError(contentHnd->errorString());
+                return false;
+            }
+        }
+    } else {
+        tags.pop_back();
+        namespaceSupport.popContext();
+    }
+    return true;
+}
+/*
+  Helper to break down the size of the code in the case statement.
+  Return false on error, otherwise true.
+*/
+bool QXmlSimpleReaderPrivate::processElementETagBegin2()
+{
+    const QString &name = QXmlSimpleReaderPrivate::name();
+
+    // pop the stack and compare it with the name
+    if (tags.pop() != name) {
+        reportParseError(QLatin1String(XMLERR_TAGMISMATCH));
+        return false;
+    }
+    // call the handler
+    if (contentHnd) {
+        QString uri, lname;
+
+        if (useNamespaces)
+            namespaceSupport.processName(name, false, uri, lname);
+        if (!contentHnd->endElement(uri, lname, name)) {
+            reportParseError(contentHnd->errorString());
+            return false;
+        }
+    }
+    if (useNamespaces) {
+        NamespaceMap prefixesBefore, prefixesAfter;
+        if (contentHnd)
+            prefixesBefore = namespaceSupport.d->ns;
+
+        namespaceSupport.popContext();
+        // call the handler for prefix mapping
+        if (contentHnd) {
+            prefixesAfter = namespaceSupport.d->ns;
+            if (prefixesBefore.size() != prefixesAfter.size()) {
+                for (NamespaceMap::const_iterator it = prefixesBefore.constBegin(); it != prefixesBefore.constEnd(); ++it) {
+                    if (!it.key().isEmpty() && !prefixesAfter.contains(it.key())) {
+                        if (!contentHnd->endPrefixMapping(it.key())) {
+                            reportParseError(contentHnd->errorString());
+                            return false;
+                        }
+                    }
+                }
+            }
+        }
+    }
+    return true;
+}
+/*
+  Helper to break down the size of the code in the case statement.
+  Return false on error, otherwise true.
+*/
+bool QXmlSimpleReaderPrivate::processElementAttribute()
+{
+    QString uri, lname, prefix;
+    const QString &name = QXmlSimpleReaderPrivate::name();
+    const QString &string = QXmlSimpleReaderPrivate::string();
+
+    // add the attribute to the list
+    if (useNamespaces) {
+        // is it a namespace declaration?
+        namespaceSupport.splitName(name, prefix, lname);
+        if (prefix == QLatin1String("xmlns")) {
+            // namespace declaration
+            namespaceSupport.setPrefix(lname, string);
+            if (useNamespacePrefixes) {
+                // according to http://www.w3.org/2000/xmlns/, the "prefix"
+                // xmlns maps to the namespace name
+                // http://www.w3.org/2000/xmlns/
+                attList.append(name, QLatin1String("http://www.w3.org/2000/xmlns/"), lname, string);
+            }
+            // call the handler for prefix mapping
+            if (contentHnd) {
+                if (!contentHnd->startPrefixMapping(lname, string)) {
+                    reportParseError(contentHnd->errorString());
+                    return false;
+                }
+            }
+        } else {
+            // no namespace delcaration
+            namespaceSupport.processName(name, true, uri, lname);
+            attList.append(name, uri, lname, string);
+        }
+    } else {
+        // no namespace support
+        attList.append(name, uri, lname, string);
+    }
+    return true;
+}
+
+/*
+  Parse a content [43].
+
+  A content is only used between tags. If a end tag is found the < is already
+  read and the head stand on the '/' of the end tag '</name>'.
+*/
+bool QXmlSimpleReaderPrivate::parseContent()
+{
+    const signed char Init             =  0;
+    const signed char ChD              =  1; // CharData
+    const signed char ChD1             =  2; // CharData help state
+    const signed char ChD2             =  3; // CharData help state
+    const signed char Ref              =  4; // Reference
+    const signed char Lt               =  5; // '<' read
+    const signed char PInstr           =  6; // PI
+    const signed char PInstrR          =  7; // same as PInstr, but already reported
+    const signed char Elem             =  8; // Element
+    const signed char Em               =  9; // '!' read
+    const signed char Com              = 10; // Comment
+    const signed char ComR             = 11; // same as Com, but already reported
+    const signed char CDS              = 12; // CDSect
+    const signed char CDS1             = 13; // read a CDSect
+    const signed char CDS2             = 14; // read a CDSect (help state)
+    const signed char CDS3             = 15; // read a CDSect (help state)
+    const signed char Done             = 16; // finished reading content
+
+    const signed char InpLt            = 0; // <
+    const signed char InpGt            = 1; // >
+    const signed char InpSlash         = 2; // /
+    const signed char InpQMark         = 3; // ?
+    const signed char InpEMark         = 4; // !
+    const signed char InpAmp           = 5; // &
+    const signed char InpDash          = 6; // -
+    const signed char InpOpenB         = 7; // [
+    const signed char InpCloseB        = 8; //]
+    const signed char InpUnknown       = 9;
+
+    static const signed char mapCLT2FSMChar[] = {
+        InpUnknown, // white space
+        InpUnknown, // %
+        InpAmp,     // &
+        InpGt,      // >
+        InpLt,      // <
+        InpSlash,   // /
+        InpQMark,   // ?
+        InpEMark,   // !
+        InpDash,    // -
+        InpCloseB,  //]
+        InpOpenB,   // [
+        InpUnknown, // =
+        InpUnknown, // "
+        InpUnknown, // '
+        InpUnknown  // unknown
+    };
+
+    static const signed char table[16][10] = {
+     /*  InpLt  InpGt  InpSlash  InpQMark  InpEMark  InpAmp  InpDash  InpOpenB  InpCloseB  InpUnknown */
+        { Lt,    ChD,   ChD,      ChD,      ChD,      Ref,    ChD,     ChD,      ChD1,      ChD  }, // Init
+        { Lt,    ChD,   ChD,      ChD,      ChD,      Ref,    ChD,     ChD,      ChD1,      ChD  }, // ChD
+        { Lt,    ChD,   ChD,      ChD,      ChD,      Ref,    ChD,     ChD,      ChD2,      ChD  }, // ChD1
+        { Lt,    -1,    ChD,      ChD,      ChD,      Ref,    ChD,     ChD,      ChD2,      ChD  }, // ChD2
+        { Lt,    ChD,   ChD,      ChD,      ChD,      Ref,    ChD,     ChD,      ChD,       ChD  }, // Ref (same as Init)
+        { -1,    -1,    Done,     PInstr,   Em,       -1,     -1,      -1,       -1,        Elem }, // Lt
+        { Lt,    ChD,   ChD,      ChD,      ChD,      Ref,    ChD,     ChD,      ChD,       ChD  }, // PInstr (same as Init)
+        { Lt,    ChD,   ChD,      ChD,      ChD,      Ref,    ChD,     ChD,      ChD,       ChD  }, // PInstrR
+        { Lt,    ChD,   ChD,      ChD,      ChD,      Ref,    ChD,     ChD,      ChD,       ChD  }, // Elem (same as Init)
+        { -1,    -1,    -1,       -1,       -1,       -1,     Com,     CDS,      -1,        -1   }, // Em
+        { Lt,    ChD,   ChD,      ChD,      ChD,      Ref,    ChD,     ChD,      ChD,       ChD  }, // Com (same as Init)
+        { Lt,    ChD,   ChD,      ChD,      ChD,      Ref,    ChD,     ChD,      ChD,       ChD  }, // ComR
+        { CDS1,  CDS1,  CDS1,     CDS1,     CDS1,     CDS1,   CDS1,    CDS1,     CDS2,      CDS1 }, // CDS
+        { CDS1,  CDS1,  CDS1,     CDS1,     CDS1,     CDS1,   CDS1,    CDS1,     CDS2,      CDS1 }, // CDS1
+        { CDS1,  CDS1,  CDS1,     CDS1,     CDS1,     CDS1,   CDS1,    CDS1,     CDS3,      CDS1 }, // CDS2
+        { CDS1,  Init,  CDS1,     CDS1,     CDS1,     CDS1,   CDS1,    CDS1,     CDS3,      CDS1 }  // CDS3
+    };
+    signed char state;
+    signed char input;
+
+    if (parseStack == 0 || parseStack->isEmpty()) {
+        contentCharDataRead = false;
+        state = Init;
+    } else {
+        state = parseStack->pop().state;
+#if defined(QT_QXML_DEBUG)
+        qDebug("QXmlSimpleReader: parseContent (cont) in state %d", state);
+#endif
+        if (!parseStack->isEmpty()) {
+            ParseFunction function = parseStack->top().function;
+            if (function == &QXmlSimpleReaderPrivate::eat_ws) {
+                parseStack->pop();
+#if defined(QT_QXML_DEBUG)
+                qDebug("QXmlSimpleReader: eat_ws (cont)");
+#endif
+            }
+            if (!(this->*function)()) {
+                parseFailed(&QXmlSimpleReaderPrivate::parseContent, state);
+                return false;
+            }
+        }
+    }
+
+    for (;;) {
+        switch (state) {
+            case Ref:
+                if (!contentCharDataRead)
+                    contentCharDataRead = parseReference_charDataRead;
+                break;
+            case PInstr:
+                if (contentHnd) {
+                    if (!contentHnd->processingInstruction(name(),string())) {
+                        reportParseError(contentHnd->errorString());
+                        return false;
+                    }
+                }
+                state = PInstrR;
+                break;
+            case Com:
+                if (lexicalHnd) {
+                    if (!lexicalHnd->comment(string())) {
+                        reportParseError(lexicalHnd->errorString());
+                        return false;
+                    }
+                }
+                state = ComR;
+                break;
+            case CDS:
+                stringClear();
+                break;
+            case CDS2:
+                if (!atEnd() && c != QLatin1Char(']'))
+                    stringAddC(QLatin1Char(']'));
+                break;
+            case CDS3:
+                // test if this skipping was legal
+                if (!atEnd()) {
+                    if (c == QLatin1Char('>')) {
+                        // the end of the CDSect
+                        if (lexicalHnd) {
+                            if (!lexicalHnd->startCDATA()) {
+                                reportParseError(lexicalHnd->errorString());
+                                return false;
+                            }
+                        }
+                        if (contentHnd) {
+                            if (!contentHnd->characters(string())) {
+                                reportParseError(contentHnd->errorString());
+                                return false;
+                            }
+                        }
+                        if (lexicalHnd) {
+                            if (!lexicalHnd->endCDATA()) {
+                                reportParseError(lexicalHnd->errorString());
+                                return false;
+                            }
+                        }
+                    } else if (c == QLatin1Char(']')) {
+                        // three or more ']'
+                        stringAddC(QLatin1Char(']'));
+                    } else {
+                        // after ']]' comes another character
+                        stringAddC(QLatin1Char(']'));
+                        stringAddC(QLatin1Char(']'));
+                    }
+                }
+                break;
+            case Done:
+                // call the handler for CharData
+                if (contentHnd) {
+                    if (contentCharDataRead) {
+                        if (reportWhitespaceCharData || !string().simplified().isEmpty()) {
+                            if (!contentHnd->characters(string())) {
+                                reportParseError(contentHnd->errorString());
+                                return false;
+                            }
+                        }
+                    }
+                }
+                // Done
+                return true;
+            case -1:
+                // Error
+                reportParseError(QLatin1String(XMLERR_ERRORPARSINGCONTENT));
+                return false;
+        }
+
+        // get input (use lookup-table instead of nested ifs for performance
+        // reasons)
+        if (atEnd()) {
+            unexpectedEof(&QXmlSimpleReaderPrivate::parseContent, state);
+            return false;
+        }
+        if (c.row()) {
+            input = InpUnknown;
+        } else {
+            input = mapCLT2FSMChar[charLookupTable[c.cell()]];
+        }
+        state = table[state][input];
+
+        switch (state) {
+            case Init:
+                // skip the ending '>' of a CDATASection
+                next();
+                break;
+            case ChD:
+                // on first call: clear string
+                if (!contentCharDataRead) {
+                    contentCharDataRead = true;
+                    stringClear();
+                }
+                stringAddC();
+                if (reportEntities) {
+                    if (!reportEndEntities())
+                        return false;
+                }
+                next();
+                break;
+            case ChD1:
+                // on first call: clear string
+                if (!contentCharDataRead) {
+                    contentCharDataRead = true;
+                    stringClear();
+                }
+                stringAddC();
+                if (reportEntities) {
+                    if (!reportEndEntities())
+                        return false;
+                }
+                next();
+                break;
+            case ChD2:
+                stringAddC();
+                if (reportEntities) {
+                    if (!reportEndEntities())
+                        return false;
+                }
+                next();
+                break;
+            case Ref:
+                if (!contentCharDataRead) {
+                    // reference may be CharData; so clear string to be safe
+                    stringClear();
+                    parseReference_context = InContent;
+                    if (!parseReference()) {
+                        parseFailed(&QXmlSimpleReaderPrivate::parseContent, state);
+                        return false;
+                    }
+                } else {
+                    if (reportEntities) {
+                        // report character data in chunks
+                        if (contentHnd) {
+                            if (reportWhitespaceCharData || !string().simplified().isEmpty()) {
+                                if (!contentHnd->characters(string())) {
+                                    reportParseError(contentHnd->errorString());
+                                    return false;
+                                }
+                            }
+                        }
+                        stringClear();
+                    }
+                    parseReference_context = InContent;
+                    if (!parseReference()) {
+                        parseFailed(&QXmlSimpleReaderPrivate::parseContent, state);
+                        return false;
+                    }
+                }
+                break;
+            case Lt:
+                // call the handler for CharData
+                if (contentHnd) {
+                    if (contentCharDataRead) {
+                        if (reportWhitespaceCharData || !string().simplified().isEmpty()) {
+                            if (!contentHnd->characters(string())) {
+                                reportParseError(contentHnd->errorString());
+                                return false;
+                            }
+                        }
+                    }
+                }
+                contentCharDataRead = false;
+                next();
+                break;
+            case PInstr:
+            case PInstrR:
+                parsePI_xmldecl = false;
+                if (!parsePI()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseContent, state);
+                    return false;
+                }
+                break;
+            case Elem:
+                if (!parseElement()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseContent, state);
+                    return false;
+                }
+                break;
+            case Em:
+                next();
+                break;
+            case Com:
+            case ComR:
+                if (!parseComment()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseContent, state);
+                    return false;
+                }
+                break;
+            case CDS:
+                parseString_s = QLatin1String("[CDATA[");
+                if (!parseString()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseContent, state);
+                    return false;
+                }
+                break;
+            case CDS1:
+                stringAddC();
+                next();
+                break;
+            case CDS2:
+                // skip ']'
+                next();
+                break;
+            case CDS3:
+                // skip ']'...
+                next();
+                break;
+        }
+    }
+    return false;
+}
+
+bool QXmlSimpleReaderPrivate::reportEndEntities()
+{
+    int count = (int)xmlRefStack.count();
+    while (count != 0 && xmlRefStack.top().isEmpty()) {
+        if (contentHnd) {
+            if (reportWhitespaceCharData || !string().simplified().isEmpty()) {
+                if (!contentHnd->characters(string())) {
+                    reportParseError(contentHnd->errorString());
+                    return false;
+                }
+            }
+        }
+        stringClear();
+        if (lexicalHnd) {
+            if (!lexicalHnd->endEntity(xmlRefStack.top().name)) {
+                reportParseError(lexicalHnd->errorString());
+                return false;
+            }
+        }
+        xmlRefStack.pop_back();
+        count--;
+    }
+    return true;
+}
+
+/*
+  Parse Misc [27].
+*/
+bool QXmlSimpleReaderPrivate::parseMisc()
+{
+    const signed char Init             = 0;
+    const signed char Lt               = 1; // '<' was read
+    const signed char Comment          = 2; // read comment
+    const signed char eatWS            = 3; // eat whitespaces
+    const signed char PInstr           = 4; // read PI
+    const signed char Comment2         = 5; // read comment
+
+    const signed char InpWs            = 0; // S
+    const signed char InpLt            = 1; // <
+    const signed char InpQm            = 2; // ?
+    const signed char InpEm            = 3; // !
+    const signed char InpUnknown       = 4;
+
+    static const signed char table[3][5] = {
+     /*  InpWs   InpLt  InpQm  InpEm     InpUnknown */
+        { eatWS,  Lt,    -1,    -1,       -1        }, // Init
+        { -1,     -1,    PInstr,Comment,  -1        }, // Lt
+        { -1,     -1,    -1,    -1,       Comment2  }  // Comment
+    };
+    signed char state;
+    signed char input;
+
+    if (parseStack==0 || parseStack->isEmpty()) {
+        state = Init;
+    } else {
+        state = parseStack->pop().state;
+#if defined(QT_QXML_DEBUG)
+        qDebug("QXmlSimpleReader: parseMisc (cont) in state %d", state);
+#endif
+        if (!parseStack->isEmpty()) {
+            ParseFunction function = parseStack->top().function;
+            if (function == &QXmlSimpleReaderPrivate::eat_ws) {
+                parseStack->pop();
+#if defined(QT_QXML_DEBUG)
+                qDebug("QXmlSimpleReader: eat_ws (cont)");
+#endif
+            }
+            if (!(this->*function)()) {
+                parseFailed(&QXmlSimpleReaderPrivate::parseMisc, state);
+                return false;
+            }
+        }
+    }
+
+    for (;;) {
+        switch (state) {
+            case eatWS:
+                return true;
+            case PInstr:
+                if (contentHnd) {
+                    if (!contentHnd->processingInstruction(name(),string())) {
+                        reportParseError(contentHnd->errorString());
+                        return false;
+                    }
+                }
+                return true;
+            case Comment2:
+                if (lexicalHnd) {
+                    if (!lexicalHnd->comment(string())) {
+                        reportParseError(lexicalHnd->errorString());
+                        return false;
+                    }
+                }
+                return true;
+            case -1:
+                // Error
+                reportParseError(QLatin1String(XMLERR_UNEXPECTEDCHARACTER));
+                return false;
+        }
+
+        if (atEnd()) {
+            unexpectedEof(&QXmlSimpleReaderPrivate::parseMisc, state);
+            return false;
+        }
+        if (is_S(c)) {
+            input = InpWs;
+        } else if (c == QLatin1Char('<')) {
+            input = InpLt;
+        } else if (c == QLatin1Char('?')) {
+            input = InpQm;
+        } else if (c == QLatin1Char('!')) {
+            input = InpEm;
+        } else {
+            input = InpUnknown;
+        }
+        state = table[state][input];
+
+        switch (state) {
+            case eatWS:
+                if (!eat_ws()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseMisc, state);
+                    return false;
+                }
+                break;
+            case Lt:
+                next();
+                break;
+            case PInstr:
+                parsePI_xmldecl = false;
+                if (!parsePI()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseMisc, state);
+                    return false;
+                }
+                break;
+            case Comment:
+                next();
+                break;
+            case Comment2:
+                if (!parseComment()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseMisc, state);
+                    return false;
+                }
+                break;
+        }
+    }
+    return false;
+}
+
+/*
+  Parse a processing instruction [16].
+
+  If xmldec is true, it tries to parse a PI or a XML declaration [23].
+
+  Precondition: the beginning '<' of the PI is already read and the head stand
+  on the '?' of '<?'.
+
+  If this funktion was successful, the head-position is on the first
+  character after the PI.
+*/
+bool QXmlSimpleReaderPrivate::parsePI()
+{
+    const signed char Init             =  0;
+    const signed char QmI              =  1; // ? was read
+    const signed char Name             =  2; // read Name
+    const signed char XMLDecl          =  3; // read XMLDecl
+    const signed char Ws1              =  4; // eat ws after "xml" of XMLDecl
+    const signed char PInstr           =  5; // read PI
+    const signed char Ws2              =  6; // eat ws after Name of PI
+    const signed char Version          =  7; // read versionInfo
+    const signed char Ws3              =  8; // eat ws after versionInfo
+    const signed char EorSD            =  9; // read EDecl or SDDecl
+    const signed char Ws4              = 10; // eat ws after EDecl or SDDecl
+    const signed char SD               = 11; // read SDDecl
+    const signed char Ws5              = 12; // eat ws after SDDecl
+    const signed char ADone            = 13; // almost done
+    const signed char Char             = 14; // Char was read
+    const signed char Qm               = 15; // Qm was read
+    const signed char Done             = 16; // finished reading content
+
+    const signed char InpWs            = 0; // whitespace
+    const signed char InpNameBe        = 1; // NameBeginning
+    const signed char InpGt            = 2; // >
+    const signed char InpQm            = 3; // ?
+    const signed char InpUnknown       = 4;
+
+    static const signed char table[16][5] = {
+     /*  InpWs,  InpNameBe  InpGt  InpQm   InpUnknown  */
+        { -1,     -1,        -1,    QmI,    -1     }, // Init
+        { -1,     Name,      -1,    -1,     -1     }, // QmI
+        { -1,     -1,        -1,    -1,     -1     }, // Name (this state is left not through input)
+        { Ws1,    -1,        -1,    -1,     -1     }, // XMLDecl
+        { -1,     Version,   -1,    -1,     -1     }, // Ws1
+        { Ws2,    -1,        -1,    Qm,     -1     }, // PInstr
+        { Char,   Char,      Char,  Qm,     Char   }, // Ws2
+        { Ws3,    -1,        -1,    ADone,  -1     }, // Version
+        { -1,     EorSD,     -1,    ADone,  -1     }, // Ws3
+        { Ws4,    -1,        -1,    ADone,  -1     }, // EorSD
+        { -1,     SD,        -1,    ADone,  -1     }, // Ws4
+        { Ws5,    -1,        -1,    ADone,  -1     }, // SD
+        { -1,     -1,        -1,    ADone,  -1     }, // Ws5
+        { -1,     -1,        Done,  -1,     -1     }, // ADone
+        { Char,   Char,      Char,  Qm,     Char   }, // Char
+        { Char,   Char,      Done,  Qm,     Char   }, // Qm
+    };
+    signed char state;
+    signed char input;
+
+    if (parseStack==0 || parseStack->isEmpty()) {
+        state = Init;
+    } else {
+        state = parseStack->pop().state;
+#if defined(QT_QXML_DEBUG)
+        qDebug("QXmlSimpleReader: parsePI (cont) in state %d", state);
+#endif
+        if (!parseStack->isEmpty()) {
+            ParseFunction function = parseStack->top().function;
+            if (function == &QXmlSimpleReaderPrivate::eat_ws) {
+                parseStack->pop();
+#if defined(QT_QXML_DEBUG)
+                qDebug("QXmlSimpleReader: eat_ws (cont)");
+#endif
+            }
+            if (!(this->*function)()) {
+                parseFailed(&QXmlSimpleReaderPrivate::parsePI, state);
+                return false;
+            }
+        }
+    }
+
+    for (;;) {
+        switch (state) {
+            case Name:
+                // test what name was read and determine the next state
+                // (not very beautiful, I admit)
+                if (name().toLower() == QLatin1String("xml")) {
+                    if (parsePI_xmldecl && name() == QLatin1String("xml")) {
+                        state = XMLDecl;
+                    } else {
+                        reportParseError(QLatin1String(XMLERR_INVALIDNAMEFORPI));
+                        return false;
+                    }
+                } else {
+                    state = PInstr;
+                    stringClear();
+                }
+                break;
+            case Version:
+                // get version (syntax like an attribute)
+                if (name() != QLatin1String("version")) {
+                    reportParseError(QLatin1String(XMLERR_VERSIONEXPECTED));
+                    return false;
+                }
+                xmlVersion = string();
+                break;
+            case EorSD:
+                // get the EDecl or SDDecl (syntax like an attribute)
+                if (name() == QLatin1String("standalone")) {
+                    if (string()== QLatin1String("yes")) {
+                        standalone = QXmlSimpleReaderPrivate::Yes;
+                    } else if (string() == QLatin1String("no")) {
+                        standalone = QXmlSimpleReaderPrivate::No;
+                    } else {
+                        reportParseError(QLatin1String(XMLERR_WRONGVALUEFORSDECL));
+                        return false;
+                    }
+                } else if (name() == QLatin1String("encoding")) {
+                    encoding = string();
+                } else {
+                    reportParseError(QLatin1String(XMLERR_EDECLORSDDECLEXPECTED));
+                    return false;
+                }
+                break;
+            case SD:
+                if (name() != QLatin1String("standalone")) {
+                    reportParseError(QLatin1String(XMLERR_SDDECLEXPECTED));
+                    return false;
+                }
+                if (string() == QLatin1String("yes")) {
+                    standalone = QXmlSimpleReaderPrivate::Yes;
+                } else if (string() == QLatin1String("no")) {
+                    standalone = QXmlSimpleReaderPrivate::No;
+                } else {
+                    reportParseError(QLatin1String(XMLERR_WRONGVALUEFORSDECL));
+                    return false;
+                }
+                break;
+            case Qm:
+                // test if the skipping was legal
+                if (!atEnd() && c != QLatin1Char('>'))
+                    stringAddC(QLatin1Char('?'));
+                break;
+            case Done:
+                return true;
+            case -1:
+                // Error
+                reportParseError(QLatin1String(XMLERR_UNEXPECTEDCHARACTER));
+                return false;
+        }
+
+        if (atEnd()) {
+            unexpectedEof(&QXmlSimpleReaderPrivate::parsePI, state);
+            return false;
+        }
+        if (is_S(c)) {
+            input = InpWs;
+        } else if (determineNameChar(c) == NameBeginning) {
+            input = InpNameBe;
+        } else if (c == QLatin1Char('>')) {
+            input = InpGt;
+        } else if (c == QLatin1Char('?')) {
+            input = InpQm;
+        } else {
+            input = InpUnknown;
+        }
+        state = table[state][input];
+
+        switch (state) {
+            case QmI:
+                next();
+                break;
+            case Name:
+                parseName_useRef = false;
+                if (!parseName()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parsePI, state);
+                    return false;
+                }
+                break;
+            case Ws1:
+            case Ws2:
+            case Ws3:
+            case Ws4:
+            case Ws5:
+                if (!eat_ws()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parsePI, state);
+                    return false;
+                }
+                break;
+            case Version:
+                if (!parseAttribute()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parsePI, state);
+                    return false;
+                }
+                break;
+            case EorSD:
+                if (!parseAttribute()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parsePI, state);
+                    return false;
+                }
+                break;
+            case SD:
+                // get the SDDecl (syntax like an attribute)
+                if (standalone != QXmlSimpleReaderPrivate::Unknown) {
+                    // already parsed the standalone declaration
+                    reportParseError(QLatin1String(XMLERR_UNEXPECTEDCHARACTER));
+                    return false;
+                }
+                if (!parseAttribute()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parsePI, state);
+                    return false;
+                }
+                break;
+            case ADone:
+                next();
+                break;
+            case Char:
+                stringAddC();
+                next();
+                break;
+            case Qm:
+                // skip the '?'
+                next();
+                break;
+            case Done:
+                next();
+                break;
+        }
+    }
+    return false;
+}
+
+/*
+  Parse a document type definition (doctypedecl [28]).
+
+  Precondition: the beginning '<!' of the doctype is already read the head
+  stands on the 'D' of '<!DOCTYPE'.
+
+  If this function was successful, the head-position is on the first
+  character after the document type definition.
+*/
+bool QXmlSimpleReaderPrivate::parseDoctype()
+{
+    const signed char Init             =  0;
+    const signed char Doctype          =  1; // read the doctype
+    const signed char Ws1              =  2; // eat_ws
+    const signed char Doctype2         =  3; // read the doctype, part 2
+    const signed char Ws2              =  4; // eat_ws
+    const signed char Sys              =  5; // read SYSTEM or PUBLIC
+    const signed char Ws3              =  6; // eat_ws
+    const signed char MP               =  7; // markupdecl or PEReference
+    const signed char MPR              =  8; // same as MP, but already reported
+    const signed char PER              =  9; // PERReference
+    const signed char Mup              = 10; // markupdecl
+    const signed char Ws4              = 11; // eat_ws
+    const signed char MPE              = 12; // end of markupdecl or PEReference
+    const signed char Done             = 13;
+
+    const signed char InpWs            = 0;
+    const signed char InpD             = 1; // 'D'
+    const signed char InpS             = 2; // 'S' or 'P'
+    const signed char InpOB            = 3; // [
+    const signed char InpCB            = 4; //]
+    const signed char InpPer           = 5; // %
+    const signed char InpGt            = 6; // >
+    const signed char InpUnknown       = 7;
+
+    static const signed char table[13][8] = {
+     /*  InpWs,  InpD       InpS       InpOB  InpCB  InpPer InpGt  InpUnknown */
+        { -1,     Doctype,   -1,        -1,    -1,    -1,    -1,    -1        }, // Init
+        { Ws1,    -1,        -1,        -1,    -1,    -1,    -1,    -1        }, // Doctype
+        { -1,     Doctype2,  Doctype2,  -1,    -1,    -1,    -1,    Doctype2  }, // Ws1
+        { Ws2,    -1,        Sys,       MP,    -1,    -1,    Done,  -1        }, // Doctype2
+        { -1,     -1,        Sys,       MP,    -1,    -1,    Done,  -1        }, // Ws2
+        { Ws3,    -1,        -1,        MP,    -1,    -1,    Done,  -1        }, // Sys
+        { -1,     -1,        -1,        MP,    -1,    -1,    Done,  -1        }, // Ws3
+        { -1,     -1,        -1,        -1,    MPE,   PER,   -1,    Mup       }, // MP
+        { -1,     -1,        -1,        -1,    MPE,   PER,   -1,    Mup       }, // MPR
+        { Ws4,    -1,        -1,        -1,    MPE,   PER,   -1,    Mup       }, // PER
+        { Ws4,    -1,        -1,        -1,    MPE,   PER,   -1,    Mup       }, // Mup
+        { -1,     -1,        -1,        -1,    MPE,   PER,   -1,    Mup       }, // Ws4
+        { -1,     -1,        -1,        -1,    -1,    -1,    Done,  -1        }  // MPE
+    };
+    signed char state;
+    signed char input;
+
+    if (parseStack==0 || parseStack->isEmpty()) {
+        startDTDwasReported = false;
+        systemId.clear();
+        publicId.clear();
+        state = Init;
+    } else {
+        state = parseStack->pop().state;
+#if defined(QT_QXML_DEBUG)
+        qDebug("QXmlSimpleReader: parseDoctype (cont) in state %d", state);
+#endif
+        if (!parseStack->isEmpty()) {
+            ParseFunction function = parseStack->top().function;
+            if (function == &QXmlSimpleReaderPrivate::eat_ws) {
+                parseStack->pop();
+#if defined(QT_QXML_DEBUG)
+                qDebug("QXmlSimpleReader: eat_ws (cont)");
+#endif
+            }
+            if (!(this->*function)()) {
+                parseFailed(&QXmlSimpleReaderPrivate::parseDoctype, state);
+                return false;
+            }
+        }
+    }
+
+    for (;;) {
+        switch (state) {
+            case Doctype2:
+                doctype = name();
+                break;
+            case MP:
+                if (!startDTDwasReported && lexicalHnd ) {
+                    startDTDwasReported = true;
+                    if (!lexicalHnd->startDTD(doctype, publicId, systemId)) {
+                        reportParseError(lexicalHnd->errorString());
+                        return false;
+                    }
+                }
+                state = MPR;
+                break;
+            case Done:
+                return true;
+            case -1:
+                // Error
+                reportParseError(QLatin1String(XMLERR_ERRORPARSINGDOCTYPE));
+                return false;
+        }
+
+        if (atEnd()) {
+            unexpectedEof(&QXmlSimpleReaderPrivate::parseDoctype, state);
+            return false;
+        }
+        if (is_S(c)) {
+            input = InpWs;
+        } else if (c == QLatin1Char('D')) {
+            input = InpD;
+        } else if (c == QLatin1Char('S')) {
+            input = InpS;
+        } else if (c == QLatin1Char('P')) {
+            input = InpS;
+        } else if (c == QLatin1Char('[')) {
+            input = InpOB;
+        } else if (c == QLatin1Char(']')) {
+            input = InpCB;
+        } else if (c == QLatin1Char('%')) {
+            input = InpPer;
+        } else if (c == QLatin1Char('>')) {
+            input = InpGt;
+        } else {
+            input = InpUnknown;
+        }
+        state = table[state][input];
+
+        switch (state) {
+            case Doctype:
+                parseString_s = QLatin1String("DOCTYPE");
+                if (!parseString()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseDoctype, state);
+                    return false;
+                }
+                break;
+            case Ws1:
+            case Ws2:
+            case Ws3:
+            case Ws4:
+                if (!eat_ws()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseDoctype, state);
+                    return false;
+                }
+                break;
+            case Doctype2:
+                parseName_useRef = false;
+                if (!parseName()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseDoctype, state);
+                    return false;
+                }
+                break;
+            case Sys:
+                parseExternalID_allowPublicID = false;
+                if (!parseExternalID()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseDoctype, state);
+                    return false;
+                }
+                thisPublicId = publicId;
+                thisSystemId = systemId;
+                break;
+            case MP:
+            case MPR:
+                if (!next_eat_ws()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseDoctype, state);
+                    return false;
+                }
+                break;
+            case PER:
+                parsePEReference_context = InDTD;
+                if (!parsePEReference()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseDoctype, state);
+                    return false;
+                }
+                break;
+            case Mup:
+                if (!parseMarkupdecl()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseDoctype, state);
+                    return false;
+                }
+                break;
+            case MPE:
+                if (!next_eat_ws()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseDoctype, state);
+                    return false;
+                }
+                break;
+            case Done:
+                if (lexicalHnd) {
+                    if (!startDTDwasReported) {
+                        startDTDwasReported = true;
+                        if (!lexicalHnd->startDTD(doctype, publicId, systemId)) {
+                            reportParseError(lexicalHnd->errorString());
+                            return false;
+                        }
+                    }
+                    if (!lexicalHnd->endDTD()) {
+                        reportParseError(lexicalHnd->errorString());
+                        return false;
+                    }
+                }
+                next();
+                break;
+        }
+    }
+    return false;
+}
+
+/*
+  Parse a ExternalID [75].
+
+  If allowPublicID is true parse ExternalID [75] or PublicID [83].
+*/
+bool QXmlSimpleReaderPrivate::parseExternalID()
+{
+    const signed char Init             =  0;
+    const signed char Sys              =  1; // parse 'SYSTEM'
+    const signed char SysWS            =  2; // parse the whitespace after 'SYSTEM'
+    const signed char SysSQ            =  3; // parse SystemLiteral with '
+    const signed char SysSQ2           =  4; // parse SystemLiteral with '
+    const signed char SysDQ            =  5; // parse SystemLiteral with "
+    const signed char SysDQ2           =  6; // parse SystemLiteral with "
+    const signed char Pub              =  7; // parse 'PUBLIC'
+    const signed char PubWS            =  8; // parse the whitespace after 'PUBLIC'
+    const signed char PubSQ            =  9; // parse PubidLiteral with '
+    const signed char PubSQ2           = 10; // parse PubidLiteral with '
+    const signed char PubDQ            = 11; // parse PubidLiteral with "
+    const signed char PubDQ2           = 12; // parse PubidLiteral with "
+    const signed char PubE             = 13; // finished parsing the PubidLiteral
+    const signed char PubWS2           = 14; // parse the whitespace after the PubidLiteral
+    const signed char PDone            = 15; // done if allowPublicID is true
+    const signed char Done             = 16;
+
+    const signed char InpSQ            = 0; // '
+    const signed char InpDQ            = 1; // "
+    const signed char InpS             = 2; // S
+    const signed char InpP             = 3; // P
+    const signed char InpWs            = 4; // white space
+    const signed char InpUnknown       = 5;
+
+    static const signed char table[15][6] = {
+     /*  InpSQ    InpDQ    InpS     InpP     InpWs     InpUnknown */
+        { -1,      -1,      Sys,     Pub,     -1,       -1      }, // Init
+        { -1,      -1,      -1,      -1,      SysWS,    -1      }, // Sys
+        { SysSQ,   SysDQ,   -1,      -1,      -1,       -1      }, // SysWS
+        { Done,    SysSQ2,  SysSQ2,  SysSQ2,  SysSQ2,   SysSQ2  }, // SysSQ
+        { Done,    SysSQ2,  SysSQ2,  SysSQ2,  SysSQ2,   SysSQ2  }, // SysSQ2
+        { SysDQ2,  Done,    SysDQ2,  SysDQ2,  SysDQ2,   SysDQ2  }, // SysDQ
+        { SysDQ2,  Done,    SysDQ2,  SysDQ2,  SysDQ2,   SysDQ2  }, // SysDQ2
+        { -1,      -1,      -1,      -1,      PubWS,    -1      }, // Pub
+        { PubSQ,   PubDQ,   -1,      -1,      -1,       -1      }, // PubWS
+        { PubE,    -1,      PubSQ2,  PubSQ2,  PubSQ2,   PubSQ2  }, // PubSQ
+        { PubE,    -1,      PubSQ2,  PubSQ2,  PubSQ2,   PubSQ2  }, // PubSQ2
+        { -1,      PubE,    PubDQ2,  PubDQ2,  PubDQ2,   PubDQ2  }, // PubDQ
+        { -1,      PubE,    PubDQ2,  PubDQ2,  PubDQ2,   PubDQ2  }, // PubDQ2
+        { PDone,   PDone,   PDone,   PDone,   PubWS2,   PDone   }, // PubE
+        { SysSQ,   SysDQ,   PDone,   PDone,   PDone,    PDone   }  // PubWS2
+    };
+    signed char state;
+    signed char input;
+
+    if (parseStack==0 || parseStack->isEmpty()) {
+        systemId.clear();
+        publicId.clear();
+        state = Init;
+    } else {
+        state = parseStack->pop().state;
+#if defined(QT_QXML_DEBUG)
+        qDebug("QXmlSimpleReader: parseExternalID (cont) in state %d", state);
+#endif
+        if (!parseStack->isEmpty()) {
+            ParseFunction function = parseStack->top().function;
+            if (function == &QXmlSimpleReaderPrivate::eat_ws) {
+                parseStack->pop();
+#if defined(QT_QXML_DEBUG)
+                qDebug("QXmlSimpleReader: eat_ws (cont)");
+#endif
+            }
+            if (!(this->*function)()) {
+                parseFailed(&QXmlSimpleReaderPrivate::parseExternalID, state);
+                return false;
+            }
+        }
+    }
+
+    for (;;) {
+        switch (state) {
+            case PDone:
+                if (parseExternalID_allowPublicID) {
+                    publicId = string();
+                    return true;
+                } else {
+                    reportParseError(QLatin1String(XMLERR_UNEXPECTEDCHARACTER));
+                    return false;
+                }
+            case Done:
+                return true;
+            case -1:
+                // Error
+                reportParseError(QLatin1String(XMLERR_UNEXPECTEDCHARACTER));
+                return false;
+        }
+
+        if (atEnd()) {
+            unexpectedEof(&QXmlSimpleReaderPrivate::parseExternalID, state);
+            return false;
+        }
+        if (is_S(c)) {
+            input = InpWs;
+        } else if (c == QLatin1Char('\'')) {
+            input = InpSQ;
+        } else if (c == QLatin1Char('"')) {
+            input = InpDQ;
+        } else if (c == QLatin1Char('S')) {
+            input = InpS;
+        } else if (c == QLatin1Char('P')) {
+            input = InpP;
+        } else {
+            input = InpUnknown;
+        }
+        state = table[state][input];
+
+        switch (state) {
+            case Sys:
+                parseString_s = QLatin1String("SYSTEM");
+                if (!parseString()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseExternalID, state);
+                    return false;
+                }
+                break;
+            case SysWS:
+                if (!eat_ws()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseExternalID, state);
+                    return false;
+                }
+                break;
+            case SysSQ:
+            case SysDQ:
+                stringClear();
+                next();
+                break;
+            case SysSQ2:
+            case SysDQ2:
+                stringAddC();
+                next();
+                break;
+            case Pub:
+                parseString_s = QLatin1String("PUBLIC");
+                if (!parseString()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseExternalID, state);
+                    return false;
+                }
+                break;
+            case PubWS:
+                if (!eat_ws()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseExternalID, state);
+                    return false;
+                }
+                break;
+            case PubSQ:
+            case PubDQ:
+                stringClear();
+                next();
+                break;
+            case PubSQ2:
+            case PubDQ2:
+                stringAddC();
+                next();
+                break;
+            case PubE:
+                next();
+                break;
+            case PubWS2:
+                publicId = string();
+                if (!eat_ws()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseExternalID, state);
+                    return false;
+                }
+                break;
+            case Done:
+                systemId = string();
+                next();
+                break;
+        }
+    }
+    return false;
+}
+
+/*
+  Parse a markupdecl [29].
+*/
+bool QXmlSimpleReaderPrivate::parseMarkupdecl()
+{
+    const signed char Init             = 0;
+    const signed char Lt               = 1; // < was read
+    const signed char Em               = 2; // ! was read
+    const signed char CE               = 3; // E was read
+    const signed char Qm               = 4; // ? was read
+    const signed char Dash             = 5; // - was read
+    const signed char CA               = 6; // A was read
+    const signed char CEL              = 7; // EL was read
+    const signed char CEN              = 8; // EN was read
+    const signed char CN               = 9; // N was read
+    const signed char Done             = 10;
+
+    const signed char InpLt            = 0; // <
+    const signed char InpQm            = 1; // ?
+    const signed char InpEm            = 2; // !
+    const signed char InpDash          = 3; // -
+    const signed char InpA             = 4; // A
+    const signed char InpE             = 5; // E
+    const signed char InpL             = 6; // L
+    const signed char InpN             = 7; // N
+    const signed char InpUnknown       = 8;
+
+    static const signed char table[4][9] = {
+     /*  InpLt  InpQm  InpEm  InpDash  InpA   InpE   InpL   InpN   InpUnknown */
+        { Lt,    -1,    -1,    -1,      -1,    -1,    -1,    -1,    -1     }, // Init
+        { -1,    Qm,    Em,    -1,      -1,    -1,    -1,    -1,    -1     }, // Lt
+        { -1,    -1,    -1,    Dash,    CA,    CE,    -1,    CN,    -1     }, // Em
+        { -1,    -1,    -1,    -1,      -1,    -1,    CEL,   CEN,   -1     }  // CE
+    };
+    signed char state;
+    signed char input;
+
+    if (parseStack==0 || parseStack->isEmpty()) {
+        state = Init;
+    } else {
+        state = parseStack->pop().state;
+#if defined(QT_QXML_DEBUG)
+        qDebug("QXmlSimpleReader: parseMarkupdecl (cont) in state %d", state);
+#endif
+        if (!parseStack->isEmpty()) {
+            ParseFunction function = parseStack->top().function;
+            if (function == &QXmlSimpleReaderPrivate::eat_ws) {
+                parseStack->pop();
+#if defined(QT_QXML_DEBUG)
+                qDebug("QXmlSimpleReader: eat_ws (cont)");
+#endif
+            }
+            if (!(this->*function)()) {
+                parseFailed(&QXmlSimpleReaderPrivate::parseMarkupdecl, state);
+                return false;
+            }
+        }
+    }
+
+    for (;;) {
+        switch (state) {
+            case Qm:
+                if (contentHnd) {
+                    if (!contentHnd->processingInstruction(name(),string())) {
+                        reportParseError(contentHnd->errorString());
+                        return false;
+                    }
+                }
+                return true;
+            case Dash:
+                if (lexicalHnd) {
+                    if (!lexicalHnd->comment(string())) {
+                        reportParseError(lexicalHnd->errorString());
+                        return false;
+                    }
+                }
+                return true;
+            case CA:
+                return true;
+            case CEL:
+                return true;
+            case CEN:
+                return true;
+            case CN:
+                return true;
+            case Done:
+                return true;
+            case -1:
+                // Error
+                reportParseError(QLatin1String(XMLERR_LETTEREXPECTED));
+                return false;
+        }
+
+        if (atEnd()) {
+            unexpectedEof(&QXmlSimpleReaderPrivate::parseMarkupdecl, state);
+            return false;
+        }
+        if        (c == QLatin1Char('<')) {
+            input = InpLt;
+        } else if (c == QLatin1Char('?')) {
+            input = InpQm;
+        } else if (c == QLatin1Char('!')) {
+            input = InpEm;
+        } else if (c == QLatin1Char('-')) {
+            input = InpDash;
+        } else if (c == QLatin1Char('A')) {
+            input = InpA;
+        } else if (c == QLatin1Char('E')) {
+            input = InpE;
+        } else if (c == QLatin1Char('L')) {
+            input = InpL;
+        } else if (c == QLatin1Char('N')) {
+            input = InpN;
+        } else {
+            input = InpUnknown;
+        }
+        state = table[state][input];
+
+        switch (state) {
+            case Lt:
+                next();
+                break;
+            case Em:
+                next();
+                break;
+            case CE:
+                next();
+                break;
+            case Qm:
+                parsePI_xmldecl = false;
+                if (!parsePI()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseMarkupdecl, state);
+                    return false;
+                }
+                break;
+            case Dash:
+                if (!parseComment()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseMarkupdecl, state);
+                    return false;
+                }
+                break;
+            case CA:
+                if (!parseAttlistDecl()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseMarkupdecl, state);
+                    return false;
+                }
+                break;
+            case CEL:
+                if (!parseElementDecl()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseMarkupdecl, state);
+                    return false;
+                }
+                break;
+            case CEN:
+                if (!parseEntityDecl()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseMarkupdecl, state);
+                    return false;
+                }
+                break;
+            case CN:
+                if (!parseNotationDecl()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseMarkupdecl, state);
+                    return false;
+                }
+                break;
+        }
+    }
+    return false;
+}
+
+/*
+  Parse a PEReference [69]
+*/
+bool QXmlSimpleReaderPrivate::parsePEReference()
+{
+    const signed char Init             = 0;
+    const signed char Next             = 1;
+    const signed char Name             = 2;
+    const signed char NameR            = 3; // same as Name, but already reported
+    const signed char Done             = 4;
+
+    const signed char InpSemi          = 0; // ;
+    const signed char InpPer           = 1; // %
+    const signed char InpUnknown       = 2;
+
+    static const signed char table[4][3] = {
+     /*  InpSemi  InpPer  InpUnknown */
+        { -1,      Next,   -1    }, // Init
+        { -1,      -1,     Name  }, // Next
+        { Done,    -1,     -1    }, // Name
+        { Done,    -1,     -1    }  // NameR
+    };
+    signed char state;
+    signed char input;
+
+    if (parseStack==0 || parseStack->isEmpty()) {
+        state = Init;
+    } else {
+        state = parseStack->pop().state;
+#if defined(QT_QXML_DEBUG)
+        qDebug("QXmlSimpleReader: parsePEReference (cont) in state %d", state);
+#endif
+        if (!parseStack->isEmpty()) {
+            ParseFunction function = parseStack->top().function;
+            if (function == &QXmlSimpleReaderPrivate::eat_ws) {
+                parseStack->pop();
+#if defined(QT_QXML_DEBUG)
+                qDebug("QXmlSimpleReader: eat_ws (cont)");
+#endif
+            }
+            if (!(this->*function)()) {
+                parseFailed(&QXmlSimpleReaderPrivate::parsePEReference, state);
+                return false;
+            }
+        }
+    }
+
+    for (;;) {
+        switch (state) {
+            case Name:
+                {
+                    bool skipIt = true;
+                    QString xmlRefString;
+
+                    QMap<QString,QString>::Iterator it;
+                    it = parameterEntities.find(ref());
+                    if (it != parameterEntities.end()) {
+                        skipIt = false;
+                        xmlRefString = *it;
+                    } else if (entityRes) {
+                        QMap<QString,QXmlSimpleReaderPrivate::ExternParameterEntity>::Iterator it2;
+                        it2 = externParameterEntities.find(ref());
+                        QXmlInputSource *ret = 0;
+                        if (it2 != externParameterEntities.end()) {
+                            if (!entityRes->resolveEntity((*it2).publicId, (*it2).systemId, ret)) {
+                                delete ret;
+                                reportParseError(entityRes->errorString());
+                                return false;
+                            }
+                            if (ret) {
+                                xmlRefString = ret->data();
+                                delete ret;
+                                if (!stripTextDecl(xmlRefString)) {
+                                    reportParseError(QLatin1String(XMLERR_ERRORINTEXTDECL));
+                                    return false;
+                                }
+                                skipIt = false;
+                            }
+                        }
+                    }
+
+                    if (skipIt) {
+                        if (contentHnd) {
+                            if (!contentHnd->skippedEntity(QLatin1Char('%') + ref())) {
+                                reportParseError(contentHnd->errorString());
+                                return false;
+                            }
+                        }
+                    } else {
+                        if (parsePEReference_context == InEntityValue) {
+                            // Included in literal
+                            if (!insertXmlRef(xmlRefString, ref(), true))
+                                return false;
+                        } else if (parsePEReference_context == InDTD) {
+                            // Included as PE
+                            if (!insertXmlRef(QLatin1Char(' ') + xmlRefString + QLatin1Char(' '), ref(), false))
+                                return false;
+                        }
+                    }
+                }
+                state = NameR;
+                break;
+            case Done:
+                return true;
+            case -1:
+                // Error
+                reportParseError(QLatin1String(XMLERR_LETTEREXPECTED));
+                return false;
+        }
+
+        if (atEnd()) {
+            unexpectedEof(&QXmlSimpleReaderPrivate::parsePEReference, state);
+            return false;
+        }
+        if        (c == QLatin1Char(';')) {
+            input = InpSemi;
+        } else if (c == QLatin1Char('%')) {
+            input = InpPer;
+        } else {
+            input = InpUnknown;
+        }
+        state = table[state][input];
+
+        switch (state) {
+            case Next:
+                next();
+                break;
+            case Name:
+            case NameR:
+                parseName_useRef = true;
+                if (!parseName()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parsePEReference, state);
+                    return false;
+                }
+                break;
+            case Done:
+                next();
+                break;
+        }
+    }
+    return false;
+}
+
+/*
+  Parse a AttlistDecl [52].
+
+  Precondition: the beginning '<!' is already read and the head
+  stands on the 'A' of '<!ATTLIST'
+*/
+bool QXmlSimpleReaderPrivate::parseAttlistDecl()
+{
+    const signed char Init             =  0;
+    const signed char Attlist          =  1; // parse the string "ATTLIST"
+    const signed char Ws               =  2; // whitespace read
+    const signed char Name             =  3; // parse name
+    const signed char Ws1              =  4; // whitespace read
+    const signed char Attdef           =  5; // parse the AttDef
+    const signed char Ws2              =  6; // whitespace read
+    const signed char Atttype          =  7; // parse the AttType
+    const signed char Ws3              =  8; // whitespace read
+    const signed char DDecH            =  9; // DefaultDecl with #
+    const signed char DefReq           = 10; // parse the string "REQUIRED"
+    const signed char DefImp           = 11; // parse the string "IMPLIED"
+    const signed char DefFix           = 12; // parse the string "FIXED"
+    const signed char Attval           = 13; // parse the AttValue
+    const signed char Ws4              = 14; // whitespace read
+    const signed char Done             = 15;
+
+    const signed char InpWs            = 0; // white space
+    const signed char InpGt            = 1; // >
+    const signed char InpHash          = 2; // #
+    const signed char InpA             = 3; // A
+    const signed char InpI             = 4; // I
+    const signed char InpF             = 5; // F
+    const signed char InpR             = 6; // R
+    const signed char InpUnknown       = 7;
+
+    static const signed char table[15][8] = {
+     /*  InpWs    InpGt    InpHash  InpA      InpI     InpF     InpR     InpUnknown */
+        { -1,      -1,      -1,      Attlist,  -1,      -1,      -1,      -1      }, // Init
+        { Ws,      -1,      -1,      -1,       -1,      -1,      -1,      -1      }, // Attlist
+        { -1,      -1,      -1,      Name,     Name,    Name,    Name,    Name    }, // Ws
+        { Ws1,     Done,    Attdef,  Attdef,   Attdef,  Attdef,  Attdef,  Attdef  }, // Name
+        { -1,      Done,    Attdef,  Attdef,   Attdef,  Attdef,  Attdef,  Attdef  }, // Ws1
+        { Ws2,     -1,      -1,      -1,       -1,      -1,      -1,      -1      }, // Attdef
+        { -1,      Atttype, Atttype, Atttype,  Atttype, Atttype, Atttype, Atttype }, // Ws2
+        { Ws3,     -1,      -1,      -1,       -1,      -1,      -1,      -1      }, // Attype
+        { -1,      Attval,  DDecH,   Attval,   Attval,  Attval,  Attval,  Attval  }, // Ws3
+        { -1,      -1,      -1,      -1,       DefImp,  DefFix,  DefReq,  -1      }, // DDecH
+        { Ws4,     Ws4,     -1,      -1,       -1,      -1,      -1,      -1      }, // DefReq
+        { Ws4,     Ws4,     -1,      -1,       -1,      -1,      -1,      -1      }, // DefImp
+        { Ws3,     -1,      -1,      -1,       -1,      -1,      -1,      -1      }, // DefFix
+        { Ws4,     Ws4,     -1,      -1,       -1,      -1,      -1,      -1      }, // Attval
+        { -1,      Done,    Attdef,  Attdef,   Attdef,  Attdef,  Attdef,  Attdef  }  // Ws4
+    };
+    signed char state;
+    signed char input;
+
+    if (parseStack==0 || parseStack->isEmpty()) {
+        state = Init;
+    } else {
+        state = parseStack->pop().state;
+#if defined(QT_QXML_DEBUG)
+        qDebug("QXmlSimpleReader: parseAttlistDecl (cont) in state %d", state);
+#endif
+        if (!parseStack->isEmpty()) {
+            ParseFunction function = parseStack->top().function;
+            if (function == &QXmlSimpleReaderPrivate::eat_ws) {
+                parseStack->pop();
+#if defined(QT_QXML_DEBUG)
+                qDebug("QXmlSimpleReader: eat_ws (cont)");
+#endif
+            }
+            if (!(this->*function)()) {
+                parseFailed(&QXmlSimpleReaderPrivate::parseAttlistDecl, state);
+                return false;
+            }
+        }
+    }
+
+    for (;;) {
+        switch (state) {
+            case Name:
+                attDeclEName = name();
+                break;
+            case Attdef:
+                attDeclAName = name();
+                break;
+            case Done:
+                return true;
+            case -1:
+                // Error
+                reportParseError(QLatin1String(XMLERR_LETTEREXPECTED));
+                return false;
+        }
+
+        if (atEnd()) {
+            unexpectedEof(&QXmlSimpleReaderPrivate::parseAttlistDecl, state);
+            return false;
+        }
+        if (is_S(c)) {
+            input = InpWs;
+        } else if (c == QLatin1Char('>')) {
+            input = InpGt;
+        } else if (c == QLatin1Char('#')) {
+            input = InpHash;
+        } else if (c == QLatin1Char('A')) {
+            input = InpA;
+        } else if (c == QLatin1Char('I')) {
+            input = InpI;
+        } else if (c == QLatin1Char('F')) {
+            input = InpF;
+        } else if (c == QLatin1Char('R')) {
+            input = InpR;
+        } else {
+            input = InpUnknown;
+        }
+        state = table[state][input];
+
+        switch (state) {
+            case Attlist:
+                parseString_s = QLatin1String("ATTLIST");
+                if (!parseString()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseAttlistDecl, state);
+                    return false;
+                }
+                break;
+            case Ws:
+            case Ws1:
+            case Ws2:
+            case Ws3:
+                if (!eat_ws()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseAttlistDecl, state);
+                    return false;
+                }
+                break;
+            case Name:
+                parseName_useRef = false;
+                if (!parseName()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseAttlistDecl, state);
+                    return false;
+                }
+                break;
+            case Attdef:
+                parseName_useRef = false;
+                if (!parseName()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseAttlistDecl, state);
+                    return false;
+                }
+                break;
+            case Atttype:
+                if (!parseAttType()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseAttlistDecl, state);
+                    return false;
+                }
+                break;
+            case DDecH:
+                next();
+                break;
+            case DefReq:
+                parseString_s = QLatin1String("REQUIRED");
+                if (!parseString()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseAttlistDecl, state);
+                    return false;
+                }
+                break;
+            case DefImp:
+                parseString_s = QLatin1String("IMPLIED");
+                if (!parseString()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseAttlistDecl, state);
+                    return false;
+                }
+                break;
+            case DefFix:
+                parseString_s = QLatin1String("FIXED");
+                if (!parseString()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseAttlistDecl, state);
+                    return false;
+                }
+                break;
+            case Attval:
+                if (!parseAttValue()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseAttlistDecl, state);
+                    return false;
+                }
+                break;
+            case Ws4:
+                if (declHnd) {
+                    // ### not all values are computed yet...
+                    if (!declHnd->attributeDecl(attDeclEName, attDeclAName, QLatin1String(""), QLatin1String(""), QLatin1String(""))) {
+                        reportParseError(declHnd->errorString());
+                        return false;
+                    }
+                }
+                if (!eat_ws()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseAttlistDecl, state);
+                    return false;
+                }
+                break;
+            case Done:
+                next();
+                break;
+        }
+    }
+    return false;
+}
+
+/*
+  Parse a AttType [54]
+*/
+bool QXmlSimpleReaderPrivate::parseAttType()
+{
+    const signed char Init             =  0;
+    const signed char ST               =  1; // StringType
+    const signed char TTI              =  2; // TokenizedType starting with 'I'
+    const signed char TTI2             =  3; // TokenizedType helpstate
+    const signed char TTI3             =  4; // TokenizedType helpstate
+    const signed char TTE              =  5; // TokenizedType starting with 'E'
+    const signed char TTEY             =  6; // TokenizedType starting with 'ENTITY'
+    const signed char TTEI             =  7; // TokenizedType starting with 'ENTITI'
+    const signed char N                =  8; // N read (TokenizedType or Notation)
+    const signed char TTNM             =  9; // TokenizedType starting with 'NM'
+    const signed char TTNM2            = 10; // TokenizedType helpstate
+    const signed char NO               = 11; // Notation
+    const signed char NO2              = 12; // Notation helpstate
+    const signed char NO3              = 13; // Notation helpstate
+    const signed char NOName           = 14; // Notation, read name
+    const signed char NO4              = 15; // Notation helpstate
+    const signed char EN               = 16; // Enumeration
+    const signed char ENNmt            = 17; // Enumeration, read Nmtoken
+    const signed char EN2              = 18; // Enumeration helpstate
+    const signed char ADone            = 19; // almost done (make next and accept)
+    const signed char Done             = 20;
+
+    const signed char InpWs            =  0; // whitespace
+    const signed char InpOp            =  1; // (
+    const signed char InpCp            =  2; //)
+    const signed char InpPipe          =  3; // |
+    const signed char InpC             =  4; // C
+    const signed char InpE             =  5; // E
+    const signed char InpI             =  6; // I
+    const signed char InpM             =  7; // M
+    const signed char InpN             =  8; // N
+    const signed char InpO             =  9; // O
+    const signed char InpR             = 10; // R
+    const signed char InpS             = 11; // S
+    const signed char InpY             = 12; // Y
+    const signed char InpUnknown       = 13;
+
+    static const signed char table[19][14] = {
+     /*  InpWs    InpOp    InpCp    InpPipe  InpC     InpE     InpI     InpM     InpN     InpO     InpR     InpS     InpY     InpUnknown */
+        { -1,      EN,      -1,      -1,      ST,      TTE,     TTI,     -1,      N,       -1,      -1,      -1,      -1,      -1     }, // Init
+        { Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done   }, // ST
+        { Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    TTI2,    Done,    Done,    Done   }, // TTI
+        { Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    TTI3,    Done,    Done   }, // TTI2
+        { Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done   }, // TTI3
+        { -1,      -1,      -1,      -1,      -1,      -1,      TTEI,    -1,      -1,      -1,      -1,      -1,      TTEY,    -1     }, // TTE
+        { Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done   }, // TTEY
+        { Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done   }, // TTEI
+        { -1,      -1,      -1,      -1,      -1,      -1,      -1,      TTNM,    -1,      NO,      -1,      -1,      -1,      -1     }, // N
+        { Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    TTNM2,   Done,    Done   }, // TTNM
+        { Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done   }, // TTNM2
+        { NO2,     -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1     }, // NO
+        { -1,      NO3,     -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1     }, // NO2
+        { NOName,  NOName,  NOName,  NOName,  NOName,  NOName,  NOName,  NOName,  NOName,  NOName,  NOName,  NOName,  NOName,  NOName }, // NO3
+        { NO4,     -1,      ADone,   NO3,     -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1     }, // NOName
+        { -1,      -1,      ADone,   NO3,     -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1     }, // NO4
+        { -1,      -1,      ENNmt,   -1,      ENNmt,   ENNmt,   ENNmt,   ENNmt,   ENNmt,   ENNmt,   ENNmt,   ENNmt,   ENNmt,   ENNmt  }, // EN
+        { EN2,     -1,      ADone,   EN,      -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1     }, // ENNmt
+        { -1,      -1,      ADone,   EN,      -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1     }  // EN2
+    };
+    signed char state;
+    signed char input;
+
+    if (parseStack==0 || parseStack->isEmpty()) {
+        state = Init;
+    } else {
+        state = parseStack->pop().state;
+#if defined(QT_QXML_DEBUG)
+        qDebug("QXmlSimpleReader: parseAttType (cont) in state %d", state);
+#endif
+        if (!parseStack->isEmpty()) {
+            ParseFunction function = parseStack->top().function;
+            if (function == &QXmlSimpleReaderPrivate::eat_ws) {
+                parseStack->pop();
+#if defined(QT_QXML_DEBUG)
+                qDebug("QXmlSimpleReader: eat_ws (cont)");
+#endif
+            }
+            if (!(this->*function)()) {
+                parseFailed(&QXmlSimpleReaderPrivate::parseAttType, state);
+                return false;
+            }
+        }
+    }
+
+    for (;;) {
+        switch (state) {
+            case ADone:
+                return true;
+            case Done:
+                return true;
+            case -1:
+                // Error
+                reportParseError(QLatin1String(XMLERR_LETTEREXPECTED));
+                return false;
+        }
+
+        if (atEnd()) {
+            unexpectedEof(&QXmlSimpleReaderPrivate::parseAttType, state);
+            return false;
+        }
+        if (is_S(c)) {
+            input = InpWs;
+        } else if (c == QLatin1Char('(')) {
+            input = InpOp;
+        } else if (c == QLatin1Char(')')) {
+            input = InpCp;
+        } else if (c == QLatin1Char('|')) {
+            input = InpPipe;
+        } else if (c == QLatin1Char('C')) {
+            input = InpC;
+        } else if (c == QLatin1Char('E')) {
+            input = InpE;
+        } else if (c == QLatin1Char('I')) {
+            input = InpI;
+        } else if (c == QLatin1Char('M')) {
+            input = InpM;
+        } else if (c == QLatin1Char('N')) {
+            input = InpN;
+        } else if (c == QLatin1Char('O')) {
+            input = InpO;
+        } else if (c == QLatin1Char('R')) {
+            input = InpR;
+        } else if (c == QLatin1Char('S')) {
+            input = InpS;
+        } else if (c == QLatin1Char('Y')) {
+            input = InpY;
+        } else {
+            input = InpUnknown;
+        }
+        state = table[state][input];
+
+        switch (state) {
+            case ST:
+                parseString_s = QLatin1String("CDATA");
+                if (!parseString()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseAttType, state);
+                    return false;
+                }
+                break;
+            case TTI:
+                parseString_s = QLatin1String("ID");
+                if (!parseString()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseAttType, state);
+                    return false;
+                }
+                break;
+            case TTI2:
+                parseString_s = QLatin1String("REF");
+                if (!parseString()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseAttType, state);
+                    return false;
+                }
+                break;
+            case TTI3:
+                next(); // S
+                break;
+            case TTE:
+                parseString_s = QLatin1String("ENTIT");
+                if (!parseString()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseAttType, state);
+                    return false;
+                }
+                break;
+            case TTEY:
+                next(); // Y
+                break;
+            case TTEI:
+                parseString_s = QLatin1String("IES");
+                if (!parseString()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseAttType, state);
+                    return false;
+                }
+                break;
+            case N:
+                next(); // N
+                break;
+            case TTNM:
+                parseString_s = QLatin1String("MTOKEN");
+                if (!parseString()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseAttType, state);
+                    return false;
+                }
+                break;
+            case TTNM2:
+                next(); // S
+                break;
+            case NO:
+                parseString_s = QLatin1String("OTATION");
+                if (!parseString()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseAttType, state);
+                    return false;
+                }
+                break;
+            case NO2:
+                if (!eat_ws()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseAttType, state);
+                    return false;
+                }
+                break;
+            case NO3:
+                if (!next_eat_ws()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseAttType, state);
+                    return false;
+                }
+                break;
+            case NOName:
+                parseName_useRef = false;
+                if (!parseName()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseAttType, state);
+                    return false;
+                }
+                break;
+            case NO4:
+                if (!eat_ws()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseAttType, state);
+                    return false;
+                }
+                break;
+            case EN:
+                if (!next_eat_ws()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseAttType, state);
+                    return false;
+                }
+                break;
+            case ENNmt:
+                if (!parseNmtoken()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseAttType, state);
+                    return false;
+                }
+                break;
+            case EN2:
+                if (!eat_ws()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseAttType, state);
+                    return false;
+                }
+                break;
+            case ADone:
+                next();
+                break;
+        }
+    }
+    return false;
+}
+
+/*
+  Parse a AttValue [10]
+
+  Precondition: the head stands on the beginning " or '
+
+  If this function was successful, the head stands on the first
+  character after the closing " or ' and the value of the attribute
+  is in string().
+*/
+bool QXmlSimpleReaderPrivate::parseAttValue()
+{
+    const signed char Init             = 0;
+    const signed char Dq               = 1; // double quotes were read
+    const signed char DqRef            = 2; // read references in double quotes
+    const signed char DqC              = 3; // signed character read in double quotes
+    const signed char Sq               = 4; // single quotes were read
+    const signed char SqRef            = 5; // read references in single quotes
+    const signed char SqC              = 6; // signed character read in single quotes
+    const signed char Done             = 7;
+
+    const signed char InpDq            = 0; // "
+    const signed char InpSq            = 1; // '
+    const signed char InpAmp           = 2; // &
+    const signed char InpLt            = 3; // <
+    const signed char InpUnknown       = 4;
+
+    static const signed char table[7][5] = {
+     /*  InpDq  InpSq  InpAmp  InpLt InpUnknown */
+        { Dq,    Sq,    -1,     -1,   -1    }, // Init
+        { Done,  DqC,   DqRef,  -1,   DqC   }, // Dq
+        { Done,  DqC,   DqRef,  -1,   DqC   }, // DqRef
+        { Done,  DqC,   DqRef,  -1,   DqC   }, // DqC
+        { SqC,   Done,  SqRef,  -1,   SqC   }, // Sq
+        { SqC,   Done,  SqRef,  -1,   SqC   }, // SqRef
+        { SqC,   Done,  SqRef,  -1,   SqC   }  // SqRef
+    };
+    signed char state;
+    signed char input;
+
+    if (parseStack==0 || parseStack->isEmpty()) {
+        state = Init;
+    } else {
+        state = parseStack->pop().state;
+#if defined(QT_QXML_DEBUG)
+        qDebug("QXmlSimpleReader: parseAttValue (cont) in state %d", state);
+#endif
+        if (!parseStack->isEmpty()) {
+            ParseFunction function = parseStack->top().function;
+            if (function == &QXmlSimpleReaderPrivate::eat_ws) {
+                parseStack->pop();
+#if defined(QT_QXML_DEBUG)
+                qDebug("QXmlSimpleReader: eat_ws (cont)");
+#endif
+            }
+            if (!(this->*function)()) {
+                parseFailed(&QXmlSimpleReaderPrivate::parseAttValue, state);
+                return false;
+            }
+        }
+    }
+
+    for (;;) {
+        switch (state) {
+            case Done:
+                return true;
+            case -1:
+                // Error
+                reportParseError(QLatin1String(XMLERR_UNEXPECTEDCHARACTER));
+                return false;
+        }
+
+        if (atEnd()) {
+            unexpectedEof(&QXmlSimpleReaderPrivate::parseAttValue, state);
+            return false;
+        }
+        if        (c == QLatin1Char('"')) {
+            input = InpDq;
+        } else if (c == QLatin1Char('\'')) {
+            input = InpSq;
+        } else if (c == QLatin1Char('&')) {
+            input = InpAmp;
+        } else if (c == QLatin1Char('<')) {
+            input = InpLt;
+        } else {
+            input = InpUnknown;
+        }
+        state = table[state][input];
+
+        switch (state) {
+            case Dq:
+            case Sq:
+                stringClear();
+                next();
+                break;
+            case DqRef:
+            case SqRef:
+                parseReference_context = InAttributeValue;
+                if (!parseReference()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseAttValue, state);
+                    return false;
+                }
+                break;
+            case DqC:
+            case SqC:
+                stringAddC();
+                next();
+                break;
+            case Done:
+                next();
+                break;
+        }
+    }
+    return false;
+}
+
+/*
+  Parse a elementdecl [45].
+
+  Precondition: the beginning '<!E' is already read and the head
+  stands on the 'L' of '<!ELEMENT'
+*/
+bool QXmlSimpleReaderPrivate::parseElementDecl()
+{
+    const signed char Init             =  0;
+    const signed char Elem             =  1; // parse the beginning string
+    const signed char Ws1              =  2; // whitespace required
+    const signed char Nam              =  3; // parse Name
+    const signed char Ws2              =  4; // whitespace required
+    const signed char Empty            =  5; // read EMPTY
+    const signed char Any              =  6; // read ANY
+    const signed char Cont             =  7; // read contentspec (except ANY or EMPTY)
+    const signed char Mix              =  8; // read Mixed
+    const signed char Mix2             =  9; //
+    const signed char Mix3             = 10; //
+    const signed char MixN1            = 11; //
+    const signed char MixN2            = 12; //
+    const signed char MixN3            = 13; //
+    const signed char MixN4            = 14; //
+    const signed char Cp               = 15; // parse cp
+    const signed char Cp2              = 16; //
+    const signed char WsD              = 17; // eat whitespace before Done
+    const signed char Done             = 18;
+
+    const signed char InpWs            =  0;
+    const signed char InpGt            =  1; // >
+    const signed char InpPipe          =  2; // |
+    const signed char InpOp            =  3; // (
+    const signed char InpCp            =  4; //)
+    const signed char InpHash          =  5; // #
+    const signed char InpQm            =  6; // ?
+    const signed char InpAst           =  7; // *
+    const signed char InpPlus          =  8; // +
+    const signed char InpA             =  9; // A
+    const signed char InpE             = 10; // E
+    const signed char InpL             = 11; // L
+    const signed char InpUnknown       = 12;
+
+    static const signed char table[18][13] = {
+     /*  InpWs   InpGt  InpPipe  InpOp  InpCp   InpHash  InpQm  InpAst  InpPlus  InpA    InpE    InpL    InpUnknown */
+        { -1,     -1,    -1,      -1,    -1,     -1,      -1,    -1,     -1,      -1,     -1,     Elem,   -1     }, // Init
+        { Ws1,    -1,    -1,      -1,    -1,     -1,      -1,    -1,     -1,      -1,     -1,     -1,     -1     }, // Elem
+        { -1,     -1,    -1,      -1,    -1,     -1,      -1,    -1,     -1,      Nam,    Nam,    Nam,    Nam    }, // Ws1
+        { Ws2,    -1,    -1,      -1,    -1,     -1,      -1,    -1,     -1,      -1,     -1,     -1,     -1     }, // Nam
+        { -1,     -1,    -1,      Cont,  -1,     -1,      -1,    -1,     -1,      Any,    Empty,  -1,     -1     }, // Ws2
+        { WsD,    Done,  -1,      -1,    -1,     -1,      -1,    -1,     -1,      -1,     -1,     -1,     -1     }, // Empty
+        { WsD,    Done,  -1,      -1,    -1,     -1,      -1,    -1,     -1,      -1,     -1,     -1,     -1     }, // Any
+        { -1,     -1,    -1,      Cp,    Cp,     Mix,     -1,    -1,     -1,      Cp,     Cp,     Cp,     Cp     }, // Cont
+        { Mix2,   -1,    MixN1,   -1,    Mix3,   -1,      -1,    -1,     -1,      -1,     -1,     -1,     -1     }, // Mix
+        { -1,     -1,    MixN1,   -1,    Mix3,   -1,      -1,    -1,     -1,      -1,     -1,     -1,     -1     }, // Mix2
+        { WsD,    Done,  -1,      -1,    -1,     -1,      -1,    WsD,    -1,      -1,     -1,     -1,     -1     }, // Mix3
+        { -1,     -1,    -1,      -1,    -1,     -1,      -1,    -1,     -1,      MixN2,  MixN2,  MixN2,  MixN2  }, // MixN1
+        { MixN3,  -1,    MixN1,   -1,    MixN4,  -1,      -1,    -1,     -1,      -1,     -1,     -1,     -1     }, // MixN2
+        { -1,     -1,    MixN1,   -1,    MixN4,  -1,      -1,    -1,     -1,      -1,     -1,     -1,     -1     }, // MixN3
+        { -1,     -1,    -1,      -1,    -1,     -1,      -1,    WsD,    -1,      -1,     -1,     -1,     -1     }, // MixN4
+        { WsD,    Done,  -1,      -1,    -1,     -1,      Cp2,   Cp2,    Cp2,     -1,     -1,     -1,     -1     }, // Cp
+        { WsD,    Done,  -1,      -1,    -1,     -1,      -1,    -1,     -1,      -1,     -1,     -1,     -1     }, // Cp2
+        { -1,     Done,  -1,      -1,    -1,     -1,      -1,    -1,     -1,      -1,     -1,     -1,     -1     }  // WsD
+    };
+    signed char state;
+    signed char input;
+
+    if (parseStack==0 || parseStack->isEmpty()) {
+        state = Init;
+    } else {
+        state = parseStack->pop().state;
+#if defined(QT_QXML_DEBUG)
+        qDebug("QXmlSimpleReader: parseElementDecl (cont) in state %d", state);
+#endif
+        if (!parseStack->isEmpty()) {
+            ParseFunction function = parseStack->top().function;
+            if (function == &QXmlSimpleReaderPrivate::eat_ws) {
+                parseStack->pop();
+#if defined(QT_QXML_DEBUG)
+                qDebug("QXmlSimpleReader: eat_ws (cont)");
+#endif
+            }
+            if (!(this->*function)()) {
+                parseFailed(&QXmlSimpleReaderPrivate::parseElementDecl, state);
+                return false;
+            }
+        }
+    }
+
+    for (;;) {
+        switch (state) {
+            case Done:
+                return true;
+            case -1:
+                reportParseError(QLatin1String(XMLERR_UNEXPECTEDCHARACTER));
+                return false;
+        }
+
+        if (atEnd()) {
+            unexpectedEof(&QXmlSimpleReaderPrivate::parseElementDecl, state);
+            return false;
+        }
+        if (is_S(c)) {
+            input = InpWs;
+        } else if (c == QLatin1Char('>')) {
+            input = InpGt;
+        } else if (c == QLatin1Char('|')) {
+            input = InpPipe;
+        } else if (c == QLatin1Char('(')) {
+            input = InpOp;
+        } else if (c == QLatin1Char(')')) {
+            input = InpCp;
+        } else if (c == QLatin1Char('#')) {
+            input = InpHash;
+        } else if (c == QLatin1Char('?')) {
+            input = InpQm;
+        } else if (c == QLatin1Char('*')) {
+            input = InpAst;
+        } else if (c == QLatin1Char('+')) {
+            input = InpPlus;
+        } else if (c == QLatin1Char('A')) {
+            input = InpA;
+        } else if (c == QLatin1Char('E')) {
+            input = InpE;
+        } else if (c == QLatin1Char('L')) {
+            input = InpL;
+        } else {
+            input = InpUnknown;
+        }
+        state = table[state][input];
+
+        switch (state) {
+            case Elem:
+                parseString_s = QLatin1String("LEMENT");
+                if (!parseString()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseElementDecl, state);
+                    return false;
+                }
+                break;
+            case Ws1:
+                if (!eat_ws()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseElementDecl, state);
+                    return false;
+                }
+                break;
+            case Nam:
+                parseName_useRef = false;
+                if (!parseName()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseElementDecl, state);
+                    return false;
+                }
+                break;
+            case Ws2:
+                if (!eat_ws()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseElementDecl, state);
+                    return false;
+                }
+                break;
+            case Empty:
+                parseString_s = QLatin1String("EMPTY");
+                if (!parseString()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseElementDecl, state);
+                    return false;
+                }
+                break;
+            case Any:
+                parseString_s = QLatin1String("ANY");
+                if (!parseString()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseElementDecl, state);
+                    return false;
+                }
+                break;
+            case Cont:
+                if (!next_eat_ws()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseElementDecl, state);
+                    return false;
+                }
+                break;
+            case Mix:
+                parseString_s = QLatin1String("#PCDATA");
+                if (!parseString()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseElementDecl, state);
+                    return false;
+                }
+                break;
+            case Mix2:
+                if (!eat_ws()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseElementDecl, state);
+                    return false;
+                }
+                break;
+            case Mix3:
+                next();
+                break;
+            case MixN1:
+                if (!next_eat_ws()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseElementDecl, state);
+                    return false;
+                }
+                break;
+            case MixN2:
+                parseName_useRef = false;
+                if (!parseName()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseElementDecl, state);
+                    return false;
+                }
+                break;
+            case MixN3:
+                if (!eat_ws()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseElementDecl, state);
+                    return false;
+                }
+                break;
+            case MixN4:
+                next();
+                break;
+            case Cp:
+                if (!parseChoiceSeq()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseElementDecl, state);
+                    return false;
+                }
+                break;
+            case Cp2:
+                next();
+                break;
+            case WsD:
+                if (!next_eat_ws()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseElementDecl, state);
+                    return false;
+                }
+                break;
+            case Done:
+                next();
+                break;
+        }
+    }
+    return false;
+}
+
+/*
+  Parse a NotationDecl [82].
+
+  Precondition: the beginning '<!' is already read and the head
+  stands on the 'N' of '<!NOTATION'
+*/
+bool QXmlSimpleReaderPrivate::parseNotationDecl()
+{
+    const signed char Init             = 0;
+    const signed char Not              = 1; // read NOTATION
+    const signed char Ws1              = 2; // eat whitespaces
+    const signed char Nam              = 3; // read Name
+    const signed char Ws2              = 4; // eat whitespaces
+    const signed char ExtID            = 5; // parse ExternalID
+    const signed char ExtIDR           = 6; // same as ExtID, but already reported
+    const signed char Ws3              = 7; // eat whitespaces
+    const signed char Done             = 8;
+
+    const signed char InpWs            = 0;
+    const signed char InpGt            = 1; // >
+    const signed char InpN             = 2; // N
+    const signed char InpUnknown       = 3;
+
+    static const signed char table[8][4] = {
+     /*  InpWs   InpGt  InpN    InpUnknown */
+        { -1,     -1,    Not,    -1     }, // Init
+        { Ws1,    -1,    -1,     -1     }, // Not
+        { -1,     -1,    Nam,    Nam    }, // Ws1
+        { Ws2,    Done,  -1,     -1     }, // Nam
+        { -1,     Done,  ExtID,  ExtID  }, // Ws2
+        { Ws3,    Done,  -1,     -1     }, // ExtID
+        { Ws3,    Done,  -1,     -1     }, // ExtIDR
+        { -1,     Done,  -1,     -1     }  // Ws3
+    };
+    signed char state;
+    signed char input;
+
+    if (parseStack==0 || parseStack->isEmpty()) {
+        state = Init;
+    } else {
+        state = parseStack->pop().state;
+#if defined(QT_QXML_DEBUG)
+        qDebug("QXmlSimpleReader: parseNotationDecl (cont) in state %d", state);
+#endif
+        if (!parseStack->isEmpty()) {
+            ParseFunction function = parseStack->top().function;
+            if (function == &QXmlSimpleReaderPrivate::eat_ws) {
+                parseStack->pop();
+#if defined(QT_QXML_DEBUG)
+                qDebug("QXmlSimpleReader: eat_ws (cont)");
+#endif
+            }
+            if (!(this->*function)()) {
+                parseFailed(&QXmlSimpleReaderPrivate::parseNotationDecl, state);
+                return false;
+            }
+        }
+    }
+
+    for (;;) {
+        switch (state) {
+            case ExtID:
+                // call the handler
+                if (dtdHnd) {
+                    if (!dtdHnd->notationDecl(name(), publicId, systemId)) {
+                        reportParseError(dtdHnd->errorString());
+                        return false;
+                    }
+                }
+                state = ExtIDR;
+                break;
+            case Done:
+                return true;
+            case -1:
+                // Error
+                reportParseError(QLatin1String(XMLERR_UNEXPECTEDCHARACTER));
+                return false;
+        }
+
+        if (atEnd()) {
+            unexpectedEof(&QXmlSimpleReaderPrivate::parseNotationDecl, state);
+            return false;
+        }
+        if (is_S(c)) {
+            input = InpWs;
+        } else if (c == QLatin1Char('>')) {
+            input = InpGt;
+        } else if (c == QLatin1Char('N')) {
+            input = InpN;
+        } else {
+            input = InpUnknown;
+        }
+        state = table[state][input];
+
+        switch (state) {
+            case Not:
+                parseString_s = QLatin1String("NOTATION");
+                if (!parseString()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseNotationDecl, state);
+                    return false;
+                }
+                break;
+            case Ws1:
+                if (!eat_ws()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseNotationDecl, state);
+                    return false;
+                }
+                break;
+            case Nam:
+                parseName_useRef = false;
+                if (!parseName()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseNotationDecl, state);
+                    return false;
+                }
+                break;
+            case Ws2:
+                if (!eat_ws()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseNotationDecl, state);
+                    return false;
+                }
+                break;
+            case ExtID:
+            case ExtIDR:
+                parseExternalID_allowPublicID = true;
+                if (!parseExternalID()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseNotationDecl, state);
+                    return false;
+                }
+                break;
+            case Ws3:
+                if (!eat_ws()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseNotationDecl, state);
+                    return false;
+                }
+                break;
+            case Done:
+                next();
+                break;
+        }
+    }
+    return false;
+}
+
+/*
+  Parse choice [49] or seq [50].
+
+  Precondition: the beginning '('S? is already read and the head
+  stands on the first non-whitespace character after it.
+*/
+bool QXmlSimpleReaderPrivate::parseChoiceSeq()
+{
+    const signed char Init             = 0;
+    const signed char Ws1              = 1; // eat whitespace
+    const signed char CoS              = 2; // choice or set
+    const signed char Ws2              = 3; // eat whitespace
+    const signed char More             = 4; // more cp to read
+    const signed char Name             = 5; // read name
+    const signed char Done             = 6; //
+
+    const signed char InpWs            = 0; // S
+    const signed char InpOp            = 1; // (
+    const signed char InpCp            = 2; //)
+    const signed char InpQm            = 3; // ?
+    const signed char InpAst           = 4; // *
+    const signed char InpPlus          = 5; // +
+    const signed char InpPipe          = 6; // |
+    const signed char InpComm          = 7; // ,
+    const signed char InpUnknown       = 8;
+
+    static const signed char table[6][9] = {
+     /*  InpWs   InpOp  InpCp  InpQm  InpAst  InpPlus  InpPipe  InpComm  InpUnknown */
+        { -1,     Ws1,   -1,    -1,    -1,     -1,      -1,      -1,      Name  }, // Init
+        { -1,     CoS,   -1,    -1,    -1,     -1,      -1,      -1,      CoS   }, // Ws1
+        { Ws2,    -1,    Done,  Ws2,   Ws2,    Ws2,     More,    More,    -1    }, // CS
+        { -1,     -1,    Done,  -1,    -1,     -1,      More,    More,    -1    }, // Ws2
+        { -1,     Ws1,   -1,    -1,    -1,     -1,      -1,      -1,      Name  }, // More (same as Init)
+        { Ws2,    -1,    Done,  Ws2,   Ws2,    Ws2,     More,    More,    -1    }  // Name (same as CS)
+    };
+    signed char state;
+    signed char input;
+
+    if (parseStack==0 || parseStack->isEmpty()) {
+        state = Init;
+    } else {
+        state = parseStack->pop().state;
+#if defined(QT_QXML_DEBUG)
+        qDebug("QXmlSimpleReader: parseChoiceSeq (cont) in state %d", state);
+#endif
+        if (!parseStack->isEmpty()) {
+            ParseFunction function = parseStack->top().function;
+            if (function == &QXmlSimpleReaderPrivate::eat_ws) {
+                parseStack->pop();
+#if defined(QT_QXML_DEBUG)
+                qDebug("QXmlSimpleReader: eat_ws (cont)");
+#endif
+            }
+            if (!(this->*function)()) {
+                parseFailed(&QXmlSimpleReaderPrivate::parseChoiceSeq, state);
+                return false;
+            }
+        }
+    }
+
+    for (;;) {
+        switch (state) {
+            case Done:
+                return true;
+            case -1:
+                // Error
+                reportParseError(QLatin1String(XMLERR_UNEXPECTEDCHARACTER));
+                return false;
+        }
+
+        if (atEnd()) {
+            unexpectedEof(&QXmlSimpleReaderPrivate::parseChoiceSeq, state);
+            return false;
+        }
+        if (is_S(c)) {
+            input = InpWs;
+        } else if (c == QLatin1Char('(')) {
+            input = InpOp;
+        } else if (c == QLatin1Char(')')) {
+            input = InpCp;
+        } else if (c == QLatin1Char('?')) {
+            input = InpQm;
+        } else if (c == QLatin1Char('*')) {
+            input = InpAst;
+        } else if (c == QLatin1Char('+')) {
+            input = InpPlus;
+        } else if (c == QLatin1Char('|')) {
+            input = InpPipe;
+        } else if (c == QLatin1Char(',')) {
+            input = InpComm;
+        } else {
+            input = InpUnknown;
+        }
+        state = table[state][input];
+
+        switch (state) {
+            case Ws1:
+                if (!next_eat_ws()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseChoiceSeq, state);
+                    return false;
+                }
+                break;
+            case CoS:
+                if (!parseChoiceSeq()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseChoiceSeq, state);
+                    return false;
+                }
+                break;
+            case Ws2:
+                if (!next_eat_ws()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseChoiceSeq, state);
+                    return false;
+                }
+                break;
+            case More:
+                if (!next_eat_ws()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseChoiceSeq, state);
+                    return false;
+                }
+                break;
+            case Name:
+                parseName_useRef = false;
+                if (!parseName()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseChoiceSeq, state);
+                    return false;
+                }
+                break;
+            case Done:
+                next();
+                break;
+        }
+    }
+    return false;
+}
+
+/*
+  Parse a EntityDecl [70].
+
+  Precondition: the beginning '<!E' is already read and the head
+  stand on the 'N' of '<!ENTITY'
+*/
+bool QXmlSimpleReaderPrivate::parseEntityDecl()
+{
+    const signed char Init             =  0;
+    const signed char Ent              =  1; // parse "ENTITY"
+    const signed char Ws1              =  2; // white space read
+    const signed char Name             =  3; // parse name
+    const signed char Ws2              =  4; // white space read
+    const signed char EValue           =  5; // parse entity value
+    const signed char EValueR          =  6; // same as EValue, but already reported
+    const signed char ExtID            =  7; // parse ExternalID
+    const signed char Ws3              =  8; // white space read
+    const signed char Ndata            =  9; // parse "NDATA"
+    const signed char Ws4              = 10; // white space read
+    const signed char NNam             = 11; // parse name
+    const signed char NNamR            = 12; // same as NNam, but already reported
+    const signed char PEDec            = 13; // parse PEDecl
+    const signed char Ws6              = 14; // white space read
+    const signed char PENam            = 15; // parse name
+    const signed char Ws7              = 16; // white space read
+    const signed char PEVal            = 17; // parse entity value
+    const signed char PEValR           = 18; // same as PEVal, but already reported
+    const signed char PEEID            = 19; // parse ExternalID
+    const signed char PEEIDR           = 20; // same as PEEID, but already reported
+    const signed char WsE              = 21; // white space read
+    const signed char Done             = 22;
+    const signed char EDDone           = 23; // done, but also report an external, unparsed entity decl
+
+    const signed char InpWs            = 0; // white space
+    const signed char InpPer           = 1; // %
+    const signed char InpQuot          = 2; // " or '
+    const signed char InpGt            = 3; // >
+    const signed char InpN             = 4; // N
+    const signed char InpUnknown       = 5;
+
+    static const signed char table[22][6] = {
+     /*  InpWs  InpPer  InpQuot  InpGt  InpN    InpUnknown */
+        { -1,    -1,     -1,      -1,    Ent,    -1      }, // Init
+        { Ws1,   -1,     -1,      -1,    -1,     -1      }, // Ent
+        { -1,    PEDec,  -1,      -1,    Name,   Name    }, // Ws1
+        { Ws2,   -1,     -1,      -1,    -1,     -1      }, // Name
+        { -1,    -1,     EValue,  -1,    -1,     ExtID   }, // Ws2
+        { WsE,   -1,     -1,      Done,  -1,     -1      }, // EValue
+        { WsE,   -1,     -1,      Done,  -1,     -1      }, // EValueR
+        { Ws3,   -1,     -1,      EDDone,-1,     -1      }, // ExtID
+        { -1,    -1,     -1,      EDDone,Ndata,  -1      }, // Ws3
+        { Ws4,   -1,     -1,      -1,    -1,     -1      }, // Ndata
+        { -1,    -1,     -1,      -1,    NNam,   NNam    }, // Ws4
+        { WsE,   -1,     -1,      Done,  -1,     -1      }, // NNam
+        { WsE,   -1,     -1,      Done,  -1,     -1      }, // NNamR
+        { Ws6,   -1,     -1,      -1,    -1,     -1      }, // PEDec
+        { -1,    -1,     -1,      -1,    PENam,  PENam   }, // Ws6
+        { Ws7,   -1,     -1,      -1,    -1,     -1      }, // PENam
+        { -1,    -1,     PEVal,   -1,    -1,     PEEID   }, // Ws7
+        { WsE,   -1,     -1,      Done,  -1,     -1      }, // PEVal
+        { WsE,   -1,     -1,      Done,  -1,     -1      }, // PEValR
+        { WsE,   -1,     -1,      Done,  -1,     -1      }, // PEEID
+        { WsE,   -1,     -1,      Done,  -1,     -1      }, // PEEIDR
+        { -1,    -1,     -1,      Done,  -1,     -1      }  // WsE
+    };
+    signed char state;
+    signed char input;
+
+    if (parseStack==0 || parseStack->isEmpty()) {
+        state = Init;
+    } else {
+        state = parseStack->pop().state;
+#if defined(QT_QXML_DEBUG)
+        qDebug("QXmlSimpleReader: parseEntityDecl (cont) in state %d", state);
+#endif
+        if (!parseStack->isEmpty()) {
+            ParseFunction function = parseStack->top().function;
+            if (function == &QXmlSimpleReaderPrivate::eat_ws) {
+                parseStack->pop();
+#if defined(QT_QXML_DEBUG)
+                qDebug("QXmlSimpleReader: eat_ws (cont)");
+#endif
+            }
+            if (!(this->*function)()) {
+                parseFailed(&QXmlSimpleReaderPrivate::parseEntityDecl, state);
+                return false;
+            }
+        }
+    }
+
+    for (;;) {
+        switch (state) {
+            case EValue:
+                if ( !entityExist(name())) {
+                    entities.insert(name(), string());
+                    if (declHnd) {
+                        if (!declHnd->internalEntityDecl(name(), string())) {
+                            reportParseError(declHnd->errorString());
+                            return false;
+                        }
+                    }
+                }
+                state = EValueR;
+                break;
+            case NNam:
+                if ( !entityExist(name())) {
+                    externEntities.insert(name(), QXmlSimpleReaderPrivate::ExternEntity(publicId, systemId, ref()));
+                    if (dtdHnd) {
+                        if (!dtdHnd->unparsedEntityDecl(name(), publicId, systemId, ref())) {
+                            reportParseError(declHnd->errorString());
+                            return false;
+                        }
+                    }
+                }
+                state = NNamR;
+                break;
+            case PEVal:
+                if ( !entityExist(name())) {
+                    parameterEntities.insert(name(), string());
+                    if (declHnd) {
+                        if (!declHnd->internalEntityDecl(QLatin1Char('%') + name(), string())) {
+                            reportParseError(declHnd->errorString());
+                            return false;
+                        }
+                    }
+                }
+                state = PEValR;
+                break;
+            case PEEID:
+                if ( !entityExist(name())) {
+                    externParameterEntities.insert(name(), QXmlSimpleReaderPrivate::ExternParameterEntity(publicId, systemId));
+                    if (declHnd) {
+                        if (!declHnd->externalEntityDecl(QLatin1Char('%') + name(), publicId, systemId)) {
+                            reportParseError(declHnd->errorString());
+                            return false;
+                        }
+                    }
+                }
+                state = PEEIDR;
+                break;
+            case EDDone:
+                if ( !entityExist(name())) {
+                    externEntities.insert(name(), QXmlSimpleReaderPrivate::ExternEntity(publicId, systemId, QString()));
+                    if (declHnd) {
+                        if (!declHnd->externalEntityDecl(name(), publicId, systemId)) {
+                            reportParseError(declHnd->errorString());
+                            return false;
+                        }
+                    }
+                }
+                return true;
+            case Done:
+                return true;
+            case -1:
+                // Error
+                reportParseError(QLatin1String(XMLERR_LETTEREXPECTED));
+                return false;
+        }
+
+        if (atEnd()) {
+            unexpectedEof(&QXmlSimpleReaderPrivate::parseEntityDecl, state);
+            return false;
+        }
+        if (is_S(c)) {
+            input = InpWs;
+        } else if (c == QLatin1Char('%')) {
+            input = InpPer;
+        } else if (c == QLatin1Char('"') || c == QLatin1Char('\'')) {
+            input = InpQuot;
+        } else if (c == QLatin1Char('>')) {
+            input = InpGt;
+        } else if (c == QLatin1Char('N')) {
+            input = InpN;
+        } else {
+            input = InpUnknown;
+        }
+        state = table[state][input];
+
+        switch (state) {
+            case Ent:
+                parseString_s = QLatin1String("NTITY");
+                if (!parseString()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseEntityDecl, state);
+                    return false;
+                }
+                break;
+            case Ws1:
+                if (!eat_ws()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseEntityDecl, state);
+                    return false;
+                }
+                break;
+            case Name:
+                parseName_useRef = false;
+                if (!parseName()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseEntityDecl, state);
+                    return false;
+                }
+                break;
+            case Ws2:
+                if (!eat_ws()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseEntityDecl, state);
+                    return false;
+                }
+                break;
+            case EValue:
+            case EValueR:
+                if (!parseEntityValue()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseEntityDecl, state);
+                    return false;
+                }
+                break;
+            case ExtID:
+                parseExternalID_allowPublicID = false;
+                if (!parseExternalID()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseEntityDecl, state);
+                    return false;
+                }
+                break;
+            case Ws3:
+                if (!eat_ws()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseEntityDecl, state);
+                    return false;
+                }
+                break;
+            case Ndata:
+                parseString_s = QLatin1String("NDATA");
+                if (!parseString()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseEntityDecl, state);
+                    return false;
+                }
+                break;
+            case Ws4:
+                if (!eat_ws()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseEntityDecl, state);
+                    return false;
+                }
+                break;
+            case NNam:
+            case NNamR:
+                parseName_useRef = true;
+                if (!parseName()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseEntityDecl, state);
+                    return false;
+                }
+                break;
+            case PEDec:
+                next();
+                break;
+            case Ws6:
+                if (!eat_ws()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseEntityDecl, state);
+                    return false;
+                }
+                break;
+            case PENam:
+                parseName_useRef = false;
+                if (!parseName()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseEntityDecl, state);
+                    return false;
+                }
+                break;
+            case Ws7:
+                if (!eat_ws()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseEntityDecl, state);
+                    return false;
+                }
+                break;
+            case PEVal:
+            case PEValR:
+                if (!parseEntityValue()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseEntityDecl, state);
+                    return false;
+                }
+                break;
+            case PEEID:
+            case PEEIDR:
+                parseExternalID_allowPublicID = false;
+                if (!parseExternalID()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseEntityDecl, state);
+                    return false;
+                }
+                break;
+            case WsE:
+                if (!eat_ws()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseEntityDecl, state);
+                    return false;
+                }
+                break;
+            case EDDone:
+                next();
+                break;
+            case Done:
+                next();
+                break;
+        }
+    }
+    return false;
+}
+
+/*
+  Parse a EntityValue [9]
+*/
+bool QXmlSimpleReaderPrivate::parseEntityValue()
+{
+    const signed char Init             = 0;
+    const signed char Dq               = 1; // EntityValue is double quoted
+    const signed char DqC              = 2; // signed character
+    const signed char DqPER            = 3; // PERefence
+    const signed char DqRef            = 4; // Reference
+    const signed char Sq               = 5; // EntityValue is double quoted
+    const signed char SqC              = 6; // signed character
+    const signed char SqPER            = 7; // PERefence
+    const signed char SqRef            = 8; // Reference
+    const signed char Done             = 9;
+
+    const signed char InpDq            = 0; // "
+    const signed char InpSq            = 1; // '
+    const signed char InpAmp           = 2; // &
+    const signed char InpPer           = 3; // %
+    const signed char InpUnknown       = 4;
+
+    static const signed char table[9][5] = {
+     /*  InpDq  InpSq  InpAmp  InpPer  InpUnknown */
+        { Dq,    Sq,    -1,     -1,     -1    }, // Init
+        { Done,  DqC,   DqRef,  DqPER,  DqC   }, // Dq
+        { Done,  DqC,   DqRef,  DqPER,  DqC   }, // DqC
+        { Done,  DqC,   DqRef,  DqPER,  DqC   }, // DqPER
+        { Done,  DqC,   DqRef,  DqPER,  DqC   }, // DqRef
+        { SqC,   Done,  SqRef,  SqPER,  SqC   }, // Sq
+        { SqC,   Done,  SqRef,  SqPER,  SqC   }, // SqC
+        { SqC,   Done,  SqRef,  SqPER,  SqC   }, // SqPER
+        { SqC,   Done,  SqRef,  SqPER,  SqC   }  // SqRef
+    };
+    signed char state;
+    signed char input;
+
+    if (parseStack==0 || parseStack->isEmpty()) {
+        state = Init;
+    } else {
+        state = parseStack->pop().state;
+#if defined(QT_QXML_DEBUG)
+        qDebug("QXmlSimpleReader: parseEntityValue (cont) in state %d", state);
+#endif
+        if (!parseStack->isEmpty()) {
+            ParseFunction function = parseStack->top().function;
+            if (function == &QXmlSimpleReaderPrivate::eat_ws) {
+                parseStack->pop();
+#if defined(QT_QXML_DEBUG)
+                qDebug("QXmlSimpleReader: eat_ws (cont)");
+#endif
+            }
+            if (!(this->*function)()) {
+                parseFailed(&QXmlSimpleReaderPrivate::parseEntityValue, state);
+                return false;
+            }
+        }
+    }
+
+    for (;;) {
+        switch (state) {
+            case Done:
+                return true;
+            case -1:
+                // Error
+                reportParseError(QLatin1String(XMLERR_LETTEREXPECTED));
+                return false;
+        }
+
+        if (atEnd()) {
+            unexpectedEof(&QXmlSimpleReaderPrivate::parseEntityValue, state);
+            return false;
+        }
+        if        (c == QLatin1Char('"')) {
+            input = InpDq;
+        } else if (c == QLatin1Char('\'')) {
+            input = InpSq;
+        } else if (c == QLatin1Char('&')) {
+            input = InpAmp;
+        } else if (c == QLatin1Char('%')) {
+            input = InpPer;
+        } else {
+            input = InpUnknown;
+        }
+        state = table[state][input];
+
+        switch (state) {
+            case Dq:
+            case Sq:
+                stringClear();
+                next();
+                break;
+            case DqC:
+            case SqC:
+                stringAddC();
+                next();
+                break;
+            case DqPER:
+            case SqPER:
+                parsePEReference_context = InEntityValue;
+                if (!parsePEReference()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseEntityValue, state);
+                    return false;
+                }
+                break;
+            case DqRef:
+            case SqRef:
+                parseReference_context = InEntityValue;
+                if (!parseReference()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseEntityValue, state);
+                    return false;
+                }
+                break;
+            case Done:
+                next();
+                break;
+        }
+    }
+    return false;
+}
+
+/*
+  Parse a comment [15].
+
+  Precondition: the beginning '<!' of the comment is already read and the head
+  stands on the first '-' of '<!--'.
+
+  If this funktion was successful, the head-position is on the first
+  character after the comment.
+*/
+bool QXmlSimpleReaderPrivate::parseComment()
+{
+    const signed char Init             = 0;
+    const signed char Dash1            = 1; // the first dash was read
+    const signed char Dash2            = 2; // the second dash was read
+    const signed char Com              = 3; // read comment
+    const signed char Com2             = 4; // read comment (help state)
+    const signed char ComE             = 5; // finished reading comment
+    const signed char Done             = 6;
+
+    const signed char InpDash          = 0; // -
+    const signed char InpGt            = 1; // >
+    const signed char InpUnknown       = 2;
+
+    static const signed char table[6][3] = {
+     /*  InpDash  InpGt  InpUnknown */
+        { Dash1,   -1,    -1  }, // Init
+        { Dash2,   -1,    -1  }, // Dash1
+        { Com2,    Com,   Com }, // Dash2
+        { Com2,    Com,   Com }, // Com
+        { ComE,    Com,   Com }, // Com2
+        { -1,      Done,  -1  }  // ComE
+    };
+    signed char state;
+    signed char input;
+
+    if (parseStack==0 || parseStack->isEmpty()) {
+        state = Init;
+    } else {
+        state = parseStack->pop().state;
+#if defined(QT_QXML_DEBUG)
+        qDebug("QXmlSimpleReader: parseComment (cont) in state %d", state);
+#endif
+        if (!parseStack->isEmpty()) {
+            ParseFunction function = parseStack->top().function;
+            if (function == &QXmlSimpleReaderPrivate::eat_ws) {
+                parseStack->pop();
+#if defined(QT_QXML_DEBUG)
+                qDebug("QXmlSimpleReader: eat_ws (cont)");
+#endif
+            }
+            if (!(this->*function)()) {
+                parseFailed(&QXmlSimpleReaderPrivate::parseComment, state);
+                return false;
+            }
+        }
+    }
+
+    for (;;) {
+        switch (state) {
+            case Dash2:
+                stringClear();
+                break;
+            case Com2:
+                // if next character is not a dash than don't skip it
+                if (!atEnd() && c != QLatin1Char('-'))
+                    stringAddC(QLatin1Char('-'));
+                break;
+            case Done:
+                return true;
+            case -1:
+                // Error
+                reportParseError(QLatin1String(XMLERR_ERRORPARSINGCOMMENT));
+                return false;
+        }
+
+        if (atEnd()) {
+            unexpectedEof(&QXmlSimpleReaderPrivate::parseComment, state);
+            return false;
+        }
+        if (c == QLatin1Char('-')) {
+            input = InpDash;
+        } else if (c == QLatin1Char('>')) {
+            input = InpGt;
+        } else {
+            input = InpUnknown;
+        }
+        state = table[state][input];
+
+        switch (state) {
+            case Dash1:
+                next();
+                break;
+            case Dash2:
+                next();
+                break;
+            case Com:
+                stringAddC();
+                next();
+                break;
+            case Com2:
+                next();
+                break;
+            case ComE:
+                next();
+                break;
+            case Done:
+                next();
+                break;
+        }
+    }
+    return false;
+}
+
+/*
+    Parse an Attribute [41].
+
+    Precondition: the head stands on the first character of the name
+    of the attribute (i.e. all whitespaces are already parsed).
+
+    The head stand on the next character after the end quotes. The
+    variable name contains the name of the attribute and the variable
+    string contains the value of the attribute.
+*/
+bool QXmlSimpleReaderPrivate::parseAttribute()
+{
+    const int Init             = 0;
+    const int PName            = 1; // parse name
+    const int Ws               = 2; // eat ws
+    const int Eq               = 3; // the '=' was read
+    const int Quotes           = 4; // " or ' were read
+
+    const int InpNameBe        = 0;
+    const int InpEq            = 1; // =
+    const int InpDq            = 2; // "
+    const int InpSq            = 3; // '
+    const int InpUnknown       = 4;
+
+    static const int table[4][5] = {
+     /*  InpNameBe  InpEq  InpDq    InpSq    InpUnknown */
+        { PName,     -1,    -1,      -1,      -1    }, // Init
+        { -1,        Eq,    -1,      -1,      Ws    }, // PName
+        { -1,        Eq,    -1,      -1,      -1    }, // Ws
+        { -1,        -1,    Quotes,  Quotes,  -1    }  // Eq
+    };
+    int state;
+    int input;
+
+    if (parseStack==0 || parseStack->isEmpty()) {
+        state = Init;
+    } else {
+        state = parseStack->pop().state;
+#if defined(QT_QXML_DEBUG)
+        qDebug("QXmlSimpleReader: parseAttribute (cont) in state %d", state);
+#endif
+        if (!parseStack->isEmpty()) {
+            ParseFunction function = parseStack->top().function;
+            if (function == &QXmlSimpleReaderPrivate::eat_ws) {
+                parseStack->pop();
+#if defined(QT_QXML_DEBUG)
+                qDebug("QXmlSimpleReader: eat_ws (cont)");
+#endif
+            }
+            if (!(this->*function)()) {
+                parseFailed(&QXmlSimpleReaderPrivate::parseAttribute, state);
+                return false;
+            }
+        }
+    }
+
+    for (;;) {
+        switch (state) {
+            case Quotes:
+                // Done
+                return true;
+            case -1:
+                // Error
+                reportParseError(QLatin1String(XMLERR_UNEXPECTEDCHARACTER));
+                return false;
+        }
+
+        if (atEnd()) {
+            unexpectedEof(&QXmlSimpleReaderPrivate::parseAttribute, state);
+            return false;
+        }
+        if (determineNameChar(c) == NameBeginning) {
+            input = InpNameBe;
+        } else if (c == QLatin1Char('=')) {
+            input = InpEq;
+        } else if (c == QLatin1Char('"')) {
+            input = InpDq;
+        } else if (c == QLatin1Char('\'')) {
+            input = InpSq;
+        } else {
+            input = InpUnknown;
+        }
+        state = table[state][input];
+
+        switch (state) {
+            case PName:
+                parseName_useRef = false;
+                if (!parseName()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseAttribute, state);
+                    return false;
+                }
+                break;
+            case Ws:
+                if (!eat_ws()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseAttribute, state);
+                    return false;
+                }
+                break;
+            case Eq:
+                if (!next_eat_ws()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseAttribute, state);
+                    return false;
+                }
+                break;
+            case Quotes:
+                if (!parseAttValue()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseAttribute, state);
+                    return false;
+                }
+                break;
+        }
+    }
+    return false;
+}
+
+/*
+  Parse a Name [5] and store the name in name or ref (if useRef is true).
+*/
+bool QXmlSimpleReaderPrivate::parseName()
+{
+    const int Init             = 0;
+    const int Name1            = 1; // parse first character of the name
+    const int Name             = 2; // parse name
+    const int Done             = 3;
+
+    static const int table[3][3] = {
+     /*  InpNameBe  InpNameCh  InpUnknown */
+        { Name1,     -1,        -1    }, // Init
+        { Name,      Name,      Done  }, // Name1
+        { Name,      Name,      Done  }  // Name
+    };
+    int state;
+
+    if (parseStack==0 || parseStack->isEmpty()) {
+        state = Init;
+    } else {
+        state = parseStack->pop().state;
+#if defined(QT_QXML_DEBUG)
+        qDebug("QXmlSimpleReader: parseName (cont) in state %d", state);
+#endif
+        if (!parseStack->isEmpty()) {
+            ParseFunction function = parseStack->top().function;
+            if (function == &QXmlSimpleReaderPrivate::eat_ws) {
+                parseStack->pop();
+#if defined(QT_QXML_DEBUG)
+                qDebug("QXmlSimpleReader: eat_ws (cont)");
+#endif
+            }
+            if (!(this->*function)()) {
+                parseFailed(&QXmlSimpleReaderPrivate::parseName, state);
+                return false;
+            }
+        }
+    }
+
+    for (;;) {
+        switch (state) {
+            case Done:
+                return true;
+            case -1:
+                // Error
+                reportParseError(QLatin1String(XMLERR_LETTEREXPECTED));
+                return false;
+        }
+
+        if (atEnd()) {
+            unexpectedEof(&QXmlSimpleReaderPrivate::parseName, state);
+            return false;
+        }
+
+        // we can safely do the (int) cast thanks to the Q_ASSERTs earlier in this function
+        state = table[state][(int)fastDetermineNameChar(c)];
+
+        switch (state) {
+            case Name1:
+                if (parseName_useRef) {
+                    refClear();
+                    refAddC();
+                } else {
+                    nameClear();
+                    nameAddC();
+                }
+                next();
+                break;
+            case Name:
+                if (parseName_useRef) {
+                    refAddC();
+                } else {
+                    nameAddC();
+                }
+                next();
+                break;
+        }
+    }
+    return false;
+}
+
+/*
+  Parse a Nmtoken [7] and store the name in name.
+*/
+bool QXmlSimpleReaderPrivate::parseNmtoken()
+{
+    const signed char Init             = 0;
+    const signed char NameF            = 1;
+    const signed char Name             = 2;
+    const signed char Done             = 3;
+
+    const signed char InpNameCh        = 0; // NameChar without InpNameBe
+    const signed char InpUnknown       = 1;
+
+    static const signed char table[3][2] = {
+     /*  InpNameCh  InpUnknown */
+        { NameF,     -1    }, // Init
+        { Name,      Done  }, // NameF
+        { Name,      Done  }  // Name
+    };
+    signed char state;
+    signed char input;
+
+    if (parseStack==0 || parseStack->isEmpty()) {
+        state = Init;
+    } else {
+        state = parseStack->pop().state;
+#if defined(QT_QXML_DEBUG)
+        qDebug("QXmlSimpleReader: parseNmtoken (cont) in state %d", state);
+#endif
+        if (!parseStack->isEmpty()) {
+            ParseFunction function = parseStack->top().function;
+            if (function == &QXmlSimpleReaderPrivate::eat_ws) {
+                parseStack->pop();
+#if defined(QT_QXML_DEBUG)
+                qDebug("QXmlSimpleReader: eat_ws (cont)");
+#endif
+            }
+            if (!(this->*function)()) {
+                parseFailed(&QXmlSimpleReaderPrivate::parseNmtoken, state);
+                return false;
+            }
+        }
+    }
+
+    for (;;) {
+        switch (state) {
+            case Done:
+                return true;
+            case -1:
+                // Error
+                reportParseError(QLatin1String(XMLERR_LETTEREXPECTED));
+                return false;
+        }
+
+        if (atEnd()) {
+            unexpectedEof(&QXmlSimpleReaderPrivate::parseNmtoken, state);
+            return false;
+        }
+        if (determineNameChar(c) == NotName) {
+            input = InpUnknown;
+        } else {
+            input = InpNameCh;
+        }
+        state = table[state][input];
+
+        switch (state) {
+            case NameF:
+                nameClear();
+                nameAddC();
+                next();
+                break;
+            case Name:
+                nameAddC();
+                next();
+                break;
+        }
+    }
+    return false;
+}
+
+/*
+  Parse a Reference [67].
+
+  parseReference_charDataRead is set to true if the reference must not be
+  parsed. The character(s) which the reference mapped to are appended to
+  string. The head stands on the first character after the reference.
+
+  parseReference_charDataRead is set to false if the reference must be parsed.
+  The charachter(s) which the reference mapped to are inserted at the reference
+  position. The head stands on the first character of the replacement).
+*/
+bool QXmlSimpleReaderPrivate::parseReference()
+{
+    // temporary variables (only used in very local context, so they don't
+    // interfere with incremental parsing)
+    uint tmp;
+    bool ok;
+
+    const signed char Init             =  0;
+    const signed char SRef             =  1; // start of a reference
+    const signed char ChRef            =  2; // parse CharRef
+    const signed char ChDec            =  3; // parse CharRef decimal
+    const signed char ChHexS           =  4; // start CharRef hexadecimal
+    const signed char ChHex            =  5; // parse CharRef hexadecimal
+    const signed char Name             =  6; // parse name
+    const signed char DoneD            =  7; // done CharRef decimal
+    const signed char DoneH            =  8; // done CharRef hexadecimal
+    const signed char DoneN            =  9; // done EntityRef
+
+    const signed char InpAmp           = 0; // &
+    const signed char InpSemi          = 1; // ;
+    const signed char InpHash          = 2; // #
+    const signed char InpX             = 3; // x
+    const signed char InpNum           = 4; // 0-9
+    const signed char InpHex           = 5; // a-f A-F
+    const signed char InpUnknown       = 6;
+
+    static const signed char table[8][7] = {
+     /*  InpAmp  InpSemi  InpHash  InpX     InpNum  InpHex  InpUnknown */
+        { SRef,   -1,      -1,      -1,      -1,     -1,     -1    }, // Init
+        { -1,     -1,      ChRef,   Name,    Name,   Name,   Name  }, // SRef
+        { -1,     -1,      -1,      ChHexS,  ChDec,  -1,     -1    }, // ChRef
+        { -1,     DoneD,   -1,      -1,      ChDec,  -1,     -1    }, // ChDec
+        { -1,     -1,      -1,      -1,      ChHex,  ChHex,  -1    }, // ChHexS
+        { -1,     DoneH,   -1,      -1,      ChHex,  ChHex,  -1    }, // ChHex
+        { -1,     DoneN,   -1,      -1,      -1,     -1,     -1    }  // Name
+    };
+    signed char state;
+    signed char input;
+
+    if (parseStack==0 || parseStack->isEmpty()) {
+        parseReference_charDataRead = false;
+        state = Init;
+    } else {
+        state = parseStack->pop().state;
+#if defined(QT_QXML_DEBUG)
+        qDebug("QXmlSimpleReader: parseReference (cont) in state %d", state);
+#endif
+        if (!parseStack->isEmpty()) {
+            ParseFunction function = parseStack->top().function;
+            if (function == &QXmlSimpleReaderPrivate::eat_ws) {
+                parseStack->pop();
+#if defined(QT_QXML_DEBUG)
+                qDebug("QXmlSimpleReader: eat_ws (cont)");
+#endif
+            }
+            if (!(this->*function)()) {
+                parseFailed(&QXmlSimpleReaderPrivate::parseReference, state);
+                return false;
+            }
+        }
+    }
+
+    for (;;) {
+        switch (state) {
+            case DoneD:
+                return true;
+            case DoneH:
+                return true;
+            case DoneN:
+                return true;
+            case -1:
+                // Error
+                reportParseError(QLatin1String(XMLERR_ERRORPARSINGREFERENCE));
+                return false;
+        }
+
+        if (atEnd()) {
+            unexpectedEof(&QXmlSimpleReaderPrivate::parseReference, state);
+            return false;
+        }
+        if        (c.row()) {
+            input = InpUnknown;
+        } else if (c.cell() == '&') {
+            input = InpAmp;
+        } else if (c.cell() == ';') {
+            input = InpSemi;
+        } else if (c.cell() == '#') {
+            input = InpHash;
+        } else if (c.cell() == 'x') {
+            input = InpX;
+        } else if ('0' <= c.cell() && c.cell() <= '9') {
+            input = InpNum;
+        } else if ('a' <= c.cell() && c.cell() <= 'f') {
+            input = InpHex;
+        } else if ('A' <= c.cell() && c.cell() <= 'F') {
+            input = InpHex;
+        } else {
+            input = InpUnknown;
+        }
+        state = table[state][input];
+
+        switch (state) {
+            case SRef:
+                refClear();
+                next();
+                break;
+            case ChRef:
+                next();
+                break;
+            case ChDec:
+                refAddC();
+                next();
+                break;
+            case ChHexS:
+                next();
+                break;
+            case ChHex:
+                refAddC();
+                next();
+                break;
+            case Name:
+                // read the name into the ref
+                parseName_useRef = true;
+                if (!parseName()) {
+                    parseFailed(&QXmlSimpleReaderPrivate::parseReference, state);
+                    return false;
+                }
+                break;
+            case DoneD:
+                tmp = ref().toUInt(&ok, 10);
+                if (ok) {
+                    stringAddC(QChar(tmp));
+                } else {
+                    reportParseError(QLatin1String(XMLERR_ERRORPARSINGREFERENCE));
+                    return false;
+                }
+                parseReference_charDataRead = true;
+                next();
+                break;
+            case DoneH:
+                tmp = ref().toUInt(&ok, 16);
+                if (ok) {
+                    stringAddC(QChar(tmp));
+                } else {
+                    reportParseError(QLatin1String(XMLERR_ERRORPARSINGREFERENCE));
+                    return false;
+                }
+                parseReference_charDataRead = true;
+                next();
+                break;
+            case DoneN:
+                if (!processReference())
+                    return false;
+                next();
+                break;
+        }
+    }
+    return false;
+}
+
+/*
+  Helper function for parseReference()
+*/
+bool QXmlSimpleReaderPrivate::processReference()
+{
+    QString reference = ref();
+    if (reference == QLatin1String("amp")) {
+        if (parseReference_context == InEntityValue) {
+            // Bypassed
+            stringAddC(QLatin1Char('&')); stringAddC(QLatin1Char('a')); stringAddC(QLatin1Char('m')); stringAddC(QLatin1Char('p')); stringAddC(QLatin1Char(';'));
+        } else {
+            // Included or Included in literal
+            stringAddC(QLatin1Char('&'));
+        }
+        parseReference_charDataRead = true;
+    } else if (reference == QLatin1String("lt")) {
+        if (parseReference_context == InEntityValue) {
+            // Bypassed
+            stringAddC(QLatin1Char('&')); stringAddC(QLatin1Char('l')); stringAddC(QLatin1Char('t')); stringAddC(QLatin1Char(';'));
+        } else {
+            // Included or Included in literal
+            stringAddC(QLatin1Char('<'));
+        }
+        parseReference_charDataRead = true;
+    } else if (reference == QLatin1String("gt")) {
+        if (parseReference_context == InEntityValue) {
+            // Bypassed
+            stringAddC(QLatin1Char('&')); stringAddC(QLatin1Char('g')); stringAddC(QLatin1Char('t')); stringAddC(QLatin1Char(';'));
+        } else {
+            // Included or Included in literal
+            stringAddC(QLatin1Char('>'));
+        }
+        parseReference_charDataRead = true;
+    } else if (reference == QLatin1String("apos")) {
+        if (parseReference_context == InEntityValue) {
+            // Bypassed
+            stringAddC(QLatin1Char('&')); stringAddC(QLatin1Char('a')); stringAddC(QLatin1Char('p')); stringAddC(QLatin1Char('o')); stringAddC(QLatin1Char('s')); stringAddC(QLatin1Char(';'));
+        } else {
+            // Included or Included in literal
+            stringAddC(QLatin1Char('\''));
+        }
+        parseReference_charDataRead = true;
+    } else if (reference == QLatin1String("quot")) {
+        if (parseReference_context == InEntityValue) {
+            // Bypassed
+            stringAddC(QLatin1Char('&')); stringAddC(QLatin1Char('q')); stringAddC(QLatin1Char('u')); stringAddC(QLatin1Char('o')); stringAddC(QLatin1Char('t')); stringAddC(QLatin1Char(';'));
+        } else {
+            // Included or Included in literal
+            stringAddC(QLatin1Char('"'));
+        }
+        parseReference_charDataRead = true;
+    } else {
+        QMap<QString,QString>::Iterator it;
+        it = entities.find(reference);
+        if (it != entities.end()) {
+            // "Internal General"
+            switch (parseReference_context) {
+                case InContent:
+                    // Included
+                    if (!insertXmlRef(*it, reference, false))
+                        return false;
+                    parseReference_charDataRead = false;
+                    break;
+                case InAttributeValue:
+                    // Included in literal
+                    if (!insertXmlRef(*it, reference, true))
+                        return false;
+                    parseReference_charDataRead = false;
+                    break;
+                case InEntityValue:
+                    {
+                        // Bypassed
+                        stringAddC(QLatin1Char('&'));
+                        for (int i=0; i<(int)reference.length(); i++) {
+                            stringAddC(reference[i]);
+                        }
+                        stringAddC(QLatin1Char(';'));
+                        parseReference_charDataRead = true;
+                    }
+                    break;
+                case InDTD:
+                    // Forbidden
+                    parseReference_charDataRead = false;
+                    reportParseError(QLatin1String(XMLERR_INTERNALGENERALENTITYINDTD));
+                    return false;
+            }
+        } else {
+            QMap<QString,QXmlSimpleReaderPrivate::ExternEntity>::Iterator itExtern;
+            itExtern = externEntities.find(reference);
+            if (itExtern == externEntities.end()) {
+                // entity not declared
+                // ### check this case for conformance
+                if (parseReference_context == InEntityValue) {
+                    // Bypassed
+                    stringAddC(QLatin1Char('&'));
+                    for (int i=0; i<(int)reference.length(); i++) {
+                        stringAddC(reference[i]);
+                    }
+                    stringAddC(QLatin1Char(';'));
+                    parseReference_charDataRead = true;
+                } else {
+                    // if we have some char data read, report it now
+                    if (parseReference_context == InContent) {
+                        if (contentCharDataRead) {
+                            if (reportWhitespaceCharData || !string().simplified().isEmpty()) {
+                                if (contentHnd != 0 && !contentHnd->characters(string())) {
+                                    reportParseError(contentHnd->errorString());
+                                    return false;
+                                }
+                            }
+                            stringClear();
+                            contentCharDataRead = false;
+                        }
+                    }
+
+                    if (contentHnd) {
+                        qt_xml_skipped_entity_in_content = parseReference_context == InContent;
+                        if (!contentHnd->skippedEntity(reference)) {
+                            qt_xml_skipped_entity_in_content = false;
+                            reportParseError(contentHnd->errorString());
+                            return false; // error
+                        }
+                        qt_xml_skipped_entity_in_content = false;
+                    }
+                }
+            } else if ((*itExtern).notation.isNull()) {
+                // "External Parsed General"
+                switch (parseReference_context) {
+                    case InContent:
+                        {
+                            // Included if validating
+                            bool skipIt = true;
+                            if (entityRes) {
+                                QXmlInputSource *ret = 0;
+                                if (!entityRes->resolveEntity((*itExtern).publicId, (*itExtern).systemId, ret)) {
+                                    delete ret;
+                                    reportParseError(entityRes->errorString());
+                                    return false;
+                                }
+                                if (ret) {
+                                    QString xmlRefString = ret->data();
+                                    delete ret;
+                                    if (!stripTextDecl(xmlRefString)) {
+                                        reportParseError(QLatin1String(XMLERR_ERRORINTEXTDECL));
+                                        return false;
+                                    }
+                                    if (!insertXmlRef(xmlRefString, reference, false))
+                                        return false;
+                                    skipIt = false;
+                                }
+                            }
+                            if (skipIt && contentHnd) {
+                                qt_xml_skipped_entity_in_content = true;
+                                if (!contentHnd->skippedEntity(reference)) {
+                                    qt_xml_skipped_entity_in_content = false;
+                                    reportParseError(contentHnd->errorString());
+                                    return false; // error
+                                }
+                                qt_xml_skipped_entity_in_content = false;
+                            }
+                            parseReference_charDataRead = false;
+                        } break;
+                    case InAttributeValue:
+                        // Forbidden
+                        parseReference_charDataRead = false;
+                        reportParseError(QLatin1String(XMLERR_EXTERNALGENERALENTITYINAV));
+                        return false;
+                    case InEntityValue:
+                        {
+                            // Bypassed
+                            stringAddC(QLatin1Char('&'));
+                            for (int i=0; i<(int)reference.length(); i++) {
+                                stringAddC(reference[i]);
+                            }
+                            stringAddC(QLatin1Char(';'));
+                            parseReference_charDataRead = true;
+                        }
+                        break;
+                    case InDTD:
+                        // Forbidden
+                        parseReference_charDataRead = false;
+                        reportParseError(QLatin1String(XMLERR_EXTERNALGENERALENTITYINDTD));
+                        return false;
+                }
+            } else {
+                // "Unparsed"
+                // ### notify for "Occurs as Attribute Value" missing (but this is no refence, anyway)
+                // Forbidden
+                parseReference_charDataRead = false;
+                reportParseError(QLatin1String(XMLERR_UNPARSEDENTITYREFERENCE));
+                return false; // error
+            }
+        }
+    }
+    return true; // no error
+}
+
+
+/*
+  Parses over a simple string.
+
+  After the string was successfully parsed, the head is on the first
+  character after the string.
+*/
+bool QXmlSimpleReaderPrivate::parseString()
+{
+    const signed char InpCharExpected  = 0; // the character that was expected
+    const signed char InpUnknown       = 1;
+
+    signed char state; // state in this function is the position in the string s
+    signed char input;
+
+    if (parseStack==0 || parseStack->isEmpty()) {
+        Done = parseString_s.length();
+        state = 0;
+    } else {
+        state = parseStack->pop().state;
+#if defined(QT_QXML_DEBUG)
+        qDebug("QXmlSimpleReader: parseString (cont) in state %d", state);
+#endif
+        if (!parseStack->isEmpty()) {
+            ParseFunction function = parseStack->top().function;
+            if (function == &QXmlSimpleReaderPrivate::eat_ws) {
+                parseStack->pop();
+#if defined(QT_QXML_DEBUG)
+                qDebug("QXmlSimpleReader: eat_ws (cont)");
+#endif
+            }
+            if (!(this->*function)()) {
+                parseFailed(&QXmlSimpleReaderPrivate::parseString, state);
+                return false;
+            }
+        }
+    }
+
+    for (;;) {
+        if (state == Done) {
+            return true;
+        }
+
+        if (atEnd()) {
+            unexpectedEof(&QXmlSimpleReaderPrivate::parseString, state);
+            return false;
+        }
+        if (c == parseString_s[(int)state]) {
+            input = InpCharExpected;
+        } else {
+            input = InpUnknown;
+        }
+        if (input == InpCharExpected) {
+            state++;
+        } else {
+            // Error
+            reportParseError(QLatin1String(XMLERR_UNEXPECTEDCHARACTER));
+            return false;
+        }
+
+        next();
+    }
+    return false;
+}
+
+/*
+  This private function inserts and reports an entity substitution. The
+  substituted string is \a data and the name of the entity reference is \a
+  name. If \a inLiteral is true, the entity is IncludedInLiteral (i.e., " and '
+  must be quoted. Otherwise they are not quoted.
+
+  This function returns false on error.
+*/
+bool QXmlSimpleReaderPrivate::insertXmlRef(const QString &data, const QString &name, bool inLiteral)
+{
+    if (inLiteral) {
+        QString tmp = data;
+        xmlRefStack.push(XmlRef(name, tmp.replace(QLatin1Char('\"'),
+                            QLatin1String("&quot;")).replace(QLatin1Char('\''), QLatin1String("&apos;"))));
+    } else {
+        xmlRefStack.push(XmlRef(name, data));
+    }
+    int n = qMax(parameterEntities.count(), entities.count());
+    if (xmlRefStack.count() > n+1) {
+        // recursive entities
+        reportParseError(QLatin1String(XMLERR_RECURSIVEENTITIES));
+        return false;
+    }
+    if (reportEntities && lexicalHnd) {
+        if (!lexicalHnd->startEntity(name)) {
+            reportParseError(lexicalHnd->errorString());
+            return false;
+        }
+    }
+    return true;
+}
+
+/*
+  This private function moves the cursor to the next character.
+*/
+void QXmlSimpleReaderPrivate::next()
+{
+    int count = xmlRefStack.size();
+    while (count != 0) {
+        if (xmlRefStack.top().isEmpty()) {
+            xmlRefStack.pop_back();
+            count--;
+        } else {
+            c = xmlRefStack.top().next();
+            return;
+        }
+    }
+
+    // the following could be written nicer, but since it is a time-critical
+    // function, rather optimize for speed
+    ushort uc = c.unicode();
+    c = inputSource->next();
+    // If we are not incremental parsing, we just skip over EndOfData chars to give the
+    // parser an uninterrupted stream of document chars.
+    if (c == QXmlInputSource::EndOfData && parseStack == 0)
+        c = inputSource->next();
+    if (uc == '\n') {
+        lineNr++;
+        columnNr = -1;
+    } else if (uc == '\r') {
+        if (c != QLatin1Char('\n')) {
+            lineNr++;
+            columnNr = -1;
+        }
+    }
+    ++columnNr;
+}
+
+/*
+  This private function moves the cursor to the next non-whitespace character.
+  This function does not move the cursor if the actual cursor position is a
+  non-whitespace charcter.
+
+  Returns false when you use incremental parsing and this function reaches EOF
+  with reading only whitespace characters. In this case it also poplulates the
+  parseStack with useful information. In all other cases, this function returns
+  true.
+*/
+bool QXmlSimpleReaderPrivate::eat_ws()
+{
+    while (!atEnd()) {
+        if (!is_S(c)) {
+            return true;
+        }
+        next();
+    }
+    if (parseStack != 0) {
+        unexpectedEof(&QXmlSimpleReaderPrivate::eat_ws, 0);
+        return false;
+    }
+    return true;
+}
+
+bool QXmlSimpleReaderPrivate::next_eat_ws()
+{
+    next();
+    return eat_ws();
+}
+
+
+/*
+  This private function initializes the reader. \a i is the input source to
+  read the data from.
+*/
+void QXmlSimpleReaderPrivate::init(const QXmlInputSource *i)
+{
+    lineNr = 0;
+    columnNr = -1;
+    inputSource = const_cast<QXmlInputSource *>(i);
+    initData();
+
+    externParameterEntities.clear();
+    parameterEntities.clear();
+    externEntities.clear();
+    entities.clear();
+
+    tags.clear();
+
+    doctype.clear();
+    xmlVersion.clear();
+    encoding.clear();
+    standalone = QXmlSimpleReaderPrivate::Unknown;
+    error.clear();
+}
+
+/*
+  This private function initializes the XML data related variables. Especially,
+  it reads the data from the input source.
+*/
+void QXmlSimpleReaderPrivate::initData()
+{
+    c = QXmlInputSource::EndOfData;
+    xmlRefStack.clear();
+    next();
+}
+
+/*
+  Returns true if a entity with the name \a e exists,
+  otherwise returns false.
+*/
+bool QXmlSimpleReaderPrivate::entityExist(const QString& e) const
+{
+    if ( parameterEntities.find(e) == parameterEntities.end() &&
+          externParameterEntities.find(e) == externParameterEntities.end() &&
+          externEntities.find(e) == externEntities.end() &&
+          entities.find(e) == entities.end()) {
+        return false;
+    } else {
+        return true;
+    }
+}
+
+void QXmlSimpleReaderPrivate::reportParseError(const QString& error)
+{
+    this->error = error;
+    if (errorHnd) {
+        if (this->error.isNull()) {
+            const QXmlParseException ex(QLatin1String(XMLERR_OK), columnNr+1, lineNr+1,
+                                        thisPublicId, thisSystemId);
+            errorHnd->fatalError(ex);
+        } else {
+            const QXmlParseException ex(this->error, columnNr+1, lineNr+1,
+                                        thisPublicId, thisSystemId);
+            errorHnd->fatalError(ex);
+        }
+    }
+}
+
+/*
+  This private function is called when a parsing function encounters an
+  unexpected EOF. It decides what to do (depending on incremental parsing or
+  not). \a where is a pointer to the function where the error occurred and \a
+  state is the parsing state in this function.
+*/
+void QXmlSimpleReaderPrivate::unexpectedEof(ParseFunction where, int state)
+{
+    if (parseStack == 0) {
+        reportParseError(QLatin1String(XMLERR_UNEXPECTEDEOF));
+    } else {
+        if (c == QXmlInputSource::EndOfDocument) {
+            reportParseError(QLatin1String(XMLERR_UNEXPECTEDEOF));
+        } else {
+            pushParseState(where, state);
+        }
+    }
+}
+
+/*
+  This private function is called when a parse...() function returned false. It
+  determines if there was an error or if incremental parsing simply went out of
+  data and does the right thing for the case. \a where is a pointer to the
+  function where the error occurred and \a state is the parsing state in this
+  function.
+*/
+void QXmlSimpleReaderPrivate::parseFailed(ParseFunction where, int state)
+{
+    if (parseStack!=0 && error.isNull()) {
+        pushParseState(where, state);
+    }
+}
+
+/*
+  This private function pushes the function pointer \a function and state \a
+  state to the parse stack. This is used when you are doing an incremental
+  parsing and reach the end of file too early.
+
+  Only call this function when d->parseStack!=0.
+*/
+void QXmlSimpleReaderPrivate::pushParseState(ParseFunction function, int state)
+{
+    QXmlSimpleReaderPrivate::ParseState ps;
+    ps.function = function;
+    ps.state = state;
+    parseStack->push(ps);
+}
+
+inline static void updateValue(QString &value, const QChar *array, int &arrayPos, int &valueLen)
+{
+    value.resize(valueLen + arrayPos);
+    memcpy(value.data() + valueLen, array, arrayPos * sizeof(QChar));
+    valueLen += arrayPos;
+    arrayPos = 0;
+}
+
+// use buffers instead of QString::operator+= when single characters are read
+const QString& QXmlSimpleReaderPrivate::string()
+{
+    updateValue(stringValue, stringArray, stringArrayPos, stringValueLen);
+    return stringValue;
+}
+const QString& QXmlSimpleReaderPrivate::name()
+{
+    updateValue(nameValue, nameArray, nameArrayPos, nameValueLen);
+    return nameValue;
+}
+const QString& QXmlSimpleReaderPrivate::ref()
+{
+    updateValue(refValue, refArray, refArrayPos, refValueLen);
+    return refValue;
+}
+
+void QXmlSimpleReaderPrivate::stringAddC(QChar ch)
+{
+    if (stringArrayPos == 256)
+        updateValue(stringValue, stringArray, stringArrayPos, stringValueLen);
+    stringArray[stringArrayPos++] = ch;
+}
+void QXmlSimpleReaderPrivate::nameAddC(QChar ch)
+{
+    if (nameArrayPos == 256)
+        updateValue(nameValue, nameArray, nameArrayPos, nameValueLen);
+    nameArray[nameArrayPos++] = ch;
+}
+void QXmlSimpleReaderPrivate::refAddC(QChar ch)
+{
+    if (refArrayPos == 256)
+        updateValue(refValue, refArray, refArrayPos, refValueLen);
+    refArray[refArrayPos++] = ch;
+}
+QT_END_NAMESPACE