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.
9 * Daniel.Veillard@imag.fr
12 #include "xsltconfig.h"
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>
24 #include <libxml/xmlversion.h>
26 #include "xsltInternals.h"
27 #include "xsltutils.h"
28 #include "variables.h"
29 #include "transform.h"
32 #define DEBUG_VARIABLE
34 /************************************************************************
38 ************************************************************************/
43 * Create a new XSLT ParserContext
45 * Returns the newly allocated xsltParserStackElem or NULL in case of error
47 static xsltStackElemPtr
48 xsltNewStackElem(void) {
51 cur = (xsltStackElemPtr) xmlMalloc(sizeof(xsltStackElem));
53 xsltGenericError(xsltGenericErrorContext,
54 "xsltNewStackElem : malloc failed\n");
57 memset(cur, 0, sizeof(xsltStackElem));
64 * @elem: an XSLT stack element
66 * Free up the memory allocated by @elem
69 xsltFreeStackElem(xsltStackElemPtr elem) {
72 if (elem->name != NULL)
74 if (elem->nameURI != NULL)
75 xmlFree(elem->nameURI);
76 if (elem->select != NULL)
77 xmlFree(elem->select);
78 if (elem->value != NULL)
79 xmlXPathFreeObject(elem->value);
81 memset(elem, -1, sizeof(xsltStackElem));
86 * xsltFreeStackElemList:
87 * @elem: an XSLT stack element
89 * Free up the memory allocated by @elem
92 xsltFreeStackElemList(xsltStackElemPtr elem) {
93 xsltStackElemPtr next;
97 xsltFreeStackElem(elem);
103 * xsltCheckStackElem:
104 * @ctxt: xn XSLT transformation context
105 * @name: the variable name
106 * @nameURI: the variable namespace URI
108 * check wether the variable or param is already defined
110 * Returns 1 if present, 0 if not, -1 in case of failure.
113 xsltCheckStackElem(xsltTransformContextPtr ctxt, const xmlChar *name,
114 const xmlChar *nameURI) {
115 xsltStackElemPtr cur;
117 if ((ctxt == NULL) || (name == NULL))
121 while (cur != NULL) {
122 if (xmlStrEqual(name, cur->name)) {
123 if (((nameURI == NULL) && (cur->nameURI == NULL)) ||
124 ((nameURI != NULL) && (cur->nameURI != NULL) &&
125 (xmlStrEqual(nameURI, cur->nameURI)))) {
136 * @ctxt: xn XSLT transformation context
137 * @elem: a stack element
139 * add a new element at this level of the stack.
141 * Returns 0 in case of success, -1 in case of failure.
144 xsltAddStackElem(xsltTransformContextPtr ctxt, xsltStackElemPtr elem) {
145 if ((ctxt == NULL) || (elem == NULL))
148 elem->next = ctxt->varsTab[ctxt->varsNr - 1];
149 ctxt->varsTab[ctxt->varsNr - 1] = elem;
155 * xsltAddStackElemList:
156 * @ctxt: xn XSLT transformation context
157 * @elems: a stack element list
159 * add the new element list at this level of the stack.
161 * Returns 0 in case of success, -1 in case of failure.
164 xsltAddStackElemList(xsltTransformContextPtr ctxt, xsltStackElemPtr elems) {
165 xsltStackElemPtr cur;
167 if ((ctxt == NULL) || (elems == NULL))
170 /* TODO: check doublons */
171 if (ctxt->varsTab[ctxt->varsNr - 1] != NULL) {
172 cur = ctxt->varsTab[ctxt->varsNr - 1];
173 while (cur->next != NULL)
177 elems->next = ctxt->varsTab[ctxt->varsNr - 1];
178 ctxt->varsTab[ctxt->varsNr - 1] = elems;
186 * @ctxt: an XSLT transformation context
187 * @name: the local part of the name
188 * @nameURI: the URI part of the name
190 * Locate an element in the stack based on its name.
192 static xsltStackElemPtr
193 xsltStackLookup(xsltTransformContextPtr ctxt, const xmlChar *name,
194 const xmlChar *nameURI) {
195 xsltStackElemPtr ret = NULL;
197 xsltStackElemPtr cur;
199 if ((ctxt == NULL) || (name == NULL))
203 * Do the lookup from the top of the stack, but
204 * don't use params being computed in a call-param
206 i = ctxt->varsNr - 1;
209 cur = ctxt->varsTab[i];
210 while (cur != NULL) {
211 if (xmlStrEqual(cur->name, name)) {
212 if (nameURI == NULL) {
213 if (cur->nameURI == NULL) {
217 if ((cur->nameURI != NULL) &&
218 (xmlStrEqual(cur->nameURI, nameURI))) {
230 /************************************************************************
232 * Module interfaces *
234 ************************************************************************/
238 * @ctxt: the XSLT transformation context
239 * @elem: the variable or parameter.
241 * Evaluate a variable value.
243 * Returns 0 in case of success, -1 in case of error
246 xsltEvalVariable(xsltTransformContextPtr ctxt, xsltStackElemPtr elem) {
247 if ((ctxt == NULL) || (elem == NULL))
250 #ifdef DEBUG_VARIABLE
251 xsltGenericDebug(xsltGenericDebugContext,
252 "Evaluating variable %s\n", elem->name);
254 if (elem->select != NULL) {
255 xmlXPathCompExprPtr comp;
256 xmlXPathObjectPtr result;
258 comp = xmlXPathCompile(elem->select);
261 ctxt->xpathCtxt->node = (xmlNodePtr) ctxt->node;
262 result = xmlXPathCompiledEval(comp, ctxt->xpathCtxt);
263 xmlXPathFreeCompExpr(comp);
264 if (result == NULL) {
265 xsltGenericError(xsltGenericErrorContext,
266 "Evaluating global variable %s failed\n");
268 #ifdef DEBUG_VARIABLE
269 #ifdef LIBXML_DEBUG_ENABLED
270 if ((xsltGenericDebugContext == stdout) ||
271 (xsltGenericDebugContext == stderr))
272 xmlXPathDebugDumpObject((FILE *)xsltGenericDebugContext,
276 if (elem->value != NULL)
277 xmlXPathFreeObject(elem->value);
278 elem->value = result;
282 if (elem->tree == NULL) {
283 elem->value = xmlXPathNewCString("");
286 * This is a result tree fragment.
288 xmlNodePtr container;
289 xmlNodePtr oldInsert, oldNode;
291 container = xmlNewDocNode(ctxt->output, NULL,
292 (const xmlChar *) "fake", NULL);
293 if (container == NULL)
296 oldInsert = ctxt->insert;
297 oldNode = ctxt->node;
298 ctxt->insert = container;
299 xsltApplyOneTemplate(ctxt, ctxt->node, elem->tree, 0);
300 ctxt->insert = oldInsert;
301 ctxt->node = oldNode;
303 if (elem->value != NULL)
304 xmlXPathFreeObject(elem->value);
305 elem->value = xmlXPathNewValueTree(container);
306 if (elem->value == NULL) {
307 elem->value = xmlXPathNewCString("");
309 #ifdef DEBUG_VARIABLE
310 #ifdef LIBXML_DEBUG_ENABLED
311 if ((xsltGenericDebugContext == stdout) ||
312 (xsltGenericDebugContext == stderr))
313 xmlXPathDebugDumpObject((FILE *)xsltGenericDebugContext,
324 * xsltEvalGlobalVariables:
325 * @ctxt: the XSLT transformation context
327 * Evaluate the global variables of a stylesheet. This need to be
328 * done on parsed stylesheets before starting to apply transformations
330 * Returns 0 in case of success, -1 in case of error
333 xsltEvalGlobalVariables(xsltTransformContextPtr ctxt) {
334 xsltStackElemPtr elem;
335 xsltStylesheetPtr style;
340 #ifdef DEBUG_VARIABLE
341 xsltGenericDebug(xsltGenericDebugContext,
342 "Evaluating global variables\n");
344 ctxt->node = (xmlNodePtr) ctxt->document->doc;
346 while (style != NULL) {
347 elem = style->variables;
349 while (elem != NULL) {
350 if (elem->computed == 0)
351 xsltEvalVariable(ctxt, elem);
355 style = xsltNextImport(style);
361 * xsltRegisterGlobalVariable:
362 * @style: the XSLT transformation context
363 * @name: the variable name
364 * @ns_uri: the variable namespace URI
365 * @select: the expression which need to be evaluated to generate a value
366 * @tree: the subtree if select is NULL
367 * @param: this is a parameter actually
368 * @value: the string value if available
370 * Register a new variable value. If @value is NULL it unregisters
373 * Returns 0 in case of success, -1 in case of error
376 xsltRegisterGlobalVariable(xsltStylesheetPtr style, const xmlChar *name,
377 const xmlChar *ns_uri, const xmlChar *select,
378 xmlNodePtr tree, int param, const xmlChar *value) {
379 xsltStackElemPtr elem;
385 #ifdef DEBUG_VARIABLE
387 xsltGenericDebug(xsltGenericDebugContext,
388 "Defineing global param %s\n", name);
390 xsltGenericDebug(xsltGenericDebugContext,
391 "Defineing global variable %s\n", name);
393 elem = xsltNewStackElem();
397 elem->type = XSLT_ELEM_PARAM;
399 elem->type = XSLT_ELEM_VARIABLE;
400 elem->name = xmlStrdup(name);
401 elem->select = xmlStrdup(select);
403 elem->nameURI = xmlStrdup(ns_uri);
405 elem->next = style->variables;
406 style->variables = elem;
409 elem->value = xmlXPathNewString(value);
415 * xsltEvalUserParams:
416 * @ctxt: the XSLT transformation context
417 * @params: a NULL terminated arry of parameters names/values tuples
419 * Evaluate the global variables of a stylesheet. This need to be
420 * done on parsed stylesheets before starting to apply transformations
422 * Returns 0 in case of success, -1 in case of error
425 xsltEvalUserParams(xsltTransformContextPtr ctxt, const char **params) {
426 xsltStylesheetPtr style;
429 const xmlChar *value;
430 xmlChar *ncname, *prefix;
438 while (params[indx] != NULL) {
439 name = (const xmlChar *)params[indx++];
440 value = (const xmlChar *)params[indx++];
441 if ((name == NULL) || (value == NULL))
444 #ifdef DEBUG_VARIABLE
445 xsltGenericDebug(xsltGenericDebugContext,
446 "Evaluating user parameter %s=%s\n", name, value);
448 ncname = xmlSplitQName2(name, &prefix);
449 if (ncname != NULL) {
450 if (prefix != NULL) {
453 ns = xmlSearchNs(style->doc, xmlDocGetRootElement(style->doc),
456 xsltGenericError(xsltGenericErrorContext,
457 "user param : no namespace bound to prefix %s\n", prefix);
459 xsltRegisterGlobalVariable(style, ncname, ns->href, NULL,
464 xsltRegisterGlobalVariable(style, ncname, NULL, NULL, NULL,
469 xsltRegisterGlobalVariable(style, name, NULL, NULL, NULL, 1, value);
479 * @ctxt: the XSLT transformation context
480 * @name: the variable name
481 * @ns_uri: the variable namespace URI
482 * @select: the expression which need to be evaluated to generate a value
483 * @tree: the tree if select is NULL
484 * @param: this is a parameter actually
486 * Computes a new variable value.
488 * Returns the xsltStackElemPtr or NULL in case of error
490 static xsltStackElemPtr
491 xsltBuildVariable(xsltTransformContextPtr ctxt, const xmlChar *name,
492 const xmlChar *ns_uri, const xmlChar *select,
493 xmlNodePtr tree, int param) {
494 xsltStackElemPtr elem;
500 #ifdef DEBUG_VARIABLE
501 xsltGenericDebug(xsltGenericDebugContext,
502 "Building variable %s", name);
504 xsltGenericDebug(xsltGenericDebugContext,
505 " select %s", select);
506 xsltGenericDebug(xsltGenericDebugContext, "\n");
508 elem = xsltNewStackElem();
512 elem->type = XSLT_ELEM_PARAM;
514 elem->type = XSLT_ELEM_VARIABLE;
515 elem->name = xmlStrdup(name);
517 elem->select = xmlStrdup(select);
521 elem->nameURI = xmlStrdup(ns_uri);
523 xsltEvalVariable(ctxt, elem);
528 * xsltRegisterVariable:
529 * @ctxt: the XSLT transformation context
530 * @name: the variable name
531 * @ns_uri: the variable namespace URI
532 * @select: the expression which need to be evaluated to generate a value
533 * @tree: the tree if select is NULL
534 * @param: this is a parameter actually
536 * Computes and register a new variable value.
538 * Returns 0 in case of success, -1 in case of error
541 xsltRegisterVariable(xsltTransformContextPtr ctxt, const xmlChar *name,
542 const xmlChar *ns_uri, const xmlChar *select,
543 xmlNodePtr tree, int param) {
544 xsltStackElemPtr elem;
550 if (xsltCheckStackElem(ctxt, name, ns_uri) != 0) {
552 xsltGenericError(xsltGenericErrorContext,
553 "xsl:variable : redefining %s\n", name);
555 #ifdef DEBUG_VARIABLE
557 xsltGenericDebug(xsltGenericDebugContext,
558 "param %s defined by caller", name);
562 elem = xsltBuildVariable(ctxt, name, ns_uri, select, tree, param);
563 xsltAddStackElem(ctxt, elem);
568 * xsltGlobalVariableLookup:
569 * @ctxt: the XSLT transformation context
570 * @name: the variable name
571 * @ns_uri: the variable namespace URI
573 * Search in the Variable array of the context for the given
576 * Returns the value or NULL if not found
578 static xmlXPathObjectPtr
579 xsltGlobalVariableLookup(xsltTransformContextPtr ctxt, const xmlChar *name,
580 const xmlChar *ns_uri) {
581 xsltStylesheetPtr style;
582 xsltStackElemPtr elem = NULL;
585 while (style != NULL) {
586 elem = style->variables;
588 while (elem != NULL) {
589 if (xmlStrEqual(elem->name, name)) {
590 if (ns_uri == NULL) {
591 if (elem->nameURI == NULL)
594 if ((elem->nameURI != NULL) &&
595 (xmlStrEqual(elem->nameURI, ns_uri)))
602 if (elem != NULL) break;
604 style = xsltNextImport(style);
609 if (!elem->computed) {
610 #ifdef DEBUG_VARIABLE
611 xsltGenericDebug(xsltGenericDebugContext,
612 "uncomputed global variable %s\n", name);
614 xsltEvalVariable(ctxt, elem);
616 if (elem->value != NULL)
617 return(xmlXPathObjectCopy(elem->value));
618 #ifdef DEBUG_VARIABLE
619 xsltGenericDebug(xsltGenericDebugContext,
620 "global variable not found %s\n", name);
626 * xsltVariableLookup:
627 * @ctxt: the XSLT transformation context
628 * @name: the variable name
629 * @ns_uri: the variable namespace URI
631 * Search in the Variable array of the context for the given
634 * Returns the value or NULL if not found
637 xsltVariableLookup(xsltTransformContextPtr ctxt, const xmlChar *name,
638 const xmlChar *ns_uri) {
639 xsltStackElemPtr elem;
644 elem = xsltStackLookup(ctxt, name, ns_uri);
646 return(xsltGlobalVariableLookup(ctxt, name, ns_uri));
648 if (!elem->computed) {
649 #ifdef DEBUG_VARIABLE
650 xsltGenericDebug(xsltGenericDebugContext,
651 "uncomputed variable %s\n", name);
653 xsltEvalVariable(ctxt, elem);
655 if (elem->value != NULL)
656 return(xmlXPathObjectCopy(elem->value));
657 #ifdef DEBUG_VARIABLE
658 xsltGenericDebug(xsltGenericDebugContext,
659 "variable not found %s\n", name);
665 * xsltParseStylesheetCallerParam:
666 * @ctxt: the XSLT transformation context
667 * @cur: the "param" element
669 * parse an XSLT transformation param declaration, compute
670 * its value but doesn't record it.
672 * It returns the new xsltStackElemPtr or NULL
676 xsltParseStylesheetCallerParam(xsltTransformContextPtr ctxt, xmlNodePtr cur) {
677 xmlChar *name, *ncname, *prefix;
679 xmlNodePtr tree = NULL;
680 xsltStackElemPtr elem = NULL;
682 if ((cur == NULL) || (ctxt == NULL))
685 name = xmlGetNsProp(cur, (const xmlChar *)"name", XSLT_NAMESPACE);
687 xsltGenericError(xsltGenericErrorContext,
688 "xsl:param : missing name attribute\n");
692 #ifdef DEBUG_VARIABLE
693 xsltGenericDebug(xsltGenericDebugContext,
694 "Parsing param %s\n", name);
697 select = xmlGetNsProp(cur, (const xmlChar *)"select", XSLT_NAMESPACE);
698 if (select == NULL) {
699 tree = cur->children;
701 #ifdef DEBUG_VARIABLE
702 xsltGenericDebug(xsltGenericDebugContext,
703 " select %s\n", select);
705 if (cur->children != NULL)
706 xsltGenericError(xsltGenericErrorContext,
707 "xsl:param : content shuld be empty since select is present \n");
710 ncname = xmlSplitQName2(name, &prefix);
712 if (ncname != NULL) {
713 if (prefix != NULL) {
716 ns = xmlSearchNs(cur->doc, cur, prefix);
718 xsltGenericError(xsltGenericErrorContext,
719 "xsl:param : no namespace bound to prefix %s\n", prefix);
721 elem = xsltBuildVariable(ctxt, ncname, ns->href, select,
726 elem = xsltBuildVariable(ctxt, ncname, NULL, select, tree, 1);
730 elem = xsltBuildVariable(ctxt, name, NULL, select, tree, 1);
740 * xsltParseStylesheetParam:
741 * @ctxt: the XSLT transformation context
742 * @cur: the "param" element
744 * parse an XSLT transformation param declaration and record
749 xsltParseStylesheetParam(xsltTransformContextPtr ctxt, xmlNodePtr cur) {
750 xmlChar *name, *ncname, *prefix;
752 xmlNodePtr tree = NULL;
754 if ((cur == NULL) || (ctxt == NULL))
757 name = xmlGetNsProp(cur, (const xmlChar *)"name", XSLT_NAMESPACE);
759 xsltGenericError(xsltGenericErrorContext,
760 "xsl:param : missing name attribute\n");
764 #ifdef DEBUG_VARIABLE
765 xsltGenericDebug(xsltGenericDebugContext,
766 "Parsing param %s\n", name);
769 select = xmlGetNsProp(cur, (const xmlChar *)"select", XSLT_NAMESPACE);
770 if (select == NULL) {
771 tree = cur->children;
773 #ifdef DEBUG_VARIABLE
774 xsltGenericDebug(xsltGenericDebugContext,
775 " select %s\n", select);
777 if (cur->children != NULL)
778 xsltGenericError(xsltGenericErrorContext,
779 "xsl:param : content shuld be empty since select is present \n");
782 ncname = xmlSplitQName2(name, &prefix);
784 if (ncname != NULL) {
785 if (prefix != NULL) {
788 ns = xmlSearchNs(cur->doc, cur, prefix);
790 xsltGenericError(xsltGenericErrorContext,
791 "xsl:param : no namespace bound to prefix %s\n", prefix);
793 xsltRegisterVariable(ctxt, ncname, ns->href, select, tree, 1);
797 xsltRegisterVariable(ctxt, ncname, NULL, select, tree, 1);
801 xsltRegisterVariable(ctxt, name, NULL, select, tree, 1);
811 * xsltParseGlobalVariable:
812 * @style: the XSLT stylesheet
813 * @cur: the "variable" element
815 * parse an XSLT transformation variable declaration and record
820 xsltParseGlobalVariable(xsltStylesheetPtr style, xmlNodePtr cur) {
821 xmlChar *name, *ncname, *prefix;
823 xmlNodePtr tree = NULL;
825 if ((cur == NULL) || (style == NULL))
828 name = xmlGetNsProp(cur, (const xmlChar *)"name", XSLT_NAMESPACE);
830 xsltGenericError(xsltGenericErrorContext,
831 "xsl:variable : missing name attribute\n");
835 #ifdef DEBUG_VARIABLE
836 xsltGenericDebug(xsltGenericDebugContext,
837 "Parsing global variable %s\n", name);
840 select = xmlGetNsProp(cur, (const xmlChar *)"select", XSLT_NAMESPACE);
841 if (select == NULL) {
842 tree = cur->children;
844 if (cur->children != NULL)
845 xsltGenericError(xsltGenericErrorContext,
846 "xsl:variable : content shuld be empty since select is present \n");
849 ncname = xmlSplitQName2(name, &prefix);
851 if (ncname != NULL) {
852 if (prefix != NULL) {
855 ns = xmlSearchNs(cur->doc, cur, prefix);
857 xsltGenericError(xsltGenericErrorContext,
858 "xsl:variable : no namespace bound to prefix %s\n", prefix);
860 xsltRegisterGlobalVariable(style, ncname, ns->href, select,
865 xsltRegisterGlobalVariable(style, ncname, NULL, select, tree,
870 xsltRegisterGlobalVariable(style, name, NULL, select, tree, 0, NULL);
880 * xsltParseGlobalParam:
881 * @style: the XSLT stylesheet
882 * @cur: the "param" element
884 * parse an XSLT transformation param declaration and record
889 xsltParseGlobalParam(xsltStylesheetPtr style, xmlNodePtr cur) {
890 xmlChar *name, *ncname, *prefix;
892 xmlNodePtr tree = NULL;
894 if ((cur == NULL) || (style == NULL))
897 name = xmlGetNsProp(cur, (const xmlChar *)"name", XSLT_NAMESPACE);
899 xsltGenericError(xsltGenericErrorContext,
900 "xsl:param : missing name attribute\n");
904 #ifdef DEBUG_VARIABLE
905 xsltGenericDebug(xsltGenericDebugContext,
906 "Parsing global param %s\n", name);
909 select = xmlGetNsProp(cur, (const xmlChar *)"select", XSLT_NAMESPACE);
910 if (select == NULL) {
911 tree = cur->children;
913 if (cur->children != NULL)
914 xsltGenericError(xsltGenericErrorContext,
915 "xsl:param : content shuld be empty since select is present \n");
918 ncname = xmlSplitQName2(name, &prefix);
920 if (ncname != NULL) {
921 if (prefix != NULL) {
924 ns = xmlSearchNs(cur->doc, cur, prefix);
926 xsltGenericError(xsltGenericErrorContext,
927 "xsl:param : no namespace bound to prefix %s\n", prefix);
929 xsltRegisterGlobalVariable(style, ncname, ns->href, select,
934 xsltRegisterGlobalVariable(style, ncname, NULL, select, tree,
939 xsltRegisterGlobalVariable(style, name, NULL, select, tree, 1, NULL);
948 * xsltParseStylesheetVariable:
949 * @ctxt: the XSLT transformation context
950 * @cur: the "variable" element
952 * parse an XSLT transformation variable declaration and record
957 xsltParseStylesheetVariable(xsltTransformContextPtr ctxt, xmlNodePtr cur) {
958 xmlChar *name, *ncname, *prefix;
960 xmlNodePtr tree = NULL;
962 if ((cur == NULL) || (ctxt == NULL))
965 name = xmlGetNsProp(cur, (const xmlChar *)"name", XSLT_NAMESPACE);
967 xsltGenericError(xsltGenericErrorContext,
968 "xsl:variable : missing name attribute\n");
972 #ifdef DEBUG_VARIABLE
973 xsltGenericDebug(xsltGenericDebugContext,
974 "Parsing variable %s\n", name);
977 select = xmlGetNsProp(cur, (const xmlChar *)"select", XSLT_NAMESPACE);
978 if (select == NULL) {
979 tree = cur->children;
981 if (cur->children != NULL)
982 xsltGenericError(xsltGenericErrorContext,
983 "xsl:variable : content should be empty since select is present \n");
986 ncname = xmlSplitQName2(name, &prefix);
988 if (ncname != NULL) {
989 if (prefix != NULL) {
992 ns = xmlSearchNs(cur->doc, cur, prefix);
994 xsltGenericError(xsltGenericErrorContext,
995 "xsl:variable : no namespace bound to prefix %s\n", prefix);
997 xsltRegisterVariable(ctxt, ncname, ns->href, select, tree, 0);
1001 xsltRegisterVariable(ctxt, ncname, NULL, select, tree, 0);
1005 xsltRegisterVariable(ctxt, name, NULL, select, tree, 0);
1015 * xsltVariableLookup:
1016 * @ctxt: a void * but the the XSLT transformation context actually
1017 * @name: the variable name
1018 * @ns_uri: the variable namespace URI
1020 * This is the entry point when a varibale is needed by the XPath
1023 * Returns the value or NULL if not found
1026 xsltXPathVariableLookup(void *ctxt, const xmlChar *name,
1027 const xmlChar *ns_uri) {
1028 xsltTransformContextPtr context;
1029 xmlXPathObjectPtr ret;
1031 if ((ctxt == NULL) || (name == NULL))
1034 #ifdef DEBUG_VARIABLE
1035 xsltGenericDebug(xsltGenericDebugContext,
1036 "Lookup variable %s\n", name);
1038 context = (xsltTransformContextPtr) ctxt;
1039 ret = xsltVariableLookup(context, name, ns_uri);
1041 xsltGenericError(xsltGenericErrorContext,
1042 "unregistered variable %s\n", name);
1044 #ifdef DEBUG_VARIABLE
1046 xsltGenericDebug(xsltGenericDebugContext,
1047 "found variable %s\n", name);