1 /***************************************
2 $Header: /home/amb/routino/src/RCS/tagmodifier.c,v 1.8 2010/11/13 14:22:28 amb Exp $
4 Test application for OSM XML file parser / tagging rule testing.
6 Part of the Routino routing software.
7 ******************/ /******************
8 This file Copyright 2010 Andrew M. Bishop
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.
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.
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 ***************************************/
39 static long nnodes=0,nways=0,nrelations=0;
40 TagList *current_tags=NULL;
45 static void print_usage(int detail);
48 /* The XML tag processing function prototypes */
50 static int xmlDeclaration_function(const char *_tag_,int _type_,const char *version,const char *encoding);
51 static int osmType_function(const char *_tag_,int _type_,const char *version,const char *generator);
52 static int relationType_function(const char *_tag_,int _type_,const char *id,const char *timestamp,const char *uid,const char *user,const char *visible,const char *version,const char *action);
53 static int wayType_function(const char *_tag_,int _type_,const char *id,const char *timestamp,const char *uid,const char *user,const char *visible,const char *version,const char *action);
54 static int memberType_function(const char *_tag_,int _type_,const char *type,const char *ref,const char *role);
55 static int ndType_function(const char *_tag_,int _type_,const char *ref);
56 static int nodeType_function(const char *_tag_,int _type_,const char *id,const char *lat,const char *lon,const char *timestamp,const char *uid,const char *user,const char *visible,const char *version,const char *action);
57 static int tagType_function(const char *_tag_,int _type_,const char *k,const char *v);
58 static int boundType_function(const char *_tag_,int _type_,const char *box,const char *origin);
59 static int boundsType_function(const char *_tag_,int _type_,const char *minlat,const char *minlon,const char *maxlat,const char *maxlon,const char *origin);
62 /* The XML tag definitions */
64 /*+ The boundsType type tag. +*/
65 static xmltag boundsType_tag=
67 5, {"minlat","minlon","maxlat","maxlon","origin"},
71 /*+ The boundType type tag. +*/
72 static xmltag boundType_tag=
78 /*+ The tagType type tag. +*/
79 static xmltag tagType_tag=
85 /*+ The nodeType type tag. +*/
86 static xmltag nodeType_tag=
88 9, {"id","lat","lon","timestamp","uid","user","visible","version","action"},
92 /*+ The ndType type tag. +*/
93 static xmltag ndType_tag=
99 /*+ The memberType type tag. +*/
100 static xmltag memberType_tag=
102 3, {"type","ref","role"},
106 /*+ The wayType type tag. +*/
107 static xmltag wayType_tag=
109 7, {"id","timestamp","uid","user","visible","version","action"},
111 {&ndType_tag,&tagType_tag,NULL}};
113 /*+ The relationType type tag. +*/
114 static xmltag relationType_tag=
116 7, {"id","timestamp","uid","user","visible","version","action"},
117 relationType_function,
118 {&memberType_tag,&tagType_tag,NULL}};
120 /*+ The osmType type tag. +*/
121 static xmltag osmType_tag=
123 2, {"version","generator"},
125 {&boundsType_tag,&boundType_tag,&nodeType_tag,&wayType_tag,&relationType_tag,NULL}};
127 /*+ The xmlDeclaration type tag. +*/
128 static xmltag xmlDeclaration_tag=
130 2, {"version","encoding"},
131 xmlDeclaration_function,
135 /*+ The complete set of tags at the top level. +*/
136 static xmltag *xml_toplevel_tags[]={&xmlDeclaration_tag,&osmType_tag,NULL};
139 /* The XML tag processing functions */
142 /*++++++++++++++++++++++++++++++++++++++
143 The function that is called when the boundsType XSD type is seen
145 int boundsType_function Returns 0 if no error occured or something else otherwise.
147 const char *_tag_ Set to the name of the element tag that triggered this function call.
149 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
151 const char *minlat The contents of the 'minlat' attribute (or NULL if not defined).
153 const char *minlon The contents of the 'minlon' attribute (or NULL if not defined).
155 const char *maxlat The contents of the 'maxlat' attribute (or NULL if not defined).
157 const char *maxlon The contents of the 'maxlon' attribute (or NULL if not defined).
159 const char *origin The contents of the 'origin' attribute (or NULL if not defined).
160 ++++++++++++++++++++++++++++++++++++++*/
162 static int boundsType_function(const char *_tag_,int _type_,const char *minlat,const char *minlon,const char *maxlat,const char *maxlon,const char *origin)
164 printf(" <%s%s",(_type_==XMLPARSE_TAG_END)?"/":"",_tag_);
165 if(minlat) printf(" minlat=\"%s\"",ParseXML_Encode_Safe_XML(minlat));
166 if(minlon) printf(" minlon=\"%s\"",ParseXML_Encode_Safe_XML(minlon));
167 if(maxlat) printf(" maxlat=\"%s\"",ParseXML_Encode_Safe_XML(maxlat));
168 if(maxlon) printf(" maxlon=\"%s\"",ParseXML_Encode_Safe_XML(maxlon));
169 if(origin) printf(" origin=\"%s\"",ParseXML_Encode_Safe_XML(origin));
170 printf("%s>\n",(_type_==(XMLPARSE_TAG_START|XMLPARSE_TAG_END))?" /":"");
175 /*++++++++++++++++++++++++++++++++++++++
176 The function that is called when the boundType XSD type is seen
178 int boundType_function Returns 0 if no error occured or something else otherwise.
180 const char *_tag_ Set to the name of the element tag that triggered this function call.
182 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
184 const char *box The contents of the 'box' attribute (or NULL if not defined).
186 const char *origin The contents of the 'origin' attribute (or NULL if not defined).
187 ++++++++++++++++++++++++++++++++++++++*/
189 static int boundType_function(const char *_tag_,int _type_,const char *box,const char *origin)
191 printf(" <%s%s",(_type_==XMLPARSE_TAG_END)?"/":"",_tag_);
192 if(box) printf(" box=\"%s\"",ParseXML_Encode_Safe_XML(box));
193 if(origin) printf(" origin=\"%s\"",ParseXML_Encode_Safe_XML(origin));
194 printf("%s>\n",(_type_==(XMLPARSE_TAG_START|XMLPARSE_TAG_END))?" /":"");
199 /*++++++++++++++++++++++++++++++++++++++
200 The function that is called when the tagType XSD type is seen
202 int tagType_function Returns 0 if no error occured or something else otherwise.
204 const char *_tag_ Set to the name of the element tag that triggered this function call.
206 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
208 const char *k The contents of the 'k' attribute (or NULL if not defined).
210 const char *v The contents of the 'v' attribute (or NULL if not defined).
211 ++++++++++++++++++++++++++++++++++++++*/
213 static int tagType_function(const char *_tag_,int _type_,const char *k,const char *v)
215 if(_type_&XMLPARSE_TAG_START)
217 XMLPARSE_ASSERT_STRING(_tag_,k);
218 XMLPARSE_ASSERT_STRING(_tag_,v);
220 AppendTag(current_tags,k,v);
227 /*++++++++++++++++++++++++++++++++++++++
228 The function that is called when the nodeType XSD type is seen
230 int nodeType_function Returns 0 if no error occured or something else otherwise.
232 const char *_tag_ Set to the name of the element tag that triggered this function call.
234 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
236 const char *id The contents of the 'id' attribute (or NULL if not defined).
238 const char *lat The contents of the 'lat' attribute (or NULL if not defined).
240 const char *lon The contents of the 'lon' attribute (or NULL if not defined).
242 const char *timestamp The contents of the 'timestamp' attribute (or NULL if not defined).
244 const char *uid The contents of the 'uid' attribute (or NULL if not defined).
246 const char *user The contents of the 'user' attribute (or NULL if not defined).
248 const char *visible The contents of the 'visible' attribute (or NULL if not defined).
250 const char *version The contents of the 'version' attribute (or NULL if not defined).
252 const char *action The contents of the 'action' attribute (or NULL if not defined).
253 ++++++++++++++++++++++++++++++++++++++*/
255 static int nodeType_function(const char *_tag_,int _type_,const char *id,const char *lat,const char *lon,const char *timestamp,const char *uid,const char *user,const char *visible,const char *version,const char *action)
257 if(_type_&XMLPARSE_TAG_START)
262 fprintf_middle(stderr,"Reading: Lines=%ld Nodes=%ld Ways=%ld Relations=%ld",ParseXML_LineNumber(),nnodes,nways,nrelations);
264 current_tags=NewTagList();
267 if(_type_&XMLPARSE_TAG_END)
269 TagList *result=ApplyTaggingRules(&NodeRules,current_tags);
272 for(i=0;i<result->ntags;i++)
275 printf(" k=\"%s\"",ParseXML_Encode_Safe_XML(result->k[i]));
276 printf(" v=\"%s\"",ParseXML_Encode_Safe_XML(result->v[i]));
280 DeleteTagList(current_tags);
281 DeleteTagList(result);
284 printf(" <%s%s",(_type_==XMLPARSE_TAG_END)?"/":"",_tag_);
285 if(id) printf(" id=\"%s\"",ParseXML_Encode_Safe_XML(id));
286 if(lat) printf(" lat=\"%s\"",ParseXML_Encode_Safe_XML(lat));
287 if(lon) printf(" lon=\"%s\"",ParseXML_Encode_Safe_XML(lon));
288 if(timestamp) printf(" timestamp=\"%s\"",ParseXML_Encode_Safe_XML(timestamp));
289 if(uid) printf(" uid=\"%s\"",ParseXML_Encode_Safe_XML(uid));
290 if(user) printf(" user=\"%s\"",ParseXML_Encode_Safe_XML(user));
291 if(visible) printf(" visible=\"%s\"",ParseXML_Encode_Safe_XML(visible));
292 if(version) printf(" version=\"%s\"",ParseXML_Encode_Safe_XML(version));
293 if(action) printf(" action=\"%s\"",ParseXML_Encode_Safe_XML(action));
294 printf("%s>\n",(_type_==(XMLPARSE_TAG_START|XMLPARSE_TAG_END))?" /":"");
299 /*++++++++++++++++++++++++++++++++++++++
300 The function that is called when the ndType XSD type is seen
302 int ndType_function Returns 0 if no error occured or something else otherwise.
304 const char *_tag_ Set to the name of the element tag that triggered this function call.
306 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
308 const char *ref The contents of the 'ref' attribute (or NULL if not defined).
309 ++++++++++++++++++++++++++++++++++++++*/
311 static int ndType_function(const char *_tag_,int _type_,const char *ref)
313 printf(" <%s%s",(_type_==XMLPARSE_TAG_END)?"/":"",_tag_);
314 if(ref) printf(" ref=\"%s\"",ParseXML_Encode_Safe_XML(ref));
315 printf("%s>\n",(_type_==(XMLPARSE_TAG_START|XMLPARSE_TAG_END))?" /":"");
320 /*++++++++++++++++++++++++++++++++++++++
321 The function that is called when the memberType XSD type is seen
323 int memberType_function Returns 0 if no error occured or something else otherwise.
325 const char *_tag_ Set to the name of the element tag that triggered this function call.
327 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
329 const char *type The contents of the 'type' attribute (or NULL if not defined).
331 const char *ref The contents of the 'ref' attribute (or NULL if not defined).
333 const char *role The contents of the 'role' attribute (or NULL if not defined).
334 ++++++++++++++++++++++++++++++++++++++*/
336 static int memberType_function(const char *_tag_,int _type_,const char *type,const char *ref,const char *role)
338 printf(" <%s%s",(_type_==XMLPARSE_TAG_END)?"/":"",_tag_);
339 if(type) printf(" type=\"%s\"",ParseXML_Encode_Safe_XML(type));
340 if(ref) printf(" ref=\"%s\"",ParseXML_Encode_Safe_XML(ref));
341 if(role) printf(" role=\"%s\"",ParseXML_Encode_Safe_XML(role));
342 printf("%s>\n",(_type_==(XMLPARSE_TAG_START|XMLPARSE_TAG_END))?" /":"");
347 /*++++++++++++++++++++++++++++++++++++++
348 The function that is called when the wayType XSD type is seen
350 int wayType_function Returns 0 if no error occured or something else otherwise.
352 const char *_tag_ Set to the name of the element tag that triggered this function call.
354 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
356 const char *id The contents of the 'id' attribute (or NULL if not defined).
358 const char *timestamp The contents of the 'timestamp' attribute (or NULL if not defined).
360 const char *uid The contents of the 'uid' attribute (or NULL if not defined).
362 const char *user The contents of the 'user' attribute (or NULL if not defined).
364 const char *visible The contents of the 'visible' attribute (or NULL if not defined).
366 const char *version The contents of the 'version' attribute (or NULL if not defined).
368 const char *action The contents of the 'action' attribute (or NULL if not defined).
369 ++++++++++++++++++++++++++++++++++++++*/
371 static int wayType_function(const char *_tag_,int _type_,const char *id,const char *timestamp,const char *uid,const char *user,const char *visible,const char *version,const char *action)
373 if(_type_&XMLPARSE_TAG_START)
378 fprintf_middle(stderr,"Reading: Lines=%ld Nodes=%ld Ways=%ld Relations=%ld",ParseXML_LineNumber(),nnodes,nways,nrelations);
380 current_tags=NewTagList();
383 if(_type_&XMLPARSE_TAG_END)
385 TagList *result=ApplyTaggingRules(&WayRules,current_tags);
388 for(i=0;i<result->ntags;i++)
391 printf(" k=\"%s\"",ParseXML_Encode_Safe_XML(result->k[i]));
392 printf(" v=\"%s\"",ParseXML_Encode_Safe_XML(result->v[i]));
396 DeleteTagList(current_tags);
397 DeleteTagList(result);
400 printf(" <%s%s",(_type_==XMLPARSE_TAG_END)?"/":"",_tag_);
401 if(id) printf(" id=\"%s\"",ParseXML_Encode_Safe_XML(id));
402 if(timestamp) printf(" timestamp=\"%s\"",ParseXML_Encode_Safe_XML(timestamp));
403 if(uid) printf(" uid=\"%s\"",ParseXML_Encode_Safe_XML(uid));
404 if(user) printf(" user=\"%s\"",ParseXML_Encode_Safe_XML(user));
405 if(visible) printf(" visible=\"%s\"",ParseXML_Encode_Safe_XML(visible));
406 if(version) printf(" version=\"%s\"",ParseXML_Encode_Safe_XML(version));
407 if(action) printf(" action=\"%s\"",ParseXML_Encode_Safe_XML(action));
408 printf("%s>\n",(_type_==(XMLPARSE_TAG_START|XMLPARSE_TAG_END))?" /":"");
413 /*++++++++++++++++++++++++++++++++++++++
414 The function that is called when the relationType XSD type is seen
416 int relationType_function Returns 0 if no error occured or something else otherwise.
418 const char *_tag_ Set to the name of the element tag that triggered this function call.
420 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
422 const char *id The contents of the 'id' attribute (or NULL if not defined).
424 const char *timestamp The contents of the 'timestamp' attribute (or NULL if not defined).
426 const char *uid The contents of the 'uid' attribute (or NULL if not defined).
428 const char *user The contents of the 'user' attribute (or NULL if not defined).
430 const char *visible The contents of the 'visible' attribute (or NULL if not defined).
432 const char *version The contents of the 'version' attribute (or NULL if not defined).
434 const char *action The contents of the 'action' attribute (or NULL if not defined).
435 ++++++++++++++++++++++++++++++++++++++*/
437 static int relationType_function(const char *_tag_,int _type_,const char *id,const char *timestamp,const char *uid,const char *user,const char *visible,const char *version,const char *action)
439 if(_type_&XMLPARSE_TAG_START)
443 if(!(nrelations%1000))
444 fprintf_middle(stderr,"Reading: Lines=%ld Nodes=%ld Ways=%ld Relations=%ld",ParseXML_LineNumber(),nnodes,nways,nrelations);
446 current_tags=NewTagList();
449 if(_type_&XMLPARSE_TAG_END)
451 TagList *result=ApplyTaggingRules(&RelationRules,current_tags);
454 for(i=0;i<result->ntags;i++)
457 printf(" k=\"%s\"",ParseXML_Encode_Safe_XML(result->k[i]));
458 printf(" v=\"%s\"",ParseXML_Encode_Safe_XML(result->v[i]));
462 DeleteTagList(current_tags);
463 DeleteTagList(result);
466 printf(" <%s%s",(_type_==XMLPARSE_TAG_END)?"/":"",_tag_);
467 if(id) printf(" id=\"%s\"",ParseXML_Encode_Safe_XML(id));
468 if(timestamp) printf(" timestamp=\"%s\"",ParseXML_Encode_Safe_XML(timestamp));
469 if(uid) printf(" uid=\"%s\"",ParseXML_Encode_Safe_XML(uid));
470 if(user) printf(" user=\"%s\"",ParseXML_Encode_Safe_XML(user));
471 if(visible) printf(" visible=\"%s\"",ParseXML_Encode_Safe_XML(visible));
472 if(version) printf(" version=\"%s\"",ParseXML_Encode_Safe_XML(version));
473 if(action) printf(" action=\"%s\"",ParseXML_Encode_Safe_XML(action));
474 printf("%s>\n",(_type_==(XMLPARSE_TAG_START|XMLPARSE_TAG_END))?" /":"");
479 /*++++++++++++++++++++++++++++++++++++++
480 The function that is called when the osmType XSD type is seen
482 int osmType_function Returns 0 if no error occured or something else otherwise.
484 const char *_tag_ Set to the name of the element tag that triggered this function call.
486 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
488 const char *version The contents of the 'version' attribute (or NULL if not defined).
490 const char *generator The contents of the 'generator' attribute (or NULL if not defined).
491 ++++++++++++++++++++++++++++++++++++++*/
493 static int osmType_function(const char *_tag_,int _type_,const char *version,const char *generator)
495 printf("<%s%s",(_type_==XMLPARSE_TAG_END)?"/":"",_tag_);
496 if(version) printf(" version=\"%s\"",ParseXML_Encode_Safe_XML(version));
497 if(generator) printf(" generator=\"%s\"",ParseXML_Encode_Safe_XML(generator));
498 printf("%s>\n",(_type_==(XMLPARSE_TAG_START|XMLPARSE_TAG_END))?" /":"");
503 /*++++++++++++++++++++++++++++++++++++++
504 The function that is called when the XML declaration is seen
506 int xmlDeclaration_function Returns 0 if no error occured or something else otherwise.
508 const char *_tag_ Set to the name of the element tag that triggered this function call.
510 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
512 const char *version The contents of the 'version' attribute (or NULL if not defined).
514 const char *encoding The contents of the 'encoding' attribute (or NULL if not defined).
515 ++++++++++++++++++++++++++++++++++++++*/
517 static int xmlDeclaration_function(const char *_tag_,int _type_,const char *version,const char *encoding)
519 printf("<?%s",_tag_);
520 if(version) printf(" version=\"%s\"",ParseXML_Encode_Safe_XML(version));
521 if(encoding) printf(" encoding=\"%s\"",ParseXML_Encode_Safe_XML(encoding));
527 /*++++++++++++++++++++++++++++++++++++++
528 The main program for the planetsplitter.
529 ++++++++++++++++++++++++++++++++++++++*/
531 int main(int argc,char **argv)
533 char *tagging=NULL,*filename=NULL;
537 /* Parse the command line arguments */
539 for(arg=1;arg<argc;arg++)
541 if(!strcmp(argv[arg],"--help"))
543 else if(!strcmp(argv[arg],"--loggable"))
545 else if(!strncmp(argv[arg],"--tagging=",10))
546 tagging=&argv[arg][10];
547 else if(argv[arg][0]=='-' && argv[arg][1]=='-')
555 /* Check the specified command line options */
559 if(!ExistsFile(tagging))
561 fprintf(stderr,"Error: The '--tagging' option specifies a file that does not exist.\n");
567 if(ExistsFile("tagging.xml"))
568 tagging="tagging.xml";
571 fprintf(stderr,"Error: The '--tagging' option was not used and the default 'tagging.xml' does not exist.\n");
576 if(ParseXMLTaggingRules(tagging))
578 fprintf(stderr,"Error: Cannot read the tagging rules in the file '%s'.\n",tagging);
582 /* Open the input file */
586 file=fopen(filename,"rb");
590 fprintf(stderr,"Cannot open file '%s' for reading [%s].\n",argv[arg],strerror(errno));
599 fprintf_first(stderr,"Reading: Lines=0 Nodes=0 Ways=0 Relations=0");
601 retval=ParseXML(file,xml_toplevel_tags,XMLPARSE_UNKNOWN_ATTR_IGNORE);
603 fprintf_last(stderr,"Read: Lines=%ld Nodes=%ld Ways=%ld Relations=%ld",ParseXML_LineNumber(),nnodes,nways,nrelations);
614 /*++++++++++++++++++++++++++++++++++++++
615 Print out the usage information.
617 int detail The level of detail to use - 0 = low, 1 = high.
618 ++++++++++++++++++++++++++++++++++++++*/
620 static void print_usage(int detail)
623 "Usage: tagmodifier [--help]\n"
625 " [--tagging=<filename>]\n"
626 " [<filename.osm>]\n");
631 "--help Prints this information.\n"
633 "--loggable Print progress messages suitable for logging to file.\n"
635 "--tagging=<filename> The name of the XML file containing the tagging rules\n"
636 " (defaults to 'tagging.xml' in current directory).\n"
638 "<filename.osm> The name of the file to process (by default data is\n"
639 " read from standard input).\n");