Add:maptool:parse osm tag addr:postcode| From #1031. thanks ziaou
[profile/ivi/navit.git] / navit / navit / maptool / osm_xml.c
1 /**
2  * Navit, a modular navigation system.
3  * Copyright (C) 2005-2011 Navit Team
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * version 2 as published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the
16  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA  02110-1301, USA.
18  */
19 #include <string.h>
20 #include <stdlib.h>
21 #include <math.h>
22 #include <unistd.h>
23 #include "maptool.h"
24
25 int
26 osm_xml_get_attribute(char *xml, char *attribute, char *buffer, int buffer_size)
27 {
28         int len=strlen(attribute);
29         char *pos,*i,s,attr[len+2];
30         strcpy(attr, attribute);
31         strcpy(attr+len, "=");
32         pos=strstr(xml, attr);
33         if (! pos)
34                 return 0;
35         pos+=len+1;
36         s=*pos++;
37         if (! s)
38                 return 0;
39         i=strchr(pos, s);
40         if (! i)
41                 return 0;
42         if (i - pos > buffer_size) {
43                 fprintf(stderr,"Buffer overflow %ld vs %d\n", (long)(i-pos), buffer_size);
44                 return 0;
45         }
46         strncpy(buffer, pos, i-pos);
47         buffer[i-pos]='\0';
48         return 1;
49 }
50
51 static struct entity {
52         char *entity;
53         char c;
54 } entities[]= {
55         {"&quot;",'"'},
56         {"&apos;",'\''},
57         {"&amp;",'&'},
58         {"&lt;",'<'},
59         {"&gt;",'>'},
60         {"&#34;",'"'},
61         {"&#39;",'\''},
62         {"&#38;",'&'},
63         {"&#60;",'<'},
64         {"&#62;",'>'},
65         {"&#123;",'{'},
66         {"&#125;",'}'},
67 };
68
69 void
70 osm_xml_decode_entities(char *buffer)
71 {
72         char *pos=buffer;
73         int i,len,found;
74
75         while ((pos=strchr(pos, '&'))) {
76                 found=0;
77                 for (i = 0 ; i < sizeof(entities)/sizeof(struct entity); i++) {
78                         len=strlen(entities[i].entity);
79                         if (!strncmp(pos, entities[i].entity, len)) {
80                                 *pos=entities[i].c;
81                                 memmove(pos+1, pos+len, strlen(pos+len)+1);
82                                 found=1;
83                                 break;
84                         }
85                 }
86                 pos++;
87         }
88 }
89
90 static int
91 parse_tag(char *p)
92 {
93         char k_buffer[BUFFER_SIZE];
94         char v_buffer[BUFFER_SIZE];
95         if (!osm_xml_get_attribute(p, "k", k_buffer, BUFFER_SIZE))
96                 return 0;
97         if (!osm_xml_get_attribute(p, "v", v_buffer, BUFFER_SIZE))
98                 return 0;
99         osm_xml_decode_entities(v_buffer);
100         osm_add_tag(k_buffer, v_buffer);
101         return 1;
102 }
103
104
105 static int
106 parse_node(char *p)
107 {
108         char id_buffer[BUFFER_SIZE];
109         char lat_buffer[BUFFER_SIZE];
110         char lon_buffer[BUFFER_SIZE];
111         if (!osm_xml_get_attribute(p, "id", id_buffer, BUFFER_SIZE))
112                 return 0;
113         if (!osm_xml_get_attribute(p, "lat", lat_buffer, BUFFER_SIZE))
114                 return 0;
115         if (!osm_xml_get_attribute(p, "lon", lon_buffer, BUFFER_SIZE))
116                 return 0;
117         osm_add_node(atoll(id_buffer), atof(lat_buffer), atof(lon_buffer));
118         return 1;
119 }
120
121
122 static int
123 parse_way(char *p)
124 {
125         char id_buffer[BUFFER_SIZE];
126         if (!osm_xml_get_attribute(p, "id", id_buffer, BUFFER_SIZE))
127                 return 0;
128         osm_add_way(atoll(id_buffer));
129         return 1;
130 }
131
132 static int
133 parse_relation(char *p)
134 {
135         char id_buffer[BUFFER_SIZE];
136         if (!osm_xml_get_attribute(p, "id", id_buffer, BUFFER_SIZE))
137                 return 0;
138         osm_add_relation(atoll(id_buffer));
139         return 1;
140 }
141
142 static int
143 parse_member(char *p)
144 {
145         char type_buffer[BUFFER_SIZE];
146         char ref_buffer[BUFFER_SIZE];
147         char role_buffer[BUFFER_SIZE];
148         int type;
149         if (!osm_xml_get_attribute(p, "type", type_buffer, BUFFER_SIZE))
150                 return 0;
151         if (!osm_xml_get_attribute(p, "ref", ref_buffer, BUFFER_SIZE))
152                 return 0;
153         if (!osm_xml_get_attribute(p, "role", role_buffer, BUFFER_SIZE))
154                 return 0;
155         if (!strcmp(type_buffer,"node")) 
156                 type=1;
157         else if (!strcmp(type_buffer,"way")) 
158                 type=2;
159         else if (!strcmp(type_buffer,"relation")) 
160                 type=3;
161         else {
162                 fprintf(stderr,"Unknown type %s\n",type_buffer);
163                 type=0;
164         }
165         osm_add_member(type, atoll(ref_buffer), role_buffer);
166         
167         return 1;
168 }
169
170 static int
171 parse_nd(char *p)
172 {
173         char ref_buffer[BUFFER_SIZE];
174         if (!osm_xml_get_attribute(p, "ref", ref_buffer, BUFFER_SIZE))
175                 return 0;
176         osm_add_nd(atoll(ref_buffer));
177         return 1;
178 }
179
180 int
181 map_collect_data_osm(FILE *in, struct maptool_osm *osm)
182 {
183         int size=BUFFER_SIZE;
184         char buffer[size];
185         char *p;
186         sig_alrm(0);
187         while (fgets(buffer, size, in)) {
188                 p=strchr(buffer,'<');
189                 if (! p) {
190                         fprintf(stderr,"WARNING: wrong line %s\n", buffer);
191                         continue;
192                 }
193                 if (!strncmp(p, "<?xml ",6)) {
194                 } else if (!strncmp(p, "<osm ",5)) {
195                 } else if (!strncmp(p, "<bound ",7)) {
196                 } else if (!strncmp(p, "<node ",6)) {
197                         if (!parse_node(p))
198                                 fprintf(stderr,"WARNING: failed to parse %s\n", buffer);
199                         processed_nodes++;
200                 } else if (!strncmp(p, "<tag ",5)) {
201                         if (!parse_tag(p))
202                                 fprintf(stderr,"WARNING: failed to parse %s\n", buffer);
203                 } else if (!strncmp(p, "<way ",5)) {
204                         if (!parse_way(p))
205                                 fprintf(stderr,"WARNING: failed to parse %s\n", buffer);
206                         processed_ways++;
207                 } else if (!strncmp(p, "<nd ",4)) {
208                         if (!parse_nd(p))
209                                 fprintf(stderr,"WARNING: failed to parse %s\n", buffer);
210                 } else if (!strncmp(p, "<relation ",10)) {
211                         if (!parse_relation(p))
212                                 fprintf(stderr,"WARNING: failed to parse %s\n", buffer);
213                         processed_relations++;
214                 } else if (!strncmp(p, "<member ",8)) {
215                         if (!parse_member(p))
216                                 fprintf(stderr,"WARNING: failed to parse %s\n", buffer);
217                 } else if (!strncmp(p, "</node>",7)) {
218                         osm_end_node(osm);
219                 } else if (!strncmp(p, "</way>",6)) {
220                         osm_end_way(osm);
221                 } else if (!strncmp(p, "</relation>",11)) {
222                         osm_end_relation(osm);
223                 } else if (!strncmp(p, "</osm>",6)) {
224                 } else {
225                         fprintf(stderr,"WARNING: unknown tag in %s\n", buffer);
226                 }
227         }
228         sig_alrm(0);
229         sig_alrm_end();
230         return 1;
231 }