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