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