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 ctxt->state = XSLT_STATE_STOPPED;
341 #ifdef WITH_XSLT_DEBUG_VARIABLE
342 #ifdef LIBXML_DEBUG_ENABLED
344 if ((xsltGenericDebugContext == stdout) ||
345 (xsltGenericDebugContext == stderr))
346 xmlXPathDebugDumpObject((FILE *)xsltGenericDebugContext,
352 if (elem->tree == NULL) {
353 result = xmlXPathNewCString("");
356 * This is a result tree fragment.
358 xmlNodePtr container;
359 xmlNodePtr oldInsert;
361 container = xmlNewDocNode(ctxt->document->doc, NULL,
362 (const xmlChar *) "fake", NULL);
363 if (container == NULL)
366 oldInsert = ctxt->insert;
367 ctxt->insert = container;
368 xsltApplyOneTemplate(ctxt, ctxt->node, elem->tree, NULL, NULL);
369 ctxt->insert = oldInsert;
371 result = xmlXPathNewValueTree(container);
372 if (result == NULL) {
373 result = xmlXPathNewCString("");
376 * Tag the subtree for removal once consumed
380 #ifdef WITH_XSLT_DEBUG_VARIABLE
381 #ifdef LIBXML_DEBUG_ENABLED
382 if ((xsltGenericDebugContext == stdout) ||
383 (xsltGenericDebugContext == stderr))
384 xmlXPathDebugDumpObject((FILE *)xsltGenericDebugContext,
394 * xsltEvalGlobalVariable:
395 * @elem: the variable or parameter.
396 * @ctxt: the XSLT transformation context
398 * Evaluate a global variable value.
400 * Returns the XPath Object value or NULL in case of error
402 static xmlXPathObjectPtr
403 xsltEvalGlobalVariable(xsltStackElemPtr elem, xsltTransformContextPtr ctxt) {
404 xmlXPathObjectPtr result = NULL;
405 xsltStylePreCompPtr precomp;
406 int oldProximityPosition, oldContextSize;
409 xmlNsPtr *oldNamespaces;
411 if ((ctxt == NULL) || (elem == NULL))
417 #ifdef WITH_XSLT_DEBUG_VARIABLE
418 xsltGenericDebug(xsltGenericDebugContext,
419 "Evaluating global variable %s\n", elem->name);
422 precomp = elem->comp;
423 if (elem->select != NULL) {
424 xmlXPathCompExprPtr comp = NULL;
426 if ((precomp != NULL) && (precomp->comp != NULL)) {
427 comp = precomp->comp;
429 comp = xmlXPathCompile(elem->select);
433 oldProximityPosition = ctxt->xpathCtxt->proximityPosition;
434 oldContextSize = ctxt->xpathCtxt->contextSize;
435 oldInst = ctxt->inst;
436 oldNsNr = ctxt->xpathCtxt->nsNr;
437 oldNamespaces = ctxt->xpathCtxt->namespaces;
438 if (precomp != NULL) {
439 ctxt->inst = precomp->inst;
440 ctxt->xpathCtxt->namespaces = precomp->nsList;
441 ctxt->xpathCtxt->nsNr = precomp->nsNr;
444 ctxt->xpathCtxt->namespaces = NULL;
445 ctxt->xpathCtxt->nsNr = 0;
447 ctxt->xpathCtxt->node = (xmlNodePtr) ctxt->node;
448 result = xmlXPathCompiledEval(comp, ctxt->xpathCtxt);
449 ctxt->xpathCtxt->contextSize = oldContextSize;
450 ctxt->xpathCtxt->proximityPosition = oldProximityPosition;
451 ctxt->inst = oldInst;
452 ctxt->xpathCtxt->nsNr = oldNsNr;
453 ctxt->xpathCtxt->namespaces = oldNamespaces;
454 if ((precomp == NULL) || (precomp->comp == NULL))
455 xmlXPathFreeCompExpr(comp);
456 if (result == NULL) {
457 xsltPrintErrorContext(ctxt, NULL, precomp->inst);
458 xsltGenericError(xsltGenericErrorContext,
459 "Evaluating global variable %s failed\n", elem->name);
460 ctxt->state = XSLT_STATE_STOPPED;
461 #ifdef WITH_XSLT_DEBUG_VARIABLE
462 #ifdef LIBXML_DEBUG_ENABLED
464 if ((xsltGenericDebugContext == stdout) ||
465 (xsltGenericDebugContext == stderr))
466 xmlXPathDebugDumpObject((FILE *)xsltGenericDebugContext,
472 if (elem->tree == NULL) {
473 result = xmlXPathNewCString("");
476 * This is a result tree fragment.
478 xmlNodePtr container;
479 xmlNodePtr oldInsert;
481 container = xmlNewDocNode(ctxt->document->doc, NULL,
482 (const xmlChar *) "fake", NULL);
483 if (container == NULL)
486 oldInsert = ctxt->insert;
487 ctxt->insert = container;
488 xsltApplyOneTemplate(ctxt, ctxt->node, elem->tree, NULL, NULL);
489 ctxt->insert = oldInsert;
491 result = xmlXPathNewValueTree(container);
492 if (result == NULL) {
493 result = xmlXPathNewCString("");
496 * Tag the subtree for removal once consumed
500 #ifdef WITH_XSLT_DEBUG_VARIABLE
501 #ifdef LIBXML_DEBUG_ENABLED
502 if ((xsltGenericDebugContext == stdout) ||
503 (xsltGenericDebugContext == stderr))
504 xmlXPathDebugDumpObject((FILE *)xsltGenericDebugContext,
510 if (result != NULL) {
511 elem->value = result;
518 * xsltEvalGlobalVariables:
519 * @ctxt: the XSLT transformation context
521 * Evaluate the global variables of a stylesheet. This need to be
522 * done on parsed stylesheets before starting to apply transformations
524 * Returns 0 in case of success, -1 in case of error
527 xsltEvalGlobalVariables(xsltTransformContextPtr ctxt) {
528 xsltStackElemPtr elem;
529 xsltStylesheetPtr style;
534 #ifdef WITH_XSLT_DEBUG_VARIABLE
535 xsltGenericDebug(xsltGenericDebugContext,
536 "Registering global variables\n");
538 ctxt->node = (xmlNodePtr) ctxt->document->doc;
539 ctxt->xpathCtxt->contextSize = 1;
540 ctxt->xpathCtxt->proximityPosition = 1;
543 * Walk the list from the stylesheets and populate the hash table
546 while (style != NULL) {
547 elem = style->variables;
549 #ifdef WITH_XSLT_DEBUG_VARIABLE
550 if ((style->doc != NULL) && (style->doc->URL != NULL)) {
551 xsltGenericDebug(xsltGenericDebugContext,
552 "Registering global variables from %s\n",
557 while (elem != NULL) {
558 xsltStackElemPtr def;
561 * Global variables are stored in the variables pool.
563 def = (xsltStackElemPtr)
564 xmlHashLookup2(ctxt->globalVars,
565 elem->name, elem->nameURI);
569 def = xsltCopyStackElem(elem);
570 res = xmlHashAddEntry2(ctxt->globalVars,
571 elem->name, elem->nameURI, def);
572 } else if ((elem->comp != NULL) &&
573 (elem->comp->type == XSLT_FUNC_VARIABLE)) {
575 * Redefinition of variables from a different stylesheet
576 * should not generate a message.
578 if ((elem->comp->inst != NULL) &&
579 (def->comp != NULL) && (def->comp->inst != NULL) &&
580 (elem->comp->inst->doc == def->comp->inst->doc)) {
581 xsltPrintErrorContext(ctxt, style, elem->comp->inst);
582 xsltGenericError(xsltGenericErrorContext,
583 "Global variable %s already defined\n", elem->name);
589 style = xsltNextImport(style);
593 * This part does the actual evaluation
595 ctxt->node = (xmlNodePtr) ctxt->document->doc;
596 ctxt->xpathCtxt->contextSize = 1;
597 ctxt->xpathCtxt->proximityPosition = 1;
598 xmlHashScan(ctxt->globalVars,
599 (xmlHashScanner) xsltEvalGlobalVariable, ctxt);
605 * xsltRegisterGlobalVariable:
606 * @style: the XSLT transformation context
607 * @name: the variable name
608 * @ns_uri: the variable namespace URI
609 * @select: the expression which need to be evaluated to generate a value
610 * @tree: the subtree if select is NULL
611 * @comp: the precompiled value
612 * @value: the string value if available
614 * Register a new variable value. If @value is NULL it unregisters
617 * Returns 0 in case of success, -1 in case of error
620 xsltRegisterGlobalVariable(xsltStylesheetPtr style, const xmlChar *name,
621 const xmlChar *ns_uri, const xmlChar *select,
622 xmlNodePtr tree, xsltStylePreCompPtr comp,
623 const xmlChar *value) {
624 xsltStackElemPtr elem, tmp;
632 #ifdef WITH_XSLT_DEBUG_VARIABLE
633 if (comp->type == XSLT_FUNC_PARAM)
634 xsltGenericDebug(xsltGenericDebugContext,
635 "Defining global param %s\n", name);
637 xsltGenericDebug(xsltGenericDebugContext,
638 "Defining global variable %s\n", name);
641 elem = xsltNewStackElem();
645 elem->name = xmlStrdup(name);
646 elem->select = xmlStrdup(select);
648 elem->nameURI = xmlStrdup(ns_uri);
650 tmp = style->variables;
653 style->variables = elem;
655 while (tmp->next != NULL)
662 elem->value = xmlXPathNewString(value);
668 * xsltProcessUserParamInternal
670 * @ctxt: the XSLT transformation context
671 * @name: a null terminated parameter name
672 * @value: a null terminated value (may be an XPath expression)
673 * @eval: 0 to treat the value literally, else evaluate as XPath expression
675 * If @eval is 0 then @value is treated literally and is stored in the global
676 * parameter/variable table without any change.
678 * Uf @eval is 1 then @value is treated as an XPath expression and is
679 * evaluated. In this case, if you want to pass a string which will be
680 * interpreted literally then it must be enclosed in single or double quotes.
681 * If the string contains single quotes (double quotes) then it cannot be
682 * enclosed single quotes (double quotes). If the string which you want to
683 * be treated literally contains both single and double quotes (e.g. Meet
684 * at Joe's for "Twelfth Night" at 7 o'clock) then there is no suitable
685 * quoting character. You cannot use ' or " inside the string
686 * because the replacement of character entities with their equivalents is
687 * done at a different stage of processing. The solution is to call
688 * xsltQuoteUserParams or xsltQuoteOneUserParam.
690 * This needs to be done on parsed stylesheets before starting to apply
691 * transformations. Normally this will be called (directly or indirectly)
692 * only from xsltEvalUserParams, xsltEvalOneUserParam, xsltQuoteUserParams,
693 * or xsltQuoteOneUserParam.
695 * Returns 0 in case of success, -1 in case of error
700 xsltProcessUserParamInternal(xsltTransformContextPtr ctxt,
701 const xmlChar * name,
702 const xmlChar * value,
705 xsltStylesheetPtr style;
709 xmlXPathCompExprPtr comp;
710 xmlXPathObjectPtr result;
711 int oldProximityPosition;
714 xmlNsPtr *oldNamespaces;
715 xsltStackElemPtr elem;
727 #ifdef WITH_XSLT_DEBUG_VARIABLE
728 xsltGenericDebug(xsltGenericDebugContext,
729 "Evaluating user parameter %s=%s\n", name, value);
736 ncname = xmlSplitQName2(name, &prefix);
738 if (ncname != NULL) {
739 if (prefix != NULL) {
742 ns = xmlSearchNs(style->doc, xmlDocGetRootElement(style->doc),
745 xsltPrintErrorContext(ctxt, style, NULL);
746 xsltGenericError(xsltGenericErrorContext,
747 "user param : no namespace bound to prefix %s\n", prefix);
759 ncname = xmlStrdup(name);
763 * Do the evaluation if @eval is non-zero.
768 comp = xmlXPathCompile(value);
770 oldProximityPosition = ctxt->xpathCtxt->proximityPosition;
771 oldContextSize = ctxt->xpathCtxt->contextSize;
772 ctxt->xpathCtxt->node = (xmlNodePtr) ctxt->node;
775 * There is really no in scope namespace for parameters on the
779 oldNsNr = ctxt->xpathCtxt->nsNr;
780 oldNamespaces = ctxt->xpathCtxt->namespaces;
781 ctxt->xpathCtxt->namespaces = NULL;
782 ctxt->xpathCtxt->nsNr = 0;
783 result = xmlXPathCompiledEval(comp, ctxt->xpathCtxt);
784 ctxt->xpathCtxt->contextSize = oldContextSize;
785 ctxt->xpathCtxt->proximityPosition = oldProximityPosition;
786 ctxt->xpathCtxt->nsNr = oldNsNr;
787 ctxt->xpathCtxt->namespaces = oldNamespaces;
788 xmlXPathFreeCompExpr(comp);
790 if (result == NULL) {
791 xsltPrintErrorContext(ctxt, style, NULL);
792 xsltGenericError(xsltGenericErrorContext,
793 "Evaluating user parameter %s failed\n", name);
794 ctxt->state = XSLT_STATE_STOPPED;
801 * If @eval is 0 then @value is to be taken literally and result is NULL
803 * If @eval is not 0, then @value is an XPath expression and has been
804 * successfully evaluated and result contains the resulting value and
807 * Now create an xsltStackElemPtr for insertion into the context's
808 * global variable/parameter hash table.
811 #ifdef WITH_XSLT_DEBUG_VARIABLE
812 #ifdef LIBXML_DEBUG_ENABLED
813 if ((xsltGenericDebugContext == stdout) ||
814 (xsltGenericDebugContext == stderr))
815 xmlXPathDebugDumpObject((FILE *)xsltGenericDebugContext,
820 elem = xsltNewStackElem();
822 elem->name = xmlStrdup(ncname);
824 elem->select = xmlStrdup(value);
828 elem->nameURI = xmlStrdup(href);
832 elem->value = xmlXPathNewString(value);
835 elem->value = result;
840 * Global parameters are stored in the XPath context variables pool.
843 res = xmlHashAddEntry2(ctxt->globalVars, ncname, href, elem);
845 xsltFreeStackElem(elem);
846 xsltPrintErrorContext(ctxt, style, NULL);
847 xsltGenericError(xsltGenericErrorContext,
848 "Global parameter %s already defined\n", ncname);
855 * xsltEvalUserParams:
857 * @ctxt: the XSLT transformation context
858 * @params: a NULL terminated array of parameters name/value tuples
860 * Evaluate the global variables of a stylesheet. This needs to be
861 * done on parsed stylesheets before starting to apply transformations.
862 * Each of the parameters is evaluated as an XPath expression and stored
863 * in the global variables/parameter hash table. If you want your
864 * parameter used literally, use xsltQuoteUserParams.
866 * Returns 0 in case of success, -1 in case of error
870 xsltEvalUserParams(xsltTransformContextPtr ctxt, const char **params) {
873 const xmlChar *value;
877 while (params[indx] != NULL) {
878 name = (const xmlChar *) params[indx++];
879 value = (const xmlChar *) params[indx++];
880 if (xsltEvalOneUserParam(ctxt, name, value) != 0)
887 * xsltQuoteUserParams:
889 * @ctxt: the XSLT transformation context
890 * @params: a NULL terminated arry of parameters names/values tuples
892 * Similar to xsltEvalUserParams, but the values are treated literally and
893 * are * *not* evaluated as XPath expressions. This should be done on parsed
894 * stylesheets before starting to apply transformations.
896 * Returns 0 in case of success, -1 in case of error.
900 xsltQuoteUserParams(xsltTransformContextPtr ctxt, const char **params) {
903 const xmlChar *value;
907 while (params[indx] != NULL) {
908 name = (const xmlChar *) params[indx++];
909 value = (const xmlChar *) params[indx++];
910 if (xsltQuoteOneUserParam(ctxt, name, value) != 0)
917 * xsltEvalOneUserParam:
919 * @ctxt: the XSLT transformation context
920 * @name: a null terminated string giving the name of the parameter
921 * @value a null terminated string giving the XPath expression to be evaluated
923 * This is normally called from xsltEvalUserParams to process a single
924 * parameter from a list of parameters. The @value is evaluated as an
925 * XPath expression and the result is stored in the context's global
926 * variable/parameter hash table.
928 * To have a parameter treated literally (not as an XPath expression)
929 * use xsltQuoteUserParams (or xsltQuoteOneUserParam). For more
930 * details see description of xsltProcessOneUserParamInternal.
932 * Returns 0 in case of success, -1 in case of error.
936 xsltEvalOneUserParam(xsltTransformContextPtr ctxt,
937 const xmlChar * name,
938 const xmlChar * value) {
939 return xsltProcessUserParamInternal(ctxt, name, value,
940 1 /* xpath eval ? */);
944 * xsltQuoteOneUserParam:
946 * @ctxt: the XSLT transformation context
947 * @name: a null terminated string giving the name of the parameter
948 * @value a null terminated string giving the parameter value
950 * This is normally called from xsltQuoteUserParams to process a single
951 * parameter from a list of parameters. The @value is stored in the
952 * context's global variable/parameter hash table.
954 * Returns 0 in case of success, -1 in case of error.
958 xsltQuoteOneUserParam(xsltTransformContextPtr ctxt,
959 const xmlChar * name,
960 const xmlChar * value) {
961 return xsltProcessUserParamInternal(ctxt, name, value,
962 0 /* xpath eval ? */);
967 * @ctxt: the XSLT transformation context
968 * @comp: the precompiled form
969 * @tree: the tree if select is NULL
971 * Computes a new variable value.
973 * Returns the xsltStackElemPtr or NULL in case of error
975 static xsltStackElemPtr
976 xsltBuildVariable(xsltTransformContextPtr ctxt, xsltStylePreCompPtr comp,
978 xsltStackElemPtr elem;
980 #ifdef WITH_XSLT_DEBUG_VARIABLE
981 xsltGenericDebug(xsltGenericDebugContext,
982 "Building variable %s", comp->name);
983 if (comp->select != NULL)
984 xsltGenericDebug(xsltGenericDebugContext,
985 " select %s", comp->select);
986 xsltGenericDebug(xsltGenericDebugContext, "\n");
989 elem = xsltNewStackElem();
993 elem->name = xmlStrdup(comp->name);
994 if (comp->select != NULL)
995 elem->select = xmlStrdup(comp->select);
999 elem->nameURI = xmlStrdup(comp->ns);
1001 if (elem->computed == 0) {
1002 elem->value = xsltEvalVariable(ctxt, elem, comp);
1003 if (elem->value != NULL)
1010 * xsltRegisterVariable:
1011 * @ctxt: the XSLT transformation context
1012 * @comp: pointer to precompiled data
1013 * @tree: the tree if select is NULL
1014 * @param: this is a parameter actually
1016 * Computes and register a new variable value.
1018 * Returns 0 in case of success, -1 in case of error
1021 xsltRegisterVariable(xsltTransformContextPtr ctxt, xsltStylePreCompPtr comp,
1022 xmlNodePtr tree, int param) {
1023 xsltStackElemPtr elem;
1025 if (xsltCheckStackElem(ctxt, comp->name, comp->ns) != 0) {
1027 xsltPrintErrorContext(ctxt, NULL, comp->inst);
1028 xsltGenericError(xsltGenericErrorContext,
1029 "xsl:variable : redefining %s\n", comp->name);
1031 #ifdef WITH_XSLT_DEBUG_VARIABLE
1033 xsltGenericDebug(xsltGenericDebugContext,
1034 "param %s defined by caller\n", comp->name);
1038 elem = xsltBuildVariable(ctxt, comp, tree);
1039 xsltAddStackElem(ctxt, elem);
1044 * xsltGlobalVariableLookup:
1045 * @ctxt: the XSLT transformation context
1046 * @name: the variable name
1047 * @ns_uri: the variable namespace URI
1049 * Search in the Variable array of the context for the given
1052 * Returns the value or NULL if not found
1054 static xmlXPathObjectPtr
1055 xsltGlobalVariableLookup(xsltTransformContextPtr ctxt, const xmlChar *name,
1056 const xmlChar *ns_uri) {
1057 xsltStackElemPtr elem;
1058 xmlXPathObjectPtr ret = NULL;
1061 * Lookup the global variables in XPath global variable hash table
1063 if ((ctxt->xpathCtxt == NULL) || (ctxt->globalVars == NULL))
1065 elem = (xsltStackElemPtr)
1066 xmlHashLookup2(ctxt->globalVars, name, ns_uri);
1068 #ifdef WITH_XSLT_DEBUG_VARIABLE
1069 xsltGenericDebug(xsltGenericDebugContext,
1070 "global variable not found %s\n", name);
1074 if (elem->computed == 0)
1075 ret = xsltEvalGlobalVariable(elem, ctxt);
1078 return(xmlXPathObjectCopy(ret));
1082 * xsltVariableLookup:
1083 * @ctxt: the XSLT transformation context
1084 * @name: the variable name
1085 * @ns_uri: the variable namespace URI
1087 * Search in the Variable array of the context for the given
1090 * Returns the value or NULL if not found
1093 xsltVariableLookup(xsltTransformContextPtr ctxt, const xmlChar *name,
1094 const xmlChar *ns_uri) {
1095 xsltStackElemPtr elem;
1100 elem = xsltStackLookup(ctxt, name, ns_uri);
1102 return(xsltGlobalVariableLookup(ctxt, name, ns_uri));
1104 if (elem->computed == 0) {
1105 #ifdef WITH_XSLT_DEBUG_VARIABLE
1106 xsltGenericDebug(xsltGenericDebugContext,
1107 "uncomputed variable %s\n", name);
1109 elem->value = xsltEvalVariable(ctxt, elem, NULL);
1112 if (elem->value != NULL)
1113 return(xmlXPathObjectCopy(elem->value));
1114 #ifdef WITH_XSLT_DEBUG_VARIABLE
1115 xsltGenericDebug(xsltGenericDebugContext,
1116 "variable not found %s\n", name);
1122 * xsltParseStylesheetCallerParam:
1123 * @ctxt: the XSLT transformation context
1124 * @cur: the "param" element
1126 * parse an XSLT transformation param declaration, compute
1127 * its value but doesn't record it.
1129 * It returns the new xsltStackElemPtr or NULL
1133 xsltParseStylesheetCallerParam(xsltTransformContextPtr ctxt, xmlNodePtr cur) {
1134 xmlNodePtr tree = NULL;
1135 xsltStackElemPtr elem = NULL;
1136 xsltStylePreCompPtr comp;
1138 if ((cur == NULL) || (ctxt == NULL))
1140 comp = (xsltStylePreCompPtr) cur->_private;
1142 xsltPrintErrorContext(ctxt, NULL, cur);
1143 xsltGenericError(xsltGenericErrorContext,
1144 "xsl:param : compilation error\n");
1148 if (comp->name == NULL) {
1149 xsltPrintErrorContext(ctxt, NULL, cur);
1150 xsltGenericError(xsltGenericErrorContext,
1151 "xsl:param : missing name attribute\n");
1155 #ifdef WITH_XSLT_DEBUG_VARIABLE
1156 xsltGenericDebug(xsltGenericDebugContext,
1157 "Handling param %s\n", comp->name);
1160 if (comp->select == NULL) {
1161 tree = cur->children;
1163 #ifdef WITH_XSLT_DEBUG_VARIABLE
1164 xsltGenericDebug(xsltGenericDebugContext,
1165 " select %s\n", comp->select);
1170 elem = xsltBuildVariable(ctxt, comp, tree);
1176 * xsltParseGlobalVariable:
1177 * @style: the XSLT stylesheet
1178 * @cur: the "variable" element
1180 * parse an XSLT transformation variable declaration and record
1185 xsltParseGlobalVariable(xsltStylesheetPtr style, xmlNodePtr cur) {
1186 xsltStylePreCompPtr comp;
1188 if ((cur == NULL) || (style == NULL))
1191 xsltStylePreCompute(style, cur);
1192 comp = (xsltStylePreCompPtr) cur->_private;
1194 xsltPrintErrorContext(NULL, style, cur);
1195 xsltGenericError(xsltGenericErrorContext,
1196 "xsl:variable : compilation failed\n");
1200 if (comp->name == NULL) {
1201 xsltPrintErrorContext(NULL, style, cur);
1202 xsltGenericError(xsltGenericErrorContext,
1203 "xsl:variable : missing name attribute\n");
1207 #ifdef WITH_XSLT_DEBUG_VARIABLE
1208 xsltGenericDebug(xsltGenericDebugContext,
1209 "Registering global variable %s\n", comp->name);
1212 xsltRegisterGlobalVariable(style, comp->name, comp->ns, comp->select,
1213 cur->children, comp, NULL);
1217 * xsltParseGlobalParam:
1218 * @style: the XSLT stylesheet
1219 * @cur: the "param" element
1221 * parse an XSLT transformation param declaration and record
1226 xsltParseGlobalParam(xsltStylesheetPtr style, xmlNodePtr cur) {
1227 xsltStylePreCompPtr comp;
1229 if ((cur == NULL) || (style == NULL))
1232 xsltStylePreCompute(style, cur);
1233 comp = (xsltStylePreCompPtr) cur->_private;
1235 xsltPrintErrorContext(NULL, style, cur);
1236 xsltGenericError(xsltGenericErrorContext,
1237 "xsl:param : compilation failed\n");
1241 if (comp->name == NULL) {
1242 xsltPrintErrorContext(NULL, style, cur);
1243 xsltGenericError(xsltGenericErrorContext,
1244 "xsl:param : missing name attribute\n");
1248 #ifdef WITH_XSLT_DEBUG_VARIABLE
1249 xsltGenericDebug(xsltGenericDebugContext,
1250 "Registering global param %s\n", comp->name);
1253 xsltRegisterGlobalVariable(style, comp->name, comp->ns, comp->select,
1254 cur->children, comp, NULL);
1258 * xsltParseStylesheetVariable:
1259 * @ctxt: the XSLT transformation context
1260 * @cur: the "variable" element
1262 * parse an XSLT transformation variable declaration and record
1267 xsltParseStylesheetVariable(xsltTransformContextPtr ctxt, xmlNodePtr cur) {
1268 xsltStylePreCompPtr comp;
1270 if ((cur == NULL) || (ctxt == NULL))
1273 comp = (xsltStylePreCompPtr) cur->_private;
1275 xsltPrintErrorContext(ctxt, NULL, cur);
1276 xsltGenericError(xsltGenericErrorContext,
1277 "xsl:variable : compilation failed\n");
1281 if (comp->name == NULL) {
1282 xsltPrintErrorContext(ctxt, NULL, cur);
1283 xsltGenericError(xsltGenericErrorContext,
1284 "xsl:variable : missing name attribute\n");
1288 #ifdef WITH_XSLT_DEBUG_VARIABLE
1289 xsltGenericDebug(xsltGenericDebugContext,
1290 "Registering variable %s\n", comp->name);
1293 xsltRegisterVariable(ctxt, comp, cur->children, 0);
1297 * xsltParseStylesheetParam:
1298 * @ctxt: the XSLT transformation context
1299 * @cur: the "param" element
1301 * parse an XSLT transformation param declaration and record
1306 xsltParseStylesheetParam(xsltTransformContextPtr ctxt, xmlNodePtr cur) {
1307 xsltStylePreCompPtr comp;
1309 if ((cur == NULL) || (ctxt == NULL))
1312 comp = (xsltStylePreCompPtr) cur->_private;
1314 xsltPrintErrorContext(ctxt, NULL, cur);
1315 xsltGenericError(xsltGenericErrorContext,
1316 "xsl:param : compilation failed\n");
1320 if (comp->name == NULL) {
1321 xsltPrintErrorContext(ctxt, NULL, cur);
1322 xsltGenericError(xsltGenericErrorContext,
1323 "xsl:param : missing name attribute\n");
1327 #ifdef WITH_XSLT_DEBUG_VARIABLE
1328 xsltGenericDebug(xsltGenericDebugContext,
1329 "Registering param %s\n", comp->name);
1332 xsltRegisterVariable(ctxt, comp, cur->children, 1);
1336 * xsltFreeGlobalVariables:
1337 * @ctxt: the XSLT transformation context
1339 * Free up the data associated to the global variables
1344 xsltFreeGlobalVariables(xsltTransformContextPtr ctxt) {
1345 xmlHashFree(ctxt->globalVars, (xmlHashDeallocator) xsltFreeStackElem);
1349 * xsltXPathVariableLookup:
1350 * @ctxt: a void * but the the XSLT transformation context actually
1351 * @name: the variable name
1352 * @ns_uri: the variable namespace URI
1354 * This is the entry point when a varibale is needed by the XPath
1357 * Returns the value or NULL if not found
1360 xsltXPathVariableLookup(void *ctxt, const xmlChar *name,
1361 const xmlChar *ns_uri) {
1362 xsltTransformContextPtr context;
1363 xmlXPathObjectPtr ret;
1365 if ((ctxt == NULL) || (name == NULL))
1368 #ifdef WITH_XSLT_DEBUG_VARIABLE
1369 xsltGenericDebug(xsltGenericDebugContext,
1370 "Lookup variable %s\n", name);
1372 context = (xsltTransformContextPtr) ctxt;
1373 ret = xsltVariableLookup(context, name, ns_uri);
1375 xsltPrintErrorContext(ctxt, NULL, NULL);
1376 xsltGenericError(xsltGenericErrorContext,
1377 "unregistered variable %s\n", name);
1379 #ifdef WITH_XSLT_DEBUG_VARIABLE
1381 xsltGenericDebug(xsltGenericDebugContext,
1382 "found variable %s\n", name);