2 * imports.c: Implementation of the XSLT imports
5 * http://www.w3.org/TR/1999/REC-xslt-19991116
7 * See Copyright for the status of this software.
17 #ifdef HAVE_SYS_TYPES_H
18 #include <sys/types.h>
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>
42 #include "xsltInternals.h"
43 #include "xsltutils.h"
46 #include "documents.h"
51 /************************************************************************
55 ************************************************************************/
57 * xsltFixImportedCompSteps:
58 * @master: the "master" stylesheet
59 * @style: the stylesheet being imported by the master
61 * normalize the comp steps for the stylesheet being imported
62 * by the master, together with any imports within that.
65 static void xsltFixImportedCompSteps(xsltStylesheetPtr master,
66 xsltStylesheetPtr style) {
67 xsltStylesheetPtr res;
68 xmlHashScan(style->templatesHash,
69 (xmlHashScanner) xsltNormalizeCompSteps, master);
70 master->extrasNr += style->extrasNr;
71 for (res = style->imports; res != NULL; res = res->next) {
72 xsltFixImportedCompSteps(master, res);
77 * xsltParseStylesheetImport:
78 * @style: the XSLT stylesheet
79 * @cur: the import element
81 * parse an XSLT stylesheet import element
83 * Returns 0 in case of success -1 in case of failure.
87 xsltParseStylesheetImport(xsltStylesheetPtr style, xmlNodePtr cur) {
89 xmlDocPtr import = NULL;
91 xmlChar *uriRef = NULL;
93 xsltStylesheetPtr res;
94 xsltSecurityPrefsPtr sec;
96 if ((cur == NULL) || (style == NULL))
99 uriRef = xmlGetNsProp(cur, (const xmlChar *)"href", NULL);
100 if (uriRef == NULL) {
101 xsltTransformError(NULL, style, cur,
102 "xsl:import : missing href attribute\n");
106 base = xmlNodeGetBase(style->doc, cur);
107 URI = xmlBuildURI(uriRef, base);
109 xsltTransformError(NULL, style, cur,
110 "xsl:import : invalid URI reference %s\n", uriRef);
115 while (res != NULL) {
116 if (res->doc == NULL)
118 if (xmlStrEqual(res->doc->URL, URI)) {
119 xsltTransformError(NULL, style, cur,
120 "xsl:import : recursion detected on imported URL %s\n", URI);
127 * Security framework check
129 sec = xsltGetDefaultSecurityPrefs();
133 secres = xsltCheckRead(sec, NULL, URI);
135 xsltTransformError(NULL, NULL, NULL,
136 "xsl:import: read rights for %s denied\n",
142 import = xsltDocDefaultLoader(URI, style->dict, XSLT_PARSE_OPTIONS,
143 (void *) style, XSLT_LOAD_STYLESHEET);
144 if (import == NULL) {
145 xsltTransformError(NULL, style, cur,
146 "xsl:import : unable to load %s\n", URI);
150 res = xsltParseStylesheetImportedDoc(import, style);
152 res->next = style->imports;
153 style->imports = res;
154 if (style->parent == NULL) {
155 xsltFixImportedCompSteps(style, res);
174 * xsltParseStylesheetInclude:
175 * @style: the XSLT stylesheet
176 * @cur: the include node
178 * parse an XSLT stylesheet include element
180 * Returns 0 in case of success -1 in case of failure
184 xsltParseStylesheetInclude(xsltStylesheetPtr style, xmlNodePtr cur) {
187 xmlChar *base = NULL;
188 xmlChar *uriRef = NULL;
190 xsltStylesheetPtr result;
191 xsltDocumentPtr include;
192 xsltDocumentPtr docptr;
195 if ((cur == NULL) || (style == NULL))
198 uriRef = xmlGetNsProp(cur, (const xmlChar *)"href", NULL);
199 if (uriRef == NULL) {
200 xsltTransformError(NULL, style, cur,
201 "xsl:include : missing href attribute\n");
205 base = xmlNodeGetBase(style->doc, cur);
206 URI = xmlBuildURI(uriRef, base);
208 xsltTransformError(NULL, style, cur,
209 "xsl:include : invalid URI reference %s\n", uriRef);
214 * in order to detect recursion, we check all previously included
217 docptr = style->includes;
218 while (docptr != NULL) {
219 if (xmlStrEqual(docptr->doc->URL, URI)) {
220 xsltTransformError(NULL, style, cur,
221 "xsl:include : recursion detected on included URL %s\n", URI);
224 docptr = docptr->includes;
227 include = xsltLoadStyleDocument(style, URI);
228 if (include == NULL) {
229 xsltTransformError(NULL, style, cur,
230 "xsl:include : unable to load %s\n", URI);
233 #ifdef XSLT_REFACTORED
234 if (IS_XSLT_ELEM_FAST(cur) && (cur->psvi != NULL)) {
235 ((xsltStyleItemIncludePtr) cur->psvi)->include = include;
237 xsltTransformError(NULL, style, cur,
238 "Internal error: (xsltParseStylesheetInclude) "
239 "The xsl:include element was not compiled.\n", URI);
244 style->doc = include->doc;
245 /* chain to stylesheet for recursion checking */
246 include->includes = style->includes;
247 style->includes = include;
248 oldNopreproc = style->nopreproc;
249 style->nopreproc = include->preproc;
251 * TODO: This will change some values of the
252 * including stylesheet with every included module
253 * (e.g. excluded-result-prefixes)
254 * We need to strictly seperate such stylesheet-owned values.
256 result = xsltParseStylesheetProcess(style, include->doc);
257 style->nopreproc = oldNopreproc;
258 include->preproc = 1;
259 style->includes = include->includes;
261 if (result == NULL) {
280 * @cur: the current XSLT stylesheet
282 * Find the next stylesheet in import precedence.
284 * Returns the next stylesheet or NULL if it was the last one
288 xsltNextImport(xsltStylesheetPtr cur) {
291 if (cur->imports != NULL)
292 return(cur->imports);
293 if (cur->next != NULL)
297 if (cur == NULL) break;
298 if (cur->next != NULL) return(cur->next);
299 } while (cur != NULL);
304 * xsltNeedElemSpaceHandling:
305 * @ctxt: an XSLT transformation context
307 * Checks whether that stylesheet requires white-space stripping
309 * Returns 1 if space should be stripped, 0 if not
313 xsltNeedElemSpaceHandling(xsltTransformContextPtr ctxt) {
314 xsltStylesheetPtr style;
319 while (style != NULL) {
320 if (style->stripSpaces != NULL)
322 style = xsltNextImport(style);
328 * xsltFindElemSpaceHandling:
329 * @ctxt: an XSLT transformation context
332 * Find strip-space or preserve-space informations for an element
333 * respect the import precedence or the wildcards
335 * Returns 1 if space should be stripped, 0 if not, and 2 if everything
336 * should be CDTATA wrapped.
340 xsltFindElemSpaceHandling(xsltTransformContextPtr ctxt, xmlNodePtr node) {
341 xsltStylesheetPtr style;
344 if ((ctxt == NULL) || (node == NULL))
347 while (style != NULL) {
348 if (node->ns != NULL) {
349 val = (const xmlChar *)
350 xmlHashLookup2(style->stripSpaces, node->name, node->ns->href);
352 val = (const xmlChar *)
353 xmlHashLookup2(style->stripSpaces, BAD_CAST "*",
357 val = (const xmlChar *)
358 xmlHashLookup2(style->stripSpaces, node->name, NULL);
361 if (xmlStrEqual(val, (xmlChar *) "strip"))
363 if (xmlStrEqual(val, (xmlChar *) "preserve"))
366 if (style->stripAll == 1)
368 if (style->stripAll == -1)
371 style = xsltNextImport(style);
378 * @ctxt: an XSLT transformation context
379 * @name: the template name
380 * @nameURI: the template name URI
382 * Finds the named template, apply import precedence rule.
383 * REVISIT TODO: We'll change the nameURI fields of
384 * templates to be in the string dict, so if the
385 * specified @nameURI is in the same dict, then use pointer
386 * comparison. Check if this can be done in a sane way.
387 * Maybe this function is not needed internally at
388 * transformation-time if we hard-wire the called templates
391 * Returns the xsltTemplatePtr or NULL if not found
394 xsltFindTemplate(xsltTransformContextPtr ctxt, const xmlChar *name,
395 const xmlChar *nameURI) {
397 xsltStylesheetPtr style;
399 if ((ctxt == NULL) || (name == NULL))
402 while (style != NULL) {
403 cur = style->templates;
404 while (cur != NULL) {
405 if (xmlStrEqual(name, cur->name)) {
406 if (((nameURI == NULL) && (cur->nameURI == NULL)) ||
407 ((nameURI != NULL) && (cur->nameURI != NULL) &&
408 (xmlStrEqual(nameURI, cur->nameURI)))) {
415 style = xsltNextImport(style);