1
0
mirror of https://gitlab.gnome.org/GNOME/libxml2.git synced 2024-10-26 12:25:09 +03:00

reimplemented a large part of the XInclude processor, trying to minimize

* xinclude.c: reimplemented a large part of the XInclude
  processor, trying to minimize resources used, James Henstridge
  provided a huge test case which was exhibiting severe memory
  consumption problems.
Daniel
This commit is contained in:
Daniel Veillard 2002-09-05 10:52:10 +00:00
parent 2206dbfabe
commit bbc72c3abf
2 changed files with 465 additions and 140 deletions

View File

@ -1,3 +1,10 @@
Thu Sep 5 12:49:35 CEST 2002 Daniel Veillard <daniel@veillard.com>
* xinclude.c: reimplemented a large part of the XInclude
processor, trying to minimize resources used, James Henstridge
provided a huge test case which was exhibiting severe memory
consumption problems.
Thu Sep 5 10:07:13 CEST 2002 Daniel Veillard <daniel@veillard.com>
* python/Makefile.am: applied patch from Christophe Merlet to

View File

@ -55,18 +55,28 @@
* An XInclude context
*/
typedef xmlChar *xmlURL;
typedef struct _xmlXIncludeRef xmlXIncludeRef;
typedef xmlXIncludeRef *xmlXIncludeRefPtr;
struct _xmlXIncludeRef {
xmlChar *URI; /* the rully 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 */
};
typedef struct _xmlXIncludeCtxt xmlXIncludeCtxt;
typedef xmlXIncludeCtxt *xmlXIncludeCtxtPtr;
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 */
xmlNodePtr *incTab; /* array of include nodes */
xmlNodePtr *repTab; /* array of replacement node lists */
int docNr; /* number of parsed documents */
int docMax; /* size of parsed documents tab */
xmlDocPtr *docTab; /* array of parsed documents */
xmlURL *urlTab; /* array of parsed documents URLs */
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 */
@ -76,6 +86,89 @@ struct _xmlXIncludeCtxt {
static int
xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc);
/**
* xmlXIncludeFreeRef:
* @ref: the XInclude reference
*
* Free an XInclude reference
*/
static void
xmlXIncludeFreeRef(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);
xmlFree(ref);
}
/**
* xmlXIncludeNewRef:
* @ctxt: the XInclude context
* @URI: the resource URI
*
* Creates a new reference within an XInclude context
*
* Returns the new set
*/
static xmlXIncludeRefPtr
xmlXIncludeNewRef(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)
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) {
xmlGenericError(xmlGenericErrorContext,
"malloc failed !\n");
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) {
xmlGenericError(xmlGenericErrorContext,
"realloc failed !\n");
xmlXIncludeFreeRef(ret);
return(NULL);
}
}
ctxt->incTab[ctxt->incNr++] = ret;
return(ret);
}
/**
* xmlXIncludeNewContext:
* @doc: an XML Document
@ -88,6 +181,9 @@ static xmlXIncludeCtxtPtr
xmlXIncludeNewContext(xmlDocPtr doc) {
xmlXIncludeCtxtPtr ret;
#ifdef DEBUG_XINCLUDE
xmlGenericError(xmlGenericErrorContext, "New context\n");
#endif
if (doc == NULL)
return(NULL);
ret = (xmlXIncludeCtxtPtr) xmlMalloc(sizeof(xmlXIncludeCtxt));
@ -96,13 +192,9 @@ xmlXIncludeNewContext(xmlDocPtr doc) {
memset(ret, 0, sizeof(xmlXIncludeCtxt));
ret->doc = doc;
ret->incNr = 0;
ret->incBase = 0;
ret->incMax = 0;
ret->incTab = NULL;
ret->repTab = NULL;
ret->docNr = 0;
ret->docMax = 0;
ret->docTab = NULL;
ret->urlTab = NULL;
return(ret);
}
@ -116,12 +208,14 @@ static void
xmlXIncludeFreeContext(xmlXIncludeCtxtPtr ctxt) {
int i;
#ifdef DEBUG_XINCLUDE
xmlGenericError(xmlGenericErrorContext, "Freeing context\n");
#endif
if (ctxt == NULL)
return;
for (i = 0;i < ctxt->docNr;i++) {
xmlFreeDoc(ctxt->docTab[i]);
if (ctxt->urlTab[i] != NULL)
xmlFree(ctxt->urlTab[i]);
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)
@ -129,12 +223,6 @@ xmlXIncludeFreeContext(xmlXIncludeCtxtPtr ctxt) {
}
if (ctxt->incTab != NULL)
xmlFree(ctxt->incTab);
if (ctxt->repTab != NULL)
xmlFree(ctxt->repTab);
if (ctxt->urlTab != NULL)
xmlFree(ctxt->urlTab);
if (ctxt->docTab != NULL)
xmlFree(ctxt->docTab);
if (ctxt->txtTab != NULL)
xmlFree(ctxt->txtTab);
if (ctxt->txturlTab != NULL)
@ -145,103 +233,149 @@ xmlXIncludeFreeContext(xmlXIncludeCtxtPtr ctxt) {
/**
* xmlXIncludeAddNode:
* @ctxt: the XInclude context
* @node: the new node
* @cur: the new node
*
* Add a new node to process to an XInclude context
*/
static void
xmlXIncludeAddNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node) {
if (ctxt->incMax == 0) {
ctxt->incMax = 4;
ctxt->incTab = (xmlNodePtr *) xmlMalloc(ctxt->incMax *
sizeof(ctxt->incTab[0]));
if (ctxt->incTab == NULL) {
xmlGenericError(xmlGenericErrorContext,
"malloc failed !\n");
return;
}
ctxt->repTab = (xmlNodePtr *) xmlMalloc(ctxt->incMax *
sizeof(ctxt->repTab[0]));
if (ctxt->repTab == NULL) {
xmlGenericError(xmlGenericErrorContext,
"malloc failed !\n");
return;
static int
xmlXIncludeAddNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr cur) {
xmlXIncludeRefPtr ref;
xmlURIPtr uri;
xmlChar *URL;
xmlChar *fragment = NULL;
xmlChar *href;
xmlChar *parse;
xmlChar *base;
xmlChar *URI;
int xml = 1; /* default Issue 64 */
if (ctxt == NULL)
return(-1);
if (cur == NULL)
return(-1);
#ifdef DEBUG_XINCLUDE
xmlGenericError(xmlGenericErrorContext, "Add node\n");
#endif
/*
* read the attributes
*/
href = xmlGetNsProp(cur, XINCLUDE_NS, XINCLUDE_HREF);
if (href == NULL) {
href = xmlGetProp(cur, XINCLUDE_HREF);
if (href == NULL) {
xmlGenericError(xmlGenericErrorContext, "XInclude: no href\n");
return(-1);
}
}
if (ctxt->incNr >= ctxt->incMax) {
ctxt->incMax *= 2;
ctxt->incTab = (xmlNodePtr *) xmlRealloc(ctxt->incTab,
ctxt->incMax * sizeof(ctxt->incTab[0]));
if (ctxt->incTab == NULL) {
parse = xmlGetNsProp(cur, XINCLUDE_NS, XINCLUDE_PARSE);
if (parse == NULL) {
parse = xmlGetProp(cur, XINCLUDE_PARSE);
}
if (parse != NULL) {
if (xmlStrEqual(parse, XINCLUDE_PARSE_XML))
xml = 1;
else if (xmlStrEqual(parse, XINCLUDE_PARSE_TEXT))
xml = 0;
else {
xmlGenericError(xmlGenericErrorContext,
"realloc failed !\n");
return;
}
ctxt->repTab = (xmlNodePtr *) xmlRealloc(ctxt->repTab,
ctxt->incMax * sizeof(ctxt->repTab[0]));
if (ctxt->repTab == NULL) {
xmlGenericError(xmlGenericErrorContext,
"realloc failed !\n");
return;
"XInclude: invalid value %s for %s\n",
parse, XINCLUDE_PARSE);
if (href != NULL)
xmlFree(href);
if (parse != NULL)
xmlFree(parse);
return(-1);
}
}
ctxt->incTab[ctxt->incNr] = node;
ctxt->repTab[ctxt->incNr] = NULL;
ctxt->incNr++;
/*
* compute the URI
*/
base = xmlNodeGetBase(ctxt->doc, cur);
if (base == NULL) {
URI = xmlBuildURI(href, ctxt->doc->URL);
} else {
URI = xmlBuildURI(href, base);
}
if (URI == NULL) {
xmlChar *escbase;
xmlChar *eschref;
/*
* Some escaping may be needed
*/
escbase = xmlURIEscape(base);
eschref = xmlURIEscape(href);
URI = xmlBuildURI(eschref, escbase);
if (escbase != NULL)
xmlFree(escbase);
if (eschref != NULL)
xmlFree(eschref);
}
if (parse != NULL)
xmlFree(parse);
if (href != NULL)
xmlFree(href);
if (base != NULL)
xmlFree(base);
if (URI == NULL) {
xmlGenericError(xmlGenericErrorContext, "XInclude: failed build URL\n");
return(-1);
}
/*
* Check the URL and remove any fragment identifier
*/
uri = xmlParseURI((const char *)URI);
if (uri == NULL) {
xmlGenericError(xmlGenericErrorContext,
"XInclude: invalid value URI %s\n", URI);
return(-1);
}
if (uri->fragment != NULL) {
fragment = (xmlChar *) uri->fragment;
uri->fragment = NULL;
}
URL = xmlSaveUri(uri);
xmlFreeURI(uri);
xmlFree(URI);
if (URL == NULL) {
xmlGenericError(xmlGenericErrorContext,
"XInclude: invalid value URI %s\n", URI);
if (fragment != NULL)
xmlFree(fragment);
return(-1);
}
ref = xmlXIncludeNewRef(ctxt, URL, cur);
if (ref == NULL) {
return(-1);
}
ref->fragment = fragment;
ref->doc = NULL;
ref->xml = xml;
ref->count = 1;
xmlFree(URL);
return(0);
}
/**
* xmlXIncludeAddDoc:
* xmlXIncludeRecurseDoc:
* @ctxt: the XInclude context
* @doc: the new document
* @url: the associated URL
*
* Add a new document to the list. The XInclude recursive nature is handled
* at this point.
* The XInclude recursive nature is handled at this point.
*/
static void
xmlXIncludeAddDoc(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, const xmlURL url) {
xmlXIncludeRecurseDoc(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, const xmlURL url) {
xmlXIncludeCtxtPtr newctxt;
int i;
if (ctxt->docMax == 0) {
ctxt->docMax = 4;
ctxt->docTab = (xmlDocPtr *) xmlMalloc(ctxt->docMax *
sizeof(ctxt->docTab[0]));
if (ctxt->docTab == NULL) {
xmlGenericError(xmlGenericErrorContext,
"malloc failed !\n");
return;
}
ctxt->urlTab = (xmlURL *) xmlMalloc(ctxt->docMax *
sizeof(ctxt->urlTab[0]));
if (ctxt->urlTab == NULL) {
xmlGenericError(xmlGenericErrorContext,
"malloc failed !\n");
return;
}
}
if (ctxt->docNr >= ctxt->docMax) {
ctxt->docMax *= 2;
ctxt->docTab = (xmlDocPtr *) xmlRealloc(ctxt->docTab,
ctxt->docMax * sizeof(ctxt->docTab[0]));
if (ctxt->docTab == NULL) {
xmlGenericError(xmlGenericErrorContext,
"realloc failed !\n");
return;
}
ctxt->urlTab = (xmlURL *) xmlRealloc(ctxt->urlTab,
ctxt->docMax * sizeof(ctxt->urlTab[0]));
if (ctxt->urlTab == NULL) {
xmlGenericError(xmlGenericErrorContext,
"realloc failed !\n");
return;
}
}
ctxt->docTab[ctxt->docNr] = doc;
ctxt->urlTab[ctxt->docNr] = xmlStrdup(url);
ctxt->docNr++;
#ifdef DEBUG_XINCLUDE
xmlGenericError(xmlGenericErrorContext, "Recursing in doc %s\n", doc->URL);
#endif
/*
* Handle recursion here.
*/
@ -251,36 +385,36 @@ xmlXIncludeAddDoc(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, const xmlURL url) {
/*
* Copy the existing document set
*/
newctxt->docMax = ctxt->docMax;
newctxt->docNr = ctxt->docNr;
newctxt->docTab = (xmlDocPtr *) xmlMalloc(newctxt->docMax *
sizeof(newctxt->docTab[0]));
if (newctxt->docTab == NULL) {
xmlGenericError(xmlGenericErrorContext,
"malloc failed !\n");
xmlFree(newctxt);
return;
}
newctxt->urlTab = (xmlURL *) xmlMalloc(newctxt->docMax *
sizeof(newctxt->urlTab[0]));
if (ctxt->urlTab == NULL) {
newctxt->incMax = ctxt->incMax;
newctxt->incNr = ctxt->incNr;
newctxt->incTab = (xmlXIncludeRefPtr *) xmlMalloc(newctxt->incMax *
sizeof(newctxt->incTab[0]));
if (newctxt->incTab == NULL) {
xmlGenericError(xmlGenericErrorContext,
"malloc failed !\n");
xmlFree(newctxt);
return;
}
for (i = 0;i < ctxt->docNr;i++) {
newctxt->docTab[i] = ctxt->docTab[i];
newctxt->urlTab[i] = ctxt->urlTab[i];
/*
* Inherit the documents already in use by others includes
*/
newctxt->incBase = ctxt->incNr;
for (i = 0;i < ctxt->incNr;i++) {
newctxt->incTab[i] = ctxt->incTab[i];
newctxt->incTab[i]->count++; /* prevent the recursion from
freeing it */
}
xmlXIncludeDoProcess(newctxt, doc);
for (i = 0;i < ctxt->docNr;i++) {
newctxt->docTab[i] = NULL;
newctxt->urlTab[i] = NULL;
for (i = 0;i < ctxt->incNr;i++) {
newctxt->incTab[i]->count--;
newctxt->incTab[i] = NULL;
}
xmlXIncludeFreeContext(newctxt);
}
#ifdef DEBUG_XINCLUDE
xmlGenericError(xmlGenericErrorContext, "Done recursing in doc %s\n", url);
#endif
}
/**
@ -293,6 +427,9 @@ xmlXIncludeAddDoc(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, const xmlURL url) {
*/
static void
xmlXIncludeAddTxt(xmlXIncludeCtxtPtr ctxt, xmlNodePtr txt, const xmlURL url) {
#ifdef DEBUG_XINCLUDE
xmlGenericError(xmlGenericErrorContext, "Adding text %s\n", url);
#endif
if (ctxt->txtMax == 0) {
ctxt->txtMax = 4;
ctxt->txtTab = (xmlNodePtr *) xmlMalloc(ctxt->txtMax *
@ -320,7 +457,7 @@ xmlXIncludeAddTxt(xmlXIncludeCtxtPtr ctxt, xmlNodePtr txt, const xmlURL url) {
return;
}
ctxt->txturlTab = (xmlURL *) xmlRealloc(ctxt->txturlTab,
ctxt->txtMax * sizeof(ctxt->urlTab[0]));
ctxt->txtMax * sizeof(ctxt->txturlTab[0]));
if (ctxt->txturlTab == NULL) {
xmlGenericError(xmlGenericErrorContext,
"realloc failed !\n");
@ -719,7 +856,11 @@ xmlXIncludeLoadDoc(xmlXIncludeCtxtPtr ctxt, const xmlChar *url, int nr) {
xmlURIPtr uri;
xmlChar *URL;
xmlChar *fragment = NULL;
int i;
int i = 0;
#ifdef DEBUG_XINCLUDE
xmlGenericError(xmlGenericErrorContext, "Loading doc %s:%d\n", url, nr);
#endif
/*
* Check the URL and remove any fragment identifier
*/
@ -755,15 +896,23 @@ xmlXIncludeLoadDoc(xmlXIncludeCtxtPtr ctxt, const xmlChar *url, int nr) {
/*
* Prevent reloading twice the document.
*/
for (i = 0; i < ctxt->docNr; i++) {
if (xmlStrEqual(URL, ctxt->urlTab[i])) {
doc = ctxt->docTab[i];
for (i = 0; i < ctxt->incNr; i++) {
if ((xmlStrEqual(URL, ctxt->incTab[i]->URI)) &&
(ctxt->incTab[i]->doc != NULL)) {
doc = ctxt->incTab[i]->doc;
#ifdef DEBUG_XINCLUDE
printf("Already loaded %s\n", URL);
#endif
goto loaded;
}
}
/*
* Load it.
*/
#ifdef DEBUG_XINCLUDE
printf("loading %s\n", URL);
#endif
doc = xmlParseFile((const char *)URL);
if (doc == NULL) {
xmlFree(URL);
@ -771,7 +920,26 @@ xmlXIncludeLoadDoc(xmlXIncludeCtxtPtr ctxt, const xmlChar *url, int nr) {
xmlFree(fragment);
return(-1);
}
xmlXIncludeAddDoc(ctxt, doc, URL);
ctxt->incTab[nr]->doc = doc;
/*
* TODO: Make sure we have all entities fixed up
*/
/*
* We don't need the DTD anymore, free up space
if (doc->intSubset != NULL) {
xmlUnlinkNode((xmlNodePtr) doc->intSubset);
xmlFreeNode((xmlNodePtr) doc->intSubset);
doc->intSubset = NULL;
}
if (doc->extSubset != NULL) {
xmlUnlinkNode((xmlNodePtr) doc->extSubset);
xmlFreeNode((xmlNodePtr) doc->extSubset);
doc->extSubset = NULL;
}
*/
xmlXIncludeRecurseDoc(ctxt, doc, URL);
loaded:
if (fragment == NULL) {
@ -782,9 +950,9 @@ loaded:
{
/* Hopefully a DTD declaration won't be copied from
* the same document */
ctxt->repTab[nr] = xmlCopyNodeList(ctxt->doc->children);
ctxt->incTab[nr]->inc = xmlCopyNodeList(ctxt->doc->children);
} else {
ctxt->repTab[nr] = xmlXIncludeCopyNodeList(ctxt, ctxt->doc,
ctxt->incTab[nr]->inc = xmlXIncludeCopyNodeList(ctxt, ctxt->doc,
doc, doc->children);
}
} else {
@ -797,7 +965,8 @@ loaded:
xmlNodeSetPtr set;
if (doc == NULL) {
xptrctxt = xmlXPtrNewContext(ctxt->doc, ctxt->incTab[nr], NULL);
xptrctxt = xmlXPtrNewContext(ctxt->doc, ctxt->incTab[nr]->ref,
NULL);
} else {
xptrctxt = xmlXPtrNewContext(doc, NULL, NULL);
}
@ -887,7 +1056,8 @@ loaded:
}
}
}
ctxt->repTab[nr] = xmlXIncludeCopyXPointer(ctxt, ctxt->doc, doc, xptr);
ctxt->incTab[nr]->inc =
xmlXIncludeCopyXPointer(ctxt, ctxt->doc, doc, xptr);
xmlXPathFreeObject(xptr);
xmlXPathFreeContext(xptrctxt);
xmlFree(fragment);
@ -899,13 +1069,21 @@ loaded:
if ((doc != NULL) && (URL != NULL) && (xmlStrchr(URL, (xmlChar) '/'))) {
xmlNodePtr node;
node = ctxt->repTab[nr];
node = ctxt->incTab[nr]->inc;
while (node != NULL) {
if (node->type == XML_ELEMENT_NODE)
xmlNodeSetBase(node, URL);
node = node->next;
}
}
if ((nr < ctxt->incNr) && (ctxt->incTab[nr]->doc != NULL) &&
(ctxt->incTab[nr]->count <= 1)) {
#ifdef DEBUG_XINCLUDE
printf("freeing %s\n", ctxt->incTab[nr]->doc->URL);
#endif
xmlFreeDoc(ctxt->incTab[nr]->doc);
ctxt->incTab[nr]->doc = NULL;
}
xmlFree(URL);
return(0);
}
@ -1011,7 +1189,7 @@ loaded:
/*
* Add the element as the replacement copy.
*/
ctxt->repTab[nr] = node;
ctxt->incTab[nr]->inc = node;
xmlFree(URL);
return(0);
}
@ -1022,7 +1200,7 @@ loaded:
* @fallback: the fallback node
* @nr: the xinclude node number
*
* Load the content of teh fallback node, and store the result
* Load the content of the fallback node, and store the result
* in the XInclude context
*
* Returns 0 in case of success, -1 in case of failure
@ -1032,7 +1210,7 @@ xmlXIncludeLoadFallback(xmlXIncludeCtxtPtr ctxt, xmlNodePtr fallback, int nr) {
if ((fallback == NULL) || (ctxt == NULL))
return(-1);
ctxt->repTab[nr] = xmlCopyNode(fallback->children, 1);
ctxt->incTab[nr]->inc = xmlCopyNode(fallback->children, 1);
return(0);
}
@ -1058,6 +1236,144 @@ xmlXIncludePreProcessNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node) {
return(0);
}
/**
* xmlXIncludePreloadNode:
* @ctxt: an XInclude context
* @nr: the node number
*
* Do some precomputations and preload shared documents
*
* Returns 0 if substitution succeeded, -1 if some processing failed
*/
static int
xmlXIncludePreloadNode(xmlXIncludeCtxtPtr ctxt, int nr) {
xmlNodePtr cur;
xmlChar *href;
xmlChar *parse;
xmlChar *base;
xmlChar *URI;
int xml = 1; /* default Issue 64 */
xmlURIPtr uri;
xmlChar *URL;
xmlChar *fragment = NULL;
int i;
if (ctxt == NULL)
return(-1);
if ((nr < 0) || (nr >= ctxt->incNr))
return(-1);
cur = ctxt->incTab[nr]->ref;
if (cur == NULL)
return(-1);
/*
* read the attributes
*/
href = xmlGetNsProp(cur, XINCLUDE_NS, XINCLUDE_HREF);
if (href == NULL) {
href = xmlGetProp(cur, XINCLUDE_HREF);
if (href == NULL) {
xmlGenericError(xmlGenericErrorContext, "XInclude: no href\n");
return(-1);
}
}
parse = xmlGetNsProp(cur, XINCLUDE_NS, XINCLUDE_PARSE);
if (parse == NULL) {
parse = xmlGetProp(cur, XINCLUDE_PARSE);
}
if (parse != NULL) {
if (xmlStrEqual(parse, XINCLUDE_PARSE_XML))
xml = 1;
else if (xmlStrEqual(parse, XINCLUDE_PARSE_TEXT))
xml = 0;
else {
xmlGenericError(xmlGenericErrorContext,
"XInclude: invalid value %s for %s\n",
parse, XINCLUDE_PARSE);
if (href != NULL)
xmlFree(href);
if (parse != NULL)
xmlFree(parse);
return(-1);
}
}
/*
* compute the URI
*/
base = xmlNodeGetBase(ctxt->doc, cur);
if (base == NULL) {
URI = xmlBuildURI(href, ctxt->doc->URL);
} else {
URI = xmlBuildURI(href, base);
}
if (URI == NULL) {
xmlChar *escbase;
xmlChar *eschref;
/*
* Some escaping may be needed
*/
escbase = xmlURIEscape(base);
eschref = xmlURIEscape(href);
URI = xmlBuildURI(eschref, escbase);
if (escbase != NULL)
xmlFree(escbase);
if (eschref != NULL)
xmlFree(eschref);
}
if (parse != NULL)
xmlFree(parse);
if (href != NULL)
xmlFree(href);
if (base != NULL)
xmlFree(base);
if (URI == NULL) {
xmlGenericError(xmlGenericErrorContext, "XInclude: failed build URL\n");
return(-1);
}
/*
* Check the URL and remove any fragment identifier
*/
uri = xmlParseURI((const char *)URI);
if (uri == NULL) {
xmlGenericError(xmlGenericErrorContext,
"XInclude: invalid value URI %s\n", URI);
xmlFree(URI);
return(-1);
}
if (uri->fragment != NULL) {
fragment = (xmlChar *) uri->fragment;
uri->fragment = NULL;
}
URL = xmlSaveUri(uri);
xmlFreeURI(uri);
if (URL == NULL) {
xmlGenericError(xmlGenericErrorContext,
"XInclude: invalid value URI %s\n", URI);
if (fragment != NULL)
xmlFree(fragment);
xmlFree(URI);
return(-1);
}
xmlFree(URI);
if (fragment != NULL)
xmlFree(fragment);
for (i = 0; i < nr; i++) {
if (xmlStrEqual(URL, ctxt->incTab[i]->URI)) {
#ifdef DEBUG_XINCLUDE
printf("Incrementing count for %d : %s\n", i, ctxt->incTab[i]->URI);
#endif
ctxt->incTab[i]->count++;
break;
}
}
xmlFree(URL);
return(0);
}
/**
* xmlXIncludeLoadNode:
* @ctxt: an XInclude context
@ -1081,13 +1397,10 @@ xmlXIncludeLoadNode(xmlXIncludeCtxtPtr ctxt, int nr) {
return(-1);
if ((nr < 0) || (nr >= ctxt->incNr))
return(-1);
cur = ctxt->incTab[nr];
cur = ctxt->incTab[nr]->ref;
if (cur == NULL)
return(-1);
#ifdef DEBUG_XINCLUDE
xmlDebugDumpNode(stdout, cur, 0);
#endif
/*
* read the attributes
*/
@ -1227,7 +1540,7 @@ xmlXIncludeIncludeNode(xmlXIncludeCtxtPtr ctxt, int nr) {
return(-1);
if ((nr < 0) || (nr >= ctxt->incNr))
return(-1);
cur = ctxt->incTab[nr];
cur = ctxt->incTab[nr]->ref;
if (cur == NULL)
return(-1);
@ -1248,8 +1561,8 @@ xmlXIncludeIncludeNode(xmlXIncludeCtxtPtr ctxt, int nr) {
/*
* Add the list of nodes
*/
list = ctxt->repTab[nr];
ctxt->repTab[nr] = NULL;
list = ctxt->incTab[nr]->inc;
ctxt->incTab[nr]->inc = NULL;
while (list != NULL) {
cur = list;
list = list->next;
@ -1335,14 +1648,19 @@ xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc) {
/*
* Second Phase : collect the infosets fragments
*/
for (i = 0;i < ctxt->incNr; i++) {
/*
for (i = ctxt->incBase;i < ctxt->incNr; i++) {
xmlXIncludePreloadNode(ctxt, i);
}
*/
for (i = ctxt->incBase;i < ctxt->incNr; i++) {
xmlXIncludeLoadNode(ctxt, i);
}
/*
* Third phase: extend the original document infoset.
*/
for (i = 0;i < ctxt->incNr; i++) {
for (i = ctxt->incBase;i < ctxt->incNr; i++) {
xmlXIncludeIncludeNode(ctxt, i);
}