2 * documents.c: Implementation of the documents handling
4 * See Copyright for the status of this software.
11 #ifdef LIBXML_XINCLUDE_ENABLED
12 #include <libxml/xinclude.h>
15 #define WITH_XSLT_DEBUG_DOCUMENTS
17 #ifdef WITH_XSLT_DEBUG
18 #define WITH_XSLT_DEBUG_DOCUMENTS
21 /************************************************************************
23 * Hooks for the document loader *
25 ************************************************************************/
28 * xsltDocDefaultLoaderFunc:
29 * @URI: the URI of the document to load
30 * @dict: the dictionary to use when parsing that document
31 * @options: parsing options, a set of xmlParserOption
32 * @ctxt: the context, either a stylesheet or a transformation context
33 * @type: the xsltLoadType indicating the kind of loading required
35 * Default function to load document not provided by the compilation or
36 * transformation API themselve, for example when an xsl:import,
37 * xsl:include is found at compilation time or when a document()
38 * call is made at runtime.
40 * Returns the pointer to the document (which will be modified and
41 * freed by the engine later), or NULL in case of error.
44 xsltDocDefaultLoaderFunc(const xmlChar
* URI
, xmlDictPtr dict
, int options
,
45 void *ctxt ATTRIBUTE_UNUSED
,
46 xsltLoadType type ATTRIBUTE_UNUSED
)
48 xmlParserCtxtPtr pctxt
;
49 xmlParserInputPtr inputStream
;
52 pctxt
= xmlNewParserCtxt();
55 if ((dict
!= NULL
) && (pctxt
->dict
!= NULL
)) {
56 xmlDictFree(pctxt
->dict
);
61 xmlDictReference(pctxt
->dict
);
62 #ifdef WITH_XSLT_DEBUG
63 xsltGenericDebug(xsltGenericDebugContext
,
64 "Reusing dictionary for document\n");
67 xmlCtxtUseOptions(pctxt
, options
);
68 inputStream
= xmlLoadExternalEntity((const char *) URI
, NULL
, pctxt
);
69 if (inputStream
== NULL
) {
70 xmlFreeParserCtxt(pctxt
);
73 inputPush(pctxt
, inputStream
);
74 if (pctxt
->directory
== NULL
)
75 pctxt
->directory
= xmlParserGetDirectory((const char *) URI
);
77 xmlParseDocument(pctxt
);
79 if (pctxt
->wellFormed
) {
84 xmlFreeDoc(pctxt
->myDoc
);
87 xmlFreeParserCtxt(pctxt
);
93 xsltDocLoaderFunc xsltDocDefaultLoader
= xsltDocDefaultLoaderFunc
;
97 * @f: the new function to handle document loading.
99 * Set the new function to load document, if NULL it resets it to the
104 xsltSetLoaderFunc(xsltDocLoaderFunc f
) {
106 xsltDocDefaultLoader
= xsltDocDefaultLoaderFunc
;
108 xsltDocDefaultLoader
= f
;
111 /************************************************************************
113 * Module interfaces *
115 ************************************************************************/
119 * @ctxt: an XSLT transformation context (or NULL)
120 * @doc: a parsed XML document
122 * Register a new document, apply key computations
124 * Returns a handler to the document
127 xsltNewDocument(xsltTransformContextPtr ctxt
, xmlDocPtr doc
) {
130 cur
= (xsltDocumentPtr
) xmlMalloc(sizeof(xsltDocument
));
132 xsltTransformError(ctxt
, NULL
, (xmlNodePtr
) doc
,
133 "xsltNewDocument : malloc failed\n");
136 memset(cur
, 0, sizeof(xsltDocument
));
139 if (! XSLT_IS_RES_TREE_FRAG(doc
)) {
140 cur
->next
= ctxt
->docList
;
144 * A key with a specific name for a specific document
145 * will only be computed if there's a call to the key()
146 * function using that specific name for that specific
147 * document. I.e. computation of keys will be done in
148 * xsltGetKey() (keys.c) on an on-demand basis.
150 * xsltInitCtxtKeys(ctxt, cur); not called here anymore
157 * xsltNewStyleDocument:
158 * @style: an XSLT style sheet
159 * @doc: a parsed XML document
161 * Register a new document, apply key computations
163 * Returns a handler to the document
166 xsltNewStyleDocument(xsltStylesheetPtr style
, xmlDocPtr doc
) {
169 cur
= (xsltDocumentPtr
) xmlMalloc(sizeof(xsltDocument
));
171 xsltTransformError(NULL
, style
, (xmlNodePtr
) doc
,
172 "xsltNewStyleDocument : malloc failed\n");
175 memset(cur
, 0, sizeof(xsltDocument
));
178 cur
->next
= style
->docList
;
179 style
->docList
= cur
;
185 * xsltFreeStyleDocuments:
186 * @style: an XSLT stylesheet (representing a stylesheet-level)
188 * Frees the node-trees (and xsltDocument structures) of all
189 * stylesheet-modules of the stylesheet-level represented by
193 xsltFreeStyleDocuments(xsltStylesheetPtr style
) {
194 xsltDocumentPtr doc
, cur
;
195 #ifdef XSLT_REFACTORED_XSLT_NSCOMP
202 #ifdef XSLT_REFACTORED_XSLT_NSCOMP
203 if (XSLT_HAS_INTERNAL_NSMAP(style
))
204 nsMap
= XSLT_GET_INTERNAL_NSMAP(style
);
209 cur
= style
->docList
;
210 while (cur
!= NULL
) {
213 #ifdef XSLT_REFACTORED_XSLT_NSCOMP
215 * Restore all changed namespace URIs of ns-decls.
218 xsltRestoreDocumentNamespaces(nsMap
, doc
->doc
);
220 xsltFreeDocumentKeys(doc
);
222 xmlFreeDoc(doc
->doc
);
229 * @ctxt: an XSLT transformation context
231 * Free up all the space used by the loaded documents
234 xsltFreeDocuments(xsltTransformContextPtr ctxt
) {
235 xsltDocumentPtr doc
, cur
;
238 while (cur
!= NULL
) {
241 xsltFreeDocumentKeys(doc
);
243 xmlFreeDoc(doc
->doc
);
246 cur
= ctxt
->styleList
;
247 while (cur
!= NULL
) {
250 xsltFreeDocumentKeys(doc
);
252 xmlFreeDoc(doc
->doc
);
259 * @ctxt: an XSLT transformation context
260 * @URI: the computed URI of the document
262 * Try to load a document (not a stylesheet)
263 * within the XSLT transformation context
265 * Returns the new xsltDocumentPtr or NULL in case of error
268 xsltLoadDocument(xsltTransformContextPtr ctxt
, const xmlChar
*URI
) {
272 if ((ctxt
== NULL
) || (URI
== NULL
))
276 * Security framework check
278 if (ctxt
->sec
!= NULL
) {
281 res
= xsltCheckRead(ctxt
->sec
, ctxt
, URI
);
283 xsltTransformError(ctxt
, NULL
, NULL
,
284 "xsltLoadDocument: read rights for %s denied\n",
291 * Walk the context list to find the document if preparsed
294 while (ret
!= NULL
) {
295 if ((ret
->doc
!= NULL
) && (ret
->doc
->URL
!= NULL
) &&
296 (xmlStrEqual(ret
->doc
->URL
, URI
)))
301 doc
= xsltDocDefaultLoader(URI
, ctxt
->dict
, ctxt
->parserOptions
,
302 (void *) ctxt
, XSLT_LOAD_DOCUMENT
);
307 if (ctxt
->xinclude
!= 0) {
308 #ifdef LIBXML_XINCLUDE_ENABLED
309 #if LIBXML_VERSION >= 20603
310 xmlXIncludeProcessFlags(doc
, ctxt
->parserOptions
);
312 xmlXIncludeProcess(doc
);
315 xsltTransformError(ctxt
, NULL
, NULL
,
316 "xsltLoadDocument(%s) : XInclude processing not compiled in\n",
321 * Apply white-space stripping if asked for
323 if (xsltNeedElemSpaceHandling(ctxt
))
324 xsltApplyStripSpaces(ctxt
, xmlDocGetRootElement(doc
));
325 if (ctxt
->debugStatus
== XSLT_DEBUG_NONE
)
326 xmlXPathOrderDocElems(doc
);
328 ret
= xsltNewDocument(ctxt
, doc
);
333 * xsltLoadStyleDocument:
334 * @style: an XSLT style sheet
335 * @URI: the computed URI of the document
337 * Try to load a stylesheet document within the XSLT transformation context
339 * Returns the new xsltDocumentPtr or NULL in case of error
342 xsltLoadStyleDocument(xsltStylesheetPtr style
, const xmlChar
*URI
) {
345 xsltSecurityPrefsPtr sec
;
347 if ((style
== NULL
) || (URI
== NULL
))
351 * Security framework check
353 sec
= xsltGetDefaultSecurityPrefs();
357 res
= xsltCheckRead(sec
, NULL
, URI
);
359 xsltTransformError(NULL
, NULL
, NULL
,
360 "xsltLoadStyleDocument: read rights for %s denied\n",
367 * Walk the context list to find the document if preparsed
369 ret
= style
->docList
;
370 while (ret
!= NULL
) {
371 if ((ret
->doc
!= NULL
) && (ret
->doc
->URL
!= NULL
) &&
372 (xmlStrEqual(ret
->doc
->URL
, URI
)))
377 doc
= xsltDocDefaultLoader(URI
, style
->dict
, XSLT_PARSE_OPTIONS
,
378 (void *) style
, XSLT_LOAD_STYLESHEET
);
382 ret
= xsltNewStyleDocument(style
, doc
);
388 * @ctxt: an XSLT transformation context
389 * @doc: a parsed XML document
391 * Try to find a document within the XSLT transformation context.
392 * This will not find document infos for temporary
393 * Result Tree Fragments.
395 * Returns the desired xsltDocumentPtr or NULL in case of error
398 xsltFindDocument (xsltTransformContextPtr ctxt
, xmlDocPtr doc
) {
401 if ((ctxt
== NULL
) || (doc
== NULL
))
405 * Walk the context list to find the document
408 while (ret
!= NULL
) {
413 if (doc
== ctxt
->style
->doc
)
414 return(ctxt
->document
);