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