*
* See Copyright for the status of this software.
*
- * Daniel.Veillard@imag.fr
+ * daniel@veillard.com
*/
-#include "xsltconfig.h"
+#define IN_LIBXSLT
+#include "libxslt.h"
#include <string.h>
#include <libxml/xpath.h>
#include <libxml/xpathInternals.h>
#include <libxml/parserInternals.h>
-#include <libxml/xmlversion.h>
#include "xslt.h"
#include "xsltInternals.h"
#include "xsltutils.h"
#include "variables.h"
#include "transform.h"
#include "imports.h"
+#include "preproc.h"
-#define DEBUG_VARIABLE
+#ifdef WITH_XSLT_DEBUG
+#define WITH_XSLT_DEBUG_VARIABLE
+#endif
+
+/************************************************************************
+ * *
+ * 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;
+ }
+}
/************************************************************************
* *
*
* Returns the newly allocated xsltParserStackElem or NULL in case of error
*/
-xsltStackElemPtr
+static xsltStackElemPtr
xsltNewStackElem(void) {
xsltStackElemPtr cur;
cur = (xsltStackElemPtr) xmlMalloc(sizeof(xsltStackElem));
if (cur == NULL) {
- xsltGenericError(xsltGenericErrorContext,
+ xsltTransformError(NULL, NULL, NULL,
"xsltNewStackElem : malloc failed\n");
return(NULL);
}
- memset(cur, 0, sizeof(xsltStackElem));
cur->computed = 0;
+ cur->name = NULL;
+ cur->nameURI = NULL;
+ cur->select = NULL;
+ cur->tree = NULL;
+ cur->value = NULL;
+ cur->comp = NULL;
+ return(cur);
+}
+
+/**
+ * xsltCopyStackElem:
+ * @elem: an XSLT stack element
+ *
+ * Makes a copy of the stack element
+ *
+ * Returns the copy of NULL
+ */
+static xsltStackElemPtr
+xsltCopyStackElem(xsltStackElemPtr elem) {
+ xsltStackElemPtr cur;
+
+ cur = (xsltStackElemPtr) xmlMalloc(sizeof(xsltStackElem));
+ if (cur == NULL) {
+ xsltTransformError(NULL, NULL, NULL,
+ "xsltCopyStackElem : malloc failed\n");
+ return(NULL);
+ }
+ cur->name = xmlStrdup(elem->name);
+ cur->nameURI = xmlStrdup(elem->nameURI);
+ cur->select = xmlStrdup(elem->select);
+ cur->tree = elem->tree;
+ cur->comp = elem->comp;
+ cur->computed = 0;
+ cur->value = NULL;
return(cur);
}
*
* Free up the memory allocated by @elem
*/
-void
+static void
xsltFreeStackElem(xsltStackElemPtr elem) {
if (elem == NULL)
return;
if (elem->value != NULL)
xmlXPathFreeObject(elem->value);
- memset(elem, -1, sizeof(xsltStackElem));
xmlFree(elem);
}
}
/**
+ * 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
*
* check wether the variable or param is already defined
*
- * Returns 1 if present, 0 if not, -1 in case of failure.
+ * Returns 1 if variable is present, 2 if param is present, 3 if this
+ * is an inherited param, 0 if not found, -1 in case of failure.
*/
-int
+static int
xsltCheckStackElem(xsltTransformContextPtr ctxt, const xmlChar *name,
const xmlChar *nameURI) {
xsltStackElemPtr cur;
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)))) {
- 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);
}
/**
*
* Returns 0 in case of success, -1 in case of failure.
*/
-int
+static int
xsltAddStackElem(xsltTransformContextPtr ctxt, xsltStackElemPtr elem) {
if ((ctxt == NULL) || (elem == NULL))
return(-1);
return(0);
}
+/************************************************************************
+ * *
+ * Module interfaces *
+ * *
+ ************************************************************************/
+
/**
- * xsltStackLookup:
- * @ctxt: an XSLT transformation context
- * @name: the local part of the name
- * @nameURI: the URI part of the name
+ * xsltEvalVariable:
+ * @ctxt: the XSLT transformation context
+ * @elem: the variable or parameter.
+ * @precomp: pointer to precompiled data
*
- * Locate an element in the stack based on its name.
+ * Evaluate a variable value.
+ *
+ * Returns the XPath Object value or NULL in case of error
*/
-xsltStackElemPtr
-xsltStackLookup(xsltTransformContextPtr ctxt, const xmlChar *name,
- const xmlChar *nameURI) {
- xsltStackElemPtr ret = NULL;
- int i;
- xsltStackElemPtr cur;
+static xmlXPathObjectPtr
+xsltEvalVariable(xsltTransformContextPtr ctxt, xsltStackElemPtr elem,
+ xsltStylePreCompPtr precomp) {
+ xmlXPathObjectPtr result = NULL;
+ int oldProximityPosition, oldContextSize;
+ xmlNodePtr oldInst, oldNode;
+ xsltDocumentPtr oldDoc;
+ int oldNsNr;
+ xmlNsPtr *oldNamespaces;
- if ((ctxt == NULL) || (name == NULL))
+ if ((ctxt == NULL) || (elem == NULL))
return(NULL);
- /*
- * Do the lookup from the top of the stack, but
- * don't use params being computed in a call-param
- */
- i = ctxt->varsNr - 1;
+#ifdef WITH_XSLT_DEBUG_VARIABLE
+ xsltGenericDebug(xsltGenericDebugContext,
+ "Evaluating variable %s\n", elem->name);
+#endif
+ if (elem->select != NULL) {
+ xmlXPathCompExprPtr comp = NULL;
- for (;i >= 0;i--) {
- cur = ctxt->varsTab[i];
- 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);
- }
- }
+ if ((precomp != NULL) && (precomp->comp != NULL)) {
+ comp = precomp->comp;
+ } else {
+ comp = xmlXPathCompile(elem->select);
+ }
+ if (comp == NULL)
+ return(NULL);
+ oldProximityPosition = ctxt->xpathCtxt->proximityPosition;
+ oldContextSize = ctxt->xpathCtxt->contextSize;
+ ctxt->xpathCtxt->node = (xmlNodePtr) ctxt->node;
+ oldDoc = ctxt->document;
+ oldNode = ctxt->node;
+ oldInst = ctxt->inst;
+ oldNsNr = ctxt->xpathCtxt->nsNr;
+ oldNamespaces = ctxt->xpathCtxt->namespaces;
+ if (precomp != NULL) {
+ ctxt->inst = precomp->inst;
+ ctxt->xpathCtxt->namespaces = precomp->nsList;
+ ctxt->xpathCtxt->nsNr = precomp->nsNr;
+ } else {
+ ctxt->inst = NULL;
+ ctxt->xpathCtxt->namespaces = NULL;
+ ctxt->xpathCtxt->nsNr = 0;
+ }
+ result = xmlXPathCompiledEval(comp, ctxt->xpathCtxt);
+ ctxt->xpathCtxt->contextSize = oldContextSize;
+ ctxt->xpathCtxt->proximityPosition = oldProximityPosition;
+ ctxt->xpathCtxt->nsNr = oldNsNr;
+ ctxt->xpathCtxt->namespaces = oldNamespaces;
+ ctxt->inst = oldInst;
+ ctxt->node = oldNode;
+ ctxt->document = oldDoc;
+ if ((precomp == NULL) || (precomp->comp == NULL))
+ xmlXPathFreeCompExpr(comp);
+ if (result == NULL) {
+ xsltTransformError(ctxt, NULL, precomp->inst,
+ "Evaluating variable %s failed\n", elem->name);
+ ctxt->state = XSLT_STATE_STOPPED;
+#ifdef WITH_XSLT_DEBUG_VARIABLE
+#ifdef LIBXML_DEBUG_ENABLED
+ } else {
+ if ((xsltGenericDebugContext == stdout) ||
+ (xsltGenericDebugContext == stderr))
+ xmlXPathDebugDumpObject((FILE *)xsltGenericDebugContext,
+ result, 0);
+#endif
+#endif
+ }
+ } else {
+ if (elem->tree == NULL) {
+ result = xmlXPathNewCString("");
+ } else {
+ /*
+ * This is a result tree fragment.
+ */
+ xmlDocPtr container;
+ xmlNodePtr oldInsert;
+ xmlDocPtr oldoutput;
+ container = xsltCreateRVT(ctxt);
+ if (container == NULL)
+ return(NULL);
+ /*
+ * Tag the subtree for removal once consumed
+ */
+ xsltRegisterTmpRVT(ctxt, container);
+ oldoutput = ctxt->output;
+ ctxt->output = container;
+ oldInsert = ctxt->insert;
+ ctxt->insert = (xmlNodePtr) container;
+ xsltApplyOneTemplate(ctxt, ctxt->node, elem->tree, NULL, NULL);
+ ctxt->insert = oldInsert;
+ ctxt->output = oldoutput;
+
+ result = xmlXPathNewValueTree((xmlNodePtr) container);
+ if (result == NULL) {
+ result = xmlXPathNewCString("");
+ } else {
+ result->boolval = 0; /* Freeing is not handled there anymore */
}
- cur = cur->next;
+#ifdef WITH_XSLT_DEBUG_VARIABLE
+#ifdef LIBXML_DEBUG_ENABLED
+ if ((xsltGenericDebugContext == stdout) ||
+ (xsltGenericDebugContext == stderr))
+ xmlXPathDebugDumpObject((FILE *)xsltGenericDebugContext,
+ result, 0);
+#endif
+#endif
}
}
- return(ret);
+ return(result);
}
-/************************************************************************
- * *
- * Module interfaces *
- * *
- ************************************************************************/
-
/**
- * xsltEvalVariable:
- * @ctxt: the XSLT transformation context
+ * xsltEvalGlobalVariable:
* @elem: the variable or parameter.
+ * @ctxt: the XSLT transformation context
*
- * Evaluate a variable value.
+ * Evaluate a global variable value.
*
- * Returns 0 in case of success, -1 in case of error
+ * Returns the XPath Object value or NULL in case of error
*/
-int
-xsltEvalVariables(xsltTransformContextPtr ctxt, xsltStackElemPtr elem) {
- xmlXPathParserContextPtr xpathParserCtxt;
+static xmlXPathObjectPtr
+xsltEvalGlobalVariable(xsltStackElemPtr elem, xsltTransformContextPtr ctxt) {
+ xmlXPathObjectPtr result = NULL;
+ xsltStylePreCompPtr precomp;
+ int oldProximityPosition, oldContextSize;
+ xmlNodePtr oldInst;
+ int oldNsNr;
+ xmlNsPtr *oldNamespaces;
+ xmlChar *name;
if ((ctxt == NULL) || (elem == NULL))
- return(-1);
+ return(NULL);
+ if (elem->computed)
+ return(elem->value);
-#ifdef DEBUG_VARIABLE
+
+#ifdef WITH_XSLT_DEBUG_VARIABLE
xsltGenericDebug(xsltGenericDebugContext,
- "Evaluating variable %s\n", elem->name);
+ "Evaluating global variable %s\n", elem->name);
#endif
+
+#ifdef WITH_DEBUGGER
+ if ((xslDebugStatus != XSLT_DEBUG_NONE) &&
+ elem->comp && elem->comp->inst)
+ xslHandleDebugger(elem->comp->inst, NULL, NULL, ctxt);
+#endif
+
+ name = elem->name;
+ elem->name = BAD_CAST " being computed ... ";
+
+ precomp = elem->comp;
if (elem->select != NULL) {
- xmlXPathObjectPtr result, tmp;
+ xmlXPathCompExprPtr comp = NULL;
- xpathParserCtxt = xmlXPathNewParserContext(elem->select,
- ctxt->xpathCtxt);
- if (xpathParserCtxt == NULL)
- return(-1);
+ if ((precomp != NULL) && (precomp->comp != NULL)) {
+ comp = precomp->comp;
+ } else {
+ comp = xmlXPathCompile(elem->select);
+ }
+ if (comp == NULL) {
+ elem->name = name;
+ return(NULL);
+ }
+ oldProximityPosition = ctxt->xpathCtxt->proximityPosition;
+ oldContextSize = ctxt->xpathCtxt->contextSize;
+ oldInst = ctxt->inst;
+ oldNsNr = ctxt->xpathCtxt->nsNr;
+ oldNamespaces = ctxt->xpathCtxt->namespaces;
+ if (precomp != NULL) {
+ ctxt->inst = precomp->inst;
+ ctxt->xpathCtxt->namespaces = precomp->nsList;
+ ctxt->xpathCtxt->nsNr = precomp->nsNr;
+ } else {
+ ctxt->inst = NULL;
+ ctxt->xpathCtxt->namespaces = NULL;
+ ctxt->xpathCtxt->nsNr = 0;
+ }
ctxt->xpathCtxt->node = (xmlNodePtr) ctxt->node;
- xmlXPathEvalExpr(xpathParserCtxt);
- result = valuePop(xpathParserCtxt);
- do {
- tmp = valuePop(xpathParserCtxt);
- if (tmp != NULL) {
- xmlXPathFreeObject(tmp);
- }
- } while (tmp != NULL);
-
+ result = xmlXPathCompiledEval(comp, ctxt->xpathCtxt);
+ ctxt->xpathCtxt->contextSize = oldContextSize;
+ ctxt->xpathCtxt->proximityPosition = oldProximityPosition;
+ ctxt->inst = oldInst;
+ ctxt->xpathCtxt->nsNr = oldNsNr;
+ ctxt->xpathCtxt->namespaces = oldNamespaces;
+ if ((precomp == NULL) || (precomp->comp == NULL))
+ xmlXPathFreeCompExpr(comp);
if (result == NULL) {
- xsltGenericError(xsltGenericErrorContext,
- "Evaluating global variable %s failed\n");
- }
- if (xpathParserCtxt != NULL)
- xmlXPathFreeParserContext(xpathParserCtxt);
- if (result != NULL) {
-#ifdef DEBUG_VARIABLE
+ xsltTransformError(ctxt, NULL, precomp->inst,
+ "Evaluating global variable %s failed\n", elem->name);
+ ctxt->state = XSLT_STATE_STOPPED;
+#ifdef WITH_XSLT_DEBUG_VARIABLE
#ifdef LIBXML_DEBUG_ENABLED
+ } else {
if ((xsltGenericDebugContext == stdout) ||
(xsltGenericDebugContext == stderr))
xmlXPathDebugDumpObject((FILE *)xsltGenericDebugContext,
result, 0);
#endif
#endif
- if (elem->value != NULL)
- xmlXPathFreeObject(elem->value);
- elem->value = result;
}
- elem->computed = 1;
} else {
if (elem->tree == NULL) {
- elem->value = xmlXPathNewCString("");
+ result = xmlXPathNewCString("");
} else {
/*
* This is a result tree fragment.
*/
- xmlNodePtr container;
- xmlNodePtr oldInsert, oldNode;
+ xmlDocPtr container;
+ xmlNodePtr oldInsert;
+ xmlDocPtr oldoutput;
- container = xmlNewDocNode(ctxt->output, NULL,
- (const xmlChar *) "fake", NULL);
+ container = xsltCreateRVT(ctxt);
if (container == NULL)
- return(-1);
-
+ return(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;
- oldNode = ctxt->node;
- ctxt->insert = container;
- xsltApplyOneTemplate(ctxt, ctxt->node, elem->tree, 0);
+ ctxt->insert = (xmlNodePtr) container;
+ xsltApplyOneTemplate(ctxt, ctxt->node, elem->tree, NULL, NULL);
ctxt->insert = oldInsert;
- ctxt->node = oldNode;
+ ctxt->output = oldoutput;
- if (elem->value != NULL)
- xmlXPathFreeObject(elem->value);
- elem->value = xmlXPathNewValueTree(container);
- if (elem->value == NULL) {
- elem->value = xmlXPathNewCString("");
+ result = xmlXPathNewValueTree((xmlNodePtr) container);
+ if (result == NULL) {
+ result = xmlXPathNewCString("");
+ } else {
+ result->boolval = 0; /* Freeing is not handled there anymore */
}
-#ifdef DEBUG_VARIABLE
+#ifdef WITH_XSLT_DEBUG_VARIABLE
#ifdef LIBXML_DEBUG_ENABLED
if ((xsltGenericDebugContext == stdout) ||
(xsltGenericDebugContext == stderr))
xmlXPathDebugDumpObject((FILE *)xsltGenericDebugContext,
- elem->value, 0);
+ result, 0);
#endif
#endif
}
+ }
+ if (result != NULL) {
+ elem->value = result;
elem->computed = 1;
}
- return(0);
+ elem->name = name;
+ return(result);
}
+
/**
* xsltEvalGlobalVariables:
* @ctxt: the XSLT transformation context
xsltStackElemPtr elem;
xsltStylesheetPtr style;
- if (ctxt == NULL)
+ if ((ctxt == NULL) || (ctxt->document == NULL))
return(-1);
-#ifdef DEBUG_VARIABLE
+#ifdef WITH_XSLT_DEBUG_VARIABLE
xsltGenericDebug(xsltGenericDebugContext,
- "Evaluating global variables\n");
+ "Registering global variables\n");
#endif
+
ctxt->node = (xmlNodePtr) ctxt->document->doc;
+ ctxt->xpathCtxt->contextSize = 1;
+ ctxt->xpathCtxt->proximityPosition = 1;
+
+ /*
+ * Walk the list from the stylesheets and populate the hash table
+ */
style = ctxt->style;
while (style != NULL) {
elem = style->variables;
+#ifdef WITH_XSLT_DEBUG_VARIABLE
+ if ((style->doc != NULL) && (style->doc->URL != NULL)) {
+ xsltGenericDebug(xsltGenericDebugContext,
+ "Registering global variables from %s\n",
+ style->doc->URL);
+ }
+#endif
+
while (elem != NULL) {
- xsltEvalVariables(ctxt, elem);
+ xsltStackElemPtr def;
+
+ /*
+ * Global variables are stored in the variables pool.
+ */
+ def = (xsltStackElemPtr)
+ xmlHashLookup2(ctxt->globalVars,
+ elem->name, elem->nameURI);
+ if (def == NULL) {
+
+ def = xsltCopyStackElem(elem);
+ xmlHashAddEntry2(ctxt->globalVars,
+ elem->name, elem->nameURI, def);
+ } else if ((elem->comp != NULL) &&
+ (elem->comp->type == XSLT_FUNC_VARIABLE)) {
+ /*
+ * Redefinition of variables from a different stylesheet
+ * should not generate a message.
+ */
+ if ((elem->comp->inst != NULL) &&
+ (def->comp != NULL) && (def->comp->inst != NULL) &&
+ (elem->comp->inst->doc == def->comp->inst->doc)) {
+ xsltTransformError(ctxt, style, elem->comp->inst,
+ "Global variable %s already defined\n", elem->name);
+ if (style != NULL) style->errors++;
+ }
+ }
elem = elem->next;
}
style = xsltNextImport(style);
}
+
+ /*
+ * This part does the actual evaluation
+ */
+ ctxt->node = (xmlNodePtr) ctxt->document->doc;
+ ctxt->xpathCtxt->contextSize = 1;
+ ctxt->xpathCtxt->proximityPosition = 1;
+ xmlHashScan(ctxt->globalVars,
+ (xmlHashScanner) xsltEvalGlobalVariable, ctxt);
+
return(0);
}
* @ns_uri: the variable namespace URI
* @select: the expression which need to be evaluated to generate a value
* @tree: the subtree if select is NULL
- * @param: this is a parameter actually
+ * @comp: the precompiled value
+ * @value: the string value if available
+ *
+ * Register a new variable value. If @value is NULL it unregisters
+ * the variable
+ *
+ * Returns 0 in case of success, -1 in case of error
+ */
+static int
+xsltRegisterGlobalVariable(xsltStylesheetPtr style, const xmlChar *name,
+ const xmlChar *ns_uri, const xmlChar *select,
+ xmlNodePtr tree, xsltStylePreCompPtr comp,
+ const xmlChar *value) {
+ xsltStackElemPtr elem, tmp;
+ if (style == NULL)
+ return(-1);
+ if (name == NULL)
+ return(-1);
+ if (comp == NULL)
+ return(-1);
+
+#ifdef WITH_XSLT_DEBUG_VARIABLE
+ if (comp->type == XSLT_FUNC_PARAM)
+ xsltGenericDebug(xsltGenericDebugContext,
+ "Defining global param %s\n", name);
+ else
+ xsltGenericDebug(xsltGenericDebugContext,
+ "Defining global variable %s\n", name);
+#endif
+
+ elem = xsltNewStackElem();
+ if (elem == NULL)
+ return(-1);
+ elem->comp = comp;
+ elem->name = xmlStrdup(name);
+ elem->select = xmlStrdup(select);
+ if (ns_uri)
+ elem->nameURI = xmlStrdup(ns_uri);
+ elem->tree = tree;
+ tmp = style->variables;
+ if (tmp == NULL) {
+ elem->next = NULL;
+ style->variables = elem;
+ } else {
+ while (tmp != NULL) {
+ if ((elem->comp->type == XSLT_FUNC_VARIABLE) &&
+ (tmp->comp->type == XSLT_FUNC_VARIABLE) &&
+ (xmlStrEqual(elem->name, tmp->name)) &&
+ ((elem->nameURI == tmp->nameURI) ||
+ (xmlStrEqual(elem->nameURI, tmp->nameURI)))) {
+ xsltTransformError(NULL, style, comp->inst,
+ "redefinition of global variable %s\n", elem->name);
+ if (style != NULL) style->errors++;
+ }
+ if (tmp->next == NULL)
+ break;
+ tmp = tmp->next;
+ }
+ elem->next = NULL;
+ tmp->next = elem;
+ }
+ if (value != NULL) {
+ elem->computed = 1;
+ elem->value = xmlXPathNewString(value);
+ }
+ return(0);
+}
+
+/**
+ * xsltProcessUserParamInternal
+ *
+ * @ctxt: the XSLT transformation context
+ * @name: a null terminated parameter name
+ * @value: a null terminated value (may be an XPath expression)
+ * @eval: 0 to treat the value literally, else evaluate as XPath expression
+ *
+ * If @eval is 0 then @value is treated literally and is stored in the global
+ * parameter/variable table without any change.
+ *
+ * Uf @eval is 1 then @value is treated as an XPath expression and is
+ * evaluated. In this case, if you want to pass a string which will be
+ * interpreted literally then it must be enclosed in single or double quotes.
+ * If the string contains single quotes (double quotes) then it cannot be
+ * enclosed single quotes (double quotes). If the string which you want to
+ * be treated literally contains both single and double quotes (e.g. Meet
+ * at Joe's for "Twelfth Night" at 7 o'clock) then there is no suitable
+ * quoting character. You cannot use ' or " inside the string
+ * because the replacement of character entities with their equivalents is
+ * done at a different stage of processing. The solution is to call
+ * xsltQuoteUserParams or xsltQuoteOneUserParam.
+ *
+ * This needs to be done on parsed stylesheets before starting to apply
+ * transformations. Normally this will be called (directly or indirectly)
+ * only from xsltEvalUserParams, xsltEvalOneUserParam, xsltQuoteUserParams,
+ * or xsltQuoteOneUserParam.
+ *
+ * Returns 0 in case of success, -1 in case of error
+ */
+
+static
+int
+xsltProcessUserParamInternal(xsltTransformContextPtr ctxt,
+ const xmlChar * name,
+ const xmlChar * value,
+ int eval) {
+
+ xsltStylesheetPtr style;
+ xmlChar *ncname;
+ xmlChar *prefix;
+ const xmlChar *href;
+ xmlXPathCompExprPtr comp;
+ xmlXPathObjectPtr result;
+ int oldProximityPosition;
+ int oldContextSize;
+ int oldNsNr;
+ xmlNsPtr *oldNamespaces;
+ xsltStackElemPtr elem;
+ int res;
+ void *res_ptr;
+
+ if (ctxt == NULL)
+ return(-1);
+ if (name == NULL)
+ return(0);
+ if (value == NULL)
+ return(0);
+
+ style = ctxt->style;
+
+#ifdef WITH_XSLT_DEBUG_VARIABLE
+ xsltGenericDebug(xsltGenericDebugContext,
+ "Evaluating user parameter %s=%s\n", name, value);
+#endif
+
+ /*
+ * Name lookup
+ */
+
+ ncname = xmlSplitQName2(name, &prefix);
+ href = NULL;
+ if (ncname != NULL) {
+ if (prefix != NULL) {
+ xmlNsPtr ns;
+
+ ns = xmlSearchNs(style->doc, xmlDocGetRootElement(style->doc),
+ prefix);
+ if (ns == NULL) {
+ xsltTransformError(ctxt, style, NULL,
+ "user param : no namespace bound to prefix %s\n", prefix);
+ href = NULL;
+ } else {
+ href = ns->href;
+ }
+ xmlFree(prefix);
+ prefix = NULL;
+ } else {
+ href = NULL;
+ }
+ xmlFree(ncname);
+ ncname = NULL;
+ } else {
+ href = NULL;
+ ncname = xmlStrdup(name);
+ }
+
+ 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.
+ */
+
+ result = NULL;
+ if (eval != 0) {
+ comp = xmlXPathCompile(value);
+ if (comp != NULL) {
+ oldProximityPosition = ctxt->xpathCtxt->proximityPosition;
+ oldContextSize = ctxt->xpathCtxt->contextSize;
+ ctxt->xpathCtxt->node = (xmlNodePtr) ctxt->node;
+
+ /*
+ * There is really no in scope namespace for parameters on the
+ * command line.
+ */
+
+ oldNsNr = ctxt->xpathCtxt->nsNr;
+ oldNamespaces = ctxt->xpathCtxt->namespaces;
+ ctxt->xpathCtxt->namespaces = NULL;
+ ctxt->xpathCtxt->nsNr = 0;
+ result = xmlXPathCompiledEval(comp, ctxt->xpathCtxt);
+ ctxt->xpathCtxt->contextSize = oldContextSize;
+ ctxt->xpathCtxt->proximityPosition = oldProximityPosition;
+ ctxt->xpathCtxt->nsNr = oldNsNr;
+ ctxt->xpathCtxt->namespaces = oldNamespaces;
+ xmlXPathFreeCompExpr(comp);
+ }
+ if (result == NULL) {
+ xsltTransformError(ctxt, style, NULL,
+ "Evaluating user parameter %s failed\n", name);
+ ctxt->state = XSLT_STATE_STOPPED;
+ xmlFree(ncname);
+ return(-1);
+ }
+ }
+
+ /*
+ * If @eval is 0 then @value is to be taken literally and result is NULL
+ *
+ * If @eval is not 0, then @value is an XPath expression and has been
+ * successfully evaluated and result contains the resulting value and
+ * is not NULL.
+ *
+ * Now create an xsltStackElemPtr for insertion into the context's
+ * global variable/parameter hash table.
+ */
+
+#ifdef WITH_XSLT_DEBUG_VARIABLE
+#ifdef LIBXML_DEBUG_ENABLED
+ if ((xsltGenericDebugContext == stdout) ||
+ (xsltGenericDebugContext == stderr))
+ xmlXPathDebugDumpObject((FILE *)xsltGenericDebugContext,
+ result, 0);
+#endif
+#endif
+
+ elem = xsltNewStackElem();
+ if (elem != NULL) {
+ elem->name = xmlStrdup(ncname);
+ if (value != NULL)
+ elem->select = xmlStrdup(value);
+ else
+ elem->select = NULL;
+ if (href)
+ elem->nameURI = xmlStrdup(href);
+ elem->tree = NULL;
+ elem->computed = 1;
+ if (eval == 0) {
+ elem->value = xmlXPathNewString(value);
+ }
+ else {
+ elem->value = result;
+ }
+ }
+
+ /*
+ * Global parameters are stored in the XPath context variables pool.
+ */
+
+ res = xmlHashAddEntry2(ctxt->globalVars, ncname, href, elem);
+ if (res != 0) {
+ xsltFreeStackElem(elem);
+ xsltTransformError(ctxt, style, NULL,
+ "Global parameter %s already defined\n", ncname);
+ }
+ xmlFree(ncname);
+ return(0);
+}
+
+/**
+ * xsltEvalUserParams:
+ *
+ * @ctxt: the XSLT transformation context
+ * @params: a NULL terminated array of parameters name/value tuples
+ *
+ * Evaluate the global variables of a stylesheet. This needs to be
+ * done on parsed stylesheets before starting to apply transformations.
+ * Each of the parameters is evaluated as an XPath expression and stored
+ * in the global variables/parameter hash table. If you want your
+ * parameter used literally, use xsltQuoteUserParams.
+ *
+ * Returns 0 in case of success, -1 in case of error
+ */
+
+int
+xsltEvalUserParams(xsltTransformContextPtr ctxt, const char **params) {
+ int indx = 0;
+ const xmlChar *name;
+ const xmlChar *value;
+
+ if (params == NULL)
+ return(0);
+ while (params[indx] != NULL) {
+ name = (const xmlChar *) params[indx++];
+ value = (const xmlChar *) params[indx++];
+ if (xsltEvalOneUserParam(ctxt, name, value) != 0)
+ return(-1);
+ }
+ return 0;
+}
+
+/**
+ * xsltQuoteUserParams:
+ *
+ * @ctxt: the XSLT transformation context
+ * @params: a NULL terminated arry of parameters names/values tuples
+ *
+ * Similar to xsltEvalUserParams, but the values are treated literally and
+ * are * *not* evaluated as XPath expressions. This should be done on parsed
+ * stylesheets before starting to apply transformations.
+ *
+ * Returns 0 in case of success, -1 in case of error.
+ */
+
+int
+xsltQuoteUserParams(xsltTransformContextPtr ctxt, const char **params) {
+ int indx = 0;
+ const xmlChar *name;
+ const xmlChar *value;
+
+ if (params == NULL)
+ return(0);
+ while (params[indx] != NULL) {
+ name = (const xmlChar *) params[indx++];
+ value = (const xmlChar *) params[indx++];
+ if (xsltQuoteOneUserParam(ctxt, name, value) != 0)
+ return(-1);
+ }
+ return 0;
+}
+
+/**
+ * xsltEvalOneUserParam:
+ * @ctxt: the XSLT transformation context
+ * @name: a null terminated string giving the name of the parameter
+ * @value: a null terminated string giving the XPath expression to be evaluated
+ *
+ * This is normally called from xsltEvalUserParams to process a single
+ * parameter from a list of parameters. The @value is evaluated as an
+ * XPath expression and the result is stored in the context's global
+ * variable/parameter hash table.
+ *
+ * To have a parameter treated literally (not as an XPath expression)
+ * use xsltQuoteUserParams (or xsltQuoteOneUserParam). For more
+ * details see description of xsltProcessOneUserParamInternal.
+ *
+ * Returns 0 in case of success, -1 in case of error.
+ */
+
+int
+xsltEvalOneUserParam(xsltTransformContextPtr ctxt,
+ const xmlChar * name,
+ const xmlChar * value) {
+ return xsltProcessUserParamInternal(ctxt, name, value,
+ 1 /* xpath eval ? */);
+}
+
+/**
+ * xsltQuoteOneUserParam:
+ * @ctxt: the XSLT transformation context
+ * @name: a null terminated string giving the name of the parameter
+ * @value: a null terminated string giving the parameter value
*
- * Register a new variable value. If @value is NULL it unregisters
- * the variable
+ * This is normally called from xsltQuoteUserParams to process a single
+ * parameter from a list of parameters. The @value is stored in the
+ * context's global variable/parameter hash table.
*
- * Returns 0 in case of success, -1 in case of error
+ * Returns 0 in case of success, -1 in case of error.
*/
-int
-xsltRegisterGlobalVariable(xsltStylesheetPtr style, const xmlChar *name,
- const xmlChar *ns_uri, const xmlChar *select,
- xmlNodePtr tree, int param) {
- xsltStackElemPtr elem;
- if (style == NULL)
- return(-1);
- if (name == NULL)
- return(-1);
-#ifdef DEBUG_VARIABLE
- if (param)
- xsltGenericDebug(xsltGenericDebugContext,
- "Defineing global param %s\n", name);
- else
- xsltGenericDebug(xsltGenericDebugContext,
- "Defineing global variable %s\n", name);
-#endif
- elem = xsltNewStackElem();
- if (elem == NULL)
- return(-1);
- if (param)
- elem->type = XSLT_ELEM_PARAM;
- else
- elem->type = XSLT_ELEM_VARIABLE;
- elem->name = xmlStrdup(name);
- elem->select = xmlStrdup(select);
- if (ns_uri)
- elem->nameURI = xmlStrdup(ns_uri);
- elem->tree = tree;
- elem->next = style->variables;
- style->variables = elem;
- return(0);
+int
+xsltQuoteOneUserParam(xsltTransformContextPtr ctxt,
+ const xmlChar * name,
+ const xmlChar * value) {
+ return xsltProcessUserParamInternal(ctxt, name, value,
+ 0 /* xpath eval ? */);
}
/**
* xsltBuildVariable:
* @ctxt: the XSLT transformation context
- * @name: the variable name
- * @ns_uri: the variable namespace URI
- * @select: the expression which need to be evaluated to generate a value
+ * @comp: the precompiled form
* @tree: the tree if select is NULL
- * @param: this is a parameter actually
*
* Computes a new variable value.
*
* Returns the xsltStackElemPtr or NULL in case of error
*/
-xsltStackElemPtr
-xsltBuildVariable(xsltTransformContextPtr ctxt, const xmlChar *name,
- const xmlChar *ns_uri, const xmlChar *select,
- xmlNodePtr tree, int param) {
+static xsltStackElemPtr
+xsltBuildVariable(xsltTransformContextPtr ctxt, xsltStylePreCompPtr comp,
+ xmlNodePtr tree) {
xsltStackElemPtr elem;
- if (ctxt == NULL)
- return(NULL);
- if (name == NULL)
- return(NULL);
-#ifdef DEBUG_VARIABLE
+#ifdef WITH_XSLT_DEBUG_VARIABLE
xsltGenericDebug(xsltGenericDebugContext,
- "Building variable %s", name);
- if (select != NULL)
+ "Building variable %s", comp->name);
+ if (comp->select != NULL)
xsltGenericDebug(xsltGenericDebugContext,
- " select %s", select);
+ " select %s", comp->select);
xsltGenericDebug(xsltGenericDebugContext, "\n");
#endif
+
elem = xsltNewStackElem();
if (elem == NULL)
return(NULL);
- if (param)
- elem->type = XSLT_ELEM_PARAM;
- else
- elem->type = XSLT_ELEM_VARIABLE;
- elem->name = xmlStrdup(name);
- if (select != NULL)
- elem->select = xmlStrdup(select);
+ elem->comp = comp;
+ elem->name = xmlStrdup(comp->name);
+ if (comp->select != NULL)
+ elem->select = xmlStrdup(comp->select);
else
elem->select = NULL;
- if (ns_uri)
- elem->nameURI = xmlStrdup(ns_uri);
+ if (comp->ns)
+ elem->nameURI = xmlStrdup(comp->ns);
elem->tree = tree;
- xsltEvalVariables(ctxt, elem);
+ if (elem->computed == 0) {
+ elem->value = xsltEvalVariable(ctxt, elem, comp);
+ if (elem->value != NULL)
+ elem->computed = 1;
+ }
return(elem);
}
/**
* xsltRegisterVariable:
* @ctxt: the XSLT transformation context
- * @name: the variable name
- * @ns_uri: the variable namespace URI
- * @select: the expression which need to be evaluated to generate a value
+ * @comp: pointer to precompiled data
* @tree: the tree if select is NULL
* @param: this is a parameter actually
*
*
* Returns 0 in case of success, -1 in case of error
*/
-int
-xsltRegisterVariable(xsltTransformContextPtr ctxt, const xmlChar *name,
- const xmlChar *ns_uri, const xmlChar *select,
+static int
+xsltRegisterVariable(xsltTransformContextPtr ctxt, xsltStylePreCompPtr comp,
xmlNodePtr tree, int param) {
xsltStackElemPtr elem;
- if (ctxt == NULL)
- return(-1);
- if (name == NULL)
- return(-1);
-
- if (xsltCheckStackElem(ctxt, name, ns_uri) != 0) {
- if (!param) {
- xsltGenericError(xsltGenericErrorContext,
- "xsl:variable : redefining %s\n", name);
+ int present;
+
+ present = xsltCheckStackElem(ctxt, comp->name, comp->ns);
+ if (param == 0) {
+ if ((present != 0) && (present != 3)) {
+ xsltTransformError(ctxt, NULL, comp->inst,
+ "xsl:variable : redefining %s\n", comp->name);
+ return(0);
}
-#ifdef DEBUG_VARIABLE
- else
- xsltGenericDebug(xsltGenericDebugContext,
- "param %s defined by caller", name);
+ } else if (present != 0) {
+ if ((present == 1) || (present == 2)) {
+ xsltTransformError(ctxt, NULL, comp->inst,
+ "xsl:param : redefining %s\n", comp->name);
+ return(0);
+ }
+#ifdef WITH_XSLT_DEBUG_VARIABLE
+ xsltGenericDebug(xsltGenericDebugContext,
+ "param %s defined by caller\n", comp->name);
#endif
return(0);
}
- elem = xsltBuildVariable(ctxt, name, ns_uri, select, tree, param);
+ elem = xsltBuildVariable(ctxt, comp, tree);
xsltAddStackElem(ctxt, elem);
return(0);
}
*
* Returns the value or NULL if not found
*/
-xmlXPathObjectPtr
+static xmlXPathObjectPtr
xsltGlobalVariableLookup(xsltTransformContextPtr ctxt, const xmlChar *name,
const xmlChar *ns_uri) {
- xsltStylesheetPtr style;
- xsltStackElemPtr elem = NULL;
-
- style = ctxt->style;
- while (style != NULL) {
- elem = style->variables;
-
- while (elem != NULL) {
- if (xmlStrEqual(elem->name, name)) {
- if (ns_uri == NULL) {
- if (elem->nameURI == NULL)
- break;
- } else {
- if ((elem->nameURI != NULL) &&
- (xmlStrEqual(elem->nameURI, ns_uri)))
- break;
- }
-
- }
- elem = elem->next;
- }
- if (elem != NULL) break;
+ xsltStackElemPtr elem;
+ xmlXPathObjectPtr ret = NULL;
- style = xsltNextImport(style);
- }
- if (elem == NULL)
+ /*
+ * Lookup the global variables in XPath global variable hash table
+ */
+ if ((ctxt->xpathCtxt == NULL) || (ctxt->globalVars == NULL))
return(NULL);
-
- if (!elem->computed) {
-#ifdef DEBUG_VARIABLE
+ elem = (xsltStackElemPtr)
+ xmlHashLookup2(ctxt->globalVars, name, ns_uri);
+ if (elem == NULL) {
+#ifdef WITH_XSLT_DEBUG_VARIABLE
xsltGenericDebug(xsltGenericDebugContext,
- "uncomputed global variable %s\n", name);
+ "global variable not found %s\n", name);
#endif
- xsltEvalVariables(ctxt, elem);
+ return(NULL);
}
- if (elem->value != NULL)
- return(xmlXPathObjectCopy(elem->value));
-#ifdef DEBUG_VARIABLE
- xsltGenericDebug(xsltGenericDebugContext,
- "global variable not found %s\n", name);
-#endif
- return(NULL);
+ if (elem->computed == 0) {
+ if (xmlStrEqual(elem->name, BAD_CAST " being computed ... ")) {
+ xsltTransformError(ctxt, NULL, elem->comp->inst,
+ "Recursive definition of %s\n", name);
+ return(NULL);
+ }
+ ret = xsltEvalGlobalVariable(elem, ctxt);
+ } else
+ ret = elem->value;
+ return(xmlXPathObjectCopy(ret));
}
/**
if (elem == NULL) {
return(xsltGlobalVariableLookup(ctxt, name, ns_uri));
}
- if (!elem->computed) {
-#ifdef DEBUG_VARIABLE
+ if (elem->computed == 0) {
+#ifdef WITH_XSLT_DEBUG_VARIABLE
xsltGenericDebug(xsltGenericDebugContext,
"uncomputed variable %s\n", name);
#endif
- xsltEvalVariables(ctxt, elem);
+ elem->value = xsltEvalVariable(ctxt, elem, NULL);
+ elem->computed = 1;
}
if (elem->value != NULL)
return(xmlXPathObjectCopy(elem->value));
-#ifdef DEBUG_VARIABLE
+#ifdef WITH_XSLT_DEBUG_VARIABLE
xsltGenericDebug(xsltGenericDebugContext,
"variable not found %s\n", name);
#endif
* parse an XSLT transformation param declaration, compute
* its value but doesn't record it.
*
- * It returns the new xsltStackElemPtr or NULL
+ * Returns the new xsltStackElemPtr or NULL
*/
xsltStackElemPtr
xsltParseStylesheetCallerParam(xsltTransformContextPtr ctxt, xmlNodePtr cur) {
- xmlChar *name, *ncname, *prefix;
- xmlChar *select;
xmlNodePtr tree = NULL;
xsltStackElemPtr elem = NULL;
+ xsltStylePreCompPtr comp;
if ((cur == NULL) || (ctxt == NULL))
return(NULL);
-
- name = xmlGetNsProp(cur, (const xmlChar *)"name", XSLT_NAMESPACE);
- if (name == NULL) {
- xsltGenericError(xsltGenericErrorContext,
- "xsl:param : missing name attribute\n");
+ comp = (xsltStylePreCompPtr) cur->_private;
+ if (comp == NULL) {
+ xsltTransformError(ctxt, NULL, cur,
+ "xsl:param : compilation error\n");
return(NULL);
}
-#ifdef DEBUG_VARIABLE
- xsltGenericDebug(xsltGenericDebugContext,
- "Parsing param %s\n", name);
-#endif
-
- select = xmlGetNsProp(cur, (const xmlChar *)"select", XSLT_NAMESPACE);
- if (select == NULL) {
- tree = cur->children;
- } else {
-#ifdef DEBUG_VARIABLE
- xsltGenericDebug(xsltGenericDebugContext,
- " select %s\n", select);
-#endif
- if (cur->children != NULL)
- xsltGenericError(xsltGenericErrorContext,
- "xsl:param : content shuld be empty since select is present \n");
- }
-
- ncname = xmlSplitQName2(name, &prefix);
-
- if (ncname != NULL) {
- if (prefix != NULL) {
- xmlNsPtr ns;
-
- ns = xmlSearchNs(cur->doc, cur, prefix);
- if (ns == NULL) {
- xsltGenericError(xsltGenericErrorContext,
- "xsl:param : no namespace bound to prefix %s\n", prefix);
- } else {
- elem = xsltBuildVariable(ctxt, ncname, ns->href, select,
- tree, 1);
- }
- xmlFree(prefix);
- } else {
- elem = xsltBuildVariable(ctxt, ncname, NULL, select, tree, 1);
- }
- xmlFree(ncname);
- } else {
- elem = xsltBuildVariable(ctxt, name, NULL, select, tree, 1);
- }
-
- xmlFree(name);
- if (select != NULL)
- xmlFree(select);
- return(elem);
-}
-
-/**
- * xsltParseStylesheetParam:
- * @ctxt: the XSLT transformation context
- * @cur: the "param" element
- *
- * parse an XSLT transformation param declaration and record
- * its value.
- */
-
-void
-xsltParseStylesheetParam(xsltTransformContextPtr ctxt, xmlNodePtr cur) {
- xmlChar *name, *ncname, *prefix;
- xmlChar *select;
- xmlNodePtr tree = NULL;
-
- if ((cur == NULL) || (ctxt == NULL))
- return;
-
- name = xmlGetNsProp(cur, (const xmlChar *)"name", XSLT_NAMESPACE);
- if (name == NULL) {
- xsltGenericError(xsltGenericErrorContext,
+ if (comp->name == NULL) {
+ xsltTransformError(ctxt, NULL, cur,
"xsl:param : missing name attribute\n");
- return;
+ return(NULL);
}
-#ifdef DEBUG_VARIABLE
+#ifdef WITH_XSLT_DEBUG_VARIABLE
xsltGenericDebug(xsltGenericDebugContext,
- "Parsing param %s\n", name);
+ "Handling param %s\n", comp->name);
#endif
- select = xmlGetNsProp(cur, (const xmlChar *)"select", XSLT_NAMESPACE);
- if (select == NULL) {
+ if (comp->select == NULL) {
tree = cur->children;
} else {
-#ifdef DEBUG_VARIABLE
+#ifdef WITH_XSLT_DEBUG_VARIABLE
xsltGenericDebug(xsltGenericDebugContext,
- " select %s\n", select);
+ " select %s\n", comp->select);
#endif
- if (cur->children != NULL)
- xsltGenericError(xsltGenericErrorContext,
- "xsl:param : content shuld be empty since select is present \n");
- }
-
- ncname = xmlSplitQName2(name, &prefix);
-
- if (ncname != NULL) {
- if (prefix != NULL) {
- xmlNsPtr ns;
-
- ns = xmlSearchNs(cur->doc, cur, prefix);
- if (ns == NULL) {
- xsltGenericError(xsltGenericErrorContext,
- "xsl:param : no namespace bound to prefix %s\n", prefix);
- } else {
- xsltRegisterVariable(ctxt, ncname, ns->href, select, tree, 1);
- }
- xmlFree(prefix);
- } else {
- xsltRegisterVariable(ctxt, ncname, NULL, select, tree, 1);
- }
- xmlFree(ncname);
- } else {
- xsltRegisterVariable(ctxt, name, NULL, select, tree, 1);
+ tree = cur;
}
- xmlFree(name);
- if (select != NULL)
- xmlFree(select);
+ elem = xsltBuildVariable(ctxt, comp, tree);
+ return(elem);
}
/**
void
xsltParseGlobalVariable(xsltStylesheetPtr style, xmlNodePtr cur) {
- xmlChar *name, *ncname, *prefix;
- xmlChar *select;
- xmlNodePtr tree = NULL;
+ xsltStylePreCompPtr comp;
if ((cur == NULL) || (style == NULL))
return;
- name = xmlGetNsProp(cur, (const xmlChar *)"name", XSLT_NAMESPACE);
- if (name == NULL) {
- xsltGenericError(xsltGenericErrorContext,
+ xsltStylePreCompute(style, cur);
+ comp = (xsltStylePreCompPtr) cur->_private;
+ if (comp == NULL) {
+ xsltTransformError(NULL, style, cur,
+ "xsl:variable : compilation failed\n");
+ return;
+ }
+
+ if (comp->name == NULL) {
+ xsltTransformError(NULL, style, cur,
"xsl:variable : missing name attribute\n");
return;
}
-#ifdef DEBUG_VARIABLE
+#ifdef WITH_XSLT_DEBUG_VARIABLE
xsltGenericDebug(xsltGenericDebugContext,
- "Parsing global variable %s\n", name);
+ "Registering global variable %s\n", comp->name);
#endif
- select = xmlGetNsProp(cur, (const xmlChar *)"select", XSLT_NAMESPACE);
- if (select == NULL) {
- tree = cur->children;
- } else {
- if (cur->children != NULL)
- xsltGenericError(xsltGenericErrorContext,
- "xsl:variable : content shuld be empty since select is present \n");
- }
-
- ncname = xmlSplitQName2(name, &prefix);
-
- if (ncname != NULL) {
- if (prefix != NULL) {
- xmlNsPtr ns;
-
- ns = xmlSearchNs(cur->doc, cur, prefix);
- if (ns == NULL) {
- xsltGenericError(xsltGenericErrorContext,
- "xsl:variable : no namespace bound to prefix %s\n", prefix);
- } else {
- xsltRegisterGlobalVariable(style, ncname, ns->href, select, tree, 0);
- }
- xmlFree(prefix);
- } else {
- xsltRegisterGlobalVariable(style, ncname, NULL, select, tree, 0);
- }
- xmlFree(ncname);
- } else {
- xsltRegisterGlobalVariable(style, name, NULL, select, tree, 0);
- }
-
- xmlFree(name);
- if (select != NULL)
- xmlFree(select);
-
+ xsltRegisterGlobalVariable(style, comp->name, comp->ns, comp->select,
+ cur->children, comp, NULL);
}
/**
void
xsltParseGlobalParam(xsltStylesheetPtr style, xmlNodePtr cur) {
- xmlChar *name, *ncname, *prefix;
- xmlChar *select;
- xmlNodePtr tree = NULL;
+ xsltStylePreCompPtr comp;
if ((cur == NULL) || (style == NULL))
return;
- name = xmlGetNsProp(cur, (const xmlChar *)"name", XSLT_NAMESPACE);
- if (name == NULL) {
- xsltGenericError(xsltGenericErrorContext,
+ xsltStylePreCompute(style, cur);
+ comp = (xsltStylePreCompPtr) cur->_private;
+ if (comp == NULL) {
+ xsltTransformError(NULL, style, cur,
+ "xsl:param : compilation failed\n");
+ return;
+ }
+
+ if (comp->name == NULL) {
+ xsltTransformError(NULL, style, cur,
"xsl:param : missing name attribute\n");
return;
}
-#ifdef DEBUG_VARIABLE
+#ifdef WITH_XSLT_DEBUG_VARIABLE
xsltGenericDebug(xsltGenericDebugContext,
- "Parsing global param %s\n", name);
+ "Registering global param %s\n", comp->name);
#endif
- select = xmlGetNsProp(cur, (const xmlChar *)"select", XSLT_NAMESPACE);
- if (select == NULL) {
- tree = cur->children;
- } else {
- if (cur->children != NULL)
- xsltGenericError(xsltGenericErrorContext,
- "xsl:param : content shuld be empty since select is present \n");
- }
-
- ncname = xmlSplitQName2(name, &prefix);
-
- if (ncname != NULL) {
- if (prefix != NULL) {
- xmlNsPtr ns;
-
- ns = xmlSearchNs(cur->doc, cur, prefix);
- if (ns == NULL) {
- xsltGenericError(xsltGenericErrorContext,
- "xsl:param : no namespace bound to prefix %s\n", prefix);
- } else {
- xsltRegisterGlobalVariable(style, ncname, ns->href, select, tree, 1);
- }
- xmlFree(prefix);
- } else {
- xsltRegisterGlobalVariable(style, ncname, NULL, select, tree, 1);
- }
- xmlFree(ncname);
- } else {
- xsltRegisterGlobalVariable(style, name, NULL, select, tree, 1);
- }
-
- xmlFree(name);
- if (select != NULL)
- xmlFree(select);
+ xsltRegisterGlobalVariable(style, comp->name, comp->ns, comp->select,
+ cur->children, comp, NULL);
}
/**
void
xsltParseStylesheetVariable(xsltTransformContextPtr ctxt, xmlNodePtr cur) {
- xmlChar *name, *ncname, *prefix;
- xmlChar *select;
- xmlNodePtr tree = NULL;
+ xsltStylePreCompPtr comp;
if ((cur == NULL) || (ctxt == NULL))
return;
- name = xmlGetNsProp(cur, (const xmlChar *)"name", XSLT_NAMESPACE);
- if (name == NULL) {
- xsltGenericError(xsltGenericErrorContext,
+ comp = (xsltStylePreCompPtr) cur->_private;
+ if (comp == NULL) {
+ xsltTransformError(ctxt, NULL, cur,
+ "xsl:variable : compilation failed\n");
+ return;
+ }
+
+ if (comp->name == NULL) {
+ xsltTransformError(ctxt, NULL, cur,
"xsl:variable : missing name attribute\n");
return;
}
-#ifdef DEBUG_VARIABLE
+#ifdef WITH_XSLT_DEBUG_VARIABLE
xsltGenericDebug(xsltGenericDebugContext,
- "Parsing variable %s\n", name);
+ "Registering variable %s\n", comp->name);
#endif
- select = xmlGetNsProp(cur, (const xmlChar *)"select", XSLT_NAMESPACE);
- if (select == NULL) {
- tree = cur->children;
- } else {
- if (cur->children != NULL)
- xsltGenericError(xsltGenericErrorContext,
- "xsl:variable : content should be empty since select is present \n");
- }
+ xsltRegisterVariable(ctxt, comp, cur->children, 0);
+}
- ncname = xmlSplitQName2(name, &prefix);
+/**
+ * xsltParseStylesheetParam:
+ * @ctxt: the XSLT transformation context
+ * @cur: the "param" element
+ *
+ * parse an XSLT transformation param declaration and record
+ * its value.
+ */
- if (ncname != NULL) {
- if (prefix != NULL) {
- xmlNsPtr ns;
+void
+xsltParseStylesheetParam(xsltTransformContextPtr ctxt, xmlNodePtr cur) {
+ xsltStylePreCompPtr comp;
- ns = xmlSearchNs(cur->doc, cur, prefix);
- if (ns == NULL) {
- xsltGenericError(xsltGenericErrorContext,
- "xsl:variable : no namespace bound to prefix %s\n", prefix);
- } else {
- xsltRegisterVariable(ctxt, ncname, ns->href, select, tree, 0);
- }
- xmlFree(prefix);
- } else {
- xsltRegisterVariable(ctxt, ncname, NULL, select, tree, 0);
- }
- xmlFree(ncname);
- } else {
- xsltRegisterVariable(ctxt, name, NULL, select, tree, 0);
+ if ((cur == NULL) || (ctxt == NULL))
+ return;
+
+ comp = (xsltStylePreCompPtr) cur->_private;
+ if (comp == NULL) {
+ xsltTransformError(ctxt, NULL, cur,
+ "xsl:param : compilation failed\n");
+ return;
+ }
+
+ if (comp->name == NULL) {
+ xsltTransformError(ctxt, NULL, cur,
+ "xsl:param : missing name attribute\n");
+ return;
}
- xmlFree(name);
- if (select != NULL)
- xmlFree(select);
+#ifdef WITH_XSLT_DEBUG_VARIABLE
+ xsltGenericDebug(xsltGenericDebugContext,
+ "Registering param %s\n", comp->name);
+#endif
+ xsltRegisterVariable(ctxt, comp, cur->children, 1);
}
/**
- * xsltVariableLookup:
+ * xsltFreeGlobalVariables:
+ * @ctxt: the XSLT transformation context
+ *
+ * Free up the data associated to the global variables
+ * its value.
+ */
+
+void
+xsltFreeGlobalVariables(xsltTransformContextPtr ctxt) {
+ xmlHashFree(ctxt->globalVars, (xmlHashDeallocator) xsltFreeStackElem);
+}
+
+/**
+ * xsltXPathVariableLookup:
* @ctxt: a void * but the the XSLT transformation context actually
* @name: the variable name
* @ns_uri: the variable namespace URI
if ((ctxt == NULL) || (name == NULL))
return(NULL);
-#ifdef DEBUG_VARIABLE
+#ifdef WITH_XSLT_DEBUG_VARIABLE
xsltGenericDebug(xsltGenericDebugContext,
"Lookup variable %s\n", name);
#endif
context = (xsltTransformContextPtr) ctxt;
ret = xsltVariableLookup(context, name, ns_uri);
if (ret == NULL) {
- xsltGenericError(xsltGenericErrorContext,
+ xsltTransformError(ctxt, NULL, NULL,
"unregistered variable %s\n", name);
}
-#ifdef DEBUG_VARIABLE
+#ifdef WITH_XSLT_DEBUG_VARIABLE
if (ret != NULL)
xsltGenericDebug(xsltGenericDebugContext,
"found variable %s\n", name);
return(ret);
}
+