/src/libxslt/libxslt/xslt.c
Line  | Count  | Source (jump to first uncovered line)  | 
1  |  | /*  | 
2  |  |  * xslt.c: Implemetation of an XSL Transformation 1.0 engine  | 
3  |  |  *  | 
4  |  |  * Reference:  | 
5  |  |  *   XSLT specification  | 
6  |  |  *   http://www.w3.org/TR/1999/REC-xslt-19991116  | 
7  |  |  *  | 
8  |  |  *   Associating Style Sheets with XML documents  | 
9  |  |  *   http://www.w3.org/1999/06/REC-xml-stylesheet-19990629  | 
10  |  |  *  | 
11  |  |  * See Copyright for the status of this software.  | 
12  |  |  *  | 
13  |  |  * daniel@veillard.com  | 
14  |  |  */  | 
15  |  |  | 
16  |  | #define IN_LIBXSLT  | 
17  |  | #include "libxslt.h"  | 
18  |  |  | 
19  |  | #include <string.h>  | 
20  |  |  | 
21  |  | #include <libxml/xmlmemory.h>  | 
22  |  | #include <libxml/parser.h>  | 
23  |  | #include <libxml/tree.h>  | 
24  |  | #include <libxml/valid.h>  | 
25  |  | #include <libxml/hash.h>  | 
26  |  | #include <libxml/uri.h>  | 
27  |  | #include <libxml/xmlerror.h>  | 
28  |  | #include <libxml/parserInternals.h>  | 
29  |  | #include <libxml/xpathInternals.h>  | 
30  |  | #include <libxml/xpath.h>  | 
31  |  | #include "xslt.h"  | 
32  |  | #include "xsltInternals.h"  | 
33  |  | #include "pattern.h"  | 
34  |  | #include "variables.h"  | 
35  |  | #include "namespaces.h"  | 
36  |  | #include "attributes.h"  | 
37  |  | #include "xsltutils.h"  | 
38  |  | #include "imports.h"  | 
39  |  | #include "keys.h"  | 
40  |  | #include "documents.h"  | 
41  |  | #include "extensions.h"  | 
42  |  | #include "preproc.h"  | 
43  |  | #include "extra.h"  | 
44  |  | #include "security.h"  | 
45  |  | #include "xsltlocale.h"  | 
46  |  |  | 
47  |  | #ifdef WITH_XSLT_DEBUG  | 
48  |  | #define WITH_XSLT_DEBUG_PARSING  | 
49  |  | /* #define WITH_XSLT_DEBUG_BLANKS */  | 
50  |  | #endif  | 
51  |  |  | 
52  |  | const char *xsltEngineVersion = LIBXSLT_VERSION_STRING LIBXSLT_VERSION_EXTRA;  | 
53  |  | const int xsltLibxsltVersion = LIBXSLT_VERSION;  | 
54  |  | const int xsltLibxmlVersion = LIBXML_VERSION;  | 
55  |  |  | 
56  |  | #ifdef XSLT_REFACTORED  | 
57  |  |  | 
58  |  | const xmlChar *xsltConstNamespaceNameXSLT = (const xmlChar *) XSLT_NAMESPACE;  | 
59  |  |  | 
60  |  | #define XSLT_ELEMENT_CATEGORY_XSLT 0  | 
61  |  | #define XSLT_ELEMENT_CATEGORY_EXTENSION 1  | 
62  |  | #define XSLT_ELEMENT_CATEGORY_LRE 2  | 
63  |  |  | 
64  |  | /*  | 
65  |  | * xsltLiteralResultMarker:  | 
66  |  | * Marker for Literal result elements, in order to avoid multiple attempts  | 
67  |  | * to recognize such elements in the stylesheet's tree.  | 
68  |  | * This marker is set on node->psvi during the initial traversal  | 
69  |  | * of a stylesheet's node tree.  | 
70  |  | *  | 
71  |  | const xmlChar *xsltLiteralResultMarker =  | 
72  |  |     (const xmlChar *) "Literal Result Element";  | 
73  |  | */  | 
74  |  |  | 
75  |  | /*  | 
76  |  | * xsltXSLTTextMarker:  | 
77  |  | * Marker for xsl:text elements. Used to recognize xsl:text elements  | 
78  |  | * for post-processing of the stylesheet's tree, where those  | 
79  |  | * elements are removed from the tree.  | 
80  |  | */  | 
81  |  | const xmlChar *xsltXSLTTextMarker = (const xmlChar *) "XSLT Text Element";  | 
82  |  |  | 
83  |  | /*  | 
84  |  | * xsltXSLTAttrMarker:  | 
85  |  | * Marker for XSLT attribute on Literal Result Elements.  | 
86  |  | */  | 
87  |  | const xmlChar *xsltXSLTAttrMarker = (const xmlChar *) "LRE XSLT Attr";  | 
88  |  |  | 
89  |  | #endif  | 
90  |  |  | 
91  |  | #ifdef XSLT_LOCALE_WINAPI  | 
92  |  | extern xmlRMutexPtr xsltLocaleMutex;  | 
93  |  | #endif  | 
94  |  |  | 
95  |  | /*  | 
96  |  |  * Useful macros  | 
97  |  |  */  | 
98  |  |  | 
99  |  | #ifdef  IS_BLANK  | 
100  |  | #undef  IS_BLANK  | 
101  |  | #endif  | 
102  | 0  | #define IS_BLANK(c) (((c) == 0x20) || ((c) == 0x09) || ((c) == 0xA) || \  | 
103  | 0  |                      ((c) == 0x0D))  | 
104  |  |  | 
105  |  | #ifdef  IS_BLANK_NODE  | 
106  |  | #undef  IS_BLANK_NODE  | 
107  |  | #endif  | 
108  |  | #define IS_BLANK_NODE(n)            \  | 
109  | 0  |     (((n)->type == XML_TEXT_NODE) && (xsltIsBlank((n)->content)))  | 
110  |  |  | 
111  |  | /**  | 
112  |  |  * xsltParseContentError:  | 
113  |  |  *  | 
114  |  |  * @style: the stylesheet  | 
115  |  |  * @node: the node where the error occured  | 
116  |  |  *  | 
117  |  |  * Compile-time error function.  | 
118  |  |  */  | 
119  |  | static void  | 
120  |  | xsltParseContentError(xsltStylesheetPtr style,  | 
121  |  |            xmlNodePtr node)  | 
122  | 0  | { | 
123  | 0  |     if ((style == NULL) || (node == NULL))  | 
124  | 0  |   return;  | 
125  |  |  | 
126  | 0  |     if (IS_XSLT_ELEM(node))  | 
127  | 0  |   xsltTransformError(NULL, style, node,  | 
128  | 0  |       "The XSLT-element '%s' is not allowed at this position.\n",  | 
129  | 0  |       node->name);  | 
130  | 0  |     else  | 
131  | 0  |   xsltTransformError(NULL, style, node,  | 
132  | 0  |       "The element '%s' is not allowed at this position.\n",  | 
133  | 0  |       node->name);  | 
134  | 0  |     style->errors++;  | 
135  | 0  | }  | 
136  |  |  | 
137  |  | #ifdef XSLT_REFACTORED  | 
138  |  | #else  | 
139  |  | /**  | 
140  |  |  * exclPrefixPush:  | 
141  |  |  * @style: the transformation stylesheet  | 
142  |  |  * @value:  the excluded namespace name to push on the stack  | 
143  |  |  *  | 
144  |  |  * Push an excluded namespace name on the stack  | 
145  |  |  *  | 
146  |  |  * Returns the new index in the stack or -1 if already present or  | 
147  |  |  * in case of error  | 
148  |  |  */  | 
149  |  | static int  | 
150  |  | exclPrefixPush(xsltStylesheetPtr style, xmlChar * value)  | 
151  | 0  | { | 
152  | 0  |     int i;  | 
153  |  | 
  | 
154  | 0  |     if (style->exclPrefixMax == 0) { | 
155  | 0  |         style->exclPrefixMax = 4;  | 
156  | 0  |         style->exclPrefixTab =  | 
157  | 0  |             (xmlChar * *)xmlMalloc(style->exclPrefixMax *  | 
158  | 0  |                                    sizeof(style->exclPrefixTab[0]));  | 
159  | 0  |         if (style->exclPrefixTab == NULL) { | 
160  | 0  |             xmlGenericError(xmlGenericErrorContext, "malloc failed !\n");  | 
161  | 0  |             return (-1);  | 
162  | 0  |         }  | 
163  | 0  |     }  | 
164  |  |     /* do not push duplicates */  | 
165  | 0  |     for (i = 0;i < style->exclPrefixNr;i++) { | 
166  | 0  |         if (xmlStrEqual(style->exclPrefixTab[i], value))  | 
167  | 0  |       return(-1);  | 
168  | 0  |     }  | 
169  | 0  |     if (style->exclPrefixNr >= style->exclPrefixMax) { | 
170  | 0  |         style->exclPrefixMax *= 2;  | 
171  | 0  |         style->exclPrefixTab =  | 
172  | 0  |             (xmlChar * *)xmlRealloc(style->exclPrefixTab,  | 
173  | 0  |                                     style->exclPrefixMax *  | 
174  | 0  |                                     sizeof(style->exclPrefixTab[0]));  | 
175  | 0  |         if (style->exclPrefixTab == NULL) { | 
176  | 0  |             xmlGenericError(xmlGenericErrorContext, "realloc failed !\n");  | 
177  | 0  |             return (-1);  | 
178  | 0  |         }  | 
179  | 0  |     }  | 
180  | 0  |     style->exclPrefixTab[style->exclPrefixNr] = value;  | 
181  | 0  |     style->exclPrefix = value;  | 
182  | 0  |     return (style->exclPrefixNr++);  | 
183  | 0  | }  | 
184  |  | /**  | 
185  |  |  * exclPrefixPop:  | 
186  |  |  * @style: the transformation stylesheet  | 
187  |  |  *  | 
188  |  |  * Pop an excluded prefix value from the stack  | 
189  |  |  *  | 
190  |  |  * Returns the stored excluded prefix value  | 
191  |  |  */  | 
192  |  | static xmlChar *  | 
193  |  | exclPrefixPop(xsltStylesheetPtr style)  | 
194  | 0  | { | 
195  | 0  |     xmlChar *ret;  | 
196  |  | 
  | 
197  | 0  |     if (style->exclPrefixNr <= 0)  | 
198  | 0  |         return (0);  | 
199  | 0  |     style->exclPrefixNr--;  | 
200  | 0  |     if (style->exclPrefixNr > 0)  | 
201  | 0  |         style->exclPrefix = style->exclPrefixTab[style->exclPrefixNr - 1];  | 
202  | 0  |     else  | 
203  | 0  |         style->exclPrefix = NULL;  | 
204  | 0  |     ret = style->exclPrefixTab[style->exclPrefixNr];  | 
205  | 0  |     style->exclPrefixTab[style->exclPrefixNr] = 0;  | 
206  | 0  |     return (ret);  | 
207  | 0  | }  | 
208  |  | #endif  | 
209  |  |  | 
210  |  | /************************************************************************  | 
211  |  |  *                  *  | 
212  |  |  *      Helper functions        *  | 
213  |  |  *                  *  | 
214  |  |  ************************************************************************/  | 
215  |  |  | 
216  |  | static int initialized = 0;  | 
217  |  | /**  | 
218  |  |  * xsltInit:  | 
219  |  |  *  | 
220  |  |  * Initializes the processor (e.g. registers built-in extensions,  | 
221  |  |  * etc.)  | 
222  |  |  */  | 
223  |  | void  | 
224  | 58  | xsltInit (void) { | 
225  | 58  |     if (initialized == 0) { | 
226  | 29  |   initialized = 1;  | 
227  |  | #ifdef XSLT_LOCALE_WINAPI  | 
228  |  |   xsltLocaleMutex = xmlNewRMutex();  | 
229  |  | #endif  | 
230  | 29  |         xsltRegisterAllExtras();  | 
231  | 29  |     }  | 
232  | 58  | }  | 
233  |  |  | 
234  |  | /**  | 
235  |  |  * xsltUninit:  | 
236  |  |  *  | 
237  |  |  * Uninitializes the processor.  | 
238  |  |  */  | 
239  |  | void  | 
240  | 0  | xsltUninit (void) { | 
241  |  | #ifdef XSLT_LOCALE_WINAPI  | 
242  |  |     xmlFreeRMutex(xsltLocaleMutex);  | 
243  |  |     xsltLocaleMutex = NULL;  | 
244  |  | #endif  | 
245  | 0  |     initialized = 0;  | 
246  | 0  | }  | 
247  |  |  | 
248  |  | /**  | 
249  |  |  * xsltIsBlank:  | 
250  |  |  * @str:  a string  | 
251  |  |  *  | 
252  |  |  * Check if a string is ignorable  | 
253  |  |  *  | 
254  |  |  * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise  | 
255  |  |  */  | 
256  |  | int  | 
257  | 0  | xsltIsBlank(xmlChar *str) { | 
258  | 0  |     if (str == NULL)  | 
259  | 0  |   return(1);  | 
260  | 0  |     while (*str != 0) { | 
261  | 0  |   if (!(IS_BLANK(*str))) return(0);  | 
262  | 0  |   str++;  | 
263  | 0  |     }  | 
264  | 0  |     return(1);  | 
265  | 0  | }  | 
266  |  |  | 
267  |  | /************************************************************************  | 
268  |  |  *                  *  | 
269  |  |  *    Routines to handle XSLT data structures     *  | 
270  |  |  *                  *  | 
271  |  |  ************************************************************************/  | 
272  |  | static xsltDecimalFormatPtr  | 
273  |  | xsltNewDecimalFormat(const xmlChar *nsUri, xmlChar *name)  | 
274  | 29  | { | 
275  | 29  |     xsltDecimalFormatPtr self;  | 
276  |  |     /* UTF-8 for 0x2030 */  | 
277  | 29  |     static const xmlChar permille[4] = {0xe2, 0x80, 0xb0, 0}; | 
278  |  |  | 
279  | 29  |     self = xmlMalloc(sizeof(xsltDecimalFormat));  | 
280  | 29  |     if (self != NULL) { | 
281  | 29  |   self->next = NULL;  | 
282  | 29  |         self->nsUri = nsUri;  | 
283  | 29  |   self->name = name;  | 
284  |  |  | 
285  |  |   /* Default values */  | 
286  | 29  |   self->digit = xmlStrdup(BAD_CAST("#")); | 
287  | 29  |   self->patternSeparator = xmlStrdup(BAD_CAST(";")); | 
288  | 29  |   self->decimalPoint = xmlStrdup(BAD_CAST(".")); | 
289  | 29  |   self->grouping = xmlStrdup(BAD_CAST(",")); | 
290  | 29  |   self->percent = xmlStrdup(BAD_CAST("%")); | 
291  | 29  |   self->permille = xmlStrdup(BAD_CAST(permille));  | 
292  | 29  |   self->zeroDigit = xmlStrdup(BAD_CAST("0")); | 
293  | 29  |   self->minusSign = xmlStrdup(BAD_CAST("-")); | 
294  | 29  |   self->infinity = xmlStrdup(BAD_CAST("Infinity")); | 
295  | 29  |   self->noNumber = xmlStrdup(BAD_CAST("NaN")); | 
296  | 29  |     }  | 
297  | 29  |     return self;  | 
298  | 29  | }  | 
299  |  |  | 
300  |  | static void  | 
301  |  | xsltFreeDecimalFormat(xsltDecimalFormatPtr self)  | 
302  | 0  | { | 
303  | 0  |     if (self != NULL) { | 
304  | 0  |   if (self->digit)  | 
305  | 0  |       xmlFree(self->digit);  | 
306  | 0  |   if (self->patternSeparator)  | 
307  | 0  |       xmlFree(self->patternSeparator);  | 
308  | 0  |   if (self->decimalPoint)  | 
309  | 0  |       xmlFree(self->decimalPoint);  | 
310  | 0  |   if (self->grouping)  | 
311  | 0  |       xmlFree(self->grouping);  | 
312  | 0  |   if (self->percent)  | 
313  | 0  |       xmlFree(self->percent);  | 
314  | 0  |   if (self->permille)  | 
315  | 0  |       xmlFree(self->permille);  | 
316  | 0  |   if (self->zeroDigit)  | 
317  | 0  |       xmlFree(self->zeroDigit);  | 
318  | 0  |   if (self->minusSign)  | 
319  | 0  |       xmlFree(self->minusSign);  | 
320  | 0  |   if (self->infinity)  | 
321  | 0  |       xmlFree(self->infinity);  | 
322  | 0  |   if (self->noNumber)  | 
323  | 0  |       xmlFree(self->noNumber);  | 
324  | 0  |   if (self->name)  | 
325  | 0  |       xmlFree(self->name);  | 
326  | 0  |   xmlFree(self);  | 
327  | 0  |     }  | 
328  | 0  | }  | 
329  |  |  | 
330  |  | static void  | 
331  |  | xsltFreeDecimalFormatList(xsltStylesheetPtr self)  | 
332  | 0  | { | 
333  | 0  |     xsltDecimalFormatPtr iter;  | 
334  | 0  |     xsltDecimalFormatPtr tmp;  | 
335  |  | 
  | 
336  | 0  |     if (self == NULL)  | 
337  | 0  |   return;  | 
338  |  |  | 
339  | 0  |     iter = self->decimalFormat;  | 
340  | 0  |     while (iter != NULL) { | 
341  | 0  |   tmp = iter->next;  | 
342  | 0  |   xsltFreeDecimalFormat(iter);  | 
343  | 0  |   iter = tmp;  | 
344  | 0  |     }  | 
345  | 0  | }  | 
346  |  |  | 
347  |  | /**  | 
348  |  |  * xsltDecimalFormatGetByName:  | 
349  |  |  * @style: the XSLT stylesheet  | 
350  |  |  * @name: the decimal-format name to find  | 
351  |  |  *  | 
352  |  |  * Find decimal-format by name  | 
353  |  |  *  | 
354  |  |  * Returns the xsltDecimalFormatPtr  | 
355  |  |  */  | 
356  |  | xsltDecimalFormatPtr  | 
357  |  | xsltDecimalFormatGetByName(xsltStylesheetPtr style, xmlChar *name)  | 
358  | 0  | { | 
359  | 0  |     xsltDecimalFormatPtr result = NULL;  | 
360  |  | 
  | 
361  | 0  |     if (name == NULL)  | 
362  | 0  |   return style->decimalFormat;  | 
363  |  |  | 
364  | 0  |     while (style != NULL) { | 
365  | 0  |   for (result = style->decimalFormat->next;  | 
366  | 0  |        result != NULL;  | 
367  | 0  |        result = result->next) { | 
368  | 0  |       if ((result->nsUri == NULL) && xmlStrEqual(name, result->name))  | 
369  | 0  |     return result;  | 
370  | 0  |   }  | 
371  | 0  |   style = xsltNextImport(style);  | 
372  | 0  |     }  | 
373  | 0  |     return result;  | 
374  | 0  | }  | 
375  |  |  | 
376  |  | /**  | 
377  |  |  * xsltDecimalFormatGetByQName:  | 
378  |  |  * @style: the XSLT stylesheet  | 
379  |  |  * @nsUri: the namespace URI of the QName  | 
380  |  |  * @name: the local part of the QName  | 
381  |  |  *  | 
382  |  |  * Find decimal-format by QName  | 
383  |  |  *  | 
384  |  |  * Returns the xsltDecimalFormatPtr  | 
385  |  |  */  | 
386  |  | xsltDecimalFormatPtr  | 
387  |  | xsltDecimalFormatGetByQName(xsltStylesheetPtr style, const xmlChar *nsUri,  | 
388  |  |                             const xmlChar *name)  | 
389  | 0  | { | 
390  | 0  |     xsltDecimalFormatPtr result = NULL;  | 
391  |  | 
  | 
392  | 0  |     if (name == NULL)  | 
393  | 0  |   return style->decimalFormat;  | 
394  |  |  | 
395  | 0  |     while (style != NULL) { | 
396  | 0  |   for (result = style->decimalFormat->next;  | 
397  | 0  |        result != NULL;  | 
398  | 0  |        result = result->next) { | 
399  | 0  |       if (xmlStrEqual(nsUri, result->nsUri) &&  | 
400  | 0  |                 xmlStrEqual(name, result->name))  | 
401  | 0  |     return result;  | 
402  | 0  |   }  | 
403  | 0  |   style = xsltNextImport(style);  | 
404  | 0  |     }  | 
405  | 0  |     return result;  | 
406  | 0  | }  | 
407  |  |  | 
408  |  |  | 
409  |  | /**  | 
410  |  |  * xsltNewTemplate:  | 
411  |  |  *  | 
412  |  |  * Create a new XSLT Template  | 
413  |  |  *  | 
414  |  |  * Returns the newly allocated xsltTemplatePtr or NULL in case of error  | 
415  |  |  */  | 
416  |  | static xsltTemplatePtr  | 
417  | 0  | xsltNewTemplate(void) { | 
418  | 0  |     xsltTemplatePtr cur;  | 
419  |  | 
  | 
420  | 0  |     cur = (xsltTemplatePtr) xmlMalloc(sizeof(xsltTemplate));  | 
421  | 0  |     if (cur == NULL) { | 
422  | 0  |   xsltTransformError(NULL, NULL, NULL,  | 
423  | 0  |     "xsltNewTemplate : malloc failed\n");  | 
424  | 0  |   return(NULL);  | 
425  | 0  |     }  | 
426  | 0  |     memset(cur, 0, sizeof(xsltTemplate));  | 
427  | 0  |     cur->priority = XSLT_PAT_NO_PRIORITY;  | 
428  | 0  |     return(cur);  | 
429  | 0  | }  | 
430  |  |  | 
431  |  | /**  | 
432  |  |  * xsltFreeTemplate:  | 
433  |  |  * @template:  an XSLT template  | 
434  |  |  *  | 
435  |  |  * Free up the memory allocated by @template  | 
436  |  |  */  | 
437  |  | static void  | 
438  | 0  | xsltFreeTemplate(xsltTemplatePtr template) { | 
439  | 0  |     if (template == NULL)  | 
440  | 0  |   return;  | 
441  | 0  |     if (template->match) xmlFree(template->match);  | 
442  |  | /*  | 
443  |  | *   NOTE: @name and @nameURI are put into the string dict now.  | 
444  |  | *   if (template->name) xmlFree(template->name);  | 
445  |  | *   if (template->nameURI) xmlFree(template->nameURI);  | 
446  |  | */  | 
447  |  | /*  | 
448  |  |     if (template->mode) xmlFree(template->mode);  | 
449  |  |     if (template->modeURI) xmlFree(template->modeURI);  | 
450  |  |  */  | 
451  | 0  |     if (template->inheritedNs) xmlFree(template->inheritedNs);  | 
452  |  |  | 
453  |  |     /* free profiling data */  | 
454  | 0  |     if (template->templCalledTab) xmlFree(template->templCalledTab);  | 
455  | 0  |     if (template->templCountTab) xmlFree(template->templCountTab);  | 
456  |  | 
  | 
457  | 0  |     memset(template, -1, sizeof(xsltTemplate));  | 
458  | 0  |     xmlFree(template);  | 
459  | 0  | }  | 
460  |  |  | 
461  |  | /**  | 
462  |  |  * xsltFreeTemplateList:  | 
463  |  |  * @template:  an XSLT template list  | 
464  |  |  *  | 
465  |  |  * Free up the memory allocated by all the elements of @template  | 
466  |  |  */  | 
467  |  | static void  | 
468  | 0  | xsltFreeTemplateList(xsltTemplatePtr template) { | 
469  | 0  |     xsltTemplatePtr cur;  | 
470  |  | 
  | 
471  | 0  |     while (template != NULL) { | 
472  | 0  |   cur = template;  | 
473  | 0  |   template = template->next;  | 
474  | 0  |   xsltFreeTemplate(cur);  | 
475  | 0  |     }  | 
476  | 0  | }  | 
477  |  |  | 
478  |  | #ifdef XSLT_REFACTORED  | 
479  |  |  | 
480  |  | static void  | 
481  |  | xsltFreeNsAliasList(xsltNsAliasPtr item)  | 
482  |  | { | 
483  |  |     xsltNsAliasPtr tmp;  | 
484  |  |  | 
485  |  |     while (item) { | 
486  |  |   tmp = item;  | 
487  |  |   item = item->next;  | 
488  |  |   xmlFree(tmp);  | 
489  |  |     }  | 
490  |  |     return;  | 
491  |  | }  | 
492  |  |  | 
493  |  | #ifdef XSLT_REFACTORED_XSLT_NSCOMP  | 
494  |  | static void  | 
495  |  | xsltFreeNamespaceMap(xsltNsMapPtr item)  | 
496  |  | { | 
497  |  |     xsltNsMapPtr tmp;  | 
498  |  |  | 
499  |  |     while (item) { | 
500  |  |   tmp = item;  | 
501  |  |   item = item->next;  | 
502  |  |   xmlFree(tmp);  | 
503  |  |     }  | 
504  |  |     return;  | 
505  |  | }  | 
506  |  |  | 
507  |  | static xsltNsMapPtr  | 
508  |  | xsltNewNamespaceMapItem(xsltCompilerCtxtPtr cctxt,  | 
509  |  |       xmlDocPtr doc,  | 
510  |  |       xmlNsPtr ns,  | 
511  |  |       xmlNodePtr elem)  | 
512  |  | { | 
513  |  |     xsltNsMapPtr ret;  | 
514  |  |  | 
515  |  |     if ((cctxt == NULL) || (doc == NULL) || (ns == NULL))  | 
516  |  |   return(NULL);  | 
517  |  |  | 
518  |  |     ret = (xsltNsMapPtr) xmlMalloc(sizeof(xsltNsMap));  | 
519  |  |     if (ret == NULL) { | 
520  |  |   xsltTransformError(NULL, cctxt->style, elem,  | 
521  |  |       "Internal error: (xsltNewNamespaceMapItem) "  | 
522  |  |       "memory allocation failed.\n");  | 
523  |  |   return(NULL);  | 
524  |  |     }  | 
525  |  |     memset(ret, 0, sizeof(xsltNsMap));  | 
526  |  |     ret->doc = doc;  | 
527  |  |     ret->ns = ns;  | 
528  |  |     ret->origNsName = ns->href;  | 
529  |  |     /*  | 
530  |  |     * Store the item at current stylesheet-level.  | 
531  |  |     */  | 
532  |  |     if (cctxt->psData->nsMap != NULL)  | 
533  |  |   ret->next = cctxt->psData->nsMap;  | 
534  |  |     cctxt->psData->nsMap = ret;  | 
535  |  |  | 
536  |  |     return(ret);  | 
537  |  | }  | 
538  |  | #endif /* XSLT_REFACTORED_XSLT_NSCOMP */  | 
539  |  |  | 
540  |  | /**  | 
541  |  |  * xsltCompilerVarInfoFree:  | 
542  |  |  * @cctxt: the compilation context  | 
543  |  |  *  | 
544  |  |  * Frees the list of information for vars/params.  | 
545  |  |  */  | 
546  |  | static void  | 
547  |  | xsltCompilerVarInfoFree(xsltCompilerCtxtPtr cctxt)  | 
548  |  | { | 
549  |  |     xsltVarInfoPtr ivar = cctxt->ivars, ivartmp;  | 
550  |  |  | 
551  |  |     while (ivar) { | 
552  |  |   ivartmp = ivar;  | 
553  |  |   ivar = ivar->next;  | 
554  |  |   xmlFree(ivartmp);  | 
555  |  |     }  | 
556  |  | }  | 
557  |  |  | 
558  |  | /**  | 
559  |  |  * xsltCompilerCtxtFree:  | 
560  |  |  *  | 
561  |  |  * Free an XSLT compiler context.  | 
562  |  |  */  | 
563  |  | static void  | 
564  |  | xsltCompilationCtxtFree(xsltCompilerCtxtPtr cctxt)  | 
565  |  | { | 
566  |  |     if (cctxt == NULL)  | 
567  |  |   return;  | 
568  |  | #ifdef WITH_XSLT_DEBUG_PARSING  | 
569  |  |     xsltGenericDebug(xsltGenericDebugContext,  | 
570  |  |   "Freeing compilation context\n");  | 
571  |  |     xsltGenericDebug(xsltGenericDebugContext,  | 
572  |  |   "### Max inodes: %d\n", cctxt->maxNodeInfos);  | 
573  |  |     xsltGenericDebug(xsltGenericDebugContext,  | 
574  |  |   "### Max LREs  : %d\n", cctxt->maxLREs);  | 
575  |  | #endif  | 
576  |  |     /*  | 
577  |  |     * Free node-infos.  | 
578  |  |     */  | 
579  |  |     if (cctxt->inodeList != NULL) { | 
580  |  |   xsltCompilerNodeInfoPtr tmp, cur = cctxt->inodeList;  | 
581  |  |   while (cur != NULL) { | 
582  |  |       tmp = cur;  | 
583  |  |       cur = cur->next;  | 
584  |  |       xmlFree(tmp);  | 
585  |  |   }  | 
586  |  |     }  | 
587  |  |     if (cctxt->tmpList != NULL)  | 
588  |  |   xsltPointerListFree(cctxt->tmpList);  | 
589  |  |     if (cctxt->nsAliases != NULL)  | 
590  |  |   xsltFreeNsAliasList(cctxt->nsAliases);  | 
591  |  |  | 
592  |  |     if (cctxt->ivars)  | 
593  |  |   xsltCompilerVarInfoFree(cctxt);  | 
594  |  |  | 
595  |  |     xmlFree(cctxt);  | 
596  |  | }  | 
597  |  |  | 
598  |  | /**  | 
599  |  |  * xsltCompilerCreate:  | 
600  |  |  *  | 
601  |  |  * Creates an XSLT compiler context.  | 
602  |  |  *  | 
603  |  |  * Returns the pointer to the created xsltCompilerCtxt or  | 
604  |  |  *         NULL in case of an internal error.  | 
605  |  |  */  | 
606  |  | static xsltCompilerCtxtPtr  | 
607  |  | xsltCompilationCtxtCreate(xsltStylesheetPtr style) { | 
608  |  |     xsltCompilerCtxtPtr ret;  | 
609  |  |  | 
610  |  |     ret = (xsltCompilerCtxtPtr) xmlMalloc(sizeof(xsltCompilerCtxt));  | 
611  |  |     if (ret == NULL) { | 
612  |  |   xsltTransformError(NULL, style, NULL,  | 
613  |  |       "xsltCompilerCreate: allocation of compiler "  | 
614  |  |       "context failed.\n");  | 
615  |  |   return(NULL);  | 
616  |  |     }  | 
617  |  |     memset(ret, 0, sizeof(xsltCompilerCtxt));  | 
618  |  |  | 
619  |  |     ret->errSeverity = XSLT_ERROR_SEVERITY_ERROR;  | 
620  |  |     ret->tmpList = xsltPointerListCreate(20);  | 
621  |  |     if (ret->tmpList == NULL) { | 
622  |  |   goto internal_err;  | 
623  |  |     }  | 
624  |  |  | 
625  |  |     return(ret);  | 
626  |  |  | 
627  |  | internal_err:  | 
628  |  |     xsltCompilationCtxtFree(ret);  | 
629  |  |     return(NULL);  | 
630  |  | }  | 
631  |  |  | 
632  |  | static void  | 
633  |  | xsltLREEffectiveNsNodesFree(xsltEffectiveNsPtr first)  | 
634  |  | { | 
635  |  |     xsltEffectiveNsPtr tmp;  | 
636  |  |  | 
637  |  |     while (first != NULL) { | 
638  |  |   tmp = first;  | 
639  |  |   first = first->nextInStore;  | 
640  |  |   xmlFree(tmp);  | 
641  |  |     }  | 
642  |  | }  | 
643  |  |  | 
644  |  | static void  | 
645  |  | xsltFreePrincipalStylesheetData(xsltPrincipalStylesheetDataPtr data)  | 
646  |  | { | 
647  |  |     if (data == NULL)  | 
648  |  |   return;  | 
649  |  |  | 
650  |  |     if (data->inScopeNamespaces != NULL) { | 
651  |  |   int i;  | 
652  |  |   xsltNsListContainerPtr nsi;  | 
653  |  |   xsltPointerListPtr list =  | 
654  |  |       (xsltPointerListPtr) data->inScopeNamespaces;  | 
655  |  |  | 
656  |  |   for (i = 0; i < list->number; i++) { | 
657  |  |       /*  | 
658  |  |       * REVISIT TODO: Free info of in-scope namespaces.  | 
659  |  |       */  | 
660  |  |       nsi = (xsltNsListContainerPtr) list->items[i];  | 
661  |  |       if (nsi->list != NULL)  | 
662  |  |     xmlFree(nsi->list);  | 
663  |  |       xmlFree(nsi);  | 
664  |  |   }  | 
665  |  |   xsltPointerListFree(list);  | 
666  |  |   data->inScopeNamespaces = NULL;  | 
667  |  |     }  | 
668  |  |  | 
669  |  |     if (data->exclResultNamespaces != NULL) { | 
670  |  |   int i;  | 
671  |  |   xsltPointerListPtr list = (xsltPointerListPtr)  | 
672  |  |       data->exclResultNamespaces;  | 
673  |  |  | 
674  |  |   for (i = 0; i < list->number; i++)  | 
675  |  |       xsltPointerListFree((xsltPointerListPtr) list->items[i]);  | 
676  |  |  | 
677  |  |   xsltPointerListFree(list);  | 
678  |  |   data->exclResultNamespaces = NULL;  | 
679  |  |     }  | 
680  |  |  | 
681  |  |     if (data->extElemNamespaces != NULL) { | 
682  |  |   xsltPointerListPtr list = (xsltPointerListPtr)  | 
683  |  |       data->extElemNamespaces;  | 
684  |  |   int i;  | 
685  |  |  | 
686  |  |   for (i = 0; i < list->number; i++)  | 
687  |  |       xsltPointerListFree((xsltPointerListPtr) list->items[i]);  | 
688  |  |  | 
689  |  |   xsltPointerListFree(list);  | 
690  |  |   data->extElemNamespaces = NULL;  | 
691  |  |     }  | 
692  |  |     if (data->effectiveNs) { | 
693  |  |   xsltLREEffectiveNsNodesFree(data->effectiveNs);  | 
694  |  |   data->effectiveNs = NULL;  | 
695  |  |     }  | 
696  |  | #ifdef XSLT_REFACTORED_XSLT_NSCOMP  | 
697  |  |     xsltFreeNamespaceMap(data->nsMap);  | 
698  |  | #endif  | 
699  |  |     xmlFree(data);  | 
700  |  | }  | 
701  |  |  | 
702  |  | static xsltPrincipalStylesheetDataPtr  | 
703  |  | xsltNewPrincipalStylesheetData(void)  | 
704  |  | { | 
705  |  |     xsltPrincipalStylesheetDataPtr ret;  | 
706  |  |  | 
707  |  |     ret = (xsltPrincipalStylesheetDataPtr)  | 
708  |  |   xmlMalloc(sizeof(xsltPrincipalStylesheetData));  | 
709  |  |     if (ret == NULL) { | 
710  |  |   xsltTransformError(NULL, NULL, NULL,  | 
711  |  |       "xsltNewPrincipalStylesheetData: memory allocation failed.\n");  | 
712  |  |   return(NULL);  | 
713  |  |     }  | 
714  |  |     memset(ret, 0, sizeof(xsltPrincipalStylesheetData));  | 
715  |  |  | 
716  |  |     /*  | 
717  |  |     * Global list of in-scope namespaces.  | 
718  |  |     */  | 
719  |  |     ret->inScopeNamespaces = xsltPointerListCreate(-1);  | 
720  |  |     if (ret->inScopeNamespaces == NULL)  | 
721  |  |   goto internal_err;  | 
722  |  |     /*  | 
723  |  |     * Global list of excluded result ns-decls.  | 
724  |  |     */  | 
725  |  |     ret->exclResultNamespaces = xsltPointerListCreate(-1);  | 
726  |  |     if (ret->exclResultNamespaces == NULL)  | 
727  |  |   goto internal_err;  | 
728  |  |     /*  | 
729  |  |     * Global list of extension instruction namespace names.  | 
730  |  |     */  | 
731  |  |     ret->extElemNamespaces = xsltPointerListCreate(-1);  | 
732  |  |     if (ret->extElemNamespaces == NULL)  | 
733  |  |   goto internal_err;  | 
734  |  |  | 
735  |  |     return(ret);  | 
736  |  |  | 
737  |  | internal_err:  | 
738  |  |  | 
739  |  |     return(NULL);  | 
740  |  | }  | 
741  |  |  | 
742  |  | #endif  | 
743  |  |  | 
744  |  | /**  | 
745  |  |  * xsltNewStylesheetInternal:  | 
746  |  |  * @parent:  the parent stylesheet or NULL  | 
747  |  |  *  | 
748  |  |  * Create a new XSLT Stylesheet  | 
749  |  |  *  | 
750  |  |  * Returns the newly allocated xsltStylesheetPtr or NULL in case of error  | 
751  |  |  */  | 
752  |  | static xsltStylesheetPtr  | 
753  | 29  | xsltNewStylesheetInternal(xsltStylesheetPtr parent) { | 
754  | 29  |     xsltStylesheetPtr ret = NULL;  | 
755  |  |  | 
756  | 29  |     ret = (xsltStylesheetPtr) xmlMalloc(sizeof(xsltStylesheet));  | 
757  | 29  |     if (ret == NULL) { | 
758  | 0  |   xsltTransformError(NULL, NULL, NULL,  | 
759  | 0  |     "xsltNewStylesheet : malloc failed\n");  | 
760  | 0  |   goto internal_err;  | 
761  | 0  |     }  | 
762  | 29  |     memset(ret, 0, sizeof(xsltStylesheet));  | 
763  |  |  | 
764  | 29  |     ret->parent = parent;  | 
765  | 29  |     ret->omitXmlDeclaration = -1;  | 
766  | 29  |     ret->standalone = -1;  | 
767  | 29  |     ret->decimalFormat = xsltNewDecimalFormat(NULL, NULL);  | 
768  | 29  |     ret->indent = -1;  | 
769  | 29  |     ret->errors = 0;  | 
770  | 29  |     ret->warnings = 0;  | 
771  | 29  |     ret->exclPrefixNr = 0;  | 
772  | 29  |     ret->exclPrefixMax = 0;  | 
773  | 29  |     ret->exclPrefixTab = NULL;  | 
774  | 29  |     ret->extInfos = NULL;  | 
775  | 29  |     ret->extrasNr = 0;  | 
776  | 29  |     ret->internalized = 1;  | 
777  | 29  |     ret->literal_result = 0;  | 
778  | 29  |     ret->forwards_compatible = 0;  | 
779  | 29  |     ret->dict = xmlDictCreate();  | 
780  |  | #ifdef WITH_XSLT_DEBUG  | 
781  |  |     xsltGenericDebug(xsltGenericDebugContext,  | 
782  |  |   "creating dictionary for stylesheet\n");  | 
783  |  | #endif  | 
784  |  |  | 
785  | 29  |     if (parent == NULL) { | 
786  | 29  |         ret->principal = ret;  | 
787  |  |  | 
788  | 29  |         ret->xpathCtxt = xmlXPathNewContext(NULL);  | 
789  | 29  |         if (ret->xpathCtxt == NULL) { | 
790  | 0  |             xsltTransformError(NULL, NULL, NULL,  | 
791  | 0  |                     "xsltNewStylesheet: xmlXPathNewContext failed\n");  | 
792  | 0  |             goto internal_err;  | 
793  | 0  |         }  | 
794  | 29  |         if (xmlXPathContextSetCache(ret->xpathCtxt, 1, -1, 0) == -1)  | 
795  | 0  |             goto internal_err;  | 
796  | 29  |     } else { | 
797  | 0  |         ret->principal = parent->principal;  | 
798  | 0  |     }  | 
799  |  |  | 
800  | 29  |     xsltInit();  | 
801  |  |  | 
802  | 29  |     return(ret);  | 
803  |  |  | 
804  | 0  | internal_err:  | 
805  | 0  |     if (ret != NULL)  | 
806  | 0  |   xsltFreeStylesheet(ret);  | 
807  | 0  |     return(NULL);  | 
808  | 29  | }  | 
809  |  |  | 
810  |  | /**  | 
811  |  |  * xsltNewStylesheet:  | 
812  |  |  *  | 
813  |  |  * Create a new XSLT Stylesheet  | 
814  |  |  *  | 
815  |  |  * Returns the newly allocated xsltStylesheetPtr or NULL in case of error  | 
816  |  |  */  | 
817  |  | xsltStylesheetPtr  | 
818  | 29  | xsltNewStylesheet(void) { | 
819  | 29  |     return xsltNewStylesheetInternal(NULL);  | 
820  | 29  | }  | 
821  |  |  | 
822  |  | /**  | 
823  |  |  * xsltAllocateExtra:  | 
824  |  |  * @style:  an XSLT stylesheet  | 
825  |  |  *  | 
826  |  |  * Allocate an extra runtime information slot statically while compiling  | 
827  |  |  * the stylesheet and return its number  | 
828  |  |  *  | 
829  |  |  * Returns the number of the slot  | 
830  |  |  */  | 
831  |  | int  | 
832  |  | xsltAllocateExtra(xsltStylesheetPtr style)  | 
833  | 0  | { | 
834  | 0  |     return(style->extrasNr++);  | 
835  | 0  | }  | 
836  |  |  | 
837  |  | /**  | 
838  |  |  * xsltAllocateExtraCtxt:  | 
839  |  |  * @ctxt:  an XSLT transformation context  | 
840  |  |  *  | 
841  |  |  * Allocate an extra runtime information slot at run-time  | 
842  |  |  * and return its number  | 
843  |  |  * This make sure there is a slot ready in the transformation context  | 
844  |  |  *  | 
845  |  |  * Returns the number of the slot  | 
846  |  |  */  | 
847  |  | int  | 
848  |  | xsltAllocateExtraCtxt(xsltTransformContextPtr ctxt)  | 
849  | 0  | { | 
850  | 0  |     if (ctxt->extrasNr >= ctxt->extrasMax) { | 
851  | 0  |   int i;  | 
852  | 0  |   if (ctxt->extrasNr == 0) { | 
853  | 0  |       ctxt->extrasMax = 20;  | 
854  | 0  |       ctxt->extras = (xsltRuntimeExtraPtr)  | 
855  | 0  |     xmlMalloc(ctxt->extrasMax * sizeof(xsltRuntimeExtra));  | 
856  | 0  |       if (ctxt->extras == NULL) { | 
857  | 0  |     xsltTransformError(ctxt, NULL, NULL,  | 
858  | 0  |       "xsltAllocateExtraCtxt: out of memory\n");  | 
859  | 0  |     return(0);  | 
860  | 0  |       }  | 
861  | 0  |       for (i = 0;i < ctxt->extrasMax;i++) { | 
862  | 0  |     ctxt->extras[i].info = NULL;  | 
863  | 0  |     ctxt->extras[i].deallocate = NULL;  | 
864  | 0  |     ctxt->extras[i].val.ptr = NULL;  | 
865  | 0  |       }  | 
866  |  | 
  | 
867  | 0  |   } else { | 
868  | 0  |       xsltRuntimeExtraPtr tmp;  | 
869  |  | 
  | 
870  | 0  |       ctxt->extrasMax += 100;  | 
871  | 0  |       tmp = (xsltRuntimeExtraPtr) xmlRealloc(ctxt->extras,  | 
872  | 0  |                 ctxt->extrasMax * sizeof(xsltRuntimeExtra));  | 
873  | 0  |       if (tmp == NULL) { | 
874  | 0  |     xsltTransformError(ctxt, NULL, NULL,  | 
875  | 0  |       "xsltAllocateExtraCtxt: out of memory\n");  | 
876  | 0  |     return(0);  | 
877  | 0  |       }  | 
878  | 0  |       ctxt->extras = tmp;  | 
879  | 0  |       for (i = ctxt->extrasNr;i < ctxt->extrasMax;i++) { | 
880  | 0  |     ctxt->extras[i].info = NULL;  | 
881  | 0  |     ctxt->extras[i].deallocate = NULL;  | 
882  | 0  |     ctxt->extras[i].val.ptr = NULL;  | 
883  | 0  |       }  | 
884  | 0  |   }  | 
885  | 0  |     }  | 
886  | 0  |     return(ctxt->extrasNr++);  | 
887  | 0  | }  | 
888  |  |  | 
889  |  | /**  | 
890  |  |  * xsltFreeStylesheetList:  | 
891  |  |  * @style:  an XSLT stylesheet list  | 
892  |  |  *  | 
893  |  |  * Free up the memory allocated by the list @style  | 
894  |  |  */  | 
895  |  | static void  | 
896  | 0  | xsltFreeStylesheetList(xsltStylesheetPtr style) { | 
897  | 0  |     xsltStylesheetPtr next;  | 
898  |  | 
  | 
899  | 0  |     while (style != NULL) { | 
900  | 0  |   next = style->next;  | 
901  | 0  |   xsltFreeStylesheet(style);  | 
902  | 0  |   style = next;  | 
903  | 0  |     }  | 
904  | 0  | }  | 
905  |  |  | 
906  |  | /**  | 
907  |  |  * xsltCleanupStylesheetTree:  | 
908  |  |  *  | 
909  |  |  * @doc: the document-node  | 
910  |  |  * @node: the element where the stylesheet is rooted at  | 
911  |  |  *  | 
912  |  |  * Actually @node need not be the document-element, but  | 
913  |  |  * currently Libxslt does not support embedded stylesheets.  | 
914  |  |  *  | 
915  |  |  * Returns 0 if OK, -1 on API or internal errors.  | 
916  |  |  */  | 
917  |  | static int  | 
918  |  | xsltCleanupStylesheetTree(xmlDocPtr doc ATTRIBUTE_UNUSED,  | 
919  |  |         xmlNodePtr rootElem ATTRIBUTE_UNUSED)  | 
920  | 0  | { | 
921  |  | #if 0 /* TODO: Currently disabled, since probably not needed. */  | 
922  |  |     xmlNodePtr cur;  | 
923  |  |  | 
924  |  |     if ((doc == NULL) || (rootElem == NULL) ||  | 
925  |  |   (rootElem->type != XML_ELEMENT_NODE) ||  | 
926  |  |   (doc != rootElem->doc))  | 
927  |  |   return(-1);  | 
928  |  |  | 
929  |  |     /*  | 
930  |  |     * Cleanup was suggested by Aleksey Sanin:  | 
931  |  |     * Clear the PSVI field to avoid problems if the  | 
932  |  |     * node-tree of the stylesheet is intended to be used for  | 
933  |  |     * further processing by the user (e.g. for compiling it  | 
934  |  |     * once again - although not recommended).  | 
935  |  |     */  | 
936  |  |  | 
937  |  |     cur = rootElem;  | 
938  |  |     while (cur != NULL) { | 
939  |  |   if (cur->type == XML_ELEMENT_NODE) { | 
940  |  |       /*  | 
941  |  |       * Clear the PSVI field.  | 
942  |  |       */  | 
943  |  |       cur->psvi = NULL;  | 
944  |  |       if (cur->children) { | 
945  |  |     cur = cur->children;  | 
946  |  |     continue;  | 
947  |  |       }  | 
948  |  |   }  | 
949  |  |  | 
950  |  | leave_node:  | 
951  |  |   if (cur == rootElem)  | 
952  |  |       break;  | 
953  |  |   if (cur->next != NULL)  | 
954  |  |       cur = cur->next;  | 
955  |  |   else { | 
956  |  |       cur = cur->parent;  | 
957  |  |       if (cur == NULL)  | 
958  |  |     break;  | 
959  |  |       goto leave_node;  | 
960  |  |   }  | 
961  |  |     }  | 
962  |  | #endif /* #if 0 */  | 
963  | 0  |     return(0);  | 
964  | 0  | }  | 
965  |  |  | 
966  |  | /**  | 
967  |  |  * xsltFreeStylesheet:  | 
968  |  |  * @style:  an XSLT stylesheet  | 
969  |  |  *  | 
970  |  |  * Free up the memory allocated by @style  | 
971  |  |  */  | 
972  |  | void  | 
973  |  | xsltFreeStylesheet(xsltStylesheetPtr style)  | 
974  | 0  | { | 
975  | 0  |     if (style == NULL)  | 
976  | 0  |         return;  | 
977  |  |  | 
978  |  | #ifdef XSLT_REFACTORED  | 
979  |  |     /*  | 
980  |  |     * Start with a cleanup of the main stylesheet's doc.  | 
981  |  |     */  | 
982  |  |     if ((style->principal == style) && (style->doc))  | 
983  |  |   xsltCleanupStylesheetTree(style->doc,  | 
984  |  |       xmlDocGetRootElement(style->doc));  | 
985  |  | #ifdef XSLT_REFACTORED_XSLT_NSCOMP  | 
986  |  |     /*  | 
987  |  |     * Restore changed ns-decls before freeing the document.  | 
988  |  |     */  | 
989  |  |     if ((style->doc != NULL) &&  | 
990  |  |   XSLT_HAS_INTERNAL_NSMAP(style))  | 
991  |  |     { | 
992  |  |   xsltRestoreDocumentNamespaces(XSLT_GET_INTERNAL_NSMAP(style),  | 
993  |  |       style->doc);  | 
994  |  |     }  | 
995  |  | #endif /* XSLT_REFACTORED_XSLT_NSCOMP */  | 
996  |  | #else  | 
997  |  |     /*  | 
998  |  |     * Start with a cleanup of the main stylesheet's doc.  | 
999  |  |     */  | 
1000  | 0  |     if ((style->parent == NULL) && (style->doc))  | 
1001  | 0  |   xsltCleanupStylesheetTree(style->doc,  | 
1002  | 0  |       xmlDocGetRootElement(style->doc));  | 
1003  | 0  | #endif /* XSLT_REFACTORED */  | 
1004  |  | 
  | 
1005  | 0  |     xsltFreeKeys(style);  | 
1006  | 0  |     xsltFreeExts(style);  | 
1007  | 0  |     xsltFreeTemplateHashes(style);  | 
1008  | 0  |     xsltFreeDecimalFormatList(style);  | 
1009  | 0  |     xsltFreeTemplateList(style->templates);  | 
1010  | 0  |     xsltFreeAttributeSetsHashes(style);  | 
1011  | 0  |     xsltFreeNamespaceAliasHashes(style);  | 
1012  | 0  |     xsltFreeStylePreComps(style);  | 
1013  |  |     /*  | 
1014  |  |     * Free documents of all included stylsheet modules of this  | 
1015  |  |     * stylesheet level.  | 
1016  |  |     */  | 
1017  | 0  |     xsltFreeStyleDocuments(style);  | 
1018  |  |     /*  | 
1019  |  |     * TODO: Best time to shutdown extension stuff?  | 
1020  |  |     */  | 
1021  | 0  |     xsltShutdownExts(style);  | 
1022  |  | 
  | 
1023  | 0  |     if (style->variables != NULL)  | 
1024  | 0  |         xsltFreeStackElemList(style->variables);  | 
1025  | 0  |     if (style->cdataSection != NULL)  | 
1026  | 0  |         xmlHashFree(style->cdataSection, NULL);  | 
1027  | 0  |     if (style->stripSpaces != NULL)  | 
1028  | 0  |         xmlHashFree(style->stripSpaces, NULL);  | 
1029  | 0  |     if (style->nsHash != NULL)  | 
1030  | 0  |         xmlHashFree(style->nsHash, NULL);  | 
1031  | 0  |     if (style->exclPrefixTab != NULL)  | 
1032  | 0  |         xmlFree(style->exclPrefixTab);  | 
1033  | 0  |     if (style->method != NULL)  | 
1034  | 0  |         xmlFree(style->method);  | 
1035  | 0  |     if (style->methodURI != NULL)  | 
1036  | 0  |         xmlFree(style->methodURI);  | 
1037  | 0  |     if (style->version != NULL)  | 
1038  | 0  |         xmlFree(style->version);  | 
1039  | 0  |     if (style->encoding != NULL)  | 
1040  | 0  |         xmlFree(style->encoding);  | 
1041  | 0  |     if (style->doctypePublic != NULL)  | 
1042  | 0  |         xmlFree(style->doctypePublic);  | 
1043  | 0  |     if (style->doctypeSystem != NULL)  | 
1044  | 0  |         xmlFree(style->doctypeSystem);  | 
1045  | 0  |     if (style->mediaType != NULL)  | 
1046  | 0  |         xmlFree(style->mediaType);  | 
1047  | 0  |     if (style->attVTs)  | 
1048  | 0  |         xsltFreeAVTList(style->attVTs);  | 
1049  | 0  |     if (style->imports != NULL)  | 
1050  | 0  |         xsltFreeStylesheetList(style->imports);  | 
1051  |  | 
  | 
1052  |  | #ifdef XSLT_REFACTORED  | 
1053  |  |     /*  | 
1054  |  |     * If this is the principal stylesheet, then  | 
1055  |  |     * free its internal data.  | 
1056  |  |     */  | 
1057  |  |     if (style->principal == style) { | 
1058  |  |   if (style->principalData) { | 
1059  |  |       xsltFreePrincipalStylesheetData(style->principalData);  | 
1060  |  |       style->principalData = NULL;  | 
1061  |  |   }  | 
1062  |  |     }  | 
1063  |  | #endif  | 
1064  |  |     /*  | 
1065  |  |     * Better to free the main document of this stylesheet level  | 
1066  |  |     * at the end - so here.  | 
1067  |  |     */  | 
1068  | 0  |     if (style->doc != NULL) { | 
1069  | 0  |         xmlFreeDoc(style->doc);  | 
1070  | 0  |     }  | 
1071  |  | 
  | 
1072  |  | #ifdef WITH_XSLT_DEBUG  | 
1073  |  |     xsltGenericDebug(xsltGenericDebugContext,  | 
1074  |  |                      "freeing dictionary from stylesheet\n");  | 
1075  |  | #endif  | 
1076  | 0  |     xmlDictFree(style->dict);  | 
1077  |  | 
  | 
1078  | 0  |     if (style->xpathCtxt != NULL)  | 
1079  | 0  |   xmlXPathFreeContext(style->xpathCtxt);  | 
1080  |  | 
  | 
1081  | 0  |     memset(style, -1, sizeof(xsltStylesheet));  | 
1082  | 0  |     xmlFree(style);  | 
1083  | 0  | }  | 
1084  |  |  | 
1085  |  | /************************************************************************  | 
1086  |  |  *                  *  | 
1087  |  |  *    Parsing of an XSLT Stylesheet       *  | 
1088  |  |  *                  *  | 
1089  |  |  ************************************************************************/  | 
1090  |  |  | 
1091  |  | #ifdef XSLT_REFACTORED  | 
1092  |  |     /*  | 
1093  |  |     * This is now performed in an optimized way in xsltParseXSLTTemplate.  | 
1094  |  |     */  | 
1095  |  | #else  | 
1096  |  | /**  | 
1097  |  |  * xsltGetInheritedNsList:  | 
1098  |  |  * @style:  the stylesheet  | 
1099  |  |  * @template: the template  | 
1100  |  |  * @node:  the current node  | 
1101  |  |  *  | 
1102  |  |  * Search all the namespace applying to a given element except the ones  | 
1103  |  |  * from excluded output prefixes currently in scope. Initialize the  | 
1104  |  |  * template inheritedNs list with it.  | 
1105  |  |  *  | 
1106  |  |  * Returns the number of entries found  | 
1107  |  |  */  | 
1108  |  | static int  | 
1109  |  | xsltGetInheritedNsList(xsltStylesheetPtr style,  | 
1110  |  |                  xsltTemplatePtr template,  | 
1111  |  |                  xmlNodePtr node)  | 
1112  | 0  | { | 
1113  | 0  |     xmlNsPtr cur;  | 
1114  | 0  |     xmlNsPtr *ret = NULL;  | 
1115  | 0  |     int nbns = 0;  | 
1116  | 0  |     int maxns = 10;  | 
1117  | 0  |     int i;  | 
1118  |  | 
  | 
1119  | 0  |     if ((style == NULL) || (template == NULL) || (node == NULL) ||  | 
1120  | 0  |   (template->inheritedNsNr != 0) || (template->inheritedNs != NULL))  | 
1121  | 0  |   return(0);  | 
1122  | 0  |     while (node != NULL) { | 
1123  | 0  |         if (node->type == XML_ELEMENT_NODE) { | 
1124  | 0  |             cur = node->nsDef;  | 
1125  | 0  |             while (cur != NULL) { | 
1126  | 0  |     if (xmlStrEqual(cur->href, XSLT_NAMESPACE))  | 
1127  | 0  |         goto skip_ns;  | 
1128  |  |  | 
1129  | 0  |     if ((cur->prefix != NULL) &&  | 
1130  | 0  |         (xsltCheckExtPrefix(style, cur->prefix)))  | 
1131  | 0  |         goto skip_ns;  | 
1132  |  |     /*  | 
1133  |  |     * Check if this namespace was excluded.  | 
1134  |  |     * Note that at this point only the exclusions defined  | 
1135  |  |     * on the topmost stylesheet element are in the exclusion-list.  | 
1136  |  |     */  | 
1137  | 0  |     for (i = 0;i < style->exclPrefixNr;i++) { | 
1138  | 0  |         if (xmlStrEqual(cur->href, style->exclPrefixTab[i]))  | 
1139  | 0  |       goto skip_ns;  | 
1140  | 0  |     }  | 
1141  | 0  |                 if (ret == NULL) { | 
1142  | 0  |                     ret =  | 
1143  | 0  |                         (xmlNsPtr *) xmlMalloc((maxns + 1) *  | 
1144  | 0  |                                                sizeof(xmlNsPtr));  | 
1145  | 0  |                     if (ret == NULL) { | 
1146  | 0  |                         xmlGenericError(xmlGenericErrorContext,  | 
1147  | 0  |                                         "xsltGetInheritedNsList : out of memory!\n");  | 
1148  | 0  |                         return(0);  | 
1149  | 0  |                     }  | 
1150  | 0  |                     ret[nbns] = NULL;  | 
1151  | 0  |                 }  | 
1152  |  |     /*  | 
1153  |  |     * Skip shadowed namespace bindings.  | 
1154  |  |     */  | 
1155  | 0  |                 for (i = 0; i < nbns; i++) { | 
1156  | 0  |                     if ((cur->prefix == ret[i]->prefix) ||  | 
1157  | 0  |                         (xmlStrEqual(cur->prefix, ret[i]->prefix)))  | 
1158  | 0  |                         break;  | 
1159  | 0  |                 }  | 
1160  | 0  |                 if (i >= nbns) { | 
1161  | 0  |                     if (nbns >= maxns) { | 
1162  | 0  |                         maxns *= 2;  | 
1163  | 0  |                         ret = (xmlNsPtr *) xmlRealloc(ret,  | 
1164  | 0  |                                                       (maxns +  | 
1165  | 0  |                                                        1) *  | 
1166  | 0  |                                                       sizeof(xmlNsPtr));  | 
1167  | 0  |                         if (ret == NULL) { | 
1168  | 0  |                             xmlGenericError(xmlGenericErrorContext,  | 
1169  | 0  |                                             "xsltGetInheritedNsList : realloc failed!\n");  | 
1170  | 0  |                             return(0);  | 
1171  | 0  |                         }  | 
1172  | 0  |                     }  | 
1173  | 0  |                     ret[nbns++] = cur;  | 
1174  | 0  |                     ret[nbns] = NULL;  | 
1175  | 0  |                 }  | 
1176  | 0  | skip_ns:  | 
1177  | 0  |                 cur = cur->next;  | 
1178  | 0  |             }  | 
1179  | 0  |         }  | 
1180  | 0  |         node = node->parent;  | 
1181  | 0  |     }  | 
1182  | 0  |     if (nbns != 0) { | 
1183  |  | #ifdef WITH_XSLT_DEBUG_PARSING  | 
1184  |  |         xsltGenericDebug(xsltGenericDebugContext,  | 
1185  |  |                          "template has %d inherited namespaces\n", nbns);  | 
1186  |  | #endif  | 
1187  | 0  |   template->inheritedNsNr = nbns;  | 
1188  | 0  |   template->inheritedNs = ret;  | 
1189  | 0  |     }  | 
1190  | 0  |     return (nbns);  | 
1191  | 0  | }  | 
1192  |  | #endif /* else of XSLT_REFACTORED */  | 
1193  |  |  | 
1194  |  | /**  | 
1195  |  |  * xsltParseStylesheetOutput:  | 
1196  |  |  * @style:  the XSLT stylesheet  | 
1197  |  |  * @cur:  the "output" element  | 
1198  |  |  *  | 
1199  |  |  * parse an XSLT stylesheet output element and record  | 
1200  |  |  * information related to the stylesheet output  | 
1201  |  |  */  | 
1202  |  |  | 
1203  |  | void  | 
1204  |  | xsltParseStylesheetOutput(xsltStylesheetPtr style, xmlNodePtr cur)  | 
1205  | 0  | { | 
1206  | 0  |     xmlChar *elements,  | 
1207  | 0  |      *prop;  | 
1208  | 0  |     xmlChar *element,  | 
1209  | 0  |      *end;  | 
1210  |  | 
  | 
1211  | 0  |     if ((cur == NULL) || (style == NULL) || (cur->type != XML_ELEMENT_NODE))  | 
1212  | 0  |         return;  | 
1213  |  |  | 
1214  | 0  |     prop = xmlGetNsProp(cur, (const xmlChar *) "version", NULL);  | 
1215  | 0  |     if (prop != NULL) { | 
1216  | 0  |         if (style->version != NULL)  | 
1217  | 0  |             xmlFree(style->version);  | 
1218  | 0  |         style->version = prop;  | 
1219  | 0  |     }  | 
1220  |  | 
  | 
1221  | 0  |     prop = xmlGetNsProp(cur, (const xmlChar *) "encoding", NULL);  | 
1222  | 0  |     if (prop != NULL) { | 
1223  | 0  |         if (style->encoding != NULL)  | 
1224  | 0  |             xmlFree(style->encoding);  | 
1225  | 0  |         style->encoding = prop;  | 
1226  | 0  |     }  | 
1227  |  |  | 
1228  |  |     /* relaxed to support xt:document  | 
1229  |  |     * TODO KB: What does "relaxed to support xt:document" mean?  | 
1230  |  |     */  | 
1231  | 0  |     prop = xmlGetNsProp(cur, (const xmlChar *) "method", NULL);  | 
1232  | 0  |     if (prop != NULL) { | 
1233  | 0  |         const xmlChar *URI;  | 
1234  |  | 
  | 
1235  | 0  |         if (style->method != NULL)  | 
1236  | 0  |             xmlFree(style->method);  | 
1237  | 0  |         style->method = NULL;  | 
1238  | 0  |         if (style->methodURI != NULL)  | 
1239  | 0  |             xmlFree(style->methodURI);  | 
1240  | 0  |         style->methodURI = NULL;  | 
1241  |  |  | 
1242  |  |   /*  | 
1243  |  |   * TODO: Don't use xsltGetQNameURI().  | 
1244  |  |   */  | 
1245  | 0  |   URI = xsltGetQNameURI(cur, &prop);  | 
1246  | 0  |   if (prop == NULL) { | 
1247  | 0  |       if (style != NULL) style->errors++;  | 
1248  | 0  |   } else if (URI == NULL) { | 
1249  | 0  |             if ((xmlStrEqual(prop, (const xmlChar *) "xml")) ||  | 
1250  | 0  |                 (xmlStrEqual(prop, (const xmlChar *) "html")) ||  | 
1251  | 0  |                 (xmlStrEqual(prop, (const xmlChar *) "text"))) { | 
1252  | 0  |                 style->method = prop;  | 
1253  | 0  |             } else { | 
1254  | 0  |     xsltTransformError(NULL, style, cur,  | 
1255  | 0  |                                  "invalid value for method: %s\n", prop);  | 
1256  | 0  |                 if (style != NULL) style->warnings++;  | 
1257  | 0  |                 xmlFree(prop);  | 
1258  | 0  |             }  | 
1259  | 0  |   } else { | 
1260  | 0  |       style->method = prop;  | 
1261  | 0  |       style->methodURI = xmlStrdup(URI);  | 
1262  | 0  |   }  | 
1263  | 0  |     }  | 
1264  |  | 
  | 
1265  | 0  |     prop = xmlGetNsProp(cur, (const xmlChar *) "doctype-system", NULL);  | 
1266  | 0  |     if (prop != NULL) { | 
1267  | 0  |         if (style->doctypeSystem != NULL)  | 
1268  | 0  |             xmlFree(style->doctypeSystem);  | 
1269  | 0  |         style->doctypeSystem = prop;  | 
1270  | 0  |     }  | 
1271  |  | 
  | 
1272  | 0  |     prop = xmlGetNsProp(cur, (const xmlChar *) "doctype-public", NULL);  | 
1273  | 0  |     if (prop != NULL) { | 
1274  | 0  |         if (style->doctypePublic != NULL)  | 
1275  | 0  |             xmlFree(style->doctypePublic);  | 
1276  | 0  |         style->doctypePublic = prop;  | 
1277  | 0  |     }  | 
1278  |  | 
  | 
1279  | 0  |     prop = xmlGetNsProp(cur, (const xmlChar *) "standalone", NULL);  | 
1280  | 0  |     if (prop != NULL) { | 
1281  | 0  |         if (xmlStrEqual(prop, (const xmlChar *) "yes")) { | 
1282  | 0  |             style->standalone = 1;  | 
1283  | 0  |         } else if (xmlStrEqual(prop, (const xmlChar *) "no")) { | 
1284  | 0  |             style->standalone = 0;  | 
1285  | 0  |         } else { | 
1286  | 0  |       xsltTransformError(NULL, style, cur,  | 
1287  | 0  |                              "invalid value for standalone: %s\n", prop);  | 
1288  | 0  |             style->errors++;  | 
1289  | 0  |         }  | 
1290  | 0  |         xmlFree(prop);  | 
1291  | 0  |     }  | 
1292  |  | 
  | 
1293  | 0  |     prop = xmlGetNsProp(cur, (const xmlChar *) "indent", NULL);  | 
1294  | 0  |     if (prop != NULL) { | 
1295  | 0  |         if (xmlStrEqual(prop, (const xmlChar *) "yes")) { | 
1296  | 0  |             style->indent = 1;  | 
1297  | 0  |         } else if (xmlStrEqual(prop, (const xmlChar *) "no")) { | 
1298  | 0  |             style->indent = 0;  | 
1299  | 0  |         } else { | 
1300  | 0  |       xsltTransformError(NULL, style, cur,  | 
1301  | 0  |                              "invalid value for indent: %s\n", prop);  | 
1302  | 0  |             style->errors++;  | 
1303  | 0  |         }  | 
1304  | 0  |         xmlFree(prop);  | 
1305  | 0  |     }  | 
1306  |  | 
  | 
1307  | 0  |     prop = xmlGetNsProp(cur, (const xmlChar *) "omit-xml-declaration", NULL);  | 
1308  | 0  |     if (prop != NULL) { | 
1309  | 0  |         if (xmlStrEqual(prop, (const xmlChar *) "yes")) { | 
1310  | 0  |             style->omitXmlDeclaration = 1;  | 
1311  | 0  |         } else if (xmlStrEqual(prop, (const xmlChar *) "no")) { | 
1312  | 0  |             style->omitXmlDeclaration = 0;  | 
1313  | 0  |         } else { | 
1314  | 0  |       xsltTransformError(NULL, style, cur,  | 
1315  | 0  |                              "invalid value for omit-xml-declaration: %s\n",  | 
1316  | 0  |                              prop);  | 
1317  | 0  |             style->errors++;  | 
1318  | 0  |         }  | 
1319  | 0  |         xmlFree(prop);  | 
1320  | 0  |     }  | 
1321  |  | 
  | 
1322  | 0  |     elements = xmlGetNsProp(cur, (const xmlChar *) "cdata-section-elements",  | 
1323  | 0  |   NULL);  | 
1324  | 0  |     if (elements != NULL) { | 
1325  | 0  |         if (style->cdataSection == NULL)  | 
1326  | 0  |             style->cdataSection = xmlHashCreate(10);  | 
1327  | 0  |         if (style->cdataSection == NULL)  | 
1328  | 0  |             return;  | 
1329  |  |  | 
1330  | 0  |         element = elements;  | 
1331  | 0  |         while (*element != 0) { | 
1332  | 0  |             while (IS_BLANK(*element))  | 
1333  | 0  |                 element++;  | 
1334  | 0  |             if (*element == 0)  | 
1335  | 0  |                 break;  | 
1336  | 0  |             end = element;  | 
1337  | 0  |             while ((*end != 0) && (!IS_BLANK(*end)))  | 
1338  | 0  |                 end++;  | 
1339  | 0  |             element = xmlStrndup(element, end - element);  | 
1340  | 0  |             if (element) { | 
1341  |  | #ifdef WITH_XSLT_DEBUG_PARSING  | 
1342  |  |                 xsltGenericDebug(xsltGenericDebugContext,  | 
1343  |  |                                  "add cdata section output element %s\n",  | 
1344  |  |                                  element);  | 
1345  |  | #endif  | 
1346  | 0  |     if (xmlValidateQName(BAD_CAST element, 0) != 0) { | 
1347  | 0  |         xsltTransformError(NULL, style, cur,  | 
1348  | 0  |       "Attribute 'cdata-section-elements': The value "  | 
1349  | 0  |       "'%s' is not a valid QName.\n", element);  | 
1350  | 0  |         xmlFree(element);  | 
1351  | 0  |         style->errors++;  | 
1352  | 0  |     } else { | 
1353  | 0  |         const xmlChar *URI;  | 
1354  |  |  | 
1355  |  |         /*  | 
1356  |  |         * TODO: Don't use xsltGetQNameURI().  | 
1357  |  |         */  | 
1358  | 0  |         URI = xsltGetQNameURI(cur, &element);  | 
1359  | 0  |         if (element == NULL) { | 
1360  |  |       /*  | 
1361  |  |       * TODO: We'll report additionally an error  | 
1362  |  |       *  via the stylesheet's error handling.  | 
1363  |  |       */  | 
1364  | 0  |       xsltTransformError(NULL, style, cur,  | 
1365  | 0  |           "Attribute 'cdata-section-elements': "  | 
1366  | 0  |           "Not a valid QName.\n");  | 
1367  | 0  |       style->errors++;  | 
1368  | 0  |         } else { | 
1369  | 0  |       xmlNsPtr ns;  | 
1370  |  |  | 
1371  |  |       /*  | 
1372  |  |       * XSLT-1.0 "Each QName is expanded into an  | 
1373  |  |       *  expanded-name using the namespace declarations in  | 
1374  |  |       *  effect on the xsl:output element in which the QName  | 
1375  |  |       *  occurs; if there is a default namespace, it is used  | 
1376  |  |       *  for QNames that do not have a prefix"  | 
1377  |  |       * NOTE: Fix of bug #339570.  | 
1378  |  |       */  | 
1379  | 0  |       if (URI == NULL) { | 
1380  | 0  |           ns = xmlSearchNs(style->doc, cur, NULL);  | 
1381  | 0  |           if (ns != NULL)  | 
1382  | 0  |         URI = ns->href;  | 
1383  | 0  |       }  | 
1384  | 0  |       xmlHashAddEntry2(style->cdataSection, element, URI,  | 
1385  | 0  |           (void *) "cdata");  | 
1386  | 0  |       xmlFree(element);  | 
1387  | 0  |         }  | 
1388  | 0  |     }  | 
1389  | 0  |             }  | 
1390  | 0  |             element = end;  | 
1391  | 0  |         }  | 
1392  | 0  |         xmlFree(elements);  | 
1393  | 0  |     }  | 
1394  |  |  | 
1395  | 0  |     prop = xmlGetNsProp(cur, (const xmlChar *) "media-type", NULL);  | 
1396  | 0  |     if (prop != NULL) { | 
1397  | 0  |   if (style->mediaType)  | 
1398  | 0  |       xmlFree(style->mediaType);  | 
1399  | 0  |   style->mediaType = prop;  | 
1400  | 0  |     }  | 
1401  | 0  |     if (cur->children != NULL) { | 
1402  | 0  |   xsltParseContentError(style, cur->children);  | 
1403  | 0  |     }  | 
1404  | 0  | }  | 
1405  |  |  | 
1406  |  | /**  | 
1407  |  |  * xsltParseStylesheetDecimalFormat:  | 
1408  |  |  * @style:  the XSLT stylesheet  | 
1409  |  |  * @cur:  the "decimal-format" element  | 
1410  |  |  *  | 
1411  |  |  * <!-- Category: top-level-element -->  | 
1412  |  |  * <xsl:decimal-format  | 
1413  |  |  *   name = qname, decimal-separator = char, grouping-separator = char,  | 
1414  |  |  *   infinity = string, minus-sign = char, NaN = string, percent = char  | 
1415  |  |  *   per-mille = char, zero-digit = char, digit = char,  | 
1416  |  |  * pattern-separator = char />  | 
1417  |  |  *  | 
1418  |  |  * parse an XSLT stylesheet decimal-format element and  | 
1419  |  |  * and record the formatting characteristics  | 
1420  |  |  */  | 
1421  |  | static void  | 
1422  |  | xsltParseStylesheetDecimalFormat(xsltStylesheetPtr style, xmlNodePtr cur)  | 
1423  | 0  | { | 
1424  | 0  |     xmlChar *prop;  | 
1425  | 0  |     xsltDecimalFormatPtr format;  | 
1426  | 0  |     xsltDecimalFormatPtr iter;  | 
1427  |  | 
  | 
1428  | 0  |     if ((cur == NULL) || (style == NULL) || (cur->type != XML_ELEMENT_NODE))  | 
1429  | 0  |   return;  | 
1430  |  |  | 
1431  | 0  |     format = style->decimalFormat;  | 
1432  |  | 
  | 
1433  | 0  |     prop = xmlGetNsProp(cur, BAD_CAST("name"), NULL); | 
1434  | 0  |     if (prop != NULL) { | 
1435  | 0  |         const xmlChar *nsUri;  | 
1436  |  | 
  | 
1437  | 0  |         if (xmlValidateQName(prop, 0) != 0) { | 
1438  | 0  |             xsltTransformError(NULL, style, cur,  | 
1439  | 0  |                 "xsl:decimal-format: Invalid QName '%s'.\n", prop);  | 
1440  | 0  |       style->warnings++;  | 
1441  | 0  |             xmlFree(prop);  | 
1442  | 0  |             return;  | 
1443  | 0  |         }  | 
1444  |  |         /*  | 
1445  |  |         * TODO: Don't use xsltGetQNameURI().  | 
1446  |  |         */  | 
1447  | 0  |         nsUri = xsltGetQNameURI(cur, &prop);  | 
1448  | 0  |         if (prop == NULL) { | 
1449  | 0  |       style->warnings++;  | 
1450  | 0  |             return;  | 
1451  | 0  |         }  | 
1452  | 0  |   format = xsltDecimalFormatGetByQName(style, nsUri, prop);  | 
1453  | 0  |   if (format != NULL) { | 
1454  | 0  |       xsltTransformError(NULL, style, cur,  | 
1455  | 0  |    "xsltParseStylestyleDecimalFormat: %s already exists\n", prop);  | 
1456  | 0  |       style->warnings++;  | 
1457  | 0  |             xmlFree(prop);  | 
1458  | 0  |       return;  | 
1459  | 0  |   }  | 
1460  | 0  |   format = xsltNewDecimalFormat(nsUri, prop);  | 
1461  | 0  |   if (format == NULL) { | 
1462  | 0  |       xsltTransformError(NULL, style, cur,  | 
1463  | 0  |      "xsltParseStylestyleDecimalFormat: failed creating new decimal-format\n");  | 
1464  | 0  |       style->errors++;  | 
1465  | 0  |             xmlFree(prop);  | 
1466  | 0  |       return;  | 
1467  | 0  |   }  | 
1468  |  |   /* Append new decimal-format structure */  | 
1469  | 0  |   for (iter = style->decimalFormat; iter->next; iter = iter->next)  | 
1470  | 0  |       ;  | 
1471  | 0  |   if (iter)  | 
1472  | 0  |       iter->next = format;  | 
1473  | 0  |     }  | 
1474  |  |  | 
1475  | 0  |     prop = xmlGetNsProp(cur, (const xmlChar *)"decimal-separator", NULL);  | 
1476  | 0  |     if (prop != NULL) { | 
1477  | 0  |   if (format->decimalPoint != NULL) xmlFree(format->decimalPoint);  | 
1478  | 0  |   format->decimalPoint  = prop;  | 
1479  | 0  |     }  | 
1480  |  | 
  | 
1481  | 0  |     prop = xmlGetNsProp(cur, (const xmlChar *)"grouping-separator", NULL);  | 
1482  | 0  |     if (prop != NULL) { | 
1483  | 0  |   if (format->grouping != NULL) xmlFree(format->grouping);  | 
1484  | 0  |   format->grouping  = prop;  | 
1485  | 0  |     }  | 
1486  |  | 
  | 
1487  | 0  |     prop = xmlGetNsProp(cur, (const xmlChar *)"infinity", NULL);  | 
1488  | 0  |     if (prop != NULL) { | 
1489  | 0  |   if (format->infinity != NULL) xmlFree(format->infinity);  | 
1490  | 0  |   format->infinity  = prop;  | 
1491  | 0  |     }  | 
1492  |  | 
  | 
1493  | 0  |     prop = xmlGetNsProp(cur, (const xmlChar *)"minus-sign", NULL);  | 
1494  | 0  |     if (prop != NULL) { | 
1495  | 0  |   if (format->minusSign != NULL) xmlFree(format->minusSign);  | 
1496  | 0  |   format->minusSign  = prop;  | 
1497  | 0  |     }  | 
1498  |  | 
  | 
1499  | 0  |     prop = xmlGetNsProp(cur, (const xmlChar *)"NaN", NULL);  | 
1500  | 0  |     if (prop != NULL) { | 
1501  | 0  |   if (format->noNumber != NULL) xmlFree(format->noNumber);  | 
1502  | 0  |   format->noNumber  = prop;  | 
1503  | 0  |     }  | 
1504  |  | 
  | 
1505  | 0  |     prop = xmlGetNsProp(cur, (const xmlChar *)"percent", NULL);  | 
1506  | 0  |     if (prop != NULL) { | 
1507  | 0  |   if (format->percent != NULL) xmlFree(format->percent);  | 
1508  | 0  |   format->percent  = prop;  | 
1509  | 0  |     }  | 
1510  |  | 
  | 
1511  | 0  |     prop = xmlGetNsProp(cur, (const xmlChar *)"per-mille", NULL);  | 
1512  | 0  |     if (prop != NULL) { | 
1513  | 0  |   if (format->permille != NULL) xmlFree(format->permille);  | 
1514  | 0  |   format->permille  = prop;  | 
1515  | 0  |     }  | 
1516  |  | 
  | 
1517  | 0  |     prop = xmlGetNsProp(cur, (const xmlChar *)"zero-digit", NULL);  | 
1518  | 0  |     if (prop != NULL) { | 
1519  | 0  |   if (format->zeroDigit != NULL) xmlFree(format->zeroDigit);  | 
1520  | 0  |   format->zeroDigit  = prop;  | 
1521  | 0  |     }  | 
1522  |  | 
  | 
1523  | 0  |     prop = xmlGetNsProp(cur, (const xmlChar *)"digit", NULL);  | 
1524  | 0  |     if (prop != NULL) { | 
1525  | 0  |   if (format->digit != NULL) xmlFree(format->digit);  | 
1526  | 0  |   format->digit  = prop;  | 
1527  | 0  |     }  | 
1528  |  | 
  | 
1529  | 0  |     prop = xmlGetNsProp(cur, (const xmlChar *)"pattern-separator", NULL);  | 
1530  | 0  |     if (prop != NULL) { | 
1531  | 0  |   if (format->patternSeparator != NULL) xmlFree(format->patternSeparator);  | 
1532  | 0  |   format->patternSeparator  = prop;  | 
1533  | 0  |     }  | 
1534  | 0  |     if (cur->children != NULL) { | 
1535  | 0  |   xsltParseContentError(style, cur->children);  | 
1536  | 0  |     }  | 
1537  | 0  | }  | 
1538  |  |  | 
1539  |  | /**  | 
1540  |  |  * xsltParseStylesheetPreserveSpace:  | 
1541  |  |  * @style:  the XSLT stylesheet  | 
1542  |  |  * @cur:  the "preserve-space" element  | 
1543  |  |  *  | 
1544  |  |  * parse an XSLT stylesheet preserve-space element and record  | 
1545  |  |  * elements needing preserving  | 
1546  |  |  */  | 
1547  |  |  | 
1548  |  | static void  | 
1549  | 0  | xsltParseStylesheetPreserveSpace(xsltStylesheetPtr style, xmlNodePtr cur) { | 
1550  | 0  |     xmlChar *elements;  | 
1551  | 0  |     xmlChar *element, *end;  | 
1552  |  | 
  | 
1553  | 0  |     if ((cur == NULL) || (style == NULL) || (cur->type != XML_ELEMENT_NODE))  | 
1554  | 0  |   return;  | 
1555  |  |  | 
1556  | 0  |     elements = xmlGetNsProp(cur, (const xmlChar *)"elements", NULL);  | 
1557  | 0  |     if (elements == NULL) { | 
1558  | 0  |   xsltTransformError(NULL, style, cur,  | 
1559  | 0  |       "xsltParseStylesheetPreserveSpace: missing elements attribute\n");  | 
1560  | 0  |   if (style != NULL) style->warnings++;  | 
1561  | 0  |   return;  | 
1562  | 0  |     }  | 
1563  |  |  | 
1564  | 0  |     if (style->stripSpaces == NULL)  | 
1565  | 0  |   style->stripSpaces = xmlHashCreate(10);  | 
1566  | 0  |     if (style->stripSpaces == NULL)  | 
1567  | 0  |   return;  | 
1568  |  |  | 
1569  | 0  |     element = elements;  | 
1570  | 0  |     while (*element != 0) { | 
1571  | 0  |   while (IS_BLANK(*element)) element++;  | 
1572  | 0  |   if (*element == 0)  | 
1573  | 0  |       break;  | 
1574  | 0  |         end = element;  | 
1575  | 0  |   while ((*end != 0) && (!IS_BLANK(*end))) end++;  | 
1576  | 0  |   element = xmlStrndup(element, end - element);  | 
1577  | 0  |   if (element) { | 
1578  |  | #ifdef WITH_XSLT_DEBUG_PARSING  | 
1579  |  |       xsltGenericDebug(xsltGenericDebugContext,  | 
1580  |  |     "add preserved space element %s\n", element);  | 
1581  |  | #endif  | 
1582  | 0  |       if (xmlStrEqual(element, (const xmlChar *)"*")) { | 
1583  | 0  |     style->stripAll = -1;  | 
1584  | 0  |       } else { | 
1585  | 0  |     const xmlChar *URI;  | 
1586  |  |  | 
1587  |  |     /*  | 
1588  |  |     * TODO: Don't use xsltGetQNameURI().  | 
1589  |  |     */  | 
1590  | 0  |                 URI = xsltGetQNameURI(cur, &element);  | 
1591  |  | 
  | 
1592  | 0  |     xmlHashAddEntry2(style->stripSpaces, element, URI,  | 
1593  | 0  |         (xmlChar *) "preserve");  | 
1594  | 0  |       }  | 
1595  | 0  |       xmlFree(element);  | 
1596  | 0  |   }  | 
1597  | 0  |   element = end;  | 
1598  | 0  |     }  | 
1599  | 0  |     xmlFree(elements);  | 
1600  | 0  |     if (cur->children != NULL) { | 
1601  | 0  |   xsltParseContentError(style, cur->children);  | 
1602  | 0  |     }  | 
1603  | 0  | }  | 
1604  |  |  | 
1605  |  | #ifdef XSLT_REFACTORED  | 
1606  |  | #else  | 
1607  |  | /**  | 
1608  |  |  * xsltParseStylesheetExtPrefix:  | 
1609  |  |  * @style:  the XSLT stylesheet  | 
1610  |  |  * @template:  the "extension-element-prefixes" prefix  | 
1611  |  |  *  | 
1612  |  |  * parse an XSLT stylesheet's "extension-element-prefix" attribute value  | 
1613  |  |  * and register the namespaces of extension instruction.  | 
1614  |  |  * SPEC "A namespace is designated as an extension namespace by using  | 
1615  |  |  *   an extension-element-prefixes attribute on:  | 
1616  |  |  *   1) an xsl:stylesheet element  | 
1617  |  |  *   2) an xsl:extension-element-prefixes attribute on a  | 
1618  |  |  *      literal result element  | 
1619  |  |  *   3) an extension instruction."  | 
1620  |  |  */  | 
1621  |  | static void  | 
1622  |  | xsltParseStylesheetExtPrefix(xsltStylesheetPtr style, xmlNodePtr cur,  | 
1623  | 0  |            int isXsltElem) { | 
1624  | 0  |     xmlChar *prefixes;  | 
1625  | 0  |     xmlChar *prefix, *end;  | 
1626  |  | 
  | 
1627  | 0  |     if ((cur == NULL) || (style == NULL) || (cur->type != XML_ELEMENT_NODE))  | 
1628  | 0  |   return;  | 
1629  |  |  | 
1630  | 0  |     if (isXsltElem) { | 
1631  |  |   /* For xsl:stylesheet/xsl:transform. */  | 
1632  | 0  |   prefixes = xmlGetNsProp(cur,  | 
1633  | 0  |       (const xmlChar *)"extension-element-prefixes", NULL);  | 
1634  | 0  |     } else { | 
1635  |  |   /* For literal result elements and extension instructions. */  | 
1636  | 0  |   prefixes = xmlGetNsProp(cur,  | 
1637  | 0  |       (const xmlChar *)"extension-element-prefixes", XSLT_NAMESPACE);  | 
1638  | 0  |     }  | 
1639  | 0  |     if (prefixes == NULL) { | 
1640  | 0  |   return;  | 
1641  | 0  |     }  | 
1642  |  |  | 
1643  | 0  |     prefix = prefixes;  | 
1644  | 0  |     while (*prefix != 0) { | 
1645  | 0  |   while (IS_BLANK(*prefix)) prefix++;  | 
1646  | 0  |   if (*prefix == 0)  | 
1647  | 0  |       break;  | 
1648  | 0  |         end = prefix;  | 
1649  | 0  |   while ((*end != 0) && (!IS_BLANK(*end))) end++;  | 
1650  | 0  |   prefix = xmlStrndup(prefix, end - prefix);  | 
1651  | 0  |   if (prefix) { | 
1652  | 0  |       xmlNsPtr ns;  | 
1653  |  | 
  | 
1654  | 0  |       if (xmlStrEqual(prefix, (const xmlChar *)"#default"))  | 
1655  | 0  |     ns = xmlSearchNs(style->doc, cur, NULL);  | 
1656  | 0  |       else  | 
1657  | 0  |     ns = xmlSearchNs(style->doc, cur, prefix);  | 
1658  | 0  |       if (ns == NULL) { | 
1659  | 0  |     xsltTransformError(NULL, style, cur,  | 
1660  | 0  |       "xsl:extension-element-prefix : undefined namespace %s\n",  | 
1661  | 0  |                            prefix);  | 
1662  | 0  |     if (style != NULL) style->warnings++;  | 
1663  | 0  |       } else { | 
1664  |  | #ifdef WITH_XSLT_DEBUG_PARSING  | 
1665  |  |     xsltGenericDebug(xsltGenericDebugContext,  | 
1666  |  |         "add extension prefix %s\n", prefix);  | 
1667  |  | #endif  | 
1668  | 0  |     xsltRegisterExtPrefix(style, prefix, ns->href);  | 
1669  | 0  |       }  | 
1670  | 0  |       xmlFree(prefix);  | 
1671  | 0  |   }  | 
1672  | 0  |   prefix = end;  | 
1673  | 0  |     }  | 
1674  | 0  |     xmlFree(prefixes);  | 
1675  | 0  | }  | 
1676  |  | #endif /* else of XSLT_REFACTORED */  | 
1677  |  |  | 
1678  |  | /**  | 
1679  |  |  * xsltParseStylesheetStripSpace:  | 
1680  |  |  * @style:  the XSLT stylesheet  | 
1681  |  |  * @cur:  the "strip-space" element  | 
1682  |  |  *  | 
1683  |  |  * parse an XSLT stylesheet's strip-space element and record  | 
1684  |  |  * the elements needing stripping  | 
1685  |  |  */  | 
1686  |  |  | 
1687  |  | static void  | 
1688  | 0  | xsltParseStylesheetStripSpace(xsltStylesheetPtr style, xmlNodePtr cur) { | 
1689  | 0  |     xmlChar *elements;  | 
1690  | 0  |     xmlChar *element, *end;  | 
1691  |  | 
  | 
1692  | 0  |     if ((cur == NULL) || (style == NULL) || (cur->type != XML_ELEMENT_NODE))  | 
1693  | 0  |   return;  | 
1694  |  |  | 
1695  | 0  |     elements = xmlGetNsProp(cur, (const xmlChar *)"elements", NULL);  | 
1696  | 0  |     if (elements == NULL) { | 
1697  | 0  |   xsltTransformError(NULL, style, cur,  | 
1698  | 0  |       "xsltParseStylesheetStripSpace: missing elements attribute\n");  | 
1699  | 0  |   if (style != NULL) style->warnings++;  | 
1700  | 0  |   return;  | 
1701  | 0  |     }  | 
1702  |  |  | 
1703  | 0  |     if (style->stripSpaces == NULL)  | 
1704  | 0  |   style->stripSpaces = xmlHashCreate(10);  | 
1705  | 0  |     if (style->stripSpaces == NULL)  | 
1706  | 0  |   return;  | 
1707  |  |  | 
1708  | 0  |     element = elements;  | 
1709  | 0  |     while (*element != 0) { | 
1710  | 0  |   while (IS_BLANK(*element)) element++;  | 
1711  | 0  |   if (*element == 0)  | 
1712  | 0  |       break;  | 
1713  | 0  |         end = element;  | 
1714  | 0  |   while ((*end != 0) && (!IS_BLANK(*end))) end++;  | 
1715  | 0  |   element = xmlStrndup(element, end - element);  | 
1716  | 0  |   if (element) { | 
1717  |  | #ifdef WITH_XSLT_DEBUG_PARSING  | 
1718  |  |       xsltGenericDebug(xsltGenericDebugContext,  | 
1719  |  |     "add stripped space element %s\n", element);  | 
1720  |  | #endif  | 
1721  | 0  |       if (xmlStrEqual(element, (const xmlChar *)"*")) { | 
1722  | 0  |     style->stripAll = 1;  | 
1723  | 0  |       } else { | 
1724  | 0  |     const xmlChar *URI;  | 
1725  |  |  | 
1726  |  |     /*  | 
1727  |  |     * TODO: Don't use xsltGetQNameURI().  | 
1728  |  |     */  | 
1729  | 0  |                 URI = xsltGetQNameURI(cur, &element);  | 
1730  |  | 
  | 
1731  | 0  |     xmlHashAddEntry2(style->stripSpaces, element, URI,  | 
1732  | 0  |               (xmlChar *) "strip");  | 
1733  | 0  |       }  | 
1734  | 0  |       xmlFree(element);  | 
1735  | 0  |   }  | 
1736  | 0  |   element = end;  | 
1737  | 0  |     }  | 
1738  | 0  |     xmlFree(elements);  | 
1739  | 0  |     if (cur->children != NULL) { | 
1740  | 0  |   xsltParseContentError(style, cur->children);  | 
1741  | 0  |     }  | 
1742  | 0  | }  | 
1743  |  |  | 
1744  |  | #ifdef XSLT_REFACTORED  | 
1745  |  | #else  | 
1746  |  | /**  | 
1747  |  |  * xsltParseStylesheetExcludePrefix:  | 
1748  |  |  * @style:  the XSLT stylesheet  | 
1749  |  |  * @cur:  the current point in the stylesheet  | 
1750  |  |  *  | 
1751  |  |  * parse an XSLT stylesheet exclude prefix and record  | 
1752  |  |  * namespaces needing stripping  | 
1753  |  |  *  | 
1754  |  |  * Returns the number of Excluded prefixes added at that level  | 
1755  |  |  */  | 
1756  |  |  | 
1757  |  | static int  | 
1758  |  | xsltParseStylesheetExcludePrefix(xsltStylesheetPtr style, xmlNodePtr cur,  | 
1759  |  |          int isXsltElem)  | 
1760  | 0  | { | 
1761  | 0  |     int nb = 0;  | 
1762  | 0  |     xmlChar *prefixes;  | 
1763  | 0  |     xmlChar *prefix, *end;  | 
1764  |  | 
  | 
1765  | 0  |     if ((cur == NULL) || (style == NULL) || (cur->type != XML_ELEMENT_NODE))  | 
1766  | 0  |   return(0);  | 
1767  |  |  | 
1768  | 0  |     if (isXsltElem)  | 
1769  | 0  |   prefixes = xmlGetNsProp(cur,  | 
1770  | 0  |       (const xmlChar *)"exclude-result-prefixes", NULL);  | 
1771  | 0  |     else  | 
1772  | 0  |   prefixes = xmlGetNsProp(cur,  | 
1773  | 0  |       (const xmlChar *)"exclude-result-prefixes", XSLT_NAMESPACE);  | 
1774  |  | 
  | 
1775  | 0  |     if (prefixes == NULL) { | 
1776  | 0  |   return(0);  | 
1777  | 0  |     }  | 
1778  |  |  | 
1779  | 0  |     prefix = prefixes;  | 
1780  | 0  |     while (*prefix != 0) { | 
1781  | 0  |   while (IS_BLANK(*prefix)) prefix++;  | 
1782  | 0  |   if (*prefix == 0)  | 
1783  | 0  |       break;  | 
1784  | 0  |         end = prefix;  | 
1785  | 0  |   while ((*end != 0) && (!IS_BLANK(*end))) end++;  | 
1786  | 0  |   prefix = xmlStrndup(prefix, end - prefix);  | 
1787  | 0  |   if (prefix) { | 
1788  | 0  |       xmlNsPtr ns;  | 
1789  |  | 
  | 
1790  | 0  |       if (xmlStrEqual(prefix, (const xmlChar *)"#default"))  | 
1791  | 0  |     ns = xmlSearchNs(style->doc, cur, NULL);  | 
1792  | 0  |       else  | 
1793  | 0  |     ns = xmlSearchNs(style->doc, cur, prefix);  | 
1794  | 0  |       if (ns == NULL) { | 
1795  | 0  |     xsltTransformError(NULL, style, cur,  | 
1796  | 0  |       "xsl:exclude-result-prefixes : undefined namespace %s\n",  | 
1797  | 0  |                            prefix);  | 
1798  | 0  |     if (style != NULL) style->warnings++;  | 
1799  | 0  |       } else { | 
1800  | 0  |     if (exclPrefixPush(style, (xmlChar *) ns->href) >= 0) { | 
1801  |  | #ifdef WITH_XSLT_DEBUG_PARSING  | 
1802  |  |         xsltGenericDebug(xsltGenericDebugContext,  | 
1803  |  |       "exclude result prefix %s\n", prefix);  | 
1804  |  | #endif  | 
1805  | 0  |         nb++;  | 
1806  | 0  |     }  | 
1807  | 0  |       }  | 
1808  | 0  |       xmlFree(prefix);  | 
1809  | 0  |   }  | 
1810  | 0  |   prefix = end;  | 
1811  | 0  |     }  | 
1812  | 0  |     xmlFree(prefixes);  | 
1813  | 0  |     return(nb);  | 
1814  | 0  | }  | 
1815  |  | #endif /* else of XSLT_REFACTORED */  | 
1816  |  |  | 
1817  |  | #ifdef XSLT_REFACTORED  | 
1818  |  |  | 
1819  |  | /*  | 
1820  |  | * xsltTreeEnsureXMLDecl:  | 
1821  |  | * @doc: the doc  | 
1822  |  | *  | 
1823  |  | * BIG NOTE:  | 
1824  |  | *  This was copy&pasted from Libxml2's xmlTreeEnsureXMLDecl() in "tree.c".  | 
1825  |  | * Ensures that there is an XML namespace declaration on the doc.  | 
1826  |  | *  | 
1827  |  | * Returns the XML ns-struct or NULL on API and internal errors.  | 
1828  |  | */  | 
1829  |  | static xmlNsPtr  | 
1830  |  | xsltTreeEnsureXMLDecl(xmlDocPtr doc)  | 
1831  |  | { | 
1832  |  |     if (doc == NULL)  | 
1833  |  |   return (NULL);  | 
1834  |  |     if (doc->oldNs != NULL)  | 
1835  |  |   return (doc->oldNs);  | 
1836  |  |     { | 
1837  |  |   xmlNsPtr ns;  | 
1838  |  |   ns = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));  | 
1839  |  |   if (ns == NULL) { | 
1840  |  |       xmlGenericError(xmlGenericErrorContext,  | 
1841  |  |     "xsltTreeEnsureXMLDecl: Failed to allocate "  | 
1842  |  |     "the XML namespace.\n");  | 
1843  |  |       return (NULL);  | 
1844  |  |   }  | 
1845  |  |   memset(ns, 0, sizeof(xmlNs));  | 
1846  |  |   ns->type = XML_LOCAL_NAMESPACE;  | 
1847  |  |   /*  | 
1848  |  |   * URGENT TODO: revisit this.  | 
1849  |  |   */  | 
1850  |  | #ifdef LIBXML_NAMESPACE_DICT  | 
1851  |  |   if (doc->dict)  | 
1852  |  |       ns->href = xmlDictLookup(doc->dict, XML_XML_NAMESPACE, -1);  | 
1853  |  |   else  | 
1854  |  |       ns->href = xmlStrdup(XML_XML_NAMESPACE);  | 
1855  |  | #else  | 
1856  |  |   ns->href = xmlStrdup(XML_XML_NAMESPACE);  | 
1857  |  | #endif  | 
1858  |  |   ns->prefix = xmlStrdup((const xmlChar *)"xml");  | 
1859  |  |   doc->oldNs = ns;  | 
1860  |  |   return (ns);  | 
1861  |  |     }  | 
1862  |  | }  | 
1863  |  |  | 
1864  |  | /*  | 
1865  |  | * xsltTreeAcquireStoredNs:  | 
1866  |  | * @doc: the doc  | 
1867  |  | * @nsName: the namespace name  | 
1868  |  | * @prefix: the prefix  | 
1869  |  | *  | 
1870  |  | * BIG NOTE:  | 
1871  |  | *  This was copy&pasted from Libxml2's xmlDOMWrapStoreNs() in "tree.c".  | 
1872  |  | * Creates or reuses an xmlNs struct on doc->oldNs with  | 
1873  |  | * the given prefix and namespace name.  | 
1874  |  | *  | 
1875  |  | * Returns the aquired ns struct or NULL in case of an API  | 
1876  |  | *         or internal error.  | 
1877  |  | */  | 
1878  |  | static xmlNsPtr  | 
1879  |  | xsltTreeAcquireStoredNs(xmlDocPtr doc,  | 
1880  |  |       const xmlChar *nsName,  | 
1881  |  |       const xmlChar *prefix)  | 
1882  |  | { | 
1883  |  |     xmlNsPtr ns;  | 
1884  |  |  | 
1885  |  |     if (doc == NULL)  | 
1886  |  |   return (NULL);  | 
1887  |  |     if (doc->oldNs != NULL)  | 
1888  |  |   ns = doc->oldNs;  | 
1889  |  |     else  | 
1890  |  |   ns = xsltTreeEnsureXMLDecl(doc);  | 
1891  |  |     if (ns == NULL)  | 
1892  |  |   return (NULL);  | 
1893  |  |     if (ns->next != NULL) { | 
1894  |  |   /* Reuse. */  | 
1895  |  |   ns = ns->next;  | 
1896  |  |   while (ns != NULL) { | 
1897  |  |       if ((ns->prefix == NULL) != (prefix == NULL)) { | 
1898  |  |     /* NOP */  | 
1899  |  |       } else if (prefix == NULL) { | 
1900  |  |     if (xmlStrEqual(ns->href, nsName))  | 
1901  |  |         return (ns);  | 
1902  |  |       } else { | 
1903  |  |     if ((ns->prefix[0] == prefix[0]) &&  | 
1904  |  |          xmlStrEqual(ns->prefix, prefix) &&  | 
1905  |  |          xmlStrEqual(ns->href, nsName))  | 
1906  |  |         return (ns);  | 
1907  |  |  | 
1908  |  |       }  | 
1909  |  |       if (ns->next == NULL)  | 
1910  |  |     break;  | 
1911  |  |       ns = ns->next;  | 
1912  |  |   }  | 
1913  |  |     }  | 
1914  |  |     /* Create. */  | 
1915  |  |     ns->next = xmlNewNs(NULL, nsName, prefix);  | 
1916  |  |     return (ns->next);  | 
1917  |  | }  | 
1918  |  |  | 
1919  |  | /**  | 
1920  |  |  * xsltLREBuildEffectiveNs:  | 
1921  |  |  *  | 
1922  |  |  * Apply ns-aliasing on the namespace of the given @elem and  | 
1923  |  |  * its attributes.  | 
1924  |  |  */  | 
1925  |  | static int  | 
1926  |  | xsltLREBuildEffectiveNs(xsltCompilerCtxtPtr cctxt,  | 
1927  |  |       xmlNodePtr elem)  | 
1928  |  | { | 
1929  |  |     xmlNsPtr ns;  | 
1930  |  |     xsltNsAliasPtr alias;  | 
1931  |  |  | 
1932  |  |     if ((cctxt == NULL) || (elem == NULL))  | 
1933  |  |   return(-1);  | 
1934  |  |     if ((cctxt->nsAliases == NULL) || (! cctxt->hasNsAliases))  | 
1935  |  |   return(0);  | 
1936  |  |  | 
1937  |  |     alias = cctxt->nsAliases;  | 
1938  |  |     while (alias != NULL) { | 
1939  |  |   if ( /* If both namespaces are NULL... */  | 
1940  |  |       ( (elem->ns == NULL) &&  | 
1941  |  |       ((alias->literalNs == NULL) ||  | 
1942  |  |       (alias->literalNs->href == NULL)) ) ||  | 
1943  |  |       /* ... or both namespace are equal */  | 
1944  |  |       ( (elem->ns != NULL) &&  | 
1945  |  |       (alias->literalNs != NULL) &&  | 
1946  |  |       xmlStrEqual(elem->ns->href, alias->literalNs->href) ) )  | 
1947  |  |   { | 
1948  |  |       if ((alias->targetNs != NULL) &&  | 
1949  |  |     (alias->targetNs->href != NULL))  | 
1950  |  |       { | 
1951  |  |     /*  | 
1952  |  |     * Convert namespace.  | 
1953  |  |     */  | 
1954  |  |     if (elem->doc == alias->docOfTargetNs) { | 
1955  |  |         /*  | 
1956  |  |         * This is the nice case: same docs.  | 
1957  |  |         * This will eventually assign a ns-decl which  | 
1958  |  |         * is shadowed, but this has no negative effect on  | 
1959  |  |         * the generation of the result tree.  | 
1960  |  |         */  | 
1961  |  |         elem->ns = alias->targetNs;  | 
1962  |  |     } else { | 
1963  |  |         /*  | 
1964  |  |         * This target xmlNs originates from a different  | 
1965  |  |         * stylesheet tree. Try to locate it in the  | 
1966  |  |         * in-scope namespaces.  | 
1967  |  |         * OPTIMIZE TODO: Use the compiler-node-info inScopeNs.  | 
1968  |  |         */  | 
1969  |  |         ns = xmlSearchNs(elem->doc, elem,  | 
1970  |  |       alias->targetNs->prefix);  | 
1971  |  |         /*  | 
1972  |  |         * If no matching ns-decl found, then assign a  | 
1973  |  |         * ns-decl stored in xmlDoc.  | 
1974  |  |         */  | 
1975  |  |         if ((ns == NULL) ||  | 
1976  |  |       (! xmlStrEqual(ns->href, alias->targetNs->href)))  | 
1977  |  |         { | 
1978  |  |       /*  | 
1979  |  |       * BIG NOTE: The use of xsltTreeAcquireStoredNs()  | 
1980  |  |       *  is not very efficient, but currently I don't  | 
1981  |  |       *  see an other way of *safely* changing a node's  | 
1982  |  |       *  namespace, since the xmlNs struct in  | 
1983  |  |       *  alias->targetNs might come from an other  | 
1984  |  |       *  stylesheet tree. So we need to anchor it in the  | 
1985  |  |       *  current document, without adding it to the tree,  | 
1986  |  |       *  which would otherwise change the in-scope-ns  | 
1987  |  |       *  semantic of the tree.  | 
1988  |  |       */  | 
1989  |  |       ns = xsltTreeAcquireStoredNs(elem->doc,  | 
1990  |  |           alias->targetNs->href,  | 
1991  |  |           alias->targetNs->prefix);  | 
1992  |  |  | 
1993  |  |       if (ns == NULL) { | 
1994  |  |           xsltTransformError(NULL, cctxt->style, elem,  | 
1995  |  |         "Internal error in "  | 
1996  |  |         "xsltLREBuildEffectiveNs(): "  | 
1997  |  |         "failed to acquire a stored "  | 
1998  |  |         "ns-declaration.\n");  | 
1999  |  |           cctxt->style->errors++;  | 
2000  |  |           return(-1);  | 
2001  |  |  | 
2002  |  |       }  | 
2003  |  |         }  | 
2004  |  |         elem->ns = ns;  | 
2005  |  |     }  | 
2006  |  |       } else { | 
2007  |  |     /*  | 
2008  |  |     * Move into or leave in the NULL namespace.  | 
2009  |  |     */  | 
2010  |  |     elem->ns = NULL;  | 
2011  |  |       }  | 
2012  |  |       break;  | 
2013  |  |   }  | 
2014  |  |   alias = alias->next;  | 
2015  |  |     }  | 
2016  |  |     /*  | 
2017  |  |     * Same with attributes of literal result elements.  | 
2018  |  |     */  | 
2019  |  |     if (elem->properties != NULL) { | 
2020  |  |   xmlAttrPtr attr = elem->properties;  | 
2021  |  |  | 
2022  |  |   while (attr != NULL) { | 
2023  |  |       if (attr->ns == NULL) { | 
2024  |  |     attr = attr->next;  | 
2025  |  |     continue;  | 
2026  |  |       }  | 
2027  |  |       alias = cctxt->nsAliases;  | 
2028  |  |       while (alias != NULL) { | 
2029  |  |     if ( /* If both namespaces are NULL... */  | 
2030  |  |         ( (elem->ns == NULL) &&  | 
2031  |  |         ((alias->literalNs == NULL) ||  | 
2032  |  |         (alias->literalNs->href == NULL)) ) ||  | 
2033  |  |         /* ... or both namespace are equal */  | 
2034  |  |         ( (elem->ns != NULL) &&  | 
2035  |  |         (alias->literalNs != NULL) &&  | 
2036  |  |         xmlStrEqual(elem->ns->href, alias->literalNs->href) ) )  | 
2037  |  |     { | 
2038  |  |         if ((alias->targetNs != NULL) &&  | 
2039  |  |       (alias->targetNs->href != NULL))  | 
2040  |  |         { | 
2041  |  |       if (elem->doc == alias->docOfTargetNs) { | 
2042  |  |           elem->ns = alias->targetNs;  | 
2043  |  |       } else { | 
2044  |  |           ns = xmlSearchNs(elem->doc, elem,  | 
2045  |  |         alias->targetNs->prefix);  | 
2046  |  |           if ((ns == NULL) ||  | 
2047  |  |         (! xmlStrEqual(ns->href, alias->targetNs->href)))  | 
2048  |  |           { | 
2049  |  |         ns = xsltTreeAcquireStoredNs(elem->doc,  | 
2050  |  |             alias->targetNs->href,  | 
2051  |  |             alias->targetNs->prefix);  | 
2052  |  |  | 
2053  |  |         if (ns == NULL) { | 
2054  |  |             xsltTransformError(NULL, cctxt->style, elem,  | 
2055  |  |           "Internal error in "  | 
2056  |  |           "xsltLREBuildEffectiveNs(): "  | 
2057  |  |           "failed to acquire a stored "  | 
2058  |  |           "ns-declaration.\n");  | 
2059  |  |             cctxt->style->errors++;  | 
2060  |  |             return(-1);  | 
2061  |  |  | 
2062  |  |         }  | 
2063  |  |           }  | 
2064  |  |           elem->ns = ns;  | 
2065  |  |       }  | 
2066  |  |         } else { | 
2067  |  |         /*  | 
2068  |  |         * Move into or leave in the NULL namespace.  | 
2069  |  |       */  | 
2070  |  |       elem->ns = NULL;  | 
2071  |  |         }  | 
2072  |  |         break;  | 
2073  |  |     }  | 
2074  |  |     alias = alias->next;  | 
2075  |  |       }  | 
2076  |  |  | 
2077  |  |       attr = attr->next;  | 
2078  |  |   }  | 
2079  |  |     }  | 
2080  |  |     return(0);  | 
2081  |  | }  | 
2082  |  |  | 
2083  |  | /**  | 
2084  |  |  * xsltLREBuildEffectiveNsNodes:  | 
2085  |  |  *  | 
2086  |  |  * Computes the effective namespaces nodes for a literal result  | 
2087  |  |  * element.  | 
2088  |  |  * @effectiveNs is the set of effective ns-nodes  | 
2089  |  |  *  on the literal result element, which will be added to the result  | 
2090  |  |  *  element if not already existing in the result tree.  | 
2091  |  |  *  This means that excluded namespaces (via exclude-result-prefixes,  | 
2092  |  |  *  extension-element-prefixes and the XSLT namespace) not added  | 
2093  |  |  *  to the set.  | 
2094  |  |  *  Namespace-aliasing was applied on the @effectiveNs.  | 
2095  |  |  */  | 
2096  |  | static int  | 
2097  |  | xsltLREBuildEffectiveNsNodes(xsltCompilerCtxtPtr cctxt,  | 
2098  |  |            xsltStyleItemLRElementInfoPtr item,  | 
2099  |  |            xmlNodePtr elem,  | 
2100  |  |            int isLRE)  | 
2101  |  | { | 
2102  |  |     xmlNsPtr ns, tmpns;  | 
2103  |  |     xsltEffectiveNsPtr effNs, lastEffNs = NULL;  | 
2104  |  |     int i, j, holdByElem;  | 
2105  |  |     xsltPointerListPtr extElemNs = cctxt->inode->extElemNs;  | 
2106  |  |     xsltPointerListPtr exclResultNs = cctxt->inode->exclResultNs;  | 
2107  |  |  | 
2108  |  |     if ((cctxt == NULL) || (cctxt->inode == NULL) || (elem == NULL) ||  | 
2109  |  |   (item == NULL) || (item->effectiveNs != NULL))  | 
2110  |  |   return(-1);  | 
2111  |  |  | 
2112  |  |     if (item->inScopeNs == NULL)  | 
2113  |  |   return(0);  | 
2114  |  |  | 
2115  |  |     extElemNs = cctxt->inode->extElemNs;  | 
2116  |  |     exclResultNs = cctxt->inode->exclResultNs;  | 
2117  |  |  | 
2118  |  |     for (i = 0; i < item->inScopeNs->totalNumber; i++) { | 
2119  |  |   ns = item->inScopeNs->list[i];  | 
2120  |  |   /*  | 
2121  |  |   * Skip namespaces designated as excluded namespaces  | 
2122  |  |   * -------------------------------------------------  | 
2123  |  |   *  | 
2124  |  |   * XSLT-20 TODO: In XSLT 2.0 we need to keep namespaces  | 
2125  |  |   *  which are target namespaces of namespace-aliases  | 
2126  |  |   *  regardless if designated as excluded.  | 
2127  |  |   *  | 
2128  |  |   * Exclude the XSLT namespace.  | 
2129  |  |   */  | 
2130  |  |   if (xmlStrEqual(ns->href, XSLT_NAMESPACE))  | 
2131  |  |       goto skip_ns;  | 
2132  |  |  | 
2133  |  |   /*  | 
2134  |  |   * Apply namespace aliasing  | 
2135  |  |   * ------------------------  | 
2136  |  |   *  | 
2137  |  |   * SPEC XSLT 2.0  | 
2138  |  |   *  "- A namespace node whose string value is a literal namespace  | 
2139  |  |   *     URI is not copied to the result tree.  | 
2140  |  |   *   - A namespace node whose string value is a target namespace URI  | 
2141  |  |   *     is copied to the result tree, whether or not the URI  | 
2142  |  |   *     identifies an excluded namespace."  | 
2143  |  |   *  | 
2144  |  |   * NOTE: The ns-aliasing machanism is non-cascading.  | 
2145  |  |   *  (checked with Saxon, Xalan and MSXML .NET).  | 
2146  |  |   * URGENT TODO: is style->nsAliases the effective list of  | 
2147  |  |   *  ns-aliases, or do we need to lookup the whole  | 
2148  |  |   *  import-tree?  | 
2149  |  |   * TODO: Get rid of import-tree lookup.  | 
2150  |  |   */  | 
2151  |  |   if (cctxt->hasNsAliases) { | 
2152  |  |       xsltNsAliasPtr alias;  | 
2153  |  |       /*  | 
2154  |  |       * First check for being a target namespace.  | 
2155  |  |       */  | 
2156  |  |       alias = cctxt->nsAliases;  | 
2157  |  |       do { | 
2158  |  |     /*  | 
2159  |  |     * TODO: Is xmlns="" handled already?  | 
2160  |  |     */  | 
2161  |  |     if ((alias->targetNs != NULL) &&  | 
2162  |  |         (xmlStrEqual(alias->targetNs->href, ns->href)))  | 
2163  |  |     { | 
2164  |  |         /*  | 
2165  |  |         * Recognized as a target namespace; use it regardless  | 
2166  |  |         * if excluded otherwise.  | 
2167  |  |         */  | 
2168  |  |         goto add_effective_ns;  | 
2169  |  |     }  | 
2170  |  |     alias = alias->next;  | 
2171  |  |       } while (alias != NULL);  | 
2172  |  |  | 
2173  |  |       alias = cctxt->nsAliases;  | 
2174  |  |       do { | 
2175  |  |     /*  | 
2176  |  |     * TODO: Is xmlns="" handled already?  | 
2177  |  |     */  | 
2178  |  |     if ((alias->literalNs != NULL) &&  | 
2179  |  |         (xmlStrEqual(alias->literalNs->href, ns->href)))  | 
2180  |  |     { | 
2181  |  |         /*  | 
2182  |  |         * Recognized as an namespace alias; do not use it.  | 
2183  |  |         */  | 
2184  |  |         goto skip_ns;  | 
2185  |  |     }  | 
2186  |  |     alias = alias->next;  | 
2187  |  |       } while (alias != NULL);  | 
2188  |  |   }  | 
2189  |  |  | 
2190  |  |   /*  | 
2191  |  |   * Exclude excluded result namespaces.  | 
2192  |  |   */  | 
2193  |  |   if (exclResultNs) { | 
2194  |  |       for (j = 0; j < exclResultNs->number; j++)  | 
2195  |  |     if (xmlStrEqual(ns->href, BAD_CAST exclResultNs->items[j]))  | 
2196  |  |         goto skip_ns;  | 
2197  |  |   }  | 
2198  |  |   /*  | 
2199  |  |   * Exclude extension-element namespaces.  | 
2200  |  |   */  | 
2201  |  |   if (extElemNs) { | 
2202  |  |       for (j = 0; j < extElemNs->number; j++)  | 
2203  |  |     if (xmlStrEqual(ns->href, BAD_CAST extElemNs->items[j]))  | 
2204  |  |         goto skip_ns;  | 
2205  |  |   }  | 
2206  |  |  | 
2207  |  | add_effective_ns:  | 
2208  |  |   /*  | 
2209  |  |   * OPTIMIZE TODO: This information may not be needed.  | 
2210  |  |   */  | 
2211  |  |   if (isLRE && (elem->nsDef != NULL)) { | 
2212  |  |       holdByElem = 0;  | 
2213  |  |       tmpns = elem->nsDef;  | 
2214  |  |       do { | 
2215  |  |     if (tmpns == ns) { | 
2216  |  |         holdByElem = 1;  | 
2217  |  |         break;  | 
2218  |  |     }  | 
2219  |  |     tmpns = tmpns->next;  | 
2220  |  |       } while (tmpns != NULL);  | 
2221  |  |   } else  | 
2222  |  |       holdByElem = 0;  | 
2223  |  |  | 
2224  |  |  | 
2225  |  |   /*  | 
2226  |  |   * Add the effective namespace declaration.  | 
2227  |  |   */  | 
2228  |  |   effNs = (xsltEffectiveNsPtr) xmlMalloc(sizeof(xsltEffectiveNs));  | 
2229  |  |   if (effNs == NULL) { | 
2230  |  |       xsltTransformError(NULL, cctxt->style, elem,  | 
2231  |  |     "Internal error in xsltLREBuildEffectiveNs(): "  | 
2232  |  |     "failed to allocate memory.\n");  | 
2233  |  |       cctxt->style->errors++;  | 
2234  |  |       return(-1);  | 
2235  |  |   }  | 
2236  |  |   if (cctxt->psData->effectiveNs == NULL) { | 
2237  |  |       cctxt->psData->effectiveNs = effNs;  | 
2238  |  |       effNs->nextInStore = NULL;  | 
2239  |  |   } else { | 
2240  |  |       effNs->nextInStore = cctxt->psData->effectiveNs;  | 
2241  |  |       cctxt->psData->effectiveNs = effNs;  | 
2242  |  |   }  | 
2243  |  |  | 
2244  |  |   effNs->next = NULL;  | 
2245  |  |   effNs->prefix = ns->prefix;  | 
2246  |  |   effNs->nsName = ns->href;  | 
2247  |  |   effNs->holdByElem = holdByElem;  | 
2248  |  |  | 
2249  |  |   if (lastEffNs == NULL)  | 
2250  |  |       item->effectiveNs = effNs;  | 
2251  |  |   else  | 
2252  |  |       lastEffNs->next = effNs;  | 
2253  |  |   lastEffNs = effNs;  | 
2254  |  |  | 
2255  |  | skip_ns:  | 
2256  |  |   {} | 
2257  |  |     }  | 
2258  |  |     return(0);  | 
2259  |  | }  | 
2260  |  |  | 
2261  |  |  | 
2262  |  | /**  | 
2263  |  |  * xsltLREInfoCreate:  | 
2264  |  |  *  | 
2265  |  |  * @isLRE: indicates if the given @elem is a literal result element  | 
2266  |  |  *  | 
2267  |  |  * Creates a new info for a literal result element.  | 
2268  |  |  */  | 
2269  |  | static int  | 
2270  |  | xsltLREInfoCreate(xsltCompilerCtxtPtr cctxt,  | 
2271  |  |       xmlNodePtr elem,  | 
2272  |  |       int isLRE)  | 
2273  |  | { | 
2274  |  |     xsltStyleItemLRElementInfoPtr item;  | 
2275  |  |  | 
2276  |  |     if ((cctxt == NULL) || (cctxt->inode == NULL))  | 
2277  |  |   return(-1);  | 
2278  |  |  | 
2279  |  |     item = (xsltStyleItemLRElementInfoPtr)  | 
2280  |  |   xmlMalloc(sizeof(xsltStyleItemLRElementInfo));  | 
2281  |  |     if (item == NULL) { | 
2282  |  |   xsltTransformError(NULL, cctxt->style, NULL,  | 
2283  |  |       "Internal error in xsltLREInfoCreate(): "  | 
2284  |  |       "memory allocation failed.\n");  | 
2285  |  |   cctxt->style->errors++;  | 
2286  |  |   return(-1);  | 
2287  |  |     }  | 
2288  |  |     memset(item, 0, sizeof(xsltStyleItemLRElementInfo));  | 
2289  |  |     item->type = XSLT_FUNC_LITERAL_RESULT_ELEMENT;  | 
2290  |  |     /*  | 
2291  |  |     * Store it in the stylesheet.  | 
2292  |  |     */  | 
2293  |  |     item->next = cctxt->style->preComps;  | 
2294  |  |     cctxt->style->preComps = (xsltElemPreCompPtr) item;  | 
2295  |  |     /*  | 
2296  |  |     * @inScopeNs are used for execution of XPath expressions  | 
2297  |  |     *  in AVTs.  | 
2298  |  |     */  | 
2299  |  |     item->inScopeNs = cctxt->inode->inScopeNs;  | 
2300  |  |  | 
2301  |  |     if (elem)  | 
2302  |  |   xsltLREBuildEffectiveNsNodes(cctxt, item, elem, isLRE);  | 
2303  |  |  | 
2304  |  |     cctxt->inode->litResElemInfo = item;  | 
2305  |  |     cctxt->inode->nsChanged = 0;  | 
2306  |  |     cctxt->maxLREs++;  | 
2307  |  |     return(0);  | 
2308  |  | }  | 
2309  |  |  | 
2310  |  | /**  | 
2311  |  |  * xsltCompilerVarInfoPush:  | 
2312  |  |  * @cctxt: the compilation context  | 
2313  |  |  *  | 
2314  |  |  * Pushes a new var/param info onto the stack.  | 
2315  |  |  *  | 
2316  |  |  * Returns the acquired variable info.  | 
2317  |  |  */  | 
2318  |  | static xsltVarInfoPtr  | 
2319  |  | xsltCompilerVarInfoPush(xsltCompilerCtxtPtr cctxt,  | 
2320  |  |           xmlNodePtr inst,  | 
2321  |  |           const xmlChar *name,  | 
2322  |  |           const xmlChar *nsName)  | 
2323  |  | { | 
2324  |  |     xsltVarInfoPtr ivar;  | 
2325  |  |  | 
2326  |  |     if ((cctxt->ivar != NULL) && (cctxt->ivar->next != NULL)) { | 
2327  |  |   ivar = cctxt->ivar->next;  | 
2328  |  |     } else if ((cctxt->ivar == NULL) && (cctxt->ivars != NULL)) { | 
2329  |  |   ivar = cctxt->ivars;  | 
2330  |  |     } else { | 
2331  |  |   ivar = (xsltVarInfoPtr) xmlMalloc(sizeof(xsltVarInfo));  | 
2332  |  |   if (ivar == NULL) { | 
2333  |  |       xsltTransformError(NULL, cctxt->style, inst,  | 
2334  |  |     "xsltParseInScopeVarPush: xmlMalloc() failed!\n");  | 
2335  |  |       cctxt->style->errors++;  | 
2336  |  |       return(NULL);  | 
2337  |  |   }  | 
2338  |  |   /* memset(retVar, 0, sizeof(xsltInScopeVar)); */  | 
2339  |  |   if (cctxt->ivars == NULL) { | 
2340  |  |       cctxt->ivars = ivar;  | 
2341  |  |       ivar->prev = NULL;  | 
2342  |  |   } else { | 
2343  |  |       cctxt->ivar->next = ivar;  | 
2344  |  |       ivar->prev = cctxt->ivar;  | 
2345  |  |   }  | 
2346  |  |   cctxt->ivar = ivar;  | 
2347  |  |   ivar->next = NULL;  | 
2348  |  |     }  | 
2349  |  |     ivar->depth = cctxt->depth;  | 
2350  |  |     ivar->name = name;  | 
2351  |  |     ivar->nsName = nsName;  | 
2352  |  |     return(ivar);  | 
2353  |  | }  | 
2354  |  |  | 
2355  |  | /**  | 
2356  |  |  * xsltCompilerVarInfoPop:  | 
2357  |  |  * @cctxt: the compilation context  | 
2358  |  |  *  | 
2359  |  |  * Pops all var/param infos from the stack, which  | 
2360  |  |  * have the current depth.  | 
2361  |  |  */  | 
2362  |  | static void  | 
2363  |  | xsltCompilerVarInfoPop(xsltCompilerCtxtPtr cctxt)  | 
2364  |  | { | 
2365  |  |  | 
2366  |  |     while ((cctxt->ivar != NULL) &&  | 
2367  |  |   (cctxt->ivar->depth > cctxt->depth))  | 
2368  |  |     { | 
2369  |  |   cctxt->ivar = cctxt->ivar->prev;  | 
2370  |  |     }  | 
2371  |  | }  | 
2372  |  |  | 
2373  |  | /*  | 
2374  |  | * xsltCompilerNodePush:  | 
2375  |  | *  | 
2376  |  | * @cctxt: the compilation context  | 
2377  |  | * @node: the node to be pushed (this can also be the doc-node)  | 
2378  |  | *  | 
2379  |  | *  | 
2380  |  | *  | 
2381  |  | * Returns the current node info structure or  | 
2382  |  | *         NULL in case of an internal error.  | 
2383  |  | */  | 
2384  |  | static xsltCompilerNodeInfoPtr  | 
2385  |  | xsltCompilerNodePush(xsltCompilerCtxtPtr cctxt, xmlNodePtr node)  | 
2386  |  | { | 
2387  |  |     xsltCompilerNodeInfoPtr inode, iprev;  | 
2388  |  |  | 
2389  |  |     if ((cctxt->inode != NULL) && (cctxt->inode->next != NULL)) { | 
2390  |  |   inode = cctxt->inode->next;  | 
2391  |  |     } else if ((cctxt->inode == NULL) && (cctxt->inodeList != NULL)) { | 
2392  |  |   inode = cctxt->inodeList;  | 
2393  |  |     } else { | 
2394  |  |   /*  | 
2395  |  |   * Create a new node-info.  | 
2396  |  |   */  | 
2397  |  |   inode = (xsltCompilerNodeInfoPtr)  | 
2398  |  |       xmlMalloc(sizeof(xsltCompilerNodeInfo));  | 
2399  |  |   if (inode == NULL) { | 
2400  |  |       xsltTransformError(NULL, cctxt->style, NULL,  | 
2401  |  |     "xsltCompilerNodePush: malloc failed.\n");  | 
2402  |  |       return(NULL);  | 
2403  |  |   }  | 
2404  |  |   memset(inode, 0, sizeof(xsltCompilerNodeInfo));  | 
2405  |  |   if (cctxt->inodeList == NULL)  | 
2406  |  |       cctxt->inodeList = inode;  | 
2407  |  |   else { | 
2408  |  |       cctxt->inodeLast->next = inode;  | 
2409  |  |       inode->prev = cctxt->inodeLast;  | 
2410  |  |   }  | 
2411  |  |   cctxt->inodeLast = inode;  | 
2412  |  |   cctxt->maxNodeInfos++;  | 
2413  |  |   if (cctxt->inode == NULL) { | 
2414  |  |       cctxt->inode = inode;  | 
2415  |  |       /*  | 
2416  |  |       * Create an initial literal result element info for  | 
2417  |  |       * the root of the stylesheet.  | 
2418  |  |       */  | 
2419  |  |       xsltLREInfoCreate(cctxt, NULL, 0);  | 
2420  |  |   }  | 
2421  |  |     }  | 
2422  |  |     cctxt->depth++;  | 
2423  |  |     cctxt->inode = inode;  | 
2424  |  |     /*  | 
2425  |  |     * REVISIT TODO: Keep the reset always complete.  | 
2426  |  |     * NOTE: Be carefull with the @node, since it might be  | 
2427  |  |     *  a doc-node.  | 
2428  |  |     */  | 
2429  |  |     inode->node = node;  | 
2430  |  |     inode->depth = cctxt->depth;  | 
2431  |  |     inode->templ = NULL;  | 
2432  |  |     inode->category = XSLT_ELEMENT_CATEGORY_XSLT;  | 
2433  |  |     inode->type = 0;  | 
2434  |  |     inode->item = NULL;  | 
2435  |  |     inode->curChildType = 0;  | 
2436  |  |     inode->extContentHandled = 0;  | 
2437  |  |     inode->isRoot = 0;  | 
2438  |  |  | 
2439  |  |     if (inode->prev != NULL) { | 
2440  |  |   iprev = inode->prev;  | 
2441  |  |   /*  | 
2442  |  |   * Inherit the following information:  | 
2443  |  |   * ---------------------------------  | 
2444  |  |   *  | 
2445  |  |   * In-scope namespaces  | 
2446  |  |   */  | 
2447  |  |   inode->inScopeNs = iprev->inScopeNs;  | 
2448  |  |   /*  | 
2449  |  |   * Info for literal result elements  | 
2450  |  |   */  | 
2451  |  |   inode->litResElemInfo = iprev->litResElemInfo;  | 
2452  |  |   inode->nsChanged = iprev->nsChanged;  | 
2453  |  |   /*  | 
2454  |  |   * Excluded result namespaces  | 
2455  |  |   */  | 
2456  |  |   inode->exclResultNs = iprev->exclResultNs;  | 
2457  |  |   /*  | 
2458  |  |   * Extension instruction namespaces  | 
2459  |  |   */  | 
2460  |  |   inode->extElemNs = iprev->extElemNs;  | 
2461  |  |   /*  | 
2462  |  |   * Whitespace preservation  | 
2463  |  |   */  | 
2464  |  |   inode->preserveWhitespace = iprev->preserveWhitespace;  | 
2465  |  |   /*  | 
2466  |  |   * Forwards-compatible mode  | 
2467  |  |   */  | 
2468  |  |   inode->forwardsCompat = iprev->forwardsCompat;  | 
2469  |  |     } else { | 
2470  |  |   inode->inScopeNs = NULL;  | 
2471  |  |   inode->exclResultNs = NULL;  | 
2472  |  |   inode->extElemNs = NULL;  | 
2473  |  |   inode->preserveWhitespace = 0;  | 
2474  |  |   inode->forwardsCompat = 0;  | 
2475  |  |     }  | 
2476  |  |  | 
2477  |  |     return(inode);  | 
2478  |  | }  | 
2479  |  |  | 
2480  |  | /*  | 
2481  |  | * xsltCompilerNodePop:  | 
2482  |  | *  | 
2483  |  | * @cctxt: the compilation context  | 
2484  |  | * @node: the node to be pushed (this can also be the doc-node)  | 
2485  |  | *  | 
2486  |  | * Pops the current node info.  | 
2487  |  | */  | 
2488  |  | static void  | 
2489  |  | xsltCompilerNodePop(xsltCompilerCtxtPtr cctxt, xmlNodePtr node)  | 
2490  |  | { | 
2491  |  |     if (cctxt->inode == NULL) { | 
2492  |  |   xmlGenericError(xmlGenericErrorContext,  | 
2493  |  |       "xsltCompilerNodePop: Top-node mismatch.\n");  | 
2494  |  |   return;  | 
2495  |  |     }  | 
2496  |  |     /*  | 
2497  |  |     * NOTE: Be carefull with the @node, since it might be  | 
2498  |  |     *  a doc-node.  | 
2499  |  |     */  | 
2500  |  |     if (cctxt->inode->node != node) { | 
2501  |  |   xmlGenericError(xmlGenericErrorContext,  | 
2502  |  |   "xsltCompilerNodePop: Node mismatch.\n");  | 
2503  |  |   goto mismatch;  | 
2504  |  |     }  | 
2505  |  |     if (cctxt->inode->depth != cctxt->depth) { | 
2506  |  |   xmlGenericError(xmlGenericErrorContext,  | 
2507  |  |   "xsltCompilerNodePop: Depth mismatch.\n");  | 
2508  |  |   goto mismatch;  | 
2509  |  |     }  | 
2510  |  |     cctxt->depth--;  | 
2511  |  |     /*  | 
2512  |  |     * Pop information of variables.  | 
2513  |  |     */  | 
2514  |  |     if ((cctxt->ivar) && (cctxt->ivar->depth > cctxt->depth))  | 
2515  |  |   xsltCompilerVarInfoPop(cctxt);  | 
2516  |  |  | 
2517  |  |     cctxt->inode = cctxt->inode->prev;  | 
2518  |  |     if (cctxt->inode != NULL)  | 
2519  |  |   cctxt->inode->curChildType = 0;  | 
2520  |  |     return;  | 
2521  |  |  | 
2522  |  | mismatch:  | 
2523  |  |     { | 
2524  |  |   const xmlChar *nsName = NULL, *name = NULL;  | 
2525  |  |   const xmlChar *infnsName = NULL, *infname = NULL;  | 
2526  |  |  | 
2527  |  |   if (node) { | 
2528  |  |       if (node->type == XML_ELEMENT_NODE) { | 
2529  |  |     name = node->name;  | 
2530  |  |     if (node->ns != NULL)  | 
2531  |  |         nsName = node->ns->href;  | 
2532  |  |     else  | 
2533  |  |         nsName = BAD_CAST "";  | 
2534  |  |       } else { | 
2535  |  |     name = BAD_CAST "#document";  | 
2536  |  |     nsName = BAD_CAST "";  | 
2537  |  |       }  | 
2538  |  |   } else  | 
2539  |  |       name = BAD_CAST "Not given";  | 
2540  |  |  | 
2541  |  |   if (cctxt->inode->node) { | 
2542  |  |       if (node->type == XML_ELEMENT_NODE) { | 
2543  |  |     infname = cctxt->inode->node->name;  | 
2544  |  |     if (cctxt->inode->node->ns != NULL)  | 
2545  |  |         infnsName = cctxt->inode->node->ns->href;  | 
2546  |  |     else  | 
2547  |  |         infnsName = BAD_CAST "";  | 
2548  |  |       } else { | 
2549  |  |     infname = BAD_CAST "#document";  | 
2550  |  |     infnsName = BAD_CAST "";  | 
2551  |  |       }  | 
2552  |  |   } else  | 
2553  |  |       infname = BAD_CAST "Not given";  | 
2554  |  |  | 
2555  |  |  | 
2556  |  |   xmlGenericError(xmlGenericErrorContext,  | 
2557  |  |       "xsltCompilerNodePop: Given   : '%s' URI '%s'\n",  | 
2558  |  |       name, nsName);  | 
2559  |  |   xmlGenericError(xmlGenericErrorContext,  | 
2560  |  |       "xsltCompilerNodePop: Expected: '%s' URI '%s'\n",  | 
2561  |  |       infname, infnsName);  | 
2562  |  |     }  | 
2563  |  | }  | 
2564  |  |  | 
2565  |  | /*  | 
2566  |  | * xsltCompilerBuildInScopeNsList:  | 
2567  |  | *  | 
2568  |  | * Create and store the list of in-scope namespaces for the given  | 
2569  |  | * node in the stylesheet. If there are no changes in the in-scope  | 
2570  |  | * namespaces then the last ns-info of the ancestor axis will be returned.  | 
2571  |  | * Compilation-time only.  | 
2572  |  | *  | 
2573  |  | * Returns the ns-info or NULL if there are no namespaces in scope.  | 
2574  |  | */  | 
2575  |  | static xsltNsListContainerPtr  | 
2576  |  | xsltCompilerBuildInScopeNsList(xsltCompilerCtxtPtr cctxt, xmlNodePtr node)  | 
2577  |  | { | 
2578  |  |     xsltNsListContainerPtr nsi = NULL;  | 
2579  |  |     xmlNsPtr *list = NULL, ns;  | 
2580  |  |     int i, maxns = 5;  | 
2581  |  |     /*  | 
2582  |  |     * Create a new ns-list for this position in the node-tree.  | 
2583  |  |     * xmlGetNsList() will return NULL, if there are no ns-decls in the  | 
2584  |  |     * tree. Note that the ns-decl for the XML namespace is not added  | 
2585  |  |     * to the resulting list; the XPath module handles the XML namespace  | 
2586  |  |     * internally.  | 
2587  |  |     */  | 
2588  |  |     while (node != NULL) { | 
2589  |  |         if (node->type == XML_ELEMENT_NODE) { | 
2590  |  |             ns = node->nsDef;  | 
2591  |  |             while (ns != NULL) { | 
2592  |  |                 if (nsi == NULL) { | 
2593  |  |         nsi = (xsltNsListContainerPtr)  | 
2594  |  |       xmlMalloc(sizeof(xsltNsListContainer));  | 
2595  |  |         if (nsi == NULL) { | 
2596  |  |       xsltTransformError(NULL, cctxt->style, NULL,  | 
2597  |  |           "xsltCompilerBuildInScopeNsList: "  | 
2598  |  |           "malloc failed!\n");  | 
2599  |  |       goto internal_err;  | 
2600  |  |         }  | 
2601  |  |         memset(nsi, 0, sizeof(xsltNsListContainer));  | 
2602  |  |                     nsi->list =  | 
2603  |  |                         (xmlNsPtr *) xmlMalloc(maxns * sizeof(xmlNsPtr));  | 
2604  |  |                     if (nsi->list == NULL) { | 
2605  |  |       xsltTransformError(NULL, cctxt->style, NULL,  | 
2606  |  |           "xsltCompilerBuildInScopeNsList: "  | 
2607  |  |           "malloc failed!\n");  | 
2608  |  |       goto internal_err;  | 
2609  |  |                     }  | 
2610  |  |                     nsi->list[0] = NULL;  | 
2611  |  |                 }  | 
2612  |  |     /*  | 
2613  |  |     * Skip shadowed namespace bindings.  | 
2614  |  |     */  | 
2615  |  |                 for (i = 0; i < nsi->totalNumber; i++) { | 
2616  |  |                     if ((ns->prefix == nsi->list[i]->prefix) ||  | 
2617  |  |                         (xmlStrEqual(ns->prefix, nsi->list[i]->prefix)))  | 
2618  |  |         break;  | 
2619  |  |                 }  | 
2620  |  |                 if (i >= nsi->totalNumber) { | 
2621  |  |                     if (nsi->totalNumber +1 >= maxns) { | 
2622  |  |                         maxns *= 2;  | 
2623  |  |       nsi->list =  | 
2624  |  |           (xmlNsPtr *) xmlRealloc(nsi->list,  | 
2625  |  |         maxns * sizeof(xmlNsPtr));  | 
2626  |  |                         if (nsi->list == NULL) { | 
2627  |  |                             xsltTransformError(NULL, cctxt->style, NULL,  | 
2628  |  |         "xsltCompilerBuildInScopeNsList: "  | 
2629  |  |         "realloc failed!\n");  | 
2630  |  |         goto internal_err;  | 
2631  |  |                         }  | 
2632  |  |                     }  | 
2633  |  |                     nsi->list[nsi->totalNumber++] = ns;  | 
2634  |  |                     nsi->list[nsi->totalNumber] = NULL;  | 
2635  |  |                 }  | 
2636  |  |  | 
2637  |  |                 ns = ns->next;  | 
2638  |  |             }  | 
2639  |  |         }  | 
2640  |  |         node = node->parent;  | 
2641  |  |     }  | 
2642  |  |     if (nsi == NULL)  | 
2643  |  |   return(NULL);  | 
2644  |  |     /*  | 
2645  |  |     * Move the default namespace to last position.  | 
2646  |  |     */  | 
2647  |  |     nsi->xpathNumber = nsi->totalNumber;  | 
2648  |  |     for (i = 0; i < nsi->totalNumber; i++) { | 
2649  |  |   if (nsi->list[i]->prefix == NULL) { | 
2650  |  |       ns = nsi->list[i];  | 
2651  |  |       nsi->list[i] = nsi->list[nsi->totalNumber-1];  | 
2652  |  |       nsi->list[nsi->totalNumber-1] = ns;  | 
2653  |  |       nsi->xpathNumber--;  | 
2654  |  |       break;  | 
2655  |  |   }  | 
2656  |  |     }  | 
2657  |  |     /*  | 
2658  |  |     * Store the ns-list in the stylesheet.  | 
2659  |  |     */  | 
2660  |  |     if (xsltPointerListAddSize(  | 
2661  |  |   (xsltPointerListPtr)cctxt->psData->inScopeNamespaces,  | 
2662  |  |   (void *) nsi, 5) == -1)  | 
2663  |  |     { | 
2664  |  |   xmlFree(nsi);  | 
2665  |  |   nsi = NULL;  | 
2666  |  |   xsltTransformError(NULL, cctxt->style, NULL,  | 
2667  |  |       "xsltCompilerBuildInScopeNsList: failed to add ns-info.\n");  | 
2668  |  |   goto internal_err;  | 
2669  |  |     }  | 
2670  |  |     /*  | 
2671  |  |     * Notify of change in status wrt namespaces.  | 
2672  |  |     */  | 
2673  |  |     if (cctxt->inode != NULL)  | 
2674  |  |   cctxt->inode->nsChanged = 1;  | 
2675  |  |  | 
2676  |  |     return(nsi);  | 
2677  |  |  | 
2678  |  | internal_err:  | 
2679  |  |     if (list != NULL)  | 
2680  |  |   xmlFree(list);  | 
2681  |  |     cctxt->style->errors++;  | 
2682  |  |     return(NULL);  | 
2683  |  | }  | 
2684  |  |  | 
2685  |  | static int  | 
2686  |  | xsltParseNsPrefixList(xsltCompilerCtxtPtr cctxt,  | 
2687  |  |           xsltPointerListPtr list,  | 
2688  |  |           xmlNodePtr node,  | 
2689  |  |           const xmlChar *value)  | 
2690  |  | { | 
2691  |  |     xmlChar *cur, *end;  | 
2692  |  |     xmlNsPtr ns;  | 
2693  |  |  | 
2694  |  |     if ((cctxt == NULL) || (value == NULL) || (list == NULL))  | 
2695  |  |   return(-1);  | 
2696  |  |  | 
2697  |  |     list->number = 0;  | 
2698  |  |  | 
2699  |  |     cur = (xmlChar *) value;  | 
2700  |  |     while (*cur != 0) { | 
2701  |  |   while (IS_BLANK(*cur)) cur++;  | 
2702  |  |   if (*cur == 0)  | 
2703  |  |       break;  | 
2704  |  |   end = cur;  | 
2705  |  |   while ((*end != 0) && (!IS_BLANK(*end))) end++;  | 
2706  |  |   cur = xmlStrndup(cur, end - cur);  | 
2707  |  |   if (cur == NULL) { | 
2708  |  |       cur = end;  | 
2709  |  |       continue;  | 
2710  |  |   }  | 
2711  |  |   /*  | 
2712  |  |   * TODO: Export and use xmlSearchNsByPrefixStrict()  | 
2713  |  |   *   in Libxml2, tree.c, since xmlSearchNs() is in most  | 
2714  |  |   *   cases not efficient and in some cases not correct.  | 
2715  |  |   *  | 
2716  |  |   * XSLT-2 TODO: XSLT 2.0 allows an additional "#all" value.  | 
2717  |  |   */  | 
2718  |  |   if ((cur[0] == '#') &&  | 
2719  |  |       xmlStrEqual(cur, (const xmlChar *)"#default"))  | 
2720  |  |       ns = xmlSearchNs(cctxt->style->doc, node, NULL);  | 
2721  |  |   else  | 
2722  |  |       ns = xmlSearchNs(cctxt->style->doc, node, cur);  | 
2723  |  |  | 
2724  |  |   if (ns == NULL) { | 
2725  |  |       /*  | 
2726  |  |       * TODO: Better to report the attr-node, otherwise  | 
2727  |  |       *  the user won't know which attribute was invalid.  | 
2728  |  |       */  | 
2729  |  |       xsltTransformError(NULL, cctxt->style, node,  | 
2730  |  |     "No namespace binding in scope for prefix '%s'.\n", cur);  | 
2731  |  |       /*  | 
2732  |  |       * XSLT-1.0: "It is an error if there is no namespace  | 
2733  |  |       *  bound to the prefix on the element bearing the  | 
2734  |  |       *  exclude-result-prefixes or xsl:exclude-result-prefixes  | 
2735  |  |       *  attribute."  | 
2736  |  |       */  | 
2737  |  |       cctxt->style->errors++;  | 
2738  |  |   } else { | 
2739  |  | #ifdef WITH_XSLT_DEBUG_PARSING  | 
2740  |  |       xsltGenericDebug(xsltGenericDebugContext,  | 
2741  |  |     "resolved prefix '%s'\n", cur);  | 
2742  |  | #endif  | 
2743  |  |       /*  | 
2744  |  |       * Note that we put the namespace name into the dict.  | 
2745  |  |       */  | 
2746  |  |       if (xsltPointerListAddSize(list,  | 
2747  |  |     (void *) xmlDictLookup(cctxt->style->dict,  | 
2748  |  |     ns->href, -1), 5) == -1)  | 
2749  |  |       { | 
2750  |  |     xmlFree(cur);  | 
2751  |  |     goto internal_err;  | 
2752  |  |       }  | 
2753  |  |   }  | 
2754  |  |   xmlFree(cur);  | 
2755  |  |  | 
2756  |  |   cur = end;  | 
2757  |  |     }  | 
2758  |  |     return(0);  | 
2759  |  |  | 
2760  |  | internal_err:  | 
2761  |  |     cctxt->style->errors++;  | 
2762  |  |     return(-1);  | 
2763  |  | }  | 
2764  |  |  | 
2765  |  | /**  | 
2766  |  |  * xsltCompilerUtilsCreateMergedList:  | 
2767  |  |  * @dest: the destination list (optional)  | 
2768  |  |  * @first: the first list  | 
2769  |  |  * @second: the second list (optional)  | 
2770  |  |  *  | 
2771  |  |  * Appends the content of @second to @first into @destination.  | 
2772  |  |  * If @destination is NULL a new list will be created.  | 
2773  |  |  *  | 
2774  |  |  * Returns the merged list of items or NULL if there's nothing to merge.  | 
2775  |  |  */  | 
2776  |  | static xsltPointerListPtr  | 
2777  |  | xsltCompilerUtilsCreateMergedList(xsltPointerListPtr first,  | 
2778  |  |           xsltPointerListPtr second)  | 
2779  |  | { | 
2780  |  |     xsltPointerListPtr ret;  | 
2781  |  |     size_t num;  | 
2782  |  |  | 
2783  |  |     if (first)  | 
2784  |  |   num = first->number;  | 
2785  |  |     else  | 
2786  |  |   num = 0;  | 
2787  |  |     if (second)  | 
2788  |  |   num += second->number;  | 
2789  |  |     if (num == 0)  | 
2790  |  |   return(NULL);  | 
2791  |  |     ret = xsltPointerListCreate(num);  | 
2792  |  |     if (ret == NULL)  | 
2793  |  |   return(NULL);  | 
2794  |  |     /*  | 
2795  |  |     * Copy contents.  | 
2796  |  |     */  | 
2797  |  |     if ((first != NULL) &&  (first->number != 0)) { | 
2798  |  |   memcpy(ret->items, first->items,  | 
2799  |  |       first->number * sizeof(void *));  | 
2800  |  |   if ((second != NULL) && (second->number != 0))  | 
2801  |  |       memcpy(ret->items + first->number, second->items,  | 
2802  |  |     second->number * sizeof(void *));  | 
2803  |  |     } else if ((second != NULL) && (second->number != 0))  | 
2804  |  |   memcpy(ret->items, (void *) second->items,  | 
2805  |  |       second->number * sizeof(void *));  | 
2806  |  |     ret->number = num;  | 
2807  |  |     return(ret);  | 
2808  |  | }  | 
2809  |  |  | 
2810  |  | /*  | 
2811  |  | * xsltParseExclResultPrefixes:  | 
2812  |  | *  | 
2813  |  | * Create and store the list of in-scope namespaces for the given  | 
2814  |  | * node in the stylesheet. If there are no changes in the in-scope  | 
2815  |  | * namespaces then the last ns-info of the ancestor axis will be returned.  | 
2816  |  | * Compilation-time only.  | 
2817  |  | *  | 
2818  |  | * Returns the ns-info or NULL if there are no namespaces in scope.  | 
2819  |  | */  | 
2820  |  | static xsltPointerListPtr  | 
2821  |  | xsltParseExclResultPrefixes(xsltCompilerCtxtPtr cctxt, xmlNodePtr node,  | 
2822  |  |           xsltPointerListPtr def,  | 
2823  |  |           int instrCategory)  | 
2824  |  | { | 
2825  |  |     xsltPointerListPtr list = NULL;  | 
2826  |  |     xmlChar *value;  | 
2827  |  |     xmlAttrPtr attr;  | 
2828  |  |  | 
2829  |  |     if ((cctxt == NULL) || (node == NULL))  | 
2830  |  |   return(NULL);  | 
2831  |  |  | 
2832  |  |     if (instrCategory == XSLT_ELEMENT_CATEGORY_XSLT)  | 
2833  |  |   attr = xmlHasNsProp(node, BAD_CAST "exclude-result-prefixes", NULL);  | 
2834  |  |     else  | 
2835  |  |   attr = xmlHasNsProp(node, BAD_CAST "exclude-result-prefixes",  | 
2836  |  |       XSLT_NAMESPACE);  | 
2837  |  |     if (attr == NULL)  | 
2838  |  |   return(def);  | 
2839  |  |  | 
2840  |  |     if (attr && (instrCategory == XSLT_ELEMENT_CATEGORY_LRE)) { | 
2841  |  |   /*  | 
2842  |  |   * Mark the XSLT attr.  | 
2843  |  |   */  | 
2844  |  |   attr->psvi = (void *) xsltXSLTAttrMarker;  | 
2845  |  |     }  | 
2846  |  |  | 
2847  |  |     if ((attr->children != NULL) &&  | 
2848  |  |   (attr->children->content != NULL))  | 
2849  |  |   value = attr->children->content;  | 
2850  |  |     else { | 
2851  |  |   xsltTransformError(NULL, cctxt->style, node,  | 
2852  |  |       "Attribute 'exclude-result-prefixes': Invalid value.\n");  | 
2853  |  |   cctxt->style->errors++;  | 
2854  |  |   return(def);  | 
2855  |  |     }  | 
2856  |  |  | 
2857  |  |     if (xsltParseNsPrefixList(cctxt, cctxt->tmpList, node,  | 
2858  |  |   BAD_CAST value) != 0)  | 
2859  |  |   goto exit;  | 
2860  |  |     if (cctxt->tmpList->number == 0)  | 
2861  |  |   goto exit;  | 
2862  |  |     /*  | 
2863  |  |     * Merge the list with the inherited list.  | 
2864  |  |     */  | 
2865  |  |     list = xsltCompilerUtilsCreateMergedList(def, cctxt->tmpList);  | 
2866  |  |     if (list == NULL)  | 
2867  |  |   goto exit;  | 
2868  |  |     /*  | 
2869  |  |     * Store the list in the stylesheet/compiler context.  | 
2870  |  |     */  | 
2871  |  |     if (xsltPointerListAddSize(  | 
2872  |  |   cctxt->psData->exclResultNamespaces, list, 5) == -1)  | 
2873  |  |     { | 
2874  |  |   xsltPointerListFree(list);  | 
2875  |  |   list = NULL;  | 
2876  |  |   goto exit;  | 
2877  |  |     }  | 
2878  |  |     /*  | 
2879  |  |     * Notify of change in status wrt namespaces.  | 
2880  |  |     */  | 
2881  |  |     if (cctxt->inode != NULL)  | 
2882  |  |   cctxt->inode->nsChanged = 1;  | 
2883  |  |  | 
2884  |  | exit:  | 
2885  |  |     if (list != NULL)  | 
2886  |  |   return(list);  | 
2887  |  |     else  | 
2888  |  |   return(def);  | 
2889  |  | }  | 
2890  |  |  | 
2891  |  | /*  | 
2892  |  | * xsltParseExtElemPrefixes:  | 
2893  |  | *  | 
2894  |  | * Create and store the list of in-scope namespaces for the given  | 
2895  |  | * node in the stylesheet. If there are no changes in the in-scope  | 
2896  |  | * namespaces then the last ns-info of the ancestor axis will be returned.  | 
2897  |  | * Compilation-time only.  | 
2898  |  | *  | 
2899  |  | * Returns the ns-info or NULL if there are no namespaces in scope.  | 
2900  |  | */  | 
2901  |  | static xsltPointerListPtr  | 
2902  |  | xsltParseExtElemPrefixes(xsltCompilerCtxtPtr cctxt, xmlNodePtr node,  | 
2903  |  |        xsltPointerListPtr def,  | 
2904  |  |        int instrCategory)  | 
2905  |  | { | 
2906  |  |     xsltPointerListPtr list = NULL;  | 
2907  |  |     xmlAttrPtr attr;  | 
2908  |  |     xmlChar *value;  | 
2909  |  |     int i;  | 
2910  |  |  | 
2911  |  |     if ((cctxt == NULL) || (node == NULL))  | 
2912  |  |   return(NULL);  | 
2913  |  |  | 
2914  |  |     if (instrCategory == XSLT_ELEMENT_CATEGORY_XSLT)  | 
2915  |  |   attr = xmlHasNsProp(node, BAD_CAST "extension-element-prefixes", NULL);  | 
2916  |  |     else  | 
2917  |  |   attr = xmlHasNsProp(node, BAD_CAST "extension-element-prefixes",  | 
2918  |  |       XSLT_NAMESPACE);  | 
2919  |  |     if (attr == NULL)  | 
2920  |  |   return(def);  | 
2921  |  |  | 
2922  |  |     if (attr && (instrCategory == XSLT_ELEMENT_CATEGORY_LRE)) { | 
2923  |  |   /*  | 
2924  |  |   * Mark the XSLT attr.  | 
2925  |  |   */  | 
2926  |  |   attr->psvi = (void *) xsltXSLTAttrMarker;  | 
2927  |  |     }  | 
2928  |  |  | 
2929  |  |     if ((attr->children != NULL) &&  | 
2930  |  |   (attr->children->content != NULL))  | 
2931  |  |   value = attr->children->content;  | 
2932  |  |     else { | 
2933  |  |   xsltTransformError(NULL, cctxt->style, node,  | 
2934  |  |       "Attribute 'extension-element-prefixes': Invalid value.\n");  | 
2935  |  |   cctxt->style->errors++;  | 
2936  |  |   return(def);  | 
2937  |  |     }  | 
2938  |  |  | 
2939  |  |  | 
2940  |  |     if (xsltParseNsPrefixList(cctxt, cctxt->tmpList, node,  | 
2941  |  |   BAD_CAST value) != 0)  | 
2942  |  |   goto exit;  | 
2943  |  |  | 
2944  |  |     if (cctxt->tmpList->number == 0)  | 
2945  |  |   goto exit;  | 
2946  |  |     /*  | 
2947  |  |     * REVISIT: Register the extension namespaces.  | 
2948  |  |     */  | 
2949  |  |     for (i = 0; i < cctxt->tmpList->number; i++)  | 
2950  |  |   xsltRegisterExtPrefix(cctxt->style, NULL,  | 
2951  |  |   BAD_CAST cctxt->tmpList->items[i]);  | 
2952  |  |     /*  | 
2953  |  |     * Merge the list with the inherited list.  | 
2954  |  |     */  | 
2955  |  |     list = xsltCompilerUtilsCreateMergedList(def, cctxt->tmpList);  | 
2956  |  |     if (list == NULL)  | 
2957  |  |   goto exit;  | 
2958  |  |     /*  | 
2959  |  |     * Store the list in the stylesheet.  | 
2960  |  |     */  | 
2961  |  |     if (xsltPointerListAddSize(  | 
2962  |  |   cctxt->psData->extElemNamespaces, list, 5) == -1)  | 
2963  |  |     { | 
2964  |  |   xsltPointerListFree(list);  | 
2965  |  |   list = NULL;  | 
2966  |  |   goto exit;  | 
2967  |  |     }  | 
2968  |  |     /*  | 
2969  |  |     * Notify of change in status wrt namespaces.  | 
2970  |  |     */  | 
2971  |  |     if (cctxt->inode != NULL)  | 
2972  |  |   cctxt->inode->nsChanged = 1;  | 
2973  |  |  | 
2974  |  | exit:  | 
2975  |  |     if (list != NULL)  | 
2976  |  |   return(list);  | 
2977  |  |     else  | 
2978  |  |   return(def);  | 
2979  |  | }  | 
2980  |  |  | 
2981  |  | /*  | 
2982  |  | * xsltParseAttrXSLTVersion:  | 
2983  |  | *  | 
2984  |  | * @cctxt: the compilation context  | 
2985  |  | * @node: the element-node  | 
2986  |  | * @isXsltElem: whether this is an XSLT element  | 
2987  |  | *  | 
2988  |  | * Parses the attribute xsl:version.  | 
2989  |  | *  | 
2990  |  | * Returns 1 if there was such an attribute, 0 if not and  | 
2991  |  | *         -1 if an internal or API error occured.  | 
2992  |  | */  | 
2993  |  | static int  | 
2994  |  | xsltParseAttrXSLTVersion(xsltCompilerCtxtPtr cctxt, xmlNodePtr node,  | 
2995  |  |        int instrCategory)  | 
2996  |  | { | 
2997  |  |     xmlChar *value;  | 
2998  |  |     xmlAttrPtr attr;  | 
2999  |  |  | 
3000  |  |     if ((cctxt == NULL) || (node == NULL))  | 
3001  |  |   return(-1);  | 
3002  |  |  | 
3003  |  |     if (instrCategory == XSLT_ELEMENT_CATEGORY_XSLT)  | 
3004  |  |   attr = xmlHasNsProp(node, BAD_CAST "version", NULL);  | 
3005  |  |     else  | 
3006  |  |   attr = xmlHasNsProp(node, BAD_CAST "version", XSLT_NAMESPACE);  | 
3007  |  |  | 
3008  |  |     if (attr == NULL)  | 
3009  |  |   return(0);  | 
3010  |  |  | 
3011  |  |     attr->psvi = (void *) xsltXSLTAttrMarker;  | 
3012  |  |  | 
3013  |  |     if ((attr->children != NULL) &&  | 
3014  |  |   (attr->children->content != NULL))  | 
3015  |  |   value = attr->children->content;  | 
3016  |  |     else { | 
3017  |  |   xsltTransformError(NULL, cctxt->style, node,  | 
3018  |  |       "Attribute 'version': Invalid value.\n");  | 
3019  |  |   cctxt->style->errors++;  | 
3020  |  |   return(1);  | 
3021  |  |     }  | 
3022  |  |  | 
3023  |  |     if (! xmlStrEqual(value, (const xmlChar *)"1.0")) { | 
3024  |  |   cctxt->inode->forwardsCompat = 1;  | 
3025  |  |   /*  | 
3026  |  |   * TODO: To what extent do we support the  | 
3027  |  |   *  forwards-compatible mode?  | 
3028  |  |   */  | 
3029  |  |   /*  | 
3030  |  |   * Report this only once per compilation episode.  | 
3031  |  |   */  | 
3032  |  |   if (! cctxt->hasForwardsCompat) { | 
3033  |  |       cctxt->hasForwardsCompat = 1;  | 
3034  |  |       cctxt->errSeverity = XSLT_ERROR_SEVERITY_WARNING;  | 
3035  |  |       xsltTransformError(NULL, cctxt->style, node,  | 
3036  |  |     "Warning: the attribute xsl:version specifies a value "  | 
3037  |  |     "different from '1.0'. Switching to forwards-compatible "  | 
3038  |  |     "mode. Only features of XSLT 1.0 are supported by this "  | 
3039  |  |     "processor.\n");  | 
3040  |  |       cctxt->style->warnings++;  | 
3041  |  |       cctxt->errSeverity = XSLT_ERROR_SEVERITY_ERROR;  | 
3042  |  |   }  | 
3043  |  |     } else { | 
3044  |  |   cctxt->inode->forwardsCompat = 0;  | 
3045  |  |     }  | 
3046  |  |  | 
3047  |  |     if (attr && (instrCategory == XSLT_ELEMENT_CATEGORY_LRE)) { | 
3048  |  |   /*  | 
3049  |  |   * Set a marker on XSLT attributes.  | 
3050  |  |   */  | 
3051  |  |   attr->psvi = (void *) xsltXSLTAttrMarker;  | 
3052  |  |     }  | 
3053  |  |     return(1);  | 
3054  |  | }  | 
3055  |  |  | 
3056  |  | static int  | 
3057  |  | xsltParsePreprocessStylesheetTree(xsltCompilerCtxtPtr cctxt, xmlNodePtr node)  | 
3058  |  | { | 
3059  |  |     xmlNodePtr deleteNode, cur, txt, textNode = NULL;  | 
3060  |  |     xmlDocPtr doc;  | 
3061  |  |     xsltStylesheetPtr style;  | 
3062  |  |     int internalize = 0, findSpaceAttr;  | 
3063  |  |     int xsltStylesheetElemDepth;  | 
3064  |  |     xmlAttrPtr attr;  | 
3065  |  |     xmlChar *value;  | 
3066  |  |     const xmlChar *name, *nsNameXSLT = NULL;  | 
3067  |  |     int strictWhitespace, inXSLText = 0;  | 
3068  |  | #ifdef XSLT_REFACTORED_XSLT_NSCOMP  | 
3069  |  |     xsltNsMapPtr nsMapItem;  | 
3070  |  | #endif  | 
3071  |  |  | 
3072  |  |     if ((cctxt == NULL) || (cctxt->style == NULL) ||  | 
3073  |  |   (node == NULL) || (node->type != XML_ELEMENT_NODE))  | 
3074  |  |         return(-1);  | 
3075  |  |  | 
3076  |  |     doc = node->doc;  | 
3077  |  |     if (doc == NULL)  | 
3078  |  |   goto internal_err;  | 
3079  |  |  | 
3080  |  |     style = cctxt->style;  | 
3081  |  |     if ((style->dict != NULL) && (doc->dict == style->dict))  | 
3082  |  |   internalize = 1;  | 
3083  |  |     else  | 
3084  |  |         style->internalized = 0;  | 
3085  |  |  | 
3086  |  |     /*  | 
3087  |  |     * Init value of xml:space. Since this might be an embedded  | 
3088  |  |     * stylesheet, this is needed to be performed on the element  | 
3089  |  |     * where the stylesheet is rooted at, taking xml:space of  | 
3090  |  |     * ancestors into account.  | 
3091  |  |     */  | 
3092  |  |     if (! cctxt->simplified)  | 
3093  |  |   xsltStylesheetElemDepth = cctxt->depth +1;  | 
3094  |  |     else  | 
3095  |  |   xsltStylesheetElemDepth = 0;  | 
3096  |  |  | 
3097  |  |     if (xmlNodeGetSpacePreserve(node) != 1)  | 
3098  |  |   cctxt->inode->preserveWhitespace = 0;  | 
3099  |  |     else  | 
3100  |  |   cctxt->inode->preserveWhitespace = 1;  | 
3101  |  |  | 
3102  |  |     /*  | 
3103  |  |     * Eval if we should keep the old incorrect behaviour.  | 
3104  |  |     */  | 
3105  |  |     strictWhitespace = (cctxt->strict != 0) ? 1 : 0;  | 
3106  |  |  | 
3107  |  |     nsNameXSLT = xsltConstNamespaceNameXSLT;  | 
3108  |  |  | 
3109  |  |     deleteNode = NULL;  | 
3110  |  |     cur = node;  | 
3111  |  |     while (cur != NULL) { | 
3112  |  |   if (deleteNode != NULL) { | 
3113  |  |  | 
3114  |  | #ifdef WITH_XSLT_DEBUG_BLANKS  | 
3115  |  |       xsltGenericDebug(xsltGenericDebugContext,  | 
3116  |  |        "xsltParsePreprocessStylesheetTree: removing node\n");  | 
3117  |  | #endif  | 
3118  |  |       xmlUnlinkNode(deleteNode);  | 
3119  |  |       xmlFreeNode(deleteNode);  | 
3120  |  |       deleteNode = NULL;  | 
3121  |  |   }  | 
3122  |  |   if (cur->type == XML_ELEMENT_NODE) { | 
3123  |  |  | 
3124  |  |       /*  | 
3125  |  |       * Clear the PSVI field.  | 
3126  |  |       */  | 
3127  |  |       cur->psvi = NULL;  | 
3128  |  |  | 
3129  |  |       xsltCompilerNodePush(cctxt, cur);  | 
3130  |  |  | 
3131  |  |       inXSLText = 0;  | 
3132  |  |       textNode = NULL;  | 
3133  |  |       findSpaceAttr = 1;  | 
3134  |  |       cctxt->inode->stripWhitespace = 0;  | 
3135  |  |       /*  | 
3136  |  |       * TODO: I'd love to use a string pointer comparison here :-/  | 
3137  |  |       */  | 
3138  |  |       if (IS_XSLT_ELEM(cur)) { | 
3139  |  | #ifdef XSLT_REFACTORED_XSLT_NSCOMP  | 
3140  |  |     if (cur->ns->href != nsNameXSLT) { | 
3141  |  |         nsMapItem = xsltNewNamespaceMapItem(cctxt,  | 
3142  |  |       doc, cur->ns, cur);  | 
3143  |  |         if (nsMapItem == NULL)  | 
3144  |  |       goto internal_err;  | 
3145  |  |         cur->ns->href = nsNameXSLT;  | 
3146  |  |     }  | 
3147  |  | #endif  | 
3148  |  |  | 
3149  |  |     if (cur->name == NULL)  | 
3150  |  |         goto process_attributes;  | 
3151  |  |     /*  | 
3152  |  |     * Mark the XSLT element for later recognition.  | 
3153  |  |     * TODO: Using the marker is still too dangerous, since if  | 
3154  |  |     *   the parsing mechanism leaves out an XSLT element, then  | 
3155  |  |     *   this might hit the transformation-mechanism, which  | 
3156  |  |     *   will break if it doesn't expect such a marker.  | 
3157  |  |     */  | 
3158  |  |     /* cur->psvi = (void *) xsltXSLTElemMarker; */  | 
3159  |  |  | 
3160  |  |     /*  | 
3161  |  |     * XSLT 2.0: "Any whitespace text node whose parent is  | 
3162  |  |     * one of the following elements is removed from the "  | 
3163  |  |     * tree, regardless of any xml:space attributes:..."  | 
3164  |  |     * xsl:apply-imports,  | 
3165  |  |     * xsl:apply-templates,  | 
3166  |  |     * xsl:attribute-set,  | 
3167  |  |     * xsl:call-template,  | 
3168  |  |     * xsl:choose,  | 
3169  |  |     * xsl:stylesheet, xsl:transform.  | 
3170  |  |     * XSLT 2.0: xsl:analyze-string,  | 
3171  |  |     *           xsl:character-map,  | 
3172  |  |     *           xsl:next-match  | 
3173  |  |     *  | 
3174  |  |     * TODO: I'd love to use a string pointer comparison here :-/  | 
3175  |  |     */  | 
3176  |  |     name = cur->name;  | 
3177  |  |     switch (*name) { | 
3178  |  |         case 't':  | 
3179  |  |       if ((name[0] == 't') && (name[1] == 'e') &&  | 
3180  |  |           (name[2] == 'x') && (name[3] == 't') &&  | 
3181  |  |           (name[4] == 0))  | 
3182  |  |       { | 
3183  |  |           /*  | 
3184  |  |           * Process the xsl:text element.  | 
3185  |  |           * ----------------------------  | 
3186  |  |           * Mark it for later recognition.  | 
3187  |  |           */  | 
3188  |  |           cur->psvi = (void *) xsltXSLTTextMarker;  | 
3189  |  |           /*  | 
3190  |  |           * For stylesheets, the set of  | 
3191  |  |           * whitespace-preserving element names  | 
3192  |  |           * consists of just xsl:text.  | 
3193  |  |           */  | 
3194  |  |           findSpaceAttr = 0;  | 
3195  |  |           cctxt->inode->preserveWhitespace = 1;  | 
3196  |  |           inXSLText = 1;  | 
3197  |  |       }  | 
3198  |  |       break;  | 
3199  |  |         case 'c':  | 
3200  |  |       if (xmlStrEqual(name, BAD_CAST "choose") ||  | 
3201  |  |           xmlStrEqual(name, BAD_CAST "call-template"))  | 
3202  |  |           cctxt->inode->stripWhitespace = 1;  | 
3203  |  |       break;  | 
3204  |  |         case 'a':  | 
3205  |  |       if (xmlStrEqual(name, BAD_CAST "apply-templates") ||  | 
3206  |  |           xmlStrEqual(name, BAD_CAST "apply-imports") ||  | 
3207  |  |           xmlStrEqual(name, BAD_CAST "attribute-set"))  | 
3208  |  |  | 
3209  |  |           cctxt->inode->stripWhitespace = 1;  | 
3210  |  |       break;  | 
3211  |  |         default:  | 
3212  |  |       if (xsltStylesheetElemDepth == cctxt->depth) { | 
3213  |  |           /*  | 
3214  |  |           * This is a xsl:stylesheet/xsl:transform.  | 
3215  |  |           */  | 
3216  |  |           cctxt->inode->stripWhitespace = 1;  | 
3217  |  |           break;  | 
3218  |  |       }  | 
3219  |  |  | 
3220  |  |       if ((cur->prev != NULL) &&  | 
3221  |  |           (cur->prev->type == XML_TEXT_NODE))  | 
3222  |  |       { | 
3223  |  |           /*  | 
3224  |  |           * XSLT 2.0 : "Any whitespace text node whose  | 
3225  |  |           *  following-sibling node is an xsl:param or  | 
3226  |  |           *  xsl:sort element is removed from the tree,  | 
3227  |  |           *  regardless of any xml:space attributes."  | 
3228  |  |           */  | 
3229  |  |           if (((*name == 'p') || (*name == 's')) &&  | 
3230  |  |         (xmlStrEqual(name, BAD_CAST "param") ||  | 
3231  |  |          xmlStrEqual(name, BAD_CAST "sort")))  | 
3232  |  |           { | 
3233  |  |         do { | 
3234  |  |             if (IS_BLANK_NODE(cur->prev)) { | 
3235  |  |           txt = cur->prev;  | 
3236  |  |           xmlUnlinkNode(txt);  | 
3237  |  |           xmlFreeNode(txt);  | 
3238  |  |             } else { | 
3239  |  |           /*  | 
3240  |  |           * This will result in a content  | 
3241  |  |           * error, when hitting the parsing  | 
3242  |  |           * functions.  | 
3243  |  |           */  | 
3244  |  |           break;  | 
3245  |  |             }  | 
3246  |  |         } while (cur->prev);  | 
3247  |  |           }  | 
3248  |  |       }  | 
3249  |  |       break;  | 
3250  |  |     }  | 
3251  |  |       }  | 
3252  |  |  | 
3253  |  | process_attributes:  | 
3254  |  |       /*  | 
3255  |  |       * Process attributes.  | 
3256  |  |       * ------------------  | 
3257  |  |       */  | 
3258  |  |       if (cur->properties != NULL) { | 
3259  |  |     if (cur->children == NULL)  | 
3260  |  |         findSpaceAttr = 0;  | 
3261  |  |     attr = cur->properties;  | 
3262  |  |     do { | 
3263  |  | #ifdef XSLT_REFACTORED_XSLT_NSCOMP  | 
3264  |  |         if ((attr->ns) && (attr->ns->href != nsNameXSLT) &&  | 
3265  |  |       xmlStrEqual(attr->ns->href, nsNameXSLT))  | 
3266  |  |         { | 
3267  |  |       nsMapItem = xsltNewNamespaceMapItem(cctxt,  | 
3268  |  |           doc, attr->ns, cur);  | 
3269  |  |       if (nsMapItem == NULL)  | 
3270  |  |           goto internal_err;  | 
3271  |  |       attr->ns->href = nsNameXSLT;  | 
3272  |  |         }  | 
3273  |  | #endif  | 
3274  |  |         if (internalize) { | 
3275  |  |       /*  | 
3276  |  |       * Internalize the attribute's value; the goal is to  | 
3277  |  |       * speed up operations and minimize used space by  | 
3278  |  |       * compiled stylesheets.  | 
3279  |  |       */  | 
3280  |  |       txt = attr->children;  | 
3281  |  |       /*  | 
3282  |  |       * NOTE that this assumes only one  | 
3283  |  |       *  text-node in the attribute's content.  | 
3284  |  |       */  | 
3285  |  |       if ((txt != NULL) && (txt->content != NULL) &&  | 
3286  |  |           (!xmlDictOwns(style->dict, txt->content)))  | 
3287  |  |       { | 
3288  |  |           value = (xmlChar *) xmlDictLookup(style->dict,  | 
3289  |  |         txt->content, -1);  | 
3290  |  |           xmlNodeSetContent(txt, NULL);  | 
3291  |  |           txt->content = value;  | 
3292  |  |       }  | 
3293  |  |         }  | 
3294  |  |         /*  | 
3295  |  |         * Process xml:space attributes.  | 
3296  |  |         * ----------------------------  | 
3297  |  |         */  | 
3298  |  |         if ((findSpaceAttr != 0) &&  | 
3299  |  |       (attr->ns != NULL) &&  | 
3300  |  |       (attr->name != NULL) &&  | 
3301  |  |       (attr->name[0] == 's') &&  | 
3302  |  |       (attr->ns->prefix != NULL) &&  | 
3303  |  |       (attr->ns->prefix[0] == 'x') &&  | 
3304  |  |       (attr->ns->prefix[1] == 'm') &&  | 
3305  |  |       (attr->ns->prefix[2] == 'l') &&  | 
3306  |  |       (attr->ns->prefix[3] == 0))  | 
3307  |  |         { | 
3308  |  |       value = xmlGetNsProp(cur, BAD_CAST "space",  | 
3309  |  |           XML_XML_NAMESPACE);  | 
3310  |  |       if (value != NULL) { | 
3311  |  |           if (xmlStrEqual(value, BAD_CAST "preserve")) { | 
3312  |  |         cctxt->inode->preserveWhitespace = 1;  | 
3313  |  |           } else if (xmlStrEqual(value, BAD_CAST "default")) { | 
3314  |  |         cctxt->inode->preserveWhitespace = 0;  | 
3315  |  |           } else { | 
3316  |  |         /* Invalid value for xml:space. */  | 
3317  |  |         xsltTransformError(NULL, style, cur,  | 
3318  |  |             "Attribute xml:space: Invalid value.\n");  | 
3319  |  |         cctxt->style->warnings++;  | 
3320  |  |           }  | 
3321  |  |           findSpaceAttr = 0;  | 
3322  |  |           xmlFree(value);  | 
3323  |  |       }  | 
3324  |  |  | 
3325  |  |         }  | 
3326  |  |         attr = attr->next;  | 
3327  |  |     } while (attr != NULL);  | 
3328  |  |       }  | 
3329  |  |       /*  | 
3330  |  |       * We'll descend into the children of element nodes only.  | 
3331  |  |       */  | 
3332  |  |       if (cur->children != NULL) { | 
3333  |  |     cur = cur->children;  | 
3334  |  |     continue;  | 
3335  |  |       }  | 
3336  |  |   } else if ((cur->type == XML_TEXT_NODE) ||  | 
3337  |  |     (cur->type == XML_CDATA_SECTION_NODE))  | 
3338  |  |   { | 
3339  |  |       /*  | 
3340  |  |       * Merge adjacent text/CDATA-section-nodes  | 
3341  |  |       * ---------------------------------------  | 
3342  |  |       * In order to avoid breaking of existing stylesheets,  | 
3343  |  |       * if the old behaviour is wanted (strictWhitespace == 0),  | 
3344  |  |       * then we *won't* merge adjacent text-nodes  | 
3345  |  |       * (except in xsl:text); this will ensure that whitespace-only  | 
3346  |  |       * text nodes are (incorrectly) not stripped in some cases.  | 
3347  |  |       *  | 
3348  |  |       * Example:               : <foo>  <!-- bar -->zoo</foo>  | 
3349  |  |       * Corrent (strict) result: <foo>  zoo</foo>  | 
3350  |  |       * Incorrect (old) result : <foo>zoo</foo>  | 
3351  |  |       *  | 
3352  |  |       * NOTE that we *will* merge adjacent text-nodes if  | 
3353  |  |       * they are in xsl:text.  | 
3354  |  |       * Example, the following:  | 
3355  |  |       * <xsl:text>  <!-- bar -->zoo<xsl:text>  | 
3356  |  |       * will result in both cases in:  | 
3357  |  |       * <xsl:text>  zoo<xsl:text>  | 
3358  |  |       */  | 
3359  |  |       cur->type = XML_TEXT_NODE;  | 
3360  |  |       if ((strictWhitespace != 0) || (inXSLText != 0)) { | 
3361  |  |     /*  | 
3362  |  |     * New behaviour; merge nodes.  | 
3363  |  |     */  | 
3364  |  |     if (textNode == NULL)  | 
3365  |  |         textNode = cur;  | 
3366  |  |     else { | 
3367  |  |         if (cur->content != NULL)  | 
3368  |  |       xmlNodeAddContent(textNode, cur->content);  | 
3369  |  |         deleteNode = cur;  | 
3370  |  |     }  | 
3371  |  |     if ((cur->next == NULL) ||  | 
3372  |  |         (cur->next->type == XML_ELEMENT_NODE))  | 
3373  |  |         goto end_of_text;  | 
3374  |  |     else  | 
3375  |  |         goto next_sibling;  | 
3376  |  |       } else { | 
3377  |  |     /*  | 
3378  |  |     * Old behaviour.  | 
3379  |  |     */  | 
3380  |  |     if (textNode == NULL)  | 
3381  |  |         textNode = cur;  | 
3382  |  |     goto end_of_text;  | 
3383  |  |       }  | 
3384  |  |   } else if ((cur->type == XML_COMMENT_NODE) ||  | 
3385  |  |       (cur->type == XML_PI_NODE))  | 
3386  |  |   { | 
3387  |  |       /*  | 
3388  |  |       * Remove processing instructions and comments.  | 
3389  |  |       */  | 
3390  |  |       deleteNode = cur;  | 
3391  |  |       if ((cur->next == NULL) ||  | 
3392  |  |     (cur->next->type == XML_ELEMENT_NODE))  | 
3393  |  |     goto end_of_text;  | 
3394  |  |       else  | 
3395  |  |     goto next_sibling;  | 
3396  |  |   } else { | 
3397  |  |       textNode = NULL;  | 
3398  |  |       /*  | 
3399  |  |       * Invalid node-type for this data-model.  | 
3400  |  |       */  | 
3401  |  |       xsltTransformError(NULL, style, cur,  | 
3402  |  |     "Invalid type of node for the XSLT data model.\n");  | 
3403  |  |       cctxt->style->errors++;  | 
3404  |  |       goto next_sibling;  | 
3405  |  |   }  | 
3406  |  |  | 
3407  |  | end_of_text:  | 
3408  |  |   if (textNode) { | 
3409  |  |       value = textNode->content;  | 
3410  |  |       /*  | 
3411  |  |       * At this point all adjacent text/CDATA-section nodes  | 
3412  |  |       * have been merged.  | 
3413  |  |       *  | 
3414  |  |       * Strip whitespace-only text-nodes.  | 
3415  |  |       * (cctxt->inode->stripWhitespace)  | 
3416  |  |       */  | 
3417  |  |       if ((value == NULL) || (*value == 0) ||  | 
3418  |  |     (((cctxt->inode->stripWhitespace) ||  | 
3419  |  |       (! cctxt->inode->preserveWhitespace)) &&  | 
3420  |  |      IS_BLANK(*value) &&  | 
3421  |  |      xsltIsBlank(value)))  | 
3422  |  |       { | 
3423  |  |     if (textNode != cur) { | 
3424  |  |         xmlUnlinkNode(textNode);  | 
3425  |  |         xmlFreeNode(textNode);  | 
3426  |  |     } else  | 
3427  |  |         deleteNode = textNode;  | 
3428  |  |     textNode = NULL;  | 
3429  |  |     goto next_sibling;  | 
3430  |  |       }  | 
3431  |  |       /*  | 
3432  |  |       * Convert CDATA-section nodes to text-nodes.  | 
3433  |  |       * TODO: Can this produce problems?  | 
3434  |  |       */  | 
3435  |  |       if (textNode->type != XML_TEXT_NODE) { | 
3436  |  |     textNode->type = XML_TEXT_NODE;  | 
3437  |  |     textNode->name = xmlStringText;  | 
3438  |  |       }  | 
3439  |  |       if (internalize &&  | 
3440  |  |     (textNode->content != NULL) &&  | 
3441  |  |     (!xmlDictOwns(style->dict, textNode->content)))  | 
3442  |  |       { | 
3443  |  |     /*  | 
3444  |  |     * Internalize the string.  | 
3445  |  |     */  | 
3446  |  |     value = (xmlChar *) xmlDictLookup(style->dict,  | 
3447  |  |         textNode->content, -1);  | 
3448  |  |     xmlNodeSetContent(textNode, NULL);  | 
3449  |  |     textNode->content = value;  | 
3450  |  |       }  | 
3451  |  |       textNode = NULL;  | 
3452  |  |       /*  | 
3453  |  |       * Note that "disable-output-escaping" of the xsl:text  | 
3454  |  |       * element will be applied at a later level, when  | 
3455  |  |       * XSLT elements are processed.  | 
3456  |  |       */  | 
3457  |  |   }  | 
3458  |  |  | 
3459  |  | next_sibling:  | 
3460  |  |   if (cur->type == XML_ELEMENT_NODE) { | 
3461  |  |       xsltCompilerNodePop(cctxt, cur);  | 
3462  |  |   }  | 
3463  |  |   if (cur == node)  | 
3464  |  |       break;  | 
3465  |  |   if (cur->next != NULL) { | 
3466  |  |       cur = cur->next;  | 
3467  |  |   } else { | 
3468  |  |       cur = cur->parent;  | 
3469  |  |       inXSLText = 0;  | 
3470  |  |       goto next_sibling;  | 
3471  |  |   };  | 
3472  |  |     }  | 
3473  |  |     if (deleteNode != NULL) { | 
3474  |  | #ifdef WITH_XSLT_DEBUG_PARSING  | 
3475  |  |   xsltGenericDebug(xsltGenericDebugContext,  | 
3476  |  |    "xsltParsePreprocessStylesheetTree: removing node\n");  | 
3477  |  | #endif  | 
3478  |  |   xmlUnlinkNode(deleteNode);  | 
3479  |  |   xmlFreeNode(deleteNode);  | 
3480  |  |     }  | 
3481  |  |     return(0);  | 
3482  |  |  | 
3483  |  | internal_err:  | 
3484  |  |     return(-1);  | 
3485  |  | }  | 
3486  |  |  | 
3487  |  | #endif /* XSLT_REFACTORED */  | 
3488  |  |  | 
3489  |  | #ifdef XSLT_REFACTORED  | 
3490  |  | #else  | 
3491  |  | static void  | 
3492  |  | xsltPreprocessStylesheet(xsltStylesheetPtr style, xmlNodePtr cur)  | 
3493  | 0  | { | 
3494  | 0  |     xmlNodePtr deleteNode, styleelem;  | 
3495  | 0  |     int internalize = 0;  | 
3496  |  | 
  | 
3497  | 0  |     if ((style == NULL) || (cur == NULL))  | 
3498  | 0  |         return;  | 
3499  |  |  | 
3500  | 0  |     if ((cur->doc != NULL) && (style->dict != NULL) &&  | 
3501  | 0  |         (cur->doc->dict == style->dict))  | 
3502  | 0  |   internalize = 1;  | 
3503  | 0  |     else  | 
3504  | 0  |         style->internalized = 0;  | 
3505  |  | 
  | 
3506  | 0  |     if ((cur != NULL) && (IS_XSLT_ELEM(cur)) &&  | 
3507  | 0  |         (IS_XSLT_NAME(cur, "stylesheet"))) { | 
3508  | 0  |   styleelem = cur;  | 
3509  | 0  |     } else { | 
3510  | 0  |         styleelem = NULL;  | 
3511  | 0  |     }  | 
3512  |  |  | 
3513  |  |     /*  | 
3514  |  |      * This content comes from the stylesheet  | 
3515  |  |      * For stylesheets, the set of whitespace-preserving  | 
3516  |  |      * element names consists of just xsl:text.  | 
3517  |  |      */  | 
3518  | 0  |     deleteNode = NULL;  | 
3519  | 0  |     while (cur != NULL) { | 
3520  | 0  |   if (deleteNode != NULL) { | 
3521  |  | #ifdef WITH_XSLT_DEBUG_BLANKS  | 
3522  |  |       xsltGenericDebug(xsltGenericDebugContext,  | 
3523  |  |        "xsltPreprocessStylesheet: removing ignorable blank node\n");  | 
3524  |  | #endif  | 
3525  | 0  |       xmlUnlinkNode(deleteNode);  | 
3526  | 0  |       xmlFreeNode(deleteNode);  | 
3527  | 0  |       deleteNode = NULL;  | 
3528  | 0  |   }  | 
3529  | 0  |   if (cur->type == XML_ELEMENT_NODE) { | 
3530  | 0  |       int exclPrefixes;  | 
3531  |  |       /*  | 
3532  |  |        * Internalize attributes values.  | 
3533  |  |        */  | 
3534  | 0  |       if ((internalize) && (cur->properties != NULL)) { | 
3535  | 0  |           xmlAttrPtr attr = cur->properties;  | 
3536  | 0  |     xmlNodePtr txt;  | 
3537  |  | 
  | 
3538  | 0  |     while (attr != NULL) { | 
3539  | 0  |         txt = attr->children;  | 
3540  | 0  |         if ((txt != NULL) && (txt->type == XML_TEXT_NODE) &&  | 
3541  | 0  |             (txt->content != NULL) &&  | 
3542  | 0  |       (!xmlDictOwns(style->dict, txt->content)))  | 
3543  | 0  |         { | 
3544  | 0  |       xmlChar *tmp;  | 
3545  |  |  | 
3546  |  |       /*  | 
3547  |  |        * internalize the text string, goal is to speed  | 
3548  |  |        * up operations and minimize used space by compiled  | 
3549  |  |        * stylesheets.  | 
3550  |  |        */  | 
3551  | 0  |       tmp = (xmlChar *) xmlDictLookup(style->dict,  | 
3552  | 0  |                                       txt->content, -1);  | 
3553  | 0  |       if (tmp != txt->content) { | 
3554  | 0  |           xmlNodeSetContent(txt, NULL);  | 
3555  | 0  |           txt->content = tmp;  | 
3556  | 0  |       }  | 
3557  | 0  |         }  | 
3558  | 0  |         attr = attr->next;  | 
3559  | 0  |     }  | 
3560  | 0  |       }  | 
3561  | 0  |       if (IS_XSLT_ELEM(cur)) { | 
3562  | 0  |     exclPrefixes = 0;  | 
3563  | 0  |     if (IS_XSLT_NAME(cur, "text")) { | 
3564  | 0  |         for (;exclPrefixes > 0;exclPrefixes--)  | 
3565  | 0  |       exclPrefixPop(style);  | 
3566  | 0  |         goto skip_children;  | 
3567  | 0  |     }  | 
3568  | 0  |       } else { | 
3569  | 0  |     exclPrefixes = xsltParseStylesheetExcludePrefix(style, cur, 0);  | 
3570  | 0  |       }  | 
3571  |  |  | 
3572  | 0  |       if ((cur->nsDef != NULL) && (style->exclPrefixNr > 0)) { | 
3573  | 0  |     xmlNsPtr ns = cur->nsDef, prev = NULL, next;  | 
3574  | 0  |     xmlNodePtr root = NULL;  | 
3575  | 0  |     int i, moved;  | 
3576  |  | 
  | 
3577  | 0  |     root = xmlDocGetRootElement(cur->doc);  | 
3578  | 0  |     if ((root != NULL) && (root != cur)) { | 
3579  | 0  |         while (ns != NULL) { | 
3580  | 0  |       moved = 0;  | 
3581  | 0  |       next = ns->next;  | 
3582  | 0  |       for (i = 0;i < style->exclPrefixNr;i++) { | 
3583  | 0  |           if ((ns->prefix != NULL) &&  | 
3584  | 0  |               (xmlStrEqual(ns->href,  | 
3585  | 0  |                style->exclPrefixTab[i]))) { | 
3586  |  |         /*  | 
3587  |  |          * Move the namespace definition on the root  | 
3588  |  |          * element to avoid duplicating it without  | 
3589  |  |          * loosing it.  | 
3590  |  |          */  | 
3591  | 0  |         if (prev == NULL) { | 
3592  | 0  |             cur->nsDef = ns->next;  | 
3593  | 0  |         } else { | 
3594  | 0  |             prev->next = ns->next;  | 
3595  | 0  |         }  | 
3596  | 0  |         ns->next = root->nsDef;  | 
3597  | 0  |         root->nsDef = ns;  | 
3598  | 0  |         moved = 1;  | 
3599  | 0  |         break;  | 
3600  | 0  |           }  | 
3601  | 0  |       }  | 
3602  | 0  |       if (moved == 0)  | 
3603  | 0  |           prev = ns;  | 
3604  | 0  |       ns = next;  | 
3605  | 0  |         }  | 
3606  | 0  |     }  | 
3607  | 0  |       }  | 
3608  |  |       /*  | 
3609  |  |        * If we have prefixes locally, recurse and pop them up when  | 
3610  |  |        * going back  | 
3611  |  |        */  | 
3612  | 0  |       if (exclPrefixes > 0) { | 
3613  | 0  |     xsltPreprocessStylesheet(style, cur->children);  | 
3614  | 0  |     for (;exclPrefixes > 0;exclPrefixes--)  | 
3615  | 0  |         exclPrefixPop(style);  | 
3616  | 0  |     goto skip_children;  | 
3617  | 0  |       }  | 
3618  | 0  |   } else if (cur->type == XML_TEXT_NODE) { | 
3619  | 0  |       if (IS_BLANK_NODE(cur)) { | 
3620  | 0  |     if (xmlNodeGetSpacePreserve(cur->parent) != 1) { | 
3621  | 0  |         deleteNode = cur;  | 
3622  | 0  |     }  | 
3623  | 0  |       } else if ((cur->content != NULL) && (internalize) &&  | 
3624  | 0  |                  (!xmlDictOwns(style->dict, cur->content))) { | 
3625  | 0  |     xmlChar *tmp;  | 
3626  |  |  | 
3627  |  |     /*  | 
3628  |  |      * internalize the text string, goal is to speed  | 
3629  |  |      * up operations and minimize used space by compiled  | 
3630  |  |      * stylesheets.  | 
3631  |  |      */  | 
3632  | 0  |     tmp = (xmlChar *) xmlDictLookup(style->dict, cur->content, -1);  | 
3633  | 0  |     xmlNodeSetContent(cur, NULL);  | 
3634  | 0  |     cur->content = tmp;  | 
3635  | 0  |       }  | 
3636  | 0  |   } else if ((cur->type != XML_ELEMENT_NODE) &&  | 
3637  | 0  |        (cur->type != XML_CDATA_SECTION_NODE)) { | 
3638  | 0  |       deleteNode = cur;  | 
3639  | 0  |       goto skip_children;  | 
3640  | 0  |   }  | 
3641  |  |  | 
3642  |  |   /*  | 
3643  |  |    * Skip to next node. In case of a namespaced element children of  | 
3644  |  |    * the stylesheet and not in the XSLT namespace and not an extension  | 
3645  |  |    * element, ignore its content.  | 
3646  |  |    */  | 
3647  | 0  |   if ((cur->type == XML_ELEMENT_NODE) && (cur->ns != NULL) &&  | 
3648  | 0  |       (styleelem != NULL) && (cur->parent == styleelem) &&  | 
3649  | 0  |       (!xmlStrEqual(cur->ns->href, XSLT_NAMESPACE)) &&  | 
3650  | 0  |       (!xsltCheckExtURI(style, cur->ns->href))) { | 
3651  | 0  |       goto skip_children;  | 
3652  | 0  |   } else if (cur->children != NULL) { | 
3653  | 0  |       cur = cur->children;  | 
3654  | 0  |       continue;  | 
3655  | 0  |   }  | 
3656  |  |  | 
3657  | 0  | skip_children:  | 
3658  | 0  |   if (cur->next != NULL) { | 
3659  | 0  |       cur = cur->next;  | 
3660  | 0  |       continue;  | 
3661  | 0  |   }  | 
3662  | 0  |   do { | 
3663  |  | 
  | 
3664  | 0  |       cur = cur->parent;  | 
3665  | 0  |       if (cur == NULL)  | 
3666  | 0  |     break;  | 
3667  | 0  |       if (cur == (xmlNodePtr) style->doc) { | 
3668  | 0  |     cur = NULL;  | 
3669  | 0  |     break;  | 
3670  | 0  |       }  | 
3671  | 0  |       if (cur->next != NULL) { | 
3672  | 0  |     cur = cur->next;  | 
3673  | 0  |     break;  | 
3674  | 0  |       }  | 
3675  | 0  |   } while (cur != NULL);  | 
3676  | 0  |     }  | 
3677  | 0  |     if (deleteNode != NULL) { | 
3678  |  | #ifdef WITH_XSLT_DEBUG_PARSING  | 
3679  |  |   xsltGenericDebug(xsltGenericDebugContext,  | 
3680  |  |    "xsltPreprocessStylesheet: removing ignorable blank node\n");  | 
3681  |  | #endif  | 
3682  | 0  |   xmlUnlinkNode(deleteNode);  | 
3683  | 0  |   xmlFreeNode(deleteNode);  | 
3684  | 0  |     }  | 
3685  | 0  | }  | 
3686  |  | #endif /* end of else XSLT_REFACTORED */  | 
3687  |  |  | 
3688  |  | /**  | 
3689  |  |  * xsltGatherNamespaces:  | 
3690  |  |  * @style:  the XSLT stylesheet  | 
3691  |  |  *  | 
3692  |  |  * Browse the stylesheet and build the namspace hash table which  | 
3693  |  |  * will be used for XPath interpretation. If needed do a bit of normalization  | 
3694  |  |  */  | 
3695  |  |  | 
3696  |  | static void  | 
3697  | 0  | xsltGatherNamespaces(xsltStylesheetPtr style) { | 
3698  | 0  |     xmlNodePtr cur;  | 
3699  | 0  |     const xmlChar *URI;  | 
3700  |  | 
  | 
3701  | 0  |     if (style == NULL)  | 
3702  | 0  |         return;  | 
3703  |  |     /*  | 
3704  |  |      * TODO: basically if the stylesheet uses the same prefix for different  | 
3705  |  |      *       patterns, well they may be in problem, hopefully they will get  | 
3706  |  |      *       a warning first.  | 
3707  |  |      */  | 
3708  |  |     /*  | 
3709  |  |     * TODO: Eliminate the use of the hash for XPath expressions.  | 
3710  |  |     *   An expression should be evaluated in the context of the in-scope  | 
3711  |  |     *   namespaces; eliminate the restriction of an XML document to contain  | 
3712  |  |     *   no duplicate prefixes for different namespace names.  | 
3713  |  |     *  | 
3714  |  |     */  | 
3715  | 0  |     cur = xmlDocGetRootElement(style->doc);  | 
3716  | 0  |     while (cur != NULL) { | 
3717  | 0  |   if (cur->type == XML_ELEMENT_NODE) { | 
3718  | 0  |       xmlNsPtr ns = cur->nsDef;  | 
3719  | 0  |       while (ns != NULL) { | 
3720  | 0  |     if (ns->prefix != NULL) { | 
3721  | 0  |         if (style->nsHash == NULL) { | 
3722  | 0  |       style->nsHash = xmlHashCreate(10);  | 
3723  | 0  |       if (style->nsHash == NULL) { | 
3724  | 0  |           xsltTransformError(NULL, style, cur,  | 
3725  | 0  |      "xsltGatherNamespaces: failed to create hash table\n");  | 
3726  | 0  |           style->errors++;  | 
3727  | 0  |           return;  | 
3728  | 0  |       }  | 
3729  | 0  |         }  | 
3730  | 0  |         URI = xmlHashLookup(style->nsHash, ns->prefix);  | 
3731  | 0  |         if ((URI != NULL) && (!xmlStrEqual(URI, ns->href))) { | 
3732  | 0  |       xsltTransformError(NULL, style, cur,  | 
3733  | 0  |        "Namespaces prefix %s used for multiple namespaces\n",ns->prefix);  | 
3734  | 0  |       style->warnings++;  | 
3735  | 0  |         } else if (URI == NULL) { | 
3736  | 0  |       xmlHashUpdateEntry(style->nsHash, ns->prefix,  | 
3737  | 0  |           (void *) ns->href, NULL);  | 
3738  |  | 
  | 
3739  |  | #ifdef WITH_XSLT_DEBUG_PARSING  | 
3740  |  |       xsltGenericDebug(xsltGenericDebugContext,  | 
3741  |  |      "Added namespace: %s mapped to %s\n", ns->prefix, ns->href);  | 
3742  |  | #endif  | 
3743  | 0  |         }  | 
3744  | 0  |     }  | 
3745  | 0  |     ns = ns->next;  | 
3746  | 0  |       }  | 
3747  | 0  |   }  | 
3748  |  |  | 
3749  |  |   /*  | 
3750  |  |    * Skip to next node  | 
3751  |  |    */  | 
3752  | 0  |   if (cur->children != NULL) { | 
3753  | 0  |       if (cur->children->type != XML_ENTITY_DECL) { | 
3754  | 0  |     cur = cur->children;  | 
3755  | 0  |     continue;  | 
3756  | 0  |       }  | 
3757  | 0  |   }  | 
3758  | 0  |   if (cur->next != NULL) { | 
3759  | 0  |       cur = cur->next;  | 
3760  | 0  |       continue;  | 
3761  | 0  |   }  | 
3762  |  |  | 
3763  | 0  |   do { | 
3764  | 0  |       cur = cur->parent;  | 
3765  | 0  |       if (cur == NULL)  | 
3766  | 0  |     break;  | 
3767  | 0  |       if (cur == (xmlNodePtr) style->doc) { | 
3768  | 0  |     cur = NULL;  | 
3769  | 0  |     break;  | 
3770  | 0  |       }  | 
3771  | 0  |       if (cur->next != NULL) { | 
3772  | 0  |     cur = cur->next;  | 
3773  | 0  |     break;  | 
3774  | 0  |       }  | 
3775  | 0  |   } while (cur != NULL);  | 
3776  | 0  |     }  | 
3777  | 0  | }  | 
3778  |  |  | 
3779  |  | #ifdef XSLT_REFACTORED  | 
3780  |  |  | 
3781  |  | static xsltStyleType  | 
3782  |  | xsltGetXSLTElementTypeByNode(xsltCompilerCtxtPtr cctxt,  | 
3783  |  |            xmlNodePtr node)  | 
3784  |  | { | 
3785  |  |     if ((node == NULL) || (node->type != XML_ELEMENT_NODE) ||  | 
3786  |  |   (node->name == NULL))  | 
3787  |  |   return(0);  | 
3788  |  |  | 
3789  |  |     if (node->name[0] == 'a') { | 
3790  |  |   if (IS_XSLT_NAME(node, "apply-templates"))  | 
3791  |  |       return(XSLT_FUNC_APPLYTEMPLATES);  | 
3792  |  |   else if (IS_XSLT_NAME(node, "attribute"))  | 
3793  |  |       return(XSLT_FUNC_ATTRIBUTE);  | 
3794  |  |   else if (IS_XSLT_NAME(node, "apply-imports"))  | 
3795  |  |       return(XSLT_FUNC_APPLYIMPORTS);  | 
3796  |  |   else if (IS_XSLT_NAME(node, "attribute-set"))  | 
3797  |  |       return(0);  | 
3798  |  |  | 
3799  |  |     } else if (node->name[0] == 'c') { | 
3800  |  |   if (IS_XSLT_NAME(node, "choose"))  | 
3801  |  |       return(XSLT_FUNC_CHOOSE);  | 
3802  |  |   else if (IS_XSLT_NAME(node, "copy"))  | 
3803  |  |       return(XSLT_FUNC_COPY);  | 
3804  |  |   else if (IS_XSLT_NAME(node, "copy-of"))  | 
3805  |  |       return(XSLT_FUNC_COPYOF);  | 
3806  |  |   else if (IS_XSLT_NAME(node, "call-template"))  | 
3807  |  |       return(XSLT_FUNC_CALLTEMPLATE);  | 
3808  |  |   else if (IS_XSLT_NAME(node, "comment"))  | 
3809  |  |       return(XSLT_FUNC_COMMENT);  | 
3810  |  |  | 
3811  |  |     } else if (node->name[0] == 'd') { | 
3812  |  |   if (IS_XSLT_NAME(node, "document"))  | 
3813  |  |       return(XSLT_FUNC_DOCUMENT);  | 
3814  |  |   else if (IS_XSLT_NAME(node, "decimal-format"))  | 
3815  |  |       return(0);  | 
3816  |  |  | 
3817  |  |     } else if (node->name[0] == 'e') { | 
3818  |  |   if (IS_XSLT_NAME(node, "element"))  | 
3819  |  |       return(XSLT_FUNC_ELEMENT);  | 
3820  |  |  | 
3821  |  |     } else if (node->name[0] == 'f') { | 
3822  |  |   if (IS_XSLT_NAME(node, "for-each"))  | 
3823  |  |       return(XSLT_FUNC_FOREACH);  | 
3824  |  |   else if (IS_XSLT_NAME(node, "fallback"))  | 
3825  |  |       return(XSLT_FUNC_FALLBACK);  | 
3826  |  |  | 
3827  |  |     } else if (*(node->name) == 'i') { | 
3828  |  |   if (IS_XSLT_NAME(node, "if"))  | 
3829  |  |       return(XSLT_FUNC_IF);  | 
3830  |  |   else if (IS_XSLT_NAME(node, "include"))  | 
3831  |  |       return(0);  | 
3832  |  |   else if (IS_XSLT_NAME(node, "import"))  | 
3833  |  |       return(0);  | 
3834  |  |  | 
3835  |  |     } else if (*(node->name) == 'k') { | 
3836  |  |   if (IS_XSLT_NAME(node, "key"))  | 
3837  |  |       return(0);  | 
3838  |  |  | 
3839  |  |     } else if (*(node->name) == 'm') { | 
3840  |  |   if (IS_XSLT_NAME(node, "message"))  | 
3841  |  |       return(XSLT_FUNC_MESSAGE);  | 
3842  |  |  | 
3843  |  |     } else if (*(node->name) == 'n') { | 
3844  |  |   if (IS_XSLT_NAME(node, "number"))  | 
3845  |  |       return(XSLT_FUNC_NUMBER);  | 
3846  |  |   else if (IS_XSLT_NAME(node, "namespace-alias"))  | 
3847  |  |       return(0);  | 
3848  |  |  | 
3849  |  |     } else if (*(node->name) == 'o') { | 
3850  |  |   if (IS_XSLT_NAME(node, "otherwise"))  | 
3851  |  |       return(XSLT_FUNC_OTHERWISE);  | 
3852  |  |   else if (IS_XSLT_NAME(node, "output"))  | 
3853  |  |       return(0);  | 
3854  |  |  | 
3855  |  |     } else if (*(node->name) == 'p') { | 
3856  |  |   if (IS_XSLT_NAME(node, "param"))  | 
3857  |  |       return(XSLT_FUNC_PARAM);  | 
3858  |  |   else if (IS_XSLT_NAME(node, "processing-instruction"))  | 
3859  |  |       return(XSLT_FUNC_PI);  | 
3860  |  |   else if (IS_XSLT_NAME(node, "preserve-space"))  | 
3861  |  |       return(0);  | 
3862  |  |  | 
3863  |  |     } else if (*(node->name) == 's') { | 
3864  |  |   if (IS_XSLT_NAME(node, "sort"))  | 
3865  |  |       return(XSLT_FUNC_SORT);  | 
3866  |  |   else if (IS_XSLT_NAME(node, "strip-space"))  | 
3867  |  |       return(0);  | 
3868  |  |   else if (IS_XSLT_NAME(node, "stylesheet"))  | 
3869  |  |       return(0);  | 
3870  |  |  | 
3871  |  |     } else if (node->name[0] == 't') { | 
3872  |  |   if (IS_XSLT_NAME(node, "text"))  | 
3873  |  |       return(XSLT_FUNC_TEXT);  | 
3874  |  |   else if (IS_XSLT_NAME(node, "template"))  | 
3875  |  |       return(0);  | 
3876  |  |   else if (IS_XSLT_NAME(node, "transform"))  | 
3877  |  |       return(0);  | 
3878  |  |  | 
3879  |  |     } else if (*(node->name) == 'v') { | 
3880  |  |   if (IS_XSLT_NAME(node, "value-of"))  | 
3881  |  |       return(XSLT_FUNC_VALUEOF);  | 
3882  |  |   else if (IS_XSLT_NAME(node, "variable"))  | 
3883  |  |       return(XSLT_FUNC_VARIABLE);  | 
3884  |  |  | 
3885  |  |     } else if (*(node->name) == 'w') { | 
3886  |  |   if (IS_XSLT_NAME(node, "when"))  | 
3887  |  |       return(XSLT_FUNC_WHEN);  | 
3888  |  |   if (IS_XSLT_NAME(node, "with-param"))  | 
3889  |  |       return(XSLT_FUNC_WITHPARAM);  | 
3890  |  |     }  | 
3891  |  |     return(0);  | 
3892  |  | }  | 
3893  |  |  | 
3894  |  | /**  | 
3895  |  |  * xsltParseAnyXSLTElem:  | 
3896  |  |  *  | 
3897  |  |  * @cctxt: the compilation context  | 
3898  |  |  * @elem: the element node of the XSLT instruction  | 
3899  |  |  *  | 
3900  |  |  * Parses, validates the content models and compiles XSLT instructions.  | 
3901  |  |  *  | 
3902  |  |  * Returns 0 if everything's fine;  | 
3903  |  |  *         -1 on API or internal errors.  | 
3904  |  |  */  | 
3905  |  | int  | 
3906  |  | xsltParseAnyXSLTElem(xsltCompilerCtxtPtr cctxt, xmlNodePtr elem)  | 
3907  |  | { | 
3908  |  |     if ((cctxt == NULL) || (elem == NULL) ||  | 
3909  |  |   (elem->type != XML_ELEMENT_NODE))  | 
3910  |  |   return(-1);  | 
3911  |  |  | 
3912  |  |     elem->psvi = NULL;  | 
3913  |  |  | 
3914  |  |     if (! (IS_XSLT_ELEM_FAST(elem)))  | 
3915  |  |   return(-1);  | 
3916  |  |     /*  | 
3917  |  |     * Detection of handled content of extension instructions.  | 
3918  |  |     */  | 
3919  |  |     if (cctxt->inode->category == XSLT_ELEMENT_CATEGORY_EXTENSION) { | 
3920  |  |   cctxt->inode->extContentHandled = 1;  | 
3921  |  |     }  | 
3922  |  |  | 
3923  |  |     xsltCompilerNodePush(cctxt, elem);  | 
3924  |  |     /*  | 
3925  |  |     * URGENT TODO: Find a way to speed up this annoying redundant  | 
3926  |  |     *  textual node-name and namespace comparison.  | 
3927  |  |     */  | 
3928  |  |     if (cctxt->inode->prev->curChildType != 0)  | 
3929  |  |   cctxt->inode->type = cctxt->inode->prev->curChildType;  | 
3930  |  |     else  | 
3931  |  |   cctxt->inode->type = xsltGetXSLTElementTypeByNode(cctxt, elem);  | 
3932  |  |     /*  | 
3933  |  |     * Update the in-scope namespaces if needed.  | 
3934  |  |     */  | 
3935  |  |     if (elem->nsDef != NULL)  | 
3936  |  |   cctxt->inode->inScopeNs =  | 
3937  |  |       xsltCompilerBuildInScopeNsList(cctxt, elem);  | 
3938  |  |     /*  | 
3939  |  |     * xsltStylePreCompute():  | 
3940  |  |     *  This will compile the information found on the current  | 
3941  |  |     *  element's attributes. NOTE that this won't process the  | 
3942  |  |     *  children of the instruction.  | 
3943  |  |     */  | 
3944  |  |     xsltStylePreCompute(cctxt->style, elem);  | 
3945  |  |     /*  | 
3946  |  |     * TODO: How to react on errors in xsltStylePreCompute() ?  | 
3947  |  |     */  | 
3948  |  |  | 
3949  |  |     /*  | 
3950  |  |     * Validate the content model of the XSLT-element.  | 
3951  |  |     */  | 
3952  |  |     switch (cctxt->inode->type) { | 
3953  |  |   case XSLT_FUNC_APPLYIMPORTS:  | 
3954  |  |       /* EMPTY */  | 
3955  |  |       goto empty_content;  | 
3956  |  |   case XSLT_FUNC_APPLYTEMPLATES:  | 
3957  |  |       /* <!-- Content: (xsl:sort | xsl:with-param)* --> */  | 
3958  |  |       goto apply_templates;  | 
3959  |  |   case XSLT_FUNC_ATTRIBUTE:  | 
3960  |  |       /* <!-- Content: template --> */  | 
3961  |  |       goto sequence_constructor;  | 
3962  |  |   case XSLT_FUNC_CALLTEMPLATE:  | 
3963  |  |       /* <!-- Content: xsl:with-param* --> */  | 
3964  |  |       goto call_template;  | 
3965  |  |   case XSLT_FUNC_CHOOSE:  | 
3966  |  |       /* <!-- Content: (xsl:when+, xsl:otherwise?) --> */  | 
3967  |  |       goto choose;  | 
3968  |  |   case XSLT_FUNC_COMMENT:  | 
3969  |  |       /* <!-- Content: template --> */  | 
3970  |  |       goto sequence_constructor;  | 
3971  |  |   case XSLT_FUNC_COPY:  | 
3972  |  |       /* <!-- Content: template --> */  | 
3973  |  |       goto sequence_constructor;  | 
3974  |  |   case XSLT_FUNC_COPYOF:  | 
3975  |  |       /* EMPTY */  | 
3976  |  |       goto empty_content;  | 
3977  |  |   case XSLT_FUNC_DOCUMENT: /* Extra one */  | 
3978  |  |       /* ?? template ?? */  | 
3979  |  |       goto sequence_constructor;  | 
3980  |  |   case XSLT_FUNC_ELEMENT:  | 
3981  |  |       /* <!-- Content: template --> */  | 
3982  |  |       goto sequence_constructor;  | 
3983  |  |   case XSLT_FUNC_FALLBACK:  | 
3984  |  |       /* <!-- Content: template --> */  | 
3985  |  |       goto sequence_constructor;  | 
3986  |  |   case XSLT_FUNC_FOREACH:  | 
3987  |  |       /* <!-- Content: (xsl:sort*, template) --> */  | 
3988  |  |       goto for_each;  | 
3989  |  |   case XSLT_FUNC_IF:  | 
3990  |  |       /* <!-- Content: template --> */  | 
3991  |  |       goto sequence_constructor;  | 
3992  |  |   case XSLT_FUNC_OTHERWISE:  | 
3993  |  |       /* <!-- Content: template --> */  | 
3994  |  |       goto sequence_constructor;  | 
3995  |  |   case XSLT_FUNC_MESSAGE:  | 
3996  |  |       /* <!-- Content: template --> */  | 
3997  |  |       goto sequence_constructor;  | 
3998  |  |   case XSLT_FUNC_NUMBER:  | 
3999  |  |       /* EMPTY */  | 
4000  |  |       goto empty_content;  | 
4001  |  |   case XSLT_FUNC_PARAM:  | 
4002  |  |       /*  | 
4003  |  |       * Check for redefinition.  | 
4004  |  |       */  | 
4005  |  |       if ((elem->psvi != NULL) && (cctxt->ivar != NULL)) { | 
4006  |  |     xsltVarInfoPtr ivar = cctxt->ivar;  | 
4007  |  |  | 
4008  |  |     do { | 
4009  |  |         if ((ivar->name ==  | 
4010  |  |        ((xsltStyleItemParamPtr) elem->psvi)->name) &&  | 
4011  |  |       (ivar->nsName ==  | 
4012  |  |        ((xsltStyleItemParamPtr) elem->psvi)->ns))  | 
4013  |  |         { | 
4014  |  |       elem->psvi = NULL;  | 
4015  |  |       xsltTransformError(NULL, cctxt->style, elem,  | 
4016  |  |           "Redefinition of variable or parameter '%s'.\n",  | 
4017  |  |           ivar->name);  | 
4018  |  |       cctxt->style->errors++;  | 
4019  |  |       goto error;  | 
4020  |  |         }  | 
4021  |  |         ivar = ivar->prev;  | 
4022  |  |     } while (ivar != NULL);  | 
4023  |  |       }  | 
4024  |  |       /*  <!-- Content: template --> */  | 
4025  |  |       goto sequence_constructor;  | 
4026  |  |   case XSLT_FUNC_PI:  | 
4027  |  |       /*  <!-- Content: template --> */  | 
4028  |  |       goto sequence_constructor;  | 
4029  |  |   case XSLT_FUNC_SORT:  | 
4030  |  |       /* EMPTY */  | 
4031  |  |       goto empty_content;  | 
4032  |  |   case XSLT_FUNC_TEXT:  | 
4033  |  |       /* <!-- Content: #PCDATA --> */  | 
4034  |  |       goto text;  | 
4035  |  |   case XSLT_FUNC_VALUEOF:  | 
4036  |  |       /* EMPTY */  | 
4037  |  |       goto empty_content;  | 
4038  |  |   case XSLT_FUNC_VARIABLE:  | 
4039  |  |       /*  | 
4040  |  |       * Check for redefinition.  | 
4041  |  |       */  | 
4042  |  |       if ((elem->psvi != NULL) && (cctxt->ivar != NULL)) { | 
4043  |  |     xsltVarInfoPtr ivar = cctxt->ivar;  | 
4044  |  |  | 
4045  |  |     do { | 
4046  |  |         if ((ivar->name ==  | 
4047  |  |        ((xsltStyleItemVariablePtr) elem->psvi)->name) &&  | 
4048  |  |       (ivar->nsName ==  | 
4049  |  |        ((xsltStyleItemVariablePtr) elem->psvi)->ns))  | 
4050  |  |         { | 
4051  |  |       elem->psvi = NULL;  | 
4052  |  |       xsltTransformError(NULL, cctxt->style, elem,  | 
4053  |  |           "Redefinition of variable or parameter '%s'.\n",  | 
4054  |  |           ivar->name);  | 
4055  |  |       cctxt->style->errors++;  | 
4056  |  |       goto error;  | 
4057  |  |         }  | 
4058  |  |         ivar = ivar->prev;  | 
4059  |  |     } while (ivar != NULL);  | 
4060  |  |       }  | 
4061  |  |       /* <!-- Content: template --> */  | 
4062  |  |       goto sequence_constructor;  | 
4063  |  |   case XSLT_FUNC_WHEN:  | 
4064  |  |       /* <!-- Content: template --> */  | 
4065  |  |       goto sequence_constructor;  | 
4066  |  |   case XSLT_FUNC_WITHPARAM:  | 
4067  |  |       /* <!-- Content: template --> */  | 
4068  |  |       goto sequence_constructor;  | 
4069  |  |   default:  | 
4070  |  | #ifdef WITH_XSLT_DEBUG_PARSING  | 
4071  |  |       xsltGenericDebug(xsltGenericDebugContext,  | 
4072  |  |     "xsltParseXSLTNode: Unhandled XSLT element '%s'.\n",  | 
4073  |  |     elem->name);  | 
4074  |  | #endif  | 
4075  |  |       xsltTransformError(NULL, cctxt->style, elem,  | 
4076  |  |     "xsltParseXSLTNode: Internal error; "  | 
4077  |  |     "unhandled XSLT element '%s'.\n", elem->name);  | 
4078  |  |       cctxt->style->errors++;  | 
4079  |  |       goto internal_err;  | 
4080  |  |     }  | 
4081  |  |  | 
4082  |  | apply_templates:  | 
4083  |  |     /* <!-- Content: (xsl:sort | xsl:with-param)* --> */  | 
4084  |  |     if (elem->children != NULL) { | 
4085  |  |   xmlNodePtr child = elem->children;  | 
4086  |  |   do { | 
4087  |  |       if (child->type == XML_ELEMENT_NODE) { | 
4088  |  |     if (IS_XSLT_ELEM_FAST(child)) { | 
4089  |  |         if (xmlStrEqual(child->name, BAD_CAST "with-param")) { | 
4090  |  |       cctxt->inode->curChildType = XSLT_FUNC_WITHPARAM;  | 
4091  |  |       xsltParseAnyXSLTElem(cctxt, child);  | 
4092  |  |         } else if (xmlStrEqual(child->name, BAD_CAST "sort")) { | 
4093  |  |       cctxt->inode->curChildType = XSLT_FUNC_SORT;  | 
4094  |  |       xsltParseAnyXSLTElem(cctxt, child);  | 
4095  |  |         } else  | 
4096  |  |       xsltParseContentError(cctxt->style, child);  | 
4097  |  |     } else  | 
4098  |  |         xsltParseContentError(cctxt->style, child);  | 
4099  |  |       }  | 
4100  |  |       child = child->next;  | 
4101  |  |   } while (child != NULL);  | 
4102  |  |     }  | 
4103  |  |     goto exit;  | 
4104  |  |  | 
4105  |  | call_template:  | 
4106  |  |     /* <!-- Content: xsl:with-param* --> */  | 
4107  |  |     if (elem->children != NULL) { | 
4108  |  |   xmlNodePtr child = elem->children;  | 
4109  |  |   do { | 
4110  |  |       if (child->type == XML_ELEMENT_NODE) { | 
4111  |  |     if (IS_XSLT_ELEM_FAST(child)) { | 
4112  |  |         xsltStyleType type;  | 
4113  |  |  | 
4114  |  |         type = xsltGetXSLTElementTypeByNode(cctxt, child);  | 
4115  |  |         if (type == XSLT_FUNC_WITHPARAM) { | 
4116  |  |       cctxt->inode->curChildType = XSLT_FUNC_WITHPARAM;  | 
4117  |  |       xsltParseAnyXSLTElem(cctxt, child);  | 
4118  |  |         } else { | 
4119  |  |       xsltParseContentError(cctxt->style, child);  | 
4120  |  |         }  | 
4121  |  |     } else  | 
4122  |  |         xsltParseContentError(cctxt->style, child);  | 
4123  |  |       }  | 
4124  |  |       child = child->next;  | 
4125  |  |   } while (child != NULL);  | 
4126  |  |     }  | 
4127  |  |     goto exit;  | 
4128  |  |  | 
4129  |  | text:  | 
4130  |  |     if (elem->children != NULL) { | 
4131  |  |   xmlNodePtr child = elem->children;  | 
4132  |  |   do { | 
4133  |  |       if ((child->type != XML_TEXT_NODE) &&  | 
4134  |  |     (child->type != XML_CDATA_SECTION_NODE))  | 
4135  |  |       { | 
4136  |  |     xsltTransformError(NULL, cctxt->style, elem,  | 
4137  |  |         "The XSLT 'text' element must have only character "  | 
4138  |  |         "data as content.\n");  | 
4139  |  |       }  | 
4140  |  |       child = child->next;  | 
4141  |  |   } while (child != NULL);  | 
4142  |  |     }  | 
4143  |  |     goto exit;  | 
4144  |  |  | 
4145  |  | empty_content:  | 
4146  |  |     if (elem->children != NULL) { | 
4147  |  |   xmlNodePtr child = elem->children;  | 
4148  |  |   /*  | 
4149  |  |   * Relaxed behaviour: we will allow whitespace-only text-nodes.  | 
4150  |  |   */  | 
4151  |  |   do { | 
4152  |  |       if (((child->type != XML_TEXT_NODE) &&  | 
4153  |  |      (child->type != XML_CDATA_SECTION_NODE)) ||  | 
4154  |  |     (! IS_BLANK_NODE(child)))  | 
4155  |  |       { | 
4156  |  |     xsltTransformError(NULL, cctxt->style, elem,  | 
4157  |  |         "This XSLT element must have no content.\n");  | 
4158  |  |     cctxt->style->errors++;  | 
4159  |  |     break;  | 
4160  |  |       }  | 
4161  |  |       child = child->next;  | 
4162  |  |   } while (child != NULL);  | 
4163  |  |     }  | 
4164  |  |     goto exit;  | 
4165  |  |  | 
4166  |  | choose:  | 
4167  |  |     /* <!-- Content: (xsl:when+, xsl:otherwise?) --> */  | 
4168  |  |     /*  | 
4169  |  |     * TODO: text-nodes in between are *not* allowed in XSLT 1.0.  | 
4170  |  |     *   The old behaviour did not check this.  | 
4171  |  |     * NOTE: In XSLT 2.0 they are stripped beforehand  | 
4172  |  |     *  if whitespace-only (regardless of xml:space).  | 
4173  |  |     */  | 
4174  |  |     if (elem->children != NULL) { | 
4175  |  |   xmlNodePtr child = elem->children;  | 
4176  |  |   int nbWhen = 0, nbOtherwise = 0, err = 0;  | 
4177  |  |   do { | 
4178  |  |       if (child->type == XML_ELEMENT_NODE) { | 
4179  |  |     if (IS_XSLT_ELEM_FAST(child)) { | 
4180  |  |         xsltStyleType type;  | 
4181  |  |  | 
4182  |  |         type = xsltGetXSLTElementTypeByNode(cctxt, child);  | 
4183  |  |         if (type == XSLT_FUNC_WHEN) { | 
4184  |  |       nbWhen++;  | 
4185  |  |       if (nbOtherwise) { | 
4186  |  |           xsltParseContentError(cctxt->style, child);  | 
4187  |  |           err = 1;  | 
4188  |  |           break;  | 
4189  |  |       }  | 
4190  |  |       cctxt->inode->curChildType = XSLT_FUNC_WHEN;  | 
4191  |  |       xsltParseAnyXSLTElem(cctxt, child);  | 
4192  |  |         } else if (type == XSLT_FUNC_OTHERWISE) { | 
4193  |  |       if (! nbWhen) { | 
4194  |  |           xsltParseContentError(cctxt->style, child);  | 
4195  |  |           err = 1;  | 
4196  |  |           break;  | 
4197  |  |       }  | 
4198  |  |       if (nbOtherwise) { | 
4199  |  |           xsltTransformError(NULL, cctxt->style, elem,  | 
4200  |  |         "The XSLT 'choose' element must not contain "  | 
4201  |  |         "more than one XSLT 'otherwise' element.\n");  | 
4202  |  |           cctxt->style->errors++;  | 
4203  |  |           err = 1;  | 
4204  |  |           break;  | 
4205  |  |       }  | 
4206  |  |       nbOtherwise++;  | 
4207  |  |       cctxt->inode->curChildType = XSLT_FUNC_OTHERWISE;  | 
4208  |  |       xsltParseAnyXSLTElem(cctxt, child);  | 
4209  |  |         } else  | 
4210  |  |       xsltParseContentError(cctxt->style, child);  | 
4211  |  |     } else  | 
4212  |  |         xsltParseContentError(cctxt->style, child);  | 
4213  |  |       }  | 
4214  |  |       /*  | 
4215  |  |     else  | 
4216  |  |         xsltParseContentError(cctxt, child);  | 
4217  |  |       */  | 
4218  |  |       child = child->next;  | 
4219  |  |   } while (child != NULL);  | 
4220  |  |   if ((! err) && (! nbWhen)) { | 
4221  |  |       xsltTransformError(NULL, cctxt->style, elem,  | 
4222  |  |     "The XSLT element 'choose' must contain at least one "  | 
4223  |  |     "XSLT element 'when'.\n");  | 
4224  |  |     cctxt->style->errors++;  | 
4225  |  |   }  | 
4226  |  |     }  | 
4227  |  |     goto exit;  | 
4228  |  |  | 
4229  |  | for_each:  | 
4230  |  |     /* <!-- Content: (xsl:sort*, template) --> */  | 
4231  |  |     /*  | 
4232  |  |     * NOTE: Text-nodes before xsl:sort are *not* allowed in XSLT 1.0.  | 
4233  |  |     *   The old behaviour did not allow this, but it catched this  | 
4234  |  |     *   only at transformation-time.  | 
4235  |  |     *   In XSLT 2.0 they are stripped beforehand if whitespace-only  | 
4236  |  |     *   (regardless of xml:space).  | 
4237  |  |     */  | 
4238  |  |     if (elem->children != NULL) { | 
4239  |  |   xmlNodePtr child = elem->children;  | 
4240  |  |   /*  | 
4241  |  |   * Parse xsl:sort first.  | 
4242  |  |   */  | 
4243  |  |   do { | 
4244  |  |       if ((child->type == XML_ELEMENT_NODE) &&  | 
4245  |  |     IS_XSLT_ELEM_FAST(child))  | 
4246  |  |       { | 
4247  |  |     if (xsltGetXSLTElementTypeByNode(cctxt, child) ==  | 
4248  |  |         XSLT_FUNC_SORT)  | 
4249  |  |     { | 
4250  |  |         cctxt->inode->curChildType = XSLT_FUNC_SORT;  | 
4251  |  |         xsltParseAnyXSLTElem(cctxt, child);  | 
4252  |  |     } else  | 
4253  |  |         break;  | 
4254  |  |       } else  | 
4255  |  |     break;  | 
4256  |  |       child = child->next;  | 
4257  |  |   } while (child != NULL);  | 
4258  |  |   /*  | 
4259  |  |   * Parse the sequece constructor.  | 
4260  |  |   */  | 
4261  |  |   if (child != NULL)  | 
4262  |  |       xsltParseSequenceConstructor(cctxt, child);  | 
4263  |  |     }  | 
4264  |  |     goto exit;  | 
4265  |  |  | 
4266  |  | sequence_constructor:  | 
4267  |  |     /*  | 
4268  |  |     * Parse the sequence constructor.  | 
4269  |  |     */  | 
4270  |  |     if (elem->children != NULL)  | 
4271  |  |   xsltParseSequenceConstructor(cctxt, elem->children);  | 
4272  |  |  | 
4273  |  |     /*  | 
4274  |  |     * Register information for vars/params. Only needed if there  | 
4275  |  |     * are any following siblings.  | 
4276  |  |     */  | 
4277  |  |     if ((elem->next != NULL) &&  | 
4278  |  |   ((cctxt->inode->type == XSLT_FUNC_VARIABLE) ||  | 
4279  |  |    (cctxt->inode->type == XSLT_FUNC_PARAM)))  | 
4280  |  |     { | 
4281  |  |   if ((elem->psvi != NULL) &&  | 
4282  |  |       (((xsltStyleBasicItemVariablePtr) elem->psvi)->name))  | 
4283  |  |   { | 
4284  |  |       xsltCompilerVarInfoPush(cctxt, elem,  | 
4285  |  |     ((xsltStyleBasicItemVariablePtr) elem->psvi)->name,  | 
4286  |  |     ((xsltStyleBasicItemVariablePtr) elem->psvi)->ns);  | 
4287  |  |   }  | 
4288  |  |     }  | 
4289  |  |  | 
4290  |  | error:  | 
4291  |  | exit:  | 
4292  |  |     xsltCompilerNodePop(cctxt, elem);  | 
4293  |  |     return(0);  | 
4294  |  |  | 
4295  |  | internal_err:  | 
4296  |  |     xsltCompilerNodePop(cctxt, elem);  | 
4297  |  |     return(-1);  | 
4298  |  | }  | 
4299  |  |  | 
4300  |  | /**  | 
4301  |  |  * xsltForwardsCompatUnkownItemCreate:  | 
4302  |  |  *  | 
4303  |  |  * @cctxt: the compilation context  | 
4304  |  |  *  | 
4305  |  |  * Creates a compiled representation of the unknown  | 
4306  |  |  * XSLT instruction.  | 
4307  |  |  *  | 
4308  |  |  * Returns the compiled representation.  | 
4309  |  |  */  | 
4310  |  | static xsltStyleItemUknownPtr  | 
4311  |  | xsltForwardsCompatUnkownItemCreate(xsltCompilerCtxtPtr cctxt)  | 
4312  |  | { | 
4313  |  |     xsltStyleItemUknownPtr item;  | 
4314  |  |  | 
4315  |  |     item = (xsltStyleItemUknownPtr) xmlMalloc(sizeof(xsltStyleItemUknown));  | 
4316  |  |     if (item == NULL) { | 
4317  |  |   xsltTransformError(NULL, cctxt->style, NULL,  | 
4318  |  |       "Internal error in xsltForwardsCompatUnkownItemCreate(): "  | 
4319  |  |       "Failed to allocate memory.\n");  | 
4320  |  |   cctxt->style->errors++;  | 
4321  |  |   return(NULL);  | 
4322  |  |     }  | 
4323  |  |     memset(item, 0, sizeof(xsltStyleItemUknown));  | 
4324  |  |     item->type = XSLT_FUNC_UNKOWN_FORWARDS_COMPAT;  | 
4325  |  |     /*  | 
4326  |  |     * Store it in the stylesheet.  | 
4327  |  |     */  | 
4328  |  |     item->next = cctxt->style->preComps;  | 
4329  |  |     cctxt->style->preComps = (xsltElemPreCompPtr) item;  | 
4330  |  |     return(item);  | 
4331  |  | }  | 
4332  |  |  | 
4333  |  | /**  | 
4334  |  |  * xsltParseUnknownXSLTElem:  | 
4335  |  |  *  | 
4336  |  |  * @cctxt: the compilation context  | 
4337  |  |  * @node: the element of the unknown XSLT instruction  | 
4338  |  |  *  | 
4339  |  |  * Parses an unknown XSLT element.  | 
4340  |  |  * If forwards compatible mode is enabled this will allow  | 
4341  |  |  * such an unknown XSLT and; otherwise it is rejected.  | 
4342  |  |  *  | 
4343  |  |  * Returns 1 in the unknown XSLT instruction is rejected,  | 
4344  |  |  *         0 if everything's fine and  | 
4345  |  |  *         -1 on API or internal errors.  | 
4346  |  |  */  | 
4347  |  | static int  | 
4348  |  | xsltParseUnknownXSLTElem(xsltCompilerCtxtPtr cctxt,  | 
4349  |  |           xmlNodePtr node)  | 
4350  |  | { | 
4351  |  |     if ((cctxt == NULL) || (node == NULL) || (node->type != XML_ELEMENT_NODE))  | 
4352  |  |   return(-1);  | 
4353  |  |  | 
4354  |  |     /*  | 
4355  |  |     * Detection of handled content of extension instructions.  | 
4356  |  |     */  | 
4357  |  |     if (cctxt->inode->category == XSLT_ELEMENT_CATEGORY_EXTENSION) { | 
4358  |  |   cctxt->inode->extContentHandled = 1;  | 
4359  |  |     }  | 
4360  |  |     if (cctxt->inode->forwardsCompat == 0) { | 
4361  |  |   /*  | 
4362  |  |   * We are not in forwards-compatible mode, so raise an error.  | 
4363  |  |   */  | 
4364  |  |   xsltTransformError(NULL, cctxt->style, node,  | 
4365  |  |       "Unknown XSLT element '%s'.\n", node->name);  | 
4366  |  |   cctxt->style->errors++;  | 
4367  |  |   return(1);  | 
4368  |  |     }  | 
4369  |  |     /*  | 
4370  |  |     * Forwards-compatible mode.  | 
4371  |  |     * ------------------------  | 
4372  |  |     *  | 
4373  |  |     * Parse/compile xsl:fallback elements.  | 
4374  |  |     *  | 
4375  |  |     * QUESTION: Do we have to raise an error if there's no xsl:fallback?  | 
4376  |  |     * ANSWER: No, since in the stylesheet the fallback behaviour might  | 
4377  |  |     *  also be provided by using the XSLT function "element-available".  | 
4378  |  |     */  | 
4379  |  |     if (cctxt->unknownItem == NULL) { | 
4380  |  |   /*  | 
4381  |  |   * Create a singleton for all unknown XSLT instructions.  | 
4382  |  |   */  | 
4383  |  |   cctxt->unknownItem = xsltForwardsCompatUnkownItemCreate(cctxt);  | 
4384  |  |   if (cctxt->unknownItem == NULL) { | 
4385  |  |       node->psvi = NULL;  | 
4386  |  |       return(-1);  | 
4387  |  |   }  | 
4388  |  |     }  | 
4389  |  |     node->psvi = cctxt->unknownItem;  | 
4390  |  |     if (node->children == NULL)  | 
4391  |  |   return(0);  | 
4392  |  |     else { | 
4393  |  |   xmlNodePtr child = node->children;  | 
4394  |  |  | 
4395  |  |   xsltCompilerNodePush(cctxt, node);  | 
4396  |  |   /*  | 
4397  |  |   * Update the in-scope namespaces if needed.  | 
4398  |  |   */  | 
4399  |  |   if (node->nsDef != NULL)  | 
4400  |  |       cctxt->inode->inScopeNs =  | 
4401  |  |     xsltCompilerBuildInScopeNsList(cctxt, node);  | 
4402  |  |   /*  | 
4403  |  |   * Parse all xsl:fallback children.  | 
4404  |  |   */  | 
4405  |  |   do { | 
4406  |  |       if ((child->type == XML_ELEMENT_NODE) &&  | 
4407  |  |     IS_XSLT_ELEM_FAST(child) &&  | 
4408  |  |     IS_XSLT_NAME(child, "fallback"))  | 
4409  |  |       { | 
4410  |  |     cctxt->inode->curChildType = XSLT_FUNC_FALLBACK;  | 
4411  |  |     xsltParseAnyXSLTElem(cctxt, child);  | 
4412  |  |       }  | 
4413  |  |       child = child->next;  | 
4414  |  |   } while (child != NULL);  | 
4415  |  |  | 
4416  |  |   xsltCompilerNodePop(cctxt, node);  | 
4417  |  |     }  | 
4418  |  |     return(0);  | 
4419  |  | }  | 
4420  |  |  | 
4421  |  | /**  | 
4422  |  |  * xsltParseSequenceConstructor:  | 
4423  |  |  *  | 
4424  |  |  * @cctxt: the compilation context  | 
4425  |  |  * @cur: the start-node of the content to be parsed  | 
4426  |  |  *  | 
4427  |  |  * Parses a "template" content (or "sequence constructor" in XSLT 2.0 terms).  | 
4428  |  |  * This will additionally remove xsl:text elements from the tree.  | 
4429  |  |  */  | 
4430  |  | void  | 
4431  |  | xsltParseSequenceConstructor(xsltCompilerCtxtPtr cctxt, xmlNodePtr cur)  | 
4432  |  | { | 
4433  |  |     xsltStyleType type;  | 
4434  |  |     xmlNodePtr deleteNode = NULL;  | 
4435  |  |  | 
4436  |  |     if (cctxt == NULL) { | 
4437  |  |   xmlGenericError(xmlGenericErrorContext,  | 
4438  |  |       "xsltParseSequenceConstructor: Bad arguments\n");  | 
4439  |  |   cctxt->style->errors++;  | 
4440  |  |   return;  | 
4441  |  |     }  | 
4442  |  |     /*  | 
4443  |  |     * Detection of handled content of extension instructions.  | 
4444  |  |     */  | 
4445  |  |     if (cctxt->inode->category == XSLT_ELEMENT_CATEGORY_EXTENSION) { | 
4446  |  |   cctxt->inode->extContentHandled = 1;  | 
4447  |  |     }  | 
4448  |  |     if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL))  | 
4449  |  |   return;  | 
4450  |  |     /*  | 
4451  |  |     * This is the content reffered to as a "template".  | 
4452  |  |     * E.g. an xsl:element has such content model:  | 
4453  |  |     * <xsl:element  | 
4454  |  |     *   name = { qname } | 
4455  |  |     *   namespace = { uri-reference } | 
4456  |  |     *   use-attribute-sets = qnames>  | 
4457  |  |     * <!-- Content: template -->  | 
4458  |  |     *  | 
4459  |  |     * NOTE that in XSLT-2 the term "template" was abandoned due to  | 
4460  |  |     *  confusion with xsl:template and the term "sequence constructor"  | 
4461  |  |     *  was introduced instead.  | 
4462  |  |     *  | 
4463  |  |     * The following XSLT-instructions are allowed to appear:  | 
4464  |  |     *  xsl:apply-templates, xsl:call-template, xsl:apply-imports,  | 
4465  |  |     *  xsl:for-each, xsl:value-of, xsl:copy-of, xsl:number,  | 
4466  |  |     *  xsl:choose, xsl:if, xsl:text, xsl:copy, xsl:variable,  | 
4467  |  |     *  xsl:message, xsl:fallback,  | 
4468  |  |     *  xsl:processing-instruction, xsl:comment, xsl:element  | 
4469  |  |     *  xsl:attribute.  | 
4470  |  |     * Additional allowed content:  | 
4471  |  |     * 1) extension instructions  | 
4472  |  |     * 2) literal result elements  | 
4473  |  |     * 3) PCDATA  | 
4474  |  |     *  | 
4475  |  |     * NOTE that this content model does *not* allow xsl:param.  | 
4476  |  |     */  | 
4477  |  |     while (cur != NULL) { | 
4478  |  |   if (deleteNode != NULL) { | 
4479  |  | #ifdef WITH_XSLT_DEBUG_BLANKS  | 
4480  |  |       xsltGenericDebug(xsltGenericDebugContext,  | 
4481  |  |        "xsltParseSequenceConstructor: removing xsl:text element\n");  | 
4482  |  | #endif  | 
4483  |  |       xmlUnlinkNode(deleteNode);  | 
4484  |  |       xmlFreeNode(deleteNode);  | 
4485  |  |       deleteNode = NULL;  | 
4486  |  |   }  | 
4487  |  |   if (cur->type == XML_ELEMENT_NODE) { | 
4488  |  |  | 
4489  |  |       if (cur->psvi == xsltXSLTTextMarker) { | 
4490  |  |     /*  | 
4491  |  |     * xsl:text elements  | 
4492  |  |     * --------------------------------------------------------  | 
4493  |  |     */  | 
4494  |  |     xmlNodePtr tmp;  | 
4495  |  |  | 
4496  |  |     cur->psvi = NULL;  | 
4497  |  |     /*  | 
4498  |  |     * Mark the xsl:text element for later deletion.  | 
4499  |  |     */  | 
4500  |  |     deleteNode = cur;  | 
4501  |  |     /*  | 
4502  |  |     * Validate content.  | 
4503  |  |     */  | 
4504  |  |     tmp = cur->children;  | 
4505  |  |     if (tmp) { | 
4506  |  |         /*  | 
4507  |  |         * We don't expect more than one text-node in the  | 
4508  |  |         * content, since we already merged adjacent  | 
4509  |  |         * text/CDATA-nodes and eliminated PI/comment-nodes.  | 
4510  |  |         */  | 
4511  |  |         if ((tmp->type == XML_TEXT_NODE) ||  | 
4512  |  |       (tmp->next == NULL))  | 
4513  |  |         { | 
4514  |  |       /*  | 
4515  |  |       * Leave the contained text-node in the tree.  | 
4516  |  |       */  | 
4517  |  |       xmlUnlinkNode(tmp);  | 
4518  |  |       xmlAddPrevSibling(cur, tmp);  | 
4519  |  |         } else { | 
4520  |  |       tmp = NULL;  | 
4521  |  |       xsltTransformError(NULL, cctxt->style, cur,  | 
4522  |  |           "Element 'xsl:text': Invalid type "  | 
4523  |  |           "of node found in content.\n");  | 
4524  |  |       cctxt->style->errors++;  | 
4525  |  |         }  | 
4526  |  |     }  | 
4527  |  |     if (cur->properties) { | 
4528  |  |         xmlAttrPtr attr;  | 
4529  |  |         /*  | 
4530  |  |         * TODO: We need to report errors for  | 
4531  |  |         *  invalid attrs.  | 
4532  |  |         */  | 
4533  |  |         attr = cur->properties;  | 
4534  |  |         do { | 
4535  |  |       if ((attr->ns == NULL) &&  | 
4536  |  |           (attr->name != NULL) &&  | 
4537  |  |           (attr->name[0] == 'd') &&  | 
4538  |  |           xmlStrEqual(attr->name,  | 
4539  |  |           BAD_CAST "disable-output-escaping"))  | 
4540  |  |       { | 
4541  |  |           /*  | 
4542  |  |           * Attr "disable-output-escaping".  | 
4543  |  |           * XSLT-2: This attribute is deprecated.  | 
4544  |  |           */  | 
4545  |  |           if ((attr->children != NULL) &&  | 
4546  |  |         xmlStrEqual(attr->children->content,  | 
4547  |  |         BAD_CAST "yes"))  | 
4548  |  |           { | 
4549  |  |         /*  | 
4550  |  |         * Disable output escaping for this  | 
4551  |  |         * text node.  | 
4552  |  |         */  | 
4553  |  |         if (tmp)  | 
4554  |  |             tmp->name = xmlStringTextNoenc;  | 
4555  |  |           } else if ((attr->children == NULL) ||  | 
4556  |  |         (attr->children->content == NULL) ||  | 
4557  |  |         (!xmlStrEqual(attr->children->content,  | 
4558  |  |         BAD_CAST "no")))  | 
4559  |  |           { | 
4560  |  |         xsltTransformError(NULL, cctxt->style,  | 
4561  |  |             cur,  | 
4562  |  |             "Attribute 'disable-output-escaping': "  | 
4563  |  |             "Invalid value. Expected is "  | 
4564  |  |             "'yes' or 'no'.\n");  | 
4565  |  |         cctxt->style->errors++;  | 
4566  |  |           }  | 
4567  |  |           break;  | 
4568  |  |       }  | 
4569  |  |       attr = attr->next;  | 
4570  |  |         } while (attr != NULL);  | 
4571  |  |     }  | 
4572  |  |       } else if (IS_XSLT_ELEM_FAST(cur)) { | 
4573  |  |     /*  | 
4574  |  |     * TODO: Using the XSLT-marker is still not stable yet.  | 
4575  |  |     */  | 
4576  |  |     /* if (cur->psvi == xsltXSLTElemMarker) { */ | 
4577  |  |     /*  | 
4578  |  |     * XSLT instructions  | 
4579  |  |     * --------------------------------------------------------  | 
4580  |  |     */  | 
4581  |  |     cur->psvi = NULL;  | 
4582  |  |     type = xsltGetXSLTElementTypeByNode(cctxt, cur);  | 
4583  |  |     switch (type) { | 
4584  |  |         case XSLT_FUNC_APPLYIMPORTS:  | 
4585  |  |         case XSLT_FUNC_APPLYTEMPLATES:  | 
4586  |  |         case XSLT_FUNC_ATTRIBUTE:  | 
4587  |  |         case XSLT_FUNC_CALLTEMPLATE:  | 
4588  |  |         case XSLT_FUNC_CHOOSE:  | 
4589  |  |         case XSLT_FUNC_COMMENT:  | 
4590  |  |         case XSLT_FUNC_COPY:  | 
4591  |  |         case XSLT_FUNC_COPYOF:  | 
4592  |  |         case XSLT_FUNC_DOCUMENT: /* Extra one */  | 
4593  |  |         case XSLT_FUNC_ELEMENT:  | 
4594  |  |         case XSLT_FUNC_FALLBACK:  | 
4595  |  |         case XSLT_FUNC_FOREACH:  | 
4596  |  |         case XSLT_FUNC_IF:  | 
4597  |  |         case XSLT_FUNC_MESSAGE:  | 
4598  |  |         case XSLT_FUNC_NUMBER:  | 
4599  |  |         case XSLT_FUNC_PI:  | 
4600  |  |         case XSLT_FUNC_TEXT:  | 
4601  |  |         case XSLT_FUNC_VALUEOF:  | 
4602  |  |         case XSLT_FUNC_VARIABLE:  | 
4603  |  |       /*  | 
4604  |  |       * Parse the XSLT element.  | 
4605  |  |       */  | 
4606  |  |       cctxt->inode->curChildType = type;  | 
4607  |  |       xsltParseAnyXSLTElem(cctxt, cur);  | 
4608  |  |       break;  | 
4609  |  |         default:  | 
4610  |  |       xsltParseUnknownXSLTElem(cctxt, cur);  | 
4611  |  |       cur = cur->next;  | 
4612  |  |       continue;  | 
4613  |  |     }  | 
4614  |  |       } else { | 
4615  |  |     /*  | 
4616  |  |     * Non-XSLT elements  | 
4617  |  |     * -----------------  | 
4618  |  |     */  | 
4619  |  |     xsltCompilerNodePush(cctxt, cur);  | 
4620  |  |     /*  | 
4621  |  |     * Update the in-scope namespaces if needed.  | 
4622  |  |     */  | 
4623  |  |     if (cur->nsDef != NULL)  | 
4624  |  |         cctxt->inode->inScopeNs =  | 
4625  |  |       xsltCompilerBuildInScopeNsList(cctxt, cur);  | 
4626  |  |     /*  | 
4627  |  |     * The current element is either a literal result element  | 
4628  |  |     * or an extension instruction.  | 
4629  |  |     *  | 
4630  |  |     * Process attr "xsl:extension-element-prefixes".  | 
4631  |  |     * FUTURE TODO: IIRC in XSLT 2.0 this attribute must be  | 
4632  |  |     * processed by the implementor of the extension function;  | 
4633  |  |     * i.e., it won't be handled by the XSLT processor.  | 
4634  |  |     */  | 
4635  |  |     /* SPEC 1.0:  | 
4636  |  |     *   "exclude-result-prefixes" is only allowed on literal  | 
4637  |  |     *   result elements and "xsl:exclude-result-prefixes"  | 
4638  |  |     *   on xsl:stylesheet/xsl:transform.  | 
4639  |  |     * SPEC 2.0:  | 
4640  |  |     *   "There are a number of standard attributes  | 
4641  |  |     *   that may appear on any XSLT element: specifically  | 
4642  |  |     *   version, exclude-result-prefixes,  | 
4643  |  |     *   extension-element-prefixes, xpath-default-namespace,  | 
4644  |  |     *   default-collation, and use-when."  | 
4645  |  |     *  | 
4646  |  |     * SPEC 2.0:  | 
4647  |  |     *   For literal result elements:  | 
4648  |  |     *   "xsl:version, xsl:exclude-result-prefixes,  | 
4649  |  |     *    xsl:extension-element-prefixes,  | 
4650  |  |     *    xsl:xpath-default-namespace,  | 
4651  |  |     *    xsl:default-collation, or xsl:use-when."  | 
4652  |  |     */  | 
4653  |  |     if (cur->properties)  | 
4654  |  |         cctxt->inode->extElemNs =  | 
4655  |  |       xsltParseExtElemPrefixes(cctxt,  | 
4656  |  |           cur, cctxt->inode->extElemNs,  | 
4657  |  |           XSLT_ELEMENT_CATEGORY_LRE);  | 
4658  |  |     /*  | 
4659  |  |     * Eval if we have an extension instruction here.  | 
4660  |  |     */  | 
4661  |  |     if ((cur->ns != NULL) &&  | 
4662  |  |         (cctxt->inode->extElemNs != NULL) &&  | 
4663  |  |         (xsltCheckExtPrefix(cctxt->style, cur->ns->href) == 1))  | 
4664  |  |     { | 
4665  |  |         /*  | 
4666  |  |         * Extension instructions  | 
4667  |  |         * ----------------------------------------------------  | 
4668  |  |         * Mark the node information.  | 
4669  |  |         */  | 
4670  |  |         cctxt->inode->category = XSLT_ELEMENT_CATEGORY_EXTENSION;  | 
4671  |  |         cctxt->inode->extContentHandled = 0;  | 
4672  |  |         if (cur->psvi != NULL) { | 
4673  |  |       cur->psvi = NULL;  | 
4674  |  |       /*  | 
4675  |  |       * TODO: Temporary sanity check.  | 
4676  |  |       */  | 
4677  |  |       xsltTransformError(NULL, cctxt->style, cur,  | 
4678  |  |           "Internal error in xsltParseSequenceConstructor(): "  | 
4679  |  |           "Occupied PSVI field.\n");  | 
4680  |  |       cctxt->style->errors++;  | 
4681  |  |       cur = cur->next;  | 
4682  |  |       continue;  | 
4683  |  |         }  | 
4684  |  |         cur->psvi = (void *)  | 
4685  |  |       xsltPreComputeExtModuleElement(cctxt->style, cur);  | 
4686  |  |  | 
4687  |  |         if (cur->psvi == NULL) { | 
4688  |  |       /*  | 
4689  |  |       * OLD COMMENT: "Unknown element, maybe registered  | 
4690  |  |       *  at the context level. Mark it for later  | 
4691  |  |       *  recognition."  | 
4692  |  |       * QUESTION: What does the xsltExtMarker mean?  | 
4693  |  |       *  ANSWER: It is used in  | 
4694  |  |       *   xsltApplySequenceConstructor() at  | 
4695  |  |       *   transformation-time to look out for extension  | 
4696  |  |       *   registered in the transformation context.  | 
4697  |  |       */  | 
4698  |  |       cur->psvi = (void *) xsltExtMarker;  | 
4699  |  |         }  | 
4700  |  |         /*  | 
4701  |  |         * BIG NOTE: Now the ugly part. In previous versions  | 
4702  |  |         *  of Libxslt (until 1.1.16), all the content of an  | 
4703  |  |         *  extension instruction was processed and compiled without  | 
4704  |  |         *  the need of the extension-author to explicitely call  | 
4705  |  |         *  such a processing;.We now need to mimic this old  | 
4706  |  |         *  behaviour in order to avoid breaking old code  | 
4707  |  |         *  on the extension-author's side.  | 
4708  |  |         * The mechanism:  | 
4709  |  |         *  1) If the author does *not* set the  | 
4710  |  |         *    compile-time-flag @extContentHandled, then we'll  | 
4711  |  |         *    parse the content assuming that it's a "template"  | 
4712  |  |         *    (or "sequence constructor in XSLT 2.0 terms).  | 
4713  |  |         *    NOTE: If the extension is registered at  | 
4714  |  |         *    transformation-time only, then there's no way of  | 
4715  |  |         *    knowing that content shall be valid, and we'll  | 
4716  |  |         *    process the content the same way.  | 
4717  |  |         *  2) If the author *does* set the flag, then we'll assume  | 
4718  |  |         *   that the author has handled the parsing him/herself  | 
4719  |  |         *   (e.g. called xsltParseSequenceConstructor(), etc.  | 
4720  |  |         *   explicitely in his/her code).  | 
4721  |  |         */  | 
4722  |  |         if ((cur->children != NULL) &&  | 
4723  |  |       (cctxt->inode->extContentHandled == 0))  | 
4724  |  |         { | 
4725  |  |       /*  | 
4726  |  |       * Default parsing of the content using the  | 
4727  |  |       * sequence-constructor model.  | 
4728  |  |       */  | 
4729  |  |       xsltParseSequenceConstructor(cctxt, cur->children);  | 
4730  |  |         }  | 
4731  |  |     } else { | 
4732  |  |         /*  | 
4733  |  |         * Literal result element  | 
4734  |  |         * ----------------------------------------------------  | 
4735  |  |         * Allowed XSLT attributes:  | 
4736  |  |         *  xsl:extension-element-prefixes CDATA #IMPLIED  | 
4737  |  |         *  xsl:exclude-result-prefixes CDATA #IMPLIED  | 
4738  |  |         *  TODO: xsl:use-attribute-sets %qnames; #IMPLIED  | 
4739  |  |         *  xsl:version NMTOKEN #IMPLIED  | 
4740  |  |         */  | 
4741  |  |         cur->psvi = NULL;  | 
4742  |  |         cctxt->inode->category = XSLT_ELEMENT_CATEGORY_LRE;  | 
4743  |  |         if (cur->properties != NULL) { | 
4744  |  |       xmlAttrPtr attr = cur->properties;  | 
4745  |  |       /*  | 
4746  |  |       * Attribute "xsl:exclude-result-prefixes".  | 
4747  |  |       */  | 
4748  |  |       cctxt->inode->exclResultNs =  | 
4749  |  |           xsltParseExclResultPrefixes(cctxt, cur,  | 
4750  |  |         cctxt->inode->exclResultNs,  | 
4751  |  |         XSLT_ELEMENT_CATEGORY_LRE);  | 
4752  |  |       /*  | 
4753  |  |       * Attribute "xsl:version".  | 
4754  |  |       */  | 
4755  |  |       xsltParseAttrXSLTVersion(cctxt, cur,  | 
4756  |  |           XSLT_ELEMENT_CATEGORY_LRE);  | 
4757  |  |       /*  | 
4758  |  |       * Report invalid XSLT attributes.  | 
4759  |  |       * For XSLT 1.0 only xsl:use-attribute-sets is allowed  | 
4760  |  |       * next to xsl:version, xsl:exclude-result-prefixes and  | 
4761  |  |       * xsl:extension-element-prefixes.  | 
4762  |  |       *  | 
4763  |  |       * Mark all XSLT attributes, in order to skip such  | 
4764  |  |       * attributes when instantiating the LRE.  | 
4765  |  |       */  | 
4766  |  |       do { | 
4767  |  |           if ((attr->psvi != xsltXSLTAttrMarker) &&  | 
4768  |  |         IS_XSLT_ATTR_FAST(attr))  | 
4769  |  |           { | 
4770  |  |         if (! xmlStrEqual(attr->name,  | 
4771  |  |             BAD_CAST "use-attribute-sets"))  | 
4772  |  |         { | 
4773  |  |             xsltTransformError(NULL, cctxt->style,  | 
4774  |  |           cur,  | 
4775  |  |           "Unknown XSLT attribute '%s'.\n",  | 
4776  |  |           attr->name);  | 
4777  |  |             cctxt->style->errors++;  | 
4778  |  |         } else { | 
4779  |  |             /*  | 
4780  |  |             * XSLT attr marker.  | 
4781  |  |             */  | 
4782  |  |             attr->psvi = (void *) xsltXSLTAttrMarker;  | 
4783  |  |         }  | 
4784  |  |           }  | 
4785  |  |           attr = attr->next;  | 
4786  |  |       } while (attr != NULL);  | 
4787  |  |         }  | 
4788  |  |         /*  | 
4789  |  |         * Create/reuse info for the literal result element.  | 
4790  |  |         */  | 
4791  |  |         if (cctxt->inode->nsChanged)  | 
4792  |  |       xsltLREInfoCreate(cctxt, cur, 1);  | 
4793  |  |         cur->psvi = cctxt->inode->litResElemInfo;  | 
4794  |  |         /*  | 
4795  |  |         * Apply ns-aliasing on the element and on its attributes.  | 
4796  |  |         */  | 
4797  |  |         if (cctxt->hasNsAliases)  | 
4798  |  |       xsltLREBuildEffectiveNs(cctxt, cur);  | 
4799  |  |         /*  | 
4800  |  |         * Compile attribute value templates (AVT).  | 
4801  |  |         */  | 
4802  |  |         if (cur->properties) { | 
4803  |  |       xmlAttrPtr attr = cur->properties;  | 
4804  |  |  | 
4805  |  |       while (attr != NULL) { | 
4806  |  |           xsltCompileAttr(cctxt->style, attr);  | 
4807  |  |           attr = attr->next;  | 
4808  |  |       }  | 
4809  |  |         }  | 
4810  |  |         /*  | 
4811  |  |         * Parse the content, which is defined to be a "template"  | 
4812  |  |         * (or "sequence constructor" in XSLT 2.0 terms).  | 
4813  |  |         */  | 
4814  |  |         if (cur->children != NULL) { | 
4815  |  |       xsltParseSequenceConstructor(cctxt, cur->children);  | 
4816  |  |         }  | 
4817  |  |     }  | 
4818  |  |     /*  | 
4819  |  |     * Leave the non-XSLT element.  | 
4820  |  |     */  | 
4821  |  |     xsltCompilerNodePop(cctxt, cur);  | 
4822  |  |       }  | 
4823  |  |   }  | 
4824  |  |   cur = cur->next;  | 
4825  |  |     }  | 
4826  |  |     if (deleteNode != NULL) { | 
4827  |  | #ifdef WITH_XSLT_DEBUG_BLANKS  | 
4828  |  |   xsltGenericDebug(xsltGenericDebugContext,  | 
4829  |  |       "xsltParseSequenceConstructor: removing xsl:text element\n");  | 
4830  |  | #endif  | 
4831  |  |   xmlUnlinkNode(deleteNode);  | 
4832  |  |   xmlFreeNode(deleteNode);  | 
4833  |  |   deleteNode = NULL;  | 
4834  |  |     }  | 
4835  |  | }  | 
4836  |  |  | 
4837  |  | /**  | 
4838  |  |  * xsltParseTemplateContent:  | 
4839  |  |  * @style:  the XSLT stylesheet  | 
4840  |  |  * @templ:  the node containing the content to be parsed  | 
4841  |  |  *  | 
4842  |  |  * Parses and compiles the content-model of an xsl:template element.  | 
4843  |  |  * Note that this is *not* the "template" content model (or "sequence  | 
4844  |  |  *  constructor" in XSLT 2.0); it it allows addional xsl:param  | 
4845  |  |  *  elements as immediate children of @templ.  | 
4846  |  |  *  | 
4847  |  |  * Called by:  | 
4848  |  |  *   exsltFuncFunctionComp() (EXSLT, functions.c)  | 
4849  |  |  *   So this is intended to be called from extension functions.  | 
4850  |  |  */  | 
4851  |  | void  | 
4852  |  | xsltParseTemplateContent(xsltStylesheetPtr style, xmlNodePtr templ) { | 
4853  |  |     if ((style == NULL) || (templ == NULL) ||  | 
4854  |  |         (templ->type == XML_NAMESPACE_DECL))  | 
4855  |  |   return;  | 
4856  |  |  | 
4857  |  |     /*  | 
4858  |  |     * Detection of handled content of extension instructions.  | 
4859  |  |     */  | 
4860  |  |     if (XSLT_CCTXT(style)->inode->category == XSLT_ELEMENT_CATEGORY_EXTENSION) { | 
4861  |  |   XSLT_CCTXT(style)->inode->extContentHandled = 1;  | 
4862  |  |     }  | 
4863  |  |  | 
4864  |  |     if (templ->children != NULL) { | 
4865  |  |   xmlNodePtr child = templ->children;  | 
4866  |  |   /*  | 
4867  |  |   * Process xsl:param elements, which can only occur as the  | 
4868  |  |   * immediate children of xsl:template (well, and of any  | 
4869  |  |   * user-defined extension instruction if needed).  | 
4870  |  |   */  | 
4871  |  |   do { | 
4872  |  |       if ((child->type == XML_ELEMENT_NODE) &&  | 
4873  |  |     IS_XSLT_ELEM_FAST(child) &&  | 
4874  |  |     IS_XSLT_NAME(child, "param"))  | 
4875  |  |       { | 
4876  |  |     XSLT_CCTXT(style)->inode->curChildType = XSLT_FUNC_PARAM;  | 
4877  |  |     xsltParseAnyXSLTElem(XSLT_CCTXT(style), child);  | 
4878  |  |       } else  | 
4879  |  |     break;  | 
4880  |  |       child = child->next;  | 
4881  |  |   } while (child != NULL);  | 
4882  |  |   /*  | 
4883  |  |   * Parse the content and register the pattern.  | 
4884  |  |   */  | 
4885  |  |   xsltParseSequenceConstructor(XSLT_CCTXT(style), child);  | 
4886  |  |     }  | 
4887  |  | }  | 
4888  |  |  | 
4889  |  | #else /* XSLT_REFACTORED */  | 
4890  |  |  | 
4891  |  | /**  | 
4892  |  |  * xsltParseTemplateContent:  | 
4893  |  |  * @style:  the XSLT stylesheet  | 
4894  |  |  * @templ:  the container node (can be a document for literal results)  | 
4895  |  |  *  | 
4896  |  |  * parse a template content-model  | 
4897  |  |  * Clean-up the template content from unwanted ignorable blank nodes  | 
4898  |  |  * and process xslt:text  | 
4899  |  |  */  | 
4900  |  | void  | 
4901  | 0  | xsltParseTemplateContent(xsltStylesheetPtr style, xmlNodePtr templ) { | 
4902  | 0  |     xmlNodePtr cur, delete;  | 
4903  |  | 
  | 
4904  | 0  |     if ((style == NULL) || (templ == NULL) ||  | 
4905  | 0  |         (templ->type == XML_NAMESPACE_DECL)) return;  | 
4906  |  |  | 
4907  |  |     /*  | 
4908  |  |      * This content comes from the stylesheet  | 
4909  |  |      * For stylesheets, the set of whitespace-preserving  | 
4910  |  |      * element names consists of just xsl:text.  | 
4911  |  |      */  | 
4912  | 0  |     cur = templ->children;  | 
4913  | 0  |     delete = NULL;  | 
4914  | 0  |     while (cur != NULL) { | 
4915  | 0  |   if (delete != NULL) { | 
4916  |  | #ifdef WITH_XSLT_DEBUG_BLANKS  | 
4917  |  |       xsltGenericDebug(xsltGenericDebugContext,  | 
4918  |  |        "xsltParseTemplateContent: removing text\n");  | 
4919  |  | #endif  | 
4920  | 0  |       xmlUnlinkNode(delete);  | 
4921  | 0  |       xmlFreeNode(delete);  | 
4922  | 0  |       delete = NULL;  | 
4923  | 0  |   }  | 
4924  | 0  |   if (IS_XSLT_ELEM(cur)) { | 
4925  | 0  |             xsltStylePreCompute(style, cur);  | 
4926  |  | 
  | 
4927  | 0  |       if (IS_XSLT_NAME(cur, "text")) { | 
4928  |  |     /*  | 
4929  |  |     * TODO: Processing of xsl:text should be moved to  | 
4930  |  |     *   xsltPreprocessStylesheet(), since otherwise this  | 
4931  |  |     *   will be performed for every multiply included  | 
4932  |  |     *   stylesheet; i.e. this here is not skipped with  | 
4933  |  |     *   the use of the style->nopreproc flag.  | 
4934  |  |     */  | 
4935  | 0  |     if (cur->children != NULL) { | 
4936  | 0  |         xmlChar *prop;  | 
4937  | 0  |         xmlNodePtr text = cur->children, next;  | 
4938  | 0  |         int noesc = 0;  | 
4939  |  | 
  | 
4940  | 0  |         prop = xmlGetNsProp(cur,  | 
4941  | 0  |       (const xmlChar *)"disable-output-escaping",  | 
4942  | 0  |       NULL);  | 
4943  | 0  |         if (prop != NULL) { | 
4944  |  | #ifdef WITH_XSLT_DEBUG_PARSING  | 
4945  |  |       xsltGenericDebug(xsltGenericDebugContext,  | 
4946  |  |            "Disable escaping: %s\n", text->content);  | 
4947  |  | #endif  | 
4948  | 0  |       if (xmlStrEqual(prop, (const xmlChar *)"yes")) { | 
4949  | 0  |           noesc = 1;  | 
4950  | 0  |       } else if (!xmlStrEqual(prop,  | 
4951  | 0  |             (const xmlChar *)"no")){ | 
4952  | 0  |           xsltTransformError(NULL, style, cur,  | 
4953  | 0  |        "xsl:text: disable-output-escaping allows only yes or no\n");  | 
4954  | 0  |           style->warnings++;  | 
4955  |  | 
  | 
4956  | 0  |       }  | 
4957  | 0  |       xmlFree(prop);  | 
4958  | 0  |         }  | 
4959  |  | 
  | 
4960  | 0  |         while (text != NULL) { | 
4961  | 0  |       if (text->type == XML_COMMENT_NODE) { | 
4962  | 0  |           text = text->next;  | 
4963  | 0  |           continue;  | 
4964  | 0  |       }  | 
4965  | 0  |       if ((text->type != XML_TEXT_NODE) &&  | 
4966  | 0  |            (text->type != XML_CDATA_SECTION_NODE)) { | 
4967  | 0  |           xsltTransformError(NULL, style, cur,  | 
4968  | 0  |      "xsltParseTemplateContent: xslt:text content problem\n");  | 
4969  | 0  |           style->errors++;  | 
4970  | 0  |           break;  | 
4971  | 0  |       }  | 
4972  | 0  |       if ((noesc) && (text->type != XML_CDATA_SECTION_NODE))  | 
4973  | 0  |           text->name = xmlStringTextNoenc;  | 
4974  | 0  |       text = text->next;  | 
4975  | 0  |         }  | 
4976  |  |  | 
4977  |  |         /*  | 
4978  |  |          * replace xsl:text by the list of childs  | 
4979  |  |          */  | 
4980  | 0  |         if (text == NULL) { | 
4981  | 0  |       text = cur->children;  | 
4982  | 0  |       while (text != NULL) { | 
4983  | 0  |           if ((style->internalized) &&  | 
4984  | 0  |               (text->content != NULL) &&  | 
4985  | 0  |               (!xmlDictOwns(style->dict, text->content))) { | 
4986  |  |  | 
4987  |  |         /*  | 
4988  |  |          * internalize the text string  | 
4989  |  |          */  | 
4990  | 0  |         if (text->doc->dict != NULL) { | 
4991  | 0  |             const xmlChar *tmp;  | 
4992  |  | 
  | 
4993  | 0  |             tmp = xmlDictLookup(text->doc->dict,  | 
4994  | 0  |                                 text->content, -1);  | 
4995  | 0  |             if (tmp != text->content) { | 
4996  | 0  |                 xmlNodeSetContent(text, NULL);  | 
4997  | 0  |           text->content = (xmlChar *) tmp;  | 
4998  | 0  |             }  | 
4999  | 0  |         }  | 
5000  | 0  |           }  | 
5001  |  | 
  | 
5002  | 0  |           next = text->next;  | 
5003  | 0  |           xmlUnlinkNode(text);  | 
5004  | 0  |           xmlAddPrevSibling(cur, text);  | 
5005  | 0  |           text = next;  | 
5006  | 0  |       }  | 
5007  | 0  |         }  | 
5008  | 0  |     }  | 
5009  | 0  |     delete = cur;  | 
5010  | 0  |     goto skip_children;  | 
5011  | 0  |       }  | 
5012  | 0  |   }  | 
5013  | 0  |   else if ((cur->ns != NULL) && (style->nsDefs != NULL) &&  | 
5014  | 0  |       (xsltCheckExtPrefix(style, cur->ns->prefix)))  | 
5015  | 0  |   { | 
5016  |  |       /*  | 
5017  |  |        * okay this is an extension element compile it too  | 
5018  |  |        */  | 
5019  | 0  |       xsltStylePreCompute(style, cur);  | 
5020  | 0  |   }  | 
5021  | 0  |   else if (cur->type == XML_ELEMENT_NODE)  | 
5022  | 0  |   { | 
5023  |  |       /*  | 
5024  |  |        * This is an element which will be output as part of the  | 
5025  |  |        * template exectution, precompile AVT if found.  | 
5026  |  |        */  | 
5027  | 0  |       if ((cur->ns == NULL) && (style->defaultAlias != NULL)) { | 
5028  | 0  |     cur->ns = xmlSearchNsByHref(cur->doc, cur,  | 
5029  | 0  |       style->defaultAlias);  | 
5030  | 0  |       }  | 
5031  | 0  |       if (cur->properties != NULL) { | 
5032  | 0  |           xmlAttrPtr attr = cur->properties;  | 
5033  |  | 
  | 
5034  | 0  |     while (attr != NULL) { | 
5035  | 0  |         xsltCompileAttr(style, attr);  | 
5036  | 0  |         attr = attr->next;  | 
5037  | 0  |     }  | 
5038  | 0  |       }  | 
5039  | 0  |   }  | 
5040  |  |   /*  | 
5041  |  |    * Skip to next node  | 
5042  |  |    */  | 
5043  | 0  |   if (cur->children != NULL) { | 
5044  | 0  |       if (cur->children->type != XML_ENTITY_DECL) { | 
5045  | 0  |     cur = cur->children;  | 
5046  | 0  |     continue;  | 
5047  | 0  |       }  | 
5048  | 0  |   }  | 
5049  | 0  | skip_children:  | 
5050  | 0  |   if (cur->next != NULL) { | 
5051  | 0  |       cur = cur->next;  | 
5052  | 0  |       continue;  | 
5053  | 0  |   }  | 
5054  |  |  | 
5055  | 0  |   do { | 
5056  | 0  |       cur = cur->parent;  | 
5057  | 0  |       if (cur == NULL)  | 
5058  | 0  |     break;  | 
5059  | 0  |       if (cur == templ) { | 
5060  | 0  |     cur = NULL;  | 
5061  | 0  |     break;  | 
5062  | 0  |       }  | 
5063  | 0  |       if (cur->next != NULL) { | 
5064  | 0  |     cur = cur->next;  | 
5065  | 0  |     break;  | 
5066  | 0  |       }  | 
5067  | 0  |   } while (cur != NULL);  | 
5068  | 0  |     }  | 
5069  | 0  |     if (delete != NULL) { | 
5070  |  | #ifdef WITH_XSLT_DEBUG_PARSING  | 
5071  |  |   xsltGenericDebug(xsltGenericDebugContext,  | 
5072  |  |    "xsltParseTemplateContent: removing text\n");  | 
5073  |  | #endif  | 
5074  | 0  |   xmlUnlinkNode(delete);  | 
5075  | 0  |   xmlFreeNode(delete);  | 
5076  | 0  |   delete = NULL;  | 
5077  | 0  |     }  | 
5078  |  |  | 
5079  |  |     /*  | 
5080  |  |      * Skip the first params  | 
5081  |  |      */  | 
5082  | 0  |     cur = templ->children;  | 
5083  | 0  |     while (cur != NULL) { | 
5084  | 0  |   if ((IS_XSLT_ELEM(cur)) && (!(IS_XSLT_NAME(cur, "param"))))  | 
5085  | 0  |       break;  | 
5086  | 0  |   cur = cur->next;  | 
5087  | 0  |     }  | 
5088  |  |  | 
5089  |  |     /*  | 
5090  |  |      * Browse the remainder of the template  | 
5091  |  |      */  | 
5092  | 0  |     while (cur != NULL) { | 
5093  | 0  |   if ((IS_XSLT_ELEM(cur)) && (IS_XSLT_NAME(cur, "param"))) { | 
5094  | 0  |       xmlNodePtr param = cur;  | 
5095  |  | 
  | 
5096  | 0  |       xsltTransformError(NULL, style, cur,  | 
5097  | 0  |     "xsltParseTemplateContent: ignoring misplaced param element\n");  | 
5098  | 0  |       if (style != NULL) style->warnings++;  | 
5099  | 0  |             cur = cur->next;  | 
5100  | 0  |       xmlUnlinkNode(param);  | 
5101  | 0  |       xmlFreeNode(param);  | 
5102  | 0  |   } else  | 
5103  | 0  |       break;  | 
5104  | 0  |     }  | 
5105  | 0  | }  | 
5106  |  |  | 
5107  |  | #endif /* else XSLT_REFACTORED */  | 
5108  |  |  | 
5109  |  | /**  | 
5110  |  |  * xsltParseStylesheetKey:  | 
5111  |  |  * @style:  the XSLT stylesheet  | 
5112  |  |  * @key:  the "key" element  | 
5113  |  |  *  | 
5114  |  |  * <!-- Category: top-level-element -->  | 
5115  |  |  * <xsl:key name = qname, match = pattern, use = expression />  | 
5116  |  |  *  | 
5117  |  |  * parse an XSLT stylesheet key definition and register it  | 
5118  |  |  */  | 
5119  |  |  | 
5120  |  | static void  | 
5121  | 0  | xsltParseStylesheetKey(xsltStylesheetPtr style, xmlNodePtr key) { | 
5122  | 0  |     xmlChar *prop = NULL;  | 
5123  | 0  |     xmlChar *use = NULL;  | 
5124  | 0  |     xmlChar *match = NULL;  | 
5125  | 0  |     xmlChar *name = NULL;  | 
5126  | 0  |     xmlChar *nameURI = NULL;  | 
5127  |  | 
  | 
5128  | 0  |     if ((style == NULL) || (key == NULL) || (key->type != XML_ELEMENT_NODE))  | 
5129  | 0  |   return;  | 
5130  |  |  | 
5131  |  |     /*  | 
5132  |  |      * Get arguments  | 
5133  |  |      */  | 
5134  | 0  |     prop = xmlGetNsProp(key, (const xmlChar *)"name", NULL);  | 
5135  | 0  |     if (prop != NULL) { | 
5136  | 0  |         const xmlChar *URI;  | 
5137  |  |  | 
5138  |  |   /*  | 
5139  |  |   * TODO: Don't use xsltGetQNameURI().  | 
5140  |  |   */  | 
5141  | 0  |   URI = xsltGetQNameURI(key, &prop);  | 
5142  | 0  |   if (prop == NULL) { | 
5143  | 0  |       if (style != NULL) style->errors++;  | 
5144  | 0  |       goto error;  | 
5145  | 0  |   } else { | 
5146  | 0  |       name = prop;  | 
5147  | 0  |       if (URI != NULL)  | 
5148  | 0  |     nameURI = xmlStrdup(URI);  | 
5149  | 0  |   }  | 
5150  |  | #ifdef WITH_XSLT_DEBUG_PARSING  | 
5151  |  |   xsltGenericDebug(xsltGenericDebugContext,  | 
5152  |  |        "xsltParseStylesheetKey: name %s\n", name);  | 
5153  |  | #endif  | 
5154  | 0  |     } else { | 
5155  | 0  |   xsltTransformError(NULL, style, key,  | 
5156  | 0  |       "xsl:key : error missing name\n");  | 
5157  | 0  |   if (style != NULL) style->errors++;  | 
5158  | 0  |   goto error;  | 
5159  | 0  |     }  | 
5160  |  |  | 
5161  | 0  |     match = xmlGetNsProp(key, (const xmlChar *)"match", NULL);  | 
5162  | 0  |     if (match == NULL) { | 
5163  | 0  |   xsltTransformError(NULL, style, key,  | 
5164  | 0  |       "xsl:key : error missing match\n");  | 
5165  | 0  |   if (style != NULL) style->errors++;  | 
5166  | 0  |   goto error;  | 
5167  | 0  |     }  | 
5168  |  |  | 
5169  | 0  |     use = xmlGetNsProp(key, (const xmlChar *)"use", NULL);  | 
5170  | 0  |     if (use == NULL) { | 
5171  | 0  |   xsltTransformError(NULL, style, key,  | 
5172  | 0  |       "xsl:key : error missing use\n");  | 
5173  | 0  |   if (style != NULL) style->errors++;  | 
5174  | 0  |   goto error;  | 
5175  | 0  |     }  | 
5176  |  |  | 
5177  |  |     /*  | 
5178  |  |      * register the keys  | 
5179  |  |      */  | 
5180  | 0  |     xsltAddKey(style, name, nameURI, match, use, key);  | 
5181  |  |  | 
5182  |  | 
  | 
5183  | 0  | error:  | 
5184  | 0  |     if (use != NULL)  | 
5185  | 0  |   xmlFree(use);  | 
5186  | 0  |     if (match != NULL)  | 
5187  | 0  |   xmlFree(match);  | 
5188  | 0  |     if (name != NULL)  | 
5189  | 0  |   xmlFree(name);  | 
5190  | 0  |     if (nameURI != NULL)  | 
5191  | 0  |   xmlFree(nameURI);  | 
5192  |  | 
  | 
5193  | 0  |     if (key->children != NULL) { | 
5194  | 0  |   xsltParseContentError(style, key->children);  | 
5195  | 0  |     }  | 
5196  | 0  | }  | 
5197  |  |  | 
5198  |  | #ifdef XSLT_REFACTORED  | 
5199  |  | /**  | 
5200  |  |  * xsltParseXSLTTemplate:  | 
5201  |  |  * @style:  the XSLT stylesheet  | 
5202  |  |  * @template:  the "template" element  | 
5203  |  |  *  | 
5204  |  |  * parse an XSLT stylesheet template building the associated structures  | 
5205  |  |  * TODO: Is @style ever expected to be NULL?  | 
5206  |  |  *  | 
5207  |  |  * Called from:  | 
5208  |  |  *   xsltParseXSLTStylesheet()  | 
5209  |  |  *   xsltParseStylesheetTop()  | 
5210  |  |  */  | 
5211  |  |  | 
5212  |  | static void  | 
5213  |  | xsltParseXSLTTemplate(xsltCompilerCtxtPtr cctxt, xmlNodePtr templNode) { | 
5214  |  |     xsltTemplatePtr templ;  | 
5215  |  |     xmlChar *prop;  | 
5216  |  |     double  priority;  | 
5217  |  |  | 
5218  |  |     if ((cctxt == NULL) || (templNode == NULL) ||  | 
5219  |  |         (templNode->type != XML_ELEMENT_NODE))  | 
5220  |  |   return;  | 
5221  |  |  | 
5222  |  |     /*  | 
5223  |  |      * Create and link the structure  | 
5224  |  |      */  | 
5225  |  |     templ = xsltNewTemplate();  | 
5226  |  |     if (templ == NULL)  | 
5227  |  |   return;  | 
5228  |  |  | 
5229  |  |     xsltCompilerNodePush(cctxt, templNode);  | 
5230  |  |     if (templNode->nsDef != NULL)  | 
5231  |  |   cctxt->inode->inScopeNs =  | 
5232  |  |       xsltCompilerBuildInScopeNsList(cctxt, templNode);  | 
5233  |  |  | 
5234  |  |     templ->next = cctxt->style->templates;  | 
5235  |  |     cctxt->style->templates = templ;  | 
5236  |  |     templ->style = cctxt->style;  | 
5237  |  |  | 
5238  |  |     /*  | 
5239  |  |     * Attribute "mode".  | 
5240  |  |     */  | 
5241  |  |     prop = xmlGetNsProp(templNode, (const xmlChar *)"mode", NULL);  | 
5242  |  |     if (prop != NULL) { | 
5243  |  |         const xmlChar *modeURI;  | 
5244  |  |  | 
5245  |  |   /*  | 
5246  |  |   * TODO: We need a standardized function for extraction  | 
5247  |  |   *  of namespace names and local names from QNames.  | 
5248  |  |   *  Don't use xsltGetQNameURI() as it cannot channe�  | 
5249  |  |   *  reports through the context.  | 
5250  |  |   */  | 
5251  |  |   modeURI = xsltGetQNameURI(templNode, &prop);  | 
5252  |  |   if (prop == NULL) { | 
5253  |  |       cctxt->style->errors++;  | 
5254  |  |       goto error;  | 
5255  |  |   }  | 
5256  |  |   templ->mode = xmlDictLookup(cctxt->style->dict, prop, -1);  | 
5257  |  |   xmlFree(prop);  | 
5258  |  |   prop = NULL;  | 
5259  |  |   if (xmlValidateNCName(templ->mode, 0)) { | 
5260  |  |       xsltTransformError(NULL, cctxt->style, templNode,  | 
5261  |  |     "xsl:template: Attribute 'mode': The local part '%s' "  | 
5262  |  |     "of the value is not a valid NCName.\n", templ->name);  | 
5263  |  |       cctxt->style->errors++;  | 
5264  |  |       goto error;  | 
5265  |  |   }  | 
5266  |  |   if (modeURI != NULL)  | 
5267  |  |       templ->modeURI = xmlDictLookup(cctxt->style->dict, modeURI, -1);  | 
5268  |  | #ifdef WITH_XSLT_DEBUG_PARSING  | 
5269  |  |   xsltGenericDebug(xsltGenericDebugContext,  | 
5270  |  |        "xsltParseXSLTTemplate: mode %s\n", templ->mode);  | 
5271  |  | #endif  | 
5272  |  |     }  | 
5273  |  |     /*  | 
5274  |  |     * Attribute "match".  | 
5275  |  |     */  | 
5276  |  |     prop = xmlGetNsProp(templNode, (const xmlChar *)"match", NULL);  | 
5277  |  |     if (prop != NULL) { | 
5278  |  |   templ->match  = prop;  | 
5279  |  |   prop = NULL;  | 
5280  |  |     }  | 
5281  |  |     /*  | 
5282  |  |     * Attribute "priority".  | 
5283  |  |     */  | 
5284  |  |     prop = xmlGetNsProp(templNode, (const xmlChar *)"priority", NULL);  | 
5285  |  |     if (prop != NULL) { | 
5286  |  |   priority = xmlXPathStringEvalNumber(prop);  | 
5287  |  |   templ->priority = (float) priority;  | 
5288  |  |   xmlFree(prop);  | 
5289  |  |   prop = NULL;  | 
5290  |  |     }  | 
5291  |  |     /*  | 
5292  |  |     * Attribute "name".  | 
5293  |  |     */  | 
5294  |  |     prop = xmlGetNsProp(templNode, (const xmlChar *)"name", NULL);  | 
5295  |  |     if (prop != NULL) { | 
5296  |  |         const xmlChar *nameURI;  | 
5297  |  |   xsltTemplatePtr curTempl;  | 
5298  |  |  | 
5299  |  |   /*  | 
5300  |  |   * TODO: Don't use xsltGetQNameURI().  | 
5301  |  |   */  | 
5302  |  |   nameURI = xsltGetQNameURI(templNode, &prop);  | 
5303  |  |   if (prop == NULL) { | 
5304  |  |       cctxt->style->errors++;  | 
5305  |  |       goto error;  | 
5306  |  |   }  | 
5307  |  |   templ->name = xmlDictLookup(cctxt->style->dict, prop, -1);  | 
5308  |  |   xmlFree(prop);  | 
5309  |  |   prop = NULL;  | 
5310  |  |   if (xmlValidateNCName(templ->name, 0)) { | 
5311  |  |       xsltTransformError(NULL, cctxt->style, templNode,  | 
5312  |  |     "xsl:template: Attribute 'name': The local part '%s' of "  | 
5313  |  |     "the value is not a valid NCName.\n", templ->name);  | 
5314  |  |       cctxt->style->errors++;  | 
5315  |  |       goto error;  | 
5316  |  |   }  | 
5317  |  |   if (nameURI != NULL)  | 
5318  |  |       templ->nameURI = xmlDictLookup(cctxt->style->dict, nameURI, -1);  | 
5319  |  |   curTempl = templ->next;  | 
5320  |  |   while (curTempl != NULL) { | 
5321  |  |       if ((nameURI != NULL && xmlStrEqual(curTempl->name, templ->name) &&  | 
5322  |  |     xmlStrEqual(curTempl->nameURI, nameURI) ) ||  | 
5323  |  |     (nameURI == NULL && curTempl->nameURI == NULL &&  | 
5324  |  |     xmlStrEqual(curTempl->name, templ->name)))  | 
5325  |  |       { | 
5326  |  |     xsltTransformError(NULL, cctxt->style, templNode,  | 
5327  |  |         "xsl:template: error duplicate name '%s'\n", templ->name);  | 
5328  |  |     cctxt->style->errors++;  | 
5329  |  |     goto error;  | 
5330  |  |       }  | 
5331  |  |       curTempl = curTempl->next;  | 
5332  |  |   }  | 
5333  |  |     }  | 
5334  |  |     if (templNode->children != NULL) { | 
5335  |  |   xsltParseTemplateContent(cctxt->style, templNode);  | 
5336  |  |   /*  | 
5337  |  |   * MAYBE TODO: Custom behaviour: In order to stay compatible with  | 
5338  |  |   * Xalan and MSXML(.NET), we could allow whitespace  | 
5339  |  |   * to appear before an xml:param element; this whitespace  | 
5340  |  |   * will additionally become part of the "template".  | 
5341  |  |   * NOTE that this is totally deviates from the spec, but  | 
5342  |  |   * is the de facto behaviour of Xalan and MSXML(.NET).  | 
5343  |  |   * Personally I wouldn't allow this, since if we have:  | 
5344  |  |   * <xsl:template ...xml:space="preserve">  | 
5345  |  |   *   <xsl:param name="foo"/>  | 
5346  |  |   *   <xsl:param name="bar"/>  | 
5347  |  |   *   <xsl:param name="zoo"/>  | 
5348  |  |   * ... the whitespace between every xsl:param would be  | 
5349  |  |   * added to the result tree.  | 
5350  |  |   */  | 
5351  |  |     }  | 
5352  |  |  | 
5353  |  |     templ->elem = templNode;  | 
5354  |  |     templ->content = templNode->children;  | 
5355  |  |     xsltAddTemplate(cctxt->style, templ, templ->mode, templ->modeURI);  | 
5356  |  |  | 
5357  |  | error:  | 
5358  |  |     xsltCompilerNodePop(cctxt, templNode);  | 
5359  |  |     return;  | 
5360  |  | }  | 
5361  |  |  | 
5362  |  | #else /* XSLT_REFACTORED */  | 
5363  |  |  | 
5364  |  | /**  | 
5365  |  |  * xsltParseStylesheetTemplate:  | 
5366  |  |  * @style:  the XSLT stylesheet  | 
5367  |  |  * @template:  the "template" element  | 
5368  |  |  *  | 
5369  |  |  * parse an XSLT stylesheet template building the associated structures  | 
5370  |  |  */  | 
5371  |  |  | 
5372  |  | static void  | 
5373  | 0  | xsltParseStylesheetTemplate(xsltStylesheetPtr style, xmlNodePtr template) { | 
5374  | 0  |     xsltTemplatePtr ret;  | 
5375  | 0  |     xmlChar *prop;  | 
5376  | 0  |     xmlChar *mode = NULL;  | 
5377  | 0  |     xmlChar *modeURI = NULL;  | 
5378  | 0  |     double  priority;  | 
5379  |  | 
  | 
5380  | 0  |     if ((style == NULL) || (template == NULL) ||  | 
5381  | 0  |         (template->type != XML_ELEMENT_NODE))  | 
5382  | 0  |   return;  | 
5383  |  |  | 
5384  |  |     /*  | 
5385  |  |      * Create and link the structure  | 
5386  |  |      */  | 
5387  | 0  |     ret = xsltNewTemplate();  | 
5388  | 0  |     if (ret == NULL)  | 
5389  | 0  |   return;  | 
5390  | 0  |     ret->next = style->templates;  | 
5391  | 0  |     style->templates = ret;  | 
5392  | 0  |     ret->style = style;  | 
5393  |  |  | 
5394  |  |     /*  | 
5395  |  |      * Get inherited namespaces  | 
5396  |  |      */  | 
5397  |  |     /*  | 
5398  |  |     * TODO: Apply the optimized in-scope-namespace mechanism  | 
5399  |  |     *   as for the other XSLT instructions.  | 
5400  |  |     */  | 
5401  | 0  |     xsltGetInheritedNsList(style, ret, template);  | 
5402  |  |  | 
5403  |  |     /*  | 
5404  |  |      * Get arguments  | 
5405  |  |      */  | 
5406  | 0  |     prop = xmlGetNsProp(template, (const xmlChar *)"mode", NULL);  | 
5407  | 0  |     if (prop != NULL) { | 
5408  | 0  |         const xmlChar *URI;  | 
5409  |  |  | 
5410  |  |   /*  | 
5411  |  |   * TODO: Don't use xsltGetQNameURI().  | 
5412  |  |   */  | 
5413  | 0  |   URI = xsltGetQNameURI(template, &prop);  | 
5414  | 0  |   if (prop == NULL) { | 
5415  | 0  |       if (style != NULL) style->errors++;  | 
5416  | 0  |       goto error;  | 
5417  | 0  |   } else { | 
5418  | 0  |       mode = prop;  | 
5419  | 0  |       if (URI != NULL)  | 
5420  | 0  |     modeURI = xmlStrdup(URI);  | 
5421  | 0  |   }  | 
5422  | 0  |   ret->mode = xmlDictLookup(style->dict, mode, -1);  | 
5423  | 0  |   ret->modeURI = xmlDictLookup(style->dict, modeURI, -1);  | 
5424  |  | #ifdef WITH_XSLT_DEBUG_PARSING  | 
5425  |  |   xsltGenericDebug(xsltGenericDebugContext,  | 
5426  |  |        "xsltParseStylesheetTemplate: mode %s\n", mode);  | 
5427  |  | #endif  | 
5428  | 0  |         if (mode != NULL) xmlFree(mode);  | 
5429  | 0  |   if (modeURI != NULL) xmlFree(modeURI);  | 
5430  | 0  |     }  | 
5431  | 0  |     prop = xmlGetNsProp(template, (const xmlChar *)"match", NULL);  | 
5432  | 0  |     if (prop != NULL) { | 
5433  | 0  |   if (ret->match != NULL) xmlFree(ret->match);  | 
5434  | 0  |   ret->match  = prop;  | 
5435  | 0  |     }  | 
5436  |  | 
  | 
5437  | 0  |     prop = xmlGetNsProp(template, (const xmlChar *)"priority", NULL);  | 
5438  | 0  |     if (prop != NULL) { | 
5439  | 0  |   priority = xmlXPathStringEvalNumber(prop);  | 
5440  | 0  |   ret->priority = (float) priority;  | 
5441  | 0  |   xmlFree(prop);  | 
5442  | 0  |     }  | 
5443  |  | 
  | 
5444  | 0  |     prop = xmlGetNsProp(template, (const xmlChar *)"name", NULL);  | 
5445  | 0  |     if (prop != NULL) { | 
5446  | 0  |         const xmlChar *URI;  | 
5447  |  |  | 
5448  |  |   /*  | 
5449  |  |   * TODO: Don't use xsltGetQNameURI().  | 
5450  |  |   */  | 
5451  | 0  |   URI = xsltGetQNameURI(template, &prop);  | 
5452  | 0  |   if (prop == NULL) { | 
5453  | 0  |       if (style != NULL) style->errors++;  | 
5454  | 0  |       goto error;  | 
5455  | 0  |   } else { | 
5456  | 0  |       if (xmlValidateNCName(prop,0)) { | 
5457  | 0  |           xsltTransformError(NULL, style, template,  | 
5458  | 0  |               "xsl:template : error invalid name '%s'\n", prop);  | 
5459  | 0  |     if (style != NULL) style->errors++;  | 
5460  | 0  |                 xmlFree(prop);  | 
5461  | 0  |     goto error;  | 
5462  | 0  |       }  | 
5463  | 0  |       ret->name = xmlDictLookup(style->dict, BAD_CAST prop, -1);  | 
5464  | 0  |       xmlFree(prop);  | 
5465  | 0  |       prop = NULL;  | 
5466  | 0  |       if (URI != NULL)  | 
5467  | 0  |     ret->nameURI = xmlDictLookup(style->dict, BAD_CAST URI, -1);  | 
5468  | 0  |       else  | 
5469  | 0  |     ret->nameURI = NULL;  | 
5470  | 0  |   }  | 
5471  | 0  |     }  | 
5472  |  |  | 
5473  |  |     /*  | 
5474  |  |      * parse the content and register the pattern  | 
5475  |  |      */  | 
5476  | 0  |     xsltParseTemplateContent(style, template);  | 
5477  | 0  |     ret->elem = template;  | 
5478  | 0  |     ret->content = template->children;  | 
5479  | 0  |     xsltAddTemplate(style, ret, ret->mode, ret->modeURI);  | 
5480  |  | 
  | 
5481  | 0  | error:  | 
5482  | 0  |     return;  | 
5483  | 0  | }  | 
5484  |  |  | 
5485  |  | #endif /* else XSLT_REFACTORED */  | 
5486  |  |  | 
5487  |  | #ifdef XSLT_REFACTORED  | 
5488  |  |  | 
5489  |  | /**  | 
5490  |  |  * xsltIncludeComp:  | 
5491  |  |  * @cctxt: the compilation context  | 
5492  |  |  * @node:  the xsl:include node  | 
5493  |  |  *  | 
5494  |  |  * Process the xslt include node on the source node  | 
5495  |  |  */  | 
5496  |  | static xsltStyleItemIncludePtr  | 
5497  |  | xsltCompileXSLTIncludeElem(xsltCompilerCtxtPtr cctxt, xmlNodePtr node) { | 
5498  |  |     xsltStyleItemIncludePtr item;  | 
5499  |  |  | 
5500  |  |     if ((cctxt == NULL) || (node == NULL) || (node->type != XML_ELEMENT_NODE))  | 
5501  |  |   return(NULL);  | 
5502  |  |  | 
5503  |  |     node->psvi = NULL;  | 
5504  |  |     item = (xsltStyleItemIncludePtr) xmlMalloc(sizeof(xsltStyleItemInclude));  | 
5505  |  |     if (item == NULL) { | 
5506  |  |   xsltTransformError(NULL, cctxt->style, node,  | 
5507  |  |     "xsltIncludeComp : malloc failed\n");  | 
5508  |  |   cctxt->style->errors++;  | 
5509  |  |   return(NULL);  | 
5510  |  |     }  | 
5511  |  |     memset(item, 0, sizeof(xsltStyleItemInclude));  | 
5512  |  |  | 
5513  |  |     node->psvi = item;  | 
5514  |  |     item->inst = node;  | 
5515  |  |     item->type = XSLT_FUNC_INCLUDE;  | 
5516  |  |  | 
5517  |  |     item->next = cctxt->style->preComps;  | 
5518  |  |     cctxt->style->preComps = (xsltElemPreCompPtr) item;  | 
5519  |  |  | 
5520  |  |     return(item);  | 
5521  |  | }  | 
5522  |  |  | 
5523  |  | /**  | 
5524  |  |  * xsltParseFindTopLevelElem:  | 
5525  |  |  */  | 
5526  |  | static int  | 
5527  |  | xsltParseFindTopLevelElem(xsltCompilerCtxtPtr cctxt,  | 
5528  |  |             xmlNodePtr cur,  | 
5529  |  |             const xmlChar *name,  | 
5530  |  |             const xmlChar *namespaceURI,  | 
5531  |  |             int breakOnOtherElem,  | 
5532  |  |             xmlNodePtr *resultNode)  | 
5533  |  | { | 
5534  |  |     if (name == NULL)  | 
5535  |  |   return(-1);  | 
5536  |  |  | 
5537  |  |     *resultNode = NULL;  | 
5538  |  |     while (cur != NULL) { | 
5539  |  |   if (cur->type == XML_ELEMENT_NODE) { | 
5540  |  |       if ((cur->ns != NULL) && (cur->name != NULL)) { | 
5541  |  |     if ((*(cur->name) == *name) &&  | 
5542  |  |         xmlStrEqual(cur->name, name) &&  | 
5543  |  |         xmlStrEqual(cur->ns->href, namespaceURI))  | 
5544  |  |     { | 
5545  |  |         *resultNode = cur;  | 
5546  |  |         return(1);  | 
5547  |  |     }  | 
5548  |  |       }  | 
5549  |  |       if (breakOnOtherElem)  | 
5550  |  |     break;  | 
5551  |  |   }  | 
5552  |  |   cur = cur->next;  | 
5553  |  |     }  | 
5554  |  |     *resultNode = cur;  | 
5555  |  |     return(0);  | 
5556  |  | }  | 
5557  |  |  | 
5558  |  | static int  | 
5559  |  | xsltParseTopLevelXSLTElem(xsltCompilerCtxtPtr cctxt,  | 
5560  |  |         xmlNodePtr node,  | 
5561  |  |         xsltStyleType type)  | 
5562  |  | { | 
5563  |  |     int ret = 0;  | 
5564  |  |  | 
5565  |  |     /*  | 
5566  |  |     * TODO: The reason why this function exists:  | 
5567  |  |     *  due to historical reasons some of the  | 
5568  |  |     *  top-level declarations are processed by functions  | 
5569  |  |     *  in other files. Since we need still to set  | 
5570  |  |     *  up the node-info and generate information like  | 
5571  |  |     *  in-scope namespaces, this is a wrapper around  | 
5572  |  |     *  those old parsing functions.  | 
5573  |  |     */  | 
5574  |  |     xsltCompilerNodePush(cctxt, node);  | 
5575  |  |     if (node->nsDef != NULL)  | 
5576  |  |   cctxt->inode->inScopeNs =  | 
5577  |  |       xsltCompilerBuildInScopeNsList(cctxt, node);  | 
5578  |  |     cctxt->inode->type = type;  | 
5579  |  |  | 
5580  |  |     switch (type) { | 
5581  |  |   case XSLT_FUNC_INCLUDE:  | 
5582  |  |       { | 
5583  |  |     int oldIsInclude;  | 
5584  |  |  | 
5585  |  |     if (xsltCompileXSLTIncludeElem(cctxt, node) == NULL)  | 
5586  |  |         goto exit;  | 
5587  |  |     /*  | 
5588  |  |     * Mark this stylesheet tree as being currently included.  | 
5589  |  |     */  | 
5590  |  |     oldIsInclude = cctxt->isInclude;  | 
5591  |  |     cctxt->isInclude = 1;  | 
5592  |  |  | 
5593  |  |     if (xsltParseStylesheetInclude(cctxt->style, node) != 0) { | 
5594  |  |         cctxt->style->errors++;  | 
5595  |  |     }  | 
5596  |  |     cctxt->isInclude = oldIsInclude;  | 
5597  |  |       }  | 
5598  |  |       break;  | 
5599  |  |   case XSLT_FUNC_PARAM:  | 
5600  |  |       xsltStylePreCompute(cctxt->style, node);  | 
5601  |  |       xsltParseGlobalParam(cctxt->style, node);  | 
5602  |  |       break;  | 
5603  |  |   case XSLT_FUNC_VARIABLE:  | 
5604  |  |       xsltStylePreCompute(cctxt->style, node);  | 
5605  |  |       xsltParseGlobalVariable(cctxt->style, node);  | 
5606  |  |       break;  | 
5607  |  |   case XSLT_FUNC_ATTRSET:  | 
5608  |  |       xsltParseStylesheetAttributeSet(cctxt->style, node);  | 
5609  |  |       break;  | 
5610  |  |   default:  | 
5611  |  |       xsltTransformError(NULL, cctxt->style, node,  | 
5612  |  |     "Internal error: (xsltParseTopLevelXSLTElem) "  | 
5613  |  |     "Cannot handle this top-level declaration.\n");  | 
5614  |  |       cctxt->style->errors++;  | 
5615  |  |       ret = -1;  | 
5616  |  |     }  | 
5617  |  |  | 
5618  |  | exit:  | 
5619  |  |     xsltCompilerNodePop(cctxt, node);  | 
5620  |  |  | 
5621  |  |     return(ret);  | 
5622  |  | }  | 
5623  |  |  | 
5624  |  | #if 0  | 
5625  |  | static int  | 
5626  |  | xsltParseRemoveWhitespace(xmlNodePtr node)  | 
5627  |  | { | 
5628  |  |     if ((node == NULL) || (node->children == NULL))  | 
5629  |  |   return(0);  | 
5630  |  |     else { | 
5631  |  |   xmlNodePtr delNode = NULL, child = node->children;  | 
5632  |  |  | 
5633  |  |   do { | 
5634  |  |       if (delNode) { | 
5635  |  |     xmlUnlinkNode(delNode);  | 
5636  |  |     xmlFreeNode(delNode);  | 
5637  |  |     delNode = NULL;  | 
5638  |  |       }  | 
5639  |  |       if (((child->type == XML_TEXT_NODE) ||  | 
5640  |  |      (child->type == XML_CDATA_SECTION_NODE)) &&  | 
5641  |  |     (IS_BLANK_NODE(child)))  | 
5642  |  |     delNode = child;  | 
5643  |  |       child = child->next;  | 
5644  |  |   } while (child != NULL);  | 
5645  |  |   if (delNode) { | 
5646  |  |       xmlUnlinkNode(delNode);  | 
5647  |  |       xmlFreeNode(delNode);  | 
5648  |  |       delNode = NULL;  | 
5649  |  |   }  | 
5650  |  |     }  | 
5651  |  |     return(0);  | 
5652  |  | }  | 
5653  |  | #endif  | 
5654  |  |  | 
5655  |  | static int  | 
5656  |  | xsltParseXSLTStylesheetElemCore(xsltCompilerCtxtPtr cctxt, xmlNodePtr node)  | 
5657  |  | { | 
5658  |  | #ifdef WITH_XSLT_DEBUG_PARSING  | 
5659  |  |     int templates = 0;  | 
5660  |  | #endif  | 
5661  |  |     xmlNodePtr cur, start = NULL;  | 
5662  |  |     xsltStylesheetPtr style;  | 
5663  |  |  | 
5664  |  |     if ((cctxt == NULL) || (node == NULL) ||  | 
5665  |  |   (node->type != XML_ELEMENT_NODE))  | 
5666  |  |   return(-1);  | 
5667  |  |  | 
5668  |  |     style = cctxt->style;  | 
5669  |  |     /*  | 
5670  |  |     * At this stage all import declarations of all stylesheet modules  | 
5671  |  |     * with the same stylesheet level have been processed.  | 
5672  |  |     * Now we can safely parse the rest of the declarations.  | 
5673  |  |     */  | 
5674  |  |     if (IS_XSLT_ELEM_FAST(node) && IS_XSLT_NAME(node, "include"))  | 
5675  |  |     { | 
5676  |  |   xsltDocumentPtr include;  | 
5677  |  |   /*  | 
5678  |  |   * URGENT TODO: Make this work with simplified stylesheets!  | 
5679  |  |   *   I.e., when we won't find an xsl:stylesheet element.  | 
5680  |  |   */  | 
5681  |  |   /*  | 
5682  |  |   * This is as include declaration.  | 
5683  |  |   */  | 
5684  |  |   include = ((xsltStyleItemIncludePtr) node->psvi)->include;  | 
5685  |  |   if (include == NULL) { | 
5686  |  |       /* TODO: raise error? */  | 
5687  |  |       return(-1);  | 
5688  |  |   }  | 
5689  |  |   /*  | 
5690  |  |   * TODO: Actually an xsl:include should locate an embedded  | 
5691  |  |   *  stylesheet as well; so the document-element won't always  | 
5692  |  |   *  be the element where the actual stylesheet is rooted at.  | 
5693  |  |   *  But such embedded stylesheets are not supported by Libxslt yet.  | 
5694  |  |   */  | 
5695  |  |   node = xmlDocGetRootElement(include->doc);  | 
5696  |  |   if (node == NULL) { | 
5697  |  |       return(-1);  | 
5698  |  |   }  | 
5699  |  |     }  | 
5700  |  |  | 
5701  |  |     if (node->children == NULL)  | 
5702  |  |   return(0);  | 
5703  |  |     /*  | 
5704  |  |     * Push the xsl:stylesheet/xsl:transform element.  | 
5705  |  |     */  | 
5706  |  |     xsltCompilerNodePush(cctxt, node);  | 
5707  |  |     cctxt->inode->isRoot = 1;  | 
5708  |  |     cctxt->inode->nsChanged = 0;  | 
5709  |  |     /*  | 
5710  |  |     * Start with the naked dummy info for literal result elements.  | 
5711  |  |     */  | 
5712  |  |     cctxt->inode->litResElemInfo = cctxt->inodeList->litResElemInfo;  | 
5713  |  |  | 
5714  |  |     /*  | 
5715  |  |     * In every case, we need to have  | 
5716  |  |     * the in-scope namespaces of the element, where the  | 
5717  |  |     * stylesheet is rooted at, regardless if it's an XSLT  | 
5718  |  |     * instruction or a literal result instruction (or if  | 
5719  |  |     * this is an embedded stylesheet).  | 
5720  |  |     */  | 
5721  |  |     cctxt->inode->inScopeNs =  | 
5722  |  |   xsltCompilerBuildInScopeNsList(cctxt, node);  | 
5723  |  |  | 
5724  |  |     /*  | 
5725  |  |     * Process attributes of xsl:stylesheet/xsl:transform.  | 
5726  |  |     * --------------------------------------------------  | 
5727  |  |     * Allowed are:  | 
5728  |  |     *  id = id  | 
5729  |  |     *  extension-element-prefixes = tokens  | 
5730  |  |     *  exclude-result-prefixes = tokens  | 
5731  |  |     *  version = number (mandatory)  | 
5732  |  |     */  | 
5733  |  |     if (xsltParseAttrXSLTVersion(cctxt, node,  | 
5734  |  |   XSLT_ELEMENT_CATEGORY_XSLT) == 0)  | 
5735  |  |     { | 
5736  |  |   /*  | 
5737  |  |   * Attribute "version".  | 
5738  |  |   * XSLT 1.0: "An xsl:stylesheet element *must* have a version  | 
5739  |  |   *  attribute, indicating the version of XSLT that the  | 
5740  |  |   *  stylesheet requires".  | 
5741  |  |   * The root element of a simplified stylesheet must also have  | 
5742  |  |   * this attribute.  | 
5743  |  |   */  | 
5744  |  | #ifdef XSLT_REFACTORED_MANDATORY_VERSION  | 
5745  |  |   if (isXsltElem)  | 
5746  |  |       xsltTransformError(NULL, cctxt->style, node,  | 
5747  |  |     "The attribute 'version' is missing.\n");  | 
5748  |  |   cctxt->style->errors++;  | 
5749  |  | #else  | 
5750  |  |   /* OLD behaviour. */  | 
5751  |  |   xsltTransformError(NULL, cctxt->style, node,  | 
5752  |  |       "xsl:version is missing: document may not be a stylesheet\n");  | 
5753  |  |   cctxt->style->warnings++;  | 
5754  |  | #endif  | 
5755  |  |     }  | 
5756  |  |     /*  | 
5757  |  |     * The namespaces declared by the attributes  | 
5758  |  |     *  "extension-element-prefixes" and  | 
5759  |  |     *  "exclude-result-prefixes" are local to *this*  | 
5760  |  |     *  stylesheet tree; i.e., they are *not* visible to  | 
5761  |  |     *  other stylesheet-modules, whether imported or included.  | 
5762  |  |     *  | 
5763  |  |     * Attribute "extension-element-prefixes".  | 
5764  |  |     */  | 
5765  |  |     cctxt->inode->extElemNs =  | 
5766  |  |   xsltParseExtElemPrefixes(cctxt, node, NULL,  | 
5767  |  |       XSLT_ELEMENT_CATEGORY_XSLT);  | 
5768  |  |     /*  | 
5769  |  |     * Attribute "exclude-result-prefixes".  | 
5770  |  |     */  | 
5771  |  |     cctxt->inode->exclResultNs =  | 
5772  |  |   xsltParseExclResultPrefixes(cctxt, node, NULL,  | 
5773  |  |       XSLT_ELEMENT_CATEGORY_XSLT);  | 
5774  |  |     /*  | 
5775  |  |     * Create/reuse info for the literal result element.  | 
5776  |  |     */  | 
5777  |  |     if (cctxt->inode->nsChanged)  | 
5778  |  |   xsltLREInfoCreate(cctxt, node, 0);  | 
5779  |  |     /*  | 
5780  |  |     * Processed top-level elements:  | 
5781  |  |     * ----------------------------  | 
5782  |  |     *  xsl:variable, xsl:param (QName, in-scope ns,  | 
5783  |  |     *    expression (vars allowed))  | 
5784  |  |     *  xsl:attribute-set (QName, in-scope ns)  | 
5785  |  |     *  xsl:strip-space, xsl:preserve-space (XPath NameTests,  | 
5786  |  |     *    in-scope ns)  | 
5787  |  |     *    I *think* global scope, merge with includes  | 
5788  |  |     *  xsl:output (QName, in-scope ns)  | 
5789  |  |     *  xsl:key (QName, in-scope ns, pattern,  | 
5790  |  |     *    expression (vars *not* allowed))  | 
5791  |  |     *  xsl:decimal-format (QName, needs in-scope ns)  | 
5792  |  |     *  xsl:namespace-alias (in-scope ns)  | 
5793  |  |     *    global scope, merge with includes  | 
5794  |  |     *  xsl:template (last, QName, pattern)  | 
5795  |  |     *  | 
5796  |  |     * (whitespace-only text-nodes have *not* been removed  | 
5797  |  |     *  yet; this will be done in xsltParseSequenceConstructor)  | 
5798  |  |     *  | 
5799  |  |     * Report misplaced child-nodes first.  | 
5800  |  |     */  | 
5801  |  |     cur = node->children;  | 
5802  |  |     while (cur != NULL) { | 
5803  |  |   if (cur->type == XML_TEXT_NODE) { | 
5804  |  |       xsltTransformError(NULL, style, cur,  | 
5805  |  |     "Misplaced text node (content: '%s').\n",  | 
5806  |  |     (cur->content != NULL) ? cur->content : BAD_CAST "");  | 
5807  |  |       style->errors++;  | 
5808  |  |   } else if (cur->type != XML_ELEMENT_NODE) { | 
5809  |  |       xsltTransformError(NULL, style, cur, "Misplaced node.\n");  | 
5810  |  |       style->errors++;  | 
5811  |  |   }  | 
5812  |  |   cur = cur->next;  | 
5813  |  |     }  | 
5814  |  |     /*  | 
5815  |  |     * Skip xsl:import elements; they have been processed  | 
5816  |  |     * already.  | 
5817  |  |     */  | 
5818  |  |     cur = node->children;  | 
5819  |  |     while ((cur != NULL) && xsltParseFindTopLevelElem(cctxt, cur,  | 
5820  |  |       BAD_CAST "import", XSLT_NAMESPACE, 1, &cur) == 1)  | 
5821  |  |   cur = cur->next;  | 
5822  |  |     if (cur == NULL)  | 
5823  |  |   goto exit;  | 
5824  |  |  | 
5825  |  |     start = cur;  | 
5826  |  |     /*  | 
5827  |  |     * Process all top-level xsl:param elements.  | 
5828  |  |     */  | 
5829  |  |     while ((cur != NULL) &&  | 
5830  |  |   xsltParseFindTopLevelElem(cctxt, cur,  | 
5831  |  |   BAD_CAST "param", XSLT_NAMESPACE, 0, &cur) == 1)  | 
5832  |  |     { | 
5833  |  |   xsltParseTopLevelXSLTElem(cctxt, cur, XSLT_FUNC_PARAM);  | 
5834  |  |   cur = cur->next;  | 
5835  |  |     }  | 
5836  |  |     /*  | 
5837  |  |     * Process all top-level xsl:variable elements.  | 
5838  |  |     */  | 
5839  |  |     cur = start;  | 
5840  |  |     while ((cur != NULL) &&  | 
5841  |  |   xsltParseFindTopLevelElem(cctxt, cur,  | 
5842  |  |   BAD_CAST "variable", XSLT_NAMESPACE, 0, &cur) == 1)  | 
5843  |  |     { | 
5844  |  |   xsltParseTopLevelXSLTElem(cctxt, cur, XSLT_FUNC_VARIABLE);  | 
5845  |  |   cur = cur->next;  | 
5846  |  |     }  | 
5847  |  |     /*  | 
5848  |  |     * Process all the rest of top-level elements.  | 
5849  |  |     */  | 
5850  |  |     cur = start;  | 
5851  |  |     while (cur != NULL) { | 
5852  |  |   /*  | 
5853  |  |   * Process element nodes.  | 
5854  |  |   */  | 
5855  |  |   if (cur->type == XML_ELEMENT_NODE) { | 
5856  |  |       if (cur->ns == NULL) { | 
5857  |  |     xsltTransformError(NULL, style, cur,  | 
5858  |  |         "Unexpected top-level element in no namespace.\n");  | 
5859  |  |     style->errors++;  | 
5860  |  |     cur = cur->next;  | 
5861  |  |     continue;  | 
5862  |  |       }  | 
5863  |  |       /*  | 
5864  |  |       * Process all XSLT elements.  | 
5865  |  |       */  | 
5866  |  |       if (IS_XSLT_ELEM_FAST(cur)) { | 
5867  |  |     /*  | 
5868  |  |     * xsl:import is only allowed at the beginning.  | 
5869  |  |     */  | 
5870  |  |     if (IS_XSLT_NAME(cur, "import")) { | 
5871  |  |         xsltTransformError(NULL, style, cur,  | 
5872  |  |       "Misplaced xsl:import element.\n");  | 
5873  |  |         style->errors++;  | 
5874  |  |         cur = cur->next;  | 
5875  |  |         continue;  | 
5876  |  |     }  | 
5877  |  |     /*  | 
5878  |  |     * TODO: Change the return type of the parsing functions  | 
5879  |  |     *  to int.  | 
5880  |  |     */  | 
5881  |  |     if (IS_XSLT_NAME(cur, "template")) { | 
5882  |  | #ifdef WITH_XSLT_DEBUG_PARSING  | 
5883  |  |         templates++;  | 
5884  |  | #endif  | 
5885  |  |         /*  | 
5886  |  |         * TODO: Is the position of xsl:template in the  | 
5887  |  |         *  tree significant? If not it would be easier to  | 
5888  |  |         *  parse them at a later stage.  | 
5889  |  |         */  | 
5890  |  |         xsltParseXSLTTemplate(cctxt, cur);  | 
5891  |  |     } else if (IS_XSLT_NAME(cur, "variable")) { | 
5892  |  |         /* NOP; done already */  | 
5893  |  |     } else if (IS_XSLT_NAME(cur, "param")) { | 
5894  |  |         /* NOP; done already */  | 
5895  |  |     } else if (IS_XSLT_NAME(cur, "include")) { | 
5896  |  |         if (cur->psvi != NULL)  | 
5897  |  |       xsltParseXSLTStylesheetElemCore(cctxt, cur);  | 
5898  |  |         else { | 
5899  |  |       xsltTransformError(NULL, style, cur,  | 
5900  |  |           "Internal error: "  | 
5901  |  |           "(xsltParseXSLTStylesheetElemCore) "  | 
5902  |  |           "The xsl:include element was not compiled.\n");  | 
5903  |  |       style->errors++;  | 
5904  |  |         }  | 
5905  |  |     } else if (IS_XSLT_NAME(cur, "strip-space")) { | 
5906  |  |         /* No node info needed. */  | 
5907  |  |         xsltParseStylesheetStripSpace(style, cur);  | 
5908  |  |     } else if (IS_XSLT_NAME(cur, "preserve-space")) { | 
5909  |  |         /* No node info needed. */  | 
5910  |  |         xsltParseStylesheetPreserveSpace(style, cur);  | 
5911  |  |     } else if (IS_XSLT_NAME(cur, "output")) { | 
5912  |  |         /* No node-info needed. */  | 
5913  |  |         xsltParseStylesheetOutput(style, cur);  | 
5914  |  |     } else if (IS_XSLT_NAME(cur, "key")) { | 
5915  |  |         /* TODO: node-info needed for expressions ? */  | 
5916  |  |         xsltParseStylesheetKey(style, cur);  | 
5917  |  |     } else if (IS_XSLT_NAME(cur, "decimal-format")) { | 
5918  |  |         /* No node-info needed. */  | 
5919  |  |         xsltParseStylesheetDecimalFormat(style, cur);  | 
5920  |  |     } else if (IS_XSLT_NAME(cur, "attribute-set")) { | 
5921  |  |         xsltParseTopLevelXSLTElem(cctxt, cur,  | 
5922  |  |       XSLT_FUNC_ATTRSET);  | 
5923  |  |     } else if (IS_XSLT_NAME(cur, "namespace-alias")) { | 
5924  |  |         /* NOP; done already */  | 
5925  |  |     } else { | 
5926  |  |         if (cctxt->inode->forwardsCompat) { | 
5927  |  |       /*  | 
5928  |  |       * Forwards-compatible mode:  | 
5929  |  |       *  | 
5930  |  |       * XSLT-1: "if it is a top-level element and  | 
5931  |  |       *  XSLT 1.0 does not allow such elements as top-level  | 
5932  |  |       *  elements, then the element must be ignored along  | 
5933  |  |       *  with its content;"  | 
5934  |  |       */  | 
5935  |  |       /*  | 
5936  |  |       * TODO: I don't think we should generate a warning.  | 
5937  |  |       */  | 
5938  |  |       xsltTransformError(NULL, style, cur,  | 
5939  |  |           "Forwards-compatible mode: Ignoring unknown XSLT "  | 
5940  |  |           "element '%s'.\n", cur->name);  | 
5941  |  |       style->warnings++;  | 
5942  |  |         } else { | 
5943  |  |       xsltTransformError(NULL, style, cur,  | 
5944  |  |           "Unknown XSLT element '%s'.\n", cur->name);  | 
5945  |  |       style->errors++;  | 
5946  |  |         }  | 
5947  |  |     }  | 
5948  |  |       } else { | 
5949  |  |     xsltTopLevelFunction function;  | 
5950  |  |  | 
5951  |  |     /*  | 
5952  |  |     * Process non-XSLT elements, which are in a  | 
5953  |  |     *  non-NULL namespace.  | 
5954  |  |     */  | 
5955  |  |     /*  | 
5956  |  |     * QUESTION: What does xsltExtModuleTopLevelLookup()  | 
5957  |  |     *  do exactly?  | 
5958  |  |     */  | 
5959  |  |     function = xsltExtModuleTopLevelLookup(cur->name,  | 
5960  |  |         cur->ns->href);  | 
5961  |  |     if (function != NULL)  | 
5962  |  |         function(style, cur);  | 
5963  |  | #ifdef WITH_XSLT_DEBUG_PARSING  | 
5964  |  |     xsltGenericDebug(xsltGenericDebugContext,  | 
5965  |  |         "xsltParseXSLTStylesheetElemCore : User-defined "  | 
5966  |  |         "data element '%s'.\n", cur->name);  | 
5967  |  | #endif  | 
5968  |  |       }  | 
5969  |  |   }  | 
5970  |  |   cur = cur->next;  | 
5971  |  |     }  | 
5972  |  |  | 
5973  |  | exit:  | 
5974  |  |  | 
5975  |  | #ifdef WITH_XSLT_DEBUG_PARSING  | 
5976  |  |     xsltGenericDebug(xsltGenericDebugContext,  | 
5977  |  |   "### END of parsing top-level elements of doc '%s'.\n",  | 
5978  |  |   node->doc->URL);  | 
5979  |  |     xsltGenericDebug(xsltGenericDebugContext,  | 
5980  |  |   "### Templates: %d\n", templates);  | 
5981  |  | #ifdef XSLT_REFACTORED  | 
5982  |  |     xsltGenericDebug(xsltGenericDebugContext,  | 
5983  |  |   "### Max inodes: %d\n", cctxt->maxNodeInfos);  | 
5984  |  |     xsltGenericDebug(xsltGenericDebugContext,  | 
5985  |  |   "### Max LREs  : %d\n", cctxt->maxLREs);  | 
5986  |  | #endif /* XSLT_REFACTORED */  | 
5987  |  | #endif /* WITH_XSLT_DEBUG_PARSING */  | 
5988  |  |  | 
5989  |  |     xsltCompilerNodePop(cctxt, node);  | 
5990  |  |     return(0);  | 
5991  |  | }  | 
5992  |  |  | 
5993  |  | /**  | 
5994  |  |  * xsltParseXSLTStylesheet:  | 
5995  |  |  * @cctxt: the compiler context  | 
5996  |  |  * @node: the xsl:stylesheet/xsl:transform element-node  | 
5997  |  |  *  | 
5998  |  |  * Parses the xsl:stylesheet and xsl:transform element.  | 
5999  |  |  *  | 
6000  |  |  * <xsl:stylesheet  | 
6001  |  |  *  id = id  | 
6002  |  |  *  extension-element-prefixes = tokens  | 
6003  |  |  *  exclude-result-prefixes = tokens  | 
6004  |  |  *  version = number>  | 
6005  |  |  *  <!-- Content: (xsl:import*, top-level-elements) -->  | 
6006  |  |  * </xsl:stylesheet>  | 
6007  |  |  *  | 
6008  |  |  * BIG TODO: The xsl:include stuff.  | 
6009  |  |  *  | 
6010  |  |  * Called by xsltParseStylesheetTree()  | 
6011  |  |  *  | 
6012  |  |  * Returns 0 on success, a positive result on errors and  | 
6013  |  |  *         -1 on API or internal errors.  | 
6014  |  |  */  | 
6015  |  | static int  | 
6016  |  | xsltParseXSLTStylesheetElem(xsltCompilerCtxtPtr cctxt, xmlNodePtr node)  | 
6017  |  | { | 
6018  |  |     xmlNodePtr cur, start;  | 
6019  |  |  | 
6020  |  |     if ((cctxt == NULL) || (node == NULL) || (node->type != XML_ELEMENT_NODE))  | 
6021  |  |   return(-1);  | 
6022  |  |  | 
6023  |  |     if (node->children == NULL)  | 
6024  |  |   goto exit;  | 
6025  |  |  | 
6026  |  |     /*  | 
6027  |  |     * Process top-level elements:  | 
6028  |  |     *  xsl:import (must be first)  | 
6029  |  |     *  xsl:include (this is just a pre-processing)  | 
6030  |  |     */  | 
6031  |  |     cur = node->children;  | 
6032  |  |     /*  | 
6033  |  |     * Process xsl:import elements.  | 
6034  |  |     * XSLT 1.0: "The xsl:import element children must precede all  | 
6035  |  |     *  other element children of an xsl:stylesheet element,  | 
6036  |  |     *  including any xsl:include element children."  | 
6037  |  |     */  | 
6038  |  |     while ((cur != NULL) &&  | 
6039  |  |   xsltParseFindTopLevelElem(cctxt, cur,  | 
6040  |  |       BAD_CAST "import", XSLT_NAMESPACE, 1, &cur) == 1)  | 
6041  |  |     { | 
6042  |  |   if (xsltParseStylesheetImport(cctxt->style, cur) != 0) { | 
6043  |  |       cctxt->style->errors++;  | 
6044  |  |   }  | 
6045  |  |   cur = cur->next;  | 
6046  |  |     }  | 
6047  |  |     if (cur == NULL)  | 
6048  |  |   goto exit;  | 
6049  |  |     start = cur;  | 
6050  |  |     /*  | 
6051  |  |     * Pre-process all xsl:include elements.  | 
6052  |  |     */  | 
6053  |  |     cur = start;  | 
6054  |  |     while ((cur != NULL) &&  | 
6055  |  |   xsltParseFindTopLevelElem(cctxt, cur,  | 
6056  |  |       BAD_CAST "include", XSLT_NAMESPACE, 0, &cur) == 1)  | 
6057  |  |     { | 
6058  |  |   xsltParseTopLevelXSLTElem(cctxt, cur, XSLT_FUNC_INCLUDE);  | 
6059  |  |   cur = cur->next;  | 
6060  |  |     }  | 
6061  |  |     /*  | 
6062  |  |     * Pre-process all xsl:namespace-alias elements.  | 
6063  |  |     * URGENT TODO: This won't work correctly: the order of included  | 
6064  |  |     *  aliases and aliases defined here is significant.  | 
6065  |  |     */  | 
6066  |  |     cur = start;  | 
6067  |  |     while ((cur != NULL) &&  | 
6068  |  |   xsltParseFindTopLevelElem(cctxt, cur,  | 
6069  |  |       BAD_CAST "namespace-alias", XSLT_NAMESPACE, 0, &cur) == 1)  | 
6070  |  |     { | 
6071  |  |   xsltNamespaceAlias(cctxt->style, cur);  | 
6072  |  |   cur = cur->next;  | 
6073  |  |     }  | 
6074  |  |  | 
6075  |  |     if (cctxt->isInclude) { | 
6076  |  |   /*  | 
6077  |  |   * If this stylesheet is intended for inclusion, then  | 
6078  |  |   * we will process only imports and includes.  | 
6079  |  |   */  | 
6080  |  |   goto exit;  | 
6081  |  |     }  | 
6082  |  |     /*  | 
6083  |  |     * Now parse the rest of the top-level elements.  | 
6084  |  |     */  | 
6085  |  |     xsltParseXSLTStylesheetElemCore(cctxt, node);  | 
6086  |  | exit:  | 
6087  |  |  | 
6088  |  |     return(0);  | 
6089  |  | }  | 
6090  |  |  | 
6091  |  | #else /* XSLT_REFACTORED */  | 
6092  |  |  | 
6093  |  | /**  | 
6094  |  |  * xsltParseStylesheetTop:  | 
6095  |  |  * @style:  the XSLT stylesheet  | 
6096  |  |  * @top:  the top level "stylesheet" or "transform" element  | 
6097  |  |  *  | 
6098  |  |  * scan the top level elements of an XSL stylesheet  | 
6099  |  |  */  | 
6100  |  | static void  | 
6101  | 0  | xsltParseStylesheetTop(xsltStylesheetPtr style, xmlNodePtr top) { | 
6102  | 0  |     xmlNodePtr cur;  | 
6103  | 0  |     xmlChar *prop;  | 
6104  |  | #ifdef WITH_XSLT_DEBUG_PARSING  | 
6105  |  |     int templates = 0;  | 
6106  |  | #endif  | 
6107  |  | 
  | 
6108  | 0  |     if ((top == NULL) || (top->type != XML_ELEMENT_NODE))  | 
6109  | 0  |   return;  | 
6110  |  |  | 
6111  | 0  |     prop = xmlGetNsProp(top, (const xmlChar *)"version", NULL);  | 
6112  | 0  |     if (prop == NULL) { | 
6113  | 0  |   xsltTransformError(NULL, style, top,  | 
6114  | 0  |       "xsl:version is missing: document may not be a stylesheet\n");  | 
6115  | 0  |   if (style != NULL) style->warnings++;  | 
6116  | 0  |     } else { | 
6117  | 0  |   if ((!xmlStrEqual(prop, (const xmlChar *)"1.0")) &&  | 
6118  | 0  |             (!xmlStrEqual(prop, (const xmlChar *)"1.1"))) { | 
6119  | 0  |       xsltTransformError(NULL, style, top,  | 
6120  | 0  |     "xsl:version: only 1.1 features are supported\n");  | 
6121  | 0  |       if (style != NULL) { | 
6122  | 0  |                 style->forwards_compatible = 1;  | 
6123  | 0  |                 style->warnings++;  | 
6124  | 0  |             }  | 
6125  | 0  |   }  | 
6126  | 0  |   xmlFree(prop);  | 
6127  | 0  |     }  | 
6128  |  |  | 
6129  |  |     /*  | 
6130  |  |      * process xsl:import elements  | 
6131  |  |      */  | 
6132  | 0  |     cur = top->children;  | 
6133  | 0  |     while (cur != NULL) { | 
6134  | 0  |       if (IS_BLANK_NODE(cur)) { | 
6135  | 0  |         cur = cur->next;  | 
6136  | 0  |         continue;  | 
6137  | 0  |       }  | 
6138  | 0  |       if (IS_XSLT_ELEM(cur) && IS_XSLT_NAME(cur, "import")) { | 
6139  | 0  |         if (xsltParseStylesheetImport(style, cur) != 0)  | 
6140  | 0  |           if (style != NULL) style->errors++;  | 
6141  | 0  |       } else  | 
6142  | 0  |         break;  | 
6143  | 0  |       cur = cur->next;  | 
6144  | 0  |     }  | 
6145  |  |  | 
6146  |  |     /*  | 
6147  |  |      * process other top-level elements  | 
6148  |  |      */  | 
6149  | 0  |     while (cur != NULL) { | 
6150  | 0  |   if (IS_BLANK_NODE(cur)) { | 
6151  | 0  |       cur = cur->next;  | 
6152  | 0  |       continue;  | 
6153  | 0  |   }  | 
6154  | 0  |   if (cur->type == XML_TEXT_NODE) { | 
6155  | 0  |       if (cur->content != NULL) { | 
6156  | 0  |     xsltTransformError(NULL, style, cur,  | 
6157  | 0  |         "misplaced text node: '%s'\n", cur->content);  | 
6158  | 0  |       }  | 
6159  | 0  |       if (style != NULL) style->errors++;  | 
6160  | 0  |             cur = cur->next;  | 
6161  | 0  |       continue;  | 
6162  | 0  |   }  | 
6163  | 0  |   if ((cur->type == XML_ELEMENT_NODE) && (cur->ns == NULL)) { | 
6164  | 0  |       xsltGenericError(xsltGenericErrorContext,  | 
6165  | 0  |          "Found a top-level element %s with null namespace URI\n",  | 
6166  | 0  |          cur->name);  | 
6167  | 0  |       if (style != NULL) style->errors++;  | 
6168  | 0  |       cur = cur->next;  | 
6169  | 0  |       continue;  | 
6170  | 0  |   }  | 
6171  | 0  |   if ((cur->type == XML_ELEMENT_NODE) && (!(IS_XSLT_ELEM(cur)))) { | 
6172  | 0  |       xsltTopLevelFunction function;  | 
6173  |  | 
  | 
6174  | 0  |       function = xsltExtModuleTopLevelLookup(cur->name,  | 
6175  | 0  |                cur->ns->href);  | 
6176  | 0  |       if (function != NULL)  | 
6177  | 0  |     function(style, cur);  | 
6178  |  | 
  | 
6179  |  | #ifdef WITH_XSLT_DEBUG_PARSING  | 
6180  |  |       xsltGenericDebug(xsltGenericDebugContext,  | 
6181  |  |         "xsltParseStylesheetTop : found foreign element %s\n",  | 
6182  |  |         cur->name);  | 
6183  |  | #endif  | 
6184  | 0  |             cur = cur->next;  | 
6185  | 0  |       continue;  | 
6186  | 0  |   }  | 
6187  | 0  |   if (IS_XSLT_NAME(cur, "import")) { | 
6188  | 0  |       xsltTransformError(NULL, style, cur,  | 
6189  | 0  |       "xsltParseStylesheetTop: ignoring misplaced import element\n");  | 
6190  | 0  |       if (style != NULL) style->errors++;  | 
6191  | 0  |         } else if (IS_XSLT_NAME(cur, "include")) { | 
6192  | 0  |       if (xsltParseStylesheetInclude(style, cur) != 0)  | 
6193  | 0  |     if (style != NULL) style->errors++;  | 
6194  | 0  |         } else if (IS_XSLT_NAME(cur, "strip-space")) { | 
6195  | 0  |       xsltParseStylesheetStripSpace(style, cur);  | 
6196  | 0  |         } else if (IS_XSLT_NAME(cur, "preserve-space")) { | 
6197  | 0  |       xsltParseStylesheetPreserveSpace(style, cur);  | 
6198  | 0  |         } else if (IS_XSLT_NAME(cur, "output")) { | 
6199  | 0  |       xsltParseStylesheetOutput(style, cur);  | 
6200  | 0  |         } else if (IS_XSLT_NAME(cur, "key")) { | 
6201  | 0  |       xsltParseStylesheetKey(style, cur);  | 
6202  | 0  |         } else if (IS_XSLT_NAME(cur, "decimal-format")) { | 
6203  | 0  |       xsltParseStylesheetDecimalFormat(style, cur);  | 
6204  | 0  |         } else if (IS_XSLT_NAME(cur, "attribute-set")) { | 
6205  | 0  |       xsltParseStylesheetAttributeSet(style, cur);  | 
6206  | 0  |         } else if (IS_XSLT_NAME(cur, "variable")) { | 
6207  | 0  |       xsltParseGlobalVariable(style, cur);  | 
6208  | 0  |         } else if (IS_XSLT_NAME(cur, "param")) { | 
6209  | 0  |       xsltParseGlobalParam(style, cur);  | 
6210  | 0  |         } else if (IS_XSLT_NAME(cur, "template")) { | 
6211  |  | #ifdef WITH_XSLT_DEBUG_PARSING  | 
6212  |  |       templates++;  | 
6213  |  | #endif  | 
6214  | 0  |       xsltParseStylesheetTemplate(style, cur);  | 
6215  | 0  |         } else if (IS_XSLT_NAME(cur, "namespace-alias")) { | 
6216  | 0  |       xsltNamespaceAlias(style, cur);  | 
6217  | 0  |   } else { | 
6218  | 0  |             if ((style != NULL) && (style->forwards_compatible == 0)) { | 
6219  | 0  |           xsltTransformError(NULL, style, cur,  | 
6220  | 0  |       "xsltParseStylesheetTop: unknown %s element\n",  | 
6221  | 0  |       cur->name);  | 
6222  | 0  |           if (style != NULL) style->errors++;  | 
6223  | 0  |       }  | 
6224  | 0  |   }  | 
6225  | 0  |   cur = cur->next;  | 
6226  | 0  |     }  | 
6227  |  | #ifdef WITH_XSLT_DEBUG_PARSING  | 
6228  |  |     xsltGenericDebug(xsltGenericDebugContext,  | 
6229  |  |         "parsed %d templates\n", templates);  | 
6230  |  | #endif  | 
6231  | 0  | }  | 
6232  |  |  | 
6233  |  | #endif /* else of XSLT_REFACTORED */  | 
6234  |  |  | 
6235  |  | #ifdef XSLT_REFACTORED  | 
6236  |  | /**  | 
6237  |  |  * xsltParseSimplifiedStylesheetTree:  | 
6238  |  |  *  | 
6239  |  |  * @style: the stylesheet (TODO: Change this to the compiler context)  | 
6240  |  |  * @doc: the document containing the stylesheet.  | 
6241  |  |  * @node: the node where the stylesheet is rooted at  | 
6242  |  |  *  | 
6243  |  |  * Returns 0 in case of success, a positive result if an error occurred  | 
6244  |  |  *         and -1 on API and internal errors.  | 
6245  |  |  */  | 
6246  |  | static int  | 
6247  |  | xsltParseSimplifiedStylesheetTree(xsltCompilerCtxtPtr cctxt,  | 
6248  |  |           xmlDocPtr doc,  | 
6249  |  |           xmlNodePtr node)  | 
6250  |  | { | 
6251  |  |     xsltTemplatePtr templ;  | 
6252  |  |  | 
6253  |  |     if ((cctxt == NULL) || (node == NULL))  | 
6254  |  |   return(-1);  | 
6255  |  |  | 
6256  |  |     if (xsltParseAttrXSLTVersion(cctxt, node, 0) == XSLT_ELEMENT_CATEGORY_LRE)  | 
6257  |  |     { | 
6258  |  |   /*  | 
6259  |  |   * TODO: Adjust report, since this might be an  | 
6260  |  |   * embedded stylesheet.  | 
6261  |  |   */  | 
6262  |  |   xsltTransformError(NULL, cctxt->style, node,  | 
6263  |  |       "The attribute 'xsl:version' is missing; cannot identify "  | 
6264  |  |       "this document as an XSLT stylesheet document.\n");  | 
6265  |  |   cctxt->style->errors++;  | 
6266  |  |   return(1);  | 
6267  |  |     }  | 
6268  |  |  | 
6269  |  | #ifdef WITH_XSLT_DEBUG_PARSING  | 
6270  |  |     xsltGenericDebug(xsltGenericDebugContext,  | 
6271  |  |   "xsltParseSimplifiedStylesheetTree: document is stylesheet\n");  | 
6272  |  | #endif  | 
6273  |  |  | 
6274  |  |     /*  | 
6275  |  |     * Create and link the template  | 
6276  |  |     */  | 
6277  |  |     templ = xsltNewTemplate();  | 
6278  |  |     if (templ == NULL) { | 
6279  |  |   return(-1);  | 
6280  |  |     }  | 
6281  |  |     templ->next = cctxt->style->templates;  | 
6282  |  |     cctxt->style->templates = templ;  | 
6283  |  |     templ->match = xmlStrdup(BAD_CAST "/");  | 
6284  |  |  | 
6285  |  |     /*  | 
6286  |  |     * Note that we push the document-node in this special case.  | 
6287  |  |     */  | 
6288  |  |     xsltCompilerNodePush(cctxt, (xmlNodePtr) doc);  | 
6289  |  |     /*  | 
6290  |  |     * In every case, we need to have  | 
6291  |  |     * the in-scope namespaces of the element, where the  | 
6292  |  |     * stylesheet is rooted at, regardless if it's an XSLT  | 
6293  |  |     * instruction or a literal result instruction (or if  | 
6294  |  |     * this is an embedded stylesheet).  | 
6295  |  |     */  | 
6296  |  |     cctxt->inode->inScopeNs =  | 
6297  |  |   xsltCompilerBuildInScopeNsList(cctxt, node);  | 
6298  |  |     /*  | 
6299  |  |     * Parse the content and register the match-pattern.  | 
6300  |  |     */  | 
6301  |  |     xsltParseSequenceConstructor(cctxt, node);  | 
6302  |  |     xsltCompilerNodePop(cctxt, (xmlNodePtr) doc);  | 
6303  |  |  | 
6304  |  |     templ->elem = (xmlNodePtr) doc;  | 
6305  |  |     templ->content = node;  | 
6306  |  |     xsltAddTemplate(cctxt->style, templ, NULL, NULL);  | 
6307  |  |     cctxt->style->literal_result = 1;  | 
6308  |  |     return(0);  | 
6309  |  | }  | 
6310  |  |  | 
6311  |  | #ifdef XSLT_REFACTORED_XSLT_NSCOMP  | 
6312  |  | /**  | 
6313  |  |  * xsltRestoreDocumentNamespaces:  | 
6314  |  |  * @ns: map of namespaces  | 
6315  |  |  * @doc: the document  | 
6316  |  |  *  | 
6317  |  |  * Restore the namespaces for the document  | 
6318  |  |  *  | 
6319  |  |  * Returns 0 in case of success, -1 in case of failure  | 
6320  |  |  */  | 
6321  |  | int  | 
6322  |  | xsltRestoreDocumentNamespaces(xsltNsMapPtr ns, xmlDocPtr doc)  | 
6323  |  | { | 
6324  |  |     if (doc == NULL)  | 
6325  |  |   return(-1);  | 
6326  |  |     /*  | 
6327  |  |     * Revert the changes we have applied to the namespace-URIs of  | 
6328  |  |     * ns-decls.  | 
6329  |  |     */  | 
6330  |  |     while (ns != NULL) { | 
6331  |  |   if ((ns->doc == doc) && (ns->ns != NULL)) { | 
6332  |  |       ns->ns->href = ns->origNsName;  | 
6333  |  |       ns->origNsName = NULL;  | 
6334  |  |       ns->ns = NULL;  | 
6335  |  |   }  | 
6336  |  |   ns = ns->next;  | 
6337  |  |     }  | 
6338  |  |     return(0);  | 
6339  |  | }  | 
6340  |  | #endif /* XSLT_REFACTORED_XSLT_NSCOMP */  | 
6341  |  |  | 
6342  |  | /**  | 
6343  |  |  * xsltParseStylesheetProcess:  | 
6344  |  |  * @style:  the XSLT stylesheet (the current stylesheet-level)  | 
6345  |  |  * @doc:  and xmlDoc parsed XML  | 
6346  |  |  *  | 
6347  |  |  * Parses an XSLT stylesheet, adding the associated structures.  | 
6348  |  |  * Called by:  | 
6349  |  |  *  xsltParseStylesheetImportedDoc() (xslt.c)  | 
6350  |  |  *  xsltParseStylesheetInclude() (imports.c)  | 
6351  |  |  *  | 
6352  |  |  * Returns the value of the @style parameter if everything  | 
6353  |  |  * went right, NULL if something went amiss.  | 
6354  |  |  */  | 
6355  |  | xsltStylesheetPtr  | 
6356  |  | xsltParseStylesheetProcess(xsltStylesheetPtr style, xmlDocPtr doc)  | 
6357  |  | { | 
6358  |  |     xsltCompilerCtxtPtr cctxt;  | 
6359  |  |     xmlNodePtr cur;  | 
6360  |  |     int oldIsSimplifiedStylesheet;  | 
6361  |  |  | 
6362  |  |     xsltInitGlobals();  | 
6363  |  |  | 
6364  |  |     if ((style == NULL) || (doc == NULL))  | 
6365  |  |   return(NULL);  | 
6366  |  |  | 
6367  |  |     cctxt = XSLT_CCTXT(style);  | 
6368  |  |  | 
6369  |  |     cur = xmlDocGetRootElement(doc);  | 
6370  |  |     if (cur == NULL) { | 
6371  |  |   xsltTransformError(NULL, style, (xmlNodePtr) doc,  | 
6372  |  |     "xsltParseStylesheetProcess : empty stylesheet\n");  | 
6373  |  |   return(NULL);  | 
6374  |  |     }  | 
6375  |  |     oldIsSimplifiedStylesheet = cctxt->simplified;  | 
6376  |  |  | 
6377  |  |     if ((IS_XSLT_ELEM(cur)) &&  | 
6378  |  |   ((IS_XSLT_NAME(cur, "stylesheet")) ||  | 
6379  |  |    (IS_XSLT_NAME(cur, "transform")))) { | 
6380  |  | #ifdef WITH_XSLT_DEBUG_PARSING  | 
6381  |  |   xsltGenericDebug(xsltGenericDebugContext,  | 
6382  |  |     "xsltParseStylesheetProcess : found stylesheet\n");  | 
6383  |  | #endif  | 
6384  |  |   cctxt->simplified = 0;  | 
6385  |  |   style->literal_result = 0;  | 
6386  |  |     } else { | 
6387  |  |   cctxt->simplified = 1;  | 
6388  |  |   style->literal_result = 1;  | 
6389  |  |     }  | 
6390  |  |     /*  | 
6391  |  |     * Pre-process the stylesheet if not already done before.  | 
6392  |  |     *  This will remove PIs and comments, merge adjacent  | 
6393  |  |     *  text nodes, internalize strings, etc.  | 
6394  |  |     */  | 
6395  |  |     if (! style->nopreproc)  | 
6396  |  |   xsltParsePreprocessStylesheetTree(cctxt, cur);  | 
6397  |  |     /*  | 
6398  |  |     * Parse and compile the stylesheet.  | 
6399  |  |     */  | 
6400  |  |     if (style->literal_result == 0) { | 
6401  |  |   if (xsltParseXSLTStylesheetElem(cctxt, cur) != 0)  | 
6402  |  |       return(NULL);  | 
6403  |  |     } else { | 
6404  |  |   if (xsltParseSimplifiedStylesheetTree(cctxt, doc, cur) != 0)  | 
6405  |  |       return(NULL);  | 
6406  |  |     }  | 
6407  |  |  | 
6408  |  |     cctxt->simplified = oldIsSimplifiedStylesheet;  | 
6409  |  |  | 
6410  |  |     return(style);  | 
6411  |  | }  | 
6412  |  |  | 
6413  |  | #else /* XSLT_REFACTORED */  | 
6414  |  |  | 
6415  |  | /**  | 
6416  |  |  * xsltParseStylesheetProcess:  | 
6417  |  |  * @ret:  the XSLT stylesheet (the current stylesheet-level)  | 
6418  |  |  * @doc:  and xmlDoc parsed XML  | 
6419  |  |  *  | 
6420  |  |  * Parses an XSLT stylesheet, adding the associated structures.  | 
6421  |  |  * Called by:  | 
6422  |  |  *  xsltParseStylesheetImportedDoc() (xslt.c)  | 
6423  |  |  *  xsltParseStylesheetInclude() (imports.c)  | 
6424  |  |  *  | 
6425  |  |  * Returns the value of the @style parameter if everything  | 
6426  |  |  * went right, NULL if something went amiss.  | 
6427  |  |  */  | 
6428  |  | xsltStylesheetPtr  | 
6429  | 0  | xsltParseStylesheetProcess(xsltStylesheetPtr ret, xmlDocPtr doc) { | 
6430  | 0  |     xmlNodePtr cur;  | 
6431  |  | 
  | 
6432  | 0  |     xsltInitGlobals();  | 
6433  |  | 
  | 
6434  | 0  |     if (doc == NULL)  | 
6435  | 0  |   return(NULL);  | 
6436  | 0  |     if (ret == NULL)  | 
6437  | 0  |   return(ret);  | 
6438  |  |  | 
6439  |  |     /*  | 
6440  |  |      * First steps, remove blank nodes,  | 
6441  |  |      * locate the xsl:stylesheet element and the  | 
6442  |  |      * namespace declaration.  | 
6443  |  |      */  | 
6444  | 0  |     cur = xmlDocGetRootElement(doc);  | 
6445  | 0  |     if (cur == NULL) { | 
6446  | 0  |   xsltTransformError(NULL, ret, (xmlNodePtr) doc,  | 
6447  | 0  |     "xsltParseStylesheetProcess : empty stylesheet\n");  | 
6448  | 0  |   return(NULL);  | 
6449  | 0  |     }  | 
6450  |  |  | 
6451  | 0  |     if ((IS_XSLT_ELEM(cur)) &&  | 
6452  | 0  |   ((IS_XSLT_NAME(cur, "stylesheet")) ||  | 
6453  | 0  |    (IS_XSLT_NAME(cur, "transform")))) { | 
6454  |  | #ifdef WITH_XSLT_DEBUG_PARSING  | 
6455  |  |   xsltGenericDebug(xsltGenericDebugContext,  | 
6456  |  |     "xsltParseStylesheetProcess : found stylesheet\n");  | 
6457  |  | #endif  | 
6458  | 0  |   ret->literal_result = 0;  | 
6459  | 0  |   xsltParseStylesheetExcludePrefix(ret, cur, 1);  | 
6460  | 0  |   xsltParseStylesheetExtPrefix(ret, cur, 1);  | 
6461  | 0  |     } else { | 
6462  | 0  |   xsltParseStylesheetExcludePrefix(ret, cur, 0);  | 
6463  | 0  |   xsltParseStylesheetExtPrefix(ret, cur, 0);  | 
6464  | 0  |   ret->literal_result = 1;  | 
6465  | 0  |     }  | 
6466  | 0  |     if (!ret->nopreproc) { | 
6467  | 0  |   xsltPreprocessStylesheet(ret, cur);  | 
6468  | 0  |     }  | 
6469  | 0  |     if (ret->literal_result == 0) { | 
6470  | 0  |   xsltParseStylesheetTop(ret, cur);  | 
6471  | 0  |     } else { | 
6472  | 0  |   xmlChar *prop;  | 
6473  | 0  |   xsltTemplatePtr template;  | 
6474  |  |  | 
6475  |  |   /*  | 
6476  |  |    * the document itself might be the template, check xsl:version  | 
6477  |  |    */  | 
6478  | 0  |   prop = xmlGetNsProp(cur, (const xmlChar *)"version", XSLT_NAMESPACE);  | 
6479  | 0  |   if (prop == NULL) { | 
6480  | 0  |       xsltTransformError(NULL, ret, cur,  | 
6481  | 0  |     "xsltParseStylesheetProcess : document is not a stylesheet\n");  | 
6482  | 0  |       return(NULL);  | 
6483  | 0  |   }  | 
6484  |  |  | 
6485  |  | #ifdef WITH_XSLT_DEBUG_PARSING  | 
6486  |  |         xsltGenericDebug(xsltGenericDebugContext,  | 
6487  |  |     "xsltParseStylesheetProcess : document is stylesheet\n");  | 
6488  |  | #endif  | 
6489  |  |  | 
6490  | 0  |   if ((!xmlStrEqual(prop, (const xmlChar *)"1.0")) &&  | 
6491  | 0  |             (!xmlStrEqual(prop, (const xmlChar *)"1.1"))) { | 
6492  | 0  |       xsltTransformError(NULL, ret, cur,  | 
6493  | 0  |     "xsl:version: only 1.1 features are supported\n");  | 
6494  | 0  |             ret->forwards_compatible = 1;  | 
6495  | 0  |       ret->warnings++;  | 
6496  | 0  |   }  | 
6497  | 0  |   xmlFree(prop);  | 
6498  |  |  | 
6499  |  |   /*  | 
6500  |  |    * Create and link the template  | 
6501  |  |    */  | 
6502  | 0  |   template = xsltNewTemplate();  | 
6503  | 0  |   if (template == NULL) { | 
6504  | 0  |       return(NULL);  | 
6505  | 0  |   }  | 
6506  | 0  |   template->next = ret->templates;  | 
6507  | 0  |   ret->templates = template;  | 
6508  | 0  |   template->match = xmlStrdup((const xmlChar *)"/");  | 
6509  |  |  | 
6510  |  |   /*  | 
6511  |  |    * parse the content and register the pattern  | 
6512  |  |    */  | 
6513  | 0  |   xsltParseTemplateContent(ret, (xmlNodePtr) doc);  | 
6514  | 0  |   template->elem = (xmlNodePtr) doc;  | 
6515  | 0  |   template->content = doc->children;  | 
6516  | 0  |   xsltAddTemplate(ret, template, NULL, NULL);  | 
6517  | 0  |   ret->literal_result = 1;  | 
6518  | 0  |     }  | 
6519  |  |  | 
6520  | 0  |     return(ret);  | 
6521  | 0  | }  | 
6522  |  |  | 
6523  |  | #endif /* else of XSLT_REFACTORED */  | 
6524  |  |  | 
6525  |  | /**  | 
6526  |  |  * xsltParseStylesheetImportedDoc:  | 
6527  |  |  * @doc:  an xmlDoc parsed XML  | 
6528  |  |  * @parentStyle: pointer to the parent stylesheet (if it exists)  | 
6529  |  |  *  | 
6530  |  |  * parse an XSLT stylesheet building the associated structures  | 
6531  |  |  * except the processing not needed for imported documents.  | 
6532  |  |  *  | 
6533  |  |  * Returns a new XSLT stylesheet structure.  | 
6534  |  |  */  | 
6535  |  |  | 
6536  |  | xsltStylesheetPtr  | 
6537  |  | xsltParseStylesheetImportedDoc(xmlDocPtr doc,  | 
6538  | 0  |              xsltStylesheetPtr parentStyle) { | 
6539  | 0  |     xsltStylesheetPtr retStyle;  | 
6540  |  | 
  | 
6541  | 0  |     if (doc == NULL)  | 
6542  | 0  |   return(NULL);  | 
6543  |  |  | 
6544  | 0  |     retStyle = xsltNewStylesheetInternal(parentStyle);  | 
6545  | 0  |     if (retStyle == NULL)  | 
6546  | 0  |   return(NULL);  | 
6547  |  |  | 
6548  | 0  |     if (xsltParseStylesheetUser(retStyle, doc) != 0) { | 
6549  | 0  |         xsltFreeStylesheet(retStyle);  | 
6550  | 0  |         return(NULL);  | 
6551  | 0  |     }  | 
6552  |  |  | 
6553  | 0  |     return(retStyle);  | 
6554  | 0  | }  | 
6555  |  |  | 
6556  |  | /**  | 
6557  |  |  * xsltParseStylesheetUser:  | 
6558  |  |  * @style: pointer to the stylesheet  | 
6559  |  |  * @doc:  an xmlDoc parsed XML  | 
6560  |  |  *  | 
6561  |  |  * Parse an XSLT stylesheet with a user-provided stylesheet struct.  | 
6562  |  |  *  | 
6563  |  |  * Returns 0 if successful, -1 in case of error.  | 
6564  |  |  */  | 
6565  |  | int  | 
6566  | 0  | xsltParseStylesheetUser(xsltStylesheetPtr style, xmlDocPtr doc) { | 
6567  | 0  |     if ((style == NULL) || (doc == NULL))  | 
6568  | 0  |   return(-1);  | 
6569  |  |  | 
6570  |  |     /*  | 
6571  |  |     * Adjust the string dict.  | 
6572  |  |     */  | 
6573  | 0  |     if (doc->dict != NULL) { | 
6574  | 0  |         xmlDictFree(style->dict);  | 
6575  | 0  |   style->dict = doc->dict;  | 
6576  |  | #ifdef WITH_XSLT_DEBUG  | 
6577  |  |         xsltGenericDebug(xsltGenericDebugContext,  | 
6578  |  |       "reusing dictionary from %s for stylesheet\n",  | 
6579  |  |       doc->URL);  | 
6580  |  | #endif  | 
6581  | 0  |   xmlDictReference(style->dict);  | 
6582  | 0  |     }  | 
6583  |  |  | 
6584  |  |     /*  | 
6585  |  |     * TODO: Eliminate xsltGatherNamespaces(); we must not restrict  | 
6586  |  |     *  the stylesheet to containt distinct namespace prefixes.  | 
6587  |  |     */  | 
6588  | 0  |     xsltGatherNamespaces(style);  | 
6589  |  | 
  | 
6590  |  | #ifdef XSLT_REFACTORED  | 
6591  |  |     { | 
6592  |  |   xsltCompilerCtxtPtr cctxt;  | 
6593  |  |   xsltStylesheetPtr oldCurSheet;  | 
6594  |  |  | 
6595  |  |   if (style->parent == NULL) { | 
6596  |  |       xsltPrincipalStylesheetDataPtr principalData;  | 
6597  |  |       /*  | 
6598  |  |       * Create extra data for the principal stylesheet.  | 
6599  |  |       */  | 
6600  |  |       principalData = xsltNewPrincipalStylesheetData();  | 
6601  |  |       if (principalData == NULL) { | 
6602  |  |     return(-1);  | 
6603  |  |       }  | 
6604  |  |       style->principalData = principalData;  | 
6605  |  |       /*  | 
6606  |  |       * Create the compilation context  | 
6607  |  |       * ------------------------------  | 
6608  |  |       * (only once; for the principal stylesheet).  | 
6609  |  |       * This is currently the only function where the  | 
6610  |  |       * compilation context is created.  | 
6611  |  |       */  | 
6612  |  |       cctxt = xsltCompilationCtxtCreate(style);  | 
6613  |  |       if (cctxt == NULL) { | 
6614  |  |     return(-1);  | 
6615  |  |       }  | 
6616  |  |       style->compCtxt = (void *) cctxt;  | 
6617  |  |       cctxt->style = style;  | 
6618  |  |       cctxt->dict = style->dict;  | 
6619  |  |       cctxt->psData = principalData;  | 
6620  |  |       /*  | 
6621  |  |       * Push initial dummy node info.  | 
6622  |  |       */  | 
6623  |  |       cctxt->depth = -1;  | 
6624  |  |       xsltCompilerNodePush(cctxt, (xmlNodePtr) doc);  | 
6625  |  |   } else { | 
6626  |  |       /*  | 
6627  |  |       * Imported stylesheet.  | 
6628  |  |       */  | 
6629  |  |       cctxt = style->parent->compCtxt;  | 
6630  |  |       style->compCtxt = cctxt;  | 
6631  |  |   }  | 
6632  |  |   /*  | 
6633  |  |   * Save the old and set the current stylesheet structure in the  | 
6634  |  |   * compilation context.  | 
6635  |  |   */  | 
6636  |  |   oldCurSheet = cctxt->style;  | 
6637  |  |   cctxt->style = style;  | 
6638  |  |  | 
6639  |  |   style->doc = doc;  | 
6640  |  |   xsltParseStylesheetProcess(style, doc);  | 
6641  |  |  | 
6642  |  |   cctxt->style = oldCurSheet;  | 
6643  |  |   if (style->parent == NULL) { | 
6644  |  |       /*  | 
6645  |  |       * Pop the initial dummy node info.  | 
6646  |  |       */  | 
6647  |  |       xsltCompilerNodePop(cctxt, (xmlNodePtr) doc);  | 
6648  |  |   } else { | 
6649  |  |       /*  | 
6650  |  |       * Clear the compilation context of imported  | 
6651  |  |       * stylesheets.  | 
6652  |  |       * TODO: really?  | 
6653  |  |       */  | 
6654  |  |       /* style->compCtxt = NULL; */  | 
6655  |  |   }  | 
6656  |  |  | 
6657  |  | #ifdef XSLT_REFACTORED_XSLT_NSCOMP  | 
6658  |  |         if (style->errors != 0) { | 
6659  |  |             /*  | 
6660  |  |             * Restore all changes made to namespace URIs of ns-decls.  | 
6661  |  |             */  | 
6662  |  |             if (cctxt->psData->nsMap)  | 
6663  |  |                 xsltRestoreDocumentNamespaces(cctxt->psData->nsMap, doc);  | 
6664  |  |         }  | 
6665  |  | #endif  | 
6666  |  |  | 
6667  |  |         if (style->parent == NULL) { | 
6668  |  |             xsltCompilationCtxtFree(style->compCtxt);  | 
6669  |  |             style->compCtxt = NULL;  | 
6670  |  |         }  | 
6671  |  |     }  | 
6672  |  |  | 
6673  |  | #else /* XSLT_REFACTORED */  | 
6674  |  |     /*  | 
6675  |  |     * Old behaviour.  | 
6676  |  |     */  | 
6677  | 0  |     style->doc = doc;  | 
6678  | 0  |     if (xsltParseStylesheetProcess(style, doc) == NULL) { | 
6679  | 0  |         style->doc = NULL;  | 
6680  | 0  |         return(-1);  | 
6681  | 0  |     }  | 
6682  | 0  | #endif /* else of XSLT_REFACTORED */  | 
6683  |  |  | 
6684  | 0  |     if (style->parent == NULL)  | 
6685  | 0  |         xsltResolveStylesheetAttributeSet(style);  | 
6686  |  | 
  | 
6687  | 0  |     if (style->errors != 0) { | 
6688  |  |         /*  | 
6689  |  |         * Detach the doc from the stylesheet; otherwise the doc  | 
6690  |  |         * will be freed in xsltFreeStylesheet().  | 
6691  |  |         */  | 
6692  | 0  |         style->doc = NULL;  | 
6693  |  |         /*  | 
6694  |  |         * Cleanup the doc if its the main stylesheet.  | 
6695  |  |         */  | 
6696  | 0  |         if (style->parent == NULL)  | 
6697  | 0  |             xsltCleanupStylesheetTree(doc, xmlDocGetRootElement(doc));  | 
6698  | 0  |         return(-1);  | 
6699  | 0  |     }  | 
6700  |  |  | 
6701  | 0  |     return(0);  | 
6702  | 0  | }  | 
6703  |  |  | 
6704  |  | /**  | 
6705  |  |  * xsltParseStylesheetDoc:  | 
6706  |  |  * @doc:  an xmlDoc parsed XML  | 
6707  |  |  *  | 
6708  |  |  * parse an XSLT stylesheet, building the associated structures.  doc  | 
6709  |  |  * is kept as a reference within the returned stylesheet, so changes  | 
6710  |  |  * to doc after the parsing will be reflected when the stylesheet  | 
6711  |  |  * is applied, and the doc is automatically freed when the  | 
6712  |  |  * stylesheet is closed.  | 
6713  |  |  *  | 
6714  |  |  * Returns a new XSLT stylesheet structure.  | 
6715  |  |  */  | 
6716  |  |  | 
6717  |  | xsltStylesheetPtr  | 
6718  | 0  | xsltParseStylesheetDoc(xmlDocPtr doc) { | 
6719  | 0  |     xsltInitGlobals();  | 
6720  |  | 
  | 
6721  | 0  |     return(xsltParseStylesheetImportedDoc(doc, NULL));  | 
6722  | 0  | }  | 
6723  |  |  | 
6724  |  | /**  | 
6725  |  |  * xsltParseStylesheetFile:  | 
6726  |  |  * @filename:  the filename/URL to the stylesheet  | 
6727  |  |  *  | 
6728  |  |  * Load and parse an XSLT stylesheet  | 
6729  |  |  *  | 
6730  |  |  * Returns a new XSLT stylesheet structure.  | 
6731  |  |  */  | 
6732  |  |  | 
6733  |  | xsltStylesheetPtr  | 
6734  | 0  | xsltParseStylesheetFile(const xmlChar* filename) { | 
6735  | 0  |     xsltSecurityPrefsPtr sec;  | 
6736  | 0  |     xsltStylesheetPtr ret;  | 
6737  | 0  |     xmlDocPtr doc;  | 
6738  |  | 
  | 
6739  | 0  |     xsltInitGlobals();  | 
6740  |  | 
  | 
6741  | 0  |     if (filename == NULL)  | 
6742  | 0  |   return(NULL);  | 
6743  |  |  | 
6744  |  | #ifdef WITH_XSLT_DEBUG_PARSING  | 
6745  |  |     xsltGenericDebug(xsltGenericDebugContext,  | 
6746  |  |       "xsltParseStylesheetFile : parse %s\n", filename);  | 
6747  |  | #endif  | 
6748  |  |  | 
6749  |  |     /*  | 
6750  |  |      * Security framework check  | 
6751  |  |      */  | 
6752  | 0  |     sec = xsltGetDefaultSecurityPrefs();  | 
6753  | 0  |     if (sec != NULL) { | 
6754  | 0  |   int res;  | 
6755  |  | 
  | 
6756  | 0  |   res = xsltCheckRead(sec, NULL, filename);  | 
6757  | 0  |   if (res <= 0) { | 
6758  | 0  |             if (res == 0)  | 
6759  | 0  |                 xsltTransformError(NULL, NULL, NULL,  | 
6760  | 0  |                      "xsltParseStylesheetFile: read rights for %s denied\n",  | 
6761  | 0  |                                  filename);  | 
6762  | 0  |       return(NULL);  | 
6763  | 0  |   }  | 
6764  | 0  |     }  | 
6765  |  |  | 
6766  | 0  |     doc = xsltDocDefaultLoader(filename, NULL, XSLT_PARSE_OPTIONS,  | 
6767  | 0  |                                NULL, XSLT_LOAD_START);  | 
6768  | 0  |     if (doc == NULL) { | 
6769  | 0  |   xsltTransformError(NULL, NULL, NULL,  | 
6770  | 0  |     "xsltParseStylesheetFile : cannot parse %s\n", filename);  | 
6771  | 0  |   return(NULL);  | 
6772  | 0  |     }  | 
6773  | 0  |     ret = xsltParseStylesheetDoc(doc);  | 
6774  | 0  |     if (ret == NULL) { | 
6775  | 0  |   xmlFreeDoc(doc);  | 
6776  | 0  |   return(NULL);  | 
6777  | 0  |     }  | 
6778  |  |  | 
6779  | 0  |     return(ret);  | 
6780  | 0  | }  | 
6781  |  |  | 
6782  |  | /************************************************************************  | 
6783  |  |  *                  *  | 
6784  |  |  *      Handling of Stylesheet PI     *  | 
6785  |  |  *                  *  | 
6786  |  |  ************************************************************************/  | 
6787  |  |  | 
6788  | 0  | #define CUR (*cur)  | 
6789  | 0  | #define SKIP(val) cur += (val)  | 
6790  | 0  | #define NXT(val) cur[(val)]  | 
6791  |  | #define SKIP_BLANKS           \  | 
6792  | 0  |     while (IS_BLANK(CUR)) NEXT  | 
6793  | 0  | #define NEXT ((*cur) ?  cur++ : cur)  | 
6794  |  |  | 
6795  |  | /**  | 
6796  |  |  * xsltParseStylesheetPI:  | 
6797  |  |  * @value: the value of the PI  | 
6798  |  |  *  | 
6799  |  |  * This function checks that the type is text/xml and extracts  | 
6800  |  |  * the URI-Reference for the stylesheet  | 
6801  |  |  *  | 
6802  |  |  * Returns the URI-Reference for the stylesheet or NULL (it need to  | 
6803  |  |  *         be freed by the caller)  | 
6804  |  |  */  | 
6805  |  | static xmlChar *  | 
6806  | 0  | xsltParseStylesheetPI(const xmlChar *value) { | 
6807  | 0  |     const xmlChar *cur;  | 
6808  | 0  |     const xmlChar *start;  | 
6809  | 0  |     xmlChar *val;  | 
6810  | 0  |     xmlChar tmp;  | 
6811  | 0  |     xmlChar *href = NULL;  | 
6812  | 0  |     int isXml = 0;  | 
6813  |  | 
  | 
6814  | 0  |     if (value == NULL)  | 
6815  | 0  |   return(NULL);  | 
6816  |  |  | 
6817  | 0  |     cur = value;  | 
6818  | 0  |     while (CUR != 0) { | 
6819  | 0  |   SKIP_BLANKS;  | 
6820  | 0  |   if ((CUR == 't') && (NXT(1) == 'y') && (NXT(2) == 'p') &&  | 
6821  | 0  |       (NXT(3) == 'e')) { | 
6822  | 0  |       SKIP(4);  | 
6823  | 0  |       SKIP_BLANKS;  | 
6824  | 0  |       if (CUR != '=')  | 
6825  | 0  |     continue;  | 
6826  | 0  |       NEXT;  | 
6827  | 0  |       if ((CUR != '\'') && (CUR != '"'))  | 
6828  | 0  |     continue;  | 
6829  | 0  |       tmp = CUR;  | 
6830  | 0  |       NEXT;  | 
6831  | 0  |       start = cur;  | 
6832  | 0  |       while ((CUR != 0) && (CUR != tmp))  | 
6833  | 0  |     NEXT;  | 
6834  | 0  |       if (CUR != tmp)  | 
6835  | 0  |     continue;  | 
6836  | 0  |       val = xmlStrndup(start, cur - start);  | 
6837  | 0  |       NEXT;  | 
6838  | 0  |       if (val == NULL)  | 
6839  | 0  |     return(NULL);  | 
6840  | 0  |       if ((xmlStrcasecmp(val, BAD_CAST "text/xml")) &&  | 
6841  | 0  |     (xmlStrcasecmp(val, BAD_CAST "text/xsl")) &&  | 
6842  | 0  |     (xmlStrcasecmp(val, BAD_CAST "application/xslt+xml"))) { | 
6843  | 0  |                 xmlFree(val);  | 
6844  | 0  |     break;  | 
6845  | 0  |       }  | 
6846  | 0  |       isXml = 1;  | 
6847  | 0  |       xmlFree(val);  | 
6848  | 0  |   } else if ((CUR == 'h') && (NXT(1) == 'r') && (NXT(2) == 'e') &&  | 
6849  | 0  |       (NXT(3) == 'f')) { | 
6850  | 0  |       SKIP(4);  | 
6851  | 0  |       SKIP_BLANKS;  | 
6852  | 0  |       if (CUR != '=')  | 
6853  | 0  |     continue;  | 
6854  | 0  |       NEXT;  | 
6855  | 0  |       if ((CUR != '\'') && (CUR != '"'))  | 
6856  | 0  |     continue;  | 
6857  | 0  |       tmp = CUR;  | 
6858  | 0  |       NEXT;  | 
6859  | 0  |       start = cur;  | 
6860  | 0  |       while ((CUR != 0) && (CUR != tmp))  | 
6861  | 0  |     NEXT;  | 
6862  | 0  |       if (CUR != tmp)  | 
6863  | 0  |     continue;  | 
6864  | 0  |       if (href == NULL)  | 
6865  | 0  |     href = xmlStrndup(start, cur - start);  | 
6866  | 0  |       NEXT;  | 
6867  | 0  |   } else { | 
6868  | 0  |       while ((CUR != 0) && (!IS_BLANK(CUR)))  | 
6869  | 0  |     NEXT;  | 
6870  | 0  |   }  | 
6871  |  | 
  | 
6872  | 0  |     }  | 
6873  |  |  | 
6874  | 0  |     if (!isXml) { | 
6875  | 0  |   if (href != NULL)  | 
6876  | 0  |       xmlFree(href);  | 
6877  | 0  |   href = NULL;  | 
6878  | 0  |     }  | 
6879  | 0  |     return(href);  | 
6880  | 0  | }  | 
6881  |  |  | 
6882  |  | /**  | 
6883  |  |  * xsltLoadStylesheetPI:  | 
6884  |  |  * @doc:  a document to process  | 
6885  |  |  *  | 
6886  |  |  * This function tries to locate the stylesheet PI in the given document  | 
6887  |  |  * If found, and if contained within the document, it will extract  | 
6888  |  |  * that subtree to build the stylesheet to process @doc (doc itself will  | 
6889  |  |  * be modified). If found but referencing an external document it will  | 
6890  |  |  * attempt to load it and generate a stylesheet from it. In both cases,  | 
6891  |  |  * the resulting stylesheet and the document need to be freed once the  | 
6892  |  |  * transformation is done.  | 
6893  |  |  *  | 
6894  |  |  * Returns a new XSLT stylesheet structure or NULL if not found.  | 
6895  |  |  */  | 
6896  |  | xsltStylesheetPtr  | 
6897  | 0  | xsltLoadStylesheetPI(xmlDocPtr doc) { | 
6898  | 0  |     xmlNodePtr child;  | 
6899  | 0  |     xsltStylesheetPtr ret = NULL;  | 
6900  | 0  |     xmlChar *href = NULL;  | 
6901  | 0  |     xmlURIPtr URI;  | 
6902  |  | 
  | 
6903  | 0  |     xsltInitGlobals();  | 
6904  |  | 
  | 
6905  | 0  |     if (doc == NULL)  | 
6906  | 0  |   return(NULL);  | 
6907  |  |  | 
6908  |  |     /*  | 
6909  |  |      * Find the text/xml stylesheet PI id any before the root  | 
6910  |  |      */  | 
6911  | 0  |     child = doc->children;  | 
6912  | 0  |     while ((child != NULL) && (child->type != XML_ELEMENT_NODE)) { | 
6913  | 0  |   if ((child->type == XML_PI_NODE) &&  | 
6914  | 0  |       (xmlStrEqual(child->name, BAD_CAST "xml-stylesheet"))) { | 
6915  | 0  |       href = xsltParseStylesheetPI(child->content);  | 
6916  | 0  |       if (href != NULL)  | 
6917  | 0  |     break;  | 
6918  | 0  |   }  | 
6919  | 0  |   child = child->next;  | 
6920  | 0  |     }  | 
6921  |  |  | 
6922  |  |     /*  | 
6923  |  |      * If found check the href to select processing  | 
6924  |  |      */  | 
6925  | 0  |     if (href != NULL) { | 
6926  |  | #ifdef WITH_XSLT_DEBUG_PARSING  | 
6927  |  |   xsltGenericDebug(xsltGenericDebugContext,  | 
6928  |  |     "xsltLoadStylesheetPI : found PI href=%s\n", href);  | 
6929  |  | #endif  | 
6930  | 0  |   URI = xmlParseURI((const char *) href);  | 
6931  | 0  |   if (URI == NULL) { | 
6932  | 0  |       xsltTransformError(NULL, NULL, child,  | 
6933  | 0  |         "xml-stylesheet : href %s is not valid\n", href);  | 
6934  | 0  |       xmlFree(href);  | 
6935  | 0  |       return(NULL);  | 
6936  | 0  |   }  | 
6937  | 0  |   if ((URI->fragment != NULL) && (URI->scheme == NULL) &&  | 
6938  | 0  |             (URI->opaque == NULL) && (URI->authority == NULL) &&  | 
6939  | 0  |             (URI->server == NULL) && (URI->user == NULL) &&  | 
6940  | 0  |             (URI->path == NULL) && (URI->query == NULL)) { | 
6941  | 0  |       xmlAttrPtr ID;  | 
6942  |  | 
  | 
6943  |  | #ifdef WITH_XSLT_DEBUG_PARSING  | 
6944  |  |       xsltGenericDebug(xsltGenericDebugContext,  | 
6945  |  |         "xsltLoadStylesheetPI : Reference to ID %s\n", href);  | 
6946  |  | #endif  | 
6947  | 0  |       if (URI->fragment[0] == '#')  | 
6948  | 0  |     ID = xmlGetID(doc, (const xmlChar *) &(URI->fragment[1]));  | 
6949  | 0  |       else  | 
6950  | 0  |     ID = xmlGetID(doc, (const xmlChar *) URI->fragment);  | 
6951  | 0  |       if (ID == NULL) { | 
6952  | 0  |     xsltTransformError(NULL, NULL, child,  | 
6953  | 0  |         "xml-stylesheet : no ID %s found\n", URI->fragment);  | 
6954  | 0  |       } else { | 
6955  | 0  |     xmlDocPtr fake;  | 
6956  | 0  |     xmlNodePtr subtree, newtree;  | 
6957  | 0  |     xmlNsPtr ns;  | 
6958  |  | 
  | 
6959  |  | #ifdef WITH_XSLT_DEBUG  | 
6960  |  |     xsltGenericDebug(xsltGenericDebugContext,  | 
6961  |  |         "creating new document from %s for embedded stylesheet\n",  | 
6962  |  |         doc->URL);  | 
6963  |  | #endif  | 
6964  |  |     /*  | 
6965  |  |      * move the subtree in a new document passed to  | 
6966  |  |      * the stylesheet analyzer  | 
6967  |  |      */  | 
6968  | 0  |     subtree = ID->parent;  | 
6969  | 0  |     fake = xmlNewDoc(NULL);  | 
6970  | 0  |     if (fake != NULL) { | 
6971  |  |         /*  | 
6972  |  |         * Should the dictionary still be shared even though  | 
6973  |  |         * the nodes are being copied rather than moved?  | 
6974  |  |         */  | 
6975  | 0  |         fake->dict = doc->dict;  | 
6976  | 0  |         xmlDictReference(doc->dict);  | 
6977  |  | #ifdef WITH_XSLT_DEBUG  | 
6978  |  |         xsltGenericDebug(xsltGenericDebugContext,  | 
6979  |  |       "reusing dictionary from %s for embedded stylesheet\n",  | 
6980  |  |       doc->URL);  | 
6981  |  | #endif  | 
6982  |  | 
  | 
6983  | 0  |         newtree = xmlDocCopyNode(subtree, fake, 1);  | 
6984  |  | 
  | 
6985  | 0  |         fake->URL = xmlNodeGetBase(doc, subtree->parent);  | 
6986  |  | #ifdef WITH_XSLT_DEBUG  | 
6987  |  |         xsltGenericDebug(xsltGenericDebugContext,  | 
6988  |  |       "set base URI for embedded stylesheet as %s\n",  | 
6989  |  |       fake->URL);  | 
6990  |  | #endif  | 
6991  |  |  | 
6992  |  |         /*  | 
6993  |  |         * Add all namespaces in scope of embedded stylesheet to  | 
6994  |  |         * root element of newly created stylesheet document  | 
6995  |  |         */  | 
6996  | 0  |         while ((subtree = subtree->parent) != (xmlNodePtr)doc) { | 
6997  | 0  |       for (ns = subtree->ns; ns; ns = ns->next) { | 
6998  | 0  |           xmlNewNs(newtree,  ns->href, ns->prefix);  | 
6999  | 0  |       }  | 
7000  | 0  |         }  | 
7001  |  | 
  | 
7002  | 0  |         xmlAddChild((xmlNodePtr)fake, newtree);  | 
7003  | 0  |         ret = xsltParseStylesheetDoc(fake);  | 
7004  | 0  |         if (ret == NULL)  | 
7005  | 0  |       xmlFreeDoc(fake);  | 
7006  | 0  |     }  | 
7007  | 0  |       }  | 
7008  | 0  |   } else { | 
7009  | 0  |       xmlChar *URL, *base;  | 
7010  |  |  | 
7011  |  |       /*  | 
7012  |  |        * Reference to an external stylesheet  | 
7013  |  |        */  | 
7014  |  | 
  | 
7015  | 0  |       base = xmlNodeGetBase(doc, (xmlNodePtr) doc);  | 
7016  | 0  |       URL = xmlBuildURI(href, base);  | 
7017  | 0  |       if (URL != NULL) { | 
7018  |  | #ifdef WITH_XSLT_DEBUG_PARSING  | 
7019  |  |     xsltGenericDebug(xsltGenericDebugContext,  | 
7020  |  |       "xsltLoadStylesheetPI : fetching %s\n", URL);  | 
7021  |  | #endif  | 
7022  | 0  |     ret = xsltParseStylesheetFile(URL);  | 
7023  | 0  |     xmlFree(URL);  | 
7024  | 0  |       } else { | 
7025  |  | #ifdef WITH_XSLT_DEBUG_PARSING  | 
7026  |  |     xsltGenericDebug(xsltGenericDebugContext,  | 
7027  |  |       "xsltLoadStylesheetPI : fetching %s\n", href);  | 
7028  |  | #endif  | 
7029  | 0  |     ret = xsltParseStylesheetFile(href);  | 
7030  | 0  |       }  | 
7031  | 0  |       if (base != NULL)  | 
7032  | 0  |     xmlFree(base);  | 
7033  | 0  |   }  | 
7034  | 0  |   xmlFreeURI(URI);  | 
7035  | 0  |   xmlFree(href);  | 
7036  | 0  |     }  | 
7037  | 0  |     return(ret);  | 
7038  | 0  | }  |