Roll src/third_party/WebKit a3b4a2e:7441784 (svn 202551:202552)
[chromium-blink-merge.git] / third_party / libxslt / libexslt / functions.c
blobe6e245fd18fa2df6c81d804425d8fa9709d2d033
1 #define IN_LIBEXSLT
2 #include "libexslt/libexslt.h"
4 #if defined(WIN32) && !defined (__CYGWIN__) && (!__MINGW32__)
5 #include <win32config.h>
6 #else
7 #include "config.h"
8 #endif
10 #include <string.h>
12 #include <libxml/tree.h>
13 #include <libxml/xpath.h>
14 #include <libxml/xpathInternals.h>
15 #include <libxml/hash.h>
16 #include <libxml/debugXML.h>
18 #include <libxslt/xsltutils.h>
19 #include <libxslt/variables.h>
20 #include <libxslt/xsltInternals.h>
21 #include <libxslt/extensions.h>
22 #include <libxslt/transform.h>
23 #include <libxslt/imports.h>
25 #include "exslt.h"
27 typedef struct _exsltFuncFunctionData exsltFuncFunctionData;
28 struct _exsltFuncFunctionData {
29 int nargs; /* number of arguments to the function */
30 xmlNodePtr content; /* the func:fuction template content */
33 typedef struct _exsltFuncData exsltFuncData;
34 struct _exsltFuncData {
35 xmlHashTablePtr funcs; /* pointer to the stylesheet module data */
36 xmlXPathObjectPtr result; /* returned by func:result */
37 int error; /* did an error occur? */
38 xmlDocPtr RVT; /* result tree fragment */
41 typedef struct _exsltFuncResultPreComp exsltFuncResultPreComp;
42 struct _exsltFuncResultPreComp {
43 xsltElemPreComp comp;
44 xmlXPathCompExprPtr select;
45 xmlNsPtr *nsList;
46 int nsNr;
49 /* Used for callback function in exsltInitFunc */
50 typedef struct _exsltFuncImportRegData exsltFuncImportRegData;
51 struct _exsltFuncImportRegData {
52 xsltTransformContextPtr ctxt;
53 xmlHashTablePtr hash;
56 static void exsltFuncFunctionFunction (xmlXPathParserContextPtr ctxt,
57 int nargs);
58 static exsltFuncFunctionData *exsltFuncNewFunctionData(void);
60 #define MAX_FUNC_RECURSION 1000
62 /*static const xmlChar *exsltResultDataID = (const xmlChar *) "EXSLT Result";*/
64 /**
65 * exsltFuncRegisterFunc:
66 * @func: the #exsltFuncFunctionData for the function
67 * @ctxt: an XSLT transformation context
68 * @URI: the function namespace URI
69 * @name: the function name
71 * Registers a function declared by a func:function element
73 static void
74 exsltFuncRegisterFunc (exsltFuncFunctionData *data,
75 xsltTransformContextPtr ctxt,
76 const xmlChar *URI, const xmlChar *name,
77 ATTRIBUTE_UNUSED const xmlChar *ignored) {
78 if ((data == NULL) || (ctxt == NULL) || (URI == NULL) || (name == NULL))
79 return;
81 xsltGenericDebug(xsltGenericDebugContext,
82 "exsltFuncRegisterFunc: register {%s}%s\n",
83 URI, name);
84 xsltRegisterExtFunction(ctxt, name, URI,
85 exsltFuncFunctionFunction);
89 * exsltFuncRegisterImportFunc
90 * @data: the exsltFuncFunctionData for the function
91 * @ch: structure containing context and hash table
92 * @URI: the function namespace URI
93 * @name: the function name
95 * Checks if imported function is already registered in top-level
96 * stylesheet. If not, copies function data and registers function
98 static void
99 exsltFuncRegisterImportFunc (exsltFuncFunctionData *data,
100 exsltFuncImportRegData *ch,
101 const xmlChar *URI, const xmlChar *name,
102 ATTRIBUTE_UNUSED const xmlChar *ignored) {
103 exsltFuncFunctionData *func=NULL;
105 if ((data == NULL) || (ch == NULL) || (URI == NULL) || (name == NULL))
106 return;
108 if (ch->ctxt == NULL || ch->hash == NULL)
109 return;
111 /* Check if already present */
112 func = (exsltFuncFunctionData*)xmlHashLookup2(ch->hash, URI, name);
113 if (func == NULL) { /* Not yet present - copy it in */
114 func = exsltFuncNewFunctionData();
115 memcpy(func, data, sizeof(exsltFuncFunctionData));
116 if (xmlHashAddEntry2(ch->hash, URI, name, func) < 0) {
117 xsltGenericError(xsltGenericErrorContext,
118 "Failed to register function {%s}%s\n",
119 URI, name);
120 } else { /* Do the registration */
121 xsltGenericDebug(xsltGenericDebugContext,
122 "exsltFuncRegisterImportFunc: register {%s}%s\n",
123 URI, name);
124 xsltRegisterExtFunction(ch->ctxt, name, URI,
125 exsltFuncFunctionFunction);
131 * exsltFuncInit:
132 * @ctxt: an XSLT transformation context
133 * @URI: the namespace URI for the extension
135 * Initializes the EXSLT - Functions module.
136 * Called at transformation-time; merges all
137 * functions declared in the import tree taking
138 * import precedence into account, i.e. overriding
139 * functions with lower import precedence.
141 * Returns the data for this transformation
143 static exsltFuncData *
144 exsltFuncInit (xsltTransformContextPtr ctxt, const xmlChar *URI) {
145 exsltFuncData *ret;
146 xsltStylesheetPtr tmp;
147 exsltFuncImportRegData ch;
148 xmlHashTablePtr hash;
150 ret = (exsltFuncData *) xmlMalloc (sizeof(exsltFuncData));
151 if (ret == NULL) {
152 xsltGenericError(xsltGenericErrorContext,
153 "exsltFuncInit: not enough memory\n");
154 return(NULL);
156 memset(ret, 0, sizeof(exsltFuncData));
158 ret->result = NULL;
159 ret->error = 0;
161 ch.hash = (xmlHashTablePtr) xsltStyleGetExtData(ctxt->style, URI);
162 ret->funcs = ch.hash;
163 xmlHashScanFull(ch.hash, (xmlHashScannerFull) exsltFuncRegisterFunc, ctxt);
164 tmp = ctxt->style;
165 ch.ctxt = ctxt;
166 while ((tmp=xsltNextImport(tmp))!=NULL) {
167 hash = xsltGetExtInfo(tmp, URI);
168 if (hash != NULL) {
169 xmlHashScanFull(hash,
170 (xmlHashScannerFull) exsltFuncRegisterImportFunc, &ch);
174 return(ret);
178 * exsltFuncShutdown:
179 * @ctxt: an XSLT transformation context
180 * @URI: the namespace URI for the extension
181 * @data: the module data to free up
183 * Shutdown the EXSLT - Functions module
184 * Called at transformation-time.
186 static void
187 exsltFuncShutdown (xsltTransformContextPtr ctxt ATTRIBUTE_UNUSED,
188 const xmlChar *URI ATTRIBUTE_UNUSED,
189 exsltFuncData *data) {
190 if (data->result != NULL)
191 xmlXPathFreeObject(data->result);
192 xmlFree(data);
196 * exsltFuncStyleInit:
197 * @style: an XSLT stylesheet
198 * @URI: the namespace URI for the extension
200 * Allocates the stylesheet data for EXSLT - Function
201 * Called at compile-time.
203 * Returns the allocated data
205 static xmlHashTablePtr
206 exsltFuncStyleInit (xsltStylesheetPtr style ATTRIBUTE_UNUSED,
207 const xmlChar *URI ATTRIBUTE_UNUSED) {
208 return xmlHashCreate(1);
212 * exsltFuncStyleShutdown:
213 * @style: an XSLT stylesheet
214 * @URI: the namespace URI for the extension
215 * @data: the stylesheet data to free up
217 * Shutdown the EXSLT - Function module
218 * Called at compile-time.
220 static void
221 exsltFuncStyleShutdown (xsltStylesheetPtr style ATTRIBUTE_UNUSED,
222 const xmlChar *URI ATTRIBUTE_UNUSED,
223 xmlHashTablePtr data) {
224 xmlHashFree(data, (xmlHashDeallocator) xmlFree);
228 * exsltFuncNewFunctionData:
230 * Allocates an #exslFuncFunctionData object
232 * Returns the new structure
234 static exsltFuncFunctionData *
235 exsltFuncNewFunctionData (void) {
236 exsltFuncFunctionData *ret;
238 ret = (exsltFuncFunctionData *) xmlMalloc (sizeof(exsltFuncFunctionData));
239 if (ret == NULL) {
240 xsltGenericError(xsltGenericErrorContext,
241 "exsltFuncNewFunctionData: not enough memory\n");
242 return (NULL);
244 memset(ret, 0, sizeof(exsltFuncFunctionData));
246 ret->nargs = 0;
247 ret->content = NULL;
249 return(ret);
253 * exsltFreeFuncResultPreComp:
254 * @comp: the #exsltFuncResultPreComp to free up
256 * Deallocates an #exsltFuncResultPreComp
258 static void
259 exsltFreeFuncResultPreComp (exsltFuncResultPreComp *comp) {
260 if (comp == NULL)
261 return;
263 if (comp->select != NULL)
264 xmlXPathFreeCompExpr (comp->select);
265 if (comp->nsList != NULL)
266 xmlFree(comp->nsList);
267 xmlFree(comp);
271 * exsltFuncFunctionFunction:
272 * @ctxt: an XPath parser context
273 * @nargs: the number of arguments
275 * Evaluates the func:function element that defines the called function.
277 static void
278 exsltFuncFunctionFunction (xmlXPathParserContextPtr ctxt, int nargs) {
279 xmlXPathObjectPtr oldResult, ret;
280 exsltFuncData *data;
281 exsltFuncFunctionData *func;
282 xmlNodePtr paramNode, oldInsert, fake;
283 int oldBase;
284 xsltStackElemPtr params = NULL, param;
285 xsltTransformContextPtr tctxt = xsltXPathGetTransformContext(ctxt);
286 int i, notSet;
287 struct objChain {
288 struct objChain *next;
289 xmlXPathObjectPtr obj;
291 struct objChain *savedObjChain = NULL, *savedObj;
294 * retrieve func:function template
296 data = (exsltFuncData *) xsltGetExtData (tctxt,
297 EXSLT_FUNCTIONS_NAMESPACE);
298 oldResult = data->result;
299 data->result = NULL;
301 func = (exsltFuncFunctionData*) xmlHashLookup2 (data->funcs,
302 ctxt->context->functionURI,
303 ctxt->context->function);
306 * params handling
308 if (nargs > func->nargs) {
309 xsltGenericError(xsltGenericErrorContext,
310 "{%s}%s: called with too many arguments\n",
311 ctxt->context->functionURI, ctxt->context->function);
312 ctxt->error = XPATH_INVALID_ARITY;
313 return;
315 if (func->content != NULL) {
316 paramNode = func->content->prev;
318 else
319 paramNode = NULL;
320 if ((paramNode == NULL) && (func->nargs != 0)) {
321 xsltGenericError(xsltGenericErrorContext,
322 "exsltFuncFunctionFunction: nargs != 0 and "
323 "param == NULL\n");
324 return;
326 if (tctxt->funcLevel > MAX_FUNC_RECURSION) {
327 xsltGenericError(xsltGenericErrorContext,
328 "{%s}%s: detected a recursion\n",
329 ctxt->context->functionURI, ctxt->context->function);
330 ctxt->error = XPATH_MEMORY_ERROR;
331 return;
333 tctxt->funcLevel++;
336 * We have a problem with the evaluation of function parameters.
337 * The original library code did not evaluate XPath expressions until
338 * the last moment. After version 1.1.17 of the libxslt, the logic
339 * of other parts of the library was changed, and the evaluation of
340 * XPath expressions within parameters now takes place as soon as the
341 * parameter is parsed/evaluated (xsltParseStylesheetCallerParam).
342 * This means that the parameters need to be evaluated in lexical
343 * order (since a variable is "in scope" as soon as it is declared).
344 * However, on entry to this routine, the values (from the caller) are
345 * in reverse order (held on the XPath context variable stack). To
346 * accomplish what is required, I have added code to pop the XPath
347 * objects off of the stack at the beginning and save them, then use
348 * them (in the reverse order) as the params are evaluated. This
349 * requires an xmlMalloc/xmlFree for each param set by the caller,
350 * which is not very nice. There is probably a much better solution
351 * (like change other code to delay the evaluation).
354 * In order to give the function params and variables a new 'scope'
355 * we change varsBase in the context.
357 oldBase = tctxt->varsBase;
358 tctxt->varsBase = tctxt->varsNr;
359 /* If there are any parameters */
360 if (paramNode != NULL) {
361 /* Fetch the stored argument values from the caller */
362 for (i = 0; i < nargs; i++) {
363 savedObj = xmlMalloc(sizeof(struct objChain));
364 savedObj->next = savedObjChain;
365 savedObj->obj = valuePop(ctxt);
366 savedObjChain = savedObj;
370 * Prepare to process params in reverse order. First, go to
371 * the beginning of the param chain.
373 for (i = 1; i <= func->nargs; i++) {
374 if (paramNode->prev == NULL)
375 break;
376 paramNode = paramNode->prev;
379 * i has total # params found, nargs is number which are present
380 * as arguments from the caller
381 * Calculate the number of un-set parameters
383 notSet = func->nargs - nargs;
384 for (; i > 0; i--) {
385 param = xsltParseStylesheetCallerParam (tctxt, paramNode);
386 if (i > notSet) { /* if parameter value set */
387 param->computed = 1;
388 if (param->value != NULL)
389 xmlXPathFreeObject(param->value);
390 savedObj = savedObjChain; /* get next val from chain */
391 param->value = savedObj->obj;
392 savedObjChain = savedObjChain->next;
393 xmlFree(savedObj);
395 xsltLocalVariablePush(tctxt, param, -1);
396 param->next = params;
397 params = param;
398 paramNode = paramNode->next;
402 * actual processing
404 fake = xmlNewDocNode(tctxt->output, NULL,
405 (const xmlChar *)"fake", NULL);
406 oldInsert = tctxt->insert;
407 tctxt->insert = fake;
408 xsltApplyOneTemplate (tctxt, xmlXPathGetContextNode(ctxt),
409 func->content, NULL, NULL);
410 xsltLocalVariablePop(tctxt, tctxt->varsBase, -2);
411 tctxt->insert = oldInsert;
412 tctxt->varsBase = oldBase; /* restore original scope */
413 if (params != NULL)
414 xsltFreeStackElemList(params);
416 if (data->error != 0)
417 goto error;
419 if (data->result != NULL) {
420 ret = data->result;
421 } else
422 ret = xmlXPathNewCString("");
424 data->result = oldResult;
427 * It is an error if the instantiation of the template results in
428 * the generation of result nodes.
430 if (fake->children != NULL) {
431 #ifdef LIBXML_DEBUG_ENABLED
432 xmlDebugDumpNode (stderr, fake, 1);
433 #endif
434 xsltGenericError(xsltGenericErrorContext,
435 "{%s}%s: cannot write to result tree while "
436 "executing a function\n",
437 ctxt->context->functionURI, ctxt->context->function);
438 xmlFreeNode(fake);
439 goto error;
441 xmlFreeNode(fake);
442 valuePush(ctxt, ret);
444 error:
446 * IMPORTANT: This enables previously tree fragments marked as
447 * being results of a function, to be garbage-collected after
448 * the calling process exits.
450 xsltExtensionInstructionResultFinalize(tctxt);
451 tctxt->funcLevel--;
455 static void
456 exsltFuncFunctionComp (xsltStylesheetPtr style, xmlNodePtr inst) {
457 xmlChar *name, *prefix;
458 xmlNsPtr ns;
459 xmlHashTablePtr data;
460 exsltFuncFunctionData *func;
462 if ((style == NULL) || (inst == NULL) || (inst->type != XML_ELEMENT_NODE))
463 return;
466 xmlChar *qname;
468 qname = xmlGetProp(inst, (const xmlChar *) "name");
469 name = xmlSplitQName2 (qname, &prefix);
470 xmlFree(qname);
472 if ((name == NULL) || (prefix == NULL)) {
473 xsltGenericError(xsltGenericErrorContext,
474 "func:function: not a QName\n");
475 if (name != NULL)
476 xmlFree(name);
477 return;
479 /* namespace lookup */
480 ns = xmlSearchNs (inst->doc, inst, prefix);
481 if (ns == NULL) {
482 xsltGenericError(xsltGenericErrorContext,
483 "func:function: undeclared prefix %s\n",
484 prefix);
485 xmlFree(name);
486 xmlFree(prefix);
487 return;
489 xmlFree(prefix);
491 xsltParseTemplateContent(style, inst);
494 * Create function data
496 func = exsltFuncNewFunctionData();
497 func->content = inst->children;
498 while (IS_XSLT_ELEM(func->content) &&
499 IS_XSLT_NAME(func->content, "param")) {
500 func->content = func->content->next;
501 func->nargs++;
505 * Register the function data such that it can be retrieved
506 * by exslFuncFunctionFunction
508 #ifdef XSLT_REFACTORED
510 * Ensure that the hash table will be stored in the *current*
511 * stylesheet level in order to correctly evaluate the
512 * import precedence.
514 data = (xmlHashTablePtr)
515 xsltStyleStylesheetLevelGetExtData(style,
516 EXSLT_FUNCTIONS_NAMESPACE);
517 #else
518 data = (xmlHashTablePtr)
519 xsltStyleGetExtData (style, EXSLT_FUNCTIONS_NAMESPACE);
520 #endif
521 if (data == NULL) {
522 xsltGenericError(xsltGenericErrorContext,
523 "exsltFuncFunctionComp: no stylesheet data\n");
524 xmlFree(name);
525 return;
528 if (xmlHashAddEntry2 (data, ns->href, name, func) < 0) {
529 xsltTransformError(NULL, style, inst,
530 "Failed to register function {%s}%s\n",
531 ns->href, name);
532 style->errors++;
533 } else {
534 xsltGenericDebug(xsltGenericDebugContext,
535 "exsltFuncFunctionComp: register {%s}%s\n",
536 ns->href, name);
538 xmlFree(name);
541 static xsltElemPreCompPtr
542 exsltFuncResultComp (xsltStylesheetPtr style, xmlNodePtr inst,
543 xsltTransformFunction function) {
544 xmlNodePtr test;
545 xmlChar *sel;
546 exsltFuncResultPreComp *ret;
548 if ((style == NULL) || (inst == NULL) || (inst->type != XML_ELEMENT_NODE))
549 return (NULL);
552 * "Validity" checking
554 /* it is an error to have any following sibling elements aside
555 * from the xsl:fallback element.
557 for (test = inst->next; test != NULL; test = test->next) {
558 if (test->type != XML_ELEMENT_NODE)
559 continue;
560 if (IS_XSLT_ELEM(test) && IS_XSLT_NAME(test, "fallback"))
561 continue;
562 xsltGenericError(xsltGenericErrorContext,
563 "exsltFuncResultElem: only xsl:fallback is "
564 "allowed to follow func:result\n");
565 style->errors++;
566 return (NULL);
568 /* it is an error for a func:result element to not be a descendant
569 * of func:function.
570 * it is an error if a func:result occurs within a func:result
571 * element.
572 * it is an error if instanciating the content of a variable
573 * binding element (i.e. xsl:variable, xsl:param) results in the
574 * instanciation of a func:result element.
576 for (test = inst->parent; test != NULL; test = test->parent) {
577 if (IS_XSLT_ELEM(test) &&
578 IS_XSLT_NAME(test, "stylesheet")) {
579 xsltGenericError(xsltGenericErrorContext,
580 "func:result element not a descendant "
581 "of a func:function\n");
582 style->errors++;
583 return (NULL);
585 if ((test->ns != NULL) &&
586 (xmlStrEqual(test->ns->href, EXSLT_FUNCTIONS_NAMESPACE))) {
587 if (xmlStrEqual(test->name, (const xmlChar *) "function")) {
588 break;
590 if (xmlStrEqual(test->name, (const xmlChar *) "result")) {
591 xsltGenericError(xsltGenericErrorContext,
592 "func:result element not allowed within"
593 " another func:result element\n");
594 style->errors++;
595 return (NULL);
598 if (IS_XSLT_ELEM(test) &&
599 (IS_XSLT_NAME(test, "variable") ||
600 IS_XSLT_NAME(test, "param"))) {
601 xsltGenericError(xsltGenericErrorContext,
602 "func:result element not allowed within"
603 " a variable binding element\n");
604 style->errors++;
605 return (NULL);
610 * Precomputation
612 ret = (exsltFuncResultPreComp *)
613 xmlMalloc (sizeof(exsltFuncResultPreComp));
614 if (ret == NULL) {
615 xsltPrintErrorContext(NULL, NULL, NULL);
616 xsltGenericError(xsltGenericErrorContext,
617 "exsltFuncResultComp : malloc failed\n");
618 style->errors++;
619 return (NULL);
621 memset(ret, 0, sizeof(exsltFuncResultPreComp));
623 xsltInitElemPreComp ((xsltElemPreCompPtr) ret, style, inst, function,
624 (xsltElemPreCompDeallocator) exsltFreeFuncResultPreComp);
625 ret->select = NULL;
628 * Precompute the select attribute
630 sel = xmlGetNsProp(inst, (const xmlChar *) "select", NULL);
631 if (sel != NULL) {
632 ret->select = xmlXPathCompile (sel);
633 xmlFree(sel);
636 * Precompute the namespace list
638 ret->nsList = xmlGetNsList(inst->doc, inst);
639 if (ret->nsList != NULL) {
640 int i = 0;
641 while (ret->nsList[i] != NULL)
642 i++;
643 ret->nsNr = i;
645 return ((xsltElemPreCompPtr) ret);
648 static void
649 exsltFuncResultElem (xsltTransformContextPtr ctxt,
650 xmlNodePtr node ATTRIBUTE_UNUSED, xmlNodePtr inst,
651 exsltFuncResultPreComp *comp) {
652 exsltFuncData *data;
653 xmlXPathObjectPtr ret;
656 /* It is an error if instantiating the content of the
657 * func:function element results in the instantiation of more than
658 * one func:result elements.
660 data = (exsltFuncData *) xsltGetExtData (ctxt, EXSLT_FUNCTIONS_NAMESPACE);
661 if (data == NULL) {
662 xsltGenericError(xsltGenericErrorContext,
663 "exsltFuncReturnElem: data == NULL\n");
664 return;
666 if (data->result != NULL) {
667 xsltGenericError(xsltGenericErrorContext,
668 "func:result already instanciated\n");
669 data->error = 1;
670 return;
673 * Processing
675 if (comp->select != NULL) {
676 xmlNsPtr *oldXPNsList;
677 int oldXPNsNr;
678 xmlNodePtr oldXPContextNode;
679 /* If the func:result element has a select attribute, then the
680 * value of the attribute must be an expression and the
681 * returned value is the object that results from evaluating
682 * the expression. In this case, the content must be empty.
684 if (inst->children != NULL) {
685 xsltGenericError(xsltGenericErrorContext,
686 "func:result content must be empty if"
687 " the function has a select attribute\n");
688 data->error = 1;
689 return;
691 oldXPNsList = ctxt->xpathCtxt->namespaces;
692 oldXPNsNr = ctxt->xpathCtxt->nsNr;
693 oldXPContextNode = ctxt->xpathCtxt->node;
695 ctxt->xpathCtxt->namespaces = comp->nsList;
696 ctxt->xpathCtxt->nsNr = comp->nsNr;
698 ret = xmlXPathCompiledEval(comp->select, ctxt->xpathCtxt);
700 ctxt->xpathCtxt->node = oldXPContextNode;
701 ctxt->xpathCtxt->nsNr = oldXPNsNr;
702 ctxt->xpathCtxt->namespaces = oldXPNsList;
704 if (ret == NULL) {
705 xsltGenericError(xsltGenericErrorContext,
706 "exsltFuncResultElem: ret == NULL\n");
707 return;
710 * Mark it as a function result in order to avoid garbage
711 * collecting of tree fragments before the function exits.
713 xsltExtensionInstructionResultRegister(ctxt, ret);
714 } else if (inst->children != NULL) {
715 /* If the func:result element does not have a select attribute
716 * and has non-empty content (i.e. the func:result element has
717 * one or more child nodes), then the content of the
718 * func:result element specifies the value.
720 xmlNodePtr oldInsert;
721 xmlDocPtr container;
723 container = xsltCreateRVT(ctxt);
724 if (container == NULL) {
725 xsltGenericError(xsltGenericErrorContext,
726 "exsltFuncResultElem: out of memory\n");
727 data->error = 1;
728 return;
730 xsltRegisterLocalRVT(ctxt, container);
732 oldInsert = ctxt->insert;
733 ctxt->insert = (xmlNodePtr) container;
734 xsltApplyOneTemplate (ctxt, ctxt->xpathCtxt->node,
735 inst->children, NULL, NULL);
736 ctxt->insert = oldInsert;
738 ret = xmlXPathNewValueTree((xmlNodePtr) container);
739 if (ret == NULL) {
740 xsltGenericError(xsltGenericErrorContext,
741 "exsltFuncResultElem: ret == NULL\n");
742 data->error = 1;
743 } else {
744 ret->boolval = 0; /* Freeing is not handled there anymore */
746 * Mark it as a function result in order to avoid garbage
747 * collecting of tree fragments before the function exits.
749 xsltExtensionInstructionResultRegister(ctxt, ret);
751 } else {
752 /* If the func:result element has empty content and does not
753 * have a select attribute, then the returned value is an
754 * empty string.
756 ret = xmlXPathNewCString("");
758 data->result = ret;
762 * exsltFuncRegister:
764 * Registers the EXSLT - Functions module
766 void
767 exsltFuncRegister (void) {
768 xsltRegisterExtModuleFull (EXSLT_FUNCTIONS_NAMESPACE,
769 (xsltExtInitFunction) exsltFuncInit,
770 (xsltExtShutdownFunction) exsltFuncShutdown,
771 (xsltStyleExtInitFunction) exsltFuncStyleInit,
772 (xsltStyleExtShutdownFunction) exsltFuncStyleShutdown);
774 xsltRegisterExtModuleTopLevel ((const xmlChar *) "function",
775 EXSLT_FUNCTIONS_NAMESPACE,
776 exsltFuncFunctionComp);
777 xsltRegisterExtModuleElement ((const xmlChar *) "result",
778 EXSLT_FUNCTIONS_NAMESPACE,
779 (xsltPreComputeFunction)exsltFuncResultComp,
780 (xsltTransformFunction) exsltFuncResultElem);