/* * (c) 2020 Vincenzo "KatolaZ" Nicosia * * A simple xml-to-tsv 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 #include "xml.h" #include "config.h" /* tag stack */ typedef struct { int top; char st[DEPTH_MAX][STR_MAX]; } tstack_t; int stack_empty(tstack_t *t){ return (t->top < 0); } int stack_push(tstack_t *t, const char *c){ if (t->top < DEPTH_MAX){ t->top ++; strncpy(t->st[t->top], c, STR_MAX - 1); t->st[t->top][STR_MAX - 1] = '\0'; return 0; } return -1; } char* stack_pop(tstack_t *t){ if (!stack_empty(t)) return t->st[t->top--]; return NULL; } char* stack_peek(tstack_t *t){ if (!stack_empty(t)) return t->st[t->top]; return NULL; } void stack_init(tstack_t *t){ t->top = -1; } /* utility functions */ /* quote_print: quote \\, \n, \t, and strip other ctrl chars */ void quote_print(FILE *f, const char *s){ const char *tmp = s; size_t len; int i; while (*tmp != '\0'){ len = strcspn(tmp, "\\\n\t"); for(i=0; i 0){ fprintf(f, "\\n"); } tmp ++; break; case '\t': fprintf(f, "\\t"); tmp ++; break; case '\r': fprintf(f, "\\r"); tmp ++; break; case '\\': fprintf(f, "\\\\"); tmp ++; break; } } } 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("%s", v); } void xmlattrentity(XMLParser *x, const char *t, size_t tl, const char *a, size_t al, const char *v, size_t vl) { char buf[16]; int n; if ((n = xml_entitytostr(v, buf, sizeof(buf))) > 0) xmlattr(x, t, tl, a, al, buf, (size_t)n); else xmlattr(x, t, tl, a, al, v, vl); } 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) { printf("%c%s%c", SEP, a, SATTR); } void xmlcdatastart(XMLParser *x) { printf("%c", SEP); } void xmlcdata(XMLParser *x, const char *d, size_t dl) { quote_print(stdout, 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) { quote_print(stdout, d); } void xmldataend(XMLParser *x) { } void xmldataentity(XMLParser *x, const char *d, size_t dl) { char buf[16]; int n; if ((n = xml_entitytostr(d, buf, sizeof(buf))) > 0) xmldata(x, buf, (size_t)n); else xmldata(x, d, dl); } void xmldatastart(XMLParser *x) { printf("%c", SEP); } 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); } if (isshort) { printf("\n"); print_cur_str(stdout, &st); } } 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"); if (! stack_empty(&st)) { fprintf(stderr, "Error: tags still open at EOF: "); print_cur_str(stderr, &st); fprintf(stderr, "\n"); } return 0; }