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