xmltree.cc
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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
00322
This file is part of the documentation for OPIE Version 1.1.