| 1 | /**************************************************************************** |
| 2 | ** |
| 3 | ** Copyright (C) 2016 The Qt Company Ltd. |
| 4 | ** Contact: https://www.qt.io/licensing/ |
| 5 | ** |
| 6 | ** This file is part of the QtXmlPatterns module of the Qt Toolkit. |
| 7 | ** |
| 8 | ** $QT_BEGIN_LICENSE:LGPL$ |
| 9 | ** Commercial License Usage |
| 10 | ** Licensees holding valid commercial Qt licenses may use this file in |
| 11 | ** accordance with the commercial license agreement provided with the |
| 12 | ** Software or, alternatively, in accordance with the terms contained in |
| 13 | ** a written agreement between you and The Qt Company. For licensing terms |
| 14 | ** and conditions see https://www.qt.io/terms-conditions. For further |
| 15 | ** information use the contact form at https://www.qt.io/contact-us. |
| 16 | ** |
| 17 | ** GNU Lesser General Public License Usage |
| 18 | ** Alternatively, this file may be used under the terms of the GNU Lesser |
| 19 | ** General Public License version 3 as published by the Free Software |
| 20 | ** Foundation and appearing in the file LICENSE.LGPL3 included in the |
| 21 | ** packaging of this file. Please review the following information to |
| 22 | ** ensure the GNU Lesser General Public License version 3 requirements |
| 23 | ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. |
| 24 | ** |
| 25 | ** GNU General Public License Usage |
| 26 | ** Alternatively, this file may be used under the terms of the GNU |
| 27 | ** General Public License version 2.0 or (at your option) the GNU General |
| 28 | ** Public license version 3 or any later version approved by the KDE Free |
| 29 | ** Qt Foundation. The licenses are as published by the Free Software |
| 30 | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 |
| 31 | ** included in the packaging of this file. Please review the following |
| 32 | ** information to ensure the GNU General Public License requirements will |
| 33 | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and |
| 34 | ** https://www.gnu.org/licenses/gpl-3.0.html. |
| 35 | ** |
| 36 | ** $QT_END_LICENSE$ |
| 37 | ** |
| 38 | ****************************************************************************/ |
| 39 | |
| 40 | #include <QtCore/QBuffer> |
| 41 | #include <QtCore/QStringList> |
| 42 | #include <QtXmlPatterns/QXmlFormatter> |
| 43 | |
| 44 | #include "qacceltreeresourceloader_p.h" |
| 45 | #include "qcommonvalues_p.h" |
| 46 | #include "qxmlresultitems.h" |
| 47 | #include "qxmlresultitems_p.h" |
| 48 | #include "qxmlserializer.h" |
| 49 | #include "qxpathhelper_p.h" |
| 50 | |
| 51 | #include "qxmlquery.h" |
| 52 | #include "qxmlquery_p.h" |
| 53 | |
| 54 | QT_BEGIN_NAMESPACE |
| 55 | |
| 56 | /*! |
| 57 | \class QXmlQuery |
| 58 | |
| 59 | \brief The QXmlQuery class performs XQueries on XML data, or on non-XML data modeled to look like XML. |
| 60 | |
| 61 | \reentrant |
| 62 | \since 4.4 |
| 63 | \ingroup xml-tools |
| 64 | \inmodule QtXmlPatterns |
| 65 | |
| 66 | The QXmlQuery class compiles and executes queries written in the |
| 67 | \l {http://www.w3.org/TR/xquery/}{XQuery language}. QXmlQuery is |
| 68 | typically used to query XML data, but it can also query non-XML |
| 69 | data that has been modeled to look like XML. |
| 70 | |
| 71 | Using QXmlQuery to query XML data, as in the snippet below, is |
| 72 | simple because it can use the built-in \l {QAbstractXmlNodeModel} |
| 73 | {XML data model} as its delegate to the underlying query engine for |
| 74 | traversing the data. The built-in data model is specified in \l |
| 75 | {http://www.w3.org/TR/xpath-datamodel/} {XQuery 1.0 and XPath 2.0 |
| 76 | Data Model}. |
| 77 | |
| 78 | \snippet code/src_xmlpatterns_api_qabstractxmlreceiver.cpp 0 |
| 79 | |
| 80 | The example uses QXmlQuery to match the first paragraph of an XML |
| 81 | document and then \l {QXmlSerializer} {output the result} to a |
| 82 | device as XML. |
| 83 | |
| 84 | Using QXmlQuery to query \e {non-XML} data requires writing a |
| 85 | subclass of QAbstractXmlNodeModel to use as a replacement for the |
| 86 | built-in XML data model. The custom data model will be able to |
| 87 | traverse the non-XML data as required by the QAbstractXmlNodeModel |
| 88 | interface. An instance of this custom data model then becomes the |
| 89 | delegate used by the query engine to traverse the non-XML data. For |
| 90 | an example of how to use QXmlQuery to query non-XML data, see the |
| 91 | documentation for QAbstractXmlNodeModel. |
| 92 | |
| 93 | \section1 Running XQueries |
| 94 | |
| 95 | To run a query set up with QXmlQuery, call one of the evaluation |
| 96 | functions. |
| 97 | |
| 98 | \list |
| 99 | |
| 100 | \li evaluateTo(QAbstractXmlReceiver *) is called with a pointer to an |
| 101 | XML \l {QAbstractXmlReceiver} {receiver}, which receives the query |
| 102 | results as a sequence of callbacks. The receiver callback class is |
| 103 | like the callback class used for translating the output of a SAX |
| 104 | parser. QXmlSerializer, for example, is a receiver callback class |
| 105 | for translating the sequence of callbacks for output as unformatted |
| 106 | XML text. |
| 107 | |
| 108 | \endlist |
| 109 | |
| 110 | \list |
| 111 | |
| 112 | \li evaluateTo(QXmlResultItems *) is called with a pointer to an |
| 113 | iterator for an empty sequence of query \l {QXmlResultItems} {result |
| 114 | items}. The Java-like iterator allows the query results to be |
| 115 | accessed sequentially. |
| 116 | |
| 117 | \endlist |
| 118 | |
| 119 | \list |
| 120 | |
| 121 | \li evaluateTo(QStringList *) is like evaluateTo(QXmlResultItems *), |
| 122 | but the query must evaluate to a sequence of strings. |
| 123 | |
| 124 | \endlist |
| 125 | |
| 126 | \section1 Running XPath Expressions |
| 127 | |
| 128 | The XPath language is a subset of the XQuery language, so |
| 129 | running an XPath expression is the same as running an XQuery |
| 130 | query. Pass the XPath expression to QXmlQuery using setQuery(). |
| 131 | |
| 132 | \section1 Running XSLT Stylesheets |
| 133 | |
| 134 | Running an XSLT stylesheet is like running an XQuery, except that |
| 135 | when you construct your QXmlQuery, you must pass QXmlQuery::XSLT20 |
| 136 | to tell QXmlQuery to interpret whatever it gets from setQuery() as |
| 137 | an XSLT stylesheet instead of as an XQuery. You must also set the |
| 138 | input document by calling setFocus(). |
| 139 | |
| 140 | \snippet code/src_xmlpatterns_api_qxmlquery.cpp 7 |
| 141 | |
| 142 | \note Currently, setFocus() must be called \e before setQuery() when |
| 143 | using XSLT. |
| 144 | |
| 145 | Another way to run an XSLT stylesheet is to use the \c xmlpatterns |
| 146 | command line utility. |
| 147 | |
| 148 | \code |
| 149 | xmlpatterns myStylesheet.xsl myInput.xml |
| 150 | \endcode |
| 151 | |
| 152 | \note For the current release, XSLT support should be considered |
| 153 | experimental. See section \l{XQuery#XSLT 2.0} {XSLT conformance} for |
| 154 | details. |
| 155 | |
| 156 | Stylesheet parameters are bound using bindVariable(). |
| 157 | |
| 158 | \section1 Binding A Query To A Starting Node |
| 159 | |
| 160 | When a query is run on XML data, as in the snippet above, the |
| 161 | \c{doc()} function returns the node in the built-in data model where |
| 162 | the query evaluation will begin. But when a query is run on a custom |
| 163 | node model containing non-XML data, one of the bindVariable() |
| 164 | functions must be called to bind a variable name to a starting node |
| 165 | in the custom model. A $variable reference is used in the XQuery |
| 166 | text to access the starting node in the custom model. It is not |
| 167 | necessary to declare the variable name external in the query. See |
| 168 | the example in the documentation for QAbstractXmlNodeModel. |
| 169 | |
| 170 | \section1 Reentrancy and Thread-Safety |
| 171 | |
| 172 | QXmlQuery is reentrant but not thread-safe. It is safe to use the |
| 173 | QxmlQuery copy constructor to create a copy of a query and run the |
| 174 | same query multiple times. Behind the scenes, QXmlQuery will reuse |
| 175 | resources such as opened files and compiled queries to the extent |
| 176 | possible. But it is not safe to use the same instance of QXmlQuery |
| 177 | in multiple threads. |
| 178 | |
| 179 | \section1 Error Handling |
| 180 | |
| 181 | Errors can occur during query evaluation. Examples include type |
| 182 | errors and file loading errors. When an error occurs: |
| 183 | |
| 184 | \list |
| 185 | |
| 186 | \li The error message is sent to the messageHandler(). |
| 187 | |
| 188 | \li QXmlResultItems::hasError() will return \c{true}, or |
| 189 | evaluateTo() will return \c{false}; |
| 190 | |
| 191 | \li The results of the evaluation are undefined. |
| 192 | |
| 193 | \endlist |
| 194 | |
| 195 | \section1 Resource Management |
| 196 | |
| 197 | When a query runs, it parses documents, allocating internal data |
| 198 | structures to hold them, and it may load other resources over the |
| 199 | network. It reuses these allocated resources when possible, to |
| 200 | avoid having to reload and reparse them. |
| 201 | |
| 202 | When setQuery() is called, the query text is compiled into an |
| 203 | internal data structure and optimized. The optimized form can |
| 204 | then be reused for multiple evaluations of the query. Since the |
| 205 | compile-and-optimize process can be expensive, repeating it for |
| 206 | the same query should be avoided by using a separate instance of |
| 207 | QXmlQuery for each query text. |
| 208 | |
| 209 | Once a document has been parsed, its internal representation is |
| 210 | maintained in the QXmlQuery instance and shared among multiple |
| 211 | QXmlQuery instances. |
| 212 | |
| 213 | An instance of QCoreApplication must exist before QXmlQuery can be |
| 214 | used. |
| 215 | |
| 216 | \section1 Event Handling |
| 217 | |
| 218 | When QXmlQuery accesses resources (e.g., calling \c fn:doc() to load a file, |
| 219 | or accessing a device via a bound variable), the event loop is used, which |
| 220 | means events will be processed. To avoid processing events when QXmlQuery |
| 221 | accesses resources, create your QXmlQuery instance in a separate thread. |
| 222 | */ |
| 223 | |
| 224 | /*! |
| 225 | \enum QXmlQuery::QueryLanguage |
| 226 | \since 4.5 |
| 227 | |
| 228 | Specifies whether you want QXmlQuery to interpret the input to |
| 229 | setQuery() as an XQuery or as an XSLT stylesheet. |
| 230 | |
| 231 | \value XQuery10 XQuery 1.0. |
| 232 | \value XSLT20 XSLT 2.0 |
| 233 | \omitvalue XmlSchema11IdentityConstraintSelector The selector, the restricted |
| 234 | XPath pattern found in W3C XML Schema 1.1 for uniqueness |
| 235 | contraints. Apart from restricting the syntax, the type check stage |
| 236 | for the expression assumes a sequence of nodes to be the focus. |
| 237 | \omitvalue XmlSchema11IdentityConstraintField The field, the restricted |
| 238 | XPath pattern found in W3C XML Schema 1.1 for uniqueness |
| 239 | contraints. Apart from restricting the syntax, the type check stage |
| 240 | for the expression assumes a sequence of nodes to be the focus. |
| 241 | \omitvalue XPath20 Signifies XPath 2.0. Has no effect in the public API, it's |
| 242 | used internally. As With XmlSchema11IdentityConstraintSelector and |
| 243 | XmlSchema11IdentityConstraintField, the type check stage |
| 244 | for the expression assumes a sequence of nodes to be the focus. |
| 245 | |
| 246 | \sa setQuery() |
| 247 | */ |
| 248 | |
| 249 | // ### Qt5: Merge constructor overloads |
| 250 | /*! |
| 251 | Constructs an invalid, empty query that cannot be used until |
| 252 | setQuery() is called. |
| 253 | |
| 254 | \note This constructor must not be used if you intend to use |
| 255 | this QXmlQuery to process XSL-T stylesheets. The other constructor |
| 256 | must be used in that case. |
| 257 | */ |
| 258 | QXmlQuery::QXmlQuery() : d(new QXmlQueryPrivate()) |
| 259 | { |
| 260 | } |
| 261 | |
| 262 | /*! |
| 263 | Constructs a QXmlQuery that is a copy of \a other. The new |
| 264 | instance will share resources with the existing query |
| 265 | to the extent possible. |
| 266 | */ |
| 267 | QXmlQuery::QXmlQuery(const QXmlQuery &other) : d(new QXmlQueryPrivate(*other.d)) |
| 268 | { |
| 269 | /* First we have invoked QXmlQueryPrivate's synthesized copy constructor. |
| 270 | * Keep this section in sync with QXmlQuery::operator=(). */ |
| 271 | d->detach(); |
| 272 | } |
| 273 | |
| 274 | /*! |
| 275 | Constructs a query that will use \a np as its name pool. The query |
| 276 | cannot be evaluated until setQuery() has been called. |
| 277 | */ |
| 278 | QXmlQuery::QXmlQuery(const QXmlNamePool &np) : d(new QXmlQueryPrivate(np)) |
| 279 | { |
| 280 | } |
| 281 | |
| 282 | /*! |
| 283 | |
| 284 | Constructs a query that will be used to run Xqueries or XSL-T |
| 285 | stylesheets, depending on the value of \a queryLanguage. It will use |
| 286 | \a np as its name pool. |
| 287 | |
| 288 | \note If your QXmlQuery will process XSL-T stylesheets, this |
| 289 | constructor must be used. The default constructor can only |
| 290 | create instances of QXmlQuery for running XQueries. |
| 291 | |
| 292 | \note The XSL-T support in this release is considered experimental. |
| 293 | See the \l{XQuery#XSLT 2.0} {XSLT conformance} for details. |
| 294 | |
| 295 | \since 4.5 |
| 296 | \sa queryLanguage() |
| 297 | */ |
| 298 | QXmlQuery::QXmlQuery(QueryLanguage queryLanguage, |
| 299 | const QXmlNamePool &np) : d(new QXmlQueryPrivate(np)) |
| 300 | { |
| 301 | d->queryLanguage = queryLanguage; |
| 302 | } |
| 303 | |
| 304 | /*! |
| 305 | Destroys this QXmlQuery. |
| 306 | */ |
| 307 | QXmlQuery::~QXmlQuery() |
| 308 | { |
| 309 | delete d; |
| 310 | } |
| 311 | |
| 312 | /*! |
| 313 | Assigns \a other to this QXmlQuery instance. |
| 314 | */ |
| 315 | QXmlQuery &QXmlQuery::operator=(const QXmlQuery &other) |
| 316 | { |
| 317 | /* Keep this section in sync with QXmlQuery::QXmlQuery(const QXmlQuery &). |
| 318 | */ |
| 319 | if(d != other.d) |
| 320 | { |
| 321 | *d = *other.d; |
| 322 | d->detach(); |
| 323 | } |
| 324 | |
| 325 | return *this; |
| 326 | } |
| 327 | |
| 328 | /*! |
| 329 | Changes the \l {QAbstractMessageHandler}{message handler} for this |
| 330 | QXmlQuery to \a aMessageHandler. The query sends all compile and |
| 331 | runtime messages to this message handler. QXmlQuery does not take |
| 332 | ownership of \a aMessageHandler. |
| 333 | |
| 334 | Normally, the default message handler is sufficient. It writes |
| 335 | compile and runtime messages to \e stderr. The default message |
| 336 | handler includes color codes if \e stderr can render colors. |
| 337 | |
| 338 | Note that changing the message handler after the query has been |
| 339 | compiled has no effect, i.e. the query uses the same message handler |
| 340 | at runtime that it uses at compile time. |
| 341 | |
| 342 | When QXmlQuery calls QAbstractMessageHandler::message(), |
| 343 | the arguments are as follows: |
| 344 | |
| 345 | \table |
| 346 | \header |
| 347 | \li message() argument |
| 348 | \li Semantics |
| 349 | \row |
| 350 | \li QtMsgType type |
| 351 | \li Only QtWarningMsg and QtFatalMsg are used. The former |
| 352 | identifies a compile or runtime warning, while the |
| 353 | latter identifies a dynamic or static error. |
| 354 | \row |
| 355 | \li const QString & description |
| 356 | \li An XHTML document which is the actual message. It is translated |
| 357 | into the current language. |
| 358 | \row |
| 359 | \li const QUrl &identifier |
| 360 | \li Identifies the error with a URI, where the fragment is |
| 361 | the error code, and the rest of the URI is the error namespace. |
| 362 | \row |
| 363 | \li const QSourceLocation & sourceLocation |
| 364 | \li Identifies where the error occurred. |
| 365 | \endtable |
| 366 | |
| 367 | */ |
| 368 | void QXmlQuery::setMessageHandler(QAbstractMessageHandler *aMessageHandler) |
| 369 | { |
| 370 | d->messageHandler = aMessageHandler; |
| 371 | } |
| 372 | |
| 373 | /*! |
| 374 | Returns the message handler that handles compile and runtime |
| 375 | messages for this QXmlQuery. |
| 376 | */ |
| 377 | QAbstractMessageHandler *QXmlQuery::messageHandler() const |
| 378 | { |
| 379 | return d->messageHandler; |
| 380 | } |
| 381 | |
| 382 | /*! |
| 383 | Sets this QXmlQuery to an XQuery read from the \a sourceCode |
| 384 | device. The device must have been opened with at least |
| 385 | QIODevice::ReadOnly. |
| 386 | |
| 387 | \a documentURI represents the query obtained from the \a sourceCode |
| 388 | device. It is the base URI of the static context, as defined in the |
| 389 | \l {http://www.w3.org/TR/xquery/}{XQuery language}. It is used |
| 390 | internally to resolve relative URIs that appear in the query, and |
| 391 | for message reporting. \a documentURI can be empty. If it is empty, |
| 392 | the \l{QCoreApplication::applicationFilePath()} {application file |
| 393 | path} is used. If it is not empty, it may be either relative or |
| 394 | absolute. If it is relative, it is resolved itself against the |
| 395 | \l {QCoreApplication::applicationFilePath()} {application file |
| 396 | path} before it is used. If \a documentURI is neither a valid URI |
| 397 | nor empty, the result is undefined. |
| 398 | |
| 399 | If the query contains a static error (e.g. syntax error), an error |
| 400 | message is sent to the messageHandler(), and isValid() will return |
| 401 | \e false. |
| 402 | |
| 403 | Variables must be bound before setQuery() is called. |
| 404 | |
| 405 | The encoding of the XQuery in \a sourceCode is detected internally |
| 406 | using the rules for setting and detecting encoding of XQuery files, |
| 407 | which are explained in the \l {http://www.w3.org/TR/xquery/} |
| 408 | {XQuery language}. |
| 409 | |
| 410 | If \a sourceCode is \c null or not readable, or if \a documentURI is not |
| 411 | a valid URI, behavior is undefined. |
| 412 | \sa isValid() |
| 413 | */ |
| 414 | void QXmlQuery::setQuery(QIODevice *sourceCode, const QUrl &documentURI) |
| 415 | { |
| 416 | if(!sourceCode) |
| 417 | { |
| 418 | qWarning(msg: "A null QIODevice pointer cannot be passed." ); |
| 419 | return; |
| 420 | } |
| 421 | |
| 422 | if(!sourceCode->isReadable()) |
| 423 | { |
| 424 | qWarning(msg: "The device must be readable." ); |
| 425 | return; |
| 426 | } |
| 427 | |
| 428 | d->queryURI = QPatternist::XPathHelper::normalizeQueryURI(uri: documentURI); |
| 429 | d->expression(queryDevice: sourceCode); |
| 430 | } |
| 431 | |
| 432 | /*! |
| 433 | \overload |
| 434 | The behavior and requirements of this function are the same as for |
| 435 | setQuery(QIODevice*, const QUrl&), after the XQuery has been read |
| 436 | from the IO device into a string. Because \a sourceCode is already |
| 437 | a Unicode string, detection of its encoding is unnecessary. |
| 438 | */ |
| 439 | void QXmlQuery::setQuery(const QString &sourceCode, const QUrl &documentURI) |
| 440 | { |
| 441 | Q_ASSERT_X(documentURI.isEmpty() || documentURI.isValid(), Q_FUNC_INFO, |
| 442 | "The document URI must be valid." ); |
| 443 | |
| 444 | QByteArray query(sourceCode.toUtf8()); |
| 445 | QBuffer buffer(&query); |
| 446 | buffer.open(openMode: QIODevice::ReadOnly); |
| 447 | |
| 448 | setQuery(sourceCode: &buffer, documentURI); |
| 449 | } |
| 450 | |
| 451 | /*! |
| 452 | Sets this QXmlQuery to the XQuery read from the \a queryURI. Use |
| 453 | isValid() after calling this function. If an error occurred reading |
| 454 | \a queryURI, e.g., the query does not exist, cannot be read, or is |
| 455 | invalid, isValid() will return \e false. |
| 456 | |
| 457 | The supported URI schemes are the same as those in the XQuery |
| 458 | function \c{fn:doc}, except that queryURI can be the object of |
| 459 | a variable binding. |
| 460 | |
| 461 | \a baseURI is the Base URI of the static context, as defined in the |
| 462 | \l {http://www.w3.org/TR/xquery/}{XQuery language}. It is used |
| 463 | internally to resolve relative URIs that appear in the query, and |
| 464 | for message reporting. If \a baseURI is empty, \a queryURI is used. |
| 465 | Otherwise, \a baseURI is used, and it is resolved against the \l |
| 466 | {QCoreApplication::applicationFilePath()} {application file path} if |
| 467 | it is relative. |
| 468 | |
| 469 | If \a queryURI is empty or invalid, or if \a baseURI is invalid, |
| 470 | the behavior of this function is undefined. |
| 471 | */ |
| 472 | void QXmlQuery::setQuery(const QUrl &queryURI, const QUrl &baseURI) |
| 473 | { |
| 474 | Q_ASSERT_X(queryURI.isValid(), Q_FUNC_INFO, "The passed URI must be valid." ); |
| 475 | |
| 476 | const QUrl canonicalURI(QPatternist::XPathHelper::normalizeQueryURI(uri: queryURI)); |
| 477 | Q_ASSERT(canonicalURI.isValid()); |
| 478 | Q_ASSERT(!canonicalURI.isRelative()); |
| 479 | Q_ASSERT(baseURI.isValid() || baseURI.isEmpty()); |
| 480 | |
| 481 | d->queryURI = QPatternist::XPathHelper::normalizeQueryURI(uri: baseURI.isEmpty() ? queryURI : baseURI); |
| 482 | |
| 483 | QPatternist::AutoPtr<QIODevice> result; |
| 484 | |
| 485 | try |
| 486 | { |
| 487 | result.reset(other: QPatternist::AccelTreeResourceLoader::load(uri: canonicalURI, networkDelegator: d->m_networkAccessDelegator, |
| 488 | context: d->staticContext())); |
| 489 | } |
| 490 | catch(const QPatternist::Exception) |
| 491 | { |
| 492 | /* We do nothing, result will be 0. */ |
| 493 | } |
| 494 | |
| 495 | if(result) |
| 496 | { |
| 497 | setQuery(sourceCode: result.data(), documentURI: d->queryURI); |
| 498 | result->close(); |
| 499 | } |
| 500 | else |
| 501 | d->recompileRequired(); |
| 502 | } |
| 503 | |
| 504 | /*! |
| 505 | Binds the variable \a name to the \a value so that $\a name can be |
| 506 | used from within the query to refer to the \a value. |
| 507 | |
| 508 | \a name must not be \e null. \a {name}.isNull() must return false. |
| 509 | If \a name has already been bound by a previous bindVariable() call, |
| 510 | its previous binding will be overridden. |
| 511 | |
| 512 | If \a {value} is null so that \a {value}.isNull() returns true, and |
| 513 | \a {name} already has a binding, the effect is to remove the |
| 514 | existing binding for \a {name}. |
| 515 | |
| 516 | To bind a value of type QString or QUrl, wrap the value in a |
| 517 | QVariant such that QXmlItem's QVariant constructor is called. |
| 518 | |
| 519 | All strings processed by the query must be valid XQuery strings, |
| 520 | which means they must contain only XML 1.0 characters. However, |
| 521 | this requirement is not checked. If the query processes an invalid |
| 522 | string, the behavior is undefined. |
| 523 | |
| 524 | \sa QVariant::isValid(), {QtXDM}{How QVariant maps to XQuery's Data Model}, |
| 525 | QXmlItem::isNull() |
| 526 | */ |
| 527 | void QXmlQuery::bindVariable(const QXmlName &name, const QXmlItem &value) |
| 528 | { |
| 529 | if(name.isNull()) |
| 530 | { |
| 531 | qWarning(msg: "The variable name cannot be null." ); |
| 532 | return; |
| 533 | } |
| 534 | |
| 535 | const QPatternist::VariableLoader::Ptr vl(d->variableLoader()); |
| 536 | const QVariant variant(QVariant::fromValue(value)); |
| 537 | |
| 538 | /* If the type of the variable changed(as opposed to only the value), |
| 539 | * we will have to recompile. */ |
| 540 | if(vl->invalidationRequired(name, variant) || value.isNull()) |
| 541 | d->recompileRequired(); |
| 542 | |
| 543 | vl->addBinding(name, value: variant); |
| 544 | } |
| 545 | |
| 546 | /*! |
| 547 | \overload |
| 548 | |
| 549 | This function constructs a QXmlName from \a localName using the |
| 550 | query's \l {QXmlNamePool} {namespace}. The function then behaves as |
| 551 | the overloaded function. It is equivalent to the following snippet. |
| 552 | |
| 553 | \snippet code/src_xmlpatterns_api_qxmlquery.cpp 0 |
| 554 | */ |
| 555 | void QXmlQuery::bindVariable(const QString &localName, const QXmlItem &value) |
| 556 | { |
| 557 | bindVariable(name: QXmlName(d->namePool, localName), value); |
| 558 | } |
| 559 | |
| 560 | /*! |
| 561 | Binds the variable \a name to the \a device so that $\a name can be |
| 562 | used from within the query to refer to the \a device. The QIODevice |
| 563 | \a device is exposed to the query as a URI of type \c{xs:anyURI}, |
| 564 | which can be passed to the \c{fn:doc()} function to be read. E.g., |
| 565 | this function can be used to pass an XML document in memory to |
| 566 | \c{fn:doc}. |
| 567 | |
| 568 | \snippet code/src_xmlpatterns_api_qxmlquery.cpp 1 |
| 569 | |
| 570 | The caller must ensure that \a device has been opened with at least |
| 571 | QIODevice::ReadOnly prior to this binding. Otherwise, behavior is |
| 572 | undefined. |
| 573 | |
| 574 | If the query will access an XML document contained in a QString, use |
| 575 | a QBuffer as shown in the following snippet. Suppose \e myQString |
| 576 | contains \c{<document>content</document>} |
| 577 | |
| 578 | \snippet qxmlquery/bindingExample.cpp 0 |
| 579 | |
| 580 | \a name must not be \e null. \a {name}.isNull() must return false. |
| 581 | If \a name has already been bound, its previous binding will be |
| 582 | overridden. The URI that \a name evaluates to is arbitrary and may |
| 583 | change. |
| 584 | |
| 585 | If the type of the variable binding changes (e.g., if a previous |
| 586 | binding by the same name was a QVariant, or if there was no previous |
| 587 | binding), isValid() will return \c{false}, and recompilation of the |
| 588 | query text is required. To recompile the query, call setQuery(). For |
| 589 | this reason, bindVariable() should be called before setQuery(), if |
| 590 | possible. |
| 591 | |
| 592 | \note \a device must not be deleted while this QXmlQuery exists. |
| 593 | */ |
| 594 | void QXmlQuery::bindVariable(const QXmlName &name, QIODevice *device) |
| 595 | { |
| 596 | if(device && !device->isReadable()) |
| 597 | { |
| 598 | qWarning(msg: "A null, or readable QIODevice must be passed." ); |
| 599 | return; |
| 600 | } |
| 601 | |
| 602 | if(name.isNull()) |
| 603 | { |
| 604 | qWarning(msg: "The variable name cannot be null." ); |
| 605 | return; |
| 606 | } |
| 607 | |
| 608 | const QPatternist::VariableLoader::Ptr vl(d->variableLoader()); |
| 609 | |
| 610 | if(device) |
| 611 | { |
| 612 | const QVariant variant(QVariant::fromValue(value: device)); |
| 613 | |
| 614 | if(vl->invalidationRequired(name, variant)) |
| 615 | d->recompileRequired(); |
| 616 | |
| 617 | vl->addBinding(name, value: variant); |
| 618 | |
| 619 | /* We need to tell the resource loader to discard its document, because |
| 620 | * the underlying QIODevice has changed, but the variable name is the |
| 621 | * same which means that the URI is the same, and hence the resource |
| 622 | * loader will return the document for the old QIODevice. |
| 623 | */ |
| 624 | d->resourceLoader()->clear(uri: QUrl(QLatin1String("tag:trolltech.com,2007:QtXmlPatterns:QIODeviceVariable:" ) + d->namePool.d->stringForLocalName(code: name.localName()))); |
| 625 | } |
| 626 | else |
| 627 | { |
| 628 | vl->removeBinding(name); |
| 629 | d->recompileRequired(); |
| 630 | } |
| 631 | } |
| 632 | |
| 633 | /*! |
| 634 | \overload |
| 635 | |
| 636 | If \a localName is a valid \l {QXmlName::isNCName()} {NCName}, this |
| 637 | function is equivalent to the following snippet. |
| 638 | |
| 639 | \snippet code/src_xmlpatterns_api_qxmlquery.cpp 2 |
| 640 | |
| 641 | A QXmlName is constructed from \a localName, and is passed |
| 642 | to the appropriate overload along with \a device. |
| 643 | |
| 644 | \sa QXmlName::isNCName() |
| 645 | */ |
| 646 | void QXmlQuery::bindVariable(const QString &localName, QIODevice *device) |
| 647 | { |
| 648 | bindVariable(name: QXmlName(d->namePool, localName), device); |
| 649 | } |
| 650 | |
| 651 | /*! |
| 652 | Evaluates this query and sends the result as a sequence of callbacks |
| 653 | to the \l {QAbstractXmlReceiver} {receiver} \a callback. QXmlQuery |
| 654 | does not take ownership of \a callback. |
| 655 | |
| 656 | If an error occurs during the evaluation, error messages are sent to |
| 657 | messageHandler() and \c false is returned. |
| 658 | |
| 659 | If this query \l {isValid()} {is invalid}, \c{false} is returned |
| 660 | and the behavior is undefined. If \a callback is null, |
| 661 | behavior is undefined. |
| 662 | |
| 663 | \sa QAbstractXmlReceiver, isValid() |
| 664 | */ |
| 665 | bool QXmlQuery::evaluateTo(QAbstractXmlReceiver *callback) const |
| 666 | { |
| 667 | if(!callback) |
| 668 | { |
| 669 | qWarning(msg: "A non-null callback must be passed." ); |
| 670 | return false; |
| 671 | } |
| 672 | |
| 673 | if(isValid()) |
| 674 | { |
| 675 | try |
| 676 | { |
| 677 | /* |
| 678 | * This order is significant. expression() might cause |
| 679 | * query recompilation, and as part of that it recreates |
| 680 | * the static context. However, if we create the dynamic |
| 681 | * context before the query recompilation has been |
| 682 | * triggered, it will use the old static context, and |
| 683 | * hence old source locations. |
| 684 | */ |
| 685 | const QPatternist::Expression::Ptr expr(d->expression()); |
| 686 | const QPatternist::DynamicContext::Ptr dynContext(d->dynamicContext(callback)); |
| 687 | callback->startOfSequence(); |
| 688 | expr->evaluateToSequenceReceiver(context: dynContext); |
| 689 | callback->endOfSequence(); |
| 690 | return true; |
| 691 | } |
| 692 | catch(const QPatternist::Exception) |
| 693 | { |
| 694 | return false; |
| 695 | } |
| 696 | } |
| 697 | else |
| 698 | return false; |
| 699 | } |
| 700 | |
| 701 | /*! |
| 702 | Attempts to evaluate the query and returns the results in the |
| 703 | \a target \l {QStringList} {string list}. |
| 704 | |
| 705 | If the query \l {isValid()} {is valid} and the evaluation succeeds, |
| 706 | true is returned. Otherwise, false is returned and the contents of |
| 707 | \a target are undefined. |
| 708 | |
| 709 | The query must evaluate to a sequence of \c{xs:string} values. If |
| 710 | the query does not evaluate to a sequence of strings, the values can |
| 711 | often be converted by adding a call to \c{string()} at the end of |
| 712 | the XQuery. |
| 713 | |
| 714 | If \a target is null, the behavior is undefined. |
| 715 | */ |
| 716 | bool QXmlQuery::evaluateTo(QStringList *target) const |
| 717 | { |
| 718 | if(!target) |
| 719 | { |
| 720 | qWarning(msg: "A non-null callback must be passed." ); |
| 721 | return false; |
| 722 | } |
| 723 | |
| 724 | if(isValid()) |
| 725 | { |
| 726 | try |
| 727 | { |
| 728 | /* |
| 729 | * This order is significant. expression() might cause |
| 730 | * query recompilation, and as part of that it recreates |
| 731 | * the static context. However, if we create the dynamic |
| 732 | * context before the query recompilation has been |
| 733 | * triggered, it will use the old static context, and |
| 734 | * hence old source locations. |
| 735 | */ |
| 736 | const QPatternist::Expression::Ptr expr(d->expression()); |
| 737 | if(!expr) |
| 738 | return false; |
| 739 | |
| 740 | QPatternist::DynamicContext::Ptr dynContext(d->dynamicContext()); |
| 741 | |
| 742 | if(!QPatternist::BuiltinTypes::xsString->xdtTypeMatches(other: expr->staticType()->itemType())) |
| 743 | return false; |
| 744 | |
| 745 | const QPatternist::Item::Iterator::Ptr it(expr->evaluateSequence(context: dynContext)); |
| 746 | QPatternist::Item next(it->next()); |
| 747 | |
| 748 | while(!next.isNull()) |
| 749 | { |
| 750 | target->append(t: next.stringValue()); |
| 751 | next = it->next(); |
| 752 | } |
| 753 | |
| 754 | return true; |
| 755 | } |
| 756 | catch(const QPatternist::Exception) |
| 757 | { |
| 758 | return false; |
| 759 | } |
| 760 | } |
| 761 | else |
| 762 | return false; |
| 763 | } |
| 764 | |
| 765 | /*! |
| 766 | Evaluates the query or stylesheet, and writes the output to \a target. |
| 767 | |
| 768 | QXmlSerializer is used to write the output to \a target. In a future |
| 769 | release, it is expected that this function will be changed to |
| 770 | respect serialization options set in the stylesheet. |
| 771 | |
| 772 | If an error occurs during the evaluation, error messages are sent to |
| 773 | messageHandler() and \c false is returned. |
| 774 | |
| 775 | If \a target is \c null, or is not opened in at least |
| 776 | QIODevice::WriteOnly mode, the behavior is undefined. QXmlQuery |
| 777 | does not take ownership of \a target. |
| 778 | |
| 779 | \since 4.5 |
| 780 | \overload |
| 781 | */ |
| 782 | bool QXmlQuery::evaluateTo(QIODevice *target) const |
| 783 | { |
| 784 | if(!target) |
| 785 | { |
| 786 | qWarning(msg: "The pointer to the device cannot be null." ); |
| 787 | return false; |
| 788 | } |
| 789 | |
| 790 | if(!target->isWritable()) |
| 791 | { |
| 792 | qWarning(msg: "The device must be writable." ); |
| 793 | return false; |
| 794 | } |
| 795 | |
| 796 | QXmlSerializer serializer(*this, target); |
| 797 | return evaluateTo(callback: &serializer); |
| 798 | } |
| 799 | |
| 800 | /*! |
| 801 | Starts the evaluation and makes it available in \a result. If \a |
| 802 | result is null, the behavior is undefined. The evaluation takes |
| 803 | place incrementally (lazy evaluation), as the caller uses |
| 804 | QXmlResultItems::next() to get the next result. |
| 805 | |
| 806 | \sa QXmlResultItems::next() |
| 807 | */ |
| 808 | void QXmlQuery::evaluateTo(QXmlResultItems *result) const |
| 809 | { |
| 810 | if(!result) |
| 811 | { |
| 812 | qWarning(msg: "A null pointer cannot be passed." ); |
| 813 | return; |
| 814 | } |
| 815 | |
| 816 | if(isValid()) |
| 817 | { |
| 818 | try |
| 819 | { |
| 820 | /* |
| 821 | * We don't have the d->expression() calls and |
| 822 | * d->dynamicContext() calls in the same order as seen in |
| 823 | * QXmlQuery::evaluateTo(), and the reason to why |
| 824 | * that isn't a problem, is that we call isValid(). |
| 825 | */ |
| 826 | const QPatternist::DynamicContext::Ptr dynContext(d->dynamicContext()); |
| 827 | result->d_ptr->setDynamicContext(dynContext); |
| 828 | result->d_ptr->iterator = d->expression()->evaluateSequence(context: dynContext); |
| 829 | } |
| 830 | catch(const QPatternist::Exception) |
| 831 | { |
| 832 | result->d_ptr->iterator = QPatternist::CommonValues::emptyIterator; |
| 833 | result->d_ptr->hasError = true; |
| 834 | } |
| 835 | } |
| 836 | else |
| 837 | { |
| 838 | result->d_ptr->iterator= QPatternist::CommonValues::emptyIterator; |
| 839 | result->d_ptr->hasError = true; |
| 840 | } |
| 841 | } |
| 842 | |
| 843 | /*! |
| 844 | Evaluates the query, and serializes the output as XML to \a output. |
| 845 | |
| 846 | If an error occurs during the evaluation, error messages are sent to |
| 847 | messageHandler(), the content of \a output is undefined and \c false is |
| 848 | returned, otherwise \c true is returned. |
| 849 | |
| 850 | If \a output is \c null behavior is undefined. QXmlQuery |
| 851 | does not take ownership of \a output. |
| 852 | |
| 853 | Internally, the class QXmlFormatter is used for this. |
| 854 | \since 4.5 |
| 855 | */ |
| 856 | bool QXmlQuery::evaluateTo(QString *output) const |
| 857 | { |
| 858 | Q_ASSERT_X(output, Q_FUNC_INFO, |
| 859 | "The input cannot be null" ); |
| 860 | |
| 861 | QBuffer outputDevice; |
| 862 | outputDevice.open(openMode: QIODevice::ReadWrite); |
| 863 | |
| 864 | QXmlFormatter formatter(*this, &outputDevice); |
| 865 | const bool success = evaluateTo(callback: &formatter); |
| 866 | |
| 867 | outputDevice.close(); |
| 868 | *output = QString::fromUtf8(str: outputDevice.data().constData()); |
| 869 | |
| 870 | return success; |
| 871 | } |
| 872 | |
| 873 | /*! |
| 874 | Returns true if this query is valid. Examples of invalid queries |
| 875 | are ones that contain syntax errors or that have not had setQuery() |
| 876 | called for them yet. |
| 877 | */ |
| 878 | bool QXmlQuery::isValid() const |
| 879 | { |
| 880 | return d->isValid(); |
| 881 | } |
| 882 | |
| 883 | /*! |
| 884 | Sets the URI resolver to \a resolver. QXmlQuery does not take |
| 885 | ownership of \a resolver. |
| 886 | |
| 887 | \sa uriResolver() |
| 888 | */ |
| 889 | void QXmlQuery::setUriResolver(const QAbstractUriResolver *resolver) |
| 890 | { |
| 891 | d->uriResolver = resolver; |
| 892 | } |
| 893 | |
| 894 | /*! |
| 895 | Returns the query's URI resolver. If no URI resolver has been set, |
| 896 | Qt XML Patterns will use the URIs in queries as they are. |
| 897 | |
| 898 | The URI resolver provides a level of abstraction, or \e{polymorphic |
| 899 | URIs}. A resolver can rewrite \e{logical} URIs to physical ones, or |
| 900 | it can translate obsolete or invalid URIs to valid ones. |
| 901 | |
| 902 | Qt XML Patterns calls the URI resolver for all URIs it encounters, |
| 903 | except for namespaces. Specifically, all builtin functions that deal |
| 904 | with URIs (\c{fn:doc()}, and \c{fn:doc-available()}). |
| 905 | |
| 906 | In the case of \c{fn:doc()}, the absolute URI is the base URI in the |
| 907 | static context (which most likely is the location of the query). |
| 908 | Rather than use the URI the user specified, the return value of |
| 909 | QAbstractUriResolver::resolve() will be used. |
| 910 | |
| 911 | When Qt XML Patterns calls QAbstractUriResolver::resolve() the |
| 912 | absolute URI is the URI mandated by the XQuery language, and the |
| 913 | relative URI is the URI specified by the user. |
| 914 | |
| 915 | \sa setUriResolver() |
| 916 | */ |
| 917 | const QAbstractUriResolver *QXmlQuery::uriResolver() const |
| 918 | { |
| 919 | return d->uriResolver; |
| 920 | } |
| 921 | |
| 922 | /*! |
| 923 | Returns the name pool used by this QXmlQuery for constructing \l |
| 924 | {QXmlName} {names}. There is no setter for the name pool, because |
| 925 | mixing name pools causes errors due to name confusion. |
| 926 | */ |
| 927 | QXmlNamePool QXmlQuery::namePool() const |
| 928 | { |
| 929 | return d->namePool; |
| 930 | } |
| 931 | |
| 932 | /*! |
| 933 | Sets the focus to \a item. The focus is the set of items that the |
| 934 | context item expression and path expressions navigate from. For |
| 935 | example, in the expression \e p/span, the element that \e p |
| 936 | evaluates to is the focus for the following expression, \e span. |
| 937 | |
| 938 | The focus can be accessed using the context item expression, i.e., |
| 939 | dot ("."). |
| 940 | |
| 941 | By default, the focus is not set and is undefined. It will |
| 942 | therefore result in a dynamic error, \c XPDY0002, if the focus |
| 943 | is attempted to be accessed. The focus must be set before the |
| 944 | query is set with setQuery(). |
| 945 | |
| 946 | There is no behavior defined for setting an item which is null. |
| 947 | |
| 948 | */ |
| 949 | void QXmlQuery::setFocus(const QXmlItem &item) |
| 950 | { |
| 951 | d->contextItem = item; |
| 952 | } |
| 953 | |
| 954 | /** |
| 955 | * This function should be a private member function of QXmlQuery, |
| 956 | * but we don't dare that due to our weird compilers. |
| 957 | * @internal |
| 958 | * @relates QXmlQuery |
| 959 | */ |
| 960 | template<typename TInputType> |
| 961 | bool setFocusHelper(QXmlQuery *const queryInstance, |
| 962 | const TInputType &focusValue) |
| 963 | { |
| 964 | /* We call resourceLoader(), so we have ensured that we have a resourceLoader |
| 965 | * that we will share in our copy. */ |
| 966 | queryInstance->d->resourceLoader(); |
| 967 | |
| 968 | QXmlQuery focusQuery(*queryInstance); |
| 969 | |
| 970 | /* Now we use the same, so we own the loaded document. */ |
| 971 | focusQuery.d->m_resourceLoader = queryInstance->d->m_resourceLoader; |
| 972 | |
| 973 | /* The copy constructor doesn't allow us to copy an existing QXmlQuery and |
| 974 | * changing the language at the same time so we need to use private API. */ |
| 975 | focusQuery.d->queryLanguage = QXmlQuery::XQuery10; |
| 976 | |
| 977 | Q_ASSERT(focusQuery.queryLanguage() == QXmlQuery::XQuery10); |
| 978 | focusQuery.bindVariable(QChar::fromLatin1(c: 'u'), focusValue); |
| 979 | focusQuery.setQuery(sourceCode: QLatin1String("doc($u)" )); |
| 980 | Q_ASSERT(focusQuery.isValid()); |
| 981 | |
| 982 | QXmlResultItems focusResult; |
| 983 | |
| 984 | queryInstance->d->m_resourceLoader = focusQuery.d->m_resourceLoader; |
| 985 | |
| 986 | focusQuery.evaluateTo(result: &focusResult); |
| 987 | const QXmlItem focusItem(focusResult.next()); |
| 988 | |
| 989 | if(focusItem.isNull() || focusResult.hasError()) |
| 990 | return false; |
| 991 | else |
| 992 | { |
| 993 | queryInstance->setFocus(focusItem); |
| 994 | return true; |
| 995 | } |
| 996 | } |
| 997 | |
| 998 | /*! |
| 999 | \since 4.5 |
| 1000 | \overload |
| 1001 | |
| 1002 | Sets the focus to be the document located at \a documentURI and |
| 1003 | returns true. If \a documentURI cannot be loaded, false is returned. |
| 1004 | It is undefined at what time the document may be loaded. When |
| 1005 | loading the document, the message handler and URI resolver set on |
| 1006 | this QXmlQuery are used. |
| 1007 | |
| 1008 | If \a documentURI is empty or is not a valid URI, the behavior of |
| 1009 | this function is undefined. |
| 1010 | */ |
| 1011 | bool QXmlQuery::setFocus(const QUrl &documentURI) |
| 1012 | { |
| 1013 | Q_ASSERT_X(documentURI.isValid() && !documentURI.isEmpty(), |
| 1014 | Q_FUNC_INFO, |
| 1015 | "The URI passed must be valid." ); |
| 1016 | |
| 1017 | return setFocusHelper(queryInstance: this, focusValue: QVariant(documentURI)); |
| 1018 | } |
| 1019 | |
| 1020 | /*! |
| 1021 | |
| 1022 | Sets the focus to be the \a document read from the QIODevice and |
| 1023 | returns true. If \a document cannot be loaded, false is returned. |
| 1024 | |
| 1025 | QXmlQuery does not take ownership of \a document. The user |
| 1026 | guarantees that a document is available from the \a document device |
| 1027 | and that the document is not empty. The device must be opened in at |
| 1028 | least read-only mode. \a document must stay in scope as long as the |
| 1029 | current query is active. |
| 1030 | |
| 1031 | \since 4.5 |
| 1032 | \overload |
| 1033 | */ |
| 1034 | bool QXmlQuery::setFocus(QIODevice *document) |
| 1035 | { |
| 1036 | if(!document) |
| 1037 | { |
| 1038 | qWarning(msg: "A null QIODevice pointer cannot be passed." ); |
| 1039 | return false; |
| 1040 | } |
| 1041 | |
| 1042 | if(!document->isReadable()) |
| 1043 | { |
| 1044 | qWarning(msg: "The device must be readable." ); |
| 1045 | return false; |
| 1046 | } |
| 1047 | |
| 1048 | return setFocusHelper(queryInstance: this, focusValue: document); |
| 1049 | } |
| 1050 | |
| 1051 | /*! |
| 1052 | This function behaves identically to calling the setFocus() overload with a |
| 1053 | QIODevice whose content is \a focus encoded as UTF-8. That is, \a focus is |
| 1054 | treated as if it contained an XML document. |
| 1055 | |
| 1056 | Returns the same result as the overload. |
| 1057 | |
| 1058 | \overload |
| 1059 | \since 4.6 |
| 1060 | */ |
| 1061 | bool QXmlQuery::setFocus(const QString &focus) |
| 1062 | { |
| 1063 | QBuffer device; |
| 1064 | device.setData(focus.toUtf8()); |
| 1065 | device.open(openMode: QIODevice::ReadOnly); |
| 1066 | |
| 1067 | return setFocusHelper(queryInstance: this, focusValue: &device); |
| 1068 | } |
| 1069 | |
| 1070 | /*! |
| 1071 | Returns a value indicating what this QXmlQuery is being used for. |
| 1072 | The default is QXmlQuery::XQuery10, which means the QXmlQuery is |
| 1073 | being used for running XQuery and XPath queries. QXmlQuery::XSLT20 |
| 1074 | can also be returned, which indicates the QXmlQuery is for running |
| 1075 | XSL-T spreadsheets. |
| 1076 | |
| 1077 | \since 4.5 |
| 1078 | */ |
| 1079 | QXmlQuery::QueryLanguage QXmlQuery::queryLanguage() const |
| 1080 | { |
| 1081 | return d->queryLanguage; |
| 1082 | } |
| 1083 | |
| 1084 | /*! |
| 1085 | Sets the \a name of the initial template. The initial template is |
| 1086 | the one the processor calls first, instead of attempting to match a |
| 1087 | template to the context node (if any). If an initial template is not |
| 1088 | set, the standard order of template invocation will be used. |
| 1089 | |
| 1090 | This function only applies when using QXmlQuery to process XSL-T |
| 1091 | stylesheets. The name becomes part of the compiled stylesheet. |
| 1092 | Therefore, this function must be called before calling setQuery(). |
| 1093 | |
| 1094 | If the stylesheet has no template named \a name, the processor will |
| 1095 | use the standard order of template invocation. |
| 1096 | |
| 1097 | \since 4.5 |
| 1098 | \sa initialTemplateName() |
| 1099 | */ |
| 1100 | void QXmlQuery::setInitialTemplateName(const QXmlName &name) |
| 1101 | { |
| 1102 | d->initialTemplateName = name; |
| 1103 | } |
| 1104 | |
| 1105 | /*! |
| 1106 | \overload |
| 1107 | |
| 1108 | Sets the name of the initial template to \a localName, which must be |
| 1109 | a valid \l{QXmlName::localName}{local name}. The initial template |
| 1110 | is the one the processor calls first, instead of attempting to match |
| 1111 | a template to the context node (if any). If an initial template is |
| 1112 | not set, the standard order of template invocation will be used. |
| 1113 | |
| 1114 | This function only applies when using QXmlQuery to process XSL-T |
| 1115 | stylesheets. The name becomes part of the compiled stylesheet. |
| 1116 | Therefore, this function must be called before calling setQuery(). |
| 1117 | |
| 1118 | If \a localName is not a valid \l{QXmlName::localName} {local |
| 1119 | name}, the effect is undefined. If the stylesheet has no template |
| 1120 | named \a localName, the processor will use the standard order of |
| 1121 | template invocation. |
| 1122 | |
| 1123 | \since 4.5 |
| 1124 | \sa initialTemplateName() |
| 1125 | */ |
| 1126 | void QXmlQuery::setInitialTemplateName(const QString &localName) |
| 1127 | { |
| 1128 | Q_ASSERT_X(QXmlName::isNCName(localName), |
| 1129 | Q_FUNC_INFO, |
| 1130 | "The name passed must be a valid NCName." ); |
| 1131 | setInitialTemplateName(QXmlName(d->namePool, localName)); |
| 1132 | } |
| 1133 | |
| 1134 | /*! |
| 1135 | Returns the name of the XSL-T stylesheet template that the processor |
| 1136 | will call first when running an XSL-T stylesheet. This function only |
| 1137 | applies when using QXmlQuery to process XSL-T stylesheets. By |
| 1138 | default, no initial template is set. In that case, a default |
| 1139 | constructed QXmlName is returned. |
| 1140 | |
| 1141 | \since 4.5 |
| 1142 | */ |
| 1143 | QXmlName QXmlQuery::initialTemplateName() const |
| 1144 | { |
| 1145 | return d->initialTemplateName; |
| 1146 | } |
| 1147 | |
| 1148 | /*! |
| 1149 | Sets the network manager to \a newManager. |
| 1150 | QXmlQuery does not take ownership of \a newManager. |
| 1151 | |
| 1152 | \sa networkAccessManager() |
| 1153 | \since 4.5 |
| 1154 | */ |
| 1155 | void QXmlQuery::setNetworkAccessManager(QNetworkAccessManager *newManager) |
| 1156 | { |
| 1157 | d->m_networkAccessDelegator->m_genericManager = newManager; |
| 1158 | } |
| 1159 | |
| 1160 | /*! |
| 1161 | Returns the network manager, or 0 if it has not been set. |
| 1162 | |
| 1163 | \sa setNetworkAccessManager() |
| 1164 | \since 4.5 |
| 1165 | */ |
| 1166 | QNetworkAccessManager *QXmlQuery::networkAccessManager() const |
| 1167 | { |
| 1168 | return d->m_networkAccessDelegator->m_genericManager; |
| 1169 | } |
| 1170 | |
| 1171 | /*! |
| 1172 | Binds the result of the query \a query, to a variable by name \a name. |
| 1173 | |
| 1174 | Evaluation of \a query will be commenced when this function is called. |
| 1175 | |
| 1176 | If \a query is invalid, behavior is undefined. \a query will be copied. |
| 1177 | |
| 1178 | \since 4.5 |
| 1179 | \sa isValid() |
| 1180 | */ |
| 1181 | void QXmlQuery::bindVariable(const QXmlName &name, const QXmlQuery &query) |
| 1182 | { |
| 1183 | Q_ASSERT_X(query.isValid(), Q_FUNC_INFO, "The query being bound must be valid." ); |
| 1184 | |
| 1185 | const QPatternist::VariableLoader::Ptr vl(d->variableLoader()); |
| 1186 | const QVariant variant(QVariant::fromValue(value: query)); |
| 1187 | |
| 1188 | if(vl->invalidationRequired(name, variant)) |
| 1189 | d->recompileRequired(); |
| 1190 | |
| 1191 | vl->addBinding(name, value: variant); |
| 1192 | } |
| 1193 | |
| 1194 | /*! |
| 1195 | \overload |
| 1196 | |
| 1197 | Has the same behavior and effects as the function being overloaded, but takes |
| 1198 | the variable name \a localName as a QString. \a query is used as in the |
| 1199 | overloaded function. |
| 1200 | |
| 1201 | \since 4.5 |
| 1202 | */ |
| 1203 | void QXmlQuery::bindVariable(const QString &localName, const QXmlQuery &query) |
| 1204 | { |
| 1205 | return bindVariable(name: QXmlName(d->namePool, localName), query); |
| 1206 | } |
| 1207 | |
| 1208 | QT_END_NAMESPACE |
| 1209 | |