1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the QtXml module of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
43 #include "qtextcodec.h"
51 #ifdef Q_CC_BOR // borland 6 finds bogus warnings when building this file in uic3
55 //#define QT_QXML_DEBUG
57 // Error strings for the XML reader
58 #define XMLERR_OK QT_TRANSLATE_NOOP("QXml", "no error occurred")
59 #define XMLERR_ERRORBYCONSUMER QT_TRANSLATE_NOOP("QXml", "error triggered by consumer")
60 #define XMLERR_UNEXPECTEDEOF QT_TRANSLATE_NOOP("QXml", "unexpected end of file")
61 #define XMLERR_MORETHANONEDOCTYPE QT_TRANSLATE_NOOP("QXml", "more than one document type definition")
62 #define XMLERR_ERRORPARSINGELEMENT QT_TRANSLATE_NOOP("QXml", "error occurred while parsing element")
63 #define XMLERR_TAGMISMATCH QT_TRANSLATE_NOOP("QXml", "tag mismatch")
64 #define XMLERR_ERRORPARSINGCONTENT QT_TRANSLATE_NOOP("QXml", "error occurred while parsing content")
65 #define XMLERR_UNEXPECTEDCHARACTER QT_TRANSLATE_NOOP("QXml", "unexpected character")
66 #define XMLERR_INVALIDNAMEFORPI QT_TRANSLATE_NOOP("QXml", "invalid name for processing instruction")
67 #define XMLERR_VERSIONEXPECTED QT_TRANSLATE_NOOP("QXml", "version expected while reading the XML declaration")
68 #define XMLERR_WRONGVALUEFORSDECL QT_TRANSLATE_NOOP("QXml", "wrong value for standalone declaration")
69 #define XMLERR_EDECLORSDDECLEXPECTED QT_TRANSLATE_NOOP("QXml", "encoding declaration or standalone declaration expected while reading the XML declaration")
70 #define XMLERR_SDDECLEXPECTED QT_TRANSLATE_NOOP("QXml", "standalone declaration expected while reading the XML declaration")
71 #define XMLERR_ERRORPARSINGDOCTYPE QT_TRANSLATE_NOOP("QXml", "error occurred while parsing document type definition")
72 #define XMLERR_LETTEREXPECTED QT_TRANSLATE_NOOP("QXml", "letter is expected")
73 #define XMLERR_ERRORPARSINGCOMMENT QT_TRANSLATE_NOOP("QXml", "error occurred while parsing comment")
74 #define XMLERR_ERRORPARSINGREFERENCE QT_TRANSLATE_NOOP("QXml", "error occurred while parsing reference")
75 #define XMLERR_INTERNALGENERALENTITYINDTD QT_TRANSLATE_NOOP("QXml", "internal general entity reference not allowed in DTD")
76 #define XMLERR_EXTERNALGENERALENTITYINAV QT_TRANSLATE_NOOP("QXml", "external parsed general entity reference not allowed in attribute value")
77 #define XMLERR_EXTERNALGENERALENTITYINDTD QT_TRANSLATE_NOOP("QXml", "external parsed general entity reference not allowed in DTD")
78 #define XMLERR_UNPARSEDENTITYREFERENCE QT_TRANSLATE_NOOP("QXml", "unparsed entity reference in wrong context")
79 #define XMLERR_RECURSIVEENTITIES QT_TRANSLATE_NOOP("QXml", "recursive entities")
80 #define XMLERR_ERRORINTEXTDECL QT_TRANSLATE_NOOP("QXml", "error in the text declaration of an external entity")
84 // the constants for the lookup table
85 static const signed char cltWS = 0; // white space
86 static const signed char cltPer = 1; // %
87 static const signed char cltAmp = 2; // &
88 static const signed char cltGt = 3; // >
89 static const signed char cltLt = 4; // <
90 static const signed char cltSlash = 5; // /
91 static const signed char cltQm = 6; // ?
92 static const signed char cltEm = 7; // !
93 static const signed char cltDash = 8; // -
94 static const signed char cltCB = 9; // ]
95 static const signed char cltOB = 10; // [
96 static const signed char cltEq = 11; // =
97 static const signed char cltDq = 12; // "
98 static const signed char cltSq = 13; // '
99 static const signed char cltUnknown = 14;
101 // Hack for letting QDom know where the skipped entity occurred
102 // ### Qt5: the use of this variable means the code isn't reentrant.
103 bool qt_xml_skipped_entity_in_content;
105 // character lookup table
106 static const signed char charLookupTable[256]={
107 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x00 - 0x07
116 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x17 - 0x16
117 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x18 - 0x1F
134 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x30 - 0x37
143 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x40 - 0x47
144 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x48 - 0x4F
145 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x50 - 0x57
154 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x60 - 0x67
155 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x68 - 0x6F
156 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x70 - 0x77
157 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x78 - 0x7F
158 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x80 - 0x87
159 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x88 - 0x8F
160 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x90 - 0x97
161 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x98 - 0x9F
162 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xA0 - 0xA7
163 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xA8 - 0xAF
164 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xB0 - 0xB7
165 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xB8 - 0xBF
166 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xC0 - 0xC7
167 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xC8 - 0xCF
168 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xD0 - 0xD7
169 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xD8 - 0xDF
170 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xE0 - 0xE7
171 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xE8 - 0xEF
172 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xF0 - 0xF7
173 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown // 0xF8 - 0xFF
177 // local helper functions
181 This function strips the TextDecl [77] ("<?xml ...?>") from the string \a
182 str. The stripped version is stored in \a str. If this function finds an
183 invalid TextDecl, it returns false, otherwise true.
185 This function is used for external entities since those can include an
186 TextDecl that must be stripped before inserting the entity.
188 static bool stripTextDecl(QString& str)
190 QString textDeclStart(QLatin1String("<?xml"));
191 if (str.startsWith(textDeclStart)) {
192 QRegExp textDecl(QString::fromLatin1(
194 "(version\\s*=\\s*((['\"])[-a-zA-Z0-9_.:]+\\3))?"
196 "(encoding\\s*=\\s*((['\"])[A-Za-z][-a-zA-Z0-9_.]*\\6))?"
199 QString strTmp = str.replace(textDecl, QLatin1String(""));
200 if (strTmp.length() != str.length())
201 return false; // external entity has wrong TextDecl
208 class QXmlAttributesPrivate
212 /* \class QXmlInputSourcePrivate
215 There's a slight misdesign in this class that can
216 be worth to keep in mind: the `str' member is
217 a buffer which QXmlInputSource::next() returns from,
218 and which is populated from the input device or input
219 stream. However, when the input is a QString(the user called
220 QXmlInputSource::setData()), `str' has two roles: it's the
221 buffer, but also the source. This /seems/ to be no problem
222 because in the case of having no device or stream, the QString
225 class QXmlInputSourcePrivate
228 QIODevice *inputDevice;
229 QTextStream *inputStream;
232 const QChar *unicode;
235 bool nextReturnedEndOfData;
236 #ifndef QT_NO_TEXTCODEC
237 QTextDecoder *encMapper;
240 QByteArray encodingDeclBytes;
241 QString encodingDeclChars;
242 bool lookingForEncodingDecl;
244 class QXmlParseExceptionPrivate
247 QXmlParseExceptionPrivate()
248 : column(-1), line(-1)
251 QXmlParseExceptionPrivate(const QXmlParseExceptionPrivate &other)
252 : msg(other.msg), column(other.column), line(other.line),
253 pub(other.pub), sys(other.sys)
265 class QXmlLocatorPrivate
269 class QXmlDefaultHandlerPrivate
273 class QXmlSimpleReaderPrivate
276 ~QXmlSimpleReaderPrivate();
279 QXmlSimpleReaderPrivate(QXmlSimpleReader *reader);
280 void initIncrementalParsing();
282 // used to determine if elements are correctly nested
283 QStack<QString> tags;
285 // used by parseReference() and parsePEReference()
286 enum EntityRecognitionContext { InContent, InAttributeValue, InEntityValue, InDTD };
288 // used for entity declarations
289 struct ExternParameterEntity
291 ExternParameterEntity() {}
292 ExternParameterEntity(const QString &p, const QString &s)
293 : publicId(p), systemId(s) {}
297 Q_DUMMY_COMPARISON_OPERATOR(ExternParameterEntity)
302 ExternEntity(const QString &p, const QString &s, const QString &n)
303 : publicId(p), systemId(s), notation(n) {}
307 Q_DUMMY_COMPARISON_OPERATOR(ExternEntity)
309 QMap<QString,ExternParameterEntity> externParameterEntities;
310 QMap<QString,QString> parameterEntities;
311 QMap<QString,ExternEntity> externEntities;
312 QMap<QString,QString> entities;
314 // used for parsing of entity references
318 XmlRef(const QString &_name, const QString &_value)
319 : name(_name), value(_value), index(0) {}
320 bool isEmpty() const { return index == value.length(); }
321 QChar next() { return value.at(index++); }
326 QStack<XmlRef> xmlRefStack;
328 // used for standalone declaration
329 enum Standalone { Yes, No, Unknown };
331 QString doctype; // only used for the doctype
332 QString xmlVersion; // only used to store the version information
333 QString encoding; // only used to store the encoding
334 Standalone standalone; // used to store the value of the standalone declaration
336 QString publicId; // used by parseExternalID() to store the public ID
337 QString systemId; // used by parseExternalID() to store the system ID
339 // Since publicId/systemId is used as temporary variables by parseExternalID(), it
340 // might overwrite the PUBLIC/SYSTEM for the document we're parsing. In effect, we would
341 // possibly send off an QXmlParseException that has the PUBLIC/SYSTEM of a entity declaration
342 // instead of those of the current document.
343 // Hence we have these two variables for storing the document's data.
344 QString thisPublicId;
345 QString thisSystemId;
347 QString attDeclEName; // use by parseAttlistDecl()
348 QString attDeclAName; // use by parseAttlistDecl()
350 // flags for some features support
352 bool useNamespacePrefixes;
353 bool reportWhitespaceCharData;
356 // used to build the attribute list
357 QXmlAttributes attList;
359 // used in QXmlSimpleReader::parseContent() to decide whether character
361 bool contentCharDataRead;
364 QScopedPointer<QXmlLocator> locator;
365 QXmlNamespaceSupport namespaceSupport;
370 // arguments for parse functions (this is needed to allow incremental
372 bool parsePI_xmldecl;
373 bool parseName_useRef;
374 bool parseReference_charDataRead;
375 EntityRecognitionContext parseReference_context;
376 bool parseExternalID_allowPublicID;
377 EntityRecognitionContext parsePEReference_context;
378 QString parseString_s;
380 // for incremental parsing
382 typedef bool (QXmlSimpleReaderPrivate::*ParseFunction)();
383 ParseFunction function;
386 QStack<ParseState> *parseStack;
388 // used in parseProlog()
389 bool xmldecl_possible;
392 // used in parseDoctype()
393 bool startDTDwasReported;
395 // used in parseString()
400 QXmlContentHandler *contentHnd;
401 QXmlErrorHandler *errorHnd;
402 QXmlDTDHandler *dtdHnd;
403 QXmlEntityResolver *entityRes;
404 QXmlLexicalHandler *lexicalHnd;
405 QXmlDeclHandler *declHnd;
407 QXmlInputSource *inputSource;
409 QChar c; // the character at reading position
410 int lineNr; // number of line
411 int columnNr; // position in line
413 QChar nameArray[256]; // only used for names
414 QString nameValue; // only used for names
417 QChar refArray[256]; // only used for references
418 QString refValue; // only used for references
421 QChar stringArray[256]; // used for any other strings that are parsed
422 QString stringValue; // used for any other strings that are parsed
427 const QString &string();
429 void stringAddC(QChar);
430 inline void stringAddC() { stringAddC(c); }
431 const QString &name();
433 void nameAddC(QChar);
434 inline void nameAddC() { nameAddC(c); }
435 const QString &ref();
438 inline void refAddC() { refAddC(c); }
444 void QT_FASTCALL next();
447 void init(const QXmlInputSource* i);
450 bool entityExist(const QString&) const;
452 bool parseBeginOrContinue(int state, bool incremental);
456 bool processElementEmptyTag();
457 bool processElementETagBegin2();
458 bool processElementAttribute();
468 bool parseAttribute();
469 bool parseReference();
470 bool processReference();
472 bool parseExternalID();
473 bool parsePEReference();
474 bool parseMarkupdecl();
475 bool parseAttlistDecl();
477 bool parseAttValue();
478 bool parseElementDecl();
479 bool parseNotationDecl();
480 bool parseChoiceSeq();
481 bool parseEntityDecl();
482 bool parseEntityValue();
486 bool insertXmlRef(const QString&, const QString&, bool);
488 bool reportEndEntities();
489 void reportParseError(const QString& error);
491 typedef bool (QXmlSimpleReaderPrivate::*ParseFunction) ();
492 void unexpectedEof(ParseFunction where, int state);
493 void parseFailed(ParseFunction where, int state);
494 void pushParseState(ParseFunction function, int state);
496 Q_DECLARE_PUBLIC(QXmlSimpleReader)
497 QXmlSimpleReader *q_ptr;
499 friend class QXmlSimpleReaderLocator;
503 \class QXmlParseException
505 \brief The QXmlParseException class is used to report errors with
506 the QXmlErrorHandler interface.
511 The XML subsystem constructs an instance of this class when it
512 detects an error. You can retrieve the place where the error
513 occurred using systemId(), publicId(), lineNumber() and
514 columnNumber(), along with the error message(). The possible error
519 \o "no error occurred"
520 \o "error triggered by consumer"
521 \o "unexpected end of file"
522 \o "more than one document type definition"
523 \o "error occurred while parsing element"
525 \o "error occurred while parsing content"
526 \o "unexpected character"
527 \o "invalid name for processing instruction"
528 \o "version expected while reading the XML declaration"
529 \o "wrong value for standalone declaration"
530 \o "encoding declaration or standalone declaration expected while reading the XML declaration"
531 \o "standalone declaration expected while reading the XML declaration"
532 \o "error occurred while parsing document type definition"
533 \o "letter is expected"
534 \o "error occurred while parsing comment"
535 \o "error occurred while parsing reference"
536 \o "internal general entity reference not allowed in DTD"
537 \o "external parsed general entity reference not allowed in attribute value"
538 \o "external parsed general entity reference not allowed in DTD"
539 \o "unparsed entity reference n wrong context"
540 \o "recursive entities"
541 \o "error in the text declaration of an external entity"
544 Note that, if you want to display these error messages to your
545 application's users, they will be displayed in English unless
546 they are explicitly translated.
548 \sa QXmlErrorHandler, QXmlReader
552 Constructs a parse exception with the error string \a name for
553 column \a c and line \a l for the public identifier \a p and the
554 system identifier \a s.
557 QXmlParseException::QXmlParseException(const QString& name, int c, int l,
558 const QString& p, const QString& s)
559 : d(new QXmlParseExceptionPrivate)
569 Creates a copy of \a other.
571 QXmlParseException::QXmlParseException(const QXmlParseException& other) :
572 d(new QXmlParseExceptionPrivate(*other.d))
578 Destroys the QXmlParseException.
580 QXmlParseException::~QXmlParseException()
585 Returns the error message.
587 QString QXmlParseException::message() const
592 Returns the column number where the error occurred.
594 int QXmlParseException::columnNumber() const
599 Returns the line number where the error occurred.
601 int QXmlParseException::lineNumber() const
606 Returns the public identifier where the error occurred.
608 QString QXmlParseException::publicId() const
613 Returns the system identifier where the error occurred.
615 QString QXmlParseException::systemId() const
624 \brief The QXmlLocator class provides the XML handler classes with
625 information about the parsing position within a file.
630 The reader reports a QXmlLocator to the content handler before it
631 starts to parse the document. This is done with the
632 QXmlContentHandler::setDocumentLocator() function. The handler
633 classes can now use this locator to get the position (lineNumber()
634 and columnNumber()) that the reader has reached.
640 QXmlLocator::QXmlLocator()
647 QXmlLocator::~QXmlLocator()
652 \fn int QXmlLocator::columnNumber() const
654 Returns the column number (starting at 1) or -1 if there is no
655 column number available.
659 \fn int QXmlLocator::lineNumber() const
661 Returns the line number (starting at 1) or -1 if there is no line
665 class QXmlSimpleReaderLocator : public QXmlLocator
668 QXmlSimpleReaderLocator(QXmlSimpleReader* parent)
672 ~QXmlSimpleReaderLocator()
676 int columnNumber() const
678 return (reader->d_ptr->columnNr == -1 ? -1 : reader->d_ptr->columnNr + 1);
680 int lineNumber() const
682 return (reader->d_ptr->lineNr == -1 ? -1 : reader->d_ptr->lineNr + 1);
684 // QString getPublicId()
685 // QString getSystemId()
688 QXmlSimpleReader *reader;
691 /*********************************************
693 * QXmlNamespaceSupport
695 *********************************************/
697 typedef QMap<QString, QString> NamespaceMap;
699 class QXmlNamespaceSupportPrivate
702 QXmlNamespaceSupportPrivate()
704 ns.insert(QLatin1String("xml"), QLatin1String("http://www.w3.org/XML/1998/namespace")); // the XML namespace
707 ~QXmlNamespaceSupportPrivate()
711 QStack<NamespaceMap> nsStack;
716 \class QXmlNamespaceSupport
719 \brief The QXmlNamespaceSupport class is a helper class for XML
720 readers which want to include namespace support.
725 You can set the prefix for the current namespace with setPrefix(),
726 and get the list of current prefixes (or those for a given URI)
727 with prefixes(). The namespace URI is available from uri(). Use
728 pushContext() to start a new namespace context, and popContext()
729 to return to the previous namespace context. Use splitName() or
730 processName() to split a name into its prefix and local name.
732 \sa {Namespace Support via Features}
736 Constructs a QXmlNamespaceSupport.
738 QXmlNamespaceSupport::QXmlNamespaceSupport()
740 d = new QXmlNamespaceSupportPrivate;
744 Destroys a QXmlNamespaceSupport.
746 QXmlNamespaceSupport::~QXmlNamespaceSupport()
752 This function declares a prefix \a pre in the current namespace
753 context to be the namespace URI \a uri. The prefix remains in
754 force until this context is popped, unless it is shadowed in a
757 Note that there is an asymmetry in this library. prefix() does not
758 return the default "" prefix, even if you have declared one; to
759 check for a default prefix, you must look it up explicitly using
760 uri(). This asymmetry exists to make it easier to look up prefixes
761 for attribute names, where the default prefix is not allowed.
763 void QXmlNamespaceSupport::setPrefix(const QString& pre, const QString& uri)
766 d->ns.insert(QLatin1String(""), uri);
768 d->ns.insert(pre, uri);
773 Returns one of the prefixes mapped to the namespace URI \a uri.
775 If more than one prefix is currently mapped to the same URI, this
776 function makes an arbitrary selection; if you want all of the
777 prefixes, use prefixes() instead.
779 Note: to check for a default prefix, use the uri() function with
782 QString QXmlNamespaceSupport::prefix(const QString& uri) const
784 NamespaceMap::const_iterator itc, it = d->ns.constBegin();
785 while ((itc=it) != d->ns.constEnd()) {
787 if (*itc == uri && !itc.key().isEmpty())
790 return QLatin1String("");
794 Looks up the prefix \a prefix in the current context and returns
795 the currently-mapped namespace URI. Use the empty string ("") for
796 the default namespace.
798 QString QXmlNamespaceSupport::uri(const QString& prefix) const
800 return d->ns[prefix];
804 Splits the name \a qname at the ':' and returns the prefix in \a
805 prefix and the local name in \a localname.
809 void QXmlNamespaceSupport::splitName(const QString& qname, QString& prefix,
810 QString& localname) const
812 int pos = qname.indexOf(QLatin1Char(':'));
816 prefix = qname.left(pos);
817 localname = qname.mid(pos+1);
821 Processes a raw XML 1.0 name in the current context by removing
822 the prefix and looking it up among the prefixes currently
825 \a qname is the raw XML 1.0 name to be processed. \a isAttribute
826 is true if the name is an attribute name.
828 This function stores the namespace URI in \a nsuri (which will be
829 set to an empty string if the raw name has an undeclared prefix),
830 and stores the local name (without prefix) in \a localname (which
831 will be set to an empty string if no namespace is in use).
833 Note that attribute names are processed differently than element
834 names: an unprefixed element name gets the default namespace (if
835 any), while an unprefixed attribute name does not.
837 void QXmlNamespaceSupport::processName(const QString& qname,
839 QString& nsuri, QString& localname) const
841 int len = qname.size();
842 const QChar *data = qname.constData();
843 for (int pos = 0; pos < len; ++pos) {
844 if (data[pos] == QLatin1Char(':')) {
845 nsuri = uri(qname.left(pos));
846 localname = qname.mid(pos + 1);
853 // attributes don't take default namespace
854 if (!isAttribute && !d->ns.isEmpty()) {
856 We want to access d->ns.value(""), but as an optimization
857 we use the fact that "" compares less than any other
858 string, so it's either first in the map or not there.
860 NamespaceMap::const_iterator first = d->ns.constBegin();
861 if (first.key().isEmpty())
862 nsuri = first.value(); // get default namespace
868 Returns a list of all the prefixes currently declared.
870 If there is a default prefix, this function does not return it in
871 the list; check for the default prefix using uri() with an
874 QStringList QXmlNamespaceSupport::prefixes() const
878 NamespaceMap::const_iterator itc, it = d->ns.constBegin();
879 while ((itc=it) != d->ns.constEnd()) {
881 if (!itc.key().isEmpty())
882 list.append(itc.key());
890 Returns a list of all prefixes currently declared for the
891 namespace URI \a uri.
893 The "xml:" prefix is included. If you only want one prefix that is
894 mapped to the namespace URI, and you don't care which one you get,
895 use the prefix() function instead.
897 Note: The empty (default) prefix is never included in this list;
898 to check for the presence of a default namespace, call uri() with
901 QStringList QXmlNamespaceSupport::prefixes(const QString& uri) const
905 NamespaceMap::const_iterator itc, it = d->ns.constBegin();
906 while ((itc=it) != d->ns.constEnd()) {
908 if (*itc == uri && !itc.key().isEmpty())
909 list.append(itc.key());
915 Starts a new namespace context.
917 Normally, you should push a new context at the beginning of each
918 XML element: the new context automatically inherits the
919 declarations of its parent context, and it also keeps track of
920 which declarations were made within this context.
924 void QXmlNamespaceSupport::pushContext()
926 d->nsStack.push(d->ns);
930 Reverts to the previous namespace context.
932 Normally, you should pop the context at the end of each XML
933 element. After popping the context, all namespace prefix mappings
934 that were previously in force are restored.
938 void QXmlNamespaceSupport::popContext()
941 if(!d->nsStack.isEmpty())
942 d->ns = d->nsStack.pop();
946 Resets this namespace support object ready for reuse.
948 void QXmlNamespaceSupport::reset()
950 QXmlNamespaceSupportPrivate *newD = new QXmlNamespaceSupportPrivate;
957 /*********************************************
961 *********************************************/
964 \class QXmlAttributes
966 \brief The QXmlAttributes class provides XML attributes.
971 If attributes are reported by QXmlContentHandler::startElement()
972 this class is used to pass the attribute values.
974 Use index() to locate the position of an attribute in the list,
975 count() to retrieve the number of attributes, and clear() to
976 remove the attributes. New attributes can be added with append().
977 Use type() to get an attribute's type and value() to get its
978 value. The attribute's name is available from localName() or
979 qName(), and its namespace URI from uri().
984 \fn QXmlAttributes::QXmlAttributes()
986 Constructs an empty attribute list.
990 \fn QXmlAttributes::~QXmlAttributes()
992 Destroys the attributes object.
996 Looks up the index of an attribute by the qualified name \a qName.
998 Returns the index of the attribute or -1 if it wasn't found.
1000 \sa {Namespace Support via Features}
1002 int QXmlAttributes::index(const QString& qName) const
1004 for (int i = 0; i < attList.size(); ++i) {
1005 if (attList.at(i).qname == qName)
1013 int QXmlAttributes::index(const QLatin1String& qName) const
1015 for (int i = 0; i < attList.size(); ++i) {
1016 if (attList.at(i).qname == qName)
1025 Looks up the index of an attribute by a namespace name.
1027 \a uri specifies the namespace URI, or an empty string if the name
1028 has no namespace URI. \a localPart specifies the attribute's local
1031 Returns the index of the attribute, or -1 if it wasn't found.
1033 \sa {Namespace Support via Features}
1035 int QXmlAttributes::index(const QString& uri, const QString& localPart) const
1037 for (int i = 0; i < attList.size(); ++i) {
1038 const Attribute &att = attList.at(i);
1039 if (att.uri == uri && att.localname == localPart)
1046 Returns the number of attributes in the list.
1050 int QXmlAttributes::length() const
1052 return attList.count();
1056 \fn int QXmlAttributes::count() const
1058 Returns the number of attributes in the list. This function is
1059 equivalent to length().
1063 Looks up an attribute's local name for the attribute at position
1064 \a index. If no namespace processing is done, the local name is
1067 \sa {Namespace Support via Features}
1069 QString QXmlAttributes::localName(int index) const
1071 return attList.at(index).localname;
1075 Looks up an attribute's XML 1.0 qualified name for the attribute
1076 at position \a index.
1078 \sa {Namespace Support via Features}
1080 QString QXmlAttributes::qName(int index) const
1082 return attList.at(index).qname;
1086 Looks up an attribute's namespace URI for the attribute at
1087 position \a index. If no namespace processing is done or if the
1088 attribute has no namespace, the namespace URI is an empty string.
1090 \sa {Namespace Support via Features}
1092 QString QXmlAttributes::uri(int index) const
1094 return attList.at(index).uri;
1098 Looks up an attribute's type for the attribute at position \a
1101 Currently only "CDATA" is returned.
1103 QString QXmlAttributes::type(int) const
1105 return QLatin1String("CDATA");
1111 Looks up an attribute's type for the qualified name \a qName.
1113 Currently only "CDATA" is returned.
1115 QString QXmlAttributes::type(const QString&) const
1117 return QLatin1String("CDATA");
1123 Looks up an attribute's type by namespace name.
1125 \a uri specifies the namespace URI and \a localName specifies the
1126 local name. If the name has no namespace URI, use an empty string
1129 Currently only "CDATA" is returned.
1131 QString QXmlAttributes::type(const QString&, const QString&) const
1133 return QLatin1String("CDATA");
1137 Returns an attribute's value for the attribute at position \a
1138 index. The index must be a valid position
1139 (i.e., 0 <= \a index < count()).
1141 QString QXmlAttributes::value(int index) const
1143 return attList.at(index).value;
1149 Returns an attribute's value for the qualified name \a qName, or an
1150 empty string if no attribute exists for the name given.
1152 \sa {Namespace Support via Features}
1154 QString QXmlAttributes::value(const QString& qName) const
1156 int i = index(qName);
1159 return attList.at(i).value;
1165 Returns an attribute's value for the qualified name \a qName, or an
1166 empty string if no attribute exists for the name given.
1168 \sa {Namespace Support via Features}
1170 QString QXmlAttributes::value(const QLatin1String& qName) const
1172 int i = index(qName);
1175 return attList.at(i).value;
1181 Returns an attribute's value by namespace name.
1183 \a uri specifies the namespace URI, or an empty string if the name
1184 has no namespace URI. \a localName specifies the attribute's local
1187 QString QXmlAttributes::value(const QString& uri, const QString& localName) const
1189 int i = index(uri, localName);
1192 return attList.at(i).value;
1196 Clears the list of attributes.
1200 void QXmlAttributes::clear()
1206 Appends a new attribute entry to the list of attributes. The
1207 qualified name of the attribute is \a qName, the namespace URI is
1208 \a uri and the local name is \a localPart. The value of the
1209 attribute is \a value.
1211 \sa qName() uri() localName() value()
1213 void QXmlAttributes::append(const QString &qName, const QString &uri, const QString &localPart, const QString &value)
1218 att.localname = localPart;
1221 attList.append(att);
1225 /*********************************************
1229 *********************************************/
1232 \class QXmlInputSource
1234 \brief The QXmlInputSource class provides the input data for the
1235 QXmlReader subclasses.
1240 All subclasses of QXmlReader read the input XML document from this
1243 This class recognizes the encoding of the data by reading the
1244 encoding declaration in the XML file if it finds one, and reading
1245 the data using the corresponding encoding. If it does not find an
1246 encoding declaration, then it assumes that the data is either in
1247 UTF-8 or UTF-16, depending on whether it can find a byte-order
1250 There are two ways to populate the input source with data: you can
1251 construct it with a QIODevice* so that the input source reads the
1252 data from that device. Or you can set the data explicitly with one
1253 of the setData() functions.
1255 Usually you either construct a QXmlInputSource that works on a
1256 QIODevice* or you construct an empty QXmlInputSource and set the
1257 data with setData(). There are only rare occasions where you would
1258 want to mix both methods.
1260 The QXmlReader subclasses use the next() function to read the
1261 input character by character. If you want to start from the
1262 beginning again, use reset().
1264 The functions data() and fetchData() are useful if you want to do
1265 something with the data other than parsing, e.g. displaying the
1266 raw XML file. The benefit of using the QXmlInputClass in such
1267 cases is that it tries to use the correct encoding.
1269 \sa QXmlReader QXmlSimpleReader
1272 // the following two are guaranteed not to be a character
1273 const ushort QXmlInputSource::EndOfData = 0xfffe;
1274 const ushort QXmlInputSource::EndOfDocument = 0xffff;
1277 Common part of the constructors.
1279 void QXmlInputSource::init()
1281 d = new QXmlInputSourcePrivate;
1288 #ifndef QT_NO_TEXTCODEC
1291 d->nextReturnedEndOfData = true; // first call to next() will call fetchData()
1293 d->encodingDeclBytes.clear();
1294 d->encodingDeclChars.clear();
1295 d->lookingForEncodingDecl = true;
1303 Constructs an input source which contains no data.
1307 QXmlInputSource::QXmlInputSource()
1313 Constructs an input source and gets the data from device \a dev.
1314 If \a dev is not open, it is opened in read-only mode. If \a dev
1315 is 0 or it is not possible to read from the device, the input
1316 source will contain no data.
1318 \sa setData() fetchData() QIODevice
1320 QXmlInputSource::QXmlInputSource(QIODevice *dev)
1323 d->inputDevice = dev;
1324 d->inputDevice->setTextModeEnabled(false);
1329 Use the QXmlInputSource(QIODevice *) constructor instead, with
1330 the device used by \a stream.
1332 \sa QTextStream::device()
1334 QXmlInputSource::QXmlInputSource(QTextStream& stream)
1337 d->inputStream = &stream;
1341 Use QXmlInputSource(&\a file) instead.
1343 QXmlInputSource::QXmlInputSource(QFile& file)
1346 d->inputDevice = &file;
1353 QXmlInputSource::~QXmlInputSource()
1355 // ### Qt 5: close the input device. See task 153111
1356 #ifndef QT_NO_TEXTCODEC
1357 delete d->encMapper;
1363 Returns the next character of the input source. If this function
1364 reaches the end of available data, it returns
1365 QXmlInputSource::EndOfData. If you call next() after that, it
1366 tries to fetch more data by calling fetchData(). If the
1367 fetchData() call results in new data, this function returns the
1368 first character of that data; otherwise it returns
1369 QXmlInputSource::EndOfDocument.
1371 Readers, such as QXmlSimpleReader, will assume that the end of
1372 the XML document has been reached if the this function returns
1373 QXmlInputSource::EndOfDocument, and will check that the
1374 supplied input is well-formed. Therefore, when reimplementing
1375 this function, it is important to ensure that this behavior is
1378 \sa reset() fetchData() QXmlSimpleReader::parse() QXmlSimpleReader::parseContinue()
1380 QChar QXmlInputSource::next()
1382 if (d->pos >= d->length) {
1383 if (d->nextReturnedEndOfData) {
1384 d->nextReturnedEndOfData = false;
1386 if (d->pos >= d->length) {
1387 return EndOfDocument;
1391 d->nextReturnedEndOfData = true;
1395 // QXmlInputSource has no way to signal encoding errors. The best we can do
1396 // is return EndOfDocument. We do *not* return EndOfData, because the reader
1397 // will then just call this function again to get the next char.
1398 QChar c = d->unicode[d->pos++];
1399 if (c.unicode() == EndOfData)
1405 This function sets the position used by next() to the beginning of
1406 the data returned by data(). This is useful if you want to use the
1407 input source for more than one parse.
1409 \note In the case that the underlying data source is a QIODevice,
1410 the current position in the device is not automatically set to the
1411 start of input. Call QIODevice::seek(0) on the device to do this.
1415 void QXmlInputSource::reset()
1417 d->nextReturnedEndOfData = false;
1422 Returns the data the input source contains or an empty string if the
1423 input source does not contain any data.
1425 \sa setData() QXmlInputSource() fetchData()
1427 QString QXmlInputSource::data() const
1429 if (d->nextReturnedEndOfData) {
1430 QXmlInputSource *that = const_cast<QXmlInputSource*>(this);
1431 that->d->nextReturnedEndOfData = false;
1438 Sets the data of the input source to \a dat.
1440 If the input source already contains data, this function deletes
1445 void QXmlInputSource::setData(const QString& dat)
1448 d->unicode = dat.unicode();
1450 d->length = d->str.length();
1451 d->nextReturnedEndOfData = false;
1457 The data \a dat is passed through the correct text-codec, before
1460 void QXmlInputSource::setData(const QByteArray& dat)
1462 setData(fromRawData(dat));
1466 This function reads more data from the device that was set during
1467 construction. If the input source already contained data, this
1468 function deletes that data first.
1470 This object contains no data after a call to this function if the
1471 object was constructed without a device to read data from or if
1472 this function was not able to get more data from the device.
1474 There are two occasions where a fetch is done implicitly by
1475 another function call: during construction (so that the object
1476 starts out with some initial data where available), and during a
1477 call to next() (if the data had run out).
1479 You don't normally need to use this function if you use next().
1481 \sa data() next() QXmlInputSource()
1484 void QXmlInputSource::fetchData()
1493 if (d->inputDevice || d->inputStream) {
1494 QIODevice *device = d->inputDevice ? d->inputDevice : d->inputStream->device();
1497 if (d->inputStream && d->inputStream->string()) {
1498 QString *s = d->inputStream->string();
1499 rawData = QByteArray((const char *) s->constData(), s->size() * sizeof(QChar));
1501 } else if (device->isOpen() || device->open(QIODevice::ReadOnly)) {
1502 rawData.resize(BufferSize);
1503 qint64 size = device->read(rawData.data(), BufferSize);
1506 // We don't want to give fromRawData() less than four bytes if we can avoid it.
1508 if (!device->waitForReadyRead(-1))
1510 int ret = device->read(rawData.data() + size, BufferSize - size);
1517 rawData.resize(qMax(qint64(0), size));
1520 /* We do this inside the "if (d->inputDevice ..." scope
1521 * because if we're not using a stream or device, that is,
1522 * the user set a QString manually, we don't want to set
1524 setData(fromRawData(rawData));
1528 #ifndef QT_NO_TEXTCODEC
1529 static QString extractEncodingDecl(const QString &text, bool *needMoreText)
1531 *needMoreText = false;
1533 int l = text.length();
1534 QString snip = QString::fromLatin1("<?xml").left(l);
1535 if (l > 0 && !text.startsWith(snip))
1538 int endPos = text.indexOf(QLatin1Char('>'));
1540 *needMoreText = l < 255; // we won't look forever
1544 int pos = text.indexOf(QLatin1String("encoding"));
1545 if (pos == -1 || pos >= endPos)
1548 while (pos < endPos) {
1549 ushort uc = text.at(pos).unicode();
1550 if (uc == '\'' || uc == '"')
1560 while (pos < endPos) {
1561 ushort uc = text.at(pos).unicode();
1562 if (uc == '\'' || uc == '"')
1564 encoding.append(uc);
1570 #endif // QT_NO_TEXTCODEC
1573 This function reads the XML file from \a data and tries to
1574 recognize the encoding. It converts the raw data \a data into a
1575 QString and returns it. It tries its best to get the correct
1576 encoding for the XML file.
1578 If \a beginning is true, this function assumes that the data
1579 starts at the beginning of a new XML document and looks for an
1580 encoding declaration. If \a beginning is false, it converts the
1581 raw data using the encoding determined from prior calls.
1583 QString QXmlInputSource::fromRawData(const QByteArray &data, bool beginning)
1585 #ifdef QT_NO_TEXTCODEC
1586 Q_UNUSED(beginning);
1587 return QString::fromAscii(data.constData(), data.size());
1589 if (data.size() == 0)
1592 delete d->encMapper;
1596 int mib = 106; // UTF-8
1598 // This is the initial UTF codec we will read the encoding declaration with
1599 if (d->encMapper == 0) {
1600 d->encodingDeclBytes.clear();
1601 d->encodingDeclChars.clear();
1602 d->lookingForEncodingDecl = true;
1604 // look for byte order mark and read the first 5 characters
1605 if (data.size() >= 4) {
1606 uchar ch1 = data.at(0);
1607 uchar ch2 = data.at(1);
1608 uchar ch3 = data.at(2);
1609 uchar ch4 = data.at(3);
1611 if ((ch1 == 0 && ch2 == 0 && ch3 == 0xfe && ch4 == 0xff) ||
1612 (ch1 == 0xff && ch2 == 0xfe && ch3 == 0 && ch4 == 0))
1613 mib = 1017; // UTF-32 with byte order mark
1614 else if (ch1 == 0x3c && ch2 == 0x00 && ch3 == 0x00 && ch4 == 0x00)
1615 mib = 1019; // UTF-32LE
1616 else if (ch1 == 0x00 && ch2 == 0x00 && ch3 == 0x00 && ch4 == 0x3c)
1617 mib = 1018; // UTF-32BE
1619 if (mib == 106 && data.size() >= 2) {
1620 uchar ch1 = data.at(0);
1621 uchar ch2 = data.at(1);
1623 if ((ch1 == 0xfe && ch2 == 0xff) || (ch1 == 0xff && ch2 == 0xfe))
1624 mib = 1015; // UTF-16 with byte order mark
1625 else if (ch1 == 0x3c && ch2 == 0x00)
1626 mib = 1014; // UTF-16LE
1627 else if (ch1 == 0x00 && ch2 == 0x3c)
1628 mib = 1013; // UTF-16BE
1631 QTextCodec *codec = QTextCodec::codecForMib(mib);
1634 d->encMapper = codec->makeDecoder();
1637 QString input = d->encMapper->toUnicode(data, data.size());
1639 if (d->lookingForEncodingDecl) {
1640 d->encodingDeclChars += input;
1643 QString encoding = extractEncodingDecl(d->encodingDeclChars, &needMoreText);
1645 if (!encoding.isEmpty()) {
1646 if (QTextCodec *codec = QTextCodec::codecForName(encoding.toLatin1())) {
1647 /* If the encoding is the same, we don't have to do toUnicode() all over again. */
1648 if(codec->mibEnum() != mib) {
1649 delete d->encMapper;
1650 d->encMapper = codec->makeDecoder();
1652 /* The variable input can potentially be large, so we deallocate
1653 * it before calling toUnicode() in order to avoid having two
1654 * large QStrings in memory simultaneously. */
1657 // prime the decoder with the data so far
1658 d->encMapper->toUnicode(d->encodingDeclBytes, d->encodingDeclBytes.size());
1659 // now feed it the new data
1660 input = d->encMapper->toUnicode(data, data.size());
1665 d->encodingDeclBytes += data;
1666 d->lookingForEncodingDecl = needMoreText;
1674 /*********************************************
1676 * QXmlDefaultHandler
1678 *********************************************/
1681 \class QXmlContentHandler
1683 \brief The QXmlContentHandler class provides an interface to
1684 report the logical content of XML data.
1689 If the application needs to be informed of basic parsing events,
1690 it can implement this interface and activate it using
1691 QXmlReader::setContentHandler(). The reader can then report basic
1692 document-related events like the start and end of elements and
1693 character data through this interface.
1695 The order of events in this interface is very important, and
1696 mirrors the order of information in the document itself. For
1697 example, all of an element's content (character data, processing
1698 instructions, and sub-elements) appears, in order, between the
1699 startElement() event and the corresponding endElement() event.
1701 The class QXmlDefaultHandler provides a default implementation for
1702 this interface; subclassing from the QXmlDefaultHandler class is
1703 very convenient if you only want to be informed of some parsing
1706 The startDocument() function is called at the start of the
1707 document, and endDocument() is called at the end. Before parsing
1708 begins setDocumentLocator() is called. For each element
1709 startElement() is called, with endElement() being called at the
1710 end of each element. The characters() function is called with
1711 chunks of character data; ignorableWhitespace() is called with
1712 chunks of whitespace and processingInstruction() is called with
1713 processing instructions. If an entity is skipped skippedEntity()
1714 is called. At the beginning of prefix-URI scopes
1715 startPrefixMapping() is called.
1717 \sa QXmlDTDHandler, QXmlDeclHandler, QXmlEntityResolver, QXmlErrorHandler,
1718 QXmlLexicalHandler, {Introduction to SAX2}
1722 \fn QXmlContentHandler::~QXmlContentHandler()
1724 Destroys the content handler.
1728 \fn void QXmlContentHandler::setDocumentLocator(QXmlLocator* locator)
1730 The reader calls this function before it starts parsing the
1731 document. The argument \a locator is a pointer to a QXmlLocator
1732 which allows the application to get the parsing position within
1735 Do not destroy the \a locator; it is destroyed when the reader is
1736 destroyed. (Do not use the \a locator after the reader is
1741 \fn bool QXmlContentHandler::startDocument()
1743 The reader calls this function when it starts parsing the
1744 document. The reader calls this function just once, after the call
1745 to setDocumentLocator(), and before any other functions in this
1746 class or in the QXmlDTDHandler class are called.
1748 If this function returns false the reader stops parsing and
1749 reports an error. The reader uses the function errorString() to
1750 get the error message.
1756 \fn bool QXmlContentHandler::endDocument()
1758 The reader calls this function after it has finished parsing. It
1759 is called just once, and is the last handler function called. It
1760 is called after the reader has read all input or has abandoned
1761 parsing because of a fatal error.
1763 If this function returns false the reader stops parsing and
1764 reports an error. The reader uses the function errorString() to
1765 get the error message.
1771 \fn bool QXmlContentHandler::startPrefixMapping(const QString& prefix, const QString& uri)
1773 The reader calls this function to signal the begin of a prefix-URI
1774 namespace mapping scope. This information is not necessary for
1775 normal namespace processing since the reader automatically
1776 replaces prefixes for element and attribute names.
1778 Note that startPrefixMapping() and endPrefixMapping() calls are
1779 not guaranteed to be properly nested relative to each other: all
1780 startPrefixMapping() events occur before the corresponding
1781 startElement() event, and all endPrefixMapping() events occur
1782 after the corresponding endElement() event, but their order is not
1783 otherwise guaranteed.
1785 The argument \a prefix is the namespace prefix being declared and
1786 the argument \a uri is the namespace URI the prefix is mapped to.
1788 If this function returns false the reader stops parsing and
1789 reports an error. The reader uses the function errorString() to
1790 get the error message.
1792 \sa endPrefixMapping(), {Namespace Support via Features}
1796 \fn bool QXmlContentHandler::endPrefixMapping(const QString& prefix)
1798 The reader calls this function to signal the end of a prefix
1799 mapping for the prefix \a prefix.
1801 If this function returns false the reader stops parsing and
1802 reports an error. The reader uses the function errorString() to
1803 get the error message.
1805 \sa startPrefixMapping(), {Namespace Support via Features}
1809 \fn bool QXmlContentHandler::startElement(const QString& namespaceURI, const QString& localName, const QString& qName, const QXmlAttributes& atts)
1811 The reader calls this function when it has parsed a start element
1814 There is a corresponding endElement() call when the corresponding
1815 end element tag is read. The startElement() and endElement() calls
1816 are always nested correctly. Empty element tags (e.g. \c{<x/>})
1817 cause a startElement() call to be immediately followed by an
1820 The attribute list provided only contains attributes with explicit
1821 values. The attribute list contains attributes used for namespace
1822 declaration (i.e. attributes starting with xmlns) only if the
1823 namespace-prefix property of the reader is true.
1825 The argument \a namespaceURI is the namespace URI, or
1826 an empty string if the element has no namespace URI or if no
1827 namespace processing is done. \a localName is the local name
1828 (without prefix), or an empty string if no namespace processing is
1829 done, \a qName is the qualified name (with prefix) and \a atts are
1830 the attributes attached to the element. If there are no
1831 attributes, \a atts is an empty attributes object.
1833 If this function returns false the reader stops parsing and
1834 reports an error. The reader uses the function errorString() to
1835 get the error message.
1837 \sa endElement(), {Namespace Support via Features}
1841 \fn bool QXmlContentHandler::endElement(const QString& namespaceURI, const QString& localName, const QString& qName)
1843 The reader calls this function when it has parsed an end element
1844 tag with the qualified name \a qName, the local name \a localName
1845 and the namespace URI \a namespaceURI.
1847 If this function returns false the reader stops parsing and
1848 reports an error. The reader uses the function errorString() to
1849 get the error message.
1851 \sa startElement(), {Namespace Support via Features}
1855 \fn bool QXmlContentHandler::characters(const QString& ch)
1857 The reader calls this function when it has parsed a chunk of
1858 character data (either normal character data or character data
1859 inside a CDATA section; if you need to distinguish between those
1860 two types you must use QXmlLexicalHandler::startCDATA() and
1861 QXmlLexicalHandler::endCDATA()). The character data is reported in
1864 Some readers report whitespace in element content using the
1865 ignorableWhitespace() function rather than using this one.
1867 A reader may report the character data of an element in more than
1868 one chunk; e.g. a reader might want to report "a\<b" in three
1869 characters() events ("a ", "\<" and " b").
1871 If this function returns false the reader stops parsing and
1872 reports an error. The reader uses the function errorString() to
1873 get the error message.
1877 \fn bool QXmlContentHandler::ignorableWhitespace(const QString& ch)
1879 Some readers may use this function to report each chunk of
1880 whitespace in element content. The whitespace is reported in \a ch.
1882 If this function returns false the reader stops parsing and
1883 reports an error. The reader uses the function errorString() to
1884 get the error message.
1888 \fn bool QXmlContentHandler::processingInstruction(const QString& target, const QString& data)
1890 The reader calls this function when it has parsed a processing
1893 \a target is the target name of the processing instruction and \a
1894 data is the data in the processing instruction.
1896 If this function returns false the reader stops parsing and
1897 reports an error. The reader uses the function errorString() to
1898 get the error message.
1902 \fn bool QXmlContentHandler::skippedEntity(const QString& name)
1904 Some readers may skip entities if they have not seen the
1905 declarations (e.g. because they are in an external DTD). If they
1906 do so they report that they skipped the entity called \a name by
1907 calling this function.
1909 If this function returns false the reader stops parsing and
1910 reports an error. The reader uses the function errorString() to
1911 get the error message.
1915 \fn QString QXmlContentHandler::errorString() const
1917 The reader calls this function to get an error string, e.g. if any
1918 of the handler functions returns false.
1923 \class QXmlErrorHandler
1925 \brief The QXmlErrorHandler class provides an interface to report
1931 If you want your application to report errors to the user or to
1932 perform customized error handling, you should subclass this class.
1934 You can set the error handler with QXmlReader::setErrorHandler().
1936 Errors can be reported using warning(), error() and fatalError(),
1937 with the error text being reported with errorString().
1939 \sa QXmlDTDHandler, QXmlDeclHandler, QXmlContentHandler, QXmlEntityResolver,
1940 QXmlLexicalHandler, {Introduction to SAX2}
1944 \fn QXmlErrorHandler::~QXmlErrorHandler()
1946 Destroys the error handler.
1950 \fn bool QXmlErrorHandler::warning(const QXmlParseException& exception)
1952 A reader might use this function to report a warning. Warnings are
1953 conditions that are not errors or fatal errors as defined by the
1954 XML 1.0 specification. Details of the warning are stored in \a
1957 If this function returns false the reader stops parsing and
1958 reports an error. The reader uses the function errorString() to
1959 get the error message.
1963 \fn bool QXmlErrorHandler::error(const QXmlParseException& exception)
1965 A reader might use this function to report a recoverable error. A
1966 recoverable error corresponds to the definiton of "error" in
1967 section 1.2 of the XML 1.0 specification. Details of the error are
1968 stored in \a exception.
1970 The reader must continue to provide normal parsing events after
1971 invoking this function.
1973 If this function returns false the reader stops parsing and
1974 reports an error. The reader uses the function errorString() to
1975 get the error message.
1979 \fn bool QXmlErrorHandler::fatalError(const QXmlParseException& exception)
1981 A reader must use this function to report a non-recoverable error.
1982 Details of the error are stored in \a exception.
1984 If this function returns true the reader might try to go on
1985 parsing and reporting further errors, but no regular parsing
1986 events are reported.
1990 \fn QString QXmlErrorHandler::errorString() const
1992 The reader calls this function to get an error string if any of
1993 the handler functions returns false.
1998 \class QXmlDTDHandler
2000 \brief The QXmlDTDHandler class provides an interface to report
2001 DTD content of XML data.
2006 If an application needs information about notations and unparsed
2007 entities, it can implement this interface and register an instance
2008 with QXmlReader::setDTDHandler().
2010 Note that this interface includes only those DTD events that the
2011 XML recommendation requires processors to report, i.e. notation
2012 and unparsed entity declarations using notationDecl() and
2013 unparsedEntityDecl() respectively.
2015 \sa QXmlDeclHandler, QXmlContentHandler, QXmlEntityResolver, QXmlErrorHandler,
2016 QXmlLexicalHandler, {Introduction to SAX2}
2020 \fn QXmlDTDHandler::~QXmlDTDHandler()
2022 Destroys the DTD handler.
2026 \fn bool QXmlDTDHandler::notationDecl(const QString& name, const QString& publicId, const QString& systemId)
2028 The reader calls this function when it has parsed a notation
2031 The argument \a name is the notation name, \a publicId is the
2032 notation's public identifier and \a systemId is the notation's
2035 If this function returns false the reader stops parsing and
2036 reports an error. The reader uses the function errorString() to
2037 get the error message.
2041 \fn bool QXmlDTDHandler::unparsedEntityDecl(const QString& name, const QString& publicId, const QString& systemId, const QString& notationName)
2043 The reader calls this function when it finds an unparsed entity
2046 The argument \a name is the unparsed entity's name, \a publicId is
2047 the entity's public identifier, \a systemId is the entity's system
2048 identifier and \a notationName is the name of the associated
2051 If this function returns false the reader stops parsing and
2052 reports an error. The reader uses the function errorString() to
2053 get the error message.
2057 \fn QString QXmlDTDHandler::errorString() const
2059 The reader calls this function to get an error string if any of
2060 the handler functions returns false.
2065 \class QXmlEntityResolver
2067 \brief The QXmlEntityResolver class provides an interface to
2068 resolve external entities contained in XML data.
2073 If an application needs to implement customized handling for
2074 external entities, it must implement this interface, i.e.
2075 resolveEntity(), and register it with
2076 QXmlReader::setEntityResolver().
2078 \sa QXmlDTDHandler, QXmlDeclHandler, QXmlContentHandler, QXmlErrorHandler,
2079 QXmlLexicalHandler, {Introduction to SAX2}
2083 \fn QXmlEntityResolver::~QXmlEntityResolver()
2085 Destroys the entity resolver.
2089 \fn bool QXmlEntityResolver::resolveEntity(const QString& publicId, const QString& systemId, QXmlInputSource*& ret)
2091 The reader calls this function before it opens any external
2092 entity, except the top-level document entity. The application may
2093 request the reader to resolve the entity itself (\a ret is 0) or
2094 to use an entirely different input source (\a ret points to the
2097 The reader deletes the input source \a ret when it no longer needs
2098 it, so you should allocate it on the heap with \c new.
2100 The argument \a publicId is the public identifier of the external
2101 entity, \a systemId is the system identifier of the external
2102 entity and \a ret is the return value of this function. If \a ret
2103 is 0 the reader should resolve the entity itself, if it is
2104 non-zero it must point to an input source which the reader uses
2107 If this function returns false the reader stops parsing and
2108 reports an error. The reader uses the function errorString() to
2109 get the error message.
2113 \fn QString QXmlEntityResolver::errorString() const
2115 The reader calls this function to get an error string if any of
2116 the handler functions returns false.
2121 \class QXmlLexicalHandler
2123 \brief The QXmlLexicalHandler class provides an interface to
2124 report the lexical content of XML data.
2129 The events in the lexical handler apply to the entire document,
2130 not just to the document element, and all lexical handler events
2131 appear between the content handler's startDocument and endDocument
2134 You can set the lexical handler with
2135 QXmlReader::setLexicalHandler().
2137 This interface's design is based on the SAX2 extension
2140 The interface provides the startDTD(), endDTD(), startEntity(),
2141 endEntity(), startCDATA(), endCDATA() and comment() functions.
2143 \sa QXmlDTDHandler, QXmlDeclHandler, QXmlContentHandler, QXmlEntityResolver,
2144 QXmlErrorHandler, {Introduction to SAX2}
2148 \fn QXmlLexicalHandler::~QXmlLexicalHandler()
2150 Destroys the lexical handler.
2154 \fn bool QXmlLexicalHandler::startDTD(const QString& name, const QString& publicId, const QString& systemId)
2156 The reader calls this function to report the start of a DTD
2157 declaration, if any. It reports the name of the document type in
2158 \a name, the public identifier in \a publicId and the system
2159 identifier in \a systemId.
2161 If the public identifier is missing, \a publicId is set to
2162 an empty string. If the system identifier is missing, \a systemId is
2163 set to an empty string. Note that it is not valid XML to have a
2164 public identifier but no system identifier; in such cases a parse
2167 All declarations reported through QXmlDTDHandler or
2168 QXmlDeclHandler appear between the startDTD() and endDTD() calls.
2170 If this function returns false the reader stops parsing and
2171 reports an error. The reader uses the function errorString() to
2172 get the error message.
2178 \fn bool QXmlLexicalHandler::endDTD()
2180 The reader calls this function to report the end of a DTD
2181 declaration, if any.
2183 If this function returns false the reader stops parsing and
2184 reports an error. The reader uses the function errorString() to
2185 get the error message.
2191 \fn bool QXmlLexicalHandler::startEntity(const QString& name)
2193 The reader calls this function to report the start of an entity
2196 Note that if the entity is unknown, the reader reports it through
2197 QXmlContentHandler::skippedEntity() and not through this
2200 If this function returns false the reader stops parsing and
2201 reports an error. The reader uses the function errorString() to
2202 get the error message.
2204 \sa endEntity(), QXmlSimpleReader::setFeature()
2208 \fn bool QXmlLexicalHandler::endEntity(const QString& name)
2210 The reader calls this function to report the end of an entity
2213 For every startEntity() call, there is a corresponding endEntity()
2214 call. The calls to startEntity() and endEntity() are properly
2217 If this function returns false the reader stops parsing and
2218 reports an error. The reader uses the function errorString() to
2219 get the error message.
2221 \sa startEntity(), QXmlContentHandler::skippedEntity(), QXmlSimpleReader::setFeature()
2225 \fn bool QXmlLexicalHandler::startCDATA()
2227 The reader calls this function to report the start of a CDATA
2228 section. The content of the CDATA section is reported through the
2229 QXmlContentHandler::characters() function. This function is
2230 intended only to report the boundary.
2232 If this function returns false the reader stops parsing and
2233 reports an error. The reader uses the function errorString() to
2234 get the error message.
2240 \fn bool QXmlLexicalHandler::endCDATA()
2242 The reader calls this function to report the end of a CDATA
2245 If this function returns false the reader stops parsing and reports
2246 an error. The reader uses the function errorString() to get the error
2249 \sa startCDATA(), QXmlContentHandler::characters()
2253 \fn bool QXmlLexicalHandler::comment(const QString& ch)
2255 The reader calls this function to report an XML comment anywhere
2256 in the document. It reports the text of the comment in \a ch.
2258 If this function returns false the reader stops parsing and
2259 reports an error. The reader uses the function errorString() to
2260 get the error message.
2264 \fn QString QXmlLexicalHandler::errorString() const
2266 The reader calls this function to get an error string if any of
2267 the handler functions returns false.
2272 \class QXmlDeclHandler
2274 \brief The QXmlDeclHandler class provides an interface to report declaration
2275 content of XML data.
2280 You can set the declaration handler with
2281 QXmlReader::setDeclHandler().
2283 This interface is based on the SAX2 extension DeclHandler.
2285 The interface provides attributeDecl(), internalEntityDecl() and
2286 externalEntityDecl() functions.
2288 \sa QXmlDTDHandler, QXmlContentHandler, QXmlEntityResolver, QXmlErrorHandler,
2289 QXmlLexicalHandler, {Introduction to SAX2}
2293 \fn QXmlDeclHandler::~QXmlDeclHandler()
2295 Destroys the declaration handler.
2299 \fn bool QXmlDeclHandler::attributeDecl(const QString& eName, const QString& aName, const QString& type, const QString& valueDefault, const QString& value)
2301 The reader calls this function to report an attribute type
2302 declaration. Only the effective (first) declaration for an
2303 attribute is reported.
2305 The reader passes the name of the associated element in \a eName
2306 and the name of the attribute in \a aName. It passes a string that
2307 represents the attribute type in \a type and a string that
2308 represents the attribute default in \a valueDefault. This string
2309 is one of "#IMPLIED", "#REQUIRED", "#FIXED" or an empty string (if
2310 none of the others applies). The reader passes the attribute's
2311 default value in \a value. If no default value is specified in the
2312 XML file, \a value is an empty string.
2314 If this function returns false the reader stops parsing and
2315 reports an error. The reader uses the function errorString() to
2316 get the error message.
2320 \fn bool QXmlDeclHandler::internalEntityDecl(const QString& name, const QString& value)
2322 The reader calls this function to report an internal entity
2323 declaration. Only the effective (first) declaration is reported.
2325 The reader passes the name of the entity in \a name and the value
2326 of the entity in \a value.
2328 If this function returns false the reader stops parsing and
2329 reports an error. The reader uses the function errorString() to
2330 get the error message.
2334 \fn bool QXmlDeclHandler::externalEntityDecl(const QString& name, const QString& publicId, const QString& systemId)
2336 The reader calls this function to report a parsed external entity
2337 declaration. Only the effective (first) declaration for each
2340 The reader passes the name of the entity in \a name, the public
2341 identifier in \a publicId and the system identifier in \a
2342 systemId. If there is no public identifier specified, it passes
2343 an empty string in \a publicId.
2345 If this function returns false the reader stops parsing and
2346 reports an error. The reader uses the function errorString() to
2347 get the error message.
2351 \fn QString QXmlDeclHandler::errorString() const
2353 The reader calls this function to get an error string if any of
2354 the handler functions returns false.
2359 \class QXmlDefaultHandler
2361 \brief The QXmlDefaultHandler class provides a default implementation of all
2362 the XML handler classes.
2367 This class gathers together the features of
2368 the specialized handler classes, making it a convenient
2369 starting point when implementing custom handlers for
2370 subclasses of QXmlReader, particularly QXmlSimpleReader.
2371 The virtual functions from each of the base classes are
2372 reimplemented in this class, providing sensible default behavior
2373 for many common cases. By subclassing this class, and
2374 overriding these functions, you can concentrate
2375 on implementing the parts of the handler relevant to your
2378 The XML reader must be told which handler to use for different
2379 kinds of events during parsing. This means that, although
2380 QXmlDefaultHandler provides default implementations of functions
2381 inherited from all its base classes, we can still use specialized
2382 handlers for particular kinds of events.
2384 For example, QXmlDefaultHandler subclasses both
2385 QXmlContentHandler and QXmlErrorHandler, so by subclassing
2386 it we can use the same handler for both of the following
2389 \snippet doc/src/snippets/xml/rsslisting/rsslisting.cpp 0
2391 Since the reader will inform the handler of parsing errors, it is
2392 necessary to reimplement QXmlErrorHandler::fatalError() if, for
2393 example, we want to stop parsing when such an error occurs:
2395 \snippet doc/src/snippets/xml/rsslisting/handler.cpp 0
2397 The above function returns false, which tells the reader to stop
2398 parsing. To continue to use the same reader,
2399 it is necessary to create a new handler instance, and set up the
2400 reader to use it in the manner described above.
2402 It is useful to examine some of the functions inherited by
2403 QXmlDefaultHandler, and consider why they might be
2404 reimplemented in a custom handler.
2405 Custom handlers will typically reimplement
2406 QXmlContentHandler::startDocument() to prepare the handler for
2407 new content. Document elements and the text within them can be
2408 processed by reimplementing QXmlContentHandler::startElement(),
2409 QXmlContentHandler::endElement(), and
2410 QXmlContentHandler::characters().
2411 You may want to reimplement QXmlContentHandler::endDocument()
2412 to perform some finalization or validation on the content once the
2413 document has been read completely.
2415 \sa QXmlDTDHandler, QXmlDeclHandler, QXmlContentHandler, QXmlEntityResolver,
2416 QXmlErrorHandler, QXmlLexicalHandler, {Introduction to SAX2}
2420 \fn QXmlDefaultHandler::QXmlDefaultHandler()
2422 Constructs a handler for use with subclasses of QXmlReader.
2425 \fn QXmlDefaultHandler::~QXmlDefaultHandler()
2427 Destroys the handler.
2433 This reimplementation does nothing.
2435 void QXmlDefaultHandler::setDocumentLocator(QXmlLocator*)
2442 This reimplementation does nothing.
2444 bool QXmlDefaultHandler::startDocument()
2452 This reimplementation does nothing.
2454 bool QXmlDefaultHandler::endDocument()
2462 This reimplementation does nothing.
2464 bool QXmlDefaultHandler::startPrefixMapping(const QString&, const QString&)
2472 This reimplementation does nothing.
2474 bool QXmlDefaultHandler::endPrefixMapping(const QString&)
2482 This reimplementation does nothing.
2484 bool QXmlDefaultHandler::startElement(const QString&, const QString&,
2485 const QString&, const QXmlAttributes&)
2493 This reimplementation does nothing.
2495 bool QXmlDefaultHandler::endElement(const QString&, const QString&,
2504 This reimplementation does nothing.
2506 bool QXmlDefaultHandler::characters(const QString&)
2514 This reimplementation does nothing.
2516 bool QXmlDefaultHandler::ignorableWhitespace(const QString&)
2524 This reimplementation does nothing.
2526 bool QXmlDefaultHandler::processingInstruction(const QString&,
2535 This reimplementation does nothing.
2537 bool QXmlDefaultHandler::skippedEntity(const QString&)
2545 This reimplementation does nothing.
2547 bool QXmlDefaultHandler::warning(const QXmlParseException&)
2555 This reimplementation does nothing.
2557 bool QXmlDefaultHandler::error(const QXmlParseException&)
2565 This reimplementation does nothing.
2567 bool QXmlDefaultHandler::fatalError(const QXmlParseException&)
2575 This reimplementation does nothing.
2577 bool QXmlDefaultHandler::notationDecl(const QString&, const QString&,
2586 This reimplementation does nothing.
2588 bool QXmlDefaultHandler::unparsedEntityDecl(const QString&, const QString&,
2589 const QString&, const QString&)
2597 Sets \a ret to 0, so that the reader uses the system identifier
2598 provided in the XML document.
2600 bool QXmlDefaultHandler::resolveEntity(const QString&, const QString&,
2601 QXmlInputSource*& ret)
2610 Returns the default error string.
2612 QString QXmlDefaultHandler::errorString() const
2614 return QString::fromLatin1(XMLERR_ERRORBYCONSUMER);
2620 This reimplementation does nothing.
2622 bool QXmlDefaultHandler::startDTD(const QString&, const QString&, const QString&)
2630 This reimplementation does nothing.
2632 bool QXmlDefaultHandler::endDTD()
2640 This reimplementation does nothing.
2642 bool QXmlDefaultHandler::startEntity(const QString&)
2650 This reimplementation does nothing.
2652 bool QXmlDefaultHandler::endEntity(const QString&)
2660 This reimplementation does nothing.
2662 bool QXmlDefaultHandler::startCDATA()
2670 This reimplementation does nothing.
2672 bool QXmlDefaultHandler::endCDATA()
2680 This reimplementation does nothing.
2682 bool QXmlDefaultHandler::comment(const QString&)
2690 This reimplementation does nothing.
2692 bool QXmlDefaultHandler::attributeDecl(const QString&, const QString&, const QString&, const QString&, const QString&)
2700 This reimplementation does nothing.
2702 bool QXmlDefaultHandler::internalEntityDecl(const QString&, const QString&)
2710 This reimplementation does nothing.
2712 bool QXmlDefaultHandler::externalEntityDecl(const QString&, const QString&, const QString&)
2718 /*********************************************
2720 * QXmlSimpleReaderPrivate
2722 *********************************************/
2724 inline bool QXmlSimpleReaderPrivate::atEnd()
2726 return (c.unicode()|0x0001) == 0xffff;
2729 inline void QXmlSimpleReaderPrivate::stringClear()
2731 stringValueLen = 0; stringArrayPos = 0;
2733 inline void QXmlSimpleReaderPrivate::nameClear()
2735 nameValueLen = 0; nameArrayPos = 0;
2738 inline void QXmlSimpleReaderPrivate::refClear()
2740 refValueLen = 0; refArrayPos = 0;
2743 QXmlSimpleReaderPrivate::QXmlSimpleReaderPrivate(QXmlSimpleReader *reader)
2748 locator.reset(new QXmlSimpleReaderLocator(reader));
2756 // default feature settings
2757 useNamespaces = true;
2758 useNamespacePrefixes = false;
2759 reportWhitespaceCharData = true;
2760 reportEntities = false;
2763 QXmlSimpleReaderPrivate::~QXmlSimpleReaderPrivate()
2768 void QXmlSimpleReaderPrivate::initIncrementalParsing()
2771 parseStack->clear();
2773 parseStack = new QStack<ParseState>;
2776 /*********************************************
2780 *********************************************/
2785 \brief The QXmlReader class provides an interface for XML readers (i.e.
2791 This abstract class provides an interface for all of Qt's XML
2792 readers. Currently there is only one implementation of a reader
2793 included in Qt's XML module: QXmlSimpleReader. In future releases
2794 there might be more readers with different properties available
2795 (e.g. a validating parser).
2797 The design of the XML classes follows the \link
2798 http://www.saxproject.org/ SAX2 Java interface\endlink, with
2799 the names adapted to fit Qt naming conventions. It should be very
2800 easy for anybody who has worked with SAX2 to get started with the
2803 All readers use the class QXmlInputSource to read the input
2804 document. Since you are normally interested in particular content
2805 in the XML document, the reader reports the content through
2806 special handler classes (QXmlDTDHandler, QXmlDeclHandler,
2807 QXmlContentHandler, QXmlEntityResolver, QXmlErrorHandler and
2808 QXmlLexicalHandler), which you must subclass, if you want to
2809 process the contents.
2811 Since the handler classes only describe interfaces you must
2812 implement all the functions. We provide the QXmlDefaultHandler
2813 class to make this easier: it implements a default behavior (do
2814 nothing) for all functions, so you can subclass it and just
2815 implement the functions you are interested in.
2817 Features and properties of the reader can be set with setFeature()
2818 and setProperty() respectively. You can set the reader to use your
2819 own subclasses with setEntityResolver(), setDTDHandler(),
2820 setContentHandler(), setErrorHandler(), setLexicalHandler() and
2821 setDeclHandler(). The parse itself is started with a call to
2824 \sa QXmlSimpleReader
2828 \fn QXmlReader::~QXmlReader()
2830 Destroys the reader.
2834 \fn bool QXmlReader::feature(const QString& name, bool *ok) const
2836 If the reader has the feature called \a name, the feature's value
2837 is returned. If no such feature exists the return value is
2840 If \a ok is not 0: \c{*}\a{ok} is set to true if the reader has the
2841 feature called \a name; otherwise \c{*}\a{ok} is set to false.
2843 \sa setFeature(), hasFeature()
2847 \fn void QXmlReader::setFeature(const QString& name, bool value)
2849 Sets the feature called \a name to the given \a value. If the
2850 reader doesn't have the feature nothing happens.
2852 \sa feature(), hasFeature()
2856 \fn bool QXmlReader::hasFeature(const QString& name) const
2858 Returns \c true if the reader has the feature called \a name;
2859 otherwise returns false.
2861 \sa feature(), setFeature()
2865 \fn void* QXmlReader::property(const QString& name, bool *ok) const
2867 If the reader has the property \a name, this function returns the
2868 value of the property; otherwise the return value is undefined.
2870 If \a ok is not 0: if the reader has the \a name property
2871 \c{*}\a{ok} is set to true; otherwise \c{*}\a{ok} is set to false.
2873 \sa setProperty(), hasProperty()
2877 \fn void QXmlReader::setProperty(const QString& name, void* value)
2879 Sets the property \a name to \a value. If the reader doesn't have
2880 the property nothing happens.
2882 \sa property(), hasProperty()
2886 \fn bool QXmlReader::hasProperty(const QString& name) const
2888 Returns true if the reader has the property \a name; otherwise
2891 \sa property(), setProperty()
2895 \fn void QXmlReader::setEntityResolver(QXmlEntityResolver* handler)
2897 Sets the entity resolver to \a handler.
2899 \sa entityResolver()
2903 \fn QXmlEntityResolver* QXmlReader::entityResolver() const
2905 Returns the entity resolver or 0 if none was set.
2907 \sa setEntityResolver()
2911 \fn void QXmlReader::setDTDHandler(QXmlDTDHandler* handler)
2913 Sets the DTD handler to \a handler.
2919 \fn QXmlDTDHandler* QXmlReader::DTDHandler() const
2921 Returns the DTD handler or 0 if none was set.
2927 \fn void QXmlReader::setContentHandler(QXmlContentHandler* handler)
2929 Sets the content handler to \a handler.
2931 \sa contentHandler()
2935 \fn QXmlContentHandler* QXmlReader::contentHandler() const
2937 Returns the content handler or 0 if none was set.
2939 \sa setContentHandler()
2943 \fn void QXmlReader::setErrorHandler(QXmlErrorHandler* handler)
2945 Sets the error handler to \a handler. Clears the error handler if
2952 \fn QXmlErrorHandler* QXmlReader::errorHandler() const
2954 Returns the error handler or 0 if none is set.
2956 \sa setErrorHandler()
2960 \fn void QXmlReader::setLexicalHandler(QXmlLexicalHandler* handler)
2962 Sets the lexical handler to \a handler.
2964 \sa lexicalHandler()
2968 \fn QXmlLexicalHandler* QXmlReader::lexicalHandler() const
2970 Returns the lexical handler or 0 if none was set.
2972 \sa setLexicalHandler()
2976 \fn void QXmlReader::setDeclHandler(QXmlDeclHandler* handler)
2978 Sets the declaration handler to \a handler.
2984 \fn QXmlDeclHandler* QXmlReader::declHandler() const
2986 Returns the declaration handler or 0 if none was set.
2988 \sa setDeclHandler()
2992 \fn bool QXmlReader::parse(const QXmlInputSource &input)
2996 Parses the given \a input.
3000 \fn bool QXmlReader::parse(const QXmlInputSource *input)
3002 Reads an XML document from \a input and parses it. Returns true if
3003 the parsing was successful; otherwise returns false.
3008 \class QXmlSimpleReader
3010 \brief The QXmlSimpleReader class provides an implementation of a
3017 This XML reader is suitable for a wide range of applications. It
3018 is able to parse well-formed XML and can report the namespaces of
3019 elements to a content handler; however, it does not parse any
3020 external entities. For historical reasons, Attribute Value
3021 Normalization and End-of-Line Handling as described in the XML 1.0
3022 specification is not performed.
3024 The easiest pattern of use for this class is to create a reader
3025 instance, define an input source, specify the handlers to be used
3026 by the reader, and parse the data.
3028 For example, we could use a QFile to supply the input. Here, we
3029 create a reader, and define an input source to be used by the
3032 \snippet doc/src/snippets/xml/simpleparse/main.cpp 0
3034 A handler lets us perform actions when the reader encounters
3035 certain types of content, or if errors in the input are found. The
3036 reader must be told which handler to use for each type of
3037 event. For many common applications, we can create a custom
3038 handler by subclassing QXmlDefaultHandler, and use this to handle
3039 both error and content events:
3041 \snippet doc/src/snippets/xml/simpleparse/main.cpp 1
3043 If you don't set at least the content and error handlers, the
3044 parser will fall back on its default behavior---and will do
3047 The most convenient way to handle the input is to read it in a
3048 single pass using the parse() function with an argument that
3049 specifies the input source:
3051 \snippet doc/src/snippets/xml/simpleparse/main.cpp 2
3053 If you can't parse the entire input in one go (for example, it is
3054 huge, or is being delivered over a network connection), data can
3055 be fed to the parser in pieces. This is achieved by telling
3056 parse() to work incrementally, and making subsequent calls to the
3057 parseContinue() function, until all the data has been processed.
3059 A common way to perform incremental parsing is to connect the \c
3060 readyRead() signal of a \l{QNetworkReply} {network reply} a slot,
3061 and handle the incoming data there. See QNetworkAccessManager.
3063 Aspects of the parsing behavior can be adapted using setFeature()
3066 \snippet doc/src/snippets/code/src_xml_sax_qxml.cpp 0
3068 QXmlSimpleReader is not reentrant. If you want to use the class
3069 in threaded code, lock the code using QXmlSimpleReader with a
3070 locking mechanism, such as a QMutex.
3073 static inline bool is_S(QChar ch)
3075 ushort uc = ch.unicode();
3076 return (uc == ' ' || uc == '\t' || uc == '\n' || uc == '\r');
3079 enum NameChar { NameBeginning, NameNotBeginning, NotName };
3081 static const char Begi = (char)NameBeginning;
3082 static const char NtBg = (char)NameNotBeginning;
3083 static const char NotN = (char)NotName;
3085 static const char nameCharTable[128] =
3088 NotN, NotN, NotN, NotN, NotN, NotN, NotN, NotN,
3089 NotN, NotN, NotN, NotN, NotN, NotN, NotN, NotN,
3091 NotN, NotN, NotN, NotN, NotN, NotN, NotN, NotN,
3092 NotN, NotN, NotN, NotN, NotN, NotN, NotN, NotN,
3093 // 0x20 (0x2D is '-', 0x2E is '.')
3094 NotN, NotN, NotN, NotN, NotN, NotN, NotN, NotN,
3095 NotN, NotN, NotN, NotN, NotN, NtBg, NtBg, NotN,
3096 // 0x30 (0x30..0x39 are '0'..'9', 0x3A is ':')
3097 NtBg, NtBg, NtBg, NtBg, NtBg, NtBg, NtBg, NtBg,
3098 NtBg, NtBg, Begi, NotN, NotN, NotN, NotN, NotN,
3099 // 0x40 (0x41..0x5A are 'A'..'Z')
3100 NotN, Begi, Begi, Begi, Begi, Begi, Begi, Begi,
3101 Begi, Begi, Begi, Begi, Begi, Begi, Begi, Begi,
3102 // 0x50 (0x5F is '_')
3103 Begi, Begi, Begi, Begi, Begi, Begi, Begi, Begi,
3104 Begi, Begi, Begi, NotN, NotN, NotN, NotN, Begi,
3105 // 0x60 (0x61..0x7A are 'a'..'z')
3106 NotN, Begi, Begi, Begi, Begi, Begi, Begi, Begi,
3107 Begi, Begi, Begi, Begi, Begi, Begi, Begi, Begi,
3109 Begi, Begi, Begi, Begi, Begi, Begi, Begi, Begi,
3110 Begi, Begi, Begi, NotN, NotN, NotN, NotN, NotN
3113 static inline NameChar fastDetermineNameChar(QChar ch)
3115 ushort uc = ch.unicode();
3116 if (!(uc & ~0x7f)) // uc < 128
3117 return (NameChar)nameCharTable[uc];
3119 QChar::Category cat = ch.category();
3120 // ### some these categories might be slightly wrong
3121 if ((cat >= QChar::Letter_Uppercase && cat <= QChar::Letter_Other)
3122 || cat == QChar::Number_Letter)
3123 return NameBeginning;
3124 if ((cat >= QChar::Number_DecimalDigit && cat <= QChar::Number_Other)
3125 || (cat >= QChar::Mark_NonSpacing && cat <= QChar::Mark_Enclosing))
3126 return NameNotBeginning;
3130 static NameChar determineNameChar(QChar ch)
3132 return fastDetermineNameChar(ch);
3136 Constructs a simple XML reader.
3139 QXmlSimpleReader::QXmlSimpleReader()
3140 : d_ptr(new QXmlSimpleReaderPrivate(this))
3145 Destroys the simple XML reader.
3147 QXmlSimpleReader::~QXmlSimpleReader()
3154 bool QXmlSimpleReader::feature(const QString& name, bool *ok) const
3156 const QXmlSimpleReaderPrivate *d = d_func();
3158 // Qt5 ###: Change these strings to qt.nokia.com
3161 if (name == QLatin1String("http://xml.org/sax/features/namespaces")) {
3162 return d->useNamespaces;
3163 } else if (name == QLatin1String("http://xml.org/sax/features/namespace-prefixes")) {
3164 return d->useNamespacePrefixes;
3165 } else if (name == QLatin1String("http://trolltech.com/xml/features/report-whitespace-only-CharData")) { // Shouldn't change in Qt 4
3166 return d->reportWhitespaceCharData;
3167 } else if (name == QLatin1String("http://trolltech.com/xml/features/report-start-end-entity")) { // Shouldn't change in Qt 4
3168 return d->reportEntities;
3170 qWarning("Unknown feature %s", name.toLatin1().data());
3178 Turns on the feature \a name if \a enable is true; otherwise turns it off.
3180 The \a name parameter must be one of the following strings:
3182 \header \i Feature \i Default \i Notes
3183 \row \i \e http://xml.org/sax/features/namespaces
3185 \i If enabled, namespaces are reported to the content handler.
3186 \row \i \e http://xml.org/sax/features/namespace-prefixes
3188 \i If enabled, the original prefixed names
3189 and attributes used for namespace declarations are
3191 \row \i \e http://trolltech.com/xml/features/report-whitespace-only-CharData
3193 \i If enabled, CharData that consist of
3194 only whitespace characters are reported
3195 using QXmlContentHandler::characters(). If disabled, whitespace is silently
3197 \row \i \e http://trolltech.com/xml/features/report-start-end-entity
3199 \i If enabled, the parser reports
3200 QXmlContentHandler::startEntity() and
3201 QXmlContentHandler::endEntity() events, so character data
3202 might be reported in chunks.
3203 If disabled, the parser does not report these events, but
3204 silently substitutes the entities, and reports the character
3208 \sa feature(), hasFeature(), {SAX2 Features}
3210 void QXmlSimpleReader::setFeature(const QString& name, bool enable)
3212 Q_D(QXmlSimpleReader);
3213 // Qt5 ###: Change these strings to qt.nokia.com
3214 if (name == QLatin1String("http://xml.org/sax/features/namespaces")) {
3215 d->useNamespaces = enable;
3216 } else if (name == QLatin1String("http://xml.org/sax/features/namespace-prefixes")) {
3217 d->useNamespacePrefixes = enable;
3218 } else if (name == QLatin1String("http://trolltech.com/xml/features/report-whitespace-only-CharData")) { // Shouldn't change in Qt 4
3219 d->reportWhitespaceCharData = enable;
3220 } else if (name == QLatin1String("http://trolltech.com/xml/features/report-start-end-entity")) { // Shouldn't change in Qt 4
3221 d->reportEntities = enable;
3223 qWarning("Unknown feature %s", name.toLatin1().data());
3229 bool QXmlSimpleReader::hasFeature(const QString& name) const
3231 // Qt5 ###: Change these strings to qt.nokia.com
3232 if (name == QLatin1String("http://xml.org/sax/features/namespaces")
3233 || name == QLatin1String("http://xml.org/sax/features/namespace-prefixes")
3234 || name == QLatin1String("http://trolltech.com/xml/features/report-whitespace-only-CharData") // Shouldn't change in Qt 4
3235 || name == QLatin1String("http://trolltech.com/xml/features/report-start-end-entity")) { // Shouldn't change in Qt 4
3244 void* QXmlSimpleReader::property(const QString&, bool *ok) const
3253 void QXmlSimpleReader::setProperty(const QString&, void*)
3260 bool QXmlSimpleReader::hasProperty(const QString&) const
3268 void QXmlSimpleReader::setEntityResolver(QXmlEntityResolver* handler)
3270 Q_D(QXmlSimpleReader);
3271 d->entityRes = handler;
3277 QXmlEntityResolver* QXmlSimpleReader::entityResolver() const
3279 const QXmlSimpleReaderPrivate *d = d_func();
3280 return d->entityRes;
3286 void QXmlSimpleReader::setDTDHandler(QXmlDTDHandler* handler)
3288 Q_D(QXmlSimpleReader);
3289 d->dtdHnd = handler;
3295 QXmlDTDHandler* QXmlSimpleReader::DTDHandler() const
3297 const QXmlSimpleReaderPrivate *d = d_func();
3304 void QXmlSimpleReader::setContentHandler(QXmlContentHandler* handler)
3306 Q_D(QXmlSimpleReader);
3307 d->contentHnd = handler;
3313 QXmlContentHandler* QXmlSimpleReader::contentHandler() const
3315 const QXmlSimpleReaderPrivate *d = d_func();
3316 return d->contentHnd;
3322 void QXmlSimpleReader::setErrorHandler(QXmlErrorHandler* handler)
3324 Q_D(QXmlSimpleReader);
3325 d->errorHnd = handler;
3331 QXmlErrorHandler* QXmlSimpleReader::errorHandler() const
3333 const QXmlSimpleReaderPrivate *d = d_func();
3340 void QXmlSimpleReader::setLexicalHandler(QXmlLexicalHandler* handler)
3342 Q_D(QXmlSimpleReader);
3343 d->lexicalHnd = handler;
3349 QXmlLexicalHandler* QXmlSimpleReader::lexicalHandler() const
3351 const QXmlSimpleReaderPrivate *d = d_func();
3352 return d->lexicalHnd;
3358 void QXmlSimpleReader::setDeclHandler(QXmlDeclHandler* handler)
3360 Q_D(QXmlSimpleReader);
3361 d->declHnd = handler;
3367 QXmlDeclHandler* QXmlSimpleReader::declHandler() const
3369 const QXmlSimpleReaderPrivate *d = d_func();
3378 bool QXmlSimpleReader::parse(const QXmlInputSource& input)
3380 return parse(&input, false);
3384 Reads an XML document from \a input and parses it in one pass (non-incrementally).
3385 Returns true if the parsing was successful; otherwise returns false.
3387 bool QXmlSimpleReader::parse(const QXmlInputSource* input)
3389 return parse(input, false);
3393 Reads an XML document from \a input and parses it. Returns true
3394 if the parsing is completed successfully; otherwise returns false,
3395 indicating that an error occurred.
3397 If \a incremental is false, this function will return false if the XML
3398 file is not read completely. The parsing cannot be continued in this
3401 If \a incremental is true, the parser does not return false if
3402 it reaches the end of the \a input before reaching the end
3403 of the XML file. Instead, it stores the state of the parser so that
3404 parsing can be continued later when more data is available.
3405 In such a case, you can use the function parseContinue() to
3406 continue with parsing. This class stores a pointer to the input
3407 source \a input and the parseContinue() function tries to read from
3408 that input source. Therefore, you should not delete the input
3409 source \a input until you no longer need to call parseContinue().
3411 If this function is called with \a incremental set to true
3412 while an incremental parse is in progress, a new parsing
3413 session will be started, and the previous session will be lost.
3415 \sa parseContinue(), QTcpSocket
3417 bool QXmlSimpleReader::parse(const QXmlInputSource *input, bool incremental)
3419 Q_D(QXmlSimpleReader);
3422 d->initIncrementalParsing();
3424 delete d->parseStack;
3430 if (d->contentHnd) {
3431 d->contentHnd->setDocumentLocator(d->locator.data());
3432 if (!d->contentHnd->startDocument()) {
3433 d->reportParseError(d->contentHnd->errorString());
3438 qt_xml_skipped_entity_in_content = false;
3439 return d->parseBeginOrContinue(0, incremental);
3443 Continues incremental parsing, taking input from the
3444 QXmlInputSource that was specified with the most recent
3445 call to parse(). To use this function, you \e must have called
3446 parse() with the incremental argument set to true.
3448 Returns false if a parsing error occurs; otherwise returns true,
3449 even if the end of the XML file has not been reached. You can
3450 continue parsing at a later stage by calling this function again
3451 when there is more data available to parse.
3453 Calling this function when there is no data available in the input
3454 source indicates to the reader that the end of the XML file has
3455 been reached. If the input supplied up to this point was
3456 not well-formed then a parsing error occurs, and false is returned.
3457 If the input supplied was well-formed, true is returned.
3458 It is important to end the input in this way because it allows you
3459 to reuse the reader to parse other XML files.
3461 Calling this function after the end of file has been reached, but
3462 without available data will cause false to be returned whether the
3463 previous input was well-formed or not.
3465 \sa parse(), QXmlInputSource::data(), QXmlInputSource::next()
3467 bool QXmlSimpleReader::parseContinue()
3469 Q_D(QXmlSimpleReader);
3470 if (d->parseStack == 0 || d->parseStack->isEmpty())
3473 int state = d->parseStack->pop().state;
3474 return d->parseBeginOrContinue(state, true);
3478 Common part of parse() and parseContinue()
3480 bool QXmlSimpleReaderPrivate::parseBeginOrContinue(int state, bool incremental)
3482 bool atEndOrig = atEnd();
3485 if (!parseProlog()) {
3486 if (incremental && error.isNull()) {
3487 pushParseState(0, 0);
3497 if (!parseElement()) {
3498 if (incremental && error.isNull()) {
3499 pushParseState(0, 1);
3511 if (incremental && error.isNull()) {
3512 pushParseState(0, 2);
3520 if (!atEndOrig && incremental) {
3521 // we parsed something at all, so be prepared to come back later
3522 pushParseState(0, 2);
3526 if (!tags.isEmpty() && !error.isNull()) {
3527 reportParseError(QLatin1String(XMLERR_UNEXPECTEDEOF));
3535 if (!contentHnd->endDocument()) {
3536 reportParseError(contentHnd->errorString());
3544 // The following private parse functions have another semantics for the return
3545 // value: They return true iff parsing has finished successfully (i.e. the end
3546 // of the XML file must be reached!). If one of these functions return false,
3547 // there is only an error when d->error.isNULL() is also false.
3551 For the incremental parsing, it is very important that the parse...()
3552 functions have a certain structure. Since it might be hard to understand how
3553 they work, here is a description of the layout of these functions:
3555 bool QXmlSimpleReader::parse...()
3557 (1) const signed char Init = 0;
3560 (2) const signed char Inp... = 0;
3563 (3) static const signed char table[3][2] = {
3569 (4) if (d->parseStack == 0 || d->parseStack->isEmpty()) {
3576 (5) switch (state) {
3582 unexpectedEof(&QXmlSimpleReader::parseNmtoken, state);
3585 (6b) if (determineNameChar(c) != NotName) {
3588 (7) state = table[state][input];
3590 (8) switch (state) {
3597 ad 1: constants for the states (used in the transition table)
3598 ad 2: constants for the input (used in the transition table)
3599 ad 3: the transition table for the state machine
3600 ad 4: test if we are in a parseContinue() step
3601 a) if no, do inititalizations
3602 b) if yes, restore the state and call parse functions recursively
3603 ad 5: Do some actions according to the state; from the logical execution
3604 order, this code belongs after 8 (see there for an explanation)
3605 ad 6: Check the character that is at the actual "cursor" position:
3606 a) If we reached the EOF, report either error or push the state (in the
3607 case of incremental parsing).
3608 b) Otherwise, set the input character constant for the transition
3610 ad 7: Get the new state according to the input that was read.
3611 ad 8: Do some actions according to the state. The last line in every case
3612 statement reads new data (i.e. it move the cursor). This can also be
3613 done by calling another parse...() function. If you need processing for
3614 this state after that, you have to put it into the switch statement 5.
3615 This ensures that you have a well defined re-entry point, when you ran
3620 Parses the prolog [22].
3623 bool QXmlSimpleReaderPrivate::parseProlog()
3625 const signed char Init = 0;
3626 const signed char EatWS = 1; // eat white spaces
3627 const signed char Lt = 2; // '<' read
3628 const signed char Em = 3; // '!' read
3629 const signed char DocType = 4; // read doctype
3630 const signed char Comment = 5; // read comment
3631 const signed char CommentR = 6; // same as Comment, but already reported
3632 const signed char PInstr = 7; // read PI
3633 const signed char PInstrR = 8; // same as PInstr, but already reported
3634 const signed char Done = 9;
3636 const signed char InpWs = 0;
3637 const signed char InpLt = 1; // <
3638 const signed char InpQm = 2; // ?
3639 const signed char InpEm = 3; // !
3640 const signed char InpD = 4; // D
3641 const signed char InpDash = 5; // -
3642 const signed char InpUnknown = 6;
3644 static const signed char table[9][7] = {
3645 /* InpWs InpLt InpQm InpEm InpD InpDash InpUnknown */
3646 { EatWS, Lt, -1, -1, -1, -1, -1 }, // Init
3647 { -1, Lt, -1, -1, -1, -1, -1 }, // EatWS
3648 { -1, -1, PInstr,Em, Done, -1, Done }, // Lt
3649 { -1, -1, -1, -1, DocType, Comment, -1 }, // Em
3650 { EatWS, Lt, -1, -1, -1, -1, -1 }, // DocType
3651 { EatWS, Lt, -1, -1, -1, -1, -1 }, // Comment
3652 { EatWS, Lt, -1, -1, -1, -1, -1 }, // CommentR
3653 { EatWS, Lt, -1, -1, -1, -1, -1 }, // PInstr
3654 { EatWS, Lt, -1, -1, -1, -1, -1 } // PInstrR
3659 if (parseStack == 0 || parseStack->isEmpty()) {
3660 xmldecl_possible = true;
3661 doctype_read = false;
3664 state = parseStack->pop().state;
3665 #if defined(QT_QXML_DEBUG)
3666 qDebug("QXmlSimpleReader: parseProlog (cont) in state %d", state);
3668 if (!parseStack->isEmpty()) {
3669 ParseFunction function = parseStack->top().function;
3670 if (function == &QXmlSimpleReaderPrivate::eat_ws) {
3672 #if defined(QT_QXML_DEBUG)
3673 qDebug("QXmlSimpleReader: eat_ws (cont)");
3676 if (!(this->*function)()) {
3677 parseFailed(&QXmlSimpleReaderPrivate::parseProlog, state);
3687 reportParseError(QLatin1String(XMLERR_MORETHANONEDOCTYPE));
3690 doctype_read = false;
3695 if (!lexicalHnd->comment(string())) {
3696 reportParseError(lexicalHnd->errorString());
3705 if (xmldecl_possible && !xmlVersion.isEmpty()) {
3706 QString value(QLatin1String("version='"));
3707 value += xmlVersion;
3708 value += QLatin1Char('\'');
3709 if (!encoding.isEmpty()) {
3710 value += QLatin1String(" encoding='");
3712 value += QLatin1Char('\'');
3714 if (standalone == QXmlSimpleReaderPrivate::Yes) {
3715 value += QLatin1String(" standalone='yes'");
3716 } else if (standalone == QXmlSimpleReaderPrivate::No) {
3717 value += QLatin1String(" standalone='no'");
3719 if (!contentHnd->processingInstruction(QLatin1String("xml"), value)) {
3720 reportParseError(contentHnd->errorString());
3724 if (!contentHnd->processingInstruction(name(), string())) {
3725 reportParseError(contentHnd->errorString());
3730 // XML declaration only on first position possible
3731 xmldecl_possible = false;
3737 reportParseError(QLatin1String(XMLERR_ERRORPARSINGELEMENT));
3742 unexpectedEof(&QXmlSimpleReaderPrivate::parseProlog, state);
3747 } else if (c == QLatin1Char('<')) {
3749 } else if (c == QLatin1Char('?')) {
3751 } else if (c == QLatin1Char('!')) {
3753 } else if (c == QLatin1Char('D')) {
3755 } else if (c == QLatin1Char('-')) {
3760 state = table[state][input];
3764 // XML declaration only on first position possible
3765 xmldecl_possible = false;
3767 parseFailed(&QXmlSimpleReaderPrivate::parseProlog, state);
3775 // XML declaration only on first position possible
3776 xmldecl_possible = false;
3780 if (!parseDoctype()) {
3781 parseFailed(&QXmlSimpleReaderPrivate::parseProlog, state);
3787 if (!parseComment()) {
3788 parseFailed(&QXmlSimpleReaderPrivate::parseProlog, state);
3794 parsePI_xmldecl = xmldecl_possible;
3796 parseFailed(&QXmlSimpleReaderPrivate::parseProlog, state);
3806 Parse an element [39].
3808 Precondition: the opening '<' is already read.
3810 bool QXmlSimpleReaderPrivate::parseElement()
3813 const int ReadName = 1;
3815 const int STagEnd = 3;
3816 const int STagEnd2 = 4;
3817 const int ETagBegin = 5;
3818 const int ETagBegin2 = 6;
3820 const int EmptyTag = 8;
3821 const int Attrib = 9;
3822 const int AttribPro = 10; // like Attrib, but processAttribute was already called
3824 const int Done = 12;
3826 const int InpWs = 0; // whitespace
3827 const int InpNameBe = 1; // NameBeginning
3828 const int InpGt = 2; // >
3829 const int InpSlash = 3; // /
3830 const int InpUnknown = 4;
3832 static const int table[12][5] = {
3833 /* InpWs InpNameBe InpGt InpSlash InpUnknown */
3834 { -1, ReadName, -1, -1, -1 }, // Init
3835 { Ws1, Attrib, STagEnd, EmptyTag, -1 }, // ReadName
3836 { -1, Attrib, STagEnd, EmptyTag, -1 }, // Ws1
3837 { STagEnd2, STagEnd2, STagEnd2, STagEnd2, STagEnd2 }, // STagEnd
3838 { -1, -1, -1, ETagBegin, -1 }, // STagEnd2
3839 { -1, ETagBegin2, -1, -1, -1 }, // ETagBegin
3840 { Ws2, -1, Done, -1, -1 }, // ETagBegin2
3841 { -1, -1, Done, -1, -1 }, // Ws2
3842 { -1, -1, Done, -1, -1 }, // EmptyTag
3843 { Ws3, Attrib, STagEnd, EmptyTag, -1 }, // Attrib
3844 { Ws3, Attrib, STagEnd, EmptyTag, -1 }, // AttribPro
3845 { -1, Attrib, STagEnd, EmptyTag, -1 } // Ws3
3850 if (parseStack == 0 || parseStack->isEmpty()) {
3853 state = parseStack->pop().state;
3854 #if defined(QT_QXML_DEBUG)
3855 qDebug("QXmlSimpleReader: parseElement (cont) in state %d", state);
3857 if (!parseStack->isEmpty()) {
3858 ParseFunction function = parseStack->top().function;
3859 if (function == &QXmlSimpleReaderPrivate::eat_ws) {
3861 #if defined(QT_QXML_DEBUG)
3862 qDebug("QXmlSimpleReader: eat_ws (cont)");
3865 if (!(this->*function)()) {
3866 parseFailed(&QXmlSimpleReaderPrivate::parseElement, state);
3875 // store it on the stack
3877 // empty the attributes
3880 namespaceSupport.pushContext();
3883 if (!processElementETagBegin2())
3887 if (!processElementAttribute())
3894 reportParseError(QLatin1String(XMLERR_ERRORPARSINGELEMENT));
3899 unexpectedEof(&QXmlSimpleReaderPrivate::parseElement, state);
3902 if (fastDetermineNameChar(c) == NameBeginning) {
3904 } else if (c == QLatin1Char('>')) {
3906 } else if (is_S(c)) {
3908 } else if (c == QLatin1Char('/')) {
3913 state = table[state][input];
3917 parseName_useRef = false;
3919 parseFailed(&QXmlSimpleReaderPrivate::parseElement, state);
3927 parseFailed(&QXmlSimpleReaderPrivate::parseElement, state);
3934 const QString &tagsTop = tags.top();
3935 if (useNamespaces) {
3937 namespaceSupport.processName(tagsTop, false, uri, lname);
3938 if (!contentHnd->startElement(uri, lname, tagsTop, attList)) {
3939 reportParseError(contentHnd->errorString());
3943 if (!contentHnd->startElement(QString(), QString(), tagsTop, attList)) {
3944 reportParseError(contentHnd->errorString());
3952 if (!parseContent()) {
3953 parseFailed(&QXmlSimpleReaderPrivate::parseElement, state);
3961 // get the name of the tag
3962 parseName_useRef = false;
3964 parseFailed(&QXmlSimpleReaderPrivate::parseElement, state);
3969 if (tags.isEmpty()) {
3970 reportParseError(QLatin1String(XMLERR_TAGMISMATCH));
3973 if (!processElementEmptyTag())
3979 // get name and value of attribute
3980 if (!parseAttribute()) {
3981 parseFailed(&QXmlSimpleReaderPrivate::parseElement, state);
3994 Helper to break down the size of the code in the case statement.
3995 Return false on error, otherwise true.
3997 bool QXmlSimpleReaderPrivate::processElementEmptyTag()
4000 // pop the stack and call the handler
4002 if (useNamespaces) {
4003 // report startElement first...
4004 namespaceSupport.processName(tags.top(), false, uri, lname);
4005 if (!contentHnd->startElement(uri, lname, tags.top(), attList)) {
4006 reportParseError(contentHnd->errorString());
4009 // ... followed by endElement...
4010 if (!contentHnd->endElement(uri, lname, tags.pop())) {
4011 reportParseError(contentHnd->errorString());
4014 // ... followed by endPrefixMapping
4015 QStringList prefixesBefore, prefixesAfter;
4017 prefixesBefore = namespaceSupport.prefixes();
4019 namespaceSupport.popContext();
4020 // call the handler for prefix mapping
4021 prefixesAfter = namespaceSupport.prefixes();
4022 for (QStringList::Iterator it = prefixesBefore.begin(); it != prefixesBefore.end(); ++it) {
4023 if (!prefixesAfter.contains(*it)) {
4024 if (!contentHnd->endPrefixMapping(*it)) {
4025 reportParseError(contentHnd->errorString());
4031 // report startElement first...
4032 if (!contentHnd->startElement(QString(), QString(), tags.top(), attList)) {
4033 reportParseError(contentHnd->errorString());
4036 // ... followed by endElement
4037 if (!contentHnd->endElement(QString(), QString(), tags.pop())) {
4038 reportParseError(contentHnd->errorString());
4044 namespaceSupport.popContext();
4049 Helper to break down the size of the code in the case statement.
4050 Return false on error, otherwise true.
4052 bool QXmlSimpleReaderPrivate::processElementETagBegin2()
4054 const QString &name = QXmlSimpleReaderPrivate::name();
4056 // pop the stack and compare it with the name
4057 if (tags.pop() != name) {
4058 reportParseError(QLatin1String(XMLERR_TAGMISMATCH));
4066 namespaceSupport.processName(name, false, uri, lname);
4067 if (!contentHnd->endElement(uri, lname, name)) {
4068 reportParseError(contentHnd->errorString());
4072 if (useNamespaces) {
4073 NamespaceMap prefixesBefore, prefixesAfter;
4075 prefixesBefore = namespaceSupport.d->ns;
4077 namespaceSupport.popContext();
4078 // call the handler for prefix mapping
4080 prefixesAfter = namespaceSupport.d->ns;
4081 if (prefixesBefore.size() != prefixesAfter.size()) {
4082 for (NamespaceMap::const_iterator it = prefixesBefore.constBegin(); it != prefixesBefore.constEnd(); ++it) {
4083 if (!it.key().isEmpty() && !prefixesAfter.contains(it.key())) {
4084 if (!contentHnd->endPrefixMapping(it.key())) {
4085 reportParseError(contentHnd->errorString());
4096 Helper to break down the size of the code in the case statement.
4097 Return false on error, otherwise true.
4099 bool QXmlSimpleReaderPrivate::processElementAttribute()
4101 QString uri, lname, prefix;
4102 const QString &name = QXmlSimpleReaderPrivate::name();
4103 const QString &string = QXmlSimpleReaderPrivate::string();
4105 // add the attribute to the list
4106 if (useNamespaces) {
4107 // is it a namespace declaration?
4108 namespaceSupport.splitName(name, prefix, lname);
4109 if (prefix == QLatin1String("xmlns")) {
4110 // namespace declaration
4111 namespaceSupport.setPrefix(lname, string);
4112 if (useNamespacePrefixes) {
4113 // according to http://www.w3.org/2000/xmlns/, the "prefix"
4114 // xmlns maps to the namespace name
4115 // http://www.w3.org/2000/xmlns/
4116 attList.append(name, QLatin1String("http://www.w3.org/2000/xmlns/"), lname, string);
4118 // call the handler for prefix mapping
4120 if (!contentHnd->startPrefixMapping(lname, string)) {
4121 reportParseError(contentHnd->errorString());
4126 // no namespace delcaration
4127 namespaceSupport.processName(name, true, uri, lname);
4128 attList.append(name, uri, lname, string);
4131 // no namespace support
4132 attList.append(name, uri, lname, string);
4138 Parse a content [43].
4140 A content is only used between tags. If a end tag is found the < is already
4141 read and the head stand on the '/' of the end tag '</name>'.
4143 bool QXmlSimpleReaderPrivate::parseContent()
4145 const signed char Init = 0;
4146 const signed char ChD = 1; // CharData
4147 const signed char ChD1 = 2; // CharData help state
4148 const signed char ChD2 = 3; // CharData help state
4149 const signed char Ref = 4; // Reference
4150 const signed char Lt = 5; // '<' read
4151 const signed char PInstr = 6; // PI
4152 const signed char PInstrR = 7; // same as PInstr, but already reported
4153 const signed char Elem = 8; // Element
4154 const signed char Em = 9; // '!' read
4155 const signed char Com = 10; // Comment
4156 const signed char ComR = 11; // same as Com, but already reported
4157 const signed char CDS = 12; // CDSect
4158 const signed char CDS1 = 13; // read a CDSect
4159 const signed char CDS2 = 14; // read a CDSect (help state)
4160 const signed char CDS3 = 15; // read a CDSect (help state)
4161 const signed char Done = 16; // finished reading content
4163 const signed char InpLt = 0; // <
4164 const signed char InpGt = 1; // >
4165 const signed char InpSlash = 2; // /
4166 const signed char InpQMark = 3; // ?
4167 const signed char InpEMark = 4; // !
4168 const signed char InpAmp = 5; // &
4169 const signed char InpDash = 6; // -
4170 const signed char InpOpenB = 7; // [
4171 const signed char InpCloseB = 8; //]
4172 const signed char InpUnknown = 9;
4174 static const signed char mapCLT2FSMChar[] = {
4175 InpUnknown, // white space
4189 InpUnknown // unknown
4192 static const signed char table[16][10] = {
4193 /* InpLt InpGt InpSlash InpQMark InpEMark InpAmp InpDash InpOpenB InpCloseB InpUnknown */
4194 { Lt, ChD, ChD, ChD, ChD, Ref, ChD, ChD, ChD1, ChD }, // Init
4195 { Lt, ChD, ChD, ChD, ChD, Ref, ChD, ChD, ChD1, ChD }, // ChD
4196 { Lt, ChD, ChD, ChD, ChD, Ref, ChD, ChD, ChD2, ChD }, // ChD1
4197 { Lt, -1, ChD, ChD, ChD, Ref, ChD, ChD, ChD2, ChD }, // ChD2
4198 { Lt, ChD, ChD, ChD, ChD, Ref, ChD, ChD, ChD, ChD }, // Ref (same as Init)
4199 { -1, -1, Done, PInstr, Em, -1, -1, -1, -1, Elem }, // Lt
4200 { Lt, ChD, ChD, ChD, ChD, Ref, ChD, ChD, ChD, ChD }, // PInstr (same as Init)
4201 { Lt, ChD, ChD, ChD, ChD, Ref, ChD, ChD, ChD, ChD }, // PInstrR
4202 { Lt, ChD, ChD, ChD, ChD, Ref, ChD, ChD, ChD, ChD }, // Elem (same as Init)
4203 { -1, -1, -1, -1, -1, -1, Com, CDS, -1, -1 }, // Em
4204 { Lt, ChD, ChD, ChD, ChD, Ref, ChD, ChD, ChD, ChD }, // Com (same as Init)
4205 { Lt, ChD, ChD, ChD, ChD, Ref, ChD, ChD, ChD, ChD }, // ComR
4206 { CDS1, CDS1, CDS1, CDS1, CDS1, CDS1, CDS1, CDS1, CDS2, CDS1 }, // CDS
4207 { CDS1, CDS1, CDS1, CDS1, CDS1, CDS1, CDS1, CDS1, CDS2, CDS1 }, // CDS1
4208 { CDS1, CDS1, CDS1, CDS1, CDS1, CDS1, CDS1, CDS1, CDS3, CDS1 }, // CDS2
4209 { CDS1, Init, CDS1, CDS1, CDS1, CDS1, CDS1, CDS1, CDS3, CDS1 } // CDS3
4214 if (parseStack == 0 || parseStack->isEmpty()) {
4215 contentCharDataRead = false;
4218 state = parseStack->pop().state;
4219 #if defined(QT_QXML_DEBUG)
4220 qDebug("QXmlSimpleReader: parseContent (cont) in state %d", state);
4222 if (!parseStack->isEmpty()) {
4223 ParseFunction function = parseStack->top().function;
4224 if (function == &QXmlSimpleReaderPrivate::eat_ws) {
4226 #if defined(QT_QXML_DEBUG)
4227 qDebug("QXmlSimpleReader: eat_ws (cont)");
4230 if (!(this->*function)()) {
4231 parseFailed(&QXmlSimpleReaderPrivate::parseContent, state);
4240 if (!contentCharDataRead)
4241 contentCharDataRead = parseReference_charDataRead;
4245 if (!contentHnd->processingInstruction(name(),string())) {
4246 reportParseError(contentHnd->errorString());
4254 if (!lexicalHnd->comment(string())) {
4255 reportParseError(lexicalHnd->errorString());
4265 if (!atEnd() && c != QLatin1Char(']'))
4266 stringAddC(QLatin1Char(']'));
4269 // test if this skipping was legal
4271 if (c == QLatin1Char('>')) {
4272 // the end of the CDSect
4274 if (!lexicalHnd->startCDATA()) {
4275 reportParseError(lexicalHnd->errorString());
4280 if (!contentHnd->characters(string())) {
4281 reportParseError(contentHnd->errorString());
4286 if (!lexicalHnd->endCDATA()) {
4287 reportParseError(lexicalHnd->errorString());
4291 } else if (c == QLatin1Char(']')) {
4292 // three or more ']'
4293 stringAddC(QLatin1Char(']'));
4295 // after ']]' comes another character
4296 stringAddC(QLatin1Char(']'));
4297 stringAddC(QLatin1Char(']'));
4302 // call the handler for CharData
4304 if (contentCharDataRead) {
4305 if (reportWhitespaceCharData || !string().simplified().isEmpty()) {
4306 if (!contentHnd->characters(string())) {
4307 reportParseError(contentHnd->errorString());
4317 reportParseError(QLatin1String(XMLERR_ERRORPARSINGCONTENT));
4321 // get input (use lookup-table instead of nested ifs for performance
4324 unexpectedEof(&QXmlSimpleReaderPrivate::parseContent, state);
4330 input = mapCLT2FSMChar[charLookupTable[c.cell()]];
4332 state = table[state][input];
4336 // skip the ending '>' of a CDATASection
4340 // on first call: clear string
4341 if (!contentCharDataRead) {
4342 contentCharDataRead = true;
4346 if (reportEntities) {
4347 if (!reportEndEntities())
4353 // on first call: clear string
4354 if (!contentCharDataRead) {
4355 contentCharDataRead = true;
4359 if (reportEntities) {
4360 if (!reportEndEntities())
4367 if (reportEntities) {
4368 if (!reportEndEntities())
4374 if (!contentCharDataRead) {
4375 // reference may be CharData; so clear string to be safe
4377 parseReference_context = InContent;
4378 if (!parseReference()) {
4379 parseFailed(&QXmlSimpleReaderPrivate::parseContent, state);
4383 if (reportEntities) {
4384 // report character data in chunks
4386 if (reportWhitespaceCharData || !string().simplified().isEmpty()) {
4387 if (!contentHnd->characters(string())) {
4388 reportParseError(contentHnd->errorString());
4395 parseReference_context = InContent;
4396 if (!parseReference()) {
4397 parseFailed(&QXmlSimpleReaderPrivate::parseContent, state);
4403 // call the handler for CharData
4405 if (contentCharDataRead) {
4406 if (reportWhitespaceCharData || !string().simplified().isEmpty()) {
4407 if (!contentHnd->characters(string())) {
4408 reportParseError(contentHnd->errorString());
4414 contentCharDataRead = false;
4419 parsePI_xmldecl = false;
4421 parseFailed(&QXmlSimpleReaderPrivate::parseContent, state);
4426 if (!parseElement()) {
4427 parseFailed(&QXmlSimpleReaderPrivate::parseContent, state);
4436 if (!parseComment()) {
4437 parseFailed(&QXmlSimpleReaderPrivate::parseContent, state);
4442 parseString_s = QLatin1String("[CDATA[");
4443 if (!parseString()) {
4444 parseFailed(&QXmlSimpleReaderPrivate::parseContent, state);
4465 bool QXmlSimpleReaderPrivate::reportEndEntities()
4467 int count = (int)xmlRefStack.count();
4468 while (count != 0 && xmlRefStack.top().isEmpty()) {
4470 if (reportWhitespaceCharData || !string().simplified().isEmpty()) {
4471 if (!contentHnd->characters(string())) {
4472 reportParseError(contentHnd->errorString());
4479 if (!lexicalHnd->endEntity(xmlRefStack.top().name)) {
4480 reportParseError(lexicalHnd->errorString());
4484 xmlRefStack.pop_back();
4493 bool QXmlSimpleReaderPrivate::parseMisc()
4495 const signed char Init = 0;
4496 const signed char Lt = 1; // '<' was read
4497 const signed char Comment = 2; // read comment
4498 const signed char eatWS = 3; // eat whitespaces
4499 const signed char PInstr = 4; // read PI
4500 const signed char Comment2 = 5; // read comment
4502 const signed char InpWs = 0; // S
4503 const signed char InpLt = 1; // <
4504 const signed char InpQm = 2; // ?
4505 const signed char InpEm = 3; // !
4506 const signed char InpUnknown = 4;
4508 static const signed char table[3][5] = {
4509 /* InpWs InpLt InpQm InpEm InpUnknown */
4510 { eatWS, Lt, -1, -1, -1 }, // Init
4511 { -1, -1, PInstr,Comment, -1 }, // Lt
4512 { -1, -1, -1, -1, Comment2 } // Comment
4517 if (parseStack==0 || parseStack->isEmpty()) {
4520 state = parseStack->pop().state;
4521 #if defined(QT_QXML_DEBUG)
4522 qDebug("QXmlSimpleReader: parseMisc (cont) in state %d", state);
4524 if (!parseStack->isEmpty()) {
4525 ParseFunction function = parseStack->top().function;
4526 if (function == &QXmlSimpleReaderPrivate::eat_ws) {
4528 #if defined(QT_QXML_DEBUG)
4529 qDebug("QXmlSimpleReader: eat_ws (cont)");
4532 if (!(this->*function)()) {
4533 parseFailed(&QXmlSimpleReaderPrivate::parseMisc, state);
4545 if (!contentHnd->processingInstruction(name(),string())) {
4546 reportParseError(contentHnd->errorString());
4553 if (!lexicalHnd->comment(string())) {
4554 reportParseError(lexicalHnd->errorString());
4561 reportParseError(QLatin1String(XMLERR_UNEXPECTEDCHARACTER));
4566 unexpectedEof(&QXmlSimpleReaderPrivate::parseMisc, state);
4571 } else if (c == QLatin1Char('<')) {
4573 } else if (c == QLatin1Char('?')) {
4575 } else if (c == QLatin1Char('!')) {
4580 state = table[state][input];
4585 parseFailed(&QXmlSimpleReaderPrivate::parseMisc, state);
4593 parsePI_xmldecl = false;
4595 parseFailed(&QXmlSimpleReaderPrivate::parseMisc, state);
4603 if (!parseComment()) {
4604 parseFailed(&QXmlSimpleReaderPrivate::parseMisc, state);
4614 Parse a processing instruction [16].
4616 If xmldec is true, it tries to parse a PI or a XML declaration [23].
4618 Precondition: the beginning '<' of the PI is already read and the head stand
4621 If this funktion was successful, the head-position is on the first
4622 character after the PI.
4624 bool QXmlSimpleReaderPrivate::parsePI()
4626 const signed char Init = 0;
4627 const signed char QmI = 1; // ? was read
4628 const signed char Name = 2; // read Name
4629 const signed char XMLDecl = 3; // read XMLDecl
4630 const signed char Ws1 = 4; // eat ws after "xml" of XMLDecl
4631 const signed char PInstr = 5; // read PI
4632 const signed char Ws2 = 6; // eat ws after Name of PI
4633 const signed char Version = 7; // read versionInfo
4634 const signed char Ws3 = 8; // eat ws after versionInfo
4635 const signed char EorSD = 9; // read EDecl or SDDecl
4636 const signed char Ws4 = 10; // eat ws after EDecl or SDDecl
4637 const signed char SD = 11; // read SDDecl
4638 const signed char Ws5 = 12; // eat ws after SDDecl
4639 const signed char ADone = 13; // almost done
4640 const signed char Char = 14; // Char was read
4641 const signed char Qm = 15; // Qm was read
4642 const signed char Done = 16; // finished reading content
4644 const signed char InpWs = 0; // whitespace
4645 const signed char InpNameBe = 1; // NameBeginning
4646 const signed char InpGt = 2; // >
4647 const signed char InpQm = 3; // ?
4648 const signed char InpUnknown = 4;
4650 static const signed char table[16][5] = {
4651 /* InpWs, InpNameBe InpGt InpQm InpUnknown */
4652 { -1, -1, -1, QmI, -1 }, // Init
4653 { -1, Name, -1, -1, -1 }, // QmI
4654 { -1, -1, -1, -1, -1 }, // Name (this state is left not through input)
4655 { Ws1, -1, -1, -1, -1 }, // XMLDecl
4656 { -1, Version, -1, -1, -1 }, // Ws1
4657 { Ws2, -1, -1, Qm, -1 }, // PInstr
4658 { Char, Char, Char, Qm, Char }, // Ws2
4659 { Ws3, -1, -1, ADone, -1 }, // Version
4660 { -1, EorSD, -1, ADone, -1 }, // Ws3
4661 { Ws4, -1, -1, ADone, -1 }, // EorSD
4662 { -1, SD, -1, ADone, -1 }, // Ws4
4663 { Ws5, -1, -1, ADone, -1 }, // SD
4664 { -1, -1, -1, ADone, -1 }, // Ws5
4665 { -1, -1, Done, -1, -1 }, // ADone
4666 { Char, Char, Char, Qm, Char }, // Char
4667 { Char, Char, Done, Qm, Char }, // Qm
4672 if (parseStack==0 || parseStack->isEmpty()) {
4675 state = parseStack->pop().state;
4676 #if defined(QT_QXML_DEBUG)
4677 qDebug("QXmlSimpleReader: parsePI (cont) in state %d", state);
4679 if (!parseStack->isEmpty()) {
4680 ParseFunction function = parseStack->top().function;
4681 if (function == &QXmlSimpleReaderPrivate::eat_ws) {
4683 #if defined(QT_QXML_DEBUG)
4684 qDebug("QXmlSimpleReader: eat_ws (cont)");
4687 if (!(this->*function)()) {
4688 parseFailed(&QXmlSimpleReaderPrivate::parsePI, state);
4697 // test what name was read and determine the next state
4698 // (not very beautiful, I admit)
4699 if (name().toLower() == QLatin1String("xml")) {
4700 if (parsePI_xmldecl && name() == QLatin1String("xml")) {
4703 reportParseError(QLatin1String(XMLERR_INVALIDNAMEFORPI));
4712 // get version (syntax like an attribute)
4713 if (name() != QLatin1String("version")) {
4714 reportParseError(QLatin1String(XMLERR_VERSIONEXPECTED));
4717 xmlVersion = string();
4720 // get the EDecl or SDDecl (syntax like an attribute)
4721 if (name() == QLatin1String("standalone")) {
4722 if (string()== QLatin1String("yes")) {
4723 standalone = QXmlSimpleReaderPrivate::Yes;
4724 } else if (string() == QLatin1String("no")) {
4725 standalone = QXmlSimpleReaderPrivate::No;
4727 reportParseError(QLatin1String(XMLERR_WRONGVALUEFORSDECL));
4730 } else if (name() == QLatin1String("encoding")) {
4731 encoding = string();
4733 reportParseError(QLatin1String(XMLERR_EDECLORSDDECLEXPECTED));
4738 if (name() != QLatin1String("standalone")) {
4739 reportParseError(QLatin1String(XMLERR_SDDECLEXPECTED));
4742 if (string() == QLatin1String("yes")) {
4743 standalone = QXmlSimpleReaderPrivate::Yes;
4744 } else if (string() == QLatin1String("no")) {
4745 standalone = QXmlSimpleReaderPrivate::No;
4747 reportParseError(QLatin1String(XMLERR_WRONGVALUEFORSDECL));
4752 // test if the skipping was legal
4753 if (!atEnd() && c != QLatin1Char('>'))
4754 stringAddC(QLatin1Char('?'));
4760 reportParseError(QLatin1String(XMLERR_UNEXPECTEDCHARACTER));
4765 unexpectedEof(&QXmlSimpleReaderPrivate::parsePI, state);
4770 } else if (determineNameChar(c) == NameBeginning) {
4772 } else if (c == QLatin1Char('>')) {
4774 } else if (c == QLatin1Char('?')) {
4779 state = table[state][input];
4786 parseName_useRef = false;
4788 parseFailed(&QXmlSimpleReaderPrivate::parsePI, state);
4798 parseFailed(&QXmlSimpleReaderPrivate::parsePI, state);
4803 if (!parseAttribute()) {
4804 parseFailed(&QXmlSimpleReaderPrivate::parsePI, state);
4809 if (!parseAttribute()) {
4810 parseFailed(&QXmlSimpleReaderPrivate::parsePI, state);
4815 // get the SDDecl (syntax like an attribute)
4816 if (standalone != QXmlSimpleReaderPrivate::Unknown) {
4817 // already parsed the standalone declaration
4818 reportParseError(QLatin1String(XMLERR_UNEXPECTEDCHARACTER));
4821 if (!parseAttribute()) {
4822 parseFailed(&QXmlSimpleReaderPrivate::parsePI, state);
4846 Parse a document type definition (doctypedecl [28]).
4848 Precondition: the beginning '<!' of the doctype is already read the head
4849 stands on the 'D' of '<!DOCTYPE'.
4851 If this function was successful, the head-position is on the first
4852 character after the document type definition.
4854 bool QXmlSimpleReaderPrivate::parseDoctype()
4856 const signed char Init = 0;
4857 const signed char Doctype = 1; // read the doctype
4858 const signed char Ws1 = 2; // eat_ws
4859 const signed char Doctype2 = 3; // read the doctype, part 2
4860 const signed char Ws2 = 4; // eat_ws
4861 const signed char Sys = 5; // read SYSTEM or PUBLIC
4862 const signed char Ws3 = 6; // eat_ws
4863 const signed char MP = 7; // markupdecl or PEReference
4864 const signed char MPR = 8; // same as MP, but already reported
4865 const signed char PER = 9; // PERReference
4866 const signed char Mup = 10; // markupdecl
4867 const signed char Ws4 = 11; // eat_ws
4868 const signed char MPE = 12; // end of markupdecl or PEReference
4869 const signed char Done = 13;
4871 const signed char InpWs = 0;
4872 const signed char InpD = 1; // 'D'
4873 const signed char InpS = 2; // 'S' or 'P'
4874 const signed char InpOB = 3; // [
4875 const signed char InpCB = 4; //]
4876 const signed char InpPer = 5; // %
4877 const signed char InpGt = 6; // >
4878 const signed char InpUnknown = 7;
4880 static const signed char table[13][8] = {
4881 /* InpWs, InpD InpS InpOB InpCB InpPer InpGt InpUnknown */
4882 { -1, Doctype, -1, -1, -1, -1, -1, -1 }, // Init
4883 { Ws1, -1, -1, -1, -1, -1, -1, -1 }, // Doctype
4884 { -1, Doctype2, Doctype2, -1, -1, -1, -1, Doctype2 }, // Ws1
4885 { Ws2, -1, Sys, MP, -1, -1, Done, -1 }, // Doctype2
4886 { -1, -1, Sys, MP, -1, -1, Done, -1 }, // Ws2
4887 { Ws3, -1, -1, MP, -1, -1, Done, -1 }, // Sys
4888 { -1, -1, -1, MP, -1, -1, Done, -1 }, // Ws3
4889 { -1, -1, -1, -1, MPE, PER, -1, Mup }, // MP
4890 { -1, -1, -1, -1, MPE, PER, -1, Mup }, // MPR
4891 { Ws4, -1, -1, -1, MPE, PER, -1, Mup }, // PER
4892 { Ws4, -1, -1, -1, MPE, PER, -1, Mup }, // Mup
4893 { -1, -1, -1, -1, MPE, PER, -1, Mup }, // Ws4
4894 { -1, -1, -1, -1, -1, -1, Done, -1 } // MPE
4899 if (parseStack==0 || parseStack->isEmpty()) {
4900 startDTDwasReported = false;
4905 state = parseStack->pop().state;
4906 #if defined(QT_QXML_DEBUG)
4907 qDebug("QXmlSimpleReader: parseDoctype (cont) in state %d", state);
4909 if (!parseStack->isEmpty()) {
4910 ParseFunction function = parseStack->top().function;
4911 if (function == &QXmlSimpleReaderPrivate::eat_ws) {
4913 #if defined(QT_QXML_DEBUG)
4914 qDebug("QXmlSimpleReader: eat_ws (cont)");
4917 if (!(this->*function)()) {
4918 parseFailed(&QXmlSimpleReaderPrivate::parseDoctype, state);
4930 if (!startDTDwasReported && lexicalHnd ) {
4931 startDTDwasReported = true;
4932 if (!lexicalHnd->startDTD(doctype, publicId, systemId)) {
4933 reportParseError(lexicalHnd->errorString());
4943 reportParseError(QLatin1String(XMLERR_ERRORPARSINGDOCTYPE));
4948 unexpectedEof(&QXmlSimpleReaderPrivate::parseDoctype, state);
4953 } else if (c == QLatin1Char('D')) {
4955 } else if (c == QLatin1Char('S')) {
4957 } else if (c == QLatin1Char('P')) {
4959 } else if (c == QLatin1Char('[')) {
4961 } else if (c == QLatin1Char(']')) {
4963 } else if (c == QLatin1Char('%')) {
4965 } else if (c == QLatin1Char('>')) {
4970 state = table[state][input];
4974 parseString_s = QLatin1String("DOCTYPE");
4975 if (!parseString()) {
4976 parseFailed(&QXmlSimpleReaderPrivate::parseDoctype, state);
4985 parseFailed(&QXmlSimpleReaderPrivate::parseDoctype, state);
4990 parseName_useRef = false;
4992 parseFailed(&QXmlSimpleReaderPrivate::parseDoctype, state);
4997 parseExternalID_allowPublicID = false;
4998 if (!parseExternalID()) {
4999 parseFailed(&QXmlSimpleReaderPrivate::parseDoctype, state);
5002 thisPublicId = publicId;
5003 thisSystemId = systemId;
5007 if (!next_eat_ws()) {
5008 parseFailed(&QXmlSimpleReaderPrivate::parseDoctype, state);
5013 parsePEReference_context = InDTD;
5014 if (!parsePEReference()) {
5015 parseFailed(&QXmlSimpleReaderPrivate::parseDoctype, state);
5020 if (!parseMarkupdecl()) {
5021 parseFailed(&QXmlSimpleReaderPrivate::parseDoctype, state);
5026 if (!next_eat_ws()) {
5027 parseFailed(&QXmlSimpleReaderPrivate::parseDoctype, state);
5033 if (!startDTDwasReported) {
5034 startDTDwasReported = true;
5035 if (!lexicalHnd->startDTD(doctype, publicId, systemId)) {
5036 reportParseError(lexicalHnd->errorString());
5040 if (!lexicalHnd->endDTD()) {
5041 reportParseError(lexicalHnd->errorString());
5053 Parse a ExternalID [75].
5055 If allowPublicID is true parse ExternalID [75] or PublicID [83].
5057 bool QXmlSimpleReaderPrivate::parseExternalID()
5059 const signed char Init = 0;
5060 const signed char Sys = 1; // parse 'SYSTEM'
5061 const signed char SysWS = 2; // parse the whitespace after 'SYSTEM'
5062 const signed char SysSQ = 3; // parse SystemLiteral with '
5063 const signed char SysSQ2 = 4; // parse SystemLiteral with '
5064 const signed char SysDQ = 5; // parse SystemLiteral with "
5065 const signed char SysDQ2 = 6; // parse SystemLiteral with "
5066 const signed char Pub = 7; // parse 'PUBLIC'
5067 const signed char PubWS = 8; // parse the whitespace after 'PUBLIC'
5068 const signed char PubSQ = 9; // parse PubidLiteral with '
5069 const signed char PubSQ2 = 10; // parse PubidLiteral with '
5070 const signed char PubDQ = 11; // parse PubidLiteral with "
5071 const signed char PubDQ2 = 12; // parse PubidLiteral with "
5072 const signed char PubE = 13; // finished parsing the PubidLiteral
5073 const signed char PubWS2 = 14; // parse the whitespace after the PubidLiteral
5074 const signed char PDone = 15; // done if allowPublicID is true
5075 const signed char Done = 16;
5077 const signed char InpSQ = 0; // '
5078 const signed char InpDQ = 1; // "
5079 const signed char InpS = 2; // S
5080 const signed char InpP = 3; // P
5081 const signed char InpWs = 4; // white space
5082 const signed char InpUnknown = 5;
5084 static const signed char table[15][6] = {
5085 /* InpSQ InpDQ InpS InpP InpWs InpUnknown */
5086 { -1, -1, Sys, Pub, -1, -1 }, // Init
5087 { -1, -1, -1, -1, SysWS, -1 }, // Sys
5088 { SysSQ, SysDQ, -1, -1, -1, -1 }, // SysWS
5089 { Done, SysSQ2, SysSQ2, SysSQ2, SysSQ2, SysSQ2 }, // SysSQ
5090 { Done, SysSQ2, SysSQ2, SysSQ2, SysSQ2, SysSQ2 }, // SysSQ2
5091 { SysDQ2, Done, SysDQ2, SysDQ2, SysDQ2, SysDQ2 }, // SysDQ
5092 { SysDQ2, Done, SysDQ2, SysDQ2, SysDQ2, SysDQ2 }, // SysDQ2
5093 { -1, -1, -1, -1, PubWS, -1 }, // Pub
5094 { PubSQ, PubDQ, -1, -1, -1, -1 }, // PubWS
5095 { PubE, -1, PubSQ2, PubSQ2, PubSQ2, PubSQ2 }, // PubSQ
5096 { PubE, -1, PubSQ2, PubSQ2, PubSQ2, PubSQ2 }, // PubSQ2
5097 { -1, PubE, PubDQ2, PubDQ2, PubDQ2, PubDQ2 }, // PubDQ
5098 { -1, PubE, PubDQ2, PubDQ2, PubDQ2, PubDQ2 }, // PubDQ2
5099 { PDone, PDone, PDone, PDone, PubWS2, PDone }, // PubE
5100 { SysSQ, SysDQ, PDone, PDone, PDone, PDone } // PubWS2
5105 if (parseStack==0 || parseStack->isEmpty()) {
5110 state = parseStack->pop().state;
5111 #if defined(QT_QXML_DEBUG)
5112 qDebug("QXmlSimpleReader: parseExternalID (cont) in state %d", state);
5114 if (!parseStack->isEmpty()) {
5115 ParseFunction function = parseStack->top().function;
5116 if (function == &QXmlSimpleReaderPrivate::eat_ws) {
5118 #if defined(QT_QXML_DEBUG)
5119 qDebug("QXmlSimpleReader: eat_ws (cont)");
5122 if (!(this->*function)()) {
5123 parseFailed(&QXmlSimpleReaderPrivate::parseExternalID, state);
5132 if (parseExternalID_allowPublicID) {
5133 publicId = string();
5136 reportParseError(QLatin1String(XMLERR_UNEXPECTEDCHARACTER));
5143 reportParseError(QLatin1String(XMLERR_UNEXPECTEDCHARACTER));
5148 unexpectedEof(&QXmlSimpleReaderPrivate::parseExternalID, state);
5153 } else if (c == QLatin1Char('\'')) {
5155 } else if (c == QLatin1Char('"')) {
5157 } else if (c == QLatin1Char('S')) {
5159 } else if (c == QLatin1Char('P')) {
5164 state = table[state][input];
5168 parseString_s = QLatin1String("SYSTEM");
5169 if (!parseString()) {
5170 parseFailed(&QXmlSimpleReaderPrivate::parseExternalID, state);
5176 parseFailed(&QXmlSimpleReaderPrivate::parseExternalID, state);
5191 parseString_s = QLatin1String("PUBLIC");
5192 if (!parseString()) {
5193 parseFailed(&QXmlSimpleReaderPrivate::parseExternalID, state);
5199 parseFailed(&QXmlSimpleReaderPrivate::parseExternalID, state);
5217 publicId = string();
5219 parseFailed(&QXmlSimpleReaderPrivate::parseExternalID, state);
5224 systemId = string();
5233 Parse a markupdecl [29].
5235 bool QXmlSimpleReaderPrivate::parseMarkupdecl()
5237 const signed char Init = 0;
5238 const signed char Lt = 1; // < was read
5239 const signed char Em = 2; // ! was read
5240 const signed char CE = 3; // E was read
5241 const signed char Qm = 4; // ? was read
5242 const signed char Dash = 5; // - was read
5243 const signed char CA = 6; // A was read
5244 const signed char CEL = 7; // EL was read
5245 const signed char CEN = 8; // EN was read
5246 const signed char CN = 9; // N was read
5247 const signed char Done = 10;
5249 const signed char InpLt = 0; // <
5250 const signed char InpQm = 1; // ?
5251 const signed char InpEm = 2; // !
5252 const signed char InpDash = 3; // -
5253 const signed char InpA = 4; // A
5254 const signed char InpE = 5; // E
5255 const signed char InpL = 6; // L
5256 const signed char InpN = 7; // N
5257 const signed char InpUnknown = 8;
5259 static const signed char table[4][9] = {
5260 /* InpLt InpQm InpEm InpDash InpA InpE InpL InpN InpUnknown */
5261 { Lt, -1, -1, -1, -1, -1, -1, -1, -1 }, // Init
5262 { -1, Qm, Em, -1, -1, -1, -1, -1, -1 }, // Lt
5263 { -1, -1, -1, Dash, CA, CE, -1, CN, -1 }, // Em
5264 { -1, -1, -1, -1, -1, -1, CEL, CEN, -1 } // CE
5269 if (parseStack==0 || parseStack->isEmpty()) {
5272 state = parseStack->pop().state;
5273 #if defined(QT_QXML_DEBUG)
5274 qDebug("QXmlSimpleReader: parseMarkupdecl (cont) in state %d", state);
5276 if (!parseStack->isEmpty()) {
5277 ParseFunction function = parseStack->top().function;
5278 if (function == &QXmlSimpleReaderPrivate::eat_ws) {
5280 #if defined(QT_QXML_DEBUG)
5281 qDebug("QXmlSimpleReader: eat_ws (cont)");
5284 if (!(this->*function)()) {
5285 parseFailed(&QXmlSimpleReaderPrivate::parseMarkupdecl, state);
5295 if (!contentHnd->processingInstruction(name(),string())) {
5296 reportParseError(contentHnd->errorString());
5303 if (!lexicalHnd->comment(string())) {
5304 reportParseError(lexicalHnd->errorString());
5321 reportParseError(QLatin1String(XMLERR_LETTEREXPECTED));
5326 unexpectedEof(&QXmlSimpleReaderPrivate::parseMarkupdecl, state);
5329 if (c == QLatin1Char('<')) {
5331 } else if (c == QLatin1Char('?')) {
5333 } else if (c == QLatin1Char('!')) {
5335 } else if (c == QLatin1Char('-')) {
5337 } else if (c == QLatin1Char('A')) {
5339 } else if (c == QLatin1Char('E')) {
5341 } else if (c == QLatin1Char('L')) {
5343 } else if (c == QLatin1Char('N')) {
5348 state = table[state][input];
5361 parsePI_xmldecl = false;
5363 parseFailed(&QXmlSimpleReaderPrivate::parseMarkupdecl, state);
5368 if (!parseComment()) {
5369 parseFailed(&QXmlSimpleReaderPrivate::parseMarkupdecl, state);
5374 if (!parseAttlistDecl()) {
5375 parseFailed(&QXmlSimpleReaderPrivate::parseMarkupdecl, state);
5380 if (!parseElementDecl()) {
5381 parseFailed(&QXmlSimpleReaderPrivate::parseMarkupdecl, state);
5386 if (!parseEntityDecl()) {
5387 parseFailed(&QXmlSimpleReaderPrivate::parseMarkupdecl, state);
5392 if (!parseNotationDecl()) {
5393 parseFailed(&QXmlSimpleReaderPrivate::parseMarkupdecl, state);
5403 Parse a PEReference [69]
5405 bool QXmlSimpleReaderPrivate::parsePEReference()
5407 const signed char Init = 0;
5408 const signed char Next = 1;
5409 const signed char Name = 2;
5410 const signed char NameR = 3; // same as Name, but already reported
5411 const signed char Done = 4;
5413 const signed char InpSemi = 0; // ;
5414 const signed char InpPer = 1; // %
5415 const signed char InpUnknown = 2;
5417 static const signed char table[4][3] = {
5418 /* InpSemi InpPer InpUnknown */
5419 { -1, Next, -1 }, // Init
5420 { -1, -1, Name }, // Next
5421 { Done, -1, -1 }, // Name
5422 { Done, -1, -1 } // NameR
5427 if (parseStack==0 || parseStack->isEmpty()) {
5430 state = parseStack->pop().state;
5431 #if defined(QT_QXML_DEBUG)
5432 qDebug("QXmlSimpleReader: parsePEReference (cont) in state %d", state);
5434 if (!parseStack->isEmpty()) {
5435 ParseFunction function = parseStack->top().function;
5436 if (function == &QXmlSimpleReaderPrivate::eat_ws) {
5438 #if defined(QT_QXML_DEBUG)
5439 qDebug("QXmlSimpleReader: eat_ws (cont)");
5442 if (!(this->*function)()) {
5443 parseFailed(&QXmlSimpleReaderPrivate::parsePEReference, state);
5454 QString xmlRefString;
5456 QMap<QString,QString>::Iterator it;
5457 it = parameterEntities.find(ref());
5458 if (it != parameterEntities.end()) {
5461 } else if (entityRes) {
5462 QMap<QString,QXmlSimpleReaderPrivate::ExternParameterEntity>::Iterator it2;
5463 it2 = externParameterEntities.find(ref());
5464 QXmlInputSource *ret = 0;
5465 if (it2 != externParameterEntities.end()) {
5466 if (!entityRes->resolveEntity((*it2).publicId, (*it2).systemId, ret)) {
5468 reportParseError(entityRes->errorString());
5472 xmlRefString = ret->data();
5474 if (!stripTextDecl(xmlRefString)) {
5475 reportParseError(QLatin1String(XMLERR_ERRORINTEXTDECL));
5485 if (!contentHnd->skippedEntity(QLatin1Char('%') + ref())) {
5486 reportParseError(contentHnd->errorString());
5491 if (parsePEReference_context == InEntityValue) {
5492 // Included in literal
5493 if (!insertXmlRef(xmlRefString, ref(), true))
5495 } else if (parsePEReference_context == InDTD) {
5497 if (!insertXmlRef(QLatin1Char(' ') + xmlRefString + QLatin1Char(' '), ref(), false))
5508 reportParseError(QLatin1String(XMLERR_LETTEREXPECTED));
5513 unexpectedEof(&QXmlSimpleReaderPrivate::parsePEReference, state);
5516 if (c == QLatin1Char(';')) {
5518 } else if (c == QLatin1Char('%')) {
5523 state = table[state][input];
5531 parseName_useRef = true;
5533 parseFailed(&QXmlSimpleReaderPrivate::parsePEReference, state);
5546 Parse a AttlistDecl [52].
5548 Precondition: the beginning '<!' is already read and the head
5549 stands on the 'A' of '<!ATTLIST'
5551 bool QXmlSimpleReaderPrivate::parseAttlistDecl()
5553 const signed char Init = 0;
5554 const signed char Attlist = 1; // parse the string "ATTLIST"
5555 const signed char Ws = 2; // whitespace read
5556 const signed char Name = 3; // parse name
5557 const signed char Ws1 = 4; // whitespace read
5558 const signed char Attdef = 5; // parse the AttDef
5559 const signed char Ws2 = 6; // whitespace read
5560 const signed char Atttype = 7; // parse the AttType
5561 const signed char Ws3 = 8; // whitespace read
5562 const signed char DDecH = 9; // DefaultDecl with #
5563 const signed char DefReq = 10; // parse the string "REQUIRED"
5564 const signed char DefImp = 11; // parse the string "IMPLIED"
5565 const signed char DefFix = 12; // parse the string "FIXED"
5566 const signed char Attval = 13; // parse the AttValue
5567 const signed char Ws4 = 14; // whitespace read
5568 const signed char Done = 15;
5570 const signed char InpWs = 0; // white space
5571 const signed char InpGt = 1; // >
5572 const signed char InpHash = 2; // #
5573 const signed char InpA = 3; // A
5574 const signed char InpI = 4; // I
5575 const signed char InpF = 5; // F
5576 const signed char InpR = 6; // R
5577 const signed char InpUnknown = 7;
5579 static const signed char table[15][8] = {
5580 /* InpWs InpGt InpHash InpA InpI InpF InpR InpUnknown */
5581 { -1, -1, -1, Attlist, -1, -1, -1, -1 }, // Init
5582 { Ws, -1, -1, -1, -1, -1, -1, -1 }, // Attlist
5583 { -1, -1, -1, Name, Name, Name, Name, Name }, // Ws
5584 { Ws1, Done, Attdef, Attdef, Attdef, Attdef, Attdef, Attdef }, // Name
5585 { -1, Done, Attdef, Attdef, Attdef, Attdef, Attdef, Attdef }, // Ws1
5586 { Ws2, -1, -1, -1, -1, -1, -1, -1 }, // Attdef
5587 { -1, Atttype, Atttype, Atttype, Atttype, Atttype, Atttype, Atttype }, // Ws2
5588 { Ws3, -1, -1, -1, -1, -1, -1, -1 }, // Attype
5589 { -1, Attval, DDecH, Attval, Attval, Attval, Attval, Attval }, // Ws3
5590 { -1, -1, -1, -1, DefImp, DefFix, DefReq, -1 }, // DDecH
5591 { Ws4, Ws4, -1, -1, -1, -1, -1, -1 }, // DefReq
5592 { Ws4, Ws4, -1, -1, -1, -1, -1, -1 }, // DefImp
5593 { Ws3, -1, -1, -1, -1, -1, -1, -1 }, // DefFix
5594 { Ws4, Ws4, -1, -1, -1, -1, -1, -1 }, // Attval
5595 { -1, Done, Attdef, Attdef, Attdef, Attdef, Attdef, Attdef } // Ws4
5600 if (parseStack==0 || parseStack->isEmpty()) {
5603 state = parseStack->pop().state;
5604 #if defined(QT_QXML_DEBUG)
5605 qDebug("QXmlSimpleReader: parseAttlistDecl (cont) in state %d", state);
5607 if (!parseStack->isEmpty()) {
5608 ParseFunction function = parseStack->top().function;
5609 if (function == &QXmlSimpleReaderPrivate::eat_ws) {
5611 #if defined(QT_QXML_DEBUG)
5612 qDebug("QXmlSimpleReader: eat_ws (cont)");
5615 if (!(this->*function)()) {
5616 parseFailed(&QXmlSimpleReaderPrivate::parseAttlistDecl, state);
5625 attDeclEName = name();
5628 attDeclAName = name();
5634 reportParseError(QLatin1String(XMLERR_LETTEREXPECTED));
5639 unexpectedEof(&QXmlSimpleReaderPrivate::parseAttlistDecl, state);
5644 } else if (c == QLatin1Char('>')) {
5646 } else if (c == QLatin1Char('#')) {
5648 } else if (c == QLatin1Char('A')) {
5650 } else if (c == QLatin1Char('I')) {
5652 } else if (c == QLatin1Char('F')) {
5654 } else if (c == QLatin1Char('R')) {
5659 state = table[state][input];
5663 parseString_s = QLatin1String("ATTLIST");
5664 if (!parseString()) {
5665 parseFailed(&QXmlSimpleReaderPrivate::parseAttlistDecl, state);
5674 parseFailed(&QXmlSimpleReaderPrivate::parseAttlistDecl, state);
5679 parseName_useRef = false;
5681 parseFailed(&QXmlSimpleReaderPrivate::parseAttlistDecl, state);
5686 parseName_useRef = false;
5688 parseFailed(&QXmlSimpleReaderPrivate::parseAttlistDecl, state);
5693 if (!parseAttType()) {
5694 parseFailed(&QXmlSimpleReaderPrivate::parseAttlistDecl, state);
5702 parseString_s = QLatin1String("REQUIRED");
5703 if (!parseString()) {
5704 parseFailed(&QXmlSimpleReaderPrivate::parseAttlistDecl, state);
5709 parseString_s = QLatin1String("IMPLIED");
5710 if (!parseString()) {
5711 parseFailed(&QXmlSimpleReaderPrivate::parseAttlistDecl, state);
5716 parseString_s = QLatin1String("FIXED");
5717 if (!parseString()) {
5718 parseFailed(&QXmlSimpleReaderPrivate::parseAttlistDecl, state);
5723 if (!parseAttValue()) {
5724 parseFailed(&QXmlSimpleReaderPrivate::parseAttlistDecl, state);
5730 // ### not all values are computed yet...
5731 if (!declHnd->attributeDecl(attDeclEName, attDeclAName, QLatin1String(""), QLatin1String(""), QLatin1String(""))) {
5732 reportParseError(declHnd->errorString());
5737 parseFailed(&QXmlSimpleReaderPrivate::parseAttlistDecl, state);
5750 Parse a AttType [54]
5752 bool QXmlSimpleReaderPrivate::parseAttType()
5754 const signed char Init = 0;
5755 const signed char ST = 1; // StringType
5756 const signed char TTI = 2; // TokenizedType starting with 'I'
5757 const signed char TTI2 = 3; // TokenizedType helpstate
5758 const signed char TTI3 = 4; // TokenizedType helpstate
5759 const signed char TTE = 5; // TokenizedType starting with 'E'
5760 const signed char TTEY = 6; // TokenizedType starting with 'ENTITY'
5761 const signed char TTEI = 7; // TokenizedType starting with 'ENTITI'
5762 const signed char N = 8; // N read (TokenizedType or Notation)
5763 const signed char TTNM = 9; // TokenizedType starting with 'NM'
5764 const signed char TTNM2 = 10; // TokenizedType helpstate
5765 const signed char NO = 11; // Notation
5766 const signed char NO2 = 12; // Notation helpstate
5767 const signed char NO3 = 13; // Notation helpstate
5768 const signed char NOName = 14; // Notation, read name
5769 const signed char NO4 = 15; // Notation helpstate
5770 const signed char EN = 16; // Enumeration
5771 const signed char ENNmt = 17; // Enumeration, read Nmtoken
5772 const signed char EN2 = 18; // Enumeration helpstate
5773 const signed char ADone = 19; // almost done (make next and accept)
5774 const signed char Done = 20;
5776 const signed char InpWs = 0; // whitespace
5777 const signed char InpOp = 1; // (
5778 const signed char InpCp = 2; //)
5779 const signed char InpPipe = 3; // |
5780 const signed char InpC = 4; // C
5781 const signed char InpE = 5; // E
5782 const signed char InpI = 6; // I
5783 const signed char InpM = 7; // M
5784 const signed char InpN = 8; // N
5785 const signed char InpO = 9; // O
5786 const signed char InpR = 10; // R
5787 const signed char InpS = 11; // S
5788 const signed char InpY = 12; // Y
5789 const signed char InpUnknown = 13;
5791 static const signed char table[19][14] = {
5792 /* InpWs InpOp InpCp InpPipe InpC InpE InpI InpM InpN InpO InpR InpS InpY InpUnknown */
5793 { -1, EN, -1, -1, ST, TTE, TTI, -1, N, -1, -1, -1, -1, -1 }, // Init
5794 { Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done }, // ST
5795 { Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, TTI2, Done, Done, Done }, // TTI
5796 { Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, TTI3, Done, Done }, // TTI2
5797 { Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done }, // TTI3
5798 { -1, -1, -1, -1, -1, -1, TTEI, -1, -1, -1, -1, -1, TTEY, -1 }, // TTE
5799 { Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done }, // TTEY
5800 { Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done }, // TTEI
5801 { -1, -1, -1, -1, -1, -1, -1, TTNM, -1, NO, -1, -1, -1, -1 }, // N
5802 { Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, TTNM2, Done, Done }, // TTNM
5803 { Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done }, // TTNM2
5804 { NO2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, // NO
5805 { -1, NO3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, // NO2
5806 { NOName, NOName, NOName, NOName, NOName, NOName, NOName, NOName, NOName, NOName, NOName, NOName, NOName, NOName }, // NO3
5807 { NO4, -1, ADone, NO3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, // NOName
5808 { -1, -1, ADone, NO3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, // NO4
5809 { -1, -1, ENNmt, -1, ENNmt, ENNmt, ENNmt, ENNmt, ENNmt, ENNmt, ENNmt, ENNmt, ENNmt, ENNmt }, // EN
5810 { EN2, -1, ADone, EN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, // ENNmt
5811 { -1, -1, ADone, EN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } // EN2
5816 if (parseStack==0 || parseStack->isEmpty()) {
5819 state = parseStack->pop().state;
5820 #if defined(QT_QXML_DEBUG)
5821 qDebug("QXmlSimpleReader: parseAttType (cont) in state %d", state);
5823 if (!parseStack->isEmpty()) {
5824 ParseFunction function = parseStack->top().function;
5825 if (function == &QXmlSimpleReaderPrivate::eat_ws) {
5827 #if defined(QT_QXML_DEBUG)
5828 qDebug("QXmlSimpleReader: eat_ws (cont)");
5831 if (!(this->*function)()) {
5832 parseFailed(&QXmlSimpleReaderPrivate::parseAttType, state);
5846 reportParseError(QLatin1String(XMLERR_LETTEREXPECTED));
5851 unexpectedEof(&QXmlSimpleReaderPrivate::parseAttType, state);
5856 } else if (c == QLatin1Char('(')) {
5858 } else if (c == QLatin1Char(')')) {
5860 } else if (c == QLatin1Char('|')) {
5862 } else if (c == QLatin1Char('C')) {
5864 } else if (c == QLatin1Char('E')) {
5866 } else if (c == QLatin1Char('I')) {
5868 } else if (c == QLatin1Char('M')) {
5870 } else if (c == QLatin1Char('N')) {
5872 } else if (c == QLatin1Char('O')) {
5874 } else if (c == QLatin1Char('R')) {
5876 } else if (c == QLatin1Char('S')) {
5878 } else if (c == QLatin1Char('Y')) {
5883 state = table[state][input];
5887 parseString_s = QLatin1String("CDATA");
5888 if (!parseString()) {
5889 parseFailed(&QXmlSimpleReaderPrivate::parseAttType, state);
5894 parseString_s = QLatin1String("ID");
5895 if (!parseString()) {
5896 parseFailed(&QXmlSimpleReaderPrivate::parseAttType, state);
5901 parseString_s = QLatin1String("REF");
5902 if (!parseString()) {
5903 parseFailed(&QXmlSimpleReaderPrivate::parseAttType, state);
5911 parseString_s = QLatin1String("ENTIT");
5912 if (!parseString()) {
5913 parseFailed(&QXmlSimpleReaderPrivate::parseAttType, state);
5921 parseString_s = QLatin1String("IES");
5922 if (!parseString()) {
5923 parseFailed(&QXmlSimpleReaderPrivate::parseAttType, state);
5931 parseString_s = QLatin1String("MTOKEN");
5932 if (!parseString()) {
5933 parseFailed(&QXmlSimpleReaderPrivate::parseAttType, state);
5941 parseString_s = QLatin1String("OTATION");
5942 if (!parseString()) {
5943 parseFailed(&QXmlSimpleReaderPrivate::parseAttType, state);
5949 parseFailed(&QXmlSimpleReaderPrivate::parseAttType, state);
5954 if (!next_eat_ws()) {
5955 parseFailed(&QXmlSimpleReaderPrivate::parseAttType, state);
5960 parseName_useRef = false;
5962 parseFailed(&QXmlSimpleReaderPrivate::parseAttType, state);
5968 parseFailed(&QXmlSimpleReaderPrivate::parseAttType, state);
5973 if (!next_eat_ws()) {
5974 parseFailed(&QXmlSimpleReaderPrivate::parseAttType, state);
5979 if (!parseNmtoken()) {
5980 parseFailed(&QXmlSimpleReaderPrivate::parseAttType, state);
5986 parseFailed(&QXmlSimpleReaderPrivate::parseAttType, state);
5999 Parse a AttValue [10]
6001 Precondition: the head stands on the beginning " or '
6003 If this function was successful, the head stands on the first
6004 character after the closing " or ' and the value of the attribute
6007 bool QXmlSimpleReaderPrivate::parseAttValue()
6009 const signed char Init = 0;
6010 const signed char Dq = 1; // double quotes were read
6011 const signed char DqRef = 2; // read references in double quotes
6012 const signed char DqC = 3; // signed character read in double quotes
6013 const signed char Sq = 4; // single quotes were read
6014 const signed char SqRef = 5; // read references in single quotes
6015 const signed char SqC = 6; // signed character read in single quotes
6016 const signed char Done = 7;
6018 const signed char InpDq = 0; // "
6019 const signed char InpSq = 1; // '
6020 const signed char InpAmp = 2; // &
6021 const signed char InpLt = 3; // <
6022 const signed char InpUnknown = 4;
6024 static const signed char table[7][5] = {
6025 /* InpDq InpSq InpAmp InpLt InpUnknown */
6026 { Dq, Sq, -1, -1, -1 }, // Init
6027 { Done, DqC, DqRef, -1, DqC }, // Dq
6028 { Done, DqC, DqRef, -1, DqC }, // DqRef
6029 { Done, DqC, DqRef, -1, DqC }, // DqC
6030 { SqC, Done, SqRef, -1, SqC }, // Sq
6031 { SqC, Done, SqRef, -1, SqC }, // SqRef
6032 { SqC, Done, SqRef, -1, SqC } // SqRef
6037 if (parseStack==0 || parseStack->isEmpty()) {
6040 state = parseStack->pop().state;
6041 #if defined(QT_QXML_DEBUG)
6042 qDebug("QXmlSimpleReader: parseAttValue (cont) in state %d", state);
6044 if (!parseStack->isEmpty()) {
6045 ParseFunction function = parseStack->top().function;
6046 if (function == &QXmlSimpleReaderPrivate::eat_ws) {
6048 #if defined(QT_QXML_DEBUG)
6049 qDebug("QXmlSimpleReader: eat_ws (cont)");
6052 if (!(this->*function)()) {
6053 parseFailed(&QXmlSimpleReaderPrivate::parseAttValue, state);
6065 reportParseError(QLatin1String(XMLERR_UNEXPECTEDCHARACTER));
6070 unexpectedEof(&QXmlSimpleReaderPrivate::parseAttValue, state);
6073 if (c == QLatin1Char('"')) {
6075 } else if (c == QLatin1Char('\'')) {
6077 } else if (c == QLatin1Char('&')) {
6079 } else if (c == QLatin1Char('<')) {
6084 state = table[state][input];
6094 parseReference_context = InAttributeValue;
6095 if (!parseReference()) {
6096 parseFailed(&QXmlSimpleReaderPrivate::parseAttValue, state);
6114 Parse a elementdecl [45].
6116 Precondition: the beginning '<!E' is already read and the head
6117 stands on the 'L' of '<!ELEMENT'
6119 bool QXmlSimpleReaderPrivate::parseElementDecl()
6121 const signed char Init = 0;
6122 const signed char Elem = 1; // parse the beginning string
6123 const signed char Ws1 = 2; // whitespace required
6124 const signed char Nam = 3; // parse Name
6125 const signed char Ws2 = 4; // whitespace required
6126 const signed char Empty = 5; // read EMPTY
6127 const signed char Any = 6; // read ANY
6128 const signed char Cont = 7; // read contentspec (except ANY or EMPTY)
6129 const signed char Mix = 8; // read Mixed
6130 const signed char Mix2 = 9; //
6131 const signed char Mix3 = 10; //
6132 const signed char MixN1 = 11; //
6133 const signed char MixN2 = 12; //
6134 const signed char MixN3 = 13; //
6135 const signed char MixN4 = 14; //
6136 const signed char Cp = 15; // parse cp
6137 const signed char Cp2 = 16; //
6138 const signed char WsD = 17; // eat whitespace before Done
6139 const signed char Done = 18;
6141 const signed char InpWs = 0;
6142 const signed char InpGt = 1; // >
6143 const signed char InpPipe = 2; // |
6144 const signed char InpOp = 3; // (
6145 const signed char InpCp = 4; //)
6146 const signed char InpHash = 5; // #
6147 const signed char InpQm = 6; // ?
6148 const signed char InpAst = 7; // *
6149 const signed char InpPlus = 8; // +
6150 const signed char InpA = 9; // A
6151 const signed char InpE = 10; // E
6152 const signed char InpL = 11; // L
6153 const signed char InpUnknown = 12;
6155 static const signed char table[18][13] = {
6156 /* InpWs InpGt InpPipe InpOp InpCp InpHash InpQm InpAst InpPlus InpA InpE InpL InpUnknown */
6157 { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, Elem, -1 }, // Init
6158 { Ws1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, // Elem
6159 { -1, -1, -1, -1, -1, -1, -1, -1, -1, Nam, Nam, Nam, Nam }, // Ws1
6160 { Ws2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, // Nam
6161 { -1, -1, -1, Cont, -1, -1, -1, -1, -1, Any, Empty, -1, -1 }, // Ws2
6162 { WsD, Done, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, // Empty
6163 { WsD, Done, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, // Any
6164 { -1, -1, -1, Cp, Cp, Mix, -1, -1, -1, Cp, Cp, Cp, Cp }, // Cont
6165 { Mix2, -1, MixN1, -1, Mix3, -1, -1, -1, -1, -1, -1, -1, -1 }, // Mix
6166 { -1, -1, MixN1, -1, Mix3, -1, -1, -1, -1, -1, -1, -1, -1 }, // Mix2
6167 { WsD, Done, -1, -1, -1, -1, -1, WsD, -1, -1, -1, -1, -1 }, // Mix3
6168 { -1, -1, -1, -1, -1, -1, -1, -1, -1, MixN2, MixN2, MixN2, MixN2 }, // MixN1
6169 { MixN3, -1, MixN1, -1, MixN4, -1, -1, -1, -1, -1, -1, -1, -1 }, // MixN2
6170 { -1, -1, MixN1, -1, MixN4, -1, -1, -1, -1, -1, -1, -1, -1 }, // MixN3
6171 { -1, -1, -1, -1, -1, -1, -1, WsD, -1, -1, -1, -1, -1 }, // MixN4
6172 { WsD, Done, -1, -1, -1, -1, Cp2, Cp2, Cp2, -1, -1, -1, -1 }, // Cp
6173 { WsD, Done, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, // Cp2
6174 { -1, Done, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } // WsD
6179 if (parseStack==0 || parseStack->isEmpty()) {
6182 state = parseStack->pop().state;
6183 #if defined(QT_QXML_DEBUG)
6184 qDebug("QXmlSimpleReader: parseElementDecl (cont) in state %d", state);
6186 if (!parseStack->isEmpty()) {
6187 ParseFunction function = parseStack->top().function;
6188 if (function == &QXmlSimpleReaderPrivate::eat_ws) {
6190 #if defined(QT_QXML_DEBUG)
6191 qDebug("QXmlSimpleReader: eat_ws (cont)");
6194 if (!(this->*function)()) {
6195 parseFailed(&QXmlSimpleReaderPrivate::parseElementDecl, state);
6206 reportParseError(QLatin1String(XMLERR_UNEXPECTEDCHARACTER));
6211 unexpectedEof(&QXmlSimpleReaderPrivate::parseElementDecl, state);
6216 } else if (c == QLatin1Char('>')) {
6218 } else if (c == QLatin1Char('|')) {
6220 } else if (c == QLatin1Char('(')) {
6222 } else if (c == QLatin1Char(')')) {
6224 } else if (c == QLatin1Char('#')) {
6226 } else if (c == QLatin1Char('?')) {
6228 } else if (c == QLatin1Char('*')) {
6230 } else if (c == QLatin1Char('+')) {
6232 } else if (c == QLatin1Char('A')) {
6234 } else if (c == QLatin1Char('E')) {
6236 } else if (c == QLatin1Char('L')) {
6241 state = table[state][input];
6245 parseString_s = QLatin1String("LEMENT");
6246 if (!parseString()) {
6247 parseFailed(&QXmlSimpleReaderPrivate::parseElementDecl, state);
6253 parseFailed(&QXmlSimpleReaderPrivate::parseElementDecl, state);
6258 parseName_useRef = false;
6260 parseFailed(&QXmlSimpleReaderPrivate::parseElementDecl, state);
6266 parseFailed(&QXmlSimpleReaderPrivate::parseElementDecl, state);
6271 parseString_s = QLatin1String("EMPTY");
6272 if (!parseString()) {
6273 parseFailed(&QXmlSimpleReaderPrivate::parseElementDecl, state);
6278 parseString_s = QLatin1String("ANY");
6279 if (!parseString()) {
6280 parseFailed(&QXmlSimpleReaderPrivate::parseElementDecl, state);
6285 if (!next_eat_ws()) {
6286 parseFailed(&QXmlSimpleReaderPrivate::parseElementDecl, state);
6291 parseString_s = QLatin1String("#PCDATA");
6292 if (!parseString()) {
6293 parseFailed(&QXmlSimpleReaderPrivate::parseElementDecl, state);
6299 parseFailed(&QXmlSimpleReaderPrivate::parseElementDecl, state);
6307 if (!next_eat_ws()) {
6308 parseFailed(&QXmlSimpleReaderPrivate::parseElementDecl, state);
6313 parseName_useRef = false;
6315 parseFailed(&QXmlSimpleReaderPrivate::parseElementDecl, state);
6321 parseFailed(&QXmlSimpleReaderPrivate::parseElementDecl, state);
6329 if (!parseChoiceSeq()) {
6330 parseFailed(&QXmlSimpleReaderPrivate::parseElementDecl, state);
6338 if (!next_eat_ws()) {
6339 parseFailed(&QXmlSimpleReaderPrivate::parseElementDecl, state);
6352 Parse a NotationDecl [82].
6354 Precondition: the beginning '<!' is already read and the head
6355 stands on the 'N' of '<!NOTATION'
6357 bool QXmlSimpleReaderPrivate::parseNotationDecl()
6359 const signed char Init = 0;
6360 const signed char Not = 1; // read NOTATION
6361 const signed char Ws1 = 2; // eat whitespaces
6362 const signed char Nam = 3; // read Name
6363 const signed char Ws2 = 4; // eat whitespaces
6364 const signed char ExtID = 5; // parse ExternalID
6365 const signed char ExtIDR = 6; // same as ExtID, but already reported
6366 const signed char Ws3 = 7; // eat whitespaces
6367 const signed char Done = 8;
6369 const signed char InpWs = 0;
6370 const signed char InpGt = 1; // >
6371 const signed char InpN = 2; // N
6372 const signed char InpUnknown = 3;
6374 static const signed char table[8][4] = {
6375 /* InpWs InpGt InpN InpUnknown */
6376 { -1, -1, Not, -1 }, // Init
6377 { Ws1, -1, -1, -1 }, // Not
6378 { -1, -1, Nam, Nam }, // Ws1
6379 { Ws2, Done, -1, -1 }, // Nam
6380 { -1, Done, ExtID, ExtID }, // Ws2
6381 { Ws3, Done, -1, -1 }, // ExtID
6382 { Ws3, Done, -1, -1 }, // ExtIDR
6383 { -1, Done, -1, -1 } // Ws3
6388 if (parseStack==0 || parseStack->isEmpty()) {
6391 state = parseStack->pop().state;
6392 #if defined(QT_QXML_DEBUG)
6393 qDebug("QXmlSimpleReader: parseNotationDecl (cont) in state %d", state);
6395 if (!parseStack->isEmpty()) {
6396 ParseFunction function = parseStack->top().function;
6397 if (function == &QXmlSimpleReaderPrivate::eat_ws) {
6399 #if defined(QT_QXML_DEBUG)
6400 qDebug("QXmlSimpleReader: eat_ws (cont)");
6403 if (!(this->*function)()) {
6404 parseFailed(&QXmlSimpleReaderPrivate::parseNotationDecl, state);
6415 if (!dtdHnd->notationDecl(name(), publicId, systemId)) {
6416 reportParseError(dtdHnd->errorString());
6426 reportParseError(QLatin1String(XMLERR_UNEXPECTEDCHARACTER));
6431 unexpectedEof(&QXmlSimpleReaderPrivate::parseNotationDecl, state);
6436 } else if (c == QLatin1Char('>')) {
6438 } else if (c == QLatin1Char('N')) {
6443 state = table[state][input];
6447 parseString_s = QLatin1String("NOTATION");
6448 if (!parseString()) {
6449 parseFailed(&QXmlSimpleReaderPrivate::parseNotationDecl, state);
6455 parseFailed(&QXmlSimpleReaderPrivate::parseNotationDecl, state);
6460 parseName_useRef = false;
6462 parseFailed(&QXmlSimpleReaderPrivate::parseNotationDecl, state);
6468 parseFailed(&QXmlSimpleReaderPrivate::parseNotationDecl, state);
6474 parseExternalID_allowPublicID = true;
6475 if (!parseExternalID()) {
6476 parseFailed(&QXmlSimpleReaderPrivate::parseNotationDecl, state);
6482 parseFailed(&QXmlSimpleReaderPrivate::parseNotationDecl, state);
6495 Parse choice [49] or seq [50].
6497 Precondition: the beginning '('S? is already read and the head
6498 stands on the first non-whitespace character after it.
6500 bool QXmlSimpleReaderPrivate::parseChoiceSeq()
6502 const signed char Init = 0;
6503 const signed char Ws1 = 1; // eat whitespace
6504 const signed char CoS = 2; // choice or set
6505 const signed char Ws2 = 3; // eat whitespace
6506 const signed char More = 4; // more cp to read
6507 const signed char Name = 5; // read name
6508 const signed char Done = 6; //
6510 const signed char InpWs = 0; // S
6511 const signed char InpOp = 1; // (
6512 const signed char InpCp = 2; //)
6513 const signed char InpQm = 3; // ?
6514 const signed char InpAst = 4; // *
6515 const signed char InpPlus = 5; // +
6516 const signed char InpPipe = 6; // |
6517 const signed char InpComm = 7; // ,
6518 const signed char InpUnknown = 8;
6520 static const signed char table[6][9] = {
6521 /* InpWs InpOp InpCp InpQm InpAst InpPlus InpPipe InpComm InpUnknown */
6522 { -1, Ws1, -1, -1, -1, -1, -1, -1, Name }, // Init
6523 { -1, CoS, -1, -1, -1, -1, -1, -1, CoS }, // Ws1
6524 { Ws2, -1, Done, Ws2, Ws2, Ws2, More, More, -1 }, // CS
6525 { -1, -1, Done, -1, -1, -1, More, More, -1 }, // Ws2
6526 { -1, Ws1, -1, -1, -1, -1, -1, -1, Name }, // More (same as Init)
6527 { Ws2, -1, Done, Ws2, Ws2, Ws2, More, More, -1 } // Name (same as CS)
6532 if (parseStack==0 || parseStack->isEmpty()) {
6535 state = parseStack->pop().state;
6536 #if defined(QT_QXML_DEBUG)
6537 qDebug("QXmlSimpleReader: parseChoiceSeq (cont) in state %d", state);
6539 if (!parseStack->isEmpty()) {
6540 ParseFunction function = parseStack->top().function;
6541 if (function == &QXmlSimpleReaderPrivate::eat_ws) {
6543 #if defined(QT_QXML_DEBUG)
6544 qDebug("QXmlSimpleReader: eat_ws (cont)");
6547 if (!(this->*function)()) {
6548 parseFailed(&QXmlSimpleReaderPrivate::parseChoiceSeq, state);
6560 reportParseError(QLatin1String(XMLERR_UNEXPECTEDCHARACTER));
6565 unexpectedEof(&QXmlSimpleReaderPrivate::parseChoiceSeq, state);
6570 } else if (c == QLatin1Char('(')) {
6572 } else if (c == QLatin1Char(')')) {
6574 } else if (c == QLatin1Char('?')) {
6576 } else if (c == QLatin1Char('*')) {
6578 } else if (c == QLatin1Char('+')) {
6580 } else if (c == QLatin1Char('|')) {
6582 } else if (c == QLatin1Char(',')) {
6587 state = table[state][input];
6591 if (!next_eat_ws()) {
6592 parseFailed(&QXmlSimpleReaderPrivate::parseChoiceSeq, state);
6597 if (!parseChoiceSeq()) {
6598 parseFailed(&QXmlSimpleReaderPrivate::parseChoiceSeq, state);
6603 if (!next_eat_ws()) {
6604 parseFailed(&QXmlSimpleReaderPrivate::parseChoiceSeq, state);
6609 if (!next_eat_ws()) {
6610 parseFailed(&QXmlSimpleReaderPrivate::parseChoiceSeq, state);
6615 parseName_useRef = false;
6617 parseFailed(&QXmlSimpleReaderPrivate::parseChoiceSeq, state);
6630 Parse a EntityDecl [70].
6632 Precondition: the beginning '<!E' is already read and the head
6633 stand on the 'N' of '<!ENTITY'
6635 bool QXmlSimpleReaderPrivate::parseEntityDecl()
6637 const signed char Init = 0;
6638 const signed char Ent = 1; // parse "ENTITY"
6639 const signed char Ws1 = 2; // white space read
6640 const signed char Name = 3; // parse name
6641 const signed char Ws2 = 4; // white space read
6642 const signed char EValue = 5; // parse entity value
6643 const signed char EValueR = 6; // same as EValue, but already reported
6644 const signed char ExtID = 7; // parse ExternalID
6645 const signed char Ws3 = 8; // white space read
6646 const signed char Ndata = 9; // parse "NDATA"
6647 const signed char Ws4 = 10; // white space read
6648 const signed char NNam = 11; // parse name
6649 const signed char NNamR = 12; // same as NNam, but already reported
6650 const signed char PEDec = 13; // parse PEDecl
6651 const signed char Ws6 = 14; // white space read
6652 const signed char PENam = 15; // parse name
6653 const signed char Ws7 = 16; // white space read
6654 const signed char PEVal = 17; // parse entity value
6655 const signed char PEValR = 18; // same as PEVal, but already reported
6656 const signed char PEEID = 19; // parse ExternalID
6657 const signed char PEEIDR = 20; // same as PEEID, but already reported
6658 const signed char WsE = 21; // white space read
6659 const signed char Done = 22;
6660 const signed char EDDone = 23; // done, but also report an external, unparsed entity decl
6662 const signed char InpWs = 0; // white space
6663 const signed char InpPer = 1; // %
6664 const signed char InpQuot = 2; // " or '
6665 const signed char InpGt = 3; // >
6666 const signed char InpN = 4; // N
6667 const signed char InpUnknown = 5;
6669 static const signed char table[22][6] = {
6670 /* InpWs InpPer InpQuot InpGt InpN InpUnknown */
6671 { -1, -1, -1, -1, Ent, -1 }, // Init
6672 { Ws1, -1, -1, -1, -1, -1 }, // Ent
6673 { -1, PEDec, -1, -1, Name, Name }, // Ws1
6674 { Ws2, -1, -1, -1, -1, -1 }, // Name
6675 { -1, -1, EValue, -1, -1, ExtID }, // Ws2
6676 { WsE, -1, -1, Done, -1, -1 }, // EValue
6677 { WsE, -1, -1, Done, -1, -1 }, // EValueR
6678 { Ws3, -1, -1, EDDone,-1, -1 }, // ExtID
6679 { -1, -1, -1, EDDone,Ndata, -1 }, // Ws3
6680 { Ws4, -1, -1, -1, -1, -1 }, // Ndata
6681 { -1, -1, -1, -1, NNam, NNam }, // Ws4
6682 { WsE, -1, -1, Done, -1, -1 }, // NNam
6683 { WsE, -1, -1, Done, -1, -1 }, // NNamR
6684 { Ws6, -1, -1, -1, -1, -1 }, // PEDec
6685 { -1, -1, -1, -1, PENam, PENam }, // Ws6
6686 { Ws7, -1, -1, -1, -1, -1 }, // PENam
6687 { -1, -1, PEVal, -1, -1, PEEID }, // Ws7
6688 { WsE, -1, -1, Done, -1, -1 }, // PEVal
6689 { WsE, -1, -1, Done, -1, -1 }, // PEValR
6690 { WsE, -1, -1, Done, -1, -1 }, // PEEID
6691 { WsE, -1, -1, Done, -1, -1 }, // PEEIDR
6692 { -1, -1, -1, Done, -1, -1 } // WsE
6697 if (parseStack==0 || parseStack->isEmpty()) {
6700 state = parseStack->pop().state;
6701 #if defined(QT_QXML_DEBUG)
6702 qDebug("QXmlSimpleReader: parseEntityDecl (cont) in state %d", state);
6704 if (!parseStack->isEmpty()) {
6705 ParseFunction function = parseStack->top().function;
6706 if (function == &QXmlSimpleReaderPrivate::eat_ws) {
6708 #if defined(QT_QXML_DEBUG)
6709 qDebug("QXmlSimpleReader: eat_ws (cont)");
6712 if (!(this->*function)()) {
6713 parseFailed(&QXmlSimpleReaderPrivate::parseEntityDecl, state);
6722 if ( !entityExist(name())) {
6723 entities.insert(name(), string());
6725 if (!declHnd->internalEntityDecl(name(), string())) {
6726 reportParseError(declHnd->errorString());
6734 if ( !entityExist(name())) {
6735 externEntities.insert(name(), QXmlSimpleReaderPrivate::ExternEntity(publicId, systemId, ref()));
6737 if (!dtdHnd->unparsedEntityDecl(name(), publicId, systemId, ref())) {
6738 reportParseError(declHnd->errorString());
6746 if ( !entityExist(name())) {
6747 parameterEntities.insert(name(), string());
6749 if (!declHnd->internalEntityDecl(QLatin1Char('%') + name(), string())) {
6750 reportParseError(declHnd->errorString());
6758 if ( !entityExist(name())) {
6759 externParameterEntities.insert(name(), QXmlSimpleReaderPrivate::ExternParameterEntity(publicId, systemId));
6761 if (!declHnd->externalEntityDecl(QLatin1Char('%') + name(), publicId, systemId)) {
6762 reportParseError(declHnd->errorString());
6770 if ( !entityExist(name())) {
6771 externEntities.insert(name(), QXmlSimpleReaderPrivate::ExternEntity(publicId, systemId, QString()));
6773 if (!declHnd->externalEntityDecl(name(), publicId, systemId)) {
6774 reportParseError(declHnd->errorString());
6784 reportParseError(QLatin1String(XMLERR_LETTEREXPECTED));
6789 unexpectedEof(&QXmlSimpleReaderPrivate::parseEntityDecl, state);
6794 } else if (c == QLatin1Char('%')) {
6796 } else if (c == QLatin1Char('"') || c == QLatin1Char('\'')) {
6798 } else if (c == QLatin1Char('>')) {
6800 } else if (c == QLatin1Char('N')) {
6805 state = table[state][input];
6809 parseString_s = QLatin1String("NTITY");
6810 if (!parseString()) {
6811 parseFailed(&QXmlSimpleReaderPrivate::parseEntityDecl, state);
6817 parseFailed(&QXmlSimpleReaderPrivate::parseEntityDecl, state);
6822 parseName_useRef = false;
6824 parseFailed(&QXmlSimpleReaderPrivate::parseEntityDecl, state);
6830 parseFailed(&QXmlSimpleReaderPrivate::parseEntityDecl, state);
6836 if (!parseEntityValue()) {
6837 parseFailed(&QXmlSimpleReaderPrivate::parseEntityDecl, state);
6842 parseExternalID_allowPublicID = false;
6843 if (!parseExternalID()) {
6844 parseFailed(&QXmlSimpleReaderPrivate::parseEntityDecl, state);
6850 parseFailed(&QXmlSimpleReaderPrivate::parseEntityDecl, state);
6855 parseString_s = QLatin1String("NDATA");
6856 if (!parseString()) {
6857 parseFailed(&QXmlSimpleReaderPrivate::parseEntityDecl, state);
6863 parseFailed(&QXmlSimpleReaderPrivate::parseEntityDecl, state);
6869 parseName_useRef = true;
6871 parseFailed(&QXmlSimpleReaderPrivate::parseEntityDecl, state);
6880 parseFailed(&QXmlSimpleReaderPrivate::parseEntityDecl, state);
6885 parseName_useRef = false;
6887 parseFailed(&QXmlSimpleReaderPrivate::parseEntityDecl, state);
6893 parseFailed(&QXmlSimpleReaderPrivate::parseEntityDecl, state);
6899 if (!parseEntityValue()) {
6900 parseFailed(&QXmlSimpleReaderPrivate::parseEntityDecl, state);
6906 parseExternalID_allowPublicID = false;
6907 if (!parseExternalID()) {
6908 parseFailed(&QXmlSimpleReaderPrivate::parseEntityDecl, state);
6914 parseFailed(&QXmlSimpleReaderPrivate::parseEntityDecl, state);
6930 Parse a EntityValue [9]
6932 bool QXmlSimpleReaderPrivate::parseEntityValue()
6934 const signed char Init = 0;
6935 const signed char Dq = 1; // EntityValue is double quoted
6936 const signed char DqC = 2; // signed character
6937 const signed char DqPER = 3; // PERefence
6938 const signed char DqRef = 4; // Reference
6939 const signed char Sq = 5; // EntityValue is double quoted
6940 const signed char SqC = 6; // signed character
6941 const signed char SqPER = 7; // PERefence
6942 const signed char SqRef = 8; // Reference
6943 const signed char Done = 9;
6945 const signed char InpDq = 0; // "
6946 const signed char InpSq = 1; // '
6947 const signed char InpAmp = 2; // &
6948 const signed char InpPer = 3; // %
6949 const signed char InpUnknown = 4;
6951 static const signed char table[9][5] = {
6952 /* InpDq InpSq InpAmp InpPer InpUnknown */
6953 { Dq, Sq, -1, -1, -1 }, // Init
6954 { Done, DqC, DqRef, DqPER, DqC }, // Dq
6955 { Done, DqC, DqRef, DqPER, DqC }, // DqC
6956 { Done, DqC, DqRef, DqPER, DqC }, // DqPER
6957 { Done, DqC, DqRef, DqPER, DqC }, // DqRef
6958 { SqC, Done, SqRef, SqPER, SqC }, // Sq
6959 { SqC, Done, SqRef, SqPER, SqC }, // SqC
6960 { SqC, Done, SqRef, SqPER, SqC }, // SqPER
6961 { SqC, Done, SqRef, SqPER, SqC } // SqRef
6966 if (parseStack==0 || parseStack->isEmpty()) {
6969 state = parseStack->pop().state;
6970 #if defined(QT_QXML_DEBUG)
6971 qDebug("QXmlSimpleReader: parseEntityValue (cont) in state %d", state);
6973 if (!parseStack->isEmpty()) {
6974 ParseFunction function = parseStack->top().function;
6975 if (function == &QXmlSimpleReaderPrivate::eat_ws) {
6977 #if defined(QT_QXML_DEBUG)
6978 qDebug("QXmlSimpleReader: eat_ws (cont)");
6981 if (!(this->*function)()) {
6982 parseFailed(&QXmlSimpleReaderPrivate::parseEntityValue, state);
6994 reportParseError(QLatin1String(XMLERR_LETTEREXPECTED));
6999 unexpectedEof(&QXmlSimpleReaderPrivate::parseEntityValue, state);
7002 if (c == QLatin1Char('"')) {
7004 } else if (c == QLatin1Char('\'')) {
7006 } else if (c == QLatin1Char('&')) {
7008 } else if (c == QLatin1Char('%')) {
7013 state = table[state][input];
7028 parsePEReference_context = InEntityValue;
7029 if (!parsePEReference()) {
7030 parseFailed(&QXmlSimpleReaderPrivate::parseEntityValue, state);
7036 parseReference_context = InEntityValue;
7037 if (!parseReference()) {
7038 parseFailed(&QXmlSimpleReaderPrivate::parseEntityValue, state);
7051 Parse a comment [15].
7053 Precondition: the beginning '<!' of the comment is already read and the head
7054 stands on the first '-' of '<!--'.
7056 If this funktion was successful, the head-position is on the first
7057 character after the comment.
7059 bool QXmlSimpleReaderPrivate::parseComment()
7061 const signed char Init = 0;
7062 const signed char Dash1 = 1; // the first dash was read
7063 const signed char Dash2 = 2; // the second dash was read
7064 const signed char Com = 3; // read comment
7065 const signed char Com2 = 4; // read comment (help state)
7066 const signed char ComE = 5; // finished reading comment
7067 const signed char Done = 6;
7069 const signed char InpDash = 0; // -
7070 const signed char InpGt = 1; // >
7071 const signed char InpUnknown = 2;
7073 static const signed char table[6][3] = {
7074 /* InpDash InpGt InpUnknown */
7075 { Dash1, -1, -1 }, // Init
7076 { Dash2, -1, -1 }, // Dash1
7077 { Com2, Com, Com }, // Dash2
7078 { Com2, Com, Com }, // Com
7079 { ComE, Com, Com }, // Com2
7080 { -1, Done, -1 } // ComE
7085 if (parseStack==0 || parseStack->isEmpty()) {
7088 state = parseStack->pop().state;
7089 #if defined(QT_QXML_DEBUG)
7090 qDebug("QXmlSimpleReader: parseComment (cont) in state %d", state);
7092 if (!parseStack->isEmpty()) {
7093 ParseFunction function = parseStack->top().function;
7094 if (function == &QXmlSimpleReaderPrivate::eat_ws) {
7096 #if defined(QT_QXML_DEBUG)
7097 qDebug("QXmlSimpleReader: eat_ws (cont)");
7100 if (!(this->*function)()) {
7101 parseFailed(&QXmlSimpleReaderPrivate::parseComment, state);
7113 // if next character is not a dash than don't skip it
7114 if (!atEnd() && c != QLatin1Char('-'))
7115 stringAddC(QLatin1Char('-'));
7121 reportParseError(QLatin1String(XMLERR_ERRORPARSINGCOMMENT));
7126 unexpectedEof(&QXmlSimpleReaderPrivate::parseComment, state);
7129 if (c == QLatin1Char('-')) {
7131 } else if (c == QLatin1Char('>')) {
7136 state = table[state][input];
7164 Parse an Attribute [41].
7166 Precondition: the head stands on the first character of the name
7167 of the attribute (i.e. all whitespaces are already parsed).
7169 The head stand on the next character after the end quotes. The
7170 variable name contains the name of the attribute and the variable
7171 string contains the value of the attribute.
7173 bool QXmlSimpleReaderPrivate::parseAttribute()
7176 const int PName = 1; // parse name
7177 const int Ws = 2; // eat ws
7178 const int Eq = 3; // the '=' was read
7179 const int Quotes = 4; // " or ' were read
7181 const int InpNameBe = 0;
7182 const int InpEq = 1; // =
7183 const int InpDq = 2; // "
7184 const int InpSq = 3; // '
7185 const int InpUnknown = 4;
7187 static const int table[4][5] = {
7188 /* InpNameBe InpEq InpDq InpSq InpUnknown */
7189 { PName, -1, -1, -1, -1 }, // Init
7190 { -1, Eq, -1, -1, Ws }, // PName
7191 { -1, Eq, -1, -1, -1 }, // Ws
7192 { -1, -1, Quotes, Quotes, -1 } // Eq
7197 if (parseStack==0 || parseStack->isEmpty()) {
7200 state = parseStack->pop().state;
7201 #if defined(QT_QXML_DEBUG)
7202 qDebug("QXmlSimpleReader: parseAttribute (cont) in state %d", state);
7204 if (!parseStack->isEmpty()) {
7205 ParseFunction function = parseStack->top().function;
7206 if (function == &QXmlSimpleReaderPrivate::eat_ws) {
7208 #if defined(QT_QXML_DEBUG)
7209 qDebug("QXmlSimpleReader: eat_ws (cont)");
7212 if (!(this->*function)()) {
7213 parseFailed(&QXmlSimpleReaderPrivate::parseAttribute, state);
7226 reportParseError(QLatin1String(XMLERR_UNEXPECTEDCHARACTER));
7231 unexpectedEof(&QXmlSimpleReaderPrivate::parseAttribute, state);
7234 if (determineNameChar(c) == NameBeginning) {
7236 } else if (c == QLatin1Char('=')) {
7238 } else if (c == QLatin1Char('"')) {
7240 } else if (c == QLatin1Char('\'')) {
7245 state = table[state][input];
7249 parseName_useRef = false;
7251 parseFailed(&QXmlSimpleReaderPrivate::parseAttribute, state);
7257 parseFailed(&QXmlSimpleReaderPrivate::parseAttribute, state);
7262 if (!next_eat_ws()) {
7263 parseFailed(&QXmlSimpleReaderPrivate::parseAttribute, state);
7268 if (!parseAttValue()) {
7269 parseFailed(&QXmlSimpleReaderPrivate::parseAttribute, state);
7279 Parse a Name [5] and store the name in name or ref (if useRef is true).
7281 bool QXmlSimpleReaderPrivate::parseName()
7284 const int Name1 = 1; // parse first character of the name
7285 const int Name = 2; // parse name
7288 static const int table[3][3] = {
7289 /* InpNameBe InpNameCh InpUnknown */
7290 { Name1, -1, -1 }, // Init
7291 { Name, Name, Done }, // Name1
7292 { Name, Name, Done } // Name
7296 if (parseStack==0 || parseStack->isEmpty()) {
7299 state = parseStack->pop().state;
7300 #if defined(QT_QXML_DEBUG)
7301 qDebug("QXmlSimpleReader: parseName (cont) in state %d", state);
7303 if (!parseStack->isEmpty()) {
7304 ParseFunction function = parseStack->top().function;
7305 if (function == &QXmlSimpleReaderPrivate::eat_ws) {
7307 #if defined(QT_QXML_DEBUG)
7308 qDebug("QXmlSimpleReader: eat_ws (cont)");
7311 if (!(this->*function)()) {
7312 parseFailed(&QXmlSimpleReaderPrivate::parseName, state);
7324 reportParseError(QLatin1String(XMLERR_LETTEREXPECTED));
7329 unexpectedEof(&QXmlSimpleReaderPrivate::parseName, state);
7333 // we can safely do the (int) cast thanks to the Q_ASSERTs earlier in this function
7334 state = table[state][(int)fastDetermineNameChar(c)];
7338 if (parseName_useRef) {
7348 if (parseName_useRef) {
7361 Parse a Nmtoken [7] and store the name in name.
7363 bool QXmlSimpleReaderPrivate::parseNmtoken()
7365 const signed char Init = 0;
7366 const signed char NameF = 1;
7367 const signed char Name = 2;
7368 const signed char Done = 3;
7370 const signed char InpNameCh = 0; // NameChar without InpNameBe
7371 const signed char InpUnknown = 1;
7373 static const signed char table[3][2] = {
7374 /* InpNameCh InpUnknown */
7375 { NameF, -1 }, // Init
7376 { Name, Done }, // NameF
7377 { Name, Done } // Name
7382 if (parseStack==0 || parseStack->isEmpty()) {
7385 state = parseStack->pop().state;
7386 #if defined(QT_QXML_DEBUG)
7387 qDebug("QXmlSimpleReader: parseNmtoken (cont) in state %d", state);
7389 if (!parseStack->isEmpty()) {
7390 ParseFunction function = parseStack->top().function;
7391 if (function == &QXmlSimpleReaderPrivate::eat_ws) {
7393 #if defined(QT_QXML_DEBUG)
7394 qDebug("QXmlSimpleReader: eat_ws (cont)");
7397 if (!(this->*function)()) {
7398 parseFailed(&QXmlSimpleReaderPrivate::parseNmtoken, state);
7410 reportParseError(QLatin1String(XMLERR_LETTEREXPECTED));
7415 unexpectedEof(&QXmlSimpleReaderPrivate::parseNmtoken, state);
7418 if (determineNameChar(c) == NotName) {
7423 state = table[state][input];
7441 Parse a Reference [67].
7443 parseReference_charDataRead is set to true if the reference must not be
7444 parsed. The character(s) which the reference mapped to are appended to
7445 string. The head stands on the first character after the reference.
7447 parseReference_charDataRead is set to false if the reference must be parsed.
7448 The charachter(s) which the reference mapped to are inserted at the reference
7449 position. The head stands on the first character of the replacement).
7451 bool QXmlSimpleReaderPrivate::parseReference()
7453 // temporary variables (only used in very local context, so they don't
7454 // interfere with incremental parsing)
7458 const signed char Init = 0;
7459 const signed char SRef = 1; // start of a reference
7460 const signed char ChRef = 2; // parse CharRef
7461 const signed char ChDec = 3; // parse CharRef decimal
7462 const signed char ChHexS = 4; // start CharRef hexadecimal
7463 const signed char ChHex = 5; // parse CharRef hexadecimal
7464 const signed char Name = 6; // parse name
7465 const signed char DoneD = 7; // done CharRef decimal
7466 const signed char DoneH = 8; // done CharRef hexadecimal
7467 const signed char DoneN = 9; // done EntityRef
7469 const signed char InpAmp = 0; // &
7470 const signed char InpSemi = 1; // ;
7471 const signed char InpHash = 2; // #
7472 const signed char InpX = 3; // x
7473 const signed char InpNum = 4; // 0-9
7474 const signed char InpHex = 5; // a-f A-F
7475 const signed char InpUnknown = 6;
7477 static const signed char table[8][7] = {
7478 /* InpAmp InpSemi InpHash InpX InpNum InpHex InpUnknown */
7479 { SRef, -1, -1, -1, -1, -1, -1 }, // Init
7480 { -1, -1, ChRef, Name, Name, Name, Name }, // SRef
7481 { -1, -1, -1, ChHexS, ChDec, -1, -1 }, // ChRef
7482 { -1, DoneD, -1, -1, ChDec, -1, -1 }, // ChDec
7483 { -1, -1, -1, -1, ChHex, ChHex, -1 }, // ChHexS
7484 { -1, DoneH, -1, -1, ChHex, ChHex, -1 }, // ChHex
7485 { -1, DoneN, -1, -1, -1, -1, -1 } // Name
7490 if (parseStack==0 || parseStack->isEmpty()) {
7491 parseReference_charDataRead = false;
7494 state = parseStack->pop().state;
7495 #if defined(QT_QXML_DEBUG)
7496 qDebug("QXmlSimpleReader: parseReference (cont) in state %d", state);
7498 if (!parseStack->isEmpty()) {
7499 ParseFunction function = parseStack->top().function;
7500 if (function == &QXmlSimpleReaderPrivate::eat_ws) {
7502 #if defined(QT_QXML_DEBUG)
7503 qDebug("QXmlSimpleReader: eat_ws (cont)");
7506 if (!(this->*function)()) {
7507 parseFailed(&QXmlSimpleReaderPrivate::parseReference, state);
7523 reportParseError(QLatin1String(XMLERR_ERRORPARSINGREFERENCE));
7528 unexpectedEof(&QXmlSimpleReaderPrivate::parseReference, state);
7533 } else if (c.cell() == '&') {
7535 } else if (c.cell() == ';') {
7537 } else if (c.cell() == '#') {
7539 } else if (c.cell() == 'x') {
7541 } else if ('0' <= c.cell() && c.cell() <= '9') {
7543 } else if ('a' <= c.cell() && c.cell() <= 'f') {
7545 } else if ('A' <= c.cell() && c.cell() <= 'F') {
7550 state = table[state][input];
7572 // read the name into the ref
7573 parseName_useRef = true;
7575 parseFailed(&QXmlSimpleReaderPrivate::parseReference, state);
7580 tmp = ref().toUInt(&ok, 10);
7582 stringAddC(QChar(tmp));
7584 reportParseError(QLatin1String(XMLERR_ERRORPARSINGREFERENCE));
7587 parseReference_charDataRead = true;
7591 tmp = ref().toUInt(&ok, 16);
7593 stringAddC(QChar(tmp));
7595 reportParseError(QLatin1String(XMLERR_ERRORPARSINGREFERENCE));
7598 parseReference_charDataRead = true;
7602 if (!processReference())
7612 Helper function for parseReference()
7614 bool QXmlSimpleReaderPrivate::processReference()
7616 QString reference = ref();
7617 if (reference == QLatin1String("amp")) {
7618 if (parseReference_context == InEntityValue) {
7620 stringAddC(QLatin1Char('&')); stringAddC(QLatin1Char('a')); stringAddC(QLatin1Char('m')); stringAddC(QLatin1Char('p')); stringAddC(QLatin1Char(';'));
7622 // Included or Included in literal
7623 stringAddC(QLatin1Char('&'));
7625 parseReference_charDataRead = true;
7626 } else if (reference == QLatin1String("lt")) {
7627 if (parseReference_context == InEntityValue) {
7629 stringAddC(QLatin1Char('&')); stringAddC(QLatin1Char('l')); stringAddC(QLatin1Char('t')); stringAddC(QLatin1Char(';'));
7631 // Included or Included in literal
7632 stringAddC(QLatin1Char('<'));
7634 parseReference_charDataRead = true;
7635 } else if (reference == QLatin1String("gt")) {
7636 if (parseReference_context == InEntityValue) {
7638 stringAddC(QLatin1Char('&')); stringAddC(QLatin1Char('g')); stringAddC(QLatin1Char('t')); stringAddC(QLatin1Char(';'));
7640 // Included or Included in literal
7641 stringAddC(QLatin1Char('>'));
7643 parseReference_charDataRead = true;
7644 } else if (reference == QLatin1String("apos")) {
7645 if (parseReference_context == InEntityValue) {
7647 stringAddC(QLatin1Char('&')); stringAddC(QLatin1Char('a')); stringAddC(QLatin1Char('p')); stringAddC(QLatin1Char('o')); stringAddC(QLatin1Char('s')); stringAddC(QLatin1Char(';'));
7649 // Included or Included in literal
7650 stringAddC(QLatin1Char('\''));
7652 parseReference_charDataRead = true;
7653 } else if (reference == QLatin1String("quot")) {
7654 if (parseReference_context == InEntityValue) {
7656 stringAddC(QLatin1Char('&')); stringAddC(QLatin1Char('q')); stringAddC(QLatin1Char('u')); stringAddC(QLatin1Char('o')); stringAddC(QLatin1Char('t')); stringAddC(QLatin1Char(';'));
7658 // Included or Included in literal
7659 stringAddC(QLatin1Char('"'));
7661 parseReference_charDataRead = true;
7663 QMap<QString,QString>::Iterator it;
7664 it = entities.find(reference);
7665 if (it != entities.end()) {
7666 // "Internal General"
7667 switch (parseReference_context) {
7670 if (!insertXmlRef(*it, reference, false))
7672 parseReference_charDataRead = false;
7674 case InAttributeValue:
7675 // Included in literal
7676 if (!insertXmlRef(*it, reference, true))
7678 parseReference_charDataRead = false;
7683 stringAddC(QLatin1Char('&'));
7684 for (int i=0; i<(int)reference.length(); i++) {
7685 stringAddC(reference[i]);
7687 stringAddC(QLatin1Char(';'));
7688 parseReference_charDataRead = true;
7693 parseReference_charDataRead = false;
7694 reportParseError(QLatin1String(XMLERR_INTERNALGENERALENTITYINDTD));
7698 QMap<QString,QXmlSimpleReaderPrivate::ExternEntity>::Iterator itExtern;
7699 itExtern = externEntities.find(reference);
7700 if (itExtern == externEntities.end()) {
7701 // entity not declared
7702 // ### check this case for conformance
7703 if (parseReference_context == InEntityValue) {
7705 stringAddC(QLatin1Char('&'));
7706 for (int i=0; i<(int)reference.length(); i++) {
7707 stringAddC(reference[i]);
7709 stringAddC(QLatin1Char(';'));
7710 parseReference_charDataRead = true;
7712 // if we have some char data read, report it now
7713 if (parseReference_context == InContent) {
7714 if (contentCharDataRead) {
7715 if (reportWhitespaceCharData || !string().simplified().isEmpty()) {
7716 if (contentHnd != 0 && !contentHnd->characters(string())) {
7717 reportParseError(contentHnd->errorString());
7722 contentCharDataRead = false;
7727 qt_xml_skipped_entity_in_content = parseReference_context == InContent;
7728 if (!contentHnd->skippedEntity(reference)) {
7729 qt_xml_skipped_entity_in_content = false;
7730 reportParseError(contentHnd->errorString());
7731 return false; // error
7733 qt_xml_skipped_entity_in_content = false;
7736 } else if ((*itExtern).notation.isNull()) {
7737 // "External Parsed General"
7738 switch (parseReference_context) {
7741 // Included if validating
7744 QXmlInputSource *ret = 0;
7745 if (!entityRes->resolveEntity((*itExtern).publicId, (*itExtern).systemId, ret)) {
7747 reportParseError(entityRes->errorString());
7751 QString xmlRefString = ret->data();
7753 if (!stripTextDecl(xmlRefString)) {
7754 reportParseError(QLatin1String(XMLERR_ERRORINTEXTDECL));
7757 if (!insertXmlRef(xmlRefString, reference, false))
7762 if (skipIt && contentHnd) {
7763 qt_xml_skipped_entity_in_content = true;
7764 if (!contentHnd->skippedEntity(reference)) {
7765 qt_xml_skipped_entity_in_content = false;
7766 reportParseError(contentHnd->errorString());
7767 return false; // error
7769 qt_xml_skipped_entity_in_content = false;
7771 parseReference_charDataRead = false;
7773 case InAttributeValue:
7775 parseReference_charDataRead = false;
7776 reportParseError(QLatin1String(XMLERR_EXTERNALGENERALENTITYINAV));
7781 stringAddC(QLatin1Char('&'));
7782 for (int i=0; i<(int)reference.length(); i++) {
7783 stringAddC(reference[i]);
7785 stringAddC(QLatin1Char(';'));
7786 parseReference_charDataRead = true;
7791 parseReference_charDataRead = false;
7792 reportParseError(QLatin1String(XMLERR_EXTERNALGENERALENTITYINDTD));
7797 // ### notify for "Occurs as Attribute Value" missing (but this is no refence, anyway)
7799 parseReference_charDataRead = false;
7800 reportParseError(QLatin1String(XMLERR_UNPARSEDENTITYREFERENCE));
7801 return false; // error
7805 return true; // no error
7810 Parses over a simple string.
7812 After the string was successfully parsed, the head is on the first
7813 character after the string.
7815 bool QXmlSimpleReaderPrivate::parseString()
7817 const signed char InpCharExpected = 0; // the character that was expected
7818 const signed char InpUnknown = 1;
7820 signed char state; // state in this function is the position in the string s
7823 if (parseStack==0 || parseStack->isEmpty()) {
7824 Done = parseString_s.length();
7827 state = parseStack->pop().state;
7828 #if defined(QT_QXML_DEBUG)
7829 qDebug("QXmlSimpleReader: parseString (cont) in state %d", state);
7831 if (!parseStack->isEmpty()) {
7832 ParseFunction function = parseStack->top().function;
7833 if (function == &QXmlSimpleReaderPrivate::eat_ws) {
7835 #if defined(QT_QXML_DEBUG)
7836 qDebug("QXmlSimpleReader: eat_ws (cont)");
7839 if (!(this->*function)()) {
7840 parseFailed(&QXmlSimpleReaderPrivate::parseString, state);
7847 if (state == Done) {
7852 unexpectedEof(&QXmlSimpleReaderPrivate::parseString, state);
7855 if (c == parseString_s[(int)state]) {
7856 input = InpCharExpected;
7860 if (input == InpCharExpected) {
7864 reportParseError(QLatin1String(XMLERR_UNEXPECTEDCHARACTER));
7874 This private function inserts and reports an entity substitution. The
7875 substituted string is \a data and the name of the entity reference is \a
7876 name. If \a inLiteral is true, the entity is IncludedInLiteral (i.e., " and '
7877 must be quoted. Otherwise they are not quoted.
7879 This function returns false on error.
7881 bool QXmlSimpleReaderPrivate::insertXmlRef(const QString &data, const QString &name, bool inLiteral)
7885 xmlRefStack.push(XmlRef(name, tmp.replace(QLatin1Char('\"'),
7886 QLatin1String(""")).replace(QLatin1Char('\''), QLatin1String("'"))));
7888 xmlRefStack.push(XmlRef(name, data));
7890 int n = qMax(parameterEntities.count(), entities.count());
7891 if (xmlRefStack.count() > n+1) {
7892 // recursive entities
7893 reportParseError(QLatin1String(XMLERR_RECURSIVEENTITIES));
7896 if (reportEntities && lexicalHnd) {
7897 if (!lexicalHnd->startEntity(name)) {
7898 reportParseError(lexicalHnd->errorString());
7906 This private function moves the cursor to the next character.
7908 void QXmlSimpleReaderPrivate::next()
7910 int count = xmlRefStack.size();
7911 while (count != 0) {
7912 if (xmlRefStack.top().isEmpty()) {
7913 xmlRefStack.pop_back();
7916 c = xmlRefStack.top().next();
7921 // the following could be written nicer, but since it is a time-critical
7922 // function, rather optimize for speed
7923 ushort uc = c.unicode();
7924 c = inputSource->next();
7925 // If we are not incremental parsing, we just skip over EndOfData chars to give the
7926 // parser an uninterrupted stream of document chars.
7927 if (c == QXmlInputSource::EndOfData && parseStack == 0)
7928 c = inputSource->next();
7932 } else if (uc == '\r') {
7933 if (c != QLatin1Char('\n')) {
7942 This private function moves the cursor to the next non-whitespace character.
7943 This function does not move the cursor if the actual cursor position is a
7944 non-whitespace charcter.
7946 Returns false when you use incremental parsing and this function reaches EOF
7947 with reading only whitespace characters. In this case it also poplulates the
7948 parseStack with useful information. In all other cases, this function returns
7951 bool QXmlSimpleReaderPrivate::eat_ws()
7959 if (parseStack != 0) {
7960 unexpectedEof(&QXmlSimpleReaderPrivate::eat_ws, 0);
7966 bool QXmlSimpleReaderPrivate::next_eat_ws()
7974 This private function initializes the reader. \a i is the input source to
7977 void QXmlSimpleReaderPrivate::init(const QXmlInputSource *i)
7981 inputSource = const_cast<QXmlInputSource *>(i);
7984 externParameterEntities.clear();
7985 parameterEntities.clear();
7986 externEntities.clear();
7994 standalone = QXmlSimpleReaderPrivate::Unknown;
7999 This private function initializes the XML data related variables. Especially,
8000 it reads the data from the input source.
8002 void QXmlSimpleReaderPrivate::initData()
8004 c = QXmlInputSource::EndOfData;
8005 xmlRefStack.clear();
8010 Returns true if a entity with the name \a e exists,
8011 otherwise returns false.
8013 bool QXmlSimpleReaderPrivate::entityExist(const QString& e) const
8015 if ( parameterEntities.find(e) == parameterEntities.end() &&
8016 externParameterEntities.find(e) == externParameterEntities.end() &&
8017 externEntities.find(e) == externEntities.end() &&
8018 entities.find(e) == entities.end()) {
8025 void QXmlSimpleReaderPrivate::reportParseError(const QString& error)
8027 this->error = error;
8029 if (this->error.isNull()) {
8030 const QXmlParseException ex(QLatin1String(XMLERR_OK), columnNr+1, lineNr+1,
8031 thisPublicId, thisSystemId);
8032 errorHnd->fatalError(ex);
8034 const QXmlParseException ex(this->error, columnNr+1, lineNr+1,
8035 thisPublicId, thisSystemId);
8036 errorHnd->fatalError(ex);
8042 This private function is called when a parsing function encounters an
8043 unexpected EOF. It decides what to do (depending on incremental parsing or
8044 not). \a where is a pointer to the function where the error occurred and \a
8045 state is the parsing state in this function.
8047 void QXmlSimpleReaderPrivate::unexpectedEof(ParseFunction where, int state)
8049 if (parseStack == 0) {
8050 reportParseError(QLatin1String(XMLERR_UNEXPECTEDEOF));
8052 if (c == QXmlInputSource::EndOfDocument) {
8053 reportParseError(QLatin1String(XMLERR_UNEXPECTEDEOF));
8055 pushParseState(where, state);
8061 This private function is called when a parse...() function returned false. It
8062 determines if there was an error or if incremental parsing simply went out of
8063 data and does the right thing for the case. \a where is a pointer to the
8064 function where the error occurred and \a state is the parsing state in this
8067 void QXmlSimpleReaderPrivate::parseFailed(ParseFunction where, int state)
8069 if (parseStack!=0 && error.isNull()) {
8070 pushParseState(where, state);
8075 This private function pushes the function pointer \a function and state \a
8076 state to the parse stack. This is used when you are doing an incremental
8077 parsing and reach the end of file too early.
8079 Only call this function when d->parseStack!=0.
8081 void QXmlSimpleReaderPrivate::pushParseState(ParseFunction function, int state)
8083 QXmlSimpleReaderPrivate::ParseState ps;
8084 ps.function = function;
8086 parseStack->push(ps);
8089 inline static void updateValue(QString &value, const QChar *array, int &arrayPos, int &valueLen)
8091 value.resize(valueLen + arrayPos);
8092 memcpy(value.data() + valueLen, array, arrayPos * sizeof(QChar));
8093 valueLen += arrayPos;
8097 // use buffers instead of QString::operator+= when single characters are read
8098 const QString& QXmlSimpleReaderPrivate::string()
8100 updateValue(stringValue, stringArray, stringArrayPos, stringValueLen);
8103 const QString& QXmlSimpleReaderPrivate::name()
8105 updateValue(nameValue, nameArray, nameArrayPos, nameValueLen);
8108 const QString& QXmlSimpleReaderPrivate::ref()
8110 updateValue(refValue, refArray, refArrayPos, refValueLen);
8114 void QXmlSimpleReaderPrivate::stringAddC(QChar ch)
8116 if (stringArrayPos == 256)
8117 updateValue(stringValue, stringArray, stringArrayPos, stringValueLen);
8118 stringArray[stringArrayPos++] = ch;
8120 void QXmlSimpleReaderPrivate::nameAddC(QChar ch)
8122 if (nameArrayPos == 256)
8123 updateValue(nameValue, nameArray, nameArrayPos, nameValueLen);
8124 nameArray[nameArrayPos++] = ch;
8126 void QXmlSimpleReaderPrivate::refAddC(QChar ch)
8128 if (refArrayPos == 256)
8129 updateValue(refValue, refArray, refArrayPos, refValueLen);
8130 refArray[refArrayPos++] = ch;