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
);