2 * preproc.c: Preprocessing of style operations
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.
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/xmlerror.h>
31 #include "xsltutils.h"
32 #include "xsltInternals.h"
33 #include "transform.h"
34 #include "templates.h"
35 #include "variables.h"
36 #include "numbersInternals.h"
40 #include "extensions.h"
42 #ifdef WITH_XSLT_DEBUG
43 #define WITH_XSLT_DEBUG_PREPROC
46 const xmlChar *xsltExtMarker = (const xmlChar *) "Extension Element";
48 /************************************************************************
50 * handling of precomputed data *
52 ************************************************************************/
55 * xsltNewStylePreComp:
56 * @style: the XSLT stylesheet
57 * @type: the construct type
59 * Create a new XSLT Style precomputed block
61 * Returns the newly allocated xsltStylePreCompPtr or NULL in case of error
63 static xsltStylePreCompPtr
64 xsltNewStylePreComp(xsltStylesheetPtr style, xsltStyleType type) {
65 xsltStylePreCompPtr cur;
67 cur = (xsltStylePreCompPtr) xmlMalloc(sizeof(xsltStylePreComp));
69 xsltPrintErrorContext(NULL, style, NULL);
70 xsltGenericError(xsltGenericErrorContext,
71 "xsltNewStylePreComp : malloc failed\n");
75 memset(cur, 0, sizeof(xsltStylePreComp));
80 cur->func = (xsltTransformFunction) xsltCopy;break;
82 cur->func = (xsltTransformFunction) xsltSort;break;
84 cur->func = (xsltTransformFunction) xsltText;break;
85 case XSLT_FUNC_ELEMENT:
86 cur->func = (xsltTransformFunction) xsltElement;break;
87 case XSLT_FUNC_ATTRIBUTE:
88 cur->func = (xsltTransformFunction) xsltAttribute;break;
89 case XSLT_FUNC_COMMENT:
90 cur->func = (xsltTransformFunction) xsltComment;break;
92 cur->func = (xsltTransformFunction) xsltProcessingInstruction;
94 case XSLT_FUNC_COPYOF:
95 cur->func = (xsltTransformFunction) xsltCopyOf;break;
96 case XSLT_FUNC_VALUEOF:
97 cur->func = (xsltTransformFunction) xsltValueOf;break;
98 case XSLT_FUNC_NUMBER:
99 cur->func = (xsltTransformFunction) xsltNumber;break;
100 case XSLT_FUNC_APPLYIMPORTS:
101 cur->func = (xsltTransformFunction) xsltApplyImports;break;
102 case XSLT_FUNC_CALLTEMPLATE:
103 cur->func = (xsltTransformFunction) xsltCallTemplate;break;
104 case XSLT_FUNC_APPLYTEMPLATES:
105 cur->func = (xsltTransformFunction) xsltApplyTemplates;break;
106 case XSLT_FUNC_CHOOSE:
107 cur->func = (xsltTransformFunction) xsltChoose;break;
109 cur->func = (xsltTransformFunction) xsltIf;break;
110 case XSLT_FUNC_FOREACH:
111 cur->func = (xsltTransformFunction) xsltForEach;break;
112 case XSLT_FUNC_DOCUMENT:
113 cur->func = (xsltTransformFunction) xsltDocumentElem;break;
114 case XSLT_FUNC_WITHPARAM:
115 cur->func = NULL;break;
116 case XSLT_FUNC_PARAM:
117 cur->func = NULL;break;
118 case XSLT_FUNC_VARIABLE:
119 cur->func = NULL;break;
121 cur->func = NULL;break;
123 if (cur->func == NULL) {
124 xsltPrintErrorContext(NULL, style, NULL);
125 xsltGenericError(xsltGenericErrorContext,
126 "xsltNewStylePreComp : no function for type %d\n", type);
130 cur->next = style->preComps;
131 style->preComps = (xsltElemPreCompPtr) cur;
137 * xsltFreeStylePreComp:
138 * @comp: an XSLT Style precomputed block
140 * Free up the memory allocated by @comp
143 xsltFreeStylePreComp(xsltStylePreCompPtr comp) {
146 if (comp->stype != NULL)
147 xmlFree(comp->stype);
148 if (comp->order != NULL)
149 xmlFree(comp->order);
150 if (comp->use != NULL)
152 if (comp->name != NULL)
154 if (comp->ns != NULL)
156 if (comp->mode != NULL)
158 if (comp->modeURI != NULL)
159 xmlFree(comp->modeURI);
160 if (comp->test != NULL)
162 if (comp->select != NULL)
163 xmlFree(comp->select);
165 if (comp->filename != NULL)
166 xmlFree(comp->filename);
168 if (comp->numdata.level != NULL)
169 xmlFree(comp->numdata.level);
170 if (comp->numdata.count != NULL)
171 xmlFree(comp->numdata.count);
172 if (comp->numdata.from != NULL)
173 xmlFree(comp->numdata.from);
174 if (comp->numdata.value != NULL)
175 xmlFree(comp->numdata.value);
176 if (comp->numdata.format != NULL)
177 xmlFree(comp->numdata.format);
178 if (comp->comp != NULL)
179 xmlXPathFreeCompExpr(comp->comp);
180 if (comp->nsList != NULL)
181 xmlFree(comp->nsList);
187 /************************************************************************
189 * XSLT-1.1 extensions *
191 ************************************************************************/
195 * @style: the XSLT stylesheet
196 * @inst: the instruction in the stylesheet
198 * Pre process an XSLT-1.1 document element
201 xsltDocumentComp(xsltStylesheetPtr style, xmlNodePtr inst,
202 xsltTransformFunction function ATTRIBUTE_UNUSED) {
203 xsltStylePreCompPtr comp;
204 xmlChar *filename = NULL;
205 xmlChar *base = NULL;
208 comp = xsltNewStylePreComp(style, XSLT_FUNC_DOCUMENT);
214 if (xmlStrEqual(inst->name, (const xmlChar *) "output")) {
215 #ifdef WITH_XSLT_DEBUG_EXTRA
216 xsltGenericDebug(xsltGenericDebugContext,
217 "Found saxon:output extension\n");
219 filename = xsltEvalStaticAttrValueTemplate(style, inst,
220 (const xmlChar *)"file",
221 XSLT_SAXON_NAMESPACE, &comp->has_filename);
222 } else if (xmlStrEqual(inst->name, (const xmlChar *) "write")) {
223 #ifdef WITH_XSLT_DEBUG_EXTRA
224 xsltGenericDebug(xsltGenericDebugContext,
225 "Found xalan:write extension\n");
227 comp->ver11 = 0; /* the filename need to be interpreted */
228 } else if (xmlStrEqual(inst->name, (const xmlChar *) "document")) {
229 filename = xsltEvalStaticAttrValueTemplate(style, inst,
230 (const xmlChar *)"href",
231 XSLT_XT_NAMESPACE, &comp->has_filename);
232 if (comp->has_filename == 0) {
233 #ifdef WITH_XSLT_DEBUG_EXTRA
234 xsltGenericDebug(xsltGenericDebugContext,
235 "Found xslt11:document construct\n");
237 filename = xsltEvalStaticAttrValueTemplate(style, inst,
238 (const xmlChar *)"href",
239 XSLT_NAMESPACE, &comp->has_filename);
242 #ifdef WITH_XSLT_DEBUG_EXTRA
243 xsltGenericDebug(xsltGenericDebugContext,
244 "Found xt:document extension\n");
249 if (!comp->has_filename) {
253 if (filename != NULL) {
257 base = xmlNodeGetBase(inst->doc, inst);
258 URL = xmlBuildURI(filename, base);
260 xsltPrintErrorContext(NULL, style, inst);
261 xsltGenericError(xsltGenericErrorContext,
262 "xsltDocumentComp: URL computation failed %s\n", filename);
264 comp->filename = xmlStrdup(filename);
266 comp->filename = URL;
269 comp->filename = NULL;
275 if (filename != NULL)
278 return ((xsltElemPreCompPtr) comp);
281 /************************************************************************
283 * Most of the XSLT-1.0 transformations *
285 ************************************************************************/
289 * @style: the XSLT stylesheet
290 * @inst: the xslt sort node
292 * Process the xslt sort node on the source node
295 xsltSortComp(xsltStylesheetPtr style, xmlNodePtr inst) {
296 xsltStylePreCompPtr comp;
299 if ((style == NULL) || (inst == NULL))
301 comp = xsltNewStylePreComp(style, XSLT_FUNC_SORT);
304 inst->_private = comp;
307 comp->stype = xsltEvalStaticAttrValueTemplate(style, inst,
308 (const xmlChar *)"data-type",
309 XSLT_NAMESPACE, &comp->has_stype);
310 if (comp->stype != NULL) {
311 if (xmlStrEqual(comp->stype, (const xmlChar *) "text"))
313 else if (xmlStrEqual(comp->stype, (const xmlChar *) "number"))
316 xsltPrintErrorContext(NULL, style, inst);
317 xsltGenericError(xsltGenericErrorContext,
318 "xsltSortComp: no support for data-type = %s\n", comp->stype);
323 comp->order = xsltEvalStaticAttrValueTemplate(style, inst,
324 (const xmlChar *)"order",
325 XSLT_NAMESPACE, &comp->has_order);
326 if (comp->order != NULL) {
327 if (xmlStrEqual(comp->order, (const xmlChar *) "ascending"))
328 comp->descending = 0;
329 else if (xmlStrEqual(comp->order, (const xmlChar *) "descending"))
330 comp->descending = 1;
332 xsltPrintErrorContext(NULL, style, inst);
333 xsltGenericError(xsltGenericErrorContext,
334 "xsltSortComp: invalid value %s for order\n", comp->order);
335 comp->descending = -1;
339 /* TODO: xsl:sort lang attribute */
340 /* TODO: xsl:sort case-order attribute */
342 comp->select = xsltGetNsProp(inst,(const xmlChar *)"select", XSLT_NAMESPACE);
343 if (comp->select == NULL) {
345 * The default value of the select attribute is ., which will
346 * cause the string-value of the current node to be used as
349 comp->select = xmlStrdup((const xmlChar *)".");
351 comp->comp = xmlXPathCompile(comp->select);
352 if (comp->comp == NULL) {
353 xsltPrintErrorContext(NULL, style, inst);
354 xsltGenericError(xsltGenericErrorContext,
355 "xsltSortComp: could not compile select expression '%s'\n",
363 * @style: the XSLT stylesheet
364 * @inst: the xslt copy node
366 * Process the xslt copy node on the source node
369 xsltCopyComp(xsltStylesheetPtr style, xmlNodePtr inst) {
370 xsltStylePreCompPtr comp;
373 if ((style == NULL) || (inst == NULL))
375 comp = xsltNewStylePreComp(style, XSLT_FUNC_COPY);
378 inst->_private = comp;
382 comp->use = xsltGetNsProp(inst, (const xmlChar *)"use-attribute-sets",
384 if (comp->use == NULL)
392 * @style: a XSLT process context
393 * @inst: the xslt text node
395 * Process the xslt text node on the source node
398 xsltTextComp(xsltStylesheetPtr style, xmlNodePtr inst) {
399 xsltStylePreCompPtr comp;
402 if ((style == NULL) || (inst == NULL))
404 comp = xsltNewStylePreComp(style, XSLT_FUNC_TEXT);
407 inst->_private = comp;
411 prop = xsltGetNsProp(inst,
412 (const xmlChar *)"disable-output-escaping",
415 if (xmlStrEqual(prop, (const xmlChar *)"yes")) {
417 } else if (!xmlStrEqual(prop,
418 (const xmlChar *)"no")){
419 xsltPrintErrorContext(NULL, style, inst);
420 xsltGenericError(xsltGenericErrorContext,
421 "xsl:text: disable-output-escaping allows only yes or no\n");
430 * @style: a XSLT process context
431 * @inst: the xslt element node
433 * Process the xslt element node on the source node
436 xsltElementComp(xsltStylesheetPtr style, xmlNodePtr inst) {
437 xsltStylePreCompPtr comp;
439 if ((style == NULL) || (inst == NULL))
441 comp = xsltNewStylePreComp(style, XSLT_FUNC_ELEMENT);
444 inst->_private = comp;
448 * TODO: more computation can be done there, especially namespace lookup
450 comp->name = xsltEvalStaticAttrValueTemplate(style, inst,
451 (const xmlChar *)"name",
452 XSLT_NAMESPACE, &comp->has_name);
453 comp->ns = xsltEvalStaticAttrValueTemplate(style, inst,
454 (const xmlChar *)"namespace",
455 XSLT_NAMESPACE, &comp->has_ns);
457 comp->use = xsltEvalStaticAttrValueTemplate(style, inst,
458 (const xmlChar *)"use-attribute-sets",
459 XSLT_NAMESPACE, &comp->has_use);
464 * @style: a XSLT process context
465 * @inst: the xslt attribute node
467 * Process the xslt attribute node on the source node
470 xsltAttributeComp(xsltStylesheetPtr style, xmlNodePtr inst) {
471 xsltStylePreCompPtr comp;
473 if ((style == NULL) || (inst == NULL))
475 comp = xsltNewStylePreComp(style, XSLT_FUNC_ATTRIBUTE);
478 inst->_private = comp;
482 * TODO: more computation can be done there, especially namespace lookup
484 comp->name = xsltEvalStaticAttrValueTemplate(style, inst,
485 (const xmlChar *)"name",
486 XSLT_NAMESPACE, &comp->has_name);
487 comp->ns = xsltEvalStaticAttrValueTemplate(style, inst,
488 (const xmlChar *)"namespace",
489 XSLT_NAMESPACE, &comp->has_ns);
495 * @style: a XSLT process context
496 * @inst: the xslt comment node
498 * Process the xslt comment node on the source node
501 xsltCommentComp(xsltStylesheetPtr style, xmlNodePtr inst) {
502 xsltStylePreCompPtr comp;
504 if ((style == NULL) || (inst == NULL))
506 comp = xsltNewStylePreComp(style, XSLT_FUNC_COMMENT);
509 inst->_private = comp;
514 * xsltProcessingInstructionComp:
515 * @style: a XSLT process context
516 * @inst: the xslt processing-instruction node
518 * Process the xslt processing-instruction node on the source node
521 xsltProcessingInstructionComp(xsltStylesheetPtr style, xmlNodePtr inst) {
522 xsltStylePreCompPtr comp;
524 if ((style == NULL) || (inst == NULL))
526 comp = xsltNewStylePreComp(style, XSLT_FUNC_PI);
529 inst->_private = comp;
532 comp->name = xsltEvalStaticAttrValueTemplate(style, inst,
533 (const xmlChar *)"name",
534 XSLT_NAMESPACE, &comp->has_name);
539 * @style: a XSLT process context
540 * @inst: the xslt copy-of node
542 * Process the xslt copy-of node on the source node
545 xsltCopyOfComp(xsltStylesheetPtr style, xmlNodePtr inst) {
546 xsltStylePreCompPtr comp;
548 if ((style == NULL) || (inst == NULL))
550 comp = xsltNewStylePreComp(style, XSLT_FUNC_COPYOF);
553 inst->_private = comp;
556 comp->select = xsltGetNsProp(inst, (const xmlChar *)"select",
558 if (comp->select == NULL) {
559 xsltPrintErrorContext(NULL, style, inst);
560 xsltGenericError(xsltGenericErrorContext,
561 "xsl:copy-of : select is missing\n");
565 comp->comp = xmlXPathCompile(comp->select);
566 if (comp->comp == NULL) {
567 xsltPrintErrorContext(NULL, style, inst);
568 xsltGenericError(xsltGenericErrorContext,
569 "xsl:copy-of : could not compile select expression '%s'\n",
577 * @style: a XSLT process context
578 * @inst: the xslt value-of node
580 * Process the xslt value-of node on the source node
583 xsltValueOfComp(xsltStylesheetPtr style, xmlNodePtr inst) {
584 xsltStylePreCompPtr comp;
587 if ((style == NULL) || (inst == NULL))
589 comp = xsltNewStylePreComp(style, XSLT_FUNC_VALUEOF);
592 inst->_private = comp;
595 prop = xsltGetNsProp(inst,
596 (const xmlChar *)"disable-output-escaping",
599 if (xmlStrEqual(prop, (const xmlChar *)"yes")) {
601 } else if (!xmlStrEqual(prop,
602 (const xmlChar *)"no")){
603 xsltPrintErrorContext(NULL, style, inst);
604 xsltGenericError(xsltGenericErrorContext,
605 "xsl:value-of : disable-output-escaping allows only yes or no\n");
610 comp->select = xsltGetNsProp(inst, (const xmlChar *)"select",
612 if (comp->select == NULL) {
613 xsltPrintErrorContext(NULL, style, inst);
614 xsltGenericError(xsltGenericErrorContext,
615 "xsl:value-of : select is missing\n");
619 comp->comp = xmlXPathCompile(comp->select);
620 if (comp->comp == NULL) {
621 xsltPrintErrorContext(NULL, style, inst);
622 xsltGenericError(xsltGenericErrorContext,
623 "xsl:value-of : could not compile select expression '%s'\n",
631 * @style: a XSLT process context
632 * @inst: the xslt with-param node
634 * Process the xslt with-param node on the source node
637 xsltWithParamComp(xsltStylesheetPtr style, xmlNodePtr inst) {
638 xsltStylePreCompPtr comp;
641 if ((style == NULL) || (inst == NULL))
643 comp = xsltNewStylePreComp(style, XSLT_FUNC_WITHPARAM);
646 inst->_private = comp;
650 * The full namespace resolution can be done statically
652 prop = xsltGetNsProp(inst, (const xmlChar *)"name", XSLT_NAMESPACE);
654 xsltPrintErrorContext(NULL, style, inst);
655 xsltGenericError(xsltGenericErrorContext,
656 "xsl:with-param : name is missing\n");
661 URI = xsltGetQNameURI(inst, &prop);
668 comp->ns = xmlStrdup(URI);
676 comp->select = xsltGetNsProp(inst, (const xmlChar *)"select",
678 if (comp->select != NULL) {
679 comp->comp = xmlXPathCompile(comp->select);
680 if (comp->comp == NULL) {
681 xsltPrintErrorContext(NULL, style, inst);
682 xsltGenericError(xsltGenericErrorContext,
683 "xsl:param : could not compile select expression '%s'\n",
687 if (inst->children != NULL) {
688 xsltPrintErrorContext(NULL, style, inst);
689 xsltGenericError(xsltGenericErrorContext,
690 "xsl:param : content should be empty since select is present \n");
698 * @style: a XSLT process context
699 * @cur: the xslt number node
701 * Process the xslt number node on the source node
704 xsltNumberComp(xsltStylesheetPtr style, xmlNodePtr cur) {
705 xsltStylePreCompPtr comp;
708 if ((style == NULL) || (cur == NULL))
710 comp = xsltNewStylePreComp(style, XSLT_FUNC_NUMBER);
713 cur->_private = comp;
715 if ((style == NULL) || (cur == NULL))
718 comp->numdata.doc = cur->doc;
719 comp->numdata.node = cur;
720 comp->numdata.value = xsltGetNsProp(cur, (const xmlChar *)"value",
723 prop = xsltEvalStaticAttrValueTemplate(style, cur,
724 (const xmlChar *)"format",
725 XSLT_NAMESPACE, &comp->numdata.has_format);
726 if (comp->numdata.has_format == 0) {
727 comp->numdata.format = xmlStrdup(BAD_CAST(""));
729 comp->numdata.format = prop;
732 comp->numdata.count = xsltGetNsProp(cur, (const xmlChar *)"count",
734 comp->numdata.from = xsltGetNsProp(cur, (const xmlChar *)"from",
737 prop = xsltGetNsProp(cur, (const xmlChar *)"level", XSLT_NAMESPACE);
739 if (xmlStrEqual(prop, BAD_CAST("single")) ||
740 xmlStrEqual(prop, BAD_CAST("multiple")) ||
741 xmlStrEqual(prop, BAD_CAST("any"))) {
742 comp->numdata.level = prop;
744 xsltPrintErrorContext(NULL, style, cur);
745 xsltGenericError(xsltGenericErrorContext,
746 "xsl:number : invalid value %s for level\n", prop);
752 prop = xsltGetNsProp(cur, (const xmlChar *)"lang", XSLT_NAMESPACE);
754 XSLT_TODO; /* xsl:number lang attribute */
758 prop = xsltGetNsProp(cur, (const xmlChar *)"letter-value", XSLT_NAMESPACE);
760 if (xmlStrEqual(prop, BAD_CAST("alphabetic"))) {
761 xsltPrintErrorContext(NULL, style, cur);
762 xsltGenericError(xsltGenericErrorContext,
763 "xsl:number : letter-value 'alphabetic' not implemented\n");
765 XSLT_TODO; /* xsl:number letter-value attribute alphabetic */
766 } else if (xmlStrEqual(prop, BAD_CAST("traditional"))) {
767 xsltPrintErrorContext(NULL, style, cur);
768 xsltGenericError(xsltGenericErrorContext,
769 "xsl:number : letter-value 'traditional' not implemented\n");
771 XSLT_TODO; /* xsl:number letter-value attribute traditional */
773 xsltPrintErrorContext(NULL, style, cur);
774 xsltGenericError(xsltGenericErrorContext,
775 "xsl:number : invalid value %s for letter-value\n", prop);
781 prop = xsltGetNsProp(cur, (const xmlChar *)"grouping-separator",
784 comp->numdata.groupingCharacter = prop[0];
788 prop = xsltGetNsProp(cur, (const xmlChar *)"grouping-size", XSLT_NAMESPACE);
790 sscanf((char *)prop, "%d", &comp->numdata.digitsPerGroup);
793 comp->numdata.groupingCharacter = 0;
796 /* Set default values */
797 if (comp->numdata.value == NULL) {
798 if (comp->numdata.level == NULL) {
799 comp->numdata.level = xmlStrdup(BAD_CAST("single"));
806 * xsltApplyImportsComp:
807 * @style: a XSLT process context
808 * @inst: the xslt apply-imports node
810 * Process the xslt apply-imports node on the source node
813 xsltApplyImportsComp(xsltStylesheetPtr style, xmlNodePtr inst) {
814 xsltStylePreCompPtr comp;
816 if ((style == NULL) || (inst == NULL))
818 comp = xsltNewStylePreComp(style, XSLT_FUNC_APPLYIMPORTS);
821 inst->_private = comp;
826 * xsltCallTemplateComp:
827 * @style: a XSLT process context
828 * @inst: the xslt call-template node
830 * Process the xslt call-template node on the source node
833 xsltCallTemplateComp(xsltStylesheetPtr style, xmlNodePtr inst) {
834 xsltStylePreCompPtr comp;
837 if ((style == NULL) || (inst == NULL))
839 comp = xsltNewStylePreComp(style, XSLT_FUNC_CALLTEMPLATE);
842 inst->_private = comp;
846 * The full template resolution can be done statically
848 prop = xsltGetNsProp(inst, (const xmlChar *)"name", XSLT_NAMESPACE);
850 xsltPrintErrorContext(NULL, style, inst);
851 xsltGenericError(xsltGenericErrorContext,
852 "xsl:call-template : name is missing\n");
857 URI = xsltGetQNameURI(inst, &prop);
864 comp->ns = xmlStrdup(URI);
875 * xsltApplyTemplatesComp:
876 * @style: a XSLT process context
877 * @inst: the apply-templates node
879 * Process the apply-templates node on the source node
882 xsltApplyTemplatesComp(xsltStylesheetPtr style, xmlNodePtr inst) {
883 xsltStylePreCompPtr comp;
886 if ((style == NULL) || (inst == NULL))
888 comp = xsltNewStylePreComp(style, XSLT_FUNC_APPLYTEMPLATES);
891 inst->_private = comp;
897 prop = xsltGetNsProp(inst, (const xmlChar *)"mode", XSLT_NAMESPACE);
901 URI = xsltGetQNameURI(inst, &prop);
907 comp->modeURI = xmlStrdup(URI);
909 comp->modeURI = NULL;
913 comp->select = xsltGetNsProp(inst, (const xmlChar *)"select",
915 if (comp->select != NULL) {
916 comp->comp = xmlXPathCompile(comp->select);
917 if (comp->comp == NULL) {
918 xsltPrintErrorContext(NULL, style, inst);
919 xsltGenericError(xsltGenericErrorContext,
920 "xsl:apply-templates : could not compile select expression '%s'\n",
926 /* TODO: handle (or skip) the xsl:sort and xsl:with-param */
931 * @style: a XSLT process context
932 * @inst: the xslt choose node
934 * Process the xslt choose node on the source node
937 xsltChooseComp(xsltStylesheetPtr style, xmlNodePtr inst) {
938 xsltStylePreCompPtr comp;
940 if ((style == NULL) || (inst == NULL))
942 comp = xsltNewStylePreComp(style, XSLT_FUNC_CHOOSE);
945 inst->_private = comp;
951 * @style: a XSLT process context
952 * @inst: the xslt if node
954 * Process the xslt if node on the source node
957 xsltIfComp(xsltStylesheetPtr style, xmlNodePtr inst) {
958 xsltStylePreCompPtr comp;
960 if ((style == NULL) || (inst == NULL))
962 comp = xsltNewStylePreComp(style, XSLT_FUNC_IF);
965 inst->_private = comp;
968 comp->test = xsltGetNsProp(inst, (const xmlChar *)"test", XSLT_NAMESPACE);
969 if (comp->test == NULL) {
970 xsltPrintErrorContext(NULL, style, inst);
971 xsltGenericError(xsltGenericErrorContext,
972 "xsl:if : test is not defined\n");
976 comp->comp = xmlXPathCompile(comp->test);
977 if (comp->comp == NULL) {
978 xsltPrintErrorContext(NULL, style, inst);
979 xsltGenericError(xsltGenericErrorContext,
980 "xsl:if : could not compile test expression '%s'\n",
988 * @style: a XSLT process context
989 * @inst: the xslt if node
991 * Process the xslt if node on the source node
994 xsltWhenComp(xsltStylesheetPtr style, xmlNodePtr inst) {
995 xsltStylePreCompPtr comp;
997 if ((style == NULL) || (inst == NULL))
999 comp = xsltNewStylePreComp(style, XSLT_FUNC_WHEN);
1002 inst->_private = comp;
1005 comp->test = xsltGetNsProp(inst, (const xmlChar *)"test", XSLT_NAMESPACE);
1006 if (comp->test == NULL) {
1007 xsltPrintErrorContext(NULL, style, inst);
1008 xsltGenericError(xsltGenericErrorContext,
1009 "xsl:when : test is not defined\n");
1013 comp->comp = xmlXPathCompile(comp->test);
1014 if (comp->comp == NULL) {
1015 xsltPrintErrorContext(NULL, style, inst);
1016 xsltGenericError(xsltGenericErrorContext,
1017 "xsl:when : could not compile test expression '%s'\n",
1025 * @style: a XSLT process context
1026 * @inst: the xslt for-each node
1028 * Process the xslt for-each node on the source node
1031 xsltForEachComp(xsltStylesheetPtr style, xmlNodePtr inst) {
1032 xsltStylePreCompPtr comp;
1034 if ((style == NULL) || (inst == NULL))
1036 comp = xsltNewStylePreComp(style, XSLT_FUNC_FOREACH);
1039 inst->_private = comp;
1042 comp->select = xsltGetNsProp(inst, (const xmlChar *)"select",
1044 if (comp->select == NULL) {
1045 xsltPrintErrorContext(NULL, style, inst);
1046 xsltGenericError(xsltGenericErrorContext,
1047 "xsl:for-each : select is missing\n");
1050 comp->comp = xmlXPathCompile(comp->select);
1051 if (comp->comp == NULL) {
1052 xsltPrintErrorContext(NULL, style, inst);
1053 xsltGenericError(xsltGenericErrorContext,
1054 "xsl:for-each : could not compile select expression '%s'\n",
1059 /* TODO: handle and skip the xsl:sort */
1064 * @style: a XSLT process context
1065 * @inst: the xslt variable node
1067 * Process the xslt variable node on the source node
1070 xsltVariableComp(xsltStylesheetPtr style, xmlNodePtr inst) {
1071 xsltStylePreCompPtr comp;
1074 if ((style == NULL) || (inst == NULL))
1076 comp = xsltNewStylePreComp(style, XSLT_FUNC_VARIABLE);
1079 inst->_private = comp;
1083 * The full template resolution can be done statically
1085 prop = xsltGetNsProp(inst, (const xmlChar *)"name", XSLT_NAMESPACE);
1087 xsltPrintErrorContext(NULL, style, inst);
1088 xsltGenericError(xsltGenericErrorContext,
1089 "xsl:variable : name is missing\n");
1094 URI = xsltGetQNameURI(inst, &prop);
1101 comp->ns = xmlStrdup(URI);
1109 comp->select = xsltGetNsProp(inst, (const xmlChar *)"select",
1111 if (comp->select != NULL) {
1112 comp->comp = xmlXPathCompile(comp->select);
1113 if (comp->comp == NULL) {
1114 xsltPrintErrorContext(NULL, style, inst);
1115 xsltGenericError(xsltGenericErrorContext,
1116 "xsl:variable : could not compile select expression '%s'\n",
1120 if (inst->children != NULL) {
1121 xsltPrintErrorContext(NULL, style, inst);
1122 xsltGenericError(xsltGenericErrorContext,
1123 "xsl:variable : content should be empty since select is present \n");
1131 * @style: a XSLT process context
1132 * @inst: the xslt param node
1134 * Process the xslt param node on the source node
1137 xsltParamComp(xsltStylesheetPtr style, xmlNodePtr inst) {
1138 xsltStylePreCompPtr comp;
1141 if ((style == NULL) || (inst == NULL))
1143 comp = xsltNewStylePreComp(style, XSLT_FUNC_PARAM);
1146 inst->_private = comp;
1150 * The full template resolution can be done statically
1152 prop = xsltGetNsProp(inst, (const xmlChar *)"name", XSLT_NAMESPACE);
1154 xsltPrintErrorContext(NULL, style, inst);
1155 xsltGenericError(xsltGenericErrorContext,
1156 "xsl:param : name is missing\n");
1161 URI = xsltGetQNameURI(inst, &prop);
1168 comp->ns = xmlStrdup(URI);
1176 comp->select = xsltGetNsProp(inst, (const xmlChar *)"select",
1178 if (comp->select != NULL) {
1179 comp->comp = xmlXPathCompile(comp->select);
1180 if (comp->comp == NULL) {
1181 xsltPrintErrorContext(NULL, style, inst);
1182 xsltGenericError(xsltGenericErrorContext,
1183 "xsl:param : could not compile select expression '%s'\n",
1187 if (inst->children != NULL) {
1188 xsltPrintErrorContext(NULL, style, inst);
1189 xsltGenericError(xsltGenericErrorContext,
1190 "xsl:param : content should be empty since select is present \n");
1197 /************************************************************************
1199 * Generic interface *
1201 ************************************************************************/
1204 * xsltFreeStylePreComps:
1205 * @style: an XSLT transformation context
1207 * Free up the memory allocated by all precomputed blocks
1210 xsltFreeStylePreComps(xsltStylesheetPtr style) {
1211 xsltElemPreCompPtr cur, next;
1215 cur = style->preComps;
1216 while (cur != NULL) {
1218 if (cur->type == XSLT_FUNC_EXTENSION)
1221 xsltFreeStylePreComp((xsltStylePreCompPtr) cur);
1227 * xsltStylePreCompute:
1228 * @style: the XSLT stylesheet
1229 * @inst: the instruction in the stylesheet
1231 * Precompute an XSLT stylesheet element
1234 xsltStylePreCompute(xsltStylesheetPtr style, xmlNodePtr inst) {
1235 if (inst->_private != NULL)
1237 if (IS_XSLT_ELEM(inst)) {
1238 xsltStylePreCompPtr cur;
1240 if (IS_XSLT_NAME(inst, "apply-templates")) {
1241 xsltApplyTemplatesComp(style, inst);
1242 } else if (IS_XSLT_NAME(inst, "with-param")) {
1243 xsltWithParamComp(style, inst);
1244 } else if (IS_XSLT_NAME(inst, "value-of")) {
1245 xsltValueOfComp(style, inst);
1246 } else if (IS_XSLT_NAME(inst, "copy")) {
1247 xsltCopyComp(style, inst);
1248 } else if (IS_XSLT_NAME(inst, "copy-of")) {
1249 xsltCopyOfComp(style, inst);
1250 } else if (IS_XSLT_NAME(inst, "if")) {
1251 xsltIfComp(style, inst);
1252 } else if (IS_XSLT_NAME(inst, "when")) {
1253 xsltWhenComp(style, inst);
1254 } else if (IS_XSLT_NAME(inst, "choose")) {
1255 xsltChooseComp(style, inst);
1256 } else if (IS_XSLT_NAME(inst, "for-each")) {
1257 xsltForEachComp(style, inst);
1258 } else if (IS_XSLT_NAME(inst, "apply-imports")) {
1259 xsltApplyImportsComp(style, inst);
1260 } else if (IS_XSLT_NAME(inst, "attribute")) {
1261 xsltAttributeComp(style, inst);
1262 } else if (IS_XSLT_NAME(inst, "element")) {
1263 xsltElementComp(style, inst);
1264 } else if (IS_XSLT_NAME(inst, "text")) {
1265 xsltTextComp(style, inst);
1266 } else if (IS_XSLT_NAME(inst, "sort")) {
1267 xsltSortComp(style, inst);
1268 } else if (IS_XSLT_NAME(inst, "comment")) {
1269 xsltCommentComp(style, inst);
1270 } else if (IS_XSLT_NAME(inst, "number")) {
1271 xsltNumberComp(style, inst);
1272 } else if (IS_XSLT_NAME(inst, "processing-instruction")) {
1273 xsltProcessingInstructionComp(style, inst);
1274 } else if (IS_XSLT_NAME(inst, "call-template")) {
1275 xsltCallTemplateComp(style, inst);
1276 } else if (IS_XSLT_NAME(inst, "param")) {
1277 xsltParamComp(style, inst);
1278 } else if (IS_XSLT_NAME(inst, "variable")) {
1279 xsltVariableComp(style, inst);
1280 } else if (IS_XSLT_NAME(inst, "otherwise")) {
1281 /* no computation needed */
1283 } else if (IS_XSLT_NAME(inst, "template")) {
1284 /* no computation needed */
1286 } else if (IS_XSLT_NAME(inst, "output")) {
1287 /* no computation needed */
1289 } else if (IS_XSLT_NAME(inst, "preserve-space")) {
1290 /* no computation needed */
1292 } else if (IS_XSLT_NAME(inst, "strip-space")) {
1293 /* no computation needed */
1295 } else if (IS_XSLT_NAME(inst, "stylesheet")) {
1296 /* no computation needed */
1298 } else if (IS_XSLT_NAME(inst, "transform")) {
1299 /* no computation needed */
1301 } else if (IS_XSLT_NAME(inst, "key")) {
1302 /* no computation needed */
1304 } else if (IS_XSLT_NAME(inst, "message")) {
1305 /* no computation needed */
1307 } else if (IS_XSLT_NAME(inst, "attribute-set")) {
1308 /* no computation needed */
1310 } else if (IS_XSLT_NAME(inst, "namespace-alias")) {
1311 /* no computation needed */
1313 } else if (IS_XSLT_NAME(inst, "include")) {
1314 /* no computation needed */
1316 } else if (IS_XSLT_NAME(inst, "import")) {
1317 /* no computation needed */
1319 } else if (IS_XSLT_NAME(inst, "decimal-format")) {
1320 /* no computation needed */
1322 } else if (IS_XSLT_NAME(inst, "fallback")) {
1323 /* no computation needed */
1325 } else if (IS_XSLT_NAME(inst, "document")) {
1326 inst->_private = (void *) xsltDocumentComp(style, inst,
1327 (xsltTransformFunction) xsltDocumentElem);
1329 xsltPrintErrorContext(NULL, style, inst);
1330 xsltGenericError(xsltGenericErrorContext,
1331 "xsltStylePreCompute: unknown xsl:%s\n", inst->name);
1335 * Add the namespace lookup here, this code can be shared by
1336 * all precomputations.
1338 cur = (xsltStylePreCompPtr) inst->_private;
1342 cur->nsList = xmlGetNsList(inst->doc, inst);
1343 if (cur->nsList != NULL) {
1344 while (cur->nsList[i] != NULL)
1351 (void *) xsltPreComputeExtModuleElement(style, inst);
1354 * Unknown element, maybe registered at the context
1355 * level. Mark it for later recognition.
1357 if (inst->_private == NULL)
1358 inst->_private = (void *) xsltExtMarker;