source: vendor/trolltech/current/src/xml/qxml.cpp

Last change on this file was 2, checked in by dmik, 20 years ago

Imported xplatform parts of the official release 3.3.1 from Trolltech

  • Property svn:keywords set to Id
File size: 220.8 KB
Line 
1/****************************************************************************
2** $Id: qxml.cpp 2 2005-11-16 15:49:26Z dmik $
3**
4** Implementation of QXmlSimpleReader and related classes.
5**
6** Created : 000518
7**
8** Copyright (C) 1992-2004 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#include "qxml.h"
39#include "qtextcodec.h"
40#include "qbuffer.h"
41#include "qregexp.h"
42#include "qptrstack.h"
43#include "qmap.h"
44#include "qvaluestack.h"
45
46// needed for QT_TRANSLATE_NOOP:
47#include "qobject.h"
48
49#ifndef QT_NO_XML
50
51//#define QT_QXML_DEBUG
52
53// Error strings for the XML reader
54#define XMLERR_OK QT_TRANSLATE_NOOP( "QXml", "no error occurred" )
55#define XMLERR_ERRORBYCONSUMER QT_TRANSLATE_NOOP( "QXml", "error triggered by consumer" )
56#define XMLERR_UNEXPECTEDEOF QT_TRANSLATE_NOOP( "QXml", "unexpected end of file" )
57#define XMLERR_MORETHANONEDOCTYPE QT_TRANSLATE_NOOP( "QXml", "more than one document type definition" )
58#define XMLERR_ERRORPARSINGELEMENT QT_TRANSLATE_NOOP( "QXml", "error occurred while parsing element" )
59#define XMLERR_TAGMISMATCH QT_TRANSLATE_NOOP( "QXml", "tag mismatch" )
60#define XMLERR_ERRORPARSINGCONTENT QT_TRANSLATE_NOOP( "QXml", "error occurred while parsing content" )
61#define XMLERR_UNEXPECTEDCHARACTER QT_TRANSLATE_NOOP( "QXml", "unexpected character" )
62#define XMLERR_INVALIDNAMEFORPI QT_TRANSLATE_NOOP( "QXml", "invalid name for processing instruction" )
63#define XMLERR_VERSIONEXPECTED QT_TRANSLATE_NOOP( "QXml", "version expected while reading the XML declaration" )
64#define XMLERR_WRONGVALUEFORSDECL QT_TRANSLATE_NOOP( "QXml", "wrong value for standalone declaration" )
65#define XMLERR_EDECLORSDDECLEXPECTED QT_TRANSLATE_NOOP( "QXml", "encoding declaration or standalone declaration expected while reading the XML declaration" )
66#define XMLERR_SDDECLEXPECTED QT_TRANSLATE_NOOP( "QXml", "standalone declaration expected while reading the XML declaration" )
67#define XMLERR_ERRORPARSINGDOCTYPE QT_TRANSLATE_NOOP( "QXml", "error occurred while parsing document type definition" )
68#define XMLERR_LETTEREXPECTED QT_TRANSLATE_NOOP( "QXml", "letter is expected" )
69#define XMLERR_ERRORPARSINGCOMMENT QT_TRANSLATE_NOOP( "QXml", "error occurred while parsing comment" )
70#define XMLERR_ERRORPARSINGREFERENCE QT_TRANSLATE_NOOP( "QXml", "error occurred while parsing reference" )
71#define XMLERR_INTERNALGENERALENTITYINDTD QT_TRANSLATE_NOOP( "QXml", "internal general entity reference not allowed in DTD" )
72#define XMLERR_EXTERNALGENERALENTITYINAV QT_TRANSLATE_NOOP( "QXml", "external parsed general entity reference not allowed in attribute value" )
73#define XMLERR_EXTERNALGENERALENTITYINDTD QT_TRANSLATE_NOOP( "QXml", "external parsed general entity reference not allowed in DTD" )
74#define XMLERR_UNPARSEDENTITYREFERENCE QT_TRANSLATE_NOOP( "QXml", "unparsed entity reference in wrong context" )
75#define XMLERR_RECURSIVEENTITIES QT_TRANSLATE_NOOP( "QXml", "recursive entities" )
76#define XMLERR_ERRORINTEXTDECL QT_TRANSLATE_NOOP( "QXml", "error in the text declaration of an external entity" )
77
78// the constants for the lookup table
79static const signed char cltWS = 0; // white space
80static const signed char cltPer = 1; // %
81static const signed char cltAmp = 2; // &
82static const signed char cltGt = 3; // >
83static const signed char cltLt = 4; // <
84static const signed char cltSlash = 5; // /
85static const signed char cltQm = 6; // ?
86static const signed char cltEm = 7; // !
87static const signed char cltDash = 8; // -
88static const signed char cltCB = 9; // ]
89static const signed char cltOB = 10; // [
90static const signed char cltEq = 11; // =
91static const signed char cltDq = 12; // "
92static const signed char cltSq = 13; // '
93static const signed char cltUnknown = 14;
94
95// character lookup table
96static const signed char charLookupTable[256]={
97 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x00 - 0x07
98 cltUnknown, // 0x08
99 cltWS, // 0x09 \t
100 cltWS, // 0x0A \n
101 cltUnknown, // 0x0B
102 cltUnknown, // 0x0C
103 cltWS, // 0x0D \r
104 cltUnknown, // 0x0E
105 cltUnknown, // 0x0F
106 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x17 - 0x16
107 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x18 - 0x1F
108 cltWS, // 0x20 Space
109 cltEm, // 0x21 !
110 cltDq, // 0x22 "
111 cltUnknown, // 0x23
112 cltUnknown, // 0x24
113 cltPer, // 0x25 %
114 cltAmp, // 0x26 &
115 cltSq, // 0x27 '
116 cltUnknown, // 0x28
117 cltUnknown, // 0x29
118 cltUnknown, // 0x2A
119 cltUnknown, // 0x2B
120 cltUnknown, // 0x2C
121 cltDash, // 0x2D -
122 cltUnknown, // 0x2E
123 cltSlash, // 0x2F /
124 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x30 - 0x37
125 cltUnknown, // 0x38
126 cltUnknown, // 0x39
127 cltUnknown, // 0x3A
128 cltUnknown, // 0x3B
129 cltLt, // 0x3C <
130 cltEq, // 0x3D =
131 cltGt, // 0x3E >
132 cltQm, // 0x3F ?
133 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x40 - 0x47
134 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x48 - 0x4F
135 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x50 - 0x57
136 cltUnknown, // 0x58
137 cltUnknown, // 0x59
138 cltUnknown, // 0x5A
139 cltOB, // 0x5B [
140 cltUnknown, // 0x5C
141 cltCB, // 0x5D ]
142 cltUnknown, // 0x5E
143 cltUnknown, // 0x5F
144 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x60 - 0x67
145 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x68 - 0x6F
146 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x70 - 0x77
147 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x78 - 0x7F
148 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x80 - 0x87
149 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x88 - 0x8F
150 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x90 - 0x97
151 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x98 - 0x9F
152 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xA0 - 0xA7
153 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xA8 - 0xAF
154 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xB0 - 0xB7
155 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xB8 - 0xBF
156 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xC0 - 0xC7
157 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xC8 - 0xCF
158 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xD0 - 0xD7
159 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xD8 - 0xDF
160 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xE0 - 0xE7
161 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xE8 - 0xEF
162 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xF0 - 0xF7
163 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown // 0xF8 - 0xFF
164};
165
166
167//
168// local helper functions
169//
170
171/*
172 This function strips the TextDecl [77] ("<?xml ...?>") from the string \a
173 str. The stripped version is stored in \a str. If this function finds an
174 invalid TextDecl, it returns FALSE, otherwise TRUE.
175
176 This function is used for external entities since those can include an
177 TextDecl that must be stripped before inserting the entity.
178*/
179static bool stripTextDecl( QString& str )
180{
181 QString textDeclStart( "<?xml" );
182 if ( str.startsWith( textDeclStart ) ) {
183 QRegExp textDecl(QString::fromLatin1(
184 "^<\\?xml\\s+"
185 "(version\\s*=\\s*((['\"])[-a-zA-Z0-9_.:]+\\3))?"
186 "\\s*"
187 "(encoding\\s*=\\s*((['\"])[A-Za-z][-a-zA-Z0-9_.]*\\6))?"
188 "\\s*\\?>"
189 ));
190 QString strTmp = str.replace( textDecl, "" );
191 if ( strTmp.length() != str.length() )
192 return FALSE; // external entity has wrong TextDecl
193 str = strTmp;
194 }
195 return TRUE;
196}
197
198
199class QXmlAttributesPrivate
200{
201};
202class QXmlInputSourcePrivate
203{
204};
205class QXmlParseExceptionPrivate
206{
207};
208class QXmlLocatorPrivate
209{
210};
211class QXmlDefaultHandlerPrivate
212{
213};
214
215/*!
216 \class QXmlParseException qxml.h
217 \reentrant
218 \brief The QXmlParseException class is used to report errors with
219 the QXmlErrorHandler interface.
220\if defined(commercial)
221 It is part of the <a href="commercialeditions.html">Qt Enterprise Edition</a>.
222\endif
223
224 \module XML
225 \ingroup xml-tools
226
227 The XML subsystem constructs an instance of this class when it
228 detects an error. You can retrieve the place where the error
229 occurred using systemId(), publicId(), lineNumber() and
230 columnNumber(), along with the error message().
231
232 \sa QXmlErrorHandler QXmlReader
233*/
234
235/*!
236 \fn QXmlParseException::QXmlParseException( const QString& name, int c, int l, const QString& p, const QString& s )
237
238 Constructs a parse exception with the error string \a name for
239 column \a c and line \a l for the public identifier \a p and the
240 system identifier \a s.
241*/
242
243/*!
244 Returns the error message.
245*/
246QString QXmlParseException::message() const
247{
248 return msg;
249}
250/*!
251 Returns the column number where the error occurred.
252*/
253int QXmlParseException::columnNumber() const
254{
255 return column;
256}
257/*!
258 Returns the line number where the error occurred.
259*/
260int QXmlParseException::lineNumber() const
261{
262 return line;
263}
264/*!
265 Returns the public identifier where the error occurred.
266*/
267QString QXmlParseException::publicId() const
268{
269 return pub;
270}
271/*!
272 Returns the system identifier where the error occurred.
273*/
274QString QXmlParseException::systemId() const
275{
276 return sys;
277}
278
279
280/*!
281 \class QXmlLocator qxml.h
282 \reentrant
283 \brief The QXmlLocator class provides the XML handler classes with
284 information about the parsing position within a file.
285\if defined(commercial)
286 It is part of the <a href="commercialeditions.html">Qt Enterprise Edition</a>.
287\endif
288
289 \module XML
290 \ingroup xml-tools
291
292 The reader reports a QXmlLocator to the content handler before it
293 starts to parse the document. This is done with the
294 QXmlContentHandler::setDocumentLocator() function. The handler
295 classes can now use this locator to get the position (lineNumber()
296 and columnNumber()) that the reader has reached.
297*/
298
299/*!
300 Constructor.
301*/
302QXmlLocator::QXmlLocator()
303{
304}
305
306/*!
307 Destructor.
308*/
309QXmlLocator::~QXmlLocator()
310{
311}
312
313/*!
314 \fn int QXmlLocator::columnNumber()
315
316 Returns the column number (starting at 1) or -1 if there is no
317 column number available.
318*/
319
320/*!
321 \fn int QXmlLocator::lineNumber()
322
323 Returns the line number (starting at 1) or -1 if there is no line
324 number available.
325*/
326
327class QXmlSimpleReaderLocator : public QXmlLocator
328{
329public:
330 QXmlSimpleReaderLocator( QXmlSimpleReader* parent )
331 {
332 reader = parent;
333 }
334 ~QXmlSimpleReaderLocator()
335 {
336 }
337
338 int columnNumber()
339 {
340 return ( reader->columnNr == -1 ? -1 : reader->columnNr + 1 );
341 }
342 int lineNumber()
343 {
344 return ( reader->lineNr == -1 ? -1 : reader->lineNr + 1 );
345 }
346// QString getPublicId()
347// QString getSystemId()
348
349private:
350 QXmlSimpleReader *reader;
351};
352
353/*********************************************
354 *
355 * QXmlNamespaceSupport
356 *
357 *********************************************/
358
359class QXmlNamespaceSupportPrivate
360{
361public:
362 QXmlNamespaceSupportPrivate()
363 {
364 ns = new QMap<QString, QString>;
365 ns->insert( "xml", "http://www.w3.org/XML/1998/namespace" ); // the XML namespace
366 }
367
368 ~QXmlNamespaceSupportPrivate()
369 {
370 nsStack.setAutoDelete( TRUE );
371 nsStack.clear();
372 delete ns;
373 }
374
375 QPtrStack<QMap<QString, QString> > nsStack;
376 QMap<QString, QString> *ns;
377};
378
379/*!
380 \class QXmlNamespaceSupport qxml.h
381 \reentrant
382 \brief The QXmlNamespaceSupport class is a helper class for XML
383 readers which want to include namespace support.
384\if defined(commercial)
385 It is part of the <a href="commercialeditions.html">Qt Enterprise Edition</a>.
386\endif
387
388 \module XML
389 \ingroup xml-tools
390
391 You can set the prefix for the current namespace with setPrefix(),
392 and get the list of current prefixes (or those for a given URI)
393 with prefixes(). The namespace URI is available from uri(). Use
394 pushContext() to start a new namespace context, and popContext()
395 to return to the previous namespace context. Use splitName() or
396 processName() to split a name into its prefix and local name.
397
398 See also the \link xml.html#sax2Namespaces namespace description\endlink.
399*/
400
401/*!
402 Constructs a QXmlNamespaceSupport.
403*/
404QXmlNamespaceSupport::QXmlNamespaceSupport()
405{
406 d = new QXmlNamespaceSupportPrivate;
407}
408
409/*!
410 Destroys a QXmlNamespaceSupport.
411*/
412QXmlNamespaceSupport::~QXmlNamespaceSupport()
413{
414 delete d;
415}
416
417/*!
418 This function declares a prefix \a pre in the current namespace
419 context to be the namespace URI \a uri. The prefix remains in
420 force until this context is popped, unless it is shadowed in a
421 descendant context.
422
423 Note that there is an asymmetry in this library. prefix() does not
424 return the default "" prefix, even if you have declared one; to
425 check for a default prefix, you must look it up explicitly using
426 uri(). This asymmetry exists to make it easier to look up prefixes
427 for attribute names, where the default prefix is not allowed.
428*/
429void QXmlNamespaceSupport::setPrefix( const QString& pre, const QString& uri )
430{
431 if( pre.isNull() ) {
432 d->ns->insert( "", uri );
433 } else {
434 d->ns->insert( pre, uri );
435 }
436}
437
438/*!
439 Returns one of the prefixes mapped to the namespace URI \a uri.
440
441 If more than one prefix is currently mapped to the same URI, this
442 function makes an arbitrary selection; if you want all of the
443 prefixes, use prefixes() instead.
444
445 Note: to check for a default prefix, use the uri() function with
446 an argument of "".
447*/
448QString QXmlNamespaceSupport::prefix( const QString& uri ) const
449{
450 QMap<QString, QString>::ConstIterator itc, it = d->ns->begin();
451 while ( (itc=it) != d->ns->end() ) {
452 ++it;
453 if ( itc.data() == uri && !itc.key().isEmpty() )
454 return itc.key();
455 }
456 return "";
457}
458
459/*!
460 Looks up the prefix \a prefix in the current context and returns
461 the currently-mapped namespace URI. Use the empty string ("") for
462 the default namespace.
463*/
464QString QXmlNamespaceSupport::uri( const QString& prefix ) const
465{
466 const QString& returi = (*d->ns)[ prefix ];
467 return returi;
468}
469
470/*!
471 Splits the name \a qname at the ':' and returns the prefix in \a
472 prefix and the local name in \a localname.
473
474 \sa processName()
475*/
476void QXmlNamespaceSupport::splitName( const QString& qname,
477 QString& prefix, QString& localname ) const
478{
479 uint pos;
480 // search the ':'
481 for( pos=0; pos<qname.length(); pos++ ) {
482 if ( qname.at(pos) == ':' )
483 break;
484 }
485 // and split
486 prefix = qname.left( pos );
487 localname = qname.mid( pos+1 );
488}
489
490/*!
491 Processes a raw XML 1.0 name in the current context by removing
492 the prefix and looking it up among the prefixes currently
493 declared.
494
495 \a qname is the raw XML 1.0 name to be processed. \a isAttribute
496 is TRUE if the name is an attribute name.
497
498 This function stores the namespace URI in \a nsuri (which will be
499 set to QString::null if the raw name has an undeclared prefix),
500 and stores the local name (without prefix) in \a localname (which
501 will be set to QString::null if no namespace is in use).
502
503 Note that attribute names are processed differently than element
504 names: an unprefixed element name gets the default namespace (if
505 any), while an unprefixed element name does not.
506*/
507void QXmlNamespaceSupport::processName( const QString& qname,
508 bool isAttribute,
509 QString& nsuri, QString& localname ) const
510{
511 uint pos = qname.find( ':' );
512 if ( pos < qname.length() ) {
513 // there was a ':'
514 nsuri = uri( qname.left( pos ) );
515 localname = qname.mid( pos+1 );
516 } else {
517 // there was no ':'
518 if ( isAttribute ) {
519 nsuri = QString::null; // attributes don't take default namespace
520 } else {
521 nsuri = uri( "" ); // get default namespace
522 }
523 localname = qname;
524 }
525}
526
527/*!
528 Returns a list of all the prefixes currently declared.
529
530 If there is a default prefix, this function does not return it in
531 the list; check for the default prefix using uri() with an
532 argument of "".
533
534 Note that if you want to iterate over the list, you should iterate
535 over a copy, e.g.
536 \code
537 QStringList list = myXmlNamespaceSupport.prefixes();
538 QStringList::Iterator it = list.begin();
539 while( it != list.end() ) {
540 myProcessing( *it );
541 ++it;
542 }
543 \endcode
544*/
545QStringList QXmlNamespaceSupport::prefixes() const
546{
547 QStringList list;
548
549 QMap<QString, QString>::ConstIterator itc, it = d->ns->begin();
550 while ( (itc=it) != d->ns->end() ) {
551 ++it;
552 if ( !itc.key().isEmpty() )
553 list.append( itc.key() );
554 }
555 return list;
556}
557
558/*!
559 \overload
560
561 Returns a list of all prefixes currently declared for the
562 namespace URI \a uri.
563
564 The "xml:" prefix is included. If you only want one prefix that is
565 mapped to the namespace URI, and you don't care which one you get,
566 use the prefix() function instead.
567
568 Note: the empty (default) prefix is never included in this list;
569 to check for the presence of a default namespace, use uri() with
570 an argument of "".
571
572 Note that if you want to iterate over the list, you should iterate
573 over a copy, e.g.
574 \code
575 QStringList list = myXmlNamespaceSupport.prefixes( "" );
576 QStringList::Iterator it = list.begin();
577 while( it != list.end() ) {
578 myProcessing( *it );
579 ++it;
580 }
581 \endcode
582*/
583QStringList QXmlNamespaceSupport::prefixes( const QString& uri ) const
584{
585 QStringList list;
586
587 QMap<QString, QString>::ConstIterator itc, it = d->ns->begin();
588 while ( (itc=it) != d->ns->end() ) {
589 ++it;
590 if ( itc.data() == uri && !itc.key().isEmpty() )
591 list.append( itc.key() );
592 }
593 return list;
594}
595
596/*!
597 Starts a new namespace context.
598
599 Normally, you should push a new context at the beginning of each
600 XML element: the new context automatically inherits the
601 declarations of its parent context, and it also keeps track of
602 which declarations were made within this context.
603
604 \sa popContext()
605*/
606void QXmlNamespaceSupport::pushContext()
607{
608 d->nsStack.push( new QMap<QString, QString>(*d->ns) );
609}
610
611/*!
612 Reverts to the previous namespace context.
613
614 Normally, you should pop the context at the end of each XML
615 element. After popping the context, all namespace prefix mappings
616 that were previously in force are restored.
617
618 \sa pushContext()
619*/
620void QXmlNamespaceSupport::popContext()
621{
622 delete d->ns;
623 if( !d->nsStack.isEmpty() )
624 d->ns = d->nsStack.pop();
625}
626
627/*!
628 Resets this namespace support object ready for reuse.
629*/
630void QXmlNamespaceSupport::reset()
631{
632 delete d;
633 d = new QXmlNamespaceSupportPrivate;
634}
635
636
637
638/*********************************************
639 *
640 * QXmlAttributes
641 *
642 *********************************************/
643
644/*!
645 \class QXmlAttributes qxml.h
646 \reentrant
647 \brief The QXmlAttributes class provides XML attributes.
648\if defined(commercial)
649 It is part of the <a href="commercialeditions.html">Qt Enterprise Edition</a>.
650\endif
651
652 \module XML
653 \ingroup xml-tools
654
655 If attributes are reported by QXmlContentHandler::startElement()
656 this class is used to pass the attribute values.
657
658 Use index() to locate the position of an attribute in the list,
659 count() to retrieve the number of attributes, and clear() to
660 remove the attributes. New attributes can be added with append().
661 Use type() to get an attribute's type and value() to get its
662 value. The attribute's name is available from localName() or
663 qName(), and its namespace URI from uri().
664
665*/
666
667/*!
668 \fn QXmlAttributes::QXmlAttributes()
669
670 Constructs an empty attribute list.
671*/
672
673/*!
674 \fn QXmlAttributes::~QXmlAttributes()
675
676 Destroys the attributes object.
677*/
678
679/*!
680 Looks up the index of an attribute by the qualified name \a qName.
681
682 Returns the index of the attribute or -1 if it wasn't found.
683
684 See also the \link xml.html#sax2Namespaces namespace description\endlink.
685*/
686int QXmlAttributes::index( const QString& qName ) const
687{
688 return qnameList.findIndex( qName );
689}
690
691/*!
692 \overload
693
694 Looks up the index of an attribute by a namespace name.
695
696 \a uri specifies the namespace URI, or an empty string if the name
697 has no namespace URI. \a localPart specifies the attribute's local
698 name.
699
700 Returns the index of the attribute, or -1 if it wasn't found.
701
702 See also the \link xml.html#sax2Namespaces namespace description\endlink.
703*/
704int QXmlAttributes::index( const QString& uri, const QString& localPart ) const
705{
706 QString uriTmp;
707 if ( uri.isEmpty() )
708 uriTmp = QString::null;
709 else
710 uriTmp = uri;
711 uint count = (uint)uriList.count(); // ### size_t/int cast
712 for ( uint i=0; i<count; i++ ) {
713 if ( uriList[i] == uriTmp && localnameList[i] == localPart )
714 return i;
715 }
716 return -1;
717}
718
719/*!
720 Returns the number of attributes in the list.
721
722 \sa count()
723*/
724int QXmlAttributes::length() const
725{
726 return (int)valueList.count();
727}
728
729/*!
730 \fn int QXmlAttributes::count() const
731
732 Returns the number of attributes in the list. This function is
733 equivalent to length().
734*/
735
736/*!
737 Looks up an attribute's local name for the attribute at position
738 \a index. If no namespace processing is done, the local name is
739 QString::null.
740
741 See also the \link xml.html#sax2Namespaces namespace description\endlink.
742*/
743QString QXmlAttributes::localName( int index ) const
744{
745 return localnameList[index];
746}
747
748/*!
749 Looks up an attribute's XML 1.0 qualified name for the attribute
750 at position \a index.
751
752 See also the \link xml.html#sax2Namespaces namespace description\endlink.
753*/
754QString QXmlAttributes::qName( int index ) const
755{
756 return qnameList[index];
757}
758
759/*!
760 Looks up an attribute's namespace URI for the attribute at
761 position \a index. If no namespace processing is done or if the
762 attribute has no namespace, the namespace URI is QString::null.
763
764 See also the \link xml.html#sax2Namespaces namespace description\endlink.
765*/
766QString QXmlAttributes::uri( int index ) const
767{
768 return uriList[index];
769}
770
771/*!
772 Looks up an attribute's type for the attribute at position \a
773 index.
774
775 Currently only "CDATA" is returned.
776*/
777QString QXmlAttributes::type( int ) const
778{
779 return "CDATA";
780}
781
782/*!
783 \overload
784
785 Looks up an attribute's type for the qualified name \a qName.
786
787 Currently only "CDATA" is returned.
788*/
789QString QXmlAttributes::type( const QString& ) const
790{
791 return "CDATA";
792}
793
794/*!
795 \overload
796
797 Looks up an attribute's type by namespace name.
798
799 \a uri specifies the namespace URI and \a localName specifies the
800 local name. If the name has no namespace URI, use an empty string
801 for \a uri.
802
803 Currently only "CDATA" is returned.
804*/
805QString QXmlAttributes::type( const QString&, const QString& ) const
806{
807 return "CDATA";
808}
809
810/*!
811 Looks up an attribute's value for the attribute at position \a
812 index.
813*/
814QString QXmlAttributes::value( int index ) const
815{
816 return valueList[index];
817}
818
819/*!
820 \overload
821
822 Looks up an attribute's value for the qualified name \a qName.
823
824 See also the \link xml.html#sax2Namespaces namespace description\endlink.
825*/
826QString QXmlAttributes::value( const QString& qName ) const
827{
828 int i = index( qName );
829 if ( i == -1 )
830 return QString::null;
831 return valueList[ i ];
832}
833
834/*!
835 \overload
836
837 Looks up an attribute's value by namespace name.
838
839 \a uri specifies the namespace URI, or an empty string if the name
840 has no namespace URI. \a localName specifies the attribute's local
841 name.
842
843 See also the \link xml.html#sax2Namespaces namespace description\endlink.
844*/
845QString QXmlAttributes::value( const QString& uri, const QString& localName ) const
846{
847 int i = index( uri, localName );
848 if ( i == -1 )
849 return QString::null;
850 return valueList[ i ];
851}
852
853/*!
854 Clears the list of attributes.
855
856 \sa append()
857*/
858void QXmlAttributes::clear()
859{
860 qnameList.clear();
861 uriList.clear();
862 localnameList.clear();
863 valueList.clear();
864}
865
866/*!
867 Appends a new attribute entry to the list of attributes. The
868 qualified name of the attribute is \a qName, the namespace URI is
869 \a uri and the local name is \a localPart. The value of the
870 attribute is \a value.
871
872 \sa qName() uri() localName() value()
873*/
874void QXmlAttributes::append( const QString &qName, const QString &uri, const QString &localPart, const QString &value )
875{
876 qnameList.append( qName );
877 uriList.append( uri );
878 localnameList.append( localPart);
879 valueList.append( value );
880}
881
882
883/*********************************************
884 *
885 * QXmlInputSource
886 *
887 *********************************************/
888
889/*!
890 \class QXmlInputSource qxml.h
891 \reentrant
892 \brief The QXmlInputSource class provides the input data for the
893 QXmlReader subclasses.
894\if defined(commercial)
895 It is part of the <a href="commercialeditions.html">Qt Enterprise Edition</a>.
896\endif
897
898 \module XML
899 \ingroup xml-tools
900
901 All subclasses of QXmlReader read the input XML document from this
902 class.
903
904 This class recognizes the encoding of the data by reading the
905 encoding declaration in the XML file if it finds one, and reading
906 the data using the corresponding encoding. If it does not find an
907 encoding declaration, then it assumes that the data is either in
908 UTF-8 or UTF-16, depending on whether it can find a byte-order
909 mark.
910
911 There are two ways to populate the input source with data: you can
912 construct it with a QIODevice* so that the input source reads the
913 data from that device. Or you can set the data explicitly with one
914 of the setData() functions.
915
916 Usually you either construct a QXmlInputSource that works on a
917 QIODevice* or you construct an empty QXmlInputSource and set the
918 data with setData(). There are only rare occasions where you would
919 want to mix both methods.
920
921 The QXmlReader subclasses use the next() function to read the
922 input character by character. If you want to start from the
923 beginning again, use reset().
924
925 The functions data() and fetchData() are useful if you want to do
926 something with the data other than parsing, e.g. displaying the
927 raw XML file. The benefit of using the QXmlInputClass in such
928 cases is that it tries to use the correct encoding.
929
930 \sa QXmlReader QXmlSimpleReader
931*/
932
933// the following two are guaranteed not to be a character
934const QChar QXmlInputSource::EndOfData = QChar((ushort)0xfffe);
935const QChar QXmlInputSource::EndOfDocument = QChar((ushort)0xffff);
936
937/*
938 Common part of the constructors.
939*/
940void QXmlInputSource::init()
941{
942 inputDevice = 0;
943 inputStream = 0;
944
945 setData( QString::null );
946 encMapper = 0;
947}
948
949/*!
950 Constructs an input source which contains no data.
951
952 \sa setData()
953*/
954QXmlInputSource::QXmlInputSource()
955{
956 init();
957}
958
959/*!
960 Constructs an input source and gets the data from device \a dev.
961 If \a dev is not open, it is opened in read-only mode. If \a dev
962 is 0 or it is not possible to read from the device, the input
963 source will contain no data.
964
965 \sa setData() fetchData() QIODevice
966*/
967QXmlInputSource::QXmlInputSource( QIODevice *dev )
968{
969 init();
970 inputDevice = dev;
971 fetchData();
972}
973
974/*! \obsolete
975 Constructs an input source and gets the data from the text stream \a stream.
976*/
977QXmlInputSource::QXmlInputSource( QTextStream& stream )
978{
979 init();
980 inputStream = &stream;
981 fetchData();
982}
983
984/*! \obsolete
985 Constructs an input source and gets the data from the file \a file. If the
986 file cannot be read the input source is empty.
987*/
988QXmlInputSource::QXmlInputSource( QFile& file )
989{
990 init();
991 inputDevice = &file;
992 fetchData();
993}
994
995/*!
996 Destructor.
997*/
998QXmlInputSource::~QXmlInputSource()
999{
1000 delete encMapper;
1001}
1002
1003/*!
1004 Returns the next character of the input source. If this function
1005 reaches the end of available data, it returns
1006 QXmlInputSource::EndOfData. If you call next() after that, it
1007 tries to fetch more data by calling fetchData(). If the
1008 fetchData() call results in new data, this function returns the
1009 first character of that data; otherwise it returns
1010 QXmlInputSource::EndOfDocument.
1011
1012 \sa reset() fetchData() QXmlSimpleReader::parse() QXmlSimpleReader::parseContinue()
1013*/
1014QChar QXmlInputSource::next()
1015{
1016 if ( pos >= length ) {
1017 if ( nextReturnedEndOfData ) {
1018 nextReturnedEndOfData = FALSE;
1019 fetchData();
1020 if ( pos >= length ) {
1021 return EndOfDocument;
1022 }
1023 return next();
1024 }
1025 nextReturnedEndOfData = TRUE;
1026 return EndOfData;
1027 }
1028 return unicode[pos++];
1029}
1030
1031/*!
1032 This function sets the position used by next() to the beginning of
1033 the data returned by data(). This is useful if you want to use the
1034 input source for more than one parse.
1035
1036 \sa next()
1037*/
1038void QXmlInputSource::reset()
1039{
1040 nextReturnedEndOfData = FALSE;
1041 pos = 0;
1042}
1043
1044/*!
1045 Returns the data the input source contains or QString::null if the
1046 input source does not contain any data.
1047
1048 \sa setData() QXmlInputSource() fetchData()
1049*/
1050QString QXmlInputSource::data()
1051{
1052 return str;
1053}
1054
1055/*!
1056 Sets the data of the input source to \a dat.
1057
1058 If the input source already contains data, this function deletes
1059 that data first.
1060
1061 \sa data()
1062*/
1063void QXmlInputSource::setData( const QString& dat )
1064{
1065 str = dat;
1066 unicode = dat.unicode();
1067 pos = 0;
1068 length = str.length();
1069 nextReturnedEndOfData = FALSE;
1070}
1071
1072/*!
1073 \overload
1074
1075 The data \a dat is passed through the correct text-codec, before
1076 it is set.
1077*/
1078void QXmlInputSource::setData( const QByteArray& dat )
1079{
1080 setData( fromRawData( dat ) );
1081}
1082
1083/*!
1084 This function reads more data from the device that was set during
1085 construction. If the input source already contained data, this
1086 function deletes that data first.
1087
1088 This object contains no data after a call to this function if the
1089 object was constructed without a device to read data from or if
1090 this function was not able to get more data from the device.
1091
1092 There are two occasions where a fetch is done implicitly by
1093 another function call: during construction (so that the object
1094 starts out with some initial data where available), and during a
1095 call to next() (if the data had run out).
1096
1097 You don't normally need to use this function if you use next().
1098
1099 \sa data() next() QXmlInputSource()
1100*/
1101void QXmlInputSource::fetchData()
1102{
1103 QByteArray rawData;
1104
1105 if ( inputDevice != 0 ) {
1106 if ( inputDevice->isOpen() || inputDevice->open( IO_ReadOnly ) )
1107 rawData = inputDevice->readAll();
1108 } else if ( inputStream != 0 ) {
1109 if ( inputStream->device()->isDirectAccess() ) {
1110 rawData = inputStream->device()->readAll();
1111 } else {
1112 int nread = 0;
1113 const int bufsize = 512;
1114 while ( !inputStream->device()->atEnd() ) {
1115 rawData.resize( nread + bufsize );
1116 nread += inputStream->device()->readBlock( rawData.data()+nread, bufsize );
1117 }
1118 rawData.resize( nread );
1119 }
1120 }
1121 setData( fromRawData( rawData ) );
1122}
1123
1124/*!
1125 This function reads the XML file from \a data and tries to
1126 recognize the encoding. It converts the raw data \a data into a
1127 QString and returns it. It tries its best to get the correct
1128 encoding for the XML file.
1129
1130 If \a beginning is TRUE, this function assumes that the data
1131 starts at the beginning of a new XML document and looks for an
1132 encoding declaration. If \a beginning is FALSE, it converts the
1133 raw data using the encoding determined from prior calls.
1134*/
1135QString QXmlInputSource::fromRawData( const QByteArray &data, bool beginning )
1136{
1137 if ( data.size() == 0 )
1138 return QString::null;
1139 if ( beginning ) {
1140 delete encMapper;
1141 encMapper = 0;
1142 }
1143 if ( encMapper == 0 ) {
1144 QTextCodec *codec = 0;
1145 // look for byte order mark and read the first 5 characters
1146 if ( data.size() >= 2 &&
1147 ( ((uchar)data.at(0)==(uchar)0xfe &&
1148 (uchar)data.at(1)==(uchar)0xff ) ||
1149 ((uchar)data.at(0)==(uchar)0xff &&
1150 (uchar)data.at(1)==(uchar)0xfe ) )) {
1151 codec = QTextCodec::codecForMib( 1000 ); // UTF-16
1152 } else {
1153 codec = QTextCodec::codecForMib( 106 ); // UTF-8
1154 }
1155 if ( !codec )
1156 return QString::null;
1157
1158 encMapper = codec->makeDecoder();
1159 QString input = encMapper->toUnicode( data.data(), data.size() );
1160 // ### unexpected EOF? (for incremental parsing)
1161 // starts the document with an XML declaration?
1162 if ( input.find("<?xml") == 0 ) {
1163 // try to find out if there is an encoding
1164 int endPos = input.find( ">" );
1165 int pos = input.find( "encoding" );
1166 if ( pos < endPos && pos != -1 ) {
1167 QString encoding;
1168 do {
1169 pos++;
1170 if ( pos > endPos ) {
1171 return input;
1172 }
1173 } while( input[pos] != '"' && input[pos] != '\'' );
1174 pos++;
1175 while( input[pos] != '"' && input[pos] != '\'' ) {
1176 encoding += input[pos];
1177 pos++;
1178 if ( pos > endPos ) {
1179 return input;
1180 }
1181 }
1182
1183 codec = QTextCodec::codecForName( encoding );
1184 if ( codec == 0 ) {
1185 return input;
1186 }
1187 delete encMapper;
1188 encMapper = codec->makeDecoder();
1189 return encMapper->toUnicode( data.data(), data.size() );
1190 }
1191 }
1192 return input;
1193 }
1194 return encMapper->toUnicode( data.data(), data.size() );
1195}
1196
1197
1198/*********************************************
1199 *
1200 * QXmlDefaultHandler
1201 *
1202 *********************************************/
1203
1204/*!
1205 \class QXmlContentHandler qxml.h
1206 \reentrant
1207 \brief The QXmlContentHandler class provides an interface to
1208 report the logical content of XML data.
1209\if defined(commercial)
1210 It is part of the <a href="commercialeditions.html">Qt Enterprise Edition</a>.
1211\endif
1212
1213 \module XML
1214 \ingroup xml-tools
1215
1216 If the application needs to be informed of basic parsing events,
1217 it can implement this interface and activate it using
1218 QXmlReader::setContentHandler(). The reader can then report basic
1219 document-related events like the start and end of elements and
1220 character data through this interface.
1221
1222 The order of events in this interface is very important, and
1223 mirrors the order of information in the document itself. For
1224 example, all of an element's content (character data, processing
1225 instructions, and sub-elements) appears, in order, between the
1226 startElement() event and the corresponding endElement() event.
1227
1228 The class QXmlDefaultHandler provides a default implementation for
1229 this interface; subclassing from the QXmlDefaultHandler class is
1230 very convenient if you only want to be informed of some parsing
1231 events.
1232
1233 The startDocument() function is called at the start of the
1234 document, and endDocument() is called at the end. Before parsing
1235 begins setDocumentLocator() is called. For each element
1236 startElement() is called, with endElement() being called at the
1237 end of each element. The characters() function is called with
1238 chunks of character data; ignorableWhitespace() is called with
1239 chunks of whitespace and processingInstruction() is called with
1240 processing instructions. If an entity is skipped skippedEntity()
1241 is called. At the beginning of prefix-URI scopes
1242 startPrefixMapping() is called.
1243
1244 See also the \link xml.html#sax2Intro Introduction to SAX2\endlink.
1245
1246 \sa QXmlDTDHandler QXmlDeclHandler QXmlEntityResolver QXmlErrorHandler
1247 QXmlLexicalHandler
1248*/
1249
1250/*!
1251 \fn void QXmlContentHandler::setDocumentLocator( QXmlLocator* locator )
1252
1253 The reader calls this function before it starts parsing the
1254 document. The argument \a locator is a pointer to a QXmlLocator
1255 which allows the application to get the parsing position within
1256 the document.
1257
1258 Do not destroy the \a locator; it is destroyed when the reader is
1259 destroyed. (Do not use the \a locator after the reader is
1260 destroyed).
1261*/
1262
1263/*!
1264 \fn bool QXmlContentHandler::startDocument()
1265
1266 The reader calls this function when it starts parsing the
1267 document. The reader calls this function just once, after the call
1268 to setDocumentLocator(), and before any other functions in this
1269 class or in the QXmlDTDHandler class are called.
1270
1271 If this function returns FALSE the reader stops parsing and
1272 reports an error. The reader uses the function errorString() to
1273 get the error message.
1274
1275 \sa endDocument()
1276*/
1277
1278/*!
1279 \fn bool QXmlContentHandler::endDocument()
1280
1281 The reader calls this function after it has finished parsing. It
1282 is called just once, and is the last handler function called. It
1283 is called after the reader has read all input or has abandoned
1284 parsing because of a fatal error.
1285
1286 If this function returns FALSE the reader stops parsing and
1287 reports an error. The reader uses the function errorString() to
1288 get the error message.
1289
1290 \sa startDocument()
1291*/
1292
1293/*!
1294 \fn bool QXmlContentHandler::startPrefixMapping( const QString& prefix, const QString& uri )
1295
1296 The reader calls this function to signal the begin of a prefix-URI
1297 namespace mapping scope. This information is not necessary for
1298 normal namespace processing since the reader automatically
1299 replaces prefixes for element and attribute names.
1300
1301 Note that startPrefixMapping() and endPrefixMapping() calls are
1302 not guaranteed to be properly nested relative to each other: all
1303 startPrefixMapping() events occur before the corresponding
1304 startElement() event, and all endPrefixMapping() events occur
1305 after the corresponding endElement() event, but their order is not
1306 otherwise guaranteed.
1307
1308 The argument \a prefix is the namespace prefix being declared and
1309 the argument \a uri is the namespace URI the prefix is mapped to.
1310
1311 If this function returns FALSE the reader stops parsing and
1312 reports an error. The reader uses the function errorString() to
1313 get the error message.
1314
1315 See also the \link xml.html#sax2Namespaces namespace description\endlink.
1316
1317 \sa endPrefixMapping()
1318*/
1319
1320/*!
1321 \fn bool QXmlContentHandler::endPrefixMapping( const QString& prefix )
1322
1323 The reader calls this function to signal the end of a prefix
1324 mapping for the prefix \a prefix.
1325
1326 If this function returns FALSE the reader stops parsing and
1327 reports an error. The reader uses the function errorString() to
1328 get the error message.
1329
1330 See also the \link xml.html#sax2Namespaces namespace description\endlink.
1331
1332 \sa startPrefixMapping()
1333*/
1334
1335/*!
1336 \fn bool QXmlContentHandler::startElement( const QString& namespaceURI, const QString& localName, const QString& qName, const QXmlAttributes& atts )
1337
1338 The reader calls this function when it has parsed a start element
1339 tag.
1340
1341 There is a corresponding endElement() call when the corresponding
1342 end element tag is read. The startElement() and endElement() calls
1343 are always nested correctly. Empty element tags (e.g. \c{<x/>})
1344 cause a startElement() call to be immediately followed by an
1345 endElement() call.
1346
1347 The attribute list provided only contains attributes with explicit
1348 values. The attribute list contains attributes used for namespace
1349 declaration (i.e. attributes starting with xmlns) only if the
1350 namespace-prefix property of the reader is TRUE.
1351
1352 The argument \a namespaceURI is the namespace URI, or
1353 QString::null if the element has no namespace URI or if no
1354 namespace processing is done. \a localName is the local name
1355 (without prefix), or QString::null if no namespace processing is
1356 done, \a qName is the qualified name (with prefix) and \a atts are
1357 the attributes attached to the element. If there are no
1358 attributes, \a atts is an empty attributes object.
1359
1360 If this function returns FALSE the reader stops parsing and
1361 reports an error. The reader uses the function errorString() to
1362 get the error message.
1363
1364 See also the \link xml.html#sax2Namespaces namespace description\endlink.
1365
1366 \sa endElement()
1367*/
1368
1369/*!
1370 \fn bool QXmlContentHandler::endElement( const QString& namespaceURI, const QString& localName, const QString& qName )
1371
1372 The reader calls this function when it has parsed an end element
1373 tag with the qualified name \a qName, the local name \a localName
1374 and the namespace URI \a namespaceURI.
1375
1376 If this function returns FALSE the reader stops parsing and
1377 reports an error. The reader uses the function errorString() to
1378 get the error message.
1379
1380 See also the \link xml.html#sax2Namespaces namespace description\endlink.
1381
1382 \sa startElement()
1383*/
1384
1385/*!
1386 \fn bool QXmlContentHandler::characters( const QString& ch )
1387
1388 The reader calls this function when it has parsed a chunk of
1389 character data (either normal character data or character data
1390 inside a CDATA section; if you need to distinguish between those
1391 two types you must use QXmlLexicalHandler::startCDATA() and
1392 QXmlLexicalHandler::endCDATA()). The character data is reported in
1393 \a ch.
1394
1395 Some readers report whitespace in element content using the
1396 ignorableWhitespace() function rather than using this one.
1397
1398 A reader may report the character data of an element in more than
1399 one chunk; e.g. a reader might want to report "a\<b" in three
1400 characters() events ("a ", "\<" and " b").
1401
1402 If this function returns FALSE the reader stops parsing and
1403 reports an error. The reader uses the function errorString() to
1404 get the error message.
1405*/
1406
1407/*!
1408 \fn bool QXmlContentHandler::ignorableWhitespace( const QString& ch )
1409
1410 Some readers may use this function to report each chunk of
1411 whitespace in element content. The whitespace is reported in \a ch.
1412
1413 If this function returns FALSE the reader stops parsing and
1414 reports an error. The reader uses the function errorString() to
1415 get the error message.
1416*/
1417
1418/*!
1419 \fn bool QXmlContentHandler::processingInstruction( const QString& target, const QString& data )
1420
1421 The reader calls this function when it has parsed a processing
1422 instruction.
1423
1424 \a target is the target name of the processing instruction and \a
1425 data is the data in the processing instruction.
1426
1427 If this function returns FALSE the reader stops parsing and
1428 reports an error. The reader uses the function errorString() to
1429 get the error message.
1430*/
1431
1432/*!
1433 \fn bool QXmlContentHandler::skippedEntity( const QString& name )
1434
1435 Some readers may skip entities if they have not seen the
1436 declarations (e.g. because they are in an external DTD). If they
1437 do so they report that they skipped the entity called \a name by
1438 calling this function.
1439
1440 If this function returns FALSE the reader stops parsing and
1441 reports an error. The reader uses the function errorString() to
1442 get the error message.
1443*/
1444
1445/*!
1446 \fn QString QXmlContentHandler::errorString()
1447
1448 The reader calls this function to get an error string, e.g. if any
1449 of the handler functions returns FALSE.
1450*/
1451
1452
1453/*!
1454 \class QXmlErrorHandler qxml.h
1455 \reentrant
1456 \brief The QXmlErrorHandler class provides an interface to report
1457 errors in XML data.
1458\if defined(commercial)
1459 It is part of the <a href="commercialeditions.html">Qt Enterprise Edition</a>.
1460\endif
1461
1462 \module XML
1463 \ingroup xml-tools
1464
1465 If you want your application to report errors to the user or to
1466 perform customized error handling, you should subclass this class.
1467
1468 You can set the error handler with QXmlReader::setErrorHandler().
1469
1470 Errors can be reported using warning(), error() and fatalError(),
1471 with the error text being reported with errorString().
1472
1473 See also the \link xml.html#sax2Intro Introduction to SAX2\endlink.
1474
1475 \sa QXmlDTDHandler QXmlDeclHandler QXmlContentHandler QXmlEntityResolver
1476 QXmlLexicalHandler
1477*/
1478
1479/*!
1480 \fn bool QXmlErrorHandler::warning( const QXmlParseException& exception )
1481
1482 A reader might use this function to report a warning. Warnings are
1483 conditions that are not errors or fatal errors as defined by the
1484 XML 1.0 specification. Details of the warning are stored in \a
1485 exception.
1486
1487 If this function returns FALSE the reader stops parsing and
1488 reports an error. The reader uses the function errorString() to
1489 get the error message.
1490*/
1491
1492/*!
1493 \fn bool QXmlErrorHandler::error( const QXmlParseException& exception )
1494
1495 A reader might use this function to report a recoverable error. A
1496 recoverable error corresponds to the definiton of "error" in
1497 section 1.2 of the XML 1.0 specification. Details of the error are
1498 stored in \a exception.
1499
1500 The reader must continue to provide normal parsing events after
1501 invoking this function.
1502
1503 If this function returns FALSE the reader stops parsing and
1504 reports an error. The reader uses the function errorString() to
1505 get the error message.
1506*/
1507
1508/*!
1509 \fn bool QXmlErrorHandler::fatalError( const QXmlParseException& exception )
1510
1511 A reader must use this function to report a non-recoverable error.
1512 Details of the error are stored in \a exception.
1513
1514 If this function returns TRUE the reader might try to go on
1515 parsing and reporting further errors; but no regular parsing
1516 events are reported.
1517*/
1518
1519/*!
1520 \fn QString QXmlErrorHandler::errorString()
1521
1522 The reader calls this function to get an error string if any of
1523 the handler functions returns FALSE.
1524*/
1525
1526
1527/*!
1528 \class QXmlDTDHandler qxml.h
1529 \reentrant
1530 \brief The QXmlDTDHandler class provides an interface to report
1531 DTD content of XML data.
1532\if defined(commercial)
1533 It is part of the <a href="commercialeditions.html">Qt Enterprise Edition</a>.
1534\endif
1535
1536 \module XML
1537 \ingroup xml-tools
1538
1539 If an application needs information about notations and unparsed
1540 entities, it can implement this interface and register an instance
1541 with QXmlReader::setDTDHandler().
1542
1543 Note that this interface includes only those DTD events that the
1544 XML recommendation requires processors to report, i.e. notation
1545 and unparsed entity declarations using notationDecl() and
1546 unparsedEntityDecl() respectively.
1547
1548 See also the \link xml.html#sax2Intro Introduction to SAX2\endlink.
1549
1550 \sa QXmlDeclHandler QXmlContentHandler QXmlEntityResolver QXmlErrorHandler
1551 QXmlLexicalHandler
1552*/
1553
1554/*!
1555 \fn bool QXmlDTDHandler::notationDecl( const QString& name, const QString& publicId, const QString& systemId )
1556
1557 The reader calls this function when it has parsed a notation
1558 declaration.
1559
1560 The argument \a name is the notation name, \a publicId is the
1561 notation's public identifier and \a systemId is the notation's
1562 system identifier.
1563
1564 If this function returns FALSE the reader stops parsing and
1565 reports an error. The reader uses the function errorString() to
1566 get the error message.
1567*/
1568
1569/*!
1570 \fn bool QXmlDTDHandler::unparsedEntityDecl( const QString& name, const QString& publicId, const QString& systemId, const QString& notationName )
1571
1572 The reader calls this function when it finds an unparsed entity
1573 declaration.
1574
1575 The argument \a name is the unparsed entity's name, \a publicId is
1576 the entity's public identifier, \a systemId is the entity's system
1577 identifier and \a notationName is the name of the associated
1578 notation.
1579
1580 If this function returns FALSE the reader stops parsing and
1581 reports an error. The reader uses the function errorString() to
1582 get the error message.
1583*/
1584
1585/*!
1586 \fn QString QXmlDTDHandler::errorString()
1587
1588 The reader calls this function to get an error string if any of
1589 the handler functions returns FALSE.
1590*/
1591
1592
1593/*!
1594 \class QXmlEntityResolver qxml.h
1595 \reentrant
1596 \brief The QXmlEntityResolver class provides an interface to
1597 resolve external entities contained in XML data.
1598\if defined(commercial)
1599 It is part of the <a href="commercialeditions.html">Qt Enterprise Edition</a>.
1600\endif
1601
1602 \module XML
1603 \ingroup xml-tools
1604
1605 If an application needs to implement customized handling for
1606 external entities, it must implement this interface, i.e.
1607 resolveEntity(), and register it with
1608 QXmlReader::setEntityResolver().
1609
1610 See also the \link xml.html#sax2Intro Introduction to SAX2\endlink.
1611
1612 \sa QXmlDTDHandler QXmlDeclHandler QXmlContentHandler QXmlErrorHandler
1613 QXmlLexicalHandler
1614*/
1615
1616/*!
1617 \fn bool QXmlEntityResolver::resolveEntity( const QString& publicId, const QString& systemId, QXmlInputSource*& ret )
1618
1619 The reader calls this function before it opens any external
1620 entity, except the top-level document entity. The application may
1621 request the reader to resolve the entity itself (\a ret is 0) or
1622 to use an entirely different input source (\a ret points to the
1623 input source).
1624
1625 The reader deletes the input source \a ret when it no longer needs
1626 it, so you should allocate it on the heap with \c new.
1627
1628 The argument \a publicId is the public identifier of the external
1629 entity, \a systemId is the system identifier of the external
1630 entity and \a ret is the return value of this function. If \a ret
1631 is 0 the reader should resolve the entity itself, if it is
1632 non-zero it must point to an input source which the reader uses
1633 instead.
1634
1635 If this function returns FALSE the reader stops parsing and
1636 reports an error. The reader uses the function errorString() to
1637 get the error message.
1638*/
1639
1640/*!
1641 \fn QString QXmlEntityResolver::errorString()
1642
1643 The reader calls this function to get an error string if any of
1644 the handler functions returns FALSE.
1645*/
1646
1647
1648/*!
1649 \class QXmlLexicalHandler qxml.h
1650 \reentrant
1651 \brief The QXmlLexicalHandler class provides an interface to
1652 report the lexical content of XML data.
1653\if defined(commercial)
1654 It is part of the <a href="commercialeditions.html">Qt Enterprise Edition</a>.
1655\endif
1656
1657 \module XML
1658 \ingroup xml-tools
1659
1660 The events in the lexical handler apply to the entire document,
1661 not just to the document element, and all lexical handler events
1662 appear between the content handler's startDocument and endDocument
1663 events.
1664
1665 You can set the lexical handler with
1666 QXmlReader::setLexicalHandler().
1667
1668 This interface's design is based on the the SAX2 extension
1669 LexicalHandler.
1670
1671 The interface provides the startDTD(), endDTD(), startEntity(),
1672 endEntity(), startCDATA(), endCDATA() and comment() functions.
1673
1674 See also the \link xml.html#sax2Intro Introduction to SAX2\endlink.
1675
1676 \sa QXmlDTDHandler QXmlDeclHandler QXmlContentHandler QXmlEntityResolver
1677 QXmlErrorHandler
1678*/
1679
1680/*!
1681 \fn bool QXmlLexicalHandler::startDTD( const QString& name, const QString& publicId, const QString& systemId )
1682
1683 The reader calls this function to report the start of a DTD
1684 declaration, if any. It reports the name of the document type in
1685 \a name, the public identifier in \a publicId and the system
1686 identifier in \a systemId.
1687
1688 If the public identifier is missing, \a publicId is set to
1689 QString::null. If the system identifier is missing, \a systemId is
1690 set to QString::null. Note that it is not valid XML to have a
1691 public identifier but no system identifier; in such cases a parse
1692 error will occur.
1693
1694 All declarations reported through QXmlDTDHandler or
1695 QXmlDeclHandler appear between the startDTD() and endDTD() calls.
1696
1697 If this function returns FALSE the reader stops parsing and
1698 reports an error. The reader uses the function errorString() to
1699 get the error message.
1700
1701 \sa endDTD()
1702*/
1703
1704/*!
1705 \fn bool QXmlLexicalHandler::endDTD()
1706
1707 The reader calls this function to report the end of a DTD
1708 declaration, if any.
1709
1710 If this function returns FALSE the reader stops parsing and
1711 reports an error. The reader uses the function errorString() to
1712 get the error message.
1713
1714 \sa startDTD()
1715*/
1716
1717/*!
1718 \fn bool QXmlLexicalHandler::startEntity( const QString& name )
1719
1720 The reader calls this function to report the start of an entity
1721 called \a name.
1722
1723 Note that if the entity is unknown, the reader reports it through
1724 QXmlContentHandler::skippedEntity() and not through this
1725 function.
1726
1727 If this function returns FALSE the reader stops parsing and
1728 reports an error. The reader uses the function errorString() to
1729 get the error message.
1730
1731 \sa endEntity() QXmlSimpleReader::setFeature()
1732*/
1733
1734/*!
1735 \fn bool QXmlLexicalHandler::endEntity( const QString& name )
1736
1737 The reader calls this function to report the end of an entity
1738 called \a name.
1739
1740 For every startEntity() call, there is a corresponding endEntity()
1741 call. The calls to startEntity() and endEntity() are properly
1742 nested.
1743
1744 If this function returns FALSE the reader stops parsing and
1745 reports an error. The reader uses the function errorString() to
1746 get the error message.
1747
1748 \sa startEntity() QXmlContentHandler::skippedEntity() QXmlSimpleReader::setFeature()
1749*/
1750
1751/*!
1752 \fn bool QXmlLexicalHandler::startCDATA()
1753
1754 The reader calls this function to report the start of a CDATA
1755 section. The content of the CDATA section is reported through the
1756 QXmlContentHandler::characters() function. This function is
1757 intended only to report the boundary.
1758
1759 If this function returns FALSE the reader stops parsing and
1760 reports an error. The reader uses the function errorString() to
1761 get the error message.
1762
1763 \sa endCDATA()
1764*/
1765
1766/*!
1767 \fn bool QXmlLexicalHandler::endCDATA()
1768
1769 The reader calls this function to report the end of a CDATA
1770 section.
1771
1772 If this function returns FALSE the reader stops parsing and reports
1773 an error. The reader uses the function errorString() to get the error
1774 message.
1775
1776 \sa startCDATA() QXmlContentHandler::characters()
1777*/
1778
1779/*!
1780 \fn bool QXmlLexicalHandler::comment( const QString& ch )
1781
1782 The reader calls this function to report an XML comment anywhere
1783 in the document. It reports the text of the comment in \a ch.
1784
1785 If this function returns FALSE the reader stops parsing and
1786 reports an error. The reader uses the function errorString() to
1787 get the error message.
1788*/
1789
1790/*!
1791 \fn QString QXmlLexicalHandler::errorString()
1792
1793 The reader calls this function to get an error string if any of
1794 the handler functions returns FALSE.
1795*/
1796
1797
1798/*!
1799 \class QXmlDeclHandler qxml.h
1800 \reentrant
1801 \brief The QXmlDeclHandler class provides an interface to report declaration
1802 content of XML data.
1803\if defined(commercial)
1804 It is part of the <a href="commercialeditions.html">Qt Enterprise Edition</a>.
1805\endif
1806
1807 \module XML
1808 \ingroup xml-tools
1809
1810 You can set the declaration handler with
1811 QXmlReader::setDeclHandler().
1812
1813 This interface is based on the SAX2 extension DeclHandler.
1814
1815 The interface provides attributeDecl(), internalEntityDecl() and
1816 externalEntityDecl() functions.
1817
1818 See also the \link xml.html#sax2Intro Introduction to SAX2\endlink.
1819
1820 \sa QXmlDTDHandler QXmlContentHandler QXmlEntityResolver QXmlErrorHandler
1821 QXmlLexicalHandler
1822*/
1823
1824/*!
1825 \fn bool QXmlDeclHandler::attributeDecl( const QString& eName, const QString& aName, const QString& type, const QString& valueDefault, const QString& value )
1826
1827 The reader calls this function to report an attribute type
1828 declaration. Only the effective (first) declaration for an
1829 attribute is reported.
1830
1831 The reader passes the name of the associated element in \a eName
1832 and the name of the attribute in \a aName. It passes a string that
1833 represents the attribute type in \a type and a string that
1834 represents the attribute default in \a valueDefault. This string
1835 is one of "#IMPLIED", "#REQUIRED", "#FIXED" or QString::null (if
1836 none of the others applies). The reader passes the attribute's
1837 default value in \a value. If no default value is specified in the
1838 XML file, \a value is QString::null.
1839
1840 If this function returns FALSE the reader stops parsing and
1841 reports an error. The reader uses the function errorString() to
1842 get the error message.
1843*/
1844
1845/*!
1846 \fn bool QXmlDeclHandler::internalEntityDecl( const QString& name, const QString& value )
1847
1848 The reader calls this function to report an internal entity
1849 declaration. Only the effective (first) declaration is reported.
1850
1851 The reader passes the name of the entity in \a name and the value
1852 of the entity in \a value.
1853
1854 If this function returns FALSE the reader stops parsing and
1855 reports an error. The reader uses the function errorString() to
1856 get the error message.
1857*/
1858
1859/*!
1860 \fn bool QXmlDeclHandler::externalEntityDecl( const QString& name, const QString& publicId, const QString& systemId )
1861
1862 The reader calls this function to report a parsed external entity
1863 declaration. Only the effective (first) declaration for each
1864 entity is reported.
1865
1866 The reader passes the name of the entity in \a name, the public
1867 identifier in \a publicId and the system identifier in \a
1868 systemId. If there is no public identifier specified, it passes
1869 QString::null in \a publicId.
1870
1871 If this function returns FALSE the reader stops parsing and
1872 reports an error. The reader uses the function errorString() to
1873 get the error message.
1874*/
1875
1876/*!
1877 \fn QString QXmlDeclHandler::errorString()
1878
1879 The reader calls this function to get an error string if any of
1880 the handler functions returns FALSE.
1881*/
1882
1883
1884/*!
1885 \class QXmlDefaultHandler qxml.h
1886 \reentrant
1887 \brief The QXmlDefaultHandler class provides a default implementation of all
1888 the XML handler classes.
1889\if defined(commercial)
1890 It is part of the <a href="commercialeditions.html">Qt Enterprise Edition</a>.
1891\endif
1892
1893 \module XML
1894 \ingroup xml-tools
1895
1896 Very often we are only interested in parts of the things that the
1897 reader reports. This class implements a default behaviour for the
1898 handler classes (i.e. most of the time do nothing). Usually this
1899 is the class you subclass for implementing your own customized
1900 handler.
1901
1902 See also the \link xml.html#sax2Intro Introduction to SAX2\endlink.
1903
1904 \sa QXmlDTDHandler QXmlDeclHandler QXmlContentHandler QXmlEntityResolver
1905 QXmlErrorHandler QXmlLexicalHandler
1906*/
1907
1908/*!
1909 \fn QXmlDefaultHandler::QXmlDefaultHandler()
1910
1911 Constructor.
1912*/
1913/*!
1914 \fn QXmlDefaultHandler::~QXmlDefaultHandler()
1915
1916 Destructor.
1917*/
1918
1919/*!
1920 \reimp
1921
1922 Does nothing.
1923*/
1924void QXmlDefaultHandler::setDocumentLocator( QXmlLocator* )
1925{
1926}
1927
1928/*!
1929 \reimp
1930
1931 Does nothing.
1932*/
1933bool QXmlDefaultHandler::startDocument()
1934{
1935 return TRUE;
1936}
1937
1938/*!
1939 \reimp
1940
1941 Does nothing.
1942*/
1943bool QXmlDefaultHandler::endDocument()
1944{
1945 return TRUE;
1946}
1947
1948/*!
1949 \reimp
1950
1951 Does nothing.
1952*/
1953bool QXmlDefaultHandler::startPrefixMapping( const QString&, const QString& )
1954{
1955 return TRUE;
1956}
1957
1958/*!
1959 \reimp
1960
1961 Does nothing.
1962*/
1963bool QXmlDefaultHandler::endPrefixMapping( const QString& )
1964{
1965 return TRUE;
1966}
1967
1968/*!
1969 \reimp
1970
1971 Does nothing.
1972*/
1973bool QXmlDefaultHandler::startElement( const QString&, const QString&,
1974 const QString&, const QXmlAttributes& )
1975{
1976 return TRUE;
1977}
1978
1979/*!
1980 \reimp
1981
1982 Does nothing.
1983*/
1984bool QXmlDefaultHandler::endElement( const QString&, const QString&,
1985 const QString& )
1986{
1987 return TRUE;
1988}
1989
1990/*!
1991 \reimp
1992
1993 Does nothing.
1994*/
1995bool QXmlDefaultHandler::characters( const QString& )
1996{
1997 return TRUE;
1998}
1999
2000/*!
2001 \reimp
2002
2003 Does nothing.
2004*/
2005bool QXmlDefaultHandler::ignorableWhitespace( const QString& )
2006{
2007 return TRUE;
2008}
2009
2010/*!
2011 \reimp
2012
2013 Does nothing.
2014*/
2015bool QXmlDefaultHandler::processingInstruction( const QString&,
2016 const QString& )
2017{
2018 return TRUE;
2019}
2020
2021/*!
2022 \reimp
2023
2024 Does nothing.
2025*/
2026bool QXmlDefaultHandler::skippedEntity( const QString& )
2027{
2028 return TRUE;
2029}
2030
2031/*!
2032 \reimp
2033
2034 Does nothing.
2035*/
2036bool QXmlDefaultHandler::warning( const QXmlParseException& )
2037{
2038 return TRUE;
2039}
2040
2041/*!
2042 \reimp
2043
2044 Does nothing.
2045*/
2046bool QXmlDefaultHandler::error( const QXmlParseException& )
2047{
2048 return TRUE;
2049}
2050
2051/*!
2052 \reimp
2053
2054 Does nothing.
2055*/
2056bool QXmlDefaultHandler::fatalError( const QXmlParseException& )
2057{
2058 return TRUE;
2059}
2060
2061/*!
2062 \reimp
2063
2064 Does nothing.
2065*/
2066bool QXmlDefaultHandler::notationDecl( const QString&, const QString&,
2067 const QString& )
2068{
2069 return TRUE;
2070}
2071
2072/*!
2073 \reimp
2074
2075 Does nothing.
2076*/
2077bool QXmlDefaultHandler::unparsedEntityDecl( const QString&, const QString&,
2078 const QString&, const QString& )
2079{
2080 return TRUE;
2081}
2082
2083/*!
2084 \reimp
2085
2086 Sets \a ret to 0, so that the reader uses the system identifier
2087 provided in the XML document.
2088*/
2089bool QXmlDefaultHandler::resolveEntity( const QString&, const QString&,
2090 QXmlInputSource*& ret )
2091{
2092 ret = 0;
2093 return TRUE;
2094}
2095
2096/*!
2097 \reimp
2098
2099 Returns the default error string.
2100*/
2101QString QXmlDefaultHandler::errorString()
2102{
2103 return QString( XMLERR_ERRORBYCONSUMER );
2104}
2105
2106/*!
2107 \reimp
2108
2109 Does nothing.
2110*/
2111bool QXmlDefaultHandler::startDTD( const QString&, const QString&, const QString& )
2112{
2113 return TRUE;
2114}
2115
2116/*!
2117 \reimp
2118
2119 Does nothing.
2120*/
2121bool QXmlDefaultHandler::endDTD()
2122{
2123 return TRUE;
2124}
2125
2126/*!
2127 \reimp
2128
2129 Does nothing.
2130*/
2131bool QXmlDefaultHandler::startEntity( const QString& )
2132{
2133 return TRUE;
2134}
2135
2136/*!
2137 \reimp
2138
2139 Does nothing.
2140*/
2141bool QXmlDefaultHandler::endEntity( const QString& )
2142{
2143 return TRUE;
2144}
2145
2146/*!
2147 \reimp
2148
2149 Does nothing.
2150*/
2151bool QXmlDefaultHandler::startCDATA()
2152{
2153 return TRUE;
2154}
2155
2156/*!
2157 \reimp
2158
2159 Does nothing.
2160*/
2161bool QXmlDefaultHandler::endCDATA()
2162{
2163 return TRUE;
2164}
2165
2166/*!
2167 \reimp
2168
2169 Does nothing.
2170*/
2171bool QXmlDefaultHandler::comment( const QString& )
2172{
2173 return TRUE;
2174}
2175
2176/*!
2177 \reimp
2178
2179 Does nothing.
2180*/
2181bool QXmlDefaultHandler::attributeDecl( const QString&, const QString&, const QString&, const QString&, const QString& )
2182{
2183 return TRUE;
2184}
2185
2186/*!
2187 \reimp
2188
2189 Does nothing.
2190*/
2191bool QXmlDefaultHandler::internalEntityDecl( const QString&, const QString& )
2192{
2193 return TRUE;
2194}
2195
2196/*!
2197 \reimp
2198
2199 Does nothing.
2200*/
2201bool QXmlDefaultHandler::externalEntityDecl( const QString&, const QString&, const QString& )
2202{
2203 return TRUE;
2204}
2205
2206
2207/*********************************************
2208 *
2209 * QXmlSimpleReaderPrivate
2210 *
2211 *********************************************/
2212
2213class QXmlSimpleReaderPrivate
2214{
2215private:
2216 // functions
2217 QXmlSimpleReaderPrivate()
2218 {
2219 parseStack = 0;
2220 }
2221
2222 ~QXmlSimpleReaderPrivate()
2223 {
2224 delete parseStack;
2225 }
2226
2227 void initIncrementalParsing()
2228 {
2229 delete parseStack;
2230 parseStack = new QPtrStack<ParseState>;
2231 parseStack->setAutoDelete( TRUE );
2232 }
2233
2234 // used to determine if elements are correctly nested
2235 QValueStack<QString> tags;
2236
2237 // used for entity declarations
2238 struct ExternParameterEntity
2239 {
2240 ExternParameterEntity( ) {}
2241 ExternParameterEntity( const QString &p, const QString &s )
2242 : publicId(p), systemId(s) {}
2243 QString publicId;
2244 QString systemId;
2245
2246 Q_DUMMY_COMPARISON_OPERATOR(ExternParameterEntity)
2247 };
2248 struct ExternEntity
2249 {
2250 ExternEntity( ) {}
2251 ExternEntity( const QString &p, const QString &s, const QString &n )
2252 : publicId(p), systemId(s), notation(n) {}
2253 QString publicId;
2254 QString systemId;
2255 QString notation;
2256 Q_DUMMY_COMPARISON_OPERATOR(ExternEntity)
2257 };
2258 QMap<QString,ExternParameterEntity> externParameterEntities;
2259 QMap<QString,QString> parameterEntities;
2260 QMap<QString,ExternEntity> externEntities;
2261 QMap<QString,QString> entities;
2262
2263 // used for parsing of entity references
2264 QValueStack<QString> xmlRef;
2265 QValueStack<QString> xmlRefName;
2266
2267 // used for standalone declaration
2268 enum Standalone { Yes, No, Unknown };
2269
2270 QString doctype; // only used for the doctype
2271 QString xmlVersion; // only used to store the version information
2272 QString encoding; // only used to store the encoding
2273 Standalone standalone; // used to store the value of the standalone declaration
2274
2275 QString publicId; // used by parseExternalID() to store the public ID
2276 QString systemId; // used by parseExternalID() to store the system ID
2277 QString attDeclEName; // use by parseAttlistDecl()
2278 QString attDeclAName; // use by parseAttlistDecl()
2279
2280 // flags for some features support
2281 bool useNamespaces;
2282 bool useNamespacePrefixes;
2283 bool reportWhitespaceCharData;
2284 bool reportEntities;
2285
2286 // used to build the attribute list
2287 QXmlAttributes attList;
2288
2289 // used in QXmlSimpleReader::parseContent() to decide whether character
2290 // data was read
2291 bool contentCharDataRead;
2292
2293 // helper classes
2294 QXmlLocator *locator;
2295 QXmlNamespaceSupport namespaceSupport;
2296
2297 // error string
2298 QString error;
2299
2300 // arguments for parse functions (this is needed to allow incremental
2301 // parsing)
2302 bool parsePI_xmldecl;
2303 bool parseName_useRef;
2304 bool parseReference_charDataRead;
2305 QXmlSimpleReader::EntityRecognitionContext parseReference_context;
2306 bool parseExternalID_allowPublicID;
2307 QXmlSimpleReader::EntityRecognitionContext parsePEReference_context;
2308 QString parseString_s;
2309
2310 // for incremental parsing
2311 struct ParseState {
2312 typedef bool (QXmlSimpleReader::*ParseFunction) ();
2313 ParseFunction function;
2314 int state;
2315 };
2316 QPtrStack<ParseState> *parseStack;
2317
2318 // used in parseProlog()
2319 bool xmldecl_possible;
2320 bool doctype_read;
2321
2322 // used in parseDoctype()
2323 bool startDTDwasReported;
2324
2325 // used in parseString()
2326 signed char Done;
2327
2328
2329 // friend declarations
2330 friend class QXmlSimpleReader;
2331};
2332
2333
2334/*********************************************
2335 *
2336 * QXmlSimpleReader
2337 *
2338 *********************************************/
2339
2340/*!
2341 \class QXmlReader qxml.h
2342 \reentrant
2343 \brief The QXmlReader class provides an interface for XML readers (i.e.
2344 parsers).
2345\if defined(commercial)
2346 It is part of the <a href="commercialeditions.html">Qt Enterprise Edition</a>.
2347\endif
2348
2349 \module XML
2350 \ingroup xml-tools
2351
2352 This abstract class provides an interface for all of Qt's XML
2353 readers. Currently there is only one implementation of a reader
2354 included in Qt's XML module: QXmlSimpleReader. In future releases
2355 there might be more readers with different properties available
2356 (e.g. a validating parser).
2357
2358 The design of the XML classes follows the \link
2359 http://www.saxproject.org/ SAX2 Java interface\endlink, with
2360 the names adapted to fit Qt naming conventions. It should be very
2361 easy for anybody who has worked with SAX2 to get started with the
2362 Qt XML classes.
2363
2364 All readers use the class QXmlInputSource to read the input
2365 document. Since you are normally interested in particular content
2366 in the XML document, the reader reports the content through
2367 special handler classes (QXmlDTDHandler, QXmlDeclHandler,
2368 QXmlContentHandler, QXmlEntityResolver, QXmlErrorHandler and
2369 QXmlLexicalHandler), which you must subclass, if you want to
2370 process the contents.
2371
2372 Since the handler classes only describe interfaces you must
2373 implement all the functions. We provide the QXmlDefaultHandler
2374 class to make this easier: it implements a default behaviour (do
2375 nothing) for all functions, so you can subclass it and just
2376 implement the functions you are interested in.
2377
2378 Features and properties of the reader can be set with setFeature()
2379 and setProperty() respectively. You can set the reader to use your
2380 own subclasses with setEntityResolver(), setDTDHandler(),
2381 setContentHandler(), setErrorHandler(), setLexicalHandler() and
2382 setDeclHandler(). The parse itself is started with a call to
2383 parse().
2384
2385 \sa QXmlSimpleReader
2386*/
2387
2388/*!
2389 \fn bool QXmlReader::feature( const QString& name, bool *ok ) const
2390
2391 If the reader has the feature called \a name, the feature's value
2392 is returned. If no such feature exists the return value is
2393 undefined.
2394
2395 If \a ok is not 0: \a *ok is set to TRUE if the reader has the
2396 feature called \a name; otherwise \a *ok is set to FALSE.
2397
2398 \sa setFeature() hasFeature()
2399*/
2400
2401/*!
2402 \fn void QXmlReader::setFeature( const QString& name, bool value )
2403
2404 Sets the feature called \a name to the given \a value. If the
2405 reader doesn't have the feature nothing happens.
2406
2407 \sa feature() hasFeature()
2408*/
2409
2410/*!
2411 \fn bool QXmlReader::hasFeature( const QString& name ) const
2412
2413 Returns \c TRUE if the reader has the feature called \a name;
2414 otherwise returns FALSE.
2415
2416 \sa feature() setFeature()
2417*/
2418
2419/*!
2420 \fn void* QXmlReader::property( const QString& name, bool *ok ) const
2421
2422 If the reader has the property \a name, this function returns the
2423 value of the property; otherwise the return value is undefined.
2424
2425 If \a ok is not 0: if the reader has the \a name property \a *ok
2426 is set to TRUE; otherwise \a *ok is set to FALSE.
2427
2428 \sa setProperty() hasProperty()
2429*/
2430
2431/*!
2432 \fn void QXmlReader::setProperty( const QString& name, void* value )
2433
2434 Sets the property \a name to \a value. If the reader doesn't have
2435 the property nothing happens.
2436
2437 \sa property() hasProperty()
2438*/
2439
2440/*!
2441 \fn bool QXmlReader::hasProperty( const QString& name ) const
2442
2443 Returns TRUE if the reader has the property \a name; otherwise
2444 returns FALSE.
2445
2446 \sa property() setProperty()
2447*/
2448
2449/*!
2450 \fn void QXmlReader::setEntityResolver( QXmlEntityResolver* handler )
2451
2452 Sets the entity resolver to \a handler.
2453
2454 \sa entityResolver()
2455*/
2456
2457/*!
2458 \fn QXmlEntityResolver* QXmlReader::entityResolver() const
2459
2460 Returns the entity resolver or 0 if none was set.
2461
2462 \sa setEntityResolver()
2463*/
2464
2465/*!
2466 \fn void QXmlReader::setDTDHandler( QXmlDTDHandler* handler )
2467
2468 Sets the DTD handler to \a handler.
2469
2470 \sa DTDHandler()
2471*/
2472
2473/*!
2474 \fn QXmlDTDHandler* QXmlReader::DTDHandler() const
2475
2476 Returns the DTD handler or 0 if none was set.
2477
2478 \sa setDTDHandler()
2479*/
2480
2481/*!
2482 \fn void QXmlReader::setContentHandler( QXmlContentHandler* handler )
2483
2484 Sets the content handler to \a handler.
2485
2486 \sa contentHandler()
2487*/
2488
2489/*!
2490 \fn QXmlContentHandler* QXmlReader::contentHandler() const
2491
2492 Returns the content handler or 0 if none was set.
2493
2494 \sa setContentHandler()
2495*/
2496
2497/*!
2498 \fn void QXmlReader::setErrorHandler( QXmlErrorHandler* handler )
2499
2500 Sets the error handler to \a handler. Clears the error handler if
2501 \a handler is 0.
2502
2503 \sa errorHandler()
2504*/
2505
2506/*!
2507 \fn QXmlErrorHandler* QXmlReader::errorHandler() const
2508
2509 Returns the error handler or 0 if none is set.
2510
2511 \sa setErrorHandler()
2512*/
2513
2514/*!
2515 \fn void QXmlReader::setLexicalHandler( QXmlLexicalHandler* handler )
2516
2517 Sets the lexical handler to \a handler.
2518
2519 \sa lexicalHandler()
2520*/
2521
2522/*!
2523 \fn QXmlLexicalHandler* QXmlReader::lexicalHandler() const
2524
2525 Returns the lexical handler or 0 if none was set.
2526
2527 \sa setLexicalHandler()
2528*/
2529
2530/*!
2531 \fn void QXmlReader::setDeclHandler( QXmlDeclHandler* handler )
2532
2533 Sets the declaration handler to \a handler.
2534
2535 \sa declHandler()
2536*/
2537
2538/*!
2539 \fn QXmlDeclHandler* QXmlReader::declHandler() const
2540
2541 Returns the declaration handler or 0 if none was set.
2542
2543 \sa setDeclHandler()
2544*/
2545
2546/*!
2547 \fn bool QXmlReader::parse( const QXmlInputSource& input )
2548
2549 \obsolete
2550*/
2551
2552/*!
2553 \fn bool QXmlReader::parse( const QXmlInputSource* input )
2554
2555 Reads an XML document from \a input and parses it. Returns TRUE if
2556 the parsing was successful; otherwise returns FALSE.
2557*/
2558
2559
2560/*!
2561 \class QXmlSimpleReader qxml.h
2562 \reentrant
2563 \brief The QXmlSimpleReader class provides an implementation of a
2564 simple XML reader (parser).
2565\if defined(commercial)
2566 It is part of the <a href="commercialeditions.html">Qt Enterprise Edition</a>.
2567\endif
2568
2569 \module XML
2570 \ingroup xml-tools
2571 \mainclass
2572
2573 This XML reader is sufficient for simple parsing tasks. The reader:
2574 \list
2575 \i provides a well-formed parser;
2576 \i does not parse any external entities;
2577 \i can do namespace processing.
2578 \endlist
2579
2580 Documents are parsed with a call to parse().
2581
2582*/
2583
2584
2585/*!
2586 Constructs a simple XML reader with the following feature settings:
2587 \table
2588 \header \i Feature \i Setting
2589 \row \i \e http://xml.org/sax/features/namespaces \i TRUE
2590 \row \i \e http://xml.org/sax/features/namespace-prefixes \i FALSE
2591 \row \i \e http://trolltech.com/xml/features/report-whitespace-only-CharData
2592 \i TRUE
2593 \row \i \e http://trolltech.com/xml/features/report-start-end-entity \i FALSE
2594 \endtable
2595
2596 More information about features can be found in the \link
2597 xml.html#sax2Features Qt SAX2 overview. \endlink
2598
2599 \sa setFeature()
2600*/
2601QXmlSimpleReader::QXmlSimpleReader()
2602{
2603 d = new QXmlSimpleReaderPrivate();
2604 d->locator = new QXmlSimpleReaderLocator( this );
2605
2606 entityRes = 0;
2607 dtdHnd = 0;
2608 contentHnd = 0;
2609 errorHnd = 0;
2610 lexicalHnd = 0;
2611 declHnd = 0;
2612
2613 // default feature settings
2614 d->useNamespaces = TRUE;
2615 d->useNamespacePrefixes = FALSE;
2616 d->reportWhitespaceCharData = TRUE;
2617 d->reportEntities = FALSE;
2618}
2619
2620/*!
2621 Destroys the simple XML reader.
2622*/
2623QXmlSimpleReader::~QXmlSimpleReader()
2624{
2625 delete d->locator;
2626 delete d;
2627}
2628
2629/*!
2630 \reimp
2631*/
2632bool QXmlSimpleReader::feature( const QString& name, bool *ok ) const
2633{
2634 if ( ok != 0 )
2635 *ok = TRUE;
2636 if ( name == "http://xml.org/sax/features/namespaces" ) {
2637 return d->useNamespaces;
2638 } else if ( name == "http://xml.org/sax/features/namespace-prefixes" ) {
2639 return d->useNamespacePrefixes;
2640 } else if ( name == "http://trolltech.com/xml/features/report-whitespace-only-CharData" ) {
2641 return d->reportWhitespaceCharData;
2642 } else if ( name == "http://trolltech.com/xml/features/report-start-end-entity" ) {
2643 return d->reportEntities;
2644 } else {
2645 qWarning( "Unknown feature %s", name.latin1() );
2646 if ( ok != 0 )
2647 *ok = FALSE;
2648 }
2649 return FALSE;
2650}
2651
2652/*!
2653 Sets the state of the feature \a name to \a value:
2654
2655 If the feature is not recognized, it is ignored.
2656
2657 The following features are supported:
2658 \table
2659 \header \i Feature \i Notes
2660 \row \i \e http://xml.org/sax/features/namespaces
2661 \i If this feature is TRUE, namespace processing is
2662 performed.
2663 \row \i \e http://xml.org/sax/features/namespace-prefixes
2664 \i If this feature is TRUE, the the original prefixed names
2665 and attributes used for namespace declarations are
2666 reported.
2667 \row \i \e http://trolltech.com/xml/features/report-whitespace-only-CharData
2668 \i If this feature is TRUE, CharData that consist of
2669 whitespace only (and no other characters) are not reported
2670 via QXmlContentHandler::characters().
2671 \row \i \e http://trolltech.com/xml/features/report-start-end-entity
2672 \i If this feature is TRUE, the parser reports
2673 QXmlContentHandler::startEntity() and
2674 QXmlContentHandler::endEntity() events. So character data
2675 might be reported in chunks. If this feature is FALSE, the
2676 parser does not report those events, but rather silently
2677 substitutes the entities and reports the character data in
2678 one chunk.
2679 \endtable
2680
2681 \quotefile xml/tagreader-with-features/tagreader.cpp
2682 \skipto reader
2683 \printline reader
2684 \skipto setFeature
2685 \printline setFeature
2686 \printline TRUE
2687
2688 (Code taken from xml/tagreader-with-features/tagreader.cpp)
2689
2690 \sa feature() hasFeature()
2691*/
2692void QXmlSimpleReader::setFeature( const QString& name, bool value )
2693{
2694 if ( name == "http://xml.org/sax/features/namespaces" ) {
2695 d->useNamespaces = value;
2696 } else if ( name == "http://xml.org/sax/features/namespace-prefixes" ) {
2697 d->useNamespacePrefixes = value;
2698 } else if ( name == "http://trolltech.com/xml/features/report-whitespace-only-CharData" ) {
2699 d->reportWhitespaceCharData = value;
2700 } else if ( name == "http://trolltech.com/xml/features/report-start-end-entity" ) {
2701 d->reportEntities = value;
2702 } else {
2703 qWarning( "Unknown feature %s", name.latin1() );
2704 }
2705}
2706
2707/*! \reimp
2708*/
2709bool QXmlSimpleReader::hasFeature( const QString& name ) const
2710{
2711 if ( name == "http://xml.org/sax/features/namespaces"
2712 || name == "http://xml.org/sax/features/namespace-prefixes"
2713 || name == "http://trolltech.com/xml/features/report-whitespace-only-CharData"
2714 || name == "http://trolltech.com/xml/features/report-start-end-entity" ) {
2715 return TRUE;
2716 } else {
2717 return FALSE;
2718 }
2719}
2720
2721/*! \reimp
2722*/
2723void* QXmlSimpleReader::property( const QString&, bool *ok ) const
2724{
2725 if ( ok != 0 )
2726 *ok = FALSE;
2727 return 0;
2728}
2729
2730/*! \reimp
2731*/
2732void QXmlSimpleReader::setProperty( const QString&, void* )
2733{
2734}
2735
2736/*!
2737 \reimp
2738*/
2739bool QXmlSimpleReader::hasProperty( const QString& ) const
2740{
2741 return FALSE;
2742}
2743
2744/*!
2745 \reimp
2746*/
2747void QXmlSimpleReader::setEntityResolver( QXmlEntityResolver* handler )
2748{ entityRes = handler; }
2749
2750/*!
2751 \reimp
2752*/
2753QXmlEntityResolver* QXmlSimpleReader::entityResolver() const
2754{ return entityRes; }
2755
2756/*!
2757 \reimp
2758*/
2759void QXmlSimpleReader::setDTDHandler( QXmlDTDHandler* handler )
2760{ dtdHnd = handler; }
2761
2762/*!
2763 \reimp
2764*/
2765QXmlDTDHandler* QXmlSimpleReader::DTDHandler() const
2766{ return dtdHnd; }
2767
2768/*!
2769 \reimp
2770*/
2771void QXmlSimpleReader::setContentHandler( QXmlContentHandler* handler )
2772{ contentHnd = handler; }
2773
2774/*!
2775 \reimp
2776*/
2777QXmlContentHandler* QXmlSimpleReader::contentHandler() const
2778{ return contentHnd; }
2779
2780/*!
2781 \reimp
2782*/
2783void QXmlSimpleReader::setErrorHandler( QXmlErrorHandler* handler )
2784{ errorHnd = handler; }
2785
2786/*!
2787 \reimp
2788*/
2789QXmlErrorHandler* QXmlSimpleReader::errorHandler() const
2790{ return errorHnd; }
2791
2792/*!
2793 \reimp
2794*/
2795void QXmlSimpleReader::setLexicalHandler( QXmlLexicalHandler* handler )
2796{ lexicalHnd = handler; }
2797
2798/*!
2799 \reimp
2800*/
2801QXmlLexicalHandler* QXmlSimpleReader::lexicalHandler() const
2802{ return lexicalHnd; }
2803
2804/*!
2805 \reimp
2806*/
2807void QXmlSimpleReader::setDeclHandler( QXmlDeclHandler* handler )
2808{ declHnd = handler; }
2809
2810/*!
2811 \reimp
2812*/
2813QXmlDeclHandler* QXmlSimpleReader::declHandler() const
2814{ return declHnd; }
2815
2816
2817
2818/*!
2819 \reimp
2820*/
2821bool QXmlSimpleReader::parse( const QXmlInputSource& input )
2822{
2823 return parse( &input, FALSE );
2824}
2825
2826/*!
2827 \reimp
2828*/
2829bool QXmlSimpleReader::parse( const QXmlInputSource* input )
2830{
2831 return parse( input, FALSE );
2832}
2833
2834/*!
2835 Reads an XML document from \a input and parses it. Returns FALSE
2836 if the parsing detects an error; otherwise returns TRUE.
2837
2838 If \a incremental is TRUE, the parser does not return FALSE when
2839 it reaches the end of the \a input without reaching the end of the
2840 XML file. Instead it stores the state of the parser so that
2841 parsing can be continued at a later stage when more data is
2842 available. You can use the function parseContinue() to continue
2843 with parsing. This class stores a pointer to the input source \a
2844 input and the parseContinue() function tries to read from that
2845 input souce. This means that you should not delete the input
2846 source \a input until you've finished your calls to
2847 parseContinue(). If you call this function with \a incremental
2848 TRUE whilst an incremental parse is in progress a new parsing
2849 session will be started and the previous session lost.
2850
2851 If \a incremental is FALSE, this function behaves like the normal
2852 parse function, i.e. it returns FALSE when the end of input is
2853 reached without reaching the end of the XML file and the parsing
2854 cannot be continued.
2855
2856 \sa parseContinue() QSocket
2857*/
2858bool QXmlSimpleReader::parse( const QXmlInputSource *input, bool incremental )
2859{
2860 init( input );
2861 if ( incremental ) {
2862 d->initIncrementalParsing();
2863 } else {
2864 delete d->parseStack;
2865 d->parseStack = 0;
2866 }
2867 // call the handler
2868 if ( contentHnd ) {
2869 contentHnd->setDocumentLocator( d->locator );
2870 if ( !contentHnd->startDocument() ) {
2871 reportParseError( contentHnd->errorString() );
2872 d->tags.clear();
2873 return FALSE;
2874 }
2875 }
2876 return parseBeginOrContinue( 0, incremental );
2877}
2878
2879/*!
2880 Continues incremental parsing; this function reads the input from
2881 the QXmlInputSource that was specified with the last parse()
2882 command. To use this function, you \e must have called parse()
2883 with the incremental argument set to TRUE.
2884
2885 Returns FALSE if a parsing error occurs; otherwise returns TRUE.
2886
2887 If the input source returns an empty string for the function
2888 QXmlInputSource::data(), then this means that the end of the XML
2889 file has been reached; this is quite important, especially if you
2890 want to use the reader to parse more than one XML file.
2891
2892 The case of the end of the XML file being reached without having
2893 finished parsing is not considered to be an error: you can
2894 continue parsing at a later stage by calling this function again
2895 when there is more data available to parse.
2896
2897 This function assumes that the end of the XML document is reached
2898 if the QXmlInputSource::next() function returns
2899 QXmlInputSource::EndOfDocument. If the parser has not finished
2900 parsing when it encounters this symbol, it is an error and FALSE
2901 is returned.
2902
2903 \sa parse() QXmlInputSource::next()
2904*/
2905bool QXmlSimpleReader::parseContinue()
2906{
2907 if ( d->parseStack == 0 )
2908 return FALSE;
2909 if ( d->parseStack->isEmpty() )
2910 return FALSE;
2911 initData();
2912 int state = state = d->parseStack->top()->state;
2913 d->parseStack->remove();
2914 return parseBeginOrContinue( state, TRUE );
2915}
2916
2917/*
2918 Common part of parse() and parseContinue()
2919*/
2920bool QXmlSimpleReader::parseBeginOrContinue( int state, bool incremental )
2921{
2922 bool atEndOrig = atEnd();
2923
2924 if ( state==0 ) {
2925 if ( !parseProlog() ) {
2926 if ( incremental && d->error.isNull() ) {
2927 pushParseState( 0, 0 );
2928 return TRUE;
2929 } else {
2930 d->tags.clear();
2931 return FALSE;
2932 }
2933 }
2934 state = 1;
2935 }
2936 if ( state==1 ) {
2937 if ( !parseElement() ) {
2938 if ( incremental && d->error.isNull() ) {
2939 pushParseState( 0, 1 );
2940 return TRUE;
2941 } else {
2942 d->tags.clear();
2943 return FALSE;
2944 }
2945 }
2946 state = 2;
2947 }
2948 // parse Misc*
2949 while ( !atEnd() ) {
2950 if ( !parseMisc() ) {
2951 if ( incremental && d->error.isNull() ) {
2952 pushParseState( 0, 2 );
2953 return TRUE;
2954 } else {
2955 d->tags.clear();
2956 return FALSE;
2957 }
2958 }
2959 }
2960 if ( !atEndOrig && incremental ) {
2961 // we parsed something at all, so be prepared to come back later
2962 pushParseState( 0, 2 );
2963 return TRUE;
2964 }
2965 // is stack empty?
2966 if ( !d->tags.isEmpty() && !d->error.isNull() ) {
2967 reportParseError( XMLERR_UNEXPECTEDEOF );
2968 d->tags.clear();
2969 return FALSE;
2970 }
2971 // call the handler
2972 if ( contentHnd ) {
2973 delete d->parseStack;
2974 d->parseStack = 0;
2975 if ( !contentHnd->endDocument() ) {
2976 reportParseError( contentHnd->errorString() );
2977 return FALSE;
2978 }
2979 }
2980 return TRUE;
2981}
2982
2983//
2984// The following private parse functions have another semantics for the return
2985// value: They return TRUE iff parsing has finished successfully (i.e. the end
2986// of the XML file must be reached!). If one of these functions return FALSE,
2987// there is only an error when d->error.isNULL() is also FALSE.
2988//
2989
2990/*
2991 For the incremental parsing, it is very important that the parse...()
2992 functions have a certain structure. Since it might be hard to understand how
2993 they work, here is a description of the layout of these functions:
2994
2995 bool QXmlSimpleReader::parse...()
2996 {
2997(1) const signed char Init = 0;
2998 ...
2999
3000(2) const signed char Inp... = 0;
3001 ...
3002
3003(3) static signed char table[3][2] = {
3004 ...
3005 };
3006 signed char state;
3007 signed char input;
3008
3009(4) if ( d->parseStack==0 || d->parseStack->isEmpty() ) {
3010(4a) ...
3011 } else {
3012(4b) ...
3013 }
3014
3015 for ( ; ; ) {
3016(5) switch ( state ) {
3017 ...
3018 }
3019
3020(6)
3021(6a) if ( atEnd() ) {
3022 unexpectedEof( &QXmlSimpleReader::parseNmtoken, state );
3023 return FALSE;
3024 }
3025(6b) if ( is_NameChar(c) ) {
3026 ...
3027 }
3028(7) state = table[state][input];
3029
3030(8) switch ( state ) {
3031 ...
3032 }
3033 }
3034 }
3035
3036 Explanation:
3037 ad 1: constants for the states (used in the transition table)
3038 ad 2: constants for the input (used in the transition table)
3039 ad 3: the transition table for the state machine
3040 ad 4: test if we are in a parseContinue() step
3041 a) if no, do inititalizations
3042 b) if yes, restore the state and call parse functions recursively
3043 ad 5: Do some actions according to the state; from the logical execution
3044 order, this code belongs after 8 (see there for an explanation)
3045 ad 6: Check the character that is at the actual "cursor" position:
3046 a) If we reached the EOF, report either error or push the state (in the
3047 case of incremental parsing).
3048 b) Otherwise, set the input character constant for the transition
3049 table.
3050 ad 7: Get the new state according to the input that was read.
3051 ad 8: Do some actions according to the state. The last line in every case
3052 statement reads new data (i.e. it move the cursor). This can also be
3053 done by calling another parse...() funtion. If you need processing for
3054 this state after that, you have to put it into the switch statement 5.
3055 This ensures that you have a well defined re-entry point, when you ran
3056 out of data.
3057*/
3058
3059/*
3060 Parses the prolog [22].
3061*/
3062bool QXmlSimpleReader::parseProlog()
3063{
3064 const signed char Init = 0;
3065 const signed char EatWS = 1; // eat white spaces
3066 const signed char Lt = 2; // '<' read
3067 const signed char Em = 3; // '!' read
3068 const signed char DocType = 4; // read doctype
3069 const signed char Comment = 5; // read comment
3070 const signed char CommentR = 6; // same as Comment, but already reported
3071 const signed char PInstr = 7; // read PI
3072 const signed char PInstrR = 8; // same as PInstr, but already reported
3073 const signed char Done = 9;
3074
3075 const signed char InpWs = 0;
3076 const signed char InpLt = 1; // <
3077 const signed char InpQm = 2; // ?
3078 const signed char InpEm = 3; // !
3079 const signed char InpD = 4; // D
3080 const signed char InpDash = 5; // -
3081 const signed char InpUnknown = 6;
3082
3083 static const signed char table[9][7] = {
3084 /* InpWs InpLt InpQm InpEm InpD InpDash InpUnknown */
3085 { EatWS, Lt, -1, -1, -1, -1, -1 }, // Init
3086 { -1, Lt, -1, -1, -1, -1, -1 }, // EatWS
3087 { -1, -1, PInstr,Em, Done, -1, Done }, // Lt
3088 { -1, -1, -1, -1, DocType, Comment, -1 }, // Em
3089 { EatWS, Lt, -1, -1, -1, -1, -1 }, // DocType
3090 { EatWS, Lt, -1, -1, -1, -1, -1 }, // Comment
3091 { EatWS, Lt, -1, -1, -1, -1, -1 }, // CommentR
3092 { EatWS, Lt, -1, -1, -1, -1, -1 }, // PInstr
3093 { EatWS, Lt, -1, -1, -1, -1, -1 } // PInstrR
3094 };
3095 signed char state;
3096 signed char input;
3097
3098 if ( d->parseStack==0 || d->parseStack->isEmpty() ) {
3099 d->xmldecl_possible = TRUE;
3100 d->doctype_read = FALSE;
3101 state = Init;
3102 } else {
3103 state = d->parseStack->top()->state;
3104 d->parseStack->remove();
3105#if defined(QT_QXML_DEBUG)
3106 qDebug( "QXmlSimpleReader: parseProlog (cont) in state %d", state );
3107#endif
3108 if ( !d->parseStack->isEmpty() ) {
3109 ParseFunction function = d->parseStack->top()->function;
3110 if ( function == &QXmlSimpleReader::eat_ws ) {
3111 d->parseStack->remove();
3112#if defined(QT_QXML_DEBUG)
3113 qDebug( "QXmlSimpleReader: eat_ws (cont)" );
3114#endif
3115 }
3116 if ( !(this->*function)() ) {
3117 parseFailed( &QXmlSimpleReader::parseProlog, state );
3118 return FALSE;
3119 }
3120 }
3121 }
3122
3123 for (;;) {
3124 switch ( state ) {
3125 case DocType:
3126 if ( d->doctype_read ) {
3127 reportParseError( XMLERR_MORETHANONEDOCTYPE );
3128 return FALSE;
3129 } else {
3130 d->doctype_read = FALSE;
3131 }
3132 break;
3133 case Comment:
3134 if ( lexicalHnd ) {
3135 if ( !lexicalHnd->comment( string() ) ) {
3136 reportParseError( lexicalHnd->errorString() );
3137 return FALSE;
3138 }
3139 }
3140 state = CommentR;
3141 break;
3142 case PInstr:
3143 // call the handler
3144 if ( contentHnd ) {
3145 if ( d->xmldecl_possible && !d->xmlVersion.isEmpty() ) {
3146 QString value( "version = '" );
3147 value += d->xmlVersion;
3148 value += "'";
3149 if ( !d->encoding.isEmpty() ) {
3150 value += " encoding = '";
3151 value += d->encoding;
3152 value += "'";
3153 }
3154 if ( d->standalone == QXmlSimpleReaderPrivate::Yes ) {
3155 value += " standalone = 'yes'";
3156 } else if ( d->standalone == QXmlSimpleReaderPrivate::No ) {
3157 value += " standalone = 'no'";
3158 }
3159 if ( !contentHnd->processingInstruction( "xml", value ) ) {
3160 reportParseError( contentHnd->errorString() );
3161 return FALSE;
3162 }
3163 } else {
3164 if ( !contentHnd->processingInstruction( name(), string() ) ) {
3165 reportParseError( contentHnd->errorString() );
3166 return FALSE;
3167 }
3168 }
3169 }
3170 // XML declaration only on first position possible
3171 d->xmldecl_possible = FALSE;
3172 state = PInstrR;
3173 break;
3174 case Done:
3175 return TRUE;
3176 case -1:
3177 reportParseError( XMLERR_ERRORPARSINGELEMENT );
3178 return FALSE;
3179 }
3180
3181 if ( atEnd() ) {
3182 unexpectedEof( &QXmlSimpleReader::parseProlog, state );
3183 return FALSE;
3184 }
3185 if ( is_S(c) ) {
3186 input = InpWs;
3187 } else if ( c == '<' ) {
3188 input = InpLt;
3189 } else if ( c == '?' ) {
3190 input = InpQm;
3191 } else if ( c == '!' ) {
3192 input = InpEm;
3193 } else if ( c == 'D' ) {
3194 input = InpD;
3195 } else if ( c == '-' ) {
3196 input = InpDash;
3197 } else {
3198 input = InpUnknown;
3199 }
3200 state = table[state][input];
3201
3202 switch ( state ) {
3203 case EatWS:
3204 // XML declaration only on first position possible
3205 d->xmldecl_possible = FALSE;
3206 if ( !eat_ws() ) {
3207 parseFailed( &QXmlSimpleReader::parseProlog, state );
3208 return FALSE;
3209 }
3210 break;
3211 case Lt:
3212 next();
3213 break;
3214 case Em:
3215 // XML declaration only on first position possible
3216 d->xmldecl_possible = FALSE;
3217 next();
3218 break;
3219 case DocType:
3220 if ( !parseDoctype() ) {
3221 parseFailed( &QXmlSimpleReader::parseProlog, state );
3222 return FALSE;
3223 }
3224 break;
3225 case Comment:
3226 case CommentR:
3227 if ( !parseComment() ) {
3228 parseFailed( &QXmlSimpleReader::parseProlog, state );
3229 return FALSE;
3230 }
3231 break;
3232 case PInstr:
3233 case PInstrR:
3234 d->parsePI_xmldecl = d->xmldecl_possible;
3235 if ( !parsePI() ) {
3236 parseFailed( &QXmlSimpleReader::parseProlog, state );
3237 return FALSE;
3238 }
3239 break;
3240 }
3241 }
3242}
3243
3244/*
3245 Parse an element [39].
3246
3247 Precondition: the opening '<' is already read.
3248*/
3249bool QXmlSimpleReader::parseElement()
3250{
3251 const signed char Init = 0;
3252 const signed char ReadName = 1;
3253 const signed char Ws1 = 2;
3254 const signed char STagEnd = 3;
3255 const signed char STagEnd2 = 4;
3256 const signed char ETagBegin = 5;
3257 const signed char ETagBegin2 = 6;
3258 const signed char Ws2 = 7;
3259 const signed char EmptyTag = 8;
3260 const signed char Attrib = 9;
3261 const signed char AttribPro = 10; // like Attrib, but processAttribute was already called
3262 const signed char Ws3 = 11;
3263 const signed char Done = 12;
3264
3265 const signed char InpWs = 0; // whitespace
3266 const signed char InpNameBe = 1; // is_NameBeginning()
3267 const signed char InpGt = 2; // >
3268 const signed char InpSlash = 3; // /
3269 const signed char InpUnknown = 4;
3270
3271 static const signed char table[12][5] = {
3272 /* InpWs InpNameBe InpGt InpSlash InpUnknown */
3273 { -1, ReadName, -1, -1, -1 }, // Init
3274 { Ws1, Attrib, STagEnd, EmptyTag, -1 }, // ReadName
3275 { -1, Attrib, STagEnd, EmptyTag, -1 }, // Ws1
3276 { STagEnd2, STagEnd2, STagEnd2, STagEnd2, STagEnd2 }, // STagEnd
3277 { -1, -1, -1, ETagBegin, -1 }, // STagEnd2
3278 { -1, ETagBegin2, -1, -1, -1 }, // ETagBegin
3279 { Ws2, -1, Done, -1, -1 }, // ETagBegin2
3280 { -1, -1, Done, -1, -1 }, // Ws2
3281 { -1, -1, Done, -1, -1 }, // EmptyTag
3282 { Ws3, Attrib, STagEnd, EmptyTag, -1 }, // Attrib
3283 { Ws3, Attrib, STagEnd, EmptyTag, -1 }, // AttribPro
3284 { -1, Attrib, STagEnd, EmptyTag, -1 } // Ws3
3285 };
3286 signed char state;
3287 signed char input;
3288
3289 if ( d->parseStack==0 || d->parseStack->isEmpty() ) {
3290 state = Init;
3291 } else {
3292 state = d->parseStack->top()->state;
3293 d->parseStack->remove();
3294#if defined(QT_QXML_DEBUG)
3295 qDebug( "QXmlSimpleReader: parseElement (cont) in state %d", state );
3296#endif
3297 if ( !d->parseStack->isEmpty() ) {
3298 ParseFunction function = d->parseStack->top()->function;
3299 if ( function == &QXmlSimpleReader::eat_ws ) {
3300 d->parseStack->remove();
3301#if defined(QT_QXML_DEBUG)
3302 qDebug( "QXmlSimpleReader: eat_ws (cont)" );
3303#endif
3304 }
3305 if ( !(this->*function)() ) {
3306 parseFailed( &QXmlSimpleReader::parseElement, state );
3307 return FALSE;
3308 }
3309 }
3310 }
3311
3312 for (;;) {
3313 switch ( state ) {
3314 case ReadName:
3315 // store it on the stack
3316 d->tags.push( name() );
3317 // empty the attributes
3318 d->attList.clear();
3319 if ( d->useNamespaces ) {
3320 d->namespaceSupport.pushContext();
3321 }
3322 break;
3323 case ETagBegin2:
3324 if ( !processElementETagBegin2() )
3325 return FALSE;
3326 break;
3327 case Attrib:
3328 if ( !processElementAttribute() )
3329 return FALSE;
3330 state = AttribPro;
3331 break;
3332 case Done:
3333 return TRUE;
3334 case -1:
3335 reportParseError( XMLERR_ERRORPARSINGELEMENT );
3336 return FALSE;
3337 }
3338
3339 if ( atEnd() ) {
3340 unexpectedEof( &QXmlSimpleReader::parseElement, state );
3341 return FALSE;
3342 }
3343 if ( is_S(c) ) {
3344 input = InpWs;
3345 } else if ( is_NameBeginning(c) ) {
3346 input = InpNameBe;
3347 } else if ( c == '>' ) {
3348 input = InpGt;
3349 } else if ( c == '/' ) {
3350 input = InpSlash;
3351 } else {
3352 input = InpUnknown;
3353 }
3354 state = table[state][input];
3355
3356 switch ( state ) {
3357 case ReadName:
3358 d->parseName_useRef = FALSE;
3359 if ( !parseName() ) {
3360 parseFailed( &QXmlSimpleReader::parseElement, state );
3361 return FALSE;
3362 }
3363 break;
3364 case Ws1:
3365 case Ws2:
3366 case Ws3:
3367 if ( !eat_ws() ) {
3368 parseFailed( &QXmlSimpleReader::parseElement, state );
3369 return FALSE;
3370 }
3371 break;
3372 case STagEnd:
3373 // call the handler
3374 if ( contentHnd ) {
3375 if ( d->useNamespaces ) {
3376 QString uri, lname;
3377 d->namespaceSupport.processName( d->tags.top(), FALSE, uri, lname );
3378 if ( !contentHnd->startElement( uri, lname, d->tags.top(), d->attList ) ) {
3379 reportParseError( contentHnd->errorString() );
3380 return FALSE;
3381 }
3382 } else {
3383 if ( !contentHnd->startElement( QString::null, QString::null, d->tags.top(), d->attList ) ) {
3384 reportParseError( contentHnd->errorString() );
3385 return FALSE;
3386 }
3387 }
3388 }
3389 next();
3390 break;
3391 case STagEnd2:
3392 if ( !parseContent() ) {
3393 parseFailed( &QXmlSimpleReader::parseElement, state );
3394 return FALSE;
3395 }
3396 break;
3397 case ETagBegin:
3398 next();
3399 break;
3400 case ETagBegin2:
3401 // get the name of the tag
3402 d->parseName_useRef = FALSE;
3403 if ( !parseName() ) {
3404 parseFailed( &QXmlSimpleReader::parseElement, state );
3405 return FALSE;
3406 }
3407 break;
3408 case EmptyTag:
3409 if ( d->tags.isEmpty() ) {
3410 reportParseError( XMLERR_TAGMISMATCH );
3411 return FALSE;
3412 }
3413 if ( !processElementEmptyTag() )
3414 return FALSE;
3415 next();
3416 break;
3417 case Attrib:
3418 case AttribPro:
3419 // get name and value of attribute
3420 if ( !parseAttribute() ) {
3421 parseFailed( &QXmlSimpleReader::parseElement, state );
3422 return FALSE;
3423 }
3424 break;
3425 case Done:
3426 next();
3427 break;
3428 }
3429 }
3430}
3431/*
3432 Helper to break down the size of the code in the case statement.
3433 Return FALSE on error, otherwise TRUE.
3434*/
3435bool QXmlSimpleReader::processElementEmptyTag()
3436{
3437 QString uri, lname;
3438 // pop the stack and call the handler
3439 if ( contentHnd ) {
3440 if ( d->useNamespaces ) {
3441 // report startElement first...
3442 d->namespaceSupport.processName( d->tags.top(), FALSE, uri, lname );
3443 if ( !contentHnd->startElement( uri, lname, d->tags.top(), d->attList ) ) {
3444 reportParseError( contentHnd->errorString() );
3445 return FALSE;
3446 }
3447 // ... followed by endElement...
3448 if ( !contentHnd->endElement( uri, lname, d->tags.pop() ) ) {
3449 reportParseError( contentHnd->errorString() );
3450 return FALSE;
3451 }
3452 // ... followed by endPrefixMapping
3453 QStringList prefixesBefore, prefixesAfter;
3454 if ( contentHnd ) {
3455 prefixesBefore = d->namespaceSupport.prefixes();
3456 }
3457 d->namespaceSupport.popContext();
3458 // call the handler for prefix mapping
3459 prefixesAfter = d->namespaceSupport.prefixes();
3460 for ( QStringList::Iterator it = prefixesBefore.begin(); it != prefixesBefore.end(); ++it ) {
3461 if ( prefixesAfter.contains(*it) == 0 ) {
3462 if ( !contentHnd->endPrefixMapping( *it ) ) {
3463 reportParseError( contentHnd->errorString() );
3464 return FALSE;
3465 }
3466 }
3467 }
3468 } else {
3469 // report startElement first...
3470 if ( !contentHnd->startElement( QString::null, QString::null, d->tags.top(), d->attList ) ) {
3471 reportParseError( contentHnd->errorString() );
3472 return FALSE;
3473 }
3474 // ... followed by endElement
3475 if ( !contentHnd->endElement( QString::null, QString::null, d->tags.pop() ) ) {
3476 reportParseError( contentHnd->errorString() );
3477 return FALSE;
3478 }
3479 }
3480 } else {
3481 d->tags.pop_back();
3482 d->namespaceSupport.popContext();
3483 }
3484 return TRUE;
3485}
3486/*
3487 Helper to break down the size of the code in the case statement.
3488 Return FALSE on error, otherwise TRUE.
3489*/
3490bool QXmlSimpleReader::processElementETagBegin2()
3491{
3492 // pop the stack and compare it with the name
3493 if ( d->tags.pop() != name() ) {
3494 reportParseError( XMLERR_TAGMISMATCH );
3495 return FALSE;
3496 }
3497 // call the handler
3498 if ( contentHnd ) {
3499 if ( d->useNamespaces ) {
3500 QString uri, lname;
3501 d->namespaceSupport.processName( name(), FALSE, uri, lname );
3502 if ( !contentHnd->endElement( uri, lname, name() ) ) {
3503 reportParseError( contentHnd->errorString() );
3504 return FALSE;
3505 }
3506 } else {
3507 if ( !contentHnd->endElement( QString::null, QString::null, name() ) ) {
3508 reportParseError( contentHnd->errorString() );
3509 return FALSE;
3510 }
3511 }
3512 }
3513 if ( d->useNamespaces ) {
3514 QStringList prefixesBefore, prefixesAfter;
3515 if ( contentHnd ) {
3516 prefixesBefore = d->namespaceSupport.prefixes();
3517 }
3518 d->namespaceSupport.popContext();
3519 // call the handler for prefix mapping
3520 if ( contentHnd ) {
3521 prefixesAfter = d->namespaceSupport.prefixes();
3522 for ( QStringList::Iterator it = prefixesBefore.begin(); it != prefixesBefore.end(); ++it ) {
3523 if ( prefixesAfter.contains(*it) == 0 ) {
3524 if ( !contentHnd->endPrefixMapping( *it ) ) {
3525 reportParseError( contentHnd->errorString() );
3526 return FALSE;
3527 }
3528 }
3529 }
3530 }
3531 }
3532 return TRUE;
3533}
3534/*
3535 Helper to break down the size of the code in the case statement.
3536 Return FALSE on error, otherwise TRUE.
3537*/
3538bool QXmlSimpleReader::processElementAttribute()
3539{
3540 QString uri, lname, prefix;
3541 // add the attribute to the list
3542 if ( d->useNamespaces ) {
3543 // is it a namespace declaration?
3544 d->namespaceSupport.splitName( name(), prefix, lname );
3545 if ( prefix == "xmlns" ) {
3546 // namespace declaration
3547 d->namespaceSupport.setPrefix( lname, string() );
3548 if ( d->useNamespacePrefixes ) {
3549 // according to http://www.w3.org/2000/xmlns/, the "prefix"
3550 // xmlns maps to the namespace name
3551 // http://www.w3.org/2000/xmlns/
3552 d->attList.append( name(), "http://www.w3.org/2000/xmlns/", lname, string() );
3553 }
3554 // call the handler for prefix mapping
3555 if ( contentHnd ) {
3556 if ( !contentHnd->startPrefixMapping( lname, string() ) ) {
3557 reportParseError( contentHnd->errorString() );
3558 return FALSE;
3559 }
3560 }
3561 } else {
3562 // no namespace delcaration
3563 d->namespaceSupport.processName( name(), TRUE, uri, lname );
3564 d->attList.append( name(), uri, lname, string() );
3565 }
3566 } else {
3567 // no namespace support
3568 d->attList.append( name(), QString::null, QString::null, string() );
3569 }
3570 return TRUE;
3571}
3572
3573/*
3574 Parse a content [43].
3575
3576 A content is only used between tags. If a end tag is found the < is already
3577 read and the head stand on the '/' of the end tag '</name>'.
3578*/
3579bool QXmlSimpleReader::parseContent()
3580{
3581 const signed char Init = 0;
3582 const signed char ChD = 1; // CharData
3583 const signed char ChD1 = 2; // CharData help state
3584 const signed char ChD2 = 3; // CharData help state
3585 const signed char Ref = 4; // Reference
3586 const signed char Lt = 5; // '<' read
3587 const signed char PInstr = 6; // PI
3588 const signed char PInstrR = 7; // same as PInstr, but already reported
3589 const signed char Elem = 8; // Element
3590 const signed char Em = 9; // '!' read
3591 const signed char Com = 10; // Comment
3592 const signed char ComR = 11; // same as Com, but already reported
3593 const signed char CDS = 12; // CDSect
3594 const signed char CDS1 = 13; // read a CDSect
3595 const signed char CDS2 = 14; // read a CDSect (help state)
3596 const signed char CDS3 = 15; // read a CDSect (help state)
3597 const signed char Done = 16; // finished reading content
3598
3599 const signed char InpLt = 0; // <
3600 const signed char InpGt = 1; // >
3601 const signed char InpSlash = 2; // /
3602 const signed char InpQMark = 3; // ?
3603 const signed char InpEMark = 4; // !
3604 const signed char InpAmp = 5; // &
3605 const signed char InpDash = 6; // -
3606 const signed char InpOpenB = 7; // [
3607 const signed char InpCloseB = 8; // ]
3608 const signed char InpUnknown = 9;
3609
3610 static const signed char mapCLT2FSMChar[] = {
3611 InpUnknown, // white space
3612 InpUnknown, // %
3613 InpAmp, // &
3614 InpGt, // >
3615 InpLt, // <
3616 InpSlash, // /
3617 InpQMark, // ?
3618 InpEMark, // !
3619 InpDash, // -
3620 InpCloseB, // ]
3621 InpOpenB, // [
3622 InpUnknown, // =
3623 InpUnknown, // "
3624 InpUnknown, // '
3625 InpUnknown // unknown
3626 };
3627
3628 static const signed char table[16][10] = {
3629 /* InpLt InpGt InpSlash InpQMark InpEMark InpAmp InpDash InpOpenB InpCloseB InpUnknown */
3630 { Lt, ChD, ChD, ChD, ChD, Ref, ChD, ChD, ChD1, ChD }, // Init
3631 { Lt, ChD, ChD, ChD, ChD, Ref, ChD, ChD, ChD1, ChD }, // ChD
3632 { Lt, ChD, ChD, ChD, ChD, Ref, ChD, ChD, ChD2, ChD }, // ChD1
3633 { Lt, -1, ChD, ChD, ChD, Ref, ChD, ChD, ChD2, ChD }, // ChD2
3634 { Lt, ChD, ChD, ChD, ChD, Ref, ChD, ChD, ChD, ChD }, // Ref (same as Init)
3635 { -1, -1, Done, PInstr, Em, -1, -1, -1, -1, Elem }, // Lt
3636 { Lt, ChD, ChD, ChD, ChD, Ref, ChD, ChD, ChD, ChD }, // PInstr (same as Init)
3637 { Lt, ChD, ChD, ChD, ChD, Ref, ChD, ChD, ChD, ChD }, // PInstrR
3638 { Lt, ChD, ChD, ChD, ChD, Ref, ChD, ChD, ChD, ChD }, // Elem (same as Init)
3639 { -1, -1, -1, -1, -1, -1, Com, CDS, -1, -1 }, // Em
3640 { Lt, ChD, ChD, ChD, ChD, Ref, ChD, ChD, ChD, ChD }, // Com (same as Init)
3641 { Lt, ChD, ChD, ChD, ChD, Ref, ChD, ChD, ChD, ChD }, // ComR
3642 { CDS1, CDS1, CDS1, CDS1, CDS1, CDS1, CDS1, CDS1, CDS2, CDS1 }, // CDS
3643 { CDS1, CDS1, CDS1, CDS1, CDS1, CDS1, CDS1, CDS1, CDS2, CDS1 }, // CDS1
3644 { CDS1, CDS1, CDS1, CDS1, CDS1, CDS1, CDS1, CDS1, CDS3, CDS1 }, // CDS2
3645 { CDS1, Init, CDS1, CDS1, CDS1, CDS1, CDS1, CDS1, CDS3, CDS1 } // CDS3
3646 };
3647 signed char state;
3648 signed char input;
3649
3650 if ( d->parseStack==0 || d->parseStack->isEmpty() ) {
3651 d->contentCharDataRead = FALSE;
3652 state = Init;
3653 } else {
3654 state = d->parseStack->top()->state;
3655 d->parseStack->remove();
3656#if defined(QT_QXML_DEBUG)
3657 qDebug( "QXmlSimpleReader: parseContent (cont) in state %d", state );
3658#endif
3659 if ( !d->parseStack->isEmpty() ) {
3660 ParseFunction function = d->parseStack->top()->function;
3661 if ( function == &QXmlSimpleReader::eat_ws ) {
3662 d->parseStack->remove();
3663#if defined(QT_QXML_DEBUG)
3664 qDebug( "QXmlSimpleReader: eat_ws (cont)" );
3665#endif
3666 }
3667 if ( !(this->*function)() ) {
3668 parseFailed( &QXmlSimpleReader::parseContent, state );
3669 return FALSE;
3670 }
3671 }
3672 }
3673
3674 for (;;) {
3675 switch ( state ) {
3676 case Ref:
3677 if ( !d->contentCharDataRead)
3678 d->contentCharDataRead = d->parseReference_charDataRead;
3679 break;
3680 case PInstr:
3681 if ( contentHnd ) {
3682 if ( !contentHnd->processingInstruction(name(),string()) ) {
3683 reportParseError( contentHnd->errorString() );
3684 return FALSE;
3685 }
3686 }
3687 state = PInstrR;
3688 break;
3689 case Com:
3690 if ( lexicalHnd ) {
3691 if ( !lexicalHnd->comment( string() ) ) {
3692 reportParseError( lexicalHnd->errorString() );
3693 return FALSE;
3694 }
3695 }
3696 state = ComR;
3697 break;
3698 case CDS:
3699 stringClear();
3700 break;
3701 case CDS2:
3702 if ( !atEnd() && c != ']' )
3703 stringAddC( ']' );
3704 break;
3705 case CDS3:
3706 // test if this skipping was legal
3707 if ( !atEnd() ) {
3708 if ( c == '>' ) {
3709 // the end of the CDSect
3710 if ( lexicalHnd ) {
3711 if ( !lexicalHnd->startCDATA() ) {
3712 reportParseError( lexicalHnd->errorString() );
3713 return FALSE;
3714 }
3715 }
3716 if ( contentHnd ) {
3717 if ( !contentHnd->characters( string() ) ) {
3718 reportParseError( contentHnd->errorString() );
3719 return FALSE;
3720 }
3721 }
3722 if ( lexicalHnd ) {
3723 if ( !lexicalHnd->endCDATA() ) {
3724 reportParseError( lexicalHnd->errorString() );
3725 return FALSE;
3726 }
3727 }
3728 } else if (c == ']') {
3729 // three or more ']'
3730 stringAddC( ']' );
3731 } else {
3732 // after ']]' comes another character
3733 stringAddC( ']' );
3734 stringAddC( ']' );
3735 }
3736 }
3737 break;
3738 case Done:
3739 // call the handler for CharData
3740 if ( contentHnd ) {
3741 if ( d->contentCharDataRead ) {
3742 if ( d->reportWhitespaceCharData || !string().simplifyWhiteSpace().isEmpty() ) {
3743 if ( !contentHnd->characters( string() ) ) {
3744 reportParseError( contentHnd->errorString() );
3745 return FALSE;
3746 }
3747 }
3748 }
3749 }
3750 // Done
3751 return TRUE;
3752 case -1:
3753 // Error
3754 reportParseError( XMLERR_ERRORPARSINGCONTENT );
3755 return FALSE;
3756 }
3757
3758 // get input (use lookup-table instead of nested ifs for performance
3759 // reasons)
3760 if ( atEnd() ) {
3761 unexpectedEof( &QXmlSimpleReader::parseContent, state );
3762 return FALSE;
3763 }
3764 if ( c.row() ) {
3765 input = InpUnknown;
3766 } else {
3767 input = mapCLT2FSMChar[ charLookupTable[ c.cell() ] ];
3768 }
3769 state = table[state][input];
3770
3771 switch ( state ) {
3772 case Init:
3773 // skip the ending '>' of a CDATASection
3774 next();
3775 break;
3776 case ChD:
3777 // on first call: clear string
3778 if ( !d->contentCharDataRead ) {
3779 d->contentCharDataRead = TRUE;
3780 stringClear();
3781 }
3782 stringAddC();
3783 if ( d->reportEntities ) {
3784 if ( !reportEndEntities() )
3785 return FALSE;
3786 }
3787 next();
3788 break;
3789 case ChD1:
3790 // on first call: clear string
3791 if ( !d->contentCharDataRead ) {
3792 d->contentCharDataRead = TRUE;
3793 stringClear();
3794 }
3795 stringAddC();
3796 if ( d->reportEntities ) {
3797 if ( !reportEndEntities() )
3798 return FALSE;
3799 }
3800 next();
3801 break;
3802 case ChD2:
3803 stringAddC();
3804 if ( d->reportEntities ) {
3805 if ( !reportEndEntities() )
3806 return FALSE;
3807 }
3808 next();
3809 break;
3810 case Ref:
3811 if ( !d->contentCharDataRead) {
3812 // reference may be CharData; so clear string to be safe
3813 stringClear();
3814 d->parseReference_context = InContent;
3815 if ( !parseReference() ) {
3816 parseFailed( &QXmlSimpleReader::parseContent, state );
3817 return FALSE;
3818 }
3819 } else {
3820 if ( d->reportEntities ) {
3821 // report character data in chunks
3822 if ( contentHnd ) {
3823 if ( d->reportWhitespaceCharData || !string().simplifyWhiteSpace().isEmpty() ) {
3824 if ( !contentHnd->characters( string() ) ) {
3825 reportParseError( contentHnd->errorString() );
3826 return FALSE;
3827 }
3828 }
3829 }
3830 stringClear();
3831 }
3832 d->parseReference_context = InContent;
3833 if ( !parseReference() ) {
3834 parseFailed( &QXmlSimpleReader::parseContent, state );
3835 return FALSE;
3836 }
3837 }
3838 break;
3839 case Lt:
3840 // call the handler for CharData
3841 if ( contentHnd ) {
3842 if ( d->contentCharDataRead ) {
3843 if ( d->reportWhitespaceCharData || !string().simplifyWhiteSpace().isEmpty() ) {
3844 if ( !contentHnd->characters( string() ) ) {
3845 reportParseError( contentHnd->errorString() );
3846 return FALSE;
3847 }
3848 }
3849 }
3850 }
3851 d->contentCharDataRead = FALSE;
3852 next();
3853 break;
3854 case PInstr:
3855 case PInstrR:
3856 d->parsePI_xmldecl = FALSE;
3857 if ( !parsePI() ) {
3858 parseFailed( &QXmlSimpleReader::parseContent, state );
3859 return FALSE;
3860 }
3861 break;
3862 case Elem:
3863 if ( !parseElement() ) {
3864 parseFailed( &QXmlSimpleReader::parseContent, state );
3865 return FALSE;
3866 }
3867 break;
3868 case Em:
3869 next();
3870 break;
3871 case Com:
3872 case ComR:
3873 if ( !parseComment() ) {
3874 parseFailed( &QXmlSimpleReader::parseContent, state );
3875 return FALSE;
3876 }
3877 break;
3878 case CDS:
3879 d->parseString_s = "[CDATA[";
3880 if ( !parseString() ) {
3881 parseFailed( &QXmlSimpleReader::parseContent, state );
3882 return FALSE;
3883 }
3884 break;
3885 case CDS1:
3886 stringAddC();
3887 next();
3888 break;
3889 case CDS2:
3890 // skip ']'
3891 next();
3892 break;
3893 case CDS3:
3894 // skip ']'...
3895 next();
3896 break;
3897 }
3898 }
3899}
3900bool QXmlSimpleReader::reportEndEntities()
3901{
3902 int count = (int)d->xmlRef.count();
3903 while ( count != 0 && d->xmlRef.top().isEmpty() ) {
3904 if ( contentHnd ) {
3905 if ( d->reportWhitespaceCharData || !string().simplifyWhiteSpace().isEmpty() ) {
3906 if ( !contentHnd->characters( string() ) ) {
3907 reportParseError( contentHnd->errorString() );
3908 return FALSE;
3909 }
3910 }
3911 }
3912 stringClear();
3913 if ( lexicalHnd ) {
3914 if ( !lexicalHnd->endEntity(d->xmlRefName.top()) ) {
3915 reportParseError( lexicalHnd->errorString() );
3916 return FALSE;
3917 }
3918 }
3919 d->xmlRef.pop_back();
3920 d->xmlRefName.pop_back();
3921 count--;
3922 }
3923 return TRUE;
3924}
3925
3926/*
3927 Parse Misc [27].
3928*/
3929bool QXmlSimpleReader::parseMisc()
3930{
3931 const signed char Init = 0;
3932 const signed char Lt = 1; // '<' was read
3933 const signed char Comment = 2; // read comment
3934 const signed char eatWS = 3; // eat whitespaces
3935 const signed char PInstr = 4; // read PI
3936 const signed char Comment2 = 5; // read comment
3937
3938 const signed char InpWs = 0; // S
3939 const signed char InpLt = 1; // <
3940 const signed char InpQm = 2; // ?
3941 const signed char InpEm = 3; // !
3942 const signed char InpUnknown = 4;
3943
3944 static const signed char table[3][5] = {
3945 /* InpWs InpLt InpQm InpEm InpUnknown */
3946 { eatWS, Lt, -1, -1, -1 }, // Init
3947 { -1, -1, PInstr,Comment, -1 }, // Lt
3948 { -1, -1, -1, -1, Comment2 } // Comment
3949 };
3950 signed char state;
3951 signed char input;
3952
3953 if ( d->parseStack==0 || d->parseStack->isEmpty() ) {
3954 state = Init;
3955 } else {
3956 state = d->parseStack->top()->state;
3957 d->parseStack->remove();
3958#if defined(QT_QXML_DEBUG)
3959 qDebug( "QXmlSimpleReader: parseMisc (cont) in state %d", state );
3960#endif
3961 if ( !d->parseStack->isEmpty() ) {
3962 ParseFunction function = d->parseStack->top()->function;
3963 if ( function == &QXmlSimpleReader::eat_ws ) {
3964 d->parseStack->remove();
3965#if defined(QT_QXML_DEBUG)
3966 qDebug( "QXmlSimpleReader: eat_ws (cont)" );
3967#endif
3968 }
3969 if ( !(this->*function)() ) {
3970 parseFailed( &QXmlSimpleReader::parseMisc, state );
3971 return FALSE;
3972 }
3973 }
3974 }
3975
3976 for (;;) {
3977 switch ( state ) {
3978 case eatWS:
3979 return TRUE;
3980 case PInstr:
3981 if ( contentHnd ) {
3982 if ( !contentHnd->processingInstruction(name(),string()) ) {
3983 reportParseError( contentHnd->errorString() );
3984 return FALSE;
3985 }
3986 }
3987 return TRUE;
3988 case Comment2:
3989 if ( lexicalHnd ) {
3990 if ( !lexicalHnd->comment( string() ) ) {
3991 reportParseError( lexicalHnd->errorString() );
3992 return FALSE;
3993 }
3994 }
3995 return TRUE;
3996 case -1:
3997 // Error
3998 reportParseError( XMLERR_UNEXPECTEDCHARACTER );
3999 return FALSE;
4000 }
4001
4002 if ( atEnd() ) {
4003 unexpectedEof( &QXmlSimpleReader::parseMisc, state );
4004 return FALSE;
4005 }
4006 if ( is_S(c) ) {
4007 input = InpWs;
4008 } else if ( c == '<' ) {
4009 input = InpLt;
4010 } else if ( c == '?' ) {
4011 input = InpQm;
4012 } else if ( c == '!' ) {
4013 input = InpEm;
4014 } else {
4015 input = InpUnknown;
4016 }
4017 state = table[state][input];
4018
4019 switch ( state ) {
4020 case eatWS:
4021 if ( !eat_ws() ) {
4022 parseFailed( &QXmlSimpleReader::parseMisc, state );
4023 return FALSE;
4024 }
4025 break;
4026 case Lt:
4027 next();
4028 break;
4029 case PInstr:
4030 d->parsePI_xmldecl = FALSE;
4031 if ( !parsePI() ) {
4032 parseFailed( &QXmlSimpleReader::parseMisc, state );
4033 return FALSE;
4034 }
4035 break;
4036 case Comment:
4037 next();
4038 break;
4039 case Comment2:
4040 if ( !parseComment() ) {
4041 parseFailed( &QXmlSimpleReader::parseMisc, state );
4042 return FALSE;
4043 }
4044 break;
4045 }
4046 }
4047}
4048
4049/*
4050 Parse a processing instruction [16].
4051
4052 If xmldec is TRUE, it tries to parse a PI or a XML declaration [23].
4053
4054 Precondition: the beginning '<' of the PI is already read and the head stand
4055 on the '?' of '<?'.
4056
4057 If this funktion was successful, the head-position is on the first
4058 character after the PI.
4059*/
4060bool QXmlSimpleReader::parsePI()
4061{
4062 const signed char Init = 0;
4063 const signed char QmI = 1; // ? was read
4064 const signed char Name = 2; // read Name
4065 const signed char XMLDecl = 3; // read XMLDecl
4066 const signed char Ws1 = 4; // eat ws after "xml" of XMLDecl
4067 const signed char PInstr = 5; // read PI
4068 const signed char Ws2 = 6; // eat ws after Name of PI
4069 const signed char Version = 7; // read versionInfo
4070 const signed char Ws3 = 8; // eat ws after versionInfo
4071 const signed char EorSD = 9; // read EDecl or SDDecl
4072 const signed char Ws4 = 10; // eat ws after EDecl or SDDecl
4073 const signed char SD = 11; // read SDDecl
4074 const signed char Ws5 = 12; // eat ws after SDDecl
4075 const signed char ADone = 13; // almost done
4076 const signed char Char = 14; // Char was read
4077 const signed char Qm = 15; // Qm was read
4078 const signed char Done = 16; // finished reading content
4079
4080 const signed char InpWs = 0; // whitespace
4081 const signed char InpNameBe = 1; // is_nameBeginning()
4082 const signed char InpGt = 2; // >
4083 const signed char InpQm = 3; // ?
4084 const signed char InpUnknown = 4;
4085
4086 static const signed char table[16][5] = {
4087 /* InpWs, InpNameBe InpGt InpQm InpUnknown */
4088 { -1, -1, -1, QmI, -1 }, // Init
4089 { -1, Name, -1, -1, -1 }, // QmI
4090 { -1, -1, -1, -1, -1 }, // Name (this state is left not through input)
4091 { Ws1, -1, -1, -1, -1 }, // XMLDecl
4092 { -1, Version, -1, -1, -1 }, // Ws1
4093 { Ws2, -1, -1, Qm, -1 }, // PInstr
4094 { Char, Char, Char, Qm, Char }, // Ws2
4095 { Ws3, -1, -1, ADone, -1 }, // Version
4096 { -1, EorSD, -1, ADone, -1 }, // Ws3
4097 { Ws4, -1, -1, ADone, -1 }, // EorSD
4098 { -1, SD, -1, ADone, -1 }, // Ws4
4099 { Ws5, -1, -1, ADone, -1 }, // SD
4100 { -1, -1, -1, ADone, -1 }, // Ws5
4101 { -1, -1, Done, -1, -1 }, // ADone
4102 { Char, Char, Char, Qm, Char }, // Char
4103 { Char, Char, Done, Qm, Char }, // Qm
4104 };
4105 signed char state;
4106 signed char input;
4107
4108 if ( d->parseStack==0 || d->parseStack->isEmpty() ) {
4109 state = Init;
4110 } else {
4111 state = d->parseStack->top()->state;
4112 d->parseStack->remove();
4113#if defined(QT_QXML_DEBUG)
4114 qDebug( "QXmlSimpleReader: parsePI (cont) in state %d", state );
4115#endif
4116 if ( !d->parseStack->isEmpty() ) {
4117 ParseFunction function = d->parseStack->top()->function;
4118 if ( function == &QXmlSimpleReader::eat_ws ) {
4119 d->parseStack->remove();
4120#if defined(QT_QXML_DEBUG)
4121 qDebug( "QXmlSimpleReader: eat_ws (cont)" );
4122#endif
4123 }
4124 if ( !(this->*function)() ) {
4125 parseFailed( &QXmlSimpleReader::parsePI, state );
4126 return FALSE;
4127 }
4128 }
4129 }
4130
4131 for (;;) {
4132 switch ( state ) {
4133 case Name:
4134 // test what name was read and determine the next state
4135 // (not very beautiful, I admit)
4136 if ( name().lower() == "xml" ) {
4137 if ( d->parsePI_xmldecl && name()=="xml" ) {
4138 state = XMLDecl;
4139 } else {
4140 reportParseError( XMLERR_INVALIDNAMEFORPI );
4141 return FALSE;
4142 }
4143 } else {
4144 state = PInstr;
4145 stringClear();
4146 }
4147 break;
4148 case Version:
4149 // get version (syntax like an attribute)
4150 if ( name() != "version" ) {
4151 reportParseError( XMLERR_VERSIONEXPECTED );
4152 return FALSE;
4153 }
4154 d->xmlVersion = string();
4155 break;
4156 case EorSD:
4157 // get the EDecl or SDDecl (syntax like an attribute)
4158 if ( name() == "standalone" ) {
4159 if ( string()=="yes" ) {
4160 d->standalone = QXmlSimpleReaderPrivate::Yes;
4161 } else if ( string()=="no" ) {
4162 d->standalone = QXmlSimpleReaderPrivate::No;
4163 } else {
4164 reportParseError( XMLERR_WRONGVALUEFORSDECL );
4165 return FALSE;
4166 }
4167 } else if ( name() == "encoding" ) {
4168 d->encoding = string();
4169 } else {
4170 reportParseError( XMLERR_EDECLORSDDECLEXPECTED );
4171 return FALSE;
4172 }
4173 break;
4174 case SD:
4175 if ( name() != "standalone" ) {
4176 reportParseError( XMLERR_SDDECLEXPECTED );
4177 return FALSE;
4178 }
4179 if ( string()=="yes" ) {
4180 d->standalone = QXmlSimpleReaderPrivate::Yes;
4181 } else if ( string()=="no" ) {
4182 d->standalone = QXmlSimpleReaderPrivate::No;
4183 } else {
4184 reportParseError( XMLERR_WRONGVALUEFORSDECL );
4185 return FALSE;
4186 }
4187 break;
4188 case Qm:
4189 // test if the skipping was legal
4190 if ( !atEnd() && c != '>' )
4191 stringAddC( '?' );
4192 break;
4193 case Done:
4194 return TRUE;
4195 case -1:
4196 // Error
4197 reportParseError( XMLERR_UNEXPECTEDCHARACTER );
4198 return FALSE;
4199 }
4200
4201 if ( atEnd() ) {
4202 unexpectedEof( &QXmlSimpleReader::parsePI, state );
4203 return FALSE;
4204 }
4205 if ( is_S(c) ) {
4206 input = InpWs;
4207 } else if ( is_NameBeginning(c) ) {
4208 input = InpNameBe;
4209 } else if ( c == '>' ) {
4210 input = InpGt;
4211 } else if ( c == '?' ) {
4212 input = InpQm;
4213 } else {
4214 input = InpUnknown;
4215 }
4216 state = table[state][input];
4217
4218 switch ( state ) {
4219 case QmI:
4220 next();
4221 break;
4222 case Name:
4223 d->parseName_useRef = FALSE;
4224 if ( !parseName() ) {
4225 parseFailed( &QXmlSimpleReader::parsePI, state );
4226 return FALSE;
4227 }
4228 break;
4229 case Ws1:
4230 case Ws2:
4231 case Ws3:
4232 case Ws4:
4233 case Ws5:
4234 if ( !eat_ws() ) {
4235 parseFailed( &QXmlSimpleReader::parsePI, state );
4236 return FALSE;
4237 }
4238 break;
4239 case Version:
4240 if ( !parseAttribute() ) {
4241 parseFailed( &QXmlSimpleReader::parsePI, state );
4242 return FALSE;
4243 }
4244 break;
4245 case EorSD:
4246 if ( !parseAttribute() ) {
4247 parseFailed( &QXmlSimpleReader::parsePI, state );
4248 return FALSE;
4249 }
4250 break;
4251 case SD:
4252 // get the SDDecl (syntax like an attribute)
4253 if ( d->standalone != QXmlSimpleReaderPrivate::Unknown ) {
4254 // already parsed the standalone declaration
4255 reportParseError( XMLERR_UNEXPECTEDCHARACTER );
4256 return FALSE;
4257 }
4258 if ( !parseAttribute() ) {
4259 parseFailed( &QXmlSimpleReader::parsePI, state );
4260 return FALSE;
4261 }
4262 break;
4263 case ADone:
4264 next();
4265 break;
4266 case Char:
4267 stringAddC();
4268 next();
4269 break;
4270 case Qm:
4271 // skip the '?'
4272 next();
4273 break;
4274 case Done:
4275 next();
4276 break;
4277 }
4278 }
4279}
4280
4281/*
4282 Parse a document type definition (doctypedecl [28]).
4283
4284 Precondition: the beginning '<!' of the doctype is already read the head
4285 stands on the 'D' of '<!DOCTYPE'.
4286
4287 If this funktion was successful, the head-position is on the first
4288 character after the document type definition.
4289*/
4290bool QXmlSimpleReader::parseDoctype()
4291{
4292 const signed char Init = 0;
4293 const signed char Doctype = 1; // read the doctype
4294 const signed char Ws1 = 2; // eat_ws
4295 const signed char Doctype2 = 3; // read the doctype, part 2
4296 const signed char Ws2 = 4; // eat_ws
4297 const signed char Sys = 5; // read SYSTEM or PUBLIC
4298 const signed char Ws3 = 6; // eat_ws
4299 const signed char MP = 7; // markupdecl or PEReference
4300 const signed char MPR = 8; // same as MP, but already reported
4301 const signed char PER = 9; // PERReference
4302 const signed char Mup = 10; // markupdecl
4303 const signed char Ws4 = 11; // eat_ws
4304 const signed char MPE = 12; // end of markupdecl or PEReference
4305 const signed char Done = 13;
4306
4307 const signed char InpWs = 0;
4308 const signed char InpD = 1; // 'D'
4309 const signed char InpS = 2; // 'S' or 'P'
4310 const signed char InpOB = 3; // [
4311 const signed char InpCB = 4; // ]
4312 const signed char InpPer = 5; // %
4313 const signed char InpGt = 6; // >
4314 const signed char InpUnknown = 7;
4315
4316 static const signed char table[13][8] = {
4317 /* InpWs, InpD InpS InpOB InpCB InpPer InpGt InpUnknown */
4318 { -1, Doctype, -1, -1, -1, -1, -1, -1 }, // Init
4319 { Ws1, -1, -1, -1, -1, -1, -1, -1 }, // Doctype
4320 { -1, Doctype2, Doctype2, -1, -1, -1, -1, Doctype2 }, // Ws1
4321 { Ws2, -1, Sys, MP, -1, -1, Done, -1 }, // Doctype2
4322 { -1, -1, Sys, MP, -1, -1, Done, -1 }, // Ws2
4323 { Ws3, -1, -1, MP, -1, -1, Done, -1 }, // Sys
4324 { -1, -1, -1, MP, -1, -1, Done, -1 }, // Ws3
4325 { -1, -1, -1, -1, MPE, PER, -1, Mup }, // MP
4326 { -1, -1, -1, -1, MPE, PER, -1, Mup }, // MPR
4327 { Ws4, -1, -1, -1, MPE, PER, -1, Mup }, // PER
4328 { Ws4, -1, -1, -1, MPE, PER, -1, Mup }, // Mup
4329 { -1, -1, -1, -1, MPE, PER, -1, Mup }, // Ws4
4330 { -1, -1, -1, -1, -1, -1, Done, -1 } // MPE
4331 };
4332 signed char state;
4333 signed char input;
4334
4335 if ( d->parseStack==0 || d->parseStack->isEmpty() ) {
4336 d->startDTDwasReported = FALSE;
4337 d->systemId = QString::null;
4338 d->publicId = QString::null;
4339 state = Init;
4340 } else {
4341 state = d->parseStack->top()->state;
4342 d->parseStack->remove();
4343#if defined(QT_QXML_DEBUG)
4344 qDebug( "QXmlSimpleReader: parseDoctype (cont) in state %d", state );
4345#endif
4346 if ( !d->parseStack->isEmpty() ) {
4347 ParseFunction function = d->parseStack->top()->function;
4348 if ( function == &QXmlSimpleReader::eat_ws ) {
4349 d->parseStack->remove();
4350#if defined(QT_QXML_DEBUG)
4351 qDebug( "QXmlSimpleReader: eat_ws (cont)" );
4352#endif
4353 }
4354 if ( !(this->*function)() ) {
4355 parseFailed( &QXmlSimpleReader::parseDoctype, state );
4356 return FALSE;
4357 }
4358 }
4359 }
4360
4361 for (;;) {
4362 switch ( state ) {
4363 case Doctype2:
4364 d->doctype = name();
4365 break;
4366 case MP:
4367 if ( !d->startDTDwasReported && lexicalHnd ) {
4368 d->startDTDwasReported = TRUE;
4369 if ( !lexicalHnd->startDTD( d->doctype, d->publicId, d->systemId ) ) {
4370 reportParseError( lexicalHnd->errorString() );
4371 return FALSE;
4372 }
4373 }
4374 state = MPR;
4375 break;
4376 case Done:
4377 return TRUE;
4378 case -1:
4379 // Error
4380 reportParseError( XMLERR_ERRORPARSINGDOCTYPE );
4381 return FALSE;
4382 }
4383
4384 if ( atEnd() ) {
4385 unexpectedEof( &QXmlSimpleReader::parseDoctype, state );
4386 return FALSE;
4387 }
4388 if ( is_S(c) ) {
4389 input = InpWs;
4390 } else if ( c == 'D' ) {
4391 input = InpD;
4392 } else if ( c == 'S' ) {
4393 input = InpS;
4394 } else if ( c == 'P' ) {
4395 input = InpS;
4396 } else if ( c == '[' ) {
4397 input = InpOB;
4398 } else if ( c == ']' ) {
4399 input = InpCB;
4400 } else if ( c == '%' ) {
4401 input = InpPer;
4402 } else if ( c == '>' ) {
4403 input = InpGt;
4404 } else {
4405 input = InpUnknown;
4406 }
4407 state = table[state][input];
4408
4409 switch ( state ) {
4410 case Doctype:
4411 d->parseString_s = "DOCTYPE";
4412 if ( !parseString() ) {
4413 parseFailed( &QXmlSimpleReader::parseDoctype, state );
4414 return FALSE;
4415 }
4416 break;
4417 case Ws1:
4418 case Ws2:
4419 case Ws3:
4420 case Ws4:
4421 if ( !eat_ws() ) {
4422 parseFailed( &QXmlSimpleReader::parseDoctype, state );
4423 return FALSE;
4424 }
4425 break;
4426 case Doctype2:
4427 d->parseName_useRef = FALSE;
4428 if ( !parseName() ) {
4429 parseFailed( &QXmlSimpleReader::parseDoctype, state );
4430 return FALSE;
4431 }
4432 break;
4433 case Sys:
4434 d->parseExternalID_allowPublicID = FALSE;
4435 if ( !parseExternalID() ) {
4436 parseFailed( &QXmlSimpleReader::parseDoctype, state );
4437 return FALSE;
4438 }
4439 break;
4440 case MP:
4441 case MPR:
4442 if ( !next_eat_ws() ) {
4443 parseFailed( &QXmlSimpleReader::parseDoctype, state );
4444 return FALSE;
4445 }
4446 break;
4447 case PER:
4448 d->parsePEReference_context = InDTD;
4449 if ( !parsePEReference() ) {
4450 parseFailed( &QXmlSimpleReader::parseDoctype, state );
4451 return FALSE;
4452 }
4453 break;
4454 case Mup:
4455 if ( !parseMarkupdecl() ) {
4456 parseFailed( &QXmlSimpleReader::parseDoctype, state );
4457 return FALSE;
4458 }
4459 break;
4460 case MPE:
4461 if ( !next_eat_ws() ) {
4462 parseFailed( &QXmlSimpleReader::parseDoctype, state );
4463 return FALSE;
4464 }
4465 break;
4466 case Done:
4467 if ( lexicalHnd ) {
4468 if ( !d->startDTDwasReported ) {
4469 d->startDTDwasReported = TRUE;
4470 if ( !lexicalHnd->startDTD( d->doctype, d->publicId, d->systemId ) ) {
4471 reportParseError( lexicalHnd->errorString() );
4472 return FALSE;
4473 }
4474 }
4475 if ( !lexicalHnd->endDTD() ) {
4476 reportParseError( lexicalHnd->errorString() );
4477 return FALSE;
4478 }
4479 }
4480 next();
4481 break;
4482 }
4483 }
4484}
4485
4486/*
4487 Parse a ExternalID [75].
4488
4489 If allowPublicID is TRUE parse ExternalID [75] or PublicID [83].
4490*/
4491bool QXmlSimpleReader::parseExternalID()
4492{
4493 const signed char Init = 0;
4494 const signed char Sys = 1; // parse 'SYSTEM'
4495 const signed char SysWS = 2; // parse the whitespace after 'SYSTEM'
4496 const signed char SysSQ = 3; // parse SystemLiteral with '
4497 const signed char SysSQ2 = 4; // parse SystemLiteral with '
4498 const signed char SysDQ = 5; // parse SystemLiteral with "
4499 const signed char SysDQ2 = 6; // parse SystemLiteral with "
4500 const signed char Pub = 7; // parse 'PUBLIC'
4501 const signed char PubWS = 8; // parse the whitespace after 'PUBLIC'
4502 const signed char PubSQ = 9; // parse PubidLiteral with '
4503 const signed char PubSQ2 = 10; // parse PubidLiteral with '
4504 const signed char PubDQ = 11; // parse PubidLiteral with "
4505 const signed char PubDQ2 = 12; // parse PubidLiteral with "
4506 const signed char PubE = 13; // finished parsing the PubidLiteral
4507 const signed char PubWS2 = 14; // parse the whitespace after the PubidLiteral
4508 const signed char PDone = 15; // done if allowPublicID is TRUE
4509 const signed char Done = 16;
4510
4511 const signed char InpSQ = 0; // '
4512 const signed char InpDQ = 1; // "
4513 const signed char InpS = 2; // S
4514 const signed char InpP = 3; // P
4515 const signed char InpWs = 4; // white space
4516 const signed char InpUnknown = 5;
4517
4518 static const signed char table[15][6] = {
4519 /* InpSQ InpDQ InpS InpP InpWs InpUnknown */
4520 { -1, -1, Sys, Pub, -1, -1 }, // Init
4521 { -1, -1, -1, -1, SysWS, -1 }, // Sys
4522 { SysSQ, SysDQ, -1, -1, -1, -1 }, // SysWS
4523 { Done, SysSQ2, SysSQ2, SysSQ2, SysSQ2, SysSQ2 }, // SysSQ
4524 { Done, SysSQ2, SysSQ2, SysSQ2, SysSQ2, SysSQ2 }, // SysSQ2
4525 { SysDQ2, Done, SysDQ2, SysDQ2, SysDQ2, SysDQ2 }, // SysDQ
4526 { SysDQ2, Done, SysDQ2, SysDQ2, SysDQ2, SysDQ2 }, // SysDQ2
4527 { -1, -1, -1, -1, PubWS, -1 }, // Pub
4528 { PubSQ, PubDQ, -1, -1, -1, -1 }, // PubWS
4529 { PubE, -1, PubSQ2, PubSQ2, PubSQ2, PubSQ2 }, // PubSQ
4530 { PubE, -1, PubSQ2, PubSQ2, PubSQ2, PubSQ2 }, // PubSQ2
4531 { -1, PubE, PubDQ2, PubDQ2, PubDQ2, PubDQ2 }, // PubDQ
4532 { -1, PubE, PubDQ2, PubDQ2, PubDQ2, PubDQ2 }, // PubDQ2
4533 { PDone, PDone, PDone, PDone, PubWS2, PDone }, // PubE
4534 { SysSQ, SysDQ, PDone, PDone, PDone, PDone } // PubWS2
4535 };
4536 signed char state;
4537 signed char input;
4538
4539 if ( d->parseStack==0 || d->parseStack->isEmpty() ) {
4540 d->systemId = QString::null;
4541 d->publicId = QString::null;
4542 state = Init;
4543 } else {
4544 state = d->parseStack->top()->state;
4545 d->parseStack->remove();
4546#if defined(QT_QXML_DEBUG)
4547 qDebug( "QXmlSimpleReader: parseExternalID (cont) in state %d", state );
4548#endif
4549 if ( !d->parseStack->isEmpty() ) {
4550 ParseFunction function = d->parseStack->top()->function;
4551 if ( function == &QXmlSimpleReader::eat_ws ) {
4552 d->parseStack->remove();
4553#if defined(QT_QXML_DEBUG)
4554 qDebug( "QXmlSimpleReader: eat_ws (cont)" );
4555#endif
4556 }
4557 if ( !(this->*function)() ) {
4558 parseFailed( &QXmlSimpleReader::parseExternalID, state );
4559 return FALSE;
4560 }
4561 }
4562 }
4563
4564 for (;;) {
4565 switch ( state ) {
4566 case PDone:
4567 if ( d->parseExternalID_allowPublicID ) {
4568 d->publicId = string();
4569 return TRUE;
4570 } else {
4571 reportParseError( XMLERR_UNEXPECTEDCHARACTER );
4572 return FALSE;
4573 }
4574 case Done:
4575 return TRUE;
4576 case -1:
4577 // Error
4578 reportParseError( XMLERR_UNEXPECTEDCHARACTER );
4579 return FALSE;
4580 }
4581
4582 if ( atEnd() ) {
4583 unexpectedEof( &QXmlSimpleReader::parseExternalID, state );
4584 return FALSE;
4585 }
4586 if ( is_S(c) ) {
4587 input = InpWs;
4588 } else if ( c == '\'' ) {
4589 input = InpSQ;
4590 } else if ( c == '"' ) {
4591 input = InpDQ;
4592 } else if ( c == 'S' ) {
4593 input = InpS;
4594 } else if ( c == 'P' ) {
4595 input = InpP;
4596 } else {
4597 input = InpUnknown;
4598 }
4599 state = table[state][input];
4600
4601 switch ( state ) {
4602 case Sys:
4603 d->parseString_s = "SYSTEM";
4604 if ( !parseString() ) {
4605 parseFailed( &QXmlSimpleReader::parseExternalID, state );
4606 return FALSE;
4607 }
4608 break;
4609 case SysWS:
4610 if ( !eat_ws() ) {
4611 parseFailed( &QXmlSimpleReader::parseExternalID, state );
4612 return FALSE;
4613 }
4614 break;
4615 case SysSQ:
4616 case SysDQ:
4617 stringClear();
4618 next();
4619 break;
4620 case SysSQ2:
4621 case SysDQ2:
4622 stringAddC();
4623 next();
4624 break;
4625 case Pub:
4626 d->parseString_s = "PUBLIC";
4627 if ( !parseString() ) {
4628 parseFailed( &QXmlSimpleReader::parseExternalID, state );
4629 return FALSE;
4630 }
4631 break;
4632 case PubWS:
4633 if ( !eat_ws() ) {
4634 parseFailed( &QXmlSimpleReader::parseExternalID, state );
4635 return FALSE;
4636 }
4637 break;
4638 case PubSQ:
4639 case PubDQ:
4640 stringClear();
4641 next();
4642 break;
4643 case PubSQ2:
4644 case PubDQ2:
4645 stringAddC();
4646 next();
4647 break;
4648 case PubE:
4649 next();
4650 break;
4651 case PubWS2:
4652 d->publicId = string();
4653 if ( !eat_ws() ) {
4654 parseFailed( &QXmlSimpleReader::parseExternalID, state );
4655 return FALSE;
4656 }
4657 break;
4658 case Done:
4659 d->systemId = string();
4660 next();
4661 break;
4662 }
4663 }
4664}
4665
4666/*
4667 Parse a markupdecl [29].
4668*/
4669bool QXmlSimpleReader::parseMarkupdecl()
4670{
4671 const signed char Init = 0;
4672 const signed char Lt = 1; // < was read
4673 const signed char Em = 2; // ! was read
4674 const signed char CE = 3; // E was read
4675 const signed char Qm = 4; // ? was read
4676 const signed char Dash = 5; // - was read
4677 const signed char CA = 6; // A was read
4678 const signed char CEL = 7; // EL was read
4679 const signed char CEN = 8; // EN was read
4680 const signed char CN = 9; // N was read
4681 const signed char Done = 10;
4682
4683 const signed char InpLt = 0; // <
4684 const signed char InpQm = 1; // ?
4685 const signed char InpEm = 2; // !
4686 const signed char InpDash = 3; // -
4687 const signed char InpA = 4; // A
4688 const signed char InpE = 5; // E
4689 const signed char InpL = 6; // L
4690 const signed char InpN = 7; // N
4691 const signed char InpUnknown = 8;
4692
4693 static const signed char table[4][9] = {
4694 /* InpLt InpQm InpEm InpDash InpA InpE InpL InpN InpUnknown */
4695 { Lt, -1, -1, -1, -1, -1, -1, -1, -1 }, // Init
4696 { -1, Qm, Em, -1, -1, -1, -1, -1, -1 }, // Lt
4697 { -1, -1, -1, Dash, CA, CE, -1, CN, -1 }, // Em
4698 { -1, -1, -1, -1, -1, -1, CEL, CEN, -1 } // CE
4699 };
4700 signed char state;
4701 signed char input;
4702
4703 if ( d->parseStack==0 || d->parseStack->isEmpty() ) {
4704 state = Init;
4705 } else {
4706 state = d->parseStack->top()->state;
4707 d->parseStack->remove();
4708#if defined(QT_QXML_DEBUG)
4709 qDebug( "QXmlSimpleReader: parseMarkupdecl (cont) in state %d", state );
4710#endif
4711 if ( !d->parseStack->isEmpty() ) {
4712 ParseFunction function = d->parseStack->top()->function;
4713 if ( function == &QXmlSimpleReader::eat_ws ) {
4714 d->parseStack->remove();
4715#if defined(QT_QXML_DEBUG)
4716 qDebug( "QXmlSimpleReader: eat_ws (cont)" );
4717#endif
4718 }
4719 if ( !(this->*function)() ) {
4720 parseFailed( &QXmlSimpleReader::parseMarkupdecl, state );
4721 return FALSE;
4722 }
4723 }
4724 }
4725
4726 for (;;) {
4727 switch ( state ) {
4728 case Qm:
4729 if ( contentHnd ) {
4730 if ( !contentHnd->processingInstruction(name(),string()) ) {
4731 reportParseError( contentHnd->errorString() );
4732 return FALSE;
4733 }
4734 }
4735 return TRUE;
4736 case Dash:
4737 if ( lexicalHnd ) {
4738 if ( !lexicalHnd->comment( string() ) ) {
4739 reportParseError( lexicalHnd->errorString() );
4740 return FALSE;
4741 }
4742 }
4743 return TRUE;
4744 case CA:
4745 return TRUE;
4746 case CEL:
4747 return TRUE;
4748 case CEN:
4749 return TRUE;
4750 case CN:
4751 return TRUE;
4752 case Done:
4753 return TRUE;
4754 case -1:
4755 // Error
4756 reportParseError( XMLERR_LETTEREXPECTED );
4757 return FALSE;
4758 }
4759
4760 if ( atEnd() ) {
4761 unexpectedEof( &QXmlSimpleReader::parseMarkupdecl, state );
4762 return FALSE;
4763 }
4764 if ( c == '<' ) {
4765 input = InpLt;
4766 } else if ( c == '?' ) {
4767 input = InpQm;
4768 } else if ( c == '!' ) {
4769 input = InpEm;
4770 } else if ( c == '-' ) {
4771 input = InpDash;
4772 } else if ( c == 'A' ) {
4773 input = InpA;
4774 } else if ( c == 'E' ) {
4775 input = InpE;
4776 } else if ( c == 'L' ) {
4777 input = InpL;
4778 } else if ( c == 'N' ) {
4779 input = InpN;
4780 } else {
4781 input = InpUnknown;
4782 }
4783 state = table[state][input];
4784
4785 switch ( state ) {
4786 case Lt:
4787 next();
4788 break;
4789 case Em:
4790 next();
4791 break;
4792 case CE:
4793 next();
4794 break;
4795 case Qm:
4796 d->parsePI_xmldecl = FALSE;
4797 if ( !parsePI() ) {
4798 parseFailed( &QXmlSimpleReader::parseMarkupdecl, state );
4799 return FALSE;
4800 }
4801 break;
4802 case Dash:
4803 if ( !parseComment() ) {
4804 parseFailed( &QXmlSimpleReader::parseMarkupdecl, state );
4805 return FALSE;
4806 }
4807 break;
4808 case CA:
4809 if ( !parseAttlistDecl() ) {
4810 parseFailed( &QXmlSimpleReader::parseMarkupdecl, state );
4811 return FALSE;
4812 }
4813 break;
4814 case CEL:
4815 if ( !parseElementDecl() ) {
4816 parseFailed( &QXmlSimpleReader::parseMarkupdecl, state );
4817 return FALSE;
4818 }
4819 break;
4820 case CEN:
4821 if ( !parseEntityDecl() ) {
4822 parseFailed( &QXmlSimpleReader::parseMarkupdecl, state );
4823 return FALSE;
4824 }
4825 break;
4826 case CN:
4827 if ( !parseNotationDecl() ) {
4828 parseFailed( &QXmlSimpleReader::parseMarkupdecl, state );
4829 return FALSE;
4830 }
4831 break;
4832 }
4833 }
4834}
4835
4836/*
4837 Parse a PEReference [69]
4838*/
4839bool QXmlSimpleReader::parsePEReference()
4840{
4841 const signed char Init = 0;
4842 const signed char Next = 1;
4843 const signed char Name = 2;
4844 const signed char NameR = 3; // same as Name, but already reported
4845 const signed char Done = 4;
4846
4847 const signed char InpSemi = 0; // ;
4848 const signed char InpPer = 1; // %
4849 const signed char InpUnknown = 2;
4850
4851 static const signed char table[4][3] = {
4852 /* InpSemi InpPer InpUnknown */
4853 { -1, Next, -1 }, // Init
4854 { -1, -1, Name }, // Next
4855 { Done, -1, -1 }, // Name
4856 { Done, -1, -1 } // NameR
4857 };
4858 signed char state;
4859 signed char input;
4860
4861 if ( d->parseStack==0 || d->parseStack->isEmpty() ) {
4862 state = Init;
4863 } else {
4864 state = d->parseStack->top()->state;
4865 d->parseStack->remove();
4866#if defined(QT_QXML_DEBUG)
4867 qDebug( "QXmlSimpleReader: parsePEReference (cont) in state %d", state );
4868#endif
4869 if ( !d->parseStack->isEmpty() ) {
4870 ParseFunction function = d->parseStack->top()->function;
4871 if ( function == &QXmlSimpleReader::eat_ws ) {
4872 d->parseStack->remove();
4873#if defined(QT_QXML_DEBUG)
4874 qDebug( "QXmlSimpleReader: eat_ws (cont)" );
4875#endif
4876 }
4877 if ( !(this->*function)() ) {
4878 parseFailed( &QXmlSimpleReader::parsePEReference, state );
4879 return FALSE;
4880 }
4881 }
4882 }
4883
4884 for (;;) {
4885 switch ( state ) {
4886 case Name:
4887 {
4888 bool skipIt = TRUE;
4889 QString xmlRefString;
4890
4891 QMap<QString,QString>::Iterator it;
4892 it = d->parameterEntities.find( ref() );
4893 if ( it != d->parameterEntities.end() ) {
4894 skipIt = FALSE;
4895 xmlRefString = it.data();
4896 } else if ( entityRes ) {
4897 QMap<QString,QXmlSimpleReaderPrivate::ExternParameterEntity>::Iterator it2;
4898 it2 = d->externParameterEntities.find( ref() );
4899 QXmlInputSource *ret = 0;
4900 if ( it2 != d->externParameterEntities.end() ) {
4901 if ( !entityRes->resolveEntity( it2.data().publicId, it2.data().systemId, ret ) ) {
4902 delete ret;
4903 reportParseError( entityRes->errorString() );
4904 return FALSE;
4905 }
4906 if ( ret ) {
4907 xmlRefString = ret->data();
4908 delete ret;
4909 if ( !stripTextDecl( xmlRefString ) ) {
4910 reportParseError( XMLERR_ERRORINTEXTDECL );
4911 return FALSE;
4912 }
4913 skipIt = FALSE;
4914 }
4915 }
4916 }
4917
4918 if ( skipIt ) {
4919 if ( contentHnd ) {
4920 if ( !contentHnd->skippedEntity( QString("%") + ref() ) ) {
4921 reportParseError( contentHnd->errorString() );
4922 return FALSE;
4923 }
4924 }
4925 } else {
4926 if ( d->parsePEReference_context == InEntityValue ) {
4927 // Included in literal
4928 if ( !insertXmlRef( xmlRefString, ref(), TRUE ) )
4929 return FALSE;
4930 } else if ( d->parsePEReference_context == InDTD ) {
4931 // Included as PE
4932 if ( !insertXmlRef( QString(" ")+xmlRefString+QString(" "), ref(), FALSE ) )
4933 return FALSE;
4934 }
4935 }
4936 }
4937 state = NameR;
4938 break;
4939 case Done:
4940 return TRUE;
4941 case -1:
4942 // Error
4943 reportParseError( XMLERR_LETTEREXPECTED );
4944 return FALSE;
4945 }
4946
4947 if ( atEnd() ) {
4948 unexpectedEof( &QXmlSimpleReader::parsePEReference, state );
4949 return FALSE;
4950 }
4951 if ( c == ';' ) {
4952 input = InpSemi;
4953 } else if ( c == '%' ) {
4954 input = InpPer;
4955 } else {
4956 input = InpUnknown;
4957 }
4958 state = table[state][input];
4959
4960 switch ( state ) {
4961 case Next:
4962 next();
4963 break;
4964 case Name:
4965 case NameR:
4966 d->parseName_useRef = TRUE;
4967 if ( !parseName() ) {
4968 parseFailed( &QXmlSimpleReader::parsePEReference, state );
4969 return FALSE;
4970 }
4971 break;
4972 case Done:
4973 next();
4974 break;
4975 }
4976 }
4977}
4978
4979/*
4980 Parse a AttlistDecl [52].
4981
4982 Precondition: the beginning '<!' is already read and the head
4983 stands on the 'A' of '<!ATTLIST'
4984*/
4985bool QXmlSimpleReader::parseAttlistDecl()
4986{
4987 const signed char Init = 0;
4988 const signed char Attlist = 1; // parse the string "ATTLIST"
4989 const signed char Ws = 2; // whitespace read
4990 const signed char Name = 3; // parse name
4991 const signed char Ws1 = 4; // whitespace read
4992 const signed char Attdef = 5; // parse the AttDef
4993 const signed char Ws2 = 6; // whitespace read
4994 const signed char Atttype = 7; // parse the AttType
4995 const signed char Ws3 = 8; // whitespace read
4996 const signed char DDecH = 9; // DefaultDecl with #
4997 const signed char DefReq = 10; // parse the string "REQUIRED"
4998 const signed char DefImp = 11; // parse the string "IMPLIED"
4999 const signed char DefFix = 12; // parse the string "FIXED"
5000 const signed char Attval = 13; // parse the AttValue
5001 const signed char Ws4 = 14; // whitespace read
5002 const signed char Done = 15;
5003
5004 const signed char InpWs = 0; // white space
5005 const signed char InpGt = 1; // >
5006 const signed char InpHash = 2; // #
5007 const signed char InpA = 3; // A
5008 const signed char InpI = 4; // I
5009 const signed char InpF = 5; // F
5010 const signed char InpR = 6; // R
5011 const signed char InpUnknown = 7;
5012
5013 static const signed char table[15][8] = {
5014 /* InpWs InpGt InpHash InpA InpI InpF InpR InpUnknown */
5015 { -1, -1, -1, Attlist, -1, -1, -1, -1 }, // Init
5016 { Ws, -1, -1, -1, -1, -1, -1, -1 }, // Attlist
5017 { -1, -1, -1, Name, Name, Name, Name, Name }, // Ws
5018 { Ws1, Done, Attdef, Attdef, Attdef, Attdef, Attdef, Attdef }, // Name
5019 { -1, Done, Attdef, Attdef, Attdef, Attdef, Attdef, Attdef }, // Ws1
5020 { Ws2, -1, -1, -1, -1, -1, -1, -1 }, // Attdef
5021 { -1, Atttype, Atttype, Atttype, Atttype, Atttype, Atttype, Atttype }, // Ws2
5022 { Ws3, -1, -1, -1, -1, -1, -1, -1 }, // Attype
5023 { -1, Attval, DDecH, Attval, Attval, Attval, Attval, Attval }, // Ws3
5024 { -1, -1, -1, -1, DefImp, DefFix, DefReq, -1 }, // DDecH
5025 { Ws4, Ws4, -1, -1, -1, -1, -1, -1 }, // DefReq
5026 { Ws4, Ws4, -1, -1, -1, -1, -1, -1 }, // DefImp
5027 { Ws3, -1, -1, -1, -1, -1, -1, -1 }, // DefFix
5028 { Ws4, Ws4, -1, -1, -1, -1, -1, -1 }, // Attval
5029 { -1, Done, Attdef, Attdef, Attdef, Attdef, Attdef, Attdef } // Ws4
5030 };
5031 signed char state;
5032 signed char input;
5033
5034 if ( d->parseStack==0 || d->parseStack->isEmpty() ) {
5035 state = Init;
5036 } else {
5037 state = d->parseStack->top()->state;
5038 d->parseStack->remove();
5039#if defined(QT_QXML_DEBUG)
5040 qDebug( "QXmlSimpleReader: parseAttlistDecl (cont) in state %d", state );
5041#endif
5042 if ( !d->parseStack->isEmpty() ) {
5043 ParseFunction function = d->parseStack->top()->function;
5044 if ( function == &QXmlSimpleReader::eat_ws ) {
5045 d->parseStack->remove();
5046#if defined(QT_QXML_DEBUG)
5047 qDebug( "QXmlSimpleReader: eat_ws (cont)" );
5048#endif
5049 }
5050 if ( !(this->*function)() ) {
5051 parseFailed( &QXmlSimpleReader::parseAttlistDecl, state );
5052 return FALSE;
5053 }
5054 }
5055 }
5056
5057 for (;;) {
5058 switch ( state ) {
5059 case Name:
5060 d->attDeclEName = name();
5061 break;
5062 case Attdef:
5063 d->attDeclAName = name();
5064 break;
5065 case Done:
5066 return TRUE;
5067 case -1:
5068 // Error
5069 reportParseError( XMLERR_LETTEREXPECTED );
5070 return FALSE;
5071 }
5072
5073 if ( atEnd() ) {
5074 unexpectedEof( &QXmlSimpleReader::parseAttlistDecl, state );
5075 return FALSE;
5076 }
5077 if ( is_S(c) ) {
5078 input = InpWs;
5079 } else if ( c == '>' ) {
5080 input = InpGt;
5081 } else if ( c == '#' ) {
5082 input = InpHash;
5083 } else if ( c == 'A' ) {
5084 input = InpA;
5085 } else if ( c == 'I' ) {
5086 input = InpI;
5087 } else if ( c == 'F' ) {
5088 input = InpF;
5089 } else if ( c == 'R' ) {
5090 input = InpR;
5091 } else {
5092 input = InpUnknown;
5093 }
5094 state = table[state][input];
5095
5096 switch ( state ) {
5097 case Attlist:
5098 d->parseString_s = "ATTLIST";
5099 if ( !parseString() ) {
5100 parseFailed( &QXmlSimpleReader::parseAttlistDecl, state );
5101 return FALSE;
5102 }
5103 break;
5104 case Ws:
5105 case Ws1:
5106 case Ws2:
5107 case Ws3:
5108 if ( !eat_ws() ) {
5109 parseFailed( &QXmlSimpleReader::parseAttlistDecl, state );
5110 return FALSE;
5111 }
5112 break;
5113 case Name:
5114 d->parseName_useRef = FALSE;
5115 if ( !parseName() ) {
5116 parseFailed( &QXmlSimpleReader::parseAttlistDecl, state );
5117 return FALSE;
5118 }
5119 break;
5120 case Attdef:
5121 d->parseName_useRef = FALSE;
5122 if ( !parseName() ) {
5123 parseFailed( &QXmlSimpleReader::parseAttlistDecl, state );
5124 return FALSE;
5125 }
5126 break;
5127 case Atttype:
5128 if ( !parseAttType() ) {
5129 parseFailed( &QXmlSimpleReader::parseAttlistDecl, state );
5130 return FALSE;
5131 }
5132 break;
5133 case DDecH:
5134 next();
5135 break;
5136 case DefReq:
5137 d->parseString_s = "REQUIRED";
5138 if ( !parseString() ) {
5139 parseFailed( &QXmlSimpleReader::parseAttlistDecl, state );
5140 return FALSE;
5141 }
5142 break;
5143 case DefImp:
5144 d->parseString_s = "IMPLIED";
5145 if ( !parseString() ) {
5146 parseFailed( &QXmlSimpleReader::parseAttlistDecl, state );
5147 return FALSE;
5148 }
5149 break;
5150 case DefFix:
5151 d->parseString_s = "FIXED";
5152 if ( !parseString() ) {
5153 parseFailed( &QXmlSimpleReader::parseAttlistDecl, state );
5154 return FALSE;
5155 }
5156 break;
5157 case Attval:
5158 if ( !parseAttValue() ) {
5159 parseFailed( &QXmlSimpleReader::parseAttlistDecl, state );
5160 return FALSE;
5161 }
5162 break;
5163 case Ws4:
5164 if ( declHnd ) {
5165 // ### not all values are computed yet...
5166 if ( !declHnd->attributeDecl( d->attDeclEName, d->attDeclAName, "", "", "" ) ) {
5167 reportParseError( declHnd->errorString() );
5168 return FALSE;
5169 }
5170 }
5171 if ( !eat_ws() ) {
5172 parseFailed( &QXmlSimpleReader::parseAttlistDecl, state );
5173 return FALSE;
5174 }
5175 break;
5176 case Done:
5177 next();
5178 break;
5179 }
5180 }
5181}
5182
5183/*
5184 Parse a AttType [54]
5185*/
5186bool QXmlSimpleReader::parseAttType()
5187{
5188 const signed char Init = 0;
5189 const signed char ST = 1; // StringType
5190 const signed char TTI = 2; // TokenizedType starting with 'I'
5191 const signed char TTI2 = 3; // TokenizedType helpstate
5192 const signed char TTI3 = 4; // TokenizedType helpstate
5193 const signed char TTE = 5; // TokenizedType starting with 'E'
5194 const signed char TTEY = 6; // TokenizedType starting with 'ENTITY'
5195 const signed char TTEI = 7; // TokenizedType starting with 'ENTITI'
5196 const signed char N = 8; // N read (TokenizedType or Notation)
5197 const signed char TTNM = 9; // TokenizedType starting with 'NM'
5198 const signed char TTNM2 = 10; // TokenizedType helpstate
5199 const signed char NO = 11; // Notation
5200 const signed char NO2 = 12; // Notation helpstate
5201 const signed char NO3 = 13; // Notation helpstate
5202 const signed char NOName = 14; // Notation, read name
5203 const signed char NO4 = 15; // Notation helpstate
5204 const signed char EN = 16; // Enumeration
5205 const signed char ENNmt = 17; // Enumeration, read Nmtoken
5206 const signed char EN2 = 18; // Enumeration helpstate
5207 const signed char ADone = 19; // almost done (make next and accept)
5208 const signed char Done = 20;
5209
5210 const signed char InpWs = 0; // whitespace
5211 const signed char InpOp = 1; // (
5212 const signed char InpCp = 2; // )
5213 const signed char InpPipe = 3; // |
5214 const signed char InpC = 4; // C
5215 const signed char InpE = 5; // E
5216 const signed char InpI = 6; // I
5217 const signed char InpM = 7; // M
5218 const signed char InpN = 8; // N
5219 const signed char InpO = 9; // O
5220 const signed char InpR = 10; // R
5221 const signed char InpS = 11; // S
5222 const signed char InpY = 12; // Y
5223 const signed char InpUnknown = 13;
5224
5225 static const signed char table[19][14] = {
5226 /* InpWs InpOp InpCp InpPipe InpC InpE InpI InpM InpN InpO InpR InpS InpY InpUnknown */
5227 { -1, EN, -1, -1, ST, TTE, TTI, -1, N, -1, -1, -1, -1, -1 }, // Init
5228 { Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done }, // ST
5229 { Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, TTI2, Done, Done, Done }, // TTI
5230 { Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, TTI3, Done, Done }, // TTI2
5231 { Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done }, // TTI3
5232 { -1, -1, -1, -1, -1, -1, TTEI, -1, -1, -1, -1, -1, TTEY, -1 }, // TTE
5233 { Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done }, // TTEY
5234 { Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done }, // TTEI
5235 { -1, -1, -1, -1, -1, -1, -1, TTNM, -1, NO, -1, -1, -1, -1 }, // N
5236 { Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, TTNM2, Done, Done }, // TTNM
5237 { Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done }, // TTNM2
5238 { NO2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, // NO
5239 { -1, NO3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, // NO2
5240 { NOName, NOName, NOName, NOName, NOName, NOName, NOName, NOName, NOName, NOName, NOName, NOName, NOName, NOName }, // NO3
5241 { NO4, -1, ADone, NO3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, // NOName
5242 { -1, -1, ADone, NO3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, // NO4
5243 { -1, -1, ENNmt, -1, ENNmt, ENNmt, ENNmt, ENNmt, ENNmt, ENNmt, ENNmt, ENNmt, ENNmt, ENNmt }, // EN
5244 { EN2, -1, ADone, EN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, // ENNmt
5245 { -1, -1, ADone, EN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } // EN2
5246 };
5247 signed char state;
5248 signed char input;
5249
5250 if ( d->parseStack==0 || d->parseStack->isEmpty() ) {
5251 state = Init;
5252 } else {
5253 state = d->parseStack->top()->state;
5254 d->parseStack->remove();
5255#if defined(QT_QXML_DEBUG)
5256 qDebug( "QXmlSimpleReader: parseAttType (cont) in state %d", state );
5257#endif
5258 if ( !d->parseStack->isEmpty() ) {
5259 ParseFunction function = d->parseStack->top()->function;
5260 if ( function == &QXmlSimpleReader::eat_ws ) {
5261 d->parseStack->remove();
5262#if defined(QT_QXML_DEBUG)
5263 qDebug( "QXmlSimpleReader: eat_ws (cont)" );
5264#endif
5265 }
5266 if ( !(this->*function)() ) {
5267 parseFailed( &QXmlSimpleReader::parseAttType, state );
5268 return FALSE;
5269 }
5270 }
5271 }
5272
5273 for (;;) {
5274 switch ( state ) {
5275 case ADone:
5276 return TRUE;
5277 case Done:
5278 return TRUE;
5279 case -1:
5280 // Error
5281 reportParseError( XMLERR_LETTEREXPECTED );
5282 return FALSE;
5283 }
5284
5285 if ( atEnd() ) {
5286 unexpectedEof( &QXmlSimpleReader::parseAttType, state );
5287 return FALSE;
5288 }
5289 if ( is_S(c) ) {
5290 input = InpWs;
5291 } else if ( c == '(' ) {
5292 input = InpOp;
5293 } else if ( c == ')' ) {
5294 input = InpCp;
5295 } else if ( c == '|' ) {
5296 input = InpPipe;
5297 } else if ( c == 'C' ) {
5298 input = InpC;
5299 } else if ( c == 'E' ) {
5300 input = InpE;
5301 } else if ( c == 'I' ) {
5302 input = InpI;
5303 } else if ( c == 'M' ) {
5304 input = InpM;
5305 } else if ( c == 'N' ) {
5306 input = InpN;
5307 } else if ( c == 'O' ) {
5308 input = InpO;
5309 } else if ( c == 'R' ) {
5310 input = InpR;
5311 } else if ( c == 'S' ) {
5312 input = InpS;
5313 } else if ( c == 'Y' ) {
5314 input = InpY;
5315 } else {
5316 input = InpUnknown;
5317 }
5318 state = table[state][input];
5319
5320 switch ( state ) {
5321 case ST:
5322 d->parseString_s = "CDATA";
5323 if ( !parseString() ) {
5324 parseFailed( &QXmlSimpleReader::parseAttType, state );
5325 return FALSE;
5326 }
5327 break;
5328 case TTI:
5329 d->parseString_s = "ID";
5330 if ( !parseString() ) {
5331 parseFailed( &QXmlSimpleReader::parseAttType, state );
5332 return FALSE;
5333 }
5334 break;
5335 case TTI2:
5336 d->parseString_s = "REF";
5337 if ( !parseString() ) {
5338 parseFailed( &QXmlSimpleReader::parseAttType, state );
5339 return FALSE;
5340 }
5341 break;
5342 case TTI3:
5343 next(); // S
5344 break;
5345 case TTE:
5346 d->parseString_s = "ENTIT";
5347 if ( !parseString() ) {
5348 parseFailed( &QXmlSimpleReader::parseAttType, state );
5349 return FALSE;
5350 }
5351 break;
5352 case TTEY:
5353 next(); // Y
5354 break;
5355 case TTEI:
5356 d->parseString_s = "IES";
5357 if ( !parseString() ) {
5358 parseFailed( &QXmlSimpleReader::parseAttType, state );
5359 return FALSE;
5360 }
5361 break;
5362 case N:
5363 next(); // N
5364 break;
5365 case TTNM:
5366 d->parseString_s = "MTOKEN";
5367 if ( !parseString() ) {
5368 parseFailed( &QXmlSimpleReader::parseAttType, state );
5369 return FALSE;
5370 }
5371 break;
5372 case TTNM2:
5373 next(); // S
5374 break;
5375 case NO:
5376 d->parseString_s = "OTATION";
5377 if ( !parseString() ) {
5378 parseFailed( &QXmlSimpleReader::parseAttType, state );
5379 return FALSE;
5380 }
5381 break;
5382 case NO2:
5383 if ( !eat_ws() ) {
5384 parseFailed( &QXmlSimpleReader::parseAttType, state );
5385 return FALSE;
5386 }
5387 break;
5388 case NO3:
5389 if ( !next_eat_ws() ) {
5390 parseFailed( &QXmlSimpleReader::parseAttType, state );
5391 return FALSE;
5392 }
5393 break;
5394 case NOName:
5395 d->parseName_useRef = FALSE;
5396 if ( !parseName() ) {
5397 parseFailed( &QXmlSimpleReader::parseAttType, state );
5398 return FALSE;
5399 }
5400 break;
5401 case NO4:
5402 if ( !eat_ws() ) {
5403 parseFailed( &QXmlSimpleReader::parseAttType, state );
5404 return FALSE;
5405 }
5406 break;
5407 case EN:
5408 if ( !next_eat_ws() ) {
5409 parseFailed( &QXmlSimpleReader::parseAttType, state );
5410 return FALSE;
5411 }
5412 break;
5413 case ENNmt:
5414 if ( !parseNmtoken() ) {
5415 parseFailed( &QXmlSimpleReader::parseAttType, state );
5416 return FALSE;
5417 }
5418 break;
5419 case EN2:
5420 if ( !eat_ws() ) {
5421 parseFailed( &QXmlSimpleReader::parseAttType, state );
5422 return FALSE;
5423 }
5424 break;
5425 case ADone:
5426 next();
5427 break;
5428 }
5429 }
5430}
5431
5432/*
5433 Parse a AttValue [10]
5434
5435 Precondition: the head stands on the beginning " or '
5436
5437 If this function was successful, the head stands on the first
5438 character after the closing " or ' and the value of the attribute
5439 is in string().
5440*/
5441bool QXmlSimpleReader::parseAttValue()
5442{
5443 const signed char Init = 0;
5444 const signed char Dq = 1; // double quotes were read
5445 const signed char DqRef = 2; // read references in double quotes
5446 const signed char DqC = 3; // signed character read in double quotes
5447 const signed char Sq = 4; // single quotes were read
5448 const signed char SqRef = 5; // read references in single quotes
5449 const signed char SqC = 6; // signed character read in single quotes
5450 const signed char Done = 7;
5451
5452 const signed char InpDq = 0; // "
5453 const signed char InpSq = 1; // '
5454 const signed char InpAmp = 2; // &
5455 const signed char InpLt = 3; // <
5456 const signed char InpUnknown = 4;
5457
5458 static const signed char table[7][5] = {
5459 /* InpDq InpSq InpAmp InpLt InpUnknown */
5460 { Dq, Sq, -1, -1, -1 }, // Init
5461 { Done, DqC, DqRef, -1, DqC }, // Dq
5462 { Done, DqC, DqRef, -1, DqC }, // DqRef
5463 { Done, DqC, DqRef, -1, DqC }, // DqC
5464 { SqC, Done, SqRef, -1, SqC }, // Sq
5465 { SqC, Done, SqRef, -1, SqC }, // SqRef
5466 { SqC, Done, SqRef, -1, SqC } // SqRef
5467 };
5468 signed char state;
5469 signed char input;
5470
5471 if ( d->parseStack==0 || d->parseStack->isEmpty() ) {
5472 state = Init;
5473 } else {
5474 state = d->parseStack->top()->state;
5475 d->parseStack->remove();
5476#if defined(QT_QXML_DEBUG)
5477 qDebug( "QXmlSimpleReader: parseAttValue (cont) in state %d", state );
5478#endif
5479 if ( !d->parseStack->isEmpty() ) {
5480 ParseFunction function = d->parseStack->top()->function;
5481 if ( function == &QXmlSimpleReader::eat_ws ) {
5482 d->parseStack->remove();
5483#if defined(QT_QXML_DEBUG)
5484 qDebug( "QXmlSimpleReader: eat_ws (cont)" );
5485#endif
5486 }
5487 if ( !(this->*function)() ) {
5488 parseFailed( &QXmlSimpleReader::parseAttValue, state );
5489 return FALSE;
5490 }
5491 }
5492 }
5493
5494 for (;;) {
5495 switch ( state ) {
5496 case Done:
5497 return TRUE;
5498 case -1:
5499 // Error
5500 reportParseError( XMLERR_UNEXPECTEDCHARACTER );
5501 return FALSE;
5502 }
5503
5504 if ( atEnd() ) {
5505 unexpectedEof( &QXmlSimpleReader::parseAttValue, state );
5506 return FALSE;
5507 }
5508 if ( c == '"' ) {
5509 input = InpDq;
5510 } else if ( c == '\'' ) {
5511 input = InpSq;
5512 } else if ( c == '&' ) {
5513 input = InpAmp;
5514 } else if ( c == '<' ) {
5515 input = InpLt;
5516 } else {
5517 input = InpUnknown;
5518 }
5519 state = table[state][input];
5520
5521 switch ( state ) {
5522 case Dq:
5523 case Sq:
5524 stringClear();
5525 next();
5526 break;
5527 case DqRef:
5528 case SqRef:
5529 d->parseReference_context = InAttributeValue;
5530 if ( !parseReference() ) {
5531 parseFailed( &QXmlSimpleReader::parseAttValue, state );
5532 return FALSE;
5533 }
5534 break;
5535 case DqC:
5536 case SqC:
5537 stringAddC();
5538 next();
5539 break;
5540 case Done:
5541 next();
5542 break;
5543 }
5544 }
5545}
5546
5547/*
5548 Parse a elementdecl [45].
5549
5550 Precondition: the beginning '<!E' is already read and the head
5551 stands on the 'L' of '<!ELEMENT'
5552*/
5553bool QXmlSimpleReader::parseElementDecl()
5554{
5555 const signed char Init = 0;
5556 const signed char Elem = 1; // parse the beginning string
5557 const signed char Ws1 = 2; // whitespace required
5558 const signed char Nam = 3; // parse Name
5559 const signed char Ws2 = 4; // whitespace required
5560 const signed char Empty = 5; // read EMPTY
5561 const signed char Any = 6; // read ANY
5562 const signed char Cont = 7; // read contentspec (except ANY or EMPTY)
5563 const signed char Mix = 8; // read Mixed
5564 const signed char Mix2 = 9; //
5565 const signed char Mix3 = 10; //
5566 const signed char MixN1 = 11; //
5567 const signed char MixN2 = 12; //
5568 const signed char MixN3 = 13; //
5569 const signed char MixN4 = 14; //
5570 const signed char Cp = 15; // parse cp
5571 const signed char Cp2 = 16; //
5572 const signed char WsD = 17; // eat whitespace before Done
5573 const signed char Done = 18;
5574
5575 const signed char InpWs = 0;
5576 const signed char InpGt = 1; // >
5577 const signed char InpPipe = 2; // |
5578 const signed char InpOp = 3; // (
5579 const signed char InpCp = 4; // )
5580 const signed char InpHash = 5; // #
5581 const signed char InpQm = 6; // ?
5582 const signed char InpAst = 7; // *
5583 const signed char InpPlus = 8; // +
5584 const signed char InpA = 9; // A
5585 const signed char InpE = 10; // E
5586 const signed char InpL = 11; // L
5587 const signed char InpUnknown = 12;
5588
5589 static const signed char table[18][13] = {
5590 /* InpWs InpGt InpPipe InpOp InpCp InpHash InpQm InpAst InpPlus InpA InpE InpL InpUnknown */
5591 { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, Elem, -1 }, // Init
5592 { Ws1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, // Elem
5593 { -1, -1, -1, -1, -1, -1, -1, -1, -1, Nam, Nam, Nam, Nam }, // Ws1
5594 { Ws2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, // Nam
5595 { -1, -1, -1, Cont, -1, -1, -1, -1, -1, Any, Empty, -1, -1 }, // Ws2
5596 { WsD, Done, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, // Empty
5597 { WsD, Done, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, // Any
5598 { -1, -1, -1, Cp, Cp, Mix, -1, -1, -1, Cp, Cp, Cp, Cp }, // Cont
5599 { Mix2, -1, MixN1, -1, Mix3, -1, -1, -1, -1, -1, -1, -1, -1 }, // Mix
5600 { -1, -1, MixN1, -1, Mix3, -1, -1, -1, -1, -1, -1, -1, -1 }, // Mix2
5601 { WsD, Done, -1, -1, -1, -1, -1, WsD, -1, -1, -1, -1, -1 }, // Mix3
5602 { -1, -1, -1, -1, -1, -1, -1, -1, -1, MixN2, MixN2, MixN2, MixN2 }, // MixN1
5603 { MixN3, -1, MixN1, -1, MixN4, -1, -1, -1, -1, -1, -1, -1, -1 }, // MixN2
5604 { -1, -1, MixN1, -1, MixN4, -1, -1, -1, -1, -1, -1, -1, -1 }, // MixN3
5605 { -1, -1, -1, -1, -1, -1, -1, WsD, -1, -1, -1, -1, -1 }, // MixN4
5606 { WsD, Done, -1, -1, -1, -1, Cp2, Cp2, Cp2, -1, -1, -1, -1 }, // Cp
5607 { WsD, Done, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, // Cp2
5608 { -1, Done, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } // WsD
5609 };
5610 signed char state;
5611 signed char input;
5612
5613 if ( d->parseStack==0 || d->parseStack->isEmpty() ) {
5614 state = Init;
5615 } else {
5616 state = d->parseStack->top()->state;
5617 d->parseStack->remove();
5618#if defined(QT_QXML_DEBUG)
5619 qDebug( "QXmlSimpleReader: parseElementDecl (cont) in state %d", state );
5620#endif
5621 if ( !d->parseStack->isEmpty() ) {
5622 ParseFunction function = d->parseStack->top()->function;
5623 if ( function == &QXmlSimpleReader::eat_ws ) {
5624 d->parseStack->remove();
5625#if defined(QT_QXML_DEBUG)
5626 qDebug( "QXmlSimpleReader: eat_ws (cont)" );
5627#endif
5628 }
5629 if ( !(this->*function)() ) {
5630 parseFailed( &QXmlSimpleReader::parseElementDecl, state );
5631 return FALSE;
5632 }
5633 }
5634 }
5635
5636 for (;;) {
5637 switch ( state ) {
5638 case Done:
5639 return TRUE;
5640 case -1:
5641 reportParseError( XMLERR_UNEXPECTEDCHARACTER );
5642 return FALSE;
5643 }
5644
5645 if ( atEnd() ) {
5646 unexpectedEof( &QXmlSimpleReader::parseElementDecl, state );
5647 return FALSE;
5648 }
5649 if ( is_S(c) ) {
5650 input = InpWs;
5651 } else if ( c == '>' ) {
5652 input = InpGt;
5653 } else if ( c == '|' ) {
5654 input = InpPipe;
5655 } else if ( c == '(' ) {
5656 input = InpOp;
5657 } else if ( c == ')' ) {
5658 input = InpCp;
5659 } else if ( c == '#' ) {
5660 input = InpHash;
5661 } else if ( c == '?' ) {
5662 input = InpQm;
5663 } else if ( c == '*' ) {
5664 input = InpAst;
5665 } else if ( c == '+' ) {
5666 input = InpPlus;
5667 } else if ( c == 'A' ) {
5668 input = InpA;
5669 } else if ( c == 'E' ) {
5670 input = InpE;
5671 } else if ( c == 'L' ) {
5672 input = InpL;
5673 } else {
5674 input = InpUnknown;
5675 }
5676 state = table[state][input];
5677
5678 switch ( state ) {
5679 case Elem:
5680 d->parseString_s = "LEMENT";
5681 if ( !parseString() ) {
5682 parseFailed( &QXmlSimpleReader::parseElementDecl, state );
5683 return FALSE;
5684 }
5685 break;
5686 case Ws1:
5687 if ( !eat_ws() ) {
5688 parseFailed( &QXmlSimpleReader::parseElementDecl, state );
5689 return FALSE;
5690 }
5691 break;
5692 case Nam:
5693 d->parseName_useRef = FALSE;
5694 if ( !parseName() ) {
5695 parseFailed( &QXmlSimpleReader::parseElementDecl, state );
5696 return FALSE;
5697 }
5698 break;
5699 case Ws2:
5700 if ( !eat_ws() ) {
5701 parseFailed( &QXmlSimpleReader::parseElementDecl, state );
5702 return FALSE;
5703 }
5704 break;
5705 case Empty:
5706 d->parseString_s = "EMPTY";
5707 if ( !parseString() ) {
5708 parseFailed( &QXmlSimpleReader::parseElementDecl, state );
5709 return FALSE;
5710 }
5711 break;
5712 case Any:
5713 d->parseString_s = "ANY";
5714 if ( !parseString() ) {
5715 parseFailed( &QXmlSimpleReader::parseElementDecl, state );
5716 return FALSE;
5717 }
5718 break;
5719 case Cont:
5720 if ( !next_eat_ws() ) {
5721 parseFailed( &QXmlSimpleReader::parseElementDecl, state );
5722 return FALSE;
5723 }
5724 break;
5725 case Mix:
5726 d->parseString_s = "#PCDATA";
5727 if ( !parseString() ) {
5728 parseFailed( &QXmlSimpleReader::parseElementDecl, state );
5729 return FALSE;
5730 }
5731 break;
5732 case Mix2:
5733 if ( !eat_ws() ) {
5734 parseFailed( &QXmlSimpleReader::parseElementDecl, state );
5735 return FALSE;
5736 }
5737 break;
5738 case Mix3:
5739 next();
5740 break;
5741 case MixN1:
5742 if ( !next_eat_ws() ) {
5743 parseFailed( &QXmlSimpleReader::parseElementDecl, state );
5744 return FALSE;
5745 }
5746 break;
5747 case MixN2:
5748 d->parseName_useRef = FALSE;
5749 if ( !parseName() ) {
5750 parseFailed( &QXmlSimpleReader::parseElementDecl, state );
5751 return FALSE;
5752 }
5753 break;
5754 case MixN3:
5755 if ( !eat_ws() ) {
5756 parseFailed( &QXmlSimpleReader::parseElementDecl, state );
5757 return FALSE;
5758 }
5759 break;
5760 case MixN4:
5761 next();
5762 break;
5763 case Cp:
5764 if ( !parseChoiceSeq() ) {
5765 parseFailed( &QXmlSimpleReader::parseElementDecl, state );
5766 return FALSE;
5767 }
5768 break;
5769 case Cp2:
5770 next();
5771 break;
5772 case WsD:
5773 if ( !next_eat_ws() ) {
5774 parseFailed( &QXmlSimpleReader::parseElementDecl, state );
5775 return FALSE;
5776 }
5777 break;
5778 case Done:
5779 next();
5780 break;
5781 }
5782 }
5783}
5784
5785/*
5786 Parse a NotationDecl [82].
5787
5788 Precondition: the beginning '<!' is already read and the head
5789 stands on the 'N' of '<!NOTATION'
5790*/
5791bool QXmlSimpleReader::parseNotationDecl()
5792{
5793 const signed char Init = 0;
5794 const signed char Not = 1; // read NOTATION
5795 const signed char Ws1 = 2; // eat whitespaces
5796 const signed char Nam = 3; // read Name
5797 const signed char Ws2 = 4; // eat whitespaces
5798 const signed char ExtID = 5; // parse ExternalID
5799 const signed char ExtIDR = 6; // same as ExtID, but already reported
5800 const signed char Ws3 = 7; // eat whitespaces
5801 const signed char Done = 8;
5802
5803 const signed char InpWs = 0;
5804 const signed char InpGt = 1; // >
5805 const signed char InpN = 2; // N
5806 const signed char InpUnknown = 3;
5807
5808 static const signed char table[8][4] = {
5809 /* InpWs InpGt InpN InpUnknown */
5810 { -1, -1, Not, -1 }, // Init
5811 { Ws1, -1, -1, -1 }, // Not
5812 { -1, -1, Nam, Nam }, // Ws1
5813 { Ws2, Done, -1, -1 }, // Nam
5814 { -1, Done, ExtID, ExtID }, // Ws2
5815 { Ws3, Done, -1, -1 }, // ExtID
5816 { Ws3, Done, -1, -1 }, // ExtIDR
5817 { -1, Done, -1, -1 } // Ws3
5818 };
5819 signed char state;
5820 signed char input;
5821
5822 if ( d->parseStack==0 || d->parseStack->isEmpty() ) {
5823 state = Init;
5824 } else {
5825 state = d->parseStack->top()->state;
5826 d->parseStack->remove();
5827#if defined(QT_QXML_DEBUG)
5828 qDebug( "QXmlSimpleReader: parseNotationDecl (cont) in state %d", state );
5829#endif
5830 if ( !d->parseStack->isEmpty() ) {
5831 ParseFunction function = d->parseStack->top()->function;
5832 if ( function == &QXmlSimpleReader::eat_ws ) {
5833 d->parseStack->remove();
5834#if defined(QT_QXML_DEBUG)
5835 qDebug( "QXmlSimpleReader: eat_ws (cont)" );
5836#endif
5837 }
5838 if ( !(this->*function)() ) {
5839 parseFailed( &QXmlSimpleReader::parseNotationDecl, state );
5840 return FALSE;
5841 }
5842 }
5843 }
5844
5845 for (;;) {
5846 switch ( state ) {
5847 case ExtID:
5848 // call the handler
5849 if ( dtdHnd ) {
5850 if ( !dtdHnd->notationDecl( name(), d->publicId, d->systemId ) ) {
5851 reportParseError( dtdHnd->errorString() );
5852 return FALSE;
5853 }
5854 }
5855 state = ExtIDR;
5856 break;
5857 case Done:
5858 return TRUE;
5859 case -1:
5860 // Error
5861 reportParseError( XMLERR_UNEXPECTEDCHARACTER );
5862 return FALSE;
5863 }
5864
5865 if ( atEnd() ) {
5866 unexpectedEof( &QXmlSimpleReader::parseNotationDecl, state );
5867 return FALSE;
5868 }
5869 if ( is_S(c) ) {
5870 input = InpWs;
5871 } else if ( c == '>' ) {
5872 input = InpGt;
5873 } else if ( c == 'N' ) {
5874 input = InpN;
5875 } else {
5876 input = InpUnknown;
5877 }
5878 state = table[state][input];
5879
5880 switch ( state ) {
5881 case Not:
5882 d->parseString_s = "NOTATION";
5883 if ( !parseString() ) {
5884 parseFailed( &QXmlSimpleReader::parseNotationDecl, state );
5885 return FALSE;
5886 }
5887 break;
5888 case Ws1:
5889 if ( !eat_ws() ) {
5890 parseFailed( &QXmlSimpleReader::parseNotationDecl, state );
5891 return FALSE;
5892 }
5893 break;
5894 case Nam:
5895 d->parseName_useRef = FALSE;
5896 if ( !parseName() ) {
5897 parseFailed( &QXmlSimpleReader::parseNotationDecl, state );
5898 return FALSE;
5899 }
5900 break;
5901 case Ws2:
5902 if ( !eat_ws() ) {
5903 parseFailed( &QXmlSimpleReader::parseNotationDecl, state );
5904 return FALSE;
5905 }
5906 break;
5907 case ExtID:
5908 case ExtIDR:
5909 d->parseExternalID_allowPublicID = TRUE;
5910 if ( !parseExternalID() ) {
5911 parseFailed( &QXmlSimpleReader::parseNotationDecl, state );
5912 return FALSE;
5913 }
5914 break;
5915 case Ws3:
5916 if ( !eat_ws() ) {
5917 parseFailed( &QXmlSimpleReader::parseNotationDecl, state );
5918 return FALSE;
5919 }
5920 break;
5921 case Done:
5922 next();
5923 break;
5924 }
5925 }
5926}
5927
5928/*
5929 Parse choice [49] or seq [50].
5930
5931 Precondition: the beginning '('S? is already read and the head
5932 stands on the first non-whitespace character after it.
5933*/
5934bool QXmlSimpleReader::parseChoiceSeq()
5935{
5936 const signed char Init = 0;
5937 const signed char Ws1 = 1; // eat whitespace
5938 const signed char CS = 2; // choice or set
5939 const signed char Ws2 = 3; // eat whitespace
5940 const signed char More = 4; // more cp to read
5941 const signed char Name = 5; // read name
5942 const signed char Done = 6; //
5943
5944 const signed char InpWs = 0; // S
5945 const signed char InpOp = 1; // (
5946 const signed char InpCp = 2; // )
5947 const signed char InpQm = 3; // ?
5948 const signed char InpAst = 4; // *
5949 const signed char InpPlus = 5; // +
5950 const signed char InpPipe = 6; // |
5951 const signed char InpComm = 7; // ,
5952 const signed char InpUnknown = 8;
5953
5954 static const signed char table[6][9] = {
5955 /* InpWs InpOp InpCp InpQm InpAst InpPlus InpPipe InpComm InpUnknown */
5956 { -1, Ws1, -1, -1, -1, -1, -1, -1, Name }, // Init
5957 { -1, CS, -1, -1, -1, -1, -1, -1, CS }, // Ws1
5958 { Ws2, -1, Done, Ws2, Ws2, Ws2, More, More, -1 }, // CS
5959 { -1, -1, Done, -1, -1, -1, More, More, -1 }, // Ws2
5960 { -1, Ws1, -1, -1, -1, -1, -1, -1, Name }, // More (same as Init)
5961 { Ws2, -1, Done, Ws2, Ws2, Ws2, More, More, -1 } // Name (same as CS)
5962 };
5963 signed char state;
5964 signed char input;
5965
5966 if ( d->parseStack==0 || d->parseStack->isEmpty() ) {
5967 state = Init;
5968 } else {
5969 state = d->parseStack->top()->state;
5970 d->parseStack->remove();
5971#if defined(QT_QXML_DEBUG)
5972 qDebug( "QXmlSimpleReader: parseChoiceSeq (cont) in state %d", state );
5973#endif
5974 if ( !d->parseStack->isEmpty() ) {
5975 ParseFunction function = d->parseStack->top()->function;
5976 if ( function == &QXmlSimpleReader::eat_ws ) {
5977 d->parseStack->remove();
5978#if defined(QT_QXML_DEBUG)
5979 qDebug( "QXmlSimpleReader: eat_ws (cont)" );
5980#endif
5981 }
5982 if ( !(this->*function)() ) {
5983 parseFailed( &QXmlSimpleReader::parseChoiceSeq, state );
5984 return FALSE;
5985 }
5986 }
5987 }
5988
5989 for (;;) {
5990 switch ( state ) {
5991 case Done:
5992 return TRUE;
5993 case -1:
5994 // Error
5995 reportParseError( XMLERR_UNEXPECTEDCHARACTER );
5996 return FALSE;
5997 }
5998
5999 if ( atEnd() ) {
6000 unexpectedEof( &QXmlSimpleReader::parseChoiceSeq, state );
6001 return FALSE;
6002 }
6003 if ( is_S(c) ) {
6004 input = InpWs;
6005 } else if ( c == '(' ) {
6006 input = InpOp;
6007 } else if ( c == ')' ) {
6008 input = InpCp;
6009 } else if ( c == '?' ) {
6010 input = InpQm;
6011 } else if ( c == '*' ) {
6012 input = InpAst;
6013 } else if ( c == '+' ) {
6014 input = InpPlus;
6015 } else if ( c == '|' ) {
6016 input = InpPipe;
6017 } else if ( c == ',' ) {
6018 input = InpComm;
6019 } else {
6020 input = InpUnknown;
6021 }
6022 state = table[state][input];
6023
6024 switch ( state ) {
6025 case Ws1:
6026 if ( !next_eat_ws() ) {
6027 parseFailed( &QXmlSimpleReader::parseChoiceSeq, state );
6028 return FALSE;
6029 }
6030 break;
6031 case CS:
6032 if ( !parseChoiceSeq() ) {
6033 parseFailed( &QXmlSimpleReader::parseChoiceSeq, state );
6034 return FALSE;
6035 }
6036 break;
6037 case Ws2:
6038 if ( !next_eat_ws() ) {
6039 parseFailed( &QXmlSimpleReader::parseChoiceSeq, state );
6040 return FALSE;
6041 }
6042 break;
6043 case More:
6044 if ( !next_eat_ws() ) {
6045 parseFailed( &QXmlSimpleReader::parseChoiceSeq, state );
6046 return FALSE;
6047 }
6048 break;
6049 case Name:
6050 d->parseName_useRef = FALSE;
6051 if ( !parseName() ) {
6052 parseFailed( &QXmlSimpleReader::parseChoiceSeq, state );
6053 return FALSE;
6054 }
6055 break;
6056 case Done:
6057 next();
6058 break;
6059 }
6060 }
6061}
6062
6063/*
6064 Parse a EntityDecl [70].
6065
6066 Precondition: the beginning '<!E' is already read and the head
6067 stand on the 'N' of '<!ENTITY'
6068*/
6069bool QXmlSimpleReader::parseEntityDecl()
6070{
6071 const signed char Init = 0;
6072 const signed char Ent = 1; // parse "ENTITY"
6073 const signed char Ws1 = 2; // white space read
6074 const signed char Name = 3; // parse name
6075 const signed char Ws2 = 4; // white space read
6076 const signed char EValue = 5; // parse entity value
6077 const signed char EValueR = 6; // same as EValue, but already reported
6078 const signed char ExtID = 7; // parse ExternalID
6079 const signed char Ws3 = 8; // white space read
6080 const signed char Ndata = 9; // parse "NDATA"
6081 const signed char Ws4 = 10; // white space read
6082 const signed char NNam = 11; // parse name
6083 const signed char NNamR = 12; // same as NNam, but already reported
6084 const signed char PEDec = 13; // parse PEDecl
6085 const signed char Ws6 = 14; // white space read
6086 const signed char PENam = 15; // parse name
6087 const signed char Ws7 = 16; // white space read
6088 const signed char PEVal = 17; // parse entity value
6089 const signed char PEValR = 18; // same as PEVal, but already reported
6090 const signed char PEEID = 19; // parse ExternalID
6091 const signed char PEEIDR = 20; // same as PEEID, but already reported
6092 const signed char WsE = 21; // white space read
6093 const signed char Done = 22;
6094 const signed char EDDone = 23; // done, but also report an external, unparsed entity decl
6095
6096 const signed char InpWs = 0; // white space
6097 const signed char InpPer = 1; // %
6098 const signed char InpQuot = 2; // " or '
6099 const signed char InpGt = 3; // >
6100 const signed char InpN = 4; // N
6101 const signed char InpUnknown = 5;
6102
6103 static const signed char table[22][6] = {
6104 /* InpWs InpPer InpQuot InpGt InpN InpUnknown */
6105 { -1, -1, -1, -1, Ent, -1 }, // Init
6106 { Ws1, -1, -1, -1, -1, -1 }, // Ent
6107 { -1, PEDec, -1, -1, Name, Name }, // Ws1
6108 { Ws2, -1, -1, -1, -1, -1 }, // Name
6109 { -1, -1, EValue, -1, -1, ExtID }, // Ws2
6110 { WsE, -1, -1, Done, -1, -1 }, // EValue
6111 { WsE, -1, -1, Done, -1, -1 }, // EValueR
6112 { Ws3, -1, -1, EDDone,-1, -1 }, // ExtID
6113 { -1, -1, -1, EDDone,Ndata, -1 }, // Ws3
6114 { Ws4, -1, -1, -1, -1, -1 }, // Ndata
6115 { -1, -1, -1, -1, NNam, NNam }, // Ws4
6116 { WsE, -1, -1, Done, -1, -1 }, // NNam
6117 { WsE, -1, -1, Done, -1, -1 }, // NNamR
6118 { Ws6, -1, -1, -1, -1, -1 }, // PEDec
6119 { -1, -1, -1, -1, PENam, PENam }, // Ws6
6120 { Ws7, -1, -1, -1, -1, -1 }, // PENam
6121 { -1, -1, PEVal, -1, -1, PEEID }, // Ws7
6122 { WsE, -1, -1, Done, -1, -1 }, // PEVal
6123 { WsE, -1, -1, Done, -1, -1 }, // PEValR
6124 { WsE, -1, -1, Done, -1, -1 }, // PEEID
6125 { WsE, -1, -1, Done, -1, -1 }, // PEEIDR
6126 { -1, -1, -1, Done, -1, -1 } // WsE
6127 };
6128 signed char state;
6129 signed char input;
6130
6131 if ( d->parseStack==0 || d->parseStack->isEmpty() ) {
6132 state = Init;
6133 } else {
6134 state = d->parseStack->top()->state;
6135 d->parseStack->remove();
6136#if defined(QT_QXML_DEBUG)
6137 qDebug( "QXmlSimpleReader: parseEntityDecl (cont) in state %d", state );
6138#endif
6139 if ( !d->parseStack->isEmpty() ) {
6140 ParseFunction function = d->parseStack->top()->function;
6141 if ( function == &QXmlSimpleReader::eat_ws ) {
6142 d->parseStack->remove();
6143#if defined(QT_QXML_DEBUG)
6144 qDebug( "QXmlSimpleReader: eat_ws (cont)" );
6145#endif
6146 }
6147 if ( !(this->*function)() ) {
6148 parseFailed( &QXmlSimpleReader::parseEntityDecl, state );
6149 return FALSE;
6150 }
6151 }
6152 }
6153
6154 for (;;) {
6155 switch ( state ) {
6156 case EValue:
6157 if ( !entityExist( name() ) ) {
6158 d->entities.insert( name(), string() );
6159 if ( declHnd ) {
6160 if ( !declHnd->internalEntityDecl( name(), string() ) ) {
6161 reportParseError( declHnd->errorString() );
6162 return FALSE;
6163 }
6164 }
6165 }
6166 state = EValueR;
6167 break;
6168 case NNam:
6169 if ( !entityExist( name() ) ) {
6170 d->externEntities.insert( name(), QXmlSimpleReaderPrivate::ExternEntity( d->publicId, d->systemId, ref() ) );
6171 if ( dtdHnd ) {
6172 if ( !dtdHnd->unparsedEntityDecl( name(), d->publicId, d->systemId, ref() ) ) {
6173 reportParseError( declHnd->errorString() );
6174 return FALSE;
6175 }
6176 }
6177 }
6178 state = NNamR;
6179 break;
6180 case PEVal:
6181 if ( !entityExist( name() ) ) {
6182 d->parameterEntities.insert( name(), string() );
6183 if ( declHnd ) {
6184 if ( !declHnd->internalEntityDecl( QString("%")+name(), string() ) ) {
6185 reportParseError( declHnd->errorString() );
6186 return FALSE;
6187 }
6188 }
6189 }
6190 state = PEValR;
6191 break;
6192 case PEEID:
6193 if ( !entityExist( name() ) ) {
6194 d->externParameterEntities.insert( name(), QXmlSimpleReaderPrivate::ExternParameterEntity( d->publicId, d->systemId ) );
6195 if ( declHnd ) {
6196 if ( !declHnd->externalEntityDecl( QString("%")+name(), d->publicId, d->systemId ) ) {
6197 reportParseError( declHnd->errorString() );
6198 return FALSE;
6199 }
6200 }
6201 }
6202 state = PEEIDR;
6203 break;
6204 case EDDone:
6205 if ( !entityExist( name() ) ) {
6206 d->externEntities.insert( name(), QXmlSimpleReaderPrivate::ExternEntity( d->publicId, d->systemId, QString::null ) );
6207 if ( declHnd ) {
6208 if ( !declHnd->externalEntityDecl( name(), d->publicId, d->systemId ) ) {
6209 reportParseError( declHnd->errorString() );
6210 return FALSE;
6211 }
6212 }
6213 }
6214 return TRUE;
6215 case Done:
6216 return TRUE;
6217 case -1:
6218 // Error
6219 reportParseError( XMLERR_LETTEREXPECTED );
6220 return FALSE;
6221 }
6222
6223 if ( atEnd() ) {
6224 unexpectedEof( &QXmlSimpleReader::parseEntityDecl, state );
6225 return FALSE;
6226 }
6227 if ( is_S(c) ) {
6228 input = InpWs;
6229 } else if ( c == '%' ) {
6230 input = InpPer;
6231 } else if ( c == '"' || c == '\'' ) {
6232 input = InpQuot;
6233 } else if ( c == '>' ) {
6234 input = InpGt;
6235 } else if ( c == 'N' ) {
6236 input = InpN;
6237 } else {
6238 input = InpUnknown;
6239 }
6240 state = table[state][input];
6241
6242 switch ( state ) {
6243 case Ent:
6244 d->parseString_s = "NTITY";
6245 if ( !parseString() ) {
6246 parseFailed( &QXmlSimpleReader::parseEntityDecl, state );
6247 return FALSE;
6248 }
6249 break;
6250 case Ws1:
6251 if ( !eat_ws() ) {
6252 parseFailed( &QXmlSimpleReader::parseEntityDecl, state );
6253 return FALSE;
6254 }
6255 break;
6256 case Name:
6257 d->parseName_useRef = FALSE;
6258 if ( !parseName() ) {
6259 parseFailed( &QXmlSimpleReader::parseEntityDecl, state );
6260 return FALSE;
6261 }
6262 break;
6263 case Ws2:
6264 if ( !eat_ws() ) {
6265 parseFailed( &QXmlSimpleReader::parseEntityDecl, state );
6266 return FALSE;
6267 }
6268 break;
6269 case EValue:
6270 case EValueR:
6271 if ( !parseEntityValue() ) {
6272 parseFailed( &QXmlSimpleReader::parseEntityDecl, state );
6273 return FALSE;
6274 }
6275 break;
6276 case ExtID:
6277 d->parseExternalID_allowPublicID = FALSE;
6278 if ( !parseExternalID() ) {
6279 parseFailed( &QXmlSimpleReader::parseEntityDecl, state );
6280 return FALSE;
6281 }
6282 break;
6283 case Ws3:
6284 if ( !eat_ws() ) {
6285 parseFailed( &QXmlSimpleReader::parseEntityDecl, state );
6286 return FALSE;
6287 }
6288 break;
6289 case Ndata:
6290 d->parseString_s = "NDATA";
6291 if ( !parseString() ) {
6292 parseFailed( &QXmlSimpleReader::parseEntityDecl, state );
6293 return FALSE;
6294 }
6295 break;
6296 case Ws4:
6297 if ( !eat_ws() ) {
6298 parseFailed( &QXmlSimpleReader::parseEntityDecl, state );
6299 return FALSE;
6300 }
6301 break;
6302 case NNam:
6303 case NNamR:
6304 d->parseName_useRef = TRUE;
6305 if ( !parseName() ) {
6306 parseFailed( &QXmlSimpleReader::parseEntityDecl, state );
6307 return FALSE;
6308 }
6309 break;
6310 case PEDec:
6311 next();
6312 break;
6313 case Ws6:
6314 if ( !eat_ws() ) {
6315 parseFailed( &QXmlSimpleReader::parseEntityDecl, state );
6316 return FALSE;
6317 }
6318 break;
6319 case PENam:
6320 d->parseName_useRef = FALSE;
6321 if ( !parseName() ) {
6322 parseFailed( &QXmlSimpleReader::parseEntityDecl, state );
6323 return FALSE;
6324 }
6325 break;
6326 case Ws7:
6327 if ( !eat_ws() ) {
6328 parseFailed( &QXmlSimpleReader::parseEntityDecl, state );
6329 return FALSE;
6330 }
6331 break;
6332 case PEVal:
6333 case PEValR:
6334 if ( !parseEntityValue() ) {
6335 parseFailed( &QXmlSimpleReader::parseEntityDecl, state );
6336 return FALSE;
6337 }
6338 break;
6339 case PEEID:
6340 case PEEIDR:
6341 d->parseExternalID_allowPublicID = FALSE;
6342 if ( !parseExternalID() ) {
6343 parseFailed( &QXmlSimpleReader::parseEntityDecl, state );
6344 return FALSE;
6345 }
6346 break;
6347 case WsE:
6348 if ( !eat_ws() ) {
6349 parseFailed( &QXmlSimpleReader::parseEntityDecl, state );
6350 return FALSE;
6351 }
6352 break;
6353 case EDDone:
6354 next();
6355 break;
6356 case Done:
6357 next();
6358 break;
6359 }
6360 }
6361}
6362
6363/*
6364 Parse a EntityValue [9]
6365*/
6366bool QXmlSimpleReader::parseEntityValue()
6367{
6368 const signed char Init = 0;
6369 const signed char Dq = 1; // EntityValue is double quoted
6370 const signed char DqC = 2; // signed character
6371 const signed char DqPER = 3; // PERefence
6372 const signed char DqRef = 4; // Reference
6373 const signed char Sq = 5; // EntityValue is double quoted
6374 const signed char SqC = 6; // signed character
6375 const signed char SqPER = 7; // PERefence
6376 const signed char SqRef = 8; // Reference
6377 const signed char Done = 9;
6378
6379 const signed char InpDq = 0; // "
6380 const signed char InpSq = 1; // '
6381 const signed char InpAmp = 2; // &
6382 const signed char InpPer = 3; // %
6383 const signed char InpUnknown = 4;
6384
6385 static const signed char table[9][5] = {
6386 /* InpDq InpSq InpAmp InpPer InpUnknown */
6387 { Dq, Sq, -1, -1, -1 }, // Init
6388 { Done, DqC, DqRef, DqPER, DqC }, // Dq
6389 { Done, DqC, DqRef, DqPER, DqC }, // DqC
6390 { Done, DqC, DqRef, DqPER, DqC }, // DqPER
6391 { Done, DqC, DqRef, DqPER, DqC }, // DqRef
6392 { SqC, Done, SqRef, SqPER, SqC }, // Sq
6393 { SqC, Done, SqRef, SqPER, SqC }, // SqC
6394 { SqC, Done, SqRef, SqPER, SqC }, // SqPER
6395 { SqC, Done, SqRef, SqPER, SqC } // SqRef
6396 };
6397 signed char state;
6398 signed char input;
6399
6400 if ( d->parseStack==0 || d->parseStack->isEmpty() ) {
6401 state = Init;
6402 } else {
6403 state = d->parseStack->top()->state;
6404 d->parseStack->remove();
6405#if defined(QT_QXML_DEBUG)
6406 qDebug( "QXmlSimpleReader: parseEntityValue (cont) in state %d", state );
6407#endif
6408 if ( !d->parseStack->isEmpty() ) {
6409 ParseFunction function = d->parseStack->top()->function;
6410 if ( function == &QXmlSimpleReader::eat_ws ) {
6411 d->parseStack->remove();
6412#if defined(QT_QXML_DEBUG)
6413 qDebug( "QXmlSimpleReader: eat_ws (cont)" );
6414#endif
6415 }
6416 if ( !(this->*function)() ) {
6417 parseFailed( &QXmlSimpleReader::parseEntityValue, state );
6418 return FALSE;
6419 }
6420 }
6421 }
6422
6423 for (;;) {
6424 switch ( state ) {
6425 case Done:
6426 return TRUE;
6427 case -1:
6428 // Error
6429 reportParseError( XMLERR_LETTEREXPECTED );
6430 return FALSE;
6431 }
6432
6433 if ( atEnd() ) {
6434 unexpectedEof( &QXmlSimpleReader::parseEntityValue, state );
6435 return FALSE;
6436 }
6437 if ( c == '"' ) {
6438 input = InpDq;
6439 } else if ( c == '\'' ) {
6440 input = InpSq;
6441 } else if ( c == '&' ) {
6442 input = InpAmp;
6443 } else if ( c == '%' ) {
6444 input = InpPer;
6445 } else {
6446 input = InpUnknown;
6447 }
6448 state = table[state][input];
6449
6450 switch ( state ) {
6451 case Dq:
6452 case Sq:
6453 stringClear();
6454 next();
6455 break;
6456 case DqC:
6457 case SqC:
6458 stringAddC();
6459 next();
6460 break;
6461 case DqPER:
6462 case SqPER:
6463 d->parsePEReference_context = InEntityValue;
6464 if ( !parsePEReference() ) {
6465 parseFailed( &QXmlSimpleReader::parseEntityValue, state );
6466 return FALSE;
6467 }
6468 break;
6469 case DqRef:
6470 case SqRef:
6471 d->parseReference_context = InEntityValue;
6472 if ( !parseReference() ) {
6473 parseFailed( &QXmlSimpleReader::parseEntityValue, state );
6474 return FALSE;
6475 }
6476 break;
6477 case Done:
6478 next();
6479 break;
6480 }
6481 }
6482}
6483
6484/*
6485 Parse a comment [15].
6486
6487 Precondition: the beginning '<!' of the comment is already read and the head
6488 stands on the first '-' of '<!--'.
6489
6490 If this funktion was successful, the head-position is on the first
6491 character after the comment.
6492*/
6493bool QXmlSimpleReader::parseComment()
6494{
6495 const signed char Init = 0;
6496 const signed char Dash1 = 1; // the first dash was read
6497 const signed char Dash2 = 2; // the second dash was read
6498 const signed char Com = 3; // read comment
6499 const signed char Com2 = 4; // read comment (help state)
6500 const signed char ComE = 5; // finished reading comment
6501 const signed char Done = 6;
6502
6503 const signed char InpDash = 0; // -
6504 const signed char InpGt = 1; // >
6505 const signed char InpUnknown = 2;
6506
6507 static const signed char table[6][3] = {
6508 /* InpDash InpGt InpUnknown */
6509 { Dash1, -1, -1 }, // Init
6510 { Dash2, -1, -1 }, // Dash1
6511 { Com2, Com, Com }, // Dash2
6512 { Com2, Com, Com }, // Com
6513 { ComE, Com, Com }, // Com2
6514 { -1, Done, -1 } // ComE
6515 };
6516 signed char state;
6517 signed char input;
6518
6519 if ( d->parseStack==0 || d->parseStack->isEmpty() ) {
6520 state = Init;
6521 } else {
6522 state = d->parseStack->top()->state;
6523 d->parseStack->remove();
6524#if defined(QT_QXML_DEBUG)
6525 qDebug( "QXmlSimpleReader: parseComment (cont) in state %d", state );
6526#endif
6527 if ( !d->parseStack->isEmpty() ) {
6528 ParseFunction function = d->parseStack->top()->function;
6529 if ( function == &QXmlSimpleReader::eat_ws ) {
6530 d->parseStack->remove();
6531#if defined(QT_QXML_DEBUG)
6532 qDebug( "QXmlSimpleReader: eat_ws (cont)" );
6533#endif
6534 }
6535 if ( !(this->*function)() ) {
6536 parseFailed( &QXmlSimpleReader::parseComment, state );
6537 return FALSE;
6538 }
6539 }
6540 }
6541
6542 for (;;) {
6543 switch ( state ) {
6544 case Dash2:
6545 stringClear();
6546 break;
6547 case Com2:
6548 // if next character is not a dash than don't skip it
6549 if ( !atEnd() && c != '-' )
6550 stringAddC( '-' );
6551 break;
6552 case Done:
6553 return TRUE;
6554 case -1:
6555 // Error
6556 reportParseError( XMLERR_ERRORPARSINGCOMMENT );
6557 return FALSE;
6558 }
6559
6560 if ( atEnd() ) {
6561 unexpectedEof( &QXmlSimpleReader::parseComment, state );
6562 return FALSE;
6563 }
6564 if ( c == '-' ) {
6565 input = InpDash;
6566 } else if ( c == '>' ) {
6567 input = InpGt;
6568 } else {
6569 input = InpUnknown;
6570 }
6571 state = table[state][input];
6572
6573 switch ( state ) {
6574 case Dash1:
6575 next();
6576 break;
6577 case Dash2:
6578 next();
6579 break;
6580 case Com:
6581 stringAddC();
6582 next();
6583 break;
6584 case Com2:
6585 next();
6586 break;
6587 case ComE:
6588 next();
6589 break;
6590 case Done:
6591 next();
6592 break;
6593 }
6594 }
6595}
6596
6597/*
6598 Parse an Attribute [41].
6599
6600 Precondition: the head stands on the first character of the name
6601 of the attribute (i.e. all whitespaces are already parsed).
6602
6603 The head stand on the next character after the end quotes. The
6604 variable name contains the name of the attribute and the variable
6605 string contains the value of the attribute.
6606*/
6607bool QXmlSimpleReader::parseAttribute()
6608{
6609 const signed char Init = 0;
6610 const signed char PName = 1; // parse name
6611 const signed char Ws = 2; // eat ws
6612 const signed char Eq = 3; // the '=' was read
6613 const signed char Quotes = 4; // " or ' were read
6614
6615 const signed char InpNameBe = 0;
6616 const signed char InpEq = 1; // =
6617 const signed char InpDq = 2; // "
6618 const signed char InpSq = 3; // '
6619 const signed char InpUnknown = 4;
6620
6621 static const signed char table[4][5] = {
6622 /* InpNameBe InpEq InpDq InpSq InpUnknown */
6623 { PName, -1, -1, -1, -1 }, // Init
6624 { -1, Eq, -1, -1, Ws }, // PName
6625 { -1, Eq, -1, -1, -1 }, // Ws
6626 { -1, -1, Quotes, Quotes, -1 } // Eq
6627 };
6628 signed char state;
6629 signed char input;
6630
6631 if ( d->parseStack==0 || d->parseStack->isEmpty() ) {
6632 state = Init;
6633 } else {
6634 state = d->parseStack->top()->state;
6635 d->parseStack->remove();
6636#if defined(QT_QXML_DEBUG)
6637 qDebug( "QXmlSimpleReader: parseAttribute (cont) in state %d", state );
6638#endif
6639 if ( !d->parseStack->isEmpty() ) {
6640 ParseFunction function = d->parseStack->top()->function;
6641 if ( function == &QXmlSimpleReader::eat_ws ) {
6642 d->parseStack->remove();
6643#if defined(QT_QXML_DEBUG)
6644 qDebug( "QXmlSimpleReader: eat_ws (cont)" );
6645#endif
6646 }
6647 if ( !(this->*function)() ) {
6648 parseFailed( &QXmlSimpleReader::parseAttribute, state );
6649 return FALSE;
6650 }
6651 }
6652 }
6653
6654 for (;;) {
6655 switch ( state ) {
6656 case Quotes:
6657 // Done
6658 return TRUE;
6659 case -1:
6660 // Error
6661 reportParseError( XMLERR_UNEXPECTEDCHARACTER );
6662 return FALSE;
6663 }
6664
6665 if ( atEnd() ) {
6666 unexpectedEof( &QXmlSimpleReader::parseAttribute, state );
6667 return FALSE;
6668 }
6669 if ( is_NameBeginning(c) ) {
6670 input = InpNameBe;
6671 } else if ( c == '=' ) {
6672 input = InpEq;
6673 } else if ( c == '"' ) {
6674 input = InpDq;
6675 } else if ( c == '\'' ) {
6676 input = InpSq;
6677 } else {
6678 input = InpUnknown;
6679 }
6680 state = table[state][input];
6681
6682 switch ( state ) {
6683 case PName:
6684 d->parseName_useRef = FALSE;
6685 if ( !parseName() ) {
6686 parseFailed( &QXmlSimpleReader::parseAttribute, state );
6687 return FALSE;
6688 }
6689 break;
6690 case Ws:
6691 if ( !eat_ws() ) {
6692 parseFailed( &QXmlSimpleReader::parseAttribute, state );
6693 return FALSE;
6694 }
6695 break;
6696 case Eq:
6697 if ( !next_eat_ws() ) {
6698 parseFailed( &QXmlSimpleReader::parseAttribute, state );
6699 return FALSE;
6700 }
6701 break;
6702 case Quotes:
6703 if ( !parseAttValue() ) {
6704 parseFailed( &QXmlSimpleReader::parseAttribute, state );
6705 return FALSE;
6706 }
6707 break;
6708 }
6709 }
6710}
6711
6712/*
6713 Parse a Name [5] and store the name in name or ref (if useRef is TRUE).
6714*/
6715bool QXmlSimpleReader::parseName()
6716{
6717 const signed char Init = 0;
6718 const signed char Name1 = 1; // parse first signed character of the name
6719 const signed char Name = 2; // parse name
6720 const signed char Done = 3;
6721
6722 const signed char InpNameBe = 0; // name beginning signed characters
6723 const signed char InpNameCh = 1; // NameChar without InpNameBe
6724 const signed char InpUnknown = 2;
6725
6726 static const signed char table[3][3] = {
6727 /* InpNameBe InpNameCh InpUnknown */
6728 { Name1, -1, -1 }, // Init
6729 { Name, Name, Done }, // Name1
6730 { Name, Name, Done } // Name
6731 };
6732 signed char state;
6733 signed char input;
6734
6735 if ( d->parseStack==0 || d->parseStack->isEmpty() ) {
6736 state = Init;
6737 } else {
6738 state = d->parseStack->top()->state;
6739 d->parseStack->remove();
6740#if defined(QT_QXML_DEBUG)
6741 qDebug( "QXmlSimpleReader: parseName (cont) in state %d", state );
6742#endif
6743 if ( !d->parseStack->isEmpty() ) {
6744 ParseFunction function = d->parseStack->top()->function;
6745 if ( function == &QXmlSimpleReader::eat_ws ) {
6746 d->parseStack->remove();
6747#if defined(QT_QXML_DEBUG)
6748 qDebug( "QXmlSimpleReader: eat_ws (cont)" );
6749#endif
6750 }
6751 if ( !(this->*function)() ) {
6752 parseFailed( &QXmlSimpleReader::parseName, state );
6753 return FALSE;
6754 }
6755 }
6756 }
6757
6758 for (;;) {
6759 switch ( state ) {
6760 case Done:
6761 return TRUE;
6762 case -1:
6763 // Error
6764 reportParseError( XMLERR_LETTEREXPECTED );
6765 return FALSE;
6766 }
6767
6768 if ( atEnd() ) {
6769 unexpectedEof( &QXmlSimpleReader::parseName, state );
6770 return FALSE;
6771 }
6772 if ( is_NameBeginning(c) ) {
6773 input = InpNameBe;
6774 } else if ( is_NameChar(c) ) {
6775 input = InpNameCh;
6776 } else {
6777 input = InpUnknown;
6778 }
6779 state = table[state][input];
6780
6781 switch ( state ) {
6782 case Name1:
6783 if ( d->parseName_useRef ) {
6784 refClear();
6785 refAddC();
6786 } else {
6787 nameClear();
6788 nameAddC();
6789 }
6790 next();
6791 break;
6792 case Name:
6793 if ( d->parseName_useRef ) {
6794 refAddC();
6795 } else {
6796 nameAddC();
6797 }
6798 next();
6799 break;
6800 }
6801 }
6802}
6803
6804/*
6805 Parse a Nmtoken [7] and store the name in name.
6806*/
6807bool QXmlSimpleReader::parseNmtoken()
6808{
6809 const signed char Init = 0;
6810 const signed char NameF = 1;
6811 const signed char Name = 2;
6812 const signed char Done = 3;
6813
6814 const signed char InpNameCh = 0; // NameChar without InpNameBe
6815 const signed char InpUnknown = 1;
6816
6817 static const signed char table[3][2] = {
6818 /* InpNameCh InpUnknown */
6819 { NameF, -1 }, // Init
6820 { Name, Done }, // NameF
6821 { Name, Done } // Name
6822 };
6823 signed char state;
6824 signed char input;
6825
6826 if ( d->parseStack==0 || d->parseStack->isEmpty() ) {
6827 state = Init;
6828 } else {
6829 state = d->parseStack->top()->state;
6830 d->parseStack->remove();
6831#if defined(QT_QXML_DEBUG)
6832 qDebug( "QXmlSimpleReader: parseNmtoken (cont) in state %d", state );
6833#endif
6834 if ( !d->parseStack->isEmpty() ) {
6835 ParseFunction function = d->parseStack->top()->function;
6836 if ( function == &QXmlSimpleReader::eat_ws ) {
6837 d->parseStack->remove();
6838#if defined(QT_QXML_DEBUG)
6839 qDebug( "QXmlSimpleReader: eat_ws (cont)" );
6840#endif
6841 }
6842 if ( !(this->*function)() ) {
6843 parseFailed( &QXmlSimpleReader::parseNmtoken, state );
6844 return FALSE;
6845 }
6846 }
6847 }
6848
6849 for (;;) {
6850 switch ( state ) {
6851 case Done:
6852 return TRUE;
6853 case -1:
6854 // Error
6855 reportParseError( XMLERR_LETTEREXPECTED );
6856 return FALSE;
6857 }
6858
6859 if ( atEnd() ) {
6860 unexpectedEof( &QXmlSimpleReader::parseNmtoken, state );
6861 return FALSE;
6862 }
6863 if ( is_NameChar(c) ) {
6864 input = InpNameCh;
6865 } else {
6866 input = InpUnknown;
6867 }
6868 state = table[state][input];
6869
6870 switch ( state ) {
6871 case NameF:
6872 nameClear();
6873 nameAddC();
6874 next();
6875 break;
6876 case Name:
6877 nameAddC();
6878 next();
6879 break;
6880 }
6881 }
6882}
6883
6884/*
6885 Parse a Reference [67].
6886
6887 parseReference_charDataRead is set to TRUE if the reference must not be
6888 parsed. The character(s) which the reference mapped to are appended to
6889 string. The head stands on the first character after the reference.
6890
6891 parseReference_charDataRead is set to FALSE if the reference must be parsed.
6892 The charachter(s) which the reference mapped to are inserted at the reference
6893 position. The head stands on the first character of the replacement).
6894*/
6895bool QXmlSimpleReader::parseReference()
6896{
6897 // temporary variables (only used in very local context, so they don't
6898 // interfere with incremental parsing)
6899 uint tmp;
6900 bool ok;
6901
6902 const signed char Init = 0;
6903 const signed char SRef = 1; // start of a reference
6904 const signed char ChRef = 2; // parse CharRef
6905 const signed char ChDec = 3; // parse CharRef decimal
6906 const signed char ChHexS = 4; // start CharRef hexadecimal
6907 const signed char ChHex = 5; // parse CharRef hexadecimal
6908 const signed char Name = 6; // parse name
6909 const signed char DoneD = 7; // done CharRef decimal
6910 const signed char DoneH = 8; // done CharRef hexadecimal
6911 const signed char DoneN = 9; // done EntityRef
6912
6913 const signed char InpAmp = 0; // &
6914 const signed char InpSemi = 1; // ;
6915 const signed char InpHash = 2; // #
6916 const signed char InpX = 3; // x
6917 const signed char InpNum = 4; // 0-9
6918 const signed char InpHex = 5; // a-f A-F
6919 const signed char InpUnknown = 6;
6920
6921 static const signed char table[8][7] = {
6922 /* InpAmp InpSemi InpHash InpX InpNum InpHex InpUnknown */
6923 { SRef, -1, -1, -1, -1, -1, -1 }, // Init
6924 { -1, -1, ChRef, Name, Name, Name, Name }, // SRef
6925 { -1, -1, -1, ChHexS, ChDec, -1, -1 }, // ChRef
6926 { -1, DoneD, -1, -1, ChDec, -1, -1 }, // ChDec
6927 { -1, -1, -1, -1, ChHex, ChHex, -1 }, // ChHexS
6928 { -1, DoneH, -1, -1, ChHex, ChHex, -1 }, // ChHex
6929 { -1, DoneN, -1, -1, -1, -1, -1 } // Name
6930 };
6931 signed char state;
6932 signed char input;
6933
6934 if ( d->parseStack==0 || d->parseStack->isEmpty() ) {
6935 d->parseReference_charDataRead = FALSE;
6936 state = Init;
6937 } else {
6938 state = d->parseStack->top()->state;
6939 d->parseStack->remove();
6940#if defined(QT_QXML_DEBUG)
6941 qDebug( "QXmlSimpleReader: parseReference (cont) in state %d", state );
6942#endif
6943 if ( !d->parseStack->isEmpty() ) {
6944 ParseFunction function = d->parseStack->top()->function;
6945 if ( function == &QXmlSimpleReader::eat_ws ) {
6946 d->parseStack->remove();
6947#if defined(QT_QXML_DEBUG)
6948 qDebug( "QXmlSimpleReader: eat_ws (cont)" );
6949#endif
6950 }
6951 if ( !(this->*function)() ) {
6952 parseFailed( &QXmlSimpleReader::parseReference, state );
6953 return FALSE;
6954 }
6955 }
6956 }
6957
6958 for (;;) {
6959 switch ( state ) {
6960 case DoneD:
6961 return TRUE;
6962 case DoneH:
6963 return TRUE;
6964 case DoneN:
6965 return TRUE;
6966 case -1:
6967 // Error
6968 reportParseError( XMLERR_ERRORPARSINGREFERENCE );
6969 return FALSE;
6970 }
6971
6972 if ( atEnd() ) {
6973 unexpectedEof( &QXmlSimpleReader::parseReference, state );
6974 return FALSE;
6975 }
6976 if ( c.row() ) {
6977 input = InpUnknown;
6978 } else if ( c.cell() == '&' ) {
6979 input = InpAmp;
6980 } else if ( c.cell() == ';' ) {
6981 input = InpSemi;
6982 } else if ( c.cell() == '#' ) {
6983 input = InpHash;
6984 } else if ( c.cell() == 'x' ) {
6985 input = InpX;
6986 } else if ( '0' <= c.cell() && c.cell() <= '9' ) {
6987 input = InpNum;
6988 } else if ( 'a' <= c.cell() && c.cell() <= 'f' ) {
6989 input = InpHex;
6990 } else if ( 'A' <= c.cell() && c.cell() <= 'F' ) {
6991 input = InpHex;
6992 } else {
6993 input = InpUnknown;
6994 }
6995 state = table[state][input];
6996
6997 switch ( state ) {
6998 case SRef:
6999 refClear();
7000 next();
7001 break;
7002 case ChRef:
7003 next();
7004 break;
7005 case ChDec:
7006 refAddC();
7007 next();
7008 break;
7009 case ChHexS:
7010 next();
7011 break;
7012 case ChHex:
7013 refAddC();
7014 next();
7015 break;
7016 case Name:
7017 // read the name into the ref
7018 d->parseName_useRef = TRUE;
7019 if ( !parseName() ) {
7020 parseFailed( &QXmlSimpleReader::parseReference, state );
7021 return FALSE;
7022 }
7023 break;
7024 case DoneD:
7025 tmp = ref().toUInt( &ok, 10 );
7026 if ( ok ) {
7027 stringAddC( QChar(tmp) );
7028 } else {
7029 reportParseError( XMLERR_ERRORPARSINGREFERENCE );
7030 return FALSE;
7031 }
7032 d->parseReference_charDataRead = TRUE;
7033 next();
7034 break;
7035 case DoneH:
7036 tmp = ref().toUInt( &ok, 16 );
7037 if ( ok ) {
7038 stringAddC( QChar(tmp) );
7039 } else {
7040 reportParseError( XMLERR_ERRORPARSINGREFERENCE );
7041 return FALSE;
7042 }
7043 d->parseReference_charDataRead = TRUE;
7044 next();
7045 break;
7046 case DoneN:
7047 if ( !processReference() )
7048 return FALSE;
7049 next();
7050 break;
7051 }
7052 }
7053}
7054
7055/*
7056 Helper function for parseReference()
7057*/
7058bool QXmlSimpleReader::processReference()
7059{
7060 QString reference = ref();
7061 if ( reference == "amp" ) {
7062 if ( d->parseReference_context == InEntityValue ) {
7063 // Bypassed
7064 stringAddC( '&' ); stringAddC( 'a' ); stringAddC( 'm' ); stringAddC( 'p' ); stringAddC( ';' );
7065 } else {
7066 // Included or Included in literal
7067 stringAddC( '&' );
7068 }
7069 d->parseReference_charDataRead = TRUE;
7070 } else if ( reference == "lt" ) {
7071 if ( d->parseReference_context == InEntityValue ) {
7072 // Bypassed
7073 stringAddC( '&' ); stringAddC( 'l' ); stringAddC( 't' ); stringAddC( ';' );
7074 } else {
7075 // Included or Included in literal
7076 stringAddC( '<' );
7077 }
7078 d->parseReference_charDataRead = TRUE;
7079 } else if ( reference == "gt" ) {
7080 if ( d->parseReference_context == InEntityValue ) {
7081 // Bypassed
7082 stringAddC( '&' ); stringAddC( 'g' ); stringAddC( 't' ); stringAddC( ';' );
7083 } else {
7084 // Included or Included in literal
7085 stringAddC( '>' );
7086 }
7087 d->parseReference_charDataRead = TRUE;
7088 } else if ( reference == "apos" ) {
7089 if ( d->parseReference_context == InEntityValue ) {
7090 // Bypassed
7091 stringAddC( '&' ); stringAddC( 'a' ); stringAddC( 'p' ); stringAddC( 'o' ); stringAddC( 's' ); stringAddC( ';' );
7092 } else {
7093 // Included or Included in literal
7094 stringAddC( '\'' );
7095 }
7096 d->parseReference_charDataRead = TRUE;
7097 } else if ( reference == "quot" ) {
7098 if ( d->parseReference_context == InEntityValue ) {
7099 // Bypassed
7100 stringAddC( '&' ); stringAddC( 'q' ); stringAddC( 'u' ); stringAddC( 'o' ); stringAddC( 't' ); stringAddC( ';' );
7101 } else {
7102 // Included or Included in literal
7103 stringAddC( '"' );
7104 }
7105 d->parseReference_charDataRead = TRUE;
7106 } else {
7107 QMap<QString,QString>::Iterator it;
7108 it = d->entities.find( reference );
7109 if ( it != d->entities.end() ) {
7110 // "Internal General"
7111 switch ( d->parseReference_context ) {
7112 case InContent:
7113 // Included
7114 if ( !insertXmlRef( it.data(), reference, FALSE ) )
7115 return FALSE;
7116 d->parseReference_charDataRead = FALSE;
7117 break;
7118 case InAttributeValue:
7119 // Included in literal
7120 if ( !insertXmlRef( it.data(), reference, TRUE ) )
7121 return FALSE;
7122 d->parseReference_charDataRead = FALSE;
7123 break;
7124 case InEntityValue:
7125 {
7126 // Bypassed
7127 stringAddC( '&' );
7128 for ( int i=0; i<(int)reference.length(); i++ ) {
7129 stringAddC( reference[i] );
7130 }
7131 stringAddC( ';');
7132 d->parseReference_charDataRead = TRUE;
7133 }
7134 break;
7135 case InDTD:
7136 // Forbidden
7137 d->parseReference_charDataRead = FALSE;
7138 reportParseError( XMLERR_INTERNALGENERALENTITYINDTD );
7139 return FALSE;
7140 }
7141 } else {
7142 QMap<QString,QXmlSimpleReaderPrivate::ExternEntity>::Iterator itExtern;
7143 itExtern = d->externEntities.find( reference );
7144 if ( itExtern == d->externEntities.end() ) {
7145 // entity not declared
7146 // ### check this case for conformance
7147 if ( d->parseReference_context == InEntityValue ) {
7148 // Bypassed
7149 stringAddC( '&' );
7150 for ( int i=0; i<(int)reference.length(); i++ ) {
7151 stringAddC( reference[i] );
7152 }
7153 stringAddC( ';');
7154 d->parseReference_charDataRead = TRUE;
7155 } else {
7156 if ( contentHnd ) {
7157 if ( !contentHnd->skippedEntity( reference ) ) {
7158 reportParseError( contentHnd->errorString() );
7159 return FALSE; // error
7160 }
7161 }
7162 }
7163 } else if ( (*itExtern).notation.isNull() ) {
7164 // "External Parsed General"
7165 switch ( d->parseReference_context ) {
7166 case InContent:
7167 {
7168 // Included if validating
7169 bool skipIt = TRUE;
7170 if ( entityRes ) {
7171 QXmlInputSource *ret = 0;
7172 if ( !entityRes->resolveEntity( itExtern.data().publicId, itExtern.data().systemId, ret ) ) {
7173 delete ret;
7174 reportParseError( entityRes->errorString() );
7175 return FALSE;
7176 }
7177 if ( ret ) {
7178 QString xmlRefString = ret->data();
7179 delete ret;
7180 if ( !stripTextDecl( xmlRefString ) ) {
7181 reportParseError( XMLERR_ERRORINTEXTDECL );
7182 return FALSE;
7183 }
7184 if ( !insertXmlRef( xmlRefString, reference, FALSE ) )
7185 return FALSE;
7186 skipIt = FALSE;
7187 }
7188 }
7189 if ( skipIt && contentHnd ) {
7190 if ( !contentHnd->skippedEntity( reference ) ) {
7191 reportParseError( contentHnd->errorString() );
7192 return FALSE; // error
7193 }
7194 }
7195 d->parseReference_charDataRead = FALSE;
7196 } break;
7197 case InAttributeValue:
7198 // Forbidden
7199 d->parseReference_charDataRead = FALSE;
7200 reportParseError( XMLERR_EXTERNALGENERALENTITYINAV );
7201 return FALSE;
7202 case InEntityValue:
7203 {
7204 // Bypassed
7205 stringAddC( '&' );
7206 for ( int i=0; i<(int)reference.length(); i++ ) {
7207 stringAddC( reference[i] );
7208 }
7209 stringAddC( ';');
7210 d->parseReference_charDataRead = TRUE;
7211 }
7212 break;
7213 case InDTD:
7214 // Forbidden
7215 d->parseReference_charDataRead = FALSE;
7216 reportParseError( XMLERR_EXTERNALGENERALENTITYINDTD );
7217 return FALSE;
7218 }
7219 } else {
7220 // "Unparsed"
7221 // ### notify for "Occurs as Attribute Value" missing (but this is no refence, anyway)
7222 // Forbidden
7223 d->parseReference_charDataRead = FALSE;
7224 reportParseError( XMLERR_UNPARSEDENTITYREFERENCE );
7225 return FALSE; // error
7226 }
7227 }
7228 }
7229 return TRUE; // no error
7230}
7231
7232
7233/*
7234 Parses over a simple string.
7235
7236 After the string was successfully parsed, the head is on the first
7237 character after the string.
7238*/
7239bool QXmlSimpleReader::parseString()
7240{
7241 const signed char InpCharExpected = 0; // the character that was expected
7242 const signed char InpUnknown = 1;
7243
7244 signed char state; // state in this function is the position in the string s
7245 signed char input;
7246
7247 if ( d->parseStack==0 || d->parseStack->isEmpty() ) {
7248 d->Done = d->parseString_s.length();
7249 state = 0;
7250 } else {
7251 state = d->parseStack->top()->state;
7252 d->parseStack->remove();
7253#if defined(QT_QXML_DEBUG)
7254 qDebug( "QXmlSimpleReader: parseString (cont) in state %d", state );
7255#endif
7256 if ( !d->parseStack->isEmpty() ) {
7257 ParseFunction function = d->parseStack->top()->function;
7258 if ( function == &QXmlSimpleReader::eat_ws ) {
7259 d->parseStack->remove();
7260#if defined(QT_QXML_DEBUG)
7261 qDebug( "QXmlSimpleReader: eat_ws (cont)" );
7262#endif
7263 }
7264 if ( !(this->*function)() ) {
7265 parseFailed( &QXmlSimpleReader::parseString, state );
7266 return FALSE;
7267 }
7268 }
7269 }
7270
7271 for (;;) {
7272 if ( state == d->Done ) {
7273 return TRUE;
7274 }
7275
7276 if ( atEnd() ) {
7277 unexpectedEof( &QXmlSimpleReader::parseString, state );
7278 return FALSE;
7279 }
7280 if ( c == d->parseString_s[(int)state] ) {
7281 input = InpCharExpected;
7282 } else {
7283 input = InpUnknown;
7284 }
7285 if ( input == InpCharExpected ) {
7286 state++;
7287 } else {
7288 // Error
7289 reportParseError( XMLERR_UNEXPECTEDCHARACTER );
7290 return FALSE;
7291 }
7292
7293 next();
7294 }
7295}
7296
7297/*
7298 This private function inserts and reports an entity substitution. The
7299 substituted string is \a data and the name of the entity reference is \a
7300 name. If \a inLiteral is TRUE, the entity is IncludedInLiteral (i.e., " and '
7301 must be quoted. Otherwise they are not quoted.
7302
7303 This function returns FALSE on error.
7304*/
7305bool QXmlSimpleReader::insertXmlRef( const QString &data, const QString &name, bool inLiteral )
7306{
7307 if ( inLiteral ) {
7308 QString tmp = data;
7309 d->xmlRef.push( tmp.replace( "\"", "&quot;" ).replace( "'", "&apos;" ) );
7310 } else {
7311 d->xmlRef.push( data );
7312 }
7313 d->xmlRefName.push( name );
7314 uint n = (uint)QMAX( d->parameterEntities.count(), d->entities.count() );
7315 if ( d->xmlRefName.count() > n+1 ) {
7316 // recursive entities
7317 reportParseError( XMLERR_RECURSIVEENTITIES );
7318 return FALSE;
7319 }
7320 if ( d->reportEntities && lexicalHnd ) {
7321 if ( !lexicalHnd->startEntity( name ) ) {
7322 reportParseError( lexicalHnd->errorString() );
7323 return FALSE;
7324 }
7325 }
7326 return TRUE;
7327}
7328
7329/*
7330 This private function moves the cursor to the next character.
7331*/
7332void QXmlSimpleReader::next()
7333{
7334 int count = (uint)d->xmlRef.count();
7335 while ( count != 0 ) {
7336 if ( d->xmlRef.top().isEmpty() ) {
7337 d->xmlRef.pop_back();
7338 d->xmlRefName.pop_back();
7339 count--;
7340 } else {
7341 c = d->xmlRef.top().constref( 0 );
7342 d->xmlRef.top().remove( (uint)0, 1 );
7343 return;
7344 }
7345 }
7346 // the following could be written nicer, but since it is a time-critical
7347 // function, rather optimize for speed
7348 if ( c == '\n' ) {
7349 c = inputSource->next();
7350 lineNr++;
7351 columnNr = -1;
7352 } else if ( c == '\r' ) {
7353 c = inputSource->next();
7354 if ( c != '\n' ) {
7355 lineNr++;
7356 columnNr = -1;
7357 }
7358 } else {
7359 c = inputSource->next();
7360 }
7361 columnNr++;
7362}
7363
7364/*
7365 This private function moves the cursor to the next non-whitespace character.
7366 This function does not move the cursor if the actual cursor position is a
7367 non-whitespace charcter.
7368
7369 Returns FALSE when you use incremental parsing and this function reaches EOF
7370 with reading only whitespace characters. In this case it also poplulates the
7371 parseStack with useful information. In all other cases, this function returns
7372 TRUE.
7373*/
7374bool QXmlSimpleReader::eat_ws()
7375{
7376 while ( !atEnd() ) {
7377 if ( !is_S(c) ) {
7378 return TRUE;
7379 }
7380 next();
7381 }
7382 if ( d->parseStack != 0 ) {
7383 unexpectedEof( &QXmlSimpleReader::eat_ws, 0 );
7384 return FALSE;
7385 }
7386 return TRUE;
7387}
7388
7389bool QXmlSimpleReader::next_eat_ws()
7390{
7391 next();
7392 return eat_ws();
7393}
7394
7395
7396/*
7397 This private function initializes the reader. \a i is the input source to
7398 read the data from.
7399*/
7400void QXmlSimpleReader::init( const QXmlInputSource *i )
7401{
7402 lineNr = 0;
7403 columnNr = -1;
7404 inputSource = (QXmlInputSource *)i;
7405 initData();
7406
7407 d->externParameterEntities.clear();
7408 d->parameterEntities.clear();
7409 d->externEntities.clear();
7410 d->entities.clear();
7411
7412 d->tags.clear();
7413
7414 d->doctype = "";
7415 d->xmlVersion = "";
7416 d->encoding = "";
7417 d->standalone = QXmlSimpleReaderPrivate::Unknown;
7418 d->error = QString::null;
7419}
7420
7421/*
7422 This private function initializes the XML data related variables. Especially,
7423 it reads the data from the input source.
7424*/
7425void QXmlSimpleReader::initData()
7426{
7427 c = QXmlInputSource::EndOfData;
7428 d->xmlRef.clear();
7429 next();
7430}
7431
7432/*
7433 Returns TRUE if a entity with the name \a e exists,
7434 otherwise returns FALSE.
7435*/
7436bool QXmlSimpleReader::entityExist( const QString& e ) const
7437{
7438 if ( d->parameterEntities.find(e) == d->parameterEntities.end() &&
7439 d->externParameterEntities.find(e) == d->externParameterEntities.end() &&
7440 d->externEntities.find(e) == d->externEntities.end() &&
7441 d->entities.find(e) == d->entities.end() ) {
7442 return FALSE;
7443 } else {
7444 return TRUE;
7445 }
7446}
7447
7448void QXmlSimpleReader::reportParseError( const QString& error )
7449{
7450 d->error = error;
7451 if ( errorHnd ) {
7452 if ( d->error.isNull() ) {
7453 errorHnd->fatalError( QXmlParseException( XMLERR_OK, columnNr+1, lineNr+1 ) );
7454 } else {
7455 errorHnd->fatalError( QXmlParseException( d->error, columnNr+1, lineNr+1 ) );
7456 }
7457 }
7458}
7459
7460/*
7461 This private function is called when a parsing function encounters an
7462 unexpected EOF. It decides what to do (depending on incremental parsing or
7463 not). \a where is a pointer to the function where the error occurred and \a
7464 state is the parsing state in this function.
7465*/
7466void QXmlSimpleReader::unexpectedEof( ParseFunction where, int state )
7467{
7468 if ( d->parseStack == 0 ) {
7469 reportParseError( XMLERR_UNEXPECTEDEOF );
7470 } else {
7471 if ( c == QXmlInputSource::EndOfDocument ) {
7472 reportParseError( XMLERR_UNEXPECTEDEOF );
7473 } else {
7474 pushParseState( where, state );
7475 }
7476 }
7477}
7478
7479/*
7480 This private function is called when a parse...() function returned FALSE. It
7481 determines if there was an error or if incremental parsing simply went out of
7482 data and does the right thing for the case. \a where is a pointer to the
7483 function where the error occurred and \a state is the parsing state in this
7484 function.
7485*/
7486void QXmlSimpleReader::parseFailed( ParseFunction where, int state )
7487{
7488 if ( d->parseStack!=0 && d->error.isNull() ) {
7489 pushParseState( where, state );
7490 }
7491}
7492
7493/*
7494 This private function pushes the function pointer \a function and state \a
7495 state to the parse stack. This is used when you are doing an incremental
7496 parsing and reach the end of file too early.
7497
7498 Only call this function when d->parseStack!=0.
7499*/
7500void QXmlSimpleReader::pushParseState( ParseFunction function, int state )
7501{
7502 QXmlSimpleReaderPrivate::ParseState *ps = new QXmlSimpleReaderPrivate::ParseState;
7503 ps->function = function;
7504 ps->state = state;
7505 d->parseStack->push( ps );
7506}
7507
7508
7509// use buffers instead of QString::operator+= when single characters are read
7510QString& QXmlSimpleReader::string()
7511{
7512 stringValue += QString( stringArray, stringPos );
7513 stringPos = 0;
7514 return stringValue;
7515}
7516QString& QXmlSimpleReader::name()
7517{
7518 nameValue += QString( nameArray, namePos );
7519 namePos = 0;
7520 return nameValue;
7521}
7522QString& QXmlSimpleReader::ref()
7523{
7524 refValue += QString( refArray, refPos );
7525 refPos = 0;
7526 return refValue;
7527}
7528
7529void QXmlSimpleReader::stringAddC()
7530{
7531 if ( stringPos >= 256 ) {
7532 stringValue += QString( stringArray, stringPos );
7533 stringPos = 0;
7534 }
7535 stringArray[stringPos++] = c;
7536}
7537void QXmlSimpleReader::nameAddC()
7538{
7539 if ( namePos >= 256 ) {
7540 nameValue += QString( nameArray, namePos );
7541 namePos = 0;
7542 }
7543 nameArray[namePos++] = c;
7544}
7545void QXmlSimpleReader::refAddC()
7546{
7547 if ( refPos >= 256 ) {
7548 refValue += QString( refArray, refPos );
7549 refPos = 0;
7550 }
7551 refArray[refPos++] = c;
7552}
7553
7554void QXmlSimpleReader::stringAddC(const QChar& ch)
7555{
7556 if ( stringPos >= 256 ) {
7557 stringValue += QString( stringArray, stringPos );
7558 stringPos = 0;
7559 }
7560 stringArray[stringPos++] = ch;
7561}
7562void QXmlSimpleReader::nameAddC(const QChar& ch)
7563{
7564 if ( namePos >= 256 ) {
7565 nameValue += QString( nameArray, namePos );
7566 namePos = 0;
7567 }
7568 nameArray[namePos++] = ch;
7569}
7570void QXmlSimpleReader::refAddC(const QChar& ch)
7571{
7572 if ( refPos >= 256 ) {
7573 refValue += QString( refArray, refPos );
7574 refPos = 0;
7575 }
7576 refArray[refPos++] = ch;
7577}
7578
7579#endif //QT_NO_XML
Note: See TracBrowser for help on using the repository browser.