VirtualBox

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

最後變更 在這個檔案從7296是 7296,由 vboxsync 提交於 17 年 前

Added libxslt-1.1.22 sources.

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

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