Check out the latest version of Routino: svn co http://routino.org/svn/trunk routino
Contents of /trunk/src/osmparser.c
Parent Directory
|
Revision Log
Revision 293 -
(show annotations)
(download)
(as text)
Mon Oct 26 19:04:40 2009 UTC (15 years, 4 months ago) by amb
File MIME type: text/x-csrc
File size: 18747 byte(s)
Mon Oct 26 19:04:40 2009 UTC (15 years, 4 months ago) by amb
File MIME type: text/x-csrc
File size: 18747 byte(s)
Remove the Bridleway and Footway highway types and use the Path type instead (also re-ordered the types so that Cycleway comes before Path).
1 | /*************************************** |
2 | $Header: /home/amb/CVS/routino/src/osmparser.c,v 1.52 2009-10-26 19:04:40 amb Exp $ |
3 | |
4 | OSM XML file parser (either JOSM or planet) |
5 | |
6 | Part of the Routino routing software. |
7 | ******************/ /****************** |
8 | This file Copyright 2008,2009 Andrew M. Bishop |
9 | |
10 | This program is free software: you can redistribute it and/or modify |
11 | it under the terms of the GNU Affero General Public License as published by |
12 | the Free Software Foundation, either version 3 of the License, or |
13 | (at your option) any later version. |
14 | |
15 | This program is distributed in the hope that it will be useful, |
16 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
18 | GNU Affero General Public License for more details. |
19 | |
20 | You should have received a copy of the GNU Affero General Public License |
21 | along with this program. If not, see <http://www.gnu.org/licenses/>. |
22 | ***************************************/ |
23 | |
24 | |
25 | #include <stdio.h> |
26 | #include <stdlib.h> |
27 | #include <string.h> |
28 | #include <ctype.h> |
29 | |
30 | #include "typesx.h" |
31 | #include "functionsx.h" |
32 | #include "nodesx.h" |
33 | #include "segmentsx.h" |
34 | #include "waysx.h" |
35 | #include "ways.h" |
36 | |
37 | |
38 | /*+ The length of the buffer and the size increment for reading lines from the file. +*/ |
39 | #define BUFFSIZE 256 |
40 | |
41 | /* Local functions */ |
42 | |
43 | static char *fgets_realloc(char *buffer,FILE *file); |
44 | |
45 | |
46 | /*++++++++++++++++++++++++++++++++++++++ |
47 | Parse an OSM XML file (from JOSM or planet download). |
48 | |
49 | int ParseXML Returns 0 if OK or something else in case of an error. |
50 | |
51 | FILE *file The file to read from. |
52 | |
53 | NodesX *OSMNodes The array of nodes to fill in. |
54 | |
55 | SegmentsX *OSMSegments The array of segments to fill in. |
56 | |
57 | WaysX *OSMWays The arrray of ways to fill in. |
58 | |
59 | Profile *profile A profile of the allowed transport types and included/excluded highway types. |
60 | ++++++++++++++++++++++++++++++++++++++*/ |
61 | |
62 | int ParseXML(FILE *file,NodesX *OSMNodes,SegmentsX *OSMSegments,WaysX *OSMWays,Profile *profile) |
63 | { |
64 | char *line=NULL; |
65 | long nlines=0; |
66 | long nnodes=0,nways=0,nrelations=0; |
67 | int isnode=0,isway=0,isrelation=0; |
68 | way_t way_id=0; |
69 | int way_oneway=0,way_roundabout=0; |
70 | speed_t way_maxspeed=0; |
71 | weight_t way_maxweight=0; |
72 | height_t way_maxheight=0; |
73 | width_t way_maxwidth=0; |
74 | length_t way_maxlength=0; |
75 | char *way_highway=NULL,*way_name=NULL,*way_ref=NULL; |
76 | wayallow_t way_allow_no=0,way_allow_yes=0; |
77 | node_t *way_nodes=NULL; |
78 | int way_nnodes=0,way_nalloc=0; |
79 | |
80 | printf("\rReading: Lines=0 Nodes=0 Ways=0 Relations=0"); |
81 | fflush(stdout); |
82 | |
83 | /* Parse the file */ |
84 | |
85 | while((line=fgets_realloc(line,file))) |
86 | { |
87 | char *l=line,*m; |
88 | |
89 | nlines++; |
90 | |
91 | while(isspace(*l)) |
92 | l++; |
93 | |
94 | if(!strncmp(l,"<node",5)) /* The start of a node */ |
95 | { |
96 | node_t id; |
97 | double latitude,longitude; |
98 | |
99 | nnodes++; |
100 | |
101 | isnode=1; isway=0; isrelation=0; |
102 | |
103 | m=strstr(l,"id="); m+=4; if(*m=='"' || *m=='\'') m++; id=atoll(m); |
104 | m=strstr(l,"lat="); m+=5; if(*m=='"' || *m=='\'') m++; latitude=degrees_to_radians(atof(m)); |
105 | m=strstr(l,"lon="); m+=4; if(*m=='"' || *m=='\'') m++; longitude=degrees_to_radians(atof(m)); |
106 | |
107 | AppendNode(OSMNodes,id,latitude,longitude); |
108 | |
109 | if(strstr(l,"/>")) /* The end of a node */ |
110 | { |
111 | isnode=0; isway=0; isrelation=0; |
112 | } |
113 | } |
114 | else if(!strncmp(l,"</node",6)) /* The end of a node */ |
115 | { |
116 | isnode=0; isway=0; isrelation=0; |
117 | } |
118 | else if(!strncmp(l,"<way",4)) /* The start of a way */ |
119 | { |
120 | nways++; |
121 | |
122 | isnode=0; isway=1; isrelation=0; |
123 | |
124 | m=strstr(l,"id="); m+=4; if(*m=='"' || *m=='\'') m++; way_id=atoll(m); |
125 | |
126 | way_oneway=0; way_roundabout=0; |
127 | way_maxspeed=0; way_maxweight=0; way_maxheight=0; way_maxwidth=0; |
128 | way_maxlength=0; |
129 | way_highway=NULL; way_name=NULL; way_ref=NULL; |
130 | way_allow_no=0; way_allow_yes=0; |
131 | way_nnodes=0; |
132 | } |
133 | else if(!strncmp(l,"</way",5)) /* The end of a way */ |
134 | { |
135 | isnode=0; isway=0; isrelation=0; |
136 | |
137 | if(way_highway) |
138 | { |
139 | waytype_t type; |
140 | wayallow_t allow; |
141 | |
142 | type=HighwayType(way_highway); |
143 | |
144 | switch(type) |
145 | { |
146 | case Way_Motorway: |
147 | allow=Allow_Motorbike|Allow_Motorcar|Allow_PSV|Allow_Goods|Allow_HGV; |
148 | break; |
149 | case Way_Trunk: |
150 | allow=Allow_Bicycle|Allow_Motorbike|Allow_Motorcar|Allow_PSV|Allow_Goods|Allow_HGV; |
151 | break; |
152 | case Way_Primary: |
153 | allow=Allow_Foot|Allow_Bicycle|Allow_Horse|Allow_Motorbike|Allow_Motorcar|Allow_PSV|Allow_Goods|Allow_HGV; |
154 | break; |
155 | case Way_Secondary: |
156 | allow=Allow_Foot|Allow_Bicycle|Allow_Horse|Allow_Motorbike|Allow_Motorcar|Allow_PSV|Allow_Goods|Allow_HGV; |
157 | break; |
158 | case Way_Tertiary: |
159 | allow=Allow_Foot|Allow_Bicycle|Allow_Horse|Allow_Motorbike|Allow_Motorcar|Allow_PSV|Allow_Goods|Allow_HGV; |
160 | break; |
161 | case Way_Unclassified: |
162 | allow=Allow_Foot|Allow_Bicycle|Allow_Horse|Allow_Motorbike|Allow_Motorcar|Allow_PSV|Allow_Goods|Allow_HGV; |
163 | break; |
164 | case Way_Residential: |
165 | allow=Allow_Foot|Allow_Bicycle|Allow_Horse|Allow_Motorbike|Allow_Motorcar|Allow_PSV|Allow_Goods|Allow_HGV; |
166 | break; |
167 | case Way_Service: |
168 | allow=Allow_Foot|Allow_Bicycle|Allow_Horse|Allow_Motorbike|Allow_Motorcar|Allow_PSV|Allow_Goods|Allow_HGV; |
169 | break; |
170 | case Way_Track: |
171 | allow=Allow_Foot|Allow_Bicycle|Allow_Horse; |
172 | break; |
173 | case Way_Cycleway: |
174 | allow=Allow_Foot|Allow_Bicycle; |
175 | break; |
176 | case Way_Path: |
177 | if(!strcmp(way_highway,"bridleway")) |
178 | allow=Allow_Foot|Allow_Bicycle|Allow_Horse; /* Special case for UK "bridleway". */ |
179 | else |
180 | allow=Allow_Foot; /* Only allow bicycle and horse if so indicated. */ |
181 | break; |
182 | default: |
183 | allow=0; |
184 | break; |
185 | } |
186 | |
187 | if(way_allow_no) /* Remove the ones explicitly denied (e.g. private) */ |
188 | allow&=~way_allow_no; |
189 | |
190 | if(way_allow_yes) /* Add the ones explicitly allowed (e.g. footpath along private) */ |
191 | allow|=way_allow_yes; |
192 | |
193 | if(allow&profile->allow && profile->highway[HIGHWAY(type)]) |
194 | { |
195 | Way way={0}; |
196 | char *refname; |
197 | int i; |
198 | |
199 | if(way_ref && way_name) |
200 | { |
201 | refname=(char*)malloc(strlen(way_ref)+strlen(way_name)+4); |
202 | sprintf(refname,"%s (%s)",way_name,way_ref); |
203 | } |
204 | else if(way_ref && !way_name && way_roundabout) |
205 | { |
206 | refname=(char*)malloc(strlen(way_ref)+14); |
207 | sprintf(refname,"%s (roundabout)",way_ref); |
208 | } |
209 | else if(way_ref && !way_name) |
210 | refname=way_ref; |
211 | else if(!way_ref && way_name) |
212 | refname=way_name; |
213 | else if(way_roundabout) |
214 | { |
215 | refname=(char*)malloc(strlen(way_highway)+14); |
216 | sprintf(refname,"%s (roundabout)",way_highway); |
217 | } |
218 | else /* if(!way_ref && !way_name && !way_roundabout) */ |
219 | refname=way_highway; |
220 | |
221 | way.speed=way_maxspeed; |
222 | way.weight=way_maxweight; |
223 | way.height=way_maxheight; |
224 | way.width=way_maxwidth; |
225 | way.length=way_maxlength; |
226 | |
227 | way.type=type; |
228 | |
229 | way.allow=allow; |
230 | |
231 | if(way_oneway) |
232 | way.type|=Way_OneWay; |
233 | |
234 | if(way_roundabout) |
235 | way.type|=Way_Roundabout; |
236 | |
237 | AppendWay(OSMWays,way_id,&way,refname); |
238 | |
239 | if(refname!=way_ref && refname!=way_name && refname!=way_highway) |
240 | free(refname); |
241 | |
242 | for(i=1;i<way_nnodes;i++) |
243 | { |
244 | node_t from=way_nodes[i-1]; |
245 | node_t to =way_nodes[i]; |
246 | |
247 | if(way_oneway>0) |
248 | { |
249 | AppendSegment(OSMSegments,way_id,from,to,ONEWAY_1TO2); |
250 | AppendSegment(OSMSegments,way_id,to,from,ONEWAY_2TO1); |
251 | } |
252 | else if(way_oneway<0) |
253 | { |
254 | AppendSegment(OSMSegments,way_id,from,to,ONEWAY_2TO1); |
255 | AppendSegment(OSMSegments,way_id,to,from,ONEWAY_1TO2); |
256 | } |
257 | else |
258 | { |
259 | AppendSegment(OSMSegments,way_id,from,to,0); |
260 | AppendSegment(OSMSegments,way_id,to,from,0); |
261 | } |
262 | } |
263 | } |
264 | } |
265 | |
266 | if(way_highway) free(way_highway); |
267 | if(way_name) free(way_name); |
268 | if(way_ref) free(way_ref); |
269 | } |
270 | else if(!strncmp(l,"<relation",9)) /* The start of a relation */ |
271 | { |
272 | nrelations++; |
273 | |
274 | isnode=0; isway=0; isrelation=1; |
275 | } |
276 | else if(!strncmp(l,"</relation",10)) /* The end of a relation */ |
277 | { |
278 | isnode=0; isway=0; isrelation=0; |
279 | } |
280 | else if(isnode) /* The middle of a node */ |
281 | { |
282 | } |
283 | else if(isway) /* The middle of a way */ |
284 | { |
285 | node_t id; |
286 | |
287 | if(!strncmp(l,"<nd",3)) /* The start of a node specifier */ |
288 | { |
289 | m=strstr(l,"ref="); m+=4; if(*m=='"' || *m=='\'') m++; id=atoll(m); |
290 | |
291 | if(way_nnodes==way_nalloc) |
292 | way_nodes=(node_t*)realloc((void*)way_nodes,(way_nalloc+=256)*sizeof(node_t)); |
293 | |
294 | way_nodes[way_nnodes++]=id; |
295 | } |
296 | |
297 | if(!strncmp(l,"<tag",4)) /* The start of a tag specifier */ |
298 | { |
299 | char delimiter,*k="",*v=""; |
300 | |
301 | m=strstr(l,"k="); m+=2; delimiter=*m; m++; k=m; |
302 | while(*m!=delimiter) m++; *m=0; l=m+1; |
303 | |
304 | m=strstr(l,"v="); m+=2; delimiter=*m; m++; v=m; |
305 | while(*m!=delimiter) m++; *m=0; |
306 | |
307 | switch(*k) |
308 | { |
309 | case 'a': |
310 | if(!strcmp(k,"access")) |
311 | { |
312 | if(!strcmp(v,"true") || !strcmp(v,"yes") || !strcmp(v,"1") || !strcmp(v,"permissive") || !strcmp(v,"designated")) |
313 | ; |
314 | else |
315 | way_allow_no=~0; |
316 | } |
317 | break; |
318 | |
319 | case 'b': |
320 | if(!strcmp(k,"bicycle")) |
321 | { |
322 | if(!strcmp(v,"true") || !strcmp(v,"yes") || !strcmp(v,"1") || !strcmp(v,"permissive") || !strcmp(v,"designated")) |
323 | way_allow_yes|=Allow_Bicycle; |
324 | else |
325 | way_allow_no|=Allow_Bicycle; |
326 | } |
327 | break; |
328 | |
329 | case 'f': |
330 | if(!strcmp(k,"foot")) |
331 | { |
332 | if(!strcmp(v,"true") || !strcmp(v,"yes") || !strcmp(v,"1") || !strcmp(v,"permissive") || !strcmp(v,"designated")) |
333 | way_allow_yes|=Allow_Foot; |
334 | else |
335 | way_allow_no|=Allow_Foot; |
336 | } |
337 | break; |
338 | |
339 | case 'g': |
340 | if(!strcmp(k,"goods")) |
341 | { |
342 | if(!strcmp(v,"true") || !strcmp(v,"yes") || !strcmp(v,"1") || !strcmp(v,"permissive") || !strcmp(v,"designated")) |
343 | way_allow_yes|=Allow_Goods; |
344 | else |
345 | way_allow_no|=Allow_Goods; |
346 | } |
347 | break; |
348 | |
349 | case 'h': |
350 | if(!strcmp(k,"highway")) |
351 | { |
352 | if(!strncmp(v,"motorway",8)) way_oneway=1; |
353 | |
354 | way_highway=strcpy((char*)malloc(strlen(v)+1),v); |
355 | } |
356 | if(!strcmp(k,"horse")) |
357 | { |
358 | if(!strcmp(v,"true") || !strcmp(v,"yes") || !strcmp(v,"1") || !strcmp(v,"permissive") || !strcmp(v,"designated")) |
359 | way_allow_yes|=Allow_Horse; |
360 | else |
361 | way_allow_no|=Allow_Horse; |
362 | } |
363 | if(!strcmp(k,"hgv")) |
364 | { |
365 | if(!strcmp(v,"true") || !strcmp(v,"yes") || !strcmp(v,"1") || !strcmp(v,"permissive") || !strcmp(v,"designated")) |
366 | way_allow_yes|=Allow_HGV; |
367 | else |
368 | way_allow_no|=Allow_HGV; |
369 | } |
370 | break; |
371 | |
372 | case 'j': |
373 | if(!strcmp(k,"junction")) |
374 | if(!strcmp(v,"roundabout")) |
375 | {way_oneway=1; way_roundabout=1;} |
376 | break; |
377 | |
378 | case 'm': |
379 | if(!strcmp(k,"maxspeed")) |
380 | { |
381 | if(strstr(v,"mph")) |
382 | way_maxspeed=kph_to_speed(1.609*atof(v)); |
383 | else |
384 | way_maxspeed=kph_to_speed(atof(v)); |
385 | } |
386 | if(!strcmp(k,"maxspeed:mph")) |
387 | way_maxspeed=kph_to_speed(1.609*atof(v)); |
388 | if(!strcmp(k,"maxweight")) |
389 | { |
390 | if(strstr(v,"kg")) |
391 | way_maxweight=tonnes_to_weight(atof(v)/1000); |
392 | else |
393 | way_maxweight=tonnes_to_weight(atof(v)); |
394 | } |
395 | if(!strcmp(k,"maxheight")) |
396 | { |
397 | if(strchr(v,'\'')) |
398 | { |
399 | int feet,inches; |
400 | |
401 | if(sscanf(v,"%d'%d\"",&feet,&inches)==2) |
402 | way_maxheight=metres_to_height((feet+(double)inches/12.0)*0.254); |
403 | else if(sscanf(v,"%d'",&feet)==1) |
404 | way_maxheight=metres_to_height((feet+(double)inches/12.0)*0.254); |
405 | } |
406 | else if(strstr(v,"ft") || strstr(v,"feet")) |
407 | way_maxheight=metres_to_height(atof(v)*0.254); |
408 | else |
409 | way_maxheight=metres_to_height(atof(v)); |
410 | } |
411 | if(!strcmp(k,"maxwidth")) |
412 | { |
413 | if(strchr(v,'\'')) |
414 | { |
415 | int feet,inches; |
416 | |
417 | if(sscanf(v,"%d'%d\"",&feet,&inches)==2) |
418 | way_maxwidth=metres_to_height((feet+(double)inches/12.0)*0.254); |
419 | else if(sscanf(v,"%d'",&feet)==1) |
420 | way_maxwidth=metres_to_height((feet+(double)inches/12.0)*0.254); |
421 | } |
422 | else if(strstr(v,"ft") || strstr(v,"feet")) |
423 | way_maxwidth=metres_to_width(atof(v)*0.254); |
424 | else |
425 | way_maxwidth=metres_to_width(atof(v)); |
426 | } |
427 | if(!strcmp(k,"maxlength")) |
428 | { |
429 | if(strchr(v,'\'')) |
430 | { |
431 | int feet,inches; |
432 | |
433 | if(sscanf(v,"%d'%d\"",&feet,&inches)==2) |
434 | way_maxlength=metres_to_height((feet+(double)inches/12.0)*0.254); |
435 | else if(sscanf(v,"%d'",&feet)==1) |
436 | way_maxlength=metres_to_height((feet+(double)inches/12.0)*0.254); |
437 | } |
438 | else if(strstr(v,"ft") || strstr(v,"feet")) |
439 | way_maxlength=metres_to_length(atof(v)*0.254); |
440 | else |
441 | way_maxlength=metres_to_length(atof(v)); |
442 | } |
443 | if(!strcmp(k,"motorbike")) |
444 | { |
445 | if(!strcmp(v,"true") || !strcmp(v,"yes") || !strcmp(v,"1") || !strcmp(v,"permissive") || !strcmp(v,"designated")) |
446 | way_allow_yes|=Allow_Motorbike; |
447 | else |
448 | way_allow_no|=Allow_Motorbike; |
449 | } |
450 | if(!strcmp(k,"motorcar")) |
451 | { |
452 | if(!strcmp(v,"true") || !strcmp(v,"yes") || !strcmp(v,"1") || !strcmp(v,"permissive") || !strcmp(v,"designated")) |
453 | way_allow_yes|=Allow_Motorcar; |
454 | else |
455 | way_allow_no|=Allow_Motorcar; |
456 | } |
457 | if(!strcmp(k,"motor_vehicle")) |
458 | { |
459 | if(!strcmp(v,"true") || !strcmp(v,"yes") || !strcmp(v,"1") || !strcmp(v,"permissive") || !strcmp(v,"designated")) |
460 | way_allow_yes|=Allow_Motorbike|Allow_Motorcar|Allow_Goods|Allow_HGV|Allow_PSV; |
461 | else |
462 | way_allow_no|=Allow_Motorbike|Allow_Motorcar|Allow_Goods|Allow_HGV|Allow_PSV; |
463 | } |
464 | break; |
465 | |
466 | case 'n': |
467 | if(!strcmp(k,"name")) |
468 | way_name=strcpy((char*)malloc(strlen(v)+1),v); |
469 | break; |
470 | |
471 | case 'o': |
472 | if(!strcmp(k,"oneway")) |
473 | { |
474 | if(!strcmp(v,"true") || !strcmp(v,"yes") || !strcmp(v,"1")) |
475 | way_oneway=1; |
476 | else if(!strcmp(v,"-1")) |
477 | way_oneway=-1; |
478 | } |
479 | break; |
480 | |
481 | case 'p': |
482 | if(!strcmp(k,"psv")) |
483 | { |
484 | if(!strcmp(v,"true") || !strcmp(v,"yes") || !strcmp(v,"1") || !strcmp(v,"permissive") || !strcmp(v,"designated")) |
485 | way_allow_yes|=Allow_PSV; |
486 | else |
487 | way_allow_no|=Allow_PSV; |
488 | } |
489 | break; |
490 | |
491 | case 'r': |
492 | if(!strcmp(k,"ref")) |
493 | way_ref=strcpy((char*)malloc(strlen(v)+1),v); |
494 | break; |
495 | |
496 | case 'v': |
497 | if(!strcmp(k,"vehicle")) |
498 | { |
499 | if(!strcmp(v,"true") || !strcmp(v,"yes") || !strcmp(v,"1") || !strcmp(v,"permissive") || !strcmp(v,"designated")) |
500 | way_allow_yes|=Allow_Bicycle|Allow_Motorbike|Allow_Motorcar|Allow_Goods|Allow_HGV|Allow_PSV; |
501 | else |
502 | way_allow_no|=Allow_Bicycle|Allow_Motorbike|Allow_Motorcar|Allow_Goods|Allow_HGV|Allow_PSV; |
503 | } |
504 | break; |
505 | |
506 | default: |
507 | ; |
508 | } |
509 | } |
510 | } |
511 | else if(isrelation) /* The middle of a relation */ |
512 | { |
513 | } |
514 | |
515 | if(!(nlines%10000)) |
516 | { |
517 | printf("\rReading: Lines=%ld Nodes=%ld Ways=%ld Relations=%ld",nlines,nnodes,nways,nrelations); |
518 | fflush(stdout); |
519 | } |
520 | } |
521 | |
522 | printf("\rRead: Lines=%ld Nodes=%ld Ways=%ld Relations=%ld \n",nlines,nnodes,nways,nrelations); |
523 | fflush(stdout); |
524 | |
525 | if(line) |
526 | free(line); |
527 | |
528 | if(way_nalloc) |
529 | free(way_nodes); |
530 | |
531 | return(0); |
532 | } |
533 | |
534 | |
535 | /*++++++++++++++++++++++++++++++++++++++ |
536 | Call fgets and realloc the buffer as needed to get a whole line. |
537 | |
538 | char *fgets_realloc Returns the modified buffer (NULL at the end of the file). |
539 | |
540 | char *buffer The current buffer. |
541 | |
542 | FILE *file The file to read from. |
543 | ++++++++++++++++++++++++++++++++++++++*/ |
544 | |
545 | static char *fgets_realloc(char *buffer,FILE *file) |
546 | { |
547 | int n=0; |
548 | char *buf; |
549 | |
550 | if(!buffer) |
551 | buffer=(char*)malloc(BUFFSIZE+1); |
552 | |
553 | while((buf=fgets(&buffer[n],BUFFSIZE,file))) |
554 | { |
555 | int s=strlen(buf); |
556 | n+=s; |
557 | |
558 | if(buffer[n-1]=='\n') |
559 | break; |
560 | else |
561 | buffer=(char*)realloc(buffer,n+BUFFSIZE+1); |
562 | } |
563 | |
564 | if(!buf) |
565 | {free(buffer);buffer=NULL;} |
566 | |
567 | return(buffer); |
568 | } |
Properties
Name | Value |
---|---|
cvs:description | OSM XML file parser. |