SVN checkout 11/12/2010
[monav:monav.git] / plugins / osmimporter / xmlreader.h
1 /*
2 Copyright 2010  Christian Vetter veaac.fdirct@gmail.com
3
4 This file is part of MoNav.
5
6 MoNav is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 MoNav is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with MoNav.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #ifndef XMLREADER_H
21 #define XMLREADER_H
22
23 #include "ientityreader.h"
24 #include "bz2input.h"
25 #include <libxml/xmlreader.h>
26 #include <QHash>
27
28 class XMLReader: public IEntityReader {
29
30 public:
31
32         XMLReader()
33         {
34         }
35
36         virtual bool open( QString filename )
37         {
38                 if ( filename.endsWith( ".bz2" ) )
39                         m_inputReader = getBz2Reader( filename.toUtf8().constData() );
40                 else
41                         m_inputReader = xmlNewTextReaderFilename( filename.toUtf8().constData() );
42
43                 if ( m_inputReader == NULL ) {
44                         qCritical() << "failed to open XML reader";
45                         return false;
46                 }
47
48                 return true;
49         }
50
51         virtual ~XMLReader()
52         {
53                 if ( m_inputReader != NULL )
54                         xmlFreeTextReader( m_inputReader );
55         }
56
57         virtual void setNodeTags( QStringList tags )
58         {
59                 for ( int i = 0; i < tags.size(); i++ )
60                         m_nodeTags.insert( tags[i], i );
61         }
62
63         virtual void setWayTags( QStringList tags )
64         {
65                 for ( int i = 0; i < tags.size(); i++ )
66                         m_wayTags.insert( tags[i], i );
67         }
68
69         virtual void setRelationTags( QStringList tags )
70         {
71                 for ( int i = 0; i < tags.size(); i++ )
72                         m_relationTags.insert( tags[i], i );
73         }
74
75         virtual EntityType getEntitiy( Node* node, Way* way, Relation* relation )
76         {
77                 assert( node != NULL );
78                 assert( way != NULL );
79                 assert( relation != NULL );
80
81                 while ( xmlTextReaderRead( m_inputReader ) == 1 ) {
82                         const int type = xmlTextReaderNodeType( m_inputReader );
83
84                         if ( type != 1 ) // 1 is Element
85                                 continue;
86
87                         xmlChar* currentName = xmlTextReaderName( m_inputReader );
88                         if ( currentName == NULL )
89                                 continue;
90
91                         if ( xmlStrEqual( currentName, ( const xmlChar* ) "node" ) == 1 ) {
92                                 readNode( node );
93                                 xmlFree( currentName );
94                                 return EntityNode;
95                         }
96
97                         if ( xmlStrEqual( currentName, ( const xmlChar* ) "way" ) == 1 ) {
98                                 readWay( way );
99                                 xmlFree( currentName );
100                                 return EntityWay;
101                         }
102
103                         if ( xmlStrEqual( currentName, ( const xmlChar* ) "relation" ) == 1 ) {
104                                 readRelation( relation );
105                                 xmlFree( currentName );
106                                 return EntityRelation;
107                         }
108
109                         xmlFree( currentName );
110                 }
111
112                 return EntityNone;
113         }
114
115 protected:
116
117         void readNode( Node* node )
118         {
119                 node->tags.clear();
120                 xmlChar* attribute = xmlTextReaderGetAttribute( m_inputReader, ( const xmlChar* ) "id" );
121                 if ( attribute != NULL ) {
122                         node->id =  atoi( ( const char* ) attribute );
123                         xmlFree( attribute );
124                 }
125                 attribute = xmlTextReaderGetAttribute( m_inputReader, ( const xmlChar* ) "lat" );
126                 if ( attribute != NULL ) {
127                         node->coordinate.latitude =  atof( ( const char* ) attribute );
128                         xmlFree( attribute );
129                 }
130                 attribute = xmlTextReaderGetAttribute( m_inputReader, ( const xmlChar* ) "lon" );
131                 if ( attribute != NULL ) {
132                         node->coordinate.longitude =  atof( ( const char* ) attribute );
133                         xmlFree( attribute );
134                 }
135
136                 if ( xmlTextReaderIsEmptyElement( m_inputReader ) != 1 ) {
137                         const int depth = xmlTextReaderDepth( m_inputReader );
138
139                         while ( xmlTextReaderRead( m_inputReader ) == 1 ) {
140                                 const int childType = xmlTextReaderNodeType( m_inputReader );
141
142                                 if ( childType != 1 && childType != 15 ) // element begin / end
143                                         continue;
144
145                                 const int childDepth = xmlTextReaderDepth( m_inputReader );
146                                 xmlChar* childName = xmlTextReaderName( m_inputReader );
147
148                                 if ( childName == NULL )
149                                         continue;
150
151                                 if ( depth == childDepth && childType == 15 && xmlStrEqual( childName, ( const xmlChar* ) "node" ) == 1 ) {
152                                         xmlFree( childName );
153                                         break;
154                                 }
155
156                                 if ( childType != 1 ) {
157                                         xmlFree( childName );
158                                         continue;
159                                 }
160
161                                 if ( xmlStrEqual( childName, ( const xmlChar* ) "tag" ) == 1 ) {
162                                         xmlChar* key = xmlTextReaderGetAttribute( m_inputReader, ( const xmlChar* ) "k" );
163                                         xmlChar* value = xmlTextReaderGetAttribute( m_inputReader, ( const xmlChar* ) "v" );
164
165                                         if ( key != NULL && value != NULL ) {
166                                                 int tagID = m_nodeTags.value( QString( ( const char* ) key ), -1 );
167                                                 if ( tagID != -1 ) {
168                                                         Tag tag;
169                                                         tag.key = tagID;
170                                                         tag.value = QString::fromUtf8( ( const char* ) value );
171                                                         node->tags.push_back( tag );
172                                                 }
173                                         }
174
175                                         if ( key != NULL )
176                                                 xmlFree( key );
177                                         if ( value != NULL )
178                                                 xmlFree( value );
179                                 }
180
181                                 xmlFree( childName );
182                         }
183                 }
184         }
185
186         void readWay( Way* way )
187         {
188                 way->tags.clear();
189                 way->nodes.clear();
190
191                 xmlChar* attribute = xmlTextReaderGetAttribute( m_inputReader, ( const xmlChar* ) "id" );
192                 if ( attribute != NULL ) {
193                         way->id =  atoi( ( const char* ) attribute );
194                         xmlFree( attribute );
195                 }
196
197                 if ( xmlTextReaderIsEmptyElement( m_inputReader ) != 1 ) {
198                         const int depth = xmlTextReaderDepth( m_inputReader );
199
200                         while ( xmlTextReaderRead( m_inputReader ) == 1 ) {
201                                 const int childType = xmlTextReaderNodeType( m_inputReader );
202
203                                 if ( childType != 1 && childType != 15 ) // element begin / end
204                                         continue;
205
206                                 const int childDepth = xmlTextReaderDepth( m_inputReader );
207                                 xmlChar* childName = xmlTextReaderName( m_inputReader );
208
209                                 if ( childName == NULL )
210                                         continue;
211
212                                 if ( depth == childDepth && childType == 15 && xmlStrEqual( childName, ( const xmlChar* ) "way" ) == 1 ) {
213                                         xmlFree( childName );
214                                         break;
215                                 }
216
217                                 if ( childType != 1 ) {
218                                         xmlFree( childName );
219                                         continue;
220                                 }
221
222                                 if ( xmlStrEqual( childName, ( const xmlChar* ) "tag" ) == 1 ) {
223                                         xmlChar* key = xmlTextReaderGetAttribute( m_inputReader, ( const xmlChar* ) "k" );
224                                         xmlChar* value = xmlTextReaderGetAttribute( m_inputReader, ( const xmlChar* ) "v" );
225
226                                         if ( key != NULL && value != NULL ) {
227                                                 int tagID = m_wayTags.value( QString( ( const char* ) key ), -1 );
228                                                 if ( tagID != -1 ) {
229                                                         Tag tag;
230                                                         tag.key = tagID;
231                                                         tag.value = QString::fromUtf8( ( const char* ) value );
232                                                         way->tags.push_back( tag );
233                                                 }
234                                         }
235
236                                         if ( key != NULL )
237                                                 xmlFree( key );
238                                         if ( value != NULL )
239                                                 xmlFree( value );
240                                 } else if ( xmlStrEqual( childName, ( const xmlChar* ) "nd" ) == 1 ) {
241                                         xmlChar* ref = xmlTextReaderGetAttribute( m_inputReader, ( const xmlChar* ) "ref" );
242                                         if ( ref != NULL ) {
243                                                 way->nodes.push_back( atoi( ( const char* ) ref ) );
244                                                 xmlFree( ref );
245                                         }
246                                 }
247
248                                 xmlFree( childName );
249                         }
250                 }
251         }
252
253         void readRelation( Relation* relation )
254         {
255                 relation->tags.clear();
256
257                 xmlChar* attribute = xmlTextReaderGetAttribute( m_inputReader, ( const xmlChar* ) "id" );
258                 if ( attribute != NULL ) {
259                         relation->id =  atoi( ( const char* ) attribute );
260                         xmlFree( attribute );
261                 }
262
263                 if ( xmlTextReaderIsEmptyElement( m_inputReader ) != 1 ) {
264                         const int depth = xmlTextReaderDepth( m_inputReader );
265
266                         while ( xmlTextReaderRead( m_inputReader ) == 1 ) {
267                                 const int childType = xmlTextReaderNodeType( m_inputReader );
268
269                                 if ( childType != 1 && childType != 15 ) // element begin / end
270                                         continue;
271
272                                 const int childDepth = xmlTextReaderDepth( m_inputReader );
273                                 xmlChar* childName = xmlTextReaderName( m_inputReader );
274
275                                 if ( childName == NULL )
276                                         continue;
277
278                                 if ( depth == childDepth && childType == 15 && xmlStrEqual( childName, ( const xmlChar* ) "node" ) == 1 ) {
279                                         xmlFree( childName );
280                                         break;
281                                 }
282
283                                 if ( childType != 1 ) {
284                                         xmlFree( childName );
285                                         continue;
286                                 }
287
288                                 if ( xmlStrEqual( childName, ( const xmlChar* ) "tag" ) == 1 ) {
289                                         xmlChar* key = xmlTextReaderGetAttribute( m_inputReader, ( const xmlChar* ) "k" );
290                                         xmlChar* value = xmlTextReaderGetAttribute( m_inputReader, ( const xmlChar* ) "v" );
291
292                                         if ( key != NULL && value != NULL ) {
293                                                 int tagID = m_relationTags.value( QString( ( const char* ) key ), -1 );
294                                                 if ( tagID != -1 ) {
295                                                         Tag tag;
296                                                         tag.key = tagID;
297                                                         tag.value = QString::fromUtf8( ( const char* ) value );
298                                                         relation->tags.push_back( tag );
299                                                 }
300                                         }
301
302                                         if ( key != NULL )
303                                                 xmlFree( key );
304                                         if ( value != NULL )
305                                                 xmlFree( value );
306                                 } else if ( xmlStrEqual( childName, ( const xmlChar* ) "member" ) == 1 ) {
307                                         xmlChar* type = xmlTextReaderGetAttribute( m_inputReader, ( const xmlChar* ) "type" );
308                                         xmlChar* ref = xmlTextReaderGetAttribute( m_inputReader, ( const xmlChar* ) "ref" );
309                                         xmlChar* role = xmlTextReaderGetAttribute( m_inputReader, ( const xmlChar* ) "role" );
310
311                                         if ( type != NULL && ref != NULL && role != NULL ) {
312                                                 RelationMember member;
313                                                 bool validType = false;
314                                                 if ( xmlStrEqual( type, ( const xmlChar* ) "node" ) == 1 ) {
315                                                         member.type = RelationMember::Node;
316                                                         validType = true;
317                                                 } else if ( xmlStrEqual( type, ( const xmlChar* ) "way" ) == 1 ) {
318                                                         member.type = RelationMember::Way;
319                                                         validType = true;
320                                                 } else if ( xmlStrEqual( type, ( const xmlChar* ) "relation" ) == 1 ) {
321                                                         member.type = RelationMember::Relation;
322                                                         validType = true;
323                                                 }
324
325                                                 if ( validType ) {
326                                                         member.ref = atoi( ( const char* ) ref );
327                                                         member.role = QString::fromUtf8( ( const char* ) role );
328                                                         relation->members.push_back( member );
329                                                 }
330                                         }
331
332                                         if ( type != NULL )
333                                                 xmlFree( type );
334                                         if ( ref != NULL )
335                                                 xmlFree( ref );
336                                         if ( role != NULL )
337                                                 xmlFree( role );
338                                 }
339
340                                 xmlFree( childName );
341                         }
342                 }
343         }
344
345         xmlTextReaderPtr m_inputReader;
346         QHash< QString, int > m_nodeTags;
347         QHash< QString, int > m_wayTags;
348         QHash< QString, int > m_relationTags;
349 };
350
351 #endif // XMLREADER_H