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 xsltPrintErrorContext(NULL, NULL, NULL);
57 xsltGenericError(xsltGenericErrorContext,
58 "xsltNewStackElem : malloc failed\n");
73 * @elem: an XSLT stack element
75 * Makes a copy of the stack element
77 * Returns the copy of NULL
79 static xsltStackElemPtr
80 xsltCopyStackElem(xsltStackElemPtr elem) {
83 cur = (xsltStackElemPtr) xmlMalloc(sizeof(xsltStackElem));
85 xsltPrintErrorContext(NULL, NULL, NULL);
86 xsltGenericError(xsltGenericErrorContext,
87 "xsltCopyStackElem : malloc failed\n");
90 cur->name = xmlStrdup(elem->name);
91 cur->nameURI = xmlStrdup(elem->nameURI);
92 cur->select = xmlStrdup(elem->select);
93 cur->tree = elem->tree;
94 cur->comp = elem->comp;
102 * @elem: an XSLT stack element
104 * Free up the memory allocated by @elem
107 xsltFreeStackElem(xsltStackElemPtr elem) {
110 if (elem->name != NULL)
112 if (elem->nameURI != NULL)
113 xmlFree(elem->nameURI);
114 if (elem->select != NULL)
115 xmlFree(elem->select);
116 if (elem->value != NULL)
117 xmlXPathFreeObject(elem->value);
123 * xsltFreeStackElemList:
124 * @elem: an XSLT stack element
126 * Free up the memory allocated by @elem
129 xsltFreeStackElemList(xsltStackElemPtr elem) {
130 xsltStackElemPtr next;
132 while(elem != NULL) {
134 xsltFreeStackElem(elem);
140 * xsltCheckStackElem:
141 * @ctxt: xn XSLT transformation context
142 * @name: the variable name
143 * @nameURI: the variable namespace URI
145 * check wether the variable or param is already defined
147 * Returns 1 if present, 0 if not, -1 in case of failure.
150 xsltCheckStackElem(xsltTransformContextPtr ctxt, const xmlChar *name,
151 const xmlChar *nameURI) {
152 xsltStackElemPtr cur;
154 if ((ctxt == NULL) || (name == NULL))
158 while (cur != NULL) {
159 if (xmlStrEqual(name, cur->name)) {
160 if (((nameURI == NULL) && (cur->nameURI == NULL)) ||
161 ((nameURI != NULL) && (cur->nameURI != NULL) &&
162 (xmlStrEqual(nameURI, cur->nameURI)))) {
173 * @ctxt: xn XSLT transformation context
174 * @elem: a stack element
176 * add a new element at this level of the stack.
178 * Returns 0 in case of success, -1 in case of failure.
181 xsltAddStackElem(xsltTransformContextPtr ctxt, xsltStackElemPtr elem) {
182 if ((ctxt == NULL) || (elem == NULL))
185 elem->next = ctxt->varsTab[ctxt->varsNr - 1];
186 ctxt->varsTab[ctxt->varsNr - 1] = elem;
192 * xsltAddStackElemList:
193 * @ctxt: xn XSLT transformation context
194 * @elems: a stack element list
196 * add the new element list at this level of the stack.
198 * Returns 0 in case of success, -1 in case of failure.
201 xsltAddStackElemList(xsltTransformContextPtr ctxt, xsltStackElemPtr elems) {
202 xsltStackElemPtr cur;
204 if ((ctxt == NULL) || (elems == NULL))
207 /* TODO: check doublons */
208 if (ctxt->varsTab[ctxt->varsNr - 1] != NULL) {
209 cur = ctxt->varsTab[ctxt->varsNr - 1];
210 while (cur->next != NULL)
214 elems->next = ctxt->varsTab[ctxt->varsNr - 1];
215 ctxt->varsTab[ctxt->varsNr - 1] = elems;
223 * @ctxt: an XSLT transformation context
224 * @name: the local part of the name
225 * @nameURI: the URI part of the name
227 * Locate an element in the stack based on its name.
229 static xsltStackElemPtr
230 xsltStackLookup(xsltTransformContextPtr ctxt, const xmlChar *name,
231 const xmlChar *nameURI) {
232 xsltStackElemPtr ret = NULL;
234 xsltStackElemPtr cur;
236 if ((ctxt == NULL) || (name == NULL) || (ctxt->varsNr == 0))
240 * Do the lookup from the top of the stack, but
241 * don't use params being computed in a call-param
245 for (i = ctxt->varsNr; i > ctxt->varsBase; i--) {
246 cur = ctxt->varsTab[i-1];
247 while (cur != NULL) {
248 if (xmlStrEqual(cur->name, name)) {
249 if (nameURI == NULL) {
250 if (cur->nameURI == NULL) {
254 if ((cur->nameURI != NULL) &&
255 (xmlStrEqual(cur->nameURI, nameURI))) {
267 /************************************************************************
269 * Module interfaces *
271 ************************************************************************/
275 * @ctxt: the XSLT transformation context
276 * @elem: the variable or parameter.
277 * @precomp: pointer to precompiled data
279 * Evaluate a variable value.
281 * Returns the XPath Object value or NULL in case of error
283 static xmlXPathObjectPtr
284 xsltEvalVariable(xsltTransformContextPtr ctxt, xsltStackElemPtr elem,
285 xsltStylePreCompPtr precomp) {
286 xmlXPathObjectPtr result = NULL;
287 int oldProximityPosition, oldContextSize;
288 xmlNodePtr oldInst, oldNode;
289 xsltDocumentPtr oldDoc;
291 xmlNsPtr *oldNamespaces;
293 if ((ctxt == NULL) || (elem == NULL))
296 #ifdef WITH_XSLT_DEBUG_VARIABLE
297 xsltGenericDebug(xsltGenericDebugContext,
298 "Evaluating variable %s\n", elem->name);
300 if (elem->select != NULL) {
301 xmlXPathCompExprPtr comp = NULL;
303 if ((precomp != NULL) && (precomp->comp != NULL)) {
304 comp = precomp->comp;
306 comp = xmlXPathCompile(elem->select);
310 oldProximityPosition = ctxt->xpathCtxt->proximityPosition;
311 oldContextSize = ctxt->xpathCtxt->contextSize;
312 ctxt->xpathCtxt->node = (xmlNodePtr) ctxt->node;
313 oldDoc = ctxt->document;
314 oldNode = ctxt->node;
315 oldInst = ctxt->inst;
316 oldNsNr = ctxt->xpathCtxt->nsNr;
317 oldNamespaces = ctxt->xpathCtxt->namespaces;
318 if (precomp != NULL) {
319 ctxt->inst = precomp->inst;
320 ctxt->xpathCtxt->namespaces = precomp->nsList;
321 ctxt->xpathCtxt->nsNr = precomp->nsNr;
324 ctxt->xpathCtxt->namespaces = NULL;
325 ctxt->xpathCtxt->nsNr = 0;
327 result = xmlXPathCompiledEval(comp, ctxt->xpathCtxt);
328 ctxt->xpathCtxt->contextSize = oldContextSize;
329 ctxt->xpathCtxt->proximityPosition = oldProximityPosition;
330 ctxt->xpathCtxt->nsNr = oldNsNr;
331 ctxt->xpathCtxt->namespaces = oldNamespaces;
332 ctxt->inst = oldInst;
333 ctxt->node = oldNode;
334 ctxt->document = oldDoc;
335 if ((precomp == NULL) || (precomp->comp == NULL))
336 xmlXPathFreeCompExpr(comp);
337 if (result == NULL) {
338 xsltPrintErrorContext(ctxt, NULL, precomp->inst);
339 xsltGenericError(xsltGenericErrorContext,
340 "Evaluating variable %s failed\n", elem->name);
341 ctxt->state = XSLT_STATE_STOPPED;
342 #ifdef WITH_XSLT_DEBUG_VARIABLE
343 #ifdef LIBXML_DEBUG_ENABLED
345 if ((xsltGenericDebugContext == stdout) ||
346 (xsltGenericDebugContext == stderr))
347 xmlXPathDebugDumpObject((FILE *)xsltGenericDebugContext,
353 if (elem->tree == NULL) {
354 result = xmlXPathNewCString("");
357 * This is a result tree fragment.
359 xmlNodePtr container;
360 xmlNodePtr oldInsert;
363 container = xmlNewDocNode(ctxt->document->doc, NULL,
364 (const xmlChar *) "fake node libxslt", NULL);
365 if (container == NULL)
367 container->parent = NULL;
369 oldoutput = ctxt->output;
371 oldInsert = ctxt->insert;
372 ctxt->insert = container;
373 xsltApplyOneTemplate(ctxt, ctxt->node, elem->tree, NULL, NULL);
374 ctxt->insert = oldInsert;
375 ctxt->output = oldoutput;
377 result = xmlXPathNewValueTree(container);
378 if (result == NULL) {
379 result = xmlXPathNewCString("");
382 * Tag the subtree for removal once consumed
386 #ifdef WITH_XSLT_DEBUG_VARIABLE
387 #ifdef LIBXML_DEBUG_ENABLED
388 if ((xsltGenericDebugContext == stdout) ||
389 (xsltGenericDebugContext == stderr))
390 xmlXPathDebugDumpObject((FILE *)xsltGenericDebugContext,
400 * xsltEvalGlobalVariable:
401 * @elem: the variable or parameter.
402 * @ctxt: the XSLT transformation context
404 * Evaluate a global variable value.
406 * Returns the XPath Object value or NULL in case of error
408 static xmlXPathObjectPtr
409 xsltEvalGlobalVariable(xsltStackElemPtr elem, xsltTransformContextPtr ctxt) {
410 xmlXPathObjectPtr result = NULL;
411 xsltStylePreCompPtr precomp;
412 int oldProximityPosition, oldContextSize;
415 xmlNsPtr *oldNamespaces;
417 if ((ctxt == NULL) || (elem == NULL))
423 #ifdef WITH_XSLT_DEBUG_VARIABLE
424 xsltGenericDebug(xsltGenericDebugContext,
425 "Evaluating global variable %s\n", elem->name);
429 if ((xslDebugStatus != XSLT_DEBUG_NONE) &&
430 elem->comp && elem->comp->inst)
431 xslHandleDebugger(elem->comp->inst, NULL, NULL, ctxt);
434 precomp = elem->comp;
435 if (elem->select != NULL) {
436 xmlXPathCompExprPtr comp = NULL;
438 if ((precomp != NULL) && (precomp->comp != NULL)) {
439 comp = precomp->comp;
441 comp = xmlXPathCompile(elem->select);
445 oldProximityPosition = ctxt->xpathCtxt->proximityPosition;
446 oldContextSize = ctxt->xpathCtxt->contextSize;
447 oldInst = ctxt->inst;
448 oldNsNr = ctxt->xpathCtxt->nsNr;
449 oldNamespaces = ctxt->xpathCtxt->namespaces;
450 if (precomp != NULL) {
451 ctxt->inst = precomp->inst;
452 ctxt->xpathCtxt->namespaces = precomp->nsList;
453 ctxt->xpathCtxt->nsNr = precomp->nsNr;
456 ctxt->xpathCtxt->namespaces = NULL;
457 ctxt->xpathCtxt->nsNr = 0;
459 ctxt->xpathCtxt->node = (xmlNodePtr) ctxt->node;
460 result = xmlXPathCompiledEval(comp, ctxt->xpathCtxt);
461 ctxt->xpathCtxt->contextSize = oldContextSize;
462 ctxt->xpathCtxt->proximityPosition = oldProximityPosition;
463 ctxt->inst = oldInst;
464 ctxt->xpathCtxt->nsNr = oldNsNr;
465 ctxt->xpathCtxt->namespaces = oldNamespaces;
466 if ((precomp == NULL) || (precomp->comp == NULL))
467 xmlXPathFreeCompExpr(comp);
468 if (result == NULL) {
469 xsltPrintErrorContext(ctxt, NULL, precomp->inst);
470 xsltGenericError(xsltGenericErrorContext,
471 "Evaluating global variable %s failed\n", elem->name);
472 ctxt->state = XSLT_STATE_STOPPED;
473 #ifdef WITH_XSLT_DEBUG_VARIABLE
474 #ifdef LIBXML_DEBUG_ENABLED
476 if ((xsltGenericDebugContext == stdout) ||
477 (xsltGenericDebugContext == stderr))
478 xmlXPathDebugDumpObject((FILE *)xsltGenericDebugContext,
484 if (elem->tree == NULL) {
485 result = xmlXPathNewCString("");
488 * This is a result tree fragment.
490 xmlNodePtr container;
491 xmlNodePtr oldInsert;
494 container = xmlNewDocNode(ctxt->document->doc, NULL,
495 (const xmlChar *) "fake node libxslt", NULL);
496 if (container == NULL)
498 container->parent = NULL;
500 oldoutput = ctxt->output;
502 oldInsert = ctxt->insert;
503 ctxt->insert = container;
504 xsltApplyOneTemplate(ctxt, ctxt->node, elem->tree, NULL, NULL);
505 ctxt->insert = oldInsert;
506 ctxt->output = oldoutput;
508 result = xmlXPathNewValueTree(container);
509 if (result == NULL) {
510 result = xmlXPathNewCString("");
513 * Tag the subtree for removal once consumed
517 #ifdef WITH_XSLT_DEBUG_VARIABLE
518 #ifdef LIBXML_DEBUG_ENABLED
519 if ((xsltGenericDebugContext == stdout) ||
520 (xsltGenericDebugContext == stderr))
521 xmlXPathDebugDumpObject((FILE *)xsltGenericDebugContext,
527 if (result != NULL) {
528 elem->value = result;
535 * xsltEvalGlobalVariables:
536 * @ctxt: the XSLT transformation context
538 * Evaluate the global variables of a stylesheet. This need to be
539 * done on parsed stylesheets before starting to apply transformations
541 * Returns 0 in case of success, -1 in case of error
544 xsltEvalGlobalVariables(xsltTransformContextPtr ctxt) {
545 xsltStackElemPtr elem;
546 xsltStylesheetPtr style;
551 #ifdef WITH_XSLT_DEBUG_VARIABLE
552 xsltGenericDebug(xsltGenericDebugContext,
553 "Registering global variables\n");
555 ctxt->node = (xmlNodePtr) ctxt->document->doc;
556 ctxt->xpathCtxt->contextSize = 1;
557 ctxt->xpathCtxt->proximityPosition = 1;
560 * Walk the list from the stylesheets and populate the hash table
563 while (style != NULL) {
564 elem = style->variables;
566 #ifdef WITH_XSLT_DEBUG_VARIABLE
567 if ((style->doc != NULL) && (style->doc->URL != NULL)) {
568 xsltGenericDebug(xsltGenericDebugContext,
569 "Registering global variables from %s\n",
574 while (elem != NULL) {
575 xsltStackElemPtr def;
578 * Global variables are stored in the variables pool.
580 def = (xsltStackElemPtr)
581 xmlHashLookup2(ctxt->globalVars,
582 elem->name, elem->nameURI);
586 def = xsltCopyStackElem(elem);
587 res = xmlHashAddEntry2(ctxt->globalVars,
588 elem->name, elem->nameURI, def);
589 } else if ((elem->comp != NULL) &&
590 (elem->comp->type == XSLT_FUNC_VARIABLE)) {
592 * Redefinition of variables from a different stylesheet
593 * should not generate a message.
595 if ((elem->comp->inst != NULL) &&
596 (def->comp != NULL) && (def->comp->inst != NULL) &&
597 (elem->comp->inst->doc == def->comp->inst->doc)) {
598 xsltPrintErrorContext(ctxt, style, elem->comp->inst);
599 xsltGenericError(xsltGenericErrorContext,
600 "Global variable %s already defined\n", elem->name);
606 style = xsltNextImport(style);
610 * This part does the actual evaluation
612 ctxt->node = (xmlNodePtr) ctxt->document->doc;
613 ctxt->xpathCtxt->contextSize = 1;
614 ctxt->xpathCtxt->proximityPosition = 1;
615 xmlHashScan(ctxt->globalVars,
616 (xmlHashScanner) xsltEvalGlobalVariable, ctxt);
622 * xsltRegisterGlobalVariable:
623 * @style: the XSLT transformation context
624 * @name: the variable name
625 * @ns_uri: the variable namespace URI
626 * @select: the expression which need to be evaluated to generate a value
627 * @tree: the subtree if select is NULL
628 * @comp: the precompiled value
629 * @value: the string value if available
631 * Register a new variable value. If @value is NULL it unregisters
634 * Returns 0 in case of success, -1 in case of error
637 xsltRegisterGlobalVariable(xsltStylesheetPtr style, const xmlChar *name,
638 const xmlChar *ns_uri, const xmlChar *select,
639 xmlNodePtr tree, xsltStylePreCompPtr comp,
640 const xmlChar *value) {
641 xsltStackElemPtr elem, tmp;
649 #ifdef WITH_XSLT_DEBUG_VARIABLE
650 if (comp->type == XSLT_FUNC_PARAM)
651 xsltGenericDebug(xsltGenericDebugContext,
652 "Defining global param %s\n", name);
654 xsltGenericDebug(xsltGenericDebugContext,
655 "Defining global variable %s\n", name);
658 elem = xsltNewStackElem();
662 elem->name = xmlStrdup(name);
663 elem->select = xmlStrdup(select);
665 elem->nameURI = xmlStrdup(ns_uri);
667 tmp = style->variables;
670 style->variables = elem;
672 while (tmp->next != NULL)
679 elem->value = xmlXPathNewString(value);
685 * xsltProcessUserParamInternal
687 * @ctxt: the XSLT transformation context
688 * @name: a null terminated parameter name
689 * @value: a null terminated value (may be an XPath expression)
690 * @eval: 0 to treat the value literally, else evaluate as XPath expression
692 * If @eval is 0 then @value is treated literally and is stored in the global
693 * parameter/variable table without any change.
695 * Uf @eval is 1 then @value is treated as an XPath expression and is
696 * evaluated. In this case, if you want to pass a string which will be
697 * interpreted literally then it must be enclosed in single or double quotes.
698 * If the string contains single quotes (double quotes) then it cannot be
699 * enclosed single quotes (double quotes). If the string which you want to
700 * be treated literally contains both single and double quotes (e.g. Meet
701 * at Joe's for "Twelfth Night" at 7 o'clock) then there is no suitable
702 * quoting character. You cannot use ' or " inside the string
703 * because the replacement of character entities with their equivalents is
704 * done at a different stage of processing. The solution is to call
705 * xsltQuoteUserParams or xsltQuoteOneUserParam.
707 * This needs to be done on parsed stylesheets before starting to apply
708 * transformations. Normally this will be called (directly or indirectly)
709 * only from xsltEvalUserParams, xsltEvalOneUserParam, xsltQuoteUserParams,
710 * or xsltQuoteOneUserParam.
712 * Returns 0 in case of success, -1 in case of error
717 xsltProcessUserParamInternal(xsltTransformContextPtr ctxt,
718 const xmlChar * name,
719 const xmlChar * value,
722 xsltStylesheetPtr style;
726 xmlXPathCompExprPtr comp;
727 xmlXPathObjectPtr result;
728 int oldProximityPosition;
731 xmlNsPtr *oldNamespaces;
732 xsltStackElemPtr elem;
744 #ifdef WITH_XSLT_DEBUG_VARIABLE
745 xsltGenericDebug(xsltGenericDebugContext,
746 "Evaluating user parameter %s=%s\n", name, value);
753 ncname = xmlSplitQName2(name, &prefix);
755 if (ncname != NULL) {
756 if (prefix != NULL) {
759 ns = xmlSearchNs(style->doc, xmlDocGetRootElement(style->doc),
762 xsltPrintErrorContext(ctxt, style, NULL);
763 xsltGenericError(xsltGenericErrorContext,
764 "user param : no namespace bound to prefix %s\n", prefix);
776 ncname = xmlStrdup(name);
780 * Do the evaluation if @eval is non-zero.
785 comp = xmlXPathCompile(value);
787 oldProximityPosition = ctxt->xpathCtxt->proximityPosition;
788 oldContextSize = ctxt->xpathCtxt->contextSize;
789 ctxt->xpathCtxt->node = (xmlNodePtr) ctxt->node;
792 * There is really no in scope namespace for parameters on the
796 oldNsNr = ctxt->xpathCtxt->nsNr;
797 oldNamespaces = ctxt->xpathCtxt->namespaces;
798 ctxt->xpathCtxt->namespaces = NULL;
799 ctxt->xpathCtxt->nsNr = 0;
800 result = xmlXPathCompiledEval(comp, ctxt->xpathCtxt);
801 ctxt->xpathCtxt->contextSize = oldContextSize;
802 ctxt->xpathCtxt->proximityPosition = oldProximityPosition;
803 ctxt->xpathCtxt->nsNr = oldNsNr;
804 ctxt->xpathCtxt->namespaces = oldNamespaces;
805 xmlXPathFreeCompExpr(comp);
807 if (result == NULL) {
808 xsltPrintErrorContext(ctxt, style, NULL);
809 xsltGenericError(xsltGenericErrorContext,
810 "Evaluating user parameter %s failed\n", name);
811 ctxt->state = XSLT_STATE_STOPPED;
818 * If @eval is 0 then @value is to be taken literally and result is NULL
820 * If @eval is not 0, then @value is an XPath expression and has been
821 * successfully evaluated and result contains the resulting value and
824 * Now create an xsltStackElemPtr for insertion into the context's
825 * global variable/parameter hash table.
828 #ifdef WITH_XSLT_DEBUG_VARIABLE
829 #ifdef LIBXML_DEBUG_ENABLED
830 if ((xsltGenericDebugContext == stdout) ||
831 (xsltGenericDebugContext == stderr))
832 xmlXPathDebugDumpObject((FILE *)xsltGenericDebugContext,
837 elem = xsltNewStackElem();
839 elem->name = xmlStrdup(ncname);
841 elem->select = xmlStrdup(value);
845 elem->nameURI = xmlStrdup(href);
849 elem->value = xmlXPathNewString(value);
852 elem->value = result;
857 * Global parameters are stored in the XPath context variables pool.
860 res = xmlHashAddEntry2(ctxt->globalVars, ncname, href, elem);
862 xsltFreeStackElem(elem);
863 xsltPrintErrorContext(ctxt, style, NULL);
864 xsltGenericError(xsltGenericErrorContext,
865 "Global parameter %s already defined\n", ncname);
872 * xsltEvalUserParams:
874 * @ctxt: the XSLT transformation context
875 * @params: a NULL terminated array of parameters name/value tuples
877 * Evaluate the global variables of a stylesheet. This needs to be
878 * done on parsed stylesheets before starting to apply transformations.
879 * Each of the parameters is evaluated as an XPath expression and stored
880 * in the global variables/parameter hash table. If you want your
881 * parameter used literally, use xsltQuoteUserParams.
883 * Returns 0 in case of success, -1 in case of error
887 xsltEvalUserParams(xsltTransformContextPtr ctxt, const char **params) {
890 const xmlChar *value;
894 while (params[indx] != NULL) {
895 name = (const xmlChar *) params[indx++];
896 value = (const xmlChar *) params[indx++];
897 if (xsltEvalOneUserParam(ctxt, name, value) != 0)
904 * xsltQuoteUserParams:
906 * @ctxt: the XSLT transformation context
907 * @params: a NULL terminated arry of parameters names/values tuples
909 * Similar to xsltEvalUserParams, but the values are treated literally and
910 * are * *not* evaluated as XPath expressions. This should be done on parsed
911 * stylesheets before starting to apply transformations.
913 * Returns 0 in case of success, -1 in case of error.
917 xsltQuoteUserParams(xsltTransformContextPtr ctxt, const char **params) {
920 const xmlChar *value;
924 while (params[indx] != NULL) {
925 name = (const xmlChar *) params[indx++];
926 value = (const xmlChar *) params[indx++];
927 if (xsltQuoteOneUserParam(ctxt, name, value) != 0)
934 * xsltEvalOneUserParam:
936 * @ctxt: the XSLT transformation context
937 * @name: a null terminated string giving the name of the parameter
938 * @value a null terminated string giving the XPath expression to be evaluated
940 * This is normally called from xsltEvalUserParams to process a single
941 * parameter from a list of parameters. The @value is evaluated as an
942 * XPath expression and the result is stored in the context's global
943 * variable/parameter hash table.
945 * To have a parameter treated literally (not as an XPath expression)
946 * use xsltQuoteUserParams (or xsltQuoteOneUserParam). For more
947 * details see description of xsltProcessOneUserParamInternal.
949 * Returns 0 in case of success, -1 in case of error.
953 xsltEvalOneUserParam(xsltTransformContextPtr ctxt,
954 const xmlChar * name,
955 const xmlChar * value) {
956 return xsltProcessUserParamInternal(ctxt, name, value,
957 1 /* xpath eval ? */);
961 * xsltQuoteOneUserParam:
963 * @ctxt: the XSLT transformation context
964 * @name: a null terminated string giving the name of the parameter
965 * @value a null terminated string giving the parameter value
967 * This is normally called from xsltQuoteUserParams to process a single
968 * parameter from a list of parameters. The @value is stored in the
969 * context's global variable/parameter hash table.
971 * Returns 0 in case of success, -1 in case of error.
975 xsltQuoteOneUserParam(xsltTransformContextPtr ctxt,
976 const xmlChar * name,
977 const xmlChar * value) {
978 return xsltProcessUserParamInternal(ctxt, name, value,
979 0 /* xpath eval ? */);
984 * @ctxt: the XSLT transformation context
985 * @comp: the precompiled form
986 * @tree: the tree if select is NULL
988 * Computes a new variable value.
990 * Returns the xsltStackElemPtr or NULL in case of error
992 static xsltStackElemPtr
993 xsltBuildVariable(xsltTransformContextPtr ctxt, xsltStylePreCompPtr comp,
995 xsltStackElemPtr elem;
997 #ifdef WITH_XSLT_DEBUG_VARIABLE
998 xsltGenericDebug(xsltGenericDebugContext,
999 "Building variable %s", comp->name);
1000 if (comp->select != NULL)
1001 xsltGenericDebug(xsltGenericDebugContext,
1002 " select %s", comp->select);
1003 xsltGenericDebug(xsltGenericDebugContext, "\n");
1006 elem = xsltNewStackElem();
1010 elem->name = xmlStrdup(comp->name);
1011 if (comp->select != NULL)
1012 elem->select = xmlStrdup(comp->select);
1014 elem->select = NULL;
1016 elem->nameURI = xmlStrdup(comp->ns);
1018 if (elem->computed == 0) {
1019 elem->value = xsltEvalVariable(ctxt, elem, comp);
1020 if (elem->value != NULL)
1027 * xsltRegisterVariable:
1028 * @ctxt: the XSLT transformation context
1029 * @comp: pointer to precompiled data
1030 * @tree: the tree if select is NULL
1031 * @param: this is a parameter actually
1033 * Computes and register a new variable value.
1035 * Returns 0 in case of success, -1 in case of error
1038 xsltRegisterVariable(xsltTransformContextPtr ctxt, xsltStylePreCompPtr comp,
1039 xmlNodePtr tree, int param) {
1040 xsltStackElemPtr elem;
1042 if (xsltCheckStackElem(ctxt, comp->name, comp->ns) != 0) {
1044 xsltPrintErrorContext(ctxt, NULL, comp->inst);
1045 xsltGenericError(xsltGenericErrorContext,
1046 "xsl:variable : redefining %s\n", comp->name);
1048 #ifdef WITH_XSLT_DEBUG_VARIABLE
1050 xsltGenericDebug(xsltGenericDebugContext,
1051 "param %s defined by caller\n", comp->name);
1055 elem = xsltBuildVariable(ctxt, comp, tree);
1056 xsltAddStackElem(ctxt, elem);
1061 * xsltGlobalVariableLookup:
1062 * @ctxt: the XSLT transformation context
1063 * @name: the variable name
1064 * @ns_uri: the variable namespace URI
1066 * Search in the Variable array of the context for the given
1069 * Returns the value or NULL if not found
1071 static xmlXPathObjectPtr
1072 xsltGlobalVariableLookup(xsltTransformContextPtr ctxt, const xmlChar *name,
1073 const xmlChar *ns_uri) {
1074 xsltStackElemPtr elem;
1075 xmlXPathObjectPtr ret = NULL;
1078 * Lookup the global variables in XPath global variable hash table
1080 if ((ctxt->xpathCtxt == NULL) || (ctxt->globalVars == NULL))
1082 elem = (xsltStackElemPtr)
1083 xmlHashLookup2(ctxt->globalVars, name, ns_uri);
1085 #ifdef WITH_XSLT_DEBUG_VARIABLE
1086 xsltGenericDebug(xsltGenericDebugContext,
1087 "global variable not found %s\n", name);
1091 if (elem->computed == 0)
1092 ret = xsltEvalGlobalVariable(elem, ctxt);
1095 return(xmlXPathObjectCopy(ret));
1099 * xsltVariableLookup:
1100 * @ctxt: the XSLT transformation context
1101 * @name: the variable name
1102 * @ns_uri: the variable namespace URI
1104 * Search in the Variable array of the context for the given
1107 * Returns the value or NULL if not found
1110 xsltVariableLookup(xsltTransformContextPtr ctxt, const xmlChar *name,
1111 const xmlChar *ns_uri) {
1112 xsltStackElemPtr elem;
1117 elem = xsltStackLookup(ctxt, name, ns_uri);
1119 return(xsltGlobalVariableLookup(ctxt, name, ns_uri));
1121 if (elem->computed == 0) {
1122 #ifdef WITH_XSLT_DEBUG_VARIABLE
1123 xsltGenericDebug(xsltGenericDebugContext,
1124 "uncomputed variable %s\n", name);
1126 elem->value = xsltEvalVariable(ctxt, elem, NULL);
1129 if (elem->value != NULL)
1130 return(xmlXPathObjectCopy(elem->value));
1131 #ifdef WITH_XSLT_DEBUG_VARIABLE
1132 xsltGenericDebug(xsltGenericDebugContext,
1133 "variable not found %s\n", name);
1139 * xsltParseStylesheetCallerParam:
1140 * @ctxt: the XSLT transformation context
1141 * @cur: the "param" element
1143 * parse an XSLT transformation param declaration, compute
1144 * its value but doesn't record it.
1146 * It returns the new xsltStackElemPtr or NULL
1150 xsltParseStylesheetCallerParam(xsltTransformContextPtr ctxt, xmlNodePtr cur) {
1151 xmlNodePtr tree = NULL;
1152 xsltStackElemPtr elem = NULL;
1153 xsltStylePreCompPtr comp;
1155 if ((cur == NULL) || (ctxt == NULL))
1157 comp = (xsltStylePreCompPtr) cur->_private;
1159 xsltPrintErrorContext(ctxt, NULL, cur);
1160 xsltGenericError(xsltGenericErrorContext,
1161 "xsl:param : compilation error\n");
1165 if (comp->name == NULL) {
1166 xsltPrintErrorContext(ctxt, NULL, cur);
1167 xsltGenericError(xsltGenericErrorContext,
1168 "xsl:param : missing name attribute\n");
1172 #ifdef WITH_XSLT_DEBUG_VARIABLE
1173 xsltGenericDebug(xsltGenericDebugContext,
1174 "Handling param %s\n", comp->name);
1177 if (comp->select == NULL) {
1178 tree = cur->children;
1180 #ifdef WITH_XSLT_DEBUG_VARIABLE
1181 xsltGenericDebug(xsltGenericDebugContext,
1182 " select %s\n", comp->select);
1187 elem = xsltBuildVariable(ctxt, comp, tree);
1193 * xsltParseGlobalVariable:
1194 * @style: the XSLT stylesheet
1195 * @cur: the "variable" element
1197 * parse an XSLT transformation variable declaration and record
1202 xsltParseGlobalVariable(xsltStylesheetPtr style, xmlNodePtr cur) {
1203 xsltStylePreCompPtr comp;
1205 if ((cur == NULL) || (style == NULL))
1208 xsltStylePreCompute(style, cur);
1209 comp = (xsltStylePreCompPtr) cur->_private;
1211 xsltPrintErrorContext(NULL, style, cur);
1212 xsltGenericError(xsltGenericErrorContext,
1213 "xsl:variable : compilation failed\n");
1217 if (comp->name == NULL) {
1218 xsltPrintErrorContext(NULL, style, cur);
1219 xsltGenericError(xsltGenericErrorContext,
1220 "xsl:variable : missing name attribute\n");
1224 #ifdef WITH_XSLT_DEBUG_VARIABLE
1225 xsltGenericDebug(xsltGenericDebugContext,
1226 "Registering global variable %s\n", comp->name);
1229 xsltRegisterGlobalVariable(style, comp->name, comp->ns, comp->select,
1230 cur->children, comp, NULL);
1234 * xsltParseGlobalParam:
1235 * @style: the XSLT stylesheet
1236 * @cur: the "param" element
1238 * parse an XSLT transformation param declaration and record
1243 xsltParseGlobalParam(xsltStylesheetPtr style, xmlNodePtr cur) {
1244 xsltStylePreCompPtr comp;
1246 if ((cur == NULL) || (style == NULL))
1249 xsltStylePreCompute(style, cur);
1250 comp = (xsltStylePreCompPtr) cur->_private;
1252 xsltPrintErrorContext(NULL, style, cur);
1253 xsltGenericError(xsltGenericErrorContext,
1254 "xsl:param : compilation failed\n");
1258 if (comp->name == NULL) {
1259 xsltPrintErrorContext(NULL, style, cur);
1260 xsltGenericError(xsltGenericErrorContext,
1261 "xsl:param : missing name attribute\n");
1265 #ifdef WITH_XSLT_DEBUG_VARIABLE
1266 xsltGenericDebug(xsltGenericDebugContext,
1267 "Registering global param %s\n", comp->name);
1270 xsltRegisterGlobalVariable(style, comp->name, comp->ns, comp->select,
1271 cur->children, comp, NULL);
1275 * xsltParseStylesheetVariable:
1276 * @ctxt: the XSLT transformation context
1277 * @cur: the "variable" element
1279 * parse an XSLT transformation variable declaration and record
1284 xsltParseStylesheetVariable(xsltTransformContextPtr ctxt, xmlNodePtr cur) {
1285 xsltStylePreCompPtr comp;
1287 if ((cur == NULL) || (ctxt == NULL))
1290 comp = (xsltStylePreCompPtr) cur->_private;
1292 xsltPrintErrorContext(ctxt, NULL, cur);
1293 xsltGenericError(xsltGenericErrorContext,
1294 "xsl:variable : compilation failed\n");
1298 if (comp->name == NULL) {
1299 xsltPrintErrorContext(ctxt, NULL, cur);
1300 xsltGenericError(xsltGenericErrorContext,
1301 "xsl:variable : missing name attribute\n");
1305 #ifdef WITH_XSLT_DEBUG_VARIABLE
1306 xsltGenericDebug(xsltGenericDebugContext,
1307 "Registering variable %s\n", comp->name);
1310 xsltRegisterVariable(ctxt, comp, cur->children, 0);
1314 * xsltParseStylesheetParam:
1315 * @ctxt: the XSLT transformation context
1316 * @cur: the "param" element
1318 * parse an XSLT transformation param declaration and record
1323 xsltParseStylesheetParam(xsltTransformContextPtr ctxt, xmlNodePtr cur) {
1324 xsltStylePreCompPtr comp;
1326 if ((cur == NULL) || (ctxt == NULL))
1329 comp = (xsltStylePreCompPtr) cur->_private;
1331 xsltPrintErrorContext(ctxt, NULL, cur);
1332 xsltGenericError(xsltGenericErrorContext,
1333 "xsl:param : compilation failed\n");
1337 if (comp->name == NULL) {
1338 xsltPrintErrorContext(ctxt, NULL, cur);
1339 xsltGenericError(xsltGenericErrorContext,
1340 "xsl:param : missing name attribute\n");
1344 #ifdef WITH_XSLT_DEBUG_VARIABLE
1345 xsltGenericDebug(xsltGenericDebugContext,
1346 "Registering param %s\n", comp->name);
1349 xsltRegisterVariable(ctxt, comp, cur->children, 1);
1353 * xsltFreeGlobalVariables:
1354 * @ctxt: the XSLT transformation context
1356 * Free up the data associated to the global variables
1361 xsltFreeGlobalVariables(xsltTransformContextPtr ctxt) {
1362 xmlHashFree(ctxt->globalVars, (xmlHashDeallocator) xsltFreeStackElem);
1366 * xsltXPathVariableLookup:
1367 * @ctxt: a void * but the the XSLT transformation context actually
1368 * @name: the variable name
1369 * @ns_uri: the variable namespace URI
1371 * This is the entry point when a varibale is needed by the XPath
1374 * Returns the value or NULL if not found
1377 xsltXPathVariableLookup(void *ctxt, const xmlChar *name,
1378 const xmlChar *ns_uri) {
1379 xsltTransformContextPtr context;
1380 xmlXPathObjectPtr ret;
1382 if ((ctxt == NULL) || (name == NULL))
1385 #ifdef WITH_XSLT_DEBUG_VARIABLE
1386 xsltGenericDebug(xsltGenericDebugContext,
1387 "Lookup variable %s\n", name);
1389 context = (xsltTransformContextPtr) ctxt;
1390 ret = xsltVariableLookup(context, name, ns_uri);
1392 xsltPrintErrorContext(ctxt, NULL, NULL);
1393 xsltGenericError(xsltGenericErrorContext,
1394 "unregistered variable %s\n", name);
1396 #ifdef WITH_XSLT_DEBUG_VARIABLE
1398 xsltGenericDebug(xsltGenericDebugContext,
1399 "found variable %s\n", name);