1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the QtXmlPatterns module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39 
40 #include <QVector>
41 
42 #include "qabstractxmlnodemodel_p.h"
43 #include "qabstractxmlreceiver.h"
44 #include "qcommonvalues_p.h"
45 #include "qemptyiterator_p.h"
46 #include "qitemmappingiterator_p.h"
47 #include "qitem_p.h"
48 #include "qnamespaceresolver_p.h"
49 #include "qsequencemappingiterator_p.h"
50 #include "qsingletoniterator_p.h"
51 
52 #include "qabstractxmlnodemodel.h"
53 
54 QT_BEGIN_NAMESPACE
55 
56 using namespace QPatternist;
57 
58 typedef QExplicitlySharedDataPointer<QAbstractXmlForwardIterator<QXmlNodeModelIndex> > QXmlNodeModelIndexIteratorPointer;
59 
60 /**
61  * @file
62  * @short Contains the implementation of QAbstractXmlNodeModel.
63  */
64 
isIgnorableInDeepEqual(const QXmlNodeModelIndex & n)65 bool QAbstractXmlNodeModel::isIgnorableInDeepEqual(const QXmlNodeModelIndex &n)
66 {
67     Q_ASSERT(!n.isNull());
68     const QXmlNodeModelIndex::NodeKind nk = n.kind();
69     return nk == QXmlNodeModelIndex::ProcessingInstruction ||
70            nk == QXmlNodeModelIndex::Comment;
71 }
72 
73 
74 /*!
75   \class QAbstractXmlNodeModel
76   \brief The QAbstractXmlNodeModel class is an abstract base class for modeling non-XML data to look like XML for QXmlQuery.
77   \threadsafe
78   \since 4.4
79   \ingroup xml-tools
80   \inmodule QtXmlPatterns
81 
82   The QAbstractXmlNodeModel specifies the interface that a node model
83   must implement for that node model be accessible to the query engine
84   for processing XQuery queries.  A node model represents data as a
85   structure that can be queried as if the data were XML.
86 
87   The node model represented by a subclass of QAbstractXmlNodeModel is
88   meant to be accessed by the Qt XML Patterns query engine. If the API
89   seems a little strange in a few places, it is because the member
90   functions are called by the query engine as it evaluates an
91   XQuery. They aren't meant to be used programatically.
92 
93   \section1 Usage
94 
95   QAbstractXmlNodeModel bridges the gap between the arbitrary structure
96   of the non-XML data to be queried and the well-defined structure of
97   XML data understood by QXmlQuery.
98 
99   Consider a chemistry application that reads the file \c
100   chemistryData, which contains non-XML data that represents a
101   chemical structure composed of molecules and atoms. The application
102   will query this chemistry data with an XQuery it reads from file \c
103   queryFile. We write a custom subclass of QAbstractXmlNodeModel (\c
104   ChemistryNodeModel) that reads \c chemistryData and builds a data
105   structure, perhaps composed of objects of our own classes \c
106   molecule and \c atom.  Clearly, this data structure is not XML. Our
107   custom subclass will know how to traverse this non-XML structure and
108   present it through the \l
109   {http://www.w3.org/TR/xpath-datamodel/}{XPath Data Model interface}.
110 
111   \snippet code/src_xmlpatterns_api_qabstractxmlnodemodel.cpp 1
112 
113   The application first creates an instance of QXmlQuery and calls \l
114   {QXmlQuery::setQuery()}{setQuery()} to read \c queryFile containing
115   the XQuery we want to run. Then it creates an instance of our custom
116   node model class, \c ChemistryNodeModel, which is a subclass of
117   QAbstractXmlNodeModel. Its constructor is called with the \l
118   {QXmlNamePool} {name pool} obtained from our QXmlQuery, and with the
119   \c chemistryFile containing the structure of molecules and atoms to
120   be queried. The \l {QXmlNamePool} {name pool} is required because
121   our custom node model has the member function \l
122   {QAbstractXmlNodeModel::name()} {name()}, which returns the \l
123   {QXmlName} {name} of any node in the model. The \l {QXmlQuery}
124   {query} and the custom node model must use the same name pool for
125   constructing these \l {QXmlName} {names}. The constructor would then
126   read \c chemistryFile and build the custom node model structure.
127 
128   To connect the \c query to the custom node model, we must bind a
129   variable name used in the query to a node in the model. The variable
130   can then be used in the query as a starting node. First, an \l
131   {QXmlNodeModelIndex} {index} for the desired starting node is
132   retrieved by calling QAbstractXmlNodeModel::createIndex(). Then the
133   index is bound to a variable name, in this case \c queryRoot, by
134   passing the name and the index to QXmlQuery::bindVariable(). The
135   query can then use a variable reference \c $queryRoot to refer to
136   the starting node. Note that if the \l {QXmlQuery} {query} uses
137   multiple variable references, a call to QXmlQuery::bindVariable()
138   is required to bind each different variable name to a node in the
139   model.
140 
141   The query is executed when the application calls one of the
142   QXmlQuery evaluation functions. The application uses
143   QXmlQuery::evaluateTo(QAbstractXmlReceiver *), because it then uses
144   a \l {QXmlSerializer} {serializer} to out the query result as XML to
145   \c stdout. We could have used QXmlQuery::evaluateTo(QXmlResultItems
146   *) to get a list of result items, or
147   QXmlQuery::evaluateTo(QStringList *) if the query evaluated to a
148   sequence of \c {xs:string} values.
149 
150   During query execution, the engine iterates over the node model
151   using nextFromSimpleAxis() to get the \l {QXmlNodeModelIndex}
152   {index} of the next node to be visited. The engine can get the name
153   of a node by calling name() with the node's \l {QXmlNodeModelIndex}
154   {index}. stringValue(), baseUri(), documentUri() and kind() are also
155   called as needed with a node \l {QXmlNodeModelIndex} {index}.
156 
157   The example demonstrates the standard pattern for using a subclass
158   of QAbstractXmlNodeModel in combination with QXmlQuery to perform
159   an XQuery.
160 
161   \list 1
162 
163     \li Instantiate QXmlQuery and give it the XQuery to be run;
164 
165     \li Instantiate a subclass of QAbstractXmlNodeModel or
166     QSimpleXmlNodeModel;
167 
168     \li Retrieve a QXmlNodeModelIndex for the node in the model where
169     the QXmlQuery should start the query;
170 
171     \li Use QXmlQuery::bindVariable() to bind the QXmlNodeModelIndex
172     to \c {$variable name};
173 
174     \li Call one of the QXmlQuery evaluation functions to run the
175     query.
176 
177   \endlist
178 
179   \section1 Subclassing
180 
181   Because the \l {http://www.w3.org/TR/xpath-datamodel/}{XPath Data Model
182   interface} presented by QAbstractXmlNodeModel allows QXmlQuery to
183   operate on non-XML data as if it were XML, implementing subclasses
184   of QAbstractXmlNodeModel can involve a significant amount of
185   work. The QSimpleXmlNodeModel class is provided to simplify the
186   implementation for many common use cases.
187 
188   \section1 Thread Safety
189 
190   Because the node model can be accessed concurrently by threads in
191   the Qt XML Patterns module, subclasses of QAbstractXmlNodeModel must
192   be written to be \l{Reentrancy and Thread-Safety}{thread-safe}.
193   Classes that simplify implementing thread-safety include QReadLocker
194   and QWriteLocker.
195 
196   See the example \l{File System Example} for a demonstration.
197  */
198 
199 /*!
200   \enum QXmlNodeModelIndex::Constants
201 
202   \value ForwardAxis All forward axes include this flag.
203   \value ReverseAxis All reverse axes include this flag.
204  */
205 
206 /*!
207   \enum QXmlNodeModelIndex::DocumentOrder
208 
209   Identifies the specific node comparison operator that should be
210   used.
211 
212   \value Precedes Signifies the \c \<\< operator. Test whether the
213          first operand precedes the second in the document.
214 
215   \value Follows Signifies the \c \>\> operator. Test whether the
216                  first operand follows the second in the document.
217 
218   \value Is Signifies the \c is operator. Test whether two nodes have
219   the same node identity.
220  */
221 
222 /*!
223   \enum QAbstractXmlNodeModel::SimpleAxis
224 
225   Four axes that each contain one node only.
226 
227   \value Parent The parent of the context node
228   \value FirstChild The first child of the context node
229   \value PreviousSibling The previous child of the context node
230   \value NextSibling The next child of the context node
231 */
232 
233 /*!
234  \enum QXmlNodeModelIndex::Axis
235  \internal
236 
237    Identify the axes emanating from a node.
238 
239    The axes AxisChild, AxisDescendant, AxisAttribute, AxisSelf,
240    AxisDescendantOrSelf, AxisFollowingSibling, and AxisFollowing are
241    forward axes.
242 
243    The axes AxisParent, AxisAncestor, AxisPrecedingSibling,
244    AxisPreceding and AxisAncestorOrSelf are reverse axes.
245 
246    \sa {http://www.w3.org/TR/xquery/#axes}{XQuery 1.0: An XML Query Language, 3.2.1.1 Axes}
247 
248    \value AxisChild                The \c child axis.
249 
250    \value AxisDescendant           The \c descendant axis.
251 
252    \value AxisAttribute            The \c attribute axis. Note: There
253                                    is a node kind named \c{Attribute}.
254 
255    \value AxisSelf                 The \c self axis.
256 
257    \value AxisDescendantOrSelf     The \c descendant-or-self axis.
258 
259    \value AxisFollowingSibling     The \c following-sibling axis.
260 
261    \value AxisNamespace            The \c namespace axis. Note: Does
262                                    not exist in XQuery; deprecated in
263                                    XPath 2.0 (optionally supported);
264                                    mandatory in XPath 1.0.
265 
266    \value AxisFollowing            The \c following axis.
267 
268    \value AxisParent               The \c parent axis.
269 
270    \value AxisAncestor             The \c ancestor axis.
271 
272    \value AxisPrecedingSibling     The \c preceding-sibling axis.
273 
274    \value AxisPreceding            The \c preceding axis.
275 
276    \value AxisAncestorOrSelf       The \c ancestor-or-self axis.
277 */
278 
279 using namespace QPatternist;
280 
281 /*!
282   Default constructor.
283  */
QAbstractXmlNodeModel()284 QAbstractXmlNodeModel::QAbstractXmlNodeModel() : d_ptr(0)
285 {
286 }
287 
288 /*!
289  \internal
290 
291  Takes the d-pointer.
292 
293  */
QAbstractXmlNodeModel(QAbstractXmlNodeModelPrivate * d)294 QAbstractXmlNodeModel::QAbstractXmlNodeModel(QAbstractXmlNodeModelPrivate *d) : d_ptr(d)
295 {
296 }
297 
298 /*!
299   Destructor.
300  */
~QAbstractXmlNodeModel()301 QAbstractXmlNodeModel::~QAbstractXmlNodeModel()
302 {
303 }
304 
305 /*!
306   \typedef QAbstractXmlNodeModel::List
307 
308   A \l{QList}{list} of \l{QExplicitlySharedDataPointer} {smart
309   pointers} to instances of QAbstractXmlNodeModel.
310 
311   \sa QExplicitlySharedDataPointer
312  */
313 
314 /*!
315   \typedef QAbstractXmlNodeModel::Ptr
316 
317   A \l {QExplicitlySharedDataPointer} {smart pointer} to an
318   instance of QAbstractXmlNodeModel.
319 
320   \sa QExplicitlySharedDataPointer
321  */
322 
323 /*!
324   \fn QUrl QAbstractXmlNodeModel::baseUri(const QXmlNodeModelIndex &n) const
325 
326   Returns the base URI for the node whose index is \a n. The caller
327   guarantees that \a n is not \c null and that it belongs to a node
328   in this node model.
329 
330   The base URI of a node can be extracted using the \c fn:base-uri()
331   function. The base URI is typically used for resolving relative URIs
332   that appear in the node or its children. It is conformant to just
333   return the document URI, although that might not properly reflect
334   the underlying data.
335 
336   This function maps to the \c dm:base-uri accessor, which returns
337   a base URI according to the following:
338 
339   \list
340 
341   \li For document nodes, the base URI and the document URI are the same.
342 
343   \li For elements, the base URI is the URI appearing in the element's
344      \c xml:base attribute, if present, or it is resolved to the
345      parent element's base URI.
346 
347   \li Namespace nodes have no base URI.
348 
349   \li The base URI for a processing instruction, comment, attribute,
350   or text node is the base URI of the node's parent element.
351 
352   \endlist
353 
354   The implementation guarantees to return a valid QUrl, or a default
355   constructed QUrl. If a node has no base URI, as in the case where a
356   comment has no parent, a default constructed QUrl is returned.
357 
358    \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}
359  */
360 
361 /*!
362   \fn QUrl QAbstractXmlNodeModel::documentUri(const QXmlNodeModelIndex &n) const
363 
364   Returns the document URI of \a n. The document URI identifies the
365   resource which is the document. For example, the document could be a
366   regular file, e.g., \c{file:/}, or it could be the \c{http://} URL of
367   the location of a file. The document URI is used for resolving URIs
368   and to simply know where the document is.
369 
370   If the node model maps to a URI in a natural way, return that URI.
371   Otherwise, return the company or product URI. The document URI can
372   be any URI as long as its valid and absolute.
373 
374   The caller guarantees that \a n is not \c null and that it belongs
375   to this QAbstractXmlNodeModel.
376 
377   This function maps to the \c dm:document-uri accessor, which
378   returns a document URI according to the following:
379 
380   \list
381 
382   \li If \a n is a document node, return an absolute QUrl containing
383      the document URI, or a default constructed QUrl. The latter
384      signals that no document URI is available for the document node.
385 
386   \li For all other nodes, return a default constructed QUrl.
387 
388   \endlist
389 
390   \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}
391   \sa QUrl::isValid(), QUrl::isRelative()
392  */
393 
394 /*
395 ### Qt 5:
396 
397 Add the function:
398 
399     virtual QSourceLocation sourceLocation(const QXmlNodeModelIndex &nodeIndex) const = 0;
400 
401 Such that the data model can communicate back source locations.
402  */
403 
404 /*!
405   \fn QXmlNodeModelIndex::NodeKind QAbstractXmlNodeModel::kind(const QXmlNodeModelIndex &ni) const
406 
407   Returns a value indicating the kind of node identified by \a ni.
408   The caller guarantees that \a ni is not null and that it identifies
409   a node in this node model. This function maps to the \c
410   dm:node-kind() accessor.
411 
412   \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}
413  */
414 
415 /*!
416   \fn QXmlNodeModelIndex::DocumentOrder QAbstractXmlNodeModel::compareOrder(const QXmlNodeModelIndex &ni1, const QXmlNodeModelIndex &ni2) const
417 
418   This function returns the relative document order for the
419   nodes indexed by \a ni1 and \a ni2. It is used for the \c Is
420   operator and for sorting nodes in document order.
421 
422   The caller guarantees that \a ni1 and \a ni2 are not \c null and
423   that both identify nodes in this node model.
424 
425   If \a ni1 is identical to \a ni2, QXmlNodeModelIndex::Is is returned.
426   If \a ni1 precedes \a ni2 in document order, QXmlNodeModelIndex::Precedes
427   is returned. If \a ni1 follows \a ni2 in document order,
428   QXmlNodeModelIndex::Follows is returned.
429 
430   \sa {http://www.w3.org/TR/xpath-datamodel/#document-order}{XQuery 1.0 and XPath 2.0 Data Model (XDM), 2.4 Document Order}
431  */
432 
433 /*!
434   \fn QXmlNodeModelIndex QAbstractXmlNodeModel::root(const QXmlNodeModelIndex &n) const
435 
436   Returns the root node of the tree that contains the node whose index
437   is \a n. The caller guarantees that \a n is not \c null and that it
438   identifies a node in this node model.
439 
440   If \a n identifies a node that is a direct child of the root,
441   parent() would return the same QXmlNodeModelIndex returned by
442   this function.
443  */
444 
445 namespace QPatternist
446 {
447     class MergeIterator
448     {
449     public:
450 
451         inline
452         QXmlNodeModelIndexIteratorPointer
mapToSequence(const QXmlNodeModelIndexIteratorPointer & it,const DynamicContext::Ptr &) const453         mapToSequence(const QXmlNodeModelIndexIteratorPointer &it,
454                       const DynamicContext::Ptr &) const
455         {
456             return it;
457         }
458     };
459 
460     static const MergeIterator mergeIterator = {};
461 
462     /**
463      * One might wonder, why not use makeVectorIterator() directly on a QVector
464      * with iterators?
465      *
466      * A problem emerges QAbstractXmlForwardIterator::copy(). All "meta
467      * iterators" that contain other iterators and so forth, propagate the
468      * copy() call such that all involved iterators are copied. However, if we
469      * have a ListIterator of iterators it isn't aware of that it contains
470      * iterators. Hence, we have this class which is specialized(not in the
471      * template sense) on iterators, and hence copies them appropriately.
472      */
473     class IteratorVector : public ListIterator<QXmlNodeModelIndexIteratorPointer, QVector<QXmlNodeModelIndexIteratorPointer> >
474     {
475         typedef QVector<QXmlNodeModelIndexIteratorPointer> ItVector;
476     public:
477         typedef QAbstractXmlForwardIterator<QXmlNodeModelIndexIteratorPointer>::Ptr Ptr;
478 
IteratorVector(const ItVector & in)479         IteratorVector(const ItVector &in) : ListIterator<QXmlNodeModelIndexIteratorPointer, QVector<QXmlNodeModelIndexIteratorPointer> >(in)
480         {
481         }
482 
copy() const483         QAbstractXmlForwardIterator<QXmlNodeModelIndexIteratorPointer>::Ptr copy() const override
484         {
485             ItVector result;
486             const int count = m_list.count();
487             result.reserve(count);
488             for (int i = 0; i < count; ++i)
489                 result.append(m_list.at(i)->copy());
490 
491             return Ptr(new IteratorVector(result));
492         }
493     };
494 }
495 
496 /*!
497  \internal
498  This function is not a private member of QAbstractXmlNodeModel
499  because it would be messy to forward declare the required types.
500 */
mergeIterators(const QXmlNodeModelIndex & node,const QXmlNodeModelIndexIteratorPointer & it2)501 static inline QXmlNodeModelIndexIteratorPointer mergeIterators(const QXmlNodeModelIndex &node,
502                                                                const QXmlNodeModelIndexIteratorPointer &it2)
503 {
504     QVector<QXmlNodeModelIndexIteratorPointer> iterators;
505     iterators.reserve(2);
506     iterators.append(makeSingletonIterator(node));
507     iterators.append(it2);
508 
509     return makeSequenceMappingIterator<QXmlNodeModelIndex>(&mergeIterator,
510                                                            IteratorVector::Ptr(new IteratorVector(iterators)),
511                                                            DynamicContext::Ptr());
512 }
513 
514 inline QAbstractXmlForwardIterator<QXmlNodeModelIndex>::Ptr
mapToSequence(const QXmlNodeModelIndex & ni,const DynamicContext::Ptr &) const515 QAbstractXmlNodeModel::mapToSequence(const QXmlNodeModelIndex &ni,
516                                      const DynamicContext::Ptr &) const
517 {
518     Q_ASSERT(!ni.isNull());
519     /* Since we pass in this here, mapToSequence is used recursively. */
520     return mergeIterators(ni, makeSequenceMappingIterator<QXmlNodeModelIndex>(this,
521                                                                               ni.iterate(QXmlNodeModelIndex::AxisChild),
522                                                                               DynamicContext::Ptr()));
523 }
524 
525 /*!
526   \fn QVector<QXmlNodeModelIndex> QAbstractXmlNodeModel::attributes(const QXmlNodeModelIndex &element) const
527 
528   Returns the attributes of \a element. The caller guarantees
529   that \a element is an element in this node model.
530  */
531 
532 /*!
533   \internal
534 
535   Performs navigation, starting from \a ni, by returning an
536   QAbstractXmlForwardIterator that returns nodes the \a axis emanating
537   from \a ni.
538 
539   The implementation returns the nodes on the \a axis, without
540   duplicates and in \a axis order. This means that if \a axis is a
541   reverse axis, which is the case for the \c parent, \c ancestor, \c
542   ancestor-or-self, \c preceding, and \c preceding-sibling, the nodes
543   are delivered in reverse document order. Otherwise the nodes are
544   delivered in document order.
545 
546   The implementor guarantees that the nodes delivered for the axes are
547   consistent with the XPath Data Model. This just implies common
548   sense, e.g., The child axis for a comment node can't contain any
549   children; a document node can't be a child of an element, etc.
550   Attributes aren't considered children of an element, but are only
551   available on AxisAttribute.
552 
553   The value past in \a axis is not guaranteed based on what is used in
554   a query. Qt XML Patterns may call this function arbitrarily with any
555   value for \a axis. This is because Qt XML Patterns may rewrite queries
556   to be more efficient, using axes in different ways from the original
557   query.
558 
559   QAbstractXmlNodeModel::Axis has a good overview of the axes and what
560   they select.
561 
562   The caller guarantees that \a ni is not \c null and that it belongs
563   to this QAbstractXmlNodeModel instance.
564 
565   Implementing iterate() can involve significant work, since it
566   requires different iterators for all the axes used. In the worst
567   case, it could require writing as many QAbstractXmlForwardIterator
568   subclasses as there are axes, but the number can often be reduced
569   with clever use of lists and template classes. It is better to use
570   or subclass QSimpleXmlNodeModel, which makes it easier to write the
571   node navigation code without loss of efficiency or flexibility.
572 
573   \sa QSimpleXmlNodeModel
574   \sa QXmlNodeModelIndex::Axis
575   \sa {http://www.w3.org/TR/xquery/#axes}{XQuery 1.0: An XML Query Language, 3.2.1.1 Axes}
576   \sa {http://www.w3.org/TR/xpath-datamodel/}{W3CXQuery 1.0 and XPath 2.0 Data Model (XDM)}
577  */
578 QExplicitlySharedDataPointer<QAbstractXmlForwardIterator<QXmlNodeModelIndex> >
iterate(const QXmlNodeModelIndex & ni,QXmlNodeModelIndex::Axis axis) const579 QAbstractXmlNodeModel::iterate(const QXmlNodeModelIndex &ni,
580                                QXmlNodeModelIndex::Axis axis) const
581 {
582     /* Returns iterators that track state and calls nextFromSimpleAxis()
583      * iteratively. Typically, when sub-classing QSimpleXmlNodeModel,
584      * you don't reimplement this function, but instead implement
585      * nextFromSimpleAxis(). */
586 
587     switch(axis)
588     {
589         case QXmlNodeModelIndex::AxisSelf:
590             return makeSingletonIterator(ni);
591         case QXmlNodeModelIndex::AxisParent:
592         {
593             if(kind(ni) == QXmlNodeModelIndex::Document)
594                 return makeEmptyIterator<QXmlNodeModelIndex>();
595             else
596                 return makeSingletonIterator(nextFromSimpleAxis(Parent, ni));
597         }
598         case QXmlNodeModelIndex::AxisNamespace:
599             return makeEmptyIterator<QXmlNodeModelIndex>();
600         case QXmlNodeModelIndex::AxisAncestor:
601         {
602             QList<QXmlNodeModelIndex> ancestors;
603             QXmlNodeModelIndex ancestor = nextFromSimpleAxis(Parent, ni);
604 
605             while(!ancestor.isNull())
606             {
607                 ancestors.append(ancestor);
608                 ancestor = nextFromSimpleAxis(Parent, ancestor);
609             }
610 
611             return makeListIterator(ancestors);
612         }
613         case QXmlNodeModelIndex::AxisAncestorOrSelf:
614         {
615             QList<QXmlNodeModelIndex> ancestors;
616             ancestors.append(ni);
617             QXmlNodeModelIndex ancestor = nextFromSimpleAxis(Parent, ni);
618 
619             while(!ancestor.isNull())
620             {
621                 ancestors.append(ancestor);
622                 ancestor = nextFromSimpleAxis(Parent, ancestor);
623             }
624 
625             return makeListIterator(ancestors);
626         }
627         case QXmlNodeModelIndex::AxisPrecedingSibling:
628         {
629             QList<QXmlNodeModelIndex> preceding;
630             QXmlNodeModelIndex sibling = nextFromSimpleAxis(PreviousSibling, ni);
631 
632             while(!sibling.isNull())
633             {
634                 preceding.append(sibling);
635                 sibling = nextFromSimpleAxis(PreviousSibling, sibling);
636             }
637 
638             return makeListIterator(preceding);
639         }
640         case QXmlNodeModelIndex::AxisFollowingSibling:
641         {
642             QList<QXmlNodeModelIndex> preceding;
643             QXmlNodeModelIndex sibling = nextFromSimpleAxis(NextSibling, ni);
644 
645             while(!sibling.isNull())
646             {
647                 preceding.append(sibling);
648                 sibling = nextFromSimpleAxis(NextSibling, sibling);
649             }
650 
651             return makeListIterator(preceding);
652         }
653         case QXmlNodeModelIndex::AxisChildOrTop:
654         {
655             if(nextFromSimpleAxis(Parent, ni).isNull())
656             {
657                 switch(kind(ni))
658                 {
659                     case QXmlNodeModelIndex::Comment:
660                     case QXmlNodeModelIndex::ProcessingInstruction:
661                     case QXmlNodeModelIndex::Element:
662                     case QXmlNodeModelIndex::Text:
663                         return makeSingletonIterator(ni);
664                     case QXmlNodeModelIndex::Attribute:
665                     case QXmlNodeModelIndex::Document:
666                     case QXmlNodeModelIndex::Namespace:
667                         /* Do nothing. */;
668                 }
669             }
670 
671             Q_FALLTHROUGH();
672         }
673         case QXmlNodeModelIndex::AxisChild:
674         {
675             QList<QXmlNodeModelIndex> children;
676             QXmlNodeModelIndex child = nextFromSimpleAxis(FirstChild, ni);
677 
678             while(!child.isNull())
679             {
680                 children.append(child);
681                 child = nextFromSimpleAxis(NextSibling, child);
682             }
683 
684             return makeListIterator(children);
685         }
686         case QXmlNodeModelIndex::AxisDescendant:
687         {
688             return makeSequenceMappingIterator<QXmlNodeModelIndex>(this,
689                                                                    ni.iterate(QXmlNodeModelIndex::AxisChild),
690                                                                    DynamicContext::Ptr());
691         }
692         case QXmlNodeModelIndex::AxisAttributeOrTop:
693         {
694             if(kind(ni) == QXmlNodeModelIndex::Attribute && nextFromSimpleAxis(Parent, ni).isNull())
695                 return makeSingletonIterator(ni);
696 
697             Q_FALLTHROUGH();
698         }
699         case QXmlNodeModelIndex::AxisAttribute:
700             return makeVectorIterator(attributes(ni));
701         case QXmlNodeModelIndex::AxisDescendantOrSelf:
702             return mergeIterators(ni, iterate(ni, QXmlNodeModelIndex::AxisDescendant));
703         case QXmlNodeModelIndex::AxisFollowing:
704         case QXmlNodeModelIndex::AxisPreceding:
705         {
706             /* We walk up along the ancestors, and for each parent, we grab its preceding/following
707              * siblings, and evaluate the descendant axis. The descendant axes gets added
708              * to a list and we then merge those iterators. */
709             QVector<QXmlNodeModelIndexIteratorPointer> descendantIterators;
710 
711             QXmlNodeModelIndex current(ni);
712             while(!current.isNull())
713             {
714                 QXmlNodeModelIndex candidate(nextFromSimpleAxis(axis == QXmlNodeModelIndex::AxisPreceding ? PreviousSibling : NextSibling, current));
715                 if(candidate.isNull())
716                 {
717                     /* current is an ancestor. We don't want it, so next iteration we
718                      * will grab its preceding sibling. */
719                     current = nextFromSimpleAxis(Parent, current);
720                 }
721                 else
722                 {
723                     current = candidate;
724                     descendantIterators.append(iterate(current, QXmlNodeModelIndex::AxisDescendantOrSelf)->toReversed());
725                 }
726             }
727 
728             return makeSequenceMappingIterator<QXmlNodeModelIndex>(&mergeIterator,
729                                                                    IteratorVector::Ptr(new IteratorVector(descendantIterators)),
730                                                                    DynamicContext::Ptr());
731         }
732     }
733 
734     Q_ASSERT_X(false, Q_FUNC_INFO, "Unknown axis, internal error.");
735     return makeEmptyIterator<QXmlNodeModelIndex>();
736 }
737 
738 /*!
739   \fn QXmlNodeModelIndex QAbstractXmlNodeModel::nextFromSimpleAxis(SimpleAxis axis, const QXmlNodeModelIndex &origin) const
740 
741   When Qt XML Patterns evaluate path expressions, it emulate them through a
742   combination of calls with QSimpleXmlNodeModel::SimpleAxis values. Therefore,
743   the implementation of this function must return the node, if any, that
744   appears on the \a axis emanating from the \a origin.
745 
746   If no such node is available, a default constructed
747   QXmlNodeModelIndex is returned.
748 
749   QSimpleXmlNodeModel eliminates the need to handle redundant corner
750   cases by guaranteeing that it will never ask for:
751 
752   \list
753     \li Children or siblings for attributes.
754     \li Children for comments, processing instructions, and text nodes.
755     \li Siblings or parents for document nodes.
756   \endlist
757 
758   A typical implementation performs a \c switch on the value of \a
759   axis:
760 
761   \code
762   QXmlNodeModelIndex MyTreeModel::nextFromSimpleAxis(SimpleAxis axis, const QXmlNodeModelIndex &origin) const
763   {
764     // Convert the QXmlNodeModelIndex to a value that is specific to what we represent.
765     const MyValue value = toMyValue(ni);
766 
767     switch(axis)
768     {
769         case Parent:
770             return toNodeIndex(value.parent());
771         case FirstChild:
772         case PreviousSibling:
773         case NextSibling:
774             // and so on
775     }
776   }
777   \endcode
778 
779  */
780 
781 /*!
782   \fn QXmlNodeModelIndex QAbstractXmlNodeModel::createIndex(qint64 data) const
783 
784   Creates a node index with \a data as its internal data. \a data is
785   not constrained.
786  */
787 
788 /*!
789   \fn QXmlNodeModelIndex QAbstractXmlNodeModel::createIndex(void *pointer, qint64 additionalData) const
790 
791   Creates a node index with \a pointer and \a additionalData as
792   its internal data.
793 
794   What \a pointer and \a additionalData is, is not constrained.
795  */
796 
797 /*!
798   \fn QXmlNodeModelIndex QAbstractXmlNodeModel::createIndex(qint64 data, qint64 additionalData) const;
799   \overload
800 
801   Creates a QXmlNodeModelIndex containing \a data and \a
802   additionalData.
803  */
804 
805 /*!
806   \fn  QXmlName QAbstractXmlNodeModel::name(const QXmlNodeModelIndex &ni) const
807 
808   Returns the name of \a ni. The caller guarantees that \a ni is not
809   \c null and that it belongs to this QAbstractXmlNodeModel.
810 
811   If a node does not have a name, e.g., comment nodes, a null QXmlName
812   is returned. QXmlNames must be created with the instance of
813   QXmlQuery that is being used for evaluating queries using this
814   QAbstractXmlNodeModel.
815 
816   This function maps to the \c dm:node-name() accessor.
817 
818   If \a ni is a processing instruction, a QXmlName is returned with
819   the local name as the target name and the namespace URI and prefix
820   both empty.
821 
822   \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}
823   \sa QXmlName
824  */
825 
826 /*!
827   \fn QVector<QXmlName> QAbstractXmlNodeModel::namespaceBindings(const QXmlNodeModelIndex &n) const
828 
829   Returns the in-scope namespaces of \a n. The caller guarantees that
830   \a n is not \c null and that it belongs to this QAbstractXmlNodeModel.
831 
832   This function corresponds to the \c dm:namespace-nodes accessor.
833 
834   The returned vector of namespace declarations includes namespaces
835   of the ancestors of \a n.
836 
837   The caller guarantees that \a n is an Element that belongs to this
838   QAbstractXmlNodeModel.
839  */
840 
841 /*!
842   \internal
843   Sends the namespaces declared on \a n to \a receiver.
844 
845   As a consequence, no namespaces are sent unless this node is an
846   element and has namespaces declared.
847 
848   The caller guarantees that \a n is not \c null and that it belongs
849   to this QAbstractXmlNodeModel instance.
850 
851   Note that it is not the namespaces that are in scope on \a n, but
852   only the namespaces that are specifically declared on \a n.
853 
854   \a receiver is the receiver that this node is supposed to send its
855   namespaces to. This is guaranteed by the caller to be a valid
856   pointer.  \a n is the index of the node whose namespaces are to
857   be sent.
858  */
sendNamespaces(const QXmlNodeModelIndex & n,QAbstractXmlReceiver * const receiver) const859 void QAbstractXmlNodeModel::sendNamespaces(const QXmlNodeModelIndex &n,
860                                            QAbstractXmlReceiver *const receiver) const
861 {
862     Q_ASSERT(receiver);
863     const QVector<QXmlName> nss(namespaceBindings(n));
864 
865     /* This is by far the most common case. */
866     if(nss.isEmpty())
867         return;
868 
869     const int len = nss.size();
870     for(int i = 0; i < len; ++i)
871         receiver->namespaceBinding(nss.at(i));
872 }
873 
874 /*!
875   \fn QString QAbstractXmlNodeModel::stringValue(const QXmlNodeModelIndex &n) const
876 
877   Returns the string value for node \a n.
878 
879   The caller guarantees that \a n is not \c null and that it belong to
880   this QAbstractXmlNodeModel instance.
881 
882   This function maps to the \c dm:string-value() accessor, which the
883   specification completely specifies. Here's a summary:
884 
885   \list
886 
887   \li For processing instructions, the string value is the data
888   section(excluding any whitespace appearing between the name and the
889   data).
890 
891   \li For text nodes, the string value equals the text node.
892 
893   \li For comments, the content of the comment
894 
895   \li For elements, the concatenation of all text nodes that are
896   descendants. Note, this is not only the children, but the
897   childrens' childrens' text nodes, and so forth.
898 
899   \li For document nodes, the concatenation of all text nodes in the
900   document.
901 
902   \endlist
903 
904   \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}
905  */
906 
907 /*!
908   \fn QVariant QAbstractXmlNodeModel::typedValue(const QXmlNodeModelIndex &node) const
909 
910   Returns the typed value for node \a node.
911 
912   The typed value is an atomic value, which an element or attribute
913   contains.
914 
915   The caller guarantees that \a node is either an element or an
916   attribute. The implementor guarantees that the returned QVariant has
917   a value which is supported in XQuery. It cannot be an arbitrary
918   QVariant value.  The implementor also guarantees that stringValue()
919   returns a lexical representation of typedValue() (this is guaranteed
920   by QSimpleXmlNodeModel::stringValue()).
921 
922   If the return QVariant is a default constructed variant, it signals
923   that \a node has no typed value.
924 */
925 
926 /*!
927    \internal
928  */
sequencedTypedValue(const QXmlNodeModelIndex & ni) const929 QPatternist::ItemIteratorPtr QAbstractXmlNodeModel::sequencedTypedValue(const QXmlNodeModelIndex &ni) const
930 {
931     const QVariant &candidate = typedValue(ni);
932     if(candidate.isNull())
933         return QPatternist::CommonValues::emptyIterator;
934     else
935         return makeSingletonIterator(AtomicValue::toXDM(candidate));
936 }
937 
938 /*!
939  \internal
940  */
type(const QXmlNodeModelIndex &) const941 QPatternist::ItemTypePtr QAbstractXmlNodeModel::type(const QXmlNodeModelIndex &) const
942 {
943     Q_ASSERT_X(false, Q_FUNC_INFO,
944                "This function is internal and must not be called.");
945     return QPatternist::ItemTypePtr();
946 }
947 
948 /*!
949   \internal
950 
951   Returns the namespace URI on \a ni that corresponds to \a prefix.
952 
953   If \a prefix is StandardPrefixes::empty, the namespace URI for the
954   default namespace is returned.
955 
956   The default implementation use namespaceBindings(), in a straight
957   forward manner.
958 
959   If no namespace exists for \a prefix, NamespaceResolver::NoBinding
960   is returned.
961 
962   The caller guarantees to only call this function for element nodes.
963  */
namespaceForPrefix(const QXmlNodeModelIndex & ni,const QXmlName::PrefixCode prefix) const964 QXmlName::NamespaceCode QAbstractXmlNodeModel::namespaceForPrefix(const QXmlNodeModelIndex &ni,
965                                                                   const QXmlName::PrefixCode prefix) const
966 {
967     Q_ASSERT(kind(ni) == QXmlNodeModelIndex::Element);
968 
969     const QVector<QXmlName> nbs(namespaceBindings(ni));
970     const int len = nbs.size();
971 
972     for(int i = 0; i < len; ++i)
973     {
974         if(nbs.at(i).prefix() == prefix)
975             return nbs.at(i).namespaceURI();
976     }
977 
978     return NamespaceResolver::NoBinding;
979 }
980 
981 
982 /*!
983   \internal
984 
985   Determines whether \a ni1 is deep equal to \a ni2.
986 
987   isDeepEqual() is defined as evaluating the expression \c
988   fn:deep-equal($n1, $n2) where \c $n1 is \a ni1 and \c $n1 is \a
989   ni2. This function is associative, meaning the same value is
990   returned regardless of if isDeepEqual() is invoked with \a ni1 as
991   first argument or second. It is guaranteed that \a ni1 and \a ni2
992   are nodes, as opposed to the definition of \c fn:deep-equal().
993 
994   Returns true if \a ni1 is deep-equal to \a ni2, otherwise false
995 
996   \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}
997  */
isDeepEqual(const QXmlNodeModelIndex & n1,const QXmlNodeModelIndex & n2) const998 bool QAbstractXmlNodeModel::isDeepEqual(const QXmlNodeModelIndex &n1,
999                                         const QXmlNodeModelIndex &n2) const
1000 {
1001     Q_ASSERT(!n1.isNull());
1002     Q_ASSERT(!n2.isNull());
1003 
1004     const QXmlNodeModelIndex::NodeKind nk = n1.kind();
1005 
1006     if(nk != n2.kind())
1007         return false;
1008 
1009     if(n1.name() != n2.name())
1010         return false;
1011 
1012     switch(nk)
1013     {
1014         case QXmlNodeModelIndex::Element:
1015         {
1016             QXmlNodeModelIndexIteratorPointer atts1(n1.iterate(QXmlNodeModelIndex::AxisAttribute));
1017             QXmlNodeModelIndex node(atts1->next());
1018 
1019             const QXmlNodeModelIndex::List atts2(n2.iterate(QXmlNodeModelIndex::AxisAttribute)->toList());
1020             const QXmlNodeModelIndex::List::const_iterator end(atts2.constEnd());
1021 
1022             while(!node.isNull())
1023             {
1024                 bool equal = false;
1025                 for(QXmlNodeModelIndex::List::const_iterator it = atts2.constBegin(); it != end; ++it)
1026                 {
1027                     if(isDeepEqual(node, (*it)))
1028                         equal = true;
1029                 }
1030 
1031                 if(!equal)
1032                     return false;
1033 
1034                 node = atts1->next();
1035             }
1036 
1037             /* Fallthrough, so we check the children. */
1038             Q_FALLTHROUGH();
1039         }
1040         case QXmlNodeModelIndex::Document:
1041         {
1042             QXmlNodeModelIndexIteratorPointer itn1(n1.iterate(QXmlNodeModelIndex::AxisChild));
1043             QXmlNodeModelIndexIteratorPointer itn2(n2.iterate(QXmlNodeModelIndex::AxisChild));
1044 
1045             while(true)
1046             {
1047                 QXmlNodeModelIndex no1(itn1->next());
1048                 QXmlNodeModelIndex no2(itn2->next());
1049 
1050                 while(!no1.isNull() && isIgnorableInDeepEqual(no1))
1051                     no1 = itn1->next();
1052 
1053                 while(!no2.isNull() && isIgnorableInDeepEqual(no2))
1054                     no2 = itn2->next();
1055 
1056                 if(!no1.isNull() && !no2.isNull())
1057                 {
1058                    if(!isDeepEqual(no1, no2))
1059                        return false;
1060                 }
1061                 else
1062                     return no1.isNull() && no2.isNull();
1063             }
1064 
1065             return true;
1066         }
1067         case QXmlNodeModelIndex::Attribute:
1068         case QXmlNodeModelIndex::ProcessingInstruction:
1069         case QXmlNodeModelIndex::Text:
1070         case QXmlNodeModelIndex::Comment:
1071             return n1.stringValue() == n2.stringValue();
1072         case QXmlNodeModelIndex::Namespace:
1073         {
1074             Q_ASSERT_X(false, Q_FUNC_INFO, "Not implemented");
1075             return false;
1076         }
1077     }
1078 
1079     return false;
1080 }
1081 
1082 /*!
1083   \class QXmlItem
1084   \reentrant
1085   \since 4.4
1086   \brief The QXmlItem class contains either an XML node or an atomic value.
1087   \ingroup xml-tools
1088   \inmodule QtXmlPatterns
1089 
1090   In XQuery, all expressions evaluate to a sequence of items, where
1091   each item is either an XML node or an atomic value. The query in the
1092   following snippet evaluates to sequence of five items.
1093 
1094   \quotefile patternist/items.xq
1095 
1096   The five items are: An element, an atomic value (binary data encoded
1097   in base64), a date, a float, and an attribute.
1098 
1099   QXmlItem is the class that represents these XQuery items in the
1100   Qt XML Patterns API. A non-null instance of QXmlItem is either a node
1101   or an atomic value. Calling isNode() or isAtomicValue() tells you
1102   which it is. Atomic values are represented elsewhere in the Qt API
1103   as instances of QVariant, and an instance of QXmlItem that
1104   represents an atomic value can be converted to a QVariant by calling
1105   toAtomicValue(). A QXmlItem that wraps a node is represented
1106   elsewhere as an instance of QXmlNodeModelIndex. A node QXmlItem can
1107   be converted to a QXmlNodeModelIndex by calling toNodeModelIndex().
1108 
1109   A default constructed QXmlItem instance is neither a node nor an
1110   atomic value. It is considered null, in which case isNull() returns
1111   true.
1112 
1113   An instance of QXmlItem will be left dangling if the
1114   \l{QAbstractXmlNodeModel} {XML node model} it
1115   refers to is deleted, if it is a QXmlNodeModelIndex.
1116  */
1117 
1118 /*!
1119   \typedef QXmlItem::Iterator
1120   A QAbstractXmlForwardIterator over QXmlItem.
1121  */
1122 
1123 /*!
1124   Constructs a null QXmlItem that is neither a node nor an atomic
1125   value. isNull() returns true for a default constructed instance.
1126  */
QXmlItem()1127 QXmlItem::QXmlItem()
1128 {
1129     m_node.reset();
1130 }
1131 
internalIsAtomicValue() const1132 bool QXmlItem::internalIsAtomicValue() const
1133 {
1134     return m_node.model == reinterpret_cast<QAbstractXmlNodeModel *>(~0);
1135 }
1136 
1137 /*!
1138   The copy constructor constructs a copy of \a other.
1139  */
QXmlItem(const QXmlItem & other)1140 QXmlItem::QXmlItem(const QXmlItem &other) : m_node(other.m_node)
1141 {
1142     if(internalIsAtomicValue())
1143         m_atomicValue->ref.ref();
1144 }
1145 
1146 /*!
1147   Constructs an atomic value QXmlItem with \a atomicValue.
1148 
1149   \sa isAtomicValue()
1150  */
QXmlItem(const QVariant & atomicValue)1151 QXmlItem::QXmlItem(const QVariant &atomicValue)
1152 {
1153     m_node.reset();
1154     if(atomicValue.isNull())
1155     {
1156         /* Then we behave just like the default constructor. */
1157         return;
1158     }
1159 
1160     /*
1161       We can't assign directly to m_atomicValue, because the
1162       temporary will self-destruct before we've ref'd it.
1163     */
1164     const QPatternist::Item temp(QPatternist::AtomicValue::toXDM(atomicValue));
1165 
1166     if(temp)
1167     {
1168         temp.asAtomicValue()->ref.ref();
1169         m_node.model = reinterpret_cast<const QAbstractXmlNodeModel *>(~0);
1170         m_atomicValue = temp.asAtomicValue();
1171     }
1172     else
1173     {
1174         m_atomicValue = 0;
1175     }
1176 }
1177 
1178 /*!
1179   Constructs a node QXmlItem that is a copy of \a node.
1180 
1181   \sa isNode()
1182  */
QXmlItem(const QXmlNodeModelIndex & node)1183 QXmlItem::QXmlItem(const QXmlNodeModelIndex &node) : m_node(node.m_storage)
1184 {
1185 }
1186 
1187 
1188 /*!
1189   Destructor.
1190  */
~QXmlItem()1191 QXmlItem::~QXmlItem()
1192 {
1193     if(internalIsAtomicValue() && !m_atomicValue->ref.deref())
1194         delete m_atomicValue;
1195 }
1196 
operator !=(const NodeIndexStorage & other) const1197 bool QPatternist::NodeIndexStorage::operator!=(const NodeIndexStorage &other) const
1198 {
1199     return data != other.data
1200            || additionalData != other.additionalData
1201            || model != other.model;
1202 }
1203 
1204 /*!
1205   Assigns \a other to \c this.
1206  */
operator =(const QXmlItem & other)1207 QXmlItem &QXmlItem::operator=(const QXmlItem &other)
1208 {
1209     if(m_node != other.m_node)
1210     {
1211         if(internalIsAtomicValue() && !m_atomicValue->ref.deref())
1212             delete m_atomicValue;
1213 
1214         m_node = other.m_node;
1215 
1216         if(internalIsAtomicValue())
1217             m_atomicValue->ref.ref();
1218     }
1219 
1220     return *this;
1221 }
1222 
1223 /*!
1224   Returns true if this item is a Node. Returns false if it
1225   is an atomic value or null.
1226 
1227   \sa isNull(), isAtomicValue()
1228  */
isNode() const1229 bool QXmlItem::isNode() const
1230 {
1231     return QPatternist::Item::fromPublic(*this).isNode();
1232 }
1233 
1234 /*!
1235   Returns true if this item is an atomic value. Returns false
1236   if it is a node or null.
1237 
1238   \sa isNull(), isNode()
1239  */
isAtomicValue() const1240 bool QXmlItem::isAtomicValue() const
1241 {
1242     return internalIsAtomicValue();
1243 }
1244 
1245 /*!
1246   If this QXmlItem represents an atomic value, it is converted
1247   to an appropriate QVariant and returned. If this QXmlItem is
1248   not an atomic value, the return value is a default constructed
1249   QVariant. You can call isAtomicValue() to test whether the
1250   item is an atomic value.
1251 
1252  \sa isAtomicValue()
1253  */
toAtomicValue() const1254 QVariant QXmlItem::toAtomicValue() const
1255 {
1256     if(isAtomicValue())
1257         return QPatternist::AtomicValue::toQt(m_atomicValue);
1258     else
1259         return QVariant();
1260 }
1261 
1262 /*!
1263   If this QXmlItem represents a node, it returns the item as a
1264   QXmlNodeModelIndex. If this QXmlItem is not a node, the return
1265   value is undefined. You can call isNode() to test whether the
1266   item is a node.
1267 
1268  \sa isNode()
1269  */
toNodeModelIndex() const1270 QXmlNodeModelIndex QXmlItem::toNodeModelIndex() const
1271 {
1272     if(isNode())
1273         return reinterpret_cast<const QXmlNodeModelIndex &>(m_node);
1274     else
1275         return QXmlNodeModelIndex();
1276 }
1277 
1278 /*!
1279   Returns true if this QXmlItem is neither a node nor an
1280   atomic value. Default constructed instances of QXmlItem
1281   are null.
1282  */
isNull() const1283 bool QXmlItem::isNull() const
1284 {
1285     return !m_node.model;
1286 }
1287 
1288 /*!
1289   \class QXmlNodeModelIndex
1290   \brief The QXmlNodeModelIndex class identifies a node in an XML node model subclassed from QAbstractXmlNodeModel.
1291   \reentrant
1292   \since 4.4
1293   \ingroup xml-tools
1294   \inmodule QtXmlPatterns
1295 
1296   QXmlNodeModelIndex is an index into an \l{QAbstractXmlNodeModel}
1297   {XML node model}. It contains:
1298 
1299   \list
1300     \li A pointer to an \l{QAbstractXmlNodeModel} {XML node model},
1301     which is returned by model(), and
1302     \li Some data, which is returned by data(), internalPointer(),
1303     and additionalData().
1304   \endlist
1305 
1306   Because QXmlNodeModelIndex is intentionally a simple class, it
1307   doesn't have member functions for accessing the properties of
1308   nodes. For example, it doesn't have functions for getting a
1309   node's name or its list of attributes or child nodes. If you find
1310   that you need to retrieve this kind of information from your
1311   query results, there are two ways to proceed.
1312 
1313   \list
1314 
1315   \li Send the output of your XQuery to an \l{QAbstractXmlReceiver}
1316   {XML receiver}, or
1317 
1318   \li Let your XQuery do all the work to produce the desired result.
1319 
1320   \endlist
1321 
1322   The second case is explained by example. Suppose you want to
1323   populate a list widget with the values of certain attributes from a
1324   set of result elements. You could write an XQuery to return the set
1325   of elements, and then you would write the code to iterate over the
1326   result elements, get their attributes, and extract the desired
1327   string values. But the simpler way is to just augment your XQuery to
1328   finding the desired attribute values. Then all you have to do is
1329   evaluate the XQuery using the version of QXmlQuery::evaluateTo()
1330   that populates a QStringList, which you can send directly to your
1331   widget.
1332 
1333   QXmlNodeModelIndex doesn't impose any restrictions on the \c data
1334   value an QXmlNodeModelIndex should contain. The meaning of the data
1335   left to the associated \l {QAbstractXmlNodeModel} {node model}.
1336   Because QXmlNodeModelIndex depends on a particular subclass of
1337   QAbstractXmlNodeModel for its existence, the only way you can create
1338   an instance of QXmlNodeModelIndex is by asking the node model to
1339   create one for you with QAbstractXmlNodeModel::createIndex(). Since
1340   that function is protected, it is usually a good idea to write a
1341   public function that creates a QXmlNodeModelIndex from arguments that
1342   are appropriate for your particular node model.
1343 
1344   A default constructed node index is said to be null, i.e., isNull()
1345   returns true.
1346 
1347   QXmlNodeModelIndex and QAbstractXmlNodeModel follow the same design
1348   pattern used for QModelIndex and QAbstractItemModel.
1349  */
1350 
1351 /*!
1352   \since 4.4
1353   \relates QHash
1354 
1355   Computes a hash key from the QXmlNodeModelIndex \a index, and
1356   returns it. This function would be used by QHash if you wanted
1357   to build a hash table for instances of QXmlNodeModelIndex.
1358 
1359   The hash is computed on QXmlNodeModelIndex::data(),
1360   QXmlNodeModelIndex::additionalData(), and
1361   QXmlNodeModelIndex::model(). This means the hash key can be used for
1362   node indexes from different node models.
1363  */
qHash(const QXmlNodeModelIndex & index)1364 uint qHash(const QXmlNodeModelIndex &index)
1365 {
1366     return uint(index.data() + index.additionalData() + quintptr(index.model()));
1367 }
1368 
1369 /*!
1370   \enum QXmlNodeModelIndex::NodeKind
1371 
1372   Identifies a kind of node.
1373 
1374   \value Attribute Identifies an attribute node
1375   \value Text Identifies a text node
1376   \value Comment Identifies a comment node
1377   \value Document Identifies a document node
1378   \value Element Identifies an element node
1379   \value Namespace Identifies a namespace node
1380   \value ProcessingInstruction Identifies a processing instruction.
1381 
1382   Note that the optional XML declaration at very beginning of the XML
1383   document is not a processing instruction
1384 
1385   \sa QAbstractXmlNodeModel::kind()
1386 */
1387 
1388 /*!
1389  \typedef QXmlNodeModelIndex::List
1390 
1391  Typedef for QList<QXmlNodeModelIndex>.
1392  */
1393 
1394 /*!
1395   Returns true if this node is the same as \a other. This operator
1396   does not compare values, children, or names of nodes. It compares
1397   node identities, i.e., whether two nodes are from the same document
1398   and are found at the exact same place.
1399  */
operator ==(const QXmlNodeModelIndex & other) const1400 bool QXmlNodeModelIndex::operator==(const QXmlNodeModelIndex &other) const
1401 {
1402     return !(m_storage != other.m_storage);
1403 }
1404 
1405 /*!
1406   Returns true if \a other is the same node as this.
1407  */
operator !=(const QXmlNodeModelIndex & other) const1408 bool QXmlNodeModelIndex::operator!=(const QXmlNodeModelIndex &other) const
1409 {
1410     return !(operator==(other));
1411 }
1412 
1413 /*!
1414  \fn QXmlNodeModelIndex::QXmlNodeModelIndex()
1415 
1416  Default constructor. Creates an item that is \c null.
1417 
1418  \sa isNull()
1419  */
1420 
1421 /*!
1422  \fn QXmlNodeModelIndex::QXmlNodeModelIndex(const QXmlNodeModelIndex &other)
1423 
1424  Standard copy constructor. Creates a QXmlNodeModelIndex instance that
1425  is a copy of \a other.
1426  */
1427 
1428 /*!
1429  \fn bool QXmlNodeModelIndex::isNull() const
1430 
1431  Returns true if this QXmlNodeModelIndex is a default constructed
1432  value, otherwise false.
1433 
1434  A null QXmlNodeModelIndex doesn't represent any node and cannot
1435  be used in conjunction with QAbstractXmlNodeModel.
1436  */
1437 
1438 /*!
1439  \fn const QAbstractXmlNodeModel *QXmlNodeModelIndex::model() const
1440 
1441  Returns the QAbstractXmlNodeModel that this node index refers to.
1442  QXmlNodeModelIndex does not own QAbstractXmlNodeModel and does not
1443  keep track of its lifetime, so this pointer will dangle if the
1444  QAbstractXmlNodeModel is deallocated first.
1445 
1446  There is no setter for the node model because instances of
1447  QXmlNodeModelIndex instances are only created with
1448  QAbstractXmlNodeModel::createIndex().
1449 */
1450 
1451 /*!
1452  \fn qint64 QXmlNodeModelIndex::data() const
1453 
1454  Returns the first data value. The node index holds two data values.
1455  additionalData() returns the second one.
1456 
1457  \sa additionalData()
1458 */
1459 
1460 /*!
1461  \fn void *QXmlNodeModelIndex::internalPointer() const
1462 
1463  Returns the first data value as a void* pointer.
1464 
1465  \sa additionalData()
1466 */
1467 
1468 /*!
1469  \fn qint64 QXmlNodeModelIndex::additionalData() const
1470 
1471  Returns the second data value. The node index holds two data values.
1472  data() returns the first one.
1473 
1474  \sa data()
1475 */
1476 
1477 /*!
1478  \fn void QXmlNodeModelIndex::reset()
1479  \internal
1480 
1481  Resets this QXmlNodeModelIndex to be null. It is equivalent to
1482  writing:
1483 
1484  \snippet code/src_xmlpatterns_api_qabstractxmlnodemodel.cpp 0
1485  */
1486 
1487 /*!
1488  \fn QXmlName QXmlNodeModelIndex::name() const
1489  \internal
1490 */
1491 
1492 /*!
1493  \typedef QXmlNodeModelIndex::Iterator
1494  \internal
1495 
1496  Typedef for QAbstractXmlForwardIterator<QXmlNodeModelIndex>.
1497  */
1498 /*!
1499  \fn QXmlNodeModelIndex QXmlNodeModelIndex::root() const
1500  \internal
1501 */
1502 
1503 /*!
1504  \fn QExplicitlySharedDataPointer<QAbstractXmlForwardIterator<QXmlNodeModelIndex> > QXmlNodeModelIndex::iterate(const Axis axis) const
1505  \internal
1506 */
1507 
1508 /*!
1509  \fn QExplicitlySharedDataPointer<QAbstractXmlForwardIterator<QPatternist::Item> > QXmlNodeModelIndex::sequencedTypedValue() const
1510  \internal
1511 */
1512 
1513 /*!
1514  \fn QUrl QXmlNodeModelIndex::documentUri() const
1515  \internal
1516 */
1517 
1518 /*!
1519  \fn QUrl QXmlNodeModelIndex::baseUri() const
1520  \internal
1521 */
1522 
1523 /*!
1524  \fn NodeKind QXmlNodeModelIndex::kind() const
1525  \internal
1526 */
1527 
1528 /*!
1529  \fn bool QXmlNodeModelIndex::isDeepEqual(const QXmlNodeModelIndex &other) const
1530  \internal
1531 */
1532 
1533 /*!
1534  \fn DocumentOrder QXmlNodeModelIndex::compareOrder(const QXmlNodeModelIndex &other) const
1535  \internal
1536 */
1537 
1538 /*!
1539  \fn void QXmlNodeModelIndex::sendNamespaces(QAbstractXmlReceiver *const receiver) const
1540  \internal
1541 */
1542 
1543 /*!
1544  \fn QVector<QXmlName> QXmlNodeModelIndex::namespaceBindings() const
1545  \internal
1546 */
1547 
1548 /*!
1549  \fn QXmlNodeModelIndex QAbstractXmlNodeModel::elementById(const QXmlName &id) const
1550 
1551  Returns the index of the element identified as \a id. XQuery's \c
1552  id() function calls this function.
1553 
1554  The node index returned will be the element node whose value is of
1555  type \c ID and equals \a id, or it will be the element node that has
1556  an attribute whose typed value is of type \c ID and equals \a id. If
1557  there is no such element, a default constructed QXmlNodeModelIndex
1558  instance is returned. The implementor guarantees that if the returned
1559  node index is not null, it identifies an element.
1560 
1561  It is not sufficient for an attribute or element to merely be called
1562  \c id. Its value type must also be \c ID. However, the reserved name
1563  \c xml:id is sufficient.
1564 
1565  In \a id, the \c{namespace URI} and the \c{prefix} are undefined, and
1566  the \c{local name} is the ID that should be looked up.
1567 
1568  \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}
1569  */
1570 
1571 /*!
1572  \fn QVector<QXmlNodeModelIndex> QAbstractXmlNodeModel::nodesByIdref(const QXmlName &idref) const
1573 
1574  Returns the elements and/or attributes that have an \c IDREF value
1575  equal to \a idref. XQuery's \c idref() function calls this function.
1576 
1577  The implementor guarantees that the nodes identified by the returned
1578  indexes are elements or attributes.
1579 
1580  It is not sufficient for an attribute or element to merely be called
1581  \c idref. It must also be of type \c IDREF. Elements must be typed as
1582  \c xs:IDREF or \c xs:IDREFS, or, in the case of attributes, as \c
1583  IDREF or \c IDREFS in the schema.
1584 
1585  In \a idref, the \c{namespace URI} and the \c{prefix} are undefined,
1586  and the \c{local name} is the ID that should be looked up.
1587 
1588  \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}
1589  */
1590 
1591 /*!
1592  \fn QXmlName::NamespaceCode QXmlNodeModelIndex::namespaceForPrefix(const QXmlName::PrefixCode prefix) const
1593  \internal
1594 */
1595 
1596 /*!
1597  \fn QString QXmlNodeModelIndex::stringValue() const
1598  \internal
1599 */
1600 
1601 /*!
1602  \fn QPatternist::ItemTypePtr QXmlNodeModelIndex::type() const
1603  \internal
1604 */
1605 
1606 /*!
1607  \fn bool QXmlNodeModelIndex::is(const QXmlNodeModelIndex &other) const
1608  \internal
1609 */
1610 
1611 /*!
1612  \enum QAbstractXmlNodeModel::NodeCopySetting
1613  \internal
1614 
1615  Controls how nodes are copied with copyNodeTo.
1616 
1617  \value InheritNamespaces Copies the node with the \c copy-namespaces
1618         setting being \c inherit. If not set, \c no-inherit is assumed.
1619  \value PreserveNamespaces Copies the node with the \c copy-namespaces
1620         settings being \c preserve. If not set, \c no-preserve is assumed.
1621  */
1622 
1623 /*!
1624  \typedef QAbstractXmlNodeModel::NodeCopySettings
1625  \internal
1626  */
1627 
1628 /*!
1629  \internal
1630 
1631  Copies node \a node to \a receiver, steered by \a copySettings.
1632 
1633  The caller guarantees that \a node is not \c null, and that is
1634  belongs to this QAbstractXmlNodeModel instance.
1635 
1636  The caller guarantees that \a receiver is not \c null.
1637 */
copyNodeTo(const QXmlNodeModelIndex & node,QAbstractXmlReceiver * const receiver,const NodeCopySettings & copySettings) const1638 void QAbstractXmlNodeModel::copyNodeTo(const QXmlNodeModelIndex &node,
1639                                        QAbstractXmlReceiver *const receiver,
1640                                        const NodeCopySettings &copySettings) const
1641 {
1642     Q_UNUSED(node);
1643     Q_UNUSED(receiver);
1644     Q_UNUSED(copySettings);
1645     Q_ASSERT_X(false, Q_FUNC_INFO,
1646                "This function is not expected to be called.");
1647 }
1648 
1649 /*!
1650     Returns the source location for the object with the given \a index
1651     or a default constructed QSourceLocation in case no location
1652     information is available.
1653 
1654     \since 4.6
1655 */
sourceLocation(const QXmlNodeModelIndex & index) const1656 QSourceLocation QAbstractXmlNodeModel::sourceLocation(const QXmlNodeModelIndex &index) const
1657 {
1658     // TODO: make this method virtual in Qt5 to allow source location support in custom models
1659     if (d_ptr)
1660         return d_ptr->sourceLocation(index);
1661     else
1662         return QSourceLocation();
1663 }
1664 
1665 QT_END_NAMESPACE
1666