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.
22 #include <libxml/xmlmemory.h>
23 #include <libxml/parser.h>
24 #include <libxml/tree.h>
25 #include <libxml/valid.h>
26 #include <libxml/hash.h>
27 #include <libxml/uri.h>
28 #include <libxml/xmlerror.h>
30 #include "xsltutils.h"
31 #include "xsltInternals.h"
32 #include "transform.h"
33 #include "templates.h"
34 #include "variables.h"
35 #include "numbersInternals.h"
39 #include "extensions.h"
41 #ifdef WITH_XSLT_DEBUG
42 #define WITH_XSLT_DEBUG_PREPROC
45 const xmlChar *xsltExtMarker = (const xmlChar *) "Extension Element";
47 /************************************************************************
49 * handling of precomputed data *
51 ************************************************************************/
54 * xsltNewStylePreComp:
55 * @style: the XSLT stylesheet
56 * @type: the construct type
58 * Create a new XSLT Style precomputed block
60 * Returns the newly allocated xsltStylePreCompPtr or NULL in case of error
62 static xsltStylePreCompPtr
63 xsltNewStylePreComp(xsltStylesheetPtr style, xsltStyleType type) {
64 xsltStylePreCompPtr cur;
66 cur = (xsltStylePreCompPtr) xmlMalloc(sizeof(xsltStylePreComp));
68 xsltPrintErrorContext(NULL, style, NULL);
69 xsltGenericError(xsltGenericErrorContext,
70 "xsltNewStylePreComp : malloc failed\n");
74 memset(cur, 0, sizeof(xsltStylePreComp));
79 cur->func = (xsltTransformFunction) xsltCopy;break;
81 cur->func = (xsltTransformFunction) xsltSort;break;
83 cur->func = (xsltTransformFunction) xsltText;break;
84 case XSLT_FUNC_ELEMENT:
85 cur->func = (xsltTransformFunction) xsltElement;break;
86 case XSLT_FUNC_ATTRIBUTE:
87 cur->func = (xsltTransformFunction) xsltAttribute;break;
88 case XSLT_FUNC_COMMENT:
89 cur->func = (xsltTransformFunction) xsltComment;break;
91 cur->func = (xsltTransformFunction) xsltProcessingInstruction;
93 case XSLT_FUNC_COPYOF:
94 cur->func = (xsltTransformFunction) xsltCopyOf;break;
95 case XSLT_FUNC_VALUEOF:
96 cur->func = (xsltTransformFunction) xsltValueOf;break;
97 case XSLT_FUNC_NUMBER:
98 cur->func = (xsltTransformFunction) xsltNumber;break;
99 case XSLT_FUNC_APPLYIMPORTS:
100 cur->func = (xsltTransformFunction) xsltApplyImports;break;
101 case XSLT_FUNC_CALLTEMPLATE:
102 cur->func = (xsltTransformFunction) xsltCallTemplate;break;
103 case XSLT_FUNC_APPLYTEMPLATES:
104 cur->func = (xsltTransformFunction) xsltApplyTemplates;break;
105 case XSLT_FUNC_CHOOSE:
106 cur->func = (xsltTransformFunction) xsltChoose;break;
108 cur->func = (xsltTransformFunction) xsltIf;break;
109 case XSLT_FUNC_FOREACH:
110 cur->func = (xsltTransformFunction) xsltForEach;break;
111 case XSLT_FUNC_DOCUMENT:
112 cur->func = (xsltTransformFunction) xsltDocumentElem;break;
113 case XSLT_FUNC_WITHPARAM:
114 cur->func = NULL;break;
115 case XSLT_FUNC_PARAM:
116 cur->func = NULL;break;
117 case XSLT_FUNC_VARIABLE:
118 cur->func = NULL;break;
120 cur->func = NULL;break;
122 if (cur->func == NULL) {
123 xsltPrintErrorContext(NULL, style, NULL);
124 xsltGenericError(xsltGenericErrorContext,
125 "xsltNewStylePreComp : no function for type %d\n", type);
129 cur->next = style->preComps;
130 style->preComps = (xsltElemPreCompPtr) cur;
136 * xsltFreeStylePreComp:
137 * @comp: an XSLT Style precomputed block
139 * Free up the memory allocated by @comp
142 xsltFreeStylePreComp(xsltStylePreCompPtr comp) {
145 if (comp->stype != NULL)
146 xmlFree(comp->stype);
147 if (comp->order != NULL)
148 xmlFree(comp->order);
149 if (comp->use != NULL)
151 if (comp->name != NULL)
153 if (comp->ns != NULL)
155 if (comp->mode != NULL)
157 if (comp->modeURI != NULL)
158 xmlFree(comp->modeURI);
159 if (comp->test != NULL)
161 if (comp->select != NULL)
162 xmlFree(comp->select);
164 if (comp->filename != NULL)
165 xmlFree(comp->filename);
167 if (comp->numdata.level != NULL)
168 xmlFree(comp->numdata.level);
169 if (comp->numdata.count != NULL)
170 xmlFree(comp->numdata.count);
171 if (comp->numdata.from != NULL)
172 xmlFree(comp->numdata.from);
173 if (comp->numdata.value != NULL)
174 xmlFree(comp->numdata.value);
175 if (comp->numdata.format != NULL)
176 xmlFree(comp->numdata.format);
177 if (comp->comp != NULL)
178 xmlXPathFreeCompExpr(comp->comp);
179 if (comp->nsList != NULL)
180 xmlFree(comp->nsList);
186 /************************************************************************
188 * XSLT-1.1 extensions *
190 ************************************************************************/
194 * @style: the XSLT stylesheet
195 * @inst: the instruction in the stylesheet
197 * Pre process an XSLT-1.1 document element
200 xsltDocumentComp(xsltStylesheetPtr style, xmlNodePtr inst,
201 xsltTransformFunction function ATTRIBUTE_UNUSED) {
202 xsltStylePreCompPtr comp;
203 xmlChar *filename = NULL;
204 xmlChar *base = NULL;
207 comp = xsltNewStylePreComp(style, XSLT_FUNC_DOCUMENT);
213 if (xmlStrEqual(inst->name, (const xmlChar *) "output")) {
214 #ifdef WITH_XSLT_DEBUG_EXTRA
215 xsltGenericDebug(xsltGenericDebugContext,
216 "Found saxon:output extension\n");
218 filename = xsltEvalStaticAttrValueTemplate(style, inst,
219 (const xmlChar *)"file",
220 XSLT_SAXON_NAMESPACE, &comp->has_filename);
221 } else if (xmlStrEqual(inst->name, (const xmlChar *) "write")) {
222 #ifdef WITH_XSLT_DEBUG_EXTRA
223 xsltGenericDebug(xsltGenericDebugContext,
224 "Found xalan:write extension\n");
226 comp->ver11 = 0; /* the filename need to be interpreted */
227 } else if (xmlStrEqual(inst->name, (const xmlChar *) "document")) {
228 filename = xsltEvalStaticAttrValueTemplate(style, inst,
229 (const xmlChar *)"href",
230 XSLT_XT_NAMESPACE, &comp->has_filename);
231 if (comp->has_filename == 0) {
232 #ifdef WITH_XSLT_DEBUG_EXTRA
233 xsltGenericDebug(xsltGenericDebugContext,
234 "Found xslt11:document construct\n");
236 filename = xsltEvalStaticAttrValueTemplate(style, inst,
237 (const xmlChar *)"href",
238 XSLT_NAMESPACE, &comp->has_filename);
241 #ifdef WITH_XSLT_DEBUG_EXTRA
242 xsltGenericDebug(xsltGenericDebugContext,
243 "Found xt:document extension\n");
248 if (!comp->has_filename) {
252 if (filename != NULL) {
256 base = xmlNodeGetBase(inst->doc, inst);
257 URL = xmlBuildURI(filename, base);
259 xsltPrintErrorContext(NULL, style, inst);
260 xsltGenericError(xsltGenericErrorContext,
261 "xsltDocumentComp: URL computation failed %s\n", filename);
263 comp->filename = xmlStrdup(filename);
265 comp->filename = URL;
268 comp->filename = NULL;
274 if (filename != NULL)
277 return ((xsltElemPreCompPtr) comp);
280 /************************************************************************
282 * Most of the XSLT-1.0 transformations *
284 ************************************************************************/
288 * @style: the XSLT stylesheet
289 * @inst: the xslt sort node
291 * Process the xslt sort node on the source node
294 xsltSortComp(xsltStylesheetPtr style, xmlNodePtr inst) {
295 xsltStylePreCompPtr comp;
298 if ((style == NULL) || (inst == NULL))
300 comp = xsltNewStylePreComp(style, XSLT_FUNC_SORT);
303 inst->_private = comp;
306 comp->stype = xsltEvalStaticAttrValueTemplate(style, inst,
307 (const xmlChar *)"data-type",
308 XSLT_NAMESPACE, &comp->has_stype);
309 if (comp->stype != NULL) {
310 if (xmlStrEqual(comp->stype, (const xmlChar *) "text"))
312 else if (xmlStrEqual(comp->stype, (const xmlChar *) "number"))
315 xsltPrintErrorContext(NULL, style, inst);
316 xsltGenericError(xsltGenericErrorContext,
317 "xsltSortComp: no support for data-type = %s\n", comp->stype);
322 comp->order = xsltEvalStaticAttrValueTemplate(style, inst,
323 (const xmlChar *)"order",
324 XSLT_NAMESPACE, &comp->has_order);
325 if (comp->order != NULL) {
326 if (xmlStrEqual(comp->order, (const xmlChar *) "ascending"))
327 comp->descending = 0;
328 else if (xmlStrEqual(comp->order, (const xmlChar *) "descending"))
329 comp->descending = 1;
331 xsltPrintErrorContext(NULL, style, inst);
332 xsltGenericError(xsltGenericErrorContext,
333 "xsltSortComp: invalid value %s for order\n", comp->order);
334 comp->descending = -1;
338 /* TODO: xsl:sort lang attribute */
339 /* TODO: xsl:sort case-order attribute */
341 comp->select = xsltGetNsProp(inst,(const xmlChar *)"select", XSLT_NAMESPACE);
342 if (comp->select == NULL) {
344 * The default value of the select attribute is ., which will
345 * cause the string-value of the current node to be used as
348 comp->select = xmlStrdup((const xmlChar *)".");
350 comp->comp = xmlXPathCompile(comp->select);
351 if (comp->comp == NULL) {
352 xsltPrintErrorContext(NULL, style, inst);
353 xsltGenericError(xsltGenericErrorContext,
354 "xsltSortComp: could not compile select expression '%s'\n",
362 * @style: the XSLT stylesheet
363 * @inst: the xslt copy node
365 * Process the xslt copy node on the source node
368 xsltCopyComp(xsltStylesheetPtr style, xmlNodePtr inst) {
369 xsltStylePreCompPtr comp;
372 if ((style == NULL) || (inst == NULL))
374 comp = xsltNewStylePreComp(style, XSLT_FUNC_COPY);
377 inst->_private = comp;
381 comp->use = xsltGetNsProp(inst, (const xmlChar *)"use-attribute-sets",
383 if (comp->use == NULL)
391 * @style: a XSLT process context
392 * @inst: the xslt text node
394 * Process the xslt text node on the source node
397 xsltTextComp(xsltStylesheetPtr style, xmlNodePtr inst) {
398 xsltStylePreCompPtr comp;
401 if ((style == NULL) || (inst == NULL))
403 comp = xsltNewStylePreComp(style, XSLT_FUNC_TEXT);
406 inst->_private = comp;
410 prop = xsltGetNsProp(inst,
411 (const xmlChar *)"disable-output-escaping",
414 if (xmlStrEqual(prop, (const xmlChar *)"yes")) {
416 } else if (!xmlStrEqual(prop,
417 (const xmlChar *)"no")){
418 xsltPrintErrorContext(NULL, style, inst);
419 xsltGenericError(xsltGenericErrorContext,
420 "xsl:text: disable-output-escaping allows only yes or no\n");
429 * @style: a XSLT process context
430 * @inst: the xslt element node
432 * Process the xslt element node on the source node
435 xsltElementComp(xsltStylesheetPtr style, xmlNodePtr inst) {
436 xsltStylePreCompPtr comp;
438 if ((style == NULL) || (inst == NULL))
440 comp = xsltNewStylePreComp(style, XSLT_FUNC_ELEMENT);
443 inst->_private = comp;
447 * TODO: more computation can be done there, especially namespace lookup
449 comp->name = xsltEvalStaticAttrValueTemplate(style, inst,
450 (const xmlChar *)"name",
451 XSLT_NAMESPACE, &comp->has_name);
452 comp->ns = xsltEvalStaticAttrValueTemplate(style, inst,
453 (const xmlChar *)"namespace",
454 XSLT_NAMESPACE, &comp->has_ns);
456 comp->use = xsltEvalStaticAttrValueTemplate(style, inst,
457 (const xmlChar *)"use-attribute-sets",
458 XSLT_NAMESPACE, &comp->has_use);
463 * @style: a XSLT process context
464 * @inst: the xslt attribute node
466 * Process the xslt attribute node on the source node
469 xsltAttributeComp(xsltStylesheetPtr style, xmlNodePtr inst) {
470 xsltStylePreCompPtr comp;
472 if ((style == NULL) || (inst == NULL))
474 comp = xsltNewStylePreComp(style, XSLT_FUNC_ATTRIBUTE);
477 inst->_private = comp;
481 * TODO: more computation can be done there, especially namespace lookup
483 comp->name = xsltEvalStaticAttrValueTemplate(style, inst,
484 (const xmlChar *)"name",
485 XSLT_NAMESPACE, &comp->has_name);
486 comp->ns = xsltEvalStaticAttrValueTemplate(style, inst,
487 (const xmlChar *)"namespace",
488 XSLT_NAMESPACE, &comp->has_ns);
494 * @style: a XSLT process context
495 * @inst: the xslt comment node
497 * Process the xslt comment node on the source node
500 xsltCommentComp(xsltStylesheetPtr style, xmlNodePtr inst) {
501 xsltStylePreCompPtr comp;
503 if ((style == NULL) || (inst == NULL))
505 comp = xsltNewStylePreComp(style, XSLT_FUNC_COMMENT);
508 inst->_private = comp;
513 * xsltProcessingInstructionComp:
514 * @style: a XSLT process context
515 * @inst: the xslt processing-instruction node
517 * Process the xslt processing-instruction node on the source node
520 xsltProcessingInstructionComp(xsltStylesheetPtr style, xmlNodePtr inst) {
521 xsltStylePreCompPtr comp;
523 if ((style == NULL) || (inst == NULL))
525 comp = xsltNewStylePreComp(style, XSLT_FUNC_PI);
528 inst->_private = comp;
531 comp->name = xsltEvalStaticAttrValueTemplate(style, inst,
532 (const xmlChar *)"name",
533 XSLT_NAMESPACE, &comp->has_name);
538 * @style: a XSLT process context
539 * @inst: the xslt copy-of node
541 * Process the xslt copy-of node on the source node
544 xsltCopyOfComp(xsltStylesheetPtr style, xmlNodePtr inst) {
545 xsltStylePreCompPtr comp;
547 if ((style == NULL) || (inst == NULL))
549 comp = xsltNewStylePreComp(style, XSLT_FUNC_COPYOF);
552 inst->_private = comp;
555 comp->select = xsltGetNsProp(inst, (const xmlChar *)"select",
557 if (comp->select == NULL) {
558 xsltPrintErrorContext(NULL, style, inst);
559 xsltGenericError(xsltGenericErrorContext,
560 "xsl:copy-of : select is missing\n");
564 comp->comp = xmlXPathCompile(comp->select);
565 if (comp->comp == NULL) {
566 xsltPrintErrorContext(NULL, style, inst);
567 xsltGenericError(xsltGenericErrorContext,
568 "xsl:copy-of : could not compile select expression '%s'\n",
576 * @style: a XSLT process context
577 * @inst: the xslt value-of node
579 * Process the xslt value-of node on the source node
582 xsltValueOfComp(xsltStylesheetPtr style, xmlNodePtr inst) {
583 xsltStylePreCompPtr comp;
586 if ((style == NULL) || (inst == NULL))
588 comp = xsltNewStylePreComp(style, XSLT_FUNC_VALUEOF);
591 inst->_private = comp;
594 prop = xsltGetNsProp(inst,
595 (const xmlChar *)"disable-output-escaping",
598 if (xmlStrEqual(prop, (const xmlChar *)"yes")) {
600 } else if (!xmlStrEqual(prop,
601 (const xmlChar *)"no")){
602 xsltPrintErrorContext(NULL, style, inst);
603 xsltGenericError(xsltGenericErrorContext,
604 "xsl:value-of : disable-output-escaping allows only yes or no\n");
609 comp->select = xsltGetNsProp(inst, (const xmlChar *)"select",
611 if (comp->select == NULL) {
612 xsltPrintErrorContext(NULL, style, inst);
613 xsltGenericError(xsltGenericErrorContext,
614 "xsl:value-of : select is missing\n");
618 comp->comp = xmlXPathCompile(comp->select);
619 if (comp->comp == NULL) {
620 xsltPrintErrorContext(NULL, style, inst);
621 xsltGenericError(xsltGenericErrorContext,
622 "xsl:value-of : could not compile select expression '%s'\n",
630 * @style: a XSLT process context
631 * @inst: the xslt with-param node
633 * Process the xslt with-param node on the source node
636 xsltWithParamComp(xsltStylesheetPtr style, xmlNodePtr inst) {
637 xsltStylePreCompPtr comp;
640 if ((style == NULL) || (inst == NULL))
642 comp = xsltNewStylePreComp(style, XSLT_FUNC_WITHPARAM);
645 inst->_private = comp;
649 * The full namespace resolution can be done statically
651 prop = xsltGetNsProp(inst, (const xmlChar *)"name", XSLT_NAMESPACE);
653 xsltPrintErrorContext(NULL, style, inst);
654 xsltGenericError(xsltGenericErrorContext,
655 "xsl:with-param : name is missing\n");
660 URI = xsltGetQNameURI(inst, &prop);
667 comp->ns = xmlStrdup(URI);
675 comp->select = xsltGetNsProp(inst, (const xmlChar *)"select",
677 if (comp->select != NULL) {
678 comp->comp = xmlXPathCompile(comp->select);
679 if (comp->comp == NULL) {
680 xsltPrintErrorContext(NULL, style, inst);
681 xsltGenericError(xsltGenericErrorContext,
682 "xsl:param : could not compile select expression '%s'\n",
686 if (inst->children != NULL) {
687 xsltPrintErrorContext(NULL, style, inst);
688 xsltGenericError(xsltGenericErrorContext,
689 "xsl:param : content should be empty since select is present \n");
697 * @style: a XSLT process context
698 * @cur: the xslt number node
700 * Process the xslt number node on the source node
703 xsltNumberComp(xsltStylesheetPtr style, xmlNodePtr cur) {
704 xsltStylePreCompPtr comp;
707 if ((style == NULL) || (cur == NULL))
709 comp = xsltNewStylePreComp(style, XSLT_FUNC_NUMBER);
712 cur->_private = comp;
714 if ((style == NULL) || (cur == NULL))
717 comp->numdata.doc = cur->doc;
718 comp->numdata.node = cur;
719 comp->numdata.value = xsltGetNsProp(cur, (const xmlChar *)"value",
722 prop = xsltEvalStaticAttrValueTemplate(style, cur,
723 (const xmlChar *)"format",
724 XSLT_NAMESPACE, &comp->numdata.has_format);
725 if (comp->numdata.has_format == 0) {
726 comp->numdata.format = xmlStrdup(BAD_CAST(""));
728 comp->numdata.format = prop;
731 comp->numdata.count = xsltGetNsProp(cur, (const xmlChar *)"count",
733 comp->numdata.from = xsltGetNsProp(cur, (const xmlChar *)"from",
736 prop = xsltGetNsProp(cur, (const xmlChar *)"level", XSLT_NAMESPACE);
738 if (xmlStrEqual(prop, BAD_CAST("single")) ||
739 xmlStrEqual(prop, BAD_CAST("multiple")) ||
740 xmlStrEqual(prop, BAD_CAST("any"))) {
741 comp->numdata.level = prop;
743 xsltPrintErrorContext(NULL, style, cur);
744 xsltGenericError(xsltGenericErrorContext,
745 "xsl:number : invalid value %s for level\n", prop);
751 prop = xsltGetNsProp(cur, (const xmlChar *)"lang", XSLT_NAMESPACE);
753 XSLT_TODO; /* xsl:number lang attribute */
757 prop = xsltGetNsProp(cur, (const xmlChar *)"letter-value", XSLT_NAMESPACE);
759 if (xmlStrEqual(prop, BAD_CAST("alphabetic"))) {
760 xsltPrintErrorContext(NULL, style, cur);
761 xsltGenericError(xsltGenericErrorContext,
762 "xsl:number : letter-value 'alphabetic' not implemented\n");
764 XSLT_TODO; /* xsl:number letter-value attribute alphabetic */
765 } else if (xmlStrEqual(prop, BAD_CAST("traditional"))) {
766 xsltPrintErrorContext(NULL, style, cur);
767 xsltGenericError(xsltGenericErrorContext,
768 "xsl:number : letter-value 'traditional' not implemented\n");
770 XSLT_TODO; /* xsl:number letter-value attribute traditional */
772 xsltPrintErrorContext(NULL, style, cur);
773 xsltGenericError(xsltGenericErrorContext,
774 "xsl:number : invalid value %s for letter-value\n", prop);
780 prop = xsltGetNsProp(cur, (const xmlChar *)"grouping-separator",
783 comp->numdata.groupingCharacter = prop[0];
787 prop = xsltGetNsProp(cur, (const xmlChar *)"grouping-size", XSLT_NAMESPACE);
789 sscanf((char *)prop, "%d", &comp->numdata.digitsPerGroup);
792 comp->numdata.groupingCharacter = 0;
795 /* Set default values */
796 if (comp->numdata.value == NULL) {
797 if (comp->numdata.level == NULL) {
798 comp->numdata.level = xmlStrdup(BAD_CAST("single"));
805 * xsltApplyImportsComp:
806 * @style: a XSLT process context
807 * @inst: the xslt apply-imports node
809 * Process the xslt apply-imports node on the source node
812 xsltApplyImportsComp(xsltStylesheetPtr style, xmlNodePtr inst) {
813 xsltStylePreCompPtr comp;
815 if ((style == NULL) || (inst == NULL))
817 comp = xsltNewStylePreComp(style, XSLT_FUNC_APPLYIMPORTS);
820 inst->_private = comp;
825 * xsltCallTemplateComp:
826 * @style: a XSLT process context
827 * @inst: the xslt call-template node
829 * Process the xslt call-template node on the source node
832 xsltCallTemplateComp(xsltStylesheetPtr style, xmlNodePtr inst) {
833 xsltStylePreCompPtr comp;
836 if ((style == NULL) || (inst == NULL))
838 comp = xsltNewStylePreComp(style, XSLT_FUNC_CALLTEMPLATE);
841 inst->_private = comp;
845 * The full template resolution can be done statically
847 prop = xsltGetNsProp(inst, (const xmlChar *)"name", XSLT_NAMESPACE);
849 xsltPrintErrorContext(NULL, style, inst);
850 xsltGenericError(xsltGenericErrorContext,
851 "xsl:call-template : name is missing\n");
856 URI = xsltGetQNameURI(inst, &prop);
863 comp->ns = xmlStrdup(URI);
874 * xsltApplyTemplatesComp:
875 * @style: a XSLT process context
876 * @inst: the apply-templates node
878 * Process the apply-templates node on the source node
881 xsltApplyTemplatesComp(xsltStylesheetPtr style, xmlNodePtr inst) {
882 xsltStylePreCompPtr comp;
885 if ((style == NULL) || (inst == NULL))
887 comp = xsltNewStylePreComp(style, XSLT_FUNC_APPLYTEMPLATES);
890 inst->_private = comp;
896 prop = xsltGetNsProp(inst, (const xmlChar *)"mode", XSLT_NAMESPACE);
900 URI = xsltGetQNameURI(inst, &prop);
906 comp->modeURI = xmlStrdup(URI);
908 comp->modeURI = NULL;
912 comp->select = xsltGetNsProp(inst, (const xmlChar *)"select",
914 if (comp->select != NULL) {
915 comp->comp = xmlXPathCompile(comp->select);
916 if (comp->comp == NULL) {
917 xsltPrintErrorContext(NULL, style, inst);
918 xsltGenericError(xsltGenericErrorContext,
919 "xsl:apply-templates : could not compile select expression '%s'\n",
925 /* TODO: handle (or skip) the xsl:sort and xsl:with-param */
930 * @style: a XSLT process context
931 * @inst: the xslt choose node
933 * Process the xslt choose node on the source node
936 xsltChooseComp(xsltStylesheetPtr style, xmlNodePtr inst) {
937 xsltStylePreCompPtr comp;
939 if ((style == NULL) || (inst == NULL))
941 comp = xsltNewStylePreComp(style, XSLT_FUNC_CHOOSE);
944 inst->_private = comp;
950 * @style: a XSLT process context
951 * @inst: the xslt if node
953 * Process the xslt if node on the source node
956 xsltIfComp(xsltStylesheetPtr style, xmlNodePtr inst) {
957 xsltStylePreCompPtr comp;
959 if ((style == NULL) || (inst == NULL))
961 comp = xsltNewStylePreComp(style, XSLT_FUNC_IF);
964 inst->_private = comp;
967 comp->test = xsltGetNsProp(inst, (const xmlChar *)"test", XSLT_NAMESPACE);
968 if (comp->test == NULL) {
969 xsltPrintErrorContext(NULL, style, inst);
970 xsltGenericError(xsltGenericErrorContext,
971 "xsl:if : test is not defined\n");
975 comp->comp = xmlXPathCompile(comp->test);
976 if (comp->comp == NULL) {
977 xsltPrintErrorContext(NULL, style, inst);
978 xsltGenericError(xsltGenericErrorContext,
979 "xsl:if : could not compile test expression '%s'\n",
987 * @style: a XSLT process context
988 * @inst: the xslt if node
990 * Process the xslt if node on the source node
993 xsltWhenComp(xsltStylesheetPtr style, xmlNodePtr inst) {
994 xsltStylePreCompPtr comp;
996 if ((style == NULL) || (inst == NULL))
998 comp = xsltNewStylePreComp(style, XSLT_FUNC_WHEN);
1001 inst->_private = comp;
1004 comp->test = xsltGetNsProp(inst, (const xmlChar *)"test", XSLT_NAMESPACE);
1005 if (comp->test == NULL) {
1006 xsltPrintErrorContext(NULL, style, inst);
1007 xsltGenericError(xsltGenericErrorContext,
1008 "xsl:when : test is not defined\n");
1012 comp->comp = xmlXPathCompile(comp->test);
1013 if (comp->comp == NULL) {
1014 xsltPrintErrorContext(NULL, style, inst);
1015 xsltGenericError(xsltGenericErrorContext,
1016 "xsl:when : could not compile test expression '%s'\n",
1024 * @style: a XSLT process context
1025 * @inst: the xslt for-each node
1027 * Process the xslt for-each node on the source node
1030 xsltForEachComp(xsltStylesheetPtr style, xmlNodePtr inst) {
1031 xsltStylePreCompPtr comp;
1033 if ((style == NULL) || (inst == NULL))
1035 comp = xsltNewStylePreComp(style, XSLT_FUNC_FOREACH);
1038 inst->_private = comp;
1041 comp->select = xsltGetNsProp(inst, (const xmlChar *)"select",
1043 if (comp->select == NULL) {
1044 xsltPrintErrorContext(NULL, style, inst);
1045 xsltGenericError(xsltGenericErrorContext,
1046 "xsl:for-each : select is missing\n");
1049 comp->comp = xmlXPathCompile(comp->select);
1050 if (comp->comp == NULL) {
1051 xsltPrintErrorContext(NULL, style, inst);
1052 xsltGenericError(xsltGenericErrorContext,
1053 "xsl:for-each : could not compile select expression '%s'\n",
1058 /* TODO: handle and skip the xsl:sort */
1063 * @style: a XSLT process context
1064 * @inst: the xslt variable node
1066 * Process the xslt variable node on the source node
1069 xsltVariableComp(xsltStylesheetPtr style, xmlNodePtr inst) {
1070 xsltStylePreCompPtr comp;
1073 if ((style == NULL) || (inst == NULL))
1075 comp = xsltNewStylePreComp(style, XSLT_FUNC_VARIABLE);
1078 inst->_private = comp;
1082 * The full template resolution can be done statically
1084 prop = xsltGetNsProp(inst, (const xmlChar *)"name", XSLT_NAMESPACE);
1086 xsltPrintErrorContext(NULL, style, inst);
1087 xsltGenericError(xsltGenericErrorContext,
1088 "xsl:variable : name is missing\n");
1093 URI = xsltGetQNameURI(inst, &prop);
1100 comp->ns = xmlStrdup(URI);
1108 comp->select = xsltGetNsProp(inst, (const xmlChar *)"select",
1110 if (comp->select != NULL) {
1111 comp->comp = xmlXPathCompile(comp->select);
1112 if (comp->comp == NULL) {
1113 xsltPrintErrorContext(NULL, style, inst);
1114 xsltGenericError(xsltGenericErrorContext,
1115 "xsl:variable : could not compile select expression '%s'\n",
1119 if (inst->children != NULL) {
1120 xsltPrintErrorContext(NULL, style, inst);
1121 xsltGenericError(xsltGenericErrorContext,
1122 "xsl:variable : content should be empty since select is present \n");
1130 * @style: a XSLT process context
1131 * @inst: the xslt param node
1133 * Process the xslt param node on the source node
1136 xsltParamComp(xsltStylesheetPtr style, xmlNodePtr inst) {
1137 xsltStylePreCompPtr comp;
1140 if ((style == NULL) || (inst == NULL))
1142 comp = xsltNewStylePreComp(style, XSLT_FUNC_PARAM);
1145 inst->_private = comp;
1149 * The full template resolution can be done statically
1151 prop = xsltGetNsProp(inst, (const xmlChar *)"name", XSLT_NAMESPACE);
1153 xsltPrintErrorContext(NULL, style, inst);
1154 xsltGenericError(xsltGenericErrorContext,
1155 "xsl:param : name is missing\n");
1160 URI = xsltGetQNameURI(inst, &prop);
1167 comp->ns = xmlStrdup(URI);
1175 comp->select = xsltGetNsProp(inst, (const xmlChar *)"select",
1177 if (comp->select != NULL) {
1178 comp->comp = xmlXPathCompile(comp->select);
1179 if (comp->comp == NULL) {
1180 xsltPrintErrorContext(NULL, style, inst);
1181 xsltGenericError(xsltGenericErrorContext,
1182 "xsl:param : could not compile select expression '%s'\n",
1186 if (inst->children != NULL) {
1187 xsltPrintErrorContext(NULL, style, inst);
1188 xsltGenericError(xsltGenericErrorContext,
1189 "xsl:param : content should be empty since select is present \n");
1196 /************************************************************************
1198 * Generic interface *
1200 ************************************************************************/
1203 * xsltFreeStylePreComps:
1204 * @style: an XSLT transformation context
1206 * Free up the memory allocated by all precomputed blocks
1209 xsltFreeStylePreComps(xsltStylesheetPtr style) {
1210 xsltElemPreCompPtr cur, next;
1214 cur = style->preComps;
1215 while (cur != NULL) {
1217 if (cur->type == XSLT_FUNC_EXTENSION)
1220 xsltFreeStylePreComp((xsltStylePreCompPtr) cur);
1226 * xsltStylePreCompute:
1227 * @style: the XSLT stylesheet
1228 * @inst: the instruction in the stylesheet
1230 * Precompute an XSLT stylesheet element
1233 xsltStylePreCompute(xsltStylesheetPtr style, xmlNodePtr inst) {
1234 if (inst->_private != NULL)
1236 if (IS_XSLT_ELEM(inst)) {
1237 xsltStylePreCompPtr cur;
1239 if (IS_XSLT_NAME(inst, "apply-templates")) {
1240 xsltApplyTemplatesComp(style, inst);
1241 } else if (IS_XSLT_NAME(inst, "with-param")) {
1242 xsltWithParamComp(style, inst);
1243 } else if (IS_XSLT_NAME(inst, "value-of")) {
1244 xsltValueOfComp(style, inst);
1245 } else if (IS_XSLT_NAME(inst, "copy")) {
1246 xsltCopyComp(style, inst);
1247 } else if (IS_XSLT_NAME(inst, "copy-of")) {
1248 xsltCopyOfComp(style, inst);
1249 } else if (IS_XSLT_NAME(inst, "if")) {
1250 xsltIfComp(style, inst);
1251 } else if (IS_XSLT_NAME(inst, "when")) {
1252 xsltWhenComp(style, inst);
1253 } else if (IS_XSLT_NAME(inst, "choose")) {
1254 xsltChooseComp(style, inst);
1255 } else if (IS_XSLT_NAME(inst, "for-each")) {
1256 xsltForEachComp(style, inst);
1257 } else if (IS_XSLT_NAME(inst, "apply-imports")) {
1258 xsltApplyImportsComp(style, inst);
1259 } else if (IS_XSLT_NAME(inst, "attribute")) {
1260 xsltAttributeComp(style, inst);
1261 } else if (IS_XSLT_NAME(inst, "element")) {
1262 xsltElementComp(style, inst);
1263 } else if (IS_XSLT_NAME(inst, "text")) {
1264 xsltTextComp(style, inst);
1265 } else if (IS_XSLT_NAME(inst, "sort")) {
1266 xsltSortComp(style, inst);
1267 } else if (IS_XSLT_NAME(inst, "comment")) {
1268 xsltCommentComp(style, inst);
1269 } else if (IS_XSLT_NAME(inst, "number")) {
1270 xsltNumberComp(style, inst);
1271 } else if (IS_XSLT_NAME(inst, "processing-instruction")) {
1272 xsltProcessingInstructionComp(style, inst);
1273 } else if (IS_XSLT_NAME(inst, "call-template")) {
1274 xsltCallTemplateComp(style, inst);
1275 } else if (IS_XSLT_NAME(inst, "param")) {
1276 xsltParamComp(style, inst);
1277 } else if (IS_XSLT_NAME(inst, "variable")) {
1278 xsltVariableComp(style, inst);
1279 } else if (IS_XSLT_NAME(inst, "otherwise")) {
1280 /* no computation needed */
1282 } else if (IS_XSLT_NAME(inst, "template")) {
1283 /* no computation needed */
1285 } else if (IS_XSLT_NAME(inst, "output")) {
1286 /* no computation needed */
1288 } else if (IS_XSLT_NAME(inst, "preserve-space")) {
1289 /* no computation needed */
1291 } else if (IS_XSLT_NAME(inst, "strip-space")) {
1292 /* no computation needed */
1294 } else if (IS_XSLT_NAME(inst, "stylesheet")) {
1295 /* no computation needed */
1297 } else if (IS_XSLT_NAME(inst, "transform")) {
1298 /* no computation needed */
1300 } else if (IS_XSLT_NAME(inst, "key")) {
1301 /* no computation needed */
1303 } else if (IS_XSLT_NAME(inst, "message")) {
1304 /* no computation needed */
1306 } else if (IS_XSLT_NAME(inst, "attribute-set")) {
1307 /* no computation needed */
1309 } else if (IS_XSLT_NAME(inst, "namespace-alias")) {
1310 /* no computation needed */
1312 } else if (IS_XSLT_NAME(inst, "include")) {
1313 /* no computation needed */
1315 } else if (IS_XSLT_NAME(inst, "import")) {
1316 /* no computation needed */
1318 } else if (IS_XSLT_NAME(inst, "decimal-format")) {
1319 /* no computation needed */
1321 } else if (IS_XSLT_NAME(inst, "fallback")) {
1322 /* no computation needed */
1324 } else if (IS_XSLT_NAME(inst, "document")) {
1325 inst->_private = (void *) xsltDocumentComp(style, inst,
1326 (xsltTransformFunction) xsltDocumentElem);
1328 xsltPrintErrorContext(NULL, style, inst);
1329 xsltGenericError(xsltGenericErrorContext,
1330 "xsltStylePreCompute: unknown xsl:%s\n", inst->name);
1334 * Add the namespace lookup here, this code can be shared by
1335 * all precomputations.
1337 cur = (xsltStylePreCompPtr) inst->_private;
1341 cur->nsList = xmlGetNsList(inst->doc, inst);
1342 if (cur->nsList != NULL) {
1343 while (cur->nsList[i] != NULL)
1350 (void *) xsltPreComputeExtModuleElement(style, inst);
1353 * Unknown element, maybe registered at the context
1354 * level. Mark it for later recognition.
1356 if (inst->_private == NULL)
1357 inst->_private = (void *) xsltExtMarker;