📄 ne_xml.c
字号:
if (state > 0) elm->state = state; else if (state == NE_XML_DECLINE) /* prune this branch. */ p->prune++; else /* state == NE_XML_ABORT */ p->valid = 0;}/* Destroys an element structure. */static void destroy_element(struct element *elm) { struct namespace *this_ns, *next_ns; ne_free(elm->name); /* Free the namespaces */ this_ns = elm->nspaces; while (this_ns != NULL) { next_ns = this_ns->next; ne_free(this_ns->name); ne_free(this_ns->uri); ne_free(this_ns); this_ns = next_ns; }; if (elm->default_ns) ne_free(elm->default_ns); ne_free(elm);}/* cdata SAX callback */static void char_data(void *userdata, const ne_xml_char *data, int len) { ne_xml_parser *p = userdata; struct element *elm = p->current; if (!p->valid || p->prune) return; if (elm->handler->cdata_cb && elm->handler->cdata_cb(elm->handler->userdata, elm->state, data, len)) { NE_DEBUG(NE_DBG_XML, "Cdata callback failed.\n"); p->valid = 0; } }/* Called with the end of an element */static void end_element(void *userdata, const ne_xml_char *name) { ne_xml_parser *p = userdata; struct element *elm = p->current; if (!p->valid) return; if (p->prune) { if (p->prune-- > 1) return; } else if (elm->handler->endelm_cb && elm->handler->endelm_cb(elm->handler->userdata, elm->state, elm->nspace, elm->name)) { NE_DEBUG(NE_DBG_XML, "XML: end-element for %d failed.\n", elm->state); p->valid = 0; } NE_DEBUG(NE_DBG_XMLPARSE, "XML: end-element (%d, {%s, %s})\n", elm->state, elm->nspace, elm->name); /* move back up the tree */ p->current = elm->parent; p->prune = 0; destroy_element(elm);}/* Find a namespace definition for 'prefix' in given element, where * length of prefix is 'pfxlen'. Returns the URI or NULL. */static const char *resolve_nspace(const struct element *elm, const char *prefix, size_t pfxlen){ const struct element *s; /* Search up the tree. */ for (s = elm; s != NULL; s = s->parent) { const struct namespace *ns; /* Iterate over defined spaces on this node. */ for (ns = s->nspaces; ns != NULL; ns = ns->next) { if (strlen(ns->name) == pfxlen && memcmp(ns->name, prefix, pfxlen) == 0) return ns->uri; } } return NULL;}ne_xml_parser *ne_xml_create(void) { ne_xml_parser *p = ne_calloc(sizeof *p); /* Initialize other stuff */ p->valid = 1; /* Placeholder for the root element */ p->current = p->root = ne_calloc(sizeof *p->root); p->root->default_ns = ""; p->root->state = 0; strcpy(p->error, _("Unknown error"));#ifdef HAVE_EXPAT p->parser = XML_ParserCreate(NULL); if (p->parser == NULL) { abort(); } XML_SetElementHandler(p->parser, start_element, end_element); XML_SetCharacterDataHandler(p->parser, char_data); XML_SetUserData(p->parser, (void *) p); XML_SetXmlDeclHandler(p->parser, decl_handler);#else p->parser = xmlCreatePushParserCtxt(&sax_handler, (void *)p, NULL, 0, NULL); if (p->parser == NULL) { abort(); } p->parser->replaceEntities = 1;#endif return p;}void ne_xml_push_handler(ne_xml_parser *p, ne_xml_startelm_cb *startelm_cb, ne_xml_cdata_cb *cdata_cb, ne_xml_endelm_cb *endelm_cb, void *userdata){ struct handler *hand = ne_calloc(sizeof(struct handler)); hand->startelm_cb = startelm_cb; hand->cdata_cb = cdata_cb; hand->endelm_cb = endelm_cb; hand->userdata = userdata; /* If this is the first handler registered, update the * base pointer too. */ if (p->top_handlers == NULL) { p->root->handler = hand; p->top_handlers = hand; } else { p->top_handlers->next = hand; p->top_handlers = hand; }}void ne_xml_parse_v(void *userdata, const char *block, size_t len) { ne_xml_parser *p = userdata; /* FIXME: The two XML parsers break all our nice abstraction by * choosing different char *'s. The swine. This cast will come * back and bite us someday, no doubt. */ ne_xml_parse(p, block, len);}/* Parse the given block of input of length len */void ne_xml_parse(ne_xml_parser *p, const char *block, size_t len) { int ret, flag; /* duck out if it's broken */ if (!p->valid) { NE_DEBUG(NE_DBG_XML, "Not parsing %" NE_FMT_SIZE_T " bytes.\n", len); return; } if (len == 0) { flag = -1; block = ""; NE_DEBUG(NE_DBG_XML, "Got 0-length buffer, end of document.\n"); } else { NE_DEBUG(NE_DBG_XML, "Parsing %" NE_FMT_SIZE_T " length buffer.\n", len); flag = 0; } /* Note, don't write a parser error if !p->valid, since an error * will already have been written in that case. */#ifdef HAVE_EXPAT ret = XML_Parse(p->parser, block, len, flag); NE_DEBUG(NE_DBG_XMLPARSE, "XML_Parse returned %d\n", ret); if (ret == 0 && p->valid) { ne_snprintf(p->error, ERR_SIZE, "XML parse error at line %d: %s", XML_GetCurrentLineNumber(p->parser), XML_ErrorString(XML_GetErrorCode(p->parser))); p->valid = 0; }#else ret = xmlParseChunk(p->parser, block, len, flag); NE_DEBUG(NE_DBG_XMLPARSE, "xmlParseChunk returned %d\n", ret); /* Parse errors are normally caught by the sax_error() callback, * which clears p->valid. */ if (p->parser->errNo && p->valid) { ne_snprintf(p->error, ERR_SIZE, "XML parse error at line %d.", ne_xml_currentline(p)); p->valid = 0; }#endif}int ne_xml_valid(ne_xml_parser *p){ return p->valid;}void ne_xml_destroy(ne_xml_parser *p) { struct element *elm, *parent; struct handler *hand, *next; /* Free up the handlers on the stack: the root element has the * pointer to the base of the handler stack. */ for (hand = p->root->handler; hand!=NULL; hand=next) { next = hand->next; ne_free(hand); } /* Clean up remaining elements */ for (elm = p->current; elm != p->root; elm = parent) { parent = elm->parent; destroy_element(elm); } /* free root element */ ne_free(p->root);#ifdef HAVE_EXPAT XML_ParserFree(p->parser); if (p->encoding) ne_free(p->encoding);#else xmlFreeParserCtxt(p->parser);#endif ne_free(p);}void ne_xml_set_error(ne_xml_parser *p, const char *msg){ ne_snprintf(p->error, ERR_SIZE, "%s", msg);}#ifdef HAVE_LIBXMLstatic void sax_error(void *ctx, const char *msg, ...){ ne_xml_parser *p = ctx; va_list ap; char buf[1024]; va_start(ap, msg); ne_vsnprintf(buf, 1024, msg, ap); va_end(ap); ne_snprintf(p->error, ERR_SIZE, _("XML parse error at line %d: %s."), p->parser->input->line, buf); p->valid = 0;}#endifconst char *ne_xml_get_error(ne_xml_parser *p){ return p->error;}const char *ne_xml_get_attr(ne_xml_parser *p, const char **attrs, const char *nspace, const char *name){ int n; for (n = 0; attrs[n] != NULL; n += 2) { char *pnt = strchr(attrs[n], ':'); if (!nspace && !pnt && strcmp(attrs[n], name) == 0) { return attrs[n+1]; } else if (nspace && pnt) { /* If a namespace is given, and the local part matches, * then resolve the namespace and compare that too. */ if (strcmp(pnt + 1, name) == 0) { const char *uri = resolve_nspace(p->current, attrs[n], pnt - attrs[n]); if (uri && strcmp(uri, nspace) == 0) return attrs[n+1]; } } } return NULL;}int ne_xml_mapid(const struct ne_xml_idmap map[], size_t maplen, const char *nspace, const char *name){ size_t n; for (n = 0; n < maplen; n++) if (strcmp(name, map[n].name) == 0 && strcmp(nspace, map[n].nspace) == 0) return map[n].id; return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -