Work on implementing import support:
[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@imag.fr
10  */
11
12 #include "xsltconfig.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
45
46
47 /************************************************************************
48  *                                                                      *
49  *                      Module interfaces                               *
50  *                                                                      *
51  ************************************************************************/
52
53 /**
54  * xsltParseStylesheetImport:
55  * @style:  the XSLT stylesheet
56  * @template:  the "strip-space" element
57  *
58  * parse an XSLT stylesheet strip-space element and record
59  * elements needing stripping
60  */
61
62 void
63 xsltParseStylesheetImport(xsltStylesheetPtr style, xmlNodePtr cur) {
64     xmlDocPtr import = NULL;
65     xmlChar *base = NULL;
66     xmlChar *uriRef = NULL;
67     xmlChar *URI = NULL;
68     xsltStylesheetPtr res;
69
70     if ((cur == NULL) || (style == NULL))
71         return;
72
73     uriRef = xmlGetNsProp(cur, (const xmlChar *)"href", XSLT_NAMESPACE);
74     if (uriRef == NULL) {
75         xsltGenericError(xsltGenericErrorContext,
76             "xsl:import : missing href attribute\n");
77         goto error;
78     }
79
80     base = xmlNodeGetBase(style->doc, cur);
81     URI = xmlBuildURI(uriRef, base);
82     if (URI == NULL) {
83         xsltGenericError(xsltGenericErrorContext,
84             "xsl:import : invalid URI reference %s\n", uriRef);
85         goto error;
86     }
87     import = xmlParseFile((const char *)URI);
88     if (import == NULL) {
89         xsltGenericError(xsltGenericErrorContext,
90             "xsl:import : unable to load %s\n", URI);
91         goto error;
92     }
93
94     res = xsltParseStylesheetDoc(import);
95     if (res != NULL) {
96         res->parent = style;
97         res->next = style->imports;
98         style->imports = res;
99     }
100
101 error:
102     if (import != NULL)
103         xmlFreeDoc(import);
104     if (uriRef != NULL)
105         xmlFree(uriRef);
106     if (base != NULL)
107         xmlFree(base);
108     if (URI != NULL)
109         xmlFree(URI);
110 }
111
112 /**
113  * xsltParseStylesheetInclude:
114  * @style:  the XSLT stylesheet
115  * @template:  the "strip-space" element
116  *
117  * parse an XSLT stylesheet strip-space element and record
118  * elements needing stripping
119  */
120
121 void
122 xsltParseStylesheetInclude(xsltStylesheetPtr style, xmlNodePtr cur) {
123     xmlDocPtr include = NULL, oldDoc;
124     xmlChar *base = NULL;
125     xmlChar *uriRef = NULL;
126     xmlChar *URI = NULL;
127
128     if ((cur == NULL) || (style == NULL))
129         return;
130
131     uriRef = xmlGetNsProp(cur, (const xmlChar *)"href", XSLT_NAMESPACE);
132     if (uriRef == NULL) {
133         xsltGenericError(xsltGenericErrorContext,
134             "xsl:include : missing href attribute\n");
135         goto error;
136     }
137
138     base = xmlNodeGetBase(style->doc, cur);
139     URI = xmlBuildURI(uriRef, base);
140     if (URI == NULL) {
141         xsltGenericError(xsltGenericErrorContext,
142             "xsl:include : invalid URI reference %s\n", uriRef);
143         goto error;
144     }
145     include = xmlParseFile((const char *)URI);
146     if (include == NULL) {
147         xsltGenericError(xsltGenericErrorContext,
148             "xsl:include : unable to load %s\n", URI);
149         goto error;
150     }
151
152     oldDoc = style->doc;
153     style->doc = include;
154     xsltParseStylesheetProcess(style, include);
155     style->doc = oldDoc;
156
157 error:
158     if (include != NULL)
159         xmlFreeDoc(include);
160     if (uriRef != NULL)
161         xmlFree(uriRef);
162     if (base != NULL)
163         xmlFree(base);
164     if (URI != NULL)
165         xmlFree(URI);
166 }
167
168 /**
169  * xsltNextImport:
170  * @cur:  the current XSLT stylesheet
171  *
172  * Find the next stylesheet in import precedence.
173  *
174  * Returns the next stylesheet or NULL if it was the last one
175  */
176
177 xsltStylesheetPtr
178 xsltNextImport(xsltStylesheetPtr cur) {
179     if (cur == NULL)
180         return(NULL);
181     if (cur->imports != NULL)
182         return(cur->imports);
183     if (cur->next != NULL)
184         return(cur->next) ;
185     do {
186         cur = cur->parent;
187         if (cur == NULL) return(NULL);
188         if (cur->next != NULL) return(cur->next);
189     } while (cur != NULL);
190     return(cur);
191 }
192
193 /**
194  * xsltFindElemSpaceHandling:
195  * ctxt:  an XSLT transformation context
196  * node:  an XML node
197  *
198  * Find strip-space or preserve-space informations for an element
199  * respect the import precedence or the wildcards
200  *
201  * Returns 1 if space should be stripped, 0 if not, and 2 if everything
202  *         should be CDTATA wrapped.
203  */
204
205 int
206 xsltFindElemSpaceHandling(xsltTransformContextPtr ctxt, xmlNodePtr node) {
207     xsltStylesheetPtr style;
208     const xmlChar *val;
209
210     if ((ctxt == NULL) || (node == NULL))
211         return(0);
212     style = ctxt->style;
213     while (style != NULL) {
214         /* TODO: add namespaces support */
215         val = (const xmlChar *)
216               xmlHashLookup(style->stripSpaces, node->name);
217         if (val != NULL) {
218             if (xmlStrEqual(val, (xmlChar *) "strip"))
219                 return(1);
220             if (xmlStrEqual(val, (xmlChar *) "preserve"))
221                 return(0);
222         } 
223         val = (const xmlChar *)
224               xmlHashLookup(ctxt->style->stripSpaces,
225                             (const xmlChar *)"*");
226         if ((val != NULL) &&
227             (xmlStrEqual(val, (xmlChar *) "strip")))
228             return(1);
229         if (xmlStrEqual(val, (xmlChar *) "preserve"))
230             return(0);
231
232         style = xsltNextImport(style);
233     }
234     return(0);
235 }
236
237 /**
238  * xsltFindTemplate:
239  * ctxt:  an XSLT transformation context
240  * @name: the template name
241  * @nameURI: the template name URI
242  *
243  * Finds the named template, apply import precedence rule.
244  *
245  * Returns the xsltTemplatePtr or NULL if not found
246  */
247 xsltTemplatePtr
248 xsltFindTemplate(xsltTransformContextPtr ctxt, const xmlChar *name,
249                  const xmlChar *nameURI) {
250     xsltTemplatePtr cur;
251     xsltStylesheetPtr style;
252
253     if ((ctxt == NULL) || (name == NULL))
254         return(NULL);
255     style = ctxt->style;
256     while (style != NULL) {
257         cur = style->templates;
258         while (cur != NULL) {
259             if (xmlStrEqual(name, cur->name)) {
260                 if (((nameURI == NULL) && (cur->nameURI == NULL)) ||
261                     ((nameURI != NULL) && (cur->nameURI != NULL) &&
262                      (xmlStrEqual(nameURI, cur->nameURI)))) {
263                     return(cur);
264                 }
265             }
266             cur = cur->next;
267         }
268
269         style = xsltNextImport(style);
270     }
271     return(NULL);
272 }
273