summaryrefslogtreecommitdiff
path: root/xinclude.c
diff options
context:
space:
mode:
Diffstat (limited to 'xinclude.c')
-rw-r--r--xinclude.c233
1 files changed, 96 insertions, 137 deletions
diff --git a/xinclude.c b/xinclude.c
index d3b1ba6b..855ede3b 100644
--- a/xinclude.c
+++ b/xinclude.c
@@ -62,6 +62,7 @@ struct _xmlXIncludeRef {
int fallback; /* fallback was loaded */
int emptyFb; /* flag to show fallback empty */
int expanding; /* flag to detect inclusion loops */
+ int replace; /* should the node be replaced? */
};
typedef struct _xmlXIncludeDoc xmlXIncludeDoc;
@@ -80,10 +81,7 @@ struct _xmlXIncludeTxt {
};
struct _xmlXIncludeCtxt {
- xmlXIncludeCtxt *rootCtxt; /* the root context */
-
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 */
@@ -114,7 +112,7 @@ static int
xmlXIncludeLoadNode(xmlXIncludeCtxtPtr ctxt, xmlXIncludeRefPtr ref);
static int
-xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlNodePtr tree, int skipRoot);
+xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlNodePtr tree);
/************************************************************************
@@ -309,10 +307,8 @@ xmlXIncludeNewContext(xmlDocPtr doc) {
return(NULL);
}
memset(ret, 0, sizeof(xmlXIncludeCtxt));
- ret->rootCtxt = ret;
ret->doc = doc;
ret->incNr = 0;
- ret->incBase = 0;
ret->incMax = 0;
ret->incTab = NULL;
ret->nbErrors = 0;
@@ -603,68 +599,32 @@ xmlXIncludeAddNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr cur) {
static void
xmlXIncludeRecurseDoc(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc,
const xmlURL url ATTRIBUTE_UNUSED) {
- xmlXIncludeCtxtPtr newctxt;
+ xmlDocPtr oldDoc;
+ xmlXIncludeRefPtr *oldIncTab;
+ int oldIncMax, oldIncNr;
int i;
-#ifdef DEBUG_XINCLUDE
- xmlGenericError(xmlGenericErrorContext, "Recursing in doc %s\n", doc->URL);
-#endif
- /*
- * Handle recursion here.
- */
-
- newctxt = xmlXIncludeNewContext(doc);
- if (newctxt != NULL) {
- /*
- * Copy the private user data
- */
- newctxt->_private = ctxt->_private;
- /*
- * Copy the existing document set
- */
- newctxt->incMax = ctxt->incMax;
- newctxt->incNr = ctxt->incNr;
- newctxt->incTab = (xmlXIncludeRefPtr *) xmlMalloc(newctxt->incMax *
- sizeof(newctxt->incTab[0]));
- if (newctxt->incTab == NULL) {
- xmlXIncludeErrMemory(ctxt, (xmlNodePtr) doc, "processing doc");
- xmlFree(newctxt);
- return;
- }
- /*
- * reference root context
- */
- newctxt->rootCtxt = ctxt->rootCtxt;
-
- /*
- * Inherit the existing base
- */
- newctxt->base = xmlStrdup(ctxt->base);
+ oldDoc = ctxt->doc;
+ oldIncMax = ctxt->incMax;
+ oldIncNr = ctxt->incNr;
+ oldIncTab = ctxt->incTab;
+ ctxt->doc = doc;
+ ctxt->incMax = 0;
+ ctxt->incNr = 0;
+ ctxt->incTab = NULL;
- /*
- * Inherit the includes already in use by other documents
- */
- newctxt->incBase = ctxt->incNr;
- for (i = 0;i < ctxt->incNr;i++) {
- newctxt->incTab[i] = ctxt->incTab[i];
- }
- /*
- * The new context should also inherit the Parse Flags
- * (bug 132597)
- */
- newctxt->parseFlags = ctxt->parseFlags;
- newctxt->incTotal = ctxt->incTotal;
- xmlXIncludeDoProcess(newctxt, xmlDocGetRootElement(doc), 0);
- ctxt->incTotal = newctxt->incTotal;
- for (i = 0;i < ctxt->incNr;i++) {
- newctxt->incTab[i] = NULL;
- }
+ xmlXIncludeDoProcess(ctxt, xmlDocGetRootElement(doc));
- xmlXIncludeFreeContext(newctxt);
+ if (ctxt->incTab != NULL) {
+ for (i = 0; i < ctxt->incNr; i++)
+ xmlXIncludeFreeRef(ctxt->incTab[i]);
+ xmlFree(ctxt->incTab);
}
-#ifdef DEBUG_XINCLUDE
- xmlGenericError(xmlGenericErrorContext, "Done recursing in doc %s\n", url);
-#endif
+
+ ctxt->doc = oldDoc;
+ ctxt->incMax = oldIncMax;
+ ctxt->incNr = oldIncNr;
+ ctxt->incTab = oldIncTab;
}
/************************************************************************
@@ -677,17 +637,27 @@ xmlXIncludeRecurseDoc(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc,
* xmlXIncludeCopyNode:
* @ctxt: the XInclude context
* @elem: the element
+ * @copyChildren: copy children instead of node if true
*
* Make a copy of the node while expanding nested XIncludes.
*
* Returns a node list, not a single node.
*/
static xmlNodePtr
-xmlXIncludeCopyNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr elem) {
+xmlXIncludeCopyNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr elem,
+ int copyChildren) {
xmlNodePtr result = NULL;
xmlNodePtr insertParent = NULL;
xmlNodePtr insertLast = NULL;
- xmlNodePtr cur = elem;
+ xmlNodePtr cur;
+
+ if (copyChildren) {
+ cur = elem->children;
+ if (cur == NULL)
+ return(NULL);
+ } else {
+ cur = elem;
+ }
while (1) {
xmlNodePtr copy = NULL;
@@ -745,21 +715,21 @@ xmlXIncludeCopyNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr elem) {
continue;
}
- while ((cur != elem) && (cur->next == NULL)) {
+ if (cur == elem)
+ return(result);
+
+ while (cur->next == NULL) {
cur = cur->parent;
+ if (cur == elem)
+ return(result);
insertParent->last = insertLast;
insertLast = insertParent;
insertParent = insertParent->parent;
}
- if (cur == elem)
- break;
-
cur = cur->next;
}
- return(result);
-
error:
xmlFreeNodeList(result);
return(NULL);
@@ -1063,7 +1033,7 @@ xmlXIncludeCopyXPointer(xmlXIncludeCtxtPtr ctxt, xmlXPathObjectPtr obj) {
* xmlXIncludeCopyNode is only required for the initial
* document.
*/
- copy = xmlXIncludeCopyNode(ctxt, node);
+ copy = xmlXIncludeCopyNode(ctxt, node, 0);
if (copy == NULL) {
xmlFreeNodeList(list);
return(NULL);
@@ -1274,7 +1244,6 @@ xmlXIncludeMergeEntities(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc,
static int
xmlXIncludeLoadDoc(xmlXIncludeCtxtPtr ctxt, const xmlChar *url,
xmlXIncludeRefPtr ref) {
- xmlXIncludeCtxtPtr rootCtxt;
xmlXIncludeDocPtr cache;
xmlDocPtr doc;
xmlURIPtr uri;
@@ -1328,18 +1297,17 @@ xmlXIncludeLoadDoc(xmlXIncludeCtxtPtr ctxt, const xmlChar *url,
/*
* Prevent reloading the document twice.
*/
- rootCtxt = ctxt->rootCtxt;
- for (i = 0; i < rootCtxt->urlNr; i++) {
- if (xmlStrEqual(URL, rootCtxt->urlTab[i].url)) {
+ for (i = 0; i < ctxt->urlNr; i++) {
+ if (xmlStrEqual(URL, ctxt->urlTab[i].url)) {
#ifdef DEBUG_XINCLUDE
printf("Already loaded %s\n", URL);
#endif
- if (rootCtxt->urlTab[i].expanding) {
+ if (ctxt->urlTab[i].expanding) {
xmlXIncludeErr(ctxt, ref->elem, XML_XINCLUDE_RECURSION,
"inclusion loop detected\n", NULL);
return(-1);
}
- doc = rootCtxt->urlTab[i].doc;
+ doc = ctxt->urlTab[i].doc;
if (doc == NULL)
return(-1);
goto loaded;
@@ -1370,20 +1338,20 @@ xmlXIncludeLoadDoc(xmlXIncludeCtxtPtr ctxt, const xmlChar *url,
#endif
/* Also cache NULL docs */
- if (rootCtxt->urlNr >= rootCtxt->urlMax) {
+ if (ctxt->urlNr >= ctxt->urlMax) {
xmlXIncludeDoc *tmp;
- size_t newSize = rootCtxt->urlMax ? rootCtxt->urlMax * 2 : 8;
+ size_t newSize = ctxt->urlMax ? ctxt->urlMax * 2 : 8;
- tmp = xmlRealloc(rootCtxt->urlTab, sizeof(xmlXIncludeDoc) * newSize);
+ tmp = xmlRealloc(ctxt->urlTab, sizeof(xmlXIncludeDoc) * newSize);
if (tmp == NULL) {
xmlXIncludeErrMemory(ctxt, ref->elem,
"growing XInclude URL table");
return(-1);
}
- rootCtxt->urlMax = newSize;
- rootCtxt->urlTab = tmp;
+ ctxt->urlMax = newSize;
+ ctxt->urlTab = tmp;
}
- cache = &rootCtxt->urlTab[rootCtxt->urlNr++];
+ cache = &ctxt->urlTab[ctxt->urlNr++];
cache->doc = doc;
cache->url = xmlStrdup(URL);
cache->expanding = 0;
@@ -1652,7 +1620,6 @@ loaded:
static int
xmlXIncludeLoadTxt(xmlXIncludeCtxtPtr ctxt, const xmlChar *url,
xmlXIncludeRefPtr ref) {
- xmlXIncludeCtxtPtr rootCtxt;
xmlParserInputBufferPtr buf;
xmlNodePtr node;
xmlURIPtr uri;
@@ -1706,9 +1673,8 @@ xmlXIncludeLoadTxt(xmlXIncludeCtxtPtr ctxt, const xmlChar *url,
/*
* Prevent reloading the document twice.
*/
- rootCtxt = ctxt->rootCtxt;
- for (i = 0; i < rootCtxt->txtNr; i++) {
- if (xmlStrEqual(URL, rootCtxt->txtTab[i].url)) {
+ for (i = 0; i < ctxt->txtNr; i++) {
+ if (xmlStrEqual(URL, ctxt->txtTab[i].url)) {
node = xmlNewDocText(ctxt->doc, ctxt->txtTab[i].text);
goto loaded;
}
@@ -1800,22 +1766,22 @@ xinclude_multibyte_fallback:
xmlFreeParserCtxt(pctxt);
xmlFreeInputStream(inputStream);
- if (rootCtxt->txtNr >= rootCtxt->txtMax) {
+ if (ctxt->txtNr >= ctxt->txtMax) {
xmlXIncludeTxt *tmp;
- size_t newSize = rootCtxt->txtMax ? rootCtxt->txtMax * 2 : 8;
+ size_t newSize = ctxt->txtMax ? ctxt->txtMax * 2 : 8;
- tmp = xmlRealloc(rootCtxt->txtTab, sizeof(xmlXIncludeTxt) * newSize);
+ tmp = xmlRealloc(ctxt->txtTab, sizeof(xmlXIncludeTxt) * newSize);
if (tmp == NULL) {
xmlXIncludeErrMemory(ctxt, ref->elem,
"growing XInclude text table");
return(-1);
}
- rootCtxt->txtMax = newSize;
- rootCtxt->txtTab = tmp;
+ ctxt->txtMax = newSize;
+ ctxt->txtTab = tmp;
}
- rootCtxt->txtTab[rootCtxt->txtNr].text = xmlStrdup(node->content);
- rootCtxt->txtTab[rootCtxt->txtNr].url = xmlStrdup(URL);
- rootCtxt->txtNr++;
+ ctxt->txtTab[ctxt->txtNr].text = xmlStrdup(node->content);
+ ctxt->txtTab[ctxt->txtNr].url = xmlStrdup(URL);
+ ctxt->txtNr++;
loaded:
/*
@@ -1840,9 +1806,8 @@ loaded:
static int
xmlXIncludeLoadFallback(xmlXIncludeCtxtPtr ctxt, xmlNodePtr fallback,
xmlXIncludeRefPtr ref) {
- xmlXIncludeCtxtPtr newctxt;
int ret = 0;
- int oldNbErrors = ctxt->nbErrors;
+ int oldNbErrors;
if ((fallback == NULL) || (fallback->type == XML_NAMESPACE_DECL) ||
(ctxt == NULL))
@@ -1852,22 +1817,11 @@ xmlXIncludeLoadFallback(xmlXIncludeCtxtPtr ctxt, xmlNodePtr fallback,
* It's possible that the fallback also has 'includes'
* (Bug 129969), so we re-process the fallback just in case
*/
- newctxt = xmlXIncludeNewContext(ctxt->doc);
- if (newctxt == NULL)
- return (-1);
- newctxt->_private = ctxt->_private;
- newctxt->base = xmlStrdup(ctxt->base); /* Inherit the base from the existing context */
- xmlXIncludeSetFlags(newctxt, ctxt->parseFlags);
- newctxt->incTotal = ctxt->incTotal;
- if (xmlXIncludeDoProcess(newctxt, fallback, 1) < 0)
- ret = -1;
- ctxt->incTotal = newctxt->incTotal;
+ oldNbErrors = ctxt->nbErrors;
+ ref->inc = xmlXIncludeCopyNode(ctxt, fallback, 1);
if (ctxt->nbErrors > oldNbErrors)
ret = -1;
- xmlXIncludeFreeContext(newctxt);
-
- ref->inc = xmlDocCopyNodeList(ctxt->doc, fallback->children);
- if (ref->inc == NULL)
+ else if (ref->inc == NULL)
ref->emptyFb = 1;
} else {
ref->inc = NULL;
@@ -1904,7 +1858,7 @@ xmlXIncludeExpandNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node) {
return(NULL);
}
- for (i = ctxt->incBase; i < ctxt->incNr; i++) {
+ for (i = 0; i < ctxt->incNr; i++) {
if (ctxt->incTab[i]->elem == node) {
if (ctxt->incTab[i]->expanding) {
xmlXIncludeErr(ctxt, node, XML_XINCLUDE_RECURSION,
@@ -2260,7 +2214,6 @@ xmlXIncludeTestNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node) {
* xmlXIncludeDoProcess:
* @ctxt: the XInclude processing context
* @tree: the top of the tree to process
- * @skipRoot: don't process the root node of the tree
*
* Implement the XInclude substitution on the XML document @doc
*
@@ -2268,25 +2221,21 @@ xmlXIncludeTestNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node) {
* or the number of substitutions done.
*/
static int
-xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlNodePtr tree, int skipRoot) {
+xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlNodePtr tree) {
+ xmlXIncludeRefPtr ref;
xmlNodePtr cur;
int ret = 0;
int i;
if ((tree == NULL) || (tree->type == XML_NAMESPACE_DECL))
return(-1);
- if ((skipRoot) && (tree->children == NULL))
- return(-1);
if (ctxt == NULL)
return(-1);
/*
* First phase: lookup the elements in the document
*/
- if (skipRoot)
- cur = tree->children;
- else
- cur = tree;
+ cur = tree;
do {
/* TODO: need to work on entities -> stack */
if (xmlXIncludeTestNode(ctxt, cur) == 1) {
@@ -2299,7 +2248,12 @@ xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlNodePtr tree, int skipRoot) {
return(-1);
#endif
ctxt->incTotal++;
- xmlXIncludeExpandNode(ctxt, cur);
+ ref = xmlXIncludeExpandNode(ctxt, cur);
+ /*
+ * Mark direct includes.
+ */
+ if (ref != NULL)
+ ref->replace = 1;
} else if ((cur->children != NULL) &&
((cur->type == XML_DOCUMENT_NODE) ||
(cur->type == XML_ELEMENT_NODE))) {
@@ -2319,19 +2273,24 @@ xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlNodePtr tree, int skipRoot) {
/*
* Second phase: extend the original document infoset.
- *
- * Originally we bypassed the inclusion if there were any errors
- * encountered on any of the XIncludes. A bug was raised (bug
- * 132588) requesting that we output the XIncludes without error,
- * so the check for inc!=NULL || xptr!=NULL was put in. This may
- * give some other problems in the future, but for now it seems to
- * work ok.
- *
*/
- for (i = ctxt->incBase;i < ctxt->incNr; i++) {
- if ((ctxt->incTab[i]->inc != NULL) ||
- (ctxt->incTab[i]->emptyFb != 0)) /* (empty fallback) */
- xmlXIncludeIncludeNode(ctxt, ctxt->incTab[i]);
+ for (i = 0; i < ctxt->incNr; i++) {
+ if (ctxt->incTab[i]->replace != 0) {
+ if ((ctxt->incTab[i]->inc != NULL) ||
+ (ctxt->incTab[i]->emptyFb != 0)) { /* (empty fallback) */
+ xmlXIncludeIncludeNode(ctxt, ctxt->incTab[i]);
+ ctxt->incTab[i]->replace = 0;
+ }
+ } else {
+ /*
+ * Ignore includes which were added indirectly, for example
+ * inside xi:fallback elements.
+ */
+ if (ctxt->incTab[i]->inc != NULL) {
+ xmlFreeNodeList(ctxt->incTab[i]->inc);
+ ctxt->incTab[i]->inc = NULL;
+ }
+ }
ret++;
}
@@ -2383,7 +2342,7 @@ xmlXIncludeProcessTreeFlagsData(xmlNodePtr tree, int flags, void *data) {
ctxt->_private = data;
ctxt->base = xmlStrdup((xmlChar *)tree->doc->URL);
xmlXIncludeSetFlags(ctxt, flags);
- ret = xmlXIncludeDoProcess(ctxt, tree, 0);
+ ret = xmlXIncludeDoProcess(ctxt, tree);
if ((ret >= 0) && (ctxt->nbErrors > 0))
ret = -1;
@@ -2467,7 +2426,7 @@ xmlXIncludeProcessTreeFlags(xmlNodePtr tree, int flags) {
return(-1);
ctxt->base = xmlNodeGetBase(tree->doc, tree);
xmlXIncludeSetFlags(ctxt, flags);
- ret = xmlXIncludeDoProcess(ctxt, tree, 0);
+ ret = xmlXIncludeDoProcess(ctxt, tree);
if ((ret >= 0) && (ctxt->nbErrors > 0))
ret = -1;
@@ -2507,7 +2466,7 @@ xmlXIncludeProcessNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node) {
if ((node == NULL) || (node->type == XML_NAMESPACE_DECL) ||
(node->doc == NULL) || (ctxt == NULL))
return(-1);
- ret = xmlXIncludeDoProcess(ctxt, node, 0);
+ ret = xmlXIncludeDoProcess(ctxt, node);
if ((ret >= 0) && (ctxt->nbErrors > 0))
ret = -1;
return(ret);