📄 xml.c
字号:
} return NULL;}char *iks_find_cdata(iks *x, const char *name){ iks *y; y = iks_find(x, name); if(!y) return(NULL); y = y->children; if(!y) return(NULL); return y->cdata;}char *iks_find_attrib(iks *x, const char *name){ iks *y; if(!x) return(NULL); y = x->attribs; while(y) { if(iks_strcmp(y->name, name) == 0) return(y->cdata); y = y->next; } return NULL;}/***** Node Information *****/ikspool *iks_pool(iks *x){ if(x) return(x->p); return NULL;}enum ikstype iks_type(iks *x){ if(x) return(x->type); return IKS_NONE;}char *iks_name(iks *x){ if(x) return(x->name); return NULL;}char *iks_cdata(iks *x){ if(x) return(x->cdata); return NULL;}int iks_cdata_size(iks *x){ if(x) return(x->len); return 0;}int iks_has_children(iks *x){ if(x && x->children) return(1); return 0;}int iks_has_attribs(iks *x){ if(x && x->attribs) return(1); return 0;}/***** Special *****/ikstr *iks_string(ikspool *p, iks *x){ ikstr *s; int level=0, dir=0; iks *y; if(!x || x->type != IKS_TAG) return(NULL); s = iks_str_new(p); if(!s) return(NULL); p = s->p; while(1) { if(dir==0) { if(x->type == IKS_TAG) { iks *y; iks_str_add(s, "<"); iks_str_add(s, x->name); y = x->attribs; while(y) { iks_spool(s, " ", y->name, "='", iks_escape(p, y->cdata, y->len), "'", s); y = y->next; } if(x->children) { iks_str_add(s, ">"); x = x->children; level++; continue; } else iks_str_add(s, "/>"); } else iks_str_add(s, iks_escape(p, x->cdata, x->len)); } y = x->next; if(!y) { x = x->parent; level--; if(level >= 0) iks_spool(s, "</", x->name, ">", s); if(level < 1) break; dir = 1; } else { x = y; dir = 0; } } return s;}/***** dom parsers *****/static void dom_tstart(iksparser *prs, char *tag, char **atts);static void dom_tend(iksparser *prs, char *tag);static void hook_cdata(iksparser *prs, char *data, int len);iksparser *iks_sax_new(void *udata, iksTagStart *ts, iksTagEnd *te, iksCharData *cd){ iksparser *prs; prs = malloc(sizeof(iksparser)); if(!prs) return(NULL); memset(prs, 0, sizeof(iksparser));#ifdef USE_EXPAT prs->expat = XML_ParserCreate(NULL); if(!prs->expat) { free(prs); return NULL; } XML_SetUserData(prs->expat, (void *)prs); XML_SetElementHandler(prs->expat, (XML_StartElementHandler)ts, (XML_EndElementHandler)te); XML_SetCharacterDataHandler(prs->expat, (XML_CharacterDataHandler)cd);#endif prs->udata = udata; prs->udata2 = udata; prs->tagStart = ts; prs->tagEnd = te; prs->charData = cd; return prs;}iksparser *iks_dom_new(iks **iksptr){ iksparser *prs; prs = iks_sax_new(NULL, (iksTagStart *)dom_tstart, (iksTagEnd *)dom_tend, (iksCharData *)hook_cdata); if(!prs) return(NULL); prs->udata = prs; prs->iksptr = iksptr; return prs;}#ifdef USE_EXPATint iks_parse(iksparser *prs, char *data, int len, int finish){ if(XML_Parse(prs->expat, data, len, 0)) return IKS_RET_OK; return IKS_RET_BADXML;}#endifvoid iks_parser_delete(iksparser *prs){#ifdef USE_EXPAT XML_ParserFree(prs->expat);#endif free(prs);}/***** Internal Hooks *****/static void insert_attribs(iksparser* p, iks *x, char **atts){ int i=0; if(!x || !atts) return; while(atts[i]) { iks_insert_attrib(x, atts[i], atts[i+1]); i += 2; }}static void dom_tstart(iksparser *prs, char *tag, char **atts){ iks *x; /* FIX ME: handle PIs in parser */ if(tag[0] == '?') return; if(prs->current) x = iks_insert(prs->current, tag); else x = iks_new(tag); insert_attribs(prs, x, atts); prs->current = x;}static void dom_tend(iksparser *prs, char *tag){ iks *x; x = iks_parent(prs->current); if(x) prs->current = x; else *(prs->iksptr) = prs->current;}static void hook_cdata(iksparser *prs, char *data, int len){ if(prs->current) iks_insert_cdata(prs->current, data, len);}/***** sax parser *****/enum contexts{ C_CDATA = 0, C_TAG, C_ATTRIBUTE, C_VALUE, C_WHITESPACE, C_ENTITY, C_COMMENT, C_MARKUP, C_PI};static int parse_xml(iksparser *prs, char *buf, int len);/* following function sucks, it is lame,** but as long as it works, i don't care** -madcat (ode to lazy coder) */int iks_parse(iksparser *prs, char *data, int len, int finish){ char *buf; int diff; if(!data || len == 0) return(IKS_RET_OK); if(len == -1) len = strlen(data); if(prs->buffer) { buf = malloc(prs->buflen + len); if(!buf) return(IKS_RET_NOMEM); memcpy(buf, prs->buffer, prs->buflen); memcpy(buf + prs->buflen, data, len); diff = (int)buf - (int)prs->buffer; if(prs->tagname) prs->tagname += diff; if(prs->atts) { int i = 0; while(i < (prs->attmax * 2)) { if(prs->atts[i]) prs->atts[i] += diff; i++; } } free(prs->buffer); prs->buffer = buf; buf += prs->buflen; prs->buflen += len; } else { buf = malloc(len); if(!buf) return(IKS_RET_NOMEM); memcpy(buf, data, len); prs->buffer = buf; prs->buflen = len; } parse_xml(prs, buf, len); return IKS_RET_OK;}static int parse_xml(iksparser *prs, char *buf, int len){ int pos = 0, old = 0; while(pos < len) { switch(prs->context) { case C_CDATA: if(buf[pos] == '&') { prs->context = C_ENTITY; buf[pos] = '\0'; if(prs->charData) (prs->charData)(prs->udata, &buf[old], pos - old); prs->entpos = 0; } if(buf[pos] == '<') { if(old < pos) { buf[pos] = '\0'; if(prs->charData) (prs->charData)(prs->udata, &buf[old], pos - old); old = pos + 1; } prs->minpos = pos; prs->oldcontext = C_CDATA; prs->context = C_TAG; } break; case C_TAG: if(!prs->tagname) { prs->tagname = buf + pos; if(buf[pos] == '/') { prs->tagflag = 2; prs->tagname++; break; } } if(buf[pos] == ' ' || buf[pos] == '\t' || buf[pos] == '\r' || buf[pos] == '\n') { buf[pos] = '\0'; prs->oldcontext = C_ATTRIBUTE; prs->context = C_WHITESPACE; break; } if(buf[pos] == '/') { buf[pos] = '\0'; prs->tagflag = 1; } if(buf[pos] == '>') { buf[pos] = '\0'; if(prs->tagStart && prs->tagflag != 2) (prs->tagStart)(prs->udata, prs->tagname, NULL); if(prs->tagEnd && prs->tagflag) (prs->tagEnd)(prs->udata, prs->tagname); prs->tagname = NULL; prs->tagflag = 0; prs->context = C_CDATA; old = pos + 1; prs->minpos = -1; } break; case C_ATTRIBUTE: if(!prs->atts) { prs->attmax = 6; prs->atts = malloc(sizeof(char *) * 2 * 6); if(!prs->atts) return(0); memset(prs->atts, 0, sizeof(char *) * 2 * 6); prs->attcur = 0; } else { if(prs->attcur >= (prs->attmax * 2)) { void *tmp; prs->attmax += 4; tmp = malloc(sizeof(char *) * 2 * prs->attmax); if(!tmp) return(0); memset(tmp, 0, sizeof(char *) * 2 * prs->attmax); memcpy(tmp, prs->atts, sizeof(char *) * (prs->attcur - 1)); free(prs->atts); prs->atts = tmp; } } if(!prs->atts[prs->attcur]) { prs->atts[prs->attcur] = buf + pos; } if(buf[pos] == '=') { buf[pos] = '\0'; prs->context = C_VALUE; break; } if(buf[pos] == '/') prs->tagflag = 1; if(buf[pos] == '>') { buf[pos] = '\0'; if(prs->atts) prs->atts[prs->attcur] = NULL; if(prs->tagStart) (prs->tagStart)(prs->udata, prs->tagname, prs->atts); free(prs->atts); prs->atts = NULL; prs->attcur = 0; if(prs->tagEnd && prs->tagflag) (prs->tagEnd)(prs->udata, prs->tagname); prs->tagname = NULL; prs->tagflag = 0; prs->context = C_CDATA; old = pos + 1; } break; case C_VALUE: if(buf[pos] == '\'' || buf[pos] == '"') { buf[pos] = '\0'; if(prs->valflag) { prs->valflag = 0; prs->oldcontext = C_ATTRIBUTE; prs->context = C_WHITESPACE; prs->attcur += 2; break; } prs->valflag = 1; prs->atts[prs->attcur + 1] = buf + pos + 1; } break; case C_WHITESPACE: if(buf[pos] != ' ' && buf[pos] != '\t' && buf[pos] != '\r' && buf[pos] != '\n') { prs->context = prs->oldcontext; pos--; } break; case C_ENTITY: if(buf[pos] != ';') { prs->entity[prs->entpos++] = buf[pos]; } else { char t = '?'; prs->entity[prs->entpos] = '\0'; if(strcmp(prs->entity, "amp") == 0) t = '&'; else if(strcmp(prs->entity, "quot") == 0) t = '"'; else if(strcmp(prs->entity, "apos") == 0) t = '\''; else if(strcmp(prs->entity, "lt") == 0) t = '<'; else if(strcmp(prs->entity, "gt") == 0) t = '>'; buf[pos] = t; old = pos; prs->context = C_CDATA; } break; case C_COMMENT: case C_MARKUP: case C_PI: break; } pos++; } if(prs->charData && prs->context == C_CDATA && old < pos) { (prs->charData)(prs->udata, &buf[old], pos - old); } return 1;}/***** load&save *****/iks *iks_load(char *fname){ iksparser *prs; iks *x = NULL; char *buf; FILE *f; int len, done = 0; if(!fname) return(NULL); buf = malloc(2048); if(buf) { prs = iks_dom_new(&x); if(prs) { f = fopen(fname, "r"); if(f) { while(!done) { len = fread(buf, 1, 2048, f); if(len < 2048) done = 1; iks_parse(prs, buf, len, done); } fclose(f); } iks_parser_delete(prs); } free(buf); } return x;}int iks_save(char *fname, iks *x){ FILE *f; ikstr *s; char *data; int ret; s = iks_string(NULL, x); data = iks_str_print(s); if(!data) return(0); f = fopen(fname, "w"); if(!f) { iks_str_delete(s); return 0; } ret = fputs(data, f); iks_str_delete(s); fclose(f); if(ret < 0) return(0); return 1;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -