Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

xmltree.cpp

Go to the documentation of this file.
00001 /*  This file is part of the KDE project
00002     Copyright (C) 2001 Simon Hausmann <hausmann@kde.org>
00003 
00004    This library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Library General Public
00006    License as published by the Free Software Foundation; either
00007    version 2 of the License, or (at your option) any later version.
00008 
00009    This library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Library General Public License for more details.
00013 
00014    You should have received a copy of the GNU Library General Public License
00015    along with this library; see the file COPYING.LIB.  If not, write to
00016    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00017    Boston, MA 02111-1307, USA.
00018 */
00019 
00020 #include "xmltree.h"
00021 
00022 #include <qpe/stringutil.h>
00023 
00024 #include <qxml.h>
00025 
00026 #include <assert.h>
00027 
00028 using namespace Opie::Core;
00029 
00030 XMLElement::XMLElement()
00031     : m_parent( 0 ), m_next( 0 ), m_prev( 0 ), m_first( 0 ), m_last( 0 )
00032 {
00033 }
00034 
00035 XMLElement::~XMLElement()
00036 {
00037     XMLElement *n = m_first;
00038 
00039     while ( n )
00040     {
00041         XMLElement *tmp = n;
00042         n = n->m_next;
00043         delete tmp;
00044     }
00045 }
00046 
00047 void XMLElement::appendChild( XMLElement *child )
00048 {
00049     if ( child->m_parent )
00050         child->m_parent->removeChild( child );
00051 
00052     child->m_parent = this;
00053 
00054     if ( m_last )
00055         m_last->m_next = child;
00056 
00057     child->m_prev = m_last;
00058 
00059     if ( !m_first )
00060         m_first = child;
00061 
00062     m_last = child;
00063 }
00064 
00065 void XMLElement::insertAfter( XMLElement *newChild, XMLElement *refChild )
00066 {
00067     assert( newChild != refChild );
00068 
00069     if ( refChild == m_last )
00070     {
00071         appendChild( newChild );
00072         return;
00073     }
00074 
00075     assert( refChild );
00076     assert( refChild->m_parent );
00077     assert( refChild->m_parent == this );
00078 
00079     if ( newChild->m_parent && newChild != refChild )
00080         newChild->m_parent->removeChild( newChild );
00081 
00082     newChild->m_parent = this;
00083 
00084     XMLElement *next = refChild->m_next;
00085 
00086     refChild->m_next = newChild;
00087 
00088     newChild->m_prev = refChild;
00089     newChild->m_next = next;
00090 
00091     if ( next )
00092         next->m_prev = newChild;
00093 }
00094 
00095 QString XMLElement::attribute( const QString &attr ) const
00096 {
00097     AttributeMap::ConstIterator it = m_attributes.find( attr );
00098     if ( it == m_attributes.end() )
00099     return QString::null;
00100     return it.data();
00101 }
00102 
00103 void XMLElement::setAttribute( const QString &attr, const QString &value )
00104 {
00105     m_attributes.replace( attr, value );
00106 }
00107 
00108 void XMLElement::insertBefore( XMLElement *newChild, XMLElement *refChild )
00109 {
00110     assert( refChild );
00111     assert( refChild->m_parent );
00112     assert( refChild->m_parent == this );
00113     assert( newChild != refChild );
00114 
00115     if ( newChild->m_parent && newChild != refChild )
00116         newChild->m_parent->removeChild( newChild );
00117 
00118     newChild->m_parent = this;
00119 
00120     XMLElement *prev = refChild->m_prev;
00121 
00122     refChild->m_prev = newChild;
00123 
00124     newChild->m_prev = prev;
00125     newChild->m_next = refChild;
00126 
00127     if ( prev )
00128         prev->m_next = newChild;
00129 
00130     if ( refChild == m_first )
00131         m_first = newChild;
00132 }
00133 
00134 void XMLElement::removeChild( XMLElement *child )
00135 {
00136     if ( child->m_parent != this )
00137         return;
00138 
00139     if ( m_first == child )
00140         m_first = child->m_next;
00141 
00142     if ( m_last == child )
00143         m_last = child->m_prev;
00144 
00145     if ( child->m_prev )
00146         child->m_prev->m_next = child->m_next;
00147 
00148     if ( child->m_next )
00149         child->m_next->m_prev = child->m_prev;
00150 
00151     child->m_parent = 0;
00152     child->m_prev = 0;
00153     child->m_next = 0;
00154 }
00155 
00156 void XMLElement::save( QTextStream &s, uint indent )
00157 {
00158     if ( !m_value.isEmpty() )
00159     {
00160         s << Qtopia::escapeString( m_value );
00161         return;
00162     }
00163 
00164     for ( uint i = 0; i < indent; ++i )
00165         s << " ";
00166 
00167     s << "<" << m_tag;
00168 
00169     if ( !m_attributes.isEmpty() )
00170     {
00171         s << " ";
00172         AttributeMap::ConstIterator it = m_attributes.begin();
00173         AttributeMap::ConstIterator end = m_attributes.end();
00174         for (; it != end; ++it )
00175         {
00176             s << it.key() << "=\"" << Qtopia::escapeString( it.data() ) << "\"";
00177             s << " ";
00178         }
00179     }
00180 
00181     if ( m_last )
00182     {
00183         if ( ( m_first && !m_first->value().isEmpty() ) || !m_parent )
00184             s << ">";
00185         else
00186             s << ">" << endl;
00187 
00188         int newIndent = indent;
00189         if ( m_parent )
00190             newIndent++;
00191 
00192         XMLElement *n = m_first;
00193         while ( n )
00194         {
00195             n->save( s, newIndent );
00196             n = n->nextChild();
00197         }
00198 
00199         if ( m_last && m_last->value().isEmpty() && m_parent )
00200             for ( uint i = 0; i < indent; ++i )
00201                 s << " ";
00202 
00203         if ( m_parent )
00204             s << "</" << m_tag << ">" << endl;
00205     }
00206     else
00207         s << "/>" << endl;
00208 }
00209 
00210 class Handler : public QXmlDefaultHandler
00211 {
00212 public:
00213     Handler() : m_node( 0 ), m_root( 0 ) {}
00214 
00215     XMLElement *root() const { return m_root; }
00216 
00217     virtual bool startDocument();
00218     virtual bool endDocument();
00219     virtual bool startElement( const QString &ns, const QString &ln, const QString &qName,
00220                                const QXmlAttributes &attr );
00221     virtual bool endElement( const QString &ns, const QString &ln, const QString &qName );
00222     virtual bool characters( const QString &ch );
00223 
00224 private:
00225     XMLElement *m_node;
00226     XMLElement *m_root;
00227 };
00228 
00229 bool Handler::startDocument()
00230 {
00231     m_root = m_node = new XMLElement;
00232 
00233     return true;
00234 }
00235 
00236 bool Handler::endDocument()
00237 {
00238     return m_root == m_node;
00239 }
00240 
00241 bool Handler::startElement( const QString &, const QString &, const QString &qName,
00242                            const QXmlAttributes &attr )
00243 {
00244     XMLElement *bm = new XMLElement;
00245 
00246     XMLElement::AttributeMap attributes;
00247     for ( int i = 0; i < attr.length(); ++i )
00248         attributes[ attr.qName( i ) ] = attr.value( i );
00249 
00250     bm->setAttributes( attributes );
00251 
00252     bm->setTagName( qName );
00253 
00254     m_node->appendChild( bm );
00255     m_node = bm;
00256 
00257     return true;
00258 }
00259 
00260 bool Handler::endElement( const QString &, const QString &, const QString & )
00261 {
00262     if ( m_node == m_root )
00263         return false;
00264 
00265     m_node = m_node->parent();
00266     return true;
00267 }
00268 
00269 bool Handler::characters( const QString &ch )
00270 {
00271     XMLElement *textNode = new XMLElement;
00272     textNode->setValue( ch );
00273     m_node->appendChild( textNode );
00274     return true;
00275 }
00276 
00277 XMLElement *XMLElement::namedItem( const QString &name )
00278 {
00279     XMLElement *e = m_first;
00280 
00281     for (; e; e = e->nextChild() )
00282         if ( e->tagName() == name )
00283             return e;
00284 
00285     return 0;
00286 }
00287 
00288 XMLElement *XMLElement::clone() const
00289 {
00290     XMLElement *res = new XMLElement;
00291 
00292     res->setTagName( m_tag );
00293     res->setValue( m_value );
00294     res->setAttributes( m_attributes );
00295 
00296     XMLElement *e = m_first;
00297     for (; e; e = e->m_next )
00298         res->appendChild( e->clone() );
00299 
00300     return res;
00301 }
00302 
00303 XMLElement *XMLElement::load( const QString &fileName )
00304 {
00305     QFile f( fileName );
00306     if ( !f.open( IO_ReadOnly ) )
00307         return 0;
00308 
00309     QTextStream stream( &f );
00310     stream.setEncoding( QTextStream::UnicodeUTF8 );
00311     QXmlInputSource src( stream );
00312     QXmlSimpleReader reader;
00313     Handler handler;
00314 
00315     reader.setFeature( "http://trolltech.com/xml/features/report-whitespace-only-CharData", false );
00316     reader.setContentHandler( &handler );
00317     reader.parse( src );
00318 
00319     return handler.root();;
00320 }
00321 
00322 /* vim: et sw=4
00323  */

Generated on Sat Nov 5 16:16:10 2005 for OPIE by  doxygen 1.4.2