src/corelib/xml/qxmlstream.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/corelib/xml/qxmlstream.cpp	Mon Jan 11 14:00:40 2010 +0000
@@ -0,0 +1,3944 @@
+/****************************************************************************
+**
+** 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 QtCore 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 "QtCore/qxmlstream.h"
+
+#if defined(QT_BUILD_XML_LIB) && defined(Q_OS_MAC64)
+// No need to define this in the 64-bit Mac libraries.
+// Since Qt 4.4 and previous weren't supported in 64-bit, there are
+// no QXmlStream* symbols to keep compatibility with
+# define QT_NO_XMLSTREAM
+#endif
+
+#ifndef QT_NO_XMLSTREAM
+
+#include "qxmlutils_p.h"
+#include <qdebug.h>
+#include <qfile.h>
+#include <stdio.h>
+#include <qtextcodec.h>
+#include <qstack.h>
+#include <qbuffer.h>
+#ifndef QT_BOOTSTRAPPED
+#include <qcoreapplication.h>
+#else
+// This specialization of Q_DECLARE_TR_FUNCTIONS is not in qcoreapplication.h,
+// because that header depends on QObject being available, which is not the
+// case for most bootstrapped applications.
+#define Q_DECLARE_TR_FUNCTIONS(context) \
+public: \
+    static inline QString tr(const char *sourceText, const char *comment = 0) \
+        { Q_UNUSED(comment); return QString::fromLatin1(sourceText); } \
+    static inline QString trUtf8(const char *sourceText, const char *comment = 0) \
+        { Q_UNUSED(comment); return QString::fromLatin1(sourceText); } \
+    static inline QString tr(const char *sourceText, const char*, int) \
+        { return QString::fromLatin1(sourceText); } \
+    static inline QString trUtf8(const char *sourceText, const char*, int) \
+        { return QString::fromLatin1(sourceText); } \
+private:
+#endif
+QT_BEGIN_NAMESPACE
+
+#include "qxmlstream_p.h"
+
+/*!
+    \enum QXmlStreamReader::TokenType
+
+    This enum specifies the type of token the reader just read.
+
+    \value NoToken The reader has not yet read anything.
+
+    \value Invalid An error has occurred, reported in error() and
+    errorString().
+
+    \value StartDocument The reader reports the XML version number in
+    documentVersion(), and the encoding as specified in the XML
+    document in documentEncoding().  If the document is declared
+    standalone, isStandaloneDocument() returns true; otherwise it
+    returns false.
+
+    \value EndDocument The reader reports the end of the document.
+
+    \value StartElement The reader reports the start of an element
+    with namespaceUri() and name(). Empty elements are also reported
+    as StartElement, followed directly by EndElement. The convenience
+    function readElementText() can be called to concatenate all
+    content until the corresponding EndElement. Attributes are
+    reported in attributes(), namespace declarations in
+    namespaceDeclarations().
+
+    \value EndElement The reader reports the end of an element with
+    namespaceUri() and name().
+
+    \value Characters The reader reports characters in text(). If the
+    characters are all white-space, isWhitespace() returns true. If
+    the characters stem from a CDATA section, isCDATA() returns true.
+
+    \value Comment The reader reports a comment in text().
+
+    \value DTD The reader reports a DTD in text(), notation
+    declarations in notationDeclarations(), and entity declarations in
+    entityDeclarations(). Details of the DTD declaration are reported
+    in in dtdName(), dtdPublicId(), and dtdSystemId().
+
+    \value EntityReference The reader reports an entity reference that
+    could not be resolved.  The name of the reference is reported in
+    name(), the replacement text in text().
+
+    \value ProcessingInstruction The reader reports a processing
+    instruction in processingInstructionTarget() and
+    processingInstructionData().
+*/
+
+/*!
+    \enum QXmlStreamReader::ReadElementTextBehaviour
+
+    This enum specifies the different behaviours of readElementText().
+
+    \value ErrorOnUnexpectedElement Raise an UnexpectedElementError and return
+    what was read so far when a child element is encountered.
+
+    \value IncludeChildElements Recursively include the text from child elements.
+
+    \value SkipChildElements Skip child elements.
+
+    \since 4.6
+*/
+
+/*!
+    \enum QXmlStreamReader::Error
+
+    This enum specifies different error cases
+
+    \value NoError No error has occurred.
+
+    \value CustomError A custom error has been raised with
+    raiseError()
+
+    \value NotWellFormedError The parser internally raised an error
+    due to the read XML not being well-formed.
+
+    \value PrematureEndOfDocumentError The input stream ended before a
+    well-formed XML document was parsed. Recovery from this error is
+    possible if more XML arrives in the stream, either by calling
+    addData() or by waiting for it to arrive on the device().
+
+    \value UnexpectedElementError The parser encountered an element
+    that was different to those it expected.
+
+*/
+
+/*!
+  \class QXmlStreamEntityResolver
+  \reentrant
+  \since 4.4
+
+  \brief The QXmlStreamEntityResolver class provides an entity
+  resolver for a QXmlStreamReader.
+
+  \ingroup xml-tools
+ */
+
+/*!
+  Destroys the entity resolver.
+ */
+QXmlStreamEntityResolver::~QXmlStreamEntityResolver()
+{
+}
+
+/*! \internal
+
+This function is a stub for later functionality.
+*/
+QString QXmlStreamEntityResolver::resolveEntity(const QString& /*publicId*/, const QString& /*systemId*/)
+{
+    return QString();
+}
+
+
+/*!
+  Resolves the undeclared entity \a name and returns its replacement
+  text. If the entity is also unknown to the entity resolver, it
+  returns an empty string.
+
+  The default implementation always returns an empty string.
+*/
+
+QString QXmlStreamEntityResolver::resolveUndeclaredEntity(const QString &/*name*/)
+{
+    return QString();
+}
+
+#ifndef QT_NO_XMLSTREAMREADER
+
+QString QXmlStreamReaderPrivate::resolveUndeclaredEntity(const QString &name)
+{
+    if (entityResolver)
+        return entityResolver->resolveUndeclaredEntity(name);
+    return QString();
+}
+
+
+
+/*!
+   \since 4.4
+
+   Makes \a resolver the new entityResolver().
+
+   The stream reader does \e not take ownership of the resolver. It's
+   the callers responsibility to ensure that the resolver is valid
+   during the entire life-time of the stream reader object, or until
+   another resolver or 0 is set.
+
+   \sa entityResolver()
+ */
+void QXmlStreamReader::setEntityResolver(QXmlStreamEntityResolver *resolver)
+{
+    Q_D(QXmlStreamReader);
+    d->entityResolver = resolver;
+}
+
+/*!
+  \since 4.4
+
+  Returns the entity resolver, or 0 if there is no entity resolver.
+
+  \sa setEntityResolver()
+ */
+QXmlStreamEntityResolver *QXmlStreamReader::entityResolver() const
+{
+    Q_D(const QXmlStreamReader);
+    return d->entityResolver;
+}
+
+
+
+/*!
+  \class QXmlStreamReader
+  \reentrant
+  \since 4.3
+
+  \brief The QXmlStreamReader class provides a fast parser for reading
+  well-formed XML via a simple streaming API.
+
+
+  \ingroup xml-tools
+
+  QXmlStreamReader is a faster and more convenient replacement for
+  Qt's own SAX parser (see QXmlSimpleReader). In some cases it might
+  also be a faster and more convenient alternative for use in
+  applications that would otherwise use a DOM tree (see QDomDocument).
+  QXmlStreamReader reads data either from a QIODevice (see
+  setDevice()), or from a raw QByteArray (see addData()).
+
+  Qt provides QXmlStreamWriter for writing XML.
+
+  The basic concept of a stream reader is to report an XML document as
+  a stream of tokens, similar to SAX. The main difference between
+  QXmlStreamReader and SAX is \e how these XML tokens are reported.
+  With SAX, the application must provide handlers (callback functions)
+  that receive so-called XML \e events from the parser at the parser's
+  convenience.  With QXmlStreamReader, the application code itself
+  drives the loop and pulls \e tokens from the reader, one after
+  another, as it needs them. This is done by calling readNext(), where
+  the reader reads from the input stream until it completes the next
+  token, at which point it returns the tokenType(). A set of
+  convenient functions including isStartElement() and text() can then
+  be used to examine the token to obtain information about what has
+  been read. The big advantage of this \e pulling approach is the
+  possibility to build recursive descent parsers with it, meaning you
+  can split your XML parsing code easily into different methods or
+  classes. This makes it easy to keep track of the application's own
+  state when parsing XML.
+
+  A typical loop with QXmlStreamReader looks like this:
+
+  \snippet doc/src/snippets/code/src_corelib_xml_qxmlstream.cpp 0
+
+
+  QXmlStreamReader is a well-formed XML 1.0 parser that does \e not
+  include external parsed entities. As long as no error occurs, the
+  application code can thus be assured that the data provided by the
+  stream reader satisfies the W3C's criteria for well-formed XML. For
+  example, you can be certain that all tags are indeed nested and
+  closed properly, that references to internal entities have been
+  replaced with the correct replacement text, and that attributes have
+  been normalized or added according to the internal subset of the
+  DTD.
+
+  If an error occurs while parsing, atEnd() and hasError() return
+  true, and error() returns the error that occurred. The functions
+  errorString(), lineNumber(), columnNumber(), and characterOffset()
+  are for constructing an appropriate error or warning message. To
+  simplify application code, QXmlStreamReader contains a raiseError()
+  mechanism that lets you raise custom errors that trigger the same
+  error handling described.
+
+  The \l{QXmlStream Bookmarks Example} illustrates how to use the
+  recursive descent technique to read an XML bookmark file (XBEL) with
+  a stream reader.
+
+  \section1 Namespaces
+
+  QXmlStream understands and resolves XML namespaces. E.g. in case of
+  a StartElement, namespaceUri() returns the namespace the element is
+  in, and name() returns the element's \e local name. The combination
+  of namespaceUri and name uniquely identifies an element. If a
+  namespace prefix was not declared in the XML entities parsed by the
+  reader, the namespaceUri is empty.
+
+  If you parse XML data that does not utilize namespaces according to
+  the XML specification or doesn't use namespaces at all, you can use
+  the element's qualifiedName() instead. A qualified name is the
+  element's prefix() followed by colon followed by the element's local
+  name() - exactly like the element appears in the raw XML data. Since
+  the mapping namespaceUri to prefix is neither unique nor universal,
+  qualifiedName() should be avoided for namespace-compliant XML data.
+
+  In order to parse standalone documents that do use undeclared
+  namespace prefixes, you can turn off namespace processing completely
+  with the \l namespaceProcessing property.
+
+  \section1 Incremental parsing
+
+  QXmlStreamReader is an incremental parser. It can handle the case
+  where the document can't be parsed all at once because it arrives in
+  chunks (e.g. from multiple files, or over a network connection).
+  When the reader runs out of data before the complete document has
+  been parsed, it reports a PrematureEndOfDocumentError. When more
+  data arrives, either because of a call to addData() or because more
+  data is available through the network device(), the reader recovers
+  from the PrematureEndOfDocumentError error and continues parsing the
+  new data with the next call to readNext().
+
+  For example, if your application reads data from the network using a
+  \l{QNetworkAccessManager} {network access manager}, you would issue
+  a \l{QNetworkRequest} {network request} to the manager and receive a
+  \l{QNetworkReply} {network reply} in return. Since a QNetworkReply
+  is a QIODevice, you connect its \l{QNetworkReply::readyRead()}
+  {readyRead()} signal to a custom slot, e.g. \c{slotReadyRead()} in
+  the code snippet shown in the discussion for QNetworkAccessManager.
+  In this slot, you read all available data with
+  \l{QNetworkReply::readAll()} {readAll()} and pass it to the XML
+  stream reader using addData(). Then you call your custom parsing
+  function that reads the XML events from the reader.
+
+  \section1 Performance and memory consumption
+
+  QXmlStreamReader is memory-conservative by design, since it doesn't
+  store the entire XML document tree in memory, but only the current
+  token at the time it is reported. In addition, QXmlStreamReader
+  avoids the many small string allocations that it normally takes to
+  map an XML document to a convenient and Qt-ish API. It does this by
+  reporting all string data as QStringRef rather than real QString
+  objects. QStringRef is a thin wrapper around QString substrings that
+  provides a subset of the QString API without the memory allocation
+  and reference-counting overhead. Calling
+  \l{QStringRef::toString()}{toString()} on any of those objects
+  returns an equivalent real QString object.
+
+*/
+
+
+/*!
+  Constructs a stream reader.
+
+  \sa setDevice(), addData()
+ */
+QXmlStreamReader::QXmlStreamReader()
+    : d_ptr(new QXmlStreamReaderPrivate(this))
+{
+}
+
+/*!  Creates a new stream reader that reads from \a device.
+
+\sa setDevice(), clear()
+ */
+QXmlStreamReader::QXmlStreamReader(QIODevice *device)
+    : d_ptr(new QXmlStreamReaderPrivate(this))
+{
+    setDevice(device);
+}
+
+/*!
+  Creates a new stream reader that reads from \a data.
+
+  \sa addData(), clear(), setDevice()
+ */
+QXmlStreamReader::QXmlStreamReader(const QByteArray &data)
+    : d_ptr(new QXmlStreamReaderPrivate(this))
+{
+    Q_D(QXmlStreamReader);
+    d->dataBuffer = data;
+}
+
+/*!
+  Creates a new stream reader that reads from \a data.
+
+  \sa addData(), clear(), setDevice()
+ */
+QXmlStreamReader::QXmlStreamReader(const QString &data)
+    : d_ptr(new QXmlStreamReaderPrivate(this))
+{
+    Q_D(QXmlStreamReader);
+#ifdef QT_NO_TEXTCODEC
+    d->dataBuffer = data.toLatin1();
+#else
+    d->dataBuffer = d->codec->fromUnicode(data);
+    d->decoder = d->codec->makeDecoder();
+#endif
+    d->lockEncoding = true;
+
+}
+
+/*!
+  Creates a new stream reader that reads from \a data.
+
+  \sa addData(), clear(), setDevice()
+ */
+QXmlStreamReader::QXmlStreamReader(const char *data)
+    : d_ptr(new QXmlStreamReaderPrivate(this))
+{
+    Q_D(QXmlStreamReader);
+    d->dataBuffer = QByteArray(data);
+}
+
+/*!
+  Destructs the reader.
+ */
+QXmlStreamReader::~QXmlStreamReader()
+{
+    Q_D(QXmlStreamReader);
+    if (d->deleteDevice)
+        delete d->device;
+}
+
+/*! \fn bool QXmlStreamReader::hasError() const
+    Returns \c true if an error has occurred, otherwise \c false.
+
+    \sa errorString(), error()
+ */
+
+/*!
+    Sets the current device to \a device. Setting the device resets
+    the stream to its initial state.
+
+    \sa device(), clear()
+*/
+void QXmlStreamReader::setDevice(QIODevice *device)
+{
+    Q_D(QXmlStreamReader);
+    if (d->deleteDevice) {
+        delete d->device;
+        d->deleteDevice = false;
+    }
+    d->device = device;
+    d->init();
+
+}
+
+/*!
+    Returns the current device associated with the QXmlStreamReader,
+    or 0 if no device has been assigned.
+
+    \sa setDevice()
+*/
+QIODevice *QXmlStreamReader::device() const
+{
+    Q_D(const QXmlStreamReader);
+    return d->device;
+}
+
+
+/*!
+  Adds more \a data for the reader to read. This function does
+  nothing if the reader has a device().
+
+  \sa readNext(), clear()
+ */
+void QXmlStreamReader::addData(const QByteArray &data)
+{
+    Q_D(QXmlStreamReader);
+    if (d->device) {
+        qWarning("QXmlStreamReader: addData() with device()");
+        return;
+    }
+    d->dataBuffer += data;
+}
+
+/*!
+  Adds more \a data for the reader to read. This function does
+  nothing if the reader has a device().
+
+  \sa readNext(), clear()
+ */
+void QXmlStreamReader::addData(const QString &data)
+{
+    Q_D(QXmlStreamReader);
+    d->lockEncoding = true;
+#ifdef QT_NO_TEXTCODEC
+    addData(data.toLatin1());
+#else
+    addData(d->codec->fromUnicode(data));
+#endif
+}
+
+/*!
+  Adds more \a data for the reader to read. This function does
+  nothing if the reader has a device().
+
+  \sa readNext(), clear()
+ */
+void QXmlStreamReader::addData(const char *data)
+{
+    addData(QByteArray(data));
+}
+
+/*!
+    Removes any device() or data from the reader and resets its
+    internal state to the initial state.
+
+    \sa addData()
+ */
+void QXmlStreamReader::clear()
+{
+    Q_D(QXmlStreamReader);
+    d->init();
+    if (d->device) {
+        if (d->deleteDevice)
+            delete d->device;
+        d->device = 0;
+    }
+}
+
+/*!
+    Returns true if the reader has read until the end of the XML
+    document, or if an error() has occurred and reading has been
+    aborted. Otherwise, it returns false.
+
+    When atEnd() and hasError() return true and error() returns
+    PrematureEndOfDocumentError, it means the XML has been well-formed
+    so far, but a complete XML document has not been parsed. The next
+    chunk of XML can be added with addData(), if the XML is being read
+    from a QByteArray, or by waiting for more data to arrive if the
+    XML is being read from a QIODevice. Either way, atEnd() will
+    return false once more adata is available.
+
+    \sa hasError(), error(), device(), QIODevice::atEnd()
+ */
+bool QXmlStreamReader::atEnd() const
+{
+    Q_D(const QXmlStreamReader);
+    if (d->atEnd
+        && ((d->type == QXmlStreamReader::Invalid && d->error == PrematureEndOfDocumentError)
+            || (d->type == QXmlStreamReader::EndDocument))) {
+        if (d->device)
+            return d->device->atEnd();
+        else
+            return !d->dataBuffer.size();
+    }
+    return (d->atEnd || d->type == QXmlStreamReader::Invalid);
+}
+
+
+/*!
+  Reads the next token and returns its type.
+
+  With one exception, once an error() is reported by readNext(),
+  further reading of the XML stream is not possible. Then atEnd()
+  returns true, hasError() returns true, and this function returns
+  QXmlStreamReader::Invalid.
+
+  The exception is when error() returns PrematureEndOfDocumentError.
+  This error is reported when the end of an otherwise well-formed
+  chunk of XML is reached, but the chunk doesn't represent a complete
+  XML document.  In that case, parsing \e can be resumed by calling
+  addData() to add the next chunk of XML, when the stream is being
+  read from a QByteArray, or by waiting for more data to arrive when
+  the stream is being read from a device().
+
+  \sa tokenType(), tokenString()
+ */
+QXmlStreamReader::TokenType QXmlStreamReader::readNext()
+{
+    Q_D(QXmlStreamReader);
+    if (d->type != Invalid) {
+        if (!d->hasCheckedStartDocument)
+            if (!d->checkStartDocument())
+                return d->type; // synthetic StartDocument or error
+        d->parse();
+        if (d->atEnd && d->type != EndDocument && d->type != Invalid)
+            d->raiseError(PrematureEndOfDocumentError);
+        else if (!d->atEnd && d->type == EndDocument)
+            d->raiseWellFormedError(QXmlStream::tr("Extra content at end of document."));
+    } else if (d->error == PrematureEndOfDocumentError) {
+        // resume error
+        d->type = NoToken;
+        d->atEnd = false;
+        d->token = -1;
+        return readNext();
+    }
+    return d->type;
+}
+
+
+/*!
+  Returns the type of the current token.
+
+  The current token can also be queried with the convenience functions
+  isStartDocument(), isEndDocument(), isStartElement(),
+  isEndElement(), isCharacters(), isComment(), isDTD(),
+  isEntityReference(), and isProcessingInstruction().
+
+  \sa tokenString()
+ */
+QXmlStreamReader::TokenType QXmlStreamReader::tokenType() const
+{
+    Q_D(const QXmlStreamReader);
+    return d->type;
+}
+
+/*!
+  Reads until the next start element within the current element. Returns true
+  when a start element was reached. When the end element was reached, or when
+  an error occurred, false is returned.
+
+  The current element is the element matching the most recently parsed start
+  element of which a matching end element has not yet been reached. When the
+  parser has reached the end element, the current element becomes the parent
+  element.
+
+  This is a convenience function for when you're only concerned with parsing
+  XML elements. The \l{QXmlStream Bookmarks Example} makes extensive use of
+  this function.
+
+  \since 4.6
+  \sa readNext()
+ */
+bool QXmlStreamReader::readNextStartElement()
+{
+    while (readNext() != Invalid) {
+        if (isEndElement())
+            return false;
+        else if (isStartElement())
+            return true;
+    }
+    return false;
+}
+
+/*!
+  Reads until the end of the current element, skipping any child nodes.
+  This function is useful for skipping unknown elements.
+
+  The current element is the element matching the most recently parsed start
+  element of which a matching end element has not yet been reached. When the
+  parser has reached the end element, the current element becomes the parent
+  element.
+
+  \since 4.6
+ */
+void QXmlStreamReader::skipCurrentElement()
+{
+    int depth = 1;
+    while (depth && readNext() != Invalid) {
+        if (isEndElement())
+            --depth;
+        else if (isStartElement())
+            ++depth;
+    }
+}
+
+/*
+ * Use the following Perl script to generate the error string index list:
+===== PERL SCRIPT ====
+print "static const char QXmlStreamReader_tokenTypeString_string[] =\n";
+$counter = 0;
+$i = 0;
+while (<STDIN>) {
+    chomp;
+    print "    \"$_\\0\"\n";
+    $sizes[$i++] = $counter;
+    $counter += length 1 + $_;
+}
+print "    \"\\0\";\n\nstatic const short QXmlStreamReader_tokenTypeString_indices[] = {\n    ";
+for ($j = 0; $j < $i; ++$j) {
+    printf "$sizes[$j], ";
+}
+print "0\n};\n";
+===== PERL SCRIPT ====
+
+ * The input data is as follows (copied from qxmlstream.h):
+NoToken
+Invalid
+StartDocument
+EndDocument
+StartElement
+EndElement
+Characters
+Comment
+DTD
+EntityReference
+ProcessingInstruction
+*/
+static const char QXmlStreamReader_tokenTypeString_string[] =
+    "NoToken\0"
+    "Invalid\0"
+    "StartDocument\0"
+    "EndDocument\0"
+    "StartElement\0"
+    "EndElement\0"
+    "Characters\0"
+    "Comment\0"
+    "DTD\0"
+    "EntityReference\0"
+    "ProcessingInstruction\0";
+
+static const short QXmlStreamReader_tokenTypeString_indices[] = {
+    0, 8, 16, 30, 42, 55, 66, 77, 85, 89, 105, 0
+};
+
+
+/*!
+    \property  QXmlStreamReader::namespaceProcessing
+    the namespace-processing flag of the stream reader
+
+    This property controls whether or not the stream reader processes
+    namespaces. If enabled, the reader processes namespaces, otherwise
+    it does not.
+
+    By default, namespace-processing is enabled.
+*/
+
+
+void QXmlStreamReader::setNamespaceProcessing(bool enable)
+{
+    Q_D(QXmlStreamReader);
+    d->namespaceProcessing = enable;
+}
+
+bool QXmlStreamReader::namespaceProcessing() const
+{
+    Q_D(const QXmlStreamReader);
+    return d->namespaceProcessing;
+}
+
+/*! Returns the reader's current token as string.
+
+\sa tokenType()
+*/
+QString QXmlStreamReader::tokenString() const
+{
+    Q_D(const QXmlStreamReader);
+    return QLatin1String(QXmlStreamReader_tokenTypeString_string +
+                         QXmlStreamReader_tokenTypeString_indices[d->type]);
+}
+
+#endif // QT_NO_XMLSTREAMREADER
+
+QXmlStreamPrivateTagStack::QXmlStreamPrivateTagStack()
+{
+    tagStack.reserve(16);
+    tagStackStringStorage.reserve(32);
+    tagStackStringStorageSize = 0;
+    NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.push();
+    namespaceDeclaration.prefix = addToStringStorage(QLatin1String("xml"));
+    namespaceDeclaration.namespaceUri = addToStringStorage(QLatin1String("http://www.w3.org/XML/1998/namespace"));
+}
+
+#ifndef QT_NO_XMLSTREAMREADER
+
+QXmlStreamReaderPrivate::QXmlStreamReaderPrivate(QXmlStreamReader *q)
+    :q_ptr(q)
+{
+    device = 0;
+    deleteDevice = false;
+#ifndef QT_NO_TEXTCODEC
+    decoder = 0;
+#endif
+    stack_size = 64;
+    sym_stack = 0;
+    state_stack = 0;
+    reallocateStack();
+    entityResolver = 0;
+    init();
+    entityHash.insert(QLatin1String("lt"), Entity::createLiteral(QLatin1String("<")));
+    entityHash.insert(QLatin1String("gt"), Entity::createLiteral(QLatin1String(">")));
+    entityHash.insert(QLatin1String("amp"), Entity::createLiteral(QLatin1String("&")));
+    entityHash.insert(QLatin1String("apos"), Entity::createLiteral(QLatin1String("'")));
+    entityHash.insert(QLatin1String("quot"), Entity::createLiteral(QLatin1String("\"")));
+}
+
+void QXmlStreamReaderPrivate::init()
+{
+    tos = 0;
+    scanDtd = false;
+    token = -1;
+    token_char = 0;
+    isEmptyElement = false;
+    isWhitespace = true;
+    isCDATA = false;
+    standalone = false;
+    tos = 0;
+    resumeReduction = 0;
+    state_stack[tos++] = 0;
+    state_stack[tos] = 0;
+    putStack.clear();
+    putStack.reserve(32);
+    textBuffer.clear();
+    textBuffer.reserve(256);
+    tagStack.clear();
+    tagsDone = false;
+    attributes.clear();
+    attributes.reserve(16);
+    lineNumber = lastLineStart = characterOffset = 0;
+    readBufferPos = 0;
+    nbytesread = 0;
+#ifndef QT_NO_TEXTCODEC
+    codec = QTextCodec::codecForMib(106); // utf8
+    delete decoder;
+    decoder = 0;
+#endif
+    attributeStack.clear();
+    attributeStack.reserve(16);
+    entityParser = 0;
+    hasCheckedStartDocument = false;
+    normalizeLiterals = false;
+    hasSeenTag = false;
+    atEnd = false;
+    inParseEntity = false;
+    referenceToUnparsedEntityDetected = false;
+    referenceToParameterEntityDetected = false;
+    hasExternalDtdSubset = false;
+    lockEncoding = false;
+    namespaceProcessing = true;
+    rawReadBuffer.clear();
+    dataBuffer.clear();
+    readBuffer.clear();
+
+    type = QXmlStreamReader::NoToken;
+    error = QXmlStreamReader::NoError;
+}
+
+/*
+  Well-formed requires that we verify entity values. We do this with a
+  standard parser.
+ */
+void QXmlStreamReaderPrivate::parseEntity(const QString &value)
+{
+    Q_Q(QXmlStreamReader);
+
+    if (value.isEmpty())
+        return;
+
+
+    if (!entityParser)
+        entityParser = new QXmlStreamReaderPrivate(q);
+    else
+        entityParser->init();
+    entityParser->inParseEntity = true;
+    entityParser->readBuffer = value;
+    entityParser->injectToken(PARSE_ENTITY);
+    while (!entityParser->atEnd && entityParser->type != QXmlStreamReader::Invalid)
+        entityParser->parse();
+    if (entityParser->type == QXmlStreamReader::Invalid || entityParser->tagStack.size())
+        raiseWellFormedError(QXmlStream::tr("Invalid entity value."));
+
+}
+
+inline void QXmlStreamReaderPrivate::reallocateStack()
+{
+    stack_size <<= 1;
+    sym_stack = reinterpret_cast<Value*> (qRealloc(sym_stack, stack_size * sizeof(Value)));
+    Q_CHECK_PTR(sym_stack);
+    state_stack = reinterpret_cast<int*> (qRealloc(state_stack, stack_size * sizeof(int)));
+    Q_CHECK_PTR(sym_stack);
+}
+
+
+QXmlStreamReaderPrivate::~QXmlStreamReaderPrivate()
+{
+#ifndef QT_NO_TEXTCODEC
+    delete decoder;
+#endif
+    qFree(sym_stack);
+    qFree(state_stack);
+    delete entityParser;
+}
+
+
+inline uint QXmlStreamReaderPrivate::filterCarriageReturn()
+{
+    uint peekc = peekChar();
+    if (peekc == '\n') {
+        if (putStack.size())
+            putStack.pop();
+        else
+            ++readBufferPos;
+        return peekc;
+    }
+    if (peekc == 0) {
+        putChar('\r');
+        return 0;
+    }
+    return '\n';
+}
+
+/*!
+ \internal
+ If the end of the file is encountered, 0 is returned.
+ */
+inline uint QXmlStreamReaderPrivate::getChar()
+{
+    uint c;
+    if (putStack.size()) {
+        c = atEnd ? 0 : putStack.pop();
+    } else {
+        if (readBufferPos < readBuffer.size())
+            c = readBuffer.at(readBufferPos++).unicode();
+        else
+            c = getChar_helper();
+    }
+
+    return c;
+}
+
+inline uint QXmlStreamReaderPrivate::peekChar()
+{
+    uint c;
+    if (putStack.size()) {
+        c = putStack.top();
+    } else if (readBufferPos < readBuffer.size()) {
+        c = readBuffer.at(readBufferPos).unicode();
+    } else {
+        if ((c = getChar_helper()))
+            --readBufferPos;
+    }
+
+    return c;
+}
+
+/*!
+  \internal
+
+  Scans characters until \a str is encountered, and validates the characters
+  as according to the Char[2] production and do the line-ending normalization.
+  If any character is invalid, false is returned, otherwise true upon success.
+
+  If \a tokenToInject is not less than zero, injectToken() is called with
+  \a tokenToInject when \a str is found.
+
+  If any error occurred, false is returned, otherwise true.
+  */
+bool QXmlStreamReaderPrivate::scanUntil(const char *str, short tokenToInject)
+{
+    int pos = textBuffer.size();
+    int oldLineNumber = lineNumber;
+
+    while (uint c = getChar()) {
+        /* First, we do the validation & normalization. */
+        switch (c) {
+        case '\r':
+            if ((c = filterCarriageReturn()) == 0)
+                break;
+            // fall through
+        case '\n':
+            ++lineNumber;
+            lastLineStart = characterOffset + readBufferPos;
+            // fall through
+        case '\t':
+            textBuffer += QChar(c);
+            continue;
+        default:
+            if(c < 0x20 || (c > 0xFFFD && c < 0x10000) || c > 0x10FFFF ) {
+                raiseWellFormedError(QXmlStream::tr("Invalid XML character."));
+                lineNumber = oldLineNumber;
+                return false;
+            }
+            textBuffer += QChar(c);
+        }
+
+
+        /* Second, attempt to lookup str. */
+        if (c == uint(*str)) {
+            if (!*(str + 1)) {
+                if (tokenToInject >= 0)
+                    injectToken(tokenToInject);
+                return true;
+            } else {
+                if (scanString(str + 1, tokenToInject, false))
+                    return true;
+            }
+        }
+    }
+    putString(textBuffer, pos);
+    textBuffer.resize(pos);
+    lineNumber = oldLineNumber;
+    return false;
+}
+
+bool QXmlStreamReaderPrivate::scanString(const char *str, short tokenToInject, bool requireSpace)
+{
+    int n = 0;
+    while (str[n]) {
+        ushort c = getChar();
+        if (c != ushort(str[n])) {
+            if (c)
+                putChar(c);
+            while (n--) {
+                putChar(ushort(str[n]));
+            }
+            return false;
+        }
+        ++n;
+    }
+    for (int i = 0; i < n; ++i)
+        textBuffer += QChar(ushort(str[i]));
+    if (requireSpace) {
+        int s = fastScanSpace();
+        if (!s || atEnd) {
+            int pos = textBuffer.size() - n - s;
+            putString(textBuffer, pos);
+            textBuffer.resize(pos);
+            return false;
+        }
+    }
+    if (tokenToInject >= 0)
+        injectToken(tokenToInject);
+    return true;
+}
+
+bool QXmlStreamReaderPrivate::scanAfterLangleBang()
+{
+    switch (peekChar()) {
+    case '[':
+        return scanString(spell[CDATA_START], CDATA_START, false);
+    case 'D':
+        return scanString(spell[DOCTYPE], DOCTYPE);
+    case 'A':
+        return scanString(spell[ATTLIST], ATTLIST);
+    case 'N':
+        return scanString(spell[NOTATION], NOTATION);
+    case 'E':
+        if (scanString(spell[ELEMENT], ELEMENT))
+            return true;
+        return scanString(spell[ENTITY], ENTITY);
+
+    default:
+        ;
+    };
+    return false;
+}
+
+bool QXmlStreamReaderPrivate::scanPublicOrSystem()
+{
+    switch (peekChar()) {
+    case 'S':
+        return scanString(spell[SYSTEM], SYSTEM);
+    case 'P':
+        return scanString(spell[PUBLIC], PUBLIC);
+    default:
+        ;
+    }
+    return false;
+}
+
+bool QXmlStreamReaderPrivate::scanNData()
+{
+    if (fastScanSpace()) {
+        if (scanString(spell[NDATA], NDATA))
+            return true;
+        putChar(' ');
+    }
+    return false;
+}
+
+bool QXmlStreamReaderPrivate::scanAfterDefaultDecl()
+{
+    switch (peekChar()) {
+    case 'R':
+        return scanString(spell[REQUIRED], REQUIRED, false);
+    case 'I':
+        return scanString(spell[IMPLIED], IMPLIED, false);
+    case 'F':
+        return scanString(spell[FIXED], FIXED, false);
+    default:
+        ;
+    }
+    return false;
+}
+
+bool QXmlStreamReaderPrivate::scanAttType()
+{
+    switch (peekChar()) {
+    case 'C':
+        return scanString(spell[CDATA], CDATA);
+    case 'I':
+        if (scanString(spell[ID], ID))
+            return true;
+        if (scanString(spell[IDREF], IDREF))
+            return true;
+        return scanString(spell[IDREFS], IDREFS);
+    case 'E':
+        if (scanString(spell[ENTITY], ENTITY))
+            return true;
+        return scanString(spell[ENTITIES], ENTITIES);
+    case 'N':
+        if (scanString(spell[NOTATION], NOTATION))
+            return true;
+        if (scanString(spell[NMTOKEN], NMTOKEN))
+            return true;
+        return scanString(spell[NMTOKENS], NMTOKENS);
+    default:
+        ;
+    }
+    return false;
+}
+
+/*!
+ \internal
+
+ Scan strings with quotes or apostrophes surround them. For instance,
+ attributes, the version and encoding field in the XML prolog and
+ entity declarations.
+
+ If normalizeLiterals is set to true, the function also normalizes
+ whitespace. It is set to true when the first start tag is
+ encountered.
+
+ */
+inline int QXmlStreamReaderPrivate::fastScanLiteralContent()
+{
+    int n = 0;
+    uint c;
+    while ((c = getChar())) {
+        switch (ushort(c)) {
+        case 0xfffe:
+        case 0xffff:
+        case 0:
+            /* The putChar() call is necessary so the parser re-gets
+             * the character from the input source, when raising an error. */
+            putChar(c);
+            return n;
+        case '\r':
+            if (filterCarriageReturn() == 0)
+                return n;
+            // fall through
+        case '\n':
+            ++lineNumber;
+            lastLineStart = characterOffset + readBufferPos;
+            // fall through
+        case ' ':
+        case '\t':
+            if (normalizeLiterals)
+                textBuffer += QLatin1Char(' ');
+            else
+                textBuffer += QChar(c);
+            ++n;
+            break;
+        case '&':
+        case '<':
+        case '\"':
+        case '\'':
+            if (!(c & 0xff0000)) {
+                putChar(c);
+                return n;
+            }
+            // fall through
+        default:
+            textBuffer += QChar(c);
+            ++n;
+        }
+    }
+    return n;
+}
+
+inline int QXmlStreamReaderPrivate::fastScanSpace()
+{
+    int n = 0;
+    ushort c;
+    while ((c = getChar())) {
+        switch (c) {
+        case '\r':
+            if ((c = filterCarriageReturn()) == 0)
+                return n;
+            // fall through
+        case '\n':
+            ++lineNumber;
+            lastLineStart = characterOffset + readBufferPos;
+            // fall through
+        case ' ':
+        case '\t':
+            textBuffer += QChar(c);
+            ++n;
+            break;
+        default:
+            putChar(c);
+            return n;
+        }
+    }
+    return n;
+}
+
+/*!
+  \internal
+
+  Used for text nodes essentially. That is, characters appearing
+  inside elements.
+ */
+inline int QXmlStreamReaderPrivate::fastScanContentCharList()
+{
+    int n = 0;
+    uint c;
+    while ((c = getChar())) {
+        switch (ushort(c)) {
+        case 0xfffe:
+        case 0xffff:
+        case 0:
+            putChar(c);
+            return n;
+        case ']': {
+            isWhitespace = false;
+            int pos = textBuffer.size();
+            textBuffer += QChar(ushort(c));
+            ++n;
+            while ((c = getChar()) == ']') {
+                textBuffer += QChar(ushort(c));
+                ++n;
+            }
+            if (c == 0) {
+                putString(textBuffer, pos);
+                textBuffer.resize(pos);
+            } else if (c == '>' && textBuffer.at(textBuffer.size()-2) == QLatin1Char(']')) {
+                raiseWellFormedError(QXmlStream::tr("Sequence ']]>' not allowed in content."));
+            } else {
+                putChar(c);
+                break;
+            }
+            return n;
+        } break;
+        case '\r':
+            if ((c = filterCarriageReturn()) == 0)
+                return n;
+            // fall through
+        case '\n':
+            ++lineNumber;
+            lastLineStart = characterOffset + readBufferPos;
+            // fall through
+        case ' ':
+        case '\t':
+            textBuffer += QChar(ushort(c));
+            ++n;
+            break;
+        case '&':
+        case '<':
+            if (!(c & 0xff0000)) {
+                putChar(c);
+                return n;
+            }
+            // fall through
+        default:
+            if (c < 0x20) {
+                putChar(c);
+                return n;
+            }
+            isWhitespace = false;
+            textBuffer += QChar(ushort(c));
+            ++n;
+        }
+    }
+    return n;
+}
+
+inline int QXmlStreamReaderPrivate::fastScanName(int *prefix)
+{
+    int n = 0;
+    ushort c;
+    while ((c = getChar())) {
+        switch (c) {
+        case '\n':
+        case ' ':
+        case '\t':
+        case '\r':
+        case '&':
+        case '#':
+        case '\'':
+        case '\"':
+        case '<':
+        case '>':
+        case '[':
+        case ']':
+        case '=':
+        case '%':
+        case '/':
+        case ';':
+        case '?':
+        case '!':
+        case '^':
+        case '|':
+        case ',':
+        case '(':
+        case ')':
+        case '+':
+        case '*':
+            putChar(c);
+            if (prefix && *prefix == n+1) {
+                *prefix = 0;
+                putChar(':');
+                --n;
+            }
+            return n;
+        case ':':
+            if (prefix) {
+                if (*prefix == 0) {
+                    *prefix = n+2;
+                } else { // only one colon allowed according to the namespace spec.
+                    putChar(c);
+                    return n;
+                }
+            } else {
+                putChar(c);
+                return n;
+            }
+            // fall through
+        default:
+            textBuffer += QChar(c);
+            ++n;
+        }
+    }
+
+    if (prefix)
+        *prefix = 0;
+    int pos = textBuffer.size() - n;
+    putString(textBuffer, pos);
+    textBuffer.resize(pos);
+    return 0;
+}
+
+enum NameChar { NameBeginning, NameNotBeginning, NotName };
+
+static const char Begi = static_cast<char>(NameBeginning);
+static const char NtBg = static_cast<char>(NameNotBeginning);
+static const char NotN = static_cast<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 static_cast<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;
+}
+
+inline int QXmlStreamReaderPrivate::fastScanNMTOKEN()
+{
+    int n = 0;
+    uint c;
+    while ((c = getChar())) {
+        if (fastDetermineNameChar(c) == NotName) {
+            putChar(c);
+            return n;
+        } else {
+            ++n;
+            textBuffer += QChar(c);
+        }
+    }
+
+    int pos = textBuffer.size() - n;
+    putString(textBuffer, pos);
+    textBuffer.resize(pos);
+
+    return n;
+}
+
+void QXmlStreamReaderPrivate::putString(const QString &s, int from)
+{
+    putStack.reserve(s.size());
+    for (int i = s.size()-1; i >= from; --i)
+        putStack.rawPush() = s.at(i).unicode();
+}
+
+void QXmlStreamReaderPrivate::putStringLiteral(const QString &s)
+{
+    putStack.reserve(s.size());
+    for (int i = s.size()-1; i >= 0; --i)
+        putStack.rawPush() = ((LETTER << 16) | s.at(i).unicode());
+}
+
+void QXmlStreamReaderPrivate::putReplacement(const QString &s)
+{
+    putStack.reserve(s.size());
+    for (int i = s.size()-1; i >= 0; --i) {
+        ushort c = s.at(i).unicode();
+        if (c == '\n' || c == '\r')
+            putStack.rawPush() = ((LETTER << 16) | c);
+        else
+            putStack.rawPush() = c;
+    }
+}
+void QXmlStreamReaderPrivate::putReplacementInAttributeValue(const QString &s)
+{
+    putStack.reserve(s.size());
+    for (int i = s.size()-1; i >= 0; --i) {
+        ushort c = s.at(i).unicode();
+        if (c == '&' || c == ';')
+            putStack.rawPush() = c;
+        else if (c == '\n' || c == '\r')
+            putStack.rawPush() = ' ';
+        else
+            putStack.rawPush() = ((LETTER << 16) | c);
+    }
+}
+
+ushort QXmlStreamReaderPrivate::getChar_helper()
+{
+    const int BUFFER_SIZE = 8192;
+    characterOffset += readBufferPos;
+    readBufferPos = 0;
+    readBuffer.resize(0);
+#ifndef QT_NO_TEXTCODEC
+    if (decoder)
+#endif
+        nbytesread = 0;
+    if (device) {
+        rawReadBuffer.resize(BUFFER_SIZE);
+        int nbytesreadOrMinus1 = device->read(rawReadBuffer.data() + nbytesread, BUFFER_SIZE - nbytesread);
+        nbytesread += qMax(nbytesreadOrMinus1, 0);
+    } else {
+        if (nbytesread)
+            rawReadBuffer += dataBuffer;
+        else
+            rawReadBuffer = dataBuffer;
+        nbytesread = rawReadBuffer.size();
+        dataBuffer.clear();
+    }
+    if (!nbytesread) {
+        atEnd = true;
+        return 0;
+    }
+
+#ifndef QT_NO_TEXTCODEC
+    if (!decoder) {
+        if (nbytesread < 4) { // the 4 is to cover 0xef 0xbb 0xbf plus
+                              // one extra for the utf8 codec
+            atEnd = true;
+            return 0;
+        }
+        int mib = 106; // UTF-8
+
+        // look for byte order mark
+        uchar ch1 = rawReadBuffer.at(0);
+        uchar ch2 = rawReadBuffer.at(1);
+        uchar ch3 = rawReadBuffer.at(2);
+        uchar ch4 = rawReadBuffer.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
+        else 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
+        codec = QTextCodec::codecForMib(mib);
+        Q_ASSERT(codec);
+        decoder = codec->makeDecoder();
+    }
+
+    decoder->toUnicode(&readBuffer, rawReadBuffer.data(), nbytesread);
+
+    if(lockEncoding && decoder->hasFailure()) {
+        raiseWellFormedError(QXmlStream::tr("Encountered incorrectly encoded content."));
+        readBuffer.clear();
+        return 0;
+    }
+#else
+    readBuffer = QString::fromLatin1(rawReadBuffer.data(), nbytesread);
+#endif // QT_NO_TEXTCODEC
+
+    readBuffer.reserve(1); // keep capacity when calling resize() next time
+
+    if (readBufferPos < readBuffer.size()) {
+        ushort c = readBuffer.at(readBufferPos++).unicode();
+        return c;
+    }
+
+    atEnd = true;
+    return 0;
+}
+
+QStringRef QXmlStreamReaderPrivate::namespaceForPrefix(const QStringRef &prefix)
+{
+     for (int j = namespaceDeclarations.size() - 1; j >= 0; --j) {
+         const NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.at(j);
+         if (namespaceDeclaration.prefix == prefix) {
+             return namespaceDeclaration.namespaceUri;
+         }
+     }
+
+#if 1
+     if (namespaceProcessing && !prefix.isEmpty())
+         raiseWellFormedError(QXmlStream::tr("Namespace prefix '%1' not declared").arg(prefix.toString()));
+#endif
+
+     return QStringRef();
+}
+
+/*
+  uses namespaceForPrefix and builds the attribute vector
+ */
+void QXmlStreamReaderPrivate::resolveTag()
+{
+    int n = attributeStack.size();
+
+    if (namespaceProcessing) {
+        for (int a = 0; a < dtdAttributes.size(); ++a) {
+            DtdAttribute &dtdAttribute = dtdAttributes[a];
+            if (!dtdAttribute.isNamespaceAttribute
+                || dtdAttribute.defaultValue.isNull()
+                || dtdAttribute.tagName != qualifiedName
+                || dtdAttribute.attributeQualifiedName.isNull())
+                continue;
+            int i = 0;
+            while (i < n && symName(attributeStack[i].key) != dtdAttribute.attributeQualifiedName)
+                ++i;
+            if (i != n)
+                continue;
+            if (dtdAttribute.attributePrefix.isEmpty() && dtdAttribute.attributeName == QLatin1String("xmlns")) {
+                NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.push();
+                namespaceDeclaration.prefix.clear();
+
+                const QStringRef ns(dtdAttribute.defaultValue);
+                if(ns == QLatin1String("http://www.w3.org/2000/xmlns/") ||
+                   ns == QLatin1String("http://www.w3.org/XML/1998/namespace"))
+                    raiseWellFormedError(QXmlStream::tr("Illegal namespace declaration."));
+                else
+                    namespaceDeclaration.namespaceUri = ns;
+            } else if (dtdAttribute.attributePrefix == QLatin1String("xmlns")) {
+                NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.push();
+                QStringRef namespacePrefix = dtdAttribute.attributeName;
+                QStringRef namespaceUri = dtdAttribute.defaultValue;
+                if (((namespacePrefix == QLatin1String("xml"))
+                     ^ (namespaceUri == QLatin1String("http://www.w3.org/XML/1998/namespace")))
+                    || namespaceUri == QLatin1String("http://www.w3.org/2000/xmlns/")
+                    || namespaceUri.isEmpty()
+                    || namespacePrefix == QLatin1String("xmlns"))
+                    raiseWellFormedError(QXmlStream::tr("Illegal namespace declaration."));
+
+                namespaceDeclaration.prefix = namespacePrefix;
+                namespaceDeclaration.namespaceUri = namespaceUri;
+            }
+        }
+    }
+
+    tagStack.top().namespaceDeclaration.namespaceUri = namespaceUri = namespaceForPrefix(prefix);
+
+    attributes.resize(n);
+
+    for (int i = 0; i < n; ++i) {
+        QXmlStreamAttribute &attribute = attributes[i];
+        Attribute &attrib = attributeStack[i];
+        QStringRef prefix(symPrefix(attrib.key));
+        QStringRef name(symString(attrib.key));
+        QStringRef qualifiedName(symName(attrib.key));
+        QStringRef value(symString(attrib.value));
+
+        attribute.m_name = QXmlStreamStringRef(name);
+        attribute.m_qualifiedName = QXmlStreamStringRef(qualifiedName);
+        attribute.m_value = QXmlStreamStringRef(value);
+
+        if (!prefix.isEmpty()) {
+            QStringRef attributeNamespaceUri = namespaceForPrefix(prefix);
+            attribute.m_namespaceUri = QXmlStreamStringRef(attributeNamespaceUri);
+        }
+
+        for (int j = 0; j < i; ++j) {
+            if (attributes[j].name() == attribute.name()
+                && attributes[j].namespaceUri() == attribute.namespaceUri()
+                && (namespaceProcessing || attributes[j].qualifiedName() == attribute.qualifiedName()))
+                raiseWellFormedError(QXmlStream::tr("Attribute redefined."));
+        }
+    }
+
+    for (int a = 0; a < dtdAttributes.size(); ++a) {
+        DtdAttribute &dtdAttribute = dtdAttributes[a];
+        if (dtdAttribute.isNamespaceAttribute
+            || dtdAttribute.defaultValue.isNull()
+            || dtdAttribute.tagName != qualifiedName
+            || dtdAttribute.attributeQualifiedName.isNull())
+            continue;
+        int i = 0;
+        while (i < n && symName(attributeStack[i].key) != dtdAttribute.attributeQualifiedName)
+            ++i;
+        if (i != n)
+            continue;
+
+
+
+        QXmlStreamAttribute attribute;
+        attribute.m_name = QXmlStreamStringRef(dtdAttribute.attributeName);
+        attribute.m_qualifiedName = QXmlStreamStringRef(dtdAttribute.attributeQualifiedName);
+        attribute.m_value = QXmlStreamStringRef(dtdAttribute.defaultValue);
+
+        if (!dtdAttribute.attributePrefix.isEmpty()) {
+            QStringRef attributeNamespaceUri = namespaceForPrefix(dtdAttribute.attributePrefix);
+            attribute.m_namespaceUri = QXmlStreamStringRef(attributeNamespaceUri);
+        }
+        attribute.m_isDefault = true;
+        attributes.append(attribute);
+    }
+
+    attributeStack.clear();
+}
+
+void QXmlStreamReaderPrivate::resolvePublicNamespaces()
+{
+    const Tag &tag = tagStack.top();
+    int n = namespaceDeclarations.size() - tag.namespaceDeclarationsSize;
+    publicNamespaceDeclarations.resize(n);
+    for (int i = 0; i < n; ++i) {
+        const NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.at(tag.namespaceDeclarationsSize + i);
+        QXmlStreamNamespaceDeclaration &publicNamespaceDeclaration = publicNamespaceDeclarations[i];
+        publicNamespaceDeclaration.m_prefix = QXmlStreamStringRef(namespaceDeclaration.prefix);
+        publicNamespaceDeclaration.m_namespaceUri = QXmlStreamStringRef(namespaceDeclaration.namespaceUri);
+    }
+}
+
+void QXmlStreamReaderPrivate::resolveDtd()
+{
+    publicNotationDeclarations.resize(notationDeclarations.size());
+    for (int i = 0; i < notationDeclarations.size(); ++i) {
+        const QXmlStreamReaderPrivate::NotationDeclaration &notationDeclaration = notationDeclarations.at(i);
+        QXmlStreamNotationDeclaration &publicNotationDeclaration = publicNotationDeclarations[i];
+        publicNotationDeclaration.m_name = QXmlStreamStringRef(notationDeclaration.name);
+        publicNotationDeclaration.m_systemId = QXmlStreamStringRef(notationDeclaration.systemId);
+        publicNotationDeclaration.m_publicId = QXmlStreamStringRef(notationDeclaration.publicId);
+
+    }
+    notationDeclarations.clear();
+    publicEntityDeclarations.resize(entityDeclarations.size());
+    for (int i = 0; i < entityDeclarations.size(); ++i) {
+        const QXmlStreamReaderPrivate::EntityDeclaration &entityDeclaration = entityDeclarations.at(i);
+        QXmlStreamEntityDeclaration &publicEntityDeclaration = publicEntityDeclarations[i];
+        publicEntityDeclaration.m_name = QXmlStreamStringRef(entityDeclaration.name);
+        publicEntityDeclaration.m_notationName = QXmlStreamStringRef(entityDeclaration.notationName);
+        publicEntityDeclaration.m_systemId = QXmlStreamStringRef(entityDeclaration.systemId);
+        publicEntityDeclaration.m_publicId = QXmlStreamStringRef(entityDeclaration.publicId);
+        publicEntityDeclaration.m_value = QXmlStreamStringRef(entityDeclaration.value);
+    }
+    entityDeclarations.clear();
+    parameterEntityHash.clear();
+}
+
+uint QXmlStreamReaderPrivate::resolveCharRef(int symbolIndex)
+{
+    bool ok = true;
+    uint s;
+    // ### add toXShort to QStringRef?
+    if (sym(symbolIndex).c == 'x')
+        s = symString(symbolIndex, 1).toString().toUInt(&ok, 16);
+    else
+        s = symString(symbolIndex).toString().toUInt(&ok, 10);
+
+    ok &= (s == 0x9 || s == 0xa || s == 0xd || (s >= 0x20 && s <= 0xd7ff)
+           || (s >= 0xe000 && s <= 0xfffd) || (s >= 0x10000 && s <= 0x10ffff));
+
+    return ok ? s : 0;
+}
+
+
+void QXmlStreamReaderPrivate::checkPublicLiteral(const QStringRef &publicId)
+{
+//#x20 | #xD | #xA | [a-zA-Z0-9] | [-'()+,./:=?;!*#@$_%]
+
+    const ushort *data = reinterpret_cast<const ushort *>(publicId.constData());
+    uchar c = 0;
+    int i;
+    for (i = publicId.size() - 1; i >= 0; --i) {
+        if (data[i] < 256)
+            switch ((c = data[i])) {
+            case ' ': case '\n': case '\r': case '-': case '(': case ')':
+            case '+': case ',': case '.': case '/': case ':': case '=':
+            case '?': case ';': case '!': case '*': case '#': case '@':
+            case '$': case '_': case '%': case '\'': case '\"':
+                continue;
+            default:
+                if ((c >= 'a' && c <= 'z')
+                    || (c >= 'A' && c <= 'Z')
+                    || (c >= '0' && c <= '9'))
+                    continue;
+            }
+        break;
+    }
+    if (i >= 0)
+        raiseWellFormedError(QXmlStream::tr("Unexpected character '%1' in public id literal.").arg(QChar(QLatin1Char(c))));
+}
+
+/*
+  Checks whether the document starts with an xml declaration. If it
+  does, this function returns true; otherwise it sets up everything
+  for a synthetic start document event and returns false.
+ */
+bool QXmlStreamReaderPrivate::checkStartDocument()
+{
+    hasCheckedStartDocument = true;
+
+    if (scanString(spell[XML], XML))
+        return true;
+
+    type = QXmlStreamReader::StartDocument;
+    if (atEnd) {
+        hasCheckedStartDocument = false;
+        raiseError(QXmlStreamReader::PrematureEndOfDocumentError);
+    }
+    return false;
+}
+
+void QXmlStreamReaderPrivate::startDocument()
+{
+    QString err;
+    if (documentVersion != QLatin1String("1.0")) {
+        if (documentVersion.toString().contains(QLatin1Char(' ')))
+            err = QXmlStream::tr("Invalid XML version string.");
+        else
+            err = QXmlStream::tr("Unsupported XML version.");
+    }
+    int n = attributeStack.size();
+
+    /* We use this bool to ensure that the pesudo attributes are in the
+     * proper order:
+     *
+     * [23]     XMLDecl     ::=     '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>' */
+    bool hasStandalone = false;
+
+    for (int i = 0; err.isNull() && i < n; ++i) {
+        Attribute &attrib = attributeStack[i];
+        QStringRef prefix(symPrefix(attrib.key));
+        QStringRef key(symString(attrib.key));
+        QStringRef value(symString(attrib.value));
+
+        if (prefix.isEmpty() && key == QLatin1String("encoding")) {
+            const QString name(value.toString());
+            documentEncoding = value;
+
+            if(hasStandalone)
+                err = QXmlStream::tr("The standalone pseudo attribute must appear after the encoding.");
+            if(!QXmlUtils::isEncName(name))
+                err = QXmlStream::tr("%1 is an invalid encoding name.").arg(name);
+            else {
+#ifdef QT_NO_TEXTCODEC
+                readBuffer = QString::fromLatin1(rawReadBuffer.data(), nbytesread);
+#else
+                QTextCodec *const newCodec = QTextCodec::codecForName(name.toLatin1());
+                if (!newCodec)
+                    err = QXmlStream::tr("Encoding %1 is unsupported").arg(name);
+                else if (newCodec != codec && !lockEncoding) {
+                    codec = newCodec;
+                    delete decoder;
+                    decoder = codec->makeDecoder();
+                    decoder->toUnicode(&readBuffer, rawReadBuffer.data(), nbytesread);
+                }
+#endif // QT_NO_TEXTCODEC
+            }
+        } else if (prefix.isEmpty() && key == QLatin1String("standalone")) {
+            hasStandalone = true;
+            if (value == QLatin1String("yes"))
+                standalone = true;
+            else if (value == QLatin1String("no"))
+                standalone = false;
+            else
+                err = QXmlStream::tr("Standalone accepts only yes or no.");
+        } else {
+            err = QXmlStream::tr("Invalid attribute in XML declaration.");
+        }
+    }
+
+    if (!err.isNull())
+        raiseWellFormedError(err);
+    attributeStack.clear();
+}
+
+
+void QXmlStreamReaderPrivate::raiseError(QXmlStreamReader::Error error, const QString& message)
+{
+    this->error = error;
+    errorString = message;
+    if (errorString.isNull()) {
+        if (error == QXmlStreamReader::PrematureEndOfDocumentError)
+            errorString = QXmlStream::tr("Premature end of document.");
+        else if (error == QXmlStreamReader::CustomError)
+            errorString = QXmlStream::tr("Invalid document.");
+    }
+
+    type = QXmlStreamReader::Invalid;
+}
+
+void QXmlStreamReaderPrivate::raiseWellFormedError(const QString &message)
+{
+    raiseError(QXmlStreamReader::NotWellFormedError, message);
+}
+
+void QXmlStreamReaderPrivate::parseError()
+{
+
+    if (token == EOF_SYMBOL) {
+        raiseError(QXmlStreamReader::PrematureEndOfDocumentError);
+        return;
+    }
+    const int nmax = 4;
+    QString error_message;
+    int ers = state_stack[tos];
+    int nexpected = 0;
+    int expected[nmax];
+    if (token != ERROR)
+        for (int tk = 0; tk < TERMINAL_COUNT; ++tk) {
+            int k = t_action(ers, tk);
+            if (k <= 0)
+                continue;
+            if (spell[tk]) {
+                if (nexpected < nmax)
+                    expected[nexpected++] = tk;
+            }
+        }
+
+    error_message.clear ();
+    if (nexpected && nexpected < nmax) {
+        bool first = true;
+
+        for (int s = 0; s < nexpected; ++s) {
+            if (first)
+                error_message += QXmlStream::tr ("Expected ");
+            else if (s == nexpected - 1)
+                error_message += QLatin1String (nexpected > 2 ? ", or " : " or ");
+            else
+                error_message += QLatin1String (", ");
+
+            first = false;
+            error_message += QLatin1String("\'");
+            error_message += QLatin1String (spell [expected[s]]);
+            error_message += QLatin1String("\'");
+        }
+        error_message += QXmlStream::tr(", but got \'");
+        error_message += QLatin1String(spell [token]);
+        error_message += QLatin1String("\'");
+    } else {
+        error_message += QXmlStream::tr("Unexpected \'");
+        error_message += QLatin1String(spell [token]);
+        error_message += QLatin1String("\'");
+    }
+    error_message += QLatin1Char('.');
+
+    raiseWellFormedError(error_message);
+}
+
+void QXmlStreamReaderPrivate::resume(int rule) {
+    resumeReduction = rule;
+    if (error == QXmlStreamReader::NoError)
+        raiseError(QXmlStreamReader::PrematureEndOfDocumentError);
+}
+
+/*! Returns the current line number, starting with 1.
+
+\sa columnNumber(), characterOffset()
+ */
+qint64 QXmlStreamReader::lineNumber() const
+{
+    Q_D(const QXmlStreamReader);
+    return d->lineNumber + 1; // in public we start with 1
+}
+
+/*! Returns the current column number, starting with 0.
+
+\sa lineNumber(), characterOffset()
+ */
+qint64 QXmlStreamReader::columnNumber() const
+{
+    Q_D(const QXmlStreamReader);
+    return d->characterOffset - d->lastLineStart + d->readBufferPos;
+}
+
+/*! Returns the current character offset, starting with 0.
+
+\sa lineNumber(), columnNumber()
+*/
+qint64 QXmlStreamReader::characterOffset() const
+{
+    Q_D(const QXmlStreamReader);
+    return d->characterOffset + d->readBufferPos;
+}
+
+
+/*!  Returns the text of \l Characters, \l Comment, \l DTD, or
+  EntityReference.
+ */
+QStringRef QXmlStreamReader::text() const
+{
+    Q_D(const QXmlStreamReader);
+    return d->text;
+}
+
+
+/*!  If the state() is \l DTD, this function returns the DTD's
+  notation declarations. Otherwise an empty vector is returned.
+
+  The QXmlStreamNotationDeclarations class is defined to be a QVector
+  of QXmlStreamNotationDeclaration.
+ */
+QXmlStreamNotationDeclarations QXmlStreamReader::notationDeclarations() const
+{
+    Q_D(const QXmlStreamReader);
+    if (d->notationDeclarations.size())
+        const_cast<QXmlStreamReaderPrivate *>(d)->resolveDtd();
+    return d->publicNotationDeclarations;
+}
+
+
+/*!  If the state() is \l DTD, this function returns the DTD's
+  unparsed (external) entity declarations. Otherwise an empty vector is returned.
+
+  The QXmlStreamEntityDeclarations class is defined to be a QVector
+  of QXmlStreamEntityDeclaration.
+ */
+QXmlStreamEntityDeclarations QXmlStreamReader::entityDeclarations() const
+{
+    Q_D(const QXmlStreamReader);
+    if (d->entityDeclarations.size())
+        const_cast<QXmlStreamReaderPrivate *>(d)->resolveDtd();
+    return d->publicEntityDeclarations;
+}
+
+/*!
+  \since 4.4
+
+  If the state() is \l DTD, this function returns the DTD's
+  name. Otherwise an empty string is returned.
+
+ */
+QStringRef QXmlStreamReader::dtdName() const
+{
+   Q_D(const QXmlStreamReader);
+   if (d->type == QXmlStreamReader::DTD)
+       return d->dtdName;
+   return QStringRef();
+}
+
+/*!
+  \since 4.4
+
+  If the state() is \l DTD, this function returns the DTD's
+  public identifier. Otherwise an empty string is returned.
+
+ */
+QStringRef QXmlStreamReader::dtdPublicId() const
+{
+   Q_D(const QXmlStreamReader);
+   if (d->type == QXmlStreamReader::DTD)
+       return d->dtdPublicId;
+   return QStringRef();
+}
+
+/*!
+  \since 4.4
+
+  If the state() is \l DTD, this function returns the DTD's
+  system identifier. Otherwise an empty string is returned.
+
+ */
+QStringRef QXmlStreamReader::dtdSystemId() const
+{
+   Q_D(const QXmlStreamReader);
+   if (d->type == QXmlStreamReader::DTD)
+       return d->dtdSystemId;
+   return QStringRef();
+}
+
+/*!  If the state() is \l StartElement, this function returns the
+  element's namespace declarations. Otherwise an empty vector is
+  returned.
+
+  The QXmlStreamNamespaceDeclaration class is defined to be a QVector
+  of QXmlStreamNamespaceDeclaration.
+
+  \sa addExtraNamespaceDeclaration(), addExtraNamespaceDeclarations()
+ */
+QXmlStreamNamespaceDeclarations QXmlStreamReader::namespaceDeclarations() const
+{
+    Q_D(const QXmlStreamReader);
+    if (d->publicNamespaceDeclarations.isEmpty() && d->type == StartElement)
+        const_cast<QXmlStreamReaderPrivate *>(d)->resolvePublicNamespaces();
+    return d->publicNamespaceDeclarations;
+}
+
+
+/*!
+  \since 4.4
+
+  Adds an \a extraNamespaceDeclaration. The declaration will be
+  valid for children of the current element, or - should the function
+  be called before any elements are read - for the entire XML
+  document.
+
+  \sa namespaceDeclarations(), addExtraNamespaceDeclarations(), setNamespaceProcessing()
+ */
+void QXmlStreamReader::addExtraNamespaceDeclaration(const QXmlStreamNamespaceDeclaration &extraNamespaceDeclaration)
+{
+    Q_D(QXmlStreamReader);
+    QXmlStreamReaderPrivate::NamespaceDeclaration &namespaceDeclaration = d->namespaceDeclarations.push();
+    namespaceDeclaration.prefix = d->addToStringStorage(extraNamespaceDeclaration.prefix());
+    namespaceDeclaration.namespaceUri = d->addToStringStorage(extraNamespaceDeclaration.namespaceUri());
+}
+
+/*!
+  \since 4.4
+
+  Adds a vector of declarations specified by \a extraNamespaceDeclarations.
+
+  \sa namespaceDeclarations(), addExtraNamespaceDeclaration()
+ */
+void QXmlStreamReader::addExtraNamespaceDeclarations(const QXmlStreamNamespaceDeclarations &extraNamespaceDeclarations)
+{
+    for (int i = 0; i < extraNamespaceDeclarations.size(); ++i)
+        addExtraNamespaceDeclaration(extraNamespaceDeclarations.at(i));
+}
+
+
+/*!  Convenience function to be called in case a StartElement was
+  read. Reads until the corresponding EndElement and returns all text
+  in-between. In case of no error, the current token (see tokenType())
+  after having called this function is EndElement.
+
+  The function concatenates text() when it reads either \l Characters
+  or EntityReference tokens, but skips ProcessingInstruction and \l
+  Comment. If the current token is not StartElement, an empty string is
+  returned.
+
+  The \a behaviour defines what happens in case anything else is
+  read before reaching EndElement. The function can include the text from
+  child elements (useful for example for HTML), ignore child elements, or
+  raise an UnexpectedElementError and return what was read so far.
+
+  \since 4.6
+ */
+QString QXmlStreamReader::readElementText(ReadElementTextBehaviour behaviour)
+{
+    Q_D(QXmlStreamReader);
+    if (isStartElement()) {
+        QString result;
+        forever {
+            switch (readNext()) {
+            case Characters:
+            case EntityReference:
+                result.insert(result.size(), d->text.unicode(), d->text.size());
+                break;
+            case EndElement:
+                return result;
+            case ProcessingInstruction:
+            case Comment:
+                break;
+            case StartElement:
+                if (behaviour == SkipChildElements) {
+                    skipCurrentElement();
+                    break;
+                } else if (behaviour == IncludeChildElements) {
+                    result += readElementText(behaviour);
+                    break;
+                }
+                // Fall through (for ErrorOnUnexpectedElement)
+            default:
+                if (d->error || behaviour == ErrorOnUnexpectedElement) {
+                    if (!d->error)
+                        d->raiseError(UnexpectedElementError, QXmlStream::tr("Expected character data."));
+                    return result;
+                }
+            }
+        }
+    }
+    return QString();
+}
+
+/*!
+  \overload readElementText()
+
+  Calling this function is equivalent to calling readElementText(ErrorOnUnexpectedElement).
+ */
+QString QXmlStreamReader::readElementText()
+{
+    return readElementText(ErrorOnUnexpectedElement);
+}
+
+/*!  Raises a custom error with an optional error \a message.
+
+  \sa error(), errorString()
+ */
+void QXmlStreamReader::raiseError(const QString& message)
+{
+    Q_D(QXmlStreamReader);
+    d->raiseError(CustomError, message);
+}
+
+/*!
+  Returns the error message that was set with raiseError().
+
+  \sa error(), lineNumber(), columnNumber(), characterOffset()
+ */
+QString QXmlStreamReader::errorString() const
+{
+    Q_D(const QXmlStreamReader);
+    if (d->type == QXmlStreamReader::Invalid)
+        return d->errorString;
+    return QString();
+}
+
+/*!  Returns the type of the current error, or NoError if no error occurred.
+
+  \sa errorString(), raiseError()
+ */
+QXmlStreamReader::Error QXmlStreamReader::error() const
+{
+    Q_D(const QXmlStreamReader);
+    if (d->type == QXmlStreamReader::Invalid)
+        return d->error;
+    return NoError;
+}
+
+/*!
+  Returns the target of a ProcessingInstruction.
+ */
+QStringRef QXmlStreamReader::processingInstructionTarget() const
+{
+    Q_D(const QXmlStreamReader);
+    return d->processingInstructionTarget;
+}
+
+/*!
+  Returns the data of a ProcessingInstruction.
+ */
+QStringRef QXmlStreamReader::processingInstructionData() const
+{
+    Q_D(const QXmlStreamReader);
+    return d->processingInstructionData;
+}
+
+
+
+/*!
+  Returns the local name of a StartElement, EndElement, or an EntityReference.
+
+  \sa namespaceUri(), qualifiedName()
+ */
+QStringRef QXmlStreamReader::name() const
+{
+    Q_D(const QXmlStreamReader);
+    return d->name;
+}
+
+/*!
+  Returns the namespaceUri of a StartElement or EndElement.
+
+  \sa name(), qualifiedName()
+ */
+QStringRef QXmlStreamReader::namespaceUri() const
+{
+    Q_D(const QXmlStreamReader);
+    return d->namespaceUri;
+}
+
+/*!
+  Returns the qualified name of a StartElement or EndElement;
+
+  A qualified name is the raw name of an element in the XML data. It
+  consists of the namespace prefix, followed by colon, followed by the
+  element's local name. Since the namespace prefix is not unique (the
+  same prefix can point to different namespaces and different prefixes
+  can point to the same namespace), you shouldn't use qualifiedName(),
+  but the resolved namespaceUri() and the attribute's local name().
+
+   \sa name(), prefix(), namespaceUri()
+ */
+QStringRef QXmlStreamReader::qualifiedName() const
+{
+    Q_D(const QXmlStreamReader);
+    return d->qualifiedName;
+}
+
+
+
+/*!
+  \since 4.4
+
+  Returns the prefix of a StartElement or EndElement.
+
+  \sa name(), qualifiedName()
+*/
+QStringRef QXmlStreamReader::prefix() const
+{
+    Q_D(const QXmlStreamReader);
+    return d->prefix;
+}
+
+/*!
+  Returns the attributes of a StartElement.
+ */
+QXmlStreamAttributes QXmlStreamReader::attributes() const
+{
+    Q_D(const QXmlStreamReader);
+    return d->attributes;
+}
+
+#endif // QT_NO_XMLSTREAMREADER
+
+/*!
+    \class QXmlStreamAttribute
+    \since 4.3
+    \reentrant
+    \brief The QXmlStreamAttribute class represents a single XML attribute
+
+    \ingroup xml-tools
+
+    An attribute consists of an optionally empty namespaceUri(), a
+    name(), a value(), and an isDefault() attribute.
+
+    The raw XML attribute name is returned as qualifiedName().
+*/
+
+/*!
+  Creates an empty attribute.
+ */
+QXmlStreamAttribute::QXmlStreamAttribute()
+{
+    m_isDefault = false;
+}
+
+/*!
+  Destructs an attribute.
+ */
+QXmlStreamAttribute::~QXmlStreamAttribute()
+{
+}
+
+/*!  Constructs an attribute in the namespace described with \a
+  namespaceUri with \a name and value \a value.
+ */
+QXmlStreamAttribute::QXmlStreamAttribute(const QString &namespaceUri, const QString &name, const QString &value)
+{
+    m_namespaceUri = QXmlStreamStringRef(QStringRef(&namespaceUri));
+    m_name = m_qualifiedName = QXmlStreamStringRef(QStringRef(&name));
+    m_value = QXmlStreamStringRef(QStringRef(&value));
+    m_namespaceUri = QXmlStreamStringRef(QStringRef(&namespaceUri));
+}
+
+/*!
+    Constructs an attribute with qualified name \a qualifiedName and value \a value.
+ */
+QXmlStreamAttribute::QXmlStreamAttribute(const QString &qualifiedName, const QString &value)
+{
+    int colon = qualifiedName.indexOf(QLatin1Char(':'));
+    m_name = QXmlStreamStringRef(QStringRef(&qualifiedName,
+                                            colon + 1,
+                                            qualifiedName.size() - (colon + 1)));
+    m_qualifiedName = QXmlStreamStringRef(QStringRef(&qualifiedName));
+    m_value = QXmlStreamStringRef(QStringRef(&value));
+}
+
+/*! \fn QStringRef QXmlStreamAttribute::namespaceUri() const
+
+   Returns the attribute's resolved namespaceUri, or an empty string
+   reference if the attribute does not have a defined namespace.
+ */
+/*! \fn QStringRef QXmlStreamAttribute::name() const
+   Returns the attribute's local name.
+ */
+/*! \fn QStringRef QXmlStreamAttribute::qualifiedName() const
+   Returns the attribute's qualified name.
+
+   A qualified name is the raw name of an attribute in the XML
+   data. It consists of the namespace prefix(), followed by colon,
+   followed by the attribute's local name(). Since the namespace prefix
+   is not unique (the same prefix can point to different namespaces
+   and different prefixes can point to the same namespace), you
+   shouldn't use qualifiedName(), but the resolved namespaceUri() and
+   the attribute's local name().
+ */
+/*!
+   \fn QStringRef QXmlStreamAttribute::prefix() const
+   \since 4.4
+   Returns the attribute's namespace prefix.
+
+   \sa name(), qualifiedName()
+
+*/
+
+/*! \fn QStringRef QXmlStreamAttribute::value() const
+   Returns the attribute's value.
+ */
+
+/*! \fn bool QXmlStreamAttribute::isDefault() const
+
+   Returns true if the parser added this attribute with a default
+   value following an ATTLIST declaration in the DTD; otherwise
+   returns false.
+*/
+/*! \fn bool QXmlStreamAttribute::operator==(const QXmlStreamAttribute &other) const
+
+    Compares this attribute with \a other and returns true if they are
+    equal; otherwise returns false.
+ */
+/*! \fn bool QXmlStreamAttribute::operator!=(const QXmlStreamAttribute &other) const
+
+    Compares this attribute with \a other and returns true if they are
+    not equal; otherwise returns false.
+ */
+
+
+/*!
+  Creates a copy of \a other.
+ */
+QXmlStreamAttribute::QXmlStreamAttribute(const QXmlStreamAttribute &other)
+{
+    *this = other;
+}
+
+/*!
+  Assigns \a other to this attribute.
+ */
+QXmlStreamAttribute& QXmlStreamAttribute::operator=(const QXmlStreamAttribute &other)
+{
+    m_name = other.m_name;
+    m_namespaceUri = other.m_namespaceUri;
+    m_qualifiedName = other.m_qualifiedName;
+    m_value = other.m_value;
+    m_isDefault = other.m_isDefault;
+    return *this;
+}
+
+
+/*!
+    \class QXmlStreamAttributes
+    \since 4.3
+    \reentrant
+    \brief The QXmlStreamAttributes class represents a vector of QXmlStreamAttribute.
+
+    Attributes are returned by a QXmlStreamReader in
+    \l{QXmlStreamReader::attributes()} {attributes()} when the reader
+    reports a \l {QXmlStreamReader::StartElement}{start element}. The
+    class can also be used with a QXmlStreamWriter as an argument to
+    \l {QXmlStreamWriter::writeAttributes()}{writeAttributes()}.
+
+    The convenience function value() loops over the vector and returns
+    an attribute value for a given namespaceUri and an attribute's
+    name.
+
+    New attributes can be added with append().
+
+    \ingroup xml-tools
+*/
+
+/*!
+    \fn void QXmlStreamAttributes::append(const QXmlStreamAttribute &attribute)
+
+    Appends the given \a attribute to the end of the vector.
+
+    \sa QVector::append()
+*/
+
+
+/*!
+    \typedef QXmlStreamNotationDeclarations
+    \relates QXmlStreamNotationDeclaration
+
+    Synonym for QVector<QXmlStreamNotationDeclaration>.
+*/
+
+
+/*!
+    \class QXmlStreamNotationDeclaration
+    \since 4.3
+    \reentrant
+    \brief The QXmlStreamNotationDeclaration class represents a DTD notation declaration.
+
+    \ingroup xml-tools
+
+    An notation declaration consists of a name(), a systemId(), and a publicId().
+*/
+
+/*!
+  Creates an empty notation declaration.
+*/
+QXmlStreamNotationDeclaration::QXmlStreamNotationDeclaration()
+{
+}
+/*!
+  Creates a copy of \a other.
+ */
+QXmlStreamNotationDeclaration::QXmlStreamNotationDeclaration(const QXmlStreamNotationDeclaration &other)
+{
+    *this = other;
+}
+
+/*!
+  Assigns \a other to this notation declaration.
+ */
+QXmlStreamNotationDeclaration& QXmlStreamNotationDeclaration::operator=(const QXmlStreamNotationDeclaration &other)
+{
+    m_name = other.m_name;
+    m_systemId = other.m_systemId;
+    m_publicId = other.m_publicId;
+    return *this;
+}
+
+/*!
+Destructs this notation declaration.
+*/
+QXmlStreamNotationDeclaration::~QXmlStreamNotationDeclaration()
+{
+}
+
+/*! \fn QStringRef QXmlStreamNotationDeclaration::name() const
+
+Returns the notation name.
+*/
+/*! \fn QStringRef QXmlStreamNotationDeclaration::systemId() const
+
+Returns the system identifier.
+*/
+/*! \fn QStringRef QXmlStreamNotationDeclaration::publicId() const
+
+Returns the public identifier.
+*/
+
+/*! \fn inline bool QXmlStreamNotationDeclaration::operator==(const QXmlStreamNotationDeclaration &other) const
+
+    Compares this notation declaration with \a other and returns true
+    if they are equal; otherwise returns false.
+ */
+/*! \fn inline bool QXmlStreamNotationDeclaration::operator!=(const QXmlStreamNotationDeclaration &other) const
+
+    Compares this notation declaration with \a other and returns true
+    if they are not equal; otherwise returns false.
+ */
+
+/*!
+    \typedef QXmlStreamNamespaceDeclarations
+    \relates QXmlStreamNamespaceDeclaration
+
+    Synonym for QVector<QXmlStreamNamespaceDeclaration>.
+*/
+
+/*!
+    \class QXmlStreamNamespaceDeclaration
+    \since 4.3
+    \reentrant
+    \brief The QXmlStreamNamespaceDeclaration class represents a namespace declaration.
+
+    \ingroup xml-tools
+
+    An namespace declaration consists of a prefix() and a namespaceUri().
+*/
+/*! \fn inline bool QXmlStreamNamespaceDeclaration::operator==(const QXmlStreamNamespaceDeclaration &other) const
+
+    Compares this namespace declaration with \a other and returns true
+    if they are equal; otherwise returns false.
+ */
+/*! \fn inline bool QXmlStreamNamespaceDeclaration::operator!=(const QXmlStreamNamespaceDeclaration &other) const
+
+    Compares this namespace declaration with \a other and returns true
+    if they are not equal; otherwise returns false.
+ */
+
+/*!
+  Creates an empty namespace declaration.
+*/
+QXmlStreamNamespaceDeclaration::QXmlStreamNamespaceDeclaration()
+{
+}
+
+/*!
+  \since 4.4
+
+  Creates a namespace declaration with \a prefix and \a namespaceUri.
+*/
+QXmlStreamNamespaceDeclaration::QXmlStreamNamespaceDeclaration(const QString &prefix, const QString &namespaceUri)
+{
+    m_prefix = prefix;
+    m_namespaceUri = namespaceUri;
+}
+
+/*!
+  Creates a copy of \a other.
+ */
+QXmlStreamNamespaceDeclaration::QXmlStreamNamespaceDeclaration(const QXmlStreamNamespaceDeclaration &other)
+{
+    *this = other;
+}
+
+/*!
+  Assigns \a other to this namespace declaration.
+ */
+QXmlStreamNamespaceDeclaration& QXmlStreamNamespaceDeclaration::operator=(const QXmlStreamNamespaceDeclaration &other)
+{
+    m_prefix = other.m_prefix;
+    m_namespaceUri = other.m_namespaceUri;
+    return *this;
+}
+/*!
+Destructs this namespace declaration.
+*/
+QXmlStreamNamespaceDeclaration::~QXmlStreamNamespaceDeclaration()
+{
+}
+
+/*! \fn QStringRef QXmlStreamNamespaceDeclaration::prefix() const
+
+Returns the prefix.
+*/
+/*! \fn QStringRef QXmlStreamNamespaceDeclaration::namespaceUri() const
+
+Returns the namespaceUri.
+*/
+
+
+
+
+/*!
+    \typedef QXmlStreamEntityDeclarations
+    \relates QXmlStreamEntityDeclaration
+
+    Synonym for QVector<QXmlStreamEntityDeclaration>.
+*/
+
+/*!
+    \class QXmlStreamStringRef
+    \since 4.3
+    \internal
+*/
+
+/*!
+    \class QXmlStreamEntityDeclaration
+    \since 4.3
+    \reentrant
+    \brief The QXmlStreamEntityDeclaration class represents a DTD entity declaration.
+
+    \ingroup xml-tools
+
+    An entity declaration consists of a name(), a notationName(), a
+    systemId(), a publicId(), and a value().
+*/
+
+/*!
+  Creates an empty entity declaration.
+*/
+QXmlStreamEntityDeclaration::QXmlStreamEntityDeclaration()
+{
+}
+
+/*!
+  Creates a copy of \a other.
+ */
+QXmlStreamEntityDeclaration::QXmlStreamEntityDeclaration(const QXmlStreamEntityDeclaration &other)
+{
+    *this = other;
+}
+
+/*!
+  Assigns \a other to this entity declaration.
+ */
+QXmlStreamEntityDeclaration& QXmlStreamEntityDeclaration::operator=(const QXmlStreamEntityDeclaration &other)
+{
+    m_name = other.m_name;
+    m_notationName = other.m_notationName;
+    m_systemId = other.m_systemId;
+    m_publicId = other.m_publicId;
+    m_value = other.m_value;
+    return *this;
+}
+
+/*!
+  Destructs this entity declaration.
+*/
+QXmlStreamEntityDeclaration::~QXmlStreamEntityDeclaration()
+{
+}
+
+/*! \fn QStringRef QXmlStreamEntityDeclaration::name() const
+
+Returns the entity name.
+*/
+/*! \fn QStringRef QXmlStreamEntityDeclaration::notationName() const
+
+Returns the notation name.
+*/
+/*! \fn QStringRef QXmlStreamEntityDeclaration::systemId() const
+
+Returns the system identifier.
+*/
+/*! \fn QStringRef QXmlStreamEntityDeclaration::publicId() const
+
+Returns the public identifier.
+*/
+/*! \fn QStringRef QXmlStreamEntityDeclaration::value() const
+
+Returns the entity's value.
+*/
+
+/*! \fn bool QXmlStreamEntityDeclaration::operator==(const QXmlStreamEntityDeclaration &other) const
+
+    Compares this entity declaration with \a other and returns true if
+    they are equal; otherwise returns false.
+ */
+/*! \fn bool QXmlStreamEntityDeclaration::operator!=(const QXmlStreamEntityDeclaration &other) const
+
+    Compares this entity declaration with \a other and returns true if
+    they are not equal; otherwise returns false.
+ */
+
+/*!  Returns the value of the attribute \a name in the namespace
+  described with \a namespaceUri, or an empty string reference if the
+  attribute is not defined. The \a namespaceUri can be empty.
+ */
+QStringRef QXmlStreamAttributes::value(const QString &namespaceUri, const QString &name) const
+{
+    for (int i = 0; i < size(); ++i) {
+        const QXmlStreamAttribute &attribute = at(i);
+        if (attribute.name() == name && attribute.namespaceUri() == namespaceUri)
+            return attribute.value();
+    }
+    return QStringRef();
+}
+
+/*!\overload
+  Returns the value of the attribute \a name in the namespace
+  described with \a namespaceUri, or an empty string reference if the
+  attribute is not defined. The \a namespaceUri can be empty.
+ */
+QStringRef QXmlStreamAttributes::value(const QString &namespaceUri, const QLatin1String &name) const
+{
+    for (int i = 0; i < size(); ++i) {
+        const QXmlStreamAttribute &attribute = at(i);
+        if (attribute.name() == name && attribute.namespaceUri() == namespaceUri)
+            return attribute.value();
+    }
+    return QStringRef();
+}
+
+/*!\overload
+  Returns the value of the attribute \a name in the namespace
+  described with \a namespaceUri, or an empty string reference if the
+  attribute is not defined. The \a namespaceUri can be empty.
+ */
+QStringRef QXmlStreamAttributes::value(const QLatin1String &namespaceUri, const QLatin1String &name) const
+{
+    for (int i = 0; i < size(); ++i) {
+        const QXmlStreamAttribute &attribute = at(i);
+        if (attribute.name() == name && attribute.namespaceUri() == namespaceUri)
+            return attribute.value();
+    }
+    return QStringRef();
+}
+
+/*!\overload
+
+  Returns the value of the attribute with qualified name \a
+  qualifiedName , or an empty string reference if the attribute is not
+  defined. A qualified name is the raw name of an attribute in the XML
+  data. It consists of the namespace prefix, followed by colon,
+  followed by the attribute's local name. Since the namespace prefix
+  is not unique (the same prefix can point to different namespaces and
+  different prefixes can point to the same namespace), you shouldn't
+  use qualified names, but a resolved namespaceUri and the attribute's
+  local name.
+ */
+QStringRef QXmlStreamAttributes::value(const QString &qualifiedName) const
+{
+    for (int i = 0; i < size(); ++i) {
+        const QXmlStreamAttribute &attribute = at(i);
+        if (attribute.qualifiedName() == qualifiedName)
+            return attribute.value();
+    }
+    return QStringRef();
+}
+
+/*!\overload
+
+  Returns the value of the attribute with qualified name \a
+  qualifiedName , or an empty string reference if the attribute is not
+  defined. A qualified name is the raw name of an attribute in the XML
+  data. It consists of the namespace prefix, followed by colon,
+  followed by the attribute's local name. Since the namespace prefix
+  is not unique (the same prefix can point to different namespaces and
+  different prefixes can point to the same namespace), you shouldn't
+  use qualified names, but a resolved namespaceUri and the attribute's
+  local name.
+ */
+QStringRef QXmlStreamAttributes::value(const QLatin1String &qualifiedName) const
+{
+    for (int i = 0; i < size(); ++i) {
+        const QXmlStreamAttribute &attribute = at(i);
+        if (attribute.qualifiedName() == qualifiedName)
+            return attribute.value();
+    }
+    return QStringRef();
+}
+
+/*!Appends a new attribute with \a name in the namespace
+  described with \a namespaceUri, and value \a value. The \a
+  namespaceUri can be empty.
+ */
+void QXmlStreamAttributes::append(const QString &namespaceUri, const QString &name, const QString &value)
+{
+    append(QXmlStreamAttribute(namespaceUri, name, value));
+}
+
+/*!\overload
+  Appends a new attribute with qualified name \a qualifiedName and
+  value \a value.
+ */
+void QXmlStreamAttributes::append(const QString &qualifiedName, const QString &value)
+{
+    append(QXmlStreamAttribute(qualifiedName, value));
+}
+
+#ifndef QT_NO_XMLSTREAMREADER
+
+/*! \fn bool QXmlStreamReader::isStartDocument() const
+  Returns true if tokenType() equals \l StartDocument; otherwise returns false.
+*/
+/*! \fn bool QXmlStreamReader::isEndDocument() const
+  Returns true if tokenType() equals \l EndDocument; otherwise returns false.
+*/
+/*! \fn bool QXmlStreamReader::isStartElement() const
+  Returns true if tokenType() equals \l StartElement; otherwise returns false.
+*/
+/*! \fn bool QXmlStreamReader::isEndElement() const
+  Returns true if tokenType() equals \l EndElement; otherwise returns false.
+*/
+/*! \fn bool QXmlStreamReader::isCharacters() const
+  Returns true if tokenType() equals \l Characters; otherwise returns false.
+
+  \sa isWhitespace(), isCDATA()
+*/
+/*! \fn bool QXmlStreamReader::isComment() const
+  Returns true if tokenType() equals \l Comment; otherwise returns false.
+*/
+/*! \fn bool QXmlStreamReader::isDTD() const
+  Returns true if tokenType() equals \l DTD; otherwise returns false.
+*/
+/*! \fn bool QXmlStreamReader::isEntityReference() const
+  Returns true if tokenType() equals \l EntityReference; otherwise returns false.
+*/
+/*! \fn bool QXmlStreamReader::isProcessingInstruction() const
+  Returns true if tokenType() equals \l ProcessingInstruction; otherwise returns false.
+*/
+
+/*!  Returns true if the reader reports characters that only consist
+  of white-space; otherwise returns false.
+
+  \sa isCharacters(), text()
+*/
+bool QXmlStreamReader::isWhitespace() const
+{
+    Q_D(const QXmlStreamReader);
+    return d->type == QXmlStreamReader::Characters && d->isWhitespace;
+}
+
+/*!  Returns true if the reader reports characters that stem from a
+  CDATA section; otherwise returns false.
+
+  \sa isCharacters(), text()
+*/
+bool QXmlStreamReader::isCDATA() const
+{
+    Q_D(const QXmlStreamReader);
+    return d->type == QXmlStreamReader::Characters && d->isCDATA;
+}
+
+
+
+/*!
+  Returns true if this document has been declared standalone in the
+  XML declaration; otherwise returns false.
+
+  If no XML declaration has been parsed, this function returns false.
+ */
+bool QXmlStreamReader::isStandaloneDocument() const
+{
+    Q_D(const QXmlStreamReader);
+    return d->standalone;
+}
+
+
+/*!
+     \since 4.4
+
+     If the state() is \l StartDocument, this function returns the
+     version string as specified in the XML declaration.
+     Otherwise an empty string is returned.
+ */
+QStringRef QXmlStreamReader::documentVersion() const
+{
+   Q_D(const QXmlStreamReader);
+   if (d->type == QXmlStreamReader::StartDocument)
+       return d->documentVersion;
+   return QStringRef();
+}
+
+/*!
+     \since 4.4
+
+     If the state() is \l StartDocument, this function returns the
+     encoding string as specified in the XML declaration.
+     Otherwise an empty string is returned.
+ */
+QStringRef QXmlStreamReader::documentEncoding() const
+{
+   Q_D(const QXmlStreamReader);
+   if (d->type == QXmlStreamReader::StartDocument)
+       return d->documentEncoding;
+   return QStringRef();
+}
+
+#endif // QT_NO_XMLSTREAMREADER
+
+/*!
+  \class QXmlStreamWriter
+  \since 4.3
+  \reentrant
+
+  \brief The QXmlStreamWriter class provides an XML writer with a
+  simple streaming API.
+
+
+  \inmodule QtXml
+  \ingroup xml-tools
+
+  QXmlStreamWriter is the counterpart to QXmlStreamReader for writing
+  XML. Like its related class, it operates on a QIODevice specified
+  with setDevice(). The API is simple and straightforward: for every
+  XML token or event you want to write, the writer provides a
+  specialized function.
+
+  You start a document with writeStartDocument() and end it with
+  writeEndDocument(). This will implicitly close all remaining open
+  tags.
+
+  Element tags are opened with writeStartElement() followed by
+  writeAttribute() or writeAttributes(), element content, and then
+  writeEndElement(). A shorter form writeEmptyElement() can be used
+  to write empty elements, followed by writeAttributes().
+
+  Element content consists of either characters, entity references or
+  nested elements. It is written with writeCharacters(), which also
+  takes care of escaping all forbidden characters and character
+  sequences, writeEntityReference(), or subsequent calls to
+  writeStartElement(). A convenience method writeTextElement() can be
+  used for writing terminal elements that contain nothing but text.
+
+  The following abridged code snippet shows the basic use of the class
+  to write formatted XML with indentation:
+
+  \snippet doc/src/snippets/qxmlstreamwriter/main.cpp start stream
+  \dots
+  \snippet doc/src/snippets/qxmlstreamwriter/main.cpp write element
+  \dots
+  \snippet doc/src/snippets/qxmlstreamwriter/main.cpp finish stream
+
+  QXmlStreamWriter takes care of prefixing namespaces, all you have to
+  do is specify the \c namespaceUri when writing elements or
+  attributes. If you must conform to certain prefixes, you can force
+  the writer to use them by declaring the namespaces manually with
+  either writeNamespace() or writeDefaultNamespace(). Alternatively,
+  you can bypass the stream writer's namespace support and use
+  overloaded methods that take a qualified name instead. The namespace
+  \e http://www.w3.org/XML/1998/namespace is implicit and mapped to the
+  prefix \e xml.
+
+  The stream writer can automatically format the generated XML data by
+  adding line-breaks and indentation to empty sections between
+  elements, making the XML data more readable for humans and easier to
+  work with for most source code management systems. The feature can
+  be turned on with the \l autoFormatting property, and customized
+  with the \l autoFormattingIndent property.
+
+  Other functions are writeCDATA(), writeComment(),
+  writeProcessingInstruction(), and writeDTD(). Chaining of XML
+  streams is supported with writeCurrentToken().
+
+  By default, QXmlStreamWriter encodes XML in UTF-8. Different
+  encodings can be enforced using setCodec().
+
+  The \l{QXmlStream Bookmarks Example} illustrates how to use a
+  stream writer to write an XML bookmark file (XBEL) that
+  was previously read in by a QXmlStreamReader.
+
+*/
+
+#ifndef QT_NO_XMLSTREAMWRITER
+
+class QXmlStreamWriterPrivate : public QXmlStreamPrivateTagStack {
+    QXmlStreamWriter *q_ptr;
+    Q_DECLARE_PUBLIC(QXmlStreamWriter)
+public:
+    QXmlStreamWriterPrivate(QXmlStreamWriter *q);
+    ~QXmlStreamWriterPrivate() {
+        if (deleteDevice)
+            delete device;
+#ifndef QT_NO_TEXTCODEC
+        delete encoder;
+#endif
+    }
+
+    void write(const QStringRef &);
+    void write(const QString &);
+    void writeEscaped(const QString &, bool escapeWhitespace = false);
+    void write(const char *s);
+    bool finishStartElement(bool contents = true);
+    void writeStartElement(const QString &namespaceUri, const QString &name);
+    QIODevice *device;
+    QString *stringDevice;
+    uint deleteDevice :1;
+    uint inStartElement :1;
+    uint inEmptyElement :1;
+    uint lastWasStartElement :1;
+    uint wroteSomething :1;
+    uint autoFormatting :1;
+    QByteArray autoFormattingIndent;
+    NamespaceDeclaration emptyNamespace;
+    int lastNamespaceDeclaration;
+
+#ifndef QT_NO_TEXTCODEC
+    QTextCodec *codec;
+    QTextEncoder *encoder;
+#endif
+
+    NamespaceDeclaration &findNamespace(const QString &namespaceUri, bool writeDeclaration = false, bool noDefault = false);
+    void writeNamespaceDeclaration(const NamespaceDeclaration &namespaceDeclaration);
+
+    int namespacePrefixCount;
+
+    void indent(int level);
+};
+
+
+QXmlStreamWriterPrivate::QXmlStreamWriterPrivate(QXmlStreamWriter *q)
+    :autoFormattingIndent(4, ' ')
+{
+    q_ptr = q;
+    device = 0;
+    stringDevice = 0;
+    deleteDevice = false;
+#ifndef QT_NO_TEXTCODEC
+    codec = QTextCodec::codecForMib(106); // utf8
+    encoder = codec->makeEncoder();
+    encoder->fromUnicode(QLatin1String("")); // no byte order mark for utf8
+#endif
+    inStartElement = inEmptyElement = false;
+    wroteSomething = false;
+    lastWasStartElement = false;
+    lastNamespaceDeclaration = 1;
+    autoFormatting = false;
+    namespacePrefixCount = 0;
+}
+
+void QXmlStreamWriterPrivate::write(const QStringRef &s)
+{
+    if (device) {
+#ifdef QT_NO_TEXTCODEC
+        device->write(s.toString().toLatin1(), s.size());
+#else
+        device->write(encoder->fromUnicode(s.constData(), s.size()));
+#endif
+    }
+    else if (stringDevice)
+        s.appendTo(stringDevice);
+    else
+        qWarning("QXmlStreamWriter: No device");
+}
+
+void QXmlStreamWriterPrivate::write(const QString &s)
+{
+    if (device) {
+#ifdef QT_NO_TEXTCODEC
+        device->write(s.toLatin1(), s.size());
+#else
+        device->write(encoder->fromUnicode(s));
+#endif
+    }
+    else if (stringDevice)
+        stringDevice->append(s);
+    else
+        qWarning("QXmlStreamWriter: No device");
+}
+
+void QXmlStreamWriterPrivate::writeEscaped(const QString &s, bool escapeWhitespace)
+{
+    QString escaped;
+    escaped.reserve(s.size());
+    for ( int i = 0; i < s.size(); ++i ) {
+        QChar c = s.at(i);
+        if (c.unicode() == '<' )
+            escaped.append(QLatin1String("&lt;"));
+        else if (c.unicode() == '>' )
+            escaped.append(QLatin1String("&gt;"));
+        else if (c.unicode() == '&' )
+            escaped.append(QLatin1String("&amp;"));
+        else if (c.unicode() == '\"' )
+            escaped.append(QLatin1String("&quot;"));
+        else if (escapeWhitespace && c.isSpace()) {
+            if (c.unicode() == '\n')
+                escaped.append(QLatin1String("&#10;"));
+            else if (c.unicode() == '\r')
+                escaped.append(QLatin1String("&#13;"));
+            else if (c.unicode() == '\t')
+                escaped.append(QLatin1String("&#9;"));
+            else
+                escaped += c;
+        } else {
+            escaped += QChar(c);
+        }
+    }
+    if (device) {
+#ifdef QT_NO_TEXTCODEC
+        device->write(escaped.toLatin1(), escaped.size());
+#else
+        device->write(encoder->fromUnicode(escaped));
+#endif
+    }
+    else if (stringDevice)
+        stringDevice->append(escaped);
+    else
+        qWarning("QXmlStreamWriter: No device");
+}
+
+
+void QXmlStreamWriterPrivate::write(const char *s)
+{
+    if (device) {
+#ifndef QT_NO_TEXTCODEC
+        if (codec->mibEnum() != 106)
+            device->write(encoder->fromUnicode(QLatin1String(s)));
+        else
+#endif
+            device->write(s, strlen(s));
+    } else if (stringDevice) {
+        stringDevice->append(QLatin1String(s));
+    } else
+        qWarning("QXmlStreamWriter: No device");
+}
+
+void QXmlStreamWriterPrivate::writeNamespaceDeclaration(const NamespaceDeclaration &namespaceDeclaration) {
+    if (namespaceDeclaration.prefix.isEmpty()) {
+        write(" xmlns=\"");
+        write(namespaceDeclaration.namespaceUri);
+        write("\"");
+    } else {
+        write(" xmlns:");
+        write(namespaceDeclaration.prefix);
+        write("=\"");
+        write(namespaceDeclaration.namespaceUri);
+        write("\"");
+    }
+}
+
+bool QXmlStreamWriterPrivate::finishStartElement(bool contents)
+{
+    bool hadSomethingWritten = wroteSomething;
+    wroteSomething = contents;
+    if (!inStartElement)
+        return hadSomethingWritten;
+
+    if (inEmptyElement) {
+        write("/>");
+        QXmlStreamWriterPrivate::Tag &tag = tagStack_pop();
+        lastNamespaceDeclaration = tag.namespaceDeclarationsSize;
+        lastWasStartElement = false;
+    } else {
+        write(">");
+    }
+    inStartElement = inEmptyElement = false;
+    lastNamespaceDeclaration = namespaceDeclarations.size();
+    return hadSomethingWritten;
+}
+
+QXmlStreamPrivateTagStack::NamespaceDeclaration &QXmlStreamWriterPrivate::findNamespace(const QString &namespaceUri, bool writeDeclaration, bool noDefault)
+{
+    for (int j = namespaceDeclarations.size() - 1; j >= 0; --j) {
+        NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations[j];
+        if (namespaceDeclaration.namespaceUri == namespaceUri) {
+            if (!noDefault || !namespaceDeclaration.prefix.isEmpty())
+                return namespaceDeclaration;
+        }
+    }
+    if (namespaceUri.isEmpty())
+        return emptyNamespace;
+    NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.push();
+    if (namespaceUri.isEmpty()) {
+        namespaceDeclaration.prefix.clear();
+    } else {
+        QString s;
+        int n = ++namespacePrefixCount;
+        forever {
+            s = QLatin1Char('n') + QString::number(n++);
+            int j = namespaceDeclarations.size() - 2;
+            while (j >= 0 && namespaceDeclarations.at(j).prefix != s)
+                --j;
+            if (j < 0)
+                break;
+	}
+        namespaceDeclaration.prefix = addToStringStorage(s);
+    }
+    namespaceDeclaration.namespaceUri = addToStringStorage(namespaceUri);
+    if (writeDeclaration)
+        writeNamespaceDeclaration(namespaceDeclaration);
+    return namespaceDeclaration;
+}
+
+
+
+void QXmlStreamWriterPrivate::indent(int level)
+{
+    write("\n");
+    for (int i = level; i > 0; --i)
+        write(autoFormattingIndent.constData());
+}
+
+
+/*!
+  Constructs a stream writer.
+
+  \sa setDevice()
+ */
+QXmlStreamWriter::QXmlStreamWriter()
+    : d_ptr(new QXmlStreamWriterPrivate(this))
+{
+}
+
+/*!
+  Constructs a stream writer that writes into \a device;
+ */
+QXmlStreamWriter::QXmlStreamWriter(QIODevice *device)
+    : d_ptr(new QXmlStreamWriterPrivate(this))
+{
+    Q_D(QXmlStreamWriter);
+    d->device = device;
+}
+
+/*!  Constructs a stream writer that writes into \a array. This is the
+  same as creating an xml writer that operates on a QBuffer device
+  which in turn operates on \a array.
+ */
+QXmlStreamWriter::QXmlStreamWriter(QByteArray *array)
+    : d_ptr(new QXmlStreamWriterPrivate(this))
+{
+    Q_D(QXmlStreamWriter);
+    d->device = new QBuffer(array);
+    d->device->open(QIODevice::WriteOnly);
+    d->deleteDevice = true;
+}
+
+
+/*!  Constructs a stream writer that writes into \a string.
+ */
+QXmlStreamWriter::QXmlStreamWriter(QString *string)
+    : d_ptr(new QXmlStreamWriterPrivate(this))
+{
+    Q_D(QXmlStreamWriter);
+    d->stringDevice = string;
+}
+
+/*!
+    Destructor.
+*/
+QXmlStreamWriter::~QXmlStreamWriter()
+{
+}
+
+
+/*!
+    Sets the current device to \a device. If you want the stream to
+    write into a QByteArray, you can create a QBuffer device.
+
+    \sa device()
+*/
+void QXmlStreamWriter::setDevice(QIODevice *device)
+{
+    Q_D(QXmlStreamWriter);
+    if (device == d->device)
+        return;
+    d->stringDevice = 0;
+    if (d->deleteDevice) {
+        delete d->device;
+        d->deleteDevice = false;
+    }
+    d->device = device;
+}
+
+/*!
+    Returns the current device associated with the QXmlStreamWriter,
+    or 0 if no device has been assigned.
+
+    \sa setDevice()
+*/
+QIODevice *QXmlStreamWriter::device() const
+{
+    Q_D(const QXmlStreamWriter);
+    return d->device;
+}
+
+
+#ifndef QT_NO_TEXTCODEC
+/*!
+    Sets the codec for this stream to \a codec. The codec is used for
+    encoding any data that is written. By default, QXmlStreamWriter
+    uses UTF-8.
+
+    The encoding information is stored in the initial xml tag which
+    gets written when you call writeStartDocument(). Call this
+    function before calling writeStartDocument().
+
+    \sa codec()
+*/
+void QXmlStreamWriter::setCodec(QTextCodec *codec)
+{
+    Q_D(QXmlStreamWriter);
+    if (codec) {
+        d->codec = codec;
+        delete d->encoder;
+        d->encoder = codec->makeEncoder();
+        if (codec->mibEnum() == 106)
+            d->encoder->fromUnicode(QLatin1String("")); // no byte order mark for utf8
+    }
+}
+
+/*!
+    Sets the codec for this stream to the QTextCodec for the encoding
+    specified by \a codecName. Common values for \c codecName include
+    "ISO 8859-1", "UTF-8", and "UTF-16". If the encoding isn't
+    recognized, nothing happens.
+
+    \sa QTextCodec::codecForName()
+*/
+void QXmlStreamWriter::setCodec(const char *codecName)
+{
+    setCodec(QTextCodec::codecForName(codecName));
+}
+
+/*!
+    Returns the codec that is currently assigned to the stream.
+
+    \sa setCodec()
+*/
+QTextCodec *QXmlStreamWriter::codec() const
+{
+    Q_D(const QXmlStreamWriter);
+    return d->codec;
+}
+#endif // QT_NO_TEXTCODEC
+
+/*!
+    \property  QXmlStreamWriter::autoFormatting
+    \since 4.4
+    the auto-formatting flag of the stream writer
+
+    This property controls whether or not the stream writer
+    automatically formats the generated XML data. If enabled, the
+    writer automatically adds line-breaks and indentation to empty
+    sections between elements (ignorable whitespace). The main purpose
+    of auto-formatting is to split the data into several lines, and to
+    increase readability for a human reader. The indentation depth can
+    be controlled through the \l autoFormattingIndent property.
+
+    By default, auto-formatting is disabled.
+*/
+
+/*!
+ \since 4.4
+
+ Enables auto formatting if \a enable is \c true, otherwise
+ disables it.
+
+ The default value is \c false.
+ */
+void QXmlStreamWriter::setAutoFormatting(bool enable)
+{
+    Q_D(QXmlStreamWriter);
+    d->autoFormatting = enable;
+}
+
+/*!
+ \since 4.4
+
+ Returns \c true if auto formattting is enabled, otherwise \c false.
+ */
+bool QXmlStreamWriter::autoFormatting() const
+{
+    Q_D(const QXmlStreamWriter);
+    return d->autoFormatting;
+}
+
+/*!
+    \property QXmlStreamWriter::autoFormattingIndent
+    \since 4.4
+
+    \brief the number of spaces or tabs used for indentation when
+    auto-formatting is enabled.  Positive numbers indicate spaces,
+    negative numbers tabs.
+
+    The default indentation is 4.
+
+    \sa autoFormatting
+*/
+
+
+void QXmlStreamWriter::setAutoFormattingIndent(int spacesOrTabs)
+{
+    Q_D(QXmlStreamWriter);
+    d->autoFormattingIndent = QByteArray(qAbs(spacesOrTabs), spacesOrTabs >= 0 ? ' ' : '\t');
+}
+
+int QXmlStreamWriter::autoFormattingIndent() const
+{
+    Q_D(const QXmlStreamWriter);
+    return d->autoFormattingIndent.count(' ') - d->autoFormattingIndent.count('\t');
+}
+
+
+/*!
+  \overload
+  Writes an attribute with \a qualifiedName and \a value.
+
+
+  This function can only be called after writeStartElement() before
+  any content is written, or after writeEmptyElement().
+ */
+void QXmlStreamWriter::writeAttribute(const QString &qualifiedName, const QString &value)
+{
+    Q_D(QXmlStreamWriter);
+    Q_ASSERT(d->inStartElement);
+    Q_ASSERT(qualifiedName.count(QLatin1Char(':')) <= 1);
+    d->write(" ");
+    d->write(qualifiedName);
+    d->write("=\"");
+    d->writeEscaped(value, true);
+    d->write("\"");
+}
+
+/*!  Writes an attribute with \a name and \a value, prefixed for
+  the specified \a namespaceUri. If the namespace has not been
+  declared yet, QXmlStreamWriter will generate a namespace declaration
+  for it.
+
+  This function can only be called after writeStartElement() before
+  any content is written, or after writeEmptyElement().
+ */
+void QXmlStreamWriter::writeAttribute(const QString &namespaceUri, const QString &name, const QString &value)
+{
+    Q_D(QXmlStreamWriter);
+    Q_ASSERT(d->inStartElement);
+    Q_ASSERT(!name.contains(QLatin1Char(':')));
+    QXmlStreamWriterPrivate::NamespaceDeclaration &namespaceDeclaration = d->findNamespace(namespaceUri, true, true);
+    d->write(" ");
+    if (!namespaceDeclaration.prefix.isEmpty()) {
+        d->write(namespaceDeclaration.prefix);
+        d->write(":");
+    }
+    d->write(name);
+    d->write("=\"");
+    d->writeEscaped(value, true);
+    d->write("\"");
+}
+
+/*!
+  \overload
+
+  Writes the \a attribute.
+
+  This function can only be called after writeStartElement() before
+  any content is written, or after writeEmptyElement().
+ */
+void QXmlStreamWriter::writeAttribute(const QXmlStreamAttribute& attribute)
+{
+    if (attribute.namespaceUri().isEmpty())
+        writeAttribute(attribute.qualifiedName().toString(),
+                       attribute.value().toString());
+    else
+        writeAttribute(attribute.namespaceUri().toString(),
+                       attribute.name().toString(),
+                       attribute.value().toString());
+}
+
+
+/*!  Writes the attribute vector \a attributes. If a namespace
+  referenced in an attribute not been declared yet, QXmlStreamWriter
+  will generate a namespace declaration for it.
+
+  This function can only be called after writeStartElement() before
+  any content is written, or after writeEmptyElement().
+
+  \sa writeAttribute(), writeNamespace()
+ */
+void QXmlStreamWriter::writeAttributes(const QXmlStreamAttributes& attributes)
+{
+    Q_D(QXmlStreamWriter);
+    Q_ASSERT(d->inStartElement);
+    Q_UNUSED(d);
+    for (int i = 0; i < attributes.size(); ++i)
+        writeAttribute(attributes.at(i));
+}
+
+
+/*!  Writes \a text as CDATA section. If \a text contains the
+  forbidden character sequence "]]>", it is split into different CDATA
+  sections.
+
+  This function mainly exists for completeness. Normally you should
+  not need use it, because writeCharacters() automatically escapes all
+  non-content characters.
+ */
+void QXmlStreamWriter::writeCDATA(const QString &text)
+{
+    Q_D(QXmlStreamWriter);
+    d->finishStartElement();
+    QString copy(text);
+    copy.replace(QLatin1String("]]>"), QLatin1String("]]]]><![CDATA[>"));
+    d->write("<![CDATA[");
+    d->write(copy);
+    d->write("]]>");
+}
+
+
+/*!  Writes \a text. The characters "<", "&", and "\"" are escaped as entity
+  references "&lt;", "&amp;, and "&quot;". To avoid the forbidden sequence
+  "]]>", ">" is also escaped as "&gt;".
+
+  \sa writeEntityReference()
+ */
+void QXmlStreamWriter::writeCharacters(const QString &text)
+{
+    Q_D(QXmlStreamWriter);
+    d->finishStartElement();
+    d->writeEscaped(text);
+}
+
+
+/*!  Writes \a text as XML comment, where \a text must not contain the
+     forbidden sequence "--" or end with "-". Note that XML does not
+     provide any way to escape "-" in a comment.
+ */
+void QXmlStreamWriter::writeComment(const QString &text)
+{
+    Q_D(QXmlStreamWriter);
+    Q_ASSERT(!text.contains(QLatin1String("--")) && !text.endsWith(QLatin1Char('-')));
+    if (!d->finishStartElement(false) && d->autoFormatting)
+        d->indent(d->tagStack.size());
+    d->write("<!--");
+    d->write(text);
+    d->write("-->");
+    d->inStartElement = d->lastWasStartElement = false;
+}
+
+
+/*!  Writes a DTD section. The \a dtd represents the entire
+  doctypedecl production from the XML 1.0 specification.
+ */
+void QXmlStreamWriter::writeDTD(const QString &dtd)
+{
+    Q_D(QXmlStreamWriter);
+    d->finishStartElement();
+    if (d->autoFormatting)
+        d->write("\n");
+    d->write(dtd);
+    if (d->autoFormatting)
+        d->write("\n");
+}
+
+
+
+/*!  \overload
+  Writes an empty element with qualified name \a qualifiedName.
+  Subsequent calls to writeAttribute() will add attributes to this element.
+*/
+void QXmlStreamWriter::writeEmptyElement(const QString &qualifiedName)
+{
+    Q_D(QXmlStreamWriter);
+    Q_ASSERT(qualifiedName.count(QLatin1Char(':')) <= 1);
+    d->writeStartElement(QString(), qualifiedName);
+    d->inEmptyElement = true;
+}
+
+
+/*!  Writes an empty element with \a name, prefixed for the specified
+  \a namespaceUri. If the namespace has not been declared,
+  QXmlStreamWriter will generate a namespace declaration for it.
+  Subsequent calls to writeAttribute() will add attributes to this element.
+
+  \sa writeNamespace()
+ */
+void QXmlStreamWriter::writeEmptyElement(const QString &namespaceUri, const QString &name)
+{
+    Q_D(QXmlStreamWriter);
+    Q_ASSERT(!name.contains(QLatin1Char(':')));
+    d->writeStartElement(namespaceUri, name);
+    d->inEmptyElement = true;
+}
+
+
+/*!\overload
+  Writes a text element with \a qualifiedName and \a text.
+
+
+  This is a convenience function equivalent to:
+  \snippet doc/src/snippets/code/src_corelib_xml_qxmlstream.cpp 1
+
+*/
+void QXmlStreamWriter::writeTextElement(const QString &qualifiedName, const QString &text)
+{
+    writeStartElement(qualifiedName);
+    writeCharacters(text);
+    writeEndElement();
+}
+
+/*!  Writes a text element with \a name, prefixed for the specified \a
+     namespaceUri, and \a text. If the namespace has not been
+     declared, QXmlStreamWriter will generate a namespace declaration
+     for it.
+
+
+  This is a convenience function equivalent to:
+  \snippet doc/src/snippets/code/src_corelib_xml_qxmlstream.cpp 2
+
+*/
+void QXmlStreamWriter::writeTextElement(const QString &namespaceUri, const QString &name, const QString &text)
+{
+    writeStartElement(namespaceUri, name);
+    writeCharacters(text);
+    writeEndElement();
+}
+
+
+/*!
+  Closes all remaining open start elements and writes a newline.
+
+  \sa writeStartDocument()
+ */
+void QXmlStreamWriter::writeEndDocument()
+{
+    Q_D(QXmlStreamWriter);
+    while (d->tagStack.size())
+        writeEndElement();
+    d->write("\n");
+}
+
+/*!
+  Closes the previous start element.
+
+  \sa writeStartElement()
+ */
+void QXmlStreamWriter::writeEndElement()
+{
+    Q_D(QXmlStreamWriter);
+    if (d->tagStack.isEmpty())
+        return;
+
+    // shortcut: if nothing was written, close as empty tag
+    if (d->inStartElement && !d->inEmptyElement) {
+        d->write("/>");
+        d->lastWasStartElement = d->inStartElement = false;
+        QXmlStreamWriterPrivate::Tag &tag = d->tagStack_pop();
+        d->lastNamespaceDeclaration = tag.namespaceDeclarationsSize;
+        return;
+    }
+
+    if (!d->finishStartElement(false) && !d->lastWasStartElement && d->autoFormatting)
+        d->indent(d->tagStack.size()-1);
+    if (d->tagStack.isEmpty())
+        return;
+    d->lastWasStartElement = false;
+    QXmlStreamWriterPrivate::Tag &tag = d->tagStack_pop();
+    d->lastNamespaceDeclaration = tag.namespaceDeclarationsSize;
+    d->write("</");
+    if (!tag.namespaceDeclaration.prefix.isEmpty()) {
+        d->write(tag.namespaceDeclaration.prefix);
+        d->write(":");
+    }
+    d->write(tag.name);
+    d->write(">");
+}
+
+
+
+/*!
+  Writes the entity reference \a name to the stream, as "&\a{name};".
+ */
+void QXmlStreamWriter::writeEntityReference(const QString &name)
+{
+    Q_D(QXmlStreamWriter);
+    d->finishStartElement();
+    d->write("&");
+    d->write(name);
+    d->write(";");
+}
+
+
+/*!  Writes a namespace declaration for \a namespaceUri with \a
+  prefix. If \a prefix is empty, QXmlStreamWriter assigns a unique
+  prefix consisting of the letter 'n' followed by a number.
+
+  If writeStartElement() or writeEmptyElement() was called, the
+  declaration applies to the current element; otherwise it applies to
+  the next child element.
+
+  Note that the prefix \e xml is both predefined and reserved for
+  \e http://www.w3.org/XML/1998/namespace, which in turn cannot be
+  bound to any other prefix. The prefix \e xmlns and its URI
+  \e http://www.w3.org/2000/xmlns/ are used for the namespace mechanism
+  itself and thus completely forbidden in declarations.
+
+ */
+void QXmlStreamWriter::writeNamespace(const QString &namespaceUri, const QString &prefix)
+{
+    Q_D(QXmlStreamWriter);
+    Q_ASSERT(!namespaceUri.isEmpty());
+    Q_ASSERT(prefix != QLatin1String("xmlns"));
+    if (prefix.isEmpty()) {
+        d->findNamespace(namespaceUri, d->inStartElement);
+    } else {
+        Q_ASSERT(!((prefix == QLatin1String("xml")) ^ (namespaceUri == QLatin1String("http://www.w3.org/XML/1998/namespace"))));
+        Q_ASSERT(namespaceUri != QLatin1String("http://www.w3.org/2000/xmlns/"));
+        QXmlStreamWriterPrivate::NamespaceDeclaration &namespaceDeclaration = d->namespaceDeclarations.push();
+        namespaceDeclaration.prefix = d->addToStringStorage(prefix);
+        namespaceDeclaration.namespaceUri = d->addToStringStorage(namespaceUri);
+        if (d->inStartElement)
+            d->writeNamespaceDeclaration(namespaceDeclaration);
+    }
+}
+
+
+/*! Writes a default namespace declaration for \a namespaceUri.
+
+  If writeStartElement() or writeEmptyElement() was called, the
+  declaration applies to the current element; otherwise it applies to
+  the next child element.
+
+  Note that the namespaces \e http://www.w3.org/XML/1998/namespace
+  (bound to \e xmlns) and \e http://www.w3.org/2000/xmlns/ (bound to
+  \e xml) by definition cannot be declared as default.
+ */
+void QXmlStreamWriter::writeDefaultNamespace(const QString &namespaceUri)
+{
+    Q_D(QXmlStreamWriter);
+    Q_ASSERT(namespaceUri != QLatin1String("http://www.w3.org/XML/1998/namespace"));
+    Q_ASSERT(namespaceUri != QLatin1String("http://www.w3.org/2000/xmlns/"));
+    QXmlStreamWriterPrivate::NamespaceDeclaration &namespaceDeclaration = d->namespaceDeclarations.push();
+    namespaceDeclaration.prefix.clear();
+    namespaceDeclaration.namespaceUri = d->addToStringStorage(namespaceUri);
+    if (d->inStartElement)
+        d->writeNamespaceDeclaration(namespaceDeclaration);
+}
+
+
+/*!
+  Writes an XML processing instruction with \a target and \a data,
+  where \a data must not contain the sequence "?>".
+ */
+void QXmlStreamWriter::writeProcessingInstruction(const QString &target, const QString &data)
+{
+    Q_D(QXmlStreamWriter);
+    Q_ASSERT(!data.contains(QLatin1String("?>")));
+    d->finishStartElement();
+    d->write("<?");
+    d->write(target);
+    if (!data.isNull()) {
+        d->write(" ");
+        d->write(data);
+    }
+    d->write("?>");
+}
+
+
+
+/*!\overload
+
+  Writes a document start with XML version number "1.0". This also
+  writes the encoding information.
+
+  \sa writeEndDocument(), setCodec()
+  \since 4.5
+ */
+void QXmlStreamWriter::writeStartDocument()
+{
+    writeStartDocument(QLatin1String("1.0"));
+}
+
+
+/*!
+  Writes a document start with the XML version number \a version.
+
+  \sa writeEndDocument()
+ */
+void QXmlStreamWriter::writeStartDocument(const QString &version)
+{
+    Q_D(QXmlStreamWriter);
+    d->finishStartElement(false);
+    d->write("<?xml version=\"");
+    d->write(version);
+    if (d->device) { // stringDevice does not get any encoding
+        d->write("\" encoding=\"");
+#ifdef QT_NO_TEXTCODEC
+        d->write("iso-8859-1");
+#else
+        d->write(d->codec->name().constData());
+#endif
+    }
+    d->write("\"?>");
+}
+
+/*!  Writes a document start with the XML version number \a version
+  and a standalone attribute \a standalone.
+
+  \sa writeEndDocument()
+  \since 4.5
+ */
+void QXmlStreamWriter::writeStartDocument(const QString &version, bool standalone)
+{
+    Q_D(QXmlStreamWriter);
+    d->finishStartElement(false);
+    d->write("<?xml version=\"");
+    d->write(version);
+    if (d->device) { // stringDevice does not get any encoding
+        d->write("\" encoding=\"");
+#ifdef QT_NO_TEXTCODEC
+        d->write("iso-8859-1");
+#else
+        d->write(d->codec->name().constData());
+#endif
+    }
+    d->write("\" standalone=\"");
+    d->write(standalone ? "yes" : "no");
+    d->write("\"?>");
+}
+
+
+/*!\overload
+
+   Writes a start element with \a qualifiedName. Subsequent calls to
+   writeAttribute() will add attributes to this element.
+
+   \sa writeEndElement(), writeEmptyElement()
+ */
+void QXmlStreamWriter::writeStartElement(const QString &qualifiedName)
+{
+    Q_D(QXmlStreamWriter);
+    Q_ASSERT(qualifiedName.count(QLatin1Char(':')) <= 1);
+    d->writeStartElement(QString(), qualifiedName);
+}
+
+
+/*!  Writes a start element with \a name, prefixed for the specified
+  \a namespaceUri. If the namespace has not been declared yet,
+  QXmlStreamWriter will generate a namespace declaration for
+  it. Subsequent calls to writeAttribute() will add attributes to this
+  element.
+
+  \sa writeNamespace(), writeEndElement(), writeEmptyElement()
+ */
+void QXmlStreamWriter::writeStartElement(const QString &namespaceUri, const QString &name)
+{
+    Q_D(QXmlStreamWriter);
+    Q_ASSERT(!name.contains(QLatin1Char(':')));
+    d->writeStartElement(namespaceUri, name);
+}
+
+void QXmlStreamWriterPrivate::writeStartElement(const QString &namespaceUri, const QString &name)
+{
+    if (!finishStartElement(false) && autoFormatting)
+        indent(tagStack.size());
+
+    Tag &tag = tagStack_push();
+    tag.name = addToStringStorage(name);
+    tag.namespaceDeclaration = findNamespace(namespaceUri);
+    write("<");
+    if (!tag.namespaceDeclaration.prefix.isEmpty()) {
+        write(tag.namespaceDeclaration.prefix);
+        write(":");
+    }
+    write(tag.name);
+    inStartElement = lastWasStartElement = true;
+
+    for (int i = lastNamespaceDeclaration; i < namespaceDeclarations.size(); ++i)
+        writeNamespaceDeclaration(namespaceDeclarations[i]);
+    tag.namespaceDeclarationsSize = lastNamespaceDeclaration;
+}
+
+#ifndef QT_NO_XMLSTREAMREADER
+/*!  Writes the current state of the \a reader. All possible valid
+  states are supported.
+
+  The purpose of this function is to support chained processing of XML data.
+
+  \sa QXmlStreamReader::tokenType()
+ */
+void QXmlStreamWriter::writeCurrentToken(const QXmlStreamReader &reader)
+{
+    switch (reader.tokenType()) {
+    case QXmlStreamReader::NoToken:
+        break;
+    case QXmlStreamReader::StartDocument:
+        writeStartDocument();
+        break;
+    case QXmlStreamReader::EndDocument:
+        writeEndDocument();
+        break;
+    case QXmlStreamReader::StartElement: {
+        QXmlStreamNamespaceDeclarations namespaceDeclarations = reader.namespaceDeclarations();
+        for (int i = 0; i < namespaceDeclarations.size(); ++i) {
+            const QXmlStreamNamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.at(i);
+            writeNamespace(namespaceDeclaration.namespaceUri().toString(),
+                           namespaceDeclaration.prefix().toString());
+        }
+        writeStartElement(reader.namespaceUri().toString(), reader.name().toString());
+        writeAttributes(reader.attributes());
+             } break;
+    case QXmlStreamReader::EndElement:
+        writeEndElement();
+        break;
+    case QXmlStreamReader::Characters:
+        if (reader.isCDATA())
+            writeCDATA(reader.text().toString());
+        else
+            writeCharacters(reader.text().toString());
+        break;
+    case QXmlStreamReader::Comment:
+        writeComment(reader.text().toString());
+        break;
+    case QXmlStreamReader::DTD:
+        writeDTD(reader.text().toString());
+        break;
+    case QXmlStreamReader::EntityReference:
+        writeEntityReference(reader.name().toString());
+        break;
+    case QXmlStreamReader::ProcessingInstruction:
+        writeProcessingInstruction(reader.processingInstructionTarget().toString(),
+                                   reader.processingInstructionData().toString());
+        break;
+    default:
+        Q_ASSERT(reader.tokenType() != QXmlStreamReader::Invalid);
+        qWarning("QXmlStreamWriter: writeCurrentToken() with invalid state.");
+        break;
+    }
+}
+
+/*!
+ \fn bool QXmlStreamAttributes::hasAttribute(const QString &qualifiedName) const
+ \since 4.5
+
+ Returns true if this QXmlStreamAttributes has an attribute whose
+ qualified name is \a qualifiedName; otherwise returns false.
+
+ Note that this is not namespace aware. For instance, if this
+ QXmlStreamAttributes contains an attribute whose lexical name is "xlink:href"
+ this doesn't tell that an attribute named \c href in the XLink namespace is
+ present, since the \c xlink prefix can be bound to any namespace. Use the
+ overload that takes a namespace URI and a local name as parameter, for
+ namespace aware code.
+*/
+
+/*!
+ \fn bool QXmlStreamAttributes::hasAttribute(const QLatin1String &qualifiedName) const
+ \overload
+ \since 4.5
+*/
+
+/*!
+ \fn bool QXmlStreamAttributes::hasAttribute(const QString &namespaceUri,
+                                             const QString &name) const
+ \overload
+ \since 4.5
+
+ Returns true if this QXmlStreamAttributes has an attribute whose
+ namespace URI and name correspond to \a namespaceUri and \a name;
+ otherwise returns false.
+*/
+
+#endif // QT_NO_XMLSTREAMREADER
+#endif // QT_NO_XMLSTREAMWRITER
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_XMLSTREAM