Lots of tests/testing and pattern support should be decent now:
[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 (uriRef != NULL)
103         xmlFree(uriRef);
104     if (base != NULL)
105         xmlFree(base);
106     if (URI != NULL)
107         xmlFree(URI);
108 }
109
110 /**
111  * xsltParseStylesheetInclude:
112  * @style:  the XSLT stylesheet
113  * @template:  the "strip-space" element
114  *
115  * parse an XSLT stylesheet strip-space element and record
116  * elements needing stripping
117  */
118
119 void
120 xsltParseStylesheetInclude(xsltStylesheetPtr style, xmlNodePtr cur) {
121     xmlDocPtr include = NULL, oldDoc;
122     xmlChar *base = NULL;
123     xmlChar *uriRef = NULL;
124     xmlChar *URI = NULL;
125
126     if ((cur == NULL) || (style == NULL))
127         return;
128
129     uriRef = xmlGetNsProp(cur, (const xmlChar *)"href", XSLT_NAMESPACE);
130     if (uriRef == NULL) {
131         xsltGenericError(xsltGenericErrorContext,
132             "xsl:include : missing href attribute\n");
133         goto error;
134     }
135
136     base = xmlNodeGetBase(style->doc, cur);
137     URI = xmlBuildURI(uriRef, base);
138     if (URI == NULL) {
139         xsltGenericError(xsltGenericErrorContext,
140             "xsl:include : invalid URI reference %s\n", uriRef);
141         goto error;
142     }
143     include = xmlParseFile((const char *)URI);
144     if (include == NULL) {
145         xsltGenericError(xsltGenericErrorContext,
146             "xsl:include : unable to load %s\n", URI);
147         goto error;
148     }
149
150     oldDoc = style->doc;
151     style->doc = include;
152     xsltParseStylesheetProcess(style, include);
153     style->doc = oldDoc;
154
155 error:
156     if (uriRef != NULL)
157         xmlFree(uriRef);
158     if (base != NULL)
159         xmlFree(base);
160     if (URI != NULL)
161         xmlFree(URI);
162 }
163
164 /**
165  * xsltNextImport:
166  * @cur:  the current XSLT stylesheet
167  *
168  * Find the next stylesheet in import precedence.
169  *
170  * Returns the next stylesheet or NULL if it was the last one
171  */
172
173 xsltStylesheetPtr
174 xsltNextImport(xsltStylesheetPtr cur) {
175     if (cur == NULL)
176         return(NULL);
177     if (cur->imports != NULL)
178         return(cur->imports);
179     if (cur->next != NULL)
180         return(cur->next) ;
181     do {
182         cur = cur->parent;
183         if (cur == NULL) return(NULL);
184         if (cur->next != NULL) return(cur->next);
185     } while (cur != NULL);
186     return(cur);
187 }
188
189 /**
190  * xsltFindElemSpaceHandling:
191  * ctxt:  an XSLT transformation context
192  * node:  an XML node
193  *
194  * Find strip-space or preserve-space informations for an element
195  * respect the import precedence or the wildcards
196  *
197  * Returns 1 if space should be stripped, 0 if not, and 2 if everything
198  *         should be CDTATA wrapped.
199  */
200
201 int
202 xsltFindElemSpaceHandling(xsltTransformContextPtr ctxt, xmlNodePtr node) {
203     xsltStylesheetPtr style;
204     const xmlChar *val;
205
206     if ((ctxt == NULL) || (node == NULL))
207         return(0);
208     style = ctxt->style;
209     while (style != NULL) {
210         /* TODO: add namespaces support */
211         val = (const xmlChar *)
212               xmlHashLookup(style->stripSpaces, node->name);
213         if (val != NULL) {
214             if (xmlStrEqual(val, (xmlChar *) "strip"))
215                 return(1);
216             if (xmlStrEqual(val, (xmlChar *) "preserve"))
217                 return(0);
218         } 
219         val = (const xmlChar *)
220               xmlHashLookup(ctxt->style->stripSpaces,
221                             (const xmlChar *)"*");
222         if ((val != NULL) &&
223             (xmlStrEqual(val, (xmlChar *) "strip")))
224             return(1);
225         if (xmlStrEqual(val, (xmlChar *) "preserve"))
226             return(0);
227
228         style = xsltNextImport(style);
229     }
230     return(0);
231 }
232
233 /**
234  * xsltFindTemplate:
235  * ctxt:  an XSLT transformation context
236  * @name: the template name
237  * @nameURI: the template name URI
238  *
239  * Finds the named template, apply import precedence rule.
240  *
241  * Returns the xsltTemplatePtr or NULL if not found
242  */
243 xsltTemplatePtr
244 xsltFindTemplate(xsltTransformContextPtr ctxt, const xmlChar *name,
245                  const xmlChar *nameURI) {
246     xsltTemplatePtr cur;
247     xsltStylesheetPtr style;
248
249     if ((ctxt == NULL) || (name == NULL))
250         return(NULL);
251     style = ctxt->style;
252     while (style != NULL) {
253         cur = style->templates;
254         while (cur != NULL) {
255             if (xmlStrEqual(name, cur->name)) {
256                 if (((nameURI == NULL) && (cur->nameURI == NULL)) ||
257                     ((nameURI != NULL) && (cur->nameURI != NULL) &&
258                      (xmlStrEqual(nameURI, cur->nameURI)))) {
259                     return(cur);
260                 }
261             }
262             cur = cur->next;
263         }
264
265         style = xsltNextImport(style);
266     }
267     return(NULL);
268 }
269