source: trunk/src/xmlpatterns/api/qxmlquery.cpp@ 1036

Last change on this file since 1036 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: 38.9 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 <QtCore/QBuffer>
43#include <QtCore/QStringList>
44#include <QtXmlPatterns/QXmlFormatter>
45
46#include "qacceltreeresourceloader_p.h"
47#include "qcommonvalues_p.h"
48#include "qxmlresultitems.h"
49#include "qxmlresultitems_p.h"
50#include "qxmlserializer.h"
51#include "qxpathhelper_p.h"
52
53#include "qxmlquery.h"
54#include "qxmlquery_p.h"
55
56QT_BEGIN_NAMESPACE
57
58/*!
59 \class QXmlQuery
60
61 \brief The QXmlQuery class performs XQueries on XML data, or on non-XML data modeled to look like XML.
62
63 \reentrant
64 \since 4.4
65 \ingroup xml-tools
66
67 The QXmlQuery class compiles and executes queries written in the
68 \l {http://www.w3.org/TR/xquery/}{XQuery language}. QXmlQuery is
69 typically used to query XML data, but it can also query non-XML
70 data that has been modeled to look like XML.
71
72 Using QXmlQuery to query XML data, as in the snippet below, is
73 simple because it can use the built-in \l {QAbstractXmlNodeModel}
74 {XML data model} as its delegate to the underlying query engine for
75 traversing the data. The built-in data model is specified in \l
76 {http://www.w3.org/TR/xpath-datamodel/} {XQuery 1.0 and XPath 2.0
77 Data Model}.
78
79 \snippet doc/src/snippets/code/src_xmlpatterns_api_qabstractxmlreceiver.cpp 0
80
81 The example uses QXmlQuery to match the first paragraph of an XML
82 document and then \l {QXmlSerializer} {output the result} to a
83 device as XML.
84
85 Using QXmlQuery to query \e {non-XML} data requires writing a
86 subclass of QAbstractXmlNodeModel to use as a replacement for the
87 built-in XML data model. The custom data model will be able to
88 traverse the non-XML data as required by the QAbstractXmlNodeModel
89 interface. An instance of this custom data model then becomes the
90 delegate used by the query engine to traverse the non-XML data. For
91 an example of how to use QXmlQuery to query non-XML data, see the
92 documentation for QAbstractXmlNodeModel.
93
94 \section1 Running XQueries
95
96 To run a query set up with QXmlQuery, call one of the evaluation
97 functions.
98
99 \list
100
101 \o evaluateTo(QAbstractXmlReceiver *) is called with a pointer to an
102 XML \l {QAbstractXmlReceiver} {receiver}, which receives the query
103 results as a sequence of callbacks. The receiver callback class is
104 like the callback class used for translating the output of a SAX
105 parser. QXmlSerializer, for example, is a receiver callback class
106 for translating the sequence of callbacks for output as unformatted
107 XML text.
108
109 \endlist
110
111 \list
112
113 \o evaluateTo(QXmlResultItems *) is called with a pointer to an
114 iterator for an empty sequence of query \l {QXmlResultItems} {result
115 items}. The Java-like iterator allows the query results to be
116 accessed sequentially.
117
118 \endlist
119
120 \list
121
122 \o evaluateTo(QStringList *) is like evaluateTo(QXmlResultItems *),
123 but the query must evaluate to a sequence of strings.
124
125 \endlist
126
127 \section1 Running XPath Expressions
128
129 The XPath language is a subset of the XQuery language, so
130 running an XPath expression is the same as running an XQuery
131 query. Pass the XPath expression to QXmlQuery using setQuery().
132
133 \section1 Running XSLT stylesheets
134
135 Running an XSLT stylesheet is like running an XQuery, except that
136 when you construct your QXmlQuery, you must pass QXmlQuery::XSLT20
137 to tell QXmlQuery to interpret whatever it gets from setQuery() as
138 an XSLT stylesheet instead of as an XQuery. You must also set the
139 input document by calling setFocus().
140
141 \snippet doc/src/snippets/code/src_xmlpatterns_api_qxmlquery.cpp 7
142
143 \note Currently, setFocus() must be called \e before setQuery() when
144 using XSLT.
145
146 Another way to run an XSLT stylesheet is to use the \c xmlpatterns
147 command line utility.
148
149 \code
150 xmlpatterns myStylesheet.xsl myInput.xml
151 \endcode
152
153 \note For the current release, XSLT support should be considered
154 experimental. See section \l{XQuery#XSLT 2.0} {XSLT conformance} for
155 details.
156
157 Stylesheet parameters are bound using bindVariable().
158
159 \section1 Binding A Query To A Starting Node
160
161 When a query is run on XML data, as in the snippet above, the
162 \c{doc()} function returns the node in the built-in data model where
163 the query evaluation will begin. But when a query is run on a custom
164 node model containing non-XML data, one of the bindVariable()
165 functions must be called to bind a variable name to a starting node
166 in the custom model. A $variable reference is used in the XQuery
167 text to access the starting node in the custom model. It is not
168 necessary to declare the variable name external in the query. See
169 the example in the documentation for QAbstractXmlNodeModel.
170
171 \section1 Reentrancy and Thread-Safety
172
173 QXmlQuery is reentrant but not thread-safe. It is safe to use the
174 QxmlQuery copy constructor to create a copy of a query and run the
175 same query multiple times. Behind the scenes, QXmlQuery will reuse
176 resources such as opened files and compiled queries to the extent
177 possible. But it is not safe to use the same instance of QXmlQuery
178 in multiple threads.
179
180 \section1 Error Handling
181
182 Errors can occur during query evaluation. Examples include type
183 errors and file loading errors. When an error occurs:
184
185 \list
186
187 \o The error message is sent to the messageHandler().
188
189 \o QXmlResultItems::hasError() will return \c{true}, or
190 evaluateTo() will return \c{false};
191
192 \o The results of the evaluation are undefined.
193
194 \endlist
195
196 \section1 Resource Management
197
198 When a query runs, it parses documents, allocating internal data
199 structures to hold them, and it may load other resources over the
200 network. It reuses these allocated resources when possible, to
201 avoid having to reload and reparse them.
202
203 When setQuery() is called, the query text is compiled into an
204 internal data structure and optimized. The optimized form can
205 then be reused for multiple evaluations of the query. Since the
206 compile-and-optimize process can be expensive, repeating it for
207 the same query should be avoided by using a separate instance of
208 QXmlQuery for each query text.
209
210 Once a document has been parsed, its internal representation is
211 maintained in the QXmlQuery instance and shared among multiple
212 QXmlQuery instances.
213
214 An instance of QCoreApplication must exist before QXmlQuery can be
215 used.
216
217 \section1 Event Handling
218
219 When QXmlQuery accesses resources (e.g., calling \c fn:doc() to load a file,
220 or accessing a device via a bound variable), the event loop is used, which
221 means events will be processed. To avoid processing events when QXmlQuery
222 accesses resources, create your QXmlQuery instance in a separate thread.
223 */
224
225/*!
226 \enum QXmlQuery::QueryLanguage
227 \since 4.5
228
229 Specifies whether you want QXmlQuery to interpret the input to
230 setQuery() as an XQuery or as an XSLT stylesheet.
231
232 \value XQuery10 XQuery 1.0.
233 \value XSLT20 XSLT 2.0
234 \omitvalue XmlSchema11IdentityConstraintSelector The selector, the restricted
235 XPath pattern found in W3C XML Schema 1.1 for uniqueness
236 contraints. Apart from restricting the syntax, the type check stage
237 for the expression assumes a sequence of nodes to be the focus.
238 \omitvalue XmlSchema11IdentityConstraintField The field, the restricted
239 XPath pattern found in W3C XML Schema 1.1 for uniqueness
240 contraints. Apart from restricting the syntax, the type check stage
241 for the expression assumes a sequence of nodes to be the focus.
242 \omitvalue XPath20 Signifies XPath 2.0. Has no effect in the public API, it's
243 used internally. As With XmlSchema11IdentityConstraintSelector and
244 XmlSchema11IdentityConstraintField, the type check stage
245 for the expression assumes a sequence of nodes to be the focus.
246
247 \sa setQuery()
248 */
249
250// ### Qt5: Merge constructor overloads
251/*!
252 Constructs an invalid, empty query that cannot be used until
253 setQuery() is called.
254
255 \note This constructor must not be used if you intend to use
256 this QXmlQuery to process XSL-T stylesheets. The other constructor
257 must be used in that case.
258 */
259QXmlQuery::QXmlQuery() : d(new QXmlQueryPrivate())
260{
261}
262
263/*!
264 Constructs a QXmlQuery that is a copy of \a other. The new
265 instance will share resources with the existing query
266 to the extent possible.
267 */
268QXmlQuery::QXmlQuery(const QXmlQuery &other) : d(new QXmlQueryPrivate(*other.d))
269{
270 /* First we have invoked QXmlQueryPrivate's synthesized copy constructor.
271 * Keep this section in sync with QXmlQuery::operator=(). */
272 d->detach();
273}
274
275/*!
276 Constructs a query that will use \a np as its name pool. The query
277 cannot be evaluated until setQuery() has been called.
278 */
279QXmlQuery::QXmlQuery(const QXmlNamePool &np) : d(new QXmlQueryPrivate(np))
280{
281}
282
283/*!
284
285 Constructs a query that will be used to run Xqueries or XSL-T
286 stylesheets, depending on the value of \a queryLanguage. It will use
287 \a np as its name pool.
288
289 \note If your QXmlQuery will process XSL-T stylesheets, this
290 constructor must be used. The default constructor can only
291 create instances of QXmlQuery for running XQueries.
292
293 \note The XSL-T support in this release is considered experimental.
294 See the \l{XQuery#XSLT 2.0} {XSLT conformance} for details.
295
296 \since 4.5
297 \sa queryLanguage()
298 */
299QXmlQuery::QXmlQuery(QueryLanguage queryLanguage,
300 const QXmlNamePool &np) : d(new QXmlQueryPrivate(np))
301{
302 d->queryLanguage = queryLanguage;
303}
304
305/*!
306 Destroys this QXmlQuery.
307 */
308QXmlQuery::~QXmlQuery()
309{
310 delete d;
311}
312
313/*!
314 Assigns \a other to this QXmlQuery instance.
315 */
316QXmlQuery &QXmlQuery::operator=(const QXmlQuery &other)
317{
318 /* Keep this section in sync with QXmlQuery::QXmlQuery(const QXmlQuery &).
319 */
320 if(d != other.d)
321 {
322 *d = *other.d;
323 d->detach();
324 }
325
326 return *this;
327}
328
329/*!
330 Changes the \l {QAbstractMessageHandler}{message handler} for this
331 QXmlQuery to \a aMessageHandler. The query sends all compile and
332 runtime messages to this message handler. QXmlQuery does not take
333 ownership of \a aMessageHandler.
334
335 Normally, the default message handler is sufficient. It writes
336 compile and runtime messages to \e stderr. The default message
337 handler includes color codes if \e stderr can render colors.
338
339 Note that changing the message handler after the query has been
340 compiled has no effect, i.e. the query uses the same message handler
341 at runtime that it uses at compile time.
342
343 When QXmlQuery calls QAbstractMessageHandler::message(),
344 the arguments are as follows:
345
346 \table
347 \header
348 \o message() argument
349 \o Semantics
350 \row
351 \o QtMsgType type
352 \o Only QtWarningMsg and QtFatalMsg are used. The former
353 identifies a compile or runtime warning, while the
354 latter identifies a dynamic or static error.
355 \row
356 \o const QString & description
357 \o An XHTML document which is the actual message. It is translated
358 into the current language.
359 \row
360 \o const QUrl &identifier
361 \o Identifies the error with a URI, where the fragment is
362 the error code, and the rest of the URI is the error namespace.
363 \row
364 \o const QSourceLocation & sourceLocation
365 \o Identifies where the error occurred.
366 \endtable
367
368 */
369void QXmlQuery::setMessageHandler(QAbstractMessageHandler *aMessageHandler)
370{
371 d->messageHandler = aMessageHandler;
372}
373
374/*!
375 Returns the message handler that handles compile and runtime
376 messages for this QXmlQuery.
377 */
378QAbstractMessageHandler *QXmlQuery::messageHandler() const
379{
380 return d->messageHandler;
381}
382
383/*!
384 Sets this QXmlQuery to an XQuery read from the \a sourceCode
385 device. The device must have been opened with at least
386 QIODevice::ReadOnly.
387
388 \a documentURI represents the query obtained from the \a sourceCode
389 device. It is the base URI of the static context, as defined in the
390 \l {http://www.w3.org/TR/xquery/}{XQuery language}. It is used
391 internally to resolve relative URIs that appear in the query, and
392 for message reporting. \a documentURI can be empty. If it is empty,
393 the \l{QCoreApplication::applicationFilePath()} {application file
394 path} is used. If it is not empty, it may be either relative or
395 absolute. If it is relative, it is resolved itself against the
396 \l {QCoreApplication::applicationFilePath()} {application file
397 path} before it is used. If \a documentURI is neither a valid URI
398 nor empty, the result is undefined.
399
400 If the query contains a static error (e.g. syntax error), an error
401 message is sent to the messageHandler(), and isValid() will return
402 \e false.
403
404 Variables must be bound before setQuery() is called.
405
406 The encoding of the XQuery in \a sourceCode is detected internally
407 using the rules for setting and detecting encoding of XQuery files,
408 which are explained in the \l {http://www.w3.org/TR/xquery/}
409 {XQuery language}.
410
411 If \a sourceCode is \c null or not readable, or if \a documentURI is not
412 a valid URI, behavior is undefined.
413 \sa isValid()
414 */
415void QXmlQuery::setQuery(QIODevice *sourceCode, const QUrl &documentURI)
416{
417 if(!sourceCode)
418 {
419 qWarning("A null QIODevice pointer cannot be passed.");
420 return;
421 }
422
423 if(!sourceCode->isReadable())
424 {
425 qWarning("The device must be readable.");
426 return;
427 }
428
429 d->queryURI = QPatternist::XPathHelper::normalizeQueryURI(documentURI);
430 d->expression(sourceCode);
431}
432
433/*!
434 \overload
435 The behavior and requirements of this function are the same as for
436 setQuery(QIODevice*, const QUrl&), after the XQuery has been read
437 from the IO device into a string. Because \a sourceCode is already
438 a Unicode string, detection of its encoding is unnecessary.
439*/
440void QXmlQuery::setQuery(const QString &sourceCode, const QUrl &documentURI)
441{
442 Q_ASSERT_X(documentURI.isEmpty() || documentURI.isValid(), Q_FUNC_INFO,
443 "The document URI must be valid.");
444
445 QByteArray query(sourceCode.toUtf8());
446 QBuffer buffer(&query);
447 buffer.open(QIODevice::ReadOnly);
448
449 setQuery(&buffer, documentURI);
450}
451
452/*!
453 Sets this QXmlQuery to the XQuery read from the \a queryURI. Use
454 isValid() after calling this function. If an error occurred reading
455 \a queryURI, e.g., the query does not exist, cannot be read, or is
456 invalid, isValid() will return \e false.
457
458 The supported URI schemes are the same as those in the XQuery
459 function \c{fn:doc}, except that queryURI can be the object of
460 a variable binding.
461
462 \a baseURI is the Base URI of the static context, as defined in the
463 \l {http://www.w3.org/TR/xquery/}{XQuery language}. It is used
464 internally to resolve relative URIs that appear in the query, and
465 for message reporting. If \a baseURI is empty, \a queryURI is used.
466 Otherwise, \a baseURI is used, and it is resolved against the \l
467 {QCoreApplication::applicationFilePath()} {application file path} if
468 it is relative.
469
470 If \a queryURI is empty or invalid, or if \a baseURI is invalid,
471 the behavior of this function is undefined.
472 */
473void QXmlQuery::setQuery(const QUrl &queryURI, const QUrl &baseURI)
474{
475 Q_ASSERT_X(queryURI.isValid(), Q_FUNC_INFO, "The passed URI must be valid.");
476
477 const QUrl canonicalURI(QPatternist::XPathHelper::normalizeQueryURI(queryURI));
478 Q_ASSERT(canonicalURI.isValid());
479 Q_ASSERT(!canonicalURI.isRelative());
480 Q_ASSERT(baseURI.isValid() || baseURI.isEmpty());
481
482 d->queryURI = QPatternist::XPathHelper::normalizeQueryURI(baseURI.isEmpty() ? queryURI : baseURI);
483
484 QPatternist::AutoPtr<QIODevice> result;
485
486 try
487 {
488 result.reset(QPatternist::AccelTreeResourceLoader::load(canonicalURI, d->m_networkAccessDelegator,
489 d->staticContext()));
490 }
491 catch(const QPatternist::Exception)
492 {
493 /* We do nothing, result will be 0. */
494 }
495
496 if(result)
497 {
498 setQuery(result.data(), d->queryURI);
499 result->close();
500 }
501 else
502 d->recompileRequired();
503}
504
505/*!
506 Binds the variable \a name to the \a value so that $\a name can be
507 used from within the query to refer to the \a value.
508
509 \a name must not be \e null. \a {name}.isNull() must return false.
510 If \a name has already been bound by a previous bindVariable() call,
511 its previous binding will be overridden.
512
513 If \a {value} is null so that \a {value}.isNull() returns true, and
514 \a {name} already has a binding, the effect is to remove the
515 existing binding for \a {name}.
516
517 To bind a value of type QString or QUrl, wrap the value in a
518 QVariant such that QXmlItem's QVariant constructor is called.
519
520 All strings processed by the query must be valid XQuery strings,
521 which means they must contain only XML 1.0 characters. However,
522 this requirement is not checked. If the query processes an invalid
523 string, the behavior is undefined.
524
525 \sa QVariant::isValid(), {QtXDM}{How QVariant maps to XQuery's Data Model},
526 QXmlItem::isNull()
527 */
528void QXmlQuery::bindVariable(const QXmlName &name, const QXmlItem &value)
529{
530 if(name.isNull())
531 {
532 qWarning("The variable name cannot be null.");
533 return;
534 }
535
536 const QPatternist::VariableLoader::Ptr vl(d->variableLoader());
537 const QVariant variant(qVariantFromValue(value));
538
539 /* If the type of the variable changed(as opposed to only the value),
540 * we will have to recompile. */
541 if(vl->invalidationRequired(name, variant) || value.isNull())
542 d->recompileRequired();
543
544 vl->addBinding(name, variant);
545}
546
547/*!
548 \overload
549
550 This function constructs a QXmlName from \a localName using the
551 query's \l {QXmlNamePool} {namespace}. The function then behaves as
552 the overloaded function. It is equivalent to the following snippet.
553
554 \snippet doc/src/snippets/code/src_xmlpatterns_api_qxmlquery.cpp 0
555 */
556void QXmlQuery::bindVariable(const QString &localName, const QXmlItem &value)
557{
558 bindVariable(QXmlName(d->namePool, localName), value);
559}
560
561/*!
562 Binds the variable \a name to the \a device so that $\a name can be
563 used from within the query to refer to the \a device. The QIODevice
564 \a device is exposed to the query as a URI of type \c{xs:anyURI},
565 which can be passed to the \c{fn:doc()} function to be read. E.g.,
566 this function can be used to pass an XML document in memory to
567 \c{fn:doc}.
568
569 \snippet doc/src/snippets/code/src_xmlpatterns_api_qxmlquery.cpp 1
570
571 The caller must ensure that \a device has been opened with at least
572 QIODevice::ReadOnly prior to this binding. Otherwise, behavior is
573 undefined.
574
575 If the query will access an XML document contained in a QString, use
576 a QBuffer as shown in the following snippet. Suppose \e myQString
577 contains \c{<document>content</document>}
578
579 \snippet doc/src/snippets/qxmlquery/bindingExample.cpp 0
580
581 \a name must not be \e null. \a {name}.isNull() must return false.
582 If \a name has already been bound, its previous binding will be
583 overridden. The URI that \a name evaluates to is arbitrary and may
584 change.
585
586 If the type of the variable binding changes (e.g., if a previous
587 binding by the same name was a QVariant, or if there was no previous
588 binding), isValid() will return \c{false}, and recompilation of the
589 query text is required. To recompile the query, call setQuery(). For
590 this reason, bindVariable() should be called before setQuery(), if
591 possible.
592
593 \note \a device must not be deleted while this QXmlQuery exists.
594*/
595void QXmlQuery::bindVariable(const QXmlName &name, QIODevice *device)
596{
597 if(device && !device->isReadable())
598 {
599 qWarning("A null, or readable QIODevice must be passed.");
600 return;
601 }
602
603 if(name.isNull())
604 {
605 qWarning("The variable name cannot be null.");
606 return;
607 }
608
609 const QPatternist::VariableLoader::Ptr vl(d->variableLoader());
610
611 if(device)
612 {
613 const QVariant variant(qVariantFromValue(device));
614
615 if(vl->invalidationRequired(name, variant))
616 d->recompileRequired();
617
618 vl->addBinding(name, variant);
619
620 /* We need to tell the resource loader to discard its document, because
621 * the underlying QIODevice has changed, but the variable name is the
622 * same which means that the URI is the same, and hence the resource
623 * loader will return the document for the old QIODevice.
624 */
625 d->resourceLoader()->clear(QUrl(QLatin1String("tag:trolltech.com,2007:QtXmlPatterns:QIODeviceVariable:") + d->namePool.d->stringForLocalName(name.localName())));
626 }
627 else
628 {
629 vl->removeBinding(name);
630 d->recompileRequired();
631 }
632}
633
634/*!
635 \overload
636
637 If \a localName is a valid \l {QXmlName::isNCName()} {NCName}, this
638 function is equivalent to the following snippet.
639
640 \snippet doc/src/snippets/code/src_xmlpatterns_api_qxmlquery.cpp 2
641
642 A QXmlName is constructed from \a localName, and is passed
643 to the appropriate overload along with \a device.
644
645 \sa QXmlName::isNCName()
646 */
647void QXmlQuery::bindVariable(const QString &localName, QIODevice *device)
648{
649 bindVariable(QXmlName(d->namePool, localName), device);
650}
651
652/*!
653 Evaluates this query and sends the result as a sequence of callbacks
654 to the \l {QAbstractXmlReceiver} {receiver} \a callback. QXmlQuery
655 does not take ownership of \a callback.
656
657 If an error occurs during the evaluation, error messages are sent to
658 messageHandler() and \c false is returned.
659
660 If this query \l {isValid()} {is invalid}, \c{false} is returned
661 and the behavior is undefined. If \a callback is null,
662 behavior is undefined.
663
664 \sa QAbstractXmlReceiver, isValid()
665 */
666bool QXmlQuery::evaluateTo(QAbstractXmlReceiver *callback) const
667{
668 if(!callback)
669 {
670 qWarning("A non-null callback must be passed.");
671 return false;
672 }
673
674 if(isValid())
675 {
676 try
677 {
678 /*
679 * This order is significant. expression() might cause
680 * query recompilation, and as part of that it recreates
681 * the static context. However, if we create the dynamic
682 * context before the query recompilation has been
683 * triggered, it will use the old static context, and
684 * hence old source locations.
685 */
686 const QPatternist::Expression::Ptr expr(d->expression());
687 const QPatternist::DynamicContext::Ptr dynContext(d->dynamicContext(callback));
688 callback->startOfSequence();
689 expr->evaluateToSequenceReceiver(dynContext);
690 callback->endOfSequence();
691 return true;
692 }
693 catch(const QPatternist::Exception)
694 {
695 return false;
696 }
697 }
698 else
699 return false;
700}
701
702/*!
703 Attempts to evaluate the query and returns the results in the
704 \a target \l {QStringList} {string list}.
705
706 If the query \l {isValid()} {is valid} and the evaluation succeeds,
707 true is returned. Otherwise, false is returned and the contents of
708 \a target are undefined.
709
710 The query must evaluate to a sequence of \c{xs:string} values. If
711 the query does not evaluate to a sequence of strings, the values can
712 often be converted by adding a call to \c{string()} at the end of
713 the XQuery.
714
715 If \a target is null, the behavior is undefined.
716 */
717bool QXmlQuery::evaluateTo(QStringList *target) const
718{
719 if(!target)
720 {
721 qWarning("A non-null callback must be passed.");
722 return false;
723 }
724
725 if(isValid())
726 {
727 try
728 {
729 /*
730 * This order is significant. expression() might cause
731 * query recompilation, and as part of that it recreates
732 * the static context. However, if we create the dynamic
733 * context before the query recompilation has been
734 * triggered, it will use the old static context, and
735 * hence old source locations.
736 */
737 const QPatternist::Expression::Ptr expr(d->expression());
738 if(!expr)
739 return false;
740
741 QPatternist::DynamicContext::Ptr dynContext(d->dynamicContext());
742
743 if(!QPatternist::BuiltinTypes::xsString->xdtTypeMatches(expr->staticType()->itemType()))
744 return false;
745
746 const QPatternist::Item::Iterator::Ptr it(expr->evaluateSequence(dynContext));
747 QPatternist::Item next(it->next());
748
749 while(!next.isNull())
750 {
751 target->append(next.stringValue());
752 next = it->next();
753 }
754
755 return true;
756 }
757 catch(const QPatternist::Exception)
758 {
759 return false;
760 }
761 }
762 else
763 return false;
764}
765
766/*!
767 Evaluates the query or stylesheet, and writes the output to \a target.
768
769 QXmlSerializer is used to write the output to \a target. In a future
770 release, it is expected that this function will be changed to
771 respect serialization options set in the stylesheet.
772
773 If an error occurs during the evaluation, error messages are sent to
774 messageHandler() and \c false is returned.
775
776 If \a target is \c null, or is not opened in at least
777 QIODevice::WriteOnly mode, the behavior is undefined. QXmlQuery
778 does not take ownership of \a target.
779
780 \since 4.5
781 \overload
782 */
783bool QXmlQuery::evaluateTo(QIODevice *target) const
784{
785 if(!target)
786 {
787 qWarning("The pointer to the device cannot be null.");
788 return false;
789 }
790
791 if(!target->isWritable())
792 {