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