preparing 1.0.14 updated rebuilt implemented the IN_LIBXSLT and
[platform/upstream/libxslt.git] / libxslt / imports.c
1 /*
2  * imports.c: Implementation of the XSLT imports
3  *
4  * Reference:
5  *   http://www.w3.org/TR/1999/REC-xslt-19991116
6  *
7  * See Copyright for the status of this software.
8  *
9  * daniel@veillard.com
10  */
11
12 #define IN_LIBXSLT
13 #include "libxslt.h"
14
15 #include <string.h>
16
17 #ifdef HAVE_SYS_TYPES_H
18 #include <sys/types.h>
19 #endif
20 #ifdef HAVE_MATH_H
21 #include <math.h>
22 #endif
23 #ifdef HAVE_FLOAT_H
24 #include <float.h>
25 #endif
26 #ifdef HAVE_IEEEFP_H
27 #include <ieeefp.h>
28 #endif
29 #ifdef HAVE_NAN_H
30 #include <nan.h>
31 #endif
32 #ifdef HAVE_CTYPE_H
33 #include <ctype.h>
34 #endif
35
36 #include <libxml/xmlmemory.h>
37 #include <libxml/tree.h>
38 #include <libxml/hash.h>
39 #include <libxml/xmlerror.h>
40 #include <libxml/uri.h>
41 #include "xslt.h"
42 #include "xsltInternals.h"
43 #include "xsltutils.h"
44 #include "imports.h"
45 #include "documents.h"
46
47
48
49 /************************************************************************
50  *                                                                      *
51  *                      Module interfaces                               *
52  *                                                                      *
53  ************************************************************************/
54
55 /**
56  * xsltParseStylesheetImport:
57  * @style:  the XSLT stylesheet
58  * @template:  the "strip-space" element
59  *
60  * parse an XSLT stylesheet strip-space element and record
61  * elements needing stripping
62  */
63
64 void
65 xsltParseStylesheetImport(xsltStylesheetPtr style, xmlNodePtr cur) {
66     xmlDocPtr import = NULL;
67     xmlChar *base = NULL;
68     xmlChar *uriRef = NULL;
69     xmlChar *URI = NULL;
70     xsltStylesheetPtr res;
71
72     if ((cur == NULL) || (style == NULL))
73         return;
74
75     uriRef = xsltGetNsProp(cur, (const xmlChar *)"href", XSLT_NAMESPACE);
76     if (uriRef == NULL) {
77         xsltPrintErrorContext(NULL, style, cur);
78         xsltGenericError(xsltGenericErrorContext,
79             "xsl:import : missing href attribute\n");
80         goto error;
81     }
82
83     base = xmlNodeGetBase(style->doc, cur);
84     URI = xmlBuildURI(uriRef, base);
85     if (URI == NULL) {
86         xsltPrintErrorContext(NULL, style, cur);
87         xsltGenericError(xsltGenericErrorContext,
88             "xsl:import : invalid URI reference %s\n", uriRef);
89         goto error;
90     }
91     import = xmlParseFile((const char *)URI);
92     if (import == NULL) {
93         xsltPrintErrorContext(NULL, style, cur);
94         xsltGenericError(xsltGenericErrorContext,
95             "xsl:import : unable to load %s\n", URI);
96         goto error;
97     }
98
99     res = xsltParseStylesheetDoc(import);
100     if (res != NULL) {
101         res->parent = style;
102         res->next = style->imports;
103         style->imports = res;
104         style->extrasNr += res->extrasNr;
105     }
106
107 error:
108     if (uriRef != NULL)
109         xmlFree(uriRef);
110     if (base != NULL)
111         xmlFree(base);
112     if (URI != NULL)
113         xmlFree(URI);
114 }
115
116 /**
117  * xsltParseStylesheetInclude:
118  * @style:  the XSLT stylesheet
119  * @template:  the "strip-space" element
120  *
121  * parse an XSLT stylesheet strip-space element and record
122  * elements needing stripping
123  */
124
125 void
126 xsltParseStylesheetInclude(xsltStylesheetPtr style, xmlNodePtr cur) {
127     xmlDocPtr oldDoc;
128     xmlChar *base = NULL;
129     xmlChar *uriRef = NULL;
130     xmlChar *URI = NULL;
131     xsltDocumentPtr include;
132
133     if ((cur == NULL) || (style == NULL))
134         return;
135
136     uriRef = xsltGetNsProp(cur, (const xmlChar *)"href", XSLT_NAMESPACE);
137     if (uriRef == NULL) {
138         xsltPrintErrorContext(NULL, style, cur);
139         xsltGenericError(xsltGenericErrorContext,
140             "xsl:include : missing href attribute\n");
141         goto error;
142     }
143
144     base = xmlNodeGetBase(style->doc, cur);
145     URI = xmlBuildURI(uriRef, base);
146     if (URI == NULL) {
147         xsltPrintErrorContext(NULL, style, cur);
148         xsltGenericError(xsltGenericErrorContext,
149             "xsl:include : invalid URI reference %s\n", uriRef);
150         goto error;
151     }
152
153     include = xsltLoadStyleDocument(style, URI);
154     if (include == NULL) {
155         xsltPrintErrorContext(NULL, style, cur);
156         xsltGenericError(xsltGenericErrorContext,
157             "xsl:include : unable to load %s\n", URI);
158         goto error;
159     }
160
161     oldDoc = style->doc;
162     style->doc = include->doc;
163     xsltParseStylesheetProcess(style, include->doc);
164     style->doc = oldDoc;
165
166 error:
167     if (uriRef != NULL)
168         xmlFree(uriRef);
169     if (base != NULL)
170         xmlFree(base);
171     if (URI != NULL)
172         xmlFree(URI);
173 }
174
175 /**
176  * xsltNextImport:
177  * @cur:  the current XSLT stylesheet
178  *
179  * Find the next stylesheet in import precedence.
180  *
181  * Returns the next stylesheet or NULL if it was the last one
182  */
183
184 xsltStylesheetPtr
185 xsltNextImport(xsltStylesheetPtr cur) {
186     if (cur == NULL)
187         return(NULL);
188     if (cur->imports != NULL)
189         return(cur->imports);
190     if (cur->next != NULL)
191         return(cur->next) ;
192     do {
193         cur = cur->parent;
194         if (cur == NULL) return(NULL);
195         if (cur->next != NULL) return(cur->next);
196     } while (cur != NULL);
197     return(cur);
198 }
199
200 /**
201  * xsltNeedElemSpaceHandling:
202  * @ctxt:  an XSLT transformation context
203  *
204  * Returns whether that stylesheet requires white-space stripping
205  *
206  * Returns 1 if space should be stripped, 0 if not
207  */
208
209 int
210 xsltNeedElemSpaceHandling(xsltTransformContextPtr ctxt) {
211     xsltStylesheetPtr style;
212
213     if (ctxt == NULL)
214         return(0);
215     style = ctxt->style;
216     while (style != NULL) {
217         if (style->stripSpaces != NULL)
218             return(1);
219         style = xsltNextImport(style);
220     }
221     return(0);
222 }
223
224 /**
225  * xsltFindElemSpaceHandling:
226  * @ctxt:  an XSLT transformation context
227  * @node:  an XML node
228  *
229  * Find strip-space or preserve-space informations for an element
230  * respect the import precedence or the wildcards
231  *
232  * Returns 1 if space should be stripped, 0 if not, and 2 if everything
233  *         should be CDTATA wrapped.
234  */
235
236 int
237 xsltFindElemSpaceHandling(xsltTransformContextPtr ctxt, xmlNodePtr node) {
238     xsltStylesheetPtr style;
239     const xmlChar *val;
240
241     if ((ctxt == NULL) || (node == NULL))
242         return(0);
243     style = ctxt->style;
244     while (style != NULL) {
245         /* TODO: add namespaces support */
246         val = (const xmlChar *)
247               xmlHashLookup(style->stripSpaces, node->name);
248         if (val != NULL) {
249             if (xmlStrEqual(val, (xmlChar *) "strip"))
250                 return(1);
251             if (xmlStrEqual(val, (xmlChar *) "preserve"))
252                 return(0);
253         } 
254         if (ctxt->style->stripAll == 1)
255             return(1);
256         if (ctxt->style->stripAll == -1)
257             return(0);
258
259         style = xsltNextImport(style);
260     }
261     return(0);
262 }
263
264 /**
265  * xsltFindTemplate:
266  * @ctxt:  an XSLT transformation context
267  * @name: the template name
268  * @nameURI: the template name URI
269  *
270  * Finds the named template, apply import precedence rule.
271  *
272  * Returns the xsltTemplatePtr or NULL if not found
273  */
274 xsltTemplatePtr
275 xsltFindTemplate(xsltTransformContextPtr ctxt, const xmlChar *name,
276                  const xmlChar *nameURI) {
277     xsltTemplatePtr cur;
278     xsltStylesheetPtr style;
279
280     if ((ctxt == NULL) || (name == NULL))
281         return(NULL);
282     style = ctxt->style;
283     while (style != NULL) {
284         cur = style->templates;
285         while (cur != NULL) {
286             if (xmlStrEqual(name, cur->name)) {
287                 if (((nameURI == NULL) && (cur->nameURI == NULL)) ||
288                     ((nameURI != NULL) && (cur->nameURI != NULL) &&
289                      (xmlStrEqual(nameURI, cur->nameURI)))) {
290                     return(cur);
291                 }
292             }
293             cur = cur->next;
294         }
295
296         style = xsltNextImport(style);
297     }
298     return(NULL);
299 }
300