⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ne_xml.c

📁 linux subdivision ying gai ke yi le ba
💻 C
📖 第 1 页 / 共 2 页
字号:
/*    Higher Level Interface to XML Parsers.   Copyright (C) 1999-2004, Joe Orton <joe@manyfish.co.uk>   This library is free software; you can redistribute it and/or   modify it under the terms of the GNU Library General Public   License as published by the Free Software Foundation; either   version 2 of the License, or (at your option) any later version.      This library is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU   Library General Public License for more details.   You should have received a copy of the GNU Library General Public   License along with this library; if not, write to the Free   Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,   MA 02111-1307, USA*/#include "config.h"#ifdef HAVE_STDLIB_H#include <stdlib.h>#endif#ifdef HAVE_STRING_H#include <string.h>#endif#ifdef HAVE_STRINGS_H#include <strings.h>#endif#include "ne_i18n.h"#include "ne_alloc.h"#include "ne_xml.h"#include "ne_utils.h"#include "ne_string.h"#if defined(HAVE_EXPAT)/* expat support: */#ifdef HAVE_XMLPARSE_H#include "xmlparse.h"#else#include <expat.h>#endiftypedef XML_Char ne_xml_char;#elif defined(HAVE_LIBXML)/* libxml2 support: */#include <libxml/xmlversion.h>#include <libxml/parser.h>typedef xmlChar ne_xml_char;#else /* not HAVE_LIBXML */#  error need an XML parser#endif /* not HAVE_EXPAT *//* Approx. one screen of text: */#define ERR_SIZE (2048)struct handler {    ne_xml_startelm_cb *startelm_cb; /* start-element callback */    ne_xml_endelm_cb *endelm_cb; /* end-element callback */    ne_xml_cdata_cb *cdata_cb; /* character-data callback. */    void *userdata; /* userdata for the above. */    struct handler *next; /* next handler in stack. */};#ifdef HAVE_LIBXMLstatic void sax_error(void *ctx, const char *msg, ...);#endifstruct element {    const ne_xml_char *nspace;    ne_xml_char *name;    int state; /* opaque state integer */        /* Namespaces declared in this element */    ne_xml_char *default_ns; /* A default namespace */    struct namespace *nspaces; /* List of other namespace scopes */    struct handler *handler; /* Handler for this element */    struct element *parent; /* parent element, or NULL */    };/* We pass around a ne_xml_parser as the userdata in the parsing * library.  This maintains the current state of the parse and various * other bits and bobs. Within the parse, we store the current branch * of the tree, i.e., the current element and all its parents, up to * the root, but nothing other than that.  */struct ne_xml_parser_s {    struct element *root; /* the root of the document */    struct element *current; /* current element in the branch */    struct handler *top_handlers; /* always points at the 					   * handler on top of the stack. */    int valid; /* non-zero whilst parse should continue */    int prune; /* if non-zero, depth within a dead branch */#ifdef HAVE_EXPAT    XML_Parser parser;    char *encoding;#else    xmlParserCtxtPtr parser;#endif    char error[ERR_SIZE];};/* The callback handlers */static void start_element(void *userdata, const ne_xml_char *name, const ne_xml_char **atts);static void end_element(void *userdata, const ne_xml_char *name);static void char_data(void *userdata, const ne_xml_char *cdata, int len);static const char *resolve_nspace(const struct element *elm,                                   const char *prefix, size_t pfxlen);/* Linked list of namespace scopes */struct namespace {    ne_xml_char *name;    ne_xml_char *uri;    struct namespace *next;};#ifdef HAVE_LIBXML/* Could be const as far as we care, but libxml doesn't want that */static xmlSAXHandler sax_handler = {    NULL, /* internalSubset */    NULL, /* isStandalone */    NULL, /* hasInternalSubset */    NULL, /* hasExternalSubset */    NULL, /* resolveEntity */    NULL, /* getEntity */    NULL, /* entityDecl */    NULL, /* notationDecl */    NULL, /* attributeDecl */    NULL, /* elementDecl */    NULL, /* unparsedEntityDecl */    NULL, /* setDocumentLocator */    NULL, /* startDocument */    NULL, /* endDocument */    start_element, /* startElement */    end_element, /* endElement */    NULL, /* reference */    char_data, /* characters */    NULL, /* ignorableWhitespace */    NULL, /* processingInstruction */    NULL, /* comment */    NULL, /* xmlParserWarning */    sax_error, /* xmlParserError */    sax_error, /* fatal error (never called by libxml2?) */    NULL, /* getParameterEntity */    char_data /* cdataBlock */};/* empty attributes array to mimic expat behaviour */static const char *empty_atts[] = {NULL, NULL};/* macro for determining the attributes array to pass */#define PASS_ATTS(atts) (atts ? (const char **)(atts) : empty_atts)#else#define PASS_ATTS(atts) ((const char **)(atts))/* XML declaration callback for expat. */static void decl_handler(void *userdata,			 const XML_Char *version, const XML_Char *encoding, 			 int standalone){    ne_xml_parser *p = userdata;    if (encoding) p->encoding = ne_strdup(encoding);    }#endif /* HAVE_LIBXML */int ne_xml_currentline(ne_xml_parser *p) {#ifdef HAVE_EXPAT    return XML_GetCurrentLineNumber(p->parser);#else    return p->parser->input->line;#endif}const char *ne_xml_doc_encoding(const ne_xml_parser *p){#ifdef HAVE_LIBXML    return p->parser->encoding;#else    return p->encoding;#endif}/* Extract the namespace prefix declarations from 'atts'. */static int declare_nspaces(ne_xml_parser *p, struct element *elm,                           const ne_xml_char **atts){    int n;        for (n = 0; atts && atts[n]; n += 2) {        if (strcasecmp(atts[n], "xmlns") == 0) {            /* New default namespace */            elm->default_ns = ne_strdup(atts[n+1]);        } else if (strncasecmp(atts[n], "xmlns:", 6) == 0) {            struct namespace *ns;                        if (atts[n][6] == '\0' || atts[n+1][0] == '\0') {                ne_snprintf(p->error, ERR_SIZE,                             ("XML parse error at line %d: invalid namespace "                             "declaration"), ne_xml_currentline(p));                return -1;            }            /* New namespace scope */            ns = ne_calloc(sizeof(*ns));            ns->next = elm->nspaces;            elm->nspaces = ns;            ns->name = ne_strdup(atts[n]+6); /* skip the xmlns= */            ns->uri = ne_strdup(atts[n+1]);        }    }        return 0;}/* Expand an XML qualified name, which may include a namespace prefix * as well as the local part. */static int expand_qname(ne_xml_parser *p, struct element *elm,                        const ne_xml_char *qname){    const ne_xml_char *pfx;    pfx = strchr(qname, ':');    if (pfx == NULL) {        struct element *e = elm;        /* Find default namespace; guaranteed to terminate as the root         * element always has default_ns="". */        while (e->default_ns == NULL)            e = e->parent;                elm->name = ne_strdup(qname);        elm->nspace = e->default_ns;    } else {        const char *uri = resolve_nspace(elm, qname, pfx-qname);	if (uri) {	    /* The name is everything after the ':' */	    if (pfx[1] == '\0') {		ne_snprintf(p->error, ERR_SIZE, 			    ("XML parse error at line %d: element name missing"                             "after namespace prefix"), ne_xml_currentline(p));		return -1;	    }	    elm->name = ne_strdup(pfx+1);            elm->nspace = uri;	} else {	    ne_snprintf(p->error, ERR_SIZE,                         ("XML parse error at line %d: undeclared namespace"),                        ne_xml_currentline(p));	    return -1;	}    }    return 0;}/* Called with the start of a new element. */static void start_element(void *userdata, const ne_xml_char *name,			  const ne_xml_char **atts) {    ne_xml_parser *p = userdata;    struct element *elm;    struct handler *hand;    int state = NE_XML_DECLINE;    if (!p->valid) return;        if (p->prune) {        p->prune++;        return;    }    /* Create a new element */    elm = ne_calloc(sizeof *elm);    elm->parent = p->current;    p->current = elm;    if (declare_nspaces(p, elm, atts) || expand_qname(p, elm, name)) {        p->valid = 0;        return;    }    /* Find a handler which will accept this element (or abort the parse) */    for (hand = elm->parent->handler; hand && state == NE_XML_DECLINE;         hand = hand->next) {        elm->handler = hand;        state = hand->startelm_cb(hand->userdata, elm->parent->state,                                  elm->nspace, elm->name, PASS_ATTS(atts));    }    NE_DEBUG(NE_DBG_XMLPARSE, "XML: start-element (%d, {%s, %s}) => %d\n",              elm->parent->state, elm->nspace, elm->name, state);             

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -