2 * documents.c: Implementation of the documents handling
4 * See Copyright for the status of this software.
14 #include <libxml/xmlmemory.h>
15 #include <libxml/tree.h>
16 #include <libxml/hash.h>
17 #include <libxml/parser.h>
18 #include <libxml/parserInternals.h>
20 #include "xsltInternals.h"
21 #include "xsltutils.h"
22 #include "documents.h"
23 #include "transform.h"
28 #ifdef LIBXML_XINCLUDE_ENABLED
29 #include <libxml/xinclude.h>
32 #define WITH_XSLT_DEBUG_DOCUMENTS
34 #ifdef WITH_XSLT_DEBUG
35 #define WITH_XSLT_DEBUG_DOCUMENTS
38 /************************************************************************
40 * Hooks for the document loader *
42 ************************************************************************/
45 * xsltDocDefaultLoaderFunc:
46 * @URI: the URI of the document to load
47 * @dict: the dictionary to use when parsing that document
48 * @options: parsing options, a set of xmlParserOption
49 * @ctxt: the context, either a stylesheet or a transformation context
50 * @type: the xsltLoadType indicating the kind of loading required
52 * Default function to load document not provided by the compilation or
53 * transformation API themselve, for example when an xsl:import,
54 * xsl:include is found at compilation time or when a document()
55 * call is made at runtime.
57 * Returns the pointer to the document (which will be modified and
58 * freed by the engine later), or NULL in case of error.
61 xsltDocDefaultLoaderFunc(const xmlChar
* URI
, xmlDictPtr dict
, int options
,
62 void *ctxt ATTRIBUTE_UNUSED
,
63 xsltLoadType type ATTRIBUTE_UNUSED
)
65 xmlParserCtxtPtr pctxt
;
66 xmlParserInputPtr inputStream
;
69 pctxt
= xmlNewParserCtxt();
72 if ((dict
!= NULL
) && (pctxt
->dict
!= NULL
)) {
73 xmlDictFree(pctxt
->dict
);
78 xmlDictReference(pctxt
->dict
);
79 #ifdef WITH_XSLT_DEBUG
80 xsltGenericDebug(xsltGenericDebugContext
,
81 "Reusing dictionary for document\n");
84 xmlCtxtUseOptions(pctxt
, options
);
85 inputStream
= xmlLoadExternalEntity((const char *) URI
, NULL
, pctxt
);
86 if (inputStream
== NULL
) {
87 xmlFreeParserCtxt(pctxt
);
90 inputPush(pctxt
, inputStream
);
91 if (pctxt
->directory
== NULL
)
92 pctxt
->directory
= xmlParserGetDirectory((const char *) URI
);
94 xmlParseDocument(pctxt
);
96 if (pctxt
->wellFormed
) {
101 xmlFreeDoc(pctxt
->myDoc
);
104 xmlFreeParserCtxt(pctxt
);
110 xsltDocLoaderFunc xsltDocDefaultLoader
= xsltDocDefaultLoaderFunc
;
114 * @f: the new function to handle document loading.
116 * Set the new function to load document, if NULL it resets it to the
121 xsltSetLoaderFunc(xsltDocLoaderFunc f
) {
123 xsltDocDefaultLoader
= xsltDocDefaultLoaderFunc
;
125 xsltDocDefaultLoader
= f
;
128 /************************************************************************
130 * Module interfaces *
132 ************************************************************************/
136 * @ctxt: an XSLT transformation context (or NULL)
137 * @doc: a parsed XML document
139 * Register a new document, apply key computations
141 * Returns a handler to the document
144 xsltNewDocument(xsltTransformContextPtr ctxt
, xmlDocPtr doc
) {
147 cur
= (xsltDocumentPtr
) xmlMalloc(sizeof(xsltDocument
));
149 xsltTransformError(ctxt
, NULL
, (xmlNodePtr
) doc
,
150 "xsltNewDocument : malloc failed\n");
153 memset(cur
, 0, sizeof(xsltDocument
));
156 if (! XSLT_IS_RES_TREE_FRAG(doc
)) {
157 cur
->next
= ctxt
->docList
;
161 * A key with a specific name for a specific document
162 * will only be computed if there's a call to the key()
163 * function using that specific name for that specific
164 * document. I.e. computation of keys will be done in
165 * xsltGetKey() (keys.c) on an on-demand basis.
167 * xsltInitCtxtKeys(ctxt, cur); not called here anymore
174 * xsltNewStyleDocument:
175 * @style: an XSLT style sheet
176 * @doc: a parsed XML document
178 * Register a new document, apply key computations
180 * Returns a handler to the document
183 xsltNewStyleDocument(xsltStylesheetPtr style
, xmlDocPtr doc
) {
186 cur
= (xsltDocumentPtr
) xmlMalloc(sizeof(xsltDocument
));
188 xsltTransformError(NULL
, style
, (xmlNodePtr
) doc
,
189 "xsltNewStyleDocument : malloc failed\n");
192 memset(cur
, 0, sizeof(xsltDocument
));
195 cur
->next
= style
->docList
;
196 style
->docList
= cur
;
202 * xsltFreeStyleDocuments:
203 * @style: an XSLT stylesheet (representing a stylesheet-level)
205 * Frees the node-trees (and xsltDocument structures) of all
206 * stylesheet-modules of the stylesheet-level represented by
210 xsltFreeStyleDocuments(xsltStylesheetPtr style
) {
211 xsltDocumentPtr doc
, cur
;
212 #ifdef XSLT_REFACTORED_XSLT_NSCOMP
219 #ifdef XSLT_REFACTORED_XSLT_NSCOMP
220 if (XSLT_HAS_INTERNAL_NSMAP(style
))
221 nsMap
= XSLT_GET_INTERNAL_NSMAP(style
);
226 cur
= style
->docList
;
227 while (cur
!= NULL
) {
230 #ifdef XSLT_REFACTORED_XSLT_NSCOMP
232 * Restore all changed namespace URIs of ns-decls.
235 xsltRestoreDocumentNamespaces(nsMap
, doc
->doc
);
237 xsltFreeDocumentKeys(doc
);
239 xmlFreeDoc(doc
->doc
);
246 * @ctxt: an XSLT transformation context
248 * Free up all the space used by the loaded documents
251 xsltFreeDocuments(xsltTransformContextPtr ctxt
) {
252 xsltDocumentPtr doc
, cur
;
255 while (cur
!= NULL
) {
258 xsltFreeDocumentKeys(doc
);
260 xmlFreeDoc(doc
->doc
);
263 cur
= ctxt
->styleList
;
264 while (cur
!= NULL
) {
267 xsltFreeDocumentKeys(doc
);
269 xmlFreeDoc(doc
->doc
);
276 * @ctxt: an XSLT transformation context
277 * @URI: the computed URI of the document
279 * Try to load a document (not a stylesheet)
280 * within the XSLT transformation context
282 * Returns the new xsltDocumentPtr or NULL in case of error
285 xsltLoadDocument(xsltTransformContextPtr ctxt
, const xmlChar
*URI
) {
289 if ((ctxt
== NULL
) || (URI
== NULL
))
293 * Security framework check
295 if (ctxt
->sec
!= NULL
) {
298 res
= xsltCheckRead(ctxt
->sec
, ctxt
, URI
);
300 xsltTransformError(ctxt
, NULL
, NULL
,
301 "xsltLoadDocument: read rights for %s denied\n",
308 * Walk the context list to find the document if preparsed
311 while (ret
!= NULL
) {
312 if ((ret
->doc
!= NULL
) && (ret
->doc
->URL
!= NULL
) &&
313 (xmlStrEqual(ret
->doc
->URL
, URI
)))
318 doc
= xsltDocDefaultLoader(URI
, ctxt
->dict
, ctxt
->parserOptions
,
319 (void *) ctxt
, XSLT_LOAD_DOCUMENT
);
324 if (ctxt
->xinclude
!= 0) {
325 #ifdef LIBXML_XINCLUDE_ENABLED
326 #if LIBXML_VERSION >= 20603
327 xmlXIncludeProcessFlags(doc
, ctxt
->parserOptions
);
329 xmlXIncludeProcess(doc
);
332 xsltTransformError(ctxt
, NULL
, NULL
,
333 "xsltLoadDocument(%s) : XInclude processing not compiled in\n",
338 * Apply white-space stripping if asked for
340 if (xsltNeedElemSpaceHandling(ctxt
))
341 xsltApplyStripSpaces(ctxt
, xmlDocGetRootElement(doc
));
342 if (ctxt
->debugStatus
== XSLT_DEBUG_NONE
)
343 xmlXPathOrderDocElems(doc
);
345 ret
= xsltNewDocument(ctxt
, doc
);
350 * xsltLoadStyleDocument:
351 * @style: an XSLT style sheet
352 * @URI: the computed URI of the document
354 * Try to load a stylesheet document within the XSLT transformation context
356 * Returns the new xsltDocumentPtr or NULL in case of error
359 xsltLoadStyleDocument(xsltStylesheetPtr style
, const xmlChar
*URI
) {
362 xsltSecurityPrefsPtr sec
;
364 if ((style
== NULL
) || (URI
== NULL
))
368 * Security framework check
370 sec
= xsltGetDefaultSecurityPrefs();
374 res
= xsltCheckRead(sec
, NULL
, URI
);
376 xsltTransformError(NULL
, NULL
, NULL
,
377 "xsltLoadStyleDocument: read rights for %s denied\n",
384 * Walk the context list to find the document if preparsed
386 ret
= style
->docList
;
387 while (ret
!= NULL
) {
388 if ((ret
->doc
!= NULL
) && (ret
->doc
->URL
!= NULL
) &&
389 (xmlStrEqual(ret
->doc
->URL
, URI
)))
394 doc
= xsltDocDefaultLoader(URI
, style
->dict
, XSLT_PARSE_OPTIONS
,
395 (void *) style
, XSLT_LOAD_STYLESHEET
);
399 ret
= xsltNewStyleDocument(style
, doc
);
405 * @ctxt: an XSLT transformation context
406 * @doc: a parsed XML document
408 * Try to find a document within the XSLT transformation context.
409 * This will not find document infos for temporary
410 * Result Tree Fragments.
412 * Returns the desired xsltDocumentPtr or NULL in case of error
415 xsltFindDocument (xsltTransformContextPtr ctxt
, xmlDocPtr doc
) {
418 if ((ctxt
== NULL
) || (doc
== NULL
))
422 * Walk the context list to find the document
425 while (ret
!= NULL
) {
430 if (doc
== ctxt
->style
->doc
)
431 return(ctxt
->document
);