2 * variables.c: Implementation of the variable storage and lookup
5 * http://www.w3.org/TR/1999/REC-xslt-19991116
7 * See Copyright for the status of this software.
17 #include <libxml/xmlmemory.h>
18 #include <libxml/tree.h>
19 #include <libxml/valid.h>
20 #include <libxml/hash.h>
21 #include <libxml/xmlerror.h>
22 #include <libxml/xpath.h>
23 #include <libxml/xpathInternals.h>
24 #include <libxml/parserInternals.h>
26 #include "xsltInternals.h"
27 #include "xsltutils.h"
28 #include "variables.h"
29 #include "transform.h"
33 #ifdef WITH_XSLT_DEBUG
34 #define WITH_XSLT_DEBUG_VARIABLE
37 /************************************************************************
41 ************************************************************************/
46 * Create a new XSLT ParserContext
48 * Returns the newly allocated xsltParserStackElem or NULL in case of error
50 static xsltStackElemPtr
51 xsltNewStackElem(void) {
54 cur = (xsltStackElemPtr) xmlMalloc(sizeof(xsltStackElem));
56 xsltTransformError(NULL, NULL, NULL,
57 "xsltNewStackElem : malloc failed\n");
72 * @elem: an XSLT stack element
74 * Makes a copy of the stack element
76 * Returns the copy of NULL
78 static xsltStackElemPtr
79 xsltCopyStackElem(xsltStackElemPtr elem) {
82 cur = (xsltStackElemPtr) xmlMalloc(sizeof(xsltStackElem));
84 xsltTransformError(NULL, NULL, NULL,
85 "xsltCopyStackElem : malloc failed\n");
88 cur->name = xmlStrdup(elem->name);
89 cur->nameURI = xmlStrdup(elem->nameURI);
90 cur->select = xmlStrdup(elem->select);
91 cur->tree = elem->tree;
92 cur->comp = elem->comp;
100 * @elem: an XSLT stack element
102 * Free up the memory allocated by @elem
105 xsltFreeStackElem(xsltStackElemPtr elem) {
108 if (elem->name != NULL)
110 if (elem->nameURI != NULL)
111 xmlFree(elem->nameURI);
112 if (elem->select != NULL)
113 xmlFree(elem->select);
114 if (elem->value != NULL)
115 xmlXPathFreeObject(elem->value);
121 * xsltFreeStackElemList:
122 * @elem: an XSLT stack element
124 * Free up the memory allocated by @elem
127 xsltFreeStackElemList(xsltStackElemPtr elem) {
128 xsltStackElemPtr next;
130 while(elem != NULL) {
132 xsltFreeStackElem(elem);
138 * xsltCheckStackElem:
139 * @ctxt: xn XSLT transformation context
140 * @name: the variable name
141 * @nameURI: the variable namespace URI
143 * check wether the variable or param is already defined
145 * Returns 1 if present, 0 if not, -1 in case of failure.
148 xsltCheckStackElem(xsltTransformContextPtr ctxt, const xmlChar *name,
149 const xmlChar *nameURI) {
150 xsltStackElemPtr cur;
152 if ((ctxt == NULL) || (name == NULL))
156 while (cur != NULL) {
157 if (xmlStrEqual(name, cur->name)) {
158 if (((nameURI == NULL) && (cur->nameURI == NULL)) ||
159 ((nameURI != NULL) && (cur->nameURI != NULL) &&
160 (xmlStrEqual(nameURI, cur->nameURI)))) {
171 * @ctxt: xn XSLT transformation context
172 * @elem: a stack element
174 * add a new element at this level of the stack.
176 * Returns 0 in case of success, -1 in case of failure.
179 xsltAddStackElem(xsltTransformContextPtr ctxt, xsltStackElemPtr elem) {
180 if ((ctxt == NULL) || (elem == NULL))
183 elem->next = ctxt->varsTab[ctxt->varsNr - 1];
184 ctxt->varsTab[ctxt->varsNr - 1] = elem;
190 * xsltAddStackElemList:
191 * @ctxt: xn XSLT transformation context
192 * @elems: a stack element list
194 * add the new element list at this level of the stack.
196 * Returns 0 in case of success, -1 in case of failure.
199 xsltAddStackElemList(xsltTransformContextPtr ctxt, xsltStackElemPtr elems) {
200 xsltStackElemPtr cur;
202 if ((ctxt == NULL) || (elems == NULL))
205 /* TODO: check doublons */
206 if (ctxt->varsTab[ctxt->varsNr - 1] != NULL) {
207 cur = ctxt->varsTab[ctxt->varsNr - 1];
208 while (cur->next != NULL)
212 elems->next = ctxt->varsTab[ctxt->varsNr - 1];
213 ctxt->varsTab[ctxt->varsNr - 1] = elems;
221 * @ctxt: an XSLT transformation context
222 * @name: the local part of the name
223 * @nameURI: the URI part of the name
225 * Locate an element in the stack based on its name.
227 static xsltStackElemPtr
228 xsltStackLookup(xsltTransformContextPtr ctxt, const xmlChar *name,
229 const xmlChar *nameURI) {
230 xsltStackElemPtr ret = NULL;
232 xsltStackElemPtr cur;
234 if ((ctxt == NULL) || (name == NULL) || (ctxt->varsNr == 0))
238 * Do the lookup from the top of the stack, but
239 * don't use params being computed in a call-param
243 for (i = ctxt->varsNr; i > ctxt->varsBase; i--) {
244 cur = ctxt->varsTab[i-1];
245 while (cur != NULL) {
246 if (xmlStrEqual(cur->name, name)) {
247 if (nameURI == NULL) {
248 if (cur->nameURI == NULL) {
252 if ((cur->nameURI != NULL) &&
253 (xmlStrEqual(cur->nameURI, nameURI))) {
265 /************************************************************************
267 * Module interfaces *
269 ************************************************************************/
273 * @ctxt: the XSLT transformation context
274 * @elem: the variable or parameter.
275 * @precomp: pointer to precompiled data
277 * Evaluate a variable value.
279 * Returns the XPath Object value or NULL in case of error
281 static xmlXPathObjectPtr
282 xsltEvalVariable(xsltTransformContextPtr ctxt, xsltStackElemPtr elem,
283 xsltStylePreCompPtr precomp) {
284 xmlXPathObjectPtr result = NULL;
285 int oldProximityPosition, oldContextSize;
286 xmlNodePtr oldInst, oldNode;
287 xsltDocumentPtr oldDoc;
289 xmlNsPtr *oldNamespaces;
291 if ((ctxt == NULL) || (elem == NULL))
294 #ifdef WITH_XSLT_DEBUG_VARIABLE
295 xsltGenericDebug(xsltGenericDebugContext,
296 "Evaluating variable %s\n", elem->name);
298 if (elem->select != NULL) {
299 xmlXPathCompExprPtr comp = NULL;
301 if ((precomp != NULL) && (precomp->comp != NULL)) {
302 comp = precomp->comp;
304 comp = xmlXPathCompile(elem->select);
308 oldProximityPosition = ctxt->xpathCtxt->proximityPosition;
309 oldContextSize = ctxt->xpathCtxt->contextSize;
310 ctxt->xpathCtxt->node = (xmlNodePtr) ctxt->node;
311 oldDoc = ctxt->document;
312 oldNode = ctxt->node;
313 oldInst = ctxt->inst;
314 oldNsNr = ctxt->xpathCtxt->nsNr;
315 oldNamespaces = ctxt->xpathCtxt->namespaces;
316 if (precomp != NULL) {
317 ctxt->inst = precomp->inst;
318 ctxt->xpathCtxt->namespaces = precomp->nsList;
319 ctxt->xpathCtxt->nsNr = precomp->nsNr;
322 ctxt->xpathCtxt->namespaces = NULL;
323 ctxt->xpathCtxt->nsNr = 0;
325 result = xmlXPathCompiledEval(comp, ctxt->xpathCtxt);
326 ctxt->xpathCtxt->contextSize = oldContextSize;
327 ctxt->xpathCtxt->proximityPosition = oldProximityPosition;
328 ctxt->xpathCtxt->nsNr = oldNsNr;
329 ctxt->xpathCtxt->namespaces = oldNamespaces;
330 ctxt->inst = oldInst;
331 ctxt->node = oldNode;
332 ctxt->document = oldDoc;
333 if ((precomp == NULL) || (precomp->comp == NULL))
334 xmlXPathFreeCompExpr(comp);
335 if (result == NULL) {
336 xsltTransformError(ctxt, NULL, precomp->inst,
337 "Evaluating variable %s failed\n", elem->name);
338 ctxt->state = XSLT_STATE_STOPPED;
339 #ifdef WITH_XSLT_DEBUG_VARIABLE
340 #ifdef LIBXML_DEBUG_ENABLED
342 if ((xsltGenericDebugContext == stdout) ||
343 (xsltGenericDebugContext == stderr))
344 xmlXPathDebugDumpObject((FILE *)xsltGenericDebugContext,
350 if (elem->tree == NULL) {
351 result = xmlXPathNewCString("");
354 * This is a result tree fragment.
356 xmlNodePtr container;
357 xmlNodePtr oldInsert;
360 container = xmlNewDocNode(ctxt->document->doc, NULL,
361 (const xmlChar *) "fake node libxslt", NULL);
362 if (container == NULL)
364 container->parent = NULL;
366 oldoutput = ctxt->output;
368 oldInsert = ctxt->insert;
369 ctxt->insert = container;
370 xsltApplyOneTemplate(ctxt, ctxt->node, elem->tree, NULL, NULL);
371 ctxt->insert = oldInsert;
372 ctxt->output = oldoutput;
374 result = xmlXPathNewValueTree(container);
375 if (result == NULL) {
376 result = xmlXPathNewCString("");
379 * Tag the subtree for removal once consumed
383 #ifdef WITH_XSLT_DEBUG_VARIABLE
384 #ifdef LIBXML_DEBUG_ENABLED
385 if ((xsltGenericDebugContext == stdout) ||
386 (xsltGenericDebugContext == stderr))
387 xmlXPathDebugDumpObject((FILE *)xsltGenericDebugContext,
397 * xsltEvalGlobalVariable:
398 * @elem: the variable or parameter.
399 * @ctxt: the XSLT transformation context
401 * Evaluate a global variable value.
403 * Returns the XPath Object value or NULL in case of error
405 static xmlXPathObjectPtr
406 xsltEvalGlobalVariable(xsltStackElemPtr elem, xsltTransformContextPtr ctxt) {
407 xmlXPathObjectPtr result = NULL;
408 xsltStylePreCompPtr precomp;
409 int oldProximityPosition, oldContextSize;
412 xmlNsPtr *oldNamespaces;
414 if ((ctxt == NULL) || (elem == NULL))
420 #ifdef WITH_XSLT_DEBUG_VARIABLE
421 xsltGenericDebug(xsltGenericDebugContext,
422 "Evaluating global variable %s\n", elem->name);
426 if ((xslDebugStatus != XSLT_DEBUG_NONE) &&
427 elem->comp && elem->comp->inst)
428 xslHandleDebugger(elem->comp->inst, NULL, NULL, ctxt);
431 precomp = elem->comp;
432 if (elem->select != NULL) {
433 xmlXPathCompExprPtr comp = NULL;
435 if ((precomp != NULL) && (precomp->comp != NULL)) {
436 comp = precomp->comp;
438 comp = xmlXPathCompile(elem->select);
442 oldProximityPosition = ctxt->xpathCtxt->proximityPosition;
443 oldContextSize = ctxt->xpathCtxt->contextSize;
444 oldInst = ctxt->inst;
445 oldNsNr = ctxt->xpathCtxt->nsNr;
446 oldNamespaces = ctxt->xpathCtxt->namespaces;
447 if (precomp != NULL) {
448 ctxt->inst = precomp->inst;
449 ctxt->xpathCtxt->namespaces = precomp->nsList;
450 ctxt->xpathCtxt->nsNr = precomp->nsNr;
453 ctxt->xpathCtxt->namespaces = NULL;
454 ctxt->xpathCtxt->nsNr = 0;
456 ctxt->xpathCtxt->node = (xmlNodePtr) ctxt->node;
457 result = xmlXPathCompiledEval(comp, ctxt->xpathCtxt);
458 ctxt->xpathCtxt->contextSize = oldContextSize;
459 ctxt->xpathCtxt->proximityPosition = oldProximityPosition;
460 ctxt->inst = oldInst;
461 ctxt->xpathCtxt->nsNr = oldNsNr;
462 ctxt->xpathCtxt->namespaces = oldNamespaces;
463 if ((precomp == NULL) || (precomp->comp == NULL))
464 xmlXPathFreeCompExpr(comp);
465 if (result == NULL) {
466 xsltTransformError(ctxt, NULL, precomp->inst,
467 "Evaluating global variable %s failed\n", elem->name);
468 ctxt->state = XSLT_STATE_STOPPED;
469 #ifdef WITH_XSLT_DEBUG_VARIABLE
470 #ifdef LIBXML_DEBUG_ENABLED
472 if ((xsltGenericDebugContext == stdout) ||
473 (xsltGenericDebugContext == stderr))
474 xmlXPathDebugDumpObject((FILE *)xsltGenericDebugContext,
480 if (elem->tree == NULL) {
481 result = xmlXPathNewCString("");
484 * This is a result tree fragment.
486 xmlNodePtr container;
487 xmlNodePtr oldInsert;
490 container = xmlNewDocNode(ctxt->document->doc, NULL,
491 (const xmlChar *) "fake node libxslt", NULL);
492 if (container == NULL)
494 container->parent = NULL;
496 oldoutput = ctxt->output;
498 oldInsert = ctxt->insert;
499 ctxt->insert = container;
500 xsltApplyOneTemplate(ctxt, ctxt->node, elem->tree, NULL, NULL);
501 ctxt->insert = oldInsert;
502 ctxt->output = oldoutput;
504 result = xmlXPathNewValueTree(container);
505 if (result == NULL) {
506 result = xmlXPathNewCString("");
509 * Tag the subtree for removal once consumed
513 #ifdef WITH_XSLT_DEBUG_VARIABLE
514 #ifdef LIBXML_DEBUG_ENABLED
515 if ((xsltGenericDebugContext == stdout) ||
516 (xsltGenericDebugContext == stderr))
517 xmlXPathDebugDumpObject((FILE *)xsltGenericDebugContext,
523 if (result != NULL) {
524 elem->value = result;
531 * xsltEvalGlobalVariables:
532 * @ctxt: the XSLT transformation context
534 * Evaluate the global variables of a stylesheet. This need to be
535 * done on parsed stylesheets before starting to apply transformations
537 * Returns 0 in case of success, -1 in case of error
540 xsltEvalGlobalVariables(xsltTransformContextPtr ctxt) {
541 xsltStackElemPtr elem;
542 xsltStylesheetPtr style;
547 #ifdef WITH_XSLT_DEBUG_VARIABLE
548 xsltGenericDebug(xsltGenericDebugContext,
549 "Registering global variables\n");
551 ctxt->node = (xmlNodePtr) ctxt->document->doc;
552 ctxt->xpathCtxt->contextSize = 1;
553 ctxt->xpathCtxt->proximityPosition = 1;
556 * Walk the list from the stylesheets and populate the hash table
559 while (style != NULL) {
560 elem = style->variables;
562 #ifdef WITH_XSLT_DEBUG_VARIABLE
563 if ((style->doc != NULL) && (style->doc->URL != NULL)) {
564 xsltGenericDebug(xsltGenericDebugContext,
565 "Registering global variables from %s\n",
570 while (elem != NULL) {
571 xsltStackElemPtr def;
574 * Global variables are stored in the variables pool.
576 def = (xsltStackElemPtr)
577 xmlHashLookup2(ctxt->globalVars,
578 elem->name, elem->nameURI);
582 def = xsltCopyStackElem(elem);
583 res = xmlHashAddEntry2(ctxt->globalVars,
584 elem->name, elem->nameURI, def);
585 } else if ((elem->comp != NULL) &&
586 (elem->comp->type == XSLT_FUNC_VARIABLE)) {
588 * Redefinition of variables from a different stylesheet
589 * should not generate a message.
591 if ((elem->comp->inst != NULL) &&
592 (def->comp != NULL) && (def->comp->inst != NULL) &&
593 (elem->comp->inst->doc == def->comp->inst->doc)) {
594 xsltTransformError(ctxt, style, elem->comp->inst,
595 "Global variable %s already defined\n", elem->name);
601 style = xsltNextImport(style);
605 * This part does the actual evaluation
607 ctxt->node = (xmlNodePtr) ctxt->document->doc;
608 ctxt->xpathCtxt->contextSize = 1;
609 ctxt->xpathCtxt->proximityPosition = 1;
610 xmlHashScan(ctxt->globalVars,
611 (xmlHashScanner) xsltEvalGlobalVariable, ctxt);
617 * xsltRegisterGlobalVariable:
618 * @style: the XSLT transformation context
619 * @name: the variable name
620 * @ns_uri: the variable namespace URI
621 * @select: the expression which need to be evaluated to generate a value
622 * @tree: the subtree if select is NULL
623 * @comp: the precompiled value
624 * @value: the string value if available
626 * Register a new variable value. If @value is NULL it unregisters
629 * Returns 0 in case of success, -1 in case of error
632 xsltRegisterGlobalVariable(xsltStylesheetPtr style, const xmlChar *name,
633 const xmlChar *ns_uri, const xmlChar *select,
634 xmlNodePtr tree, xsltStylePreCompPtr comp,
635 const xmlChar *value) {
636 xsltStackElemPtr elem, tmp;
644 #ifdef WITH_XSLT_DEBUG_VARIABLE
645 if (comp->type == XSLT_FUNC_PARAM)
646 xsltGenericDebug(xsltGenericDebugContext,
647 "Defining global param %s\n", name);
649 xsltGenericDebug(xsltGenericDebugContext,
650 "Defining global variable %s\n", name);
653 elem = xsltNewStackElem();
657 elem->name = xmlStrdup(name);
658 elem->select = xmlStrdup(select);
660 elem->nameURI = xmlStrdup(ns_uri);
662 tmp = style->variables;
665 style->variables = elem;
667 while (tmp->next != NULL)
674 elem->value = xmlXPathNewString(value);
680 * xsltProcessUserParamInternal
682 * @ctxt: the XSLT transformation context
683 * @name: a null terminated parameter name
684 * @value: a null terminated value (may be an XPath expression)
685 * @eval: 0 to treat the value literally, else evaluate as XPath expression
687 * If @eval is 0 then @value is treated literally and is stored in the global
688 * parameter/variable table without any change.
690 * Uf @eval is 1 then @value is treated as an XPath expression and is
691 * evaluated. In this case, if you want to pass a string which will be
692 * interpreted literally then it must be enclosed in single or double quotes.
693 * If the string contains single quotes (double quotes) then it cannot be
694 * enclosed single quotes (double quotes). If the string which you want to
695 * be treated literally contains both single and double quotes (e.g. Meet
696 * at Joe's for "Twelfth Night" at 7 o'clock) then there is no suitable
697 * quoting character. You cannot use ' or " inside the string
698 * because the replacement of character entities with their equivalents is
699 * done at a different stage of processing. The solution is to call
700 * xsltQuoteUserParams or xsltQuoteOneUserParam.
702 * This needs to be done on parsed stylesheets before starting to apply
703 * transformations. Normally this will be called (directly or indirectly)
704 * only from xsltEvalUserParams, xsltEvalOneUserParam, xsltQuoteUserParams,
705 * or xsltQuoteOneUserParam.
707 * Returns 0 in case of success, -1 in case of error
712 xsltProcessUserParamInternal(xsltTransformContextPtr ctxt,
713 const xmlChar * name,
714 const xmlChar * value,
717 xsltStylesheetPtr style;
721 xmlXPathCompExprPtr comp;
722 xmlXPathObjectPtr result;
723 int oldProximityPosition;
726 xmlNsPtr *oldNamespaces;
727 xsltStackElemPtr elem;
739 #ifdef WITH_XSLT_DEBUG_VARIABLE
740 xsltGenericDebug(xsltGenericDebugContext,
741 "Evaluating user parameter %s=%s\n", name, value);
748 ncname = xmlSplitQName2(name, &prefix);
750 if (ncname != NULL) {
751 if (prefix != NULL) {
754 ns = xmlSearchNs(style->doc, xmlDocGetRootElement(style->doc),
757 xsltTransformError(ctxt, style, NULL,
758 "user param : no namespace bound to prefix %s\n", prefix);
772 ncname = xmlStrdup(name);
779 * Do the evaluation if @eval is non-zero.
784 comp = xmlXPathCompile(value);
786 oldProximityPosition = ctxt->xpathCtxt->proximityPosition;
787 oldContextSize = ctxt->xpathCtxt->contextSize;
788 ctxt->xpathCtxt->node = (xmlNodePtr) ctxt->node;
791 * There is really no in scope namespace for parameters on the
795 oldNsNr = ctxt->xpathCtxt->nsNr;
796 oldNamespaces = ctxt->xpathCtxt->namespaces;
797 ctxt->xpathCtxt->namespaces = NULL;
798 ctxt->xpathCtxt->nsNr = 0;
799 result = xmlXPathCompiledEval(comp, ctxt->xpathCtxt);
800 ctxt->xpathCtxt->contextSize = oldContextSize;
801 ctxt->xpathCtxt->proximityPosition = oldProximityPosition;
802 ctxt->xpathCtxt->nsNr = oldNsNr;
803 ctxt->xpathCtxt->namespaces = oldNamespaces;
804 xmlXPathFreeCompExpr(comp);
806 if (result == NULL) {
807 xsltTransformError(ctxt, style, NULL,
808 "Evaluating user parameter %s failed\n", name);
809 ctxt->state = XSLT_STATE_STOPPED;
816 * If @eval is 0 then @value is to be taken literally and result is NULL
818 * If @eval is not 0, then @value is an XPath expression and has been
819 * successfully evaluated and result contains the resulting value and
822 * Now create an xsltStackElemPtr for insertion into the context's
823 * global variable/parameter hash table.
826 #ifdef WITH_XSLT_DEBUG_VARIABLE
827 #ifdef LIBXML_DEBUG_ENABLED
828 if ((xsltGenericDebugContext == stdout) ||
829 (xsltGenericDebugContext == stderr))
830 xmlXPathDebugDumpObject((FILE *)xsltGenericDebugContext,
835 elem = xsltNewStackElem();
837 elem->name = xmlStrdup(ncname);
839 elem->select = xmlStrdup(value);
843 elem->nameURI = xmlStrdup(href);
847 elem->value = xmlXPathNewString(value);
850 elem->value = result;
855 * Global parameters are stored in the XPath context variables pool.
858 res = xmlHashAddEntry2(ctxt->globalVars, ncname, href, elem);
860 xsltFreeStackElem(elem);
861 xsltTransformError(ctxt, style, NULL,
862 "Global parameter %s already defined\n", ncname);
869 * xsltEvalUserParams:
871 * @ctxt: the XSLT transformation context
872 * @params: a NULL terminated array of parameters name/value tuples
874 * Evaluate the global variables of a stylesheet. This needs to be
875 * done on parsed stylesheets before starting to apply transformations.
876 * Each of the parameters is evaluated as an XPath expression and stored
877 * in the global variables/parameter hash table. If you want your
878 * parameter used literally, use xsltQuoteUserParams.
880 * Returns 0 in case of success, -1 in case of error
884 xsltEvalUserParams(xsltTransformContextPtr ctxt, const char **params) {
887 const xmlChar *value;
891 while (params[indx] != NULL) {
892 name = (const xmlChar *) params[indx++];
893 value = (const xmlChar *) params[indx++];
894 if (xsltEvalOneUserParam(ctxt, name, value) != 0)
901 * xsltQuoteUserParams:
903 * @ctxt: the XSLT transformation context
904 * @params: a NULL terminated arry of parameters names/values tuples
906 * Similar to xsltEvalUserParams, but the values are treated literally and
907 * are * *not* evaluated as XPath expressions. This should be done on parsed
908 * stylesheets before starting to apply transformations.
910 * Returns 0 in case of success, -1 in case of error.
914 xsltQuoteUserParams(xsltTransformContextPtr ctxt, const char **params) {
917 const xmlChar *value;
921 while (params[indx] != NULL) {
922 name = (const xmlChar *) params[indx++];
923 value = (const xmlChar *) params[indx++];
924 if (xsltQuoteOneUserParam(ctxt, name, value) != 0)
931 * xsltEvalOneUserParam:
933 * @ctxt: the XSLT transformation context
934 * @name: a null terminated string giving the name of the parameter
935 * @value a null terminated string giving the XPath expression to be evaluated
937 * This is normally called from xsltEvalUserParams to process a single
938 * parameter from a list of parameters. The @value is evaluated as an
939 * XPath expression and the result is stored in the context's global
940 * variable/parameter hash table.
942 * To have a parameter treated literally (not as an XPath expression)
943 * use xsltQuoteUserParams (or xsltQuoteOneUserParam). For more
944 * details see description of xsltProcessOneUserParamInternal.
946 * Returns 0 in case of success, -1 in case of error.
950 xsltEvalOneUserParam(xsltTransformContextPtr ctxt,
951 const xmlChar * name,
952 const xmlChar * value) {
953 return xsltProcessUserParamInternal(ctxt, name, value,
954 1 /* xpath eval ? */);
958 * xsltQuoteOneUserParam:
960 * @ctxt: the XSLT transformation context
961 * @name: a null terminated string giving the name of the parameter
962 * @value a null terminated string giving the parameter value
964 * This is normally called from xsltQuoteUserParams to process a single
965 * parameter from a list of parameters. The @value is stored in the
966 * context's global variable/parameter hash table.
968 * Returns 0 in case of success, -1 in case of error.
972 xsltQuoteOneUserParam(xsltTransformContextPtr ctxt,
973 const xmlChar * name,
974 const xmlChar * value) {
975 return xsltProcessUserParamInternal(ctxt, name, value,
976 0 /* xpath eval ? */);
981 * @ctxt: the XSLT transformation context
982 * @comp: the precompiled form
983 * @tree: the tree if select is NULL
985 * Computes a new variable value.
987 * Returns the xsltStackElemPtr or NULL in case of error
989 static xsltStackElemPtr
990 xsltBuildVariable(xsltTransformContextPtr ctxt, xsltStylePreCompPtr comp,
992 xsltStackElemPtr elem;
994 #ifdef WITH_XSLT_DEBUG_VARIABLE
995 xsltGenericDebug(xsltGenericDebugContext,
996 "Building variable %s", comp->name);
997 if (comp->select != NULL)
998 xsltGenericDebug(xsltGenericDebugContext,
999 " select %s", comp->select);
1000 xsltGenericDebug(xsltGenericDebugContext, "\n");
1003 elem = xsltNewStackElem();
1007 elem->name = xmlStrdup(comp->name);
1008 if (comp->select != NULL)
1009 elem->select = xmlStrdup(comp->select);
1011 elem->select = NULL;
1013 elem->nameURI = xmlStrdup(comp->ns);
1015 if (elem->computed == 0) {
1016 elem->value = xsltEvalVariable(ctxt, elem, comp);
1017 if (elem->value != NULL)
1024 * xsltRegisterVariable:
1025 * @ctxt: the XSLT transformation context
1026 * @comp: pointer to precompiled data
1027 * @tree: the tree if select is NULL
1028 * @param: this is a parameter actually
1030 * Computes and register a new variable value.
1032 * Returns 0 in case of success, -1 in case of error
1035 xsltRegisterVariable(xsltTransformContextPtr ctxt, xsltStylePreCompPtr comp,
1036 xmlNodePtr tree, int param) {
1037 xsltStackElemPtr elem;
1039 if (xsltCheckStackElem(ctxt, comp->name, comp->ns) != 0) {
1041 xsltTransformError(ctxt, NULL, comp->inst,
1042 "xsl:variable : redefining %s\n", comp->name);
1044 #ifdef WITH_XSLT_DEBUG_VARIABLE
1046 xsltGenericDebug(xsltGenericDebugContext,
1047 "param %s defined by caller\n", comp->name);
1051 elem = xsltBuildVariable(ctxt, comp, tree);
1052 xsltAddStackElem(ctxt, elem);
1057 * xsltGlobalVariableLookup:
1058 * @ctxt: the XSLT transformation context
1059 * @name: the variable name
1060 * @ns_uri: the variable namespace URI
1062 * Search in the Variable array of the context for the given
1065 * Returns the value or NULL if not found
1067 static xmlXPathObjectPtr
1068 xsltGlobalVariableLookup(xsltTransformContextPtr ctxt, const xmlChar *name,
1069 const xmlChar *ns_uri) {
1070 xsltStackElemPtr elem;
1071 xmlXPathObjectPtr ret = NULL;
1074 * Lookup the global variables in XPath global variable hash table
1076 if ((ctxt->xpathCtxt == NULL) || (ctxt->globalVars == NULL))
1078 elem = (xsltStackElemPtr)
1079 xmlHashLookup2(ctxt->globalVars, name, ns_uri);
1081 #ifdef WITH_XSLT_DEBUG_VARIABLE
1082 xsltGenericDebug(xsltGenericDebugContext,
1083 "global variable not found %s\n", name);
1087 if (elem->computed == 0)
1088 ret = xsltEvalGlobalVariable(elem, ctxt);
1091 return(xmlXPathObjectCopy(ret));
1095 * xsltVariableLookup:
1096 * @ctxt: the XSLT transformation context
1097 * @name: the variable name
1098 * @ns_uri: the variable namespace URI
1100 * Search in the Variable array of the context for the given
1103 * Returns the value or NULL if not found
1106 xsltVariableLookup(xsltTransformContextPtr ctxt, const xmlChar *name,
1107 const xmlChar *ns_uri) {
1108 xsltStackElemPtr elem;
1113 elem = xsltStackLookup(ctxt, name, ns_uri);
1115 return(xsltGlobalVariableLookup(ctxt, name, ns_uri));
1117 if (elem->computed == 0) {
1118 #ifdef WITH_XSLT_DEBUG_VARIABLE
1119 xsltGenericDebug(xsltGenericDebugContext,
1120 "uncomputed variable %s\n", name);
1122 elem->value = xsltEvalVariable(ctxt, elem, NULL);
1125 if (elem->value != NULL)
1126 return(xmlXPathObjectCopy(elem->value));
1127 #ifdef WITH_XSLT_DEBUG_VARIABLE
1128 xsltGenericDebug(xsltGenericDebugContext,
1129 "variable not found %s\n", name);
1135 * xsltParseStylesheetCallerParam:
1136 * @ctxt: the XSLT transformation context
1137 * @cur: the "param" element
1139 * parse an XSLT transformation param declaration, compute
1140 * its value but doesn't record it.
1142 * It returns the new xsltStackElemPtr or NULL
1146 xsltParseStylesheetCallerParam(xsltTransformContextPtr ctxt, xmlNodePtr cur) {
1147 xmlNodePtr tree = NULL;
1148 xsltStackElemPtr elem = NULL;
1149 xsltStylePreCompPtr comp;
1151 if ((cur == NULL) || (ctxt == NULL))
1153 comp = (xsltStylePreCompPtr) cur->_private;
1155 xsltTransformError(ctxt, NULL, cur,
1156 "xsl:param : compilation error\n");
1160 if (comp->name == NULL) {
1161 xsltTransformError(ctxt, NULL, cur,
1162 "xsl:param : missing name attribute\n");
1166 #ifdef WITH_XSLT_DEBUG_VARIABLE
1167 xsltGenericDebug(xsltGenericDebugContext,
1168 "Handling param %s\n", comp->name);
1171 if (comp->select == NULL) {
1172 tree = cur->children;
1174 #ifdef WITH_XSLT_DEBUG_VARIABLE
1175 xsltGenericDebug(xsltGenericDebugContext,
1176 " select %s\n", comp->select);
1181 elem = xsltBuildVariable(ctxt, comp, tree);
1187 * xsltParseGlobalVariable:
1188 * @style: the XSLT stylesheet
1189 * @cur: the "variable" element
1191 * parse an XSLT transformation variable declaration and record
1196 xsltParseGlobalVariable(xsltStylesheetPtr style, xmlNodePtr cur) {
1197 xsltStylePreCompPtr comp;
1199 if ((cur == NULL) || (style == NULL))
1202 xsltStylePreCompute(style, cur);
1203 comp = (xsltStylePreCompPtr) cur->_private;
1205 xsltTransformError(NULL, style, cur,
1206 "xsl:variable : compilation failed\n");
1210 if (comp->name == NULL) {
1211 xsltTransformError(NULL, style, cur,
1212 "xsl:variable : missing name attribute\n");
1216 #ifdef WITH_XSLT_DEBUG_VARIABLE
1217 xsltGenericDebug(xsltGenericDebugContext,
1218 "Registering global variable %s\n", comp->name);
1221 xsltRegisterGlobalVariable(style, comp->name, comp->ns, comp->select,
1222 cur->children, comp, NULL);
1226 * xsltParseGlobalParam:
1227 * @style: the XSLT stylesheet
1228 * @cur: the "param" element
1230 * parse an XSLT transformation param declaration and record
1235 xsltParseGlobalParam(xsltStylesheetPtr style, xmlNodePtr cur) {
1236 xsltStylePreCompPtr comp;
1238 if ((cur == NULL) || (style == NULL))
1241 xsltStylePreCompute(style, cur);
1242 comp = (xsltStylePreCompPtr) cur->_private;
1244 xsltTransformError(NULL, style, cur,
1245 "xsl:param : compilation failed\n");
1249 if (comp->name == NULL) {
1250 xsltTransformError(NULL, style, cur,
1251 "xsl:param : missing name attribute\n");
1255 #ifdef WITH_XSLT_DEBUG_VARIABLE
1256 xsltGenericDebug(xsltGenericDebugContext,
1257 "Registering global param %s\n", comp->name);
1260 xsltRegisterGlobalVariable(style, comp->name, comp->ns, comp->select,
1261 cur->children, comp, NULL);
1265 * xsltParseStylesheetVariable:
1266 * @ctxt: the XSLT transformation context
1267 * @cur: the "variable" element
1269 * parse an XSLT transformation variable declaration and record
1274 xsltParseStylesheetVariable(xsltTransformContextPtr ctxt, xmlNodePtr cur) {
1275 xsltStylePreCompPtr comp;
1277 if ((cur == NULL) || (ctxt == NULL))
1280 comp = (xsltStylePreCompPtr) cur->_private;
1282 xsltTransformError(ctxt, NULL, cur,
1283 "xsl:variable : compilation failed\n");
1287 if (comp->name == NULL) {
1288 xsltTransformError(ctxt, NULL, cur,
1289 "xsl:variable : missing name attribute\n");
1293 #ifdef WITH_XSLT_DEBUG_VARIABLE
1294 xsltGenericDebug(xsltGenericDebugContext,
1295 "Registering variable %s\n", comp->name);
1298 xsltRegisterVariable(ctxt, comp, cur->children, 0);
1302 * xsltParseStylesheetParam:
1303 * @ctxt: the XSLT transformation context
1304 * @cur: the "param" element
1306 * parse an XSLT transformation param declaration and record
1311 xsltParseStylesheetParam(xsltTransformContextPtr ctxt, xmlNodePtr cur) {
1312 xsltStylePreCompPtr comp;
1314 if ((cur == NULL) || (ctxt == NULL))
1317 comp = (xsltStylePreCompPtr) cur->_private;
1319 xsltTransformError(ctxt, NULL, cur,
1320 "xsl:param : compilation failed\n");
1324 if (comp->name == NULL) {
1325 xsltTransformError(ctxt, NULL, cur,
1326 "xsl:param : missing name attribute\n");
1330 #ifdef WITH_XSLT_DEBUG_VARIABLE
1331 xsltGenericDebug(xsltGenericDebugContext,
1332 "Registering param %s\n", comp->name);
1335 xsltRegisterVariable(ctxt, comp, cur->children, 1);
1339 * xsltFreeGlobalVariables:
1340 * @ctxt: the XSLT transformation context
1342 * Free up the data associated to the global variables
1347 xsltFreeGlobalVariables(xsltTransformContextPtr ctxt) {
1348 xmlHashFree(ctxt->globalVars, (xmlHashDeallocator) xsltFreeStackElem);
1352 * xsltXPathVariableLookup:
1353 * @ctxt: a void * but the the XSLT transformation context actually
1354 * @name: the variable name
1355 * @ns_uri: the variable namespace URI
1357 * This is the entry point when a varibale is needed by the XPath
1360 * Returns the value or NULL if not found
1363 xsltXPathVariableLookup(void *ctxt, const xmlChar *name,
1364 const xmlChar *ns_uri) {
1365 xsltTransformContextPtr context;
1366 xmlXPathObjectPtr ret;
1368 if ((ctxt == NULL) || (name == NULL))
1371 #ifdef WITH_XSLT_DEBUG_VARIABLE
1372 xsltGenericDebug(xsltGenericDebugContext,
1373 "Lookup variable %s\n", name);
1375 context = (xsltTransformContextPtr) ctxt;
1376 ret = xsltVariableLookup(context, name, ns_uri);
1378 xsltTransformError(ctxt, NULL, NULL,
1379 "unregistered variable %s\n", name);
1381 #ifdef WITH_XSLT_DEBUG_VARIABLE
1383 xsltGenericDebug(xsltGenericDebugContext,
1384 "found variable %s\n", name);