libopie API Documentation

xmltree.cc

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 <qpe/stringutil.h>
00021 #include <opie/xmltree.h>
00022 
00023 #include <qxml.h>
00024 
00025 #include <assert.h>
00026 
00027 using namespace Opie;
00028 
00029 XMLElement::XMLElement()
00030     : m_parent( 0 ), m_next( 0 ), m_prev( 0 ), m_first( 0 ), m_last( 0 )
00031 {
00032 }
00033 
00034 XMLElement::~XMLElement()
00035 {
00036     XMLElement *n = m_first;
00037 
00038     while ( n )
00039     {
00040         XMLElement *tmp = n;
00041         n = n->m_next;
00042         delete tmp;
00043     }
00044 }
00045 
00046 void XMLElement::appendChild( XMLElement *child )
00047 {
00048     if ( child->m_parent )
00049         child->m_parent->removeChild( child );
00050 
00051     child->m_parent = this;
00052 
00053     if ( m_last )
00054         m_last->m_next = child;
00055 
00056     child->m_prev = m_last;
00057 
00058     if ( !m_first )
00059         m_first = child;
00060 
00061     m_last = child;
00062 }
00063 
00064 void XMLElement::insertAfter( XMLElement *newChild, XMLElement *refChild )
00065 {
00066     assert( newChild != refChild );
00067 
00068     if ( refChild == m_last )
00069     {
00070         appendChild( newChild );
00071         return;
00072     }
00073 
00074     assert( refChild );
00075     assert( refChild->m_parent );
00076     assert( refChild->m_parent == this );
00077 
00078     if ( newChild->m_parent && newChild != refChild )
00079         newChild->m_parent->removeChild( newChild );
00080 
00081     newChild->m_parent = this;
00082 
00083     XMLElement *next = refChild->m_next;
00084 
00085     refChild->m_next = newChild;
00086 
00087     newChild->m_prev = refChild;
00088     newChild->m_next = next;
00089    
00090     if ( next )
00091         next->m_prev = newChild;
00092 }
00093 
00094 QString XMLElement::attribute( const QString &attr ) const
00095 {
00096     AttributeMap::ConstIterator it = m_attributes.find( attr );
00097     if ( it == m_attributes.end() )
00098     return QString::null;
00099     return it.data();
00100 }
00101 
00102 void XMLElement::setAttribute( const QString &attr, const QString &value )
00103 {
00104     m_attributes.replace( attr, value );
00105 }
00106 
00107 void XMLElement::insertBefore( XMLElement *newChild, XMLElement *refChild )
00108 {
00109     assert( refChild );
00110     assert( refChild->m_parent );
00111     assert( refChild->m_parent == this );
00112     assert( newChild != refChild );
00113 
00114     if ( newChild->m_parent && newChild != refChild )
00115         newChild->m_parent->removeChild( newChild );
00116 
00117     newChild->m_parent = this;
00118 
00119     XMLElement *prev = refChild->m_prev;
00120 
00121     refChild->m_prev = newChild;
00122     
00123     newChild->m_prev = prev;
00124     newChild->m_next = refChild;
00125 
00126     if ( prev )
00127         prev->m_next = newChild;
00128 
00129     if ( refChild == m_first )
00130         m_first = newChild;
00131 }
00132 
00133 void XMLElement::removeChild( XMLElement *child )
00134 {
00135     if ( child->m_parent != this )
00136         return;
00137 
00138     if ( m_first == child )
00139         m_first = child->m_next;
00140 
00141     if ( m_last == child )
00142         m_last = child->m_prev;
00143 
00144     if ( child->m_prev )
00145         child->m_prev->m_next = child->m_next;
00146 
00147     if ( child->m_next )
00148         child->m_next->m_prev = child->m_prev;
00149 
00150     child->m_parent = 0;
00151     child->m_prev = 0;
00152     child->m_next = 0;
00153 }
00154 
00155 void XMLElement::save( QTextStream &s, uint indent )
00156 {
00157     if ( !m_value.isEmpty() )
00158     {
00159         s << Qtopia::escapeString( m_value );
00160         return;
00161     }
00162 
00163     for ( uint i = 0; i < indent; ++i )
00164         s << " ";
00165 
00166     s << "<" << m_tag;
00167 
00168     if ( !m_attributes.isEmpty() )
00169     {
00170         s << " ";
00171         AttributeMap::ConstIterator it = m_attributes.begin();
00172         AttributeMap::ConstIterator end = m_attributes.end();
00173         for (; it != end; ++it )
00174         {
00175             s << it.key() << "=\"" << Qtopia::escapeString( it.data() ) << "\"";
00176             s << " ";
00177         }
00178     }
00179 
00180     if ( m_last )
00181     {
00182         if ( ( m_first && !m_first->value().isEmpty() ) || !m_parent )
00183             s << ">";
00184         else
00185             s << ">" << endl;
00186 
00187         int newIndent = indent;
00188         if ( m_parent )
00189             newIndent++;
00190 
00191         XMLElement *n = m_first;
00192         while ( n )
00193         {
00194             n->save( s, newIndent );
00195             n = n->nextChild();
00196         }
00197 
00198         if ( m_last && m_last->value().isEmpty() && m_parent )
00199             for ( uint i = 0; i < indent; ++i )
00200                 s << " ";
00201 
00202         if ( m_parent )
00203             s << "</" << m_tag << ">" << endl;
00204     }
00205     else
00206         s << "/>" << endl;
00207 }
00208 
00209 class Handler : public QXmlDefaultHandler
00210 {
00211 public:
00212     Handler() : m_node( 0 ), m_root( 0 ) {}
00213 
00214     XMLElement *root() const { return m_root; }
00215 
00216     virtual bool startDocument();
00217     virtual bool endDocument();
00218     virtual bool startElement( const QString &ns, const QString &ln, const QString &qName,
00219                                const QXmlAttributes &attr );
00220     virtual bool endElement( const QString &ns, const QString &ln, const QString &qName );
00221     virtual bool characters( const QString &ch );
00222 
00223 private:
00224     XMLElement *m_node;
00225     XMLElement *m_root;
00226 };
00227 
00228 bool Handler::startDocument()
00229 {
00230     m_root = m_node = new XMLElement;
00231 
00232     return true;
00233 }
00234 
00235 bool Handler::endDocument()
00236 {
00237     return m_root == m_node;
00238 }
00239 
00240 bool Handler::startElement( const QString &, const QString &, const QString &qName,
00241                            const QXmlAttributes &attr )
00242 {
00243     XMLElement *bm = new XMLElement;
00244 
00245     XMLElement::AttributeMap attributes;
00246     for ( int i = 0; i < attr.length(); ++i )
00247         attributes[ attr.qName( i ) ] = attr.value( i );
00248 
00249     bm->setAttributes( attributes );
00250 
00251     bm->setTagName( qName );
00252 
00253     m_node->appendChild( bm );
00254     m_node = bm;
00255 
00256     return true;
00257 }
00258 
00259 bool Handler::endElement( const QString &, const QString &, const QString & )
00260 {
00261     if ( m_node == m_root )
00262         return false;
00263 
00264     m_node = m_node->parent();
00265     return true;
00266 }
00267 
00268 bool Handler::characters( const QString &ch )
00269 {
00270     XMLElement *textNode = new XMLElement;
00271     textNode->setValue( ch );
00272     m_node->appendChild( textNode );
00273     return true;
00274 }
00275 
00276 XMLElement *XMLElement::namedItem( const QString &name )
00277 {
00278     XMLElement *e = m_first;
00279 
00280     for (; e; e = e->nextChild() )
00281         if ( e->tagName() == name )
00282             return e;
00283 
00284     return 0; 
00285 }
00286 
00287 XMLElement *XMLElement::clone() const
00288 {
00289     XMLElement *res = new XMLElement;
00290 
00291     res->setTagName( m_tag );
00292     res->setValue( m_value );
00293     res->setAttributes( m_attributes );
00294 
00295     XMLElement *e = m_first;
00296     for (; e; e = e->m_next )
00297         res->appendChild( e->clone() );
00298 
00299     return res;
00300 }
00301 
00302 XMLElement *XMLElement::load( const QString &fileName )
00303 {
00304     QFile f( fileName );
00305     if ( !f.open( IO_ReadOnly ) )
00306         return 0;
00307 
00308     QTextStream stream( &f );
00309     stream.setEncoding( QTextStream::UnicodeUTF8 );
00310     QXmlInputSource src( stream );
00311     QXmlSimpleReader reader;
00312     Handler handler;
00313 
00314     reader.setFeature( "http://trolltech.com/xml/features/report-whitespace-only-CharData", false );
00315     reader.setContentHandler( &handler );
00316     reader.parse( src );
00317 
00318     return handler.root();;
00319 }
00320 
00321 /* vim: et sw=4
00322  */
KDE Logo
This file is part of the documentation for OPIE Version 1.1.
Documentation copyright © 1997-2003 the KDE developers. 2003 OPIE developers
Generated on Tue Feb 10 20:24:46 2004 by doxygen 1.3.5 written by Dimitri van Heesch, © 1997-2001