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