1 /***************************************
2 $Header: /home/amb/routino/src/xml/RCS/xsd-to-xmlparser.c,v 1.10 2010/04/23 18:41:20 amb Exp $
4 An XML parser for simplified XML Schema Definitions to create XML parser skeletons.
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 ***************************************/
33 /*+ A forward definition of the xmltagx +*/
34 typedef struct _xmltagx xmltagx;
37 /*+ A structure to hold the extended definition of a tag. +*/
40 char *name; /*+ The name of the tag. +*/
41 char *type; /*+ The type of the tag. +*/
43 int nattributes; /*+ The number of valid attributes for the tag. +*/
44 char *attributes[XMLPARSE_MAX_ATTRS]; /*+ The valid attributes for the tag. +*/
46 int nsubtagsx; /*+ The number of valid attributes for the tag. +*/
47 xmltagx *subtagsx[XMLPARSE_MAX_SUBTAGS]; /*+ The list of types for the subtags contained within this one. +*/
51 /* The local variables and functions */
55 char *currenttype=NULL;
57 static char *safe(const char *name);
60 /* The XML tag processing function prototypes */
62 static int xmlDeclaration_function(const char *_tag_,int _type_,const char *version,const char *encoding);
63 static int schemaType_function(const char *_tag_,int _type_,const char *elementFormDefault,const char *xmlns_xsd);
64 static int complexType_function(const char *_tag_,int _type_,const char *name);
65 static int attributeType_function(const char *_tag_,int _type_,const char *name,const char *type);
66 static int sequenceType_function(const char *_tag_,int _type_);
67 static int elementType_function(const char *_tag_,int _type_,const char *name,const char *type,const char *minOccurs,const char *maxOccurs);
70 /* The XML tag definitions */
72 /*+ The elementType type tag. +*/
73 static xmltag elementType_tag=
75 4, {"name","type","minOccurs","maxOccurs"},
79 /*+ The sequenceType type tag. +*/
80 static xmltag sequenceType_tag=
83 sequenceType_function,
84 {&elementType_tag,NULL}};
86 /*+ The attributeType type tag. +*/
87 static xmltag attributeType_tag=
90 attributeType_function,
93 /*+ The complexType type tag. +*/
94 static xmltag complexType_tag=
98 {&sequenceType_tag,&attributeType_tag,NULL}};
100 /*+ The schemaType type tag. +*/
101 static xmltag schemaType_tag=
103 2, {"elementFormDefault","xmlns:xsd"},
105 {&elementType_tag,&complexType_tag,NULL}};
107 /*+ The xmlDeclaration type tag. +*/
108 static xmltag xmlDeclaration_tag=
110 2, {"version","encoding"},
111 xmlDeclaration_function,
115 /*+ The complete set of tags at the top level. +*/
116 static xmltag *xml_toplevel_tags[]={&xmlDeclaration_tag,&schemaType_tag,NULL};
119 /* The XML tag processing functions */
122 /*++++++++++++++++++++++++++++++++++++++
123 The function that is called when the elementType XSD type is seen
125 int elementType_function Returns 0 if no error occured or something else otherwise.
127 const char *_tag_ Set to the name of the element tag that triggered this function call.
129 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
131 const char *name The contents of the 'name' attribute (or NULL if not defined).
133 const char *type The contents of the 'type' attribute (or NULL if not defined).
135 const char *minOccurs The contents of the 'minOccurs' attribute (or NULL if not defined).
137 const char *maxOccurs The contents of the 'maxOccurs' attribute (or NULL if not defined).
138 ++++++++++++++++++++++++++++++++++++++*/
140 static int elementType_function(const char *_tag_,int _type_,const char *name,const char *type,const char *minOccurs,const char *maxOccurs)
145 if(_type_==XMLPARSE_TAG_END)
148 for(i=0;i<ntagsx;i++)
149 if(!strcmp(type,tagsx[i]->type) && !strcmp(name,tagsx[i]->name))
155 tagsx=(xmltagx**)realloc((void*)tagsx,ntagsx*sizeof(xmltagx*));
157 tagsx[ntagsx-1]=(xmltagx*)calloc(1,sizeof(xmltagx));
158 tagsx[ntagsx-1]->name=strcpy(malloc(strlen(name)+1),name);
159 tagsx[ntagsx-1]->type=strcpy(malloc(strlen(type)+1),type);
161 tagx=tagsx[ntagsx-1];
167 for(i=0;i<ntagsx;i++)
168 if(!strcmp(tagsx[i]->type,currenttype))
170 tagsx[i]->subtagsx[tagsx[i]->nsubtagsx]=tagx;
171 tagsx[i]->nsubtagsx++;
173 if(tagsx[i]->nsubtagsx==XMLPARSE_MAX_SUBTAGS)
174 {fprintf(stderr,"Too many subtags seen for type '%s'.\n",currenttype); exit(1);}
181 /*++++++++++++++++++++++++++++++++++++++
182 The function that is called when the sequenceType XSD type is seen
184 int sequenceType_function Returns 0 if no error occured or something else otherwise.
186 const char *_tag_ Set to the name of the element tag that triggered this function call.
188 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
189 ++++++++++++++++++++++++++++++++++++++*/
191 static int sequenceType_function(const char *_tag_,int _type_)
197 /*++++++++++++++++++++++++++++++++++++++
198 The function that is called when the attributeType XSD type is seen
200 int attributeType_function Returns 0 if no error occured or something else otherwise.
202 const char *_tag_ Set to the name of the element tag that triggered this function call.
204 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
206 const char *name The contents of the 'name' attribute (or NULL if not defined).
208 const char *type The contents of the 'type' attribute (or NULL if not defined).
209 ++++++++++++++++++++++++++++++++++++++*/
211 static int attributeType_function(const char *_tag_,int _type_,const char *name,const char *type)
215 if(_type_==XMLPARSE_TAG_END)
218 for(i=0;i<ntagsx;i++)
219 if(!strcmp(tagsx[i]->type,currenttype))
221 tagsx[i]->attributes[tagsx[i]->nattributes]=strcpy(malloc(strlen(name)+1),name);
222 tagsx[i]->nattributes++;
224 if(tagsx[i]->nattributes==XMLPARSE_MAX_ATTRS)
225 {fprintf(stderr,"Too many attributes seen for type '%s'.\n",currenttype); exit(1);}
232 /*++++++++++++++++++++++++++++++++++++++
233 The function that is called when the complexType XSD type is seen
235 int complexType_function Returns 0 if no error occured or something else otherwise.
237 const char *_tag_ Set to the name of the element tag that triggered this function call.
239 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
241 const char *name The contents of the 'name' attribute (or NULL if not defined).
242 ++++++++++++++++++++++++++++++++++++++*/
244 static int complexType_function(const char *_tag_,int _type_,const char *name)
246 if(_type_==XMLPARSE_TAG_END)
249 currenttype=strcpy(realloc(currenttype,strlen(name)+1),name);
255 /*++++++++++++++++++++++++++++++++++++++
256 The function that is called when the schemaType XSD type is seen
258 int schemaType_function Returns 0 if no error occured or something else otherwise.
260 const char *_tag_ Set to the name of the element tag that triggered this function call.
262 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
264 const char *elementFormDefault The contents of the 'elementFormDefault' attribute (or NULL if not defined).
266 const char *xmlns_xsd The contents of the 'xmlns:xsd' attribute (or NULL if not defined).
267 ++++++++++++++++++++++++++++++++++++++*/
269 static int schemaType_function(const char *_tag_,int _type_,const char *elementFormDefault,const char *xmlns_xsd)
275 /*++++++++++++++++++++++++++++++++++++++
276 The function that is called when the XML declaration is seen
278 int xmlDeclaration_function Returns 0 if no error occured or something else otherwise.
280 const char *_tag_ Set to the name of the element tag that triggered this function call.
282 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
284 const char *version The contents of the 'version' attribute (or NULL if not defined).
286 const char *encoding The contents of the 'encoding' attribute (or NULL if not defined).
287 ++++++++++++++++++++++++++++++++++++++*/
289 static int xmlDeclaration_function(const char *_tag_,int _type_,const char *version,const char *encoding)
295 /*++++++++++++++++++++++++++++++++++++++
296 The XML Schema Definition XML parser and C program generator.
297 ++++++++++++++++++++++++++++++++++++++*/
299 int main(int argc,char **argv)
303 if(ParseXML(stdin,xml_toplevel_tags,XMLPARSE_UNKNOWN_ATTR_IGNORE))
305 fprintf(stderr,"Cannot parse XML file - exiting.\n");
309 /* Add the XML declaration as a tag. */
312 elementType_function("xsd:element",XMLPARSE_TAG_START|XMLPARSE_TAG_END,"xml","xmlDeclaration",NULL,NULL);
313 complexType_function("xsd:complexType",XMLPARSE_TAG_START,"xmlDeclaration");
314 attributeType_function("xsd:attribute",XMLPARSE_TAG_START|XMLPARSE_TAG_END,"version",NULL);
315 attributeType_function("xsd:attribute",XMLPARSE_TAG_START|XMLPARSE_TAG_END,"encoding",NULL);
316 complexType_function("xsd:complexType",XMLPARSE_TAG_END,NULL);
322 for(i=0;i<ntagsx;i++)
324 for(j=0;j<tagsx[i]->nsubtagsx;j++)
326 for(k=0;k<ntagsx;k++)
327 if(tagsx[i]->subtagsx[j]==tagsx[k])
332 xmltagx *temp=tagsx[i];
343 /* Print the header */
345 printf("/***************************************\n");
346 printf(" An automatically generated skeleton XML parser.\n");
348 printf(" Automatically generated by xsd-to-xmlparser.\n");
349 printf(" ***************************************/\n");
352 printf("#include <stdio.h>\n");
354 printf("#include \"xmlparse.h\"\n");
356 /* Print the function prototypes */
360 printf("/* The XML tag processing function prototypes */\n");
363 for(i=ntagsx-1;i>=0;i--)
365 printf("static int %s_function(const char *_tag_,int _type_",safe(tagsx[i]->type));
367 for(j=0;j<tagsx[i]->nattributes;j++)
368 printf(",const char *%s",safe(tagsx[i]->attributes[j]));
373 /* Print the xmltag variables */
377 printf("/* The XML tag definitions */\n");
379 for(i=0;i<ntagsx;i++)
382 printf("/*+ The %s type tag. +*/\n",tagsx[i]->type);
383 printf("static xmltag %s_tag=\n",safe(tagsx[i]->type));
384 printf(" {\"%s\",\n",tagsx[i]->name);
386 printf(" %d, {",tagsx[i]->nattributes);
387 for(j=0;j<tagsx[i]->nattributes;j++)
388 printf("%s\"%s\"",(j?",":""),tagsx[i]->attributes[j]);
389 printf("%s},\n",(tagsx[i]->nattributes?"":"NULL"));
391 printf(" %s_function,\n",safe(tagsx[i]->type));
394 for(j=0;j<tagsx[i]->nsubtagsx;j++)
395 printf("&%s_tag,",safe(tagsx[i]->subtagsx[j]->type));
401 printf("/*+ The complete set of tags at the top level. +*/\n");
402 printf("static xmltag *xml_toplevel_tags[]={");
403 printf("&%s_tag,",safe(tagsx[ntagsx-1]->type));
404 printf("&%s_tag,",safe(tagsx[ntagsx-2]->type));
407 /* Print the functions */
411 printf("/* The XML tag processing functions */\n");
413 for(i=0;i<ntagsx;i++)
417 printf("/*++++++++++++++++++++++++++++++++++++++\n");
418 if(i==(ntagsx-1)) /* XML tag */
419 printf(" The function that is called when the XML declaration is seen\n");
421 printf(" The function that is called when the %s XSD type is seen\n",tagsx[i]->type);
423 printf(" int %s_function Returns 0 if no error occured or something else otherwise.\n",safe(tagsx[i]->type));
425 printf(" const char *_tag_ Set to the name of the element tag that triggered this function call.\n");
427 printf(" int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.\n");
428 for(j=0;j<tagsx[i]->nattributes;j++)
431 printf(" const char *%s The contents of the '%s' attribute (or NULL if not defined).\n",safe(tagsx[i]->attributes[j]),tagsx[i]->attributes[j]);
433 printf(" ++++++++++++++++++++++++++++++++++++++*/\n");
436 printf("static int %s_function(const char *_tag_,int _type_",safe(tagsx[i]->type));
438 for(j=0;j<tagsx[i]->nattributes;j++)
439 printf(",const char *%s",safe(tagsx[i]->attributes[j]));
445 if(i==(ntagsx-1)) /* XML tag */
447 printf(" printf(\"<?%%s\",_tag_);\n");
448 for(j=0;j<tagsx[i]->nattributes;j++)
450 char *safename=safe(tagsx[i]->attributes[j]);
451 printf(" if(%s) printf(\" %s=\\\"%%s\\\"\",ParseXML_Encode_Safe_XML(%s));\n",safename,tagsx[i]->attributes[j],safename);
453 printf(" printf(\" ?>\\n\");\n");
457 printf(" printf(\"<%%s%%s\",(_type_==XMLPARSE_TAG_END)?\"/\":\"\",_tag_);\n");
458 for(j=0;j<tagsx[i]->nattributes;j++)
460 char *safename=safe(tagsx[i]->attributes[j]);
461 printf(" if(%s) printf(\" %s=\\\"%%s\\\"\",ParseXML_Encode_Safe_XML(%s));\n",safename,tagsx[i]->attributes[j],safename);
463 printf(" printf(\"%%s>\\n\",(_type_==(XMLPARSE_TAG_START|XMLPARSE_TAG_END))?\" /\":\"\");\n");
466 printf(" return(0);\n");
470 /* Print the main function */
474 printf("/*++++++++++++++++++++++++++++++++++++++\n");
475 printf(" A skeleton XML parser.\n");
476 printf(" ++++++++++++++++++++++++++++++++++++++*/\n");
478 printf("int main(int argc,char **argv)\n");
480 printf(" if(ParseXML(stdin,xml_toplevel_tags,XMLPARSE_UNKNOWN_ATTR_WARN))\n");
481 printf(" return(1);\n");
483 printf(" return(0);\n");
490 /*++++++++++++++++++++++++++++++++++++++
491 A function to return a safe C identifier from an XML tag or attribute name.
493 char *safe Returns the safe name in a private string (only use once).
495 const char *name The name to convert.
496 ++++++++++++++++++++++++++++++++++++++*/
498 static char *safe(const char *name)
500 static char *safe=NULL;
503 safe=realloc(safe,strlen(name)+1);