From 2f7550f49c97557fe48c66876a45f6331d112478 Mon Sep 17 00:00:00 2001 From: ulf69 Date: Wed, 15 Sep 2004 17:43:49 +0000 Subject: initial version --- (limited to 'qtcompat/xml') 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 @@ +/**************************************************************************** +** $Id$ +** +** Implementation of QDomDocument and related classes. +** +** Created : 000518 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the XML module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition licenses may use this +** file in accordance with the Qt Commercial License Agreement provided +** with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + + +/****************************************** + * DOM support is disabled in QT 2.3.7 for sharp zaurus. + * Because of that we copied the code from 2.3.7 into qtcompat and enabled it + * there. + * Copyright (c) 2004 Ulf Schenk + * + * $Id$ + ******************************************/ + +#include "qdom.h" + +//US #ifndef QT_NO_DOM + +#include "qxml.h" +#include "qmap.h" +#include "qtextstream.h" +#include "qiodevice.h" +#include "qpixmap.h" + +#include +#include + +#if defined(_OS_LINUX_) +# if defined(__alpha__) || defined(__alpha) +# define Q_BROKEN_ALPHA +# endif +#endif + +// template class QDict; + +// NOT REVISED + +/** + * TODO: + * If the document dies, remove all pointers to it from children + * which can not be deleted at this time. + * + * If a node dies and has direct children which can not be deleted, + * then remove the pointer to the parent. + * + * Handle QDomDocumentFragment on insertion correctly. + * + * createElement and friends create double reference counts. + */ + +/** + * Reference counting: + * + * Some simple rules: + * 1) If an intern object returns a pointer to another intern object + * then the reference count of the returned object is not increased. + * 2) If an extern object is created and gets a pointer to some intern + * object, then the extern object increases the intern objects reference count. + * 3) If an extern object is deleted, then it decreases the reference count + * on its associated intern object and deletes it if nobody else hold references + * on the intern object. + */ + +/************************************************************** + * + * QDOMHandler + * + **************************************************************/ + +class QDomHandler : public QXmlDefaultHandler +{ +public: + QDomHandler( QDOM_DocumentPrivate* d ); + ~QDomHandler(); + + // content handler + void setDocumentLocator( QXmlLocator* locator ); + bool endDocument(); + bool startElement( const QString& namespaceURI, const QString& localName, const QString& qName, const QXmlAttributes& atts ); + bool endElement( const QString& namespaceURI, const QString& localName, const QString& qName ); + bool characters( const QString& ch ); + bool processingInstruction( const QString& target, const QString& data ); + + // error handler + bool fatalError( const QXmlParseException& exception ); + + // lexical handler + bool startCDATA(); + bool endCDATA(); + bool startDTD( const QString& name, const QString&, const QString& ); + bool comment( const QString& ch ); + + // decl handler + bool externalEntityDecl( const QString &name, const QString &publicId, const QString &systemId ) ; + + // DTD handler + bool notationDecl( const QString & name, const QString & publicId, const QString & systemId ); + bool unparsedEntityDecl( const QString &name, const QString &publicId, const QString &systemId, const QString ¬ationName ) ; + +private: + QXmlLocator* loc; + QDOM_DocumentPrivate* doc; + QDOM_NodePrivate* node; + bool cdata; +}; + +/*==============================================================*/ +/* Implementation */ +/*==============================================================*/ + +/************************************************************** + * + * QDOM_ImplementationPrivate + * + **************************************************************/ + +class QDOM_ImplementationPrivate : public QShared +{ +public: + QDOM_ImplementationPrivate(); + ~QDOM_ImplementationPrivate(); + + QDOM_ImplementationPrivate* clone(); + +}; + +QDOM_ImplementationPrivate::QDOM_ImplementationPrivate() +{ +} + +QDOM_ImplementationPrivate::~QDOM_ImplementationPrivate() +{ +} + +QDOM_ImplementationPrivate* QDOM_ImplementationPrivate::clone() +{ + QDOM_ImplementationPrivate* p = new QDOM_ImplementationPrivate; + // We are not interested in this node + p->deref(); + return p; +} + +/************************************************************** + * + * QDomImplementation + * + **************************************************************/ + +/*! + \class QDomImplementation qdom.h + \brief The QDomImplementation class provides information about the features + of the DOM implementation. + + \module XML + + This class describes the features that are supported by the DOM + implementation. Currently only the XML subset of DOM Level 1 is supported. + + Normally you will use the function QDomDocument::implementation() to get the + implementation object. + + For further information about the Document Objct Model see + http://www.w3.org/TR/REC-DOM-Level-1/. + For a more general introduction of the DOM implementation see the + QDomDocument documentation. + + \sa hasFeature() +*/ + +/*! + Constructs a QDomImplementation object. +*/ +QDomImplementation::QDomImplementation() +{ + impl = 0; +} + +/*! + Copy constructor. +*/ +QDomImplementation::QDomImplementation( const QDomImplementation& x ) +{ + impl = x.impl; + if ( impl ) + impl->ref(); +} + +/*! + \internal +*/ +QDomImplementation::QDomImplementation( QDOM_ImplementationPrivate* p ) +{ + // We want to be co-owners, so increase the reference count + impl = p; +} + +/*! + Assignment operator. +*/ +QDomImplementation& QDomImplementation::operator= ( const QDomImplementation& x ) +{ + if ( x.impl ) + x.impl->ref(); //avoid x=x + if ( impl && impl->deref() ) + delete impl; + impl = x.impl; + + return *this; +} + +/*! + Returns TRUE if both objects were created from the same QDomDocument. +*/ +bool QDomImplementation::operator==( const QDomImplementation& x ) const +{ + return ( impl == x.impl ); +} + +/*! + Returns TRUE if both objects were created from different QDomDocuments. +*/ +bool QDomImplementation::operator!=( const QDomImplementation& x ) const +{ + return ( impl != x.impl ); +} + +/*! + Destructor. +*/ +QDomImplementation::~QDomImplementation() +{ + if ( impl && impl->deref() ) + delete impl; +} + +/*! + The function returns TRUE if QDom implements the requested \a version of a \a + feature. + + Currently only the feature "XML" in version "1.0" is supported. +*/ +bool QDomImplementation::hasFeature( const QString& feature, const QString& version ) +{ + if ( feature == "XML" ) + if ( version.isEmpty() || version == "1.0" ) + return TRUE; + + return FALSE; +} + +/*! + Returns TRUE if the object was not created by QDomDocument::implementation(). +*/ +bool QDomImplementation::isNull() +{ + return ( impl == 0 ); +} + +/*==============================================================*/ +/* NodeList */ +/*==============================================================*/ + +/************************************************************** + * + * QDOM_NodeListPrivate + * + **************************************************************/ + +class QDOM_NodePrivate : public QShared +{ +public: + QDOM_NodePrivate( QDOM_DocumentPrivate*, QDOM_NodePrivate* parent = 0 ); + QDOM_NodePrivate( QDOM_NodePrivate* n, bool deep ); + virtual ~QDOM_NodePrivate(); + + QString nodeName() const { return name; } + QString nodeValue() const { return value; } + void setNodeValue( const QString& v ) { value = v; } + + QDOM_DocumentPrivate* ownerDocument(); + + virtual QDOM_NamedNodeMapPrivate* attributes(); + virtual QDOM_NodePrivate* insertBefore( QDOM_NodePrivate* newChild, QDOM_NodePrivate* refChild ); + virtual QDOM_NodePrivate* insertAfter( QDOM_NodePrivate* newChild, QDOM_NodePrivate* refChild ); + virtual QDOM_NodePrivate* replaceChild( QDOM_NodePrivate* newChild, QDOM_NodePrivate* oldChild ); + virtual QDOM_NodePrivate* removeChild( QDOM_NodePrivate* oldChild ); + virtual QDOM_NodePrivate* appendChild( QDOM_NodePrivate* newChild ); + + QDOM_NodePrivate* namedItem( const QString& name ); + + virtual QDOM_NodePrivate* cloneNode( bool deep = TRUE ); + virtual void clear(); + + void setParent( QDOM_NodePrivate* ); + + // Dynamic cast + virtual bool isAttr() { return FALSE; } + virtual bool isCDATASection() { return FALSE; } + virtual bool isDocumentFragment() { return FALSE; } + virtual bool isDocument() { return FALSE; } + virtual bool isDocumentType() { return FALSE; } + virtual bool isElement() { return FALSE; } + virtual bool isEntityReference() { return FALSE; } + virtual bool isText() { return FALSE; } + virtual bool isEntity() { return FALSE; } + virtual bool isNotation() { return FALSE; } + virtual bool isProcessingInstruction() { return FALSE; } + virtual bool isCharacterData() { return FALSE; } + virtual bool isComment() { return FALSE; } + + virtual void save( QTextStream&, int ) const; + + // Variables + QDOM_NodePrivate* prev; + QDOM_NodePrivate* next; + QDOM_NodePrivate* parent; + QDOM_NodePrivate* first; + QDOM_NodePrivate* last; + + QString name; + QString value; +}; + +class QDOM_NodeListPrivate : public QShared +{ +public: + QDOM_NodeListPrivate( QDOM_NodePrivate* ); + QDOM_NodeListPrivate( QDOM_NodePrivate*, const QString& ); + virtual ~QDOM_NodeListPrivate(); + + virtual bool operator== ( const QDOM_NodeListPrivate& ) const; + virtual bool operator!= ( const QDOM_NodeListPrivate& ) const; + + virtual QDOM_NodePrivate* item( int index ); + virtual uint length() const; + + QDOM_NodePrivate* node_impl; + QString tagname; +}; + +QDOM_NodeListPrivate::QDOM_NodeListPrivate( QDOM_NodePrivate* n_impl ) +{ + node_impl = n_impl; + if ( node_impl ) + node_impl->ref(); +} + +QDOM_NodeListPrivate::QDOM_NodeListPrivate( QDOM_NodePrivate* n_impl, const QString& name ) +{ + node_impl = n_impl; + if ( node_impl ) + node_impl->ref(); + tagname = name; +} + +QDOM_NodeListPrivate::~QDOM_NodeListPrivate() +{ + if ( node_impl && node_impl->deref() ) + delete node_impl; +} + +bool QDOM_NodeListPrivate::operator== ( const QDOM_NodeListPrivate& other ) const +{ + return ( node_impl == other.node_impl ) && ( tagname == other.tagname ) ; +} + +bool QDOM_NodeListPrivate::operator!= ( const QDOM_NodeListPrivate& other ) const +{ + return ( node_impl != other.node_impl ) || ( tagname != other.tagname ) ; +} + +QDOM_NodePrivate* QDOM_NodeListPrivate::item( int index ) +{ + if ( !node_impl ) + return 0; + QDOM_NodePrivate* p = node_impl->first; + int i = 0; + if ( tagname.isNull() ) { + while ( i < index && p ) { + p = p->next; + ++i; + } + } else { + while ( p && p != node_impl ) { + if ( p->isElement() && p->nodeName() == tagname ) { + if ( i == index ) + break; + ++i; + } + if ( p->first ) + p = p->first; + else if ( p->next ) + p = p->next; + else { + p = p->parent; + while ( p && p != node_impl && !p->next ) + p = p->parent; + if ( p && p != node_impl ) + p = p->next; + } + } + } + + return p; +} + +uint QDOM_NodeListPrivate::length() const +{ + if ( !node_impl ) + return 0; + uint i = 0; + QDOM_NodePrivate* p = node_impl->first; + if ( tagname.isNull() ) { + while ( p ) { + p = p->next; + ++i; + } + } else { + while ( p && p != node_impl ) { + if ( p->isElement() && p->nodeName() == tagname ) + ++i; + + if ( p->first ) + p = p->first; + else if ( p->next ) + p = p->next; + else { + p = p->parent; + while ( p && p != node_impl && !p->next ) + p = p->parent; + if ( p && p != node_impl ) + p = p->next; + } + } + } + return i; +} + +/************************************************************** + * + * QDomNodeList + * + **************************************************************/ + +/*! + \class QDomNodeList qdom.h + \brief The QDomNodeList class is a list of QDomNode objects. + + \module XML + + Lists can be obtained by QDomDocument::elementsByTagName() and + QDomNode::childNodes(). The Document Object Model (DOM) requires these lists + to be "live": whenever you change the underlying document, the contents of + the list will get updated. + + For further information about the Document Objct Model see + http://www.w3.org/TR/REC-DOM-Level-1/. + For a more general introduction of the DOM implementation see the + QDomDocument documentation. + + \sa QDomNode::childNode() QDomDocument::elementsByTagName() +*/ + +/*! + Creates an empty node list. +*/ +QDomNodeList::QDomNodeList() +{ + impl = 0; +} + +/*! \internal +*/ +QDomNodeList::QDomNodeList( QDOM_NodeListPrivate* p ) +{ + impl = p; +} + +/*! + Copy constructor. +*/ +QDomNodeList::QDomNodeList( const QDomNodeList& n ) +{ + impl = n.impl; + if ( impl ) + impl->ref(); +} + +/*! + Assigns another node list to this object. +*/ +QDomNodeList& QDomNodeList::operator= ( const QDomNodeList& n ) +{ + if ( n.impl ) + n.impl->ref(); + if ( impl && impl->deref() ) + delete impl; + impl = n.impl; + + return *this; +} + +/*! + Returns TRUE if both lists are equal, otherwise FALSE. +*/ +bool QDomNodeList::operator== ( const QDomNodeList& n ) const +{ + if ( impl == n.impl ) + return TRUE; + if ( !impl || !n.impl ) + return FALSE; + return (*impl == *n.impl); +} + +/*! + Returns TRUE if both lists are not equal, otherwise FALSE. +*/ +bool QDomNodeList::operator!= ( const QDomNodeList& n ) const +{ + return !operator==(n); +} + +/*! + Destructor. +*/ +QDomNodeList::~QDomNodeList() +{ + if ( impl && impl->deref() ) + delete impl; +} + +/*! + Returns the node at position \a index. + + If \a index is negative or if \a index >= length() then a null node is + returned (i.e. a node for which QDomNode::isNull() returns TRUE). +*/ +QDomNode QDomNodeList::item( int index ) const +{ + if ( !impl ) + return QDomNode(); + + return QDomNode( impl->item( index ) ); +} + +/*! + Returns the number of nodes in the list. + + This function is the same as count(). +*/ +uint QDomNodeList::length() const +{ + if ( !impl ) + return 0; + return impl->length(); +} + +/*! + \fn uint QDomNodeList::count() const + + Returns the number of nodes in the list. + + This function is the same as length(). +*/ + + +/*==============================================================*/ +/*==============================================================*/ + +/************************************************************** + * + * QDOM_NodePrivate + * + **************************************************************/ + +QDOM_NodePrivate::QDOM_NodePrivate( QDOM_DocumentPrivate* /* qd */, QDOM_NodePrivate *par ) +{ + parent = par; + prev = 0; + next = 0; + first = 0; + last = 0; +} + +QDOM_NodePrivate::QDOM_NodePrivate( QDOM_NodePrivate* n, bool deep ) +{ + parent = 0; + prev = 0; + next = 0; + first = 0; + last = 0; + + name = n->name; + value = n->value; + + if ( !deep ) + return; + + for ( QDOM_NodePrivate* x = n->first; x; x = x->next ) + appendChild( x->cloneNode( TRUE ) ); +} + +QDOM_NodePrivate::~QDOM_NodePrivate() +{ + QDOM_NodePrivate* p = first; + QDOM_NodePrivate* n; + + while ( p ) { + n = p->next; + if ( p->deref() ) + delete p; + else + p->parent = 0; + p = n; + } + + first = 0; + last = 0; +} + +void QDOM_NodePrivate::clear() +{ + QDOM_NodePrivate* p = first; + QDOM_NodePrivate* n; + + while ( p ) { + n = p->next; + if ( p->deref() ) + delete p; + p = n; + } + + first = 0; + last = 0; +} + +QDOM_NodePrivate* QDOM_NodePrivate::namedItem( const QString& n ) +{ + QDOM_NodePrivate* p = first; + while ( p ) { + if ( p->nodeName() == n ) + return p; + p = p->next; + } + + return 0; +} + +QDOM_NamedNodeMapPrivate* QDOM_NodePrivate::attributes() +{ + return 0; +} + +QDOM_NodePrivate* QDOM_NodePrivate::insertBefore( QDOM_NodePrivate* newChild, QDOM_NodePrivate* refChild ) +{ + // Error check + if ( !newChild ) + return 0; + + // Error check + if ( newChild == refChild ) + return 0; + + // Error check + if ( refChild && refChild->parent != this ) + return 0; + + // Special handling for inserting a fragment. We just insert + // all elements of the fragment instead of the fragment itself. + if ( newChild->isDocumentFragment() ) { + // Fragment is empty ? + if ( newChild->first == 0 ) + return newChild; + + // New parent + QDOM_NodePrivate* n = newChild->first; + while ( n ) { + n->parent = this; + n = n->next; + } + + // Insert at the beginning ? + if ( !refChild || refChild->prev == 0 ) { + if ( first ) + first->prev = newChild->last; + newChild->last->next = first; + if ( !last ) + last = newChild->last; + first = newChild->first; + } else {// Insert in the middle + newChild->last->next = refChild; + newChild->first->prev = refChild->prev; + refChild->prev->next = newChild->first; + refChild->prev = newChild->last; + } + + // No need to increase the reference since QDomDocumentFragment + // does not decrease the reference. + + // Remove the nodes from the fragment + newChild->first = 0; + newChild->last = 0; + return newChild; + } + + // No more errors can occure now, so we take + // ownership of the node. + newChild->ref(); + + if ( newChild->parent ) + newChild->parent->removeChild( newChild ); + + newChild->parent = this; + + if ( !refChild ) { + if ( first ) + first->prev = newChild; + newChild->next = first; + if ( !last ) + last = newChild; + first = newChild; + return newChild; + } + + if ( refChild->prev == 0 ) { + if ( first ) + first->prev = newChild; + newChild->next = first; + if ( !last ) + last = newChild; + first = newChild; + return newChild; + } + + newChild->next = refChild; + newChild->prev = refChild->prev; + refChild->prev->next = newChild; + refChild->prev = newChild; + + return newChild; +} + +QDOM_NodePrivate* QDOM_NodePrivate::insertAfter( QDOM_NodePrivate* newChild, QDOM_NodePrivate* refChild ) +{ + // Error check + if ( !newChild ) + return 0; + + // Error check + if ( newChild == refChild ) + return 0; + + // Error check + if ( refChild && refChild->parent != this ) + return 0; + + // Special handling for inserting a fragment. We just insert + // all elements of the fragment instead of the fragment itself. + if ( newChild->isDocumentFragment() ) { + // Fragment is empty ? + if ( newChild->first == 0 ) + return newChild; + + // New parent + QDOM_NodePrivate* n = newChild->first; + while ( n ) { + n->parent = this; + n = n->next; + } + + // Insert at the end + if ( !refChild || refChild->next == 0 ) { + if ( last ) + last->next = newChild->first; + newChild->first->prev = last; + if ( !first ) + first = newChild->first; + last = newChild->last; + } else { // Insert in the middle + newChild->first->prev = refChild; + newChild->last->next = refChild->next; + refChild->next->prev = newChild->last; + refChild->next = newChild->first; + } + + // No need to increase the reference since QDomDocumentFragment + // does not decrease the reference. + + // Remove the nodes from the fragment + newChild->first = 0; + newChild->last = 0; + return newChild; + } + + // Release new node from its current parent + if ( newChild->parent ) + newChild->parent->removeChild( newChild ); + + // No more errors can occure now, so we take + // ownership of the node + newChild->ref(); + + newChild->parent = this; + + // Insert at the end + if ( !refChild ) { + if ( last ) + last->next = newChild; + newChild->prev = last; + if ( !first ) + first = newChild; + last = newChild; + return newChild; + } + + if ( refChild->next == 0 ) { + if ( last ) + last->next = newChild; + newChild->prev = last; + if ( !first ) + first = newChild; + last = newChild; + return newChild; + } + + newChild->prev = refChild; + newChild->next = refChild->next; + refChild->next->prev = newChild; + refChild->next = newChild; + + return newChild; +} + +QDOM_NodePrivate* QDOM_NodePrivate::replaceChild( QDOM_NodePrivate* newChild, QDOM_NodePrivate* oldChild ) +{ + // Error check + if ( oldChild->parent != this ) + return 0; + + // Error check + if ( !newChild || !oldChild ) + return 0; + + // Error check + if ( newChild == oldChild ) + return 0; + + // Special handling for inserting a fragment. We just insert + // all elements of the fragment instead of the fragment itself. + if ( newChild->isDocumentFragment() ) { + // Fragment is empty ? + if ( newChild->first == 0 ) + return newChild; + + // New parent + QDOM_NodePrivate* n = newChild->first; + while ( n ) { + n->parent = this; + n = n->next; + } + + + if ( oldChild->next ) + oldChild->next->prev = newChild->last; + if ( oldChild->prev ) + oldChild->prev->next = newChild->first; + + newChild->last->next = oldChild->next; + newChild->first->prev = oldChild->prev; + + if ( first == oldChild ) + first = newChild->first; + if ( last == oldChild ) + last = newChild->last; + + oldChild->parent = 0; + oldChild->next = 0; + oldChild->prev = 0; + + // No need to increase the reference since QDomDocumentFragment + // does not decrease the reference. + + // Remove the nodes from the fragment + newChild->first = 0; + newChild->last = 0; + + // We are no longer interested in the old node + if ( oldChild ) oldChild->deref(); + + return oldChild; + } + + // No more errors can occure now, so we take + // ownership of the node + newChild->ref(); + + // Release new node from its current parent + if ( newChild->parent ) + newChild->parent->removeChild( newChild ); + + newChild->parent = this; + + if ( oldChild->next ) + oldChild->next->prev = newChild; + if ( oldChild->prev ) + oldChild->prev->next = newChild; + + newChild->next = oldChild->next; + newChild->prev = oldChild->prev; + + if ( first == oldChild ) + first = newChild; + if ( last == oldChild ) + last = newChild; + + oldChild->parent = 0; + oldChild->next = 0; + oldChild->prev = 0; + + // We are no longer interested in the old node + if ( oldChild ) oldChild->deref(); + + return oldChild; +} + +QDOM_NodePrivate* QDOM_NodePrivate::removeChild( QDOM_NodePrivate* oldChild ) +{ + // Error check + if ( oldChild->parent != this ) + return 0; + + // Perhaps oldChild was just created with "createElement" or that. In this case + // its parent is QDomDocument but it is not part of the documents child list. + if ( oldChild->next == 0 && oldChild->prev == 0 && first != oldChild ) + return 0; + + if ( oldChild->next ) + oldChild->next->prev = oldChild->prev; + if ( oldChild->prev ) + oldChild->prev->next = oldChild->next; + + if ( last == oldChild ) + last = oldChild->prev; + if ( first == oldChild ) + first = oldChild->next; + + oldChild->parent = 0; + oldChild->next = 0; + oldChild->prev = 0; + + // We are no longer interested in the old node + if ( oldChild ) oldChild->deref(); + + return oldChild; +} + +QDOM_NodePrivate* QDOM_NodePrivate::appendChild( QDOM_NodePrivate* newChild ) +{ + // No reference manipulation needed. Done in insertAfter. + return insertAfter( newChild, 0 ); +} + +void QDOM_NodePrivate::setParent( QDOM_NodePrivate* n ) +{ + // Dont take over ownership of our parent :-) + parent = n; +} + +QDOM_DocumentPrivate* QDOM_NodePrivate::ownerDocument() +{ + QDOM_NodePrivate* p = this; + while ( p && !p->isDocument() ) + p = p->parent; + + return (QDOM_DocumentPrivate*)p; +} + +QDOM_NodePrivate* QDOM_NodePrivate::cloneNode( bool deep ) +{ + QDOM_NodePrivate* p = new QDOM_NodePrivate( this, deep ); + // We are not interested in this node + p->deref(); + return p; +} + +void QDOM_NodePrivate::save( QTextStream& s, int indent ) const +{ + const QDOM_NodePrivate* n = first; + while ( n ) { + n->save( s, indent ); + n = n->next; + } +} + +/************************************************************** + * + * QDomNode + * + **************************************************************/ + +#define IMPL ((QDOM_NodePrivate*)impl) + +/*! + \class QDomNode qdom.h + \brief The QDomNode class is the base class for all nodes of the DOM tree. + + \module XML + + This class is the base class for almost all other classes in the DOM. Many + functions in the DOM return a QDomNode. The various isXxx() functions are + useful to find out the type of the node. A QDomNode can be converted to a + subclass by using the toXxx() function family. + + Copies of the QDomNode class share their data; this means modifying one will + change all copies. This is especially useful in combination with functions + which return a QDomNode, e.g. firstChild(). You can make an independent copy + of the node with cloneNode(). + + The following example looks for the first element in an XML document and + prints its name: + \code + QDomDocument d; + d.setContent( someXML ); + QDomNode n = d.firstChild(); + while ( !n.isNull() ) { + if ( n.isElement ) { + QDomElement e = n.toElement(); + cout << "The name of the element is " << e.tagName() << endl; + return; + } + n = n.nextSibling(); + } + cout << "no element in the Document" << endl; + \endcode + + For further information about the Document Objct Model see + http://www.w3.org/TR/REC-DOM-Level-1/. + For a more general introduction of the DOM implementation see the + QDomDocument documentation. +*/ + +/*! + Constructs an empty node. +*/ +QDomNode::QDomNode() +{ + impl = 0; +} + +/*! + Copy constructor. + + The data of the copy is shared: modifying one will also change the other. If + you want to make a real copy, use cloneNode() instead. +*/ +QDomNode::QDomNode( const QDomNode& n ) +{ + impl = n.impl; + if ( impl ) impl->ref(); +} + +/*! + \internal +*/ +QDomNode::QDomNode( QDOM_NodePrivate* n ) +{ + impl = n; + if ( impl ) impl->ref(); +} + +/*! + Assignment operator. + + The data of the copy is shared: modifying one will also change the other. If + you want to make a real copy, use cloneNode() instead. +*/ +QDomNode& QDomNode::operator= ( const QDomNode& n ) +{ + if ( n.impl ) n.impl->ref(); + if ( impl && impl->deref() ) delete impl; + impl = n.impl; + + return *this; +} + +/*! + Returns TRUE if the two nodes are equal, otherwise FALSE. +*/ +bool QDomNode::operator== ( const QDomNode& n ) const +{ + return ( impl == n.impl ); +} + +/*! + Returns TRUE if the two nodes are not equal, otherwise FALSE. +*/ +bool QDomNode::operator!= ( const QDomNode& n ) const +{ + return ( impl != n.impl ); +} + +/*! + Destructor. +*/ +QDomNode::~QDomNode() +{ + if ( impl && impl->deref() ) delete impl; +} + +/*! + Returns the name of the node. + + The meaning of the name depends on the subclass: + +
    +
  • QDomElement - the tag name +
  • QDomAttr - the name of the attribute +
  • QDomText - the string "#text" +
  • QDomCDATASection - the string "#cdata-section" +
  • QDomEntityReference - the name of the referenced entity +
  • QDomEntity - the name of the entity +
  • QDomProcessingInstruction - the target of the processing instruction +
  • QDomDocument - the string "#document" +
  • QDomComment - the string "#comment" +
  • QDomDocumentType - the name of the document type +
  • QDomDocumentFragment - the string "#document-fragment" +
  • QDomNotation - the name of the notation +
+ + \sa nodeValue() +*/ +QString QDomNode::nodeName() const +{ + if ( !impl ) + return QString::null; + return IMPL->name; +} + +/*! + Returns the value of the node. + + The meaning of the value depends on the subclass: + +
    +
  • QDomAttr - the attribute value +
  • QDomText - the text +
  • QDomCDATASection - the content of the CDATA section +
  • QDomProcessingInstruction - the data of the processing intruction +
  • QDomComment - the comment +
+ + All other subclasses not listed above do not have a node value. These classes + will return a null string. + + \sa setNodeValue() nodeName() +*/ +QString QDomNode::nodeValue() const +{ + if ( !impl ) + return QString::null; + return IMPL->value; +} + +/*! + Sets the value of the node to \a v. + + \sa nodeValue() +*/ +void QDomNode::setNodeValue( const QString& v ) +{ + if ( !impl ) + return; + IMPL->setNodeValue( v ); +} + +/*! + Returns the type of the node. + + \sa toAttr() toCDATASection() toDocumentFragment() toDocument() + toDocumentType() toElement() toEntityReference() toText() toEntity() + toNotation() toProcessingInstruction() toCharacterData() toComment() +*/ +QDomNode::NodeType QDomNode::nodeType() const +{ + // not very efficient, but will do for the moment. + if( isCDATASection() ) + return CDATASectionNode; + if ( isText() ) + return TextNode; + if ( isComment() ) + return CommentNode; + if ( isCharacterData() ) + return CharacterDataNode; + if( isAttr() ) + return AttributeNode; + if( isElement() ) + return ElementNode; + if (isEntityReference() ) + return EntityReferenceNode; + if ( isEntity() ) + return EntityNode; + if (isNotation() ) + return NotationNode; + if ( isProcessingInstruction() ) + return ProcessingInstructionNode; + if( isDocumentFragment() ) + return DocumentFragmentNode; + if( isDocument() ) + return DocumentNode; + if( isDocumentType() ) + return DocumentTypeNode; + + return QDomNode::BaseNode; +} + +/*! + Returns the parent node, If this node has no parent, then a null node is + returned (i.e. a node for which isNull() returns TRUE). +*/ +QDomNode QDomNode::parentNode() const +{ + if ( !impl ) + return QDomNode(); + return QDomNode( IMPL->parent ); +} + +/*! + Returns a list of all child nodes. + + Most often you will call this function on a QDomElement object. + If the XML document looks like this: + + \code + +

Heading

+

Hallo you

+ + \endcode + + Then the list of child nodes for the "body"-element will contain the node + created by the <h1> tag and the node created by the <p> tag. + + The nodes in the list are not copied; so changing the nodes in the list will + also change the children of this node. + + \sa firstChild() lastChild() +*/ +QDomNodeList QDomNode::childNodes() const +{ + if ( !impl ) + return QDomNodeList(); + return QDomNodeList( new QDOM_NodeListPrivate( impl ) ); +} + +/*! + Returns the first child of the node. If there is no child node, a null node + is returned. + + \sa lastChild() childNodes() +*/ +QDomNode QDomNode::firstChild() const +{ + if ( !impl ) + return QDomNode(); + return QDomNode( IMPL->first ); +} + +/*! + Returns the last child of the node. If there is no child node then a null + node is returned. + + \sa firstChild() childNodes() +*/ +QDomNode QDomNode::lastChild() const +{ + if ( !impl ) + return QDomNode(); + return QDomNode( IMPL->last ); +} + +/*! + Returns the previous sibling in the document tree. Changing the returned node + will also change the node in the document tree. + + If you have XML like this: + \code +

Heading

+

The text...

+

Next heading

+ \endcode + + and this QDomNode represents the <p> tag, the previousSibling + will return the node representing the <h1> tag. + + \sa nextSibling() +*/ +QDomNode QDomNode::previousSibling() const +{ + if ( !impl ) + return QDomNode(); + return QDomNode( IMPL->prev ); +} + +/*! + Returns the next sibling in the document tree. Changing the returned node + will also change the node in the document tree. + + If you have XML like this: + \code +

Heading

+

The text...

+

Next heading

+ \endcode + + and this QDomNode represents the <p> tag, the nextSibling + will return the node representing the <h2> tag. + + \sa previousSibling() +*/ +QDomNode QDomNode::nextSibling() const +{ + if ( !impl ) + return QDomNode(); + return QDomNode( IMPL->next ); +} + +/*! + Returns a map of all attributes. Attributes are only provided for + QDomElement. + + Changing the attributes in the map will also change the attributes of this + QDomNode. +*/ +QDomNamedNodeMap QDomNode::attributes() const +{ + if ( !impl ) + return QDomNamedNodeMap(); + + return QDomNamedNodeMap( impl->attributes() ); +} + +/*! + Returns the document to which this node belongs. +*/ +QDomDocument QDomNode::ownerDocument() const +{ + if ( !impl ) + return QDomDocument(); + return QDomDocument( IMPL->ownerDocument() ); +} + +/*! + Creates a real copy of the QDomNode. + + If \a deep is TRUE, then the cloning is done recursive. + That means all children are copied, too. Otherwise the cloned + node does not contain child nodes. +*/ +QDomNode QDomNode::cloneNode( bool deep ) const +{ + if ( !impl ) + return QDomNode(); + return QDomNode( IMPL->cloneNode( deep ) ); +} + +/*! + Inserts the node \a newChild before the child node \a refChild. \a refChild + has to be a direct child of this node. If \a refChild is null then \a + newChild is inserted as first child. + + If \a newChild is currently child of another parent, then it is reparented. + If \a newChild is currently a child of this QDomNode, then its position in + the list of children is changed. + + If \a newChild is a QDomDocumentFragment, then the children of the fragment + are removed from the fragment and inserted after \a refChild. + + Returns a new reference to \a newChild on success or an empty node on + failure. + + \sa insertAfter() replaceChild() removeChild() appendChild() +*/ +QDomNode QDomNode::insertBefore( const QDomNode& newChild, const QDomNode& refChild ) +{ + if ( !impl ) + return QDomNode(); + return QDomNode( IMPL->insertBefore( newChild.impl, refChild.impl ) ); +} + +/*! + Inserts the node \a newChild after the child node \a refChild. \a refChild + has to be a direct child of this node. If \a refChild is null then \a + newChild is appended as last child. + + If \a newChild is currently child of another parent, then it is reparented. + If \a newChild is currently a child of this QDomNode, then its position in + the list of children is changed. + + If \a newChild is a QDomDocumentFragment, then the children of the fragment + are removed from the fragment and inserted after \a refChild. + + Returns a new reference to \a newChild on success or an empty node on failure. + + \sa insertBefore() replaceChild() removeChild() appendChild() +*/ +QDomNode QDomNode::insertAfter( const QDomNode& newChild, const QDomNode& refChild ) +{ + if ( !impl ) + return QDomNode(); + return QDomNode( IMPL->insertAfter( newChild.impl, refChild.impl ) ); +} + +/*! + Replaces \a oldChild with \a newChild. \a oldChild has to be a direct child + of this node. + + If \a newChild is currently child of another parent, then it is reparented. + If \a newChild is currently a child of this QDomNode, then its position in + the list of children is changed. + + If \a newChild is a QDomDocumentFragment, then the children of the fragment + are removed from the fragment and inserted after \a refChild. + + Returns a new reference to \a oldChild on success or a null node an failure. + + \sa insertBefore() insertAfter() removeChild() appendChild() +*/ +QDomNode QDomNode::replaceChild( const QDomNode& newChild, const QDomNode& oldChild ) +{ + if ( !impl ) + return QDomNode(); + return QDomNode( IMPL->replaceChild( newChild.impl, oldChild.impl ) ); +} + +/*! + Removes \a oldChild from the list of children. + \a oldChild has to be a direct child of this node. + + Returns a new reference to \a oldChild on success or a null node on failure. + + \sa insertBefore() insertAfter() replaceChild() appendChild() +*/ +QDomNode QDomNode::removeChild( const QDomNode& oldChild ) +{ + if ( !impl ) + return QDomNode(); + + if ( oldChild.isNull() ) + return QDomNode(); + + return QDomNode( IMPL->removeChild( oldChild.impl ) ); +} + +/*! + Appends \a newChild to the end of the children list. + + If \a newChild is currently child of another parent, then it is reparented. + If \a newChild is currently a child of this QDomNode, then its position in + the list of children is changed. + + Returns a new reference to \a newChild. + + \sa insertBefore() insertAfter() replaceChild() removeChild() +*/ +QDomNode QDomNode::appendChild( const QDomNode& newChild ) +{ + if ( !impl ) + return QDomNode(); + return QDomNode( IMPL->appendChild( newChild.impl ) ); +} + +/*! + Returns TRUE if this node does not reference any internal object, otherwise + FALSE. +*/ +bool QDomNode::isNull() const +{ + return ( impl == 0 ); +} + +/*! + Dereferences the internal object. The node is then a null node. + + \sa isNull() +*/ +void QDomNode::clear() +{ + if ( impl && impl->deref() ) delete impl; + impl = 0; +} + +/*! + Returns the first child node for which nodeName() equals \a name. + + If no such direct child exists, a null node is returned. + + \sa nodeName() +*/ +QDomNode QDomNode::namedItem( const QString& name ) const +{ + if ( !impl ) + return QDomNode(); + return QDomNode( impl->namedItem( name ) ); +} + +/*! + Writes the XML representation of the node including all its children + on the stream. +*/ +void QDomNode::save( QTextStream& str, int indent ) const +{ + if ( impl ) + IMPL->save( str, indent ); +} + +/*! + Writes the XML representation of the node including all its children + on the stream. +*/ +QTextStream& operator<<( QTextStream& str, const QDomNode& node ) +{ + node.save( str, 0 ); + + return str; +} + +/*! + Returns TRUE if the node is an attribute, otherwise FALSE. + + If this function returns TRUE, this does not imply that this object is + a QDomAttribute; you can get the QDomAttribute with toAttribute(). + + \sa toAttribute() +*/ +bool QDomNode::isAttr() const +{ + if(impl) + return impl->isAttr(); + return FALSE; +} + +/*! + Returns TRUE if the node is a CDATA section, otherwise FALSE. + + If this function returns TRUE, this does not imply that this object is + a QDomCDATASection; you can get the QDomCDATASection with toCDATASection(). + + \sa toCDATASection() +*/ +bool QDomNode::isCDATASection() const +{ + if(impl) + return impl->isCDATASection(); + return FALSE; +} + +/*! + Returns TRUE if the node is a document fragment, otherwise FALSE. + + If this function returns TRUE, this does not imply that this object is + a QDomDocumentFragment; you can get the QDomDocumentFragment with + toDocumentFragment(). + + \sa toDocumentFragment() +*/ +bool QDomNode::isDocumentFragment() const +{ + if(impl) + return impl->isDocumentFragment(); + return FALSE; +} + +/*! + Returns TRUE if the node is a document, otherwise FALSE. + + If this function returns TRUE, this does not imply that this object is + a QDomDocument; you can get the QDomDocument with toDocument(). + + \sa toDocument() +*/ +bool QDomNode::isDocument() const +{ + if(impl) + return impl->isDocument(); + return FALSE; +} + +/*! + Returns TRUE if the node is a document type, otherwise FALSE. + + If this function returns TRUE, this does not imply that this object is + a QDomDocumentType; you can get the QDomDocumentType with toDocumentType(). + + \sa toDocumentType() +*/ +bool QDomNode::isDocumentType() const +{ + if(impl) + return impl->isDocumentType(); + return FALSE; +} + +/*! + Returns TRUE if the node is an element, otherwise FALSE. + + If this function returns TRUE, this does not imply that this object is + a QDomElement; you can get the QDomElement with toElement(). + + \sa toElement() +*/ +bool QDomNode::isElement() const +{ + if(impl) + return impl->isElement(); + return FALSE; +} + +/*! + Returns TRUE if the node is an entity reference, otherwise FALSE. + + If this function returns TRUE, this does not imply that this object is + a QDomEntityReference; you can get the QDomEntityReference with + toEntityReference(). + + \sa toEntityReference() +*/ +bool QDomNode::isEntityReference() const +{ + if(impl) + return impl->isEntityReference(); + return FALSE; +} + +/*! + Returns TRUE if the node is a text, otherwise FALSE. + + If this function returns TRUE, this does not imply that this object is + a QDomText; you can get the QDomText with toText(). + + \sa toText() +*/ +bool QDomNode::isText() const +{ + if(impl) + return impl->isText(); + return FALSE; +} + +/*! + Returns TRUE if the node is an entity, otherwise FALSE. + + If this function returns TRUE, this does not imply that this object is + a QDomEntity; you can get the QDomEntity with toEntity(). + + \sa toEntity() +*/ +bool QDomNode::isEntity() const +{ + if(impl) + return impl->isEntity(); + return FALSE; +} + +/*! + Returns TRUE if the node is a notation, otherwise FALSE. + + If this function returns TRUE, this does not imply that this object is + a QDomNotation; you can get the QDomNotation with toNotation(). + + \sa toNotation() +*/ +bool QDomNode::isNotation() const +{ + if(impl) + return impl->isNotation(); + return FALSE; +} + +/*! + Returns TRUE if the node is a processing instruction, otherwise FALSE. + + If this function returns TRUE, this does not imply that this object is + a QDomProcessingInstruction; you can get the QProcessingInstruction with + toProcessingInstruction(). + + \sa toProcessingInstruction() +*/ +bool QDomNode::isProcessingInstruction() const +{ + if(impl) + return impl->isProcessingInstruction(); + return FALSE; +} + +/*! + Returns TRUE if the node is a character data node, otherwise FALSE. + + If this function returns TRUE, this does not imply that this object is + a QDomCharacterData; you can get the QDomCharacterData with + toCharacterData(). + + \sa toCharacterData() +*/ +bool QDomNode::isCharacterData() const +{ + if(impl) + return impl->isCharacterData(); + return FALSE; +} + +/*! + Returns TRUE if the node is a comment, otherwise FALSE. + + If this function returns TRUE, this does not imply that this object is + a QDomComment; you can get the QDomComment with toComment(). + + \sa toComment() +*/ +bool QDomNode::isComment() const +{ + if(impl) + return impl->isComment(); + return FALSE; +} + +#undef IMPL + +/*==============================================================*/ +/* NamedNodeMap */ +/*==============================================================*/ + +/************************************************************** + * + * QDOM_NamedNodeMapPrivate + * + **************************************************************/ + +class QDOM_NamedNodeMapPrivate : public QShared +{ +public: + QDOM_NamedNodeMapPrivate( QDOM_NodePrivate* ); + ~QDOM_NamedNodeMapPrivate(); + + QDOM_NodePrivate* namedItem( const QString& name ) const; + QDOM_NodePrivate* setNamedItem( QDOM_NodePrivate* arg ); + QDOM_NodePrivate* removeNamedItem( const QString& name ); + QDOM_NodePrivate* item( int index ) const; + uint length() const; + bool contains( const QString& name ) const; + + /** + * Remove all children from the map. + */ + void clearMap(); + bool isReadOnly() { return readonly; } + void setReadOnly( bool r ) { readonly = r; } + bool isAppendToParent() { return appendToParent; } + /** + * If TRUE, then the node will redirect insert/remove calls + * to its parent by calling QDOM_NodePrivate::appendChild or removeChild. + * In addition the map wont increase or decrease the reference count + * of the nodes it contains. + * + * By default this value is FALSE and the map will handle reference counting + * by itself. + */ + void setAppendToParent( bool b ) { appendToParent = b; } + + /** + * Creates a copy of the map. It is a deep copy + * that means that all children are cloned. + */ + QDOM_NamedNodeMapPrivate* clone( QDOM_NodePrivate* parent ); + + // Variables + QDict map; + QDOM_NodePrivate* parent; + bool readonly; + bool appendToParent; +}; + +QDOM_NamedNodeMapPrivate::QDOM_NamedNodeMapPrivate( QDOM_NodePrivate* n ) +{ + readonly = FALSE; + parent = n; + appendToParent = FALSE; +} + +QDOM_NamedNodeMapPrivate::~QDOM_NamedNodeMapPrivate() +{ + clearMap(); +} + +QDOM_NamedNodeMapPrivate* QDOM_NamedNodeMapPrivate::clone( QDOM_NodePrivate* p ) +{ + QDOM_NamedNodeMapPrivate* m = new QDOM_NamedNodeMapPrivate( p ); + m->readonly = readonly; + m->appendToParent = appendToParent; + + QDictIterator it ( map ); + for ( ; it.current(); ++it ) + m->setNamedItem( it.current()->cloneNode() ); + + // we are no longer interested in ownership + m->deref(); + return m; +} + +void QDOM_NamedNodeMapPrivate::clearMap() +{ + // Dereference all of our children if we took references + if ( !appendToParent ) { + QDictIterator it( map ); + for ( ; it.current(); ++it ) + if ( it.current()->deref() ) + delete it.current(); + } + + map.clear(); +} + +QDOM_NodePrivate* QDOM_NamedNodeMapPrivate::namedItem( const QString& name ) const +{ + QDOM_NodePrivate* p = map[ name ]; + return p; +} + +QDOM_NodePrivate* QDOM_NamedNodeMapPrivate::setNamedItem( QDOM_NodePrivate* arg ) +{ + if ( readonly || !arg ) + return 0; + + if ( appendToParent ) + return parent->appendChild( arg ); + + // We take a reference + arg->ref(); + map.insert( arg->nodeName(), arg ); + return arg; +} + +QDOM_NodePrivate* QDOM_NamedNodeMapPrivate::removeNamedItem( const QString& name ) +{ + if ( readonly ) + return 0; + + QDOM_NodePrivate* p = namedItem( name ); + if ( p == 0 ) + return 0; + if ( appendToParent ) + return parent->removeChild( p ); + + map.remove( p->nodeName() ); + // We took a reference, so we have to free one here + p->deref(); + return p; +} + +QDOM_NodePrivate* QDOM_NamedNodeMapPrivate::item( int index ) const +{ + if ( (uint)index >= length() ) + return 0; + + QDictIterator it( map ); + for ( int i = 0; i < index; ++i, ++it ) + ; + return it.current(); +} + +uint QDOM_NamedNodeMapPrivate::length() const +{ + return map.count(); +} + +bool QDOM_NamedNodeMapPrivate::contains( const QString& name ) const +{ + return ( map[ name ] != 0 ); +} + +/************************************************************** + * + * QDomNamedNodeMap + * + **************************************************************/ + +#define IMPL ((QDOM_NamedNodeMapPrivate*)impl) + +/*! + \class QDomNamedNodeMap qdom.h + \brief The QDomNamedNodeMap class contains a collection of nodes that can be + accessed by name. + + \module XML + + Note that QDomNamedNodeMap does not inherit from QDomNodeList; + QDomNamedNodeMaps does not provide any specific order of the nodes. Nodes + contained in a QDomNamedNodeMap may also be accessed by an ordinal index, but + this is simply to allow a convenient enumeration of the contents of a + QDomNamedNodeMap and does not imply that the DOM specifies an order on the + nodes. + + The QDomNamedNodeMap is used in three places: + +
    +
  • QDomDocumentType::entities() returns a map of all entities + described in the DTD. +
  • QDomDocumentType::notations() returns a map of all notations + described in the DTD. +
  • QDomElement::attributes() returns a map of all attributes of the + element. +
+ + Items in the map are identified by the name which QDomNode::name() returns. + They can be queried using the namedItem() function and set using + setNamedItem(). + + \sa namedItem() setNamedItem() +*/ + +/*! + Constructs an empty map. +*/ +QDomNamedNodeMap::QDomNamedNodeMap() +{ + impl = 0; +} + +/*! + Copy constructor. +*/ +QDomNamedNodeMap::QDomNamedNodeMap( const QDomNamedNodeMap& n ) +{ + impl = n.impl; + if ( impl ) + impl->ref(); +} + +/*! + \internal +*/ +QDomNamedNodeMap::QDomNamedNodeMap( QDOM_NamedNodeMapPrivate* n ) +{ + impl = n; + if ( impl ) + impl->ref(); +} + +/*! + Assignement operator. +*/ +QDomNamedNodeMap& QDomNamedNodeMap::operator= ( const QDomNamedNodeMap& n ) +{ + if ( impl && impl->deref() ) + delete impl; + impl = n.impl; + if ( impl ) + impl->ref(); + + return *this; +} + +/*! + Returns TRUE if the maps are equal, FALSE otherwise. +*/ +bool QDomNamedNodeMap::operator== ( const QDomNamedNodeMap& n ) const +{ + return ( impl == n.impl ); +} + +/*! + Returns TRUE if the maps are not equal, FALSE otherwise. +*/ +bool QDomNamedNodeMap::operator!= ( const QDomNamedNodeMap& n ) const +{ + return ( impl != n.impl ); +} + +/*! + Destructor. +*/ +QDomNamedNodeMap::~QDomNamedNodeMap() +{ + if ( impl && impl->deref() ) + delete impl; +} + +/*! + Returns the node associated with they key \a name. + + If the map does not contain such a node, then a null node is returned. + + \sa setNamedItem() +*/ +QDomNode QDomNamedNodeMap::namedItem( const QString& name ) const +{ + if ( !impl ) + return QDomNode(); + return QDomNode( IMPL->namedItem( name ) ); +} + +/*! + Inserts the node \a newNode in the map. The kye for the map is the name of \a + newNode as returned by QDomNode::nodeName(). + + The function returns the newly inserted node. + + \sa removeNamedItem() +*/ +QDomNode QDomNamedNodeMap::setNamedItem( const QDomNode& newNode ) +{ + if ( !impl ) + return QDomNode(); + return QDomNode( IMPL->setNamedItem( (QDOM_NodePrivate*)newNode.impl ) ); +} + +/*! + Removes the node with the name \a name from the map. + + The function returns the removed node or a null node + if the map did not contain a node with the name \a name. + + \sa setNamedItem() +*/ +QDomNode QDomNamedNodeMap::removeNamedItem( const QString& name ) +{ + if ( !impl ) + return QDomNode(); + return QDomNode( IMPL->removeNamedItem( name ) ); +} + +/*! + Retrieves the node at position \a index. + + This can be used to iterate over the map. + + \sa length() +*/ +QDomNode QDomNamedNodeMap::item( int index ) const +{ + if ( !impl ) + return QDomNode(); + return QDomNode( IMPL->item( index ) ); +} + +/*! + Returns the number of nodes in the map. + + \sa item() +*/ +uint QDomNamedNodeMap::length() const +{ + if ( !impl ) + return 0; + return IMPL->length(); +} + +/*! + Returns TRUE if the map contains a node with the name \a name, otherwise + FALSE. +*/ +bool QDomNamedNodeMap::contains( const QString& name ) const +{ + if ( !impl ) + return FALSE; + return IMPL->contains( name ); +} + +#undef IMPL + +/*==============================================================*/ +/*==============================================================*/ + +/************************************************************** + * + * QDOM_DocumentTypePrivate + * + **************************************************************/ + +class QDOM_DocumentTypePrivate : public QDOM_NodePrivate +{ +public: + QDOM_DocumentTypePrivate( QDOM_DocumentPrivate*, QDOM_NodePrivate* parent = 0 ); + QDOM_DocumentTypePrivate( QDOM_DocumentTypePrivate* n, bool deep ); + ~QDOM_DocumentTypePrivate(); + + // virtual QDOM_NamedNodeMapPrivate* entities(); + // virtual QDOM_NamedNodeMapPrivate* notations(); + + // Overloaded from QDOM_NodePrivate + virtual QDOM_NodePrivate* cloneNode( bool deep = TRUE ); + virtual QDOM_NodePrivate* insertBefore( QDOM_NodePrivate* newChild, QDOM_NodePrivate* refChild ); + virtual QDOM_NodePrivate* insertAfter( QDOM_NodePrivate* newChild, QDOM_NodePrivate* refChild ); + virtual QDOM_NodePrivate* replaceChild( QDOM_NodePrivate* newChild, QDOM_NodePrivate* oldChild ); + virtual QDOM_NodePrivate* removeChild( QDOM_NodePrivate* oldChild ); + virtual QDOM_NodePrivate* appendChild( QDOM_NodePrivate* newChild ); + + // Overloaded from QDOM_DocumentTypePrivate + virtual bool isDocumentType() { return TRUE; } + virtual void save( QTextStream& s, int ) const; + + // Variables + QDOM_NamedNodeMapPrivate* entities; + QDOM_NamedNodeMapPrivate* notations; +}; + +QDOM_DocumentTypePrivate::QDOM_DocumentTypePrivate( QDOM_DocumentPrivate* doc, QDOM_NodePrivate* parent ) + : QDOM_NodePrivate( doc, parent ) +{ + entities = new QDOM_NamedNodeMapPrivate( this ); + notations = new QDOM_NamedNodeMapPrivate( this ); + + entities->setAppendToParent( TRUE ); + notations->setAppendToParent( TRUE ); +} + +QDOM_DocumentTypePrivate::QDOM_DocumentTypePrivate( QDOM_DocumentTypePrivate* n, bool deep ) + : QDOM_NodePrivate( n, deep ) +{ + entities = new QDOM_NamedNodeMapPrivate( this ); + notations = new QDOM_NamedNodeMapPrivate( this ); + + entities->setAppendToParent( TRUE ); + notations->setAppendToParent( TRUE ); + + // Refill the maps with our new children + QDOM_NodePrivate* p = first; + while ( p ) { + if ( p->isEntity() ) + // Dont use normal insert function since we would create infinite recursion + entities->map.insert( p->nodeName(), p ); + if ( p->isNotation() ) + // Dont use normal insert function since we would create infinite recursion + notations->map.insert( p->nodeName(), p ); + } +} + +QDOM_DocumentTypePrivate::~QDOM_DocumentTypePrivate() +{ + if ( entities->deref() ) + delete entities; + if ( notations->deref() ) + delete notations; +} + +QDOM_NodePrivate* QDOM_DocumentTypePrivate::cloneNode( bool deep) +{ + QDOM_NodePrivate* p = new QDOM_DocumentTypePrivate( this, deep ); + // We are not interested in this node + p->deref(); + return p; +} + +QDOM_NodePrivate* QDOM_DocumentTypePrivate::insertBefore( QDOM_NodePrivate* newChild, QDOM_NodePrivate* refChild ) +{ + // Call the origianl implementation + QDOM_NodePrivate* p = QDOM_NodePrivate::insertBefore( newChild, refChild ); + // Update the maps + if ( p && p->isEntity() ) + entities->map.insert( p->nodeName(), p ); + else if ( p && p->isNotation() ) + notations->map.insert( p->nodeName(), p ); + + return p; +} + +QDOM_NodePrivate* QDOM_DocumentTypePrivate::insertAfter( QDOM_NodePrivate* newChild, QDOM_NodePrivate* refChild ) +{ + // Call the origianl implementation + QDOM_NodePrivate* p = QDOM_NodePrivate::insertAfter( newChild, refChild ); + // Update the maps + if ( p && p->isEntity() ) + entities->map.insert( p->nodeName(), p ); + else if ( p && p->isNotation() ) + notations->map.insert( p->nodeName(), p ); + + return p; +} + +QDOM_NodePrivate* QDOM_DocumentTypePrivate::replaceChild( QDOM_NodePrivate* newChild, QDOM_NodePrivate* oldChild ) +{ + // Call the origianl implementation + QDOM_NodePrivate* p = QDOM_NodePrivate::replaceChild( newChild, oldChild ); + // Update the maps + if ( p ) { + if ( oldChild && oldChild->isEntity() ) + entities->map.remove( oldChild->nodeName() ); + else if ( oldChild && oldChild->isNotation() ) + notations->map.remove( oldChild->nodeName() ); + + if ( p->isEntity() ) + entities->map.insert( p->nodeName(), p ); + else if ( p->isNotation() ) + notations->map.insert( p->nodeName(), p ); + } + + return p; +} + +QDOM_NodePrivate* QDOM_DocumentTypePrivate::removeChild( QDOM_NodePrivate* oldChild ) +{ + // Call the origianl implementation + QDOM_NodePrivate* p = QDOM_NodePrivate::removeChild( oldChild ); + // Update the maps + if ( p && p->isEntity() ) + entities->map.remove( p->nodeName() ); + else if ( p && p->isNotation() ) + notations->map.remove( p ->nodeName() ); + + return p; +} + +QDOM_NodePrivate* QDOM_DocumentTypePrivate::appendChild( QDOM_NodePrivate* newChild ) +{ + return insertAfter( newChild, 0 ); +} + +void QDOM_DocumentTypePrivate::save( QTextStream& s, int ) const +{ + if ( name.isEmpty() ) + return; + s << "map.count(), notations->map.count() ); + + if ( entities->length() > 0 || notations->length() > 0 ) { + s << "[ "; + + QDictIterator it2( notations->map ); + for ( ; it2.current(); ++it2 ) + it2.current()->save( s, 0 ); + + QDictIterator it( entities->map ); + for ( ; it.current(); ++it ) + it.current()->save( s, 0 ); + + s << " ]"; + } + + s << ">"; +} + +/************************************************************** + * + * QDomDocumentType + * + **************************************************************/ + +#define IMPL ((QDOM_DocumentTypePrivate*)impl) + +/*! + \class QDomDocumentType qdom.h + \brief The QDomDocumentType class is the representation of the DTD in the + document tree. + + \module XML + + The QDomDocumentType class allows readonly access to some of the data + structures in the DTD: it can return a map of all entities() and notations(). + + In addition the function name() returns the name of the document type as + specified in the <!DOCTYPE name> tag. + + \sa QDomDocument +*/ + +/*! + Creates an empty QDomDocumentType object. +*/ +QDomDocumentType::QDomDocumentType() : QDomNode() +{ +} + +/*! + Copy constructor. + + The data of the copy is shared: modifying one will also change the other. If + you want to make a real copy, use cloneNode() instead. +*/ +QDomDocumentType::QDomDocumentType( const QDomDocumentType& n ) + : QDomNode( n ) +{ +} + +/*! + \internal +*/ +QDomDocumentType::QDomDocumentType( QDOM_DocumentTypePrivate* n ) + : QDomNode( n ) +{ +} + +/*! + Assignement operator. + + The data of the copy is shared: modifying one will also change the other. If + you want to make a real copy, use cloneNode() instead. +*/ +QDomDocumentType& QDomDocumentType::operator= ( const QDomDocumentType& n ) +{ + return (QDomDocumentType&) QDomNode::operator=( n ); +} + +/*! + Destructor. +*/ +QDomDocumentType::~QDomDocumentType() +{ +} + +/*! + Returns the name of the document type as specified in + the <!DOCTYPE name> tag. + + \sa nodeName() +*/ +QString QDomDocumentType::name() const +{ + if ( !impl ) + return QString::null; + + return IMPL->nodeName(); +} + +/*! + Returns a map of all entities described in the DTD. +*/ +QDomNamedNodeMap QDomDocumentType::entities() const +{ + if ( !impl ) + return QDomNamedNodeMap(); + return QDomNamedNodeMap( IMPL->entities ); +} + +/*! + Returns a map of all notations described in the DTD. +*/ +QDomNamedNodeMap QDomDocumentType::notations() const +{ + if ( !impl ) + return QDomNamedNodeMap(); + return QDomNamedNodeMap( IMPL->notations ); +} + +/*! + Returns \c DocumentTypeNode. + + \sa isDocumentType() QDomNode::toDocumentType() +*/ +QDomNode::NodeType QDomDocumentType::nodeType() const +{ + return DocumentTypeNode; +} + +/*! + This function overloads QDomNode::isDocumentType(). + + \sa nodeType() QDomNode::toDocumentType() +*/ +bool QDomDocumentType::isDocumentType() const +{ + return TRUE; +} + +#undef IMPL + +/*==============================================================*/ +/* DocumentFragment */ +/*==============================================================*/ + +/************************************************************** + * + * QDOM_DocumentFragmentPrivate + * + **************************************************************/ + +class QDOM_DocumentFragmentPrivate : public QDOM_NodePrivate +{ +public: + QDOM_DocumentFragmentPrivate( QDOM_DocumentPrivate*, QDOM_NodePrivate* parent = 0 ); + QDOM_DocumentFragmentPrivate( QDOM_NodePrivate* n, bool deep ); + ~QDOM_DocumentFragmentPrivate(); + + // Overloaded from QDOM_NodePrivate + virtual QDOM_NodePrivate* cloneNode( bool deep = TRUE ); + virtual bool isDocumentFragment() { return TRUE; } + + static QString* dfName; +}; + +QString* QDOM_DocumentFragmentPrivate::dfName = 0; + +QDOM_DocumentFragmentPrivate::QDOM_DocumentFragmentPrivate( QDOM_DocumentPrivate* doc, QDOM_NodePrivate* parent ) + : QDOM_NodePrivate( doc, parent ) +{ + if ( !dfName ) + dfName = new QString( "#document-fragment" ); + name = *dfName; +} + +QDOM_DocumentFragmentPrivate::QDOM_DocumentFragmentPrivate( QDOM_NodePrivate* n, bool deep ) + : QDOM_NodePrivate( n, deep ) +{ +} + +QDOM_DocumentFragmentPrivate::~QDOM_DocumentFragmentPrivate() +{ +} + +QDOM_NodePrivate* QDOM_DocumentFragmentPrivate::cloneNode( bool deep) +{ + QDOM_NodePrivate* p = new QDOM_DocumentFragmentPrivate( this, deep ); + // We are not interested in this node + p->deref(); + return p; +} + +/************************************************************** + * + * QDomDocumentFragment + * + **************************************************************/ + +#define IMPL ((QDOM_DocumentFragmentPrivate*)impl) + +/*! + \class QDomDocumentFragment qdom.h + \brief The QDomDocumentFragment class is a tree of QDomNodes which is usually + not a complete QDomDocument. + + \module XML + + If you want to do complex tree operations it is useful to have a lightweight + class to store nodes and their relations. QDomDocumentFragment stores a + subtree of a document which does not necessarily represent a well-formed XML + document. + + QDomDocumentFragment is also useful if you want to group several nodes in a + list and insert them all together as children of some + node. In these cases QDomDocumentFragment can be used as a temporary + container for this list of children. + + The most important feature of QDomDocumentFragment is, that it is treated in + a special way by QDomNode::insertAfter(), QDomNode::insertBefore() and + QDomNode::replaceChild(): instead of inserting the fragment itself, all + children of the fragment are inserted. +*/ + +/*! + Constructs an empty DocumentFragment. +*/ +QDomDocumentFragment::QDomDocumentFragment() +{ +} + +/*! + \internal +*/ +QDomDocumentFragment::QDomDocumentFragment( QDOM_DocumentFragmentPrivate* n ) + : QDomNode( n ) +{ +} + +/*! + Copy constructor. + + The data of the copy is shared: modifying one will also change the other. If + you want to make a real copy, use cloneNode() instead. +*/ +QDomDocumentFragment::QDomDocumentFragment( const QDomDocumentFragment& x ) + : QDomNode( x ) +{ +} + +/*! + Assignment operator. + + The data of the copy is shared: modifying one will also change the other. If + you want to make a real copy, use cloneNode() instead. +*/ +QDomDocumentFragment& QDomDocumentFragment::operator= ( const QDomDocumentFragment& x ) +{ + return (QDomDocumentFragment&) QDomNode::operator=( x ); +} + +/*! + Destructor. +*/ +QDomDocumentFragment::~QDomDocumentFragment() +{ +} + +/*! + Returns \c DocumentFragment. + + \sa isDocumentFragment() QDomNode::toDocumentFragment() +*/ +QDomNode::NodeType QDomDocumentFragment::nodeType() const +{ + return QDomNode::DocumentFragmentNode; +} + +/*! + This function reimplements QDomNode::isDocumentFragment(). + + \sa nodeType() QDomNode::toDocumentFragment() +*/ +bool QDomDocumentFragment::isDocumentFragment() const +{ + return TRUE; +} + +#undef IMPL + +/*==============================================================*/ +/* CharacterData */ +/*==============================================================*/ + +/************************************************************** + * + * QDOM_CharacterDataPrivate + * + **************************************************************/ + +class QDOM_CharacterDataPrivate : public QDOM_NodePrivate +{ +public: + QDOM_CharacterDataPrivate( QDOM_DocumentPrivate*, QDOM_NodePrivate* parent, const QString& data ); + QDOM_CharacterDataPrivate( QDOM_CharacterDataPrivate* n, bool deep ); + ~QDOM_CharacterDataPrivate(); + + uint dataLength() const; + QString substringData( unsigned long offset, unsigned long count ) const; + void appendData( const QString& arg ); + void insertData( unsigned long offset, const QString& arg ); + void deleteData( unsigned long offset, unsigned long count ); + void replaceData( unsigned long offset, unsigned long count, const QString& arg ); + + // Overloaded from QDOM_NodePrivate + virtual bool isCharacterData() { return TRUE; } + virtual QDOM_NodePrivate* cloneNode( bool deep = TRUE ); + + static QString* cdName; +}; + +QString* QDOM_CharacterDataPrivate::cdName = 0; + +QDOM_CharacterDataPrivate::QDOM_CharacterDataPrivate( QDOM_DocumentPrivate* d, QDOM_NodePrivate* p, + const QString& data ) + : QDOM_NodePrivate( d, p ) +{ + value = data; + + if ( !cdName ) + cdName = new QString( "#character-data" ); + name = *cdName; +} + +QDOM_CharacterDataPrivate::QDOM_CharacterDataPrivate( QDOM_CharacterDataPrivate* n, bool deep ) + : QDOM_NodePrivate( n, deep ) +{ +} + +QDOM_CharacterDataPrivate::~QDOM_CharacterDataPrivate() +{ +} + +QDOM_NodePrivate* QDOM_CharacterDataPrivate::cloneNode( bool deep ) +{ + QDOM_NodePrivate* p = new QDOM_CharacterDataPrivate( this, deep ); + // We are not interested in this node + p->deref(); + return p; +} + +uint QDOM_CharacterDataPrivate::dataLength() const +{ + return value.length(); +} + +QString QDOM_CharacterDataPrivate::substringData( unsigned long offset, unsigned long n ) const +{ + return value.mid( offset, n ); +} + +void QDOM_CharacterDataPrivate::insertData( unsigned long offset, const QString& arg ) +{ + value.insert( offset, arg ); +} + +void QDOM_CharacterDataPrivate::deleteData( unsigned long offset, unsigned long n ) +{ + value.remove( offset, n ); +} + +void QDOM_CharacterDataPrivate::replaceData( unsigned long offset, unsigned long n, const QString& arg ) +{ + value.replace( offset, n, arg ); +} + +void QDOM_CharacterDataPrivate::appendData( const QString& arg ) +{ + value += arg; +} + +/************************************************************** + * + * QDomCharacterData + * + **************************************************************/ + +#define IMPL ((QDOM_CharacterDataPrivate*)impl) + +/*! + \class QDomCharacterData qdom.h + \brief The QDomCharacterData class represents a generic string in the DOM. + + \module XML + + Character data as used in XML specifies a generic data string. + More specialized versions of this class are QDomText, QDomComment + and QDomCDATASection. + + \sa QDomText QDomComment QDomCDATASection +*/ + +/*! + Constructs an empty character data object. +*/ +QDomCharacterData::QDomCharacterData() +{ +} + +/*! + Copy constructor. + + The data of the copy is shared: modifying one will also change the other. If + you want to make a real copy, use cloneNode() instead. +*/ +QDomCharacterData::QDomCharacterData( const QDomCharacterData& x ) + : QDomNode( x ) +{ +} + +/*! + \internal +*/ +QDomCharacterData::QDomCharacterData( QDOM_CharacterDataPrivate* n ) + : QDomNode( n ) +{ +} + +/*! + Assignment operator. + + The data of the copy is shared: modifying one will also change the other. If + you want to make a real copy, use cloneNode() instead. +*/ +QDomCharacterData& QDomCharacterData::operator= ( const QDomCharacterData& x ) +{ + return (QDomCharacterData&) QDomNode::operator=( x ); +} + +/*! + Destructor. +*/ +QDomCharacterData::~QDomCharacterData() +{ +} + +/*! + Returns the string stored in this object. + + If the node is a null node, it will return a null string. +*/ +QString QDomCharacterData::data() const +{ + if ( !impl ) + return QString::null; + return impl->nodeValue(); +} + +/*! + Sets the string of this object to \a v. +*/ +void QDomCharacterData::setData( const QString& v ) +{ + if ( impl ) + impl->setNodeValue( v ); +} + +/*! + Returns the length of the stored string. +*/ +uint QDomCharacterData::length() const +{ + if ( impl ) + return IMPL->dataLength(); + return 0; +} + +/*! + Returns the substring from position \a offset with length \a count. +*/ +QString QDomCharacterData::substringData( unsigned long offset, unsigned long count ) +{ + if ( !impl ) + return QString::null; + return IMPL->substringData( offset, count ); +} + +/*! + Appends \a arg to the stored string. +*/ +void QDomCharacterData::appendData( const QString& arg ) +{ + if ( impl ) + IMPL->appendData( arg ); +} + +/*! + Inserts the string \a arg at position \a offset into the stored string. +*/ +void QDomCharacterData::insertData( unsigned long offset, const QString& arg ) +{ + if ( impl ) + IMPL->insertData( offset, arg ); +} + +/*! + Deletes the substring starting at position \a offset with length \a count. +*/ +void QDomCharacterData::deleteData( unsigned long offset, unsigned long count ) +{ + if ( impl ) + IMPL->deleteData( offset, count ); +} + +/*! + Replaces the substring starting at \a offset with length \a count with the + string \a arg. +*/ +void QDomCharacterData::replaceData( unsigned long offset, unsigned long count, const QString& arg ) +{ + if ( impl ) + IMPL->replaceData( offset, count, arg ); +} + +/*! + Returns the type of node this object refers to (i.e. \c TextNode, + \c CDATASectionNode, \c CommentNode or \c CharacterDataNode). For a null node + \c CharacterDataNode is returned. +*/ +QDomNode::NodeType QDomCharacterData::nodeType() const +{ + if( !impl ) + return CharacterDataNode; + return QDomNode::nodeType(); +} + +/*! + Returns TRUE. +*/ +bool QDomCharacterData::isCharacterData() const +{ + return TRUE; +} + +#undef IMPL + +/************************************************************** + * + * QDOM_TextPrivate + * + **************************************************************/ + +class QDOM_TextPrivate : public QDOM_CharacterDataPrivate +{ +public: + QDOM_TextPrivate( QDOM_DocumentPrivate*, QDOM_NodePrivate* parent, const QString& value ); + QDOM_TextPrivate( QDOM_TextPrivate* n, bool deep ); + ~QDOM_TextPrivate(); + + QDOM_TextPrivate* splitText( int offset ); + + // Overloaded from QDOM_NodePrivate + virtual QDOM_NodePrivate* cloneNode( bool deep = TRUE ); + virtual bool isText() { return TRUE; } + virtual void save( QTextStream& s, int ) const; + + static QString* textName; +}; + +/*==============================================================*/ +/* Attr */ +/*==============================================================*/ + +/************************************************************** + * + * QDOM_AttrPrivate + * + **************************************************************/ + +class QDOM_AttrPrivate : public QDOM_NodePrivate +{ +public: + QDOM_AttrPrivate( QDOM_DocumentPrivate*, QDOM_NodePrivate* parent, const QString& name ); + QDOM_AttrPrivate( QDOM_AttrPrivate* n, bool deep ); + ~QDOM_AttrPrivate(); + + bool specified() const; + + // Overloaded from QDOM_NodePrivate + virtual QDOM_NodePrivate* cloneNode( bool deep = TRUE ); + virtual bool isAttr() { return TRUE; } + virtual void save( QTextStream& s, int ) const; + + // Variables + bool m_specified; +}; + +QDOM_AttrPrivate::QDOM_AttrPrivate( QDOM_DocumentPrivate* d, QDOM_NodePrivate* parent, const QString& name_ ) + : QDOM_NodePrivate( d, parent ) +{ + name = name_; + m_specified = FALSE; + // qDebug("ATTR"); +} + +QDOM_AttrPrivate::QDOM_AttrPrivate( QDOM_AttrPrivate* n, bool deep ) + : QDOM_NodePrivate( n, deep ) +{ + m_specified = n->specified(); + // qDebug("ATTR"); +} + +QDOM_AttrPrivate::~QDOM_AttrPrivate() +{ + // qDebug("~ATTR %s=%s", nodeName().latin1(), nodeValue().latin1() ); +} + +QDOM_NodePrivate* QDOM_AttrPrivate::cloneNode( bool deep ) +{ + QDOM_NodePrivate* p = new QDOM_AttrPrivate( this, deep ); + // We are not interested in this node + p->deref(); + return p; +} + +bool QDOM_AttrPrivate::specified() const +{ + return m_specified; +} + +/* + Encode an attribute value upon saving. +*/ +static QString encodeAttr( const QString& str ) +{ + QString tmp( str ); + uint len = tmp.length(); + uint i = 0; + while ( i < len ) { + if ( tmp[(int)i] == '<' ) { + tmp.replace( i, 1, "<" ); + len += 3; + i += 4; + } else if ( tmp[(int)i] == '"' ) { + tmp.replace( i, 1, """ ); + len += 5; + i += 6; + } else if ( tmp[(int)i] == '&' ) { + tmp.replace( i, 1, "&" ); + len += 4; + i += 5; + } else if ( tmp[(int)i] == '>' && i>=2 && tmp[(int)i-1]==']' && tmp[(int)i-2]==']' ) { + tmp.replace( i, 1, ">" ); + len += 3; + i += 4; + } else { + ++i; + } + } + + return tmp; +} + +void QDOM_AttrPrivate::save( QTextStream& s, int ) const +{ + s << name << "=\"" << encodeAttr( value ) << "\""; +} + +/************************************************************** + * + * QDomAttr + * + **************************************************************/ + +#define IMPL ((QDOM_AttrPrivate*)impl) + +/*! + \class QDomAttr qdom.h + \brief The QDomAttr class represents one attribute of a QDomElement + + \module XML + + For example, the following piece of XML gives an element with no children, + but two attributes: + + \code + + \endcode + + One can use the attributes of an element with code similar to: + + \code + QDomElement e = ....; + QDomAttr a = e.attributeNode( "href" ); + cout << a.value() << endl // gives "http://www.trolltech.com" + a.setValue( "http://doc.trolltech.com" ); + QDomAttr a2 = e.attributeNode( "href" ); + cout << a2.value() << endl // gives "http://doc.trolltech.com" + \endcode + + This example also shows that changing an attribute received from an element + changes the attribute of the element. If you do not want to change the + value of the element's attribute you have to use cloneNode() to get an + independent copy of the attribute. + + For further information about the Document Objct Model see + http://www.w3.org/TR/REC-DOM-Level-1/. + For a more general introduction of the DOM implementation see the + QDomDocument documentation. +*/ + + +/*! + Constructs an empty attribute. +*/ +QDomAttr::QDomAttr() +{ +} + +/*! + Copy constructor. + + The data of the copy is shared: modifying one will also change the other. If + you want to make a real copy, use cloneNode() instead. +*/ +QDomAttr::QDomAttr( const QDomAttr& x ) + : QDomNode( x ) +{ +} + +/*! + \internal +*/ +QDomAttr::QDomAttr( QDOM_AttrPrivate* n ) + : QDomNode( n ) +{ +} + +/*! + Assignment operator. + + The data of the copy is shared: modifying one will also change the other. If + you want to make a real copy, use cloneNode() instead. +*/ +QDomAttr& QDomAttr::operator= ( const QDomAttr& x ) +{ + return (QDomAttr&) QDomNode::operator=( x ); +} + +/*! + Destructor. +*/ +QDomAttr::~QDomAttr() +{ +} + +/*! + Returns the name of the attribute. +*/ +QString QDomAttr::name() const +{ + if ( !impl ) + return QString::null; + return impl->nodeName(); +} + +/*! + Returns TRUE if the attribute has been expicitly specified in the XML + document or was set by the user with setValue(), otherwise FALSE. + + \sa setValue() +*/ +bool QDomAttr::specified() const +{ + if ( !impl ) + return FALSE; + return IMPL->specified(); +} + +/*! + Returns the current value of the attribute. Returns a null string + when the attribute has not been specified. + + \sa specified() setValue() +*/ +QString QDomAttr::value() const +{ + if ( !impl ) + return QString::null; + return impl->nodeValue(); +} + +/*! + Sets the value of the attribute to \a v. + + \sa value() +*/ +void QDomAttr::setValue( const QString& v ) +{ + if ( !impl ) + return; + impl->setNodeValue( v ); + IMPL->m_specified = TRUE; +} + +/*! + Returns \c AttributeNode. +*/ +QDomNode::NodeType QDomAttr::nodeType() const +{ + return AttributeNode; +} + +/*! + Returns TRUE. +*/ +bool QDomAttr::isAttr() const +{ + return TRUE; +} + +#undef IMPL + +/*==============================================================*/ +/* Element */ +/*==============================================================*/ + +/************************************************************** + * + * QDOM_ElementPrivate + * + **************************************************************/ + +static void qNormalizeElement( QDOM_NodePrivate* n ) +{ + QDOM_NodePrivate* p = n->first; + QDOM_TextPrivate* t = 0; + + while ( p ) { + if ( p->isText() ) { + if ( t ) { + QDOM_NodePrivate* tmp = p->next; + t->appendData( p->nodeValue() ); + n->removeChild( p ); + p = tmp; + } else { + t = (QDOM_TextPrivate*)p; + p = p->next; + } + } else { + p = p->next; + t = 0; + } + } +} + + +class QDOM_ElementPrivate : public QDOM_NodePrivate +{ +public: + QDOM_ElementPrivate( QDOM_DocumentPrivate*, QDOM_NodePrivate* parent, const QString& name ); + QDOM_ElementPrivate( QDOM_ElementPrivate* n, bool deep ); + ~QDOM_ElementPrivate(); + + virtual QString attribute( const QString& name, const QString& defValue ) const; + virtual void setAttribute( const QString& name, const QString& value ); + virtual void removeAttribute( const QString& name ); + virtual QDOM_AttrPrivate* attributeNode( const QString& name); + virtual QDOM_AttrPrivate* setAttributeNode( QDOM_AttrPrivate* newAttr ); + virtual QDOM_AttrPrivate* removeAttributeNode( QDOM_AttrPrivate* oldAttr ); + virtual bool hasAttribute( const QString& name ); + virtual void normalize(); + + QString text(); + + // Overloaded from QDOM_NodePrivate + virtual QDOM_NamedNodeMapPrivate* attributes() { return m_attr; } + virtual bool isElement() { return TRUE; } + virtual QDOM_NodePrivate* cloneNode( bool deep = TRUE ); + virtual void save( QTextStream& s, int ) const; + + // Variables + QDOM_NamedNodeMapPrivate* m_attr; +}; + +QDOM_ElementPrivate::QDOM_ElementPrivate( QDOM_DocumentPrivate* d, QDOM_NodePrivate* p, + const QString& tagname ) + : QDOM_NodePrivate( d, p ) +{ + name = tagname; + m_attr = new QDOM_NamedNodeMapPrivate( this ); +} + +QDOM_ElementPrivate::QDOM_ElementPrivate( QDOM_ElementPrivate* n, bool deep ) : + QDOM_NodePrivate( n, deep ) +{ + m_attr = n->m_attr->clone( this ); + // Reference is down to 0, so we set it to 1 here. + m_attr->ref(); +} + +QDOM_ElementPrivate::~QDOM_ElementPrivate() +{ + // qDebug("~Element=%s", nodeName().latin1() ); + if ( m_attr->deref() ) + delete m_attr; +} + +QDOM_NodePrivate* QDOM_ElementPrivate::cloneNode( bool deep) +{ + QDOM_NodePrivate* p = new QDOM_ElementPrivate( this, deep ); + // We are not interested in this node + p->deref(); + return p; +} + +QString QDOM_ElementPrivate::attribute( const QString& name_, const QString& defValue ) const +{ + QDOM_NodePrivate* n = m_attr->namedItem( name_ ); + if ( !n ) + return defValue; + + return n->nodeValue(); +} + +void QDOM_ElementPrivate::setAttribute( const QString& aname, const QString& newValue ) +{ + removeAttribute( aname ); + + QDOM_NodePrivate* n = new QDOM_AttrPrivate( ownerDocument(), this, aname ); + n->setNodeValue( newValue ); + + // Referencing is done by the map, so we set the reference + // counter back to 0 here. This is ok since we created the QDOM_AttrPrivate. + n->deref(); + m_attr->setNamedItem( n ); +} + +void QDOM_ElementPrivate::removeAttribute( const QString& aname ) +{ + QDOM_NodePrivate* p = m_attr->removeNamedItem( aname ); + if ( p && p->count == 0 ) + delete p; +} + +QDOM_AttrPrivate* QDOM_ElementPrivate::attributeNode( const QString& aname ) +{ + return (QDOM_AttrPrivate*)m_attr->namedItem( aname ); +} + +QDOM_AttrPrivate* QDOM_ElementPrivate::setAttributeNode( QDOM_AttrPrivate* newAttr ) +{ + QDOM_NodePrivate* n = m_attr->namedItem( newAttr->nodeName() ); + + // Referencing is done by the maps + m_attr->setNamedItem( newAttr ); + + return (QDOM_AttrPrivate*)n; +} + +QDOM_AttrPrivate* QDOM_ElementPrivate::removeAttributeNode( QDOM_AttrPrivate* oldAttr ) +{ + return (QDOM_AttrPrivate*)m_attr->removeNamedItem( oldAttr->nodeName() ); +} + +bool QDOM_ElementPrivate::hasAttribute( const QString& aname ) +{ + return m_attr->contains( aname ); +} + +void QDOM_ElementPrivate::normalize() +{ + qNormalizeElement( this ); +} + +QString QDOM_ElementPrivate::text() +{ + QString t( "" ); + + QDOM_NodePrivate* p = first; + while ( p ) { + if ( p->isText() || p->isCDATASection() ) + t += p->nodeValue(); + else if ( p->isElement() ) + t += ((QDOM_ElementPrivate*)p)->text(); + p = p->next; + } + + return t; +} + +void QDOM_ElementPrivate::save( QTextStream& s, int indent ) const +{ + for ( int i = 0; i < indent; ++i ) + s << " "; + + s << "<" << name; + + if ( !m_attr->map.isEmpty() ) { + s << " "; + QDictIterator it( m_attr->map ); + for ( ; it.current(); ++it ) { + it.current()->save( s, 0 ); + s << " "; + } + } + + if ( last ) { // has child nodes + if ( first->isText() ) + s << ">"; + else + s << ">" << endl; + QDOM_NodePrivate::save( s, indent + 1 ); + if ( !last->isText() ) + for( int i = 0; i < indent; ++i ) + s << " "; + s << "" << endl; + } else { + s << "/>" << endl; + } +} + +/************************************************************** + * + * QDomElement + * + **************************************************************/ + +#define IMPL ((QDOM_ElementPrivate*)impl) + +/*! + \class QDomElement qdom.h + \brief The QDomElement class represents one element in the DOM tree. + + \module XML + + Elements have a name() and zero or more attributes associated with them. + + Attributes of the element are represented by QDomAttr objects, that can be + queried using the attribute() and attributeNode() functions. You can set + attributes with the setAttribute() and setAttributeNode() functions. + + For further information about the Document Objct Model see + http://www.w3.org/TR/REC-DOM-Level-1/. + For a more general introduction of the DOM implementation see the + QDomDocument documentation. +*/ + +/*! + Constructs an empty element. Use the QDomDocument::createElement() function + to construct elements with content. +*/ +QDomElement::QDomElement() + : QDomNode() +{ +} + +/*! + Copy constructor. + + The data of the copy is shared: modifying one will also change the other. If + you want to make a real copy, use cloneNode() instead. +*/ +QDomElement::QDomElement( const QDomElement& x ) + : QDomNode( x ) +{ +} + +/*! + \internal +*/ +QDomElement::QDomElement( QDOM_ElementPrivate* n ) + : QDomNode( n ) +{ +} + +/*! + Assignment operator. + + The data of the copy is shared: modifying one will also change the other. If + you want to make a real copy, use cloneNode() instead. +*/ +QDomElement& QDomElement::operator= ( const QDomElement& x ) +{ + return (QDomElement&) QDomNode::operator=( x ); +} + +/*! + Destructor. +*/ +QDomElement::~QDomElement() +{ +} + +/*! + Returns \c ElementNode. +*/ +QDomNode::NodeType QDomElement::nodeType() const +{ + return ElementNode; +} + +/*! + Sets the tag name of this element. + + \sa tagName() +*/ +void QDomElement::setTagName( const QString& name ) +{ + if ( impl ) + impl->name = name; +} + +/*! + Returns the tag name of this element. For an XML element like + \code + + \endcode + the tagname would return "img". + + \sa setTagName() +*/ +QString QDomElement::tagName() const +{ + if ( !impl ) + return QString::null; + return impl->nodeName(); +} + +/*! + Returns the attribute with the name \a name. If the attribute does not exist + \a defValue is returned. + + \sa setAttribute() attributeNode() setAttributeNode() +*/ +QString QDomElement::attribute( const QString& name, const QString& defValue ) const +{ + if ( !impl ) + return defValue; + return IMPL->attribute( name, defValue ); +} + +/*! + Sets the attribute with the name \a name to the string \a value. If the + attribute does not exist, a new one is created. +*/ +void QDomElement::setAttribute( const QString& name, const QString& value ) +{ + if ( !impl ) + return; + IMPL->setAttribute( name, value ); +} + +/*! + \overload +*/ +void QDomElement::setAttribute( const QString& name, int value ) +{ + if ( !impl ) + return; + QString x; + x.setNum( value ); + IMPL->setAttribute( name, x ); +} + +/*! + \overload +*/ +void QDomElement::setAttribute( const QString& name, uint value ) +{ + if ( !impl ) + return; + QString x; + x.setNum( value ); + IMPL->setAttribute( name, x ); +} + +/*! + \overload +*/ +void QDomElement::setAttribute( const QString& name, double value ) +{ + if ( !impl ) + return; + QString x; + x.setNum( value ); + IMPL->setAttribute( name, x ); +} + +/*! + Removes the attribute with the name \a name from this element. + + \sa setAttribute() attribute() +*/ +void QDomElement::removeAttribute( const QString& name ) +{ + if ( !impl ) + return; + IMPL->removeAttribute( name ); +} + +/*! + Returns the QDomAttr object that corresponds to the attribute with the name + \a name. If no such attribute exists a null object is returned. + + \sa setAttributeNode() attribute() setAttribute() +*/ +QDomAttr QDomElement::attributeNode( const QString& name) +{ + if ( !impl ) + return QDomAttr(); + return QDomAttr( IMPL->attributeNode( name ) ); +} + +/*! + Adds the attribute \a newAttr to this element. + + If an attribute with the name \a newAttr exists in the element, the function + returns this attribute; otherwise the function returns a null attribute. + + \sa attributeNode() +*/ +QDomAttr QDomElement::setAttributeNode( const QDomAttr& newAttr ) +{ + if ( !impl ) + return QDomAttr(); + return QDomAttr( IMPL->setAttributeNode( ((QDOM_AttrPrivate*)newAttr.impl) ) ); +} + +/*! + Removes the attribute \a oldAttr from the element and returns it. + + \sa attributeNode() setAttributeNode() +*/ +QDomAttr QDomElement::removeAttributeNode( const QDomAttr& oldAttr ) +{ + if ( !impl ) + return QDomAttr(); // ### should this return oldAttr? + return QDomAttr( IMPL->removeAttributeNode( ((QDOM_AttrPrivate*)oldAttr.impl) ) ); +} + +/*! + Returns a QDomNodeList containing all descendant elements of this element + with the name \a tagname. The order they are in the node list, is the order + they are encountered in a preorder traversal of the element tree. +*/ +QDomNodeList QDomElement::elementsByTagName( const QString& tagname ) const +{ + return QDomNodeList( new QDOM_NodeListPrivate( impl, tagname ) ); +} + + +/*! + Calling normalize() on an element brings all its children into a standard + form. This means, that adjacent QDomText objects will be merged to + one text object (QDomCDATASection nodes are not merged). +*/ +void QDomElement::normalize() +{ + if ( !impl ) + return; + IMPL->normalize(); +} + +/*! + Returns TRUE. +*/ +bool QDomElement::isElement() const +{ + return TRUE; +} + +/*! + Returns a QDomNamedNodeMap containing all attributes for this element. + + \sa attribute() setAttribute() attributeNode() setAttributeNode() +*/ +QDomNamedNodeMap QDomElement::attributes() const +{ + if ( !impl ) + return QDomNamedNodeMap(); + return QDomNamedNodeMap( IMPL->attributes() ); +} + +/*! + Returns TRUE is this element has an attribute with the name \a name, + otherwise FALSE. +*/ +bool QDomElement::hasAttribute( const QString& name ) const +{ + if ( !impl ) + return FALSE; + return IMPL->hasAttribute( name ); +} + +/*! + Returns the text contained inside this element. + + Example: + \code +

Hello Qt ]]>

+ \endcode + + The function text() of the QDomElement for the <h1> tag, + will return "Hello Qt <xml is cool>". + + Comments are ignored by this function. It evaluates only + QDomText and QDomCDATASection objects. +*/ +QString QDomElement::text() const +{ + if ( !impl ) + return QString::null; + return IMPL->text(); +} + +#undef IMPL + +/*==============================================================*/ +/* Text */ +/*==============================================================*/ + +/************************************************************** + * + * QDOM_TextPrivate + * + **************************************************************/ + +QString* QDOM_TextPrivate::textName = 0; + +QDOM_TextPrivate::QDOM_TextPrivate( QDOM_DocumentPrivate* d, QDOM_NodePrivate* parent, const QString& value ) + : QDOM_CharacterDataPrivate( d, parent, value ) +{ + if ( !textName ) + textName = new QString( "#text" ); + name = *textName; +} + +QDOM_TextPrivate::QDOM_TextPrivate( QDOM_TextPrivate* n, bool deep ) + : QDOM_CharacterDataPrivate( n, deep ) +{ +} + +QDOM_TextPrivate::~QDOM_TextPrivate() +{ +} + +QDOM_NodePrivate* QDOM_TextPrivate::cloneNode( bool deep) +{ + QDOM_NodePrivate* p = new QDOM_TextPrivate( this, deep ); + // We are not interested in this node + p->deref(); + return p; +} + +QDOM_TextPrivate* QDOM_TextPrivate::splitText( int offset ) +{ + if ( !parent ) { + qWarning( "QDomText::splitText The node has no parent. So I can not split" ); + return 0; + } + + QDOM_TextPrivate* t = new QDOM_TextPrivate( ownerDocument(), 0, value.mid( offset ) ); + value.truncate( offset ); + + parent->insertAfter( t, this ); + + return t; +} + +void QDOM_TextPrivate::save( QTextStream& s, int ) const +{ + s << encodeAttr( value ); +} + +/************************************************************** + * + * QDomText + * + **************************************************************/ + +#define IMPL ((QDOM_TextPrivate*)impl) + +/*! + \class QDomText qdom.h + \brief The QDomText class represents textual data in the parsed XML document. + + \module XML + + For further information about the Document Objct Model see + http://www.w3.org/TR/REC-DOM-Level-1/. + For a more general introduction of the DOM implementation see the + QDomDocument documentation. +*/ + +/*! + Constructs an empty QDomText object. + + To construct a QDomText with content, use QDomDocument::createTextNode(). +*/ +QDomText::QDomText() + : QDomCharacterData() +{ +} + +/*! + Copy constructor. + + The data of the copy is shared: modifying one will also change the other. If + you want to make a real copy, use cloneNode() instead. +*/ +QDomText::QDomText( const QDomText& x ) + : QDomCharacterData( x ) +{ +} + +/*! + \internal +*/ +QDomText::QDomText( QDOM_TextPrivate* n ) + : QDomCharacterData( n ) +{ +} + +/*! + Assignment operator. + + The data of the copy is shared: modifying one will also change the other. If + you want to make a real copy, use cloneNode() instead. +*/ +QDomText& QDomText::operator= ( const QDomText& x ) +{ + return (QDomText&) QDomNode::operator=( x ); +} + +/*! + Destructor. +*/ +QDomText::~QDomText() +{ +} + +/*! + Returns \c TextNode. +*/ +QDomNode::NodeType QDomText::nodeType() const +{ + return TextNode; +} + +/*! + Splits this object at position \a offset into two QDomText objects. The newly + created object is inserted into the document tree after this object. + + The function returns the newly created object. + + \sa QDomElement::normalize() +*/ +QDomText QDomText::splitText( int offset ) +{ + if ( !impl ) + return QDomText(); + return QDomText( IMPL->splitText( offset ) ); +} + +/*! + Returns TRUE. +*/ +bool QDomText::isText() const +{ + return TRUE; +} + +#undef IMPL + +/*==============================================================*/ +/* Comment */ +/*==============================================================*/ + +/************************************************************** + * + * QDOM_CommentPrivate + * + **************************************************************/ + +class QDOM_CommentPrivate : public QDOM_CharacterDataPrivate +{ +public: + QDOM_CommentPrivate( QDOM_DocumentPrivate*, QDOM_NodePrivate* parent, const QString& value ); + QDOM_CommentPrivate( QDOM_CommentPrivate* n, bool deep ); + ~QDOM_CommentPrivate(); + + // Overloaded from QDOM_NodePrivate + virtual QDOM_NodePrivate* cloneNode( bool deep = TRUE ); + bool isComment() { return TRUE; } + virtual void save( QTextStream& s, int ) const; + + static QString* commentName; +}; + +QString* QDOM_CommentPrivate::commentName = 0; + +QDOM_CommentPrivate::QDOM_CommentPrivate( QDOM_DocumentPrivate* d, QDOM_NodePrivate* parent, const QString& value ) + : QDOM_CharacterDataPrivate( d, parent, value ) +{ + if ( !commentName ) + commentName = new QString( "#comment" ); + name = *commentName; +} + +QDOM_CommentPrivate::QDOM_CommentPrivate( QDOM_CommentPrivate* n, bool deep ) + : QDOM_CharacterDataPrivate( n, deep ) +{ +} + +QDOM_CommentPrivate::~QDOM_CommentPrivate() +{ +} + +QDOM_NodePrivate* QDOM_CommentPrivate::cloneNode( bool deep) +{ + QDOM_NodePrivate* p = new QDOM_CommentPrivate( this, deep ); + // We are not interested in this node + p->deref(); + return p; +} + +void QDOM_CommentPrivate::save( QTextStream& s, int ) const +{ + s << ""; +} + +/************************************************************** + * + * QDomComment + * + **************************************************************/ + +#define IMPL ((QDOM_CommentPrivate*)impl) + +/*! + \class QDomComment qdom.h + \brief The QDomComment class represents an XML comment. + + \module XML + + A comment in the parsed XML such as + \code + + \endcode + is represented by QDomComment objects in the parsed Dom tree. + + For further information about the Document Objct Model see + http://www.w3.org/TR/REC-DOM-Level-1/. + For a more general introduction of the DOM implementation see the + QDomDocument documentation. +*/ + +/*! + Constructs an empty comment. To construct a comment with content, use + the QDomDocument::createComment() function. +*/ +QDomComment::QDomComment() + : QDomCharacterData() +{ +} + +/*! + Copy constructor. + + The data of the copy is shared: modifying one will also change the other. If + you want to make a real copy, use cloneNode() instead. +*/ +QDomComment::QDomComment( const QDomComment& x ) + : QDomCharacterData( x ) +{ +} + +/*! + \internal +*/ +QDomComment::QDomComment( QDOM_CommentPrivate* n ) + : QDomCharacterData( n ) +{ +} + +/*! + Assignment operator. + + The data of the copy is shared: modifying one will also change the other. If + you want to make a real copy, use cloneNode() instead. +*/ +QDomComment& QDomComment::operator= ( const QDomComment& x ) +{ + return (QDomComment&) QDomNode::operator=( x ); +} + +/*! + Destructor. +*/ +QDomComment::~QDomComment() +{ +} + +/*! + Returns \c CommentNode. +*/ +QDomNode::NodeType QDomComment::nodeType() const +{ + return CommentNode; +} + +/*! + Returns TRUE. +*/ +bool QDomComment::isComment() const +{ + return TRUE; +} + +#undef IMPL + +/*==============================================================*/ +/* CDATASection */ +/*==============================================================*/ + +/************************************************************** + * + * QDOM_CDATASectionPrivate + * + **************************************************************/ + +class QDOM_CDATASectionPrivate : public QDOM_TextPrivate +{ +public: + QDOM_CDATASectionPrivate( QDOM_DocumentPrivate*, QDOM_NodePrivate* parent, const QString& value ); + QDOM_CDATASectionPrivate( QDOM_CDATASectionPrivate* n, bool deep ); + ~QDOM_CDATASectionPrivate(); + + // Overloaded from QDOM_NodePrivate + virtual QDOM_NodePrivate* cloneNode( bool deep = TRUE ); + virtual bool isCDATASection() { return TRUE; } + virtual void save( QTextStream& s, int ) const; + + static QString* cdataName; +}; + +QString* QDOM_CDATASectionPrivate::cdataName = 0; + +QDOM_CDATASectionPrivate::QDOM_CDATASectionPrivate( QDOM_DocumentPrivate* d, QDOM_NodePrivate* parent, + const QString& value ) + : QDOM_TextPrivate( d, parent, value ) +{ + if ( !cdataName ) + cdataName = new QString( "#cdata-section" ); + name = *cdataName; +} + +QDOM_CDATASectionPrivate::QDOM_CDATASectionPrivate( QDOM_CDATASectionPrivate* n, bool deep ) + : QDOM_TextPrivate( n, deep ) +{ +} + +QDOM_CDATASectionPrivate::~QDOM_CDATASectionPrivate() +{ +} + +QDOM_NodePrivate* QDOM_CDATASectionPrivate::cloneNode( bool deep) +{ + QDOM_NodePrivate* p = new QDOM_CDATASectionPrivate( this, deep ); + // We are not interested in this node + p->deref(); + return p; +} + +void QDOM_CDATASectionPrivate::save( QTextStream& s, int ) const +{ + // #### How do we escape "]]>" ? + s << ""; +} + +/************************************************************** + * + * QDomCDATASection + * + **************************************************************/ + +#define IMPL ((QDOM_CDATASectionPrivate*)impl) + +/*! + \class QDomCDATASection qdom.h + \brief The QDomCDATASection class represents an XML CDATA section. + + \module XML + + CDATA sections are used to escape blocks of text containing + characters that would otherwise be regarded as markup. The only + delimiter that is recognized in a CDATA section is the "]]>" + string that ends the CDATA section. CDATA sections can not be + nested. The primary purpose is for including material such as XML + fragments, without needing to escape all the delimiters. + + Adjacent QDomCDATASection nodes are not merged by the + QDomElement.normalize() function. + + For further information about the Document Objct Model see + http://www.w3.org/TR/REC-DOM-Level-1/. + For a more general introduction of the DOM implementation see the + QDomDocument documentation. +*/ + +/*! + Constructs an empty CDATA section. To create a CDATA section with content, + use the QDomDocument::createCDATASection() function. +*/ +QDomCDATASection::QDomCDATASection() + : QDomText() +{ +} + +/*! + Copy constructor. + + The data of the copy is shared: modifying one will also change the other. If + you want to make a real copy, use cloneNode() instead. +*/ +QDomCDATASection::QDomCDATASection( const QDomCDATASection& x ) + : QDomText( x ) +{ +} + +/*! + \internal +*/ +QDomCDATASection::QDomCDATASection( QDOM_CDATASectionPrivate* n ) + : QDomText( n ) +{ +} + +/*! + Assigment operator. + + The data of the copy is shared: modifying one will also change the other. If + you want to make a real copy, use cloneNode() instead. +*/ +QDomCDATASection& QDomCDATASection::operator= ( const QDomCDATASection& x ) +{ + return (QDomCDATASection&) QDomNode::operator=( x ); +} + +/*! + Destructor. +*/ +QDomCDATASection::~QDomCDATASection() +{ +} + +/*! + Returns \c CDATASection. +*/ +QDomNode::NodeType QDomCDATASection::nodeType() const +{ + return CDATASectionNode; +} + +/*! + Returns TRUE +*/ +bool QDomCDATASection::isCDATASection() const +{ + return TRUE; +} + +#undef IMPL + +/*==============================================================*/ +/* Notation */ +/*==============================================================*/ + +/************************************************************** + * + * QDOM_NotationPrivate + * + **************************************************************/ + +class QDOM_NotationPrivate : public QDOM_NodePrivate +{ +public: + QDOM_NotationPrivate( QDOM_DocumentPrivate*, QDOM_NodePrivate* parent, const QString& name, + const QString& pub, const QString& sys ); + QDOM_NotationPrivate( QDOM_NotationPrivate* n, bool deep ); + ~QDOM_NotationPrivate(); + + // Overloaded from QDOM_NodePrivate + virtual QDOM_NodePrivate* cloneNode( bool deep = TRUE ); + virtual bool isNotation() { return TRUE; } + virtual void save( QTextStream& s, int ) const; + + // Variables + QString m_sys; + QString m_pub; +}; + +QDOM_NotationPrivate::QDOM_NotationPrivate( QDOM_DocumentPrivate* d, QDOM_NodePrivate* parent, + const QString& aname, + const QString& pub, const QString& sys ) + : QDOM_NodePrivate( d, parent ) +{ + name = aname; + m_pub = pub; + m_sys = sys; +} + +QDOM_NotationPrivate::QDOM_NotationPrivate( QDOM_NotationPrivate* n, bool deep ) + : QDOM_NodePrivate( n, deep ) +{ + m_sys = n->m_sys; + m_pub = n->m_pub; +} + +QDOM_NotationPrivate::~QDOM_NotationPrivate() +{ +} + +QDOM_NodePrivate* QDOM_NotationPrivate::cloneNode( bool deep) +{ + QDOM_NodePrivate* p = new QDOM_NotationPrivate( this, deep ); + // We are not interested in this node + p->deref(); + return p; +} + +void QDOM_NotationPrivate::save( QTextStream& s, int ) const +{ + s << ""; +} + +/************************************************************** + * + * QDomNotation + * + **************************************************************/ + +#define IMPL ((QDOM_NotationPrivate*)impl) + +/*! + \class QDomNotation qdom.h + \brief The QDomNotation class represents an XML notation. + + \module XML + + A notation either declares, by name, the format of an unparsed entity + (see section 4.7 of the XML 1.0 specification), or is used for + formal declaration of processing instruction targets (see section + 2.6 of the XML 1.0 specification). + + DOM does not support editing notation nodes; they are therefore readonly. + + A notation node does not have any parent. + + For further information about the Document Objct Model see + http://www.w3.org/TR/REC-DOM-Level-1/. + For a more general introduction of the DOM implementation see the + QDomDocument documentation. +*/ + + +/*! + Constructor. +*/ +QDomNotation::QDomNotation() + : QDomNode() +{ +} + +/*! + Copy constructor. + + The data of the copy is shared: modifying one will also change the other. If + you want to make a real copy, use cloneNode() instead. +*/ +QDomNotation::QDomNotation( const QDomNotation& x ) + : QDomNode( x ) +{ +} + +/*! + \internal +*/ +QDomNotation::QDomNotation( QDOM_NotationPrivate* n ) + : QDomNode( n ) +{ +} + +/*! + Assignment operator. + + The data of the copy is shared: modifying one will also change the other. If + you want to make a real copy, use cloneNode() instead. +*/ +QDomNotation& QDomNotation::operator= ( const QDomNotation& x ) +{ + return (QDomNotation&) QDomNode::operator=( x ); +} + +/*! + Destructor. +*/ +QDomNotation::~QDomNotation() +{ +} + +/*! + Returns \c NotationNode. +*/ +QDomNode::NodeType QDomNotation::nodeType() const +{ + return NotationNode; +} + +/*! + Returns the public identifier of this notation. +*/ +QString QDomNotation::publicId() const +{ + if ( !impl ) + return QString::null; + return IMPL->m_pub; +} + +/*! + Returns the system identifier of this notation. +*/ +QString QDomNotation::systemId() const +{ + if ( !impl ) + return QString::null; + return IMPL->m_sys; +} + +/*! + Returns TRUE. +*/ +bool QDomNotation::isNotation() const +{ + return TRUE; +} + +#undef IMPL + + +/*==============================================================*/ +/* Entity */ +/*==============================================================*/ + +/************************************************************** + * + * QDOM_EntityPrivate + * + **************************************************************/ + +class QDOM_EntityPrivate : public QDOM_NodePrivate +{ +public: + QDOM_EntityPrivate( QDOM_DocumentPrivate*, QDOM_NodePrivate* parent, const QString& name, + const QString& pub, const QString& sys, const QString& notation ); + QDOM_EntityPrivate( QDOM_EntityPrivate* n, bool deep ); + ~QDOM_EntityPrivate(); + + // Overloaded from QDOM_NodePrivate + virtual QDOM_NodePrivate* cloneNode( bool deep = TRUE ); + virtual bool isEntity() { return TRUE; } + virtual void save( QTextStream& s, int ) const; + + // Variables + QString m_sys; + QString m_pub; + QString m_notationName; +}; + +QDOM_EntityPrivate::QDOM_EntityPrivate( QDOM_DocumentPrivate* d, QDOM_NodePrivate* parent, + const QString& aname, + const QString& pub, const QString& sys, const QString& notation ) + : QDOM_NodePrivate( d, parent ) +{ + name = aname; + m_pub = pub; + m_sys = sys; + m_notationName = notation; +} + +QDOM_EntityPrivate::QDOM_EntityPrivate( QDOM_EntityPrivate* n, bool deep ) + : QDOM_NodePrivate( n, deep ) +{ + m_sys = n->m_sys; + m_pub = n->m_pub; + m_notationName = n->m_notationName; +} + +QDOM_EntityPrivate::~QDOM_EntityPrivate() +{ +} + +QDOM_NodePrivate* QDOM_EntityPrivate::cloneNode( bool deep) +{ + QDOM_NodePrivate* p = new QDOM_EntityPrivate( this, deep ); + // We are not interested in this node + p->deref(); + return p; +} + +/* + Encode an entity value upon saving. +*/ +static QCString encodeEntity( const QCString& str ) +{ + QCString tmp( str ); + uint len = tmp.length(); + uint i = 0; + const char* d = tmp.data(); + while ( i < len ) { + if ( d[i] == '%' ){ + tmp.replace( i, 1, "<" ); + d = tmp.data(); + len += 4; + i += 5; + } + else if ( d[i] == '"' ) { + tmp.replace( i, 1, """ ); + d = tmp.data(); + len += 4; + i += 5; + } else if ( d[i] == '&' && i + 1 < len && d[i+1] == '#' ) { + // Dont encode < or " or &custom;. + // Only encode character references + tmp.replace( i, 1, "&" ); + d = tmp.data(); + len += 4; + i += 5; + } else { + ++i; + } + } + + return tmp; +} + +void QDOM_EntityPrivate::save( QTextStream& s, int ) const +{ + if ( m_sys.isEmpty() && m_pub.isEmpty() ) { + s << ""; + } else { + s << ""; + } +} + +/************************************************************** + * + * QDomEntity + * + **************************************************************/ + +#define IMPL ((QDOM_EntityPrivate*)impl) + +/*! + \class QDomEntity qdom.h + \brief The QDomEntity class represents an XML entity. + + \module XML + + This class represents an entity in an XML document, either parsed or + unparsed. Note that this models the entity itself not the entity declaration. + + DOM does not support editing entity nodes; if a user wants to make changes to + the contents of an entity, every related QDomEntityReference node has to be + replaced in the DOM tree by a clone of the entity's contents, and then + the desired changes must be made to each of those clones instead. All the + descendants of an entity node are readonly. + + An entity node does not have any parent. + + For further information about the Document Objct Model see + http://www.w3.org/TR/REC-DOM-Level-1/. + For a more general introduction of the DOM implementation see the + QDomDocument documentation. +*/ + + +/*! + Constructs an empty entity. +*/ +QDomEntity::QDomEntity() + : QDomNode() +{ +} + + +/*! + Copy constructor. + + The data of the copy is shared: modifying one will also change the other. If + you want to make a real copy, use cloneNode() instead. +*/ +QDomEntity::QDomEntity( const QDomEntity& x ) + : QDomNode( x ) +{ +} + +/*! + \internal +*/ +QDomEntity::QDomEntity( QDOM_EntityPrivate* n ) + : QDomNode( n ) +{ +} + +/*! + Assignment operator. + + The data of the copy is shared: modifying one will also change the other. If + you want to make a real copy, use cloneNode() instead. +*/ +QDomEntity& QDomEntity::operator= ( const QDomEntity& x ) +{ + return (QDomEntity&) QDomNode::operator=( x ); +} + +/*! + Destructor. +*/ +QDomEntity::~QDomEntity() +{ +} + +/*! + Returns \c EntityNode. +*/ +QDomNode::NodeType QDomEntity::nodeType() const +{ + return EntityNode; +} + +/*! + Returns the public identifier associated with this entity. + If the public identifier was not specified QString::null is returned. +*/ +QString QDomEntity::publicId() const +{ + if ( !impl ) + return QString::null; + return IMPL->m_pub; +} + +/*! + Returns the system identifier associated with this entity. + If the system identifier was not specified QString::null is returned. +*/ +QString QDomEntity::systemId() const +{ + if ( !impl ) + return QString::null; + return IMPL->m_sys; +} + +/*! + For unparsed entities this function returns the name of the notation for the + entity. For parsed entities this function returns QString::null. +*/ +QString QDomEntity::notationName() const +{ + if ( !impl ) + return QString::null; + return IMPL->m_notationName; +} + +/*! + Returns TRUE. +*/ +bool QDomEntity::isEntity() const +{ + return TRUE; +} + +#undef IMPL + + +/*==============================================================*/ +/* EntityReference */ +/*==============================================================*/ + +/************************************************************** + * + * QDOM_EntityReferencePrivate + * + **************************************************************/ + +class QDOM_EntityReferencePrivate : public QDOM_NodePrivate +{ +public: + QDOM_EntityReferencePrivate( QDOM_DocumentPrivate*, QDOM_NodePrivate* parent, const QString& name ); + QDOM_EntityReferencePrivate( QDOM_NodePrivate* n, bool deep ); + ~QDOM_EntityReferencePrivate(); + + // Overloaded from QDOM_NodePrivate + virtual QDOM_NodePrivate* cloneNode( bool deep = TRUE ); + virtual bool isEntityReference() { return TRUE; } + virtual void save( QTextStream& s, int ) const; +}; + +QDOM_EntityReferencePrivate::QDOM_EntityReferencePrivate( QDOM_DocumentPrivate* d, QDOM_NodePrivate* parent, const QString& aname ) + : QDOM_NodePrivate( d, parent ) +{ + name = aname; +} + +QDOM_EntityReferencePrivate::QDOM_EntityReferencePrivate( QDOM_NodePrivate* n, bool deep ) + : QDOM_NodePrivate( n, deep ) +{ +} + +QDOM_EntityReferencePrivate::~QDOM_EntityReferencePrivate() +{ +} + +QDOM_NodePrivate* QDOM_EntityReferencePrivate::cloneNode( bool deep) +{ + QDOM_NodePrivate* p = new QDOM_EntityReferencePrivate( this, deep ); + // We are not interested in this node + p->deref(); + return p; +} + +void QDOM_EntityReferencePrivate::save( QTextStream& s, int ) const +{ + s << "&" << name << ";"; +} + +/************************************************************** + * + * QDomEntityReference + * + **************************************************************/ + +#define IMPL ((QDOM_EntityReferencePrivate*)impl) + +/*! + \class QDomEntityReference qdom.h + \brief The QDomEntityReference class represents an XML entity reference. + + \module XML + + A QDomEntityReference object may be inserted into the + DOM tree when an entity reference is in the source document, + or when the user wishes to insert an entity reference. + + Note that character references and references to predefined entities are + expanded by the XML processor so that characters are represented by their + Unicode equivalent rather than by an entity reference. + + Moreover, the XML processor may completely expand references to entities + while building the DOM tree, instead of providing QDomEntityReference + objects. + + If it does provide such objects, then for a given entity reference node, it + may be that there is no entity node representing the referenced entity; but + if such an entity exists, then the child list of the entity reference node is + the same as that of the entity node. As with the entity node, all + descendants of the entity reference are readonly. + + For further information about the Document Objct Model see + http://www.w3.org/TR/REC-DOM-Level-1/. + For a more general introduction of the DOM implementation see the + QDomDocument documentation. +*/ + + + +/*! + Constructs an empty entity reference. Use + QDomDocument::createEntityReference() to create a entity reference with + content. +*/ +QDomEntityReference::QDomEntityReference() + : QDomNode() +{ +} + +/*! + Copy constructor. + + The data of the copy is shared: modifying one will also change the other. If + you want to make a real copy, use cloneNode() instead. +*/ +QDomEntityReference::QDomEntityReference( const QDomEntityReference& x ) + : QDomNode( x ) +{ +} + +/*! + \internal +*/ +QDomEntityReference::QDomEntityReference( QDOM_EntityReferencePrivate* n ) + : QDomNode( n ) +{ +} + +/*! + Assignment operator. + + The data of the copy is shared: modifying one will also change the other. If + you want to make a real copy, use cloneNode() instead. +*/ +QDomEntityReference& QDomEntityReference::operator= ( const QDomEntityReference& x ) +{ + return (QDomEntityReference&) QDomNode::operator=( x ); +} + +/*! + Destructor. +*/ +QDomEntityReference::~QDomEntityReference() +{ +} + +/*! + Returns \c EntityReference. +*/ +QDomNode::NodeType QDomEntityReference::nodeType() const +{ + return EntityReferenceNode; +} + +/*! + Returns TRUE. +*/ +bool QDomEntityReference::isEntityReference() const +{ + return TRUE; +} + +#undef IMPL + + +/*==============================================================*/ +/* ProcessingInstruction */ +/*==============================================================*/ + +/************************************************************** + * + * QDOM_ProcessingInstructionPrivate + * + **************************************************************/ + +class QDOM_ProcessingInstructionPrivate : public QDOM_NodePrivate +{ +public: + QDOM_ProcessingInstructionPrivate( QDOM_DocumentPrivate*, QDOM_NodePrivate* parent, const QString& target, + const QString& data); + QDOM_ProcessingInstructionPrivate( QDOM_ProcessingInstructionPrivate* n, bool deep ); + ~QDOM_ProcessingInstructionPrivate(); + + // Overloaded from QDOM_NodePrivate + virtual QDOM_NodePrivate* cloneNode( bool deep = TRUE ); + virtual bool isProcessingInstruction() { return TRUE; } + virtual void save( QTextStream& s, int ) const; +}; + +QDOM_ProcessingInstructionPrivate::QDOM_ProcessingInstructionPrivate( QDOM_DocumentPrivate* d, + QDOM_NodePrivate* parent, + const QString& target, + const QString& data ) + : QDOM_NodePrivate( d, parent ) +{ + name = target; + value = data; +} + +QDOM_ProcessingInstructionPrivate::QDOM_ProcessingInstructionPrivate( QDOM_ProcessingInstructionPrivate* n, bool deep ) + : QDOM_NodePrivate( n, deep ) +{ +} + +QDOM_ProcessingInstructionPrivate::~QDOM_ProcessingInstructionPrivate() +{ +} + +QDOM_NodePrivate* QDOM_ProcessingInstructionPrivate::cloneNode( bool deep) +{ + QDOM_NodePrivate* p = new QDOM_ProcessingInstructionPrivate( this, deep ); + // We are not interested in this node + p->deref(); + return p; +} + +void QDOM_ProcessingInstructionPrivate::save( QTextStream& s, int ) const +{ + s << ""; +} + +/************************************************************** + * + * QDomProcessingInstruction + * + **************************************************************/ + +#define IMPL ((QDOM_ProcessingInstructionPrivate*)impl) + +/*! + \class QDomProcessingInstruction qdom.h + \brief The QDomProcessingInstruction class represents an XML processing + instruction. + + \module XML + + Processing instructions are used in XML as a way to keep processor-specific + information in the text of the document. + + For further information about the Document Objct Model see + http://www.w3.org/TR/REC-DOM-Level-1/. + For a more general introduction of the DOM implementation see the + QDomDocument documentation. +*/ + +/*! + Constructs an empty processing instruction. Use + QDomDocument::createProcessingInstruction() to create a processing + instruction with content. +*/ +QDomProcessingInstruction::QDomProcessingInstruction() + : QDomNode() +{ +} + +/*! + Copy constructor. + + The data of the copy is shared: modifying one will also change the other. If + you want to make a real copy, use cloneNode() instead. +*/ +QDomProcessingInstruction::QDomProcessingInstruction( const QDomProcessingInstruction& x ) + : QDomNode( x ) +{ +} + +/*! + \internal +*/ +QDomProcessingInstruction::QDomProcessingInstruction( QDOM_ProcessingInstructionPrivate* n ) + : QDomNode( n ) +{ +} + +/*! + Assignment operator. + + The data of the copy is shared: modifying one will also change the other. If + you want to make a real copy, use cloneNode() instead. +*/ +QDomProcessingInstruction& QDomProcessingInstruction::operator= ( const QDomProcessingInstruction& x ) +{ + return (QDomProcessingInstruction&) QDomNode::operator=( x ); +} + +/*! + Destructor. +*/ +QDomProcessingInstruction::~QDomProcessingInstruction() +{ +} + +/*! + Returns \c ProcessingInstructionNode. +*/ +QDomNode::NodeType QDomProcessingInstruction::nodeType() const +{ + return ProcessingInstructionNode; +} + +/*! + Returns the target of this processing instruction. + + \sa data() +*/ +QString QDomProcessingInstruction::target() const +{ + if ( !impl ) + return QString::null; + return impl->nodeName(); +} + +/*! + Returns the content of this processing instruction. + + \sa setData() target() +*/ +QString QDomProcessingInstruction::data() const +{ + if ( !impl ) + return QString::null; + return impl->nodeValue(); +} + +/*! + Sets the data contained in the processing instruction. + + \sa data() +*/ +void QDomProcessingInstruction::setData( const QString& d ) +{ + if ( !impl ) + return; + impl->setNodeValue( d ); +} + +/*! + Returns TRUE. +*/ +bool QDomProcessingInstruction::isProcessingInstruction() const +{ + return TRUE; +} + +#undef IMPL + +/*==============================================================*/ +/* Document */ +/*==============================================================*/ + +/************************************************************** + * + * QDOM_DocumentPrivate + * + **************************************************************/ + +class QDOM_DocumentPrivate : public QDOM_NodePrivate +{ +public: + QDOM_DocumentPrivate(); + QDOM_DocumentPrivate( const QString& name ); + QDOM_DocumentPrivate( QDOM_DocumentPrivate* n, bool deep ); + ~QDOM_DocumentPrivate(); + + bool setContent( QXmlInputSource& source ); + + // Attributes + QDOM_DocumentTypePrivate* doctype() { return type; }; + QDOM_ImplementationPrivate* implementation() { return impl; }; + QDOM_ElementPrivate* documentElement(); + + // Factories + QDOM_ElementPrivate* createElement( const QString& tagName ); + QDOM_DocumentFragmentPrivate* createDocumentFragment(); + QDOM_TextPrivate* createTextNode( const QString& data ); + QDOM_CommentPrivate* createComment( const QString& data ); + QDOM_CDATASectionPrivate* createCDATASection( const QString& data ); + QDOM_ProcessingInstructionPrivate* createProcessingInstruction( const QString& target, const QString& data ); + QDOM_AttrPrivate* createAttribute( const QString& name ); + QDOM_EntityReferencePrivate* createEntityReference( const QString& name ); + QDOM_NodeListPrivate* elementsByTagName( const QString& tagname ); + + // Overloaded from QDOM_NodePrivate + virtual QDOM_NodePrivate* cloneNode( bool deep = TRUE ); + virtual bool isDocument() { return TRUE; } + virtual void clear(); + virtual void save( QTextStream&, int ) const; + + // Variables + QDOM_ImplementationPrivate* impl; + QDOM_DocumentTypePrivate* type; + + static QString* docName; +}; + +QString* QDOM_DocumentPrivate::docName = 0; + +QDOM_DocumentPrivate::QDOM_DocumentPrivate() + : QDOM_NodePrivate( 0 ) +{ + impl = new QDOM_ImplementationPrivate(); + type = new QDOM_DocumentTypePrivate( this, this ); + + if ( !docName ) + docName = new QString( "#document" ); + name = *docName; +} + +QDOM_DocumentPrivate::QDOM_DocumentPrivate( const QString& aname ) + : QDOM_NodePrivate( 0 ) +{ + impl = new QDOM_ImplementationPrivate(); + type = new QDOM_DocumentTypePrivate( this, this ); + type->name = aname; + + if ( !docName ) + docName = new QString( "#document" ); + QDOM_DocumentPrivate::name = *docName; +} + +QDOM_DocumentPrivate::QDOM_DocumentPrivate( QDOM_DocumentPrivate* n, bool deep ) + : QDOM_NodePrivate( n, deep ) +{ + impl = n->impl->clone(); + // Reference count is down to 0, so we set it to 1 here. + impl->ref(); + type = (QDOM_DocumentTypePrivate*)n->type->cloneNode(); + type->setParent( this ); + // Reference count is down to 0, so we set it to 1 here. + type->ref(); +} + +QDOM_DocumentPrivate::~QDOM_DocumentPrivate() +{ + // qDebug("~Document %x", this); + if ( impl->deref() ) delete impl; + if ( type->deref() ) delete type; +} + +void QDOM_DocumentPrivate::clear() +{ + if ( impl->deref() ) delete impl; + if ( type->deref() ) delete type; + impl = 0; + type = 0; + QDOM_NodePrivate::clear(); +} + +bool QDOM_DocumentPrivate::setContent( QXmlInputSource& source ) +{ + clear(); + impl = new QDOM_ImplementationPrivate; + type = new QDOM_DocumentTypePrivate( this, this ); + + QXmlSimpleReader reader; + QDomHandler hnd( this ); + reader.setContentHandler( &hnd ); + reader.setErrorHandler( &hnd ); + reader.setLexicalHandler( &hnd ); + reader.setDeclHandler( &hnd ); + reader.setDTDHandler( &hnd ); +#if defined(Q_BROKEN_ALPHA) // #### very ugly hack, ws should really be able to get rid of that + reader.setFeature( "http://xml.org/sax/features/namespaces", TRUE ); +#else + reader.setFeature( "http://xml.org/sax/features/namespaces", FALSE ); +#endif + reader.setFeature( "http://xml.org/sax/features/namespace-prefixes", TRUE ); + reader.setFeature( "http://trolltech.com/xml/features/report-whitespace-only-CharData", FALSE ); + + if ( !reader.parse( source ) ) { + qWarning("Parsing error"); + return FALSE; + } + + return TRUE; +} + +QDOM_NodePrivate* QDOM_DocumentPrivate::cloneNode( bool deep) +{ + QDOM_NodePrivate* p = new QDOM_DocumentPrivate( this, deep ); + // We are not interested in this node + p->deref(); + return p; +} + +QDOM_ElementPrivate* QDOM_DocumentPrivate::documentElement() +{ + QDOM_NodePrivate* p = first; + while ( p && !p->isElement() ) + p = p->next; + + return (QDOM_ElementPrivate*)p; +} + +QDOM_ElementPrivate* QDOM_DocumentPrivate::createElement( const QString& tagName ) +{ + QDOM_ElementPrivate* e = new QDOM_ElementPrivate( this, this, tagName ); + e->deref(); + return e; +} + +QDOM_DocumentFragmentPrivate* QDOM_DocumentPrivate::createDocumentFragment() +{ + QDOM_DocumentFragmentPrivate* f = new QDOM_DocumentFragmentPrivate( this, this ); + f->deref(); + return f; +} + +QDOM_TextPrivate* QDOM_DocumentPrivate::createTextNode( const QString& data ) +{ + QDOM_TextPrivate* t = new QDOM_TextPrivate( this, this, data ); + t->deref(); + return t; +} + +QDOM_CommentPrivate* QDOM_DocumentPrivate::createComment( const QString& data ) +{ + QDOM_CommentPrivate* c = new QDOM_CommentPrivate( this, this, data ); + c->deref(); + return c; +} + +QDOM_CDATASectionPrivate* QDOM_DocumentPrivate::createCDATASection( const QString& data ) +{ + QDOM_CDATASectionPrivate* c = new QDOM_CDATASectionPrivate( this, this, data ); + c->deref(); + return c; +} + +QDOM_ProcessingInstructionPrivate* QDOM_DocumentPrivate::createProcessingInstruction( const QString& target, const QString& data ) +{ + QDOM_ProcessingInstructionPrivate* p = new QDOM_ProcessingInstructionPrivate( this, this, target, data ); + p->deref(); + return p; +} + +QDOM_AttrPrivate* QDOM_DocumentPrivate::createAttribute( const QString& aname ) +{ + QDOM_AttrPrivate* a = new QDOM_AttrPrivate( this, this, aname ); + a->deref(); + return a; +} + +QDOM_EntityReferencePrivate* QDOM_DocumentPrivate::createEntityReference( const QString& aname ) +{ + QDOM_EntityReferencePrivate* e = new QDOM_EntityReferencePrivate( this, this, aname ); + e->deref(); + return e; +} + +void QDOM_DocumentPrivate::save( QTextStream& s, int ) const +{ + bool doc = FALSE; + + QDOM_NodePrivate* n = first; + while ( n ) { + if ( !doc && !n->isProcessingInstruction() ) { + type->save( s, 0 ); + doc = TRUE; + } + n->save( s, 0 ); + n = n->next; + } +} + +/************************************************************** + * + * QDomDocument + * + **************************************************************/ + +#define IMPL ((QDOM_DocumentPrivate*)impl) + +/*! + \class QDomDocument qdom.h + \brief The QDomDocument class is the representation of an XML document. + + \module XML + + The QDomDocument class represents the entire XML document. Conceptually, it + is the root of the document tree, and provides the primary access to the + document's data. + + Since elements, text nodes, comments, processing instructions, etc. cannot + exist outside the context of a document, the document class also contains the + factory functions needed to create these objects. The node objects created + have an ownerDocument() function which associates them with the document + within whose context they were created. + + The parsed XML is represented internally by a tree of objects that can be + accessed using the various QDom classes. All QDom classes do only reference + objects in the internal tree. The internal objects in the DOM tree will get + deleted, once the last QDom object referencing them and the QDomDocument are + deleted. + + Creation of elements, text nodes, etc. is done via the various factory + functions provided in this class. Using the default constructors of the QDom + classes will only result in empty objects, that can not be manipulated or + inserted into the Document. + + The QDom classes are typically used as follows: + \code + QDomDocument doc( "mydocument" ); + QFile f( "mydocument.xml" ); + if ( !f.open( IO_ReadOnly ) ) + return; + if ( !doc.setContent( &f ) ) { + f.close(); + return; + } + f.close(); + + // print out the element names of all elements that are a direct child + // of the outermost element. + QDomElement docElem = doc.documentElement(); + + QDomNode n = docElem.firstChild(); + while( !n.isNull() ) { + QDomElement e = n.toElement(); // try to convert the node to an element. + if( !e.isNull() ) { // the node was really an element. + cout << e.tagName() << endl; + } + n = n.nextSibling(); + } + + // lets append a new element to the end of the document + QDomElement elem = doc.createElement( "img" ); + elem.setAttribute( "src", "myimage.png" ); + docElem.appendChild( elem ); + \endcode + + Once \c doc and \c elem go out of scode, the whole internal tree representing + the XML document will get deleted. + + For further information about the Document Objct Model see + http://www.w3.org/TR/REC-DOM-Level-1/. +*/ + + +/*! + Constructs an empty document. +*/ +QDomDocument::QDomDocument() +{ +} + +/*! + Creates a document with the name \a name. +*/ +QDomDocument::QDomDocument( const QString& name ) +{ + // We take over ownership + impl = new QDOM_DocumentPrivate( name ); +} + +/*! + Copy constructor. + + The data of the copy is shared: modifying one will also change the other. If + you want to make a real copy, use cloneNode() instead. +*/ +QDomDocument::QDomDocument( const QDomDocument& x ) + : QDomNode( x ) +{ +} + +/*! + \internal +*/ +QDomDocument::QDomDocument( QDOM_DocumentPrivate* x ) + : QDomNode( x ) +{ +} + +/*! + Assignment operator. + + The data of the copy is shared: modifying one will also change the other. If + you want to make a real copy, use cloneNode() instead. +*/ +QDomDocument& QDomDocument::operator= ( const QDomDocument& x ) +{ + return (QDomDocument&) QDomNode::operator=( x ); +} + +/*! + Destructor. +*/ +QDomDocument::~QDomDocument() +{ +} + +/*! + This function parses the string \a text and sets it as the content of the + document. +*/ +bool QDomDocument::setContent( const QString& text ) +{ + if ( !impl ) + impl = new QDOM_DocumentPrivate; + QXmlInputSource source; + source.setData( text ); + return IMPL->setContent( source ); +} + +/*! + \overload +*/ +bool QDomDocument::setContent( const QByteArray& buffer ) +{ + if ( !impl ) + impl = new QDOM_DocumentPrivate; + QTextStream ts( buffer, IO_ReadOnly ); + QXmlInputSource source( ts ); + return IMPL->setContent( source ); +} + +/*! + \overload +*/ +bool QDomDocument::setContent( const QCString& buffer ) +{ + return setContent( QString::fromUtf8( buffer, buffer.length() ) ); +} + +/*! + \overload +*/ +bool QDomDocument::setContent( QIODevice* dev ) +{ + if ( !impl ) + impl = new QDOM_DocumentPrivate; + QTextStream ts( dev ); + QXmlInputSource source( ts ); + return IMPL->setContent( source ); +} + +/*! + Converts the parsed document back to its textual representation. +*/ +QString QDomDocument::toString() const +{ + QString str; + QTextStream s( str, IO_WriteOnly ); + s << *this; + + return str; +} + +/*! + \fn QCString QDomDocument::toCString() const + + Converts the parsed document back to its textual representation. +*/ + + +/*! + Returns the document type of this document. +*/ +QDomDocumentType QDomDocument::doctype() const +{ + if ( !impl ) + return QDomDocumentType(); + return QDomDocumentType( IMPL->doctype() ); +} + +/*! + Returns a QDomImplementation object. +*/ +QDomImplementation QDomDocument::implementation() const +{ + if ( !impl ) + return QDomImplementation(); + return QDomImplementation( IMPL->implementation() ); +} + +/*! + Returns the root element of the document. +*/ +QDomElement QDomDocument::documentElement() const +{ + if ( !impl ) + return QDomElement(); + return QDomElement( IMPL->documentElement() ); +} + +/*! + Creates a new element with the name \a tagName that can be inserted into the + DOM tree. +*/ +QDomElement QDomDocument::createElement( const QString& tagName ) +{ + if ( !impl ) + return QDomElement(); + return QDomElement( IMPL->createElement( tagName ) ); +} + +/*! + Creates a new document fragment, that can be used to hold parts + of the document, when doing complex manipulations of the document tree. +*/ +QDomDocumentFragment QDomDocument::createDocumentFragment() +{ + if ( !impl ) + return QDomDocumentFragment(); + return QDomDocumentFragment( IMPL->createDocumentFragment() ); +} + +/*! + Creates a text node that can be inserted into the document tree. +*/ +QDomText QDomDocument::createTextNode( const QString& value ) +{ + if ( !impl ) + return QDomText(); + return QDomText( IMPL->createTextNode( value ) ); +} + +/*! + Creates a new comment that can be inserted into the Document. +*/ +QDomComment QDomDocument::createComment( const QString& value ) +{ + if ( !impl ) + return QDomComment(); + return QDomComment( IMPL->createComment( value ) ); +} + +/*! + Creates a new CDATA section that can be inserted into the document. +*/ +QDomCDATASection QDomDocument::createCDATASection( const QString& value ) +{ + if ( !impl ) + return QDomCDATASection(); + return QDomCDATASection( IMPL->createCDATASection( value ) ); +} + +/*! + Creates a new processing instruction that can be inserted into the document. +*/ +QDomProcessingInstruction QDomDocument::createProcessingInstruction( const QString& target, + const QString& data ) +{ + if ( !impl ) + return QDomProcessingInstruction(); + return QDomProcessingInstruction( IMPL->createProcessingInstruction( target, data ) ); +} + + +/*! + Creates a new attribute that can be inserted into an element. +*/ +QDomAttr QDomDocument::createAttribute( const QString& name ) +{ + if ( !impl ) + return QDomAttr(); + return QDomAttr( IMPL->createAttribute( name ) ); +} + +/*! + Creates a new entity reference. +*/ +QDomEntityReference QDomDocument::createEntityReference( const QString& name ) +{ + if ( !impl ) + return QDomEntityReference(); + return QDomEntityReference( IMPL->createEntityReference( name ) ); +} + +/*! + Returns a QDomNodeList, that contains all elements in the document + with the tag name \a tagname. The order of the node list, is the + order they are encountered in a preorder traversal of the element tree. +*/ +QDomNodeList QDomDocument::elementsByTagName( const QString& tagname ) const +{ + return QDomNodeList( new QDOM_NodeListPrivate( impl, tagname ) ); +} + +/*! + Returns \c DocumentNode. +*/ +QDomNode::NodeType QDomDocument::nodeType() const +{ + return DocumentNode; +} + +/*! + Returns TRUE. +*/ +bool QDomDocument::isDocument() const +{ + return TRUE; +} + + +#undef IMPL + +/*==============================================================*/ +/* Node casting functions */ +/*==============================================================*/ + +/*! + Converts a QDomNode into a QDomAttr. If the node is not an attribute, + the returned object will be null. + + \sa isAttr() +*/ +QDomAttr QDomNode::toAttr() +{ + if ( impl && impl->isAttr() ) + return QDomAttr( ((QDOM_AttrPrivate*)impl) ); + return QDomAttr(); +} + +/*! + Converts a QDomNode into a QDomCDATASection. If the node is not a CDATA + section, the returned object will be null. + + \sa isCDATASection() +*/ +QDomCDATASection QDomNode::toCDATASection() +{ + if ( impl && impl->isCDATASection() ) + return QDomCDATASection( ((QDOM_CDATASectionPrivate*)impl) ); + return QDomCDATASection(); +} + +/*! + Converts a QDomNode into a QDomDocumentFragment. If the node is not a + document fragment the returned object will be null. + + \sa isDocumentFragment() +*/ +QDomDocumentFragment QDomNode::toDocumentFragment() +{ + if ( impl && impl->isDocumentFragment() ) + return QDomDocumentFragment( ((QDOM_DocumentFragmentPrivate*)impl) ); + return QDomDocumentFragment(); +} + +/*! + Converts a QDomNode into a QDomDocument. If the node is not a document + the returned object will be null. + + \sa isDocument() +*/ +QDomDocument QDomNode::toDocument() +{ + if ( impl && impl->isDocument() ) + return QDomDocument( ((QDOM_DocumentPrivate*)impl) ); + return QDomDocument(); +} + +/*! + Converts a QDomNode into a QDomDocumentType. If the node is not a document + type the returned object will be null. + + \sa isDocumentType() +*/ +QDomDocumentType QDomNode::toDocumentType() +{ + if ( impl && impl->isDocumentType() ) + return QDomDocumentType( ((QDOM_DocumentTypePrivate*)impl) ); + return QDomDocumentType(); +} + +/*! + Converts a QDomNode into a QDomElement. If the node is not an element + the returned object will be null. + + \sa isElement() +*/ +QDomElement QDomNode::toElement() +{ + if ( impl && impl->isElement() ) + return QDomElement( ((QDOM_ElementPrivate*)impl) ); + return QDomElement(); +} + +/*! + Converts a QDomNode into a QDomEntityReference. If the node is not an entity + reference, the returned object will be null. + + \sa isEntityReference() +*/ +QDomEntityReference QDomNode::toEntityReference() +{ + if ( impl && impl->isEntityReference() ) + return QDomEntityReference( ((QDOM_EntityReferencePrivate*)impl) ); + return QDomEntityReference(); +} + +/*! + Converts a QDomNode into a QDomText. If the node is not a text, the returned + object will be null. + + \sa isText() +*/ +QDomText QDomNode::toText() +{ + if ( impl && impl->isText() ) + return QDomText( ((QDOM_TextPrivate*)impl) ); + return QDomText(); +} + +/*! + Converts a QDomNode into a QDomEntity. If the node is not an entity the + returned object will be null. + + \sa isEntity() +*/ +QDomEntity QDomNode::toEntity() +{ + if ( impl && impl->isEntity() ) + return QDomEntity( ((QDOM_EntityPrivate*)impl) ); + return QDomEntity(); +} + +/*! + Converts a QDomNode into a QDomNotation. If the node is not a notation + the returned object will be null. + + \sa isNotation() +*/ +QDomNotation QDomNode::toNotation() +{ + if ( impl && impl->isNotation() ) + return QDomNotation( ((QDOM_NotationPrivate*)impl) ); + return QDomNotation(); +} + +/*! + Converts a QDomNode into a QDomProcessingInstruction. If the node is not a + processing instruction the returned object will be null. + + \sa isProcessingInstruction() +*/ +QDomProcessingInstruction QDomNode::toProcessingInstruction() +{ + if ( impl && impl->isProcessingInstruction() ) + return QDomProcessingInstruction( ((QDOM_ProcessingInstructionPrivate*)impl) ); + return QDomProcessingInstruction(); +} + +/*! + Converts a QDomNode into a QDomCharacterData. If the node is not a character + data node the returned object will be null. + + \sa isCharacterData() +*/ +QDomCharacterData QDomNode::toCharacterData() +{ + if ( impl && impl->isCharacterData() ) + return QDomCharacterData( ((QDOM_CharacterDataPrivate*)impl) ); + return QDomCharacterData(); +} + +/*! + Converts a QDomNode into a QDomComment. If the node is not a comment the + returned object will be null. + + \sa isComment() +*/ +QDomComment QDomNode::toComment() +{ + if ( impl && impl->isComment() ) + return QDomComment( ((QDOM_CommentPrivate*)impl) ); + return QDomComment(); +} + +/*==============================================================*/ +/* QDomHandler */ +/*==============================================================*/ + +QDomHandler::QDomHandler( QDOM_DocumentPrivate* adoc ) +{ + doc = adoc; + node = doc; + cdata = FALSE; +} + +QDomHandler::~QDomHandler() +{ +} + +void QDomHandler::setDocumentLocator( QXmlLocator* locator ) +{ + loc = locator; +} + +bool QDomHandler::endDocument() +{ + // ### is this really necessary? (rms) + if ( node != doc ) + return FALSE; + return TRUE; +} + +bool QDomHandler::startDTD( const QString& name, const QString&, const QString&) +{ + doc->doctype()->name = name; + return TRUE; +} + +bool QDomHandler::startElement( const QString&, const QString&, const QString& qName, const QXmlAttributes& atts ) +{ + // tag name +#if 0 + // ### do we really need this? + if ( node == doc ) { + // Has to be a special tag + if ( qName != doc->doctype()->nodeName() ) { + // TODO: Exception + return FALSE; + } + } +#endif + QDOM_NodePrivate* n = doc->createElement( qName ); + node->appendChild( n ); + node = n; + + // attributes + for ( int i=0; iisElement() ) { + // TODO: Exception + return FALSE; + } + ((QDOM_ElementPrivate*)node)->setAttribute( atts.qName(i), atts.value(i) ); + } + + return TRUE; +} + +bool QDomHandler::endElement( const QString&, const QString&, const QString& ) +{ + if ( node == doc ) + return FALSE; + node = node->parent; + + return TRUE; +} + +bool QDomHandler::characters( const QString& ch ) +{ + // No text as child of some document + if ( node == doc ) + return FALSE; + + if ( cdata ) { + node->appendChild( doc->createCDATASection( ch ) ); + } else { + node->appendChild( doc->createTextNode( ch ) ); + } + + return TRUE; +} + +bool QDomHandler::processingInstruction( const QString& target, const QString& data ) +{ + node->appendChild( doc->createProcessingInstruction( target, data ) ); + return TRUE; +} + +bool QDomHandler::fatalError( const QXmlParseException& exception ) +{ + qDebug( "fatal parsing error: " + exception.message() + " in line %d", + exception.lineNumber() ); + return QXmlDefaultHandler::fatalError( exception ); +} + +bool QDomHandler::startCDATA() +{ + cdata = TRUE; + return TRUE; +} + +bool QDomHandler::endCDATA() +{ + cdata = FALSE; + return TRUE; +} + +bool QDomHandler::comment( const QString& ch ) +{ + node->appendChild( doc->createComment( ch ) ); + return TRUE; +} + +bool QDomHandler::unparsedEntityDecl( const QString &name, const QString &publicId, const QString &systemId, const QString ¬ationName ) +{ + QDOM_EntityPrivate* e = new QDOM_EntityPrivate( doc, 0, name, + publicId, systemId, notationName ); + doc->doctype()->appendChild( e ); + return TRUE; +} + +bool QDomHandler::externalEntityDecl( const QString &name, const QString &publicId, const QString &systemId ) +{ + return unparsedEntityDecl( name, publicId, systemId, QString::null ); +} + +bool QDomHandler::notationDecl( const QString & name, const QString & publicId, const QString & systemId ) +{ + QDOM_NotationPrivate* n = new QDOM_NotationPrivate( doc, 0, name, publicId, systemId ); + doc->doctype()->appendChild( n ); + return TRUE; +} + +#if 0 +bool QDomConsumer::entity( const QString& name, const QString& value ) +{ + QDOM_EntityPrivate* e = new QDOM_EntityPrivate( doc, 0, name, QString::null, QString::null, QString::null ); + e->value = value; + doc->doctype()->appendChild( e ); + + return TRUE; +} + +bool QDomConsumer::entityRef( const QString& name ) +{ + if ( node == doc ) + return FALSE; + + // TODO: Find corresponding entity + QDOM_NamedNodeMapPrivate* m = doc->doctype()->entities; + if ( !m ) + return FALSE; + QDOM_NodePrivate* n = m->namedItem( name ); + if ( !n || !n->isEntity() ) { + qWarning( "Entity of name %s unsupported", name.latin1() ); + return FALSE; + } + + node->appendChild( doc->createEntityReference( name ) ); + + return TRUE; +} +#endif + +//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 @@ +/**************************************************************************** +** $Id$ +** +** Definition of QDomDocument and related classes. +** +** Created : 000518 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the XML module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition licenses may use this +** file in accordance with the Qt Commercial License Agreement provided +** with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +/****************************************** + * DOM support is disabled in QT 2.3.7 for sharp zaurus. + * Because of that we copied the code from 2.3.7 into qtcompat and enabled it + * there. + * Copyright (c) 2004 Ulf Schenk + * + * $Id$ + ******************************************/ + +#ifndef QDOM_H +#define QDOM_H + +#ifndef QT_H +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif // QT_H + +#include + +//US #if !defined(QT_MODULE_XML) +//US #define QM_EXPORT +//US #else +#define QM_EXPORT Q_EXPORT +//US #endif + +//US #ifndef QT_NO_DOM +class QWidget; +class QLayout; +class QIODevice; +class QTextStream; + +class QDOM_DocumentPrivate; +class QDOM_DocumentTypePrivate; +class QDOM_DocumentFragmentPrivate; +class QDOM_NodePrivate; +class QDOM_NodeListPrivate; +class QDOM_ImplementationPrivate; +class QDOM_ElementPrivate; +class QDOM_NotationPrivate; +class QDOM_EntityPrivate; +class QDOM_EntityReferencePrivate; +class QDOM_ProcessingInstructionPrivate; +class QDOM_AttrPrivate; +class QDOM_CharacterDataPrivate; +class QDOM_TextPrivate; +class QDOM_CommentPrivate; +class QDOM_CDATASectionPrivate; +class QDOM_NamedNodeMapPrivate; +class QDOM_ImplementationPrivate; + +class QDomNodeList; +class QDomElement; +class QDomText; +class QDomComment; +class QDomCDATASection; +class QDomProcessingInstruction; +class QDomAttr; +class QDomEntityReference; +class QDomDocument; +class QDomNamedNodeMap; +class QDomDocument; +class QDomDocumentFragment; +class QDomDocumentType; +class QDomImplementation; +class QDomNode; +class QDomEntity; +class QDomNotation; +class QDomCharacterData; + +class QM_EXPORT QDomImplementation +{ +public: + QDomImplementation(); + QDomImplementation( const QDomImplementation& ); + virtual ~QDomImplementation(); + QDomImplementation& operator= ( const QDomImplementation& ); + bool operator== ( const QDomImplementation& ) const; + bool operator!= ( const QDomImplementation& ) const; + + virtual bool hasFeature( const QString& feature, const QString& version ); + + bool isNull(); + +private: + QDomImplementation( QDOM_ImplementationPrivate* ); + + QDOM_ImplementationPrivate* impl; + + friend class QDomDocument; +}; + +class QM_EXPORT QDomNode // Ok +{ +public: + enum NodeType { + BaseNode = 0, + ElementNode = 1, + AttributeNode = 2, + TextNode = 3, + CDATASectionNode = 4, + EntityReferenceNode = 5, + EntityNode = 6, + ProcessingInstructionNode = 7, + CommentNode = 8, + DocumentNode = 9, + DocumentTypeNode = 10, + DocumentFragmentNode = 11, + NotationNode = 12, + CharacterDataNode = 13 + }; + + QDomNode(); + QDomNode( const QDomNode& ); + QDomNode& operator= ( const QDomNode& ); + bool operator== ( const QDomNode& ) const; + bool operator!= ( const QDomNode& ) const; + virtual ~QDomNode(); + + virtual QString nodeName() const; + virtual QString nodeValue() const; + virtual void setNodeValue( const QString& ); + virtual QDomNode::NodeType nodeType() const; + + virtual QDomNode parentNode() const; + virtual QDomNodeList childNodes() const; + virtual QDomNode firstChild() const; + virtual QDomNode lastChild() const; + virtual QDomNode previousSibling() const; + virtual QDomNode nextSibling() const; + virtual QDomNamedNodeMap attributes() const; + virtual QDomDocument ownerDocument() const; + + virtual QDomNode insertBefore( const QDomNode& newChild, const QDomNode& refChild ); + virtual QDomNode insertAfter( const QDomNode& newChild, const QDomNode& refChild ); + virtual QDomNode replaceChild( const QDomNode& newChild, const QDomNode& oldChild ); + virtual QDomNode removeChild( const QDomNode& oldChild ); + virtual QDomNode appendChild( const QDomNode& newChild ); + virtual QDomNode cloneNode( bool deep = TRUE ) const; + + // Qt extension + virtual bool isAttr() const; + virtual bool isCDATASection() const; + virtual bool isDocumentFragment() const; + virtual bool isDocument() const; + virtual bool isDocumentType() const; + virtual bool isElement() const; + virtual bool isEntityReference() const; + virtual bool isText() const; + virtual bool isEntity() const; + virtual bool isNotation() const; + virtual bool isProcessingInstruction() const; + virtual bool isCharacterData() const; + virtual bool isComment() const; + + /** + * Shortcut to avoid dealing with QDomNodeList + * all the time. + */ + QDomNode namedItem( const QString& name ) const; + + bool isNull() const; + void clear(); + + QDomAttr toAttr(); + QDomCDATASection toCDATASection(); + QDomDocumentFragment toDocumentFragment(); + QDomDocument toDocument(); + QDomDocumentType toDocumentType(); + QDomElement toElement(); + QDomEntityReference toEntityReference(); + QDomText toText(); + QDomEntity toEntity(); + QDomNotation toNotation(); + QDomProcessingInstruction toProcessingInstruction(); + QDomCharacterData toCharacterData(); + QDomComment toComment(); + + void save( QTextStream&, int ) const; + +protected: + QDOM_NodePrivate* impl; + QDomNode( QDOM_NodePrivate* ); + +private: + friend class QDomDocument; + friend class QDomDocumentType; + friend class QDomNodeList; + friend class QDomNamedNodeMap; +}; + +class QM_EXPORT QDomNodeList // Ok +{ +public: + QDomNodeList(); + QDomNodeList( const QDomNodeList& ); + QDomNodeList& operator= ( const QDomNodeList& ); + bool operator== ( const QDomNodeList& ) const; + bool operator!= ( const QDomNodeList& ) const; + virtual ~QDomNodeList(); + + virtual QDomNode item( int index ) const; + virtual uint length() const; + uint count() const { return length(); } // Qt API consitancy + + QDomNodeList( QDOM_NodeListPrivate* ); +private: + QDOM_NodeListPrivate* impl; +}; + +class QM_EXPORT QDomDocumentType : public QDomNode +{ +public: + QDomDocumentType(); + QDomDocumentType( const QDomDocumentType& x ); + QDomDocumentType& operator= ( const QDomDocumentType& ); + ~QDomDocumentType(); + + virtual QString name() const; + virtual QDomNamedNodeMap entities() const; + virtual QDomNamedNodeMap notations() const; + + // Reimplemented from QDomNode + QDomNode::NodeType nodeType() const; + bool isDocumentType() const; + +private: + QDomDocumentType( QDOM_DocumentTypePrivate* ); + + friend class QDomDocument; + friend class QDomNode; +}; + +class QM_EXPORT QDomDocument : public QDomNode +{ +public: + QDomDocument(); + QDomDocument( const QString& name ); + QDomDocument( const QDomDocument& x ); + QDomDocument& operator= ( const QDomDocument& ); + ~QDomDocument(); + + // Qt extensions + bool setContent( const QCString& text ); + bool setContent( const QByteArray& text ); + bool setContent( const QString& text ); + bool setContent( QIODevice* dev ); + + // QDomAttributes + QDomDocumentType doctype() const; + QDomImplementation implementation() const; + QDomElement documentElement() const; + + // Factories + QDomElement createElement( const QString& tagName ); + QDomDocumentFragment createDocumentFragment(); + QDomText createTextNode( const QString& data ); + QDomComment createComment( const QString& data ); + QDomCDATASection createCDATASection( const QString& data ); + QDomProcessingInstruction createProcessingInstruction( const QString& target, const QString& data ); + QDomAttr createAttribute( const QString& name ); + QDomEntityReference createEntityReference( const QString& name ); + QDomNodeList elementsByTagName( const QString& tagname ) const; + + // Reimplemented from QDomNode + QDomNode::NodeType nodeType() const; + bool isDocument() const; + + // Qt extensions + QString toString() const; + QCString toCString() const { return toString().utf8(); } + +private: + QDomDocument( QDOM_DocumentPrivate* ); + + friend class QDomNode; +}; + +class QM_EXPORT QDomNamedNodeMap +{ +public: + QDomNamedNodeMap(); + QDomNamedNodeMap( const QDomNamedNodeMap& ); + QDomNamedNodeMap& operator= ( const QDomNamedNodeMap& ); + bool operator== ( const QDomNamedNodeMap& ) const; + bool operator!= ( const QDomNamedNodeMap& ) const; + ~QDomNamedNodeMap(); + + QDomNode namedItem( const QString& name ) const; + QDomNode setNamedItem( const QDomNode& arg ); + QDomNode removeNamedItem( const QString& name ); + QDomNode item( int index ) const; + uint length() const; + bool contains( const QString& name ) const; + +private: + friend class QDomNode; + friend class QDomDocumentType; + friend class QDomElement; + + QDomNamedNodeMap( QDOM_NamedNodeMapPrivate* ); + + QDOM_NamedNodeMapPrivate* impl; +}; + +class QM_EXPORT QDomDocumentFragment : public QDomNode +{ +public: + QDomDocumentFragment(); + QDomDocumentFragment( const QDomDocumentFragment& x ); + QDomDocumentFragment& operator= ( const QDomDocumentFragment& ); + ~QDomDocumentFragment(); + + // Reimplemented from QDomNode + QDomNode::NodeType nodeType() const; + bool isDocumentFragment() const; + +private: + QDomDocumentFragment( QDOM_DocumentFragmentPrivate* ); + + friend class QDomDocument; + friend class QDomNode; +}; + +class QM_EXPORT QDomCharacterData : public QDomNode +{ +public: + QDomCharacterData(); + QDomCharacterData( const QDomCharacterData& x ); + QDomCharacterData& operator= ( const QDomCharacterData& ); + ~QDomCharacterData(); + + virtual QString data() const; + virtual void setData( const QString& ); + virtual uint length() const; + + virtual QString substringData( unsigned long offset, unsigned long count ); + virtual void appendData( const QString& arg ); + virtual void insertData( unsigned long offset, const QString& arg ); + virtual void deleteData( unsigned long offset, unsigned long count ); + virtual void replaceData( unsigned long offset, unsigned long count, const QString& arg ); + + // Reimplemented from QDomNode + QDomNode::NodeType nodeType() const; + bool isCharacterData() const; + +private: + QDomCharacterData( QDOM_CharacterDataPrivate* ); + + friend class QDomDocument; + friend class QDomText; + friend class QDomComment; + friend class QDomNode; +}; + +class QM_EXPORT QDomAttr : public QDomNode +{ +public: + QDomAttr(); + QDomAttr( const QDomAttr& x ); + QDomAttr& operator= ( const QDomAttr& ); + ~QDomAttr(); + + virtual QString name() const; + virtual bool specified() const; + virtual QString value() const; + virtual void setValue( const QString& ); + + // Reimplemented from QDomNode + QDomNode::NodeType nodeType() const; + bool isAttr() const; + +private: + QDomAttr( QDOM_AttrPrivate* ); + + friend class QDomDocument; + friend class QDomElement; + friend class QDomNode; +}; + +class QM_EXPORT QDomElement : public QDomNode +{ +public: + QDomElement(); + QDomElement( const QDomElement& x ); + QDomElement& operator= ( const QDomElement& ); + ~QDomElement(); + + void setTagName( const QString& name ); + QString tagName() const; + QString attribute( const QString& name, const QString& defValue = QString::null ) const; + void setAttribute( const QString& name, const QString& value ); + void setAttribute( const QString& name, int value ); + void setAttribute( const QString& name, uint value ); + void setAttribute( const QString& name, double value ); + void removeAttribute( const QString& name ); + QDomAttr attributeNode( const QString& name); + QDomAttr setAttributeNode( const QDomAttr& newAttr ); + QDomAttr removeAttributeNode( const QDomAttr& oldAttr ); + bool hasAttribute( const QString& name ) const; + virtual QDomNodeList elementsByTagName( const QString& tagname ) const; + void normalize(); + + // Reimplemented from QDomNode + QDomNamedNodeMap attributes() const; + QDomNode::NodeType nodeType() const; + bool isElement() const; + + QString text() const; + +private: + QDomElement( QDOM_ElementPrivate* ); + + friend class QDomDocument; + friend class QDomNode; +}; + +class QM_EXPORT QDomText : public QDomCharacterData +{ +public: + QDomText(); + QDomText( const QDomText& x ); + QDomText& operator= ( const QDomText& ); + ~QDomText(); + + QDomText splitText( int offset ); + + // Reimplemented from QDomNode + QDomNode::NodeType nodeType() const; + bool isText() const; + +private: + QDomText( QDOM_TextPrivate* ); + + friend class QDomCDATASection; + friend class QDomDocument; + friend class QDomNode; +}; + +class QM_EXPORT QDomComment : public QDomCharacterData +{ +public: + QDomComment(); + QDomComment( const QDomComment& x ); + QDomComment& operator= ( const QDomComment& ); + ~QDomComment(); + + // Reimplemented from QDomNode + QDomNode::NodeType nodeType() const; + bool isComment() const; + +private: + QDomComment( QDOM_CommentPrivate* ); + + friend class QDomDocument; + friend class QDomNode; +}; + +class QM_EXPORT QDomCDATASection : public QDomText +{ +public: + QDomCDATASection(); + QDomCDATASection( const QDomCDATASection& x ); + QDomCDATASection& operator= ( const QDomCDATASection& ); + ~QDomCDATASection(); + + // Reimplemented from QDomNode + QDomNode::NodeType nodeType() const; + bool isCDATASection() const; + +private: + QDomCDATASection( QDOM_CDATASectionPrivate* ); + + friend class QDomDocument; + friend class QDomNode; +}; + +class QM_EXPORT QDomNotation : public QDomNode +{ +public: + QDomNotation(); + QDomNotation( const QDomNotation& x ); + QDomNotation& operator= ( const QDomNotation& ); + ~QDomNotation(); + + QString publicId() const; + QString systemId() const; + + // Reimplemented from QDomNode + QDomNode::NodeType nodeType() const; + bool isNotation() const; + +private: + QDomNotation( QDOM_NotationPrivate* ); + + friend class QDomDocument; + friend class QDomNode; +}; + +class QM_EXPORT QDomEntity : public QDomNode +{ +public: + QDomEntity(); + QDomEntity( const QDomEntity& x ); + QDomEntity& operator= ( const QDomEntity& ); + ~QDomEntity(); + + virtual QString publicId() const; + virtual QString systemId() const; + virtual QString notationName() const; + + // Reimplemented from QDomNode + QDomNode::NodeType nodeType() const; + bool isEntity() const; + +private: + QDomEntity( QDOM_EntityPrivate* ); + + friend class QDomNode; +}; + +class QM_EXPORT QDomEntityReference : public QDomNode +{ +public: + QDomEntityReference(); + QDomEntityReference( const QDomEntityReference& x ); + QDomEntityReference& operator= ( const QDomEntityReference& ); + ~QDomEntityReference(); + + // Reimplemented from QDomNode + QDomNode::NodeType nodeType() const; + bool isEntityReference() const; + +private: + QDomEntityReference( QDOM_EntityReferencePrivate* ); + + friend class QDomDocument; + friend class QDomNode; +}; + +class QM_EXPORT QDomProcessingInstruction : public QDomNode +{ +public: + QDomProcessingInstruction(); + QDomProcessingInstruction( const QDomProcessingInstruction& x ); + QDomProcessingInstruction& operator= ( const QDomProcessingInstruction& ); + ~QDomProcessingInstruction(); + + virtual QString target() const; + virtual QString data() const; + virtual void setData( const QString& d ); + + // Reimplemented from QDomNode + QDomNode::NodeType nodeType() const; + bool isProcessingInstruction() const; + +private: + QDomProcessingInstruction( QDOM_ProcessingInstructionPrivate* ); + + friend class QDomDocument; + friend class QDomNode; +}; + + +QM_EXPORT QTextStream& operator<<( QTextStream&, const QDomNode& ); + +//US #endif //QT_NO_DOM +#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 @@ +/**************************************************************************** +** $Id$ +** +** Implementation of QXmlSimpleReader and related classes. +** +** Created : 000518 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the XML module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition licenses may use this +** file in accordance with the Qt Commercial License Agreement provided +** with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + + +/****************************************** + * DOM support is disabled in QT 2.3.7 for sharp zaurus. + * Because of that we copied the code from 2.3.7 into qtcompat and enabled it + * there. + * Copyright (c) 2004 Ulf Schenk + * + * $Id$ + ******************************************/ + +#define QT_XML_CPP +#include "qxml.h" +#include "qtextcodec.h" +#include "qbuffer.h" + +//US #ifndef QT_NO_XML +// NOT REVISED + +// Error strings for the XML reader +#define XMLERR_OK "no error occured" +#define XMLERR_TAGMISMATCH "tag mismatch" +#define XMLERR_UNEXPECTEDEOF "unexpected end of file" +#define XMLERR_FINISHEDPARSINGWHILENOTEOF "parsing is finished but end of file is not reached" +#define XMLERR_LETTEREXPECTED "letter is expected" +#define XMLERR_ERRORPARSINGELEMENT "error while parsing element" +#define XMLERR_ERRORPARSINGPROLOG "error while parsing prolog" +#define XMLERR_ERRORPARSINGMAINELEMENT "error while parsing main element" +#define XMLERR_ERRORPARSINGCONTENT "error while parsing content" +#define XMLERR_ERRORPARSINGNAME "error while parsing name" +#define XMLERR_ERRORPARSINGNMTOKEN "error while parsing Nmtoken" +#define XMLERR_ERRORPARSINGATTRIBUTE "error while parsing attribute" +#define XMLERR_ERRORPARSINGMISC "error while parsing misc" +#define XMLERR_ERRORPARSINGCHOICE "error while parsing choice or seq" +#define XMLERR_ERRORBYCONSUMER "error triggered by consumer" +#define XMLERR_UNEXPECTEDCHARACTER "unexpected character" +#define XMLERR_EQUALSIGNEXPECTED "expected '=' but not found" +#define XMLERR_QUOTATIONEXPECTED "expected \" or ' but not found" +#define XMLERR_ERRORPARSINGREFERENCE "error while parsing reference" +#define XMLERR_ERRORPARSINGPI "error while parsing processing instruction" +#define XMLERR_ERRORPARSINGATTLISTDECL "error while parsing attribute list declaration" +#define XMLERR_ERRORPARSINGATTTYPE "error while parsing attribute type declaration" +#define XMLERR_ERRORPARSINGATTVALUE "error while parsing attribute value declaration" +#define XMLERR_ERRORPARSINGELEMENTDECL "error while parsing element declaration" +#define XMLERR_ERRORPARSINGENTITYDECL "error while parsing entity declaration" +#define XMLERR_ERRORPARSINGNOTATIONDECL "error while parsing notation declaration" +#define XMLERR_ERRORPARSINGEXTERNALID "error while parsing external id" +#define XMLERR_ERRORPARSINGCOMMENT "error while parsing comment" +#define XMLERR_ERRORPARSINGENTITYVALUE "error while parsing entity value declaration" +#define XMLERR_CDSECTHEADEREXPECTED "expected the header for a cdata section" +#define XMLERR_MORETHANONEDOCTYPE "more than one document type definition" +#define XMLERR_ERRORPARSINGDOCTYPE "error while parsing document type definition" +#define XMLERR_INVALIDNAMEFORPI "invalid name for processing instruction" +#define XMLERR_VERSIONEXPECTED "version expected while reading the XML declaration" +#define XMLERR_EDECLORSDDECLEXPECTED "EDecl or SDDecl expected while reading the XML declaration" +#define XMLERR_SDDECLEXPECTED "SDDecl expected while reading the XML declaration" +#define XMLERR_WRONGVALUEFORSDECL "wrong value for standalone declaration" +#define XMLERR_UNPARSEDENTITYREFERENCE "unparsed entity reference in wrong context" +#define XMLERR_INTERNALGENERALENTITYINDTD "internal general entity reference not allowed in DTD" +#define XMLERR_EXTERNALGENERALENTITYINDTD "external parsed general entity reference not allowed in DTD" +#define XMLERR_EXTERNALGENERALENTITYINAV "external parsed general entity reference not allowed in attribute value" + + +// the constants for the lookup table +static const signed char cltWS = 0; // white space +static const signed char cltPer = 1; // % +static const signed char cltAmp = 2; // & +static const signed char cltGt = 3; // > +static const signed char cltLt = 4; // < +static const signed char cltSlash = 5; // / +static const signed char cltQm = 6; // ? +static const signed char cltEm = 7; // ! +static const signed char cltDash = 8; // - +static const signed char cltCB = 9; // ] +static const signed char cltOB = 10; // [ +static const signed char cltEq = 11; // = +static const signed char cltDq = 12; // " +static const signed char cltSq = 13; // ' +static const signed char cltUnknown = 14; + +// character lookup table +static const signed char charLookupTable[256]={ + cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x00 - 0x07 + cltUnknown, // 0x08 + cltWS, // 0x09 \t + cltWS, // 0x0A \n + cltUnknown, // 0x0B + cltUnknown, // 0x0C + cltWS, // 0x0D \r + cltUnknown, // 0x0E + cltUnknown, // 0x0F + cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x17 - 0x16 + cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x18 - 0x1F + cltWS, // 0x20 Space + cltEm, // 0x21 ! + cltDq, // 0x22 " + cltUnknown, // 0x23 + cltUnknown, // 0x24 + cltPer, // 0x25 % + cltAmp, // 0x26 & + cltSq, // 0x27 ' + cltUnknown, // 0x28 + cltUnknown, // 0x29 + cltUnknown, // 0x2A + cltUnknown, // 0x2B + cltUnknown, // 0x2C + cltDash, // 0x2D - + cltUnknown, // 0x2E + cltSlash, // 0x2F / + cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x30 - 0x37 + cltUnknown, // 0x38 + cltUnknown, // 0x39 + cltUnknown, // 0x3A + cltUnknown, // 0x3B + cltLt, // 0x3C < + cltEq, // 0x3D = + cltGt, // 0x3E > + cltQm, // 0x3F ? + cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x40 - 0x47 + cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x48 - 0x4F + cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x50 - 0x57 + cltUnknown, // 0x58 + cltUnknown, // 0x59 + cltUnknown, // 0x5A + cltOB, // 0x5B [ + cltUnknown, // 0x5C + cltCB, // 0x5D ] + cltUnknown, // 0x5E + cltUnknown, // 0x5F + cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x60 - 0x67 + cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x68 - 0x6F + cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x70 - 0x77 + cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x78 - 0x7F + cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x80 - 0x87 + cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x88 - 0x8F + cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x90 - 0x97 + cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x98 - 0x9F + cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xA0 - 0xA7 + cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xA8 - 0xAF + cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xB0 - 0xB7 + cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xB8 - 0xBF + cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xC0 - 0xC7 + cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xC8 - 0xCF + cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xD0 - 0xD7 + cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xD8 - 0xDF + cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xE0 - 0xE7 + cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xE8 - 0xEF + cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xF0 - 0xF7 + cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown // 0xF8 - 0xFF +}; + + +class QXmlNamespaceSupportPrivate +{ +}; +class QXmlAttributesPrivate +{ +}; +class QXmlInputSourcePrivate +{ +}; +class QXmlParseExceptionPrivate +{ +}; +class QXmlLocatorPrivate +{ +}; +class QXmlDefaultHandlerPrivate +{ +}; + +#if defined(Q_FULL_TEMPLATE_INSTANTIATION) +bool operator==( const QMap, const QMap ) +{ + return FALSE; +} +#endif + +/*! + \class QXmlParseException qxml.h + \brief The QXmlParseException class is used to report errors with the + QXmlErrorHandler interface. + + \module XML + + \sa QXmlErrorHandler +*/ +/*! + \fn QXmlParseException::QXmlParseException( const QString& name, int c, int l, const QString& p, const QString& s ) + + Constructs a parse exception with the error string \a name in the column + \a c and line \a l for the public identifier \a p and the system identifier + \a s. +*/ +/*! + Returns the error message. +*/ +QString QXmlParseException::message() const +{ + return msg; +} +/*! + Returns the column number the error occured. +*/ +int QXmlParseException::columnNumber() const +{ + return column; +} +/*! + Returns the line number the error occured. +*/ +int QXmlParseException::lineNumber() const +{ + return line; +} +/*! + Returns the public identifier the error occured. +*/ +QString QXmlParseException::publicId() const +{ + return pub; +} +/*! + Returns the system identifier the error occured. +*/ +QString QXmlParseException::systemId() const +{ + return sys; +} + + +/*! + \class QXmlLocator qxml.h + \brief The QXmlLocator class provides the XML handler classes with + information about the actual parsing position. + + \module XML + + The reader reports a QXmlLocator to the content handler before he starts to + parse the document. This is done with the + QXmlContentHandler::setDocumentLocator() function. The handler classes can + now use this locator to get the actual position the reader is at. +*/ +/*! + \fn QXmlLocator::QXmlLocator( QXmlSimpleReader* parent ) + + Constructor. +*/ +/*! + \fn QXmlLocator::~QXmlLocator() + + Destructor. +*/ +/*! + Gets the column number (starting with 1) or -1 if there is no column number + available. +*/ +int QXmlLocator::columnNumber() +{ + return ( reader->columnNr == -1 ? -1 : reader->columnNr + 1 ); +} +/*! + Gets the line number (starting with 1) or -1 if there is no line number + available. +*/ +int QXmlLocator::lineNumber() +{ + return ( reader->lineNr == -1 ? -1 : reader->lineNr + 1 ); +} + + +/********************************************* + * + * QXmlNamespaceSupport + * + *********************************************/ + +/*! + \class QXmlNamespaceSupport qxml.h + \brief The QXmlNamespaceSupport class is a helper class for XML readers which + want to include namespace support. + + \module XML + + It provides some functions that makes it easy to handle namespaces. Its main + use is for subclasses of QXmlReader which want to provide namespace + support. + + See also the namespace description. +*/ + +/*! + Constructs a QXmlNamespaceSupport. +*/ +QXmlNamespaceSupport::QXmlNamespaceSupport() +{ + reset(); +} + +/*! + Destructs a QXmlNamespaceSupport. +*/ +QXmlNamespaceSupport::~QXmlNamespaceSupport() +{ +} + +/*! + This function declares a prefix in the current namespace context; the prefix + will remain in force until this context is popped, unless it is shadowed in a + descendant context. + + Note that there is an asymmetry in this library: while prefix() will not + return the default "" prefix, even if you have declared one; to check for a + default prefix, you have to look it up explicitly using uri(). This + asymmetry exists to make it easier to look up prefixes for attribute names, + where the default prefix is not allowed. +*/ +void QXmlNamespaceSupport::setPrefix( const QString& pre, const QString& uri ) +{ + if( pre.isNull() ) { + ns.insert( "", uri ); + } else { + ns.insert( pre, uri ); + } +} + +/*! + Returns one of the prefixes mapped to a namespace URI. + + If more than one prefix is currently mapped to the same URI, this function + will make an arbitrary selection; if you want all of the prefixes, use the + prefixes() function instead. + + Note: this will never return the empty (default) prefix; to check for a + default prefix, use the uri() function with an argument of "". +*/ +QString QXmlNamespaceSupport::prefix( const QString& uri ) const +{ + QMap::ConstIterator itc, it = ns.begin(); + while ( (itc=it) != ns.end() ) { + ++it; + if ( itc.data() == uri && !itc.key().isEmpty() ) + return itc.key(); + } + return ""; +} + +/*! + Looks up a prefix in the current context and returns the currently-mapped + namespace URI. Use the empty string ("") for the default namespace. +*/ +QString QXmlNamespaceSupport::uri( const QString& prefix ) const +{ + const QString& returi = ns[ prefix ]; + return returi; +} + +/*! + Splits the name at the ':' and returns the prefix and the local name. +*/ +void QXmlNamespaceSupport::splitName( const QString& qname, + QString& prefix, QString& localname ) const +{ + uint pos; + // search the ':' + for( pos=0; pos +
  • The namespace URI, or an empty string if none is in use. +
  • The local name (without prefix). + + + If the raw name has a prefix that has not been declared, then the return + value will be empty. + + Note that attribute names are processed differently than element names: an + unprefixed element name will received the default namespace (if any), while + an unprefixed element name will not +*/ +void QXmlNamespaceSupport::processName( const QString& qname, + bool isAttribute, + QString& nsuri, QString& localname ) const +{ + uint pos; + // search the ':' + for( pos=0; pos::ConstIterator itc, it = ns.begin(); + while ( (itc=it) != ns.end() ) { + ++it; + if ( !itc.key().isEmpty() ) + list.append( itc.key() ); + } + return list; +} + +/*! + Returns a list of all prefixes currently declared for a URI. + + The xml: prefix will be included. If you want only one prefix that's + mapped to the namespace URI, and you don't care which one you get, use the + prefix() function instead. + + Note: the empty (default) prefix is never included in this enumeration; to + check for the presence of a default namespace, use uri() with an + argument of "". +*/ +QStringList QXmlNamespaceSupport::prefixes( const QString& uri ) const +{ + QStringList list; + + QMap::ConstIterator itc, it = ns.begin(); + while ( (itc=it) != ns.end() ) { + ++it; + if ( itc.data() == uri && !itc.key().isEmpty() ) + list.append( itc.key() ); + } + return list; +} + +/*! + Starts a new namespace context. + + Normally, you should push a new context at the beginning of each XML element: + the new context will automatically inherit the declarations of its parent + context, but it will also keep track of which declarations were made within + this context. +*/ +void QXmlNamespaceSupport::pushContext() +{ + nsStack.push( ns ); +} + +/*! + Reverts to the previous namespace context. + + Normally, you should pop the context at the end of each XML element. After + popping the context, all namespace prefix mappings that were previously in + force are restored. +*/ +void QXmlNamespaceSupport::popContext() +{ + if( !nsStack.isEmpty() ) + ns = nsStack.pop(); +} + +/*! + Resets this namespace support object for reuse. +*/ +void QXmlNamespaceSupport::reset() +{ + nsStack.clear(); + ns.clear(); + ns.insert( "xml", "http://www.w3.org/XML/1998/namespace" ); // the XML namespace +} + + + +/********************************************* + * + * QXmlAttributes + * + *********************************************/ + +/*! + \class QXmlAttributes qxml.h + \brief The QXmlAttributes class provides XML attributes. + + \module XML + + If attributes are reported by QXmlContentHandler::startElement() this + class is used to pass the attribute values. It provides you with different + functions to access the attribute names and values. +*/ +/*! + \fn QXmlAttributes::QXmlAttributes() + + Constructs an empty attribute list. +*/ +/*! + \fn QXmlAttributes::~QXmlAttributes() + + Destructs attributes. +*/ + +/*! + Look up the index of an attribute by an XML 1.0 qualified name. + + Returns the index of the attribute (starting with 0) or -1 if it wasn't + found. + + See also the namespace description. +*/ +int QXmlAttributes::index( const QString& qName ) const +{ + return qnameList.findIndex( qName ); +} + +/*! + Looks up the index of an attribute by a namespace name. + + \a uri specifies the namespace URI, or the empty string if the name has no + namespace URI. \a localPart specifies the attribute's local name. + + Returns the index of the attribute (starting with 0) or -1 if it wasn't + found. + + See also the namespace description. +*/ +int QXmlAttributes::index( const QString& uri, const QString& localPart ) const +{ + uint count = uriList.count(); + for ( uint i=0; inamespace description. +*/ +QString QXmlAttributes::localName( int index ) const +{ + return localnameList[index]; +} + +/*! + Looks up an attribute's XML 1.0 qualified name by index (starting with 0). + + See also the namespace description. +*/ +QString QXmlAttributes::qName( int index ) const +{ + return qnameList[index]; +} + +/*! + Looks up an attribute's namespace URI by index (starting with 0). + + See also the namespace description. +*/ +QString QXmlAttributes::uri( int index ) const +{ + return uriList[index]; +} + +/*! + Looks up an attribute's type by index (starting with 0). + + At the moment only 'CDATA' is returned. +*/ +QString QXmlAttributes::type( int ) const +{ + return "CDATA"; +} + +/*! + Looks up an attribute's type by XML 1.0 qualified name. + + At the moment only 'CDATA' is returned. +*/ +QString QXmlAttributes::type( const QString& ) const +{ + return "CDATA"; +} + +/*! + Looks up an attribute's type by namespace name. + + The first parameter specifies the namespace URI, or the empty string if + the name has no namespace URI. The second parameter specifies the + attribute's local name. + + At the moment only 'CDATA' is returned. +*/ +QString QXmlAttributes::type( const QString&, const QString& ) const +{ + return "CDATA"; +} + +/*! + Looks up an attribute's value by index (starting with 0). +*/ +QString QXmlAttributes::value( int index ) const +{ + return valueList[index]; +} + +/*! + Looks up an attribute's value by XML 1.0 qualified name. + + See also the namespace description. +*/ +QString QXmlAttributes::value( const QString& qName ) const +{ + int i = index( qName ); + if ( i == -1 ) + return QString::null; + return valueList[ i ]; +} + +/*! + Looks up an attribute's value by namespace name. + + \a uri specifies the namespace URI, or the empty string if the name has no + namespace URI. \a localName specifies the attribute's local name. + + See also the namespace description. +*/ +QString QXmlAttributes::value( const QString& uri, const QString& localName ) const +{ + int i = index( uri, localName ); + if ( i == -1 ) + return QString::null; + return valueList[ i ]; +} + + +/********************************************* + * + * QXmlInputSource + * + *********************************************/ + +/*! + \class QXmlInputSource qxml.h + \brief The QXmlInputSource class is the source where XML data is read from. + + \module XML + + All subclasses of QXmlReader read the input from this class. +*/ + +/*! + Returns all the data this input source contains. +*/ +const QString& QXmlInputSource::data() const +{ + return input; +} + +/*! + Constructs a input source which contains no data. +*/ +QXmlInputSource::QXmlInputSource( ) +{ + input = ""; +} + +/*! + Constructs a input source and get the data from the text stream. +*/ +QXmlInputSource::QXmlInputSource( QTextStream& stream ) +{ + QByteArray rawData; + if ( stream.device()->isDirectAccess() ) { + rawData = stream.device()->readAll(); + } else { + int nread = 0; + const int bufsize = 512; + while ( !stream.device()->atEnd() ) { + rawData.resize( nread + bufsize ); + nread += stream.device()->readBlock( rawData.data()+nread, bufsize ); + } + rawData.resize( nread ); + } + readInput( rawData ); +} + +/*! + Constructs a input source and get the data from a file. If the file cannot be + read the input source is empty. +*/ +QXmlInputSource::QXmlInputSource( QFile& file ) +{ + if ( !file.open(IO_ReadOnly) ) { + input = ""; + return; + } + QByteArray rawData = file.readAll(); + readInput( rawData ); + file.close(); +} + +/*! + Destructor. +*/ +QXmlInputSource::~QXmlInputSource() +{ +} + +/*! + Sets the data of the input source to \a dat. +*/ +void QXmlInputSource::setData( const QString& dat ) +{ + input = dat; +} + +/*! + Read the XML file from the byte array; try to recoginize the encoding. +*/ +// ### The input source should not do the encoding detection! +void QXmlInputSource::readInput( QByteArray& rawData ) +{ + QBuffer buf( rawData ); + buf.open( IO_ReadOnly ); + QTextStream *stream = new QTextStream( &buf ); + QChar tmp; + // assume UTF8 or UTF16 at first + stream->setEncoding( QTextStream::UnicodeUTF8 ); + input = ""; + // read the first 5 characters + for ( int i=0; i<5; i++ ) { + *stream >> tmp; + input += tmp; + } + // starts the document with an XML declaration? + if ( input == "> tmp; + input += tmp; + } while( tmp != '>' ); + // and try to find out if there is an encoding + int pos = input.find( "encoding" ); + if ( pos != -1 ) { + QString encoding; + do { + pos++; + if ( pos > (int)input.length() ) + goto finished; + } while( input[pos] != '"' && input[pos] != '\'' ); + pos++; + while( input[pos] != '"' && input[pos] != '\'' ) { + encoding += input[pos]; + pos++; + if ( pos > (int)input.length() ) + goto finished; + } + delete stream; + stream = new QTextStream( &buf ); + stream->setCodec( QTextCodec::codecForName( encoding ) ); + buf.reset(); + input = ""; + } + } +finished: + input += stream->read(); + delete stream; + buf.close(); +} + + +/********************************************* + * + * QXmlDefaultHandler + * + *********************************************/ + +/*! + \class QXmlContentHandler qxml.h + \brief The QXmlContentHandler class provides an interface to report logical + content of XML data. + + \module XML + + If the application needs to be informed of basic parsing events, it + implements this interface and sets it with QXmlReader::setContentHandler(). + The reader reports basic document-related events like the start and end of + elements and character data through this interface. + + The order of events in this interface is very important, and mirrors the + order of information in the document itself. For example, all of an element's + content (character data, processing instructions, and/or subelements) will + appear, in order, between the startElement() event and the corresponding + endElement() event. + + The class QXmlDefaultHandler gives a default implementation for this + interface; subclassing from this class is very convenient if you want only be + informed of some parsing events. + + See also the Introduction to SAX2. + + \sa QXmlDTDHandler QXmlDeclHandler QXmlEntityResolver QXmlErrorHandler + QXmlLexicalHandler +*/ +/*! + \fn void QXmlContentHandler::setDocumentLocator( QXmlLocator* locator ) + + The reader calls this function before he starts parsing the document. The + argument \a locator is a pointer to a QXmlLocator which allows the + application to get the actual position of the parsing in the document. + + Do not destroy the \a locator; it is destroyed when the reader is destroyed + (do not use the \a locator after the reader got destroyed). +*/ +/*! + \fn bool QXmlContentHandler::startDocument() + + The reader calls this function when he starts parsing the document. + The reader will call this function only once before any other functions in + this class or in the QXmlDTDHandler class are called (except + QXmlContentHandler::setDocumentLocator()). + + If this function returns FALSE the reader will stop parsing and will report + an error. The reader will use the function errorString() to get the error + message that will be used for reporting the error. + + \sa endDocument() +*/ +/*! + \fn bool QXmlContentHandler::endDocument() + + The reader calls this function after he has finished the parsing. It + is only called once. It is the last function of all handler functions that is + called. It is called after the reader has read all input or has abandoned + parsing because of a fatal error. + + If this function returns FALSE the reader will stop parsing and will report + an error. The reader will use the function errorString() to get the error + message that will be used for reporting the error. + + \sa startDocument() +*/ +/*! + \fn bool QXmlContentHandler::startPrefixMapping( const QString& prefix, const QString& uri ) + + The reader calls this function to signal the begin of a prefix-URI + namespace mapping scope. This information is not necessary for normal + namespace processing since the reader automatically replaces prefixes for + element and attribute names. + + Note that startPrefixMapping and endPrefixMapping calls are not guaranteed to + be properly nested relative to each-other: all startPrefixMapping events will + occur before the corresponding startElement event, and all endPrefixMapping + events will occur after the corresponding endElement event, but their order + is not otherwise guaranteed. + + The argument \a prefix is the namespace prefix being declared and the + argument \a uri is the namespace URI the prefix is mapped to. + + If this function returns FALSE the reader will stop parsing and will report + an error. The reader will use the function errorString() to get the error + message that will be used for reporting the error. + + See also the namespace description. + + \sa endPrefixMapping() +*/ +/*! + \fn bool QXmlContentHandler::endPrefixMapping( const QString& prefix ) + + The reader calls this function to signal the end of a prefix mapping. + + If this function returns FALSE the reader will stop parsing and will report + an error. The reader will use the function errorString() to get the error + message that will be used for reporting the error. + + See also the namespace description. + + \sa startPrefixMapping() +*/ +/*! + \fn bool QXmlContentHandler::startElement( const QString& namespaceURI, const QString& localName, const QString& qName, const QXmlAttributes& atts ) + + The reader calls this function when he has parsed a start element tag. + + There will be a corresponding endElement() call when the corresponding end + element tag was read. The startElement() and endElement() calls are always + nested correctly. Empty element tags (e.g. <a/>) are reported by + startElement() directly followed by a call to endElement(). + + The attribute list provided will contain only attributes with explicit + values. The attribute list will contain attributes used for namespace + declaration (i.e. attributes starting with xmlns) only if the + namespace-prefix property of the reader is TRUE. + + The argument \a uri is the namespace URI, or the empty string if the element + has no namespace URI or if namespace processing is not being performed, \a + localName is the local name (without prefix), or the empty string if + namespace processing is not being performed, \a qName is the qualified name + (with prefix), or the empty string if qualified names are not available and + \a atts are the attributes attached to the element. If there are no + attributes, \a atts is an empty attributes object + + If this function returns FALSE the reader will stop parsing and will report + an error. The reader will use the function errorString() to get the error + message that will be used for reporting the error. + + See also the namespace description. + + \sa endElement() +*/ +/*! + \fn bool QXmlContentHandler::endElement( const QString& namespaceURI, const QString& localName, const QString& qName ) + + The reader calls this function when he has parsed an end element tag. + + If this function returns FALSE the reader will stop parsing and will report + an error. The reader will use the function errorString() to get the error + message that will be used for reporting the error. + + See also the namespace description. + + \sa startElement() +*/ +/*! + \fn bool QXmlContentHandler::characters( const QString& ch ) + + The reader calls this function when he has parsed a chunk of character + data (either normal character data or character data inside a CDATA section; + if you have to distinguish between those two types you have to use + QXmlLexicalHandler::startCDATA() and QXmlLexicalHandler::endCDATA() in + addition). + + Some readers will report whitespace in element content using the + ignorableWhitespace() function rather than this one (QXmlSimpleReader will + do it not though). + + A reader is allowed to report the character data of an element in more than + one chunk; e.g. a reader might want to report "a &lt; b" in three + characters() events ("a ", "<" and " b"). + + If this function returns FALSE the reader will stop parsing and will report + an error. The reader will use the function errorString() to get the error + message that will be used for reporting the error. +*/ +/*! + \fn bool QXmlContentHandler::ignorableWhitespace( const QString& ch ) + + Some readers may use this function to report each chunk of whitespace in + element content (QXmlSimpleReader does not though). + + If this function returns FALSE the reader will stop parsing and will report + an error. The reader will use the function errorString() to get the error + message that will be used for reporting the error. +*/ +/*! + \fn bool QXmlContentHandler::processingInstruction( const QString& target, const QString& data ) + + The reader calls this function when he has parsed a processing + instruction. + + \a target is the target name of the processing instruction and \a data is the + data of the processing instruction. + + If this function returns FALSE the reader will stop parsing and will report + an error. The reader will use the function errorString() to get the error + message that will be used for reporting the error. +*/ +/*! + \fn bool QXmlContentHandler::skippedEntity( const QString& name ) + + Some readers may skip entities if they have not seen the declarations (e.g. + because they are in an external DTD). If they do so they will report it by + calling this function. + + If this function returns FALSE the reader will stop parsing and will report + an error. The reader will use the function errorString() to get the error + message that will be used for reporting the error. +*/ +/*! + \fn QString QXmlContentHandler::errorString() + + The reader calls this function to get an error string if any of the handler + functions returns FALSE to him. +*/ + + +/*! + \class QXmlErrorHandler qxml.h + \brief The QXmlErrorHandler class provides an interface to report errors in + XML data. + + \module XML + + If the application is interested in reporting errors to the user or any other + customized error handling, you should subclass this class. + + You can set the error handler with QXmlReader::setErrorHandler(). + + See also the Introduction to SAX2. + + \sa QXmlDTDHandler QXmlDeclHandler QXmlContentHandler QXmlEntityResolver + QXmlLexicalHandler +*/ +/*! + \fn bool QXmlErrorHandler::warning( const QXmlParseException& exception ) + + A reader might use this function to report a warning. Warnings are conditions + that are not errors or fatal errors as defined by the XML 1.0 specification. + + If this function returns FALSE the reader will stop parsing and will report + an error. The reader will use the function errorString() to get the error + message that will be used for reporting the error. +*/ +/*! + \fn bool QXmlErrorHandler::error( const QXmlParseException& exception ) + + A reader might use this function to report a recoverable error. A recoverable + error corresponds to the definiton of "error" in section 1.2 of the XML 1.0 + specification. + + The reader must continue to provide normal parsing events after invoking this + function. + + If this function returns FALSE the reader will stop parsing and will report + an error. The reader will use the function errorString() to get the error + message that will be used for reporting the error. +*/ +/*! + \fn bool QXmlErrorHandler::fatalError( const QXmlParseException& exception ) + + A reader must use this function to report a non-recoverable error. + + If this function returns TRUE the reader might try to go on parsing and + reporting further errors; but no regular parsing events are reported. +*/ +/*! + \fn QString QXmlErrorHandler::errorString() + + The reader calls this function to get an error string if any of the handler + functions returns FALSE to him. +*/ + + +/*! + \class QXmlDTDHandler qxml.h + \brief The QXmlDTDHandler class provides an interface to report DTD content + of XML data. + + \module XML + + If an application needs information about notations and unparsed entities, + then the application implements this interface and registers an instance with + QXmlReader::setDTDHandler(). + + Note that this interface includes only those DTD events that the XML + recommendation requires processors to report: notation and unparsed entity + declarations. + + See also the Introduction to SAX2. + + \sa QXmlDeclHandler QXmlContentHandler QXmlEntityResolver QXmlErrorHandler + QXmlLexicalHandler +*/ +/*! + \fn bool QXmlDTDHandler::notationDecl( const QString& name, const QString& publicId, const QString& systemId ) + + The reader calls this function when he has parsed a notation + declaration. + + The argument \a name is the notation name, \a publicId is the notations's + public identifier and \a systemId is the notations's system identifier. + + If this function returns FALSE the reader will stop parsing and will report + an error. The reader will use the function errorString() to get the error + message that will be used for reporting the error. +*/ +/*! + \fn bool QXmlDTDHandler::unparsedEntityDecl( const QString& name, const QString& publicId, const QString& systemId, const QString& notationName ) + + The reader calls this function when he finds an unparsed entity declaration. + + The argument \a name is the unparsed entity's name, \a publicId is the + entity's public identifier, \a systemId is the entity's system identifier and + \a notation is the name of the associated notation. + + If this function returns FALSE the reader will stop parsing and will report + an error. The reader will use the function errorString() to get the error + message that will be used for reporting the error. +*/ +/*! + \fn QString QXmlDTDHandler::errorString() + + The reader calls this function to get an error string if any of the handler + functions returns FALSE to him. +*/ + + +/*! + \class QXmlEntityResolver qxml.h + \brief The QXmlEntityResolver class provides an interface to resolve extern + entities contained in XML data. + + \module XML + + If an application needs to implement customized handling for external + entities, it must implement this interface and register it with + QXmlReader::setEntityResolver(). + + See also the Introduction to SAX2. + + \sa QXmlDTDHandler QXmlDeclHandler QXmlContentHandler QXmlErrorHandler + QXmlLexicalHandler +*/ +/*! + \fn bool QXmlEntityResolver::resolveEntity( const QString& publicId, const QString& systemId, QXmlInputSource* ret ) + + The reader will call this function before he opens any external entity, + except the top-level document entity. The application may request the reader + to resolve the entity itself (\a ret is 0) or to use an entirely different + input source (\a ret points to the input source). + + The reader will delete the input source \a ret when he no longer needs it. So + you should allocate it on the heap with \c new. + + The argument \a publicId is the public identifier of the external entity, \a + systemId is the system identifier of the external entity and \a ret is the + return value of this function: if it is 0 the reader should resolve the + entity itself, if it is non-zero it must point to an input source which the + reader will use instead. + + If this function returns FALSE the reader will stop parsing and will report + an error. The reader will use the function errorString() to get the error + message that will be used for reporting the error. +*/ +/*! + \fn QString QXmlEntityResolver::errorString() + + The reader calls this function to get an error string if any of the handler + functions returns FALSE to him. +*/ + + +/*! + \class QXmlLexicalHandler qxml.h + \brief The QXmlLexicalHandler class provides an interface to report lexical + content of XML data. + + \module XML + + The events in the lexical handler apply to the entire document, not just to + the document element, and all lexical handler events appear between the + content handler's startDocument and endDocument events. + + You can set the lexical handler with QXmlReader::setLexicalHandler(). + + This interface is designed after the SAX2 extension LexicalHandler. The + functions startEntity() and endEntity() are not included though. + + See also the Introduction to SAX2. + + \sa QXmlDTDHandler QXmlDeclHandler QXmlContentHandler QXmlEntityResolver + QXmlErrorHandler +*/ +/*! + \fn bool QXmlLexicalHandler::startDTD( const QString& name, const QString& publicId, const QString& systemId ) + + The reader calls this function to report the start of a DTD declaration, if + any. + + All declarations reported through QXmlDTDHandler or QXmlDeclHandler appear + between the startDTD() and endDTD() calls. + + If this function returns FALSE the reader will stop parsing and will report + an error. The reader will use the function errorString() to get the error + message that will be used for reporting the error. + + \sa endDTD() +*/ +/*! + \fn bool QXmlLexicalHandler::endDTD() + + The reader calls this function to report the end of a DTD declaration, if + any. + + If this function returns FALSE the reader will stop parsing and will report + an error. The reader will use the function errorString() to get the error + message that will be used for reporting the error. + + \sa startDTD() +*/ +/*! + \fn bool QXmlLexicalHandler::startCDATA() + + The reader calls this function to report the start of a CDATA section. The + content of the CDATA section will be reported through the regular + QXmlContentHandler::characters(). This function is intended only to report + the boundary. + + If this function returns FALSE the reader will stop parsing and will report + an error. The reader will use the function errorString() to get the error + message that will be used for reporting the error. + + \sa endCDATA() +*/ +/*! + \fn bool QXmlLexicalHandler::endCDATA() + + The reader calls this function to report the end of a CDATA section. + + If this function returns FALSE the reader will stop parsing and will report + an error. The reader will use the function errorString() to get the error + message that will be used for reporting the error. + + \sa startCDATA() +*/ +/*! + \fn bool QXmlLexicalHandler::comment( const QString& ch ) + + The reader calls this function to report an XML comment anywhere in the + document. + + If this function returns FALSE the reader will stop parsing and will report + an error. The reader will use the function errorString() to get the error + message that will be used for reporting the error. +*/ +/*! + \fn QString QXmlLexicalHandler::errorString() + + The reader calls this function to get an error string if any of the handler + functions returns FALSE to him. +*/ + + +/*! + \class QXmlDeclHandler qxml.h + \brief The QXmlDeclHandler class provides an interface to report declaration + content of XML data. + + \module XML + + You can set the declaration handler with QXmlReader::setDeclHandler(). + + This interface is designed after the SAX2 extension DeclHandler. + + See also the Introduction to SAX2. + + \sa QXmlDTDHandler QXmlContentHandler QXmlEntityResolver QXmlErrorHandler + QXmlLexicalHandler +*/ +/*! + \fn bool QXmlDeclHandler::attributeDecl( const QString& eName, const QString& aName, const QString& type, const QString& valueDefault, const QString& value ) + + The reader calls this function to report an attribute type declaration. Only + the effective (first) declaration for an attribute will be reported. + + If this function returns FALSE the reader will stop parsing and will report + an error. The reader will use the function errorString() to get the error + message that will be used for reporting the error. +*/ +/*! + \fn bool QXmlDeclHandler::internalEntityDecl( const QString& name, const QString& value ) + + The reader calls this function to report an internal entity declaration. Only + the effective (first) declaration will be reported. + + If this function returns FALSE the reader will stop parsing and will report + an error. The reader will use the function errorString() to get the error + message that will be used for reporting the error. +*/ +/*! + \fn bool QXmlDeclHandler::externalEntityDecl( const QString& name, const QString& publicId, const QString& systemId ) + + The reader calls this function to report a parsed external entity + declaration. Only the effective (first) declaration for each entity will be + reported. + + If this function returns FALSE the reader will stop parsing and will report + an error. The reader will use the function errorString() to get the error + message that will be used for reporting the error. +*/ +/*! + \fn QString QXmlDeclHandler::errorString() + + The reader calls this function to get an error string if any of the handler + functions returns FALSE to him. +*/ + + +/*! + \class QXmlDefaultHandler qxml.h + \brief The QXmlDefaultHandler class provides a default implementation of all + XML handler classes. + + \module XML + + Very often you are only interested in parts of the things that that the + reader reports to you. This class simply implements a default behaviour of + the handler classes (most of the time: do nothing). Normally this is the + class you subclass for implementing your customized handler. + + See also the Introduction to SAX2. + + \sa QXmlDTDHandler QXmlDeclHandler QXmlContentHandler QXmlEntityResolver + QXmlErrorHandler QXmlLexicalHandler +*/ +/*! + \fn QXmlDefaultHandler::QXmlDefaultHandler() + + Constructor. +*/ +/*! + \fn QXmlDefaultHandler::~QXmlDefaultHandler() + + Destructor. +*/ + +/*! + Does nothing. +*/ +void QXmlDefaultHandler::setDocumentLocator( QXmlLocator* ) +{ +} + +/*! + Does nothing. +*/ +bool QXmlDefaultHandler::startDocument() +{ + return TRUE; +} + +/*! + Does nothing. +*/ +bool QXmlDefaultHandler::endDocument() +{ + return TRUE; +} + +/*! + Does nothing. +*/ +bool QXmlDefaultHandler::startPrefixMapping( const QString&, const QString& ) +{ + return TRUE; +} + +/*! + Does nothing. +*/ +bool QXmlDefaultHandler::endPrefixMapping( const QString& ) +{ + return TRUE; +} + +/*! + Does nothing. +*/ +bool QXmlDefaultHandler::startElement( const QString&, const QString&, + const QString&, const QXmlAttributes& ) +{ + return TRUE; +} + +/*! + Does nothing. +*/ +bool QXmlDefaultHandler::endElement( const QString&, const QString&, + const QString& ) +{ + return TRUE; +} + +/*! + Does nothing. +*/ +bool QXmlDefaultHandler::characters( const QString& ) +{ + return TRUE; +} + +/*! + Does nothing. +*/ +bool QXmlDefaultHandler::ignorableWhitespace( const QString& ) +{ + return TRUE; +} + +/*! + Does nothing. +*/ +bool QXmlDefaultHandler::processingInstruction( const QString&, + const QString& ) +{ + return TRUE; +} + +/*! + Does nothing. +*/ +bool QXmlDefaultHandler::skippedEntity( const QString& ) +{ + return TRUE; +} + +/*! + Does nothing. +*/ +bool QXmlDefaultHandler::warning( const QXmlParseException& ) +{ + return TRUE; +} + +/*! + Does nothing. +*/ +bool QXmlDefaultHandler::error( const QXmlParseException& ) +{ + return TRUE; +} + +/*! + Does nothing. +*/ +bool QXmlDefaultHandler::fatalError( const QXmlParseException& ) +{ + return TRUE; +} + +/*! + Does nothing. +*/ +bool QXmlDefaultHandler::notationDecl( const QString&, const QString&, + const QString& ) +{ + return TRUE; +} + +/*! + Does nothing. +*/ +bool QXmlDefaultHandler::unparsedEntityDecl( const QString&, const QString&, + const QString&, const QString& ) +{ + return TRUE; +} + +/*! + Always sets \a ret to 0, so that the reader will use the system identifier + provided in the XML document. +*/ +bool QXmlDefaultHandler::resolveEntity( const QString&, const QString&, + QXmlInputSource* /* ret */ ) +{ +/* ### This doesn't set anything to 0! + ret = 0; +*/ + return TRUE; +} + +/*! + Returns the default error string. +*/ +QString QXmlDefaultHandler::errorString() +{ + return QString( XMLERR_ERRORBYCONSUMER ); +} + +/*! + Does nothing. +*/ +bool QXmlDefaultHandler::startDTD( const QString&, const QString&, const QString& ) +{ + return TRUE; +} + +/*! + Does nothing. +*/ +bool QXmlDefaultHandler::endDTD() +{ + return TRUE; +} + +#if 0 +/*! + Does nothing. +*/ +bool QXmlDefaultHandler::startEntity( const QString& ) +{ + return TRUE; +} + +/*! + Does nothing. +*/ +bool QXmlDefaultHandler::endEntity( const QString& ) +{ + return TRUE; +} +#endif + +/*! + Does nothing. +*/ +bool QXmlDefaultHandler::startCDATA() +{ + return TRUE; +} + +/*! + Does nothing. +*/ +bool QXmlDefaultHandler::endCDATA() +{ + return TRUE; +} + +/*! + Does nothing. +*/ +bool QXmlDefaultHandler::comment( const QString& ) +{ + return TRUE; +} + +/*! + Does nothing. +*/ +bool QXmlDefaultHandler::attributeDecl( const QString&, const QString&, const QString&, const QString&, const QString& ) +{ + return TRUE; +} + +/*! + Does nothing. +*/ +bool QXmlDefaultHandler::internalEntityDecl( const QString&, const QString& ) +{ + return TRUE; +} + +/*! + Does nothing. +*/ +bool QXmlDefaultHandler::externalEntityDecl( const QString&, const QString&, const QString& ) +{ + return TRUE; +} + + +/********************************************* + * + * QXmlSimpleReaderPrivate + * + *********************************************/ + +class QXmlSimpleReaderPrivate +{ +private: + // constructor + QXmlSimpleReaderPrivate() + { } + + + // used for entity declarations + struct ExternParameterEntity + { + ExternParameterEntity( ) {} + ExternParameterEntity( const QString &p, const QString &s ) + : publicId(p), systemId(s) {} + QString publicId; + QString systemId; + }; + struct ExternEntity + { + ExternEntity( ) {} + ExternEntity( const QString &p, const QString &s, const QString &n ) + : publicId(p), systemId(s), notation(n) {} + QString publicId; + QString systemId; + QString notation; + }; + QMap externParameterEntities; + QMap parameterEntities; + QMap externEntities; + QMap entities; + + // used for standalone declaration + enum Standalone { Yes, No, Unknown }; + + QString doctype; // only used for the doctype + QString xmlVersion; // only used to store the version information + QString encoding; // only used to store the encoding + Standalone standalone; // used to store the value of the standalone declaration + + QString publicId; // used by parseExternalID() to store the public ID + QString systemId; // used by parseExternalID() to store the system ID + QString attDeclEName; // use by parseAttlistDecl() + QString attDeclAName; // use by parseAttlistDecl() + + // flags for some features support + bool useNamespaces; + bool useNamespacePrefixes; + bool reportWhitespaceCharData; + bool reportEntities; + + // used to build the attribute list + QXmlAttributes attList; + + // helper classes + QXmlLocator *locator; + QXmlNamespaceSupport namespaceSupport; + + // error string + QString error; + + // friend declarations + friend class QXmlSimpleReader; +}; + + +/********************************************* + * + * QXmlSimpleReader + * + *********************************************/ + +/*! + \class QXmlReader qxml.h + \brief The QXmlReader class provides an interface for XML readers (i.e. + parsers). + + \module XML + + This abstract class describes an interface for all XML readers in Qt. At the + moment there is only one implementation of a reader included in the XML + module of Qt (QXmlSimpleReader). In future releases there might be more + readers with different properties available (e.g. a validating parser). + + The design of the XML classes follow the + SAX2 java interface. + It was adopted to fit into the Qt naming conventions; so it should be very + easy for anybody who has worked with SAX2 to get started with the Qt XML + classes. + + All readers use the class QXmlInputSource to read the input document from. + Since you are normally interested in certain contents of the XML document, + the reader reports those contents through special handler classes + (QXmlDTDHandler, QXmlDeclHandler, QXmlContentHandler, QXmlEntityResolver, + QXmlErrorHandler and QXmlLexicalHandler). + + You have to subclass these classes. Since the handler classes describe only + interfaces you must implement all functions; there is a class + (QXmlDefaultHandler) to make this easier; it implements a default behaviour + (do nothing) for all functions. + + For getting started see also the + Quick start. + + \sa QXmlSimpleReader +*/ +/*! + \fn bool QXmlReader::feature( const QString& name, bool *ok ) const + + If the reader has the feature \a name, this function returns the value of the + feature. + + If the reader has not the feature \a name, the return value may be anything. + + If \a ok is not 0, then \a ok is set to TRUE if the reader has the feature + \a name, otherwise \a ok is set to FALSE. + + \sa setFeature() hasFeature() +*/ +/*! + \fn void QXmlReader::setFeature( const QString& name, bool value ) + + Sets the feature \a name to \a value. If the reader has not the feature \a + name, this value is ignored. + + \sa feature() hasFeature() +*/ +/*! + \fn bool QXmlReader::hasFeature( const QString& name ) const + + Returns \c TRUE if the reader has the feature \a name, otherwise FALSE. + + \sa feature() setFeature() +*/ +/*! + \fn void* QXmlReader::property( const QString& name, bool *ok ) const + + If the reader has the property \a name, this function returns the value of + the property. + + If the reader has not the property \a name, the return value is 0. + + If \a ok is not 0, then \a ok is set to TRUE if the reader has the property + \a name, otherwise \a ok is set to FALSE. + + \sa setProperty() hasProperty() +*/ +/*! + \fn void QXmlReader::setProperty( const QString& name, void* value ) + + Sets the property \a name to \a value. If the reader has not the property \a + name, this value is ignored. + + \sa property() hasProperty() +*/ +/*! + \fn bool QXmlReader::hasProperty( const QString& name ) const + + Returns TRUE if the reader has the property \a name, otherwise FALSE. + + \sa property() setProperty() +*/ +/*! + \fn void QXmlReader::setEntityResolver( QXmlEntityResolver* handler ) + + Sets the entity resolver to \a handler. + + \sa entityResolver() +*/ +/*! + \fn QXmlEntityResolver* QXmlReader::entityResolver() const + + Returns the entity resolver or 0 if none was set. + + \sa setEntityResolver() +*/ +/*! + \fn void QXmlReader::setDTDHandler( QXmlDTDHandler* handler ) + + Sets the DTD handler to \a handler. + + \sa DTDHandler() +*/ +/*! + \fn QXmlDTDHandler* QXmlReader::DTDHandler() const + + Returns the DTD handler or 0 if none was set. + + \sa setDTDHandler() +*/ +/*! + \fn void QXmlReader::setContentHandler( QXmlContentHandler* handler ) + + Sets the content handler to \a handler. + + \sa contentHandler() +*/ +/*! + \fn QXmlContentHandler* QXmlReader::contentHandler() const + + Returns the content handler or 0 if none was set. + + \sa setContentHandler() +*/ +/*! + \fn void QXmlReader::setErrorHandler( QXmlErrorHandler* handler ) + + Sets the error handler to \a handler. + + \sa errorHandler() +*/ +/*! + \fn QXmlErrorHandler* QXmlReader::errorHandler() const + + Returns the error handler or 0 if none was set + + \sa setErrorHandler() +*/ +/*! + \fn void QXmlReader::setLexicalHandler( QXmlLexicalHandler* handler ) + + Sets the lexical handler to \a handler. + + \sa lexicalHandler() +*/ +/*! + \fn QXmlLexicalHandler* QXmlReader::lexicalHandler() const + + Returns the lexical handler or 0 if none was set. + + \sa setLexicalHandler() +*/ +/*! + \fn void QXmlReader::setDeclHandler( QXmlDeclHandler* handler ) + + Sets the declaration handler to \a handler. + + \sa declHandler() +*/ +/*! + \fn QXmlDeclHandler* QXmlReader::declHandler() const + + Returns the declaration handler or 0 if none was set. + + \sa setDeclHandler() +*/ +/*! + \fn bool QXmlReader::parse( const QXmlInputSource& input ) + + Parses the XML document \a input. Returns TRUE if the parsing was successful, + otherwise FALSE. +*/ +/*! + \fn bool QXmlReader::parse( const QString& systemId ) + + Parses the XML document at the location \a systemId. Returns TRUE if the + parsing was successful, otherwise FALSE. +*/ + + +/*! + \class QXmlSimpleReader qxml.h + \brief The QXmlSimpleReader class provides an implementation of a simple XML + reader (i.e. parser). + + \module XML + + This XML reader is sufficient for simple parsing tasks. Here is a short list + of the properties of this reader: +
      +
    • well-formed parser +
    • does not parse any external entities +
    • can do namespace processing +
    + + For getting started see also the + Quick start. +*/ + +//guaranteed not to be a characater +const QChar QXmlSimpleReader::QEOF = QChar((ushort)0xffff); + +/*! + Constructs a simple XML reader. +*/ +QXmlSimpleReader::QXmlSimpleReader() +{ + d = new QXmlSimpleReaderPrivate(); + d->locator = new QXmlLocator( this ); + + entityRes = 0; + dtdHnd = 0; + contentHnd = 0; + errorHnd = 0; + lexicalHnd = 0; + declHnd = 0; + + // default feature settings + d->useNamespaces = TRUE; + d->useNamespacePrefixes = FALSE; + d->reportWhitespaceCharData = TRUE; + d->reportEntities = FALSE; +} + +/*! + Destroys a simple XML reader. +*/ +QXmlSimpleReader::~QXmlSimpleReader() +{ + delete d->locator; + delete d; +} + +/*! + Gets the state of a feature. + + \sa setFeature() hasFeature() +*/ +bool QXmlSimpleReader::feature( const QString& name, bool *ok ) const +{ + if ( ok != 0 ) + *ok = TRUE; + if ( name == "http://xml.org/sax/features/namespaces" ) { + return d->useNamespaces; + } else if ( name == "http://xml.org/sax/features/namespace-prefixes" ) { + return d->useNamespacePrefixes; + } else if ( name == "http://trolltech.com/xml/features/report-whitespace-only-CharData" ) { + return d->reportWhitespaceCharData; + } else if ( name == "http://trolltech.com/xml/features/report-start-end-entity" ) { + return d->reportEntities; + } else { + qWarning( "Unknown feature " + name ); + if ( ok != 0 ) + *ok = FALSE; + } + return FALSE; +} + +/*! + Sets the state of a feature. + + Supported features are: +
      +
    • http://xml.org/sax/features/namespaces: + if this feature is TRUE, namespace processing is performed +
    • http://xml.org/sax/features/namespace-prefixes: + if this feature is TRUE, the the original prefixed names and attributes + used for namespace declarations are reported +
    • http://trolltech.com/xml/features/report-whitespace-only-CharData: + if this feature is TRUE, CharData that consists only of whitespace (and + no other characters) is not reported via + QXmlContentHandler::characters() +
    + + \sa feature() hasFeature() +*/ +void QXmlSimpleReader::setFeature( const QString& name, bool value ) +{ + if ( name == "http://xml.org/sax/features/namespaces" ) { + d->useNamespaces = value; + } else if ( name == "http://xml.org/sax/features/namespace-prefixes" ) { + d->useNamespacePrefixes = value; + } else if ( name == "http://trolltech.com/xml/features/report-whitespace-only-CharData" ) { + d->reportWhitespaceCharData = value; + } else if ( name == "http://trolltech.com/xml/features/report-start-end-entity" ) { + d->reportEntities = value; + } else { + qWarning( "Unknown feature " + name ); + } +} + +/*! + Returns TRUE if the class has a feature named \a feature, otherwise FALSE. + + \sa setFeature() feature() +*/ +bool QXmlSimpleReader::hasFeature( const QString& name ) const +{ + if ( name == "http://xml.org/sax/features/namespaces" || + name == "http://xml.org/sax/features/namespace-prefixes" || + name == "http://trolltech.com/xml/features/report-whitespace-only-CharData" ) { + return TRUE; + } else { + return FALSE; + } +} + +/*! + Returns 0 since this class does not support any properties. +*/ +void* QXmlSimpleReader::property( const QString&, bool *ok ) const +{ + if ( ok != 0 ) + *ok = FALSE; + return 0; +} + +/*! + Does nothing since this class does not support any properties. +*/ +void QXmlSimpleReader::setProperty( const QString&, void* ) +{ +} + +/*! + Returns FALSE since this class does not support any properties. +*/ +bool QXmlSimpleReader::hasProperty( const QString& ) const +{ + return FALSE; +} + +/*! \reimp */ +void QXmlSimpleReader::setEntityResolver( QXmlEntityResolver* handler ) +{ entityRes = handler; } + +/*! \reimp */ +QXmlEntityResolver* QXmlSimpleReader::entityResolver() const +{ return entityRes; } + +/*! \reimp */ +void QXmlSimpleReader::setDTDHandler( QXmlDTDHandler* handler ) +{ dtdHnd = handler; } + +/*! \reimp */ +QXmlDTDHandler* QXmlSimpleReader::DTDHandler() const +{ return dtdHnd; } + +/*! \reimp */ +void QXmlSimpleReader::setContentHandler( QXmlContentHandler* handler ) +{ contentHnd = handler; } + +/*! \reimp */ +QXmlContentHandler* QXmlSimpleReader::contentHandler() const +{ return contentHnd; } + +/*! \reimp */ +void QXmlSimpleReader::setErrorHandler( QXmlErrorHandler* handler ) +{ errorHnd = handler; } + +/*! \reimp */ +QXmlErrorHandler* QXmlSimpleReader::errorHandler() const +{ return errorHnd; } + +/*! \reimp */ +void QXmlSimpleReader::setLexicalHandler( QXmlLexicalHandler* handler ) +{ lexicalHnd = handler; } + +/*! \reimp */ +QXmlLexicalHandler* QXmlSimpleReader::lexicalHandler() const +{ return lexicalHnd; } + +/*! \reimp */ +void QXmlSimpleReader::setDeclHandler( QXmlDeclHandler* handler ) +{ declHnd = handler; } + +/*! \reimp */ +QXmlDeclHandler* QXmlSimpleReader::declHandler() const +{ return declHnd; } + + + +/*! \reimp */ +bool QXmlSimpleReader::parse( const QXmlInputSource& input ) +{ + init( input ); + // call the handler + if ( contentHnd ) { + contentHnd->setDocumentLocator( d->locator ); + if ( !contentHnd->startDocument() ) { + d->error = contentHnd->errorString(); + goto parseError; + } + } + // parse prolog + if ( !parseProlog() ) { + d->error = XMLERR_ERRORPARSINGPROLOG; + goto parseError; + } + // parse element + if ( !parseElement() ) { + d->error = XMLERR_ERRORPARSINGMAINELEMENT; + goto parseError; + } + // parse Misc* + while ( !atEnd() ) { + if ( !parseMisc() ) { + d->error = XMLERR_ERRORPARSINGMISC; + goto parseError; + } + } + // is stack empty? + if ( !tags.isEmpty() ) { + d->error = XMLERR_UNEXPECTEDEOF; + goto parseError; + } + // call the handler + if ( contentHnd ) { + if ( !contentHnd->endDocument() ) { + d->error = contentHnd->errorString(); + goto parseError; + } + } + + return TRUE; + + // error handling + +parseError: + reportParseError(); + tags.clear(); + return FALSE; +} + +/*! + Parses the prolog [22]. +*/ +bool QXmlSimpleReader::parseProlog() +{ + bool xmldecl_possible = TRUE; + bool doctype_read = FALSE; + + const signed char Init = 0; + const signed char EatWS = 1; // eat white spaces + const signed char Lt = 2; // '<' read + const signed char Em = 3; // '!' read + const signed char DocType = 4; // read doctype + const signed char Comment = 5; // read comment + const signed char PI = 6; // read PI + const signed char Done = 7; + + const signed char InpWs = 0; + const signed char InpLt = 1; // < + const signed char InpQm = 2; // ? + const signed char InpEm = 3; // ! + const signed char InpD = 4; // D + const signed char InpDash = 5; // - + const signed char InpUnknown = 6; + + // use some kind of state machine for parsing + static const signed char table[7][7] = { + /* InpWs InpLt InpQm InpEm InpD InpDash InpUnknown */ + { EatWS, Lt, -1, -1, -1, -1, -1 }, // Init + { -1, Lt, -1, -1, -1, -1, -1 }, // EatWS + { -1, -1, PI, Em, Done, -1, Done }, // Lt + { -1, -1, -1, -1, DocType, Comment, -1 }, // Em + { EatWS, Lt, -1, -1, -1, -1, -1 }, // DocType + { EatWS, Lt, -1, -1, -1, -1, -1 }, // Comment + { EatWS, Lt, -1, -1, -1, -1, -1 } // PI + }; + signed char state = Init; + signed char input; + bool parseOk = TRUE; + + for (;;) { + + // read input + if ( atEnd() ) { + d->error = XMLERR_UNEXPECTEDEOF; + goto parseError; + } + if ( is_S(c) ) { + input = InpWs; + } else if ( c == '<' ) { + input = InpLt; + } else if ( c == '?' ) { + input = InpQm; + } else if ( c == '!' ) { + input = InpEm; + } else if ( c == 'D' ) { + input = InpD; + } else if ( c == '-' ) { + input = InpDash; + } else { + input = InpUnknown; + } + // get new state + state = table[state][input]; + + // in some cases do special actions depending on state + switch ( state ) { + case EatWS: + // XML declaration only on first position possible + xmldecl_possible = FALSE; + // eat white spaces + eat_ws(); + break; + case Lt: + // next character + next(); + break; + case Em: + // XML declaration only on first position possible + xmldecl_possible = FALSE; + // next character + next(); + break; + case DocType: + parseOk = parseDoctype(); + break; + case Comment: + parseOk = parseComment(); + break; + case PI: + parseOk = parsePI( xmldecl_possible ); + break; + } + // no input is read after this + switch ( state ) { + case DocType: + if ( !parseOk ) { + d->error = XMLERR_ERRORPARSINGPROLOG; + goto parseError; + } + if ( doctype_read ) { + d->error = XMLERR_MORETHANONEDOCTYPE; + goto parseError; + } else { + doctype_read = FALSE; + } + break; + case Comment: + if ( !parseOk ) { + d->error = XMLERR_ERRORPARSINGPROLOG; + goto parseError; + } + if ( lexicalHnd ) { + if ( !lexicalHnd->comment( string() ) ) { + d->error = lexicalHnd->errorString(); + goto parseError; + } + } + break; + case PI: + if ( !parseOk ) { + d->error = XMLERR_ERRORPARSINGPROLOG; + goto parseError; + } + // call the handler + if ( contentHnd ) { + if ( xmldecl_possible && !d->xmlVersion.isEmpty() ) { + QString value( "version = '" ); + value += d->xmlVersion; + value += "'"; + if ( !d->encoding.isEmpty() ) { + value += " encoding = '"; + value += d->encoding; + value += "'"; + } + if ( d->standalone == QXmlSimpleReaderPrivate::Yes ) { + value += " standalone = 'yes'"; + } else if ( d->standalone == QXmlSimpleReaderPrivate::No ) { + value += " standalone = 'no'"; + } + if ( !contentHnd->processingInstruction( "xml", value ) ) { + d->error = contentHnd->errorString(); + goto parseError; + } + } else { + if ( !contentHnd->processingInstruction( name(), string() ) ) { + d->error = contentHnd->errorString(); + goto parseError; + } + } + } + // XML declaration only on first position possible + xmldecl_possible = FALSE; + break; + case Done: + return TRUE; + case -1: + d->error = XMLERR_ERRORPARSINGELEMENT; + goto parseError; + } + + } + + return TRUE; + +parseError: + reportParseError(); + return FALSE; +} + +/*! + Parse an element [39]. + + Precondition: the opening '<' is already read. +*/ +bool QXmlSimpleReader::parseElement() +{ + QString uri, lname, prefix; + bool t; + + const signed char Init = 0; + const signed char ReadName = 1; + const signed char Ws1 = 2; + const signed char STagEnd = 3; + const signed char STagEnd2 = 4; + const signed char ETagBegin = 5; + const signed char ETagBegin2 = 6; + const signed char Ws2 = 7; + const signed char EmptyTag = 8; + const signed char Attribute = 9; + const signed char Ws3 = 10; + const signed char Done = 11; + + const signed char InpWs = 0; // whitespace + const signed char InpNameBe = 1; // is_NameBeginning() + const signed char InpGt = 2; // > + const signed char InpSlash = 3; // / + const signed char InpUnknown = 4; + + // use some kind of state machine for parsing + static const signed char table[11][5] = { + /* InpWs InpNameBe InpGt InpSlash InpUnknown */ + { -1, ReadName, -1, -1, -1 }, // Init + { Ws1, Attribute, STagEnd, EmptyTag, -1 }, // ReadName + { -1, Attribute, STagEnd, EmptyTag, -1 }, // Ws1 + { STagEnd2, STagEnd2, STagEnd2, STagEnd2, STagEnd2 }, // STagEnd + { -1, -1, -1, ETagBegin, -1 }, // STagEnd2 + { -1, ETagBegin2, -1, -1, -1 }, // ETagBegin + { Ws2, -1, Done, -1, -1 }, // ETagBegin2 + { -1, -1, Done, -1, -1 }, // Ws2 + { -1, -1, Done, -1, -1 }, // EmptyTag + { Ws3, Attribute, STagEnd, EmptyTag, -1 }, // Attribute + { -1, Attribute, STagEnd, EmptyTag, -1 } // Ws3 + }; + signed char state = Init; + signed char input; + bool parseOk = TRUE; + + for (;;) { + + // read input + if ( atEnd() ) { + d->error = XMLERR_UNEXPECTEDEOF; + goto parseError; + } + if ( is_S(c) ) { + input = InpWs; + } else if ( is_NameBeginning(c) ) { + input = InpNameBe; + } else if ( c == '>' ) { + input = InpGt; + } else if ( c == '/' ) { + input = InpSlash; + } else { + input = InpUnknown; + } + // get new state +//qDebug( "%d -%d(%c)-> %d", state, input, c.latin1(), table[state][input] ); + state = table[state][input]; + + // in some cases do special actions depending on state + switch ( state ) { + case ReadName: + parseOk = parseName(); + break; + case Ws1: + case Ws2: + case Ws3: + eat_ws(); + break; + case STagEnd: + // call the handler + if ( contentHnd ) { + if ( d->useNamespaces ) { + d->namespaceSupport.processName( tags.top(), FALSE, uri, lname ); + t = contentHnd->startElement( uri, lname, tags.top(), d->attList ); + } else { + t = contentHnd->startElement( "", "", tags.top(), d->attList ); + } + if ( !t ) { + d->error = contentHnd->errorString(); + goto parseError; + } + } + next(); + break; + case STagEnd2: + parseOk = parseContent(); + break; + case ETagBegin: + next(); + break; + case ETagBegin2: + // get the name of the tag + parseOk = parseName(); + break; + case EmptyTag: + if ( tags.isEmpty() ) { + d->error = XMLERR_TAGMISMATCH; + goto parseError; + } + if ( !parseElementEmptyTag( t, uri, lname ) ) + goto parseError; + // next character + next(); + break; + case Attribute: + // get name and value of attribute + parseOk = parseAttribute(); + break; + case Done: + next(); + break; + } + // no input is read after this + switch ( state ) { + case ReadName: + if ( !parseOk ) { + d->error = XMLERR_ERRORPARSINGNAME; + goto parseError; + } + // store it on the stack + tags.push( name() ); + // empty the attributes + d->attList.qnameList.clear(); + d->attList.uriList.clear(); + d->attList.localnameList.clear(); + d->attList.valueList.clear(); + // namespace support? + if ( d->useNamespaces ) { + d->namespaceSupport.pushContext(); + } + break; + case STagEnd2: + if ( !parseOk ) { + d->error = XMLERR_ERRORPARSINGCONTENT; + goto parseError; + } + break; + case ETagBegin2: + if ( !parseOk ) { + d->error = XMLERR_ERRORPARSINGNAME; + goto parseError; + } + if ( !parseElementETagBegin2() ) + goto parseError; + break; + case Attribute: + if ( !parseOk ) { + d->error = XMLERR_ERRORPARSINGATTRIBUTE; + goto parseError; + } + if ( !parseElementAttribute( prefix, uri, lname ) ) + goto parseError; + break; + case Done: + return TRUE; + case -1: + d->error = XMLERR_ERRORPARSINGELEMENT; + goto parseError; + } + + } + + return TRUE; + +parseError: + reportParseError(); + return FALSE; +} +/*! + Helper to break down the size of the code in the case statement. + Return FALSE on error, otherwise TRUE. +*/ +// ### Remove t argument in Qt 3.0 -- I don't need it. The same should be true for uri and lname. +bool QXmlSimpleReader::parseElementEmptyTag( bool &, QString &uri, QString &lname ) +{ + // pop the stack and call the handler + if ( contentHnd ) { + if ( d->useNamespaces ) { + // report startElement first... + d->namespaceSupport.processName( tags.top(), FALSE, uri, lname ); + if ( !contentHnd->startElement( uri, lname, tags.top(), d->attList ) ) { + goto error; + } + // ... followed by endElement... + if ( !contentHnd->endElement( uri, lname, tags.pop() ) ) { + goto error; + } + // ... followed by endPrefixMapping + QStringList prefixesBefore, prefixesAfter; + if ( contentHnd ) { + prefixesBefore = d->namespaceSupport.prefixes(); + } + d->namespaceSupport.popContext(); + // call the handler for prefix mapping + prefixesAfter = d->namespaceSupport.prefixes(); + for ( QStringList::Iterator it = prefixesBefore.begin(); it != prefixesBefore.end(); ++it ) { + if ( prefixesAfter.contains(*it) == 0 ) { + if ( !contentHnd->endPrefixMapping( *it ) ) { + goto error; + } + } + } + } else { + // report startElement first... + if ( !contentHnd->startElement( "", "", tags.top(), d->attList ) ) { + goto error; + } + // ... followed by endElement + if ( !contentHnd->endElement( "","",tags.pop() ) ) { + goto error; + } + } + } else { + tags.pop(); + d->namespaceSupport.popContext(); + } + return TRUE; +error: + d->error = contentHnd->errorString(); + return FALSE; +} +/*! + Helper to break down the size of the code in the case statement. + Return FALSE on error, otherwise TRUE. +*/ +bool QXmlSimpleReader::parseElementETagBegin2() +{ + + // pop the stack and compare it with the name + if ( tags.pop() != name() ) { + d->error = XMLERR_TAGMISMATCH; + return FALSE; + } + // call the handler + if ( contentHnd ) { + if ( d->useNamespaces ) { + QString uri, lname; + d->namespaceSupport.processName( name(), FALSE, uri, lname ); + if ( !contentHnd->endElement( uri, lname, name() ) ) { + d->error = contentHnd->errorString(); + return FALSE; + } + } else { + if ( !contentHnd->endElement("","",name()) ) { + d->error = contentHnd->errorString(); + return FALSE; + } + } + } + if ( d->useNamespaces ) { + QStringList prefixesBefore, prefixesAfter; + if ( contentHnd ) { + prefixesBefore = d->namespaceSupport.prefixes(); + } + d->namespaceSupport.popContext(); + // call the handler for prefix mapping + if ( contentHnd ) { + prefixesAfter = d->namespaceSupport.prefixes(); + for ( QStringList::Iterator it = prefixesBefore.begin(); it != prefixesBefore.end(); ++it ) { + if ( prefixesAfter.contains(*it) == 0 ) { + if ( !contentHnd->endPrefixMapping( *it ) ) { + d->error = contentHnd->errorString(); + return FALSE; + } + } + } + } + } + return TRUE; +} +/*! + Helper to break down the size of the code in the case statement. + Return FALSE on error, otherwise TRUE. +*/ +// ### Remove arguments in Qt 3.0? I think, I don't need them. +bool QXmlSimpleReader::parseElementAttribute( QString &prefix, QString &uri, QString &lname ) +{ + // add the attribute to the list + if ( d->useNamespaces ) { + // is it a namespace declaration? + d->namespaceSupport.splitName( name(), prefix, lname ); + if ( prefix == "xmlns" ) { + // namespace declaration + d->namespaceSupport.setPrefix( lname, string() ); + if ( d->useNamespacePrefixes ) { + d->attList.qnameList.append( name() ); + d->attList.uriList.append( "" ); + d->attList.localnameList.append( "" ); + d->attList.valueList.append( string() ); + } + // call the handler for prefix mapping + if ( contentHnd ) { + if ( !contentHnd->startPrefixMapping( lname, string() ) ) { + d->error = contentHnd->errorString(); + return FALSE; + } + } + } else { + // no namespace delcaration + d->namespaceSupport.processName( name(), TRUE, uri, lname ); + d->attList.qnameList.append( name() ); + d->attList.uriList.append( uri ); + d->attList.localnameList.append( lname ); + d->attList.valueList.append( string() ); + } + } else { + // no namespace support + d->attList.qnameList.append( name() ); + d->attList.uriList.append( "" ); + d->attList.localnameList.append( "" ); + d->attList.valueList.append( string() ); + } + return TRUE; +} + +/*! + Parse a content [43]. + + A content is only used between tags. If a end tag is found the < is already + read and the head stand on the '/' of the end tag ''. +*/ +bool QXmlSimpleReader::parseContent() +{ + bool charDataRead = FALSE; + + const signed char Init = 0; + const signed char ChD = 1; // CharData + const signed char ChD1 = 2; // CharData help state + const signed char ChD2 = 3; // CharData help state + const signed char Ref = 4; // Reference + const signed char Lt = 5; // '<' read + const signed char PI = 6; // PI + const signed char Elem = 7; // Element + const signed char Em = 8; // '!' read + const signed char Com = 9; // Comment + const signed char CDS = 10; // CDSect + const signed char CDS1 = 11; // read a CDSect + const signed char CDS2 = 12; // read a CDSect (help state) + const signed char CDS3 = 13; // read a CDSect (help state) + const signed char Done = 14; // finished reading content + + const signed char InpLt = 0; // < + const signed char InpGt = 1; // > + const signed char InpSlash = 2; // / + const signed char InpQMark = 3; // ? + const signed char InpEMark = 4; // ! + const signed char InpAmp = 5; // & + const signed char InpDash = 6; // - + const signed char InpOpenB = 7; // [ + const signed char InpCloseB = 8; // ] + const signed char InpUnknown = 9; + + static const signed char mapCLT2FSMChar[] = { + InpUnknown, // white space + InpUnknown, // % + InpAmp, // & + InpGt, // > + InpLt, // < + InpSlash, // / + InpQMark, // ? + InpEMark, // ! + InpDash, // - + InpCloseB, // ] + InpOpenB, // [ + InpUnknown, // = + InpUnknown, // " + InpUnknown, // ' + InpUnknown // unknown + }; + + // use some kind of state machine for parsing + static const signed char table[14][10] = { + /* InpLt InpGt InpSlash InpQMark InpEMark InpAmp InpDash InpOpenB InpCloseB InpUnknown */ + { Lt, ChD, ChD, ChD, ChD, Ref, ChD, ChD, ChD1, ChD }, // Init + { Lt, ChD, ChD, ChD, ChD, Ref, ChD, ChD, ChD1, ChD }, // ChD + { Lt, ChD, ChD, ChD, ChD, Ref, ChD, ChD, ChD2, ChD }, // ChD1 + { Lt, -1, ChD, ChD, ChD, Ref, ChD, ChD, ChD2, ChD }, // ChD2 + { Lt, ChD, ChD, ChD, ChD, Ref, ChD, ChD, ChD, ChD }, // Ref (same as Init) + { -1, -1, Done, PI, Em, -1, -1, -1, -1, Elem }, // Lt + { Lt, ChD, ChD, ChD, ChD, Ref, ChD, ChD, ChD, ChD }, // PI (same as Init) + { Lt, ChD, ChD, ChD, ChD, Ref, ChD, ChD, ChD, ChD }, // Elem (same as Init) + { -1, -1, -1, -1, -1, -1, Com, CDS, -1, -1 }, // Em + { Lt, ChD, ChD, ChD, ChD, Ref, ChD, ChD, ChD, ChD }, // Com (same as Init) + { CDS1, CDS1, CDS1, CDS1, CDS1, CDS1, CDS1, CDS1, CDS2, CDS1 }, // CDS + { CDS1, CDS1, CDS1, CDS1, CDS1, CDS1, CDS1, CDS1, CDS2, CDS1 }, // CDS1 + { CDS1, CDS1, CDS1, CDS1, CDS1, CDS1, CDS1, CDS1, CDS3, CDS1 }, // CDS2 + { CDS1, Init, CDS1, CDS1, CDS1, CDS1, CDS1, CDS1, CDS3, CDS1 } // CDS3 + }; + signed char state = Init; + signed char input; + bool parseOk = TRUE; + + for (;;) { + + // get input (use lookup-table instead of nested ifs for performance + // reasons) + if ( atEnd() ) { + d->error = XMLERR_UNEXPECTEDEOF; + goto parseError; + } + if ( c.row() ) { + input = InpUnknown; + } else { + input = mapCLT2FSMChar[ charLookupTable[ c.cell() ] ]; + } + + // set state according to input + state = table[state][input]; + + // do some actions according to state + switch ( state ) { + case Init: + // next character + next(); + break; + case ChD: + // on first call: clear string + if ( !charDataRead ) { + charDataRead = TRUE; + stringClear(); + } + stringAddC(); + next(); + break; + case ChD1: + // on first call: clear string + if ( !charDataRead ) { + charDataRead = TRUE; + stringClear(); + } + stringAddC(); + next(); + break; + case ChD2: + stringAddC(); + next(); + break; + case Ref: + if ( !charDataRead) { + // reference may be CharData; so clear string to be safe + stringClear(); + parseOk = parseReference( charDataRead, InContent ); + } else { + if ( d->reportEntities ) { + // this is undocumented so far; do this right in Qt 3.0 + if ( contentHnd ) { + if ( d->reportWhitespaceCharData || !string().simplifyWhiteSpace().isEmpty() ) { + if ( !contentHnd->characters( string() ) ) { + d->error = contentHnd->errorString(); + goto parseError; + } + } + } + stringClear(); + } + bool tmp; + parseOk = parseReference( tmp, InContent ); + } + break; + case Lt: + // call the handler for CharData + if ( contentHnd ) { + if ( charDataRead ) { + if ( d->reportWhitespaceCharData || !string().simplifyWhiteSpace().isEmpty() ) { + if ( !contentHnd->characters( string() ) ) { + d->error = contentHnd->errorString(); + goto parseError; + } + } + } + } + charDataRead = FALSE; + // next character + next(); + break; + case PI: + parseOk = parsePI(); + break; + case Elem: + parseOk = parseElement(); + break; + case Em: + // next character + next(); + break; + case Com: + parseOk = parseComment(); + break; + case CDS: + parseOk = parseString( "[CDATA[" ); + break; + case CDS1: + // read one character and add it + stringAddC(); + next(); + break; + case CDS2: + // skip ']' + next(); + break; + case CDS3: + // skip ']'... + next(); + break; + } + // no input is read after this + switch ( state ) { + case Ref: + if ( !parseOk ) { + d->error = XMLERR_ERRORPARSINGREFERENCE; + goto parseError; + } + break; + case PI: + if ( !parseOk ) { + d->error = XMLERR_ERRORPARSINGPI; + goto parseError; + } + // call the handler + if ( contentHnd ) { + if ( !contentHnd->processingInstruction(name(),string()) ) { + d->error = contentHnd->errorString(); + goto parseError; + } + } + break; + case Elem: + if ( !parseOk ) { + d->error = XMLERR_ERRORPARSINGELEMENT; + goto parseError; + } + break; + case Com: + if ( !parseOk ) { + d->error = XMLERR_ERRORPARSINGCOMMENT; + goto parseError; + } + if ( lexicalHnd ) { + if ( !lexicalHnd->comment( string() ) ) { + d->error = lexicalHnd->errorString(); + goto parseError; + } + } + break; + case CDS: + if( !parseOk ) { + d->error = XMLERR_CDSECTHEADEREXPECTED; + goto parseError; + } + // empty string + stringClear(); + break; + case CDS2: + if (c != ']') { + stringAddC( ']' ); + } + break; + case CDS3: + // test if this skipping was legal + if ( c == '>' ) { + // the end of the CDSect + if ( lexicalHnd ) { + if ( !lexicalHnd->startCDATA() ) { + d->error = lexicalHnd->errorString(); + goto parseError; + } + } + if ( contentHnd ) { + if ( !contentHnd->characters( string() ) ) { + d->error = contentHnd->errorString(); + goto parseError; + } + } + if ( lexicalHnd ) { + if ( !lexicalHnd->endCDATA() ) { + d->error = lexicalHnd->errorString(); + goto parseError; + } + } + } else if (c == ']') { + // three or more ']' + stringAddC( ']' ); + } else { + // after ']]' comes another character + stringAddC( ']' ); + stringAddC( ']' ); + } + break; + case Done: + // call the handler for CharData + if ( contentHnd ) { + if ( charDataRead ) { + if ( d->reportWhitespaceCharData || !string().simplifyWhiteSpace().isEmpty() ) { + if ( !contentHnd->characters( string() ) ) { + d->error = contentHnd->errorString(); + goto parseError; + } + } + } + } + // Done + return TRUE; + case -1: + // Error + d->error = XMLERR_ERRORPARSINGCONTENT; + goto parseError; + } + + } + + return TRUE; + +parseError: + reportParseError(); + return FALSE; +} + +/*! + Parse Misc [27]. +*/ +bool QXmlSimpleReader::parseMisc() +{ + const signed char Init = 0; + const signed char Lt = 1; // '<' was read + const signed char Comment = 2; // read comment + const signed char eatWS = 3; // eat whitespaces + const signed char PI = 4; // read PI + const signed char Comment2 = 5; // read comment + + const signed char InpWs = 0; // S + const signed char InpLt = 1; // < + const signed char InpQm = 2; // ? + const signed char InpEm = 3; // ! + const signed char InpUnknown = 4; + + // use some kind of state machine for parsing + static const signed char table[3][5] = { + /* InpWs InpLt InpQm InpEm InpUnknown */ + { eatWS, Lt, -1, -1, -1 }, // Init + { -1, -1, PI, Comment, -1 }, // Lt + { -1, -1, -1, -1, Comment2 } // Comment + }; + signed char state = Init; + signed char input; + bool parseOk = TRUE; + + for (;;) { + + // get input + if ( atEnd() ) { + d->error = XMLERR_UNEXPECTEDEOF; + goto parseError; + } + if ( is_S(c) ) { + input = InpWs; + } else if ( c == '<' ) { + input = InpLt; + } else if ( c == '?' ) { + input = InpQm; + } else if ( c == '!' ) { + input = InpEm; + } else { + input = InpUnknown; + } + + // set state according to input + state = table[state][input]; + + // do some actions according to state + switch ( state ) { + case eatWS: + eat_ws(); + break; + case Lt: + next(); + break; + case PI: + parseOk = parsePI(); + break; + case Comment: + next(); + break; + case Comment2: + parseOk = parseComment(); + break; + } + // no input is read after this + switch ( state ) { + case eatWS: + return TRUE; + case PI: + if ( !parseOk ) { + d->error = XMLERR_ERRORPARSINGPI; + goto parseError; + } + if ( contentHnd ) { + if ( !contentHnd->processingInstruction(name(),string()) ) { + d->error = contentHnd->errorString(); + goto parseError; + } + } + return TRUE; + case Comment2: + if ( !parseOk ) { + d->error = XMLERR_ERRORPARSINGCOMMENT; + goto parseError; + } + if ( lexicalHnd ) { + if ( !lexicalHnd->comment( string() ) ) { + d->error = lexicalHnd->errorString(); + goto parseError; + } + } + return TRUE; + case -1: + // Error + d->error = XMLERR_UNEXPECTEDCHARACTER; + goto parseError; + } + + } + + return TRUE; + +parseError: + reportParseError(); + return FALSE; +} + +/*! + Parse a processing instruction [16]. + + If xmldec is TRUE, it tries to parse a PI or a XML declaration [23]. + + Precondition: the beginning '<' of the PI is already read and the head stand + on the '?' of ' + const signed char InpQm = 3; // ? + const signed char InpUnknown = 4; + + // use some kind of state machine for parsing + static const signed char table[16][5] = { + /* InpWs, InpNameBe InpGt InpQm InpUnknown */ + { -1, -1, -1, QmI, -1 }, // Init + { -1, Name, -1, -1, -1 }, // QmI + { -1, -1, -1, -1, -1 }, // Name (this state is left not through input) + { Ws1, -1, -1, -1, -1 }, // XMLDecl + { -1, Version, -1, -1, -1 }, // Ws1 + { Ws2, -1, -1, Qm, -1 }, // PI + { Char, Char, Char, Qm, Char }, // Ws2 + { Ws3, -1, -1, ADone, -1 }, // Version + { -1, EorSD, -1, ADone, -1 }, // Ws3 + { Ws4, -1, -1, ADone, -1 }, // EorSD + { -1, SD, -1, ADone, -1 }, // Ws4 + { Ws5, -1, -1, ADone, -1 }, // SD + { -1, -1, -1, ADone, -1 }, // Ws5 + { -1, -1, Done, -1, -1 }, // ADone + { Char, Char, Char, Qm, Char }, // Char + { Char, Char, Done, Qm, Char }, // Qm + }; + signed char state = Init; + signed char input; + bool parseOk = TRUE; + + for (;;) { + + // get input + if ( atEnd() ) { + d->error = XMLERR_UNEXPECTEDEOF; + goto parseError; + } + if ( is_S(c) ) { + input = InpWs; + } else if ( is_NameBeginning(c) ) { + input = InpNameBe; + } else if ( c == '>' ) { + input = InpGt; + } else if ( c == '?' ) { + input = InpQm; + } else { + input = InpUnknown; + } + + // set state according to input + state = table[state][input]; + + // do some actions according to state + switch ( state ) { + case QmI: + next(); + break; + case Name: + parseOk = parseName(); + break; + case Ws1: + case Ws2: + case Ws3: + case Ws4: + case Ws5: + eat_ws(); + break; + case Version: + parseOk = parseAttribute(); + break; + case EorSD: + parseOk = parseAttribute(); + break; + case SD: + // get the SDDecl (syntax like an attribute) + if ( d->standalone != QXmlSimpleReaderPrivate::Unknown ) { + // already parsed the standalone declaration + d->error = XMLERR_UNEXPECTEDCHARACTER; + goto parseError; + } + parseOk = parseAttribute(); + break; + case ADone: + next(); + break; + case Char: + stringAddC(); + next(); + break; + case Qm: + // skip the '?' + next(); + break; + case Done: + next(); + break; + } + // no input is read after this + switch ( state ) { + case Name: + if ( !parseOk ) { + d->error = XMLERR_ERRORPARSINGNAME; + goto parseError; + } + // test what name was read and determine the next state + // (not very beautiful, I admit) + if ( name().lower() == "xml" ) { + if ( xmldecl && name()=="xml" ) { + state = XMLDecl; + } else { + d->error = XMLERR_INVALIDNAMEFORPI; + goto parseError; + } + } else { + state = PI; + stringClear(); + } + break; + case Version: + // get version (syntax like an attribute) + if ( !parseOk ) { + d->error = XMLERR_VERSIONEXPECTED; + goto parseError; + } + if ( name() != "version" ) { + d->error = XMLERR_VERSIONEXPECTED; + goto parseError; + } + d->xmlVersion = string(); + break; + case EorSD: + // get the EDecl or SDDecl (syntax like an attribute) + if ( !parseOk ) { + d->error = XMLERR_EDECLORSDDECLEXPECTED; + goto parseError; + } + if ( name() == "standalone" ) { + if ( string()=="yes" ) { + d->standalone = QXmlSimpleReaderPrivate::Yes; + } else if ( string()=="no" ) { + d->standalone = QXmlSimpleReaderPrivate::No; + } else { + d->error = XMLERR_WRONGVALUEFORSDECL; + goto parseError; + } + } else if ( name() == "encoding" ) { + d->encoding = string(); + } else { + d->error = XMLERR_EDECLORSDDECLEXPECTED; + goto parseError; + } + break; + case SD: + if ( !parseOk ) { + d->error = XMLERR_SDDECLEXPECTED; + goto parseError; + } + if ( name() != "standalone" ) { + d->error = XMLERR_SDDECLEXPECTED; + goto parseError; + } + if ( string()=="yes" ) { + d->standalone = QXmlSimpleReaderPrivate::Yes; + } else if ( string()=="no" ) { + d->standalone = QXmlSimpleReaderPrivate::No; + } else { + d->error = XMLERR_WRONGVALUEFORSDECL; + goto parseError; + } + break; + case Qm: + // test if the skipping was legal + if ( c != '>' ) { + stringAddC( '?' ); + } + break; + case Done: + return TRUE; + case -1: + // Error + d->error = XMLERR_UNEXPECTEDCHARACTER; + goto parseError; + } + + } + + return TRUE; + +parseError: + reportParseError(); + return FALSE; +} + +/*! + Parse a document type definition (doctypedecl [28]). + + Precondition: the beginning 'systemId = QString::null; + d->publicId = QString::null; + + const signed char Init = 0; + const signed char Doctype = 1; // read the doctype + const signed char Ws1 = 2; // eat_ws + const signed char Doctype2 = 3; // read the doctype, part 2 + const signed char Ws2 = 4; // eat_ws + const signed char Sys = 5; // read SYSTEM + const signed char Ws3 = 6; // eat_ws + const signed char MP = 7; // markupdecl or PEReference + const signed char PER = 8; // PERReference + const signed char Mup = 9; // markupdecl + const signed char Ws4 = 10; // eat_ws + const signed char MPE = 11; // end of markupdecl or PEReference + const signed char Done = 12; + + const signed char InpWs = 0; + const signed char InpD = 1; // 'D' + const signed char InpS = 2; // 'S' or 'P' + const signed char InpOB = 3; // [ + const signed char InpCB = 4; // ] + const signed char InpPer = 5; // % + const signed char InpGt = 6; // > + const signed char InpUnknown = 7; + + // use some kind of state machine for parsing + static const signed char table[12][8] = { + /* InpWs, InpD InpS InpOB InpCB InpPer InpGt InpUnknown */ + { -1, Doctype, -1, -1, -1, -1, -1, -1 }, // Init + { Ws1, Doctype2, Doctype2, -1, -1, -1, -1, Doctype2 }, // Doctype + { -1, Doctype2, Doctype2, -1, -1, -1, -1, Doctype2 }, // Ws1 + { Ws2, -1, Sys, MP, -1, -1, Done, -1 }, // Doctype2 + { -1, -1, Sys, MP, -1, -1, Done, -1 }, // Ws2 + { Ws3, -1, -1, MP, -1, -1, Done, -1 }, // Sys + { -1, -1, -1, MP, -1, -1, Done, -1 }, // Ws3 + { -1, -1, -1, -1, MPE, PER, -1, Mup }, // MP + { Ws4, -1, -1, -1, MPE, PER, -1, Mup }, // PER + { Ws4, -1, -1, -1, MPE, PER, -1, Mup }, // Mup + { -1, -1, -1, -1, MPE, PER, -1, Mup }, // Ws4 + { -1, -1, -1, -1, -1, -1, Done, -1 } // MPE + }; + signed char state = Init; + signed char input; + bool parseOk = TRUE; + + for (;;) { + + // get input + if ( atEnd() ) { + d->error = XMLERR_UNEXPECTEDEOF; + goto parseError; + } + if ( is_S(c) ) { + input = InpWs; + } else if ( c == 'D' ) { + input = InpD; + } else if ( c == 'S' ) { + input = InpS; + } else if ( c == 'P' ) { + input = InpS; + } else if ( c == '[' ) { + input = InpOB; + } else if ( c == ']' ) { + input = InpCB; + } else if ( c == '%' ) { + input = InpPer; + } else if ( c == '>' ) { + input = InpGt; + } else { + input = InpUnknown; + } + + // set state according to input + state = table[state][input]; + + // do some actions according to state + switch ( state ) { + case Doctype: + parseOk = parseString( "DOCTYPE" ); + break; + case Ws1: + case Ws2: + case Ws3: + case Ws4: + eat_ws(); + break; + case Doctype2: + parseName(); + break; + case Sys: + parseOk = parseExternalID(); + break; + case MP: + next_eat_ws(); + break; + case PER: + parseOk = parsePEReference( InDTD ); + break; + case Mup: + parseOk = parseMarkupdecl(); + break; + case MPE: + next_eat_ws(); + break; + case Done: + if ( lexicalHnd ) { + if ( !lexicalHnd->endDTD() ) { + d->error = lexicalHnd->errorString(); + goto parseError; + } + } + next(); + break; + } + // no input is read after this + switch ( state ) { + case Doctype: + if ( !parseOk ) { + d->error = XMLERR_ERRORPARSINGDOCTYPE; + goto parseError; + } + if ( !is_S(c) ) { + d->error = XMLERR_ERRORPARSINGDOCTYPE; + goto parseError; + } + break; + case Doctype2: + d->doctype = name(); + if ( lexicalHnd ) { + if ( !lexicalHnd->startDTD( d->doctype, d->publicId, d->systemId ) ) { + d->error = lexicalHnd->errorString(); + goto parseError; + } + } + break; + case Sys: + if ( !parseOk ) { + d->error = XMLERR_ERRORPARSINGDOCTYPE; + goto parseError; + } + break; + case PER: + if ( !parseOk ) { + d->error = XMLERR_ERRORPARSINGDOCTYPE; + goto parseError; + } + break; + case Mup: + if ( !parseOk ) { + d->error = XMLERR_ERRORPARSINGDOCTYPE; + goto parseError; + } + break; + case Done: + return TRUE; + case -1: + // Error + d->error = XMLERR_ERRORPARSINGDOCTYPE; + goto parseError; + } + + } + + return TRUE; + +parseError: + reportParseError(); + return FALSE; +} + +/*! + Parse a ExternalID [75]. + + If allowPublicID is TRUE parse ExternalID [75] or PublicID [83]. +*/ +bool QXmlSimpleReader::parseExternalID( bool allowPublicID ) +{ + // some init-stuff + d->systemId = QString::null; + d->publicId = QString::null; + + const signed char Init = 0; + const signed char Sys = 1; // parse 'SYSTEM' + const signed char SysWS = 2; // parse the whitespace after 'SYSTEM' + const signed char SysSQ = 3; // parse SystemLiteral with ' + const signed char SysSQ2 = 4; // parse SystemLiteral with ' + const signed char SysDQ = 5; // parse SystemLiteral with " + const signed char SysDQ2 = 6; // parse SystemLiteral with " + const signed char Pub = 7; // parse 'PUBLIC' + const signed char PubWS = 8; // parse the whitespace after 'PUBLIC' + const signed char PubSQ = 9; // parse PubidLiteral with ' + const signed char PubSQ2 = 10; // parse PubidLiteral with ' + const signed char PubDQ = 11; // parse PubidLiteral with " + const signed char PubDQ2 = 12; // parse PubidLiteral with " + const signed char PubE = 13; // finished parsing the PubidLiteral + const signed char PubWS2 = 14; // parse the whitespace after the PubidLiteral + const signed char PDone = 15; // done if allowPublicID is TRUE + const signed char Done = 16; + + const signed char InpSQ = 0; // ' + const signed char InpDQ = 1; // " + const signed char InpS = 2; // S + const signed char InpP = 3; // P + const signed char InpWs = 4; // white space + const signed char InpUnknown = 5; + + // use some kind of state machine for parsing + static const signed char table[15][6] = { + /* InpSQ InpDQ InpS InpP InpWs InpUnknown */ + { -1, -1, Sys, Pub, -1, -1 }, // Init + { -1, -1, -1, -1, SysWS, -1 }, // Sys + { SysSQ, SysDQ, -1, -1, -1, -1 }, // SysWS + { Done, SysSQ2, SysSQ2, SysSQ2, SysSQ2, SysSQ2 }, // SysSQ + { Done, SysSQ2, SysSQ2, SysSQ2, SysSQ2, SysSQ2 }, // SysSQ2 + { SysDQ2, Done, SysDQ2, SysDQ2, SysDQ2, SysDQ2 }, // SysDQ + { SysDQ2, Done, SysDQ2, SysDQ2, SysDQ2, SysDQ2 }, // SysDQ2 + { -1, -1, -1, -1, PubWS, -1 }, // Pub + { PubSQ, PubDQ, -1, -1, -1, -1 }, // PubWS + { PubE, -1, PubSQ2, PubSQ2, PubSQ2, PubSQ2 }, // PubSQ + { PubE, -1, PubSQ2, PubSQ2, PubSQ2, PubSQ2 }, // PubSQ2 + { -1, PubE, PubDQ2, PubDQ2, PubDQ2, PubDQ2 }, // PubDQ + { -1, PubE, PubDQ2, PubDQ2, PubDQ2, PubDQ2 }, // PubDQ2 + { PDone, PDone, PDone, PDone, PubWS2, PDone }, // PubE + { SysSQ, SysDQ, PDone, PDone, PDone, PDone } // PubWS2 + }; + signed char state = Init; + signed char input; + bool parseOk = TRUE; + + for (;;) { + + // get input + if ( atEnd() ) { + d->error = XMLERR_UNEXPECTEDEOF; + goto parseError; + } + if ( is_S(c) ) { + input = InpWs; + } else if ( c == '\'' ) { + input = InpSQ; + } else if ( c == '"' ) { + input = InpDQ; + } else if ( c == 'S' ) { + input = InpS; + } else if ( c == 'P' ) { + input = InpP; + } else { + input = InpUnknown; + } + + // set state according to input + state = table[state][input]; + + // do some actions according to state + switch ( state ) { + case Sys: + parseOk = parseString( "SYSTEM" ); + break; + case SysWS: + eat_ws(); + break; + case SysSQ: + case SysDQ: + stringClear(); + next(); + break; + case SysSQ2: + case SysDQ2: + stringAddC(); + next(); + break; + case Pub: + parseOk = parseString( "PUBLIC" ); + break; + case PubWS: + eat_ws(); + break; + case PubSQ: + case PubDQ: + stringClear(); + next(); + break; + case PubSQ2: + case PubDQ2: + stringAddC(); + next(); + break; + case PubE: + next(); + break; + case PubWS2: + d->publicId = string(); + eat_ws(); + break; + case Done: + d->systemId = string(); + next(); + break; + } + // no input is read after this + switch ( state ) { + case Sys: + if( !parseOk ) { + d->error = XMLERR_UNEXPECTEDCHARACTER; + goto parseError; + } + break; + case Pub: + if( !parseOk ) { + d->error = XMLERR_UNEXPECTEDCHARACTER; + goto parseError; + } + break; + case PDone: + if ( allowPublicID ) { + d->publicId = string(); + return TRUE; + } else { + d->error = XMLERR_UNEXPECTEDCHARACTER; + goto parseError; + } + break; + case Done: + return TRUE; + case -1: + // Error + d->error = XMLERR_UNEXPECTEDCHARACTER; + goto parseError; + } + + } + + return TRUE; + +parseError: + reportParseError(); + return FALSE; +} + +/*! + Parse a markupdecl [29]. +*/ +bool QXmlSimpleReader::parseMarkupdecl() +{ + const signed char Init = 0; + const signed char Lt = 1; // < was read + const signed char Em = 2; // ! was read + const signed char CE = 3; // E was read + const signed char Qm = 4; // ? was read + const signed char Dash = 5; // - was read + const signed char CA = 6; // A was read + const signed char CEL = 7; // EL was read + const signed char CEN = 8; // EN was read + const signed char CN = 9; // N was read + const signed char Done = 10; + + const signed char InpLt = 0; // < + const signed char InpQm = 1; // ? + const signed char InpEm = 2; // ! + const signed char InpDash = 3; // - + const signed char InpA = 4; // A + const signed char InpE = 5; // E + const signed char InpL = 6; // L + const signed char InpN = 7; // N + const signed char InpUnknown = 8; + + // use some kind of state machine for parsing + static const signed char table[4][9] = { + /* InpLt InpQm InpEm InpDash InpA InpE InpL InpN InpUnknown */ + { Lt, -1, -1, -1, -1, -1, -1, -1, -1 }, // Init + { -1, Qm, Em, -1, -1, -1, -1, -1, -1 }, // Lt + { -1, -1, -1, Dash, CA, CE, -1, CN, -1 }, // Em + { -1, -1, -1, -1, -1, -1, CEL, CEN, -1 } // CE + }; + signed char state = Init; + signed char input; + bool parseOk = TRUE; + + for (;;) { + + // get input + if ( atEnd() ) { + d->error = XMLERR_UNEXPECTEDEOF; + goto parseError; + } + if ( c == '<' ) { + input = InpLt; + } else if ( c == '?' ) { + input = InpQm; + } else if ( c == '!' ) { + input = InpEm; + } else if ( c == '-' ) { + input = InpDash; + } else if ( c == 'A' ) { + input = InpA; + } else if ( c == 'E' ) { + input = InpE; + } else if ( c == 'L' ) { + input = InpL; + } else if ( c == 'N' ) { + input = InpN; + } else { + input = InpUnknown; + } + + // set state according to input + state = table[state][input]; + + // do some actions according to state + switch ( state ) { + case Lt: + next(); + break; + case Em: + next(); + break; + case CE: + next(); + break; + case Qm: + parseOk = parsePI(); + break; + case Dash: + parseOk = parseComment(); + break; + case CA: + parseOk = parseAttlistDecl(); + break; + case CEL: + parseOk = parseElementDecl(); + break; + case CEN: + parseOk = parseEntityDecl(); + break; + case CN: + parseOk = parseNotationDecl(); + break; + } + // no input is read after this + switch ( state ) { + case Qm: + if ( !parseOk ) { + d->error = XMLERR_ERRORPARSINGPI; + goto parseError; + } + if ( contentHnd ) { + if ( !contentHnd->processingInstruction(name(),string()) ) { + d->error = contentHnd->errorString(); + goto parseError; + } + } + return TRUE; + case Dash: + if ( !parseOk ) { + d->error = XMLERR_ERRORPARSINGCOMMENT; + goto parseError; + } + if ( lexicalHnd ) { + if ( !lexicalHnd->comment( string() ) ) { + d->error = lexicalHnd->errorString(); + goto parseError; + } + } + return TRUE; + case CA: + if ( !parseOk ) { + d->error = XMLERR_ERRORPARSINGATTLISTDECL; + goto parseError; + } + return TRUE; + case CEL: + if ( !parseOk ) { + d->error = XMLERR_ERRORPARSINGELEMENTDECL; + goto parseError; + } + return TRUE; + case CEN: + if ( !parseOk ) { + d->error = XMLERR_ERRORPARSINGENTITYDECL; + goto parseError; + } + return TRUE; + case CN: + if ( !parseOk ) { + d->error = XMLERR_ERRORPARSINGNOTATIONDECL; + goto parseError; + } + return TRUE; + case Done: + return TRUE; + case -1: + // Error + d->error = XMLERR_LETTEREXPECTED; + goto parseError; + } + + } + + return TRUE; + +parseError: + reportParseError(); + return FALSE; +} + +/*! + Parse a PEReference [69] +*/ +bool QXmlSimpleReader::parsePEReference( EntityRecognitionContext context ) +{ + const signed char Init = 0; + const signed char Next = 1; + const signed char Name = 2; + const signed char Done = 3; + + const signed char InpSemi = 0; // ; + const signed char InpPer = 1; // % + const signed char InpUnknown = 2; + + // use some kind of state machine for parsing + static const signed char table[3][3] = { + /* InpSemi InpPer InpUnknown */ + { -1, Next, -1 }, // Init + { -1, -1, Name }, // Next + { Done, -1, -1 } // Name + }; + signed char state = Init; + signed char input; + bool parseOk = TRUE; + + for (;;) { + + // get input + if ( atEnd() ) { + d->error = XMLERR_UNEXPECTEDEOF; + goto parseError; + } + if ( c == ';' ) { + input = InpSemi; + } else if ( c == '%' ) { + input = InpPer; + } else { + input = InpUnknown; + } + + // set state according to input + state = table[state][input]; + + // do some actions according to state + switch ( state ) { + case Next: + next(); + break; + case Name: + parseOk = parseName( TRUE ); + break; + case Done: + next(); + break; + } + // no input is read after this + switch ( state ) { + case Name: + if ( !parseOk ) { + d->error = XMLERR_ERRORPARSINGNAME; + goto parseError; + } + if ( d->parameterEntities.find( ref() ) == d->parameterEntities.end() ) { + // ### skip it??? + if ( contentHnd ) { + if ( !contentHnd->skippedEntity( QString("%") + ref() ) ) { + d->error = contentHnd->errorString(); + goto parseError; + } + } + } else { + if ( context == InEntityValue ) { + // Included in literal + xmlRef = d->parameterEntities.find( ref() ) + .data().replace( QRegExp("\""), """ ).replace( QRegExp("'"), "'" ) + + xmlRef; + } else if ( context == InDTD ) { + // Included as PE + xmlRef = QString(" ") + + d->parameterEntities.find( ref() ).data() + + QString(" ") + xmlRef; + } + } + break; + case Done: + return TRUE; + case -1: + // Error + d->error = XMLERR_LETTEREXPECTED; + goto parseError; + } + + } + + return TRUE; + +parseError: + reportParseError(); + return FALSE; +} + +/*! + Parse a AttlistDecl [52]. + + Precondition: the beginning ' + const signed char InpHash = 2; // # + const signed char InpA = 3; // A + const signed char InpI = 4; // I + const signed char InpF = 5; // F + const signed char InpR = 6; // R + const signed char InpUnknown = 7; + + // use some kind of state machine for parsing + static const signed char table[15][8] = { + /* InpWs InpGt InpHash InpA InpI InpF InpR InpUnknown */ + { -1, -1, -1, Attlist, -1, -1, -1, -1 }, // Init + { Ws, -1, -1, -1, -1, -1, -1, -1 }, // Attlist + { -1, -1, -1, Name, Name, Name, Name, Name }, // Ws + { Ws1, Done, Attdef, Attdef, Attdef, Attdef, Attdef, Attdef }, // Name + { -1, Done, Attdef, Attdef, Attdef, Attdef, Attdef, Attdef }, // Ws1 + { Ws2, -1, -1, -1, -1, -1, -1, -1 }, // Attdef + { -1, Atttype, Atttype, Atttype, Atttype, Atttype, Atttype, Atttype }, // Ws2 + { Ws3, -1, -1, -1, -1, -1, -1, -1 }, // Attype + { -1, Attval, DDecH, Attval, Attval, Attval, Attval, Attval }, // Ws3 + { -1, -1, -1, -1, DefImp, DefFix, DefReq, -1 }, // DDecH + { Ws4, Ws4, -1, -1, -1, -1, -1, -1 }, // DefReq + { Ws4, Ws4, -1, -1, -1, -1, -1, -1 }, // DefImp + { Ws3, -1, -1, -1, -1, -1, -1, -1 }, // DefFix + { Ws4, Ws4, -1, -1, -1, -1, -1, -1 }, // Attval + { -1, Done, Attdef, Attdef, Attdef, Attdef, Attdef, Attdef } // Ws4 + }; + signed char state = Init; + signed char input; + bool parseOk = TRUE; + + for (;;) { + + // get input + if ( atEnd() ) { + d->error = XMLERR_UNEXPECTEDEOF; + goto parseError; + } + if ( is_S(c) ) { + input = InpWs; + } else if ( c == '>' ) { + input = InpGt; + } else if ( c == '#' ) { + input = InpHash; + } else if ( c == 'A' ) { + input = InpA; + } else if ( c == 'I' ) { + input = InpI; + } else if ( c == 'F' ) { + input = InpF; + } else if ( c == 'R' ) { + input = InpR; + } else { + input = InpUnknown; + } + + // set state according to input + state = table[state][input]; + + // do some actions according to state + switch ( state ) { + case Attlist: + parseOk = parseString( "ATTLIST" ); + break; + case Ws: + case Ws1: + case Ws2: + case Ws3: + eat_ws(); + break; + case Name: + parseOk = parseName(); + break; + case Attdef: + parseOk = parseName(); + break; + case Atttype: + parseOk = parseAttType(); + break; + case DDecH: + next(); + break; + case DefReq: + parseOk = parseString( "REQUIRED" ); + break; + case DefImp: + parseOk = parseString( "IMPLIED" ); + break; + case DefFix: + parseOk = parseString( "FIXED" ); + break; + case Attval: + parseOk = parseAttValue(); + break; + case Ws4: + if ( declHnd ) { + // TODO: not all values are computed yet... + if ( !declHnd->attributeDecl( d->attDeclEName, d->attDeclAName, "", "", "" ) ) { + d->error = declHnd->errorString(); + goto parseError; + } + } + eat_ws(); + break; + case Done: + next(); + break; + } + // no input is read after this + switch ( state ) { + case Attlist: + if( !parseOk ) { + d->error = XMLERR_UNEXPECTEDCHARACTER; + goto parseError; + } + break; + case Name: + if ( !parseOk ) { + d->error = XMLERR_ERRORPARSINGNAME; + goto parseError; + } + d->attDeclEName = name(); + break; + case Attdef: + if ( !parseOk ) { + d->error = XMLERR_ERRORPARSINGNAME; + goto parseError; + } + d->attDeclAName = name(); + break; + case Atttype: + if ( !parseOk ) { + d->error = XMLERR_ERRORPARSINGATTTYPE; + goto parseError; + } + break; + case DefReq: + if( !parseOk ) { + d->error = XMLERR_UNEXPECTEDCHARACTER; + goto parseError; + } + break; + case DefImp: + if( !parseOk ) { + d->error = XMLERR_UNEXPECTEDCHARACTER; + goto parseError; + } + break; + case DefFix: + if( !parseOk ) { + d->error = XMLERR_UNEXPECTEDCHARACTER; + goto parseError; + } + break; + case Attval: + if ( !parseOk ) { + d->error = XMLERR_ERRORPARSINGATTVALUE; + goto parseError; + } + break; + case Done: + return TRUE; + case -1: + // Error + d->error = XMLERR_LETTEREXPECTED; + goto parseError; + } + + } + + return TRUE; + +parseError: + reportParseError(); + return FALSE; +} + +/*! + Parse a AttType [54] +*/ +bool QXmlSimpleReader::parseAttType() +{ + const signed char Init = 0; + const signed char ST = 1; // StringType + const signed char TTI = 2; // TokenizedType starting with 'I' + const signed char TTI2 = 3; // TokenizedType helpstate + const signed char TTI3 = 4; // TokenizedType helpstate + const signed char TTE = 5; // TokenizedType starting with 'E' + const signed char TTEY = 6; // TokenizedType starting with 'ENTITY' + const signed char TTEI = 7; // TokenizedType starting with 'ENTITI' + const signed char N = 8; // N read (TokenizedType or Notation) + const signed char TTNM = 9; // TokenizedType starting with 'NM' + const signed char TTNM2 = 10; // TokenizedType helpstate + const signed char NO = 11; // Notation + const signed char NO2 = 12; // Notation helpstate + const signed char NO3 = 13; // Notation helpstate + const signed char NOName = 14; // Notation, read name + const signed char NO4 = 15; // Notation helpstate + const signed char EN = 16; // Enumeration + const signed char ENNmt = 17; // Enumeration, read Nmtoken + const signed char EN2 = 18; // Enumeration helpstate + const signed char ADone = 19; // almost done (make next and accept) + const signed char Done = 20; + + const signed char InpWs = 0; // whitespace + const signed char InpOp = 1; // ( + const signed char InpCp = 2; // ) + const signed char InpPipe = 3; // | + const signed char InpC = 4; // C + const signed char InpE = 5; // E + const signed char InpI = 6; // I + const signed char InpM = 7; // M + const signed char InpN = 8; // N + const signed char InpO = 9; // O + const signed char InpR = 10; // R + const signed char InpS = 11; // S + const signed char InpY = 12; // Y + const signed char InpUnknown = 13; + + // use some kind of state machine for parsing + static const signed char table[19][14] = { + /* InpWs InpOp InpCp InpPipe InpC InpE InpI InpM InpN InpO InpR InpS InpY InpUnknown */ + { -1, EN, -1, -1, ST, TTE, TTI, -1, N, -1, -1, -1, -1, -1 }, // Init + { Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done }, // ST + { Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, TTI2, Done, Done, Done }, // TTI + { Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, TTI3, Done, Done }, // TTI2 + { Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done }, // TTI3 + { -1, -1, -1, -1, -1, -1, TTEI, -1, -1, -1, -1, -1, TTEY, -1 }, // TTE + { Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done }, // TTEY + { Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done }, // TTEI + { -1, -1, -1, -1, -1, -1, -1, TTNM, -1, NO, -1, -1, -1, -1 }, // N + { Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, TTNM2, Done, Done }, // TTNM + { Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done }, // TTNM2 + { NO2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, // NO + { -1, NO3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, // NO2 + { NOName, NOName, NOName, NOName, NOName, NOName, NOName, NOName, NOName, NOName, NOName, NOName, NOName, NOName }, // NO3 + { NO4, -1, ADone, NO3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, // NOName + { -1, -1, ADone, NO3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, // NO4 + { -1, -1, ENNmt, -1, ENNmt, ENNmt, ENNmt, ENNmt, ENNmt, ENNmt, ENNmt, ENNmt, ENNmt, ENNmt }, // EN + { EN2, -1, ADone, EN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, // ENNmt + { -1, -1, ADone, EN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } // EN2 + }; + signed char state = Init; + signed char input; + bool parseOk = TRUE; + + for (;;) { + + // get input + if ( atEnd() ) { + d->error = XMLERR_UNEXPECTEDEOF; + goto parseError; + } + if ( is_S(c) ) { + input = InpWs; + } else if ( c == '(' ) { + input = InpOp; + } else if ( c == ')' ) { + input = InpCp; + } else if ( c == '|' ) { + input = InpPipe; + } else if ( c == 'C' ) { + input = InpC; + } else if ( c == 'E' ) { + input = InpE; + } else if ( c == 'I' ) { + input = InpI; + } else if ( c == 'M' ) { + input = InpM; + } else if ( c == 'N' ) { + input = InpN; + } else if ( c == 'O' ) { + input = InpO; + } else if ( c == 'R' ) { + input = InpR; + } else if ( c == 'S' ) { + input = InpS; + } else if ( c == 'Y' ) { + input = InpY; + } else { + input = InpUnknown; + } + + // set state according to input + state = table[state][input]; + + // do some actions according to state + switch ( state ) { + case ST: + parseOk = parseString( "CDATA" ); + break; + case TTI: + parseOk = parseString( "ID" ); + break; + case TTI2: + parseOk = parseString( "REF" ); + break; + case TTI3: + next(); // S + break; + case TTE: + parseOk = parseString( "ENTIT" ); + break; + case TTEY: + next(); // Y + break; + case TTEI: + parseOk = parseString( "IES" ); + break; + case N: + next(); // N + break; + case TTNM: + parseOk = parseString( "MTOKEN" ); + break; + case TTNM2: + next(); // S + break; + case NO: + parseOk = parseString( "OTATION" ); + break; + case NO2: + eat_ws(); + break; + case NO3: + next_eat_ws(); + break; + case NOName: + parseOk = parseName(); + break; + case NO4: + eat_ws(); + break; + case EN: + next_eat_ws(); + break; + case ENNmt: + parseOk = parseNmtoken(); + break; + case EN2: + eat_ws(); + break; + case ADone: + next(); + break; + } + // no input is read after this + switch ( state ) { + case ST: + if( !parseOk ) { + d->error = XMLERR_UNEXPECTEDCHARACTER; + goto parseError; + } + break; + case TTI: + if( !parseOk ) { + d->error = XMLERR_UNEXPECTEDCHARACTER; + goto parseError; + } + break; + case TTI2: + if( !parseOk ) { + d->error = XMLERR_UNEXPECTEDCHARACTER; + goto parseError; + } + break; + case TTE: + if( !parseOk ) { + d->error = XMLERR_UNEXPECTEDCHARACTER; + goto parseError; + } + break; + case TTEI: + if( !parseOk ) { + d->error = XMLERR_UNEXPECTEDCHARACTER; + goto parseError; + } + break; + case TTNM: + if( !parseOk ) { + d->error = XMLERR_UNEXPECTEDCHARACTER; + goto parseError; + } + break; + case NO: + if( !parseOk ) { + d->error = XMLERR_UNEXPECTEDCHARACTER; + goto parseError; + } + break; + case NOName: + if ( !parseOk ) { + d->error = XMLERR_ERRORPARSINGNAME; + goto parseError; + } + break; + case ENNmt: + if ( !parseOk ) { + d->error = XMLERR_ERRORPARSINGNMTOKEN; + goto parseError; + } + break; + case ADone: + return TRUE; + case Done: + return TRUE; + case -1: + // Error + d->error = XMLERR_LETTEREXPECTED; + goto parseError; + } + + } + + return TRUE; + +parseError: + reportParseError(); + return FALSE; +} + +/*! + Parse a AttValue [10] + + Precondition: the head stands on the beginning " or ' + + If this function was successful, the head stands on the first + character after the closing " or ' and the value of the attribute + is in string(). +*/ +bool QXmlSimpleReader::parseAttValue() +{ + bool tmp; + + const signed char Init = 0; + const signed char Dq = 1; // double quotes were read + const signed char DqRef = 2; // read references in double quotes + const signed char DqC = 3; // signed character read in double quotes + const signed char Sq = 4; // single quotes were read + const signed char SqRef = 5; // read references in single quotes + const signed char SqC = 6; // signed character read in single quotes + const signed char Done = 7; + + const signed char InpDq = 0; // " + const signed char InpSq = 1; // ' + const signed char InpAmp = 2; // & + const signed char InpLt = 3; // < + const signed char InpUnknown = 4; + + // use some kind of state machine for parsing + static const signed char table[7][5] = { + /* InpDq InpSq InpAmp InpLt InpUnknown */ + { Dq, Sq, -1, -1, -1 }, // Init + { Done, DqC, DqRef, -1, DqC }, // Dq + { Done, DqC, DqRef, -1, DqC }, // DqRef + { Done, DqC, DqRef, -1, DqC }, // DqC + { SqC, Done, SqRef, -1, SqC }, // Sq + { SqC, Done, SqRef, -1, SqC }, // SqRef + { SqC, Done, SqRef, -1, SqC } // SqRef + }; + signed char state = Init; + signed char input; + bool parseOk = TRUE; + + for (;;) { + + // get input + if ( atEnd() ) { + d->error = XMLERR_UNEXPECTEDEOF; + goto parseError; + } + if ( c == '"' ) { + input = InpDq; + } else if ( c == '\'' ) { + input = InpSq; + } else if ( c == '&' ) { + input = InpAmp; + } else if ( c == '<' ) { + input = InpLt; + } else { + input = InpUnknown; + } + + // set state according to input + state = table[state][input]; + + // do some actions according to state + switch ( state ) { + case Dq: + case Sq: + stringClear(); + next(); + break; + case DqRef: + case SqRef: + parseOk = parseReference( tmp, InAttributeValue ); + break; + case DqC: + case SqC: + stringAddC(); + next(); + break; + case Done: + next(); + break; + } + // no input is read after this + switch ( state ) { + case DqRef: + case SqRef: + if ( !parseOk ) { + d->error = XMLERR_ERRORPARSINGREFERENCE; + goto parseError; + } + break; + case Done: + return TRUE; + case -1: + // Error + d->error = XMLERR_UNEXPECTEDCHARACTER; + goto parseError; + } + + } + + return TRUE; + +parseError: + reportParseError(); + return FALSE; +} + +/*! + Parse a elementdecl [45]. + + Precondition: the beginning ' + const signed char InpPipe = 2; // | + const signed char InpOp = 3; // ( + const signed char InpCp = 4; // ) + const signed char InpHash = 5; // # + const signed char InpQm = 6; // ? + const signed char InpAst = 7; // * + const signed char InpPlus = 8; // + + const signed char InpA = 9; // A + const signed char InpE = 10; // E + const signed char InpL = 11; // L + const signed char InpUnknown = 12; + + // use some kind of state machine for parsing + static const signed char table[18][13] = { + /* InpWs InpGt InpPipe InpOp InpCp InpHash InpQm InpAst InpPlus InpA InpE InpL InpUnknown */ + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, Elem, -1 }, // Init + { Ws1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, // Elem + { -1, -1, -1, -1, -1, -1, -1, -1, -1, Nam, Nam, Nam, Nam }, // Ws1 + { Ws2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, // Nam + { -1, -1, -1, Cont, -1, -1, -1, -1, -1, Any, Empty, -1, -1 }, // Ws2 + { WsD, Done, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, // Empty + { WsD, Done, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, // Any + { -1, -1, -1, Cp, Cp, Mix, -1, -1, -1, Cp, Cp, Cp, Cp }, // Cont + { Mix2, -1, MixN1, -1, Mix3, -1, -1, -1, -1, -1, -1, -1, -1 }, // Mix + { -1, -1, MixN1, -1, Mix3, -1, -1, -1, -1, -1, -1, -1, -1 }, // Mix2 + { WsD, Done, -1, -1, -1, -1, -1, WsD, -1, -1, -1, -1, -1 }, // Mix3 + { -1, -1, -1, -1, -1, -1, -1, -1, -1, MixN2, MixN2, MixN2, MixN2 }, // MixN1 + { MixN3, -1, MixN1, -1, MixN4, -1, -1, -1, -1, -1, -1, -1, -1 }, // MixN2 + { -1, -1, MixN1, -1, MixN4, -1, -1, -1, -1, -1, -1, -1, -1 }, // MixN3 + { -1, -1, -1, -1, -1, -1, -1, WsD, -1, -1, -1, -1, -1 }, // MixN4 + { WsD, Done, -1, -1, -1, -1, Cp2, Cp2, Cp2, -1, -1, -1, -1 }, // Cp + { WsD, Done, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, // Cp2 + { -1, Done, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } // WsD + }; + signed char state = Init; + signed char input; + bool parseOk = TRUE; + + for (;;) { + + // read input + if ( atEnd() ) { + d->error = XMLERR_UNEXPECTEDEOF; + goto parseError; + } + if ( is_S(c) ) { + input = InpWs; + } else if ( c == '>' ) { + input = InpGt; + } else if ( c == '|' ) { + input = InpPipe; + } else if ( c == '(' ) { + input = InpOp; + } else if ( c == ')' ) { + input = InpCp; + } else if ( c == '#' ) { + input = InpHash; + } else if ( c == '?' ) { + input = InpQm; + } else if ( c == '*' ) { + input = InpAst; + } else if ( c == '+' ) { + input = InpPlus; + } else if ( c == 'A' ) { + input = InpA; + } else if ( c == 'E' ) { + input = InpE; + } else if ( c == 'L' ) { + input = InpL; + } else { + input = InpUnknown; + } + // get new state +//qDebug( "%d -%d(%c)-> %d", state, input, c.latin1(), table[state][input] ); + state = table[state][input]; + + // in some cases do special actions depending on state + switch ( state ) { + case Elem: + parseOk = parseString( "LEMENT" ); + break; + case Ws1: + eat_ws(); + break; + case Nam: + parseOk = parseName(); + break; + case Ws2: + eat_ws(); + break; + case Empty: + parseOk = parseString( "EMPTY" ); + break; + case Any: + parseOk = parseString( "ANY" ); + break; + case Cont: + next_eat_ws(); + break; + case Mix: + parseOk = parseString( "#PCDATA" ); + break; + case Mix2: + eat_ws(); + break; + case Mix3: + next(); + break; + case MixN1: + next_eat_ws(); + break; + case MixN2: + parseOk = parseName(); + break; + case MixN3: + eat_ws(); + break; + case MixN4: + next(); + break; + case Cp: + parseOk = parseChoiceSeq(); + break; + case Cp2: + next(); + break; + case WsD: + next_eat_ws(); + break; + case Done: + next(); + break; + } + // no input is read after this + switch ( state ) { + case Elem: + if( !parseOk ) { + d->error = XMLERR_UNEXPECTEDCHARACTER; + goto parseError; + } + break; + case Nam: + if ( !parseOk ) { + d->error = XMLERR_ERRORPARSINGNAME; + goto parseError; + } + break; + case Empty: + if( !parseOk ) { + d->error = XMLERR_UNEXPECTEDCHARACTER; + goto parseError; + } + break; + case Any: + if( !parseOk ) { + d->error = XMLERR_UNEXPECTEDCHARACTER; + goto parseError; + } + break; + case Mix: + if( !parseOk ) { + d->error = XMLERR_UNEXPECTEDCHARACTER; + goto parseError; + } + break; + case MixN2: + if ( !parseOk ) { + d->error = XMLERR_ERRORPARSINGNAME; + goto parseError; + } + break; + case Cp: + if ( !parseOk ) { + d->error = XMLERR_ERRORPARSINGCHOICE; + goto parseError; + } + break; + case Done: + return TRUE; + case -1: + d->error = XMLERR_UNEXPECTEDCHARACTER; + goto parseError; + } + + } + + return TRUE; + +parseError: + reportParseError(); + return FALSE; +} + +/*! + Parse a NotationDecl [82]. + + Precondition: the beginning ' + const signed char InpN = 2; // N + const signed char InpUnknown = 3; + + // use some kind of state machine for parsing + static const signed char table[7][4] = { + /* InpWs InpGt InpN InpUnknown */ + { -1, -1, Not, -1 }, // Init + { Ws1, -1, -1, -1 }, // Not + { -1, -1, Nam, Nam }, // Ws1 + { Ws2, Done, -1, -1 }, // Nam + { -1, Done, ExtID, ExtID }, // Ws2 + { Ws3, Done, -1, -1 }, // ExtID + { -1, Done, -1, -1 } // Ws3 + }; + signed char state = Init; + signed char input; + bool parseOk = TRUE; + + for (;;) { + + // get input + if ( atEnd() ) { + d->error = XMLERR_UNEXPECTEDEOF; + goto parseError; + } + if ( is_S(c) ) { + input = InpWs; + } else if ( c == '>' ) { + input = InpGt; + } else if ( c == 'N' ) { + input = InpN; + } else { + input = InpUnknown; + } + + // set state according to input + state = table[state][input]; + + // do some actions according to state + switch ( state ) { + case Not: + parseOk = parseString( "NOTATION" ); + break; + case Ws1: + eat_ws(); + break; + case Nam: + parseOk = parseName(); + break; + case Ws2: + eat_ws(); + break; + case ExtID: + parseOk = parseExternalID( TRUE ); + break; + case Ws3: + eat_ws(); + break; + case Done: + next(); + break; + } + // no input is read after this + switch ( state ) { + case Not: + if ( !parseOk ) { + d->error = XMLERR_UNEXPECTEDCHARACTER; + goto parseError; + } + break; + case Nam: + if ( !parseOk ) { + d->error = XMLERR_ERRORPARSINGNAME; + goto parseError; + } + break; + case ExtID: + if ( !parseOk ) { + d->error = XMLERR_ERRORPARSINGEXTERNALID; + goto parseError; + } + // call the handler + if ( dtdHnd ) { + if ( !dtdHnd->notationDecl( name(), d->publicId, d->systemId ) ) { + d->error = dtdHnd->errorString(); + goto parseError; + } + } + break; + case Done: + return TRUE; + case -1: + // Error + d->error = XMLERR_UNEXPECTEDCHARACTER; + goto parseError; + } + + } + + return TRUE; + +parseError: + reportParseError(); + return FALSE; +} + +/*! + Parse choice [49] or seq [50]. + + Precondition: the beginning '('S? is already read and the head + stands on the first non-whitespace character after it. +*/ +bool QXmlSimpleReader::parseChoiceSeq() +{ + const signed char Init = 0; + const signed char Ws1 = 1; // eat whitespace + const signed char CS = 2; // choice or set + const signed char Ws2 = 3; // eat whitespace + const signed char More = 4; // more cp to read + const signed char Name = 5; // read name + const signed char Done = 6; // + + const signed char InpWs = 0; // S + const signed char InpOp = 1; // ( + const signed char InpCp = 2; // ) + const signed char InpQm = 3; // ? + const signed char InpAst = 4; // * + const signed char InpPlus = 5; // + + const signed char InpPipe = 6; // | + const signed char InpComm = 7; // , + const signed char InpUnknown = 8; + + // use some kind of state machine for parsing + static const signed char table[6][9] = { + /* InpWs InpOp InpCp InpQm InpAst InpPlus InpPipe InpComm InpUnknown */ + { -1, Ws1, -1, -1, -1, -1, -1, -1, Name }, // Init + { -1, CS, -1, -1, -1, -1, -1, -1, CS }, // Ws1 + { Ws2, -1, Done, Ws2, Ws2, Ws2, More, More, -1 }, // CS + { -1, -1, Done, -1, -1, -1, More, More, -1 }, // Ws2 + { -1, Ws1, -1, -1, -1, -1, -1, -1, Name }, // More (same as Init) + { Ws2, -1, Done, Ws2, Ws2, Ws2, More, More, -1 } // Name (same as CS) + }; + signed char state = Init; + signed char input; + bool parseOk = TRUE; + + for (;;) { + + // get input + if ( atEnd() ) { + d->error = XMLERR_UNEXPECTEDEOF; + goto parseError; + } + if ( is_S(c) ) { + input = InpWs; + } else if ( c == '(' ) { + input = InpOp; + } else if ( c == ')' ) { + input = InpCp; + } else if ( c == '?' ) { + input = InpQm; + } else if ( c == '*' ) { + input = InpAst; + } else if ( c == '+' ) { + input = InpPlus; + } else if ( c == '|' ) { + input = InpPipe; + } else if ( c == ',' ) { + input = InpComm; + } else { + input = InpUnknown; + } + + // set state according to input + state = table[state][input]; + + // do some actions according to state + switch ( state ) { + case Ws1: + next_eat_ws(); + break; + case CS: + parseOk = parseChoiceSeq(); + break; + case Ws2: + next_eat_ws(); + break; + case More: + next_eat_ws(); + break; + case Name: + parseOk = parseName(); + break; + case Done: + next(); + break; + } + // no input is read after this + switch ( state ) { + case CS: + if ( !parseOk ) { + d->error = XMLERR_ERRORPARSINGCHOICE; + goto parseError; + } + break; + case Name: + if ( !parseOk ) { + d->error = XMLERR_ERRORPARSINGNAME; + goto parseError; + } + break; + case Done: + return TRUE; + case -1: + // Error + d->error = XMLERR_UNEXPECTEDCHARACTER; + goto parseError; + } + + } + + return TRUE; + +parseError: + reportParseError(); + return FALSE; +} + +/*! + Parse a EntityDecl [70]. + + Precondition: the beginning ' + const signed char InpN = 4; // N + const signed char InpUnknown = 5; + + // use some kind of state machine for parsing + static const signed char table[18][6] = { + /* InpWs InpPer InpQuot InpGt InpN InpUnknown */ + { -1, -1, -1, -1, Ent, -1 }, // Init + { Ws1, -1, -1, -1, -1, -1 }, // Ent + { -1, PEDec, -1, -1, Name, Name }, // Ws1 + { Ws2, -1, -1, -1, -1, -1 }, // Name + { -1, -1, EValue, -1, -1, ExtID }, // Ws2 + { WsE, -1, -1, Done, -1, -1 }, // EValue + { Ws3, -1, -1, EDDone,-1, -1 }, // ExtID + { -1, -1, -1, EDDone,Ndata, -1 }, // Ws3 + { Ws4, -1, -1, -1, -1, -1 }, // Ndata + { -1, -1, -1, -1, NNam, NNam }, // Ws4 + { WsE, -1, -1, Done, -1, -1 }, // NNam + { Ws6, -1, -1, -1, -1, -1 }, // PEDec + { -1, -1, -1, -1, PENam, PENam }, // Ws6 + { Ws7, -1, -1, -1, -1, -1 }, // PENam + { -1, -1, PEVal, -1, -1, PEEID }, // Ws7 + { WsE, -1, -1, Done, -1, -1 }, // PEVal + { WsE, -1, -1, Done, -1, -1 }, // PEEID + { -1, -1, -1, Done, -1, -1 } // WsE + }; + signed char state = Init; + signed char input; + bool parseOk = TRUE; + + for (;;) { + + // get input + if ( atEnd() ) { + d->error = XMLERR_UNEXPECTEDEOF; + goto parseError; + } + if ( is_S(c) ) { + input = InpWs; + } else if ( c == '%' ) { + input = InpPer; + } else if ( c == '"' || c == '\'' ) { + input = InpQuot; + } else if ( c == '>' ) { + input = InpGt; + } else if ( c == 'N' ) { + input = InpN; + } else { + input = InpUnknown; + } + + // set state according to input + state = table[state][input]; + + // do some actions according to state + switch ( state ) { + case Ent: + parseOk = parseString( "NTITY" ); + break; + case Ws1: + eat_ws(); + break; + case Name: + parseOk = parseName(); + break; + case Ws2: + eat_ws(); + break; + case EValue: + parseOk = parseEntityValue(); + break; + case ExtID: + parseOk = parseExternalID(); + break; + case Ws3: + eat_ws(); + break; + case Ndata: + parseOk = parseString( "NDATA" ); + break; + case Ws4: + eat_ws(); + break; + case NNam: + parseOk = parseName( TRUE ); + break; + case PEDec: + next(); + break; + case Ws6: + eat_ws(); + break; + case PENam: + parseOk = parseName(); + break; + case Ws7: + eat_ws(); + break; + case PEVal: + parseOk = parseEntityValue(); + break; + case PEEID: + parseOk = parseExternalID(); + break; + case WsE: + eat_ws(); + break; + case EDDone: + next(); + break; + case Done: + next(); + break; + } + // no input is read after this + switch ( state ) { + case Ent: + if ( !parseOk ) { + d->error = XMLERR_UNEXPECTEDCHARACTER; + goto parseError; + } + break; + case Name: + if ( !parseOk ) { + d->error = XMLERR_ERRORPARSINGNAME; + goto parseError; + } + break; + case EValue: + if ( !parseOk ) { + d->error = XMLERR_ERRORPARSINGENTITYVALUE; + goto parseError; + } + if ( !entityExist( name() ) ) { + d->entities.insert( name(), string() ); + if ( declHnd ) { + if ( !declHnd->internalEntityDecl( name(), string() ) ) { + d->error = declHnd->errorString(); + goto parseError; + } + } + } + break; + case ExtID: + if ( !parseOk ) { + d->error = XMLERR_ERRORPARSINGEXTERNALID; + goto parseError; + } + break; + case Ndata: + if ( !parseOk ) { + d->error = XMLERR_UNEXPECTEDCHARACTER; + goto parseError; + } + break; + case NNam: + if ( !parseOk ) { + d->error = XMLERR_ERRORPARSINGNAME; + goto parseError; + } + if ( !entityExist( name() ) ) { + d->externEntities.insert( name(), QXmlSimpleReaderPrivate::ExternEntity( d->publicId, d->systemId, ref() ) ); + if ( dtdHnd ) { + if ( !dtdHnd->unparsedEntityDecl( name(), d->publicId, d->systemId, ref() ) ) { + d->error = declHnd->errorString(); + goto parseError; + } + } + } + break; + case PENam: + if ( !parseOk ) { + d->error = XMLERR_ERRORPARSINGNAME; + goto parseError; + } + break; + case PEVal: + if ( !parseOk ) { + d->error = XMLERR_ERRORPARSINGENTITYVALUE; + goto parseError; + } + if ( !entityExist( name() ) ) { + d->parameterEntities.insert( name(), string() ); + if ( declHnd ) { + if ( !declHnd->internalEntityDecl( QString("%")+name(), string() ) ) { + d->error = declHnd->errorString(); + goto parseError; + } + } + } + break; + case PEEID: + if ( !parseOk ) { + d->error = XMLERR_ERRORPARSINGEXTERNALID; + goto parseError; + } + if ( !entityExist( name() ) ) { + d->externParameterEntities.insert( name(), QXmlSimpleReaderPrivate::ExternParameterEntity( d->publicId, d->systemId ) ); + if ( declHnd ) { + if ( !declHnd->externalEntityDecl( QString("%")+name(), d->publicId, d->systemId ) ) { + d->error = declHnd->errorString(); + goto parseError; + } + } + } + break; + case EDDone: + if ( !entityExist( name() ) ) { + d->externEntities.insert( name(), QXmlSimpleReaderPrivate::ExternEntity( d->publicId, d->systemId, QString::null ) ); + if ( declHnd ) { + if ( !declHnd->externalEntityDecl( name(), d->publicId, d->systemId ) ) { + d->error = declHnd->errorString(); + goto parseError; + } + } + } + return TRUE; + case Done: + return TRUE; + case -1: + // Error + d->error = XMLERR_LETTEREXPECTED; + goto parseError; + } + + } + + return TRUE; + +parseError: + reportParseError(); + return FALSE; +} + +/*! + Parse a EntityValue [9] +*/ +bool QXmlSimpleReader::parseEntityValue() +{ + bool tmp; + + const signed char Init = 0; + const signed char Dq = 1; // EntityValue is double quoted + const signed char DqC = 2; // signed character + const signed char DqPER = 3; // PERefence + const signed char DqRef = 4; // Reference + const signed char Sq = 5; // EntityValue is double quoted + const signed char SqC = 6; // signed character + const signed char SqPER = 7; // PERefence + const signed char SqRef = 8; // Reference + const signed char Done = 9; + + const signed char InpDq = 0; // " + const signed char InpSq = 1; // ' + const signed char InpAmp = 2; // & + const signed char InpPer = 3; // % + const signed char InpUnknown = 4; + + // use some kind of state machine for parsing + static const signed char table[9][5] = { + /* InpDq InpSq InpAmp InpPer InpUnknown */ + { Dq, Sq, -1, -1, -1 }, // Init + { Done, DqC, DqRef, DqPER, DqC }, // Dq + { Done, DqC, DqRef, DqPER, DqC }, // DqC + { Done, DqC, DqRef, DqPER, DqC }, // DqPER + { Done, DqC, DqRef, DqPER, DqC }, // DqRef + { SqC, Done, SqRef, SqPER, SqC }, // Sq + { SqC, Done, SqRef, SqPER, SqC }, // SqC + { SqC, Done, SqRef, SqPER, SqC }, // SqPER + { SqC, Done, SqRef, SqPER, SqC } // SqRef + }; + signed char state = Init; + signed char input; + bool parseOk = TRUE; + + for (;;) { + + // get input + if ( atEnd() ) { + d->error = XMLERR_UNEXPECTEDEOF; + goto parseError; + } + if ( c == '"' ) { + input = InpDq; + } else if ( c == '\'' ) { + input = InpSq; + } else if ( c == '&' ) { + input = InpAmp; + } else if ( c == '%' ) { + input = InpPer; + } else { + input = InpUnknown; + } + + // set state according to input + state = table[state][input]; + + // do some actions according to state + switch ( state ) { + case Dq: + case Sq: + stringClear(); + next(); + break; + case DqC: + case SqC: + stringAddC(); + next(); + break; + case DqPER: + case SqPER: + parseOk = parsePEReference( InEntityValue ); + break; + case DqRef: + case SqRef: + parseOk = parseReference( tmp, InEntityValue ); + break; + case Done: + next(); + break; + } + // no input is read after this + switch ( state ) { + case DqPER: + case SqPER: + if ( !parseOk ) { + d->error = XMLERR_ERRORPARSINGDOCTYPE; + goto parseError; + } + break; + case DqRef: + case SqRef: + if ( !parseOk ) { + d->error = XMLERR_ERRORPARSINGREFERENCE; + goto parseError; + } + break; + case Done: + return TRUE; + case -1: + // Error + d->error = XMLERR_LETTEREXPECTED; + goto parseError; + } + + } + + return TRUE; + +parseError: + reportParseError(); + return FALSE; +} + +/*! + Parse a comment [15]. + + Precondition: the beginning ' + const signed char InpUnknown = 2; + + // use some kind of state machine for parsing + static const signed char table[6][3] = { + /* InpDash InpGt InpUnknown */ + { Dash1, -1, -1 }, // Init + { Dash2, -1, -1 }, // Dash1 + { Com2, Com, Com }, // Dash2 + { Com2, Com, Com }, // Com + { ComE, Com, Com }, // Com2 + { -1, Done, -1 } // ComE + }; + signed char state = Init; + signed char input; + + for (;;) { + + // get input + if ( atEnd() ) { + d->error = XMLERR_UNEXPECTEDEOF; + goto parseError; + } + if ( c == '-' ) { + input = InpDash; + } else if ( c == '>' ) { + input = InpGt; + } else { + input = InpUnknown; + } + + // set state according to input + state = table[state][input]; + + // do some actions according to state + switch ( state ) { + case Dash1: + next(); + break; + case Dash2: + next(); + break; + case Com: + stringAddC(); + next(); + break; + case Com2: + next(); + break; + case ComE: + next(); + break; + case Done: + next(); + break; + } + // no input is read after this + switch ( state ) { + case Dash2: + stringClear(); + break; + case Com2: + // if next character is not a dash than don't skip it + if ( c != '-' ) { + stringAddC( '-' ); + } + break; + case Done: + return TRUE; + case -1: + // Error + d->error = XMLERR_ERRORPARSINGCOMMENT; + goto parseError; + } + + } + + return TRUE; + +parseError: + reportParseError(); + return FALSE; +} + +/*! + Parse a Attribute [41]. + + Precondition: the head stands on the first character of the name of the + attribute (i.e. all whitespaces are already parsed). + + The head stand on the next character after the end quotes. The variable name + contains the name of the attribute and the variable string contains the value + of the attribute. +*/ +bool QXmlSimpleReader::parseAttribute() +{ + const signed char Init = 0; + const signed char PName = 1; // parse name + const signed char Ws = 2; // eat ws + const signed char Eq = 3; // the '=' was read + const signed char Quotes = 4; // " or ' were read + + const signed char InpNameBe = 0; + const signed char InpEq = 1; // = + const signed char InpDq = 2; // " + const signed char InpSq = 3; // ' + const signed char InpUnknown = 4; + + // use some kind of state machine for parsing + static const signed char table[4][5] = { + /* InpNameBe InpEq InpDq InpSq InpUnknown */ + { PName, -1, -1, -1, -1 }, // Init + { -1, Eq, -1, -1, Ws }, // PName + { -1, Eq, -1, -1, -1 }, // Ws + { -1, -1, Quotes, Quotes, -1 } // Eq + }; + signed char state = Init; + signed char input; + bool parseOk = TRUE; + + for (;;) { + + // get input + if ( atEnd() ) { + d->error = XMLERR_UNEXPECTEDEOF; + goto parseError; + } + if ( is_NameBeginning(c) ) { + input = InpNameBe; + } else if ( c == '=' ) { + input = InpEq; + } else if ( c == '"' ) { + input = InpDq; + } else if ( c == '\'' ) { + input = InpSq; + } else { + input = InpUnknown; + } + + // set state according to input + state = table[state][input]; + + // do some actions according to state + switch ( state ) { + case PName: + parseOk = parseName(); + break; + case Ws: + eat_ws(); + break; + case Eq: + next_eat_ws(); + break; + case Quotes: + parseOk = parseAttValue(); + break; + } + // no input is read after this + switch ( state ) { + case PName: + if ( !parseOk ) { + d->error = XMLERR_ERRORPARSINGNAME; + goto parseError; + } + break; + case Quotes: + if ( !parseOk ) { + d->error = XMLERR_ERRORPARSINGATTVALUE; + goto parseError; + } + // Done + return TRUE; + case -1: + // Error + d->error = XMLERR_UNEXPECTEDCHARACTER; + goto parseError; + } + + } + + return TRUE; + +parseError: + reportParseError(); + return FALSE; +} + +/*! + Parse a Name [5] and store the name in name or ref (if useRef is TRUE). +*/ +bool QXmlSimpleReader::parseName( bool useRef ) +{ + const signed char Init = 0; + const signed char Name1 = 1; // parse first signed character of the name + const signed char Name = 2; // parse name + const signed char Done = 3; + + const signed char InpNameBe = 0; // name beginning signed characters + const signed char InpNameCh = 1; // NameChar without InpNameBe + const signed char InpUnknown = 2; + + // use some kind of state machine for parsing + static const signed char table[3][3] = { + /* InpNameBe InpNameCh InpUnknown */ + { Name1, -1, -1 }, // Init + { Name, Name, Done }, // Name1 + { Name, Name, Done } // Name + }; + signed char state = Init; + signed char input; + + for (;;) { + + // get input + if ( atEnd() ) { + d->error = XMLERR_UNEXPECTEDEOF; + goto parseError; + } + if ( is_NameBeginning(c) ) { + input = InpNameBe; + } else if ( is_NameChar(c) ) { + input = InpNameCh; + } else { + input = InpUnknown; + } + + // set state according to input + state = table[state][input]; + + // do some actions according to state + switch ( state ) { + case Name1: + if ( useRef ) { + refClear(); + refAddC(); + } else { + nameClear(); + nameAddC(); + } + next(); + break; + case Name: + if ( useRef ) { + refAddC(); + } else { + nameAddC(); + } + next(); + break; + } + // no input is read after this + switch ( state ) { + case Done: + return TRUE; + case -1: + // Error + d->error = XMLERR_LETTEREXPECTED; + goto parseError; + } + + } + + return TRUE; + +parseError: + reportParseError(); + return FALSE; +} + +/*! + Parse a Nmtoken [7] and store the name in name. +*/ +bool QXmlSimpleReader::parseNmtoken() +{ + const signed char Init = 0; + const signed char NameF = 1; + const signed char Name = 2; + const signed char Done = 3; + + const signed char InpNameCh = 0; // NameChar without InpNameBe + const signed char InpUnknown = 1; + + // use some kind of state machine for parsing + static const signed char table[3][2] = { + /* InpNameCh InpUnknown */ + { NameF, -1 }, // Init + { Name, Done }, // NameF + { Name, Done } // Name + }; + signed char state = Init; + signed char input; + + for (;;) { + + // get input + if ( atEnd() ) { + d->error = XMLERR_UNEXPECTEDEOF; + goto parseError; + } + if ( is_NameChar(c) ) { + input = InpNameCh; + } else { + input = InpUnknown; + } + + // set state according to input + state = table[state][input]; + + // do some actions according to state + switch ( state ) { + case NameF: + nameClear(); + nameAddC(); + next(); + break; + case Name: + nameAddC(); + next(); + break; + } + // no input is read after this + switch ( state ) { + case Done: + return TRUE; + case -1: + // Error + d->error = XMLERR_LETTEREXPECTED; + goto parseError; + } + + } + + return TRUE; + +parseError: + reportParseError(); + return FALSE; +} + +/*! + Parse a Reference [67]. + + charDataRead is set to TRUE if the reference must not be parsed. The + character(s) which the reference mapped to are appended to string. The + head stands on the first character after the reference. + + charDataRead is set to FALSE if the reference must be parsed. The + charachter(s) which the reference mapped to are inserted at the reference + position. The head stands on the first character of the replacement). +*/ +bool QXmlSimpleReader::parseReference( bool &charDataRead, EntityRecognitionContext context ) +{ + // temporary variables + uint tmp; + bool ok; + + const signed char Init = 0; + const signed char SRef = 1; // start of a reference + const signed char ChRef = 2; // parse CharRef + const signed char ChDec = 3; // parse CharRef decimal + const signed char ChHexS = 4; // start CharRef hexadecimal + const signed char ChHex = 5; // parse CharRef hexadecimal + const signed char Name = 6; // parse name + const signed char DoneD = 7; // done CharRef decimal + const signed char DoneH = 8; // done CharRef hexadecimal + const signed char DoneN = 9; // done EntityRef + + const signed char InpAmp = 0; // & + const signed char InpSemi = 1; // ; + const signed char InpHash = 2; // # + const signed char InpX = 3; // x + const signed char InpNum = 4; // 0-9 + const signed char InpHex = 5; // a-f A-F + const signed char InpUnknown = 6; + + // use some kind of state machine for parsing + static const signed char table[8][7] = { + /* InpAmp InpSemi InpHash InpX InpNum InpHex InpUnknown */ + { SRef, -1, -1, -1, -1, -1, -1 }, // Init + { -1, -1, ChRef, Name, Name, Name, Name }, // SRef + { -1, -1, -1, ChHexS, ChDec, -1, -1 }, // ChRef + { -1, DoneD, -1, -1, ChDec, -1, -1 }, // ChDec + { -1, -1, -1, -1, ChHex, ChHex, -1 }, // ChHexS + { -1, DoneH, -1, -1, ChHex, ChHex, -1 }, // ChHex + { -1, DoneN, -1, -1, -1, -1, -1 } // Name + }; + signed char state = Init; + signed char input; + + for (;;) { + + // get input + if ( atEnd() ) { + d->error = XMLERR_UNEXPECTEDEOF; + goto parseError; + } + if ( c.row() ) { + input = InpUnknown; + } else if ( c.cell() == '&' ) { + input = InpAmp; + } else if ( c.cell() == ';' ) { + input = InpSemi; + } else if ( c.cell() == '#' ) { + input = InpHash; + } else if ( c.cell() == 'x' ) { + input = InpX; + } else if ( '0' <= c.cell() && c.cell() <= '9' ) { + input = InpNum; + } else if ( 'a' <= c.cell() && c.cell() <= 'f' ) { + input = InpHex; + } else if ( 'A' <= c.cell() && c.cell() <= 'F' ) { + input = InpHex; + } else { + input = InpUnknown; + } + + // set state according to input + state = table[state][input]; + + // do some actions according to state + switch ( state ) { + case SRef: + refClear(); + next(); + break; + case ChRef: + next(); + break; + case ChDec: + refAddC(); + next(); + break; + case ChHexS: + next(); + break; + case ChHex: + refAddC(); + next(); + break; + case Name: + // read the name into the ref + parseName( TRUE ); + break; + case DoneD: + tmp = ref().toUInt( &ok, 10 ); + if ( ok ) { + stringAddC( QChar(tmp) ); + } else { + d->error = XMLERR_ERRORPARSINGREFERENCE; + goto parseError; + } + charDataRead = TRUE; + next(); + break; + case DoneH: + tmp = ref().toUInt( &ok, 16 ); + if ( ok ) { + stringAddC( QChar(tmp) ); + } else { + d->error = XMLERR_ERRORPARSINGREFERENCE; + goto parseError; + } + charDataRead = TRUE; + next(); + break; + case DoneN: + if ( !processReference( charDataRead, context ) ) + goto parseError; + next(); + break; + } + // no input is read after this + switch ( state ) { + case DoneD: + return TRUE; + case DoneH: + return TRUE; + case DoneN: + return TRUE; + case -1: + // Error + d->error = XMLERR_ERRORPARSINGREFERENCE; + goto parseError; + } + + } + + return TRUE; + +parseError: + reportParseError(); + return FALSE; +} + +/*! + Helper function for parseReference() +*/ +bool QXmlSimpleReader::processReference( bool &charDataRead, EntityRecognitionContext context ) +{ + QString reference = ref(); + if ( reference == "amp" ) { + if ( context == InEntityValue ) { + // Bypassed + stringAddC( '&' ); stringAddC( 'a' ); stringAddC( 'm' ); stringAddC( 'p' ); stringAddC( ';' ); + } else { + // Included or Included in literal + stringAddC( '&' ); + } + charDataRead = TRUE; + } else if ( reference == "lt" ) { + if ( context == InEntityValue ) { + // Bypassed + stringAddC( '&' ); stringAddC( 'l' ); stringAddC( 't' ); stringAddC( ';' ); + } else { + // Included or Included in literal + stringAddC( '<' ); + } + charDataRead = TRUE; + } else if ( reference == "gt" ) { + if ( context == InEntityValue ) { + // Bypassed + stringAddC( '&' ); stringAddC( 'g' ); stringAddC( 't' ); stringAddC( ';' ); + } else { + // Included or Included in literal + stringAddC( '>' ); + } + charDataRead = TRUE; + } else if ( reference == "apos" ) { + if ( context == InEntityValue ) { + // Bypassed + stringAddC( '&' ); stringAddC( 'a' ); stringAddC( 'p' ); stringAddC( 'o' ); stringAddC( 's' ); stringAddC( ';' ); + } else { + // Included or Included in literal + stringAddC( '\'' ); + } + charDataRead = TRUE; + } else if ( reference == "quot" ) { + if ( context == InEntityValue ) { + // Bypassed + stringAddC( '&' ); stringAddC( 'q' ); stringAddC( 'u' ); stringAddC( 'o' ); stringAddC( 't' ); stringAddC( ';' ); + } else { + // Included or Included in literal + stringAddC( '"' ); + } + charDataRead = TRUE; + } else { + QMap::Iterator it; + it = d->entities.find( reference ); + if ( it != d->entities.end() ) { + // "Internal General" + switch ( context ) { + case InContent: + // Included + xmlRef = it.data() + xmlRef; + charDataRead = FALSE; + break; + case InAttributeValue: + // Included in literal + xmlRef = it.data().replace( QRegExp("\""), """ ).replace( QRegExp("'"), "'" ) + + xmlRef; + charDataRead = FALSE; + break; + case InEntityValue: + { + // Bypassed + stringAddC( '&' ); + for ( int i=0; i<(int)reference.length(); i++ ) { + stringAddC( reference[i] ); + } + stringAddC( ';'); + charDataRead = TRUE; + } + break; + case InDTD: + // Forbidden + d->error = XMLERR_INTERNALGENERALENTITYINDTD; + charDataRead = FALSE; + break; + } + } else { + QMap::Iterator itExtern; + itExtern = d->externEntities.find( reference ); + if ( itExtern == d->externEntities.end() ) { + // entity not declared + // ### check this case for conformance + if ( context == InEntityValue ) { + // Bypassed + stringAddC( '&' ); + for ( int i=0; i<(int)reference.length(); i++ ) { + stringAddC( reference[i] ); + } + stringAddC( ';'); + charDataRead = TRUE; + } else { + if ( contentHnd ) { + if ( !contentHnd->skippedEntity( reference ) ) { + d->error = contentHnd->errorString(); + return FALSE; // error + } + } + } + } else if ( (*itExtern).notation.isNull() ) { + // "External Parsed General" + switch ( context ) { + case InContent: + // Included if validating + if ( contentHnd ) { + if ( !contentHnd->skippedEntity( reference ) ) { + d->error = contentHnd->errorString(); + return FALSE; // error + } + } + charDataRead = FALSE; + break; + case InAttributeValue: + // Forbidden + d->error = XMLERR_EXTERNALGENERALENTITYINAV; + charDataRead = FALSE; + break; + case InEntityValue: + { + // Bypassed + stringAddC( '&' ); + for ( int i=0; i<(int)reference.length(); i++ ) { + stringAddC( reference[i] ); + } + stringAddC( ';'); + charDataRead = TRUE; + } + break; + case InDTD: + // Forbidden + d->error = XMLERR_EXTERNALGENERALENTITYINDTD; + charDataRead = FALSE; + break; + } + } else { + // "Unparsed" + // ### notify for "Occurs as Attribute Value" missing (but this is no refence, anyway) + // Forbidden + d->error = XMLERR_UNPARSEDENTITYREFERENCE; + charDataRead = FALSE; + return FALSE; // error + } + } + } + return TRUE; // no error +} + + +/*! + Parse over a simple string. + + After the string was successfully parsed, the head is on the first + character after the string. +*/ +bool QXmlSimpleReader::parseString( const QString& s ) +{ + signed char Done = s.length(); + + const signed char InpCharExpected = 0; // the character that was expected + const signed char InpUnknown = 1; + + signed char state = 0; // state in this function is the position in the string s + signed char input; + + for (;;) { + + // get input + if ( atEnd() ) { + d->error = XMLERR_UNEXPECTEDEOF; + goto parseError; + } + if ( c == s[(int)state] ) { + input = InpCharExpected; + } else { + input = InpUnknown; + } + + // set state according to input + if ( input == InpCharExpected ) { + state++; + } else { + // Error + d->error = XMLERR_UNEXPECTEDCHARACTER; + goto parseError; + } + + // do some actions according to state + next(); + // no input is read after this + if ( state == Done ) { + return TRUE; + } + + } + + return TRUE; + +parseError: + reportParseError(); + return FALSE; +} + + +/*! + Inits the data values. +*/ +void QXmlSimpleReader::init( const QXmlInputSource& i ) +{ + xml = i.data(); + xmlLength = xml.length(); + xmlRef = ""; + + d->externParameterEntities.clear(); + d->parameterEntities.clear(); + d->externEntities.clear(); + d->entities.clear(); + + tags.clear(); + + d->doctype = ""; + d->xmlVersion = ""; + d->encoding = ""; + d->standalone = QXmlSimpleReaderPrivate::Unknown; + + lineNr = 0; + columnNr = -1; + pos = 0; + next(); + d->error = XMLERR_OK; +} + +/*! + Returns TRUE if a entity with the name \a e exists, + otherwise returns FALSE. +*/ +bool QXmlSimpleReader::entityExist( const QString& e ) const +{ + if ( d->parameterEntities.find(e) == d->parameterEntities.end() && + d->externParameterEntities.find(e) == d->externParameterEntities.end() ) { + return FALSE; + } else { + return TRUE; + } +} + +void QXmlSimpleReader::reportParseError() +{ + if ( errorHnd ) + errorHnd->fatalError( QXmlParseException( d->error, columnNr+1, lineNr+1 ) ); +} + +//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 @@ +/**************************************************************************** +** $Id$ +** +** Definition of QXmlSimpleReader and related classes. +** +** Created : 000518 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the XML module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition licenses may use this +** file in accordance with the Qt Commercial License Agreement provided +** with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + + +/****************************************** + * DOM support is disabled in QT 2.3.7 for sharp zaurus. + * Because of that we copied the code from 2.3.7 into qtcompat and enabled it + * there. + * Copyright (c) 2004 Ulf Schenk + * + * $Id$ + ******************************************/ + +#ifndef QXML_H +#define QXML_H + +#include + +//US #if !defined(QT_MODULE_XML) +//US #define QM_EXPORT +//US #else +#define QM_EXPORT Q_EXPORT +//US #endif + +#ifndef QT_H +#include +#include +#include +#include +#include +#include +#endif // QT_H + +//US #ifndef QT_NO_XML + +class QXmlNamespaceSupport; +class QXmlAttributes; +class QXmlContentHandler; +class QXmlDefaultHandler; +class QXmlDTDHandler; +class QXmlEntityResolver; +class QXmlErrorHandler; +class QXmlLexicalHandler; +class QXmlDeclHandler; +class QXmlInputSource; +class QXmlLocator; +class QXmlNamespaceSupport; +class QXmlParseException; + +class QXmlReader; +class QXmlSimpleReader; + +class QXmlSimpleReaderPrivate; +class QXmlNamespaceSupportPrivate; +class QXmlAttributesPrivate; +class QXmlInputSourcePrivate; +class QXmlParseExceptionPrivate; +class QXmlLocatorPrivate; +class QXmlDefaultHandlerPrivate; + + +// +// SAX Namespace Support +// + +#if defined(Q_TEMPLATEDLL) +// MOC_SKIP_BEGIN +template class QM_EXPORT QMap; +template class QM_EXPORT QValueStack >; +template class QM_EXPORT QValueStack; +// MOC_SKIP_END +#endif + +class QM_EXPORT QXmlNamespaceSupport +{ +public: + QXmlNamespaceSupport(); + ~QXmlNamespaceSupport(); + + void setPrefix( const QString&, const QString& ); + + QString prefix( const QString& ) const; + QString uri( const QString& ) const; + void splitName( const QString&, QString&, QString& ) const; + void processName( const QString&, bool, QString&, QString& ) const; + QStringList prefixes() const; + QStringList prefixes( const QString& ) const; + + void pushContext(); + void popContext(); + void reset(); +private: + QValueStack > nsStack; + QMap ns; + + QXmlNamespaceSupportPrivate *d; +}; + + +// +// SAX Attributes +// + +class QM_EXPORT QXmlAttributes +{ +public: + QXmlAttributes() {} + virtual ~QXmlAttributes() {} + + int index( const QString& qName ) const; + int index( const QString& uri, const QString& localPart ) const; + int length() const; + QString localName( int index ) const; + QString qName( int index ) const; + QString uri( int index ) const; + QString type( int index ) const; + QString type( const QString& qName ) const; + QString type( const QString& uri, const QString& localName ) const; + QString value( int index ) const; + QString value( const QString& qName ) const; + QString value( const QString& uri, const QString& localName ) const; + +private: + QStringList qnameList; + QStringList uriList; + QStringList localnameList; + QStringList valueList; + + QXmlAttributesPrivate *d; + + friend class QXmlSimpleReader; +}; + +// +// SAX Input Source +// + +class QM_EXPORT QXmlInputSource +{ +public: + QXmlInputSource(); + QXmlInputSource( QTextStream& stream ); + QXmlInputSource( QFile& file ); + virtual ~QXmlInputSource(); + + virtual const QString& data() const; + virtual void setData( const QString& d ); + +private: + void readInput( QByteArray& rawData ); + + QString input; + + QXmlInputSourcePrivate *d; +}; + +// +// SAX Exception Classes +// + +class QM_EXPORT QXmlParseException +{ +public: + QXmlParseException( const QString& name="", int c=-1, int l=-1, const QString& p="", const QString& s="" ) + : msg( name ), column( c ), line( l ), pub( p ), sys( s ) + { } + + int columnNumber() const; + int lineNumber() const; + QString publicId() const; + QString systemId() const; + QString message() const; + +private: + QString msg; + int column; + int line; + QString pub; + QString sys; + + QXmlParseExceptionPrivate *d; +}; + + +// +// XML Reader +// + +class QM_EXPORT QXmlReader +{ +public: + virtual bool feature( const QString& name, bool *ok = 0 ) const = 0; + virtual void setFeature( const QString& name, bool value ) = 0; + virtual bool hasFeature( const QString& name ) const = 0; + virtual void* property( const QString& name, bool *ok = 0 ) const = 0; + virtual void setProperty( const QString& name, void* value ) = 0; + virtual bool hasProperty( const QString& name ) const = 0; + virtual void setEntityResolver( QXmlEntityResolver* handler ) = 0; + virtual QXmlEntityResolver* entityResolver() const = 0; + virtual void setDTDHandler( QXmlDTDHandler* handler ) = 0; + virtual QXmlDTDHandler* DTDHandler() const = 0; + virtual void setContentHandler( QXmlContentHandler* handler ) = 0; + virtual QXmlContentHandler* contentHandler() const = 0; + virtual void setErrorHandler( QXmlErrorHandler* handler ) = 0; + virtual QXmlErrorHandler* errorHandler() const = 0; + virtual void setLexicalHandler( QXmlLexicalHandler* handler ) = 0; + virtual QXmlLexicalHandler* lexicalHandler() const = 0; + virtual void setDeclHandler( QXmlDeclHandler* handler ) = 0; + virtual QXmlDeclHandler* declHandler() const = 0; + virtual bool parse( const QXmlInputSource& input ) = 0; +}; + +class QM_EXPORT QXmlSimpleReader : public QXmlReader +{ +public: + QXmlSimpleReader(); + virtual ~QXmlSimpleReader(); + + bool feature( const QString& name, bool *ok = 0 ) const; + void setFeature( const QString& name, bool value ); + bool hasFeature( const QString& name ) const; + + void* property( const QString& name, bool *ok = 0 ) const; + void setProperty( const QString& name, void* value ); + bool hasProperty( const QString& name ) const; + + void setEntityResolver( QXmlEntityResolver* handler ); + QXmlEntityResolver* entityResolver() const; + void setDTDHandler( QXmlDTDHandler* handler ); + QXmlDTDHandler* DTDHandler() const; + void setContentHandler( QXmlContentHandler* handler ); + QXmlContentHandler* contentHandler() const; + void setErrorHandler( QXmlErrorHandler* handler ); + QXmlErrorHandler* errorHandler() const; + void setLexicalHandler( QXmlLexicalHandler* handler ); + QXmlLexicalHandler* lexicalHandler() const; + void setDeclHandler( QXmlDeclHandler* handler ); + QXmlDeclHandler* declHandler() const; + + bool parse( const QXmlInputSource& input ); + +private: + // variables + QXmlContentHandler* contentHnd; + QXmlErrorHandler* errorHnd; + QXmlDTDHandler* dtdHnd; + QXmlEntityResolver* entityRes; + QXmlLexicalHandler* lexicalHnd; + QXmlDeclHandler* declHnd; + + QChar c; // the character at reading position + int lineNr; // number of line + int columnNr; // position in line + int pos; // position in string + + int namePos; + QChar nameArray[256]; // only used for names + QString nameValue; // only used for names + int refPos; + QChar refArray[256]; // only used for references + QString refValue; // only used for references + int stringPos; + QChar stringArray[256]; // used for any other strings that are parsed + QString stringValue; // used for any other strings that are parsed + + QString xml; + int xmlLength; + QString xmlRef; // used for parsing of entity references + + QValueStack tags; + + QXmlSimpleReaderPrivate* d; + + static const QChar QEOF; + + // inlines + virtual bool is_S( const QChar& ); + virtual bool is_Letter( const QChar& ); + virtual bool is_NameBeginning( const QChar& ); + virtual bool is_Digit( const QChar& ); + virtual bool is_CombiningChar( const QChar& ); + virtual bool is_Extender( const QChar& ); + virtual bool is_NameChar( const QChar& ); + + QString& string(); + void stringClear(); + void stringAddC(); + void stringAddC(const QChar&); + QString& name(); + void nameClear(); + void nameAddC(); + void nameAddC(const QChar&); + QString& ref(); + void refClear(); + void refAddC(); + void refAddC(const QChar&); + + // used by parseReference() and parsePEReference() + enum EntityRecognitionContext { InContent, InAttributeValue, InEntityValue, InDTD }; + + // private functions + void eat_ws(); + void next_eat_ws(); + + void next(); + bool atEnd(); + + void init( const QXmlInputSource& i ); + + bool entityExist( const QString& ) const; + + bool parseProlog(); + bool parseElement(); + bool parseElementEmptyTag( bool &t, QString &uri, QString &lname ); + bool parseElementETagBegin2(); + bool parseElementAttribute( QString &prefix, QString &uri, QString &lname ); + bool parseMisc(); + bool parseContent(); + + bool parsePI(bool xmldecl=FALSE); + bool parseDoctype(); + bool parseComment(); + + bool parseName( bool useRef=FALSE ); + bool parseNmtoken(); + bool parseAttribute(); + bool parseReference( bool &charDataRead, EntityRecognitionContext context ); + bool processReference( bool &charDataRead, EntityRecognitionContext context ); + + bool parseExternalID( bool allowPublicID = FALSE ); + bool parsePEReference( EntityRecognitionContext context ); + bool parseMarkupdecl(); + bool parseAttlistDecl(); + bool parseAttType(); + bool parseAttValue(); + bool parseElementDecl(); + bool parseNotationDecl(); + bool parseChoiceSeq(); + bool parseEntityDecl(); + bool parseEntityValue(); + + bool parseString( const QString& s ); + + void reportParseError(); + + friend class QXmlSimpleReaderPrivate; + friend class QXmlLocator; +}; + +// +// SAX Locator +// + +class QM_EXPORT QXmlLocator +{ +public: + QXmlLocator( QXmlSimpleReader* parent ) + { reader = parent; } + ~QXmlLocator() + { } + + int columnNumber(); + int lineNumber(); +// QString getPublicId() +// QString getSystemId() + +private: + QXmlSimpleReader* reader; + + QXmlLocatorPrivate *d; +}; + +// +// SAX handler classes +// + +class QM_EXPORT QXmlContentHandler +{ +public: + virtual void setDocumentLocator( QXmlLocator* locator ) = 0; + virtual bool startDocument() = 0; + virtual bool endDocument() = 0; + virtual bool startPrefixMapping( const QString& prefix, const QString& uri ) = 0; + virtual bool endPrefixMapping( const QString& prefix ) = 0; + virtual bool startElement( const QString& namespaceURI, const QString& localName, const QString& qName, const QXmlAttributes& atts ) = 0; + virtual bool endElement( const QString& namespaceURI, const QString& localName, const QString& qName ) = 0; + virtual bool characters( const QString& ch ) = 0; + virtual bool ignorableWhitespace( const QString& ch ) = 0; + virtual bool processingInstruction( const QString& target, const QString& data ) = 0; + virtual bool skippedEntity( const QString& name ) = 0; + virtual QString errorString() = 0; +}; + +class QM_EXPORT QXmlErrorHandler +{ +public: + virtual bool warning( const QXmlParseException& exception ) = 0; + virtual bool error( const QXmlParseException& exception ) = 0; + virtual bool fatalError( const QXmlParseException& exception ) = 0; + virtual QString errorString() = 0; +}; + +class QM_EXPORT QXmlDTDHandler +{ +public: + virtual bool notationDecl( const QString& name, const QString& publicId, const QString& systemId ) = 0; + virtual bool unparsedEntityDecl( const QString& name, const QString& publicId, const QString& systemId, const QString& notationName ) = 0; + virtual QString errorString() = 0; +}; + +class QM_EXPORT QXmlEntityResolver +{ +public: + virtual bool resolveEntity( const QString& publicId, const QString& systemId, QXmlInputSource* ret ) = 0; + virtual QString errorString() = 0; +}; + +class QM_EXPORT QXmlLexicalHandler +{ +public: + virtual bool startDTD( const QString& name, const QString& publicId, const QString& systemId ) = 0; + virtual bool endDTD() = 0; +// virtual bool startEntity( const QString& name ) = 0; +// virtual bool endEntity( const QString& name ) = 0; + virtual bool startCDATA() = 0; + virtual bool endCDATA() = 0; + virtual bool comment( const QString& ch ) = 0; + virtual QString errorString() = 0; +}; + +class QM_EXPORT QXmlDeclHandler +{ +public: + virtual bool attributeDecl( const QString& eName, const QString& aName, const QString& type, const QString& valueDefault, const QString& value ) = 0; + virtual bool internalEntityDecl( const QString& name, const QString& value ) = 0; + virtual bool externalEntityDecl( const QString& name, const QString& publicId, const QString& systemId ) = 0; + virtual QString errorString() = 0; +}; + + +class QM_EXPORT QXmlDefaultHandler : public QXmlContentHandler, public QXmlErrorHandler, public QXmlDTDHandler, public QXmlEntityResolver, public QXmlLexicalHandler, public QXmlDeclHandler +{ +public: + QXmlDefaultHandler() { } + virtual ~QXmlDefaultHandler() { } + + void setDocumentLocator( QXmlLocator* locator ); + bool startDocument(); + bool endDocument(); + bool startPrefixMapping( const QString& prefix, const QString& uri ); + bool endPrefixMapping( const QString& prefix ); + bool startElement( const QString& namespaceURI, const QString& localName, const QString& qName, const QXmlAttributes& atts ); + bool endElement( const QString& namespaceURI, const QString& localName, const QString& qName ); + bool characters( const QString& ch ); + bool ignorableWhitespace( const QString& ch ); + bool processingInstruction( const QString& target, const QString& data ); + bool skippedEntity( const QString& name ); + + bool warning( const QXmlParseException& exception ); + bool error( const QXmlParseException& exception ); + bool fatalError( const QXmlParseException& exception ); + + bool notationDecl( const QString& name, const QString& publicId, const QString& systemId ); + bool unparsedEntityDecl( const QString& name, const QString& publicId, const QString& systemId, const QString& notationName ); + + bool resolveEntity( const QString& publicId, const QString& systemId, QXmlInputSource* ret ); + + bool startDTD( const QString& name, const QString& publicId, const QString& systemId ); + bool endDTD(); +// bool startEntity( const QString& name ); +// bool endEntity( const QString& name ); + bool startCDATA(); + bool endCDATA(); + bool comment( const QString& ch ); + + bool attributeDecl( const QString& eName, const QString& aName, const QString& type, const QString& valueDefault, const QString& value ); + bool internalEntityDecl( const QString& name, const QString& value ); + bool externalEntityDecl( const QString& name, const QString& publicId, const QString& systemId ); + + QString errorString(); + +private: + QXmlDefaultHandlerPrivate *d; +}; + +#ifdef _WS_QWS_ +#ifdef QT_XML_CPP +#define inline +#else +#define QT_NO_XML_INLINE +#endif +#endif + +#ifndef QT_NO_XML_INLINE +// +// inlines +// + +inline bool QXmlSimpleReader::is_S(const QChar& ch) +{ return ch==' ' || ch=='\t' || ch=='\n' || ch=='\r'; } + +inline bool QXmlSimpleReader::is_Letter( const QChar& ch ) +{ return ch.isLetter(); } + +inline bool QXmlSimpleReader::is_NameBeginning( const QChar& ch ) +{ return ch=='_' || ch==':' || ch.isLetter(); } + +inline bool QXmlSimpleReader::is_Digit( const QChar& ch ) +{ return ch.isDigit(); } + +inline bool QXmlSimpleReader::is_CombiningChar( const QChar& ) +{ return FALSE; } + +inline bool QXmlSimpleReader::is_Extender( const QChar& ) +{ return FALSE; } + +inline bool QXmlSimpleReader::is_NameChar( const QChar& ch ) +{ + return ch=='.' || ch=='-' || ch=='_' || ch==':' || + is_Letter(ch) || is_Digit(ch) || + is_CombiningChar(ch) || is_Extender(ch); +} + +inline void QXmlSimpleReader::next() +{ + if ( !xmlRef.isEmpty() ) { + c = xmlRef[0]; + xmlRef.remove( 0, 1 ); + } else { + if ( c=='\n' || c=='\r' ) { + lineNr++; + columnNr = -1; + } + if ( pos >= xmlLength ) { + c = QEOF; + } else { + c = xml[pos]; + columnNr++; + pos++; + } + } +} + +inline bool QXmlSimpleReader::atEnd() +{ return c == QEOF; } + +inline void QXmlSimpleReader::eat_ws() +{ while ( !atEnd() && is_S(c) ) next(); } + +inline void QXmlSimpleReader::next_eat_ws() +{ next(); eat_ws(); } + + +// use buffers instead of QString::operator+= when single characters are read +inline QString& QXmlSimpleReader::string() +{ + stringValue += QString( stringArray, stringPos ); + stringPos = 0; + return stringValue; +} +inline QString& QXmlSimpleReader::name() +{ + nameValue += QString( nameArray, namePos ); + namePos = 0; + return nameValue; +} +inline QString& QXmlSimpleReader::ref() +{ + refValue += QString( refArray, refPos ); + refPos = 0; + return refValue; +} + +inline void QXmlSimpleReader::stringClear() +{ stringValue = ""; stringPos = 0; } +inline void QXmlSimpleReader::nameClear() +{ nameValue = ""; namePos = 0; } +inline void QXmlSimpleReader::refClear() +{ refValue = ""; refPos = 0; } + +inline void QXmlSimpleReader::stringAddC() +{ + if ( stringPos >= 256 ) { + stringValue += QString( stringArray, stringPos ); + stringPos = 0; + } + stringArray[stringPos++] = c; +} +inline void QXmlSimpleReader::nameAddC() +{ + if ( namePos >= 256 ) { + nameValue += QString( nameArray, namePos ); + namePos = 0; + } + nameArray[namePos++] = c; +} +inline void QXmlSimpleReader::refAddC() +{ + if ( refPos >= 256 ) { + refValue += QString( refArray, refPos ); + refPos = 0; + } + refArray[refPos++] = c; +} + +inline void QXmlSimpleReader::stringAddC(const QChar& ch) +{ + if ( stringPos >= 256 ) { + stringValue += QString( stringArray, stringPos ); + stringPos = 0; + } + stringArray[stringPos++] = ch; +} +inline void QXmlSimpleReader::nameAddC(const QChar& ch) +{ + if ( namePos >= 256 ) { + nameValue += QString( nameArray, namePos ); + namePos = 0; + } + nameArray[namePos++] = ch; +} +inline void QXmlSimpleReader::refAddC(const QChar& ch) +{ + if ( refPos >= 256 ) { + refValue += QString( refArray, refPos ); + refPos = 0; + } + refArray[refPos++] = ch; +} +#endif + +#ifdef _WS_QWS_ +#ifdef QT_XML_CPP +#undef inline +#endif +#endif + +//US #endif //QT_NO_XML + +#endif -- cgit v0.9.0.2