|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
4 ** All rights reserved. |
|
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
|
6 ** |
|
7 ** This file is part of the QtXml module of the Qt Toolkit. |
|
8 ** |
|
9 ** $QT_BEGIN_LICENSE:LGPL$ |
|
10 ** No Commercial Usage |
|
11 ** This file contains pre-release code and may not be distributed. |
|
12 ** You may use this file in accordance with the terms and conditions |
|
13 ** contained in the Technology Preview License Agreement accompanying |
|
14 ** this package. |
|
15 ** |
|
16 ** GNU Lesser General Public License Usage |
|
17 ** Alternatively, this file may be used under the terms of the GNU Lesser |
|
18 ** General Public License version 2.1 as published by the Free Software |
|
19 ** Foundation and appearing in the file LICENSE.LGPL included in the |
|
20 ** packaging of this file. Please review the following information to |
|
21 ** ensure the GNU Lesser General Public License version 2.1 requirements |
|
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
|
23 ** |
|
24 ** In addition, as a special exception, Nokia gives you certain additional |
|
25 ** rights. These rights are described in the Nokia Qt LGPL Exception |
|
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
|
27 ** |
|
28 ** If you have questions regarding the use of this file, please contact |
|
29 ** Nokia at qt-info@nokia.com. |
|
30 ** |
|
31 ** |
|
32 ** |
|
33 ** |
|
34 ** |
|
35 ** |
|
36 ** |
|
37 ** |
|
38 ** $QT_END_LICENSE$ |
|
39 ** |
|
40 ****************************************************************************/ |
|
41 |
|
42 #include "qxml.h" |
|
43 #include "qtextcodec.h" |
|
44 #include "qbuffer.h" |
|
45 #include "qregexp.h" |
|
46 #include "qmap.h" |
|
47 #include "qstack.h" |
|
48 #include <qdebug.h> |
|
49 |
|
50 |
|
51 #ifdef Q_CC_BOR // borland 6 finds bogus warnings when building this file in uic3 |
|
52 # pragma warn -8080 |
|
53 #endif |
|
54 |
|
55 //#define QT_QXML_DEBUG |
|
56 |
|
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") |
|
81 |
|
82 QT_BEGIN_NAMESPACE |
|
83 |
|
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; |
|
100 |
|
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; |
|
104 |
|
105 // character lookup table |
|
106 static const signed char charLookupTable[256]={ |
|
107 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x00 - 0x07 |
|
108 cltUnknown, // 0x08 |
|
109 cltWS, // 0x09 \t |
|
110 cltWS, // 0x0A \n |
|
111 cltUnknown, // 0x0B |
|
112 cltUnknown, // 0x0C |
|
113 cltWS, // 0x0D \r |
|
114 cltUnknown, // 0x0E |
|
115 cltUnknown, // 0x0F |
|
116 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x17 - 0x16 |
|
117 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x18 - 0x1F |
|
118 cltWS, // 0x20 Space |
|
119 cltEm, // 0x21 ! |
|
120 cltDq, // 0x22 " |
|
121 cltUnknown, // 0x23 |
|
122 cltUnknown, // 0x24 |
|
123 cltPer, // 0x25 % |
|
124 cltAmp, // 0x26 & |
|
125 cltSq, // 0x27 ' |
|
126 cltUnknown, // 0x28 |
|
127 cltUnknown, // 0x29 |
|
128 cltUnknown, // 0x2A |
|
129 cltUnknown, // 0x2B |
|
130 cltUnknown, // 0x2C |
|
131 cltDash, // 0x2D - |
|
132 cltUnknown, // 0x2E |
|
133 cltSlash, // 0x2F / |
|
134 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x30 - 0x37 |
|
135 cltUnknown, // 0x38 |
|
136 cltUnknown, // 0x39 |
|
137 cltUnknown, // 0x3A |
|
138 cltUnknown, // 0x3B |
|
139 cltLt, // 0x3C < |
|
140 cltEq, // 0x3D = |
|
141 cltGt, // 0x3E > |
|
142 cltQm, // 0x3F ? |
|
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 |
|
146 cltUnknown, // 0x58 |
|
147 cltUnknown, // 0x59 |
|
148 cltUnknown, // 0x5A |
|
149 cltOB, // 0x5B [ |
|
150 cltUnknown, // 0x5C |
|
151 cltCB, // 0x5D] |
|
152 cltUnknown, // 0x5E |
|
153 cltUnknown, // 0x5F |
|
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 |
|
174 }; |
|
175 |
|
176 // |
|
177 // local helper functions |
|
178 // |
|
179 |
|
180 /* |
|
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. |
|
184 |
|
185 This function is used for external entities since those can include an |
|
186 TextDecl that must be stripped before inserting the entity. |
|
187 */ |
|
188 static bool stripTextDecl(QString& str) |
|
189 { |
|
190 QString textDeclStart(QLatin1String("<?xml")); |
|
191 if (str.startsWith(textDeclStart)) { |
|
192 QRegExp textDecl(QString::fromLatin1( |
|
193 "^<\\?xml\\s+" |
|
194 "(version\\s*=\\s*((['\"])[-a-zA-Z0-9_.:]+\\3))?" |
|
195 "\\s*" |
|
196 "(encoding\\s*=\\s*((['\"])[A-Za-z][-a-zA-Z0-9_.]*\\6))?" |
|
197 "\\s*\\?>" |
|
198 )); |
|
199 QString strTmp = str.replace(textDecl, QLatin1String("")); |
|
200 if (strTmp.length() != str.length()) |
|
201 return false; // external entity has wrong TextDecl |
|
202 str = strTmp; |
|
203 } |
|
204 return true; |
|
205 } |
|
206 |
|
207 |
|
208 class QXmlAttributesPrivate |
|
209 { |
|
210 }; |
|
211 |
|
212 /* \class QXmlInputSourcePrivate |
|
213 \internal |
|
214 |
|
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 |
|
223 is read in one go. |
|
224 */ |
|
225 class QXmlInputSourcePrivate |
|
226 { |
|
227 public: |
|
228 QIODevice *inputDevice; |
|
229 QTextStream *inputStream; |
|
230 |
|
231 QString str; |
|
232 const QChar *unicode; |
|
233 int pos; |
|
234 int length; |
|
235 bool nextReturnedEndOfData; |
|
236 #ifndef QT_NO_TEXTCODEC |
|
237 QTextDecoder *encMapper; |
|
238 #endif |
|
239 |
|
240 QByteArray encodingDeclBytes; |
|
241 QString encodingDeclChars; |
|
242 bool lookingForEncodingDecl; |
|
243 }; |
|
244 class QXmlParseExceptionPrivate |
|
245 { |
|
246 public: |
|
247 QXmlParseExceptionPrivate() |
|
248 : column(-1), line(-1) |
|
249 { |
|
250 } |
|
251 QXmlParseExceptionPrivate(const QXmlParseExceptionPrivate &other) |
|
252 : msg(other.msg), column(other.column), line(other.line), |
|
253 pub(other.pub), sys(other.sys) |
|
254 { |
|
255 } |
|
256 |
|
257 QString msg; |
|
258 int column; |
|
259 int line; |
|
260 QString pub; |
|
261 QString sys; |
|
262 |
|
263 }; |
|
264 |
|
265 class QXmlLocatorPrivate |
|
266 { |
|
267 }; |
|
268 |
|
269 class QXmlDefaultHandlerPrivate |
|
270 { |
|
271 }; |
|
272 |
|
273 class QXmlSimpleReaderPrivate |
|
274 { |
|
275 public: |
|
276 ~QXmlSimpleReaderPrivate(); |
|
277 private: |
|
278 // functions |
|
279 QXmlSimpleReaderPrivate(QXmlSimpleReader *reader); |
|
280 void initIncrementalParsing(); |
|
281 |
|
282 // used to determine if elements are correctly nested |
|
283 QStack<QString> tags; |
|
284 |
|
285 // used by parseReference() and parsePEReference() |
|
286 enum EntityRecognitionContext { InContent, InAttributeValue, InEntityValue, InDTD }; |
|
287 |
|
288 // used for entity declarations |
|
289 struct ExternParameterEntity |
|
290 { |
|
291 ExternParameterEntity() {} |
|
292 ExternParameterEntity(const QString &p, const QString &s) |
|
293 : publicId(p), systemId(s) {} |
|
294 QString publicId; |
|
295 QString systemId; |
|
296 |
|
297 Q_DUMMY_COMPARISON_OPERATOR(ExternParameterEntity) |
|
298 }; |
|
299 struct ExternEntity |
|
300 { |
|
301 ExternEntity() {} |
|
302 ExternEntity(const QString &p, const QString &s, const QString &n) |
|
303 : publicId(p), systemId(s), notation(n) {} |
|
304 QString publicId; |
|
305 QString systemId; |
|
306 QString notation; |
|
307 Q_DUMMY_COMPARISON_OPERATOR(ExternEntity) |
|
308 }; |
|
309 QMap<QString,ExternParameterEntity> externParameterEntities; |
|
310 QMap<QString,QString> parameterEntities; |
|
311 QMap<QString,ExternEntity> externEntities; |
|
312 QMap<QString,QString> entities; |
|
313 |
|
314 // used for parsing of entity references |
|
315 struct XmlRef { |
|
316 XmlRef() |
|
317 : index(0) {} |
|
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++); } |
|
322 QString name; |
|
323 QString value; |
|
324 int index; |
|
325 }; |
|
326 QStack<XmlRef> xmlRefStack; |
|
327 |
|
328 // used for standalone declaration |
|
329 enum Standalone { Yes, No, Unknown }; |
|
330 |
|
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 |
|
335 |
|
336 QString publicId; // used by parseExternalID() to store the public ID |
|
337 QString systemId; // used by parseExternalID() to store the system ID |
|
338 |
|
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; |
|
346 |
|
347 QString attDeclEName; // use by parseAttlistDecl() |
|
348 QString attDeclAName; // use by parseAttlistDecl() |
|
349 |
|
350 // flags for some features support |
|
351 bool useNamespaces; |
|
352 bool useNamespacePrefixes; |
|
353 bool reportWhitespaceCharData; |
|
354 bool reportEntities; |
|
355 |
|
356 // used to build the attribute list |
|
357 QXmlAttributes attList; |
|
358 |
|
359 // used in QXmlSimpleReader::parseContent() to decide whether character |
|
360 // data was read |
|
361 bool contentCharDataRead; |
|
362 |
|
363 // helper classes |
|
364 QScopedPointer<QXmlLocator> locator; |
|
365 QXmlNamespaceSupport namespaceSupport; |
|
366 |
|
367 // error string |
|
368 QString error; |
|
369 |
|
370 // arguments for parse functions (this is needed to allow incremental |
|
371 // parsing) |
|
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; |
|
379 |
|
380 // for incremental parsing |
|
381 struct ParseState { |
|
382 typedef bool (QXmlSimpleReaderPrivate::*ParseFunction)(); |
|
383 ParseFunction function; |
|
384 int state; |
|
385 }; |
|
386 QStack<ParseState> *parseStack; |
|
387 |
|
388 // used in parseProlog() |
|
389 bool xmldecl_possible; |
|
390 bool doctype_read; |
|
391 |
|
392 // used in parseDoctype() |
|
393 bool startDTDwasReported; |
|
394 |
|
395 // used in parseString() |
|
396 signed char Done; |
|
397 |
|
398 |
|
399 // variables |
|
400 QXmlContentHandler *contentHnd; |
|
401 QXmlErrorHandler *errorHnd; |
|
402 QXmlDTDHandler *dtdHnd; |
|
403 QXmlEntityResolver *entityRes; |
|
404 QXmlLexicalHandler *lexicalHnd; |
|
405 QXmlDeclHandler *declHnd; |
|
406 |
|
407 QXmlInputSource *inputSource; |
|
408 |
|
409 QChar c; // the character at reading position |
|
410 int lineNr; // number of line |
|
411 int columnNr; // position in line |
|
412 |
|
413 QChar nameArray[256]; // only used for names |
|
414 QString nameValue; // only used for names |
|
415 int nameArrayPos; |
|
416 int nameValueLen; |
|
417 QChar refArray[256]; // only used for references |
|
418 QString refValue; // only used for references |
|
419 int refArrayPos; |
|
420 int refValueLen; |
|
421 QChar stringArray[256]; // used for any other strings that are parsed |
|
422 QString stringValue; // used for any other strings that are parsed |
|
423 int stringArrayPos; |
|
424 int stringValueLen; |
|
425 QString emptyStr; |
|
426 |
|
427 const QString &string(); |
|
428 void stringClear(); |
|
429 void stringAddC(QChar); |
|
430 inline void stringAddC() { stringAddC(c); } |
|
431 const QString &name(); |
|
432 void nameClear(); |
|
433 void nameAddC(QChar); |
|
434 inline void nameAddC() { nameAddC(c); } |
|
435 const QString &ref(); |
|
436 void refClear(); |
|
437 void refAddC(QChar); |
|
438 inline void refAddC() { refAddC(c); } |
|
439 |
|
440 // private functions |
|
441 bool eat_ws(); |
|
442 bool next_eat_ws(); |
|
443 |
|
444 void QT_FASTCALL next(); |
|
445 bool atEnd(); |
|
446 |
|
447 void init(const QXmlInputSource* i); |
|
448 void initData(); |
|
449 |
|
450 bool entityExist(const QString&) const; |
|
451 |
|
452 bool parseBeginOrContinue(int state, bool incremental); |
|
453 |
|
454 bool parseProlog(); |
|
455 bool parseElement(); |
|
456 bool processElementEmptyTag(); |
|
457 bool processElementETagBegin2(); |
|
458 bool processElementAttribute(); |
|
459 bool parseMisc(); |
|
460 bool parseContent(); |
|
461 |
|
462 bool parsePI(); |
|
463 bool parseDoctype(); |
|
464 bool parseComment(); |
|
465 |
|
466 bool parseName(); |
|
467 bool parseNmtoken(); |
|
468 bool parseAttribute(); |
|
469 bool parseReference(); |
|
470 bool processReference(); |
|
471 |
|
472 bool parseExternalID(); |
|
473 bool parsePEReference(); |
|
474 bool parseMarkupdecl(); |
|
475 bool parseAttlistDecl(); |
|
476 bool parseAttType(); |
|
477 bool parseAttValue(); |
|
478 bool parseElementDecl(); |
|
479 bool parseNotationDecl(); |
|
480 bool parseChoiceSeq(); |
|
481 bool parseEntityDecl(); |
|
482 bool parseEntityValue(); |
|
483 |
|
484 bool parseString(); |
|
485 |
|
486 bool insertXmlRef(const QString&, const QString&, bool); |
|
487 |
|
488 bool reportEndEntities(); |
|
489 void reportParseError(const QString& error); |
|
490 |
|
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); |
|
495 |
|
496 Q_DECLARE_PUBLIC(QXmlSimpleReader) |
|
497 QXmlSimpleReader *q_ptr; |
|
498 |
|
499 friend class QXmlSimpleReaderLocator; |
|
500 }; |
|
501 |
|
502 /*! |
|
503 \class QXmlParseException |
|
504 \reentrant |
|
505 \brief The QXmlParseException class is used to report errors with |
|
506 the QXmlErrorHandler interface. |
|
507 |
|
508 \inmodule QtXml |
|
509 \ingroup xml-tools |
|
510 |
|
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 |
|
515 messages are: |
|
516 |
|
517 |
|
518 \list |
|
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" |
|
524 \o "tag mismatch" |
|
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" |
|
542 \endlist |
|
543 |
|
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. |
|
547 |
|
548 \sa QXmlErrorHandler, QXmlReader |
|
549 */ |
|
550 |
|
551 /*! |
|
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. |
|
555 */ |
|
556 |
|
557 QXmlParseException::QXmlParseException(const QString& name, int c, int l, |
|
558 const QString& p, const QString& s) |
|
559 : d(new QXmlParseExceptionPrivate) |
|
560 { |
|
561 d->msg = name; |
|
562 d->column = c; |
|
563 d->line = l; |
|
564 d->pub = p; |
|
565 d->sys = s; |
|
566 } |
|
567 |
|
568 /*! |
|
569 Creates a copy of \a other. |
|
570 */ |
|
571 QXmlParseException::QXmlParseException(const QXmlParseException& other) : |
|
572 d(new QXmlParseExceptionPrivate(*other.d)) |
|
573 { |
|
574 |
|
575 } |
|
576 |
|
577 /*! |
|
578 Destroys the QXmlParseException. |
|
579 */ |
|
580 QXmlParseException::~QXmlParseException() |
|
581 { |
|
582 } |
|
583 |
|
584 /*! |
|
585 Returns the error message. |
|
586 */ |
|
587 QString QXmlParseException::message() const |
|
588 { |
|
589 return d->msg; |
|
590 } |
|
591 /*! |
|
592 Returns the column number where the error occurred. |
|
593 */ |
|
594 int QXmlParseException::columnNumber() const |
|
595 { |
|
596 return d->column; |
|
597 } |
|
598 /*! |
|
599 Returns the line number where the error occurred. |
|
600 */ |
|
601 int QXmlParseException::lineNumber() const |
|
602 { |
|
603 return d->line; |
|
604 } |
|
605 /*! |
|
606 Returns the public identifier where the error occurred. |
|
607 */ |
|
608 QString QXmlParseException::publicId() const |
|
609 { |
|
610 return d->pub; |
|
611 } |
|
612 /*! |
|
613 Returns the system identifier where the error occurred. |
|
614 */ |
|
615 QString QXmlParseException::systemId() const |
|
616 { |
|
617 return d->sys; |
|
618 } |
|
619 |
|
620 |
|
621 /*! |
|
622 \class QXmlLocator |
|
623 \reentrant |
|
624 \brief The QXmlLocator class provides the XML handler classes with |
|
625 information about the parsing position within a file. |
|
626 |
|
627 \inmodule QtXml |
|
628 \ingroup xml-tools |
|
629 |
|
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. |
|
635 */ |
|
636 |
|
637 /*! |
|
638 Constructor. |
|
639 */ |
|
640 QXmlLocator::QXmlLocator() |
|
641 { |
|
642 } |
|
643 |
|
644 /*! |
|
645 Destructor. |
|
646 */ |
|
647 QXmlLocator::~QXmlLocator() |
|
648 { |
|
649 } |
|
650 |
|
651 /*! |
|
652 \fn int QXmlLocator::columnNumber() const |
|
653 |
|
654 Returns the column number (starting at 1) or -1 if there is no |
|
655 column number available. |
|
656 */ |
|
657 |
|
658 /*! |
|
659 \fn int QXmlLocator::lineNumber() const |
|
660 |
|
661 Returns the line number (starting at 1) or -1 if there is no line |
|
662 number available. |
|
663 */ |
|
664 |
|
665 class QXmlSimpleReaderLocator : public QXmlLocator |
|
666 { |
|
667 public: |
|
668 QXmlSimpleReaderLocator(QXmlSimpleReader* parent) |
|
669 { |
|
670 reader = parent; |
|
671 } |
|
672 ~QXmlSimpleReaderLocator() |
|
673 { |
|
674 } |
|
675 |
|
676 int columnNumber() const |
|
677 { |
|
678 return (reader->d_ptr->columnNr == -1 ? -1 : reader->d_ptr->columnNr + 1); |
|
679 } |
|
680 int lineNumber() const |
|
681 { |
|
682 return (reader->d_ptr->lineNr == -1 ? -1 : reader->d_ptr->lineNr + 1); |
|
683 } |
|
684 // QString getPublicId() |
|
685 // QString getSystemId() |
|
686 |
|
687 private: |
|
688 QXmlSimpleReader *reader; |
|
689 }; |
|
690 |
|
691 /********************************************* |
|
692 * |
|
693 * QXmlNamespaceSupport |
|
694 * |
|
695 *********************************************/ |
|
696 |
|
697 typedef QMap<QString, QString> NamespaceMap; |
|
698 |
|
699 class QXmlNamespaceSupportPrivate |
|
700 { |
|
701 public: |
|
702 QXmlNamespaceSupportPrivate() |
|
703 { |
|
704 ns.insert(QLatin1String("xml"), QLatin1String("http://www.w3.org/XML/1998/namespace")); // the XML namespace |
|
705 } |
|
706 |
|
707 ~QXmlNamespaceSupportPrivate() |
|
708 { |
|
709 } |
|
710 |
|
711 QStack<NamespaceMap> nsStack; |
|
712 NamespaceMap ns; |
|
713 }; |
|
714 |
|
715 /*! |
|
716 \class QXmlNamespaceSupport |
|
717 \since 4.4 |
|
718 \reentrant |
|
719 \brief The QXmlNamespaceSupport class is a helper class for XML |
|
720 readers which want to include namespace support. |
|
721 |
|
722 \inmodule QtXml |
|
723 \ingroup xml-tools |
|
724 |
|
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. |
|
731 |
|
732 \sa {Namespace Support via Features} |
|
733 */ |
|
734 |
|
735 /*! |
|
736 Constructs a QXmlNamespaceSupport. |
|
737 */ |
|
738 QXmlNamespaceSupport::QXmlNamespaceSupport() |
|
739 { |
|
740 d = new QXmlNamespaceSupportPrivate; |
|
741 } |
|
742 |
|
743 /*! |
|
744 Destroys a QXmlNamespaceSupport. |
|
745 */ |
|
746 QXmlNamespaceSupport::~QXmlNamespaceSupport() |
|
747 { |
|
748 delete d; |
|
749 } |
|
750 |
|
751 /*! |
|
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 |
|
755 descendant context. |
|
756 |
|
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. |
|
762 */ |
|
763 void QXmlNamespaceSupport::setPrefix(const QString& pre, const QString& uri) |
|
764 { |
|
765 if(pre.isNull()) { |
|
766 d->ns.insert(QLatin1String(""), uri); |
|
767 } else { |
|
768 d->ns.insert(pre, uri); |
|
769 } |
|
770 } |
|
771 |
|
772 /*! |
|
773 Returns one of the prefixes mapped to the namespace URI \a uri. |
|
774 |
|
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. |
|
778 |
|
779 Note: to check for a default prefix, use the uri() function with |
|
780 an argument of "". |
|
781 */ |
|
782 QString QXmlNamespaceSupport::prefix(const QString& uri) const |
|
783 { |
|
784 NamespaceMap::const_iterator itc, it = d->ns.constBegin(); |
|
785 while ((itc=it) != d->ns.constEnd()) { |
|
786 ++it; |
|
787 if (*itc == uri && !itc.key().isEmpty()) |
|
788 return itc.key(); |
|
789 } |
|
790 return QLatin1String(""); |
|
791 } |
|
792 |
|
793 /*! |
|
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. |
|
797 */ |
|
798 QString QXmlNamespaceSupport::uri(const QString& prefix) const |
|
799 { |
|
800 return d->ns[prefix]; |
|
801 } |
|
802 |
|
803 /*! |
|
804 Splits the name \a qname at the ':' and returns the prefix in \a |
|
805 prefix and the local name in \a localname. |
|
806 |
|
807 \sa processName() |
|
808 */ |
|
809 void QXmlNamespaceSupport::splitName(const QString& qname, QString& prefix, |
|
810 QString& localname) const |
|
811 { |
|
812 int pos = qname.indexOf(QLatin1Char(':')); |
|
813 if (pos == -1) |
|
814 pos = qname.size(); |
|
815 |
|
816 prefix = qname.left(pos); |
|
817 localname = qname.mid(pos+1); |
|
818 } |
|
819 |
|
820 /*! |
|
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 |
|
823 declared. |
|
824 |
|
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. |
|
827 |
|
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). |
|
832 |
|
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. |
|
836 */ |
|
837 void QXmlNamespaceSupport::processName(const QString& qname, |
|
838 bool isAttribute, |
|
839 QString& nsuri, QString& localname) const |
|
840 { |
|
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); |
|
847 return; |
|
848 } |
|
849 } |
|
850 |
|
851 // there was no ':' |
|
852 nsuri.clear(); |
|
853 // attributes don't take default namespace |
|
854 if (!isAttribute && !d->ns.isEmpty()) { |
|
855 /* |
|
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. |
|
859 */ |
|
860 NamespaceMap::const_iterator first = d->ns.constBegin(); |
|
861 if (first.key().isEmpty()) |
|
862 nsuri = first.value(); // get default namespace |
|
863 } |
|
864 localname = qname; |
|
865 } |
|
866 |
|
867 /*! |
|
868 Returns a list of all the prefixes currently declared. |
|
869 |
|
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 |
|
872 argument of "". |
|
873 */ |
|
874 QStringList QXmlNamespaceSupport::prefixes() const |
|
875 { |
|
876 QStringList list; |
|
877 |
|
878 NamespaceMap::const_iterator itc, it = d->ns.constBegin(); |
|
879 while ((itc=it) != d->ns.constEnd()) { |
|
880 ++it; |
|
881 if (!itc.key().isEmpty()) |
|
882 list.append(itc.key()); |
|
883 } |
|
884 return list; |
|
885 } |
|
886 |
|
887 /*! |
|
888 \overload |
|
889 |
|
890 Returns a list of all prefixes currently declared for the |
|
891 namespace URI \a uri. |
|
892 |
|
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. |
|
896 |
|
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 |
|
899 "" as the argument. |
|
900 */ |
|
901 QStringList QXmlNamespaceSupport::prefixes(const QString& uri) const |
|
902 { |
|
903 QStringList list; |
|
904 |
|
905 NamespaceMap::const_iterator itc, it = d->ns.constBegin(); |
|
906 while ((itc=it) != d->ns.constEnd()) { |
|
907 ++it; |
|
908 if (*itc == uri && !itc.key().isEmpty()) |
|
909 list.append(itc.key()); |
|
910 } |
|
911 return list; |
|
912 } |
|
913 |
|
914 /*! |
|
915 Starts a new namespace context. |
|
916 |
|
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. |
|
921 |
|
922 \sa popContext() |
|
923 */ |
|
924 void QXmlNamespaceSupport::pushContext() |
|
925 { |
|
926 d->nsStack.push(d->ns); |
|
927 } |
|
928 |
|
929 /*! |
|
930 Reverts to the previous namespace context. |
|
931 |
|
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. |
|
935 |
|
936 \sa pushContext() |
|
937 */ |
|
938 void QXmlNamespaceSupport::popContext() |
|
939 { |
|
940 d->ns.clear(); |
|
941 if(!d->nsStack.isEmpty()) |
|
942 d->ns = d->nsStack.pop(); |
|
943 } |
|
944 |
|
945 /*! |
|
946 Resets this namespace support object ready for reuse. |
|
947 */ |
|
948 void QXmlNamespaceSupport::reset() |
|
949 { |
|
950 QXmlNamespaceSupportPrivate *newD = new QXmlNamespaceSupportPrivate; |
|
951 delete d; |
|
952 d = newD; |
|
953 } |
|
954 |
|
955 |
|
956 |
|
957 /********************************************* |
|
958 * |
|
959 * QXmlAttributes |
|
960 * |
|
961 *********************************************/ |
|
962 |
|
963 /*! |
|
964 \class QXmlAttributes |
|
965 \reentrant |
|
966 \brief The QXmlAttributes class provides XML attributes. |
|
967 |
|
968 \inmodule QtXml |
|
969 \ingroup xml-tools |
|
970 |
|
971 If attributes are reported by QXmlContentHandler::startElement() |
|
972 this class is used to pass the attribute values. |
|
973 |
|
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(). |
|
980 |
|
981 */ |
|
982 |
|
983 /*! |
|
984 \fn QXmlAttributes::QXmlAttributes() |
|
985 |
|
986 Constructs an empty attribute list. |
|
987 */ |
|
988 |
|
989 /*! |
|
990 \fn QXmlAttributes::~QXmlAttributes() |
|
991 |
|
992 Destroys the attributes object. |
|
993 */ |
|
994 |
|
995 /*! |
|
996 Looks up the index of an attribute by the qualified name \a qName. |
|
997 |
|
998 Returns the index of the attribute or -1 if it wasn't found. |
|
999 |
|
1000 \sa {Namespace Support via Features} |
|
1001 */ |
|
1002 int QXmlAttributes::index(const QString& qName) const |
|
1003 { |
|
1004 for (int i = 0; i < attList.size(); ++i) { |
|
1005 if (attList.at(i).qname == qName) |
|
1006 return i; |
|
1007 } |
|
1008 return -1; |
|
1009 } |
|
1010 |
|
1011 /*! \overload |
|
1012 */ |
|
1013 int QXmlAttributes::index(const QLatin1String& qName) const |
|
1014 { |
|
1015 for (int i = 0; i < attList.size(); ++i) { |
|
1016 if (attList.at(i).qname == qName) |
|
1017 return i; |
|
1018 } |
|
1019 return -1; |
|
1020 } |
|
1021 |
|
1022 /*! |
|
1023 \overload |
|
1024 |
|
1025 Looks up the index of an attribute by a namespace name. |
|
1026 |
|
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 |
|
1029 name. |
|
1030 |
|
1031 Returns the index of the attribute, or -1 if it wasn't found. |
|
1032 |
|
1033 \sa {Namespace Support via Features} |
|
1034 */ |
|
1035 int QXmlAttributes::index(const QString& uri, const QString& localPart) const |
|
1036 { |
|
1037 for (int i = 0; i < attList.size(); ++i) { |
|
1038 const Attribute &att = attList.at(i); |
|
1039 if (att.uri == uri && att.localname == localPart) |
|
1040 return i; |
|
1041 } |
|
1042 return -1; |
|
1043 } |
|
1044 |
|
1045 /*! |
|
1046 Returns the number of attributes in the list. |
|
1047 |
|
1048 \sa count() |
|
1049 */ |
|
1050 int QXmlAttributes::length() const |
|
1051 { |
|
1052 return attList.count(); |
|
1053 } |
|
1054 |
|
1055 /*! |
|
1056 \fn int QXmlAttributes::count() const |
|
1057 |
|
1058 Returns the number of attributes in the list. This function is |
|
1059 equivalent to length(). |
|
1060 */ |
|
1061 |
|
1062 /*! |
|
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 |
|
1065 an empty string. |
|
1066 |
|
1067 \sa {Namespace Support via Features} |
|
1068 */ |
|
1069 QString QXmlAttributes::localName(int index) const |
|
1070 { |
|
1071 return attList.at(index).localname; |
|
1072 } |
|
1073 |
|
1074 /*! |
|
1075 Looks up an attribute's XML 1.0 qualified name for the attribute |
|
1076 at position \a index. |
|
1077 |
|
1078 \sa {Namespace Support via Features} |
|
1079 */ |
|
1080 QString QXmlAttributes::qName(int index) const |
|
1081 { |
|
1082 return attList.at(index).qname; |
|
1083 } |
|
1084 |
|
1085 /*! |
|
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. |
|
1089 |
|
1090 \sa {Namespace Support via Features} |
|
1091 */ |
|
1092 QString QXmlAttributes::uri(int index) const |
|
1093 { |
|
1094 return attList.at(index).uri; |
|
1095 } |
|
1096 |
|
1097 /*! |
|
1098 Looks up an attribute's type for the attribute at position \a |
|
1099 index. |
|
1100 |
|
1101 Currently only "CDATA" is returned. |
|
1102 */ |
|
1103 QString QXmlAttributes::type(int) const |
|
1104 { |
|
1105 return QLatin1String("CDATA"); |
|
1106 } |
|
1107 |
|
1108 /*! |
|
1109 \overload |
|
1110 |
|
1111 Looks up an attribute's type for the qualified name \a qName. |
|
1112 |
|
1113 Currently only "CDATA" is returned. |
|
1114 */ |
|
1115 QString QXmlAttributes::type(const QString&) const |
|
1116 { |
|
1117 return QLatin1String("CDATA"); |
|
1118 } |
|
1119 |
|
1120 /*! |
|
1121 \overload |
|
1122 |
|
1123 Looks up an attribute's type by namespace name. |
|
1124 |
|
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 |
|
1127 for \a uri. |
|
1128 |
|
1129 Currently only "CDATA" is returned. |
|
1130 */ |
|
1131 QString QXmlAttributes::type(const QString&, const QString&) const |
|
1132 { |
|
1133 return QLatin1String("CDATA"); |
|
1134 } |
|
1135 |
|
1136 /*! |
|
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()). |
|
1140 */ |
|
1141 QString QXmlAttributes::value(int index) const |
|
1142 { |
|
1143 return attList.at(index).value; |
|
1144 } |
|
1145 |
|
1146 /*! |
|
1147 \overload |
|
1148 |
|
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. |
|
1151 |
|
1152 \sa {Namespace Support via Features} |
|
1153 */ |
|
1154 QString QXmlAttributes::value(const QString& qName) const |
|
1155 { |
|
1156 int i = index(qName); |
|
1157 if (i == -1) |
|
1158 return QString(); |
|
1159 return attList.at(i).value; |
|
1160 } |
|
1161 |
|
1162 /*! |
|
1163 \overload |
|
1164 |
|
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. |
|
1167 |
|
1168 \sa {Namespace Support via Features} |
|
1169 */ |
|
1170 QString QXmlAttributes::value(const QLatin1String& qName) const |
|
1171 { |
|
1172 int i = index(qName); |
|
1173 if (i == -1) |
|
1174 return QString(); |
|
1175 return attList.at(i).value; |
|
1176 } |
|
1177 |
|
1178 /*! |
|
1179 \overload |
|
1180 |
|
1181 Returns an attribute's value by namespace name. |
|
1182 |
|
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 |
|
1185 name. |
|
1186 */ |
|
1187 QString QXmlAttributes::value(const QString& uri, const QString& localName) const |
|
1188 { |
|
1189 int i = index(uri, localName); |
|
1190 if (i == -1) |
|
1191 return QString(); |
|
1192 return attList.at(i).value; |
|
1193 } |
|
1194 |
|
1195 /*! |
|
1196 Clears the list of attributes. |
|
1197 |
|
1198 \sa append() |
|
1199 */ |
|
1200 void QXmlAttributes::clear() |
|
1201 { |
|
1202 attList.clear(); |
|
1203 } |
|
1204 |
|
1205 /*! |
|
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. |
|
1210 |
|
1211 \sa qName() uri() localName() value() |
|
1212 */ |
|
1213 void QXmlAttributes::append(const QString &qName, const QString &uri, const QString &localPart, const QString &value) |
|
1214 { |
|
1215 Attribute att; |
|
1216 att.qname = qName; |
|
1217 att.uri = uri; |
|
1218 att.localname = localPart; |
|
1219 att.value = value; |
|
1220 |
|
1221 attList.append(att); |
|
1222 } |
|
1223 |
|
1224 |
|
1225 /********************************************* |
|
1226 * |
|
1227 * QXmlInputSource |
|
1228 * |
|
1229 *********************************************/ |
|
1230 |
|
1231 /*! |
|
1232 \class QXmlInputSource |
|
1233 \reentrant |
|
1234 \brief The QXmlInputSource class provides the input data for the |
|
1235 QXmlReader subclasses. |
|
1236 |
|
1237 \inmodule QtXml |
|
1238 \ingroup xml-tools |
|
1239 |
|
1240 All subclasses of QXmlReader read the input XML document from this |
|
1241 class. |
|
1242 |
|
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 |
|
1248 mark. |
|
1249 |
|
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. |
|
1254 |
|
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. |
|
1259 |
|
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(). |
|
1263 |
|
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. |
|
1268 |
|
1269 \sa QXmlReader QXmlSimpleReader |
|
1270 */ |
|
1271 |
|
1272 // the following two are guaranteed not to be a character |
|
1273 const ushort QXmlInputSource::EndOfData = 0xfffe; |
|
1274 const ushort QXmlInputSource::EndOfDocument = 0xffff; |
|
1275 |
|
1276 /* |
|
1277 Common part of the constructors. |
|
1278 */ |
|
1279 void QXmlInputSource::init() |
|
1280 { |
|
1281 d = new QXmlInputSourcePrivate; |
|
1282 |
|
1283 QT_TRY { |
|
1284 d->inputDevice = 0; |
|
1285 d->inputStream = 0; |
|
1286 |
|
1287 setData(QString()); |
|
1288 #ifndef QT_NO_TEXTCODEC |
|
1289 d->encMapper = 0; |
|
1290 #endif |
|
1291 d->nextReturnedEndOfData = true; // first call to next() will call fetchData() |
|
1292 |
|
1293 d->encodingDeclBytes.clear(); |
|
1294 d->encodingDeclChars.clear(); |
|
1295 d->lookingForEncodingDecl = true; |
|
1296 } QT_CATCH(...) { |
|
1297 delete(d); |
|
1298 QT_RETHROW; |
|
1299 } |
|
1300 } |
|
1301 |
|
1302 /*! |
|
1303 Constructs an input source which contains no data. |
|
1304 |
|
1305 \sa setData() |
|
1306 */ |
|
1307 QXmlInputSource::QXmlInputSource() |
|
1308 { |
|
1309 init(); |
|
1310 } |
|
1311 |
|
1312 /*! |
|
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. |
|
1317 |
|
1318 \sa setData() fetchData() QIODevice |
|
1319 */ |
|
1320 QXmlInputSource::QXmlInputSource(QIODevice *dev) |
|
1321 { |
|
1322 init(); |
|
1323 d->inputDevice = dev; |
|
1324 d->inputDevice->setTextModeEnabled(false); |
|
1325 } |
|
1326 |
|
1327 #ifdef QT3_SUPPORT |
|
1328 /*! |
|
1329 Use the QXmlInputSource(QIODevice *) constructor instead, with |
|
1330 the device used by \a stream. |
|
1331 |
|
1332 \sa QTextStream::device() |
|
1333 */ |
|
1334 QXmlInputSource::QXmlInputSource(QTextStream& stream) |
|
1335 { |
|
1336 init(); |
|
1337 d->inputStream = &stream; |
|
1338 } |
|
1339 |
|
1340 /*! |
|
1341 Use QXmlInputSource(&\a file) instead. |
|
1342 */ |
|
1343 QXmlInputSource::QXmlInputSource(QFile& file) |
|
1344 { |
|
1345 init(); |
|
1346 d->inputDevice = &file; |
|
1347 } |
|
1348 #endif |
|
1349 |
|
1350 /*! |
|
1351 Destructor. |
|
1352 */ |
|
1353 QXmlInputSource::~QXmlInputSource() |
|
1354 { |
|
1355 // ### Qt 5: close the input device. See task 153111 |
|
1356 #ifndef QT_NO_TEXTCODEC |
|
1357 delete d->encMapper; |
|
1358 #endif |
|
1359 delete d; |
|
1360 } |
|
1361 |
|
1362 /*! |
|
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. |
|
1370 |
|
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 |
|
1376 duplicated. |
|
1377 |
|
1378 \sa reset() fetchData() QXmlSimpleReader::parse() QXmlSimpleReader::parseContinue() |
|
1379 */ |
|
1380 QChar QXmlInputSource::next() |
|
1381 { |
|
1382 if (d->pos >= d->length) { |
|
1383 if (d->nextReturnedEndOfData) { |
|
1384 d->nextReturnedEndOfData = false; |
|
1385 fetchData(); |
|
1386 if (d->pos >= d->length) { |
|
1387 return EndOfDocument; |
|
1388 } |
|
1389 return next(); |
|
1390 } |
|
1391 d->nextReturnedEndOfData = true; |
|
1392 return EndOfData; |
|
1393 } |
|
1394 |
|
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) |
|
1400 c = EndOfDocument; |
|
1401 return c; |
|
1402 } |
|
1403 |
|
1404 /*! |
|
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. |
|
1408 |
|
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. |
|
1412 |
|
1413 \sa next() |
|
1414 */ |
|
1415 void QXmlInputSource::reset() |
|
1416 { |
|
1417 d->nextReturnedEndOfData = false; |
|
1418 d->pos = 0; |
|
1419 } |
|
1420 |
|
1421 /*! |
|
1422 Returns the data the input source contains or an empty string if the |
|
1423 input source does not contain any data. |
|
1424 |
|
1425 \sa setData() QXmlInputSource() fetchData() |
|
1426 */ |
|
1427 QString QXmlInputSource::data() const |
|
1428 { |
|
1429 if (d->nextReturnedEndOfData) { |
|
1430 QXmlInputSource *that = const_cast<QXmlInputSource*>(this); |
|
1431 that->d->nextReturnedEndOfData = false; |
|
1432 that->fetchData(); |
|
1433 } |
|
1434 return d->str; |
|
1435 } |
|
1436 |
|
1437 /*! |
|
1438 Sets the data of the input source to \a dat. |
|
1439 |
|
1440 If the input source already contains data, this function deletes |
|
1441 that data first. |
|
1442 |
|
1443 \sa data() |
|
1444 */ |
|
1445 void QXmlInputSource::setData(const QString& dat) |
|
1446 { |
|
1447 d->str = dat; |
|
1448 d->unicode = dat.unicode(); |
|
1449 d->pos = 0; |
|
1450 d->length = d->str.length(); |
|
1451 d->nextReturnedEndOfData = false; |
|
1452 } |
|
1453 |
|
1454 /*! |
|
1455 \overload |
|
1456 |
|
1457 The data \a dat is passed through the correct text-codec, before |
|
1458 it is set. |
|
1459 */ |
|
1460 void QXmlInputSource::setData(const QByteArray& dat) |
|
1461 { |
|
1462 setData(fromRawData(dat)); |
|
1463 } |
|
1464 |
|
1465 /*! |
|
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. |
|
1469 |
|
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. |
|
1473 |
|
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). |
|
1478 |
|
1479 You don't normally need to use this function if you use next(). |
|
1480 |
|
1481 \sa data() next() QXmlInputSource() |
|
1482 */ |
|
1483 |
|
1484 void QXmlInputSource::fetchData() |
|
1485 { |
|
1486 enum |
|
1487 { |
|
1488 BufferSize = 1024 |
|
1489 }; |
|
1490 |
|
1491 QByteArray rawData; |
|
1492 |
|
1493 if (d->inputDevice || d->inputStream) { |
|
1494 QIODevice *device = d->inputDevice ? d->inputDevice : d->inputStream->device(); |
|
1495 |
|
1496 if (!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)); |
|
1500 } |
|
1501 } else if (device->isOpen() || device->open(QIODevice::ReadOnly)) { |
|
1502 rawData.resize(BufferSize); |
|
1503 qint64 size = device->read(rawData.data(), BufferSize); |
|
1504 |
|
1505 if (size != -1) { |
|
1506 // We don't want to give fromRawData() less than four bytes if we can avoid it. |
|
1507 while (size < 4) { |
|
1508 if (!device->waitForReadyRead(-1)) |
|
1509 break; |
|
1510 int ret = device->read(rawData.data() + size, BufferSize - size); |
|
1511 if (ret <= 0) |
|
1512 break; |
|
1513 size += ret; |
|
1514 } |
|
1515 } |
|
1516 |
|
1517 rawData.resize(qMax(qint64(0), size)); |
|
1518 } |
|
1519 |
|
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 |
|
1523 * d->str. */ |
|
1524 setData(fromRawData(rawData)); |
|
1525 } |
|
1526 } |
|
1527 |
|
1528 #ifndef QT_NO_TEXTCODEC |
|
1529 static QString extractEncodingDecl(const QString &text, bool *needMoreText) |
|
1530 { |
|
1531 *needMoreText = false; |
|
1532 |
|
1533 int l = text.length(); |
|
1534 QString snip = QString::fromLatin1("<?xml").left(l); |
|
1535 if (l > 0 && !text.startsWith(snip)) |
|
1536 return QString(); |
|
1537 |
|
1538 int endPos = text.indexOf(QLatin1Char('>')); |
|
1539 if (endPos == -1) { |
|
1540 *needMoreText = l < 255; // we won't look forever |
|
1541 return QString(); |
|
1542 } |
|
1543 |
|
1544 int pos = text.indexOf(QLatin1String("encoding")); |
|
1545 if (pos == -1 || pos >= endPos) |
|
1546 return QString(); |
|
1547 |
|
1548 while (pos < endPos) { |
|
1549 ushort uc = text.at(pos).unicode(); |
|
1550 if (uc == '\'' || uc == '"') |
|
1551 break; |
|
1552 ++pos; |
|
1553 } |
|
1554 |
|
1555 if (pos == endPos) |
|
1556 return QString(); |
|
1557 |
|
1558 QString encoding; |
|
1559 ++pos; |
|
1560 while (pos < endPos) { |
|
1561 ushort uc = text.at(pos).unicode(); |
|
1562 if (uc == '\'' || uc == '"') |
|
1563 break; |
|
1564 encoding.append(uc); |
|
1565 ++pos; |
|
1566 } |
|
1567 |
|
1568 return encoding; |
|
1569 } |
|
1570 #endif // QT_NO_TEXTCODEC |
|
1571 |
|
1572 /*! |
|
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. |
|
1577 |
|
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. |
|
1582 */ |
|
1583 QString QXmlInputSource::fromRawData(const QByteArray &data, bool beginning) |
|
1584 { |
|
1585 #ifdef QT_NO_TEXTCODEC |
|
1586 Q_UNUSED(beginning); |
|
1587 return QString::fromAscii(data.constData(), data.size()); |
|
1588 #else |
|
1589 if (data.size() == 0) |
|
1590 return QString(); |
|
1591 if (beginning) { |
|
1592 delete d->encMapper; |
|
1593 d->encMapper = 0; |
|
1594 } |
|
1595 |
|
1596 int mib = 106; // UTF-8 |
|
1597 |
|
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; |
|
1603 |
|
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); |
|
1610 |
|
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 |
|
1618 } |
|
1619 if (mib == 106 && data.size() >= 2) { |
|
1620 uchar ch1 = data.at(0); |
|
1621 uchar ch2 = data.at(1); |
|
1622 |
|
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 |
|
1629 } |
|
1630 |
|
1631 QTextCodec *codec = QTextCodec::codecForMib(mib); |
|
1632 Q_ASSERT(codec); |
|
1633 |
|
1634 d->encMapper = codec->makeDecoder(); |
|
1635 } |
|
1636 |
|
1637 QString input = d->encMapper->toUnicode(data, data.size()); |
|
1638 |
|
1639 if (d->lookingForEncodingDecl) { |
|
1640 d->encodingDeclChars += input; |
|
1641 |
|
1642 bool needMoreText; |
|
1643 QString encoding = extractEncodingDecl(d->encodingDeclChars, &needMoreText); |
|
1644 |
|
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(); |
|
1651 |
|
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. */ |
|
1655 input.clear(); |
|
1656 |
|
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()); |
|
1661 } |
|
1662 } |
|
1663 } |
|
1664 |
|
1665 d->encodingDeclBytes += data; |
|
1666 d->lookingForEncodingDecl = needMoreText; |
|
1667 } |
|
1668 |
|
1669 return input; |
|
1670 #endif |
|
1671 } |
|
1672 |
|
1673 |
|
1674 /********************************************* |
|
1675 * |
|
1676 * QXmlDefaultHandler |
|
1677 * |
|
1678 *********************************************/ |
|
1679 |
|
1680 /*! |
|
1681 \class QXmlContentHandler |
|
1682 \reentrant |
|
1683 \brief The QXmlContentHandler class provides an interface to |
|
1684 report the logical content of XML data. |
|
1685 |
|
1686 \inmodule QtXml |
|
1687 \ingroup xml-tools |
|
1688 |
|
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. |
|
1694 |
|
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. |
|
1700 |
|
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 |
|
1704 events. |
|
1705 |
|
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. |
|
1716 |
|
1717 \sa QXmlDTDHandler, QXmlDeclHandler, QXmlEntityResolver, QXmlErrorHandler, |
|
1718 QXmlLexicalHandler, {Introduction to SAX2} |
|
1719 */ |
|
1720 |
|
1721 /*! |
|
1722 \fn QXmlContentHandler::~QXmlContentHandler() |
|
1723 |
|
1724 Destroys the content handler. |
|
1725 */ |
|
1726 |
|
1727 /*! |
|
1728 \fn void QXmlContentHandler::setDocumentLocator(QXmlLocator* locator) |
|
1729 |
|
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 |
|
1733 the document. |
|
1734 |
|
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 |
|
1737 destroyed). |
|
1738 */ |
|
1739 |
|
1740 /*! |
|
1741 \fn bool QXmlContentHandler::startDocument() |
|
1742 |
|
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. |
|
1747 |
|
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. |
|
1751 |
|
1752 \sa endDocument() |
|
1753 */ |
|
1754 |
|
1755 /*! |
|
1756 \fn bool QXmlContentHandler::endDocument() |
|
1757 |
|
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. |
|
1762 |
|
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. |
|
1766 |
|
1767 \sa startDocument() |
|
1768 */ |
|
1769 |
|
1770 /*! |
|
1771 \fn bool QXmlContentHandler::startPrefixMapping(const QString& prefix, const QString& uri) |
|
1772 |
|
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. |
|
1777 |
|
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. |
|
1784 |
|
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. |
|
1787 |
|
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. |
|
1791 |
|
1792 \sa endPrefixMapping(), {Namespace Support via Features} |
|
1793 */ |
|
1794 |
|
1795 /*! |
|
1796 \fn bool QXmlContentHandler::endPrefixMapping(const QString& prefix) |
|
1797 |
|
1798 The reader calls this function to signal the end of a prefix |
|
1799 mapping for the prefix \a prefix. |
|
1800 |
|
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. |
|
1804 |
|
1805 \sa startPrefixMapping(), {Namespace Support via Features} |
|
1806 */ |
|
1807 |
|
1808 /*! |
|
1809 \fn bool QXmlContentHandler::startElement(const QString& namespaceURI, const QString& localName, const QString& qName, const QXmlAttributes& atts) |
|
1810 |
|
1811 The reader calls this function when it has parsed a start element |
|
1812 tag. |
|
1813 |
|
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 |
|
1818 endElement() call. |
|
1819 |
|
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. |
|
1824 |
|
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. |
|
1832 |
|
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. |
|
1836 |
|
1837 \sa endElement(), {Namespace Support via Features} |
|
1838 */ |
|
1839 |
|
1840 /*! |
|
1841 \fn bool QXmlContentHandler::endElement(const QString& namespaceURI, const QString& localName, const QString& qName) |
|
1842 |
|
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. |
|
1846 |
|
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. |
|
1850 |
|
1851 \sa startElement(), {Namespace Support via Features} |
|
1852 */ |
|
1853 |
|
1854 /*! |
|
1855 \fn bool QXmlContentHandler::characters(const QString& ch) |
|
1856 |
|
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 |
|
1862 \a ch. |
|
1863 |
|
1864 Some readers report whitespace in element content using the |
|
1865 ignorableWhitespace() function rather than using this one. |
|
1866 |
|
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"). |
|
1870 |
|
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. |
|
1874 */ |
|
1875 |
|
1876 /*! |
|
1877 \fn bool QXmlContentHandler::ignorableWhitespace(const QString& ch) |
|
1878 |
|
1879 Some readers may use this function to report each chunk of |
|
1880 whitespace in element content. The whitespace is reported in \a ch. |
|
1881 |
|
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. |
|
1885 */ |
|
1886 |
|
1887 /*! |
|
1888 \fn bool QXmlContentHandler::processingInstruction(const QString& target, const QString& data) |
|
1889 |
|
1890 The reader calls this function when it has parsed a processing |
|
1891 instruction. |
|
1892 |
|
1893 \a target is the target name of the processing instruction and \a |
|
1894 data is the data in the processing instruction. |
|
1895 |
|
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. |
|
1899 */ |
|
1900 |
|
1901 /*! |
|
1902 \fn bool QXmlContentHandler::skippedEntity(const QString& name) |
|
1903 |
|
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. |
|
1908 |
|
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. |
|
1912 */ |
|
1913 |
|
1914 /*! |
|
1915 \fn QString QXmlContentHandler::errorString() const |
|
1916 |
|
1917 The reader calls this function to get an error string, e.g. if any |
|
1918 of the handler functions returns false. |
|
1919 */ |
|
1920 |
|
1921 |
|
1922 /*! |
|
1923 \class QXmlErrorHandler |
|
1924 \reentrant |
|
1925 \brief The QXmlErrorHandler class provides an interface to report |
|
1926 errors in XML data. |
|
1927 |
|
1928 \inmodule QtXml |
|
1929 \ingroup xml-tools |
|
1930 |
|
1931 If you want your application to report errors to the user or to |
|
1932 perform customized error handling, you should subclass this class. |
|
1933 |
|
1934 You can set the error handler with QXmlReader::setErrorHandler(). |
|
1935 |
|
1936 Errors can be reported using warning(), error() and fatalError(), |
|
1937 with the error text being reported with errorString(). |
|
1938 |
|
1939 \sa QXmlDTDHandler, QXmlDeclHandler, QXmlContentHandler, QXmlEntityResolver, |
|
1940 QXmlLexicalHandler, {Introduction to SAX2} |
|
1941 */ |
|
1942 |
|
1943 /*! |
|
1944 \fn QXmlErrorHandler::~QXmlErrorHandler() |
|
1945 |
|
1946 Destroys the error handler. |
|
1947 */ |
|
1948 |
|
1949 /*! |
|
1950 \fn bool QXmlErrorHandler::warning(const QXmlParseException& exception) |
|
1951 |
|
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 |
|
1955 exception. |
|
1956 |
|
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. |
|
1960 */ |
|
1961 |
|
1962 /*! |
|
1963 \fn bool QXmlErrorHandler::error(const QXmlParseException& exception) |
|
1964 |
|
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. |
|
1969 |
|
1970 The reader must continue to provide normal parsing events after |
|
1971 invoking this function. |
|
1972 |
|
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. |
|
1976 */ |
|
1977 |
|
1978 /*! |
|
1979 \fn bool QXmlErrorHandler::fatalError(const QXmlParseException& exception) |
|
1980 |
|
1981 A reader must use this function to report a non-recoverable error. |
|
1982 Details of the error are stored in \a exception. |
|
1983 |
|
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. |
|
1987 */ |
|
1988 |
|
1989 /*! |
|
1990 \fn QString QXmlErrorHandler::errorString() const |
|
1991 |
|
1992 The reader calls this function to get an error string if any of |
|
1993 the handler functions returns false. |
|
1994 */ |
|
1995 |
|
1996 |
|
1997 /*! |
|
1998 \class QXmlDTDHandler |
|
1999 \reentrant |
|
2000 \brief The QXmlDTDHandler class provides an interface to report |
|
2001 DTD content of XML data. |
|
2002 |
|
2003 \inmodule QtXml |
|
2004 \ingroup xml-tools |
|
2005 |
|
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(). |
|
2009 |
|
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. |
|
2014 |
|
2015 \sa QXmlDeclHandler, QXmlContentHandler, QXmlEntityResolver, QXmlErrorHandler, |
|
2016 QXmlLexicalHandler, {Introduction to SAX2} |
|
2017 */ |
|
2018 |
|
2019 /*! |
|
2020 \fn QXmlDTDHandler::~QXmlDTDHandler() |
|
2021 |
|
2022 Destroys the DTD handler. |
|
2023 */ |
|
2024 |
|
2025 /*! |
|
2026 \fn bool QXmlDTDHandler::notationDecl(const QString& name, const QString& publicId, const QString& systemId) |
|
2027 |
|
2028 The reader calls this function when it has parsed a notation |
|
2029 declaration. |
|
2030 |
|
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 |
|
2033 system identifier. |
|
2034 |
|
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. |
|
2038 */ |
|
2039 |
|
2040 /*! |
|
2041 \fn bool QXmlDTDHandler::unparsedEntityDecl(const QString& name, const QString& publicId, const QString& systemId, const QString& notationName) |
|
2042 |
|
2043 The reader calls this function when it finds an unparsed entity |
|
2044 declaration. |
|
2045 |
|
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 |
|
2049 notation. |
|
2050 |
|
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. |
|
2054 */ |
|
2055 |
|
2056 /*! |
|
2057 \fn QString QXmlDTDHandler::errorString() const |
|
2058 |
|
2059 The reader calls this function to get an error string if any of |
|
2060 the handler functions returns false. |
|
2061 */ |
|
2062 |
|
2063 |
|
2064 /*! |
|
2065 \class QXmlEntityResolver |
|
2066 \reentrant |
|
2067 \brief The QXmlEntityResolver class provides an interface to |
|
2068 resolve external entities contained in XML data. |
|
2069 |
|
2070 \inmodule QtXml |
|
2071 \ingroup xml-tools |
|
2072 |
|
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(). |
|
2077 |
|
2078 \sa QXmlDTDHandler, QXmlDeclHandler, QXmlContentHandler, QXmlErrorHandler, |
|
2079 QXmlLexicalHandler, {Introduction to SAX2} |
|
2080 */ |
|
2081 |
|
2082 /*! |
|
2083 \fn QXmlEntityResolver::~QXmlEntityResolver() |
|
2084 |
|
2085 Destroys the entity resolver. |
|
2086 */ |
|
2087 |
|
2088 /*! |
|
2089 \fn bool QXmlEntityResolver::resolveEntity(const QString& publicId, const QString& systemId, QXmlInputSource*& ret) |
|
2090 |
|
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 |
|
2095 input source). |
|
2096 |
|
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. |
|
2099 |
|
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 |
|
2105 instead. |
|
2106 |
|
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. |
|
2110 */ |
|
2111 |
|
2112 /*! |
|
2113 \fn QString QXmlEntityResolver::errorString() const |
|
2114 |
|
2115 The reader calls this function to get an error string if any of |
|
2116 the handler functions returns false. |
|
2117 */ |
|
2118 |
|
2119 |
|
2120 /*! |
|
2121 \class QXmlLexicalHandler |
|
2122 \reentrant |
|
2123 \brief The QXmlLexicalHandler class provides an interface to |
|
2124 report the lexical content of XML data. |
|
2125 |
|
2126 \inmodule QtXml |
|
2127 \ingroup xml-tools |
|
2128 |
|
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 |
|
2132 events. |
|
2133 |
|
2134 You can set the lexical handler with |
|
2135 QXmlReader::setLexicalHandler(). |
|
2136 |
|
2137 This interface's design is based on the SAX2 extension |
|
2138 LexicalHandler. |
|
2139 |
|
2140 The interface provides the startDTD(), endDTD(), startEntity(), |
|
2141 endEntity(), startCDATA(), endCDATA() and comment() functions. |
|
2142 |
|
2143 \sa QXmlDTDHandler, QXmlDeclHandler, QXmlContentHandler, QXmlEntityResolver, |
|
2144 QXmlErrorHandler, {Introduction to SAX2} |
|
2145 */ |
|
2146 |
|
2147 /*! |
|
2148 \fn QXmlLexicalHandler::~QXmlLexicalHandler() |
|
2149 |
|
2150 Destroys the lexical handler. |
|
2151 */ |
|
2152 |
|
2153 /*! |
|
2154 \fn bool QXmlLexicalHandler::startDTD(const QString& name, const QString& publicId, const QString& systemId) |
|
2155 |
|
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. |
|
2160 |
|
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 |
|
2165 error will occur. |
|
2166 |
|
2167 All declarations reported through QXmlDTDHandler or |
|
2168 QXmlDeclHandler appear between the startDTD() and endDTD() calls. |
|
2169 |
|
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. |
|
2173 |
|
2174 \sa endDTD() |
|
2175 */ |
|
2176 |
|
2177 /*! |
|
2178 \fn bool QXmlLexicalHandler::endDTD() |
|
2179 |
|
2180 The reader calls this function to report the end of a DTD |
|
2181 declaration, if any. |
|
2182 |
|
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. |
|
2186 |
|
2187 \sa startDTD() |
|
2188 */ |
|
2189 |
|
2190 /*! |
|
2191 \fn bool QXmlLexicalHandler::startEntity(const QString& name) |
|
2192 |
|
2193 The reader calls this function to report the start of an entity |
|
2194 called \a name. |
|
2195 |
|
2196 Note that if the entity is unknown, the reader reports it through |
|
2197 QXmlContentHandler::skippedEntity() and not through this |
|
2198 function. |
|
2199 |
|
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. |
|
2203 |
|
2204 \sa endEntity(), QXmlSimpleReader::setFeature() |
|
2205 */ |
|
2206 |
|
2207 /*! |
|
2208 \fn bool QXmlLexicalHandler::endEntity(const QString& name) |
|
2209 |
|
2210 The reader calls this function to report the end of an entity |
|
2211 called \a name. |
|
2212 |
|
2213 For every startEntity() call, there is a corresponding endEntity() |
|
2214 call. The calls to startEntity() and endEntity() are properly |
|
2215 nested. |
|
2216 |
|
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. |
|
2220 |
|
2221 \sa startEntity(), QXmlContentHandler::skippedEntity(), QXmlSimpleReader::setFeature() |
|
2222 */ |
|
2223 |
|
2224 /*! |
|
2225 \fn bool QXmlLexicalHandler::startCDATA() |
|
2226 |
|
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. |
|
2231 |
|
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. |
|
2235 |
|
2236 \sa endCDATA() |
|
2237 */ |
|
2238 |
|
2239 /*! |
|
2240 \fn bool QXmlLexicalHandler::endCDATA() |
|
2241 |
|
2242 The reader calls this function to report the end of a CDATA |
|
2243 section. |
|
2244 |
|
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 |
|
2247 message. |
|
2248 |
|
2249 \sa startCDATA(), QXmlContentHandler::characters() |
|
2250 */ |
|
2251 |
|
2252 /*! |
|
2253 \fn bool QXmlLexicalHandler::comment(const QString& ch) |
|
2254 |
|
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. |
|
2257 |
|
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. |
|
2261 */ |
|
2262 |
|
2263 /*! |
|
2264 \fn QString QXmlLexicalHandler::errorString() const |
|
2265 |
|
2266 The reader calls this function to get an error string if any of |
|
2267 the handler functions returns false. |
|
2268 */ |
|
2269 |
|
2270 |
|
2271 /*! |
|
2272 \class QXmlDeclHandler |
|
2273 \reentrant |
|
2274 \brief The QXmlDeclHandler class provides an interface to report declaration |
|
2275 content of XML data. |
|
2276 |
|
2277 \inmodule QtXml |
|
2278 \ingroup xml-tools |
|
2279 |
|
2280 You can set the declaration handler with |
|
2281 QXmlReader::setDeclHandler(). |
|
2282 |
|
2283 This interface is based on the SAX2 extension DeclHandler. |
|
2284 |
|
2285 The interface provides attributeDecl(), internalEntityDecl() and |
|
2286 externalEntityDecl() functions. |
|
2287 |
|
2288 \sa QXmlDTDHandler, QXmlContentHandler, QXmlEntityResolver, QXmlErrorHandler, |
|
2289 QXmlLexicalHandler, {Introduction to SAX2} |
|
2290 */ |
|
2291 |
|
2292 /*! |
|
2293 \fn QXmlDeclHandler::~QXmlDeclHandler() |
|
2294 |
|
2295 Destroys the declaration handler. |
|
2296 */ |
|
2297 |
|
2298 /*! |
|
2299 \fn bool QXmlDeclHandler::attributeDecl(const QString& eName, const QString& aName, const QString& type, const QString& valueDefault, const QString& value) |
|
2300 |
|
2301 The reader calls this function to report an attribute type |
|
2302 declaration. Only the effective (first) declaration for an |
|
2303 attribute is reported. |
|
2304 |
|
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. |
|
2313 |
|
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. |
|
2317 */ |
|
2318 |
|
2319 /*! |
|
2320 \fn bool QXmlDeclHandler::internalEntityDecl(const QString& name, const QString& value) |
|
2321 |
|
2322 The reader calls this function to report an internal entity |
|
2323 declaration. Only the effective (first) declaration is reported. |
|
2324 |
|
2325 The reader passes the name of the entity in \a name and the value |
|
2326 of the entity in \a value. |
|
2327 |
|
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. |
|
2331 */ |
|
2332 |
|
2333 /*! |
|
2334 \fn bool QXmlDeclHandler::externalEntityDecl(const QString& name, const QString& publicId, const QString& systemId) |
|
2335 |
|
2336 The reader calls this function to report a parsed external entity |
|
2337 declaration. Only the effective (first) declaration for each |
|
2338 entity is reported. |
|
2339 |
|
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. |
|
2344 |
|
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. |
|
2348 */ |
|
2349 |
|
2350 /*! |
|
2351 \fn QString QXmlDeclHandler::errorString() const |
|
2352 |
|
2353 The reader calls this function to get an error string if any of |
|
2354 the handler functions returns false. |
|
2355 */ |
|
2356 |
|
2357 |
|
2358 /*! |
|
2359 \class QXmlDefaultHandler |
|
2360 \reentrant |
|
2361 \brief The QXmlDefaultHandler class provides a default implementation of all |
|
2362 the XML handler classes. |
|
2363 |
|
2364 \inmodule QtXml |
|
2365 \ingroup xml-tools |
|
2366 |
|
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 |
|
2376 application. |
|
2377 |
|
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. |
|
2383 |
|
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 |
|
2387 reader functions: |
|
2388 |
|
2389 \snippet doc/src/snippets/xml/rsslisting/rsslisting.cpp 0 |
|
2390 |
|
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: |
|
2394 |
|
2395 \snippet doc/src/snippets/xml/rsslisting/handler.cpp 0 |
|
2396 |
|
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. |
|
2401 |
|
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. |
|
2414 |
|
2415 \sa QXmlDTDHandler, QXmlDeclHandler, QXmlContentHandler, QXmlEntityResolver, |
|
2416 QXmlErrorHandler, QXmlLexicalHandler, {Introduction to SAX2} |
|
2417 */ |
|
2418 |
|
2419 /*! |
|
2420 \fn QXmlDefaultHandler::QXmlDefaultHandler() |
|
2421 |
|
2422 Constructs a handler for use with subclasses of QXmlReader. |
|
2423 */ |
|
2424 /*! |
|
2425 \fn QXmlDefaultHandler::~QXmlDefaultHandler() |
|
2426 |
|
2427 Destroys the handler. |
|
2428 */ |
|
2429 |
|
2430 /*! |
|
2431 \reimp |
|
2432 |
|
2433 This reimplementation does nothing. |
|
2434 */ |
|
2435 void QXmlDefaultHandler::setDocumentLocator(QXmlLocator*) |
|
2436 { |
|
2437 } |
|
2438 |
|
2439 /*! |
|
2440 \reimp |
|
2441 |
|
2442 This reimplementation does nothing. |
|
2443 */ |
|
2444 bool QXmlDefaultHandler::startDocument() |
|
2445 { |
|
2446 return true; |
|
2447 } |
|
2448 |
|
2449 /*! |
|
2450 \reimp |
|
2451 |
|
2452 This reimplementation does nothing. |
|
2453 */ |
|
2454 bool QXmlDefaultHandler::endDocument() |
|
2455 { |
|
2456 return true; |
|
2457 } |
|
2458 |
|
2459 /*! |
|
2460 \reimp |
|
2461 |
|
2462 This reimplementation does nothing. |
|
2463 */ |
|
2464 bool QXmlDefaultHandler::startPrefixMapping(const QString&, const QString&) |
|
2465 { |
|
2466 return true; |
|
2467 } |
|
2468 |
|
2469 /*! |
|
2470 \reimp |
|
2471 |
|
2472 This reimplementation does nothing. |
|
2473 */ |
|
2474 bool QXmlDefaultHandler::endPrefixMapping(const QString&) |
|
2475 { |
|
2476 return true; |
|
2477 } |
|
2478 |
|
2479 /*! |
|
2480 \reimp |
|
2481 |
|
2482 This reimplementation does nothing. |
|
2483 */ |
|
2484 bool QXmlDefaultHandler::startElement(const QString&, const QString&, |
|
2485 const QString&, const QXmlAttributes&) |
|
2486 { |
|
2487 return true; |
|
2488 } |
|
2489 |
|
2490 /*! |
|
2491 \reimp |
|
2492 |
|
2493 This reimplementation does nothing. |
|
2494 */ |
|
2495 bool QXmlDefaultHandler::endElement(const QString&, const QString&, |
|
2496 const QString&) |
|
2497 { |
|
2498 return true; |
|
2499 } |
|
2500 |
|
2501 /*! |
|
2502 \reimp |
|
2503 |
|
2504 This reimplementation does nothing. |
|
2505 */ |
|
2506 bool QXmlDefaultHandler::characters(const QString&) |
|
2507 { |
|
2508 return true; |
|
2509 } |
|
2510 |
|
2511 /*! |
|
2512 \reimp |
|
2513 |
|
2514 This reimplementation does nothing. |
|
2515 */ |
|
2516 bool QXmlDefaultHandler::ignorableWhitespace(const QString&) |
|
2517 { |
|
2518 return true; |
|
2519 } |
|
2520 |
|
2521 /*! |
|
2522 \reimp |
|
2523 |
|
2524 This reimplementation does nothing. |
|
2525 */ |
|
2526 bool QXmlDefaultHandler::processingInstruction(const QString&, |
|
2527 const QString&) |
|
2528 { |
|
2529 return true; |
|
2530 } |
|
2531 |
|
2532 /*! |
|
2533 \reimp |
|
2534 |
|
2535 This reimplementation does nothing. |
|
2536 */ |
|
2537 bool QXmlDefaultHandler::skippedEntity(const QString&) |
|
2538 { |
|
2539 return true; |
|
2540 } |
|
2541 |
|
2542 /*! |
|
2543 \reimp |
|
2544 |
|
2545 This reimplementation does nothing. |
|
2546 */ |
|
2547 bool QXmlDefaultHandler::warning(const QXmlParseException&) |
|
2548 { |
|
2549 return true; |
|
2550 } |
|
2551 |
|
2552 /*! |
|
2553 \reimp |
|
2554 |
|
2555 This reimplementation does nothing. |
|
2556 */ |
|
2557 bool QXmlDefaultHandler::error(const QXmlParseException&) |
|
2558 { |
|
2559 return true; |
|
2560 } |
|
2561 |
|
2562 /*! |
|
2563 \reimp |
|
2564 |
|
2565 This reimplementation does nothing. |
|
2566 */ |
|
2567 bool QXmlDefaultHandler::fatalError(const QXmlParseException&) |
|
2568 { |
|
2569 return true; |
|
2570 } |
|
2571 |
|
2572 /*! |
|
2573 \reimp |
|
2574 |
|
2575 This reimplementation does nothing. |
|
2576 */ |
|
2577 bool QXmlDefaultHandler::notationDecl(const QString&, const QString&, |
|
2578 const QString&) |
|
2579 { |
|
2580 return true; |
|
2581 } |
|
2582 |
|
2583 /*! |
|
2584 \reimp |
|
2585 |
|
2586 This reimplementation does nothing. |
|
2587 */ |
|
2588 bool QXmlDefaultHandler::unparsedEntityDecl(const QString&, const QString&, |
|
2589 const QString&, const QString&) |
|
2590 { |
|
2591 return true; |
|
2592 } |
|
2593 |
|
2594 /*! |
|
2595 \reimp |
|
2596 |
|
2597 Sets \a ret to 0, so that the reader uses the system identifier |
|
2598 provided in the XML document. |
|
2599 */ |
|
2600 bool QXmlDefaultHandler::resolveEntity(const QString&, const QString&, |
|
2601 QXmlInputSource*& ret) |
|
2602 { |
|
2603 ret = 0; |
|
2604 return true; |
|
2605 } |
|
2606 |
|
2607 /*! |
|
2608 \reimp |
|
2609 |
|
2610 Returns the default error string. |
|
2611 */ |
|
2612 QString QXmlDefaultHandler::errorString() const |
|
2613 { |
|
2614 return QString::fromLatin1(XMLERR_ERRORBYCONSUMER); |
|
2615 } |
|
2616 |
|
2617 /*! |
|
2618 \reimp |
|
2619 |
|
2620 This reimplementation does nothing. |
|
2621 */ |
|
2622 bool QXmlDefaultHandler::startDTD(const QString&, const QString&, const QString&) |
|
2623 { |
|
2624 return true; |
|
2625 } |
|
2626 |
|
2627 /*! |
|
2628 \reimp |
|
2629 |
|
2630 This reimplementation does nothing. |
|
2631 */ |
|
2632 bool QXmlDefaultHandler::endDTD() |
|
2633 { |
|
2634 return true; |
|
2635 } |
|
2636 |
|
2637 /*! |
|
2638 \reimp |
|
2639 |
|
2640 This reimplementation does nothing. |
|
2641 */ |
|
2642 bool QXmlDefaultHandler::startEntity(const QString&) |
|
2643 { |
|
2644 return true; |
|
2645 } |
|
2646 |
|
2647 /*! |
|
2648 \reimp |
|
2649 |
|
2650 This reimplementation does nothing. |
|
2651 */ |
|
2652 bool QXmlDefaultHandler::endEntity(const QString&) |
|
2653 { |
|
2654 return true; |
|
2655 } |
|
2656 |
|
2657 /*! |
|
2658 \reimp |
|
2659 |
|
2660 This reimplementation does nothing. |
|
2661 */ |
|
2662 bool QXmlDefaultHandler::startCDATA() |
|
2663 { |
|
2664 return true; |
|
2665 } |
|
2666 |
|
2667 /*! |
|
2668 \reimp |
|
2669 |
|
2670 This reimplementation does nothing. |
|
2671 */ |
|
2672 bool QXmlDefaultHandler::endCDATA() |
|
2673 { |
|
2674 return true; |
|
2675 } |
|
2676 |
|
2677 /*! |
|
2678 \reimp |
|
2679 |
|
2680 This reimplementation does nothing. |
|
2681 */ |
|
2682 bool QXmlDefaultHandler::comment(const QString&) |
|
2683 { |
|
2684 return true; |
|
2685 } |
|
2686 |
|
2687 /*! |
|
2688 \reimp |
|
2689 |
|
2690 This reimplementation does nothing. |
|
2691 */ |
|
2692 bool QXmlDefaultHandler::attributeDecl(const QString&, const QString&, const QString&, const QString&, const QString&) |
|
2693 { |
|
2694 return true; |
|
2695 } |
|
2696 |
|
2697 /*! |
|
2698 \reimp |
|
2699 |
|
2700 This reimplementation does nothing. |
|
2701 */ |
|
2702 bool QXmlDefaultHandler::internalEntityDecl(const QString&, const QString&) |
|
2703 { |
|
2704 return true; |
|
2705 } |
|
2706 |
|
2707 /*! |
|
2708 \reimp |
|
2709 |
|
2710 This reimplementation does nothing. |
|
2711 */ |
|
2712 bool QXmlDefaultHandler::externalEntityDecl(const QString&, const QString&, const QString&) |
|
2713 { |
|
2714 return true; |
|
2715 } |
|
2716 |
|
2717 |
|
2718 /********************************************* |
|
2719 * |
|
2720 * QXmlSimpleReaderPrivate |
|
2721 * |
|
2722 *********************************************/ |
|
2723 |
|
2724 inline bool QXmlSimpleReaderPrivate::atEnd() |
|
2725 { |
|
2726 return (c.unicode()|0x0001) == 0xffff; |
|
2727 } |
|
2728 |
|
2729 inline void QXmlSimpleReaderPrivate::stringClear() |
|
2730 { |
|
2731 stringValueLen = 0; stringArrayPos = 0; |
|
2732 } |
|
2733 inline void QXmlSimpleReaderPrivate::nameClear() |
|
2734 { |
|
2735 nameValueLen = 0; nameArrayPos = 0; |
|
2736 } |
|
2737 |
|
2738 inline void QXmlSimpleReaderPrivate::refClear() |
|
2739 { |
|
2740 refValueLen = 0; refArrayPos = 0; |
|
2741 } |
|
2742 |
|
2743 QXmlSimpleReaderPrivate::QXmlSimpleReaderPrivate(QXmlSimpleReader *reader) |
|
2744 { |
|
2745 q_ptr = reader; |
|
2746 parseStack = 0; |
|
2747 |
|
2748 locator.reset(new QXmlSimpleReaderLocator(reader)); |
|
2749 entityRes = 0; |
|
2750 dtdHnd = 0; |
|
2751 contentHnd = 0; |
|
2752 errorHnd = 0; |
|
2753 lexicalHnd = 0; |
|
2754 declHnd = 0; |
|
2755 |
|
2756 // default feature settings |
|
2757 useNamespaces = true; |
|
2758 useNamespacePrefixes = false; |
|
2759 reportWhitespaceCharData = true; |
|
2760 reportEntities = false; |
|
2761 } |
|
2762 |
|
2763 QXmlSimpleReaderPrivate::~QXmlSimpleReaderPrivate() |
|
2764 { |
|
2765 delete parseStack; |
|
2766 } |
|
2767 |
|
2768 void QXmlSimpleReaderPrivate::initIncrementalParsing() |
|
2769 { |
|
2770 if(parseStack) |
|
2771 parseStack->clear(); |
|
2772 else |
|
2773 parseStack = new QStack<ParseState>; |
|
2774 } |
|
2775 |
|
2776 /********************************************* |
|
2777 * |
|
2778 * QXmlSimpleReader |
|
2779 * |
|
2780 *********************************************/ |
|
2781 |
|
2782 /*! |
|
2783 \class QXmlReader |
|
2784 \reentrant |
|
2785 \brief The QXmlReader class provides an interface for XML readers (i.e. |
|
2786 parsers). |
|
2787 |
|
2788 \inmodule QtXml |
|
2789 \ingroup xml-tools |
|
2790 |
|
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). |
|
2796 |
|
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 |
|
2801 Qt XML classes. |
|
2802 |
|
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. |
|
2810 |
|
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. |
|
2816 |
|
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 |
|
2822 parse(). |
|
2823 |
|
2824 \sa QXmlSimpleReader |
|
2825 */ |
|
2826 |
|
2827 /*! |
|
2828 \fn QXmlReader::~QXmlReader() |
|
2829 |
|
2830 Destroys the reader. |
|
2831 */ |
|
2832 |
|
2833 /*! |
|
2834 \fn bool QXmlReader::feature(const QString& name, bool *ok) const |
|
2835 |
|
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 |
|
2838 undefined. |
|
2839 |
|
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. |
|
2842 |
|
2843 \sa setFeature(), hasFeature() |
|
2844 */ |
|
2845 |
|
2846 /*! |
|
2847 \fn void QXmlReader::setFeature(const QString& name, bool value) |
|
2848 |
|
2849 Sets the feature called \a name to the given \a value. If the |
|
2850 reader doesn't have the feature nothing happens. |
|
2851 |
|
2852 \sa feature(), hasFeature() |
|
2853 */ |
|
2854 |
|
2855 /*! |
|
2856 \fn bool QXmlReader::hasFeature(const QString& name) const |
|
2857 |
|
2858 Returns \c true if the reader has the feature called \a name; |
|
2859 otherwise returns false. |
|
2860 |
|
2861 \sa feature(), setFeature() |
|
2862 */ |
|
2863 |
|
2864 /*! |
|
2865 \fn void* QXmlReader::property(const QString& name, bool *ok) const |
|
2866 |
|
2867 If the reader has the property \a name, this function returns the |
|
2868 value of the property; otherwise the return value is undefined. |
|
2869 |
|
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. |
|
2872 |
|
2873 \sa setProperty(), hasProperty() |
|
2874 */ |
|
2875 |
|
2876 /*! |
|
2877 \fn void QXmlReader::setProperty(const QString& name, void* value) |
|
2878 |
|
2879 Sets the property \a name to \a value. If the reader doesn't have |
|
2880 the property nothing happens. |
|
2881 |
|
2882 \sa property(), hasProperty() |
|
2883 */ |
|
2884 |
|
2885 /*! |
|
2886 \fn bool QXmlReader::hasProperty(const QString& name) const |
|
2887 |
|
2888 Returns true if the reader has the property \a name; otherwise |
|
2889 returns false. |
|
2890 |
|
2891 \sa property(), setProperty() |
|
2892 */ |
|
2893 |
|
2894 /*! |
|
2895 \fn void QXmlReader::setEntityResolver(QXmlEntityResolver* handler) |
|
2896 |
|
2897 Sets the entity resolver to \a handler. |
|
2898 |
|
2899 \sa entityResolver() |
|
2900 */ |
|
2901 |
|
2902 /*! |
|
2903 \fn QXmlEntityResolver* QXmlReader::entityResolver() const |
|
2904 |
|
2905 Returns the entity resolver or 0 if none was set. |
|
2906 |
|
2907 \sa setEntityResolver() |
|
2908 */ |
|
2909 |
|
2910 /*! |
|
2911 \fn void QXmlReader::setDTDHandler(QXmlDTDHandler* handler) |
|
2912 |
|
2913 Sets the DTD handler to \a handler. |
|
2914 |
|
2915 \sa DTDHandler() |
|
2916 */ |
|
2917 |
|
2918 /*! |
|
2919 \fn QXmlDTDHandler* QXmlReader::DTDHandler() const |
|
2920 |
|
2921 Returns the DTD handler or 0 if none was set. |
|
2922 |
|
2923 \sa setDTDHandler() |
|
2924 */ |
|
2925 |
|
2926 /*! |
|
2927 \fn void QXmlReader::setContentHandler(QXmlContentHandler* handler) |
|
2928 |
|
2929 Sets the content handler to \a handler. |
|
2930 |
|
2931 \sa contentHandler() |
|
2932 */ |
|
2933 |
|
2934 /*! |
|
2935 \fn QXmlContentHandler* QXmlReader::contentHandler() const |
|
2936 |
|
2937 Returns the content handler or 0 if none was set. |
|
2938 |
|
2939 \sa setContentHandler() |
|
2940 */ |
|
2941 |
|
2942 /*! |
|
2943 \fn void QXmlReader::setErrorHandler(QXmlErrorHandler* handler) |
|
2944 |
|
2945 Sets the error handler to \a handler. Clears the error handler if |
|
2946 \a handler is 0. |
|
2947 |
|
2948 \sa errorHandler() |
|
2949 */ |
|
2950 |
|
2951 /*! |
|
2952 \fn QXmlErrorHandler* QXmlReader::errorHandler() const |
|
2953 |
|
2954 Returns the error handler or 0 if none is set. |
|
2955 |
|
2956 \sa setErrorHandler() |
|
2957 */ |
|
2958 |
|
2959 /*! |
|
2960 \fn void QXmlReader::setLexicalHandler(QXmlLexicalHandler* handler) |
|
2961 |
|
2962 Sets the lexical handler to \a handler. |
|
2963 |
|
2964 \sa lexicalHandler() |
|
2965 */ |
|
2966 |
|
2967 /*! |
|
2968 \fn QXmlLexicalHandler* QXmlReader::lexicalHandler() const |
|
2969 |
|
2970 Returns the lexical handler or 0 if none was set. |
|
2971 |
|
2972 \sa setLexicalHandler() |
|
2973 */ |
|
2974 |
|
2975 /*! |
|
2976 \fn void QXmlReader::setDeclHandler(QXmlDeclHandler* handler) |
|
2977 |
|
2978 Sets the declaration handler to \a handler. |
|
2979 |
|
2980 \sa declHandler() |
|
2981 */ |
|
2982 |
|
2983 /*! |
|
2984 \fn QXmlDeclHandler* QXmlReader::declHandler() const |
|
2985 |
|
2986 Returns the declaration handler or 0 if none was set. |
|
2987 |
|
2988 \sa setDeclHandler() |
|
2989 */ |
|
2990 |
|
2991 /*! |
|
2992 \fn bool QXmlReader::parse(const QXmlInputSource &input) |
|
2993 |
|
2994 \obsolete |
|
2995 |
|
2996 Parses the given \a input. |
|
2997 */ |
|
2998 |
|
2999 /*! |
|
3000 \fn bool QXmlReader::parse(const QXmlInputSource *input) |
|
3001 |
|
3002 Reads an XML document from \a input and parses it. Returns true if |
|
3003 the parsing was successful; otherwise returns false. |
|
3004 */ |
|
3005 |
|
3006 |
|
3007 /*! |
|
3008 \class QXmlSimpleReader |
|
3009 \nonreentrant |
|
3010 \brief The QXmlSimpleReader class provides an implementation of a |
|
3011 simple XML parser. |
|
3012 |
|
3013 \inmodule QtXml |
|
3014 \ingroup xml-tools |
|
3015 |
|
3016 |
|
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. |
|
3023 |
|
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. |
|
3027 |
|
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 |
|
3030 reader: |
|
3031 |
|
3032 \snippet doc/src/snippets/xml/simpleparse/main.cpp 0 |
|
3033 |
|
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: |
|
3040 |
|
3041 \snippet doc/src/snippets/xml/simpleparse/main.cpp 1 |
|
3042 |
|
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 |
|
3045 nothing. |
|
3046 |
|
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: |
|
3050 |
|
3051 \snippet doc/src/snippets/xml/simpleparse/main.cpp 2 |
|
3052 |
|
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. |
|
3058 |
|
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. |
|
3062 |
|
3063 Aspects of the parsing behavior can be adapted using setFeature() |
|
3064 and setProperty(). |
|
3065 |
|
3066 QXmlSimpleReader is not reentrant. If you want to use the class |
|
3067 in threaded code, lock the code using QXmlSimpleReader with a |
|
3068 locking mechanism, such as a QMutex. |
|
3069 |
|
3070 \snippet doc/src/snippets/code/src_xml_sax_qxml.cpp 0 |
|
3071 */ |
|
3072 |
|
3073 static inline bool is_S(QChar ch) |
|
3074 { |
|
3075 ushort uc = ch.unicode(); |
|
3076 return (uc == ' ' || uc == '\t' || uc == '\n' || uc == '\r'); |
|
3077 } |
|
3078 |
|
3079 enum NameChar { NameBeginning, NameNotBeginning, NotName }; |
|
3080 |
|
3081 static const char Begi = (char)NameBeginning; |
|
3082 static const char NtBg = (char)NameNotBeginning; |
|
3083 static const char NotN = (char)NotName; |
|
3084 |
|
3085 static const char nameCharTable[128] = |
|
3086 { |
|
3087 // 0x00 |
|
3088 NotN, NotN, NotN, NotN, NotN, NotN, NotN, NotN, |
|
3089 NotN, NotN, NotN, NotN, NotN, NotN, NotN, NotN, |
|
3090 // 0x10 |
|
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, |
|
3108 // 0x70 |
|
3109 Begi, Begi, Begi, Begi, Begi, Begi, Begi, Begi, |
|
3110 Begi, Begi, Begi, NotN, NotN, NotN, NotN, NotN |
|
3111 }; |
|
3112 |
|
3113 static inline NameChar fastDetermineNameChar(QChar ch) |
|
3114 { |
|
3115 ushort uc = ch.unicode(); |
|
3116 if (!(uc & ~0x7f)) // uc < 128 |
|
3117 return (NameChar)nameCharTable[uc]; |
|
3118 |
|
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; |
|
3127 return NotName; |
|
3128 } |
|
3129 |
|
3130 static NameChar determineNameChar(QChar ch) |
|
3131 { |
|
3132 return fastDetermineNameChar(ch); |
|
3133 } |
|
3134 |
|
3135 /*! |
|
3136 Constructs a simple XML reader. |
|
3137 |
|
3138 */ |
|
3139 QXmlSimpleReader::QXmlSimpleReader() |
|
3140 : d_ptr(new QXmlSimpleReaderPrivate(this)) |
|
3141 { |
|
3142 } |
|
3143 |
|
3144 /*! |
|
3145 Destroys the simple XML reader. |
|
3146 */ |
|
3147 QXmlSimpleReader::~QXmlSimpleReader() |
|
3148 { |
|
3149 } |
|
3150 |
|
3151 /*! |
|
3152 \reimp |
|
3153 */ |
|
3154 bool QXmlSimpleReader::feature(const QString& name, bool *ok) const |
|
3155 { |
|
3156 const QXmlSimpleReaderPrivate *d = d_func(); |
|
3157 |
|
3158 // Qt5 ###: Change these strings to qt.nokia.com |
|
3159 if (ok != 0) |
|
3160 *ok = true; |
|
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; |
|
3169 } else { |
|
3170 qWarning("Unknown feature %s", name.toLatin1().data()); |
|
3171 if (ok != 0) |
|
3172 *ok = false; |
|
3173 } |
|
3174 return false; |
|
3175 } |
|
3176 |
|
3177 /*! |
|
3178 Turns on the feature \a name if \a enable is true; otherwise turns it off. |
|
3179 |
|
3180 The \a name parameter must be one of the following strings: |
|
3181 \table |
|
3182 \header \i Feature \i Default \i Notes |
|
3183 \row \i \e http://xml.org/sax/features/namespaces |
|
3184 \i true |
|
3185 \i If enabled, namespaces are reported to the content handler. |
|
3186 \row \i \e http://xml.org/sax/features/namespace-prefixes |
|
3187 \i false |
|
3188 \i If enabled, the original prefixed names |
|
3189 and attributes used for namespace declarations are |
|
3190 reported. |
|
3191 \row \i \e http://trolltech.com/xml/features/report-whitespace-only-CharData |
|
3192 \i true |
|
3193 \i If enabled, CharData that consist of |
|
3194 only whitespace characters are reported |
|
3195 using QXmlContentHandler::characters(). If disabled, whitespace is silently |
|
3196 discarded. |
|
3197 \row \i \e http://trolltech.com/xml/features/report-start-end-entity |
|
3198 \i false |
|
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 |
|
3205 data in one chunk. |
|
3206 \endtable |
|
3207 |
|
3208 \sa feature(), hasFeature(), {SAX2 Features} |
|
3209 */ |
|
3210 void QXmlSimpleReader::setFeature(const QString& name, bool enable) |
|
3211 { |
|
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; |
|
3222 } else { |
|
3223 qWarning("Unknown feature %s", name.toLatin1().data()); |
|
3224 } |
|
3225 } |
|
3226 |
|
3227 /*! \reimp |
|
3228 */ |
|
3229 bool QXmlSimpleReader::hasFeature(const QString& name) const |
|
3230 { |
|
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 |
|
3236 return true; |
|
3237 } else { |
|
3238 return false; |
|
3239 } |
|
3240 } |
|
3241 |
|
3242 /*! \reimp |
|
3243 */ |
|
3244 void* QXmlSimpleReader::property(const QString&, bool *ok) const |
|
3245 { |
|
3246 if (ok != 0) |
|
3247 *ok = false; |
|
3248 return 0; |
|
3249 } |
|
3250 |
|
3251 /*! \reimp |
|
3252 */ |
|
3253 void QXmlSimpleReader::setProperty(const QString&, void*) |
|
3254 { |
|
3255 } |
|
3256 |
|
3257 /*! |
|
3258 \reimp |
|
3259 */ |
|
3260 bool QXmlSimpleReader::hasProperty(const QString&) const |
|
3261 { |
|
3262 return false; |
|
3263 } |
|
3264 |
|
3265 /*! |
|
3266 \reimp |
|
3267 */ |
|
3268 void QXmlSimpleReader::setEntityResolver(QXmlEntityResolver* handler) |
|
3269 { |
|
3270 Q_D(QXmlSimpleReader); |
|
3271 d->entityRes = handler; |
|
3272 } |
|
3273 |
|
3274 /*! |
|
3275 \reimp |
|
3276 */ |
|
3277 QXmlEntityResolver* QXmlSimpleReader::entityResolver() const |
|
3278 { |
|
3279 const QXmlSimpleReaderPrivate *d = d_func(); |
|
3280 return d->entityRes; |
|
3281 } |
|
3282 |
|
3283 /*! |
|
3284 \reimp |
|
3285 */ |
|
3286 void QXmlSimpleReader::setDTDHandler(QXmlDTDHandler* handler) |
|
3287 { |
|
3288 Q_D(QXmlSimpleReader); |
|
3289 d->dtdHnd = handler; |
|
3290 } |
|
3291 |
|
3292 /*! |
|
3293 \reimp |
|
3294 */ |
|
3295 QXmlDTDHandler* QXmlSimpleReader::DTDHandler() const |
|
3296 { |
|
3297 const QXmlSimpleReaderPrivate *d = d_func(); |
|
3298 return d->dtdHnd; |
|
3299 } |
|
3300 |
|
3301 /*! |
|
3302 \reimp |
|
3303 */ |
|
3304 void QXmlSimpleReader::setContentHandler(QXmlContentHandler* handler) |
|
3305 { |
|
3306 Q_D(QXmlSimpleReader); |
|
3307 d->contentHnd = handler; |
|
3308 } |
|
3309 |
|
3310 /*! |
|
3311 \reimp |
|
3312 */ |
|
3313 QXmlContentHandler* QXmlSimpleReader::contentHandler() const |
|
3314 { |
|
3315 const QXmlSimpleReaderPrivate *d = d_func(); |
|
3316 return d->contentHnd; |
|
3317 } |
|
3318 |
|
3319 /*! |
|
3320 \reimp |
|
3321 */ |
|
3322 void QXmlSimpleReader::setErrorHandler(QXmlErrorHandler* handler) |
|
3323 { |
|
3324 Q_D(QXmlSimpleReader); |
|
3325 d->errorHnd = handler; |
|
3326 } |
|
3327 |
|
3328 /*! |
|
3329 \reimp |
|
3330 */ |
|
3331 QXmlErrorHandler* QXmlSimpleReader::errorHandler() const |
|
3332 { |
|
3333 const QXmlSimpleReaderPrivate *d = d_func(); |
|
3334 return d->errorHnd; |
|
3335 } |
|
3336 |
|
3337 /*! |
|
3338 \reimp |
|
3339 */ |
|
3340 void QXmlSimpleReader::setLexicalHandler(QXmlLexicalHandler* handler) |
|
3341 { |
|
3342 Q_D(QXmlSimpleReader); |
|
3343 d->lexicalHnd = handler; |
|
3344 } |
|
3345 |
|
3346 /*! |
|
3347 \reimp |
|
3348 */ |
|
3349 QXmlLexicalHandler* QXmlSimpleReader::lexicalHandler() const |
|
3350 { |
|
3351 const QXmlSimpleReaderPrivate *d = d_func(); |
|
3352 return d->lexicalHnd; |
|
3353 } |
|
3354 |
|
3355 /*! |
|
3356 \reimp |
|
3357 */ |
|
3358 void QXmlSimpleReader::setDeclHandler(QXmlDeclHandler* handler) |
|
3359 { |
|
3360 Q_D(QXmlSimpleReader); |
|
3361 d->declHnd = handler; |
|
3362 } |
|
3363 |
|
3364 /*! |
|
3365 \reimp |
|
3366 */ |
|
3367 QXmlDeclHandler* QXmlSimpleReader::declHandler() const |
|
3368 { |
|
3369 const QXmlSimpleReaderPrivate *d = d_func(); |
|
3370 return d->declHnd; |
|
3371 } |
|
3372 |
|
3373 |
|
3374 |
|
3375 /*! |
|
3376 \reimp |
|
3377 */ |
|
3378 bool QXmlSimpleReader::parse(const QXmlInputSource& input) |
|
3379 { |
|
3380 return parse(&input, false); |
|
3381 } |
|
3382 |
|
3383 /*! |
|
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. |
|
3386 */ |
|
3387 bool QXmlSimpleReader::parse(const QXmlInputSource* input) |
|
3388 { |
|
3389 return parse(input, false); |
|
3390 } |
|
3391 |
|
3392 /*! |
|
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. |
|
3396 |
|
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 |
|
3399 case. |
|
3400 |
|
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(). |
|
3410 |
|
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. |
|
3414 |
|
3415 \sa parseContinue(), QTcpSocket |
|
3416 */ |
|
3417 bool QXmlSimpleReader::parse(const QXmlInputSource *input, bool incremental) |
|
3418 { |
|
3419 Q_D(QXmlSimpleReader); |
|
3420 |
|
3421 if (incremental) { |
|
3422 d->initIncrementalParsing(); |
|
3423 } else { |
|
3424 delete d->parseStack; |
|
3425 d->parseStack = 0; |
|
3426 } |
|
3427 d->init(input); |
|
3428 |
|
3429 // call the handler |
|
3430 if (d->contentHnd) { |
|
3431 d->contentHnd->setDocumentLocator(d->locator.data()); |
|
3432 if (!d->contentHnd->startDocument()) { |
|
3433 d->reportParseError(d->contentHnd->errorString()); |
|
3434 d->tags.clear(); |
|
3435 return false; |
|
3436 } |
|
3437 } |
|
3438 qt_xml_skipped_entity_in_content = false; |
|
3439 return d->parseBeginOrContinue(0, incremental); |
|
3440 } |
|
3441 |
|
3442 /*! |
|
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. |
|
3447 |
|
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. |
|
3452 |
|
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. |
|
3460 |
|
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. |
|
3464 |
|
3465 \sa parse(), QXmlInputSource::data(), QXmlInputSource::next() |
|
3466 */ |
|
3467 bool QXmlSimpleReader::parseContinue() |
|
3468 { |
|
3469 Q_D(QXmlSimpleReader); |
|
3470 if (d->parseStack == 0 || d->parseStack->isEmpty()) |
|
3471 return false; |
|
3472 d->initData(); |
|
3473 int state = d->parseStack->pop().state; |
|
3474 return d->parseBeginOrContinue(state, true); |
|
3475 } |
|
3476 |
|
3477 /* |
|
3478 Common part of parse() and parseContinue() |
|
3479 */ |
|
3480 bool QXmlSimpleReaderPrivate::parseBeginOrContinue(int state, bool incremental) |
|
3481 { |
|
3482 bool atEndOrig = atEnd(); |
|
3483 |
|
3484 if (state==0) { |
|
3485 if (!parseProlog()) { |
|
3486 if (incremental && error.isNull()) { |
|
3487 pushParseState(0, 0); |
|
3488 return true; |
|
3489 } else { |
|
3490 tags.clear(); |
|
3491 return false; |
|
3492 } |
|
3493 } |
|
3494 state = 1; |
|
3495 } |
|
3496 if (state==1) { |
|
3497 if (!parseElement()) { |
|
3498 if (incremental && error.isNull()) { |
|
3499 pushParseState(0, 1); |
|
3500 return true; |
|
3501 } else { |
|
3502 tags.clear(); |
|
3503 return false; |
|
3504 } |
|
3505 } |
|
3506 state = 2; |
|
3507 } |
|
3508 // parse Misc* |
|
3509 while (!atEnd()) { |
|
3510 if (!parseMisc()) { |
|
3511 if (incremental && error.isNull()) { |
|
3512 pushParseState(0, 2); |
|
3513 return true; |
|
3514 } else { |
|
3515 tags.clear(); |
|
3516 return false; |
|
3517 } |
|
3518 } |
|
3519 } |
|
3520 if (!atEndOrig && incremental) { |
|
3521 // we parsed something at all, so be prepared to come back later |
|
3522 pushParseState(0, 2); |
|
3523 return true; |
|
3524 } |
|
3525 // is stack empty? |
|
3526 if (!tags.isEmpty() && !error.isNull()) { |
|
3527 reportParseError(QLatin1String(XMLERR_UNEXPECTEDEOF)); |
|
3528 tags.clear(); |
|
3529 return false; |
|
3530 } |
|
3531 // call the handler |
|
3532 if (contentHnd) { |
|
3533 delete parseStack; |
|
3534 parseStack = 0; |
|
3535 if (!contentHnd->endDocument()) { |
|
3536 reportParseError(contentHnd->errorString()); |
|
3537 return false; |
|
3538 } |
|
3539 } |
|
3540 return true; |
|
3541 } |
|
3542 |
|
3543 // |
|
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. |
|
3548 // |
|
3549 |
|
3550 /* |
|
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: |
|
3554 |
|
3555 bool QXmlSimpleReader::parse...() |
|
3556 { |
|
3557 (1) const signed char Init = 0; |
|
3558 ... |
|
3559 |
|
3560 (2) const signed char Inp... = 0; |
|
3561 ... |
|
3562 |
|
3563 (3) static const signed char table[3][2] = { |
|
3564 ... |
|
3565 }; |
|
3566 signed char state; |
|
3567 signed char input; |
|
3568 |
|
3569 (4) if (d->parseStack == 0 || d->parseStack->isEmpty()) { |
|
3570 (4a) ... |
|
3571 } else { |
|
3572 (4b) ... |
|
3573 } |
|
3574 |
|
3575 for (; ;) { |
|
3576 (5) switch (state) { |
|
3577 ... |
|
3578 } |
|
3579 |
|
3580 (6) |
|
3581 (6a) if (atEnd()) { |
|
3582 unexpectedEof(&QXmlSimpleReader::parseNmtoken, state); |
|
3583 return false; |
|
3584 } |
|
3585 (6b) if (determineNameChar(c) != NotName) { |
|
3586 ... |
|
3587 } |
|
3588 (7) state = table[state][input]; |
|
3589 |
|
3590 (8) switch (state) { |
|
3591 ... |
|
3592 } |
|
3593 } |
|
3594 } |
|
3595 |
|
3596 Explanation: |
|
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 |
|
3609 table. |
|
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 |
|
3616 out of data. |
|
3617 */ |
|
3618 |
|
3619 /* |
|
3620 Parses the prolog [22]. |
|
3621 */ |
|
3622 |
|
3623 bool QXmlSimpleReaderPrivate::parseProlog() |
|
3624 { |
|
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; |
|
3635 |
|
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; |
|
3643 |
|
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 |
|
3655 }; |
|
3656 signed char state; |
|
3657 signed char input; |
|
3658 |
|
3659 if (parseStack == 0 || parseStack->isEmpty()) { |
|
3660 xmldecl_possible = true; |
|
3661 doctype_read = false; |
|
3662 state = Init; |
|
3663 } else { |
|
3664 state = parseStack->pop().state; |
|
3665 #if defined(QT_QXML_DEBUG) |
|
3666 qDebug("QXmlSimpleReader: parseProlog (cont) in state %d", state); |
|
3667 #endif |
|
3668 if (!parseStack->isEmpty()) { |
|
3669 ParseFunction function = parseStack->top().function; |
|
3670 if (function == &QXmlSimpleReaderPrivate::eat_ws) { |
|
3671 parseStack->pop(); |
|
3672 #if defined(QT_QXML_DEBUG) |
|
3673 qDebug("QXmlSimpleReader: eat_ws (cont)"); |
|
3674 #endif |
|
3675 } |
|
3676 if (!(this->*function)()) { |
|
3677 parseFailed(&QXmlSimpleReaderPrivate::parseProlog, state); |
|
3678 return false; |
|
3679 } |
|
3680 } |
|
3681 } |
|
3682 |
|
3683 for (;;) { |
|
3684 switch (state) { |
|
3685 case DocType: |
|
3686 if (doctype_read) { |
|
3687 reportParseError(QLatin1String(XMLERR_MORETHANONEDOCTYPE)); |
|
3688 return false; |
|
3689 } else { |
|
3690 doctype_read = false; |
|
3691 } |
|
3692 break; |
|
3693 case Comment: |
|
3694 if (lexicalHnd) { |
|
3695 if (!lexicalHnd->comment(string())) { |
|
3696 reportParseError(lexicalHnd->errorString()); |
|
3697 return false; |
|
3698 } |
|
3699 } |
|
3700 state = CommentR; |
|
3701 break; |
|
3702 case PInstr: |
|
3703 // call the handler |
|
3704 if (contentHnd) { |
|
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='"); |
|
3711 value += encoding; |
|
3712 value += QLatin1Char('\''); |
|
3713 } |
|
3714 if (standalone == QXmlSimpleReaderPrivate::Yes) { |
|
3715 value += QLatin1String(" standalone='yes'"); |
|
3716 } else if (standalone == QXmlSimpleReaderPrivate::No) { |
|
3717 value += QLatin1String(" standalone='no'"); |
|
3718 } |
|
3719 if (!contentHnd->processingInstruction(QLatin1String("xml"), value)) { |
|
3720 reportParseError(contentHnd->errorString()); |
|
3721 return false; |
|
3722 } |
|
3723 } else { |
|
3724 if (!contentHnd->processingInstruction(name(), string())) { |
|
3725 reportParseError(contentHnd->errorString()); |
|
3726 return false; |
|
3727 } |
|
3728 } |
|
3729 } |
|
3730 // XML declaration only on first position possible |
|
3731 xmldecl_possible = false; |
|
3732 state = PInstrR; |
|
3733 break; |
|
3734 case Done: |
|
3735 return true; |
|
3736 case -1: |
|
3737 reportParseError(QLatin1String(XMLERR_ERRORPARSINGELEMENT)); |
|
3738 return false; |
|
3739 } |
|
3740 |
|
3741 if (atEnd()) { |
|
3742 unexpectedEof(&QXmlSimpleReaderPrivate::parseProlog, state); |
|
3743 return false; |
|
3744 } |
|
3745 if (is_S(c)) { |
|
3746 input = InpWs; |
|
3747 } else if (c == QLatin1Char('<')) { |
|
3748 input = InpLt; |
|
3749 } else if (c == QLatin1Char('?')) { |
|
3750 input = InpQm; |
|
3751 } else if (c == QLatin1Char('!')) { |
|
3752 input = InpEm; |
|
3753 } else if (c == QLatin1Char('D')) { |
|
3754 input = InpD; |
|
3755 } else if (c == QLatin1Char('-')) { |
|
3756 input = InpDash; |
|
3757 } else { |
|
3758 input = InpUnknown; |
|
3759 } |
|
3760 state = table[state][input]; |
|
3761 |
|
3762 switch (state) { |
|
3763 case EatWS: |
|
3764 // XML declaration only on first position possible |
|
3765 xmldecl_possible = false; |
|
3766 if (!eat_ws()) { |
|
3767 parseFailed(&QXmlSimpleReaderPrivate::parseProlog, state); |
|
3768 return false; |
|
3769 } |
|
3770 break; |
|
3771 case Lt: |
|
3772 next(); |
|
3773 break; |
|
3774 case Em: |
|
3775 // XML declaration only on first position possible |
|
3776 xmldecl_possible = false; |
|
3777 next(); |
|
3778 break; |
|
3779 case DocType: |
|
3780 if (!parseDoctype()) { |
|
3781 parseFailed(&QXmlSimpleReaderPrivate::parseProlog, state); |
|
3782 return false; |
|
3783 } |
|
3784 break; |
|
3785 case Comment: |
|
3786 case CommentR: |
|
3787 if (!parseComment()) { |
|
3788 parseFailed(&QXmlSimpleReaderPrivate::parseProlog, state); |
|
3789 return false; |
|
3790 } |
|
3791 break; |
|
3792 case PInstr: |
|
3793 case PInstrR: |
|
3794 parsePI_xmldecl = xmldecl_possible; |
|
3795 if (!parsePI()) { |
|
3796 parseFailed(&QXmlSimpleReaderPrivate::parseProlog, state); |
|
3797 return false; |
|
3798 } |
|
3799 break; |
|
3800 } |
|
3801 } |
|
3802 return false; |
|
3803 } |
|
3804 |
|
3805 /* |
|
3806 Parse an element [39]. |
|
3807 |
|
3808 Precondition: the opening '<' is already read. |
|
3809 */ |
|
3810 bool QXmlSimpleReaderPrivate::parseElement() |
|
3811 { |
|
3812 const int Init = 0; |
|
3813 const int ReadName = 1; |
|
3814 const int Ws1 = 2; |
|
3815 const int STagEnd = 3; |
|
3816 const int STagEnd2 = 4; |
|
3817 const int ETagBegin = 5; |
|
3818 const int ETagBegin2 = 6; |
|
3819 const int Ws2 = 7; |
|
3820 const int EmptyTag = 8; |
|
3821 const int Attrib = 9; |
|
3822 const int AttribPro = 10; // like Attrib, but processAttribute was already called |
|
3823 const int Ws3 = 11; |
|
3824 const int Done = 12; |
|
3825 |
|
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; |
|
3831 |
|
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 |
|
3846 }; |
|
3847 int state; |
|
3848 int input; |
|
3849 |
|
3850 if (parseStack == 0 || parseStack->isEmpty()) { |
|
3851 state = Init; |
|
3852 } else { |
|
3853 state = parseStack->pop().state; |
|
3854 #if defined(QT_QXML_DEBUG) |
|
3855 qDebug("QXmlSimpleReader: parseElement (cont) in state %d", state); |
|
3856 #endif |
|
3857 if (!parseStack->isEmpty()) { |
|
3858 ParseFunction function = parseStack->top().function; |
|
3859 if (function == &QXmlSimpleReaderPrivate::eat_ws) { |
|
3860 parseStack->pop(); |
|
3861 #if defined(QT_QXML_DEBUG) |
|
3862 qDebug("QXmlSimpleReader: eat_ws (cont)"); |
|
3863 #endif |
|
3864 } |
|
3865 if (!(this->*function)()) { |
|
3866 parseFailed(&QXmlSimpleReaderPrivate::parseElement, state); |
|
3867 return false; |
|
3868 } |
|
3869 } |
|
3870 } |
|
3871 |
|
3872 for (;;) { |
|
3873 switch (state) { |
|
3874 case ReadName: |
|
3875 // store it on the stack |
|
3876 tags.push(name()); |
|
3877 // empty the attributes |
|
3878 attList.clear(); |
|
3879 if (useNamespaces) |
|
3880 namespaceSupport.pushContext(); |
|
3881 break; |
|
3882 case ETagBegin2: |
|
3883 if (!processElementETagBegin2()) |
|
3884 return false; |
|
3885 break; |
|
3886 case Attrib: |
|
3887 if (!processElementAttribute()) |
|
3888 return false; |
|
3889 state = AttribPro; |
|
3890 break; |
|
3891 case Done: |
|
3892 return true; |
|
3893 case -1: |
|
3894 reportParseError(QLatin1String(XMLERR_ERRORPARSINGELEMENT)); |
|
3895 return false; |
|
3896 } |
|
3897 |
|
3898 if (atEnd()) { |
|
3899 unexpectedEof(&QXmlSimpleReaderPrivate::parseElement, state); |
|
3900 return false; |
|
3901 } |
|
3902 if (fastDetermineNameChar(c) == NameBeginning) { |
|
3903 input = InpNameBe; |
|
3904 } else if (c == QLatin1Char('>')) { |
|
3905 input = InpGt; |
|
3906 } else if (is_S(c)) { |
|
3907 input = InpWs; |
|
3908 } else if (c == QLatin1Char('/')) { |
|
3909 input = InpSlash; |
|
3910 } else { |
|
3911 input = InpUnknown; |
|
3912 } |
|
3913 state = table[state][input]; |
|
3914 |
|
3915 switch (state) { |
|
3916 case ReadName: |
|
3917 parseName_useRef = false; |
|
3918 if (!parseName()) { |
|
3919 parseFailed(&QXmlSimpleReaderPrivate::parseElement, state); |
|
3920 return false; |
|
3921 } |
|
3922 break; |
|
3923 case Ws1: |
|
3924 case Ws2: |
|
3925 case Ws3: |
|
3926 if (!eat_ws()) { |
|
3927 parseFailed(&QXmlSimpleReaderPrivate::parseElement, state); |
|
3928 return false; |
|
3929 } |
|
3930 break; |
|
3931 case STagEnd: |
|
3932 // call the handler |
|
3933 if (contentHnd) { |
|
3934 const QString &tagsTop = tags.top(); |
|
3935 if (useNamespaces) { |
|
3936 QString uri, lname; |
|
3937 namespaceSupport.processName(tagsTop, false, uri, lname); |
|
3938 if (!contentHnd->startElement(uri, lname, tagsTop, attList)) { |
|
3939 reportParseError(contentHnd->errorString()); |
|
3940 return false; |
|
3941 } |
|
3942 } else { |
|
3943 if (!contentHnd->startElement(QString(), QString(), tagsTop, attList)) { |
|
3944 reportParseError(contentHnd->errorString()); |
|
3945 return false; |
|
3946 } |
|
3947 } |
|
3948 } |
|
3949 next(); |
|
3950 break; |
|
3951 case STagEnd2: |
|
3952 if (!parseContent()) { |
|
3953 parseFailed(&QXmlSimpleReaderPrivate::parseElement, state); |
|
3954 return false; |
|
3955 } |
|
3956 break; |
|
3957 case ETagBegin: |
|
3958 next(); |
|
3959 break; |
|
3960 case ETagBegin2: |
|
3961 // get the name of the tag |
|
3962 parseName_useRef = false; |
|
3963 if (!parseName()) { |
|
3964 parseFailed(&QXmlSimpleReaderPrivate::parseElement, state); |
|
3965 return false; |
|
3966 } |
|
3967 break; |
|
3968 case EmptyTag: |
|
3969 if (tags.isEmpty()) { |
|
3970 reportParseError(QLatin1String(XMLERR_TAGMISMATCH)); |
|
3971 return false; |
|
3972 } |
|
3973 if (!processElementEmptyTag()) |
|
3974 return false; |
|
3975 next(); |
|
3976 break; |
|
3977 case Attrib: |
|
3978 case AttribPro: |
|
3979 // get name and value of attribute |
|
3980 if (!parseAttribute()) { |
|
3981 parseFailed(&QXmlSimpleReaderPrivate::parseElement, state); |
|
3982 return false; |
|
3983 } |
|
3984 break; |
|
3985 case Done: |
|
3986 next(); |
|
3987 break; |
|
3988 } |
|
3989 } |
|
3990 return false; |
|
3991 } |
|
3992 |
|
3993 /* |
|
3994 Helper to break down the size of the code in the case statement. |
|
3995 Return false on error, otherwise true. |
|
3996 */ |
|
3997 bool QXmlSimpleReaderPrivate::processElementEmptyTag() |
|
3998 { |
|
3999 QString uri, lname; |
|
4000 // pop the stack and call the handler |
|
4001 if (contentHnd) { |
|
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()); |
|
4007 return false; |
|
4008 } |
|
4009 // ... followed by endElement... |
|
4010 if (!contentHnd->endElement(uri, lname, tags.pop())) { |
|
4011 reportParseError(contentHnd->errorString()); |
|
4012 return false; |
|
4013 } |
|
4014 // ... followed by endPrefixMapping |
|
4015 QStringList prefixesBefore, prefixesAfter; |
|
4016 if (contentHnd) { |
|
4017 prefixesBefore = namespaceSupport.prefixes(); |
|
4018 } |
|
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()); |
|
4026 return false; |
|
4027 } |
|
4028 } |
|
4029 } |
|
4030 } else { |
|
4031 // report startElement first... |
|
4032 if (!contentHnd->startElement(QString(), QString(), tags.top(), attList)) { |
|
4033 reportParseError(contentHnd->errorString()); |
|
4034 return false; |
|
4035 } |
|
4036 // ... followed by endElement |
|
4037 if (!contentHnd->endElement(QString(), QString(), tags.pop())) { |
|
4038 reportParseError(contentHnd->errorString()); |
|
4039 return false; |
|
4040 } |
|
4041 } |
|
4042 } else { |
|
4043 tags.pop_back(); |
|
4044 namespaceSupport.popContext(); |
|
4045 } |
|
4046 return true; |
|
4047 } |
|
4048 /* |
|
4049 Helper to break down the size of the code in the case statement. |
|
4050 Return false on error, otherwise true. |
|
4051 */ |
|
4052 bool QXmlSimpleReaderPrivate::processElementETagBegin2() |
|
4053 { |
|
4054 const QString &name = QXmlSimpleReaderPrivate::name(); |
|
4055 |
|
4056 // pop the stack and compare it with the name |
|
4057 if (tags.pop() != name) { |
|
4058 reportParseError(QLatin1String(XMLERR_TAGMISMATCH)); |
|
4059 return false; |
|
4060 } |
|
4061 // call the handler |
|
4062 if (contentHnd) { |
|
4063 QString uri, lname; |
|
4064 |
|
4065 if (useNamespaces) |
|
4066 namespaceSupport.processName(name, false, uri, lname); |
|
4067 if (!contentHnd->endElement(uri, lname, name)) { |
|
4068 reportParseError(contentHnd->errorString()); |
|
4069 return false; |
|
4070 } |
|
4071 } |
|
4072 if (useNamespaces) { |
|
4073 NamespaceMap prefixesBefore, prefixesAfter; |
|
4074 if (contentHnd) |
|
4075 prefixesBefore = namespaceSupport.d->ns; |
|
4076 |
|
4077 namespaceSupport.popContext(); |
|
4078 // call the handler for prefix mapping |
|
4079 if (contentHnd) { |
|
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()); |
|
4086 return false; |
|
4087 } |
|
4088 } |
|
4089 } |
|
4090 } |
|
4091 } |
|
4092 } |
|
4093 return true; |
|
4094 } |
|
4095 /* |
|
4096 Helper to break down the size of the code in the case statement. |
|
4097 Return false on error, otherwise true. |
|
4098 */ |
|
4099 bool QXmlSimpleReaderPrivate::processElementAttribute() |
|
4100 { |
|
4101 QString uri, lname, prefix; |
|
4102 const QString &name = QXmlSimpleReaderPrivate::name(); |
|
4103 const QString &string = QXmlSimpleReaderPrivate::string(); |
|
4104 |
|
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); |
|
4117 } |
|
4118 // call the handler for prefix mapping |
|
4119 if (contentHnd) { |
|
4120 if (!contentHnd->startPrefixMapping(lname, string)) { |
|
4121 reportParseError(contentHnd->errorString()); |
|
4122 return false; |
|
4123 } |
|
4124 } |
|
4125 } else { |
|
4126 // no namespace delcaration |
|
4127 namespaceSupport.processName(name, true, uri, lname); |
|
4128 attList.append(name, uri, lname, string); |
|
4129 } |
|
4130 } else { |
|
4131 // no namespace support |
|
4132 attList.append(name, uri, lname, string); |
|
4133 } |
|
4134 return true; |
|
4135 } |
|
4136 |
|
4137 /* |
|
4138 Parse a content [43]. |
|
4139 |
|
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>'. |
|
4142 */ |
|
4143 bool QXmlSimpleReaderPrivate::parseContent() |
|
4144 { |
|
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 |
|
4162 |
|
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; |
|
4173 |
|
4174 static const signed char mapCLT2FSMChar[] = { |
|
4175 InpUnknown, // white space |
|
4176 InpUnknown, // % |
|
4177 InpAmp, // & |
|
4178 InpGt, // > |
|
4179 InpLt, // < |
|
4180 InpSlash, // / |
|
4181 InpQMark, // ? |
|
4182 InpEMark, // ! |
|
4183 InpDash, // - |
|
4184 InpCloseB, //] |
|
4185 InpOpenB, // [ |
|
4186 InpUnknown, // = |
|
4187 InpUnknown, // " |
|
4188 InpUnknown, // ' |
|
4189 InpUnknown // unknown |
|
4190 }; |
|
4191 |
|
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 |
|
4210 }; |
|
4211 signed char state; |
|
4212 signed char input; |
|
4213 |
|
4214 if (parseStack == 0 || parseStack->isEmpty()) { |
|
4215 contentCharDataRead = false; |
|
4216 state = Init; |
|
4217 } else { |
|
4218 state = parseStack->pop().state; |
|
4219 #if defined(QT_QXML_DEBUG) |
|
4220 qDebug("QXmlSimpleReader: parseContent (cont) in state %d", state); |
|
4221 #endif |
|
4222 if (!parseStack->isEmpty()) { |
|
4223 ParseFunction function = parseStack->top().function; |
|
4224 if (function == &QXmlSimpleReaderPrivate::eat_ws) { |
|
4225 parseStack->pop(); |
|
4226 #if defined(QT_QXML_DEBUG) |
|
4227 qDebug("QXmlSimpleReader: eat_ws (cont)"); |
|
4228 #endif |
|
4229 } |
|
4230 if (!(this->*function)()) { |
|
4231 parseFailed(&QXmlSimpleReaderPrivate::parseContent, state); |
|
4232 return false; |
|
4233 } |
|
4234 } |
|
4235 } |
|
4236 |
|
4237 for (;;) { |
|
4238 switch (state) { |
|
4239 case Ref: |
|
4240 if (!contentCharDataRead) |
|
4241 contentCharDataRead = parseReference_charDataRead; |
|
4242 break; |
|
4243 case PInstr: |
|
4244 if (contentHnd) { |
|
4245 if (!contentHnd->processingInstruction(name(),string())) { |
|
4246 reportParseError(contentHnd->errorString()); |
|
4247 return false; |
|
4248 } |
|
4249 } |
|
4250 state = PInstrR; |
|
4251 break; |
|
4252 case Com: |
|
4253 if (lexicalHnd) { |
|
4254 if (!lexicalHnd->comment(string())) { |
|
4255 reportParseError(lexicalHnd->errorString()); |
|
4256 return false; |
|
4257 } |
|
4258 } |
|
4259 state = ComR; |
|
4260 break; |
|
4261 case CDS: |
|
4262 stringClear(); |
|
4263 break; |
|
4264 case CDS2: |
|
4265 if (!atEnd() && c != QLatin1Char(']')) |
|
4266 stringAddC(QLatin1Char(']')); |
|
4267 break; |
|
4268 case CDS3: |
|
4269 // test if this skipping was legal |
|
4270 if (!atEnd()) { |
|
4271 if (c == QLatin1Char('>')) { |
|
4272 // the end of the CDSect |
|
4273 if (lexicalHnd) { |
|
4274 if (!lexicalHnd->startCDATA()) { |
|
4275 reportParseError(lexicalHnd->errorString()); |
|
4276 return false; |
|
4277 } |
|
4278 } |
|
4279 if (contentHnd) { |
|
4280 if (!contentHnd->characters(string())) { |
|
4281 reportParseError(contentHnd->errorString()); |
|
4282 return false; |
|
4283 } |
|
4284 } |
|
4285 if (lexicalHnd) { |
|
4286 if (!lexicalHnd->endCDATA()) { |
|
4287 reportParseError(lexicalHnd->errorString()); |
|
4288 return false; |
|
4289 } |
|
4290 } |
|
4291 } else if (c == QLatin1Char(']')) { |
|
4292 // three or more ']' |
|
4293 stringAddC(QLatin1Char(']')); |
|
4294 } else { |
|
4295 // after ']]' comes another character |
|
4296 stringAddC(QLatin1Char(']')); |
|
4297 stringAddC(QLatin1Char(']')); |
|
4298 } |
|
4299 } |
|
4300 break; |
|
4301 case Done: |
|
4302 // call the handler for CharData |
|
4303 if (contentHnd) { |
|
4304 if (contentCharDataRead) { |
|
4305 if (reportWhitespaceCharData || !string().simplified().isEmpty()) { |
|
4306 if (!contentHnd->characters(string())) { |
|
4307 reportParseError(contentHnd->errorString()); |
|
4308 return false; |
|
4309 } |
|
4310 } |
|
4311 } |
|
4312 } |
|
4313 // Done |
|
4314 return true; |
|
4315 case -1: |
|
4316 // Error |
|
4317 reportParseError(QLatin1String(XMLERR_ERRORPARSINGCONTENT)); |
|
4318 return false; |
|
4319 } |
|
4320 |
|
4321 // get input (use lookup-table instead of nested ifs for performance |
|
4322 // reasons) |
|
4323 if (atEnd()) { |
|
4324 unexpectedEof(&QXmlSimpleReaderPrivate::parseContent, state); |
|
4325 return false; |
|
4326 } |
|
4327 if (c.row()) { |
|
4328 input = InpUnknown; |
|
4329 } else { |
|
4330 input = mapCLT2FSMChar[charLookupTable[c.cell()]]; |
|
4331 } |
|
4332 state = table[state][input]; |
|
4333 |
|
4334 switch (state) { |
|
4335 case Init: |
|
4336 // skip the ending '>' of a CDATASection |
|
4337 next(); |
|
4338 break; |
|
4339 case ChD: |
|
4340 // on first call: clear string |
|
4341 if (!contentCharDataRead) { |
|
4342 contentCharDataRead = true; |
|
4343 stringClear(); |
|
4344 } |
|
4345 stringAddC(); |
|
4346 if (reportEntities) { |
|
4347 if (!reportEndEntities()) |
|
4348 return false; |
|
4349 } |
|
4350 next(); |
|
4351 break; |
|
4352 case ChD1: |
|
4353 // on first call: clear string |
|
4354 if (!contentCharDataRead) { |
|
4355 contentCharDataRead = true; |
|
4356 stringClear(); |
|
4357 } |
|
4358 stringAddC(); |
|
4359 if (reportEntities) { |
|
4360 if (!reportEndEntities()) |
|
4361 return false; |
|
4362 } |
|
4363 next(); |
|
4364 break; |
|
4365 case ChD2: |
|
4366 stringAddC(); |
|
4367 if (reportEntities) { |
|
4368 if (!reportEndEntities()) |
|
4369 return false; |
|
4370 } |
|
4371 next(); |
|
4372 break; |
|
4373 case Ref: |
|
4374 if (!contentCharDataRead) { |
|
4375 // reference may be CharData; so clear string to be safe |
|
4376 stringClear(); |
|
4377 parseReference_context = InContent; |
|
4378 if (!parseReference()) { |
|
4379 parseFailed(&QXmlSimpleReaderPrivate::parseContent, state); |
|
4380 return false; |
|
4381 } |
|
4382 } else { |
|
4383 if (reportEntities) { |
|
4384 // report character data in chunks |
|
4385 if (contentHnd) { |
|
4386 if (reportWhitespaceCharData || !string().simplified().isEmpty()) { |
|
4387 if (!contentHnd->characters(string())) { |
|
4388 reportParseError(contentHnd->errorString()); |
|
4389 return false; |
|
4390 } |
|
4391 } |
|
4392 } |
|
4393 stringClear(); |
|
4394 } |
|
4395 parseReference_context = InContent; |
|
4396 if (!parseReference()) { |
|
4397 parseFailed(&QXmlSimpleReaderPrivate::parseContent, state); |
|
4398 return false; |
|
4399 } |
|
4400 } |
|
4401 break; |
|
4402 case Lt: |
|
4403 // call the handler for CharData |
|
4404 if (contentHnd) { |
|
4405 if (contentCharDataRead) { |
|
4406 if (reportWhitespaceCharData || !string().simplified().isEmpty()) { |
|
4407 if (!contentHnd->characters(string())) { |
|
4408 reportParseError(contentHnd->errorString()); |
|
4409 return false; |
|
4410 } |
|
4411 } |
|
4412 } |
|
4413 } |
|
4414 contentCharDataRead = false; |
|
4415 next(); |
|
4416 break; |
|
4417 case PInstr: |
|
4418 case PInstrR: |
|
4419 parsePI_xmldecl = false; |
|
4420 if (!parsePI()) { |
|
4421 parseFailed(&QXmlSimpleReaderPrivate::parseContent, state); |
|
4422 return false; |
|
4423 } |
|
4424 break; |
|
4425 case Elem: |
|
4426 if (!parseElement()) { |
|
4427 parseFailed(&QXmlSimpleReaderPrivate::parseContent, state); |
|
4428 return false; |
|
4429 } |
|
4430 break; |
|
4431 case Em: |
|
4432 next(); |
|
4433 break; |
|
4434 case Com: |
|
4435 case ComR: |
|
4436 if (!parseComment()) { |
|
4437 parseFailed(&QXmlSimpleReaderPrivate::parseContent, state); |
|
4438 return false; |
|
4439 } |
|
4440 break; |
|
4441 case CDS: |
|
4442 parseString_s = QLatin1String("[CDATA["); |
|
4443 if (!parseString()) { |
|
4444 parseFailed(&QXmlSimpleReaderPrivate::parseContent, state); |
|
4445 return false; |
|
4446 } |
|
4447 break; |
|
4448 case CDS1: |
|
4449 stringAddC(); |
|
4450 next(); |
|
4451 break; |
|
4452 case CDS2: |
|
4453 // skip ']' |
|
4454 next(); |
|
4455 break; |
|
4456 case CDS3: |
|
4457 // skip ']'... |
|
4458 next(); |
|
4459 break; |
|
4460 } |
|
4461 } |
|
4462 return false; |
|
4463 } |
|
4464 |
|
4465 bool QXmlSimpleReaderPrivate::reportEndEntities() |
|
4466 { |
|
4467 int count = (int)xmlRefStack.count(); |
|
4468 while (count != 0 && xmlRefStack.top().isEmpty()) { |
|
4469 if (contentHnd) { |
|
4470 if (reportWhitespaceCharData || !string().simplified().isEmpty()) { |
|
4471 if (!contentHnd->characters(string())) { |
|
4472 reportParseError(contentHnd->errorString()); |
|
4473 return false; |
|
4474 } |
|
4475 } |
|
4476 } |
|
4477 stringClear(); |
|
4478 if (lexicalHnd) { |
|
4479 if (!lexicalHnd->endEntity(xmlRefStack.top().name)) { |
|
4480 reportParseError(lexicalHnd->errorString()); |
|
4481 return false; |
|
4482 } |
|
4483 } |
|
4484 xmlRefStack.pop_back(); |
|
4485 count--; |
|
4486 } |
|
4487 return true; |
|
4488 } |
|
4489 |
|
4490 /* |
|
4491 Parse Misc [27]. |
|
4492 */ |
|
4493 bool QXmlSimpleReaderPrivate::parseMisc() |
|
4494 { |
|
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 |
|
4501 |
|
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; |
|
4507 |
|
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 |
|
4513 }; |
|
4514 signed char state; |
|
4515 signed char input; |
|
4516 |
|
4517 if (parseStack==0 || parseStack->isEmpty()) { |
|
4518 state = Init; |
|
4519 } else { |
|
4520 state = parseStack->pop().state; |
|
4521 #if defined(QT_QXML_DEBUG) |
|
4522 qDebug("QXmlSimpleReader: parseMisc (cont) in state %d", state); |
|
4523 #endif |
|
4524 if (!parseStack->isEmpty()) { |
|
4525 ParseFunction function = parseStack->top().function; |
|
4526 if (function == &QXmlSimpleReaderPrivate::eat_ws) { |
|
4527 parseStack->pop(); |
|
4528 #if defined(QT_QXML_DEBUG) |
|
4529 qDebug("QXmlSimpleReader: eat_ws (cont)"); |
|
4530 #endif |
|
4531 } |
|
4532 if (!(this->*function)()) { |
|
4533 parseFailed(&QXmlSimpleReaderPrivate::parseMisc, state); |
|
4534 return false; |
|
4535 } |
|
4536 } |
|
4537 } |
|
4538 |
|
4539 for (;;) { |
|
4540 switch (state) { |
|
4541 case eatWS: |
|
4542 return true; |
|
4543 case PInstr: |
|
4544 if (contentHnd) { |
|
4545 if (!contentHnd->processingInstruction(name(),string())) { |
|
4546 reportParseError(contentHnd->errorString()); |
|
4547 return false; |
|
4548 } |
|
4549 } |
|
4550 return true; |
|
4551 case Comment2: |
|
4552 if (lexicalHnd) { |
|
4553 if (!lexicalHnd->comment(string())) { |
|
4554 reportParseError(lexicalHnd->errorString()); |
|
4555 return false; |
|
4556 } |
|
4557 } |
|
4558 return true; |
|
4559 case -1: |
|
4560 // Error |
|
4561 reportParseError(QLatin1String(XMLERR_UNEXPECTEDCHARACTER)); |
|
4562 return false; |
|
4563 } |
|
4564 |
|
4565 if (atEnd()) { |
|
4566 unexpectedEof(&QXmlSimpleReaderPrivate::parseMisc, state); |
|
4567 return false; |
|
4568 } |
|
4569 if (is_S(c)) { |
|
4570 input = InpWs; |
|
4571 } else if (c == QLatin1Char('<')) { |
|
4572 input = InpLt; |
|
4573 } else if (c == QLatin1Char('?')) { |
|
4574 input = InpQm; |
|
4575 } else if (c == QLatin1Char('!')) { |
|
4576 input = InpEm; |
|
4577 } else { |
|
4578 input = InpUnknown; |
|
4579 } |
|
4580 state = table[state][input]; |
|
4581 |
|
4582 switch (state) { |
|
4583 case eatWS: |
|
4584 if (!eat_ws()) { |
|
4585 parseFailed(&QXmlSimpleReaderPrivate::parseMisc, state); |
|
4586 return false; |
|
4587 } |
|
4588 break; |
|
4589 case Lt: |
|
4590 next(); |
|
4591 break; |
|
4592 case PInstr: |
|
4593 parsePI_xmldecl = false; |
|
4594 if (!parsePI()) { |
|
4595 parseFailed(&QXmlSimpleReaderPrivate::parseMisc, state); |
|
4596 return false; |
|
4597 } |
|
4598 break; |
|
4599 case Comment: |
|
4600 next(); |
|
4601 break; |
|
4602 case Comment2: |
|
4603 if (!parseComment()) { |
|
4604 parseFailed(&QXmlSimpleReaderPrivate::parseMisc, state); |
|
4605 return false; |
|
4606 } |
|
4607 break; |
|
4608 } |
|
4609 } |
|
4610 return false; |
|
4611 } |
|
4612 |
|
4613 /* |
|
4614 Parse a processing instruction [16]. |
|
4615 |
|
4616 If xmldec is true, it tries to parse a PI or a XML declaration [23]. |
|
4617 |
|
4618 Precondition: the beginning '<' of the PI is already read and the head stand |
|
4619 on the '?' of '<?'. |
|
4620 |
|
4621 If this funktion was successful, the head-position is on the first |
|
4622 character after the PI. |
|
4623 */ |
|
4624 bool QXmlSimpleReaderPrivate::parsePI() |
|
4625 { |
|
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 |
|
4643 |
|
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; |
|
4649 |
|
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 |
|
4668 }; |
|
4669 signed char state; |
|
4670 signed char input; |
|
4671 |
|
4672 if (parseStack==0 || parseStack->isEmpty()) { |
|
4673 state = Init; |
|
4674 } else { |
|
4675 state = parseStack->pop().state; |
|
4676 #if defined(QT_QXML_DEBUG) |
|
4677 qDebug("QXmlSimpleReader: parsePI (cont) in state %d", state); |
|
4678 #endif |
|
4679 if (!parseStack->isEmpty()) { |
|
4680 ParseFunction function = parseStack->top().function; |
|
4681 if (function == &QXmlSimpleReaderPrivate::eat_ws) { |
|
4682 parseStack->pop(); |
|
4683 #if defined(QT_QXML_DEBUG) |
|
4684 qDebug("QXmlSimpleReader: eat_ws (cont)"); |
|
4685 #endif |
|
4686 } |
|
4687 if (!(this->*function)()) { |
|
4688 parseFailed(&QXmlSimpleReaderPrivate::parsePI, state); |
|
4689 return false; |
|
4690 } |
|
4691 } |
|
4692 } |
|
4693 |
|
4694 for (;;) { |
|
4695 switch (state) { |
|
4696 case Name: |
|
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")) { |
|
4701 state = XMLDecl; |
|
4702 } else { |
|
4703 reportParseError(QLatin1String(XMLERR_INVALIDNAMEFORPI)); |
|
4704 return false; |
|
4705 } |
|
4706 } else { |
|
4707 state = PInstr; |
|
4708 stringClear(); |
|
4709 } |
|
4710 break; |
|
4711 case Version: |
|
4712 // get version (syntax like an attribute) |
|
4713 if (name() != QLatin1String("version")) { |
|
4714 reportParseError(QLatin1String(XMLERR_VERSIONEXPECTED)); |
|
4715 return false; |
|
4716 } |
|
4717 xmlVersion = string(); |
|
4718 break; |
|
4719 case EorSD: |
|
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; |
|
4726 } else { |
|
4727 reportParseError(QLatin1String(XMLERR_WRONGVALUEFORSDECL)); |
|
4728 return false; |
|
4729 } |
|
4730 } else if (name() == QLatin1String("encoding")) { |
|
4731 encoding = string(); |
|
4732 } else { |
|
4733 reportParseError(QLatin1String(XMLERR_EDECLORSDDECLEXPECTED)); |
|
4734 return false; |
|
4735 } |
|
4736 break; |
|
4737 case SD: |
|
4738 if (name() != QLatin1String("standalone")) { |
|
4739 reportParseError(QLatin1String(XMLERR_SDDECLEXPECTED)); |
|
4740 return false; |
|
4741 } |
|
4742 if (string() == QLatin1String("yes")) { |
|
4743 standalone = QXmlSimpleReaderPrivate::Yes; |
|
4744 } else if (string() == QLatin1String("no")) { |
|
4745 standalone = QXmlSimpleReaderPrivate::No; |
|
4746 } else { |
|
4747 reportParseError(QLatin1String(XMLERR_WRONGVALUEFORSDECL)); |
|
4748 return false; |
|
4749 } |
|
4750 break; |
|
4751 case Qm: |
|
4752 // test if the skipping was legal |
|
4753 if (!atEnd() && c != QLatin1Char('>')) |
|
4754 stringAddC(QLatin1Char('?')); |
|
4755 break; |
|
4756 case Done: |
|
4757 return true; |
|
4758 case -1: |
|
4759 // Error |
|
4760 reportParseError(QLatin1String(XMLERR_UNEXPECTEDCHARACTER)); |
|
4761 return false; |
|
4762 } |
|
4763 |
|
4764 if (atEnd()) { |
|
4765 unexpectedEof(&QXmlSimpleReaderPrivate::parsePI, state); |
|
4766 return false; |
|
4767 } |
|
4768 if (is_S(c)) { |
|
4769 input = InpWs; |
|
4770 } else if (determineNameChar(c) == NameBeginning) { |
|
4771 input = InpNameBe; |
|
4772 } else if (c == QLatin1Char('>')) { |
|
4773 input = InpGt; |
|
4774 } else if (c == QLatin1Char('?')) { |
|
4775 input = InpQm; |
|
4776 } else { |
|
4777 input = InpUnknown; |
|
4778 } |
|
4779 state = table[state][input]; |
|
4780 |
|
4781 switch (state) { |
|
4782 case QmI: |
|
4783 next(); |
|
4784 break; |
|
4785 case Name: |
|
4786 parseName_useRef = false; |
|
4787 if (!parseName()) { |
|
4788 parseFailed(&QXmlSimpleReaderPrivate::parsePI, state); |
|
4789 return false; |
|
4790 } |
|
4791 break; |
|
4792 case Ws1: |
|
4793 case Ws2: |
|
4794 case Ws3: |
|
4795 case Ws4: |
|
4796 case Ws5: |
|
4797 if (!eat_ws()) { |
|
4798 parseFailed(&QXmlSimpleReaderPrivate::parsePI, state); |
|
4799 return false; |
|
4800 } |
|
4801 break; |
|
4802 case Version: |
|
4803 if (!parseAttribute()) { |
|
4804 parseFailed(&QXmlSimpleReaderPrivate::parsePI, state); |
|
4805 return false; |
|
4806 } |
|
4807 break; |
|
4808 case EorSD: |
|
4809 if (!parseAttribute()) { |
|
4810 parseFailed(&QXmlSimpleReaderPrivate::parsePI, state); |
|
4811 return false; |
|
4812 } |
|
4813 break; |
|
4814 case SD: |
|
4815 // get the SDDecl (syntax like an attribute) |
|
4816 if (standalone != QXmlSimpleReaderPrivate::Unknown) { |
|
4817 // already parsed the standalone declaration |
|
4818 reportParseError(QLatin1String(XMLERR_UNEXPECTEDCHARACTER)); |
|
4819 return false; |
|
4820 } |
|
4821 if (!parseAttribute()) { |
|
4822 parseFailed(&QXmlSimpleReaderPrivate::parsePI, state); |
|
4823 return false; |
|
4824 } |
|
4825 break; |
|
4826 case ADone: |
|
4827 next(); |
|
4828 break; |
|
4829 case Char: |
|
4830 stringAddC(); |
|
4831 next(); |
|
4832 break; |
|
4833 case Qm: |
|
4834 // skip the '?' |
|
4835 next(); |
|
4836 break; |
|
4837 case Done: |
|
4838 next(); |
|
4839 break; |
|
4840 } |
|
4841 } |
|
4842 return false; |
|
4843 } |
|
4844 |
|
4845 /* |
|
4846 Parse a document type definition (doctypedecl [28]). |
|
4847 |
|
4848 Precondition: the beginning '<!' of the doctype is already read the head |
|
4849 stands on the 'D' of '<!DOCTYPE'. |
|
4850 |
|
4851 If this function was successful, the head-position is on the first |
|
4852 character after the document type definition. |
|
4853 */ |
|
4854 bool QXmlSimpleReaderPrivate::parseDoctype() |
|
4855 { |
|
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; |
|
4870 |
|
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; |
|
4879 |
|
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 |
|
4895 }; |
|
4896 signed char state; |
|
4897 signed char input; |
|
4898 |
|
4899 if (parseStack==0 || parseStack->isEmpty()) { |
|
4900 startDTDwasReported = false; |
|
4901 systemId.clear(); |
|
4902 publicId.clear(); |
|
4903 state = Init; |
|
4904 } else { |
|
4905 state = parseStack->pop().state; |
|
4906 #if defined(QT_QXML_DEBUG) |
|
4907 qDebug("QXmlSimpleReader: parseDoctype (cont) in state %d", state); |
|
4908 #endif |
|
4909 if (!parseStack->isEmpty()) { |
|
4910 ParseFunction function = parseStack->top().function; |
|
4911 if (function == &QXmlSimpleReaderPrivate::eat_ws) { |
|
4912 parseStack->pop(); |
|
4913 #if defined(QT_QXML_DEBUG) |
|
4914 qDebug("QXmlSimpleReader: eat_ws (cont)"); |
|
4915 #endif |
|
4916 } |
|
4917 if (!(this->*function)()) { |
|
4918 parseFailed(&QXmlSimpleReaderPrivate::parseDoctype, state); |
|
4919 return false; |
|
4920 } |
|
4921 } |
|
4922 } |
|
4923 |
|
4924 for (;;) { |
|
4925 switch (state) { |
|
4926 case Doctype2: |
|
4927 doctype = name(); |
|
4928 break; |
|
4929 case MP: |
|
4930 if (!startDTDwasReported && lexicalHnd ) { |
|
4931 startDTDwasReported = true; |
|
4932 if (!lexicalHnd->startDTD(doctype, publicId, systemId)) { |
|
4933 reportParseError(lexicalHnd->errorString()); |
|
4934 return false; |
|
4935 } |
|
4936 } |
|
4937 state = MPR; |
|
4938 break; |
|
4939 case Done: |
|
4940 return true; |
|
4941 case -1: |
|
4942 // Error |
|
4943 reportParseError(QLatin1String(XMLERR_ERRORPARSINGDOCTYPE)); |
|
4944 return false; |
|
4945 } |
|
4946 |
|
4947 if (atEnd()) { |
|
4948 unexpectedEof(&QXmlSimpleReaderPrivate::parseDoctype, state); |
|
4949 return false; |
|
4950 } |
|
4951 if (is_S(c)) { |
|
4952 input = InpWs; |
|
4953 } else if (c == QLatin1Char('D')) { |
|
4954 input = InpD; |
|
4955 } else if (c == QLatin1Char('S')) { |
|
4956 input = InpS; |
|
4957 } else if (c == QLatin1Char('P')) { |
|
4958 input = InpS; |
|
4959 } else if (c == QLatin1Char('[')) { |
|
4960 input = InpOB; |
|
4961 } else if (c == QLatin1Char(']')) { |
|
4962 input = InpCB; |
|
4963 } else if (c == QLatin1Char('%')) { |
|
4964 input = InpPer; |
|
4965 } else if (c == QLatin1Char('>')) { |
|
4966 input = InpGt; |
|
4967 } else { |
|
4968 input = InpUnknown; |
|
4969 } |
|
4970 state = table[state][input]; |
|
4971 |
|
4972 switch (state) { |
|
4973 case Doctype: |
|
4974 parseString_s = QLatin1String("DOCTYPE"); |
|
4975 if (!parseString()) { |
|
4976 parseFailed(&QXmlSimpleReaderPrivate::parseDoctype, state); |
|
4977 return false; |
|
4978 } |
|
4979 break; |
|
4980 case Ws1: |
|
4981 case Ws2: |
|
4982 case Ws3: |
|
4983 case Ws4: |
|
4984 if (!eat_ws()) { |
|
4985 parseFailed(&QXmlSimpleReaderPrivate::parseDoctype, state); |
|
4986 return false; |
|
4987 } |
|
4988 break; |
|
4989 case Doctype2: |
|
4990 parseName_useRef = false; |
|
4991 if (!parseName()) { |
|
4992 parseFailed(&QXmlSimpleReaderPrivate::parseDoctype, state); |
|
4993 return false; |
|
4994 } |
|
4995 break; |
|
4996 case Sys: |
|
4997 parseExternalID_allowPublicID = false; |
|
4998 if (!parseExternalID()) { |
|
4999 parseFailed(&QXmlSimpleReaderPrivate::parseDoctype, state); |
|
5000 return false; |
|
5001 } |
|
5002 thisPublicId = publicId; |
|
5003 thisSystemId = systemId; |
|
5004 break; |
|
5005 case MP: |
|
5006 case MPR: |
|
5007 if (!next_eat_ws()) { |
|
5008 parseFailed(&QXmlSimpleReaderPrivate::parseDoctype, state); |
|
5009 return false; |
|
5010 } |
|
5011 break; |
|
5012 case PER: |
|
5013 parsePEReference_context = InDTD; |
|
5014 if (!parsePEReference()) { |
|
5015 parseFailed(&QXmlSimpleReaderPrivate::parseDoctype, state); |
|
5016 return false; |
|
5017 } |
|
5018 break; |
|
5019 case Mup: |
|
5020 if (!parseMarkupdecl()) { |
|
5021 parseFailed(&QXmlSimpleReaderPrivate::parseDoctype, state); |
|
5022 return false; |
|
5023 } |
|
5024 break; |
|
5025 case MPE: |
|
5026 if (!next_eat_ws()) { |
|
5027 parseFailed(&QXmlSimpleReaderPrivate::parseDoctype, state); |
|
5028 return false; |
|
5029 } |
|
5030 break; |
|
5031 case Done: |
|
5032 if (lexicalHnd) { |
|
5033 if (!startDTDwasReported) { |
|
5034 startDTDwasReported = true; |
|
5035 if (!lexicalHnd->startDTD(doctype, publicId, systemId)) { |
|
5036 reportParseError(lexicalHnd->errorString()); |
|
5037 return false; |
|
5038 } |
|
5039 } |
|
5040 if (!lexicalHnd->endDTD()) { |
|
5041 reportParseError(lexicalHnd->errorString()); |
|
5042 return false; |
|
5043 } |
|
5044 } |
|
5045 next(); |
|
5046 break; |
|
5047 } |
|
5048 } |
|
5049 return false; |
|
5050 } |
|
5051 |
|
5052 /* |
|
5053 Parse a ExternalID [75]. |
|
5054 |
|
5055 If allowPublicID is true parse ExternalID [75] or PublicID [83]. |
|
5056 */ |
|
5057 bool QXmlSimpleReaderPrivate::parseExternalID() |
|
5058 { |
|
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; |
|
5076 |
|
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; |
|
5083 |
|
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 |
|
5101 }; |
|
5102 signed char state; |
|
5103 signed char input; |
|
5104 |
|
5105 if (parseStack==0 || parseStack->isEmpty()) { |
|
5106 systemId.clear(); |
|
5107 publicId.clear(); |
|
5108 state = Init; |
|
5109 } else { |
|
5110 state = parseStack->pop().state; |
|
5111 #if defined(QT_QXML_DEBUG) |
|
5112 qDebug("QXmlSimpleReader: parseExternalID (cont) in state %d", state); |
|
5113 #endif |
|
5114 if (!parseStack->isEmpty()) { |
|
5115 ParseFunction function = parseStack->top().function; |
|
5116 if (function == &QXmlSimpleReaderPrivate::eat_ws) { |
|
5117 parseStack->pop(); |
|
5118 #if defined(QT_QXML_DEBUG) |
|
5119 qDebug("QXmlSimpleReader: eat_ws (cont)"); |
|
5120 #endif |
|
5121 } |
|
5122 if (!(this->*function)()) { |
|
5123 parseFailed(&QXmlSimpleReaderPrivate::parseExternalID, state); |
|
5124 return false; |
|
5125 } |
|
5126 } |
|
5127 } |
|
5128 |
|
5129 for (;;) { |
|
5130 switch (state) { |
|
5131 case PDone: |
|
5132 if (parseExternalID_allowPublicID) { |
|
5133 publicId = string(); |
|
5134 return true; |
|
5135 } else { |
|
5136 reportParseError(QLatin1String(XMLERR_UNEXPECTEDCHARACTER)); |
|
5137 return false; |
|
5138 } |
|
5139 case Done: |
|
5140 return true; |
|
5141 case -1: |
|
5142 // Error |
|
5143 reportParseError(QLatin1String(XMLERR_UNEXPECTEDCHARACTER)); |
|
5144 return false; |
|
5145 } |
|
5146 |
|
5147 if (atEnd()) { |
|
5148 unexpectedEof(&QXmlSimpleReaderPrivate::parseExternalID, state); |
|
5149 return false; |
|
5150 } |
|
5151 if (is_S(c)) { |
|
5152 input = InpWs; |
|
5153 } else if (c == QLatin1Char('\'')) { |
|
5154 input = InpSQ; |
|
5155 } else if (c == QLatin1Char('"')) { |
|
5156 input = InpDQ; |
|
5157 } else if (c == QLatin1Char('S')) { |
|
5158 input = InpS; |
|
5159 } else if (c == QLatin1Char('P')) { |
|
5160 input = InpP; |
|
5161 } else { |
|
5162 input = InpUnknown; |
|
5163 } |
|
5164 state = table[state][input]; |
|
5165 |
|
5166 switch (state) { |
|
5167 case Sys: |
|
5168 parseString_s = QLatin1String("SYSTEM"); |
|
5169 if (!parseString()) { |
|
5170 parseFailed(&QXmlSimpleReaderPrivate::parseExternalID, state); |
|
5171 return false; |
|
5172 } |
|
5173 break; |
|
5174 case SysWS: |
|
5175 if (!eat_ws()) { |
|
5176 parseFailed(&QXmlSimpleReaderPrivate::parseExternalID, state); |
|
5177 return false; |
|
5178 } |
|
5179 break; |
|
5180 case SysSQ: |
|
5181 case SysDQ: |
|
5182 stringClear(); |
|
5183 next(); |
|
5184 break; |
|
5185 case SysSQ2: |
|
5186 case SysDQ2: |
|
5187 stringAddC(); |
|
5188 next(); |
|
5189 break; |
|
5190 case Pub: |
|
5191 parseString_s = QLatin1String("PUBLIC"); |
|
5192 if (!parseString()) { |
|
5193 parseFailed(&QXmlSimpleReaderPrivate::parseExternalID, state); |
|
5194 return false; |
|
5195 } |
|
5196 break; |
|
5197 case PubWS: |
|
5198 if (!eat_ws()) { |
|
5199 parseFailed(&QXmlSimpleReaderPrivate::parseExternalID, state); |
|
5200 return false; |
|
5201 } |
|
5202 break; |
|
5203 case PubSQ: |
|
5204 case PubDQ: |
|
5205 stringClear(); |
|
5206 next(); |
|
5207 break; |
|
5208 case PubSQ2: |
|
5209 case PubDQ2: |
|
5210 stringAddC(); |
|
5211 next(); |
|
5212 break; |
|
5213 case PubE: |
|
5214 next(); |
|
5215 break; |
|
5216 case PubWS2: |
|
5217 publicId = string(); |
|
5218 if (!eat_ws()) { |
|
5219 parseFailed(&QXmlSimpleReaderPrivate::parseExternalID, state); |
|
5220 return false; |
|
5221 } |
|
5222 break; |
|
5223 case Done: |
|
5224 systemId = string(); |
|
5225 next(); |
|
5226 break; |
|
5227 } |
|
5228 } |
|
5229 return false; |
|
5230 } |
|
5231 |
|
5232 /* |
|
5233 Parse a markupdecl [29]. |
|
5234 */ |
|
5235 bool QXmlSimpleReaderPrivate::parseMarkupdecl() |
|
5236 { |
|
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; |
|
5248 |
|
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; |
|
5258 |
|
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 |
|
5265 }; |
|
5266 signed char state; |
|
5267 signed char input; |
|
5268 |
|
5269 if (parseStack==0 || parseStack->isEmpty()) { |
|
5270 state = Init; |
|
5271 } else { |
|
5272 state = parseStack->pop().state; |
|
5273 #if defined(QT_QXML_DEBUG) |
|
5274 qDebug("QXmlSimpleReader: parseMarkupdecl (cont) in state %d", state); |
|
5275 #endif |
|
5276 if (!parseStack->isEmpty()) { |
|
5277 ParseFunction function = parseStack->top().function; |
|
5278 if (function == &QXmlSimpleReaderPrivate::eat_ws) { |
|
5279 parseStack->pop(); |
|
5280 #if defined(QT_QXML_DEBUG) |
|
5281 qDebug("QXmlSimpleReader: eat_ws (cont)"); |
|
5282 #endif |
|
5283 } |
|
5284 if (!(this->*function)()) { |
|
5285 parseFailed(&QXmlSimpleReaderPrivate::parseMarkupdecl, state); |
|
5286 return false; |
|
5287 } |
|
5288 } |
|
5289 } |
|
5290 |
|
5291 for (;;) { |
|
5292 switch (state) { |
|
5293 case Qm: |
|
5294 if (contentHnd) { |
|
5295 if (!contentHnd->processingInstruction(name(),string())) { |
|
5296 reportParseError(contentHnd->errorString()); |
|
5297 return false; |
|
5298 } |
|
5299 } |
|
5300 return true; |
|
5301 case Dash: |
|
5302 if (lexicalHnd) { |
|
5303 if (!lexicalHnd->comment(string())) { |
|
5304 reportParseError(lexicalHnd->errorString()); |
|
5305 return false; |
|
5306 } |
|
5307 } |
|
5308 return true; |
|
5309 case CA: |
|
5310 return true; |
|
5311 case CEL: |
|
5312 return true; |
|
5313 case CEN: |
|
5314 return true; |
|
5315 case CN: |
|
5316 return true; |
|
5317 case Done: |
|
5318 return true; |
|
5319 case -1: |
|
5320 // Error |
|
5321 reportParseError(QLatin1String(XMLERR_LETTEREXPECTED)); |
|
5322 return false; |
|
5323 } |
|
5324 |
|
5325 if (atEnd()) { |
|
5326 unexpectedEof(&QXmlSimpleReaderPrivate::parseMarkupdecl, state); |
|
5327 return false; |
|
5328 } |
|
5329 if (c == QLatin1Char('<')) { |
|
5330 input = InpLt; |
|
5331 } else if (c == QLatin1Char('?')) { |
|
5332 input = InpQm; |
|
5333 } else if (c == QLatin1Char('!')) { |
|
5334 input = InpEm; |
|
5335 } else if (c == QLatin1Char('-')) { |
|
5336 input = InpDash; |
|
5337 } else if (c == QLatin1Char('A')) { |
|
5338 input = InpA; |
|
5339 } else if (c == QLatin1Char('E')) { |
|
5340 input = InpE; |
|
5341 } else if (c == QLatin1Char('L')) { |
|
5342 input = InpL; |
|
5343 } else if (c == QLatin1Char('N')) { |
|
5344 input = InpN; |
|
5345 } else { |
|
5346 input = InpUnknown; |
|
5347 } |
|
5348 state = table[state][input]; |
|
5349 |
|
5350 switch (state) { |
|
5351 case Lt: |
|
5352 next(); |
|
5353 break; |
|
5354 case Em: |
|
5355 next(); |
|
5356 break; |
|
5357 case CE: |
|
5358 next(); |
|
5359 break; |
|
5360 case Qm: |
|
5361 parsePI_xmldecl = false; |
|
5362 if (!parsePI()) { |
|
5363 parseFailed(&QXmlSimpleReaderPrivate::parseMarkupdecl, state); |
|
5364 return false; |
|
5365 } |
|
5366 break; |
|
5367 case Dash: |
|
5368 if (!parseComment()) { |
|
5369 parseFailed(&QXmlSimpleReaderPrivate::parseMarkupdecl, state); |
|
5370 return false; |
|
5371 } |
|
5372 break; |
|
5373 case CA: |
|
5374 if (!parseAttlistDecl()) { |
|
5375 parseFailed(&QXmlSimpleReaderPrivate::parseMarkupdecl, state); |
|
5376 return false; |
|
5377 } |
|
5378 break; |
|
5379 case CEL: |
|
5380 if (!parseElementDecl()) { |
|
5381 parseFailed(&QXmlSimpleReaderPrivate::parseMarkupdecl, state); |
|
5382 return false; |
|
5383 } |
|
5384 break; |
|
5385 case CEN: |
|
5386 if (!parseEntityDecl()) { |
|
5387 parseFailed(&QXmlSimpleReaderPrivate::parseMarkupdecl, state); |
|
5388 return false; |
|
5389 } |
|
5390 break; |
|
5391 case CN: |
|
5392 if (!parseNotationDecl()) { |
|
5393 parseFailed(&QXmlSimpleReaderPrivate::parseMarkupdecl, state); |
|
5394 return false; |
|
5395 } |
|
5396 break; |
|
5397 } |
|
5398 } |
|
5399 return false; |
|
5400 } |
|
5401 |
|
5402 /* |
|
5403 Parse a PEReference [69] |
|
5404 */ |
|
5405 bool QXmlSimpleReaderPrivate::parsePEReference() |
|
5406 { |
|
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; |
|
5412 |
|
5413 const signed char InpSemi = 0; // ; |
|
5414 const signed char InpPer = 1; // % |
|
5415 const signed char InpUnknown = 2; |
|
5416 |
|
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 |
|
5423 }; |
|
5424 signed char state; |
|
5425 signed char input; |
|
5426 |
|
5427 if (parseStack==0 || parseStack->isEmpty()) { |
|
5428 state = Init; |
|
5429 } else { |
|
5430 state = parseStack->pop().state; |
|
5431 #if defined(QT_QXML_DEBUG) |
|
5432 qDebug("QXmlSimpleReader: parsePEReference (cont) in state %d", state); |
|
5433 #endif |
|
5434 if (!parseStack->isEmpty()) { |
|
5435 ParseFunction function = parseStack->top().function; |
|
5436 if (function == &QXmlSimpleReaderPrivate::eat_ws) { |
|
5437 parseStack->pop(); |
|
5438 #if defined(QT_QXML_DEBUG) |
|
5439 qDebug("QXmlSimpleReader: eat_ws (cont)"); |
|
5440 #endif |
|
5441 } |
|
5442 if (!(this->*function)()) { |
|
5443 parseFailed(&QXmlSimpleReaderPrivate::parsePEReference, state); |
|
5444 return false; |
|
5445 } |
|
5446 } |
|
5447 } |
|
5448 |
|
5449 for (;;) { |
|
5450 switch (state) { |
|
5451 case Name: |
|
5452 { |
|
5453 bool skipIt = true; |
|
5454 QString xmlRefString; |
|
5455 |
|
5456 QMap<QString,QString>::Iterator it; |
|
5457 it = parameterEntities.find(ref()); |
|
5458 if (it != parameterEntities.end()) { |
|
5459 skipIt = false; |
|
5460 xmlRefString = *it; |
|
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)) { |
|
5467 delete ret; |
|
5468 reportParseError(entityRes->errorString()); |
|
5469 return false; |
|
5470 } |
|
5471 if (ret) { |
|
5472 xmlRefString = ret->data(); |
|
5473 delete ret; |
|
5474 if (!stripTextDecl(xmlRefString)) { |
|
5475 reportParseError(QLatin1String(XMLERR_ERRORINTEXTDECL)); |
|
5476 return false; |
|
5477 } |
|
5478 skipIt = false; |
|
5479 } |
|
5480 } |
|
5481 } |
|
5482 |
|
5483 if (skipIt) { |
|
5484 if (contentHnd) { |
|
5485 if (!contentHnd->skippedEntity(QLatin1Char('%') + ref())) { |
|
5486 reportParseError(contentHnd->errorString()); |
|
5487 return false; |
|
5488 } |
|
5489 } |
|
5490 } else { |
|
5491 if (parsePEReference_context == InEntityValue) { |
|
5492 // Included in literal |
|
5493 if (!insertXmlRef(xmlRefString, ref(), true)) |
|
5494 return false; |
|
5495 } else if (parsePEReference_context == InDTD) { |
|
5496 // Included as PE |
|
5497 if (!insertXmlRef(QLatin1Char(' ') + xmlRefString + QLatin1Char(' '), ref(), false)) |
|
5498 return false; |
|
5499 } |
|
5500 } |
|
5501 } |
|
5502 state = NameR; |
|
5503 break; |
|
5504 case Done: |
|
5505 return true; |
|
5506 case -1: |
|
5507 // Error |
|
5508 reportParseError(QLatin1String(XMLERR_LETTEREXPECTED)); |
|
5509 return false; |
|
5510 } |
|
5511 |
|
5512 if (atEnd()) { |
|
5513 unexpectedEof(&QXmlSimpleReaderPrivate::parsePEReference, state); |
|
5514 return false; |
|
5515 } |
|
5516 if (c == QLatin1Char(';')) { |
|
5517 input = InpSemi; |
|
5518 } else if (c == QLatin1Char('%')) { |
|
5519 input = InpPer; |
|
5520 } else { |
|
5521 input = InpUnknown; |
|
5522 } |
|
5523 state = table[state][input]; |
|
5524 |
|
5525 switch (state) { |
|
5526 case Next: |
|
5527 next(); |
|
5528 break; |
|
5529 case Name: |
|
5530 case NameR: |
|
5531 parseName_useRef = true; |
|
5532 if (!parseName()) { |
|
5533 parseFailed(&QXmlSimpleReaderPrivate::parsePEReference, state); |
|
5534 return false; |
|
5535 } |
|
5536 break; |
|
5537 case Done: |
|
5538 next(); |
|
5539 break; |
|
5540 } |
|
5541 } |
|
5542 return false; |
|
5543 } |
|
5544 |
|
5545 /* |
|
5546 Parse a AttlistDecl [52]. |
|
5547 |
|
5548 Precondition: the beginning '<!' is already read and the head |
|
5549 stands on the 'A' of '<!ATTLIST' |
|
5550 */ |
|
5551 bool QXmlSimpleReaderPrivate::parseAttlistDecl() |
|
5552 { |
|
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; |
|
5569 |
|
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; |
|
5578 |
|
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 |
|
5596 }; |
|
5597 signed char state; |
|
5598 signed char input; |
|
5599 |
|
5600 if (parseStack==0 || parseStack->isEmpty()) { |
|
5601 state = Init; |
|
5602 } else { |
|
5603 state = parseStack->pop().state; |
|
5604 #if defined(QT_QXML_DEBUG) |
|
5605 qDebug("QXmlSimpleReader: parseAttlistDecl (cont) in state %d", state); |
|
5606 #endif |
|
5607 if (!parseStack->isEmpty()) { |
|
5608 ParseFunction function = parseStack->top().function; |
|
5609 if (function == &QXmlSimpleReaderPrivate::eat_ws) { |
|
5610 parseStack->pop(); |
|
5611 #if defined(QT_QXML_DEBUG) |
|
5612 qDebug("QXmlSimpleReader: eat_ws (cont)"); |
|
5613 #endif |
|
5614 } |
|
5615 if (!(this->*function)()) { |
|
5616 parseFailed(&QXmlSimpleReaderPrivate::parseAttlistDecl, state); |
|
5617 return false; |
|
5618 } |
|
5619 } |
|
5620 } |
|
5621 |
|
5622 for (;;) { |
|
5623 switch (state) { |
|
5624 case Name: |
|
5625 attDeclEName = name(); |
|
5626 break; |
|
5627 case Attdef: |
|
5628 attDeclAName = name(); |
|
5629 break; |
|
5630 case Done: |
|
5631 return true; |
|
5632 case -1: |
|
5633 // Error |
|
5634 reportParseError(QLatin1String(XMLERR_LETTEREXPECTED)); |
|
5635 return false; |
|
5636 } |
|
5637 |
|
5638 if (atEnd()) { |
|
5639 unexpectedEof(&QXmlSimpleReaderPrivate::parseAttlistDecl, state); |
|
5640 return false; |
|
5641 } |
|
5642 if (is_S(c)) { |
|
5643 input = InpWs; |
|
5644 } else if (c == QLatin1Char('>')) { |
|
5645 input = InpGt; |
|
5646 } else if (c == QLatin1Char('#')) { |
|
5647 input = InpHash; |
|
5648 } else if (c == QLatin1Char('A')) { |
|
5649 input = InpA; |
|
5650 } else if (c == QLatin1Char('I')) { |
|
5651 input = InpI; |
|
5652 } else if (c == QLatin1Char('F')) { |
|
5653 input = InpF; |
|
5654 } else if (c == QLatin1Char('R')) { |
|
5655 input = InpR; |
|
5656 } else { |
|
5657 input = InpUnknown; |
|
5658 } |
|
5659 state = table[state][input]; |
|
5660 |
|
5661 switch (state) { |
|
5662 case Attlist: |
|
5663 parseString_s = QLatin1String("ATTLIST"); |
|
5664 if (!parseString()) { |
|
5665 parseFailed(&QXmlSimpleReaderPrivate::parseAttlistDecl, state); |
|
5666 return false; |
|
5667 } |
|
5668 break; |
|
5669 case Ws: |
|
5670 case Ws1: |
|
5671 case Ws2: |
|
5672 case Ws3: |
|
5673 if (!eat_ws()) { |
|
5674 parseFailed(&QXmlSimpleReaderPrivate::parseAttlistDecl, state); |
|
5675 return false; |
|
5676 } |
|
5677 break; |
|
5678 case Name: |
|
5679 parseName_useRef = false; |
|
5680 if (!parseName()) { |
|
5681 parseFailed(&QXmlSimpleReaderPrivate::parseAttlistDecl, state); |
|
5682 return false; |
|
5683 } |
|
5684 break; |
|
5685 case Attdef: |
|
5686 parseName_useRef = false; |
|
5687 if (!parseName()) { |
|
5688 parseFailed(&QXmlSimpleReaderPrivate::parseAttlistDecl, state); |
|
5689 return false; |
|
5690 } |
|
5691 break; |
|
5692 case Atttype: |
|
5693 if (!parseAttType()) { |
|
5694 parseFailed(&QXmlSimpleReaderPrivate::parseAttlistDecl, state); |
|
5695 return false; |
|
5696 } |
|
5697 break; |
|
5698 case DDecH: |
|
5699 next(); |
|
5700 break; |
|
5701 case DefReq: |
|
5702 parseString_s = QLatin1String("REQUIRED"); |
|
5703 if (!parseString()) { |
|
5704 parseFailed(&QXmlSimpleReaderPrivate::parseAttlistDecl, state); |
|
5705 return false; |
|
5706 } |
|
5707 break; |
|
5708 case DefImp: |
|
5709 parseString_s = QLatin1String("IMPLIED"); |
|
5710 if (!parseString()) { |
|
5711 parseFailed(&QXmlSimpleReaderPrivate::parseAttlistDecl, state); |
|
5712 return false; |
|
5713 } |
|
5714 break; |
|
5715 case DefFix: |
|
5716 parseString_s = QLatin1String("FIXED"); |
|
5717 if (!parseString()) { |
|
5718 parseFailed(&QXmlSimpleReaderPrivate::parseAttlistDecl, state); |
|
5719 return false; |
|
5720 } |
|
5721 break; |
|
5722 case Attval: |
|
5723 if (!parseAttValue()) { |
|
5724 parseFailed(&QXmlSimpleReaderPrivate::parseAttlistDecl, state); |
|
5725 return false; |
|
5726 } |
|
5727 break; |
|
5728 case Ws4: |
|
5729 if (declHnd) { |
|
5730 // ### not all values are computed yet... |
|
5731 if (!declHnd->attributeDecl(attDeclEName, attDeclAName, QLatin1String(""), QLatin1String(""), QLatin1String(""))) { |
|
5732 reportParseError(declHnd->errorString()); |
|
5733 return false; |
|
5734 } |
|
5735 } |
|
5736 if (!eat_ws()) { |
|
5737 parseFailed(&QXmlSimpleReaderPrivate::parseAttlistDecl, state); |
|
5738 return false; |
|
5739 } |
|
5740 break; |
|
5741 case Done: |
|
5742 next(); |
|
5743 break; |
|
5744 } |
|
5745 } |
|
5746 return false; |
|
5747 } |
|
5748 |
|
5749 /* |
|
5750 Parse a AttType [54] |
|
5751 */ |
|
5752 bool QXmlSimpleReaderPrivate::parseAttType() |
|
5753 { |
|
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; |
|
5775 |
|
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; |
|
5790 |
|
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 |
|
5812 }; |
|
5813 signed char state; |
|
5814 signed char input; |
|
5815 |
|
5816 if (parseStack==0 || parseStack->isEmpty()) { |
|
5817 state = Init; |
|
5818 } else { |
|
5819 state = parseStack->pop().state; |
|
5820 #if defined(QT_QXML_DEBUG) |
|
5821 qDebug("QXmlSimpleReader: parseAttType (cont) in state %d", state); |
|
5822 #endif |
|
5823 if (!parseStack->isEmpty()) { |
|
5824 ParseFunction function = parseStack->top().function; |
|
5825 if (function == &QXmlSimpleReaderPrivate::eat_ws) { |
|
5826 parseStack->pop(); |
|
5827 #if defined(QT_QXML_DEBUG) |
|
5828 qDebug("QXmlSimpleReader: eat_ws (cont)"); |
|
5829 #endif |
|
5830 } |
|
5831 if (!(this->*function)()) { |
|
5832 parseFailed(&QXmlSimpleReaderPrivate::parseAttType, state); |
|
5833 return false; |
|
5834 } |
|
5835 } |
|
5836 } |
|
5837 |
|
5838 for (;;) { |
|
5839 switch (state) { |
|
5840 case ADone: |
|
5841 return true; |
|
5842 case Done: |
|
5843 return true; |
|
5844 case -1: |
|
5845 // Error |
|
5846 reportParseError(QLatin1String(XMLERR_LETTEREXPECTED)); |
|
5847 return false; |
|
5848 } |
|
5849 |
|
5850 if (atEnd()) { |
|
5851 unexpectedEof(&QXmlSimpleReaderPrivate::parseAttType, state); |
|
5852 return false; |
|
5853 } |
|
5854 if (is_S(c)) { |
|
5855 input = InpWs; |
|
5856 } else if (c == QLatin1Char('(')) { |
|
5857 input = InpOp; |
|
5858 } else if (c == QLatin1Char(')')) { |
|
5859 input = InpCp; |
|
5860 } else if (c == QLatin1Char('|')) { |
|
5861 input = InpPipe; |
|
5862 } else if (c == QLatin1Char('C')) { |
|
5863 input = InpC; |
|
5864 } else if (c == QLatin1Char('E')) { |
|
5865 input = InpE; |
|
5866 } else if (c == QLatin1Char('I')) { |
|
5867 input = InpI; |
|
5868 } else if (c == QLatin1Char('M')) { |
|
5869 input = InpM; |
|
5870 } else if (c == QLatin1Char('N')) { |
|
5871 input = InpN; |
|
5872 } else if (c == QLatin1Char('O')) { |
|
5873 input = InpO; |
|
5874 } else if (c == QLatin1Char('R')) { |
|
5875 input = InpR; |
|
5876 } else if (c == QLatin1Char('S')) { |
|
5877 input = InpS; |
|
5878 } else if (c == QLatin1Char('Y')) { |
|
5879 input = InpY; |
|
5880 } else { |
|
5881 input = InpUnknown; |
|
5882 } |
|
5883 state = table[state][input]; |
|
5884 |
|
5885 switch (state) { |
|
5886 case ST: |
|
5887 parseString_s = QLatin1String("CDATA"); |
|
5888 if (!parseString()) { |
|
5889 parseFailed(&QXmlSimpleReaderPrivate::parseAttType, state); |
|
5890 return false; |
|
5891 } |
|
5892 break; |
|
5893 case TTI: |
|
5894 parseString_s = QLatin1String("ID"); |
|
5895 if (!parseString()) { |
|
5896 parseFailed(&QXmlSimpleReaderPrivate::parseAttType, state); |
|
5897 return false; |
|
5898 } |
|
5899 break; |
|
5900 case TTI2: |
|
5901 parseString_s = QLatin1String("REF"); |
|
5902 if (!parseString()) { |
|
5903 parseFailed(&QXmlSimpleReaderPrivate::parseAttType, state); |
|
5904 return false; |
|
5905 } |
|
5906 break; |
|
5907 case TTI3: |
|
5908 next(); // S |
|
5909 break; |
|
5910 case TTE: |
|
5911 parseString_s = QLatin1String("ENTIT"); |
|
5912 if (!parseString()) { |
|
5913 parseFailed(&QXmlSimpleReaderPrivate::parseAttType, state); |
|
5914 return false; |
|
5915 } |
|
5916 break; |
|
5917 case TTEY: |
|
5918 next(); // Y |
|
5919 break; |
|
5920 case TTEI: |
|
5921 parseString_s = QLatin1String("IES"); |
|
5922 if (!parseString()) { |
|
5923 parseFailed(&QXmlSimpleReaderPrivate::parseAttType, state); |
|
5924 return false; |
|
5925 } |
|
5926 break; |
|
5927 case N: |
|
5928 next(); // N |
|
5929 break; |
|
5930 case TTNM: |
|
5931 parseString_s = QLatin1String("MTOKEN"); |
|
5932 if (!parseString()) { |
|
5933 parseFailed(&QXmlSimpleReaderPrivate::parseAttType, state); |
|
5934 return false; |
|
5935 } |
|
5936 break; |
|
5937 case TTNM2: |
|
5938 next(); // S |
|
5939 break; |
|
5940 case NO: |
|
5941 parseString_s = QLatin1String("OTATION"); |
|
5942 if (!parseString()) { |
|
5943 parseFailed(&QXmlSimpleReaderPrivate::parseAttType, state); |
|
5944 return false; |
|
5945 } |
|
5946 break; |
|
5947 case NO2: |
|
5948 if (!eat_ws()) { |
|
5949 parseFailed(&QXmlSimpleReaderPrivate::parseAttType, state); |
|
5950 return false; |
|
5951 } |
|
5952 break; |
|
5953 case NO3: |
|
5954 if (!next_eat_ws()) { |
|
5955 parseFailed(&QXmlSimpleReaderPrivate::parseAttType, state); |
|
5956 return false; |
|
5957 } |
|
5958 break; |
|
5959 case NOName: |
|
5960 parseName_useRef = false; |
|
5961 if (!parseName()) { |
|
5962 parseFailed(&QXmlSimpleReaderPrivate::parseAttType, state); |
|
5963 return false; |
|
5964 } |
|
5965 break; |
|
5966 case NO4: |
|
5967 if (!eat_ws()) { |
|
5968 parseFailed(&QXmlSimpleReaderPrivate::parseAttType, state); |
|
5969 return false; |
|
5970 } |
|
5971 break; |
|
5972 case EN: |
|
5973 if (!next_eat_ws()) { |
|
5974 parseFailed(&QXmlSimpleReaderPrivate::parseAttType, state); |
|
5975 return false; |
|
5976 } |
|
5977 break; |
|
5978 case ENNmt: |
|
5979 if (!parseNmtoken()) { |
|
5980 parseFailed(&QXmlSimpleReaderPrivate::parseAttType, state); |
|
5981 return false; |
|
5982 } |
|
5983 break; |
|
5984 case EN2: |
|
5985 if (!eat_ws()) { |
|
5986 parseFailed(&QXmlSimpleReaderPrivate::parseAttType, state); |
|
5987 return false; |
|
5988 } |
|
5989 break; |
|
5990 case ADone: |
|
5991 next(); |
|
5992 break; |
|
5993 } |
|
5994 } |
|
5995 return false; |
|
5996 } |
|
5997 |
|
5998 /* |
|
5999 Parse a AttValue [10] |
|
6000 |
|
6001 Precondition: the head stands on the beginning " or ' |
|
6002 |
|
6003 If this function was successful, the head stands on the first |
|
6004 character after the closing " or ' and the value of the attribute |
|
6005 is in string(). |
|
6006 */ |
|
6007 bool QXmlSimpleReaderPrivate::parseAttValue() |
|
6008 { |
|
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; |
|
6017 |
|
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; |
|
6023 |
|
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 |
|
6033 }; |
|
6034 signed char state; |
|
6035 signed char input; |
|
6036 |
|
6037 if (parseStack==0 || parseStack->isEmpty()) { |
|
6038 state = Init; |
|
6039 } else { |
|
6040 state = parseStack->pop().state; |
|
6041 #if defined(QT_QXML_DEBUG) |
|
6042 qDebug("QXmlSimpleReader: parseAttValue (cont) in state %d", state); |
|
6043 #endif |
|
6044 if (!parseStack->isEmpty()) { |
|
6045 ParseFunction function = parseStack->top().function; |
|
6046 if (function == &QXmlSimpleReaderPrivate::eat_ws) { |
|
6047 parseStack->pop(); |
|
6048 #if defined(QT_QXML_DEBUG) |
|
6049 qDebug("QXmlSimpleReader: eat_ws (cont)"); |
|
6050 #endif |
|
6051 } |
|
6052 if (!(this->*function)()) { |
|
6053 parseFailed(&QXmlSimpleReaderPrivate::parseAttValue, state); |
|
6054 return false; |
|
6055 } |
|
6056 } |
|
6057 } |
|
6058 |
|
6059 for (;;) { |
|
6060 switch (state) { |
|
6061 case Done: |
|
6062 return true; |
|
6063 case -1: |
|
6064 // Error |
|
6065 reportParseError(QLatin1String(XMLERR_UNEXPECTEDCHARACTER)); |
|
6066 return false; |
|
6067 } |
|
6068 |
|
6069 if (atEnd()) { |
|
6070 unexpectedEof(&QXmlSimpleReaderPrivate::parseAttValue, state); |
|
6071 return false; |
|
6072 } |
|
6073 if (c == QLatin1Char('"')) { |
|
6074 input = InpDq; |
|
6075 } else if (c == QLatin1Char('\'')) { |
|
6076 input = InpSq; |
|
6077 } else if (c == QLatin1Char('&')) { |
|
6078 input = InpAmp; |
|
6079 } else if (c == QLatin1Char('<')) { |
|
6080 input = InpLt; |
|
6081 } else { |
|
6082 input = InpUnknown; |
|
6083 } |
|
6084 state = table[state][input]; |
|
6085 |
|
6086 switch (state) { |
|
6087 case Dq: |
|
6088 case Sq: |
|
6089 stringClear(); |
|
6090 next(); |
|
6091 break; |
|
6092 case DqRef: |
|
6093 case SqRef: |
|
6094 parseReference_context = InAttributeValue; |
|
6095 if (!parseReference()) { |
|
6096 parseFailed(&QXmlSimpleReaderPrivate::parseAttValue, state); |
|
6097 return false; |
|
6098 } |
|
6099 break; |
|
6100 case DqC: |
|
6101 case SqC: |
|
6102 stringAddC(); |
|
6103 next(); |
|
6104 break; |
|
6105 case Done: |
|
6106 next(); |
|
6107 break; |
|
6108 } |
|
6109 } |
|
6110 return false; |
|
6111 } |
|
6112 |
|
6113 /* |
|
6114 Parse a elementdecl [45]. |
|
6115 |
|
6116 Precondition: the beginning '<!E' is already read and the head |
|
6117 stands on the 'L' of '<!ELEMENT' |
|
6118 */ |
|
6119 bool QXmlSimpleReaderPrivate::parseElementDecl() |
|
6120 { |
|
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; |
|
6140 |
|
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; |
|
6154 |
|
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 |
|
6175 }; |
|
6176 signed char state; |
|
6177 signed char input; |
|
6178 |
|
6179 if (parseStack==0 || parseStack->isEmpty()) { |
|
6180 state = Init; |
|
6181 } else { |
|
6182 state = parseStack->pop().state; |
|
6183 #if defined(QT_QXML_DEBUG) |
|
6184 qDebug("QXmlSimpleReader: parseElementDecl (cont) in state %d", state); |
|
6185 #endif |
|
6186 if (!parseStack->isEmpty()) { |
|
6187 ParseFunction function = parseStack->top().function; |
|
6188 if (function == &QXmlSimpleReaderPrivate::eat_ws) { |
|
6189 parseStack->pop(); |
|
6190 #if defined(QT_QXML_DEBUG) |
|
6191 qDebug("QXmlSimpleReader: eat_ws (cont)"); |
|
6192 #endif |
|
6193 } |
|
6194 if (!(this->*function)()) { |
|
6195 parseFailed(&QXmlSimpleReaderPrivate::parseElementDecl, state); |
|
6196 return false; |
|
6197 } |
|
6198 } |
|
6199 } |
|
6200 |
|
6201 for (;;) { |
|
6202 switch (state) { |
|
6203 case Done: |
|
6204 return true; |
|
6205 case -1: |
|
6206 reportParseError(QLatin1String(XMLERR_UNEXPECTEDCHARACTER)); |
|
6207 return false; |
|
6208 } |
|
6209 |
|
6210 if (atEnd()) { |
|
6211 unexpectedEof(&QXmlSimpleReaderPrivate::parseElementDecl, state); |
|
6212 return false; |
|
6213 } |
|
6214 if (is_S(c)) { |
|
6215 input = InpWs; |
|
6216 } else if (c == QLatin1Char('>')) { |
|
6217 input = InpGt; |
|
6218 } else if (c == QLatin1Char('|')) { |
|
6219 input = InpPipe; |
|
6220 } else if (c == QLatin1Char('(')) { |
|
6221 input = InpOp; |
|
6222 } else if (c == QLatin1Char(')')) { |
|
6223 input = InpCp; |
|
6224 } else if (c == QLatin1Char('#')) { |
|
6225 input = InpHash; |
|
6226 } else if (c == QLatin1Char('?')) { |
|
6227 input = InpQm; |
|
6228 } else if (c == QLatin1Char('*')) { |
|
6229 input = InpAst; |
|
6230 } else if (c == QLatin1Char('+')) { |
|
6231 input = InpPlus; |
|
6232 } else if (c == QLatin1Char('A')) { |
|
6233 input = InpA; |
|
6234 } else if (c == QLatin1Char('E')) { |
|
6235 input = InpE; |
|
6236 } else if (c == QLatin1Char('L')) { |
|
6237 input = InpL; |
|
6238 } else { |
|
6239 input = InpUnknown; |
|
6240 } |
|
6241 state = table[state][input]; |
|
6242 |
|
6243 switch (state) { |
|
6244 case Elem: |
|
6245 parseString_s = QLatin1String("LEMENT"); |
|
6246 if (!parseString()) { |
|
6247 parseFailed(&QXmlSimpleReaderPrivate::parseElementDecl, state); |
|
6248 return false; |
|
6249 } |
|
6250 break; |
|
6251 case Ws1: |
|
6252 if (!eat_ws()) { |
|
6253 parseFailed(&QXmlSimpleReaderPrivate::parseElementDecl, state); |
|
6254 return false; |
|
6255 } |
|
6256 break; |
|
6257 case Nam: |
|
6258 parseName_useRef = false; |
|
6259 if (!parseName()) { |
|
6260 parseFailed(&QXmlSimpleReaderPrivate::parseElementDecl, state); |
|
6261 return false; |
|
6262 } |
|
6263 break; |
|
6264 case Ws2: |
|
6265 if (!eat_ws()) { |
|
6266 parseFailed(&QXmlSimpleReaderPrivate::parseElementDecl, state); |
|
6267 return false; |
|
6268 } |
|
6269 break; |
|
6270 case Empty: |
|
6271 parseString_s = QLatin1String("EMPTY"); |
|
6272 if (!parseString()) { |
|
6273 parseFailed(&QXmlSimpleReaderPrivate::parseElementDecl, state); |
|
6274 return false; |
|
6275 } |
|
6276 break; |
|
6277 case Any: |
|
6278 parseString_s = QLatin1String("ANY"); |
|
6279 if (!parseString()) { |
|
6280 parseFailed(&QXmlSimpleReaderPrivate::parseElementDecl, state); |
|
6281 return false; |
|
6282 } |
|
6283 break; |
|
6284 case Cont: |
|
6285 if (!next_eat_ws()) { |
|
6286 parseFailed(&QXmlSimpleReaderPrivate::parseElementDecl, state); |
|
6287 return false; |
|
6288 } |
|
6289 break; |
|
6290 case Mix: |
|
6291 parseString_s = QLatin1String("#PCDATA"); |
|
6292 if (!parseString()) { |
|
6293 parseFailed(&QXmlSimpleReaderPrivate::parseElementDecl, state); |
|
6294 return false; |
|
6295 } |
|
6296 break; |
|
6297 case Mix2: |
|
6298 if (!eat_ws()) { |
|
6299 parseFailed(&QXmlSimpleReaderPrivate::parseElementDecl, state); |
|
6300 return false; |
|
6301 } |
|
6302 break; |
|
6303 case Mix3: |
|
6304 next(); |
|
6305 break; |
|
6306 case MixN1: |
|
6307 if (!next_eat_ws()) { |
|
6308 parseFailed(&QXmlSimpleReaderPrivate::parseElementDecl, state); |
|
6309 return false; |
|
6310 } |
|
6311 break; |
|
6312 case MixN2: |
|
6313 parseName_useRef = false; |
|
6314 if (!parseName()) { |
|
6315 parseFailed(&QXmlSimpleReaderPrivate::parseElementDecl, state); |
|
6316 return false; |
|
6317 } |
|
6318 break; |
|
6319 case MixN3: |
|
6320 if (!eat_ws()) { |
|
6321 parseFailed(&QXmlSimpleReaderPrivate::parseElementDecl, state); |
|
6322 return false; |
|
6323 } |
|
6324 break; |
|
6325 case MixN4: |
|
6326 next(); |
|
6327 break; |
|
6328 case Cp: |
|
6329 if (!parseChoiceSeq()) { |
|
6330 parseFailed(&QXmlSimpleReaderPrivate::parseElementDecl, state); |
|
6331 return false; |
|
6332 } |
|
6333 break; |
|
6334 case Cp2: |
|
6335 next(); |
|
6336 break; |
|
6337 case WsD: |
|
6338 if (!next_eat_ws()) { |
|
6339 parseFailed(&QXmlSimpleReaderPrivate::parseElementDecl, state); |
|
6340 return false; |
|
6341 } |
|
6342 break; |
|
6343 case Done: |
|
6344 next(); |
|
6345 break; |
|
6346 } |
|
6347 } |
|
6348 return false; |
|
6349 } |
|
6350 |
|
6351 /* |
|
6352 Parse a NotationDecl [82]. |
|
6353 |
|
6354 Precondition: the beginning '<!' is already read and the head |
|
6355 stands on the 'N' of '<!NOTATION' |
|
6356 */ |
|
6357 bool QXmlSimpleReaderPrivate::parseNotationDecl() |
|
6358 { |
|
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; |
|
6368 |
|
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; |
|
6373 |
|
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 |
|
6384 }; |
|
6385 signed char state; |
|
6386 signed char input; |
|
6387 |
|
6388 if (parseStack==0 || parseStack->isEmpty()) { |
|
6389 state = Init; |
|
6390 } else { |
|
6391 state = parseStack->pop().state; |
|
6392 #if defined(QT_QXML_DEBUG) |
|
6393 qDebug("QXmlSimpleReader: parseNotationDecl (cont) in state %d", state); |
|
6394 #endif |
|
6395 if (!parseStack->isEmpty()) { |
|
6396 ParseFunction function = parseStack->top().function; |
|
6397 if (function == &QXmlSimpleReaderPrivate::eat_ws) { |
|
6398 parseStack->pop(); |
|
6399 #if defined(QT_QXML_DEBUG) |
|
6400 qDebug("QXmlSimpleReader: eat_ws (cont)"); |
|
6401 #endif |
|
6402 } |
|
6403 if (!(this->*function)()) { |
|
6404 parseFailed(&QXmlSimpleReaderPrivate::parseNotationDecl, state); |
|
6405 return false; |
|
6406 } |
|
6407 } |
|
6408 } |
|
6409 |
|
6410 for (;;) { |
|
6411 switch (state) { |
|
6412 case ExtID: |
|
6413 // call the handler |
|
6414 if (dtdHnd) { |
|
6415 if (!dtdHnd->notationDecl(name(), publicId, systemId)) { |
|
6416 reportParseError(dtdHnd->errorString()); |
|
6417 return false; |
|
6418 } |
|
6419 } |
|
6420 state = ExtIDR; |
|
6421 break; |
|
6422 case Done: |
|
6423 return true; |
|
6424 case -1: |
|
6425 // Error |
|
6426 reportParseError(QLatin1String(XMLERR_UNEXPECTEDCHARACTER)); |
|
6427 return false; |
|
6428 } |
|
6429 |
|
6430 if (atEnd()) { |
|
6431 unexpectedEof(&QXmlSimpleReaderPrivate::parseNotationDecl, state); |
|
6432 return false; |
|
6433 } |
|
6434 if (is_S(c)) { |
|
6435 input = InpWs; |
|
6436 } else if (c == QLatin1Char('>')) { |
|
6437 input = InpGt; |
|
6438 } else if (c == QLatin1Char('N')) { |
|
6439 input = InpN; |
|
6440 } else { |
|
6441 input = InpUnknown; |
|
6442 } |
|
6443 state = table[state][input]; |
|
6444 |
|
6445 switch (state) { |
|
6446 case Not: |
|
6447 parseString_s = QLatin1String("NOTATION"); |
|
6448 if (!parseString()) { |
|
6449 parseFailed(&QXmlSimpleReaderPrivate::parseNotationDecl, state); |
|
6450 return false; |
|
6451 } |
|
6452 break; |
|
6453 case Ws1: |
|
6454 if (!eat_ws()) { |
|
6455 parseFailed(&QXmlSimpleReaderPrivate::parseNotationDecl, state); |
|
6456 return false; |
|
6457 } |
|
6458 break; |
|
6459 case Nam: |
|
6460 parseName_useRef = false; |
|
6461 if (!parseName()) { |
|
6462 parseFailed(&QXmlSimpleReaderPrivate::parseNotationDecl, state); |
|
6463 return false; |
|
6464 } |
|
6465 break; |
|
6466 case Ws2: |
|
6467 if (!eat_ws()) { |
|
6468 parseFailed(&QXmlSimpleReaderPrivate::parseNotationDecl, state); |
|
6469 return false; |
|
6470 } |
|
6471 break; |
|
6472 case ExtID: |
|
6473 case ExtIDR: |
|
6474 parseExternalID_allowPublicID = true; |
|
6475 if (!parseExternalID()) { |
|
6476 parseFailed(&QXmlSimpleReaderPrivate::parseNotationDecl, state); |
|
6477 return false; |
|
6478 } |
|
6479 break; |
|
6480 case Ws3: |
|
6481 if (!eat_ws()) { |
|
6482 parseFailed(&QXmlSimpleReaderPrivate::parseNotationDecl, state); |
|
6483 return false; |
|
6484 } |
|
6485 break; |
|
6486 case Done: |
|
6487 next(); |
|
6488 break; |
|
6489 } |
|
6490 } |
|
6491 return false; |
|
6492 } |
|
6493 |
|
6494 /* |
|
6495 Parse choice [49] or seq [50]. |
|
6496 |
|
6497 Precondition: the beginning '('S? is already read and the head |
|
6498 stands on the first non-whitespace character after it. |
|
6499 */ |
|
6500 bool QXmlSimpleReaderPrivate::parseChoiceSeq() |
|
6501 { |
|
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; // |
|
6509 |
|
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; |
|
6519 |
|
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) |
|
6528 }; |
|
6529 signed char state; |
|
6530 signed char input; |
|
6531 |
|
6532 if (parseStack==0 || parseStack->isEmpty()) { |
|
6533 state = Init; |
|
6534 } else { |
|
6535 state = parseStack->pop().state; |
|
6536 #if defined(QT_QXML_DEBUG) |
|
6537 qDebug("QXmlSimpleReader: parseChoiceSeq (cont) in state %d", state); |
|
6538 #endif |
|
6539 if (!parseStack->isEmpty()) { |
|
6540 ParseFunction function = parseStack->top().function; |
|
6541 if (function == &QXmlSimpleReaderPrivate::eat_ws) { |
|
6542 parseStack->pop(); |
|
6543 #if defined(QT_QXML_DEBUG) |
|
6544 qDebug("QXmlSimpleReader: eat_ws (cont)"); |
|
6545 #endif |
|
6546 } |
|
6547 if (!(this->*function)()) { |
|
6548 parseFailed(&QXmlSimpleReaderPrivate::parseChoiceSeq, state); |
|
6549 return false; |
|
6550 } |
|
6551 } |
|
6552 } |
|
6553 |
|
6554 for (;;) { |
|
6555 switch (state) { |
|
6556 case Done: |
|
6557 return true; |
|
6558 case -1: |
|
6559 // Error |
|
6560 reportParseError(QLatin1String(XMLERR_UNEXPECTEDCHARACTER)); |
|
6561 return false; |
|
6562 } |
|
6563 |
|
6564 if (atEnd()) { |
|
6565 unexpectedEof(&QXmlSimpleReaderPrivate::parseChoiceSeq, state); |
|
6566 return false; |
|
6567 } |
|
6568 if (is_S(c)) { |
|
6569 input = InpWs; |
|
6570 } else if (c == QLatin1Char('(')) { |
|
6571 input = InpOp; |
|
6572 } else if (c == QLatin1Char(')')) { |
|
6573 input = InpCp; |
|
6574 } else if (c == QLatin1Char('?')) { |
|
6575 input = InpQm; |
|
6576 } else if (c == QLatin1Char('*')) { |
|
6577 input = InpAst; |
|
6578 } else if (c == QLatin1Char('+')) { |
|
6579 input = InpPlus; |
|
6580 } else if (c == QLatin1Char('|')) { |
|
6581 input = InpPipe; |
|
6582 } else if (c == QLatin1Char(',')) { |
|
6583 input = InpComm; |
|
6584 } else { |
|
6585 input = InpUnknown; |
|
6586 } |
|
6587 state = table[state][input]; |
|
6588 |
|
6589 switch (state) { |
|
6590 case Ws1: |
|
6591 if (!next_eat_ws()) { |
|
6592 parseFailed(&QXmlSimpleReaderPrivate::parseChoiceSeq, state); |
|
6593 return false; |
|
6594 } |
|
6595 break; |
|
6596 case CoS: |
|
6597 if (!parseChoiceSeq()) { |
|
6598 parseFailed(&QXmlSimpleReaderPrivate::parseChoiceSeq, state); |
|
6599 return false; |
|
6600 } |
|
6601 break; |
|
6602 case Ws2: |
|
6603 if (!next_eat_ws()) { |
|
6604 parseFailed(&QXmlSimpleReaderPrivate::parseChoiceSeq, state); |
|
6605 return false; |
|
6606 } |
|
6607 break; |
|
6608 case More: |
|
6609 if (!next_eat_ws()) { |
|
6610 parseFailed(&QXmlSimpleReaderPrivate::parseChoiceSeq, state); |
|
6611 return false; |
|
6612 } |
|
6613 break; |
|
6614 case Name: |
|
6615 parseName_useRef = false; |
|
6616 if (!parseName()) { |
|
6617 parseFailed(&QXmlSimpleReaderPrivate::parseChoiceSeq, state); |
|
6618 return false; |
|
6619 } |
|
6620 break; |
|
6621 case Done: |
|
6622 next(); |
|
6623 break; |
|
6624 } |
|
6625 } |
|
6626 return false; |
|
6627 } |
|
6628 |
|
6629 /* |
|
6630 Parse a EntityDecl [70]. |
|
6631 |
|
6632 Precondition: the beginning '<!E' is already read and the head |
|
6633 stand on the 'N' of '<!ENTITY' |
|
6634 */ |
|
6635 bool QXmlSimpleReaderPrivate::parseEntityDecl() |
|
6636 { |
|
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 |
|
6661 |
|
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; |
|
6668 |
|
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 |
|
6693 }; |
|
6694 signed char state; |
|
6695 signed char input; |
|
6696 |
|
6697 if (parseStack==0 || parseStack->isEmpty()) { |
|
6698 state = Init; |
|
6699 } else { |
|
6700 state = parseStack->pop().state; |
|
6701 #if defined(QT_QXML_DEBUG) |
|
6702 qDebug("QXmlSimpleReader: parseEntityDecl (cont) in state %d", state); |
|
6703 #endif |
|
6704 if (!parseStack->isEmpty()) { |
|
6705 ParseFunction function = parseStack->top().function; |
|
6706 if (function == &QXmlSimpleReaderPrivate::eat_ws) { |
|
6707 parseStack->pop(); |
|
6708 #if defined(QT_QXML_DEBUG) |
|
6709 qDebug("QXmlSimpleReader: eat_ws (cont)"); |
|
6710 #endif |
|
6711 } |
|
6712 if (!(this->*function)()) { |
|
6713 parseFailed(&QXmlSimpleReaderPrivate::parseEntityDecl, state); |
|
6714 return false; |
|
6715 } |
|
6716 } |
|
6717 } |
|
6718 |
|
6719 for (;;) { |
|
6720 switch (state) { |
|
6721 case EValue: |
|
6722 if ( !entityExist(name())) { |
|
6723 entities.insert(name(), string()); |
|
6724 if (declHnd) { |
|
6725 if (!declHnd->internalEntityDecl(name(), string())) { |
|
6726 reportParseError(declHnd->errorString()); |
|
6727 return false; |
|
6728 } |
|
6729 } |
|
6730 } |
|
6731 state = EValueR; |
|
6732 break; |
|
6733 case NNam: |
|
6734 if ( !entityExist(name())) { |
|
6735 externEntities.insert(name(), QXmlSimpleReaderPrivate::ExternEntity(publicId, systemId, ref())); |
|
6736 if (dtdHnd) { |
|
6737 if (!dtdHnd->unparsedEntityDecl(name(), publicId, systemId, ref())) { |
|
6738 reportParseError(declHnd->errorString()); |
|
6739 return false; |
|
6740 } |
|
6741 } |
|
6742 } |
|
6743 state = NNamR; |
|
6744 break; |
|
6745 case PEVal: |
|
6746 if ( !entityExist(name())) { |
|
6747 parameterEntities.insert(name(), string()); |
|
6748 if (declHnd) { |
|
6749 if (!declHnd->internalEntityDecl(QLatin1Char('%') + name(), string())) { |
|
6750 reportParseError(declHnd->errorString()); |
|
6751 return false; |
|
6752 } |
|
6753 } |
|
6754 } |
|
6755 state = PEValR; |
|
6756 break; |
|
6757 case PEEID: |
|
6758 if ( !entityExist(name())) { |
|
6759 externParameterEntities.insert(name(), QXmlSimpleReaderPrivate::ExternParameterEntity(publicId, systemId)); |
|
6760 if (declHnd) { |
|
6761 if (!declHnd->externalEntityDecl(QLatin1Char('%') + name(), publicId, systemId)) { |
|
6762 reportParseError(declHnd->errorString()); |
|
6763 return false; |
|
6764 } |
|
6765 } |
|
6766 } |
|
6767 state = PEEIDR; |
|
6768 break; |
|
6769 case EDDone: |
|
6770 if ( !entityExist(name())) { |
|
6771 externEntities.insert(name(), QXmlSimpleReaderPrivate::ExternEntity(publicId, systemId, QString())); |
|
6772 if (declHnd) { |
|
6773 if (!declHnd->externalEntityDecl(name(), publicId, systemId)) { |
|
6774 reportParseError(declHnd->errorString()); |
|
6775 return false; |
|
6776 } |
|
6777 } |
|
6778 } |
|
6779 return true; |
|
6780 case Done: |
|
6781 return true; |
|
6782 case -1: |
|
6783 // Error |
|
6784 reportParseError(QLatin1String(XMLERR_LETTEREXPECTED)); |
|
6785 return false; |
|
6786 } |
|
6787 |
|
6788 if (atEnd()) { |
|
6789 unexpectedEof(&QXmlSimpleReaderPrivate::parseEntityDecl, state); |
|
6790 return false; |
|
6791 } |
|
6792 if (is_S(c)) { |
|
6793 input = InpWs; |
|
6794 } else if (c == QLatin1Char('%')) { |
|
6795 input = InpPer; |
|
6796 } else if (c == QLatin1Char('"') || c == QLatin1Char('\'')) { |
|
6797 input = InpQuot; |
|
6798 } else if (c == QLatin1Char('>')) { |
|
6799 input = InpGt; |
|
6800 } else if (c == QLatin1Char('N')) { |
|
6801 input = InpN; |
|
6802 } else { |
|
6803 input = InpUnknown; |
|
6804 } |
|
6805 state = table[state][input]; |
|
6806 |
|
6807 switch (state) { |
|
6808 case Ent: |
|
6809 parseString_s = QLatin1String("NTITY"); |
|
6810 if (!parseString()) { |
|
6811 parseFailed(&QXmlSimpleReaderPrivate::parseEntityDecl, state); |
|
6812 return false; |
|
6813 } |
|
6814 break; |
|
6815 case Ws1: |
|
6816 if (!eat_ws()) { |
|
6817 parseFailed(&QXmlSimpleReaderPrivate::parseEntityDecl, state); |
|
6818 return false; |
|
6819 } |
|
6820 break; |
|
6821 case Name: |
|
6822 parseName_useRef = false; |
|
6823 if (!parseName()) { |
|
6824 parseFailed(&QXmlSimpleReaderPrivate::parseEntityDecl, state); |
|
6825 return false; |
|
6826 } |
|
6827 break; |
|
6828 case Ws2: |
|
6829 if (!eat_ws()) { |
|
6830 parseFailed(&QXmlSimpleReaderPrivate::parseEntityDecl, state); |
|
6831 return false; |
|
6832 } |
|
6833 break; |
|
6834 case EValue: |
|
6835 case EValueR: |
|
6836 if (!parseEntityValue()) { |
|
6837 parseFailed(&QXmlSimpleReaderPrivate::parseEntityDecl, state); |
|
6838 return false; |
|
6839 } |
|
6840 break; |
|
6841 case ExtID: |
|
6842 parseExternalID_allowPublicID = false; |
|
6843 if (!parseExternalID()) { |
|
6844 parseFailed(&QXmlSimpleReaderPrivate::parseEntityDecl, state); |
|
6845 return false; |
|
6846 } |
|
6847 break; |
|
6848 case Ws3: |
|
6849 if (!eat_ws()) { |
|
6850 parseFailed(&QXmlSimpleReaderPrivate::parseEntityDecl, state); |
|
6851 return false; |
|
6852 } |
|
6853 break; |
|
6854 case Ndata: |
|
6855 parseString_s = QLatin1String("NDATA"); |
|
6856 if (!parseString()) { |
|
6857 parseFailed(&QXmlSimpleReaderPrivate::parseEntityDecl, state); |
|
6858 return false; |
|
6859 } |
|
6860 break; |
|
6861 case Ws4: |
|
6862 if (!eat_ws()) { |
|
6863 parseFailed(&QXmlSimpleReaderPrivate::parseEntityDecl, state); |
|
6864 return false; |
|
6865 } |
|
6866 break; |
|
6867 case NNam: |
|
6868 case NNamR: |
|
6869 parseName_useRef = true; |
|
6870 if (!parseName()) { |
|
6871 parseFailed(&QXmlSimpleReaderPrivate::parseEntityDecl, state); |
|
6872 return false; |
|
6873 } |
|
6874 break; |
|
6875 case PEDec: |
|
6876 next(); |
|
6877 break; |
|
6878 case Ws6: |
|
6879 if (!eat_ws()) { |
|
6880 parseFailed(&QXmlSimpleReaderPrivate::parseEntityDecl, state); |
|
6881 return false; |
|
6882 } |
|
6883 break; |
|
6884 case PENam: |
|
6885 parseName_useRef = false; |
|
6886 if (!parseName()) { |
|
6887 parseFailed(&QXmlSimpleReaderPrivate::parseEntityDecl, state); |
|
6888 return false; |
|
6889 } |
|
6890 break; |
|
6891 case Ws7: |
|
6892 if (!eat_ws()) { |
|
6893 parseFailed(&QXmlSimpleReaderPrivate::parseEntityDecl, state); |
|
6894 return false; |
|
6895 } |
|
6896 break; |
|
6897 case PEVal: |
|
6898 case PEValR: |
|
6899 if (!parseEntityValue()) { |
|
6900 parseFailed(&QXmlSimpleReaderPrivate::parseEntityDecl, state); |
|
6901 return false; |
|
6902 } |
|
6903 break; |
|
6904 case PEEID: |
|
6905 case PEEIDR: |
|
6906 parseExternalID_allowPublicID = false; |
|
6907 if (!parseExternalID()) { |
|
6908 parseFailed(&QXmlSimpleReaderPrivate::parseEntityDecl, state); |
|
6909 return false; |
|
6910 } |
|
6911 break; |
|
6912 case WsE: |
|
6913 if (!eat_ws()) { |
|
6914 parseFailed(&QXmlSimpleReaderPrivate::parseEntityDecl, state); |
|
6915 return false; |
|
6916 } |
|
6917 break; |
|
6918 case EDDone: |
|
6919 next(); |
|
6920 break; |
|
6921 case Done: |
|
6922 next(); |
|
6923 break; |
|
6924 } |
|
6925 } |
|
6926 return false; |
|
6927 } |
|
6928 |
|
6929 /* |
|
6930 Parse a EntityValue [9] |
|
6931 */ |
|
6932 bool QXmlSimpleReaderPrivate::parseEntityValue() |
|
6933 { |
|
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; |
|
6944 |
|
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; |
|
6950 |
|
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 |
|
6962 }; |
|
6963 signed char state; |
|
6964 signed char input; |
|
6965 |
|
6966 if (parseStack==0 || parseStack->isEmpty()) { |
|
6967 state = Init; |
|
6968 } else { |
|
6969 state = parseStack->pop().state; |
|
6970 #if defined(QT_QXML_DEBUG) |
|
6971 qDebug("QXmlSimpleReader: parseEntityValue (cont) in state %d", state); |
|
6972 #endif |
|
6973 if (!parseStack->isEmpty()) { |
|
6974 ParseFunction function = parseStack->top().function; |
|
6975 if (function == &QXmlSimpleReaderPrivate::eat_ws) { |
|
6976 parseStack->pop(); |
|
6977 #if defined(QT_QXML_DEBUG) |
|
6978 qDebug("QXmlSimpleReader: eat_ws (cont)"); |
|
6979 #endif |
|
6980 } |
|
6981 if (!(this->*function)()) { |
|
6982 parseFailed(&QXmlSimpleReaderPrivate::parseEntityValue, state); |
|
6983 return false; |
|
6984 } |
|
6985 } |
|
6986 } |
|
6987 |
|
6988 for (;;) { |
|
6989 switch (state) { |
|
6990 case Done: |
|
6991 return true; |
|
6992 case -1: |
|
6993 // Error |
|
6994 reportParseError(QLatin1String(XMLERR_LETTEREXPECTED)); |
|
6995 return false; |
|
6996 } |
|
6997 |
|
6998 if (atEnd()) { |
|
6999 unexpectedEof(&QXmlSimpleReaderPrivate::parseEntityValue, state); |
|
7000 return false; |
|
7001 } |
|
7002 if (c == QLatin1Char('"')) { |
|
7003 input = InpDq; |
|
7004 } else if (c == QLatin1Char('\'')) { |
|
7005 input = InpSq; |
|
7006 } else if (c == QLatin1Char('&')) { |
|
7007 input = InpAmp; |
|
7008 } else if (c == QLatin1Char('%')) { |
|
7009 input = InpPer; |
|
7010 } else { |
|
7011 input = InpUnknown; |
|
7012 } |
|
7013 state = table[state][input]; |
|
7014 |
|
7015 switch (state) { |
|
7016 case Dq: |
|
7017 case Sq: |
|
7018 stringClear(); |
|
7019 next(); |
|
7020 break; |
|
7021 case DqC: |
|
7022 case SqC: |
|
7023 stringAddC(); |
|
7024 next(); |
|
7025 break; |
|
7026 case DqPER: |
|
7027 case SqPER: |
|
7028 parsePEReference_context = InEntityValue; |
|
7029 if (!parsePEReference()) { |
|
7030 parseFailed(&QXmlSimpleReaderPrivate::parseEntityValue, state); |
|
7031 return false; |
|
7032 } |
|
7033 break; |
|
7034 case DqRef: |
|
7035 case SqRef: |
|
7036 parseReference_context = InEntityValue; |
|
7037 if (!parseReference()) { |
|
7038 parseFailed(&QXmlSimpleReaderPrivate::parseEntityValue, state); |
|
7039 return false; |
|
7040 } |
|
7041 break; |
|
7042 case Done: |
|
7043 next(); |
|
7044 break; |
|
7045 } |
|
7046 } |
|
7047 return false; |
|
7048 } |
|
7049 |
|
7050 /* |
|
7051 Parse a comment [15]. |
|
7052 |
|
7053 Precondition: the beginning '<!' of the comment is already read and the head |
|
7054 stands on the first '-' of '<!--'. |
|
7055 |
|
7056 If this funktion was successful, the head-position is on the first |
|
7057 character after the comment. |
|
7058 */ |
|
7059 bool QXmlSimpleReaderPrivate::parseComment() |
|
7060 { |
|
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; |
|
7068 |
|
7069 const signed char InpDash = 0; // - |
|
7070 const signed char InpGt = 1; // > |
|
7071 const signed char InpUnknown = 2; |
|
7072 |
|
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 |
|
7081 }; |
|
7082 signed char state; |
|
7083 signed char input; |
|
7084 |
|
7085 if (parseStack==0 || parseStack->isEmpty()) { |
|
7086 state = Init; |
|
7087 } else { |
|
7088 state = parseStack->pop().state; |
|
7089 #if defined(QT_QXML_DEBUG) |
|
7090 qDebug("QXmlSimpleReader: parseComment (cont) in state %d", state); |
|
7091 #endif |
|
7092 if (!parseStack->isEmpty()) { |
|
7093 ParseFunction function = parseStack->top().function; |
|
7094 if (function == &QXmlSimpleReaderPrivate::eat_ws) { |
|
7095 parseStack->pop(); |
|
7096 #if defined(QT_QXML_DEBUG) |
|
7097 qDebug("QXmlSimpleReader: eat_ws (cont)"); |
|
7098 #endif |
|
7099 } |
|
7100 if (!(this->*function)()) { |
|
7101 parseFailed(&QXmlSimpleReaderPrivate::parseComment, state); |
|
7102 return false; |
|
7103 } |
|
7104 } |
|
7105 } |
|
7106 |
|
7107 for (;;) { |
|
7108 switch (state) { |
|
7109 case Dash2: |
|
7110 stringClear(); |
|
7111 break; |
|
7112 case Com2: |
|
7113 // if next character is not a dash than don't skip it |
|
7114 if (!atEnd() && c != QLatin1Char('-')) |
|
7115 stringAddC(QLatin1Char('-')); |
|
7116 break; |
|
7117 case Done: |
|
7118 return true; |
|
7119 case -1: |
|
7120 // Error |
|
7121 reportParseError(QLatin1String(XMLERR_ERRORPARSINGCOMMENT)); |
|
7122 return false; |
|
7123 } |
|
7124 |
|
7125 if (atEnd()) { |
|
7126 unexpectedEof(&QXmlSimpleReaderPrivate::parseComment, state); |
|
7127 return false; |
|
7128 } |
|
7129 if (c == QLatin1Char('-')) { |
|
7130 input = InpDash; |
|
7131 } else if (c == QLatin1Char('>')) { |
|
7132 input = InpGt; |
|
7133 } else { |
|
7134 input = InpUnknown; |
|
7135 } |
|
7136 state = table[state][input]; |
|
7137 |
|
7138 switch (state) { |
|
7139 case Dash1: |
|
7140 next(); |
|
7141 break; |
|
7142 case Dash2: |
|
7143 next(); |
|
7144 break; |
|
7145 case Com: |
|
7146 stringAddC(); |
|
7147 next(); |
|
7148 break; |
|
7149 case Com2: |
|
7150 next(); |
|
7151 break; |
|
7152 case ComE: |
|
7153 next(); |
|
7154 break; |
|
7155 case Done: |
|
7156 next(); |
|
7157 break; |
|
7158 } |
|
7159 } |
|
7160 return false; |
|
7161 } |
|
7162 |
|
7163 /* |
|
7164 Parse an Attribute [41]. |
|
7165 |
|
7166 Precondition: the head stands on the first character of the name |
|
7167 of the attribute (i.e. all whitespaces are already parsed). |
|
7168 |
|
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. |
|
7172 */ |
|
7173 bool QXmlSimpleReaderPrivate::parseAttribute() |
|
7174 { |
|
7175 const int Init = 0; |
|
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 |
|
7180 |
|
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; |
|
7186 |
|
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 |
|
7193 }; |
|
7194 int state; |
|
7195 int input; |
|
7196 |
|
7197 if (parseStack==0 || parseStack->isEmpty()) { |
|
7198 state = Init; |
|
7199 } else { |
|
7200 state = parseStack->pop().state; |
|
7201 #if defined(QT_QXML_DEBUG) |
|
7202 qDebug("QXmlSimpleReader: parseAttribute (cont) in state %d", state); |
|
7203 #endif |
|
7204 if (!parseStack->isEmpty()) { |
|
7205 ParseFunction function = parseStack->top().function; |
|
7206 if (function == &QXmlSimpleReaderPrivate::eat_ws) { |
|
7207 parseStack->pop(); |
|
7208 #if defined(QT_QXML_DEBUG) |
|
7209 qDebug("QXmlSimpleReader: eat_ws (cont)"); |
|
7210 #endif |
|
7211 } |
|
7212 if (!(this->*function)()) { |
|
7213 parseFailed(&QXmlSimpleReaderPrivate::parseAttribute, state); |
|
7214 return false; |
|
7215 } |
|
7216 } |
|
7217 } |
|
7218 |
|
7219 for (;;) { |
|
7220 switch (state) { |
|
7221 case Quotes: |
|
7222 // Done |
|
7223 return true; |
|
7224 case -1: |
|
7225 // Error |
|
7226 reportParseError(QLatin1String(XMLERR_UNEXPECTEDCHARACTER)); |
|
7227 return false; |
|
7228 } |
|
7229 |
|
7230 if (atEnd()) { |
|
7231 unexpectedEof(&QXmlSimpleReaderPrivate::parseAttribute, state); |
|
7232 return false; |
|
7233 } |
|
7234 if (determineNameChar(c) == NameBeginning) { |
|
7235 input = InpNameBe; |
|
7236 } else if (c == QLatin1Char('=')) { |
|
7237 input = InpEq; |
|
7238 } else if (c == QLatin1Char('"')) { |
|
7239 input = InpDq; |
|
7240 } else if (c == QLatin1Char('\'')) { |
|
7241 input = InpSq; |
|
7242 } else { |
|
7243 input = InpUnknown; |
|
7244 } |
|
7245 state = table[state][input]; |
|
7246 |
|
7247 switch (state) { |
|
7248 case PName: |
|
7249 parseName_useRef = false; |
|
7250 if (!parseName()) { |
|
7251 parseFailed(&QXmlSimpleReaderPrivate::parseAttribute, state); |
|
7252 return false; |
|
7253 } |
|
7254 break; |
|
7255 case Ws: |
|
7256 if (!eat_ws()) { |
|
7257 parseFailed(&QXmlSimpleReaderPrivate::parseAttribute, state); |
|
7258 return false; |
|
7259 } |
|
7260 break; |
|
7261 case Eq: |
|
7262 if (!next_eat_ws()) { |
|
7263 parseFailed(&QXmlSimpleReaderPrivate::parseAttribute, state); |
|
7264 return false; |
|
7265 } |
|
7266 break; |
|
7267 case Quotes: |
|
7268 if (!parseAttValue()) { |
|
7269 parseFailed(&QXmlSimpleReaderPrivate::parseAttribute, state); |
|
7270 return false; |
|
7271 } |
|
7272 break; |
|
7273 } |
|
7274 } |
|
7275 return false; |
|
7276 } |
|
7277 |
|
7278 /* |
|
7279 Parse a Name [5] and store the name in name or ref (if useRef is true). |
|
7280 */ |
|
7281 bool QXmlSimpleReaderPrivate::parseName() |
|
7282 { |
|
7283 const int Init = 0; |
|
7284 const int Name1 = 1; // parse first character of the name |
|
7285 const int Name = 2; // parse name |
|
7286 const int Done = 3; |
|
7287 |
|
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 |
|
7293 }; |
|
7294 int state; |
|
7295 |
|
7296 if (parseStack==0 || parseStack->isEmpty()) { |
|
7297 state = Init; |
|
7298 } else { |
|
7299 state = parseStack->pop().state; |
|
7300 #if defined(QT_QXML_DEBUG) |
|
7301 qDebug("QXmlSimpleReader: parseName (cont) in state %d", state); |
|
7302 #endif |
|
7303 if (!parseStack->isEmpty()) { |
|
7304 ParseFunction function = parseStack->top().function; |
|
7305 if (function == &QXmlSimpleReaderPrivate::eat_ws) { |
|
7306 parseStack->pop(); |
|
7307 #if defined(QT_QXML_DEBUG) |
|
7308 qDebug("QXmlSimpleReader: eat_ws (cont)"); |
|
7309 #endif |
|
7310 } |
|
7311 if (!(this->*function)()) { |
|
7312 parseFailed(&QXmlSimpleReaderPrivate::parseName, state); |
|
7313 return false; |
|
7314 } |
|
7315 } |
|
7316 } |
|
7317 |
|
7318 for (;;) { |
|
7319 switch (state) { |
|
7320 case Done: |
|
7321 return true; |
|
7322 case -1: |
|
7323 // Error |
|
7324 reportParseError(QLatin1String(XMLERR_LETTEREXPECTED)); |
|
7325 return false; |
|
7326 } |
|
7327 |
|
7328 if (atEnd()) { |
|
7329 unexpectedEof(&QXmlSimpleReaderPrivate::parseName, state); |
|
7330 return false; |
|
7331 } |
|
7332 |
|
7333 // we can safely do the (int) cast thanks to the Q_ASSERTs earlier in this function |
|
7334 state = table[state][(int)fastDetermineNameChar(c)]; |
|
7335 |
|
7336 switch (state) { |
|
7337 case Name1: |
|
7338 if (parseName_useRef) { |
|
7339 refClear(); |
|
7340 refAddC(); |
|
7341 } else { |
|
7342 nameClear(); |
|
7343 nameAddC(); |
|
7344 } |
|
7345 next(); |
|
7346 break; |
|
7347 case Name: |
|
7348 if (parseName_useRef) { |
|
7349 refAddC(); |
|
7350 } else { |
|
7351 nameAddC(); |
|
7352 } |
|
7353 next(); |
|
7354 break; |
|
7355 } |
|
7356 } |
|
7357 return false; |
|
7358 } |
|
7359 |
|
7360 /* |
|
7361 Parse a Nmtoken [7] and store the name in name. |
|
7362 */ |
|
7363 bool QXmlSimpleReaderPrivate::parseNmtoken() |
|
7364 { |
|
7365 const signed char Init = 0; |
|
7366 const signed char NameF = 1; |
|
7367 const signed char Name = 2; |
|
7368 const signed char Done = 3; |
|
7369 |
|
7370 const signed char InpNameCh = 0; // NameChar without InpNameBe |
|
7371 const signed char InpUnknown = 1; |
|
7372 |
|
7373 static const signed char table[3][2] = { |
|
7374 /* InpNameCh InpUnknown */ |
|
7375 { NameF, -1 }, // Init |
|
7376 { Name, Done }, // NameF |
|
7377 { Name, Done } // Name |
|
7378 }; |
|
7379 signed char state; |
|
7380 signed char input; |
|
7381 |
|
7382 if (parseStack==0 || parseStack->isEmpty()) { |
|
7383 state = Init; |
|
7384 } else { |
|
7385 state = parseStack->pop().state; |
|
7386 #if defined(QT_QXML_DEBUG) |
|
7387 qDebug("QXmlSimpleReader: parseNmtoken (cont) in state %d", state); |
|
7388 #endif |
|
7389 if (!parseStack->isEmpty()) { |
|
7390 ParseFunction function = parseStack->top().function; |
|
7391 if (function == &QXmlSimpleReaderPrivate::eat_ws) { |
|
7392 parseStack->pop(); |
|
7393 #if defined(QT_QXML_DEBUG) |
|
7394 qDebug("QXmlSimpleReader: eat_ws (cont)"); |
|
7395 #endif |
|
7396 } |
|
7397 if (!(this->*function)()) { |
|
7398 parseFailed(&QXmlSimpleReaderPrivate::parseNmtoken, state); |
|
7399 return false; |
|
7400 } |
|
7401 } |
|
7402 } |
|
7403 |
|
7404 for (;;) { |
|
7405 switch (state) { |
|
7406 case Done: |
|
7407 return true; |
|
7408 case -1: |
|
7409 // Error |
|
7410 reportParseError(QLatin1String(XMLERR_LETTEREXPECTED)); |
|
7411 return false; |
|
7412 } |
|
7413 |
|
7414 if (atEnd()) { |
|
7415 unexpectedEof(&QXmlSimpleReaderPrivate::parseNmtoken, state); |
|
7416 return false; |
|
7417 } |
|
7418 if (determineNameChar(c) == NotName) { |
|
7419 input = InpUnknown; |
|
7420 } else { |
|
7421 input = InpNameCh; |
|
7422 } |
|
7423 state = table[state][input]; |
|
7424 |
|
7425 switch (state) { |
|
7426 case NameF: |
|
7427 nameClear(); |
|
7428 nameAddC(); |
|
7429 next(); |
|
7430 break; |
|
7431 case Name: |
|
7432 nameAddC(); |
|
7433 next(); |
|
7434 break; |
|
7435 } |
|
7436 } |
|
7437 return false; |
|
7438 } |
|
7439 |
|
7440 /* |
|
7441 Parse a Reference [67]. |
|
7442 |
|
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. |
|
7446 |
|
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). |
|
7450 */ |
|
7451 bool QXmlSimpleReaderPrivate::parseReference() |
|
7452 { |
|
7453 // temporary variables (only used in very local context, so they don't |
|
7454 // interfere with incremental parsing) |
|
7455 uint tmp; |
|
7456 bool ok; |
|
7457 |
|
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 |
|
7468 |
|
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; |
|
7476 |
|
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 |
|
7486 }; |
|
7487 signed char state; |
|
7488 signed char input; |
|
7489 |
|
7490 if (parseStack==0 || parseStack->isEmpty()) { |
|
7491 parseReference_charDataRead = false; |
|
7492 state = Init; |
|
7493 } else { |
|
7494 state = parseStack->pop().state; |
|
7495 #if defined(QT_QXML_DEBUG) |
|
7496 qDebug("QXmlSimpleReader: parseReference (cont) in state %d", state); |
|
7497 #endif |
|
7498 if (!parseStack->isEmpty()) { |
|
7499 ParseFunction function = parseStack->top().function; |
|
7500 if (function == &QXmlSimpleReaderPrivate::eat_ws) { |
|
7501 parseStack->pop(); |
|
7502 #if defined(QT_QXML_DEBUG) |
|
7503 qDebug("QXmlSimpleReader: eat_ws (cont)"); |
|
7504 #endif |
|
7505 } |
|
7506 if (!(this->*function)()) { |
|
7507 parseFailed(&QXmlSimpleReaderPrivate::parseReference, state); |
|
7508 return false; |
|
7509 } |
|
7510 } |
|
7511 } |
|
7512 |
|
7513 for (;;) { |
|
7514 switch (state) { |
|
7515 case DoneD: |
|
7516 return true; |
|
7517 case DoneH: |
|
7518 return true; |
|
7519 case DoneN: |
|
7520 return true; |
|
7521 case -1: |
|
7522 // Error |
|
7523 reportParseError(QLatin1String(XMLERR_ERRORPARSINGREFERENCE)); |
|
7524 return false; |
|
7525 } |
|
7526 |
|
7527 if (atEnd()) { |
|
7528 unexpectedEof(&QXmlSimpleReaderPrivate::parseReference, state); |
|
7529 return false; |
|
7530 } |
|
7531 if (c.row()) { |
|
7532 input = InpUnknown; |
|
7533 } else if (c.cell() == '&') { |
|
7534 input = InpAmp; |
|
7535 } else if (c.cell() == ';') { |
|
7536 input = InpSemi; |
|
7537 } else if (c.cell() == '#') { |
|
7538 input = InpHash; |
|
7539 } else if (c.cell() == 'x') { |
|
7540 input = InpX; |
|
7541 } else if ('0' <= c.cell() && c.cell() <= '9') { |
|
7542 input = InpNum; |
|
7543 } else if ('a' <= c.cell() && c.cell() <= 'f') { |
|
7544 input = InpHex; |
|
7545 } else if ('A' <= c.cell() && c.cell() <= 'F') { |
|
7546 input = InpHex; |
|
7547 } else { |
|
7548 input = InpUnknown; |
|
7549 } |
|
7550 state = table[state][input]; |
|
7551 |
|
7552 switch (state) { |
|
7553 case SRef: |
|
7554 refClear(); |
|
7555 next(); |
|
7556 break; |
|
7557 case ChRef: |
|
7558 next(); |
|
7559 break; |
|
7560 case ChDec: |
|
7561 refAddC(); |
|
7562 next(); |
|
7563 break; |
|
7564 case ChHexS: |
|
7565 next(); |
|
7566 break; |
|
7567 case ChHex: |
|
7568 refAddC(); |
|
7569 next(); |
|
7570 break; |
|
7571 case Name: |
|
7572 // read the name into the ref |
|
7573 parseName_useRef = true; |
|
7574 if (!parseName()) { |
|
7575 parseFailed(&QXmlSimpleReaderPrivate::parseReference, state); |
|
7576 return false; |
|
7577 } |
|
7578 break; |
|
7579 case DoneD: |
|
7580 tmp = ref().toUInt(&ok, 10); |
|
7581 if (ok) { |
|
7582 stringAddC(QChar(tmp)); |
|
7583 } else { |
|
7584 reportParseError(QLatin1String(XMLERR_ERRORPARSINGREFERENCE)); |
|
7585 return false; |
|
7586 } |
|
7587 parseReference_charDataRead = true; |
|
7588 next(); |
|
7589 break; |
|
7590 case DoneH: |
|
7591 tmp = ref().toUInt(&ok, 16); |
|
7592 if (ok) { |
|
7593 stringAddC(QChar(tmp)); |
|
7594 } else { |
|
7595 reportParseError(QLatin1String(XMLERR_ERRORPARSINGREFERENCE)); |
|
7596 return false; |
|
7597 } |
|
7598 parseReference_charDataRead = true; |
|
7599 next(); |
|
7600 break; |
|
7601 case DoneN: |
|
7602 if (!processReference()) |
|
7603 return false; |
|
7604 next(); |
|
7605 break; |
|
7606 } |
|
7607 } |
|
7608 return false; |
|
7609 } |
|
7610 |
|
7611 /* |
|
7612 Helper function for parseReference() |
|
7613 */ |
|
7614 bool QXmlSimpleReaderPrivate::processReference() |
|
7615 { |
|
7616 QString reference = ref(); |
|
7617 if (reference == QLatin1String("amp")) { |
|
7618 if (parseReference_context == InEntityValue) { |
|
7619 // Bypassed |
|
7620 stringAddC(QLatin1Char('&')); stringAddC(QLatin1Char('a')); stringAddC(QLatin1Char('m')); stringAddC(QLatin1Char('p')); stringAddC(QLatin1Char(';')); |
|
7621 } else { |
|
7622 // Included or Included in literal |
|
7623 stringAddC(QLatin1Char('&')); |
|
7624 } |
|
7625 parseReference_charDataRead = true; |
|
7626 } else if (reference == QLatin1String("lt")) { |
|
7627 if (parseReference_context == InEntityValue) { |
|
7628 // Bypassed |
|
7629 stringAddC(QLatin1Char('&')); stringAddC(QLatin1Char('l')); stringAddC(QLatin1Char('t')); stringAddC(QLatin1Char(';')); |
|
7630 } else { |
|
7631 // Included or Included in literal |
|
7632 stringAddC(QLatin1Char('<')); |
|
7633 } |
|
7634 parseReference_charDataRead = true; |
|
7635 } else if (reference == QLatin1String("gt")) { |
|
7636 if (parseReference_context == InEntityValue) { |
|
7637 // Bypassed |
|
7638 stringAddC(QLatin1Char('&')); stringAddC(QLatin1Char('g')); stringAddC(QLatin1Char('t')); stringAddC(QLatin1Char(';')); |
|
7639 } else { |
|
7640 // Included or Included in literal |
|
7641 stringAddC(QLatin1Char('>')); |
|
7642 } |
|
7643 parseReference_charDataRead = true; |
|
7644 } else if (reference == QLatin1String("apos")) { |
|
7645 if (parseReference_context == InEntityValue) { |
|
7646 // Bypassed |
|
7647 stringAddC(QLatin1Char('&')); stringAddC(QLatin1Char('a')); stringAddC(QLatin1Char('p')); stringAddC(QLatin1Char('o')); stringAddC(QLatin1Char('s')); stringAddC(QLatin1Char(';')); |
|
7648 } else { |
|
7649 // Included or Included in literal |
|
7650 stringAddC(QLatin1Char('\'')); |
|
7651 } |
|
7652 parseReference_charDataRead = true; |
|
7653 } else if (reference == QLatin1String("quot")) { |
|
7654 if (parseReference_context == InEntityValue) { |
|
7655 // Bypassed |
|
7656 stringAddC(QLatin1Char('&')); stringAddC(QLatin1Char('q')); stringAddC(QLatin1Char('u')); stringAddC(QLatin1Char('o')); stringAddC(QLatin1Char('t')); stringAddC(QLatin1Char(';')); |
|
7657 } else { |
|
7658 // Included or Included in literal |
|
7659 stringAddC(QLatin1Char('"')); |
|
7660 } |
|
7661 parseReference_charDataRead = true; |
|
7662 } else { |
|
7663 QMap<QString,QString>::Iterator it; |
|
7664 it = entities.find(reference); |
|
7665 if (it != entities.end()) { |
|
7666 // "Internal General" |
|
7667 switch (parseReference_context) { |
|
7668 case InContent: |
|
7669 // Included |
|
7670 if (!insertXmlRef(*it, reference, false)) |
|
7671 return false; |
|
7672 parseReference_charDataRead = false; |
|
7673 break; |
|
7674 case InAttributeValue: |
|
7675 // Included in literal |
|
7676 if (!insertXmlRef(*it, reference, true)) |
|
7677 return false; |
|
7678 parseReference_charDataRead = false; |
|
7679 break; |
|
7680 case InEntityValue: |
|
7681 { |
|
7682 // Bypassed |
|
7683 stringAddC(QLatin1Char('&')); |
|
7684 for (int i=0; i<(int)reference.length(); i++) { |
|
7685 stringAddC(reference[i]); |
|
7686 } |
|
7687 stringAddC(QLatin1Char(';')); |
|
7688 parseReference_charDataRead = true; |
|
7689 } |
|
7690 break; |
|
7691 case InDTD: |
|
7692 // Forbidden |
|
7693 parseReference_charDataRead = false; |
|
7694 reportParseError(QLatin1String(XMLERR_INTERNALGENERALENTITYINDTD)); |
|
7695 return false; |
|
7696 } |
|
7697 } else { |
|
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) { |
|
7704 // Bypassed |
|
7705 stringAddC(QLatin1Char('&')); |
|
7706 for (int i=0; i<(int)reference.length(); i++) { |
|
7707 stringAddC(reference[i]); |
|
7708 } |
|
7709 stringAddC(QLatin1Char(';')); |
|
7710 parseReference_charDataRead = true; |
|
7711 } else { |
|
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()); |
|
7718 return false; |
|
7719 } |
|
7720 } |
|
7721 stringClear(); |
|
7722 contentCharDataRead = false; |
|
7723 } |
|
7724 } |
|
7725 |
|
7726 if (contentHnd) { |
|
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 |
|
7732 } |
|
7733 qt_xml_skipped_entity_in_content = false; |
|
7734 } |
|
7735 } |
|
7736 } else if ((*itExtern).notation.isNull()) { |
|
7737 // "External Parsed General" |
|
7738 switch (parseReference_context) { |
|
7739 case InContent: |
|
7740 { |
|
7741 // Included if validating |
|
7742 bool skipIt = true; |
|
7743 if (entityRes) { |
|
7744 QXmlInputSource *ret = 0; |
|
7745 if (!entityRes->resolveEntity((*itExtern).publicId, (*itExtern).systemId, ret)) { |
|
7746 delete ret; |
|
7747 reportParseError(entityRes->errorString()); |
|
7748 return false; |
|
7749 } |
|
7750 if (ret) { |
|
7751 QString xmlRefString = ret->data(); |
|
7752 delete ret; |
|
7753 if (!stripTextDecl(xmlRefString)) { |
|
7754 reportParseError(QLatin1String(XMLERR_ERRORINTEXTDECL)); |
|
7755 return false; |
|
7756 } |
|
7757 if (!insertXmlRef(xmlRefString, reference, false)) |
|
7758 return false; |
|
7759 skipIt = false; |
|
7760 } |
|
7761 } |
|
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 |
|
7768 } |
|
7769 qt_xml_skipped_entity_in_content = false; |
|
7770 } |
|
7771 parseReference_charDataRead = false; |
|
7772 } break; |
|
7773 case InAttributeValue: |
|
7774 // Forbidden |
|
7775 parseReference_charDataRead = false; |
|
7776 reportParseError(QLatin1String(XMLERR_EXTERNALGENERALENTITYINAV)); |
|
7777 return false; |
|
7778 case InEntityValue: |
|
7779 { |
|
7780 // Bypassed |
|
7781 stringAddC(QLatin1Char('&')); |
|
7782 for (int i=0; i<(int)reference.length(); i++) { |
|
7783 stringAddC(reference[i]); |
|
7784 } |
|
7785 stringAddC(QLatin1Char(';')); |
|
7786 parseReference_charDataRead = true; |
|
7787 } |
|
7788 break; |
|
7789 case InDTD: |
|
7790 // Forbidden |
|
7791 parseReference_charDataRead = false; |
|
7792 reportParseError(QLatin1String(XMLERR_EXTERNALGENERALENTITYINDTD)); |
|
7793 return false; |
|
7794 } |
|
7795 } else { |
|
7796 // "Unparsed" |
|
7797 // ### notify for "Occurs as Attribute Value" missing (but this is no refence, anyway) |
|
7798 // Forbidden |
|
7799 parseReference_charDataRead = false; |
|
7800 reportParseError(QLatin1String(XMLERR_UNPARSEDENTITYREFERENCE)); |
|
7801 return false; // error |
|
7802 } |
|
7803 } |
|
7804 } |
|
7805 return true; // no error |
|
7806 } |
|
7807 |
|
7808 |
|
7809 /* |
|
7810 Parses over a simple string. |
|
7811 |
|
7812 After the string was successfully parsed, the head is on the first |
|
7813 character after the string. |
|
7814 */ |
|
7815 bool QXmlSimpleReaderPrivate::parseString() |
|
7816 { |
|
7817 const signed char InpCharExpected = 0; // the character that was expected |
|
7818 const signed char InpUnknown = 1; |
|
7819 |
|
7820 signed char state; // state in this function is the position in the string s |
|
7821 signed char input; |
|
7822 |
|
7823 if (parseStack==0 || parseStack->isEmpty()) { |
|
7824 Done = parseString_s.length(); |
|
7825 state = 0; |
|
7826 } else { |
|
7827 state = parseStack->pop().state; |
|
7828 #if defined(QT_QXML_DEBUG) |
|
7829 qDebug("QXmlSimpleReader: parseString (cont) in state %d", state); |
|
7830 #endif |
|
7831 if (!parseStack->isEmpty()) { |
|
7832 ParseFunction function = parseStack->top().function; |
|
7833 if (function == &QXmlSimpleReaderPrivate::eat_ws) { |
|
7834 parseStack->pop(); |
|
7835 #if defined(QT_QXML_DEBUG) |
|
7836 qDebug("QXmlSimpleReader: eat_ws (cont)"); |
|
7837 #endif |
|
7838 } |
|
7839 if (!(this->*function)()) { |
|
7840 parseFailed(&QXmlSimpleReaderPrivate::parseString, state); |
|
7841 return false; |
|
7842 } |
|
7843 } |
|
7844 } |
|
7845 |
|
7846 for (;;) { |
|
7847 if (state == Done) { |
|
7848 return true; |
|
7849 } |
|
7850 |
|
7851 if (atEnd()) { |
|
7852 unexpectedEof(&QXmlSimpleReaderPrivate::parseString, state); |
|
7853 return false; |
|
7854 } |
|
7855 if (c == parseString_s[(int)state]) { |
|
7856 input = InpCharExpected; |
|
7857 } else { |
|
7858 input = InpUnknown; |
|
7859 } |
|
7860 if (input == InpCharExpected) { |
|
7861 state++; |
|
7862 } else { |
|
7863 // Error |
|
7864 reportParseError(QLatin1String(XMLERR_UNEXPECTEDCHARACTER)); |
|
7865 return false; |
|
7866 } |
|
7867 |
|
7868 next(); |
|
7869 } |
|
7870 return false; |
|
7871 } |
|
7872 |
|
7873 /* |
|
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. |
|
7878 |
|
7879 This function returns false on error. |
|
7880 */ |
|
7881 bool QXmlSimpleReaderPrivate::insertXmlRef(const QString &data, const QString &name, bool inLiteral) |
|
7882 { |
|
7883 if (inLiteral) { |
|
7884 QString tmp = data; |
|
7885 xmlRefStack.push(XmlRef(name, tmp.replace(QLatin1Char('\"'), |
|
7886 QLatin1String(""")).replace(QLatin1Char('\''), QLatin1String("'")))); |
|
7887 } else { |
|
7888 xmlRefStack.push(XmlRef(name, data)); |
|
7889 } |
|
7890 int n = qMax(parameterEntities.count(), entities.count()); |
|
7891 if (xmlRefStack.count() > n+1) { |
|
7892 // recursive entities |
|
7893 reportParseError(QLatin1String(XMLERR_RECURSIVEENTITIES)); |
|
7894 return false; |
|
7895 } |
|
7896 if (reportEntities && lexicalHnd) { |
|
7897 if (!lexicalHnd->startEntity(name)) { |
|
7898 reportParseError(lexicalHnd->errorString()); |
|
7899 return false; |
|
7900 } |
|
7901 } |
|
7902 return true; |
|
7903 } |
|
7904 |
|
7905 /* |
|
7906 This private function moves the cursor to the next character. |
|
7907 */ |
|
7908 void QXmlSimpleReaderPrivate::next() |
|
7909 { |
|
7910 int count = xmlRefStack.size(); |
|
7911 while (count != 0) { |
|
7912 if (xmlRefStack.top().isEmpty()) { |
|
7913 xmlRefStack.pop_back(); |
|
7914 count--; |
|
7915 } else { |
|
7916 c = xmlRefStack.top().next(); |
|
7917 return; |
|
7918 } |
|
7919 } |
|
7920 |
|
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(); |
|
7929 if (uc == '\n') { |
|
7930 lineNr++; |
|
7931 columnNr = -1; |
|
7932 } else if (uc == '\r') { |
|
7933 if (c != QLatin1Char('\n')) { |
|
7934 lineNr++; |
|
7935 columnNr = -1; |
|
7936 } |
|
7937 } |
|
7938 ++columnNr; |
|
7939 } |
|
7940 |
|
7941 /* |
|
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. |
|
7945 |
|
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 |
|
7949 true. |
|
7950 */ |
|
7951 bool QXmlSimpleReaderPrivate::eat_ws() |
|
7952 { |
|
7953 while (!atEnd()) { |
|
7954 if (!is_S(c)) { |
|
7955 return true; |
|
7956 } |
|
7957 next(); |
|
7958 } |
|
7959 if (parseStack != 0) { |
|
7960 unexpectedEof(&QXmlSimpleReaderPrivate::eat_ws, 0); |
|
7961 return false; |
|
7962 } |
|
7963 return true; |
|
7964 } |
|
7965 |
|
7966 bool QXmlSimpleReaderPrivate::next_eat_ws() |
|
7967 { |
|
7968 next(); |
|
7969 return eat_ws(); |
|
7970 } |
|
7971 |
|
7972 |
|
7973 /* |
|
7974 This private function initializes the reader. \a i is the input source to |
|
7975 read the data from. |
|
7976 */ |
|
7977 void QXmlSimpleReaderPrivate::init(const QXmlInputSource *i) |
|
7978 { |
|
7979 lineNr = 0; |
|
7980 columnNr = -1; |
|
7981 inputSource = const_cast<QXmlInputSource *>(i); |
|
7982 initData(); |
|
7983 |
|
7984 externParameterEntities.clear(); |
|
7985 parameterEntities.clear(); |
|
7986 externEntities.clear(); |
|
7987 entities.clear(); |
|
7988 |
|
7989 tags.clear(); |
|
7990 |
|
7991 doctype.clear(); |
|
7992 xmlVersion.clear(); |
|
7993 encoding.clear(); |
|
7994 standalone = QXmlSimpleReaderPrivate::Unknown; |
|
7995 error.clear(); |
|
7996 } |
|
7997 |
|
7998 /* |
|
7999 This private function initializes the XML data related variables. Especially, |
|
8000 it reads the data from the input source. |
|
8001 */ |
|
8002 void QXmlSimpleReaderPrivate::initData() |
|
8003 { |
|
8004 c = QXmlInputSource::EndOfData; |
|
8005 xmlRefStack.clear(); |
|
8006 next(); |
|
8007 } |
|
8008 |
|
8009 /* |
|
8010 Returns true if a entity with the name \a e exists, |
|
8011 otherwise returns false. |
|
8012 */ |
|
8013 bool QXmlSimpleReaderPrivate::entityExist(const QString& e) const |
|
8014 { |
|
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()) { |
|
8019 return false; |
|
8020 } else { |
|
8021 return true; |
|
8022 } |
|
8023 } |
|
8024 |
|
8025 void QXmlSimpleReaderPrivate::reportParseError(const QString& error) |
|
8026 { |
|
8027 this->error = error; |
|
8028 if (errorHnd) { |
|
8029 if (this->error.isNull()) { |
|
8030 const QXmlParseException ex(QLatin1String(XMLERR_OK), columnNr+1, lineNr+1, |
|
8031 thisPublicId, thisSystemId); |
|
8032 errorHnd->fatalError(ex); |
|
8033 } else { |
|
8034 const QXmlParseException ex(this->error, columnNr+1, lineNr+1, |
|
8035 thisPublicId, thisSystemId); |
|
8036 errorHnd->fatalError(ex); |
|
8037 } |
|
8038 } |
|
8039 } |
|
8040 |
|
8041 /* |
|
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. |
|
8046 */ |
|
8047 void QXmlSimpleReaderPrivate::unexpectedEof(ParseFunction where, int state) |
|
8048 { |
|
8049 if (parseStack == 0) { |
|
8050 reportParseError(QLatin1String(XMLERR_UNEXPECTEDEOF)); |
|
8051 } else { |
|
8052 if (c == QXmlInputSource::EndOfDocument) { |
|
8053 reportParseError(QLatin1String(XMLERR_UNEXPECTEDEOF)); |
|
8054 } else { |
|
8055 pushParseState(where, state); |
|
8056 } |
|
8057 } |
|
8058 } |
|
8059 |
|
8060 /* |
|
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 |
|
8065 function. |
|
8066 */ |
|
8067 void QXmlSimpleReaderPrivate::parseFailed(ParseFunction where, int state) |
|
8068 { |
|
8069 if (parseStack!=0 && error.isNull()) { |
|
8070 pushParseState(where, state); |
|
8071 } |
|
8072 } |
|
8073 |
|
8074 /* |
|
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. |
|
8078 |
|
8079 Only call this function when d->parseStack!=0. |
|
8080 */ |
|
8081 void QXmlSimpleReaderPrivate::pushParseState(ParseFunction function, int state) |
|
8082 { |
|
8083 QXmlSimpleReaderPrivate::ParseState ps; |
|
8084 ps.function = function; |
|
8085 ps.state = state; |
|
8086 parseStack->push(ps); |
|
8087 } |
|
8088 |
|
8089 inline static void updateValue(QString &value, const QChar *array, int &arrayPos, int &valueLen) |
|
8090 { |
|
8091 value.resize(valueLen + arrayPos); |
|
8092 memcpy(value.data() + valueLen, array, arrayPos * sizeof(QChar)); |
|
8093 valueLen += arrayPos; |
|
8094 arrayPos = 0; |
|
8095 } |
|
8096 |
|
8097 // use buffers instead of QString::operator+= when single characters are read |
|
8098 const QString& QXmlSimpleReaderPrivate::string() |
|
8099 { |
|
8100 updateValue(stringValue, stringArray, stringArrayPos, stringValueLen); |
|
8101 return stringValue; |
|
8102 } |
|
8103 const QString& QXmlSimpleReaderPrivate::name() |
|
8104 { |
|
8105 updateValue(nameValue, nameArray, nameArrayPos, nameValueLen); |
|
8106 return nameValue; |
|
8107 } |
|
8108 const QString& QXmlSimpleReaderPrivate::ref() |
|
8109 { |
|
8110 updateValue(refValue, refArray, refArrayPos, refValueLen); |
|
8111 return refValue; |
|
8112 } |
|
8113 |
|
8114 void QXmlSimpleReaderPrivate::stringAddC(QChar ch) |
|
8115 { |
|
8116 if (stringArrayPos == 256) |
|
8117 updateValue(stringValue, stringArray, stringArrayPos, stringValueLen); |
|
8118 stringArray[stringArrayPos++] = ch; |
|
8119 } |
|
8120 void QXmlSimpleReaderPrivate::nameAddC(QChar ch) |
|
8121 { |
|
8122 if (nameArrayPos == 256) |
|
8123 updateValue(nameValue, nameArray, nameArrayPos, nameValueLen); |
|
8124 nameArray[nameArrayPos++] = ch; |
|
8125 } |
|
8126 void QXmlSimpleReaderPrivate::refAddC(QChar ch) |
|
8127 { |
|
8128 if (refArrayPos == 256) |
|
8129 updateValue(refValue, refArray, refArrayPos, refValueLen); |
|
8130 refArray[refArrayPos++] = ch; |
|
8131 } |
|
8132 QT_END_NAMESPACE |