author | ulf69 <ulf69> | 2004-09-15 17:43:49 (UTC) |
---|---|---|
committer | ulf69 <ulf69> | 2004-09-15 17:43:49 (UTC) |
commit | 2f7550f49c97557fe48c66876a45f6331d112478 (patch) (unidiff) | |
tree | 285774b0767bb927c98998a0175511a3bdbc4622 /qtcompat/xml/qxml.cpp | |
parent | bf92dc9597ae82fbdec3667f011e38aeee941cce (diff) | |
download | kdepimpi-2f7550f49c97557fe48c66876a45f6331d112478.zip kdepimpi-2f7550f49c97557fe48c66876a45f6331d112478.tar.gz kdepimpi-2f7550f49c97557fe48c66876a45f6331d112478.tar.bz2 |
initial version
-rw-r--r-- | qtcompat/xml/qxml.cpp | 6087 |
1 files changed, 6087 insertions, 0 deletions
diff --git a/qtcompat/xml/qxml.cpp b/qtcompat/xml/qxml.cpp new file mode 100644 index 0000000..e65bc59 --- a/dev/null +++ b/qtcompat/xml/qxml.cpp | |||
@@ -0,0 +1,6087 @@ | |||
1 | /**************************************************************************** | ||
2 | ** $Id$ | ||
3 | ** | ||
4 | ** Implementation of QXmlSimpleReader and related classes. | ||
5 | ** | ||
6 | ** Created : 000518 | ||
7 | ** | ||
8 | ** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. | ||
9 | ** | ||
10 | ** This file is part of the XML module of the Qt GUI Toolkit. | ||
11 | ** | ||
12 | ** This file may be distributed under the terms of the Q Public License | ||
13 | ** as defined by Trolltech AS of Norway and appearing in the file | ||
14 | ** LICENSE.QPL included in the packaging of this file. | ||
15 | ** | ||
16 | ** This file may be distributed and/or modified under the terms of the | ||
17 | ** GNU General Public License version 2 as published by the Free Software | ||
18 | ** Foundation and appearing in the file LICENSE.GPL included in the | ||
19 | ** packaging of this file. | ||
20 | ** | ||
21 | ** Licensees holding valid Qt Enterprise Edition licenses may use this | ||
22 | ** file in accordance with the Qt Commercial License Agreement provided | ||
23 | ** with the Software. | ||
24 | ** | ||
25 | ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE | ||
26 | ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. | ||
27 | ** | ||
28 | ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for | ||
29 | ** information about Qt Commercial License Agreements. | ||
30 | ** See http://www.trolltech.com/qpl/ for QPL licensing information. | ||
31 | ** See http://www.trolltech.com/gpl/ for GPL licensing information. | ||
32 | ** | ||
33 | ** Contact info@trolltech.com if any conditions of this licensing are | ||
34 | ** not clear to you. | ||
35 | ** | ||
36 | **********************************************************************/ | ||
37 | |||
38 | |||
39 | /****************************************** | ||
40 | * DOM support is disabled in QT 2.3.7 for sharp zaurus. | ||
41 | * Because of that we copied the code from 2.3.7 into qtcompat and enabled it | ||
42 | * there. | ||
43 | * Copyright (c) 2004 Ulf Schenk | ||
44 | * | ||
45 | * $Id$ | ||
46 | ******************************************/ | ||
47 | |||
48 | #define QT_XML_CPP | ||
49 | #include "qxml.h" | ||
50 | #include "qtextcodec.h" | ||
51 | #include "qbuffer.h" | ||
52 | |||
53 | //US #ifndef QT_NO_XML | ||
54 | // NOT REVISED | ||
55 | |||
56 | // Error strings for the XML reader | ||
57 | #define XMLERR_OK "no error occured" | ||
58 | #define XMLERR_TAGMISMATCH "tag mismatch" | ||
59 | #define XMLERR_UNEXPECTEDEOF "unexpected end of file" | ||
60 | #define XMLERR_FINISHEDPARSINGWHILENOTEOF "parsing is finished but end of file is not reached" | ||
61 | #define XMLERR_LETTEREXPECTED "letter is expected" | ||
62 | #define XMLERR_ERRORPARSINGELEMENT "error while parsing element" | ||
63 | #define XMLERR_ERRORPARSINGPROLOG "error while parsing prolog" | ||
64 | #define XMLERR_ERRORPARSINGMAINELEMENT "error while parsing main element" | ||
65 | #define XMLERR_ERRORPARSINGCONTENT "error while parsing content" | ||
66 | #define XMLERR_ERRORPARSINGNAME "error while parsing name" | ||
67 | #define XMLERR_ERRORPARSINGNMTOKEN "error while parsing Nmtoken" | ||
68 | #define XMLERR_ERRORPARSINGATTRIBUTE "error while parsing attribute" | ||
69 | #define XMLERR_ERRORPARSINGMISC "error while parsing misc" | ||
70 | #define XMLERR_ERRORPARSINGCHOICE "error while parsing choice or seq" | ||
71 | #define XMLERR_ERRORBYCONSUMER "error triggered by consumer" | ||
72 | #define XMLERR_UNEXPECTEDCHARACTER "unexpected character" | ||
73 | #define XMLERR_EQUALSIGNEXPECTED "expected '=' but not found" | ||
74 | #define XMLERR_QUOTATIONEXPECTED "expected \" or ' but not found" | ||
75 | #define XMLERR_ERRORPARSINGREFERENCE "error while parsing reference" | ||
76 | #define XMLERR_ERRORPARSINGPI "error while parsing processing instruction" | ||
77 | #define XMLERR_ERRORPARSINGATTLISTDECL "error while parsing attribute list declaration" | ||
78 | #define XMLERR_ERRORPARSINGATTTYPE "error while parsing attribute type declaration" | ||
79 | #define XMLERR_ERRORPARSINGATTVALUE "error while parsing attribute value declaration" | ||
80 | #define XMLERR_ERRORPARSINGELEMENTDECL "error while parsing element declaration" | ||
81 | #define XMLERR_ERRORPARSINGENTITYDECL "error while parsing entity declaration" | ||
82 | #define XMLERR_ERRORPARSINGNOTATIONDECL "error while parsing notation declaration" | ||
83 | #define XMLERR_ERRORPARSINGEXTERNALID "error while parsing external id" | ||
84 | #define XMLERR_ERRORPARSINGCOMMENT "error while parsing comment" | ||
85 | #define XMLERR_ERRORPARSINGENTITYVALUE "error while parsing entity value declaration" | ||
86 | #define XMLERR_CDSECTHEADEREXPECTED "expected the header for a cdata section" | ||
87 | #define XMLERR_MORETHANONEDOCTYPE "more than one document type definition" | ||
88 | #define XMLERR_ERRORPARSINGDOCTYPE "error while parsing document type definition" | ||
89 | #define XMLERR_INVALIDNAMEFORPI "invalid name for processing instruction" | ||
90 | #define XMLERR_VERSIONEXPECTED "version expected while reading the XML declaration" | ||
91 | #define XMLERR_EDECLORSDDECLEXPECTED "EDecl or SDDecl expected while reading the XML declaration" | ||
92 | #define XMLERR_SDDECLEXPECTED "SDDecl expected while reading the XML declaration" | ||
93 | #define XMLERR_WRONGVALUEFORSDECL "wrong value for standalone declaration" | ||
94 | #define XMLERR_UNPARSEDENTITYREFERENCE "unparsed entity reference in wrong context" | ||
95 | #define XMLERR_INTERNALGENERALENTITYINDTD "internal general entity reference not allowed in DTD" | ||
96 | #define XMLERR_EXTERNALGENERALENTITYINDTD "external parsed general entity reference not allowed in DTD" | ||
97 | #define XMLERR_EXTERNALGENERALENTITYINAV "external parsed general entity reference not allowed in attribute value" | ||
98 | |||
99 | |||
100 | // the constants for the lookup table | ||
101 | static const signed char cltWS = 0; // white space | ||
102 | static const signed char cltPer = 1; // % | ||
103 | static const signed char cltAmp = 2; // & | ||
104 | static const signed char cltGt = 3; // > | ||
105 | static const signed char cltLt = 4; // < | ||
106 | static const signed char cltSlash = 5; // / | ||
107 | static const signed char cltQm = 6; // ? | ||
108 | static const signed char cltEm = 7; // ! | ||
109 | static const signed char cltDash = 8; // - | ||
110 | static const signed char cltCB = 9; // ] | ||
111 | static const signed char cltOB = 10; // [ | ||
112 | static const signed char cltEq = 11; // = | ||
113 | static const signed char cltDq = 12; // " | ||
114 | static const signed char cltSq = 13; // ' | ||
115 | static const signed char cltUnknown = 14; | ||
116 | |||
117 | // character lookup table | ||
118 | static const signed char charLookupTable[256]={ | ||
119 | cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x00 - 0x07 | ||
120 | cltUnknown, // 0x08 | ||
121 | cltWS, // 0x09 \t | ||
122 | cltWS, // 0x0A \n | ||
123 | cltUnknown, // 0x0B | ||
124 | cltUnknown, // 0x0C | ||
125 | cltWS, // 0x0D \r | ||
126 | cltUnknown, // 0x0E | ||
127 | cltUnknown, // 0x0F | ||
128 | cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x17 - 0x16 | ||
129 | cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x18 - 0x1F | ||
130 | cltWS, // 0x20 Space | ||
131 | cltEm, // 0x21 ! | ||
132 | cltDq, // 0x22 " | ||
133 | cltUnknown, // 0x23 | ||
134 | cltUnknown, // 0x24 | ||
135 | cltPer, // 0x25 % | ||
136 | cltAmp, // 0x26 & | ||
137 | cltSq, // 0x27 ' | ||
138 | cltUnknown, // 0x28 | ||
139 | cltUnknown, // 0x29 | ||
140 | cltUnknown, // 0x2A | ||
141 | cltUnknown, // 0x2B | ||
142 | cltUnknown, // 0x2C | ||
143 | cltDash, // 0x2D - | ||
144 | cltUnknown, // 0x2E | ||
145 | cltSlash, // 0x2F / | ||
146 | cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x30 - 0x37 | ||
147 | cltUnknown, // 0x38 | ||
148 | cltUnknown, // 0x39 | ||
149 | cltUnknown, // 0x3A | ||
150 | cltUnknown, // 0x3B | ||
151 | cltLt, // 0x3C < | ||
152 | cltEq, // 0x3D = | ||
153 | cltGt, // 0x3E > | ||
154 | cltQm, // 0x3F ? | ||
155 | cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x40 - 0x47 | ||
156 | cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x48 - 0x4F | ||
157 | cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x50 - 0x57 | ||
158 | cltUnknown, // 0x58 | ||
159 | cltUnknown, // 0x59 | ||
160 | cltUnknown, // 0x5A | ||
161 | cltOB, // 0x5B [ | ||
162 | cltUnknown, // 0x5C | ||
163 | cltCB, // 0x5D ] | ||
164 | cltUnknown, // 0x5E | ||
165 | cltUnknown, // 0x5F | ||
166 | cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x60 - 0x67 | ||
167 | cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x68 - 0x6F | ||
168 | cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x70 - 0x77 | ||
169 | cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x78 - 0x7F | ||
170 | cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x80 - 0x87 | ||
171 | cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x88 - 0x8F | ||
172 | cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x90 - 0x97 | ||
173 | cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x98 - 0x9F | ||
174 | cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xA0 - 0xA7 | ||
175 | cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xA8 - 0xAF | ||
176 | cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xB0 - 0xB7 | ||
177 | cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xB8 - 0xBF | ||
178 | cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xC0 - 0xC7 | ||
179 | cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xC8 - 0xCF | ||
180 | cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xD0 - 0xD7 | ||
181 | cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xD8 - 0xDF | ||
182 | cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xE0 - 0xE7 | ||
183 | cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xE8 - 0xEF | ||
184 | cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xF0 - 0xF7 | ||
185 | cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown // 0xF8 - 0xFF | ||
186 | }; | ||
187 | |||
188 | |||
189 | class QXmlNamespaceSupportPrivate | ||
190 | { | ||
191 | }; | ||
192 | class QXmlAttributesPrivate | ||
193 | { | ||
194 | }; | ||
195 | class QXmlInputSourcePrivate | ||
196 | { | ||
197 | }; | ||
198 | class QXmlParseExceptionPrivate | ||
199 | { | ||
200 | }; | ||
201 | class QXmlLocatorPrivate | ||
202 | { | ||
203 | }; | ||
204 | class QXmlDefaultHandlerPrivate | ||
205 | { | ||
206 | }; | ||
207 | |||
208 | #if defined(Q_FULL_TEMPLATE_INSTANTIATION) | ||
209 | bool operator==( const QMap<QString, QString>, const QMap<QString, QString> ) | ||
210 | { | ||
211 | return FALSE; | ||
212 | } | ||
213 | #endif | ||
214 | |||
215 | /*! | ||
216 | \class QXmlParseException qxml.h | ||
217 | \brief The QXmlParseException class is used to report errors with the | ||
218 | QXmlErrorHandler interface. | ||
219 | |||
220 | \module XML | ||
221 | |||
222 | \sa QXmlErrorHandler | ||
223 | */ | ||
224 | /*! | ||
225 | \fn QXmlParseException::QXmlParseException( const QString& name, int c, int l, const QString& p, const QString& s ) | ||
226 | |||
227 | Constructs a parse exception with the error string \a name in the column | ||
228 | \a c and line \a l for the public identifier \a p and the system identifier | ||
229 | \a s. | ||
230 | */ | ||
231 | /*! | ||
232 | Returns the error message. | ||
233 | */ | ||
234 | QString QXmlParseException::message() const | ||
235 | { | ||
236 | return msg; | ||
237 | } | ||
238 | /*! | ||
239 | Returns the column number the error occured. | ||
240 | */ | ||
241 | int QXmlParseException::columnNumber() const | ||
242 | { | ||
243 | return column; | ||
244 | } | ||
245 | /*! | ||
246 | Returns the line number the error occured. | ||
247 | */ | ||
248 | int QXmlParseException::lineNumber() const | ||
249 | { | ||
250 | return line; | ||
251 | } | ||
252 | /*! | ||
253 | Returns the public identifier the error occured. | ||
254 | */ | ||
255 | QString QXmlParseException::publicId() const | ||
256 | { | ||
257 | return pub; | ||
258 | } | ||
259 | /*! | ||
260 | Returns the system identifier the error occured. | ||
261 | */ | ||
262 | QString QXmlParseException::systemId() const | ||
263 | { | ||
264 | return sys; | ||
265 | } | ||
266 | |||
267 | |||
268 | /*! | ||
269 | \class QXmlLocator qxml.h | ||
270 | \brief The QXmlLocator class provides the XML handler classes with | ||
271 | information about the actual parsing position. | ||
272 | |||
273 | \module XML | ||
274 | |||
275 | The reader reports a QXmlLocator to the content handler before he starts to | ||
276 | parse the document. This is done with the | ||
277 | QXmlContentHandler::setDocumentLocator() function. The handler classes can | ||
278 | now use this locator to get the actual position the reader is at. | ||
279 | */ | ||
280 | /*! | ||
281 | \fn QXmlLocator::QXmlLocator( QXmlSimpleReader* parent ) | ||
282 | |||
283 | Constructor. | ||
284 | */ | ||
285 | /*! | ||
286 | \fn QXmlLocator::~QXmlLocator() | ||
287 | |||
288 | Destructor. | ||
289 | */ | ||
290 | /*! | ||
291 | Gets the column number (starting with 1) or -1 if there is no column number | ||
292 | available. | ||
293 | */ | ||
294 | int QXmlLocator::columnNumber() | ||
295 | { | ||
296 | return ( reader->columnNr == -1 ? -1 : reader->columnNr + 1 ); | ||
297 | } | ||
298 | /*! | ||
299 | Gets the line number (starting with 1) or -1 if there is no line number | ||
300 | available. | ||
301 | */ | ||
302 | int QXmlLocator::lineNumber() | ||
303 | { | ||
304 | return ( reader->lineNr == -1 ? -1 : reader->lineNr + 1 ); | ||
305 | } | ||
306 | |||
307 | |||
308 | /********************************************* | ||
309 | * | ||
310 | * QXmlNamespaceSupport | ||
311 | * | ||
312 | *********************************************/ | ||
313 | |||
314 | /*! | ||
315 | \class QXmlNamespaceSupport qxml.h | ||
316 | \brief The QXmlNamespaceSupport class is a helper class for XML readers which | ||
317 | want to include namespace support. | ||
318 | |||
319 | \module XML | ||
320 | |||
321 | It provides some functions that makes it easy to handle namespaces. Its main | ||
322 | use is for subclasses of QXmlReader which want to provide namespace | ||
323 | support. | ||
324 | |||
325 | See also the <a href="xml-sax.html#namespaces">namespace description</a>. | ||
326 | */ | ||
327 | |||
328 | /*! | ||
329 | Constructs a QXmlNamespaceSupport. | ||
330 | */ | ||
331 | QXmlNamespaceSupport::QXmlNamespaceSupport() | ||
332 | { | ||
333 | reset(); | ||
334 | } | ||
335 | |||
336 | /*! | ||
337 | Destructs a QXmlNamespaceSupport. | ||
338 | */ | ||
339 | QXmlNamespaceSupport::~QXmlNamespaceSupport() | ||
340 | { | ||
341 | } | ||
342 | |||
343 | /*! | ||
344 | This function declares a prefix in the current namespace context; the prefix | ||
345 | will remain in force until this context is popped, unless it is shadowed in a | ||
346 | descendant context. | ||
347 | |||
348 | Note that there is an asymmetry in this library: while prefix() will not | ||
349 | return the default "" prefix, even if you have declared one; to check for a | ||
350 | default prefix, you have to look it up explicitly using uri(). This | ||
351 | asymmetry exists to make it easier to look up prefixes for attribute names, | ||
352 | where the default prefix is not allowed. | ||
353 | */ | ||
354 | void QXmlNamespaceSupport::setPrefix( const QString& pre, const QString& uri ) | ||
355 | { | ||
356 | if( pre.isNull() ) { | ||
357 | ns.insert( "", uri ); | ||
358 | } else { | ||
359 | ns.insert( pre, uri ); | ||
360 | } | ||
361 | } | ||
362 | |||
363 | /*! | ||
364 | Returns one of the prefixes mapped to a namespace URI. | ||
365 | |||
366 | If more than one prefix is currently mapped to the same URI, this function | ||
367 | will make an arbitrary selection; if you want all of the prefixes, use the | ||
368 | prefixes() function instead. | ||
369 | |||
370 | Note: this will never return the empty (default) prefix; to check for a | ||
371 | default prefix, use the uri() function with an argument of "". | ||
372 | */ | ||
373 | QString QXmlNamespaceSupport::prefix( const QString& uri ) const | ||
374 | { | ||
375 | QMap<QString, QString>::ConstIterator itc, it = ns.begin(); | ||
376 | while ( (itc=it) != ns.end() ) { | ||
377 | ++it; | ||
378 | if ( itc.data() == uri && !itc.key().isEmpty() ) | ||
379 | return itc.key(); | ||
380 | } | ||
381 | return ""; | ||
382 | } | ||
383 | |||
384 | /*! | ||
385 | Looks up a prefix in the current context and returns the currently-mapped | ||
386 | namespace URI. Use the empty string ("") for the default namespace. | ||
387 | */ | ||
388 | QString QXmlNamespaceSupport::uri( const QString& prefix ) const | ||
389 | { | ||
390 | const QString& returi = ns[ prefix ]; | ||
391 | return returi; | ||
392 | } | ||
393 | |||
394 | /*! | ||
395 | Splits the name at the ':' and returns the prefix and the local name. | ||
396 | */ | ||
397 | void QXmlNamespaceSupport::splitName( const QString& qname, | ||
398 | QString& prefix, QString& localname ) const | ||
399 | { | ||
400 | uint pos; | ||
401 | // search the ':' | ||
402 | for( pos=0; pos<qname.length(); pos++ ) { | ||
403 | if ( qname.at(pos) == ':' ) | ||
404 | break; | ||
405 | } | ||
406 | // and split | ||
407 | prefix = qname.left( pos ); | ||
408 | localname = qname.mid( pos+1 ); | ||
409 | } | ||
410 | |||
411 | /*! | ||
412 | Processes a raw XML 1.0 name in the current context by removing the prefix | ||
413 | and looking it up among the prefixes currently declared. | ||
414 | |||
415 | First parameter is the raw XML 1.0 name to be processed. The second parameter | ||
416 | is a flag wheter the name is the name of an attribute (TRUE) or not (FALSE). | ||
417 | |||
418 | The return values will be stored in the last two parameters as follows: | ||
419 | <ul> | ||
420 | <li> The namespace URI, or an empty string if none is in use. | ||
421 | <li> The local name (without prefix). | ||
422 | </ul> | ||
423 | |||
424 | If the raw name has a prefix that has not been declared, then the return | ||
425 | value will be empty. | ||
426 | |||
427 | Note that attribute names are processed differently than element names: an | ||
428 | unprefixed element name will received the default namespace (if any), while | ||
429 | an unprefixed element name will not | ||
430 | */ | ||
431 | void QXmlNamespaceSupport::processName( const QString& qname, | ||
432 | bool isAttribute, | ||
433 | QString& nsuri, QString& localname ) const | ||
434 | { | ||
435 | uint pos; | ||
436 | // search the ':' | ||
437 | for( pos=0; pos<qname.length(); pos++ ) { | ||
438 | if ( qname.at(pos) == ':' ) | ||
439 | break; | ||
440 | } | ||
441 | if ( pos < qname.length() ) { | ||
442 | // there was a ':' | ||
443 | nsuri = uri( qname.left( pos ) ); | ||
444 | localname = qname.mid( pos+1 ); | ||
445 | } else { | ||
446 | // there was no ':' | ||
447 | if ( isAttribute ) { | ||
448 | nsuri = ""; // attributes don't take default namespace | ||
449 | } else { | ||
450 | nsuri = uri( "" ); // get default namespace | ||
451 | } | ||
452 | localname = qname; | ||
453 | } | ||
454 | } | ||
455 | |||
456 | /*! | ||
457 | Returns an enumeration of all prefixes currently declared. | ||
458 | |||
459 | Note: if there is a default prefix, it will not be returned in this | ||
460 | enumeration; check for the default prefix using uri() with an argument | ||
461 | of "". | ||
462 | */ | ||
463 | QStringList QXmlNamespaceSupport::prefixes() const | ||
464 | { | ||
465 | QStringList list; | ||
466 | |||
467 | QMap<QString, QString>::ConstIterator itc, it = ns.begin(); | ||
468 | while ( (itc=it) != ns.end() ) { | ||
469 | ++it; | ||
470 | if ( !itc.key().isEmpty() ) | ||
471 | list.append( itc.key() ); | ||
472 | } | ||
473 | return list; | ||
474 | } | ||
475 | |||
476 | /*! | ||
477 | Returns a list of all prefixes currently declared for a URI. | ||
478 | |||
479 | The xml: prefix will be included. If you want only one prefix that's | ||
480 | mapped to the namespace URI, and you don't care which one you get, use the | ||
481 | prefix() function instead. | ||
482 | |||
483 | Note: the empty (default) prefix is never included in this enumeration; to | ||
484 | check for the presence of a default namespace, use uri() with an | ||
485 | argument of "". | ||
486 | */ | ||
487 | QStringList QXmlNamespaceSupport::prefixes( const QString& uri ) const | ||
488 | { | ||
489 | QStringList list; | ||
490 | |||
491 | QMap<QString, QString>::ConstIterator itc, it = ns.begin(); | ||
492 | while ( (itc=it) != ns.end() ) { | ||
493 | ++it; | ||
494 | if ( itc.data() == uri && !itc.key().isEmpty() ) | ||
495 | list.append( itc.key() ); | ||
496 | } | ||
497 | return list; | ||
498 | } | ||
499 | |||
500 | /*! | ||
501 | Starts a new namespace context. | ||
502 | |||
503 | Normally, you should push a new context at the beginning of each XML element: | ||
504 | the new context will automatically inherit the declarations of its parent | ||
505 | context, but it will also keep track of which declarations were made within | ||
506 | this context. | ||
507 | */ | ||
508 | void QXmlNamespaceSupport::pushContext() | ||
509 | { | ||
510 | nsStack.push( ns ); | ||
511 | } | ||
512 | |||
513 | /*! | ||
514 | Reverts to the previous namespace context. | ||
515 | |||
516 | Normally, you should pop the context at the end of each XML element. After | ||
517 | popping the context, all namespace prefix mappings that were previously in | ||
518 | force are restored. | ||
519 | */ | ||
520 | void QXmlNamespaceSupport::popContext() | ||
521 | { | ||
522 | if( !nsStack.isEmpty() ) | ||
523 | ns = nsStack.pop(); | ||
524 | } | ||
525 | |||
526 | /*! | ||
527 | Resets this namespace support object for reuse. | ||
528 | */ | ||
529 | void QXmlNamespaceSupport::reset() | ||
530 | { | ||
531 | nsStack.clear(); | ||
532 | ns.clear(); | ||
533 | ns.insert( "xml", "http://www.w3.org/XML/1998/namespace" ); // the XML namespace | ||
534 | } | ||
535 | |||
536 | |||
537 | |||
538 | /********************************************* | ||
539 | * | ||
540 | * QXmlAttributes | ||
541 | * | ||
542 | *********************************************/ | ||
543 | |||
544 | /*! | ||
545 | \class QXmlAttributes qxml.h | ||
546 | \brief The QXmlAttributes class provides XML attributes. | ||
547 | |||
548 | \module XML | ||
549 | |||
550 | If attributes are reported by QXmlContentHandler::startElement() this | ||
551 | class is used to pass the attribute values. It provides you with different | ||
552 | functions to access the attribute names and values. | ||
553 | */ | ||
554 | /*! | ||
555 | \fn QXmlAttributes::QXmlAttributes() | ||
556 | |||
557 | Constructs an empty attribute list. | ||
558 | */ | ||
559 | /*! | ||
560 | \fn QXmlAttributes::~QXmlAttributes() | ||
561 | |||
562 | Destructs attributes. | ||
563 | */ | ||
564 | |||
565 | /*! | ||
566 | Look up the index of an attribute by an XML 1.0 qualified name. | ||
567 | |||
568 | Returns the index of the attribute (starting with 0) or -1 if it wasn't | ||
569 | found. | ||
570 | |||
571 | See also the <a href="xml-sax.html#namespaces">namespace description</a>. | ||
572 | */ | ||
573 | int QXmlAttributes::index( const QString& qName ) const | ||
574 | { | ||
575 | return qnameList.findIndex( qName ); | ||
576 | } | ||
577 | |||
578 | /*! | ||
579 | Looks up the index of an attribute by a namespace name. | ||
580 | |||
581 | \a uri specifies the namespace URI, or the empty string if the name has no | ||
582 | namespace URI. \a localPart specifies the attribute's local name. | ||
583 | |||
584 | Returns the index of the attribute (starting with 0) or -1 if it wasn't | ||
585 | found. | ||
586 | |||
587 | See also the <a href="xml-sax.html#namespaces">namespace description</a>. | ||
588 | */ | ||
589 | int QXmlAttributes::index( const QString& uri, const QString& localPart ) const | ||
590 | { | ||
591 | uint count = uriList.count(); | ||
592 | for ( uint i=0; i<count; i++ ) { | ||
593 | if ( uriList[i] == uri && localnameList[i] == localPart ) | ||
594 | return i; | ||
595 | } | ||
596 | return -1; | ||
597 | } | ||
598 | |||
599 | /*! | ||
600 | Returns the number of attributes in the list. | ||
601 | */ | ||
602 | int QXmlAttributes::length() const | ||
603 | { | ||
604 | return valueList.count(); | ||
605 | } | ||
606 | |||
607 | /*! | ||
608 | Looks up an attribute's local name by index (starting with 0). | ||
609 | |||
610 | See also the <a href="xml-sax.html#namespaces">namespace description</a>. | ||
611 | */ | ||
612 | QString QXmlAttributes::localName( int index ) const | ||
613 | { | ||
614 | return localnameList[index]; | ||
615 | } | ||
616 | |||
617 | /*! | ||
618 | Looks up an attribute's XML 1.0 qualified name by index (starting with 0). | ||
619 | |||
620 | See also the <a href="xml-sax.html#namespaces">namespace description</a>. | ||
621 | */ | ||
622 | QString QXmlAttributes::qName( int index ) const | ||
623 | { | ||
624 | return qnameList[index]; | ||
625 | } | ||
626 | |||
627 | /*! | ||
628 | Looks up an attribute's namespace URI by index (starting with 0). | ||
629 | |||
630 | See also the <a href="xml-sax.html#namespaces">namespace description</a>. | ||
631 | */ | ||
632 | QString QXmlAttributes::uri( int index ) const | ||
633 | { | ||
634 | return uriList[index]; | ||
635 | } | ||
636 | |||
637 | /*! | ||
638 | Looks up an attribute's type by index (starting with 0). | ||
639 | |||
640 | At the moment only 'CDATA' is returned. | ||
641 | */ | ||
642 | QString QXmlAttributes::type( int ) const | ||
643 | { | ||
644 | return "CDATA"; | ||
645 | } | ||
646 | |||
647 | /*! | ||
648 | Looks up an attribute's type by XML 1.0 qualified name. | ||
649 | |||
650 | At the moment only 'CDATA' is returned. | ||
651 | */ | ||
652 | QString QXmlAttributes::type( const QString& ) const | ||
653 | { | ||
654 | return "CDATA"; | ||
655 | } | ||
656 | |||
657 | /*! | ||
658 | Looks up an attribute's type by namespace name. | ||
659 | |||
660 | The first parameter specifies the namespace URI, or the empty string if | ||
661 | the name has no namespace URI. The second parameter specifies the | ||
662 | attribute's local name. | ||
663 | |||
664 | At the moment only 'CDATA' is returned. | ||
665 | */ | ||
666 | QString QXmlAttributes::type( const QString&, const QString& ) const | ||
667 | { | ||
668 | return "CDATA"; | ||
669 | } | ||
670 | |||
671 | /*! | ||
672 | Looks up an attribute's value by index (starting with 0). | ||
673 | */ | ||
674 | QString QXmlAttributes::value( int index ) const | ||
675 | { | ||
676 | return valueList[index]; | ||
677 | } | ||
678 | |||
679 | /*! | ||
680 | Looks up an attribute's value by XML 1.0 qualified name. | ||
681 | |||
682 | See also the <a href="xml-sax.html#namespaces">namespace description</a>. | ||
683 | */ | ||
684 | QString QXmlAttributes::value( const QString& qName ) const | ||
685 | { | ||
686 | int i = index( qName ); | ||
687 | if ( i == -1 ) | ||
688 | return QString::null; | ||
689 | return valueList[ i ]; | ||
690 | } | ||
691 | |||
692 | /*! | ||
693 | Looks up an attribute's value by namespace name. | ||
694 | |||
695 | \a uri specifies the namespace URI, or the empty string if the name has no | ||
696 | namespace URI. \a localName specifies the attribute's local name. | ||
697 | |||
698 | See also the <a href="xml-sax.html#namespaces">namespace description</a>. | ||
699 | */ | ||
700 | QString QXmlAttributes::value( const QString& uri, const QString& localName ) const | ||
701 | { | ||
702 | int i = index( uri, localName ); | ||
703 | if ( i == -1 ) | ||
704 | return QString::null; | ||
705 | return valueList[ i ]; | ||
706 | } | ||
707 | |||
708 | |||
709 | /********************************************* | ||
710 | * | ||
711 | * QXmlInputSource | ||
712 | * | ||
713 | *********************************************/ | ||
714 | |||
715 | /*! | ||
716 | \class QXmlInputSource qxml.h | ||
717 | \brief The QXmlInputSource class is the source where XML data is read from. | ||
718 | |||
719 | \module XML | ||
720 | |||
721 | All subclasses of QXmlReader read the input from this class. | ||
722 | */ | ||
723 | |||
724 | /*! | ||
725 | Returns all the data this input source contains. | ||
726 | */ | ||
727 | const QString& QXmlInputSource::data() const | ||
728 | { | ||
729 | return input; | ||
730 | } | ||
731 | |||
732 | /*! | ||
733 | Constructs a input source which contains no data. | ||
734 | */ | ||
735 | QXmlInputSource::QXmlInputSource( ) | ||
736 | { | ||
737 | input = ""; | ||
738 | } | ||
739 | |||
740 | /*! | ||
741 | Constructs a input source and get the data from the text stream. | ||
742 | */ | ||
743 | QXmlInputSource::QXmlInputSource( QTextStream& stream ) | ||
744 | { | ||
745 | QByteArray rawData; | ||
746 | if ( stream.device()->isDirectAccess() ) { | ||
747 | rawData = stream.device()->readAll(); | ||
748 | } else { | ||
749 | int nread = 0; | ||
750 | const int bufsize = 512; | ||
751 | while ( !stream.device()->atEnd() ) { | ||
752 | rawData.resize( nread + bufsize ); | ||
753 | nread += stream.device()->readBlock( rawData.data()+nread, bufsize ); | ||
754 | } | ||
755 | rawData.resize( nread ); | ||
756 | } | ||
757 | readInput( rawData ); | ||
758 | } | ||
759 | |||
760 | /*! | ||
761 | Constructs a input source and get the data from a file. If the file cannot be | ||
762 | read the input source is empty. | ||
763 | */ | ||
764 | QXmlInputSource::QXmlInputSource( QFile& file ) | ||
765 | { | ||
766 | if ( !file.open(IO_ReadOnly) ) { | ||
767 | input = ""; | ||
768 | return; | ||
769 | } | ||
770 | QByteArray rawData = file.readAll(); | ||
771 | readInput( rawData ); | ||
772 | file.close(); | ||
773 | } | ||
774 | |||
775 | /*! | ||
776 | Destructor. | ||
777 | */ | ||
778 | QXmlInputSource::~QXmlInputSource() | ||
779 | { | ||
780 | } | ||
781 | |||
782 | /*! | ||
783 | Sets the data of the input source to \a dat. | ||
784 | */ | ||
785 | void QXmlInputSource::setData( const QString& dat ) | ||
786 | { | ||
787 | input = dat; | ||
788 | } | ||
789 | |||
790 | /*! | ||
791 | Read the XML file from the byte array; try to recoginize the encoding. | ||
792 | */ | ||
793 | // ### The input source should not do the encoding detection! | ||
794 | void QXmlInputSource::readInput( QByteArray& rawData ) | ||
795 | { | ||
796 | QBuffer buf( rawData ); | ||
797 | buf.open( IO_ReadOnly ); | ||
798 | QTextStream *stream = new QTextStream( &buf ); | ||
799 | QChar tmp; | ||
800 | // assume UTF8 or UTF16 at first | ||
801 | stream->setEncoding( QTextStream::UnicodeUTF8 ); | ||
802 | input = ""; | ||
803 | // read the first 5 characters | ||
804 | for ( int i=0; i<5; i++ ) { | ||
805 | *stream >> tmp; | ||
806 | input += tmp; | ||
807 | } | ||
808 | // starts the document with an XML declaration? | ||
809 | if ( input == "<?xml" ) { | ||
810 | // read the whole XML declaration | ||
811 | do { | ||
812 | *stream >> tmp; | ||
813 | input += tmp; | ||
814 | } while( tmp != '>' ); | ||
815 | // and try to find out if there is an encoding | ||
816 | int pos = input.find( "encoding" ); | ||
817 | if ( pos != -1 ) { | ||
818 | QString encoding; | ||
819 | do { | ||
820 | pos++; | ||
821 | if ( pos > (int)input.length() ) | ||
822 | goto finished; | ||
823 | } while( input[pos] != '"' && input[pos] != '\'' ); | ||
824 | pos++; | ||
825 | while( input[pos] != '"' && input[pos] != '\'' ) { | ||
826 | encoding += input[pos]; | ||
827 | pos++; | ||
828 | if ( pos > (int)input.length() ) | ||
829 | goto finished; | ||
830 | } | ||
831 | delete stream; | ||
832 | stream = new QTextStream( &buf ); | ||
833 | stream->setCodec( QTextCodec::codecForName( encoding ) ); | ||
834 | buf.reset(); | ||
835 | input = ""; | ||
836 | } | ||
837 | } | ||
838 | finished: | ||
839 | input += stream->read(); | ||
840 | delete stream; | ||
841 | buf.close(); | ||
842 | } | ||
843 | |||
844 | |||
845 | /********************************************* | ||
846 | * | ||
847 | * QXmlDefaultHandler | ||
848 | * | ||
849 | *********************************************/ | ||
850 | |||
851 | /*! | ||
852 | \class QXmlContentHandler qxml.h | ||
853 | \brief The QXmlContentHandler class provides an interface to report logical | ||
854 | content of XML data. | ||
855 | |||
856 | \module XML | ||
857 | |||
858 | If the application needs to be informed of basic parsing events, it | ||
859 | implements this interface and sets it with QXmlReader::setContentHandler(). | ||
860 | The reader reports basic document-related events like the start and end of | ||
861 | elements and character data through this interface. | ||
862 | |||
863 | The order of events in this interface is very important, and mirrors the | ||
864 | order of information in the document itself. For example, all of an element's | ||
865 | content (character data, processing instructions, and/or subelements) will | ||
866 | appear, in order, between the startElement() event and the corresponding | ||
867 | endElement() event. | ||
868 | |||
869 | The class QXmlDefaultHandler gives a default implementation for this | ||
870 | interface; subclassing from this class is very convenient if you want only be | ||
871 | informed of some parsing events. | ||
872 | |||
873 | See also the <a href="xml.html#introSAX2">Introduction to SAX2</a>. | ||
874 | |||
875 | \sa QXmlDTDHandler QXmlDeclHandler QXmlEntityResolver QXmlErrorHandler | ||
876 | QXmlLexicalHandler | ||
877 | */ | ||
878 | /*! | ||
879 | \fn void QXmlContentHandler::setDocumentLocator( QXmlLocator* locator ) | ||
880 | |||
881 | The reader calls this function before he starts parsing the document. The | ||
882 | argument \a locator is a pointer to a QXmlLocator which allows the | ||
883 | application to get the actual position of the parsing in the document. | ||
884 | |||
885 | Do not destroy the \a locator; it is destroyed when the reader is destroyed | ||
886 | (do not use the \a locator after the reader got destroyed). | ||
887 | */ | ||
888 | /*! | ||
889 | \fn bool QXmlContentHandler::startDocument() | ||
890 | |||
891 | The reader calls this function when he starts parsing the document. | ||
892 | The reader will call this function only once before any other functions in | ||
893 | this class or in the QXmlDTDHandler class are called (except | ||
894 | QXmlContentHandler::setDocumentLocator()). | ||
895 | |||
896 | If this function returns FALSE the reader will stop parsing and will report | ||
897 | an error. The reader will use the function errorString() to get the error | ||
898 | message that will be used for reporting the error. | ||
899 | |||
900 | \sa endDocument() | ||
901 | */ | ||
902 | /*! | ||
903 | \fn bool QXmlContentHandler::endDocument() | ||
904 | |||
905 | The reader calls this function after he has finished the parsing. It | ||
906 | is only called once. It is the last function of all handler functions that is | ||
907 | called. It is called after the reader has read all input or has abandoned | ||
908 | parsing because of a fatal error. | ||
909 | |||
910 | If this function returns FALSE the reader will stop parsing and will report | ||
911 | an error. The reader will use the function errorString() to get the error | ||
912 | message that will be used for reporting the error. | ||
913 | |||
914 | \sa startDocument() | ||
915 | */ | ||
916 | /*! | ||
917 | \fn bool QXmlContentHandler::startPrefixMapping( const QString& prefix, const QString& uri ) | ||
918 | |||
919 | The reader calls this function to signal the begin of a prefix-URI | ||
920 | namespace mapping scope. This information is not necessary for normal | ||
921 | namespace processing since the reader automatically replaces prefixes for | ||
922 | element and attribute names. | ||
923 | |||
924 | Note that startPrefixMapping and endPrefixMapping calls are not guaranteed to | ||
925 | be properly nested relative to each-other: all startPrefixMapping events will | ||
926 | occur before the corresponding startElement event, and all endPrefixMapping | ||
927 | events will occur after the corresponding endElement event, but their order | ||
928 | is not otherwise guaranteed. | ||
929 | |||
930 | The argument \a prefix is the namespace prefix being declared and the | ||
931 | argument \a uri is the namespace URI the prefix is mapped to. | ||
932 | |||
933 | If this function returns FALSE the reader will stop parsing and will report | ||
934 | an error. The reader will use the function errorString() to get the error | ||
935 | message that will be used for reporting the error. | ||
936 | |||
937 | See also the <a href="xml-sax.html#namespaces">namespace description</a>. | ||
938 | |||
939 | \sa endPrefixMapping() | ||
940 | */ | ||
941 | /*! | ||
942 | \fn bool QXmlContentHandler::endPrefixMapping( const QString& prefix ) | ||
943 | |||
944 | The reader calls this function to signal the end of a prefix mapping. | ||
945 | |||
946 | If this function returns FALSE the reader will stop parsing and will report | ||
947 | an error. The reader will use the function errorString() to get the error | ||
948 | message that will be used for reporting the error. | ||
949 | |||
950 | See also the <a href="xml-sax.html#namespaces">namespace description</a>. | ||
951 | |||
952 | \sa startPrefixMapping() | ||
953 | */ | ||
954 | /*! | ||
955 | \fn bool QXmlContentHandler::startElement( const QString& namespaceURI, const QString& localName, const QString& qName, const QXmlAttributes& atts ) | ||
956 | |||
957 | The reader calls this function when he has parsed a start element tag. | ||
958 | |||
959 | There will be a corresponding endElement() call when the corresponding end | ||
960 | element tag was read. The startElement() and endElement() calls are always | ||
961 | nested correctly. Empty element tags (e.g. <a/>) are reported by | ||
962 | startElement() directly followed by a call to endElement(). | ||
963 | |||
964 | The attribute list provided will contain only attributes with explicit | ||
965 | values. The attribute list will contain attributes used for namespace | ||
966 | declaration (i.e. attributes starting with xmlns) only if the | ||
967 | namespace-prefix property of the reader is TRUE. | ||
968 | |||
969 | The argument \a uri is the namespace URI, or the empty string if the element | ||
970 | has no namespace URI or if namespace processing is not being performed, \a | ||
971 | localName is the local name (without prefix), or the empty string if | ||
972 | namespace processing is not being performed, \a qName is the qualified name | ||
973 | (with prefix), or the empty string if qualified names are not available and | ||
974 | \a atts are the attributes attached to the element. If there are no | ||
975 | attributes, \a atts is an empty attributes object | ||
976 | |||
977 | If this function returns FALSE the reader will stop parsing and will report | ||
978 | an error. The reader will use the function errorString() to get the error | ||
979 | message that will be used for reporting the error. | ||
980 | |||
981 | See also the <a href="xml-sax.html#namespaces">namespace description</a>. | ||
982 | |||
983 | \sa endElement() | ||
984 | */ | ||
985 | /*! | ||
986 | \fn bool QXmlContentHandler::endElement( const QString& namespaceURI, const QString& localName, const QString& qName ) | ||
987 | |||
988 | The reader calls this function when he has parsed an end element tag. | ||
989 | |||
990 | If this function returns FALSE the reader will stop parsing and will report | ||
991 | an error. The reader will use the function errorString() to get the error | ||
992 | message that will be used for reporting the error. | ||
993 | |||
994 | See also the <a href="xml-sax.html#namespaces">namespace description</a>. | ||
995 | |||
996 | \sa startElement() | ||
997 | */ | ||
998 | /*! | ||
999 | \fn bool QXmlContentHandler::characters( const QString& ch ) | ||
1000 | |||
1001 | The reader calls this function when he has parsed a chunk of character | ||
1002 | data (either normal character data or character data inside a CDATA section; | ||
1003 | if you have to distinguish between those two types you have to use | ||
1004 | QXmlLexicalHandler::startCDATA() and QXmlLexicalHandler::endCDATA() in | ||
1005 | addition). | ||
1006 | |||
1007 | Some readers will report whitespace in element content using the | ||
1008 | ignorableWhitespace() function rather than this one (QXmlSimpleReader will | ||
1009 | do it not though). | ||
1010 | |||
1011 | A reader is allowed to report the character data of an element in more than | ||
1012 | one chunk; e.g. a reader might want to report "a &lt; b" in three | ||
1013 | characters() events ("a ", "<" and " b"). | ||
1014 | |||
1015 | If this function returns FALSE the reader will stop parsing and will report | ||
1016 | an error. The reader will use the function errorString() to get the error | ||
1017 | message that will be used for reporting the error. | ||
1018 | */ | ||
1019 | /*! | ||
1020 | \fn bool QXmlContentHandler::ignorableWhitespace( const QString& ch ) | ||
1021 | |||
1022 | Some readers may use this function to report each chunk of whitespace in | ||
1023 | element content (QXmlSimpleReader does not though). | ||
1024 | |||
1025 | If this function returns FALSE the reader will stop parsing and will report | ||
1026 | an error. The reader will use the function errorString() to get the error | ||
1027 | message that will be used for reporting the error. | ||
1028 | */ | ||
1029 | /*! | ||
1030 | \fn bool QXmlContentHandler::processingInstruction( const QString& target, const QString& data ) | ||
1031 | |||
1032 | The reader calls this function when he has parsed a processing | ||
1033 | instruction. | ||
1034 | |||
1035 | \a target is the target name of the processing instruction and \a data is the | ||
1036 | data of the processing instruction. | ||
1037 | |||
1038 | If this function returns FALSE the reader will stop parsing and will report | ||
1039 | an error. The reader will use the function errorString() to get the error | ||
1040 | message that will be used for reporting the error. | ||
1041 | */ | ||
1042 | /*! | ||
1043 | \fn bool QXmlContentHandler::skippedEntity( const QString& name ) | ||
1044 | |||
1045 | Some readers may skip entities if they have not seen the declarations (e.g. | ||
1046 | because they are in an external DTD). If they do so they will report it by | ||
1047 | calling this function. | ||
1048 | |||
1049 | If this function returns FALSE the reader will stop parsing and will report | ||
1050 | an error. The reader will use the function errorString() to get the error | ||
1051 | message that will be used for reporting the error. | ||
1052 | */ | ||
1053 | /*! | ||
1054 | \fn QString QXmlContentHandler::errorString() | ||
1055 | |||
1056 | The reader calls this function to get an error string if any of the handler | ||
1057 | functions returns FALSE to him. | ||
1058 | */ | ||
1059 | |||
1060 | |||
1061 | /*! | ||
1062 | \class QXmlErrorHandler qxml.h | ||
1063 | \brief The QXmlErrorHandler class provides an interface to report errors in | ||
1064 | XML data. | ||
1065 | |||
1066 | \module XML | ||
1067 | |||
1068 | If the application is interested in reporting errors to the user or any other | ||
1069 | customized error handling, you should subclass this class. | ||
1070 | |||
1071 | You can set the error handler with QXmlReader::setErrorHandler(). | ||
1072 | |||
1073 | See also the <a href="xml.html#introSAX2">Introduction to SAX2</a>. | ||
1074 | |||
1075 | \sa QXmlDTDHandler QXmlDeclHandler QXmlContentHandler QXmlEntityResolver | ||
1076 | QXmlLexicalHandler | ||
1077 | */ | ||
1078 | /*! | ||
1079 | \fn bool QXmlErrorHandler::warning( const QXmlParseException& exception ) | ||
1080 | |||
1081 | A reader might use this function to report a warning. Warnings are conditions | ||
1082 | that are not errors or fatal errors as defined by the XML 1.0 specification. | ||
1083 | |||
1084 | If this function returns FALSE the reader will stop parsing and will report | ||
1085 | an error. The reader will use the function errorString() to get the error | ||
1086 | message that will be used for reporting the error. | ||
1087 | */ | ||
1088 | /*! | ||
1089 | \fn bool QXmlErrorHandler::error( const QXmlParseException& exception ) | ||
1090 | |||
1091 | A reader might use this function to report a recoverable error. A recoverable | ||
1092 | error corresponds to the definiton of "error" in section 1.2 of the XML 1.0 | ||
1093 | specification. | ||
1094 | |||
1095 | The reader must continue to provide normal parsing events after invoking this | ||
1096 | function. | ||
1097 | |||
1098 | If this function returns FALSE the reader will stop parsing and will report | ||
1099 | an error. The reader will use the function errorString() to get the error | ||
1100 | message that will be used for reporting the error. | ||
1101 | */ | ||
1102 | /*! | ||
1103 | \fn bool QXmlErrorHandler::fatalError( const QXmlParseException& exception ) | ||
1104 | |||
1105 | A reader must use this function to report a non-recoverable error. | ||
1106 | |||
1107 | If this function returns TRUE the reader might try to go on parsing and | ||
1108 | reporting further errors; but no regular parsing events are reported. | ||
1109 | */ | ||
1110 | /*! | ||
1111 | \fn QString QXmlErrorHandler::errorString() | ||
1112 | |||
1113 | The reader calls this function to get an error string if any of the handler | ||
1114 | functions returns FALSE to him. | ||
1115 | */ | ||
1116 | |||
1117 | |||
1118 | /*! | ||
1119 | \class QXmlDTDHandler qxml.h | ||
1120 | \brief The QXmlDTDHandler class provides an interface to report DTD content | ||
1121 | of XML data. | ||
1122 | |||
1123 | \module XML | ||
1124 | |||
1125 | If an application needs information about notations and unparsed entities, | ||
1126 | then the application implements this interface and registers an instance with | ||
1127 | QXmlReader::setDTDHandler(). | ||
1128 | |||
1129 | Note that this interface includes only those DTD events that the XML | ||
1130 | recommendation requires processors to report: notation and unparsed entity | ||
1131 | declarations. | ||
1132 | |||
1133 | See also the <a href="xml.html#introSAX2">Introduction to SAX2</a>. | ||
1134 | |||
1135 | \sa QXmlDeclHandler QXmlContentHandler QXmlEntityResolver QXmlErrorHandler | ||
1136 | QXmlLexicalHandler | ||
1137 | */ | ||
1138 | /*! | ||
1139 | \fn bool QXmlDTDHandler::notationDecl( const QString& name, const QString& publicId, const QString& systemId ) | ||
1140 | |||
1141 | The reader calls this function when he has parsed a notation | ||
1142 | declaration. | ||
1143 | |||
1144 | The argument \a name is the notation name, \a publicId is the notations's | ||
1145 | public identifier and \a systemId is the notations's system identifier. | ||
1146 | |||
1147 | If this function returns FALSE the reader will stop parsing and will report | ||
1148 | an error. The reader will use the function errorString() to get the error | ||
1149 | message that will be used for reporting the error. | ||
1150 | */ | ||
1151 | /*! | ||
1152 | \fn bool QXmlDTDHandler::unparsedEntityDecl( const QString& name, const QString& publicId, const QString& systemId, const QString& notationName ) | ||
1153 | |||
1154 | The reader calls this function when he finds an unparsed entity declaration. | ||
1155 | |||
1156 | The argument \a name is the unparsed entity's name, \a publicId is the | ||
1157 | entity's public identifier, \a systemId is the entity's system identifier and | ||
1158 | \a notation is the name of the associated notation. | ||
1159 | |||
1160 | If this function returns FALSE the reader will stop parsing and will report | ||
1161 | an error. The reader will use the function errorString() to get the error | ||
1162 | message that will be used for reporting the error. | ||
1163 | */ | ||
1164 | /*! | ||
1165 | \fn QString QXmlDTDHandler::errorString() | ||
1166 | |||
1167 | The reader calls this function to get an error string if any of the handler | ||
1168 | functions returns FALSE to him. | ||
1169 | */ | ||
1170 | |||
1171 | |||
1172 | /*! | ||
1173 | \class QXmlEntityResolver qxml.h | ||
1174 | \brief The QXmlEntityResolver class provides an interface to resolve extern | ||
1175 | entities contained in XML data. | ||
1176 | |||
1177 | \module XML | ||
1178 | |||
1179 | If an application needs to implement customized handling for external | ||
1180 | entities, it must implement this interface and register it with | ||
1181 | QXmlReader::setEntityResolver(). | ||
1182 | |||
1183 | See also the <a href="xml.html#introSAX2">Introduction to SAX2</a>. | ||
1184 | |||
1185 | \sa QXmlDTDHandler QXmlDeclHandler QXmlContentHandler QXmlErrorHandler | ||
1186 | QXmlLexicalHandler | ||
1187 | */ | ||
1188 | /*! | ||
1189 | \fn bool QXmlEntityResolver::resolveEntity( const QString& publicId, const QString& systemId, QXmlInputSource* ret ) | ||
1190 | |||
1191 | The reader will call this function before he opens any external entity, | ||
1192 | except the top-level document entity. The application may request the reader | ||
1193 | to resolve the entity itself (\a ret is 0) or to use an entirely different | ||
1194 | input source (\a ret points to the input source). | ||
1195 | |||
1196 | The reader will delete the input source \a ret when he no longer needs it. So | ||
1197 | you should allocate it on the heap with \c new. | ||
1198 | |||
1199 | The argument \a publicId is the public identifier of the external entity, \a | ||
1200 | systemId is the system identifier of the external entity and \a ret is the | ||
1201 | return value of this function: if it is 0 the reader should resolve the | ||
1202 | entity itself, if it is non-zero it must point to an input source which the | ||
1203 | reader will use instead. | ||
1204 | |||
1205 | If this function returns FALSE the reader will stop parsing and will report | ||
1206 | an error. The reader will use the function errorString() to get the error | ||
1207 | message that will be used for reporting the error. | ||
1208 | */ | ||
1209 | /*! | ||
1210 | \fn QString QXmlEntityResolver::errorString() | ||
1211 | |||
1212 | The reader calls this function to get an error string if any of the handler | ||
1213 | functions returns FALSE to him. | ||
1214 | */ | ||
1215 | |||
1216 | |||
1217 | /*! | ||
1218 | \class QXmlLexicalHandler qxml.h | ||
1219 | \brief The QXmlLexicalHandler class provides an interface to report lexical | ||
1220 | content of XML data. | ||
1221 | |||
1222 | \module XML | ||
1223 | |||
1224 | The events in the lexical handler apply to the entire document, not just to | ||
1225 | the document element, and all lexical handler events appear between the | ||
1226 | content handler's startDocument and endDocument events. | ||
1227 | |||
1228 | You can set the lexical handler with QXmlReader::setLexicalHandler(). | ||
1229 | |||
1230 | This interface is designed after the SAX2 extension LexicalHandler. The | ||
1231 | functions startEntity() and endEntity() are not included though. | ||
1232 | |||
1233 | See also the <a href="xml.html#introSAX2">Introduction to SAX2</a>. | ||
1234 | |||
1235 | \sa QXmlDTDHandler QXmlDeclHandler QXmlContentHandler QXmlEntityResolver | ||
1236 | QXmlErrorHandler | ||
1237 | */ | ||
1238 | /*! | ||
1239 | \fn bool QXmlLexicalHandler::startDTD( const QString& name, const QString& publicId, const QString& systemId ) | ||
1240 | |||
1241 | The reader calls this function to report the start of a DTD declaration, if | ||
1242 | any. | ||
1243 | |||
1244 | All declarations reported through QXmlDTDHandler or QXmlDeclHandler appear | ||
1245 | between the startDTD() and endDTD() calls. | ||
1246 | |||
1247 | If this function returns FALSE the reader will stop parsing and will report | ||
1248 | an error. The reader will use the function errorString() to get the error | ||
1249 | message that will be used for reporting the error. | ||
1250 | |||
1251 | \sa endDTD() | ||
1252 | */ | ||
1253 | /*! | ||
1254 | \fn bool QXmlLexicalHandler::endDTD() | ||
1255 | |||
1256 | The reader calls this function to report the end of a DTD declaration, if | ||
1257 | any. | ||
1258 | |||
1259 | If this function returns FALSE the reader will stop parsing and will report | ||
1260 | an error. The reader will use the function errorString() to get the error | ||
1261 | message that will be used for reporting the error. | ||
1262 | |||
1263 | \sa startDTD() | ||
1264 | */ | ||
1265 | /*! | ||
1266 | \fn bool QXmlLexicalHandler::startCDATA() | ||
1267 | |||
1268 | The reader calls this function to report the start of a CDATA section. The | ||
1269 | content of the CDATA section will be reported through the regular | ||
1270 | QXmlContentHandler::characters(). This function is intended only to report | ||
1271 | the boundary. | ||
1272 | |||
1273 | If this function returns FALSE the reader will stop parsing and will report | ||
1274 | an error. The reader will use the function errorString() to get the error | ||
1275 | message that will be used for reporting the error. | ||
1276 | |||
1277 | \sa endCDATA() | ||
1278 | */ | ||
1279 | /*! | ||
1280 | \fn bool QXmlLexicalHandler::endCDATA() | ||
1281 | |||
1282 | The reader calls this function to report the end of a CDATA section. | ||
1283 | |||
1284 | If this function returns FALSE the reader will stop parsing and will report | ||
1285 | an error. The reader will use the function errorString() to get the error | ||
1286 | message that will be used for reporting the error. | ||
1287 | |||
1288 | \sa startCDATA() | ||
1289 | */ | ||
1290 | /*! | ||
1291 | \fn bool QXmlLexicalHandler::comment( const QString& ch ) | ||
1292 | |||
1293 | The reader calls this function to report an XML comment anywhere in the | ||
1294 | document. | ||
1295 | |||
1296 | If this function returns FALSE the reader will stop parsing and will report | ||
1297 | an error. The reader will use the function errorString() to get the error | ||
1298 | message that will be used for reporting the error. | ||
1299 | */ | ||
1300 | /*! | ||
1301 | \fn QString QXmlLexicalHandler::errorString() | ||
1302 | |||
1303 | The reader calls this function to get an error string if any of the handler | ||
1304 | functions returns FALSE to him. | ||
1305 | */ | ||
1306 | |||
1307 | |||
1308 | /*! | ||
1309 | \class QXmlDeclHandler qxml.h | ||
1310 | \brief The QXmlDeclHandler class provides an interface to report declaration | ||
1311 | content of XML data. | ||
1312 | |||
1313 | \module XML | ||
1314 | |||
1315 | You can set the declaration handler with QXmlReader::setDeclHandler(). | ||
1316 | |||
1317 | This interface is designed after the SAX2 extension DeclHandler. | ||
1318 | |||
1319 | See also the <a href="xml.html#introSAX2">Introduction to SAX2</a>. | ||
1320 | |||
1321 | \sa QXmlDTDHandler QXmlContentHandler QXmlEntityResolver QXmlErrorHandler | ||
1322 | QXmlLexicalHandler | ||
1323 | */ | ||
1324 | /*! | ||
1325 | \fn bool QXmlDeclHandler::attributeDecl( const QString& eName, const QString& aName, const QString& type, const QString& valueDefault, const QString& value ) | ||
1326 | |||
1327 | The reader calls this function to report an attribute type declaration. Only | ||
1328 | the effective (first) declaration for an attribute will be reported. | ||
1329 | |||
1330 | If this function returns FALSE the reader will stop parsing and will report | ||
1331 | an error. The reader will use the function errorString() to get the error | ||
1332 | message that will be used for reporting the error. | ||
1333 | */ | ||
1334 | /*! | ||
1335 | \fn bool QXmlDeclHandler::internalEntityDecl( const QString& name, const QString& value ) | ||
1336 | |||
1337 | The reader calls this function to report an internal entity declaration. Only | ||
1338 | the effective (first) declaration will be reported. | ||
1339 | |||
1340 | If this function returns FALSE the reader will stop parsing and will report | ||
1341 | an error. The reader will use the function errorString() to get the error | ||
1342 | message that will be used for reporting the error. | ||
1343 | */ | ||
1344 | /*! | ||
1345 | \fn bool QXmlDeclHandler::externalEntityDecl( const QString& name, const QString& publicId, const QString& systemId ) | ||
1346 | |||
1347 | The reader calls this function to report a parsed external entity | ||
1348 | declaration. Only the effective (first) declaration for each entity will be | ||
1349 | reported. | ||
1350 | |||
1351 | If this function returns FALSE the reader will stop parsing and will report | ||
1352 | an error. The reader will use the function errorString() to get the error | ||
1353 | message that will be used for reporting the error. | ||
1354 | */ | ||
1355 | /*! | ||
1356 | \fn QString QXmlDeclHandler::errorString() | ||
1357 | |||
1358 | The reader calls this function to get an error string if any of the handler | ||
1359 | functions returns FALSE to him. | ||
1360 | */ | ||
1361 | |||
1362 | |||
1363 | /*! | ||
1364 | \class QXmlDefaultHandler qxml.h | ||
1365 | \brief The QXmlDefaultHandler class provides a default implementation of all | ||
1366 | XML handler classes. | ||
1367 | |||
1368 | \module XML | ||
1369 | |||
1370 | Very often you are only interested in parts of the things that that the | ||
1371 | reader reports to you. This class simply implements a default behaviour of | ||
1372 | the handler classes (most of the time: do nothing). Normally this is the | ||
1373 | class you subclass for implementing your customized handler. | ||
1374 | |||
1375 | See also the <a href="xml.html#introSAX2">Introduction to SAX2</a>. | ||
1376 | |||
1377 | \sa QXmlDTDHandler QXmlDeclHandler QXmlContentHandler QXmlEntityResolver | ||
1378 | QXmlErrorHandler QXmlLexicalHandler | ||
1379 | */ | ||
1380 | /*! | ||
1381 | \fn QXmlDefaultHandler::QXmlDefaultHandler() | ||
1382 | |||
1383 | Constructor. | ||
1384 | */ | ||
1385 | /*! | ||
1386 | \fn QXmlDefaultHandler::~QXmlDefaultHandler() | ||
1387 | |||
1388 | Destructor. | ||
1389 | */ | ||
1390 | |||
1391 | /*! | ||
1392 | Does nothing. | ||
1393 | */ | ||
1394 | void QXmlDefaultHandler::setDocumentLocator( QXmlLocator* ) | ||
1395 | { | ||
1396 | } | ||
1397 | |||
1398 | /*! | ||
1399 | Does nothing. | ||
1400 | */ | ||
1401 | bool QXmlDefaultHandler::startDocument() | ||
1402 | { | ||
1403 | return TRUE; | ||
1404 | } | ||
1405 | |||
1406 | /*! | ||
1407 | Does nothing. | ||
1408 | */ | ||
1409 | bool QXmlDefaultHandler::endDocument() | ||
1410 | { | ||
1411 | return TRUE; | ||
1412 | } | ||
1413 | |||
1414 | /*! | ||
1415 | Does nothing. | ||
1416 | */ | ||
1417 | bool QXmlDefaultHandler::startPrefixMapping( const QString&, const QString& ) | ||
1418 | { | ||
1419 | return TRUE; | ||
1420 | } | ||
1421 | |||
1422 | /*! | ||
1423 | Does nothing. | ||
1424 | */ | ||
1425 | bool QXmlDefaultHandler::endPrefixMapping( const QString& ) | ||
1426 | { | ||
1427 | return TRUE; | ||
1428 | } | ||
1429 | |||
1430 | /*! | ||
1431 | Does nothing. | ||
1432 | */ | ||
1433 | bool QXmlDefaultHandler::startElement( const QString&, const QString&, | ||
1434 | const QString&, const QXmlAttributes& ) | ||
1435 | { | ||
1436 | return TRUE; | ||
1437 | } | ||
1438 | |||
1439 | /*! | ||
1440 | Does nothing. | ||
1441 | */ | ||
1442 | bool QXmlDefaultHandler::endElement( const QString&, const QString&, | ||
1443 | const QString& ) | ||
1444 | { | ||
1445 | return TRUE; | ||
1446 | } | ||
1447 | |||
1448 | /*! | ||
1449 | Does nothing. | ||
1450 | */ | ||
1451 | bool QXmlDefaultHandler::characters( const QString& ) | ||
1452 | { | ||
1453 | return TRUE; | ||
1454 | } | ||
1455 | |||
1456 | /*! | ||
1457 | Does nothing. | ||
1458 | */ | ||
1459 | bool QXmlDefaultHandler::ignorableWhitespace( const QString& ) | ||
1460 | { | ||
1461 | return TRUE; | ||
1462 | } | ||
1463 | |||
1464 | /*! | ||
1465 | Does nothing. | ||
1466 | */ | ||
1467 | bool QXmlDefaultHandler::processingInstruction( const QString&, | ||
1468 | const QString& ) | ||
1469 | { | ||
1470 | return TRUE; | ||
1471 | } | ||
1472 | |||
1473 | /*! | ||
1474 | Does nothing. | ||
1475 | */ | ||
1476 | bool QXmlDefaultHandler::skippedEntity( const QString& ) | ||
1477 | { | ||
1478 | return TRUE; | ||
1479 | } | ||
1480 | |||
1481 | /*! | ||
1482 | Does nothing. | ||
1483 | */ | ||
1484 | bool QXmlDefaultHandler::warning( const QXmlParseException& ) | ||
1485 | { | ||
1486 | return TRUE; | ||
1487 | } | ||
1488 | |||
1489 | /*! | ||
1490 | Does nothing. | ||
1491 | */ | ||
1492 | bool QXmlDefaultHandler::error( const QXmlParseException& ) | ||
1493 | { | ||
1494 | return TRUE; | ||
1495 | } | ||
1496 | |||
1497 | /*! | ||
1498 | Does nothing. | ||
1499 | */ | ||
1500 | bool QXmlDefaultHandler::fatalError( const QXmlParseException& ) | ||
1501 | { | ||
1502 | return TRUE; | ||
1503 | } | ||
1504 | |||
1505 | /*! | ||
1506 | Does nothing. | ||
1507 | */ | ||
1508 | bool QXmlDefaultHandler::notationDecl( const QString&, const QString&, | ||
1509 | const QString& ) | ||
1510 | { | ||
1511 | return TRUE; | ||
1512 | } | ||
1513 | |||
1514 | /*! | ||
1515 | Does nothing. | ||
1516 | */ | ||
1517 | bool QXmlDefaultHandler::unparsedEntityDecl( const QString&, const QString&, | ||
1518 | const QString&, const QString& ) | ||
1519 | { | ||
1520 | return TRUE; | ||
1521 | } | ||
1522 | |||
1523 | /*! | ||
1524 | Always sets \a ret to 0, so that the reader will use the system identifier | ||
1525 | provided in the XML document. | ||
1526 | */ | ||
1527 | bool QXmlDefaultHandler::resolveEntity( const QString&, const QString&, | ||
1528 | QXmlInputSource* /* ret */ ) | ||
1529 | { | ||
1530 | /* ### This doesn't set anything to 0! | ||
1531 | ret = 0; | ||
1532 | */ | ||
1533 | return TRUE; | ||
1534 | } | ||
1535 | |||
1536 | /*! | ||
1537 | Returns the default error string. | ||
1538 | */ | ||
1539 | QString QXmlDefaultHandler::errorString() | ||
1540 | { | ||
1541 | return QString( XMLERR_ERRORBYCONSUMER ); | ||
1542 | } | ||
1543 | |||
1544 | /*! | ||
1545 | Does nothing. | ||
1546 | */ | ||
1547 | bool QXmlDefaultHandler::startDTD( const QString&, const QString&, const QString& ) | ||
1548 | { | ||
1549 | return TRUE; | ||
1550 | } | ||
1551 | |||
1552 | /*! | ||
1553 | Does nothing. | ||
1554 | */ | ||
1555 | bool QXmlDefaultHandler::endDTD() | ||
1556 | { | ||
1557 | return TRUE; | ||
1558 | } | ||
1559 | |||
1560 | #if 0 | ||
1561 | /*! | ||
1562 | Does nothing. | ||
1563 | */ | ||
1564 | bool QXmlDefaultHandler::startEntity( const QString& ) | ||
1565 | { | ||
1566 | return TRUE; | ||
1567 | } | ||
1568 | |||
1569 | /*! | ||
1570 | Does nothing. | ||
1571 | */ | ||
1572 | bool QXmlDefaultHandler::endEntity( const QString& ) | ||
1573 | { | ||
1574 | return TRUE; | ||
1575 | } | ||
1576 | #endif | ||
1577 | |||
1578 | /*! | ||
1579 | Does nothing. | ||
1580 | */ | ||
1581 | bool QXmlDefaultHandler::startCDATA() | ||
1582 | { | ||
1583 | return TRUE; | ||
1584 | } | ||
1585 | |||
1586 | /*! | ||
1587 | Does nothing. | ||
1588 | */ | ||
1589 | bool QXmlDefaultHandler::endCDATA() | ||
1590 | { | ||
1591 | return TRUE; | ||
1592 | } | ||
1593 | |||
1594 | /*! | ||
1595 | Does nothing. | ||
1596 | */ | ||
1597 | bool QXmlDefaultHandler::comment( const QString& ) | ||
1598 | { | ||
1599 | return TRUE; | ||
1600 | } | ||
1601 | |||
1602 | /*! | ||
1603 | Does nothing. | ||
1604 | */ | ||
1605 | bool QXmlDefaultHandler::attributeDecl( const QString&, const QString&, const QString&, const QString&, const QString& ) | ||
1606 | { | ||
1607 | return TRUE; | ||
1608 | } | ||
1609 | |||
1610 | /*! | ||
1611 | Does nothing. | ||
1612 | */ | ||
1613 | bool QXmlDefaultHandler::internalEntityDecl( const QString&, const QString& ) | ||
1614 | { | ||
1615 | return TRUE; | ||
1616 | } | ||
1617 | |||
1618 | /*! | ||
1619 | Does nothing. | ||
1620 | */ | ||
1621 | bool QXmlDefaultHandler::externalEntityDecl( const QString&, const QString&, const QString& ) | ||
1622 | { | ||
1623 | return TRUE; | ||
1624 | } | ||
1625 | |||
1626 | |||
1627 | /********************************************* | ||
1628 | * | ||
1629 | * QXmlSimpleReaderPrivate | ||
1630 | * | ||
1631 | *********************************************/ | ||
1632 | |||
1633 | class QXmlSimpleReaderPrivate | ||
1634 | { | ||
1635 | private: | ||
1636 | // constructor | ||
1637 | QXmlSimpleReaderPrivate() | ||
1638 | { } | ||
1639 | |||
1640 | |||
1641 | // used for entity declarations | ||
1642 | struct ExternParameterEntity | ||
1643 | { | ||
1644 | ExternParameterEntity( ) {} | ||
1645 | ExternParameterEntity( const QString &p, const QString &s ) | ||
1646 | : publicId(p), systemId(s) {} | ||
1647 | QString publicId; | ||
1648 | QString systemId; | ||
1649 | }; | ||
1650 | struct ExternEntity | ||
1651 | { | ||
1652 | ExternEntity( ) {} | ||
1653 | ExternEntity( const QString &p, const QString &s, const QString &n ) | ||
1654 | : publicId(p), systemId(s), notation(n) {} | ||
1655 | QString publicId; | ||
1656 | QString systemId; | ||
1657 | QString notation; | ||
1658 | }; | ||
1659 | QMap<QString,ExternParameterEntity> externParameterEntities; | ||
1660 | QMap<QString,QString> parameterEntities; | ||
1661 | QMap<QString,ExternEntity> externEntities; | ||
1662 | QMap<QString,QString> entities; | ||
1663 | |||
1664 | // used for standalone declaration | ||
1665 | enum Standalone { Yes, No, Unknown }; | ||
1666 | |||
1667 | QString doctype; // only used for the doctype | ||
1668 | QString xmlVersion; // only used to store the version information | ||
1669 | QString encoding; // only used to store the encoding | ||
1670 | Standalone standalone; // used to store the value of the standalone declaration | ||
1671 | |||
1672 | QString publicId; // used by parseExternalID() to store the public ID | ||
1673 | QString systemId; // used by parseExternalID() to store the system ID | ||
1674 | QString attDeclEName; // use by parseAttlistDecl() | ||
1675 | QString attDeclAName; // use by parseAttlistDecl() | ||
1676 | |||
1677 | // flags for some features support | ||
1678 | bool useNamespaces; | ||
1679 | bool useNamespacePrefixes; | ||
1680 | bool reportWhitespaceCharData; | ||
1681 | bool reportEntities; | ||
1682 | |||
1683 | // used to build the attribute list | ||
1684 | QXmlAttributes attList; | ||
1685 | |||
1686 | // helper classes | ||
1687 | QXmlLocator *locator; | ||
1688 | QXmlNamespaceSupport namespaceSupport; | ||
1689 | |||
1690 | // error string | ||
1691 | QString error; | ||
1692 | |||
1693 | // friend declarations | ||
1694 | friend class QXmlSimpleReader; | ||
1695 | }; | ||
1696 | |||
1697 | |||
1698 | /********************************************* | ||
1699 | * | ||
1700 | * QXmlSimpleReader | ||
1701 | * | ||
1702 | *********************************************/ | ||
1703 | |||
1704 | /*! | ||
1705 | \class QXmlReader qxml.h | ||
1706 | \brief The QXmlReader class provides an interface for XML readers (i.e. | ||
1707 | parsers). | ||
1708 | |||
1709 | \module XML | ||
1710 | |||
1711 | This abstract class describes an interface for all XML readers in Qt. At the | ||
1712 | moment there is only one implementation of a reader included in the XML | ||
1713 | module of Qt (QXmlSimpleReader). In future releases there might be more | ||
1714 | readers with different properties available (e.g. a validating parser). | ||
1715 | |||
1716 | The design of the XML classes follow the | ||
1717 | <a href="http://www.megginson.com/SAX/">SAX2 java interface</a>. | ||
1718 | It was adopted to fit into the Qt naming conventions; so it should be very | ||
1719 | easy for anybody who has worked with SAX2 to get started with the Qt XML | ||
1720 | classes. | ||
1721 | |||
1722 | All readers use the class QXmlInputSource to read the input document from. | ||
1723 | Since you are normally interested in certain contents of the XML document, | ||
1724 | the reader reports those contents through special handler classes | ||
1725 | (QXmlDTDHandler, QXmlDeclHandler, QXmlContentHandler, QXmlEntityResolver, | ||
1726 | QXmlErrorHandler and QXmlLexicalHandler). | ||
1727 | |||
1728 | You have to subclass these classes. Since the handler classes describe only | ||
1729 | interfaces you must implement all functions; there is a class | ||
1730 | (QXmlDefaultHandler) to make this easier; it implements a default behaviour | ||
1731 | (do nothing) for all functions. | ||
1732 | |||
1733 | For getting started see also the | ||
1734 | <a href="xml-sax.html#quickStart">Quick start</a>. | ||
1735 | |||
1736 | \sa QXmlSimpleReader | ||
1737 | */ | ||
1738 | /*! | ||
1739 | \fn bool QXmlReader::feature( const QString& name, bool *ok ) const | ||
1740 | |||
1741 | If the reader has the feature \a name, this function returns the value of the | ||
1742 | feature. | ||
1743 | |||
1744 | If the reader has not the feature \a name, the return value may be anything. | ||
1745 | |||
1746 | If \a ok is not 0, then \a ok is set to TRUE if the reader has the feature | ||
1747 | \a name, otherwise \a ok is set to FALSE. | ||
1748 | |||
1749 | \sa setFeature() hasFeature() | ||
1750 | */ | ||
1751 | /*! | ||
1752 | \fn void QXmlReader::setFeature( const QString& name, bool value ) | ||
1753 | |||
1754 | Sets the feature \a name to \a value. If the reader has not the feature \a | ||
1755 | name, this value is ignored. | ||
1756 | |||
1757 | \sa feature() hasFeature() | ||
1758 | */ | ||
1759 | /*! | ||
1760 | \fn bool QXmlReader::hasFeature( const QString& name ) const | ||
1761 | |||
1762 | Returns \c TRUE if the reader has the feature \a name, otherwise FALSE. | ||
1763 | |||
1764 | \sa feature() setFeature() | ||
1765 | */ | ||
1766 | /*! | ||
1767 | \fn void* QXmlReader::property( const QString& name, bool *ok ) const | ||
1768 | |||
1769 | If the reader has the property \a name, this function returns the value of | ||
1770 | the property. | ||
1771 | |||
1772 | If the reader has not the property \a name, the return value is 0. | ||
1773 | |||
1774 | If \a ok is not 0, then \a ok is set to TRUE if the reader has the property | ||
1775 | \a name, otherwise \a ok is set to FALSE. | ||
1776 | |||
1777 | \sa setProperty() hasProperty() | ||
1778 | */ | ||
1779 | /*! | ||
1780 | \fn void QXmlReader::setProperty( const QString& name, void* value ) | ||
1781 | |||
1782 | Sets the property \a name to \a value. If the reader has not the property \a | ||
1783 | name, this value is ignored. | ||
1784 | |||
1785 | \sa property() hasProperty() | ||
1786 | */ | ||
1787 | /*! | ||
1788 | \fn bool QXmlReader::hasProperty( const QString& name ) const | ||
1789 | |||
1790 | Returns TRUE if the reader has the property \a name, otherwise FALSE. | ||
1791 | |||
1792 | \sa property() setProperty() | ||
1793 | */ | ||
1794 | /*! | ||
1795 | \fn void QXmlReader::setEntityResolver( QXmlEntityResolver* handler ) | ||
1796 | |||
1797 | Sets the entity resolver to \a handler. | ||
1798 | |||
1799 | \sa entityResolver() | ||
1800 | */ | ||
1801 | /*! | ||
1802 | \fn QXmlEntityResolver* QXmlReader::entityResolver() const | ||
1803 | |||
1804 | Returns the entity resolver or 0 if none was set. | ||
1805 | |||
1806 | \sa setEntityResolver() | ||
1807 | */ | ||
1808 | /*! | ||
1809 | \fn void QXmlReader::setDTDHandler( QXmlDTDHandler* handler ) | ||
1810 | |||
1811 | Sets the DTD handler to \a handler. | ||
1812 | |||
1813 | \sa DTDHandler() | ||
1814 | */ | ||
1815 | /*! | ||
1816 | \fn QXmlDTDHandler* QXmlReader::DTDHandler() const | ||
1817 | |||
1818 | Returns the DTD handler or 0 if none was set. | ||
1819 | |||
1820 | \sa setDTDHandler() | ||
1821 | */ | ||
1822 | /*! | ||
1823 | \fn void QXmlReader::setContentHandler( QXmlContentHandler* handler ) | ||
1824 | |||
1825 | Sets the content handler to \a handler. | ||
1826 | |||
1827 | \sa contentHandler() | ||
1828 | */ | ||
1829 | /*! | ||
1830 | \fn QXmlContentHandler* QXmlReader::contentHandler() const | ||
1831 | |||
1832 | Returns the content handler or 0 if none was set. | ||
1833 | |||
1834 | \sa setContentHandler() | ||
1835 | */ | ||
1836 | /*! | ||
1837 | \fn void QXmlReader::setErrorHandler( QXmlErrorHandler* handler ) | ||
1838 | |||
1839 | Sets the error handler to \a handler. | ||
1840 | |||
1841 | \sa errorHandler() | ||
1842 | */ | ||
1843 | /*! | ||
1844 | \fn QXmlErrorHandler* QXmlReader::errorHandler() const | ||
1845 | |||
1846 | Returns the error handler or 0 if none was set | ||
1847 | |||
1848 | \sa setErrorHandler() | ||
1849 | */ | ||
1850 | /*! | ||
1851 | \fn void QXmlReader::setLexicalHandler( QXmlLexicalHandler* handler ) | ||
1852 | |||
1853 | Sets the lexical handler to \a handler. | ||
1854 | |||
1855 | \sa lexicalHandler() | ||
1856 | */ | ||
1857 | /*! | ||
1858 | \fn QXmlLexicalHandler* QXmlReader::lexicalHandler() const | ||
1859 | |||
1860 | Returns the lexical handler or 0 if none was set. | ||
1861 | |||
1862 | \sa setLexicalHandler() | ||
1863 | */ | ||
1864 | /*! | ||
1865 | \fn void QXmlReader::setDeclHandler( QXmlDeclHandler* handler ) | ||
1866 | |||
1867 | Sets the declaration handler to \a handler. | ||
1868 | |||
1869 | \sa declHandler() | ||
1870 | */ | ||
1871 | /*! | ||
1872 | \fn QXmlDeclHandler* QXmlReader::declHandler() const | ||
1873 | |||
1874 | Returns the declaration handler or 0 if none was set. | ||
1875 | |||
1876 | \sa setDeclHandler() | ||
1877 | */ | ||
1878 | /*! | ||
1879 | \fn bool QXmlReader::parse( const QXmlInputSource& input ) | ||
1880 | |||
1881 | Parses the XML document \a input. Returns TRUE if the parsing was successful, | ||
1882 | otherwise FALSE. | ||
1883 | */ | ||
1884 | /*! | ||
1885 | \fn bool QXmlReader::parse( const QString& systemId ) | ||
1886 | |||
1887 | Parses the XML document at the location \a systemId. Returns TRUE if the | ||
1888 | parsing was successful, otherwise FALSE. | ||
1889 | */ | ||
1890 | |||
1891 | |||
1892 | /*! | ||
1893 | \class QXmlSimpleReader qxml.h | ||
1894 | \brief The QXmlSimpleReader class provides an implementation of a simple XML | ||
1895 | reader (i.e. parser). | ||
1896 | |||
1897 | \module XML | ||
1898 | |||
1899 | This XML reader is sufficient for simple parsing tasks. Here is a short list | ||
1900 | of the properties of this reader: | ||
1901 | <ul> | ||
1902 | <li> well-formed parser | ||
1903 | <li> does not parse any external entities | ||
1904 | <li> can do namespace processing | ||
1905 | </ul> | ||
1906 | |||
1907 | For getting started see also the | ||
1908 | <a href="xml-sax.html#quickStart">Quick start</a>. | ||
1909 | */ | ||
1910 | |||
1911 | //guaranteed not to be a characater | ||
1912 | const QChar QXmlSimpleReader::QEOF = QChar((ushort)0xffff); | ||
1913 | |||
1914 | /*! | ||
1915 | Constructs a simple XML reader. | ||
1916 | */ | ||
1917 | QXmlSimpleReader::QXmlSimpleReader() | ||
1918 | { | ||
1919 | d = new QXmlSimpleReaderPrivate(); | ||
1920 | d->locator = new QXmlLocator( this ); | ||
1921 | |||
1922 | entityRes = 0; | ||
1923 | dtdHnd = 0; | ||
1924 | contentHnd = 0; | ||
1925 | errorHnd = 0; | ||
1926 | lexicalHnd = 0; | ||
1927 | declHnd = 0; | ||
1928 | |||
1929 | // default feature settings | ||
1930 | d->useNamespaces = TRUE; | ||
1931 | d->useNamespacePrefixes = FALSE; | ||
1932 | d->reportWhitespaceCharData = TRUE; | ||
1933 | d->reportEntities = FALSE; | ||
1934 | } | ||
1935 | |||
1936 | /*! | ||
1937 | Destroys a simple XML reader. | ||
1938 | */ | ||
1939 | QXmlSimpleReader::~QXmlSimpleReader() | ||
1940 | { | ||
1941 | delete d->locator; | ||
1942 | delete d; | ||
1943 | } | ||
1944 | |||
1945 | /*! | ||
1946 | Gets the state of a feature. | ||
1947 | |||
1948 | \sa setFeature() hasFeature() | ||
1949 | */ | ||
1950 | bool QXmlSimpleReader::feature( const QString& name, bool *ok ) const | ||
1951 | { | ||
1952 | if ( ok != 0 ) | ||
1953 | *ok = TRUE; | ||
1954 | if ( name == "http://xml.org/sax/features/namespaces" ) { | ||
1955 | return d->useNamespaces; | ||
1956 | } else if ( name == "http://xml.org/sax/features/namespace-prefixes" ) { | ||
1957 | return d->useNamespacePrefixes; | ||
1958 | } else if ( name == "http://trolltech.com/xml/features/report-whitespace-only-CharData" ) { | ||
1959 | return d->reportWhitespaceCharData; | ||
1960 | } else if ( name == "http://trolltech.com/xml/features/report-start-end-entity" ) { | ||
1961 | return d->reportEntities; | ||
1962 | } else { | ||
1963 | qWarning( "Unknown feature " + name ); | ||
1964 | if ( ok != 0 ) | ||
1965 | *ok = FALSE; | ||
1966 | } | ||
1967 | return FALSE; | ||
1968 | } | ||
1969 | |||
1970 | /*! | ||
1971 | Sets the state of a feature. | ||
1972 | |||
1973 | Supported features are: | ||
1974 | <ul> | ||
1975 | <li> http://xml.org/sax/features/namespaces: | ||
1976 | if this feature is TRUE, namespace processing is performed | ||
1977 | <li> http://xml.org/sax/features/namespace-prefixes: | ||
1978 | if this feature is TRUE, the the original prefixed names and attributes | ||
1979 | used for namespace declarations are reported | ||
1980 | <li> http://trolltech.com/xml/features/report-whitespace-only-CharData: | ||
1981 | if this feature is TRUE, CharData that consists only of whitespace (and | ||
1982 | no other characters) is not reported via | ||
1983 | QXmlContentHandler::characters() | ||
1984 | </ul> | ||
1985 | |||
1986 | \sa feature() hasFeature() | ||
1987 | */ | ||
1988 | void QXmlSimpleReader::setFeature( const QString& name, bool value ) | ||
1989 | { | ||
1990 | if ( name == "http://xml.org/sax/features/namespaces" ) { | ||
1991 | d->useNamespaces = value; | ||
1992 | } else if ( name == "http://xml.org/sax/features/namespace-prefixes" ) { | ||
1993 | d->useNamespacePrefixes = value; | ||
1994 | } else if ( name == "http://trolltech.com/xml/features/report-whitespace-only-CharData" ) { | ||
1995 | d->reportWhitespaceCharData = value; | ||
1996 | } else if ( name == "http://trolltech.com/xml/features/report-start-end-entity" ) { | ||
1997 | d->reportEntities = value; | ||
1998 | } else { | ||
1999 | qWarning( "Unknown feature " + name ); | ||
2000 | } | ||
2001 | } | ||
2002 | |||
2003 | /*! | ||
2004 | Returns TRUE if the class has a feature named \a feature, otherwise FALSE. | ||
2005 | |||
2006 | \sa setFeature() feature() | ||
2007 | */ | ||
2008 | bool QXmlSimpleReader::hasFeature( const QString& name ) const | ||
2009 | { | ||
2010 | if ( name == "http://xml.org/sax/features/namespaces" || | ||
2011 | name == "http://xml.org/sax/features/namespace-prefixes" || | ||
2012 | name == "http://trolltech.com/xml/features/report-whitespace-only-CharData" ) { | ||
2013 | return TRUE; | ||
2014 | } else { | ||
2015 | return FALSE; | ||
2016 | } | ||
2017 | } | ||
2018 | |||
2019 | /*! | ||
2020 | Returns 0 since this class does not support any properties. | ||
2021 | */ | ||
2022 | void* QXmlSimpleReader::property( const QString&, bool *ok ) const | ||
2023 | { | ||
2024 | if ( ok != 0 ) | ||
2025 | *ok = FALSE; | ||
2026 | return 0; | ||
2027 | } | ||
2028 | |||
2029 | /*! | ||
2030 | Does nothing since this class does not support any properties. | ||
2031 | */ | ||
2032 | void QXmlSimpleReader::setProperty( const QString&, void* ) | ||
2033 | { | ||
2034 | } | ||
2035 | |||
2036 | /*! | ||
2037 | Returns FALSE since this class does not support any properties. | ||
2038 | */ | ||
2039 | bool QXmlSimpleReader::hasProperty( const QString& ) const | ||
2040 | { | ||
2041 | return FALSE; | ||
2042 | } | ||
2043 | |||
2044 | /*! \reimp */ | ||
2045 | void QXmlSimpleReader::setEntityResolver( QXmlEntityResolver* handler ) | ||
2046 | { entityRes = handler; } | ||
2047 | |||
2048 | /*! \reimp */ | ||
2049 | QXmlEntityResolver* QXmlSimpleReader::entityResolver() const | ||
2050 | { return entityRes; } | ||
2051 | |||
2052 | /*! \reimp */ | ||
2053 | void QXmlSimpleReader::setDTDHandler( QXmlDTDHandler* handler ) | ||
2054 | { dtdHnd = handler; } | ||
2055 | |||
2056 | /*! \reimp */ | ||
2057 | QXmlDTDHandler* QXmlSimpleReader::DTDHandler() const | ||
2058 | { return dtdHnd; } | ||
2059 | |||
2060 | /*! \reimp */ | ||
2061 | void QXmlSimpleReader::setContentHandler( QXmlContentHandler* handler ) | ||
2062 | { contentHnd = handler; } | ||
2063 | |||
2064 | /*! \reimp */ | ||
2065 | QXmlContentHandler* QXmlSimpleReader::contentHandler() const | ||
2066 | { return contentHnd; } | ||
2067 | |||
2068 | /*! \reimp */ | ||
2069 | void QXmlSimpleReader::setErrorHandler( QXmlErrorHandler* handler ) | ||
2070 | { errorHnd = handler; } | ||
2071 | |||
2072 | /*! \reimp */ | ||
2073 | QXmlErrorHandler* QXmlSimpleReader::errorHandler() const | ||
2074 | { return errorHnd; } | ||
2075 | |||
2076 | /*! \reimp */ | ||
2077 | void QXmlSimpleReader::setLexicalHandler( QXmlLexicalHandler* handler ) | ||
2078 | { lexicalHnd = handler; } | ||
2079 | |||
2080 | /*! \reimp */ | ||
2081 | QXmlLexicalHandler* QXmlSimpleReader::lexicalHandler() const | ||
2082 | { return lexicalHnd; } | ||
2083 | |||
2084 | /*! \reimp */ | ||
2085 | void QXmlSimpleReader::setDeclHandler( QXmlDeclHandler* handler ) | ||
2086 | { declHnd = handler; } | ||
2087 | |||
2088 | /*! \reimp */ | ||
2089 | QXmlDeclHandler* QXmlSimpleReader::declHandler() const | ||
2090 | { return declHnd; } | ||
2091 | |||
2092 | |||
2093 | |||
2094 | /*! \reimp */ | ||
2095 | bool QXmlSimpleReader::parse( const QXmlInputSource& input ) | ||
2096 | { | ||
2097 | init( input ); | ||
2098 | // call the handler | ||
2099 | if ( contentHnd ) { | ||
2100 | contentHnd->setDocumentLocator( d->locator ); | ||
2101 | if ( !contentHnd->startDocument() ) { | ||
2102 | d->error = contentHnd->errorString(); | ||
2103 | goto parseError; | ||
2104 | } | ||
2105 | } | ||
2106 | // parse prolog | ||
2107 | if ( !parseProlog() ) { | ||
2108 | d->error = XMLERR_ERRORPARSINGPROLOG; | ||
2109 | goto parseError; | ||
2110 | } | ||
2111 | // parse element | ||
2112 | if ( !parseElement() ) { | ||
2113 | d->error = XMLERR_ERRORPARSINGMAINELEMENT; | ||
2114 | goto parseError; | ||
2115 | } | ||
2116 | // parse Misc* | ||
2117 | while ( !atEnd() ) { | ||
2118 | if ( !parseMisc() ) { | ||
2119 | d->error = XMLERR_ERRORPARSINGMISC; | ||
2120 | goto parseError; | ||
2121 | } | ||
2122 | } | ||
2123 | // is stack empty? | ||
2124 | if ( !tags.isEmpty() ) { | ||
2125 | d->error = XMLERR_UNEXPECTEDEOF; | ||
2126 | goto parseError; | ||
2127 | } | ||
2128 | // call the handler | ||
2129 | if ( contentHnd ) { | ||
2130 | if ( !contentHnd->endDocument() ) { | ||
2131 | d->error = contentHnd->errorString(); | ||
2132 | goto parseError; | ||
2133 | } | ||
2134 | } | ||
2135 | |||
2136 | return TRUE; | ||
2137 | |||
2138 | // error handling | ||
2139 | |||
2140 | parseError: | ||
2141 | reportParseError(); | ||
2142 | tags.clear(); | ||
2143 | return FALSE; | ||
2144 | } | ||
2145 | |||
2146 | /*! | ||
2147 | Parses the prolog [22]. | ||
2148 | */ | ||
2149 | bool QXmlSimpleReader::parseProlog() | ||
2150 | { | ||
2151 | bool xmldecl_possible = TRUE; | ||
2152 | bool doctype_read = FALSE; | ||
2153 | |||
2154 | const signed char Init = 0; | ||
2155 | const signed char EatWS = 1; // eat white spaces | ||
2156 | const signed char Lt = 2; // '<' read | ||
2157 | const signed char Em = 3; // '!' read | ||
2158 | const signed char DocType = 4; // read doctype | ||
2159 | const signed char Comment = 5; // read comment | ||
2160 | const signed char PI = 6; // read PI | ||
2161 | const signed char Done = 7; | ||
2162 | |||
2163 | const signed char InpWs = 0; | ||
2164 | const signed char InpLt = 1; // < | ||
2165 | const signed char InpQm = 2; // ? | ||
2166 | const signed char InpEm = 3; // ! | ||
2167 | const signed char InpD = 4; // D | ||
2168 | const signed char InpDash = 5; // - | ||
2169 | const signed char InpUnknown = 6; | ||
2170 | |||
2171 | // use some kind of state machine for parsing | ||
2172 | static const signed char table[7][7] = { | ||
2173 | /* InpWs InpLt InpQm InpEm InpD InpDash InpUnknown */ | ||
2174 | { EatWS, Lt, -1, -1, -1, -1, -1 }, // Init | ||
2175 | { -1, Lt, -1, -1, -1, -1, -1 }, // EatWS | ||
2176 | { -1, -1, PI, Em, Done, -1, Done }, // Lt | ||
2177 | { -1, -1, -1, -1, DocType, Comment, -1 }, // Em | ||
2178 | { EatWS, Lt, -1, -1, -1, -1, -1 }, // DocType | ||
2179 | { EatWS, Lt, -1, -1, -1, -1, -1 }, // Comment | ||
2180 | { EatWS, Lt, -1, -1, -1, -1, -1 } // PI | ||
2181 | }; | ||
2182 | signed char state = Init; | ||
2183 | signed char input; | ||
2184 | bool parseOk = TRUE; | ||
2185 | |||
2186 | for (;;) { | ||
2187 | |||
2188 | // read input | ||
2189 | if ( atEnd() ) { | ||
2190 | d->error = XMLERR_UNEXPECTEDEOF; | ||
2191 | goto parseError; | ||
2192 | } | ||
2193 | if ( is_S(c) ) { | ||
2194 | input = InpWs; | ||
2195 | } else if ( c == '<' ) { | ||
2196 | input = InpLt; | ||
2197 | } else if ( c == '?' ) { | ||
2198 | input = InpQm; | ||
2199 | } else if ( c == '!' ) { | ||
2200 | input = InpEm; | ||
2201 | } else if ( c == 'D' ) { | ||
2202 | input = InpD; | ||
2203 | } else if ( c == '-' ) { | ||
2204 | input = InpDash; | ||
2205 | } else { | ||
2206 | input = InpUnknown; | ||
2207 | } | ||
2208 | // get new state | ||
2209 | state = table[state][input]; | ||
2210 | |||
2211 | // in some cases do special actions depending on state | ||
2212 | switch ( state ) { | ||
2213 | case EatWS: | ||
2214 | // XML declaration only on first position possible | ||
2215 | xmldecl_possible = FALSE; | ||
2216 | // eat white spaces | ||
2217 | eat_ws(); | ||
2218 | break; | ||
2219 | case Lt: | ||
2220 | // next character | ||
2221 | next(); | ||
2222 | break; | ||
2223 | case Em: | ||
2224 | // XML declaration only on first position possible | ||
2225 | xmldecl_possible = FALSE; | ||
2226 | // next character | ||
2227 | next(); | ||
2228 | break; | ||
2229 | case DocType: | ||
2230 | parseOk = parseDoctype(); | ||
2231 | break; | ||
2232 | case Comment: | ||
2233 | parseOk = parseComment(); | ||
2234 | break; | ||
2235 | case PI: | ||
2236 | parseOk = parsePI( xmldecl_possible ); | ||
2237 | break; | ||
2238 | } | ||
2239 | // no input is read after this | ||
2240 | switch ( state ) { | ||
2241 | case DocType: | ||
2242 | if ( !parseOk ) { | ||
2243 | d->error = XMLERR_ERRORPARSINGPROLOG; | ||
2244 | goto parseError; | ||
2245 | } | ||
2246 | if ( doctype_read ) { | ||
2247 | d->error = XMLERR_MORETHANONEDOCTYPE; | ||
2248 | goto parseError; | ||
2249 | } else { | ||
2250 | doctype_read = FALSE; | ||
2251 | } | ||
2252 | break; | ||
2253 | case Comment: | ||
2254 | if ( !parseOk ) { | ||
2255 | d->error = XMLERR_ERRORPARSINGPROLOG; | ||
2256 | goto parseError; | ||
2257 | } | ||
2258 | if ( lexicalHnd ) { | ||
2259 | if ( !lexicalHnd->comment( string() ) ) { | ||
2260 | d->error = lexicalHnd->errorString(); | ||
2261 | goto parseError; | ||
2262 | } | ||
2263 | } | ||
2264 | break; | ||
2265 | case PI: | ||
2266 | if ( !parseOk ) { | ||
2267 | d->error = XMLERR_ERRORPARSINGPROLOG; | ||
2268 | goto parseError; | ||
2269 | } | ||
2270 | // call the handler | ||
2271 | if ( contentHnd ) { | ||
2272 | if ( xmldecl_possible && !d->xmlVersion.isEmpty() ) { | ||
2273 | QString value( "version = '" ); | ||
2274 | value += d->xmlVersion; | ||
2275 | value += "'"; | ||
2276 | if ( !d->encoding.isEmpty() ) { | ||
2277 | value += " encoding = '"; | ||
2278 | value += d->encoding; | ||
2279 | value += "'"; | ||
2280 | } | ||
2281 | if ( d->standalone == QXmlSimpleReaderPrivate::Yes ) { | ||
2282 | value += " standalone = 'yes'"; | ||
2283 | } else if ( d->standalone == QXmlSimpleReaderPrivate::No ) { | ||
2284 | value += " standalone = 'no'"; | ||
2285 | } | ||
2286 | if ( !contentHnd->processingInstruction( "xml", value ) ) { | ||
2287 | d->error = contentHnd->errorString(); | ||
2288 | goto parseError; | ||
2289 | } | ||
2290 | } else { | ||
2291 | if ( !contentHnd->processingInstruction( name(), string() ) ) { | ||
2292 | d->error = contentHnd->errorString(); | ||
2293 | goto parseError; | ||
2294 | } | ||
2295 | } | ||
2296 | } | ||
2297 | // XML declaration only on first position possible | ||
2298 | xmldecl_possible = FALSE; | ||
2299 | break; | ||
2300 | case Done: | ||
2301 | return TRUE; | ||
2302 | case -1: | ||
2303 | d->error = XMLERR_ERRORPARSINGELEMENT; | ||
2304 | goto parseError; | ||
2305 | } | ||
2306 | |||
2307 | } | ||
2308 | |||
2309 | return TRUE; | ||
2310 | |||
2311 | parseError: | ||
2312 | reportParseError(); | ||
2313 | return FALSE; | ||
2314 | } | ||
2315 | |||
2316 | /*! | ||
2317 | Parse an element [39]. | ||
2318 | |||
2319 | Precondition: the opening '<' is already read. | ||
2320 | */ | ||
2321 | bool QXmlSimpleReader::parseElement() | ||
2322 | { | ||
2323 | QString uri, lname, prefix; | ||
2324 | bool t; | ||
2325 | |||
2326 | const signed char Init = 0; | ||
2327 | const signed char ReadName = 1; | ||
2328 | const signed char Ws1 = 2; | ||
2329 | const signed char STagEnd = 3; | ||
2330 | const signed char STagEnd2 = 4; | ||
2331 | const signed char ETagBegin = 5; | ||
2332 | const signed char ETagBegin2 = 6; | ||
2333 | const signed char Ws2 = 7; | ||
2334 | const signed char EmptyTag = 8; | ||
2335 | const signed char Attribute = 9; | ||
2336 | const signed char Ws3 = 10; | ||
2337 | const signed char Done = 11; | ||
2338 | |||
2339 | const signed char InpWs = 0; // whitespace | ||
2340 | const signed char InpNameBe = 1; // is_NameBeginning() | ||
2341 | const signed char InpGt = 2; // > | ||
2342 | const signed char InpSlash = 3; // / | ||
2343 | const signed char InpUnknown = 4; | ||
2344 | |||
2345 | // use some kind of state machine for parsing | ||
2346 | static const signed char table[11][5] = { | ||
2347 | /* InpWs InpNameBe InpGt InpSlash InpUnknown */ | ||
2348 | { -1, ReadName, -1, -1, -1 }, // Init | ||
2349 | { Ws1, Attribute, STagEnd, EmptyTag, -1 }, // ReadName | ||
2350 | { -1, Attribute, STagEnd, EmptyTag, -1 }, // Ws1 | ||
2351 | { STagEnd2, STagEnd2, STagEnd2, STagEnd2, STagEnd2 }, // STagEnd | ||
2352 | { -1, -1, -1, ETagBegin, -1 }, // STagEnd2 | ||
2353 | { -1, ETagBegin2, -1, -1, -1 }, // ETagBegin | ||
2354 | { Ws2, -1, Done, -1, -1 }, // ETagBegin2 | ||
2355 | { -1, -1, Done, -1, -1 }, // Ws2 | ||
2356 | { -1, -1, Done, -1, -1 }, // EmptyTag | ||
2357 | { Ws3, Attribute, STagEnd, EmptyTag, -1 }, // Attribute | ||
2358 | { -1, Attribute, STagEnd, EmptyTag, -1 } // Ws3 | ||
2359 | }; | ||
2360 | signed char state = Init; | ||
2361 | signed char input; | ||
2362 | bool parseOk = TRUE; | ||
2363 | |||
2364 | for (;;) { | ||
2365 | |||
2366 | // read input | ||
2367 | if ( atEnd() ) { | ||
2368 | d->error = XMLERR_UNEXPECTEDEOF; | ||
2369 | goto parseError; | ||
2370 | } | ||
2371 | if ( is_S(c) ) { | ||
2372 | input = InpWs; | ||
2373 | } else if ( is_NameBeginning(c) ) { | ||
2374 | input = InpNameBe; | ||
2375 | } else if ( c == '>' ) { | ||
2376 | input = InpGt; | ||
2377 | } else if ( c == '/' ) { | ||
2378 | input = InpSlash; | ||
2379 | } else { | ||
2380 | input = InpUnknown; | ||
2381 | } | ||
2382 | // get new state | ||
2383 | //qDebug( "%d -%d(%c)-> %d", state, input, c.latin1(), table[state][input] ); | ||
2384 | state = table[state][input]; | ||
2385 | |||
2386 | // in some cases do special actions depending on state | ||
2387 | switch ( state ) { | ||
2388 | case ReadName: | ||
2389 | parseOk = parseName(); | ||
2390 | break; | ||
2391 | case Ws1: | ||
2392 | case Ws2: | ||
2393 | case Ws3: | ||
2394 | eat_ws(); | ||
2395 | break; | ||
2396 | case STagEnd: | ||
2397 | // call the handler | ||
2398 | if ( contentHnd ) { | ||
2399 | if ( d->useNamespaces ) { | ||
2400 | d->namespaceSupport.processName( tags.top(), FALSE, uri, lname ); | ||
2401 | t = contentHnd->startElement( uri, lname, tags.top(), d->attList ); | ||
2402 | } else { | ||
2403 | t = contentHnd->startElement( "", "", tags.top(), d->attList ); | ||
2404 | } | ||
2405 | if ( !t ) { | ||
2406 | d->error = contentHnd->errorString(); | ||
2407 | goto parseError; | ||
2408 | } | ||
2409 | } | ||
2410 | next(); | ||
2411 | break; | ||
2412 | case STagEnd2: | ||
2413 | parseOk = parseContent(); | ||
2414 | break; | ||
2415 | case ETagBegin: | ||
2416 | next(); | ||
2417 | break; | ||
2418 | case ETagBegin2: | ||
2419 | // get the name of the tag | ||
2420 | parseOk = parseName(); | ||
2421 | break; | ||
2422 | case EmptyTag: | ||
2423 | if ( tags.isEmpty() ) { | ||
2424 | d->error = XMLERR_TAGMISMATCH; | ||
2425 | goto parseError; | ||
2426 | } | ||
2427 | if ( !parseElementEmptyTag( t, uri, lname ) ) | ||
2428 | goto parseError; | ||
2429 | // next character | ||
2430 | next(); | ||
2431 | break; | ||
2432 | case Attribute: | ||
2433 | // get name and value of attribute | ||
2434 | parseOk = parseAttribute(); | ||
2435 | break; | ||
2436 | case Done: | ||
2437 | next(); | ||
2438 | break; | ||
2439 | } | ||
2440 | // no input is read after this | ||
2441 | switch ( state ) { | ||
2442 | case ReadName: | ||
2443 | if ( !parseOk ) { | ||
2444 | d->error = XMLERR_ERRORPARSINGNAME; | ||
2445 | goto parseError; | ||
2446 | } | ||
2447 | // store it on the stack | ||
2448 | tags.push( name() ); | ||
2449 | // empty the attributes | ||
2450 | d->attList.qnameList.clear(); | ||
2451 | d->attList.uriList.clear(); | ||
2452 | d->attList.localnameList.clear(); | ||
2453 | d->attList.valueList.clear(); | ||
2454 | // namespace support? | ||
2455 | if ( d->useNamespaces ) { | ||
2456 | d->namespaceSupport.pushContext(); | ||
2457 | } | ||
2458 | break; | ||
2459 | case STagEnd2: | ||
2460 | if ( !parseOk ) { | ||
2461 | d->error = XMLERR_ERRORPARSINGCONTENT; | ||
2462 | goto parseError; | ||
2463 | } | ||
2464 | break; | ||
2465 | case ETagBegin2: | ||
2466 | if ( !parseOk ) { | ||
2467 | d->error = XMLERR_ERRORPARSINGNAME; | ||
2468 | goto parseError; | ||
2469 | } | ||
2470 | if ( !parseElementETagBegin2() ) | ||
2471 | goto parseError; | ||
2472 | break; | ||
2473 | case Attribute: | ||
2474 | if ( !parseOk ) { | ||
2475 | d->error = XMLERR_ERRORPARSINGATTRIBUTE; | ||
2476 | goto parseError; | ||
2477 | } | ||
2478 | if ( !parseElementAttribute( prefix, uri, lname ) ) | ||
2479 | goto parseError; | ||
2480 | break; | ||
2481 | case Done: | ||
2482 | return TRUE; | ||
2483 | case -1: | ||
2484 | d->error = XMLERR_ERRORPARSINGELEMENT; | ||
2485 | goto parseError; | ||
2486 | } | ||
2487 | |||
2488 | } | ||
2489 | |||
2490 | return TRUE; | ||
2491 | |||
2492 | parseError: | ||
2493 | reportParseError(); | ||
2494 | return FALSE; | ||
2495 | } | ||
2496 | /*! | ||
2497 | Helper to break down the size of the code in the case statement. | ||
2498 | Return FALSE on error, otherwise TRUE. | ||
2499 | */ | ||
2500 | // ### Remove t argument in Qt 3.0 -- I don't need it. The same should be true for uri and lname. | ||
2501 | bool QXmlSimpleReader::parseElementEmptyTag( bool &, QString &uri, QString &lname ) | ||
2502 | { | ||
2503 | // pop the stack and call the handler | ||
2504 | if ( contentHnd ) { | ||
2505 | if ( d->useNamespaces ) { | ||
2506 | // report startElement first... | ||
2507 | d->namespaceSupport.processName( tags.top(), FALSE, uri, lname ); | ||
2508 | if ( !contentHnd->startElement( uri, lname, tags.top(), d->attList ) ) { | ||
2509 | goto error; | ||
2510 | } | ||
2511 | // ... followed by endElement... | ||
2512 | if ( !contentHnd->endElement( uri, lname, tags.pop() ) ) { | ||
2513 | goto error; | ||
2514 | } | ||
2515 | // ... followed by endPrefixMapping | ||
2516 | QStringList prefixesBefore, prefixesAfter; | ||
2517 | if ( contentHnd ) { | ||
2518 | prefixesBefore = d->namespaceSupport.prefixes(); | ||
2519 | } | ||
2520 | d->namespaceSupport.popContext(); | ||
2521 | // call the handler for prefix mapping | ||
2522 | prefixesAfter = d->namespaceSupport.prefixes(); | ||
2523 | for ( QStringList::Iterator it = prefixesBefore.begin(); it != prefixesBefore.end(); ++it ) { | ||
2524 | if ( prefixesAfter.contains(*it) == 0 ) { | ||
2525 | if ( !contentHnd->endPrefixMapping( *it ) ) { | ||
2526 | goto error; | ||
2527 | } | ||
2528 | } | ||
2529 | } | ||
2530 | } else { | ||
2531 | // report startElement first... | ||
2532 | if ( !contentHnd->startElement( "", "", tags.top(), d->attList ) ) { | ||
2533 | goto error; | ||
2534 | } | ||
2535 | // ... followed by endElement | ||
2536 | if ( !contentHnd->endElement( "","",tags.pop() ) ) { | ||
2537 | goto error; | ||
2538 | } | ||
2539 | } | ||
2540 | } else { | ||
2541 | tags.pop(); | ||
2542 | d->namespaceSupport.popContext(); | ||
2543 | } | ||
2544 | return TRUE; | ||
2545 | error: | ||
2546 | d->error = contentHnd->errorString(); | ||
2547 | return FALSE; | ||
2548 | } | ||
2549 | /*! | ||
2550 | Helper to break down the size of the code in the case statement. | ||
2551 | Return FALSE on error, otherwise TRUE. | ||
2552 | */ | ||
2553 | bool QXmlSimpleReader::parseElementETagBegin2() | ||
2554 | { | ||
2555 | |||
2556 | // pop the stack and compare it with the name | ||
2557 | if ( tags.pop() != name() ) { | ||
2558 | d->error = XMLERR_TAGMISMATCH; | ||
2559 | return FALSE; | ||
2560 | } | ||
2561 | // call the handler | ||
2562 | if ( contentHnd ) { | ||
2563 | if ( d->useNamespaces ) { | ||
2564 | QString uri, lname; | ||
2565 | d->namespaceSupport.processName( name(), FALSE, uri, lname ); | ||
2566 | if ( !contentHnd->endElement( uri, lname, name() ) ) { | ||
2567 | d->error = contentHnd->errorString(); | ||
2568 | return FALSE; | ||
2569 | } | ||
2570 | } else { | ||
2571 | if ( !contentHnd->endElement("","",name()) ) { | ||
2572 | d->error = contentHnd->errorString(); | ||
2573 | return FALSE; | ||
2574 | } | ||
2575 | } | ||
2576 | } | ||
2577 | if ( d->useNamespaces ) { | ||
2578 | QStringList prefixesBefore, prefixesAfter; | ||
2579 | if ( contentHnd ) { | ||
2580 | prefixesBefore = d->namespaceSupport.prefixes(); | ||
2581 | } | ||
2582 | d->namespaceSupport.popContext(); | ||
2583 | // call the handler for prefix mapping | ||
2584 | if ( contentHnd ) { | ||
2585 | prefixesAfter = d->namespaceSupport.prefixes(); | ||
2586 | for ( QStringList::Iterator it = prefixesBefore.begin(); it != prefixesBefore.end(); ++it ) { | ||
2587 | if ( prefixesAfter.contains(*it) == 0 ) { | ||
2588 | if ( !contentHnd->endPrefixMapping( *it ) ) { | ||
2589 | d->error = contentHnd->errorString(); | ||
2590 | return FALSE; | ||
2591 | } | ||
2592 | } | ||
2593 | } | ||
2594 | } | ||
2595 | } | ||
2596 | return TRUE; | ||
2597 | } | ||
2598 | /*! | ||
2599 | Helper to break down the size of the code in the case statement. | ||
2600 | Return FALSE on error, otherwise TRUE. | ||
2601 | */ | ||
2602 | // ### Remove arguments in Qt 3.0? I think, I don't need them. | ||
2603 | bool QXmlSimpleReader::parseElementAttribute( QString &prefix, QString &uri, QString &lname ) | ||
2604 | { | ||
2605 | // add the attribute to the list | ||
2606 | if ( d->useNamespaces ) { | ||
2607 | // is it a namespace declaration? | ||
2608 | d->namespaceSupport.splitName( name(), prefix, lname ); | ||
2609 | if ( prefix == "xmlns" ) { | ||
2610 | // namespace declaration | ||
2611 | d->namespaceSupport.setPrefix( lname, string() ); | ||
2612 | if ( d->useNamespacePrefixes ) { | ||
2613 | d->attList.qnameList.append( name() ); | ||
2614 | d->attList.uriList.append( "" ); | ||
2615 | d->attList.localnameList.append( "" ); | ||
2616 | d->attList.valueList.append( string() ); | ||
2617 | } | ||
2618 | // call the handler for prefix mapping | ||
2619 | if ( contentHnd ) { | ||
2620 | if ( !contentHnd->startPrefixMapping( lname, string() ) ) { | ||
2621 | d->error = contentHnd->errorString(); | ||
2622 | return FALSE; | ||
2623 | } | ||
2624 | } | ||
2625 | } else { | ||
2626 | // no namespace delcaration | ||
2627 | d->namespaceSupport.processName( name(), TRUE, uri, lname ); | ||
2628 | d->attList.qnameList.append( name() ); | ||
2629 | d->attList.uriList.append( uri ); | ||
2630 | d->attList.localnameList.append( lname ); | ||
2631 | d->attList.valueList.append( string() ); | ||
2632 | } | ||
2633 | } else { | ||
2634 | // no namespace support | ||
2635 | d->attList.qnameList.append( name() ); | ||
2636 | d->attList.uriList.append( "" ); | ||
2637 | d->attList.localnameList.append( "" ); | ||
2638 | d->attList.valueList.append( string() ); | ||
2639 | } | ||
2640 | return TRUE; | ||
2641 | } | ||
2642 | |||
2643 | /*! | ||
2644 | Parse a content [43]. | ||
2645 | |||
2646 | A content is only used between tags. If a end tag is found the < is already | ||
2647 | read and the head stand on the '/' of the end tag '</name>'. | ||
2648 | */ | ||
2649 | bool QXmlSimpleReader::parseContent() | ||
2650 | { | ||
2651 | bool charDataRead = FALSE; | ||
2652 | |||
2653 | const signed char Init = 0; | ||
2654 | const signed char ChD = 1; // CharData | ||
2655 | const signed char ChD1 = 2; // CharData help state | ||
2656 | const signed char ChD2 = 3; // CharData help state | ||
2657 | const signed char Ref = 4; // Reference | ||
2658 | const signed char Lt = 5; // '<' read | ||
2659 | const signed char PI = 6; // PI | ||
2660 | const signed char Elem = 7; // Element | ||
2661 | const signed char Em = 8; // '!' read | ||
2662 | const signed char Com = 9; // Comment | ||
2663 | const signed char CDS = 10; // CDSect | ||
2664 | const signed char CDS1 = 11; // read a CDSect | ||
2665 | const signed char CDS2 = 12; // read a CDSect (help state) | ||
2666 | const signed char CDS3 = 13; // read a CDSect (help state) | ||
2667 | const signed char Done = 14; // finished reading content | ||
2668 | |||
2669 | const signed char InpLt = 0; // < | ||
2670 | const signed char InpGt = 1; // > | ||
2671 | const signed char InpSlash = 2; // / | ||
2672 | const signed char InpQMark = 3; // ? | ||
2673 | const signed char InpEMark = 4; // ! | ||
2674 | const signed char InpAmp = 5; // & | ||
2675 | const signed char InpDash = 6; // - | ||
2676 | const signed char InpOpenB = 7; // [ | ||
2677 | const signed char InpCloseB = 8; // ] | ||
2678 | const signed char InpUnknown = 9; | ||
2679 | |||
2680 | static const signed char mapCLT2FSMChar[] = { | ||
2681 | InpUnknown, // white space | ||
2682 | InpUnknown, // % | ||
2683 | InpAmp, // & | ||
2684 | InpGt, // > | ||
2685 | InpLt, // < | ||
2686 | InpSlash, // / | ||
2687 | InpQMark, // ? | ||
2688 | InpEMark, // ! | ||
2689 | InpDash, // - | ||
2690 | InpCloseB, // ] | ||
2691 | InpOpenB, // [ | ||
2692 | InpUnknown, // = | ||
2693 | InpUnknown, // " | ||
2694 | InpUnknown, // ' | ||
2695 | InpUnknown // unknown | ||
2696 | }; | ||
2697 | |||
2698 | // use some kind of state machine for parsing | ||
2699 | static const signed char table[14][10] = { | ||
2700 | /* InpLt InpGt InpSlash InpQMark InpEMark InpAmp InpDash InpOpenB InpCloseB InpUnknown */ | ||
2701 | { Lt, ChD, ChD, ChD, ChD, Ref, ChD, ChD, ChD1, ChD }, // Init | ||
2702 | { Lt, ChD, ChD, ChD, ChD, Ref, ChD, ChD, ChD1, ChD }, // ChD | ||
2703 | { Lt, ChD, ChD, ChD, ChD, Ref, ChD, ChD, ChD2, ChD }, // ChD1 | ||
2704 | { Lt, -1, ChD, ChD, ChD, Ref, ChD, ChD, ChD2, ChD }, // ChD2 | ||
2705 | { Lt, ChD, ChD, ChD, ChD, Ref, ChD, ChD, ChD, ChD }, // Ref (same as Init) | ||
2706 | { -1, -1, Done, PI, Em, -1, -1, -1, -1, Elem }, // Lt | ||
2707 | { Lt, ChD, ChD, ChD, ChD, Ref, ChD, ChD, ChD, ChD }, // PI (same as Init) | ||
2708 | { Lt, ChD, ChD, ChD, ChD, Ref, ChD, ChD, ChD, ChD }, // Elem (same as Init) | ||
2709 | { -1, -1, -1, -1, -1, -1, Com, CDS, -1, -1 }, // Em | ||
2710 | { Lt, ChD, ChD, ChD, ChD, Ref, ChD, ChD, ChD, ChD }, // Com (same as Init) | ||
2711 | { CDS1, CDS1, CDS1, CDS1, CDS1, CDS1, CDS1, CDS1, CDS2, CDS1 }, // CDS | ||
2712 | { CDS1, CDS1, CDS1, CDS1, CDS1, CDS1, CDS1, CDS1, CDS2, CDS1 }, // CDS1 | ||
2713 | { CDS1, CDS1, CDS1, CDS1, CDS1, CDS1, CDS1, CDS1, CDS3, CDS1 }, // CDS2 | ||
2714 | { CDS1, Init, CDS1, CDS1, CDS1, CDS1, CDS1, CDS1, CDS3, CDS1 } // CDS3 | ||
2715 | }; | ||
2716 | signed char state = Init; | ||
2717 | signed char input; | ||
2718 | bool parseOk = TRUE; | ||
2719 | |||
2720 | for (;;) { | ||
2721 | |||
2722 | // get input (use lookup-table instead of nested ifs for performance | ||
2723 | // reasons) | ||
2724 | if ( atEnd() ) { | ||
2725 | d->error = XMLERR_UNEXPECTEDEOF; | ||
2726 | goto parseError; | ||
2727 | } | ||
2728 | if ( c.row() ) { | ||
2729 | input = InpUnknown; | ||
2730 | } else { | ||
2731 | input = mapCLT2FSMChar[ charLookupTable[ c.cell() ] ]; | ||
2732 | } | ||
2733 | |||
2734 | // set state according to input | ||
2735 | state = table[state][input]; | ||
2736 | |||
2737 | // do some actions according to state | ||
2738 | switch ( state ) { | ||
2739 | case Init: | ||
2740 | // next character | ||
2741 | next(); | ||
2742 | break; | ||
2743 | case ChD: | ||
2744 | // on first call: clear string | ||
2745 | if ( !charDataRead ) { | ||
2746 | charDataRead = TRUE; | ||
2747 | stringClear(); | ||
2748 | } | ||
2749 | stringAddC(); | ||
2750 | next(); | ||
2751 | break; | ||
2752 | case ChD1: | ||
2753 | // on first call: clear string | ||
2754 | if ( !charDataRead ) { | ||
2755 | charDataRead = TRUE; | ||
2756 | stringClear(); | ||
2757 | } | ||
2758 | stringAddC(); | ||
2759 | next(); | ||
2760 | break; | ||
2761 | case ChD2: | ||
2762 | stringAddC(); | ||
2763 | next(); | ||
2764 | break; | ||
2765 | case Ref: | ||
2766 | if ( !charDataRead) { | ||
2767 | // reference may be CharData; so clear string to be safe | ||
2768 | stringClear(); | ||
2769 | parseOk = parseReference( charDataRead, InContent ); | ||
2770 | } else { | ||
2771 | if ( d->reportEntities ) { | ||
2772 | // this is undocumented so far; do this right in Qt 3.0 | ||
2773 | if ( contentHnd ) { | ||
2774 | if ( d->reportWhitespaceCharData || !string().simplifyWhiteSpace().isEmpty() ) { | ||
2775 | if ( !contentHnd->characters( string() ) ) { | ||
2776 | d->error = contentHnd->errorString(); | ||
2777 | goto parseError; | ||
2778 | } | ||
2779 | } | ||
2780 | } | ||
2781 | stringClear(); | ||
2782 | } | ||
2783 | bool tmp; | ||
2784 | parseOk = parseReference( tmp, InContent ); | ||
2785 | } | ||
2786 | break; | ||
2787 | case Lt: | ||
2788 | // call the handler for CharData | ||
2789 | if ( contentHnd ) { | ||
2790 | if ( charDataRead ) { | ||
2791 | if ( d->reportWhitespaceCharData || !string().simplifyWhiteSpace().isEmpty() ) { | ||
2792 | if ( !contentHnd->characters( string() ) ) { | ||
2793 | d->error = contentHnd->errorString(); | ||
2794 | goto parseError; | ||
2795 | } | ||
2796 | } | ||
2797 | } | ||
2798 | } | ||
2799 | charDataRead = FALSE; | ||
2800 | // next character | ||
2801 | next(); | ||
2802 | break; | ||
2803 | case PI: | ||
2804 | parseOk = parsePI(); | ||
2805 | break; | ||
2806 | case Elem: | ||
2807 | parseOk = parseElement(); | ||
2808 | break; | ||
2809 | case Em: | ||
2810 | // next character | ||
2811 | next(); | ||
2812 | break; | ||
2813 | case Com: | ||
2814 | parseOk = parseComment(); | ||
2815 | break; | ||
2816 | case CDS: | ||
2817 | parseOk = parseString( "[CDATA[" ); | ||
2818 | break; | ||
2819 | case CDS1: | ||
2820 | // read one character and add it | ||
2821 | stringAddC(); | ||
2822 | next(); | ||
2823 | break; | ||
2824 | case CDS2: | ||
2825 | // skip ']' | ||
2826 | next(); | ||
2827 | break; | ||
2828 | case CDS3: | ||
2829 | // skip ']'... | ||
2830 | next(); | ||
2831 | break; | ||
2832 | } | ||
2833 | // no input is read after this | ||
2834 | switch ( state ) { | ||
2835 | case Ref: | ||
2836 | if ( !parseOk ) { | ||
2837 | d->error = XMLERR_ERRORPARSINGREFERENCE; | ||
2838 | goto parseError; | ||
2839 | } | ||
2840 | break; | ||
2841 | case PI: | ||
2842 | if ( !parseOk ) { | ||
2843 | d->error = XMLERR_ERRORPARSINGPI; | ||
2844 | goto parseError; | ||
2845 | } | ||
2846 | // call the handler | ||
2847 | if ( contentHnd ) { | ||
2848 | if ( !contentHnd->processingInstruction(name(),string()) ) { | ||
2849 | d->error = contentHnd->errorString(); | ||
2850 | goto parseError; | ||
2851 | } | ||
2852 | } | ||
2853 | break; | ||
2854 | case Elem: | ||
2855 | if ( !parseOk ) { | ||
2856 | d->error = XMLERR_ERRORPARSINGELEMENT; | ||
2857 | goto parseError; | ||
2858 | } | ||
2859 | break; | ||
2860 | case Com: | ||
2861 | if ( !parseOk ) { | ||
2862 | d->error = XMLERR_ERRORPARSINGCOMMENT; | ||
2863 | goto parseError; | ||
2864 | } | ||
2865 | if ( lexicalHnd ) { | ||
2866 | if ( !lexicalHnd->comment( string() ) ) { | ||
2867 | d->error = lexicalHnd->errorString(); | ||
2868 | goto parseError; | ||
2869 | } | ||
2870 | } | ||
2871 | break; | ||
2872 | case CDS: | ||
2873 | if( !parseOk ) { | ||
2874 | d->error = XMLERR_CDSECTHEADEREXPECTED; | ||
2875 | goto parseError; | ||
2876 | } | ||
2877 | // empty string | ||
2878 | stringClear(); | ||
2879 | break; | ||
2880 | case CDS2: | ||
2881 | if (c != ']') { | ||
2882 | stringAddC( ']' ); | ||
2883 | } | ||
2884 | break; | ||
2885 | case CDS3: | ||
2886 | // test if this skipping was legal | ||
2887 | if ( c == '>' ) { | ||
2888 | // the end of the CDSect | ||
2889 | if ( lexicalHnd ) { | ||
2890 | if ( !lexicalHnd->startCDATA() ) { | ||
2891 | d->error = lexicalHnd->errorString(); | ||
2892 | goto parseError; | ||
2893 | } | ||
2894 | } | ||
2895 | if ( contentHnd ) { | ||
2896 | if ( !contentHnd->characters( string() ) ) { | ||
2897 | d->error = contentHnd->errorString(); | ||
2898 | goto parseError; | ||
2899 | } | ||
2900 | } | ||
2901 | if ( lexicalHnd ) { | ||
2902 | if ( !lexicalHnd->endCDATA() ) { | ||
2903 | d->error = lexicalHnd->errorString(); | ||
2904 | goto parseError; | ||
2905 | } | ||
2906 | } | ||
2907 | } else if (c == ']') { | ||
2908 | // three or more ']' | ||
2909 | stringAddC( ']' ); | ||
2910 | } else { | ||
2911 | // after ']]' comes another character | ||
2912 | stringAddC( ']' ); | ||
2913 | stringAddC( ']' ); | ||
2914 | } | ||
2915 | break; | ||
2916 | case Done: | ||
2917 | // call the handler for CharData | ||
2918 | if ( contentHnd ) { | ||
2919 | if ( charDataRead ) { | ||
2920 | if ( d->reportWhitespaceCharData || !string().simplifyWhiteSpace().isEmpty() ) { | ||
2921 | if ( !contentHnd->characters( string() ) ) { | ||
2922 | d->error = contentHnd->errorString(); | ||
2923 | goto parseError; | ||
2924 | } | ||
2925 | } | ||
2926 | } | ||
2927 | } | ||
2928 | // Done | ||
2929 | return TRUE; | ||
2930 | case -1: | ||
2931 | // Error | ||
2932 | d->error = XMLERR_ERRORPARSINGCONTENT; | ||
2933 | goto parseError; | ||
2934 | } | ||
2935 | |||
2936 | } | ||
2937 | |||
2938 | return TRUE; | ||
2939 | |||
2940 | parseError: | ||
2941 | reportParseError(); | ||
2942 | return FALSE; | ||
2943 | } | ||
2944 | |||
2945 | /*! | ||
2946 | Parse Misc [27]. | ||
2947 | */ | ||
2948 | bool QXmlSimpleReader::parseMisc() | ||
2949 | { | ||
2950 | const signed char Init = 0; | ||
2951 | const signed char Lt = 1; // '<' was read | ||
2952 | const signed char Comment = 2; // read comment | ||
2953 | const signed char eatWS = 3; // eat whitespaces | ||
2954 | const signed char PI = 4; // read PI | ||
2955 | const signed char Comment2 = 5; // read comment | ||
2956 | |||
2957 | const signed char InpWs = 0; // S | ||
2958 | const signed char InpLt = 1; // < | ||
2959 | const signed char InpQm = 2; // ? | ||
2960 | const signed char InpEm = 3; // ! | ||
2961 | const signed char InpUnknown = 4; | ||
2962 | |||
2963 | // use some kind of state machine for parsing | ||
2964 | static const signed char table[3][5] = { | ||
2965 | /* InpWs InpLt InpQm InpEm InpUnknown */ | ||
2966 | { eatWS, Lt, -1, -1, -1 }, // Init | ||
2967 | { -1, -1, PI, Comment, -1 }, // Lt | ||
2968 | { -1, -1, -1, -1, Comment2 } // Comment | ||
2969 | }; | ||
2970 | signed char state = Init; | ||
2971 | signed char input; | ||
2972 | bool parseOk = TRUE; | ||
2973 | |||
2974 | for (;;) { | ||
2975 | |||
2976 | // get input | ||
2977 | if ( atEnd() ) { | ||
2978 | d->error = XMLERR_UNEXPECTEDEOF; | ||
2979 | goto parseError; | ||
2980 | } | ||
2981 | if ( is_S(c) ) { | ||
2982 | input = InpWs; | ||
2983 | } else if ( c == '<' ) { | ||
2984 | input = InpLt; | ||
2985 | } else if ( c == '?' ) { | ||
2986 | input = InpQm; | ||
2987 | } else if ( c == '!' ) { | ||
2988 | input = InpEm; | ||
2989 | } else { | ||
2990 | input = InpUnknown; | ||
2991 | } | ||
2992 | |||
2993 | // set state according to input | ||
2994 | state = table[state][input]; | ||
2995 | |||
2996 | // do some actions according to state | ||
2997 | switch ( state ) { | ||
2998 | case eatWS: | ||
2999 | eat_ws(); | ||
3000 | break; | ||
3001 | case Lt: | ||
3002 | next(); | ||
3003 | break; | ||
3004 | case PI: | ||
3005 | parseOk = parsePI(); | ||
3006 | break; | ||
3007 | case Comment: | ||
3008 | next(); | ||
3009 | break; | ||
3010 | case Comment2: | ||
3011 | parseOk = parseComment(); | ||
3012 | break; | ||
3013 | } | ||
3014 | // no input is read after this | ||
3015 | switch ( state ) { | ||
3016 | case eatWS: | ||
3017 | return TRUE; | ||
3018 | case PI: | ||
3019 | if ( !parseOk ) { | ||
3020 | d->error = XMLERR_ERRORPARSINGPI; | ||
3021 | goto parseError; | ||
3022 | } | ||
3023 | if ( contentHnd ) { | ||
3024 | if ( !contentHnd->processingInstruction(name(),string()) ) { | ||
3025 | d->error = contentHnd->errorString(); | ||
3026 | goto parseError; | ||
3027 | } | ||
3028 | } | ||
3029 | return TRUE; | ||
3030 | case Comment2: | ||
3031 | if ( !parseOk ) { | ||
3032 | d->error = XMLERR_ERRORPARSINGCOMMENT; | ||
3033 | goto parseError; | ||
3034 | } | ||
3035 | if ( lexicalHnd ) { | ||
3036 | if ( !lexicalHnd->comment( string() ) ) { | ||
3037 | d->error = lexicalHnd->errorString(); | ||
3038 | goto parseError; | ||
3039 | } | ||
3040 | } | ||
3041 | return TRUE; | ||
3042 | case -1: | ||
3043 | // Error | ||
3044 | d->error = XMLERR_UNEXPECTEDCHARACTER; | ||
3045 | goto parseError; | ||
3046 | } | ||
3047 | |||
3048 | } | ||
3049 | |||
3050 | return TRUE; | ||
3051 | |||
3052 | parseError: | ||
3053 | reportParseError(); | ||
3054 | return FALSE; | ||
3055 | } | ||
3056 | |||
3057 | /*! | ||
3058 | Parse a processing instruction [16]. | ||
3059 | |||
3060 | If xmldec is TRUE, it tries to parse a PI or a XML declaration [23]. | ||
3061 | |||
3062 | Precondition: the beginning '<' of the PI is already read and the head stand | ||
3063 | on the '?' of '<?'. | ||
3064 | |||
3065 | If this funktion was successful, the head-position is on the first | ||
3066 | character after the PI. | ||
3067 | */ | ||
3068 | bool QXmlSimpleReader::parsePI( bool xmldecl ) | ||
3069 | { | ||
3070 | const signed char Init = 0; | ||
3071 | const signed char QmI = 1; // ? was read | ||
3072 | const signed char Name = 2; // read Name | ||
3073 | const signed char XMLDecl = 3; // read XMLDecl | ||
3074 | const signed char Ws1 = 4; // eat ws after "xml" of XMLDecl | ||
3075 | const signed char PI = 5; // read PI | ||
3076 | const signed char Ws2 = 6; // eat ws after Name of PI | ||
3077 | const signed char Version = 7; // read versionInfo | ||
3078 | const signed char Ws3 = 8; // eat ws after versionInfo | ||
3079 | const signed char EorSD = 9; // read EDecl or SDDecl | ||
3080 | const signed char Ws4 = 10; // eat ws after EDecl or SDDecl | ||
3081 | const signed char SD = 11; // read SDDecl | ||
3082 | const signed char Ws5 = 12; // eat ws after SDDecl | ||
3083 | const signed char ADone = 13; // almost done | ||
3084 | const signed char Char = 14; // Char was read | ||
3085 | const signed char Qm = 15; // Qm was read | ||
3086 | const signed char Done = 16; // finished reading content | ||
3087 | |||
3088 | const signed char InpWs = 0; // whitespace | ||
3089 | const signed char InpNameBe = 1; // is_nameBeginning() | ||
3090 | const signed char InpGt = 2; // > | ||
3091 | const signed char InpQm = 3; // ? | ||
3092 | const signed char InpUnknown = 4; | ||
3093 | |||
3094 | // use some kind of state machine for parsing | ||
3095 | static const signed char table[16][5] = { | ||
3096 | /* InpWs, InpNameBe InpGt InpQm InpUnknown */ | ||
3097 | { -1, -1, -1, QmI, -1 }, // Init | ||
3098 | { -1, Name, -1, -1, -1 }, // QmI | ||
3099 | { -1, -1, -1, -1, -1 }, // Name (this state is left not through input) | ||
3100 | { Ws1, -1, -1, -1, -1 }, // XMLDecl | ||
3101 | { -1, Version, -1, -1, -1 }, // Ws1 | ||
3102 | { Ws2, -1, -1, Qm, -1 }, // PI | ||
3103 | { Char, Char, Char, Qm, Char }, // Ws2 | ||
3104 | { Ws3, -1, -1, ADone, -1 }, // Version | ||
3105 | { -1, EorSD, -1, ADone, -1 }, // Ws3 | ||
3106 | { Ws4, -1, -1, ADone, -1 }, // EorSD | ||
3107 | { -1, SD, -1, ADone, -1 }, // Ws4 | ||
3108 | { Ws5, -1, -1, ADone, -1 }, // SD | ||
3109 | { -1, -1, -1, ADone, -1 }, // Ws5 | ||
3110 | { -1, -1, Done, -1, -1 }, // ADone | ||
3111 | { Char, Char, Char, Qm, Char }, // Char | ||
3112 | { Char, Char, Done, Qm, Char }, // Qm | ||
3113 | }; | ||
3114 | signed char state = Init; | ||
3115 | signed char input; | ||
3116 | bool parseOk = TRUE; | ||
3117 | |||
3118 | for (;;) { | ||
3119 | |||
3120 | // get input | ||
3121 | if ( atEnd() ) { | ||
3122 | d->error = XMLERR_UNEXPECTEDEOF; | ||
3123 | goto parseError; | ||
3124 | } | ||
3125 | if ( is_S(c) ) { | ||
3126 | input = InpWs; | ||
3127 | } else if ( is_NameBeginning(c) ) { | ||
3128 | input = InpNameBe; | ||
3129 | } else if ( c == '>' ) { | ||
3130 | input = InpGt; | ||
3131 | } else if ( c == '?' ) { | ||
3132 | input = InpQm; | ||
3133 | } else { | ||
3134 | input = InpUnknown; | ||
3135 | } | ||
3136 | |||
3137 | // set state according to input | ||
3138 | state = table[state][input]; | ||
3139 | |||
3140 | // do some actions according to state | ||
3141 | switch ( state ) { | ||
3142 | case QmI: | ||
3143 | next(); | ||
3144 | break; | ||
3145 | case Name: | ||
3146 | parseOk = parseName(); | ||
3147 | break; | ||
3148 | case Ws1: | ||
3149 | case Ws2: | ||
3150 | case Ws3: | ||
3151 | case Ws4: | ||
3152 | case Ws5: | ||
3153 | eat_ws(); | ||
3154 | break; | ||
3155 | case Version: | ||
3156 | parseOk = parseAttribute(); | ||
3157 | break; | ||
3158 | case EorSD: | ||
3159 | parseOk = parseAttribute(); | ||
3160 | break; | ||
3161 | case SD: | ||
3162 | // get the SDDecl (syntax like an attribute) | ||
3163 | if ( d->standalone != QXmlSimpleReaderPrivate::Unknown ) { | ||
3164 | // already parsed the standalone declaration | ||
3165 | d->error = XMLERR_UNEXPECTEDCHARACTER; | ||
3166 | goto parseError; | ||
3167 | } | ||
3168 | parseOk = parseAttribute(); | ||
3169 | break; | ||
3170 | case ADone: | ||
3171 | next(); | ||
3172 | break; | ||
3173 | case Char: | ||
3174 | stringAddC(); | ||
3175 | next(); | ||
3176 | break; | ||
3177 | case Qm: | ||
3178 | // skip the '?' | ||
3179 | next(); | ||
3180 | break; | ||
3181 | case Done: | ||
3182 | next(); | ||
3183 | break; | ||
3184 | } | ||
3185 | // no input is read after this | ||
3186 | switch ( state ) { | ||
3187 | case Name: | ||
3188 | if ( !parseOk ) { | ||
3189 | d->error = XMLERR_ERRORPARSINGNAME; | ||
3190 | goto parseError; | ||
3191 | } | ||
3192 | // test what name was read and determine the next state | ||
3193 | // (not very beautiful, I admit) | ||
3194 | if ( name().lower() == "xml" ) { | ||
3195 | if ( xmldecl && name()=="xml" ) { | ||
3196 | state = XMLDecl; | ||
3197 | } else { | ||
3198 | d->error = XMLERR_INVALIDNAMEFORPI; | ||
3199 | goto parseError; | ||
3200 | } | ||
3201 | } else { | ||
3202 | state = PI; | ||
3203 | stringClear(); | ||
3204 | } | ||
3205 | break; | ||
3206 | case Version: | ||
3207 | // get version (syntax like an attribute) | ||
3208 | if ( !parseOk ) { | ||
3209 | d->error = XMLERR_VERSIONEXPECTED; | ||
3210 | goto parseError; | ||
3211 | } | ||
3212 | if ( name() != "version" ) { | ||
3213 | d->error = XMLERR_VERSIONEXPECTED; | ||
3214 | goto parseError; | ||
3215 | } | ||
3216 | d->xmlVersion = string(); | ||
3217 | break; | ||
3218 | case EorSD: | ||
3219 | // get the EDecl or SDDecl (syntax like an attribute) | ||
3220 | if ( !parseOk ) { | ||
3221 | d->error = XMLERR_EDECLORSDDECLEXPECTED; | ||
3222 | goto parseError; | ||
3223 | } | ||
3224 | if ( name() == "standalone" ) { | ||
3225 | if ( string()=="yes" ) { | ||
3226 | d->standalone = QXmlSimpleReaderPrivate::Yes; | ||
3227 | } else if ( string()=="no" ) { | ||
3228 | d->standalone = QXmlSimpleReaderPrivate::No; | ||
3229 | } else { | ||
3230 | d->error = XMLERR_WRONGVALUEFORSDECL; | ||
3231 | goto parseError; | ||
3232 | } | ||
3233 | } else if ( name() == "encoding" ) { | ||
3234 | d->encoding = string(); | ||
3235 | } else { | ||
3236 | d->error = XMLERR_EDECLORSDDECLEXPECTED; | ||
3237 | goto parseError; | ||
3238 | } | ||
3239 | break; | ||
3240 | case SD: | ||
3241 | if ( !parseOk ) { | ||
3242 | d->error = XMLERR_SDDECLEXPECTED; | ||
3243 | goto parseError; | ||
3244 | } | ||
3245 | if ( name() != "standalone" ) { | ||
3246 | d->error = XMLERR_SDDECLEXPECTED; | ||
3247 | goto parseError; | ||
3248 | } | ||
3249 | if ( string()=="yes" ) { | ||
3250 | d->standalone = QXmlSimpleReaderPrivate::Yes; | ||
3251 | } else if ( string()=="no" ) { | ||
3252 | d->standalone = QXmlSimpleReaderPrivate::No; | ||
3253 | } else { | ||
3254 | d->error = XMLERR_WRONGVALUEFORSDECL; | ||
3255 | goto parseError; | ||
3256 | } | ||
3257 | break; | ||
3258 | case Qm: | ||
3259 | // test if the skipping was legal | ||
3260 | if ( c != '>' ) { | ||
3261 | stringAddC( '?' ); | ||
3262 | } | ||
3263 | break; | ||
3264 | case Done: | ||
3265 | return TRUE; | ||
3266 | case -1: | ||
3267 | // Error | ||
3268 | d->error = XMLERR_UNEXPECTEDCHARACTER; | ||
3269 | goto parseError; | ||
3270 | } | ||
3271 | |||
3272 | } | ||
3273 | |||
3274 | return TRUE; | ||
3275 | |||
3276 | parseError: | ||
3277 | reportParseError(); | ||
3278 | return FALSE; | ||
3279 | } | ||
3280 | |||
3281 | /*! | ||
3282 | Parse a document type definition (doctypedecl [28]). | ||
3283 | |||
3284 | Precondition: the beginning '<!' of the doctype is already read the head | ||
3285 | stands on the 'D' of '<!DOCTYPE'. | ||
3286 | |||
3287 | If this funktion was successful, the head-position is on the first | ||
3288 | character after the document type definition. | ||
3289 | */ | ||
3290 | bool QXmlSimpleReader::parseDoctype() | ||
3291 | { | ||
3292 | // some init-stuff | ||
3293 | d->systemId = QString::null; | ||
3294 | d->publicId = QString::null; | ||
3295 | |||
3296 | const signed char Init = 0; | ||
3297 | const signed char Doctype = 1; // read the doctype | ||
3298 | const signed char Ws1 = 2; // eat_ws | ||
3299 | const signed char Doctype2 = 3; // read the doctype, part 2 | ||
3300 | const signed char Ws2 = 4; // eat_ws | ||
3301 | const signed char Sys = 5; // read SYSTEM | ||
3302 | const signed char Ws3 = 6; // eat_ws | ||
3303 | const signed char MP = 7; // markupdecl or PEReference | ||
3304 | const signed char PER = 8; // PERReference | ||
3305 | const signed char Mup = 9; // markupdecl | ||
3306 | const signed char Ws4 = 10; // eat_ws | ||
3307 | const signed char MPE = 11; // end of markupdecl or PEReference | ||
3308 | const signed char Done = 12; | ||
3309 | |||
3310 | const signed char InpWs = 0; | ||
3311 | const signed char InpD = 1; // 'D' | ||
3312 | const signed char InpS = 2; // 'S' or 'P' | ||
3313 | const signed char InpOB = 3; // [ | ||
3314 | const signed char InpCB = 4; // ] | ||
3315 | const signed char InpPer = 5; // % | ||
3316 | const signed char InpGt = 6; // > | ||
3317 | const signed char InpUnknown = 7; | ||
3318 | |||
3319 | // use some kind of state machine for parsing | ||
3320 | static const signed char table[12][8] = { | ||
3321 | /* InpWs, InpD InpS InpOB InpCB InpPer InpGt InpUnknown */ | ||
3322 | { -1, Doctype, -1, -1, -1, -1, -1, -1 }, // Init | ||
3323 | { Ws1, Doctype2, Doctype2, -1, -1, -1, -1, Doctype2 }, // Doctype | ||
3324 | { -1, Doctype2, Doctype2, -1, -1, -1, -1, Doctype2 }, // Ws1 | ||
3325 | { Ws2, -1, Sys, MP, -1, -1, Done, -1 }, // Doctype2 | ||
3326 | { -1, -1, Sys, MP, -1, -1, Done, -1 }, // Ws2 | ||
3327 | { Ws3, -1, -1, MP, -1, -1, Done, -1 }, // Sys | ||
3328 | { -1, -1, -1, MP, -1, -1, Done, -1 }, // Ws3 | ||
3329 | { -1, -1, -1, -1, MPE, PER, -1, Mup }, // MP | ||
3330 | { Ws4, -1, -1, -1, MPE, PER, -1, Mup }, // PER | ||
3331 | { Ws4, -1, -1, -1, MPE, PER, -1, Mup }, // Mup | ||
3332 | { -1, -1, -1, -1, MPE, PER, -1, Mup }, // Ws4 | ||
3333 | { -1, -1, -1, -1, -1, -1, Done, -1 } // MPE | ||
3334 | }; | ||
3335 | signed char state = Init; | ||
3336 | signed char input; | ||
3337 | bool parseOk = TRUE; | ||
3338 | |||
3339 | for (;;) { | ||
3340 | |||
3341 | // get input | ||
3342 | if ( atEnd() ) { | ||
3343 | d->error = XMLERR_UNEXPECTEDEOF; | ||
3344 | goto parseError; | ||
3345 | } | ||
3346 | if ( is_S(c) ) { | ||
3347 | input = InpWs; | ||
3348 | } else if ( c == 'D' ) { | ||
3349 | input = InpD; | ||
3350 | } else if ( c == 'S' ) { | ||
3351 | input = InpS; | ||
3352 | } else if ( c == 'P' ) { | ||
3353 | input = InpS; | ||
3354 | } else if ( c == '[' ) { | ||
3355 | input = InpOB; | ||
3356 | } else if ( c == ']' ) { | ||
3357 | input = InpCB; | ||
3358 | } else if ( c == '%' ) { | ||
3359 | input = InpPer; | ||
3360 | } else if ( c == '>' ) { | ||
3361 | input = InpGt; | ||
3362 | } else { | ||
3363 | input = InpUnknown; | ||
3364 | } | ||
3365 | |||
3366 | // set state according to input | ||
3367 | state = table[state][input]; | ||
3368 | |||
3369 | // do some actions according to state | ||
3370 | switch ( state ) { | ||
3371 | case Doctype: | ||
3372 | parseOk = parseString( "DOCTYPE" ); | ||
3373 | break; | ||
3374 | case Ws1: | ||
3375 | case Ws2: | ||
3376 | case Ws3: | ||
3377 | case Ws4: | ||
3378 | eat_ws(); | ||
3379 | break; | ||
3380 | case Doctype2: | ||
3381 | parseName(); | ||
3382 | break; | ||
3383 | case Sys: | ||
3384 | parseOk = parseExternalID(); | ||
3385 | break; | ||
3386 | case MP: | ||
3387 | next_eat_ws(); | ||
3388 | break; | ||
3389 | case PER: | ||
3390 | parseOk = parsePEReference( InDTD ); | ||
3391 | break; | ||
3392 | case Mup: | ||
3393 | parseOk = parseMarkupdecl(); | ||
3394 | break; | ||
3395 | case MPE: | ||
3396 | next_eat_ws(); | ||
3397 | break; | ||
3398 | case Done: | ||
3399 | if ( lexicalHnd ) { | ||
3400 | if ( !lexicalHnd->endDTD() ) { | ||
3401 | d->error = lexicalHnd->errorString(); | ||
3402 | goto parseError; | ||
3403 | } | ||
3404 | } | ||
3405 | next(); | ||
3406 | break; | ||
3407 | } | ||
3408 | // no input is read after this | ||
3409 | switch ( state ) { | ||
3410 | case Doctype: | ||
3411 | if ( !parseOk ) { | ||
3412 | d->error = XMLERR_ERRORPARSINGDOCTYPE; | ||
3413 | goto parseError; | ||
3414 | } | ||
3415 | if ( !is_S(c) ) { | ||
3416 | d->error = XMLERR_ERRORPARSINGDOCTYPE; | ||
3417 | goto parseError; | ||
3418 | } | ||
3419 | break; | ||
3420 | case Doctype2: | ||
3421 | d->doctype = name(); | ||
3422 | if ( lexicalHnd ) { | ||
3423 | if ( !lexicalHnd->startDTD( d->doctype, d->publicId, d->systemId ) ) { | ||
3424 | d->error = lexicalHnd->errorString(); | ||
3425 | goto parseError; | ||
3426 | } | ||
3427 | } | ||
3428 | break; | ||
3429 | case Sys: | ||
3430 | if ( !parseOk ) { | ||
3431 | d->error = XMLERR_ERRORPARSINGDOCTYPE; | ||
3432 | goto parseError; | ||
3433 | } | ||
3434 | break; | ||
3435 | case PER: | ||
3436 | if ( !parseOk ) { | ||
3437 | d->error = XMLERR_ERRORPARSINGDOCTYPE; | ||
3438 | goto parseError; | ||
3439 | } | ||
3440 | break; | ||
3441 | case Mup: | ||
3442 | if ( !parseOk ) { | ||
3443 | d->error = XMLERR_ERRORPARSINGDOCTYPE; | ||
3444 | goto parseError; | ||
3445 | } | ||
3446 | break; | ||
3447 | case Done: | ||
3448 | return TRUE; | ||
3449 | case -1: | ||
3450 | // Error | ||
3451 | d->error = XMLERR_ERRORPARSINGDOCTYPE; | ||
3452 | goto parseError; | ||
3453 | } | ||
3454 | |||
3455 | } | ||
3456 | |||
3457 | return TRUE; | ||
3458 | |||
3459 | parseError: | ||
3460 | reportParseError(); | ||
3461 | return FALSE; | ||
3462 | } | ||
3463 | |||
3464 | /*! | ||
3465 | Parse a ExternalID [75]. | ||
3466 | |||
3467 | If allowPublicID is TRUE parse ExternalID [75] or PublicID [83]. | ||
3468 | */ | ||
3469 | bool QXmlSimpleReader::parseExternalID( bool allowPublicID ) | ||
3470 | { | ||
3471 | // some init-stuff | ||
3472 | d->systemId = QString::null; | ||
3473 | d->publicId = QString::null; | ||
3474 | |||
3475 | const signed char Init = 0; | ||
3476 | const signed char Sys = 1; // parse 'SYSTEM' | ||
3477 | const signed char SysWS = 2; // parse the whitespace after 'SYSTEM' | ||
3478 | const signed char SysSQ = 3; // parse SystemLiteral with ' | ||
3479 | const signed char SysSQ2 = 4; // parse SystemLiteral with ' | ||
3480 | const signed char SysDQ = 5; // parse SystemLiteral with " | ||
3481 | const signed char SysDQ2 = 6; // parse SystemLiteral with " | ||
3482 | const signed char Pub = 7; // parse 'PUBLIC' | ||
3483 | const signed char PubWS = 8; // parse the whitespace after 'PUBLIC' | ||
3484 | const signed char PubSQ = 9; // parse PubidLiteral with ' | ||
3485 | const signed char PubSQ2 = 10; // parse PubidLiteral with ' | ||
3486 | const signed char PubDQ = 11; // parse PubidLiteral with " | ||
3487 | const signed char PubDQ2 = 12; // parse PubidLiteral with " | ||
3488 | const signed char PubE = 13; // finished parsing the PubidLiteral | ||
3489 | const signed char PubWS2 = 14; // parse the whitespace after the PubidLiteral | ||
3490 | const signed char PDone = 15; // done if allowPublicID is TRUE | ||
3491 | const signed char Done = 16; | ||
3492 | |||
3493 | const signed char InpSQ = 0; // ' | ||
3494 | const signed char InpDQ = 1; // " | ||
3495 | const signed char InpS = 2; // S | ||
3496 | const signed char InpP = 3; // P | ||
3497 | const signed char InpWs = 4; // white space | ||
3498 | const signed char InpUnknown = 5; | ||
3499 | |||
3500 | // use some kind of state machine for parsing | ||
3501 | static const signed char table[15][6] = { | ||
3502 | /* InpSQ InpDQ InpS InpP InpWs InpUnknown */ | ||
3503 | { -1, -1, Sys, Pub, -1, -1 }, // Init | ||
3504 | { -1, -1, -1, -1, SysWS, -1 }, // Sys | ||
3505 | { SysSQ, SysDQ, -1, -1, -1, -1 }, // SysWS | ||
3506 | { Done, SysSQ2, SysSQ2, SysSQ2, SysSQ2, SysSQ2 }, // SysSQ | ||
3507 | { Done, SysSQ2, SysSQ2, SysSQ2, SysSQ2, SysSQ2 }, // SysSQ2 | ||
3508 | { SysDQ2, Done, SysDQ2, SysDQ2, SysDQ2, SysDQ2 }, // SysDQ | ||
3509 | { SysDQ2, Done, SysDQ2, SysDQ2, SysDQ2, SysDQ2 }, // SysDQ2 | ||
3510 | { -1, -1, -1, -1, PubWS, -1 }, // Pub | ||
3511 | { PubSQ, PubDQ, -1, -1, -1, -1 }, // PubWS | ||
3512 | { PubE, -1, PubSQ2, PubSQ2, PubSQ2, PubSQ2 }, // PubSQ | ||
3513 | { PubE, -1, PubSQ2, PubSQ2, PubSQ2, PubSQ2 }, // PubSQ2 | ||
3514 | { -1, PubE, PubDQ2, PubDQ2, PubDQ2, PubDQ2 }, // PubDQ | ||
3515 | { -1, PubE, PubDQ2, PubDQ2, PubDQ2, PubDQ2 }, // PubDQ2 | ||
3516 | { PDone, PDone, PDone, PDone, PubWS2, PDone }, // PubE | ||
3517 | { SysSQ, SysDQ, PDone, PDone, PDone, PDone } // PubWS2 | ||
3518 | }; | ||
3519 | signed char state = Init; | ||
3520 | signed char input; | ||
3521 | bool parseOk = TRUE; | ||
3522 | |||
3523 | for (;;) { | ||
3524 | |||
3525 | // get input | ||
3526 | if ( atEnd() ) { | ||
3527 | d->error = XMLERR_UNEXPECTEDEOF; | ||
3528 | goto parseError; | ||
3529 | } | ||
3530 | if ( is_S(c) ) { | ||
3531 | input = InpWs; | ||
3532 | } else if ( c == '\'' ) { | ||
3533 | input = InpSQ; | ||
3534 | } else if ( c == '"' ) { | ||
3535 | input = InpDQ; | ||
3536 | } else if ( c == 'S' ) { | ||
3537 | input = InpS; | ||
3538 | } else if ( c == 'P' ) { | ||
3539 | input = InpP; | ||
3540 | } else { | ||
3541 | input = InpUnknown; | ||
3542 | } | ||
3543 | |||
3544 | // set state according to input | ||
3545 | state = table[state][input]; | ||
3546 | |||
3547 | // do some actions according to state | ||
3548 | switch ( state ) { | ||
3549 | case Sys: | ||
3550 | parseOk = parseString( "SYSTEM" ); | ||
3551 | break; | ||
3552 | case SysWS: | ||
3553 | eat_ws(); | ||
3554 | break; | ||
3555 | case SysSQ: | ||
3556 | case SysDQ: | ||
3557 | stringClear(); | ||
3558 | next(); | ||
3559 | break; | ||
3560 | case SysSQ2: | ||
3561 | case SysDQ2: | ||
3562 | stringAddC(); | ||
3563 | next(); | ||
3564 | break; | ||
3565 | case Pub: | ||
3566 | parseOk = parseString( "PUBLIC" ); | ||
3567 | break; | ||
3568 | case PubWS: | ||
3569 | eat_ws(); | ||
3570 | break; | ||
3571 | case PubSQ: | ||
3572 | case PubDQ: | ||
3573 | stringClear(); | ||
3574 | next(); | ||
3575 | break; | ||
3576 | case PubSQ2: | ||
3577 | case PubDQ2: | ||
3578 | stringAddC(); | ||
3579 | next(); | ||
3580 | break; | ||
3581 | case PubE: | ||
3582 | next(); | ||
3583 | break; | ||
3584 | case PubWS2: | ||
3585 | d->publicId = string(); | ||
3586 | eat_ws(); | ||
3587 | break; | ||
3588 | case Done: | ||
3589 | d->systemId = string(); | ||
3590 | next(); | ||
3591 | break; | ||
3592 | } | ||
3593 | // no input is read after this | ||
3594 | switch ( state ) { | ||
3595 | case Sys: | ||
3596 | if( !parseOk ) { | ||
3597 | d->error = XMLERR_UNEXPECTEDCHARACTER; | ||
3598 | goto parseError; | ||
3599 | } | ||
3600 | break; | ||
3601 | case Pub: | ||
3602 | if( !parseOk ) { | ||
3603 | d->error = XMLERR_UNEXPECTEDCHARACTER; | ||
3604 | goto parseError; | ||
3605 | } | ||
3606 | break; | ||
3607 | case PDone: | ||
3608 | if ( allowPublicID ) { | ||
3609 | d->publicId = string(); | ||
3610 | return TRUE; | ||
3611 | } else { | ||
3612 | d->error = XMLERR_UNEXPECTEDCHARACTER; | ||
3613 | goto parseError; | ||
3614 | } | ||
3615 | break; | ||
3616 | case Done: | ||
3617 | return TRUE; | ||
3618 | case -1: | ||
3619 | // Error | ||
3620 | d->error = XMLERR_UNEXPECTEDCHARACTER; | ||
3621 | goto parseError; | ||
3622 | } | ||
3623 | |||
3624 | } | ||
3625 | |||
3626 | return TRUE; | ||
3627 | |||
3628 | parseError: | ||
3629 | reportParseError(); | ||
3630 | return FALSE; | ||
3631 | } | ||
3632 | |||
3633 | /*! | ||
3634 | Parse a markupdecl [29]. | ||
3635 | */ | ||
3636 | bool QXmlSimpleReader::parseMarkupdecl() | ||
3637 | { | ||
3638 | const signed char Init = 0; | ||
3639 | const signed char Lt = 1; // < was read | ||
3640 | const signed char Em = 2; // ! was read | ||
3641 | const signed char CE = 3; // E was read | ||
3642 | const signed char Qm = 4; // ? was read | ||
3643 | const signed char Dash = 5; // - was read | ||
3644 | const signed char CA = 6; // A was read | ||
3645 | const signed char CEL = 7; // EL was read | ||
3646 | const signed char CEN = 8; // EN was read | ||
3647 | const signed char CN = 9; // N was read | ||
3648 | const signed char Done = 10; | ||
3649 | |||
3650 | const signed char InpLt = 0; // < | ||
3651 | const signed char InpQm = 1; // ? | ||
3652 | const signed char InpEm = 2; // ! | ||
3653 | const signed char InpDash = 3; // - | ||
3654 | const signed char InpA = 4; // A | ||
3655 | const signed char InpE = 5; // E | ||
3656 | const signed char InpL = 6; // L | ||
3657 | const signed char InpN = 7; // N | ||
3658 | const signed char InpUnknown = 8; | ||
3659 | |||
3660 | // use some kind of state machine for parsing | ||
3661 | static const signed char table[4][9] = { | ||
3662 | /* InpLt InpQm InpEm InpDash InpA InpE InpL InpN InpUnknown */ | ||
3663 | { Lt, -1, -1, -1, -1, -1, -1, -1, -1 }, // Init | ||
3664 | { -1, Qm, Em, -1, -1, -1, -1, -1, -1 }, // Lt | ||
3665 | { -1, -1, -1, Dash, CA, CE, -1, CN, -1 }, // Em | ||
3666 | { -1, -1, -1, -1, -1, -1, CEL, CEN, -1 } // CE | ||
3667 | }; | ||
3668 | signed char state = Init; | ||
3669 | signed char input; | ||
3670 | bool parseOk = TRUE; | ||
3671 | |||
3672 | for (;;) { | ||
3673 | |||
3674 | // get input | ||
3675 | if ( atEnd() ) { | ||
3676 | d->error = XMLERR_UNEXPECTEDEOF; | ||
3677 | goto parseError; | ||
3678 | } | ||
3679 | if ( c == '<' ) { | ||
3680 | input = InpLt; | ||
3681 | } else if ( c == '?' ) { | ||
3682 | input = InpQm; | ||
3683 | } else if ( c == '!' ) { | ||
3684 | input = InpEm; | ||
3685 | } else if ( c == '-' ) { | ||
3686 | input = InpDash; | ||
3687 | } else if ( c == 'A' ) { | ||
3688 | input = InpA; | ||
3689 | } else if ( c == 'E' ) { | ||
3690 | input = InpE; | ||
3691 | } else if ( c == 'L' ) { | ||
3692 | input = InpL; | ||
3693 | } else if ( c == 'N' ) { | ||
3694 | input = InpN; | ||
3695 | } else { | ||
3696 | input = InpUnknown; | ||
3697 | } | ||
3698 | |||
3699 | // set state according to input | ||
3700 | state = table[state][input]; | ||
3701 | |||
3702 | // do some actions according to state | ||
3703 | switch ( state ) { | ||
3704 | case Lt: | ||
3705 | next(); | ||
3706 | break; | ||
3707 | case Em: | ||
3708 | next(); | ||
3709 | break; | ||
3710 | case CE: | ||
3711 | next(); | ||
3712 | break; | ||
3713 | case Qm: | ||
3714 | parseOk = parsePI(); | ||
3715 | break; | ||
3716 | case Dash: | ||
3717 | parseOk = parseComment(); | ||
3718 | break; | ||
3719 | case CA: | ||
3720 | parseOk = parseAttlistDecl(); | ||
3721 | break; | ||
3722 | case CEL: | ||
3723 | parseOk = parseElementDecl(); | ||
3724 | break; | ||
3725 | case CEN: | ||
3726 | parseOk = parseEntityDecl(); | ||
3727 | break; | ||
3728 | case CN: | ||
3729 | parseOk = parseNotationDecl(); | ||
3730 | break; | ||
3731 | } | ||
3732 | // no input is read after this | ||
3733 | switch ( state ) { | ||
3734 | case Qm: | ||
3735 | if ( !parseOk ) { | ||
3736 | d->error = XMLERR_ERRORPARSINGPI; | ||
3737 | goto parseError; | ||
3738 | } | ||
3739 | if ( contentHnd ) { | ||
3740 | if ( !contentHnd->processingInstruction(name(),string()) ) { | ||
3741 | d->error = contentHnd->errorString(); | ||
3742 | goto parseError; | ||
3743 | } | ||
3744 | } | ||
3745 | return TRUE; | ||
3746 | case Dash: | ||
3747 | if ( !parseOk ) { | ||
3748 | d->error = XMLERR_ERRORPARSINGCOMMENT; | ||
3749 | goto parseError; | ||
3750 | } | ||
3751 | if ( lexicalHnd ) { | ||
3752 | if ( !lexicalHnd->comment( string() ) ) { | ||
3753 | d->error = lexicalHnd->errorString(); | ||
3754 | goto parseError; | ||
3755 | } | ||
3756 | } | ||
3757 | return TRUE; | ||
3758 | case CA: | ||
3759 | if ( !parseOk ) { | ||
3760 | d->error = XMLERR_ERRORPARSINGATTLISTDECL; | ||
3761 | goto parseError; | ||
3762 | } | ||
3763 | return TRUE; | ||
3764 | case CEL: | ||
3765 | if ( !parseOk ) { | ||
3766 | d->error = XMLERR_ERRORPARSINGELEMENTDECL; | ||
3767 | goto parseError; | ||
3768 | } | ||
3769 | return TRUE; | ||
3770 | case CEN: | ||
3771 | if ( !parseOk ) { | ||
3772 | d->error = XMLERR_ERRORPARSINGENTITYDECL; | ||
3773 | goto parseError; | ||
3774 | } | ||
3775 | return TRUE; | ||
3776 | case CN: | ||
3777 | if ( !parseOk ) { | ||
3778 | d->error = XMLERR_ERRORPARSINGNOTATIONDECL; | ||
3779 | goto parseError; | ||
3780 | } | ||
3781 | return TRUE; | ||
3782 | case Done: | ||
3783 | return TRUE; | ||
3784 | case -1: | ||
3785 | // Error | ||
3786 | d->error = XMLERR_LETTEREXPECTED; | ||
3787 | goto parseError; | ||
3788 | } | ||
3789 | |||
3790 | } | ||
3791 | |||
3792 | return TRUE; | ||
3793 | |||
3794 | parseError: | ||
3795 | reportParseError(); | ||
3796 | return FALSE; | ||
3797 | } | ||
3798 | |||
3799 | /*! | ||
3800 | Parse a PEReference [69] | ||
3801 | */ | ||
3802 | bool QXmlSimpleReader::parsePEReference( EntityRecognitionContext context ) | ||
3803 | { | ||
3804 | const signed char Init = 0; | ||
3805 | const signed char Next = 1; | ||
3806 | const signed char Name = 2; | ||
3807 | const signed char Done = 3; | ||
3808 | |||
3809 | const signed char InpSemi = 0; // ; | ||
3810 | const signed char InpPer = 1; // % | ||
3811 | const signed char InpUnknown = 2; | ||
3812 | |||
3813 | // use some kind of state machine for parsing | ||
3814 | static const signed char table[3][3] = { | ||
3815 | /* InpSemi InpPer InpUnknown */ | ||
3816 | { -1, Next, -1 }, // Init | ||
3817 | { -1, -1, Name }, // Next | ||
3818 | { Done, -1, -1 } // Name | ||
3819 | }; | ||
3820 | signed char state = Init; | ||
3821 | signed char input; | ||
3822 | bool parseOk = TRUE; | ||
3823 | |||
3824 | for (;;) { | ||
3825 | |||
3826 | // get input | ||
3827 | if ( atEnd() ) { | ||
3828 | d->error = XMLERR_UNEXPECTEDEOF; | ||
3829 | goto parseError; | ||
3830 | } | ||
3831 | if ( c == ';' ) { | ||
3832 | input = InpSemi; | ||
3833 | } else if ( c == '%' ) { | ||
3834 | input = InpPer; | ||
3835 | } else { | ||
3836 | input = InpUnknown; | ||
3837 | } | ||
3838 | |||
3839 | // set state according to input | ||
3840 | state = table[state][input]; | ||
3841 | |||
3842 | // do some actions according to state | ||
3843 | switch ( state ) { | ||
3844 | case Next: | ||
3845 | next(); | ||
3846 | break; | ||
3847 | case Name: | ||
3848 | parseOk = parseName( TRUE ); | ||
3849 | break; | ||
3850 | case Done: | ||
3851 | next(); | ||
3852 | break; | ||
3853 | } | ||
3854 | // no input is read after this | ||
3855 | switch ( state ) { | ||
3856 | case Name: | ||
3857 | if ( !parseOk ) { | ||
3858 | d->error = XMLERR_ERRORPARSINGNAME; | ||
3859 | goto parseError; | ||
3860 | } | ||
3861 | if ( d->parameterEntities.find( ref() ) == d->parameterEntities.end() ) { | ||
3862 | // ### skip it??? | ||
3863 | if ( contentHnd ) { | ||
3864 | if ( !contentHnd->skippedEntity( QString("%") + ref() ) ) { | ||
3865 | d->error = contentHnd->errorString(); | ||
3866 | goto parseError; | ||
3867 | } | ||
3868 | } | ||
3869 | } else { | ||
3870 | if ( context == InEntityValue ) { | ||
3871 | // Included in literal | ||
3872 | xmlRef = d->parameterEntities.find( ref() ) | ||
3873 | .data().replace( QRegExp("\""), """ ).replace( QRegExp("'"), "'" ) | ||
3874 | + xmlRef; | ||
3875 | } else if ( context == InDTD ) { | ||
3876 | // Included as PE | ||
3877 | xmlRef = QString(" ") + | ||
3878 | d->parameterEntities.find( ref() ).data() + | ||
3879 | QString(" ") + xmlRef; | ||
3880 | } | ||
3881 | } | ||
3882 | break; | ||
3883 | case Done: | ||
3884 | return TRUE; | ||
3885 | case -1: | ||
3886 | // Error | ||
3887 | d->error = XMLERR_LETTEREXPECTED; | ||
3888 | goto parseError; | ||
3889 | } | ||
3890 | |||
3891 | } | ||
3892 | |||
3893 | return TRUE; | ||
3894 | |||
3895 | parseError: | ||
3896 | reportParseError(); | ||
3897 | return FALSE; | ||
3898 | } | ||
3899 | |||
3900 | /*! | ||
3901 | Parse a AttlistDecl [52]. | ||
3902 | |||
3903 | Precondition: the beginning '<!' is already read and the head | ||
3904 | stands on the 'A' of '<!ATTLIST' | ||
3905 | */ | ||
3906 | bool QXmlSimpleReader::parseAttlistDecl() | ||
3907 | { | ||
3908 | const signed char Init = 0; | ||
3909 | const signed char Attlist = 1; // parse the string "ATTLIST" | ||
3910 | const signed char Ws = 2; // whitespace read | ||
3911 | const signed char Name = 3; // parse name | ||
3912 | const signed char Ws1 = 4; // whitespace read | ||
3913 | const signed char Attdef = 5; // parse the AttDef | ||
3914 | const signed char Ws2 = 6; // whitespace read | ||
3915 | const signed char Atttype = 7; // parse the AttType | ||
3916 | const signed char Ws3 = 8; // whitespace read | ||
3917 | const signed char DDecH = 9; // DefaultDecl with # | ||
3918 | const signed char DefReq = 10; // parse the string "REQUIRED" | ||
3919 | const signed char DefImp = 11; // parse the string "IMPLIED" | ||
3920 | const signed char DefFix = 12; // parse the string "FIXED" | ||
3921 | const signed char Attval = 13; // parse the AttValue | ||
3922 | const signed char Ws4 = 14; // whitespace read | ||
3923 | const signed char Done = 15; | ||
3924 | |||
3925 | const signed char InpWs = 0; // white space | ||
3926 | const signed char InpGt = 1; // > | ||
3927 | const signed char InpHash = 2; // # | ||
3928 | const signed char InpA = 3; // A | ||
3929 | const signed char InpI = 4; // I | ||
3930 | const signed char InpF = 5; // F | ||
3931 | const signed char InpR = 6; // R | ||
3932 | const signed char InpUnknown = 7; | ||
3933 | |||
3934 | // use some kind of state machine for parsing | ||
3935 | static const signed char table[15][8] = { | ||
3936 | /* InpWs InpGt InpHash InpA InpI InpF InpR InpUnknown */ | ||
3937 | { -1, -1, -1, Attlist, -1, -1, -1, -1 }, // Init | ||
3938 | { Ws, -1, -1, -1, -1, -1, -1, -1 }, // Attlist | ||
3939 | { -1, -1, -1, Name, Name, Name, Name, Name }, // Ws | ||
3940 | { Ws1, Done, Attdef, Attdef, Attdef, Attdef, Attdef, Attdef }, // Name | ||
3941 | { -1, Done, Attdef, Attdef, Attdef, Attdef, Attdef, Attdef }, // Ws1 | ||
3942 | { Ws2, -1, -1, -1, -1, -1, -1, -1 }, // Attdef | ||
3943 | { -1, Atttype, Atttype, Atttype, Atttype, Atttype, Atttype, Atttype }, // Ws2 | ||
3944 | { Ws3, -1, -1, -1, -1, -1, -1, -1 }, // Attype | ||
3945 | { -1, Attval, DDecH, Attval, Attval, Attval, Attval, Attval }, // Ws3 | ||
3946 | { -1, -1, -1, -1, DefImp, DefFix, DefReq, -1 }, // DDecH | ||
3947 | { Ws4, Ws4, -1, -1, -1, -1, -1, -1 }, // DefReq | ||
3948 | { Ws4, Ws4, -1, -1, -1, -1, -1, -1 }, // DefImp | ||
3949 | { Ws3, -1, -1, -1, -1, -1, -1, -1 }, // DefFix | ||
3950 | { Ws4, Ws4, -1, -1, -1, -1, -1, -1 }, // Attval | ||
3951 | { -1, Done, Attdef, Attdef, Attdef, Attdef, Attdef, Attdef } // Ws4 | ||
3952 | }; | ||
3953 | signed char state = Init; | ||
3954 | signed char input; | ||
3955 | bool parseOk = TRUE; | ||
3956 | |||
3957 | for (;;) { | ||
3958 | |||
3959 | // get input | ||
3960 | if ( atEnd() ) { | ||
3961 | d->error = XMLERR_UNEXPECTEDEOF; | ||
3962 | goto parseError; | ||
3963 | } | ||
3964 | if ( is_S(c) ) { | ||
3965 | input = InpWs; | ||
3966 | } else if ( c == '>' ) { | ||
3967 | input = InpGt; | ||
3968 | } else if ( c == '#' ) { | ||
3969 | input = InpHash; | ||
3970 | } else if ( c == 'A' ) { | ||
3971 | input = InpA; | ||
3972 | } else if ( c == 'I' ) { | ||
3973 | input = InpI; | ||
3974 | } else if ( c == 'F' ) { | ||
3975 | input = InpF; | ||
3976 | } else if ( c == 'R' ) { | ||
3977 | input = InpR; | ||
3978 | } else { | ||
3979 | input = InpUnknown; | ||
3980 | } | ||
3981 | |||
3982 | // set state according to input | ||
3983 | state = table[state][input]; | ||
3984 | |||
3985 | // do some actions according to state | ||
3986 | switch ( state ) { | ||
3987 | case Attlist: | ||
3988 | parseOk = parseString( "ATTLIST" ); | ||
3989 | break; | ||
3990 | case Ws: | ||
3991 | case Ws1: | ||
3992 | case Ws2: | ||
3993 | case Ws3: | ||
3994 | eat_ws(); | ||
3995 | break; | ||
3996 | case Name: | ||
3997 | parseOk = parseName(); | ||
3998 | break; | ||
3999 | case Attdef: | ||
4000 | parseOk = parseName(); | ||
4001 | break; | ||
4002 | case Atttype: | ||
4003 | parseOk = parseAttType(); | ||
4004 | break; | ||
4005 | case DDecH: | ||
4006 | next(); | ||
4007 | break; | ||
4008 | case DefReq: | ||
4009 | parseOk = parseString( "REQUIRED" ); | ||
4010 | break; | ||
4011 | case DefImp: | ||
4012 | parseOk = parseString( "IMPLIED" ); | ||
4013 | break; | ||
4014 | case DefFix: | ||
4015 | parseOk = parseString( "FIXED" ); | ||
4016 | break; | ||
4017 | case Attval: | ||
4018 | parseOk = parseAttValue(); | ||
4019 | break; | ||
4020 | case Ws4: | ||
4021 | if ( declHnd ) { | ||
4022 | // TODO: not all values are computed yet... | ||
4023 | if ( !declHnd->attributeDecl( d->attDeclEName, d->attDeclAName, "", "", "" ) ) { | ||
4024 | d->error = declHnd->errorString(); | ||
4025 | goto parseError; | ||
4026 | } | ||
4027 | } | ||
4028 | eat_ws(); | ||
4029 | break; | ||
4030 | case Done: | ||
4031 | next(); | ||
4032 | break; | ||
4033 | } | ||
4034 | // no input is read after this | ||
4035 | switch ( state ) { | ||
4036 | case Attlist: | ||
4037 | if( !parseOk ) { | ||
4038 | d->error = XMLERR_UNEXPECTEDCHARACTER; | ||
4039 | goto parseError; | ||
4040 | } | ||
4041 | break; | ||
4042 | case Name: | ||
4043 | if ( !parseOk ) { | ||
4044 | d->error = XMLERR_ERRORPARSINGNAME; | ||
4045 | goto parseError; | ||
4046 | } | ||
4047 | d->attDeclEName = name(); | ||
4048 | break; | ||
4049 | case Attdef: | ||
4050 | if ( !parseOk ) { | ||
4051 | d->error = XMLERR_ERRORPARSINGNAME; | ||
4052 | goto parseError; | ||
4053 | } | ||
4054 | d->attDeclAName = name(); | ||
4055 | break; | ||
4056 | case Atttype: | ||
4057 | if ( !parseOk ) { | ||
4058 | d->error = XMLERR_ERRORPARSINGATTTYPE; | ||
4059 | goto parseError; | ||
4060 | } | ||
4061 | break; | ||
4062 | case DefReq: | ||
4063 | if( !parseOk ) { | ||
4064 | d->error = XMLERR_UNEXPECTEDCHARACTER; | ||
4065 | goto parseError; | ||
4066 | } | ||
4067 | break; | ||
4068 | case DefImp: | ||
4069 | if( !parseOk ) { | ||
4070 | d->error = XMLERR_UNEXPECTEDCHARACTER; | ||
4071 | goto parseError; | ||
4072 | } | ||
4073 | break; | ||
4074 | case DefFix: | ||
4075 | if( !parseOk ) { | ||
4076 | d->error = XMLERR_UNEXPECTEDCHARACTER; | ||
4077 | goto parseError; | ||
4078 | } | ||
4079 | break; | ||
4080 | case Attval: | ||
4081 | if ( !parseOk ) { | ||
4082 | d->error = XMLERR_ERRORPARSINGATTVALUE; | ||
4083 | goto parseError; | ||
4084 | } | ||
4085 | break; | ||
4086 | case Done: | ||
4087 | return TRUE; | ||
4088 | case -1: | ||
4089 | // Error | ||
4090 | d->error = XMLERR_LETTEREXPECTED; | ||
4091 | goto parseError; | ||
4092 | } | ||
4093 | |||
4094 | } | ||
4095 | |||
4096 | return TRUE; | ||
4097 | |||
4098 | parseError: | ||
4099 | reportParseError(); | ||
4100 | return FALSE; | ||
4101 | } | ||
4102 | |||
4103 | /*! | ||
4104 | Parse a AttType [54] | ||
4105 | */ | ||
4106 | bool QXmlSimpleReader::parseAttType() | ||
4107 | { | ||
4108 | const signed char Init = 0; | ||
4109 | const signed char ST = 1; // StringType | ||
4110 | const signed char TTI = 2; // TokenizedType starting with 'I' | ||
4111 | const signed char TTI2 = 3; // TokenizedType helpstate | ||
4112 | const signed char TTI3 = 4; // TokenizedType helpstate | ||
4113 | const signed char TTE = 5; // TokenizedType starting with 'E' | ||
4114 | const signed char TTEY = 6; // TokenizedType starting with 'ENTITY' | ||
4115 | const signed char TTEI = 7; // TokenizedType starting with 'ENTITI' | ||
4116 | const signed char N = 8; // N read (TokenizedType or Notation) | ||
4117 | const signed char TTNM = 9; // TokenizedType starting with 'NM' | ||
4118 | const signed char TTNM2 = 10; // TokenizedType helpstate | ||
4119 | const signed char NO = 11; // Notation | ||
4120 | const signed char NO2 = 12; // Notation helpstate | ||
4121 | const signed char NO3 = 13; // Notation helpstate | ||
4122 | const signed char NOName = 14; // Notation, read name | ||
4123 | const signed char NO4 = 15; // Notation helpstate | ||
4124 | const signed char EN = 16; // Enumeration | ||
4125 | const signed char ENNmt = 17; // Enumeration, read Nmtoken | ||
4126 | const signed char EN2 = 18; // Enumeration helpstate | ||
4127 | const signed char ADone = 19; // almost done (make next and accept) | ||
4128 | const signed char Done = 20; | ||
4129 | |||
4130 | const signed char InpWs = 0; // whitespace | ||
4131 | const signed char InpOp = 1; // ( | ||
4132 | const signed char InpCp = 2; // ) | ||
4133 | const signed char InpPipe = 3; // | | ||
4134 | const signed char InpC = 4; // C | ||
4135 | const signed char InpE = 5; // E | ||
4136 | const signed char InpI = 6; // I | ||
4137 | const signed char InpM = 7; // M | ||
4138 | const signed char InpN = 8; // N | ||
4139 | const signed char InpO = 9; // O | ||
4140 | const signed char InpR = 10; // R | ||
4141 | const signed char InpS = 11; // S | ||
4142 | const signed char InpY = 12; // Y | ||
4143 | const signed char InpUnknown = 13; | ||
4144 | |||
4145 | // use some kind of state machine for parsing | ||
4146 | static const signed char table[19][14] = { | ||
4147 | /* InpWs InpOp InpCp InpPipe InpC InpE InpI InpM InpN InpO InpR InpS InpY InpUnknown */ | ||
4148 | { -1, EN, -1, -1, ST, TTE, TTI, -1, N, -1, -1, -1, -1, -1 }, // Init | ||
4149 | { Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done }, // ST | ||
4150 | { Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, TTI2, Done, Done, Done }, // TTI | ||
4151 | { Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, TTI3, Done, Done }, // TTI2 | ||
4152 | { Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done }, // TTI3 | ||
4153 | { -1, -1, -1, -1, -1, -1, TTEI, -1, -1, -1, -1, -1, TTEY, -1 }, // TTE | ||
4154 | { Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done }, // TTEY | ||
4155 | { Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done }, // TTEI | ||
4156 | { -1, -1, -1, -1, -1, -1, -1, TTNM, -1, NO, -1, -1, -1, -1 }, // N | ||
4157 | { Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, TTNM2, Done, Done }, // TTNM | ||
4158 | { Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done }, // TTNM2 | ||
4159 | { NO2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, // NO | ||
4160 | { -1, NO3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, // NO2 | ||
4161 | { NOName, NOName, NOName, NOName, NOName, NOName, NOName, NOName, NOName, NOName, NOName, NOName, NOName, NOName }, // NO3 | ||
4162 | { NO4, -1, ADone, NO3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, // NOName | ||
4163 | { -1, -1, ADone, NO3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, // NO4 | ||
4164 | { -1, -1, ENNmt, -1, ENNmt, ENNmt, ENNmt, ENNmt, ENNmt, ENNmt, ENNmt, ENNmt, ENNmt, ENNmt }, // EN | ||
4165 | { EN2, -1, ADone, EN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, // ENNmt | ||
4166 | { -1, -1, ADone, EN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } // EN2 | ||
4167 | }; | ||
4168 | signed char state = Init; | ||
4169 | signed char input; | ||
4170 | bool parseOk = TRUE; | ||
4171 | |||
4172 | for (;;) { | ||
4173 | |||
4174 | // get input | ||
4175 | if ( atEnd() ) { | ||
4176 | d->error = XMLERR_UNEXPECTEDEOF; | ||
4177 | goto parseError; | ||
4178 | } | ||
4179 | if ( is_S(c) ) { | ||
4180 | input = InpWs; | ||
4181 | } else if ( c == '(' ) { | ||
4182 | input = InpOp; | ||
4183 | } else if ( c == ')' ) { | ||
4184 | input = InpCp; | ||
4185 | } else if ( c == '|' ) { | ||
4186 | input = InpPipe; | ||
4187 | } else if ( c == 'C' ) { | ||
4188 | input = InpC; | ||
4189 | } else if ( c == 'E' ) { | ||
4190 | input = InpE; | ||
4191 | } else if ( c == 'I' ) { | ||
4192 | input = InpI; | ||
4193 | } else if ( c == 'M' ) { | ||
4194 | input = InpM; | ||
4195 | } else if ( c == 'N' ) { | ||
4196 | input = InpN; | ||
4197 | } else if ( c == 'O' ) { | ||
4198 | input = InpO; | ||
4199 | } else if ( c == 'R' ) { | ||
4200 | input = InpR; | ||
4201 | } else if ( c == 'S' ) { | ||
4202 | input = InpS; | ||
4203 | } else if ( c == 'Y' ) { | ||
4204 | input = InpY; | ||
4205 | } else { | ||
4206 | input = InpUnknown; | ||
4207 | } | ||
4208 | |||
4209 | // set state according to input | ||
4210 | state = table[state][input]; | ||
4211 | |||
4212 | // do some actions according to state | ||
4213 | switch ( state ) { | ||
4214 | case ST: | ||
4215 | parseOk = parseString( "CDATA" ); | ||
4216 | break; | ||
4217 | case TTI: | ||
4218 | parseOk = parseString( "ID" ); | ||
4219 | break; | ||
4220 | case TTI2: | ||
4221 | parseOk = parseString( "REF" ); | ||
4222 | break; | ||
4223 | case TTI3: | ||
4224 | next(); // S | ||
4225 | break; | ||
4226 | case TTE: | ||
4227 | parseOk = parseString( "ENTIT" ); | ||
4228 | break; | ||
4229 | case TTEY: | ||
4230 | next(); // Y | ||
4231 | break; | ||
4232 | case TTEI: | ||
4233 | parseOk = parseString( "IES" ); | ||
4234 | break; | ||
4235 | case N: | ||
4236 | next(); // N | ||
4237 | break; | ||
4238 | case TTNM: | ||
4239 | parseOk = parseString( "MTOKEN" ); | ||
4240 | break; | ||
4241 | case TTNM2: | ||
4242 | next(); // S | ||
4243 | break; | ||
4244 | case NO: | ||
4245 | parseOk = parseString( "OTATION" ); | ||
4246 | break; | ||
4247 | case NO2: | ||
4248 | eat_ws(); | ||
4249 | break; | ||
4250 | case NO3: | ||
4251 | next_eat_ws(); | ||
4252 | break; | ||
4253 | case NOName: | ||
4254 | parseOk = parseName(); | ||
4255 | break; | ||
4256 | case NO4: | ||
4257 | eat_ws(); | ||
4258 | break; | ||
4259 | case EN: | ||
4260 | next_eat_ws(); | ||
4261 | break; | ||
4262 | case ENNmt: | ||
4263 | parseOk = parseNmtoken(); | ||
4264 | break; | ||
4265 | case EN2: | ||
4266 | eat_ws(); | ||
4267 | break; | ||
4268 | case ADone: | ||
4269 | next(); | ||
4270 | break; | ||
4271 | } | ||
4272 | // no input is read after this | ||
4273 | switch ( state ) { | ||
4274 | case ST: | ||
4275 | if( !parseOk ) { | ||
4276 | d->error = XMLERR_UNEXPECTEDCHARACTER; | ||
4277 | goto parseError; | ||
4278 | } | ||
4279 | break; | ||
4280 | case TTI: | ||
4281 | if( !parseOk ) { | ||
4282 | d->error = XMLERR_UNEXPECTEDCHARACTER; | ||
4283 | goto parseError; | ||
4284 | } | ||
4285 | break; | ||
4286 | case TTI2: | ||
4287 | if( !parseOk ) { | ||
4288 | d->error = XMLERR_UNEXPECTEDCHARACTER; | ||
4289 | goto parseError; | ||
4290 | } | ||
4291 | break; | ||
4292 | case TTE: | ||
4293 | if( !parseOk ) { | ||
4294 | d->error = XMLERR_UNEXPECTEDCHARACTER; | ||
4295 | goto parseError; | ||
4296 | } | ||
4297 | break; | ||
4298 | case TTEI: | ||
4299 | if( !parseOk ) { | ||
4300 | d->error = XMLERR_UNEXPECTEDCHARACTER; | ||
4301 | goto parseError; | ||
4302 | } | ||
4303 | break; | ||
4304 | case TTNM: | ||
4305 | if( !parseOk ) { | ||
4306 | d->error = XMLERR_UNEXPECTEDCHARACTER; | ||
4307 | goto parseError; | ||
4308 | } | ||
4309 | break; | ||
4310 | case NO: | ||
4311 | if( !parseOk ) { | ||
4312 | d->error = XMLERR_UNEXPECTEDCHARACTER; | ||
4313 | goto parseError; | ||
4314 | } | ||
4315 | break; | ||
4316 | case NOName: | ||
4317 | if ( !parseOk ) { | ||
4318 | d->error = XMLERR_ERRORPARSINGNAME; | ||
4319 | goto parseError; | ||
4320 | } | ||
4321 | break; | ||
4322 | case ENNmt: | ||
4323 | if ( !parseOk ) { | ||
4324 | d->error = XMLERR_ERRORPARSINGNMTOKEN; | ||
4325 | goto parseError; | ||
4326 | } | ||
4327 | break; | ||
4328 | case ADone: | ||
4329 | return TRUE; | ||
4330 | case Done: | ||
4331 | return TRUE; | ||
4332 | case -1: | ||
4333 | // Error | ||
4334 | d->error = XMLERR_LETTEREXPECTED; | ||
4335 | goto parseError; | ||
4336 | } | ||
4337 | |||
4338 | } | ||
4339 | |||
4340 | return TRUE; | ||
4341 | |||
4342 | parseError: | ||
4343 | reportParseError(); | ||
4344 | return FALSE; | ||
4345 | } | ||
4346 | |||
4347 | /*! | ||
4348 | Parse a AttValue [10] | ||
4349 | |||
4350 | Precondition: the head stands on the beginning " or ' | ||
4351 | |||
4352 | If this function was successful, the head stands on the first | ||
4353 | character after the closing " or ' and the value of the attribute | ||
4354 | is in string(). | ||
4355 | */ | ||
4356 | bool QXmlSimpleReader::parseAttValue() | ||
4357 | { | ||
4358 | bool tmp; | ||
4359 | |||
4360 | const signed char Init = 0; | ||
4361 | const signed char Dq = 1; // double quotes were read | ||
4362 | const signed char DqRef = 2; // read references in double quotes | ||
4363 | const signed char DqC = 3; // signed character read in double quotes | ||
4364 | const signed char Sq = 4; // single quotes were read | ||
4365 | const signed char SqRef = 5; // read references in single quotes | ||
4366 | const signed char SqC = 6; // signed character read in single quotes | ||
4367 | const signed char Done = 7; | ||
4368 | |||
4369 | const signed char InpDq = 0; // " | ||
4370 | const signed char InpSq = 1; // ' | ||
4371 | const signed char InpAmp = 2; // & | ||
4372 | const signed char InpLt = 3; // < | ||
4373 | const signed char InpUnknown = 4; | ||
4374 | |||
4375 | // use some kind of state machine for parsing | ||
4376 | static const signed char table[7][5] = { | ||
4377 | /* InpDq InpSq InpAmp InpLt InpUnknown */ | ||
4378 | { Dq, Sq, -1, -1, -1 }, // Init | ||
4379 | { Done, DqC, DqRef, -1, DqC }, // Dq | ||
4380 | { Done, DqC, DqRef, -1, DqC }, // DqRef | ||
4381 | { Done, DqC, DqRef, -1, DqC }, // DqC | ||
4382 | { SqC, Done, SqRef, -1, SqC }, // Sq | ||
4383 | { SqC, Done, SqRef, -1, SqC }, // SqRef | ||
4384 | { SqC, Done, SqRef, -1, SqC } // SqRef | ||
4385 | }; | ||
4386 | signed char state = Init; | ||
4387 | signed char input; | ||
4388 | bool parseOk = TRUE; | ||
4389 | |||
4390 | for (;;) { | ||
4391 | |||
4392 | // get input | ||
4393 | if ( atEnd() ) { | ||
4394 | d->error = XMLERR_UNEXPECTEDEOF; | ||
4395 | goto parseError; | ||
4396 | } | ||
4397 | if ( c == '"' ) { | ||
4398 | input = InpDq; | ||
4399 | } else if ( c == '\'' ) { | ||
4400 | input = InpSq; | ||
4401 | } else if ( c == '&' ) { | ||
4402 | input = InpAmp; | ||
4403 | } else if ( c == '<' ) { | ||
4404 | input = InpLt; | ||
4405 | } else { | ||
4406 | input = InpUnknown; | ||
4407 | } | ||
4408 | |||
4409 | // set state according to input | ||
4410 | state = table[state][input]; | ||
4411 | |||
4412 | // do some actions according to state | ||
4413 | switch ( state ) { | ||
4414 | case Dq: | ||
4415 | case Sq: | ||
4416 | stringClear(); | ||
4417 | next(); | ||
4418 | break; | ||
4419 | case DqRef: | ||
4420 | case SqRef: | ||
4421 | parseOk = parseReference( tmp, InAttributeValue ); | ||
4422 | break; | ||
4423 | case DqC: | ||
4424 | case SqC: | ||
4425 | stringAddC(); | ||
4426 | next(); | ||
4427 | break; | ||
4428 | case Done: | ||
4429 | next(); | ||
4430 | break; | ||
4431 | } | ||
4432 | // no input is read after this | ||
4433 | switch ( state ) { | ||
4434 | case DqRef: | ||
4435 | case SqRef: | ||
4436 | if ( !parseOk ) { | ||
4437 | d->error = XMLERR_ERRORPARSINGREFERENCE; | ||
4438 | goto parseError; | ||
4439 | } | ||
4440 | break; | ||
4441 | case Done: | ||
4442 | return TRUE; | ||
4443 | case -1: | ||
4444 | // Error | ||
4445 | d->error = XMLERR_UNEXPECTEDCHARACTER; | ||
4446 | goto parseError; | ||
4447 | } | ||
4448 | |||
4449 | } | ||
4450 | |||
4451 | return TRUE; | ||
4452 | |||
4453 | parseError: | ||
4454 | reportParseError(); | ||
4455 | return FALSE; | ||
4456 | } | ||
4457 | |||
4458 | /*! | ||
4459 | Parse a elementdecl [45]. | ||
4460 | |||
4461 | Precondition: the beginning '<!E' is already read and the head | ||
4462 | stands on the 'L' of '<!ELEMENT' | ||
4463 | */ | ||
4464 | bool QXmlSimpleReader::parseElementDecl() | ||
4465 | { | ||
4466 | const signed char Init = 0; | ||
4467 | const signed char Elem = 1; // parse the beginning string | ||
4468 | const signed char Ws1 = 2; // whitespace required | ||
4469 | const signed char Nam = 3; // parse Name | ||
4470 | const signed char Ws2 = 4; // whitespace required | ||
4471 | const signed char Empty = 5; // read EMPTY | ||
4472 | const signed char Any = 6; // read ANY | ||
4473 | const signed char Cont = 7; // read contentspec (except ANY or EMPTY) | ||
4474 | const signed char Mix = 8; // read Mixed | ||
4475 | const signed char Mix2 = 9; // | ||
4476 | const signed char Mix3 = 10; // | ||
4477 | const signed char MixN1 = 11; // | ||
4478 | const signed char MixN2 = 12; // | ||
4479 | const signed char MixN3 = 13; // | ||
4480 | const signed char MixN4 = 14; // | ||
4481 | const signed char Cp = 15; // parse cp | ||
4482 | const signed char Cp2 = 16; // | ||
4483 | const signed char WsD = 17; // eat whitespace before Done | ||
4484 | const signed char Done = 18; | ||
4485 | |||
4486 | const signed char InpWs = 0; | ||
4487 | const signed char InpGt = 1; // > | ||
4488 | const signed char InpPipe = 2; // | | ||
4489 | const signed char InpOp = 3; // ( | ||
4490 | const signed char InpCp = 4; // ) | ||
4491 | const signed char InpHash = 5; // # | ||
4492 | const signed char InpQm = 6; // ? | ||
4493 | const signed char InpAst = 7; // * | ||
4494 | const signed char InpPlus = 8; // + | ||
4495 | const signed char InpA = 9; // A | ||
4496 | const signed char InpE = 10; // E | ||
4497 | const signed char InpL = 11; // L | ||
4498 | const signed char InpUnknown = 12; | ||
4499 | |||
4500 | // use some kind of state machine for parsing | ||
4501 | static const signed char table[18][13] = { | ||
4502 | /* InpWs InpGt InpPipe InpOp InpCp InpHash InpQm InpAst InpPlus InpA InpE InpL InpUnknown */ | ||
4503 | { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, Elem, -1 }, // Init | ||
4504 | { Ws1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, // Elem | ||
4505 | { -1, -1, -1, -1, -1, -1, -1, -1, -1, Nam, Nam, Nam, Nam }, // Ws1 | ||
4506 | { Ws2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, // Nam | ||
4507 | { -1, -1, -1, Cont, -1, -1, -1, -1, -1, Any, Empty, -1, -1 }, // Ws2 | ||
4508 | { WsD, Done, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, // Empty | ||
4509 | { WsD, Done, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, // Any | ||
4510 | { -1, -1, -1, Cp, Cp, Mix, -1, -1, -1, Cp, Cp, Cp, Cp }, // Cont | ||
4511 | { Mix2, -1, MixN1, -1, Mix3, -1, -1, -1, -1, -1, -1, -1, -1 }, // Mix | ||
4512 | { -1, -1, MixN1, -1, Mix3, -1, -1, -1, -1, -1, -1, -1, -1 }, // Mix2 | ||
4513 | { WsD, Done, -1, -1, -1, -1, -1, WsD, -1, -1, -1, -1, -1 }, // Mix3 | ||
4514 | { -1, -1, -1, -1, -1, -1, -1, -1, -1, MixN2, MixN2, MixN2, MixN2 }, // MixN1 | ||
4515 | { MixN3, -1, MixN1, -1, MixN4, -1, -1, -1, -1, -1, -1, -1, -1 }, // MixN2 | ||
4516 | { -1, -1, MixN1, -1, MixN4, -1, -1, -1, -1, -1, -1, -1, -1 }, // MixN3 | ||
4517 | { -1, -1, -1, -1, -1, -1, -1, WsD, -1, -1, -1, -1, -1 }, // MixN4 | ||
4518 | { WsD, Done, -1, -1, -1, -1, Cp2, Cp2, Cp2, -1, -1, -1, -1 }, // Cp | ||
4519 | { WsD, Done, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, // Cp2 | ||
4520 | { -1, Done, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } // WsD | ||
4521 | }; | ||
4522 | signed char state = Init; | ||
4523 | signed char input; | ||
4524 | bool parseOk = TRUE; | ||
4525 | |||
4526 | for (;;) { | ||
4527 | |||
4528 | // read input | ||
4529 | if ( atEnd() ) { | ||
4530 | d->error = XMLERR_UNEXPECTEDEOF; | ||
4531 | goto parseError; | ||
4532 | } | ||
4533 | if ( is_S(c) ) { | ||
4534 | input = InpWs; | ||
4535 | } else if ( c == '>' ) { | ||
4536 | input = InpGt; | ||
4537 | } else if ( c == '|' ) { | ||
4538 | input = InpPipe; | ||
4539 | } else if ( c == '(' ) { | ||
4540 | input = InpOp; | ||
4541 | } else if ( c == ')' ) { | ||
4542 | input = InpCp; | ||
4543 | } else if ( c == '#' ) { | ||
4544 | input = InpHash; | ||
4545 | } else if ( c == '?' ) { | ||
4546 | input = InpQm; | ||
4547 | } else if ( c == '*' ) { | ||
4548 | input = InpAst; | ||
4549 | } else if ( c == '+' ) { | ||
4550 | input = InpPlus; | ||
4551 | } else if ( c == 'A' ) { | ||
4552 | input = InpA; | ||
4553 | } else if ( c == 'E' ) { | ||
4554 | input = InpE; | ||
4555 | } else if ( c == 'L' ) { | ||
4556 | input = InpL; | ||
4557 | } else { | ||
4558 | input = InpUnknown; | ||
4559 | } | ||
4560 | // get new state | ||
4561 | //qDebug( "%d -%d(%c)-> %d", state, input, c.latin1(), table[state][input] ); | ||
4562 | state = table[state][input]; | ||
4563 | |||
4564 | // in some cases do special actions depending on state | ||
4565 | switch ( state ) { | ||
4566 | case Elem: | ||
4567 | parseOk = parseString( "LEMENT" ); | ||
4568 | break; | ||
4569 | case Ws1: | ||
4570 | eat_ws(); | ||
4571 | break; | ||
4572 | case Nam: | ||
4573 | parseOk = parseName(); | ||
4574 | break; | ||
4575 | case Ws2: | ||
4576 | eat_ws(); | ||
4577 | break; | ||
4578 | case Empty: | ||
4579 | parseOk = parseString( "EMPTY" ); | ||
4580 | break; | ||
4581 | case Any: | ||
4582 | parseOk = parseString( "ANY" ); | ||
4583 | break; | ||
4584 | case Cont: | ||
4585 | next_eat_ws(); | ||
4586 | break; | ||
4587 | case Mix: | ||
4588 | parseOk = parseString( "#PCDATA" ); | ||
4589 | break; | ||
4590 | case Mix2: | ||
4591 | eat_ws(); | ||
4592 | break; | ||
4593 | case Mix3: | ||
4594 | next(); | ||
4595 | break; | ||
4596 | case MixN1: | ||
4597 | next_eat_ws(); | ||
4598 | break; | ||
4599 | case MixN2: | ||
4600 | parseOk = parseName(); | ||
4601 | break; | ||
4602 | case MixN3: | ||
4603 | eat_ws(); | ||
4604 | break; | ||
4605 | case MixN4: | ||
4606 | next(); | ||
4607 | break; | ||
4608 | case Cp: | ||
4609 | parseOk = parseChoiceSeq(); | ||
4610 | break; | ||
4611 | case Cp2: | ||
4612 | next(); | ||
4613 | break; | ||
4614 | case WsD: | ||
4615 | next_eat_ws(); | ||
4616 | break; | ||
4617 | case Done: | ||
4618 | next(); | ||
4619 | break; | ||
4620 | } | ||
4621 | // no input is read after this | ||
4622 | switch ( state ) { | ||
4623 | case Elem: | ||
4624 | if( !parseOk ) { | ||
4625 | d->error = XMLERR_UNEXPECTEDCHARACTER; | ||
4626 | goto parseError; | ||
4627 | } | ||
4628 | break; | ||
4629 | case Nam: | ||
4630 | if ( !parseOk ) { | ||
4631 | d->error = XMLERR_ERRORPARSINGNAME; | ||
4632 | goto parseError; | ||
4633 | } | ||
4634 | break; | ||
4635 | case Empty: | ||
4636 | if( !parseOk ) { | ||
4637 | d->error = XMLERR_UNEXPECTEDCHARACTER; | ||
4638 | goto parseError; | ||
4639 | } | ||
4640 | break; | ||
4641 | case Any: | ||
4642 | if( !parseOk ) { | ||
4643 | d->error = XMLERR_UNEXPECTEDCHARACTER; | ||
4644 | goto parseError; | ||
4645 | } | ||
4646 | break; | ||
4647 | case Mix: | ||
4648 | if( !parseOk ) { | ||
4649 | d->error = XMLERR_UNEXPECTEDCHARACTER; | ||
4650 | goto parseError; | ||
4651 | } | ||
4652 | break; | ||
4653 | case MixN2: | ||
4654 | if ( !parseOk ) { | ||
4655 | d->error = XMLERR_ERRORPARSINGNAME; | ||
4656 | goto parseError; | ||
4657 | } | ||
4658 | break; | ||
4659 | case Cp: | ||
4660 | if ( !parseOk ) { | ||
4661 | d->error = XMLERR_ERRORPARSINGCHOICE; | ||
4662 | goto parseError; | ||
4663 | } | ||
4664 | break; | ||
4665 | case Done: | ||
4666 | return TRUE; | ||
4667 | case -1: | ||
4668 | d->error = XMLERR_UNEXPECTEDCHARACTER; | ||
4669 | goto parseError; | ||
4670 | } | ||
4671 | |||
4672 | } | ||
4673 | |||
4674 | return TRUE; | ||
4675 | |||
4676 | parseError: | ||
4677 | reportParseError(); | ||
4678 | return FALSE; | ||
4679 | } | ||
4680 | |||
4681 | /*! | ||
4682 | Parse a NotationDecl [82]. | ||
4683 | |||
4684 | Precondition: the beginning '<!' is already read and the head | ||
4685 | stands on the 'N' of '<!NOTATION' | ||
4686 | */ | ||
4687 | bool QXmlSimpleReader::parseNotationDecl() | ||
4688 | { | ||
4689 | const signed char Init = 0; | ||
4690 | const signed char Not = 1; // read NOTATION | ||
4691 | const signed char Ws1 = 2; // eat whitespaces | ||
4692 | const signed char Nam = 3; // read Name | ||
4693 | const signed char Ws2 = 4; // eat whitespaces | ||
4694 | const signed char ExtID = 5; // parse ExternalID | ||
4695 | const signed char Ws3 = 6; // eat whitespaces | ||
4696 | const signed char Done = 7; | ||
4697 | |||
4698 | const signed char InpWs = 0; | ||
4699 | const signed char InpGt = 1; // > | ||
4700 | const signed char InpN = 2; // N | ||
4701 | const signed char InpUnknown = 3; | ||
4702 | |||
4703 | // use some kind of state machine for parsing | ||
4704 | static const signed char table[7][4] = { | ||
4705 | /* InpWs InpGt InpN InpUnknown */ | ||
4706 | { -1, -1, Not, -1 }, // Init | ||
4707 | { Ws1, -1, -1, -1 }, // Not | ||
4708 | { -1, -1, Nam, Nam }, // Ws1 | ||
4709 | { Ws2, Done, -1, -1 }, // Nam | ||
4710 | { -1, Done, ExtID, ExtID }, // Ws2 | ||
4711 | { Ws3, Done, -1, -1 }, // ExtID | ||
4712 | { -1, Done, -1, -1 } // Ws3 | ||
4713 | }; | ||
4714 | signed char state = Init; | ||
4715 | signed char input; | ||
4716 | bool parseOk = TRUE; | ||
4717 | |||
4718 | for (;;) { | ||
4719 | |||
4720 | // get input | ||
4721 | if ( atEnd() ) { | ||
4722 | d->error = XMLERR_UNEXPECTEDEOF; | ||
4723 | goto parseError; | ||
4724 | } | ||
4725 | if ( is_S(c) ) { | ||
4726 | input = InpWs; | ||
4727 | } else if ( c == '>' ) { | ||
4728 | input = InpGt; | ||
4729 | } else if ( c == 'N' ) { | ||
4730 | input = InpN; | ||
4731 | } else { | ||
4732 | input = InpUnknown; | ||
4733 | } | ||
4734 | |||
4735 | // set state according to input | ||
4736 | state = table[state][input]; | ||
4737 | |||
4738 | // do some actions according to state | ||
4739 | switch ( state ) { | ||
4740 | case Not: | ||
4741 | parseOk = parseString( "NOTATION" ); | ||
4742 | break; | ||
4743 | case Ws1: | ||
4744 | eat_ws(); | ||
4745 | break; | ||
4746 | case Nam: | ||
4747 | parseOk = parseName(); | ||
4748 | break; | ||
4749 | case Ws2: | ||
4750 | eat_ws(); | ||
4751 | break; | ||
4752 | case ExtID: | ||
4753 | parseOk = parseExternalID( TRUE ); | ||
4754 | break; | ||
4755 | case Ws3: | ||
4756 | eat_ws(); | ||
4757 | break; | ||
4758 | case Done: | ||
4759 | next(); | ||
4760 | break; | ||
4761 | } | ||
4762 | // no input is read after this | ||
4763 | switch ( state ) { | ||
4764 | case Not: | ||
4765 | if ( !parseOk ) { | ||
4766 | d->error = XMLERR_UNEXPECTEDCHARACTER; | ||
4767 | goto parseError; | ||
4768 | } | ||
4769 | break; | ||
4770 | case Nam: | ||
4771 | if ( !parseOk ) { | ||
4772 | d->error = XMLERR_ERRORPARSINGNAME; | ||
4773 | goto parseError; | ||
4774 | } | ||
4775 | break; | ||
4776 | case ExtID: | ||
4777 | if ( !parseOk ) { | ||
4778 | d->error = XMLERR_ERRORPARSINGEXTERNALID; | ||
4779 | goto parseError; | ||
4780 | } | ||
4781 | // call the handler | ||
4782 | if ( dtdHnd ) { | ||
4783 | if ( !dtdHnd->notationDecl( name(), d->publicId, d->systemId ) ) { | ||
4784 | d->error = dtdHnd->errorString(); | ||
4785 | goto parseError; | ||
4786 | } | ||
4787 | } | ||
4788 | break; | ||
4789 | case Done: | ||
4790 | return TRUE; | ||
4791 | case -1: | ||
4792 | // Error | ||
4793 | d->error = XMLERR_UNEXPECTEDCHARACTER; | ||
4794 | goto parseError; | ||
4795 | } | ||
4796 | |||
4797 | } | ||
4798 | |||
4799 | return TRUE; | ||
4800 | |||
4801 | parseError: | ||
4802 | reportParseError(); | ||
4803 | return FALSE; | ||
4804 | } | ||
4805 | |||
4806 | /*! | ||
4807 | Parse choice [49] or seq [50]. | ||
4808 | |||
4809 | Precondition: the beginning '('S? is already read and the head | ||
4810 | stands on the first non-whitespace character after it. | ||
4811 | */ | ||
4812 | bool QXmlSimpleReader::parseChoiceSeq() | ||
4813 | { | ||
4814 | const signed char Init = 0; | ||
4815 | const signed char Ws1 = 1; // eat whitespace | ||
4816 | const signed char CS = 2; // choice or set | ||
4817 | const signed char Ws2 = 3; // eat whitespace | ||
4818 | const signed char More = 4; // more cp to read | ||
4819 | const signed char Name = 5; // read name | ||
4820 | const signed char Done = 6; // | ||
4821 | |||
4822 | const signed char InpWs = 0; // S | ||
4823 | const signed char InpOp = 1; // ( | ||
4824 | const signed char InpCp = 2; // ) | ||
4825 | const signed char InpQm = 3; // ? | ||
4826 | const signed char InpAst = 4; // * | ||
4827 | const signed char InpPlus = 5; // + | ||
4828 | const signed char InpPipe = 6; // | | ||
4829 | const signed char InpComm = 7; // , | ||
4830 | const signed char InpUnknown = 8; | ||
4831 | |||
4832 | // use some kind of state machine for parsing | ||
4833 | static const signed char table[6][9] = { | ||
4834 | /* InpWs InpOp InpCp InpQm InpAst InpPlus InpPipe InpComm InpUnknown */ | ||
4835 | { -1, Ws1, -1, -1, -1, -1, -1, -1, Name }, // Init | ||
4836 | { -1, CS, -1, -1, -1, -1, -1, -1, CS }, // Ws1 | ||
4837 | { Ws2, -1, Done, Ws2, Ws2, Ws2, More, More, -1 }, // CS | ||
4838 | { -1, -1, Done, -1, -1, -1, More, More, -1 }, // Ws2 | ||
4839 | { -1, Ws1, -1, -1, -1, -1, -1, -1, Name }, // More (same as Init) | ||
4840 | { Ws2, -1, Done, Ws2, Ws2, Ws2, More, More, -1 } // Name (same as CS) | ||
4841 | }; | ||
4842 | signed char state = Init; | ||
4843 | signed char input; | ||
4844 | bool parseOk = TRUE; | ||
4845 | |||
4846 | for (;;) { | ||
4847 | |||
4848 | // get input | ||
4849 | if ( atEnd() ) { | ||
4850 | d->error = XMLERR_UNEXPECTEDEOF; | ||
4851 | goto parseError; | ||
4852 | } | ||
4853 | if ( is_S(c) ) { | ||
4854 | input = InpWs; | ||
4855 | } else if ( c == '(' ) { | ||
4856 | input = InpOp; | ||
4857 | } else if ( c == ')' ) { | ||
4858 | input = InpCp; | ||
4859 | } else if ( c == '?' ) { | ||
4860 | input = InpQm; | ||
4861 | } else if ( c == '*' ) { | ||
4862 | input = InpAst; | ||
4863 | } else if ( c == '+' ) { | ||
4864 | input = InpPlus; | ||
4865 | } else if ( c == '|' ) { | ||
4866 | input = InpPipe; | ||
4867 | } else if ( c == ',' ) { | ||
4868 | input = InpComm; | ||
4869 | } else { | ||
4870 | input = InpUnknown; | ||
4871 | } | ||
4872 | |||
4873 | // set state according to input | ||
4874 | state = table[state][input]; | ||
4875 | |||
4876 | // do some actions according to state | ||
4877 | switch ( state ) { | ||
4878 | case Ws1: | ||
4879 | next_eat_ws(); | ||
4880 | break; | ||
4881 | case CS: | ||
4882 | parseOk = parseChoiceSeq(); | ||
4883 | break; | ||
4884 | case Ws2: | ||
4885 | next_eat_ws(); | ||
4886 | break; | ||
4887 | case More: | ||
4888 | next_eat_ws(); | ||
4889 | break; | ||
4890 | case Name: | ||
4891 | parseOk = parseName(); | ||
4892 | break; | ||
4893 | case Done: | ||
4894 | next(); | ||
4895 | break; | ||
4896 | } | ||
4897 | // no input is read after this | ||
4898 | switch ( state ) { | ||
4899 | case CS: | ||
4900 | if ( !parseOk ) { | ||
4901 | d->error = XMLERR_ERRORPARSINGCHOICE; | ||
4902 | goto parseError; | ||
4903 | } | ||
4904 | break; | ||
4905 | case Name: | ||
4906 | if ( !parseOk ) { | ||
4907 | d->error = XMLERR_ERRORPARSINGNAME; | ||
4908 | goto parseError; | ||
4909 | } | ||
4910 | break; | ||
4911 | case Done: | ||
4912 | return TRUE; | ||
4913 | case -1: | ||
4914 | // Error | ||
4915 | d->error = XMLERR_UNEXPECTEDCHARACTER; | ||
4916 | goto parseError; | ||
4917 | } | ||
4918 | |||
4919 | } | ||
4920 | |||
4921 | return TRUE; | ||
4922 | |||
4923 | parseError: | ||
4924 | reportParseError(); | ||
4925 | return FALSE; | ||
4926 | } | ||
4927 | |||
4928 | /*! | ||
4929 | Parse a EntityDecl [70]. | ||
4930 | |||
4931 | Precondition: the beginning '<!E' is already read and the head | ||
4932 | stand on the 'N' of '<!ENTITY' | ||
4933 | */ | ||
4934 | bool QXmlSimpleReader::parseEntityDecl() | ||
4935 | { | ||
4936 | const signed char Init = 0; | ||
4937 | const signed char Ent = 1; // parse "ENTITY" | ||
4938 | const signed char Ws1 = 2; // white space read | ||
4939 | const signed char Name = 3; // parse name | ||
4940 | const signed char Ws2 = 4; // white space read | ||
4941 | const signed char EValue = 5; // parse entity value | ||
4942 | const signed char ExtID = 6; // parse ExternalID | ||
4943 | const signed char Ws3 = 7; // white space read | ||
4944 | const signed char Ndata = 8; // parse "NDATA" | ||
4945 | const signed char Ws4 = 9; // white space read | ||
4946 | const signed char NNam = 10; // parse name | ||
4947 | const signed char PEDec = 11; // parse PEDecl | ||
4948 | const signed char Ws6 = 12; // white space read | ||
4949 | const signed char PENam = 13; // parse name | ||
4950 | const signed char Ws7 = 14; // white space read | ||
4951 | const signed char PEVal = 15; // parse entity value | ||
4952 | const signed char PEEID = 16; // parse ExternalID | ||
4953 | const signed char WsE = 17; // white space read | ||
4954 | const signed char EDDone = 19; // done, but also report an external, unparsed entity decl | ||
4955 | const signed char Done = 18; | ||
4956 | |||
4957 | const signed char InpWs = 0; // white space | ||
4958 | const signed char InpPer = 1; // % | ||
4959 | const signed char InpQuot = 2; // " or ' | ||
4960 | const signed char InpGt = 3; // > | ||
4961 | const signed char InpN = 4; // N | ||
4962 | const signed char InpUnknown = 5; | ||
4963 | |||
4964 | // use some kind of state machine for parsing | ||
4965 | static const signed char table[18][6] = { | ||
4966 | /* InpWs InpPer InpQuot InpGt InpN InpUnknown */ | ||
4967 | { -1, -1, -1, -1, Ent, -1 }, // Init | ||
4968 | { Ws1, -1, -1, -1, -1, -1 }, // Ent | ||
4969 | { -1, PEDec, -1, -1, Name, Name }, // Ws1 | ||
4970 | { Ws2, -1, -1, -1, -1, -1 }, // Name | ||
4971 | { -1, -1, EValue, -1, -1, ExtID }, // Ws2 | ||
4972 | { WsE, -1, -1, Done, -1, -1 }, // EValue | ||
4973 | { Ws3, -1, -1, EDDone,-1, -1 }, // ExtID | ||
4974 | { -1, -1, -1, EDDone,Ndata, -1 }, // Ws3 | ||
4975 | { Ws4, -1, -1, -1, -1, -1 }, // Ndata | ||
4976 | { -1, -1, -1, -1, NNam, NNam }, // Ws4 | ||
4977 | { WsE, -1, -1, Done, -1, -1 }, // NNam | ||
4978 | { Ws6, -1, -1, -1, -1, -1 }, // PEDec | ||
4979 | { -1, -1, -1, -1, PENam, PENam }, // Ws6 | ||
4980 | { Ws7, -1, -1, -1, -1, -1 }, // PENam | ||
4981 | { -1, -1, PEVal, -1, -1, PEEID }, // Ws7 | ||
4982 | { WsE, -1, -1, Done, -1, -1 }, // PEVal | ||
4983 | { WsE, -1, -1, Done, -1, -1 }, // PEEID | ||
4984 | { -1, -1, -1, Done, -1, -1 } // WsE | ||
4985 | }; | ||
4986 | signed char state = Init; | ||
4987 | signed char input; | ||
4988 | bool parseOk = TRUE; | ||
4989 | |||
4990 | for (;;) { | ||
4991 | |||
4992 | // get input | ||
4993 | if ( atEnd() ) { | ||
4994 | d->error = XMLERR_UNEXPECTEDEOF; | ||
4995 | goto parseError; | ||
4996 | } | ||
4997 | if ( is_S(c) ) { | ||
4998 | input = InpWs; | ||
4999 | } else if ( c == '%' ) { | ||
5000 | input = InpPer; | ||
5001 | } else if ( c == '"' || c == '\'' ) { | ||
5002 | input = InpQuot; | ||
5003 | } else if ( c == '>' ) { | ||
5004 | input = InpGt; | ||
5005 | } else if ( c == 'N' ) { | ||
5006 | input = InpN; | ||
5007 | } else { | ||
5008 | input = InpUnknown; | ||
5009 | } | ||
5010 | |||
5011 | // set state according to input | ||
5012 | state = table[state][input]; | ||
5013 | |||
5014 | // do some actions according to state | ||
5015 | switch ( state ) { | ||
5016 | case Ent: | ||
5017 | parseOk = parseString( "NTITY" ); | ||
5018 | break; | ||
5019 | case Ws1: | ||
5020 | eat_ws(); | ||
5021 | break; | ||
5022 | case Name: | ||
5023 | parseOk = parseName(); | ||
5024 | break; | ||
5025 | case Ws2: | ||
5026 | eat_ws(); | ||
5027 | break; | ||
5028 | case EValue: | ||
5029 | parseOk = parseEntityValue(); | ||
5030 | break; | ||
5031 | case ExtID: | ||
5032 | parseOk = parseExternalID(); | ||
5033 | break; | ||
5034 | case Ws3: | ||
5035 | eat_ws(); | ||
5036 | break; | ||
5037 | case Ndata: | ||
5038 | parseOk = parseString( "NDATA" ); | ||
5039 | break; | ||
5040 | case Ws4: | ||
5041 | eat_ws(); | ||
5042 | break; | ||
5043 | case NNam: | ||
5044 | parseOk = parseName( TRUE ); | ||
5045 | break; | ||
5046 | case PEDec: | ||
5047 | next(); | ||
5048 | break; | ||
5049 | case Ws6: | ||
5050 | eat_ws(); | ||
5051 | break; | ||
5052 | case PENam: | ||
5053 | parseOk = parseName(); | ||
5054 | break; | ||
5055 | case Ws7: | ||
5056 | eat_ws(); | ||
5057 | break; | ||
5058 | case PEVal: | ||
5059 | parseOk = parseEntityValue(); | ||
5060 | break; | ||
5061 | case PEEID: | ||
5062 | parseOk = parseExternalID(); | ||
5063 | break; | ||
5064 | case WsE: | ||
5065 | eat_ws(); | ||
5066 | break; | ||
5067 | case EDDone: | ||
5068 | next(); | ||
5069 | break; | ||
5070 | case Done: | ||
5071 | next(); | ||
5072 | break; | ||
5073 | } | ||
5074 | // no input is read after this | ||
5075 | switch ( state ) { | ||
5076 | case Ent: | ||
5077 | if ( !parseOk ) { | ||
5078 | d->error = XMLERR_UNEXPECTEDCHARACTER; | ||
5079 | goto parseError; | ||
5080 | } | ||
5081 | break; | ||
5082 | case Name: | ||
5083 | if ( !parseOk ) { | ||
5084 | d->error = XMLERR_ERRORPARSINGNAME; | ||
5085 | goto parseError; | ||
5086 | } | ||
5087 | break; | ||
5088 | case EValue: | ||
5089 | if ( !parseOk ) { | ||
5090 | d->error = XMLERR_ERRORPARSINGENTITYVALUE; | ||
5091 | goto parseError; | ||
5092 | } | ||
5093 | if ( !entityExist( name() ) ) { | ||
5094 | d->entities.insert( name(), string() ); | ||
5095 | if ( declHnd ) { | ||
5096 | if ( !declHnd->internalEntityDecl( name(), string() ) ) { | ||
5097 | d->error = declHnd->errorString(); | ||
5098 | goto parseError; | ||
5099 | } | ||
5100 | } | ||
5101 | } | ||
5102 | break; | ||
5103 | case ExtID: | ||
5104 | if ( !parseOk ) { | ||
5105 | d->error = XMLERR_ERRORPARSINGEXTERNALID; | ||
5106 | goto parseError; | ||
5107 | } | ||
5108 | break; | ||
5109 | case Ndata: | ||
5110 | if ( !parseOk ) { | ||
5111 | d->error = XMLERR_UNEXPECTEDCHARACTER; | ||
5112 | goto parseError; | ||
5113 | } | ||
5114 | break; | ||
5115 | case NNam: | ||
5116 | if ( !parseOk ) { | ||
5117 | d->error = XMLERR_ERRORPARSINGNAME; | ||
5118 | goto parseError; | ||
5119 | } | ||
5120 | if ( !entityExist( name() ) ) { | ||
5121 | d->externEntities.insert( name(), QXmlSimpleReaderPrivate::ExternEntity( d->publicId, d->systemId, ref() ) ); | ||
5122 | if ( dtdHnd ) { | ||
5123 | if ( !dtdHnd->unparsedEntityDecl( name(), d->publicId, d->systemId, ref() ) ) { | ||
5124 | d->error = declHnd->errorString(); | ||
5125 | goto parseError; | ||
5126 | } | ||
5127 | } | ||
5128 | } | ||
5129 | break; | ||
5130 | case PENam: | ||
5131 | if ( !parseOk ) { | ||
5132 | d->error = XMLERR_ERRORPARSINGNAME; | ||
5133 | goto parseError; | ||
5134 | } | ||
5135 | break; | ||
5136 | case PEVal: | ||
5137 | if ( !parseOk ) { | ||
5138 | d->error = XMLERR_ERRORPARSINGENTITYVALUE; | ||
5139 | goto parseError; | ||
5140 | } | ||
5141 | if ( !entityExist( name() ) ) { | ||
5142 | d->parameterEntities.insert( name(), string() ); | ||
5143 | if ( declHnd ) { | ||
5144 | if ( !declHnd->internalEntityDecl( QString("%")+name(), string() ) ) { | ||
5145 | d->error = declHnd->errorString(); | ||
5146 | goto parseError; | ||
5147 | } | ||
5148 | } | ||
5149 | } | ||
5150 | break; | ||
5151 | case PEEID: | ||
5152 | if ( !parseOk ) { | ||
5153 | d->error = XMLERR_ERRORPARSINGEXTERNALID; | ||
5154 | goto parseError; | ||
5155 | } | ||
5156 | if ( !entityExist( name() ) ) { | ||
5157 | d->externParameterEntities.insert( name(), QXmlSimpleReaderPrivate::ExternParameterEntity( d->publicId, d->systemId ) ); | ||
5158 | if ( declHnd ) { | ||
5159 | if ( !declHnd->externalEntityDecl( QString("%")+name(), d->publicId, d->systemId ) ) { | ||
5160 | d->error = declHnd->errorString(); | ||
5161 | goto parseError; | ||
5162 | } | ||
5163 | } | ||
5164 | } | ||
5165 | break; | ||
5166 | case EDDone: | ||
5167 | if ( !entityExist( name() ) ) { | ||
5168 | d->externEntities.insert( name(), QXmlSimpleReaderPrivate::ExternEntity( d->publicId, d->systemId, QString::null ) ); | ||
5169 | if ( declHnd ) { | ||
5170 | if ( !declHnd->externalEntityDecl( name(), d->publicId, d->systemId ) ) { | ||
5171 | d->error = declHnd->errorString(); | ||
5172 | goto parseError; | ||
5173 | } | ||
5174 | } | ||
5175 | } | ||
5176 | return TRUE; | ||
5177 | case Done: | ||
5178 | return TRUE; | ||
5179 | case -1: | ||
5180 | // Error | ||
5181 | d->error = XMLERR_LETTEREXPECTED; | ||
5182 | goto parseError; | ||
5183 | } | ||
5184 | |||
5185 | } | ||
5186 | |||
5187 | return TRUE; | ||
5188 | |||
5189 | parseError: | ||
5190 | reportParseError(); | ||
5191 | return FALSE; | ||
5192 | } | ||
5193 | |||
5194 | /*! | ||
5195 | Parse a EntityValue [9] | ||
5196 | */ | ||
5197 | bool QXmlSimpleReader::parseEntityValue() | ||
5198 | { | ||
5199 | bool tmp; | ||
5200 | |||
5201 | const signed char Init = 0; | ||
5202 | const signed char Dq = 1; // EntityValue is double quoted | ||
5203 | const signed char DqC = 2; // signed character | ||
5204 | const signed char DqPER = 3; // PERefence | ||
5205 | const signed char DqRef = 4; // Reference | ||
5206 | const signed char Sq = 5; // EntityValue is double quoted | ||
5207 | const signed char SqC = 6; // signed character | ||
5208 | const signed char SqPER = 7; // PERefence | ||
5209 | const signed char SqRef = 8; // Reference | ||
5210 | const signed char Done = 9; | ||
5211 | |||
5212 | const signed char InpDq = 0; // " | ||
5213 | const signed char InpSq = 1; // ' | ||
5214 | const signed char InpAmp = 2; // & | ||
5215 | const signed char InpPer = 3; // % | ||
5216 | const signed char InpUnknown = 4; | ||
5217 | |||
5218 | // use some kind of state machine for parsing | ||
5219 | static const signed char table[9][5] = { | ||
5220 | /* InpDq InpSq InpAmp InpPer InpUnknown */ | ||
5221 | { Dq, Sq, -1, -1, -1 }, // Init | ||
5222 | { Done, DqC, DqRef, DqPER, DqC }, // Dq | ||
5223 | { Done, DqC, DqRef, DqPER, DqC }, // DqC | ||
5224 | { Done, DqC, DqRef, DqPER, DqC }, // DqPER | ||
5225 | { Done, DqC, DqRef, DqPER, DqC }, // DqRef | ||
5226 | { SqC, Done, SqRef, SqPER, SqC }, // Sq | ||
5227 | { SqC, Done, SqRef, SqPER, SqC }, // SqC | ||
5228 | { SqC, Done, SqRef, SqPER, SqC }, // SqPER | ||
5229 | { SqC, Done, SqRef, SqPER, SqC } // SqRef | ||
5230 | }; | ||
5231 | signed char state = Init; | ||
5232 | signed char input; | ||
5233 | bool parseOk = TRUE; | ||
5234 | |||
5235 | for (;;) { | ||
5236 | |||
5237 | // get input | ||
5238 | if ( atEnd() ) { | ||
5239 | d->error = XMLERR_UNEXPECTEDEOF; | ||
5240 | goto parseError; | ||
5241 | } | ||
5242 | if ( c == '"' ) { | ||
5243 | input = InpDq; | ||
5244 | } else if ( c == '\'' ) { | ||
5245 | input = InpSq; | ||
5246 | } else if ( c == '&' ) { | ||
5247 | input = InpAmp; | ||
5248 | } else if ( c == '%' ) { | ||
5249 | input = InpPer; | ||
5250 | } else { | ||
5251 | input = InpUnknown; | ||
5252 | } | ||
5253 | |||
5254 | // set state according to input | ||
5255 | state = table[state][input]; | ||
5256 | |||
5257 | // do some actions according to state | ||
5258 | switch ( state ) { | ||
5259 | case Dq: | ||
5260 | case Sq: | ||
5261 | stringClear(); | ||
5262 | next(); | ||
5263 | break; | ||
5264 | case DqC: | ||
5265 | case SqC: | ||
5266 | stringAddC(); | ||
5267 | next(); | ||
5268 | break; | ||
5269 | case DqPER: | ||
5270 | case SqPER: | ||
5271 | parseOk = parsePEReference( InEntityValue ); | ||
5272 | break; | ||
5273 | case DqRef: | ||
5274 | case SqRef: | ||
5275 | parseOk = parseReference( tmp, InEntityValue ); | ||
5276 | break; | ||
5277 | case Done: | ||
5278 | next(); | ||
5279 | break; | ||
5280 | } | ||
5281 | // no input is read after this | ||
5282 | switch ( state ) { | ||
5283 | case DqPER: | ||
5284 | case SqPER: | ||
5285 | if ( !parseOk ) { | ||
5286 | d->error = XMLERR_ERRORPARSINGDOCTYPE; | ||
5287 | goto parseError; | ||
5288 | } | ||
5289 | break; | ||
5290 | case DqRef: | ||
5291 | case SqRef: | ||
5292 | if ( !parseOk ) { | ||
5293 | d->error = XMLERR_ERRORPARSINGREFERENCE; | ||
5294 | goto parseError; | ||
5295 | } | ||
5296 | break; | ||
5297 | case Done: | ||
5298 | return TRUE; | ||
5299 | case -1: | ||
5300 | // Error | ||
5301 | d->error = XMLERR_LETTEREXPECTED; | ||
5302 | goto parseError; | ||
5303 | } | ||
5304 | |||
5305 | } | ||
5306 | |||
5307 | return TRUE; | ||
5308 | |||
5309 | parseError: | ||
5310 | reportParseError(); | ||
5311 | return FALSE; | ||
5312 | } | ||
5313 | |||
5314 | /*! | ||
5315 | Parse a comment [15]. | ||
5316 | |||
5317 | Precondition: the beginning '<!' of the comment is already read and the head | ||
5318 | stands on the first '-' of '<!--'. | ||
5319 | |||
5320 | If this funktion was successful, the head-position is on the first | ||
5321 | character after the comment. | ||
5322 | */ | ||
5323 | bool QXmlSimpleReader::parseComment() | ||
5324 | { | ||
5325 | const signed char Init = 0; | ||
5326 | const signed char Dash1 = 1; // the first dash was read | ||
5327 | const signed char Dash2 = 2; // the second dash was read | ||
5328 | const signed char Com = 3; // read comment | ||
5329 | const signed char Com2 = 4; // read comment (help state) | ||
5330 | const signed char ComE = 5; // finished reading comment | ||
5331 | const signed char Done = 6; | ||
5332 | |||
5333 | const signed char InpDash = 0; // - | ||
5334 | const signed char InpGt = 1; // > | ||
5335 | const signed char InpUnknown = 2; | ||
5336 | |||
5337 | // use some kind of state machine for parsing | ||
5338 | static const signed char table[6][3] = { | ||
5339 | /* InpDash InpGt InpUnknown */ | ||
5340 | { Dash1, -1, -1 }, // Init | ||
5341 | { Dash2, -1, -1 }, // Dash1 | ||
5342 | { Com2, Com, Com }, // Dash2 | ||
5343 | { Com2, Com, Com }, // Com | ||
5344 | { ComE, Com, Com }, // Com2 | ||
5345 | { -1, Done, -1 } // ComE | ||
5346 | }; | ||
5347 | signed char state = Init; | ||
5348 | signed char input; | ||
5349 | |||
5350 | for (;;) { | ||
5351 | |||
5352 | // get input | ||
5353 | if ( atEnd() ) { | ||
5354 | d->error = XMLERR_UNEXPECTEDEOF; | ||
5355 | goto parseError; | ||
5356 | } | ||
5357 | if ( c == '-' ) { | ||
5358 | input = InpDash; | ||
5359 | } else if ( c == '>' ) { | ||
5360 | input = InpGt; | ||
5361 | } else { | ||
5362 | input = InpUnknown; | ||
5363 | } | ||
5364 | |||
5365 | // set state according to input | ||
5366 | state = table[state][input]; | ||
5367 | |||
5368 | // do some actions according to state | ||
5369 | switch ( state ) { | ||
5370 | case Dash1: | ||
5371 | next(); | ||
5372 | break; | ||
5373 | case Dash2: | ||
5374 | next(); | ||
5375 | break; | ||
5376 | case Com: | ||
5377 | stringAddC(); | ||
5378 | next(); | ||
5379 | break; | ||
5380 | case Com2: | ||
5381 | next(); | ||
5382 | break; | ||
5383 | case ComE: | ||
5384 | next(); | ||
5385 | break; | ||
5386 | case Done: | ||
5387 | next(); | ||
5388 | break; | ||
5389 | } | ||
5390 | // no input is read after this | ||
5391 | switch ( state ) { | ||
5392 | case Dash2: | ||
5393 | stringClear(); | ||
5394 | break; | ||
5395 | case Com2: | ||
5396 | // if next character is not a dash than don't skip it | ||
5397 | if ( c != '-' ) { | ||
5398 | stringAddC( '-' ); | ||
5399 | } | ||
5400 | break; | ||
5401 | case Done: | ||
5402 | return TRUE; | ||
5403 | case -1: | ||
5404 | // Error | ||
5405 | d->error = XMLERR_ERRORPARSINGCOMMENT; | ||
5406 | goto parseError; | ||
5407 | } | ||
5408 | |||
5409 | } | ||
5410 | |||
5411 | return TRUE; | ||
5412 | |||
5413 | parseError: | ||
5414 | reportParseError(); | ||
5415 | return FALSE; | ||
5416 | } | ||
5417 | |||
5418 | /*! | ||
5419 | Parse a Attribute [41]. | ||
5420 | |||
5421 | Precondition: the head stands on the first character of the name of the | ||
5422 | attribute (i.e. all whitespaces are already parsed). | ||
5423 | |||
5424 | The head stand on the next character after the end quotes. The variable name | ||
5425 | contains the name of the attribute and the variable string contains the value | ||
5426 | of the attribute. | ||
5427 | */ | ||
5428 | bool QXmlSimpleReader::parseAttribute() | ||
5429 | { | ||
5430 | const signed char Init = 0; | ||
5431 | const signed char PName = 1; // parse name | ||
5432 | const signed char Ws = 2; // eat ws | ||
5433 | const signed char Eq = 3; // the '=' was read | ||
5434 | const signed char Quotes = 4; // " or ' were read | ||
5435 | |||
5436 | const signed char InpNameBe = 0; | ||
5437 | const signed char InpEq = 1; // = | ||
5438 | const signed char InpDq = 2; // " | ||
5439 | const signed char InpSq = 3; // ' | ||
5440 | const signed char InpUnknown = 4; | ||
5441 | |||
5442 | // use some kind of state machine for parsing | ||
5443 | static const signed char table[4][5] = { | ||
5444 | /* InpNameBe InpEq InpDq InpSq InpUnknown */ | ||
5445 | { PName, -1, -1, -1, -1 }, // Init | ||
5446 | { -1, Eq, -1, -1, Ws }, // PName | ||
5447 | { -1, Eq, -1, -1, -1 }, // Ws | ||
5448 | { -1, -1, Quotes, Quotes, -1 } // Eq | ||
5449 | }; | ||
5450 | signed char state = Init; | ||
5451 | signed char input; | ||
5452 | bool parseOk = TRUE; | ||
5453 | |||
5454 | for (;;) { | ||
5455 | |||
5456 | // get input | ||
5457 | if ( atEnd() ) { | ||
5458 | d->error = XMLERR_UNEXPECTEDEOF; | ||
5459 | goto parseError; | ||
5460 | } | ||
5461 | if ( is_NameBeginning(c) ) { | ||
5462 | input = InpNameBe; | ||
5463 | } else if ( c == '=' ) { | ||
5464 | input = InpEq; | ||
5465 | } else if ( c == '"' ) { | ||
5466 | input = InpDq; | ||
5467 | } else if ( c == '\'' ) { | ||
5468 | input = InpSq; | ||
5469 | } else { | ||
5470 | input = InpUnknown; | ||
5471 | } | ||
5472 | |||
5473 | // set state according to input | ||
5474 | state = table[state][input]; | ||
5475 | |||
5476 | // do some actions according to state | ||
5477 | switch ( state ) { | ||
5478 | case PName: | ||
5479 | parseOk = parseName(); | ||
5480 | break; | ||
5481 | case Ws: | ||
5482 | eat_ws(); | ||
5483 | break; | ||
5484 | case Eq: | ||
5485 | next_eat_ws(); | ||
5486 | break; | ||
5487 | case Quotes: | ||
5488 | parseOk = parseAttValue(); | ||
5489 | break; | ||
5490 | } | ||
5491 | // no input is read after this | ||
5492 | switch ( state ) { | ||
5493 | case PName: | ||
5494 | if ( !parseOk ) { | ||
5495 | d->error = XMLERR_ERRORPARSINGNAME; | ||
5496 | goto parseError; | ||
5497 | } | ||
5498 | break; | ||
5499 | case Quotes: | ||
5500 | if ( !parseOk ) { | ||
5501 | d->error = XMLERR_ERRORPARSINGATTVALUE; | ||
5502 | goto parseError; | ||
5503 | } | ||
5504 | // Done | ||
5505 | return TRUE; | ||
5506 | case -1: | ||
5507 | // Error | ||
5508 | d->error = XMLERR_UNEXPECTEDCHARACTER; | ||
5509 | goto parseError; | ||
5510 | } | ||
5511 | |||
5512 | } | ||
5513 | |||
5514 | return TRUE; | ||
5515 | |||
5516 | parseError: | ||
5517 | reportParseError(); | ||
5518 | return FALSE; | ||
5519 | } | ||
5520 | |||
5521 | /*! | ||
5522 | Parse a Name [5] and store the name in name or ref (if useRef is TRUE). | ||
5523 | */ | ||
5524 | bool QXmlSimpleReader::parseName( bool useRef ) | ||
5525 | { | ||
5526 | const signed char Init = 0; | ||
5527 | const signed char Name1 = 1; // parse first signed character of the name | ||
5528 | const signed char Name = 2; // parse name | ||
5529 | const signed char Done = 3; | ||
5530 | |||
5531 | const signed char InpNameBe = 0; // name beginning signed characters | ||
5532 | const signed char InpNameCh = 1; // NameChar without InpNameBe | ||
5533 | const signed char InpUnknown = 2; | ||
5534 | |||
5535 | // use some kind of state machine for parsing | ||
5536 | static const signed char table[3][3] = { | ||
5537 | /* InpNameBe InpNameCh InpUnknown */ | ||
5538 | { Name1, -1, -1 }, // Init | ||
5539 | { Name, Name, Done }, // Name1 | ||
5540 | { Name, Name, Done } // Name | ||
5541 | }; | ||
5542 | signed char state = Init; | ||
5543 | signed char input; | ||
5544 | |||
5545 | for (;;) { | ||
5546 | |||
5547 | // get input | ||
5548 | if ( atEnd() ) { | ||
5549 | d->error = XMLERR_UNEXPECTEDEOF; | ||
5550 | goto parseError; | ||
5551 | } | ||
5552 | if ( is_NameBeginning(c) ) { | ||
5553 | input = InpNameBe; | ||
5554 | } else if ( is_NameChar(c) ) { | ||
5555 | input = InpNameCh; | ||
5556 | } else { | ||
5557 | input = InpUnknown; | ||
5558 | } | ||
5559 | |||
5560 | // set state according to input | ||
5561 | state = table[state][input]; | ||
5562 | |||
5563 | // do some actions according to state | ||
5564 | switch ( state ) { | ||
5565 | case Name1: | ||
5566 | if ( useRef ) { | ||
5567 | refClear(); | ||
5568 | refAddC(); | ||
5569 | } else { | ||
5570 | nameClear(); | ||
5571 | nameAddC(); | ||
5572 | } | ||
5573 | next(); | ||
5574 | break; | ||
5575 | case Name: | ||
5576 | if ( useRef ) { | ||
5577 | refAddC(); | ||
5578 | } else { | ||
5579 | nameAddC(); | ||
5580 | } | ||
5581 | next(); | ||
5582 | break; | ||
5583 | } | ||
5584 | // no input is read after this | ||
5585 | switch ( state ) { | ||
5586 | case Done: | ||
5587 | return TRUE; | ||
5588 | case -1: | ||
5589 | // Error | ||
5590 | d->error = XMLERR_LETTEREXPECTED; | ||
5591 | goto parseError; | ||
5592 | } | ||
5593 | |||
5594 | } | ||
5595 | |||
5596 | return TRUE; | ||
5597 | |||
5598 | parseError: | ||
5599 | reportParseError(); | ||
5600 | return FALSE; | ||
5601 | } | ||
5602 | |||
5603 | /*! | ||
5604 | Parse a Nmtoken [7] and store the name in name. | ||
5605 | */ | ||
5606 | bool QXmlSimpleReader::parseNmtoken() | ||
5607 | { | ||
5608 | const signed char Init = 0; | ||
5609 | const signed char NameF = 1; | ||
5610 | const signed char Name = 2; | ||
5611 | const signed char Done = 3; | ||
5612 | |||
5613 | const signed char InpNameCh = 0; // NameChar without InpNameBe | ||
5614 | const signed char InpUnknown = 1; | ||
5615 | |||
5616 | // use some kind of state machine for parsing | ||
5617 | static const signed char table[3][2] = { | ||
5618 | /* InpNameCh InpUnknown */ | ||
5619 | { NameF, -1 }, // Init | ||
5620 | { Name, Done }, // NameF | ||
5621 | { Name, Done } // Name | ||
5622 | }; | ||
5623 | signed char state = Init; | ||
5624 | signed char input; | ||
5625 | |||
5626 | for (;;) { | ||
5627 | |||
5628 | // get input | ||
5629 | if ( atEnd() ) { | ||
5630 | d->error = XMLERR_UNEXPECTEDEOF; | ||
5631 | goto parseError; | ||
5632 | } | ||
5633 | if ( is_NameChar(c) ) { | ||
5634 | input = InpNameCh; | ||
5635 | } else { | ||
5636 | input = InpUnknown; | ||
5637 | } | ||
5638 | |||
5639 | // set state according to input | ||
5640 | state = table[state][input]; | ||
5641 | |||
5642 | // do some actions according to state | ||
5643 | switch ( state ) { | ||
5644 | case NameF: | ||
5645 | nameClear(); | ||
5646 | nameAddC(); | ||
5647 | next(); | ||
5648 | break; | ||
5649 | case Name: | ||
5650 | nameAddC(); | ||
5651 | next(); | ||
5652 | break; | ||
5653 | } | ||
5654 | // no input is read after this | ||
5655 | switch ( state ) { | ||
5656 | case Done: | ||
5657 | return TRUE; | ||
5658 | case -1: | ||
5659 | // Error | ||
5660 | d->error = XMLERR_LETTEREXPECTED; | ||
5661 | goto parseError; | ||
5662 | } | ||
5663 | |||
5664 | } | ||
5665 | |||
5666 | return TRUE; | ||
5667 | |||
5668 | parseError: | ||
5669 | reportParseError(); | ||
5670 | return FALSE; | ||
5671 | } | ||
5672 | |||
5673 | /*! | ||
5674 | Parse a Reference [67]. | ||
5675 | |||
5676 | charDataRead is set to TRUE if the reference must not be parsed. The | ||
5677 | character(s) which the reference mapped to are appended to string. The | ||
5678 | head stands on the first character after the reference. | ||
5679 | |||
5680 | charDataRead is set to FALSE if the reference must be parsed. The | ||
5681 | charachter(s) which the reference mapped to are inserted at the reference | ||
5682 | position. The head stands on the first character of the replacement). | ||
5683 | */ | ||
5684 | bool QXmlSimpleReader::parseReference( bool &charDataRead, EntityRecognitionContext context ) | ||
5685 | { | ||
5686 | // temporary variables | ||
5687 | uint tmp; | ||
5688 | bool ok; | ||
5689 | |||
5690 | const signed char Init = 0; | ||
5691 | const signed char SRef = 1; // start of a reference | ||
5692 | const signed char ChRef = 2; // parse CharRef | ||
5693 | const signed char ChDec = 3; // parse CharRef decimal | ||
5694 | const signed char ChHexS = 4; // start CharRef hexadecimal | ||
5695 | const signed char ChHex = 5; // parse CharRef hexadecimal | ||
5696 | const signed char Name = 6; // parse name | ||
5697 | const signed char DoneD = 7; // done CharRef decimal | ||
5698 | const signed char DoneH = 8; // done CharRef hexadecimal | ||
5699 | const signed char DoneN = 9; // done EntityRef | ||
5700 | |||
5701 | const signed char InpAmp = 0; // & | ||
5702 | const signed char InpSemi = 1; // ; | ||
5703 | const signed char InpHash = 2; // # | ||
5704 | const signed char InpX = 3; // x | ||
5705 | const signed char InpNum = 4; // 0-9 | ||
5706 | const signed char InpHex = 5; // a-f A-F | ||
5707 | const signed char InpUnknown = 6; | ||
5708 | |||
5709 | // use some kind of state machine for parsing | ||
5710 | static const signed char table[8][7] = { | ||
5711 | /* InpAmp InpSemi InpHash InpX InpNum InpHex InpUnknown */ | ||
5712 | { SRef, -1, -1, -1, -1, -1, -1 }, // Init | ||
5713 | { -1, -1, ChRef, Name, Name, Name, Name }, // SRef | ||
5714 | { -1, -1, -1, ChHexS, ChDec, -1, -1 }, // ChRef | ||
5715 | { -1, DoneD, -1, -1, ChDec, -1, -1 }, // ChDec | ||
5716 | { -1, -1, -1, -1, ChHex, ChHex, -1 }, // ChHexS | ||
5717 | { -1, DoneH, -1, -1, ChHex, ChHex, -1 }, // ChHex | ||
5718 | { -1, DoneN, -1, -1, -1, -1, -1 } // Name | ||
5719 | }; | ||
5720 | signed char state = Init; | ||
5721 | signed char input; | ||
5722 | |||
5723 | for (;;) { | ||
5724 | |||
5725 | // get input | ||
5726 | if ( atEnd() ) { | ||
5727 | d->error = XMLERR_UNEXPECTEDEOF; | ||
5728 | goto parseError; | ||
5729 | } | ||
5730 | if ( c.row() ) { | ||
5731 | input = InpUnknown; | ||
5732 | } else if ( c.cell() == '&' ) { | ||
5733 | input = InpAmp; | ||
5734 | } else if ( c.cell() == ';' ) { | ||
5735 | input = InpSemi; | ||
5736 | } else if ( c.cell() == '#' ) { | ||
5737 | input = InpHash; | ||
5738 | } else if ( c.cell() == 'x' ) { | ||
5739 | input = InpX; | ||
5740 | } else if ( '0' <= c.cell() && c.cell() <= '9' ) { | ||
5741 | input = InpNum; | ||
5742 | } else if ( 'a' <= c.cell() && c.cell() <= 'f' ) { | ||
5743 | input = InpHex; | ||
5744 | } else if ( 'A' <= c.cell() && c.cell() <= 'F' ) { | ||
5745 | input = InpHex; | ||
5746 | } else { | ||
5747 | input = InpUnknown; | ||
5748 | } | ||
5749 | |||
5750 | // set state according to input | ||
5751 | state = table[state][input]; | ||
5752 | |||
5753 | // do some actions according to state | ||
5754 | switch ( state ) { | ||
5755 | case SRef: | ||
5756 | refClear(); | ||
5757 | next(); | ||
5758 | break; | ||
5759 | case ChRef: | ||
5760 | next(); | ||
5761 | break; | ||
5762 | case ChDec: | ||
5763 | refAddC(); | ||
5764 | next(); | ||
5765 | break; | ||
5766 | case ChHexS: | ||
5767 | next(); | ||
5768 | break; | ||
5769 | case ChHex: | ||
5770 | refAddC(); | ||
5771 | next(); | ||
5772 | break; | ||
5773 | case Name: | ||
5774 | // read the name into the ref | ||
5775 | parseName( TRUE ); | ||
5776 | break; | ||
5777 | case DoneD: | ||
5778 | tmp = ref().toUInt( &ok, 10 ); | ||
5779 | if ( ok ) { | ||
5780 | stringAddC( QChar(tmp) ); | ||
5781 | } else { | ||
5782 | d->error = XMLERR_ERRORPARSINGREFERENCE; | ||
5783 | goto parseError; | ||
5784 | } | ||
5785 | charDataRead = TRUE; | ||
5786 | next(); | ||
5787 | break; | ||
5788 | case DoneH: | ||
5789 | tmp = ref().toUInt( &ok, 16 ); | ||
5790 | if ( ok ) { | ||
5791 | stringAddC( QChar(tmp) ); | ||
5792 | } else { | ||
5793 | d->error = XMLERR_ERRORPARSINGREFERENCE; | ||
5794 | goto parseError; | ||
5795 | } | ||
5796 | charDataRead = TRUE; | ||
5797 | next(); | ||
5798 | break; | ||
5799 | case DoneN: | ||
5800 | if ( !processReference( charDataRead, context ) ) | ||
5801 | goto parseError; | ||
5802 | next(); | ||
5803 | break; | ||
5804 | } | ||
5805 | // no input is read after this | ||
5806 | switch ( state ) { | ||
5807 | case DoneD: | ||
5808 | return TRUE; | ||
5809 | case DoneH: | ||
5810 | return TRUE; | ||
5811 | case DoneN: | ||
5812 | return TRUE; | ||
5813 | case -1: | ||
5814 | // Error | ||
5815 | d->error = XMLERR_ERRORPARSINGREFERENCE; | ||
5816 | goto parseError; | ||
5817 | } | ||
5818 | |||
5819 | } | ||
5820 | |||
5821 | return TRUE; | ||
5822 | |||
5823 | parseError: | ||
5824 | reportParseError(); | ||
5825 | return FALSE; | ||
5826 | } | ||
5827 | |||
5828 | /*! | ||
5829 | Helper function for parseReference() | ||
5830 | */ | ||
5831 | bool QXmlSimpleReader::processReference( bool &charDataRead, EntityRecognitionContext context ) | ||
5832 | { | ||
5833 | QString reference = ref(); | ||
5834 | if ( reference == "amp" ) { | ||
5835 | if ( context == InEntityValue ) { | ||
5836 | // Bypassed | ||
5837 | stringAddC( '&' ); stringAddC( 'a' ); stringAddC( 'm' ); stringAddC( 'p' ); stringAddC( ';' ); | ||
5838 | } else { | ||
5839 | // Included or Included in literal | ||
5840 | stringAddC( '&' ); | ||
5841 | } | ||
5842 | charDataRead = TRUE; | ||
5843 | } else if ( reference == "lt" ) { | ||
5844 | if ( context == InEntityValue ) { | ||
5845 | // Bypassed | ||
5846 | stringAddC( '&' ); stringAddC( 'l' ); stringAddC( 't' ); stringAddC( ';' ); | ||
5847 | } else { | ||
5848 | // Included or Included in literal | ||
5849 | stringAddC( '<' ); | ||
5850 | } | ||
5851 | charDataRead = TRUE; | ||
5852 | } else if ( reference == "gt" ) { | ||
5853 | if ( context == InEntityValue ) { | ||
5854 | // Bypassed | ||
5855 | stringAddC( '&' ); stringAddC( 'g' ); stringAddC( 't' ); stringAddC( ';' ); | ||
5856 | } else { | ||
5857 | // Included or Included in literal | ||
5858 | stringAddC( '>' ); | ||
5859 | } | ||
5860 | charDataRead = TRUE; | ||
5861 | } else if ( reference == "apos" ) { | ||
5862 | if ( context == InEntityValue ) { | ||
5863 | // Bypassed | ||
5864 | stringAddC( '&' ); stringAddC( 'a' ); stringAddC( 'p' ); stringAddC( 'o' ); stringAddC( 's' ); stringAddC( ';' ); | ||
5865 | } else { | ||
5866 | // Included or Included in literal | ||
5867 | stringAddC( '\'' ); | ||
5868 | } | ||
5869 | charDataRead = TRUE; | ||
5870 | } else if ( reference == "quot" ) { | ||
5871 | if ( context == InEntityValue ) { | ||
5872 | // Bypassed | ||
5873 | stringAddC( '&' ); stringAddC( 'q' ); stringAddC( 'u' ); stringAddC( 'o' ); stringAddC( 't' ); stringAddC( ';' ); | ||
5874 | } else { | ||
5875 | // Included or Included in literal | ||
5876 | stringAddC( '"' ); | ||
5877 | } | ||
5878 | charDataRead = TRUE; | ||
5879 | } else { | ||
5880 | QMap<QString,QString>::Iterator it; | ||
5881 | it = d->entities.find( reference ); | ||
5882 | if ( it != d->entities.end() ) { | ||
5883 | // "Internal General" | ||
5884 | switch ( context ) { | ||
5885 | case InContent: | ||
5886 | // Included | ||
5887 | xmlRef = it.data() + xmlRef; | ||
5888 | charDataRead = FALSE; | ||
5889 | break; | ||
5890 | case InAttributeValue: | ||
5891 | // Included in literal | ||
5892 | xmlRef = it.data().replace( QRegExp("\""), """ ).replace( QRegExp("'"), "'" ) | ||
5893 | + xmlRef; | ||
5894 | charDataRead = FALSE; | ||
5895 | break; | ||
5896 | case InEntityValue: | ||
5897 | { | ||
5898 | // Bypassed | ||
5899 | stringAddC( '&' ); | ||
5900 | for ( int i=0; i<(int)reference.length(); i++ ) { | ||
5901 | stringAddC( reference[i] ); | ||
5902 | } | ||
5903 | stringAddC( ';'); | ||
5904 | charDataRead = TRUE; | ||
5905 | } | ||
5906 | break; | ||
5907 | case InDTD: | ||
5908 | // Forbidden | ||
5909 | d->error = XMLERR_INTERNALGENERALENTITYINDTD; | ||
5910 | charDataRead = FALSE; | ||
5911 | break; | ||
5912 | } | ||
5913 | } else { | ||
5914 | QMap<QString,QXmlSimpleReaderPrivate::ExternEntity>::Iterator itExtern; | ||
5915 | itExtern = d->externEntities.find( reference ); | ||
5916 | if ( itExtern == d->externEntities.end() ) { | ||
5917 | // entity not declared | ||
5918 | // ### check this case for conformance | ||
5919 | if ( context == InEntityValue ) { | ||
5920 | // Bypassed | ||
5921 | stringAddC( '&' ); | ||
5922 | for ( int i=0; i<(int)reference.length(); i++ ) { | ||
5923 | stringAddC( reference[i] ); | ||
5924 | } | ||
5925 | stringAddC( ';'); | ||
5926 | charDataRead = TRUE; | ||
5927 | } else { | ||
5928 | if ( contentHnd ) { | ||
5929 | if ( !contentHnd->skippedEntity( reference ) ) { | ||
5930 | d->error = contentHnd->errorString(); | ||
5931 | return FALSE; // error | ||
5932 | } | ||
5933 | } | ||
5934 | } | ||
5935 | } else if ( (*itExtern).notation.isNull() ) { | ||
5936 | // "External Parsed General" | ||
5937 | switch ( context ) { | ||
5938 | case InContent: | ||
5939 | // Included if validating | ||
5940 | if ( contentHnd ) { | ||
5941 | if ( !contentHnd->skippedEntity( reference ) ) { | ||
5942 | d->error = contentHnd->errorString(); | ||
5943 | return FALSE; // error | ||
5944 | } | ||
5945 | } | ||
5946 | charDataRead = FALSE; | ||
5947 | break; | ||
5948 | case InAttributeValue: | ||
5949 | // Forbidden | ||
5950 | d->error = XMLERR_EXTERNALGENERALENTITYINAV; | ||
5951 | charDataRead = FALSE; | ||
5952 | break; | ||
5953 | case InEntityValue: | ||
5954 | { | ||
5955 | // Bypassed | ||
5956 | stringAddC( '&' ); | ||
5957 | for ( int i=0; i<(int)reference.length(); i++ ) { | ||
5958 | stringAddC( reference[i] ); | ||
5959 | } | ||
5960 | stringAddC( ';'); | ||
5961 | charDataRead = TRUE; | ||
5962 | } | ||
5963 | break; | ||
5964 | case InDTD: | ||
5965 | // Forbidden | ||
5966 | d->error = XMLERR_EXTERNALGENERALENTITYINDTD; | ||
5967 | charDataRead = FALSE; | ||
5968 | break; | ||
5969 | } | ||
5970 | } else { | ||
5971 | // "Unparsed" | ||
5972 | // ### notify for "Occurs as Attribute Value" missing (but this is no refence, anyway) | ||
5973 | // Forbidden | ||
5974 | d->error = XMLERR_UNPARSEDENTITYREFERENCE; | ||
5975 | charDataRead = FALSE; | ||
5976 | return FALSE; // error | ||
5977 | } | ||
5978 | } | ||
5979 | } | ||
5980 | return TRUE; // no error | ||
5981 | } | ||
5982 | |||
5983 | |||
5984 | /*! | ||
5985 | Parse over a simple string. | ||
5986 | |||
5987 | After the string was successfully parsed, the head is on the first | ||
5988 | character after the string. | ||
5989 | */ | ||
5990 | bool QXmlSimpleReader::parseString( const QString& s ) | ||
5991 | { | ||
5992 | signed char Done = s.length(); | ||
5993 | |||
5994 | const signed char InpCharExpected = 0; // the character that was expected | ||
5995 | const signed char InpUnknown = 1; | ||
5996 | |||
5997 | signed char state = 0; // state in this function is the position in the string s | ||
5998 | signed char input; | ||
5999 | |||
6000 | for (;;) { | ||
6001 | |||
6002 | // get input | ||
6003 | if ( atEnd() ) { | ||
6004 | d->error = XMLERR_UNEXPECTEDEOF; | ||
6005 | goto parseError; | ||
6006 | } | ||
6007 | if ( c == s[(int)state] ) { | ||
6008 | input = InpCharExpected; | ||
6009 | } else { | ||
6010 | input = InpUnknown; | ||
6011 | } | ||
6012 | |||
6013 | // set state according to input | ||
6014 | if ( input == InpCharExpected ) { | ||
6015 | state++; | ||
6016 | } else { | ||
6017 | // Error | ||
6018 | d->error = XMLERR_UNEXPECTEDCHARACTER; | ||
6019 | goto parseError; | ||
6020 | } | ||
6021 | |||
6022 | // do some actions according to state | ||
6023 | next(); | ||
6024 | // no input is read after this | ||
6025 | if ( state == Done ) { | ||
6026 | return TRUE; | ||
6027 | } | ||
6028 | |||
6029 | } | ||
6030 | |||
6031 | return TRUE; | ||
6032 | |||
6033 | parseError: | ||
6034 | reportParseError(); | ||
6035 | return FALSE; | ||
6036 | } | ||
6037 | |||
6038 | |||
6039 | /*! | ||
6040 | Inits the data values. | ||
6041 | */ | ||
6042 | void QXmlSimpleReader::init( const QXmlInputSource& i ) | ||
6043 | { | ||
6044 | xml = i.data(); | ||
6045 | xmlLength = xml.length(); | ||
6046 | xmlRef = ""; | ||
6047 | |||
6048 | d->externParameterEntities.clear(); | ||
6049 | d->parameterEntities.clear(); | ||
6050 | d->externEntities.clear(); | ||
6051 | d->entities.clear(); | ||
6052 | |||
6053 | tags.clear(); | ||
6054 | |||
6055 | d->doctype = ""; | ||
6056 | d->xmlVersion = ""; | ||
6057 | d->encoding = ""; | ||
6058 | d->standalone = QXmlSimpleReaderPrivate::Unknown; | ||
6059 | |||
6060 | lineNr = 0; | ||
6061 | columnNr = -1; | ||
6062 | pos = 0; | ||
6063 | next(); | ||
6064 | d->error = XMLERR_OK; | ||
6065 | } | ||
6066 | |||
6067 | /*! | ||
6068 | Returns TRUE if a entity with the name \a e exists, | ||
6069 | otherwise returns FALSE. | ||
6070 | */ | ||
6071 | bool QXmlSimpleReader::entityExist( const QString& e ) const | ||
6072 | { | ||
6073 | if ( d->parameterEntities.find(e) == d->parameterEntities.end() && | ||
6074 | d->externParameterEntities.find(e) == d->externParameterEntities.end() ) { | ||
6075 | return FALSE; | ||
6076 | } else { | ||
6077 | return TRUE; | ||
6078 | } | ||
6079 | } | ||
6080 | |||
6081 | void QXmlSimpleReader::reportParseError() | ||
6082 | { | ||
6083 | if ( errorHnd ) | ||
6084 | errorHnd->fatalError( QXmlParseException( d->error, columnNr+1, lineNr+1 ) ); | ||
6085 | } | ||
6086 | |||
6087 | //US #endif //QT_NO_XML | ||