source: trunk/src/xmlpatterns/api/qabstractxmlnodemodel.cpp@ 846

Last change on this file since 846 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

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