📄 xinclude.c.svn-base
字号:
/* * xinclude.c : Code to implement XInclude processing * * World Wide Web Consortium W3C Last Call Working Draft 10 November 2003 * http://www.w3.org/TR/2003/WD-xinclude-20031110 * * See Copyright for the status of this software. * * daniel@veillard.com */#define IN_LIBXML#include "libxml.h"#include <string.h>#include <libxml/xmlmemory.h>#include <libxml/tree.h>#include <libxml/parser.h>#include <libxml/uri.h>#include <libxml/xpointer.h>#include <libxml/parserInternals.h>#include <libxml/xmlerror.h>#include <libxml/encoding.h>#include <libxml/globals.h>#ifdef LIBXML_XINCLUDE_ENABLED#include <libxml/xinclude.h>#define XINCLUDE_MAX_DEPTH 40/* #define DEBUG_XINCLUDE */#ifdef DEBUG_XINCLUDE#ifdef LIBXML_DEBUG_ENABLED#include <libxml/debugXML.h>#endif#endif/************************************************************************ * * * XInclude context handling * * * ************************************************************************//* * An XInclude context */typedef xmlChar *xmlURL;typedef struct _xmlXIncludeRef xmlXIncludeRef;typedef xmlXIncludeRef *xmlXIncludeRefPtr;struct _xmlXIncludeRef { xmlChar *URI; /* the fully resolved resource URL */ xmlChar *fragment; /* the fragment in the URI */ xmlDocPtr doc; /* the parsed document */ xmlNodePtr ref; /* the node making the reference in the source */ xmlNodePtr inc; /* the included copy */ int xml; /* xml or txt */ int count; /* how many refs use that specific doc */ xmlXPathObjectPtr xptr; /* the xpointer if needed */ int emptyFb; /* flag to show fallback empty */};struct _xmlXIncludeCtxt { xmlDocPtr doc; /* the source document */ int incBase; /* the first include for this document */ int incNr; /* number of includes */ int incMax; /* size of includes tab */ xmlXIncludeRefPtr *incTab; /* array of included references */ int txtNr; /* number of unparsed documents */ int txtMax; /* size of unparsed documents tab */ xmlNodePtr *txtTab; /* array of unparsed text nodes */ xmlURL *txturlTab; /* array of unparsed text URLs */ xmlChar * url; /* the current URL processed */ int urlNr; /* number of URLs stacked */ int urlMax; /* size of URL stack */ xmlChar * *urlTab; /* URL stack */ int nbErrors; /* the number of errors detected */ int legacy; /* using XINCLUDE_OLD_NS */ int parseFlags; /* the flags used for parsing XML documents */};static intxmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr tree);/************************************************************************ * * * XInclude error handler * * * ************************************************************************//** * xmlXIncludeErrMemory: * @extra: extra information * * Handle an out of memory condition */static voidxmlXIncludeErrMemory(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node, const char *extra){ if (ctxt != NULL) ctxt->nbErrors++; __xmlRaiseError(NULL, NULL, NULL, ctxt, node, XML_FROM_XINCLUDE, XML_ERR_NO_MEMORY, XML_ERR_ERROR, NULL, 0, extra, NULL, NULL, 0, 0, "Memory allocation failed : %s\n", extra);}/** * xmlXIncludeErr: * @ctxt: the XInclude context * @node: the context node * @msg: the error message * @extra: extra information * * Handle an XInclude error */static voidxmlXIncludeErr(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node, int error, const char *msg, const xmlChar *extra){ if (ctxt != NULL) ctxt->nbErrors++; __xmlRaiseError(NULL, NULL, NULL, ctxt, node, XML_FROM_XINCLUDE, error, XML_ERR_ERROR, NULL, 0, (const char *) extra, NULL, NULL, 0, 0, msg, (const char *) extra);}#if 0/** * xmlXIncludeWarn: * @ctxt: the XInclude context * @node: the context node * @msg: the error message * @extra: extra information * * Emit an XInclude warning. */static voidxmlXIncludeWarn(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node, int error, const char *msg, const xmlChar *extra){ __xmlRaiseError(NULL, NULL, NULL, ctxt, node, XML_FROM_XINCLUDE, error, XML_ERR_WARNING, NULL, 0, (const char *) extra, NULL, NULL, 0, 0, msg, (const char *) extra);}#endif/** * xmlXIncludeGetProp: * @ctxt: the XInclude context * @cur: the node * @name: the attribute name * * Get an XInclude attribute * * Returns the value (to be freed) or NULL if not found */static xmlChar *xmlXIncludeGetProp(xmlXIncludeCtxtPtr ctxt, xmlNodePtr cur, const xmlChar *name) { xmlChar *ret; ret = xmlGetNsProp(cur, XINCLUDE_NS, name); if (ret != NULL) return(ret); if (ctxt->legacy != 0) { ret = xmlGetNsProp(cur, XINCLUDE_OLD_NS, name); if (ret != NULL) return(ret); } ret = xmlGetProp(cur, name); return(ret);}/** * xmlXIncludeFreeRef: * @ref: the XInclude reference * * Free an XInclude reference */static voidxmlXIncludeFreeRef(xmlXIncludeRefPtr ref) { if (ref == NULL) return;#ifdef DEBUG_XINCLUDE xmlGenericError(xmlGenericErrorContext, "Freeing ref\n");#endif if (ref->doc != NULL) {#ifdef DEBUG_XINCLUDE xmlGenericError(xmlGenericErrorContext, "Freeing doc %s\n", ref->URI);#endif xmlFreeDoc(ref->doc); } if (ref->URI != NULL) xmlFree(ref->URI); if (ref->fragment != NULL) xmlFree(ref->fragment); if (ref->xptr != NULL) xmlXPathFreeObject(ref->xptr); xmlFree(ref);}/** * xmlXIncludeNewRef: * @ctxt: the XInclude context * @URI: the resource URI * * Creates a new reference within an XInclude context * * Returns the new set */static xmlXIncludeRefPtrxmlXIncludeNewRef(xmlXIncludeCtxtPtr ctxt, const xmlChar *URI, xmlNodePtr ref) { xmlXIncludeRefPtr ret;#ifdef DEBUG_XINCLUDE xmlGenericError(xmlGenericErrorContext, "New ref %s\n", URI);#endif ret = (xmlXIncludeRefPtr) xmlMalloc(sizeof(xmlXIncludeRef)); if (ret == NULL) { xmlXIncludeErrMemory(ctxt, ref, "growing XInclude context"); return(NULL); } memset(ret, 0, sizeof(xmlXIncludeRef)); if (URI == NULL) ret->URI = NULL; else ret->URI = xmlStrdup(URI); ret->fragment = NULL; ret->ref = ref; ret->doc = 0; ret->count = 0; ret->xml = 0; ret->inc = NULL; if (ctxt->incMax == 0) { ctxt->incMax = 4; ctxt->incTab = (xmlXIncludeRefPtr *) xmlMalloc(ctxt->incMax * sizeof(ctxt->incTab[0])); if (ctxt->incTab == NULL) { xmlXIncludeErrMemory(ctxt, ref, "growing XInclude context"); xmlXIncludeFreeRef(ret); return(NULL); } } if (ctxt->incNr >= ctxt->incMax) { ctxt->incMax *= 2; ctxt->incTab = (xmlXIncludeRefPtr *) xmlRealloc(ctxt->incTab, ctxt->incMax * sizeof(ctxt->incTab[0])); if (ctxt->incTab == NULL) { xmlXIncludeErrMemory(ctxt, ref, "growing XInclude context"); xmlXIncludeFreeRef(ret); return(NULL); } } ctxt->incTab[ctxt->incNr++] = ret; return(ret);}/** * xmlXIncludeNewContext: * @doc: an XML Document * * Creates a new XInclude context * * Returns the new set */xmlXIncludeCtxtPtrxmlXIncludeNewContext(xmlDocPtr doc) { xmlXIncludeCtxtPtr ret;#ifdef DEBUG_XINCLUDE xmlGenericError(xmlGenericErrorContext, "New context\n");#endif if (doc == NULL) return(NULL); ret = (xmlXIncludeCtxtPtr) xmlMalloc(sizeof(xmlXIncludeCtxt)); if (ret == NULL) { xmlXIncludeErrMemory(NULL, (xmlNodePtr) doc, "creating XInclude context"); return(NULL); } memset(ret, 0, sizeof(xmlXIncludeCtxt)); ret->doc = doc; ret->incNr = 0; ret->incBase = 0; ret->incMax = 0; ret->incTab = NULL; ret->nbErrors = 0; return(ret);}/** * xmlXIncludeURLPush: * @ctxt: the parser context * @value: the url * * Pushes a new url on top of the url stack * * Returns -1 in case of error, the index in the stack otherwise */static intxmlXIncludeURLPush(xmlXIncludeCtxtPtr ctxt, const xmlChar *value){ if (ctxt->urlNr > XINCLUDE_MAX_DEPTH) { xmlXIncludeErr(ctxt, NULL, XML_XINCLUDE_RECURSION, "detected a recursion in %s\n", value); return(-1); } if (ctxt->urlTab == NULL) { ctxt->urlMax = 4; ctxt->urlNr = 0; ctxt->urlTab = (xmlChar * *) xmlMalloc( ctxt->urlMax * sizeof(ctxt->urlTab[0])); if (ctxt->urlTab == NULL) { xmlXIncludeErrMemory(ctxt, NULL, "adding URL"); return (-1); } } if (ctxt->urlNr >= ctxt->urlMax) { ctxt->urlMax *= 2; ctxt->urlTab = (xmlChar * *) xmlRealloc(ctxt->urlTab, ctxt->urlMax * sizeof(ctxt->urlTab[0])); if (ctxt->urlTab == NULL) { xmlXIncludeErrMemory(ctxt, NULL, "adding URL"); return (-1); } } ctxt->url = ctxt->urlTab[ctxt->urlNr] = xmlStrdup(value); return (ctxt->urlNr++);}/** * xmlXIncludeURLPop: * @ctxt: the parser context * * Pops the top URL from the URL stack */static voidxmlXIncludeURLPop(xmlXIncludeCtxtPtr ctxt){ xmlChar * ret; if (ctxt->urlNr <= 0) return; ctxt->urlNr--; if (ctxt->urlNr > 0) ctxt->url = ctxt->urlTab[ctxt->urlNr - 1]; else ctxt->url = NULL; ret = ctxt->urlTab[ctxt->urlNr]; ctxt->urlTab[ctxt->urlNr] = 0; if (ret != NULL) xmlFree(ret);}/** * xmlXIncludeFreeContext: * @ctxt: the XInclude context * * Free an XInclude context */voidxmlXIncludeFreeContext(xmlXIncludeCtxtPtr ctxt) { int i;#ifdef DEBUG_XINCLUDE xmlGenericError(xmlGenericErrorContext, "Freeing context\n");#endif if (ctxt == NULL) return; while (ctxt->urlNr > 0) xmlXIncludeURLPop(ctxt); if (ctxt->urlTab != NULL) xmlFree(ctxt->urlTab); for (i = 0;i < ctxt->incNr;i++) { if (ctxt->incTab[i] != NULL) xmlXIncludeFreeRef(ctxt->incTab[i]); } for (i = 0;i < ctxt->txtNr;i++) { if (ctxt->txturlTab[i] != NULL) xmlFree(ctxt->txturlTab[i]); } if (ctxt->incTab != NULL) xmlFree(ctxt->incTab); if (ctxt->txtTab != NULL) xmlFree(ctxt->txtTab); if (ctxt->txturlTab != NULL) xmlFree(ctxt->txturlTab); xmlFree(ctxt);}/** * xmlXIncludeParseFile: * @ctxt: the XInclude context * @URL: the URL or file path * * parse a document for XInclude */static xmlDocPtrxmlXIncludeParseFile(xmlXIncludeCtxtPtr ctxt, const char *URL) { xmlDocPtr ret; xmlParserCtxtPtr pctxt; char *directory = NULL; xmlParserInputPtr inputStream; xmlInitParser(); pctxt = xmlNewParserCtxt(); if (pctxt == NULL) { xmlXIncludeErrMemory(ctxt, NULL, "cannot allocate parser context"); return(NULL); } /* * try to ensure that new documents included are actually * built with the same dictionary as the including document. */ if ((ctxt->doc != NULL) && (ctxt->doc->dict != NULL) && (pctxt->dict != NULL)) { xmlDictFree(pctxt->dict); pctxt->dict = ctxt->doc->dict; xmlDictReference(pctxt->dict); } xmlCtxtUseOptions(pctxt, ctxt->parseFlags | XML_PARSE_DTDLOAD); inputStream = xmlLoadExternalEntity(URL, NULL, pctxt); if (inputStream == NULL) { xmlFreeParserCtxt(pctxt); return(NULL); } inputPush(pctxt, inputStream); if ((pctxt->directory == NULL) && (directory == NULL)) directory = xmlParserGetDirectory(URL); if ((pctxt->directory == NULL) && (directory != NULL)) pctxt->directory = (char *) xmlStrdup((xmlChar *) directory); pctxt->loadsubset = XML_DETECT_IDS; xmlParseDocument(pctxt); if (pctxt->wellFormed) { ret = pctxt->myDoc; } else { ret = NULL; if (pctxt->myDoc != NULL) xmlFreeDoc(pctxt->myDoc); pctxt->myDoc = NULL; } xmlFreeParserCtxt(pctxt); return(ret);}/** * xmlXIncludeAddNode: * @ctxt: the XInclude context * @cur: the new node * * Add a new node to process to an XInclude context */static intxmlXIncludeAddNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr cur) { xmlXIncludeRefPtr ref; xmlURIPtr uri;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -