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 QtXml 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 "qglobal.h"
41
42#include "qxml.h"
43#include "qxml_p.h"
44#include "qbuffer.h"
45#include "qstringconverter.h"
46#if QT_CONFIG(regularexpression)
47#include "qregularexpression.h"
48#endif
49#include "qmap.h"
50#include "qhash.h"
51#include "qstack.h"
52#include <qdebug.h>
53
54#ifdef Q_CC_BOR // borland 6 finds bogus warnings when building this file in uic3
55# pragma warn -8080
56#endif
57
58//#define QT_QXML_DEBUG
59
60// Error strings for the XML reader
61#define XMLERR_OK QT_TRANSLATE_NOOP("QXml", "no error occurred")
62#define XMLERR_ERRORBYCONSUMER QT_TRANSLATE_NOOP("QXml", "error triggered by consumer")
63#define XMLERR_UNEXPECTEDEOF QT_TRANSLATE_NOOP("QXml", "unexpected end of file")
64#define XMLERR_MORETHANONEDOCTYPE QT_TRANSLATE_NOOP("QXml", "more than one document type definition")
65#define XMLERR_ERRORPARSINGELEMENT QT_TRANSLATE_NOOP("QXml", "error occurred while parsing element")
66#define XMLERR_TAGMISMATCH QT_TRANSLATE_NOOP("QXml", "tag mismatch")
67#define XMLERR_ERRORPARSINGCONTENT QT_TRANSLATE_NOOP("QXml", "error occurred while parsing content")
68#define XMLERR_UNEXPECTEDCHARACTER QT_TRANSLATE_NOOP("QXml", "unexpected character")
69#define XMLERR_INVALIDNAMEFORPI QT_TRANSLATE_NOOP("QXml", "invalid name for processing instruction")
70#define XMLERR_VERSIONEXPECTED QT_TRANSLATE_NOOP("QXml", "version expected while reading the XML declaration")
71#define XMLERR_WRONGVALUEFORSDECL QT_TRANSLATE_NOOP("QXml", "wrong value for standalone declaration")
72#define XMLERR_EDECLORSDDECLEXPECTED QT_TRANSLATE_NOOP("QXml", "encoding declaration or standalone declaration expected while reading the XML declaration")
73#define XMLERR_SDDECLEXPECTED QT_TRANSLATE_NOOP("QXml", "standalone declaration expected while reading the XML declaration")
74#define XMLERR_ERRORPARSINGDOCTYPE QT_TRANSLATE_NOOP("QXml", "error occurred while parsing document type definition")
75#define XMLERR_LETTEREXPECTED QT_TRANSLATE_NOOP("QXml", "letter is expected")
76#define XMLERR_ERRORPARSINGCOMMENT QT_TRANSLATE_NOOP("QXml", "error occurred while parsing comment")
77#define XMLERR_ERRORPARSINGREFERENCE QT_TRANSLATE_NOOP("QXml", "error occurred while parsing reference")
78#define XMLERR_INTERNALGENERALENTITYINDTD QT_TRANSLATE_NOOP("QXml", "internal general entity reference not allowed in DTD")
79#define XMLERR_EXTERNALGENERALENTITYINAV QT_TRANSLATE_NOOP("QXml", "external parsed general entity reference not allowed in attribute value")
80#define XMLERR_EXTERNALGENERALENTITYINDTD QT_TRANSLATE_NOOP("QXml", "external parsed general entity reference not allowed in DTD")
81#define XMLERR_UNPARSEDENTITYREFERENCE QT_TRANSLATE_NOOP("QXml", "unparsed entity reference in wrong context")
82#define XMLERR_RECURSIVEENTITIES QT_TRANSLATE_NOOP("QXml", "recursive entities")
83#define XMLERR_ERRORINTEXTDECL QT_TRANSLATE_NOOP("QXml", "error in the text declaration of an external entity")
84
85QT_BEGIN_NAMESPACE
86
87namespace {
88
89// work around missing std::stack::clear()
90template <typename Container>
91void clear(Container &c) { c = Container(); }
92
93}
94
95// the constants for the lookup table
96static const signed char cltWS = 0; // white space
97static const signed char cltPer = 1; // %
98static const signed char cltAmp = 2; // &
99static const signed char cltGt = 3; // >
100static const signed char cltLt = 4; // <
101static const signed char cltSlash = 5; // /
102static const signed char cltQm = 6; // ?
103static const signed char cltEm = 7; // !
104static const signed char cltDash = 8; // -
105static const signed char cltCB = 9; // ]
106static const signed char cltOB = 10; // [
107static const signed char cltEq = 11; // =
108static const signed char cltDq = 12; // "
109static const signed char cltSq = 13; // '
110static const signed char cltUnknown = 14;
111
112// character lookup table
113static const signed char charLookupTable[256]={
114 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x00 - 0x07
115 cltUnknown, // 0x08
116 cltWS, // 0x09 \t
117 cltWS, // 0x0A \n
118 cltUnknown, // 0x0B
119 cltUnknown, // 0x0C
120 cltWS, // 0x0D \r
121 cltUnknown, // 0x0E
122 cltUnknown, // 0x0F
123 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x17 - 0x16
124 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x18 - 0x1F
125 cltWS, // 0x20 Space
126 cltEm, // 0x21 !
127 cltDq, // 0x22 "
128 cltUnknown, // 0x23
129 cltUnknown, // 0x24
130 cltPer, // 0x25 %
131 cltAmp, // 0x26 &
132 cltSq, // 0x27 '
133 cltUnknown, // 0x28
134 cltUnknown, // 0x29
135 cltUnknown, // 0x2A
136 cltUnknown, // 0x2B
137 cltUnknown, // 0x2C
138 cltDash, // 0x2D -
139 cltUnknown, // 0x2E
140 cltSlash, // 0x2F /
141 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x30 - 0x37
142 cltUnknown, // 0x38
143 cltUnknown, // 0x39
144 cltUnknown, // 0x3A
145 cltUnknown, // 0x3B
146 cltLt, // 0x3C <
147 cltEq, // 0x3D =
148 cltGt, // 0x3E >
149 cltQm, // 0x3F ?
150 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x40 - 0x47
151 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x48 - 0x4F
152 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x50 - 0x57
153 cltUnknown, // 0x58
154 cltUnknown, // 0x59
155 cltUnknown, // 0x5A
156 cltOB, // 0x5B [
157 cltUnknown, // 0x5C
158 cltCB, // 0x5D]
159 cltUnknown, // 0x5E
160 cltUnknown, // 0x5F
161 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x60 - 0x67
162 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x68 - 0x6F
163 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x70 - 0x77
164 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x78 - 0x7F
165 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x80 - 0x87
166 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x88 - 0x8F
167 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x90 - 0x97
168 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x98 - 0x9F
169 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xA0 - 0xA7
170 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xA8 - 0xAF
171 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xB0 - 0xB7
172 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xB8 - 0xBF
173 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xC0 - 0xC7
174 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xC8 - 0xCF
175 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xD0 - 0xD7
176 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xD8 - 0xDF
177 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xE0 - 0xE7
178 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xE8 - 0xEF
179 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xF0 - 0xF7
180 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown // 0xF8 - 0xFF
181};
182
183//
184// local helper functions
185//
186
187/*
188 This function strips the TextDecl [77] ("<?xml ...?>") from the string \a
189 str. The stripped version is stored in \a str. If this function finds an
190 invalid TextDecl, it returns \c false, otherwise true.
191
192 This function is used for external entities since those can include an
193 TextDecl that must be stripped before inserting the entity.
194*/
195static bool stripTextDecl(QString& str)
196{
197 QLatin1String textDeclStart("<?xml");
198 if (str.startsWith(textDeclStart)) {
199#if QT_CONFIG(regularexpression)
200 QRegularExpression textDecl(QString::fromLatin1(
201 "^<\\?xml\\s+"
202 "(version\\s*=\\s*((['\"])[-a-zA-Z0-9_.:]+\\3))?"
203 "\\s*"
204 "(encoding\\s*=\\s*((['\"])[A-Za-z][-a-zA-Z0-9_.]*\\6))?"
205 "\\s*\\?>"
206 ));
207 QString strTmp = str.replace(textDecl, QLatin1String(""));
208 if (strTmp.length() != str.length())
209 return false; // external entity has wrong TextDecl
210 str = strTmp;
211#else
212 return false;
213#endif
214 }
215 return true;
216}
217
218class QXmlAttributesPrivate
219{
220};
221
222/* \class QXmlInputSourcePrivate
223 \internal
224
225 There's a slight misdesign in this class that can
226 be worth to keep in mind: the `str' member is
227 a buffer which QXmlInputSource::next() returns from,
228 and which is populated from the input device or input
229 stream. However, when the input is a QString(the user called
230 QXmlInputSource::setData()), `str' has two roles: it's the
231 buffer, but also the source. This /seems/ to be no problem
232 because in the case of having no device or stream, the QString
233 is read in one go.
234 */
235class QXmlInputSourcePrivate
236{
237public:
238 QIODevice *inputDevice;
239 QTextStream *inputStream;
240
241 QString str;
242 const QChar *unicode;
243 int pos;
244 int length;
245 bool nextReturnedEndOfData;
246 QStringDecoder toUnicode;
247
248 QByteArray encodingDeclBytes;
249 QString encodingDeclChars;
250 bool lookingForEncodingDecl;
251};
252class QXmlParseExceptionPrivate
253{
254public:
255 QXmlParseExceptionPrivate()
256 : column(-1), line(-1)
257 {
258 }
259 QXmlParseExceptionPrivate(const QXmlParseExceptionPrivate &other)
260 : msg(other.msg), column(other.column), line(other.line),
261 pub(other.pub), sys(other.sys)
262 {
263 }
264
265 QString msg;
266 int column;
267 int line;
268 QString pub;
269 QString sys;
270
271};
272
273class QXmlLocatorPrivate
274{
275};
276
277class QXmlDefaultHandlerPrivate
278{
279};
280
281/*!
282 \class QXmlParseException
283 \reentrant
284 \brief The QXmlParseException class is used to report errors with
285 the QXmlErrorHandler interface.
286
287 \inmodule QtCore5Compat
288 \ingroup xml-tools
289
290 The XML subsystem constructs an instance of this class when it
291 detects an error. You can retrieve the place where the error
292 occurred using systemId(), publicId(), lineNumber() and
293 columnNumber(), along with the error message(). The possible error
294 messages are:
295
296 \list
297 \li "no error occurred"
298 \li "error triggered by consumer"
299 \li "unexpected end of file"
300 \li "more than one document type definition"
301 \li "error occurred while parsing element"
302 \li "tag mismatch"
303 \li "error occurred while parsing content"
304 \li "unexpected character"
305 \li "invalid name for processing instruction"
306 \li "version expected while reading the XML declaration"
307 \li "wrong value for standalone declaration"
308 \li "encoding declaration or standalone declaration expected while reading the XML declaration"
309 \li "standalone declaration expected while reading the XML declaration"
310 \li "error occurred while parsing document type definition"
311 \li "letter is expected"
312 \li "error occurred while parsing comment"
313 \li "error occurred while parsing reference"
314 \li "internal general entity reference not allowed in DTD"
315 \li "external parsed general entity reference not allowed in attribute value"
316 \li "external parsed general entity reference not allowed in DTD"
317 \li "unparsed entity reference n wrong context"
318 \li "recursive entities"
319 \li "error in the text declaration of an external entity"
320 \endlist
321
322 Note that, if you want to display these error messages to your
323 application's users, they will be displayed in English unless
324 they are explicitly translated.
325
326 \sa QXmlErrorHandler, QXmlReader
327*/
328
329/*!
330 Constructs a parse exception with the error string \a name for
331 column \a c and line \a l for the public identifier \a p and the
332 system identifier \a s.
333*/
334
335QXmlParseException::QXmlParseException(const QString& name, int c, int l,
336 const QString& p, const QString& s)
337 : d(new QXmlParseExceptionPrivate)
338{
339 d->msg = name;
340 d->column = c;
341 d->line = l;
342 d->pub = p;
343 d->sys = s;
344}
345
346/*!
347 Creates a copy of \a other.
348*/
349QXmlParseException::QXmlParseException(const QXmlParseException& other) :
350 d(new QXmlParseExceptionPrivate(*other.d))
351{
352
353}
354
355/*!
356 Destroys the QXmlParseException.
357*/
358QXmlParseException::~QXmlParseException()
359{
360}
361
362/*!
363 Returns the error message.
364*/
365QString QXmlParseException::message() const
366{
367 return d->msg;
368}
369/*!
370 Returns the column number where the error occurred.
371*/
372int QXmlParseException::columnNumber() const
373{
374 return d->column;
375}
376/*!
377 Returns the line number where the error occurred.
378*/
379int QXmlParseException::lineNumber() const
380{
381 return d->line;
382}
383/*!
384 Returns the public identifier where the error occurred.
385*/
386QString QXmlParseException::publicId() const
387{
388 return d->pub;
389}
390/*!
391 Returns the system identifier where the error occurred.
392*/
393QString QXmlParseException::systemId() const
394{
395 return d->sys;
396}
397
398/*!
399 \class QXmlLocator
400 \reentrant
401 \brief The QXmlLocator class provides the XML handler classes with
402 information about the parsing position within a file.
403
404 \inmodule QtCore5Compat
405 \ingroup xml-tools
406
407 The reader reports a QXmlLocator to the content handler before it
408 starts to parse the document. This is done with the
409 QXmlContentHandler::setDocumentLocator() function. The handler
410 classes can now use this locator to get the position (lineNumber()
411 and columnNumber()) that the reader has reached.
412*/
413
414/*!
415 Constructor.
416*/
417QXmlLocator::QXmlLocator()
418{
419}
420
421/*!
422 Destructor.
423*/
424QXmlLocator::~QXmlLocator()
425{
426}
427
428/*!
429 \fn int QXmlLocator::columnNumber() const
430
431 Returns the column number (starting at 1) or -1 if there is no
432 column number available.
433*/
434
435/*!
436 \fn int QXmlLocator::lineNumber() const
437
438 Returns the line number (starting at 1) or -1 if there is no line
439 number available.
440*/
441
442class QXmlSimpleReaderLocator : public QXmlLocator
443{
444public:
445 QXmlSimpleReaderLocator(QXmlSimpleReader* parent)
446 {
447 reader = parent;
448 }
449 ~QXmlSimpleReaderLocator()
450 {
451 }
452
453 int columnNumber() const override
454 {
455 return (reader->d_ptr->columnNr == -1 ? -1 : reader->d_ptr->columnNr + 1);
456 }
457 int lineNumber() const override
458 {
459 return (reader->d_ptr->lineNr == -1 ? -1 : reader->d_ptr->lineNr + 1);
460 }
461
462private:
463 QXmlSimpleReader *reader;
464};
465
466/*********************************************
467 *
468 * QXmlNamespaceSupport
469 *
470 *********************************************/
471
472typedef QMap<QString, QString> NamespaceMap;
473
474class QXmlNamespaceSupportPrivate
475{
476public:
477 QXmlNamespaceSupportPrivate()
478 {
479 ns.insert(QLatin1String("xml"), QLatin1String("http://www.w3.org/XML/1998/namespace")); // the XML namespace
480 }
481
482 ~QXmlNamespaceSupportPrivate()
483 {
484 }
485
486 QStack<NamespaceMap> nsStack;
487 NamespaceMap ns;
488};
489
490/*!
491 \class QXmlNamespaceSupport
492 \since 4.4
493 \reentrant
494 \brief The QXmlNamespaceSupport class is a helper class for XML
495 readers which want to include namespace support.
496
497 \inmodule QtCore5Compat
498 \ingroup xml-tools
499
500 You can set the prefix for the current namespace with setPrefix(),
501 and get the list of current prefixes (or those for a given URI)
502 with prefixes(). The namespace URI is available from uri(). Use
503 pushContext() to start a new namespace context, and popContext()
504 to return to the previous namespace context. Use splitName() or
505 processName() to split a name into its prefix and local name.
506*/
507
508/*!
509 Constructs a QXmlNamespaceSupport.
510*/
511QXmlNamespaceSupport::QXmlNamespaceSupport()
512{
513 d = new QXmlNamespaceSupportPrivate;
514}
515
516/*!
517 Destroys a QXmlNamespaceSupport.
518*/
519QXmlNamespaceSupport::~QXmlNamespaceSupport()
520{
521 delete d;
522}
523
524/*!
525 This function declares a prefix \a pre in the current namespace
526 context to be the namespace URI \a uri. The prefix remains in
527 force until this context is popped, unless it is shadowed in a
528 descendant context.
529
530 Note that there is an asymmetry in this library. prefix() does not
531 return the default "" prefix, even if you have declared one; to
532 check for a default prefix, you must look it up explicitly using
533 uri(). This asymmetry exists to make it easier to look up prefixes
534 for attribute names, where the default prefix is not allowed.
535*/
536void QXmlNamespaceSupport::setPrefix(const QString& pre, const QString& uri)
537{
538 if (pre.isNull()) {
539 d->ns.insert(QLatin1String(""), uri);
540 } else {
541 d->ns.insert(pre, uri);
542 }
543}
544
545/*!
546 Returns one of the prefixes mapped to the namespace URI \a uri.
547
548 If more than one prefix is currently mapped to the same URI, this
549 function makes an arbitrary selection; if you want all of the
550 prefixes, use prefixes() instead.
551
552 Note: to check for a default prefix, use the uri() function with
553 an argument of "".
554*/
555QString QXmlNamespaceSupport::prefix(const QString& uri) const
556{
557 NamespaceMap::const_iterator itc, it = d->ns.constBegin();
558 while ((itc=it) != d->ns.constEnd()) {
559 ++it;
560 if (*itc == uri && !itc.key().isEmpty())
561 return itc.key();
562 }
563 return QLatin1String("");
564}
565
566/*!
567 Looks up the prefix \a prefix in the current context and returns
568 the currently-mapped namespace URI. Use the empty string ("") for
569 the default namespace.
570*/
571QString QXmlNamespaceSupport::uri(const QString& prefix) const
572{
573 return d->ns[prefix];
574}
575
576/*!
577 Splits the name \a qname at the ':' and returns the prefix in \a
578 prefix and the local name in \a localname.
579
580 \sa processName()
581*/
582void QXmlNamespaceSupport::splitName(const QString& qname, QString& prefix,
583 QString& localname) const
584{
585 int pos = qname.indexOf(QLatin1Char(':'));
586 if (pos == -1)
587 pos = qname.size();
588
589 prefix = qname.left(pos);
590 localname = qname.mid(pos+1);
591}
592
593/*!
594 Processes a raw XML 1.0 name in the current context by removing
595 the prefix and looking it up among the prefixes currently
596 declared.
597
598 \a qname is the raw XML 1.0 name to be processed. \a isAttribute
599 is true if the name is an attribute name.
600
601 This function stores the namespace URI in \a nsuri (which will be
602 set to an empty string if the raw name has an undeclared prefix),
603 and stores the local name (without prefix) in \a localname (which
604 will be set to an empty string if no namespace is in use).
605
606 Note that attribute names are processed differently than element
607 names: an unprefixed element name gets the default namespace (if
608 any), while an unprefixed attribute name does not.
609*/
610void QXmlNamespaceSupport::processName(const QString& qname,
611 bool isAttribute,
612 QString& nsuri, QString& localname) const
613{
614 int len = qname.size();
615 const QChar *data = qname.constData();
616 for (int pos = 0; pos < len; ++pos) {
617 if (data[pos] == QLatin1Char(':')) {
618 nsuri = uri(qname.left(pos));
619 localname = qname.mid(pos + 1);
620 return;
621 }
622 }
623
624 // there was no ':'
625 nsuri.clear();
626 // attributes don't take default namespace
627 if (!isAttribute && !d->ns.isEmpty()) {
628 /*
629 We want to access d->ns.value(""), but as an optimization
630 we use the fact that "" compares less than any other
631 string, so it's either first in the map or not there.
632 */
633 NamespaceMap::const_iterator first = d->ns.constBegin();
634 if (first.key().isEmpty())
635 nsuri = first.value(); // get default namespace
636 }
637 localname = qname;
638}
639
640/*!
641 Returns a list of all the prefixes currently declared.
642
643 If there is a default prefix, this function does not return it in
644 the list; check for the default prefix using uri() with an
645 argument of "".
646*/
647QStringList QXmlNamespaceSupport::prefixes() const
648{
649 QStringList list;
650
651 NamespaceMap::const_iterator itc, it = d->ns.constBegin();
652 while ((itc=it) != d->ns.constEnd()) {
653 ++it;
654 if (!itc.key().isEmpty())
655 list.append(itc.key());
656 }
657 return list;
658}
659
660/*!
661 \overload
662
663 Returns a list of all prefixes currently declared for the
664 namespace URI \a uri.
665
666 The "xml:" prefix is included. If you only want one prefix that is
667 mapped to the namespace URI, and you don't care which one you get,
668 use the prefix() function instead.
669
670 Note: The empty (default) prefix is never included in this list;
671 to check for the presence of a default namespace, call uri() with
672 "" as the argument.
673*/
674QStringList QXmlNamespaceSupport::prefixes(const QString& uri) const
675{
676 QStringList list;
677
678 NamespaceMap::const_iterator itc, it = d->ns.constBegin();
679 while ((itc=it) != d->ns.constEnd()) {
680 ++it;
681 if (*itc == uri && !itc.key().isEmpty())
682 list.append(itc.key());
683 }
684 return list;
685}
686
687/*!
688 Starts a new namespace context.
689
690 Normally, you should push a new context at the beginning of each
691 XML element: the new context automatically inherits the
692 declarations of its parent context, and it also keeps track of
693 which declarations were made within this context.
694
695 \sa popContext()
696*/
697void QXmlNamespaceSupport::pushContext()
698{
699 d->nsStack.push(d->ns);
700}
701
702/*!
703 Reverts to the previous namespace context.
704
705 Normally, you should pop the context at the end of each XML
706 element. After popping the context, all namespace prefix mappings
707 that were previously in force are restored.
708
709 \sa pushContext()
710*/
711void QXmlNamespaceSupport::popContext()
712{
713 d->ns.clear();
714 if (!d->nsStack.isEmpty())
715 d->ns = d->nsStack.pop();
716}
717
718/*!
719 Resets this namespace support object ready for reuse.
720*/
721void QXmlNamespaceSupport::reset()
722{
723 QXmlNamespaceSupportPrivate *newD = new QXmlNamespaceSupportPrivate;
724 delete d;
725 d = newD;
726}
727
728/*********************************************
729 *
730 * QXmlAttributes
731 *
732 *********************************************/
733
734/*!
735 \class QXmlAttributes
736 \reentrant
737 \brief The QXmlAttributes class provides XML attributes.
738
739 \inmodule QtCore5Compat
740 \ingroup xml-tools
741
742 If attributes are reported by QXmlContentHandler::startElement()
743 this class is used to pass the attribute values.
744
745 Use index() to locate the position of an attribute in the list,
746 count() to retrieve the number of attributes, and clear() to
747 remove the attributes. New attributes can be added with append().
748 Use type() to get an attribute's type and value() to get its
749 value. The attribute's name is available from localName() or
750 qName(), and its namespace URI from uri().
751
752*/
753
754/*!
755 \fn QXmlAttributes::QXmlAttributes()
756
757 Constructs an empty attribute list.
758*/
759QXmlAttributes::QXmlAttributes()
760{
761 // ### In Qt 5.0, this function was inlined and d was not initialized
762 // The member cannot be used until Qt 6.0
763 Q_UNUSED(d);
764}
765
766/*!
767 \fn QXmlAttributes::~QXmlAttributes()
768
769 Destroys the attributes object.
770*/
771QXmlAttributes::~QXmlAttributes()
772{
773}
774
775/*!
776 \fn void QXmlAttributes::swap(QXmlAttributes &other)
777
778 Swaps \c this with \a other.
779 */
780
781/*!
782 Looks up the index of an attribute by the qualified name \a qName.
783
784 Returns the index of the attribute or -1 if it wasn't found.
785*/
786int QXmlAttributes::index(const QString& qName) const
787{
788 for (int i = 0; i < attList.size(); ++i) {
789 if (attList.at(i).qname == qName)
790 return i;
791 }
792 return -1;
793}
794
795/*! \overload
796 */
797int QXmlAttributes::index(QLatin1String qName) const
798{
799 for (int i = 0; i < attList.size(); ++i) {
800 if (attList.at(i).qname == qName)
801 return i;
802 }
803 return -1;
804}
805
806/*!
807 \overload
808
809 Looks up the index of an attribute by a namespace name.
810
811 \a uri specifies the namespace URI, or an empty string if the name
812 has no namespace URI. \a localPart specifies the attribute's local
813 name.
814
815 Returns the index of the attribute, or -1 if it wasn't found.
816*/
817int QXmlAttributes::index(const QString& uri, const QString& localPart) const
818{
819 for (int i = 0; i < attList.size(); ++i) {
820 const Attribute &att = attList.at(i);
821 if (att.uri == uri && att.localname == localPart)
822 return i;
823 }
824 return -1;
825}
826
827/*!
828 Returns the number of attributes in the list.
829
830 \sa count()
831*/
832int QXmlAttributes::length() const
833{
834 return attList.count();
835}
836
837/*!
838 \fn int QXmlAttributes::count() const
839
840 Returns the number of attributes in the list. This function is
841 equivalent to length().
842*/
843
844/*!
845 Looks up an attribute's local name for the attribute at position
846 \a index. If no namespace processing is done, the local name is
847 an empty string.
848*/
849QString QXmlAttributes::localName(int index) const
850{
851 return attList.at(index).localname;
852}
853
854/*!
855 Looks up an attribute's XML 1.0 qualified name for the attribute
856 at position \a index.
857*/
858QString QXmlAttributes::qName(int index) const
859{
860 return attList.at(index).qname;
861}
862
863/*!
864 Looks up an attribute's namespace URI for the attribute at
865 position \a index. If no namespace processing is done or if the
866 attribute has no namespace, the namespace URI is an empty string.
867*/
868QString QXmlAttributes::uri(int index) const
869{
870 return attList.at(index).uri;
871}
872
873/*!
874 Looks up an attribute's type for the attribute at position \a
875 index.
876
877 Currently only "CDATA" is returned.
878*/
879QString QXmlAttributes::type(int) const
880{
881 return QLatin1String("CDATA");
882}
883
884/*!
885 \overload
886
887 Looks up an attribute's type for the qualified name \a qName.
888
889 Currently only "CDATA" is returned.
890*/
891QString QXmlAttributes::type(const QString&) const
892{
893 return QLatin1String("CDATA");
894}
895
896/*!
897 \overload
898
899 Looks up an attribute's type by namespace name.
900
901 \a uri specifies the namespace URI and \a localName specifies the
902 local name. If the name has no namespace URI, use an empty string
903 for \a uri.
904
905 Currently only "CDATA" is returned.
906*/
907QString QXmlAttributes::type(const QString&, const QString&) const
908{
909 return QLatin1String("CDATA");
910}
911
912/*!
913 Returns an attribute's value for the attribute at position \a
914 index. The index must be a valid position
915 (i.e., 0 <= \a index < count()).
916*/
917QString QXmlAttributes::value(int index) const
918{
919 return attList.at(index).value;
920}
921
922/*!
923 \overload
924
925 Returns an attribute's value for the qualified name \a qName, or an
926 empty string if no attribute exists for the name given.
927*/
928QString QXmlAttributes::value(const QString& qName) const
929{
930 int i = index(qName);
931 if (i == -1)
932 return QString();
933 return attList.at(i).value;
934}
935
936/*!
937 \overload
938
939 Returns an attribute's value for the qualified name \a qName, or an
940 empty string if no attribute exists for the name given.
941*/
942QString QXmlAttributes::value(QLatin1String qName) const
943{
944 int i = index(qName);
945 if (i == -1)
946 return QString();
947 return attList.at(i).value;
948}
949
950/*!
951 \overload
952
953 Returns an attribute's value by namespace name.
954
955 \a uri specifies the namespace URI, or an empty string if the name
956 has no namespace URI. \a localName specifies the attribute's local
957 name.
958*/
959QString QXmlAttributes::value(const QString& uri, const QString& localName) const
960{
961 int i = index(uri, localName);
962 if (i == -1)
963 return QString();
964 return attList.at(i).value;
965}
966
967/*!
968 Clears the list of attributes.
969
970 \sa append()
971*/
972void QXmlAttributes::clear()
973{
974 attList.clear();
975}
976
977/*!
978 Appends a new attribute entry to the list of attributes. The
979 qualified name of the attribute is \a qName, the namespace URI is
980 \a uri and the local name is \a localPart. The value of the
981 attribute is \a value.
982
983 \sa qName(), uri(), localName(), value()
984*/
985void QXmlAttributes::append(const QString &qName, const QString &uri, const QString &localPart, const QString &value)
986{
987 Attribute att;
988 att.qname = qName;
989 att.uri = uri;
990 att.localname = localPart;
991 att.value = value;
992
993 attList.append(att);
994}
995
996/*********************************************
997 *
998 * QXmlInputSource
999 *
1000 *********************************************/
1001
1002/*!
1003 \class QXmlInputSource
1004 \reentrant
1005 \brief The QXmlInputSource class provides the input data for the
1006 QXmlReader subclasses.
1007
1008 \inmodule QtCore5Compat
1009 \ingroup xml-tools
1010
1011 All subclasses of QXmlReader read the input XML document from this
1012 class.
1013
1014 This class recognizes the encoding of the data by reading the
1015 encoding declaration in the XML file if it finds one, and reading
1016 the data using the corresponding encoding. If it does not find an
1017 encoding declaration, then it assumes that the data is either in
1018 UTF-8 or UTF-16, depending on whether it can find a byte-order
1019 mark.
1020
1021 There are two ways to populate the input source with data: you can
1022 construct it with a QIODevice* so that the input source reads the
1023 data from that device. Or you can set the data explicitly with one
1024 of the setData() functions.
1025
1026 Usually you either construct a QXmlInputSource that works on a
1027 QIODevice* or you construct an empty QXmlInputSource and set the
1028 data with setData(). There are only rare occasions where you would
1029 want to mix both methods.
1030
1031 The QXmlReader subclasses use the next() function to read the
1032 input character by character. If you want to start from the
1033 beginning again, use reset().
1034
1035 The functions data() and fetchData() are useful if you want to do
1036 something with the data other than parsing, e.g. displaying the
1037 raw XML file. The benefit of using the QXmlInputClass in such
1038 cases is that it tries to use the correct encoding.
1039
1040 \sa QXmlReader, QXmlSimpleReader
1041*/
1042
1043// the following two are guaranteed not to be a character
1044const char16_t QXmlInputSource::EndOfData = 0xfffe;
1045const char16_t QXmlInputSource::EndOfDocument = 0xffff;
1046
1047/*
1048 Common part of the constructors.
1049*/
1050void QXmlInputSource::init()
1051{
1052 d = new QXmlInputSourcePrivate;
1053
1054 QT_TRY {
1055 d->inputDevice = nullptr;
1056 d->inputStream = nullptr;
1057
1058 setData(QString());
1059 d->nextReturnedEndOfData = true; // first call to next() will call fetchData()
1060
1061 d->encodingDeclBytes.clear();
1062 d->encodingDeclChars.clear();
1063 d->lookingForEncodingDecl = true;
1064 } QT_CATCH(...) {
1065 delete(d);
1066 QT_RETHROW;
1067 }
1068}
1069
1070/*!
1071 Constructs an input source which contains no data.
1072
1073 \sa setData()
1074*/
1075QXmlInputSource::QXmlInputSource()
1076{
1077 init();
1078}
1079
1080/*!
1081 Constructs an input source and gets the data from device \a dev.
1082 If \a dev is not open, it is opened in read-only mode. If \a dev
1083 is 0 or it is not possible to read from the device, the input
1084 source will contain no data.
1085
1086 \sa setData(), fetchData(), QIODevice
1087*/
1088QXmlInputSource::QXmlInputSource(QIODevice *dev)
1089{
1090 init();
1091 d->inputDevice = dev;
1092 if (dev->isOpen())
1093 d->inputDevice->setTextModeEnabled(false);
1094}
1095
1096/*!
1097 Destructor.
1098*/
1099QXmlInputSource::~QXmlInputSource()
1100{
1101 // ### close the input device.
1102 delete d;
1103}
1104
1105/*!
1106Returns the next character of the input source. If this function
1107reaches the end of available data, it returns
1108QXmlInputSource::EndOfData. If you call next() after that, it
1109tries to fetch more data by calling fetchData(). If the
1110fetchData() call results in new data, this function returns the
1111first character of that data; otherwise it returns
1112QXmlInputSource::EndOfDocument.
1113
1114Readers, such as QXmlSimpleReader, will assume that the end of
1115the XML document has been reached if the this function returns
1116QXmlInputSource::EndOfDocument, and will check that the
1117supplied input is well-formed. Therefore, when reimplementing
1118this function, it is important to ensure that this behavior is
1119duplicated.
1120
1121\sa reset(), fetchData(), QXmlSimpleReader::parse(),
1122 QXmlSimpleReader::parseContinue()
1123*/
1124QChar QXmlInputSource::next()
1125{
1126 if (d->pos >= d->length) {
1127 if (d->nextReturnedEndOfData) {
1128 d->nextReturnedEndOfData = false;
1129 fetchData();
1130 if (d->pos >= d->length) {
1131 return EndOfDocument;
1132 }
1133 return next();
1134 }
1135 d->nextReturnedEndOfData = true;
1136 return EndOfData;
1137 }
1138
1139 // QXmlInputSource has no way to signal encoding errors. The best we can do
1140 // is return EndOfDocument. We do *not* return EndOfData, because the reader
1141 // will then just call this function again to get the next char.
1142 QChar c = d->unicode[d->pos++];
1143 if (c == EndOfData)
1144 c = EndOfDocument;
1145 return c;
1146}
1147
1148/*!
1149 This function sets the position used by next() to the beginning of
1150 the data returned by data(). This is useful if you want to use the
1151 input source for more than one parse.
1152
1153 \note In the case that the underlying data source is a QIODevice,
1154 the current position in the device is not automatically set to the
1155 start of input. Call QIODevice::seek(0) on the device to do this.
1156
1157 \sa next()
1158*/
1159void QXmlInputSource::reset()
1160{
1161 d->nextReturnedEndOfData = false;
1162 d->pos = 0;
1163}
1164
1165/*!
1166 Returns the data the input source contains or an empty string if the
1167 input source does not contain any data.
1168
1169 \sa setData(), QXmlInputSource(), fetchData()
1170*/
1171QString QXmlInputSource::data() const
1172{
1173 if (d->nextReturnedEndOfData) {
1174 QXmlInputSource *that = const_cast<QXmlInputSource*>(this);
1175 that->d->nextReturnedEndOfData = false;
1176 that->fetchData();
1177 }
1178 return d->str;
1179}
1180
1181/*!
1182 Sets the data of the input source to \a dat.
1183
1184 If the input source already contains data, this function deletes
1185 that data first.
1186
1187 \sa data()
1188*/
1189void QXmlInputSource::setData(const QString& dat)
1190{
1191 d->str = dat;
1192 d->unicode = dat.unicode();
1193 d->pos = 0;
1194 d->length = d->str.length();
1195 d->nextReturnedEndOfData = false;
1196}
1197
1198/*!
1199 \overload
1200
1201 The data \a dat is passed through the correct text-codec, before
1202 it is set.
1203*/
1204void QXmlInputSource::setData(const QByteArray& dat)
1205{
1206 setData(fromRawData(dat));
1207}
1208
1209/*!
1210 This function reads more data from the device that was set during
1211 construction. If the input source already contained data, this
1212 function deletes that data first.
1213
1214 This object contains no data after a call to this function if the
1215 object was constructed without a device to read data from or if
1216 this function was not able to get more data from the device.
1217
1218 There are two occasions where a fetch is done implicitly by
1219 another function call: during construction (so that the object
1220 starts out with some initial data where available), and during a
1221 call to next() (if the data had run out).
1222
1223 You don't normally need to use this function if you use next().
1224
1225 \sa data(), next(), QXmlInputSource()
1226*/
1227
1228void QXmlInputSource::fetchData()
1229{
1230 enum
1231 {
1232 BufferSize = 1024
1233 };
1234
1235 QByteArray rawData;
1236
1237 if (d->inputDevice || d->inputStream) {
1238 QIODevice *device = d->inputDevice ? d->inputDevice : d->inputStream->device();
1239
1240 if (!device) {
1241 if (d->inputStream && d->inputStream->string()) {
1242 QString *s = d->inputStream->string();
1243 rawData = QByteArray(reinterpret_cast<const char *>(s->constData()),
1244 int(s->size() * sizeof(QChar)));
1245 }
1246 } else if (device->isOpen() || device->open(QIODevice::ReadOnly)) {
1247 rawData.resize(BufferSize);
1248 qint64 size = device->read(rawData.data(), BufferSize);
1249 if (size == 0 && device->waitForReadyRead(-1))
1250 size = device->read(rawData.data(), BufferSize);
1251
1252 rawData.resize(qMax(qint64(0), size));
1253 }
1254
1255 /* We do this inside the "if (d->inputDevice ..." scope
1256 * because if we're not using a stream or device, that is,
1257 * the user set a QString manually, we don't want to set
1258 * d->str. */
1259 setData(fromRawData(rawData));
1260 }
1261}
1262
1263static QString extractEncodingDecl(const QString &text, bool *needMoreText)
1264{
1265 *needMoreText = false;
1266
1267 int l = text.length();
1268 const QLatin1String snip("<?xml", std::min(l, 5));
1269 if (l > 0 && !text.startsWith(snip))
1270 return QString();
1271
1272 int endPos = text.indexOf(QLatin1Char('>'));
1273 if (endPos == -1) {
1274 *needMoreText = l < 255; // we won't look forever
1275 return QString();
1276 }
1277
1278 int pos = text.indexOf(QLatin1String("encoding"));
1279 if (pos == -1 || pos >= endPos)
1280 return QString();
1281
1282 while (pos < endPos) {
1283 QChar uc = text.at(pos);
1284 if (uc == u'\'' || uc == u'"')
1285 break;
1286 ++pos;
1287 }
1288
1289 if (pos == endPos)
1290 return QString();
1291
1292 QString encoding;
1293 ++pos;
1294 while (pos < endPos) {
1295 QChar uc = text.at(pos);
1296 if (uc == u'\'' || uc == u'"')
1297 break;
1298 encoding.append(uc);
1299 ++pos;
1300 }
1301
1302 return encoding;
1303}
1304
1305/*!
1306 This function reads the XML file from \a data and tries to
1307 recognize the encoding. It converts the raw data \a data into a
1308 QString and returns it. It tries its best to get the correct
1309 encoding for the XML file.
1310
1311 If \a beginning is true, this function assumes that the data
1312 starts at the beginning of a new XML document and looks for an
1313 encoding declaration. If \a beginning is false, it converts the
1314 raw data using the encoding determined from prior calls.
1315*/
1316QString QXmlInputSource::fromRawData(const QByteArray &data, bool beginning)
1317{
1318 if (data.size() == 0)
1319 return QString();
1320
1321 if (beginning)
1322 d->toUnicode = QStringDecoder();
1323
1324 // This is the initial UTF codec we will read the encoding declaration with
1325 if (!d->toUnicode.isValid()) {
1326 d->encodingDeclBytes.clear();
1327 d->encodingDeclChars.clear();
1328 d->lookingForEncodingDecl = true;
1329
1330 auto encoding = QStringConverter::encodingForData(data, char16_t('<'));
1331 if (encoding) {
1332 d->lookingForEncodingDecl = false;
1333 d->toUnicode = QStringDecoder(*encoding);
1334 } else {
1335 d->toUnicode = QStringDecoder(QStringDecoder::Utf8);
1336 }
1337 }
1338
1339 QString input = d->toUnicode(data);
1340
1341 if (d->lookingForEncodingDecl) {
1342 d->encodingDeclChars += input;
1343
1344 bool needMoreText;
1345 QByteArray encoding = extractEncodingDecl(d->encodingDeclChars, &needMoreText).toLatin1();
1346
1347 if (!encoding.isEmpty()) {
1348 auto e = QStringDecoder::encodingForData(encoding);
1349 if (e && *e != QStringDecoder::Utf8) {
1350 d->toUnicode = QStringDecoder(*e);
1351
1352 /* The variable input can potentially be large, so we deallocate
1353 * it before calling toUnicode() in order to avoid having two
1354 * large QStrings in memory simultaneously. */
1355 input.clear();
1356
1357 // prime the decoder with the data so far
1358 d->toUnicode(d->encodingDeclBytes);
1359 // now feed it the new data
1360 input = d->toUnicode(data);
1361 }
1362 }
1363
1364 d->encodingDeclBytes += data;
1365 d->lookingForEncodingDecl = needMoreText;
1366 }
1367
1368 return input;
1369}
1370
1371/*********************************************
1372 *
1373 * QXmlDefaultHandler
1374 *
1375 *********************************************/
1376
1377/*!
1378 \class QXmlContentHandler
1379 \reentrant
1380 \brief The QXmlContentHandler class provides an interface to
1381 report the logical content of XML data.
1382
1383 \inmodule QtCore5Compat
1384 \ingroup xml-tools
1385
1386 If the application needs to be informed of basic parsing events,
1387 it can implement this interface and activate it using
1388 QXmlReader::setContentHandler(). The reader can then report basic
1389 document-related events like the start and end of elements and
1390 character data through this interface.
1391
1392 The order of events in this interface is very important, and
1393 mirrors the order of information in the document itself. For
1394 example, all of an element's content (character data, processing
1395 instructions, and sub-elements) appears, in order, between the
1396 startElement() event and the corresponding endElement() event.
1397
1398 The class QXmlDefaultHandler provides a default implementation for
1399 this interface; subclassing from the QXmlDefaultHandler class is
1400 very convenient if you only want to be informed of some parsing
1401 events.
1402
1403 The startDocument() function is called at the start of the
1404 document, and endDocument() is called at the end. Before parsing
1405 begins setDocumentLocator() is called. For each element
1406 startElement() is called, with endElement() being called at the
1407 end of each element. The characters() function is called with
1408 chunks of character data; ignorableWhitespace() is called with
1409 chunks of whitespace and processingInstruction() is called with
1410 processing instructions. If an entity is skipped skippedEntity()
1411 is called. At the beginning of prefix-URI scopes
1412 startPrefixMapping() is called.
1413
1414 \sa QXmlDTDHandler, QXmlDeclHandler, QXmlEntityResolver, QXmlErrorHandler,
1415 QXmlLexicalHandler
1416*/
1417
1418/*!
1419 \fn QXmlContentHandler::~QXmlContentHandler()
1420
1421 Destroys the content handler.
1422*/
1423
1424/*!
1425 \fn void QXmlContentHandler::setDocumentLocator(QXmlLocator* locator)
1426
1427 The reader calls this function before it starts parsing the
1428 document. The argument \a locator is a pointer to a QXmlLocator
1429 which allows the application to get the parsing position within
1430 the document.
1431
1432 Do not destroy the \a locator; it is destroyed when the reader is
1433 destroyed. (Do not use the \a locator after the reader is
1434 destroyed).
1435*/
1436
1437/*!
1438 \fn bool QXmlContentHandler::startDocument()
1439
1440 The reader calls this function when it starts parsing the
1441 document. The reader calls this function just once, after the call
1442 to setDocumentLocator(), and before any other functions in this
1443 class or in the QXmlDTDHandler class are called.
1444
1445 If this function returns \c false the reader stops parsing and
1446 reports an error. The reader uses the function errorString() to
1447 get the error message.
1448
1449 \sa endDocument()
1450*/
1451
1452/*!
1453 \fn bool QXmlContentHandler::endDocument()
1454
1455 The reader calls this function after it has finished parsing. It
1456 is called just once, and is the last handler function called. It
1457 is called after the reader has read all input or has abandoned
1458 parsing because of a fatal error.
1459
1460 If this function returns \c false the reader stops parsing and
1461 reports an error. The reader uses the function errorString() to
1462 get the error message.
1463
1464 \sa startDocument()
1465*/
1466
1467/*!
1468 \fn bool QXmlContentHandler::startPrefixMapping(const QString& prefix, const QString& uri)
1469
1470 The reader calls this function to signal the begin of a prefix-URI
1471 namespace mapping scope. This information is not necessary for
1472 normal namespace processing since the reader automatically
1473 replaces prefixes for element and attribute names.
1474
1475 Note that startPrefixMapping() and endPrefixMapping() calls are
1476 not guaranteed to be properly nested relative to each other: all
1477 startPrefixMapping() events occur before the corresponding
1478 startElement() event, and all endPrefixMapping() events occur
1479 after the corresponding endElement() event, but their order is not
1480 otherwise guaranteed.
1481
1482 The argument \a prefix is the namespace prefix being declared and
1483 the argument \a uri is the namespace URI the prefix is mapped to.
1484
1485 If this function returns \c false the reader stops parsing and
1486 reports an error. The reader uses the function errorString() to
1487 get the error message.
1488
1489 \sa endPrefixMapping()
1490*/
1491
1492/*!
1493 \fn bool QXmlContentHandler::endPrefixMapping(const QString& prefix)
1494
1495 The reader calls this function to signal the end of a prefix
1496 mapping for the prefix \a prefix.
1497
1498 If this function returns \c false the reader stops parsing and
1499 reports an error. The reader uses the function errorString() to
1500 get the error message.
1501
1502 \sa startPrefixMapping()
1503*/
1504
1505/*!
1506 \fn bool QXmlContentHandler::startElement(const QString& namespaceURI, const QString& localName, const QString& qName, const QXmlAttributes& atts)
1507
1508 The reader calls this function when it has parsed a start element
1509 tag.
1510
1511 There is a corresponding endElement() call when the corresponding
1512 end element tag is read. The startElement() and endElement() calls
1513 are always nested correctly. Empty element tags (e.g. \c{<x/>})
1514 cause a startElement() call to be immediately followed by an
1515 endElement() call.
1516
1517 The attribute list provided only contains attributes with explicit
1518 values. The attribute list contains attributes used for namespace
1519 declaration (i.e. attributes starting with xmlns) only if the
1520 namespace-prefix property of the reader is true.
1521
1522 The argument \a namespaceURI is the namespace URI, or
1523 an empty string if the element has no namespace URI or if no
1524 namespace processing is done. \a localName is the local name
1525 (without prefix), or an empty string if no namespace processing is
1526 done, \a qName is the qualified name (with prefix) and \a atts are
1527 the attributes attached to the element. If there are no
1528 attributes, \a atts is an empty attributes object.
1529
1530 If this function returns \c false the reader stops parsing and
1531 reports an error. The reader uses the function errorString() to
1532 get the error message.
1533
1534 \sa endElement()
1535*/
1536
1537/*!
1538 \fn bool QXmlContentHandler::endElement(const QString& namespaceURI, const QString& localName, const QString& qName)
1539
1540 The reader calls this function when it has parsed an end element
1541 tag with the qualified name \a qName, the local name \a localName
1542 and the namespace URI \a namespaceURI.
1543
1544 If this function returns \c false the reader stops parsing and
1545 reports an error. The reader uses the function errorString() to
1546 get the error message.
1547
1548 \sa startElement()
1549*/
1550
1551/*!
1552 \fn bool QXmlContentHandler::characters(const QString& ch)
1553
1554 The reader calls this function when it has parsed a chunk of
1555 character data (either normal character data or character data
1556 inside a CDATA section; if you need to distinguish between those
1557 two types you must use QXmlLexicalHandler::startCDATA() and
1558 QXmlLexicalHandler::endCDATA()). The character data is reported in
1559 \a ch.
1560
1561 Some readers report whitespace in element content using the
1562 ignorableWhitespace() function rather than using this one.
1563
1564 A reader may report the character data of an element in more than
1565 one chunk; e.g. a reader might want to report "a\<b" in three
1566 characters() events ("a ", "\<" and " b").
1567
1568 If this function returns \c false the reader stops parsing and
1569 reports an error. The reader uses the function errorString() to
1570 get the error message.
1571*/
1572
1573/*!
1574 \fn bool QXmlContentHandler::ignorableWhitespace(const QString& ch)
1575
1576 Some readers may use this function to report each chunk of
1577 whitespace in element content. The whitespace is reported in \a ch.
1578
1579 If this function returns \c false the reader stops parsing and
1580 reports an error. The reader uses the function errorString() to
1581 get the error message.
1582*/
1583
1584/*!
1585 \fn bool QXmlContentHandler::processingInstruction(const QString& target, const QString& data)
1586
1587 The reader calls this function when it has parsed a processing
1588 instruction.
1589
1590 \a target is the target name of the processing instruction and \a
1591 data is the data in the processing instruction.
1592
1593 If this function returns \c false the reader stops parsing and
1594 reports an error. The reader uses the function errorString() to
1595 get the error message.
1596*/
1597
1598/*!
1599 \fn bool QXmlContentHandler::skippedEntity(const QString& name)
1600
1601 Some readers may skip entities if they have not seen the
1602 declarations (e.g. because they are in an external DTD). If they
1603 do so they report that they skipped the entity called \a name by
1604 calling this function.
1605
1606 If this function returns \c false the reader stops parsing and
1607 reports an error. The reader uses the function errorString() to
1608 get the error message.
1609*/
1610
1611/*!
1612 \fn QString QXmlContentHandler::errorString() const
1613
1614 The reader calls this function to get an error string, e.g. if any
1615 of the handler functions returns \c false.
1616*/
1617
1618/*!
1619 \class QXmlErrorHandler
1620 \reentrant
1621 \brief The QXmlErrorHandler class provides an interface to report
1622 errors in XML data.
1623
1624 \inmodule QtCore5Compat
1625 \ingroup xml-tools
1626
1627 If you want your application to report errors to the user or to
1628 perform customized error handling, you should subclass this class.
1629
1630 You can set the error handler with QXmlReader::setErrorHandler().
1631
1632 Errors can be reported using warning(), error() and fatalError(),
1633 with the error text being reported with errorString().
1634
1635 \sa QXmlDTDHandler, QXmlDeclHandler, QXmlContentHandler, QXmlEntityResolver,
1636 QXmlLexicalHandler
1637*/
1638
1639/*!
1640 \fn QXmlErrorHandler::~QXmlErrorHandler()
1641
1642 Destroys the error handler.
1643*/
1644
1645/*!
1646 \fn bool QXmlErrorHandler::warning(const QXmlParseException& exception)
1647
1648 A reader might use this function to report a warning. Warnings are
1649 conditions that are not errors or fatal errors as defined by the
1650 XML 1.0 specification. Details of the warning are stored in \a
1651 exception.
1652
1653 If this function returns \c false the reader stops parsing and
1654 reports an error. The reader uses the function errorString() to
1655 get the error message.
1656*/
1657
1658/*!
1659 \fn bool QXmlErrorHandler::error(const QXmlParseException& exception)
1660
1661 A reader might use this function to report a recoverable error. A
1662 recoverable error corresponds to the definiton of "error" in
1663 section 1.2 of the XML 1.0 specification. Details of the error are
1664 stored in \a exception.
1665
1666 The reader must continue to provide normal parsing events after
1667 invoking this function.
1668
1669 If this function returns \c false the reader stops parsing and
1670 reports an error. The reader uses the function errorString() to
1671 get the error message.
1672*/
1673
1674/*!
1675\fn bool QXmlErrorHandler::fatalError(const QXmlParseException& exception)
1676
1677A reader must use this function to report a non-recoverable error.
1678Details of the error are stored in \a exception.
1679
1680If this function returns \c true the reader might try to go on
1681parsing and reporting further errors, but no regular parsing
1682events are reported.
1683*/
1684
1685/*!
1686 \fn QString QXmlErrorHandler::errorString() const
1687
1688 The reader calls this function to get an error string if any of
1689 the handler functions returns \c false.
1690*/
1691
1692/*!
1693 \class QXmlDTDHandler
1694 \reentrant
1695 \brief The QXmlDTDHandler class provides an interface to report
1696 DTD content of XML data.
1697
1698 \inmodule QtCore5Compat
1699 \ingroup xml-tools
1700
1701 If an application needs information about notations and unparsed
1702 entities, it can implement this interface and register an instance
1703 with QXmlReader::setDTDHandler().
1704
1705 Note that this interface includes only those DTD events that the
1706 XML recommendation requires processors to report, i.e. notation
1707 and unparsed entity declarations using notationDecl() and
1708 unparsedEntityDecl() respectively.
1709
1710 \sa QXmlDeclHandler, QXmlContentHandler, QXmlEntityResolver, QXmlErrorHandler,
1711 QXmlLexicalHandler
1712*/
1713
1714/*!
1715 \fn QXmlDTDHandler::~QXmlDTDHandler()
1716
1717 Destroys the DTD handler.
1718*/
1719
1720/*!
1721 \fn bool QXmlDTDHandler::notationDecl(const QString& name, const QString& publicId, const QString& systemId)
1722
1723 The reader calls this function when it has parsed a notation
1724 declaration.
1725
1726 The argument \a name is the notation name, \a publicId is the
1727 notation's public identifier and \a systemId is the notation's
1728 system identifier.
1729
1730 If this function returns \c false the reader stops parsing and
1731 reports an error. The reader uses the function errorString() to
1732 get the error message.
1733*/
1734
1735/*!
1736 \fn bool QXmlDTDHandler::unparsedEntityDecl(const QString& name, const QString& publicId, const QString& systemId, const QString& notationName)
1737
1738 The reader calls this function when it finds an unparsed entity
1739 declaration.
1740
1741 The argument \a name is the unparsed entity's name, \a publicId is
1742 the entity's public identifier, \a systemId is the entity's system
1743 identifier and \a notationName is the name of the associated
1744 notation.
1745
1746 If this function returns \c false the reader stops parsing and
1747 reports an error. The reader uses the function errorString() to
1748 get the error message.
1749*/
1750
1751/*!
1752 \fn QString QXmlDTDHandler::errorString() const
1753
1754 The reader calls this function to get an error string if any of
1755 the handler functions returns \c false.
1756*/
1757
1758/*!
1759 \class QXmlEntityResolver
1760 \reentrant
1761 \brief The QXmlEntityResolver class provides an interface to
1762 resolve external entities contained in XML data.
1763
1764 \inmodule QtCore5Compat
1765 \ingroup xml-tools
1766
1767 If an application needs to implement customized handling for
1768 external entities, it must implement this interface, i.e.
1769 resolveEntity(), and register it with
1770 QXmlReader::setEntityResolver().
1771
1772 \sa QXmlDTDHandler, QXmlDeclHandler, QXmlContentHandler, QXmlErrorHandler,
1773 QXmlLexicalHandler
1774*/
1775
1776/*!
1777 \fn QXmlEntityResolver::~QXmlEntityResolver()
1778
1779 Destroys the entity resolver.
1780*/
1781
1782/*!
1783 \fn bool QXmlEntityResolver::resolveEntity(const QString& publicId, const QString& systemId, QXmlInputSource*& ret)
1784
1785 The reader calls this function before it opens any external
1786 entity, except the top-level document entity. The application may
1787 request the reader to resolve the entity itself (\a ret is 0) or
1788 to use an entirely different input source (\a ret points to the
1789 input source).
1790
1791 The reader deletes the input source \a ret when it no longer needs
1792 it, so you should allocate it on the heap with \c new.
1793
1794 The argument \a publicId is the public identifier of the external
1795 entity, \a systemId is the system identifier of the external
1796 entity and \a ret is the return value of this function. If \a ret
1797 is 0 the reader should resolve the entity itself, if it is
1798 non-zero it must point to an input source which the reader uses
1799 instead.
1800
1801 If this function returns \c false the reader stops parsing and
1802 reports an error. The reader uses the function errorString() to
1803 get the error message.
1804*/
1805
1806/*!
1807 \fn QString QXmlEntityResolver::errorString() const
1808
1809 The reader calls this function to get an error string if any of
1810 the handler functions returns \c false.
1811*/
1812
1813/*!
1814 \class QXmlLexicalHandler
1815 \reentrant
1816 \brief The QXmlLexicalHandler class provides an interface to
1817 report the lexical content of XML data.
1818
1819 \inmodule QtCore5Compat
1820 \ingroup xml-tools
1821
1822 The events in the lexical handler apply to the entire document,
1823 not just to the document element, and all lexical handler events
1824 appear between the content handler's startDocument and endDocument
1825 events.
1826
1827 You can set the lexical handler with
1828 QXmlReader::setLexicalHandler().
1829
1830 This interface's design is based on the SAX2 extension
1831 LexicalHandler.
1832
1833 The interface provides the startDTD(), endDTD(), startEntity(),
1834 endEntity(), startCDATA(), endCDATA() and comment() functions.
1835
1836 \sa QXmlDTDHandler, QXmlDeclHandler, QXmlContentHandler, QXmlEntityResolver,
1837 QXmlErrorHandler
1838*/
1839
1840/*!
1841 \fn QXmlLexicalHandler::~QXmlLexicalHandler()
1842
1843 Destroys the lexical handler.
1844*/
1845
1846/*!
1847 \fn bool QXmlLexicalHandler::startDTD(const QString& name, const QString& publicId, const QString& systemId)
1848
1849 The reader calls this function to report the start of a DTD
1850 declaration, if any. It reports the name of the document type in
1851 \a name, the public identifier in \a publicId and the system
1852 identifier in \a systemId.
1853
1854 If the public identifier is missing, \a publicId is set to
1855 an empty string. If the system identifier is missing, \a systemId is
1856 set to an empty string. Note that it is not valid XML to have a
1857 public identifier but no system identifier; in such cases a parse
1858 error will occur.
1859
1860 All declarations reported through QXmlDTDHandler or
1861 QXmlDeclHandler appear between the startDTD() and endDTD() calls.
1862
1863 If this function returns \c false the reader stops parsing and
1864 reports an error. The reader uses the function errorString() to
1865 get the error message.
1866
1867 \sa endDTD()
1868*/
1869
1870/*!
1871 \fn bool QXmlLexicalHandler::endDTD()
1872
1873 The reader calls this function to report the end of a DTD
1874 declaration, if any.
1875
1876 If this function returns \c false the reader stops parsing and
1877 reports an error. The reader uses the function errorString() to
1878 get the error message.
1879
1880 \sa startDTD()
1881*/
1882
1883/*!
1884 \fn bool QXmlLexicalHandler::startEntity(const QString& name)
1885
1886 The reader calls this function to report the start of an entity
1887 called \a name.
1888
1889 Note that if the entity is unknown, the reader reports it through
1890 QXmlContentHandler::skippedEntity() and not through this
1891 function.
1892
1893 If this function returns \c false the reader stops parsing and
1894 reports an error. The reader uses the function errorString() to
1895 get the error message.
1896
1897 \sa endEntity(), QXmlSimpleReader::setFeature()
1898*/
1899
1900/*!
1901 \fn bool QXmlLexicalHandler::endEntity(const QString& name)
1902
1903 The reader calls this function to report the end of an entity
1904 called \a name.
1905
1906 For every startEntity() call, there is a corresponding endEntity()
1907 call. The calls to startEntity() and endEntity() are properly
1908 nested.
1909
1910 If this function returns \c false the reader stops parsing and
1911 reports an error. The reader uses the function errorString() to
1912 get the error message.
1913
1914 \sa startEntity(), QXmlContentHandler::skippedEntity(), QXmlSimpleReader::setFeature()
1915*/
1916
1917/*!
1918 \fn bool QXmlLexicalHandler::startCDATA()
1919
1920 The reader calls this function to report the start of a CDATA
1921 section. The content of the CDATA section is reported through the
1922 QXmlContentHandler::characters() function. This function is
1923 intended only to report the boundary.
1924
1925 If this function returns \c false the reader stops parsing and
1926 reports an error. The reader uses the function errorString() to
1927 get the error message.
1928
1929 \sa endCDATA()
1930*/
1931
1932/*!
1933 \fn bool QXmlLexicalHandler::endCDATA()
1934
1935 The reader calls this function to report the end of a CDATA
1936 section.
1937
1938 If this function returns \c false the reader stops parsing and reports
1939 an error. The reader uses the function errorString() to get the error
1940 message.
1941
1942 \sa startCDATA(), QXmlContentHandler::characters()
1943*/
1944
1945/*!
1946 \fn bool QXmlLexicalHandler::comment(const QString& ch)
1947
1948 The reader calls this function to report an XML comment anywhere
1949 in the document. It reports the text of the comment in \a ch.
1950
1951 If this function returns \c false the reader stops parsing and
1952 reports an error. The reader uses the function errorString() to
1953 get the error message.
1954*/
1955
1956/*!
1957 \fn QString QXmlLexicalHandler::errorString() const
1958
1959 The reader calls this function to get an error string if any of
1960 the handler functions returns \c false.
1961*/
1962
1963/*!
1964 \class QXmlDeclHandler
1965 \reentrant
1966 \brief The QXmlDeclHandler class provides an interface to report declaration
1967 content of XML data.
1968
1969 \inmodule QtCore5Compat
1970 \ingroup xml-tools
1971
1972 You can set the declaration handler with
1973 QXmlReader::setDeclHandler().
1974
1975 This interface is based on the SAX2 extension DeclHandler.
1976
1977 The interface provides attributeDecl(), internalEntityDecl() and
1978 externalEntityDecl() functions.
1979
1980 \sa QXmlDTDHandler, QXmlContentHandler, QXmlEntityResolver, QXmlErrorHandler,
1981 QXmlLexicalHandler
1982*/
1983
1984/*!
1985 \fn QXmlDeclHandler::~QXmlDeclHandler()
1986
1987 Destroys the declaration handler.
1988*/
1989
1990/*!
1991 \fn bool QXmlDeclHandler::attributeDecl(const QString& eName, const QString& aName, const QString& type, const QString& valueDefault, const QString& value)
1992
1993 The reader calls this function to report an attribute type
1994 declaration. Only the effective (first) declaration for an
1995 attribute is reported.
1996
1997 The reader passes the name of the associated element in \a eName
1998 and the name of the attribute in \a aName. It passes a string that
1999 represents the attribute type in \a type and a string that
2000 represents the attribute default in \a valueDefault. This string
2001 is one of "#IMPLIED", "#REQUIRED", "#FIXED" or an empty string (if
2002 none of the others applies). The reader passes the attribute's
2003 default value in \a value. If no default value is specified in the
2004 XML file, \a value is an empty string.
2005
2006 If this function returns \c false the reader stops parsing and
2007 reports an error. The reader uses the function errorString() to
2008 get the error message.
2009*/
2010
2011/*!
2012 \fn bool QXmlDeclHandler::internalEntityDecl(const QString& name, const QString& value)
2013
2014 The reader calls this function to report an internal entity
2015 declaration. Only the effective (first) declaration is reported.
2016
2017 The reader passes the name of the entity in \a name and the value
2018 of the entity in \a value.
2019
2020 If this function returns \c false the reader stops parsing and
2021 reports an error. The reader uses the function errorString() to
2022 get the error message.
2023*/
2024
2025/*!
2026 \fn bool QXmlDeclHandler::externalEntityDecl(const QString& name, const QString& publicId, const QString& systemId)
2027
2028 The reader calls this function to report a parsed external entity
2029 declaration. Only the effective (first) declaration for each
2030 entity is reported.
2031
2032 The reader passes the name of the entity in \a name, the public
2033 identifier in \a publicId and the system identifier in \a
2034 systemId. If there is no public identifier specified, it passes
2035 an empty string in \a publicId.
2036
2037 If this function returns \c false the reader stops parsing and
2038 reports an error. The reader uses the function errorString() to
2039 get the error message.
2040*/
2041
2042/*!
2043 \fn QString QXmlDeclHandler::errorString() const
2044
2045 The reader calls this function to get an error string if any of
2046 the handler functions returns \c false.
2047*/
2048
2049/*!
2050 \class QXmlDefaultHandler
2051 \reentrant
2052 \brief The QXmlDefaultHandler class provides a default implementation of all
2053 the XML handler classes.
2054
2055 \inmodule QtCore5Compat
2056 \ingroup xml-tools
2057
2058 This class gathers together the features of
2059 the specialized handler classes, making it a convenient
2060 starting point when implementing custom handlers for
2061 subclasses of QXmlReader, particularly QXmlSimpleReader.
2062 The virtual functions from each of the base classes are
2063 reimplemented in this class, providing sensible default behavior
2064 for many common cases. By subclassing this class, and
2065 overriding these functions, you can concentrate
2066 on implementing the parts of the handler relevant to your
2067 application.
2068
2069 The XML reader must be told which handler to use for different
2070 kinds of events during parsing. This means that, although
2071 QXmlDefaultHandler provides default implementations of functions
2072 inherited from all its base classes, we can still use specialized
2073 handlers for particular kinds of events.
2074
2075 For example, QXmlDefaultHandler subclasses both
2076 QXmlContentHandler and QXmlErrorHandler, so by subclassing
2077 it we can use the same handler for both of the following
2078 reader functions:
2079
2080 \snippet rsslisting/listing.cpp 0
2081
2082 Since the reader will inform the handler of parsing errors, it is
2083 necessary to reimplement QXmlErrorHandler::fatalError() if, for
2084 example, we want to stop parsing when such an error occurs:
2085
2086 \snippet rsslisting/handler.cpp 0
2087
2088 The above function returns \c false, which tells the reader to stop
2089 parsing. To continue to use the same reader,
2090 it is necessary to create a new handler instance, and set up the
2091 reader to use it in the manner described above.
2092
2093 It is useful to examine some of the functions inherited by
2094 QXmlDefaultHandler, and consider why they might be
2095 reimplemented in a custom handler.
2096 Custom handlers will typically reimplement
2097 QXmlContentHandler::startDocument() to prepare the handler for
2098 new content. Document elements and the text within them can be
2099 processed by reimplementing QXmlContentHandler::startElement(),
2100 QXmlContentHandler::endElement(), and
2101 QXmlContentHandler::characters().
2102 You may want to reimplement QXmlContentHandler::endDocument()
2103 to perform some finalization or validation on the content once the
2104 document has been read completely.
2105
2106 \sa QXmlDTDHandler, QXmlDeclHandler, QXmlContentHandler, QXmlEntityResolver,
2107 QXmlErrorHandler, QXmlLexicalHandler
2108*/
2109
2110/*!
2111 \fn QXmlDefaultHandler::QXmlDefaultHandler()
2112
2113 Constructs a handler for use with subclasses of QXmlReader.
2114*/
2115QXmlDefaultHandler::QXmlDefaultHandler()
2116{
2117 // ### In Qt 5.0, this function was inlined and d was not initialized
2118 // The member cannot be used until Qt 6.0
2119 Q_UNUSED(d);
2120}
2121
2122/*!
2123 \fn QXmlDefaultHandler::~QXmlDefaultHandler()
2124
2125 Destroys the handler.
2126*/
2127QXmlDefaultHandler::~QXmlDefaultHandler()
2128{
2129}
2130
2131/*!
2132 \reimp
2133
2134 This reimplementation does nothing.
2135*/
2136void QXmlDefaultHandler::setDocumentLocator(QXmlLocator*)
2137{
2138}
2139
2140/*!
2141 \reimp
2142
2143 This reimplementation does nothing.
2144*/
2145bool QXmlDefaultHandler::startDocument()
2146{
2147 return true;
2148}
2149
2150/*!
2151 \reimp
2152
2153 This reimplementation does nothing.
2154*/
2155bool QXmlDefaultHandler::endDocument()
2156{
2157 return true;
2158}
2159
2160/*!
2161 \reimp
2162
2163 This reimplementation does nothing.
2164*/
2165bool QXmlDefaultHandler::startPrefixMapping(const QString&, const QString&)
2166{
2167 return true;
2168}
2169
2170/*!
2171 \reimp
2172
2173 This reimplementation does nothing.
2174*/
2175bool QXmlDefaultHandler::endPrefixMapping(const QString&)
2176{
2177 return true;
2178}
2179
2180/*!
2181 \reimp
2182
2183 This reimplementation does nothing.
2184*/
2185bool QXmlDefaultHandler::startElement(const QString&, const QString&,
2186 const QString&, const QXmlAttributes&)
2187{
2188 return true;
2189}
2190
2191/*!
2192 \reimp
2193
2194 This reimplementation does nothing.
2195*/
2196bool QXmlDefaultHandler::endElement(const QString&, const QString&,
2197 const QString&)
2198{
2199 return true;
2200}
2201
2202/*!
2203 \reimp
2204
2205 This reimplementation does nothing.
2206*/
2207bool QXmlDefaultHandler::characters(const QString&)
2208{
2209 return true;
2210}
2211
2212/*!
2213 \reimp
2214
2215 This reimplementation does nothing.
2216*/
2217bool QXmlDefaultHandler::ignorableWhitespace(const QString&)
2218{
2219 return true;
2220}
2221
2222/*!
2223 \reimp
2224
2225 This reimplementation does nothing.
2226*/
2227bool QXmlDefaultHandler::processingInstruction(const QString&,
2228 const QString&)
2229{
2230 return true;
2231}
2232
2233/*!
2234 \reimp
2235
2236 This reimplementation does nothing.
2237*/
2238bool QXmlDefaultHandler::skippedEntity(const QString&)
2239{
2240 return true;
2241}
2242
2243/*!
2244 \reimp
2245
2246 This reimplementation does nothing.
2247*/
2248bool QXmlDefaultHandler::warning(const QXmlParseException&)
2249{
2250 return true;
2251}
2252
2253/*!
2254 \reimp
2255
2256 This reimplementation does nothing.
2257*/
2258bool QXmlDefaultHandler::error(const QXmlParseException&)
2259{
2260 return true;
2261}
2262
2263/*!
2264 \reimp
2265
2266 This reimplementation does nothing.
2267*/
2268bool QXmlDefaultHandler::fatalError(const QXmlParseException&)
2269{
2270 return true;
2271}
2272
2273/*!
2274 \reimp
2275
2276 This reimplementation does nothing.
2277*/
2278bool QXmlDefaultHandler::notationDecl(const QString&, const QString&,
2279 const QString&)
2280{
2281 return true;
2282}
2283
2284/*!
2285 \reimp
2286
2287 This reimplementation does nothing.
2288*/
2289bool QXmlDefaultHandler::unparsedEntityDecl(const QString&, const QString&,
2290 const QString&, const QString&)
2291{
2292 return true;
2293}
2294
2295/*!
2296 \reimp
2297
2298 Sets \a ret to \nullptr, so that the reader uses the system identifier
2299 provided in the XML document.
2300*/
2301bool QXmlDefaultHandler::resolveEntity(const QString&, const QString&,
2302 QXmlInputSource*& ret)
2303{
2304 ret = nullptr;
2305 return true;
2306}
2307
2308/*!
2309 \reimp
2310
2311 Returns the default error string.
2312*/
2313QString QXmlDefaultHandler::errorString() const
2314{
2315 return QString::fromLatin1(XMLERR_ERRORBYCONSUMER);
2316}
2317
2318/*!
2319 \reimp
2320
2321 This reimplementation does nothing.
2322*/
2323bool QXmlDefaultHandler::startDTD(const QString&, const QString&, const QString&)
2324{
2325 return true;
2326}
2327
2328/*!
2329 \reimp
2330
2331 This reimplementation does nothing.
2332*/
2333bool QXmlDefaultHandler::endDTD()
2334{
2335 return true;
2336}
2337
2338/*!
2339 \reimp
2340
2341 This reimplementation does nothing.
2342*/
2343bool QXmlDefaultHandler::startEntity(const QString&)
2344{
2345 return true;
2346}
2347
2348/*!
2349 \reimp
2350
2351 This reimplementation does nothing.
2352*/
2353bool QXmlDefaultHandler::endEntity(const QString&)
2354{
2355 return true;
2356}
2357
2358/*!
2359 \reimp
2360
2361 This reimplementation does nothing.
2362*/
2363bool QXmlDefaultHandler::startCDATA()
2364{
2365 return true;
2366}
2367
2368/*!
2369 \reimp
2370
2371 This reimplementation does nothing.
2372*/
2373bool QXmlDefaultHandler::endCDATA()
2374{
2375 return true;
2376}
2377
2378/*!
2379 \reimp
2380
2381 This reimplementation does nothing.
2382*/
2383bool QXmlDefaultHandler::comment(const QString&)
2384{
2385 return true;
2386}
2387
2388/*!
2389 \reimp
2390
2391 This reimplementation does nothing.
2392*/
2393bool QXmlDefaultHandler::attributeDecl(const QString&, const QString&, const QString&, const QString&, const QString&)
2394{
2395 return true;
2396}
2397
2398/*!
2399 \reimp
2400
2401 This reimplementation does nothing.
2402*/
2403bool QXmlDefaultHandler::internalEntityDecl(const QString&, const QString&)
2404{
2405 return true;
2406}
2407
2408/*!
2409 \reimp
2410
2411 This reimplementation does nothing.
2412*/
2413bool QXmlDefaultHandler::externalEntityDecl(const QString&, const QString&, const QString&)
2414{
2415 return true;
2416}
2417
2418/*********************************************
2419 *
2420 * QXmlSimpleReaderPrivate
2421 *
2422 *********************************************/
2423
2424inline bool QXmlSimpleReaderPrivate::atEnd()
2425{
2426 return (c.unicode()|0x0001) == 0xffff;
2427}
2428
2429inline void QXmlSimpleReaderPrivate::stringClear()
2430{
2431 stringValueLen = 0; stringArrayPos = 0;
2432}
2433inline void QXmlSimpleReaderPrivate::nameClear()
2434{
2435 nameValueLen = 0; nameArrayPos = 0;
2436}
2437
2438inline void QXmlSimpleReaderPrivate::refClear()
2439{
2440 refValueLen = 0; refArrayPos = 0;
2441}
2442
2443QXmlSimpleReaderPrivate::QXmlSimpleReaderPrivate(QXmlSimpleReader *reader)
2444{
2445 q_ptr = reader;
2446 parseStack = nullptr;
2447
2448 locator.reset(new QXmlSimpleReaderLocator(reader));
2449 entityRes = nullptr;
2450 dtdHnd = nullptr;
2451 contentHnd = nullptr;
2452 errorHnd = nullptr;
2453 lexicalHnd = nullptr;
2454 declHnd = nullptr;
2455
2456 // default feature settings
2457 useNamespaces = true;
2458 useNamespacePrefixes = false;
2459 reportWhitespaceCharData = true;
2460 reportEntities = false;
2461}
2462
2463QXmlSimpleReaderPrivate::~QXmlSimpleReaderPrivate()
2464{
2465 delete parseStack;
2466}
2467
2468void QXmlSimpleReaderPrivate::initIncrementalParsing()
2469{
2470 if (parseStack)
2471 parseStack->clear();
2472 else
2473 parseStack = new QStack<ParseState>;
2474}
2475
2476/*********************************************
2477 *
2478 * QXmlSimpleReader
2479 *
2480 *********************************************/
2481
2482/*!
2483 \class QXmlReader
2484 \reentrant
2485 \brief The QXmlReader class provides an interface for XML readers (i.e.
2486 parsers).
2487
2488 \inmodule QtCore5Compat
2489 \ingroup xml-tools
2490
2491 This abstract class provides an interface for all of Qt's XML
2492 readers. Currently there is only one implementation of a reader
2493 included in Qt's XML module: QXmlSimpleReader. In future releases
2494 there might be more readers with different properties available
2495 (e.g. a validating parser).
2496
2497 The design of the XML classes follows the
2498 \l {http://www.saxproject.org/}{SAX2 Java interface}, with
2499 the names adapted to fit Qt naming conventions. It should be very
2500 easy for anybody who has worked with SAX2 to get started with the
2501 Qt XML classes.
2502
2503 All readers use the class QXmlInputSource to read the input
2504 document. Since you are normally interested in particular content
2505 in the XML document, the reader reports the content through
2506 special handler classes (QXmlDTDHandler, QXmlDeclHandler,
2507 QXmlContentHandler, QXmlEntityResolver, QXmlErrorHandler and
2508 QXmlLexicalHandler), which you must subclass, if you want to
2509 process the contents.
2510
2511 Since the handler classes only describe interfaces you must
2512 implement all the functions. We provide the QXmlDefaultHandler
2513 class to make this easier: it implements a default behavior (do
2514 nothing) for all functions, so you can subclass it and just
2515 implement the functions you are interested in.
2516
2517 Features and properties of the reader can be set with setFeature()
2518 and setProperty() respectively. You can set the reader to use your
2519 own subclasses with setEntityResolver(), setDTDHandler(),
2520 setContentHandler(), setErrorHandler(), setLexicalHandler() and
2521 setDeclHandler(). The parse itself is started with a call to
2522 parse().
2523
2524 Note that this class is now deprecated, please use QXmlStreamReader or
2525 QDomDocument for reading XML files.
2526
2527 \sa QXmlSimpleReader
2528*/
2529
2530/*!
2531 \fn QXmlReader::~QXmlReader()
2532
2533 Destroys the reader.
2534*/
2535
2536/*!
2537 \fn bool QXmlReader::feature(const QString& name, bool *ok) const
2538
2539 If the reader has the feature called \a name, the feature's value
2540 is returned. If no such feature exists the return value is
2541 undefined.
2542
2543 If \a ok is not \nullptr: \c{*}\a{ok} is set to true if the
2544 reader has the feature called \a name; otherwise \c{*}\a{ok} is
2545 set to false.
2546
2547 \sa setFeature(), hasFeature()
2548*/
2549
2550/*!
2551 \fn void QXmlReader::setFeature(const QString& name, bool value)
2552
2553 Sets the feature called \a name to the given \a value. If the
2554 reader doesn't have the feature nothing happens.
2555
2556 \sa feature(), hasFeature()
2557*/
2558
2559/*!
2560 \fn bool QXmlReader::hasFeature(const QString& name) const
2561
2562 Returns \c true if the reader has the feature called \a name;
2563 otherwise returns \c false.
2564
2565 \sa feature(), setFeature()
2566*/
2567
2568/*!
2569 \fn void* QXmlReader::property(const QString& name, bool *ok) const
2570
2571 If the reader has the property \a name, this function returns the
2572 value of the property; otherwise the return value is undefined.
2573
2574 If \a ok is not \nullptr: if the reader has the \a name property
2575 \c{*}\a{ok} is set to true; otherwise \c{*}\a{ok} is set to false.
2576
2577 \sa setProperty(), hasProperty()
2578*/
2579
2580/*!
2581 \fn void QXmlReader::setProperty(const QString& name, void* value)
2582
2583 Sets the property \a name to \a value. If the reader doesn't have
2584 the property nothing happens.
2585
2586 \sa property(), hasProperty()
2587*/
2588
2589/*!
2590 \fn bool QXmlReader::hasProperty(const QString& name) const
2591
2592 Returns \c true if the reader has the property \a name; otherwise
2593 returns \c false.
2594
2595 \sa property(), setProperty()
2596*/
2597
2598/*!
2599 \fn void QXmlReader::setEntityResolver(QXmlEntityResolver* handler)
2600
2601 Sets the entity resolver to \a handler.
2602
2603 \sa entityResolver()
2604*/
2605
2606/*!
2607 \fn QXmlEntityResolver *QXmlReader::entityResolver() const
2608
2609 Returns the entity resolver or \nullptr if none was set.
2610
2611 \sa setEntityResolver()
2612*/
2613
2614/*!
2615 \fn void QXmlReader::setDTDHandler(QXmlDTDHandler* handler)
2616
2617 Sets the DTD handler to \a handler.
2618
2619 \sa DTDHandler()
2620*/
2621
2622/*!
2623 \fn QXmlDTDHandler *QXmlReader::DTDHandler() const
2624
2625 Returns the DTD handler or \nullptr if none was set.
2626
2627 \sa setDTDHandler()
2628*/
2629
2630/*!
2631 \fn void QXmlReader::setContentHandler(QXmlContentHandler* handler)
2632
2633 Sets the content handler to \a handler.
2634
2635 \sa contentHandler()
2636*/
2637
2638/*!
2639 \fn QXmlContentHandler *QXmlReader::contentHandler() const
2640
2641 Returns the content handler or \nullptr if none was set.
2642
2643 \sa setContentHandler()
2644*/
2645
2646/*!
2647 \fn void QXmlReader::setErrorHandler(QXmlErrorHandler* handler)
2648
2649 Sets the error handler to \a handler. Clears the error handler if
2650 \a handler is 0.
2651
2652 \sa errorHandler()
2653*/
2654
2655/*!
2656 \fn QXmlErrorHandler *QXmlReader::errorHandler() const
2657
2658 Returns the error handler or \nullptr if none is set.
2659
2660 \sa setErrorHandler()
2661*/
2662
2663/*!
2664 \fn void QXmlReader::setLexicalHandler(QXmlLexicalHandler* handler)
2665
2666 Sets the lexical handler to \a handler.
2667
2668 \sa lexicalHandler()
2669*/
2670
2671/*!
2672 \fn QXmlLexicalHandler *QXmlReader::lexicalHandler() const
2673
2674 Returns the lexical handler or \nullptr if none was set.
2675
2676 \sa setLexicalHandler()
2677*/
2678
2679/*!
2680 \fn void QXmlReader::setDeclHandler(QXmlDeclHandler* handler)
2681
2682 Sets the declaration handler to \a handler.
2683
2684 \sa declHandler()
2685*/
2686
2687/*!
2688 \fn QXmlDeclHandler *QXmlReader::declHandler() const
2689
2690 Returns the declaration handler or \nullptr if none was set.
2691
2692 \sa setDeclHandler()
2693*/
2694
2695/*!
2696 \fn bool QXmlReader::parse(const QXmlInputSource &input)
2697
2698 \obsolete
2699
2700 Parses the given \a input.
2701*/
2702
2703/*!
2704 \fn bool QXmlReader::parse(const QXmlInputSource *input)
2705
2706 Reads an XML document from \a input and parses it. Returns \c true if
2707 the parsing was successful; otherwise returns \c false.
2708*/
2709
2710/*!
2711 \class QXmlSimpleReader
2712 \nonreentrant
2713 \brief The QXmlSimpleReader class provides an implementation of a
2714 simple XML parser.
2715
2716 \inmodule QtCore5Compat
2717 \ingroup xml-tools
2718
2719 This XML reader is suitable for a wide range of applications. It
2720 is able to parse well-formed XML and can report the namespaces of
2721 elements to a content handler; however, it does not parse any
2722 external entities. For historical reasons, Attribute Value
2723 Normalization and End-of-Line Handling as described in the XML 1.0
2724 specification is not performed.
2725
2726 The easiest pattern of use for this class is to create a reader
2727 instance, define an input source, specify the handlers to be used
2728 by the reader, and parse the data.
2729
2730 For example, we could use a QFile to supply the input. Here, we
2731 create a reader, and define an input source to be used by the
2732 reader:
2733
2734 \snippet simpleparse/main.cpp 0
2735
2736 A handler lets us perform actions when the reader encounters
2737 certain types of content, or if errors in the input are found. The
2738 reader must be told which handler to use for each type of
2739 event. For many common applications, we can create a custom
2740 handler by subclassing QXmlDefaultHandler, and use this to handle
2741 both error and content events:
2742
2743 \snippet simpleparse/main.cpp 1
2744
2745 If you don't set at least the content and error handlers, the
2746 parser will fall back on its default behavior---and will do
2747 nothing.
2748
2749 The most convenient way to handle the input is to read it in a
2750 single pass using the parse() function with an argument that
2751 specifies the input source:
2752
2753 \snippet simpleparse/main.cpp 2
2754
2755 If you can't parse the entire input in one go (for example, it is
2756 huge, or is being delivered over a network connection), data can
2757 be fed to the parser in pieces. This is achieved by telling
2758 parse() to work incrementally, and making subsequent calls to the
2759 parseContinue() function, until all the data has been processed.
2760
2761 A common way to perform incremental parsing is to connect the \c
2762 readyRead() signal of a \l{QNetworkReply} {network reply} a slot,
2763 and handle the incoming data there. See QNetworkAccessManager.
2764
2765 Aspects of the parsing behavior can be adapted using setFeature()
2766 and setProperty().
2767
2768 \snippet code/src_xml_sax_qxml.cpp 0
2769
2770 QXmlSimpleReader is not reentrant. If you want to use the class
2771 in threaded code, lock the code using QXmlSimpleReader with a
2772 locking mechanism, such as a QMutex.
2773
2774 Note that this class is now deprecated, please use QXmlStreamReader or
2775 QDomDocument for reading XML files.
2776*/
2777
2778static inline bool is_S(QChar ch)
2779{
2780 ushort uc = ch.unicode();
2781 return (uc == ' ' || uc == '\t' || uc == '\n' || uc == '\r');
2782}
2783
2784enum NameChar { NameBeginning, NameNotBeginning, NotName };
2785
2786static const char Begi = (char)NameBeginning;
2787static const char NtBg = (char)NameNotBeginning;
2788static const char NotN = (char)NotName;
2789
2790static const char nameCharTable[128] =
2791{
2792// 0x00
2793 NotN, NotN, NotN, NotN, NotN, NotN, NotN, NotN,
2794 NotN, NotN, NotN, NotN, NotN, NotN, NotN, NotN,
2795// 0x10
2796 NotN, NotN, NotN, NotN, NotN, NotN, NotN, NotN,
2797 NotN, NotN, NotN, NotN, NotN, NotN, NotN, NotN,
2798// 0x20 (0x2D is '-', 0x2E is '.')
2799 NotN, NotN, NotN, NotN, NotN, NotN, NotN, NotN,
2800 NotN, NotN, NotN, NotN, NotN, NtBg, NtBg, NotN,
2801// 0x30 (0x30..0x39 are '0'..'9', 0x3A is ':')
2802 NtBg, NtBg, NtBg, NtBg, NtBg, NtBg, NtBg, NtBg,
2803 NtBg, NtBg, Begi, NotN, NotN, NotN, NotN, NotN,
2804// 0x40 (0x41..0x5A are 'A'..'Z')
2805 NotN, Begi, Begi, Begi, Begi, Begi, Begi, Begi,
2806 Begi, Begi, Begi, Begi, Begi, Begi, Begi, Begi,
2807// 0x50 (0x5F is '_')
2808 Begi, Begi, Begi, Begi, Begi, Begi, Begi, Begi,
2809 Begi, Begi, Begi, NotN, NotN, NotN, NotN, Begi,
2810// 0x60 (0x61..0x7A are 'a'..'z')
2811 NotN, Begi, Begi, Begi, Begi, Begi, Begi, Begi,
2812 Begi, Begi, Begi, Begi, Begi, Begi, Begi, Begi,
2813// 0x70
2814 Begi, Begi, Begi, Begi, Begi, Begi, Begi, Begi,
2815 Begi, Begi, Begi, NotN, NotN, NotN, NotN, NotN
2816};
2817
2818static inline NameChar fastDetermineNameChar(QChar ch)
2819{
2820 ushort uc = ch.unicode();
2821 if (!(uc & ~0x7f)) // uc < 128
2822 return (NameChar)nameCharTable[uc];
2823
2824 QChar::Category cat = ch.category();
2825 // ### some these categories might be slightly wrong
2826 if ((cat >= QChar::Letter_Uppercase && cat <= QChar::Letter_Other)
2827 || cat == QChar::Number_Letter)
2828 return NameBeginning;
2829 if ((cat >= QChar::Number_DecimalDigit && cat <= QChar::Number_Other)
2830 || (cat >= QChar::Mark_NonSpacing && cat <= QChar::Mark_Enclosing))
2831 return NameNotBeginning;
2832 return NotName;
2833}
2834
2835static NameChar determineNameChar(QChar ch)
2836{
2837 return fastDetermineNameChar(ch);
2838}
2839
2840/*!
2841 Constructs a simple XML reader.
2842
2843*/
2844QXmlSimpleReader::QXmlSimpleReader()
2845 : d_ptr(new QXmlSimpleReaderPrivate(this))
2846{
2847}
2848
2849/*!
2850 Destroys the simple XML reader.
2851*/
2852QXmlSimpleReader::~QXmlSimpleReader()
2853{
2854}
2855
2856/*!
2857 \reimp
2858*/
2859bool QXmlSimpleReader::feature(const QString& name, bool *ok) const
2860{
2861 const QXmlSimpleReaderPrivate *d = d_func();
2862
2863 if (ok)
2864 *ok = true;
2865 if (name == QLatin1String("http://xml.org/sax/features/namespaces")) {
2866 return d->useNamespaces;
2867 } else if (name == QLatin1String("http://xml.org/sax/features/namespace-prefixes")) {
2868 return d->useNamespacePrefixes;
2869 } else if (name == QLatin1String("http://trolltech.com/xml/features/report-whitespace-only-CharData") // For compat with Qt 4
2870 || name == QLatin1String("http://qt-project.org/xml/features/report-whitespace-only-CharData")) {
2871 return d->reportWhitespaceCharData;
2872 } else if (name == QLatin1String("http://trolltech.com/xml/features/report-start-end-entity") // For compat with Qt 4
2873 || name == QLatin1String("http://qt-project.org/xml/features/report-start-end-entity")) {
2874 return d->reportEntities;
2875 } else {
2876 qWarning("Unknown feature %s", name.toLatin1().data());
2877 if (ok)
2878 *ok = false;
2879 }
2880 return false;
2881}
2882
2883/*!
2884 Turns on the feature \a name if \a enable is true; otherwise turns it off.
2885
2886 The \a name parameter must be one of the following strings:
2887 \table
2888 \header \li Feature \li Default \li Notes
2889 \row \li \e http://xml.org/sax/features/namespaces
2890 \li true
2891 \li If enabled, namespaces are reported to the content handler.
2892 \row \li \e http://xml.org/sax/features/namespace-prefixes
2893 \li false
2894 \li If enabled, the original prefixed names
2895 and attributes used for namespace declarations are
2896 reported.
2897 \row \li \e http://qt-project.org/xml/features/report-whitespace-only-CharData
2898 \li true
2899 \li If enabled, CharData that consist of
2900 only whitespace characters are reported
2901 using QXmlContentHandler::characters(). If disabled, whitespace is silently
2902 discarded.
2903 \row \li \e http://qt-project.org/xml/features/report-start-end-entity
2904 \li false
2905 \li If enabled, the parser reports
2906 QXmlContentHandler::startEntity() and
2907 QXmlContentHandler::endEntity() events, so character data
2908 might be reported in chunks.
2909 If disabled, the parser does not report these events, but
2910 silently substitutes the entities, and reports the character
2911 data in one chunk.
2912 \endtable
2913
2914 \sa feature(), hasFeature()
2915*/
2916void QXmlSimpleReader::setFeature(const QString& name, bool enable)
2917{
2918 Q_D(QXmlSimpleReader);
2919 if (name == QLatin1String("http://xml.org/sax/features/namespaces")) {
2920 d->useNamespaces = enable;
2921 } else if (name == QLatin1String("http://xml.org/sax/features/namespace-prefixes")) {
2922 d->useNamespacePrefixes = enable;
2923 } else if (name == QLatin1String("http://trolltech.com/xml/features/report-whitespace-only-CharData") // For compat with Qt 4
2924 || name == QLatin1String("http://qt-project.org/xml/features/report-whitespace-only-CharData")) {
2925 d->reportWhitespaceCharData = enable;
2926 } else if (name == QLatin1String("http://trolltech.com/xml/features/report-start-end-entity") // For compat with Qt 4
2927 || name == QLatin1String("http://qt-project.org/xml/features/report-start-end-entity")) {
2928 d->reportEntities = enable;
2929 } else {
2930 qWarning("Unknown feature %s", name.toLatin1().data());
2931 }
2932}
2933
2934/*! \reimp
2935*/
2936bool QXmlSimpleReader::hasFeature(const QString& name) const
2937{
2938 if (name == QLatin1String("http://xml.org/sax/features/namespaces")
2939 || name == QLatin1String("http://xml.org/sax/features/namespace-prefixes")
2940 || name == QLatin1String("http://trolltech.com/xml/features/report-whitespace-only-CharData") // For compat with Qt 4
2941 || name == QLatin1String("http://qt-project.org/xml/features/report-whitespace-only-CharData")
2942 || name == QLatin1String("http://trolltech.com/xml/features/report-start-end-entity") // For compat with Qt 4
2943 || name == QLatin1String("http://qt-project.org/xml/features/report-start-end-entity")) {
2944 return true;
2945 } else {
2946 return false;
2947 }
2948}
2949
2950/*! \reimp
2951*/
2952void* QXmlSimpleReader::property(const QString&, bool *ok) const
2953{
2954 if (ok)
2955 *ok = false;
2956 return nullptr;
2957}
2958
2959/*! \reimp
2960*/
2961void QXmlSimpleReader::setProperty(const QString&, void*)
2962{
2963}
2964
2965/*!
2966 \reimp
2967*/
2968bool QXmlSimpleReader::hasProperty(const QString&) const
2969{
2970 return false;
2971}
2972
2973/*!
2974 \reimp
2975*/
2976void QXmlSimpleReader::setEntityResolver(QXmlEntityResolver* handler)
2977{
2978 Q_D(QXmlSimpleReader);
2979 d->entityRes = handler;
2980}
2981
2982/*!
2983 \reimp
2984*/
2985QXmlEntityResolver* QXmlSimpleReader::entityResolver() const
2986{
2987 const QXmlSimpleReaderPrivate *d = d_func();
2988 return d->entityRes;
2989}
2990
2991/*!
2992 \reimp
2993*/
2994void QXmlSimpleReader::setDTDHandler(QXmlDTDHandler* handler)
2995{
2996 Q_D(QXmlSimpleReader);
2997 d->dtdHnd = handler;
2998}
2999
3000/*!
3001 \reimp
3002*/
3003QXmlDTDHandler* QXmlSimpleReader::DTDHandler() const
3004{
3005 const QXmlSimpleReaderPrivate *d = d_func();
3006 return d->dtdHnd;
3007}
3008
3009/*!
3010 \reimp
3011*/
3012void QXmlSimpleReader::setContentHandler(QXmlContentHandler* handler)
3013{
3014 Q_D(QXmlSimpleReader);
3015 d->contentHnd = handler;
3016}
3017
3018/*!
3019 \reimp
3020*/
3021QXmlContentHandler* QXmlSimpleReader::contentHandler() const
3022{
3023 const QXmlSimpleReaderPrivate *d = d_func();
3024 return d->contentHnd;
3025}
3026
3027/*!
3028 \reimp
3029*/
3030void QXmlSimpleReader::setErrorHandler(QXmlErrorHandler* handler)
3031{
3032 Q_D(QXmlSimpleReader);
3033 d->errorHnd = handler;
3034}
3035
3036/*!
3037 \reimp
3038*/
3039QXmlErrorHandler* QXmlSimpleReader::errorHandler() const
3040{
3041 const QXmlSimpleReaderPrivate *d = d_func();
3042 return d->errorHnd;
3043}
3044
3045/*!
3046 \reimp
3047*/
3048void QXmlSimpleReader::setLexicalHandler(QXmlLexicalHandler* handler)
3049{
3050 Q_D(QXmlSimpleReader);
3051 d->lexicalHnd = handler;
3052}
3053
3054/*!
3055 \reimp
3056*/
3057QXmlLexicalHandler* QXmlSimpleReader::lexicalHandler() const
3058{
3059 const QXmlSimpleReaderPrivate *d = d_func();
3060 return d->lexicalHnd;
3061}
3062
3063/*!
3064 \reimp
3065*/
3066void QXmlSimpleReader::setDeclHandler(QXmlDeclHandler* handler)
3067{
3068 Q_D(QXmlSimpleReader);
3069 d->declHnd = handler;
3070}
3071
3072/*!
3073 \reimp
3074*/
3075QXmlDeclHandler* QXmlSimpleReader::declHandler() const
3076{
3077 const QXmlSimpleReaderPrivate *d = d_func();
3078 return d->declHnd;
3079}
3080
3081/*!
3082 \reimp
3083*/
3084bool QXmlSimpleReader::parse(const QXmlInputSource& input)
3085{
3086 return parse(&input, false);
3087}
3088
3089/*!
3090 Reads an XML document from \a input and parses it in one pass (non-incrementally).
3091 Returns \c true if the parsing was successful; otherwise returns \c false.
3092*/
3093bool QXmlSimpleReader::parse(const QXmlInputSource* input)
3094{
3095 return parse(input, false);
3096}
3097
3098/*!
3099 Reads an XML document from \a input and parses it. Returns \c true
3100 if the parsing is completed successfully; otherwise returns \c false,
3101 indicating that an error occurred.
3102
3103 If \a incremental is false, this function will return false if the XML
3104 file is not read completely. The parsing cannot be continued in this
3105 case.
3106
3107 If \a incremental is true, the parser does not return false if
3108 it reaches the end of the \a input before reaching the end
3109 of the XML file. Instead, it stores the state of the parser so that
3110 parsing can be continued later when more data is available.
3111 In such a case, you can use the function parseContinue() to
3112 continue with parsing. This class stores a pointer to the input
3113 source \a input and the parseContinue() function tries to read from
3114 that input source. Therefore, you should not delete the input
3115 source \a input until you no longer need to call parseContinue().
3116
3117 If this function is called with \a incremental set to true
3118 while an incremental parse is in progress, a new parsing
3119 session will be started, and the previous session will be lost.
3120
3121 \sa parseContinue(), QTcpSocket
3122*/
3123bool QXmlSimpleReader::parse(const QXmlInputSource *input, bool incremental)
3124{
3125 Q_D(QXmlSimpleReader);
3126
3127 d->literalEntitySizes.clear();
3128 d->referencesToOtherEntities.clear();
3129 d->expandedSizes.clear();
3130
3131 if (incremental) {
3132 d->initIncrementalParsing();
3133 } else {
3134 delete d->parseStack;
3135 d->parseStack = nullptr;
3136 }
3137 d->init(input);
3138
3139 // call the handler
3140 if (d->contentHnd) {
3141 d->contentHnd->setDocumentLocator(d->locator.data());
3142 if (!d->contentHnd->startDocument()) {
3143 d->reportParseError(d->contentHnd->errorString());
3144 clear(d->tags);
3145 return false;
3146 }
3147 }
3148 d->skipped_entity_in_content = false;
3149 return d->parseBeginOrContinue(0, incremental);
3150}
3151
3152/*!
3153 Continues incremental parsing, taking input from the
3154 QXmlInputSource that was specified with the most recent
3155 call to parse(). To use this function, you \e must have called
3156 parse() with the incremental argument set to true.
3157
3158 Returns \c false if a parsing error occurs; otherwise returns \c true,
3159 even if the end of the XML file has not been reached. You can
3160 continue parsing at a later stage by calling this function again
3161 when there is more data available to parse.
3162
3163 Calling this function when there is no data available in the input
3164 source indicates to the reader that the end of the XML file has
3165 been reached. If the input supplied up to this point was
3166 not well-formed then a parsing error occurs, and false is returned.
3167 If the input supplied was well-formed, true is returned.
3168 It is important to end the input in this way because it allows you
3169 to reuse the reader to parse other XML files.
3170
3171 Calling this function after the end of file has been reached, but
3172 without available data will cause false to be returned whether the
3173 previous input was well-formed or not.
3174
3175 \sa parse(), QXmlInputSource::data(), QXmlInputSource::next()
3176*/
3177bool QXmlSimpleReader::parseContinue()
3178{
3179 Q_D(QXmlSimpleReader);
3180 if (d->parseStack == nullptr || d->parseStack->isEmpty())
3181 return false;
3182 d->initData();
3183 int state = d->parseStack->pop().state;
3184 return d->parseBeginOrContinue(state, true);
3185}
3186
3187/*
3188 Common part of parse() and parseContinue()
3189*/
3190bool QXmlSimpleReaderPrivate::parseBeginOrContinue(int state, bool incremental)
3191{
3192 bool atEndOrig = atEnd();
3193
3194 if (state==0) {
3195 if (!parseProlog()) {
3196 if (incremental && error.isNull()) {
3197 pushParseState(nullptr, 0);
3198 return true;
3199 } else {
3200 clear(tags);
3201 return false;
3202 }
3203 }
3204 state = 1;
3205 }
3206 if (state==1) {
3207 if (!parseElement()) {
3208 if (incremental && error.isNull()) {
3209 pushParseState(nullptr, 1);
3210 return true;
3211 } else {
3212 clear(tags);
3213 return false;
3214 }
3215 }
3216 state = 2;
3217 }
3218 // parse Misc*
3219 while (!atEnd()) {
3220 if (!parseMisc()) {
3221 if (incremental && error.isNull()) {
3222 pushParseState(nullptr, 2);
3223 return true;
3224 } else {
3225 clear(tags);
3226 return false;
3227 }
3228 }
3229 }
3230 if (!atEndOrig && incremental) {
3231 // we parsed something at all, so be prepared to come back later
3232 pushParseState(nullptr, 2);
3233 return true;
3234 }
3235 // is stack empty?
3236 if (!tags.empty() && !error.isNull()) {
3237 reportParseError(QLatin1String(XMLERR_UNEXPECTEDEOF));
3238 clear(tags);
3239 return false;
3240 }
3241 // call the handler
3242 if (contentHnd) {
3243 delete parseStack;
3244 parseStack = nullptr;
3245 if (!contentHnd->endDocument()) {
3246 reportParseError(contentHnd->errorString());
3247 return false;
3248 }
3249 }
3250 return true;
3251}
3252
3253//
3254// The following private parse functions have another semantics for the return
3255// value: They return true iff parsing has finished successfully (i.e. the end
3256// of the XML file must be reached!). If one of these functions return false,
3257// there is only an error when d->error.isNULL() is also false.
3258//
3259
3260/*
3261 For the incremental parsing, it is very important that the parse...()
3262 functions have a certain structure. Since it might be hard to understand how
3263 they work, here is a description of the layout of these functions:
3264
3265 bool QXmlSimpleReader::parse...()
3266 {
3267(1) const signed char Init = 0;
3268 ...
3269
3270(2) const signed char Inp... = 0;
3271 ...
3272
3273(3) static const signed char table[3][2] = {
3274 ...
3275 };
3276 signed char state;
3277 signed char input;
3278
3279(4) if (d->parseStack == nullptr || d->parseStack->isEmpty()) {
3280(4a) ...
3281 } else {
3282(4b) ...
3283 }
3284
3285 for (; ;) {
3286(5) switch (state) {
3287 ...
3288 }
3289
3290(6)
3291(6a) if (atEnd()) {
3292 unexpectedEof(&QXmlSimpleReader::parseNmtoken, state);
3293 return false;
3294 }
3295(6b) if (determineNameChar(c) != NotName) {
3296 ...
3297 }
3298(7) state = table[state][input];
3299
3300(8) switch (state) {
3301 ...
3302 }
3303 }
3304 }
3305
3306 Explanation:
3307 ad 1: constants for the states (used in the transition table)
3308 ad 2: constants for the input (used in the transition table)
3309 ad 3: the transition table for the state machine
3310 ad 4: test if we are in a parseContinue() step
3311 a) if no, do initializations
3312 b) if yes, restore the state and call parse functions recursively
3313 ad 5: Do some actions according to the state; from the logical execution
3314 order, this code belongs after 8 (see there for an explanation)
3315 ad 6: Check the character that is at the actual "cursor" position:
3316 a) If we reached the EOF, report either error or push the state (in the
3317 case of incremental parsing).
3318 b) Otherwise, set the input character constant for the transition
3319 table.
3320 ad 7: Get the new state according to the input that was read.
3321 ad 8: Do some actions according to the state. The last line in every case
3322 statement reads new data (i.e. it move the cursor). This can also be
3323 done by calling another parse...() function. If you need processing for
3324 this state after that, you have to put it into the switch statement 5.
3325 This ensures that you have a well defined re-entry point, when you ran
3326 out of data.
3327*/
3328
3329/*
3330 Parses the prolog [22].
3331*/
3332
3333bool QXmlSimpleReaderPrivate::parseProlog()
3334{
3335 const signed char Init = 0;
3336 const signed char EatWS = 1; // eat white spaces
3337 const signed char Lt = 2; // '<' read
3338 const signed char Em = 3; // '!' read
3339 const signed char DocType = 4; // read doctype
3340 const signed char Comment = 5; // read comment
3341 const signed char CommentR = 6; // same as Comment, but already reported
3342 const signed char PInstr = 7; // read PI
3343 const signed char PInstrR = 8; // same as PInstr, but already reported
3344 const signed char Done = 9;
3345
3346 const signed char InpWs = 0;
3347 const signed char InpLt = 1; // <
3348 const signed char InpQm = 2; // ?
3349 const signed char InpEm = 3; // !
3350 const signed char InpD = 4; // D
3351 const signed char InpDash = 5; // -
3352 const signed char InpUnknown = 6;
3353
3354 static const signed char table[9][7] = {
3355 /* InpWs InpLt InpQm InpEm InpD InpDash InpUnknown */
3356 { EatWS, Lt, -1, -1, -1, -1, -1 }, // Init
3357 { -1, Lt, -1, -1, -1, -1, -1 }, // EatWS
3358 { -1, -1, PInstr,Em, Done, -1, Done }, // Lt
3359 { -1, -1, -1, -1, DocType, Comment, -1 }, // Em
3360 { EatWS, Lt, -1, -1, -1, -1, -1 }, // DocType
3361 { EatWS, Lt, -1, -1, -1, -1, -1 }, // Comment
3362 { EatWS, Lt, -1, -1, -1, -1, -1 }, // CommentR
3363 { EatWS, Lt, -1, -1, -1, -1, -1 }, // PInstr
3364 { EatWS, Lt, -1, -1, -1, -1, -1 } // PInstrR
3365 };
3366 signed char state;
3367 signed char input;
3368
3369 if (parseStack == nullptr|| parseStack->isEmpty()) {
3370 xmldecl_possible = true;
3371 doctype_read = false;
3372 state = Init;
3373 } else {
3374 state = parseStack->pop().state;
3375#if defined(QT_QXML_DEBUG)
3376 qDebug("QXmlSimpleReader: parseProlog (cont) in state %d", state);
3377#endif
3378 if (!parseStack->isEmpty()) {
3379 ParseFunction function = parseStack->top().function;
3380 if (function == &QXmlSimpleReaderPrivate::eat_ws) {
3381 parseStack->pop();
3382#if defined(QT_QXML_DEBUG)
3383 qDebug("QXmlSimpleReader: eat_ws (cont)");
3384#endif
3385 }
3386 if (!(this->*function)()) {
3387 parseFailed(&QXmlSimpleReaderPrivate::parseProlog, state);
3388 return false;
3389 }
3390 }
3391 }
3392
3393 for (;;) {
3394 switch (state) {
3395 case DocType:
3396 if (doctype_read) {
3397 reportParseError(QLatin1String(XMLERR_MORETHANONEDOCTYPE));
3398 return false;
3399 } else {
3400 doctype_read = false;
3401 }
3402 break;
3403 case Comment:
3404 if (lexicalHnd) {
3405 if (!lexicalHnd->comment(string())) {
3406 reportParseError(lexicalHnd->errorString());
3407 return false;
3408 }
3409 }
3410 state = CommentR;
3411 break;
3412 case PInstr:
3413 // call the handler
3414 if (contentHnd) {
3415 if (xmldecl_possible && !xmlVersion.isEmpty()) {
3416 QString value(QLatin1String("version='"));
3417 value += xmlVersion;
3418 value += QLatin1Char('\'');
3419 if (!encoding.isEmpty()) {
3420 value += QLatin1String(" encoding='");
3421 value += encoding;
3422 value += QLatin1Char('\'');
3423 }
3424 if (standalone == QXmlSimpleReaderPrivate::Yes) {
3425 value += QLatin1String(" standalone='yes'");
3426 } else if (standalone == QXmlSimpleReaderPrivate::No) {
3427 value += QLatin1String(" standalone='no'");
3428 }
3429 if (!contentHnd->processingInstruction(QLatin1String("xml"), value)) {
3430 reportParseError(contentHnd->errorString());
3431 return false;
3432 }
3433 } else {
3434 if (!contentHnd->processingInstruction(name(), string())) {
3435 reportParseError(contentHnd->errorString());
3436 return false;
3437 }
3438 }
3439 }
3440 // XML declaration only on first position possible
3441 xmldecl_possible = false;
3442 state = PInstrR;
3443 break;
3444 case Done:
3445 return true;
3446 case -1:
3447 reportParseError(QLatin1String(XMLERR_ERRORPARSINGELEMENT));
3448 return false;
3449 }
3450
3451 if (atEnd()) {
3452 unexpectedEof(&QXmlSimpleReaderPrivate::parseProlog, state);
3453 return false;
3454 }
3455 if (is_S(c)) {
3456 input = InpWs;
3457 } else if (c == QLatin1Char('<')) {
3458 input = InpLt;
3459 } else if (c == QLatin1Char('?')) {
3460 input = InpQm;
3461 } else if (c == QLatin1Char('!')) {
3462 input = InpEm;
3463 } else if (c == QLatin1Char('D')) {
3464 input = InpD;
3465 } else if (c == QLatin1Char('-')) {
3466 input = InpDash;
3467 } else {
3468 input = InpUnknown;
3469 }
3470 state = table[state][input];
3471
3472 switch (state) {
3473 case EatWS:
3474 // XML declaration only on first position possible
3475 xmldecl_possible = false;
3476 if (!eat_ws()) {
3477 parseFailed(&QXmlSimpleReaderPrivate::parseProlog, state);
3478 return false;
3479 }
3480 break;
3481 case Lt:
3482 next();
3483 break;
3484 case Em:
3485 // XML declaration only on first position possible
3486 xmldecl_possible = false;
3487 next();
3488 break;
3489 case DocType:
3490 if (!parseDoctype()) {
3491 parseFailed(&QXmlSimpleReaderPrivate::parseProlog, state);
3492 return false;
3493 }
3494 break;
3495 case Comment:
3496 case CommentR:
3497 if (!parseComment()) {
3498 parseFailed(&QXmlSimpleReaderPrivate::parseProlog, state);
3499 return false;
3500 }
3501 break;
3502 case PInstr:
3503 case PInstrR:
3504 parsePI_xmldecl = xmldecl_possible;
3505 if (!parsePI()) {
3506 parseFailed(&QXmlSimpleReaderPrivate::parseProlog, state);
3507 return false;
3508 }
3509 break;
3510 }
3511 }
3512 return false;
3513}
3514
3515/*
3516 Parse an element [39].
3517
3518 Precondition: the opening '<' is already read.
3519*/
3520bool QXmlSimpleReaderPrivate::parseElement()
3521{
3522 const int Init = 0;
3523 const int ReadName = 1;
3524 const int Ws1 = 2;
3525 const int STagEnd = 3;
3526 const int STagEnd2 = 4;
3527 const int ETagBegin = 5;
3528 const int ETagBegin2 = 6;
3529 const int Ws2 = 7;
3530 const int EmptyTag = 8;
3531 const int Attrib = 9;
3532 const int AttribPro = 10; // like Attrib, but processAttribute was already called
3533 const int Ws3 = 11;
3534 const int Done = 12;
3535
3536 const int InpWs = 0; // whitespace
3537 const int InpNameBe = 1; // NameBeginning
3538 const int InpGt = 2; // >
3539 const int InpSlash = 3; // /
3540 const int InpUnknown = 4;
3541
3542 static const int table[12][5] = {
3543 /* InpWs InpNameBe InpGt InpSlash InpUnknown */
3544 { -1, ReadName, -1, -1, -1 }, // Init
3545 { Ws1, Attrib, STagEnd, EmptyTag, -1 }, // ReadName
3546 { -1, Attrib, STagEnd, EmptyTag, -1 }, // Ws1
3547 { STagEnd2, STagEnd2, STagEnd2, STagEnd2, STagEnd2 }, // STagEnd
3548 { -1, -1, -1, ETagBegin, -1 }, // STagEnd2
3549 { -1, ETagBegin2, -1, -1, -1 }, // ETagBegin
3550 { Ws2, -1, Done, -1, -1 }, // ETagBegin2
3551 { -1, -1, Done, -1, -1 }, // Ws2
3552 { -1, -1, Done, -1, -1 }, // EmptyTag
3553 { Ws3, Attrib, STagEnd, EmptyTag, -1 }, // Attrib
3554 { Ws3, Attrib, STagEnd, EmptyTag, -1 }, // AttribPro
3555 { -1, Attrib, STagEnd, EmptyTag, -1 } // Ws3
3556 };
3557 int state;
3558 int input;
3559
3560 if (parseStack == nullptr|| parseStack->isEmpty()) {
3561 state = Init;
3562 } else {
3563 state = parseStack->pop().state;
3564#if defined(QT_QXML_DEBUG)
3565 qDebug("QXmlSimpleReader: parseElement (cont) in state %d", state);
3566#endif
3567 if (!parseStack->isEmpty()) {
3568 ParseFunction function = parseStack->top().function;
3569 if (function == &QXmlSimpleReaderPrivate::eat_ws) {
3570 parseStack->pop();
3571#if defined(QT_QXML_DEBUG)
3572 qDebug("QXmlSimpleReader: eat_ws (cont)");
3573#endif
3574 }
3575 if (!(this->*function)()) {
3576 parseFailed(&QXmlSimpleReaderPrivate::parseElement, state);
3577 return false;
3578 }
3579 }
3580 }
3581
3582 for (;;) {
3583 switch (state) {
3584 case ReadName:
3585 // store it on the stack
3586 tags.push(name());
3587 // empty the attributes
3588 attList.clear();
3589 if (useNamespaces)
3590 namespaceSupport.pushContext();
3591 break;
3592 case ETagBegin2:
3593 if (!processElementETagBegin2())
3594 return false;
3595 break;
3596 case Attrib:
3597 if (!processElementAttribute())
3598 return false;
3599 state = AttribPro;
3600 break;
3601 case Done:
3602 return true;
3603 case -1:
3604 reportParseError(QLatin1String(XMLERR_ERRORPARSINGELEMENT));
3605 return false;
3606 }
3607
3608 if (atEnd()) {
3609 unexpectedEof(&QXmlSimpleReaderPrivate::parseElement, state);
3610 return false;
3611 }
3612 if (fastDetermineNameChar(c) == NameBeginning) {
3613 input = InpNameBe;
3614 } else if (c == QLatin1Char('>')) {
3615 input = InpGt;
3616 } else if (is_S(c)) {
3617 input = InpWs;
3618 } else if (c == QLatin1Char('/')) {
3619 input = InpSlash;
3620 } else {
3621 input = InpUnknown;
3622 }
3623 state = table[state][input];
3624
3625 switch (state) {
3626 case ReadName:
3627 parseName_useRef = false;
3628 if (!parseName()) {
3629 parseFailed(&QXmlSimpleReaderPrivate::parseElement, state);
3630 return false;
3631 }
3632 break;
3633 case Ws1:
3634 case Ws2:
3635 case Ws3:
3636 if (!eat_ws()) {
3637 parseFailed(&QXmlSimpleReaderPrivate::parseElement, state);
3638 return false;
3639 }
3640 break;
3641 case STagEnd:
3642 // call the handler
3643 if (contentHnd) {
3644 if (useNamespaces) {
3645 QString uri, lname;
3646 namespaceSupport.processName(tags.top(), false, uri, lname);
3647 if (!contentHnd->startElement(uri, lname, tags.top(), attList)) {
3648 reportParseError(contentHnd->errorString());
3649 return false;
3650 }
3651 } else {
3652 if (!contentHnd->startElement(QString(), QString(), tags.top(), attList)) {
3653 reportParseError(contentHnd->errorString());
3654 return false;
3655 }
3656 }
3657 }
3658 next();
3659 break;
3660 case STagEnd2:
3661 if (!parseContent()) {
3662 parseFailed(&QXmlSimpleReaderPrivate::parseElement, state);
3663 return false;
3664 }
3665 break;
3666 case ETagBegin:
3667 next();
3668 break;
3669 case ETagBegin2:
3670 // get the name of the tag
3671 parseName_useRef = false;
3672 if (!parseName()) {
3673 parseFailed(&QXmlSimpleReaderPrivate::parseElement, state);
3674 return false;
3675 }
3676 break;
3677 case EmptyTag:
3678 if (tags.empty()) {
3679 reportParseError(QLatin1String(XMLERR_TAGMISMATCH));
3680 return false;
3681 }
3682 if (!processElementEmptyTag())
3683 return false;
3684 next();
3685 break;
3686 case Attrib:
3687 case AttribPro:
3688 // get name and value of attribute
3689 if (!parseAttribute()) {
3690 parseFailed(&QXmlSimpleReaderPrivate::parseElement, state);
3691 return false;
3692 }
3693 break;
3694 case Done:
3695 next();
3696 break;
3697 }
3698 }
3699 return false;
3700}
3701
3702/*
3703 Helper to break down the size of the code in the case statement.
3704 Return false on error, otherwise true.
3705*/
3706bool QXmlSimpleReaderPrivate::processElementEmptyTag()
3707{
3708 QString uri, lname;
3709 // pop the stack and call the handler
3710 if (contentHnd) {
3711 if (useNamespaces) {
3712 // report startElement first...
3713 namespaceSupport.processName(tags.top(), false, uri, lname);
3714 if (!contentHnd->startElement(uri, lname, tags.top(), attList)) {
3715 reportParseError(contentHnd->errorString());
3716 return false;
3717 }
3718 // ... followed by endElement...
3719 const bool endElementReturnedFalse = !contentHnd->endElement(uri, lname, tags.top());
3720 tags.pop();
3721 if (endElementReturnedFalse) {
3722 reportParseError(contentHnd->errorString());
3723 return false;
3724 }
3725 // ... followed by endPrefixMapping
3726 QStringList prefixesBefore, prefixesAfter;
3727 if (contentHnd) {
3728 prefixesBefore = namespaceSupport.prefixes();
3729 }
3730 namespaceSupport.popContext();
3731 // call the handler for prefix mapping
3732 prefixesAfter = namespaceSupport.prefixes();
3733 for (QStringList::Iterator it = prefixesBefore.begin(); it != prefixesBefore.end(); ++it) {
3734 if (!prefixesAfter.contains(*it)) {
3735 if (!contentHnd->endPrefixMapping(*it)) {
3736 reportParseError(contentHnd->errorString());
3737 return false;
3738 }
3739 }
3740 }
3741 } else {
3742 // report startElement first...
3743 if (!contentHnd->startElement(QString(), QString(), tags.top(), attList)) {
3744 reportParseError(contentHnd->errorString());
3745 return false;
3746 }
3747 // ... followed by endElement
3748 const bool endElementReturnedFalse = !contentHnd->endElement(QString(), QString(), tags.top());
3749 tags.pop();
3750 if (endElementReturnedFalse) {
3751 reportParseError(contentHnd->errorString());
3752 return false;
3753 }
3754 }
3755 } else {
3756 tags.pop();
3757 namespaceSupport.popContext();
3758 }
3759 return true;
3760}
3761/*
3762 Helper to break down the size of the code in the case statement.
3763 Return false on error, otherwise true.
3764*/
3765bool QXmlSimpleReaderPrivate::processElementETagBegin2()
3766{
3767 const QString &name = QXmlSimpleReaderPrivate::name();
3768
3769 // pop the stack and compare it with the name
3770 const bool nameIsTagsTop = tags.top() == name;
3771 tags.pop();
3772 if (!nameIsTagsTop) {
3773 reportParseError(QLatin1String(XMLERR_TAGMISMATCH));
3774 return false;
3775 }
3776 // call the handler
3777 if (contentHnd) {
3778 QString uri, lname;
3779
3780 if (useNamespaces)
3781 namespaceSupport.processName(name, false, uri, lname);
3782 if (!contentHnd->endElement(uri, lname, name)) {
3783 reportParseError(contentHnd->errorString());
3784 return false;
3785 }
3786 }
3787 if (useNamespaces) {
3788 NamespaceMap prefixesBefore, prefixesAfter;
3789 if (contentHnd)
3790 prefixesBefore = namespaceSupport.d->ns;
3791
3792 namespaceSupport.popContext();
3793 // call the handler for prefix mapping
3794 if (contentHnd) {
3795 prefixesAfter = namespaceSupport.d->ns;
3796 if (prefixesBefore.size() != prefixesAfter.size()) {
3797 for (NamespaceMap::const_iterator it = prefixesBefore.constBegin(); it != prefixesBefore.constEnd(); ++it) {
3798 if (!it.key().isEmpty() && !prefixesAfter.contains(it.key())) {
3799 if (!contentHnd->endPrefixMapping(it.key())) {
3800 reportParseError(contentHnd->errorString());
3801 return false;
3802 }
3803 }
3804 }
3805 }
3806 }
3807 }
3808 return true;
3809}
3810/*
3811 Helper to break down the size of the code in the case statement.
3812 Return false on error, otherwise true.
3813*/
3814bool QXmlSimpleReaderPrivate::processElementAttribute()
3815{
3816 QString uri, lname, prefix;
3817 const QString &name = QXmlSimpleReaderPrivate::name();
3818 const QString &string = QXmlSimpleReaderPrivate::string();
3819
3820 // add the attribute to the list
3821 if (useNamespaces) {
3822 // is it a namespace declaration?
3823 namespaceSupport.splitName(name, prefix, lname);
3824 if (prefix == QLatin1String("xmlns")) {
3825 // namespace declaration
3826 namespaceSupport.setPrefix(lname, string);
3827 if (useNamespacePrefixes) {
3828 // according to http://www.w3.org/2000/xmlns/, the "prefix"
3829 // xmlns maps to the namespace name
3830 // http://www.w3.org/2000/xmlns/
3831 attList.append(name, QLatin1String("http://www.w3.org/2000/xmlns/"), lname, string);
3832 }
3833 // call the handler for prefix mapping
3834 if (contentHnd) {
3835 if (!contentHnd->startPrefixMapping(lname, string)) {
3836 reportParseError(contentHnd->errorString());
3837 return false;
3838 }
3839 }
3840 } else {
3841 // no namespace delcaration
3842 namespaceSupport.processName(name, true, uri, lname);
3843 attList.append(name, uri, lname, string);
3844 }
3845 } else {
3846 // no namespace support
3847 attList.append(name, uri, lname, string);
3848 }
3849 return true;
3850}
3851
3852/*
3853 Parse a content [43].
3854
3855 A content is only used between tags. If a end tag is found the < is already
3856 read and the head stand on the '/' of the end tag '</name>'.
3857*/
3858bool QXmlSimpleReaderPrivate::parseContent()
3859{
3860 const signed char Init = 0;
3861 const signed char ChD = 1; // CharData
3862 const signed char ChD1 = 2; // CharData help state
3863 const signed char ChD2 = 3; // CharData help state
3864 const signed char Ref = 4; // Reference
3865 const signed char Lt = 5; // '<' read
3866 const signed char PInstr = 6; // PI
3867 const signed char PInstrR = 7; // same as PInstr, but already reported
3868 const signed char Elem = 8; // Element
3869 const signed char Em = 9; // '!' read
3870 const signed char Com = 10; // Comment
3871 const signed char ComR = 11; // same as Com, but already reported
3872 const signed char CDS = 12; // CDSect
3873 const signed char CDS1 = 13; // read a CDSect
3874 const signed char CDS2 = 14; // read a CDSect (help state)
3875 const signed char CDS3 = 15; // read a CDSect (help state)
3876 const signed char Done = 16; // finished reading content
3877
3878 const signed char InpLt = 0; // <
3879 const signed char InpGt = 1; // >
3880 const signed char InpSlash = 2; // /
3881 const signed char InpQMark = 3; // ?
3882 const signed char InpEMark = 4; // !
3883 const signed char InpAmp = 5; // &
3884 const signed char InpDash = 6; // -
3885 const signed char InpOpenB = 7; // [
3886 const signed char InpCloseB = 8; //]
3887 const signed char InpUnknown = 9;
3888
3889 static const signed char mapCLT2FSMChar[] = {
3890 InpUnknown, // white space
3891 InpUnknown, // %
3892 InpAmp, // &
3893 InpGt, // >
3894 InpLt, // <
3895 InpSlash, // /
3896 InpQMark, // ?
3897 InpEMark, // !
3898 InpDash, // -
3899 InpCloseB, //]
3900 InpOpenB, // [
3901 InpUnknown, // =
3902 InpUnknown, // "
3903 InpUnknown, // '
3904 InpUnknown // unknown
3905 };
3906
3907 static const signed char table[16][10] = {
3908 /* InpLt InpGt InpSlash InpQMark InpEMark InpAmp InpDash InpOpenB InpCloseB InpUnknown */
3909 { Lt, ChD, ChD, ChD, ChD, Ref, ChD, ChD, ChD1, ChD }, // Init
3910 { Lt, ChD, ChD, ChD, ChD, Ref, ChD, ChD, ChD1, ChD }, // ChD
3911 { Lt, ChD, ChD, ChD, ChD, Ref, ChD, ChD, ChD2, ChD }, // ChD1
3912 { Lt, -1, ChD, ChD, ChD, Ref, ChD, ChD, ChD2, ChD }, // ChD2
3913 { Lt, ChD, ChD, ChD, ChD, Ref, ChD, ChD, ChD, ChD }, // Ref (same as Init)
3914 { -1, -1, Done, PInstr, Em, -1, -1, -1, -1, Elem }, // Lt
3915 { Lt, ChD, ChD, ChD, ChD, Ref, ChD, ChD, ChD, ChD }, // PInstr (same as Init)
3916 { Lt, ChD, ChD, ChD, ChD, Ref, ChD, ChD, ChD, ChD }, // PInstrR
3917 { Lt, ChD, ChD, ChD, ChD, Ref, ChD, ChD, ChD, ChD }, // Elem (same as Init)
3918 { -1, -1, -1, -1, -1, -1, Com, CDS, -1, -1 }, // Em
3919 { Lt, ChD, ChD, ChD, ChD, Ref, ChD, ChD, ChD, ChD }, // Com (same as Init)
3920 { Lt, ChD, ChD, ChD, ChD, Ref, ChD, ChD, ChD, ChD }, // ComR
3921 { CDS1, CDS1, CDS1, CDS1, CDS1, CDS1, CDS1, CDS1, CDS2, CDS1 }, // CDS
3922 { CDS1, CDS1, CDS1, CDS1, CDS1, CDS1, CDS1, CDS1, CDS2, CDS1 }, // CDS1
3923 { CDS1, CDS1, CDS1, CDS1, CDS1, CDS1, CDS1, CDS1, CDS3, CDS1 }, // CDS2
3924 { CDS1, Init, CDS1, CDS1, CDS1, CDS1, CDS1, CDS1, CDS3, CDS1 } // CDS3
3925 };
3926 signed char state;
3927 signed char input;
3928
3929 if (parseStack == nullptr || parseStack->isEmpty()) {
3930 contentCharDataRead = false;
3931 state = Init;
3932 } else {
3933 state = parseStack->pop().state;
3934#if defined(QT_QXML_DEBUG)
3935 qDebug("QXmlSimpleReader: parseContent (cont) in state %d", state);
3936#endif
3937 if (!parseStack->isEmpty()) {
3938 ParseFunction function = parseStack->top().function;
3939 if (function == &QXmlSimpleReaderPrivate::eat_ws) {
3940 parseStack->pop();
3941#if defined(QT_QXML_DEBUG)
3942 qDebug("QXmlSimpleReader: eat_ws (cont)");
3943#endif
3944 }
3945 if (!(this->*function)()) {
3946 parseFailed(&QXmlSimpleReaderPrivate::parseContent, state);
3947 return false;
3948 }
3949 }
3950 }
3951
3952 for (;;) {
3953 switch (state) {
3954 case Ref:
3955 if (!contentCharDataRead)
3956 contentCharDataRead = parseReference_charDataRead;
3957 break;
3958 case PInstr:
3959 if (contentHnd) {
3960 if (!contentHnd->processingInstruction(name(),string())) {
3961 reportParseError(contentHnd->errorString());
3962 return false;
3963 }
3964 }
3965 state = PInstrR;
3966 break;
3967 case Com:
3968 if (lexicalHnd) {
3969 if (!lexicalHnd->comment(string())) {
3970 reportParseError(lexicalHnd->errorString());
3971 return false;
3972 }
3973 }
3974 state = ComR;
3975 break;
3976 case CDS:
3977 stringClear();
3978 break;
3979 case CDS2:
3980 if (!atEnd() && c != QLatin1Char(']'))
3981 stringAddC(QLatin1Char(']'));
3982 break;
3983 case CDS3:
3984 // test if this skipping was legal
3985 if (!atEnd()) {
3986 if (c == QLatin1Char('>')) {
3987 // the end of the CDSect
3988 if (lexicalHnd) {
3989 if (!lexicalHnd->startCDATA()) {
3990 reportParseError(lexicalHnd->errorString());
3991 return false;
3992 }
3993 }
3994 if (contentHnd) {
3995 if (!contentHnd->characters(string())) {
3996 reportParseError(contentHnd->errorString());
3997 return false;
3998 }
3999 }
4000 if (lexicalHnd) {
4001 if (!lexicalHnd->endCDATA()) {
4002 reportParseError(lexicalHnd->errorString());
4003 return false;
4004 }
4005 }
4006 } else if (c == QLatin1Char(']')) {
4007 // three or more ']'
4008 stringAddC(QLatin1Char(']'));
4009 } else {
4010 // after ']]' comes another character
4011 stringAddC(QLatin1Char(']'));
4012 stringAddC(QLatin1Char(']'));
4013 }
4014 }
4015 break;
4016 case Done:
4017 // call the handler for CharData
4018 if (contentHnd) {
4019 if (contentCharDataRead) {
4020 if (reportWhitespaceCharData || !string().simplified().isEmpty()) {
4021 if (!contentHnd->characters(string())) {
4022 reportParseError(contentHnd->errorString());
4023 return false;
4024 }
4025 }
4026 }
4027 }
4028 // Done
4029 return true;
4030 case -1:
4031 // Error
4032 reportParseError(QLatin1String(XMLERR_ERRORPARSINGCONTENT));
4033 return false;
4034 }
4035
4036 // get input (use lookup-table instead of nested ifs for performance
4037 // reasons)
4038 if (atEnd()) {
4039 unexpectedEof(&QXmlSimpleReaderPrivate::parseContent, state);
4040 return false;
4041 }
4042 if (c.row()) {
4043 input = InpUnknown;
4044 } else {
4045 input = mapCLT2FSMChar[charLookupTable[c.cell()]];
4046 }
4047 state = table[state][input];
4048
4049 switch (state) {
4050 case Init:
4051 // skip the ending '>' of a CDATASection
4052 next();
4053 break;
4054 case ChD:
4055 // on first call: clear string
4056 if (!contentCharDataRead) {
4057 contentCharDataRead = true;
4058 stringClear();
4059 }
4060 stringAddC();
4061 if (reportEntities) {
4062 if (!reportEndEntities())
4063 return false;
4064 }
4065 next();
4066 break;
4067 case ChD1:
4068 // on first call: clear string
4069 if (!contentCharDataRead) {
4070 contentCharDataRead = true;
4071 stringClear();
4072 }
4073 stringAddC();
4074 if (reportEntities) {
4075 if (!reportEndEntities())
4076 return false;
4077 }
4078 next();
4079 break;
4080 case ChD2:
4081 stringAddC();
4082 if (reportEntities) {
4083 if (!reportEndEntities())
4084 return false;
4085 }
4086 next();
4087 break;
4088 case Ref:
4089 if (!contentCharDataRead) {
4090 // reference may be CharData; so clear string to be safe
4091 stringClear();
4092 parseReference_context = InContent;
4093 if (!parseReference()) {
4094 parseFailed(&QXmlSimpleReaderPrivate::parseContent, state);
4095 return false;
4096 }
4097 } else {
4098 if (reportEntities) {
4099 // report character data in chunks
4100 if (contentHnd) {
4101 if (reportWhitespaceCharData || !string().simplified().isEmpty()) {
4102 if (!contentHnd->characters(string())) {
4103 reportParseError(contentHnd->errorString());
4104 return false;
4105 }
4106 }
4107 }
4108 stringClear();
4109 }
4110 parseReference_context = InContent;
4111 if (!parseReference()) {
4112 parseFailed(&QXmlSimpleReaderPrivate::parseContent, state);
4113 return false;
4114 }
4115 }
4116 break;
4117 case Lt:
4118 // call the handler for CharData
4119 if (contentHnd) {
4120 if (contentCharDataRead) {
4121 if (reportWhitespaceCharData || !string().simplified().isEmpty()) {
4122 if (!contentHnd->characters(string())) {
4123 reportParseError(contentHnd->errorString());
4124 return false;
4125 }
4126 }
4127 }
4128 }
4129 contentCharDataRead = false;
4130 next();
4131 break;
4132 case PInstr:
4133 case PInstrR:
4134 parsePI_xmldecl = false;
4135 if (!parsePI()) {
4136 parseFailed(&QXmlSimpleReaderPrivate::parseContent, state);
4137 return false;
4138 }
4139 break;
4140 case Elem:
4141 if (!parseElement()) {
4142 parseFailed(&QXmlSimpleReaderPrivate::parseContent, state);
4143 return false;
4144 }
4145 break;
4146 case Em:
4147 next();
4148 break;
4149 case Com:
4150 case ComR:
4151 if (!parseComment()) {
4152 parseFailed(&QXmlSimpleReaderPrivate::parseContent, state);
4153 return false;
4154 }
4155 break;
4156 case CDS:
4157 parseString_s = QLatin1String("[CDATA[");
4158 if (!parseString()) {
4159 parseFailed(&QXmlSimpleReaderPrivate::parseContent, state);
4160 return false;
4161 }
4162 break;
4163 case CDS1:
4164 stringAddC();
4165 next();
4166 break;
4167 case CDS2:
4168 // skip ']'
4169 next();
4170 break;
4171 case CDS3:
4172 // skip ']'...
4173 next();
4174 break;
4175 }
4176 }
4177 return false;
4178}
4179
4180bool QXmlSimpleReaderPrivate::reportEndEntities()
4181{
4182 int count = (int)xmlRefStack.count();
4183 while (count != 0 && xmlRefStack.top().isEmpty()) {
4184 if (contentHnd) {
4185 if (reportWhitespaceCharData || !string().simplified().isEmpty()) {
4186 if (!contentHnd->characters(string())) {
4187 reportParseError(contentHnd->errorString());
4188 return false;
4189 }
4190 }
4191 }
4192 stringClear();
4193 if (lexicalHnd) {
4194 if (!lexicalHnd->endEntity(xmlRefStack.top().name)) {
4195 reportParseError(lexicalHnd->errorString());
4196 return false;
4197 }
4198 }
4199 xmlRefStack.pop_back();
4200 count--;
4201 }
4202 return true;
4203}
4204
4205/*
4206 Parse Misc [27].
4207*/
4208bool QXmlSimpleReaderPrivate::parseMisc()
4209{
4210 const signed char Init = 0;
4211 const signed char Lt = 1; // '<' was read
4212 const signed char Comment = 2; // read comment
4213 const signed char eatWS = 3; // eat whitespaces
4214 const signed char PInstr = 4; // read PI
4215 const signed char Comment2 = 5; // read comment
4216
4217 const signed char InpWs = 0; // S
4218 const signed char InpLt = 1; // <
4219 const signed char InpQm = 2; // ?
4220 const signed char InpEm = 3; // !
4221 const signed char InpUnknown = 4;
4222
4223 static const signed char table[3][5] = {
4224 /* InpWs InpLt InpQm InpEm InpUnknown */
4225 { eatWS, Lt, -1, -1, -1 }, // Init
4226 { -1, -1, PInstr,Comment, -1 }, // Lt
4227 { -1, -1, -1, -1, Comment2 } // Comment
4228 };
4229 signed char state;
4230 signed char input;
4231
4232 if (parseStack == nullptr || parseStack->isEmpty()) {
4233 state = Init;
4234 } else {
4235 state = parseStack->pop().state;
4236#if defined(QT_QXML_DEBUG)
4237 qDebug("QXmlSimpleReader: parseMisc (cont) in state %d", state);
4238#endif
4239 if (!parseStack->isEmpty()) {
4240 ParseFunction function = parseStack->top().function;
4241 if (function == &QXmlSimpleReaderPrivate::eat_ws) {
4242 parseStack->pop();
4243#if defined(QT_QXML_DEBUG)
4244 qDebug("QXmlSimpleReader: eat_ws (cont)");
4245#endif
4246 }
4247 if (!(this->*function)()) {
4248 parseFailed(&QXmlSimpleReaderPrivate::parseMisc, state);
4249 return false;
4250 }
4251 }
4252 }
4253
4254 for (;;) {
4255 switch (state) {
4256 case eatWS:
4257 return true;
4258 case PInstr:
4259 if (contentHnd) {
4260 if (!contentHnd->processingInstruction(name(),string())) {
4261 reportParseError(contentHnd->errorString());
4262 return false;
4263 }
4264 }
4265 return true;
4266 case Comment2:
4267 if (lexicalHnd) {
4268 if (!lexicalHnd->comment(string())) {
4269 reportParseError(lexicalHnd->errorString());
4270 return false;
4271 }
4272 }
4273 return true;
4274 case -1:
4275 // Error
4276 reportParseError(QLatin1String(XMLERR_UNEXPECTEDCHARACTER));
4277 return false;
4278 }
4279
4280 if (atEnd()) {
4281 unexpectedEof(&QXmlSimpleReaderPrivate::parseMisc, state);
4282 return false;
4283 }
4284 if (is_S(c)) {
4285 input = InpWs;
4286 } else if (c == QLatin1Char('<')) {
4287 input = InpLt;
4288 } else if (c == QLatin1Char('?')) {
4289 input = InpQm;
4290 } else if (c == QLatin1Char('!')) {
4291 input = InpEm;
4292 } else {
4293 input = InpUnknown;
4294 }
4295 state = table[state][input];
4296
4297 switch (state) {
4298 case eatWS:
4299 if (!eat_ws()) {
4300 parseFailed(&QXmlSimpleReaderPrivate::parseMisc, state);
4301 return false;
4302 }
4303 break;
4304 case Lt:
4305 next();
4306 break;
4307 case PInstr:
4308 parsePI_xmldecl = false;
4309 if (!parsePI()) {
4310 parseFailed(&QXmlSimpleReaderPrivate::parseMisc, state);
4311 return false;
4312 }
4313 break;
4314 case Comment:
4315 next();
4316 break;
4317 case Comment2:
4318 if (!parseComment()) {
4319 parseFailed(&QXmlSimpleReaderPrivate::parseMisc, state);
4320 return false;
4321 }
4322 break;
4323 }
4324 }
4325 return false;
4326}
4327
4328/*
4329 Parse a processing instruction [16].
4330
4331 If xmldec is true, it tries to parse a PI or a XML declaration [23].
4332
4333 Precondition: the beginning '<' of the PI is already read and the head stand
4334 on the '?' of '<?'.
4335
4336 If this funktion was successful, the head-position is on the first
4337 character after the PI.
4338*/
4339bool QXmlSimpleReaderPrivate::parsePI()
4340{
4341 const signed char Init = 0;
4342 const signed char QmI = 1; // ? was read
4343 const signed char Name = 2; // read Name
4344 const signed char XMLDecl = 3; // read XMLDecl
4345 const signed char Ws1 = 4; // eat ws after "xml" of XMLDecl
4346 const signed char PInstr = 5; // read PI
4347 const signed char Ws2 = 6; // eat ws after Name of PI
4348 const signed char Version = 7; // read versionInfo
4349 const signed char Ws3 = 8; // eat ws after versionInfo
4350 const signed char EorSD = 9; // read EDecl or SDDecl
4351 const signed char Ws4 = 10; // eat ws after EDecl or SDDecl
4352 const signed char SD = 11; // read SDDecl
4353 const signed char Ws5 = 12; // eat ws after SDDecl
4354 const signed char ADone = 13; // almost done
4355 const signed char Char = 14; // Char was read
4356 const signed char Qm = 15; // Qm was read
4357 const signed char Done = 16; // finished reading content
4358
4359 const signed char InpWs = 0; // whitespace
4360 const signed char InpNameBe = 1; // NameBeginning
4361 const signed char InpGt = 2; // >
4362 const signed char InpQm = 3; // ?
4363 const signed char InpUnknown = 4;
4364
4365 static const signed char table[16][5] = {
4366 /* InpWs, InpNameBe InpGt InpQm InpUnknown */
4367 { -1, -1, -1, QmI, -1 }, // Init
4368 { -1, Name, -1, -1, -1 }, // QmI
4369 { -1, -1, -1, -1, -1 }, // Name (this state is left not through input)
4370 { Ws1, -1, -1, -1, -1 }, // XMLDecl
4371 { -1, Version, -1, -1, -1 }, // Ws1
4372 { Ws2, -1, -1, Qm, -1 }, // PInstr
4373 { Char, Char, Char, Qm, Char }, // Ws2
4374 { Ws3, -1, -1, ADone, -1 }, // Version
4375 { -1, EorSD, -1, ADone, -1 }, // Ws3
4376 { Ws4, -1, -1, ADone, -1 }, // EorSD
4377 { -1, SD, -1, ADone, -1 }, // Ws4
4378 { Ws5, -1, -1, ADone, -1 }, // SD
4379 { -1, -1, -1, ADone, -1 }, // Ws5
4380 { -1, -1, Done, -1, -1 }, // ADone
4381 { Char, Char, Char, Qm, Char }, // Char
4382 { Char, Char, Done, Qm, Char }, // Qm
4383 };
4384 signed char state;
4385 signed char input;
4386
4387 if (parseStack == nullptr || parseStack->isEmpty()) {
4388 state = Init;
4389 } else {
4390 state = parseStack->pop().state;
4391#if defined(QT_QXML_DEBUG)
4392 qDebug("QXmlSimpleReader: parsePI (cont) in state %d", state);
4393#endif
4394 if (!parseStack->isEmpty()) {
4395 ParseFunction function = parseStack->top().function;
4396 if (function == &QXmlSimpleReaderPrivate::eat_ws) {
4397 parseStack->pop();
4398#if defined(QT_QXML_DEBUG)
4399 qDebug("QXmlSimpleReader: eat_ws (cont)");
4400#endif
4401 }
4402 if (!(this->*function)()) {
4403 parseFailed(&QXmlSimpleReaderPrivate::parsePI, state);
4404 return false;
4405 }
4406 }
4407 }
4408
4409 for (;;) {
4410 switch (state) {
4411 case Name:
4412 // test what name was read and determine the next state
4413 // (not very beautiful, I admit)
4414 if (name().toLower() == QLatin1String("xml")) {
4415 if (parsePI_xmldecl && name() == QLatin1String("xml")) {
4416 state = XMLDecl;
4417 } else {
4418 reportParseError(QLatin1String(XMLERR_INVALIDNAMEFORPI));
4419 return false;
4420 }
4421 } else {
4422 state = PInstr;
4423 stringClear();
4424 }
4425 break;
4426 case Version:
4427 // get version (syntax like an attribute)
4428 if (name() != QLatin1String("version")) {
4429 reportParseError(QLatin1String(XMLERR_VERSIONEXPECTED));
4430 return false;
4431 }
4432 xmlVersion = string();
4433 break;
4434 case EorSD:
4435 // get the EDecl or SDDecl (syntax like an attribute)
4436 if (name() == QLatin1String("standalone")) {
4437 if (string()== QLatin1String("yes")) {
4438 standalone = QXmlSimpleReaderPrivate::Yes;
4439 } else if (string() == QLatin1String("no")) {
4440 standalone = QXmlSimpleReaderPrivate::No;
4441 } else {
4442 reportParseError(QLatin1String(XMLERR_WRONGVALUEFORSDECL));
4443 return false;
4444 }
4445 } else if (name() == QLatin1String("encoding")) {
4446 encoding = string();
4447 } else {
4448 reportParseError(QLatin1String(XMLERR_EDECLORSDDECLEXPECTED));
4449 return false;
4450 }
4451 break;
4452 case SD:
4453 if (name() != QLatin1String("standalone")) {
4454 reportParseError(QLatin1String(XMLERR_SDDECLEXPECTED));
4455 return false;
4456 }
4457 if (string() == QLatin1String("yes")) {
4458 standalone = QXmlSimpleReaderPrivate::Yes;
4459 } else if (string() == QLatin1String("no")) {
4460 standalone = QXmlSimpleReaderPrivate::No;
4461 } else {
4462 reportParseError(QLatin1String(XMLERR_WRONGVALUEFORSDECL));
4463 return false;
4464 }
4465 break;
4466 case Qm:
4467 // test if the skipping was legal
4468 if (!atEnd() && c != QLatin1Char('>'))
4469 stringAddC(QLatin1Char('?'));
4470 break;
4471 case Done:
4472 return true;
4473 case -1:
4474 // Error
4475 reportParseError(QLatin1String(XMLERR_UNEXPECTEDCHARACTER));
4476 return false;
4477 }
4478
4479 if (atEnd()) {
4480 unexpectedEof(&QXmlSimpleReaderPrivate::parsePI, state);
4481 return false;
4482 }
4483 if (is_S(c)) {
4484 input = InpWs;
4485 } else if (determineNameChar(c) == NameBeginning) {
4486 input = InpNameBe;
4487 } else if (c == QLatin1Char('>')) {
4488 input = InpGt;
4489 } else if (c == QLatin1Char('?')) {
4490 input = InpQm;
4491 } else {
4492 input = InpUnknown;
4493 }
4494 state = table[state][input];
4495
4496 switch (state) {
4497 case QmI:
4498 next();
4499 break;
4500 case Name:
4501 parseName_useRef = false;
4502 if (!parseName()) {
4503 parseFailed(&QXmlSimpleReaderPrivate::parsePI, state);
4504 return false;
4505 }
4506 break;
4507 case Ws1:
4508 case Ws2:
4509 case Ws3:
4510 case Ws4:
4511 case Ws5:
4512 if (!eat_ws()) {
4513 parseFailed(&QXmlSimpleReaderPrivate::parsePI, state);
4514 return false;
4515 }
4516 break;
4517 case Version:
4518 if (!parseAttribute()) {
4519 parseFailed(&QXmlSimpleReaderPrivate::parsePI, state);
4520 return false;
4521 }
4522 break;
4523 case EorSD:
4524 if (!parseAttribute()) {
4525 parseFailed(&QXmlSimpleReaderPrivate::parsePI, state);
4526 return false;
4527 }
4528 break;
4529 case SD:
4530 // get the SDDecl (syntax like an attribute)
4531 if (standalone != QXmlSimpleReaderPrivate::Unknown) {
4532 // already parsed the standalone declaration
4533 reportParseError(QLatin1String(XMLERR_UNEXPECTEDCHARACTER));
4534 return false;
4535 }
4536 if (!parseAttribute()) {
4537