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