source: trunk/src/corelib/xml/qxmlstream.cpp@ 788

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

trunk: Merged in qt 4.6.2 sources.

File size: 117.2 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 QtCore 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/qxmlstream.h"
43
44#if defined(QT_BUILD_XML_LIB) && defined(Q_OS_MAC64)
45// No need to define this in the 64-bit Mac libraries.
46// Since Qt 4.4 and previous weren't supported in 64-bit, there are
47// no QXmlStream* symbols to keep compatibility with
48# define QT_NO_XMLSTREAM
49#endif
50
51#ifndef QT_NO_XMLSTREAM
52
53#include "qxmlutils_p.h"
54#include <qdebug.h>
55#include <qfile.h>
56#include <stdio.h>
57#include <qtextcodec.h>
58#include <qstack.h>
59#include <qbuffer.h>
60#ifndef QT_BOOTSTRAPPED
61#include <qcoreapplication.h>
62#else
63// This specialization of Q_DECLARE_TR_FUNCTIONS is not in qcoreapplication.h,
64// because that header depends on QObject being available, which is not the
65// case for most bootstrapped applications.
66#define Q_DECLARE_TR_FUNCTIONS(context) \
67public: \
68 static inline QString tr(const char *sourceText, const char *comment = 0) \
69 { Q_UNUSED(comment); return QString::fromLatin1(sourceText); } \
70 static inline QString trUtf8(const char *sourceText, const char *comment = 0) \
71 { Q_UNUSED(comment); return QString::fromLatin1(sourceText); } \
72 static inline QString tr(const char *sourceText, const char*, int) \
73 { return QString::fromLatin1(sourceText); } \
74 static inline QString trUtf8(const char *sourceText, const char*, int) \
75 { return QString::fromLatin1(sourceText); } \
76private:
77#endif
78QT_BEGIN_NAMESPACE
79
80#include "qxmlstream_p.h"
81
82/*!
83 \enum QXmlStreamReader::TokenType
84
85 This enum specifies the type of token the reader just read.
86
87 \value NoToken The reader has not yet read anything.
88
89 \value Invalid An error has occurred, reported in error() and
90 errorString().
91
92 \value StartDocument The reader reports the XML version number in
93 documentVersion(), and the encoding as specified in the XML
94 document in documentEncoding(). If the document is declared
95 standalone, isStandaloneDocument() returns true; otherwise it
96 returns false.
97
98 \value EndDocument The reader reports the end of the document.
99
100 \value StartElement The reader reports the start of an element
101 with namespaceUri() and name(). Empty elements are also reported
102 as StartElement, followed directly by EndElement. The convenience
103 function readElementText() can be called to concatenate all
104 content until the corresponding EndElement. Attributes are
105 reported in attributes(), namespace declarations in
106 namespaceDeclarations().
107
108 \value EndElement The reader reports the end of an element with
109 namespaceUri() and name().
110
111 \value Characters The reader reports characters in text(). If the
112 characters are all white-space, isWhitespace() returns true. If
113 the characters stem from a CDATA section, isCDATA() returns true.
114
115 \value Comment The reader reports a comment in text().
116
117 \value DTD The reader reports a DTD in text(), notation
118 declarations in notationDeclarations(), and entity declarations in
119 entityDeclarations(). Details of the DTD declaration are reported
120 in in dtdName(), dtdPublicId(), and dtdSystemId().
121
122 \value EntityReference The reader reports an entity reference that
123 could not be resolved. The name of the reference is reported in
124 name(), the replacement text in text().
125
126 \value ProcessingInstruction The reader reports a processing
127 instruction in processingInstructionTarget() and
128 processingInstructionData().
129*/
130
131/*!
132 \enum QXmlStreamReader::ReadElementTextBehaviour
133
134 This enum specifies the different behaviours of readElementText().
135
136 \value ErrorOnUnexpectedElement Raise an UnexpectedElementError and return
137 what was read so far when a child element is encountered.
138
139 \value IncludeChildElements Recursively include the text from child elements.
140
141 \value SkipChildElements Skip child elements.
142
143 \since 4.6
144*/
145
146/*!
147 \enum QXmlStreamReader::Error
148
149 This enum specifies different error cases
150
151 \value NoError No error has occurred.
152
153 \value CustomError A custom error has been raised with
154 raiseError()
155
156 \value NotWellFormedError The parser internally raised an error
157 due to the read XML not being well-formed.
158
159 \value PrematureEndOfDocumentError The input stream ended before a
160 well-formed XML document was parsed. Recovery from this error is
161 possible if more XML arrives in the stream, either by calling
162 addData() or by waiting for it to arrive on the device().
163
164 \value UnexpectedElementError The parser encountered an element
165 that was different to those it expected.
166
167*/
168
169/*!
170 \class QXmlStreamEntityResolver
171 \reentrant
172 \since 4.4
173
174 \brief The QXmlStreamEntityResolver class provides an entity
175 resolver for a QXmlStreamReader.
176
177 \ingroup xml-tools
178 */
179
180/*!
181 Destroys the entity resolver.
182 */
183QXmlStreamEntityResolver::~QXmlStreamEntityResolver()
184{
185}
186
187/*! \internal
188
189This function is a stub for later functionality.
190*/
191QString QXmlStreamEntityResolver::resolveEntity(const QString& /*publicId*/, const QString& /*systemId*/)
192{
193 return QString();
194}
195
196
197/*!
198 Resolves the undeclared entity \a name and returns its replacement
199 text. If the entity is also unknown to the entity resolver, it
200 returns an empty string.
201
202 The default implementation always returns an empty string.
203*/
204
205QString QXmlStreamEntityResolver::resolveUndeclaredEntity(const QString &/*name*/)
206{
207 return QString();
208}
209
210#ifndef QT_NO_XMLSTREAMREADER
211
212QString QXmlStreamReaderPrivate::resolveUndeclaredEntity(const QString &name)
213{
214 if (entityResolver)
215 return entityResolver->resolveUndeclaredEntity(name);
216 return QString();
217}
218
219
220
221/*!
222 \since 4.4
223
224 Makes \a resolver the new entityResolver().
225
226 The stream reader does \e not take ownership of the resolver. It's
227 the callers responsibility to ensure that the resolver is valid
228 during the entire life-time of the stream reader object, or until
229 another resolver or 0 is set.
230
231 \sa entityResolver()
232 */
233void QXmlStreamReader::setEntityResolver(QXmlStreamEntityResolver *resolver)
234{
235 Q_D(QXmlStreamReader);
236 d->entityResolver = resolver;
237}
238
239/*!
240 \since 4.4
241
242 Returns the entity resolver, or 0 if there is no entity resolver.
243
244 \sa setEntityResolver()
245 */
246QXmlStreamEntityResolver *QXmlStreamReader::entityResolver() const
247{
248 Q_D(const QXmlStreamReader);
249 return d->entityResolver;
250}
251
252
253
254/*!
255 \class QXmlStreamReader
256 \reentrant
257 \since 4.3
258
259 \brief The QXmlStreamReader class provides a fast parser for reading
260 well-formed XML via a simple streaming API.
261
262
263 \ingroup xml-tools
264
265 QXmlStreamReader is a faster and more convenient replacement for
266 Qt's own SAX parser (see QXmlSimpleReader). In some cases it might
267 also be a faster and more convenient alternative for use in
268 applications that would otherwise use a DOM tree (see QDomDocument).
269 QXmlStreamReader reads data either from a QIODevice (see
270 setDevice()), or from a raw QByteArray (see addData()).
271
272 Qt provides QXmlStreamWriter for writing XML.
273
274 The basic concept of a stream reader is to report an XML document as
275 a stream of tokens, similar to SAX. The main difference between
276 QXmlStreamReader and SAX is \e how these XML tokens are reported.
277 With SAX, the application must provide handlers (callback functions)
278 that receive so-called XML \e events from the parser at the parser's
279 convenience. With QXmlStreamReader, the application code itself
280 drives the loop and pulls \e tokens from the reader, one after
281 another, as it needs them. This is done by calling readNext(), where
282 the reader reads from the input stream until it completes the next
283 token, at which point it returns the tokenType(). A set of
284 convenient functions including isStartElement() and text() can then
285 be used to examine the token to obtain information about what has
286 been read. The big advantage of this \e pulling approach is the
287 possibility to build recursive descent parsers with it, meaning you
288 can split your XML parsing code easily into different methods or
289 classes. This makes it easy to keep track of the application's own
290 state when parsing XML.
291
292 A typical loop with QXmlStreamReader looks like this:
293
294 \snippet doc/src/snippets/code/src_corelib_xml_qxmlstream.cpp 0
295
296
297 QXmlStreamReader is a well-formed XML 1.0 parser that does \e not
298 include external parsed entities. As long as no error occurs, the
299 application code can thus be assured that the data provided by the
300 stream reader satisfies the W3C's criteria for well-formed XML. For
301 example, you can be certain that all tags are indeed nested and
302 closed properly, that references to internal entities have been
303 replaced with the correct replacement text, and that attributes have
304 been normalized or added according to the internal subset of the
305 DTD.
306
307 If an error occurs while parsing, atEnd() and hasError() return
308 true, and error() returns the error that occurred. The functions
309 errorString(), lineNumber(), columnNumber(), and characterOffset()
310 are for constructing an appropriate error or warning message. To
311 simplify application code, QXmlStreamReader contains a raiseError()
312 mechanism that lets you raise custom errors that trigger the same
313 error handling described.
314
315 The \l{QXmlStream Bookmarks Example} illustrates how to use the
316 recursive descent technique to read an XML bookmark file (XBEL) with
317 a stream reader.
318
319 \section1 Namespaces
320
321 QXmlStream understands and resolves XML namespaces. E.g. in case of
322 a StartElement, namespaceUri() returns the namespace the element is
323 in, and name() returns the element's \e local name. The combination
324 of namespaceUri and name uniquely identifies an element. If a
325 namespace prefix was not declared in the XML entities parsed by the
326 reader, the namespaceUri is empty.
327
328 If you parse XML data that does not utilize namespaces according to
329 the XML specification or doesn't use namespaces at all, you can use
330 the element's qualifiedName() instead. A qualified name is the
331 element's prefix() followed by colon followed by the element's local
332 name() - exactly like the element appears in the raw XML data. Since
333 the mapping namespaceUri to prefix is neither unique nor universal,
334 qualifiedName() should be avoided for namespace-compliant XML data.
335
336 In order to parse standalone documents that do use undeclared
337 namespace prefixes, you can turn off namespace processing completely
338 with the \l namespaceProcessing property.
339
340 \section1 Incremental parsing
341
342 QXmlStreamReader is an incremental parser. It can handle the case
343 where the document can't be parsed all at once because it arrives in
344 chunks (e.g. from multiple files, or over a network connection).
345 When the reader runs out of data before the complete document has
346 been parsed, it reports a PrematureEndOfDocumentError. When more
347 data arrives, either because of a call to addData() or because more
348 data is available through the network device(), the reader recovers
349 from the PrematureEndOfDocumentError error and continues parsing the
350 new data with the next call to readNext().
351
352 For example, if your application reads data from the network using a
353 \l{QNetworkAccessManager} {network access manager}, you would issue
354 a \l{QNetworkRequest} {network request} to the manager and receive a
355 \l{QNetworkReply} {network reply} in return. Since a QNetworkReply
356 is a QIODevice, you connect its \l{QNetworkReply::readyRead()}
357 {readyRead()} signal to a custom slot, e.g. \c{slotReadyRead()} in
358 the code snippet shown in the discussion for QNetworkAccessManager.
359 In this slot, you read all available data with
360 \l{QNetworkReply::readAll()} {readAll()} and pass it to the XML
361 stream reader using addData(). Then you call your custom parsing
362 function that reads the XML events from the reader.
363
364 \section1 Performance and memory consumption
365
366 QXmlStreamReader is memory-conservative by design, since it doesn't
367 store the entire XML document tree in memory, but only the current
368 token at the time it is reported. In addition, QXmlStreamReader
369 avoids the many small string allocations that it normally takes to
370 map an XML document to a convenient and Qt-ish API. It does this by
371 reporting all string data as QStringRef rather than real QString
372 objects. QStringRef is a thin wrapper around QString substrings that
373 provides a subset of the QString API without the memory allocation
374 and reference-counting overhead. Calling
375 \l{QStringRef::toString()}{toString()} on any of those objects
376 returns an equivalent real QString object.
377
378*/
379
380
381/*!
382 Constructs a stream reader.
383
384 \sa setDevice(), addData()
385 */
386QXmlStreamReader::QXmlStreamReader()
387 : d_ptr(new QXmlStreamReaderPrivate(this))
388{
389}
390
391/*! Creates a new stream reader that reads from \a device.
392
393\sa setDevice(), clear()
394 */
395QXmlStreamReader::QXmlStreamReader(QIODevice *device)
396 : d_ptr(new QXmlStreamReaderPrivate(this))
397{
398 setDevice(device);
399}
400
401/*!
402 Creates a new stream reader that reads from \a data.
403
404 \sa addData(), clear(), setDevice()
405 */
406QXmlStreamReader::QXmlStreamReader(const QByteArray &data)
407 : d_ptr(new QXmlStreamReaderPrivate(this))
408{
409 Q_D(QXmlStreamReader);
410 d->dataBuffer = data;
411}
412
413/*!
414 Creates a new stream reader that reads from \a data.
415
416 \sa addData(), clear(), setDevice()
417 */
418QXmlStreamReader::QXmlStreamReader(const QString &data)
419 : d_ptr(new QXmlStreamReaderPrivate(this))
420{
421 Q_D(QXmlStreamReader);
422#ifdef QT_NO_TEXTCODEC
423 d->dataBuffer = data.toLatin1();
424#else
425 d->dataBuffer = d->codec->fromUnicode(data);
426 d->decoder = d->codec->makeDecoder();
427#endif
428 d->lockEncoding = true;
429
430}
431
432/*!
433 Creates a new stream reader that reads from \a data.
434
435 \sa addData(), clear(), setDevice()
436 */
437QXmlStreamReader::QXmlStreamReader(const char *data)
438 : d_ptr(new QXmlStreamReaderPrivate(this))
439{
440 Q_D(QXmlStreamReader);
441 d->dataBuffer = QByteArray(data);
442}
443
444/*!
445 Destructs the reader.
446 */
447QXmlStreamReader::~QXmlStreamReader()
448{
449 Q_D(QXmlStreamReader);
450 if (d->deleteDevice)
451 delete d->device;
452}
453
454/*! \fn bool QXmlStreamReader::hasError() const
455 Returns \c true if an error has occurred, otherwise \c false.
456
457 \sa errorString(), error()
458 */
459
460/*!
461 Sets the current device to \a device. Setting the device resets
462 the stream to its initial state.
463
464 \sa device(), clear()
465*/
466void QXmlStreamReader::setDevice(QIODevice *device)
467{
468 Q_D(QXmlStreamReader);
469 if (d->deleteDevice) {
470 delete d->device;
471 d->deleteDevice = false;
472 }
473 d->device = device;
474 d->init();
475
476}
477
478/*!
479 Returns the current device associated with the QXmlStreamReader,
480 or 0 if no device has been assigned.
481
482 \sa setDevice()
483*/
484QIODevice *QXmlStreamReader::device() const
485{
486 Q_D(const QXmlStreamReader);
487 return d->device;
488}
489
490
491/*!
492 Adds more \a data for the reader to read. This function does
493 nothing if the reader has a device().
494
495 \sa readNext(), clear()
496 */
497void QXmlStreamReader::addData(const QByteArray &data)
498{
499 Q_D(QXmlStreamReader);
500 if (d->device) {
501 qWarning("QXmlStreamReader: addData() with device()");
502 return;
503 }
504 d->dataBuffer += data;
505}
506
507/*!
508 Adds more \a data for the reader to read. This function does
509 nothing if the reader has a device().
510
511 \sa readNext(), clear()
512 */
513void QXmlStreamReader::addData(const QString &data)
514{
515 Q_D(QXmlStreamReader);
516 d->lockEncoding = true;
517#ifdef QT_NO_TEXTCODEC
518 addData(data.toLatin1());
519#else
520 addData(d->codec->fromUnicode(data));
521#endif
522}
523
524/*!
525 Adds more \a data for the reader to read. This function does
526 nothing if the reader has a device().
527
528 \sa readNext(), clear()
529 */
530void QXmlStreamReader::addData(const char *data)
531{
532 addData(QByteArray(data));
533}
534
535/*!
536 Removes any device() or data from the reader and resets its
537 internal state to the initial state.
538
539 \sa addData()
540 */
541void QXmlStreamReader::clear()
542{
543 Q_D(QXmlStreamReader);
544 d->init();
545 if (d->device) {
546 if (d->deleteDevice)
547 delete d->device;
548 d->device = 0;
549 }
550}
551
552/*!
553 Returns true if the reader has read until the end of the XML
554 document, or if an error() has occurred and reading has been
555 aborted. Otherwise, it returns false.
556
557 When atEnd() and hasError() return true and error() returns
558 PrematureEndOfDocumentError, it means the XML has been well-formed
559 so far, but a complete XML document has not been parsed. The next
560 chunk of XML can be added with addData(), if the XML is being read
561 from a QByteArray, or by waiting for more data to arrive if the
562 XML is being read from a QIODevice. Either way, atEnd() will
563 return false once more adata is available.
564
565 \sa hasError(), error(), device(), QIODevice::atEnd()
566 */
567bool QXmlStreamReader::atEnd() const
568{
569 Q_D(const QXmlStreamReader);
570 if (d->atEnd
571 && ((d->type == QXmlStreamReader::Invalid && d->error == PrematureEndOfDocumentError)
572 || (d->type == QXmlStreamReader::EndDocument))) {
573 if (d->device)
574 return d->device->atEnd();
575 else
576 return !d->dataBuffer.size();
577 }
578 return (d->atEnd || d->type == QXmlStreamReader::Invalid);
579}
580
581
582/*!
583 Reads the next token and returns its type.
584
585 With one exception, once an error() is reported by readNext(),
586 further reading of the XML stream is not possible. Then atEnd()
587 returns true, hasError() returns true, and this function returns
588 QXmlStreamReader::Invalid.
589
590 The exception is when error() returns PrematureEndOfDocumentError.
591 This error is reported when the end of an otherwise well-formed
592 chunk of XML is reached, but the chunk doesn't represent a complete
593 XML document. In that case, parsing \e can be resumed by calling
594 addData() to add the next chunk of XML, when the stream is being
595 read from a QByteArray, or by waiting for more data to arrive when
596 the stream is being read from a device().
597
598 \sa tokenType(), tokenString()
599 */
600QXmlStreamReader::TokenType QXmlStreamReader::readNext()
601{
602 Q_D(QXmlStreamReader);
603 if (d->type != Invalid) {
604 if (!d->hasCheckedStartDocument)
605 if (!d->checkStartDocument())
606 return d->type; // synthetic StartDocument or error
607 d->parse();
608 if (d->atEnd && d->type != EndDocument && d->type != Invalid)
609 d->raiseError(PrematureEndOfDocumentError);
610 else if (!d->atEnd && d->type == EndDocument)
611 d->raiseWellFormedError(QXmlStream::tr("Extra content at end of document."));
612 } else if (d->error == PrematureEndOfDocumentError) {
613 // resume error
614 d->type = NoToken;
615 d->atEnd = false;
616 d->token = -1;
617 return readNext();
618 }
619 return d->type;
620}
621
622
623/*!
624 Returns the type of the current token.
625
626 The current token can also be queried with the convenience functions
627 isStartDocument(), isEndDocument(), isStartElement(),
628 isEndElement(), isCharacters(), isComment(), isDTD(),
629 isEntityReference(), and isProcessingInstruction().
630
631 \sa tokenString()
632 */
633QXmlStreamReader::TokenType QXmlStreamReader::tokenType() const
634{
635 Q_D(const QXmlStreamReader);
636 return d->type;
637}
638
639/*!
640 Reads until the next start element within the current element. Returns true
641 when a start element was reached. When the end element was reached, or when
642 an error occurred, false is returned.
643
644 The current element is the element matching the most recently parsed start
645 element of which a matching end element has not yet been reached. When the
646 parser has reached the end element, the current element becomes the parent
647 element.
648
649 This is a convenience function for when you're only concerned with parsing
650 XML elements. The \l{QXmlStream Bookmarks Example} makes extensive use of
651 this function.
652
653 \since 4.6
654 \sa readNext()
655 */
656bool QXmlStreamReader::readNextStartElement()
657{
658 while (readNext() != Invalid) {
659 if (isEndElement())
660 return false;
661 else if (isStartElement())
662 return true;
663 }
664 return false;
665}
666
667/*!
668 Reads until the end of the current element, skipping any child nodes.
669 This function is useful for skipping unknown elements.
670
671 The current element is the element matching the most recently parsed start
672 element of which a matching end element has not yet been reached. When the
673 parser has reached the end element, the current element becomes the parent
674 element.
675
676 \since 4.6
677 */
678void QXmlStreamReader::skipCurrentElement()
679{
680 int depth = 1;
681 while (depth && readNext() != Invalid) {
682 if (isEndElement())
683 --depth;
684 else if (isStartElement())
685 ++depth;
686 }
687}
688
689/*
690 * Use the following Perl script to generate the error string index list:
691===== PERL SCRIPT ====
692print "static const char QXmlStreamReader_tokenTypeString_string[] =\n";
693$counter = 0;
694$i = 0;
695while (<STDIN>) {
696 chomp;
697 print " \"$_\\0\"\n";
698 $sizes[$i++] = $counter;
699 $counter += length 1 + $_;
700}
701print " \"\\0\";\n\nstatic const short QXmlStreamReader_tokenTypeString_indices[] = {\n ";
702for ($j = 0; $j < $i; ++$j) {
703 printf "$sizes[$j], ";
704}
705print "0\n};\n";
706===== PERL SCRIPT ====
707
708 * The input data is as follows (copied from qxmlstream.h):
709NoToken
710Invalid
711StartDocument
712EndDocument
713StartElement
714EndElement
715Characters
716Comment
717DTD
718EntityReference
719ProcessingInstruction
720*/
721static const char QXmlStreamReader_tokenTypeString_string[] =
722 "NoToken\0"
723 "Invalid\0"
724 "StartDocument\0"
725 "EndDocument\0"
726 "StartElement\0"
727 "EndElement\0"
728 "Characters\0"
729 "Comment\0"
730 "DTD\0"
731 "EntityReference\0"
732 "ProcessingInstruction\0";
733
734static const short QXmlStreamReader_tokenTypeString_indices[] = {
735 0, 8, 16, 30, 42, 55, 66, 77, 85, 89, 105, 0
736};
737
738
739/*!
740 \property QXmlStreamReader::namespaceProcessing
741 the namespace-processing flag of the stream reader
742
743 This property controls whether or not the stream reader processes
744 namespaces. If enabled, the reader processes namespaces, otherwise
745 it does not.
746
747 By default, namespace-processing is enabled.
748*/
749
750
751void QXmlStreamReader::setNamespaceProcessing(bool enable)
752{
753 Q_D(QXmlStreamReader);
754 d->namespaceProcessing = enable;
755}
756
757bool QXmlStreamReader::namespaceProcessing() const
758{
759 Q_D(const QXmlStreamReader);
760 return d->namespaceProcessing;
761}
762
763/*! Returns the reader's current token as string.
764
765\sa tokenType()
766*/
767QString QXmlStreamReader::tokenString() const
768{
769 Q_D(const QXmlStreamReader);
770 return QLatin1String(QXmlStreamReader_tokenTypeString_string +
771 QXmlStreamReader_tokenTypeString_indices[d->type]);
772}
773
774#endif // QT_NO_XMLSTREAMREADER
775
776QXmlStreamPrivateTagStack::QXmlStreamPrivateTagStack()
777{
778 tagStack.reserve(16);
779 tagStackStringStorage.reserve(32);
780 tagStackStringStorageSize = 0;
781 NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.push();
782 namespaceDeclaration.prefix = addToStringStorage(QLatin1String("xml"));
783 namespaceDeclaration.namespaceUri = addToStringStorage(QLatin1String("http://www.w3.org/XML/1998/namespace"));
784}
785
786#ifndef QT_NO_XMLSTREAMREADER
787
788QXmlStreamReaderPrivate::QXmlStreamReaderPrivate(QXmlStreamReader *q)
789 :q_ptr(q)
790{
791 device = 0;
792 deleteDevice = false;
793#ifndef QT_NO_TEXTCODEC
794 decoder = 0;
795#endif
796 stack_size = 64;
797 sym_stack = 0;
798 state_stack = 0;
799 reallocateStack();
800 entityResolver = 0;
801 init();
802 entityHash.insert(QLatin1String("lt"), Entity::createLiteral(QLatin1String("<")));
803 entityHash.insert(QLatin1String("gt"), Entity::createLiteral(QLatin1String(">")));
804 entityHash.insert(QLatin1String("amp"), Entity::createLiteral(QLatin1String("&")));
805 entityHash.insert(QLatin1String("apos"), Entity::createLiteral(QLatin1String("'")));
806 entityHash.insert(QLatin1String("quot"), Entity::createLiteral(QLatin1String("\"")));
807}
808
809void QXmlStreamReaderPrivate::init()
810{
811 tos = 0;
812 scanDtd = false;
813 token = -1;
814 token_char = 0;
815 isEmptyElement = false;
816 isWhitespace = true;
817 isCDATA = false;
818 standalone = false;
819 tos = 0;
820 resumeReduction = 0;
821 state_stack[tos++] = 0;
822 state_stack[tos] = 0;
823 putStack.clear();
824 putStack.reserve(32);
825 textBuffer.clear();
826 textBuffer.reserve(256);
827 tagStack.clear();
828 tagsDone = false;
829 attributes.clear();
830 attributes.reserve(16);
831 lineNumber = lastLineStart = characterOffset = 0;
832 readBufferPos = 0;
833 nbytesread = 0;
834#ifndef QT_NO_TEXTCODEC
835 codec = QTextCodec::codecForMib(106); // utf8
836 delete decoder;
837 decoder = 0;
838#endif
839 attributeStack.clear();
840 attributeStack.reserve(16);
841 entityParser = 0;
842 hasCheckedStartDocument = false;
843 normalizeLiterals = false;
844 hasSeenTag = false;
845 atEnd = false;
846 inParseEntity = false;
847 referenceToUnparsedEntityDetected = false;
848 referenceToParameterEntityDetected = false;
849 hasExternalDtdSubset = false;
850 lockEncoding = false;
851 namespaceProcessing = true;
852 rawReadBuffer.clear();
853 dataBuffer.clear();
854 readBuffer.clear();
855
856 type = QXmlStreamReader::NoToken;
857 error = QXmlStreamReader::NoError;
858}
859
860/*
861 Well-formed requires that we verify entity values. We do this with a
862 standard parser.
863 */
864void QXmlStreamReaderPrivate::parseEntity(const QString &value)
865{
866 Q_Q(QXmlStreamReader);
867
868 if (value.isEmpty())
869 return;
870
871
872 if (!entityParser)
873 entityParser = new QXmlStreamReaderPrivate(q);
874 else
875 entityParser->init();
876 entityParser->inParseEntity = true;
877 entityParser->readBuffer = value;
878 entityParser->injectToken(PARSE_ENTITY);
879 while (!entityParser->atEnd && entityParser->type != QXmlStreamReader::Invalid)
880 entityParser->parse();
881 if (entityParser->type == QXmlStreamReader::Invalid || entityParser->tagStack.size())
882 raiseWellFormedError(QXmlStream::tr("Invalid entity value."));
883
884}
885
886inline void QXmlStreamReaderPrivate::reallocateStack()
887{
888 stack_size <<= 1;
889 sym_stack = reinterpret_cast<Value*> (qRealloc(sym_stack, stack_size * sizeof(Value)));
890 Q_CHECK_PTR(sym_stack);
891 state_stack = reinterpret_cast<int*> (qRealloc(state_stack, stack_size * sizeof(int)));
892 Q_CHECK_PTR(sym_stack);
893}
894
895
896QXmlStreamReaderPrivate::~QXmlStreamReaderPrivate()
897{
898#ifndef QT_NO_TEXTCODEC
899 delete decoder;
900#endif
901 qFree(sym_stack);
902 qFree(state_stack);
903 delete entityParser;
904}
905
906
907inline uint QXmlStreamReaderPrivate::filterCarriageReturn()
908{
909 uint peekc = peekChar();
910 if (peekc == '\n') {
911 if (putStack.size())
912 putStack.pop();
913 else
914 ++readBufferPos;
915 return peekc;
916 }
917 if (peekc == 0) {
918 putChar('\r');
919 return 0;
920 }
921 return '\n';
922}
923
924/*!
925 \internal
926 If the end of the file is encountered, 0 is returned.
927 */
928inline uint QXmlStreamReaderPrivate::getChar()
929{
930 uint c;
931 if (putStack.size()) {
932 c = atEnd ? 0 : putStack.pop();
933 } else {
934 if (readBufferPos < readBuffer.size())
935 c = readBuffer.at(readBufferPos++).unicode();
936 else
937 c = getChar_helper();
938 }
939
940 return c;
941}
942
943inline uint QXmlStreamReaderPrivate::peekChar()
944{
945 uint c;
946 if (putStack.size()) {
947 c = putStack.top();
948 } else if (readBufferPos < readBuffer.size()) {
949 c = readBuffer.at(readBufferPos).unicode();
950 } else {
951 if ((c = getChar_helper()))
952 --readBufferPos;
953 }
954
955 return c;
956}
957
958/*!
959 \internal
960
961 Scans characters until \a str is encountered, and validates the characters
962 as according to the Char[2] production and do the line-ending normalization.
963 If any character is invalid, false is returned, otherwise true upon success.
964
965 If \a tokenToInject is not less than zero, injectToken() is called with
966 \a tokenToInject when \a str is found.
967
968 If any error occurred, false is returned, otherwise true.
969 */
970bool QXmlStreamReaderPrivate::scanUntil(const char *str, short tokenToInject)
971{
972 int pos = textBuffer.size();
973 int oldLineNumber = lineNumber;
974
975 while (uint c = getChar()) {
976 /* First, we do the validation & normalization. */
977 switch (c) {
978 case '\r':
979 if ((c = filterCarriageReturn()) == 0)
980 break;
981 // fall through
982 case '\n':
983 ++lineNumber;
984 lastLineStart = characterOffset + readBufferPos;
985 // fall through
986 case '\t':
987 textBuffer += QChar(c);
988 continue;
989 default:
990 if(c < 0x20 || (c > 0xFFFD && c < 0x10000) || c > 0x10FFFF ) {
991 raiseWellFormedError(QXmlStream::tr("Invalid XML character."));
992 lineNumber = oldLineNumber;
993 return false;
994 }
995 textBuffer += QChar(c);
996 }
997
998
999 /* Second, attempt to lookup str. */
1000 if (c == uint(*str)) {
1001 if (!*(str + 1)) {
1002 if (tokenToInject >= 0)
1003 injectToken(tokenToInject);
1004 return true;
1005 } else {
1006 if (scanString(str + 1, tokenToInject, false))
1007 return true;
1008 }
1009 }
1010 }
1011 putString(textBuffer, pos);
1012 textBuffer.resize(pos);
1013 lineNumber = oldLineNumber;
1014 return false;
1015}
1016
1017bool QXmlStreamReaderPrivate::scanString(const char *str, short tokenToInject, bool requireSpace)
1018{
1019 int n = 0;
1020 while (str[n]) {
1021 ushort c = getChar();
1022 if (c != ushort(str[n])) {
1023 if (c)
1024 putChar(c);
1025 while (n--) {
1026 putChar(ushort(str[n]));
1027 }
1028 return false;
1029 }
1030 ++n;
1031 }
1032 for (int i = 0; i < n; ++i)
1033 textBuffer += QChar(ushort(str[i]));
1034 if (requireSpace) {
1035 int s = fastScanSpace();
1036 if (!s || atEnd) {
1037 int pos = textBuffer.size() - n - s;
1038 putString(textBuffer, pos);
1039 textBuffer.resize(pos);
1040 return false;
1041 }
1042 }
1043 if (tokenToInject >= 0)
1044 injectToken(tokenToInject);
1045 return true;
1046}
1047
1048bool QXmlStreamReaderPrivate::scanAfterLangleBang()
1049{
1050 switch (peekChar()) {
1051 case '[':
1052 return scanString(spell[CDATA_START], CDATA_START, false);
1053 case 'D':
1054 return scanString(spell[DOCTYPE], DOCTYPE);
1055 case 'A':
1056 return scanString(spell[ATTLIST], ATTLIST);
1057 case 'N':
1058 return scanString(spell[NOTATION], NOTATION);
1059 case 'E':
1060 if (scanString(spell[ELEMENT], ELEMENT))
1061 return true;
1062 return scanString(spell[ENTITY], ENTITY);
1063
1064 default:
1065 ;
1066 };
1067 return false;
1068}
1069
1070bool QXmlStreamReaderPrivate::scanPublicOrSystem()
1071{
1072 switch (peekChar()) {
1073 case 'S':
1074 return scanString(spell[SYSTEM], SYSTEM);
1075 case 'P':
1076 return scanString(spell[PUBLIC], PUBLIC);
1077 default:
1078 ;
1079 }
1080 return false;
1081}
1082
1083bool QXmlStreamReaderPrivate::scanNData()
1084{
1085 if (fastScanSpace()) {
1086 if (scanString(spell[NDATA], NDATA))
1087 return true;
1088 putChar(' ');
1089 }
1090 return false;
1091}
1092
1093bool QXmlStreamReaderPrivate::scanAfterDefaultDecl()
1094{
1095 switch (peekChar()) {
1096 case 'R':
1097 return scanString(spell[REQUIRED], REQUIRED, false);
1098 case 'I':
1099 return scanString(spell[IMPLIED], IMPLIED, false);
1100 case 'F':
1101 return scanString(spell[FIXED], FIXED, false);
1102 default:
1103 ;
1104 }
1105 return false;
1106}
1107
1108bool QXmlStreamReaderPrivate::scanAttType()
1109{
1110 switch (peekChar()) {
1111 case 'C':
1112 return scanString(spell[CDATA], CDATA);
1113 case 'I':
1114 if (scanString(spell[ID], ID))
1115 return true;
1116 if (scanString(spell[IDREF], IDREF))
1117 return true;
1118 return scanString(spell[IDREFS], IDREFS);
1119 case 'E':
1120 if (scanString(spell[ENTITY], ENTITY))
1121 return true;
1122 return scanString(spell[ENTITIES], ENTITIES);
1123 case 'N':
1124 if (scanString(spell[NOTATION], NOTATION))
1125 return true;
1126 if (scanString(spell[NMTOKEN], NMTOKEN))
1127 return true;
1128 return scanString(spell[NMTOKENS], NMTOKENS);
1129 default:
1130 ;
1131 }
1132 return false;
1133}
1134
1135/*!
1136 \internal
1137
1138 Scan strings with quotes or apostrophes surround them. For instance,
1139 attributes, the version and encoding field in the XML prolog and
1140 entity declarations.
1141
1142 If normalizeLiterals is set to true, the function also normalizes
1143 whitespace. It is set to true when the first start tag is
1144 encountered.
1145
1146 */
1147inline int QXmlStreamReaderPrivate::fastScanLiteralContent()
1148{
1149 int n = 0;
1150 uint c;
1151 while ((c = getChar())) {
1152 switch (ushort(c)) {
1153 case 0xfffe:
1154 case 0xffff:
1155 case 0:
1156 /* The putChar() call is necessary so the parser re-gets
1157 * the character from the input source, when raising an error. */
1158 putChar(c);
1159 return n;
1160 case '\r':
1161 if (filterCarriageReturn() == 0)
1162 return n;
1163 // fall through
1164 case '\n':
1165 ++lineNumber;
1166 lastLineStart = characterOffset + readBufferPos;
1167 // fall through
1168 case ' ':
1169 case '\t':
1170 if (normalizeLiterals)
1171 textBuffer += QLatin1Char(' ');
1172 else
1173 textBuffer += QChar(c);
1174 ++n;
1175 break;
1176 case '&':
1177 case '<':
1178 case '\"':
1179 case '\'':
1180 if (!(c & 0xff0000)) {
1181 putChar(c);
1182 return n;
1183 }
1184 // fall through
1185 default:
1186 textBuffer += QChar(c);
1187 ++n;
1188 }
1189 }
1190 return n;
1191}
1192
1193inline int QXmlStreamReaderPrivate::fastScanSpace()
1194{
1195 int n = 0;
1196 ushort c;
1197 while ((c = getChar())) {
1198 switch (c) {
1199 case '\r':
1200 if ((c = filterCarriageReturn()) == 0)
1201 return n;
1202 // fall through
1203 case '\n':
1204 ++lineNumber;
1205 lastLineStart = characterOffset + readBufferPos;
1206 // fall through
1207 case ' ':
1208 case '\t':
1209 textBuffer += QChar(c);
1210 ++n;
1211 break;
1212 default:
1213 putChar(c);
1214 return n;
1215 }
1216 }
1217 return n;
1218}
1219
1220/*!
1221 \internal
1222
1223 Used for text nodes essentially. That is, characters appearing
1224 inside elements.
1225 */
1226inline int QXmlStreamReaderPrivate::fastScanContentCharList()
1227{
1228 int n = 0;
1229 uint c;
1230 while ((c = getChar())) {
1231 switch (ushort(c)) {
1232 case 0xfffe:
1233 case 0xffff:
1234 case 0:
1235 putChar(c);
1236 return n;
1237 case ']': {
1238 isWhitespace = false;
1239 int pos = textBuffer.size();
1240 textBuffer += QChar(ushort(c));
1241 ++n;
1242 while ((c = getChar()) == ']') {
1243 textBuffer += QChar(ushort(c));
1244 ++n;
1245 }
1246 if (c == 0) {
1247 putString(textBuffer, pos);
1248 textBuffer.resize(pos);
1249 } else if (c == '>' && textBuffer.at(textBuffer.size()-2) == QLatin1Char(']')) {
1250 raiseWellFormedError(QXmlStream::tr("Sequence ']]>' not allowed in content."));
1251 } else {
1252 putChar(c);
1253 break;
1254 }
1255 return n;
1256 } break;
1257 case '\r':
1258 if ((c = filterCarriageReturn()) == 0)
1259 return n;
1260 // fall through
1261 case '\n':
1262 ++lineNumber;
1263 lastLineStart = characterOffset + readBufferPos;
1264 // fall through
1265 case ' ':
1266 case '\t':
1267 textBuffer += QChar(ushort(c));
1268 ++n;
1269 break;
1270 case '&':
1271 case '<':
1272 if (!(c & 0xff0000)) {
1273 putChar(c);
1274 return n;
1275 }
1276 // fall through
1277 default:
1278 if (c < 0x20) {
1279 putChar(c);
1280 return n;
1281 }
1282 isWhitespace = false;
1283 textBuffer += QChar(ushort(c));
1284 ++n;
1285 }
1286 }
1287 return n;
1288}
1289
1290inline int QXmlStreamReaderPrivate::fastScanName(int *prefix)
1291{
1292 int n = 0;
1293 ushort c;
1294 while ((c = getChar())) {
1295 switch (c) {
1296 case '\n':
1297 case ' ':
1298 case '\t':
1299 case '\r':
1300 case '&':
1301 case '#':
1302 case '\'':
1303 case '\"':
1304 case '<':
1305 case '>':
1306 case '[':
1307 case ']':
1308 case '=':
1309 case '%':
1310 case '/':
1311 case ';':
1312 case '?':
1313 case '!':
1314 case '^':
1315 case '|':
1316 case ',':
1317 case '(':
1318 case ')':
1319 case '+':
1320 case '*':
1321 putChar(c);
1322 if (prefix && *prefix == n+1) {
1323 *prefix = 0;
1324 putChar(':');
1325 --n;
1326 }
1327 return n;
1328 case ':':
1329 if (prefix) {
1330 if (*prefix == 0) {
1331 *prefix = n+2;
1332 } else { // only one colon allowed according to the namespace spec.
1333 putChar(c);
1334 return n;
1335 }
1336 } else {
1337 putChar(c);
1338 return n;
1339 }
1340 // fall through
1341 default:
1342 textBuffer += QChar(c);
1343 ++n;
1344 }
1345 }
1346
1347 if (prefix)
1348 *prefix = 0;
1349 int pos = textBuffer.size() - n;
1350 putString(textBuffer, pos);
1351 textBuffer.resize(pos);
1352 return 0;
1353}
1354
1355enum NameChar { NameBeginning, NameNotBeginning, NotName };
1356
1357static const char Begi = static_cast<char>(NameBeginning);
1358static const char NtBg = static_cast<char>(NameNotBeginning);
1359static const char NotN = static_cast<char>(NotName);
1360
1361static const char nameCharTable[128] =
1362{
1363// 0x00
1364 NotN, NotN, NotN, NotN, NotN, NotN, NotN, NotN,
1365 NotN, NotN, NotN, NotN, NotN, NotN, NotN, NotN,
1366// 0x10
1367 NotN, NotN, NotN, NotN, NotN, NotN, NotN, NotN,
1368 NotN, NotN, NotN, NotN, NotN, NotN, NotN, NotN,
1369// 0x20 (0x2D is '-', 0x2E is '.')
1370 NotN, NotN, NotN, NotN, NotN, NotN, NotN, NotN,
1371 NotN, NotN, NotN, NotN, NotN, NtBg, NtBg, NotN,
1372// 0x30 (0x30..0x39 are '0'..'9', 0x3A is ':')
1373 NtBg, NtBg, NtBg, NtBg, NtBg, NtBg, NtBg, NtBg,
1374 NtBg, NtBg, Begi, NotN, NotN, NotN, NotN, NotN,
1375// 0x40 (0x41..0x5A are 'A'..'Z')
1376 NotN, Begi, Begi, Begi, Begi, Begi, Begi, Begi,
1377 Begi, Begi, Begi, Begi, Begi, Begi, Begi, Begi,
1378// 0x50 (0x5F is '_')
1379 Begi, Begi, Begi, Begi, Begi, Begi, Begi, Begi,
1380 Begi, Begi, Begi, NotN, NotN, NotN, NotN, Begi,
1381// 0x60 (0x61..0x7A are 'a'..'z')
1382 NotN, Begi, Begi, Begi, Begi, Begi, Begi, Begi,
1383 Begi, Begi, Begi, Begi, Begi, Begi, Begi, Begi,
1384// 0x70
1385 Begi, Begi, Begi, Begi, Begi, Begi, Begi, Begi,
1386 Begi, Begi, Begi, NotN, NotN, NotN, NotN, NotN
1387};
1388
1389static inline NameChar fastDetermineNameChar(QChar ch)
1390{
1391 ushort uc = ch.unicode();
1392 if (!(uc & ~0x7f)) // uc < 128
1393 return static_cast<NameChar>(nameCharTable[uc]);
1394
1395 QChar::Category cat = ch.category();
1396 // ### some these categories might be slightly wrong
1397 if ((cat >= QChar::Letter_Uppercase && cat <= QChar::Letter_Other)
1398 || cat == QChar::Number_Letter)
1399 return NameBeginning;
1400 if ((cat >= QChar::Number_DecimalDigit && cat <= QChar::Number_Other)
1401 || (cat >= QChar::Mark_NonSpacing && cat <= QChar::Mark_Enclosing))
1402 return NameNotBeginning;
1403 return NotName;
1404}
1405
1406inline int QXmlStreamReaderPrivate::fastScanNMTOKEN()
1407{
1408 int n = 0;
1409 uint c;
1410 while ((c = getChar())) {
1411 if (fastDetermineNameChar(c) == NotName) {
1412 putChar(c);
1413 return n;
1414 } else {
1415 ++n;
1416 textBuffer += QChar(c);
1417 }
1418 }
1419
1420 int pos = textBuffer.size() - n;
1421 putString(textBuffer, pos);
1422 textBuffer.resize(pos);
1423
1424 return n;
1425}
1426
1427void QXmlStreamReaderPrivate::putString(const QString &s, int from)
1428{
1429 putStack.reserve(s.size());
1430 for (int i = s.size()-1; i >= from; --i)
1431 putStack.rawPush() = s.at(i).unicode();
1432}
1433
1434void QXmlStreamReaderPrivate::putStringLiteral(const QString &s)
1435{
1436 putStack.reserve(s.size());
1437 for (int i = s.size()-1; i >= 0; --i)
1438 putStack.rawPush() = ((LETTER << 16) | s.at(i).unicode());
1439}
1440
1441void QXmlStreamReaderPrivate::putReplacement(const QString &s)
1442{
1443 putStack.reserve(s.size());
1444 for (int i = s.size()-1; i >= 0; --i) {
1445 ushort c = s.at(i).unicode();
1446 if (c == '\n' || c == '\r')
1447 putStack.rawPush() = ((LETTER << 16) | c);
1448 else
1449 putStack.rawPush() = c;
1450 }
1451}
1452void QXmlStreamReaderPrivate::putReplacementInAttributeValue(const QString &s)
1453{
1454 putStack.reserve(s.size());
1455 for (int i = s.size()-1; i >= 0; --i) {
1456 ushort c = s.at(i).unicode();
1457 if (c == '&' || c == ';')
1458 putStack.rawPush() = c;
1459 else if (c == '\n' || c == '\r')
1460 putStack.rawPush() = ' ';
1461 else
1462 putStack.rawPush() = ((LETTER << 16) | c);
1463 }
1464}
1465
1466ushort QXmlStreamReaderPrivate::getChar_helper()
1467{
1468 const int BUFFER_SIZE = 8192;
1469 characterOffset += readBufferPos;
1470 readBufferPos = 0;
1471 readBuffer.resize(0);
1472#ifndef QT_NO_TEXTCODEC
1473 if (decoder)
1474#endif
1475 nbytesread = 0;
1476 if (device) {
1477 rawReadBuffer.resize(BUFFER_SIZE);
1478 int nbytesreadOrMinus1 = device->read(rawReadBuffer.data() + nbytesread, BUFFER_SIZE - nbytesread);
1479 nbytesread += qMax(nbytesreadOrMinus1, 0);
1480 } else {
1481 if (nbytesread)
1482 rawReadBuffer += dataBuffer;
1483 else
1484 rawReadBuffer = dataBuffer;
1485 nbytesread = rawReadBuffer.size();
1486 dataBuffer.clear();
1487 }
1488 if (!nbytesread) {
1489 atEnd = true;
1490 return 0;
1491 }
1492
1493#ifndef QT_NO_TEXTCODEC
1494 if (!decoder) {
1495 if (nbytesread < 4) { // the 4 is to cover 0xef 0xbb 0xbf plus
1496 // one extra for the utf8 codec
1497 atEnd = true;
1498 return 0;
1499 }
1500 int mib = 106; // UTF-8
1501
1502 // look for byte order mark
1503 uchar ch1 = rawReadBuffer.at(0);
1504 uchar ch2 = rawReadBuffer.at(1);
1505 uchar ch3 = rawReadBuffer.at(2);
1506 uchar ch4 = rawReadBuffer.at(3);
1507
1508 if ((ch1 == 0 && ch2 == 0 && ch3 == 0xfe && ch4 == 0xff) ||
1509 (ch1 == 0xff && ch2 == 0xfe && ch3 == 0 && ch4 == 0))
1510 mib = 1017; // UTF-32 with byte order mark
1511 else if (ch1 == 0x3c && ch2 == 0x00 && ch3 == 0x00 && ch4 == 0x00)
1512 mib = 1019; // UTF-32LE
1513 else if (ch1 == 0x00 && ch2 == 0x00 && ch3 == 0x00 && ch4 == 0x3c)
1514 mib = 1018; // UTF-32BE
1515 else if ((ch1 == 0xfe && ch2 == 0xff) || (ch1 == 0xff && ch2 == 0xfe))
1516 mib = 1015; // UTF-16 with byte order mark
1517 else if (ch1 == 0x3c && ch2 == 0x00)
1518 mib = 1014; // UTF-16LE
1519 else if (ch1 == 0x00 && ch2 == 0x3c)
1520 mib = 1013; // UTF-16BE
1521 codec = QTextCodec::codecForMib(mib);
1522 Q_ASSERT(codec);
1523 decoder = codec->makeDecoder();
1524 }
1525
1526 decoder->toUnicode(&readBuffer, rawReadBuffer.data(), nbytesread);
1527
1528 if(lockEncoding && decoder->hasFailure()) {
1529 raiseWellFormedError(QXmlStream::tr("Encountered incorrectly encoded content."));
1530 readBuffer.clear();
1531 return 0;
1532 }
1533#else
1534 readBuffer = QString::fromLatin1(rawReadBuffer.data(), nbytesread);
1535#endif // QT_NO_TEXTCODEC
1536
1537 readBuffer.reserve(1); // keep capacity when calling resize() next time
1538
1539 if (readBufferPos < readBuffer.size()) {
1540 ushort c = readBuffer.at(readBufferPos++).unicode();
1541 return c;
1542 }
1543
1544 atEnd = true;
1545 return 0;
1546}
1547
1548QStringRef QXmlStreamReaderPrivate::namespaceForPrefix(const QStringRef &prefix)
1549{
1550 for (int j = namespaceDeclarations.size() - 1; j >= 0; --j) {
1551 const NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.at(j);
1552 if (namespaceDeclaration.prefix == prefix) {
1553 return namespaceDeclaration.namespaceUri;
1554 }
1555 }
1556
1557#if 1
1558 if (namespaceProcessing && !prefix.isEmpty())
1559 raiseWellFormedError(QXmlStream::tr("Namespace prefix '%1' not declared").arg(prefix.toString()));
1560#endif
1561
1562 return QStringRef();
1563}
1564
1565/*
1566 uses namespaceForPrefix and builds the attribute vector
1567 */
1568void QXmlStreamReaderPrivate::resolveTag()
1569{
1570 int n = attributeStack.size();
1571
1572 if (namespaceProcessing) {
1573 for (int a = 0; a < dtdAttributes.size(); ++a) {
1574 DtdAttribute &dtdAttribute = dtdAttributes[a];
1575 if (!dtdAttribute.isNamespaceAttribute
1576 || dtdAttribute.defaultValue.isNull()
1577 || dtdAttribute.tagName != qualifiedName
1578 || dtdAttribute.attributeQualifiedName.isNull())
1579 continue;
1580 int i = 0;
1581 while (i < n && symName(attributeStack[i].key) != dtdAttribute.attributeQualifiedName)
1582 ++i;
1583 if (i != n)
1584 continue;
1585 if (dtdAttribute.attributePrefix.isEmpty() && dtdAttribute.attributeName == QLatin1String("xmlns")) {
1586 NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.push();
1587 namespaceDeclaration.prefix.clear();
1588
1589 const QStringRef ns(dtdAttribute.defaultValue);
1590 if(ns == QLatin1String("http://www.w3.org/2000/xmlns/") ||
1591 ns == QLatin1String("http://www.w3.org/XML/1998/namespace"))
1592 raiseWellFormedError(QXmlStream::tr("Illegal namespace declaration."));
1593 else
1594 namespaceDeclaration.namespaceUri = ns;
1595 } else if (dtdAttribute.attributePrefix == QLatin1String("xmlns")) {
1596 NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.push();
1597 QStringRef namespacePrefix = dtdAttribute.attributeName;
1598 QStringRef namespaceUri = dtdAttribute.defaultValue;
1599 if (((namespacePrefix == QLatin1String("xml"))
1600 ^ (namespaceUri == QLatin1String("http://www.w3.org/XML/1998/namespace")))
1601 || namespaceUri == QLatin1String("http://www.w3.org/2000/xmlns/")
1602 || namespaceUri.isEmpty()
1603 || namespacePrefix == QLatin1String("xmlns"))
1604 raiseWellFormedError(QXmlStream::tr("Illegal namespace declaration."));
1605
1606 namespaceDeclaration.prefix = namespacePrefix;
1607 namespaceDeclaration.namespaceUri = namespaceUri;
1608 }
1609 }
1610 }
1611
1612 tagStack.top().namespaceDeclaration.namespaceUri = namespaceUri = namespaceForPrefix(prefix);
1613
1614 attributes.resize(n);
1615
1616 for (int i = 0; i < n; ++i) {
1617 QXmlStreamAttribute &attribute = attributes[i];
1618 Attribute &attrib = attributeStack[i];
1619 QStringRef prefix(symPrefix(attrib.key));
1620 QStringRef name(symString(attrib.key));
1621 QStringRef qualifiedName(symName(attrib.key));
1622 QStringRef value(symString(attrib.value));
1623
1624 attribute.m_name = QXmlStreamStringRef(name);
1625 attribute.m_qualifiedName = QXmlStreamStringRef(qualifiedName);
1626 attribute.m_value = QXmlStreamStringRef(value);
1627
1628 if (!prefix.isEmpty()) {
1629 QStringRef attributeNamespaceUri = namespaceForPrefix(prefix);
1630 attribute.m_namespaceUri = QXmlStreamStringRef(attributeNamespaceUri);
1631 }
1632
1633 for (int j = 0; j < i; ++j) {
1634 if (attributes[j].name() == attribute.name()
1635 && attributes[j].namespaceUri() == attribute.namespaceUri()
1636 && (namespaceProcessing || attributes[j].qualifiedName() == attribute.qualifiedName()))
1637 raiseWellFormedError(QXmlStream::tr("Attribute redefined."));
1638 }
1639 }
1640
1641 for (int a = 0; a < dtdAttributes.size(); ++a) {
1642 DtdAttribute &dtdAttribute = dtdAttributes[a];
1643 if (dtdAttribute.isNamespaceAttribute
1644 || dtdAttribute.defaultValue.isNull()
1645 || dtdAttribute.tagName != qualifiedName
1646 || dtdAttribute.attributeQualifiedName.isNull())
1647 continue;
1648 int i = 0;
1649 while (i < n && symName(attributeStack[i].key) != dtdAttribute.attributeQualifiedName)
1650 ++i;
1651 if (i != n)
1652 continue;
1653
1654
1655
1656 QXmlStreamAttribute attribute;
1657 attribute.m_name = QXmlStreamStringRef(dtdAttribute.attributeName);
1658 attribute.m_qualifiedName = QXmlStreamStringRef(dtdAttribute.attributeQualifiedName);
1659 attribute.m_value = QXmlStreamStringRef(dtdAttribute.defaultValue);
1660
1661 if (!dtdAttribute.attributePrefix.isEmpty()) {
1662 QStringRef attributeNamespaceUri = namespaceForPrefix(dtdAttribute.attributePrefix);
1663 attribute.m_namespaceUri = QXmlStreamStringRef(attributeNamespaceUri);
1664 }
1665 attribute.m_isDefault = true;
1666 attributes.append(attribute);
1667 }
1668
1669 attributeStack.clear();
1670}
1671
1672void QXmlStreamReaderPrivate::resolvePublicNamespaces()
1673{
1674 const Tag &tag = tagStack.top();
1675 int n = namespaceDeclarations.size() - tag.namespaceDeclarationsSize;
1676 publicNamespaceDeclarations.resize(n);
1677 for (int i = 0; i < n; ++i) {
1678 const NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.at(tag.namespaceDeclarationsSize + i);
1679 QXmlStreamNamespaceDeclaration &publicNamespaceDeclaration = publicNamespaceDeclarations[i];
1680 publicNamespaceDeclaration.m_prefix = QXmlStreamStringRef(namespaceDeclaration.prefix);
1681 publicNamespaceDeclaration.m_namespaceUri = QXmlStreamStringRef(namespaceDeclaration.namespaceUri);
1682 }
1683}
1684
1685void QXmlStreamReaderPrivate::resolveDtd()
1686{
1687 publicNotationDeclarations.resize(notationDeclarations.size());
1688 for (int i = 0; i < notationDeclarations.size(); ++i) {
1689 const QXmlStreamReaderPrivate::NotationDeclaration &notationDeclaration = notationDeclarations.at(i);
1690 QXmlStreamNotationDeclaration &publicNotationDeclaration = publicNotationDeclarations[i];
1691 publicNotationDeclaration.m_name = QXmlStreamStringRef(notationDeclaration.name);
1692 publicNotationDeclaration.m_systemId = QXmlStreamStringRef(notationDeclaration.systemId);
1693 publicNotationDeclaration.m_publicId = QXmlStreamStringRef(notationDeclaration.publicId);
1694
1695 }
1696 notationDeclarations.clear();
1697 publicEntityDeclarations.resize(entityDeclarations.size());
1698 for (int i = 0; i < entityDeclarations.size(); ++i) {
1699 const QXmlStreamReaderPrivate::EntityDeclaration &entityDeclaration = entityDeclarations.at(i);
1700 QXmlStreamEntityDeclaration &publicEntityDeclaration = publicEntityDeclarations[i];
1701 publicEntityDeclaration.m_name = QXmlStreamStringRef(entityDeclaration.name);
1702 publicEntityDeclaration.m_notationName = QXmlStreamStringRef(entityDeclaration.notationName);
1703 publicEntityDeclaration.m_systemId = QXmlStreamStringRef(entityDeclaration.systemId);
1704 publicEntityDeclaration.m_publicId = QXmlStreamStringRef(entityDeclaration.publicId);
1705 publicEntityDeclaration.m_value = QXmlStreamStringRef(entityDeclaration.value);
1706 }
1707 entityDeclarations.clear();
1708 parameterEntityHash.clear();
1709}
1710
1711uint QXmlStreamReaderPrivate::resolveCharRef(int symbolIndex)
1712{
1713 bool ok = true;
1714 uint s;
1715 // ### add toXShort to QStringRef?
1716 if (sym(symbolIndex).c == 'x')
1717 s = symString(symbolIndex, 1).toString().toUInt(&ok, 16);
1718 else
1719 s = symString(symbolIndex).toString().toUInt(&ok, 10);
1720
1721 ok &= (s == 0x9 || s == 0xa || s == 0xd || (s >= 0x20 && s <= 0xd7ff)
1722 || (s >= 0xe000 && s <= 0xfffd) || (s >= 0x10000 && s <= 0x10ffff));
1723
1724 return ok ? s : 0;
1725}
1726
1727
1728void QXmlStreamReaderPrivate::checkPublicLiteral(const QStringRef &publicId)
1729{
1730//#x20 | #xD | #xA | [a-zA-Z0-9] | [-'()+,./:=?;!*#@$_%]
1731
1732 const ushort *data = reinterpret_cast<const ushort *>(publicId.constData());
1733 uchar c = 0;
1734 int i;
1735 for (i = publicId.size() - 1; i >= 0; --i) {
1736 if (data[i] < 256)
1737 switch ((c = data[i])) {
1738 case ' ': case '\n': case '\r': case '-': case '(': case ')':
1739 case '+': case ',': case '.': case '/': case ':': case '=':
1740 case '?': case ';': case '!': case '*': case '#': case '@':
1741 case '$': case '_': case '%': case '\'': case '\"':
1742 continue;
1743 default:
1744 if ((c >= 'a' && c <= 'z')
1745 || (c >= 'A' && c <= 'Z')
1746 || (c >= '0' && c <= '9'))
1747 continue;
1748 }
1749 break;
1750 }
1751 if (i >= 0)
1752 raiseWellFormedError(QXmlStream::tr("Unexpected character '%1' in public id literal.").arg(QChar(QLatin1Char(c))));
1753}
1754
1755/*
1756 Checks whether the document starts with an xml declaration. If it
1757 does, this function returns true; otherwise it sets up everything
1758 for a synthetic start document event and returns false.
1759 */
1760bool QXmlStreamReaderPrivate::checkStartDocument()
1761{
1762 hasCheckedStartDocument = true;
1763
1764 if (scanString(spell[XML], XML))
1765 return true;
1766
1767 type = QXmlStreamReader::StartDocument;
1768 if (atEnd) {
1769 hasCheckedStartDocument = false;
1770 raiseError(QXmlStreamReader::PrematureEndOfDocumentError);
1771 }
1772 return false;
1773}
1774
1775void QXmlStreamReaderPrivate::startDocument()
1776{
1777 QString err;
1778 if (documentVersion != QLatin1String("1.0")) {
1779 if (documentVersion.toString().contains(QLatin1Char(' ')))
1780 err = QXmlStream::tr("Invalid XML version string.");
1781 else
1782 err = QXmlStream::tr("Unsupported XML version.");
1783 }
1784 int n = attributeStack.size();
1785
1786 /* We use this bool to ensure that the pesudo attributes are in the
1787 * proper order:
1788 *
1789 * [23] XMLDecl ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>' */
1790 bool hasStandalone = false;
1791
1792 for (int i = 0; err.isNull() && i < n; ++i) {
1793 Attribute &attrib = attributeStack[i];
1794 QStringRef prefix(symPrefix(attrib.key));
1795 QStringRef key(symString(attrib.key));
1796 QStringRef value(symString(attrib.value));
1797
1798 if (prefix.isEmpty() && key == QLatin1String("encoding")) {
1799 const QString name(value.toString());
1800 documentEncoding = value;
1801
1802 if(hasStandalone)
1803 err = QXmlStream::tr("The standalone pseudo attribute must appear after the encoding.");
1804 if(!QXmlUtils::isEncName(name))
1805 err = QXmlStream::tr("%1 is an invalid encoding name.").arg(name);
1806 else {
1807#ifdef QT_NO_TEXTCODEC
1808 readBuffer = QString::fromLatin1(rawReadBuffer.data(), nbytesread);
1809#else
1810 QTextCodec *const newCodec = QTextCodec::codecForName(name.toLatin1());
1811 if (!newCodec)
1812 err = QXmlStream::tr("Encoding %1 is unsupported").arg(name);
1813 else if (newCodec != codec && !lockEncoding) {
1814 codec = newCodec;
1815 delete decoder;
1816 decoder = codec->makeDecoder();
1817 decoder->toUnicode(&readBuffer, rawReadBuffer.data(), nbytesread);
1818 }
1819#endif // QT_NO_TEXTCODEC
1820 }
1821 } else if (prefix.isEmpty() && key == QLatin1String("standalone")) {
1822 hasStandalone = true;
1823 if (value == QLatin1String("yes"))
1824 standalone = true;
1825 else if (value == QLatin1String("no"))
1826 standalone = false;
1827 else
1828 err = QXmlStream::tr("Standalone accepts only yes or no.");
1829 } else {
1830 err = QXmlStream::tr("Invalid attribute in XML declaration.");
1831 }
1832 }
1833
1834 if (!err.isNull())
1835 raiseWellFormedError(err);
1836 attributeStack.clear();
1837}
1838
1839
1840void QXmlStreamReaderPrivate::raiseError(QXmlStreamReader::Error error, const QString& message)
1841{
1842 this->error = error;
1843 errorString = message;
1844 if (errorString.isNull()) {
1845 if (error == QXmlStreamReader::PrematureEndOfDocumentError)
1846 errorString = QXmlStream::tr("Premature end of document.");
1847 else if (error == QXmlStreamReader::CustomError)
1848 errorString = QXmlStream::tr("Invalid document.");
1849 }
1850
1851 type = QXmlStreamReader::Invalid;
1852}
1853
1854void QXmlStreamReaderPrivate::raiseWellFormedError(const QString &message)
1855{
1856 raiseError(QXmlStreamReader::NotWellFormedError, message);
1857}
1858
1859void QXmlStreamReaderPrivate::parseError()
1860{
1861
1862 if (token == EOF_SYMBOL) {
1863 raiseError(QXmlStreamReader::PrematureEndOfDocumentError);
1864 return;
1865 }
1866 const int nmax = 4;
1867 QString error_message;
1868 int ers = state_stack[tos];
1869 int nexpected = 0;
1870 int expected[nmax];
1871 if (token != ERROR)
1872 for (int tk = 0; tk < TERMINAL_COUNT; ++tk) {
1873 int k = t_action(ers, tk);
1874 if (k <= 0)
1875 continue;
1876 if (spell[tk]) {
1877 if (nexpected < nmax)
1878 expected[nexpected++] = tk;
1879 }
1880 }
1881
1882 error_message.clear ();
1883 if (nexpected && nexpected < nmax) {
1884 bool first = true;
1885
1886 for (int s = 0; s < nexpected; ++s) {
1887 if (first)
1888 error_message += QXmlStream::tr ("Expected ");
1889 else if (s == nexpected - 1)
1890 error_message += QLatin1String (nexpected > 2 ? ", or " : " or ");
1891 else
1892 error_message += QLatin1String (", ");
1893
1894 first = false;
1895 error_message += QLatin1String("\'");
1896 error_message += QLatin1String (spell [expected[s]]);
1897 error_message += QLatin1String("\'");
1898 }
1899 error_message += QXmlStream::tr(", but got \'");
1900 error_message += QLatin1String(spell [token]);
1901 error_message += QLatin1String("\'");
1902 } else {
1903 error_message += QXmlStream::tr("Unexpected \'");
1904 error_message += QLatin1String(spell [token]);
1905 error_message += QLatin1String("\'");
1906 }
1907 error_message += QLatin1Char('.');
1908
1909 raiseWellFormedError(error_message);
1910}
1911
1912void QXmlStreamReaderPrivate::resume(int rule) {
1913 resumeReduction = rule;
1914 if (error == QXmlStreamReader::NoError)
1915 raiseError(QXmlStreamReader::PrematureEndOfDocumentError);
1916}
1917
1918/*! Returns the current line number, starting with 1.
1919
1920\sa columnNumber(), characterOffset()
1921 */
1922qint64 QXmlStreamReader::lineNumber() const
1923{
1924 Q_D(const QXmlStreamReader);
1925 return d->lineNumber + 1; // in public we start with 1
1926}
1927
1928/*! Returns the current column number, starting with 0.
1929
1930\sa lineNumber(), characterOffset()
1931 */
1932qint64 QXmlStreamReader::columnNumber() const
1933{
1934 Q_D(const QXmlStreamReader);
1935 return d->characterOffset - d->lastLineStart + d->readBufferPos;
1936}
1937
1938/*! Returns the current character offset, starting with 0.
1939
1940\sa lineNumber(), columnNumber()
1941*/
1942qint64 QXmlStreamReader::characterOffset() const
1943{
1944 Q_D(const QXmlStreamReader);
1945 return d->characterOffset + d->readBufferPos;
1946}
1947
1948
1949/*! Returns the text of \l Characters, \l Comment, \l DTD, or
1950 EntityReference.
1951 */
1952QStringRef QXmlStreamReader::text() const
1953{
1954 Q_D(const QXmlStreamReader);
1955 return d->text;
1956}
1957
1958
1959/*! If the state() is \l DTD, this function returns the DTD's
1960 notation declarations. Otherwise an empty vector is returned.
1961
1962 The QXmlStreamNotationDeclarations class is defined to be a QVector
1963 of QXmlStreamNotationDeclaration.
1964 */
1965QXmlStreamNotationDeclarations QXmlStreamReader::notationDeclarations() const
1966{
1967 Q_D(const QXmlStreamReader);
1968 if (d->notationDeclarations.size())
1969 const_cast<QXmlStreamReaderPrivate *>(d)->resolveDtd();
1970 return d->publicNotationDeclarations;
1971}
1972
1973
1974/*! If the state() is \l DTD, this function returns the DTD's
1975 unparsed (external) entity declarations. Otherwise an empty vector is returned.
1976
1977 The QXmlStreamEntityDeclarations class is defined to be a QVector
1978 of QXmlStreamEntityDeclaration.
1979 */
1980QXmlStreamEntityDeclarations QXmlStreamReader::entityDeclarations() const
1981{
1982 Q_D(const QXmlStreamReader);
1983 if (d->entityDeclarations.size())
1984 const_cast<QXmlStreamReaderPrivate *>(d)->resolveDtd();
1985 return d->publicEntityDeclarations;
1986}
1987
1988/*!
1989 \since 4.4
1990
1991 If the state() is \l DTD, this function returns the DTD's
1992 name. Otherwise an empty string is returned.
1993
1994 */
1995QStringRef QXmlStreamReader::dtdName() const
1996{
1997 Q_D(const QXmlStreamReader);
1998 if (d->type == QXmlStreamReader::DTD)
1999 return d->dtdName;
2000 return QStringRef();
2001}
2002
2003/*!
2004 \since 4.4
2005
2006 If the state() is \l DTD, this function returns the DTD's
2007 public identifier. Otherwise an empty string is returned.
2008
2009 */
2010QStringRef QXmlStreamReader::dtdPublicId() const
2011{
2012 Q_D(const QXmlStreamReader);
2013 if (d->type == QXmlStreamReader::DTD)
2014 return d->dtdPublicId;
2015 return QStringRef();
2016}
2017
2018/*!
2019 \since 4.4
2020
2021 If the state() is \l DTD, this function returns the DTD's
2022 system identifier. Otherwise an empty string is returned.
2023
2024 */
2025QStringRef QXmlStreamReader::dtdSystemId() const
2026{
2027 Q_D(const QXmlStreamReader);
2028 if (d->type == QXmlStreamReader::DTD)
2029 return d->dtdSystemId;
2030 return QStringRef();
2031}
2032
2033/*! If the state() is \l StartElement, this function returns the
2034 element's namespace declarations. Otherwise an empty vector is
2035 returned.
2036
2037 The QXmlStreamNamespaceDeclaration class is defined to be a QVector
2038 of QXmlStreamNamespaceDeclaration.
2039
2040 \sa addExtraNamespaceDeclaration(), addExtraNamespaceDeclarations()
2041 */
2042QXmlStreamNamespaceDeclarations QXmlStreamReader::namespaceDeclarations() const
2043{
2044 Q_D(const QXmlStreamReader);
2045 if (d->publicNamespaceDeclarations.isEmpty() && d->type == StartElement)
2046 const_cast<QXmlStreamReaderPrivate *>(d)->resolvePublicNamespaces();
2047 return d->publicNamespaceDeclarations;
2048}
2049
2050
2051/*!
2052 \since 4.4
2053
2054 Adds an \a extraNamespaceDeclaration. The declaration will be
2055 valid for children of the current element, or - should the function
2056 be called before any elements are read - for the entire XML
2057 document.
2058
2059 \sa namespaceDeclarations(), addExtraNamespaceDeclarations(), setNamespaceProcessing()
2060 */
2061void QXmlStreamReader::addExtraNamespaceDeclaration(const QXmlStreamNamespaceDeclaration &extraNamespaceDeclaration)
2062{
2063 Q_D(QXmlStreamReader);
2064 QXmlStreamReaderPrivate::NamespaceDeclaration &namespaceDeclaration = d->namespaceDeclarations.push();
2065 namespaceDeclaration.prefix = d->addToStringStorage(extraNamespaceDeclaration.prefix());
2066 namespaceDeclaration.namespaceUri = d->addToStringStorage(extraNamespaceDeclaration.namespaceUri());
2067}
2068
2069/*!
2070 \since 4.4
2071
2072 Adds a vector of declarations specified by \a extraNamespaceDeclarations.
2073
2074 \sa namespaceDeclarations(), addExtraNamespaceDeclaration()
2075 */
2076void QXmlStreamReader::addExtraNamespaceDeclarations(const QXmlStreamNamespaceDeclarations &extraNamespaceDeclarations)
2077{
2078 for (int i = 0; i < extraNamespaceDeclarations.size(); ++i)
2079 addExtraNamespaceDeclaration(extraNamespaceDeclarations.at(i));
2080}
2081
2082
2083/*! Convenience function to be called in case a StartElement was
2084 read. Reads until the corresponding EndElement and returns all text
2085 in-between. In case of no error, the current token (see tokenType())
2086 after having called this function is EndElement.
2087
2088 The function concatenates text() when it reads either \l Characters
2089 or EntityReference tokens, but skips ProcessingInstruction and \l
2090 Comment. If the current token is not StartElement, an empty string is
2091 returned.
2092
2093 The \a behaviour defines what happens in case anything else is
2094 read before reaching EndElement. The function can include the text from
2095 child elements (useful for example for HTML), ignore child elements, or
2096 raise an UnexpectedElementError and return what was read so far.
2097
2098 \since 4.6
2099 */
2100QString QXmlStreamReader::readElementText(ReadElementTextBehaviour behaviour)
2101{
2102 Q_D(QXmlStreamReader);
2103 if (isStartElement()) {
2104 QString result;
2105 forever {
2106 switch (readNext()) {
2107 case Characters:
2108 case EntityReference:
2109 result.insert(result.size(), d->text.unicode(), d->text.size());
2110 break;
2111 case EndElement:
2112 return result;
2113 case ProcessingInstruction:
2114 case Comment:
2115 break;
2116 case StartElement:
2117 if (behaviour == SkipChildElements) {
2118 skipCurrentElement();
2119 break;
2120 } else if (behaviour == IncludeChildElements) {
2121 result += readElementText(behaviour);
2122 break;
2123 }
2124 // Fall through (for ErrorOnUnexpectedElement)
2125 default:
2126 if (d->error || behaviour == ErrorOnUnexpectedElement) {
2127 if (!d->error)
2128 d->raiseError(UnexpectedElementError, QXmlStream::tr("Expected character data."));
2129 return result;
2130 }
2131 }
2132 }
2133 }
2134 return QString();
2135}
2136
2137/*!
2138 \overload readElementText()
2139
2140 Calling this function is equivalent to calling readElementText(ErrorOnUnexpectedElement).
2141 */
2142QString QXmlStreamReader::readElementText()
2143{
2144 return readElementText(ErrorOnUnexpectedElement);
2145}
2146
2147/*! Raises a custom error with an optional error \a message.
2148
2149 \sa error(), errorString()
2150 */
2151void QXmlStreamReader::raiseError(const QString& message)
2152{
2153 Q_D(QXmlStreamReader);
2154 d->raiseError(CustomError, message);
2155}
2156
2157/*!
2158 Returns the error message that was set with raiseError().
2159
2160 \sa error(), lineNumber(), columnNumber(), characterOffset()
2161 */
2162QString QXmlStreamReader::errorString() const
2163{
2164 Q_D(const QXmlStreamReader);
2165 if (d->type == QXmlStreamReader::Invalid)
2166 return d->errorString;
2167 return QString();
2168}
2169
2170/*! Returns the type of the current error, or NoError if no error occurred.
2171
2172 \sa errorString(), raiseError()
2173 */
2174QXmlStreamReader::Error QXmlStreamReader::error() const
2175{
2176 Q_D(const QXmlStreamReader);
2177 if (d->type == QXmlStreamReader::Invalid)
2178 return d->error;
2179 return NoError;
2180}
2181
2182/*!
2183 Returns the target of a ProcessingInstruction.
2184 */
2185QStringRef QXmlStreamReader::processingInstructionTarget() const
2186{
2187 Q_D(const QXmlStreamReader);
2188 return d->processingInstructionTarget;
2189}
2190
2191/*!
2192 Returns the data of a ProcessingInstruction.
2193 */
2194QStringRef QXmlStreamReader::processingInstructionData() const
2195{
2196 Q_D(const QXmlStreamReader);
2197 return d->processingInstructionData;
2198}
2199
2200
2201
2202/*!
2203 Returns the local name of a StartElement, EndElement, or an EntityReference.
2204
2205 \sa namespaceUri(), qualifiedName()
2206 */
2207QStringRef QXmlStreamReader::name() const
2208{
2209 Q_D(const QXmlStreamReader);
2210 return d->name;
2211}
2212
2213/*!
2214 Returns the namespaceUri of a StartElement or EndElement.
2215
2216 \sa name(), qualifiedName()
2217 */
2218QStringRef QXmlStreamReader::namespaceUri() const
2219{
2220 Q_D(const QXmlStreamReader);
2221 return d->namespaceUri;
2222}
2223
2224/*!
2225 Returns the qualified name of a StartElement or EndElement;
2226
2227 A qualified name is the raw name of an element in the XML data. It
2228 consists of the namespace prefix, followed by colon, followed by the
2229 element's local name. Since the namespace prefix is not unique (the
2230 same prefix can point to different namespaces and different prefixes
2231 can point to the same namespace), you shouldn't use qualifiedName(),
2232 but the resolved namespaceUri() and the attribute's local name().
2233
2234 \sa name(), prefix(), namespaceUri()
2235 */
2236QStringRef QXmlStreamReader::qualifiedName() const
2237{
2238 Q_D(const QXmlStreamReader);
2239 return d->qualifiedName;
2240}
2241
2242
2243
2244/*!
2245 \since 4.4
2246
2247 Returns the prefix of a StartElement or EndElement.
2248
2249 \sa name(), qualifiedName()
2250*/
2251QStringRef QXmlStreamReader::prefix() const
2252{
2253 Q_D(const QXmlStreamReader);
2254 return d->prefix;
2255}
2256
2257/*!
2258 Returns the attributes of a StartElement.
2259 */
2260QXmlStreamAttributes QXmlStreamReader::attributes() const
2261{
2262 Q_D(const QXmlStreamReader);
2263 return d->attributes;
2264}
2265
2266#endif // QT_NO_XMLSTREAMREADER
2267
2268/*!
2269 \class QXmlStreamAttribute
2270 \since 4.3
2271 \reentrant
2272 \brief The QXmlStreamAttribute class represents a single XML attribute
2273
2274 \ingroup xml-tools
2275
2276 An attribute consists of an optionally empty namespaceUri(), a
2277 name(), a value(), and an isDefault() attribute.
2278
2279 The raw XML attribute name is returned as qualifiedName().
2280*/
2281
2282/*!
2283 Creates an empty attribute.
2284 */
2285QXmlStreamAttribute::QXmlStreamAttribute()
2286{
2287 m_isDefault = false;
2288}
2289
2290/*!
2291 Destructs an attribute.
2292 */
2293QXmlStreamAttribute::~QXmlStreamAttribute()
2294{
2295}
2296
2297/*! Constructs an attribute in the namespace described with \a
2298 namespaceUri with \a name and value \a value.
2299 */
2300QXmlStreamAttribute::QXmlStreamAttribute(const QString &namespaceUri, const QString &name, const QString &value)
2301{
2302 m_namespaceUri = QXmlStreamStringRef(QStringRef(&namespaceUri));
2303 m_name = m_qualifiedName = QXmlStreamStringRef(QStringRef(&name));
2304 m_value = QXmlStreamStringRef(QStringRef(&value));
2305 m_namespaceUri = QXmlStreamStringRef(QStringRef(&namespaceUri));
2306}
2307
2308/*!
2309 Constructs an attribute with qualified name \a qualifiedName and value \a value.
2310 */
2311QXmlStreamAttribute::QXmlStreamAttribute(const QString &qualifiedName, const QString &value)
2312{
2313 int colon = qualifiedName.indexOf(QLatin1Char(':'));
2314 m_name = QXmlStreamStringRef(QStringRef(&qualifiedName,
2315 colon + 1,
2316 qualifiedName.size() - (colon + 1)));
2317 m_qualifiedName = QXmlStreamStringRef(QStringRef(&qualifiedName));
2318 m_value = QXmlStreamStringRef(QStringRef(&value));
2319}
2320
2321/*! \fn QStringRef QXmlStreamAttribute::namespaceUri() const
2322
2323 Returns the attribute's resolved namespaceUri, or an empty string
2324 reference if the attribute does not have a defined namespace.
2325 */
2326/*! \fn QStringRef QXmlStreamAttribute::name() const
2327 Returns the attribute's local name.
2328 */
2329/*! \fn QStringRef QXmlStreamAttribute::qualifiedName() const
2330 Returns the attribute's qualified name.
2331
2332 A qualified name is the raw name of an attribute in the XML
2333 data. It consists of the namespace prefix(), followed by colon,
2334 followed by the attribute's local name(). Since the namespace prefix
2335 is not unique (the same prefix can point to different namespaces
2336 and different prefixes can point to the same namespace), you
2337 shouldn't use qualifiedName(), but the resolved namespaceUri() and
2338 the attribute's local name().
2339 */
2340/*!
2341 \fn QStringRef QXmlStreamAttribute::prefix() const
2342 \since 4.4
2343 Returns the attribute's namespace prefix.
2344
2345 \sa name(), qualifiedName()
2346
2347*/
2348
2349/*! \fn QStringRef QXmlStreamAttribute::value() const
2350 Returns the attribute's value.
2351 */
2352
2353/*! \fn bool QXmlStreamAttribute::isDefault() const
2354
2355 Returns true if the parser added this attribute with a default
2356 value following an ATTLIST declaration in the DTD; otherwise
2357 returns false.
2358*/
2359/*! \fn bool QXmlStreamAttribute::operator==(const QXmlStreamAttribute &other) const
2360
2361 Compares this attribute with \a other and returns true if they are
2362 equal; otherwise returns false.
2363 */
2364/*! \fn bool QXmlStreamAttribute::operator!=(const QXmlStreamAttribute &other) const
2365
2366 Compares this attribute with \a other and returns true if they are
2367 not equal; otherwise returns false.
2368 */
2369
2370
2371/*!
2372 Creates a copy of \a other.
2373 */
2374QXmlStreamAttribute::QXmlStreamAttribute(const QXmlStreamAttribute &other)
2375{
2376 *this = other;
2377}
2378
2379/*!
2380 Assigns \a other to this attribute.
2381 */
2382QXmlStreamAttribute& QXmlStreamAttribute::operator=(const QXmlStreamAttribute &other)
2383{
2384 m_name = other.m_name;
2385 m_namespaceUri = other.m_namespaceUri;
2386 m_qualifiedName = other.m_qualifiedName;
2387 m_value = other.m_value;
2388 m_isDefault = other.m_isDefault;
2389 return *this;
2390}
2391
2392
2393/*!
2394 \class QXmlStreamAttributes
2395 \since 4.3
2396 \reentrant
2397 \brief The QXmlStreamAttributes class represents a vector of QXmlStreamAttribute.
2398
2399 Attributes are returned by a QXmlStreamReader in
2400 \l{QXmlStreamReader::attributes()} {attributes()} when the reader
2401 reports a \l {QXmlStreamReader::StartElement}{start element}. The
2402 class can also be used with a QXmlStreamWriter as an argument to
2403 \l {QXmlStreamWriter::writeAttributes()}{writeAttributes()}.
2404
2405 The convenience function value() loops over the vector and returns
2406 an attribute value for a given namespaceUri and an attribute's
2407 name.
2408
2409 New attributes can be added with append().
2410
2411 \ingroup xml-tools
2412*/
2413
2414/*!
2415 \fn void QXmlStreamAttributes::append(const QXmlStreamAttribute &attribute)
2416
2417 Appends the given \a attribute to the end of the vector.
2418
2419 \sa QVector::append()
2420*/
2421
2422
2423/*!
2424 \typedef QXmlStreamNotationDeclarations
2425 \relates QXmlStreamNotationDeclaration
2426
2427 Synonym for QVector<QXmlStreamNotationDeclaration>.
2428*/
2429
2430
2431/*!
2432 \class QXmlStreamNotationDeclaration
2433 \since 4.3
2434 \reentrant
2435 \brief The QXmlStreamNotationDeclaration class represents a DTD notation declaration.
2436
2437 \ingroup xml-tools
2438
2439 An notation declaration consists of a name(), a systemId(), and a publicId().
2440*/
2441
2442/*!
2443 Creates an empty notation declaration.
2444*/
2445QXmlStreamNotationDeclaration::QXmlStreamNotationDeclaration()
2446{
2447}
2448/*!
2449 Creates a copy of \a other.
2450 */
2451QXmlStreamNotationDeclaration::QXmlStreamNotationDeclaration(const QXmlStreamNotationDeclaration &other)
2452{
2453 *this = other;
2454}
2455
2456/*!
2457 Assigns \a other to this notation declaration.
2458 */
2459QXmlStreamNotationDeclaration& QXmlStreamNotationDeclaration::operator=(const QXmlStreamNotationDeclaration &other)
2460{
2461 m_name = other.m_name;
2462 m_systemId = other.m_systemId;
2463 m_publicId = other.m_publicId;
2464 return *this;
2465}
2466
2467/*!
2468Destructs this notation declaration.
2469*/
2470QXmlStreamNotationDeclaration::~QXmlStreamNotationDeclaration()
2471{
2472}
2473
2474/*! \fn QStringRef QXmlStreamNotationDeclaration::name() const
2475
2476Returns the notation name.
2477*/
2478/*! \fn QStringRef QXmlStreamNotationDeclaration::systemId() const
2479
2480Returns the system identifier.
2481*/
2482/*! \fn QStringRef QXmlStreamNotationDeclaration::publicId() const
2483
2484Returns the public identifier.
2485*/
2486
2487/*! \fn inline bool QXmlStreamNotationDeclaration::operator==(const QXmlStreamNotationDeclaration &other) const
2488
2489 Compares this notation declaration with \a other and returns true
2490 if they are equal; otherwise returns false.
2491 */
2492/*! \fn inline bool QXmlStreamNotationDeclaration::operator!=(const QXmlStreamNotationDeclaration &other) const
2493
2494 Compares this notation declaration with \a other and returns true
2495 if they are not equal; otherwise returns false.
2496 */
2497
2498/*!
2499 \typedef QXmlStreamNamespaceDeclarations
2500 \relates QXmlStreamNamespaceDeclaration
2501
2502 Synonym for QVector<QXmlStreamNamespaceDeclaration>.
2503*/
2504
2505/*!
2506 \class QXmlStreamNamespaceDeclaration
2507 \since 4.3
2508 \reentrant
2509 \brief The QXmlStreamNamespaceDeclaration class represents a namespace declaration.
2510
2511 \ingroup xml-tools
2512
2513 An namespace declaration consists of a prefix() and a namespaceUri().
2514*/
2515/*! \fn inline bool QXmlStreamNamespaceDeclaration::operator==(const QXmlStreamNamespaceDeclaration &other) const
2516
2517 Compares this namespace declaration with \a other and returns true
2518 if they are equal; otherwise returns false.
2519 */
2520/*! \fn inline bool QXmlStreamNamespaceDeclaration::operator!=(const QXmlStreamNamespaceDeclaration &other) const
2521
2522 Compares this namespace declaration with \a other and returns true
2523 if they are not equal; otherwise returns false.
2524 */
2525
2526/*!
2527 Creates an empty namespace declaration.
2528*/
2529QXmlStreamNamespaceDeclaration::QXmlStreamNamespaceDeclaration()
2530{
2531}
2532
2533/*!
2534 \since 4.4
2535
2536 Creates a namespace declaration with \a prefix and \a namespaceUri.
2537*/
2538QXmlStreamNamespaceDeclaration::QXmlStreamNamespaceDeclaration(const QString &prefix, const QString &namespaceUri)
2539{
2540 m_prefix = prefix;
2541 m_namespaceUri = namespaceUri;
2542}
2543
2544/*!
2545 Creates a copy of \a other.
2546 */
2547QXmlStreamNamespaceDeclaration::QXmlStreamNamespaceDeclaration(const QXmlStreamNamespaceDeclaration &other)
2548{
2549 *this = other;
2550}
2551
2552/*!
2553 Assigns \a other to this namespace declaration.
2554 */
2555QXmlStreamNamespaceDeclaration& QXmlStreamNamespaceDeclaration::operator=(const QXmlStreamNamespaceDeclaration &other)
2556{
2557 m_prefix = other.m_prefix;
2558 m_namespaceUri = other.m_namespaceUri;
2559 return *this;
2560}
2561/*!
2562Destructs this namespace declaration.
2563*/
2564QXmlStreamNamespaceDeclaration::~QXmlStreamNamespaceDeclaration()
2565{
2566}
2567
2568/*! \fn QStringRef QXmlStreamNamespaceDeclaration::prefix() const
2569
2570Returns the prefix.
2571*/
2572/*! \fn QStringRef QXmlStreamNamespaceDeclaration::namespaceUri() const
2573
2574Returns the namespaceUri.
2575*/
2576
2577
2578
2579
2580/*!
2581 \typedef QXmlStreamEntityDeclarations
2582 \relates QXmlStreamEntityDeclaration
2583
2584 Synonym for QVector<QXmlStreamEntityDeclaration>.
2585*/
2586
2587/*!
2588 \class QXmlStreamStringRef
2589 \since 4.3
2590 \internal
2591*/
2592
2593/*!
2594 \class QXmlStreamEntityDeclaration
2595 \since 4.3
2596 \reentrant
2597 \brief The QXmlStreamEntityDeclaration class represents a DTD entity declaration.
2598
2599 \ingroup xml-tools
2600
2601 An entity declaration consists of a name(), a notationName(), a
2602 systemId(), a publicId(), and a value().
2603*/
2604
2605/*!
2606 Creates an empty entity declaration.
2607*/
2608QXmlStreamEntityDeclaration::QXmlStreamEntityDeclaration()
2609{
2610}
2611
2612/*!
2613 Creates a copy of \a other.
2614 */
2615QXmlStreamEntityDeclaration::QXmlStreamEntityDeclaration(const QXmlStreamEntityDeclaration &other)
2616{
2617 *this = other;
2618}
2619
2620/*!
2621 Assigns \a other to this entity declaration.
2622 */
2623QXmlStreamEntityDeclaration& QXmlStreamEntityDeclaration::operator=(const QXmlStreamEntityDeclaration &other)
2624{
2625 m_name = other.m_name;
2626 m_notationName = other.m_notationName;
2627 m_systemId = other.m_systemId;
2628 m_publicId = other.m_publicId;
2629 m_value = other.m_value;
2630 return *this;
2631}
2632
2633/*!
2634 Destructs this entity declaration.
2635*/
2636QXmlStreamEntityDeclaration::~QXmlStreamEntityDeclaration()
2637{
2638}
2639
2640/*! \fn QStringRef QXmlStreamEntityDeclaration::name() const
2641
2642Returns the entity name.
2643*/
2644/*! \fn QStringRef QXmlStreamEntityDeclaration::notationName() const
2645
2646Returns the notation name.
2647*/
2648/*! \fn QStringRef QXmlStreamEntityDeclaration::systemId() const
2649
2650Returns the system identifier.
2651*/
2652/*! \fn QStringRef QXmlStreamEntityDeclaration::publicId() const
2653
2654Returns the public identifier.
2655*/
2656/*! \fn QStringRef QXmlStreamEntityDeclaration::value() const
2657
2658Returns the entity's value.
2659*/
2660
2661/*! \fn bool QXmlStreamEntityDeclaration::operator==(const QXmlStreamEntityDeclaration &other) const
2662
2663 Compares this entity declaration with \a other and returns true if
2664 they are equal; otherwise returns false.
2665 */
2666/*! \fn bool QXmlStreamEntityDeclaration::operator!=(const QXmlStreamEntityDeclaration &other) const
2667
2668 Compares this entity declaration with \a other and returns true if
2669 they are not equal; otherwise returns false.
2670 */
2671
2672/*! Returns the value of the attribute \a name in the namespace
2673 described with \a namespaceUri, or an empty string reference if the
2674 attribute is not defined. The \a namespaceUri can be empty.
2675 */
2676QStringRef QXmlStreamAttributes::value(const QString &namespaceUri, const QString &name) const
2677{
2678 for (int i = 0; i < size(); ++i) {
2679 const QXmlStreamAttribute &attribute = at(i);
2680 if (attribute.name() == name && attribute.namespaceUri() == namespaceUri)
2681 return attribute.value();
2682 }
2683 return QStringRef();
2684}
2685
2686/*!\overload
2687 Returns the value of the attribute \a name in the namespace
2688 described with \a namespaceUri, or an empty string reference if the
2689 attribute is not defined. The \a namespaceUri can be empty.
2690 */
2691QStringRef QXmlStreamAttributes::value(const QString &namespaceUri, const QLatin1String &name) const
2692{
2693 for (int i = 0; i < size(); ++i) {
2694 const QXmlStreamAttribute &attribute = at(i);
2695 if (attribute.name() == name && attribute.namespaceUri() == namespaceUri)
2696 return attribute.value();
2697 }
2698 return QStringRef();
2699}
2700
2701/*!\overload
2702 Returns the value of the attribute \a name in the namespace
2703 described with \a namespaceUri, or an empty string reference if the
2704 attribute is not defined. The \a namespaceUri can be empty.
2705 */
2706QStringRef QXmlStreamAttributes::value(const QLatin1String &namespaceUri, const QLatin1String &name) const
2707{
2708 for (int i = 0; i < size(); ++i) {
2709 const QXmlStreamAttribute &attribute = at(i);
2710 if (attribute.name() == name && attribute.namespaceUri() == namespaceUri)
2711 return attribute.value();
2712 }
2713 return QStringRef();
2714}
2715
2716/*!\overload
2717
2718 Returns the value of the attribute with qualified name \a
2719 qualifiedName , or an empty string reference if the attribute is not
2720 defined. A qualified name is the raw name of an attribute in the XML
2721 data. It consists of the namespace prefix, followed by colon,
2722 followed by the attribute's local name. Since the namespace prefix
2723 is not unique (the same prefix can point to different namespaces and
2724 different prefixes can point to the same namespace), you shouldn't
2725 use qualified names, but a resolved namespaceUri and the attribute's
2726 local name.
2727 */
2728QStringRef QXmlStreamAttributes::value(const QString &qualifiedName) const
2729{
2730 for (int i = 0; i < size(); ++i) {
2731 const QXmlStreamAttribute &attribute = at(i);
2732 if (attribute.qualifiedName() == qualifiedName)
2733 return attribute.value();
2734 }
2735 return QStringRef();
2736}
2737
2738/*!\overload
2739
2740 Returns the value of the attribute with qualified name \a
2741 qualifiedName , or an empty string reference if the attribute is not
2742 defined. A qualified name is the raw name of an attribute in the XML
2743 data. It consists of the namespace prefix, followed by colon,
2744 followed by the attribute's local name. Since the namespace prefix
2745 is not unique (the same prefix can point to different namespaces and
2746 different prefixes can point to the same namespace), you shouldn't
2747 use qualified names, but a resolved namespaceUri and the attribute's
2748 local name.
2749 */
2750QStringRef QXmlStreamAttributes::value(const QLatin1String &qualifiedName) const
2751{
2752 for (int i = 0; i < size(); ++i) {
2753 const QXmlStreamAttribute &attribute = at(i);
2754 if (attribute.qualifiedName() == qualifiedName)
2755 return attribute.value();
2756 }
2757 return QStringRef();
2758}
2759
2760/*!Appends a new attribute with \a name in the namespace
2761 described with \a namespaceUri, and value \a value. The \a
2762 namespaceUri can be empty.
2763 */
2764void QXmlStreamAttributes::append(const QString &namespaceUri, const QString &name, const QString &value)
2765{
2766 append(QXmlStreamAttribute(namespaceUri, name, value));
2767}
2768
2769/*!\overload
2770 Appends a new attribute with qualified name \a qualifiedName and
2771 value \a value.
2772 */
2773void QXmlStreamAttributes::append(const QString &qualifiedName, const QString &value)
2774{
2775 append(QXmlStreamAttribute(qualifiedName, value));
2776}
2777
2778#ifndef QT_NO_XMLSTREAMREADER
2779
2780/*! \fn bool QXmlStreamReader::isStartDocument() const
2781 Returns true if tokenType() equals \l StartDocument; otherwise returns false.
2782*/
2783/*! \fn bool QXmlStreamReader::isEndDocument() const
2784 Returns true if tokenType() equals \l EndDocument; otherwise returns false.
2785*/
2786/*! \fn bool QXmlStreamReader::isStartElement() const
2787 Returns true if tokenType() equals \l StartElement; otherwise returns false.
2788*/
2789/*! \fn bool QXmlStreamReader::isEndElement() const
2790 Returns true if tokenType() equals \l EndElement; otherwise returns false.
2791*/
2792/*! \fn bool QXmlStreamReader::isCharacters() const
2793 Returns true if tokenType() equals \l Characters; otherwise returns false.
2794
2795 \sa isWhitespace(), isCDATA()
2796*/
2797/*! \fn bool QXmlStreamReader::isComment() const
2798 Returns true if tokenType() equals \l Comment; otherwise returns false.
2799*/
2800/*! \fn bool QXmlStreamReader::isDTD() const
2801 Returns true if tokenType() equals \l DTD; otherwise returns false.
2802*/
2803/*! \fn bool QXmlStreamReader::isEntityReference() const
2804 Returns true if tokenType() equals \l EntityReference; otherwise returns false.
2805*/
2806/*! \fn bool QXmlStreamReader::isProcessingInstruction() const
2807 Returns true if tokenType() equals \l ProcessingInstruction; otherwise returns false.
2808*/
2809
2810/*! Returns true if the reader reports characters that only consist
2811 of white-space; otherwise returns false.
2812
2813 \sa isCharacters(), text()
2814*/
2815bool QXmlStreamReader::isWhitespace() const
2816{
2817 Q_D(const QXmlStreamReader);
2818 return d->type == QXmlStreamReader::Characters && d->isWhitespace;
2819}
2820
2821/*! Returns true if the reader reports characters that stem from a
2822 CDATA section; otherwise returns false.
2823
2824 \sa isCharacters(), text()
2825*/
2826bool QXmlStreamReader::isCDATA() const
2827{
2828 Q_D(const QXmlStreamReader);
2829 return d->type == QXmlStreamReader::Characters && d->isCDATA;
2830}
2831
2832
2833
2834/*!
2835 Returns true if this document has been declared standalone in the
2836 XML declaration; otherwise returns false.
2837
2838 If no XML declaration has been parsed, this function returns false.
2839 */
2840bool QXmlStreamReader::isStandaloneDocument() const
2841{
2842 Q_D(const QXmlStreamReader);
2843 return d->standalone;
2844}
2845
2846
2847/*!
2848 \since 4.4
2849
2850 If the state() is \l StartDocument, this function returns the
2851 version string as specified in the XML declaration.
2852 Otherwise an empty string is returned.
2853 */
2854QStringRef QXmlStreamReader::documentVersion() const
2855{
2856 Q_D(const QXmlStreamReader);
2857 if (d->type == QXmlStreamReader::StartDocument)
2858 return d->documentVersion;
2859 return QStringRef();
2860}
2861
2862/*!
2863 \since 4.4
2864
2865 If the state() is \l StartDocument, this function returns the
2866 encoding string as specified in the XML declaration.
2867 Otherwise an empty string is returned.
2868 */
2869QStringRef QXmlStreamReader::documentEncoding() const
2870{
2871 Q_D(const QXmlStreamReader);
2872 if (d->type == QXmlStreamReader::StartDocument)
2873 return d->documentEncoding;
2874 return QStringRef();
2875}
2876
2877#endif // QT_NO_XMLSTREAMREADER
2878
2879/*!
2880 \class QXmlStreamWriter
2881 \since 4.3
2882 \reentrant
2883
2884 \brief The QXmlStreamWriter class provides an XML writer with a
2885 simple streaming API.
2886
2887 \ingroup xml-tools
2888
2889 QXmlStreamWriter is the counterpart to QXmlStreamReader for writing
2890 XML. Like its related class, it operates on a QIODevice specified
2891 with setDevice(). The API is simple and straightforward: for every
2892 XML token or event you want to write, the writer provides a
2893 specialized function.
2894
2895 You start a document with writeStartDocument() and end it with
2896 writeEndDocument(). This will implicitly close all remaining open
2897 tags.
2898
2899 Element tags are opened with writeStartElement() followed by
2900 writeAttribute() or writeAttributes(), element content, and then
2901 writeEndElement(). A shorter form writeEmptyElement() can be used
2902 to write empty elements, followed by writeAttributes().
2903
2904 Element content consists of either characters, entity references or
2905 nested elements. It is written with writeCharacters(), which also
2906 takes care of escaping all forbidden characters and character
2907 sequences, writeEntityReference(), or subsequent calls to
2908 writeStartElement(). A convenience method writeTextElement() can be
2909 used for writing terminal elements that contain nothing but text.
2910
2911 The following abridged code snippet shows the basic use of the class
2912 to write formatted XML with indentation:
2913
2914 \snippet doc/src/snippets/qxmlstreamwriter/main.cpp start stream
2915 \dots
2916 \snippet doc/src/snippets/qxmlstreamwriter/main.cpp write element
2917 \dots
2918 \snippet doc/src/snippets/qxmlstreamwriter/main.cpp finish stream
2919
2920 QXmlStreamWriter takes care of prefixing namespaces, all you have to
2921 do is specify the \c namespaceUri when writing elements or
2922 attributes. If you must conform to certain prefixes, you can force
2923 the writer to use them by declaring the namespaces manually with
2924 either writeNamespace() or writeDefaultNamespace(). Alternatively,
2925 you can bypass the stream writer's namespace support and use
2926 overloaded methods that take a qualified name instead. The namespace
2927 \e http://www.w3.org/XML/1998/namespace is implicit and mapped to the
2928 prefix \e xml.
2929
2930 The stream writer can automatically format the generated XML data by
2931 adding line-breaks and indentation to empty sections between
2932 elements, making the XML data more readable for humans and easier to
2933 work with for most source code management systems. The feature can
2934 be turned on with the \l autoFormatting property, and customized
2935 with the \l autoFormattingIndent property.
2936
2937 Other functions are writeCDATA(), writeComment(),
2938 writeProcessingInstruction(), and writeDTD(). Chaining of XML
2939 streams is supported with writeCurrentToken().
2940
2941 By default, QXmlStreamWriter encodes XML in UTF-8. Different
2942 encodings can be enforced using setCodec().
2943
2944 The \l{QXmlStream Bookmarks Example} illustrates how to use a
2945 stream writer to write an XML bookmark file (XBEL) that
2946 was previously read in by a QXmlStreamReader.
2947
2948*/
2949
2950#ifndef QT_NO_XMLSTREAMWRITER
2951
2952class QXmlStreamWriterPrivate : public QXmlStreamPrivateTagStack {
2953 QXmlStreamWriter *q_ptr;
2954 Q_DECLARE_PUBLIC(QXmlStreamWriter)
2955public:
2956 QXmlStreamWriterPrivate(QXmlStreamWriter *q);
2957 ~QXmlStreamWriterPrivate() {
2958 if (deleteDevice)
2959 delete device;
2960#ifndef QT_NO_TEXTCODEC
2961 delete encoder;
2962#endif
2963 }
2964
2965 void write(const QStringRef &);
2966 void write(const QString &);
2967 void writeEscaped(const QString &, bool escapeWhitespace = false);
2968 void write(const char *s);
2969 bool finishStartElement(bool contents = true);