Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(153)

Side by Side Diff: third_party/libxslt/libexslt/functions.c

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

Powered by Google App Engine
This is Rietveld 408576698