1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtCore module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include "QtCore/qxmlstream.h"
41
42#ifndef QT_NO_XMLSTREAM
43
44#include "qxmlutils_p.h"
45#include <qdebug.h>
46#include <qfile.h>
47#include <stdio.h>
48#if QT_CONFIG(textcodec)
49#include <qtextcodec.h>
50#endif
51#include <qstack.h>
52#include <qbuffer.h>
53#ifndef QT_BOOTSTRAPPED
54#include <qcoreapplication.h>
55#else
56// This specialization of Q_DECLARE_TR_FUNCTIONS is not in qcoreapplication.h,
57// because that header depends on QObject being available, which is not the
58// case for most bootstrapped applications.
59#define Q_DECLARE_TR_FUNCTIONS(context) \
60public: \
61 static inline QString tr(const char *sourceText, const char *comment = nullptr) \
62 { Q_UNUSED(comment); return QString::fromLatin1(sourceText); } \
63 static inline QString trUtf8(const char *sourceText, const char *comment = nullptr) \
64 { Q_UNUSED(comment); return QString::fromLatin1(sourceText); } \
65 static inline QString tr(const char *sourceText, const char*, int) \
66 { return QString::fromLatin1(sourceText); } \
67 static inline QString trUtf8(const char *sourceText, const char*, int) \
68 { return QString::fromLatin1(sourceText); } \
69private:
70#endif
71QT_BEGIN_NAMESPACE
72
73#include "qxmlstream_p.h"
74
75enum { StreamEOF = ~0U };
76
77/*!
78 \enum QXmlStreamReader::TokenType
79
80 This enum specifies the type of token the reader just read.
81
82 \value NoToken The reader has not yet read anything.
83
84 \value Invalid An error has occurred, reported in error() and
85 errorString().
86
87 \value StartDocument The reader reports the XML version number in
88 documentVersion(), and the encoding as specified in the XML
89 document in documentEncoding(). If the document is declared
90 standalone, isStandaloneDocument() returns \c true; otherwise it
91 returns \c false.
92
93 \value EndDocument The reader reports the end of the document.
94
95 \value StartElement The reader reports the start of an element
96 with namespaceUri() and name(). Empty elements are also reported
97 as StartElement, followed directly by EndElement. The convenience
98 function readElementText() can be called to concatenate all
99 content until the corresponding EndElement. Attributes are
100 reported in attributes(), namespace declarations in
101 namespaceDeclarations().
102
103 \value EndElement The reader reports the end of an element with
104 namespaceUri() and name().
105
106 \value Characters The reader reports characters in text(). If the
107 characters are all white-space, isWhitespace() returns \c true. If
108 the characters stem from a CDATA section, isCDATA() returns \c true.
109
110 \value Comment The reader reports a comment in text().
111
112 \value DTD The reader reports a DTD in text(), notation
113 declarations in notationDeclarations(), and entity declarations in
114 entityDeclarations(). Details of the DTD declaration are reported
115 in in dtdName(), dtdPublicId(), and dtdSystemId().
116
117 \value EntityReference The reader reports an entity reference that
118 could not be resolved. The name of the reference is reported in
119 name(), the replacement text in text().
120
121 \value ProcessingInstruction The reader reports a processing
122 instruction in processingInstructionTarget() and
123 processingInstructionData().
124*/
125
126/*!
127 \enum QXmlStreamReader::ReadElementTextBehaviour
128
129 This enum specifies the different behaviours of readElementText().
130
131 \value ErrorOnUnexpectedElement Raise an UnexpectedElementError and return
132 what was read so far when a child element is encountered.
133
134 \value IncludeChildElements Recursively include the text from child elements.
135
136 \value SkipChildElements Skip child elements.
137
138 \since 4.6
139*/
140
141/*!
142 \enum QXmlStreamReader::Error
143
144 This enum specifies different error cases
145
146 \value NoError No error has occurred.
147
148 \value CustomError A custom error has been raised with
149 raiseError()
150
151 \value NotWellFormedError The parser internally raised an error
152 due to the read XML not being well-formed.
153
154 \value PrematureEndOfDocumentError The input stream ended before a
155 well-formed XML document was parsed. Recovery from this error is
156 possible if more XML arrives in the stream, either by calling
157 addData() or by waiting for it to arrive on the device().
158
159 \value UnexpectedElementError The parser encountered an element
160 that was different to those it expected.
161
162*/
163
164/*!
165 \class QXmlStreamEntityResolver
166 \inmodule QtCore
167 \reentrant
168 \since 4.4
169
170 \brief The QXmlStreamEntityResolver class provides an entity
171 resolver for a QXmlStreamReader.
172
173 \ingroup xml-tools
174 */
175
176/*!
177 Destroys the entity resolver.
178 */
179QXmlStreamEntityResolver::~QXmlStreamEntityResolver()
180{
181}
182
183/*!
184 \internal
185
186This function is a stub for later functionality.
187*/
188QString QXmlStreamEntityResolver::resolveEntity(const QString& /*publicId*/, const QString& /*systemId*/)
189{
190 return QString();
191}
192
193
194/*!
195 Resolves the undeclared entity \a name and returns its replacement
196 text. If the entity is also unknown to the entity resolver, it
197 returns an empty string.
198
199 The default implementation always returns an empty string.
200*/
201
202QString QXmlStreamEntityResolver::resolveUndeclaredEntity(const QString &/*name*/)
203{
204 return QString();
205}
206
207#ifndef QT_NO_XMLSTREAMREADER
208
209QString QXmlStreamReaderPrivate::resolveUndeclaredEntity(const QString &name)
210{
211 if (entityResolver)
212 return entityResolver->resolveUndeclaredEntity(name);
213 return QString();
214}
215
216
217
218/*!
219 \since 4.4
220
221 Makes \a resolver the new entityResolver().
222
223 The stream reader does \e not take ownership of the resolver. It's
224 the callers responsibility to ensure that the resolver is valid
225 during the entire life-time of the stream reader object, or until
226 another resolver or \nullptr is set.
227
228 \sa entityResolver()
229 */
230void QXmlStreamReader::setEntityResolver(QXmlStreamEntityResolver *resolver)
231{
232 Q_D(QXmlStreamReader);
233 d->entityResolver = resolver;
234}
235
236/*!
237 \since 4.4
238
239 Returns the entity resolver, or \nullptr if there is no entity resolver.
240
241 \sa setEntityResolver()
242 */
243QXmlStreamEntityResolver *QXmlStreamReader::entityResolver() const
244{
245 Q_D(const QXmlStreamReader);
246 return d->entityResolver;
247}
248
249
250
251/*!
252 \class QXmlStreamReader
253 \inmodule QtCore
254 \reentrant
255 \since 4.3
256
257 \brief The QXmlStreamReader class provides a fast parser for reading
258 well-formed XML via a simple streaming API.
259
260
261 \ingroup xml-tools
262
263 QXmlStreamReader is a faster and more convenient replacement for
264 Qt's own SAX parser (see QXmlSimpleReader). In some cases it might
265 also be a faster and more convenient alternative for use in
266 applications that would otherwise use a DOM tree (see QDomDocument).
267 QXmlStreamReader reads data either from a QIODevice (see
268 setDevice()), or from a raw QByteArray (see addData()).
269
270 Qt provides QXmlStreamWriter for writing XML.
271
272 The basic concept of a stream reader is to report an XML document as
273 a stream of tokens, similar to SAX. The main difference between
274 QXmlStreamReader and SAX is \e how these XML tokens are reported.
275 With SAX, the application must provide handlers (callback functions)
276 that receive so-called XML \e events from the parser at the parser's
277 convenience. With QXmlStreamReader, the application code itself
278 drives the loop and pulls \e tokens from the reader, one after
279 another, as it needs them. This is done by calling readNext(), where
280 the reader reads from the input stream until it completes the next
281 token, at which point it returns the tokenType(). A set of
282 convenient functions including isStartElement() and text() can then
283 be used to examine the token to obtain information about what has
284 been read. The big advantage of this \e pulling approach is the
285 possibility to build recursive descent parsers with it, meaning you
286 can split your XML parsing code easily into different methods or
287 classes. This makes it easy to keep track of the application's own
288 state when parsing XML.
289
290 A typical loop with QXmlStreamReader looks like this:
291
292 \snippet code/src_corelib_xml_qxmlstream.cpp 0
293
294
295 QXmlStreamReader is a well-formed XML 1.0 parser that does \e not
296 include external parsed entities. As long as no error occurs, the
297 application code can thus be assured that the data provided by the
298 stream reader satisfies the W3C's criteria for well-formed XML. For
299 example, you can be certain that all tags are indeed nested and
300 closed properly, that references to internal entities have been
301 replaced with the correct replacement text, and that attributes have
302 been normalized or added according to the internal subset of the
303 DTD.
304
305 If an error occurs while parsing, atEnd() and hasError() return
306 true, and error() returns the error that occurred. The functions
307 errorString(), lineNumber(), columnNumber(), and characterOffset()
308 are for constructing an appropriate error or warning message. To
309 simplify application code, QXmlStreamReader contains a raiseError()
310 mechanism that lets you raise custom errors that trigger the same
311 error handling described.
312
313 The \l{QXmlStream Bookmarks Example} illustrates how to use the
314 recursive descent technique to read an XML bookmark file (XBEL) with
315 a stream reader.
316
317 \section1 Namespaces
318
319 QXmlStream understands and resolves XML namespaces. E.g. in case of
320 a StartElement, namespaceUri() returns the namespace the element is
321 in, and name() returns the element's \e local name. The combination
322 of namespaceUri and name uniquely identifies an element. If a
323 namespace prefix was not declared in the XML entities parsed by the
324 reader, the namespaceUri is empty.
325
326 If you parse XML data that does not utilize namespaces according to
327 the XML specification or doesn't use namespaces at all, you can use
328 the element's qualifiedName() instead. A qualified name is the
329 element's prefix() followed by colon followed by the element's local
330 name() - exactly like the element appears in the raw XML data. Since
331 the mapping namespaceUri to prefix is neither unique nor universal,
332 qualifiedName() should be avoided for namespace-compliant XML data.
333
334 In order to parse standalone documents that do use undeclared
335 namespace prefixes, you can turn off namespace processing completely
336 with the \l namespaceProcessing property.
337
338 \section1 Incremental Parsing
339
340 QXmlStreamReader is an incremental parser. It can handle the case
341 where the document can't be parsed all at once because it arrives in
342 chunks (e.g. from multiple files, or over a network connection).
343 When the reader runs out of data before the complete document has
344 been parsed, it reports a PrematureEndOfDocumentError. When more
345 data arrives, either because of a call to addData() or because more
346 data is available through the network device(), the reader recovers
347 from the PrematureEndOfDocumentError error and continues parsing the
348 new data with the next call to readNext().
349
350 For example, if your application reads data from the network using a
351 \l{QNetworkAccessManager} {network access manager}, you would issue
352 a \l{QNetworkRequest} {network request} to the manager and receive a
353 \l{QNetworkReply} {network reply} in return. Since a QNetworkReply
354 is a QIODevice, you connect its \l{QIODevice::readyRead()}
355 {readyRead()} signal to a custom slot, e.g. \c{slotReadyRead()} in
356 the code snippet shown in the discussion for QNetworkAccessManager.
357 In this slot, you read all available data with
358 \l{QIODevice::readAll()} {readAll()} and pass it to the XML
359 stream reader using addData(). Then you call your custom parsing
360 function that reads the XML events from the reader.
361
362 \section1 Performance and Memory Consumption
363
364 QXmlStreamReader is memory-conservative by design, since it doesn't
365 store the entire XML document tree in memory, but only the current
366 token at the time it is reported. In addition, QXmlStreamReader
367 avoids the many small string allocations that it normally takes to
368 map an XML document to a convenient and Qt-ish API. It does this by
369 reporting all string data as QStringRef rather than real QString
370 objects. QStringRef is a thin wrapper around QString substrings that
371 provides a subset of the QString API without the memory allocation
372 and reference-counting overhead. Calling
373 \l{QStringRef::toString()}{toString()} on any of those objects
374 returns an equivalent real QString object.
375
376*/
377
378
379/*!
380 Constructs a stream reader.
381
382 \sa setDevice(), addData()
383 */
384QXmlStreamReader::QXmlStreamReader()
385 : d_ptr(new QXmlStreamReaderPrivate(this))
386{
387}
388
389/*! Creates a new stream reader that reads from \a device.
390
391\sa setDevice(), clear()
392 */
393QXmlStreamReader::QXmlStreamReader(QIODevice *device)
394 : d_ptr(new QXmlStreamReaderPrivate(this))
395{
396 setDevice(device);
397}
398
399/*!
400 Creates a new stream reader that reads from \a data.
401
402 \sa addData(), clear(), setDevice()
403 */
404QXmlStreamReader::QXmlStreamReader(const QByteArray &data)
405 : d_ptr(new QXmlStreamReaderPrivate(this))
406{
407 Q_D(QXmlStreamReader);
408 d->dataBuffer = data;
409}
410
411/*!
412 Creates a new stream reader that reads from \a data.
413
414 This function should only be used if the XML header either says the encoding
415 is "UTF-8" or lacks any encoding information (the latter is the case of
416 QXmlStreamWriter writing to a QString). Any other encoding is likely going to
417 cause data corruption ("mojibake").
418
419 \sa addData(), clear(), setDevice()
420 */
421QXmlStreamReader::QXmlStreamReader(const QString &data)
422 : d_ptr(new QXmlStreamReaderPrivate(this))
423{
424 Q_D(QXmlStreamReader);
425#if !QT_CONFIG(textcodec)
426 d->dataBuffer = data.toLatin1();
427#else
428 d->dataBuffer = d->codec->fromUnicode(data);
429 d->decoder = d->codec->makeDecoder();
430#endif
431 d->lockEncoding = true;
432
433}
434
435/*!
436 Creates a new stream reader that reads from \a data.
437
438 \sa addData(), clear(), setDevice()
439 */
440QXmlStreamReader::QXmlStreamReader(const char *data)
441 : d_ptr(new QXmlStreamReaderPrivate(this))
442{
443 Q_D(QXmlStreamReader);
444 d->dataBuffer = QByteArray(data);
445}
446
447/*!
448 Destructs the reader.
449 */
450QXmlStreamReader::~QXmlStreamReader()
451{
452 Q_D(QXmlStreamReader);
453 if (d->deleteDevice)
454 delete d->device;
455}
456
457/*! \fn bool QXmlStreamReader::hasError() const
458 Returns \c true if an error has occurred, otherwise \c false.
459
460 \sa errorString(), error()
461 */
462
463/*!
464 Sets the current device to \a device. Setting the device resets
465 the stream to its initial state.
466
467 \sa device(), clear()
468*/
469void QXmlStreamReader::setDevice(QIODevice *device)
470{
471 Q_D(QXmlStreamReader);
472 if (d->deleteDevice) {
473 delete d->device;
474 d->deleteDevice = false;
475 }
476 d->device = device;
477 d->init();
478
479}
480
481/*!
482 Returns the current device associated with the QXmlStreamReader,
483 or \nullptr if no device has been assigned.
484
485 \sa setDevice()
486*/
487QIODevice *QXmlStreamReader::device() const
488{
489 Q_D(const QXmlStreamReader);
490 return d->device;
491}
492
493
494/*!
495 Adds more \a data for the reader to read. This function does
496 nothing if the reader has a device().
497
498 \sa readNext(), clear()
499 */
500void QXmlStreamReader::addData(const QByteArray &data)
501{
502 Q_D(QXmlStreamReader);
503 if (d->device) {
504 qWarning("QXmlStreamReader: addData() with device()");
505 return;
506 }
507 d->dataBuffer += data;
508}
509
510/*!
511 Adds more \a data for the reader to read. This function does
512 nothing if the reader has a device().
513
514 \sa readNext(), clear()
515 */
516void QXmlStreamReader::addData(const QString &data)
517{
518 Q_D(QXmlStreamReader);
519 d->lockEncoding = true;
520#if !QT_CONFIG(textcodec)
521 addData(data.toLatin1());
522#else
523 addData(d->codec->fromUnicode(data));
524#endif
525}
526
527/*!
528 Adds more \a data for the reader to read. This function does
529 nothing if the reader has a device().
530
531 \sa readNext(), clear()
532 */
533void QXmlStreamReader::addData(const char *data)
534{
535 addData(QByteArray(data));
536}
537
538/*!
539 Removes any device() or data from the reader and resets its
540 internal state to the initial state.
541
542 \sa addData()
543 */
544void QXmlStreamReader::clear()
545{
546 Q_D(QXmlStreamReader);
547 d->init();
548 if (d->device) {
549 if (d->deleteDevice)
550 delete d->device;
551 d->device = nullptr;
552 }
553}
554
555/*!
556 Returns \c true if the reader has read until the end of the XML
557 document, or if an error() has occurred and reading has been
558 aborted. Otherwise, it returns \c false.
559
560 When atEnd() and hasError() return true and error() returns
561 PrematureEndOfDocumentError, it means the XML has been well-formed
562 so far, but a complete XML document has not been parsed. The next
563 chunk of XML can be added with addData(), if the XML is being read
564 from a QByteArray, or by waiting for more data to arrive if the
565 XML is being read from a QIODevice. Either way, atEnd() will
566 return false once more data is available.
567
568 \sa hasError(), error(), device(), QIODevice::atEnd()
569 */
570bool QXmlStreamReader::atEnd() const
571{
572 Q_D(const QXmlStreamReader);
573 if (d->atEnd
574 && ((d->type == QXmlStreamReader::Invalid && d->error == PrematureEndOfDocumentError)
575 || (d->type == QXmlStreamReader::EndDocument))) {
576 if (d->device)
577 return d->device->atEnd();
578 else
579 return !d->dataBuffer.size();
580 }
581 return (d->atEnd || d->type == QXmlStreamReader::Invalid);
582}
583
584
585/*!
586 Reads the next token and returns its type.
587
588 With one exception, once an error() is reported by readNext(),
589 further reading of the XML stream is not possible. Then atEnd()
590 returns \c true, hasError() returns \c true, and this function returns
591 QXmlStreamReader::Invalid.
592
593 The exception is when error() returns PrematureEndOfDocumentError.
594 This error is reported when the end of an otherwise well-formed
595 chunk of XML is reached, but the chunk doesn't represent a complete
596 XML document. In that case, parsing \e can be resumed by calling
597 addData() to add the next chunk of XML, when the stream is being
598 read from a QByteArray, or by waiting for more data to arrive when
599 the stream is being read from a device().
600
601 \sa tokenType(), tokenString()
602 */
603QXmlStreamReader::TokenType QXmlStreamReader::readNext()
604{
605 Q_D(QXmlStreamReader);
606 if (d->type != Invalid) {
607 if (!d->hasCheckedStartDocument)
608 if (!d->checkStartDocument())
609 return d->type; // synthetic StartDocument or error
610 d->parse();
611 if (d->atEnd && d->type != EndDocument && d->type != Invalid)
612 d->raiseError(PrematureEndOfDocumentError);
613 else if (!d->atEnd && d->type == EndDocument)
614 d->raiseWellFormedError(QXmlStream::tr("Extra content at end of document."));
615 } else if (d->error == PrematureEndOfDocumentError) {
616 // resume error
617 d->type = NoToken;
618 d->atEnd = false;
619 d->token = -1;
620 return readNext();
621 }
622 return d->type;
623}
624
625
626/*!
627 Returns the type of the current token.
628
629 The current token can also be queried with the convenience functions
630 isStartDocument(), isEndDocument(), isStartElement(),
631 isEndElement(), isCharacters(), isComment(), isDTD(),
632 isEntityReference(), and isProcessingInstruction().
633
634 \sa tokenString()
635 */
636QXmlStreamReader::TokenType QXmlStreamReader::tokenType() const
637{
638 Q_D(const QXmlStreamReader);
639 return d->type;
640}
641
642/*!
643 Reads until the next start element within the current element. Returns \c true
644 when a start element was reached. When the end element was reached, or when
645 an error occurred, false is returned.
646
647 The current element is the element matching the most recently parsed start
648 element of which a matching end element has not yet been reached. When the
649 parser has reached the end element, the current element becomes the parent
650 element.
651
652 This is a convenience function for when you're only concerned with parsing
653 XML elements. The \l{QXmlStream Bookmarks Example} makes extensive use of
654 this function.
655
656 \since 4.6
657 \sa readNext()
658 */
659bool QXmlStreamReader::readNextStartElement()
660{
661 while (readNext() != Invalid) {
662 if (isEndElement())
663 return false;
664 else if (isStartElement())
665 return true;
666 }
667 return false;
668}
669
670/*!
671 Reads until the end of the current element, skipping any child nodes.
672 This function is useful for skipping unknown elements.
673
674 The current element is the element matching the most recently parsed start
675 element of which a matching end element has not yet been reached. When the
676 parser has reached the end element, the current element becomes the parent
677 element.
678
679 \since 4.6
680 */
681void QXmlStreamReader::skipCurrentElement()
682{
683 int depth = 1;
684 while (depth && readNext() != Invalid) {
685 if (isEndElement())
686 --depth;
687 else if (isStartElement())
688 ++depth;
689 }
690}
691
692/*
693 * Use the following Perl script to generate the error string index list:
694===== PERL SCRIPT ====
695print "static const char QXmlStreamReader_tokenTypeString_string[] =\n";
696$counter = 0;
697$i = 0;
698while (<STDIN>) {
699 chomp;
700 print " \"$_\\0\"\n";
701 $sizes[$i++] = $counter;
702 $counter += length 1 + $_;
703}
704print " \"\\0\";\n\nstatic const short QXmlStreamReader_tokenTypeString_indices[] = {\n ";
705for ($j = 0; $j < $i; ++$j) {
706 printf "$sizes[$j], ";
707}
708print "0\n};\n";
709===== PERL SCRIPT ====
710
711 * The input data is as follows (copied from qxmlstream.h):
712NoToken
713Invalid
714StartDocument
715EndDocument
716StartElement
717EndElement
718Characters
719Comment
720DTD
721EntityReference
722ProcessingInstruction
723*/
724static const char QXmlStreamReader_tokenTypeString_string[] =
725 "NoToken\0"
726 "Invalid\0"
727 "StartDocument\0"
728 "EndDocument\0"
729 "StartElement\0"
730 "EndElement\0"
731 "Characters\0"
732 "Comment\0"
733 "DTD\0"
734 "EntityReference\0"
735 "ProcessingInstruction\0";
736
737static const short QXmlStreamReader_tokenTypeString_indices[] = {
738 0, 8, 16, 30, 42, 55, 66, 77, 85, 89, 105, 0
739};
740
741
742/*!
743 \property QXmlStreamReader::namespaceProcessing
744 The namespace-processing flag of the stream reader
745
746 This property controls whether or not the stream reader processes
747 namespaces. If enabled, the reader processes namespaces, otherwise
748 it does not.
749
750 By default, namespace-processing is enabled.
751*/
752
753
754void QXmlStreamReader::setNamespaceProcessing(bool enable)
755{
756 Q_D(QXmlStreamReader);
757 d->namespaceProcessing = enable;
758}
759
760bool QXmlStreamReader::namespaceProcessing() const
761{
762 Q_D(const QXmlStreamReader);
763 return d->namespaceProcessing;
764}
765
766/*! Returns the reader's current token as string.
767
768\sa tokenType()
769*/
770QString QXmlStreamReader::tokenString() const
771{
772 Q_D(const QXmlStreamReader);
773 return QLatin1String(QXmlStreamReader_tokenTypeString_string +
774 QXmlStreamReader_tokenTypeString_indices[d->type]);
775}
776
777#endif // QT_NO_XMLSTREAMREADER
778
779QXmlStreamPrivateTagStack::QXmlStreamPrivateTagStack()
780{
781 tagStack.reserve(16);
782 tagStackStringStorage.reserve(32);
783 tagStackStringStorageSize = 0;
784 NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.push();
785 namespaceDeclaration.prefix = addToStringStorage(u"xml");
786 namespaceDeclaration.namespaceUri = addToStringStorage(u"http://www.w3.org/XML/1998/namespace");
787 initialTagStackStringStorageSize = tagStackStringStorageSize;
788}
789
790#ifndef QT_NO_XMLSTREAMREADER
791
792QXmlStreamReaderPrivate::QXmlStreamReaderPrivate(QXmlStreamReader *q)
793 :q_ptr(q)
794{
795 device = nullptr;
796 deleteDevice = false;
797#if QT_CONFIG(textcodec)
798 decoder = nullptr;
799#endif
800 stack_size = 64;
801 sym_stack = nullptr;
802 state_stack = nullptr;
803 reallocateStack();
804 entityResolver = nullptr;
805 init();
806#define ADD_PREDEFINED(n, v) \
807 do { \
808 Entity e = Entity::createLiteral(QLatin1String(n), QLatin1String(v)); \
809 entityHash.insert(qToStringViewIgnoringNull(e.name), std::move(e)); \
810 } while (false)
811 ADD_PREDEFINED("lt", "<");
812 ADD_PREDEFINED("gt", ">");
813 ADD_PREDEFINED("amp", "&");
814 ADD_PREDEFINED("apos", "'");
815 ADD_PREDEFINED("quot", "\"");
816#undef ADD_PREDEFINED
817}
818
819void QXmlStreamReaderPrivate::init()
820{
821 scanDtd = false;
822 token = -1;
823 token_char = 0;
824 isEmptyElement = false;
825 isWhitespace = true;
826 isCDATA = false;
827 standalone = false;
828 tos = 0;
829 resumeReduction = 0;
830 state_stack[tos++] = 0;
831 state_stack[tos] = 0;
832 putStack.clear();
833 putStack.reserve(32);
834 textBuffer.clear();
835 textBuffer.reserve(256);
836 tagStack.clear();
837 tagsDone = false;
838 attributes.clear();
839 attributes.reserve(16);
840 lineNumber = lastLineStart = characterOffset = 0;
841 readBufferPos = 0;
842 nbytesread = 0;
843#if QT_CONFIG(textcodec)
844 codec = QTextCodec::codecForMib(106); // utf8
845 delete decoder;
846 decoder = nullptr;
847#endif
848 attributeStack.clear();
849 attributeStack.reserve(16);
850 entityParser = nullptr;
851 hasCheckedStartDocument = false;
852 normalizeLiterals = false;
853 hasSeenTag = false;
854 atEnd = false;
855 inParseEntity = false;
856 referenceToUnparsedEntityDetected = false;
857 referenceToParameterEntityDetected = false;
858 hasExternalDtdSubset = false;
859 lockEncoding = false;
860 namespaceProcessing = true;
861 rawReadBuffer.clear();
862 dataBuffer.clear();
863 readBuffer.clear();
864 tagStackStringStorageSize = initialTagStackStringStorageSize;
865
866 type = QXmlStreamReader::NoToken;
867 error = QXmlStreamReader::NoError;
868}
869
870/*
871 Well-formed requires that we verify entity values. We do this with a
872 standard parser.
873 */
874void QXmlStreamReaderPrivate::parseEntity(const QString &value)
875{
876 Q_Q(QXmlStreamReader);
877
878 if (value.isEmpty())
879 return;
880
881
882 if (!entityParser)
883 entityParser = new QXmlStreamReaderPrivate(q);
884 else
885 entityParser->init();
886 entityParser->inParseEntity = true;
887 entityParser->readBuffer = value;
888 entityParser->injectToken(PARSE_ENTITY);
889 while (!entityParser->atEnd && entityParser->type != QXmlStreamReader::Invalid)
890 entityParser->parse();
891 if (entityParser->type == QXmlStreamReader::Invalid || entityParser->tagStack.size())
892 raiseWellFormedError(QXmlStream::tr("Invalid entity value."));
893
894}
895
896inline void QXmlStreamReaderPrivate::reallocateStack()
897{
898 stack_size <<= 1;
899 sym_stack = reinterpret_cast<Value*> (realloc(sym_stack, stack_size * sizeof(Value)));
900 Q_CHECK_PTR(sym_stack);
901 state_stack = reinterpret_cast<int*> (realloc(state_stack, stack_size * sizeof(int)));
902 Q_CHECK_PTR(state_stack);
903}
904
905
906QXmlStreamReaderPrivate::~QXmlStreamReaderPrivate()
907{
908#if QT_CONFIG(textcodec)
909 delete decoder;
910#endif
911 free(sym_stack);
912 free(state_stack);
913 delete entityParser;
914}
915
916
917inline uint QXmlStreamReaderPrivate::filterCarriageReturn()
918{
919 uint peekc = peekChar();
920 if (peekc == '\n') {
921 if (putStack.size())
922 putStack.pop();
923 else
924 ++readBufferPos;
925 return peekc;
926 }
927 if (peekc == StreamEOF) {
928 putChar('\r');
929 return 0;
930 }
931 return '\n';
932}
933
934/*!
935 \internal
936 If the end of the file is encountered, ~0 is returned.
937 */
938inline uint QXmlStreamReaderPrivate::getChar()
939{
940 uint c;
941 if (putStack.size()) {
942 c = atEnd ? StreamEOF : putStack.pop();
943 } else {
944 if (readBufferPos < readBuffer.size())
945 c = readBuffer.at(readBufferPos++).unicode();
946 else
947 c = getChar_helper();
948 }
949
950 return c;
951}
952
953inline uint QXmlStreamReaderPrivate::peekChar()
954{
955 uint c;
956 if (putStack.size()) {
957 c = putStack.top();
958 } else if (readBufferPos < readBuffer.size()) {
959 c = readBuffer.at(readBufferPos).unicode();
960 } else {
961 if ((c = getChar_helper()) != StreamEOF)
962 --readBufferPos;
963 }
964
965 return c;
966}
967
968/*!
969 \internal
970
971 Scans characters until \a str is encountered, and validates the characters
972 as according to the Char[2] production and do the line-ending normalization.
973 If any character is invalid, false is returned, otherwise true upon success.
974
975 If \a tokenToInject is not less than zero, injectToken() is called with
976 \a tokenToInject when \a str is found.
977
978 If any error occurred, false is returned, otherwise true.
979 */
980bool QXmlStreamReaderPrivate::scanUntil(const char *str, short tokenToInject)
981{
982 int pos = textBuffer.size();
983 int oldLineNumber = lineNumber;
984
985 uint c;
986 while ((c = getChar()) != StreamEOF) {
987 /* First, we do the validation & normalization. */
988 switch (c) {
989 case '\r':
990 if ((c = filterCarriageReturn()) == 0)
991 break;
992 Q_FALLTHROUGH();
993 case '\n':
994 ++lineNumber;
995 lastLineStart = characterOffset + readBufferPos;
996 Q_FALLTHROUGH();
997 case '\t':
998 textBuffer += QChar(c);
999 continue;
1000 default:
1001 if (c < 0x20 || (c > 0xFFFD && c < 0x10000) || c > QChar::LastValidCodePoint ) {
1002 raiseWellFormedError(QXmlStream::tr("Invalid XML character."));
1003 lineNumber = oldLineNumber;
1004 return false;
1005 }
1006 textBuffer += QChar(c);
1007 }
1008
1009
1010 /* Second, attempt to lookup str. */
1011 if (c == uint(*str)) {
1012 if (!*(str + 1)) {
1013 if (tokenToInject >= 0)
1014 injectToken(tokenToInject);
1015 return true;
1016 } else {
1017 if (scanString(str + 1, tokenToInject, false))
1018 return true;
1019 }
1020 }
1021 }
1022 putString(textBuffer, pos);
1023 textBuffer.resize(pos);
1024 lineNumber = oldLineNumber;
1025 return false;
1026}
1027
1028bool QXmlStreamReaderPrivate::scanString(const char *str, short tokenToInject, bool requireSpace)
1029{
1030 int n = 0;
1031 while (str[n]) {
1032 uint c = getChar();
1033 if (c != ushort(str[n])) {
1034 if (c != StreamEOF)
1035 putChar(c);
1036 while (n--) {
1037 putChar(ushort(str[n]));
1038 }
1039 return false;
1040 }
1041 ++n;
1042 }
1043 for (int i = 0; i < n; ++i)
1044 textBuffer += QChar(ushort(str[i]));
1045 if (requireSpace) {
1046 int s = fastScanSpace();
1047 if (!s || atEnd) {
1048 int pos = textBuffer.size() - n - s;
1049 putString(textBuffer, pos);
1050 textBuffer.resize(pos);
1051 return false;
1052 }
1053 }
1054 if (tokenToInject >= 0)
1055 injectToken(tokenToInject);
1056 return true;
1057}
1058
1059bool QXmlStreamReaderPrivate::scanAfterLangleBang()
1060{
1061 switch (peekChar()) {
1062 case '[':
1063 return scanString(spell[CDATA_START], CDATA_START, false);
1064 case 'D':
1065 return scanString(spell[DOCTYPE], DOCTYPE);
1066 case 'A':
1067 return scanString(spell[ATTLIST], ATTLIST);
1068 case 'N':
1069 return scanString(spell[NOTATION], NOTATION);
1070 case 'E':
1071 if (scanString(spell[ELEMENT], ELEMENT))
1072 return true;
1073 return scanString(spell[ENTITY], ENTITY);
1074
1075 default:
1076 ;
1077 };
1078 return false;
1079}
1080
1081bool QXmlStreamReaderPrivate::scanPublicOrSystem()
1082{
1083 switch (peekChar()) {
1084 case 'S':
1085 return scanString(spell[SYSTEM], SYSTEM);
1086 case 'P':
1087 return scanString(spell[PUBLIC], PUBLIC);
1088 default:
1089 ;
1090 }
1091 return false;
1092}
1093
1094bool QXmlStreamReaderPrivate::scanNData()
1095{
1096 if (fastScanSpace()) {
1097 if (scanString(spell[NDATA], NDATA))
1098 return true;
1099 putChar(' ');
1100 }
1101 return false;
1102}
1103
1104bool QXmlStreamReaderPrivate::scanAfterDefaultDecl()
1105{
1106 switch (peekChar()) {
1107 case 'R':
1108 return scanString(spell[REQUIRED], REQUIRED, false);
1109 case 'I':
1110 return scanString(spell[IMPLIED], IMPLIED, false);
1111 case 'F':
1112 return scanString(spell[FIXED], FIXED, false);
1113 default:
1114 ;
1115 }
1116 return false;
1117}
1118
1119bool QXmlStreamReaderPrivate::scanAttType()
1120{
1121 switch (peekChar()) {
1122 case 'C':
1123 return scanString(spell[CDATA], CDATA);
1124 case 'I':
1125 if (scanString(spell[ID], ID))
1126 return true;
1127 if (scanString(spell[IDREF], IDREF))
1128 return true;
1129 return scanString(spell[IDREFS], IDREFS);
1130 case 'E':
1131 if (scanString(spell[ENTITY], ENTITY))
1132 return true;
1133 return scanString(spell[ENTITIES], ENTITIES);
1134 case 'N':
1135 if (scanString(spell[NOTATION], NOTATION))
1136 return true;
1137 if (scanString(spell[NMTOKEN], NMTOKEN))
1138 return true;
1139 return scanString(spell[NMTOKENS], NMTOKENS);
1140 default:
1141 ;
1142 }
1143 return false;
1144}
1145
1146/*!
1147 \internal
1148
1149 Scan strings with quotes or apostrophes surround them. For instance,
1150 attributes, the version and encoding field in the XML prolog and
1151 entity declarations.
1152
1153 If normalizeLiterals is set to true, the function also normalizes
1154 whitespace. It is set to true when the first start tag is
1155 encountered.
1156
1157 */
1158inline int QXmlStreamReaderPrivate::fastScanLiteralContent()
1159{
1160 int n = 0;
1161 uint c;
1162 while ((c = getChar()) != StreamEOF) {
1163 switch (ushort(c)) {
1164 case 0xfffe:
1165 case 0xffff:
1166 case 0:
1167 /* The putChar() call is necessary so the parser re-gets
1168 * the character from the input source, when raising an error. */
1169 putChar(c);
1170 return n;
1171 case '\r':
1172 if (filterCarriageReturn() == 0)
1173 return n;
1174 Q_FALLTHROUGH();
1175 case '\n':
1176 ++lineNumber;
1177 lastLineStart = characterOffset + readBufferPos;
1178 Q_FALLTHROUGH();
1179 case ' ':
1180 case '\t':
1181 if (normalizeLiterals)
1182 textBuffer += QLatin1Char(' ');
1183 else
1184 textBuffer += QChar(c);
1185 ++n;
1186 break;
1187 case '&':
1188 case '<':
1189 case '\"':
1190 case '\'':
1191 if (!(c & 0xff0000)) {
1192 putChar(c);
1193 return n;
1194 }
1195 Q_FALLTHROUGH();
1196 default:
1197 if (c < 0x20) {
1198 putChar(c);
1199 return n;
1200 }
1201 textBuffer += QChar(c);
1202 ++n;
1203 }
1204 }
1205 return n;
1206}
1207
1208inline int QXmlStreamReaderPrivate::fastScanSpace()
1209{
1210 int n = 0;
1211 uint c;
1212 while ((c = getChar()) != StreamEOF) {
1213 switch (c) {
1214 case '\r':
1215 if ((c = filterCarriageReturn()) == 0)
1216 return n;
1217 Q_FALLTHROUGH();
1218 case '\n':
1219 ++lineNumber;
1220 lastLineStart = characterOffset + readBufferPos;
1221 Q_FALLTHROUGH();
1222 case ' ':
1223 case '\t':
1224 textBuffer += QChar(c);
1225 ++n;
1226 break;
1227 default:
1228 putChar(c);
1229 return n;
1230 }
1231 }
1232 return n;
1233}
1234
1235/*!
1236 \internal
1237
1238 Used for text nodes essentially. That is, characters appearing
1239 inside elements.
1240 */
1241inline int QXmlStreamReaderPrivate::fastScanContentCharList()
1242{
1243 int n = 0;
1244 uint c;
1245 while ((c = getChar()) != StreamEOF) {
1246 switch (ushort(c)) {
1247 case 0xfffe:
1248 case 0xffff:
1249 case 0:
1250 putChar(c);
1251 return n;
1252 case ']': {
1253 isWhitespace = false;
1254 int pos = textBuffer.size();
1255 textBuffer += QChar(ushort(c));
1256 ++n;
1257 while ((c = getChar()) == ']') {
1258 textBuffer += QChar(ushort(c));
1259 ++n;
1260 }
1261 if (c == 0) {
1262 putString(textBuffer, pos);
1263 textBuffer.resize(pos);
1264 } else if (c == '>' && textBuffer.at(textBuffer.size()-2) == QLatin1Char(']')) {
1265 raiseWellFormedError(QXmlStream::tr("Sequence ']]>' not allowed in content."));
1266 } else {
1267 putChar(c);
1268 break;
1269 }
1270 return n;
1271 } break;
1272 case '\r':
1273 if ((c = filterCarriageReturn()) == 0)
1274 return n;
1275 Q_FALLTHROUGH();
1276 case '\n':
1277 ++lineNumber;
1278 lastLineStart = characterOffset + readBufferPos;
1279 Q_FALLTHROUGH();
1280 case ' ':
1281 case '\t':
1282 textBuffer += QChar(ushort(c));
1283 ++n;
1284 break;
1285 case '&':
1286 case '<':
1287 if (!(c & 0xff0000)) {
1288 putChar(c);
1289 return n;
1290 }
1291 Q_FALLTHROUGH();
1292 default:
1293 if (c < 0x20) {
1294 putChar(c);
1295 return n;
1296 }
1297 isWhitespace = false;
1298 textBuffer += QChar(ushort(c));
1299 ++n;
1300 }
1301 }
1302 return n;
1303}
1304
1305inline int QXmlStreamReaderPrivate::fastScanName(int *prefix)
1306{
1307 int n = 0;
1308 uint c;
1309 while ((c = getChar()) != StreamEOF) {
1310 switch (c) {
1311 case '\n':
1312 case ' ':
1313 case '\t':
1314 case '\r':
1315 case '&':
1316 case '#':
1317 case '\'':
1318 case '\"':
1319 case '<':
1320 case '>':
1321 case '[':
1322 case ']':
1323 case '=':
1324 case '%':
1325 case '/':
1326 case ';':
1327 case '?':
1328 case '!':
1329 case '^':
1330 case '|':
1331 case ',':
1332 case '(':
1333 case ')':
1334 case '+':
1335 case '*':
1336 putChar(c);
1337 if (prefix && *prefix == n+1) {
1338 *prefix = 0;
1339 putChar(':');
1340 --n;
1341 }
1342 return n;
1343 case ':':
1344 if (prefix) {
1345 if (*prefix == 0) {
1346 *prefix = n+2;
1347 } else { // only one colon allowed according to the namespace spec.
1348 putChar(c);
1349 return n;
1350 }
1351 } else {
1352 putChar(c);
1353 return n;
1354 }
1355 Q_FALLTHROUGH();
1356 default:
1357 textBuffer += QChar(c);
1358 ++n;
1359 }
1360 }
1361
1362 if (prefix)
1363 *prefix = 0;
1364 int pos = textBuffer.size() - n;
1365 putString(textBuffer, pos);
1366 textBuffer.resize(pos);
1367 return 0;
1368}
1369
1370enum NameChar { NameBeginning, NameNotBeginning, NotName };
1371
1372static const char Begi = static_cast<char>(NameBeginning);
1373static const char NtBg = static_cast<char>(NameNotBeginning);
1374static const char NotN = static_cast<char>(NotName);
1375
1376static const char nameCharTable[128] =
1377{
1378// 0x00
1379 NotN, NotN, NotN, NotN, NotN, NotN, NotN, NotN,
1380 NotN, NotN, NotN, NotN, NotN, NotN, NotN, NotN,
1381// 0x10
1382 NotN, NotN, NotN, NotN, NotN, NotN, NotN, NotN,
1383 NotN, NotN, NotN, NotN, NotN, NotN, NotN, NotN,
1384// 0x20 (0x2D is '-', 0x2E is '.')
1385 NotN, NotN, NotN, NotN, NotN, NotN, NotN, NotN,
1386 NotN, NotN, NotN, NotN, NotN, NtBg, NtBg, NotN,
1387// 0x30 (0x30..0x39 are '0'..'9', 0x3A is ':')
1388 NtBg, NtBg, NtBg, NtBg, NtBg, NtBg, NtBg, NtBg,
1389 NtBg, NtBg, Begi, NotN, NotN, NotN, NotN, NotN,
1390// 0x40 (0x41..0x5A are 'A'..'Z')
1391 NotN, Begi, Begi, Begi, Begi, Begi, Begi, Begi,
1392 Begi, Begi, Begi, Begi, Begi, Begi, Begi, Begi,
1393// 0x50 (0x5F is '_')
1394 Begi, Begi, Begi, Begi, Begi, Begi, Begi, Begi,
1395 Begi, Begi, Begi, NotN, NotN, NotN, NotN, Begi,
1396// 0x60 (0x61..0x7A are 'a'..'z')
1397 NotN, Begi, Begi, Begi, Begi, Begi, Begi, Begi,
1398 Begi, Begi, Begi, Begi, Begi, Begi, Begi, Begi,
1399// 0x70
1400 Begi, Begi, Begi, Begi, Begi, Begi, Begi, Begi,
1401 Begi, Begi, Begi, NotN, NotN, NotN, NotN, NotN
1402};
1403
1404static inline NameChar fastDetermineNameChar(QChar ch)
1405{
1406 ushort uc = ch.unicode();
1407 if (!(uc & ~0x7f)) // uc < 128
1408 return static_cast<NameChar>(nameCharTable[uc]);
1409
1410 QChar::Category cat = ch.category();
1411 // ### some these categories might be slightly wrong
1412 if ((cat >= QChar::Letter_Uppercase && cat <= QChar::Letter_Other)
1413 || cat == QChar::Number_Letter)
1414 return NameBeginning;
1415 if ((cat >= QChar::Number_DecimalDigit && cat <= QChar::Number_Other)
1416 || (cat >= QChar::Mark_NonSpacing && cat <= QChar::Mark_Enclosing))
1417 return NameNotBeginning;
1418 return NotName;
1419}
1420
1421inline int QXmlStreamReaderPrivate::fastScanNMTOKEN()
1422{
1423 int n = 0;
1424 uint c;
1425 while ((c = getChar()) != StreamEOF) {
1426 if (fastDetermineNameChar(QChar(c)) == NotName) {
1427 putChar(c);
1428 return n;
1429 } else {
1430 ++n;
1431 textBuffer += QChar(c);
1432 }
1433 }
1434
1435 int pos = textBuffer.size() - n;
1436 putString(textBuffer, pos);
1437 textBuffer.resize(pos);
1438
1439 return n;
1440}
1441
1442void QXmlStreamReaderPrivate::putString(const QString &s, int from)
1443{
1444 putStack.reserve(s.size());
1445 for (int i = s.size()-1; i >= from; --i)
1446 putStack.rawPush() = s.at(i).unicode();
1447}
1448
1449void QXmlStreamReaderPrivate::putStringLiteral(const QString &s)
1450{
1451 putStack.reserve(s.size());
1452 for (int i = s.size()-1; i >= 0; --i)
1453 putStack.rawPush() = ((LETTER << 16) | s.at(i).unicode());
1454}
1455
1456void QXmlStreamReaderPrivate::putReplacement(const QString &s)
1457{
1458 putStack.reserve(s.size());
1459 for (int i = s.size()-1; i >= 0; --i) {
1460 ushort c = s.at(i).unicode();
1461 if (c == '\n' || c == '\r')
1462 putStack.rawPush() = ((LETTER << 16) | c);
1463 else
1464 putStack.rawPush() = c;
1465 }
1466}
1467void QXmlStreamReaderPrivate::putReplacementInAttributeValue(const QString &s)
1468{
1469 putStack.reserve(s.size());
1470 for (int i = s.size()-1; i >= 0; --i) {
1471 ushort c = s.at(i).unicode();
1472 if (c == '&' || c == ';')
1473 putStack.rawPush() = c;
1474 else if (c == '\n' || c == '\r')
1475 putStack.rawPush() = ' ';
1476 else
1477 putStack.rawPush() = ((LETTER << 16) | c);
1478 }
1479}
1480
1481uint QXmlStreamReaderPrivate::getChar_helper()
1482{
1483 const int BUFFER_SIZE = 8192;
1484 characterOffset += readBufferPos;
1485 readBufferPos = 0;
1486 readBuffer.resize(0);
1487#if QT_CONFIG(textcodec)
1488 if (decoder)
1489#endif
1490 nbytesread = 0;
1491 if (device) {
1492 rawReadBuffer.resize(BUFFER_SIZE);
1493 int nbytesreadOrMinus1 = device->read(rawReadBuffer.data() + nbytesread, BUFFER_SIZE - nbytesread);
1494 nbytesread += qMax(nbytesreadOrMinus1, 0);
1495 } else {
1496 if (nbytesread)
1497 rawReadBuffer += dataBuffer;
1498 else
1499 rawReadBuffer = dataBuffer;
1500 nbytesread = rawReadBuffer.size();
1501 dataBuffer.clear();
1502 }
1503 if (!nbytesread) {
1504 atEnd = true;
1505 return StreamEOF;
1506 }
1507
1508#if QT_CONFIG(textcodec)
1509 if (!decoder) {
1510 if (nbytesread < 4) { // the 4 is to cover 0xef 0xbb 0xbf plus
1511 // one extra for the utf8 codec
1512 atEnd = true;
1513 return StreamEOF;
1514 }
1515 int mib = 106; // UTF-8
1516
1517 // look for byte order mark
1518 uchar ch1 = rawReadBuffer.at(0);
1519 uchar ch2 = rawReadBuffer.at(1);
1520 uchar ch3 = rawReadBuffer.at(2);
1521 uchar ch4 = rawReadBuffer.at(3);
1522
1523 if ((ch1 == 0 && ch2 == 0 && ch3 == 0xfe && ch4 == 0xff) ||
1524 (ch1 == 0xff && ch2 == 0xfe && ch3 == 0 && ch4 == 0))
1525 mib = 1017; // UTF-32 with byte order mark
1526 else if (ch1 == 0x3c && ch2 == 0x00 && ch3 == 0x00 && ch4 == 0x00)
1527 mib = 1019; // UTF-32LE
1528 else if (ch1 == 0x00 && ch2 == 0x00 && ch3 == 0x00 && ch4 == 0x3c)
1529 mib = 1018; // UTF-32BE
1530 else if ((ch1 == 0xfe && ch2 == 0xff) || (ch1 == 0xff && ch2 == 0xfe))
1531 mib = 1015; // UTF-16 with byte order mark
1532 else if (ch1 == 0x3c && ch2 == 0x00)
1533 mib = 1014; // UTF-16LE
1534 else if (ch1 == 0x00 && ch2 == 0x3c)
1535 mib = 1013; // UTF-16BE
1536 codec = QTextCodec::codecForMib(mib);
1537 Q_ASSERT(codec);
1538 decoder = codec->makeDecoder();
1539 }
1540
1541 decoder->toUnicode(&readBuffer, rawReadBuffer.constData(), nbytesread);
1542
1543 if(lockEncoding && decoder->hasFailure()) {
1544 raiseWellFormedError(QXmlStream::tr("Encountered incorrectly encoded content."));
1545 readBuffer.clear();
1546 return StreamEOF;
1547 }
1548#else
1549 readBuffer = QString::fromLatin1(rawReadBuffer.data(), nbytesread);
1550#endif // textcodec
1551
1552 readBuffer.reserve(1); // keep capacity when calling resize() next time
1553
1554 if (readBufferPos < readBuffer.size()) {
1555 ushort c = readBuffer.at(readBufferPos++).unicode();
1556 return c;
1557 }
1558
1559 atEnd = true;
1560 return StreamEOF;
1561}
1562
1563QStringRef QXmlStreamReaderPrivate::namespaceForPrefix(const QStringRef &prefix)
1564{
1565 for (int j = namespaceDeclarations.size() - 1; j >= 0; --j) {
1566 const NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.at(j);
1567 if (namespaceDeclaration.prefix == prefix) {
1568 return namespaceDeclaration.namespaceUri;
1569 }
1570 }
1571
1572#if 1
1573 if (namespaceProcessing && !prefix.isEmpty())
1574 raiseWellFormedError(QXmlStream::tr("Namespace prefix '%1' not declared").arg(prefix));
1575#endif
1576
1577 return QStringRef();
1578}
1579
1580/*
1581 uses namespaceForPrefix and builds the attribute vector
1582 */
1583void QXmlStreamReaderPrivate::resolveTag()
1584{
1585 int n = attributeStack.size();
1586
1587 if (namespaceProcessing) {
1588 for (int a = 0; a < dtdAttributes.size(); ++a) {
1589 DtdAttribute &dtdAttribute = dtdAttributes[a];
1590 if (!dtdAttribute.isNamespaceAttribute
1591 || dtdAttribute.defaultValue.isNull()
1592 || dtdAttribute.tagName != qualifiedName
1593 || dtdAttribute.attributeQualifiedName.isNull())
1594 continue;
1595 int i = 0;
1596 while (i < n && symName(attributeStack[i].key) != dtdAttribute.attributeQualifiedName)
1597 ++i;
1598 if (i != n)
1599 continue;
1600 if (dtdAttribute.attributePrefix.isEmpty() && dtdAttribute.attributeName == QLatin1String("xmlns")) {
1601 NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.push();
1602 namespaceDeclaration.prefix.clear();
1603
1604 const QStringRef ns(dtdAttribute.defaultValue);
1605 if(ns == QLatin1String("http://www.w3.org/2000/xmlns/") ||
1606 ns == QLatin1String("http://www.w3.org/XML/1998/namespace"))
1607 raiseWellFormedError(QXmlStream::tr("Illegal namespace declaration."));
1608 else
1609 namespaceDeclaration.namespaceUri = ns;
1610 } else if (dtdAttribute.attributePrefix == QLatin1String("xmlns")) {
1611 NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.push();
1612 QStringRef namespacePrefix = dtdAttribute.attributeName;
1613 QStringRef namespaceUri = dtdAttribute.defaultValue;
1614 if (((namespacePrefix == QLatin1String("xml"))
1615 ^ (namespaceUri == QLatin1String("http://www.w3.org/XML/1998/namespace")))
1616 || namespaceUri == QLatin1String("http://www.w3.org/2000/xmlns/")
1617 || namespaceUri.isEmpty()
1618 || namespacePrefix == QLatin1String("xmlns"))
1619 raiseWellFormedError(QXmlStream::tr("Illegal namespace declaration."));
1620
1621 namespaceDeclaration.prefix = namespacePrefix;
1622 namespaceDeclaration.namespaceUri = namespaceUri;
1623 }
1624 }
1625 }
1626
1627 tagStack.top().namespaceDeclaration.namespaceUri = namespaceUri = namespaceForPrefix(prefix);
1628
1629 attributes.resize(n);
1630
1631 for (int i = 0; i < n; ++i) {
1632 QXmlStreamAttribute &attribute = attributes[i];
1633 Attribute &attrib = attributeStack[i];
1634 QStringRef prefix(symPrefix(attrib.key));
1635 QStringRef name(symString(attrib.key));
1636 QStringRef qualifiedName(symName(attrib.key));
1637 QStringRef value(symString(attrib.value));
1638
1639 attribute.m_name = QXmlStreamStringRef(name);
1640 attribute.m_qualifiedName = QXmlStreamStringRef(qualifiedName);
1641 attribute.m_value = QXmlStreamStringRef(value);
1642
1643 if (!prefix.isEmpty()) {
1644 QStringRef attributeNamespaceUri = namespaceForPrefix(prefix);
1645 attribute.m_namespaceUri = QXmlStreamStringRef(attributeNamespaceUri);
1646 }
1647
1648 for (int j = 0; j < i; ++j) {
1649 if (attributes[j].name() == attribute.name()
1650 && attributes[j].namespaceUri() == attribute.namespaceUri()
1651 && (namespaceProcessing || attributes[j].qualifiedName() == attribute.qualifiedName()))
1652 raiseWellFormedError(QXmlStream::tr("Attribute '%1' redefined.").arg(attribute.qualifiedName()));
1653 }
1654 }
1655
1656 for (int a = 0; a < dtdAttributes.size(); ++a) {
1657 DtdAttribute &dtdAttribute = dtdAttributes[a];
1658 if (dtdAttribute.isNamespaceAttribute
1659 || dtdAttribute.defaultValue.isNull()
1660 || dtdAttribute.tagName != qualifiedName
1661 || dtdAttribute.attributeQualifiedName.isNull())
1662 continue;
1663 int i = 0;
1664 while (i < n && symName(attributeStack[i].key) != dtdAttribute.attributeQualifiedName)
1665 ++i;
1666 if (i != n)
1667 continue;
1668
1669
1670
1671 QXmlStreamAttribute attribute;
1672 attribute.m_name = QXmlStreamStringRef(dtdAttribute.attributeName);
1673 attribute.m_qualifiedName = QXmlStreamStringRef(dtdAttribute.attributeQualifiedName);
1674 attribute.m_value = QXmlStreamStringRef(dtdAttribute.defaultValue);
1675
1676 if (!dtdAttribute.attributePrefix.isEmpty()) {
1677 QStringRef attributeNamespaceUri = namespaceForPrefix(dtdAttribute.attributePrefix);
1678 attribute.m_namespaceUri = QXmlStreamStringRef(attributeNamespaceUri);
1679 }
1680 attribute.m_isDefault = true;
1681 attributes.append(attribute);
1682 }
1683
1684 attributeStack.clear();
1685}
1686
1687void QXmlStreamReaderPrivate::resolvePublicNamespaces()
1688{
1689 const Tag &tag = tagStack.top();
1690 int n = namespaceDeclarations.size() - tag.namespaceDeclarationsSize;
1691 publicNamespaceDeclarations.resize(n);
1692 for (int i = 0; i < n; ++i) {
1693 const NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.at(tag.namespaceDeclarationsSize + i);
1694 QXmlStreamNamespaceDeclaration &publicNamespaceDeclaration = publicNamespaceDeclarations[i];
1695 publicNamespaceDeclaration.m_prefix = QXmlStreamStringRef(namespaceDeclaration.prefix);
1696 publicNamespaceDeclaration.m_namespaceUri = QXmlStreamStringRef(namespaceDeclaration.namespaceUri);
1697 }
1698}
1699
1700void QXmlStreamReaderPrivate::resolveDtd()
1701{
1702 publicNotationDeclarations.resize(notationDeclarations.size());
1703 for (int i = 0; i < notationDeclarations.size(); ++i) {
1704 const QXmlStreamReaderPrivate::NotationDeclaration &notationDeclaration = notationDeclarations.at(i);
1705 QXmlStreamNotationDeclaration &publicNotationDeclaration = publicNotationDeclarations[i];
1706 publicNotationDeclaration.m_name = QXmlStreamStringRef(notationDeclaration.name);
1707 publicNotationDeclaration.m_systemId = QXmlStreamStringRef(notationDeclaration.systemId);
1708 publicNotationDeclaration.m_publicId = QXmlStreamStringRef(notationDeclaration.publicId);
1709
1710 }
1711 notationDeclarations.clear();
1712 publicEntityDeclarations.resize(entityDeclarations.size());
1713 for (int i = 0; i < entityDeclarations.size(); ++i) {
1714 const QXmlStreamReaderPrivate::EntityDeclaration &entityDeclaration = entityDeclarations.at(i);
1715 QXmlStreamEntityDeclaration &publicEntityDeclaration = publicEntityDeclarations[i];
1716 publicEntityDeclaration.m_name = QXmlStreamStringRef(entityDeclaration.name);
1717 publicEntityDeclaration.m_notationName = QXmlStreamStringRef(entityDeclaration.notationName);
1718 publicEntityDeclaration.m_systemId = QXmlStreamStringRef(entityDeclaration.systemId);
1719 publicEntityDeclaration.m_publicId = QXmlStreamStringRef(entityDeclaration.publicId);
1720 publicEntityDeclaration.m_value = QXmlStreamStringRef(entityDeclaration.value);
1721 }
1722 entityDeclarations.clear();
1723 parameterEntityHash.clear();
1724}
1725
1726uint QXmlStreamReaderPrivate::resolveCharRef(int symbolIndex)
1727{
1728 bool ok = true;
1729 uint s;
1730 // ### add toXShort to QStringRef?
1731 if (sym(symbolIndex).c == 'x')
1732 s = symString(symbolIndex, 1).toUInt(&ok, 16);
1733 else
1734 s = symString(symbolIndex).toUInt(&ok, 10);
1735
1736 ok &= (s == 0x9 || s == 0xa || s == 0xd || (s >= 0x20 && s <= 0xd7ff)
1737 || (s >= 0xe000 && s <= 0xfffd) || (s >= 0x10000 && s <= QChar::LastValidCodePoint));
1738
1739 return ok ? s : 0;
1740}
1741
1742
1743void QXmlStreamReaderPrivate::checkPublicLiteral(const QStringRef &publicId)
1744{
1745//#x20 | #xD | #xA | [a-zA-Z0-9] | [-'()+,./:=?;!*#@$_%]
1746
1747 const ushort *data = reinterpret_cast<const ushort *>(publicId.constData());
1748 uchar c = 0;
1749 int i;
1750 for (i = publicId.size() - 1; i >= 0; --i) {
1751 if (data[i] < 256)
1752 switch ((c = data[i])) {
1753 case ' ': case '\n': case '\r': case '-': case '(': case ')':
1754 case '+': case ',': case '.': case '/': case ':': case '=':
1755 case '?': case ';': case '!': case '*': case '#': case '@':
1756 case '$': case '_': case '%': case '\'': case '\"':
1757 continue;
1758 default:
1759 if ((c >= 'a' && c <= 'z')
1760 || (c >= 'A' && c <= 'Z')
1761 || (c >= '0' && c <= '9'))
1762 continue;
1763 }
1764 break;
1765 }
1766 if (i >= 0)
1767 raiseWellFormedError(QXmlStream::tr("Unexpected character '%1' in public id literal.").arg(QChar(QLatin1Char(c))));
1768}
1769
1770/*
1771 Checks whether the document starts with an xml declaration. If it
1772 does, this function returns \c true; otherwise it sets up everything
1773 for a synthetic start document event and returns \c false.
1774 */
1775bool QXmlStreamReaderPrivate::checkStartDocument()
1776{
1777 hasCheckedStartDocument = true;
1778
1779 if (scanString(spell[XML], XML))
1780 return true;
1781
1782 type = QXmlStreamReader::StartDocument;
1783 if (atEnd) {
1784 hasCheckedStartDocument = false;
1785 raiseError(QXmlStreamReader::PrematureEndOfDocumentError);
1786 }
1787 return false;
1788}
1789
1790void QXmlStreamReaderPrivate::startDocument()
1791{
1792 QString err;
1793 if (documentVersion != QLatin1String("1.0")) {
1794 if (documentVersion.contains(QLatin1Char(' ')))
1795 err = QXmlStream::tr("Invalid XML version string.");
1796 else
1797 err = QXmlStream::tr("Unsupported XML version.");
1798 }
1799 int n = attributeStack.size();
1800
1801 /* We use this bool to ensure that the pesudo attributes are in the
1802 * proper order:
1803 *
1804 * [23] XMLDecl ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>' */
1805 bool hasStandalone = false;
1806
1807 for (int i = 0; err.isNull() && i < n; ++i) {
1808 Attribute &attrib = attributeStack[i];
1809 QStringRef prefix(symPrefix(attrib.key));
1810 QStringRef key(symString(attrib.key));
1811 QStringRef value(symString(attrib.value));
1812
1813 if (prefix.isEmpty() && key == QLatin1String("encoding")) {
1814 documentEncoding = value;
1815
1816 if(hasStandalone)
1817 err = QXmlStream::tr("The standalone pseudo attribute must appear after the encoding.");
1818 if (!QXmlUtils::isEncName(value))
1819 err = QXmlStream::tr("%1 is an invalid encoding name.").arg(value);
1820 else {
1821#if !QT_CONFIG(textcodec)
1822 readBuffer = QString::fromLatin1(rawReadBuffer.data(), nbytesread);
1823#else
1824 QTextCodec *const newCodec = QTextCodec::codecForName(value.toLatin1());
1825 if (!newCodec)
1826 err = QXmlStream::tr("Encoding %1 is unsupported").arg(value);
1827 else if (newCodec != codec && !lockEncoding) {
1828 codec = newCodec;
1829 delete decoder;
1830 decoder = codec->makeDecoder();
1831 decoder->toUnicode(&readBuffer, rawReadBuffer.data(), nbytesread);
1832 }
1833#endif // textcodec
1834 }
1835 } else if (prefix.isEmpty() && key == QLatin1String("standalone")) {
1836 hasStandalone = true;
1837 if (value == QLatin1String("yes"))
1838 standalone = true;
1839 else if (value == QLatin1String("no"))
1840 standalone = false;
1841 else
1842 err = QXmlStream::tr("Standalone accepts only yes or no.");
1843 } else {
1844 err = QXmlStream::tr("Invalid attribute in XML declaration.");
1845 }
1846 }
1847
1848 if (!err.isNull())
1849 raiseWellFormedError(err);
1850 attributeStack.clear();
1851}
1852
1853
1854void QXmlStreamReaderPrivate::raiseError(QXmlStreamReader::Error error, const QString& message)
1855{
1856 this->error = error;
1857 errorString = message;
1858 if (errorString.isNull()) {
1859 if (error == QXmlStreamReader::PrematureEndOfDocumentError)
1860 errorString = QXmlStream::tr("Premature end of document.");
1861 else if (error == QXmlStreamReader::CustomError)
1862 errorString = QXmlStream::tr("Invalid document.");
1863 }
1864
1865 type = QXmlStreamReader::Invalid;
1866}
1867
1868void QXmlStreamReaderPrivate::raiseWellFormedError(const QString &message)
1869{
1870 raiseError(QXmlStreamReader::NotWellFormedError, message);
1871}
1872
1873void QXmlStreamReaderPrivate::parseError()
1874{
1875
1876 if (token == EOF_SYMBOL) {
1877 raiseError(QXmlStreamReader::PrematureEndOfDocumentError);
1878 return;
1879 }
1880 const int nmax = 4;
1881 QString error_message;
1882 int ers = state_stack[tos];
1883 int nexpected = 0;
1884 int expected[nmax];
1885 if (token != ERROR)
1886 for (int tk = 0; tk < TERMINAL_COUNT; ++tk) {
1887 int k = t_action(ers, tk);
1888 if (k <= 0)
1889 continue;
1890 if (spell[tk]) {
1891 if (nexpected < nmax)
1892 expected[nexpected++] = tk;
1893 }
1894 }
1895
1896 if (nexpected && nexpected < nmax) {
1897 //: '<first option>'
1898 QString exp_str = QXmlStream::tr("'%1'", "expected").arg(QLatin1String(spell[expected[0]]));
1899 if (nexpected == 2) {
1900 //: <first option>, '<second option>'
1901 exp_str = QXmlStream::tr("%1 or '%2'", "expected").arg(exp_str, QLatin1String(spell[expected[1]]));
1902 } else if (nexpected > 2) {
1903 int s = 1;
1904 for (; s < nexpected - 1; ++s) {
1905 //: <options so far>, '<next option>'
1906 exp_str = QXmlStream::tr("%1, '%2'", "expected").arg(exp_str, QLatin1String(spell[expected[s]]));
1907 }
1908 //: <options so far>, or '<final option>'
1909 exp_str = QXmlStream::tr("%1, or '%2'", "expected").arg(exp_str, QLatin1String(spell[expected[s]]));
1910 }
1911 error_message = QXmlStream::tr("Expected %1, but got '%2'.").arg(exp_str, QLatin1String(spell[token]));
1912 } else {
1913 error_message = QXmlStream::tr("Unexpected '%1'.").arg(QLatin1String(spell[token]));
1914 }
1915
1916 raiseWellFormedError(error_message);
1917}
1918
1919void QXmlStreamReaderPrivate::resume(int rule) {
1920 resumeReduction = rule;
1921 if (error == QXmlStreamReader::NoError)
1922 raiseError(QXmlStreamReader::PrematureEndOfDocumentError);
1923}
1924
1925/*! Returns the current line number, starting with 1.
1926
1927\sa columnNumber(), characterOffset()
1928 */
1929qint64 QXmlStreamReader::lineNumber() const
1930{
1931 Q_D(const QXmlStreamReader);
1932 return d->lineNumber + 1; // in public we start with 1
1933}
1934
1935/*! Returns the current column number, starting with 0.
1936
1937\sa lineNumber(), characterOffset()
1938 */
1939qint64 QXmlStreamReader::columnNumber() const
1940{
1941 Q_D(const QXmlStreamReader);
1942 return d->characterOffset - d->lastLineStart + d->readBufferPos;
1943}
1944
1945/*! Returns the current character offset, starting with 0.
1946
1947\sa lineNumber(), columnNumber()
1948*/
1949qint64 QXmlStreamReader::characterOffset() const
1950{
1951 Q_D(const QXmlStreamReader);
1952 return d->characterOffset + d->readBufferPos;
1953}
1954
1955
1956/*! Returns the text of \l Characters, \l Comment, \l DTD, or
1957 EntityReference.
1958 */
1959QStringRef QXmlStreamReader::text() const
1960{
1961 Q_D(const QXmlStreamReader);
1962 return d->text;
1963}
1964
1965
1966/*! If the tokenType() is \l DTD, this function returns the DTD's
1967 notation declarations. Otherwise an empty vector is returned.
1968
1969 The QXmlStreamNotationDeclarations class is defined to be a QVector
1970 of QXmlStreamNotationDeclaration.
1971 */
1972QXmlStreamNotationDeclarations QXmlStreamReader::notationDeclarations() const
1973{
1974 Q_D(const QXmlStreamReader);
1975 if (d->notationDeclarations.size())
1976 const_cast<QXmlStreamReaderPrivate *>(d)->resolveDtd();
1977 return d->publicNotationDeclarations;
1978}
1979
1980
1981/*! If the tokenType() is \l DTD, this function returns the DTD's
1982 unparsed (external) entity declarations. Otherwise an empty vector is returned.
1983
1984 The QXmlStreamEntityDeclarations class is defined to be a QVector
1985 of QXmlStreamEntityDeclaration.
1986 */
1987QXmlStreamEntityDeclarations QXmlStreamReader::entityDeclarations() const
1988{
1989 Q_D(const QXmlStreamReader);
1990 if (d->entityDeclarations.size())
1991 const_cast<QXmlStreamReaderPrivate *>(d)->resolveDtd();
1992 return d->publicEntityDeclarations;
1993}
1994
1995/*!
1996 \since 4.4
1997
1998 If the tokenType() is \l DTD, this function returns the DTD's
1999 name. Otherwise an empty string is returned.
2000
2001 */
2002QStringRef QXmlStreamReader::dtdName() const
2003{
2004 Q_D(const QXmlStreamReader);
2005 if (d->type == QXmlStreamReader::DTD)
2006 return d->dtdName;
2007 return QStringRef();
2008}
2009
2010/*!
2011 \since 4.4
2012
2013 If the tokenType() is \l DTD, this function returns the DTD's
2014 public identifier. Otherwise an empty string is returned.
2015
2016 */
2017QStringRef QXmlStreamReader::dtdPublicId() const
2018{
2019 Q_D(const QXmlStreamReader);
2020 if (d->type == QXmlStreamReader::DTD)
2021 return d->dtdPublicId;
2022 return QStringRef();
2023}
2024
2025/*!
2026 \since 4.4
2027
2028 If the tokenType() is \l DTD, this function returns the DTD's
2029 system identifier. Otherwise an empty string is returned.
2030
2031 */
2032QStringRef QXmlStreamReader::dtdSystemId() const
2033{
2034 Q_D(const QXmlStreamReader);
2035 if (d->type == QXmlStreamReader::DTD)
2036 return d->dtdSystemId;
2037 return QStringRef();
2038}
2039
2040/*! If the tokenType() is \l StartElement, this function returns the
2041 element's namespace declarations. Otherwise an empty vector is
2042 returned.
2043
2044 The QXmlStreamNamespaceDeclarations class is defined to be a QVector
2045 of QXmlStreamNamespaceDeclaration.
2046
2047 \sa addExtraNamespaceDeclaration(), addExtraNamespaceDeclarations()
2048 */
2049QXmlStreamNamespaceDeclarations QXmlStreamReader::namespaceDeclarations() const
2050{
2051 Q_D(const QXmlStreamReader);
2052 if (d->publicNamespaceDeclarations.isEmpty() && d->type == StartElement)
2053 const_cast<QXmlStreamReaderPrivate *>(d)->resolvePublicNamespaces();
2054 return d->publicNamespaceDeclarations;
2055}
2056
2057
2058/*!
2059 \since 4.4
2060
2061 Adds an \a extraNamespaceDeclaration. The declaration will be
2062 valid for children of the current element, or - should the function
2063 be called before any elements are read - for the entire XML
2064 document.
2065
2066 \sa namespaceDeclarations(), addExtraNamespaceDeclarations(), setNamespaceProcessing()
2067 */
2068void QXmlStreamReader::addExtraNamespaceDeclaration(const QXmlStreamNamespaceDeclaration &extraNamespaceDeclaration)
2069{
2070 Q_D(QXmlStreamReader);
2071 QXmlStreamReaderPrivate::NamespaceDeclaration &namespaceDeclaration = d->namespaceDeclarations.push();
2072 namespaceDeclaration.prefix = d->addToStringStorage(extraNamespaceDeclaration.prefix());
2073 namespaceDeclaration.namespaceUri = d->addToStringStorage(extraNamespaceDeclaration.namespaceUri());
2074}
2075
2076/*!
2077 \since 4.4
2078
2079 Adds a vector of declarations specified by \a extraNamespaceDeclarations.
2080
2081 \sa namespaceDeclarations(), addExtraNamespaceDeclaration()
2082 */
2083void QXmlStreamReader::addExtraNamespaceDeclarations(const QXmlStreamNamespaceDeclarations &extraNamespaceDeclarations)
2084{
2085 for (int i = 0; i < extraNamespaceDeclarations.size(); ++i)
2086 addExtraNamespaceDeclaration(extraNamespaceDeclarations.at(i));
2087}
2088
2089
2090/*! Convenience function to be called in case a StartElement was
2091 read. Reads until the corresponding EndElement and returns all text
2092 in-between. In case of no error, the current token (see tokenType())
2093 after having called this function is EndElement.
2094
2095 The function concatenates text() when it reads either \l Characters
2096 or EntityReference tokens, but skips ProcessingInstruction and \l
2097 Comment. If the current token is not StartElement, an empty string is
2098 returned.
2099
2100 The \a behaviour defines what happens in case anything else is
2101 read before reaching EndElement. The function can include the text from
2102 child elements (useful for example for HTML), ignore child elements, or
2103 raise an UnexpectedElementError and return what was read so far (default).
2104
2105 \since 4.6
2106 */
2107QString QXmlStreamReader::readElementText(ReadElementTextBehaviour behaviour)
2108{
2109 Q_D(QXmlStreamReader);
2110 if (isStartElement()) {
2111 QString result;
2112 forever {
2113 switch (readNext()) {
2114 case Characters:
2115 case EntityReference:
2116 result.insert(result.size(), d->text.unicode(), d->text.size());
2117 break;
2118 case EndElement:
2119 return result;
2120 case ProcessingInstruction:
2121 case Comment:
2122 break;
2123 case StartElement:
2124 if (behaviour == SkipChildElements) {
2125 skipCurrentElement();
2126 break;
2127 } else if (behaviour == IncludeChildElements) {
2128 result += readElementText(behaviour);
2129 break;
2130 }
2131 Q_FALLTHROUGH();
2132 default:
2133 if (d->error || behaviour == ErrorOnUnexpectedElement) {
2134 if (!d->error)
2135 d->raiseError(UnexpectedElementError, QXmlStream::tr("Expected character data."));
2136 return result;
2137 }
2138 }
2139 }
2140 }
2141 return QString();
2142}
2143
2144/*! Raises a custom error with an optional error \a message.
2145
2146 \sa error(), errorString()
2147 */
2148void QXmlStreamReader::raiseError(const QString& message)
2149{
2150 Q_D(QXmlStreamReader);
2151 d->raiseError(CustomError, message);
2152}
2153
2154/*!
2155 Returns the error message that was set with raiseError().
2156
2157 \sa error(), lineNumber(), columnNumber(), characterOffset()
2158 */
2159QString QXmlStreamReader::errorString() const
2160{
2161 Q_D(const QXmlStreamReader);
2162 if (d->type == QXmlStreamReader::Invalid)
2163 return d->errorString;
2164 return QString();
2165}
2166
2167/*! Returns the type of the current error, or NoError if no error occurred.
2168
2169 \sa errorString(), raiseError()
2170 */
2171QXmlStreamReader::Error QXmlStreamReader::error() const
2172{
2173 Q_D(const QXmlStreamReader);
2174 if (d->type == QXmlStreamReader::Invalid)
2175 return d->error;
2176 return NoError;
2177}
2178
2179/*!
2180 Returns the target of a ProcessingInstruction.
2181 */
2182QStringRef QXmlStreamReader::processingInstructionTarget() const
2183{
2184 Q_D(const QXmlStreamReader);
2185 return d->processingInstructionTarget;
2186}
2187
2188/*!
2189 Returns the data of a ProcessingInstruction.
2190 */
2191QStringRef QXmlStreamReader::processingInstructionData() const
2192{
2193 Q_D(const QXmlStreamReader);
2194 return d->processingInstructionData;
2195}
2196
2197
2198
2199/*!
2200 Returns the local name of a StartElement, EndElement, or an EntityReference.
2201
2202 \sa namespaceUri(), qualifiedName()
2203 */
2204QStringRef QXmlStreamReader::name() const
2205{
2206 Q_D(const QXmlStreamReader);
2207 return d->name;
2208}
2209
2210/*!
2211 Returns the namespaceUri of a StartElement or EndElement.
2212
2213 \sa name(), qualifiedName()
2214 */
2215QStringRef QXmlStreamReader::namespaceUri() const
2216{
2217 Q_D(const QXmlStreamReader);
2218 return d->namespaceUri;
2219}
2220
2221/*!
2222 Returns the qualified name of a StartElement or EndElement;
2223
2224 A qualified name is the raw name of an element in the XML data. It
2225 consists of the namespace prefix, followed by colon, followed by the
2226 element's local name. Since the namespace prefix is not unique (the
2227 same prefix can point to different namespaces and different prefixes
2228 can point to the same namespace), you shouldn't use qualifiedName(),
2229 but the resolved namespaceUri() and the attribute's local name().
2230
2231 \sa name(), prefix(), namespaceUri()
2232 */
2233QStringRef QXmlStreamReader::qualifiedName() const
2234{
2235 Q_D(const QXmlStreamReader);
2236 return d->qualifiedName;
2237}
2238
2239
2240
2241/*!
2242 \since 4.4
2243
2244 Returns the prefix of a StartElement or EndElement.
2245
2246 \sa name(), qualifiedName()
2247*/
2248QStringRef QXmlStreamReader::prefix() const
2249{
2250 Q_D(const QXmlStreamReader);
2251 return d->prefix;
2252}
2253
2254/*!
2255 Returns the attributes of a StartElement.
2256 */
2257QXmlStreamAttributes QXmlStreamReader::attributes() const
2258{
2259 Q_D(const QXmlStreamReader);
2260 return d->attributes;
2261}
2262
2263#endif // QT_NO_XMLSTREAMREADER
2264
2265/*!
2266 \class QXmlStreamAttribute
2267 \inmodule QtCore
2268 \since 4.3
2269 \reentrant
2270 \brief The QXmlStreamAttribute class represents a single XML attribute.
2271
2272 \ingroup xml-tools
2273
2274 An attribute consists of an optionally empty namespaceUri(), a
2275 name(), a value(), and an isDefault() attribute.
2276
2277 The raw XML attribute name is returned as qualifiedName().
2278*/
2279
2280/*!
2281 Creates an empty attribute.
2282 */
2283QXmlStreamAttribute::QXmlStreamAttribute()
2284{
2285 m_isDefault = false;
2286}
2287
2288#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
2289/*!
2290 Destructs an attribute.
2291 */
2292QXmlStreamAttribute::~QXmlStreamAttribute()
2293{
2294}
2295#endif
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 \c true if the parser added this attribute with a default
2356 value following an ATTLIST declaration in the DTD; otherwise
2357 returns \c false.
2358*/
2359/*! \fn bool QXmlStreamAttribute::operator==(const QXmlStreamAttribute &other) const
2360
2361 Compares this attribute with \a other and returns \c true if they are
2362 equal; otherwise returns \c false.
2363 */
2364/*! \fn bool QXmlStreamAttribute::operator!=(const QXmlStreamAttribute &other) const
2365
2366 Compares this attribute with \a other and returns \c true if they are
2367 not equal; otherwise returns \c false.
2368 */
2369
2370
2371#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
2372/*!
2373 Creates a copy of \a other.
2374 */
2375QXmlStreamAttribute::QXmlStreamAttribute(const QXmlStreamAttribute &other)
2376{
2377 *this = other;
2378}
2379
2380/*!
2381 Assigns \a other to this attribute.
2382 */
2383QXmlStreamAttribute& QXmlStreamAttribute::operator=(const QXmlStreamAttribute &other)
2384{
2385 m_name = other.m_name;
2386 m_namespaceUri = other.m_namespaceUri;
2387 m_qualifiedName = other.m_qualifiedName;
2388 m_value = other.m_value;
2389 m_isDefault = other.m_isDefault;
2390 return *this;
2391}
2392#endif
2393
2394/*!
2395 \class QXmlStreamAttributes
2396 \inmodule QtCore
2397 \since 4.3
2398 \reentrant
2399 \brief The QXmlStreamAttributes class represents a vector of QXmlStreamAttribute.
2400
2401 Attributes are returned by a QXmlStreamReader in
2402 \l{QXmlStreamReader::attributes()} {attributes()} when the reader
2403 reports a \l {QXmlStreamReader::StartElement}{start element}. The
2404 class can also be used with a QXmlStreamWriter as an argument to
2405 \l {QXmlStreamWriter::writeAttributes()}{writeAttributes()}.
2406
2407 The convenience function value() loops over the vector and returns
2408 an attribute value for a given namespaceUri and an attribute's
2409 name.
2410
2411 New attributes can be added with append().
2412
2413 \ingroup xml-tools
2414*/
2415
2416/*!
2417 \fn QXmlStreamAttributes::QXmlStreamAttributes()
2418
2419 A constructor for QXmlStreamAttributes.
2420*/
2421
2422/*!
2423 \typedef QXmlStreamNotationDeclarations
2424 \relates QXmlStreamNotationDeclaration
2425
2426 Synonym for QVector<QXmlStreamNotationDeclaration>.
2427*/
2428
2429
2430/*!
2431 \class QXmlStreamNotationDeclaration
2432 \inmodule QtCore
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#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
2450/*!
2451 Creates a copy of \a other.
2452 */
2453QXmlStreamNotationDeclaration::QXmlStreamNotationDeclaration(const QXmlStreamNotationDeclaration &other)
2454{
2455 *this = other;
2456}
2457
2458/*!
2459 Assigns \a other to this notation declaration.
2460 */
2461QXmlStreamNotationDeclaration& QXmlStreamNotationDeclaration::operator=(const QXmlStreamNotationDeclaration &other)
2462{
2463 m_name = other.m_name;
2464 m_systemId = other.m_systemId;
2465 m_publicId = other.m_publicId;
2466 return *this;
2467}
2468
2469/*!
2470Destructs this notation declaration.
2471*/
2472QXmlStreamNotationDeclaration::~QXmlStreamNotationDeclaration()
2473{
2474}
2475#endif
2476
2477/*! \fn QStringRef QXmlStreamNotationDeclaration::name() const
2478
2479Returns the notation name.
2480*/
2481/*! \fn QStringRef QXmlStreamNotationDeclaration::systemId() const
2482
2483Returns the system identifier.
2484*/
2485/*! \fn QStringRef QXmlStreamNotationDeclaration::publicId() const
2486
2487Returns the public identifier.
2488*/
2489
2490/*! \fn inline bool QXmlStreamNotationDeclaration::operator==(const QXmlStreamNotationDeclaration &other) const
2491
2492 Compares this notation declaration with \a other and returns \c true
2493 if they are equal; otherwise returns \c false.
2494 */
2495/*! \fn inline bool QXmlStreamNotationDeclaration::operator!=(const QXmlStreamNotationDeclaration &other) const
2496
2497 Compares this notation declaration with \a other and returns \c true
2498 if they are not equal; otherwise returns \c false.
2499 */
2500
2501/*!
2502 \typedef QXmlStreamNamespaceDeclarations
2503 \relates QXmlStreamNamespaceDeclaration
2504
2505 Synonym for QVector<QXmlStreamNamespaceDeclaration>.
2506*/
2507
2508/*!
2509 \class QXmlStreamNamespaceDeclaration
2510 \inmodule QtCore
2511 \since 4.3
2512 \reentrant
2513 \brief The QXmlStreamNamespaceDeclaration class represents a namespace declaration.
2514
2515 \ingroup xml-tools
2516
2517 An namespace declaration consists of a prefix() and a namespaceUri().
2518*/
2519/*! \fn inline bool QXmlStreamNamespaceDeclaration::operator==(const QXmlStreamNamespaceDeclaration &other) const
2520
2521 Compares this namespace declaration with \a other and returns \c true
2522 if they are equal; otherwise returns \c false.
2523 */
2524/*! \fn inline bool QXmlStreamNamespaceDeclaration::operator!=(const QXmlStreamNamespaceDeclaration &other) const
2525
2526 Compares this namespace declaration with \a other and returns \c true
2527 if they are not equal; otherwise returns \c false.
2528 */
2529
2530/*!
2531 Creates an empty namespace declaration.
2532*/
2533QXmlStreamNamespaceDeclaration::QXmlStreamNamespaceDeclaration()
2534{
2535}
2536
2537/*!
2538 \since 4.4
2539
2540 Creates a namespace declaration with \a prefix and \a namespaceUri.
2541*/
2542QXmlStreamNamespaceDeclaration::QXmlStreamNamespaceDeclaration(const QString &prefix, const QString &namespaceUri)
2543{
2544 m_prefix = prefix;
2545 m_namespaceUri = namespaceUri;
2546}
2547
2548#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
2549/*!
2550 Creates a copy of \a other.
2551 */
2552QXmlStreamNamespaceDeclaration::QXmlStreamNamespaceDeclaration(const QXmlStreamNamespaceDeclaration &other)
2553{
2554 *this = other;
2555}
2556
2557/*!
2558 Assigns \a other to this namespace declaration.
2559 */
2560QXmlStreamNamespaceDeclaration& QXmlStreamNamespaceDeclaration::operator=(const QXmlStreamNamespaceDeclaration &other)
2561{
2562 m_prefix = other.m_prefix;
2563 m_namespaceUri = other.m_namespaceUri;
2564 return *this;
2565}
2566/*!
2567Destructs this namespace declaration.
2568*/
2569QXmlStreamNamespaceDeclaration::~QXmlStreamNamespaceDeclaration()
2570{
2571}
2572#endif
2573
2574/*! \fn QStringRef QXmlStreamNamespaceDeclaration::prefix() const
2575
2576Returns the prefix.
2577*/
2578/*! \fn QStringRef QXmlStreamNamespaceDeclaration::namespaceUri() const
2579
2580Returns the namespaceUri.
2581*/
2582
2583
2584
2585
2586/*!
2587 \typedef QXmlStreamEntityDeclarations
2588 \relates QXmlStreamEntityDeclaration
2589
2590 Synonym for QVector<QXmlStreamEntityDeclaration>.
2591*/
2592
2593/*!
2594 \class QXmlStreamStringRef
2595 \inmodule QtCore
2596 \since 4.3
2597 \internal
2598*/
2599
2600/*!
2601 \class QXmlStreamEntityDeclaration
2602 \inmodule QtCore
2603 \since 4.3
2604 \reentrant
2605 \brief The QXmlStreamEntityDeclaration class represents a DTD entity declaration.
2606
2607 \ingroup xml-tools
2608
2609 An entity declaration consists of a name(), a notationName(), a
2610 systemId(), a publicId(), and a value().
2611*/
2612
2613/*!
2614 Creates an empty entity declaration.
2615*/
2616QXmlStreamEntityDeclaration::QXmlStreamEntityDeclaration()
2617{
2618}
2619
2620#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
2621/*!
2622 Creates a copy of \a other.
2623 */
2624QXmlStreamEntityDeclaration::QXmlStreamEntityDeclaration(const QXmlStreamEntityDeclaration &other)
2625{
2626 *this = other;
2627}
2628
2629/*!
2630 Assigns \a other to this entity declaration.
2631 */
2632QXmlStreamEntityDeclaration& QXmlStreamEntityDeclaration::operator=(const QXmlStreamEntityDeclaration &other)
2633{
2634 m_name = other.m_name;
2635 m_notationName = other.m_notationName;
2636 m_systemId = other.m_systemId;
2637 m_publicId = other.m_publicId;
2638 m_value = other.m_value;
2639 return *this;
2640}
2641
2642/*!
2643 Destructs this entity declaration.
2644*/
2645QXmlStreamEntityDeclaration::~QXmlStreamEntityDeclaration()
2646{
2647}
2648#endif
2649
2650/*! \fn QXmlStreamStringRef::swap(QXmlStreamStringRef &other)
2651 \since 5.6
2652
2653 Swaps this string reference's contents with \a other.
2654 This function is very fast and never fails.
2655*/
2656
2657/*! \fn QStringRef QXmlStreamEntityDeclaration::name() const
2658
2659Returns the entity name.
2660*/
2661/*! \fn QStringRef QXmlStreamEntityDeclaration::notationName() const
2662
2663Returns the notation name.
2664*/
2665/*! \fn QStringRef QXmlStreamEntityDeclaration::systemId() const
2666
2667Returns the system identifier.
2668*/
2669/*! \fn QStringRef QXmlStreamEntityDeclaration::publicId() const
2670
2671Returns the public identifier.
2672*/
2673/*! \fn QStringRef QXmlStreamEntityDeclaration::value() const
2674
2675Returns the entity's value.
2676*/
2677
2678/*! \fn bool QXmlStreamEntityDeclaration::operator==(const QXmlStreamEntityDeclaration &other) const
2679
2680 Compares this entity declaration with \a other and returns \c true if
2681 they are equal; otherwise returns \c false.
2682 */
2683/*! \fn bool QXmlStreamEntityDeclaration::operator!=(const QXmlStreamEntityDeclaration &other) const
2684
2685 Compares this entity declaration with \a other and returns \c true if
2686 they are not equal; otherwise returns \c false.
2687 */
2688
2689/*! Returns the value of the attribute \a name in the namespace
2690 described with \a namespaceUri, or an empty string reference if the
2691 attribute is not defined. The \a namespaceUri can be empty.
2692 */
2693QStringRef QXmlStreamAttributes::value(const QString &namespaceUri, const QString &name) const
2694{
2695 for (int i = 0; i < size(); ++i) {
2696 const QXmlStreamAttribute &attribute = at(i);
2697 if (attribute.name() == name && attribute.namespaceUri() == namespaceUri)
2698 return attribute.value();
2699 }
2700 return QStringRef();
2701}
2702
2703/*!\overload
2704 Returns the value of the attribute \a name in the namespace
2705 described with \a namespaceUri, or an empty string reference if the
2706 attribute is not defined. The \a namespaceUri can be empty.
2707 */
2708QStringRef QXmlStreamAttributes::value(const QString &namespaceUri, QLatin1String name) const
2709{
2710 for (int i = 0; i < size(); ++i) {
2711 const QXmlStreamAttribute &attribute = at(i);
2712 if (attribute.name() == name && attribute.namespaceUri() == namespaceUri)
2713 return attribute.value();
2714 }
2715 return QStringRef();
2716}
2717
2718/*!\overload
2719 Returns the value of the attribute \a name in the namespace
2720 described with \a namespaceUri, or an empty string reference if the
2721 attribute is not defined. The \a namespaceUri can be empty.
2722 */
2723QStringRef QXmlStreamAttributes::value(QLatin1String namespaceUri, QLatin1String name) const
2724{
2725 for (int i = 0; i < size(); ++i) {
2726 const QXmlStreamAttribute &attribute = at(i);
2727 if (attribute.name() == name && attribute.namespaceUri() == namespaceUri)
2728 return attribute.value();
2729 }
2730 return QStringRef();
2731}
2732
2733/*!\overload
2734
2735 Returns the value of the attribute with qualified name \a
2736 qualifiedName , or an empty string reference if the attribute is not
2737 defined. A qualified name is the raw name of an attribute in the XML
2738 data. It consists of the namespace prefix, followed by colon,
2739 followed by the attribute's local name. Since the namespace prefix
2740 is not unique (the same prefix can point to different namespaces and
2741 different prefixes can point to the same namespace), you shouldn't
2742 use qualified names, but a resolved namespaceUri and the attribute's
2743 local name.
2744 */
2745QStringRef QXmlStreamAttributes::value(const QString &qualifiedName) const
2746{
2747 for (int i = 0; i < size(); ++i) {
2748 const QXmlStreamAttribute &attribute = at(i);
2749 if (attribute.qualifiedName() == qualifiedName)
2750 return attribute.value();
2751 }
2752 return QStringRef();
2753}
2754
2755/*!\overload
2756
2757 Returns the value of the attribute with qualified name \a
2758 qualifiedName , or an empty string reference if the attribute is not
2759 defined. A qualified name is the raw name of an attribute in the XML
2760 data. It consists of the namespace prefix, followed by colon,
2761 followed by the attribute's local name. Since the namespace prefix
2762 is not unique (the same prefix can point to different namespaces and
2763 different prefixes can point to the same namespace), you shouldn't
2764 use qualified names, but a resolved namespaceUri and the attribute's
2765 local name.
2766 */
2767QStringRef QXmlStreamAttributes::value(QLatin1String qualifiedName) const
2768{
2769 for (int i = 0; i < size(); ++i) {
2770 const QXmlStreamAttribute &attribute = at(i);
2771 if (attribute.qualifiedName() == qualifiedName)
2772 return attribute.value();
2773 }
2774 return QStringRef();
2775}
2776
2777/*!Appends a new attribute with \a name in the namespace
2778 described with \a namespaceUri, and value \a value. The \a
2779 namespaceUri can be empty.
2780 */
2781void QXmlStreamAttributes::append(const QString &namespaceUri, const QString &name, const QString &value)
2782{
2783 append(QXmlStreamAttribute(namespaceUri, name, value));
2784}
2785
2786/*!\overload
2787 Appends a new attribute with qualified name \a qualifiedName and
2788 value \a value.
2789 */
2790void QXmlStreamAttributes::append(const QString &qualifiedName, const QString &value)
2791{
2792 append(QXmlStreamAttribute(qualifiedName, value));
2793}
2794
2795#ifndef QT_NO_XMLSTREAMREADER
2796
2797/*! \fn bool QXmlStreamReader::isStartDocument() const
2798 Returns \c true if tokenType() equals \l StartDocument; otherwise returns \c false.
2799*/
2800/*! \fn bool QXmlStreamReader::isEndDocument() const
2801 Returns \c true if tokenType() equals \l EndDocument; otherwise returns \c false.
2802*/
2803/*! \fn bool QXmlStreamReader::isStartElement() const
2804 Returns \c true if tokenType() equals \l StartElement; otherwise returns \c false.
2805*/
2806/*! \fn bool QXmlStreamReader::isEndElement() const
2807 Returns \c true if tokenType() equals \l EndElement; otherwise returns \c false.
2808*/
2809/*! \fn bool QXmlStreamReader::isCharacters() const
2810 Returns \c true if tokenType() equals \l Characters; otherwise returns \c false.
2811
2812 \sa isWhitespace(), isCDATA()
2813*/
2814/*! \fn bool QXmlStreamReader::isComment() const
2815 Returns \c true if tokenType() equals \l Comment; otherwise returns \c false.
2816*/
2817/*! \fn bool QXmlStreamReader::isDTD() const
2818 Returns \c true if tokenType() equals \l DTD; otherwise returns \c false.
2819*/
2820/*! \fn bool QXmlStreamReader::isEntityReference() const
2821 Returns \c true if tokenType() equals \l EntityReference; otherwise returns \c false.
2822*/
2823/*! \fn bool QXmlStreamReader::isProcessingInstruction() const
2824 Returns \c true if tokenType() equals \l ProcessingInstruction; otherwise returns \c false.
2825*/
2826
2827/*! Returns \c true if the reader reports characters that only consist
2828 of white-space; otherwise returns \c false.
2829
2830 \sa isCharacters(), text()
2831*/
2832bool QXmlStreamReader::isWhitespace() const
2833{
2834 Q_D(const QXmlStreamReader);
2835 return d->type == QXmlStreamReader::Characters && d->isWhitespace;
2836}
2837
2838/*! Returns \c true if the reader reports characters that stem from a
2839 CDATA section; otherwise returns \c false.
2840
2841 \sa isCharacters(), text()
2842*/
2843bool QXmlStreamReader::isCDATA() const
2844{
2845 Q_D(const QXmlStreamReader);
2846 return d->type == QXmlStreamReader::Characters && d->isCDATA;
2847}
2848
2849
2850
2851/*!
2852 Returns \c true if this document has been declared standalone in the
2853 XML declaration; otherwise returns \c false.
2854
2855 If no XML declaration has been parsed, this function returns \c false.
2856 */
2857bool QXmlStreamReader::isStandaloneDocument() const
2858{
2859 Q_D(const QXmlStreamReader);
2860 return d->standalone;
2861}
2862
2863
2864/*!
2865 \since 4.4
2866
2867 If the tokenType() is \l StartDocument, this function returns the
2868 version string as specified in the XML declaration.
2869 Otherwise an empty string is returned.
2870 */
2871QStringRef QXmlStreamReader::documentVersion() const
2872{
2873 Q_D(const QXmlStreamReader);
2874 if (d->type == QXmlStreamReader::StartDocument)
2875 return d->documentVersion;
2876 return QStringRef();
2877}
2878
2879/*!
2880 \since 4.4
2881
2882 If the tokenType() is \l StartDocument, this function returns the
2883 encoding string as specified in the XML declaration.
2884 Otherwise an empty string is returned.
2885 */
2886QStringRef QXmlStreamReader::documentEncoding() const
2887{
2888 Q_D(const QXmlStreamReader);
2889 if (d->type == QXmlStreamReader::StartDocument)
2890 return d->documentEncoding;
2891 return QStringRef();
2892}
2893
2894#endif // QT_NO_XMLSTREAMREADER
2895
2896/*!
2897 \class QXmlStreamWriter
2898 \inmodule QtCore
2899 \since 4.3
2900 \reentrant
2901
2902 \brief The QXmlStreamWriter class provides an XML writer with a
2903 simple streaming API.
2904
2905 \ingroup xml-tools
2906
2907 QXmlStreamWriter is the counterpart to QXmlStreamReader for writing
2908 XML. Like its related class, it operates on a QIODevice specified
2909 with setDevice(). The API is simple and straightforward: for every
2910 XML token or event you want to write, the writer provides a
2911 specialized function.
2912
2913 You start a document with writeStartDocument() and end it with
2914 writeEndDocument(). This will implicitly close all remaining open
2915 tags.
2916
2917 Element tags are opened with writeStartElement() followed by
2918 writeAttribute() or writeAttributes(), element content, and then
2919 writeEndElement(). A shorter form writeEmptyElement() can be used
2920 to write empty elements, followed by writeAttributes().
2921
2922 Element content consists of either characters, entity references or
2923 nested elements. It is written with writeCharacters(), which also
2924 takes care of escaping all forbidden characters and character
2925 sequences, writeEntityReference(), or subsequent calls to
2926 writeStartElement(). A convenience method writeTextElement() can be
2927 used for writing terminal elements that contain nothing but text.
2928
2929 The following abridged code snippet shows the basic use of the class
2930 to write formatted XML with indentation:
2931
2932 \snippet qxmlstreamwriter/main.cpp start stream
2933 \dots
2934 \snippet qxmlstreamwriter/main.cpp write element
2935 \dots
2936 \snippet qxmlstreamwriter/main.cpp finish stream
2937
2938 QXmlStreamWriter takes care of prefixing namespaces, all you have to
2939 do is specify the \c namespaceUri when writing elements or
2940 attributes. If you must conform to certain prefixes, you can force
2941 the writer to use them by declaring the namespaces manually with
2942 either writeNamespace() or writeDefaultNamespace(). Alternatively,
2943 you can bypass the stream writer's namespace support and use
2944 overloaded methods that take a qualified name instead. The namespace
2945 \e http://www.w3.org/XML/1998/namespace is implicit and mapped to the
2946 prefix \e xml.
2947
2948 The stream writer can automatically format the generated XML data by
2949 adding line-breaks and indentation to empty sections between
2950 elements, making the XML data more readable for humans and easier to
2951 work with for most source code management systems. The feature can
2952 be turned on with the \l autoFormatting property, and customized
2953 with the \l autoFormattingIndent property.
2954
2955 Other functions are writeCDATA(), writeComment(),
2956 writeProcessingInstruction(), and writeDTD(). Chaining of XML
2957 streams is supported with writeCurrentToken().
2958
2959 By default, QXmlStreamWriter encodes XML in UTF-8. Different
2960 encodings can be enforced using setCodec().
2961
2962 If an error occurs while writing to the underlying device, hasError()
2963 starts returning true and subsequent writes are ignored.
2964
2965 The \l{QXmlStream Bookmarks Example} illustrates how to use a
2966 stream writer to write an XML bookmark file (XBEL) that
2967 was previously read in by a QXmlStreamReader.
2968
2969*/
2970
2971#ifndef QT_NO_XMLSTREAMWRITER
2972
2973class QXmlStreamWriterPrivate : public QXmlStreamPrivateTagStack {
2974 QXmlStreamWriter *q_ptr;
2975 Q_DECLARE_PUBLIC(QXmlStreamWriter)
2976public:
2977 QXmlStreamWriterPrivate(QXmlStreamWriter *q);
2978 ~QXmlStreamWriterPrivate() {
2979 if (deleteDevice)
2980 delete device;
2981#if QT_CONFIG(textcodec)
2982 delete encoder;
2983#endif
2984 }
2985
2986 void write(const QStringRef &);
2987 void write(const QString &);
2988 void writeEscaped(const QString &, bool escapeWhitespace = false);
2989 void write(const char *s, int len);
2990 template <int N> void write(const char (&s)[N]) { write(s, N - 1); }
2991 bool finishStartElement(bool contents = true);
2992 void writeStartElement(const QString &namespaceUri, const QString &name);
2993 QIODevice *device;
2994 QString *stringDevice;
2995 uint deleteDevice :1;
2996 uint inStartElement :1;
2997 uint inEmptyElement :1;
2998 uint lastWasStartElement :1;
2999 uint wroteSomething :1;
3000 uint hasIoError :1;
3001 uint hasEncodingError :1;
3002 uint autoFormatting :1;
3003 uint isCodecASCIICompatible :1;
3004 QByteArray autoFormattingIndent;
3005 NamespaceDeclaration emptyNamespace;
3006 int lastNamespaceDeclaration;
3007
3008#if QT_CONFIG(textcodec)
3009 QTextCodec *codec;
3010 QTextEncoder *encoder;
3011#endif
3012 void checkIfASCIICompatibleCodec();
3013
3014 NamespaceDeclaration &findNamespace(const QString &namespaceUri, bool writeDeclaration = false, bool noDefault = false);
3015 void writeNamespaceDeclaration(const NamespaceDeclaration &namespaceDeclaration);
3016
3017 int namespacePrefixCount;
3018
3019 void indent(int level);
3020};
3021
3022
3023QXmlStreamWriterPrivate::QXmlStreamWriterPrivate(QXmlStreamWriter *q)
3024 :autoFormattingIndent(4, ' ')
3025{
3026 q_ptr = q;
3027 device = nullptr;
3028 stringDevice = nullptr;
3029 deleteDevice = false;
3030#if QT_CONFIG(textcodec)
3031 codec = QTextCodec::codecForMib(106); // utf8
3032 encoder = codec->makeEncoder(QTextCodec::IgnoreHeader); // no byte order mark for utf8
3033#endif
3034 checkIfASCIICompatibleCodec();
3035 inStartElement = inEmptyElement = false;
3036 wroteSomething = false;
3037 hasIoError = false;
3038 hasEncodingError = false;
3039 lastWasStartElement = false;
3040 lastNamespaceDeclaration = 1;
3041 autoFormatting = false;
3042 namespacePrefixCount = 0;
3043}
3044
3045void QXmlStreamWriterPrivate::checkIfASCIICompatibleCodec()
3046{
3047#if QT_CONFIG(textcodec)
3048 Q_ASSERT(encoder);
3049 // test ASCII-compatibility using the letter 'a'
3050 QChar letterA = QLatin1Char('a');
3051 const QByteArray bytesA = encoder->fromUnicode(&letterA, 1);
3052 const bool isCodecASCIICompatibleA = (bytesA.count() == 1) && (bytesA[0] == 0x61) ;
3053 QChar letterLess = QLatin1Char('<');
3054 const QByteArray bytesLess = encoder->fromUnicode(&letterLess, 1);
3055 const bool isCodecASCIICompatibleLess = (bytesLess.count() == 1) && (bytesLess[0] == 0x3C) ;
3056 isCodecASCIICompatible = isCodecASCIICompatibleA && isCodecASCIICompatibleLess ;
3057#else
3058 isCodecASCIICompatible = true;
3059#endif
3060}
3061
3062void QXmlStreamWriterPrivate::write(const QStringRef &s)
3063{
3064 if (device) {
3065 if (hasIoError)
3066 return;
3067#if !QT_CONFIG(textcodec)
3068 QByteArray bytes = s.toLatin1();
3069#else
3070 QByteArray bytes = encoder->fromUnicode(s.constData(), s.size());
3071 if (encoder->hasFailure()) {
3072 hasEncodingError = true;
3073 return;
3074 }
3075#endif
3076 if (device->write(bytes) != bytes.size())
3077 hasIoError = true;
3078 }
3079 else if (stringDevice)
3080 s.appendTo(stringDevice);
3081 else
3082 qWarning("QXmlStreamWriter: No device");
3083}
3084
3085void QXmlStreamWriterPrivate::write(const QString &s)
3086{
3087 if (device) {
3088 if (hasIoError)
3089 return;
3090#if !QT_CONFIG(textcodec)
3091 QByteArray bytes = s.toLatin1();
3092#else
3093 QByteArray bytes = encoder->fromUnicode(s);
3094 if (encoder->hasFailure()) {
3095 hasEncodingError = true;
3096 return;
3097 }
3098#endif
3099 if (device->write(bytes) != bytes.size())
3100 hasIoError = true;
3101 }
3102 else if (stringDevice)
3103 stringDevice->append(s);
3104 else
3105 qWarning("QXmlStreamWriter: No device");
3106}
3107
3108void QXmlStreamWriterPrivate::writeEscaped(const QString &s, bool escapeWhitespace)
3109{
3110 QString escaped;
3111 escaped.reserve(s.size());
3112 for ( int i = 0; i < s.size(); ++i ) {
3113 QChar c = s.at(i);
3114 switch (c.unicode()) {
3115 case '<':
3116 escaped.append(QLatin1String("&lt;"));
3117 break;
3118 case '>':
3119 escaped.append(QLatin1String("&gt;"));
3120 break;
3121 case '&':
3122 escaped.append(QLatin1String("&amp;"));
3123 break;
3124 case '\"':
3125 escaped.append(QLatin1String("&quot;"));
3126 break;
3127 case '\t':
3128 if (escapeWhitespace)
3129 escaped.append(QLatin1String("&#9;"));
3130 else
3131 escaped += c;
3132 break;
3133 case '\n':
3134 if (escapeWhitespace)
3135 escaped.append(QLatin1String("&#10;"));
3136 else
3137 escaped += c;
3138 break;
3139 case '\v':
3140 case '\f':
3141 hasEncodingError = true;
3142 break;
3143 case '\r':
3144 if (escapeWhitespace)
3145 escaped.append(QLatin1String("&#13;"));
3146 else
3147 escaped += c;
3148 break;
3149 default:
3150 if (c.unicode() > 0x1f && c.unicode() < 0xfffe)
3151 escaped += c;
3152 else
3153 hasEncodingError = true;
3154 break;
3155 }
3156 }
3157 write(escaped);
3158}
3159
3160// Converts from ASCII to output encoding
3161void QXmlStreamWriterPrivate::write(const char *s, int len)
3162{
3163 if (device) {
3164 if (hasIoError)
3165 return;
3166 if (isCodecASCIICompatible) {
3167 if (device->write(s, len) != len)
3168 hasIoError = true;
3169 return;
3170 }
3171 }
3172
3173 write(QString::fromLatin1(s, len));
3174}
3175
3176void QXmlStreamWriterPrivate::writeNamespaceDeclaration(const NamespaceDeclaration &namespaceDeclaration) {
3177 if (namespaceDeclaration.prefix.isEmpty()) {
3178 write(" xmlns=\"");
3179 write(namespaceDeclaration.namespaceUri);
3180 write("\"");
3181 } else {
3182 write(" xmlns:");
3183 write(namespaceDeclaration.prefix);
3184 write("=\"");
3185 write(namespaceDeclaration.namespaceUri);
3186 write("\"");
3187 }
3188}
3189
3190bool QXmlStreamWriterPrivate::finishStartElement(bool contents)
3191{
3192 bool hadSomethingWritten = wroteSomething;
3193 wroteSomething = contents;
3194 if (!inStartElement)
3195 return hadSomethingWritten;
3196
3197 if (inEmptyElement) {
3198 write("/>");
3199 QXmlStreamWriterPrivate::Tag &tag = tagStack_pop();
3200 lastNamespaceDeclaration = tag.namespaceDeclarationsSize;
3201 lastWasStartElement = false;
3202 } else {
3203 write(">");
3204 }
3205 inStartElement = inEmptyElement = false;
3206 lastNamespaceDeclaration = namespaceDeclarations.size();
3207 return hadSomethingWritten;
3208}
3209
3210QXmlStreamPrivateTagStack::NamespaceDeclaration &QXmlStreamWriterPrivate::findNamespace(const QString &namespaceUri, bool writeDeclaration, bool noDefault)
3211{
3212 for (int j = namespaceDeclarations.size() - 1; j >= 0; --j) {
3213 NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations[j];
3214 if (namespaceDeclaration.namespaceUri == namespaceUri) {
3215 if (!noDefault || !namespaceDeclaration.prefix.isEmpty())
3216 return namespaceDeclaration;
3217 }
3218 }
3219 if (namespaceUri.isEmpty())
3220 return emptyNamespace;
3221 NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.push();
3222 if (namespaceUri.isEmpty()) {
3223 namespaceDeclaration.prefix.clear();
3224 } else {
3225 QString s;
3226 int n = ++namespacePrefixCount;
3227 forever {
3228 s = QLatin1Char('n') + QString::number(n++);
3229 int j = namespaceDeclarations.size() - 2;
3230 while (j >= 0 && namespaceDeclarations.at(j).prefix != s)
3231 --j;
3232 if (j < 0)
3233 break;
3234 }
3235 namespaceDeclaration.prefix = addToStringStorage(s);
3236 }
3237 namespaceDeclaration.namespaceUri = addToStringStorage(namespaceUri);
3238 if (writeDeclaration)
3239 writeNamespaceDeclaration(namespaceDeclaration);
3240 return namespaceDeclaration;
3241}
3242
3243
3244
3245void QXmlStreamWriterPrivate::indent(int level)
3246{
3247 write("\n");
3248 for (int i = level; i > 0; --i)
3249 write(autoFormattingIndent.constData(), autoFormattingIndent.length());
3250}
3251
3252
3253/*!
3254 Constructs a stream writer.
3255
3256 \sa setDevice()
3257 */
3258QXmlStreamWriter::QXmlStreamWriter()
3259 : d_ptr(new QXmlStreamWriterPrivate(this))
3260{
3261}
3262
3263/*!
3264 Constructs a stream writer that writes into \a device;
3265 */
3266QXmlStreamWriter::QXmlStreamWriter(QIODevice *device)
3267 : d_ptr(new QXmlStreamWriterPrivate(this))
3268{
3269 Q_D(QXmlStreamWriter);
3270 d->device = device;
3271}
3272
3273/*! Constructs a stream writer that writes into \a array. This is the
3274 same as creating an xml writer that operates on a QBuffer device
3275 which in turn operates on \a array.
3276 */
3277QXmlStreamWriter::QXmlStreamWriter(QByteArray *array)
3278 : d_ptr(new QXmlStreamWriterPrivate(this))
3279{
3280 Q_D(QXmlStreamWriter);
3281 d->device = new QBuffer(array);
3282 d->device->open(QIODevice::WriteOnly);
3283 d->deleteDevice = true;
3284}
3285
3286
3287/*! Constructs a stream writer that writes into \a string.
3288 *
3289 * Note that when writing to QString, QXmlStreamWriter ignores the codec set
3290 * with setCodec(). See that function for more information.
3291 */
3292QXmlStreamWriter::QXmlStreamWriter(QString *string)
3293 : d_ptr(new QXmlStreamWriterPrivate(this))
3294{
3295 Q_D(QXmlStreamWriter);
3296 d->stringDevice = string;
3297}
3298
3299/*!
3300 Destructor.
3301*/
3302QXmlStreamWriter::~QXmlStreamWriter()
3303{
3304}
3305
3306
3307/*!
3308 Sets the current device to \a device. If you want the stream to
3309 write into a QByteArray, you can create a QBuffer device.
3310
3311 \sa device()
3312*/
3313void QXmlStreamWriter::setDevice(QIODevice *device)
3314{
3315 Q_D(QXmlStreamWriter);
3316 if (device == d->device)
3317 return;
3318 d->stringDevice = nullptr;
3319 if (d->deleteDevice) {
3320 delete d->device;
3321 d->deleteDevice = false;
3322 }
3323 d->device = device;
3324}
3325
3326/*!
3327 Returns the current device associated with the QXmlStreamWriter,
3328 or \nullptr if no device has been assigned.
3329
3330 \sa setDevice()
3331*/
3332QIODevice *QXmlStreamWriter::device() const
3333{
3334 Q_D(const QXmlStreamWriter);
3335 return d->device;
3336}
3337
3338
3339#if QT_CONFIG(textcodec)
3340/*!
3341 Sets the codec for this stream to \a codec. The codec is used for
3342 encoding any data that is written. By default, QXmlStreamWriter
3343 uses UTF-8.
3344
3345 The encoding information is stored in the initial xml tag which
3346 gets written when you call writeStartDocument(). Call this
3347 function before calling writeStartDocument().
3348
3349 \note When writing the XML to a QString, the codec information is ignored
3350 and the XML header will not include any encoding information, since all
3351 QStrings are UTF-16. If you later convert the QString to an 8-bit format,
3352 you must arrange for the encoding information to be transmitted
3353 out-of-band.
3354
3355 \sa codec()
3356*/
3357void QXmlStreamWriter::setCodec(QTextCodec *codec)
3358{
3359 Q_D(QXmlStreamWriter);
3360 if (codec) {
3361 d->codec = codec;
3362 delete d->encoder;
3363 d->encoder = codec->makeEncoder(QTextCodec::IgnoreHeader); // no byte order mark for utf8
3364 d->checkIfASCIICompatibleCodec();
3365 }
3366}
3367
3368/*!
3369 Sets the codec for this stream to the QTextCodec for the encoding
3370 specified by \a codecName. Common values for \c codecName include
3371 "ISO 8859-1", "UTF-8", and "UTF-16". If the encoding isn't
3372 recognized, nothing happens.
3373
3374 \note When writing the XML to a QString, the codec information is ignored
3375 and the XML header will not include any encoding information, since all
3376 QStrings are UTF-16. If you later convert the QString to an 8-bit format,
3377 you must arrange for the encoding information to be transmitted
3378 out-of-band.
3379
3380 \sa QTextCodec::codecForName()
3381*/
3382void QXmlStreamWriter::setCodec(const char *codecName)
3383{
3384 setCodec(QTextCodec::codecForName(codecName));
3385}
3386
3387/*!
3388 Returns the codec that is currently assigned to the stream.
3389
3390 \sa setCodec()
3391*/
3392QTextCodec *QXmlStreamWriter::codec() const
3393{
3394 Q_D(const QXmlStreamWriter);
3395 return d->codec;
3396}
3397#endif // textcodec
3398
3399/*!
3400 \property QXmlStreamWriter::autoFormatting
3401 \since 4.4
3402 The auto-formatting flag of the stream writer
3403
3404 This property controls whether or not the stream writer
3405 automatically formats the generated XML data. If enabled, the
3406 writer automatically adds line-breaks and indentation to empty
3407 sections between elements (ignorable whitespace). The main purpose
3408 of auto-formatting is to split the data into several lines, and to
3409 increase readability for a human reader. The indentation depth can
3410 be controlled through the \l autoFormattingIndent property.
3411
3412 By default, auto-formatting is disabled.
3413*/
3414
3415/*!
3416 \since 4.4
3417
3418 Enables auto formatting if \a enable is \c true, otherwise
3419 disables it.
3420
3421 The default value is \c false.
3422 */
3423void QXmlStreamWriter::setAutoFormatting(bool enable)
3424{
3425 Q_D(QXmlStreamWriter);
3426 d->autoFormatting = enable;
3427}
3428
3429/*!
3430 \since 4.4
3431
3432 Returns \c true if auto formattting is enabled, otherwise \c false.
3433 */
3434bool QXmlStreamWriter::autoFormatting() const
3435{
3436 Q_D(const QXmlStreamWriter);
3437 return d->autoFormatting;
3438}
3439
3440/*!
3441 \property QXmlStreamWriter::autoFormattingIndent
3442 \since 4.4
3443
3444 \brief the number of spaces or tabs used for indentation when
3445 auto-formatting is enabled. Positive numbers indicate spaces,
3446 negative numbers tabs.
3447
3448 The default indentation is 4.
3449
3450 \sa autoFormatting
3451*/
3452
3453
3454void QXmlStreamWriter::setAutoFormattingIndent(int spacesOrTabs)
3455{
3456 Q_D(QXmlStreamWriter);
3457 d->autoFormattingIndent = QByteArray(qAbs(spacesOrTabs), spacesOrTabs >= 0 ? ' ' : '\t');
3458}
3459
3460int QXmlStreamWriter::autoFormattingIndent() const
3461{
3462 Q_D(const QXmlStreamWriter);
3463 return d->autoFormattingIndent.count(' ') - d->autoFormattingIndent.count('\t');
3464}
3465
3466/*!
3467 Returns \c true if writing failed.
3468
3469 This can happen if the stream failed to write to the underlying
3470 device or if the data to be written contained invalid characters.
3471
3472 The error status is never reset. Writes happening after the error
3473 occurred may be ignored, even if the error condition is cleared.
3474 */
3475bool QXmlStreamWriter::hasError() const
3476{
3477 Q_D(const QXmlStreamWriter);
3478 return d->hasIoError || d->hasEncodingError;
3479}
3480
3481/*!
3482 \overload
3483 Writes an attribute with \a qualifiedName and \a value.
3484
3485
3486 This function can only be called after writeStartElement() before
3487 any content is written, or after writeEmptyElement().
3488 */
3489void QXmlStreamWriter::writeAttribute(const QString &qualifiedName, const QString &value)
3490{
3491 Q_D(QXmlStreamWriter);
3492 Q_ASSERT(d->inStartElement);
3493 Q_ASSERT(qualifiedName.count(QLatin1Char(':')) <= 1);
3494 d->write(" ");
3495 d->write(qualifiedName);
3496 d->write("=\"");
3497 d->writeEscaped(value, true);
3498 d->write("\"");
3499}
3500
3501/*! Writes an attribute with \a name and \a value, prefixed for
3502 the specified \a namespaceUri. If the namespace has not been
3503 declared yet, QXmlStreamWriter will generate a namespace declaration
3504 for it.
3505
3506 This function can only be called after writeStartElement() before
3507 any content is written, or after writeEmptyElement().
3508 */
3509void QXmlStreamWriter::writeAttribute(const QString &namespaceUri, const QString &name, const QString &value)
3510{
3511 Q_D(QXmlStreamWriter);
3512 Q_ASSERT(d->inStartElement);
3513 Q_ASSERT(!name.contains(QLatin1Char(':')));
3514 QXmlStreamWriterPrivate::NamespaceDeclaration &namespaceDeclaration = d->findNamespace(namespaceUri, true, true);
3515 d->write(" ");
3516 if (!namespaceDeclaration.prefix.isEmpty()) {
3517 d->write(namespaceDeclaration.prefix);
3518 d->write(":");
3519 }
3520 d->write(name);
3521 d->write("=\"");
3522 d->writeEscaped(value, true);
3523 d->write("\"");
3524}
3525
3526/*!
3527 \overload
3528
3529 Writes the \a attribute.
3530
3531 This function can only be called after writeStartElement() before
3532 any content is written, or after writeEmptyElement().
3533 */
3534void QXmlStreamWriter::writeAttribute(const QXmlStreamAttribute& attribute)
3535{
3536 if (attribute.namespaceUri().isEmpty())
3537 writeAttribute(attribute.qualifiedName().toString(),
3538 attribute.value().toString());
3539 else
3540 writeAttribute(attribute.namespaceUri().toString(),
3541 attribute.name().toString(),
3542 attribute.value().toString());
3543}
3544
3545
3546/*! Writes the attribute vector \a attributes. If a namespace
3547 referenced in an attribute not been declared yet, QXmlStreamWriter
3548 will generate a namespace declaration for it.
3549
3550 This function can only be called after writeStartElement() before
3551 any content is written, or after writeEmptyElement().
3552
3553 \sa writeAttribute(), writeNamespace()
3554 */
3555void QXmlStreamWriter::writeAttributes(const QXmlStreamAttributes& attributes)
3556{
3557 Q_D(QXmlStreamWriter);
3558 Q_ASSERT(d->inStartElement);
3559 Q_UNUSED(d);
3560 for (int i = 0; i < attributes.size(); ++i)
3561 writeAttribute(attributes.at(i));
3562}
3563
3564
3565/*! Writes \a text as CDATA section. If \a text contains the
3566 forbidden character sequence "]]>", it is split into different CDATA
3567 sections.
3568
3569 This function mainly exists for completeness. Normally you should
3570 not need use it, because writeCharacters() automatically escapes all
3571 non-content characters.
3572 */
3573void QXmlStreamWriter::writeCDATA(const QString &text)
3574{
3575 Q_D(QXmlStreamWriter);
3576 d->finishStartElement();
3577 QString copy(text);
3578 copy.replace(QLatin1String("]]>"), QLatin1String("]]]]><![CDATA[>"));
3579 d->write("<![CDATA[");
3580 d->write(copy);
3581 d->write("]]>");
3582}
3583
3584
3585/*! Writes \a text. The characters "<", "&", and "\"" are escaped as entity
3586 references "&lt;", "&amp;, and "&quot;". To avoid the forbidden sequence
3587 "]]>", ">" is also escaped as "&gt;".
3588
3589 \sa writeEntityReference()
3590 */
3591void QXmlStreamWriter::writeCharacters(const QString &text)
3592{
3593 Q_D(QXmlStreamWriter);
3594 d->finishStartElement();
3595 d->writeEscaped(text);
3596}
3597
3598
3599/*! Writes \a text as XML comment, where \a text must not contain the
3600 forbidden sequence "--" or end with "-". Note that XML does not
3601 provide any way to escape "-" in a comment.
3602 */
3603void QXmlStreamWriter::writeComment(const QString &text)
3604{
3605 Q_D(QXmlStreamWriter);
3606 Q_ASSERT(!text.contains(QLatin1String("--")) && !text.endsWith(QLatin1Char('-')));
3607 if (!d->finishStartElement(false) && d->autoFormatting)
3608 d->indent(d->tagStack.size());
3609 d->write("<!--");
3610 d->write(text);
3611 d->write("-->");
3612 d->inStartElement = d->lastWasStartElement = false;
3613}
3614
3615
3616/*! Writes a DTD section. The \a dtd represents the entire
3617 doctypedecl production from the XML 1.0 specification.
3618 */
3619void QXmlStreamWriter::writeDTD(const QString &dtd)
3620{
3621 Q_D(QXmlStreamWriter);
3622 d->finishStartElement();
3623 if (d->autoFormatting)
3624 d->write("\n");
3625 d->write(dtd);
3626 if (d->autoFormatting)
3627 d->write("\n");
3628}
3629
3630
3631
3632/*! \overload
3633 Writes an empty element with qualified name \a qualifiedName.
3634 Subsequent calls to writeAttribute() will add attributes to this element.
3635*/
3636void QXmlStreamWriter::writeEmptyElement(const QString &qualifiedName)
3637{
3638 Q_D(QXmlStreamWriter);
3639 Q_ASSERT(qualifiedName.count(QLatin1Char(':')) <= 1);
3640 d->writeStartElement(QString(), qualifiedName);
3641 d->inEmptyElement = true;
3642}
3643
3644
3645/*! Writes an empty element with \a name, prefixed for the specified
3646 \a namespaceUri. If the namespace has not been declared,
3647 QXmlStreamWriter will generate a namespace declaration for it.
3648 Subsequent calls to writeAttribute() will add attributes to this element.
3649
3650 \sa writeNamespace()
3651 */
3652void QXmlStreamWriter::writeEmptyElement(const QString &namespaceUri, const QString &name)
3653{
3654 Q_D(QXmlStreamWriter);
3655 Q_ASSERT(!name.contains(QLatin1Char(':')));
3656 d->writeStartElement(namespaceUri, name);
3657 d->inEmptyElement = true;
3658}
3659
3660
3661/*!\overload
3662 Writes a text element with \a qualifiedName and \a text.
3663
3664
3665 This is a convenience function equivalent to:
3666 \snippet code/src_corelib_xml_qxmlstream.cpp 1
3667
3668*/
3669void QXmlStreamWriter::writeTextElement(const QString &qualifiedName, const QString &text)
3670{
3671 writeStartElement(qualifiedName);
3672 writeCharacters(text);
3673 writeEndElement();
3674}
3675
3676/*! Writes a text element with \a name, prefixed for the specified \a
3677 namespaceUri, and \a text. If the namespace has not been
3678 declared, QXmlStreamWriter will generate a namespace declaration
3679 for it.
3680
3681
3682 This is a convenience function equivalent to:
3683 \snippet code/src_corelib_xml_qxmlstream.cpp 2
3684
3685*/
3686void QXmlStreamWriter::writeTextElement(const QString &namespaceUri, const QString &name, const QString &text)
3687{
3688 writeStartElement(namespaceUri, name);
3689 writeCharacters(text);
3690 writeEndElement();
3691}
3692
3693
3694/*!
3695 Closes all remaining open start elements and writes a newline.
3696
3697 \sa writeStartDocument()
3698 */
3699void QXmlStreamWriter::writeEndDocument()
3700{
3701 Q_D(QXmlStreamWriter);
3702 while (d->tagStack.size())
3703 writeEndElement();
3704 d->write("\n");
3705}
3706
3707/*!
3708 Closes the previous start element.
3709
3710 \sa writeStartElement()
3711 */
3712void QXmlStreamWriter::writeEndElement()
3713{
3714 Q_D(QXmlStreamWriter);
3715 if (d->tagStack.isEmpty())
3716 return;
3717
3718 // shortcut: if nothing was written, close as empty tag
3719 if (d->inStartElement && !d->inEmptyElement) {
3720 d->write("/>");
3721 d->lastWasStartElement = d->inStartElement = false;
3722 QXmlStreamWriterPrivate::Tag &tag = d->tagStack_pop();
3723 d->lastNamespaceDeclaration = tag.namespaceDeclarationsSize;
3724 return;
3725 }
3726
3727 if (!d->finishStartElement(false) && !d->lastWasStartElement && d->autoFormatting)
3728 d->indent(d->tagStack.size()-1);
3729 if (d->tagStack.isEmpty())
3730 return;
3731 d->lastWasStartElement = false;
3732 QXmlStreamWriterPrivate::Tag &tag = d->tagStack_pop();
3733 d->lastNamespaceDeclaration = tag.namespaceDeclarationsSize;
3734 d->write("</");
3735 if (!tag.namespaceDeclaration.prefix.isEmpty()) {
3736 d->write(tag.namespaceDeclaration.prefix);
3737 d->write(":");
3738 }
3739 d->write(tag.name);
3740 d->write(">");
3741}
3742
3743
3744
3745/*!
3746 Writes the entity reference \a name to the stream, as "&\a{name};".
3747 */
3748void QXmlStreamWriter::writeEntityReference(const QString &name)
3749{
3750 Q_D(QXmlStreamWriter);
3751 d->finishStartElement();
3752 d->write("&");
3753 d->write(name);
3754 d->write(";");
3755}
3756
3757
3758/*! Writes a namespace declaration for \a namespaceUri with \a
3759 prefix. If \a prefix is empty, QXmlStreamWriter assigns a unique
3760 prefix consisting of the letter 'n' followed by a number.
3761
3762 If writeStartElement() or writeEmptyElement() was called, the
3763 declaration applies to the current element; otherwise it applies to
3764 the next child element.
3765
3766 Note that the prefix \e xml is both predefined and reserved for
3767 \e http://www.w3.org/XML/1998/namespace, which in turn cannot be
3768 bound to any other prefix. The prefix \e xmlns and its URI
3769 \e