/* * (c) 2020 Vincenzo "KatolaZ" Nicosia * * A simple xml-to-rsv converter, based on xmlparser by Hiltjo Posthuma * http://codemadness.org/git/xmlparser/ * * You can use, distribute, modify, and/or redistribute this program under * the terms of the ISC LICENSE. See LICENSE for details. * */ #include #include #include #include "xml.h" #define STR_MAX 128 #define DEPTH_MAX 50 /* tag stack */ typedef struct { int top; char st[DEPTH_MAX][STR_MAX]; } tstack_t; int stack_push(tstack_t *t, const char *c){ if (t->top < DEPTH_MAX){ t->top ++; strncpy(t->st[t->top], c, STR_MAX); return 0; } return -1; } char* stack_pop(tstack_t *t){ if (t->top >= 0) return t->st[t->top--]; return NULL; } char* stack_peek(tstack_t *t){ if (t->top >= 0) return t->st[t->top]; return NULL; } int stack_empty(tstack_t *t){ return (t->top < 0); } void stack_init(tstack_t *t){ t->top = -1; } /* utility functions */ void print_no_cr(FILE *f, const char *c){ char *tmp = c; while (c != NULL){ tmp = strchr(c, '\n'); if (tmp != NULL) *tmp = '\0'; fprintf(f, "%s", c); if (tmp != NULL) c = tmp + 1; else c = NULL; } } void print_cur_str(FILE *f, tstack_t *t){ int i; for (i=0; i<=t->top; i++){ fprintf(f, "/%s", t->st[i]); } } /* global variables */ tstack_t st; /* xml callbacks */ void xmlattr(XMLParser *x, const char *t, size_t tl, const char *a, size_t al, const char *v, size_t vl) { printf("\t%s=%s", a, v); } void xmlattrentity(XMLParser *x, const char *t, size_t tl, const char *a, size_t al, const char *v, size_t vl) { printf("attrentity: %s\n", a); } void xmlattrend(XMLParser *x, const char *t, size_t tl, const char *a, size_t al) { } void xmlattrstart(XMLParser *x, const char *t, size_t tl, const char *a, size_t al) { } void xmlcdatastart(XMLParser *x) { } void xmlcdata(XMLParser *x, const char *d, size_t dl) { printf("\t%s", d); } void xmlcdataend(XMLParser *x) { } void xmlcommentstart(XMLParser *x) { } void xmlcomment(XMLParser *x, const char *c, size_t cl) { } void xmlcommentend(XMLParser *x) { } void xmldata(XMLParser *x, const char *d, size_t dl) { printf("\t"); print_no_cr(stdout, d); } void xmldataend(XMLParser *x) { } void xmldataentity(XMLParser *x, const char *d, size_t dl) { } void xmldatastart(XMLParser *x) { } void xmltagend(XMLParser *x, const char *t, size_t tl, int isshort) { char *tag; if (stack_empty(&st)){ fprintf(stderr, "Error: tag-end '%s' before any open tag", t); } tag = stack_pop(&st); if (strcmp(t, tag)){ fprintf(stderr, "Error: tag-end '%s' closes tag '%s'", t, tag); } /* printf("\n"); */ } void xmltagstart(XMLParser *x, const char *t, size_t tl) { if (stack_push(&st, t)){ fprintf(stderr, "Error: stack full. Ignoring tag '%s' (parent tag: '%s')\n", t, stack_peek(&st)); return; } printf("\n"); print_cur_str(stdout, &st); } void xmltagstartparsed(XMLParser *x, const char *t, size_t tl, int isshort) { /* printf("inside tagstartparsed\n"); */ } int main(void) { stack_init(&st); XMLParser x = { 0 }; x.xmlattr = xmlattr; x.xmlattrend = xmlattrend; x.xmlattrstart = xmlattrstart; x.xmlattrentity = xmlattrentity; x.xmlcdatastart = xmlcdatastart; x.xmlcdata = xmlcdata; x.xmlcdataend = xmlcdataend; x.xmlcommentstart = xmlcommentstart; x.xmlcomment = xmlcomment; x.xmlcommentend = xmlcommentend; x.xmldata = xmldata; x.xmldataend = xmldataend; x.xmldataentity = xmldataentity; x.xmldatastart = xmldatastart; x.xmltagend = xmltagend; x.xmltagstart = xmltagstart; x.xmltagstartparsed = xmltagstartparsed; x.getnext = getchar; xml_parse(&x); printf("\n"); return 0; }