source: trunk/src/xmlpatterns/api/qabstractxmlreceiver.cpp@ 353

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

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

File size: 15.1 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
5**
6** This file is part of the QtXmlPatterns module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you are unsure which license is appropriate for your use, please
37** contact the sales department at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include <QString>
43
44#include "qitem_p.h"
45
46#include "qabstractxmlreceiver_p.h"
47#include "qabstractxmlreceiver.h"
48
49QT_BEGIN_NAMESPACE
50
51/*!
52 \class QAbstractXmlReceiver
53 \brief The QAbstractXmlReceiver class provides a callback interface
54 for transforming the output of a QXmlQuery.
55 \reentrant
56 \since 4.4
57 \ingroup xml-tools
58
59 QAbstractXmlReceiver is an abstract base class that provides
60 a callback interface for receiving an \l {XQuery Sequence}
61 {XQuery sequence}, usually the output of an QXmlQuery, and
62 transforming that sequence into a structure of your choosing,
63 usually XML. Consider the example:
64
65 \snippet doc/src/snippets/code/src_xmlpatterns_api_qabstractxmlreceiver.cpp 0
66
67 First it constructs a \l {QXmlQuery} {query} that gets the
68 first paragraph from document \c index.html. Then it constructs
69 an \l {QXmlSerializer} {XML serializer} with the \l {QXmlQuery}
70 {query} and \l {QIODevice} {myOutputDevice} (Note the
71 \l {QXmlSerializer} {serializer} is an \e {XML receiver},
72 ie a subclass of QAbstractXmlReceiver). Finally, it
73 \l {QXmlQuery::evaluateTo()} {evaluates} the
74 \l {QXmlQuery} {query}, producing an ordered sequence of calls
75 to the \l {QXmlSerializer} {serializer's} callback functions.
76 The sequence of callbacks transforms the query output to XML
77 and writes it to \l {QIODevice} {myOutputDevice}.
78
79 Although the example uses \l {QXmlQuery} to produce the sequence
80 of callbacks to functions in QAbstractXmlReceiver, you can call
81 the callback functions directly as long as your sequence of
82 calls represents a valid \l {XQuery Sequence} {XQuery sequence}.
83
84 \target XQuery Sequence
85 \section1 XQuery Sequences
86
87 An XQuery \a sequence is an ordered collection of zero, one,
88 or many \e items. Each \e item is either an \e {atomic value}
89 or a \e {node}. An \e {atomic value} is a simple data value.
90
91 There are six kinds of \e nodes.
92
93 \list
94
95 \o An \e {Element Node} represents an XML element.
96
97 \o An \e {Attribute Node} represents an XML attribute.
98
99 \o A \e {Document Node} represents an entire XML document.
100
101 \o A \e {Text Node} represents character data (element content).
102
103 \o A \e {Processing Instruction Node} represents an XML
104 processing instruction, which is used in an XML document
105 to tell the application reading the document to perform
106 some action. A typical example is to use a processing
107 instruction to tell the application to use a particular
108 XSLT stylesheet to display the document.
109
110 \o And a \e {Comment node} represents an XML comment.
111
112 \endlist
113
114 The \e sequence of \e nodes and \e {atomic values} obeys
115 the following rules. Note that \e {Namespace Node} refers
116 to a special \e {Attribute Node} with name \e {xmlns}.
117
118 \list
119
120 \o Each \e node appears in the \e sequence before its children
121 and their descendants appear.
122
123 \o A \e node's descendants appear in the \e sequence before
124 any of its siblings appear.
125
126 \o A \e {Document Node} represents an entire document. Zero or
127 more \e {Document Nodes} can appear in a \e sequence, but they
128 can only be top level items (i.e., a \e {Document Node} can't
129 be a child of another \e node.
130
131 \o \e {Namespace Nodes} immediately follow the \e {Element Node}
132 with which they are associated.
133
134 \o \e {Attribute Nodes} immediately follow the \e {Namespace Nodes}
135 of the element with which they are associated, or...
136
137 \o If there are no \e {Namespace Nodes} following an element, then
138 the \e {Attribute Nodes} immediately follow the element.
139
140 \o An \e {atomic value} can only appear as a top level \e item,
141 i.e., it can't appear as a child of a \e node.
142
143 \o \e {Processing Instruction Nodes} do not have children, and
144 their parent is either a \e {Document Node} or an \e {Element
145 Node}.
146
147 \o \e {Comment Nodes} do not have children, and
148 their parent is either a \e {Document Node} or an \e {Element
149 Node}.
150
151 \endlist
152
153 The \e sequence of \e nodes and \e {atomic values} is sent to
154 an QAbstractXmlReceiver (QXmlSerializer in
155 the example above) as a sequence of calls to the receiver's
156 callback functions. The mapping of callback functions to
157 sequence items is as follows.
158
159 \list
160
161 \o startDocument() and endDocument() are called for each
162 \e {Document Node} in the \e sequence. endDocument() is not
163 called until all the \e {Document Node's} children have
164 appeared in the \e sequence.
165
166 \o startElement() and endElement() are called for each
167 \e {Element Node}. endElement() is not called until all the
168 \e {Element Node's} children have appeared in the \e sequence.
169
170 \o attribute() is called for each \e {Attribute Node}.
171
172 \o comment() is called for each \e {Comment Node}.
173
174 \o characters() is called for each \e {Text Node}.
175
176 \o processingInstruction() is called for each \e {Processing
177 Instruction Node}.
178
179 \o namespaceBinding() is called for each \e {Namespace Node}.
180
181 \o atomicValue() is called for each \e {atomic value}.
182
183 \endlist
184
185 For a complete explanation of XQuery sequences, visit
186 \l {http://www.w3.org/TR/xpath-datamodel/}{XQuery Data Model}.
187
188 \sa {http://www.w3.org/TR/xpath-datamodel/}{W3C XQuery 1.0 and XPath 2.0 Data Model (XDM)}
189 \sa QXmlSerializer
190 \sa QXmlResultItems
191 */
192
193template<const QXmlNodeModelIndex::Axis axis>
194void QAbstractXmlReceiver::sendFromAxis(const QXmlNodeModelIndex &node)
195{
196 Q_ASSERT(!node.isNull());
197 const QXmlNodeModelIndex::Iterator::Ptr it(node.iterate(axis));
198 QXmlNodeModelIndex next(it->next());
199
200 while(!next.isNull())
201 {
202 sendAsNode(next);
203 next = it->next();
204 }
205}
206
207/*!
208 \internal
209 */
210QAbstractXmlReceiver::QAbstractXmlReceiver(QAbstractXmlReceiverPrivate *d)
211 : d_ptr(d)
212{
213}
214
215/*!
216 Constructs an abstract xml receiver.
217 */
218QAbstractXmlReceiver::QAbstractXmlReceiver() : d_ptr(0)
219{
220}
221
222/*!
223 Destroys the xml receiver.
224 */
225QAbstractXmlReceiver::~QAbstractXmlReceiver()
226{
227 delete d_ptr;
228}
229
230/*!
231 \fn void QAbstractXmlReceiver::startElement(const QXmlName &name)
232
233 This callback is called when a new element node appears
234 in the \l {XQuery Sequence} {sequence}. \a name is the
235 valid \l {QXmlName} {name} of the node element.
236 */
237
238/*
239### Qt 5:
240
241Consider how source locations should be communicated. Maybe every signature
242should be extended by adding "qint64 line = -1, qint64 column = -1".
243 */
244
245/*!
246 \fn void QAbstractXmlReceiver::endElement()
247
248 This callback is called when the end of an element node
249 appears in the \l {XQuery Sequence} {sequence}.
250*/
251
252/*!
253 \fn void QAbstractXmlReceiver::attribute(const QXmlName &name,
254 const QStringRef &value)
255 This callback is called when an attribute node
256 appears in the \l {XQuery Sequence} {sequence}.
257 \a name is the \l {QXmlName} {attribute name} and
258 the \a value string contains the attribute value.
259 */
260
261/*!
262 \fn void QAbstractXmlReceiver::comment(const QString &value)
263
264 This callback is called when a comment node appears
265 in the \l {XQuery Sequence} {sequence}. The \a value
266 is the comment text, which must not contain the string
267 "--".
268 */
269
270/*!
271 \fn void QAbstractXmlReceiver::characters(const QStringRef &value)
272
273 This callback is called when a text node appears in the
274 \l {XQuery Sequence} {sequence}. The \a value contains
275 the text. Adjacent text nodes may not occur in the
276 \l {XQuery Sequence} {sequence}, i.e., this callback must not
277 be called twice in a row.
278 */
279
280/*!
281 \fn void QAbstractXmlReceiver::startDocument()
282
283 This callback is called when a document node appears
284 in the \l {XQuery Sequence} {sequence}.
285 */
286
287/*
288### Qt 5:
289
290Change
291 virtual void startDocument() = 0;
292
293To:
294 virtual void startDocument(const QUrl &uri) = 0;
295
296Such that it allows the document URI to be communicated. The contract would
297allow null QUrls.
298*/
299
300/*!
301 \fn void QAbstractXmlReceiver::endDocument()
302
303 This callback is called when the end of a document node
304 appears in the \l {XQuery Sequence} {sequence}.
305 */
306
307/*!
308 \fn void QAbstractXmlReceiver::processingInstruction(const QXmlName &target,
309 const QString &value)
310
311 This callback is called when a processing instruction
312 appears in the \l {XQuery Sequence} {sequence}.
313 A processing instruction is used in an XML document
314 to tell the application reading the document to
315 perform some action. A typical example is to use a
316 processing instruction to tell the application to use a
317 particular XSLT stylesheet to process the document.
318
319 \quotefile doc/src/snippets/patternist/xmlStylesheet.xq
320
321 \a target is the \l {QXmlName} {name} of the processing
322 instruction. Its \e prefix and \e {namespace URI} must both
323 be empty. Its \e {local name} is the target. In the above
324 example, the name is \e {xml-stylesheet}.
325
326 The \a value specifies the action to be taken. Note that
327 the \a value must not contain the string "?>". In the above
328 example, the \a value is \e{type="test/xsl" href="formatter.xsl}.
329
330 Generally, use of processing instructions should be avoided,
331 because they are not namespace aware and in many contexts
332 are stripped out anyway. Processing instructions can often
333 be replaced with elements from a custom namespace.
334 */
335
336/*!
337 \fn void QAbstractXmlReceiver::atomicValue(const QVariant &value)
338
339 This callback is called when an atomic value appears in the \l
340 {XQuery Sequence} {sequence}. The \a value is a simple \l {QVariant}
341 {data value}. It is guaranteed to be \l {QVariant::isValid()}
342 {valid}.
343 */
344
345/*!
346 \fn virtual void QAbstractXmlReceiver::namespaceBinding(const QXmlName &name)
347
348 This callback is called when a namespace binding is in scope of an
349 element. A namespace is defined by a URI. In the \l {QXmlName}
350 \a name, the value of \l {QXmlName::namespaceUri()} is that URI. The
351 value of \l {QXmlName::prefix()} is the prefix that the URI is bound
352 to. The local name is insignificant and can be an arbitrary value.
353 */
354
355/*!
356 \internal
357
358 Treats \a outputItem as a node and calls the appropriate function,
359 e.g., attribute() or comment(), depending on its
360 QXmlNodeModelIndex::NodeKind.
361
362 This is a helper function that subclasses can use to multiplex
363 Nodes received via item().
364 */
365void QAbstractXmlReceiver::sendAsNode(const QPatternist::Item &outputItem)
366{
367 Q_ASSERT(outputItem);
368 Q_ASSERT(outputItem.isNode());
369 const QXmlNodeModelIndex asNode = outputItem.asNode();
370
371 switch(asNode.kind())
372 {
373 case QXmlNodeModelIndex::Attribute:
374 {
375 const QString &v = outputItem.stringValue();
376 attribute(asNode.name(), QStringRef(&v));
377 return;
378 }
379 case QXmlNodeModelIndex::Element:
380 {
381 startElement(asNode.name());
382
383 /* First the namespaces, then attributes, then the children. */
384 asNode.sendNamespaces(this);
385 sendFromAxis<QXmlNodeModelIndex::AxisAttribute>(asNode);
386 sendFromAxis<QXmlNodeModelIndex::AxisChild>(asNode);
387
388 endElement();
389
390 return;
391 }
392 case QXmlNodeModelIndex::Text:
393 {
394 const QString &v = asNode.stringValue();
395 characters(QStringRef(&v));
396 return;
397 }
398 case QXmlNodeModelIndex::ProcessingInstruction:
399 {
400 processingInstruction(asNode.name(), outputItem.stringValue());
401 return;
402 }
403 case QXmlNodeModelIndex::Comment:
404 {
405 comment(outputItem.stringValue());
406 return;
407 }
408 case QXmlNodeModelIndex::Document:
409 {
410 startDocument();
411 sendFromAxis<QXmlNodeModelIndex::AxisChild>(asNode);
412 endDocument();
413 return;
414 }
415 case QXmlNodeModelIndex::Namespace:
416 Q_ASSERT_X(false, Q_FUNC_INFO, "Not implemented");
417 }
418
419 Q_ASSERT_X(false, Q_FUNC_INFO,
420 QString::fromLatin1("Unknown node type: %1").arg(asNode.kind()).toUtf8().constData());
421}
422
423/*!
424 \internal
425
426 This function may be called instead of characters() if, and only if,
427 \a value consists only of whitespace.
428
429 The caller gurantees that \a value is not empty.
430
431 \e Whitespace refers to a sequence of characters that are either
432 spaces, tabs, or newlines, in any order. In other words, not all
433 the Unicode whitespace category is considered whitespace here.
434
435 However, there is no guarantee or requirement that whitespaceOnly()
436 is called for text nodes containing whitespace only. characters()
437 may be called just as well. This is why the default implementation
438 for whitespaceOnly() calls characters().
439
440 \sa characters()
441 */
442void QAbstractXmlReceiver::whitespaceOnly(const QStringRef &value)
443{
444 Q_ASSERT_X(value.toString().trimmed().isEmpty(), Q_FUNC_INFO,
445 "The caller must guarantee only whitespace is passed. Use characters() in other cases.");
446 const QString &v = value.toString();
447 characters(QStringRef(&v));
448}
449
450/*!
451 \internal
452 */
453void QAbstractXmlReceiver::item(const QPatternist::Item &item)
454{
455 if(item.isNode())
456 return sendAsNode(item);
457 else
458 atomicValue(QPatternist::AtomicValue::toQt(item.asAtomicValue()));
459}
460
461/*!
462 \fn void QAbstractXmlReceiver::startOfSequence()
463
464 This callback is called once only, right before the
465 \l {XQuery Sequence} {sequence} begins.
466 */
467
468/*!
469 \fn void QAbstractXmlReceiver::endOfSequence()
470
471 This callback is called once only, right after the
472 \l {XQuery Sequence} {sequence} ends.
473 */
474
475QT_END_NAMESPACE
476
Note: See TracBrowser for help on using the repository browser.