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.
16 #include <libxml/xmlmemory.h>
17 #include <libxml/tree.h>
18 #include <libxml/valid.h>
19 #include <libxml/hash.h>
20 #include <libxml/xmlerror.h>
21 #include <libxml/xpath.h>
22 #include <libxml/xpathInternals.h>
23 #include <libxml/parserInternals.h>
25 #include "xsltInternals.h"
26 #include "xsltutils.h"
27 #include "variables.h"
28 #include "transform.h"
32 #ifdef WITH_XSLT_DEBUG
33 #define WITH_XSLT_DEBUG_VARIABLE
36 /************************************************************************
40 ************************************************************************/
45 * Create a new XSLT ParserContext
47 * Returns the newly allocated xsltParserStackElem or NULL in case of error
49 static xsltStackElemPtr
50 xsltNewStackElem(void) {
53 cur = (xsltStackElemPtr) xmlMalloc(sizeof(xsltStackElem));
55 xsltPrintErrorContext(NULL, NULL, NULL);
56 xsltGenericError(xsltGenericErrorContext,
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 xsltPrintErrorContext(NULL, NULL, NULL);
85 xsltGenericError(xsltGenericErrorContext,
86 "xsltCopyStackElem : malloc failed\n");
89 cur->name = xmlStrdup(elem->name);
90 cur->nameURI = xmlStrdup(elem->nameURI);
91 cur->select = xmlStrdup(elem->select);
92 cur->tree = elem->tree;
93 cur->comp = elem->comp;
101 * @elem: an XSLT stack element
103 * Free up the memory allocated by @elem
106 xsltFreeStackElem(xsltStackElemPtr elem) {
109 if (elem->name != NULL)
111 if (elem->nameURI != NULL)
112 xmlFree(elem->nameURI);
113 if (elem->select != NULL)
114 xmlFree(elem->select);
115 if (elem->value != NULL)
116 xmlXPathFreeObject(elem->value);
122 * xsltFreeStackElemList:
123 * @elem: an XSLT stack element
125 * Free up the memory allocated by @elem
128 xsltFreeStackElemList(xsltStackElemPtr elem) {
129 xsltStackElemPtr next;
131 while(elem != NULL) {
133 xsltFreeStackElem(elem);
139 * xsltCheckStackElem:
140 * @ctxt: xn XSLT transformation context
141 * @name: the variable name
142 * @nameURI: the variable namespace URI
144 * check wether the variable or param is already defined
146 * Returns 1 if present, 0 if not, -1 in case of failure.
149 xsltCheckStackElem(xsltTransformContextPtr ctxt, const xmlChar *name,
150 const xmlChar *nameURI) {
151 xsltStackElemPtr cur;
153 if ((ctxt == NULL) || (name == NULL))
157 while (cur != NULL) {
158 if (xmlStrEqual(name, cur->name)) {
159 if (((nameURI == NULL) && (cur->nameURI == NULL)) ||
160 ((nameURI != NULL) && (cur->nameURI != NULL) &&
161 (xmlStrEqual(nameURI, cur->nameURI)))) {
172 * @ctxt: xn XSLT transformation context
173 * @elem: a stack element
175 * add a new element at this level of the stack.
177 * Returns 0 in case of success, -1 in case of failure.
180 xsltAddStackElem(xsltTransformContextPtr ctxt, xsltStackElemPtr elem) {
181 if ((ctxt == NULL) || (elem == NULL))
184 elem->next = ctxt->varsTab[ctxt->varsNr - 1];
185 ctxt->varsTab[ctxt->varsNr - 1] = elem;
191 * xsltAddStackElemList:
192 * @ctxt: xn XSLT transformation context
193 * @elems: a stack element list
195 * add the new element list at this level of the stack.
197 * Returns 0 in case of success, -1 in case of failure.
200 xsltAddStackElemList(xsltTransformContextPtr ctxt, xsltStackElemPtr elems) {
201 xsltStackElemPtr cur;
203 if ((ctxt == NULL) || (elems == NULL))
206 /* TODO: check doublons */
207 if (ctxt->varsTab[ctxt->varsNr - 1] != NULL) {
208 cur = ctxt->varsTab[ctxt->varsNr - 1];
209 while (cur->next != NULL)
213 elems->next = ctxt->varsTab[ctxt->varsNr - 1];
214 ctxt->varsTab[ctxt->varsNr - 1] = elems;
222 * @ctxt: an XSLT transformation context
223 * @name: the local part of the name
224 * @nameURI: the URI part of the name
226 * Locate an element in the stack based on its name.
228 static xsltStackElemPtr
229 xsltStackLookup(xsltTransformContextPtr ctxt, const xmlChar *name,
230 const xmlChar *nameURI) {
231 xsltStackElemPtr ret = NULL;
233 xsltStackElemPtr cur;
235 if ((ctxt == NULL) || (name == NULL) || (ctxt->varsNr == 0))
239 * Do the lookup from the top of the stack, but
240 * don't use params being computed in a call-param
244 for (i = ctxt->varsNr; i > ctxt->varsBase; i--) {
245 cur = ctxt->varsTab[i-1];
246 while (cur != NULL) {
247 if (xmlStrEqual(cur->name, name)) {
248 if (nameURI == NULL) {
249 if (cur->nameURI == NULL) {
253 if ((cur->nameURI != NULL) &&
254 (xmlStrEqual(cur->nameURI, nameURI))) {
266 /************************************************************************
268 * Module interfaces *
270 ************************************************************************/
274 * @ctxt: the XSLT transformation context
275 * @elem: the variable or parameter.
276 * @precomp: pointer to precompiled data
278 * Evaluate a variable value.
280 * Returns the XPath Object value or NULL in case of error
282 static xmlXPathObjectPtr
283 xsltEvalVariable(xsltTransformContextPtr ctxt, xsltStackElemPtr elem,
284 xsltStylePreCompPtr precomp) {
285 xmlXPathObjectPtr result = NULL;
286 int oldProximityPosition, oldContextSize;
287 xmlNodePtr oldInst, oldNode;
288 xsltDocumentPtr oldDoc;
290 xmlNsPtr *oldNamespaces;
292 if ((ctxt == NULL) || (elem == NULL))
295 #ifdef WITH_XSLT_DEBUG_VARIABLE
296 xsltGenericDebug(xsltGenericDebugContext,
297 "Evaluating variable %s\n", elem->name);
299 if (elem->select != NULL) {
300 xmlXPathCompExprPtr comp = NULL;
302 if ((precomp != NULL) && (precomp->comp != NULL)) {
303 comp = precomp->comp;
305 comp = xmlXPathCompile(elem->select);
309 oldProximityPosition = ctxt->xpathCtxt->proximityPosition;
310 oldContextSize = ctxt->xpathCtxt->contextSize;
311 ctxt->xpathCtxt->node = (xmlNodePtr) ctxt->node;
312 oldDoc = ctxt->document;
313 oldNode = ctxt->node;
314 oldInst = ctxt->inst;
315 oldNsNr = ctxt->xpathCtxt->nsNr;
316 oldNamespaces = ctxt->xpathCtxt->namespaces;
317 if (precomp != NULL) {
318 ctxt->inst = precomp->inst;
319 ctxt->xpathCtxt->namespaces = precomp->nsList;
320 ctxt->xpathCtxt->nsNr = precomp->nsNr;
323 ctxt->xpathCtxt->namespaces = NULL;
324 ctxt->xpathCtxt->nsNr = 0;
326 result = xmlXPathCompiledEval(comp, ctxt->xpathCtxt);
327 ctxt->xpathCtxt->contextSize = oldContextSize;
328 ctxt->xpathCtxt->proximityPosition = oldProximityPosition;
329 ctxt->xpathCtxt->nsNr = oldNsNr;
330 ctxt->xpathCtxt->namespaces = oldNamespaces;
331 ctxt->inst = oldInst;
332 ctxt->node = oldNode;
333 ctxt->document = oldDoc;
334 if ((precomp == NULL) || (precomp->comp == NULL))
335 xmlXPathFreeCompExpr(comp);
336 if (result == NULL) {
337 xsltPrintErrorContext(ctxt, NULL, precomp->inst);
338 xsltGenericError(xsltGenericErrorContext,
339 "Evaluating variable %s failed\n", elem->name);
340 #ifdef WITH_XSLT_DEBUG_VARIABLE
341 #ifdef LIBXML_DEBUG_ENABLED
343 if ((xsltGenericDebugContext == stdout) ||
344 (xsltGenericDebugContext == stderr))
345 xmlXPathDebugDumpObject((FILE *)xsltGenericDebugContext,
351 if (elem->tree == NULL) {
352 result = xmlXPathNewCString("");
355 * This is a result tree fragment.
357 xmlNodePtr container;
358 xmlNodePtr oldInsert;
360 container = xmlNewDocNode(ctxt->output, NULL,
361 (const xmlChar *) "fake", NULL);
362 if (container == NULL)
365 oldInsert = ctxt->insert;
366 ctxt->insert = container;
367 xsltApplyOneTemplate(ctxt, ctxt->node, elem->tree, NULL, NULL);
368 ctxt->insert = oldInsert;
370 result = xmlXPathNewValueTree(container);
371 if (result == NULL) {
372 result = xmlXPathNewCString("");
374 #ifdef WITH_XSLT_DEBUG_VARIABLE
375 #ifdef LIBXML_DEBUG_ENABLED
376 if ((xsltGenericDebugContext == stdout) ||
377 (xsltGenericDebugContext == stderr))
378 xmlXPathDebugDumpObject((FILE *)xsltGenericDebugContext,
388 * xsltEvalGlobalVariable:
389 * @elem: the variable or parameter.
390 * @ctxt: the XSLT transformation context
392 * Evaluate a global variable value.
394 * Returns the XPath Object value or NULL in case of error
396 static xmlXPathObjectPtr
397 xsltEvalGlobalVariable(xsltStackElemPtr elem, xsltTransformContextPtr ctxt) {
398 xmlXPathObjectPtr result = NULL;
399 xsltStylePreCompPtr precomp;
400 int oldProximityPosition, oldContextSize;
403 xmlNsPtr *oldNamespaces;
405 if ((ctxt == NULL) || (elem == NULL))
411 #ifdef WITH_XSLT_DEBUG_VARIABLE
412 xsltGenericDebug(xsltGenericDebugContext,
413 "Evaluating global variable %s\n", elem->name);
416 precomp = elem->comp;
417 if (elem->select != NULL) {
418 xmlXPathCompExprPtr comp = NULL;
420 if ((precomp != NULL) && (precomp->comp != NULL)) {
421 comp = precomp->comp;
423 comp = xmlXPathCompile(elem->select);
427 oldProximityPosition = ctxt->xpathCtxt->proximityPosition;
428 oldContextSize = ctxt->xpathCtxt->contextSize;
429 oldInst = ctxt->inst;
430 oldNsNr = ctxt->xpathCtxt->nsNr;
431 oldNamespaces = ctxt->xpathCtxt->namespaces;
432 if (precomp != NULL) {
433 ctxt->inst = precomp->inst;
434 ctxt->xpathCtxt->namespaces = precomp->nsList;
435 ctxt->xpathCtxt->nsNr = precomp->nsNr;
438 ctxt->xpathCtxt->namespaces = NULL;
439 ctxt->xpathCtxt->nsNr = 0;
441 ctxt->xpathCtxt->node = (xmlNodePtr) ctxt->node;
442 result = xmlXPathCompiledEval(comp, ctxt->xpathCtxt);
443 ctxt->xpathCtxt->contextSize = oldContextSize;
444 ctxt->xpathCtxt->proximityPosition = oldProximityPosition;
445 ctxt->inst = oldInst;
446 ctxt->xpathCtxt->nsNr = oldNsNr;
447 ctxt->xpathCtxt->namespaces = oldNamespaces;
448 if ((precomp == NULL) || (precomp->comp == NULL))
449 xmlXPathFreeCompExpr(comp);
450 if (result == NULL) {
451 xsltPrintErrorContext(ctxt, NULL, precomp->inst);
452 xsltGenericError(xsltGenericErrorContext,
453 "Evaluating global variable %s failed\n", elem->name);
454 #ifdef WITH_XSLT_DEBUG_VARIABLE
455 #ifdef LIBXML_DEBUG_ENABLED
457 if ((xsltGenericDebugContext == stdout) ||
458 (xsltGenericDebugContext == stderr))
459 xmlXPathDebugDumpObject((FILE *)xsltGenericDebugContext,
465 if (elem->tree == NULL) {
466 result = xmlXPathNewCString("");
469 * This is a result tree fragment.
471 xmlNodePtr container;
472 xmlNodePtr oldInsert;
474 container = xmlNewDocNode(ctxt->output, NULL,
475 (const xmlChar *) "fake", NULL);
476 if (container == NULL)
479 oldInsert = ctxt->insert;
480 ctxt->insert = container;
481 xsltApplyOneTemplate(ctxt, ctxt->node, elem->tree, NULL, NULL);
482 ctxt->insert = oldInsert;
484 result = xmlXPathNewValueTree(container);
485 if (result == NULL) {
486 result = xmlXPathNewCString("");
488 #ifdef WITH_XSLT_DEBUG_VARIABLE
489 #ifdef LIBXML_DEBUG_ENABLED
490 if ((xsltGenericDebugContext == stdout) ||
491 (xsltGenericDebugContext == stderr))
492 xmlXPathDebugDumpObject((FILE *)xsltGenericDebugContext,
498 if (result != NULL) {
499 elem->value = result;
506 * xsltEvalGlobalVariables:
507 * @ctxt: the XSLT transformation context
509 * Evaluate the global variables of a stylesheet. This need to be
510 * done on parsed stylesheets before starting to apply transformations
512 * Returns 0 in case of success, -1 in case of error
515 xsltEvalGlobalVariables(xsltTransformContextPtr ctxt) {
516 xsltStackElemPtr elem;
517 xsltStylesheetPtr style;
522 #ifdef WITH_XSLT_DEBUG_VARIABLE
523 xsltGenericDebug(xsltGenericDebugContext,
524 "Registering global variables\n");
526 ctxt->node = (xmlNodePtr) ctxt->document->doc;
527 ctxt->xpathCtxt->contextSize = 1;
528 ctxt->xpathCtxt->proximityPosition = 1;
531 * Walk the list from the stylesheets and populate the hash table
534 while (style != NULL) {
535 elem = style->variables;
537 #ifdef WITH_XSLT_DEBUG_VARIABLE
538 if ((style->doc != NULL) && (style->doc->URL != NULL)) {
539 xsltGenericDebug(xsltGenericDebugContext,
540 "Registering global variables from %s\n",
545 while (elem != NULL) {
546 xsltStackElemPtr def;
549 * Global variables are stored in the variables pool.
551 def = (xsltStackElemPtr)
552 xmlHashLookup2(ctxt->globalVars,
553 elem->name, elem->nameURI);
557 def = xsltCopyStackElem(elem);
558 res = xmlHashAddEntry2(ctxt->globalVars,
559 elem->name, elem->nameURI, def);
560 } else if ((elem->comp != NULL) &&
561 (elem->comp->type == XSLT_FUNC_VARIABLE)) {
562 xsltPrintErrorContext(ctxt, style, elem->comp->inst);
563 xsltGenericError(xsltGenericErrorContext,
564 "Global variable %s already defined\n", elem->name);
569 style = xsltNextImport(style);
573 * This part does the actual evaluation
575 ctxt->node = (xmlNodePtr) ctxt->document->doc;
576 ctxt->xpathCtxt->contextSize = 1;
577 ctxt->xpathCtxt->proximityPosition = 1;
578 xmlHashScan(ctxt->globalVars,
579 (xmlHashScanner) xsltEvalGlobalVariable, ctxt);
585 * xsltRegisterGlobalVariable:
586 * @style: the XSLT transformation context
587 * @name: the variable name
588 * @ns_uri: the variable namespace URI
589 * @select: the expression which need to be evaluated to generate a value
590 * @tree: the subtree if select is NULL
591 * @comp: the precompiled value
592 * @value: the string value if available
594 * Register a new variable value. If @value is NULL it unregisters
597 * Returns 0 in case of success, -1 in case of error
600 xsltRegisterGlobalVariable(xsltStylesheetPtr style, const xmlChar *name,
601 const xmlChar *ns_uri, const xmlChar *select,
602 xmlNodePtr tree, xsltStylePreCompPtr comp,
603 const xmlChar *value) {
604 xsltStackElemPtr elem, tmp;
612 #ifdef WITH_XSLT_DEBUG_VARIABLE
613 if (comp->type == XSLT_FUNC_PARAM)
614 xsltGenericDebug(xsltGenericDebugContext,
615 "Defining global param %s\n", name);
617 xsltGenericDebug(xsltGenericDebugContext,
618 "Defining global variable %s\n", name);
621 elem = xsltNewStackElem();
625 elem->name = xmlStrdup(name);
626 elem->select = xmlStrdup(select);
628 elem->nameURI = xmlStrdup(ns_uri);
630 tmp = style->variables;
633 style->variables = elem;
635 while (tmp->next != NULL)
642 elem->value = xmlXPathNewString(value);
648 * xsltEvalUserParams:
649 * @ctxt: the XSLT transformation context
650 * @params: a NULL terminated arry of parameters names/values tuples
652 * Evaluate the global variables of a stylesheet. This needs to be
653 * done on parsed stylesheets before starting to apply transformations
655 * Returns 0 in case of success, -1 in case of error
658 xsltEvalUserParams(xsltTransformContextPtr ctxt, const char **params) {
659 xsltStylesheetPtr style;
662 const xmlChar *value;
663 xmlChar *ncname, *prefix;
665 xmlXPathCompExprPtr comp;
666 xmlXPathObjectPtr result;
667 int oldProximityPosition, oldContextSize;
669 xmlNsPtr *oldNamespaces;
677 while (params[indx] != NULL) {
678 name = (const xmlChar *)params[indx++];
679 value = (const xmlChar *)params[indx++];
680 if ((name == NULL) || (value == NULL))
683 #ifdef WITH_XSLT_DEBUG_VARIABLE
684 xsltGenericDebug(xsltGenericDebugContext,
685 "Evaluating user parameter %s=%s\n", name, value);
691 ncname = xmlSplitQName2(name, &prefix);
693 if (ncname != NULL) {
694 if (prefix != NULL) {
697 ns = xmlSearchNs(style->doc, xmlDocGetRootElement(style->doc),
700 xsltPrintErrorContext(ctxt, style, NULL);
701 xsltGenericError(xsltGenericErrorContext,
702 "user param : no namespace bound to prefix %s\n", prefix);
714 ncname = xmlStrdup(name);
721 comp = xmlXPathCompile(value);
723 oldProximityPosition = ctxt->xpathCtxt->proximityPosition;
724 oldContextSize = ctxt->xpathCtxt->contextSize;
725 ctxt->xpathCtxt->node = (xmlNodePtr) ctxt->node;
728 * There is really no in scope namespace for parameters on the
731 oldNsNr = ctxt->xpathCtxt->nsNr;
732 oldNamespaces = ctxt->xpathCtxt->namespaces;
733 ctxt->xpathCtxt->namespaces = NULL;
734 ctxt->xpathCtxt->nsNr = 0;
735 result = xmlXPathCompiledEval(comp, ctxt->xpathCtxt);
736 ctxt->xpathCtxt->contextSize = oldContextSize;
737 ctxt->xpathCtxt->proximityPosition = oldProximityPosition;
738 ctxt->xpathCtxt->nsNr = oldNsNr;
739 ctxt->xpathCtxt->namespaces = oldNamespaces;
740 xmlXPathFreeCompExpr(comp);
742 if (result == NULL) {
743 xsltPrintErrorContext(ctxt, style, NULL);
744 xsltGenericError(xsltGenericErrorContext,
745 "Evaluating user parameter %s failed\n", name);
747 xsltStackElemPtr elem;
750 #ifdef WITH_XSLT_DEBUG_VARIABLE
751 #ifdef LIBXML_DEBUG_ENABLED
752 if ((xsltGenericDebugContext == stdout) ||
753 (xsltGenericDebugContext == stderr))
754 xmlXPathDebugDumpObject((FILE *)xsltGenericDebugContext,
759 elem = xsltNewStackElem();
761 elem->name = xmlStrdup(ncname);
763 elem->select = xmlStrdup(value);
767 elem->nameURI = xmlStrdup(href);
770 elem->value = result;
773 * Global parameters are stored in the XPath context
776 res = xmlHashAddEntry2(ctxt->globalVars,
779 xsltFreeStackElem(elem);
780 xsltPrintErrorContext(ctxt, style, NULL);
781 xsltGenericError(xsltGenericErrorContext,
782 "Global parameter %s already defined\n", ncname);
793 * @ctxt: the XSLT transformation context
794 * @comp: the precompiled form
795 * @tree: the tree if select is NULL
797 * Computes a new variable value.
799 * Returns the xsltStackElemPtr or NULL in case of error
801 static xsltStackElemPtr
802 xsltBuildVariable(xsltTransformContextPtr ctxt, xsltStylePreCompPtr comp,
804 xsltStackElemPtr elem;
806 #ifdef WITH_XSLT_DEBUG_VARIABLE
807 xsltGenericDebug(xsltGenericDebugContext,
808 "Building variable %s", comp->name);
809 if (comp->select != NULL)
810 xsltGenericDebug(xsltGenericDebugContext,
811 " select %s", comp->select);
812 xsltGenericDebug(xsltGenericDebugContext, "\n");
815 elem = xsltNewStackElem();
819 elem->name = xmlStrdup(comp->name);
820 if (comp->select != NULL)
821 elem->select = xmlStrdup(comp->select);
825 elem->nameURI = xmlStrdup(comp->ns);
827 if (elem->computed == 0) {
828 elem->value = xsltEvalVariable(ctxt, elem, comp);
829 if (elem->value != NULL)
836 * xsltRegisterVariable:
837 * @ctxt: the XSLT transformation context
838 * @comp: pointer to precompiled data
839 * @tree: the tree if select is NULL
840 * @param: this is a parameter actually
842 * Computes and register a new variable value.
844 * Returns 0 in case of success, -1 in case of error
847 xsltRegisterVariable(xsltTransformContextPtr ctxt, xsltStylePreCompPtr comp,
848 xmlNodePtr tree, int param) {
849 xsltStackElemPtr elem;
851 if (xsltCheckStackElem(ctxt, comp->name, comp->ns) != 0) {
853 xsltPrintErrorContext(ctxt, NULL, comp->inst);
854 xsltGenericError(xsltGenericErrorContext,
855 "xsl:variable : redefining %s\n", comp->name);
857 #ifdef WITH_XSLT_DEBUG_VARIABLE
859 xsltGenericDebug(xsltGenericDebugContext,
860 "param %s defined by caller\n", comp->name);
864 elem = xsltBuildVariable(ctxt, comp, tree);
865 xsltAddStackElem(ctxt, elem);
870 * xsltGlobalVariableLookup:
871 * @ctxt: the XSLT transformation context
872 * @name: the variable name
873 * @ns_uri: the variable namespace URI
875 * Search in the Variable array of the context for the given
878 * Returns the value or NULL if not found
880 static xmlXPathObjectPtr
881 xsltGlobalVariableLookup(xsltTransformContextPtr ctxt, const xmlChar *name,
882 const xmlChar *ns_uri) {
883 xsltStackElemPtr elem;
884 xmlXPathObjectPtr ret = NULL;
887 * Lookup the global variables in XPath global variable hash table
889 if ((ctxt->xpathCtxt == NULL) || (ctxt->globalVars == NULL))
891 elem = (xsltStackElemPtr)
892 xmlHashLookup2(ctxt->globalVars, name, ns_uri);
894 #ifdef WITH_XSLT_DEBUG_VARIABLE
895 xsltGenericDebug(xsltGenericDebugContext,
896 "global variable not found %s\n", name);
900 if (elem->computed == 0)
901 ret = xsltEvalGlobalVariable(elem, ctxt);
904 return(xmlXPathObjectCopy(ret));
908 * xsltVariableLookup:
909 * @ctxt: the XSLT transformation context
910 * @name: the variable name
911 * @ns_uri: the variable namespace URI
913 * Search in the Variable array of the context for the given
916 * Returns the value or NULL if not found
919 xsltVariableLookup(xsltTransformContextPtr ctxt, const xmlChar *name,
920 const xmlChar *ns_uri) {
921 xsltStackElemPtr elem;
926 elem = xsltStackLookup(ctxt, name, ns_uri);
928 return(xsltGlobalVariableLookup(ctxt, name, ns_uri));
930 if (elem->computed == 0) {
931 #ifdef WITH_XSLT_DEBUG_VARIABLE
932 xsltGenericDebug(xsltGenericDebugContext,
933 "uncomputed variable %s\n", name);
935 elem->value = xsltEvalVariable(ctxt, elem, NULL);
938 if (elem->value != NULL)
939 return(xmlXPathObjectCopy(elem->value));
940 #ifdef WITH_XSLT_DEBUG_VARIABLE
941 xsltGenericDebug(xsltGenericDebugContext,
942 "variable not found %s\n", name);
948 * xsltParseStylesheetCallerParam:
949 * @ctxt: the XSLT transformation context
950 * @cur: the "param" element
952 * parse an XSLT transformation param declaration, compute
953 * its value but doesn't record it.
955 * It returns the new xsltStackElemPtr or NULL
959 xsltParseStylesheetCallerParam(xsltTransformContextPtr ctxt, xmlNodePtr cur) {
960 xmlNodePtr tree = NULL;
961 xsltStackElemPtr elem = NULL;
962 xsltStylePreCompPtr comp;
964 if ((cur == NULL) || (ctxt == NULL))
966 comp = (xsltStylePreCompPtr) cur->_private;
968 xsltPrintErrorContext(ctxt, NULL, cur);
969 xsltGenericError(xsltGenericErrorContext,
970 "xsl:param : compilation error\n");
974 if (comp->name == NULL) {
975 xsltPrintErrorContext(ctxt, NULL, cur);
976 xsltGenericError(xsltGenericErrorContext,
977 "xsl:param : missing name attribute\n");
981 #ifdef WITH_XSLT_DEBUG_VARIABLE
982 xsltGenericDebug(xsltGenericDebugContext,
983 "Handling param %s\n", comp->name);
986 if (comp->select == NULL) {
987 tree = cur->children;
989 #ifdef WITH_XSLT_DEBUG_VARIABLE
990 xsltGenericDebug(xsltGenericDebugContext,
991 " select %s\n", comp->select);
996 elem = xsltBuildVariable(ctxt, comp, tree);
1002 * xsltParseGlobalVariable:
1003 * @style: the XSLT stylesheet
1004 * @cur: the "variable" element
1006 * parse an XSLT transformation variable declaration and record
1011 xsltParseGlobalVariable(xsltStylesheetPtr style, xmlNodePtr cur) {
1012 xsltStylePreCompPtr comp;
1014 if ((cur == NULL) || (style == NULL))
1017 xsltStylePreCompute(style, cur);
1018 comp = (xsltStylePreCompPtr) cur->_private;
1020 xsltPrintErrorContext(NULL, style, cur);
1021 xsltGenericError(xsltGenericErrorContext,
1022 "xsl:variable : compilation failed\n");
1026 if (comp->name == NULL) {
1027 xsltPrintErrorContext(NULL, style, cur);
1028 xsltGenericError(xsltGenericErrorContext,
1029 "xsl:variable : missing name attribute\n");
1033 #ifdef WITH_XSLT_DEBUG_VARIABLE
1034 xsltGenericDebug(xsltGenericDebugContext,
1035 "Registering global variable %s\n", comp->name);
1038 xsltRegisterGlobalVariable(style, comp->name, comp->ns, comp->select,
1039 cur->children, comp, NULL);
1043 * xsltParseGlobalParam:
1044 * @style: the XSLT stylesheet
1045 * @cur: the "param" element
1047 * parse an XSLT transformation param declaration and record
1052 xsltParseGlobalParam(xsltStylesheetPtr style, xmlNodePtr cur) {
1053 xsltStylePreCompPtr comp;
1055 if ((cur == NULL) || (style == NULL))
1058 xsltStylePreCompute(style, cur);
1059 comp = (xsltStylePreCompPtr) cur->_private;
1061 xsltPrintErrorContext(NULL, style, cur);
1062 xsltGenericError(xsltGenericErrorContext,
1063 "xsl:param : compilation failed\n");
1067 if (comp->name == NULL) {
1068 xsltPrintErrorContext(NULL, style, cur);
1069 xsltGenericError(xsltGenericErrorContext,
1070 "xsl:param : missing name attribute\n");
1074 #ifdef WITH_XSLT_DEBUG_VARIABLE
1075 xsltGenericDebug(xsltGenericDebugContext,
1076 "Registering global param %s\n", comp->name);
1079 xsltRegisterGlobalVariable(style, comp->name, comp->ns, comp->select,
1080 cur->children, comp, NULL);
1084 * xsltParseStylesheetVariable:
1085 * @ctxt: the XSLT transformation context
1086 * @cur: the "variable" element
1088 * parse an XSLT transformation variable declaration and record
1093 xsltParseStylesheetVariable(xsltTransformContextPtr ctxt, xmlNodePtr cur) {
1094 xsltStylePreCompPtr comp;
1096 if ((cur == NULL) || (ctxt == NULL))
1099 comp = (xsltStylePreCompPtr) cur->_private;
1101 xsltPrintErrorContext(ctxt, NULL, cur);
1102 xsltGenericError(xsltGenericErrorContext,
1103 "xsl:variable : compilation failed\n");
1107 if (comp->name == NULL) {
1108 xsltPrintErrorContext(ctxt, NULL, cur);
1109 xsltGenericError(xsltGenericErrorContext,
1110 "xsl:variable : missing name attribute\n");
1114 #ifdef WITH_XSLT_DEBUG_VARIABLE
1115 xsltGenericDebug(xsltGenericDebugContext,
1116 "Registering variable %s\n", comp->name);
1119 xsltRegisterVariable(ctxt, comp, cur->children, 0);
1123 * xsltParseStylesheetParam:
1124 * @ctxt: the XSLT transformation context
1125 * @cur: the "param" element
1127 * parse an XSLT transformation param declaration and record
1132 xsltParseStylesheetParam(xsltTransformContextPtr ctxt, xmlNodePtr cur) {
1133 xsltStylePreCompPtr comp;
1135 if ((cur == NULL) || (ctxt == NULL))
1138 comp = (xsltStylePreCompPtr) cur->_private;
1140 xsltPrintErrorContext(ctxt, NULL, cur);
1141 xsltGenericError(xsltGenericErrorContext,
1142 "xsl:param : compilation failed\n");
1146 if (comp->name == NULL) {
1147 xsltPrintErrorContext(ctxt, NULL, cur);
1148 xsltGenericError(xsltGenericErrorContext,
1149 "xsl:param : missing name attribute\n");
1153 #ifdef WITH_XSLT_DEBUG_VARIABLE
1154 xsltGenericDebug(xsltGenericDebugContext,
1155 "Registering param %s\n", comp->name);
1158 xsltRegisterVariable(ctxt, comp, cur->children, 1);
1162 * xsltFreeGlobalVariables:
1163 * @ctxt: the XSLT transformation context
1165 * Free up the data associated to the global variables
1170 xsltFreeGlobalVariables(xsltTransformContextPtr ctxt) {
1171 xmlHashFree(ctxt->globalVars, (xmlHashDeallocator) xsltFreeStackElem);
1175 * xsltXPathVariableLookup:
1176 * @ctxt: a void * but the the XSLT transformation context actually
1177 * @name: the variable name
1178 * @ns_uri: the variable namespace URI
1180 * This is the entry point when a varibale is needed by the XPath
1183 * Returns the value or NULL if not found
1186 xsltXPathVariableLookup(void *ctxt, const xmlChar *name,
1187 const xmlChar *ns_uri) {
1188 xsltTransformContextPtr context;
1189 xmlXPathObjectPtr ret;
1191 if ((ctxt == NULL) || (name == NULL))
1194 #ifdef WITH_XSLT_DEBUG_VARIABLE
1195 xsltGenericDebug(xsltGenericDebugContext,
1196 "Lookup variable %s\n", name);
1198 context = (xsltTransformContextPtr) ctxt;
1199 ret = xsltVariableLookup(context, name, ns_uri);
1201 xsltPrintErrorContext(ctxt, NULL, NULL);
1202 xsltGenericError(xsltGenericErrorContext,
1203 "unregistered variable %s\n", name);
1205 #ifdef WITH_XSLT_DEBUG_VARIABLE
1207 xsltGenericDebug(xsltGenericDebugContext,
1208 "found variable %s\n", name);