VirtualBox

source: vbox/trunk/src/libs/libxslt-1.1.22/libxslt/preproc.c@ 11537

Last change on this file since 11537 was 7296, checked in by vboxsync, 17 years ago

Added libxslt-1.1.22 sources.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Revision Author Id
File size: 63.8 KB
Line 
1/*
2 * preproc.c: Preprocessing of style operations
3 *
4 * References:
5 * http://www.w3.org/TR/1999/REC-xslt-19991116
6 *
7 * Michael Kay "XSLT Programmer's Reference" pp 637-643
8 * Writing Multiple Output Files
9 *
10 * XSLT-1.1 Working Draft
11 * http://www.w3.org/TR/xslt11#multiple-output
12 *
13 * See Copyright for the status of this software.
14 *
15 * [email protected]
16 */
17
18#define IN_LIBXSLT
19#include "libxslt.h"
20
21#include <string.h>
22
23#include <libxml/xmlmemory.h>
24#include <libxml/parser.h>
25#include <libxml/tree.h>
26#include <libxml/valid.h>
27#include <libxml/hash.h>
28#include <libxml/uri.h>
29#include <libxml/encoding.h>
30#include <libxml/xmlerror.h>
31#include "xslt.h"
32#include "xsltutils.h"
33#include "xsltInternals.h"
34#include "transform.h"
35#include "templates.h"
36#include "variables.h"
37#include "numbersInternals.h"
38#include "preproc.h"
39#include "extra.h"
40#include "imports.h"
41#include "extensions.h"
42
43#ifdef WITH_XSLT_DEBUG
44#define WITH_XSLT_DEBUG_PREPROC
45#endif
46
47const xmlChar *xsltExtMarker = (const xmlChar *) "Extension Element";
48
49/************************************************************************
50 * *
51 * Grammar checks *
52 * *
53 ************************************************************************/
54
55#ifdef XSLT_REFACTORED
56 /*
57 * Grammar checks are now performed in xslt.c.
58 */
59#else
60/**
61 * xsltCheckTopLevelElement:
62 * @style: the XSLT stylesheet
63 * @inst: the XSLT instruction
64 * @err: raise an error or not
65 *
66 * Check that the instruction is instanciated as a top level element.
67 *
68 * Returns -1 in case of error, 0 if failed and 1 in case of success
69 */
70static int
71xsltCheckTopLevelElement(xsltStylesheetPtr style, xmlNodePtr inst, int err) {
72 xmlNodePtr parent;
73 if ((style == NULL) || (inst == NULL) || (inst->ns == NULL))
74 return(-1);
75
76 parent = inst->parent;
77 if (parent == NULL) {
78 if (err) {
79 xsltTransformError(NULL, style, inst,
80 "internal problem: element has no parent\n");
81 style->errors++;
82 }
83 return(0);
84 }
85 if ((parent->ns == NULL) ||
86 ((parent->ns != inst->ns) &&
87 (!xmlStrEqual(parent->ns->href, inst->ns->href))) ||
88 ((!xmlStrEqual(parent->name, BAD_CAST "stylesheet")) &&
89 (!xmlStrEqual(parent->name, BAD_CAST "transform")))) {
90 if (err) {
91 xsltTransformError(NULL, style, inst,
92 "element %s only allowed as child of stylesheet\n",
93 inst->name);
94 style->errors++;
95 }
96 return(0);
97 }
98 return(1);
99}
100
101/**
102 * xsltCheckInstructionElement:
103 * @style: the XSLT stylesheet
104 * @inst: the XSLT instruction
105 *
106 * Check that the instruction is instanciated as an instruction element.
107 */
108static void
109xsltCheckInstructionElement(xsltStylesheetPtr style, xmlNodePtr inst) {
110 xmlNodePtr parent;
111 int has_ext;
112
113 if ((style == NULL) || (inst == NULL) || (inst->ns == NULL) ||
114 (style->literal_result))
115 return;
116
117 has_ext = (style->extInfos != NULL);
118
119 parent = inst->parent;
120 if (parent == NULL) {
121 xsltTransformError(NULL, style, inst,
122 "internal problem: element has no parent\n");
123 style->errors++;
124 return;
125 }
126 while ((parent != NULL) && (parent->type != XML_DOCUMENT_NODE)) {
127 if (((parent->ns == inst->ns) ||
128 ((parent->ns != NULL) &&
129 (xmlStrEqual(parent->ns->href, inst->ns->href)))) &&
130 ((xmlStrEqual(parent->name, BAD_CAST "template")) ||
131 (xmlStrEqual(parent->name, BAD_CAST "param")) ||
132 (xmlStrEqual(parent->name, BAD_CAST "attribute")) ||
133 (xmlStrEqual(parent->name, BAD_CAST "variable")))) {
134 return;
135 }
136
137 /*
138 * if we are within an extension element all bets are off
139 * about the semantic there e.g. xsl:param within func:function
140 */
141 if ((has_ext) && (parent->ns != NULL) &&
142 (xmlHashLookup(style->extInfos, parent->ns->href) != NULL))
143 return;
144
145 parent = parent->parent;
146 }
147 xsltTransformError(NULL, style, inst,
148 "element %s only allowed within a template, variable or param\n",
149 inst->name);
150 style->errors++;
151}
152
153/**
154 * xsltCheckParentElement:
155 * @style: the XSLT stylesheet
156 * @inst: the XSLT instruction
157 * @allow1: allowed parent1
158 * @allow2: allowed parent2
159 *
160 * Check that the instruction is instanciated as the childre of one of the
161 * possible parents.
162 */
163static void
164xsltCheckParentElement(xsltStylesheetPtr style, xmlNodePtr inst,
165 const xmlChar *allow1, const xmlChar *allow2) {
166 xmlNodePtr parent;
167
168 if ((style == NULL) || (inst == NULL) || (inst->ns == NULL) ||
169 (style->literal_result))
170 return;
171
172 parent = inst->parent;
173 if (parent == NULL) {
174 xsltTransformError(NULL, style, inst,
175 "internal problem: element has no parent\n");
176 style->errors++;
177 return;
178 }
179 if (((parent->ns == inst->ns) ||
180 ((parent->ns != NULL) &&
181 (xmlStrEqual(parent->ns->href, inst->ns->href)))) &&
182 ((xmlStrEqual(parent->name, allow1)) ||
183 (xmlStrEqual(parent->name, allow2)))) {
184 return;
185 }
186
187 if (style->extInfos != NULL) {
188 while ((parent != NULL) && (parent->type != XML_DOCUMENT_NODE)) {
189 /*
190 * if we are within an extension element all bets are off
191 * about the semantic there e.g. xsl:param within func:function
192 */
193 if ((parent->ns != NULL) &&
194 (xmlHashLookup(style->extInfos, parent->ns->href) != NULL))
195 return;
196
197 parent = parent->parent;
198 }
199 }
200 xsltTransformError(NULL, style, inst,
201 "element %s is not allowed within that context\n",
202 inst->name);
203 style->errors++;
204}
205#endif
206
207/************************************************************************
208 * *
209 * handling of precomputed data *
210 * *
211 ************************************************************************/
212
213/**
214 * xsltNewStylePreComp:
215 * @style: the XSLT stylesheet
216 * @type: the construct type
217 *
218 * Create a new XSLT Style precomputed block
219 *
220 * Returns the newly allocated specialized structure
221 * or NULL in case of error
222 */
223static xsltStylePreCompPtr
224xsltNewStylePreComp(xsltStylesheetPtr style, xsltStyleType type) {
225 xsltStylePreCompPtr cur;
226#ifdef XSLT_REFACTORED
227 size_t size;
228#endif
229
230 if (style == NULL)
231 return(NULL);
232
233#ifdef XSLT_REFACTORED
234 /*
235 * URGENT TODO: Use specialized factory functions in order
236 * to avoid this ugliness.
237 */
238 switch (type) {
239 case XSLT_FUNC_COPY:
240 size = sizeof(xsltStyleItemCopy); break;
241 case XSLT_FUNC_SORT:
242 size = sizeof(xsltStyleItemSort); break;
243 case XSLT_FUNC_TEXT:
244 size = sizeof(xsltStyleItemText); break;
245 case XSLT_FUNC_ELEMENT:
246 size = sizeof(xsltStyleItemElement); break;
247 case XSLT_FUNC_ATTRIBUTE:
248 size = sizeof(xsltStyleItemAttribute); break;
249 case XSLT_FUNC_COMMENT:
250 size = sizeof(xsltStyleItemComment); break;
251 case XSLT_FUNC_PI:
252 size = sizeof(xsltStyleItemPI); break;
253 case XSLT_FUNC_COPYOF:
254 size = sizeof(xsltStyleItemCopyOf); break;
255 case XSLT_FUNC_VALUEOF:
256 size = sizeof(xsltStyleItemValueOf); break;;
257 case XSLT_FUNC_NUMBER:
258 size = sizeof(xsltStyleItemNumber); break;
259 case XSLT_FUNC_APPLYIMPORTS:
260 size = sizeof(xsltStyleItemApplyImports); break;
261 case XSLT_FUNC_CALLTEMPLATE:
262 size = sizeof(xsltStyleItemCallTemplate); break;
263 case XSLT_FUNC_APPLYTEMPLATES:
264 size = sizeof(xsltStyleItemApplyTemplates); break;
265 case XSLT_FUNC_CHOOSE:
266 size = sizeof(xsltStyleItemChoose); break;
267 case XSLT_FUNC_IF:
268 size = sizeof(xsltStyleItemIf); break;
269 case XSLT_FUNC_FOREACH:
270 size = sizeof(xsltStyleItemForEach); break;
271 case XSLT_FUNC_DOCUMENT:
272 size = sizeof(xsltStyleItemDocument); break;
273 case XSLT_FUNC_WITHPARAM:
274 size = sizeof(xsltStyleItemWithParam); break;
275 case XSLT_FUNC_PARAM:
276 size = sizeof(xsltStyleItemParam); break;
277 case XSLT_FUNC_VARIABLE:
278 size = sizeof(xsltStyleItemVariable); break;
279 case XSLT_FUNC_WHEN:
280 size = sizeof(xsltStyleItemWhen); break;
281 case XSLT_FUNC_OTHERWISE:
282 size = sizeof(xsltStyleItemOtherwise); break;
283 default:
284 xsltTransformError(NULL, style, NULL,
285 "xsltNewStylePreComp : invalid type %d\n", type);
286 style->errors++;
287 return(NULL);
288 }
289 /*
290 * Create the structure.
291 */
292 cur = (xsltStylePreCompPtr) xmlMalloc(size);
293 if (cur == NULL) {
294 xsltTransformError(NULL, style, NULL,
295 "xsltNewStylePreComp : malloc failed\n");
296 style->errors++;
297 return(NULL);
298 }
299 memset(cur, 0, size);
300
301#else /* XSLT_REFACTORED */
302 /*
303 * Old behaviour.
304 */
305 cur = (xsltStylePreCompPtr) xmlMalloc(sizeof(xsltStylePreComp));
306 if (cur == NULL) {
307 xsltTransformError(NULL, style, NULL,
308 "xsltNewStylePreComp : malloc failed\n");
309 style->errors++;
310 return(NULL);
311 }
312 memset(cur, 0, sizeof(xsltStylePreComp));
313#endif /* XSLT_REFACTORED */
314
315 /*
316 * URGENT TODO: Better to move this to spezialized factory functions.
317 */
318 cur->type = type;
319 switch (cur->type) {
320 case XSLT_FUNC_COPY:
321 cur->func = (xsltTransformFunction) xsltCopy;break;
322 case XSLT_FUNC_SORT:
323 cur->func = (xsltTransformFunction) xsltSort;break;
324 case XSLT_FUNC_TEXT:
325 cur->func = (xsltTransformFunction) xsltText;break;
326 case XSLT_FUNC_ELEMENT:
327 cur->func = (xsltTransformFunction) xsltElement;break;
328 case XSLT_FUNC_ATTRIBUTE:
329 cur->func = (xsltTransformFunction) xsltAttribute;break;
330 case XSLT_FUNC_COMMENT:
331 cur->func = (xsltTransformFunction) xsltComment;break;
332 case XSLT_FUNC_PI:
333 cur->func = (xsltTransformFunction) xsltProcessingInstruction;
334 break;
335 case XSLT_FUNC_COPYOF:
336 cur->func = (xsltTransformFunction) xsltCopyOf;break;
337 case XSLT_FUNC_VALUEOF:
338 cur->func = (xsltTransformFunction) xsltValueOf;break;
339 case XSLT_FUNC_NUMBER:
340 cur->func = (xsltTransformFunction) xsltNumber;break;
341 case XSLT_FUNC_APPLYIMPORTS:
342 cur->func = (xsltTransformFunction) xsltApplyImports;break;
343 case XSLT_FUNC_CALLTEMPLATE:
344 cur->func = (xsltTransformFunction) xsltCallTemplate;break;
345 case XSLT_FUNC_APPLYTEMPLATES:
346 cur->func = (xsltTransformFunction) xsltApplyTemplates;break;
347 case XSLT_FUNC_CHOOSE:
348 cur->func = (xsltTransformFunction) xsltChoose;break;
349 case XSLT_FUNC_IF:
350 cur->func = (xsltTransformFunction) xsltIf;break;
351 case XSLT_FUNC_FOREACH:
352 cur->func = (xsltTransformFunction) xsltForEach;break;
353 case XSLT_FUNC_DOCUMENT:
354 cur->func = (xsltTransformFunction) xsltDocumentElem;break;
355 case XSLT_FUNC_WITHPARAM:
356 case XSLT_FUNC_PARAM:
357 case XSLT_FUNC_VARIABLE:
358 case XSLT_FUNC_WHEN:
359 break;
360 default:
361 if (cur->func == NULL) {
362 xsltTransformError(NULL, style, NULL,
363 "xsltNewStylePreComp : no function for type %d\n", type);
364 style->errors++;
365 }
366 }
367 cur->next = style->preComps;
368 style->preComps = (xsltElemPreCompPtr) cur;
369
370 return(cur);
371}
372
373/**
374 * xsltFreeStylePreComp:
375 * @comp: an XSLT Style precomputed block
376 *
377 * Free up the memory allocated by @comp
378 */
379static void
380xsltFreeStylePreComp(xsltStylePreCompPtr comp) {
381 if (comp == NULL)
382 return;
383#ifdef XSLT_REFACTORED
384 /*
385 * URGENT TODO: Implement destructors.
386 */
387 switch (comp->type) {
388 case XSLT_FUNC_LITERAL_RESULT_ELEMENT:
389 break;
390 case XSLT_FUNC_COPY:
391 break;
392 case XSLT_FUNC_SORT: {
393 xsltStyleItemSortPtr item = (xsltStyleItemSortPtr) comp;
394 if (item->comp != NULL)
395 xmlXPathFreeCompExpr(item->comp);
396 }
397 break;
398 case XSLT_FUNC_TEXT:
399 break;
400 case XSLT_FUNC_ELEMENT:
401 break;
402 case XSLT_FUNC_ATTRIBUTE:
403 break;
404 case XSLT_FUNC_COMMENT:
405 break;
406 case XSLT_FUNC_PI:
407 break;
408 case XSLT_FUNC_COPYOF: {
409 xsltStyleItemCopyOfPtr item = (xsltStyleItemCopyOfPtr) comp;
410 if (item->comp != NULL)
411 xmlXPathFreeCompExpr(item->comp);
412 }
413 break;
414 case XSLT_FUNC_VALUEOF: {
415 xsltStyleItemValueOfPtr item = (xsltStyleItemValueOfPtr) comp;
416 if (item->comp != NULL)
417 xmlXPathFreeCompExpr(item->comp);
418 }
419 break;
420 case XSLT_FUNC_NUMBER:
421 break;
422 case XSLT_FUNC_APPLYIMPORTS:
423 break;
424 case XSLT_FUNC_CALLTEMPLATE:
425 break;
426 case XSLT_FUNC_APPLYTEMPLATES: {
427 xsltStyleItemApplyTemplatesPtr item =
428 (xsltStyleItemApplyTemplatesPtr) comp;
429 if (item->comp != NULL)
430 xmlXPathFreeCompExpr(item->comp);
431 }
432 break;
433 case XSLT_FUNC_CHOOSE:
434 break;
435 case XSLT_FUNC_IF: {
436 xsltStyleItemIfPtr item = (xsltStyleItemIfPtr) comp;
437 if (item->comp != NULL)
438 xmlXPathFreeCompExpr(item->comp);
439 }
440 break;
441 case XSLT_FUNC_FOREACH: {
442 xsltStyleItemForEachPtr item =
443 (xsltStyleItemForEachPtr) comp;
444 if (item->comp != NULL)
445 xmlXPathFreeCompExpr(item->comp);
446 }
447 break;
448 case XSLT_FUNC_DOCUMENT:
449 break;
450 case XSLT_FUNC_WITHPARAM: {
451 xsltStyleItemWithParamPtr item =
452 (xsltStyleItemWithParamPtr) comp;
453 if (item->comp != NULL)
454 xmlXPathFreeCompExpr(item->comp);
455 }
456 break;
457 case XSLT_FUNC_PARAM: {
458 xsltStyleItemParamPtr item =
459 (xsltStyleItemParamPtr) comp;
460 if (item->comp != NULL)
461 xmlXPathFreeCompExpr(item->comp);
462 }
463 break;
464 case XSLT_FUNC_VARIABLE: {
465 xsltStyleItemVariablePtr item =
466 (xsltStyleItemVariablePtr) comp;
467 if (item->comp != NULL)
468 xmlXPathFreeCompExpr(item->comp);
469 }
470 break;
471 case XSLT_FUNC_WHEN: {
472 xsltStyleItemWhenPtr item =
473 (xsltStyleItemWhenPtr) comp;
474 if (item->comp != NULL)
475 xmlXPathFreeCompExpr(item->comp);
476 }
477 break;
478 case XSLT_FUNC_OTHERWISE:
479 case XSLT_FUNC_FALLBACK:
480 case XSLT_FUNC_MESSAGE:
481 case XSLT_FUNC_INCLUDE:
482 case XSLT_FUNC_ATTRSET:
483
484 break;
485 default:
486 /* TODO: Raise error. */
487 break;
488 }
489#else
490 if (comp->comp != NULL)
491 xmlXPathFreeCompExpr(comp->comp);
492 if (comp->nsList != NULL)
493 xmlFree(comp->nsList);
494#endif
495
496 xmlFree(comp);
497}
498
499
500/************************************************************************
501 * *
502 * XSLT-1.1 extensions *
503 * *
504 ************************************************************************/
505
506/**
507 * xsltDocumentComp:
508 * @style: the XSLT stylesheet
509 * @inst: the instruction in the stylesheet
510 * @function: unused
511 *
512 * Pre process an XSLT-1.1 document element
513 *
514 * Returns a precompiled data structure for the element
515 */
516xsltElemPreCompPtr
517xsltDocumentComp(xsltStylesheetPtr style, xmlNodePtr inst,
518 xsltTransformFunction function ATTRIBUTE_UNUSED) {
519#ifdef XSLT_REFACTORED
520 xsltStyleItemDocumentPtr comp;
521#else
522 xsltStylePreCompPtr comp;
523#endif
524 const xmlChar *filename = NULL;
525
526 /*
527 * As of 2006-03-30, this function is currently defined in Libxslt
528 * to be used for:
529 * (in libxslt/extra.c)
530 * "output" in XSLT_SAXON_NAMESPACE
531 * "write" XSLT_XALAN_NAMESPACE
532 * "document" XSLT_XT_NAMESPACE
533 * "document" XSLT_NAMESPACE (from the abandoned old working
534 * draft of XSLT 1.1)
535 * (in libexslt/common.c)
536 * "document" in EXSLT_COMMON_NAMESPACE
537 */
538#ifdef XSLT_REFACTORED
539 comp = (xsltStyleItemDocumentPtr)
540 xsltNewStylePreComp(style, XSLT_FUNC_DOCUMENT);
541#else
542 comp = xsltNewStylePreComp(style, XSLT_FUNC_DOCUMENT);
543#endif
544
545 if (comp == NULL)
546 return (NULL);
547 comp->inst = inst;
548 comp->ver11 = 0;
549
550 if (xmlStrEqual(inst->name, (const xmlChar *) "output")) {
551#ifdef WITH_XSLT_DEBUG_EXTRA
552 xsltGenericDebug(xsltGenericDebugContext,
553 "Found saxon:output extension\n");
554#endif
555 /*
556 * The element "output" is in the namespace XSLT_SAXON_NAMESPACE
557 * (http://icl.com/saxon)
558 * The @file is in no namespace; it is an AVT.
559 * (http://www.computerwizards.com/saxon/doc/extensions.html#saxon:output)
560 *
561 * TODO: Do we need not to check the namespace here?
562 */
563 filename = xsltEvalStaticAttrValueTemplate(style, inst,
564 (const xmlChar *)"file",
565 NULL, &comp->has_filename);
566 } else if (xmlStrEqual(inst->name, (const xmlChar *) "write")) {
567#ifdef WITH_XSLT_DEBUG_EXTRA
568 xsltGenericDebug(xsltGenericDebugContext,
569 "Found xalan:write extension\n");
570#endif
571 /* the filename need to be interpreted */
572 /*
573 * TODO: Is "filename need to be interpreted" meant to be a todo?
574 * Where will be the filename of xalan:write be processed?
575 *
576 * TODO: Do we need not to check the namespace here?
577 * The extension ns is "http://xml.apache.org/xalan/redirect".
578 * See http://xml.apache.org/xalan-j/extensionslib.html.
579 */
580 } else if (xmlStrEqual(inst->name, (const xmlChar *) "document")) {
581 if (inst->ns != NULL) {
582 if (xmlStrEqual(inst->ns->href, XSLT_NAMESPACE)) {
583 /*
584 * Mark the instruction as being of
585 * XSLT version 1.1 (abandoned).
586 */
587 comp->ver11 = 1;
588#ifdef WITH_XSLT_DEBUG_EXTRA
589 xsltGenericDebug(xsltGenericDebugContext,
590 "Found xslt11:document construct\n");
591#endif
592 } else {
593 if (xmlStrEqual(inst->ns->href,
594 (const xmlChar *)"http://exslt.org/common")) {
595 /* EXSLT. */
596#ifdef WITH_XSLT_DEBUG_EXTRA
597 xsltGenericDebug(xsltGenericDebugContext,
598 "Found exslt:document extension\n");
599#endif
600 } else if (xmlStrEqual(inst->ns->href, XSLT_XT_NAMESPACE)) {
601 /* James Clark's XT. */
602#ifdef WITH_XSLT_DEBUG_EXTRA
603 xsltGenericDebug(xsltGenericDebugContext,
604 "Found xt:document extension\n");
605#endif
606 }
607 }
608 }
609 /*
610 * The element "document" is used in conjunction with the
611 * following namespaces:
612 *
613 * 1) XSLT_NAMESPACE (http://www.w3.org/1999/XSL/Transform version 1.1)
614 * <!ELEMENT xsl:document %template;>
615 * <!ATTLIST xsl:document
616 * href %avt; #REQUIRED
617 * @href is an AVT
618 * IMPORTANT: xsl:document was in the abandoned XSLT 1.1 draft,
619 * it was removed and isn't available in XSLT 1.1 anymore.
620 * In XSLT 2.0 it was renamed to xsl:result-document.
621 *
622 * All other attributes are identical to the attributes
623 * on xsl:output
624 *
625 * 2) EXSLT_COMMON_NAMESPACE (http://exslt.org/common)
626 * <exsl:document
627 * href = { uri-reference }
628 * TODO: is @href is an AVT?
629 *
630 * 3) XSLT_XT_NAMESPACE (http://www.jclark.com/xt)
631 * Example: <xt:document method="xml" href="myFile.xml">
632 * TODO: is @href is an AVT?
633 *
634 * In all cases @href is in no namespace.
635 */
636 filename = xsltEvalStaticAttrValueTemplate(style, inst,
637 (const xmlChar *)"href", NULL, &comp->has_filename);
638 }
639 if (!comp->has_filename) {
640 goto error;
641 }
642 comp->filename = filename;
643
644error:
645 return ((xsltElemPreCompPtr) comp);
646}
647
648/************************************************************************
649 * *
650 * Most of the XSLT-1.0 transformations *
651 * *
652 ************************************************************************/
653
654/**
655 * xsltSortComp:
656 * @style: the XSLT stylesheet
657 * @inst: the xslt sort node
658 *
659 * Process the xslt sort node on the source node
660 */
661static void
662xsltSortComp(xsltStylesheetPtr style, xmlNodePtr inst) {
663#ifdef XSLT_REFACTORED
664 xsltStyleItemSortPtr comp;
665#else
666 xsltStylePreCompPtr comp;
667#endif
668 if ((style == NULL) || (inst == NULL))
669 return;
670
671#ifdef XSLT_REFACTORED
672 comp = (xsltStyleItemSortPtr) xsltNewStylePreComp(style, XSLT_FUNC_SORT);
673#else
674 comp = xsltNewStylePreComp(style, XSLT_FUNC_SORT);
675#endif
676
677 if (comp == NULL)
678 return;
679 inst->psvi = comp;
680 comp->inst = inst;
681
682 comp->stype = xsltEvalStaticAttrValueTemplate(style, inst,
683 (const xmlChar *)"data-type",
684 NULL, &comp->has_stype);
685 if (comp->stype != NULL) {
686 if (xmlStrEqual(comp->stype, (const xmlChar *) "text"))
687 comp->number = 0;
688 else if (xmlStrEqual(comp->stype, (const xmlChar *) "number"))
689 comp->number = 1;
690 else {
691 xsltTransformError(NULL, style, inst,
692 "xsltSortComp: no support for data-type = %s\n", comp->stype);
693 comp->number = 0; /* use default */
694 if (style != NULL) style->warnings++;
695 }
696 }
697 comp->order = xsltEvalStaticAttrValueTemplate(style, inst,
698 (const xmlChar *)"order",
699 NULL, &comp->has_order);
700 if (comp->order != NULL) {
701 if (xmlStrEqual(comp->order, (const xmlChar *) "ascending"))
702 comp->descending = 0;
703 else if (xmlStrEqual(comp->order, (const xmlChar *) "descending"))
704 comp->descending = 1;
705 else {
706 xsltTransformError(NULL, style, inst,
707 "xsltSortComp: invalid value %s for order\n", comp->order);
708 comp->descending = 0; /* use default */
709 if (style != NULL) style->warnings++;
710 }
711 }
712 comp->case_order = xsltEvalStaticAttrValueTemplate(style, inst,
713 (const xmlChar *)"case-order",
714 NULL, &comp->has_use);
715 if (comp->case_order != NULL) {
716 if (xmlStrEqual(comp->case_order, (const xmlChar *) "upper-first"))
717 comp->lower_first = 0;
718 else if (xmlStrEqual(comp->case_order, (const xmlChar *) "lower-first"))
719 comp->lower_first = 1;
720 else {
721 xsltTransformError(NULL, style, inst,
722 "xsltSortComp: invalid value %s for order\n", comp->order);
723 comp->lower_first = 0; /* use default */
724 if (style != NULL) style->warnings++;
725 }
726 }
727
728 comp->lang = xsltEvalStaticAttrValueTemplate(style, inst,
729 (const xmlChar *)"lang",
730 NULL, &comp->has_lang);
731
732 comp->select = xsltGetCNsProp(style, inst,(const xmlChar *)"select", XSLT_NAMESPACE);
733 if (comp->select == NULL) {
734 /*
735 * The default value of the select attribute is ., which will
736 * cause the string-value of the current node to be used as
737 * the sort key.
738 */
739 comp->select = xmlDictLookup(style->dict, BAD_CAST ".", 1);
740 }
741 comp->comp = xsltXPathCompile(style, comp->select);
742 if (comp->comp == NULL) {
743 xsltTransformError(NULL, style, inst,
744 "xsltSortComp: could not compile select expression '%s'\n",
745 comp->select);
746 if (style != NULL) style->errors++;
747 }
748 if (inst->children != NULL) {
749 xsltTransformError(NULL, style, inst,
750 "xsl:sort : is not empty\n");
751 if (style != NULL) style->errors++;
752 }
753}
754
755/**
756 * xsltCopyComp:
757 * @style: the XSLT stylesheet
758 * @inst: the xslt copy node
759 *
760 * Process the xslt copy node on the source node
761 */
762static void
763xsltCopyComp(xsltStylesheetPtr style, xmlNodePtr inst) {
764#ifdef XSLT_REFACTORED
765 xsltStyleItemCopyPtr comp;
766#else
767 xsltStylePreCompPtr comp;
768#endif
769
770 if ((style == NULL) || (inst == NULL))
771 return;
772#ifdef XSLT_REFACTORED
773 comp = (xsltStyleItemCopyPtr) xsltNewStylePreComp(style, XSLT_FUNC_COPY);
774#else
775 comp = xsltNewStylePreComp(style, XSLT_FUNC_COPY);
776#endif
777
778 if (comp == NULL)
779 return;
780 inst->psvi = comp;
781 comp->inst = inst;
782
783
784 comp->use = xsltGetCNsProp(style, inst, (const xmlChar *)"use-attribute-sets",
785 XSLT_NAMESPACE);
786 if (comp->use == NULL)
787 comp->has_use = 0;
788 else
789 comp->has_use = 1;
790}
791
792#ifdef XSLT_REFACTORED
793 /* Enable if ever needed for xsl:text. */
794#else
795/**
796 * xsltTextComp:
797 * @style: an XSLT compiled stylesheet
798 * @inst: the xslt text node
799 *
800 * TODO: This function is obsolete, since xsl:text won't
801 * be compiled, but removed from the tree.
802 *
803 * Process the xslt text node on the source node
804 */
805static void
806xsltTextComp(xsltStylesheetPtr style, xmlNodePtr inst) {
807#ifdef XSLT_REFACTORED
808 xsltStyleItemTextPtr comp;
809#else
810 xsltStylePreCompPtr comp;
811#endif
812 const xmlChar *prop;
813
814 if ((style == NULL) || (inst == NULL))
815 return;
816
817#ifdef XSLT_REFACTORED
818 comp = (xsltStyleItemTextPtr) xsltNewStylePreComp(style, XSLT_FUNC_TEXT);
819#else
820 comp = xsltNewStylePreComp(style, XSLT_FUNC_TEXT);
821#endif
822 if (comp == NULL)
823 return;
824 inst->psvi = comp;
825 comp->inst = inst;
826 comp->noescape = 0;
827
828 prop = xsltGetCNsProp(style, inst,
829 (const xmlChar *)"disable-output-escaping",
830 XSLT_NAMESPACE);
831 if (prop != NULL) {
832 if (xmlStrEqual(prop, (const xmlChar *)"yes")) {
833 comp->noescape = 1;
834 } else if (!xmlStrEqual(prop,
835 (const xmlChar *)"no")){
836 xsltTransformError(NULL, style, inst,
837 "xsl:text: disable-output-escaping allows only yes or no\n");
838 if (style != NULL) style->warnings++;
839 }
840 }
841}
842#endif /* else of XSLT_REFACTORED */
843
844/**
845 * xsltElementComp:
846 * @style: an XSLT compiled stylesheet
847 * @inst: the xslt element node
848 *
849 * Process the xslt element node on the source node
850 */
851static void
852xsltElementComp(xsltStylesheetPtr style, xmlNodePtr inst) {
853#ifdef XSLT_REFACTORED
854 xsltStyleItemElementPtr comp;
855#else
856 xsltStylePreCompPtr comp;
857#endif
858
859 /*
860 * <xsl:element
861 * name = { qname }
862 * namespace = { uri-reference }
863 * use-attribute-sets = qnames>
864 * <!-- Content: template -->
865 * </xsl:element>
866 */
867 if ((style == NULL) || (inst == NULL))
868 return;
869
870#ifdef XSLT_REFACTORED
871 comp = (xsltStyleItemElementPtr) xsltNewStylePreComp(style, XSLT_FUNC_ELEMENT);
872#else
873 comp = xsltNewStylePreComp(style, XSLT_FUNC_ELEMENT);
874#endif
875
876 if (comp == NULL)
877 return;
878 inst->psvi = comp;
879 comp->inst = inst;
880
881 /*
882 * Attribute "name".
883 */
884 /*
885 * TODO: Precompile the AVT. See bug #344894.
886 */
887 comp->name = xsltEvalStaticAttrValueTemplate(style, inst,
888 (const xmlChar *)"name", NULL, &comp->has_name);
889 if (! comp->has_name) {
890 xsltTransformError(NULL, style, inst,
891 "xsl:element: The attribute 'name' is missing.\n");
892 style->errors++;
893 goto error;
894 }
895 /*
896 * Attribute "namespace".
897 */
898 /*
899 * TODO: Precompile the AVT. See bug #344894.
900 */
901 comp->ns = xsltEvalStaticAttrValueTemplate(style, inst,
902 (const xmlChar *)"namespace", NULL, &comp->has_ns);
903
904 if (comp->name != NULL) {
905 if (xmlValidateQName(comp->name, 0)) {
906 xsltTransformError(NULL, style, inst,
907 "xsl:element: The value '%s' of the attribute 'name' is "
908 "not a valid QName.\n", comp->name);
909 style->errors++;
910 } else {
911 const xmlChar *prefix = NULL, *name;
912
913 name = xsltSplitQName(style->dict, comp->name, &prefix);
914 if (comp->has_ns == 0) {
915 xmlNsPtr ns;
916
917 /*
918 * SPEC XSLT 1.0:
919 * "If the namespace attribute is not present, then the QName is
920 * expanded into an expanded-name using the namespace declarations
921 * in effect for the xsl:element element, including any default
922 * namespace declaration.
923 */
924 ns = xmlSearchNs(inst->doc, inst, prefix);
925 if (ns != NULL) {
926 comp->ns = xmlDictLookup(style->dict, ns->href, -1);
927 comp->has_ns = 1;
928#ifdef XSLT_REFACTORED
929 comp->nsPrefix = prefix;
930 comp->name = name;
931#endif
932 } else if (prefix != NULL) {
933 xsltTransformError(NULL, style, inst,
934 "xsl:element: The prefixed QName '%s' "
935 "has no namespace binding in scope in the "
936 "stylesheet; this is an error, since the namespace was "
937 "not specified by the instruction itself.\n", comp->name);
938 style->errors++;
939 }
940 }
941 if ((prefix != NULL) &&
942 (!xmlStrncasecmp(prefix, (xmlChar *)"xml", 3)))
943 {
944 /*
945 * Mark is to be skipped.
946 */
947 comp->has_name = 0;
948 }
949 }
950 }
951 /*
952 * Attribute "use-attribute-sets",
953 */
954 comp->use = xsltEvalStaticAttrValueTemplate(style, inst,
955 (const xmlChar *)"use-attribute-sets",
956 NULL, &comp->has_use);
957
958error:
959 return;
960}
961
962/**
963 * xsltAttributeComp:
964 * @style: an XSLT compiled stylesheet
965 * @inst: the xslt attribute node
966 *
967 * Process the xslt attribute node on the source node
968 */
969static void
970xsltAttributeComp(xsltStylesheetPtr style, xmlNodePtr inst) {
971#ifdef XSLT_REFACTORED
972 xsltStyleItemAttributePtr comp;
973#else
974 xsltStylePreCompPtr comp;
975#endif
976
977 /*
978 * <xsl:attribute
979 * name = { qname }
980 * namespace = { uri-reference }>
981 * <!-- Content: template -->
982 * </xsl:attribute>
983 */
984 if ((style == NULL) || (inst == NULL))
985 return;
986
987#ifdef XSLT_REFACTORED
988 comp = (xsltStyleItemAttributePtr) xsltNewStylePreComp(style,
989 XSLT_FUNC_ATTRIBUTE);
990#else
991 comp = xsltNewStylePreComp(style, XSLT_FUNC_ATTRIBUTE);
992#endif
993
994 if (comp == NULL)
995 return;
996 inst->psvi = comp;
997 comp->inst = inst;
998
999 /*
1000 * Attribute "name".
1001 */
1002 /*
1003 * TODO: Precompile the AVT. See bug #344894.
1004 */
1005 comp->name = xsltEvalStaticAttrValueTemplate(style, inst,
1006 (const xmlChar *)"name",
1007 NULL, &comp->has_name);
1008 if (! comp->has_name) {
1009 xsltTransformError(NULL, style, inst,
1010 "XSLT-attribute: The attribute 'name' is missing.\n");
1011 style->errors++;
1012 return;
1013 }
1014 /*
1015 * Attribute "namespace".
1016 */
1017 /*
1018 * TODO: Precompile the AVT. See bug #344894.
1019 */
1020 comp->ns = xsltEvalStaticAttrValueTemplate(style, inst,
1021 (const xmlChar *)"namespace",
1022 NULL, &comp->has_ns);
1023
1024 if (comp->name != NULL) {
1025 if (xmlValidateQName(comp->name, 0)) {
1026 xsltTransformError(NULL, style, inst,
1027 "xsl:attribute: The value '%s' of the attribute 'name' is "
1028 "not a valid QName.\n", comp->name);
1029 style->errors++;
1030 } else {
1031 const xmlChar *prefix = NULL, *name;
1032
1033 name = xsltSplitQName(style->dict, comp->name, &prefix);
1034 if (prefix != NULL) {
1035 if (comp->has_ns == 0) {
1036 xmlNsPtr ns;
1037
1038 /*
1039 * SPEC XSLT 1.0:
1040 * "If the namespace attribute is not present, then the
1041 * QName is expanded into an expanded-name using the
1042 * namespace declarations in effect for the xsl:element
1043 * element, including any default namespace declaration.
1044 */
1045 ns = xmlSearchNs(inst->doc, inst, prefix);
1046 if (ns != NULL) {
1047 comp->ns = xmlDictLookup(style->dict, ns->href, -1);
1048 comp->has_ns = 1;
1049#ifdef XSLT_REFACTORED
1050 comp->nsPrefix = prefix;
1051 comp->name = name;
1052#endif
1053 } else {
1054 xsltTransformError(NULL, style, inst,
1055 "xsl:attribute: The prefixed QName '%s' "
1056 "has no namespace binding in scope in the "
1057 "stylesheet; this is an error, since the "
1058 "namespace was not specified by the instruction "
1059 "itself.\n", comp->name);
1060 style->errors++;
1061 }
1062 }
1063 if (!xmlStrncasecmp(prefix, (xmlChar *) "xmlns", 5)) {
1064 /*
1065 * SPEC XSLT 1.0:
1066 * "It is an error if the string that results from
1067 * instantiating the attribute value template is not a
1068 * QName or is the string xmlns. An XSLT processor may
1069 * signal the error; if it does not signal the error,
1070 * it must recover by not adding the attribute to the
1071 * result tree."
1072 *
1073 * Reject a prefix of "xmlns". Mark to be skipped.
1074 */
1075 comp->has_name = 0;
1076
1077#ifdef WITH_XSLT_DEBUG_PARSING
1078 xsltGenericDebug(xsltGenericDebugContext,
1079 "xsltAttribute: xmlns prefix forbidden\n");
1080#endif
1081 return;
1082 }
1083
1084 }
1085 }
1086 }
1087}
1088
1089/**
1090 * xsltCommentComp:
1091 * @style: an XSLT compiled stylesheet
1092 * @inst: the xslt comment node
1093 *
1094 * Process the xslt comment node on the source node
1095 */
1096static void
1097xsltCommentComp(xsltStylesheetPtr style, xmlNodePtr inst) {
1098#ifdef XSLT_REFACTORED
1099 xsltStyleItemCommentPtr comp;
1100#else
1101 xsltStylePreCompPtr comp;
1102#endif
1103
1104 if ((style == NULL) || (inst == NULL))
1105 return;
1106
1107#ifdef XSLT_REFACTORED
1108 comp = (xsltStyleItemCommentPtr) xsltNewStylePreComp(style, XSLT_FUNC_COMMENT);
1109#else
1110 comp = xsltNewStylePreComp(style, XSLT_FUNC_COMMENT);
1111#endif
1112
1113 if (comp == NULL)
1114 return;
1115 inst->psvi = comp;
1116 comp->inst = inst;
1117}
1118
1119/**
1120 * xsltProcessingInstructionComp:
1121 * @style: an XSLT compiled stylesheet
1122 * @inst: the xslt processing-instruction node
1123 *
1124 * Process the xslt processing-instruction node on the source node
1125 */
1126static void
1127xsltProcessingInstructionComp(xsltStylesheetPtr style, xmlNodePtr inst) {
1128#ifdef XSLT_REFACTORED
1129 xsltStyleItemPIPtr comp;
1130#else
1131 xsltStylePreCompPtr comp;
1132#endif
1133
1134 if ((style == NULL) || (inst == NULL))
1135 return;
1136
1137#ifdef XSLT_REFACTORED
1138 comp = (xsltStyleItemPIPtr) xsltNewStylePreComp(style, XSLT_FUNC_PI);
1139#else
1140 comp = xsltNewStylePreComp(style, XSLT_FUNC_PI);
1141#endif
1142
1143 if (comp == NULL)
1144 return;
1145 inst->psvi = comp;
1146 comp->inst = inst;
1147
1148 comp->name = xsltEvalStaticAttrValueTemplate(style, inst,
1149 (const xmlChar *)"name",
1150 XSLT_NAMESPACE, &comp->has_name);
1151}
1152
1153/**
1154 * xsltCopyOfComp:
1155 * @style: an XSLT compiled stylesheet
1156 * @inst: the xslt copy-of node
1157 *
1158 * Process the xslt copy-of node on the source node
1159 */
1160static void
1161xsltCopyOfComp(xsltStylesheetPtr style, xmlNodePtr inst) {
1162#ifdef XSLT_REFACTORED
1163 xsltStyleItemCopyOfPtr comp;
1164#else
1165 xsltStylePreCompPtr comp;
1166#endif
1167
1168 if ((style == NULL) || (inst == NULL))
1169 return;
1170
1171#ifdef XSLT_REFACTORED
1172 comp = (xsltStyleItemCopyOfPtr) xsltNewStylePreComp(style, XSLT_FUNC_COPYOF);
1173#else
1174 comp = xsltNewStylePreComp(style, XSLT_FUNC_COPYOF);
1175#endif
1176
1177 if (comp == NULL)
1178 return;
1179 inst->psvi = comp;
1180 comp->inst = inst;
1181
1182 comp->select = xsltGetCNsProp(style, inst, (const xmlChar *)"select",
1183 XSLT_NAMESPACE);
1184 if (comp->select == NULL) {
1185 xsltTransformError(NULL, style, inst,
1186 "xsl:copy-of : select is missing\n");
1187 if (style != NULL) style->errors++;
1188 return;
1189 }
1190 comp->comp = xsltXPathCompile(style, comp->select);
1191 if (comp->comp == NULL) {
1192 xsltTransformError(NULL, style, inst,
1193 "xsl:copy-of : could not compile select expression '%s'\n",
1194 comp->select);
1195 if (style != NULL) style->errors++;
1196 }
1197}
1198
1199/**
1200 * xsltValueOfComp:
1201 * @style: an XSLT compiled stylesheet
1202 * @inst: the xslt value-of node
1203 *
1204 * Process the xslt value-of node on the source node
1205 */
1206static void
1207xsltValueOfComp(xsltStylesheetPtr style, xmlNodePtr inst) {
1208#ifdef XSLT_REFACTORED
1209 xsltStyleItemValueOfPtr comp;
1210#else
1211 xsltStylePreCompPtr comp;
1212#endif
1213 const xmlChar *prop;
1214
1215 if ((style == NULL) || (inst == NULL))
1216 return;
1217
1218#ifdef XSLT_REFACTORED
1219 comp = (xsltStyleItemValueOfPtr) xsltNewStylePreComp(style, XSLT_FUNC_VALUEOF);
1220#else
1221 comp = xsltNewStylePreComp(style, XSLT_FUNC_VALUEOF);
1222#endif
1223
1224 if (comp == NULL)
1225 return;
1226 inst->psvi = comp;
1227 comp->inst = inst;
1228
1229 prop = xsltGetCNsProp(style, inst,
1230 (const xmlChar *)"disable-output-escaping",
1231 XSLT_NAMESPACE);
1232 if (prop != NULL) {
1233 if (xmlStrEqual(prop, (const xmlChar *)"yes")) {
1234 comp->noescape = 1;
1235 } else if (!xmlStrEqual(prop,
1236 (const xmlChar *)"no")){
1237 xsltTransformError(NULL, style, inst,
1238"xsl:value-of : disable-output-escaping allows only yes or no\n");
1239 if (style != NULL) style->warnings++;
1240 }
1241 }
1242 comp->select = xsltGetCNsProp(style, inst, (const xmlChar *)"select",
1243 XSLT_NAMESPACE);
1244 if (comp->select == NULL) {
1245 xsltTransformError(NULL, style, inst,
1246 "xsl:value-of : select is missing\n");
1247 if (style != NULL) style->errors++;
1248 return;
1249 }
1250 comp->comp = xsltXPathCompile(style, comp->select);
1251 if (comp->comp == NULL) {
1252 xsltTransformError(NULL, style, inst,
1253 "xsl:value-of : could not compile select expression '%s'\n",
1254 comp->select);
1255 if (style != NULL) style->errors++;
1256 }
1257}
1258
1259static void
1260xsltGetQNameProperty(xsltStylesheetPtr style, xmlNodePtr inst,
1261 const xmlChar *propName,
1262 int mandatory,
1263 int *hasProp, const xmlChar **nsName,
1264 const xmlChar** localName)
1265{
1266 const xmlChar *prop;
1267
1268 if (nsName)
1269 *nsName = NULL;
1270 if (localName)
1271 *localName = NULL;
1272 if (hasProp)
1273 *hasProp = 0;
1274
1275 prop = xsltGetCNsProp(style, inst, propName, XSLT_NAMESPACE);
1276 if (prop == NULL) {
1277 if (mandatory) {
1278 xsltTransformError(NULL, style, inst,
1279 "The attribute '%s' is missing.\n", propName);
1280 style->errors++;
1281 return;
1282 }
1283 } else {
1284 const xmlChar *URI;
1285
1286 if (xmlValidateQName(prop, 0)) {
1287 xsltTransformError(NULL, style, inst,
1288 "The value '%s' of the attribute "
1289 "'%s' is not a valid QName.\n", prop, propName);
1290 style->errors++;
1291 return;
1292 } else {
1293 /*
1294 * @prop will be in the string dict afterwards, @URI not.
1295 */
1296 URI = xsltGetQNameURI2(style, inst, &prop);
1297 if (prop == NULL) {
1298 style->errors++;
1299 } else {
1300 *localName = prop;
1301 if (hasProp)
1302 *hasProp = 1;
1303 if (URI != NULL) {
1304 /*
1305 * Fixes bug #308441: Put the ns-name in the dict
1306 * in order to pointer compare names during XPath's
1307 * variable lookup.
1308 */
1309 if (nsName)
1310 *nsName = xmlDictLookup(style->dict, URI, -1);
1311 /* comp->has_ns = 1; */
1312 }
1313 }
1314 }
1315 }
1316 return;
1317}
1318
1319/**
1320 * xsltWithParamComp:
1321 * @style: an XSLT compiled stylesheet
1322 * @inst: the xslt with-param node
1323 *
1324 * Process the xslt with-param node on the source node
1325 * Allowed parents: xsl:call-template, xsl:apply-templates.
1326 * <xsl:with-param
1327 * name = qname
1328 * select = expression>
1329 * <!-- Content: template -->
1330 * </xsl:with-param>
1331 */
1332static void
1333xsltWithParamComp(xsltStylesheetPtr style, xmlNodePtr inst) {
1334#ifdef XSLT_REFACTORED
1335 xsltStyleItemWithParamPtr comp;
1336#else
1337 xsltStylePreCompPtr comp;
1338#endif
1339
1340 if ((style == NULL) || (inst == NULL))
1341 return;
1342
1343#ifdef XSLT_REFACTORED
1344 comp = (xsltStyleItemWithParamPtr) xsltNewStylePreComp(style, XSLT_FUNC_WITHPARAM);
1345#else
1346 comp = xsltNewStylePreComp(style, XSLT_FUNC_WITHPARAM);
1347#endif
1348
1349 if (comp == NULL)
1350 return;
1351 inst->psvi = comp;
1352 comp->inst = inst;
1353
1354 /*
1355 * Attribute "name".
1356 */
1357 xsltGetQNameProperty(style, inst, BAD_CAST "name",
1358 1, &(comp->has_name), &(comp->ns), &(comp->name));
1359 if (comp->ns)
1360 comp->has_ns = 1;
1361 /*
1362 * Attribute "select".
1363 */
1364 comp->select = xsltGetCNsProp(style, inst, (const xmlChar *)"select",
1365 XSLT_NAMESPACE);
1366 if (comp->select != NULL) {
1367 comp->comp = xsltXPathCompile(style, comp->select);
1368 if (comp->comp == NULL) {
1369 xsltTransformError(NULL, style, inst,
1370 "XSLT-with-param: Failed to compile select "
1371 "expression '%s'\n", comp->select);
1372 style->errors++;
1373 }
1374 if (inst->children != NULL) {
1375 xsltTransformError(NULL, style, inst,
1376 "XSLT-with-param: The content should be empty since "
1377 "the attribute select is present.\n");
1378 style->warnings++;
1379 }
1380 }
1381}
1382
1383/**
1384 * xsltNumberComp:
1385 * @style: an XSLT compiled stylesheet
1386 * @cur: the xslt number node
1387 *
1388 * Process the xslt number node on the source node
1389 */
1390static void
1391xsltNumberComp(xsltStylesheetPtr style, xmlNodePtr cur) {
1392#ifdef XSLT_REFACTORED
1393 xsltStyleItemNumberPtr comp;
1394#else
1395 xsltStylePreCompPtr comp;
1396#endif
1397 const xmlChar *prop;
1398
1399 if ((style == NULL) || (cur == NULL))
1400 return;
1401
1402#ifdef XSLT_REFACTORED
1403 comp = (xsltStyleItemNumberPtr) xsltNewStylePreComp(style, XSLT_FUNC_NUMBER);
1404#else
1405 comp = xsltNewStylePreComp(style, XSLT_FUNC_NUMBER);
1406#endif
1407
1408 if (comp == NULL)
1409 return;
1410 cur->psvi = comp;
1411
1412 if ((style == NULL) || (cur == NULL))
1413 return;
1414
1415 comp->numdata.doc = cur->doc;
1416 comp->numdata.node = cur;
1417 comp->numdata.value = xsltGetCNsProp(style, cur, (const xmlChar *)"value",
1418 XSLT_NAMESPACE);
1419
1420 prop = xsltEvalStaticAttrValueTemplate(style, cur,
1421 (const xmlChar *)"format",
1422 XSLT_NAMESPACE, &comp->numdata.has_format);
1423 if (comp->numdata.has_format == 0) {
1424 comp->numdata.format = xmlDictLookup(style->dict, BAD_CAST "" , 0);
1425 } else {
1426 comp->numdata.format = prop;
1427 }
1428
1429 comp->numdata.count = xsltGetCNsProp(style, cur, (const xmlChar *)"count",
1430 XSLT_NAMESPACE);
1431 comp->numdata.from = xsltGetCNsProp(style, cur, (const xmlChar *)"from",
1432 XSLT_NAMESPACE);
1433
1434 prop = xsltGetCNsProp(style, cur, (const xmlChar *)"level", XSLT_NAMESPACE);
1435 if (prop != NULL) {
1436 if (xmlStrEqual(prop, BAD_CAST("single")) ||
1437 xmlStrEqual(prop, BAD_CAST("multiple")) ||
1438 xmlStrEqual(prop, BAD_CAST("any"))) {
1439 comp->numdata.level = prop;
1440 } else {
1441 xsltTransformError(NULL, style, cur,
1442 "xsl:number : invalid value %s for level\n", prop);
1443 if (style != NULL) style->warnings++;
1444 }
1445 }
1446
1447 prop = xsltGetCNsProp(style, cur, (const xmlChar *)"lang", XSLT_NAMESPACE);
1448 if (prop != NULL) {
1449 xsltTransformError(NULL, style, cur,
1450 "xsl:number : lang attribute not implemented\n");
1451 XSLT_TODO; /* xsl:number lang attribute */
1452 }
1453
1454 prop = xsltGetCNsProp(style, cur, (const xmlChar *)"letter-value", XSLT_NAMESPACE);
1455 if (prop != NULL) {
1456 if (xmlStrEqual(prop, BAD_CAST("alphabetic"))) {
1457 xsltTransformError(NULL, style, cur,
1458 "xsl:number : letter-value 'alphabetic' not implemented\n");
1459 if (style != NULL) style->warnings++;
1460 XSLT_TODO; /* xsl:number letter-value attribute alphabetic */
1461 } else if (xmlStrEqual(prop, BAD_CAST("traditional"))) {
1462 xsltTransformError(NULL, style, cur,
1463 "xsl:number : letter-value 'traditional' not implemented\n");
1464 if (style != NULL) style->warnings++;
1465 XSLT_TODO; /* xsl:number letter-value attribute traditional */
1466 } else {
1467 xsltTransformError(NULL, style, cur,
1468 "xsl:number : invalid value %s for letter-value\n", prop);
1469 if (style != NULL) style->warnings++;
1470 }
1471 }
1472
1473 prop = xsltGetCNsProp(style, cur, (const xmlChar *)"grouping-separator",
1474 XSLT_NAMESPACE);
1475 if (prop != NULL) {
1476 comp->numdata.groupingCharacterLen = xmlStrlen(prop);
1477 comp->numdata.groupingCharacter =
1478 xsltGetUTF8Char(prop, &(comp->numdata.groupingCharacterLen));
1479 }
1480
1481 prop = xsltGetCNsProp(style, cur, (const xmlChar *)"grouping-size", XSLT_NAMESPACE);
1482 if (prop != NULL) {
1483 sscanf((char *)prop, "%d", &comp->numdata.digitsPerGroup);
1484 } else {
1485 comp->numdata.groupingCharacter = 0;
1486 }
1487
1488 /* Set default values */
1489 if (comp->numdata.value == NULL) {
1490 if (comp->numdata.level == NULL) {
1491 comp->numdata.level = xmlDictLookup(style->dict,
1492 BAD_CAST"single", 6);
1493 }
1494 }
1495
1496}
1497
1498/**
1499 * xsltApplyImportsComp:
1500 * @style: an XSLT compiled stylesheet
1501 * @inst: the xslt apply-imports node
1502 *
1503 * Process the xslt apply-imports node on the source node
1504 */
1505static void
1506xsltApplyImportsComp(xsltStylesheetPtr style, xmlNodePtr inst) {
1507#ifdef XSLT_REFACTORED
1508 xsltStyleItemApplyImportsPtr comp;
1509#else
1510 xsltStylePreCompPtr comp;
1511#endif
1512
1513 if ((style == NULL) || (inst == NULL))
1514 return;
1515
1516#ifdef XSLT_REFACTORED
1517 comp = (xsltStyleItemApplyImportsPtr) xsltNewStylePreComp(style, XSLT_FUNC_APPLYIMPORTS);
1518#else
1519 comp = xsltNewStylePreComp(style, XSLT_FUNC_APPLYIMPORTS);
1520#endif
1521
1522 if (comp == NULL)
1523 return;
1524 inst->psvi = comp;
1525 comp->inst = inst;
1526}
1527
1528/**
1529 * xsltCallTemplateComp:
1530 * @style: an XSLT compiled stylesheet
1531 * @inst: the xslt call-template node
1532 *
1533 * Process the xslt call-template node on the source node
1534 */
1535static void
1536xsltCallTemplateComp(xsltStylesheetPtr style, xmlNodePtr inst) {
1537#ifdef XSLT_REFACTORED
1538 xsltStyleItemCallTemplatePtr comp;
1539#else
1540 xsltStylePreCompPtr comp;
1541#endif
1542
1543 if ((style == NULL) || (inst == NULL))
1544 return;
1545
1546#ifdef XSLT_REFACTORED
1547 comp = (xsltStyleItemCallTemplatePtr)
1548 xsltNewStylePreComp(style, XSLT_FUNC_CALLTEMPLATE);
1549#else
1550 comp = xsltNewStylePreComp(style, XSLT_FUNC_CALLTEMPLATE);
1551#endif
1552
1553 if (comp == NULL)
1554 return;
1555 inst->psvi = comp;
1556 comp->inst = inst;
1557
1558 /*
1559 * Attribute "name".
1560 */
1561 xsltGetQNameProperty(style, inst, BAD_CAST "name",
1562 1, &(comp->has_name), &(comp->ns), &(comp->name));
1563 if (comp->ns)
1564 comp->has_ns = 1;
1565}
1566
1567/**
1568 * xsltApplyTemplatesComp:
1569 * @style: an XSLT compiled stylesheet
1570 * @inst: the apply-templates node
1571 *
1572 * Process the apply-templates node on the source node
1573 */
1574static void
1575xsltApplyTemplatesComp(xsltStylesheetPtr style, xmlNodePtr inst) {
1576#ifdef XSLT_REFACTORED
1577 xsltStyleItemApplyTemplatesPtr comp;
1578#else
1579 xsltStylePreCompPtr comp;
1580#endif
1581
1582 if ((style == NULL) || (inst == NULL))
1583 return;
1584
1585#ifdef XSLT_REFACTORED
1586 comp = (xsltStyleItemApplyTemplatesPtr)
1587 xsltNewStylePreComp(style, XSLT_FUNC_APPLYTEMPLATES);
1588#else
1589 comp = xsltNewStylePreComp(style, XSLT_FUNC_APPLYTEMPLATES);
1590#endif
1591
1592 if (comp == NULL)
1593 return;
1594 inst->psvi = comp;
1595 comp->inst = inst;
1596
1597 /*
1598 * Attribute "mode".
1599 */
1600 xsltGetQNameProperty(style, inst, BAD_CAST "mode",
1601 0, NULL, &(comp->modeURI), &(comp->mode));
1602 /*
1603 * Attribute "select".
1604 */
1605 comp->select = xsltGetCNsProp(style, inst, BAD_CAST "select",
1606 XSLT_NAMESPACE);
1607 if (comp->select != NULL) {
1608 comp->comp = xsltXPathCompile(style, comp->select);
1609 if (comp->comp == NULL) {
1610 xsltTransformError(NULL, style, inst,
1611 "XSLT-apply-templates: could not compile select "
1612 "expression '%s'\n", comp->select);
1613 style->errors++;
1614 }
1615 }
1616 /* TODO: handle (or skip) the xsl:sort and xsl:with-param */
1617}
1618
1619/**
1620 * xsltChooseComp:
1621 * @style: an XSLT compiled stylesheet
1622 * @inst: the xslt choose node
1623 *
1624 * Process the xslt choose node on the source node
1625 */
1626static void
1627xsltChooseComp(xsltStylesheetPtr style, xmlNodePtr inst) {
1628#ifdef XSLT_REFACTORED
1629 xsltStyleItemChoosePtr comp;
1630#else
1631 xsltStylePreCompPtr comp;
1632#endif
1633
1634 if ((style == NULL) || (inst == NULL))
1635 return;
1636
1637#ifdef XSLT_REFACTORED
1638 comp = (xsltStyleItemChoosePtr)
1639 xsltNewStylePreComp(style, XSLT_FUNC_CHOOSE);
1640#else
1641 comp = xsltNewStylePreComp(style, XSLT_FUNC_CHOOSE);
1642#endif
1643
1644 if (comp == NULL)
1645 return;
1646 inst->psvi = comp;
1647 comp->inst = inst;
1648}
1649
1650/**
1651 * xsltIfComp:
1652 * @style: an XSLT compiled stylesheet
1653 * @inst: the xslt if node
1654 *
1655 * Process the xslt if node on the source node
1656 */
1657static void
1658xsltIfComp(xsltStylesheetPtr style, xmlNodePtr inst) {
1659#ifdef XSLT_REFACTORED
1660 xsltStyleItemIfPtr comp;
1661#else
1662 xsltStylePreCompPtr comp;
1663#endif
1664
1665 if ((style == NULL) || (inst == NULL))
1666 return;
1667
1668#ifdef XSLT_REFACTORED
1669 comp = (xsltStyleItemIfPtr)
1670 xsltNewStylePreComp(style, XSLT_FUNC_IF);
1671#else
1672 comp = xsltNewStylePreComp(style, XSLT_FUNC_IF);
1673#endif
1674
1675 if (comp == NULL)
1676 return;
1677 inst->psvi = comp;
1678 comp->inst = inst;
1679
1680 comp->test = xsltGetCNsProp(style, inst, (const xmlChar *)"test", XSLT_NAMESPACE);
1681 if (comp->test == NULL) {
1682 xsltTransformError(NULL, style, inst,
1683 "xsl:if : test is not defined\n");
1684 if (style != NULL) style->errors++;
1685 return;
1686 }
1687 comp->comp = xsltXPathCompile(style, comp->test);
1688 if (comp->comp == NULL) {
1689 xsltTransformError(NULL, style, inst,
1690 "xsl:if : could not compile test expression '%s'\n",
1691 comp->test);
1692 if (style != NULL) style->errors++;
1693 }
1694}
1695
1696/**
1697 * xsltWhenComp:
1698 * @style: an XSLT compiled stylesheet
1699 * @inst: the xslt if node
1700 *
1701 * Process the xslt if node on the source node
1702 */
1703static void
1704xsltWhenComp(xsltStylesheetPtr style, xmlNodePtr inst) {
1705#ifdef XSLT_REFACTORED
1706 xsltStyleItemWhenPtr comp;
1707#else
1708 xsltStylePreCompPtr comp;
1709#endif
1710
1711 if ((style == NULL) || (inst == NULL))
1712 return;
1713
1714#ifdef XSLT_REFACTORED
1715 comp = (xsltStyleItemWhenPtr)
1716 xsltNewStylePreComp(style, XSLT_FUNC_WHEN);
1717#else
1718 comp = xsltNewStylePreComp(style, XSLT_FUNC_WHEN);
1719#endif
1720
1721 if (comp == NULL)
1722 return;
1723 inst->psvi = comp;
1724 comp->inst = inst;
1725
1726 comp->test = xsltGetCNsProp(style, inst, (const xmlChar *)"test", XSLT_NAMESPACE);
1727 if (comp->test == NULL) {
1728 xsltTransformError(NULL, style, inst,
1729 "xsl:when : test is not defined\n");
1730 if (style != NULL) style->errors++;
1731 return;
1732 }
1733 comp->comp = xsltXPathCompile(style, comp->test);
1734 if (comp->comp == NULL) {
1735 xsltTransformError(NULL, style, inst,
1736 "xsl:when : could not compile test expression '%s'\n",
1737 comp->test);
1738 if (style != NULL) style->errors++;
1739 }
1740}
1741
1742/**
1743 * xsltForEachComp:
1744 * @style: an XSLT compiled stylesheet
1745 * @inst: the xslt for-each node
1746 *
1747 * Process the xslt for-each node on the source node
1748 */
1749static void
1750xsltForEachComp(xsltStylesheetPtr style, xmlNodePtr inst) {
1751#ifdef XSLT_REFACTORED
1752 xsltStyleItemForEachPtr comp;
1753#else
1754 xsltStylePreCompPtr comp;
1755#endif
1756
1757 if ((style == NULL) || (inst == NULL))
1758 return;
1759
1760#ifdef XSLT_REFACTORED
1761 comp = (xsltStyleItemForEachPtr)
1762 xsltNewStylePreComp(style, XSLT_FUNC_FOREACH);
1763#else
1764 comp = xsltNewStylePreComp(style, XSLT_FUNC_FOREACH);
1765#endif
1766
1767 if (comp == NULL)
1768 return;
1769 inst->psvi = comp;
1770 comp->inst = inst;
1771
1772 comp->select = xsltGetCNsProp(style, inst, (const xmlChar *)"select",
1773 XSLT_NAMESPACE);
1774 if (comp->select == NULL) {
1775 xsltTransformError(NULL, style, inst,
1776 "xsl:for-each : select is missing\n");
1777 if (style != NULL) style->errors++;
1778 } else {
1779 comp->comp = xsltXPathCompile(style, comp->select);
1780 if (comp->comp == NULL) {
1781 xsltTransformError(NULL, style, inst,
1782 "xsl:for-each : could not compile select expression '%s'\n",
1783 comp->select);
1784 if (style != NULL) style->errors++;
1785 }
1786 }
1787 /* TODO: handle and skip the xsl:sort */
1788}
1789
1790/**
1791 * xsltVariableComp:
1792 * @style: an XSLT compiled stylesheet
1793 * @inst: the xslt variable node
1794 *
1795 * Process the xslt variable node on the source node
1796 */
1797static void
1798xsltVariableComp(xsltStylesheetPtr style, xmlNodePtr inst) {
1799#ifdef XSLT_REFACTORED
1800 xsltStyleItemVariablePtr comp;
1801#else
1802 xsltStylePreCompPtr comp;
1803#endif
1804
1805 if ((style == NULL) || (inst == NULL))
1806 return;
1807
1808#ifdef XSLT_REFACTORED
1809 comp = (xsltStyleItemVariablePtr)
1810 xsltNewStylePreComp(style, XSLT_FUNC_VARIABLE);
1811#else
1812 comp = xsltNewStylePreComp(style, XSLT_FUNC_VARIABLE);
1813#endif
1814
1815 if (comp == NULL)
1816 return;
1817
1818 inst->psvi = comp;
1819 comp->inst = inst;
1820 /*
1821 * The full template resolution can be done statically
1822 */
1823
1824 /*
1825 * Attribute "name".
1826 */
1827 xsltGetQNameProperty(style, inst, BAD_CAST "name",
1828 1, &(comp->has_name), &(comp->ns), &(comp->name));
1829 if (comp->ns)
1830 comp->has_ns = 1;
1831 /*
1832 * Attribute "select".
1833 */
1834 comp->select = xsltGetCNsProp(style, inst, (const xmlChar *)"select",
1835 XSLT_NAMESPACE);
1836 if (comp->select != NULL) {
1837 comp->comp = xsltXPathCompile(style, comp->select);
1838 if (comp->comp == NULL) {
1839 xsltTransformError(NULL, style, inst,
1840 "XSLT-variable: Failed to compile the XPath expression '%s'.\n",
1841 comp->select);
1842 style->errors++;
1843 }
1844 if (inst->children != NULL) {
1845 xsltTransformError(NULL, style, inst,
1846 "XSLT-variable: The must be no child nodes, since the "
1847 "attribute 'select' was specified.\n");
1848 style->errors++;
1849 }
1850 }
1851}
1852
1853/**
1854 * xsltParamComp:
1855 * @style: an XSLT compiled stylesheet
1856 * @inst: the xslt param node
1857 *
1858 * Process the xslt param node on the source node
1859 */
1860static void
1861xsltParamComp(xsltStylesheetPtr style, xmlNodePtr inst) {
1862#ifdef XSLT_REFACTORED
1863 xsltStyleItemParamPtr comp;
1864#else
1865 xsltStylePreCompPtr comp;
1866#endif
1867
1868 if ((style == NULL) || (inst == NULL))
1869 return;
1870
1871#ifdef XSLT_REFACTORED
1872 comp = (xsltStyleItemParamPtr)
1873 xsltNewStylePreComp(style, XSLT_FUNC_PARAM);
1874#else
1875 comp = xsltNewStylePreComp(style, XSLT_FUNC_PARAM);
1876#endif
1877
1878 if (comp == NULL)
1879 return;
1880 inst->psvi = comp;
1881 comp->inst = inst;
1882
1883 /*
1884 * Attribute "name".
1885 */
1886 xsltGetQNameProperty(style, inst, BAD_CAST "name",
1887 1, &(comp->has_name), &(comp->ns), &(comp->name));
1888 if (comp->ns)
1889 comp->has_ns = 1;
1890 /*
1891 * Attribute "select".
1892 */
1893 comp->select = xsltGetCNsProp(style, inst, (const xmlChar *)"select",
1894 XSLT_NAMESPACE);
1895 if (comp->select != NULL) {
1896 comp->comp = xsltXPathCompile(style, comp->select);
1897 if (comp->comp == NULL) {
1898 xsltTransformError(NULL, style, inst,
1899 "XSLT-param: could not compile select expression '%s'.\n",
1900 comp->select);
1901 style->errors++;
1902 }
1903 if (inst->children != NULL) {
1904 xsltTransformError(NULL, style, inst,
1905 "XSLT-param: The content should be empty since the "
1906 "attribute 'select' is present.\n");
1907 style->warnings++;
1908 }
1909 }
1910}
1911
1912/************************************************************************
1913 * *
1914 * Generic interface *
1915 * *
1916 ************************************************************************/
1917
1918/**
1919 * xsltFreeStylePreComps:
1920 * @style: an XSLT transformation context
1921 *
1922 * Free up the memory allocated by all precomputed blocks
1923 */
1924void
1925xsltFreeStylePreComps(xsltStylesheetPtr style) {
1926 xsltElemPreCompPtr cur, next;
1927
1928 if (style == NULL)
1929 return;
1930
1931 cur = style->preComps;
1932 while (cur != NULL) {
1933 next = cur->next;
1934 if (cur->type == XSLT_FUNC_EXTENSION)
1935 cur->free(cur);
1936 else
1937 xsltFreeStylePreComp((xsltStylePreCompPtr) cur);
1938 cur = next;
1939 }
1940}
1941
1942#ifdef XSLT_REFACTORED
1943
1944/**
1945 * xsltStylePreCompute:
1946 * @style: the XSLT stylesheet
1947 * @node: the element in the XSLT namespace
1948 *
1949 * Precompute an XSLT element.
1950 * This expects the type of the element to be already
1951 * set in style->compCtxt->inode->type;
1952 */
1953void
1954xsltStylePreCompute(xsltStylesheetPtr style, xmlNodePtr node) {
1955 /*
1956 * The xsltXSLTElemMarker marker was set beforehand by
1957 * the parsing mechanism for all elements in the XSLT namespace.
1958 */
1959 if (style == NULL) {
1960 if (node != NULL)
1961 node->psvi = NULL;
1962 return;
1963 }
1964 if (node == NULL)
1965 return;
1966 if (! IS_XSLT_ELEM_FAST(node))
1967 return;
1968
1969 node->psvi = NULL;
1970 if (XSLT_CCTXT(style)->inode->type != 0) {
1971 switch (XSLT_CCTXT(style)->inode->type) {
1972 case XSLT_FUNC_APPLYTEMPLATES:
1973 xsltApplyTemplatesComp(style, node);
1974 break;
1975 case XSLT_FUNC_WITHPARAM:
1976 xsltWithParamComp(style, node);
1977 break;
1978 case XSLT_FUNC_VALUEOF:
1979 xsltValueOfComp(style, node);
1980 break;
1981 case XSLT_FUNC_COPY:
1982 xsltCopyComp(style, node);
1983 break;
1984 case XSLT_FUNC_COPYOF:
1985 xsltCopyOfComp(style, node);
1986 break;
1987 case XSLT_FUNC_IF:
1988 xsltIfComp(style, node);
1989 break;
1990 case XSLT_FUNC_CHOOSE:
1991 xsltChooseComp(style, node);
1992 break;
1993 case XSLT_FUNC_WHEN:
1994 xsltWhenComp(style, node);
1995 break;
1996 case XSLT_FUNC_OTHERWISE:
1997 /* NOP yet */
1998 return;
1999 case XSLT_FUNC_FOREACH:
2000 xsltForEachComp(style, node);
2001 break;
2002 case XSLT_FUNC_APPLYIMPORTS:
2003 xsltApplyImportsComp(style, node);
2004 break;
2005 case XSLT_FUNC_ATTRIBUTE:
2006 xsltAttributeComp(style, node);
2007 break;
2008 case XSLT_FUNC_ELEMENT:
2009 xsltElementComp(style, node);
2010 break;
2011 case XSLT_FUNC_SORT:
2012 xsltSortComp(style, node);
2013 break;
2014 case XSLT_FUNC_COMMENT:
2015 xsltCommentComp(style, node);
2016 break;
2017 case XSLT_FUNC_NUMBER:
2018 xsltNumberComp(style, node);
2019 break;
2020 case XSLT_FUNC_PI:
2021 xsltProcessingInstructionComp(style, node);
2022 break;
2023 case XSLT_FUNC_CALLTEMPLATE:
2024 xsltCallTemplateComp(style, node);
2025 break;
2026 case XSLT_FUNC_PARAM:
2027 xsltParamComp(style, node);
2028 break;
2029 case XSLT_FUNC_VARIABLE:
2030 xsltVariableComp(style, node);
2031 break;
2032 case XSLT_FUNC_FALLBACK:
2033 /* NOP yet */
2034 return;
2035 case XSLT_FUNC_DOCUMENT:
2036 /* The extra one */
2037 node->psvi = (void *) xsltDocumentComp(style, node,
2038 (xsltTransformFunction) xsltDocumentElem);
2039 break;
2040 case XSLT_FUNC_MESSAGE:
2041 /* NOP yet */
2042 return;
2043 default:
2044 /*
2045 * NOTE that xsl:text, xsl:template, xsl:stylesheet,
2046 * xsl:transform, xsl:import, xsl:include are not expected
2047 * to be handed over to this function.
2048 */
2049 xsltTransformError(NULL, style, node,
2050 "Internal error: (xsltStylePreCompute) cannot handle "
2051 "the XSLT element '%s'.\n", node->name);
2052 style->errors++;
2053 return;
2054 }
2055 } else {
2056 /*
2057 * Fallback to string comparison.
2058 */
2059 if (IS_XSLT_NAME(node, "apply-templates")) {
2060 xsltApplyTemplatesComp(style, node);
2061 } else if (IS_XSLT_NAME(node, "with-param")) {
2062 xsltWithParamComp(style, node);
2063 } else if (IS_XSLT_NAME(node, "value-of")) {
2064 xsltValueOfComp(style, node);
2065 } else if (IS_XSLT_NAME(node, "copy")) {
2066 xsltCopyComp(style, node);
2067 } else if (IS_XSLT_NAME(node, "copy-of")) {
2068 xsltCopyOfComp(style, node);
2069 } else if (IS_XSLT_NAME(node, "if")) {
2070 xsltIfComp(style, node);
2071 } else if (IS_XSLT_NAME(node, "choose")) {
2072 xsltChooseComp(style, node);
2073 } else if (IS_XSLT_NAME(node, "when")) {
2074 xsltWhenComp(style, node);
2075 } else if (IS_XSLT_NAME(node, "otherwise")) {
2076 /* NOP yet */
2077 return;
2078 } else if (IS_XSLT_NAME(node, "for-each")) {
2079 xsltForEachComp(style, node);
2080 } else if (IS_XSLT_NAME(node, "apply-imports")) {
2081 xsltApplyImportsComp(style, node);
2082 } else if (IS_XSLT_NAME(node, "attribute")) {
2083 xsltAttributeComp(style, node);
2084 } else if (IS_XSLT_NAME(node, "element")) {
2085 xsltElementComp(style, node);
2086 } else if (IS_XSLT_NAME(node, "sort")) {
2087 xsltSortComp(style, node);
2088 } else if (IS_XSLT_NAME(node, "comment")) {
2089 xsltCommentComp(style, node);
2090 } else if (IS_XSLT_NAME(node, "number")) {
2091 xsltNumberComp(style, node);
2092 } else if (IS_XSLT_NAME(node, "processing-instruction")) {
2093 xsltProcessingInstructionComp(style, node);
2094 } else if (IS_XSLT_NAME(node, "call-template")) {
2095 xsltCallTemplateComp(style, node);
2096 } else if (IS_XSLT_NAME(node, "param")) {
2097 xsltParamComp(style, node);
2098 } else if (IS_XSLT_NAME(node, "variable")) {
2099 xsltVariableComp(style, node);
2100 } else if (IS_XSLT_NAME(node, "fallback")) {
2101 /* NOP yet */
2102 return;
2103 } else if (IS_XSLT_NAME(node, "document")) {
2104 /* The extra one */
2105 node->psvi = (void *) xsltDocumentComp(style, node,
2106 (xsltTransformFunction) xsltDocumentElem);
2107 } else if (IS_XSLT_NAME(node, "output")) {
2108 /* Top-level */
2109 return;
2110 } else if (IS_XSLT_NAME(node, "preserve-space")) {
2111 /* Top-level */
2112 return;
2113 } else if (IS_XSLT_NAME(node, "strip-space")) {
2114 /* Top-level */
2115 return;
2116 } else if (IS_XSLT_NAME(node, "key")) {
2117 /* Top-level */
2118 return;
2119 } else if (IS_XSLT_NAME(node, "message")) {
2120 return;
2121 } else if (IS_XSLT_NAME(node, "attribute-set")) {
2122 /* Top-level */
2123 return;
2124 } else if (IS_XSLT_NAME(node, "namespace-alias")) {
2125 /* Top-level */
2126 return;
2127 } else if (IS_XSLT_NAME(node, "decimal-format")) {
2128 /* Top-level */
2129 return;
2130 } else if (IS_XSLT_NAME(node, "include")) {
2131 /* Top-level */
2132 } else {
2133 /*
2134 * NOTE that xsl:text, xsl:template, xsl:stylesheet,
2135 * xsl:transform, xsl:import, xsl:include are not expected
2136 * to be handed over to this function.
2137 */
2138 xsltTransformError(NULL, style, node,
2139 "Internal error: (xsltStylePreCompute) cannot handle "
2140 "the XSLT element '%s'.\n", node->name);
2141 style->errors++;
2142 return;
2143 }
2144 }
2145 /*
2146 * Assign the current list of in-scope namespaces to the
2147 * item. This is needed for XPath expressions.
2148 */
2149 if (node->psvi != NULL) {
2150 ((xsltStylePreCompPtr) node->psvi)->inScopeNs =
2151 XSLT_CCTXT(style)->inode->inScopeNs;
2152 }
2153}
2154
2155#else
2156
2157/**
2158 * xsltStylePreCompute:
2159 * @style: the XSLT stylesheet
2160 * @inst: the instruction in the stylesheet
2161 *
2162 * Precompute an XSLT stylesheet element
2163 */
2164void
2165xsltStylePreCompute(xsltStylesheetPtr style, xmlNodePtr inst) {
2166 /*
2167 * URGENT TODO: Normally inst->psvi Should never be reserved here,
2168 * BUT: since if we include the same stylesheet from
2169 * multiple imports, then the stylesheet will be parsed
2170 * again. We simply must not try to compute the stylesheet again.
2171 * TODO: Get to the point where we don't need to query the
2172 * namespace- and local-name of the node, but can evaluate this
2173 * using cctxt->style->inode->category;
2174 */
2175 if (inst->psvi != NULL)
2176 return;
2177
2178 if (IS_XSLT_ELEM(inst)) {
2179 xsltStylePreCompPtr cur;
2180
2181 if (IS_XSLT_NAME(inst, "apply-templates")) {
2182 xsltCheckInstructionElement(style, inst);
2183 xsltApplyTemplatesComp(style, inst);
2184 } else if (IS_XSLT_NAME(inst, "with-param")) {
2185 xsltCheckParentElement(style, inst, BAD_CAST "apply-templates",
2186 BAD_CAST "call-template");
2187 xsltWithParamComp(style, inst);
2188 } else if (IS_XSLT_NAME(inst, "value-of")) {
2189 xsltCheckInstructionElement(style, inst);
2190 xsltValueOfComp(style, inst);
2191 } else if (IS_XSLT_NAME(inst, "copy")) {
2192 xsltCheckInstructionElement(style, inst);
2193 xsltCopyComp(style, inst);
2194 } else if (IS_XSLT_NAME(inst, "copy-of")) {
2195 xsltCheckInstructionElement(style, inst);
2196 xsltCopyOfComp(style, inst);
2197 } else if (IS_XSLT_NAME(inst, "if")) {
2198 xsltCheckInstructionElement(style, inst);
2199 xsltIfComp(style, inst);
2200 } else if (IS_XSLT_NAME(inst, "when")) {
2201 xsltCheckParentElement(style, inst, BAD_CAST "choose", NULL);
2202 xsltWhenComp(style, inst);
2203 } else if (IS_XSLT_NAME(inst, "choose")) {
2204 xsltCheckInstructionElement(style, inst);
2205 xsltChooseComp(style, inst);
2206 } else if (IS_XSLT_NAME(inst, "for-each")) {
2207 xsltCheckInstructionElement(style, inst);
2208 xsltForEachComp(style, inst);
2209 } else if (IS_XSLT_NAME(inst, "apply-imports")) {
2210 xsltCheckInstructionElement(style, inst);
2211 xsltApplyImportsComp(style, inst);
2212 } else if (IS_XSLT_NAME(inst, "attribute")) {
2213 xmlNodePtr parent = inst->parent;
2214
2215 if ((parent == NULL) || (parent->ns == NULL) ||
2216 ((parent->ns != inst->ns) &&
2217 (!xmlStrEqual(parent->ns->href, inst->ns->href))) ||
2218 (!xmlStrEqual(parent->name, BAD_CAST "attribute-set"))) {
2219 xsltCheckInstructionElement(style, inst);
2220 }
2221 xsltAttributeComp(style, inst);
2222 } else if (IS_XSLT_NAME(inst, "element")) {
2223 xsltCheckInstructionElement(style, inst);
2224 xsltElementComp(style, inst);
2225 } else if (IS_XSLT_NAME(inst, "text")) {
2226 xsltCheckInstructionElement(style, inst);
2227 xsltTextComp(style, inst);
2228 } else if (IS_XSLT_NAME(inst, "sort")) {
2229 xsltCheckParentElement(style, inst, BAD_CAST "apply-templates",
2230 BAD_CAST "for-each");
2231 xsltSortComp(style, inst);
2232 } else if (IS_XSLT_NAME(inst, "comment")) {
2233 xsltCheckInstructionElement(style, inst);
2234 xsltCommentComp(style, inst);
2235 } else if (IS_XSLT_NAME(inst, "number")) {
2236 xsltCheckInstructionElement(style, inst);
2237 xsltNumberComp(style, inst);
2238 } else if (IS_XSLT_NAME(inst, "processing-instruction")) {
2239 xsltCheckInstructionElement(style, inst);
2240 xsltProcessingInstructionComp(style, inst);
2241 } else if (IS_XSLT_NAME(inst, "call-template")) {
2242 xsltCheckInstructionElement(style, inst);
2243 xsltCallTemplateComp(style, inst);
2244 } else if (IS_XSLT_NAME(inst, "param")) {
2245 if (xsltCheckTopLevelElement(style, inst, 0) == 0)
2246 xsltCheckInstructionElement(style, inst);
2247 xsltParamComp(style, inst);
2248 } else if (IS_XSLT_NAME(inst, "variable")) {
2249 if (xsltCheckTopLevelElement(style, inst, 0) == 0)
2250 xsltCheckInstructionElement(style, inst);
2251 xsltVariableComp(style, inst);
2252 } else if (IS_XSLT_NAME(inst, "otherwise")) {
2253 xsltCheckParentElement(style, inst, BAD_CAST "choose", NULL);
2254 xsltCheckInstructionElement(style, inst);
2255 return;
2256 } else if (IS_XSLT_NAME(inst, "template")) {
2257 xsltCheckTopLevelElement(style, inst, 1);
2258 return;
2259 } else if (IS_XSLT_NAME(inst, "output")) {
2260 xsltCheckTopLevelElement(style, inst, 1);
2261 return;
2262 } else if (IS_XSLT_NAME(inst, "preserve-space")) {
2263 xsltCheckTopLevelElement(style, inst, 1);
2264 return;
2265 } else if (IS_XSLT_NAME(inst, "strip-space")) {
2266 xsltCheckTopLevelElement(style, inst, 1);
2267 return;
2268 } else if ((IS_XSLT_NAME(inst, "stylesheet")) ||
2269 (IS_XSLT_NAME(inst, "transform"))) {
2270 xmlNodePtr parent = inst->parent;
2271
2272 if ((parent == NULL) || (parent->type != XML_DOCUMENT_NODE)) {
2273 xsltTransformError(NULL, style, inst,
2274 "element %s only allowed only as root element\n",
2275 inst->name);
2276 style->errors++;
2277 }
2278 return;
2279 } else if (IS_XSLT_NAME(inst, "key")) {
2280 xsltCheckTopLevelElement(style, inst, 1);
2281 return;
2282 } else if (IS_XSLT_NAME(inst, "message")) {
2283 xsltCheckInstructionElement(style, inst);
2284 return;
2285 } else if (IS_XSLT_NAME(inst, "attribute-set")) {
2286 xsltCheckTopLevelElement(style, inst, 1);
2287 return;
2288 } else if (IS_XSLT_NAME(inst, "namespace-alias")) {
2289 xsltCheckTopLevelElement(style, inst, 1);
2290 return;
2291 } else if (IS_XSLT_NAME(inst, "include")) {
2292 xsltCheckTopLevelElement(style, inst, 1);
2293 return;
2294 } else if (IS_XSLT_NAME(inst, "import")) {
2295 xsltCheckTopLevelElement(style, inst, 1);
2296 return;
2297 } else if (IS_XSLT_NAME(inst, "decimal-format")) {
2298 xsltCheckTopLevelElement(style, inst, 1);
2299 return;
2300 } else if (IS_XSLT_NAME(inst, "fallback")) {
2301 xsltCheckInstructionElement(style, inst);
2302 return;
2303 } else if (IS_XSLT_NAME(inst, "document")) {
2304 xsltCheckInstructionElement(style, inst);
2305 inst->psvi = (void *) xsltDocumentComp(style, inst,
2306 (xsltTransformFunction) xsltDocumentElem);
2307 } else {
2308 xsltTransformError(NULL, style, inst,
2309 "xsltStylePreCompute: unknown xsl:%s\n", inst->name);
2310 if (style != NULL) style->warnings++;
2311 }
2312
2313 cur = (xsltStylePreCompPtr) inst->psvi;
2314 /*
2315 * A ns-list is build for every XSLT item in the
2316 * node-tree. This is needed for XPath expressions.
2317 */
2318 if (cur != NULL) {
2319 int i = 0;
2320
2321 cur->nsList = xmlGetNsList(inst->doc, inst);
2322 if (cur->nsList != NULL) {
2323 while (cur->nsList[i] != NULL)
2324 i++;
2325 }
2326 cur->nsNr = i;
2327 }
2328 } else {
2329 inst->psvi =
2330 (void *) xsltPreComputeExtModuleElement(style, inst);
2331
2332 /*
2333 * Unknown element, maybe registered at the context
2334 * level. Mark it for later recognition.
2335 */
2336 if (inst->psvi == NULL)
2337 inst->psvi = (void *) xsltExtMarker;
2338 }
2339}
2340#endif /* XSLT_REFACTORED */
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