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