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
54QT_BEGIN_NAMESPACE
55
56using namespace QPatternist;
57
58typedef QExplicitlySharedDataPointer<QAbstractXmlForwardIterator<QXmlNodeModelIndex> > QXmlNodeModelIndexIteratorPointer;
59
60/**
61 * @file
62 * @short Contains the implementation of QAbstractXmlNodeModel.
63 */
64
65bool 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
279using namespace QPatternist;
280
281/*!
282 Default constructor.
283 */
284QAbstractXmlNodeModel::QAbstractXmlNodeModel() : d_ptr(0)
285{
286}
287
288/*!
289 \internal
290
291 Takes the d-pointer.
292
293 */
294QAbstractXmlNodeModel::QAbstractXmlNodeModel(QAbstractXmlNodeModelPrivate *d) : d_ptr(d)
295{
296}
297
298/*!
299 Destructor.
300 */
301QAbstractXmlNodeModel::~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
397Add the function:
398
399 virtual QSourceLocation sourceLocation(const QXmlNodeModelIndex &nodeIndex) const = 0;
400
401Such 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
445namespace QPatternist
446{
447 class MergeIterator
448 {
449 public:
450
451 inline
452 QXmlNodeModelIndexIteratorPointer
453 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
479 IteratorVector(const ItVector &in) : ListIterator<QXmlNodeModelIndexIteratorPointer, QVector<QXmlNodeModelIndexIteratorPointer> >(in)
480 {
481 }
482
483 QAbstractXmlForwardIterator<QXmlNodeModelIndexIteratorPointer>::Ptr copy() const override
484 {
485 ItVector result;
486 const int count = m_list.count();
487 result.reserve(asize: count);
488 for (int i = 0; i < count; ++i)
489 result.append(t: 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*/
501static inline QXmlNodeModelIndexIteratorPointer mergeIterators(const QXmlNodeModelIndex &node,
502 const QXmlNodeModelIndexIteratorPointer &it2)
503{
504 QVector<QXmlNodeModelIndexIteratorPointer> iterators;
505 iterators.reserve(asize: 2);
506 iterators.append(t: makeSingletonIterator(item: node));
507 iterators.append(t: it2);
508
509 return makeSequenceMappingIterator<QXmlNodeModelIndex>(mapper: &mergeIterator,
510 source: IteratorVector::Ptr(new IteratorVector(iterators)),
511 context: DynamicContext::Ptr());
512}
513
514inline QAbstractXmlForwardIterator<QXmlNodeModelIndex>::Ptr
515QAbstractXmlNodeModel::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(node: ni, it2: makeSequenceMappingIterator<QXmlNodeModelIndex>(mapper: this,
521 source: ni.iterate(axis: QXmlNodeModelIndex::AxisChild),
522 context: 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 */
578QExplicitlySharedDataPointer<QAbstractXmlForwardIterator<QXmlNodeModelIndex> >
579QAbstractXmlNodeModel::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(item: ni);
591 case QXmlNodeModelIndex::AxisParent:
592 {
593 if(kind(ni) == QXmlNodeModelIndex::Document)
594 return makeEmptyIterator<QXmlNodeModelIndex>();
595 else
596 return makeSingletonIterator(item: nextFromSimpleAxis(axis: Parent, origin: ni));
597 }
598 case QXmlNodeModelIndex::AxisNamespace:
599 return makeEmptyIterator<QXmlNodeModelIndex>();
600 case QXmlNodeModelIndex::AxisAncestor:
601 {
602 QList<QXmlNodeModelIndex> ancestors;
603 QXmlNodeModelIndex ancestor = nextFromSimpleAxis(axis: Parent, origin: ni);
604
605 while(!ancestor.isNull())
606 {
607 ancestors.append(t: ancestor);
608 ancestor = nextFromSimpleAxis(axis: Parent, origin: ancestor);
609 }
610
611 return makeListIterator(list: ancestors);
612 }
613 case QXmlNodeModelIndex::AxisAncestorOrSelf:
614 {
615 QList<QXmlNodeModelIndex> ancestors;
616 ancestors.append(t: ni);
617 QXmlNodeModelIndex ancestor = nextFromSimpleAxis(axis: Parent, origin: ni);
618
619 while(!ancestor.isNull())
620 {
621 ancestors.append(t: ancestor);
622 ancestor = nextFromSimpleAxis(axis: Parent, origin: ancestor);
623 }
624
625 return makeListIterator(list: ancestors);
626 }
627 case QXmlNodeModelIndex::AxisPrecedingSibling:
628 {
629 QList<QXmlNodeModelIndex> preceding;
630 QXmlNodeModelIndex sibling = nextFromSimpleAxis(axis: PreviousSibling, origin: ni);
631
632 while(!sibling.isNull())
633 {
634 preceding.append(t: sibling);
635 sibling = nextFromSimpleAxis(axis: PreviousSibling, origin: sibling);
636 }
637
638 return makeListIterator(list: preceding);
639 }
640 case QXmlNodeModelIndex::AxisFollowingSibling:
641 {
642 QList<QXmlNodeModelIndex> preceding;
643 QXmlNodeModelIndex sibling = nextFromSimpleAxis(axis: NextSibling, origin: ni);
644
645 while(!sibling.isNull())
646 {
647 preceding.append(t: sibling);
648 sibling = nextFromSimpleAxis(axis: NextSibling, origin: sibling);
649 }
650
651 return makeListIterator(list: preceding);
652 }
653 case QXmlNodeModelIndex::AxisChildOrTop:
654 {
655 if(nextFromSimpleAxis(axis: Parent, origin: 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(item: 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(axis: FirstChild, origin: ni);
677
678 while(!child.isNull())
679 {
680 children.append(t: child);
681 child = nextFromSimpleAxis(axis: NextSibling, origin: child);
682 }
683
684 return makeListIterator(list: children);
685 }
686 case QXmlNodeModelIndex::AxisDescendant:
687 {
688 return makeSequenceMappingIterator<QXmlNodeModelIndex>(mapper: this,
689 source: ni.iterate(axis: QXmlNodeModelIndex::AxisChild),
690 context: DynamicContext::Ptr());
691 }
692 case QXmlNodeModelIndex::AxisAttributeOrTop:
693 {
694 if(kind(ni) == QXmlNodeModelIndex::Attribute && nextFromSimpleAxis(axis: Parent, origin: ni).isNull())
695 return makeSingletonIterator(item: ni);
696
697 Q_FALLTHROUGH();
698 }
699 case QXmlNodeModelIndex::AxisAttribute:
700 return makeVectorIterator(vector: attributes(element: ni));
701 case QXmlNodeModelIndex::AxisDescendantOrSelf:
702 return mergeIterators(node: ni, it2: iterate(ni, axis: 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: axis == QXmlNodeModelIndex::AxisPreceding ? PreviousSibling : NextSibling, origin: 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(axis: Parent, origin: current);
720 }
721 else
722 {
723 current = candidate;
724 descendantIterators.append(t: iterate(ni: current, axis: QXmlNodeModelIndex::AxisDescendantOrSelf)->toReversed());
725 }
726 }
727
728 return makeSequenceMappingIterator<QXmlNodeModelIndex>(mapper: &mergeIterator,
729 source: IteratorVector::Ptr(new IteratorVector(descendantIterators)),
730 context: 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 */
859void 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(name: 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 */
929QPatternist::ItemIteratorPtr QAbstractXmlNodeModel::sequencedTypedValue(const QXmlNodeModelIndex &ni) const
930{
931 const QVariant &candidate = typedValue(n: ni);
932 if(candidate.isNull())
933 return QPatternist::CommonValues::emptyIterator;
934 else
935 return makeSingletonIterator(item: AtomicValue::toXDM(value: candidate));
936}
937
938/*!
939 \internal
940 */
941QPatternist::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 */
964QXmlName::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(n: 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 */
998bool 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(axis: QXmlNodeModelIndex::AxisAttribute));
1017 QXmlNodeModelIndex node(atts1->next());
1018
1019 const QXmlNodeModelIndex::List atts2(n2.iterate(axis: 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(n1: node, n2: (*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(axis: QXmlNodeModelIndex::AxisChild));
1043 QXmlNodeModelIndexIteratorPointer itn2(n2.iterate(axis: QXmlNodeModelIndex::AxisChild));
1044
1045 while(true)
1046 {
1047 QXmlNodeModelIndex no1(itn1->next());
1048 QXmlNodeModelIndex no2(itn2->next());
1049
1050 while(!no1.isNull() && isIgnorableInDeepEqual(n: no1))
1051 no1 = itn1->next();
1052
1053 while(!no2.isNull() && isIgnorableInDeepEqual(n: no2))
1054 no2 = itn2->next();
1055
1056 if(!no1.isNull() && !no2.isNull())
1057 {
1058 if(!isDeepEqual(n1: no1, n2: 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 */
1127QXmlItem::QXmlItem()
1128{
1129 m_node.reset();
1130}
1131
1132bool 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 */
1140QXmlItem::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 */
1151QXmlItem::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(value: 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 */
1183QXmlItem::QXmlItem(const QXmlNodeModelIndex &node) : m_node(node.m_storage)
1184{
1185}
1186
1187
1188/*!
1189 Destructor.
1190 */
1191QXmlItem::~QXmlItem()
1192{
1193 if(internalIsAtomicValue() && !m_atomicValue->ref.deref())
1194 delete m_atomicValue;
1195}
1196
1197bool 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 */
1207QXmlItem &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 */
1229bool QXmlItem::isNode() const
1230{
1231 return QPatternist::Item::fromPublic(i: *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 */
1240bool 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 */
1254QVariant QXmlItem::toAtomicValue() const
1255{
1256 if(isAtomicValue())
1257 return QPatternist::AtomicValue::toQt(value: 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 */
1270QXmlNodeModelIndex 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 */
1283bool 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 */
1364uint 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 */
1400bool 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 */
1408bool 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*/
1638void 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*/
1656QSourceLocation 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
1665QT_END_NAMESPACE
1666

source code of qtxmlpatterns/src/xmlpatterns/api/qabstractxmlnodemodel.cpp