/************************************************************************
* *
+ * Result Value Tree interfaces *
+ * *
+ ************************************************************************/
+/**
+ * xsltCreateRVT:
+ * @ctxt: an XSLT transformation context
+ *
+ * Create a result value tree
+ *
+ * Returns the result value tree or NULL in case of error
+ */
+xmlDocPtr
+xsltCreateRVT(xsltTransformContextPtr ctxt)
+{
+ xmlDocPtr container;
+
+ if (ctxt == NULL) return(NULL);
+
+ container = xmlNewDoc(NULL);
+ if (container == NULL)
+ return(NULL);
+
+ container->name = (char *) xmlStrdup(BAD_CAST " fake node libxslt");
+ container->doc = container;
+ container->parent = NULL;
+ return(container);
+}
+
+/**
+ * xsltRegisterTmpRVT:
+ * @ctxt: an XSLT transformation context
+ * @RVT: a result value tree
+ *
+ * Register the result value tree for destruction at the end of the context
+ *
+ * Returns 0 in case of success and -1 in case of error.
+ */
+int
+xsltRegisterTmpRVT(xsltTransformContextPtr ctxt, xmlDocPtr RVT)
+{
+ if ((ctxt == NULL) || (RVT == NULL)) return(-1);
+
+ RVT->next = (xmlNodePtr) ctxt->tmpRVT;
+ if (ctxt->tmpRVT != NULL)
+ ctxt->tmpRVT->prev = (xmlNodePtr) RVT;
+ ctxt->tmpRVT = RVT;
+ return(0);
+}
+
+/**
+ * xsltRegisterPersistRVT:
+ * @ctxt: an XSLT transformation context
+ * @RVT: a result value tree
+ *
+ * Register the result value tree for destruction at the end of the processing
+ *
+ * Returns 0 in case of success and -1 in case of error.
+ */
+int
+xsltRegisterPersistRVT(xsltTransformContextPtr ctxt, xmlDocPtr RVT)
+{
+ if ((ctxt == NULL) || (RVT == NULL)) return(-1);
+
+ RVT->next = (xmlNodePtr) ctxt->persistRVT;
+ if (ctxt->persistRVT != NULL)
+ ctxt->persistRVT->prev = (xmlNodePtr) RVT;
+ ctxt->persistRVT = RVT;
+ return(0);
+}
+
+/**
+ * xsltFreeRVTs:
+ * @ctxt: an XSLT transformation context
+ *
+ * Free all the registered result value tree of the transformation
+ */
+void
+xsltFreeRVTs(xsltTransformContextPtr ctxt)
+{
+ xmlDocPtr cur, next;
+
+ if (ctxt == NULL) return;
+
+ cur = ctxt->tmpRVT;
+ while (cur != NULL) {
+ next = (xmlDocPtr) cur->next;
+ xmlFreeDoc(cur);
+ cur = next;
+ }
+ cur = ctxt->persistRVT;
+ while (cur != NULL) {
+ next = (xmlDocPtr) cur->next;
+ xmlFreeDoc(cur);
+ cur = next;
+ }
+}
+
+/************************************************************************
+ * *
* Module interfaces *
* *
************************************************************************/
}
/**
+ * xsltStackLookup:
+ * @ctxt: an XSLT transformation context
+ * @name: the local part of the name
+ * @nameURI: the URI part of the name
+ *
+ * Locate an element in the stack based on its name.
+ */
+static xsltStackElemPtr
+xsltStackLookup(xsltTransformContextPtr ctxt, const xmlChar *name,
+ const xmlChar *nameURI) {
+ xsltStackElemPtr ret = NULL;
+ int i;
+ xsltStackElemPtr cur;
+
+ if ((ctxt == NULL) || (name == NULL) || (ctxt->varsNr == 0))
+ return(NULL);
+
+ /*
+ * Do the lookup from the top of the stack, but
+ * don't use params being computed in a call-param
+ */
+ ;
+
+ for (i = ctxt->varsNr; i > ctxt->varsBase; i--) {
+ cur = ctxt->varsTab[i-1];
+ while (cur != NULL) {
+ if (xmlStrEqual(cur->name, name)) {
+ if (nameURI == NULL) {
+ if (cur->nameURI == NULL) {
+ return(cur);
+ }
+ } else {
+ if ((cur->nameURI != NULL) &&
+ (xmlStrEqual(cur->nameURI, nameURI))) {
+ return(cur);
+ }
+ }
+
+ }
+ cur = cur->next;
+ }
+ }
+ return(ret);
+}
+
+/**
* xsltCheckStackElem:
* @ctxt: xn XSLT transformation context
* @name: the variable name
if ((ctxt == NULL) || (name == NULL))
return(-1);
- cur = ctxt->vars;
- while (cur != NULL) {
- if (xmlStrEqual(name, cur->name)) {
- if (((nameURI == NULL) && (cur->nameURI == NULL)) ||
- ((nameURI != NULL) && (cur->nameURI != NULL) &&
- (xmlStrEqual(nameURI, cur->nameURI)))) {
- if ((cur->comp != NULL) &&
- (cur->comp->type == XSLT_FUNC_WITHPARAM))
- return(3);
- if ((cur->comp != NULL) &&
- (cur->comp->type == XSLT_FUNC_PARAM))
- return(2);
- return(1);
- }
- }
- cur = cur->next;
+ cur = xsltStackLookup(ctxt, name, nameURI);
+ if (cur == NULL)
+ return(0);
+ if (cur->comp != NULL) {
+ if (cur->comp->type == XSLT_FUNC_WITHPARAM)
+ return(3);
+ else if (cur->comp->type == XSLT_FUNC_PARAM)
+ return(2);
}
- return(0);
+
+ return(1);
}
/**
return(0);
}
-/**
- * xsltStackLookup:
- * @ctxt: an XSLT transformation context
- * @name: the local part of the name
- * @nameURI: the URI part of the name
- *
- * Locate an element in the stack based on its name.
- */
-static xsltStackElemPtr
-xsltStackLookup(xsltTransformContextPtr ctxt, const xmlChar *name,
- const xmlChar *nameURI) {
- xsltStackElemPtr ret = NULL;
- int i;
- xsltStackElemPtr cur;
-
- if ((ctxt == NULL) || (name == NULL) || (ctxt->varsNr == 0))
- return(NULL);
-
- /*
- * Do the lookup from the top of the stack, but
- * don't use params being computed in a call-param
- */
- ;
-
- for (i = ctxt->varsNr; i > ctxt->varsBase; i--) {
- cur = ctxt->varsTab[i-1];
- while (cur != NULL) {
- if (xmlStrEqual(cur->name, name)) {
- if (nameURI == NULL) {
- if (cur->nameURI == NULL) {
- return(cur);
- }
- } else {
- if ((cur->nameURI != NULL) &&
- (xmlStrEqual(cur->nameURI, nameURI))) {
- return(cur);
- }
- }
-
- }
- cur = cur->next;
- }
- }
- return(ret);
-}
-
/************************************************************************
* *
* Module interfaces *
xmlNodePtr oldInsert;
xmlDocPtr oldoutput;
- container = xmlNewDoc(NULL);
+ container = xsltCreateRVT(ctxt);
if (container == NULL)
return(NULL);
- container->name = xmlStrdup(BAD_CAST " fake node libxslt");
- container->doc = container;
- container->parent = NULL;
-
+ /*
+ * Tag the subtree for removal once consumed
+ */
+ xsltRegisterTmpRVT(ctxt, container);
oldoutput = ctxt->output;
ctxt->output = container;
oldInsert = ctxt->insert;
ctxt->insert = oldInsert;
ctxt->output = oldoutput;
- result = xmlXPathNewValueTree(container);
+ result = xmlXPathNewValueTree((xmlNodePtr) container);
if (result == NULL) {
result = xmlXPathNewCString("");
} else {
- /*
- * Tag the subtree for removal once consumed
- */
- result->boolval = 1;
+ result->boolval = 0; /* Freeing is not handled there anymore */
}
#ifdef WITH_XSLT_DEBUG_VARIABLE
#ifdef LIBXML_DEBUG_ENABLED
xmlNodePtr oldInsert;
xmlDocPtr oldoutput;
- container = xmlNewDoc(NULL);
+ container = xsltCreateRVT(ctxt);
if (container == NULL)
return(NULL);
- container->name = xmlStrdup(BAD_CAST " fake node libxslt");
- container->doc = container;
- container->parent = NULL;
-
+ /*
+ * Tag the subtree for removal once consumed
+ */
+ xsltRegisterTmpRVT(ctxt, container);
+ /*
+ * Save a pointer to the global variable for later cleanup
+ */
+ container->_private = elem;
oldoutput = ctxt->output;
ctxt->output = container;
oldInsert = ctxt->insert;
ctxt->insert = oldInsert;
ctxt->output = oldoutput;
- result = xmlXPathNewValueTree(container);
+ result = xmlXPathNewValueTree((xmlNodePtr) container);
if (result == NULL) {
result = xmlXPathNewCString("");
} else {
- /*
- * Tag the subtree for removal once consumed
- */
- result->boolval = 1;
+ result->boolval = 0; /* Freeing is not handled there anymore */
}
#ifdef WITH_XSLT_DEBUG_VARIABLE
#ifdef LIBXML_DEBUG_ENABLED
xsltStackElemPtr elem;
xsltStylesheetPtr style;
- if (ctxt == NULL)
+ if ((ctxt == NULL) || (ctxt->document == NULL))
return(-1);
#ifdef WITH_XSLT_DEBUG_VARIABLE
xsltGenericDebug(xsltGenericDebugContext,
"Registering global variables\n");
#endif
+
ctxt->node = (xmlNodePtr) ctxt->document->doc;
ctxt->xpathCtxt->contextSize = 1;
ctxt->xpathCtxt->proximityPosition = 1;
xmlHashLookup2(ctxt->globalVars,
elem->name, elem->nameURI);
if (def == NULL) {
- int res;
def = xsltCopyStackElem(elem);
- res = xmlHashAddEntry2(ctxt->globalVars,
+ xmlHashAddEntry2(ctxt->globalVars,
elem->name, elem->nameURI, def);
} else if ((elem->comp != NULL) &&
(elem->comp->type == XSLT_FUNC_VARIABLE)) {
xmlNsPtr *oldNamespaces;
xsltStackElemPtr elem;
int res;
+ void *res_ptr;
if (ctxt == NULL)
return(-1);
if (ncname == NULL)
return (-1);
+ res_ptr = xmlHashLookup2(ctxt->globalVars, ncname, href);
+ if (res_ptr != 0) {
+ xsltTransformError(ctxt, style, NULL,
+ "Global parameter %s already defined\n", ncname);
+ }
+
+ /*
+ * do not overwrite variables with parameters from the command line
+ */
+ while (style != NULL) {
+ elem = ctxt->style->variables;
+ while (elem != NULL) {
+ if ((elem->comp != NULL) &&
+ (elem->comp->type == XSLT_FUNC_VARIABLE) &&
+ (xmlStrEqual(elem->name, ncname)) &&
+ (xmlStrEqual(elem->nameURI, href))) {
+ xmlFree(ncname);
+ return(0);
+ }
+ elem = elem->next;
+ }
+ style = xsltNextImport(style);
+ }
+ style = ctxt->style;
+ elem = NULL;
+
/*
* Do the evaluation if @eval is non-zero.
*/