VirtualBox

source: vbox/trunk/src/libs/libxslt-1.1.22/libexslt/functions.c@ 28321

Last change on this file since 28321 was 7299, checked in by vboxsync, 17 years ago

Added vboxconfig.h for linux builds.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Revision Author Id
File size: 21.7 KB
Line 
1#define IN_LIBEXSLT
2#include "libexslt/libexslt.h"
3
4#if defined(WIN32) && !defined (__CYGWIN__) && (!__MINGW32__)
5#include <win32config.h>
6#elif defined(VBOX)
7#include "vboxconfig.h"
8#else
9#include "config.h"
10#endif
11
12#include <string.h>
13
14#include <libxml/tree.h>
15#include <libxml/xpath.h>
16#include <libxml/xpathInternals.h>
17#include <libxml/hash.h>
18#include <libxml/debugXML.h>
19
20#include <libxslt/xsltutils.h>
21#include <libxslt/variables.h>
22#include <libxslt/xsltInternals.h>
23#include <libxslt/extensions.h>
24#include <libxslt/transform.h>
25#include <libxslt/imports.h>
26
27#include "exslt.h"
28
29typedef struct _exsltFuncFunctionData exsltFuncFunctionData;
30struct _exsltFuncFunctionData {
31 int nargs; /* number of arguments to the function */
32 xmlNodePtr content; /* the func:fuction template content */
33};
34
35typedef struct _exsltFuncData exsltFuncData;
36struct _exsltFuncData {
37 xmlHashTablePtr funcs; /* pointer to the stylesheet module data */
38 xmlXPathObjectPtr result; /* returned by func:result */
39 int error; /* did an error occur? */
40 xmlDocPtr RVT; /* result tree fragment */
41};
42
43typedef struct _exsltFuncResultPreComp exsltFuncResultPreComp;
44struct _exsltFuncResultPreComp {
45 xsltElemPreComp comp;
46 xmlXPathCompExprPtr select;
47 xmlNsPtr *nsList;
48 int nsNr;
49};
50
51/* Used for callback function in exsltInitFunc */
52typedef struct _exsltFuncImportRegData exsltFuncImportRegData;
53struct _exsltFuncImportRegData {
54 xsltTransformContextPtr ctxt;
55 xmlHashTablePtr hash;
56};
57
58static void exsltFuncFunctionFunction (xmlXPathParserContextPtr ctxt,
59 int nargs);
60static exsltFuncFunctionData *exsltFuncNewFunctionData(void);
61
62/*static const xmlChar *exsltResultDataID = (const xmlChar *) "EXSLT Result";*/
63
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
70 *
71 * Registers a function declared by a func:function element
72 */
73static void
74exsltFuncRegisterFunc (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;
80
81 xsltGenericDebug(xsltGenericDebugContext,
82 "exsltFuncRegisterFunc: register {%s}%s\n",
83 URI, name);
84 xsltRegisterExtFunction(ctxt, name, URI,
85 exsltFuncFunctionFunction);
86}
87
88/*
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
94 *
95 * Checks if imported function is already registered in top-level
96 * stylesheet. If not, copies function data and registers function
97 */
98static void
99exsltFuncRegisterImportFunc (exsltFuncFunctionData *data,
100 exsltFuncImportRegData *ch,
101 const xmlChar *URI, const xmlChar *name,
102 ATTRIBUTE_UNUSED const xmlChar *ignored) {
103 exsltFuncFunctionData *func=NULL;
104
105 if ((data == NULL) || (ch == NULL) || (URI == NULL) || (name == NULL))
106 return;
107
108 if (ch->ctxt == NULL || ch->hash == NULL)
109 return;
110
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);
126 }
127 }
128}
129
130/**
131 * exsltFuncInit:
132 * @ctxt: an XSLT transformation context
133 * @URI: the namespace URI for the extension
134 *
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.
140 *
141 * Returns the data for this transformation
142 */
143static exsltFuncData *
144exsltFuncInit (xsltTransformContextPtr ctxt, const xmlChar *URI) {
145 exsltFuncData *ret;
146 xsltStylesheetPtr tmp;
147 exsltFuncImportRegData ch;
148 xmlHashTablePtr hash;
149
150 ret = (exsltFuncData *) xmlMalloc (sizeof(exsltFuncData));
151 if (ret == NULL) {
152 xsltGenericError(xsltGenericErrorContext,
153 "exsltFuncInit: not enough memory\n");
154 return(NULL);
155 }
156 memset(ret, 0, sizeof(exsltFuncData));
157
158 ret->result = NULL;
159 ret->error = 0;
160
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);
171 }
172 }
173
174 return(ret);
175}
176
177/**
178 * exsltFuncShutdown:
179 * @ctxt: an XSLT transformation context
180 * @URI: the namespace URI for the extension
181 * @data: the module data to free up
182 *
183 * Shutdown the EXSLT - Functions module
184 * Called at transformation-time.
185 */
186static void
187exsltFuncShutdown (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);
193}
194
195/**
196 * exsltFuncStyleInit:
197 * @style: an XSLT stylesheet
198 * @URI: the namespace URI for the extension
199 *
200 * Allocates the stylesheet data for EXSLT - Function
201 * Called at compile-time.
202 *
203 * Returns the allocated data
204 */
205static xmlHashTablePtr
206exsltFuncStyleInit (xsltStylesheetPtr style ATTRIBUTE_UNUSED,
207 const xmlChar *URI ATTRIBUTE_UNUSED) {
208 return xmlHashCreate(1);
209}
210
211/**
212 * exsltFuncStyleShutdown:
213 * @style: an XSLT stylesheet
214 * @URI: the namespace URI for the extension
215 * @data: the stylesheet data to free up
216 *
217 * Shutdown the EXSLT - Function module
218 * Called at compile-time.
219 */
220static void
221exsltFuncStyleShutdown (xsltStylesheetPtr style ATTRIBUTE_UNUSED,
222 const xmlChar *URI ATTRIBUTE_UNUSED,
223 xmlHashTablePtr data) {
224 xmlHashFree(data, (xmlHashDeallocator) xmlFree);
225}
226
227/**
228 * exsltFuncNewFunctionData:
229 *
230 * Allocates an #exslFuncFunctionData object
231 *
232 * Returns the new structure
233 */
234static exsltFuncFunctionData *
235exsltFuncNewFunctionData (void) {
236 exsltFuncFunctionData *ret;
237
238 ret = (exsltFuncFunctionData *) xmlMalloc (sizeof(exsltFuncFunctionData));
239 if (ret == NULL) {
240 xsltGenericError(xsltGenericErrorContext,
241 "exsltFuncNewFunctionData: not enough memory\n");
242 return (NULL);
243 }
244 memset(ret, 0, sizeof(exsltFuncFunctionData));
245
246 ret->nargs = 0;
247 ret->content = NULL;
248
249 return(ret);
250}
251
252/**
253 * exsltFreeFuncResultPreComp:
254 * @comp: the #exsltFuncResultPreComp to free up
255 *
256 * Deallocates an #exsltFuncResultPreComp
257 */
258static void
259exsltFreeFuncResultPreComp (exsltFuncResultPreComp *comp) {
260 if (comp == NULL)
261 return;
262
263 if (comp->select != NULL)
264 xmlXPathFreeCompExpr (comp->select);
265 if (comp->nsList != NULL)
266 xmlFree(comp->nsList);
267 xmlFree(comp);
268}
269
270/**
271 * exsltFuncFunctionFunction:
272 * @ctxt: an XPath parser context
273 * @nargs: the number of arguments
274 *
275 * Evaluates the func:function element that defines the called function.
276 */
277static void
278exsltFuncFunctionFunction (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;
290 };
291 struct objChain *savedObjChain = NULL, *savedObj;
292
293 /*
294 * retrieve func:function template
295 */
296 data = (exsltFuncData *) xsltGetExtData (tctxt,
297 EXSLT_FUNCTIONS_NAMESPACE);
298 oldResult = data->result;
299 data->result = NULL;
300
301 func = (exsltFuncFunctionData*) xmlHashLookup2 (data->funcs,
302 ctxt->context->functionURI,
303 ctxt->context->function);
304
305 /*
306 * params handling
307 */
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;
314 }
315 if (func->content != NULL) {
316 paramNode = func->content->prev;
317 }
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;
325 }
326 /*
327 * We have a problem with the evaluation of function parameters.
328 * The original library code did not evaluate XPath expressions until
329 * the last moment. After version 1.1.17 of the libxslt, the logic
330 * of other parts of the library was changed, and the evaluation of
331 * XPath expressions within parameters now takes place as soon as the
332 * parameter is parsed/evaluated (xsltParseStylesheetCallerParam).
333 * This means that the parameters need to be evaluated in lexical
334 * order (since a variable is "in scope" as soon as it is declared).
335 * However, on entry to this routine, the values (from the caller) are
336 * in reverse order (held on the XPath context variable stack). To
337 * accomplish what is required, I have added code to pop the XPath
338 * objects off of the stack at the beginning and save them, then use
339 * them (in the reverse order) as the params are evaluated. This
340 * requires an xmlMalloc/xmlFree for each param set by the caller,
341 * which is not very nice. There is probably a much better solution
342 * (like change other code to delay the evaluation).
343 */
344 /*
345 * In order to give the function params and variables a new 'scope'
346 * we change varsBase in the context.
347 */
348 oldBase = tctxt->varsBase;
349 tctxt->varsBase = tctxt->varsNr;
350 /* If there are any parameters */
351 if (paramNode != NULL) {
352 /* Fetch the stored argument values from the caller */
353 for (i = 0; i < nargs; i++) {
354 savedObj = xmlMalloc(sizeof(struct objChain));
355 savedObj->next = savedObjChain;
356 savedObj->obj = valuePop(ctxt);
357 savedObjChain = savedObj;
358 }
359
360 /*
361 * Prepare to process params in reverse order. First, go to
362 * the beginning of the param chain.
363 */
364 for (i = 1; i <= func->nargs; i++) {
365 if (paramNode->prev == NULL)
366 break;
367 paramNode = paramNode->prev;
368 }
369 /*
370 * i has total # params found, nargs is number which are present
371 * as arguments from the caller
372 * Calculate the number of un-set parameters
373 */
374 notSet = func->nargs - nargs;
375 for (; i > 0; i--) {
376 param = xsltParseStylesheetCallerParam (tctxt, paramNode);
377 if (i > notSet) { /* if parameter value set */
378 param->computed = 1;
379 if (param->value != NULL)
380 xmlXPathFreeObject(param->value);
381 savedObj = savedObjChain; /* get next val from chain */
382 param->value = savedObj->obj;
383 savedObjChain = savedObjChain->next;
384 xmlFree(savedObj);
385 }
386 xsltLocalVariablePush(tctxt, param, -1);
387 param->next = params;
388 params = param;
389 paramNode = paramNode->next;
390 }
391 }
392 /*
393 * actual processing
394 */
395 fake = xmlNewDocNode(tctxt->output, NULL,
396 (const xmlChar *)"fake", NULL);
397 oldInsert = tctxt->insert;
398 tctxt->insert = fake;
399 xsltApplyOneTemplate (tctxt, xmlXPathGetContextNode(ctxt),
400 func->content, NULL, NULL);
401 xsltLocalVariablePop(tctxt, tctxt->varsBase, -2);
402 tctxt->insert = oldInsert;
403 tctxt->varsBase = oldBase; /* restore original scope */
404 if (params != NULL)
405 xsltFreeStackElemList(params);
406
407 if (data->error != 0)
408 goto error;
409
410 if (data->result != NULL) {
411 ret = data->result;
412 } else
413 ret = xmlXPathNewCString("");
414
415 data->result = oldResult;
416
417 /*
418 * It is an error if the instantiation of the template results in
419 * the generation of result nodes.
420 */
421 if (fake->children != NULL) {
422#ifdef LIBXML_DEBUG_ENABLED
423 xmlDebugDumpNode (stderr, fake, 1);
424#endif
425 xsltGenericError(xsltGenericErrorContext,
426 "{%s}%s: cannot write to result tree while "
427 "executing a function\n",
428 ctxt->context->functionURI, ctxt->context->function);
429 xmlFreeNode(fake);
430 goto error;
431 }
432 xmlFreeNode(fake);
433 valuePush(ctxt, ret);
434
435error:
436 /*
437 * IMPORTANT: This enables previously tree fragments marked as
438 * being results of a function, to be garbage-collected after
439 * the calling process exits.
440 */
441 xsltExtensionInstructionResultFinalize(tctxt);
442}
443
444
445static void
446exsltFuncFunctionComp (xsltStylesheetPtr style, xmlNodePtr inst) {
447 xmlChar *name, *prefix;
448 xmlNsPtr ns;
449 xmlHashTablePtr data;
450 exsltFuncFunctionData *func;
451
452 if ((style == NULL) || (inst == NULL))
453 return;
454
455
456 {
457 xmlChar *qname;
458
459 qname = xmlGetProp(inst, (const xmlChar *) "name");
460 name = xmlSplitQName2 (qname, &prefix);
461 xmlFree(qname);
462 }
463 if ((name == NULL) || (prefix == NULL)) {
464 xsltGenericError(xsltGenericErrorContext,
465 "func:function: not a QName\n");
466 if (name != NULL)
467 xmlFree(name);
468 return;
469 }
470 /* namespace lookup */
471 ns = xmlSearchNs (inst->doc, inst, prefix);
472 if (ns == NULL) {
473 xsltGenericError(xsltGenericErrorContext,
474 "func:function: undeclared prefix %s\n",
475 prefix);
476 xmlFree(name);
477 xmlFree(prefix);
478 return;
479 }
480 xmlFree(prefix);
481
482 /*
483 * Create function data
484 */
485 func = exsltFuncNewFunctionData();
486 func->content = inst->children;
487 while (IS_XSLT_ELEM(func->content) &&
488 IS_XSLT_NAME(func->content, "param")) {
489 func->content = func->content->next;
490 func->nargs++;
491 }
492
493 xsltParseTemplateContent(style, inst);
494
495 /*
496 * Register the function data such that it can be retrieved
497 * by exslFuncFunctionFunction
498 */
499#ifdef XSLT_REFACTORED
500 /*
501 * Ensure that the hash table will be stored in the *current*
502 * stylesheet level in order to correctly evaluate the
503 * import precedence.
504 */
505 data = (xmlHashTablePtr)
506 xsltStyleStylesheetLevelGetExtData(style,
507 EXSLT_FUNCTIONS_NAMESPACE);
508#else
509 data = (xmlHashTablePtr)
510 xsltStyleGetExtData (style, EXSLT_FUNCTIONS_NAMESPACE);
511#endif
512 if (data == NULL) {
513 xsltGenericError(xsltGenericErrorContext,
514 "exsltFuncFunctionComp: no stylesheet data\n");
515 xmlFree(name);
516 return;
517 }
518
519 if (xmlHashAddEntry2 (data, ns->href, name, func) < 0) {
520 xsltTransformError(NULL, style, inst,
521 "Failed to register function {%s}%s\n",
522 ns->href, name);
523 style->errors++;
524 } else {
525 xsltGenericDebug(xsltGenericDebugContext,
526 "exsltFuncFunctionComp: register {%s}%s\n",
527 ns->href, name);
528 }
529 xmlFree(name);
530}
531
532static xsltElemPreCompPtr
533exsltFuncResultComp (xsltStylesheetPtr style, xmlNodePtr inst,
534 xsltTransformFunction function) {
535 xmlNodePtr test;
536 xmlChar *sel;
537 exsltFuncResultPreComp *ret;
538
539 /*
540 * "Validity" checking
541 */
542 /* it is an error to have any following sibling elements aside
543 * from the xsl:fallback element.
544 */
545 for (test = inst->next; test != NULL; test = test->next) {
546 if (test->type != XML_ELEMENT_NODE)
547 continue;
548 if (IS_XSLT_ELEM(test) && IS_XSLT_NAME(test, "fallback"))
549 continue;
550 xsltGenericError(xsltGenericErrorContext,
551 "exsltFuncResultElem: only xsl:fallback is "
552 "allowed to follow func:result\n");
553 return (NULL);
554 }
555 /* it is an error for a func:result element to not be a descendant
556 * of func:function.
557 * it is an error if a func:result occurs within a func:result
558 * element.
559 * it is an error if instanciating the content of a variable
560 * binding element (i.e. xsl:variable, xsl:param) results in the
561 * instanciation of a func:result element.
562 */
563 for (test = inst->parent; test != NULL; test = test->parent) {
564 if ((test->ns != NULL) &&
565 (xmlStrEqual(test->ns->href, EXSLT_FUNCTIONS_NAMESPACE))) {
566 if (xmlStrEqual(test->name, (const xmlChar *) "function")) {
567 break;
568 }
569 if (xmlStrEqual(test->name, (const xmlChar *) "result")) {
570 xsltGenericError(xsltGenericErrorContext,
571 "func:result element not allowed within"
572 " another func:result element\n");
573 return (NULL);
574 }
575 }
576 if (IS_XSLT_ELEM(test) &&
577 (IS_XSLT_NAME(test, "variable") ||
578 IS_XSLT_NAME(test, "param"))) {
579 xsltGenericError(xsltGenericErrorContext,
580 "func:result element not allowed within"
581 " a variable binding element\n");
582 return (NULL);
583 }
584 }
585
586 /*
587 * Precomputation
588 */
589 ret = (exsltFuncResultPreComp *)
590 xmlMalloc (sizeof(exsltFuncResultPreComp));
591 if (ret == NULL) {
592 xsltPrintErrorContext(NULL, NULL, NULL);
593 xsltGenericError(xsltGenericErrorContext,
594 "exsltFuncResultComp : malloc failed\n");
595 return (NULL);
596 }
597 memset(ret, 0, sizeof(exsltFuncResultPreComp));
598
599 xsltInitElemPreComp ((xsltElemPreCompPtr) ret, style, inst, function,
600 (xsltElemPreCompDeallocator) exsltFreeFuncResultPreComp);
601 ret->select = NULL;
602
603 /*
604 * Precompute the select attribute
605 */
606 sel = xmlGetNsProp(inst, (const xmlChar *) "select", NULL);
607 if (sel != NULL) {
608 ret->select = xmlXPathCompile (sel);
609 xmlFree(sel);
610 }
611 /*
612 * Precompute the namespace list
613 */
614 ret->nsList = xmlGetNsList(inst->doc, inst);
615 if (ret->nsList != NULL) {
616 int i = 0;
617 while (ret->nsList[i] != NULL)
618 i++;
619 ret->nsNr = i;
620 }
621 return ((xsltElemPreCompPtr) ret);
622}
623
624static void
625exsltFuncResultElem (xsltTransformContextPtr ctxt,
626 xmlNodePtr node ATTRIBUTE_UNUSED, xmlNodePtr inst,
627 exsltFuncResultPreComp *comp) {
628 exsltFuncData *data;
629 xmlXPathObjectPtr ret;
630
631
632 /* It is an error if instantiating the content of the
633 * func:function element results in the instantiation of more than
634 * one func:result elements.
635 */
636 data = (exsltFuncData *) xsltGetExtData (ctxt, EXSLT_FUNCTIONS_NAMESPACE);
637 if (data == NULL) {
638 xsltGenericError(xsltGenericErrorContext,
639 "exsltFuncReturnElem: data == NULL\n");
640 return;
641 }
642 if (data->result != NULL) {
643 xsltGenericError(xsltGenericErrorContext,
644 "func:result already instanciated\n");
645 data->error = 1;
646 return;
647 }
648 /*
649 * Processing
650 */
651 if (comp->select != NULL) {
652 xmlNsPtr *oldXPNsList;
653 int oldXPNsNr;
654 xmlNodePtr oldXPContextNode;
655 /* If the func:result element has a select attribute, then the
656 * value of the attribute must be an expression and the
657 * returned value is the object that results from evaluating
658 * the expression. In this case, the content must be empty.
659 */
660 if (inst->children != NULL) {
661 xsltGenericError(xsltGenericErrorContext,
662 "func:result content must be empty if it"
663 " has a select attribute\n");
664 data->error = 1;
665 return;
666 }
667 oldXPNsList = ctxt->xpathCtxt->namespaces;
668 oldXPNsNr = ctxt->xpathCtxt->nsNr;
669 oldXPContextNode = ctxt->xpathCtxt->node;
670
671 ctxt->xpathCtxt->namespaces = comp->nsList;
672 ctxt->xpathCtxt->nsNr = comp->nsNr;
673
674 ret = xmlXPathCompiledEval(comp->select, ctxt->xpathCtxt);
675
676 ctxt->xpathCtxt->node = oldXPContextNode;
677 ctxt->xpathCtxt->nsNr = oldXPNsNr;
678 ctxt->xpathCtxt->namespaces = oldXPNsList;
679
680 if (ret == NULL) {
681 xsltGenericError(xsltGenericErrorContext,
682 "exsltFuncResultElem: ret == NULL\n");
683 return;
684 }
685 /*
686 * Mark it as a function result in order to avoid garbage
687 * collecting of tree fragments before the function exits.
688 */
689 xsltExtensionInstructionResultRegister(ctxt, ret);
690 } else if (inst->children != NULL) {
691 /* If the func:result element does not have a select attribute
692 * and has non-empty content (i.e. the func:result element has
693 * one or more child nodes), then the content of the
694 * func:result element specifies the value.
695 */
696 xmlNodePtr oldInsert;
697 xmlDocPtr container;
698
699 container = xsltCreateRVT(ctxt);
700 if (container == NULL) {
701 xsltGenericError(xsltGenericErrorContext,
702 "exsltFuncResultElem: out of memory\n");
703 data->error = 1;
704 return;
705 }
706 xsltRegisterLocalRVT(ctxt, container);
707
708 oldInsert = ctxt->insert;
709 ctxt->insert = (xmlNodePtr) container;
710 xsltApplyOneTemplate (ctxt, ctxt->xpathCtxt->node,
711 inst->children, NULL, NULL);
712 ctxt->insert = oldInsert;
713
714 ret = xmlXPathNewValueTree((xmlNodePtr) container);
715 if (ret == NULL) {
716 xsltGenericError(xsltGenericErrorContext,
717 "exsltFuncResultElem: ret == NULL\n");
718 data->error = 1;
719 } else {
720 ret->boolval = 0; /* Freeing is not handled there anymore */
721 /*
722 * Mark it as a function result in order to avoid garbage
723 * collecting of tree fragments before the function exits.
724 */
725 xsltExtensionInstructionResultRegister(ctxt, ret);
726 }
727 } else {
728 /* If the func:result element has empty content and does not
729 * have a select attribute, then the returned value is an
730 * empty string.
731 */
732 ret = xmlXPathNewCString("");
733 }
734 data->result = ret;
735}
736
737/**
738 * exsltFuncRegister:
739 *
740 * Registers the EXSLT - Functions module
741 */
742void
743exsltFuncRegister (void) {
744 xsltRegisterExtModuleFull (EXSLT_FUNCTIONS_NAMESPACE,
745 (xsltExtInitFunction) exsltFuncInit,
746 (xsltExtShutdownFunction) exsltFuncShutdown,
747 (xsltStyleExtInitFunction) exsltFuncStyleInit,
748 (xsltStyleExtShutdownFunction) exsltFuncStyleShutdown);
749
750 xsltRegisterExtModuleTopLevel ((const xmlChar *) "function",
751 EXSLT_FUNCTIONS_NAMESPACE,
752 exsltFuncFunctionComp);
753 xsltRegisterExtModuleElement ((const xmlChar *) "result",
754 EXSLT_FUNCTIONS_NAMESPACE,
755 (xsltPreComputeFunction)exsltFuncResultComp,
756 (xsltTransformFunction) exsltFuncResultElem);
757}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette