Sync to trunk revision 61757.
[reactos.git] / dll / 3rdparty / libxslt / preproc.c
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
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
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
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
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 = (xsltTransformFunction) xsltCopy;break;
299 case XSLT_FUNC_SORT:
300 cur->func = (xsltTransformFunction) xsltSort;break;
301 case XSLT_FUNC_TEXT:
302 cur->func = (xsltTransformFunction) xsltText;break;
303 case XSLT_FUNC_ELEMENT:
304 cur->func = (xsltTransformFunction) xsltElement;break;
305 case XSLT_FUNC_ATTRIBUTE:
306 cur->func = (xsltTransformFunction) xsltAttribute;break;
307 case XSLT_FUNC_COMMENT:
308 cur->func = (xsltTransformFunction) xsltComment;break;
309 case XSLT_FUNC_PI:
310 cur->func = (xsltTransformFunction) xsltProcessingInstruction;
311 break;
312 case XSLT_FUNC_COPYOF:
313 cur->func = (xsltTransformFunction) xsltCopyOf;break;
314 case XSLT_FUNC_VALUEOF:
315 cur->func = (xsltTransformFunction) xsltValueOf;break;
316 case XSLT_FUNC_NUMBER:
317 cur->func = (xsltTransformFunction) xsltNumber;break;
318 case XSLT_FUNC_APPLYIMPORTS:
319 cur->func = (xsltTransformFunction) xsltApplyImports;break;
320 case XSLT_FUNC_CALLTEMPLATE:
321 cur->func = (xsltTransformFunction) xsltCallTemplate;break;
322 case XSLT_FUNC_APPLYTEMPLATES:
323 cur->func = (xsltTransformFunction) xsltApplyTemplates;break;
324 case XSLT_FUNC_CHOOSE:
325 cur->func = (xsltTransformFunction) xsltChoose;break;
326 case XSLT_FUNC_IF:
327 cur->func = (xsltTransformFunction) xsltIf;break;
328 case XSLT_FUNC_FOREACH:
329 cur->func = (xsltTransformFunction) xsltForEach;break;
330 case XSLT_FUNC_DOCUMENT:
331 cur->func = (xsltTransformFunction) 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
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
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
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
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
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
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 #endif
929 } else if (prefix != NULL) {
930 xsltTransformError(NULL, style, inst,
931 "xsl:element: The prefixed QName '%s' "
932 "has no namespace binding in scope in the "
933 "stylesheet; this is an error, since the namespace was "
934 "not specified by the instruction itself.\n", comp->name);
935 style->errors++;
936 }
937 }
938 if ((prefix != NULL) &&
939 (!xmlStrncasecmp(prefix, (xmlChar *)"xml", 3)))
940 {
941 /*
942 * Mark is to be skipped.
943 */
944 comp->has_name = 0;
945 }
946 }
947 }
948 /*
949 * Attribute "use-attribute-sets",
950 */
951 comp->use = xsltEvalStaticAttrValueTemplate(style, inst,
952 (const xmlChar *)"use-attribute-sets",
953 NULL, &comp->has_use);
954
955 error:
956 return;
957 }
958
959 /**
960 * xsltAttributeComp:
961 * @style: an XSLT compiled stylesheet
962 * @inst: the xslt attribute node
963 *
964 * Process the xslt attribute node on the source node
965 */
966 static void
967 xsltAttributeComp(xsltStylesheetPtr style, xmlNodePtr inst) {
968 #ifdef XSLT_REFACTORED
969 xsltStyleItemAttributePtr comp;
970 #else
971 xsltStylePreCompPtr comp;
972 #endif
973
974 /*
975 * <xsl:attribute
976 * name = { qname }
977 * namespace = { uri-reference }>
978 * <!-- Content: template -->
979 * </xsl:attribute>
980 */
981 if ((style == NULL) || (inst == NULL) || (inst->type != XML_ELEMENT_NODE))
982 return;
983
984 #ifdef XSLT_REFACTORED
985 comp = (xsltStyleItemAttributePtr) xsltNewStylePreComp(style,
986 XSLT_FUNC_ATTRIBUTE);
987 #else
988 comp = xsltNewStylePreComp(style, XSLT_FUNC_ATTRIBUTE);
989 #endif
990
991 if (comp == NULL)
992 return;
993 inst->psvi = comp;
994 comp->inst = inst;
995
996 /*
997 * Attribute "name".
998 */
999 /*
1000 * TODO: Precompile the AVT. See bug #344894.
1001 */
1002 comp->name = xsltEvalStaticAttrValueTemplate(style, inst,
1003 (const xmlChar *)"name",
1004 NULL, &comp->has_name);
1005 if (! comp->has_name) {
1006 xsltTransformError(NULL, style, inst,
1007 "XSLT-attribute: The attribute 'name' is missing.\n");
1008 style->errors++;
1009 return;
1010 }
1011 /*
1012 * Attribute "namespace".
1013 */
1014 /*
1015 * TODO: Precompile the AVT. See bug #344894.
1016 */
1017 comp->ns = xsltEvalStaticAttrValueTemplate(style, inst,
1018 (const xmlChar *)"namespace",
1019 NULL, &comp->has_ns);
1020
1021 if (comp->name != NULL) {
1022 if (xmlValidateQName(comp->name, 0)) {
1023 xsltTransformError(NULL, style, inst,
1024 "xsl:attribute: The value '%s' of the attribute 'name' is "
1025 "not a valid QName.\n", comp->name);
1026 style->errors++;
1027 } else if (xmlStrEqual(comp->name, BAD_CAST "xmlns")) {
1028 xsltTransformError(NULL, style, inst,
1029 "xsl:attribute: The attribute name 'xmlns' is not allowed.\n");
1030 style->errors++;
1031 } else {
1032 const xmlChar *prefix = NULL, *name;
1033
1034 name = xsltSplitQName(style->dict, comp->name, &prefix);
1035 if (prefix != NULL) {
1036 if (comp->has_ns == 0) {
1037 xmlNsPtr ns;
1038
1039 /*
1040 * SPEC XSLT 1.0:
1041 * "If the namespace attribute is not present, then the
1042 * QName is expanded into an expanded-name using the
1043 * namespace declarations in effect for the xsl:element
1044 * element, including any default namespace declaration.
1045 */
1046 ns = xmlSearchNs(inst->doc, inst, prefix);
1047 if (ns != NULL) {
1048 comp->ns = xmlDictLookup(style->dict, ns->href, -1);
1049 comp->has_ns = 1;
1050 #ifdef XSLT_REFACTORED
1051 comp->nsPrefix = prefix;
1052 comp->name = name;
1053 #endif
1054 } else {
1055 xsltTransformError(NULL, style, inst,
1056 "xsl:attribute: The prefixed QName '%s' "
1057 "has no namespace binding in scope in the "
1058 "stylesheet; this is an error, since the "
1059 "namespace was not specified by the instruction "
1060 "itself.\n", comp->name);
1061 style->errors++;
1062 }
1063 }
1064 }
1065 }
1066 }
1067 }
1068
1069 /**
1070 * xsltCommentComp:
1071 * @style: an XSLT compiled stylesheet
1072 * @inst: the xslt comment node
1073 *
1074 * Process the xslt comment node on the source node
1075 */
1076 static void
1077 xsltCommentComp(xsltStylesheetPtr style, xmlNodePtr inst) {
1078 #ifdef XSLT_REFACTORED
1079 xsltStyleItemCommentPtr comp;
1080 #else
1081 xsltStylePreCompPtr comp;
1082 #endif
1083
1084 if ((style == NULL) || (inst == NULL) || (inst->type != XML_ELEMENT_NODE))
1085 return;
1086
1087 #ifdef XSLT_REFACTORED
1088 comp = (xsltStyleItemCommentPtr) xsltNewStylePreComp(style, XSLT_FUNC_COMMENT);
1089 #else
1090 comp = xsltNewStylePreComp(style, XSLT_FUNC_COMMENT);
1091 #endif
1092
1093 if (comp == NULL)
1094 return;
1095 inst->psvi = comp;
1096 comp->inst = inst;
1097 }
1098
1099 /**
1100 * xsltProcessingInstructionComp:
1101 * @style: an XSLT compiled stylesheet
1102 * @inst: the xslt processing-instruction node
1103 *
1104 * Process the xslt processing-instruction node on the source node
1105 */
1106 static void
1107 xsltProcessingInstructionComp(xsltStylesheetPtr style, xmlNodePtr inst) {
1108 #ifdef XSLT_REFACTORED
1109 xsltStyleItemPIPtr comp;
1110 #else
1111 xsltStylePreCompPtr comp;
1112 #endif
1113
1114 if ((style == NULL) || (inst == NULL) || (inst->type != XML_ELEMENT_NODE))
1115 return;
1116
1117 #ifdef XSLT_REFACTORED
1118 comp = (xsltStyleItemPIPtr) xsltNewStylePreComp(style, XSLT_FUNC_PI);
1119 #else
1120 comp = xsltNewStylePreComp(style, XSLT_FUNC_PI);
1121 #endif
1122
1123 if (comp == NULL)
1124 return;
1125 inst->psvi = comp;
1126 comp->inst = inst;
1127
1128 comp->name = xsltEvalStaticAttrValueTemplate(style, inst,
1129 (const xmlChar *)"name",
1130 XSLT_NAMESPACE, &comp->has_name);
1131 }
1132
1133 /**
1134 * xsltCopyOfComp:
1135 * @style: an XSLT compiled stylesheet
1136 * @inst: the xslt copy-of node
1137 *
1138 * Process the xslt copy-of node on the source node
1139 */
1140 static void
1141 xsltCopyOfComp(xsltStylesheetPtr style, xmlNodePtr inst) {
1142 #ifdef XSLT_REFACTORED
1143 xsltStyleItemCopyOfPtr comp;
1144 #else
1145 xsltStylePreCompPtr comp;
1146 #endif
1147
1148 if ((style == NULL) || (inst == NULL) || (inst->type != XML_ELEMENT_NODE))
1149 return;
1150
1151 #ifdef XSLT_REFACTORED
1152 comp = (xsltStyleItemCopyOfPtr) xsltNewStylePreComp(style, XSLT_FUNC_COPYOF);
1153 #else
1154 comp = xsltNewStylePreComp(style, XSLT_FUNC_COPYOF);
1155 #endif
1156
1157 if (comp == NULL)
1158 return;
1159 inst->psvi = comp;
1160 comp->inst = inst;
1161
1162 comp->select = xsltGetCNsProp(style, inst, (const xmlChar *)"select",
1163 XSLT_NAMESPACE);
1164 if (comp->select == NULL) {
1165 xsltTransformError(NULL, style, inst,
1166 "xsl:copy-of : select is missing\n");
1167 if (style != NULL) style->errors++;
1168 return;
1169 }
1170 comp->comp = xsltXPathCompile(style, comp->select);
1171 if (comp->comp == NULL) {
1172 xsltTransformError(NULL, style, inst,
1173 "xsl:copy-of : could not compile select expression '%s'\n",
1174 comp->select);
1175 if (style != NULL) style->errors++;
1176 }
1177 }
1178
1179 /**
1180 * xsltValueOfComp:
1181 * @style: an XSLT compiled stylesheet
1182 * @inst: the xslt value-of node
1183 *
1184 * Process the xslt value-of node on the source node
1185 */
1186 static void
1187 xsltValueOfComp(xsltStylesheetPtr style, xmlNodePtr inst) {
1188 #ifdef XSLT_REFACTORED
1189 xsltStyleItemValueOfPtr comp;
1190 #else
1191 xsltStylePreCompPtr comp;
1192 #endif
1193 const xmlChar *prop;
1194
1195 if ((style == NULL) || (inst == NULL) || (inst->type != XML_ELEMENT_NODE))
1196 return;
1197
1198 #ifdef XSLT_REFACTORED
1199 comp = (xsltStyleItemValueOfPtr) xsltNewStylePreComp(style, XSLT_FUNC_VALUEOF);
1200 #else
1201 comp = xsltNewStylePreComp(style, XSLT_FUNC_VALUEOF);
1202 #endif
1203
1204 if (comp == NULL)
1205 return;
1206 inst->psvi = comp;
1207 comp->inst = inst;
1208
1209 prop = xsltGetCNsProp(style, inst,
1210 (const xmlChar *)"disable-output-escaping",
1211 XSLT_NAMESPACE);
1212 if (prop != NULL) {
1213 if (xmlStrEqual(prop, (const xmlChar *)"yes")) {
1214 comp->noescape = 1;
1215 } else if (!xmlStrEqual(prop,
1216 (const xmlChar *)"no")){
1217 xsltTransformError(NULL, style, inst,
1218 "xsl:value-of : disable-output-escaping allows only yes or no\n");
1219 if (style != NULL) style->warnings++;
1220 }
1221 }
1222 comp->select = xsltGetCNsProp(style, inst, (const xmlChar *)"select",
1223 XSLT_NAMESPACE);
1224 if (comp->select == NULL) {
1225 xsltTransformError(NULL, style, inst,
1226 "xsl:value-of : select is missing\n");
1227 if (style != NULL) style->errors++;
1228 return;
1229 }
1230 comp->comp = xsltXPathCompile(style, comp->select);
1231 if (comp->comp == NULL) {
1232 xsltTransformError(NULL, style, inst,
1233 "xsl:value-of : could not compile select expression '%s'\n",
1234 comp->select);
1235 if (style != NULL) style->errors++;
1236 }
1237 }
1238
1239 static void
1240 xsltGetQNameProperty(xsltStylesheetPtr style, xmlNodePtr inst,
1241 const xmlChar *propName,
1242 int mandatory,
1243 int *hasProp, const xmlChar **nsName,
1244 const xmlChar** localName)
1245 {
1246 const xmlChar *prop;
1247
1248 if (nsName)
1249 *nsName = NULL;
1250 if (localName)
1251 *localName = NULL;
1252 if (hasProp)
1253 *hasProp = 0;
1254
1255 prop = xsltGetCNsProp(style, inst, propName, XSLT_NAMESPACE);
1256 if (prop == NULL) {
1257 if (mandatory) {
1258 xsltTransformError(NULL, style, inst,
1259 "The attribute '%s' is missing.\n", propName);
1260 style->errors++;
1261 return;
1262 }
1263 } else {
1264 const xmlChar *URI;
1265
1266 if (xmlValidateQName(prop, 0)) {
1267 xsltTransformError(NULL, style, inst,
1268 "The value '%s' of the attribute "
1269 "'%s' is not a valid QName.\n", prop, propName);
1270 style->errors++;
1271 return;
1272 } else {
1273 /*
1274 * @prop will be in the string dict afterwards, @URI not.
1275 */
1276 URI = xsltGetQNameURI2(style, inst, &prop);
1277 if (prop == NULL) {
1278 style->errors++;
1279 } else {
1280 *localName = prop;
1281 if (hasProp)
1282 *hasProp = 1;
1283 if (URI != NULL) {
1284 /*
1285 * Fixes bug #308441: Put the ns-name in the dict
1286 * in order to pointer compare names during XPath's
1287 * variable lookup.
1288 */
1289 if (nsName)
1290 *nsName = xmlDictLookup(style->dict, URI, -1);
1291 /* comp->has_ns = 1; */
1292 }
1293 }
1294 }
1295 }
1296 return;
1297 }
1298
1299 /**
1300 * xsltWithParamComp:
1301 * @style: an XSLT compiled stylesheet
1302 * @inst: the xslt with-param node
1303 *
1304 * Process the xslt with-param node on the source node
1305 * Allowed parents: xsl:call-template, xsl:apply-templates.
1306 * <xsl:with-param
1307 * name = qname
1308 * select = expression>
1309 * <!-- Content: template -->
1310 * </xsl:with-param>
1311 */
1312 static void
1313 xsltWithParamComp(xsltStylesheetPtr style, xmlNodePtr inst) {
1314 #ifdef XSLT_REFACTORED
1315 xsltStyleItemWithParamPtr comp;
1316 #else
1317 xsltStylePreCompPtr comp;
1318 #endif
1319
1320 if ((style == NULL) || (inst == NULL) || (inst->type != XML_ELEMENT_NODE))
1321 return;
1322
1323 #ifdef XSLT_REFACTORED
1324 comp = (xsltStyleItemWithParamPtr) xsltNewStylePreComp(style, XSLT_FUNC_WITHPARAM);
1325 #else
1326 comp = xsltNewStylePreComp(style, XSLT_FUNC_WITHPARAM);
1327 #endif
1328
1329 if (comp == NULL)
1330 return;
1331 inst->psvi = comp;
1332 comp->inst = inst;
1333
1334 /*
1335 * Attribute "name".
1336 */
1337 xsltGetQNameProperty(style, inst, BAD_CAST "name",
1338 1, &(comp->has_name), &(comp->ns), &(comp->name));
1339 if (comp->ns)
1340 comp->has_ns = 1;
1341 /*
1342 * Attribute "select".
1343 */
1344 comp->select = xsltGetCNsProp(style, inst, (const xmlChar *)"select",
1345 XSLT_NAMESPACE);
1346 if (comp->select != NULL) {
1347 comp->comp = xsltXPathCompile(style, comp->select);
1348 if (comp->comp == NULL) {
1349 xsltTransformError(NULL, style, inst,
1350 "XSLT-with-param: Failed to compile select "
1351 "expression '%s'\n", comp->select);
1352 style->errors++;
1353 }
1354 if (inst->children != NULL) {
1355 xsltTransformError(NULL, style, inst,
1356 "XSLT-with-param: The content should be empty since "
1357 "the attribute select is present.\n");
1358 style->warnings++;
1359 }
1360 }
1361 }
1362
1363 /**
1364 * xsltNumberComp:
1365 * @style: an XSLT compiled stylesheet
1366 * @cur: the xslt number node
1367 *
1368 * Process the xslt number node on the source node
1369 */
1370 static void
1371 xsltNumberComp(xsltStylesheetPtr style, xmlNodePtr cur) {
1372 #ifdef XSLT_REFACTORED
1373 xsltStyleItemNumberPtr comp;
1374 #else
1375 xsltStylePreCompPtr comp;
1376 #endif
1377 const xmlChar *prop;
1378
1379 if ((style == NULL) || (cur == NULL) || (cur->type != XML_ELEMENT_NODE))
1380 return;
1381
1382 #ifdef XSLT_REFACTORED
1383 comp = (xsltStyleItemNumberPtr) xsltNewStylePreComp(style, XSLT_FUNC_NUMBER);
1384 #else
1385 comp = xsltNewStylePreComp(style, XSLT_FUNC_NUMBER);
1386 #endif
1387
1388 if (comp == NULL)
1389 return;
1390 cur->psvi = comp;
1391
1392 if ((style == NULL) || (cur == NULL))
1393 return;
1394
1395 comp->numdata.doc = cur->doc;
1396 comp->numdata.node = cur;
1397 comp->numdata.value = xsltGetCNsProp(style, cur, (const xmlChar *)"value",
1398 XSLT_NAMESPACE);
1399
1400 prop = xsltEvalStaticAttrValueTemplate(style, cur,
1401 (const xmlChar *)"format",
1402 XSLT_NAMESPACE, &comp->numdata.has_format);
1403 if (comp->numdata.has_format == 0) {
1404 comp->numdata.format = xmlDictLookup(style->dict, BAD_CAST "" , 0);
1405 } else {
1406 comp->numdata.format = prop;
1407 }
1408
1409 comp->numdata.count = xsltGetCNsProp(style, cur, (const xmlChar *)"count",
1410 XSLT_NAMESPACE);
1411 comp->numdata.from = xsltGetCNsProp(style, cur, (const xmlChar *)"from",
1412 XSLT_NAMESPACE);
1413
1414 prop = xsltGetCNsProp(style, cur, (const xmlChar *)"count", XSLT_NAMESPACE);
1415 if (prop != NULL) {
1416 comp->numdata.countPat = xsltCompilePattern(prop, cur->doc, cur, style,
1417 NULL);
1418 }
1419
1420 prop = xsltGetCNsProp(style, cur, (const xmlChar *)"from", XSLT_NAMESPACE);
1421 if (prop != NULL) {
1422 comp->numdata.fromPat = xsltCompilePattern(prop, cur->doc, cur, style,
1423 NULL);
1424 }
1425
1426 prop = xsltGetCNsProp(style, cur, (const xmlChar *)"level", XSLT_NAMESPACE);
1427 if (prop != NULL) {
1428 if (xmlStrEqual(prop, BAD_CAST("single")) ||
1429 xmlStrEqual(prop, BAD_CAST("multiple")) ||
1430 xmlStrEqual(prop, BAD_CAST("any"))) {
1431 comp->numdata.level = prop;
1432 } else {
1433 xsltTransformError(NULL, style, cur,
1434 "xsl:number : invalid value %s for level\n", prop);
1435 if (style != NULL) style->warnings++;
1436 }
1437 }
1438
1439 prop = xsltGetCNsProp(style, cur, (const xmlChar *)"lang", XSLT_NAMESPACE);
1440 if (prop != NULL) {
1441 xsltTransformError(NULL, style, cur,
1442 "xsl:number : lang attribute not implemented\n");
1443 XSLT_TODO; /* xsl:number lang attribute */
1444 }
1445
1446 prop = xsltGetCNsProp(style, cur, (const xmlChar *)"letter-value", XSLT_NAMESPACE);
1447 if (prop != NULL) {
1448 if (xmlStrEqual(prop, BAD_CAST("alphabetic"))) {
1449 xsltTransformError(NULL, style, cur,
1450 "xsl:number : letter-value 'alphabetic' not implemented\n");
1451 if (style != NULL) style->warnings++;
1452 XSLT_TODO; /* xsl:number letter-value attribute alphabetic */
1453 } else if (xmlStrEqual(prop, BAD_CAST("traditional"))) {
1454 xsltTransformError(NULL, style, cur,
1455 "xsl:number : letter-value 'traditional' not implemented\n");
1456 if (style != NULL) style->warnings++;
1457 XSLT_TODO; /* xsl:number letter-value attribute traditional */
1458 } else {
1459 xsltTransformError(NULL, style, cur,
1460 "xsl:number : invalid value %s for letter-value\n", prop);
1461 if (style != NULL) style->warnings++;
1462 }
1463 }
1464
1465 prop = xsltGetCNsProp(style, cur, (const xmlChar *)"grouping-separator",
1466 XSLT_NAMESPACE);
1467 if (prop != NULL) {
1468 comp->numdata.groupingCharacterLen = xmlStrlen(prop);
1469 comp->numdata.groupingCharacter =
1470 xsltGetUTF8Char(prop, &(comp->numdata.groupingCharacterLen));
1471 }
1472
1473 prop = xsltGetCNsProp(style, cur, (const xmlChar *)"grouping-size", XSLT_NAMESPACE);
1474 if (prop != NULL) {
1475 sscanf((char *)prop, "%d", &comp->numdata.digitsPerGroup);
1476 } else {
1477 comp->numdata.groupingCharacter = 0;
1478 }
1479
1480 /* Set default values */
1481 if (comp->numdata.value == NULL) {
1482 if (comp->numdata.level == NULL) {
1483 comp->numdata.level = xmlDictLookup(style->dict,
1484 BAD_CAST"single", 6);
1485 }
1486 }
1487
1488 }
1489
1490 /**
1491 * xsltApplyImportsComp:
1492 * @style: an XSLT compiled stylesheet
1493 * @inst: the xslt apply-imports node
1494 *
1495 * Process the xslt apply-imports node on the source node
1496 */
1497 static void
1498 xsltApplyImportsComp(xsltStylesheetPtr style, xmlNodePtr inst) {
1499 #ifdef XSLT_REFACTORED
1500 xsltStyleItemApplyImportsPtr comp;
1501 #else
1502 xsltStylePreCompPtr comp;
1503 #endif
1504
1505 if ((style == NULL) || (inst == NULL) || (inst->type != XML_ELEMENT_NODE))
1506 return;
1507
1508 #ifdef XSLT_REFACTORED
1509 comp = (xsltStyleItemApplyImportsPtr) xsltNewStylePreComp(style, XSLT_FUNC_APPLYIMPORTS);
1510 #else
1511 comp = xsltNewStylePreComp(style, XSLT_FUNC_APPLYIMPORTS);
1512 #endif
1513
1514 if (comp == NULL)
1515 return;
1516 inst->psvi = comp;
1517 comp->inst = inst;
1518 }
1519
1520 /**
1521 * xsltCallTemplateComp:
1522 * @style: an XSLT compiled stylesheet
1523 * @inst: the xslt call-template node
1524 *
1525 * Process the xslt call-template node on the source node
1526 */
1527 static void
1528 xsltCallTemplateComp(xsltStylesheetPtr style, xmlNodePtr inst) {
1529 #ifdef XSLT_REFACTORED
1530 xsltStyleItemCallTemplatePtr comp;
1531 #else
1532 xsltStylePreCompPtr comp;
1533 #endif
1534
1535 if ((style == NULL) || (inst == NULL) || (inst->type != XML_ELEMENT_NODE))
1536 return;
1537
1538 #ifdef XSLT_REFACTORED
1539 comp = (xsltStyleItemCallTemplatePtr)
1540 xsltNewStylePreComp(style, XSLT_FUNC_CALLTEMPLATE);
1541 #else
1542 comp = xsltNewStylePreComp(style, XSLT_FUNC_CALLTEMPLATE);
1543 #endif
1544
1545 if (comp == NULL)
1546 return;
1547 inst->psvi = comp;
1548 comp->inst = inst;
1549
1550 /*
1551 * Attribute "name".
1552 */
1553 xsltGetQNameProperty(style, inst, BAD_CAST "name",
1554 1, &(comp->has_name), &(comp->ns), &(comp->name));
1555 if (comp->ns)
1556 comp->has_ns = 1;
1557 }
1558
1559 /**
1560 * xsltApplyTemplatesComp:
1561 * @style: an XSLT compiled stylesheet
1562 * @inst: the apply-templates node
1563 *
1564 * Process the apply-templates node on the source node
1565 */
1566 static void
1567 xsltApplyTemplatesComp(xsltStylesheetPtr style, xmlNodePtr inst) {
1568 #ifdef XSLT_REFACTORED
1569 xsltStyleItemApplyTemplatesPtr comp;
1570 #else
1571 xsltStylePreCompPtr comp;
1572 #endif
1573
1574 if ((style == NULL) || (inst == NULL) || (inst->type != XML_ELEMENT_NODE))
1575 return;
1576
1577 #ifdef XSLT_REFACTORED
1578 comp = (xsltStyleItemApplyTemplatesPtr)
1579 xsltNewStylePreComp(style, XSLT_FUNC_APPLYTEMPLATES);
1580 #else
1581 comp = xsltNewStylePreComp(style, XSLT_FUNC_APPLYTEMPLATES);
1582 #endif
1583
1584 if (comp == NULL)
1585 return;
1586 inst->psvi = comp;
1587 comp->inst = inst;
1588
1589 /*
1590 * Attribute "mode".
1591 */
1592 xsltGetQNameProperty(style, inst, BAD_CAST "mode",
1593 0, NULL, &(comp->modeURI), &(comp->mode));
1594 /*
1595 * Attribute "select".
1596 */
1597 comp->select = xsltGetCNsProp(style, inst, BAD_CAST "select",
1598 XSLT_NAMESPACE);
1599 if (comp->select != NULL) {
1600 comp->comp = xsltXPathCompile(style, comp->select);
1601 if (comp->comp == NULL) {
1602 xsltTransformError(NULL, style, inst,
1603 "XSLT-apply-templates: could not compile select "
1604 "expression '%s'\n", comp->select);
1605 style->errors++;
1606 }
1607 }
1608 /* TODO: handle (or skip) the xsl:sort and xsl:with-param */
1609 }
1610
1611 /**
1612 * xsltChooseComp:
1613 * @style: an XSLT compiled stylesheet
1614 * @inst: the xslt choose node
1615 *
1616 * Process the xslt choose node on the source node
1617 */
1618 static void
1619 xsltChooseComp(xsltStylesheetPtr style, xmlNodePtr inst) {
1620 #ifdef XSLT_REFACTORED
1621 xsltStyleItemChoosePtr comp;
1622 #else
1623 xsltStylePreCompPtr comp;
1624 #endif
1625
1626 if ((style == NULL) || (inst == NULL) || (inst->type != XML_ELEMENT_NODE))
1627 return;
1628
1629 #ifdef XSLT_REFACTORED
1630 comp = (xsltStyleItemChoosePtr)
1631 xsltNewStylePreComp(style, XSLT_FUNC_CHOOSE);
1632 #else
1633 comp = xsltNewStylePreComp(style, XSLT_FUNC_CHOOSE);
1634 #endif
1635
1636 if (comp == NULL)
1637 return;
1638 inst->psvi = comp;
1639 comp->inst = inst;
1640 }
1641
1642 /**
1643 * xsltIfComp:
1644 * @style: an XSLT compiled stylesheet
1645 * @inst: the xslt if node
1646 *
1647 * Process the xslt if node on the source node
1648 */
1649 static void
1650 xsltIfComp(xsltStylesheetPtr style, xmlNodePtr inst) {
1651 #ifdef XSLT_REFACTORED
1652 xsltStyleItemIfPtr comp;
1653 #else
1654 xsltStylePreCompPtr comp;
1655 #endif
1656
1657 if ((style == NULL) || (inst == NULL) || (inst->type != XML_ELEMENT_NODE))
1658 return;
1659
1660 #ifdef XSLT_REFACTORED
1661 comp = (xsltStyleItemIfPtr)
1662 xsltNewStylePreComp(style, XSLT_FUNC_IF);
1663 #else
1664 comp = xsltNewStylePreComp(style, XSLT_FUNC_IF);
1665 #endif
1666
1667 if (comp == NULL)
1668 return;
1669 inst->psvi = comp;
1670 comp->inst = inst;
1671
1672 comp->test = xsltGetCNsProp(style, inst, (const xmlChar *)"test", XSLT_NAMESPACE);
1673 if (comp->test == NULL) {
1674 xsltTransformError(NULL, style, inst,
1675 "xsl:if : test is not defined\n");
1676 if (style != NULL) style->errors++;
1677 return;
1678 }
1679 comp->comp = xsltXPathCompile(style, comp->test);
1680 if (comp->comp == NULL) {
1681 xsltTransformError(NULL, style, inst,
1682 "xsl:if : could not compile test expression '%s'\n",
1683 comp->test);
1684 if (style != NULL) style->errors++;
1685 }
1686 }
1687
1688 /**
1689 * xsltWhenComp:
1690 * @style: an XSLT compiled stylesheet
1691 * @inst: the xslt if node
1692 *
1693 * Process the xslt if node on the source node
1694 */
1695 static void
1696 xsltWhenComp(xsltStylesheetPtr style, xmlNodePtr inst) {
1697 #ifdef XSLT_REFACTORED
1698 xsltStyleItemWhenPtr comp;
1699 #else
1700 xsltStylePreCompPtr comp;
1701 #endif
1702
1703 if ((style == NULL) || (inst == NULL) || (inst->type != XML_ELEMENT_NODE))
1704 return;
1705
1706 #ifdef XSLT_REFACTORED
1707 comp = (xsltStyleItemWhenPtr)
1708 xsltNewStylePreComp(style, XSLT_FUNC_WHEN);
1709 #else
1710 comp = xsltNewStylePreComp(style, XSLT_FUNC_WHEN);
1711 #endif
1712
1713 if (comp == NULL)
1714 return;
1715 inst->psvi = comp;
1716 comp->inst = inst;
1717
1718 comp->test = xsltGetCNsProp(style, inst, (const xmlChar *)"test", XSLT_NAMESPACE);
1719 if (comp->test == NULL) {
1720 xsltTransformError(NULL, style, inst,
1721 "xsl:when : test is not defined\n");
1722 if (style != NULL) style->errors++;
1723 return;
1724 }
1725 comp->comp = xsltXPathCompile(style, comp->test);
1726 if (comp->comp == NULL) {
1727 xsltTransformError(NULL, style, inst,
1728 "xsl:when : could not compile test expression '%s'\n",
1729 comp->test);
1730 if (style != NULL) style->errors++;
1731 }
1732 }
1733
1734 /**
1735 * xsltForEachComp:
1736 * @style: an XSLT compiled stylesheet
1737 * @inst: the xslt for-each node
1738 *
1739 * Process the xslt for-each node on the source node
1740 */
1741 static void
1742 xsltForEachComp(xsltStylesheetPtr style, xmlNodePtr inst) {
1743 #ifdef XSLT_REFACTORED
1744 xsltStyleItemForEachPtr comp;
1745 #else
1746 xsltStylePreCompPtr comp;
1747 #endif
1748
1749 if ((style == NULL) || (inst == NULL) || (inst->type != XML_ELEMENT_NODE))
1750 return;
1751
1752 #ifdef XSLT_REFACTORED
1753 comp = (xsltStyleItemForEachPtr)
1754 xsltNewStylePreComp(style, XSLT_FUNC_FOREACH);
1755 #else
1756 comp = xsltNewStylePreComp(style, XSLT_FUNC_FOREACH);
1757 #endif
1758
1759 if (comp == NULL)
1760 return;
1761 inst->psvi = comp;
1762 comp->inst = inst;
1763
1764 comp->select = xsltGetCNsProp(style, inst, (const xmlChar *)"select",
1765 XSLT_NAMESPACE);
1766 if (comp->select == NULL) {
1767 xsltTransformError(NULL, style, inst,
1768 "xsl:for-each : select is missing\n");
1769 if (style != NULL) style->errors++;
1770 } else {
1771 comp->comp = xsltXPathCompile(style, comp->select);
1772 if (comp->comp == NULL) {
1773 xsltTransformError(NULL, style, inst,
1774 "xsl:for-each : could not compile select expression '%s'\n",
1775 comp->select);
1776 if (style != NULL) style->errors++;
1777 }
1778 }
1779 /* TODO: handle and skip the xsl:sort */
1780 }
1781
1782 /**
1783 * xsltVariableComp:
1784 * @style: an XSLT compiled stylesheet
1785 * @inst: the xslt variable node
1786 *
1787 * Process the xslt variable node on the source node
1788 */
1789 static void
1790 xsltVariableComp(xsltStylesheetPtr style, xmlNodePtr inst) {
1791 #ifdef XSLT_REFACTORED
1792 xsltStyleItemVariablePtr comp;
1793 #else
1794 xsltStylePreCompPtr comp;
1795 #endif
1796
1797 if ((style == NULL) || (inst == NULL) || (inst->type != XML_ELEMENT_NODE))
1798 return;
1799
1800 #ifdef XSLT_REFACTORED
1801 comp = (xsltStyleItemVariablePtr)
1802 xsltNewStylePreComp(style, XSLT_FUNC_VARIABLE);
1803 #else
1804 comp = xsltNewStylePreComp(style, XSLT_FUNC_VARIABLE);
1805 #endif
1806
1807 if (comp == NULL)
1808 return;
1809
1810 inst->psvi = comp;
1811 comp->inst = inst;
1812 /*
1813 * The full template resolution can be done statically
1814 */
1815
1816 /*
1817 * Attribute "name".
1818 */
1819 xsltGetQNameProperty(style, inst, BAD_CAST "name",
1820 1, &(comp->has_name), &(comp->ns), &(comp->name));
1821 if (comp->ns)
1822 comp->has_ns = 1;
1823 /*
1824 * Attribute "select".
1825 */
1826 comp->select = xsltGetCNsProp(style, inst, (const xmlChar *)"select",
1827 XSLT_NAMESPACE);
1828 if (comp->select != NULL) {
1829 #ifndef XSLT_REFACTORED
1830 xmlNodePtr cur;
1831 #endif
1832 comp->comp = xsltXPathCompile(style, comp->select);
1833 if (comp->comp == NULL) {
1834 xsltTransformError(NULL, style, inst,
1835 "XSLT-variable: Failed to compile the XPath expression '%s'.\n",
1836 comp->select);
1837 style->errors++;
1838 }
1839 #ifdef XSLT_REFACTORED
1840 if (inst->children != NULL) {
1841 xsltTransformError(NULL, style, inst,
1842 "XSLT-variable: There must be no child nodes, since the "
1843 "attribute 'select' was specified.\n");
1844 style->errors++;
1845 }
1846 #else
1847 for (cur = inst->children; cur != NULL; cur = cur->next) {
1848 if (cur->type != XML_COMMENT_NODE &&
1849 (cur->type != XML_TEXT_NODE || !xsltIsBlank(cur->content)))
1850 {
1851 xsltTransformError(NULL, style, inst,
1852 "XSLT-variable: There must be no child nodes, since the "
1853 "attribute 'select' was specified.\n");
1854 style->errors++;
1855 }
1856 }
1857 #endif
1858 }
1859 }
1860
1861 /**
1862 * xsltParamComp:
1863 * @style: an XSLT compiled stylesheet
1864 * @inst: the xslt param node
1865 *
1866 * Process the xslt param node on the source node
1867 */
1868 static void
1869 xsltParamComp(xsltStylesheetPtr style, xmlNodePtr inst) {
1870 #ifdef XSLT_REFACTORED
1871 xsltStyleItemParamPtr comp;
1872 #else
1873 xsltStylePreCompPtr comp;
1874 #endif
1875
1876 if ((style == NULL) || (inst == NULL) || (inst->type != XML_ELEMENT_NODE))
1877 return;
1878
1879 #ifdef XSLT_REFACTORED
1880 comp = (xsltStyleItemParamPtr)
1881 xsltNewStylePreComp(style, XSLT_FUNC_PARAM);
1882 #else
1883 comp = xsltNewStylePreComp(style, XSLT_FUNC_PARAM);
1884 #endif
1885
1886 if (comp == NULL)
1887 return;
1888 inst->psvi = comp;
1889 comp->inst = inst;
1890
1891 /*
1892 * Attribute "name".
1893 */
1894 xsltGetQNameProperty(style, inst, BAD_CAST "name",
1895 1, &(comp->has_name), &(comp->ns), &(comp->name));
1896 if (comp->ns)
1897 comp->has_ns = 1;
1898 /*
1899 * Attribute "select".
1900 */
1901 comp->select = xsltGetCNsProp(style, inst, (const xmlChar *)"select",
1902 XSLT_NAMESPACE);
1903 if (comp->select != NULL) {
1904 comp->comp = xsltXPathCompile(style, comp->select);
1905 if (comp->comp == NULL) {
1906 xsltTransformError(NULL, style, inst,
1907 "XSLT-param: could not compile select expression '%s'.\n",
1908 comp->select);
1909 style->errors++;
1910 }
1911 if (inst->children != NULL) {
1912 xsltTransformError(NULL, style, inst,
1913 "XSLT-param: The content should be empty since the "
1914 "attribute 'select' is present.\n");
1915 style->warnings++;
1916 }
1917 }
1918 }
1919
1920 /************************************************************************
1921 * *
1922 * Generic interface *
1923 * *
1924 ************************************************************************/
1925
1926 /**
1927 * xsltFreeStylePreComps:
1928 * @style: an XSLT transformation context
1929 *
1930 * Free up the memory allocated by all precomputed blocks
1931 */
1932 void
1933 xsltFreeStylePreComps(xsltStylesheetPtr style) {
1934 xsltElemPreCompPtr cur, next;
1935
1936 if (style == NULL)
1937 return;
1938
1939 cur = style->preComps;
1940 while (cur != NULL) {
1941 next = cur->next;
1942 if (cur->type == XSLT_FUNC_EXTENSION)
1943 cur->free(cur);
1944 else
1945 xsltFreeStylePreComp((xsltStylePreCompPtr) cur);
1946 cur = next;
1947 }
1948 }
1949
1950 #ifdef XSLT_REFACTORED
1951
1952 /**
1953 * xsltStylePreCompute:
1954 * @style: the XSLT stylesheet
1955 * @node: the element in the XSLT namespace
1956 *
1957 * Precompute an XSLT element.
1958 * This expects the type of the element to be already
1959 * set in style->compCtxt->inode->type;
1960 */
1961 void
1962 xsltStylePreCompute(xsltStylesheetPtr style, xmlNodePtr node) {
1963 /*
1964 * The xsltXSLTElemMarker marker was set beforehand by
1965 * the parsing mechanism for all elements in the XSLT namespace.
1966 */
1967 if (style == NULL) {
1968 if ((node != NULL) && (node->type == XML_ELEMENT_NODE))
1969 node->psvi = NULL;
1970 return;
1971 }
1972 if (node == NULL)
1973 return;
1974 if (! IS_XSLT_ELEM_FAST(node))
1975 return;
1976
1977 node->psvi = NULL;
1978 if (XSLT_CCTXT(style)->inode->type != 0) {
1979 switch (XSLT_CCTXT(style)->inode->type) {
1980 case XSLT_FUNC_APPLYTEMPLATES:
1981 xsltApplyTemplatesComp(style, node);
1982 break;
1983 case XSLT_FUNC_WITHPARAM:
1984 xsltWithParamComp(style, node);
1985 break;
1986 case XSLT_FUNC_VALUEOF:
1987 xsltValueOfComp(style, node);
1988 break;
1989 case XSLT_FUNC_COPY:
1990 xsltCopyComp(style, node);
1991 break;
1992 case XSLT_FUNC_COPYOF:
1993 xsltCopyOfComp(style, node);
1994 break;
1995 case XSLT_FUNC_IF:
1996 xsltIfComp(style, node);
1997 break;
1998 case XSLT_FUNC_CHOOSE:
1999 xsltChooseComp(style, node);
2000 break;
2001 case XSLT_FUNC_WHEN:
2002 xsltWhenComp(style, node);
2003 break;
2004 case XSLT_FUNC_OTHERWISE:
2005 /* NOP yet */
2006 return;
2007 case XSLT_FUNC_FOREACH:
2008 xsltForEachComp(style, node);
2009 break;
2010 case XSLT_FUNC_APPLYIMPORTS:
2011 xsltApplyImportsComp(style, node);
2012 break;
2013 case XSLT_FUNC_ATTRIBUTE:
2014 xsltAttributeComp(style, node);
2015 break;
2016 case XSLT_FUNC_ELEMENT:
2017 xsltElementComp(style, node);
2018 break;
2019 case XSLT_FUNC_SORT:
2020 xsltSortComp(style, node);
2021 break;
2022 case XSLT_FUNC_COMMENT:
2023 xsltCommentComp(style, node);
2024 break;
2025 case XSLT_FUNC_NUMBER:
2026 xsltNumberComp(style, node);
2027 break;
2028 case XSLT_FUNC_PI:
2029 xsltProcessingInstructionComp(style, node);
2030 break;
2031 case XSLT_FUNC_CALLTEMPLATE:
2032 xsltCallTemplateComp(style, node);
2033 break;
2034 case XSLT_FUNC_PARAM:
2035 xsltParamComp(style, node);
2036 break;
2037 case XSLT_FUNC_VARIABLE:
2038 xsltVariableComp(style, node);
2039 break;
2040 case XSLT_FUNC_FALLBACK:
2041 /* NOP yet */
2042 return;
2043 case XSLT_FUNC_DOCUMENT:
2044 /* The extra one */
2045 node->psvi = (void *) xsltDocumentComp(style, node,
2046 (xsltTransformFunction) xsltDocumentElem);
2047 break;
2048 case XSLT_FUNC_MESSAGE:
2049 /* NOP yet */
2050 return;
2051 default:
2052 /*
2053 * NOTE that xsl:text, xsl:template, xsl:stylesheet,
2054 * xsl:transform, xsl:import, xsl:include are not expected
2055 * to be handed over to this function.
2056 */
2057 xsltTransformError(NULL, style, node,
2058 "Internal error: (xsltStylePreCompute) cannot handle "
2059 "the XSLT element '%s'.\n", node->name);
2060 style->errors++;
2061 return;
2062 }
2063 } else {
2064 /*
2065 * Fallback to string comparison.
2066 */
2067 if (IS_XSLT_NAME(node, "apply-templates")) {
2068 xsltApplyTemplatesComp(style, node);
2069 } else if (IS_XSLT_NAME(node, "with-param")) {
2070 xsltWithParamComp(style, node);
2071 } else if (IS_XSLT_NAME(node, "value-of")) {
2072 xsltValueOfComp(style, node);
2073 } else if (IS_XSLT_NAME(node, "copy")) {
2074 xsltCopyComp(style, node);
2075 } else if (IS_XSLT_NAME(node, "copy-of")) {
2076 xsltCopyOfComp(style, node);
2077 } else if (IS_XSLT_NAME(node, "if")) {
2078 xsltIfComp(style, node);
2079 } else if (IS_XSLT_NAME(node, "choose")) {
2080 xsltChooseComp(style, node);
2081 } else if (IS_XSLT_NAME(node, "when")) {
2082 xsltWhenComp(style, node);
2083 } else if (IS_XSLT_NAME(node, "otherwise")) {
2084 /* NOP yet */
2085 return;
2086 } else if (IS_XSLT_NAME(node, "for-each")) {
2087 xsltForEachComp(style, node);
2088 } else if (IS_XSLT_NAME(node, "apply-imports")) {
2089 xsltApplyImportsComp(style, node);
2090 } else if (IS_XSLT_NAME(node, "attribute")) {
2091 xsltAttributeComp(style, node);
2092 } else if (IS_XSLT_NAME(node, "element")) {
2093 xsltElementComp(style, node);
2094 } else if (IS_XSLT_NAME(node, "sort")) {
2095 xsltSortComp(style, node);
2096 } else if (IS_XSLT_NAME(node, "comment")) {
2097 xsltCommentComp(style, node);
2098 } else if (IS_XSLT_NAME(node, "number")) {
2099 xsltNumberComp(style, node);
2100 } else if (IS_XSLT_NAME(node, "processing-instruction")) {
2101 xsltProcessingInstructionComp(style, node);
2102 } else if (IS_XSLT_NAME(node, "call-template")) {
2103 xsltCallTemplateComp(style, node);
2104 } else if (IS_XSLT_NAME(node, "param")) {
2105 xsltParamComp(style, node);
2106 } else if (IS_XSLT_NAME(node, "variable")) {
2107 xsltVariableComp(style, node);
2108 } else if (IS_XSLT_NAME(node, "fallback")) {
2109 /* NOP yet */
2110 return;
2111 } else if (IS_XSLT_NAME(node, "document")) {
2112 /* The extra one */
2113 node->psvi = (void *) xsltDocumentComp(style, node,
2114 (xsltTransformFunction) xsltDocumentElem);
2115 } else if (IS_XSLT_NAME(node, "output")) {
2116 /* Top-level */
2117 return;
2118 } else if (IS_XSLT_NAME(node, "preserve-space")) {
2119 /* Top-level */
2120 return;
2121 } else if (IS_XSLT_NAME(node, "strip-space")) {
2122 /* Top-level */
2123 return;
2124 } else if (IS_XSLT_NAME(node, "key")) {
2125 /* Top-level */
2126 return;
2127 } else if (IS_XSLT_NAME(node, "message")) {
2128 return;
2129 } else if (IS_XSLT_NAME(node, "attribute-set")) {
2130 /* Top-level */
2131 return;
2132 } else if (IS_XSLT_NAME(node, "namespace-alias")) {
2133 /* Top-level */
2134 return;
2135 } else if (IS_XSLT_NAME(node, "decimal-format")) {
2136 /* Top-level */
2137 return;
2138 } else if (IS_XSLT_NAME(node, "include")) {
2139 /* Top-level */
2140 } else {
2141 /*
2142 * NOTE that xsl:text, xsl:template, xsl:stylesheet,
2143 * xsl:transform, xsl:import, xsl:include are not expected
2144 * to be handed over to this function.
2145 */
2146 xsltTransformError(NULL, style, node,
2147 "Internal error: (xsltStylePreCompute) cannot handle "
2148 "the XSLT element '%s'.\n", node->name);
2149 style->errors++;
2150 return;
2151 }
2152 }
2153 /*
2154 * Assign the current list of in-scope namespaces to the
2155 * item. This is needed for XPath expressions.
2156 */
2157 if (node->psvi != NULL) {
2158 ((xsltStylePreCompPtr) node->psvi)->inScopeNs =
2159 XSLT_CCTXT(style)->inode->inScopeNs;
2160 }
2161 }
2162
2163 #else
2164
2165 /**
2166 * xsltStylePreCompute:
2167 * @style: the XSLT stylesheet
2168 * @inst: the instruction in the stylesheet
2169 *
2170 * Precompute an XSLT stylesheet element
2171 */
2172 void
2173 xsltStylePreCompute(xsltStylesheetPtr style, xmlNodePtr inst) {
2174 /*
2175 * URGENT TODO: Normally inst->psvi Should never be reserved here,
2176 * BUT: since if we include the same stylesheet from
2177 * multiple imports, then the stylesheet will be parsed
2178 * again. We simply must not try to compute the stylesheet again.
2179 * TODO: Get to the point where we don't need to query the
2180 * namespace- and local-name of the node, but can evaluate this
2181 * using cctxt->style->inode->category;
2182 */
2183 if ((inst == NULL) || (inst->type != XML_ELEMENT_NODE) ||
2184 (inst->psvi != NULL))
2185 return;
2186
2187 if (IS_XSLT_ELEM(inst)) {
2188 xsltStylePreCompPtr cur;
2189
2190 if (IS_XSLT_NAME(inst, "apply-templates")) {
2191 xsltCheckInstructionElement(style, inst);
2192 xsltApplyTemplatesComp(style, inst);
2193 } else if (IS_XSLT_NAME(inst, "with-param")) {
2194 xsltCheckParentElement(style, inst, BAD_CAST "apply-templates",
2195 BAD_CAST "call-template");
2196 xsltWithParamComp(style, inst);
2197 } else if (IS_XSLT_NAME(inst, "value-of")) {
2198 xsltCheckInstructionElement(style, inst);
2199 xsltValueOfComp(style, inst);
2200 } else if (IS_XSLT_NAME(inst, "copy")) {
2201 xsltCheckInstructionElement(style, inst);
2202 xsltCopyComp(style, inst);
2203 } else if (IS_XSLT_NAME(inst, "copy-of")) {
2204 xsltCheckInstructionElement(style, inst);
2205 xsltCopyOfComp(style, inst);
2206 } else if (IS_XSLT_NAME(inst, "if")) {
2207 xsltCheckInstructionElement(style, inst);
2208 xsltIfComp(style, inst);
2209 } else if (IS_XSLT_NAME(inst, "when")) {
2210 xsltCheckParentElement(style, inst, BAD_CAST "choose", NULL);
2211 xsltWhenComp(style, inst);
2212 } else if (IS_XSLT_NAME(inst, "choose")) {
2213 xsltCheckInstructionElement(style, inst);
2214 xsltChooseComp(style, inst);
2215 } else if (IS_XSLT_NAME(inst, "for-each")) {
2216 xsltCheckInstructionElement(style, inst);
2217 xsltForEachComp(style, inst);
2218 } else if (IS_XSLT_NAME(inst, "apply-imports")) {
2219 xsltCheckInstructionElement(style, inst);
2220 xsltApplyImportsComp(style, inst);
2221 } else if (IS_XSLT_NAME(inst, "attribute")) {
2222 xmlNodePtr parent = inst->parent;
2223
2224 if ((parent == NULL) || (parent->ns == NULL) ||
2225 ((parent->ns != inst->ns) &&
2226 (!xmlStrEqual(parent->ns->href, inst->ns->href))) ||
2227 (!xmlStrEqual(parent->name, BAD_CAST "attribute-set"))) {
2228 xsltCheckInstructionElement(style, inst);
2229 }
2230 xsltAttributeComp(style, inst);
2231 } else if (IS_XSLT_NAME(inst, "element")) {
2232 xsltCheckInstructionElement(style, inst);
2233 xsltElementComp(style, inst);
2234 } else if (IS_XSLT_NAME(inst, "text")) {
2235 xsltCheckInstructionElement(style, inst);
2236 xsltTextComp(style, inst);
2237 } else if (IS_XSLT_NAME(inst, "sort")) {
2238 xsltCheckParentElement(style, inst, BAD_CAST "apply-templates",
2239 BAD_CAST "for-each");
2240 xsltSortComp(style, inst);
2241 } else if (IS_XSLT_NAME(inst, "comment")) {
2242 xsltCheckInstructionElement(style, inst);
2243 xsltCommentComp(style, inst);
2244 } else if (IS_XSLT_NAME(inst, "number")) {
2245 xsltCheckInstructionElement(style, inst);
2246 xsltNumberComp(style, inst);
2247 } else if (IS_XSLT_NAME(inst, "processing-instruction")) {
2248 xsltCheckInstructionElement(style, inst);
2249 xsltProcessingInstructionComp(style, inst);
2250 } else if (IS_XSLT_NAME(inst, "call-template")) {
2251 xsltCheckInstructionElement(style, inst);
2252 xsltCallTemplateComp(style, inst);
2253 } else if (IS_XSLT_NAME(inst, "param")) {
2254 if (xsltCheckTopLevelElement(style, inst, 0) == 0)
2255 xsltCheckInstructionElement(style, inst);
2256 xsltParamComp(style, inst);
2257 } else if (IS_XSLT_NAME(inst, "variable")) {
2258 if (xsltCheckTopLevelElement(style, inst, 0) == 0)
2259 xsltCheckInstructionElement(style, inst);
2260 xsltVariableComp(style, inst);
2261 } else if (IS_XSLT_NAME(inst, "otherwise")) {
2262 xsltCheckParentElement(style, inst, BAD_CAST "choose", NULL);
2263 xsltCheckInstructionElement(style, inst);
2264 return;
2265 } else if (IS_XSLT_NAME(inst, "template")) {
2266 xsltCheckTopLevelElement(style, inst, 1);
2267 return;
2268 } else if (IS_XSLT_NAME(inst, "output")) {
2269 xsltCheckTopLevelElement(style, inst, 1);
2270 return;
2271 } else if (IS_XSLT_NAME(inst, "preserve-space")) {
2272 xsltCheckTopLevelElement(style, inst, 1);
2273 return;
2274 } else if (IS_XSLT_NAME(inst, "strip-space")) {
2275 xsltCheckTopLevelElement(style, inst, 1);
2276 return;
2277 } else if ((IS_XSLT_NAME(inst, "stylesheet")) ||
2278 (IS_XSLT_NAME(inst, "transform"))) {
2279 xmlNodePtr parent = inst->parent;
2280
2281 if ((parent == NULL) || (parent->type != XML_DOCUMENT_NODE)) {
2282 xsltTransformError(NULL, style, inst,
2283 "element %s only allowed only as root element\n",
2284 inst->name);
2285 style->errors++;
2286 }
2287 return;
2288 } else if (IS_XSLT_NAME(inst, "key")) {
2289 xsltCheckTopLevelElement(style, inst, 1);
2290 return;
2291 } else if (IS_XSLT_NAME(inst, "message")) {
2292 xsltCheckInstructionElement(style, inst);
2293 return;
2294 } else if (IS_XSLT_NAME(inst, "attribute-set")) {
2295 xsltCheckTopLevelElement(style, inst, 1);
2296 return;
2297 } else if (IS_XSLT_NAME(inst, "namespace-alias")) {
2298 xsltCheckTopLevelElement(style, inst, 1);
2299 return;
2300 } else if (IS_XSLT_NAME(inst, "include")) {
2301 xsltCheckTopLevelElement(style, inst, 1);
2302 return;
2303 } else if (IS_XSLT_NAME(inst, "import")) {
2304 xsltCheckTopLevelElement(style, inst, 1);
2305 return;
2306 } else if (IS_XSLT_NAME(inst, "decimal-format")) {
2307 xsltCheckTopLevelElement(style, inst, 1);
2308 return;
2309 } else if (IS_XSLT_NAME(inst, "fallback")) {
2310 xsltCheckInstructionElement(style, inst);
2311 return;
2312 } else if (IS_XSLT_NAME(inst, "document")) {
2313 xsltCheckInstructionElement(style, inst);
2314 inst->psvi = (void *) xsltDocumentComp(style, inst,
2315 (xsltTransformFunction) xsltDocumentElem);
2316 } else {
2317 xsltTransformError(NULL, style, inst,
2318 "xsltStylePreCompute: unknown xsl:%s\n", inst->name);
2319 if (style != NULL) style->warnings++;
2320 }
2321
2322 cur = (xsltStylePreCompPtr) inst->psvi;
2323 /*
2324 * A ns-list is build for every XSLT item in the
2325 * node-tree. This is needed for XPath expressions.
2326 */
2327 if (cur != NULL) {
2328 int i = 0;
2329
2330 cur->nsList = xmlGetNsList(inst->doc, inst);
2331 if (cur->nsList != NULL) {
2332 while (cur->nsList[i] != NULL)
2333 i++;
2334 }
2335 cur->nsNr = i;
2336 }
2337 } else {
2338 inst->psvi =
2339 (void *) xsltPreComputeExtModuleElement(style, inst);
2340
2341 /*
2342 * Unknown element, maybe registered at the context
2343 * level. Mark it for later recognition.
2344 */
2345 if (inst->psvi == NULL)
2346 inst->psvi = (void *) xsltExtMarker;
2347 }
2348 }
2349 #endif /* XSLT_REFACTORED */