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