xref: /reactos/dll/3rdparty/libxslt/documents.c (revision b01a4801)
1c2c66affSColin Finck /*
2c2c66affSColin Finck  * documents.c: Implementation of the documents handling
3c2c66affSColin Finck  *
4c2c66affSColin Finck  * See Copyright for the status of this software.
5c2c66affSColin Finck  *
6c2c66affSColin Finck  * daniel@veillard.com
7c2c66affSColin Finck  */
8c2c66affSColin Finck 
9c2c66affSColin Finck #include "precomp.h"
10c2c66affSColin Finck 
11c2c66affSColin Finck #ifdef LIBXML_XINCLUDE_ENABLED
12c2c66affSColin Finck #include <libxml/xinclude.h>
13c2c66affSColin Finck #endif
14c2c66affSColin Finck 
15c2c66affSColin Finck #define WITH_XSLT_DEBUG_DOCUMENTS
16c2c66affSColin Finck 
17c2c66affSColin Finck #ifdef WITH_XSLT_DEBUG
18c2c66affSColin Finck #define WITH_XSLT_DEBUG_DOCUMENTS
19c2c66affSColin Finck #endif
20c2c66affSColin Finck 
21c2c66affSColin Finck /************************************************************************
22c2c66affSColin Finck  *									*
23c2c66affSColin Finck  *		Hooks for the document loader				*
24c2c66affSColin Finck  *									*
25c2c66affSColin Finck  ************************************************************************/
26c2c66affSColin Finck 
27c2c66affSColin Finck /**
28c2c66affSColin Finck  * xsltDocDefaultLoaderFunc:
29c2c66affSColin Finck  * @URI: the URI of the document to load
30c2c66affSColin Finck  * @dict: the dictionary to use when parsing that document
31c2c66affSColin Finck  * @options: parsing options, a set of xmlParserOption
32c2c66affSColin Finck  * @ctxt: the context, either a stylesheet or a transformation context
33c2c66affSColin Finck  * @type: the xsltLoadType indicating the kind of loading required
34c2c66affSColin Finck  *
35c2c66affSColin Finck  * Default function to load document not provided by the compilation or
36c2c66affSColin Finck  * transformation API themselve, for example when an xsl:import,
37c2c66affSColin Finck  * xsl:include is found at compilation time or when a document()
38c2c66affSColin Finck  * call is made at runtime.
39c2c66affSColin Finck  *
40c2c66affSColin Finck  * Returns the pointer to the document (which will be modified and
41c2c66affSColin Finck  * freed by the engine later), or NULL in case of error.
42c2c66affSColin Finck  */
43c2c66affSColin Finck static xmlDocPtr
xsltDocDefaultLoaderFunc(const xmlChar * URI,xmlDictPtr dict,int options,void * ctxt ATTRIBUTE_UNUSED,xsltLoadType type ATTRIBUTE_UNUSED)44c2c66affSColin Finck xsltDocDefaultLoaderFunc(const xmlChar * URI, xmlDictPtr dict, int options,
45c2c66affSColin Finck                          void *ctxt ATTRIBUTE_UNUSED,
46c2c66affSColin Finck 			 xsltLoadType type ATTRIBUTE_UNUSED)
47c2c66affSColin Finck {
48c2c66affSColin Finck     xmlParserCtxtPtr pctxt;
49c2c66affSColin Finck     xmlParserInputPtr inputStream;
50c2c66affSColin Finck     xmlDocPtr doc;
51c2c66affSColin Finck 
52c2c66affSColin Finck     pctxt = xmlNewParserCtxt();
53c2c66affSColin Finck     if (pctxt == NULL)
54c2c66affSColin Finck         return(NULL);
55c2c66affSColin Finck     if ((dict != NULL) && (pctxt->dict != NULL)) {
56c2c66affSColin Finck         xmlDictFree(pctxt->dict);
57c2c66affSColin Finck 	pctxt->dict = NULL;
58c2c66affSColin Finck     }
59c2c66affSColin Finck     if (dict != NULL) {
60c2c66affSColin Finck 	pctxt->dict = dict;
61c2c66affSColin Finck 	xmlDictReference(pctxt->dict);
62c2c66affSColin Finck #ifdef WITH_XSLT_DEBUG
63c2c66affSColin Finck 	xsltGenericDebug(xsltGenericDebugContext,
64c2c66affSColin Finck                      "Reusing dictionary for document\n");
65c2c66affSColin Finck #endif
66c2c66affSColin Finck     }
67c2c66affSColin Finck     xmlCtxtUseOptions(pctxt, options);
68c2c66affSColin Finck     inputStream = xmlLoadExternalEntity((const char *) URI, NULL, pctxt);
69c2c66affSColin Finck     if (inputStream == NULL) {
70c2c66affSColin Finck         xmlFreeParserCtxt(pctxt);
71c2c66affSColin Finck 	return(NULL);
72c2c66affSColin Finck     }
73c2c66affSColin Finck     inputPush(pctxt, inputStream);
74c2c66affSColin Finck     if (pctxt->directory == NULL)
75c2c66affSColin Finck         pctxt->directory = xmlParserGetDirectory((const char *) URI);
76c2c66affSColin Finck 
77c2c66affSColin Finck     xmlParseDocument(pctxt);
78c2c66affSColin Finck 
79c2c66affSColin Finck     if (pctxt->wellFormed) {
80c2c66affSColin Finck         doc = pctxt->myDoc;
81c2c66affSColin Finck     }
82c2c66affSColin Finck     else {
83c2c66affSColin Finck         doc = NULL;
84c2c66affSColin Finck         xmlFreeDoc(pctxt->myDoc);
85c2c66affSColin Finck         pctxt->myDoc = NULL;
86c2c66affSColin Finck     }
87c2c66affSColin Finck     xmlFreeParserCtxt(pctxt);
88c2c66affSColin Finck 
89c2c66affSColin Finck     return(doc);
90c2c66affSColin Finck }
91c2c66affSColin Finck 
92c2c66affSColin Finck 
93c2c66affSColin Finck xsltDocLoaderFunc xsltDocDefaultLoader = xsltDocDefaultLoaderFunc;
94c2c66affSColin Finck 
95c2c66affSColin Finck /**
96c2c66affSColin Finck  * xsltSetLoaderFunc:
97c2c66affSColin Finck  * @f: the new function to handle document loading.
98c2c66affSColin Finck  *
99c2c66affSColin Finck  * Set the new function to load document, if NULL it resets it to the
100c2c66affSColin Finck  * default function.
101c2c66affSColin Finck  */
102c2c66affSColin Finck 
103c2c66affSColin Finck void
xsltSetLoaderFunc(xsltDocLoaderFunc f)104c2c66affSColin Finck xsltSetLoaderFunc(xsltDocLoaderFunc f) {
105c2c66affSColin Finck     if (f == NULL)
106c2c66affSColin Finck         xsltDocDefaultLoader = xsltDocDefaultLoaderFunc;
107c2c66affSColin Finck     else
108c2c66affSColin Finck         xsltDocDefaultLoader = f;
109c2c66affSColin Finck }
110c2c66affSColin Finck 
111c2c66affSColin Finck /************************************************************************
112c2c66affSColin Finck  *									*
113c2c66affSColin Finck  *			Module interfaces				*
114c2c66affSColin Finck  *									*
115c2c66affSColin Finck  ************************************************************************/
116c2c66affSColin Finck 
117c2c66affSColin Finck /**
118c2c66affSColin Finck  * xsltNewDocument:
119c2c66affSColin Finck  * @ctxt: an XSLT transformation context (or NULL)
120c2c66affSColin Finck  * @doc:  a parsed XML document
121c2c66affSColin Finck  *
122c2c66affSColin Finck  * Register a new document, apply key computations
123c2c66affSColin Finck  *
124c2c66affSColin Finck  * Returns a handler to the document
125c2c66affSColin Finck  */
126c2c66affSColin Finck xsltDocumentPtr
xsltNewDocument(xsltTransformContextPtr ctxt,xmlDocPtr doc)127c2c66affSColin Finck xsltNewDocument(xsltTransformContextPtr ctxt, xmlDocPtr doc) {
128c2c66affSColin Finck     xsltDocumentPtr cur;
129c2c66affSColin Finck 
130c2c66affSColin Finck     cur = (xsltDocumentPtr) xmlMalloc(sizeof(xsltDocument));
131c2c66affSColin Finck     if (cur == NULL) {
132c2c66affSColin Finck 	xsltTransformError(ctxt, NULL, (xmlNodePtr) doc,
133c2c66affSColin Finck 		"xsltNewDocument : malloc failed\n");
134c2c66affSColin Finck 	return(NULL);
135c2c66affSColin Finck     }
136c2c66affSColin Finck     memset(cur, 0, sizeof(xsltDocument));
137c2c66affSColin Finck     cur->doc = doc;
138c2c66affSColin Finck     if (ctxt != NULL) {
139c2c66affSColin Finck         if (! XSLT_IS_RES_TREE_FRAG(doc)) {
140c2c66affSColin Finck 	    cur->next = ctxt->docList;
141c2c66affSColin Finck 	    ctxt->docList = cur;
142c2c66affSColin Finck 	}
143c2c66affSColin Finck 	/*
144c2c66affSColin Finck 	* A key with a specific name for a specific document
145c2c66affSColin Finck 	* will only be computed if there's a call to the key()
146c2c66affSColin Finck 	* function using that specific name for that specific
147c2c66affSColin Finck 	* document. I.e. computation of keys will be done in
148c2c66affSColin Finck 	* xsltGetKey() (keys.c) on an on-demand basis.
149c2c66affSColin Finck 	*
150c2c66affSColin Finck 	* xsltInitCtxtKeys(ctxt, cur); not called here anymore
151c2c66affSColin Finck 	*/
152c2c66affSColin Finck     }
153c2c66affSColin Finck     return(cur);
154c2c66affSColin Finck }
155c2c66affSColin Finck 
156c2c66affSColin Finck /**
157c2c66affSColin Finck  * xsltNewStyleDocument:
158c2c66affSColin Finck  * @style: an XSLT style sheet
159c2c66affSColin Finck  * @doc:  a parsed XML document
160c2c66affSColin Finck  *
161c2c66affSColin Finck  * Register a new document, apply key computations
162c2c66affSColin Finck  *
163c2c66affSColin Finck  * Returns a handler to the document
164c2c66affSColin Finck  */
165c2c66affSColin Finck xsltDocumentPtr
xsltNewStyleDocument(xsltStylesheetPtr style,xmlDocPtr doc)166c2c66affSColin Finck xsltNewStyleDocument(xsltStylesheetPtr style, xmlDocPtr doc) {
167c2c66affSColin Finck     xsltDocumentPtr cur;
168c2c66affSColin Finck 
169c2c66affSColin Finck     cur = (xsltDocumentPtr) xmlMalloc(sizeof(xsltDocument));
170c2c66affSColin Finck     if (cur == NULL) {
171c2c66affSColin Finck 	xsltTransformError(NULL, style, (xmlNodePtr) doc,
172c2c66affSColin Finck 		"xsltNewStyleDocument : malloc failed\n");
173c2c66affSColin Finck 	return(NULL);
174c2c66affSColin Finck     }
175c2c66affSColin Finck     memset(cur, 0, sizeof(xsltDocument));
176c2c66affSColin Finck     cur->doc = doc;
177c2c66affSColin Finck     if (style != NULL) {
178c2c66affSColin Finck 	cur->next = style->docList;
179c2c66affSColin Finck 	style->docList = cur;
180c2c66affSColin Finck     }
181c2c66affSColin Finck     return(cur);
182c2c66affSColin Finck }
183c2c66affSColin Finck 
184c2c66affSColin Finck /**
185c2c66affSColin Finck  * xsltFreeStyleDocuments:
186c2c66affSColin Finck  * @style: an XSLT stylesheet (representing a stylesheet-level)
187c2c66affSColin Finck  *
188c2c66affSColin Finck  * Frees the node-trees (and xsltDocument structures) of all
189c2c66affSColin Finck  * stylesheet-modules of the stylesheet-level represented by
190c2c66affSColin Finck  * the given @style.
191c2c66affSColin Finck  */
192c2c66affSColin Finck void
xsltFreeStyleDocuments(xsltStylesheetPtr style)193c2c66affSColin Finck xsltFreeStyleDocuments(xsltStylesheetPtr style) {
194c2c66affSColin Finck     xsltDocumentPtr doc, cur;
195c2c66affSColin Finck #ifdef XSLT_REFACTORED_XSLT_NSCOMP
196c2c66affSColin Finck     xsltNsMapPtr nsMap;
197c2c66affSColin Finck #endif
198c2c66affSColin Finck 
199c2c66affSColin Finck     if (style == NULL)
200c2c66affSColin Finck 	return;
201c2c66affSColin Finck 
202c2c66affSColin Finck #ifdef XSLT_REFACTORED_XSLT_NSCOMP
203c2c66affSColin Finck     if (XSLT_HAS_INTERNAL_NSMAP(style))
204c2c66affSColin Finck 	nsMap = XSLT_GET_INTERNAL_NSMAP(style);
205c2c66affSColin Finck     else
206c2c66affSColin Finck 	nsMap = NULL;
207c2c66affSColin Finck #endif
208c2c66affSColin Finck 
209c2c66affSColin Finck     cur = style->docList;
210c2c66affSColin Finck     while (cur != NULL) {
211c2c66affSColin Finck 	doc = cur;
212c2c66affSColin Finck 	cur = cur->next;
213c2c66affSColin Finck #ifdef XSLT_REFACTORED_XSLT_NSCOMP
214c2c66affSColin Finck 	/*
215c2c66affSColin Finck 	* Restore all changed namespace URIs of ns-decls.
216c2c66affSColin Finck 	*/
217c2c66affSColin Finck 	if (nsMap)
218c2c66affSColin Finck 	    xsltRestoreDocumentNamespaces(nsMap, doc->doc);
219c2c66affSColin Finck #endif
220c2c66affSColin Finck 	xsltFreeDocumentKeys(doc);
221c2c66affSColin Finck 	if (!doc->main)
222c2c66affSColin Finck 	    xmlFreeDoc(doc->doc);
223c2c66affSColin Finck         xmlFree(doc);
224c2c66affSColin Finck     }
225c2c66affSColin Finck }
226c2c66affSColin Finck 
227c2c66affSColin Finck /**
228c2c66affSColin Finck  * xsltFreeDocuments:
229c2c66affSColin Finck  * @ctxt: an XSLT transformation context
230c2c66affSColin Finck  *
231c2c66affSColin Finck  * Free up all the space used by the loaded documents
232c2c66affSColin Finck  */
233c2c66affSColin Finck void
xsltFreeDocuments(xsltTransformContextPtr ctxt)234c2c66affSColin Finck xsltFreeDocuments(xsltTransformContextPtr ctxt) {
235c2c66affSColin Finck     xsltDocumentPtr doc, cur;
236c2c66affSColin Finck 
237c2c66affSColin Finck     cur = ctxt->docList;
238c2c66affSColin Finck     while (cur != NULL) {
239c2c66affSColin Finck 	doc = cur;
240c2c66affSColin Finck 	cur = cur->next;
241c2c66affSColin Finck 	xsltFreeDocumentKeys(doc);
242c2c66affSColin Finck 	if (!doc->main)
243c2c66affSColin Finck 	    xmlFreeDoc(doc->doc);
244c2c66affSColin Finck         xmlFree(doc);
245c2c66affSColin Finck     }
246c2c66affSColin Finck     cur = ctxt->styleList;
247c2c66affSColin Finck     while (cur != NULL) {
248c2c66affSColin Finck 	doc = cur;
249c2c66affSColin Finck 	cur = cur->next;
250c2c66affSColin Finck 	xsltFreeDocumentKeys(doc);
251c2c66affSColin Finck 	if (!doc->main)
252c2c66affSColin Finck 	    xmlFreeDoc(doc->doc);
253c2c66affSColin Finck         xmlFree(doc);
254c2c66affSColin Finck     }
255c2c66affSColin Finck }
256c2c66affSColin Finck 
257c2c66affSColin Finck /**
258c2c66affSColin Finck  * xsltLoadDocument:
259c2c66affSColin Finck  * @ctxt: an XSLT transformation context
260c2c66affSColin Finck  * @URI:  the computed URI of the document
261c2c66affSColin Finck  *
262c2c66affSColin Finck  * Try to load a document (not a stylesheet)
263c2c66affSColin Finck  * within the XSLT transformation context
264c2c66affSColin Finck  *
265c2c66affSColin Finck  * Returns the new xsltDocumentPtr or NULL in case of error
266c2c66affSColin Finck  */
267c2c66affSColin Finck xsltDocumentPtr
xsltLoadDocument(xsltTransformContextPtr ctxt,const xmlChar * URI)268c2c66affSColin Finck xsltLoadDocument(xsltTransformContextPtr ctxt, const xmlChar *URI) {
269c2c66affSColin Finck     xsltDocumentPtr ret;
270c2c66affSColin Finck     xmlDocPtr doc;
271c2c66affSColin Finck 
272c2c66affSColin Finck     if ((ctxt == NULL) || (URI == NULL))
273c2c66affSColin Finck 	return(NULL);
274c2c66affSColin Finck 
275c2c66affSColin Finck     /*
276c2c66affSColin Finck      * Security framework check
277c2c66affSColin Finck      */
278c2c66affSColin Finck     if (ctxt->sec != NULL) {
279c2c66affSColin Finck 	int res;
280c2c66affSColin Finck 
281c2c66affSColin Finck 	res = xsltCheckRead(ctxt->sec, ctxt, URI);
282*b01a4801SThomas Faber 	if (res <= 0) {
283*b01a4801SThomas Faber             if (res == 0)
284c2c66affSColin Finck                 xsltTransformError(ctxt, NULL, NULL,
285c2c66affSColin Finck                      "xsltLoadDocument: read rights for %s denied\n",
286c2c66affSColin Finck                                  URI);
287c2c66affSColin Finck 	    return(NULL);
288c2c66affSColin Finck 	}
289c2c66affSColin Finck     }
290c2c66affSColin Finck 
291c2c66affSColin Finck     /*
292c2c66affSColin Finck      * Walk the context list to find the document if preparsed
293c2c66affSColin Finck      */
294c2c66affSColin Finck     ret = ctxt->docList;
295c2c66affSColin Finck     while (ret != NULL) {
296c2c66affSColin Finck 	if ((ret->doc != NULL) && (ret->doc->URL != NULL) &&
297c2c66affSColin Finck 	    (xmlStrEqual(ret->doc->URL, URI)))
298c2c66affSColin Finck 	    return(ret);
299c2c66affSColin Finck 	ret = ret->next;
300c2c66affSColin Finck     }
301c2c66affSColin Finck 
302c2c66affSColin Finck     doc = xsltDocDefaultLoader(URI, ctxt->dict, ctxt->parserOptions,
303c2c66affSColin Finck                                (void *) ctxt, XSLT_LOAD_DOCUMENT);
304c2c66affSColin Finck 
305c2c66affSColin Finck     if (doc == NULL)
306c2c66affSColin Finck 	return(NULL);
307c2c66affSColin Finck 
308c2c66affSColin Finck     if (ctxt->xinclude != 0) {
309c2c66affSColin Finck #ifdef LIBXML_XINCLUDE_ENABLED
310c2c66affSColin Finck #if LIBXML_VERSION >= 20603
311c2c66affSColin Finck 	xmlXIncludeProcessFlags(doc, ctxt->parserOptions);
312c2c66affSColin Finck #else
313c2c66affSColin Finck 	xmlXIncludeProcess(doc);
314c2c66affSColin Finck #endif
315c2c66affSColin Finck #else
316c2c66affSColin Finck 	xsltTransformError(ctxt, NULL, NULL,
317c2c66affSColin Finck 	    "xsltLoadDocument(%s) : XInclude processing not compiled in\n",
318c2c66affSColin Finck 	                 URI);
319c2c66affSColin Finck #endif
320c2c66affSColin Finck     }
321c2c66affSColin Finck     /*
322c2c66affSColin Finck      * Apply white-space stripping if asked for
323c2c66affSColin Finck      */
324c2c66affSColin Finck     if (xsltNeedElemSpaceHandling(ctxt))
325c2c66affSColin Finck 	xsltApplyStripSpaces(ctxt, xmlDocGetRootElement(doc));
326c2c66affSColin Finck     if (ctxt->debugStatus == XSLT_DEBUG_NONE)
327c2c66affSColin Finck 	xmlXPathOrderDocElems(doc);
328c2c66affSColin Finck 
329c2c66affSColin Finck     ret = xsltNewDocument(ctxt, doc);
330c2c66affSColin Finck     return(ret);
331c2c66affSColin Finck }
332c2c66affSColin Finck 
333c2c66affSColin Finck /**
334c2c66affSColin Finck  * xsltLoadStyleDocument:
335c2c66affSColin Finck  * @style: an XSLT style sheet
336c2c66affSColin Finck  * @URI:  the computed URI of the document
337c2c66affSColin Finck  *
338c2c66affSColin Finck  * Try to load a stylesheet document within the XSLT transformation context
339c2c66affSColin Finck  *
340c2c66affSColin Finck  * Returns the new xsltDocumentPtr or NULL in case of error
341c2c66affSColin Finck  */
342c2c66affSColin Finck xsltDocumentPtr
xsltLoadStyleDocument(xsltStylesheetPtr style,const xmlChar * URI)343c2c66affSColin Finck xsltLoadStyleDocument(xsltStylesheetPtr style, const xmlChar *URI) {
344c2c66affSColin Finck     xsltDocumentPtr ret;
345c2c66affSColin Finck     xmlDocPtr doc;
346c2c66affSColin Finck     xsltSecurityPrefsPtr sec;
347c2c66affSColin Finck 
348c2c66affSColin Finck     if ((style == NULL) || (URI == NULL))
349c2c66affSColin Finck 	return(NULL);
350c2c66affSColin Finck 
351c2c66affSColin Finck     /*
352c2c66affSColin Finck      * Security framework check
353c2c66affSColin Finck      */
354c2c66affSColin Finck     sec = xsltGetDefaultSecurityPrefs();
355c2c66affSColin Finck     if (sec != NULL) {
356c2c66affSColin Finck 	int res;
357c2c66affSColin Finck 
358c2c66affSColin Finck 	res = xsltCheckRead(sec, NULL, URI);
359*b01a4801SThomas Faber 	if (res <= 0) {
360*b01a4801SThomas Faber             if (res == 0)
361c2c66affSColin Finck                 xsltTransformError(NULL, NULL, NULL,
362c2c66affSColin Finck                      "xsltLoadStyleDocument: read rights for %s denied\n",
363c2c66affSColin Finck                                  URI);
364c2c66affSColin Finck 	    return(NULL);
365c2c66affSColin Finck 	}
366c2c66affSColin Finck     }
367c2c66affSColin Finck 
368c2c66affSColin Finck     /*
369c2c66affSColin Finck      * Walk the context list to find the document if preparsed
370c2c66affSColin Finck      */
371c2c66affSColin Finck     ret = style->docList;
372c2c66affSColin Finck     while (ret != NULL) {
373c2c66affSColin Finck 	if ((ret->doc != NULL) && (ret->doc->URL != NULL) &&
374c2c66affSColin Finck 	    (xmlStrEqual(ret->doc->URL, URI)))
375c2c66affSColin Finck 	    return(ret);
376c2c66affSColin Finck 	ret = ret->next;
377c2c66affSColin Finck     }
378c2c66affSColin Finck 
379c2c66affSColin Finck     doc = xsltDocDefaultLoader(URI, style->dict, XSLT_PARSE_OPTIONS,
380c2c66affSColin Finck                                (void *) style, XSLT_LOAD_STYLESHEET);
381c2c66affSColin Finck     if (doc == NULL)
382c2c66affSColin Finck 	return(NULL);
383c2c66affSColin Finck 
384c2c66affSColin Finck     ret = xsltNewStyleDocument(style, doc);
385c2c66affSColin Finck     return(ret);
386c2c66affSColin Finck }
387c2c66affSColin Finck 
388c2c66affSColin Finck /**
389c2c66affSColin Finck  * xsltFindDocument:
390c2c66affSColin Finck  * @ctxt: an XSLT transformation context
391c2c66affSColin Finck  * @doc: a parsed XML document
392c2c66affSColin Finck  *
393c2c66affSColin Finck  * Try to find a document within the XSLT transformation context.
394c2c66affSColin Finck  * This will not find document infos for temporary
395c2c66affSColin Finck  * Result Tree Fragments.
396c2c66affSColin Finck  *
397c2c66affSColin Finck  * Returns the desired xsltDocumentPtr or NULL in case of error
398c2c66affSColin Finck  */
399c2c66affSColin Finck xsltDocumentPtr
xsltFindDocument(xsltTransformContextPtr ctxt,xmlDocPtr doc)400c2c66affSColin Finck xsltFindDocument (xsltTransformContextPtr ctxt, xmlDocPtr doc) {
401c2c66affSColin Finck     xsltDocumentPtr ret;
402c2c66affSColin Finck 
403c2c66affSColin Finck     if ((ctxt == NULL) || (doc == NULL))
404c2c66affSColin Finck 	return(NULL);
405c2c66affSColin Finck 
406c2c66affSColin Finck     /*
407c2c66affSColin Finck      * Walk the context list to find the document
408c2c66affSColin Finck      */
409c2c66affSColin Finck     ret = ctxt->docList;
410c2c66affSColin Finck     while (ret != NULL) {
411c2c66affSColin Finck 	if (ret->doc == doc)
412c2c66affSColin Finck 	    return(ret);
413c2c66affSColin Finck 	ret = ret->next;
414c2c66affSColin Finck     }
415c2c66affSColin Finck     if (doc == ctxt->style->doc)
416c2c66affSColin Finck 	return(ctxt->document);
417c2c66affSColin Finck     return(NULL);
418c2c66affSColin Finck }
419c2c66affSColin Finck 
420