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