Routino SVN Repository Browser

Check out the latest version of Routino: svn co http://routino.org/svn/trunk routino

ViewVC logotype

Contents of /trunk/src/xmlparse.l

Parent Directory Parent Directory | Revision Log Revision Log


Revision 368 - (show annotations) (download)
Thu Apr 22 17:53:42 2010 UTC (14 years, 11 months ago) by amb
File size: 23009 byte(s)
Restart properly so that a different file can be read.

1 %{
2 /***************************************
3 $Header: /home/amb/CVS/routino/src/xmlparse.l,v 1.9 2010-04-22 17:53:42 amb Exp $
4
5 A simple generic XML parser where the structure comes from the function parameters.
6 Not intended to be fully conforming to XML staandard or a validating parser but
7 sufficient to parse OSM XML and simple program configuration files.
8
9 Part of the Routino routing software.
10 ******************/ /******************
11 This file Copyright 2010 Andrew M. Bishop
12
13 This program is free software: you can redistribute it and/or modify
14 it under the terms of the GNU Affero General Public License as published by
15 the Free Software Foundation, either version 3 of the License, or
16 (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU Affero General Public License for more details.
22
23 You should have received a copy of the GNU Affero General Public License
24 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 ***************************************/
26
27
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <ctype.h>
31 #include <string.h>
32
33 #include "xmlparse.h"
34
35
36 /* Parser outputs */
37
38 #define LEX_EOF 0
39
40 #define LEX_TAG_BEGIN 1
41 #define LEX_XML_DECL_BEGIN 2
42 #define LEX_TAG_POP 3
43 #define LEX_TAG_PUSH 4
44 #define LEX_XML_DECL_FINISH 6
45 #define LEX_TAG_FINISH 7
46 #define LEX_ATTR_KEY 8
47 #define LEX_ATTR_VAL 9
48
49 #define LEX_ERROR 100
50
51 #define LEX_ERROR_TAG_START 101
52 #define LEX_ERROR_XML_DECL_START 102
53 #define LEX_ERROR_TAG 103
54 #define LEX_ERROR_XML_DECL 104
55 #define LEX_ERROR_ATTR 105
56 #define LEX_ERROR_END_TAG 106
57 #define LEX_ERROR_COMMENT 107
58 #define LEX_ERROR_CLOSE 108
59 #define LEX_ERROR_ATTR_VAL 109
60 #define LEX_ERROR_ENTITY_REF 110
61 #define LEX_ERROR_CHAR_REF 111
62
63 #define LEX_ERROR_UNEXP_TAG 201
64 #define LEX_ERROR_UNBALANCED 202
65 #define LEX_ERROR_NO_START 203
66 #define LEX_ERROR_UNEXP_ATT 204
67 #define LEX_ERROR_UNEXP_EOF 205
68 #define LEX_ERROR_XML_NOT_FIRST 206
69
70 #define LEX_ERROR_CALLBACK 255
71
72
73 /* Lexer definitions */
74
75 #define YY_SKIP_YYWRAP 1 /* Remove error with prototype of ..._yywrap */
76 #ifndef yywrap
77 /*+ Needed in lex but does nothing. +*/
78 #define yywrap() 1
79 #endif
80
81 /*+ Reset the current string. +*/
82 #define reset_string \
83 if(string) *string=0; \
84 stringused=0;
85
86 /*+ append information to the current string. +*/
87 #define append_string(xx) \
88 newlen=strlen(xx); \
89 if((stringused+newlen)>=stringlen) \
90 string=(char*)realloc((void*)string,stringlen=(stringused+newlen+16)); \
91 strcpy(string+stringused,xx); \
92 stringused+=newlen;
93
94 #define YY_NO_INPUT
95
96
97 /* Lexer functions and variables */
98
99 extern int yylex(void);
100
101 static char *yylval=NULL;
102
103 %}
104
105 %option 8bit
106 %option pointer
107 %option batch
108 %option yylineno
109
110 %option nodefault
111 %option perf-report
112 %option fast
113 %option nounput
114
115
116 /* Grammar based on http://www.w3.org/TR/2004/REC-xml-20040204/ but for ASCII not Unicode. */
117
118 S [ \t\r\n]
119
120 letter [a-zA-Z]
121 digit [0-9]
122 xdigit [a-fA-F0-9]
123
124 namechar ({letter}|{digit}|[-._:])
125 name ({letter}|[_:]){namechar}*
126
127 entityref &{name};
128 charref &#({digit}+|x{xdigit}+);
129
130
131 %x COMMENT
132 %x CDATA
133 %x DOCTYPE
134 %x XML_DECL_START XML_DECL
135 %x TAG_START TAG
136 %x ATTR_KEY ATTR_VAL
137 %x END_TAG1 END_TAG2
138 %x DQUOTED SQUOTED
139
140 %%
141 /* Must use static variables since the parser returns often. */
142 static char *string=NULL;
143 static int stringlen=0,stringused=0;
144 static int after_attr=0;
145 int newlen;
146 int doctype_depth=0;
147
148 /* Handle top level entities */
149
150 "<!--" { BEGIN(COMMENT); }
151 "<![CDATA[" { BEGIN(CDATA); }
152 "<!DOCTYPE" { BEGIN(DOCTYPE); doctype_depth=0; }
153 "</" { BEGIN(END_TAG1); }
154 "<?" { BEGIN(XML_DECL_START); }
155 "<" { BEGIN(TAG_START); }
156 ">" { return(LEX_ERROR_CLOSE); }
157 [^<>]+ { }
158
159 /* Comments */
160
161 <COMMENT>"--->" { return(LEX_ERROR_COMMENT); }
162 <COMMENT>"-->" { BEGIN(INITIAL); }
163 <COMMENT>"--"[^->]+ { }
164 <COMMENT>[^-]+ { }
165 <COMMENT>"-" { }
166
167 /* CDATA */
168
169 <CDATA>"]]>" { BEGIN(INITIAL); }
170 <CDATA>"]" { }
171 <CDATA>[^]]+ { }
172
173 /* CDATA */
174
175 <DOCTYPE>"<" { doctype_depth++; }
176 <DOCTYPE>">" { if(doctype_depth==0) BEGIN(INITIAL); else doctype_depth--; }
177 <DOCTYPE>[^<>]+ { }
178
179 /* XML Declaration start */
180
181 <XML_DECL_START>{name} { BEGIN(XML_DECL); yylval=yytext; return(LEX_XML_DECL_BEGIN); }
182 <XML_DECL_START>.|\n { return(LEX_ERROR_XML_DECL_START); }
183
184 /* Tag middle */
185
186 <XML_DECL>"?>" { BEGIN(INITIAL); return(LEX_XML_DECL_FINISH); }
187 <XML_DECL>{S}+ { }
188 <XML_DECL>{name} { after_attr=XML_DECL; BEGIN(ATTR_KEY); yylval=yytext; return(LEX_ATTR_KEY); }
189 <XML_DECL>.|\n { return(LEX_ERROR_XML_DECL); }
190
191 /* Any tag start */
192
193 <TAG_START>{name} { BEGIN(TAG); yylval=yytext; return(LEX_TAG_BEGIN); }
194 <TAG_START>.|\n { return(LEX_ERROR_TAG_START); }
195
196 /* End-tag start */
197
198 <END_TAG1>{name} { BEGIN(END_TAG2); yylval=yytext; return(LEX_TAG_POP); }
199 <END_TAG1>.|\n { return(LEX_ERROR_END_TAG); }
200
201 <END_TAG2>">" { BEGIN(INITIAL); }
202 <END_TAG2>.|\n { return(LEX_ERROR_END_TAG); }
203
204 /* Any tag middle */
205
206 <TAG>"/>" { BEGIN(INITIAL); return(LEX_TAG_FINISH); }
207 <TAG>">" { BEGIN(INITIAL); return(LEX_TAG_PUSH); }
208 <TAG>{S}+ { }
209 <TAG>{name} { after_attr=TAG; BEGIN(ATTR_KEY); yylval=yytext; return(LEX_ATTR_KEY); }
210 <TAG>.|\n { return(LEX_ERROR_TAG); }
211
212 /* Attributes */
213
214 <ATTR_KEY>= { BEGIN(ATTR_VAL); }
215 <ATTR_KEY>.|\n { return(LEX_ERROR_ATTR); }
216
217 <ATTR_VAL>\" { BEGIN(DQUOTED); reset_string; }
218 <ATTR_VAL>\' { BEGIN(SQUOTED); reset_string; }
219 <ATTR_VAL>.|\n { return(LEX_ERROR_ATTR); }
220
221 /* Quoted strings */
222
223 <DQUOTED>\" { BEGIN(after_attr); yylval=string; return(LEX_ATTR_VAL); }
224 <DQUOTED>{entityref} { const char *str=ParseXML_Decode_Entity_Ref(yytext); if(str) {append_string(str);} else {yylval=yytext; return(LEX_ERROR_ENTITY_REF);} }
225 <DQUOTED>{charref} { const char *str=ParseXML_Decode_Char_Ref(yytext); if(str) {append_string(str);} else {yylval=yytext; return(LEX_ERROR_CHAR_REF);} }
226 <DQUOTED>[<>&] { yylval=yytext; return(LEX_ERROR_ATTR_VAL); }
227 <DQUOTED>[^<>&\"]+ { append_string(yytext); }
228
229 <SQUOTED>\' { BEGIN(after_attr); yylval=string; return(LEX_ATTR_VAL); }
230 <SQUOTED>{entityref} { const char *str=ParseXML_Decode_Entity_Ref(yytext); if(str) {append_string(str);} else {yylval=yytext; return(LEX_ERROR_ENTITY_REF);} }
231 <SQUOTED>{charref} { const char *str=ParseXML_Decode_Char_Ref(yytext); if(str) {append_string(str);} else {yylval=yytext; return(LEX_ERROR_CHAR_REF);} }
232 <SQUOTED>[<>&] { yylval=yytext; return(LEX_ERROR_ATTR_VAL); }
233 <SQUOTED>[^<>&\']+ { append_string(yytext); }
234
235 /* End of file */
236
237 <<EOF>> { free(string); string=NULL; stringlen=stringused=0; BEGIN(INITIAL); return(LEX_EOF); }
238
239 %%
240
241
242 /*++++++++++++++++++++++++++++++++++++++
243 A function to call the callback function with the parameters needed.
244
245 int call_callback Returns 1 if the callback returned with an error.
246
247 const char *name The name of the tag.
248
249 int (*callback)() The callback function.
250
251 int type The type of tag (start and/or end).
252
253 int nattributes The number of attributes collected.
254
255 char *attributes[XMLPARSE_MAX_ATTRS] The list of attributes.
256 ++++++++++++++++++++++++++++++++++++++*/
257
258 static inline int call_callback(const char *name,int (*callback)(),int type,int nattributes,char *attributes[XMLPARSE_MAX_ATTRS])
259 {
260 switch(nattributes)
261 {
262 case 0: return (*callback)(type);
263 case 1: return (*callback)(type,attributes[0]);
264 case 2: return (*callback)(type,attributes[0],attributes[1]);
265 case 3: return (*callback)(type,attributes[0],attributes[1],attributes[2]);
266 case 4: return (*callback)(type,attributes[0],attributes[1],attributes[2],attributes[3]);
267 case 5: return (*callback)(type,attributes[0],attributes[1],attributes[2],attributes[3],attributes[4]);
268 case 6: return (*callback)(type,attributes[0],attributes[1],attributes[2],attributes[3],attributes[4],attributes[5]);
269 case 7: return (*callback)(type,attributes[0],attributes[1],attributes[2],attributes[3],attributes[4],attributes[5],attributes[6]);
270 case 8: return (*callback)(type,attributes[0],attributes[1],attributes[2],attributes[3],attributes[4],attributes[5],attributes[6],attributes[7]);
271 case 9: return (*callback)(type,attributes[0],attributes[1],attributes[2],attributes[3],attributes[4],attributes[5],attributes[6],attributes[7],attributes[8]);
272 case 10: return (*callback)(type,attributes[0],attributes[1],attributes[2],attributes[3],attributes[4],attributes[5],attributes[6],attributes[7],attributes[8],attributes[9]);
273 case 11: return (*callback)(type,attributes[0],attributes[1],attributes[2],attributes[3],attributes[4],attributes[5],attributes[6],attributes[7],attributes[8],attributes[9],attributes[10]);
274 case 12: return (*callback)(type,attributes[0],attributes[1],attributes[2],attributes[3],attributes[4],attributes[5],attributes[6],attributes[7],attributes[8],attributes[9],attributes[10],attributes[11]);
275 case 13: return (*callback)(type,attributes[0],attributes[1],attributes[2],attributes[3],attributes[4],attributes[5],attributes[6],attributes[7],attributes[8],attributes[9],attributes[10],attributes[11],attributes[12]);
276 case 14: return (*callback)(type,attributes[0],attributes[1],attributes[2],attributes[3],attributes[4],attributes[5],attributes[6],attributes[7],attributes[8],attributes[9],attributes[10],attributes[11],attributes[12],attributes[13]);
277 case 15: return (*callback)(type,attributes[0],attributes[1],attributes[2],attributes[3],attributes[4],attributes[5],attributes[6],attributes[7],attributes[8],attributes[9],attributes[10],attributes[11],attributes[12],attributes[13],attributes[14]);
278 case 16: return (*callback)(type,attributes[0],attributes[1],attributes[2],attributes[3],attributes[4],attributes[5],attributes[6],attributes[7],attributes[8],attributes[9],attributes[10],attributes[11],attributes[12],attributes[13],attributes[14],attributes[15]);
279
280 default:
281 fprintf(stderr,"XML Parser: Error on line %d: too many attributes for tag '%s' source code needs changing.\n",yylineno,name);
282 exit(1);
283 }
284 }
285
286
287 /*++++++++++++++++++++++++++++++++++++++
288 Parse the XML and call the functions for each tag as seen.
289
290 int ParseXML Returns 0 if OK or something else in case of an error.
291
292 FILE *file The file to parse.
293
294 xmltag **tags The array of pointers to tags for the top level.
295
296 int options A list of XML Parser options OR-ed together.
297 ++++++++++++++++++++++++++++++++++++++*/
298
299 int ParseXML(FILE *file,xmltag **tags,int options)
300 {
301 int yychar,i;
302
303 char *attributes[XMLPARSE_MAX_ATTRS]={NULL};
304 int attribute=0;
305
306 int stackdepth=0,stackused=0;
307 xmltag ***tags_stack=NULL;
308 xmltag **tag_stack=NULL;
309 xmltag *tag=NULL;
310
311 /* The actual parser. */
312
313 yyin=file;
314
315 yyrestart(yyin);
316
317 BEGIN(INITIAL);
318
319 do
320 {
321 yychar=yylex();
322
323 switch(yychar)
324 {
325 /* The start of a tag for an XML declaration */
326
327 case LEX_XML_DECL_BEGIN:
328
329 if(tag_stack)
330 {
331 fprintf(stderr,"XML Parser: Error on line %d: XML declaration not before all other tags.\n",yylineno);
332 yychar=LEX_ERROR_XML_NOT_FIRST;
333 break;
334 }
335
336 /* The start of a tag for an element */
337
338 case LEX_TAG_BEGIN:
339
340 tag=NULL;
341
342 for(i=0;tags[i];i++)
343 if(!strcasecmp(yylval,tags[i]->name))
344 {
345 tag=tags[i];
346
347 for(i=0;i<tag->nattributes;i++)
348 if(attributes[i])
349 {
350 free(attributes[i]);
351 attributes[i]=NULL;
352 }
353
354 break;
355 }
356
357 if(tag==NULL)
358 {
359 fprintf(stderr,"XML Parser: Error on line %d: unexpected tag '%s'.\n",yylineno,yylval);
360 yychar=LEX_ERROR_UNEXP_TAG;
361 }
362
363 break;
364
365 /* The end of the start-tag for an element */
366
367 case LEX_TAG_PUSH:
368
369 if(stackused==stackdepth)
370 {
371 tag_stack =(xmltag**) realloc((void*)tag_stack ,(stackdepth+=8)*sizeof(xmltag*));
372 tags_stack=(xmltag***)realloc((void*)tags_stack,(stackdepth+=8)*sizeof(xmltag**));
373 }
374
375 tag_stack [stackused]=tag;
376 tags_stack[stackused]=tags;
377 stackused++;
378
379 if(tag->callback)
380 if(call_callback(tag->name,tag->callback,XMLPARSE_TAG_START,tag->nattributes,attributes))
381 yychar=LEX_ERROR_CALLBACK;
382
383 tags=tag->subtags;
384
385 break;
386
387 /* The end of the empty-element-tag for an XML declaration */
388
389 case LEX_XML_DECL_FINISH:
390
391 /* The end of the empty-element-tag for an element */
392
393 case LEX_TAG_FINISH:
394
395 if(tag->callback)
396 if(call_callback(tag->name,tag->callback,XMLPARSE_TAG_START|XMLPARSE_TAG_END,tag->nattributes,attributes))
397 yychar=LEX_ERROR_CALLBACK;
398
399 if(stackused>0)
400 tag=tag_stack[stackused-1];
401 else
402 tag=NULL;
403
404 break;
405
406 /* The end of the end-tag for an element */
407
408 case LEX_TAG_POP:
409
410 stackused--;
411 tags=tags_stack[stackused];
412 tag =tag_stack [stackused];
413
414 if(strcmp(tag->name,yylval))
415 {
416 fprintf(stderr,"XML Parser: Error on line %d: end tag '</%s>' doesn't match start tag '<%s ...>'.\n",yylineno,yylval,tag->name);
417 yychar=LEX_ERROR_UNBALANCED;
418 }
419
420 if(stackused<0)
421 {
422 fprintf(stderr,"XML Parser: Error on line %d: end tag '</%s>' seen but there was no start tag '<%s ...>'.\n",yylineno,yylval,yylval);
423 yychar=LEX_ERROR_NO_START;
424 }
425
426 for(i=0;i<tag->nattributes;i++)
427 if(attributes[i])
428 {
429 free(attributes[i]);
430 attributes[i]=NULL;
431 }
432
433 if(tag->callback)
434 if(call_callback(tag->name,tag->callback,XMLPARSE_TAG_END,tag->nattributes,attributes))
435 yychar=LEX_ERROR_CALLBACK;
436
437 if(stackused>0)
438 tag=tag_stack[stackused-1];
439 else
440 tag=NULL;
441
442 break;
443
444 /* An attribute key */
445
446 case LEX_ATTR_KEY:
447
448 attribute=-1;
449
450 for(i=0;i<tag->nattributes;i++)
451 if(!strcasecmp(yylval,tag->attributes[i]))
452 {
453 attribute=i;
454
455 break;
456 }
457
458 if(attribute==-1)
459 {
460 if((options&XMLPARSE_UNKNOWN_ATTRIBUTES)==XMLPARSE_UNKNOWN_ATTR_ERROR ||
461 ((options&XMLPARSE_UNKNOWN_ATTRIBUTES)==XMLPARSE_UNKNOWN_ATTR_ERRNONAME && !strchr(yylval,':')))
462 {
463 fprintf(stderr,"XML Parser: Error on line %d: unexpected attribute '%s' for tag '%s'.\n",yylineno,yylval,tag->name);
464 yychar=LEX_ERROR_UNEXP_ATT;
465 }
466 else if((options&XMLPARSE_UNKNOWN_ATTRIBUTES)==XMLPARSE_UNKNOWN_ATTR_WARN)
467 fprintf(stderr,"XML Parser: Warning on line %d: unexpected attribute '%s' for tag '%s'.\n",yylineno,yylval,tag->name);
468 }
469
470 break;
471
472 /* An attribute value */
473
474 case LEX_ATTR_VAL:
475
476 if(tag->callback && attribute!=-1 && yylval)
477 attributes[attribute]=strcpy(malloc(strlen(yylval)+1),yylval);
478
479 break;
480
481 /* End of file */
482
483 case LEX_EOF:
484
485 if(tag)
486 {
487 fprintf(stderr,"XML Parser: Error on line %d: end of file seen without end tag '</%s>'.\n",yylineno,tag->name);
488 yychar=LEX_ERROR_UNEXP_EOF;
489 }
490
491 break;
492
493 case LEX_ERROR_TAG_START:
494 fprintf(stderr,"XML Parser: Error on line %d: character '<' seen not at start of tag.\n",yylineno);
495 break;
496
497 case LEX_ERROR_XML_DECL_START:
498 fprintf(stderr,"XML Parser: Error on line %d: characters '<?' seen not at start of XML declaration.\n",yylineno);
499 break;
500
501 case LEX_ERROR_TAG:
502 fprintf(stderr,"XML Parser: Error on line %d: invalid character seen inside tag '<%s...>'.\n",yylineno,tag->name);
503 break;
504
505 case LEX_ERROR_XML_DECL:
506 fprintf(stderr,"XML Parser: Error on line %d: invalid character seen inside XML declaration '<?%s...>'.\n",yylineno,tag->name);
507 break;
508
509 case LEX_ERROR_ATTR:
510 fprintf(stderr,"XML Parser: Error on line %d: invalid attribute definition seen in tag.\n",yylineno);
511 break;
512
513 case LEX_ERROR_END_TAG:
514 fprintf(stderr,"XML Parser: Error on line %d: invalid character seen in end-tag.\n",yylineno);
515 break;
516
517 case LEX_ERROR_COMMENT:
518 fprintf(stderr,"XML Parser: Error on line %d: invalid comment seen.\n",yylineno);
519 break;
520
521 case LEX_ERROR_CLOSE:
522 fprintf(stderr,"XML Parser: Error on line %d: character '>' seen not at end of tag.\n",yylineno);
523 break;
524
525 case LEX_ERROR_ATTR_VAL:
526 fprintf(stderr,"XML Parser: Error on line %d: invalid character '%s' seen in attribute value.\n",yylineno,yylval);
527 break;
528
529 case LEX_ERROR_ENTITY_REF:
530 fprintf(stderr,"XML Parser: Error on line %d: invalid entity reference '%s' seen in attribute value.\n",yylineno,yylval);
531 break;
532
533 case LEX_ERROR_CHAR_REF:
534 fprintf(stderr,"XML Parser: Error on line %d: invalid character reference '%s' seen in attribute value.\n",yylineno,yylval);
535 break;
536 }
537 }
538 while(yychar>LEX_EOF && yychar<LEX_ERROR);
539
540 /* Delete the tagdata */
541
542 for(i=0;i<XMLPARSE_MAX_ATTRS;i++)
543 if(attributes[i])
544 free(attributes[i]);
545
546 if(stackdepth)
547 free(tags_stack);
548
549 return(yychar);
550 }
551
552
553 /*++++++++++++++++++++++++++++++++++++++
554 Return the current parser line number.
555
556 int ParseXML_LineNumber Returns the line number.
557 ++++++++++++++++++++++++++++++++++++++*/
558
559 int ParseXML_LineNumber(void)
560 {
561 return(yylineno);
562 }
563
564
565 /*++++++++++++++++++++++++++++++++++++++
566 Convert an XML entity reference into an ASCII string.
567
568 const char *ParseXML_Decode_Entity_Ref Returns a pointer to the replacement decoded string.
569
570 const char *string The entity reference string.
571 ++++++++++++++++++++++++++++++++++++++*/
572
573 const char *ParseXML_Decode_Entity_Ref(const char *string)
574 {
575 if(!strcmp(string,"&amp;")) return("&");
576 if(!strcmp(string,"&lt;")) return("<");
577 if(!strcmp(string,"&gt;")) return(">");
578 if(!strcmp(string,"&apos;")) return("'");
579 if(!strcmp(string,"&quot;")) return("\"");
580 return(NULL);
581 }
582
583
584 /*++++++++++++++++++++++++++++++++++++++
585 Convert an XML character reference into an ASCII string.
586
587 const char *ParseXML_Decode_Char_Ref Returns a pointer to the replacement decoded string.
588
589 const char *string The character reference string.
590 ++++++++++++++++++++++++++++++++++++++*/
591
592 const char *ParseXML_Decode_Char_Ref(const char *string)
593 {
594 static char result[2]=" ";
595 long int val;
596
597 if(string[2]=='x') val=strtol(string+3,NULL,16);
598 else val=strtol(string+2,NULL,10);
599
600 if(val<0 || val>255)
601 return(NULL);
602
603 result[0]=val&0xff;
604
605 return(result);
606 }
607
608
609 /*++++++++++++++++++++++++++++++++++++++
610 Convert a string into something that is safe to output in an XML file.
611
612 const char *ParseXML_Encode_Safe_XML Returns a pointer to the replacement encoded string (or the original if no change needed).
613
614 const char *string The string to convert.
615 ++++++++++++++++++++++++++++++++++++++*/
616
617 const char *ParseXML_Encode_Safe_XML(const char *string)
618 {
619 static const char hexstring[17]="0123456789ABCDEF";
620 int i=0,j=0,len;
621 char *result;
622
623 for(i=0;string[i];i++)
624 if(string[i]=='<' || string[i]=='>' || string[i]=='&' || string[i]=='\'' || string[i]=='"' || string[i]<32 || string[i]>126)
625 break;
626
627 if(!string[i])
628 return(string);
629
630 len=i+256-6;
631
632 result=(char*)malloc(len+7);
633 strncpy(result,string,i);
634
635 do
636 {
637 for(;j<len && string[i];i++)
638 if(string[i]=='<')
639 {
640 result[j++]='&';
641 result[j++]='l';
642 result[j++]='t';
643 result[j++]=';';
644 }
645 else if(string[i]=='>')
646 {
647 result[j++]='&';
648 result[j++]='g';
649 result[j++]='t';
650 result[j++]=';';
651 }
652 else if(string[i]=='&')
653 {
654 result[j++]='&';
655 result[j++]='a';
656 result[j++]='m';
657 result[j++]='p';
658 result[j++]=';';
659 }
660 else if(string[i]=='\'')
661 {
662 result[j++]='&';
663 result[j++]='a';
664 result[j++]='p';
665 result[j++]='o';
666 result[j++]='s';
667 result[j++]=';';
668 }
669 else if(string[i]=='"')
670 {
671 result[j++]='&';
672 result[j++]='q';
673 result[j++]='u';
674 result[j++]='o';
675 result[j++]='t';
676 result[j++]=';';
677 }
678 else if(string[i]<32 || string[i]>126)
679 {
680 result[j++]='&';
681 result[j++]='#';
682 result[j++]='x';
683 result[j++]=hexstring[(string[i]&0xf0)>>4];
684 result[j++]=hexstring[ string[i]&0x0f ];
685 result[j++]=';';
686 }
687 else
688 result[j++]=string[i];
689
690 if(string[i]) /* Not finished */
691 {
692 len+=256;
693 result=(char*)realloc((void*)result,len+7);
694 }
695 }
696 while(string[i]);
697
698 result[j]=0;
699
700 return(result);
701 }
702
703
704 /*++++++++++++++++++++++++++++++++++++++
705 Convert a string to a integer (checking that it really is a integer).
706
707 int ParseXML_GetInteger Returns 1 if a integer could be found or 0 otherwise.
708
709 const char *string The string to be parsed.
710
711 int *number Returns the number.
712 ++++++++++++++++++++++++++++++++++++++*/
713
714 int ParseXML_GetInteger(const char *string,int *number)
715 {
716 const char *p=string;
717
718 if(*p=='-' || *p=='+')
719 p++;
720
721 while(isdigit(*p))
722 p++;
723
724 if(*p)
725 return(0);
726
727 *number=atoi(string);
728
729 return(1);
730 }
731
732
733 /*++++++++++++++++++++++++++++++++++++++
734 Convert a string to a floating point number (checking that it really is a number).
735
736 int ParseXML_GetFloating Returns 1 if a number could be found or 0 otherwise.
737
738 const char *string The string to be parsed.
739
740 int *number Returns the number.
741 ++++++++++++++++++++++++++++++++++++++*/
742
743 int ParseXML_GetFloating(const char *string,double *number)
744 {
745 const char *p=string;
746
747 if(*p=='-' || *p=='+')
748 p++;
749
750 while(isdigit(*p) || *p=='.')
751 p++;
752
753 if(*p)
754 return(0);
755
756 *number=atof(string);
757
758 return(1);
759 }

Properties

Name Value
cvs:description A simple generic XML parser.