00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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
00323