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

Last change on this file since 243 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

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