src/xmlpatterns/api/qabstractxmlreceiver.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtXmlPatterns module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include <QString>
       
    43 
       
    44 #include "qitem_p.h"
       
    45 
       
    46 #include "qabstractxmlreceiver_p.h"
       
    47 #include "qabstractxmlreceiver.h"
       
    48 
       
    49 QT_BEGIN_NAMESPACE
       
    50 
       
    51 /*!
       
    52   \class QAbstractXmlReceiver
       
    53   \brief The QAbstractXmlReceiver class provides a callback interface
       
    54          for transforming the output of a QXmlQuery.
       
    55   \reentrant
       
    56   \since 4.4
       
    57   \ingroup xml-tools
       
    58 
       
    59   QAbstractXmlReceiver is an abstract base class that provides
       
    60   a callback interface for receiving an \l {XQuery Sequence}
       
    61   {XQuery sequence}, usually the output of an QXmlQuery, and
       
    62   transforming that sequence into a structure of your choosing,
       
    63   usually XML. Consider the example:
       
    64 
       
    65   \snippet doc/src/snippets/code/src_xmlpatterns_api_qabstractxmlreceiver.cpp 0
       
    66 
       
    67   First it constructs a \l {QXmlQuery} {query} that gets the
       
    68   first paragraph from document \c index.html. Then it constructs
       
    69   an \l {QXmlSerializer} {XML serializer} with the \l {QXmlQuery}
       
    70   {query} and \l {QIODevice} {myOutputDevice} (Note the
       
    71   \l {QXmlSerializer} {serializer} is an \e {XML receiver},
       
    72   ie a subclass of QAbstractXmlReceiver). Finally, it
       
    73   \l {QXmlQuery::evaluateTo()} {evaluates} the
       
    74   \l {QXmlQuery} {query}, producing an ordered sequence of calls
       
    75   to the \l {QXmlSerializer} {serializer's} callback functions.
       
    76   The sequence of callbacks transforms the query output to XML
       
    77   and writes it to \l {QIODevice} {myOutputDevice}.
       
    78 
       
    79   Although the example uses \l {QXmlQuery} to produce the sequence
       
    80   of callbacks to functions in QAbstractXmlReceiver, you can call
       
    81   the callback functions directly as long as your sequence of
       
    82   calls represents a valid \l {XQuery Sequence} {XQuery sequence}.
       
    83 
       
    84   \target XQuery Sequence
       
    85   \section1 XQuery Sequences
       
    86 
       
    87   An XQuery \a sequence is an ordered collection of zero, one,
       
    88   or many \e items. Each \e item is either an \e {atomic value}
       
    89   or a \e {node}. An \e {atomic value} is a simple data value.
       
    90 
       
    91   There are six kinds of \e nodes.
       
    92 
       
    93   \list
       
    94 
       
    95   \o An \e {Element Node} represents an XML element.
       
    96 
       
    97   \o An \e {Attribute Node} represents an XML attribute.
       
    98 
       
    99   \o A \e {Document Node} represents an entire XML document.
       
   100 
       
   101   \o A \e {Text Node} represents character data (element content).
       
   102 
       
   103   \o A \e {Processing Instruction Node} represents an XML
       
   104   processing instruction, which is used in an XML document
       
   105   to tell the application reading the document to perform
       
   106   some action. A typical example is to use a processing
       
   107   instruction to tell the application to use a particular
       
   108   XSLT stylesheet to display the document.
       
   109 
       
   110   \o And a \e {Comment node} represents an XML comment.
       
   111 
       
   112   \endlist
       
   113 
       
   114   The \e sequence of \e nodes and \e {atomic values} obeys
       
   115   the following rules. Note that \e {Namespace Node} refers
       
   116   to a special \e {Attribute Node} with name \e {xmlns}.
       
   117 
       
   118   \list
       
   119 
       
   120   \o Each \e node appears in the \e sequence before its children
       
   121   and their descendants appear.
       
   122 
       
   123   \o A \e node's descendants appear in the \e sequence before
       
   124   any of its siblings appear.
       
   125 
       
   126   \o A \e {Document Node} represents an entire document. Zero or
       
   127   more \e {Document Nodes} can appear in a \e sequence, but they
       
   128   can only be top level items (i.e., a \e {Document Node} can't
       
   129   be a child of another \e node.
       
   130 
       
   131   \o \e {Namespace Nodes} immediately follow the \e {Element Node}
       
   132    with which they are associated.
       
   133 
       
   134   \o \e {Attribute Nodes} immediately follow the \e {Namespace Nodes}
       
   135    of the element with which they are associated, or...
       
   136 
       
   137    \o If there are no \e {Namespace Nodes} following an element, then
       
   138    the \e {Attribute Nodes} immediately follow the element.
       
   139 
       
   140    \o An \e {atomic value} can only appear as a top level \e item,
       
   141    i.e., it can't appear as a child of a \e node.
       
   142 
       
   143    \o \e {Processing Instruction Nodes} do not have children, and
       
   144    their parent is either a \e {Document Node} or an \e {Element
       
   145    Node}.
       
   146 
       
   147    \o \e {Comment Nodes} do not have children, and
       
   148    their parent is either a \e {Document Node} or an \e {Element
       
   149    Node}.
       
   150 
       
   151   \endlist
       
   152 
       
   153   The \e sequence of \e nodes and \e {atomic values} is sent to
       
   154   an QAbstractXmlReceiver (QXmlSerializer in
       
   155   the example above) as a sequence of calls to the receiver's
       
   156   callback functions. The mapping of callback functions to
       
   157   sequence items is as follows.
       
   158 
       
   159   \list
       
   160 
       
   161   \o startDocument() and endDocument() are called for each
       
   162   \e {Document Node} in the \e sequence. endDocument() is not
       
   163   called until all the \e {Document Node's} children have
       
   164   appeared in the \e sequence.
       
   165 
       
   166   \o startElement() and endElement() are called for each
       
   167   \e {Element Node}. endElement() is not called until all the
       
   168   \e {Element Node's} children have appeared in the \e sequence.
       
   169 
       
   170   \o attribute() is called for each \e {Attribute Node}.
       
   171 
       
   172   \o comment() is called for each \e {Comment Node}.
       
   173 
       
   174   \o characters() is called for each \e {Text Node}.
       
   175 
       
   176   \o processingInstruction() is called for each \e {Processing
       
   177   Instruction Node}.
       
   178 
       
   179   \o namespaceBinding() is called for each \e {Namespace Node}.
       
   180 
       
   181   \o atomicValue() is called for each \e {atomic value}.
       
   182 
       
   183   \endlist
       
   184 
       
   185   For a complete explanation of XQuery sequences, visit
       
   186   \l {http://www.w3.org/TR/xpath-datamodel/}{XQuery Data Model}.
       
   187 
       
   188   \sa {http://www.w3.org/TR/xpath-datamodel/}{W3C XQuery 1.0 and XPath 2.0 Data Model (XDM)}
       
   189   \sa QXmlSerializer
       
   190   \sa QXmlResultItems
       
   191  */
       
   192 
       
   193 template<const QXmlNodeModelIndex::Axis axis>
       
   194 void QAbstractXmlReceiver::sendFromAxis(const QXmlNodeModelIndex &node)
       
   195 {
       
   196     Q_ASSERT(!node.isNull());
       
   197     const QXmlNodeModelIndex::Iterator::Ptr it(node.iterate(axis));
       
   198     QXmlNodeModelIndex next(it->next());
       
   199 
       
   200     while(!next.isNull())
       
   201     {
       
   202         sendAsNode(next);
       
   203         next = it->next();
       
   204     }
       
   205 }
       
   206 
       
   207 /*!
       
   208  \internal
       
   209  */
       
   210 QAbstractXmlReceiver::QAbstractXmlReceiver(QAbstractXmlReceiverPrivate *d)
       
   211   : d_ptr(d)
       
   212 {
       
   213 }
       
   214 
       
   215 /*!
       
   216   Constructs an abstract xml receiver.
       
   217  */
       
   218 QAbstractXmlReceiver::QAbstractXmlReceiver() : d_ptr(0)
       
   219 {
       
   220 }
       
   221 
       
   222 /*!
       
   223   Destroys the xml receiver.
       
   224  */
       
   225 QAbstractXmlReceiver::~QAbstractXmlReceiver()
       
   226 {
       
   227 }
       
   228 
       
   229 /*!
       
   230   \fn void QAbstractXmlReceiver::startElement(const QXmlName &name)
       
   231 
       
   232   This callback is called when a new element node appears
       
   233   in the \l {XQuery Sequence} {sequence}. \a name is the
       
   234   valid \l {QXmlName} {name} of the node element.
       
   235  */
       
   236 
       
   237 /*
       
   238 ### Qt 5:
       
   239 
       
   240 Consider how source locations should be communicated. Maybe every signature
       
   241 should be extended by adding "qint64 line = -1, qint64 column = -1".
       
   242  */
       
   243 
       
   244 /*!
       
   245   \fn void QAbstractXmlReceiver::endElement()
       
   246 
       
   247   This callback is called when the end of an element node
       
   248   appears in the \l {XQuery Sequence} {sequence}.
       
   249 */
       
   250 
       
   251 /*!
       
   252   \fn void QAbstractXmlReceiver::attribute(const QXmlName &name,
       
   253                                            const QStringRef &value)
       
   254   This callback is called when an attribute node
       
   255   appears in the \l {XQuery Sequence} {sequence}.
       
   256   \a name is the \l {QXmlName} {attribute name} and
       
   257   the \a value string contains the attribute value.
       
   258  */
       
   259 
       
   260 /*!
       
   261   \fn void QAbstractXmlReceiver::comment(const QString &value)
       
   262 
       
   263   This callback is called when a comment node appears
       
   264   in the \l {XQuery Sequence} {sequence}. The \a value
       
   265   is the comment text, which must not contain the string
       
   266   "--".
       
   267  */
       
   268 
       
   269 /*!
       
   270   \fn void QAbstractXmlReceiver::characters(const QStringRef &value)
       
   271 
       
   272   This callback is called when a text node appears in the
       
   273   \l {XQuery Sequence} {sequence}. The \a value contains
       
   274   the text. Adjacent text nodes may not occur in the
       
   275   \l {XQuery Sequence} {sequence}, i.e., this callback must not
       
   276   be called twice in a row.
       
   277  */
       
   278 
       
   279 /*!
       
   280   \fn void QAbstractXmlReceiver::startDocument()
       
   281 
       
   282   This callback is called when a document node appears
       
   283   in the \l {XQuery Sequence} {sequence}.
       
   284  */
       
   285 
       
   286 /*
       
   287 ### Qt 5:
       
   288 
       
   289 Change
       
   290     virtual void startDocument() = 0;
       
   291 
       
   292 To:
       
   293     virtual void startDocument(const QUrl &uri) = 0;
       
   294 
       
   295 Such that it allows the document URI to be communicated. The contract would
       
   296 allow null QUrls.
       
   297 */
       
   298 
       
   299 /*!
       
   300   \fn void QAbstractXmlReceiver::endDocument()
       
   301 
       
   302   This callback is called when the end of a document node
       
   303   appears in the \l {XQuery Sequence} {sequence}.
       
   304  */
       
   305 
       
   306 /*!
       
   307   \fn void QAbstractXmlReceiver::processingInstruction(const QXmlName &target,
       
   308                                                        const QString &value)
       
   309 
       
   310   This callback is called when a processing instruction
       
   311   appears in the \l {XQuery Sequence} {sequence}.
       
   312   A processing instruction is used in an XML document
       
   313   to tell the application reading the document to
       
   314   perform some action. A typical example is to use a
       
   315   processing instruction to tell the application to use a
       
   316   particular XSLT stylesheet to process the document.
       
   317 
       
   318   \quotefile doc/src/snippets/patternist/xmlStylesheet.xq
       
   319 
       
   320   \a target is the \l {QXmlName} {name} of the processing
       
   321   instruction. Its \e prefix and \e {namespace URI} must both
       
   322   be empty. Its \e {local name} is the target. In the above
       
   323   example, the name is \e {xml-stylesheet}.
       
   324 
       
   325   The \a value specifies the action to be taken. Note that
       
   326   the \a value must not contain the string "?>". In the above
       
   327   example, the \a value is \e{type="test/xsl" href="formatter.xsl}.
       
   328 
       
   329   Generally, use of processing instructions should be avoided,
       
   330   because they are not namespace aware and in many contexts
       
   331   are stripped out anyway. Processing instructions can often
       
   332   be replaced with elements from a custom namespace.
       
   333  */
       
   334 
       
   335 /*!
       
   336   \fn void QAbstractXmlReceiver::atomicValue(const QVariant &value)
       
   337 
       
   338   This callback is called when an atomic value appears in the \l
       
   339   {XQuery Sequence} {sequence}. The \a value is a simple \l {QVariant}
       
   340   {data value}. It is guaranteed to be \l {QVariant::isValid()}
       
   341   {valid}.
       
   342  */
       
   343 
       
   344 /*!
       
   345   \fn virtual void QAbstractXmlReceiver::namespaceBinding(const QXmlName &name)
       
   346 
       
   347   This callback is called when a namespace binding is in scope of an
       
   348   element. A namespace is defined by a URI. In the \l {QXmlName}
       
   349   \a name, the value of \l {QXmlName::namespaceUri()} is that URI. The
       
   350   value of \l {QXmlName::prefix()} is the prefix that the URI is bound
       
   351   to. The local name is insignificant and can be an arbitrary value.
       
   352  */
       
   353 
       
   354 /*!
       
   355   \internal
       
   356 
       
   357    Treats \a outputItem as a node and calls the appropriate function,
       
   358    e.g., attribute() or comment(), depending on its
       
   359    QXmlNodeModelIndex::NodeKind.
       
   360 
       
   361    This is a helper function that subclasses can use to multiplex
       
   362    Nodes received via item().
       
   363  */
       
   364 void QAbstractXmlReceiver::sendAsNode(const QPatternist::Item &outputItem)
       
   365 {
       
   366     Q_ASSERT(outputItem);
       
   367     Q_ASSERT(outputItem.isNode());
       
   368     const QXmlNodeModelIndex asNode = outputItem.asNode();
       
   369 
       
   370     switch(asNode.kind())
       
   371     {
       
   372         case QXmlNodeModelIndex::Attribute:
       
   373         {
       
   374             const QString &v = outputItem.stringValue();
       
   375             attribute(asNode.name(), QStringRef(&v));
       
   376             return;
       
   377         }
       
   378         case QXmlNodeModelIndex::Element:
       
   379         {
       
   380             startElement(asNode.name());
       
   381 
       
   382             /* First the namespaces, then attributes, then the children. */
       
   383             asNode.sendNamespaces(this);
       
   384             sendFromAxis<QXmlNodeModelIndex::AxisAttribute>(asNode);
       
   385             sendFromAxis<QXmlNodeModelIndex::AxisChild>(asNode);
       
   386 
       
   387             endElement();
       
   388 
       
   389             return;
       
   390         }
       
   391         case QXmlNodeModelIndex::Text:
       
   392         {
       
   393             const QString &v = asNode.stringValue();
       
   394             characters(QStringRef(&v));
       
   395             return;
       
   396         }
       
   397         case QXmlNodeModelIndex::ProcessingInstruction:
       
   398         {
       
   399             processingInstruction(asNode.name(), outputItem.stringValue());
       
   400             return;
       
   401         }
       
   402         case QXmlNodeModelIndex::Comment:
       
   403         {
       
   404             comment(outputItem.stringValue());
       
   405             return;
       
   406         }
       
   407         case QXmlNodeModelIndex::Document:
       
   408         {
       
   409             startDocument();
       
   410             sendFromAxis<QXmlNodeModelIndex::AxisChild>(asNode);
       
   411             endDocument();
       
   412             return;
       
   413         }
       
   414         case QXmlNodeModelIndex::Namespace:
       
   415             Q_ASSERT_X(false, Q_FUNC_INFO, "Not implemented");
       
   416     }
       
   417 
       
   418     Q_ASSERT_X(false, Q_FUNC_INFO,
       
   419                QString::fromLatin1("Unknown node type: %1").arg(asNode.kind()).toUtf8().constData());
       
   420 }
       
   421 
       
   422 /*!
       
   423   \internal
       
   424 
       
   425    This function may be called instead of characters() if, and only if,
       
   426    \a value consists only of whitespace.
       
   427 
       
   428    The caller gurantees that \a value is not empty.
       
   429 
       
   430    \e Whitespace refers to a sequence of characters that are either
       
   431    spaces, tabs, or newlines, in any order. In other words, not all
       
   432    the Unicode whitespace category is considered whitespace here.
       
   433 
       
   434    However, there is no guarantee or requirement that whitespaceOnly()
       
   435    is called for text nodes containing whitespace only. characters()
       
   436    may be called just as well. This is why the default implementation
       
   437    for whitespaceOnly() calls characters().
       
   438 
       
   439    \sa characters()
       
   440  */
       
   441 void QAbstractXmlReceiver::whitespaceOnly(const QStringRef &value)
       
   442 {
       
   443     Q_ASSERT_X(value.toString().trimmed().isEmpty(), Q_FUNC_INFO,
       
   444                "The caller must guarantee only whitespace is passed. Use characters() in other cases.");
       
   445     const QString &v = value.toString();
       
   446     characters(QStringRef(&v));
       
   447 }
       
   448 
       
   449 /*!
       
   450   \internal
       
   451  */
       
   452 void QAbstractXmlReceiver::item(const QPatternist::Item &item)
       
   453 {
       
   454     if(item.isNode())
       
   455         return sendAsNode(item);
       
   456     else
       
   457         atomicValue(QPatternist::AtomicValue::toQt(item.asAtomicValue()));
       
   458 }
       
   459 
       
   460 /*!
       
   461  \fn void QAbstractXmlReceiver::startOfSequence()
       
   462 
       
   463  This callback is called once only, right before the
       
   464  \l {XQuery Sequence} {sequence} begins.
       
   465  */
       
   466 
       
   467 /*!
       
   468   \fn void QAbstractXmlReceiver::endOfSequence()
       
   469 
       
   470  This callback is called once only, right after the
       
   471  \l {XQuery Sequence} {sequence} ends.
       
   472  */
       
   473 
       
   474 QT_END_NAMESPACE
       
   475