Git conversion: Make reactos the root directory, move rosapps, rostests, wallpapers...
[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 #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
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
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
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
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
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
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
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
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 if ((style == NULL) || (cur == NULL))
1398 return;
1399
1400 comp->numdata.doc = cur->doc;
1401 comp->numdata.node = cur;
1402 comp->numdata.value = xsltGetCNsProp(style, cur, (const xmlChar *)"value",
1403 XSLT_NAMESPACE);
1404
1405 prop = xsltEvalStaticAttrValueTemplate(style, cur,
1406 (const xmlChar *)"format",
1407 XSLT_NAMESPACE, &comp->numdata.has_format);
1408 if (comp->numdata.has_format == 0) {
1409 comp->numdata.format = xmlDictLookup(style->dict, BAD_CAST "" , 0);
1410 } else {
1411 comp->numdata.format = prop;
1412 }
1413
1414 comp->numdata.count = xsltGetCNsProp(style, cur, (const xmlChar *)"count",
1415 XSLT_NAMESPACE);
1416 comp->numdata.from = xsltGetCNsProp(style, cur, (const xmlChar *)"from",
1417 XSLT_NAMESPACE);
1418
1419 prop = xsltGetCNsProp(style, cur, (const xmlChar *)"count", XSLT_NAMESPACE);
1420 if (prop != NULL) {
1421 comp->numdata.countPat = xsltCompilePattern(prop, cur->doc, cur, style,
1422 NULL);
1423 }
1424
1425 prop = xsltGetCNsProp(style, cur, (const xmlChar *)"from", XSLT_NAMESPACE);
1426 if (prop != NULL) {
1427 comp->numdata.fromPat = xsltCompilePattern(prop, cur->doc, cur, style,
1428 NULL);
1429 }
1430
1431 prop = xsltGetCNsProp(style, cur, (const xmlChar *)"level", XSLT_NAMESPACE);
1432 if (prop != NULL) {
1433 if (xmlStrEqual(prop, BAD_CAST("single")) ||
1434 xmlStrEqual(prop, BAD_CAST("multiple")) ||
1435 xmlStrEqual(prop, BAD_CAST("any"))) {
1436 comp->numdata.level = prop;
1437 } else {
1438 xsltTransformError(NULL, style, cur,
1439 "xsl:number : invalid value %s for level\n", prop);
1440 if (style != NULL) style->warnings++;
1441 }
1442 }
1443
1444 prop = xsltGetCNsProp(style, cur, (const xmlChar *)"lang", XSLT_NAMESPACE);
1445 if (prop != NULL) {
1446 xsltTransformError(NULL, style, cur,
1447 "xsl:number : lang attribute not implemented\n");
1448 XSLT_TODO; /* xsl:number lang attribute */
1449 }
1450
1451 prop = xsltGetCNsProp(style, cur, (const xmlChar *)"letter-value", XSLT_NAMESPACE);
1452 if (prop != NULL) {
1453 if (xmlStrEqual(prop, BAD_CAST("alphabetic"))) {
1454 xsltTransformError(NULL, style, cur,
1455 "xsl:number : letter-value 'alphabetic' not implemented\n");
1456 if (style != NULL) style->warnings++;
1457 XSLT_TODO; /* xsl:number letter-value attribute alphabetic */
1458 } else if (xmlStrEqual(prop, BAD_CAST("traditional"))) {
1459 xsltTransformError(NULL, style, cur,
1460 "xsl:number : letter-value 'traditional' not implemented\n");
1461 if (style != NULL) style->warnings++;
1462 XSLT_TODO; /* xsl:number letter-value attribute traditional */
1463 } else {
1464 xsltTransformError(NULL, style, cur,
1465 "xsl:number : invalid value %s for letter-value\n", prop);
1466 if (style != NULL) style->warnings++;
1467 }
1468 }
1469
1470 prop = xsltGetCNsProp(style, cur, (const xmlChar *)"grouping-separator",
1471 XSLT_NAMESPACE);
1472 if (prop != NULL) {
1473 comp->numdata.groupingCharacterLen = xmlStrlen(prop);
1474 comp->numdata.groupingCharacter =
1475 xsltGetUTF8Char(prop, &(comp->numdata.groupingCharacterLen));
1476 }
1477
1478 prop = xsltGetCNsProp(style, cur, (const xmlChar *)"grouping-size", XSLT_NAMESPACE);
1479 if (prop != NULL) {
1480 sscanf((char *)prop, "%d", &comp->numdata.digitsPerGroup);
1481 } else {
1482 comp->numdata.groupingCharacter = 0;
1483 }
1484
1485 /* Set default values */
1486 if (comp->numdata.value == NULL) {
1487 if (comp->numdata.level == NULL) {
1488 comp->numdata.level = xmlDictLookup(style->dict,
1489 BAD_CAST"single", 6);
1490 }
1491 }
1492
1493 }
1494
1495 /**
1496 * xsltApplyImportsComp:
1497 * @style: an XSLT compiled stylesheet
1498 * @inst: the xslt apply-imports node
1499 *
1500 * Process the xslt apply-imports node on the source node
1501 */
1502 static void
1503 xsltApplyImportsComp(xsltStylesheetPtr style, xmlNodePtr inst) {
1504 #ifdef XSLT_REFACTORED
1505 xsltStyleItemApplyImportsPtr comp;
1506 #else
1507 xsltStylePreCompPtr comp;
1508 #endif
1509
1510 if ((style == NULL) || (inst == NULL) || (inst->type != XML_ELEMENT_NODE))
1511 return;
1512
1513 #ifdef XSLT_REFACTORED
1514 comp = (xsltStyleItemApplyImportsPtr) xsltNewStylePreComp(style, XSLT_FUNC_APPLYIMPORTS);
1515 #else
1516 comp = xsltNewStylePreComp(style, XSLT_FUNC_APPLYIMPORTS);
1517 #endif
1518
1519 if (comp == NULL)
1520 return;
1521 inst->psvi = comp;
1522 comp->inst = inst;
1523 }
1524
1525 /**
1526 * xsltCallTemplateComp:
1527 * @style: an XSLT compiled stylesheet
1528 * @inst: the xslt call-template node
1529 *
1530 * Process the xslt call-template node on the source node
1531 */
1532 static void
1533 xsltCallTemplateComp(xsltStylesheetPtr style, xmlNodePtr inst) {
1534 #ifdef XSLT_REFACTORED
1535 xsltStyleItemCallTemplatePtr comp;
1536 #else
1537 xsltStylePreCompPtr comp;
1538 #endif
1539
1540 if ((style == NULL) || (inst == NULL) || (inst->type != XML_ELEMENT_NODE))
1541 return;
1542
1543 #ifdef XSLT_REFACTORED
1544 comp = (xsltStyleItemCallTemplatePtr)
1545 xsltNewStylePreComp(style, XSLT_FUNC_CALLTEMPLATE);
1546 #else
1547 comp = xsltNewStylePreComp(style, XSLT_FUNC_CALLTEMPLATE);
1548 #endif
1549
1550 if (comp == NULL)
1551 return;
1552 inst->psvi = comp;
1553 comp->inst = inst;
1554
1555 /*
1556 * Attribute "name".
1557 */
1558 xsltGetQNameProperty(style, inst, BAD_CAST "name",
1559 1, &(comp->has_name), &(comp->ns), &(comp->name));
1560 if (comp->ns)
1561 comp->has_ns = 1;
1562 }
1563
1564 /**
1565 * xsltApplyTemplatesComp:
1566 * @style: an XSLT compiled stylesheet
1567 * @inst: the apply-templates node
1568 *
1569 * Process the apply-templates node on the source node
1570 */
1571 static void
1572 xsltApplyTemplatesComp(xsltStylesheetPtr style, xmlNodePtr inst) {
1573 #ifdef XSLT_REFACTORED
1574 xsltStyleItemApplyTemplatesPtr comp;
1575 #else
1576 xsltStylePreCompPtr comp;
1577 #endif
1578
1579 if ((style == NULL) || (inst == NULL) || (inst->type != XML_ELEMENT_NODE))
1580 return;
1581
1582 #ifdef XSLT_REFACTORED
1583 comp = (xsltStyleItemApplyTemplatesPtr)
1584 xsltNewStylePreComp(style, XSLT_FUNC_APPLYTEMPLATES);
1585 #else
1586 comp = xsltNewStylePreComp(style, XSLT_FUNC_APPLYTEMPLATES);
1587 #endif
1588
1589 if (comp == NULL)
1590 return;
1591 inst->psvi = comp;
1592 comp->inst = inst;
1593
1594 /*
1595 * Attribute "mode".
1596 */
1597 xsltGetQNameProperty(style, inst, BAD_CAST "mode",
1598 0, NULL, &(comp->modeURI), &(comp->mode));
1599 /*
1600 * Attribute "select".
1601 */
1602 comp->select = xsltGetCNsProp(style, inst, BAD_CAST "select",
1603 XSLT_NAMESPACE);
1604 if (comp->select != NULL) {
1605 comp->comp = xsltXPathCompile(style, comp->select);
1606 if (comp->comp == NULL) {
1607 xsltTransformError(NULL, style, inst,
1608 "XSLT-apply-templates: could not compile select "
1609 "expression '%s'\n", comp->select);
1610 style->errors++;
1611 }
1612 }
1613 /* TODO: handle (or skip) the xsl:sort and xsl:with-param */
1614 }
1615
1616 /**
1617 * xsltChooseComp:
1618 * @style: an XSLT compiled stylesheet
1619 * @inst: the xslt choose node
1620 *
1621 * Process the xslt choose node on the source node
1622 */
1623 static void
1624 xsltChooseComp(xsltStylesheetPtr style, xmlNodePtr inst) {
1625 #ifdef XSLT_REFACTORED
1626 xsltStyleItemChoosePtr comp;
1627 #else
1628 xsltStylePreCompPtr comp;
1629 #endif
1630
1631 if ((style == NULL) || (inst == NULL) || (inst->type != XML_ELEMENT_NODE))
1632 return;
1633
1634 #ifdef XSLT_REFACTORED
1635 comp = (xsltStyleItemChoosePtr)
1636 xsltNewStylePreComp(style, XSLT_FUNC_CHOOSE);
1637 #else
1638 comp = xsltNewStylePreComp(style, XSLT_FUNC_CHOOSE);
1639 #endif
1640
1641 if (comp == NULL)
1642 return;
1643 inst->psvi = comp;
1644 comp->inst = inst;
1645 }
1646
1647 /**
1648 * xsltIfComp:
1649 * @style: an XSLT compiled stylesheet
1650 * @inst: the xslt if node
1651 *
1652 * Process the xslt if node on the source node
1653 */
1654 static void
1655 xsltIfComp(xsltStylesheetPtr style, xmlNodePtr inst) {
1656 #ifdef XSLT_REFACTORED
1657 xsltStyleItemIfPtr comp;
1658 #else
1659 xsltStylePreCompPtr comp;
1660 #endif
1661
1662 if ((style == NULL) || (inst == NULL) || (inst->type != XML_ELEMENT_NODE))
1663 return;
1664
1665 #ifdef XSLT_REFACTORED
1666 comp = (xsltStyleItemIfPtr)
1667 xsltNewStylePreComp(style, XSLT_FUNC_IF);
1668 #else
1669 comp = xsltNewStylePreComp(style, XSLT_FUNC_IF);
1670 #endif
1671
1672 if (comp == NULL)
1673 return;
1674 inst->psvi = comp;
1675 comp->inst = inst;
1676
1677 comp->test = xsltGetCNsProp(style, inst, (const xmlChar *)"test", XSLT_NAMESPACE);
1678 if (comp->test == NULL) {
1679 xsltTransformError(NULL, style, inst,
1680 "xsl:if : test is not defined\n");
1681 if (style != NULL) style->errors++;
1682 return;
1683 }
1684 comp->comp = xsltXPathCompile(style, comp->test);
1685 if (comp->comp == NULL) {
1686 xsltTransformError(NULL, style, inst,
1687 "xsl:if : could not compile test expression '%s'\n",
1688 comp->test);
1689 if (style != NULL) style->errors++;
1690 }
1691 }
1692
1693 /**
1694 * xsltWhenComp:
1695 * @style: an XSLT compiled stylesheet
1696 * @inst: the xslt if node
1697 *
1698 * Process the xslt if node on the source node
1699 */
1700 static void
1701 xsltWhenComp(xsltStylesheetPtr style, xmlNodePtr inst) {
1702 #ifdef XSLT_REFACTORED
1703 xsltStyleItemWhenPtr comp;
1704 #else
1705 xsltStylePreCompPtr comp;
1706 #endif
1707
1708 if ((style == NULL) || (inst == NULL) || (inst->type != XML_ELEMENT_NODE))
1709 return;
1710
1711 #ifdef XSLT_REFACTORED
1712 comp = (xsltStyleItemWhenPtr)
1713 xsltNewStylePreComp(style, XSLT_FUNC_WHEN);
1714 #else
1715 comp = xsltNewStylePreComp(style, XSLT_FUNC_WHEN);
1716 #endif
1717
1718 if (comp == NULL)
1719 return;
1720 inst->psvi = comp;
1721 comp->inst = inst;
1722
1723 comp->test = xsltGetCNsProp(style, inst, (const xmlChar *)"test", XSLT_NAMESPACE);
1724 if (comp->test == NULL) {
1725 xsltTransformError(NULL, style, inst,
1726 "xsl:when : test is not defined\n");
1727 if (style != NULL) style->errors++;
1728 return;
1729 }
1730 comp->comp = xsltXPathCompile(style, comp->test);
1731 if (comp->comp == NULL) {
1732 xsltTransformError(NULL, style, inst,
1733 "xsl:when : could not compile test expression '%s'\n",
1734 comp->test);
1735 if (style != NULL) style->errors++;
1736 }
1737 }
1738
1739 /**
1740 * xsltForEachComp:
1741 * @style: an XSLT compiled stylesheet
1742 * @inst: the xslt for-each node
1743 *
1744 * Process the xslt for-each node on the source node
1745 */
1746 static void
1747 xsltForEachComp(xsltStylesheetPtr style, xmlNodePtr inst) {
1748 #ifdef XSLT_REFACTORED
1749 xsltStyleItemForEachPtr comp;
1750 #else
1751 xsltStylePreCompPtr comp;
1752 #endif
1753
1754 if ((style == NULL) || (inst == NULL) || (inst->type != XML_ELEMENT_NODE))
1755 return;
1756
1757 #ifdef XSLT_REFACTORED
1758 comp = (xsltStyleItemForEachPtr)
1759 xsltNewStylePreComp(style, XSLT_FUNC_FOREACH);
1760 #else
1761 comp = xsltNewStylePreComp(style, XSLT_FUNC_FOREACH);
1762 #endif
1763
1764 if (comp == NULL)
1765 return;
1766 inst->psvi = comp;
1767 comp->inst = inst;
1768
1769 comp->select = xsltGetCNsProp(style, inst, (const xmlChar *)"select",
1770 XSLT_NAMESPACE);
1771 if (comp->select == NULL) {
1772 xsltTransformError(NULL, style, inst,
1773 "xsl:for-each : select is missing\n");
1774 if (style != NULL) style->errors++;
1775 } else {
1776 comp->comp = xsltXPathCompile(style, comp->select);
1777 if (comp->comp == NULL) {
1778 xsltTransformError(NULL, style, inst,
1779 "xsl:for-each : could not compile select expression '%s'\n",
1780 comp->select);
1781 if (style != NULL) style->errors++;
1782 }
1783 }
1784 /* TODO: handle and skip the xsl:sort */
1785 }
1786
1787 /**
1788 * xsltVariableComp:
1789 * @style: an XSLT compiled stylesheet
1790 * @inst: the xslt variable node
1791 *
1792 * Process the xslt variable node on the source node
1793 */
1794 static void
1795 xsltVariableComp(xsltStylesheetPtr style, xmlNodePtr inst) {
1796 #ifdef XSLT_REFACTORED
1797 xsltStyleItemVariablePtr comp;
1798 #else
1799 xsltStylePreCompPtr comp;
1800 #endif
1801
1802 if ((style == NULL) || (inst == NULL) || (inst->type != XML_ELEMENT_NODE))
1803 return;
1804
1805 #ifdef XSLT_REFACTORED
1806 comp = (xsltStyleItemVariablePtr)
1807 xsltNewStylePreComp(style, XSLT_FUNC_VARIABLE);
1808 #else
1809 comp = xsltNewStylePreComp(style, XSLT_FUNC_VARIABLE);
1810 #endif
1811
1812 if (comp == NULL)
1813 return;
1814
1815 inst->psvi = comp;
1816 comp->inst = inst;
1817 /*
1818 * The full template resolution can be done statically
1819 */
1820
1821 /*
1822 * Attribute "name".
1823 */
1824 xsltGetQNameProperty(style, inst, BAD_CAST "name",
1825 1, &(comp->has_name), &(comp->ns), &(comp->name));
1826 if (comp->ns)
1827 comp->has_ns = 1;
1828 /*
1829 * Attribute "select".
1830 */
1831 comp->select = xsltGetCNsProp(style, inst, (const xmlChar *)"select",
1832 XSLT_NAMESPACE);
1833 if (comp->select != NULL) {
1834 #ifndef XSLT_REFACTORED
1835 xmlNodePtr cur;
1836 #endif
1837 comp->comp = xsltXPathCompile(style, comp->select);
1838 if (comp->comp == NULL) {
1839 xsltTransformError(NULL, style, inst,
1840 "XSLT-variable: Failed to compile the XPath expression '%s'.\n",
1841 comp->select);
1842 style->errors++;
1843 }
1844 #ifdef XSLT_REFACTORED
1845 if (inst->children != NULL) {
1846 xsltTransformError(NULL, style, inst,
1847 "XSLT-variable: There must be no child nodes, since the "
1848 "attribute 'select' was specified.\n");
1849 style->errors++;
1850 }
1851 #else
1852 for (cur = inst->children; cur != NULL; cur = cur->next) {
1853 if (cur->type != XML_COMMENT_NODE &&
1854 (cur->type != XML_TEXT_NODE || !xsltIsBlank(cur->content)))
1855 {
1856 xsltTransformError(NULL, style, inst,
1857 "XSLT-variable: There must be no child nodes, since the "
1858 "attribute 'select' was specified.\n");
1859 style->errors++;
1860 }
1861 }
1862 #endif
1863 }
1864 }
1865
1866 /**
1867 * xsltParamComp:
1868 * @style: an XSLT compiled stylesheet
1869 * @inst: the xslt param node
1870 *
1871 * Process the xslt param node on the source node
1872 */
1873 static void
1874 xsltParamComp(xsltStylesheetPtr style, xmlNodePtr inst) {
1875 #ifdef XSLT_REFACTORED
1876 xsltStyleItemParamPtr comp;
1877 #else
1878 xsltStylePreCompPtr comp;
1879 #endif
1880
1881 if ((style == NULL) || (inst == NULL) || (inst->type != XML_ELEMENT_NODE))
1882 return;
1883
1884 #ifdef XSLT_REFACTORED
1885 comp = (xsltStyleItemParamPtr)
1886 xsltNewStylePreComp(style, XSLT_FUNC_PARAM);
1887 #else
1888 comp = xsltNewStylePreComp(style, XSLT_FUNC_PARAM);
1889 #endif
1890
1891 if (comp == NULL)
1892 return;
1893 inst->psvi = comp;
1894 comp->inst = inst;
1895
1896 /*
1897 * Attribute "name".
1898 */
1899 xsltGetQNameProperty(style, inst, BAD_CAST "name",
1900 1, &(comp->has_name), &(comp->ns), &(comp->name));
1901 if (comp->ns)
1902 comp->has_ns = 1;
1903 /*
1904 * Attribute "select".
1905 */
1906 comp->select = xsltGetCNsProp(style, inst, (const xmlChar *)"select",
1907 XSLT_NAMESPACE);
1908 if (comp->select != NULL) {
1909 comp->comp = xsltXPathCompile(style, comp->select);
1910 if (comp->comp == NULL) {
1911 xsltTransformError(NULL, style, inst,
1912 "XSLT-param: could not compile select expression '%s'.\n",
1913 comp->select);
1914 style->errors++;
1915 }
1916 if (inst->children != NULL) {
1917 xsltTransformError(NULL, style, inst,
1918 "XSLT-param: The content should be empty since the "
1919 "attribute 'select' is present.\n");
1920 style->warnings++;
1921 }
1922 }
1923 }
1924
1925 /************************************************************************
1926 * *
1927 * Generic interface *
1928 * *
1929 ************************************************************************/
1930
1931 /**
1932 * xsltFreeStylePreComps:
1933 * @style: an XSLT transformation context
1934 *
1935 * Free up the memory allocated by all precomputed blocks
1936 */
1937 void
1938 xsltFreeStylePreComps(xsltStylesheetPtr style) {
1939 xsltElemPreCompPtr cur, next;
1940
1941 if (style == NULL)
1942 return;
1943
1944 cur = style->preComps;
1945 while (cur != NULL) {
1946 next = cur->next;
1947 if (cur->type == XSLT_FUNC_EXTENSION)
1948 cur->free(cur);
1949 else
1950 xsltFreeStylePreComp((xsltStylePreCompPtr) cur);
1951 cur = next;
1952 }
1953 }
1954
1955 #ifdef XSLT_REFACTORED
1956
1957 /**
1958 * xsltStylePreCompute:
1959 * @style: the XSLT stylesheet
1960 * @node: the element in the XSLT namespace
1961 *
1962 * Precompute an XSLT element.
1963 * This expects the type of the element to be already
1964 * set in style->compCtxt->inode->type;
1965 */
1966 void
1967 xsltStylePreCompute(xsltStylesheetPtr style, xmlNodePtr node) {
1968 /*
1969 * The xsltXSLTElemMarker marker was set beforehand by
1970 * the parsing mechanism for all elements in the XSLT namespace.
1971 */
1972 if (style == NULL) {
1973 if ((node != NULL) && (node->type == XML_ELEMENT_NODE))
1974 node->psvi = NULL;
1975 return;
1976 }
1977 if (node == NULL)
1978 return;
1979 if (! IS_XSLT_ELEM_FAST(node))
1980 return;
1981
1982 node->psvi = NULL;
1983 if (XSLT_CCTXT(style)->inode->type != 0) {
1984 switch (XSLT_CCTXT(style)->inode->type) {
1985 case XSLT_FUNC_APPLYTEMPLATES:
1986 xsltApplyTemplatesComp(style, node);
1987 break;
1988 case XSLT_FUNC_WITHPARAM:
1989 xsltWithParamComp(style, node);
1990 break;
1991 case XSLT_FUNC_VALUEOF:
1992 xsltValueOfComp(style, node);
1993 break;
1994 case XSLT_FUNC_COPY:
1995 xsltCopyComp(style, node);
1996 break;
1997 case XSLT_FUNC_COPYOF:
1998 xsltCopyOfComp(style, node);
1999 break;
2000 case XSLT_FUNC_IF:
2001 xsltIfComp(style, node);
2002 break;
2003 case XSLT_FUNC_CHOOSE:
2004 xsltChooseComp(style, node);
2005 break;
2006 case XSLT_FUNC_WHEN:
2007 xsltWhenComp(style, node);
2008 break;
2009 case XSLT_FUNC_OTHERWISE:
2010 /* NOP yet */
2011 return;
2012 case XSLT_FUNC_FOREACH:
2013 xsltForEachComp(style, node);
2014 break;
2015 case XSLT_FUNC_APPLYIMPORTS:
2016 xsltApplyImportsComp(style, node);
2017 break;
2018 case XSLT_FUNC_ATTRIBUTE:
2019 xsltAttributeComp(style, node);
2020 break;
2021 case XSLT_FUNC_ELEMENT:
2022 xsltElementComp(style, node);
2023 break;
2024 case XSLT_FUNC_SORT:
2025 xsltSortComp(style, node);
2026 break;
2027 case XSLT_FUNC_COMMENT:
2028 xsltCommentComp(style, node);
2029 break;
2030 case XSLT_FUNC_NUMBER:
2031 xsltNumberComp(style, node);
2032 break;
2033 case XSLT_FUNC_PI:
2034 xsltProcessingInstructionComp(style, node);
2035 break;
2036 case XSLT_FUNC_CALLTEMPLATE:
2037 xsltCallTemplateComp(style, node);
2038 break;
2039 case XSLT_FUNC_PARAM:
2040 xsltParamComp(style, node);
2041 break;
2042 case XSLT_FUNC_VARIABLE:
2043 xsltVariableComp(style, node);
2044 break;
2045 case XSLT_FUNC_FALLBACK:
2046 /* NOP yet */
2047 return;
2048 case XSLT_FUNC_DOCUMENT:
2049 /* The extra one */
2050 node->psvi = (void *) xsltDocumentComp(style, node,
2051 (xsltTransformFunction) xsltDocumentElem);
2052 break;
2053 case XSLT_FUNC_MESSAGE:
2054 /* NOP yet */
2055 return;
2056 default:
2057 /*
2058 * NOTE that xsl:text, xsl:template, xsl:stylesheet,
2059 * xsl:transform, xsl:import, xsl:include are not expected
2060 * to be handed over to this function.
2061 */
2062 xsltTransformError(NULL, style, node,
2063 "Internal error: (xsltStylePreCompute) cannot handle "
2064 "the XSLT element '%s'.\n", node->name);
2065 style->errors++;
2066 return;
2067 }
2068 } else {
2069 /*
2070 * Fallback to string comparison.
2071 */
2072 if (IS_XSLT_NAME(node, "apply-templates")) {
2073 xsltApplyTemplatesComp(style, node);
2074 } else if (IS_XSLT_NAME(node, "with-param")) {
2075 xsltWithParamComp(style, node);
2076 } else if (IS_XSLT_NAME(node, "value-of")) {
2077 xsltValueOfComp(style, node);
2078 } else if (IS_XSLT_NAME(node, "copy")) {
2079 xsltCopyComp(style, node);
2080 } else if (IS_XSLT_NAME(node, "copy-of")) {
2081 xsltCopyOfComp(style, node);
2082 } else if (IS_XSLT_NAME(node, "if")) {
2083 xsltIfComp(style, node);
2084 } else if (IS_XSLT_NAME(node, "choose")) {
2085 xsltChooseComp(style, node);
2086 } else if (IS_XSLT_NAME(node, "when")) {
2087 xsltWhenComp(style, node);
2088 } else if (IS_XSLT_NAME(node, "otherwise")) {
2089 /* NOP yet */
2090 return;
2091 } else if (IS_XSLT_NAME(node, "for-each")) {
2092 xsltForEachComp(style, node);
2093 } else if (IS_XSLT_NAME(node, "apply-imports")) {
2094 xsltApplyImportsComp(style, node);
2095 } else if (IS_XSLT_NAME(node, "attribute")) {
2096 xsltAttributeComp(style, node);
2097 } else if (IS_XSLT_NAME(node, "element")) {
2098 xsltElementComp(style, node);
2099 } else if (IS_XSLT_NAME(node, "sort")) {
2100 xsltSortComp(style, node);
2101 } else if (IS_XSLT_NAME(node, "comment")) {
2102 xsltCommentComp(style, node);
2103 } else if (IS_XSLT_NAME(node, "number")) {
2104 xsltNumberComp(style, node);
2105 } else if (IS_XSLT_NAME(node, "processing-instruction")) {
2106 xsltProcessingInstructionComp(style, node);
2107 } else if (IS_XSLT_NAME(node, "call-template")) {
2108 xsltCallTemplateComp(style, node);
2109 } else if (IS_XSLT_NAME(node, "param")) {
2110 xsltParamComp(style, node);
2111 } else if (IS_XSLT_NAME(node, "variable")) {
2112 xsltVariableComp(style, node);
2113 } else if (IS_XSLT_NAME(node, "fallback")) {
2114 /* NOP yet */
2115 return;
2116 } else if (IS_XSLT_NAME(node, "document")) {
2117 /* The extra one */
2118 node->psvi = (void *) xsltDocumentComp(style, node,
2119 (xsltTransformFunction) xsltDocumentElem);
2120 } else if (IS_XSLT_NAME(node, "output")) {
2121 /* Top-level */
2122 return;
2123 } else if (IS_XSLT_NAME(node, "preserve-space")) {
2124 /* Top-level */
2125 return;
2126 } else if (IS_XSLT_NAME(node, "strip-space")) {
2127 /* Top-level */
2128 return;
2129 } else if (IS_XSLT_NAME(node, "key")) {
2130 /* Top-level */
2131 return;
2132 } else if (IS_XSLT_NAME(node, "message")) {
2133 return;
2134 } else if (IS_XSLT_NAME(node, "attribute-set")) {
2135 /* Top-level */
2136 return;
2137 } else if (IS_XSLT_NAME(node, "namespace-alias")) {
2138 /* Top-level */
2139 return;
2140 } else if (IS_XSLT_NAME(node, "decimal-format")) {
2141 /* Top-level */
2142 return;
2143 } else if (IS_XSLT_NAME(node, "include")) {
2144 /* Top-level */
2145 } else {
2146 /*
2147 * NOTE that xsl:text, xsl:template, xsl:stylesheet,
2148 * xsl:transform, xsl:import, xsl:include are not expected
2149 * to be handed over to this function.
2150 */
2151 xsltTransformError(NULL, style, node,
2152 "Internal error: (xsltStylePreCompute) cannot handle "
2153 "the XSLT element '%s'.\n", node->name);
2154 style->errors++;
2155 return;
2156 }
2157 }
2158 /*
2159 * Assign the current list of in-scope namespaces to the
2160 * item. This is needed for XPath expressions.
2161 */
2162 if (node->psvi != NULL) {
2163 ((xsltStylePreCompPtr) node->psvi)->inScopeNs =
2164 XSLT_CCTXT(style)->inode->inScopeNs;
2165 }
2166 }
2167
2168 #else
2169
2170 /**
2171 * xsltStylePreCompute:
2172 * @style: the XSLT stylesheet
2173 * @inst: the instruction in the stylesheet
2174 *
2175 * Precompute an XSLT stylesheet element
2176 */
2177 void
2178 xsltStylePreCompute(xsltStylesheetPtr style, xmlNodePtr inst) {
2179 /*
2180 * URGENT TODO: Normally inst->psvi Should never be reserved here,
2181 * BUT: since if we include the same stylesheet from
2182 * multiple imports, then the stylesheet will be parsed
2183 * again. We simply must not try to compute the stylesheet again.
2184 * TODO: Get to the point where we don't need to query the
2185 * namespace- and local-name of the node, but can evaluate this
2186 * using cctxt->style->inode->category;
2187 */
2188 if ((inst == NULL) || (inst->type != XML_ELEMENT_NODE) ||
2189 (inst->psvi != NULL))
2190 return;
2191
2192 if (IS_XSLT_ELEM(inst)) {
2193 xsltStylePreCompPtr cur;
2194
2195 if (IS_XSLT_NAME(inst, "apply-templates")) {
2196 xsltCheckInstructionElement(style, inst);
2197 xsltApplyTemplatesComp(style, inst);
2198 } else if (IS_XSLT_NAME(inst, "with-param")) {
2199 xsltCheckParentElement(style, inst, BAD_CAST "apply-templates",
2200 BAD_CAST "call-template");
2201 xsltWithParamComp(style, inst);
2202 } else if (IS_XSLT_NAME(inst, "value-of")) {
2203 xsltCheckInstructionElement(style, inst);
2204 xsltValueOfComp(style, inst);
2205 } else if (IS_XSLT_NAME(inst, "copy")) {
2206 xsltCheckInstructionElement(style, inst);
2207 xsltCopyComp(style, inst);
2208 } else if (IS_XSLT_NAME(inst, "copy-of")) {
2209 xsltCheckInstructionElement(style, inst);
2210 xsltCopyOfComp(style, inst);
2211 } else if (IS_XSLT_NAME(inst, "if")) {
2212 xsltCheckInstructionElement(style, inst);
2213 xsltIfComp(style, inst);
2214 } else if (IS_XSLT_NAME(inst, "when")) {
2215 xsltCheckParentElement(style, inst, BAD_CAST "choose", NULL);
2216 xsltWhenComp(style, inst);
2217 } else if (IS_XSLT_NAME(inst, "choose")) {
2218 xsltCheckInstructionElement(style, inst);
2219 xsltChooseComp(style, inst);
2220 } else if (IS_XSLT_NAME(inst, "for-each")) {
2221 xsltCheckInstructionElement(style, inst);
2222 xsltForEachComp(style, inst);
2223 } else if (IS_XSLT_NAME(inst, "apply-imports")) {
2224 xsltCheckInstructionElement(style, inst);
2225 xsltApplyImportsComp(style, inst);
2226 } else if (IS_XSLT_NAME(inst, "attribute")) {
2227 xmlNodePtr parent = inst->parent;
2228
2229 if ((parent == NULL) ||
2230 (parent->type != XML_ELEMENT_NODE) || (parent->ns == NULL) ||
2231 ((parent->ns != inst->ns) &&
2232 (!xmlStrEqual(parent->ns->href, inst->ns->href))) ||
2233 (!xmlStrEqual(parent->name, BAD_CAST "attribute-set"))) {
2234 xsltCheckInstructionElement(style, inst);
2235 }
2236 xsltAttributeComp(style, inst);
2237 } else if (IS_XSLT_NAME(inst, "element")) {
2238 xsltCheckInstructionElement(style, inst);
2239 xsltElementComp(style, inst);
2240 } else if (IS_XSLT_NAME(inst, "text")) {
2241 xsltCheckInstructionElement(style, inst);
2242 xsltTextComp(style, inst);
2243 } else if (IS_XSLT_NAME(inst, "sort")) {
2244 xsltCheckParentElement(style, inst, BAD_CAST "apply-templates",
2245 BAD_CAST "for-each");
2246 xsltSortComp(style, inst);
2247 } else if (IS_XSLT_NAME(inst, "comment")) {
2248 xsltCheckInstructionElement(style, inst);
2249 xsltCommentComp(style, inst);
2250 } else if (IS_XSLT_NAME(inst, "number")) {
2251 xsltCheckInstructionElement(style, inst);
2252 xsltNumberComp(style, inst);
2253 } else if (IS_XSLT_NAME(inst, "processing-instruction")) {
2254 xsltCheckInstructionElement(style, inst);
2255 xsltProcessingInstructionComp(style, inst);
2256 } else if (IS_XSLT_NAME(inst, "call-template")) {
2257 xsltCheckInstructionElement(style, inst);
2258 xsltCallTemplateComp(style, inst);
2259 } else if (IS_XSLT_NAME(inst, "param")) {
2260 if (xsltCheckTopLevelElement(style, inst, 0) == 0)
2261 xsltCheckInstructionElement(style, inst);
2262 xsltParamComp(style, inst);
2263 } else if (IS_XSLT_NAME(inst, "variable")) {
2264 if (xsltCheckTopLevelElement(style, inst, 0) == 0)
2265 xsltCheckInstructionElement(style, inst);
2266 xsltVariableComp(style, inst);
2267 } else if (IS_XSLT_NAME(inst, "otherwise")) {
2268 xsltCheckParentElement(style, inst, BAD_CAST "choose", NULL);
2269 xsltCheckInstructionElement(style, inst);
2270 return;
2271 } else if (IS_XSLT_NAME(inst, "template")) {
2272 xsltCheckTopLevelElement(style, inst, 1);
2273 return;
2274 } else if (IS_XSLT_NAME(inst, "output")) {
2275 xsltCheckTopLevelElement(style, inst, 1);
2276 return;
2277 } else if (IS_XSLT_NAME(inst, "preserve-space")) {
2278 xsltCheckTopLevelElement(style, inst, 1);
2279 return;
2280 } else if (IS_XSLT_NAME(inst, "strip-space")) {
2281 xsltCheckTopLevelElement(style, inst, 1);
2282 return;
2283 } else if ((IS_XSLT_NAME(inst, "stylesheet")) ||
2284 (IS_XSLT_NAME(inst, "transform"))) {
2285 xmlNodePtr parent = inst->parent;
2286
2287 if ((parent == NULL) || (parent->type != XML_DOCUMENT_NODE)) {
2288 xsltTransformError(NULL, style, inst,
2289 "element %s only allowed only as root element\n",
2290 inst->name);
2291 style->errors++;
2292 }
2293 return;
2294 } else if (IS_XSLT_NAME(inst, "key")) {
2295 xsltCheckTopLevelElement(style, inst, 1);
2296 return;
2297 } else if (IS_XSLT_NAME(inst, "message")) {
2298 xsltCheckInstructionElement(style, inst);
2299 return;
2300 } else if (IS_XSLT_NAME(inst, "attribute-set")) {
2301 xsltCheckTopLevelElement(style, inst, 1);
2302 return;
2303 } else if (IS_XSLT_NAME(inst, "namespace-alias")) {
2304 xsltCheckTopLevelElement(style, inst, 1);
2305 return;
2306 } else if (IS_XSLT_NAME(inst, "include")) {
2307 xsltCheckTopLevelElement(style, inst, 1);
2308 return;
2309 } else if (IS_XSLT_NAME(inst, "import")) {
2310 xsltCheckTopLevelElement(style, inst, 1);
2311 return;
2312 } else if (IS_XSLT_NAME(inst, "decimal-format")) {
2313 xsltCheckTopLevelElement(style, inst, 1);
2314 return;
2315 } else if (IS_XSLT_NAME(inst, "fallback")) {
2316 xsltCheckInstructionElement(style, inst);
2317 return;
2318 } else if (IS_XSLT_NAME(inst, "document")) {
2319 xsltCheckInstructionElement(style, inst);
2320 inst->psvi = (void *) xsltDocumentComp(style, inst,
2321 (xsltTransformFunction) xsltDocumentElem);
2322 } else {
2323 xsltTransformError(NULL, style, inst,
2324 "xsltStylePreCompute: unknown xsl:%s\n", inst->name);
2325 if (style != NULL) style->warnings++;
2326 }
2327
2328 cur = (xsltStylePreCompPtr) inst->psvi;
2329 /*
2330 * A ns-list is build for every XSLT item in the
2331 * node-tree. This is needed for XPath expressions.
2332 */
2333 if (cur != NULL) {
2334 int i = 0;
2335
2336 cur->nsList = xmlGetNsList(inst->doc, inst);
2337 if (cur->nsList != NULL) {
2338 while (cur->nsList[i] != NULL)
2339 i++;
2340 }
2341 cur->nsNr = i;
2342 }
2343 } else {
2344 inst->psvi =
2345 (void *) xsltPreComputeExtModuleElement(style, inst);
2346
2347 /*
2348 * Unknown element, maybe registered at the context
2349 * level. Mark it for later recognition.
2350 */
2351 if (inst->psvi == NULL)
2352 inst->psvi = (void *) xsltExtMarker;
2353 }
2354 }
2355 #endif /* XSLT_REFACTORED */