summaryrefslogtreecommitdiff
path: root/src/xmlpatterns/api
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@nokia.com>2009-03-23 10:18:55 +0100
committerSimon Hausmann <simon.hausmann@nokia.com>2009-03-23 10:18:55 +0100
commite5fcad302d86d316390c6b0f62759a067313e8a9 (patch)
treec2afbf6f1066b6ce261f14341cf6d310e5595bc1 /src/xmlpatterns/api
downloadqt4-tools-e5fcad302d86d316390c6b0f62759a067313e8a9.tar.gz
Long live Qt 4.5!
Diffstat (limited to 'src/xmlpatterns/api')
-rw-r--r--src/xmlpatterns/api/api.pri48
-rw-r--r--src/xmlpatterns/api/qabstractmessagehandler.cpp149
-rw-r--r--src/xmlpatterns/api/qabstractmessagehandler.h81
-rw-r--r--src/xmlpatterns/api/qabstracturiresolver.cpp111
-rw-r--r--src/xmlpatterns/api/qabstracturiresolver.h74
-rw-r--r--src/xmlpatterns/api/qabstractxmlforwarditerator.cpp269
-rw-r--r--src/xmlpatterns/api/qabstractxmlforwarditerator_p.h328
-rw-r--r--src/xmlpatterns/api/qabstractxmlnodemodel.cpp1669
-rw-r--r--src/xmlpatterns/api/qabstractxmlnodemodel.h423
-rw-r--r--src/xmlpatterns/api/qabstractxmlnodemodel_p.h71
-rw-r--r--src/xmlpatterns/api/qabstractxmlreceiver.cpp476
-rw-r--r--src/xmlpatterns/api/qabstractxmlreceiver.h106
-rw-r--r--src/xmlpatterns/api/qabstractxmlreceiver_p.h71
-rw-r--r--src/xmlpatterns/api/qdeviceresourceloader_p.h88
-rw-r--r--src/xmlpatterns/api/qiodevicedelegate.cpp166
-rw-r--r--src/xmlpatterns/api/qiodevicedelegate_p.h108
-rw-r--r--src/xmlpatterns/api/qnetworkaccessdelegator.cpp80
-rw-r--r--src/xmlpatterns/api/qnetworkaccessdelegator_p.h106
-rw-r--r--src/xmlpatterns/api/qreferencecountedvalue_p.h106
-rw-r--r--src/xmlpatterns/api/qresourcedelegator.cpp111
-rw-r--r--src/xmlpatterns/api/qresourcedelegator_p.h119
-rw-r--r--src/xmlpatterns/api/qsimplexmlnodemodel.cpp184
-rw-r--r--src/xmlpatterns/api/qsimplexmlnodemodel.h77
-rw-r--r--src/xmlpatterns/api/qsourcelocation.cpp240
-rw-r--r--src/xmlpatterns/api/qsourcelocation.h101
-rw-r--r--src/xmlpatterns/api/quriloader.cpp84
-rw-r--r--src/xmlpatterns/api/quriloader_p.h86
-rw-r--r--src/xmlpatterns/api/qvariableloader.cpp264
-rw-r--r--src/xmlpatterns/api/qvariableloader_p.h118
-rw-r--r--src/xmlpatterns/api/qxmlformatter.cpp338
-rw-r--r--src/xmlpatterns/api/qxmlformatter.h94
-rw-r--r--src/xmlpatterns/api/qxmlname.cpp511
-rw-r--r--src/xmlpatterns/api/qxmlname.h142
-rw-r--r--src/xmlpatterns/api/qxmlnamepool.cpp109
-rw-r--r--src/xmlpatterns/api/qxmlnamepool.h88
-rw-r--r--src/xmlpatterns/api/qxmlquery.cpp1179
-rw-r--r--src/xmlpatterns/api/qxmlquery.h147
-rw-r--r--src/xmlpatterns/api/qxmlquery_p.h330
-rw-r--r--src/xmlpatterns/api/qxmlresultitems.cpp149
-rw-r--r--src/xmlpatterns/api/qxmlresultitems.h76
-rw-r--r--src/xmlpatterns/api/qxmlresultitems_p.h87
-rw-r--r--src/xmlpatterns/api/qxmlserializer.cpp653
-rw-r--r--src/xmlpatterns/api/qxmlserializer.h158
-rw-r--r--src/xmlpatterns/api/qxmlserializer_p.h130
44 files changed, 10105 insertions, 0 deletions
diff --git a/src/xmlpatterns/api/api.pri b/src/xmlpatterns/api/api.pri
new file mode 100644
index 0000000000..a0298f25fb
--- /dev/null
+++ b/src/xmlpatterns/api/api.pri
@@ -0,0 +1,48 @@
+HEADERS += $$PWD/qabstractxmlforwarditerator_p.h \
+ $$PWD/qabstractmessagehandler.h \
+ $$PWD/qabstracturiresolver.h \
+ $$PWD/qabstractxmlnodemodel.h \
+ $$PWD/qabstractxmlnodemodel_p.h \
+ $$PWD/qabstractxmlreceiver.h \
+ $$PWD/qabstractxmlreceiver_p.h \
+ $$PWD/qdeviceresourceloader_p.h \
+ $$PWD/qiodevicedelegate_p.h \
+ $$PWD/qnetworkaccessdelegator_p.h \
+ $$PWD/qresourcedelegator_p.h \
+ $$PWD/qsimplexmlnodemodel.h \
+ $$PWD/qsourcelocation.h \
+ $$PWD/quriloader_p.h \
+ $$PWD/qvariableloader_p.h \
+ $$PWD/qxmlformatter.h \
+ $$PWD/qxmlname.h \
+ $$PWD/qxmlnamepool.h \
+ $$PWD/qxmlquery.h \
+ $$PWD/qxmlquery_p.h \
+ $$PWD/qxmlresultitems.h \
+ $$PWD/qxmlresultitems_p.h \
+ $$PWD/qxmlserializer.h \
+ $$PWD/qxmlserializer_p.h \
+ $$PWD/../../../tools/xmlpatterns/qcoloringmessagehandler_p.h \
+ $$PWD/../../../tools/xmlpatterns/qcoloroutput_p.h
+
+SOURCES += $$PWD/qvariableloader.cpp \
+ $$PWD/qabstractmessagehandler.cpp \
+ $$PWD/qabstracturiresolver.cpp \
+ $$PWD/qabstractxmlnodemodel.cpp \
+ $$PWD/qabstractxmlreceiver.cpp \
+ $$PWD/qiodevicedelegate.cpp \
+ $$PWD/qnetworkaccessdelegator.cpp \
+ $$PWD/qresourcedelegator.cpp \
+ $$PWD/qsimplexmlnodemodel.cpp \
+ $$PWD/qsourcelocation.cpp \
+ $$PWD/quriloader.cpp \
+ $$PWD/qxmlformatter.cpp \
+ $$PWD/qxmlname.cpp \
+ $$PWD/qxmlnamepool.cpp \
+ $$PWD/qxmlquery.cpp \
+ $$PWD/qxmlresultitems.cpp \
+ $$PWD/qxmlserializer.cpp \
+ $$PWD/../../../tools/xmlpatterns/qcoloringmessagehandler.cpp \
+ $$PWD/../../../tools/xmlpatterns/qcoloroutput.cpp
+
+INCLUDEPATH += $$PWD/../../../tools/xmlpatterns/
diff --git a/src/xmlpatterns/api/qabstractmessagehandler.cpp b/src/xmlpatterns/api/qabstractmessagehandler.cpp
new file mode 100644
index 0000000000..1792bb5ac8
--- /dev/null
+++ b/src/xmlpatterns/api/qabstractmessagehandler.cpp
@@ -0,0 +1,149 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtXmlPatterns 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QMutex>
+
+#include "private/qobject_p.h"
+#include "qabstractmessagehandler.h"
+
+QT_BEGIN_NAMESPACE
+
+class QAbstractMessageHandlerPrivate : public QObjectPrivate
+{
+public:
+ QMutex mutex;
+};
+
+/*!
+ \class QAbstractMessageHandler
+ \threadsafe
+ \since 4.4
+ \ingroup xml-tools
+
+ \brief The QAbstractMessageHandler class provides a callback interface for handling messages.
+
+ QAbstractMessageHandler is an abstract base class that provides a
+ callback interface for handling messages. For example, class
+ QXmlQuery parses and runs an XQuery. When it detects a compile
+ or runtime error, it generates an appropriate error message,
+ but rather than output the message itself, it passes the message to
+ the message() function of its QAbstractMessageHandler.
+ See QXmlQuery::setMessageHandler().
+
+ You create a message handler by subclassing QAbstractMessageHandler
+ and implementing handleMessage(). You then pass a pointer to an
+ instance of your subclass to any classes that must generate
+ messages. The messages are sent to the message handler via the
+ message() function, which forwards them to your handleMessge().
+ The effect is to serialize the handling of all messages, which
+ means your QAbstractMessageHandler subclass is thread safe.
+
+ A single instance of QAbstractMessageHandler can be called on to
+ handle messages from multiple sources. Hence, the content of a
+ message, which is the \e description parameter passed to message()
+ and handleMessage(), must be interpreted in light of the context
+ that required the message to be sent. That context is specified by
+ the \e identifier and \e sourceLocation parameters to message()
+ handleMessage().
+ */
+
+/*!
+ Constructs a QAbstractMessageHandler. The \a parent is passed
+ to the QObject base class constructor.
+ */
+QAbstractMessageHandler::QAbstractMessageHandler(QObject *parent) : QObject(*new QAbstractMessageHandlerPrivate(), parent)
+{
+}
+
+/*!
+ Destructs this QAbstractMessageHandler.
+ */
+QAbstractMessageHandler::~QAbstractMessageHandler()
+{
+}
+
+/*!
+ Sends a message to this message handler. \a type is the kind of
+ message being sent. \a description is the message content. The \a
+ identifier is a URI that identifies the message and is the key to
+ interpreting the other arguments.
+
+ Typically, this class is used for reporting errors, as is the case
+ for QXmlQuery, which uses a QAbstractMessageHandler to report
+ compile and runtime XQuery errors. Hence, using a QUrl as the
+ message \a identifier is was inspired by the explanation of \l{error
+ handling in the XQuery language}. Because the \a identifier is
+ composed of a namespace URI and a local part, identifiers with the
+ same local part are unique. The caller is responsible for ensuring
+ that \a identifier is either a valid QUrl or a default constructed
+ QUrl.
+
+ \a sourceLocation identifies a location in a resource (i.e., file or
+ document) where the need for reporting a message was detected.
+
+ This function unconditionally calls handleMessage(), passing all
+ its parameters unmodified.
+
+ \sa {http://www.w3.org/TR/xquery/#errors}
+ */
+void QAbstractMessageHandler::message(QtMsgType type,
+ const QString &description,
+ const QUrl &identifier,
+ const QSourceLocation &sourceLocation)
+{
+ Q_D(QAbstractMessageHandler);
+ QMutexLocker(&d->mutex);
+ handleMessage(type, description, identifier, sourceLocation);
+}
+
+/*!
+ \fn void QAbstractMessageHandler::handleMessage(QtMsgType type,
+ const QString &description,
+ const QUrl &identifier = QUrl(),
+ const QSourceLocation &sourceLocation = QSourceLocation()) = 0
+
+ This function must be implemented by the sub-class. message() will
+ call this function, passing in its parameters, \a type,
+ \a description, \a identifier and \a sourceLocation unmodified.
+ */
+
+QT_END_NAMESPACE
+
diff --git a/src/xmlpatterns/api/qabstractmessagehandler.h b/src/xmlpatterns/api/qabstractmessagehandler.h
new file mode 100644
index 0000000000..efc22376db
--- /dev/null
+++ b/src/xmlpatterns/api/qabstractmessagehandler.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtXmlPatterns 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QABSTRACTMESSAGEHANDLER_H
+#define QABSTRACTMESSAGEHANDLER_H
+
+#include <QtXmlPatterns/QSourceLocation>
+#include <QtCore/QObject>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(XmlPatterns)
+
+class QAbstractMessageHandlerPrivate;
+class Q_XMLPATTERNS_EXPORT QAbstractMessageHandler : public QObject
+{
+ Q_OBJECT
+public:
+ QAbstractMessageHandler(QObject *parent = 0);
+ virtual ~QAbstractMessageHandler();
+
+ void message(QtMsgType type,
+ const QString &description,
+ const QUrl &identifier = QUrl(),
+ const QSourceLocation &sourceLocation = QSourceLocation());
+
+protected:
+ virtual void handleMessage(QtMsgType type,
+ const QString &description,
+ const QUrl &identifier,
+ const QSourceLocation &sourceLocation) = 0;
+private:
+ Q_DECLARE_PRIVATE(QAbstractMessageHandler)
+ Q_DISABLE_COPY(QAbstractMessageHandler)
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/xmlpatterns/api/qabstracturiresolver.cpp b/src/xmlpatterns/api/qabstracturiresolver.cpp
new file mode 100644
index 0000000000..b1f708be21
--- /dev/null
+++ b/src/xmlpatterns/api/qabstracturiresolver.cpp
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtXmlPatterns 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QUrl>
+
+#include "qabstracturiresolver.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QAbstractUriResolver
+ \brief The QAbstractUriResolver class is a callback interface for resolving Uniform Resource Identifiers.
+ \since 4.4
+ \reentrant
+ \ingroup xml-tools
+
+ A Uniform Resource Identifier (URI) is a string that uniquely
+ identifies a resource. URIs are versatile global identifiers. It is
+ often useful to transform a URI that identifies something logical
+ into a URI that locates something physical (a URL), or to simply map
+ a URI to a different URI. QAbstractUriResolver::resolve() provides
+ this functionality.
+
+ For example, one could write a QAbstractUriResolver subclass that
+ rewrites library ISBN number URIs as book title URLs, e.g.,
+ \e{urn:isbn:0-345-33973-8} would be rewritten as
+ \e{file:///books/returnOfTheKing.doc}. Or a QAbstractUriResolver
+ subclass could be written for a web browser to let the web browser
+ protect the user's private files by mapping incoming requests for
+ them to null URIs.
+
+ \sa {http://en.wikipedia.org/wiki/Uniform_Resource_Identifier}
+*/
+
+/*!
+ Constructs a QAbstractUriResolver with the specified \a parent.
+ */
+QAbstractUriResolver::QAbstractUriResolver(QObject *parent) : QObject(parent)
+{
+}
+
+/*!
+ Destructor.
+ */
+QAbstractUriResolver::~QAbstractUriResolver()
+{
+}
+
+/*!
+ \fn QUrl QAbstractUriResolver::resolve(const QUrl &relative, const QUrl &baseURI) const
+
+ Returns the \a relative URI resolved using the \a baseURI.
+
+ The caller guarantees that both \a relative and \a baseURI are
+ valid, and that \a baseURI is absolute. \a relative can be relative,
+ absolute, or empty.
+
+ The returned QUrl can be a default constructed QUrl. If it is not a
+ default constructed QUrl, it will be absolute and valid. If a default
+ constructed QUrl is returned, it means the \a relative URI was not
+ accepted to be resolved.
+
+ If the reimplemented resolve() function decides it has nothing to do
+ about resolving the \a relative URI, it should simply return the \a
+ relative URI resolved against the \a baseURI, i.e.:
+
+ \snippet doc/src/snippets/code/src_xmlpatterns_api_qabstracturiresolver.cpp 0
+
+ \sa QUrl::isRelative(), QUrl::isValid()
+ */
+
+QT_END_NAMESPACE
+
diff --git a/src/xmlpatterns/api/qabstracturiresolver.h b/src/xmlpatterns/api/qabstracturiresolver.h
new file mode 100644
index 0000000000..ec850279b4
--- /dev/null
+++ b/src/xmlpatterns/api/qabstracturiresolver.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtXmlPatterns 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QABSTRACTURIRESOLVER_H
+#define QABSTRACTURIRESOLVER_H
+
+#include <QtCore/QObject>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(XmlPatterns)
+
+class QUrl;
+class QAbstractUriResolverPrivate;
+
+class Q_XMLPATTERNS_EXPORT QAbstractUriResolver : public QObject
+{
+ Q_OBJECT
+public:
+ QAbstractUriResolver(QObject *parent = 0);
+ virtual ~QAbstractUriResolver();
+
+ virtual QUrl resolve(const QUrl &relative,
+ const QUrl &baseURI) const = 0;
+
+private:
+ Q_DISABLE_COPY(QAbstractUriResolver)
+ Q_DECLARE_PRIVATE(QAbstractUriResolver)
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/xmlpatterns/api/qabstractxmlforwarditerator.cpp b/src/xmlpatterns/api/qabstractxmlforwarditerator.cpp
new file mode 100644
index 0000000000..5bddeeebb4
--- /dev/null
+++ b/src/xmlpatterns/api/qabstractxmlforwarditerator.cpp
@@ -0,0 +1,269 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtXmlPatterns 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QAbstractXmlForwardIterator
+ \brief The QAbstractXmlForwardIterator class is a base class for forward iterators.
+ \reentrant
+ \since 4.4
+ \ingroup xml-tools
+ \internal
+
+ This abstract base class is for creating iterators for
+ traversing custom data structures modeled to look like XML.
+ An item can be instantiated in QAbstractXmlForwardIterator if:
+ \list
+
+ \o It has a default constructor, a copy constructor, and an
+ assignment operator, and
+
+ \o It has an appropriate qIsForwardIteratorEnd() function.
+ \endlist
+
+ @ingroup Patternist_iterators
+ @author Frans Englich <fenglich@trolltech.com>
+ */
+
+/*!
+ \typedef QAbstractXmlForwardIterator::Ptr
+
+ A smart pointer wrapping an instance of a QAbstractXmlForwardIterator subclass.
+ */
+
+/*!
+ \typedef QAbstractXmlForwardIterator::List
+ A QList containing QAbstractXmlForwardIterator::Ptr instances.
+ */
+
+/*!
+ \typedef QAbstractXmlForwardIterator::Vector
+ A QVector containing QAbstractXmlForwardIterator::Ptr instances.
+ */
+
+/*!
+ \fn QAbstractXmlForwardIterator::QAbstractXmlForwardIterator()
+
+ Default constructor.
+ */
+
+/*!
+ \fn QAbstractXmlForwardIterator::~QAbstractXmlForwardIterator()
+
+ Destructor.
+ */
+
+/*!
+ \fn T QAbstractXmlForwardIterator::next() = 0;
+
+ Returns the next item in the sequence, or
+ a null object if the end has been reached.
+ */
+
+/*!
+ \fn T QAbstractXmlForwardIterator::current() const = 0;
+
+ Returns the current item in the sequence. If this function is called
+ before the first call to next(), a null object is returned. If the
+ end of the sequence has been reached, a null object is returned.
+ */
+
+/*!
+ \fn qint64 QAbstractXmlForwardIterator::position() const = 0;
+
+ Returns the current position in the sequence represented
+ by \e this.
+
+ The first position is 1, not 0. If next() hasn't been called, 0 is
+ returned. If \e this has reached the end, -1 is returned.
+ */
+
+/*!
+ \fn bool qIsForwardIteratorEnd(const T &unit)
+ \since 4.4
+ \relates QAbstractXmlForwardIterator
+
+ The Callback QAbstractXmlForwardIterator uses for determining
+ whether \a unit is the end of a sequence.
+
+ If \a unit is a value that would signal the end of a sequence
+ (typically a default constructed value), this function returns \c
+ true, otherwise \c false.
+
+ This implementation works for any type that has a boolean operator.
+ For example, this function should work satisfactory for pointers.
+ */
+
+/*!
+ \fn qint64 QAbstractXmlForwardIterator::count()
+ \internal
+
+ Determines the number of items this QAbstractXmlForwardIterator
+ represents.
+
+ Note that this function is not \c const. It modifies the
+ QAbstractXmlForwardIterator. The reason for this is efficiency. If
+ this QAbstractXmlForwardIterator must not be changed, get a copy()
+ before performing the count.
+
+ The default implementation simply calls next() until the end is
+ reached. Hence, it may be of interest to override this function if
+ the sub-class knows a better way of computing its count.
+
+ The number of items in the sequence is returned.
+ */
+
+/*!
+ \fn QAbstractXmlForwardIterator<T>::Ptr QAbstractXmlForwardIterator::toReversed();
+ \internal
+
+ Returns a reverse iterator for the sequence.
+
+ This function may modify the iterator, it can be considered a
+ function that evaluates this QAbstractXmlForwardIterator. It is not
+ a \e getter, but potentially alters the iterator in the same way the
+ next() function does. If this QAbstractXmlForwardIterator must not
+ be modified, such that it can be used for evaluation with next(),
+ use a copy().
+ */
+
+/*!
+ \fn QList<T> QAbstractXmlForwardIterator<T>::toList();
+ \internal
+
+ Performs a copy of this QAbstractXmlForwardIterator(with copy()),
+ and returns its items in a QList. Thus, this function acts as a
+ conversion function, converting the sequence to a QList.
+
+ This function may modify the iterator. It is not a \e getter, but
+ potentially alters the iterator in the same way the next() function
+ does. If this QAbstractXmlForwardIterator must not be modified,
+ such that it can be used for evaluation with next(), use a copy().
+ */
+
+/*!
+ \fn T QAbstractXmlForwardIterator::last();
+ \internal
+
+ Returns the item at the end of this QAbstractXmlForwardIterator.
+ The default implementation calls next() until the end is reached.
+ */
+
+/*!
+ \fn T QAbstractXmlForwardIterator::isEmpty();
+ \internal
+ Returns true if the sequence is empty.
+ */
+
+/*!
+ \fn qint64 QAbstractXmlForwardIterator::sizeHint() const;
+ \internal
+
+ Gives a hint to the size of the contained sequence. The hint is
+ assumed to be as close as possible to the actual size.
+
+ If no sensible estimate can be computed, -1 should be returned.
+ */
+
+/*!
+ \fn typename QAbstractXmlForwardIterator<T>::Ptr QAbstractXmlForwardIterator::copy() const;
+ \internal
+
+ Copies this QAbstractXmlForwardIterator and returns the copy.
+
+ A copy and the original instance are completely independent of each
+ other. Because evaluating an QAbstractXmlForwardIterator modifies
+ it, one should always use a copy when an
+ QAbstractXmlForwardIterator needs to be used several times.
+ */
+
+/*!
+ \class QPatternist::ListIteratorPlatform
+ \brief Helper class for ListIterator, and should only be instantiated through sub-classing.
+ \reentrant
+ \since 4.4
+ \internal
+ \ingroup xml-tools
+
+ ListIteratorPlatform iterates an InputList with instances
+ of InputType. For every item in it, it returns an item from it,
+ that is converted to OutputType by calling a function on Derived
+ that has the following signature:
+
+ \snippet doc/src/snippets/code/src_xmlpatterns_api_qabstractxmlforwarditerator.cpp 0
+
+ TODO Document why this class doesn't duplicate ItemMappingIterator.
+ */
+
+/*!
+ \fn QPatternist::ListIteratorPlatform::ListIteratorPlatform(const ListType &list);
+
+ Constructs a ListIteratorPlatform that walks the given \a list.
+ */
+
+/*!
+ \class QPatternist::ListIterator
+ \brief Bridges values in Qt's QList container class into an QAbstractXmlForwardIterator.
+ \reentrant
+ \since 4.4
+ \internal
+ \ingroup xml-tools
+
+ ListIterator takes a reference to a QList<T> instance and allows
+ access to that list via its QAbstractXmlForwardIterator interface.
+ ListIterator is parameterized with the type to iterate over, e.g.,
+ Item or Expression::Ptr.
+
+ ListIterator is used by the ExpressionSequence to create an
+ iterator over its operands. The iterator will be passed to a
+ MappingIterator.
+ */
+
+/*!
+ \fn QPatternist::makeListIterator(const QList<T> &qList)
+ \relates QPatternist::ListIterator
+
+ An object generator for ListIterator.
+
+ makeListIterator() is a convenience function to avoid specifying
+ the full template instantiation for ListIterator. Conceptually, it
+ is identical to Qt's qMakePair().
+
+ */
diff --git a/src/xmlpatterns/api/qabstractxmlforwarditerator_p.h b/src/xmlpatterns/api/qabstractxmlforwarditerator_p.h
new file mode 100644
index 0000000000..836218e5fc
--- /dev/null
+++ b/src/xmlpatterns/api/qabstractxmlforwarditerator_p.h
@@ -0,0 +1,328 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtXmlPatterns 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef QABSTRACTXMLFORWARDITERATOR_H
+#define QABSTRACTXMLFORWARDITERATOR_H
+
+#include <QtCore/QList>
+#include <QtCore/QVector>
+#include <QtCore/QSharedData>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(XmlPatterns)
+
+template<typename T> class QVector;
+
+/* In this file we in some cases do not use QAbstractXmlForwardIterator's Ptr typedef.
+ * This is a compiler workaround for MS VS 6.0. */
+
+template<typename T>
+inline bool qIsForwardIteratorEnd(const T &unit)
+{
+ return !unit;
+}
+
+template<typename T> class QAbstractXmlForwardIterator;
+
+class QAbstractXmlForwardIteratorPrivate;
+
+template<typename T>
+class QAbstractXmlForwardIterator : public QSharedData
+{
+public:
+ typedef QExplicitlySharedDataPointer<QAbstractXmlForwardIterator<T> > Ptr;
+ typedef QList<QExplicitlySharedDataPointer<QAbstractXmlForwardIterator<T> > > List;
+ typedef QVector<QExplicitlySharedDataPointer<QAbstractXmlForwardIterator<T> > > Vector;
+
+ inline QAbstractXmlForwardIterator() {}
+ virtual ~QAbstractXmlForwardIterator() {}
+
+ virtual T next() = 0;
+ virtual T current() const = 0;
+
+ virtual qint64 position() const = 0;
+
+ virtual typename QAbstractXmlForwardIterator<T>::Ptr toReversed();
+ virtual QList<T> toList();
+ virtual typename QAbstractXmlForwardIterator<T>::Ptr copy() const;
+ virtual T last();
+ virtual bool isEmpty();
+ virtual qint64 count();
+ virtual qint64 sizeHint() const;
+
+private:
+ Q_DISABLE_COPY(QAbstractXmlForwardIterator<T>)
+
+ QAbstractXmlForwardIteratorPrivate *d_ptr; /* Currently not used. */
+};
+
+/* The namespace QPatternist and its members are internal, not part of the public API, and
+ * unsupported. Using them leads to undefined behavior. */
+namespace QPatternist
+{
+ class DeduplicateIterator;
+
+ template<typename InputType,
+ typename OutputType,
+ typename Derived,
+ typename ListType = QList<InputType> >
+ class ListIteratorPlatform : public QAbstractXmlForwardIterator<OutputType>
+ {
+ /* This declaration is a workaround for a set of GCC versions on OS X,
+ * amongst others powerpc-apple-darwin8-gcc-4.0.1 (GCC) 4.0.1. In
+ * DeduplicateIterator, it fails to see the protected inheritance. */
+ friend class DeduplicateIterator;
+
+ public:
+ virtual OutputType next()
+ {
+ if(m_position == -1)
+ return OutputType();
+
+ if(m_position == m_list.count())
+ {
+ m_position = -1;
+ m_current = OutputType();
+ return OutputType();
+ }
+
+ m_current = static_cast<const Derived *>(this)->inputToOutputItem(m_list.at(m_position));
+ ++m_position;
+ return m_current;
+ }
+
+ virtual OutputType current() const
+ {
+ return m_current;
+ }
+
+ virtual qint64 position() const
+ {
+ return m_position;
+ }
+
+ virtual qint64 count()
+ {
+ return m_list.count();
+ }
+
+ virtual typename QAbstractXmlForwardIterator<OutputType>::Ptr copy() const
+ {
+ return QExplicitlySharedDataPointer<QAbstractXmlForwardIterator<OutputType> >(new ListIteratorPlatform<InputType, OutputType, Derived, ListType>(m_list));
+ }
+
+ protected:
+ inline ListIteratorPlatform(const ListType &list) : m_list(list)
+ , m_position(0)
+ {
+ }
+
+ const ListType m_list;
+ qint64 m_position;
+ OutputType m_current;
+ };
+
+ template<typename T,
+ typename ListType = QList<T> >
+ class ListIterator : public ListIteratorPlatform<T, T, ListIterator<T, ListType>, ListType>
+ {
+ /*
+ * This declaration is needed for MSVC 2005, 14.00.50727.42 for 80x86.
+ */
+ friend class IteratorVector;
+
+ using ListIteratorPlatform<T, T, ListIterator<T, ListType>, ListType>::m_list;
+
+ static inline QVector<T> toVector(const QVector<T> &vector)
+ {
+ return vector;
+ }
+
+ static inline QVector<T> toVector(const QList<T> &list)
+ {
+ return list.toVector();
+ }
+
+ static inline QList<T> toList(const QVector<T> &vector)
+ {
+ return vector.toList();
+ }
+
+ static inline QList<T> toList(const QList<T> &list)
+ {
+ return list;
+ }
+
+ public:
+ inline ListIterator(const ListType &list) : ListIteratorPlatform<T, T, ListIterator<T, ListType>, ListType>(list)
+ {
+ }
+
+ virtual QList<T> toList()
+ {
+ return toList(m_list);
+ }
+
+ virtual QVector<T> toVector()
+ {
+ return toVector(m_list);
+ }
+
+ private:
+ inline const T &inputToOutputItem(const T &inputType) const
+ {
+ return inputType;
+ }
+ friend class ListIteratorPlatform<T, T, ListIterator<T, ListType>, ListType>;
+
+ // needed for MSVC 2005
+ friend class DeduplicateIterator;
+ };
+
+ template<typename T>
+ inline
+ typename QAbstractXmlForwardIterator<T>::Ptr
+ makeListIterator(const QList<T> &list)
+ {
+ return typename ListIterator<T>::Ptr(new ListIterator<T>(list));
+ }
+
+ template<typename T>
+ inline
+ typename QAbstractXmlForwardIterator<T>::Ptr
+ makeVectorIterator(const QVector<T> &vector)
+ {
+ return typename ListIterator<T, QVector<T> >::Ptr(new ListIterator<T, QVector<T> >(vector));
+ }
+}
+
+template<typename T>
+QList<T> QAbstractXmlForwardIterator<T>::toList()
+{
+ QList<T> result;
+ T item(next());
+
+ while(!qIsForwardIteratorEnd(item))
+ {
+ result.append(item);
+ item = next();
+ }
+
+ return result;
+}
+
+template<typename T>
+qint64 QAbstractXmlForwardIterator<T>::count()
+{
+ qint64 retval = 0;
+
+ while(!qIsForwardIteratorEnd(next()))
+ ++retval;
+
+ return retval;
+}
+
+template<typename T>
+typename QAbstractXmlForwardIterator<T>::Ptr QAbstractXmlForwardIterator<T>::toReversed()
+{
+ T item(next());
+ QList<T> result;
+
+ while(!qIsForwardIteratorEnd(item))
+ {
+ result.prepend(item);
+ item = next();
+ }
+
+ return QExplicitlySharedDataPointer<QAbstractXmlForwardIterator<T> >(new QPatternist::ListIterator<T>(result));
+}
+
+template<typename T>
+T QAbstractXmlForwardIterator<T>::last()
+{
+ T item(next());
+
+ while(!qIsForwardIteratorEnd(item))
+ item = next();
+
+ return item;
+}
+
+template<typename T>
+typename QAbstractXmlForwardIterator<T>::Ptr QAbstractXmlForwardIterator<T>::copy() const
+{
+ Q_ASSERT_X(false, Q_FUNC_INFO,
+ "This function is internal, unsupported, and should never be called.");
+ return typename QAbstractXmlForwardIterator<T>::Ptr();
+}
+
+template<typename T>
+bool QAbstractXmlForwardIterator<T>::isEmpty()
+{
+ return qIsForwardIteratorEnd(next());
+}
+
+template<typename T>
+qint64 QAbstractXmlForwardIterator<T>::sizeHint() const
+{
+ Q_ASSERT_X(false, Q_FUNC_INFO, "This function is currently not expected to be used.");
+ return -1;
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/xmlpatterns/api/qabstractxmlnodemodel.cpp b/src/xmlpatterns/api/qabstractxmlnodemodel.cpp
new file mode 100644
index 0000000000..0caa8c48f4
--- /dev/null
+++ b/src/xmlpatterns/api/qabstractxmlnodemodel.cpp
@@ -0,0 +1,1669 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtXmlPatterns 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QVector>
+
+#include "qabstractxmlnodemodel_p.h"
+#include "qabstractxmlreceiver.h"
+#include "qcommonvalues_p.h"
+#include "qemptyiterator_p.h"
+#include "qitemmappingiterator_p.h"
+#include "qitem_p.h"
+#include "qnamespaceresolver_p.h"
+#include "qsequencemappingiterator_p.h"
+#include "qsingletoniterator_p.h"
+
+#include "qabstractxmlnodemodel.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace QPatternist;
+
+typedef QExplicitlySharedDataPointer<QAbstractXmlForwardIterator<QXmlNodeModelIndex> > QXmlNodeModelIndexIteratorPointer;
+
+/**
+ * @file
+ * @short Contains the implementation of QAbstractXmlNodeModel.
+ */
+
+bool QAbstractXmlNodeModel::isIgnorableInDeepEqual(const QXmlNodeModelIndex &n)
+{
+ Q_ASSERT(!n.isNull());
+ const QXmlNodeModelIndex::NodeKind nk = n.kind();
+ return nk == QXmlNodeModelIndex::ProcessingInstruction ||
+ nk == QXmlNodeModelIndex::Comment;
+}
+
+
+/*!
+ \class QAbstractXmlNodeModel
+ \brief The QAbstractXmlNodeModel class is an abstract base class for modeling non-XML data to look like XML for QXmlQuery.
+ \threadsafe
+ \since 4.4
+ \ingroup xml-tools
+
+ The QAbstractXmlNodeModel specifies the interface that a node model
+ must implement for that node model be accessible to the query engine
+ for processing XQuery queries. A node model represents data as a
+ structure that can be queried as if the data were XML.
+
+ The node model represented by a subclass of QAbstractXmlNodeModel is
+ meant to be accessed by the QtXmlPatterns query engine. If the API
+ seems a little strange in a few places, it is because the member
+ functions are called by the query engine as it evaluates an
+ XQuery. They aren't meant to be used programatically.
+
+ \section1 Usage
+
+ QAbstractXmlNodeModel bridges the gap between the arbitrary structure
+ of the non-XML data to be queried and the well-defined structure of
+ XML data understood by QXmlQuery.
+
+ Consider a chemistry application that reads the file \c
+ chemistryData, which contains non-XML data that represents a
+ chemical structure composed of molecules and atoms. The application
+ will query this chemistry data with an XQuery it reads from file \c
+ queryFile. We write a custom subclass of QAbstractXmlNodeModel (\c
+ ChemistryNodeModel) that reads \c chemistryData and builds a data
+ structure, perhaps composed of objects of our own classes \c
+ molecule and \c atom. Clearly, this data structure is not XML. Our
+ custom subclass will know how to traverse this non-XML structure and
+ present it through the \l
+ {http://www.w3.org/TR/xpath-datamodel/}{XPath Data Model interface}.
+
+ \snippet doc/src/snippets/code/src_xmlpatterns_api_qabstractxmlnodemodel.cpp 1
+
+ The application first creates an instance of QXmlQuery and calls \l
+ {QXmlQuery::setQuery()}{setQuery()} to read \c queryFile containing
+ the XQuery we want to run. Then it creates an instance of our custom
+ node model class, \c ChemistryNodeModel, which is a subclass of
+ QAbstractXmlNodeModel. Its constructor is called with the \l
+ {QXmlNamePool} {name pool} obtained from our QXmlQuery, and with the
+ \c chemistryFile containing the structure of molecules and atoms to
+ be queried. The \l {QXmlNamePool} {name pool} is required because
+ our custom node model has the member function \l
+ {QAbstractXmlNodeModel::name()} {name()}, which returns the \l
+ {QXmlName} {name} of any node in the model. The \l {QXmlQuery}
+ {query} and the custom node model must use the same name pool for
+ constructing these \l {QXmlName} {names}. The constructor would then
+ read \c chemistryFile and build the custom node model structure.
+
+ To connect the \c query to the custom node model, we must bind a
+ variable name used in the query to a node in the model. The variable
+ can then be used in the query as a starting node. First, an \l
+ {QXmlNodeModelIndex} {index} for the desired starting node is
+ retrieved by calling QAbstractXmlNodeModel::createIndex(). Then the
+ index is bound to a variable name, in this case \c queryRoot, by
+ passing the name and the index to QXmlQuery::bindVariable(). The
+ query can then use a variable reference \c $queryRoot to refer to
+ the starting node. Note that if the \l {QXmlQuery} {query} uses
+ multiple variable references, a call to QXmlQuery::bindVariable()
+ is required to bind each different variable name to a node in the
+ model.
+
+ The query is executed when the application calls one of the
+ QXmlQuery evaluation functions. The application uses
+ QXmlQuery::evaluateTo(QAbstractXmlReceiver *), because it then uses
+ a \l {QXmlSerializer} {serializer} to out the query result as XML to
+ \c stdout. We could have used QXmlQuery::evaluateTo(QXmlResultItems
+ *) to get a list of result items, or
+ QXmlQuery::evaluateTo(QStringList *) if the query evaluated to a
+ sequence of \c {xs:string} values.
+
+ During query execution, the engine iterates over the node model
+ using nextFromSimpleAxis() to get the \l {QXmlNodeModelIndex}
+ {index} of the next node to be visited. The engine can get the name
+ of a node by calling name() with the node's \l {QXmlNodeModelIndex}
+ {index}. stringValue(), baseUri(), documentUri() and kind() are also
+ called as needed with a node \l {QXmlNodeModelIndex} {index}.
+
+ The example demonstrates the standard pattern for using a subclass
+ of QAbstractXmlNodeModel in combination with QXmlQuery to perform
+ an XQuery.
+
+ \list 1
+
+ \o Instantiate QXmlQuery and give it the XQuery to be run;
+
+ \o Instantiate a subclass of QAbstractXmlNodeModel or
+ QSimpleXmlNodeModel;
+
+ \o Retrieve a QXmlNodeModelIndex for the node in the model where
+ the QXmlQuery should start the query;
+
+ \o Use QXmlQuery::bindVariable() to bind the QXmlNodeModelIndex
+ to \c {$variable name};
+
+ \o Call one of the QXmlQuery evaluation functions to run the
+ query.
+
+ \endlist
+
+ \section1 Subclassing
+
+ Because the \l {http://www.w3.org/TR/xpath-datamodel/}{XPath Data Model
+ interface} presented by QAbstractXmlNodeModel allows QXmlQuery to
+ operate on non-XML data as if it were XML, implementing subclasses
+ of QAbstractXmlNodeModel can involve a significant amount of
+ work. The QSimpleXmlNodeModel class is provided to simplify the
+ implementation for many common use cases.
+
+ \section1 Thread Safety
+
+ Because the node model can be accessed concurrently by threads in
+ the QtXmlPatterns module, subclasses of QAbstractXmlNodeModel must
+ be written to be \l{Thread Support in Qt#Reentrancy and Thread-Safety}
+ {thread-safe}.
+ Classes that simplify implementing thread-safety include QReadLocker
+ and QWriteLocker.
+
+ See the example \l{File System Example} for a demonstration.
+ */
+
+/*!
+ \enum QXmlNodeModelIndex::Constants
+
+ \value ForwardAxis All forward axes include this flag.
+ \value ReverseAxis All reverse axes include this flag.
+ */
+
+/*!
+ \enum QXmlNodeModelIndex::DocumentOrder
+
+ Identifies the specific node comparison operator that should be
+ used.
+
+ \value Precedes Signifies the \c \<\< operator. Test whether the
+ first operand precedes the second in the document.
+
+ \value Follows Signifies the \c \>\> operator. Test whether the
+ first operand follows the second in the document.
+
+ \value Is Signifies the \c is operator. Test whether two nodes have
+ the same node identity.
+ */
+
+/*!
+ \enum QAbstractXmlNodeModel::SimpleAxis
+
+ Four axes that each contain one node only.
+
+ \value Parent The parent of the context node
+ \value FirstChild The first child of the context node
+ \value PreviousSibling The previous child of the context node
+ \value NextSibling The next child of the context node
+*/
+
+/*!
+ \enum QXmlNodeModelIndex::Axis
+ \internal
+
+ Identify the axes emanating from a node.
+
+ The axes AxisChild, AxisDescendant, AxisAttribute, AxisSelf,
+ AxisDescendantOrSelf, AxisFollowingSibling, and AxisFollowing are
+ forward axes.
+
+ The axes AxisParent, AxisAncestor, AxisPrecedingSibling,
+ AxisPreceding and AxisAncestorOrSelf are reverse axes.
+
+ \sa {http://www.w3.org/TR/xquery/#axes}{XQuery 1.0: An XML Query Language, 3.2.1.1 Axes}
+
+ \value AxisChild The \c child axis.
+
+ \value AxisDescendant The \c descendant axis.
+
+ \value AxisAttribute The \c attribute axis. Note: There
+ is a node kind named \c{Attribute}.
+
+ \value AxisSelf The \c self axis.
+
+ \value AxisDescendantOrSelf The \c descendant-or-self axis.
+
+ \value AxisFollowingSibling The \c following-sibling axis.
+
+ \value AxisNamespace The \c namespace axis. Note: Does
+ not exist in XQuery; deprecated in
+ XPath 2.0 (optionally supported);
+ mandatory in XPath 1.0.
+
+ \value AxisFollowing The \c following axis.
+
+ \value AxisParent The \c parent axis.
+
+ \value AxisAncestor The \c ancestor axis.
+
+ \value AxisPrecedingSibling The \c preceding-sibling axis.
+
+ \value AxisPreceding The \c preceding axis.
+
+ \value AxisAncestorOrSelf The \c ancestor-or-self axis.
+*/
+
+using namespace QPatternist;
+
+/*!
+ Default constructor.
+ */
+QAbstractXmlNodeModel::QAbstractXmlNodeModel() : d_ptr(0)
+{
+}
+
+/*!
+ \internal
+
+ Takes the d-pointer.
+
+ */
+QAbstractXmlNodeModel::QAbstractXmlNodeModel(QAbstractXmlNodeModelPrivate *d) : d_ptr(d)
+{
+}
+
+/*!
+ Destructor.
+ */
+QAbstractXmlNodeModel::~QAbstractXmlNodeModel()
+{
+ delete d_ptr;
+}
+
+/*!
+ \typedef QAbstractXmlNodeModel::List
+
+ A \l{QList}{list} of \l{QExplicitlySharedDataPointer} {smart
+ pointers} to instances of QAbstractXmlNodeModel.
+
+ \sa QExplicitlySharedDataPointer
+ */
+
+/*!
+ \typedef QAbstractXmlNodeModel::Ptr
+
+ A \l {QExplicitlySharedDataPointer} {smart pointer} to an
+ instance of QAbstractXmlNodeModel.
+
+ \sa QExplicitlySharedDataPointer
+ */
+
+/*!
+ \fn QUrl QAbstractXmlNodeModel::baseUri(const QXmlNodeModelIndex &n) const
+
+ Returns the base URI for the node whose index is \a n. The caller
+ guarantees that \a n is not \c null and that it belongs to a node
+ in this node model.
+
+ The base URI of a node can be extracted using the \c fn:base-uri()
+ function. The base URI is typically used for resolving relative URIs
+ that appear in the node or its children. It is conformant to just
+ return the document URI, although that might not properly reflect
+ the underlying data.
+
+ This function maps to the \c dm:base-uri accessor, which returns
+ a base URI according to the following:
+
+ \list
+
+ \o For document nodes, the base URI and the document URI are the same.
+
+ \o For elements, the base URI is the URI appearing in the element's
+ \c xml:base attribute, if present, or it is resolved to the
+ parent element's base URI.
+
+ \o Namespace nodes have no base URI.
+
+ \o The base URI for a processing instruction, comment, attribute,
+ or text node is the base URI of the node's parent element.
+
+ \endlist
+
+ The implementation guarantees to return a valid QUrl, or a default
+ constructed QUrl. If a node has no base URI, as in the case where a
+ comment has no parent, a default constructed QUrl is returned.
+
+ \sa {http://www.w3.org/TR/xpath-datamodel/#dm-base-uri}{XQuery 1.0 and XPath 2.0 Data Model (XDM), 5.2 base-uri Accessor}
+ */
+
+/*!
+ \fn QUrl QAbstractXmlNodeModel::documentUri(const QXmlNodeModelIndex &n) const
+
+ Returns the document URI of \a n. The document URI identifies the
+ resource which is the document. For example, the document could be a
+ regular file, e.g., \c{file:/}, or it could be the \c{http://} URL of
+ the location of a file. The document URI is used for resolving URIs
+ and to simply know where the document is.
+
+ If the node model maps to a URI in a natural way, return that URI.
+ Otherwise, return the company or product URI. The document URI can
+ be any URI as long as its valid and absolute.
+
+ The caller guarantees that \a n is not \c null and that it belongs
+ to this QAbstractXmlNodeModel.
+
+ This function maps to the \c dm:document-uri accessor, which
+ returns a document URI according to the following:
+
+ \list
+
+ \o If \a n is a document node, return an absolute QUrl containing
+ the document URI, or a default constructed QUrl. The latter
+ signals that no document URI is available for the document node.
+
+ \o For all other nodes, return a default constructed QUrl.
+
+ \endlist
+
+ \sa {http://www.w3.org/TR/xpath-datamodel/#dm-document-uri}{XQuery 1.0 and XPath 2.0 Data Model (XDM), 5.4 document-uri Accessor}
+ \sa QUrl::isValid(), QUrl::isRelative()
+ */
+
+/*
+### Qt 5:
+
+Add the function:
+
+ virtual QSourceLocation sourceLocation(const QXmlNodeModelIndex &nodeIndex) const = 0;
+
+Such that the data model can communicate back source locations.
+ */
+
+/*!
+ \fn QXmlNodeModelIndex::NodeKind QAbstractXmlNodeModel::kind(const QXmlNodeModelIndex &ni) const
+
+ Returns a value indicating the kind of node identified by \a ni.
+ The caller guarantees that \a ni is not null and that it identifies
+ a node in this node model. This function maps to the \c
+ dm:node-kind() accessor.
+
+ \sa {http://www.w3.org/TR/xpath-datamodel/#dm-node-kind}{XQuery 1.0 and XPath 2.0 Data Model (XDM), 5.10 node-kind Accessor}
+ */
+
+/*!
+ \fn QXmlNodeModelIndex::DocumentOrder QAbstractXmlNodeModel::compareOrder(const QXmlNodeModelIndex &ni1, const QXmlNodeModelIndex &ni2) const
+
+ This function returns the relative document order for the
+ nodes indexed by \a ni1 and \a ni2. It is used for the \c Is
+ operator and for sorting nodes in document order.
+
+ The caller guarantees that \a ni1 and \a ni2 are not \c null and
+ that both identify nodes in this node model.
+
+ If \a ni1 is identical to \a ni2, QXmlNodeModelIndex::Is is returned.
+ If \a ni1 precedes \a ni2 in document order, QXmlNodeModelIndex::Precedes
+ is returned. If \a ni1 follows \a ni2 in document order,
+ QXmlNodeModelIndex::Follows is returned.
+
+ \sa {http://www.w3.org/TR/xpath-datamodel/#document-order}{XQuery 1.0 and XPath 2.0 Data Model (XDM), 2.4 Document Order}
+ */
+
+/*!
+ \fn QXmlNodeModelIndex QAbstractXmlNodeModel::root(const QXmlNodeModelIndex &n) const
+
+ Returns the root node of the tree that contains the node whose index
+ is \a n. The caller guarantees that \a n is not \c null and that it
+ identifies a node in this node model.
+
+ If \a n identifies a node that is a direct child of the root,
+ parent() would return the same QXmlNodeModelIndex returned by
+ this function.
+ */
+
+namespace QPatternist
+{
+ class MergeIterator
+ {
+ public:
+ inline MergeIterator()
+ {
+ }
+
+ inline
+ QXmlNodeModelIndexIteratorPointer
+ mapToSequence(const QXmlNodeModelIndexIteratorPointer &it,
+ const DynamicContext::Ptr &) const
+ {
+ return it;
+ }
+
+ private:
+ Q_DISABLE_COPY(MergeIterator)
+ };
+
+ static const MergeIterator mergeIterator;
+
+ /**
+ * One might wonder, why not use makeVectorIterator() directly on a QVector
+ * with iterators?
+ *
+ * A problem emerges QAbstractXmlForwardIterator::copy(). All "meta
+ * iterators" that contain other iterators and so forth, propagate the
+ * copy() call such that all involved iterators are copied. However, if we
+ * have a ListIterator of iterators it isn't aware of that it contains
+ * iterators. Hence, we have this class which is specialized(not in the
+ * template sense) on iterators, and hence copies them appropriately.
+ */
+ class IteratorVector : public ListIterator<QXmlNodeModelIndexIteratorPointer, QVector<QXmlNodeModelIndexIteratorPointer> >
+ {
+ typedef QVector<QXmlNodeModelIndexIteratorPointer> ItVector;
+ public:
+ typedef QAbstractXmlForwardIterator<QXmlNodeModelIndexIteratorPointer>::Ptr Ptr;
+
+ IteratorVector(const ItVector &in) : ListIterator<QXmlNodeModelIndexIteratorPointer, QVector<QXmlNodeModelIndexIteratorPointer> >(in)
+ {
+ }
+
+ virtual QAbstractXmlForwardIterator<QXmlNodeModelIndexIteratorPointer>::Ptr copy() const
+ {
+ ItVector result;
+
+ for(int i = 0; i < m_list.count(); ++i)
+ result.append(m_list.at(i)->copy());
+
+ return Ptr(new IteratorVector(result));
+ }
+ };
+}
+
+/*!
+ \internal
+ This function is not a private member of QAbstractXmlNodeModel
+ because it would be messy to forward declare the required types.
+*/
+static inline QXmlNodeModelIndexIteratorPointer mergeIterators(const QXmlNodeModelIndex &node,
+ const QXmlNodeModelIndexIteratorPointer &it2)
+{
+ QVector<QXmlNodeModelIndexIteratorPointer> iterators;
+ iterators.append(makeSingletonIterator(node));
+ iterators.append(it2);
+
+ return makeSequenceMappingIterator<QXmlNodeModelIndex>(&mergeIterator,
+ IteratorVector::Ptr(new IteratorVector(iterators)),
+ DynamicContext::Ptr());
+}
+
+inline QAbstractXmlForwardIterator<QXmlNodeModelIndex>::Ptr
+QAbstractXmlNodeModel::mapToSequence(const QXmlNodeModelIndex &ni,
+ const DynamicContext::Ptr &) const
+{
+ Q_ASSERT(!ni.isNull());
+ /* Since we pass in this here, mapToSequence is used recursively. */
+ return mergeIterators(ni, makeSequenceMappingIterator<QXmlNodeModelIndex>(this,
+ ni.iterate(QXmlNodeModelIndex::AxisChild),
+ DynamicContext::Ptr()));
+}
+
+/*!
+ \fn QVector<QXmlNodeModelIndex> QAbstractXmlNodeModel::attributes(const QXmlNodeModelIndex &element) const
+
+ Returns the attributes of \a element. The caller guarantees
+ that \a element is an element in this node model.
+ */
+
+/*!
+ \internal
+
+ Performs navigation, starting from \a ni, by returning an
+ QAbstractXmlForwardIterator that returns nodes the \a axis emanating
+ from \a ni.
+
+ The implementation returns the nodes on the \a axis, without
+ duplicates and in \a axis order. This means that if \a axis is a
+ reverse axis, which is the case for the \c parent, \c ancestor, \c
+ ancestor-or-self, \c preceding, and \c preceding-sibling, the nodes
+ are delivered in reverse document order. Otherwise the nodes are
+ delivered in document order.
+
+ The implementor guarantees that the nodes delivered for the axes are
+ consistent with the XPath Data Model. This just implies common
+ sense, e.g., The child axis for a comment node can't contain any
+ children; a document node can't be a child of an element, etc.
+ Attributes aren't considered children of an element, but are only
+ available on AxisAttribute.
+
+ The value past in \a axis is not guaranteed based on what is used in
+ a query. QtXmlPatterns may call this function arbitrarily with any
+ value for \a axis. This is because QtXmlPatterns may rewrite queries
+ to be more efficient, using axes in different ways from the original
+ query.
+
+ QAbstractXmlNodeModel::Axis has a good overview of the axes and what
+ they select.
+
+ The caller guarantees that \a ni is not \c null and that it belongs
+ to this QAbstractXmlNodeModel instance.
+
+ Implementing iterate() can involve significant work, since it
+ requires different iterators for all the axes used. In the worst
+ case, it could require writing as many QAbstractXmlForwardIterator
+ subclasses as there are axes, but the number can often be reduced
+ with clever use of lists and template classes. It is better to use
+ or subclass QSimpleXmlNodeModel, which makes it easier to write the
+ node navigation code without loss of efficiency or flexibility.
+
+ \sa QSimpleXmlNodeModel
+ \sa QXmlNodeModelIndex::Axis
+ \sa {http://www.w3.org/TR/xquery/#axes}{XQuery 1.0: An XML Query Language, 3.2.1.1 Axes}
+ \sa {http://www.w3.org/TR/xpath-datamodel/}{W3CXQuery 1.0 and XPath 2.0 Data Model (XDM)}
+ */
+QExplicitlySharedDataPointer<QAbstractXmlForwardIterator<QXmlNodeModelIndex> >
+QAbstractXmlNodeModel::iterate(const QXmlNodeModelIndex &ni,
+ QXmlNodeModelIndex::Axis axis) const
+{
+ /* Returns iterators that track state and calls nextFromSimpleAxis()
+ * iteratively. Typically, when sub-classing QSimpleXmlNodeModel,
+ * you don't reimplement this function, but instead implement
+ * nextFromSimpleAxis(). */
+
+ switch(axis)
+ {
+ case QXmlNodeModelIndex::AxisSelf:
+ return makeSingletonIterator(ni);
+ case QXmlNodeModelIndex::AxisParent:
+ {
+ if(kind(ni) == QXmlNodeModelIndex::Document)
+ return makeEmptyIterator<QXmlNodeModelIndex>();
+ else
+ return makeSingletonIterator(nextFromSimpleAxis(Parent, ni));
+ }
+ case QXmlNodeModelIndex::AxisNamespace:
+ return makeEmptyIterator<QXmlNodeModelIndex>();
+ case QXmlNodeModelIndex::AxisAncestor:
+ {
+ QList<QXmlNodeModelIndex> ancestors;
+ QXmlNodeModelIndex ancestor = nextFromSimpleAxis(Parent, ni);
+
+ while(!ancestor.isNull())
+ {
+ ancestors.append(ancestor);
+ ancestor = nextFromSimpleAxis(Parent, ancestor);
+ }
+
+ return makeListIterator(ancestors);
+ }
+ case QXmlNodeModelIndex::AxisAncestorOrSelf:
+ {
+ QList<QXmlNodeModelIndex> ancestors;
+ ancestors.append(ni);
+ QXmlNodeModelIndex ancestor = nextFromSimpleAxis(Parent, ni);
+
+ while(!ancestor.isNull())
+ {
+ ancestors.append(ancestor);
+ ancestor = nextFromSimpleAxis(Parent, ancestor);
+ }
+
+ return makeListIterator(ancestors);
+ }
+ case QXmlNodeModelIndex::AxisPrecedingSibling:
+ {
+ QList<QXmlNodeModelIndex> preceding;
+ QXmlNodeModelIndex sibling = nextFromSimpleAxis(PreviousSibling, ni);
+
+ while(!sibling.isNull())
+ {
+ preceding.append(sibling);
+ sibling = nextFromSimpleAxis(PreviousSibling, sibling);
+ }
+
+ return makeListIterator(preceding);
+ }
+ case QXmlNodeModelIndex::AxisFollowingSibling:
+ {
+ QList<QXmlNodeModelIndex> preceding;
+ QXmlNodeModelIndex sibling = nextFromSimpleAxis(NextSibling, ni);
+
+ while(!sibling.isNull())
+ {
+ preceding.append(sibling);
+ sibling = nextFromSimpleAxis(NextSibling, sibling);
+ }
+
+ return makeListIterator(preceding);
+ }
+ case QXmlNodeModelIndex::AxisChildOrTop:
+ {
+ if(nextFromSimpleAxis(Parent, ni).isNull())
+ {
+ switch(kind(ni))
+ {
+ case QXmlNodeModelIndex::Comment:
+ /* Fallthrough. */
+ case QXmlNodeModelIndex::ProcessingInstruction:
+ /* Fallthrough. */
+ case QXmlNodeModelIndex::Element:
+ /* Fallthrough. */
+ case QXmlNodeModelIndex::Text:
+ return makeSingletonIterator(ni);
+ case QXmlNodeModelIndex::Attribute:
+ /* Fallthrough. */
+ case QXmlNodeModelIndex::Document:
+ /* Fallthrough. */
+ case QXmlNodeModelIndex::Namespace:
+ /* Do nothing. */;
+ }
+ }
+
+ /* Else, fallthrough to AxisChild. */
+ }
+ case QXmlNodeModelIndex::AxisChild:
+ {
+ QList<QXmlNodeModelIndex> children;
+ QXmlNodeModelIndex child = nextFromSimpleAxis(FirstChild, ni);
+
+ while(!child.isNull())
+ {
+ children.append(child);
+ child = nextFromSimpleAxis(NextSibling, child);
+ }
+
+ return makeListIterator(children);
+ }
+ case QXmlNodeModelIndex::AxisDescendant:
+ {
+ return makeSequenceMappingIterator<QXmlNodeModelIndex>(this,
+ ni.iterate(QXmlNodeModelIndex::AxisChild),
+ DynamicContext::Ptr());
+ }
+ case QXmlNodeModelIndex::AxisAttributeOrTop:
+ {
+ if(kind(ni) == QXmlNodeModelIndex::Attribute && nextFromSimpleAxis(Parent, ni).isNull())
+ return makeSingletonIterator(ni);
+
+ /* Else, fallthrough to AxisAttribute. */
+ }
+ case QXmlNodeModelIndex::AxisAttribute:
+ return makeVectorIterator(attributes(ni));
+ case QXmlNodeModelIndex::AxisDescendantOrSelf:
+ return mergeIterators(ni, iterate(ni, QXmlNodeModelIndex::AxisDescendant));
+ case QXmlNodeModelIndex::AxisFollowing:
+ /* Fallthrough. */
+ case QXmlNodeModelIndex::AxisPreceding:
+ {
+ /* We walk up along the ancestors, and for each parent, we grab its preceding/following
+ * siblings, and evaluate the descendant axis. The descendant axes gets added
+ * to a list and we then merge those iterators. */
+ QVector<QXmlNodeModelIndexIteratorPointer> descendantIterators;
+
+ QXmlNodeModelIndex current(ni);
+ while(!current.isNull())
+ {
+ QXmlNodeModelIndex candidate(nextFromSimpleAxis(axis == QXmlNodeModelIndex::AxisPreceding ? PreviousSibling : NextSibling, current));
+ if(candidate.isNull())
+ {
+ /* current is an ancestor. We don't want it, so next iteration we
+ * will grab its preceding sibling. */
+ current = nextFromSimpleAxis(Parent, current);
+ }
+ else
+ {
+ current = candidate;
+ descendantIterators.append(iterate(current, QXmlNodeModelIndex::AxisDescendantOrSelf)->toReversed());
+ }
+ }
+
+ return makeSequenceMappingIterator<QXmlNodeModelIndex>(&mergeIterator,
+ IteratorVector::Ptr(new IteratorVector(descendantIterators)),
+ DynamicContext::Ptr());
+ }
+ }
+
+ Q_ASSERT_X(false, Q_FUNC_INFO, "Unknown axis, internal error.");
+ return makeEmptyIterator<QXmlNodeModelIndex>();
+}
+
+/*!
+ \fn QXmlNodeModelIndex QAbstractXmlNodeModel::nextFromSimpleAxis(SimpleAxis axis, const QXmlNodeModelIndex &origin) const
+
+ When QtXmlPatterns evaluate path expressions, it emulate them through a
+ combination of calls with QSimpleXmlNodeModel::SimpleAxis values. Therefore,
+ the implementation of this function must return the node, if any, that
+ appears on the \a axis emanating from the \a origin.
+
+ If no such node is available, a default constructed
+ QXmlNodeModelIndex is returned.
+
+ QSimpleXmlNodeModel eliminates the need to handle redundant corner
+ cases by guaranteeing that it will never ask for:
+
+ \list
+ \o Children or siblings for attributes.
+ \o Children for comments, processing instructions, and text nodes.
+ \o Siblings or parents for document nodes.
+ \endlist
+
+ A typical implementation performs a \c switch on the value of \a
+ axis:
+
+ \code
+ QXmlNodeModelIndex MyTreeModel::nextFromSimpleAxis(SimpleAxis axis, const QXmlNodeModelIndex &origin) const
+ {
+ // Convert the QXmlNodeModelIndex to a value that is specific to what we represent.
+ const MyValue value = toMyValue(ni);
+
+ switch(axis)
+ {
+ case Parent:
+ return toNodeIndex(value.parent());
+ case FirstChild:
+ case PreviousSibling:
+ case NextSibling:
+ // and so on
+ }
+ }
+ \endcode
+
+ */
+
+/*!
+ \fn QXmlNodeModelIndex QAbstractXmlNodeModel::createIndex(qint64 data) const
+
+ Creates a node index with \a data as its internal data. \a data is
+ not constrained.
+ */
+
+/*!
+ \fn QXmlNodeModelIndex QAbstractXmlNodeModel::createIndex(void *pointer, qint64 additionalData) const
+
+ Creates a node index with \a pointer and \a additionalData as
+ its internal data.
+
+ What \a pointer and \a additionalData is, is not constrained.
+ */
+
+/*!
+ \fn QXmlNodeModelIndex QAbstractXmlNodeModel::createIndex(qint64 data, qint64 additionalData) const;
+ \overload
+
+ Creates a QXmlNodeModelIndex containing \a data and \a
+ additionalData.
+ */
+
+/*!
+ \fn QXmlName QAbstractXmlNodeModel::name(const QXmlNodeModelIndex &ni) const
+
+ Returns the name of \a ni. The caller guarantees that \a ni is not
+ \c null and that it belongs to this QAbstractXmlNodeModel.
+
+ If a node does not have a name, e.g., comment nodes, a null QXmlName
+ is returned. QXmlNames must be created with the instance of
+ QXmlQuery that is being used for evaluating queries using this
+ QAbstractXmlNodeModel.
+
+ This function maps to the \c dm:node-name() accessor.
+
+ If \a ni is a processing instruction, a QXmlName is returned with
+ the local name as the target name and the namespace URI and prefix
+ both empty.
+
+ \sa {http://www.w3.org/TR/xpath-datamodel/#dm-node-name}{XQuery 1.0 and XPath 2.0 Data Model (XDM), 5.11 node-name Accessor}
+ \sa QXmlName
+ */
+
+/*!
+ \fn QVector<QXmlName> QAbstractXmlNodeModel::namespaceBindings(const QXmlNodeModelIndex &n) const
+
+ Returns the in-scope namespaces of \a n. The caller guarantees that
+ \a n is not \c null and that it belongs to this QAbstractXmlNodeModel.
+
+ This function corresponds to the \c dm:namespace-nodes accessor.
+
+ The returned vector of namespace declarations includes namespaces
+ of the ancestors of \a n.
+
+ The caller guarantees that \a n is an Element that belongs to this
+ QAbstractXmlNodeModel.
+ */
+
+/*!
+ \internal
+ Sends the namespaces declared on \a n to \a receiver.
+
+ As a consequence, no namespaces are sent unless this node is an
+ element and has namespaces declared.
+
+ The caller guarantees that \a n is not \c null and that it belongs
+ to this QAbstractXmlNodeModel instance.
+
+ Note that it is not the namespaces that are in scope on \a n, but
+ only the namespaces that are specifically declared on \a n.
+
+ \a receiver is the receiver that this node is supposed to send its
+ namespaces to. This is guaranteed by the caller to be a valid
+ pointer. \a n is the index of the node whose namespaces are to
+ be sent.
+ */
+void QAbstractXmlNodeModel::sendNamespaces(const QXmlNodeModelIndex &n,
+ QAbstractXmlReceiver *const receiver) const
+{
+ Q_ASSERT(receiver);
+ const QVector<QXmlName> nss(namespaceBindings(n));
+
+ /* This is by far the most common case. */
+ if(nss.isEmpty())
+ return;
+
+ const int len = nss.size();
+ for(int i = 0; i < len; ++i)
+ receiver->namespaceBinding(nss.at(i));
+}
+
+/*!
+ \fn QString QAbstractXmlNodeModel::stringValue(const QXmlNodeModelIndex &n) const
+
+ Returns the string value for node \a n.
+
+ The caller guarantees that \a n is not \c null and that it belong to
+ this QAbstractXmlNodeModel instance.
+
+ This function maps to the \c dm:string-value() accessor, which the
+ specification completely specifies. Here's a summary:
+
+ \list
+
+ \o For processing instructions, the string value is the data
+ section(excluding any whitespace appearing between the name and the
+ data).
+
+ \o For text nodes, the string value equals the text node.
+
+ \o For comments, the content of the comment
+
+ \o For elements, the concatenation of all text nodes that are
+ descendants. Note, this is not only the children, but the
+ childrens' childrens' text nodes, and so forth.
+
+ \o For document nodes, the concatenation of all text nodes in the
+ document.
+
+ \endlist
+
+ \sa {http://www.w3.org/TR/xpath-datamodel/#dm-string-value}{XQuery 1.0 and XPath 2.0 Data Model (XDM), 5.13 string-value Accessor}
+ */
+
+/*!
+ \fn QVariant QAbstractXmlNodeModel::typedValue(const QXmlNodeModelIndex &node) const
+
+ Returns the typed value for node \a node.
+
+ The typed value is an atomic value, which an element or attribute
+ contains.
+
+ The caller guarantees that \a node is either an element or an
+ attribute. The implementor guarantees that the returned QVariant has
+ a value which is supported in XQuery. It cannot be an arbitrary
+ QVariant value. The implementor also guarantees that stringValue()
+ returns a lexical representation of typedValue()(this is guaranteed
+ by QSimpleXmlNodeModel::stringValue()).
+
+ If the return QVariant is a default constructed variant, it signals
+ that \a node has no typed value.
+*/
+
+/*!
+ \internal
+ */
+QPatternist::ItemIteratorPtr QAbstractXmlNodeModel::sequencedTypedValue(const QXmlNodeModelIndex &ni) const
+{
+ const QVariant &candidate = typedValue(ni);
+ if(candidate.isNull())
+ return QPatternist::CommonValues::emptyIterator;
+ else
+ return makeSingletonIterator(AtomicValue::toXDM(candidate));
+}
+
+/*!
+ \internal
+ */
+QPatternist::ItemTypePtr QAbstractXmlNodeModel::type(const QXmlNodeModelIndex &) const
+{
+ Q_ASSERT_X(false, Q_FUNC_INFO,
+ "This function is internal and must not be called.");
+ return QPatternist::ItemTypePtr();
+}
+
+/*!
+ \internal
+
+ Returns the namespace URI on \a ni that corresponds to \a prefix.
+
+ If \a prefix is StandardPrefixes::empty, the namespace URI for the
+ default namespace is returned.
+
+ The default implementation use namespaceBindings(), in a straight
+ forward manner.
+
+ If no namespace exists for \a prefix, NamespaceResolver::NoBinding
+ is returned.
+
+ The caller guarantees to only call this function for element nodes.
+ */
+QXmlName::NamespaceCode QAbstractXmlNodeModel::namespaceForPrefix(const QXmlNodeModelIndex &ni,
+ const QXmlName::PrefixCode prefix) const
+{
+ Q_ASSERT(kind(ni) == QXmlNodeModelIndex::Element);
+
+ const QVector<QXmlName> nbs(namespaceBindings(ni));
+ const int len = nbs.size();
+
+ for(int i = 0; i < len; ++i)
+ {
+ if(nbs.at(i).prefix() == prefix)
+ return nbs.at(i).namespaceURI();
+ }
+
+ return NamespaceResolver::NoBinding;
+}
+
+
+/*!
+ \internal
+
+ Determines whether \a ni1 is deep equal to \a ni2.
+
+ isDeepEqual() is defined as evaluating the expression \c
+ fn:deep-equal($n1, $n2) where \c $n1 is \a ni1 and \c $n1 is \a
+ ni2. This function is associative, meaning the same value is
+ returned regardless of if isDeepEqual() is invoked with \a ni1 as
+ first argument or second. It is guaranteed that \a ni1 and \a ni2
+ are nodes, as opposed to the definition of \c fn:deep-equal().
+
+ Returns true if \a ni1 is deep-equal to \a ni2, otherwise false
+
+ \sa {"http://www.w3.org/TR/xpath-functions/#func-deep-equal"}{XQuery 1.0 and XPath 2.0 Functions and Operators, 15.3.1 fn:deep-equal}
+ */
+bool QAbstractXmlNodeModel::isDeepEqual(const QXmlNodeModelIndex &n1,
+ const QXmlNodeModelIndex &n2) const
+{
+ Q_ASSERT(!n1.isNull());
+ Q_ASSERT(!n2.isNull());
+
+ const QXmlNodeModelIndex::NodeKind nk = n1.kind();
+
+ if(nk != n2.kind())
+ return false;
+
+ if(n1.name() != n2.name())
+ return false;
+
+ switch(nk)
+ {
+ case QXmlNodeModelIndex::Element:
+ {
+ QXmlNodeModelIndexIteratorPointer atts1(n1.iterate(QXmlNodeModelIndex::AxisAttribute));
+ QXmlNodeModelIndex node(atts1->next());
+
+ const QXmlNodeModelIndex::List atts2(n2.iterate(QXmlNodeModelIndex::AxisAttribute)->toList());
+ const QXmlNodeModelIndex::List::const_iterator end(atts2.constEnd());
+
+ while(!node.isNull())
+ {
+ bool equal = false;
+ for(QXmlNodeModelIndex::List::const_iterator it = atts2.constBegin(); it != end; ++it)
+ {
+ if(isDeepEqual(node, (*it)))
+ equal = true;
+ }
+
+ if(!equal)
+ return false;
+
+ node = atts1->next();
+ }
+
+ /* Fallthrough, so we check the children. */
+ }
+ case QXmlNodeModelIndex::Document:
+ {
+ QXmlNodeModelIndexIteratorPointer itn1(n1.iterate(QXmlNodeModelIndex::AxisChild));
+ QXmlNodeModelIndexIteratorPointer itn2(n2.iterate(QXmlNodeModelIndex::AxisChild));
+
+ while(true)
+ {
+ QXmlNodeModelIndex no1(itn1->next());
+ QXmlNodeModelIndex no2(itn2->next());
+
+ while(!no1.isNull() && isIgnorableInDeepEqual(no1))
+ no1 = itn1->next();
+
+ while(!no2.isNull() && isIgnorableInDeepEqual(no2))
+ no2 = itn2->next();
+
+ if(!no1.isNull() && !no2.isNull())
+ {
+ if(!isDeepEqual(no1, no2))
+ return false;
+ }
+ else
+ return no1.isNull() && no2.isNull();
+ }
+
+ return true;
+ }
+ case QXmlNodeModelIndex::Attribute:
+ /* Fallthrough */
+ case QXmlNodeModelIndex::ProcessingInstruction:
+ /* Fallthrough. */
+ case QXmlNodeModelIndex::Text:
+ /* Fallthrough. */
+ case QXmlNodeModelIndex::Comment:
+ return n1.stringValue() == n2.stringValue();
+ case QXmlNodeModelIndex::Namespace:
+ {
+ Q_ASSERT_X(false, Q_FUNC_INFO, "Not implemented");
+ return false;
+ }
+ }
+
+ return false;
+}
+
+/*!
+ \class QXmlItem
+ \reentrant
+ \since 4.4
+ \brief The QXmlItem class contains either an XML node or an atomic value.
+ \ingroup xml-tools
+
+ In XQuery, all expressions evaluate to a sequence of items, where
+ each item is either an XML node or an atomic value. The query in the
+ following snippet evaluates to sequence of five items.
+
+ \quotefile doc/src/snippets/patternist/items.xq
+
+ The five items are: An element, an atomic value (binary data encoded
+ in base64), a date, a float, and an attribute.
+
+ QXmlItem is the class that represents these XQuery items in the
+ QtXmlPatterns API. A non-null instance of QXmlItem is either a node
+ or an atomic value. Calling isNode() or isAtomicValue() tells you
+ which it is. Atomic values are represented elsewhere in the Qt API
+ as instances of QVariant, and an instance of QXmlItem that
+ represents an atomic value can be converted to a QVariant by calling
+ toAtomicValue(). A QXmlItem that wraps a node is represented
+ elsewhere as an instance of QXmlNodeModelIndex. A node QXmlItem can
+ be converted to a QXmlNodeModelIndex by calling toNodeModelIndex().
+
+ A default constructed QXmlItem instance is neither a node nor an
+ atomic value. It is considered null, in which case isNull() returns
+ true.
+
+ An instance of QXmlItem will be left dangling if the
+ \l{QAbstractXmlNodeModel} {XML node model} it
+ refers to is deleted, if it is a QXmlNodeModelIndex.
+ */
+
+/*!
+ \typedef QXmlItem::Iterator
+ A QAbstractXmlForwardIterator over QXmlItem.
+ */
+
+/*!
+ Constructs a null QXmlItem that is neither a node nor an atomic
+ value. isNull() returns true for a default constructed instance.
+ */
+QXmlItem::QXmlItem()
+{
+ m_node.model = 0;
+ m_node.data = 0;
+ m_node.additionalData = 0;
+}
+
+bool QXmlItem::internalIsAtomicValue() const
+{
+ return m_node.model == reinterpret_cast<QAbstractXmlNodeModel *>(~0);
+}
+
+/*!
+ The copy constructor constructs a copy of \a other.
+ */
+QXmlItem::QXmlItem(const QXmlItem &other) : m_node(other.m_node)
+{
+ if(internalIsAtomicValue())
+ m_atomicValue->ref.ref();
+}
+
+/*!
+ Constructs an atomic value QXmlItem with \a atomicValue.
+
+ \sa isAtomicValue()
+ */
+QXmlItem::QXmlItem(const QVariant &atomicValue)
+{
+ if(atomicValue.isNull())
+ {
+ /* Then we behave just like the default constructor. */
+ m_node.model = 0;
+ m_node.data = 0;
+ m_node.additionalData = 0;
+ return;
+ }
+
+ /*
+ We can't assign directly to m_atomicValue, because the
+ temporary will self-destruct before we've ref'd it.
+ */
+ const QPatternist::Item temp(QPatternist::AtomicValue::toXDM(atomicValue));
+
+ if(temp)
+ {
+ temp.asAtomicValue()->ref.ref();
+ m_node.model = reinterpret_cast<const QAbstractXmlNodeModel *>(~0);
+ m_atomicValue = temp.asAtomicValue();
+ }
+ else
+ {
+ m_atomicValue = 0;
+ m_node.model = 0;
+ }
+
+ m_node.additionalData = 0;
+}
+
+/*!
+ Constructs a node QXmlItem that is a copy of \a node.
+
+ \sa isNode()
+ */
+QXmlItem::QXmlItem(const QXmlNodeModelIndex &node) : m_node(node.m_storage)
+{
+}
+
+
+/*!
+ Destructor.
+ */
+QXmlItem::~QXmlItem()
+{
+ if(internalIsAtomicValue() && !m_atomicValue->ref.deref())
+ delete m_atomicValue;
+}
+
+bool QPatternist::NodeIndexStorage::operator!=(const NodeIndexStorage &other) const
+{
+ return data != other.data
+ || additionalData != other.additionalData
+ || model != other.model;
+}
+
+/*!
+ Assigns \a other to \c this.
+ */
+QXmlItem &QXmlItem::operator=(const QXmlItem &other)
+{
+ if(m_node != other.m_node)
+ {
+ if(internalIsAtomicValue() && !m_atomicValue->ref.deref())
+ delete m_atomicValue;
+
+ m_node = other.m_node;
+
+ if(internalIsAtomicValue())
+ m_atomicValue->ref.ref();
+ }
+
+ return *this;
+}
+
+/*!
+ Returns true if this item is a Node. Returns false if it
+ is an atomic value or null.
+
+ \sa isNull(), isAtomicValue()
+ */
+bool QXmlItem::isNode() const
+{
+ return QPatternist::Item::fromPublic(*this).isNode();
+}
+
+/*!
+ Returns true if this item is an atomic value. Returns false
+ if it is a node or null.
+
+ \sa isNull(), isNode()
+ */
+bool QXmlItem::isAtomicValue() const
+{
+ return internalIsAtomicValue();
+}
+
+/*!
+ If this QXmlItem represents an atomic value, it is converted
+ to an appropriate QVariant and returned. If this QXmlItem is
+ not an atomic value, the return value is a default constructed
+ QVariant. You can call isAtomicValue() to test whether the
+ item is an atomic value.
+
+ \sa isAtomicValue()
+ */
+QVariant QXmlItem::toAtomicValue() const
+{
+ if(isAtomicValue())
+ return QPatternist::AtomicValue::toQt(m_atomicValue);
+ else
+ return QVariant();
+}
+
+/*!
+ If this QXmlItem represents a node, it returns the item as a
+ QXmlNodeModelIndex. If this QXmlItem is not a node, the return
+ value is undefined. You can call isNode() to test whether the
+ item is a node.
+
+ \sa isNode()
+ */
+QXmlNodeModelIndex QXmlItem::toNodeModelIndex() const
+{
+ if(isNode())
+ return reinterpret_cast<const QXmlNodeModelIndex &>(m_node);
+ else
+ return QXmlNodeModelIndex();
+}
+
+/*!
+ Returns true if this QXmlItem is neither a node nor an
+ atomic value. Default constructed instances of QXmlItem
+ are null.
+ */
+bool QXmlItem::isNull() const
+{
+ return !m_node.model;
+}
+
+/*!
+ \class QXmlNodeModelIndex
+ \brief The QXmlNodeModelIndex class identifies a node in an XML node model subclassed from QAbstractXmlNodeModel.
+ \reentrant
+ \since 4.4
+ \ingroup xml-tools
+
+ QXmlNodeModelIndex is an index into an \l{QAbstractXmlNodeModel}
+ {XML node model}. It contains:
+
+ \list
+ \o A pointer to an \l{QAbstractXmlNodeModel} {XML node model},
+ which is returned by model(), and
+ \o Some data, which is returned by data(), internalPointer(),
+ and additionalData().
+ \endlist
+
+ Because QXmlNodeModelIndex is intentionally a simple class, it
+ doesn't have member functions for accessing the properties of
+ nodes. For example, it doesn't have functions for getting a
+ node's name or its list of attributes or child nodes. If you find
+ that you need to retrieve this kind of information from your
+ query results, there are two ways to proceed.
+
+ \list
+
+ \o Send the output of your XQuery to an \l{QAbstractXmlReceiver}
+ {XML receiver}, or
+
+ \o Let your XQuery do all the work to produce the desired result.
+
+ \endlist
+
+ The second case is explained by example. Suppose you want to
+ populate a list widget with the values of certain attributes from a
+ set of result elements. You could write an XQuery to return the set
+ of elements, and then you would write the code to iterate over the
+ result elements, get their attributes, and extract the desired
+ string values. But the simpler way is to just augment your XQuery to
+ finding the desired attribute values. Then all you have to do is
+ evaluate the XQuery using the version of QXmlQuery::evaluateTo()
+ that populates a QStringList, which you can send directly to your
+ widget.
+
+ QXmlNodeModelIndex doesn't impose any restrictions on the \c data
+ value an QXmlNodeModelIndex should contain. The meaning of the data
+ left to the associated \l {QAbstractXmlNodeModel} {node model}.
+ Because QXmlNodeModelIndex depends on a particular subclass of
+ QAbstractXmlNodeModel for its existence, the only way you can create
+ an instance of QXmlNodeModelIndex is by asking the node model to
+ create one for you with QAbstractXmlNodeModel::createIndex(). Since
+ that function is protected, it is usually a good ide to write a
+ public function that creates a QXmlNodeModelIndex from arguments that
+ are appropriate for your particular node model.
+
+ A default constructed node index is said to be null, i.e., isNull()
+ returns true.
+
+ QXmlNodeModelIndex and QAbstractXmlNodeModel follow the same design
+ pattern used for QModelIndex and QAbstractItemModel.
+ */
+
+/*!
+ \since 4.4
+ \relates QHash
+
+ Computes a hash key from the QXmlNodeModelIndex \a index, and
+ returns it. This function would be used by QHash if you wanted
+ to build a hash table for instances of QXmlNodeModelIndex.
+
+ The hash is computed on QXmlNodeModelIndex::data(),
+ QXmlNodeModelIndex::additionalData(), and
+ QXmlNodeModelIndex::model(). This means the hash key can be used for
+ node indexes from different node models.
+ */
+uint qHash(const QXmlNodeModelIndex &index)
+{
+ return uint(index.data() + index.additionalData() + quintptr(index.model()));
+}
+
+/*!
+ \enum QXmlNodeModelIndex::NodeKind
+
+ Identifies a kind of node.
+
+ \value Attribute Identifies an attribute node
+ \value Text Identifies a text node
+ \value Comment Identifies a comment node
+ \value Document Identifies a document node
+ \value Element Identifies an element node
+ \value Namespace Identifies a namespace node
+ \value ProcessingInstruction Identifies a processing instruction.
+
+ Note that the optional XML declaration at very beginning of the XML
+ document is not a processing instruction
+
+ \sa QAbstractXmlNodeModel::kind()
+*/
+
+/*!
+ \typedef QXmlNodeModelIndex::List
+
+ Typedef for QList<QXmlNodeModelIndex>.
+ */
+
+/*!
+ Returns true if this node is the same as \a other. This operator
+ does not compare values, children, or names of nodes. It compares
+ node identities, i.e., whether two nodes are from the same document
+ and are found at the exact same place.
+ */
+bool QXmlNodeModelIndex::operator==(const QXmlNodeModelIndex &other) const
+{
+ return !(m_storage != other.m_storage);
+}
+
+/*!
+ Returns true if \a other is the same node as this.
+ */
+bool QXmlNodeModelIndex::operator!=(const QXmlNodeModelIndex &other) const
+{
+ return !(operator==(other));
+}
+
+/*!
+ \fn QXmlNodeModelIndex::QXmlNodeModelIndex()
+
+ Default constructor. Creates an item that is \c null.
+
+ \sa isNull()
+ */
+
+/*!
+ \fn QXmlNodeModelIndex::QXmlNodeModelIndex(const QXmlNodeModelIndex &other)
+
+ Standard copy constructor. Creates a QXmlNodeModelIndex instance that
+ is a copy of \a other.
+ */
+
+/*!
+ \fn bool QXmlNodeModelIndex::isNull() const
+
+ Returns true if this QXmlNodeModelIndex is a default constructed
+ value, otherwise false.
+
+ A null QXmlNodeModelIndex doesn't represent any node and cannot
+ be used in conjunction with QAbstractXmlNodeModel.
+ */
+
+/*!
+ \fn const QAbstractXmlNodeModel *QXmlNodeModelIndex::model() const
+
+ Returns the QAbstractXmlNodeModel that this node index refers to.
+ QXmlNodeModelIndex does not own QAbstractXmlNodeModel and does not
+ keep track of its lifetime, so this pointer will dangle if the
+ QAbstractXmlNodeModel is deallocated first.
+
+ There is no setter for the node model because instances of
+ QXmlNodeModelIndex instances are only created with
+ QAbstractXmlNodeModel::createIndex().
+*/
+
+/*!
+ \fn qint64 QXmlNodeModelIndex::data() const
+
+ Returns the first data value. The node index holds two data values.
+ additionalData() returns the second one.
+
+ \sa additionalData()
+*/
+
+/*!
+ \fn void *QXmlNodeModelIndex::internalPointer() const
+
+ Returns the first data value as a void* pointer.
+
+ \sa additionalData()
+*/
+
+/*!
+ \fn qint64 QXmlNodeModelIndex::additionalData() const
+
+ Returns the second data value. The node index holds two data values.
+ data() returns the first one.
+
+ \sa data()
+*/
+
+/*!
+ \fn void QXmlNodeModelIndex::reset()
+ \internal
+
+ Resets this QXmlNodeModelIndex to be null. It is equivalent to
+ writing:
+
+ \snippet doc/src/snippets/code/src_xmlpatterns_api_qabstractxmlnodemodel.cpp 0
+ */
+
+/*!
+ \fn QXmlName QXmlNodeModelIndex::name() const
+ \internal
+*/
+
+/*!
+ \typedef QXmlNodeModelIndex::Iterator
+ \internal
+
+ Typedef for QAbstractXmlForwardIterator<QXmlNodeModelIndex>.
+ */
+/*!
+ \fn QXmlNodeModelIndex QXmlNodeModelIndex::root() const
+ \internal
+*/
+
+/*!
+ \fn QExplicitlySharedDataPointer<QAbstractXmlForwardIterator<QXmlNodeModelIndex> > QXmlNodeModelIndex::iterate(const Axis axis) const
+ \internal
+*/
+
+/*!
+ \fn QExplicitlySharedDataPointer<QAbstractXmlForwardIterator<QPatternist::Item> > QXmlNodeModelIndex::sequencedTypedValue() const
+ \internal
+*/
+
+/*!
+ \fn QUrl QXmlNodeModelIndex::documentUri() const
+ \internal
+*/
+
+/*!
+ \fn QUrl QXmlNodeModelIndex::baseUri() const
+ \internal
+*/
+
+/*!
+ \fn NodeKind QXmlNodeModelIndex::kind() const
+ \internal
+*/
+
+/*!
+ \fn bool QXmlNodeModelIndex::isDeepEqual(const QXmlNodeModelIndex &other) const
+ \internal
+*/
+
+/*!
+ \fn DocumentOrder QXmlNodeModelIndex::compareOrder(const QXmlNodeModelIndex &other) const
+ \internal
+*/
+
+/*!
+ \fn void QXmlNodeModelIndex::sendNamespaces(QAbstractXmlReceiver *const receiver) const
+ \internal
+*/
+
+/*!
+ \fn QVector<QXmlName> QXmlNodeModelIndex::namespaceBindings() const
+ \internal
+*/
+
+/*!
+ \fn QXmlNodeModelIndex QAbstractXmlNodeModel::elementById(const QXmlName &id) const
+
+ Returns the index of the element identified as \a id. XQuery's \c
+ id() function calls this function.
+
+ The node index returned will be the element node whose value is of
+ type \c ID and equals \a id, or it will be the element node that has
+ an attribute whose typed value is of type \c ID and equals \a id. If
+ there is no such element, a default constructed QXmlNodeModelIndex
+ instance is returned. The implementor guarantees that if the returned
+ node index is not null, it identifies an element.
+
+ It is not sufficient for an attribute or element to merely be called
+ \c id. Its value type must also be \c ID. However, the reserved name
+ \c xml:id is sufficient.
+
+ In \a id, the \c{namespace URI} and the \c{prefix} are undefined, and
+ the \c{local name} is the ID that should be looked up.
+
+ \sa {http://www.w3.org/TR/xpath-functions/#func-id}{XQuery 1.0 and XPath 2.0 Functions and Operators, 15.5.2 fn:id}
+ */
+
+/*!
+ \fn QVector<QXmlNodeModelIndex> QAbstractXmlNodeModel::nodesByIdref(const QXmlName &idref) const
+
+ Returns the elements and/or attributes that have an \c IDREF value
+ equal to \a idref. XQuery's \c idref() function calls this function.
+
+ The implementor guarantees that the nodes identified by the returned
+ indexes are elements or attributes.
+
+ It is not sufficient for an attribute or element to merely be called
+ \c idref. It must also be of type \c IDREF. Elements must be typed as
+ \c xs:IDREF or \c xs:IDREFS, or, in the case of attributes, as \c
+ IDREF or \c IDREFS in the schema.
+
+ In \a idref, the \c{namespace URI} and the \c{prefix} are undefined,
+ and the \c{local name} is the ID that should be looked up.
+
+ \sa {http://www.w3.org/TR/xpath-functions/#func-idref}{XQuery 1.0 and XPath 2.0 Functions and Operators, 15.5.3 fn:idref}
+ */
+
+/*!
+ \fn QXmlName::NamespaceCode QXmlNodeModelIndex::namespaceForPrefix(const QXmlName::PrefixCode prefix) const
+ \internal
+*/
+
+/*!
+ \fn QString QXmlNodeModelIndex::stringValue() const
+ \internal
+*/
+
+/*!
+ \fn QPatternist::ItemTypePtr QXmlNodeModelIndex::type() const
+ \internal
+*/
+
+/*!
+ \fn bool QXmlNodeModelIndex::is(const QXmlNodeModelIndex &other) const
+ \internal
+*/
+
+/*!
+ \enum QAbstractXmlNodeModel::NodeCopySetting
+ \internal
+
+ Controls how nodes are copied with copyNodeTo.
+
+ \value InheritNamespaces Copies the node with the \c copy-namespaces
+ setting being \c inherit. If not set, \c no-inherit is assumed.
+ \value PreserveNamespaces Copies the node with the \c copy-namespaces
+ settings being \c preserve. If not set, \c no-preserve is assumed.
+ */
+
+/*!
+ \typedef QAbstractXmlNodeModel::NodeCopySettings
+ \internal
+ */
+
+/*!
+ \internal
+
+ Copies node \a node to \a receiver, steered by \a copySettings.
+
+ The caller guarantees that \a node is not \c null, and that is
+ belongs to this QAbstractXmlNodeModel instance.
+
+ The caller guarantees that \a receiver is not \c null.
+*/
+void QAbstractXmlNodeModel::copyNodeTo(const QXmlNodeModelIndex &node,
+ QAbstractXmlReceiver *const receiver,
+ const NodeCopySettings &copySettings) const
+{
+ Q_UNUSED(node);
+ Q_UNUSED(receiver);
+ Q_UNUSED(copySettings);
+ Q_ASSERT_X(false, Q_FUNC_INFO,
+ "This function is not expected to be called.");
+}
+
+QT_END_NAMESPACE
diff --git a/src/xmlpatterns/api/qabstractxmlnodemodel.h b/src/xmlpatterns/api/qabstractxmlnodemodel.h
new file mode 100644
index 0000000000..6c9574c420
--- /dev/null
+++ b/src/xmlpatterns/api/qabstractxmlnodemodel.h
@@ -0,0 +1,423 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtXmlPatterns 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QABSTRACTXMLNODEMODEL_H
+#define QABSTRACTXMLNODEMODEL_H
+
+#include <QtXmlPatterns/QXmlName>
+#include <QtCore/QSharedData>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(XmlPatterns)
+
+/* This file contains the classes QXmlNodeModelIndex, QAbstractXmlNodeModel,
+ * QXmlItem and QPatternist::NodeIndexStorage. */
+
+class QAbstractXmlNodeModel;
+class QAbstractXmlNodeModelPrivate;
+class QAbstractXmlReceiver;
+class QUrl;
+class QXmlName;
+class QXmlNodeModelIndex;
+template<typename T> class QAbstractXmlForwardIterator;
+template<typename T> class QVector;
+
+/* The members in the namespace QPatternist are internal, not part of the public API, and
+ * unsupported. Using them leads to undefined behavior. */
+namespace QPatternist
+{
+ class DynamicContext;
+ class Item;
+ class ItemType;
+ template<typename TResult, typename TSource, typename TMapper, typename Context> class ItemMappingIterator;
+ template<typename TResult, typename TSource, typename TMapper> class SequenceMappingIterator;
+ typedef QExplicitlySharedDataPointer<ItemType> ItemTypePtr;
+ typedef QExplicitlySharedDataPointer<QAbstractXmlForwardIterator<Item> > ItemIteratorPtr;
+ typedef QVector<QXmlName> QXmlNameVector;
+
+ class NodeIndexStorage
+ {
+ public:
+ typedef qint64 Data;
+
+ /*!
+ \note Changing merely the order of these two members, ptr and data,
+ is a binary incompatible change on Mac Power PC.
+ */
+ union
+ {
+ void *ptr; // Do not use ptr directy, use pointer() instead.
+ Data data;
+ };
+ void *pointer() const
+ {
+ /* Constructing to qptrdiff means we avoid the warning "cast to pointer
+ * from integer of different size."
+ */
+ return (void *)qptrdiff(data);
+ }
+
+ Data additionalData;
+ const QAbstractXmlNodeModel *model;
+
+ /* Implementation is in qabstractxmlnodemodel.cpp. */
+ inline bool operator!=(const NodeIndexStorage &other) const;
+ };
+}
+
+class Q_XMLPATTERNS_EXPORT QXmlNodeModelIndex
+{
+ enum Constants
+ {
+ ForwardAxis = 8192,
+ ReverseAxis = 16384
+ };
+
+public:
+ inline QXmlNodeModelIndex()
+ {
+ reset();
+ }
+
+ inline QXmlNodeModelIndex(const QXmlNodeModelIndex &other) : m_storage(other.m_storage)
+ {
+ }
+
+ bool operator==(const QXmlNodeModelIndex &other) const;
+ bool operator!=(const QXmlNodeModelIndex &other) const;
+
+ typedef QAbstractXmlForwardIterator<QXmlNodeModelIndex> Iterator;
+ typedef QList<QXmlNodeModelIndex> List;
+
+ enum NodeKind
+ {
+ Attribute = 1,
+ Comment = 2,
+ Document = 4,
+ Element = 8,
+ Namespace = 16,
+ ProcessingInstruction = 32,
+ Text = 64
+ };
+
+ enum DocumentOrder
+ {
+ Precedes = -1,
+ Is = 0,
+ Follows = 1
+ };
+
+ enum Axis
+ {
+ AxisChild = 1 | ForwardAxis,
+ AxisDescendant = 2 | ForwardAxis,
+ AxisAttribute = 4 | ForwardAxis,
+ AxisSelf = 8 | ForwardAxis,
+ AxisDescendantOrSelf = 16 | ForwardAxis,
+ AxisFollowingSibling = 32 | ForwardAxis,
+ AxisNamespace = 64 | ForwardAxis,
+ AxisFollowing = 128 | ReverseAxis,
+ AxisParent = 256 | ReverseAxis,
+ AxisAncestor = 512 | ReverseAxis,
+ AxisPrecedingSibling = 1024 | ReverseAxis,
+ AxisPreceding = 2048 | ReverseAxis,
+ AxisAncestorOrSelf = 4096 | ReverseAxis,
+ /* Note that we cannot clash with the values of ForwardAxis and
+ * ReverseAxis. */
+ AxisChildOrTop = 32768 | ForwardAxis,
+ AxisAttributeOrTop = 65536 | ForwardAxis
+ };
+
+ inline qint64 data() const
+ {
+ return m_storage.data;
+ }
+
+ inline void *internalPointer() const
+ {
+ return m_storage.pointer();
+ }
+
+ inline const QAbstractXmlNodeModel *model() const
+ {
+ return m_storage.model;
+ }
+
+ inline qint64 additionalData() const
+ {
+ return m_storage.additionalData;
+ }
+
+ inline bool isNull() const
+ {
+ return !m_storage.model;
+ }
+
+ /* The members below are internal, not part of the public API, and
+ * unsupported. Using them leads to undefined behavior. */
+
+ inline QXmlName name() const;
+ inline QXmlNodeModelIndex root() const;
+ inline QExplicitlySharedDataPointer<QAbstractXmlForwardIterator<QXmlNodeModelIndex> > iterate(const Axis axis) const;
+ inline QExplicitlySharedDataPointer<QAbstractXmlForwardIterator<QPatternist::Item> > sequencedTypedValue() const;
+ inline QUrl documentUri() const;
+ inline QUrl baseUri() const;
+ inline NodeKind kind() const;
+ inline bool isDeepEqual(const QXmlNodeModelIndex &other) const;
+ inline DocumentOrder compareOrder(const QXmlNodeModelIndex &other) const;
+ inline void sendNamespaces(QAbstractXmlReceiver *const receiver) const;
+ inline QVector<QXmlName> namespaceBindings() const;
+ inline QXmlName::NamespaceCode namespaceForPrefix(const QXmlName::PrefixCode prefix) const;
+ inline QString stringValue() const;
+ inline QPatternist::ItemTypePtr type() const;
+ inline bool is(const QXmlNodeModelIndex &other) const;
+
+ inline void reset()
+ {
+ m_storage.data = 0;
+ m_storage.additionalData = 0;
+ m_storage.model = 0;
+ }
+
+private:
+ static inline QXmlNodeModelIndex create(const qint64 d,
+ const QAbstractXmlNodeModel *const nm)
+ {
+ QXmlNodeModelIndex n;
+ n.m_storage.data = d;
+ n.m_storage.model = nm;
+ n.m_storage.additionalData = 0;
+ return n;
+ }
+
+ static inline QXmlNodeModelIndex create(const qint64 data,
+ const QAbstractXmlNodeModel *const nm,
+ const qint64 addData)
+ {
+ QXmlNodeModelIndex n;
+ n.m_storage.data = data;
+ n.m_storage.model = nm;
+ n.m_storage.additionalData = addData;
+ return n;
+ }
+
+ inline QXmlNodeModelIndex(const QPatternist::NodeIndexStorage &storage) : m_storage(storage)
+ {
+ }
+
+ friend class QAbstractXmlNodeModel;
+ friend class QPatternist::Item;
+ friend class QXmlItem;
+ inline operator int() const; // Disable
+
+ QPatternist::NodeIndexStorage m_storage;
+};
+
+Q_XMLPATTERNS_EXPORT uint qHash(const QXmlNodeModelIndex &index);
+
+inline bool qIsForwardIteratorEnd(const QXmlNodeModelIndex &item)
+{
+ return item.isNull();
+}
+
+class Q_XMLPATTERNS_EXPORT QAbstractXmlNodeModel : public QSharedData
+{
+public:
+ enum SimpleAxis
+ {
+ Parent,
+ FirstChild,
+ PreviousSibling,
+ NextSibling
+ };
+
+ typedef QExplicitlySharedDataPointer<QAbstractXmlNodeModel> Ptr;
+ typedef QList<Ptr> List;
+
+ QAbstractXmlNodeModel();
+ virtual ~QAbstractXmlNodeModel();
+
+ virtual QUrl baseUri(const QXmlNodeModelIndex &ni) const = 0;
+ virtual QUrl documentUri(const QXmlNodeModelIndex &ni) const = 0;
+ virtual QXmlNodeModelIndex::NodeKind kind(const QXmlNodeModelIndex &ni) const = 0;
+ virtual QXmlNodeModelIndex::DocumentOrder compareOrder(const QXmlNodeModelIndex &ni1,
+ const QXmlNodeModelIndex &ni2) const = 0;
+ virtual QXmlNodeModelIndex root(const QXmlNodeModelIndex &n) const = 0;
+ virtual QXmlName name(const QXmlNodeModelIndex &ni) const = 0;
+ virtual QString stringValue(const QXmlNodeModelIndex &n) const = 0;
+ virtual QVariant typedValue(const QXmlNodeModelIndex &n) const = 0;
+
+ /* The members below are internal, not part of the public API, and
+ * unsupported. Using them leads to undefined behavior. */
+ virtual QExplicitlySharedDataPointer<QAbstractXmlForwardIterator<QXmlNodeModelIndex> > iterate(const QXmlNodeModelIndex &ni, QXmlNodeModelIndex::Axis axis) const;
+ virtual QPatternist::ItemIteratorPtr sequencedTypedValue(const QXmlNodeModelIndex &ni) const;
+ virtual QPatternist::ItemTypePtr type(const QXmlNodeModelIndex &ni) const;
+ virtual QXmlName::NamespaceCode namespaceForPrefix(const QXmlNodeModelIndex &ni,
+ const QXmlName::PrefixCode prefix) const;
+ virtual bool isDeepEqual(const QXmlNodeModelIndex &ni1,
+ const QXmlNodeModelIndex &ni2) const;
+ virtual void sendNamespaces(const QXmlNodeModelIndex &n,
+ QAbstractXmlReceiver *const receiver) const;
+ virtual QVector<QXmlName> namespaceBindings(const QXmlNodeModelIndex &n) const = 0;
+
+
+ virtual QXmlNodeModelIndex elementById(const QXmlName &NCName) const = 0;
+ virtual QVector<QXmlNodeModelIndex> nodesByIdref(const QXmlName &NCName) const = 0;
+
+ enum NodeCopySetting
+ {
+ InheritNamespaces = 0x1,
+ PreserveNamespaces = 0x2
+ };
+
+ typedef QFlags<NodeCopySetting> NodeCopySettings;
+ virtual void copyNodeTo(const QXmlNodeModelIndex &node,
+ QAbstractXmlReceiver *const receiver,
+ const NodeCopySettings &) const;
+
+protected:
+
+ virtual QXmlNodeModelIndex nextFromSimpleAxis(SimpleAxis axis, const QXmlNodeModelIndex &origin) const = 0;
+ virtual QVector<QXmlNodeModelIndex> attributes(const QXmlNodeModelIndex &element) const = 0;
+
+ QAbstractXmlNodeModel(QAbstractXmlNodeModelPrivate *d);
+
+ inline QXmlNodeModelIndex createIndex(qint64 data) const
+ {
+ return QXmlNodeModelIndex::create(data, this);
+ }
+
+ inline QXmlNodeModelIndex createIndex(void * pointer,
+ qint64 additionalData = 0) const
+ {
+ return QXmlNodeModelIndex::create(qptrdiff(pointer), this, additionalData);
+ }
+
+ inline QXmlNodeModelIndex createIndex(qint64 data,
+ qint64 additionalData) const
+ {
+ return QXmlNodeModelIndex::create(data, this, additionalData);
+ }
+
+ QAbstractXmlNodeModelPrivate *d_ptr;
+private:
+ friend class QPatternist::ItemMappingIterator<QXmlNodeModelIndex, QXmlNodeModelIndex, const QAbstractXmlNodeModel *, QExplicitlySharedDataPointer<QPatternist::DynamicContext> >;
+ friend class QPatternist::SequenceMappingIterator<QXmlNodeModelIndex, QXmlNodeModelIndex, const QAbstractXmlNodeModel *>;
+
+ inline QExplicitlySharedDataPointer<QAbstractXmlForwardIterator<QXmlNodeModelIndex> > mapToSequence(const QXmlNodeModelIndex &ni,
+ const QExplicitlySharedDataPointer<QPatternist::DynamicContext> &) const;
+
+ static inline bool isIgnorableInDeepEqual(const QXmlNodeModelIndex &n);
+ Q_DISABLE_COPY(QAbstractXmlNodeModel)
+};
+
+Q_DECLARE_TYPEINFO(QXmlNodeModelIndex, Q_MOVABLE_TYPE);
+
+template<typename T> class QAbstractXmlForwardIterator;
+class QVariant;
+class QXmlItemPrivate;
+
+namespace QPatternist
+{
+ class AtomicValue;
+ class VariableLoader;
+ class IteratorBridge;
+ class ToQXmlItemMapper;
+ class ToItemMapper;
+}
+
+class Q_XMLPATTERNS_EXPORT QXmlItem
+{
+public:
+ typedef QAbstractXmlForwardIterator<QXmlItem> Iterator;
+
+ QXmlItem();
+ QXmlItem(const QXmlItem &other);
+ QXmlItem(const QXmlNodeModelIndex &node);
+ QXmlItem(const QVariant &atomicValue);
+ ~QXmlItem();
+ QXmlItem &operator=(const QXmlItem &other);
+
+ bool isNull() const;
+ bool isNode() const;
+ bool isAtomicValue() const;
+
+ QVariant toAtomicValue() const;
+ QXmlNodeModelIndex toNodeModelIndex() const;
+
+private:
+ friend class QPatternist::IteratorBridge;
+ friend class QPatternist::VariableLoader;
+ friend class QPatternist::ToQXmlItemMapper;
+ friend class QPatternist::ToItemMapper;
+ friend class QPatternist::Item;
+
+ inline bool internalIsAtomicValue() const;
+
+ inline QXmlItem(const QPatternist::Item &i);
+
+ union
+ {
+ QPatternist::NodeIndexStorage m_node;
+
+ /* These two sits at the position of NodeIndexStorage::data.
+ * NodeIndexStorage::{additionalData,model} are free. */
+ const QPatternist::AtomicValue *m_atomicValue;
+ QXmlItemPrivate * m_ptr; /* Not currently used. */
+ };
+};
+
+inline bool qIsForwardIteratorEnd(const QXmlItem &item)
+{
+ return item.isNull();
+}
+
+Q_DECLARE_TYPEINFO(QXmlItem, Q_MOVABLE_TYPE);
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QXmlItem) /* This macro must appear after QT_END_NAMESPACE. */
+
+QT_END_HEADER
+
+#endif
diff --git a/src/xmlpatterns/api/qabstractxmlnodemodel_p.h b/src/xmlpatterns/api/qabstractxmlnodemodel_p.h
new file mode 100644
index 0000000000..16ce6134a5
--- /dev/null
+++ b/src/xmlpatterns/api/qabstractxmlnodemodel_p.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtXmlPatterns 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef QABSTRACTXMLNODEMODEL_P_H
+#define QABSTRACTXMLNODEMODEL_P_H
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QAbstractXmlNodeModelPrivate
+{
+public:
+ virtual ~QAbstractXmlNodeModelPrivate()
+ {
+ }
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/xmlpatterns/api/qabstractxmlreceiver.cpp b/src/xmlpatterns/api/qabstractxmlreceiver.cpp
new file mode 100644
index 0000000000..ddd01e4a96
--- /dev/null
+++ b/src/xmlpatterns/api/qabstractxmlreceiver.cpp
@@ -0,0 +1,476 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtXmlPatterns 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QString>
+
+#include "qitem_p.h"
+
+#include "qabstractxmlreceiver_p.h"
+#include "qabstractxmlreceiver.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QAbstractXmlReceiver
+ \brief The QAbstractXmlReceiver class provides a callback interface
+ for transforming the output of a QXmlQuery.
+ \reentrant
+ \since 4.4
+ \ingroup xml-tools
+
+ QAbstractXmlReceiver is an abstract base class that provides
+ a callback interface for receiving an \l {XQuery Sequence}
+ {XQuery sequence}, usually the output of an QXmlQuery, and
+ transforming that sequence into a structure of your choosing,
+ usually XML. Consider the example:
+
+ \snippet doc/src/snippets/code/src_xmlpatterns_api_qabstractxmlreceiver.cpp 0
+
+ First it constructs a \l {QXmlQuery} {query} that gets the
+ first paragraph from document \c index.html. Then it constructs
+ an \l {QXmlSerializer} {XML serializer} with the \l {QXmlQuery}
+ {query} and \l {QIODevice} {myOutputDevice} (Note the
+ \l {QXmlSerializer} {serializer} is an \e {XML receiver},
+ ie a subclass of QAbstractXmlReceiver). Finally, it
+ \l {QXmlQuery::evaluateTo()} {evaluates} the
+ \l {QXmlQuery} {query}, producing an ordered sequence of calls
+ to the \l {QXmlSerializer} {serializer's} callback functions.
+ The sequence of callbacks transforms the query output to XML
+ and writes it to \l {QIODevice} {myOutputDevice}.
+
+ Although the example uses \l {QXmlQuery} to produce the sequence
+ of callbacks to functions in QAbstractXmlReceiver, you can call
+ the callback functions directly as long as your sequence of
+ calls represents a valid \l {XQuery Sequence} {XQuery sequence}.
+
+ \target XQuery Sequence
+ \section1 XQuery Sequences
+
+ An XQuery \a sequence is an ordered collection of zero, one,
+ or many \e items. Each \e item is either an \e {atomic value}
+ or a \e {node}. An \e {atomic value} is a simple data value.
+
+ There are six kinds of \e nodes.
+
+ \list
+
+ \o An \e {Element Node} represents an XML element.
+
+ \o An \e {Attribute Node} represents an XML attribute.
+
+ \o A \e {Document Node} represents an entire XML document.
+
+ \o A \e {Text Node} represents character data (element content).
+
+ \o A \e {Processing Instruction Node} represents an XML
+ processing instruction, which is used in an XML document
+ to tell the application reading the document to perform
+ some action. A typical example is to use a processing
+ instruction to tell the application to use a particular
+ XSLT stylesheet to display the document.
+
+ \o And a \e {Comment node} represents an XML comment.
+
+ \endlist
+
+ The \e sequence of \e nodes and \e {atomic values} obeys
+ the following rules. Note that \e {Namespace Node} refers
+ to a special \e {Attribute Node} with name \e {xmlns}.
+
+ \list
+
+ \o Each \e node appears in the \e sequence before its children
+ and their descendants appear.
+
+ \o A \e node's descendants appear in the \e sequence before
+ any of its siblings appear.
+
+ \o A \e {Document Node} represents an entire document. Zero or
+ more \e {Document Nodes} can appear in a \e sequence, but they
+ can only be top level items (i.e., a \e {Document Node} can't
+ be a child of another \e node.
+
+ \o \e {Namespace Nodes} immediately follow the \e {Element Node}
+ with which they are associated.
+
+ \o \e {Attribute Nodes} immediately follow the \e {Namespace Nodes}
+ of the element with which they are associated, or...
+
+ \o If there are no \e {Namespace Nodes} following an element, then
+ the \e {Attribute Nodes} immediately follow the element.
+
+ \o An \e {atomic value} can only appear as a top level \e item,
+ i.e., it can't appear as a child of a \e node.
+
+ \o \e {Processing Instruction Nodes} do not have children, and
+ their parent is either a \e {Document Node} or an \e {Element
+ Node}.
+
+ \o \e {Comment Nodes} do not have children, and
+ their parent is either a \e {Document Node} or an \e {Element
+ Node}.
+
+ \endlist
+
+ The \e sequence of \e nodes and \e {atomic values} is sent to
+ an QAbstractXmlReceiver (QXmlSerializer in
+ the example above) as a sequence of calls to the receiver's
+ callback functions. The mapping of callback functions to
+ sequence items is as follows.
+
+ \list
+
+ \o startDocument() and endDocument() are called for each
+ \e {Document Node} in the \e sequence. endDocument() is not
+ called until all the \e {Document Node's} children have
+ appeared in the \e sequence.
+
+ \o startElement() and endElement() are called for each
+ \e {Element Node}. endElement() is not called until all the
+ \e {Element Node's} children have appeared in the \e sequence.
+
+ \o attribute() is called for each \e {Attribute Node}.
+
+ \o comment() is called for each \e {Comment Node}.
+
+ \o characters() is called for each \e {Text Node}.
+
+ \o processingInstruction() is called for each \e {Processing
+ Instruction Node}.
+
+ \o namespaceBinding() is called for each \e {Namespace Node}.
+
+ \o atomicValue() is called for each \e {atomic value}.
+
+ \endlist
+
+ For a complete explanation of XQuery sequences, visit
+ \l {http://www.w3.org/TR/xpath-datamodel/}{XQuery Data Model}.
+
+ \sa {http://www.w3.org/TR/xpath-datamodel/}{W3C XQuery 1.0 and XPath 2.0 Data Model (XDM)}
+ \sa QXmlSerializer
+ \sa QXmlResultItems
+ */
+
+template<const QXmlNodeModelIndex::Axis axis>
+void QAbstractXmlReceiver::sendFromAxis(const QXmlNodeModelIndex &node)
+{
+ Q_ASSERT(!node.isNull());
+ const QXmlNodeModelIndex::Iterator::Ptr it(node.iterate(axis));
+ QXmlNodeModelIndex next(it->next());
+
+ while(!next.isNull())
+ {
+ sendAsNode(next);
+ next = it->next();
+ }
+}
+
+/*!
+ \internal
+ */
+QAbstractXmlReceiver::QAbstractXmlReceiver(QAbstractXmlReceiverPrivate *d)
+ : d_ptr(d)
+{
+}
+
+/*!
+ Constructs an abstract xml receiver.
+ */
+QAbstractXmlReceiver::QAbstractXmlReceiver() : d_ptr(0)
+{
+}
+
+/*!
+ Destroys the xml receiver.
+ */
+QAbstractXmlReceiver::~QAbstractXmlReceiver()
+{
+ delete d_ptr;
+}
+
+/*!
+ \fn void QAbstractXmlReceiver::startElement(const QXmlName &name)
+
+ This callback is called when a new element node appears
+ in the \l {XQuery Sequence} {sequence}. \a name is the
+ valid \l {QXmlName} {name} of the node element.
+ */
+
+/*
+### Qt 5:
+
+Consider how source locations should be communicated. Maybe every signature
+should be extended by adding "qint64 line = -1, qint64 column = -1".
+ */
+
+/*!
+ \fn void QAbstractXmlReceiver::endElement()
+
+ This callback is called when the end of an element node
+ appears in the \l {XQuery Sequence} {sequence}.
+*/
+
+/*!
+ \fn void QAbstractXmlReceiver::attribute(const QXmlName &name,
+ const QStringRef &value)
+ This callback is called when an attribute node
+ appears in the \l {XQuery Sequence} {sequence}.
+ \a name is the \l {QXmlName} {attribute name} and
+ the \a value string contains the attribute value.
+ */
+
+/*!
+ \fn void QAbstractXmlReceiver::comment(const QString &value)
+
+ This callback is called when a comment node appears
+ in the \l {XQuery Sequence} {sequence}. The \a value
+ is the comment text, which must not contain the string
+ "--".
+ */
+
+/*!
+ \fn void QAbstractXmlReceiver::characters(const QStringRef &value)
+
+ This callback is called when a text node appears in the
+ \l {XQuery Sequence} {sequence}. The \a value contains
+ the text. Adjacent text nodes may not occur in the
+ \l {XQuery Sequence} {sequence}, i.e., this callback must not
+ be called twice in a row.
+ */
+
+/*!
+ \fn void QAbstractXmlReceiver::startDocument()
+
+ This callback is called when a document node appears
+ in the \l {XQuery Sequence} {sequence}.
+ */
+
+/*
+### Qt 5:
+
+Change
+ virtual void startDocument() = 0;
+
+To:
+ virtual void startDocument(const QUrl &uri) = 0;
+
+Such that it allows the document URI to be communicated. The contract would
+allow null QUrls.
+*/
+
+/*!
+ \fn void QAbstractXmlReceiver::endDocument()
+
+ This callback is called when the end of a document node
+ appears in the \l {XQuery Sequence} {sequence}.
+ */
+
+/*!
+ \fn void QAbstractXmlReceiver::processingInstruction(const QXmlName &target,
+ const QString &value)
+
+ This callback is called when a processing instruction
+ appears in the \l {XQuery Sequence} {sequence}.
+ A processing instruction is used in an XML document
+ to tell the application reading the document to
+ perform some action. A typical example is to use a
+ processing instruction to tell the application to use a
+ particular XSLT stylesheet to process the document.
+
+ \quotefile doc/src/snippets/patternist/xmlStylesheet.xq
+
+ \a target is the \l {QXmlName} {name} of the processing
+ instruction. Its \e prefix and \e {namespace URI} must both
+ be empty. Its \e {local name} is the target. In the above
+ example, the name is \e {xml-stylesheet}.
+
+ The \a value specifies the action to be taken. Note that
+ the \a value must not contain the string "?>". In the above
+ example, the \a value is \e{type="test/xsl" href="formatter.xsl}.
+
+ Generally, use of processing instructions should be avoided,
+ because they are not namespace aware and in many contexts
+ are stripped out anyway. Processing instructions can often
+ be replaced with elements from a custom namespace.
+ */
+
+/*!
+ \fn void QAbstractXmlReceiver::atomicValue(const QVariant &value)
+
+ This callback is called when an atomic value appears in the \l
+ {XQuery Sequence} {sequence}. The \a value is a simple \l {QVariant}
+ {data value}. It is guaranteed to be \l {QVariant::isValid()}
+ {valid}.
+ */
+
+/*!
+ \fn virtual void QAbstractXmlReceiver::namespaceBinding(const QXmlName &name)
+
+ This callback is called when a namespace binding is in scope of an
+ element. A namespace is defined by a URI. In the \l {QXmlName}
+ \a name, the value of \l {QXmlName::namespaceUri()} is that URI. The
+ value of \l {QXmlName::prefix()} is the prefix that the URI is bound
+ to. The local name is insignificant and can be an arbitrary value.
+ */
+
+/*!
+ \internal
+
+ Treats \a outputItem as a node and calls the appropriate function,
+ e.g., attribute() or comment(), depending on its
+ QXmlNodeModelIndex::NodeKind.
+
+ This is a helper function that subclasses can use to multiplex
+ Nodes received via item().
+ */
+void QAbstractXmlReceiver::sendAsNode(const QPatternist::Item &outputItem)
+{
+ Q_ASSERT(outputItem);
+ Q_ASSERT(outputItem.isNode());
+ const QXmlNodeModelIndex asNode = outputItem.asNode();
+
+ switch(asNode.kind())
+ {
+ case QXmlNodeModelIndex::Attribute:
+ {
+ const QString &v = outputItem.stringValue();
+ attribute(asNode.name(), QStringRef(&v));
+ return;
+ }
+ case QXmlNodeModelIndex::Element:
+ {
+ startElement(asNode.name());
+
+ /* First the namespaces, then attributes, then the children. */
+ asNode.sendNamespaces(this);
+ sendFromAxis<QXmlNodeModelIndex::AxisAttribute>(asNode);
+ sendFromAxis<QXmlNodeModelIndex::AxisChild>(asNode);
+
+ endElement();
+
+ return;
+ }
+ case QXmlNodeModelIndex::Text:
+ {
+ const QString &v = asNode.stringValue();
+ characters(QStringRef(&v));
+ return;
+ }
+ case QXmlNodeModelIndex::ProcessingInstruction:
+ {
+ processingInstruction(asNode.name(), outputItem.stringValue());
+ return;
+ }
+ case QXmlNodeModelIndex::Comment:
+ {
+ comment(outputItem.stringValue());
+ return;
+ }
+ case QXmlNodeModelIndex::Document:
+ {
+ startDocument();
+ sendFromAxis<QXmlNodeModelIndex::AxisChild>(asNode);
+ endDocument();
+ return;
+ }
+ case QXmlNodeModelIndex::Namespace:
+ Q_ASSERT_X(false, Q_FUNC_INFO, "Not implemented");
+ }
+
+ Q_ASSERT_X(false, Q_FUNC_INFO,
+ QString::fromLatin1("Unknown node type: %1").arg(asNode.kind()).toUtf8().constData());
+}
+
+/*!
+ \internal
+
+ This function may be called instead of characters() if, and only if,
+ \a value consists only of whitespace.
+
+ The caller gurantees that \a value is not empty.
+
+ \e Whitespace refers to a sequence of characters that are either
+ spaces, tabs, or newlines, in any order. In other words, not all
+ the Unicode whitespace category is considered whitespace here.
+
+ However, there is no guarantee or requirement that whitespaceOnly()
+ is called for text nodes containing whitespace only. characters()
+ may be called just as well. This is why the default implementation
+ for whitespaceOnly() calls characters().
+
+ \sa characters()
+ */
+void QAbstractXmlReceiver::whitespaceOnly(const QStringRef &value)
+{
+ Q_ASSERT_X(value.toString().trimmed().isEmpty(), Q_FUNC_INFO,
+ "The caller must guarantee only whitespace is passed. Use characters() in other cases.");
+ const QString &v = value.toString();
+ characters(QStringRef(&v));
+}
+
+/*!
+ \internal
+ */
+void QAbstractXmlReceiver::item(const QPatternist::Item &item)
+{
+ if(item.isNode())
+ return sendAsNode(item);
+ else
+ atomicValue(QPatternist::AtomicValue::toQt(item.asAtomicValue()));
+}
+
+/*!
+ \fn void QAbstractXmlReceiver::startOfSequence()
+
+ This callback is called once only, right before the
+ \l {XQuery Sequence} {sequence} begins.
+ */
+
+/*!
+ \fn void QAbstractXmlReceiver::endOfSequence()
+
+ This callback is called once only, right after the
+ \l {XQuery Sequence} {sequence} ends.
+ */
+
+QT_END_NAMESPACE
+
diff --git a/src/xmlpatterns/api/qabstractxmlreceiver.h b/src/xmlpatterns/api/qabstractxmlreceiver.h
new file mode 100644
index 0000000000..355576a198
--- /dev/null
+++ b/src/xmlpatterns/api/qabstractxmlreceiver.h
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtXmlPatterns 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QABSTRACTXMLRECEIVER_H
+#define QABSTRACTXMLRECEIVER_H
+
+#include <QtCore/QVariant>
+#include <QtXmlPatterns/QXmlNodeModelIndex>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(XmlPatterns)
+
+class QAbstractXmlReceiverPrivate;
+class QXmlName;
+
+namespace QPatternist
+{
+ class Item;
+}
+
+class Q_XMLPATTERNS_EXPORT QAbstractXmlReceiver
+{
+public:
+ QAbstractXmlReceiver();
+
+ virtual ~QAbstractXmlReceiver();
+
+ virtual void startElement(const QXmlName &name) = 0;
+ virtual void endElement() = 0;
+ virtual void attribute(const QXmlName &name,
+ const QStringRef &value) = 0;
+ virtual void comment(const QString &value) = 0;
+ virtual void characters(const QStringRef &value) = 0;
+ virtual void startDocument() = 0;
+ virtual void endDocument() = 0;
+
+ virtual void processingInstruction(const QXmlName &target,
+ const QString &value) = 0;
+
+ virtual void atomicValue(const QVariant &value) = 0;
+ virtual void namespaceBinding(const QXmlName &name) = 0;
+ virtual void startOfSequence() = 0;
+ virtual void endOfSequence() = 0;
+
+ /* The members below are internal, not part of the public API, and
+ * unsupported. Using them leads to undefined behavior. */
+ virtual void whitespaceOnly(const QStringRef &value);
+ virtual void item(const QPatternist::Item &item);
+
+protected:
+ QAbstractXmlReceiver(QAbstractXmlReceiverPrivate *d);
+ QAbstractXmlReceiverPrivate *d_ptr;
+
+ void sendAsNode(const QPatternist::Item &outputItem);
+private:
+ template<const QXmlNodeModelIndex::Axis axis>
+ void sendFromAxis(const QXmlNodeModelIndex &node);
+ Q_DISABLE_COPY(QAbstractXmlReceiver)
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/xmlpatterns/api/qabstractxmlreceiver_p.h b/src/xmlpatterns/api/qabstractxmlreceiver_p.h
new file mode 100644
index 0000000000..3954a4f9c2
--- /dev/null
+++ b/src/xmlpatterns/api/qabstractxmlreceiver_p.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtXmlPatterns 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef QABSTRACTXMLRECEIVER_P_H
+#define QABSTRACTXMLRECEIVER_P_H
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QAbstractXmlReceiverPrivate
+{
+public:
+ virtual ~QAbstractXmlReceiverPrivate()
+ {
+ }
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/xmlpatterns/api/qdeviceresourceloader_p.h b/src/xmlpatterns/api/qdeviceresourceloader_p.h
new file mode 100644
index 0000000000..be88a76217
--- /dev/null
+++ b/src/xmlpatterns/api/qdeviceresourceloader_p.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtXmlPatterns 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef QPatternist_DeviceResourceLoader_p_H
+#define QPatternist_DeviceResourceLoader_p_H
+
+template<typename T> class QSet;
+class QUrl;
+
+#include "qresourceloader_p.h"
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+namespace QPatternist
+{
+ /**
+ * @short Base class for resource loaders that manage device variables.
+ *
+ * @author Frans Englich <fenglich@trolltech.com>
+ * @since 4.5
+ */
+ class DeviceResourceLoader : public ResourceLoader
+ {
+ public:
+ typedef QExplicitlySharedDataPointer<DeviceResourceLoader> Ptr;
+ /**
+ * @short Returns the URIs for device variables that this
+ * ResourceLoader has loaded.
+ *
+ * The returned set may be empty.
+ */
+ virtual QSet<QUrl> deviceURIs() const = 0;
+ };
+}
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif
diff --git a/src/xmlpatterns/api/qiodevicedelegate.cpp b/src/xmlpatterns/api/qiodevicedelegate.cpp
new file mode 100644
index 0000000000..05820a75b0
--- /dev/null
+++ b/src/xmlpatterns/api/qiodevicedelegate.cpp
@@ -0,0 +1,166 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtXmlPatterns 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtDebug>
+
+#include "qpatternistlocale_p.h"
+
+#include "qiodevicedelegate_p.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace QPatternist;
+
+QIODeviceDelegate::QIODeviceDelegate(QIODevice *const source) : m_source(source)
+{
+ Q_ASSERT(m_source);
+
+ connect(source, SIGNAL(aboutToClose()), SIGNAL(aboutToClose()));
+ connect(source, SIGNAL(bytesWritten(qint64)), SIGNAL(bytesWritten(qint64)));
+ connect(source, SIGNAL(readChannelFinished()), SIGNAL(readChannelFinished()));
+ connect(source, SIGNAL(readyRead()), SIGNAL(readyRead()));
+
+ /* According to Thiago these two signals are very similar, but QtNetworkAccess uses finished()
+ * instead for a minor but significant reason. */
+ connect(source, SIGNAL(readChannelFinished()), SIGNAL(finished()));
+
+ /* For instance QFile emits no signals, so how do we know if the device has all data available
+ * and it therefore is safe and correct to emit finished()? isSequential() tells us whether it's
+ * not random access, and whether it's safe to emit finished(). */
+ if(m_source->isSequential())
+ QMetaObject::invokeMethod(this, "readyRead", Qt::QueuedConnection);
+ else
+ QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection);
+
+ setOpenMode(QIODevice::ReadOnly);
+
+ /* Set up the timeout timer. */
+ connect(&m_timeout, SIGNAL(timeout()), SLOT(networkTimeout()));
+
+ m_timeout.setSingleShot(true);
+ m_timeout.start(Timeout);
+}
+
+void QIODeviceDelegate::networkTimeout()
+{
+ setErrorString(QtXmlPatterns::tr("Network timeout."));
+ error(QNetworkReply::TimeoutError);
+}
+
+void QIODeviceDelegate::abort()
+{
+ /* Do nothing, just to please QNetworkReply's pure virtual. */
+}
+
+bool QIODeviceDelegate::atEnd() const
+{
+ return m_source->atEnd();
+}
+
+qint64 QIODeviceDelegate::bytesAvailable() const
+{
+ return m_source->bytesAvailable();
+}
+
+qint64 QIODeviceDelegate::bytesToWrite() const
+{
+ return m_source->bytesToWrite();
+}
+
+bool QIODeviceDelegate::canReadLine() const
+{
+ return m_source->canReadLine();
+}
+
+void QIODeviceDelegate::close()
+{
+ return m_source->close();
+}
+
+bool QIODeviceDelegate::isSequential() const
+{
+ return m_source->isSequential();
+}
+
+bool QIODeviceDelegate::open(OpenMode mode)
+{
+ const bool success = m_source->open(mode);
+ setOpenMode(m_source->openMode());
+ return success;
+}
+
+qint64 QIODeviceDelegate::pos() const
+{
+ return m_source->pos();
+}
+
+bool QIODeviceDelegate::reset()
+{
+ return m_source->reset();
+}
+
+bool QIODeviceDelegate::seek(qint64 pos)
+{
+ return m_source->seek(pos);
+}
+
+qint64 QIODeviceDelegate::size() const
+{
+ return m_source->size();
+}
+
+bool QIODeviceDelegate::waitForBytesWritten(int msecs)
+{
+ return m_source->waitForBytesWritten(msecs);
+}
+
+bool QIODeviceDelegate::waitForReadyRead(int msecs)
+{
+ return m_source->waitForReadyRead(msecs);
+}
+
+qint64 QIODeviceDelegate::readData(char *data, qint64 maxSize)
+{
+ return m_source->read(data, maxSize);
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/xmlpatterns/api/qiodevicedelegate_p.h b/src/xmlpatterns/api/qiodevicedelegate_p.h
new file mode 100644
index 0000000000..bf4e882da1
--- /dev/null
+++ b/src/xmlpatterns/api/qiodevicedelegate_p.h
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtXmlPatterns 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef QIODEVICEDELEGATE_P_H
+#define QIODEVICEDELEGATE_P_H
+
+#include <QtCore/QTimer>
+#include <QtNetwork/QNetworkReply>
+
+QT_BEGIN_NAMESPACE
+
+namespace QPatternist
+{
+ /**
+ * This is read-only currently.
+ */
+ class QIODeviceDelegate : public QNetworkReply
+ {
+ Q_OBJECT
+ public:
+ QIODeviceDelegate(QIODevice *const source);
+
+ virtual void abort();
+
+ virtual bool atEnd() const;
+ virtual qint64 bytesAvailable() const;
+ virtual qint64 bytesToWrite() const;
+ virtual bool canReadLine() const;
+ virtual void close();
+ virtual bool isSequential() const;
+ virtual bool open(OpenMode mode);
+ virtual qint64 pos() const;
+ virtual bool reset();
+ virtual bool seek(qint64 pos);
+ virtual qint64 size() const;
+ virtual bool waitForBytesWritten(int msecs);
+ virtual bool waitForReadyRead(int msecs);
+
+ protected:
+ virtual qint64 readData(char *data, qint64 maxSize);
+
+ private Q_SLOTS:
+ void networkTimeout();
+ private:
+ enum
+ {
+ /**
+ * 20 seconds expressed in milliseconds.
+ */
+ Timeout = 20000
+ };
+
+ QIODevice *const m_source;
+ QTimer m_timeout;
+ };
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/xmlpatterns/api/qnetworkaccessdelegator.cpp b/src/xmlpatterns/api/qnetworkaccessdelegator.cpp
new file mode 100644
index 0000000000..3ca0383c19
--- /dev/null
+++ b/src/xmlpatterns/api/qnetworkaccessdelegator.cpp
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtXmlPatterns 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QUrl>
+
+#include <QNetworkAccessManager>
+
+#include "qnetworkaccessdelegator_p.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace QPatternist;
+
+NetworkAccessDelegator::NetworkAccessDelegator(QNetworkAccessManager *const genericManager,
+ QNetworkAccessManager *const variableURIManager) : m_genericManager(genericManager)
+ , m_variableURIManager(variableURIManager)
+{
+}
+
+QNetworkAccessManager *NetworkAccessDelegator::managerFor(const QUrl &uri)
+{
+ /* Unfortunately we have to do it this way, QUrl::isParentOf() doesn't
+ * understand URI schemes like this one. */
+ const QString requestedUrl(uri.toString());
+
+ /* On the topic of timeouts:
+ *
+ * Currently the schemes QNetworkAccessManager handles should/will do
+ * timeouts for 4.4, but we need to do timeouts for our own. */
+ if(requestedUrl.startsWith(QLatin1String("tag:trolltech.com,2007:QtXmlPatterns:QIODeviceVariable:")))
+ return m_variableURIManager;
+ else
+ {
+ if(!m_genericManager)
+ m_genericManager = new QNetworkAccessManager(this);
+
+ return m_genericManager;
+ }
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/xmlpatterns/api/qnetworkaccessdelegator_p.h b/src/xmlpatterns/api/qnetworkaccessdelegator_p.h
new file mode 100644
index 0000000000..7b7c0a48e8
--- /dev/null
+++ b/src/xmlpatterns/api/qnetworkaccessdelegator_p.h
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtXmlPatterns 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef QNETWORKACCESSDELEGATOR_P_H
+#define QNETWORKACCESSDELEGATOR_P_H
+
+#include <QObject>
+#include <QPointer>
+#include <QSharedData>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+class QNetworkAccessManager;
+class QUrl;
+
+namespace QPatternist
+{
+ /**
+ * @short A value based class that hands out QNetworkAccessManager
+ * appropriately for variable bindings.
+ *
+ * NetworkAccessDelegator is an indirection mechanism which takes care of
+ * the fact that QIODevice instances are injected into the data model by
+ * having them represented using a URI. managerFor() returns appropriately
+ * the right network access manager depending on whether the URI refers to
+ * a variable, or to something else.
+ *
+ * The constructor take a pointer to two NetworkAccessDelegator instances.
+ * First is a generic one, the second is the one which handles variable
+ * bindings. managerFor() then returns the appropriate one depending on the
+ * URI.
+ *
+ * @since 4.5
+ * @see AccelTreeResourceLoader::load()
+ * @author Frans Englich <fenglich@trolltech.com>
+ */
+ class Q_AUTOTEST_EXPORT NetworkAccessDelegator : public QObject
+ , public QSharedData
+ {
+ public:
+ typedef QExplicitlySharedDataPointer<NetworkAccessDelegator> Ptr;
+ NetworkAccessDelegator(QNetworkAccessManager *const genericManager,
+ QNetworkAccessManager *const variableURIManager);
+
+ QNetworkAccessManager *managerFor(const QUrl &uri);
+
+ QPointer<QNetworkAccessManager> m_genericManager;
+ QPointer<QNetworkAccessManager> m_variableURIManager;
+ private:
+ Q_DISABLE_COPY(NetworkAccessDelegator)
+ };
+}
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif
diff --git a/src/xmlpatterns/api/qreferencecountedvalue_p.h b/src/xmlpatterns/api/qreferencecountedvalue_p.h
new file mode 100644
index 0000000000..49437f2c04
--- /dev/null
+++ b/src/xmlpatterns/api/qreferencecountedvalue_p.h
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtXmlPatterns 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef QPatternist_ReferenceCountedValue_p_h
+#define QPatternist_ReferenceCountedValue_p_h
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+namespace QPatternist
+{
+/*!
+ \class ReferenceCountedValue
+ \internal
+ \since 4.4
+ \brief A template class that reference counts a value.
+
+ This class is useful when an instance needs to have ownership semantics
+ as if it was value based. A typical examples is a QObject pointer, which
+ doesn't have a single owner.
+
+ This is achieved through storing a copy of the object as
+ a member inside ReferenceCountedValue, which never is copied. It will
+ stay in scope until the last reference to the ReferenceCountedValue instance
+ is removed, and subsequently ReferenceCountedValue is deleted and hence also
+ the contained value. One should use ReferenceCountedValue by passing around
+ copies of Ptr, which is a typedef for the QExplicitlySharedDataPointer
+ smart pointer.
+*/
+ template<typename T>
+ class ReferenceCountedValue : public QSharedData
+ {
+ public:
+ typedef QExplicitlySharedDataPointer<ReferenceCountedValue<T> > Ptr;
+
+ inline ReferenceCountedValue(T *const v) : value(v)
+ {
+ }
+
+ inline ~ReferenceCountedValue()
+ {
+ delete value;
+ }
+
+ T *const value;
+ private:
+ /*!
+ Disabled, no implementation provided.
+ */
+ inline ReferenceCountedValue();
+ Q_DISABLE_COPY(ReferenceCountedValue)
+ };
+}
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif
diff --git a/src/xmlpatterns/api/qresourcedelegator.cpp b/src/xmlpatterns/api/qresourcedelegator.cpp
new file mode 100644
index 0000000000..9d43419310
--- /dev/null
+++ b/src/xmlpatterns/api/qresourcedelegator.cpp
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtXmlPatterns 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qresourcedelegator_p.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace QPatternist;
+
+/**
+ * Duplicated in qacceltreeresourceloader.cpp.
+ */
+static inline uint qHash(const QUrl &uri)
+{
+ return qHash(uri.toString());
+}
+
+bool ResourceDelegator::isUnparsedTextAvailable(const QUrl &uri,
+ const QString &encoding)
+{
+ return m_parentLoader->isUnparsedTextAvailable(uri, encoding);
+}
+
+ItemType::Ptr ResourceDelegator::announceUnparsedText(const QUrl &uri)
+{
+ return m_parentLoader->announceUnparsedText(uri);
+}
+
+Item ResourceDelegator::openUnparsedText(const QUrl &uri,
+ const QString &encoding,
+ const ReportContext::Ptr &context,
+ const SourceLocationReflection *const where)
+{
+ return m_parentLoader->openUnparsedText(uri, encoding, context, where);
+}
+
+Item ResourceDelegator::openDocument(const QUrl &uri,
+ const ReportContext::Ptr &context)
+{
+ if(m_needsOverride.contains(uri))
+ return m_forDeviceLoader->openDocument(uri, context);
+ else
+ return m_parentLoader->openDocument(uri, context);
+}
+
+SequenceType::Ptr ResourceDelegator::announceDocument(const QUrl &uri, const Usage usageHint)
+{
+ return m_parentLoader->announceDocument(uri, usageHint);
+}
+
+bool ResourceDelegator::isDocumentAvailable(const QUrl &uri)
+{
+ return m_parentLoader->isDocumentAvailable(uri);
+}
+
+Item::Iterator::Ptr ResourceDelegator::openCollection(const QUrl &uri)
+{
+ return m_parentLoader->openCollection(uri);
+}
+
+SequenceType::Ptr ResourceDelegator::announceCollection(const QUrl &uri)
+{
+ return m_parentLoader->announceCollection(uri);
+}
+
+QSet<QUrl> ResourceDelegator::deviceURIs() const
+{
+ QSet<QUrl> uris(m_needsOverride);
+ uris |= m_forDeviceLoader->deviceURIs();
+ return uris;
+}
+
+QT_END_NAMESPACE
diff --git a/src/xmlpatterns/api/qresourcedelegator_p.h b/src/xmlpatterns/api/qresourcedelegator_p.h
new file mode 100644
index 0000000000..d0f832ea0a
--- /dev/null
+++ b/src/xmlpatterns/api/qresourcedelegator_p.h
@@ -0,0 +1,119 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtXmlPatterns 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef QPatternist_ResourceDelegator_p_H
+#define QPatternist_ResourceDelegator_p_H
+
+#include <QSet>
+#include <QUrl>
+
+#include "qdeviceresourceloader_p.h"
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+namespace QPatternist
+{
+ /**
+ * @short Delegates to another ResourceLoader, but in case a URI is in an
+ * exception list, it delegates to a different loader.
+ *
+ * This is used for handling device variables, since when a device variable
+ * is rebound, a resource loader needs to carry that binding, while the
+ * resource loader for the other query remains as is.
+ *
+ * @since 4.5
+ * @author Frans Englich <fenglich@trolltech.com>
+ */
+ class ResourceDelegator : public DeviceResourceLoader
+ {
+ public:
+ ResourceDelegator(const QSet<QUrl> &needsOverride,
+ const ResourceLoader::Ptr &parentLoader,
+ const ResourceLoader::Ptr &forDeviceLoader) : m_needsOverride(needsOverride)
+ , m_parentLoader(parentLoader)
+ , m_forDeviceLoader(forDeviceLoader)
+
+ {
+ Q_ASSERT(m_parentLoader);
+ }
+
+ virtual bool isUnparsedTextAvailable(const QUrl &uri,
+ const QString &encoding);
+ virtual ItemType::Ptr announceUnparsedText(const QUrl &uri);
+ virtual Item openUnparsedText(const QUrl &uri,
+ const QString &encoding,
+ const ReportContext::Ptr &context,
+ const SourceLocationReflection *const where);
+ virtual Item openDocument(const QUrl &uri,
+ const ReportContext::Ptr &context);
+ virtual SequenceType::Ptr announceDocument(const QUrl &uri, const Usage usageHint);
+ virtual bool isDocumentAvailable(const QUrl &uri);
+ virtual Item::Iterator::Ptr openCollection(const QUrl &uri);
+ virtual SequenceType::Ptr announceCollection(const QUrl &uri);
+
+ /**
+ * Returns the union of the deviceURIs() that ResourceDelegator's two
+ * resource loaders has.
+ */
+ virtual QSet<QUrl> deviceURIs() const;
+
+ private:
+ const QSet<QUrl> m_needsOverride;
+ const ResourceLoader::Ptr m_parentLoader;
+ const ResourceDelegator::Ptr m_forDeviceLoader;
+ };
+}
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif
diff --git a/src/xmlpatterns/api/qsimplexmlnodemodel.cpp b/src/xmlpatterns/api/qsimplexmlnodemodel.cpp
new file mode 100644
index 0000000000..119a4b1e28
--- /dev/null
+++ b/src/xmlpatterns/api/qsimplexmlnodemodel.cpp
@@ -0,0 +1,184 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtXmlPatterns 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QUrl>
+#include <QVector>
+#include <QXmlNamePool>
+
+#include "qabstractxmlnodemodel_p.h"
+#include "qemptyiterator_p.h"
+#include "qitemmappingiterator_p.h"
+#include "qsequencemappingiterator_p.h"
+#include "qsimplexmlnodemodel.h"
+#include "qsingletoniterator_p.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace QPatternist;
+
+class QSimpleXmlNodeModelPrivate : public QAbstractXmlNodeModelPrivate
+{
+public:
+ QSimpleXmlNodeModelPrivate(const QXmlNamePool &np) : namePool(np)
+ {
+ }
+
+ mutable QXmlNamePool namePool;
+};
+
+/*!
+ \class QSimpleXmlNodeModel
+ \brief The QSimpleXmlNodeModel class is an implementation of QAbstractXmlNodeModel sufficient for many common cases.
+ \reentrant
+ \since 4.4
+ \ingroup xml-tools
+
+ Subclassing QAbstractXmlNodeModel can be a significant task, because it
+ requires implementing several, complex member functions. QSimpleXmlNodeModel
+ provides default implementations of these member functions that are suitable
+ for a wide range of node models.
+
+ Subclasses of QSimpleXmlNodeModel must be thread-safe.
+ */
+
+/*!
+ Constructs a QSimpleXmlNodeModel for use with with the specified
+ \a namePool.
+ */
+QSimpleXmlNodeModel::QSimpleXmlNodeModel(const QXmlNamePool &namePool)
+ : QAbstractXmlNodeModel(new QSimpleXmlNodeModelPrivate(namePool))
+{
+}
+
+/*!
+ Destructor.
+ */
+QSimpleXmlNodeModel::~QSimpleXmlNodeModel()
+{
+}
+
+/*!
+ If \a node is an element or attribute, typedValue() is called, and
+ the return value converted to a string, as per XQuery's rules.
+
+ If \a node is another type of node, the empty string is returned.
+
+ If this function is overridden for comments or processing
+ instructions, it is important to remember to call it (for elements
+ and attributes having values not of type \c xs:string) to ensure that
+ the values are formatted according to XQuery.
+
+ */
+QString QSimpleXmlNodeModel::stringValue(const QXmlNodeModelIndex &node) const
+{
+ const QXmlNodeModelIndex::NodeKind k= kind(node);
+ if(k == QXmlNodeModelIndex::Element || k == QXmlNodeModelIndex::Attribute)
+ {
+ const QVariant &candidate = typedValue(node);
+ if(candidate.isNull())
+ return QString();
+ else
+ return AtomicValue::toXDM(candidate).stringValue();
+ }
+ else
+ return QString();
+}
+
+/*!
+ Returns the base URI for \a node. This is always the document
+ URI.
+
+ \sa documentUri()
+ */
+QUrl QSimpleXmlNodeModel::baseUri(const QXmlNodeModelIndex &node) const
+{
+ return documentUri(node);
+}
+
+/*!
+ Returns the name pool associated with this model. The
+ implementation of name() will use this name pool to create
+ names.
+ */
+QXmlNamePool &QSimpleXmlNodeModel::namePool() const
+{
+ Q_D(const QSimpleXmlNodeModel);
+
+ return d->namePool;
+}
+
+/*!
+ Always returns an empty QVector. This signals that no namespace
+ bindings are in scope for \a node.
+ */
+QVector<QXmlName> QSimpleXmlNodeModel::namespaceBindings(const QXmlNodeModelIndex &node) const
+{
+ Q_UNUSED(node);
+ return QVector<QXmlName>();
+}
+
+/*!
+ Always returns a default constructed QXmlNodeModelIndex instance,
+ regardless of \a id.
+
+ This effectively means the model has no elements that have an id.
+ */
+QXmlNodeModelIndex QSimpleXmlNodeModel::elementById(const QXmlName &id) const
+{
+ Q_UNUSED(id);
+ return QXmlNodeModelIndex();
+}
+
+/*!
+ Always returns an empty vector, regardless of \a idref.
+
+ This effectively means the model has no elements or attributes of
+ type \c IDREF.
+ */
+QVector<QXmlNodeModelIndex> QSimpleXmlNodeModel::nodesByIdref(const QXmlName &idref) const
+{
+ Q_UNUSED(idref);
+ return QVector<QXmlNodeModelIndex>();
+}
+
+QT_END_NAMESPACE
+
+
diff --git a/src/xmlpatterns/api/qsimplexmlnodemodel.h b/src/xmlpatterns/api/qsimplexmlnodemodel.h
new file mode 100644
index 0000000000..14e2faf3c4
--- /dev/null
+++ b/src/xmlpatterns/api/qsimplexmlnodemodel.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtXmlPatterns 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSIMPLEXMLNODEMODEL_H
+#define QSIMPLEXMLNODEMODEL_H
+
+#include <QtXmlPatterns/QAbstractXmlNodeModel>
+#include <QtXmlPatterns/QXmlQuery>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(XmlPatterns)
+
+template<typename T> class QExplicitlySharedDataPointer;
+class QSimpleXmlNodeModelPrivate;
+class Q_XMLPATTERNS_EXPORT QSimpleXmlNodeModel : public QAbstractXmlNodeModel
+{
+public:
+ QSimpleXmlNodeModel(const QXmlNamePool &namePool);
+ virtual ~QSimpleXmlNodeModel();
+
+ virtual QUrl baseUri(const QXmlNodeModelIndex &node) const;
+ QXmlNamePool &namePool() const;
+ virtual QVector<QXmlName> namespaceBindings(const QXmlNodeModelIndex&) const;
+ virtual QString stringValue(const QXmlNodeModelIndex &node) const;
+ virtual QXmlNodeModelIndex elementById(const QXmlName &id) const;
+ virtual QVector<QXmlNodeModelIndex> nodesByIdref(const QXmlName &idref) const;
+
+private:
+ Q_DECLARE_PRIVATE(QSimpleXmlNodeModel)
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/xmlpatterns/api/qsourcelocation.cpp b/src/xmlpatterns/api/qsourcelocation.cpp
new file mode 100644
index 0000000000..4eee39ce74
--- /dev/null
+++ b/src/xmlpatterns/api/qsourcelocation.cpp
@@ -0,0 +1,240 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtXmlPatterns 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdebug_p.h"
+
+#include "qsourcelocation.h"
+
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QSourceLocation
+ \reentrant
+ \since 4.4
+ \brief The QSourceLocation class identifies a location in a resource by URI, line, and column.
+ \ingroup xml-tools
+
+ QSourceLocation is a simple value based class that has three
+ properties, uri(), line(), and column(), that, taken together,
+ identify a certain point in a resource, e.g., a file or an in-memory
+ document.
+
+ line() and column() refer to character counts (not byte counts), and
+ they both start from 1, as opposed to 0.
+ */
+
+/*!
+ Construct a QSourceLocation that doesn't identify anything at all.
+
+ For a default constructed QSourceLocation(), isNull() returns \c true.
+ */
+QSourceLocation::QSourceLocation() : m_line(-1), m_column(-1)
+{
+}
+
+/*!
+ Constructs a QSourceLocation that is a copy of \a other.
+ */
+QSourceLocation::QSourceLocation(const QSourceLocation &other)
+ : m_line(other.m_line), m_column(other.m_column), m_uri(other.m_uri)
+{
+}
+
+/*!
+ Constructs a QSourceLocation with URI \a u, line \a l and column \a c.
+ */
+QSourceLocation::QSourceLocation(const QUrl &u, int l, int c)
+ : m_line(l), m_column(c), m_uri(u)
+{
+}
+
+/*!
+ Destructor.
+ */
+QSourceLocation::~QSourceLocation()
+{
+}
+
+/*!
+ Returns true if this QSourceLocation is identical to \a other.
+
+ Two QSourceLocation instances are equal if their uri(), line() and
+ column() are equal.
+
+ QSourceLocation instances for which isNull() returns true are
+ considered equal.
+ */
+bool QSourceLocation::operator==(const QSourceLocation &other) const
+{
+ return m_line == other.m_line
+ && m_column == other.m_column
+ && m_uri == other.m_uri;
+}
+
+/*!
+ Returns the opposite of applying operator==() for this QXmlName
+ and \a other.
+ */
+bool QSourceLocation::operator!=(const QSourceLocation &other) const
+{
+ return operator==(other);
+}
+
+/*!
+ Assigns this QSourceLocation instance to \a other.
+ */
+QSourceLocation &QSourceLocation::operator=(const QSourceLocation &other)
+{
+ if(this != &other)
+ {
+ m_line = other.m_line;
+ m_column = other.m_column;
+ m_uri = other.m_uri;
+ }
+
+ return *this;
+}
+
+/*!
+ Returns the current column number. The column number refers to the
+ count of characters, not bytes. The first column is column 1, not 0.
+ The default value is -1, indicating the column number is unknown.
+ */
+qint64 QSourceLocation::column() const
+{
+ return m_column;
+}
+
+/*!
+ Sets the column number to \a newColumn. 0 is an invalid column
+ number. The first column number is 1.
+ */
+void QSourceLocation::setColumn(qint64 newColumn)
+{
+ Q_ASSERT_X(newColumn != 0, Q_FUNC_INFO,
+ "0 is an invalid column number. The first column number is 1.");
+ m_column = newColumn;
+}
+
+/*!
+ Returns the current line number. The first line number is 1, not 0.
+ The default value is -1, indicating the line number is unknown.
+ */
+qint64 QSourceLocation::line() const
+{
+ return m_line;
+}
+
+/*!
+ Sets the line number to \a newLine. 0 is an invalid line
+ number. The first line number is 1.
+ */
+void QSourceLocation::setLine(qint64 newLine)
+{
+ m_line = newLine;
+}
+
+/*!
+ Returns the resource that this QSourceLocation refers to. For
+ example, the resource could be a file in the local file system,
+ if the URI scheme is \c file.
+ */
+QUrl QSourceLocation::uri() const
+{
+ return m_uri;
+}
+
+/*!
+ Sets the URI to \a newUri.
+ */
+void QSourceLocation::setUri(const QUrl &newUri)
+{
+ m_uri = newUri;
+}
+
+/*!
+ \relates QSourceLocation
+ \since 4.4
+
+ Prints \a sourceLocation to the debug stream \a debug.
+ */
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug debug, const QSourceLocation &sourceLocation)
+{
+ debug << "QSourceLocation("
+ << sourceLocation.uri()
+ << ", line:"
+ << sourceLocation.line()
+ << ", column:"
+ << sourceLocation.column()
+ << ")";
+ return debug;
+}
+#endif
+
+/*!
+ Returns \c true if this QSourceLocation doesn't identify anything.
+
+ For a default constructed QSourceLocation, this function returns \c
+ true. The same applies for any other QSourceLocation whose uri() is
+ invalid.
+ */
+bool QSourceLocation::isNull() const
+{
+ return !m_uri.isValid();
+}
+
+/*!
+ \since 4.4
+
+ Computes a hash key for the QSourceLocation \a location.
+
+ \relates QSourceLocation
+ */
+uint qHash(const QSourceLocation &location)
+{
+ /* Not the world's best hash function exactly. */
+ return qHash(location.uri().toString()) + location.line() + location.column();
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/xmlpatterns/api/qsourcelocation.h b/src/xmlpatterns/api/qsourcelocation.h
new file mode 100644
index 0000000000..d970edd392
--- /dev/null
+++ b/src/xmlpatterns/api/qsourcelocation.h
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtXmlPatterns 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSOURCELOCATION_H
+#define QSOURCELOCATION_H
+
+#include <QtCore/QMetaType>
+#include <QtCore/QUrl>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(XmlPatterns)
+
+class QSourceLocationPrivate;
+
+class Q_XMLPATTERNS_EXPORT QSourceLocation
+{
+public:
+ QSourceLocation();
+ QSourceLocation(const QSourceLocation &other);
+ QSourceLocation(const QUrl &uri, int line = -1, int column = -1);
+ ~QSourceLocation();
+ QSourceLocation &operator=(const QSourceLocation &other);
+ bool operator==(const QSourceLocation &other) const;
+ bool operator!=(const QSourceLocation &other) const;
+
+ qint64 column() const;
+ void setColumn(qint64 newColumn);
+
+ qint64 line() const;
+ void setLine(qint64 newLine);
+
+ QUrl uri() const;
+ void setUri(const QUrl &newUri);
+ bool isNull() const;
+
+private:
+ union
+ {
+ qint64 m_line;
+ QSourceLocationPrivate *m_ptr;
+ };
+ qint64 m_column;
+ QUrl m_uri;
+};
+
+Q_XMLPATTERNS_EXPORT uint qHash(const QSourceLocation &location);
+
+#ifndef QT_NO_DEBUG_STREAM
+Q_XMLPATTERNS_EXPORT QDebug operator<<(QDebug debug, const QSourceLocation &sourceLocation);
+#endif
+
+Q_DECLARE_TYPEINFO(QSourceLocation, Q_MOVABLE_TYPE);
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QSourceLocation) /* This macro must appear after QT_END_NAMESPACE. */
+
+QT_END_HEADER
+
+#endif
diff --git a/src/xmlpatterns/api/quriloader.cpp b/src/xmlpatterns/api/quriloader.cpp
new file mode 100644
index 0000000000..8b29b3c4f7
--- /dev/null
+++ b/src/xmlpatterns/api/quriloader.cpp
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtXmlPatterns 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtNetwork/QNetworkRequest>
+#include <QtNetwork/QNetworkReply>
+
+#include "qiodevicedelegate_p.h"
+#include "quriloader_p.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace QPatternist;
+
+URILoader::URILoader(QObject *const parent,
+ const NamePool::Ptr &np,
+ const VariableLoader::Ptr &l) : QNetworkAccessManager(parent)
+ , m_variableNS(QLatin1String("tag:trolltech.com,2007:QtXmlPatterns:QIODeviceVariable:"))
+ , m_namePool(np)
+ , m_variableLoader(l)
+{
+ Q_ASSERT(m_variableLoader);
+}
+
+QNetworkReply *URILoader::createRequest(Operation op, const QNetworkRequest &req, QIODevice *outgoingData)
+{
+ const QString requestedUrl(req.url().toString());
+
+ /* We got a QIODevice variable. */
+ const QString name(requestedUrl.right(requestedUrl.length() - m_variableNS.length()));
+
+ const QVariant variant(m_variableLoader->valueFor(m_namePool->allocateQName(QString(), name, QString())));
+
+ if(!variant.isNull() && variant.userType() == qMetaTypeId<QIODevice *>())
+ return new QIODeviceDelegate(qVariantValue<QIODevice *>(variant));
+ else
+ {
+ /* If we're entering this code path, the variable URI identified a variable
+ * which we don't have, which means we either have a bug, or the user had
+ * crafted an invalid URI manually. */
+
+ return QNetworkAccessManager::createRequest(op, req, outgoingData);
+ }
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/xmlpatterns/api/quriloader_p.h b/src/xmlpatterns/api/quriloader_p.h
new file mode 100644
index 0000000000..c5ba3754e8
--- /dev/null
+++ b/src/xmlpatterns/api/quriloader_p.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtXmlPatterns 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef QURILOADER_P_H
+#define QURILOADER_P_H
+
+#include <QtNetwork/QNetworkAccessManager>
+#include <QtXmlPatterns/QXmlName>
+
+#include "qnamepool_p.h"
+#include "qvariableloader_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace QPatternist
+{
+ class URILoader : public QNetworkAccessManager
+ {
+ public:
+ URILoader(QObject *const parent,
+ const NamePool::Ptr &np,
+ const VariableLoader::Ptr &variableLoader);
+
+ virtual QNetworkReply *createRequest(Operation op,
+ const QNetworkRequest & req,
+ QIODevice *outgoingData = 0);
+
+ private:
+ const QString m_variableNS;
+ const NamePool::Ptr m_namePool;
+ const VariableLoader::Ptr m_variableLoader;
+
+ };
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/xmlpatterns/api/qvariableloader.cpp b/src/xmlpatterns/api/qvariableloader.cpp
new file mode 100644
index 0000000000..076adc3e9a
--- /dev/null
+++ b/src/xmlpatterns/api/qvariableloader.cpp
@@ -0,0 +1,264 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtXmlPatterns 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QVariant>
+#include <QStringList>
+
+#include "qanyuri_p.h"
+#include "qatomicstring_p.h"
+#include "qbuiltintypes_p.h"
+#include "qcommonsequencetypes_p.h"
+#include "qgenericsequencetype_p.h"
+#include "qinteger_p.h"
+#include "qitem_p.h"
+#include "qsequencetype_p.h"
+#include "qvariableloader_p.h"
+#include "qxmlquery_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace QPatternist
+{
+
+ class VariantListIterator : public ListIteratorPlatform<QVariant, Item, VariantListIterator>
+ {
+ public:
+ inline VariantListIterator(const QVariantList &list) : ListIteratorPlatform<QVariant, Item, VariantListIterator>(list)
+ {
+ }
+
+ private:
+ friend class ListIteratorPlatform<QVariant, Item, VariantListIterator>;
+
+ inline Item inputToOutputItem(const QVariant &inputType) const
+ {
+ return AtomicValue::toXDM(inputType);
+ }
+ };
+
+ class StringListIterator : public ListIteratorPlatform<QString, Item, StringListIterator>
+ {
+ public:
+ inline StringListIterator(const QStringList &list) : ListIteratorPlatform<QString, Item, StringListIterator>(list)
+ {
+ }
+
+ private:
+ friend class ListIteratorPlatform<QString, Item, StringListIterator>;
+
+ static inline Item inputToOutputItem(const QString &inputType)
+ {
+ return AtomicString::fromValue(inputType);
+ }
+ };
+
+ /**
+ * Takes two DynamicContext instances, and redirects the storage of temporary trees
+ * to one of them.
+ *
+ * @since 4.5
+ */
+ class TemporaryTreesRedirectingContext : public DelegatingDynamicContext
+ {
+ public:
+ TemporaryTreesRedirectingContext(const DynamicContext::Ptr &other,
+ const DynamicContext::Ptr &modelStorage) : DelegatingDynamicContext(other)
+ , m_modelStorage(modelStorage)
+ {
+ Q_ASSERT(m_modelStorage);
+ }
+
+ virtual void addNodeModel(const QAbstractXmlNodeModel::Ptr &nodeModel)
+ {
+ m_modelStorage->addNodeModel(nodeModel);
+ }
+
+ private:
+ const DynamicContext::Ptr m_modelStorage;
+ };
+}
+
+using namespace QPatternist;
+
+SequenceType::Ptr VariableLoader::announceExternalVariable(const QXmlName name,
+ const SequenceType::Ptr &declaredType)
+{
+ Q_UNUSED(declaredType);
+ const QVariant &variant = m_bindingHash.value(name);
+
+
+ if(variant.isNull())
+ return SequenceType::Ptr();
+ else if(variant.userType() == qMetaTypeId<QIODevice *>())
+ return CommonSequenceTypes::ExactlyOneAnyURI;
+ else if(variant.userType() == qMetaTypeId<QXmlQuery>())
+ {
+ const QXmlQuery variableQuery(qVariantValue<QXmlQuery>(variant));
+ return variableQuery.d->expression()->staticType();
+ }
+ else
+ {
+ return makeGenericSequenceType(AtomicValue::qtToXDMType(qVariantValue<QXmlItem>(variant)),
+ Cardinality::exactlyOne());
+ }
+}
+
+Item::Iterator::Ptr VariableLoader::evaluateSequence(const QXmlName name,
+ const DynamicContext::Ptr &context)
+{
+
+ const QVariant &variant = m_bindingHash.value(name);
+ Q_ASSERT_X(!variant.isNull(), Q_FUNC_INFO,
+ "We assume that we have a binding.");
+
+ /* Same code as in the default clause below. */
+ if(variant.userType() == qMetaTypeId<QIODevice *>())
+ return makeSingletonIterator(itemForName(name));
+ else if(variant.userType() == qMetaTypeId<QXmlQuery>())
+ {
+ const QXmlQuery variableQuery(qVariantValue<QXmlQuery>(variant));
+
+ return variableQuery.d->expression()->evaluateSequence(DynamicContext::Ptr(new TemporaryTreesRedirectingContext(variableQuery.d->dynamicContext(), context)));
+ }
+
+ const QVariant v(qVariantValue<QXmlItem>(variant).toAtomicValue());
+
+ switch(v.type())
+ {
+ case QVariant::StringList:
+ return Item::Iterator::Ptr(new StringListIterator(v.toStringList()));
+ case QVariant::List:
+ return Item::Iterator::Ptr(new VariantListIterator(v.toList()));
+ default:
+ return makeSingletonIterator(itemForName(name));
+ }
+}
+
+Item VariableLoader::itemForName(const QXmlName &name) const
+{
+ const QVariant &variant = m_bindingHash.value(name);
+
+ if(variant.userType() == qMetaTypeId<QIODevice *>())
+ return Item(AnyURI::fromValue(QLatin1String("tag:trolltech.com,2007:QtXmlPatterns:QIODeviceVariable:") + m_namePool->stringForLocalName(name.localName())));
+
+ const QXmlItem item(qVariantValue<QXmlItem>(variant));
+
+ if(item.isNode())
+ return Item::fromPublic(item);
+ else
+ {
+ const QVariant atomicValue(item.toAtomicValue());
+ /* If the atomicValue is null it means it doesn't exist in m_bindingHash, and therefore it must
+ * be a QIODevice, since Patternist guarantees to only ask for variables that announceExternalVariable()
+ * has accepted. */
+ if(atomicValue.isNull())
+ return Item(AnyURI::fromValue(QLatin1String("tag:trolltech.com,2007:QtXmlPatterns:QIODeviceVariable:") + m_namePool->stringForLocalName(name.localName())));
+ else
+ return AtomicValue::toXDM(atomicValue);
+ }
+}
+
+Item VariableLoader::evaluateSingleton(const QXmlName name,
+ const DynamicContext::Ptr &)
+{
+ return itemForName(name);
+}
+
+bool VariableLoader::isSameType(const QVariant &v1,
+ const QVariant &v2) const
+{
+ /* Are both of type QIODevice *? */
+ if(v1.userType() == qMetaTypeId<QIODevice *>() && v1.userType() == v2.userType())
+ return true;
+
+ /* Ok, we have two QXmlItems. */
+ const QXmlItem i1(qVariantValue<QXmlItem>(v1));
+ const QXmlItem i2(qVariantValue<QXmlItem>(v2));
+
+ if(i1.isNode())
+ {
+ Q_ASSERT(false);
+ return false;
+ }
+ else if(i2.isAtomicValue())
+ return i1.toAtomicValue().type() == i2.toAtomicValue().type();
+ else
+ {
+ /* One is an atomic, the other is a node or they are null. */
+ return false;
+ }
+}
+
+void VariableLoader::removeBinding(const QXmlName &name)
+{
+ m_bindingHash.remove(name);
+}
+
+bool VariableLoader::hasBinding(const QXmlName &name) const
+{
+ return m_bindingHash.contains(name)
+ || (m_previousLoader && m_previousLoader->hasBinding(name));
+}
+
+QVariant VariableLoader::valueFor(const QXmlName &name) const
+{
+ if(m_bindingHash.contains(name))
+ return m_bindingHash.value(name);
+ else if(m_previousLoader)
+ return m_previousLoader->valueFor(name);
+ else
+ return QVariant();
+}
+
+void VariableLoader::addBinding(const QXmlName &name,
+ const QVariant &value)
+{
+ m_bindingHash.insert(name, value);
+}
+
+bool VariableLoader::invalidationRequired(const QXmlName &name,
+ const QVariant &variant) const
+{
+ return hasBinding(name) && !isSameType(valueFor(name), variant);
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/xmlpatterns/api/qvariableloader_p.h b/src/xmlpatterns/api/qvariableloader_p.h
new file mode 100644
index 0000000000..7c02d9f59b
--- /dev/null
+++ b/src/xmlpatterns/api/qvariableloader_p.h
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtXmlPatterns 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef PATTERNIST_VARIABLELOADER_P_H
+#define PATTERNIST_VARIABLELOADER_P_H
+
+#include <QtCore/QSet>
+#include <QtXmlPatterns/QXmlQuery>
+#include <QtDebug>
+
+#include "qdynamiccontext_p.h"
+#include "qexternalvariableloader_p.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+namespace QPatternist
+{
+ class VariableLoader : public ExternalVariableLoader
+ {
+ public:
+ typedef QHash<QXmlName, QVariant> BindingHash;
+ typedef QExplicitlySharedDataPointer<VariableLoader> Ptr;
+
+ inline VariableLoader(const NamePool::Ptr &np,
+ const VariableLoader::Ptr &previousLoader = VariableLoader::Ptr()) : m_namePool(np)
+ , m_previousLoader(previousLoader)
+
+ {
+ }
+
+ virtual QPatternist::SequenceType::Ptr announceExternalVariable(const QXmlName name,
+ const QPatternist::SequenceType::Ptr &declaredType);
+ virtual QPatternist::Item::Iterator::Ptr evaluateSequence(const QXmlName name,
+ const QPatternist::DynamicContext::Ptr &);
+
+ virtual QPatternist::Item evaluateSingleton(const QXmlName name,
+ const QPatternist::DynamicContext::Ptr &);
+
+ void removeBinding(const QXmlName &name);
+ bool hasBinding(const QXmlName &name) const;
+ QVariant valueFor(const QXmlName &name) const;
+ void addBinding(const QXmlName &name,
+ const QVariant &value);
+
+ bool isSameType(const QVariant &v1,
+ const QVariant &v2) const;
+
+ bool invalidationRequired(const QXmlName &name,
+ const QVariant &variant) const;
+
+ private:
+
+ inline QPatternist::Item itemForName(const QXmlName &name) const;
+
+ const NamePool::Ptr m_namePool;
+ VariableLoader::Ptr m_previousLoader;
+ BindingHash m_bindingHash;
+ };
+}
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QIODevice *)
+Q_DECLARE_METATYPE(QXmlQuery)
+
+QT_END_HEADER
+
+#endif
diff --git a/src/xmlpatterns/api/qxmlformatter.cpp b/src/xmlpatterns/api/qxmlformatter.cpp
new file mode 100644
index 0000000000..7e1c1f569c
--- /dev/null
+++ b/src/xmlpatterns/api/qxmlformatter.cpp
@@ -0,0 +1,338 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtXmlPatterns 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtDebug>
+
+#include "qxmlformatter.h"
+#include "qxpathhelper_p.h"
+#include "qxmlserializer_p.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace QPatternist;
+
+class QXmlFormatterPrivate : public QXmlSerializerPrivate
+{
+public:
+ inline QXmlFormatterPrivate(const QXmlQuery &q,
+ QIODevice *const outputDevice);
+
+ int indentationDepth;
+ int currentDepth;
+ QString characterBuffer;
+ QString indentString;
+
+ /**
+ * Whether we /have/ sent nodes like processing instructions and comments
+ * to QXmlSerializer.
+ */
+ QStack<bool> canIndent;
+};
+
+QXmlFormatterPrivate::QXmlFormatterPrivate(const QXmlQuery &query,
+ QIODevice *const outputDevice) : QXmlSerializerPrivate(query, outputDevice)
+ , indentationDepth(4)
+ , currentDepth(0)
+{
+ indentString.reserve(30);
+ indentString.resize(1);
+ indentString[0] = QLatin1Char('\n');
+ canIndent.push(false);
+}
+
+/*!
+ \class QXmlFormatter
+ \brief The QXmlFormatter class is an implementation of QXmlSerializer for transforming XQuery output into formatted XML.
+ \reentrant
+ \since 4.4
+ \ingroup xml-tools
+
+ QXmlFormatter is a subclass of QXmlSerializer that formats the XML
+ output to make it easier for humans to read.
+
+ QXmlSerializer outputs XML without adding unnecessary whitespace.
+ In particular, it does not add \e {newlines} and indentation.
+ To make the XML output easier to read, QXmlFormatter adds \e{newlines}
+ and indentation by adding, removing, and modifying
+ \l{XQuery Sequence}{sequence nodes} that only consist of whitespace.
+ It also modifies whitespace in other places where it is not
+ significant; e.g., between attributes and in the document prologue.
+
+ For example, where the base class QXmlSerializer would
+ output this:
+
+ \quotefile doc/src/snippets/patternist/notIndented.xml
+
+ QXmlFormatter outputs this:
+
+ \quotefile doc/src/snippets/patternist/indented.xml
+
+ If you just want to serialize your XML in a human-readable
+ format, use QXmlFormatter as it is. The default indentation
+ level is 4 spaces, but you can set your own indentation value
+ setIndentationDepth().
+
+ The \e{newlines} and indentation added by QXmlFormatter are
+ suitable for common formats, such as XHTML, SVG, or Docbook,
+ where whitespace is not significant. However, if your XML will
+ be used as input where whitespace is significant, then you must
+ write your own subclass of QXmlSerializer or QAbstractXmlReceiver.
+
+ Note that using QXmlFormatter instead of QXmlSerializer will
+ increase computational overhead and document storage size due
+ to the insertion of whitespace.
+
+ Note also that the indentation style used by QXmlFormatter
+ remains loosely defined and may change in future versions of
+ Qt. If a specific indentation style is required then either
+ use the base class QXmlSerializer directly, or write your own
+ subclass of QXmlSerializer or QAbstractXmlReceiver.
+ Alternatively, you can subclass QXmlFormatter and reimplement
+ the callbacks there.
+
+ \snippet doc/src/snippets/code/src_xmlpatterns_api_qxmlformatter.cpp 0
+*/
+
+/*!
+ Constructs a formatter that uses the name pool and message
+ handler in \a query, and writes the result to \a outputDevice
+ as formatted XML.
+
+ \a outputDevice is passed directly to QXmlSerializer's constructor.
+
+ \sa QXmlSerializer
+ */
+QXmlFormatter::QXmlFormatter(const QXmlQuery &query,
+ QIODevice *outputDevice) : QXmlSerializer(new QXmlFormatterPrivate(query, outputDevice))
+{
+}
+
+/*!
+ \internal
+ */
+void QXmlFormatter::startFormattingContent()
+{
+ Q_D(QXmlFormatter);
+
+ if(QPatternist::XPathHelper::isWhitespaceOnly(d->characterBuffer))
+ {
+ if(d->canIndent.top())
+ QXmlSerializer::characters(QStringRef(&d->indentString));
+ }
+ else
+ {
+ if(!d->characterBuffer.isEmpty()) /* Significant data, we don't touch it. */
+ QXmlSerializer::characters(QStringRef(&d->characterBuffer));
+ }
+
+ d->characterBuffer.clear();
+}
+
+/*!
+ \reimp
+ */
+void QXmlFormatter::startElement(const QXmlName &name)
+{
+ Q_D(QXmlFormatter);
+ startFormattingContent();
+ ++d->currentDepth;
+ d->indentString.append(QString(d->indentationDepth, QLatin1Char(' ')));
+ d->canIndent.push(true);
+
+ QXmlSerializer::startElement(name);
+}
+
+/*!
+ \reimp
+ */
+void QXmlFormatter::endElement()
+{
+ Q_D(QXmlFormatter);
+ --d->currentDepth;
+ d->indentString.chop(d->indentationDepth);
+
+ if(!d->hasClosedElement.top().second)
+ d->canIndent.top() = false;
+
+ startFormattingContent();
+
+ d->canIndent.pop();
+ d->canIndent.top() = true;
+ QXmlSerializer::endElement();
+}
+
+/*!
+ \reimp
+ */
+void QXmlFormatter::attribute(const QXmlName &name,
+ const QStringRef &value)
+{
+ QXmlSerializer::attribute(name, value);
+}
+
+/*!
+ \reimp
+ */
+void QXmlFormatter::comment(const QString &value)
+{
+ Q_D(QXmlFormatter);
+ startFormattingContent();
+ QXmlSerializer::comment(value);
+ d->canIndent.top() = true;
+}
+
+/*!
+ \reimp
+ */
+void QXmlFormatter::characters(const QStringRef &value)
+{
+ Q_D(QXmlFormatter);
+ d->isPreviousAtomic = false;
+ d->characterBuffer += value.toString();
+}
+
+/*!
+ \reimp
+ */
+void QXmlFormatter::processingInstruction(const QXmlName &name,
+ const QString &value)
+{
+ Q_D(QXmlFormatter);
+ startFormattingContent();
+ QXmlSerializer::processingInstruction(name, value);
+ d->canIndent.top() = true;
+}
+
+/*!
+ \reimp
+ */
+void QXmlFormatter::atomicValue(const QVariant &value)
+{
+ Q_D(QXmlFormatter);
+ d->canIndent.top() = false;
+ QXmlSerializer::atomicValue(value);
+}
+
+/*!
+ \reimp
+ */
+void QXmlFormatter::startDocument()
+{
+ QXmlSerializer::startDocument();
+}
+
+/*!
+ \reimp
+ */
+void QXmlFormatter::endDocument()
+{
+ QXmlSerializer::endDocument();
+}
+
+/*!
+ \reimp
+ */
+void QXmlFormatter::startOfSequence()
+{
+ QXmlSerializer::startOfSequence();
+}
+
+/*!
+ \reimp
+ */
+void QXmlFormatter::endOfSequence()
+{
+ Q_D(QXmlFormatter);
+
+ /* Flush any buffered content. */
+ if(!d->characterBuffer.isEmpty())
+ QXmlSerializer::characters(QStringRef(&d->characterBuffer));
+
+ d->write('\n');
+ QXmlSerializer::endOfSequence();
+}
+
+/*!
+ \internal
+ */
+void QXmlFormatter::item(const QPatternist::Item &item)
+{
+ Q_D(QXmlFormatter);
+
+ if(item.isAtomicValue())
+ {
+ if(QPatternist::XPathHelper::isWhitespaceOnly(item.stringValue()))
+ return;
+ else
+ {
+ d->canIndent.top() = false;
+ startFormattingContent();
+ }
+ }
+
+ QXmlSerializer::item(item);
+}
+
+/*!
+ Returns the number of spaces QXmlFormatter will output for each
+ indentation level. The default is four.
+
+ \sa setIndentationDepth()
+ */
+int QXmlFormatter::indentationDepth() const
+{
+ Q_D(const QXmlFormatter);
+ return d->indentationDepth;
+}
+
+/*!
+ Sets \a depth to be the number of spaces QXmlFormatter will
+ output for level of indentation. The default is four.
+
+ \sa indentationDepth()
+ */
+void QXmlFormatter::setIndentationDepth(int depth)
+{
+ Q_D(QXmlFormatter);
+ d->indentationDepth = depth;
+}
+
+QT_END_NAMESPACE
diff --git a/src/xmlpatterns/api/qxmlformatter.h b/src/xmlpatterns/api/qxmlformatter.h
new file mode 100644
index 0000000000..a839751059
--- /dev/null
+++ b/src/xmlpatterns/api/qxmlformatter.h
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtXmlPatterns 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QXMLFORMATTER_H
+#define QXMLFORMATTER_H
+
+#include <QtXmlPatterns/QXmlSerializer>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(XmlPatterns)
+
+class QIODevice;
+class QTextCodec;
+class QXmlQuery;
+class QXmlFormatterPrivate;
+
+class Q_XMLPATTERNS_EXPORT QXmlFormatter : public QXmlSerializer
+{
+public:
+ QXmlFormatter(const QXmlQuery &query,
+ QIODevice *outputDevice);
+
+ virtual void characters(const QStringRef &value);
+ virtual void comment(const QString &value);
+ virtual void startElement(const QXmlName &name);
+ virtual void endElement();
+
+ virtual void attribute(const QXmlName &name,
+ const QStringRef &value);
+ virtual void processingInstruction(const QXmlName &name,
+ const QString &value);
+ virtual void atomicValue(const QVariant &value);
+ virtual void startDocument();
+ virtual void endDocument();
+ virtual void startOfSequence();
+ virtual void endOfSequence();
+
+ int indentationDepth() const;
+ void setIndentationDepth(int depth);
+
+ /* The members below are internal, not part of the public API, and
+ * unsupported. Using them leads to undefined behavior. */
+ virtual void item(const QPatternist::Item &item);
+private:
+ inline void startFormattingContent();
+ Q_DECLARE_PRIVATE(QXmlFormatter)
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/xmlpatterns/api/qxmlname.cpp b/src/xmlpatterns/api/qxmlname.cpp
new file mode 100644
index 0000000000..82350b2e1d
--- /dev/null
+++ b/src/xmlpatterns/api/qxmlname.cpp
@@ -0,0 +1,511 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtXmlPatterns 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ * QXmlName is conceptually identical to QPatternist::QName. The
+ * difference is that the latter is elegant, powerful and fast.
+ *
+ * However, it is too powerful and too open and not at all designed
+ * for being public. QXmlName, in contrast, is only a public marker,
+ * that for instance uses a qint64 instead of qint32, such that we in
+ * the future can use that, if needed.
+ */
+
+#include "qnamepool_p.h"
+#include "qxmlname.h"
+#include "qxmlnamepool.h"
+#include "qxpathhelper_p.h"
+#include "private/qxmlutils_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QXmlName
+ \brief The QXmlName class represents the name of an XML node, in an efficient, namespace-aware way.
+ \reentrant
+ \since 4.4
+ \ingroup xml-tools
+
+ QXmlName represents the name of an XML node in a way that
+ is both efficient and safe for comparing names. Normally,
+ an XML node represents an XML element or attribute, but
+ QXmlName can also represent the names of other kinds of
+ nodes, e.g., QAbstractXmlReceiver::processingInstruction()
+ and QAbstractXmlReceiver::namespaceBinding().
+
+ The name of an XML node has three components: The \e {namespace
+ URI}, the \e {local name}, and the \e {prefix}. To see what these
+ refer to in XML, consider the following snippet.
+
+ \quotefile doc/src/snippets/patternist/mobeyDick.xml
+
+ For the element named \e book, localName() returns \e book,
+ namespaceUri() returns \e http://example.com/MyDefault,
+ and prefix() returns an empty string. For the element named
+ \e title, localName() returns \e title, namespaceUri() returns
+ \e http://purl.org/dc/elements/1.1, and prefix() returns \e dc.
+
+ To ensure that operations with QXmlName are efficient, e.g.,
+ copying names and comparing them, each instance of QXmlName is
+ associated with a \l {QXmlNamePool} {name pool}, which must be
+ specified at QXmlName construction time. The three components
+ of the QXmlName, i.e., the namespace URI, the local name, and
+ the prefix, are stored in the name pool mapped to identifiers
+ so they can be shared. For this reason, the only way to create
+ a valid instance of QXmlName is to use the class constructor,
+ where the \l {QXmlNamePool} {name pool}, local name, namespace
+ URI, and prefix must all be specified.
+
+ Note that QXmlName's default constructor constructs a null
+ instance. It is typically used for allocating unused entries
+ in collections of QXmlName.
+
+ A side effect of associating each instance of QXmlName with
+ a \l {QXmlNamePool} {name pool} is that each instance of
+ QXmlName is tied to the QXmlNamePool with which it was created.
+ However, the QXmlName class does not keep track of the name pool,
+ so all the accessor functions, e.g., namespaceUri(), prefix(),
+ localName(), and toClarkName() require that the correct name
+ pool be passed to them. Failure to provide the correct name
+ pool to these accessor functions results in undefined behavior.
+
+ Note that a \l {QXmlNamePool} {name pool} is \e not an XML
+ namespace. One \l {QXmlNamePool} {name pool} can represent
+ instances of QXmlName from different XML namespaces, and the
+ instances of QXmlName from one XML namespace can be distributed
+ over multiple \l {QXmlNamePool} {name pools}.
+
+ \target Comparing QXmlNames
+ \section1 Comparing QXmlNames
+
+ To determine what a QXmlName refers to, the \e {namespace URI}
+ and the \e {local name} are used. The \e prefix is not used
+ because the prefix is simply a shorthand name for use in place
+ of the normally much longer namespace URI. Nor is the prefix
+ used in name comparisons. For example, the following two element
+ nodes represent the same element and compare equal.
+
+ \quotefile doc/src/snippets/patternist/svgDocumentElement.xml
+
+ \quotefile doc/src/snippets/patternist/xsvgDocumentElement.xml
+
+ Although the second name has the prefix \e x, the two names compare
+ equal as instances of QXmlName, because the prefix is not used in
+ the comparison.
+
+ A local name can never be an empty string, although the prefix and
+ namespace URI can. If the prefix is not empty, the namespace URI
+ cannot be empty. Local names and prefixes must be valid
+ \l {http://www.w3.org/TR/REC-xml-names/#NT-NCName} {NCNames},
+ e.g., \e abc.def or \e abc123.
+
+ QXmlName represents what is sometimes called an \e {expanded QName},
+ or simply a QName.
+
+ \sa {http://www.w3.org/TR/REC-xml-names/#NT-NCName} {Namespaces in XML 1.0 (Second Edition), [4] NCName}
+ */
+
+/*!
+ \enum QXmlName::Constant
+ \internal
+ Various constants used in the QPatternist::NamePool and QXmlName.
+
+ Setting of the mask enums use essentially this:
+
+ \quotefile doc/src/snippets/code/src_xmlpatterns_api_qxmlname.cpp
+
+ The masks, such as LocalNameMask, are positive. That is, for the
+ area which the name resides, the bits are set.
+ */
+
+/*!
+ Constructs a QXmlName instance that inserts \a localName,
+ \a namespaceURI and \a prefix into \a namePool if they aren't
+ already there. The accessor functions namespaceUri(), prefix(),
+ localName(), and toClarkName() must be passed the \a namePool
+ used here, so the \a namePool must remain in scope while the
+ accessor functions might be used. However, two instances can
+ be compared with \e {==} or \e {!=} and copied without the
+ \a namePool.
+
+ The user guarantees that the string components are valid for a
+ QName. In particular, the local name, and the prefix (if present),
+ must be valid \l {http://www.w3.org/TR/REC-xml-names/#NT-NCName}
+ {NCNames}. The function isNCName() can be used to test validity
+ of these names. The namespace URI should be an absolute URI.
+ QUrl::isRelative() can be used to test whether the namespace URI
+ is relative or absolute. Finally, providing a prefix is not valid
+ when no namespace URI is provided.
+
+ \a namePool is not copied. Nor is the reference to it retained
+ in this instance. This constructor inserts the three strings
+ into \a namePool.
+ */
+QXmlName::QXmlName(QXmlNamePool &namePool,
+ const QString &localName,
+ const QString &namespaceURI,
+ const QString &prefix)
+{
+ Q_ASSERT_X(prefix.isEmpty() || QXmlUtils::isNCName(prefix), Q_FUNC_INFO,
+ "The prefix is invalid, maybe the arguments were mixed up?");
+ Q_ASSERT_X(QXmlUtils::isNCName(localName), Q_FUNC_INFO,
+ "The local name is invalid, maybe the arguments were mixed up?");
+
+ m_qNameCode = namePool.d->allocateQName(namespaceURI, localName, prefix).code();
+}
+
+/*!
+ \typedef QXmlName::Code
+ \internal
+
+ Stores the \l {QXmlNamePool} {name pool} identifiers for
+ the namespace URI, local name, and prefix.
+ */
+
+/*!
+ Returns true if this QXmlName is not initialized with a
+ valid combination of \e {namespace URI}, \e {local name},
+ and \e {prefix}.
+
+ A valid local name is always required. The prefix and
+ namespace URI can be empty, but if the prefix is not empty,
+ the namespace URI must not be empty. Local names and
+ prefixes must be valid
+ \l {http://www.w3.org/TR/REC-xml-names/#NT-NCName} {NCNames},
+ e.g., \e abc.def or \e abc123.
+ */
+bool QXmlName::isNull() const
+{
+ return m_qNameCode == InvalidCode;
+}
+
+/*!
+ Constructs an uninitialized QXmlName. To build
+ a valid QXmlName, you normally use the other constructor, which
+ takes a \l {QXmlNamePool} {name pool}, namespace URI, local name,
+ and prefix as parameters. But you can also use this constructor
+ to build a null QXmlName and then assign an existing QXmlName
+ to it.
+
+ \sa isNull()
+ */
+QXmlName::QXmlName() : m_qNameCode(InvalidCode)
+{
+}
+
+/*!
+ \fn QXmlName::QXmlName(const NamespaceCode uri,
+ const LocalNameCode ln,
+ const PrefixCode p = 0)
+ \internal
+ */
+
+/*!
+ \fn QXmlName::hasPrefix() const
+ \internal
+
+ Returns true if this QXmlName has a non-empty prefix. If this
+ function returns true, hasNamespace() will also return true,
+ because a QXmlName can't have a prefix if it doesn't have a
+ namespace URI.
+ */
+
+/*!
+ \fn bool QXmlName::hasNamespace() const
+ \internal
+
+ Returns true if this QXmlName has a non-empty namespace URI.
+ */
+
+/*!
+ \fn Code QXmlName::code() const
+ \internal
+
+ Returns the internal code that contains the id codes for the
+ local name, prefix and namespace URI. It is opaque when used
+ outside QXmlName, but it can be useful when one wants to put
+ a QXmlName in a hash, and the prefix is significant.
+ */
+
+/*!
+ Returns true if this QXmlName is equal to \a other; otherwise false.
+ Two QXmlNames are equal if their namespace URIs are the same \e and
+ their local names are the same. The prefixes are ignored.
+
+ Note that it is meaningless to compare two instances of QXmlName
+ that were created with different \l {QXmlNamePool} {name pools},
+ but the attempt is not detected and the behavior is undefined.
+
+ \sa operator!=()
+ */
+bool QXmlName::operator==(const QXmlName &other) const
+{
+ return (m_qNameCode & ExpandedNameMask) == (other.m_qNameCode & ExpandedNameMask);
+}
+
+/*!
+ Returns true if this QXmlName is \e not equal to \a other;
+ otherwise false. Two QXmlNames are equal if their namespace
+ URIs are the same \e and their local names are the same. They
+ are not equal if either their namespace URIs differ or their
+ local names differ. Their prefixes are ignored.
+
+ Note that it is meaningless to compare two instances of QXmlName
+ that were created with different \l {QXmlNamePool} {name pools},
+ but the attempt is not detected and the behavior is undefined.
+
+ \sa operator==()
+ */
+bool QXmlName::operator!=(const QXmlName &other) const
+{
+ return !operator==(other);
+}
+
+/*!
+ \fn bool QXmlName::isLexicallyEqual(const QXmlName &other) const
+ \internal
+
+ Returns true if this and \a other are lexically equal. Two
+ QXmlNames are lexically equal if their local names are equal
+ \e and their prefixes are equal.
+ */
+
+/*!
+ \fn uint qHash(const QXmlName &name)
+ \since 4.4
+ \relates QXmlName
+
+ Computes a hash key from the local name and the namespace
+ URI in \a name. The prefix in \a name is not used in the computation.
+ */
+uint qHash(const QXmlName &name)
+{
+ return name.m_qNameCode & QXmlName::ExpandedNameMask;
+}
+
+/*!
+ Returns the namespace URI.
+
+ Note that for efficiency, the namespace URI string is not
+ stored in the QXmlName but in the \l {QXmlNamePool} that was
+ passed to the constructor. Hence, that same \a namePool must
+ be passed to this function, so it can be used for looking up
+ the namespace URI.
+ */
+QString QXmlName::namespaceUri(const QXmlNamePool &namePool) const
+{
+ if(isNull())
+ return QString();
+ else
+ return namePool.d->stringForNamespace(namespaceURI());
+}
+
+/*!
+ Returns the prefix.
+
+ Note that for efficiency, the prefix string is not stored in
+ the QXmlName but in the \l {QXmlNamePool} that was passed to
+ the constructor. Hence, that same \a namePool must be passed
+ to this function, so it can be used for looking up the prefix.
+ */
+QString QXmlName::prefix(const QXmlNamePool &namePool) const
+{
+ if(isNull())
+ return QString();
+ else
+ return namePool.d->stringForPrefix(prefix());
+}
+
+/*!
+ Returns the local name.
+
+ Note that for efficiency, the local name string is not stored
+ in the QXmlName but in the \l {QXmlNamePool} that was passed to
+ the constructor. Hence, that same \a namePool must be passed
+ to this function, so it can be used for looking up the
+ local name.
+ */
+QString QXmlName::localName(const QXmlNamePool &namePool) const
+{
+ if(isNull())
+ return QString();
+ else
+ return namePool.d->stringForLocalName(localName());
+}
+
+/*!
+ Returns this QXmlName formatted as a Clark Name. For example,
+ if the local name is \c html, the prefix is \c x, and the
+ namespace URI is \c {http://www.w3.org/1999/xhtml/},
+ then the Clark Name returned is:
+
+ \code
+ {http://www.w3.org/1999/xhtml/}x:html.
+ \endcode
+
+ If the local name is \e {MyWidget} and the namespace is empty,
+ the Clark Name returned is:
+
+ \code
+ MyWidget
+ \endcode
+
+ Note that for efficiency, the namespace URI, local name, and
+ prefix strings are not stored in the QXmlName but in the
+ \l {QXmlNamePool} that was passed to the constructor. Hence,
+ that same \a namePool must be passed to this function, so it
+ can be used for looking up the three string components.
+
+ This function can be useful for debugging.
+
+ \sa {http://www.jclark.com/xml/xmlns.htm} {XML Namespaces, James Clark}
+ \sa fromClarkName()
+ */
+QString QXmlName::toClarkName(const QXmlNamePool &namePool) const
+{
+ return namePool.d->toClarkName(*this);
+}
+
+/*!
+ Assigns \a other to \e this and returns \e this.
+ */
+QXmlName &QXmlName::operator=(const QXmlName &other)
+{
+ m_qNameCode = other.m_qNameCode;
+ return *this;
+}
+
+/*!
+ Returns true if \a candidate is an \c NCName. An \c NCName
+ is a string that can be used as a name in XML and XQuery,
+ e.g., the prefix or local name in an element or attribute,
+ or the name of a variable.
+
+ \sa {http://www.w3.org/TR/REC-xml-names/#NT-NCName} {Namespaces in XML 1.0 (Second Edition), [4] NCName}
+ */
+bool QXmlName::isNCName(const QString &candidate)
+{
+ return QXmlUtils::isNCName(candidate);
+}
+
+/*!
+ Converts \a clarkName into a QXmlName, inserts into \a namePool, and
+ returns it.
+
+ A clark name is a way to present a full QName with only one string, where
+ the namespace cannot contain braces. Here are a couple of examples:
+
+ \table
+ \header
+ \o Clark Name
+ \o Description
+ \row
+ \o \c html
+ \o The local name \c html, in no namespace
+ \row
+ \o \c {http://www.w3.org/1999/xhtml}html
+ \o The local name \c html, in the XHTML namespace
+ \row
+ \o \c {http://www.w3.org/1999/xhtml}my:html
+ \o The local name \c html, in the XHTML namespace, with the prefix \c my
+ \endtable
+
+ If the namespace contains braces, the returned value is either invalid or
+ has undefined content.
+
+ If \a clarkName is an invalid name, a default constructed QXmlName is
+ returned.
+
+ \since 4.5
+ \sa toClarkName()
+ */
+QXmlName QXmlName::fromClarkName(const QString &clarkName,
+ const QXmlNamePool &namePool)
+{
+ return namePool.d->fromClarkName(clarkName);
+}
+
+/*!
+ \typedef QXmlName::LocalNameCode
+ \internal
+ */
+
+/*!
+ \typedef QXmlName::PrefixCode
+ \internal
+ */
+
+/*!
+ \typedef QXmlName::NamespaceCode
+ \internal
+ */
+
+/*!
+ \fn void QXmlName::setLocalName(const LocalNameCode c)
+ \internal
+*/
+
+/*!
+ \fn LocalNameCode QXmlName::localName() const
+ \internal
+*/
+
+/*!
+ \fn PrefixCode QXmlName::prefix() const
+ \internal
+*/
+
+/*!
+ \fn NamespaceCode QXmlName::namespaceURI() const
+ \internal
+*/
+
+/*!
+ \fn void QXmlName::setNamespaceURI(const NamespaceCode c)
+ \internal
+*/
+
+/*!
+ \fn void QXmlName::setPrefix(const PrefixCode c)
+ \internal
+*/
+QT_END_NAMESPACE
+
diff --git a/src/xmlpatterns/api/qxmlname.h b/src/xmlpatterns/api/qxmlname.h
new file mode 100644
index 0000000000..f5dcddf912
--- /dev/null
+++ b/src/xmlpatterns/api/qxmlname.h
@@ -0,0 +1,142 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtXmlPatterns 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QXMLNAME_H
+#define QXMLNAME_H
+
+#include <QtCore/QString>
+#include <QtCore/QMetaType>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(XmlPatterns)
+
+class QXmlName;
+class QXmlNamePool;
+Q_XMLPATTERNS_EXPORT uint qHash(const QXmlName &name);
+
+class Q_XMLPATTERNS_EXPORT QXmlName
+{
+private:
+ enum Constant
+ {
+ LocalNameOffset = 0,
+ LocalNameLength = 12,
+ NamespaceOffset = LocalNameLength,
+ NamespaceLength = 9,
+ PrefixLength = 9,
+ InvalidCode = 1 << 31,
+ NamespaceMask = ((1 << ((NamespaceOffset + NamespaceLength) - NamespaceOffset)) - 1) << NamespaceOffset,
+ LocalNameMask = ((1 << ((LocalNameOffset + LocalNameLength) - LocalNameOffset)) - 1) << LocalNameOffset,
+ PrefixOffset = LocalNameLength + NamespaceLength,
+ PrefixMask = ((1 << ((PrefixOffset + PrefixLength) - PrefixOffset)) - 1) << PrefixOffset,
+ MaximumPrefixes = (PrefixMask >> PrefixOffset) - 1,
+ MaximumLocalNames = (LocalNameMask >> LocalNameOffset) - 1,
+ MaximumNamespaces = (NamespaceMask >> NamespaceOffset) - 1,
+ ExpandedNameMask = LocalNameMask | NamespaceMask,
+ LexicalQNameMask = LocalNameMask | PrefixMask
+ };
+
+public:
+
+ typedef qint16 NamespaceCode;
+ typedef NamespaceCode PrefixCode;
+ typedef NamespaceCode LocalNameCode;
+
+ QXmlName();
+
+ QXmlName(QXmlNamePool &namePool,
+ const QString &localName,
+ const QString &namespaceURI = QString(),
+ const QString &prefix = QString());
+
+ QString namespaceUri(const QXmlNamePool &query) const;
+ QString prefix(const QXmlNamePool &query) const;
+ QString localName(const QXmlNamePool &query) const;
+ QString toClarkName(const QXmlNamePool &query) const;
+ bool operator==(const QXmlName &other) const;
+ bool operator!=(const QXmlName &other) const;
+ QXmlName &operator=(const QXmlName &other);
+ bool isNull() const;
+ static bool isNCName(const QString &candidate);
+ static QXmlName fromClarkName(const QString &clarkName,
+ const QXmlNamePool &namePool);
+
+ /* The members below are internal, not part of the public API, and
+ * unsupported. Using them leads to undefined behavior. */
+ typedef qint64 Code;
+
+ inline QXmlName(const NamespaceCode uri,
+ const LocalNameCode ln,
+ const PrefixCode p = 0);
+ /* The implementation for these functions are in utils/qnamepool_p.h. */
+ inline LocalNameCode localName() const;
+ inline PrefixCode prefix() const;
+ inline bool hasPrefix() const;
+ inline bool hasNamespace() const;
+ inline NamespaceCode namespaceURI() const;
+ inline bool isLexicallyEqual(const QXmlName &other) const;
+ inline void setPrefix(const PrefixCode c);
+ inline void setNamespaceURI(const NamespaceCode c);
+ inline void setLocalName(const LocalNameCode c);
+ inline Code code() const;
+
+ friend Q_XMLPATTERNS_EXPORT uint qHash(const QXmlName &);
+
+private:
+ inline QXmlName(const int c) : m_qNameCode(c)
+ {
+ }
+
+ Code m_qNameCode;
+};
+
+Q_DECLARE_TYPEINFO(QXmlName, Q_MOVABLE_TYPE);
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QXmlName) /* This macro must appear after QT_END_NAMESPACE. */
+
+QT_END_HEADER
+
+#endif
diff --git a/src/xmlpatterns/api/qxmlnamepool.cpp b/src/xmlpatterns/api/qxmlnamepool.cpp
new file mode 100644
index 0000000000..2337f8d813
--- /dev/null
+++ b/src/xmlpatterns/api/qxmlnamepool.cpp
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtXmlPatterns 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qnamepool_p.h"
+#include "qxmlnamepool.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QXmlNamePool
+ \brief The QXmlNamePool class is a table of shared strings referenced by instances of QXmlName.
+ \reentrant
+ \since 4.4
+ \ingroup xml-tools
+
+ QXmlNamePool is used to optimize operations on instances of
+ QXmlName. An instance of QXmlName represents an XML name in
+ a way that allows the XML name to be compared and passed around
+ efficiently. The efficiency is achieved by storing the strings
+ comprising the XML names in an instance of QXmlNamePool, where
+ they are mapped to binary identifiers, which are then packed
+ into a key which is stored in the QXmlName.
+
+ This means that each instance of QXmlName is tied to the name
+ pool it was created with, and that name pool should be kept in
+ scope and used to create all instances of QXmlName that might
+ be compared. Note also that the name pool is required if you
+ must reconstitute the QXmlName as text, or if you must access
+ any of its component strings, so although instances of
+ QXmlName can be compared without reference to a name pool, the
+ name pool must be kept in scope if the name's strings must be
+ accessed later.
+
+ \sa QXmlName
+ \sa QXmlQuery::namePool()
+ */
+
+/*!
+ Constructs an empty name pool.
+ */
+QXmlNamePool::QXmlNamePool() : d(new QPatternist::NamePool())
+{
+}
+
+/*!
+ Constructs a copy of the \a other name pool.
+ */
+QXmlNamePool::QXmlNamePool(const QXmlNamePool &other) : d(other.d)
+{
+}
+
+/*!
+ Destroys the name pool. Instances of QXmlName constructed
+ with this name pool can still be compared after this destructor
+ is called, but their text strings cannot be accessed.
+ */
+QXmlNamePool::~QXmlNamePool()
+{
+}
+
+/*!
+ Assigns the \a other name pool to this one.
+ */
+QXmlNamePool &QXmlNamePool::operator=(const QXmlNamePool &other)
+{
+ d = other.d;
+ return *this;
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/xmlpatterns/api/qxmlnamepool.h b/src/xmlpatterns/api/qxmlnamepool.h
new file mode 100644
index 0000000000..3c1e112114
--- /dev/null
+++ b/src/xmlpatterns/api/qxmlnamepool.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtXmlPatterns 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QXMLNAMEPOOL_H
+#define QXMLNAMEPOOL_H
+
+#include <QtCore/QSharedData>
+#include <QtCore/QString>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(XmlPatterns)
+
+namespace QPatternist
+{
+ class NamePool;
+}
+
+namespace QPatternistSDK
+{
+ class Global;
+}
+
+class QXmlQueryPrivate;
+class QXmlName;
+
+class Q_XMLPATTERNS_EXPORT QXmlNamePool
+{
+public:
+ QXmlNamePool();
+ QXmlNamePool(const QXmlNamePool &other);
+ ~QXmlNamePool();
+ QXmlNamePool &operator=(const QXmlNamePool &other);
+
+private:
+ friend class QXmlQueryPrivate;
+ friend class QXmlQuery;
+ friend class QXmlSerializerPrivate;
+ friend class QXmlName;
+ friend class QPatternistSDK::Global;
+ QExplicitlySharedDataPointer<QPatternist::NamePool> d;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/xmlpatterns/api/qxmlquery.cpp b/src/xmlpatterns/api/qxmlquery.cpp
new file mode 100644
index 0000000000..5f9d87d748
--- /dev/null
+++ b/src/xmlpatterns/api/qxmlquery.cpp
@@ -0,0 +1,1179 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtXmlPatterns 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/QBuffer>
+#include <QtCore/QStringList>
+#include <QtXmlPatterns/QXmlFormatter>
+
+#include "qacceltreeresourceloader_p.h"
+#include "qcommonvalues_p.h"
+#include "qxmlresultitems.h"
+#include "qxmlresultitems_p.h"
+#include "qxmlserializer.h"
+#include "qxpathhelper_p.h"
+
+#include "qxmlquery.h"
+#include "qxmlquery_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QXmlQuery
+
+ \brief The QXmlQuery class performs XQueries on XML data, or on non-XML data modeled to look like XML.
+
+ \reentrant
+ \since 4.4
+ \ingroup xml-tools
+
+ The QXmlQuery class compiles and executes queries written in the
+ \l {http://www.w3.org/TR/xquery/}{XQuery language}. QXmlQuery is
+ typically used to query XML data, but it can also query non-XML
+ data that has been modeled to look like XML.
+
+ Using QXmlQuery to query XML data, as in the snippet below, is
+ simple because it can use the built-in \l {QAbstractXmlNodeModel}
+ {XML data model} as its delegate to the underlying query engine for
+ traversing the data. The built-in data model is specified in \l
+ {http://www.w3.org/TR/xpath-datamodel/} {XQuery 1.0 and XPath 2.0
+ Data Model}.
+
+ \snippet doc/src/snippets/code/src_xmlpatterns_api_qabstractxmlreceiver.cpp 0
+
+ The example uses QXmlQuery to match the first paragraph of an XML
+ document and then \l {QXmlSerializer} {output the result} to a
+ device as XML.
+
+ Using QXmlQuery to query \e {non-XML} data requires writing a
+ subclass of QAbstractXmlNodeModel to use as a replacement for the
+ built-in XML data model. The custom data model will be able to
+ traverse the non-XML data as required by the QAbstractXmlNodeModel
+ interface. An instance of this custom data model then becomes the
+ delegate used by the query engine to traverse the non-XML data. For
+ an example of how to use QXmlQuery to query non-XML data, see the
+ documentation for QAbstractXmlNodeModel.
+
+ \section1 Running XQueries
+
+ To run a query set up with QXmlQuery, call one of the evaluation
+ functions.
+
+ \list
+
+ \o evaluateTo(QAbstractXmlReceiver *) is called with a pointer to an
+ XML \l {QAbstractXmlReceiver} {receiver}, which receives the query
+ results as a sequence of callbacks. The receiver callback class is
+ like the callback class used for translating the output of a SAX
+ parser. QXmlSerializer, for example, is a receiver callback class
+ for translating the sequence of callbacks for output as unformatted
+ XML text.
+
+ \endlist
+
+ \list
+
+ \o evaluateTo(QXmlResultItems *) is called with a pointer to an
+ iterator for an empty sequence of query \l {QXmlResultItems} {result
+ items}. The Java-like iterator allows the query results to be
+ accessed sequentially.
+
+ \endlist
+
+ \list
+
+ \o evaluateTo(QStringList *) is like evaluateTo(QXmlResultItems *),
+ but the query must evaluate to a sequence of strings.
+
+ \endlist
+
+ \section1 Running XPath Expressions
+
+ The XPath language is a subset of the XQuery language, so
+ running an XPath expression is the same as running an XQuery
+ query. Pass the XPath expression to QXmlQuery using setQuery().
+
+ \section1 Running XSLT stylesheets
+
+ Running an XSLT stylesheet is like running an XQuery, except that
+ when you construct your QXmlQuery, you must pass QXmlQuery::XSLT20
+ to tell QXmlQuery to interpret whatever it gets from setQuery() as
+ an XSLT stylesheet instead of as an XQuery. You must also set the
+ input document by calling setFocus().
+
+ \snippet doc/src/snippets/code/src_xmlpatterns_api_qxmlquery.cpp 7
+
+ \note Currently, setFocus() must be called \e before setQuery() when
+ using XSLT.
+
+ Another way to run an XSLT stylesheet is to use the \c xmlpatterns
+ command line utility.
+
+ \code
+ xmlpatterns myStylesheet.xsl myInput.xml
+ \endcode
+
+ \note For the current release, XSLT support should be considered
+ experimental. See section \l{QtXmlPatterns Module#XSLT
+ 2.0}{XSLT conformance} for details.
+
+ Stylesheet parameters are bound using bindVariable().
+
+ \section1 Binding A Query To A Starting Node
+
+ When a query is run on XML data, as in the snippet above, the
+ \c{doc()} function returns the node in the built-in data model where
+ the query evaluation will begin. But when a query is run on a custom
+ node model containing non-XML data, one of the bindVariable()
+ functions must be called to bind a variable name to a starting node
+ in the custom model. A $variable reference is used in the XQuery
+ text to access the starting node in the custom model. It is not
+ necessary to declare the variable name external in the query. See
+ the example in the documentation for QAbstractXmlNodeModel.
+
+ \section1 Reentrancy and Thread-Safety
+
+ QXmlQuery is reentrant but not thread-safe. It is safe to use the
+ QxmlQuery copy constructor to create a copy of a query and run the
+ same query multiple times. Behind the scenes, QXmlQuery will reuse
+ resources such as opened files and compiled queries to the extent
+ possible. But it is not safe to use the same instance of QXmlQuery
+ in multiple threads.
+
+ \section1 Error Handling
+
+ Errors can occur during query evaluation. Examples include type
+ errors and file loading errors. When an error occurs:
+
+ \list
+
+ \o The error message is sent to the messageHandler().
+
+ \o QXmlResultItems::hasError() will return \c{true}, or
+ evaluateTo() will return \c{false};
+
+ \o The results of the evaluation are undefined.
+
+ \endlist
+
+ \section1 Resource Management
+
+ When a query runs, it parses documents, allocating internal data
+ structures to hold them, and it may load other resources over the
+ network. It reuses these allocated resources when possible, to
+ avoid having to reload and reparse them.
+
+ When setQuery() is called, the query text is compiled into an
+ internal data structure and optimized. The optimized form can
+ then be reused for multiple evaluations of the query. Since the
+ compile-and-optimize process can be expensive, repeating it for
+ the same query should be avoided by using a separate instance of
+ QXmlQuery for each query text.
+
+ Once a document has been parsed, its internal representation is
+ maintained in the QXmlQuery instance and shared among multiple
+ QXmlQuery instances.
+
+ An instance of QCoreApplication must exist before QXmlQuery can be
+ used.
+
+ \section1 Event Handling
+
+ When QXmlQuery accesses resources (e.g., calling \c fn:doc() to load a file,
+ or accessing a device via a bound variable), the event loop is used, which
+ means events will be processed. To avoid processing events when QXmlQuery
+ accesses resources, create your QXmlQuery instance in a separate thread.
+ */
+
+/*!
+ \enum QXmlQuery::QueryLanguage
+ \since 4.5
+
+ Specifies whether you want QXmlQuery to interpret the input to
+ setQuery() as an XQuery or as an XSLT stylesheet.
+
+ \value XQuery10 XQuery 1.0.
+ \value XSLT20 XSLT 2.0
+
+ \sa setQuery()
+ */
+
+// ### Qt5: Merge constructor overloads
+/*!
+ Constructs an invalid, empty query that cannot be used until
+ setQuery() is called.
+
+ \note This constructor must not be used if you intend to use
+ this QXmlQuery to process XSL-T stylesheets. The other constructor
+ must be used in that case.
+ */
+QXmlQuery::QXmlQuery() : d(new QXmlQueryPrivate())
+{
+}
+
+/*!
+ Constructs a QXmlQuery that is a copy of \a other. The new
+ instance will share resources with the existing query
+ to the extent possible.
+ */
+QXmlQuery::QXmlQuery(const QXmlQuery &other) : d(new QXmlQueryPrivate(*other.d))
+{
+ /* First we have invoked QXmlQueryPrivate's synthesized copy constructor.
+ * Keep this section in sync with QXmlQuery::operator=(). */
+ d->detach();
+}
+
+/*!
+ Constructs a query that will use \a np as its name pool. The query
+ cannot be evaluated until setQuery() has been called.
+ */
+QXmlQuery::QXmlQuery(const QXmlNamePool &np) : d(new QXmlQueryPrivate(np))
+{
+}
+
+/*!
+
+ Constructs a query that will be used to run Xqueries or XSL-T
+ stylesheets, depending on the value of \a queryLanguage. It will use
+ \a np as its name pool.
+
+ \note If your QXmlQuery will process XSL-T stylesheets, this
+ constructor must be used. The default constructor can only
+ create instances of QXmlQuery for running XQueries.
+
+ \note The XSL-T support in this release is considered experimental.
+ See the \l{QtXmlPatterns Module#XSLT 2.0}{XSLT conformance} for
+ details.
+
+ \since 4.5
+ \sa queryLanguage()
+ */
+QXmlQuery::QXmlQuery(QueryLanguage queryLanguage,
+ const QXmlNamePool &np) : d(new QXmlQueryPrivate(np))
+{
+ d->queryLanguage = queryLanguage;
+}
+
+/*!
+ Destroys this QXmlQuery.
+ */
+QXmlQuery::~QXmlQuery()
+{
+ delete d;
+}
+
+/*!
+ Assigns \a other to this QXmlQuery instance.
+ */
+QXmlQuery &QXmlQuery::operator=(const QXmlQuery &other)
+{
+ /* Keep this section in sync with QXmlQuery::QXmlQuery(const QXmlQuery &).
+ */
+ if(d != other.d)
+ {
+ *d = *other.d;
+ d->detach();
+ }
+
+ return *this;
+}
+
+/*!
+ Changes the \l {QAbstractMessageHandler}{message handler} for this
+ QXmlQuery to \a aMessageHandler. The query sends all compile and
+ runtime messages to this message handler. QXmlQuery does not take
+ ownership of \a aMessageHandler.
+
+ Normally, the default message handler is sufficient. It writes
+ compile and runtime messages to \e stderr. The default message
+ handler includes color codes if \e stderr can render colors.
+
+ Note that changing the message handler after the query has been
+ compiled has no effect, i.e. the query uses the same message handler
+ at runtime that it uses at compile time.
+
+ When QXmlQuery calls QAbstractMessageHandler::message(),
+ the arguments are as follows:
+
+ \table
+ \header
+ \o message() argument
+ \o Semantics
+ \row
+ \o QtMsgType type
+ \o Only QtWarningMsg and QtFatalMsg are used. The former
+ identifies a compile or runtime warning, while the
+ latter identifies a dynamic or static error.
+ \row
+ \o const QString & description
+ \o An XHTML document which is the actual message. It is translated
+ into the current language.
+ \row
+ \o const QUrl &identifier
+ \o Identifies the error with a URI, where the fragment is
+ the error code, and the rest of the URI is the error namespace.
+ \row
+ \o const QSourceLocation & sourceLocation
+ \o Identifies where the error occurred.
+ \endtable
+
+ */
+void QXmlQuery::setMessageHandler(QAbstractMessageHandler *aMessageHandler)
+{
+ d->messageHandler = aMessageHandler;
+}
+
+/*!
+ Returns the message handler that handles compile and runtime
+ messages for this QXmlQuery.
+ */
+QAbstractMessageHandler *QXmlQuery::messageHandler() const
+{
+ return d->messageHandler;
+}
+
+/*!
+ Sets this QXmlQuery to an XQuery read from the \a sourceCode
+ device. The device must have been opened with at least
+ QIODevice::ReadOnly.
+
+ \a documentURI represents the query obtained from the \a sourceCode
+ device. It is the base URI of the static context, as defined in the
+ \l {http://www.w3.org/TR/xquery/}{XQuery language}. It is used
+ internally to resolve relative URIs that appear in the query, and
+ for message reporting. \a documentURI can be empty. If it is empty,
+ the \l{QCoreApplication::applicationFilePath()} {application file
+ path} is used. If it is not empty, it may be either relative or
+ absolute. If it is relative, it is resolved itself against the
+ \l {QCoreApplication::applicationFilePath()} {application file
+ path} before it is used. If \a documentURI is neither a valid URI
+ nor empty, the result is undefined.
+
+ If the query contains a static error (e.g. syntax error), an error
+ message is sent to the messageHandler(), and isValid() will return
+ \e false.
+
+ Variables must be bound before setQuery() is called.
+
+ The encoding of the XQuery in \a sourceCode is detected internally
+ using the rules for setting and detecting encoding of XQuery files,
+ which are explained in the \l {http://www.w3.org/TR/xquery/}
+ {XQuery language}.
+
+ If \a sourceCode is \c null or not readable, or if \a documentURI is not
+ a valid URI, behavior is undefined.
+ \sa isValid()
+ */
+void QXmlQuery::setQuery(QIODevice *sourceCode, const QUrl &documentURI)
+{
+ if(!sourceCode)
+ {
+ qWarning("A null QIODevice pointer cannot be passed.");
+ return;
+ }
+
+ if(!sourceCode->isReadable())
+ {
+ qWarning("The device must be readable.");
+ return;
+ }
+
+ d->queryURI = QXmlQueryPrivate::normalizeQueryURI(documentURI);
+ d->expression(sourceCode);
+}
+
+/*!
+ \overload
+ The behavior and requirements of this function are the same as for
+ setQuery(QIODevice*, const QUrl&), after the XQuery has been read
+ from the IO device into a string. Because \a sourceCode is already
+ a Unicode string, detection of its encoding is unnecessary.
+*/
+void QXmlQuery::setQuery(const QString &sourceCode, const QUrl &documentURI)
+{
+ Q_ASSERT_X(documentURI.isEmpty() || documentURI.isValid(), Q_FUNC_INFO,
+ "The document URI must be valid.");
+
+ QByteArray query(sourceCode.toUtf8());
+ QBuffer buffer(&query);
+ buffer.open(QIODevice::ReadOnly);
+
+ setQuery(&buffer, documentURI);
+}
+
+/*!
+ Sets this QXmlQuery to the XQuery read from the \a queryURI. Use
+ isValid() after calling this function. If an error occurred reading
+ \a queryURI, e.g., the query does not exist, cannot be read, or is
+ invalid, isValid() will return \e false.
+
+ The supported URI schemes are the same as those in the XQuery
+ function \c{fn:doc}, except that queryURI can be the object of
+ a variable binding.
+
+ \a baseURI is the Base URI of the static context, as defined in the
+ \l {http://www.w3.org/TR/xquery/}{XQuery language}. It is used
+ internally to resolve relative URIs that appear in the query, and
+ for message reporting. If \a baseURI is empty, \a queryURI is used.
+ Otherwise, \a baseURI is used, and it is resolved against the \l
+ {QCoreApplication::applicationFilePath()} {application file path} if
+ it is relative.
+
+ If \a queryURI is empty or invalid, or if \a baseURI is invalid,
+ the behavior of this function is undefined.
+ */
+void QXmlQuery::setQuery(const QUrl &queryURI, const QUrl &baseURI)
+{
+ Q_ASSERT_X(queryURI.isValid(), Q_FUNC_INFO, "The passed URI must be valid.");
+
+ const QUrl canonicalURI(QXmlQueryPrivate::normalizeQueryURI(queryURI));
+ Q_ASSERT(canonicalURI.isValid());
+ Q_ASSERT(!canonicalURI.isRelative());
+ Q_ASSERT(baseURI.isValid() || baseURI.isEmpty());
+
+ d->queryURI = QXmlQueryPrivate::normalizeQueryURI(baseURI.isEmpty() ? queryURI : baseURI);
+
+ QPatternist::AutoPtr<QIODevice> result;
+
+ try
+ {
+ result.reset(QPatternist::AccelTreeResourceLoader::load(canonicalURI, d->m_networkAccessDelegator,
+ d->staticContext()));
+ }
+ catch(const QPatternist::Exception)
+ {
+ /* We do nothing, result will be 0. */
+ }
+
+ if(result)
+ {
+ setQuery(result.data(), d->queryURI);
+ result->close();
+ }
+ else
+ d->recompileRequired();
+}
+
+/*!
+ Binds the variable \a name to the \a value so that $\a name can be
+ used from within the query to refer to the \a value.
+
+ \a name must not be \e null. \a {name}.isNull() must return false.
+ If \a name has already been bound by a previous bindVariable() call,
+ its previous binding will be overridden.
+
+ If \a {value} is null so that \a {value}.isNull() returns true, and
+ \a {name} already has a binding, the effect is to remove the
+ existing binding for \a {name}.
+
+ To bind a value of type QString or QUrl, wrap the value in a
+ QVariant such that QXmlItem's QVariant constructor is called.
+
+ All strings processed by the query must be valid XQuery strings,
+ which means they must contain only XML 1.0 characters. However,
+ this requirement is not checked. If the query processes an invalid
+ string, the behavior is undefined.
+
+ \sa QVariant::isValid(), {QtXDM}{How QVariant maps to XQuery's Data Model},
+ QXmlItem::isNull()
+ */
+void QXmlQuery::bindVariable(const QXmlName &name, const QXmlItem &value)
+{
+ if(name.isNull())
+ {
+ qWarning("The variable name cannot be null.");
+ return;
+ }
+
+ const QPatternist::VariableLoader::Ptr vl(d->variableLoader());
+ const QVariant variant(qVariantFromValue(value));
+
+ /* If the type of the variable changed(as opposed to only the value),
+ * we will have to recompile. */
+ if(vl->invalidationRequired(name, variant) || value.isNull())
+ d->recompileRequired();
+
+ vl->addBinding(name, variant);
+}
+
+/*!
+ \overload
+
+ This function constructs a QXmlName from \a localName using the
+ query's \l {QXmlNamePool} {namespace}. The function then behaves as
+ the overloaded function. It is equivalent to the following snippet.
+
+ \snippet doc/src/snippets/code/src_xmlpatterns_api_qxmlquery.cpp 0
+ */
+void QXmlQuery::bindVariable(const QString &localName, const QXmlItem &value)
+{
+ bindVariable(QXmlName(d->namePool, localName), value);
+}
+
+/*!
+ Binds the variable \a name to the \a device so that $\a name can be
+ used from within the query to refer to the \a device. The QIODevice
+ \a device is exposed to the query as a URI of type \c{xs:anyURI},
+ which can be passed to the \c{fn:doc()} function to be read. E.g.,
+ this function can be used to pass an XML document in memory to
+ \c{fn:doc}.
+
+ \snippet doc/src/snippets/code/src_xmlpatterns_api_qxmlquery.cpp 1
+
+ The caller must ensure that \a device has been opened with at least
+ QIODevice::ReadOnly prior to this binding. Otherwise, behavior is
+ undefined.
+
+ If the query will access an XML document contained in a QString, use
+ a QBuffer as shown in the following snippet. Suppose \e myQString
+ contains \c{<document>content</document>}
+
+ \snippet doc/src/snippets/qxmlquery/bindingExample.cpp 0
+
+ \a name must not be \e null. \a {name}.isNull() must return false.
+ If \a name has already been bound, its previous binding will be
+ overridden. The URI that \a name evaluates to is arbitrary and may
+ change.
+
+ If the type of the variable binding changes (e.g., if a previous
+ binding by the same name was a QVariant, or if there was no previous
+ binding), isValid() will return \c{false}, and recompilation of the
+ query text is required. To recompile the query, call setQuery(). For
+ this reason, bindVariable() should be called before setQuery(), if
+ possible.
+
+ \note \a device must not be deleted while this QXmlQuery exists.
+*/
+void QXmlQuery::bindVariable(const QXmlName &name, QIODevice *device)
+{
+ if(device && !device->isReadable())
+ {
+ qWarning("A null, or readable QIODevice must be passed.");
+ return;
+ }
+
+ if(name.isNull())
+ {
+ qWarning("The variable name cannot be null.");
+ return;
+ }
+
+ const QPatternist::VariableLoader::Ptr vl(d->variableLoader());
+
+ if(device)
+ {
+ const QVariant variant(qVariantFromValue(device));
+
+ if(vl->invalidationRequired(name, variant))
+ d->recompileRequired();
+
+ vl->addBinding(name, variant);
+
+ /* We need to tell the resource loader to discard its document, because
+ * the underlying QIODevice has changed, but the variable name is the
+ * same which means that the URI is the same, and hence the resource
+ * loader will return the document for the old QIODevice.
+ */
+ d->resourceLoader()->clear(QUrl(QLatin1String("tag:trolltech.com,2007:QtXmlPatterns:QIODeviceVariable:") + d->namePool.d->stringForLocalName(name.localName())));
+ }
+ else
+ {
+ vl->removeBinding(name);
+ d->recompileRequired();
+ }
+}
+
+/*!
+ \overload
+
+ If \a localName is a valid \l {QXmlName::isNCName()} {NCName}, this
+ function is equivalent to the following snippet.
+
+ \snippet doc/src/snippets/code/src_xmlpatterns_api_qxmlquery.cpp 2
+
+ A QXmlName is constructed from \a localName, and is passed
+ to the appropriate overload along with \a device.
+
+ \sa QXmlName::isNCName()
+ */
+void QXmlQuery::bindVariable(const QString &localName, QIODevice *device)
+{
+ bindVariable(QXmlName(d->namePool, localName), device);
+}
+
+/*!
+ Evaluates this query and sends the result as a sequence of callbacks
+ to the \l {QAbstractXmlReceiver} {receiver} \a callback. QXmlQuery
+ does not take ownership of \a callback.
+
+ If an error occurs during the evaluation, error messages are sent to
+ messageHandler() and \c false is returned.
+
+ If this query \l {isValid()} {is invalid}, \c{false} is returned
+ and the behavior is undefined. If \a callback is null,
+ behavior is undefined.
+
+ \sa QAbstractXmlReceiver, isValid()
+ */
+bool QXmlQuery::evaluateTo(QAbstractXmlReceiver *callback) const
+{
+ if(!callback)
+ {
+ qWarning("A non-null callback must be passed.");
+ return false;
+ }
+
+ if(isValid())
+ {
+ try
+ {
+ /*
+ * This order is significant. expression() might cause
+ * query recompilation, and as part of that it recreates
+ * the static context. However, if we create the dynamic
+ * context before the query recompilation has been
+ * triggered, it will use the old static context, and
+ * hence old source locations.
+ */
+ const QPatternist::Expression::Ptr expr(d->expression());
+ const QPatternist::DynamicContext::Ptr dynContext(d->dynamicContext(callback));
+ callback->startOfSequence();
+ expr->evaluateToSequenceReceiver(dynContext);
+ callback->endOfSequence();
+ return true;
+ }
+ catch(const QPatternist::Exception)
+ {
+ return false;
+ }
+ }
+ else
+ return false;
+}
+
+/*!
+ Attempts to evaluate the query and returns the results in the
+ \a target \l {QStringList} {string list}.
+
+ If the query \l {isValid()} {is valid} and the evaluation succeeds,
+ true is returned. Otherwise, false is returned and the contents of
+ \a target are undefined.
+
+ The query must evaluate to a sequence of \c{xs:string} values. If
+ the query does not evaluate to a sequence of strings, the values can
+ often be converted by adding a call to \c{string()} at the end of
+ the XQuery.
+
+ If \a target is null, the behavior is undefined.
+ */
+bool QXmlQuery::evaluateTo(QStringList *target) const
+{
+ if(!target)
+ {
+ qWarning("A non-null callback must be passed.");
+ return false;
+ }
+
+ if(isValid())
+ {
+ try
+ {
+ /*
+ * This order is significant. expression() might cause
+ * query recompilation, and as part of that it recreates
+ * the static context. However, if we create the dynamic
+ * context before the query recompilation has been
+ * triggered, it will use the old static context, and
+ * hence old source locations.
+ */
+ const QPatternist::Expression::Ptr expr(d->expression());
+ if(!expr)
+ return false;
+
+ QPatternist::DynamicContext::Ptr dynContext(d->dynamicContext());
+
+ if(!QPatternist::BuiltinTypes::xsString->xdtTypeMatches(expr->staticType()->itemType()))
+ return false;
+
+ const QPatternist::Item::Iterator::Ptr it(expr->evaluateSequence(dynContext));
+ QPatternist::Item next(it->next());
+
+ while(!next.isNull())
+ {
+ target->append(next.stringValue());
+ next = it->next();
+ }
+
+ return true;
+ }
+ catch(const QPatternist::Exception)
+ {
+ return false;
+ }
+ }
+ else
+ return false;
+}
+
+/*!
+ Evaluates the query or stylesheet, and writes the output to \a target.
+
+ QXmlSerializer is used to write the output to \a target. In a future
+ release, it is expected that this function will be changed to
+ respect serialization options set in the stylesheet.
+
+ If an error occurs during the evaluation, error messages are sent to
+ messageHandler() and \c false is returned.
+
+ If \a target is \c null, or is not opened in at least
+ QIODevice::WriteOnly mode, the behavior is undefined. QXmlQuery
+ does not take ownership of \a target.
+
+ \since 4.5
+ \overload
+ */
+bool QXmlQuery::evaluateTo(QIODevice *target) const
+{
+ if(!target)
+ {
+ qWarning("The pointer to the device cannot be null.");
+ return false;
+ }
+
+ if(!target->isWritable())
+ {
+ qWarning("The device must be writable.");
+ return false;
+ }
+
+ QXmlSerializer serializer(*this, target);
+ return evaluateTo(&serializer);
+}
+
+/*!
+ Starts the evaluation and makes it available in \a result. If \a
+ result is null, the behavior is undefined. The evaluation takes
+ place incrementally (lazy evaluation), as the caller uses
+ QXmlResultItems::next() to get the next result.
+
+ \sa QXmlResultItems::next()
+*/
+void QXmlQuery::evaluateTo(QXmlResultItems *result) const
+{
+ if(!result)
+ {
+ qWarning("A null pointer cannot be passed.");
+ return;
+ }
+
+ if(isValid())
+ {
+ try
+ {
+ /*
+ * We don't have the d->expression() calls and
+ * d->dynamicContext() calls in the same order as seen in
+ * QXmlQuery::evaluateTo(), and the reason to why
+ * that isn't a problem, is that we call isValid().
+ */
+ const QPatternist::DynamicContext::Ptr dynContext(d->dynamicContext());
+ result->d_ptr->setDynamicContext(dynContext);
+ result->d_ptr->iterator = d->expression()->evaluateSequence(dynContext);
+ }
+ catch(const QPatternist::Exception)
+ {
+ result->d_ptr->iterator = QPatternist::CommonValues::emptyIterator;
+ result->d_ptr->hasError = true;
+ }
+ }
+ else
+ {
+ result->d_ptr->iterator= QPatternist::CommonValues::emptyIterator;
+ result->d_ptr->hasError = true;
+ }
+}
+
+/*!
+ Evaluates the query, and serializes the output as XML to \a output.
+
+ If an error occurs during the evaluation, error messages are sent to
+ messageHandler(), the content of \a output is undefined and \c false is
+ returned, otherwise \c true is returned.
+
+ If \a output is \c null behavior is undefined. QXmlQuery
+ does not take ownership of \a output.
+
+ Internally, the class QXmlFormatter is used for this.
+ \since 4.5
+ */
+bool QXmlQuery::evaluateTo(QString *output) const
+{
+ Q_ASSERT_X(output, Q_FUNC_INFO,
+ "The input cannot be null");
+
+ QBuffer outputDevice;
+ outputDevice.open(QIODevice::ReadWrite);
+
+ QXmlFormatter formatter(*this, &outputDevice);
+ const bool success = evaluateTo(&formatter);
+
+ outputDevice.close();
+ *output = QString::fromUtf8(outputDevice.data().constData());
+
+ return success;
+}
+
+/*!
+ Returns true if this query is valid. Examples of invalid queries
+ are ones that contain syntax errors or that have not had setQuery()
+ called for them yet.
+ */
+bool QXmlQuery::isValid() const
+{
+ return d->isValid();
+}
+
+/*!
+ Sets the URI resolver to \a resolver. QXmlQuery does not take
+ ownership of \a resolver.
+
+ \sa uriResolver()
+ */
+void QXmlQuery::setUriResolver(const QAbstractUriResolver *resolver)
+{
+ d->uriResolver = resolver;
+}
+
+/*!
+ Returns the query's URI resolver. If no URI resolver has been set,
+ QtXmlPatterns will use the URIs in queries as they are.
+
+ The URI resolver provides a level of abstraction, or \e{polymorphic
+ URIs}. A resolver can rewrite \e{logical} URIs to physical ones, or
+ it can translate obsolete or invalid URIs to valid ones.
+
+ QtXmlPatterns calls the URI resolver for all URIs it encounters,
+ except for namespaces. Specifically, all builtin functions that deal
+ with URIs (\c{fn:doc()}, and \c{fn:doc-available()}).
+
+ In the case of \c{fn:doc()}, the absolute URI is the base URI in the
+ static context (which most likely is the location of the query).
+ Rather than use the URI the user specified, the return value of
+ QAbstractUriResolver::resolve() will be used.
+
+ When QtXmlPatterns calls QAbstractUriResolver::resolve() the
+ absolute URI is the URI mandated by the XQuery language, and the
+ relative URI is the URI specified by the user.
+
+ \sa setUriResolver()
+ */
+const QAbstractUriResolver *QXmlQuery::uriResolver() const
+{
+ return d->uriResolver;
+}
+
+/*!
+ Returns the name pool used by this QXmlQuery for constructing \l
+ {QXmlName} {names}. There is no setter for the name pool, because
+ mixing name pools causes errors due to name confusion.
+ */
+QXmlNamePool QXmlQuery::namePool() const
+{
+ return d->namePool;
+}
+
+/*!
+ Sets the focus to \a item. The focus is the set of items that the
+ context item expression and path expressions navigate from. For
+ example, in the expression \e p/span, the element that \e p
+ evaluates to is the focus for the following expression, \e span.
+
+ The focus can be accessed using the context item expression, i.e.,
+ dot (".").
+
+ By default, the focus is not set and is undefined. It will
+ therefore result in a dynamic error, \c XPDY0002, if the focus
+ is attempted to be accessed. The focus must be set before the
+ query is set with setQuery().
+
+ There is no behavior defined for setting an item which is null.
+
+ */
+void QXmlQuery::setFocus(const QXmlItem &item)
+{
+ d->contextItem = item;
+}
+
+/**
+ * This function should be a private member function of QXmlQuery,
+ * but we don't dare that due to our weird compilers.
+ * @internal
+ * @relates QXmlQuery
+ */
+template<typename TInputType>
+bool setFocusHelper(QXmlQuery *const queryInstance,
+ const TInputType &focusValue)
+{
+ /* We call resourceLoader(), so we have ensured that we have a resourceLoader
+ * that we will share in our copy. */
+ queryInstance->d->resourceLoader();
+
+ QXmlQuery focusQuery(*queryInstance);
+
+ /* Now we use the same, so we own the loaded document. */
+ focusQuery.d->m_resourceLoader = queryInstance->d->m_resourceLoader;
+
+ /* The copy constructor doesn't allow us to copy an existing QXmlQuery and
+ * changing the language at the same time so we need to use private API. */
+ focusQuery.d->queryLanguage = QXmlQuery::XQuery10;
+
+ Q_ASSERT(focusQuery.queryLanguage() == QXmlQuery::XQuery10);
+ focusQuery.bindVariable(QChar::fromLatin1('u'), focusValue);
+ focusQuery.setQuery(QLatin1String("doc($u)"));
+ Q_ASSERT(focusQuery.isValid());
+
+ QXmlResultItems focusResult;
+
+ queryInstance->d->m_resourceLoader = focusQuery.d->m_resourceLoader;
+
+ focusQuery.evaluateTo(&focusResult);
+ const QXmlItem focusItem(focusResult.next());
+
+ if(focusItem.isNull() || focusResult.hasError())
+ return false;
+ else
+ {
+ queryInstance->setFocus(focusItem);
+ return true;
+ }
+}
+
+/*!
+ \since 4.5
+ \overload
+
+ Sets the focus to be the document located at \a documentURI and
+ returns true. If \a documentURI cannot be loaded, false is returned.
+ It is undefined at what time the document may be loaded. When
+ loading the document, the message handler and URI resolver set on
+ this QXmlQuery are used.
+
+ If \a documentURI is empty or is not a valid URI, the behavior of
+ this function is undefined.
+ */
+bool QXmlQuery::setFocus(const QUrl &documentURI)
+{
+ Q_ASSERT_X(documentURI.isValid() && !documentURI.isEmpty(),
+ Q_FUNC_INFO,
+ "The URI passed must be valid.");
+
+ return setFocusHelper(this, QVariant(documentURI));
+}
+
+/*!
+
+ Sets the focus to be the \a document read from the QIODevice and
+ returns true. If \a document cannot be loaded, false is returned.
+
+ QXmlQuery does not take ownership of \a document. The user
+ guarantees that a document is available from the \a document device
+ and that the document is not empty. The device must be opened in at
+ least read-only mode. \a document must stay in scope as long as the
+ current query is active.
+
+ \since 4.5
+ \overload
+ */
+bool QXmlQuery::setFocus(QIODevice *document)
+{
+ if(!document)
+ {
+ qWarning("A null QIODevice pointer cannot be passed.");
+ return false;
+ }
+
+ if(!document->isReadable())
+ {
+ qWarning("The device must be readable.");
+ return false;
+ }
+
+ return setFocusHelper(this, document);
+}
+
+/*!
+ Returns a value indicating what this QXmlQuery is being used for.
+ The default is QXmlQuery::XQuery10, which means the QXmlQuery is
+ being used for running XQuery and XPath queries. QXmlQuery::XSLT20
+ can also be returned, which indicates the QXmlQuery is for running
+ XSL-T spreadsheets.
+
+ \since 4.5
+ */
+QXmlQuery::QueryLanguage QXmlQuery::queryLanguage() const
+{
+ return d->queryLanguage;
+}
+
+/*!
+ Sets the \a name of the initial template. The initial template is
+ the one the processor calls first, instead of attempting to match a
+ template to the context node (if any). If an initial template is not
+ set, the standard order of template invocation will be used.
+
+ This function only applies when using QXmlQuery to process XSL-T
+ stylesheets. The name becomes part of the compiled stylesheet.
+ Therefore, this function must be called before calling setQuery().
+
+ If the stylesheet has no template named \a name, the processor will
+ use the standard order of template invocation.
+
+ \since 4.5
+ \sa initialTemplateName()
+ */
+void QXmlQuery::setInitialTemplateName(const QXmlName &name)
+{
+ d->initialTemplateName = name;
+}
+
+/*!
+ \overload
+
+ Sets the name of the initial template to \a localName, which must be
+ a valid \l{QXmlName::localName()} {local name}. The initial template
+ is the one the processor calls first, instead of attempting to match
+ a template to the context node (if any). If an initial template is
+ not set, the standard order of template invocation will be used.
+
+ This function only applies when using QXmlQuery to process XSL-T
+ stylesheets. The name becomes part of the compiled stylesheet.
+ Therefore, this function must be called before calling setQuery().
+
+ If \a localName is not a valid \l{QXmlName::localName()} {local
+ name}, the effect is undefined. If the stylesheet has no template
+ named \a localName, the processor will use the standard order of
+ template invocation.
+
+ \since 4.5
+ \sa initialTemplateName()
+ */
+void QXmlQuery::setInitialTemplateName(const QString &localName)
+{
+ Q_ASSERT_X(QXmlName::isNCName(localName),
+ Q_FUNC_INFO,
+ "The name passed must be a valid NCName.");
+ setInitialTemplateName(QXmlName(d->namePool, localName));
+}
+
+/*!
+ Returns the name of the XSL-T stylesheet template that the processor
+ will call first when running an XSL-T stylesheet. This function only
+ applies when using QXmlQuery to process XSL-T stylesheets. By
+ default, no initial template is set. In that case, a default
+ constructed QXmlName is returned.
+
+ \since 4.5
+ */
+QXmlName QXmlQuery::initialTemplateName() const
+{
+ return d->initialTemplateName;
+}
+
+/*!
+ Sets the network manager to \a newManager.
+ QXmlQuery does not take ownership of \a newManager.
+
+ \sa networkAccessManager()
+ \since 4.5
+ */
+void QXmlQuery::setNetworkAccessManager(QNetworkAccessManager *newManager)
+{
+ d->m_networkAccessDelegator->m_genericManager = newManager;
+}
+
+/*!
+ Returns the network manager, or 0 if it has not been set.
+
+ \sa setNetworkAccessManager()
+ \since 4.5
+ */
+QNetworkAccessManager *QXmlQuery::networkAccessManager() const
+{
+ return d->m_networkAccessDelegator->m_genericManager;
+}
+
+/*!
+ Binds the result of the query \a query, to a variable by name \a name.
+
+ Evaluation of \a query will be commenced when this function is called.
+
+ If \a query is invalid, behavior is undefined. \a query will be copied.
+
+ \since 4.5
+ \sa isValid()
+ */
+void QXmlQuery::bindVariable(const QXmlName &name, const QXmlQuery &query)
+{
+ Q_ASSERT_X(query.isValid(), Q_FUNC_INFO, "The query being bound must be valid.");
+
+ const QPatternist::VariableLoader::Ptr vl(d->variableLoader());
+ const QVariant variant(qVariantFromValue(query));
+
+ if(vl->invalidationRequired(name, variant))
+ d->recompileRequired();
+
+ vl->addBinding(name, variant);
+}
+
+/*!
+ \overload
+
+ Has the same behavior and effects as the function being overloaded, but takes
+ the variable name \a localName as a QString. \a query is used as in the
+ overloaded function.
+
+ \since 4.5
+ */
+void QXmlQuery::bindVariable(const QString &localName, const QXmlQuery &query)
+{
+ return bindVariable(QXmlName(d->namePool, localName), query);
+}
+
+QT_END_NAMESPACE
diff --git a/src/xmlpatterns/api/qxmlquery.h b/src/xmlpatterns/api/qxmlquery.h
new file mode 100644
index 0000000000..138819c087
--- /dev/null
+++ b/src/xmlpatterns/api/qxmlquery.h
@@ -0,0 +1,147 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtXmlPatterns 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QXMLQUERY_H
+#define QXMLQUERY_H
+
+#include <QtCore/QUrl>
+#include <QtXmlPatterns/QAbstractXmlNodeModel>
+#include <QtXmlPatterns/QAbstractXmlReceiver>
+#include <QtXmlPatterns/QXmlNamePool>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(XmlPatterns)
+
+class QAbstractMessageHandler;
+class QAbstractUriResolver;
+class QIODevice;
+class QNetworkAccessManager;
+class QXmlName;
+class QXmlNodeIndex;
+class QXmlQueryPrivate;
+class QXmlResultItems;
+class QXmlSerializer;
+
+/* The members in the namespace QPatternistSDK are internal, not part of the public API, and
+ * unsupported. Using them leads to undefined behavior. */
+namespace QPatternistSDK
+{
+ class TestCase;
+}
+
+namespace QPatternist
+{
+ class VariableLoader;
+};
+
+class Q_XMLPATTERNS_EXPORT QXmlQuery
+{
+public:
+ enum QueryLanguage
+ {
+ XQuery10 = 1,
+ XSLT20 = 2
+ };
+
+ QXmlQuery();
+ QXmlQuery(const QXmlQuery &other);
+ QXmlQuery(const QXmlNamePool &np);
+ QXmlQuery(QueryLanguage queryLanguage,
+ const QXmlNamePool &np = QXmlNamePool());
+ ~QXmlQuery();
+ QXmlQuery &operator=(const QXmlQuery &other);
+
+ void setMessageHandler(QAbstractMessageHandler *messageHandler);
+ QAbstractMessageHandler *messageHandler() const;
+
+ void setQuery(const QString &sourceCode, const QUrl &documentURI = QUrl());
+ void setQuery(QIODevice *sourceCode, const QUrl &documentURI = QUrl());
+ void setQuery(const QUrl &queryURI, const QUrl &baseURI = QUrl());
+
+ QXmlNamePool namePool() const;
+
+ void bindVariable(const QXmlName &name, const QXmlItem &value);
+ void bindVariable(const QString &localName, const QXmlItem &value);
+
+ void bindVariable(const QXmlName &name, QIODevice *);
+ void bindVariable(const QString &localName, QIODevice *);
+ void bindVariable(const QXmlName &name, const QXmlQuery &query);
+ void bindVariable(const QString &localName, const QXmlQuery &query);
+
+ bool isValid() const;
+
+ void evaluateTo(QXmlResultItems *result) const;
+ bool evaluateTo(QAbstractXmlReceiver *callback) const;
+ bool evaluateTo(QStringList *target) const;
+ bool evaluateTo(QIODevice *target) const;
+ bool evaluateTo(QString *output) const;
+
+ void setUriResolver(const QAbstractUriResolver *resolver);
+ const QAbstractUriResolver *uriResolver() const;
+
+ void setFocus(const QXmlItem &item);
+ bool setFocus(const QUrl &documentURI);
+ bool setFocus(QIODevice *document);
+
+ void setInitialTemplateName(const QXmlName &name);
+ void setInitialTemplateName(const QString &name);
+ QXmlName initialTemplateName() const;
+
+ void setNetworkAccessManager(QNetworkAccessManager *newManager);
+ QNetworkAccessManager *networkAccessManager() const;
+
+ QueryLanguage queryLanguage() const;
+private:
+ friend class QXmlName;
+ friend class QXmlSerializer;
+ friend class QPatternistSDK::TestCase;
+ friend class QPatternist::VariableLoader;
+ template<typename TInputType> friend bool setFocusHelper(QXmlQuery *const queryInstance,
+ const TInputType &focusValue);
+ QXmlQueryPrivate *d;
+};
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif
diff --git a/src/xmlpatterns/api/qxmlquery_p.h b/src/xmlpatterns/api/qxmlquery_p.h
new file mode 100644
index 0000000000..c8ed4412ca
--- /dev/null
+++ b/src/xmlpatterns/api/qxmlquery_p.h
@@ -0,0 +1,330 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtXmlPatterns 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef QXMLQUERY_P_H
+#define QXMLQUERY_P_H
+
+#include <QAbstractMessageHandler>
+#include <QAbstractUriResolver>
+#include <QCoreApplication>
+#include <QPointer>
+#include <QSourceLocation>
+#include <QUrl>
+#include <QVariant>
+#include <QXmlName>
+#include <QXmlNamePool>
+#include <QXmlQuery>
+
+#include "qacceltreebuilder_p.h"
+#include "qacceltreeresourceloader_p.h"
+#include "qcoloringmessagehandler_p.h"
+#include "qcommonsequencetypes_p.h"
+#include "qexpressionfactory_p.h"
+#include "qfocus_p.h"
+#include "qfunctionfactorycollection_p.h"
+#include "qgenericdynamiccontext_p.h"
+#include "qgenericstaticcontext_p.h"
+#include "qnamepool_p.h"
+#include "qnetworkaccessdelegator_p.h"
+#include "qreferencecountedvalue_p.h"
+#include "qresourcedelegator_p.h"
+#include "qstaticfocuscontext_p.h"
+#include "quriloader_p.h"
+#include "qvariableloader_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QXmlQueryPrivate
+{
+public:
+
+ inline QXmlQueryPrivate(const QXmlNamePool &np = QXmlNamePool()) : namePool(np)
+ , messageHandler(0)
+ , uriResolver(0)
+ , queryLanguage(QXmlQuery::XQuery10)
+ , m_networkAccessDelegator(new QPatternist::NetworkAccessDelegator(0, 0))
+ {
+ m_networkAccessDelegator->m_variableURIManager = new QPatternist::URILoader(ownerObject(), namePool.d, variableLoader());
+ }
+
+ void detach()
+ {
+ if(m_variableLoader)
+ m_variableLoader = QPatternist::VariableLoader::Ptr(new QPatternist::VariableLoader(namePool.d, m_variableLoader));
+
+ delete m_networkAccessDelegator->m_variableURIManager;
+ m_networkAccessDelegator->m_variableURIManager = new QPatternist::URILoader(ownerObject(), namePool.d, m_variableLoader);
+
+ if(m_resourceLoader)
+ {
+ const QPatternist::AccelTreeResourceLoader::Ptr nev(new QPatternist::AccelTreeResourceLoader(namePool.d,
+ m_networkAccessDelegator));
+ m_resourceLoader = QPatternist::ResourceLoader::Ptr(new QPatternist::ResourceDelegator(m_resourceLoader->deviceURIs(),
+ m_resourceLoader,
+ nev));
+ }
+ }
+
+ bool isValid()
+ {
+ return expression();
+ }
+
+ inline void recompileRequired()
+ {
+ m_expr.reset();
+ }
+
+ inline QPatternist::VariableLoader::Ptr variableLoader()
+ {
+ if(!m_variableLoader)
+ m_variableLoader = QPatternist::VariableLoader::Ptr(new QPatternist::VariableLoader(namePool.d));
+
+ return m_variableLoader;
+ }
+
+ inline QPatternist::GenericStaticContext::Ptr staticContext()
+ {
+ if(m_staticContext && m_expr)
+ return m_staticContext;
+ /* Else, re-create the staticContext. */
+
+ if(!messageHandler)
+ messageHandler = new QPatternist::ColoringMessageHandler(ownerObject());
+
+ if(!m_functionFactory)
+ {
+ if(queryLanguage == QXmlQuery::XQuery10)
+ m_functionFactory = QPatternist::FunctionFactoryCollection::xpath20Factory(namePool.d);
+ else
+ {
+ Q_ASSERT(queryLanguage == QXmlQuery::XSLT20);
+ m_functionFactory = QPatternist::FunctionFactoryCollection::xslt20Factory(namePool.d);
+ }
+ }
+
+ const QPatternist::GenericStaticContext::Ptr genericStaticContext(new QPatternist::GenericStaticContext(namePool.d,
+ messageHandler,
+ queryURI,
+ m_functionFactory,
+ queryLanguage));
+ genericStaticContext->setResourceLoader(resourceLoader());
+
+ genericStaticContext->setExternalVariableLoader(variableLoader());
+
+ m_staticContext = genericStaticContext;
+
+ if(!contextItem.isNull())
+ m_staticContext = QPatternist::StaticContext::Ptr(new QPatternist::StaticFocusContext(QPatternist::AtomicValue::qtToXDMType(contextItem), m_staticContext));
+
+ return m_staticContext;
+ }
+
+ inline QPatternist::DynamicContext::Ptr dynamicContext(QAbstractXmlReceiver *const callback = 0)
+ {
+ const QPatternist::StaticContext::Ptr statContext(staticContext());
+ Q_ASSERT(statContext);
+
+ QPatternist::GenericDynamicContext::Ptr dynContext(new QPatternist::GenericDynamicContext(namePool.d, statContext->messageHandler(),
+ statContext->sourceLocations()));
+
+ QPatternist::AutoPtr<QPatternist::NodeBuilder> nodeBuilder(new QPatternist::AccelTreeBuilder<false>(QUrl(), QUrl(), namePool.d,
+ dynContext.data()));
+ dynContext->setNodeBuilder(nodeBuilder);
+
+ dynContext->setResourceLoader(statContext->resourceLoader());
+ dynContext->setExternalVariableLoader(statContext->externalVariableLoader());
+ dynContext->setUriResolver(uriResolver);
+
+ if(callback)
+ dynContext->setOutputReceiver(callback);
+
+ if(contextItem.isNull())
+ return dynContext;
+ else
+ {
+ QPatternist::DynamicContext::Ptr focus(new QPatternist::Focus(dynContext));
+ QPatternist::Item::Iterator::Ptr it(QPatternist::makeSingletonIterator(QPatternist::Item::fromPublic(contextItem)));
+ it->next();
+ focus->setFocusIterator(it);
+ return focus;
+ }
+ }
+
+ inline QPatternist::AccelTreeResourceLoader::Ptr resourceLoader()
+ {
+ if(!m_resourceLoader)
+ m_resourceLoader = (new QPatternist::AccelTreeResourceLoader(namePool.d, m_networkAccessDelegator));
+
+ return m_resourceLoader;
+ }
+
+
+ static inline QUrl normalizeQueryURI(const QUrl &uri)
+ {
+ Q_ASSERT_X(uri.isEmpty() || uri.isValid(), Q_FUNC_INFO,
+ "The URI passed to QXmlQuery::setQuery() must be valid or empty.");
+ if(uri.isEmpty())
+ return QUrl::fromLocalFile(QCoreApplication::applicationFilePath());
+ else if(uri.isRelative())
+ return QUrl::fromLocalFile(QCoreApplication::applicationFilePath()).resolved(uri);
+ else
+ return uri;
+ }
+
+ void setRequiredType(const QPatternist::SequenceType::Ptr &seqType)
+ {
+ Q_ASSERT(seqType);
+ if(!m_requiredType || m_requiredType->is(seqType))
+ return;
+
+ m_requiredType = seqType;
+ m_staticContext.reset();
+ }
+
+ QPatternist::SequenceType::Ptr requiredType()
+ {
+ if(m_requiredType)
+ return m_requiredType;
+ else
+ {
+ m_requiredType = QPatternist::CommonSequenceTypes::ZeroOrMoreItems;
+ return m_requiredType;
+ }
+ }
+
+ QPatternist::Expression::Ptr expression(QIODevice *const queryDevice = 0)
+ {
+ if(m_expr && !queryDevice)
+ return m_expr;
+
+ /* If we need to update, but we don't have any source code, we can
+ * never create an Expression. */
+ if(!queryDevice)
+ return QPatternist::Expression::Ptr();
+
+ try
+ {
+ /* The static context has source locations, and they need to be
+ * updated to the new query. */
+ m_staticContext.reset();
+
+ if(!m_expressionFactory)
+ m_expressionFactory = QPatternist::ExpressionFactory::Ptr(new QPatternist::ExpressionFactory());
+
+ m_expr = m_expressionFactory->createExpression(queryDevice, staticContext(),
+ queryLanguage,
+ requiredType(),
+ queryURI,
+ initialTemplateName);
+ }
+ catch(const QPatternist::Exception)
+ {
+ m_expr.reset();
+
+ /* We don't call m_staticContext.reset() because it shouldn't be
+ * necessary, since m_staticContext is changed when the expression
+ * is changed. */
+ }
+
+ return m_expr;
+ }
+
+ QXmlNamePool namePool;
+ QPointer<QAbstractMessageHandler> messageHandler;
+ /**
+ * Must be absolute and valid.
+ */
+ QUrl queryURI;
+ const QAbstractUriResolver * uriResolver;
+ QXmlItem contextItem;
+ QXmlName initialTemplateName;
+
+ inline void setExpressionFactory(const QPatternist::ExpressionFactory::Ptr &expr)
+ {
+ m_expressionFactory = expr;
+ }
+
+ QXmlQuery::QueryLanguage queryLanguage;
+ QPointer<QNetworkAccessManager> userNetworkManager;
+
+ inline QObject *ownerObject()
+ {
+ if(!m_owner)
+ m_owner = new QPatternist::ReferenceCountedValue<QObject>(new QObject());
+
+ return m_owner->value;
+ }
+
+ QPatternist::ExpressionFactory::Ptr m_expressionFactory;
+ QPatternist::StaticContext::Ptr m_staticContext;
+ QPatternist::VariableLoader::Ptr m_variableLoader;
+ QPatternist::DeviceResourceLoader::Ptr m_resourceLoader;
+ /**
+ * This is the AST for the query.
+ */
+ QPatternist::Expression::Ptr m_expr;
+ QPatternist::ReferenceCountedValue<QObject>::Ptr m_owner;
+
+ /**
+ * This is our effective network manager, that we end up using. The one the
+ * user sets is userNetworkManager.
+ */
+ QPatternist::SequenceType::Ptr m_requiredType;
+ QPatternist::FunctionFactory::Ptr m_functionFactory;
+ QPatternist::NetworkAccessDelegator::Ptr m_networkAccessDelegator;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/xmlpatterns/api/qxmlresultitems.cpp b/src/xmlpatterns/api/qxmlresultitems.cpp
new file mode 100644
index 0000000000..a2253c98e8
--- /dev/null
+++ b/src/xmlpatterns/api/qxmlresultitems.cpp
@@ -0,0 +1,149 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtXmlPatterns 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qxmlresultitems.h"
+#include "qxmlresultitems_p.h"
+#include "qitem_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QXmlResultItems
+ \brief The QXmlResultItems class iterates through the results of evaluating an XQuery in QXmlQuery.
+ \reentrant
+ \since 4.4
+ \ingroup xml-tools
+
+ QXmlResultItems presents the evaluation of an associated query as a
+ sequence of \l{QXmlItem}{QXmlItems}. The sequence is traversed by
+ repeatedly calling next(), which actually produces the sequence by
+ lazy evaluation of the query.
+
+ \snippet doc/src/snippets/code/src_xmlpatterns_api_qxmlresultitems.cpp 0
+
+ An effect of letting next() produce the sequence by lazy evaluation
+ is that a query error can occur on any call to next(). If an error
+ occurs, both next() and current() will return the null QXmlItem, and
+ hasError() will return true.
+
+ QXmlResultItems can be thought of as an "iterator" that traverses
+ the sequence of query results once, in the forward direction. Each
+ call to next() advances the iterator to the next QXmlItem in the
+ sequence and returns it, and current() always returns the QXmlItem
+ that next() returned the last time it was called.
+
+ \sa QXmlItem::isNode(), QXmlItem::isAtomicValue(), QXmlNodeModelIndex
+ */
+
+/*!
+ Constructs an instance of QXmlResultItems.
+ */
+QXmlResultItems::QXmlResultItems() : d_ptr(new QXmlResultItemsPrivate())
+{
+}
+
+/*!
+ Destroys this instance of QXmlResultItems.
+ */
+QXmlResultItems::~QXmlResultItems()
+{
+ delete d_ptr;
+}
+
+/*!
+ Returns the next result in the sequence produced by lazy evaluation
+ of the associated query. When the returned QXmlItem is null, either
+ the evaluation terminated normally without producing another result,
+ or an error occurred. Call hasError() to determine whether the null
+ item was caused by normal termination or by an error.
+
+ Returns a null QXmlItem if there is no associated QXmlQuery.
+ */
+QXmlItem QXmlResultItems::next()
+{
+ Q_D(QXmlResultItems);
+ if(d->hasError)
+ return QXmlItem();
+
+ try
+ {
+ d->current = QPatternist::Item::toPublic(d->iterator->next());
+ return d->current;
+ }
+ catch(const QPatternist::Exception)
+ {
+ d->current = QXmlItem();
+ d->hasError = true;
+ return QXmlItem();
+ }
+}
+
+/*!
+ Returns the current item. The current item is the last item
+ that was produced and returned by next().
+
+ Returns a null QXmlItem if there is no associated QXmlQuery.
+ */
+QXmlItem QXmlResultItems::current() const
+{
+ Q_D(const QXmlResultItems);
+
+ if(d->hasError)
+ return QXmlItem();
+ else
+ return d->current;
+}
+
+/*!
+
+ If an error occurred during evaluation of the query, true is
+ returned.
+
+ Returns false if query evaluation has been done.
+ */
+bool QXmlResultItems::hasError() const
+{
+ Q_D(const QXmlResultItems);
+ return d->hasError;
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/xmlpatterns/api/qxmlresultitems.h b/src/xmlpatterns/api/qxmlresultitems.h
new file mode 100644
index 0000000000..aeb7d2c66d
--- /dev/null
+++ b/src/xmlpatterns/api/qxmlresultitems.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtXmlPatterns 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QXMLRESULTITEMS
+#define QXMLRESULTITEMS
+
+#include <QtCore/QString>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(XmlPatterns)
+
+class QXmlItem;
+class QXmlQuery;
+class QXmlResultItemsPrivate;
+
+class Q_XMLPATTERNS_EXPORT QXmlResultItems
+{
+public:
+ QXmlResultItems();
+ virtual ~QXmlResultItems();
+
+ bool hasError() const;
+ QXmlItem next();
+ QXmlItem current() const;
+
+private:
+ friend class QXmlQuery;
+ Q_DECLARE_PRIVATE(QXmlResultItems)
+ QXmlResultItemsPrivate *d_ptr;
+ Q_DISABLE_COPY(QXmlResultItems)
+};
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif
diff --git a/src/xmlpatterns/api/qxmlresultitems_p.h b/src/xmlpatterns/api/qxmlresultitems_p.h
new file mode 100644
index 0000000000..af3e2d3314
--- /dev/null
+++ b/src/xmlpatterns/api/qxmlresultitems_p.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtXmlPatterns 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef QXMLRESULTITEMS_P_H
+#define QXMLRESULTITEMS_P_H
+
+#include "qcommonvalues_p.h"
+#include "qdynamiccontext_p.h"
+#include "qitem_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QXmlResultItemsPrivate
+{
+public:
+ inline QXmlResultItemsPrivate() : iterator(QPatternist::CommonValues::emptyIterator)
+ , hasError(false)
+ {
+ }
+
+ void setDynamicContext(const QPatternist::DynamicContext::Ptr &context)
+ {
+ m_context = context;
+ }
+
+ QPatternist::Item::Iterator::Ptr iterator;
+ QXmlItem current;
+ bool hasError;
+private:
+ /**
+ * We never use it. We only keep a ref to it such that it doesn't get
+ * de-allocated.
+ */
+ QPatternist::DynamicContext::Ptr m_context;
+};
+
+QT_END_NAMESPACE
+#endif
+
diff --git a/src/xmlpatterns/api/qxmlserializer.cpp b/src/xmlpatterns/api/qxmlserializer.cpp
new file mode 100644
index 0000000000..0c2f92dad9
--- /dev/null
+++ b/src/xmlpatterns/api/qxmlserializer.cpp
@@ -0,0 +1,653 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtXmlPatterns 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdynamiccontext_p.h"
+#include "qpatternistlocale_p.h"
+#include "qitem_p.h"
+#include "qxmlquery_p.h"
+#include "qxmlserializer_p.h"
+#include "qxmlserializer.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace QPatternist;
+
+QXmlSerializerPrivate::QXmlSerializerPrivate(const QXmlQuery &query,
+ QIODevice *outputDevice)
+ : isPreviousAtomic(false),
+ state(QXmlSerializer::BeforeDocumentElement),
+ np(query.namePool().d),
+ device(outputDevice),
+ codec(QTextCodec::codecForMib(106)), /* UTF-8 */
+ query(query)
+{
+ hasClosedElement.reserve(EstimatedTreeDepth);
+ namespaces.reserve(EstimatedTreeDepth);
+ nameCache.reserve(EstimatedNameCount);
+
+ hasClosedElement.push(qMakePair(QXmlName(), true));
+
+ /*
+ We push the empty namespace such that first of all
+ namespaceBinding() won't assert on an empty QStack,
+ and such that the empty namespace is in-scope and
+ that the code doesn't attempt to declare it.
+
+ We push the XML namespace. Although we won't receive
+ declarations for it, we may output attributes by that
+ name.
+ */
+ QVector<QXmlName> defNss;
+ defNss.resize(2);
+ defNss[0] = QXmlName(StandardNamespaces::empty,
+ StandardLocalNames::empty,
+ StandardPrefixes::empty);
+ defNss[1] = QXmlName(StandardNamespaces::xml,
+ StandardLocalNames::empty,
+ StandardPrefixes::xml);
+
+ namespaces.push(defNss);
+
+ /* If we don't set this flag, QTextCodec will generate a BOM. */
+ converterState.flags = QTextCodec::IgnoreHeader;
+}
+
+/*!
+ \class QXmlSerializer
+ \brief The QXmlSerializer class is an implementation of QAbstractXmlReceiver for transforming XQuery output into unformatted XML.
+
+ \reentrant
+ \since 4.4
+ \ingroup xml-tools
+
+ QXmlSerializer translates an \l {XQuery Sequence} {XQuery sequence}, usually
+ the output of an QXmlQuery, into XML. Consider the example:
+
+ \snippet doc/src/snippets/code/src_xmlpatterns_api_qxmlserializer.cpp 0
+
+ First it constructs a \l {QXmlQuery} {query} that gets the
+ first paragraph from document \c index.html. Then it constructs
+ an instance of this class with the \l {QXmlQuery} {query} and
+ \l {QIODevice} {myOutputDevice}. Finally, it
+ \l {QXmlQuery::evaluateTo()} {evaluates} the
+ \l {QXmlQuery} {query}, producing an ordered sequence of calls
+ to the serializer's callback functions. The sequence of callbacks
+ transforms the query output to XML and writes it to
+ \l {QIODevice} {myOutputDevice}.
+
+ QXmlSerializer will:
+
+ \list
+ \o Declare namespaces when needed,
+
+ \o Use appropriate escaping, when characters can't be
+ represented in the XML,
+
+ \o Handle line endings appropriately,
+
+ \o Report errors, when it can't serialize the content, e.g.,
+ when asked to serialize an attribute that is a top-level node,
+ or when more than one top-level element is encountered.
+
+ \endlist
+
+ If an error occurs during serialization, result is undefined
+ unless the serializer is driven through a call to
+ QXmlQuery::evaluateTo().
+
+ If the generated XML should be indented and formatted for reading,
+ use QXmlFormatter.
+
+ \sa {http://www.w3.org/TR/xslt-xquery-serialization/}{XSLT 2.0 and XQuery 1.0 Serialization}
+
+ \sa QXmlFormatter
+ */
+
+/*!
+ Constructs a serializer that uses the name pool and message
+ handler in \a query, and writes the output to \a outputDevice.
+
+ \a outputDevice must be a valid, non-null device that is open in
+ write mode, otherwise behavior is undefined.
+
+ \a outputDevice must not be opened with QIODevice::Text because it
+ will cause the output to be incorrect. This class will ensure line
+ endings are serialized as according with the XML specification.
+ QXmlSerializer does not take ownership of \a outputDevice.
+ */
+QXmlSerializer::QXmlSerializer(const QXmlQuery &query,
+ QIODevice *outputDevice) : QAbstractXmlReceiver(new QXmlSerializerPrivate(query, outputDevice))
+{
+ if(!outputDevice)
+ {
+ qWarning("outputDevice cannot be null.");
+ return;
+ }
+
+ if(!outputDevice->isWritable())
+ {
+ qWarning("outputDevice must be opened in write mode.");
+ return;
+ }
+}
+
+/*!
+ \internal
+ */
+QXmlSerializer::QXmlSerializer(QAbstractXmlReceiverPrivate *d) : QAbstractXmlReceiver(d)
+{
+}
+
+/*!
+ \internal
+ */
+bool QXmlSerializer::atDocumentRoot() const
+{
+ Q_D(const QXmlSerializer);
+ return d->state == BeforeDocumentElement ||
+ (d->state == InsideDocumentElement && d->hasClosedElement.size() == 1);
+}
+
+/*!
+ \internal
+ */
+void QXmlSerializer::startContent()
+{
+ Q_D(QXmlSerializer);
+ if (!d->hasClosedElement.top().second) {
+ d->write('>');
+ d->hasClosedElement.top().second = true;
+ }
+}
+
+/*!
+ \internal
+ */
+void QXmlSerializer::writeEscaped(const QString &toEscape)
+{
+ if(toEscape.isEmpty()) /* Early exit. */
+ return;
+
+ QString result;
+ result.reserve(int(toEscape.length() * 1.1));
+ const int length = toEscape.length();
+
+ for(int i = 0; i < length; ++i)
+ {
+ const QChar c(toEscape.at(i));
+
+ if(c == QLatin1Char('<'))
+ result += QLatin1String("&lt;");
+ else if(c == QLatin1Char('>'))
+ result += QLatin1String("&gt;");
+ else if(c == QLatin1Char('&'))
+ result += QLatin1String("&amp;");
+ else
+ result += toEscape.at(i);
+ }
+
+ write(result);
+}
+
+/*!
+ \internal
+ */
+void QXmlSerializer::writeEscapedAttribute(const QString &toEscape)
+{
+ if(toEscape.isEmpty()) /* Early exit. */
+ return;
+
+ QString result;
+ result.reserve(int(toEscape.length() * 1.1));
+ const int length = toEscape.length();
+
+ for(int i = 0; i < length; ++i)
+ {
+ const QChar c(toEscape.at(i));
+
+ if(c == QLatin1Char('<'))
+ result += QLatin1String("&lt;");
+ else if(c == QLatin1Char('>'))
+ result += QLatin1String("&gt;");
+ else if(c == QLatin1Char('&'))
+ result += QLatin1String("&amp;");
+ else if(c == QLatin1Char('"'))
+ result += QLatin1String("&quot;");
+ else
+ result += toEscape.at(i);
+ }
+
+ write(result);
+}
+
+/*!
+ \internal
+ */
+void QXmlSerializer::write(const QString &content)
+{
+ Q_D(QXmlSerializer);
+ d->device->write(d->codec->fromUnicode(content.constData(), content.length(), &d->converterState));
+}
+
+/*!
+ \internal
+ */
+void QXmlSerializer::write(const QXmlName &name)
+{
+ Q_D(QXmlSerializer);
+ const QByteArray &cell = d->nameCache[name.code()];
+
+ if(cell.isNull())
+ {
+ QByteArray &mutableCell = d->nameCache[name.code()];
+
+ const QString content(d->np->toLexical(name));
+ mutableCell = d->codec->fromUnicode(content.constData(),
+ content.length(),
+ &d->converterState);
+ d->device->write(mutableCell);
+ }
+ else
+ d->device->write(cell);
+}
+
+/*!
+ \internal
+ */
+void QXmlSerializer::write(const char *const chars)
+{
+ Q_D(QXmlSerializer);
+ d->device->write(chars);
+}
+
+/*!
+ \reimp
+ */
+void QXmlSerializer::startElement(const QXmlName &name)
+{
+ Q_D(QXmlSerializer);
+ Q_ASSERT(d->device);
+ Q_ASSERT(d->device->isWritable());
+ Q_ASSERT(d->codec);
+ Q_ASSERT(!name.isNull());
+
+ d->namespaces.push(QVector<QXmlName>());
+
+ if(atDocumentRoot())
+ {
+ if(d->state == BeforeDocumentElement)
+ d->state = InsideDocumentElement;
+ else if(d->state != InsideDocumentElement)
+ {
+ d->query.d->staticContext()->error(QtXmlPatterns::tr(
+ "Element %1 can't be serialized because it appears outside "
+ "the document element.").arg(formatKeyword(d->np, name)),
+ ReportContext::SENR0001,
+ d->query.d->expression().data());
+ }
+ }
+
+ startContent();
+ d->write('<');
+ write(name);
+
+ /* Ensure that the namespace URI used in the name gets outputted. */
+ namespaceBinding(name);
+
+ d->hasClosedElement.push(qMakePair(name, false));
+ d->isPreviousAtomic = false;
+}
+
+/*!
+ \reimp
+ */
+void QXmlSerializer::endElement()
+{
+ Q_D(QXmlSerializer);
+ const QPair<QXmlName, bool> e(d->hasClosedElement.pop());
+ d->namespaces.pop();
+
+ if(e.second)
+ {
+ write("</");
+ write(e.first);
+ d->write('>');
+ }
+ else
+ write("/>");
+
+ d->isPreviousAtomic = false;
+}
+
+/*!
+ \reimp
+ */
+void QXmlSerializer::attribute(const QXmlName &name,
+ const QStringRef &value)
+{
+ Q_D(QXmlSerializer);
+ Q_ASSERT(!name.isNull());
+
+ /* Ensure that the namespace URI used in the name gets outputted. */
+ {
+ /* Since attributes doesn't pick up the default namespace, a
+ * namespace declaration would cause trouble if we output it. */
+ if(name.prefix() != StandardPrefixes::empty)
+ namespaceBinding(name);
+ }
+
+ if(atDocumentRoot())
+ {
+ Q_UNUSED(d);
+ d->query.d->staticContext()->error(QtXmlPatterns::tr(
+ "Attribute %1 can't be serialized because it appears at "
+ "the top level.").arg(formatKeyword(d->np, name)),
+ ReportContext::SENR0001,
+ d->query.d->expression().data());
+ }
+ else
+ {
+ d->write(' ');
+ write(name);
+ write("=\"");
+ writeEscapedAttribute(value.toString());
+ d->write('"');
+ }
+}
+
+/*!
+ \internal
+ */
+bool QXmlSerializer::isBindingInScope(const QXmlName nb) const
+{
+ Q_D(const QXmlSerializer);
+ const int levelLen = d->namespaces.size();
+
+ if(nb.prefix() == StandardPrefixes::empty)
+ {
+ for(int lvl = levelLen - 1; lvl >= 0; --lvl)
+ {
+ const QVector<QXmlName> &scope = d->namespaces.at(lvl);
+ const int vectorLen = scope.size();
+
+ for(int s = vectorLen - 1; s >= 0; --s)
+ {
+ const QXmlName &nsb = scope.at(s);
+
+ if(nsb.prefix() == StandardPrefixes::empty)
+ return nsb.namespaceURI() == nb.namespaceURI();
+ }
+ }
+ }
+ else
+ {
+ for(int lvl = 0; lvl < levelLen; ++lvl)
+ {
+ const QVector<QXmlName> &scope = d->namespaces.at(lvl);
+ const int vectorLen = scope.size();
+
+ for(int s = 0; s < vectorLen; ++s)
+ {
+ const QXmlName &n = scope.at(s);
+ if (n.prefix() == nb.prefix() &&
+ n.namespaceURI() == nb.namespaceURI())
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+/*!
+ \reimp
+ */
+void QXmlSerializer::namespaceBinding(const QXmlName &nb)
+{
+ /*
+ * Writes out \a nb.
+ *
+ * Namespace bindings aren't looked up in a cache, because
+ * we typically receive very few.
+ */
+
+ Q_D(QXmlSerializer);
+ Q_ASSERT_X(!nb.isNull(), Q_FUNC_INFO,
+ "It makes no sense to pass a null QXmlName.");
+
+ Q_ASSERT_X((nb.namespaceURI() != StandardNamespaces::empty) ||
+ (nb.prefix() == StandardPrefixes::empty),
+ Q_FUNC_INFO,
+ "Undeclarations of prefixes aren't allowed in XML 1.0 "
+ "and aren't supposed to be received.");
+
+ if(nb.namespaceURI() == QPatternist::StandardNamespaces::StopNamespaceInheritance)
+ return;
+
+ if(isBindingInScope(nb))
+ return;
+
+ d->namespaces.top().append(nb);
+
+ if(nb.prefix() == StandardPrefixes::empty)
+ write(" xmlns");
+ else
+ {
+ write(" xmlns:");
+ write(d->np->stringForPrefix(nb.prefix()));
+ }
+
+ write("=\"");
+ writeEscapedAttribute(d->np->stringForNamespace(nb.namespaceURI()));
+ d->write('"');
+}
+
+/*!
+ \reimp
+ */
+void QXmlSerializer::comment(const QString &value)
+{
+ Q_D(QXmlSerializer);
+ Q_ASSERT_X(!value.contains(QLatin1String("--")),
+ Q_FUNC_INFO,
+ "Invalid input; it's the caller's responsibility to ensure "
+ "the input is correct.");
+
+ startContent();
+ write("<!--");
+ write(value);
+ write("-->");
+ d->isPreviousAtomic = false;
+}
+
+/*!
+ \reimp
+ */
+void QXmlSerializer::characters(const QStringRef &value)
+{
+ Q_D(QXmlSerializer);
+ d->isPreviousAtomic = false;
+ startContent();
+ writeEscaped(value.toString());
+}
+
+/*!
+ \reimp
+ */
+void QXmlSerializer::processingInstruction(const QXmlName &name,
+ const QString &value)
+{
+ Q_D(QXmlSerializer);
+ Q_ASSERT_X(!value.contains(QLatin1String("?>")),
+ Q_FUNC_INFO,
+ "Invalid input; it's the caller's responsibility to ensure "
+ "the input is correct.");
+
+ startContent();
+ write("<?");
+ write(name);
+ d->write(' ');
+ write(value);
+ write("?>");
+
+ d->isPreviousAtomic = false;
+}
+
+/*!
+ \internal
+ */
+void QXmlSerializer::item(const QPatternist::Item &outputItem)
+{
+ Q_D(QXmlSerializer);
+
+ if(outputItem.isAtomicValue())
+ {
+ if(d->isPreviousAtomic)
+ {
+ startContent();
+ d->write(' ');
+ writeEscaped(outputItem.stringValue());
+ }
+ else
+ {
+ d->isPreviousAtomic = true;
+ const QString value(outputItem.stringValue());
+
+ if(!value.isEmpty())
+ {
+ startContent();
+ writeEscaped(value);
+ }
+ }
+ }
+ else
+ {
+ startContent();
+ Q_ASSERT(outputItem.isNode());
+ sendAsNode(outputItem);
+ }
+}
+
+/*!
+ \reimp
+ */
+void QXmlSerializer::atomicValue(const QVariant &value)
+{
+ Q_UNUSED(value);
+}
+
+/*!
+ \reimp
+ */
+void QXmlSerializer::startDocument()
+{
+ Q_D(QXmlSerializer);
+ d->isPreviousAtomic = false;
+}
+
+/*!
+ \reimp
+ */
+void QXmlSerializer::endDocument()
+{
+ Q_D(QXmlSerializer);
+ d->isPreviousAtomic = false;
+}
+
+/*!
+
+ Returns a pointer to the output device. There is no corresponding
+ function to \e set the output device, because the output device must
+ be passed to the constructor. The serializer does not take ownership
+ of its IO device.
+ */
+QIODevice *QXmlSerializer::outputDevice() const
+{
+ Q_D(const QXmlSerializer);
+ return d->device;
+}
+
+/*!
+ Sets the codec the serializer will use for encoding its XML output.
+ The output codec is set to \a outputCodec. By default, the output
+ codec is set to the one for \c UTF-8. The serializer does not take
+ ownership of the codec.
+
+ \sa codec()
+
+ */
+void QXmlSerializer::setCodec(const QTextCodec *outputCodec)
+{
+ Q_D(QXmlSerializer);
+ d->codec = outputCodec;
+}
+
+/*!
+ Returns the codec being used by the serializer for encoding its
+ XML output.
+
+ \sa setCodec()
+ */
+const QTextCodec *QXmlSerializer::codec() const
+{
+ Q_D(const QXmlSerializer);
+ return d->codec;
+}
+
+/*!
+ \reimp
+ */
+void QXmlSerializer::startOfSequence()
+{
+}
+
+/*!
+ \reimp
+ */
+void QXmlSerializer::endOfSequence()
+{
+ /* If this function is changed to flush or close or something like that,
+ * take into consideration QXmlFormatter, especially
+ * QXmlFormatter::endOfSequence().
+ */
+}
+
+QT_END_NAMESPACE
diff --git a/src/xmlpatterns/api/qxmlserializer.h b/src/xmlpatterns/api/qxmlserializer.h
new file mode 100644
index 0000000000..a24b42bc0b
--- /dev/null
+++ b/src/xmlpatterns/api/qxmlserializer.h
@@ -0,0 +1,158 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtXmlPatterns 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QXMLSERIALIZER_H
+#define QXMLSERIALIZER_H
+
+#include <QtXmlPatterns/QAbstractXmlReceiver>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(XmlPatterns)
+
+class QIODevice;
+class QTextCodec;
+class QXmlQuery;
+class QXmlSerializerPrivate;
+
+class Q_XMLPATTERNS_EXPORT QXmlSerializer : public QAbstractXmlReceiver
+{
+public:
+ QXmlSerializer(const QXmlQuery &query,
+ QIODevice *outputDevice);
+
+ virtual void namespaceBinding(const QXmlName &nb);
+
+ virtual void characters(const QStringRef &value);
+ virtual void comment(const QString &value);
+
+ virtual void startElement(const QXmlName &name);
+
+ virtual void endElement();
+
+ virtual void attribute(const QXmlName &name,
+ const QStringRef &value);
+
+ virtual void processingInstruction(const QXmlName &name,
+ const QString &value);
+
+ virtual void atomicValue(const QVariant &value);
+
+ virtual void startDocument();
+ virtual void endDocument();
+ virtual void startOfSequence();
+ virtual void endOfSequence();
+
+ QIODevice *outputDevice() const;
+
+ void setCodec(const QTextCodec *codec);
+ const QTextCodec *codec() const;
+
+ /* The members below are internal, not part of the public API, and
+ * unsupported. Using them leads to undefined behavior. */
+ virtual void item(const QPatternist::Item &item);
+protected:
+ QXmlSerializer(QAbstractXmlReceiverPrivate *d);
+
+private:
+ inline bool isBindingInScope(const QXmlName nb) const;
+
+ /**
+ * Where in the document the QXmlSerializer is currently working.
+ */
+ enum State
+ {
+ /**
+ * Before the document element. This is the XML prolog where the
+ * XML declaration, and possibly comments and processing
+ * instructions are found.
+ */
+ BeforeDocumentElement,
+
+ /**
+ * This is inside the document element, at any level.
+ */
+ InsideDocumentElement
+ };
+
+ /**
+ * If the current state is neither BeforeDocumentElement or
+ * AfterDocumentElement.
+ */
+ inline bool atDocumentRoot() const;
+
+ /**
+ * Closes any open element start tag. Must be called before outputting
+ * any element content.
+ */
+ inline void startContent();
+
+ /**
+ * Escapes content intended as text nodes for elements.
+ */
+ void writeEscaped(const QString &toEscape);
+
+ /**
+ * Identical to writeEscaped(), but also escapes quotes.
+ */
+ inline void writeEscapedAttribute(const QString &toEscape);
+
+ /**
+ * Writes out @p name.
+ */
+ inline void write(const QXmlName &name);
+
+ inline void write(const char *const chars);
+ /**
+ * Encodes and writes out @p content.
+ */
+ inline void write(const QString &content);
+
+ Q_DECLARE_PRIVATE(QXmlSerializer)
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/xmlpatterns/api/qxmlserializer_p.h b/src/xmlpatterns/api/qxmlserializer_p.h
new file mode 100644
index 0000000000..0bdff216f8
--- /dev/null
+++ b/src/xmlpatterns/api/qxmlserializer_p.h
@@ -0,0 +1,130 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtXmlPatterns 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef QXMLSERIALIZER_P_H
+#define QXMLSERIALIZER_P_H
+
+#include <QtCore/QIODevice>
+#include <QtCore/QStack>
+#include <QtCore/QTextCodec>
+#include <QtXmlPatterns/QXmlQuery>
+#include <QtXmlPatterns/QXmlNamePool>
+#include <QtXmlPatterns/QXmlSerializer>
+
+#include "qnamepool_p.h"
+#include "qabstractxmlreceiver_p.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QXmlSerializerPrivate : public QAbstractXmlReceiverPrivate
+{
+public:
+ QXmlSerializerPrivate(const QXmlQuery &q,
+ QIODevice *outputDevice);
+
+ QStack<QPair<QXmlName, bool> > hasClosedElement;
+ bool isPreviousAtomic;
+ QXmlSerializer::State state;
+ const QPatternist::NamePool::Ptr np;
+
+ /**
+ * This member worries me a bit. We never use it but nevertheless
+ * it is pushed and pops linear to startElement() and endElement().
+ * An optimization would be to at least merge it with hasClosedElement,
+ * but even better to push it on demand. That is, namespaceBinding()
+ * pushes it up to the tree depth first when it is needed.
+ */
+ QStack<QVector<QXmlName> > namespaces;
+
+ QIODevice * device;
+ const QTextCodec * codec;
+ QTextCodec::ConverterState converterState;
+ /**
+ * Name cache. Since encoding QStrings are rather expensive
+ * operations to do, and we on top of that would have to do
+ * it each time a name appears, we here map names to their
+ * encoded equivalents.
+ *
+ * This means that when writing out large documents, the serialization
+ * of names after a while is reduced to a hash lookup and passing an
+ * existing byte array.
+ *
+ * We use QXmlName::Code as key as opposed to merely QName, because the
+ * prefix is of significance.
+ */
+ QHash<QXmlName::Code, QByteArray> nameCache;
+ const QXmlQuery query;
+
+ inline void write(const char c);
+
+private:
+ enum Constants
+ {
+ EstimatedTreeDepth = 10,
+
+ /**
+ * We use a high count to avoid rehashing. We can afford it since we
+ * only allocate one hash for this.
+ */
+ EstimatedNameCount = 60
+ };
+};
+
+void QXmlSerializerPrivate::write(const char c)
+{
+ device->putChar(c);
+}
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif