source: psi/trunk/src/tools/qxml/qxml.cpp

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

Imported original Psi 0.10 sources from Affinix

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