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

Last change on this file since 745 was 651, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.2 sources.

File size: 38.9 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2010 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{Using XML technologies#XSLT
155 2.0}{XSLT conformance} for 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{Using XML technologies#XSLT 2.0}{XSLT conformance} for
295 details.
296
297 \since 4.5
298 \sa queryLanguage()
299 */
300QXmlQuery::QXmlQuery(QueryLanguage queryLanguage,
301 const QXmlNamePool &np) : d(new QXmlQueryPrivate(np))
302{
303 d->queryLanguage = queryLanguage;
304}
305
306/*!
307 Destroys this QXmlQuery.
308 */
309QXmlQuery::~QXmlQuery()
310{
311 delete d;
312}
313
314/*!
315 Assigns \a other to this QXmlQuery instance.
316 */
317QXmlQuery &QXmlQuery::operator=(const QXmlQuery &other)
318{
319 /* Keep this section in sync with QXmlQuery::QXmlQuery(const QXmlQuery &).
320 */
321 if(d != other.d)
322 {
323 *d = *other.d;
324 d->detach();
325 }
326
327 return *this;
328}
329
330/*!
331 Changes the \l {QAbstractMessageHandler}{message handler} for this
332 QXmlQuery to \a aMessageHandler. The query sends all compile and
333 runtime messages to this message handler. QXmlQuery does not take
334 ownership of \a aMessageHandler.
335
336 Normally, the default message handler is sufficient. It writes
337 compile and runtime messages to \e stderr. The default message
338 handler includes color codes if \e stderr can render colors.
339
340 Note that changing the message handler after the query has been
341 compiled has no effect, i.e. the query uses the same message handler
342 at runtime that it uses at compile time.
343
344 When QXmlQuery calls QAbstractMessageHandler::message(),
345 the arguments are as follows:
346
347 \table
348 \header
349 \o message() argument
350 \o Semantics
351 \row
352 \o QtMsgType type
353 \o Only QtWarningMsg and QtFatalMsg are used. The former
354 identifies a compile or runtime warning, while the
355 latter identifies a dynamic or static error.
356 \row
357 \o const QString & description
358 \o An XHTML document which is the actual message. It is translated
359 into the current language.
360 \row
361 \o const QUrl &identifier
362 \o Identifies the error with a URI, where the fragment is
363 the error code, and the rest of the URI is the error namespace.
364 \row
365 \o const QSourceLocation & sourceLocation
366 \o Identifies where the error occurred.
367 \endtable
368
369 */
370void QXmlQuery::setMessageHandler(QAbstractMessageHandler *aMessageHandler)
371{
372 d->messageHandler = aMessageHandler;
373}
374
375/*!
376 Returns the message handler that handles compile and runtime
377 messages for this QXmlQuery.
378 */
379QAbstractMessageHandler *QXmlQuery::messageHandler() const
380{
381 return d->messageHandler;
382}
383
384/*!
385 Sets this QXmlQuery to an XQuery read from the \a sourceCode
386 device. The device must have been opened with at least
387 QIODevice::ReadOnly.
388
389 \a documentURI represents the query obtained from the \a sourceCode
390 device. It is the base URI of the static context, as defined in the
391 \l {http://www.w3.org/TR/xquery/}{XQuery language}. It is used
392 internally to resolve relative URIs that appear in the query, and
393 for message reporting. \a documentURI can be empty. If it is empty,
394 the \l{QCoreApplication::applicationFilePath()} {application file
395 path} is used. If it is not empty, it may be either relative or
396 absolute. If it is relative, it is resolved itself against the
397 \l {QCoreApplication::applicationFilePath()} {application file
398 path} before it is used. If \a documentURI is neither a valid URI
399 nor empty, the result is undefined.
400
401 If the query contains a static error (e.g. syntax error), an error
402 message is sent to the messageHandler(), and isValid() will return
403 \e false.
404
405 Variables must be bound before setQuery() is called.
406
407 The encoding of the XQuery in \a sourceCode is detected internally
408 using the rules for setting and detecting encoding of XQuery files,
409 which are explained in the \l {http://www.w3.org/TR/xquery/}
410 {XQuery language}.
411
412 If \a sourceCode is \c null or not readable, or if \a documentURI is not
413 a valid URI, behavior is undefined.
414 \sa isValid()
415 */
416void QXmlQuery::setQuery(QIODevice *sourceCode, const QUrl &documentURI)
417{
418 if(!sourceCode)
419 {
420 qWarning("A null QIODevice pointer cannot be passed.");
421 return;
422 }
423
424 if(!sourceCode->isReadable())
425 {
426 qWarning("The device must be readable.");
427 return;
428 }
429
430 d->queryURI = QPatternist::XPathHelper::normalizeQueryURI(documentURI);
431 d->expression(sourceCode);
432}
433
434/*!
435 \overload
436 The behavior and requirements of this function are the same as for
437 setQuery(QIODevice*, const QUrl&), after the XQuery has been read
438 from the IO device into a string. Because \a sourceCode is already
439 a Unicode string, detection of its encoding is unnecessary.
440*/
441void QXmlQuery::setQuery(const QString &sourceCode, const QUrl &documentURI)
442{
443 Q_ASSERT_X(documentURI.isEmpty() || documentURI.isValid(), Q_FUNC_INFO,
444 "The document URI must be valid.");
445
446 QByteArray query(sourceCode.toUtf8());
447 QBuffer buffer(&query);
448 buffer.open(QIODevice::ReadOnly);
449
450 setQuery(&buffer, documentURI);
451}
452
453/*!
454 Sets this QXmlQuery to the XQuery read from the \a queryURI. Use
455 isValid() after calling this function. If an error occurred reading
456 \a queryURI, e.g., the query does not exist, cannot be read, or is
457 invalid, isValid() will return \e false.
458
459 The supported URI schemes are the same as those in the XQuery
460 function \c{fn:doc}, except that queryURI can be the object of
461 a variable binding.
462
463 \a baseURI is the Base URI of the static context, as defined in the
464 \l {http://www.w3.org/TR/xquery/}{XQuery language}. It is used
465 internally to resolve relative URIs that appear in the query, and
466 for message reporting. If \a baseURI is empty, \a queryURI is used.
467 Otherwise, \a baseURI is used, and it is resolved against the \l
468 {QCoreApplication::applicationFilePath()} {application file path} if
469 it is relative.
470
471 If \a queryURI is empty or invalid, or if \a baseURI is invalid,
472 the behavior of this function is undefined.