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/encoding.h>
30 #include <libxml/xmlerror.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"
41 #include "extensions.h"
43 #ifdef WITH_XSLT_DEBUG
44 #define WITH_XSLT_DEBUG_PREPROC
47 const xmlChar
*xsltExtMarker
= (const xmlChar
*) "Extension Element";
49 /************************************************************************
53 ************************************************************************/
55 #ifdef XSLT_REFACTORED
57 * Grammar checks are now performed in xslt.c.
61 * xsltCheckTopLevelElement:
62 * @style: the XSLT stylesheet
63 * @inst: the XSLT instruction
64 * @err: raise an error or not
66 * Check that the instruction is instanciated as a top level element.
68 * Returns -1 in case of error, 0 if failed and 1 in case of success
71 xsltCheckTopLevelElement(xsltStylesheetPtr style
, xmlNodePtr inst
, int err
) {
73 if ((style
== NULL
) || (inst
== NULL
) || (inst
->ns
== NULL
))
76 parent
= inst
->parent
;
79 xsltTransformError(NULL
, style
, inst
,
80 "internal problem: element has no parent\n");
85 if ((parent
->ns
== NULL
) || (parent
->type
!= XML_ELEMENT_NODE
) ||
86 ((parent
->ns
!= inst
->ns
) &&
87 (!xmlStrEqual(parent
->ns
->href
, inst
->ns
->href
))) ||
88 ((!xmlStrEqual(parent
->name
, BAD_CAST
"stylesheet")) &&
89 (!xmlStrEqual(parent
->name
, BAD_CAST
"transform")))) {
91 xsltTransformError(NULL
, style
, inst
,
92 "element %s only allowed as child of stylesheet\n",
102 * xsltCheckInstructionElement:
103 * @style: the XSLT stylesheet
104 * @inst: the XSLT instruction
106 * Check that the instruction is instanciated as an instruction element.
109 xsltCheckInstructionElement(xsltStylesheetPtr style
, xmlNodePtr inst
) {
113 if ((style
== NULL
) || (inst
== NULL
) || (inst
->ns
== NULL
) ||
114 (style
->literal_result
))
117 has_ext
= (style
->extInfos
!= NULL
);
119 parent
= inst
->parent
;
120 if (parent
== NULL
) {
121 xsltTransformError(NULL
, style
, inst
,
122 "internal problem: element has no parent\n");
126 while ((parent
!= NULL
) && (parent
->type
!= XML_DOCUMENT_NODE
)) {
127 if (((parent
->ns
== inst
->ns
) ||
128 ((parent
->ns
!= NULL
) &&
129 (xmlStrEqual(parent
->ns
->href
, inst
->ns
->href
)))) &&
130 ((xmlStrEqual(parent
->name
, BAD_CAST
"template")) ||
131 (xmlStrEqual(parent
->name
, BAD_CAST
"param")) ||
132 (xmlStrEqual(parent
->name
, BAD_CAST
"attribute")) ||
133 (xmlStrEqual(parent
->name
, BAD_CAST
"variable")))) {
138 * if we are within an extension element all bets are off
139 * about the semantic there e.g. xsl:param within func:function
141 if ((has_ext
) && (parent
->ns
!= NULL
) &&
142 (xmlHashLookup(style
->extInfos
, parent
->ns
->href
) != NULL
))
145 parent
= parent
->parent
;
147 xsltTransformError(NULL
, style
, inst
,
148 "element %s only allowed within a template, variable or param\n",
154 * xsltCheckParentElement:
155 * @style: the XSLT stylesheet
156 * @inst: the XSLT instruction
157 * @allow1: allowed parent1
158 * @allow2: allowed parent2
160 * Check that the instruction is instanciated as the childre of one of the
164 xsltCheckParentElement(xsltStylesheetPtr style
, xmlNodePtr inst
,
165 const xmlChar
*allow1
, const xmlChar
*allow2
) {
168 if ((style
== NULL
) || (inst
== NULL
) || (inst
->ns
== NULL
) ||
169 (style
->literal_result
))
172 parent
= inst
->parent
;
173 if (parent
== NULL
) {
174 xsltTransformError(NULL
, style
, inst
,
175 "internal problem: element has no parent\n");
179 if (((parent
->ns
== inst
->ns
) ||
180 ((parent
->ns
!= NULL
) &&
181 (xmlStrEqual(parent
->ns
->href
, inst
->ns
->href
)))) &&
182 ((xmlStrEqual(parent
->name
, allow1
)) ||
183 (xmlStrEqual(parent
->name
, allow2
)))) {
187 if (style
->extInfos
!= NULL
) {
188 while ((parent
!= NULL
) && (parent
->type
!= XML_DOCUMENT_NODE
)) {
190 * if we are within an extension element all bets are off
191 * about the semantic there e.g. xsl:param within func:function
193 if ((parent
->ns
!= NULL
) &&
194 (xmlHashLookup(style
->extInfos
, parent
->ns
->href
) != NULL
))
197 parent
= parent
->parent
;
200 xsltTransformError(NULL
, style
, inst
,
201 "element %s is not allowed within that context\n",
207 /************************************************************************
209 * handling of precomputed data *
211 ************************************************************************/
214 * xsltNewStylePreComp:
215 * @style: the XSLT stylesheet
216 * @type: the construct type
218 * Create a new XSLT Style precomputed block
220 * Returns the newly allocated specialized structure
221 * or NULL in case of error
223 static xsltStylePreCompPtr
224 xsltNewStylePreComp(xsltStylesheetPtr style
, xsltStyleType type
) {
225 xsltStylePreCompPtr cur
;
226 #ifdef XSLT_REFACTORED
233 #ifdef XSLT_REFACTORED
235 * URGENT TODO: Use specialized factory functions in order
236 * to avoid this ugliness.
240 size
= sizeof(xsltStyleItemCopy
); break;
242 size
= sizeof(xsltStyleItemSort
); break;
244 size
= sizeof(xsltStyleItemText
); break;
245 case XSLT_FUNC_ELEMENT
:
246 size
= sizeof(xsltStyleItemElement
); break;
247 case XSLT_FUNC_ATTRIBUTE
:
248 size
= sizeof(xsltStyleItemAttribute
); break;
249 case XSLT_FUNC_COMMENT
:
250 size
= sizeof(xsltStyleItemComment
); break;
252 size
= sizeof(xsltStyleItemPI
); break;
253 case XSLT_FUNC_COPYOF
:
254 size
= sizeof(xsltStyleItemCopyOf
); break;
255 case XSLT_FUNC_VALUEOF
:
256 size
= sizeof(xsltStyleItemValueOf
); break;;
257 case XSLT_FUNC_NUMBER
:
258 size
= sizeof(xsltStyleItemNumber
); break;
259 case XSLT_FUNC_APPLYIMPORTS
:
260 size
= sizeof(xsltStyleItemApplyImports
); break;
261 case XSLT_FUNC_CALLTEMPLATE
:
262 size
= sizeof(xsltStyleItemCallTemplate
); break;
263 case XSLT_FUNC_APPLYTEMPLATES
:
264 size
= sizeof(xsltStyleItemApplyTemplates
); break;
265 case XSLT_FUNC_CHOOSE
:
266 size
= sizeof(xsltStyleItemChoose
); break;
268 size
= sizeof(xsltStyleItemIf
); break;
269 case XSLT_FUNC_FOREACH
:
270 size
= sizeof(xsltStyleItemForEach
); break;
271 case XSLT_FUNC_DOCUMENT
:
272 size
= sizeof(xsltStyleItemDocument
); break;
273 case XSLT_FUNC_WITHPARAM
:
274 size
= sizeof(xsltStyleItemWithParam
); break;
275 case XSLT_FUNC_PARAM
:
276 size
= sizeof(xsltStyleItemParam
); break;
277 case XSLT_FUNC_VARIABLE
:
278 size
= sizeof(xsltStyleItemVariable
); break;
280 size
= sizeof(xsltStyleItemWhen
); break;
281 case XSLT_FUNC_OTHERWISE
:
282 size
= sizeof(xsltStyleItemOtherwise
); break;
284 xsltTransformError(NULL
, style
, NULL
,
285 "xsltNewStylePreComp : invalid type %d\n", type
);
290 * Create the structure.
292 cur
= (xsltStylePreCompPtr
) xmlMalloc(size
);
294 xsltTransformError(NULL
, style
, NULL
,
295 "xsltNewStylePreComp : malloc failed\n");
299 memset(cur
, 0, size
);
301 #else /* XSLT_REFACTORED */
305 cur
= (xsltStylePreCompPtr
) xmlMalloc(sizeof(xsltStylePreComp
));
307 xsltTransformError(NULL
, style
, NULL
,
308 "xsltNewStylePreComp : malloc failed\n");
312 memset(cur
, 0, sizeof(xsltStylePreComp
));
313 #endif /* XSLT_REFACTORED */
316 * URGENT TODO: Better to move this to spezialized factory functions.
321 cur
->func
= (xsltTransformFunction
) xsltCopy
;break;
323 cur
->func
= (xsltTransformFunction
) xsltSort
;break;
325 cur
->func
= (xsltTransformFunction
) xsltText
;break;
326 case XSLT_FUNC_ELEMENT
:
327 cur
->func
= (xsltTransformFunction
) xsltElement
;break;
328 case XSLT_FUNC_ATTRIBUTE
:
329 cur
->func
= (xsltTransformFunction
) xsltAttribute
;break;
330 case XSLT_FUNC_COMMENT
:
331 cur
->func
= (xsltTransformFunction
) xsltComment
;break;
333 cur
->func
= (xsltTransformFunction
) xsltProcessingInstruction
;
335 case XSLT_FUNC_COPYOF
:
336 cur
->func
= (xsltTransformFunction
) xsltCopyOf
;break;
337 case XSLT_FUNC_VALUEOF
:
338 cur
->func
= (xsltTransformFunction
) xsltValueOf
;break;
339 case XSLT_FUNC_NUMBER
:
340 cur
->func
= (xsltTransformFunction
) xsltNumber
;break;
341 case XSLT_FUNC_APPLYIMPORTS
:
342 cur
->func
= (xsltTransformFunction
) xsltApplyImports
;break;
343 case XSLT_FUNC_CALLTEMPLATE
:
344 cur
->func
= (xsltTransformFunction
) xsltCallTemplate
;break;
345 case XSLT_FUNC_APPLYTEMPLATES
:
346 cur
->func
= (xsltTransformFunction
) xsltApplyTemplates
;break;
347 case XSLT_FUNC_CHOOSE
:
348 cur
->func
= (xsltTransformFunction
) xsltChoose
;break;
350 cur
->func
= (xsltTransformFunction
) xsltIf
;break;
351 case XSLT_FUNC_FOREACH
:
352 cur
->func
= (xsltTransformFunction
) xsltForEach
;break;
353 case XSLT_FUNC_DOCUMENT
:
354 cur
->func
= (xsltTransformFunction
) xsltDocumentElem
;break;
355 case XSLT_FUNC_WITHPARAM
:
356 case XSLT_FUNC_PARAM
:
357 case XSLT_FUNC_VARIABLE
:
361 if (cur
->func
== NULL
) {
362 xsltTransformError(NULL
, style
, NULL
,
363 "xsltNewStylePreComp : no function for type %d\n", type
);
367 cur
->next
= style
->preComps
;
368 style
->preComps
= (xsltElemPreCompPtr
) cur
;
374 * xsltFreeStylePreComp:
375 * @comp: an XSLT Style precomputed block
377 * Free up the memory allocated by @comp
380 xsltFreeStylePreComp(xsltStylePreCompPtr comp
) {
383 #ifdef XSLT_REFACTORED
385 * URGENT TODO: Implement destructors.
387 switch (comp
->type
) {
388 case XSLT_FUNC_LITERAL_RESULT_ELEMENT
:
392 case XSLT_FUNC_SORT
: {
393 xsltStyleItemSortPtr item
= (xsltStyleItemSortPtr
) comp
;
394 if (item
->locale
!= (xsltLocale
)0)
395 xsltFreeLocale(item
->locale
);
396 if (item
->comp
!= NULL
)
397 xmlXPathFreeCompExpr(item
->comp
);
402 case XSLT_FUNC_ELEMENT
:
404 case XSLT_FUNC_ATTRIBUTE
:
406 case XSLT_FUNC_COMMENT
:
410 case XSLT_FUNC_COPYOF
: {
411 xsltStyleItemCopyOfPtr item
= (xsltStyleItemCopyOfPtr
) comp
;
412 if (item
->comp
!= NULL
)
413 xmlXPathFreeCompExpr(item
->comp
);
416 case XSLT_FUNC_VALUEOF
: {
417 xsltStyleItemValueOfPtr item
= (xsltStyleItemValueOfPtr
) comp
;
418 if (item
->comp
!= NULL
)
419 xmlXPathFreeCompExpr(item
->comp
);
422 case XSLT_FUNC_NUMBER
:
424 case XSLT_FUNC_APPLYIMPORTS
:
426 case XSLT_FUNC_CALLTEMPLATE
:
428 case XSLT_FUNC_APPLYTEMPLATES
: {
429 xsltStyleItemApplyTemplatesPtr item
=
430 (xsltStyleItemApplyTemplatesPtr
) comp
;
431 if (item
->comp
!= NULL
)
432 xmlXPathFreeCompExpr(item
->comp
);
435 case XSLT_FUNC_CHOOSE
:
438 xsltStyleItemIfPtr item
= (xsltStyleItemIfPtr
) comp
;
439 if (item
->comp
!= NULL
)
440 xmlXPathFreeCompExpr(item
->comp
);
443 case XSLT_FUNC_FOREACH
: {
444 xsltStyleItemForEachPtr item
=
445 (xsltStyleItemForEachPtr
) comp
;
446 if (item
->comp
!= NULL
)
447 xmlXPathFreeCompExpr(item
->comp
);
450 case XSLT_FUNC_DOCUMENT
:
452 case XSLT_FUNC_WITHPARAM
: {
453 xsltStyleItemWithParamPtr item
=
454 (xsltStyleItemWithParamPtr
) comp
;
455 if (item
->comp
!= NULL
)
456 xmlXPathFreeCompExpr(item
->comp
);
459 case XSLT_FUNC_PARAM
: {
460 xsltStyleItemParamPtr item
=
461 (xsltStyleItemParamPtr
) comp
;
462 if (item
->comp
!= NULL
)
463 xmlXPathFreeCompExpr(item
->comp
);
466 case XSLT_FUNC_VARIABLE
: {
467 xsltStyleItemVariablePtr item
=
468 (xsltStyleItemVariablePtr
) comp
;
469 if (item
->comp
!= NULL
)
470 xmlXPathFreeCompExpr(item
->comp
);
473 case XSLT_FUNC_WHEN
: {
474 xsltStyleItemWhenPtr item
=
475 (xsltStyleItemWhenPtr
) comp
;
476 if (item
->comp
!= NULL
)
477 xmlXPathFreeCompExpr(item
->comp
);
480 case XSLT_FUNC_OTHERWISE
:
481 case XSLT_FUNC_FALLBACK
:
482 case XSLT_FUNC_MESSAGE
:
483 case XSLT_FUNC_INCLUDE
:
484 case XSLT_FUNC_ATTRSET
:
488 /* TODO: Raise error. */
492 if (comp
->locale
!= (xsltLocale
)0)
493 xsltFreeLocale(comp
->locale
);
494 if (comp
->comp
!= NULL
)
495 xmlXPathFreeCompExpr(comp
->comp
);
496 if (comp
->nsList
!= NULL
)
497 xmlFree(comp
->nsList
);
504 /************************************************************************
506 * XSLT-1.1 extensions *
508 ************************************************************************/
512 * @style: the XSLT stylesheet
513 * @inst: the instruction in the stylesheet
516 * Pre process an XSLT-1.1 document element
518 * Returns a precompiled data structure for the element
521 xsltDocumentComp(xsltStylesheetPtr style
, xmlNodePtr inst
,
522 xsltTransformFunction function ATTRIBUTE_UNUSED
) {
523 #ifdef XSLT_REFACTORED
524 xsltStyleItemDocumentPtr comp
;
526 xsltStylePreCompPtr comp
;
528 const xmlChar
*filename
= NULL
;
531 * As of 2006-03-30, this function is currently defined in Libxslt
533 * (in libxslt/extra.c)
534 * "output" in XSLT_SAXON_NAMESPACE
535 * "write" XSLT_XALAN_NAMESPACE
536 * "document" XSLT_XT_NAMESPACE
537 * "document" XSLT_NAMESPACE (from the abandoned old working
539 * (in libexslt/common.c)
540 * "document" in EXSLT_COMMON_NAMESPACE
542 #ifdef XSLT_REFACTORED
543 comp
= (xsltStyleItemDocumentPtr
)
544 xsltNewStylePreComp(style
, XSLT_FUNC_DOCUMENT
);
546 comp
= xsltNewStylePreComp(style
, XSLT_FUNC_DOCUMENT
);
554 if (xmlStrEqual(inst
->name
, (const xmlChar
*) "output")) {
555 #ifdef WITH_XSLT_DEBUG_EXTRA
556 xsltGenericDebug(xsltGenericDebugContext
,
557 "Found saxon:output extension\n");
560 * The element "output" is in the namespace XSLT_SAXON_NAMESPACE
561 * (http://icl.com/saxon)
562 * The @file is in no namespace; it is an AVT.
563 * (http://www.computerwizards.com/saxon/doc/extensions.html#saxon:output)
565 * TODO: Do we need not to check the namespace here?
567 filename
= xsltEvalStaticAttrValueTemplate(style
, inst
,
568 (const xmlChar
*)"file",
569 NULL
, &comp
->has_filename
);
570 } else if (xmlStrEqual(inst
->name
, (const xmlChar
*) "write")) {
571 #ifdef WITH_XSLT_DEBUG_EXTRA
572 xsltGenericDebug(xsltGenericDebugContext
,
573 "Found xalan:write extension\n");
575 /* the filename need to be interpreted */
577 * TODO: Is "filename need to be interpreted" meant to be a todo?
578 * Where will be the filename of xalan:write be processed?
580 * TODO: Do we need not to check the namespace here?
581 * The extension ns is "http://xml.apache.org/xalan/redirect".
582 * See http://xml.apache.org/xalan-j/extensionslib.html.
584 } else if (xmlStrEqual(inst
->name
, (const xmlChar
*) "document")) {
585 if (inst
->ns
!= NULL
) {
586 if (xmlStrEqual(inst
->ns
->href
, XSLT_NAMESPACE
)) {
588 * Mark the instruction as being of
589 * XSLT version 1.1 (abandoned).
592 #ifdef WITH_XSLT_DEBUG_EXTRA
593 xsltGenericDebug(xsltGenericDebugContext
,
594 "Found xslt11:document construct\n");
597 if (xmlStrEqual(inst
->ns
->href
,
598 (const xmlChar
*)"http://exslt.org/common")) {
600 #ifdef WITH_XSLT_DEBUG_EXTRA
601 xsltGenericDebug(xsltGenericDebugContext
,
602 "Found exslt:document extension\n");
604 } else if (xmlStrEqual(inst
->ns
->href
, XSLT_XT_NAMESPACE
)) {
605 /* James Clark's XT. */
606 #ifdef WITH_XSLT_DEBUG_EXTRA
607 xsltGenericDebug(xsltGenericDebugContext
,
608 "Found xt:document extension\n");
614 * The element "document" is used in conjunction with the
615 * following namespaces:
617 * 1) XSLT_NAMESPACE (http://www.w3.org/1999/XSL/Transform version 1.1)
618 * <!ELEMENT xsl:document %template;>
619 * <!ATTLIST xsl:document
620 * href %avt; #REQUIRED
622 * IMPORTANT: xsl:document was in the abandoned XSLT 1.1 draft,
623 * it was removed and isn't available in XSLT 1.1 anymore.
624 * In XSLT 2.0 it was renamed to xsl:result-document.
626 * All other attributes are identical to the attributes
629 * 2) EXSLT_COMMON_NAMESPACE (http://exslt.org/common)
631 * href = { uri-reference }
632 * TODO: is @href is an AVT?
634 * 3) XSLT_XT_NAMESPACE (http://www.jclark.com/xt)
635 * Example: <xt:document method="xml" href="myFile.xml">
636 * TODO: is @href is an AVT?
638 * In all cases @href is in no namespace.
640 filename
= xsltEvalStaticAttrValueTemplate(style
, inst
,
641 (const xmlChar
*)"href", NULL
, &comp
->has_filename
);
643 if (!comp
->has_filename
) {
646 comp
->filename
= filename
;
649 return ((xsltElemPreCompPtr
) comp
);
652 /************************************************************************
654 * Most of the XSLT-1.0 transformations *
656 ************************************************************************/
660 * @style: the XSLT stylesheet
661 * @inst: the xslt sort node
663 * Process the xslt sort node on the source node
666 xsltSortComp(xsltStylesheetPtr style
, xmlNodePtr inst
) {
667 #ifdef XSLT_REFACTORED
668 xsltStyleItemSortPtr comp
;
670 xsltStylePreCompPtr comp
;
672 if ((style
== NULL
) || (inst
== NULL
))
675 #ifdef XSLT_REFACTORED
676 comp
= (xsltStyleItemSortPtr
) xsltNewStylePreComp(style
, XSLT_FUNC_SORT
);
678 comp
= xsltNewStylePreComp(style
, XSLT_FUNC_SORT
);
686 comp
->stype
= xsltEvalStaticAttrValueTemplate(style
, inst
,
687 (const xmlChar
*)"data-type",
688 NULL
, &comp
->has_stype
);
689 if (comp
->stype
!= NULL
) {
690 if (xmlStrEqual(comp
->stype
, (const xmlChar
*) "text"))
692 else if (xmlStrEqual(comp
->stype
, (const xmlChar
*) "number"))
695 xsltTransformError(NULL
, style
, inst
,
696 "xsltSortComp: no support for data-type = %s\n", comp
->stype
);
697 comp
->number
= 0; /* use default */
698 if (style
!= NULL
) style
->warnings
++;
701 comp
->order
= xsltEvalStaticAttrValueTemplate(style
, inst
,
702 (const xmlChar
*)"order",
703 NULL
, &comp
->has_order
);
704 if (comp
->order
!= NULL
) {
705 if (xmlStrEqual(comp
->order
, (const xmlChar
*) "ascending"))
706 comp
->descending
= 0;
707 else if (xmlStrEqual(comp
->order
, (const xmlChar
*) "descending"))
708 comp
->descending
= 1;
710 xsltTransformError(NULL
, style
, inst
,
711 "xsltSortComp: invalid value %s for order\n", comp
->order
);
712 comp
->descending
= 0; /* use default */
713 if (style
!= NULL
) style
->warnings
++;
716 comp
->case_order
= xsltEvalStaticAttrValueTemplate(style
, inst
,
717 (const xmlChar
*)"case-order",
718 NULL
, &comp
->has_use
);
719 if (comp
->case_order
!= NULL
) {
720 if (xmlStrEqual(comp
->case_order
, (const xmlChar
*) "upper-first"))
721 comp
->lower_first
= 0;
722 else if (xmlStrEqual(comp
->case_order
, (const xmlChar
*) "lower-first"))
723 comp
->lower_first
= 1;
725 xsltTransformError(NULL
, style
, inst
,
726 "xsltSortComp: invalid value %s for order\n", comp
->order
);
727 comp
->lower_first
= 0; /* use default */
728 if (style
!= NULL
) style
->warnings
++;
732 comp
->lang
= xsltEvalStaticAttrValueTemplate(style
, inst
,
733 (const xmlChar
*)"lang",
734 NULL
, &comp
->has_lang
);
735 if (comp
->lang
!= NULL
) {
736 comp
->locale
= xsltNewLocale(comp
->lang
);
739 comp
->locale
= (xsltLocale
)0;
742 comp
->select
= xsltGetCNsProp(style
, inst
,(const xmlChar
*)"select", XSLT_NAMESPACE
);
743 if (comp
->select
== NULL
) {
745 * The default value of the select attribute is ., which will
746 * cause the string-value of the current node to be used as
749 comp
->select
= xmlDictLookup(style
->dict
, BAD_CAST
".", 1);
751 comp
->comp
= xsltXPathCompile(style
, comp
->select
);
752 if (comp
->comp
== NULL
) {
753 xsltTransformError(NULL
, style
, inst
,
754 "xsltSortComp: could not compile select expression '%s'\n",
756 if (style
!= NULL
) style
->errors
++;
758 if (inst
->children
!= NULL
) {
759 xsltTransformError(NULL
, style
, inst
,
760 "xsl:sort : is not empty\n");
761 if (style
!= NULL
) style
->errors
++;
767 * @style: the XSLT stylesheet
768 * @inst: the xslt copy node
770 * Process the xslt copy node on the source node
773 xsltCopyComp(xsltStylesheetPtr style
, xmlNodePtr inst
) {
774 #ifdef XSLT_REFACTORED
775 xsltStyleItemCopyPtr comp
;
777 xsltStylePreCompPtr comp
;
780 if ((style
== NULL
) || (inst
== NULL
))
782 #ifdef XSLT_REFACTORED
783 comp
= (xsltStyleItemCopyPtr
) xsltNewStylePreComp(style
, XSLT_FUNC_COPY
);
785 comp
= xsltNewStylePreComp(style
, XSLT_FUNC_COPY
);
794 comp
->use
= xsltGetCNsProp(style
, inst
, (const xmlChar
*)"use-attribute-sets",
796 if (comp
->use
== NULL
)
802 #ifdef XSLT_REFACTORED
803 /* Enable if ever needed for xsl:text. */
807 * @style: an XSLT compiled stylesheet
808 * @inst: the xslt text node
810 * TODO: This function is obsolete, since xsl:text won't
811 * be compiled, but removed from the tree.
813 * Process the xslt text node on the source node
816 xsltTextComp(xsltStylesheetPtr style
, xmlNodePtr inst
) {
817 #ifdef XSLT_REFACTORED
818 xsltStyleItemTextPtr comp
;
820 xsltStylePreCompPtr comp
;
824 if ((style
== NULL
) || (inst
== NULL
))
827 #ifdef XSLT_REFACTORED
828 comp
= (xsltStyleItemTextPtr
) xsltNewStylePreComp(style
, XSLT_FUNC_TEXT
);
830 comp
= xsltNewStylePreComp(style
, XSLT_FUNC_TEXT
);
838 prop
= xsltGetCNsProp(style
, inst
,
839 (const xmlChar
*)"disable-output-escaping",
842 if (xmlStrEqual(prop
, (const xmlChar
*)"yes")) {
844 } else if (!xmlStrEqual(prop
,
845 (const xmlChar
*)"no")){
846 xsltTransformError(NULL
, style
, inst
,
847 "xsl:text: disable-output-escaping allows only yes or no\n");
848 if (style
!= NULL
) style
->warnings
++;
852 #endif /* else of XSLT_REFACTORED */
856 * @style: an XSLT compiled stylesheet
857 * @inst: the xslt element node
859 * Process the xslt element node on the source node
862 xsltElementComp(xsltStylesheetPtr style
, xmlNodePtr inst
) {
863 #ifdef XSLT_REFACTORED
864 xsltStyleItemElementPtr comp
;
866 xsltStylePreCompPtr comp
;
872 * namespace = { uri-reference }
873 * use-attribute-sets = qnames>
874 * <!-- Content: template -->
877 if ((style
== NULL
) || (inst
== NULL
))
880 #ifdef XSLT_REFACTORED
881 comp
= (xsltStyleItemElementPtr
) xsltNewStylePreComp(style
, XSLT_FUNC_ELEMENT
);
883 comp
= xsltNewStylePreComp(style
, XSLT_FUNC_ELEMENT
);
895 * TODO: Precompile the AVT. See bug #344894.
897 comp
->name
= xsltEvalStaticAttrValueTemplate(style
, inst
,
898 (const xmlChar
*)"name", NULL
, &comp
->has_name
);
899 if (! comp
->has_name
) {
900 xsltTransformError(NULL
, style
, inst
,
901 "xsl:element: The attribute 'name' is missing.\n");
906 * Attribute "namespace".
909 * TODO: Precompile the AVT. See bug #344894.
911 comp
->ns
= xsltEvalStaticAttrValueTemplate(style
, inst
,
912 (const xmlChar
*)"namespace", NULL
, &comp
->has_ns
);
914 if (comp
->name
!= NULL
) {
915 if (xmlValidateQName(comp
->name
, 0)) {
916 xsltTransformError(NULL
, style
, inst
,
917 "xsl:element: The value '%s' of the attribute 'name' is "
918 "not a valid QName.\n", comp
->name
);
921 const xmlChar
*prefix
= NULL
, *name
;
923 name
= xsltSplitQName(style
->dict
, comp
->name
, &prefix
);
924 if (comp
->has_ns
== 0) {
929 * "If the namespace attribute is not present, then the QName is
930 * expanded into an expanded-name using the namespace declarations
931 * in effect for the xsl:element element, including any default
932 * namespace declaration.
934 ns
= xmlSearchNs(inst
->doc
, inst
, prefix
);
936 comp
->ns
= xmlDictLookup(style
->dict
, ns
->href
, -1);
938 #ifdef XSLT_REFACTORED
939 comp
->nsPrefix
= prefix
;
942 } else if (prefix
!= NULL
) {
943 xsltTransformError(NULL
, style
, inst
,
944 "xsl:element: The prefixed QName '%s' "
945 "has no namespace binding in scope in the "
946 "stylesheet; this is an error, since the namespace was "
947 "not specified by the instruction itself.\n", comp
->name
);
951 if ((prefix
!= NULL
) &&
952 (!xmlStrncasecmp(prefix
, (xmlChar
*)"xml", 3)))
955 * Mark is to be skipped.
962 * Attribute "use-attribute-sets",
964 comp
->use
= xsltEvalStaticAttrValueTemplate(style
, inst
,
965 (const xmlChar
*)"use-attribute-sets",
966 NULL
, &comp
->has_use
);
974 * @style: an XSLT compiled stylesheet
975 * @inst: the xslt attribute node
977 * Process the xslt attribute node on the source node
980 xsltAttributeComp(xsltStylesheetPtr style
, xmlNodePtr inst
) {
981 #ifdef XSLT_REFACTORED
982 xsltStyleItemAttributePtr comp
;
984 xsltStylePreCompPtr comp
;
990 * namespace = { uri-reference }>
991 * <!-- Content: template -->
994 if ((style
== NULL
) || (inst
== NULL
))
997 #ifdef XSLT_REFACTORED
998 comp
= (xsltStyleItemAttributePtr
) xsltNewStylePreComp(style
,
999 XSLT_FUNC_ATTRIBUTE
);
1001 comp
= xsltNewStylePreComp(style
, XSLT_FUNC_ATTRIBUTE
);
1013 * TODO: Precompile the AVT. See bug #344894.
1015 comp
->name
= xsltEvalStaticAttrValueTemplate(style
, inst
,
1016 (const xmlChar
*)"name",
1017 NULL
, &comp
->has_name
);
1018 if (! comp
->has_name
) {
1019 xsltTransformError(NULL
, style
, inst
,
1020 "XSLT-attribute: The attribute 'name' is missing.\n");
1025 * Attribute "namespace".
1028 * TODO: Precompile the AVT. See bug #344894.
1030 comp
->ns
= xsltEvalStaticAttrValueTemplate(style
, inst
,
1031 (const xmlChar
*)"namespace",
1032 NULL
, &comp
->has_ns
);
1034 if (comp
->name
!= NULL
) {
1035 if (xmlValidateQName(comp
->name
, 0)) {
1036 xsltTransformError(NULL
, style
, inst
,
1037 "xsl:attribute: The value '%s' of the attribute 'name' is "
1038 "not a valid QName.\n", comp
->name
);
1041 const xmlChar
*prefix
= NULL
, *name
;
1043 name
= xsltSplitQName(style
->dict
, comp
->name
, &prefix
);
1044 if (prefix
!= NULL
) {
1045 if (comp
->has_ns
== 0) {
1050 * "If the namespace attribute is not present, then the
1051 * QName is expanded into an expanded-name using the
1052 * namespace declarations in effect for the xsl:element
1053 * element, including any default namespace declaration.
1055 ns
= xmlSearchNs(inst
->doc
, inst
, prefix
);
1057 comp
->ns
= xmlDictLookup(style
->dict
, ns
->href
, -1);
1059 #ifdef XSLT_REFACTORED
1060 comp
->nsPrefix
= prefix
;
1064 xsltTransformError(NULL
, style
, inst
,
1065 "xsl:attribute: The prefixed QName '%s' "
1066 "has no namespace binding in scope in the "
1067 "stylesheet; this is an error, since the "
1068 "namespace was not specified by the instruction "
1069 "itself.\n", comp
->name
);
1073 if (!xmlStrncasecmp(prefix
, (xmlChar
*) "xmlns", 5)) {
1076 * "It is an error if the string that results from
1077 * instantiating the attribute value template is not a
1078 * QName or is the string xmlns. An XSLT processor may
1079 * signal the error; if it does not signal the error,
1080 * it must recover by not adding the attribute to the
1083 * Reject a prefix of "xmlns". Mark to be skipped.
1087 #ifdef WITH_XSLT_DEBUG_PARSING
1088 xsltGenericDebug(xsltGenericDebugContext
,
1089 "xsltAttribute: xmlns prefix forbidden\n");
1101 * @style: an XSLT compiled stylesheet
1102 * @inst: the xslt comment node
1104 * Process the xslt comment node on the source node
1107 xsltCommentComp(xsltStylesheetPtr style
, xmlNodePtr inst
) {
1108 #ifdef XSLT_REFACTORED
1109 xsltStyleItemCommentPtr comp
;
1111 xsltStylePreCompPtr comp
;
1114 if ((style
== NULL
) || (inst
== NULL
))
1117 #ifdef XSLT_REFACTORED
1118 comp
= (xsltStyleItemCommentPtr
) xsltNewStylePreComp(style
, XSLT_FUNC_COMMENT
);
1120 comp
= xsltNewStylePreComp(style
, XSLT_FUNC_COMMENT
);
1130 * xsltProcessingInstructionComp:
1131 * @style: an XSLT compiled stylesheet
1132 * @inst: the xslt processing-instruction node
1134 * Process the xslt processing-instruction node on the source node
1137 xsltProcessingInstructionComp(xsltStylesheetPtr style
, xmlNodePtr inst
) {
1138 #ifdef XSLT_REFACTORED
1139 xsltStyleItemPIPtr comp
;
1141 xsltStylePreCompPtr comp
;
1144 if ((style
== NULL
) || (inst
== NULL
))
1147 #ifdef XSLT_REFACTORED
1148 comp
= (xsltStyleItemPIPtr
) xsltNewStylePreComp(style
, XSLT_FUNC_PI
);
1150 comp
= xsltNewStylePreComp(style
, XSLT_FUNC_PI
);
1158 comp
->name
= xsltEvalStaticAttrValueTemplate(style
, inst
,
1159 (const xmlChar
*)"name",
1160 XSLT_NAMESPACE
, &comp
->has_name
);
1165 * @style: an XSLT compiled stylesheet
1166 * @inst: the xslt copy-of node
1168 * Process the xslt copy-of node on the source node
1171 xsltCopyOfComp(xsltStylesheetPtr style
, xmlNodePtr inst
) {
1172 #ifdef XSLT_REFACTORED
1173 xsltStyleItemCopyOfPtr comp
;
1175 xsltStylePreCompPtr comp
;
1178 if ((style
== NULL
) || (inst
== NULL
))
1181 #ifdef XSLT_REFACTORED
1182 comp
= (xsltStyleItemCopyOfPtr
) xsltNewStylePreComp(style
, XSLT_FUNC_COPYOF
);
1184 comp
= xsltNewStylePreComp(style
, XSLT_FUNC_COPYOF
);
1192 comp
->select
= xsltGetCNsProp(style
, inst
, (const xmlChar
*)"select",
1194 if (comp
->select
== NULL
) {
1195 xsltTransformError(NULL
, style
, inst
,
1196 "xsl:copy-of : select is missing\n");
1197 if (style
!= NULL
) style
->errors
++;
1200 comp
->comp
= xsltXPathCompile(style
, comp
->select
);
1201 if (comp
->comp
== NULL
) {
1202 xsltTransformError(NULL
, style
, inst
,
1203 "xsl:copy-of : could not compile select expression '%s'\n",
1205 if (style
!= NULL
) style
->errors
++;
1211 * @style: an XSLT compiled stylesheet
1212 * @inst: the xslt value-of node
1214 * Process the xslt value-of node on the source node
1217 xsltValueOfComp(xsltStylesheetPtr style
, xmlNodePtr inst
) {
1218 #ifdef XSLT_REFACTORED
1219 xsltStyleItemValueOfPtr comp
;
1221 xsltStylePreCompPtr comp
;
1223 const xmlChar
*prop
;
1225 if ((style
== NULL
) || (inst
== NULL
))
1228 #ifdef XSLT_REFACTORED
1229 comp
= (xsltStyleItemValueOfPtr
) xsltNewStylePreComp(style
, XSLT_FUNC_VALUEOF
);
1231 comp
= xsltNewStylePreComp(style
, XSLT_FUNC_VALUEOF
);
1239 prop
= xsltGetCNsProp(style
, inst
,
1240 (const xmlChar
*)"disable-output-escaping",
1243 if (xmlStrEqual(prop
, (const xmlChar
*)"yes")) {
1245 } else if (!xmlStrEqual(prop
,
1246 (const xmlChar
*)"no")){
1247 xsltTransformError(NULL
, style
, inst
,
1248 "xsl:value-of : disable-output-escaping allows only yes or no\n");
1249 if (style
!= NULL
) style
->warnings
++;
1252 comp
->select
= xsltGetCNsProp(style
, inst
, (const xmlChar
*)"select",
1254 if (comp
->select
== NULL
) {
1255 xsltTransformError(NULL
, style
, inst
,
1256 "xsl:value-of : select is missing\n");
1257 if (style
!= NULL
) style
->errors
++;
1260 comp
->comp
= xsltXPathCompile(style
, comp
->select
);
1261 if (comp
->comp
== NULL
) {
1262 xsltTransformError(NULL
, style
, inst
,
1263 "xsl:value-of : could not compile select expression '%s'\n",
1265 if (style
!= NULL
) style
->errors
++;
1270 xsltGetQNameProperty(xsltStylesheetPtr style
, xmlNodePtr inst
,
1271 const xmlChar
*propName
,
1273 int *hasProp
, const xmlChar
**nsName
,
1274 const xmlChar
** localName
)
1276 const xmlChar
*prop
;
1285 prop
= xsltGetCNsProp(style
, inst
, propName
, XSLT_NAMESPACE
);
1288 xsltTransformError(NULL
, style
, inst
,
1289 "The attribute '%s' is missing.\n", propName
);
1296 if (xmlValidateQName(prop
, 0)) {
1297 xsltTransformError(NULL
, style
, inst
,
1298 "The value '%s' of the attribute "
1299 "'%s' is not a valid QName.\n", prop
, propName
);
1304 * @prop will be in the string dict afterwards, @URI not.
1306 URI
= xsltGetQNameURI2(style
, inst
, &prop
);
1315 * Fixes bug #308441: Put the ns-name in the dict
1316 * in order to pointer compare names during XPath's
1320 *nsName
= xmlDictLookup(style
->dict
, URI
, -1);
1321 /* comp->has_ns = 1; */
1330 * xsltWithParamComp:
1331 * @style: an XSLT compiled stylesheet
1332 * @inst: the xslt with-param node
1334 * Process the xslt with-param node on the source node
1335 * Allowed parents: xsl:call-template, xsl:apply-templates.
1338 * select = expression>
1339 * <!-- Content: template -->
1343 xsltWithParamComp(xsltStylesheetPtr style
, xmlNodePtr inst
) {
1344 #ifdef XSLT_REFACTORED
1345 xsltStyleItemWithParamPtr comp
;
1347 xsltStylePreCompPtr comp
;
1350 if ((style
== NULL
) || (inst
== NULL
))
1353 #ifdef XSLT_REFACTORED
1354 comp
= (xsltStyleItemWithParamPtr
) xsltNewStylePreComp(style
, XSLT_FUNC_WITHPARAM
);
1356 comp
= xsltNewStylePreComp(style
, XSLT_FUNC_WITHPARAM
);
1367 xsltGetQNameProperty(style
, inst
, BAD_CAST
"name",
1368 1, &(comp
->has_name
), &(comp
->ns
), &(comp
->name
));
1372 * Attribute "select".
1374 comp
->select
= xsltGetCNsProp(style
, inst
, (const xmlChar
*)"select",
1376 if (comp
->select
!= NULL
) {
1377 comp
->comp
= xsltXPathCompile(style
, comp
->select
);
1378 if (comp
->comp
== NULL
) {
1379 xsltTransformError(NULL
, style
, inst
,
1380 "XSLT-with-param: Failed to compile select "
1381 "expression '%s'\n", comp
->select
);
1384 if (inst
->children
!= NULL
) {
1385 xsltTransformError(NULL
, style
, inst
,
1386 "XSLT-with-param: The content should be empty since "
1387 "the attribute select is present.\n");
1395 * @style: an XSLT compiled stylesheet
1396 * @cur: the xslt number node
1398 * Process the xslt number node on the source node
1401 xsltNumberComp(xsltStylesheetPtr style
, xmlNodePtr cur
) {
1402 #ifdef XSLT_REFACTORED
1403 xsltStyleItemNumberPtr comp
;
1405 xsltStylePreCompPtr comp
;
1407 const xmlChar
*prop
;
1409 if ((style
== NULL
) || (cur
== NULL
))
1412 #ifdef XSLT_REFACTORED
1413 comp
= (xsltStyleItemNumberPtr
) xsltNewStylePreComp(style
, XSLT_FUNC_NUMBER
);
1415 comp
= xsltNewStylePreComp(style
, XSLT_FUNC_NUMBER
);
1422 if ((style
== NULL
) || (cur
== NULL
))
1425 comp
->numdata
.doc
= cur
->doc
;
1426 comp
->numdata
.node
= cur
;
1427 comp
->numdata
.value
= xsltGetCNsProp(style
, cur
, (const xmlChar
*)"value",
1430 prop
= xsltEvalStaticAttrValueTemplate(style
, cur
,
1431 (const xmlChar
*)"format",
1432 XSLT_NAMESPACE
, &comp
->numdata
.has_format
);
1433 if (comp
->numdata
.has_format
== 0) {
1434 comp
->numdata
.format
= xmlDictLookup(style
->dict
, BAD_CAST
"" , 0);
1436 comp
->numdata
.format
= prop
;
1439 comp
->numdata
.count
= xsltGetCNsProp(style
, cur
, (const xmlChar
*)"count",
1441 comp
->numdata
.from
= xsltGetCNsProp(style
, cur
, (const xmlChar
*)"from",
1444 prop
= xsltGetCNsProp(style
, cur
, (const xmlChar
*)"level", XSLT_NAMESPACE
);
1446 if (xmlStrEqual(prop
, BAD_CAST("single")) ||
1447 xmlStrEqual(prop
, BAD_CAST("multiple")) ||
1448 xmlStrEqual(prop
, BAD_CAST("any"))) {
1449 comp
->numdata
.level
= prop
;
1451 xsltTransformError(NULL
, style
, cur
,
1452 "xsl:number : invalid value %s for level\n", prop
);
1453 if (style
!= NULL
) style
->warnings
++;
1457 prop
= xsltGetCNsProp(style
, cur
, (const xmlChar
*)"lang", XSLT_NAMESPACE
);
1459 xsltTransformError(NULL
, style
, cur
,
1460 "xsl:number : lang attribute not implemented\n");
1461 XSLT_TODO
; /* xsl:number lang attribute */
1464 prop
= xsltGetCNsProp(style
, cur
, (const xmlChar
*)"letter-value", XSLT_NAMESPACE
);
1466 if (xmlStrEqual(prop
, BAD_CAST("alphabetic"))) {
1467 xsltTransformError(NULL
, style
, cur
,
1468 "xsl:number : letter-value 'alphabetic' not implemented\n");
1469 if (style
!= NULL
) style
->warnings
++;
1470 XSLT_TODO
; /* xsl:number letter-value attribute alphabetic */
1471 } else if (xmlStrEqual(prop
, BAD_CAST("traditional"))) {
1472 xsltTransformError(NULL
, style
, cur
,
1473 "xsl:number : letter-value 'traditional' not implemented\n");
1474 if (style
!= NULL
) style
->warnings
++;
1475 XSLT_TODO
; /* xsl:number letter-value attribute traditional */
1477 xsltTransformError(NULL
, style
, cur
,
1478 "xsl:number : invalid value %s for letter-value\n", prop
);
1479 if (style
!= NULL
) style
->warnings
++;
1483 prop
= xsltGetCNsProp(style
, cur
, (const xmlChar
*)"grouping-separator",
1486 comp
->numdata
.groupingCharacterLen
= xmlStrlen(prop
);
1487 comp
->numdata
.groupingCharacter
=
1488 xsltGetUTF8Char(prop
, &(comp
->numdata
.groupingCharacterLen
));
1491 prop
= xsltGetCNsProp(style
, cur
, (const xmlChar
*)"grouping-size", XSLT_NAMESPACE
);
1493 sscanf((char *)prop
, "%d", &comp
->numdata
.digitsPerGroup
);
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
1516 xsltApplyImportsComp(xsltStylesheetPtr style
, xmlNodePtr inst
) {
1517 #ifdef XSLT_REFACTORED
1518 xsltStyleItemApplyImportsPtr comp
;
1520 xsltStylePreCompPtr comp
;
1523 if ((style
== NULL
) || (inst
== NULL
))
1526 #ifdef XSLT_REFACTORED
1527 comp
= (xsltStyleItemApplyImportsPtr
) xsltNewStylePreComp(style
, XSLT_FUNC_APPLYIMPORTS
);
1529 comp
= xsltNewStylePreComp(style
, XSLT_FUNC_APPLYIMPORTS
);
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
1546 xsltCallTemplateComp(xsltStylesheetPtr style
, xmlNodePtr inst
) {
1547 #ifdef XSLT_REFACTORED
1548 xsltStyleItemCallTemplatePtr comp
;
1550 xsltStylePreCompPtr comp
;
1553 if ((style
== NULL
) || (inst
== NULL
))
1556 #ifdef XSLT_REFACTORED
1557 comp
= (xsltStyleItemCallTemplatePtr
)
1558 xsltNewStylePreComp(style
, XSLT_FUNC_CALLTEMPLATE
);
1560 comp
= xsltNewStylePreComp(style
, XSLT_FUNC_CALLTEMPLATE
);
1571 xsltGetQNameProperty(style
, inst
, BAD_CAST
"name",
1572 1, &(comp
->has_name
), &(comp
->ns
), &(comp
->name
));
1578 * xsltApplyTemplatesComp:
1579 * @style: an XSLT compiled stylesheet
1580 * @inst: the apply-templates node
1582 * Process the apply-templates node on the source node
1585 xsltApplyTemplatesComp(xsltStylesheetPtr style
, xmlNodePtr inst
) {
1586 #ifdef XSLT_REFACTORED
1587 xsltStyleItemApplyTemplatesPtr comp
;
1589 xsltStylePreCompPtr comp
;
1592 if ((style
== NULL
) || (inst
== NULL
))
1595 #ifdef XSLT_REFACTORED
1596 comp
= (xsltStyleItemApplyTemplatesPtr
)
1597 xsltNewStylePreComp(style
, XSLT_FUNC_APPLYTEMPLATES
);
1599 comp
= xsltNewStylePreComp(style
, XSLT_FUNC_APPLYTEMPLATES
);
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",
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
);
1626 /* TODO: handle (or skip) the xsl:sort and xsl:with-param */
1631 * @style: an XSLT compiled stylesheet
1632 * @inst: the xslt choose node
1634 * Process the xslt choose node on the source node
1637 xsltChooseComp(xsltStylesheetPtr style
, xmlNodePtr inst
) {
1638 #ifdef XSLT_REFACTORED
1639 xsltStyleItemChoosePtr comp
;
1641 xsltStylePreCompPtr comp
;
1644 if ((style
== NULL
) || (inst
== NULL
))
1647 #ifdef XSLT_REFACTORED
1648 comp
= (xsltStyleItemChoosePtr
)
1649 xsltNewStylePreComp(style
, XSLT_FUNC_CHOOSE
);
1651 comp
= xsltNewStylePreComp(style
, XSLT_FUNC_CHOOSE
);
1662 * @style: an XSLT compiled stylesheet
1663 * @inst: the xslt if node
1665 * Process the xslt if node on the source node
1668 xsltIfComp(xsltStylesheetPtr style
, xmlNodePtr inst
) {
1669 #ifdef XSLT_REFACTORED
1670 xsltStyleItemIfPtr comp
;
1672 xsltStylePreCompPtr comp
;
1675 if ((style
== NULL
) || (inst
== NULL
))
1678 #ifdef XSLT_REFACTORED
1679 comp
= (xsltStyleItemIfPtr
)
1680 xsltNewStylePreComp(style
, XSLT_FUNC_IF
);
1682 comp
= xsltNewStylePreComp(style
, XSLT_FUNC_IF
);
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
++;
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",
1702 if (style
!= NULL
) style
->errors
++;
1708 * @style: an XSLT compiled stylesheet
1709 * @inst: the xslt if node
1711 * Process the xslt if node on the source node
1714 xsltWhenComp(xsltStylesheetPtr style
, xmlNodePtr inst
) {
1715 #ifdef XSLT_REFACTORED
1716 xsltStyleItemWhenPtr comp
;
1718 xsltStylePreCompPtr comp
;
1721 if ((style
== NULL
) || (inst
== NULL
))
1724 #ifdef XSLT_REFACTORED
1725 comp
= (xsltStyleItemWhenPtr
)
1726 xsltNewStylePreComp(style
, XSLT_FUNC_WHEN
);
1728 comp
= xsltNewStylePreComp(style
, XSLT_FUNC_WHEN
);
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
++;
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",
1748 if (style
!= NULL
) style
->errors
++;
1754 * @style: an XSLT compiled stylesheet
1755 * @inst: the xslt for-each node
1757 * Process the xslt for-each node on the source node
1760 xsltForEachComp(xsltStylesheetPtr style
, xmlNodePtr inst
) {
1761 #ifdef XSLT_REFACTORED
1762 xsltStyleItemForEachPtr comp
;
1764 xsltStylePreCompPtr comp
;
1767 if ((style
== NULL
) || (inst
== NULL
))
1770 #ifdef XSLT_REFACTORED
1771 comp
= (xsltStyleItemForEachPtr
)
1772 xsltNewStylePreComp(style
, XSLT_FUNC_FOREACH
);
1774 comp
= xsltNewStylePreComp(style
, XSLT_FUNC_FOREACH
);
1782 comp
->select
= xsltGetCNsProp(style
, inst
, (const xmlChar
*)"select",
1784 if (comp
->select
== NULL
) {
1785 xsltTransformError(NULL
, style
, inst
,
1786 "xsl:for-each : select is missing\n");
1787 if (style
!= NULL
) style
->errors
++;
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",
1794 if (style
!= NULL
) style
->errors
++;
1797 /* TODO: handle and skip the xsl:sort */
1802 * @style: an XSLT compiled stylesheet
1803 * @inst: the xslt variable node
1805 * Process the xslt variable node on the source node
1808 xsltVariableComp(xsltStylesheetPtr style
, xmlNodePtr inst
) {
1809 #ifdef XSLT_REFACTORED
1810 xsltStyleItemVariablePtr comp
;
1812 xsltStylePreCompPtr comp
;
1815 if ((style
== NULL
) || (inst
== NULL
))
1818 #ifdef XSLT_REFACTORED
1819 comp
= (xsltStyleItemVariablePtr
)
1820 xsltNewStylePreComp(style
, XSLT_FUNC_VARIABLE
);
1822 comp
= xsltNewStylePreComp(style
, XSLT_FUNC_VARIABLE
);
1831 * The full template resolution can be done statically
1837 xsltGetQNameProperty(style
, inst
, BAD_CAST
"name",
1838 1, &(comp
->has_name
), &(comp
->ns
), &(comp
->name
));
1842 * Attribute "select".
1844 comp
->select
= xsltGetCNsProp(style
, inst
, (const xmlChar
*)"select",
1846 if (comp
->select
!= NULL
) {
1847 comp
->comp
= xsltXPathCompile(style
, comp
->select
);
1848 if (comp
->comp
== NULL
) {
1849 xsltTransformError(NULL
, style
, inst
,
1850 "XSLT-variable: Failed to compile the XPath expression '%s'.\n",
1854 if (inst
->children
!= NULL
) {
1855 xsltTransformError(NULL
, style
, inst
,
1856 "XSLT-variable: The must be no child nodes, since the "
1857 "attribute 'select' was specified.\n");
1865 * @style: an XSLT compiled stylesheet
1866 * @inst: the xslt param node
1868 * Process the xslt param node on the source node
1871 xsltParamComp(xsltStylesheetPtr style
, xmlNodePtr inst
) {
1872 #ifdef XSLT_REFACTORED
1873 xsltStyleItemParamPtr comp
;
1875 xsltStylePreCompPtr comp
;
1878 if ((style
== NULL
) || (inst
== NULL
))
1881 #ifdef XSLT_REFACTORED
1882 comp
= (xsltStyleItemParamPtr
)
1883 xsltNewStylePreComp(style
, XSLT_FUNC_PARAM
);
1885 comp
= xsltNewStylePreComp(style
, XSLT_FUNC_PARAM
);
1896 xsltGetQNameProperty(style
, inst
, BAD_CAST
"name",
1897 1, &(comp
->has_name
), &(comp
->ns
), &(comp
->name
));
1901 * Attribute "select".
1903 comp
->select
= xsltGetCNsProp(style
, inst
, (const xmlChar
*)"select",
1905 if (comp
->select
!= NULL
) {
1906 comp
->comp
= xsltXPathCompile(style
, comp
->select
);
1907 if (comp
->comp
== NULL
) {
1908 xsltTransformError(NULL
, style
, inst
,
1909 "XSLT-param: could not compile select expression '%s'.\n",
1913 if (inst
->children
!= NULL
) {
1914 xsltTransformError(NULL
, style
, inst
,
1915 "XSLT-param: The content should be empty since the "
1916 "attribute 'select' is present.\n");
1922 /************************************************************************
1924 * Generic interface *
1926 ************************************************************************/
1929 * xsltFreeStylePreComps:
1930 * @style: an XSLT transformation context
1932 * Free up the memory allocated by all precomputed blocks
1935 xsltFreeStylePreComps(xsltStylesheetPtr style
) {
1936 xsltElemPreCompPtr cur
, next
;
1941 cur
= style
->preComps
;
1942 while (cur
!= NULL
) {
1944 if (cur
->type
== XSLT_FUNC_EXTENSION
)
1947 xsltFreeStylePreComp((xsltStylePreCompPtr
) cur
);
1952 #ifdef XSLT_REFACTORED
1955 * xsltStylePreCompute:
1956 * @style: the XSLT stylesheet
1957 * @node: the element in the XSLT namespace
1959 * Precompute an XSLT element.
1960 * This expects the type of the element to be already
1961 * set in style->compCtxt->inode->type;
1964 xsltStylePreCompute(xsltStylesheetPtr style
, xmlNodePtr node
) {
1966 * The xsltXSLTElemMarker marker was set beforehand by
1967 * the parsing mechanism for all elements in the XSLT namespace.
1969 if (style
== NULL
) {
1976 if (! IS_XSLT_ELEM_FAST(node
))
1980 if (XSLT_CCTXT(style
)->inode
->type
!= 0) {
1981 switch (XSLT_CCTXT(style
)->inode
->type
) {
1982 case XSLT_FUNC_APPLYTEMPLATES
:
1983 xsltApplyTemplatesComp(style
, node
);
1985 case XSLT_FUNC_WITHPARAM
:
1986 xsltWithParamComp(style
, node
);
1988 case XSLT_FUNC_VALUEOF
:
1989 xsltValueOfComp(style
, node
);
1991 case XSLT_FUNC_COPY
:
1992 xsltCopyComp(style
, node
);
1994 case XSLT_FUNC_COPYOF
:
1995 xsltCopyOfComp(style
, node
);
1998 xsltIfComp(style
, node
);
2000 case XSLT_FUNC_CHOOSE
:
2001 xsltChooseComp(style
, node
);
2003 case XSLT_FUNC_WHEN
:
2004 xsltWhenComp(style
, node
);
2006 case XSLT_FUNC_OTHERWISE
:
2009 case XSLT_FUNC_FOREACH
:
2010 xsltForEachComp(style
, node
);
2012 case XSLT_FUNC_APPLYIMPORTS
:
2013 xsltApplyImportsComp(style
, node
);
2015 case XSLT_FUNC_ATTRIBUTE
:
2016 xsltAttributeComp(style
, node
);
2018 case XSLT_FUNC_ELEMENT
:
2019 xsltElementComp(style
, node
);
2021 case XSLT_FUNC_SORT
:
2022 xsltSortComp(style
, node
);
2024 case XSLT_FUNC_COMMENT
:
2025 xsltCommentComp(style
, node
);
2027 case XSLT_FUNC_NUMBER
:
2028 xsltNumberComp(style
, node
);
2031 xsltProcessingInstructionComp(style
, node
);
2033 case XSLT_FUNC_CALLTEMPLATE
:
2034 xsltCallTemplateComp(style
, node
);
2036 case XSLT_FUNC_PARAM
:
2037 xsltParamComp(style
, node
);
2039 case XSLT_FUNC_VARIABLE
:
2040 xsltVariableComp(style
, node
);
2042 case XSLT_FUNC_FALLBACK
:
2045 case XSLT_FUNC_DOCUMENT
:
2047 node
->psvi
= (void *) xsltDocumentComp(style
, node
,
2048 (xsltTransformFunction
) xsltDocumentElem
);
2050 case XSLT_FUNC_MESSAGE
:
2055 * NOTE that xsl:text, xsl:template, xsl:stylesheet,
2056 * xsl:transform, xsl:import, xsl:include are not expected
2057 * to be handed over to this function.
2059 xsltTransformError(NULL
, style
, node
,
2060 "Internal error: (xsltStylePreCompute) cannot handle "
2061 "the XSLT element '%s'.\n", node
->name
);
2067 * Fallback to string comparison.
2069 if (IS_XSLT_NAME(node
, "apply-templates")) {
2070 xsltApplyTemplatesComp(style
, node
);
2071 } else if (IS_XSLT_NAME(node
, "with-param")) {
2072 xsltWithParamComp(style
, node
);
2073 } else if (IS_XSLT_NAME(node
, "value-of")) {
2074 xsltValueOfComp(style
, node
);
2075 } else if (IS_XSLT_NAME(node
, "copy")) {
2076 xsltCopyComp(style
, node
);
2077 } else if (IS_XSLT_NAME(node
, "copy-of")) {
2078 xsltCopyOfComp(style
, node
);
2079 } else if (IS_XSLT_NAME(node
, "if")) {
2080 xsltIfComp(style
, node
);
2081 } else if (IS_XSLT_NAME(node
, "choose")) {
2082 xsltChooseComp(style
, node
);
2083 } else if (IS_XSLT_NAME(node
, "when")) {
2084 xsltWhenComp(style
, node
);
2085 } else if (IS_XSLT_NAME(node
, "otherwise")) {
2088 } else if (IS_XSLT_NAME(node
, "for-each")) {
2089 xsltForEachComp(style
, node
);
2090 } else if (IS_XSLT_NAME(node
, "apply-imports")) {
2091 xsltApplyImportsComp(style
, node
);
2092 } else if (IS_XSLT_NAME(node
, "attribute")) {
2093 xsltAttributeComp(style
, node
);
2094 } else if (IS_XSLT_NAME(node
, "element")) {
2095 xsltElementComp(style
, node
);
2096 } else if (IS_XSLT_NAME(node
, "sort")) {
2097 xsltSortComp(style
, node
);
2098 } else if (IS_XSLT_NAME(node
, "comment")) {
2099 xsltCommentComp(style
, node
);
2100 } else if (IS_XSLT_NAME(node
, "number")) {
2101 xsltNumberComp(style
, node
);
2102 } else if (IS_XSLT_NAME(node
, "processing-instruction")) {
2103 xsltProcessingInstructionComp(style
, node
);
2104 } else if (IS_XSLT_NAME(node
, "call-template")) {
2105 xsltCallTemplateComp(style
, node
);
2106 } else if (IS_XSLT_NAME(node
, "param")) {
2107 xsltParamComp(style
, node
);
2108 } else if (IS_XSLT_NAME(node
, "variable")) {
2109 xsltVariableComp(style
, node
);
2110 } else if (IS_XSLT_NAME(node
, "fallback")) {
2113 } else if (IS_XSLT_NAME(node
, "document")) {
2115 node
->psvi
= (void *) xsltDocumentComp(style
, node
,
2116 (xsltTransformFunction
) xsltDocumentElem
);
2117 } else if (IS_XSLT_NAME(node
, "output")) {
2120 } else if (IS_XSLT_NAME(node
, "preserve-space")) {
2123 } else if (IS_XSLT_NAME(node
, "strip-space")) {
2126 } else if (IS_XSLT_NAME(node
, "key")) {
2129 } else if (IS_XSLT_NAME(node
, "message")) {
2131 } else if (IS_XSLT_NAME(node
, "attribute-set")) {
2134 } else if (IS_XSLT_NAME(node
, "namespace-alias")) {
2137 } else if (IS_XSLT_NAME(node
, "decimal-format")) {
2140 } else if (IS_XSLT_NAME(node
, "include")) {
2144 * NOTE that xsl:text, xsl:template, xsl:stylesheet,
2145 * xsl:transform, xsl:import, xsl:include are not expected
2146 * to be handed over to this function.
2148 xsltTransformError(NULL
, style
, node
,
2149 "Internal error: (xsltStylePreCompute) cannot handle "
2150 "the XSLT element '%s'.\n", node
->name
);
2156 * Assign the current list of in-scope namespaces to the
2157 * item. This is needed for XPath expressions.
2159 if (node
->psvi
!= NULL
) {
2160 ((xsltStylePreCompPtr
) node
->psvi
)->inScopeNs
=
2161 XSLT_CCTXT(style
)->inode
->inScopeNs
;
2168 * xsltStylePreCompute:
2169 * @style: the XSLT stylesheet
2170 * @inst: the instruction in the stylesheet
2172 * Precompute an XSLT stylesheet element
2175 xsltStylePreCompute(xsltStylesheetPtr style
, xmlNodePtr inst
) {
2177 * URGENT TODO: Normally inst->psvi Should never be reserved here,
2178 * BUT: since if we include the same stylesheet from
2179 * multiple imports, then the stylesheet will be parsed
2180 * again. We simply must not try to compute the stylesheet again.
2181 * TODO: Get to the point where we don't need to query the
2182 * namespace- and local-name of the node, but can evaluate this
2183 * using cctxt->style->inode->category;
2185 if (inst
->psvi
!= NULL
)
2188 if (IS_XSLT_ELEM(inst
)) {
2189 xsltStylePreCompPtr cur
;
2191 if (IS_XSLT_NAME(inst
, "apply-templates")) {
2192 xsltCheckInstructionElement(style
, inst
);
2193 xsltApplyTemplatesComp(style
, inst
);
2194 } else if (IS_XSLT_NAME(inst
, "with-param")) {
2195 xsltCheckParentElement(style
, inst
, BAD_CAST
"apply-templates",
2196 BAD_CAST
"call-template");
2197 xsltWithParamComp(style
, inst
);
2198 } else if (IS_XSLT_NAME(inst
, "value-of")) {
2199 xsltCheckInstructionElement(style
, inst
);
2200 xsltValueOfComp(style
, inst
);
2201 } else if (IS_XSLT_NAME(inst
, "copy")) {
2202 xsltCheckInstructionElement(style
, inst
);
2203 xsltCopyComp(style
, inst
);
2204 } else if (IS_XSLT_NAME(inst
, "copy-of")) {
2205 xsltCheckInstructionElement(style
, inst
);
2206 xsltCopyOfComp(style
, inst
);
2207 } else if (IS_XSLT_NAME(inst
, "if")) {
2208 xsltCheckInstructionElement(style
, inst
);
2209 xsltIfComp(style
, inst
);
2210 } else if (IS_XSLT_NAME(inst
, "when")) {
2211 xsltCheckParentElement(style
, inst
, BAD_CAST
"choose", NULL
);
2212 xsltWhenComp(style
, inst
);
2213 } else if (IS_XSLT_NAME(inst
, "choose")) {
2214 xsltCheckInstructionElement(style
, inst
);
2215 xsltChooseComp(style
, inst
);
2216 } else if (IS_XSLT_NAME(inst
, "for-each")) {
2217 xsltCheckInstructionElement(style
, inst
);
2218 xsltForEachComp(style
, inst
);
2219 } else if (IS_XSLT_NAME(inst
, "apply-imports")) {
2220 xsltCheckInstructionElement(style
, inst
);
2221 xsltApplyImportsComp(style
, inst
);
2222 } else if (IS_XSLT_NAME(inst
, "attribute")) {
2223 xmlNodePtr parent
= inst
->parent
;
2225 if ((parent
== NULL
) || (parent
->ns
== NULL
) ||
2226 ((parent
->ns
!= inst
->ns
) &&
2227 (!xmlStrEqual(parent
->ns
->href
, inst
->ns
->href
))) ||
2228 (!xmlStrEqual(parent
->name
, BAD_CAST
"attribute-set"))) {
2229 xsltCheckInstructionElement(style
, inst
);
2231 xsltAttributeComp(style
, inst
);
2232 } else if (IS_XSLT_NAME(inst
, "element")) {
2233 xsltCheckInstructionElement(style
, inst
);
2234 xsltElementComp(style
, inst
);
2235 } else if (IS_XSLT_NAME(inst
, "text")) {
2236 xsltCheckInstructionElement(style
, inst
);
2237 xsltTextComp(style
, inst
);
2238 } else if (IS_XSLT_NAME(inst
, "sort")) {
2239 xsltCheckParentElement(style
, inst
, BAD_CAST
"apply-templates",
2240 BAD_CAST
"for-each");
2241 xsltSortComp(style
, inst
);
2242 } else if (IS_XSLT_NAME(inst
, "comment")) {
2243 xsltCheckInstructionElement(style
, inst
);
2244 xsltCommentComp(style
, inst
);
2245 } else if (IS_XSLT_NAME(inst
, "number")) {
2246 xsltCheckInstructionElement(style
, inst
);
2247 xsltNumberComp(style
, inst
);
2248 } else if (IS_XSLT_NAME(inst
, "processing-instruction")) {
2249 xsltCheckInstructionElement(style
, inst
);
2250 xsltProcessingInstructionComp(style
, inst
);
2251 } else if (IS_XSLT_NAME(inst
, "call-template")) {
2252 xsltCheckInstructionElement(style
, inst
);
2253 xsltCallTemplateComp(style
, inst
);
2254 } else if (IS_XSLT_NAME(inst
, "param")) {
2255 if (xsltCheckTopLevelElement(style
, inst
, 0) == 0)
2256 xsltCheckInstructionElement(style
, inst
);
2257 xsltParamComp(style
, inst
);
2258 } else if (IS_XSLT_NAME(inst
, "variable")) {
2259 if (xsltCheckTopLevelElement(style
, inst
, 0) == 0)
2260 xsltCheckInstructionElement(style
, inst
);
2261 xsltVariableComp(style
, inst
);
2262 } else if (IS_XSLT_NAME(inst
, "otherwise")) {
2263 xsltCheckParentElement(style
, inst
, BAD_CAST
"choose", NULL
);
2264 xsltCheckInstructionElement(style
, inst
);
2266 } else if (IS_XSLT_NAME(inst
, "template")) {
2267 xsltCheckTopLevelElement(style
, inst
, 1);
2269 } else if (IS_XSLT_NAME(inst
, "output")) {
2270 xsltCheckTopLevelElement(style
, inst
, 1);
2272 } else if (IS_XSLT_NAME(inst
, "preserve-space")) {
2273 xsltCheckTopLevelElement(style
, inst
, 1);
2275 } else if (IS_XSLT_NAME(inst
, "strip-space")) {
2276 xsltCheckTopLevelElement(style
, inst
, 1);
2278 } else if ((IS_XSLT_NAME(inst
, "stylesheet")) ||
2279 (IS_XSLT_NAME(inst
, "transform"))) {
2280 xmlNodePtr parent
= inst
->parent
;
2282 if ((parent
== NULL
) || (parent
->type
!= XML_DOCUMENT_NODE
)) {
2283 xsltTransformError(NULL
, style
, inst
,
2284 "element %s only allowed only as root element\n",
2289 } else if (IS_XSLT_NAME(inst
, "key")) {
2290 xsltCheckTopLevelElement(style
, inst
, 1);
2292 } else if (IS_XSLT_NAME(inst
, "message")) {
2293 xsltCheckInstructionElement(style
, inst
);
2295 } else if (IS_XSLT_NAME(inst
, "attribute-set")) {
2296 xsltCheckTopLevelElement(style
, inst
, 1);
2298 } else if (IS_XSLT_NAME(inst
, "namespace-alias")) {
2299 xsltCheckTopLevelElement(style
, inst
, 1);
2301 } else if (IS_XSLT_NAME(inst
, "include")) {
2302 xsltCheckTopLevelElement(style
, inst
, 1);
2304 } else if (IS_XSLT_NAME(inst
, "import")) {
2305 xsltCheckTopLevelElement(style
, inst
, 1);
2307 } else if (IS_XSLT_NAME(inst
, "decimal-format")) {
2308 xsltCheckTopLevelElement(style
, inst
, 1);
2310 } else if (IS_XSLT_NAME(inst
, "fallback")) {
2311 xsltCheckInstructionElement(style
, inst
);
2313 } else if (IS_XSLT_NAME(inst
, "document")) {
2314 xsltCheckInstructionElement(style
, inst
);
2315 inst
->psvi
= (void *) xsltDocumentComp(style
, inst
,
2316 (xsltTransformFunction
) xsltDocumentElem
);
2318 xsltTransformError(NULL
, style
, inst
,
2319 "xsltStylePreCompute: unknown xsl:%s\n", inst
->name
);
2320 if (style
!= NULL
) style
->warnings
++;
2323 cur
= (xsltStylePreCompPtr
) inst
->psvi
;
2325 * A ns-list is build for every XSLT item in the
2326 * node-tree. This is needed for XPath expressions.
2331 cur
->nsList
= xmlGetNsList(inst
->doc
, inst
);
2332 if (cur
->nsList
!= NULL
) {
2333 while (cur
->nsList
[i
] != NULL
)
2340 (void *) xsltPreComputeExtModuleElement(style
, inst
);
2343 * Unknown element, maybe registered at the context
2344 * level. Mark it for later recognition.
2346 if (inst
->psvi
== NULL
)
2347 inst
->psvi
= (void *) xsltExtMarker
;
2350 #endif /* XSLT_REFACTORED */