xslt: Import upstream release 1.1.38.
[wine.git] / libs / xslt / libxslt / preproc.c
blobfae69a09d489f686b30c285eff1fb8a310226e0f
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->comp != NULL)
396 xmlXPathFreeCompExpr(item->comp);
398 break;
399 case XSLT_FUNC_TEXT:
400 break;
401 case XSLT_FUNC_ELEMENT:
402 break;
403 case XSLT_FUNC_ATTRIBUTE:
404 break;
405 case XSLT_FUNC_COMMENT:
406 break;
407 case XSLT_FUNC_PI:
408 break;
409 case XSLT_FUNC_COPYOF: {
410 xsltStyleItemCopyOfPtr item = (xsltStyleItemCopyOfPtr) comp;
411 if (item->comp != NULL)
412 xmlXPathFreeCompExpr(item->comp);
414 break;
415 case XSLT_FUNC_VALUEOF: {
416 xsltStyleItemValueOfPtr item = (xsltStyleItemValueOfPtr) comp;
417 if (item->comp != NULL)
418 xmlXPathFreeCompExpr(item->comp);
420 break;
421 case XSLT_FUNC_NUMBER: {
422 xsltStyleItemNumberPtr item = (xsltStyleItemNumberPtr) comp;
423 if (item->numdata.countPat != NULL)
424 xsltFreeCompMatchList(item->numdata.countPat);
425 if (item->numdata.fromPat != NULL)
426 xsltFreeCompMatchList(item->numdata.fromPat);
428 break;
429 case XSLT_FUNC_APPLYIMPORTS:
430 break;
431 case XSLT_FUNC_CALLTEMPLATE:
432 break;
433 case XSLT_FUNC_APPLYTEMPLATES: {
434 xsltStyleItemApplyTemplatesPtr item =
435 (xsltStyleItemApplyTemplatesPtr) comp;
436 if (item->comp != NULL)
437 xmlXPathFreeCompExpr(item->comp);
439 break;
440 case XSLT_FUNC_CHOOSE:
441 break;
442 case XSLT_FUNC_IF: {
443 xsltStyleItemIfPtr item = (xsltStyleItemIfPtr) comp;
444 if (item->comp != NULL)
445 xmlXPathFreeCompExpr(item->comp);
447 break;
448 case XSLT_FUNC_FOREACH: {
449 xsltStyleItemForEachPtr item =
450 (xsltStyleItemForEachPtr) comp;
451 if (item->comp != NULL)
452 xmlXPathFreeCompExpr(item->comp);
454 break;
455 case XSLT_FUNC_DOCUMENT:
456 break;
457 case XSLT_FUNC_WITHPARAM: {
458 xsltStyleItemWithParamPtr item =
459 (xsltStyleItemWithParamPtr) comp;
460 if (item->comp != NULL)
461 xmlXPathFreeCompExpr(item->comp);
463 break;
464 case XSLT_FUNC_PARAM: {
465 xsltStyleItemParamPtr item =
466 (xsltStyleItemParamPtr) comp;
467 if (item->comp != NULL)
468 xmlXPathFreeCompExpr(item->comp);
470 break;
471 case XSLT_FUNC_VARIABLE: {
472 xsltStyleItemVariablePtr item =
473 (xsltStyleItemVariablePtr) comp;
474 if (item->comp != NULL)
475 xmlXPathFreeCompExpr(item->comp);
477 break;
478 case XSLT_FUNC_WHEN: {
479 xsltStyleItemWhenPtr item =
480 (xsltStyleItemWhenPtr) comp;
481 if (item->comp != NULL)
482 xmlXPathFreeCompExpr(item->comp);
484 break;
485 case XSLT_FUNC_OTHERWISE:
486 case XSLT_FUNC_FALLBACK:
487 case XSLT_FUNC_MESSAGE:
488 case XSLT_FUNC_INCLUDE:
489 case XSLT_FUNC_ATTRSET:
491 break;
492 default:
493 /* TODO: Raise error. */
494 break;
496 #else
497 if (comp->comp != NULL)
498 xmlXPathFreeCompExpr(comp->comp);
499 if (comp->numdata.countPat != NULL)
500 xsltFreeCompMatchList(comp->numdata.countPat);
501 if (comp->numdata.fromPat != NULL)
502 xsltFreeCompMatchList(comp->numdata.fromPat);
503 if (comp->nsList != NULL)
504 xmlFree(comp->nsList);
505 #endif
507 xmlFree(comp);
511 /************************************************************************
513 * XSLT-1.1 extensions *
515 ************************************************************************/
518 * xsltDocumentComp:
519 * @style: the XSLT stylesheet
520 * @inst: the instruction in the stylesheet
521 * @function: unused
523 * Pre process an XSLT-1.1 document element
525 * Returns a precompiled data structure for the element
527 xsltElemPreCompPtr
528 xsltDocumentComp(xsltStylesheetPtr style, xmlNodePtr inst,
529 xsltTransformFunction function ATTRIBUTE_UNUSED) {
530 #ifdef XSLT_REFACTORED
531 xsltStyleItemDocumentPtr comp;
532 #else
533 xsltStylePreCompPtr comp;
534 #endif
535 const xmlChar *filename = NULL;
538 * As of 2006-03-30, this function is currently defined in Libxslt
539 * to be used for:
540 * (in libxslt/extra.c)
541 * "output" in XSLT_SAXON_NAMESPACE
542 * "write" XSLT_XALAN_NAMESPACE
543 * "document" XSLT_XT_NAMESPACE
544 * "document" XSLT_NAMESPACE (from the abandoned old working
545 * draft of XSLT 1.1)
546 * (in libexslt/common.c)
547 * "document" in EXSLT_COMMON_NAMESPACE
549 #ifdef XSLT_REFACTORED
550 comp = (xsltStyleItemDocumentPtr)
551 xsltNewStylePreComp(style, XSLT_FUNC_DOCUMENT);
552 #else
553 comp = xsltNewStylePreComp(style, XSLT_FUNC_DOCUMENT);
554 #endif
556 if (comp == NULL)
557 return (NULL);
558 comp->inst = inst;
559 comp->ver11 = 0;
561 if (xmlStrEqual(inst->name, (const xmlChar *) "output")) {
562 #ifdef WITH_XSLT_DEBUG_EXTRA
563 xsltGenericDebug(xsltGenericDebugContext,
564 "Found saxon:output extension\n");
565 #endif
567 * The element "output" is in the namespace XSLT_SAXON_NAMESPACE
568 * (http://icl.com/saxon)
569 * The @file is in no namespace; it is an AVT.
570 * (http://www.computerwizards.com/saxon/doc/extensions.html#saxon:output)
572 * TODO: Do we need not to check the namespace here?
574 filename = xsltEvalStaticAttrValueTemplate(style, inst,
575 (const xmlChar *)"file",
576 NULL, &comp->has_filename);
577 } else if (xmlStrEqual(inst->name, (const xmlChar *) "write")) {
578 #ifdef WITH_XSLT_DEBUG_EXTRA
579 xsltGenericDebug(xsltGenericDebugContext,
580 "Found xalan:write extension\n");
581 #endif
582 /* the filename need to be interpreted */
584 * TODO: Is "filename need to be interpreted" meant to be a todo?
585 * Where will be the filename of xalan:write be processed?
587 * TODO: Do we need not to check the namespace here?
588 * The extension ns is "http://xml.apache.org/xalan/redirect".
589 * See http://xml.apache.org/xalan-j/extensionslib.html.
591 } else if (xmlStrEqual(inst->name, (const xmlChar *) "document")) {
592 if (inst->ns != NULL) {
593 if (xmlStrEqual(inst->ns->href, XSLT_NAMESPACE)) {
595 * Mark the instruction as being of
596 * XSLT version 1.1 (abandoned).
598 comp->ver11 = 1;
599 #ifdef WITH_XSLT_DEBUG_EXTRA
600 xsltGenericDebug(xsltGenericDebugContext,
601 "Found xslt11:document construct\n");
602 #endif
603 } else {
604 if (xmlStrEqual(inst->ns->href,
605 (const xmlChar *)"http://exslt.org/common")) {
606 /* EXSLT. */
607 #ifdef WITH_XSLT_DEBUG_EXTRA
608 xsltGenericDebug(xsltGenericDebugContext,
609 "Found exslt:document extension\n");
610 #endif
611 } else if (xmlStrEqual(inst->ns->href, XSLT_XT_NAMESPACE)) {
612 /* James Clark's XT. */
613 #ifdef WITH_XSLT_DEBUG_EXTRA
614 xsltGenericDebug(xsltGenericDebugContext,
615 "Found xt:document extension\n");
616 #endif
621 * The element "document" is used in conjunction with the
622 * following namespaces:
624 * 1) XSLT_NAMESPACE (http://www.w3.org/1999/XSL/Transform version 1.1)
625 * <!ELEMENT xsl:document %template;>
626 * <!ATTLIST xsl:document
627 * href %avt; #REQUIRED
628 * @href is an AVT
629 * IMPORTANT: xsl:document was in the abandoned XSLT 1.1 draft,
630 * it was removed and isn't available in XSLT 1.1 anymore.
631 * In XSLT 2.0 it was renamed to xsl:result-document.
633 * All other attributes are identical to the attributes
634 * on xsl:output
636 * 2) EXSLT_COMMON_NAMESPACE (http://exslt.org/common)
637 * <exsl:document
638 * href = { uri-reference }
639 * TODO: is @href is an AVT?
641 * 3) XSLT_XT_NAMESPACE (http://www.jclark.com/xt)
642 * Example: <xt:document method="xml" href="myFile.xml">
643 * TODO: is @href is an AVT?
645 * In all cases @href is in no namespace.
647 filename = xsltEvalStaticAttrValueTemplate(style, inst,
648 (const xmlChar *)"href", NULL, &comp->has_filename);
650 if (!comp->has_filename) {
651 goto error;
653 comp->filename = filename;
655 error:
656 return ((xsltElemPreCompPtr) comp);
659 /************************************************************************
661 * Most of the XSLT-1.0 transformations *
663 ************************************************************************/
666 * xsltSortComp:
667 * @style: the XSLT stylesheet
668 * @inst: the xslt sort node
670 * Process the xslt sort node on the source node
672 static void
673 xsltSortComp(xsltStylesheetPtr style, xmlNodePtr inst) {
674 #ifdef XSLT_REFACTORED
675 xsltStyleItemSortPtr comp;
676 #else
677 xsltStylePreCompPtr comp;
678 #endif
679 if ((style == NULL) || (inst == NULL) || (inst->type != XML_ELEMENT_NODE))
680 return;
682 #ifdef XSLT_REFACTORED
683 comp = (xsltStyleItemSortPtr) xsltNewStylePreComp(style, XSLT_FUNC_SORT);
684 #else
685 comp = xsltNewStylePreComp(style, XSLT_FUNC_SORT);
686 #endif
688 if (comp == NULL)
689 return;
690 inst->psvi = comp;
691 comp->inst = inst;
693 comp->stype = xsltEvalStaticAttrValueTemplate(style, inst,
694 (const xmlChar *)"data-type",
695 NULL, &comp->has_stype);
696 if (comp->stype != NULL) {
697 if (xmlStrEqual(comp->stype, (const xmlChar *) "text"))
698 comp->number = 0;
699 else if (xmlStrEqual(comp->stype, (const xmlChar *) "number"))
700 comp->number = 1;
701 else {
702 xsltTransformError(NULL, style, inst,
703 "xsltSortComp: no support for data-type = %s\n", comp->stype);
704 comp->number = 0; /* use default */
705 if (style != NULL) style->warnings++;
708 comp->order = xsltEvalStaticAttrValueTemplate(style, inst,
709 (const xmlChar *)"order",
710 NULL, &comp->has_order);
711 if (comp->order != NULL) {
712 if (xmlStrEqual(comp->order, (const xmlChar *) "ascending"))
713 comp->descending = 0;
714 else if (xmlStrEqual(comp->order, (const xmlChar *) "descending"))
715 comp->descending = 1;
716 else {
717 xsltTransformError(NULL, style, inst,
718 "xsltSortComp: invalid value %s for order\n", comp->order);
719 comp->descending = 0; /* use default */
720 if (style != NULL) style->warnings++;
723 comp->case_order = xsltEvalStaticAttrValueTemplate(style, inst,
724 (const xmlChar *)"case-order",
725 NULL, &comp->has_use);
726 if (comp->case_order != NULL) {
727 if (xmlStrEqual(comp->case_order, (const xmlChar *) "upper-first"))
728 comp->lower_first = 0;
729 else if (xmlStrEqual(comp->case_order, (const xmlChar *) "lower-first"))
730 comp->lower_first = 1;
731 else {
732 xsltTransformError(NULL, style, inst,
733 "xsltSortComp: invalid value %s for order\n", comp->order);
734 comp->lower_first = 0; /* use default */
735 if (style != NULL) style->warnings++;
739 comp->lang = xsltEvalStaticAttrValueTemplate(style, inst,
740 (const xmlChar *)"lang",
741 NULL, &comp->has_lang);
743 comp->select = xsltGetCNsProp(style, inst,(const xmlChar *)"select", XSLT_NAMESPACE);
744 if (comp->select == NULL) {
746 * The default value of the select attribute is ., which will
747 * cause the string-value of the current node to be used as
748 * the sort key.
750 comp->select = xmlDictLookup(style->dict, BAD_CAST ".", 1);
752 comp->comp = xsltXPathCompile(style, comp->select);
753 if (comp->comp == NULL) {
754 xsltTransformError(NULL, style, inst,
755 "xsltSortComp: could not compile select expression '%s'\n",
756 comp->select);
757 if (style != NULL) style->errors++;
759 if (inst->children != NULL) {
760 xsltTransformError(NULL, style, inst,
761 "xsl:sort : is not empty\n");
762 if (style != NULL) style->errors++;
767 * xsltCopyComp:
768 * @style: the XSLT stylesheet
769 * @inst: the xslt copy node
771 * Process the xslt copy node on the source node
773 static void
774 xsltCopyComp(xsltStylesheetPtr style, xmlNodePtr inst) {
775 #ifdef XSLT_REFACTORED
776 xsltStyleItemCopyPtr comp;
777 #else
778 xsltStylePreCompPtr comp;
779 #endif
781 if ((style == NULL) || (inst == NULL) || (inst->type != XML_ELEMENT_NODE))
782 return;
783 #ifdef XSLT_REFACTORED
784 comp = (xsltStyleItemCopyPtr) xsltNewStylePreComp(style, XSLT_FUNC_COPY);
785 #else
786 comp = xsltNewStylePreComp(style, XSLT_FUNC_COPY);
787 #endif
789 if (comp == NULL)
790 return;
791 inst->psvi = comp;
792 comp->inst = inst;
795 comp->use = xsltGetCNsProp(style, inst, (const xmlChar *)"use-attribute-sets",
796 XSLT_NAMESPACE);
797 if (comp->use == NULL)
798 comp->has_use = 0;
799 else
800 comp->has_use = 1;
803 #ifdef XSLT_REFACTORED
804 /* Enable if ever needed for xsl:text. */
805 #else
807 * xsltTextComp:
808 * @style: an XSLT compiled stylesheet
809 * @inst: the xslt text node
811 * TODO: This function is obsolete, since xsl:text won't
812 * be compiled, but removed from the tree.
814 * Process the xslt text node on the source node
816 static void
817 xsltTextComp(xsltStylesheetPtr style, xmlNodePtr inst) {
818 #ifdef XSLT_REFACTORED
819 xsltStyleItemTextPtr comp;
820 #else
821 xsltStylePreCompPtr comp;
822 #endif
823 const xmlChar *prop;
825 if ((style == NULL) || (inst == NULL) || (inst->type != XML_ELEMENT_NODE))
826 return;
828 #ifdef XSLT_REFACTORED
829 comp = (xsltStyleItemTextPtr) xsltNewStylePreComp(style, XSLT_FUNC_TEXT);
830 #else
831 comp = xsltNewStylePreComp(style, XSLT_FUNC_TEXT);
832 #endif
833 if (comp == NULL)
834 return;
835 inst->psvi = comp;
836 comp->inst = inst;
837 comp->noescape = 0;
839 prop = xsltGetCNsProp(style, inst,
840 (const xmlChar *)"disable-output-escaping",
841 XSLT_NAMESPACE);
842 if (prop != NULL) {
843 if (xmlStrEqual(prop, (const xmlChar *)"yes")) {
844 comp->noescape = 1;
845 } else if (!xmlStrEqual(prop,
846 (const xmlChar *)"no")){
847 xsltTransformError(NULL, style, inst,
848 "xsl:text: disable-output-escaping allows only yes or no\n");
849 if (style != NULL) style->warnings++;
853 #endif /* else of XSLT_REFACTORED */
856 * xsltElementComp:
857 * @style: an XSLT compiled stylesheet
858 * @inst: the xslt element node
860 * Process the xslt element node on the source node
862 static void
863 xsltElementComp(xsltStylesheetPtr style, xmlNodePtr inst) {
864 #ifdef XSLT_REFACTORED
865 xsltStyleItemElementPtr comp;
866 #else
867 xsltStylePreCompPtr comp;
868 #endif
871 * <xsl:element
872 * name = { qname }
873 * namespace = { uri-reference }
874 * use-attribute-sets = qnames>
875 * <!-- Content: template -->
876 * </xsl:element>
878 if ((style == NULL) || (inst == NULL) || (inst->type != XML_ELEMENT_NODE))
879 return;
881 #ifdef XSLT_REFACTORED
882 comp = (xsltStyleItemElementPtr) xsltNewStylePreComp(style, XSLT_FUNC_ELEMENT);
883 #else
884 comp = xsltNewStylePreComp(style, XSLT_FUNC_ELEMENT);
885 #endif
887 if (comp == NULL)
888 return;
889 inst->psvi = comp;
890 comp->inst = inst;
893 * Attribute "name".
896 * TODO: Precompile the AVT. See bug #344894.
898 comp->name = xsltEvalStaticAttrValueTemplate(style, inst,
899 (const xmlChar *)"name", NULL, &comp->has_name);
900 if (! comp->has_name) {
901 xsltTransformError(NULL, style, inst,
902 "xsl:element: The attribute 'name' is missing.\n");
903 style->errors++;
904 goto error;
907 * Attribute "namespace".
910 * TODO: Precompile the AVT. See bug #344894.
912 comp->ns = xsltEvalStaticAttrValueTemplate(style, inst,
913 (const xmlChar *)"namespace", NULL, &comp->has_ns);
915 if (comp->name != NULL) {
916 if (xmlValidateQName(comp->name, 0)) {
917 xsltTransformError(NULL, style, inst,
918 "xsl:element: The value '%s' of the attribute 'name' is "
919 "not a valid QName.\n", comp->name);
920 style->errors++;
921 } else {
922 const xmlChar *prefix = NULL, *name;
924 name = xsltSplitQName(style->dict, comp->name, &prefix);
925 if (comp->has_ns == 0) {
926 xmlNsPtr ns;
929 * SPEC XSLT 1.0:
930 * "If the namespace attribute is not present, then the QName is
931 * expanded into an expanded-name using the namespace declarations
932 * in effect for the xsl:element element, including any default
933 * namespace declaration.
935 ns = xmlSearchNs(inst->doc, inst, prefix);
936 if (ns != NULL) {
937 comp->ns = xmlDictLookup(style->dict, ns->href, -1);
938 comp->has_ns = 1;
939 #ifdef XSLT_REFACTORED
940 comp->nsPrefix = prefix;
941 comp->name = name;
942 #else
943 (void)name; /* Suppress unused variable warning. */
944 #endif
945 } else if (prefix != NULL) {
946 xsltTransformError(NULL, style, inst,
947 "xsl:element: The prefixed QName '%s' "
948 "has no namespace binding in scope in the "
949 "stylesheet; this is an error, since the namespace was "
950 "not specified by the instruction itself.\n", comp->name);
951 style->errors++;
954 if ((prefix != NULL) &&
955 (!xmlStrncasecmp(prefix, (xmlChar *)"xml", 3)))
958 * Mark is to be skipped.
960 comp->has_name = 0;
965 * Attribute "use-attribute-sets",
967 comp->use = xsltEvalStaticAttrValueTemplate(style, inst,
968 (const xmlChar *)"use-attribute-sets",
969 NULL, &comp->has_use);
971 error:
972 return;
976 * xsltAttributeComp:
977 * @style: an XSLT compiled stylesheet
978 * @inst: the xslt attribute node
980 * Process the xslt attribute node on the source node
982 static void
983 xsltAttributeComp(xsltStylesheetPtr style, xmlNodePtr inst) {
984 #ifdef XSLT_REFACTORED
985 xsltStyleItemAttributePtr comp;
986 #else
987 xsltStylePreCompPtr comp;
988 #endif
991 * <xsl:attribute
992 * name = { qname }
993 * namespace = { uri-reference }>
994 * <!-- Content: template -->
995 * </xsl:attribute>
997 if ((style == NULL) || (inst == NULL) || (inst->type != XML_ELEMENT_NODE))
998 return;
1000 #ifdef XSLT_REFACTORED
1001 comp = (xsltStyleItemAttributePtr) xsltNewStylePreComp(style,
1002 XSLT_FUNC_ATTRIBUTE);
1003 #else
1004 comp = xsltNewStylePreComp(style, XSLT_FUNC_ATTRIBUTE);
1005 #endif
1007 if (comp == NULL)
1008 return;
1009 inst->psvi = comp;
1010 comp->inst = inst;
1013 * Attribute "name".
1016 * TODO: Precompile the AVT. See bug #344894.
1018 comp->name = xsltEvalStaticAttrValueTemplate(style, inst,
1019 (const xmlChar *)"name",
1020 NULL, &comp->has_name);
1021 if (! comp->has_name) {
1022 xsltTransformError(NULL, style, inst,
1023 "XSLT-attribute: The attribute 'name' is missing.\n");
1024 style->errors++;
1025 return;
1028 * Attribute "namespace".
1031 * TODO: Precompile the AVT. See bug #344894.
1033 comp->ns = xsltEvalStaticAttrValueTemplate(style, inst,
1034 (const xmlChar *)"namespace",
1035 NULL, &comp->has_ns);
1037 if (comp->name != NULL) {
1038 if (xmlValidateQName(comp->name, 0)) {
1039 xsltTransformError(NULL, style, inst,
1040 "xsl:attribute: The value '%s' of the attribute 'name' is "
1041 "not a valid QName.\n", comp->name);
1042 style->errors++;
1043 } else if (xmlStrEqual(comp->name, BAD_CAST "xmlns")) {
1044 xsltTransformError(NULL, style, inst,
1045 "xsl:attribute: The attribute name 'xmlns' is not allowed.\n");
1046 style->errors++;
1047 } else {
1048 const xmlChar *prefix = NULL, *name;
1050 name = xsltSplitQName(style->dict, comp->name, &prefix);
1051 if (prefix != NULL) {
1052 if (comp->has_ns == 0) {
1053 xmlNsPtr ns;
1056 * SPEC XSLT 1.0:
1057 * "If the namespace attribute is not present, then the
1058 * QName is expanded into an expanded-name using the
1059 * namespace declarations in effect for the xsl:element
1060 * element, including any default namespace declaration.
1062 ns = xmlSearchNs(inst->doc, inst, prefix);
1063 if (ns != NULL) {
1064 comp->ns = xmlDictLookup(style->dict, ns->href, -1);
1065 comp->has_ns = 1;
1066 #ifdef XSLT_REFACTORED
1067 comp->nsPrefix = prefix;
1068 comp->name = name;
1069 #else
1070 (void)name; /* Suppress unused variable warning. */
1071 #endif
1072 } else {
1073 xsltTransformError(NULL, style, inst,
1074 "xsl:attribute: The prefixed QName '%s' "
1075 "has no namespace binding in scope in the "
1076 "stylesheet; this is an error, since the "
1077 "namespace was not specified by the instruction "
1078 "itself.\n", comp->name);
1079 style->errors++;
1088 * xsltCommentComp:
1089 * @style: an XSLT compiled stylesheet
1090 * @inst: the xslt comment node
1092 * Process the xslt comment node on the source node
1094 static void
1095 xsltCommentComp(xsltStylesheetPtr style, xmlNodePtr inst) {
1096 #ifdef XSLT_REFACTORED
1097 xsltStyleItemCommentPtr comp;
1098 #else
1099 xsltStylePreCompPtr comp;
1100 #endif
1102 if ((style == NULL) || (inst == NULL) || (inst->type != XML_ELEMENT_NODE))
1103 return;
1105 #ifdef XSLT_REFACTORED
1106 comp = (xsltStyleItemCommentPtr) xsltNewStylePreComp(style, XSLT_FUNC_COMMENT);
1107 #else
1108 comp = xsltNewStylePreComp(style, XSLT_FUNC_COMMENT);
1109 #endif
1111 if (comp == NULL)
1112 return;
1113 inst->psvi = comp;
1114 comp->inst = inst;
1118 * xsltProcessingInstructionComp:
1119 * @style: an XSLT compiled stylesheet
1120 * @inst: the xslt processing-instruction node
1122 * Process the xslt processing-instruction node on the source node
1124 static void
1125 xsltProcessingInstructionComp(xsltStylesheetPtr style, xmlNodePtr inst) {
1126 #ifdef XSLT_REFACTORED
1127 xsltStyleItemPIPtr comp;
1128 #else
1129 xsltStylePreCompPtr comp;
1130 #endif
1132 if ((style == NULL) || (inst == NULL) || (inst->type != XML_ELEMENT_NODE))
1133 return;
1135 #ifdef XSLT_REFACTORED
1136 comp = (xsltStyleItemPIPtr) xsltNewStylePreComp(style, XSLT_FUNC_PI);
1137 #else
1138 comp = xsltNewStylePreComp(style, XSLT_FUNC_PI);
1139 #endif
1141 if (comp == NULL)
1142 return;
1143 inst->psvi = comp;
1144 comp->inst = inst;
1146 comp->name = xsltEvalStaticAttrValueTemplate(style, inst,
1147 (const xmlChar *)"name",
1148 XSLT_NAMESPACE, &comp->has_name);
1152 * xsltCopyOfComp:
1153 * @style: an XSLT compiled stylesheet
1154 * @inst: the xslt copy-of node
1156 * Process the xslt copy-of node on the source node
1158 static void
1159 xsltCopyOfComp(xsltStylesheetPtr style, xmlNodePtr inst) {
1160 #ifdef XSLT_REFACTORED
1161 xsltStyleItemCopyOfPtr comp;
1162 #else
1163 xsltStylePreCompPtr comp;
1164 #endif
1166 if ((style == NULL) || (inst == NULL) || (inst->type != XML_ELEMENT_NODE))
1167 return;
1169 #ifdef XSLT_REFACTORED
1170 comp = (xsltStyleItemCopyOfPtr) xsltNewStylePreComp(style, XSLT_FUNC_COPYOF);
1171 #else
1172 comp = xsltNewStylePreComp(style, XSLT_FUNC_COPYOF);
1173 #endif
1175 if (comp == NULL)
1176 return;
1177 inst->psvi = comp;
1178 comp->inst = inst;
1180 comp->select = xsltGetCNsProp(style, inst, (const xmlChar *)"select",
1181 XSLT_NAMESPACE);
1182 if (comp->select == NULL) {
1183 xsltTransformError(NULL, style, inst,
1184 "xsl:copy-of : select is missing\n");
1185 if (style != NULL) style->errors++;
1186 return;
1188 comp->comp = xsltXPathCompile(style, comp->select);
1189 if (comp->comp == NULL) {
1190 xsltTransformError(NULL, style, inst,
1191 "xsl:copy-of : could not compile select expression '%s'\n",
1192 comp->select);
1193 if (style != NULL) style->errors++;
1198 * xsltValueOfComp:
1199 * @style: an XSLT compiled stylesheet
1200 * @inst: the xslt value-of node
1202 * Process the xslt value-of node on the source node
1204 static void
1205 xsltValueOfComp(xsltStylesheetPtr style, xmlNodePtr inst) {
1206 #ifdef XSLT_REFACTORED
1207 xsltStyleItemValueOfPtr comp;
1208 #else
1209 xsltStylePreCompPtr comp;
1210 #endif
1211 const xmlChar *prop;
1213 if ((style == NULL) || (inst == NULL) || (inst->type != XML_ELEMENT_NODE))
1214 return;
1216 #ifdef XSLT_REFACTORED
1217 comp = (xsltStyleItemValueOfPtr) xsltNewStylePreComp(style, XSLT_FUNC_VALUEOF);
1218 #else
1219 comp = xsltNewStylePreComp(style, XSLT_FUNC_VALUEOF);
1220 #endif
1222 if (comp == NULL)
1223 return;
1224 inst->psvi = comp;
1225 comp->inst = inst;
1227 prop = xsltGetCNsProp(style, inst,
1228 (const xmlChar *)"disable-output-escaping",
1229 XSLT_NAMESPACE);
1230 if (prop != NULL) {
1231 if (xmlStrEqual(prop, (const xmlChar *)"yes")) {
1232 comp->noescape = 1;
1233 } else if (!xmlStrEqual(prop,
1234 (const xmlChar *)"no")){
1235 xsltTransformError(NULL, style, inst,
1236 "xsl:value-of : disable-output-escaping allows only yes or no\n");
1237 if (style != NULL) style->warnings++;
1240 comp->select = xsltGetCNsProp(style, inst, (const xmlChar *)"select",
1241 XSLT_NAMESPACE);
1242 if (comp->select == NULL) {
1243 xsltTransformError(NULL, style, inst,
1244 "xsl:value-of : select is missing\n");
1245 if (style != NULL) style->errors++;
1246 return;
1248 comp->comp = xsltXPathCompile(style, comp->select);
1249 if (comp->comp == NULL) {
1250 xsltTransformError(NULL, style, inst,
1251 "xsl:value-of : could not compile select expression '%s'\n",
1252 comp->select);
1253 if (style != NULL) style->errors++;
1257 static void
1258 xsltGetQNameProperty(xsltStylesheetPtr style, xmlNodePtr inst,
1259 const xmlChar *propName,
1260 int mandatory,
1261 int *hasProp, const xmlChar **nsName,
1262 const xmlChar** localName)
1264 const xmlChar *prop;
1266 if (nsName)
1267 *nsName = NULL;
1268 if (localName)
1269 *localName = NULL;
1270 if (hasProp)
1271 *hasProp = 0;
1273 prop = xsltGetCNsProp(style, inst, propName, XSLT_NAMESPACE);
1274 if (prop == NULL) {
1275 if (mandatory) {
1276 xsltTransformError(NULL, style, inst,
1277 "The attribute '%s' is missing.\n", propName);
1278 style->errors++;
1279 return;
1281 } else {
1282 const xmlChar *URI;
1284 if (xmlValidateQName(prop, 0)) {
1285 xsltTransformError(NULL, style, inst,
1286 "The value '%s' of the attribute "
1287 "'%s' is not a valid QName.\n", prop, propName);
1288 style->errors++;
1289 return;
1290 } else {
1292 * @prop will be in the string dict afterwards, @URI not.
1294 URI = xsltGetQNameURI2(style, inst, &prop);
1295 if (prop == NULL) {
1296 style->errors++;
1297 } else {
1298 if (localName)
1299 *localName = prop;
1300 if (hasProp)
1301 *hasProp = 1;
1302 if (URI != NULL) {
1304 * Fixes bug #308441: Put the ns-name in the dict
1305 * in order to pointer compare names during XPath's
1306 * variable lookup.
1308 if (nsName)
1309 *nsName = xmlDictLookup(style->dict, URI, -1);
1310 /* comp->has_ns = 1; */
1315 return;
1319 * xsltWithParamComp:
1320 * @style: an XSLT compiled stylesheet
1321 * @inst: the xslt with-param node
1323 * Process the xslt with-param node on the source node
1324 * Allowed parents: xsl:call-template, xsl:apply-templates.
1325 * <xsl:with-param
1326 * name = qname
1327 * select = expression>
1328 * <!-- Content: template -->
1329 * </xsl:with-param>
1331 static void
1332 xsltWithParamComp(xsltStylesheetPtr style, xmlNodePtr inst) {
1333 #ifdef XSLT_REFACTORED
1334 xsltStyleItemWithParamPtr comp;
1335 #else
1336 xsltStylePreCompPtr comp;
1337 #endif
1339 if ((style == NULL) || (inst == NULL) || (inst->type != XML_ELEMENT_NODE))
1340 return;
1342 #ifdef XSLT_REFACTORED
1343 comp = (xsltStyleItemWithParamPtr) xsltNewStylePreComp(style, XSLT_FUNC_WITHPARAM);
1344 #else
1345 comp = xsltNewStylePreComp(style, XSLT_FUNC_WITHPARAM);
1346 #endif
1348 if (comp == NULL)
1349 return;
1350 inst->psvi = comp;
1351 comp->inst = inst;
1354 * Attribute "name".
1356 xsltGetQNameProperty(style, inst, BAD_CAST "name",
1357 1, &(comp->has_name), &(comp->ns), &(comp->name));
1358 if (comp->ns)
1359 comp->has_ns = 1;
1361 * Attribute "select".
1363 comp->select = xsltGetCNsProp(style, inst, (const xmlChar *)"select",
1364 XSLT_NAMESPACE);
1365 if (comp->select != NULL) {
1366 comp->comp = xsltXPathCompile(style, comp->select);
1367 if (comp->comp == NULL) {
1368 xsltTransformError(NULL, style, inst,
1369 "XSLT-with-param: Failed to compile select "
1370 "expression '%s'\n", comp->select);
1371 style->errors++;
1373 if (inst->children != NULL) {
1374 xsltTransformError(NULL, style, inst,
1375 "XSLT-with-param: The content should be empty since "
1376 "the attribute select is present.\n");
1377 style->warnings++;
1383 * xsltNumberComp:
1384 * @style: an XSLT compiled stylesheet
1385 * @cur: the xslt number node
1387 * Process the xslt number node on the source node
1389 static void
1390 xsltNumberComp(xsltStylesheetPtr style, xmlNodePtr cur) {
1391 #ifdef XSLT_REFACTORED
1392 xsltStyleItemNumberPtr comp;
1393 #else
1394 xsltStylePreCompPtr comp;
1395 #endif
1396 const xmlChar *prop;
1398 if ((style == NULL) || (cur == NULL) || (cur->type != XML_ELEMENT_NODE))
1399 return;
1401 #ifdef XSLT_REFACTORED
1402 comp = (xsltStyleItemNumberPtr) xsltNewStylePreComp(style, XSLT_FUNC_NUMBER);
1403 #else
1404 comp = xsltNewStylePreComp(style, XSLT_FUNC_NUMBER);
1405 #endif
1407 if (comp == NULL)
1408 return;
1409 cur->psvi = comp;
1411 comp->numdata.doc = cur->doc;
1412 comp->numdata.node = cur;
1413 comp->numdata.value = xsltGetCNsProp(style, cur, (const xmlChar *)"value",
1414 XSLT_NAMESPACE);
1416 prop = xsltEvalStaticAttrValueTemplate(style, cur,
1417 (const xmlChar *)"format",
1418 XSLT_NAMESPACE, &comp->numdata.has_format);
1419 if (comp->numdata.has_format == 0) {
1420 comp->numdata.format = xmlDictLookup(style->dict, BAD_CAST "" , 0);
1421 } else {
1422 comp->numdata.format = prop;
1425 comp->numdata.count = xsltGetCNsProp(style, cur, (const xmlChar *)"count",
1426 XSLT_NAMESPACE);
1427 comp->numdata.from = xsltGetCNsProp(style, cur, (const xmlChar *)"from",
1428 XSLT_NAMESPACE);
1430 prop = xsltGetCNsProp(style, cur, (const xmlChar *)"count", XSLT_NAMESPACE);
1431 if (prop != NULL) {
1432 comp->numdata.countPat = xsltCompilePattern(prop, cur->doc, cur, style,
1433 NULL);
1436 prop = xsltGetCNsProp(style, cur, (const xmlChar *)"from", XSLT_NAMESPACE);
1437 if (prop != NULL) {
1438 comp->numdata.fromPat = xsltCompilePattern(prop, cur->doc, cur, style,
1439 NULL);
1442 prop = xsltGetCNsProp(style, cur, (const xmlChar *)"level", XSLT_NAMESPACE);
1443 if (prop != NULL) {
1444 if (xmlStrEqual(prop, BAD_CAST("single")) ||
1445 xmlStrEqual(prop, BAD_CAST("multiple")) ||
1446 xmlStrEqual(prop, BAD_CAST("any"))) {
1447 comp->numdata.level = prop;
1448 } else {
1449 xsltTransformError(NULL, style, cur,
1450 "xsl:number : invalid value %s for level\n", prop);
1451 if (style != NULL) style->warnings++;
1455 prop = xsltGetCNsProp(style, cur, (const xmlChar *)"lang", XSLT_NAMESPACE);
1456 if (prop != NULL) {
1457 xsltTransformError(NULL, style, cur,
1458 "xsl:number : lang attribute not implemented\n");
1459 XSLT_TODO; /* xsl:number lang attribute */
1462 prop = xsltGetCNsProp(style, cur, (const xmlChar *)"letter-value", XSLT_NAMESPACE);
1463 if (prop != NULL) {
1464 if (xmlStrEqual(prop, BAD_CAST("alphabetic"))) {
1465 xsltTransformError(NULL, style, cur,
1466 "xsl:number : letter-value 'alphabetic' not implemented\n");
1467 if (style != NULL) style->warnings++;
1468 XSLT_TODO; /* xsl:number letter-value attribute alphabetic */
1469 } else if (xmlStrEqual(prop, BAD_CAST("traditional"))) {
1470 xsltTransformError(NULL, style, cur,
1471 "xsl:number : letter-value 'traditional' not implemented\n");
1472 if (style != NULL) style->warnings++;
1473 XSLT_TODO; /* xsl:number letter-value attribute traditional */
1474 } else {
1475 xsltTransformError(NULL, style, cur,
1476 "xsl:number : invalid value %s for letter-value\n", prop);
1477 if (style != NULL) style->warnings++;
1481 prop = xsltGetCNsProp(style, cur, (const xmlChar *)"grouping-separator",
1482 XSLT_NAMESPACE);
1483 if (prop != NULL) {
1484 comp->numdata.groupingCharacterLen = xmlStrlen(prop);
1485 comp->numdata.groupingCharacter =
1486 xsltGetUTF8Char(prop, &(comp->numdata.groupingCharacterLen));
1487 if (comp->numdata.groupingCharacter < 0)
1488 comp->numdata.groupingCharacter = 0;
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;
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);
1509 * xsltApplyImportsComp:
1510 * @style: an XSLT compiled stylesheet
1511 * @inst: the xslt apply-imports node
1513 * Process the xslt apply-imports node on the source node
1515 static void
1516 xsltApplyImportsComp(xsltStylesheetPtr style, xmlNodePtr inst) {
1517 #ifdef XSLT_REFACTORED
1518 xsltStyleItemApplyImportsPtr comp;
1519 #else
1520 xsltStylePreCompPtr comp;
1521 #endif
1523 if ((style == NULL) || (inst == NULL) || (inst->type != XML_ELEMENT_NODE))
1524 return;
1526 #ifdef XSLT_REFACTORED
1527 comp = (xsltStyleItemApplyImportsPtr) xsltNewStylePreComp(style, XSLT_FUNC_APPLYIMPORTS);
1528 #else
1529 comp = xsltNewStylePreComp(style, XSLT_FUNC_APPLYIMPORTS);
1530 #endif
1532 if (comp == NULL)
1533 return;
1534 inst->psvi = comp;
1535 comp->inst = inst;
1539 * xsltCallTemplateComp:
1540 * @style: an XSLT compiled stylesheet
1541 * @inst: the xslt call-template node
1543 * Process the xslt call-template node on the source node
1545 static void
1546 xsltCallTemplateComp(xsltStylesheetPtr style, xmlNodePtr inst) {
1547 #ifdef XSLT_REFACTORED
1548 xsltStyleItemCallTemplatePtr comp;
1549 #else
1550 xsltStylePreCompPtr comp;
1551 #endif
1553 if ((style == NULL) || (inst == NULL) || (inst->type != XML_ELEMENT_NODE))
1554 return;
1556 #ifdef XSLT_REFACTORED
1557 comp = (xsltStyleItemCallTemplatePtr)
1558 xsltNewStylePreComp(style, XSLT_FUNC_CALLTEMPLATE);
1559 #else
1560 comp = xsltNewStylePreComp(style, XSLT_FUNC_CALLTEMPLATE);
1561 #endif
1563 if (comp == NULL)
1564 return;
1565 inst->psvi = comp;
1566 comp->inst = inst;
1569 * Attribute "name".
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;
1578 * xsltApplyTemplatesComp:
1579 * @style: an XSLT compiled stylesheet
1580 * @inst: the apply-templates node
1582 * Process the apply-templates node on the source node
1584 static void
1585 xsltApplyTemplatesComp(xsltStylesheetPtr style, xmlNodePtr inst) {
1586 #ifdef XSLT_REFACTORED
1587 xsltStyleItemApplyTemplatesPtr comp;
1588 #else
1589 xsltStylePreCompPtr comp;
1590 #endif
1592 if ((style == NULL) || (inst == NULL) || (inst->type != XML_ELEMENT_NODE))
1593 return;
1595 #ifdef XSLT_REFACTORED
1596 comp = (xsltStyleItemApplyTemplatesPtr)
1597 xsltNewStylePreComp(style, XSLT_FUNC_APPLYTEMPLATES);
1598 #else
1599 comp = xsltNewStylePreComp(style, XSLT_FUNC_APPLYTEMPLATES);
1600 #endif
1602 if (comp == NULL)
1603 return;
1604 inst->psvi = comp;
1605 comp->inst = inst;
1608 * Attribute "mode".
1610 xsltGetQNameProperty(style, inst, BAD_CAST "mode",
1611 0, NULL, &(comp->modeURI), &(comp->mode));
1613 * Attribute "select".
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++;
1626 /* TODO: handle (or skip) the xsl:sort and xsl:with-param */
1630 * xsltChooseComp:
1631 * @style: an XSLT compiled stylesheet
1632 * @inst: the xslt choose node
1634 * Process the xslt choose node on the source node
1636 static void
1637 xsltChooseComp(xsltStylesheetPtr style, xmlNodePtr inst) {
1638 #ifdef XSLT_REFACTORED
1639 xsltStyleItemChoosePtr comp;
1640 #else
1641 xsltStylePreCompPtr comp;
1642 #endif
1644 if ((style == NULL) || (inst == NULL) || (inst->type != XML_ELEMENT_NODE))
1645 return;
1647 #ifdef XSLT_REFACTORED
1648 comp = (xsltStyleItemChoosePtr)
1649 xsltNewStylePreComp(style, XSLT_FUNC_CHOOSE);
1650 #else
1651 comp = xsltNewStylePreComp(style, XSLT_FUNC_CHOOSE);
1652 #endif
1654 if (comp == NULL)
1655 return;
1656 inst->psvi = comp;
1657 comp->inst = inst;
1661 * xsltIfComp:
1662 * @style: an XSLT compiled stylesheet
1663 * @inst: the xslt if node
1665 * Process the xslt if node on the source node
1667 static void
1668 xsltIfComp(xsltStylesheetPtr style, xmlNodePtr inst) {
1669 #ifdef XSLT_REFACTORED
1670 xsltStyleItemIfPtr comp;
1671 #else
1672 xsltStylePreCompPtr comp;
1673 #endif
1675 if ((style == NULL) || (inst == NULL) || (inst->type != XML_ELEMENT_NODE))
1676 return;
1678 #ifdef XSLT_REFACTORED
1679 comp = (xsltStyleItemIfPtr)
1680 xsltNewStylePreComp(style, XSLT_FUNC_IF);
1681 #else
1682 comp = xsltNewStylePreComp(style, XSLT_FUNC_IF);
1683 #endif
1685 if (comp == NULL)
1686 return;
1687 inst->psvi = comp;
1688 comp->inst = inst;
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;
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++;
1707 * xsltWhenComp:
1708 * @style: an XSLT compiled stylesheet
1709 * @inst: the xslt if node
1711 * Process the xslt if node on the source node
1713 static void
1714 xsltWhenComp(xsltStylesheetPtr style, xmlNodePtr inst) {
1715 #ifdef XSLT_REFACTORED
1716 xsltStyleItemWhenPtr comp;
1717 #else
1718 xsltStylePreCompPtr comp;
1719 #endif
1721 if ((style == NULL) || (inst == NULL) || (inst->type != XML_ELEMENT_NODE))
1722 return;
1724 #ifdef XSLT_REFACTORED
1725 comp = (xsltStyleItemWhenPtr)
1726 xsltNewStylePreComp(style, XSLT_FUNC_WHEN);
1727 #else
1728 comp = xsltNewStylePreComp(style, XSLT_FUNC_WHEN);
1729 #endif
1731 if (comp == NULL)
1732 return;
1733 inst->psvi = comp;
1734 comp->inst = inst;
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;
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++;
1753 * xsltForEachComp:
1754 * @style: an XSLT compiled stylesheet
1755 * @inst: the xslt for-each node
1757 * Process the xslt for-each node on the source node
1759 static void
1760 xsltForEachComp(xsltStylesheetPtr style, xmlNodePtr inst) {
1761 #ifdef XSLT_REFACTORED
1762 xsltStyleItemForEachPtr comp;
1763 #else
1764 xsltStylePreCompPtr comp;
1765 #endif
1767 if ((style == NULL) || (inst == NULL) || (inst->type != XML_ELEMENT_NODE))
1768 return;
1770 #ifdef XSLT_REFACTORED
1771 comp = (xsltStyleItemForEachPtr)
1772 xsltNewStylePreComp(style, XSLT_FUNC_FOREACH);
1773 #else
1774 comp = xsltNewStylePreComp(style, XSLT_FUNC_FOREACH);
1775 #endif
1777 if (comp == NULL)
1778 return;
1779 inst->psvi = comp;
1780 comp->inst = inst;
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++;
1797 /* TODO: handle and skip the xsl:sort */
1801 * xsltVariableComp:
1802 * @style: an XSLT compiled stylesheet
1803 * @inst: the xslt variable node
1805 * Process the xslt variable node on the source node
1807 static void
1808 xsltVariableComp(xsltStylesheetPtr style, xmlNodePtr inst) {
1809 #ifdef XSLT_REFACTORED
1810 xsltStyleItemVariablePtr comp;
1811 #else
1812 xsltStylePreCompPtr comp;
1813 #endif
1815 if ((style == NULL) || (inst == NULL) || (inst->type != XML_ELEMENT_NODE))
1816 return;
1818 #ifdef XSLT_REFACTORED
1819 comp = (xsltStyleItemVariablePtr)
1820 xsltNewStylePreComp(style, XSLT_FUNC_VARIABLE);
1821 #else
1822 comp = xsltNewStylePreComp(style, XSLT_FUNC_VARIABLE);
1823 #endif
1825 if (comp == NULL)
1826 return;
1828 inst->psvi = comp;
1829 comp->inst = inst;
1831 * The full template resolution can be done statically
1835 * Attribute "name".
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;
1842 * Attribute "select".
1844 comp->select = xsltGetCNsProp(style, inst, (const xmlChar *)"select",
1845 XSLT_NAMESPACE);
1846 if (comp->select != NULL) {
1847 #ifndef XSLT_REFACTORED
1848 xmlNodePtr cur;
1849 #endif
1850 comp->comp = xsltXPathCompile(style, comp->select);
1851 if (comp->comp == NULL) {
1852 xsltTransformError(NULL, style, inst,
1853 "XSLT-variable: Failed to compile the XPath expression '%s'.\n",
1854 comp->select);
1855 style->errors++;
1857 #ifdef XSLT_REFACTORED
1858 if (inst->children != NULL) {
1859 xsltTransformError(NULL, style, inst,
1860 "XSLT-variable: There must be no child nodes, since the "
1861 "attribute 'select' was specified.\n");
1862 style->errors++;
1864 #else
1865 for (cur = inst->children; cur != NULL; cur = cur->next) {
1866 if (cur->type != XML_COMMENT_NODE &&
1867 (cur->type != XML_TEXT_NODE || !xsltIsBlank(cur->content)))
1869 xsltTransformError(NULL, style, inst,
1870 "XSLT-variable: There must be no child nodes, since the "
1871 "attribute 'select' was specified.\n");
1872 style->errors++;
1875 #endif
1880 * xsltParamComp:
1881 * @style: an XSLT compiled stylesheet
1882 * @inst: the xslt param node
1884 * Process the xslt param node on the source node
1886 static void
1887 xsltParamComp(xsltStylesheetPtr style, xmlNodePtr inst) {
1888 #ifdef XSLT_REFACTORED
1889 xsltStyleItemParamPtr comp;
1890 #else
1891 xsltStylePreCompPtr comp;
1892 #endif
1894 if ((style == NULL) || (inst == NULL) || (inst->type != XML_ELEMENT_NODE))
1895 return;
1897 #ifdef XSLT_REFACTORED
1898 comp = (xsltStyleItemParamPtr)
1899 xsltNewStylePreComp(style, XSLT_FUNC_PARAM);
1900 #else
1901 comp = xsltNewStylePreComp(style, XSLT_FUNC_PARAM);
1902 #endif
1904 if (comp == NULL)
1905 return;
1906 inst->psvi = comp;
1907 comp->inst = inst;
1910 * Attribute "name".
1912 xsltGetQNameProperty(style, inst, BAD_CAST "name",
1913 1, &(comp->has_name), &(comp->ns), &(comp->name));
1914 if (comp->ns)
1915 comp->has_ns = 1;
1917 * Attribute "select".
1919 comp->select = xsltGetCNsProp(style, inst, (const xmlChar *)"select",
1920 XSLT_NAMESPACE);
1921 if (comp->select != NULL) {
1922 comp->comp = xsltXPathCompile(style, comp->select);
1923 if (comp->comp == NULL) {
1924 xsltTransformError(NULL, style, inst,
1925 "XSLT-param: could not compile select expression '%s'.\n",
1926 comp->select);
1927 style->errors++;
1929 if (inst->children != NULL) {
1930 xsltTransformError(NULL, style, inst,
1931 "XSLT-param: The content should be empty since the "
1932 "attribute 'select' is present.\n");
1933 style->warnings++;
1938 /************************************************************************
1940 * Generic interface *
1942 ************************************************************************/
1945 * xsltFreeStylePreComps:
1946 * @style: an XSLT transformation context
1948 * Free up the memory allocated by all precomputed blocks
1950 void
1951 xsltFreeStylePreComps(xsltStylesheetPtr style) {
1952 xsltElemPreCompPtr cur, next;
1954 if (style == NULL)
1955 return;
1957 cur = style->preComps;
1958 while (cur != NULL) {
1959 next = cur->next;
1960 if (cur->type == XSLT_FUNC_EXTENSION)
1961 cur->free(cur);
1962 else
1963 xsltFreeStylePreComp((xsltStylePreCompPtr) cur);
1964 cur = next;
1968 #ifdef XSLT_REFACTORED
1971 * xsltStylePreCompute:
1972 * @style: the XSLT stylesheet
1973 * @node: the element in the XSLT namespace
1975 * Precompute an XSLT element.
1976 * This expects the type of the element to be already
1977 * set in style->compCtxt->inode->type;
1979 void
1980 xsltStylePreCompute(xsltStylesheetPtr style, xmlNodePtr node) {
1982 * The xsltXSLTElemMarker marker was set beforehand by
1983 * the parsing mechanism for all elements in the XSLT namespace.
1985 if (style == NULL) {
1986 if ((node != NULL) && (node->type == XML_ELEMENT_NODE))
1987 node->psvi = NULL;
1988 return;
1990 if (node == NULL)
1991 return;
1992 if (! IS_XSLT_ELEM_FAST(node))
1993 return;
1995 node->psvi = NULL;
1996 if (XSLT_CCTXT(style)->inode->type != 0) {
1997 switch (XSLT_CCTXT(style)->inode->type) {
1998 case XSLT_FUNC_APPLYTEMPLATES:
1999 xsltApplyTemplatesComp(style, node);
2000 break;
2001 case XSLT_FUNC_WITHPARAM:
2002 xsltWithParamComp(style, node);
2003 break;
2004 case XSLT_FUNC_VALUEOF:
2005 xsltValueOfComp(style, node);
2006 break;
2007 case XSLT_FUNC_COPY:
2008 xsltCopyComp(style, node);
2009 break;
2010 case XSLT_FUNC_COPYOF:
2011 xsltCopyOfComp(style, node);
2012 break;
2013 case XSLT_FUNC_IF:
2014 xsltIfComp(style, node);
2015 break;
2016 case XSLT_FUNC_CHOOSE:
2017 xsltChooseComp(style, node);
2018 break;
2019 case XSLT_FUNC_WHEN:
2020 xsltWhenComp(style, node);
2021 break;
2022 case XSLT_FUNC_OTHERWISE:
2023 /* NOP yet */
2024 return;
2025 case XSLT_FUNC_FOREACH:
2026 xsltForEachComp(style, node);
2027 break;
2028 case XSLT_FUNC_APPLYIMPORTS:
2029 xsltApplyImportsComp(style, node);
2030 break;
2031 case XSLT_FUNC_ATTRIBUTE:
2032 xsltAttributeComp(style, node);
2033 break;
2034 case XSLT_FUNC_ELEMENT:
2035 xsltElementComp(style, node);
2036 break;
2037 case XSLT_FUNC_SORT:
2038 xsltSortComp(style, node);
2039 break;
2040 case XSLT_FUNC_COMMENT:
2041 xsltCommentComp(style, node);
2042 break;
2043 case XSLT_FUNC_NUMBER:
2044 xsltNumberComp(style, node);
2045 break;
2046 case XSLT_FUNC_PI:
2047 xsltProcessingInstructionComp(style, node);
2048 break;
2049 case XSLT_FUNC_CALLTEMPLATE:
2050 xsltCallTemplateComp(style, node);
2051 break;
2052 case XSLT_FUNC_PARAM:
2053 xsltParamComp(style, node);
2054 break;
2055 case XSLT_FUNC_VARIABLE:
2056 xsltVariableComp(style, node);
2057 break;
2058 case XSLT_FUNC_FALLBACK:
2059 /* NOP yet */
2060 return;
2061 case XSLT_FUNC_DOCUMENT:
2062 /* The extra one */
2063 node->psvi = (void *) xsltDocumentComp(style, node,
2064 xsltDocumentElem);
2065 break;
2066 case XSLT_FUNC_MESSAGE:
2067 /* NOP yet */
2068 return;
2069 default:
2071 * NOTE that xsl:text, xsl:template, xsl:stylesheet,
2072 * xsl:transform, xsl:import, xsl:include are not expected
2073 * to be handed over to this function.
2075 xsltTransformError(NULL, style, node,
2076 "Internal error: (xsltStylePreCompute) cannot handle "
2077 "the XSLT element '%s'.\n", node->name);
2078 style->errors++;
2079 return;
2081 } else {
2083 * Fallback to string comparison.
2085 if (IS_XSLT_NAME(node, "apply-templates")) {
2086 xsltApplyTemplatesComp(style, node);
2087 } else if (IS_XSLT_NAME(node, "with-param")) {
2088 xsltWithParamComp(style, node);
2089 } else if (IS_XSLT_NAME(node, "value-of")) {
2090 xsltValueOfComp(style, node);
2091 } else if (IS_XSLT_NAME(node, "copy")) {
2092 xsltCopyComp(style, node);
2093 } else if (IS_XSLT_NAME(node, "copy-of")) {
2094 xsltCopyOfComp(style, node);
2095 } else if (IS_XSLT_NAME(node, "if")) {
2096 xsltIfComp(style, node);
2097 } else if (IS_XSLT_NAME(node, "choose")) {
2098 xsltChooseComp(style, node);
2099 } else if (IS_XSLT_NAME(node, "when")) {
2100 xsltWhenComp(style, node);
2101 } else if (IS_XSLT_NAME(node, "otherwise")) {
2102 /* NOP yet */
2103 return;
2104 } else if (IS_XSLT_NAME(node, "for-each")) {
2105 xsltForEachComp(style, node);
2106 } else if (IS_XSLT_NAME(node, "apply-imports")) {
2107 xsltApplyImportsComp(style, node);
2108 } else if (IS_XSLT_NAME(node, "attribute")) {
2109 xsltAttributeComp(style, node);
2110 } else if (IS_XSLT_NAME(node, "element")) {
2111 xsltElementComp(style, node);
2112 } else if (IS_XSLT_NAME(node, "sort")) {
2113 xsltSortComp(style, node);
2114 } else if (IS_XSLT_NAME(node, "comment")) {
2115 xsltCommentComp(style, node);
2116 } else if (IS_XSLT_NAME(node, "number")) {
2117 xsltNumberComp(style, node);
2118 } else if (IS_XSLT_NAME(node, "processing-instruction")) {
2119 xsltProcessingInstructionComp(style, node);
2120 } else if (IS_XSLT_NAME(node, "call-template")) {
2121 xsltCallTemplateComp(style, node);
2122 } else if (IS_XSLT_NAME(node, "param")) {
2123 xsltParamComp(style, node);
2124 } else if (IS_XSLT_NAME(node, "variable")) {
2125 xsltVariableComp(style, node);
2126 } else if (IS_XSLT_NAME(node, "fallback")) {
2127 /* NOP yet */
2128 return;
2129 } else if (IS_XSLT_NAME(node, "document")) {
2130 /* The extra one */
2131 node->psvi = (void *) xsltDocumentComp(style, node,
2132 xsltDocumentElem);
2133 } else if (IS_XSLT_NAME(node, "output")) {
2134 /* Top-level */
2135 return;
2136 } else if (IS_XSLT_NAME(node, "preserve-space")) {
2137 /* Top-level */
2138 return;
2139 } else if (IS_XSLT_NAME(node, "strip-space")) {
2140 /* Top-level */
2141 return;
2142 } else if (IS_XSLT_NAME(node, "key")) {
2143 /* Top-level */
2144 return;
2145 } else if (IS_XSLT_NAME(node, "message")) {
2146 return;
2147 } else if (IS_XSLT_NAME(node, "attribute-set")) {
2148 /* Top-level */
2149 return;
2150 } else if (IS_XSLT_NAME(node, "namespace-alias")) {
2151 /* Top-level */
2152 return;
2153 } else if (IS_XSLT_NAME(node, "decimal-format")) {
2154 /* Top-level */
2155 return;
2156 } else if (IS_XSLT_NAME(node, "include")) {
2157 /* Top-level */
2158 } else {
2160 * NOTE that xsl:text, xsl:template, xsl:stylesheet,
2161 * xsl:transform, xsl:import, xsl:include are not expected
2162 * to be handed over to this function.
2164 xsltTransformError(NULL, style, node,
2165 "Internal error: (xsltStylePreCompute) cannot handle "
2166 "the XSLT element '%s'.\n", node->name);
2167 style->errors++;
2168 return;
2172 * Assign the current list of in-scope namespaces to the
2173 * item. This is needed for XPath expressions.
2175 if (node->psvi != NULL) {
2176 ((xsltStylePreCompPtr) node->psvi)->inScopeNs =
2177 XSLT_CCTXT(style)->inode->inScopeNs;
2181 #else
2184 * xsltStylePreCompute:
2185 * @style: the XSLT stylesheet
2186 * @inst: the instruction in the stylesheet
2188 * Precompute an XSLT stylesheet element
2190 void
2191 xsltStylePreCompute(xsltStylesheetPtr style, xmlNodePtr inst) {
2193 * URGENT TODO: Normally inst->psvi Should never be reserved here,
2194 * BUT: since if we include the same stylesheet from
2195 * multiple imports, then the stylesheet will be parsed
2196 * again. We simply must not try to compute the stylesheet again.
2197 * TODO: Get to the point where we don't need to query the
2198 * namespace- and local-name of the node, but can evaluate this
2199 * using cctxt->style->inode->category;
2201 if ((inst == NULL) || (inst->type != XML_ELEMENT_NODE) ||
2202 (inst->psvi != NULL))
2203 return;
2205 if (IS_XSLT_ELEM(inst)) {
2206 xsltStylePreCompPtr cur;
2208 if (IS_XSLT_NAME(inst, "apply-templates")) {
2209 xsltCheckInstructionElement(style, inst);
2210 xsltApplyTemplatesComp(style, inst);
2211 } else if (IS_XSLT_NAME(inst, "with-param")) {
2212 xsltCheckParentElement(style, inst, BAD_CAST "apply-templates",
2213 BAD_CAST "call-template");
2214 xsltWithParamComp(style, inst);
2215 } else if (IS_XSLT_NAME(inst, "value-of")) {
2216 xsltCheckInstructionElement(style, inst);
2217 xsltValueOfComp(style, inst);
2218 } else if (IS_XSLT_NAME(inst, "copy")) {
2219 xsltCheckInstructionElement(style, inst);
2220 xsltCopyComp(style, inst);
2221 } else if (IS_XSLT_NAME(inst, "copy-of")) {
2222 xsltCheckInstructionElement(style, inst);
2223 xsltCopyOfComp(style, inst);
2224 } else if (IS_XSLT_NAME(inst, "if")) {
2225 xsltCheckInstructionElement(style, inst);
2226 xsltIfComp(style, inst);
2227 } else if (IS_XSLT_NAME(inst, "when")) {
2228 xsltCheckParentElement(style, inst, BAD_CAST "choose", NULL);
2229 xsltWhenComp(style, inst);
2230 } else if (IS_XSLT_NAME(inst, "choose")) {
2231 xsltCheckInstructionElement(style, inst);
2232 xsltChooseComp(style, inst);
2233 } else if (IS_XSLT_NAME(inst, "for-each")) {
2234 xsltCheckInstructionElement(style, inst);
2235 xsltForEachComp(style, inst);
2236 } else if (IS_XSLT_NAME(inst, "apply-imports")) {
2237 xsltCheckInstructionElement(style, inst);
2238 xsltApplyImportsComp(style, inst);
2239 } else if (IS_XSLT_NAME(inst, "attribute")) {
2240 xmlNodePtr parent = inst->parent;
2242 if ((parent == NULL) ||
2243 (parent->type != XML_ELEMENT_NODE) || (parent->ns == NULL) ||
2244 ((parent->ns != inst->ns) &&
2245 (!xmlStrEqual(parent->ns->href, inst->ns->href))) ||
2246 (!xmlStrEqual(parent->name, BAD_CAST "attribute-set"))) {
2247 xsltCheckInstructionElement(style, inst);
2249 xsltAttributeComp(style, inst);
2250 } else if (IS_XSLT_NAME(inst, "element")) {
2251 xsltCheckInstructionElement(style, inst);
2252 xsltElementComp(style, inst);
2253 } else if (IS_XSLT_NAME(inst, "text")) {
2254 xsltCheckInstructionElement(style, inst);
2255 xsltTextComp(style, inst);
2256 } else if (IS_XSLT_NAME(inst, "sort")) {
2257 xsltCheckParentElement(style, inst, BAD_CAST "apply-templates",
2258 BAD_CAST "for-each");
2259 xsltSortComp(style, inst);
2260 } else if (IS_XSLT_NAME(inst, "comment")) {
2261 xsltCheckInstructionElement(style, inst);
2262 xsltCommentComp(style, inst);
2263 } else if (IS_XSLT_NAME(inst, "number")) {
2264 xsltCheckInstructionElement(style, inst);
2265 xsltNumberComp(style, inst);
2266 } else if (IS_XSLT_NAME(inst, "processing-instruction")) {
2267 xsltCheckInstructionElement(style, inst);
2268 xsltProcessingInstructionComp(style, inst);
2269 } else if (IS_XSLT_NAME(inst, "call-template")) {
2270 xsltCheckInstructionElement(style, inst);
2271 xsltCallTemplateComp(style, inst);
2272 } else if (IS_XSLT_NAME(inst, "param")) {
2273 if (xsltCheckTopLevelElement(style, inst, 0) == 0)
2274 xsltCheckInstructionElement(style, inst);
2275 xsltParamComp(style, inst);
2276 } else if (IS_XSLT_NAME(inst, "variable")) {
2277 if (xsltCheckTopLevelElement(style, inst, 0) == 0)
2278 xsltCheckInstructionElement(style, inst);
2279 xsltVariableComp(style, inst);
2280 } else if (IS_XSLT_NAME(inst, "otherwise")) {
2281 xsltCheckParentElement(style, inst, BAD_CAST "choose", NULL);
2282 xsltCheckInstructionElement(style, inst);
2283 return;
2284 } else if (IS_XSLT_NAME(inst, "template")) {
2285 xsltCheckTopLevelElement(style, inst, 1);
2286 return;
2287 } else if (IS_XSLT_NAME(inst, "output")) {
2288 xsltCheckTopLevelElement(style, inst, 1);
2289 return;
2290 } else if (IS_XSLT_NAME(inst, "preserve-space")) {
2291 xsltCheckTopLevelElement(style, inst, 1);
2292 return;
2293 } else if (IS_XSLT_NAME(inst, "strip-space")) {
2294 xsltCheckTopLevelElement(style, inst, 1);
2295 return;
2296 } else if ((IS_XSLT_NAME(inst, "stylesheet")) ||
2297 (IS_XSLT_NAME(inst, "transform"))) {
2298 xmlNodePtr parent = inst->parent;
2300 if ((parent == NULL) || (parent->type != XML_DOCUMENT_NODE)) {
2301 xsltTransformError(NULL, style, inst,
2302 "element %s only allowed only as root element\n",
2303 inst->name);
2304 style->errors++;
2306 return;
2307 } else if (IS_XSLT_NAME(inst, "key")) {
2308 xsltCheckTopLevelElement(style, inst, 1);
2309 return;
2310 } else if (IS_XSLT_NAME(inst, "message")) {
2311 xsltCheckInstructionElement(style, inst);
2312 return;
2313 } else if (IS_XSLT_NAME(inst, "attribute-set")) {
2314 xsltCheckTopLevelElement(style, inst, 1);
2315 return;
2316 } else if (IS_XSLT_NAME(inst, "namespace-alias")) {
2317 xsltCheckTopLevelElement(style, inst, 1);
2318 return;
2319 } else if (IS_XSLT_NAME(inst, "include")) {
2320 xsltCheckTopLevelElement(style, inst, 1);
2321 return;
2322 } else if (IS_XSLT_NAME(inst, "import")) {
2323 xsltCheckTopLevelElement(style, inst, 1);
2324 return;
2325 } else if (IS_XSLT_NAME(inst, "decimal-format")) {
2326 xsltCheckTopLevelElement(style, inst, 1);
2327 return;
2328 } else if (IS_XSLT_NAME(inst, "fallback")) {
2329 xsltCheckInstructionElement(style, inst);
2330 return;
2331 } else if (IS_XSLT_NAME(inst, "document")) {
2332 xsltCheckInstructionElement(style, inst);
2333 inst->psvi = (void *) xsltDocumentComp(style, inst,
2334 xsltDocumentElem);
2335 } else if ((style == NULL) || (style->forwards_compatible == 0)) {
2336 xsltTransformError(NULL, style, inst,
2337 "xsltStylePreCompute: unknown xsl:%s\n", inst->name);
2338 if (style != NULL) style->warnings++;
2341 cur = (xsltStylePreCompPtr) inst->psvi;
2343 * A ns-list is build for every XSLT item in the
2344 * node-tree. This is needed for XPath expressions.
2346 if (cur != NULL) {
2347 int i = 0;
2349 cur->nsList = xmlGetNsList(inst->doc, inst);
2350 if (cur->nsList != NULL) {
2351 while (cur->nsList[i] != NULL)
2352 i++;
2354 cur->nsNr = i;
2356 } else {
2357 inst->psvi =
2358 (void *) xsltPreComputeExtModuleElement(style, inst);
2361 * Unknown element, maybe registered at the context
2362 * level. Mark it for later recognition.
2364 if (inst->psvi == NULL)
2365 inst->psvi = (void *) xsltExtMarker;
2368 #endif /* XSLT_REFACTORED */