summaryrefslogtreecommitdiff
path: root/libopie/xmltree.cc
Unidiff
Diffstat (limited to 'libopie/xmltree.cc') (more/less context) (ignore whitespace changes)
-rw-r--r--libopie/xmltree.cc42
1 files changed, 17 insertions, 25 deletions
diff --git a/libopie/xmltree.cc b/libopie/xmltree.cc
index d5ce74a..3d03cc6 100644
--- a/libopie/xmltree.cc
+++ b/libopie/xmltree.cc
@@ -1,326 +1,318 @@
1/* This file is part of the KDE project 1/* This file is part of the KDE project
2 Copyright (C) 2001 Simon Hausmann <hausmann@kde.org> 2 Copyright (C) 2001 Simon Hausmann <hausmann@kde.org>
3 3
4 This library is free software; you can redistribute it and/or 4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public 5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either 6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version. 7 version 2 of the License, or (at your option) any later version.
8 8
9 This library is distributed in the hope that it will be useful, 9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of 10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details. 12 Library General Public License for more details.
13 13
14 You should have received a copy of the GNU Library General Public License 14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to 15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 16 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 Boston, MA 02111-1307, USA. 17 Boston, MA 02111-1307, USA.
18*/ 18*/
19 19
20 20#include <qpe/stringutil.h>
21#include <opie/xmltree.h> 21#include <opie/xmltree.h>
22 22
23#include <qxml.h> 23#include <qxml.h>
24 24
25#include <assert.h> 25#include <assert.h>
26 26
27namespace
28{
29
30/**
31 Encode an attribute value upon saving.
32 replaces '"' with "&quot"
33 replaces '<' with "&lt"
34 replaces '&' with "&amp"
35 replaces '>' with "&gt"
36*/
37QString encodeAttr( const QString& str )
38{
39 QString encAttr( str ); // cause of the const parameter
40 encAttr = encAttr.replace( QRegExp( "[<]" ), "&lt" );
41 encAttr = encAttr.replace( QRegExp( "[>]" ), "&gt" );
42 encAttr = encAttr.replace( QRegExp( "[\"]" ), "&quot" );
43 encAttr = encAttr.replace( QRegExp( "[&]" ), "&amp" );
44 return encAttr;
45}
46
47}
48 27
49XMLElement::XMLElement() 28XMLElement::XMLElement()
50 : m_parent( 0 ), m_next( 0 ), m_prev( 0 ), m_first( 0 ), m_last( 0 ) 29 : m_parent( 0 ), m_next( 0 ), m_prev( 0 ), m_first( 0 ), m_last( 0 )
51{ 30{
52} 31}
53 32
54XMLElement::~XMLElement() 33XMLElement::~XMLElement()
55{ 34{
56 XMLElement *n = m_first; 35 XMLElement *n = m_first;
57 36
58 while ( n ) 37 while ( n )
59 { 38 {
60 XMLElement *tmp = n; 39 XMLElement *tmp = n;
61 n = n->m_next; 40 n = n->m_next;
62 delete tmp; 41 delete tmp;
63 } 42 }
64} 43}
65 44
66void XMLElement::appendChild( XMLElement *child ) 45void XMLElement::appendChild( XMLElement *child )
67{ 46{
68 if ( child->m_parent ) 47 if ( child->m_parent )
69 child->m_parent->removeChild( child ); 48 child->m_parent->removeChild( child );
70 49
71 child->m_parent = this; 50 child->m_parent = this;
72 51
73 if ( m_last ) 52 if ( m_last )
74 m_last->m_next = child; 53 m_last->m_next = child;
75 54
76 child->m_prev = m_last; 55 child->m_prev = m_last;
77 56
78 if ( !m_first ) 57 if ( !m_first )
79 m_first = child; 58 m_first = child;
80 59
81 m_last = child; 60 m_last = child;
82} 61}
83 62
84void XMLElement::insertAfter( XMLElement *newChild, XMLElement *refChild ) 63void XMLElement::insertAfter( XMLElement *newChild, XMLElement *refChild )
85{ 64{
86 assert( newChild != refChild ); 65 assert( newChild != refChild );
87 66
88 if ( refChild == m_last ) 67 if ( refChild == m_last )
89 { 68 {
90 appendChild( newChild ); 69 appendChild( newChild );
91 return; 70 return;
92 } 71 }
93 72
94 assert( refChild ); 73 assert( refChild );
95 assert( refChild->m_parent ); 74 assert( refChild->m_parent );
96 assert( refChild->m_parent == this ); 75 assert( refChild->m_parent == this );
97 76
98 if ( newChild->m_parent && newChild != refChild ) 77 if ( newChild->m_parent && newChild != refChild )
99 newChild->m_parent->removeChild( newChild ); 78 newChild->m_parent->removeChild( newChild );
100 79
101 newChild->m_parent = this; 80 newChild->m_parent = this;
102 81
103 XMLElement *next = refChild->m_next; 82 XMLElement *next = refChild->m_next;
104 83
105 refChild->m_next = newChild; 84 refChild->m_next = newChild;
106 85
107 newChild->m_prev = refChild; 86 newChild->m_prev = refChild;
108 newChild->m_next = next; 87 newChild->m_next = next;
109 88
110 if ( next ) 89 if ( next )
111 next->m_prev = newChild; 90 next->m_prev = newChild;
112} 91}
113 92QString XMLElement::attribute(const QString &attr )const
93{
94 if ( !m_attributes.contains( attr ) )
95 return QString::null;
96 AttributeMap::ConstIterator it = m_attributes.find( attr );
97 return it.data();
98}
99void XMLElement::setAttribute(const QString &attr, const QString &value )
100{
101 m_attributes.remove( attr );
102 m_attributes.insert( attr, value );
103}
114void XMLElement::insertBefore( XMLElement *newChild, XMLElement *refChild ) 104void XMLElement::insertBefore( XMLElement *newChild, XMLElement *refChild )
115{ 105{
116 assert( refChild ); 106 assert( refChild );
117 assert( refChild->m_parent ); 107 assert( refChild->m_parent );
118 assert( refChild->m_parent == this ); 108 assert( refChild->m_parent == this );
119 assert( newChild != refChild ); 109 assert( newChild != refChild );
120 110
121 if ( newChild->m_parent && newChild != refChild ) 111 if ( newChild->m_parent && newChild != refChild )
122 newChild->m_parent->removeChild( newChild ); 112 newChild->m_parent->removeChild( newChild );
123 113
124 newChild->m_parent = this; 114 newChild->m_parent = this;
125 115
126 XMLElement *prev = refChild->m_prev; 116 XMLElement *prev = refChild->m_prev;
127 117
128 refChild->m_prev = newChild; 118 refChild->m_prev = newChild;
129 119
130 newChild->m_prev = prev; 120 newChild->m_prev = prev;
131 newChild->m_next = refChild; 121 newChild->m_next = refChild;
132 122
133 if ( prev ) 123 if ( prev )
134 prev->m_next = newChild; 124 prev->m_next = newChild;
135 125
136 if ( refChild == m_first ) 126 if ( refChild == m_first )
137 m_first = newChild; 127 m_first = newChild;
138} 128}
139 129
140void XMLElement::removeChild( XMLElement *child ) 130void XMLElement::removeChild( XMLElement *child )
141{ 131{
142 if ( child->m_parent != this ) 132 if ( child->m_parent != this )
143 return; 133 return;
144 134
145 if ( m_first == child ) 135 if ( m_first == child )
146 m_first = child->m_next; 136 m_first = child->m_next;
147 137
148 if ( m_last == child ) 138 if ( m_last == child )
149 m_last = child->m_prev; 139 m_last = child->m_prev;
150 140
151 if ( child->m_prev ) 141 if ( child->m_prev )
152 child->m_prev->m_next = child->m_next; 142 child->m_prev->m_next = child->m_next;
153 143
154 if ( child->m_next ) 144 if ( child->m_next )
155 child->m_next->m_prev = child->m_prev; 145 child->m_next->m_prev = child->m_prev;
156 146
157 child->m_parent = 0; 147 child->m_parent = 0;
158 child->m_prev = 0; 148 child->m_prev = 0;
159 child->m_next = 0; 149 child->m_next = 0;
160} 150}
161 151
162void XMLElement::save( QTextStream &s, uint indent ) 152void XMLElement::save( QTextStream &s, uint indent )
163{ 153{
164 if ( !m_value.isEmpty() ) 154 if ( !m_value.isEmpty() )
165 { 155 {
166 s << encodeAttr( m_value ); 156 s << Qtopia::escapeString( m_value );
167 return; 157 return;
168 } 158 }
169 159
170 for ( uint i = 0; i < indent; ++i ) 160 for ( uint i = 0; i < indent; ++i )
171 s << " "; 161 s << " ";
172 162
173 s << "<" << m_tag; 163 s << "<" << m_tag;
174 164
175 if ( !m_attributes.isEmpty() ) 165 if ( !m_attributes.isEmpty() )
176 { 166 {
177 s << " "; 167 s << " ";
178 AttributeMap::ConstIterator it = m_attributes.begin(); 168 AttributeMap::ConstIterator it = m_attributes.begin();
179 AttributeMap::ConstIterator end = m_attributes.end(); 169 AttributeMap::ConstIterator end = m_attributes.end();
180 for (; it != end; ++it ) 170 for (; it != end; ++it )
181 { 171 {
182 s << it.key() << "=\"" << encodeAttr( it.data() ) << "\""; 172 s << it.key() << "=\"" << Qtopia::escapeString( it.data() ) << "\"";
183 s << " "; 173 s << " ";
184 } 174 }
185 } 175 }
186 176
187 if ( m_last ) 177 if ( m_last )
188 { 178 {
189 if ( ( m_first && !m_first->value().isEmpty() ) || !m_parent ) 179 if ( ( m_first && !m_first->value().isEmpty() ) || !m_parent )
190 s << ">"; 180 s << ">";
191 else 181 else
192 s << ">" << endl; 182 s << ">" << endl;
193 183
194 int newIndent = indent; 184 int newIndent = indent;
195 if ( m_parent ) 185 if ( m_parent )
196 newIndent++; 186 newIndent++;
197 187
198 XMLElement *n = m_first; 188 XMLElement *n = m_first;
199 while ( n ) 189 while ( n )
200 { 190 {
201 n->save( s, newIndent ); 191 n->save( s, newIndent );
202 n = n->nextChild(); 192 n = n->nextChild();
203 } 193 }
204 194
205 if ( m_last && m_last->value().isEmpty() && m_parent ) 195 if ( m_last && m_last->value().isEmpty() && m_parent )
206 for ( uint i = 0; i < indent; ++i ) 196 for ( uint i = 0; i < indent; ++i )
207 s << " "; 197 s << " ";
208 198
209 if ( m_parent ) 199 if ( m_parent )
210 s << "</" << m_tag << ">" << endl; 200 s << "</" << m_tag << ">" << endl;
211 } 201 }
212 else 202 else
213 s << "/>" << endl; 203 s << "/>" << endl;
214} 204}
215 205
216class Handler : public QXmlDefaultHandler 206class Handler : public QXmlDefaultHandler
217{ 207{
218public: 208public:
219 Handler() : m_node( 0 ), m_root( 0 ) {} 209 Handler() : m_node( 0 ), m_root( 0 ) {}
220 210
221 XMLElement *root() const { return m_root; } 211 XMLElement *root() const { return m_root; }
222 212
223 virtual bool startDocument(); 213 virtual bool startDocument();
224 virtual bool endDocument(); 214 virtual bool endDocument();
225 virtual bool startElement( const QString &ns, const QString &ln, const QString &qName, 215 virtual bool startElement( const QString &ns, const QString &ln, const QString &qName,
226 const QXmlAttributes &attr ); 216 const QXmlAttributes &attr );
227 virtual bool endElement( const QString &ns, const QString &ln, const QString &qName ); 217 virtual bool endElement( const QString &ns, const QString &ln, const QString &qName );
228 virtual bool characters( const QString &ch ); 218 virtual bool characters( const QString &ch );
229 219
230private: 220private:
231 XMLElement *m_node; 221 XMLElement *m_node;
232 XMLElement *m_root; 222 XMLElement *m_root;
233}; 223};
234 224
235bool Handler::startDocument() 225bool Handler::startDocument()
236{ 226{
237 m_root = m_node = new XMLElement; 227 m_root = m_node = new XMLElement;
238 228
239 return true; 229 return true;
240} 230}
241 231
242bool Handler::endDocument() 232bool Handler::endDocument()
243{ 233{
244 return m_root == m_node; 234 return m_root == m_node;
245} 235}
246 236
247bool Handler::startElement( const QString &, const QString &, const QString &qName, 237bool Handler::startElement( const QString &, const QString &, const QString &qName,
248 const QXmlAttributes &attr ) 238 const QXmlAttributes &attr )
249{ 239{
250 XMLElement *bm = new XMLElement; 240 XMLElement *bm = new XMLElement;
251 241
252 XMLElement::AttributeMap attributes; 242 XMLElement::AttributeMap attributes;
253 for ( int i = 0; i < attr.length(); ++i ) 243 for ( int i = 0; i < attr.length(); ++i )
254 attributes[ attr.qName( i ) ] = attr.value( i ); 244 attributes[ attr.qName( i ) ] = attr.value( i );
255 245
256 bm->setAttributes( attributes ); 246 bm->setAttributes( attributes );
257 247
258 bm->setTagName( qName ); 248 bm->setTagName( qName );
259 249
260 m_node->appendChild( bm ); 250 m_node->appendChild( bm );
261 m_node = bm; 251 m_node = bm;
262 252
263 return true; 253 return true;
264} 254}
265 255
266bool Handler::endElement( const QString &, const QString &, const QString & ) 256bool Handler::endElement( const QString &, const QString &, const QString & )
267{ 257{
268 if ( m_node == m_root ) 258 if ( m_node == m_root )
269 return false; 259 return false;
270 260
271 m_node = m_node->parent(); 261 m_node = m_node->parent();
272 return true; 262 return true;
273} 263}
274 264
275bool Handler::characters( const QString &ch ) 265bool Handler::characters( const QString &ch )
276{ 266{
277 XMLElement *textNode = new XMLElement; 267 XMLElement *textNode = new XMLElement;
278 textNode->setValue( ch ); 268 textNode->setValue( ch );
279 m_node->appendChild( textNode ); 269 m_node->appendChild( textNode );
280 return true; 270 return true;
281} 271}
282 272
283XMLElement *XMLElement::namedItem( const QString &name ) 273XMLElement *XMLElement::namedItem( const QString &name )
284{ 274{
285 XMLElement *e = m_first; 275 XMLElement *e = m_first;
286 276
287 for (; e; e = e->nextChild() ) 277 for (; e; e = e->nextChild() )
288 if ( e->tagName() == name ) 278 if ( e->tagName() == name )
289 return e; 279 return e;
290 280
291 return 0; 281 return 0;
292} 282}
293 283
294XMLElement *XMLElement::clone() const 284XMLElement *XMLElement::clone() const
295{ 285{
296 XMLElement *res = new XMLElement; 286 XMLElement *res = new XMLElement;
297 287
298 res->setTagName( m_tag ); 288 res->setTagName( m_tag );
299 res->setValue( m_value ); 289 res->setValue( m_value );
300 res->setAttributes( m_attributes ); 290 res->setAttributes( m_attributes );
301 291
302 XMLElement *e = m_first; 292 XMLElement *e = m_first;
303 for (; e; e = e->m_next ) 293 for (; e; e = e->m_next )
304 res->appendChild( e->clone() ); 294 res->appendChild( e->clone() );
305 295
306 return res; 296 return res;
307} 297}
308 298
309XMLElement *XMLElement::load( const QString &fileName ) 299XMLElement *XMLElement::load( const QString &fileName )
310{ 300{
311 QFile f( fileName ); 301 QFile f( fileName );
312 if ( !f.open( IO_ReadOnly ) ) 302 if ( !f.open( IO_ReadOnly ) )
313 return 0; 303 return 0;
314 304
315 QTextStream stream( &f ); 305 QTextStream stream( &f );
316 stream.setEncoding( QTextStream::UnicodeUTF8 ); 306 stream.setEncoding( QTextStream::UnicodeUTF8 );
317 QXmlInputSource src( stream ); 307 QXmlInputSource src( stream );
318 QXmlSimpleReader reader; 308 QXmlSimpleReader reader;
319 Handler handler; 309 Handler handler;
320 310
321 reader.setFeature( "http://trolltech.com/xml/features/report-whitespace-only-CharData", false ); 311 reader.setFeature( "http://trolltech.com/xml/features/report-whitespace-only-CharData", false );
322 reader.setContentHandler( &handler ); 312 reader.setContentHandler( &handler );
323 reader.parse( src ); 313 reader.parse( src );
324 314
325 return handler.root();; 315 return handler.root();;
326} 316}
317
318