blob: 05e05ed52c3f440b862c359fd8372a6480795c9d [file] [log] [blame]
Owen Taylor3473f882001-02-23 17:55:21 +00001/*
2 * xinclude.c : Code to implement XInclude processing
3 *
Daniel Veillarde74d2e12003-12-09 11:35:37 +00004 * World Wide Web Consortium W3C Last Call Working Draft 10 November 2003
5 * http://www.w3.org/TR/2003/WD-xinclude-20031110
Owen Taylor3473f882001-02-23 17:55:21 +00006 *
7 * See Copyright for the status of this software.
8 *
Daniel Veillardc5d64342001-06-24 12:13:24 +00009 * daniel@veillard.com
Owen Taylor3473f882001-02-23 17:55:21 +000010 */
11
Daniel Veillard34ce8be2002-03-18 19:37:11 +000012#define IN_LIBXML
Bjorn Reese70a9da52001-04-21 16:57:29 +000013#include "libxml.h"
Owen Taylor3473f882001-02-23 17:55:21 +000014
Owen Taylor3473f882001-02-23 17:55:21 +000015#include <string.h>
16#include <libxml/xmlmemory.h>
17#include <libxml/tree.h>
18#include <libxml/parser.h>
19#include <libxml/uri.h>
20#include <libxml/xpointer.h>
21#include <libxml/parserInternals.h>
Owen Taylor3473f882001-02-23 17:55:21 +000022#include <libxml/xmlerror.h>
Daniel Veillardd076a202002-11-20 13:28:31 +000023#include <libxml/encoding.h>
Daniel Veillard3c01b1d2001-10-17 15:58:35 +000024#include <libxml/globals.h>
Owen Taylor3473f882001-02-23 17:55:21 +000025
26#ifdef LIBXML_XINCLUDE_ENABLED
27#include <libxml/xinclude.h>
28
Owen Taylor3473f882001-02-23 17:55:21 +000029
Daniel Veillardf4b4f982003-02-13 11:02:08 +000030#define XINCLUDE_MAX_DEPTH 40
31
Daniel Veillard98485322003-08-14 15:44:40 +000032/* #define DEBUG_XINCLUDE */
Daniel Veillard017b1082001-06-21 11:20:21 +000033#ifdef DEBUG_XINCLUDE
34#ifdef LIBXML_DEBUG_ENABLED
35#include <libxml/debugXML.h>
36#endif
37#endif
Owen Taylor3473f882001-02-23 17:55:21 +000038
39/************************************************************************
40 * *
William M. Brack72ee48d2003-12-30 08:30:19 +000041 * XInclude context handling *
Owen Taylor3473f882001-02-23 17:55:21 +000042 * *
43 ************************************************************************/
44
45/*
46 * An XInclude context
47 */
Daniel Veillardedac3c92001-02-26 01:36:19 +000048typedef xmlChar *xmlURL;
Daniel Veillardbbc72c32002-09-05 10:52:10 +000049
50typedef struct _xmlXIncludeRef xmlXIncludeRef;
51typedef xmlXIncludeRef *xmlXIncludeRefPtr;
52struct _xmlXIncludeRef {
William M. Brack72ee48d2003-12-30 08:30:19 +000053 xmlChar *URI; /* the fully resolved resource URL */
Daniel Veillardbbc72c32002-09-05 10:52:10 +000054 xmlChar *fragment; /* the fragment in the URI */
55 xmlDocPtr doc; /* the parsed document */
56 xmlNodePtr ref; /* the node making the reference in the source */
57 xmlNodePtr inc; /* the included copy */
58 int xml; /* xml or txt */
59 int count; /* how many refs use that specific doc */
Daniel Veillardf4b4f982003-02-13 11:02:08 +000060 xmlXPathObjectPtr xptr; /* the xpointer if needed */
William M. Brack95af5942004-02-08 04:12:49 +000061 int emptyFb; /* flag to show fallback empty */
Daniel Veillardbbc72c32002-09-05 10:52:10 +000062};
63
Owen Taylor3473f882001-02-23 17:55:21 +000064struct _xmlXIncludeCtxt {
65 xmlDocPtr doc; /* the source document */
Daniel Veillardbbc72c32002-09-05 10:52:10 +000066 int incBase; /* the first include for this document */
Owen Taylor3473f882001-02-23 17:55:21 +000067 int incNr; /* number of includes */
68 int incMax; /* size of includes tab */
Daniel Veillardbbc72c32002-09-05 10:52:10 +000069 xmlXIncludeRefPtr *incTab; /* array of included references */
70
Owen Taylor3473f882001-02-23 17:55:21 +000071 int txtNr; /* number of unparsed documents */
72 int txtMax; /* size of unparsed documents tab */
73 xmlNodePtr *txtTab; /* array of unparsed text nodes */
William M. Brack72ee48d2003-12-30 08:30:19 +000074 xmlURL *txturlTab; /* array of unparsed text URLs */
Daniel Veillardd581b7e2003-02-11 18:03:05 +000075
Daniel Veillardf4b4f982003-02-13 11:02:08 +000076 xmlChar * url; /* the current URL processed */
William M. Brack72ee48d2003-12-30 08:30:19 +000077 int urlNr; /* number of URLs stacked */
78 int urlMax; /* size of URL stack */
79 xmlChar * *urlTab; /* URL stack */
Daniel Veillardf4b4f982003-02-13 11:02:08 +000080
Daniel Veillardd581b7e2003-02-11 18:03:05 +000081 int nbErrors; /* the number of errors detected */
Daniel Veillardb5fa0202003-12-08 17:41:29 +000082 int legacy; /* using XINCLUDE_OLD_NS */
Daniel Veillarde74d2e12003-12-09 11:35:37 +000083 int parseFlags; /* the flags used for parsing XML documents */
Owen Taylor3473f882001-02-23 17:55:21 +000084};
85
Daniel Veillardd16df9f2001-05-23 13:44:21 +000086static int
Daniel Veillard8edf1c52003-07-22 20:52:14 +000087xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr tree);
Owen Taylor3473f882001-02-23 17:55:21 +000088
Daniel Veillard98485322003-08-14 15:44:40 +000089
Daniel Veillardcd6ff282003-10-08 22:38:13 +000090/************************************************************************
91 * *
Daniel Veillard69d2c172003-10-09 11:46:07 +000092 * XInclude error handler *
Daniel Veillardcd6ff282003-10-08 22:38:13 +000093 * *
94 ************************************************************************/
95
Daniel Veillard98485322003-08-14 15:44:40 +000096/**
Daniel Veillardcd6ff282003-10-08 22:38:13 +000097 * xmlXIncludeErrMemory:
William M. Brack72ee48d2003-12-30 08:30:19 +000098 * @extra: extra information
Daniel Veillard98485322003-08-14 15:44:40 +000099 *
Daniel Veillardcd6ff282003-10-08 22:38:13 +0000100 * Handle an out of memory condition
Daniel Veillard98485322003-08-14 15:44:40 +0000101 */
102static void
Daniel Veillardcd6ff282003-10-08 22:38:13 +0000103xmlXIncludeErrMemory(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node,
104 const char *extra)
Daniel Veillard98485322003-08-14 15:44:40 +0000105{
Daniel Veillardcd6ff282003-10-08 22:38:13 +0000106 if (ctxt != NULL)
107 ctxt->nbErrors++;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000108 __xmlRaiseError(NULL, NULL, NULL, ctxt, node, XML_FROM_XINCLUDE,
Daniel Veillardcd6ff282003-10-08 22:38:13 +0000109 XML_ERR_NO_MEMORY, XML_ERR_ERROR, NULL, 0,
110 extra, NULL, NULL, 0, 0,
111 "Memory allocation failed : %s\n", extra);
112}
Daniel Veillard98485322003-08-14 15:44:40 +0000113
Daniel Veillardcd6ff282003-10-08 22:38:13 +0000114/**
115 * xmlXIncludeErr:
116 * @ctxt: the XInclude context
117 * @node: the context node
118 * @msg: the error message
William M. Brack72ee48d2003-12-30 08:30:19 +0000119 * @extra: extra information
Daniel Veillardcd6ff282003-10-08 22:38:13 +0000120 *
Daniel Veillardb5fa0202003-12-08 17:41:29 +0000121 * Handle an XInclude error
Daniel Veillardcd6ff282003-10-08 22:38:13 +0000122 */
123static void
124xmlXIncludeErr(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node, int error,
125 const char *msg, const xmlChar *extra)
126{
127 if (ctxt != NULL)
128 ctxt->nbErrors++;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000129 __xmlRaiseError(NULL, NULL, NULL, ctxt, node, XML_FROM_XINCLUDE,
Daniel Veillardcd6ff282003-10-08 22:38:13 +0000130 error, XML_ERR_ERROR, NULL, 0,
131 (const char *) extra, NULL, NULL, 0, 0,
132 msg, (const char *) extra);
Daniel Veillard98485322003-08-14 15:44:40 +0000133}
134
Daniel Veillardf54cd532004-02-25 11:52:31 +0000135#if 0
Owen Taylor3473f882001-02-23 17:55:21 +0000136/**
Daniel Veillardb5fa0202003-12-08 17:41:29 +0000137 * xmlXIncludeWarn:
138 * @ctxt: the XInclude context
139 * @node: the context node
140 * @msg: the error message
William M. Brack72ee48d2003-12-30 08:30:19 +0000141 * @extra: extra information
Daniel Veillardb5fa0202003-12-08 17:41:29 +0000142 *
143 * Emit an XInclude warning.
144 */
145static void
146xmlXIncludeWarn(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node, int error,
147 const char *msg, const xmlChar *extra)
148{
149 __xmlRaiseError(NULL, NULL, NULL, ctxt, node, XML_FROM_XINCLUDE,
150 error, XML_ERR_WARNING, NULL, 0,
151 (const char *) extra, NULL, NULL, 0, 0,
152 msg, (const char *) extra);
153}
Daniel Veillardf54cd532004-02-25 11:52:31 +0000154#endif
Daniel Veillardb5fa0202003-12-08 17:41:29 +0000155
156/**
157 * xmlXIncludeGetProp:
158 * @ctxt: the XInclude context
159 * @cur: the node
160 * @name: the attribute name
161 *
162 * Get an XInclude attribute
163 *
164 * Returns the value (to be freed) or NULL if not found
165 */
166static xmlChar *
167xmlXIncludeGetProp(xmlXIncludeCtxtPtr ctxt, xmlNodePtr cur,
168 const xmlChar *name) {
169 xmlChar *ret;
170
171 ret = xmlGetNsProp(cur, XINCLUDE_NS, name);
172 if (ret != NULL)
173 return(ret);
174 if (ctxt->legacy != 0) {
175 ret = xmlGetNsProp(cur, XINCLUDE_OLD_NS, name);
176 if (ret != NULL)
177 return(ret);
178 }
179 ret = xmlGetProp(cur, name);
180 return(ret);
181}
182/**
Daniel Veillardbbc72c32002-09-05 10:52:10 +0000183 * xmlXIncludeFreeRef:
184 * @ref: the XInclude reference
185 *
186 * Free an XInclude reference
187 */
188static void
189xmlXIncludeFreeRef(xmlXIncludeRefPtr ref) {
190 if (ref == NULL)
191 return;
192#ifdef DEBUG_XINCLUDE
193 xmlGenericError(xmlGenericErrorContext, "Freeing ref\n");
194#endif
195 if (ref->doc != NULL) {
196#ifdef DEBUG_XINCLUDE
197 xmlGenericError(xmlGenericErrorContext, "Freeing doc %s\n", ref->URI);
198#endif
199 xmlFreeDoc(ref->doc);
200 }
201 if (ref->URI != NULL)
202 xmlFree(ref->URI);
203 if (ref->fragment != NULL)
204 xmlFree(ref->fragment);
Daniel Veillardf4b4f982003-02-13 11:02:08 +0000205 if (ref->xptr != NULL)
206 xmlXPathFreeObject(ref->xptr);
Daniel Veillardbbc72c32002-09-05 10:52:10 +0000207 xmlFree(ref);
208}
209
210/**
211 * xmlXIncludeNewRef:
212 * @ctxt: the XInclude context
213 * @URI: the resource URI
214 *
215 * Creates a new reference within an XInclude context
216 *
217 * Returns the new set
218 */
219static xmlXIncludeRefPtr
220xmlXIncludeNewRef(xmlXIncludeCtxtPtr ctxt, const xmlChar *URI,
221 xmlNodePtr ref) {
222 xmlXIncludeRefPtr ret;
223
224#ifdef DEBUG_XINCLUDE
225 xmlGenericError(xmlGenericErrorContext, "New ref %s\n", URI);
226#endif
227 ret = (xmlXIncludeRefPtr) xmlMalloc(sizeof(xmlXIncludeRef));
Daniel Veillardcd6ff282003-10-08 22:38:13 +0000228 if (ret == NULL) {
229 xmlXIncludeErrMemory(ctxt, ref, "growing XInclude context");
Daniel Veillardbbc72c32002-09-05 10:52:10 +0000230 return(NULL);
Daniel Veillardcd6ff282003-10-08 22:38:13 +0000231 }
Daniel Veillardbbc72c32002-09-05 10:52:10 +0000232 memset(ret, 0, sizeof(xmlXIncludeRef));
233 if (URI == NULL)
234 ret->URI = NULL;
235 else
236 ret->URI = xmlStrdup(URI);
237 ret->fragment = NULL;
238 ret->ref = ref;
239 ret->doc = 0;
240 ret->count = 0;
241 ret->xml = 0;
242 ret->inc = NULL;
243 if (ctxt->incMax == 0) {
244 ctxt->incMax = 4;
245 ctxt->incTab = (xmlXIncludeRefPtr *) xmlMalloc(ctxt->incMax *
246 sizeof(ctxt->incTab[0]));
247 if (ctxt->incTab == NULL) {
Daniel Veillardcd6ff282003-10-08 22:38:13 +0000248 xmlXIncludeErrMemory(ctxt, ref, "growing XInclude context");
Daniel Veillardbbc72c32002-09-05 10:52:10 +0000249 xmlXIncludeFreeRef(ret);
250 return(NULL);
251 }
252 }
253 if (ctxt->incNr >= ctxt->incMax) {
254 ctxt->incMax *= 2;
255 ctxt->incTab = (xmlXIncludeRefPtr *) xmlRealloc(ctxt->incTab,
256 ctxt->incMax * sizeof(ctxt->incTab[0]));
257 if (ctxt->incTab == NULL) {
Daniel Veillardcd6ff282003-10-08 22:38:13 +0000258 xmlXIncludeErrMemory(ctxt, ref, "growing XInclude context");
Daniel Veillardbbc72c32002-09-05 10:52:10 +0000259 xmlXIncludeFreeRef(ret);
260 return(NULL);
261 }
262 }
263 ctxt->incTab[ctxt->incNr++] = ret;
264 return(ret);
265}
266
267/**
Owen Taylor3473f882001-02-23 17:55:21 +0000268 * xmlXIncludeNewContext:
269 * @doc: an XML Document
270 *
271 * Creates a new XInclude context
272 *
273 * Returns the new set
274 */
Daniel Veillard7899c5c2003-11-03 12:31:38 +0000275xmlXIncludeCtxtPtr
Owen Taylor3473f882001-02-23 17:55:21 +0000276xmlXIncludeNewContext(xmlDocPtr doc) {
277 xmlXIncludeCtxtPtr ret;
278
Daniel Veillardbbc72c32002-09-05 10:52:10 +0000279#ifdef DEBUG_XINCLUDE
280 xmlGenericError(xmlGenericErrorContext, "New context\n");
281#endif
Owen Taylor3473f882001-02-23 17:55:21 +0000282 if (doc == NULL)
283 return(NULL);
284 ret = (xmlXIncludeCtxtPtr) xmlMalloc(sizeof(xmlXIncludeCtxt));
Daniel Veillardcd6ff282003-10-08 22:38:13 +0000285 if (ret == NULL) {
286 xmlXIncludeErrMemory(NULL, (xmlNodePtr) doc,
287 "creating XInclude context");
Owen Taylor3473f882001-02-23 17:55:21 +0000288 return(NULL);
Daniel Veillardcd6ff282003-10-08 22:38:13 +0000289 }
Owen Taylor3473f882001-02-23 17:55:21 +0000290 memset(ret, 0, sizeof(xmlXIncludeCtxt));
291 ret->doc = doc;
292 ret->incNr = 0;
Daniel Veillardbbc72c32002-09-05 10:52:10 +0000293 ret->incBase = 0;
Owen Taylor3473f882001-02-23 17:55:21 +0000294 ret->incMax = 0;
295 ret->incTab = NULL;
Daniel Veillardd581b7e2003-02-11 18:03:05 +0000296 ret->nbErrors = 0;
Owen Taylor3473f882001-02-23 17:55:21 +0000297 return(ret);
298}
299
300/**
Daniel Veillardf4b4f982003-02-13 11:02:08 +0000301 * xmlXIncludeURLPush:
302 * @ctxt: the parser context
303 * @value: the url
304 *
305 * Pushes a new url on top of the url stack
306 *
307 * Returns -1 in case of error, the index in the stack otherwise
308 */
309static int
310xmlXIncludeURLPush(xmlXIncludeCtxtPtr ctxt,
311 const xmlChar *value)
312{
313 if (ctxt->urlNr > XINCLUDE_MAX_DEPTH) {
Daniel Veillardcd6ff282003-10-08 22:38:13 +0000314 xmlXIncludeErr(ctxt, NULL, XML_XINCLUDE_RECURSION,
315 "detected a recursion in %s\n", value);
Daniel Veillardf4b4f982003-02-13 11:02:08 +0000316 return(-1);
317 }
318 if (ctxt->urlTab == NULL) {
319 ctxt->urlMax = 4;
320 ctxt->urlNr = 0;
321 ctxt->urlTab = (xmlChar * *) xmlMalloc(
322 ctxt->urlMax * sizeof(ctxt->urlTab[0]));
323 if (ctxt->urlTab == NULL) {
Daniel Veillardcd6ff282003-10-08 22:38:13 +0000324 xmlXIncludeErrMemory(ctxt, NULL, "adding URL");
Daniel Veillardf4b4f982003-02-13 11:02:08 +0000325 return (-1);
326 }
327 }
328 if (ctxt->urlNr >= ctxt->urlMax) {
329 ctxt->urlMax *= 2;
330 ctxt->urlTab =
331 (xmlChar * *) xmlRealloc(ctxt->urlTab,
332 ctxt->urlMax *
333 sizeof(ctxt->urlTab[0]));
334 if (ctxt->urlTab == NULL) {
Daniel Veillardcd6ff282003-10-08 22:38:13 +0000335 xmlXIncludeErrMemory(ctxt, NULL, "adding URL");
Daniel Veillardf4b4f982003-02-13 11:02:08 +0000336 return (-1);
337 }
338 }
339 ctxt->url = ctxt->urlTab[ctxt->urlNr] = xmlStrdup(value);
340 return (ctxt->urlNr++);
341}
342
343/**
344 * xmlXIncludeURLPop:
345 * @ctxt: the parser context
346 *
William M. Brack72ee48d2003-12-30 08:30:19 +0000347 * Pops the top URL from the URL stack
Daniel Veillardf4b4f982003-02-13 11:02:08 +0000348 */
349static void
350xmlXIncludeURLPop(xmlXIncludeCtxtPtr ctxt)
351{
352 xmlChar * ret;
353
354 if (ctxt->urlNr <= 0)
355 return;
356 ctxt->urlNr--;
357 if (ctxt->urlNr > 0)
358 ctxt->url = ctxt->urlTab[ctxt->urlNr - 1];
359 else
360 ctxt->url = NULL;
361 ret = ctxt->urlTab[ctxt->urlNr];
362 ctxt->urlTab[ctxt->urlNr] = 0;
363 if (ret != NULL)
364 xmlFree(ret);
365}
366
367/**
Owen Taylor3473f882001-02-23 17:55:21 +0000368 * xmlXIncludeFreeContext:
369 * @ctxt: the XInclude context
370 *
371 * Free an XInclude context
372 */
Daniel Veillard7899c5c2003-11-03 12:31:38 +0000373void
Owen Taylor3473f882001-02-23 17:55:21 +0000374xmlXIncludeFreeContext(xmlXIncludeCtxtPtr ctxt) {
375 int i;
376
Daniel Veillardbbc72c32002-09-05 10:52:10 +0000377#ifdef DEBUG_XINCLUDE
378 xmlGenericError(xmlGenericErrorContext, "Freeing context\n");
379#endif
Owen Taylor3473f882001-02-23 17:55:21 +0000380 if (ctxt == NULL)
381 return;
Daniel Veillardf4b4f982003-02-13 11:02:08 +0000382 while (ctxt->urlNr > 0)
383 xmlXIncludeURLPop(ctxt);
384 if (ctxt->urlTab != NULL)
385 xmlFree(ctxt->urlTab);
Daniel Veillardbbc72c32002-09-05 10:52:10 +0000386 for (i = 0;i < ctxt->incNr;i++) {
387 if (ctxt->incTab[i] != NULL)
388 xmlXIncludeFreeRef(ctxt->incTab[i]);
Owen Taylor3473f882001-02-23 17:55:21 +0000389 }
390 for (i = 0;i < ctxt->txtNr;i++) {
391 if (ctxt->txturlTab[i] != NULL)
392 xmlFree(ctxt->txturlTab[i]);
393 }
394 if (ctxt->incTab != NULL)
395 xmlFree(ctxt->incTab);
Owen Taylor3473f882001-02-23 17:55:21 +0000396 if (ctxt->txtTab != NULL)
397 xmlFree(ctxt->txtTab);
398 if (ctxt->txturlTab != NULL)
399 xmlFree(ctxt->txturlTab);
Owen Taylor3473f882001-02-23 17:55:21 +0000400 xmlFree(ctxt);
401}
402
Daniel Veillardd16df9f2001-05-23 13:44:21 +0000403/**
Daniel Veillard98485322003-08-14 15:44:40 +0000404 * xmlXIncludeParseFile:
405 * @ctxt: the XInclude context
406 * @URL: the URL or file path
407 *
William M. Brack72ee48d2003-12-30 08:30:19 +0000408 * parse a document for XInclude
Daniel Veillard98485322003-08-14 15:44:40 +0000409 */
410static xmlDocPtr
Daniel Veillarde74d2e12003-12-09 11:35:37 +0000411xmlXIncludeParseFile(xmlXIncludeCtxtPtr ctxt, const char *URL) {
Daniel Veillard98485322003-08-14 15:44:40 +0000412 xmlDocPtr ret;
413 xmlParserCtxtPtr pctxt;
414 char *directory = NULL;
Daniel Veillarde74d2e12003-12-09 11:35:37 +0000415 xmlParserInputPtr inputStream;
Daniel Veillard98485322003-08-14 15:44:40 +0000416
417 xmlInitParser();
418
Daniel Veillarde74d2e12003-12-09 11:35:37 +0000419 pctxt = xmlNewParserCtxt();
Daniel Veillard98485322003-08-14 15:44:40 +0000420 if (pctxt == NULL) {
Daniel Veillarde74d2e12003-12-09 11:35:37 +0000421 xmlXIncludeErrMemory(ctxt, NULL, "cannot allocate parser context");
Daniel Veillard98485322003-08-14 15:44:40 +0000422 return(NULL);
423 }
Daniel Veillarde74d2e12003-12-09 11:35:37 +0000424 /*
William M. Brack72ee48d2003-12-30 08:30:19 +0000425 * try to ensure that new documents included are actually
Daniel Veillarde74d2e12003-12-09 11:35:37 +0000426 * built with the same dictionary as the including document.
427 */
428 if ((ctxt->doc != NULL) && (ctxt->doc->dict != NULL) &&
429 (pctxt->dict != NULL)) {
430 xmlDictFree(pctxt->dict);
431 pctxt->dict = ctxt->doc->dict;
432 xmlDictReference(pctxt->dict);
433 }
434
435 xmlCtxtUseOptions(pctxt, ctxt->parseFlags | XML_PARSE_DTDLOAD);
436
437 inputStream = xmlLoadExternalEntity(URL, NULL, pctxt);
438 if (inputStream == NULL) {
439 xmlFreeParserCtxt(pctxt);
440 return(NULL);
441 }
442
443 inputPush(pctxt, inputStream);
Daniel Veillard98485322003-08-14 15:44:40 +0000444
445 if ((pctxt->directory == NULL) && (directory == NULL))
446 directory = xmlParserGetDirectory(URL);
447 if ((pctxt->directory == NULL) && (directory != NULL))
448 pctxt->directory = (char *) xmlStrdup((xmlChar *) directory);
449
450 pctxt->loadsubset = XML_DETECT_IDS;
451
452 xmlParseDocument(pctxt);
453
William M. Brack1ff42132003-12-31 14:05:15 +0000454 if (pctxt->wellFormed) {
Daniel Veillard98485322003-08-14 15:44:40 +0000455 ret = pctxt->myDoc;
William M. Brack1ff42132003-12-31 14:05:15 +0000456 xmlDictReference(pctxt->dict);
457 }
Daniel Veillard98485322003-08-14 15:44:40 +0000458 else {
459 ret = NULL;
Daniel Veillard4773df22004-01-23 13:15:13 +0000460 if (pctxt->myDoc != NULL) {
461 if ((ctxt->doc != NULL) && (ctxt->doc->dict != NULL) &&
462 (pctxt->myDoc->dict == ctxt->doc->dict))
463 xmlDictReference(ctxt->doc->dict);
William M. Brackb2d25dd2004-02-04 00:51:21 +0000464 else if ((pctxt->dict != NULL) &&
465 (pctxt->dict == pctxt->myDoc->dict))
466 xmlDictReference(pctxt->dict);
Daniel Veillard4773df22004-01-23 13:15:13 +0000467 xmlFreeDoc(pctxt->myDoc);
468 }
Daniel Veillard98485322003-08-14 15:44:40 +0000469 pctxt->myDoc = NULL;
470 }
471 xmlFreeParserCtxt(pctxt);
472
473 return(ret);
474}
475
476/**
Daniel Veillardd16df9f2001-05-23 13:44:21 +0000477 * xmlXIncludeAddNode:
478 * @ctxt: the XInclude context
Daniel Veillardbbc72c32002-09-05 10:52:10 +0000479 * @cur: the new node
Daniel Veillardd16df9f2001-05-23 13:44:21 +0000480 *
481 * Add a new node to process to an XInclude context
482 */
Daniel Veillardbbc72c32002-09-05 10:52:10 +0000483static int
484xmlXIncludeAddNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr cur) {
485 xmlXIncludeRefPtr ref;
486 xmlURIPtr uri;
487 xmlChar *URL;
488 xmlChar *fragment = NULL;
489 xmlChar *href;
490 xmlChar *parse;
491 xmlChar *base;
492 xmlChar *URI;
Daniel Veillardf4b4f982003-02-13 11:02:08 +0000493 int xml = 1, i; /* default Issue 64 */
494 int local = 0;
Daniel Veillardbbc72c32002-09-05 10:52:10 +0000495
496
497 if (ctxt == NULL)
498 return(-1);
499 if (cur == NULL)
500 return(-1);
501
502#ifdef DEBUG_XINCLUDE
503 xmlGenericError(xmlGenericErrorContext, "Add node\n");
504#endif
505 /*
506 * read the attributes
507 */
Daniel Veillardb5fa0202003-12-08 17:41:29 +0000508 href = xmlXIncludeGetProp(ctxt, cur, XINCLUDE_HREF);
Daniel Veillardbbc72c32002-09-05 10:52:10 +0000509 if (href == NULL) {
Daniel Veillardb5fa0202003-12-08 17:41:29 +0000510 href = xmlStrdup(BAD_CAST ""); /* @@@@ href is now optional */
511 if (href == NULL)
Daniel Veillardbbc72c32002-09-05 10:52:10 +0000512 return(-1);
Daniel Veillardb5fa0202003-12-08 17:41:29 +0000513 local = 1;
Daniel Veillardd16df9f2001-05-23 13:44:21 +0000514 }
Daniel Veillardf4b4f982003-02-13 11:02:08 +0000515 if (href[0] == '#')
516 local = 1;
Daniel Veillardb5fa0202003-12-08 17:41:29 +0000517 parse = xmlXIncludeGetProp(ctxt, cur, XINCLUDE_PARSE);
Daniel Veillardbbc72c32002-09-05 10:52:10 +0000518 if (parse != NULL) {
519 if (xmlStrEqual(parse, XINCLUDE_PARSE_XML))
520 xml = 1;
521 else if (xmlStrEqual(parse, XINCLUDE_PARSE_TEXT))
522 xml = 0;
523 else {
Daniel Veillardcd6ff282003-10-08 22:38:13 +0000524 xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_PARSE_VALUE,
525 "invalid value %s for 'parse'\n", parse);
Daniel Veillardbbc72c32002-09-05 10:52:10 +0000526 if (href != NULL)
527 xmlFree(href);
528 if (parse != NULL)
529 xmlFree(parse);
530 return(-1);
Daniel Veillardd16df9f2001-05-23 13:44:21 +0000531 }
532 }
Daniel Veillardbbc72c32002-09-05 10:52:10 +0000533
534 /*
535 * compute the URI
536 */
537 base = xmlNodeGetBase(ctxt->doc, cur);
538 if (base == NULL) {
539 URI = xmlBuildURI(href, ctxt->doc->URL);
540 } else {
541 URI = xmlBuildURI(href, base);
542 }
543 if (URI == NULL) {
544 xmlChar *escbase;
545 xmlChar *eschref;
546 /*
547 * Some escaping may be needed
548 */
549 escbase = xmlURIEscape(base);
550 eschref = xmlURIEscape(href);
551 URI = xmlBuildURI(eschref, escbase);
552 if (escbase != NULL)
553 xmlFree(escbase);
554 if (eschref != NULL)
555 xmlFree(eschref);
556 }
557 if (parse != NULL)
558 xmlFree(parse);
559 if (href != NULL)
560 xmlFree(href);
561 if (base != NULL)
562 xmlFree(base);
563 if (URI == NULL) {
Daniel Veillardcd6ff282003-10-08 22:38:13 +0000564 xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_HREF_URI,
565 "failed build URL\n", NULL);
Daniel Veillardbbc72c32002-09-05 10:52:10 +0000566 return(-1);
567 }
Daniel Veillarde74d2e12003-12-09 11:35:37 +0000568 fragment = xmlXIncludeGetProp(ctxt, cur, XINCLUDE_PARSE_XPOINTER);
Daniel Veillardbbc72c32002-09-05 10:52:10 +0000569
570 /*
571 * Check the URL and remove any fragment identifier
572 */
573 uri = xmlParseURI((const char *)URI);
574 if (uri == NULL) {
Daniel Veillardcd6ff282003-10-08 22:38:13 +0000575 xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_HREF_URI,
576 "invalid value URI %s\n", URI);
Daniel Veillarde74d2e12003-12-09 11:35:37 +0000577 if (fragment != NULL)
578 xmlFree(fragment);
579 xmlFree(URI);
Daniel Veillardbbc72c32002-09-05 10:52:10 +0000580 return(-1);
581 }
Daniel Veillarde74d2e12003-12-09 11:35:37 +0000582
Daniel Veillardbbc72c32002-09-05 10:52:10 +0000583 if (uri->fragment != NULL) {
Daniel Veillarde74d2e12003-12-09 11:35:37 +0000584 if (ctxt->legacy != 0) {
585 if (fragment == NULL) {
586 fragment = (xmlChar *) uri->fragment;
587 } else {
588 xmlFree(uri->fragment);
589 }
590 } else {
591 xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_FRAGMENT_ID,
592 "Invalid fragment identifier in URI %s use the xpointer attribute\n",
593 URI);
594 if (fragment != NULL)
595 xmlFree(fragment);
596 xmlFreeURI(uri);
597 xmlFree(URI);
598 return(-1);
599 }
Daniel Veillardbbc72c32002-09-05 10:52:10 +0000600 uri->fragment = NULL;
601 }
602 URL = xmlSaveUri(uri);
603 xmlFreeURI(uri);
604 xmlFree(URI);
605 if (URL == NULL) {
Daniel Veillardcd6ff282003-10-08 22:38:13 +0000606 xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_HREF_URI,
607 "invalid value URI %s\n", URI);
Daniel Veillardbbc72c32002-09-05 10:52:10 +0000608 if (fragment != NULL)
609 xmlFree(fragment);
610 return(-1);
611 }
612
Daniel Veillardf4b4f982003-02-13 11:02:08 +0000613 /*
614 * Check the URL against the stack for recursions
615 */
616 if (!local) {
617 for (i = 0;i < ctxt->urlNr;i++) {
618 if (xmlStrEqual(URL, ctxt->urlTab[i])) {
Daniel Veillardcd6ff282003-10-08 22:38:13 +0000619 xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_RECURSION,
620 "detected a recursion in %s\n", URL);
Daniel Veillardf4b4f982003-02-13 11:02:08 +0000621 return(-1);
622 }
623 }
624 }
625
Daniel Veillardbbc72c32002-09-05 10:52:10 +0000626 ref = xmlXIncludeNewRef(ctxt, URL, cur);
627 if (ref == NULL) {
628 return(-1);
629 }
630 ref->fragment = fragment;
631 ref->doc = NULL;
632 ref->xml = xml;
633 ref->count = 1;
634 xmlFree(URL);
635 return(0);
Daniel Veillardd16df9f2001-05-23 13:44:21 +0000636}
637
638/**
Daniel Veillardbbc72c32002-09-05 10:52:10 +0000639 * xmlXIncludeRecurseDoc:
Daniel Veillardd16df9f2001-05-23 13:44:21 +0000640 * @ctxt: the XInclude context
641 * @doc: the new document
642 * @url: the associated URL
643 *
Daniel Veillardbbc72c32002-09-05 10:52:10 +0000644 * The XInclude recursive nature is handled at this point.
Daniel Veillardd16df9f2001-05-23 13:44:21 +0000645 */
646static void
Daniel Veillard118aed72002-09-24 14:13:13 +0000647xmlXIncludeRecurseDoc(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc,
Daniel Veillarddda8f1b2002-09-26 09:47:36 +0000648 const xmlURL url ATTRIBUTE_UNUSED) {
Daniel Veillardd16df9f2001-05-23 13:44:21 +0000649 xmlXIncludeCtxtPtr newctxt;
650 int i;
651
Daniel Veillardf4b4f982003-02-13 11:02:08 +0000652 /*
653 * Avoid recursion in already substitued resources
654 for (i = 0;i < ctxt->urlNr;i++) {
655 if (xmlStrEqual(doc->URL, ctxt->urlTab[i]))
656 return;
657 }
658 */
659
Daniel Veillardbbc72c32002-09-05 10:52:10 +0000660#ifdef DEBUG_XINCLUDE
661 xmlGenericError(xmlGenericErrorContext, "Recursing in doc %s\n", doc->URL);
662#endif
Daniel Veillardd16df9f2001-05-23 13:44:21 +0000663 /*
664 * Handle recursion here.
665 */
666
667 newctxt = xmlXIncludeNewContext(doc);
668 if (newctxt != NULL) {
669 /*
670 * Copy the existing document set
671 */
Daniel Veillardbbc72c32002-09-05 10:52:10 +0000672 newctxt->incMax = ctxt->incMax;
673 newctxt->incNr = ctxt->incNr;
674 newctxt->incTab = (xmlXIncludeRefPtr *) xmlMalloc(newctxt->incMax *
675 sizeof(newctxt->incTab[0]));
676 if (newctxt->incTab == NULL) {
Daniel Veillardcd6ff282003-10-08 22:38:13 +0000677 xmlXIncludeErrMemory(ctxt, (xmlNodePtr) doc, "processing doc");
Daniel Veillardd16df9f2001-05-23 13:44:21 +0000678 xmlFree(newctxt);
679 return;
680 }
Daniel Veillardf4b4f982003-02-13 11:02:08 +0000681 /*
682 * copy the urlTab
683 */
684 newctxt->urlMax = ctxt->urlMax;
685 newctxt->urlNr = ctxt->urlNr;
686 newctxt->urlTab = ctxt->urlTab;
Daniel Veillardd16df9f2001-05-23 13:44:21 +0000687
Daniel Veillardbbc72c32002-09-05 10:52:10 +0000688 /*
William M. Brack72ee48d2003-12-30 08:30:19 +0000689 * Inherit the documents already in use by other includes
Daniel Veillardbbc72c32002-09-05 10:52:10 +0000690 */
691 newctxt->incBase = ctxt->incNr;
692 for (i = 0;i < ctxt->incNr;i++) {
693 newctxt->incTab[i] = ctxt->incTab[i];
694 newctxt->incTab[i]->count++; /* prevent the recursion from
695 freeing it */
Daniel Veillardd16df9f2001-05-23 13:44:21 +0000696 }
William M. Bracka11e4832004-03-07 11:03:43 +0000697 /*
698 * The new context should also inherit the Parse Flags
699 * (bug 132597)
700 */
701 newctxt->parseFlags = ctxt->parseFlags;
Daniel Veillard8edf1c52003-07-22 20:52:14 +0000702 xmlXIncludeDoProcess(newctxt, doc, xmlDocGetRootElement(doc));
Daniel Veillardbbc72c32002-09-05 10:52:10 +0000703 for (i = 0;i < ctxt->incNr;i++) {
704 newctxt->incTab[i]->count--;
705 newctxt->incTab[i] = NULL;
Daniel Veillardd16df9f2001-05-23 13:44:21 +0000706 }
Daniel Veillardd9b72832003-03-27 14:24:00 +0000707
708 /* urlTab may have been reallocated */
709 ctxt->urlTab = newctxt->urlTab;
710 ctxt->urlMax = newctxt->urlMax;
711
Daniel Veillardf4b4f982003-02-13 11:02:08 +0000712 newctxt->urlMax = 0;
713 newctxt->urlNr = 0;
714 newctxt->urlTab = NULL;
715
Daniel Veillardd16df9f2001-05-23 13:44:21 +0000716 xmlXIncludeFreeContext(newctxt);
717 }
Daniel Veillardbbc72c32002-09-05 10:52:10 +0000718#ifdef DEBUG_XINCLUDE
719 xmlGenericError(xmlGenericErrorContext, "Done recursing in doc %s\n", url);
720#endif
Daniel Veillardd16df9f2001-05-23 13:44:21 +0000721}
722
723/**
724 * xmlXIncludeAddTxt:
725 * @ctxt: the XInclude context
726 * @txt: the new text node
727 * @url: the associated URL
728 *
729 * Add a new txtument to the list
730 */
731static void
732xmlXIncludeAddTxt(xmlXIncludeCtxtPtr ctxt, xmlNodePtr txt, const xmlURL url) {
Daniel Veillardbbc72c32002-09-05 10:52:10 +0000733#ifdef DEBUG_XINCLUDE
734 xmlGenericError(xmlGenericErrorContext, "Adding text %s\n", url);
735#endif
Daniel Veillardd16df9f2001-05-23 13:44:21 +0000736 if (ctxt->txtMax == 0) {
737 ctxt->txtMax = 4;
738 ctxt->txtTab = (xmlNodePtr *) xmlMalloc(ctxt->txtMax *
739 sizeof(ctxt->txtTab[0]));
740 if (ctxt->txtTab == NULL) {
Daniel Veillardcd6ff282003-10-08 22:38:13 +0000741 xmlXIncludeErrMemory(ctxt, NULL, "processing text");
Daniel Veillardd16df9f2001-05-23 13:44:21 +0000742 return;
743 }
744 ctxt->txturlTab = (xmlURL *) xmlMalloc(ctxt->txtMax *
745 sizeof(ctxt->txturlTab[0]));
746 if (ctxt->txturlTab == NULL) {
Daniel Veillardcd6ff282003-10-08 22:38:13 +0000747 xmlXIncludeErrMemory(ctxt, NULL, "processing text");
Daniel Veillardd16df9f2001-05-23 13:44:21 +0000748 return;
749 }
750 }
751 if (ctxt->txtNr >= ctxt->txtMax) {
752 ctxt->txtMax *= 2;
753 ctxt->txtTab = (xmlNodePtr *) xmlRealloc(ctxt->txtTab,
754 ctxt->txtMax * sizeof(ctxt->txtTab[0]));
755 if (ctxt->txtTab == NULL) {
Daniel Veillardcd6ff282003-10-08 22:38:13 +0000756 xmlXIncludeErrMemory(ctxt, NULL, "processing text");
Daniel Veillardd16df9f2001-05-23 13:44:21 +0000757 return;
758 }
759 ctxt->txturlTab = (xmlURL *) xmlRealloc(ctxt->txturlTab,
Daniel Veillardbbc72c32002-09-05 10:52:10 +0000760 ctxt->txtMax * sizeof(ctxt->txturlTab[0]));
Daniel Veillardd16df9f2001-05-23 13:44:21 +0000761 if (ctxt->txturlTab == NULL) {
Daniel Veillardcd6ff282003-10-08 22:38:13 +0000762 xmlXIncludeErrMemory(ctxt, NULL, "processing text");
Daniel Veillardd16df9f2001-05-23 13:44:21 +0000763 return;
764 }
765 }
766 ctxt->txtTab[ctxt->txtNr] = txt;
767 ctxt->txturlTab[ctxt->txtNr] = xmlStrdup(url);
768 ctxt->txtNr++;
769}
770
Owen Taylor3473f882001-02-23 17:55:21 +0000771/************************************************************************
772 * *
Daniel Veillardc5f05ad2002-02-10 11:57:22 +0000773 * Node copy with specific semantic *
774 * *
775 ************************************************************************/
776
777/**
778 * xmlXIncludeCopyNode:
779 * @ctxt: the XInclude context
780 * @target: the document target
781 * @source: the document source
782 * @elem: the element
783 *
784 * Make a copy of the node while preserving the XInclude semantic
785 * of the Infoset copy
786 */
787static xmlNodePtr
788xmlXIncludeCopyNode(xmlXIncludeCtxtPtr ctxt, xmlDocPtr target,
789 xmlDocPtr source, xmlNodePtr elem) {
790 xmlNodePtr result = NULL;
791
792 if ((ctxt == NULL) || (target == NULL) || (source == NULL) ||
793 (elem == NULL))
794 return(NULL);
795 if (elem->type == XML_DTD_NODE)
796 return(NULL);
797 result = xmlDocCopyNode(elem, target, 1);
798 return(result);
799}
800
801/**
802 * xmlXIncludeCopyNodeList:
803 * @ctxt: the XInclude context
804 * @target: the document target
805 * @source: the document source
806 * @elem: the element list
807 *
808 * Make a copy of the node list while preserving the XInclude semantic
809 * of the Infoset copy
810 */
811static xmlNodePtr
812xmlXIncludeCopyNodeList(xmlXIncludeCtxtPtr ctxt, xmlDocPtr target,
813 xmlDocPtr source, xmlNodePtr elem) {
814 xmlNodePtr cur, res, result = NULL, last = NULL;
815
816 if ((ctxt == NULL) || (target == NULL) || (source == NULL) ||
817 (elem == NULL))
818 return(NULL);
819 cur = elem;
820 while (cur != NULL) {
821 res = xmlXIncludeCopyNode(ctxt, target, source, cur);
822 if (res != NULL) {
823 if (result == NULL) {
824 result = last = res;
825 } else {
826 last->next = res;
827 res->prev = last;
828 last = res;
829 }
830 }
831 cur = cur->next;
832 }
833 return(result);
834}
835
836/**
William M. Brack72ee48d2003-12-30 08:30:19 +0000837 * xmlXIncludeGetNthChild:
Daniel Veillardc5f05ad2002-02-10 11:57:22 +0000838 * @cur: the node
839 * @no: the child number
840 *
William M. Brack72ee48d2003-12-30 08:30:19 +0000841 * Returns the @n'th element child of @cur or NULL
Daniel Veillardc5f05ad2002-02-10 11:57:22 +0000842 */
843static xmlNodePtr
844xmlXIncludeGetNthChild(xmlNodePtr cur, int no) {
845 int i;
846 if (cur == NULL)
847 return(cur);
848 cur = cur->children;
849 for (i = 0;i <= no;cur = cur->next) {
850 if (cur == NULL)
851 return(cur);
852 if ((cur->type == XML_ELEMENT_NODE) ||
853 (cur->type == XML_DOCUMENT_NODE) ||
854 (cur->type == XML_HTML_DOCUMENT_NODE)) {
855 i++;
856 if (i == no)
857 break;
858 }
859 }
860 return(cur);
861}
862
William M. Brackf7eb7942003-12-31 07:59:17 +0000863xmlNodePtr xmlXPtrAdvanceNode(xmlNodePtr cur, int *level); /* in xpointer.c */
Daniel Veillardc5f05ad2002-02-10 11:57:22 +0000864/**
865 * xmlXIncludeCopyRange:
866 * @ctxt: the XInclude context
867 * @target: the document target
868 * @source: the document source
869 * @obj: the XPointer result from the evaluation.
870 *
871 * Build a node list tree copy of the XPointer result.
872 *
873 * Returns an xmlNodePtr list or NULL.
William M. Brack72ee48d2003-12-30 08:30:19 +0000874 * The caller has to free the node tree.
Daniel Veillardc5f05ad2002-02-10 11:57:22 +0000875 */
876static xmlNodePtr
877xmlXIncludeCopyRange(xmlXIncludeCtxtPtr ctxt, xmlDocPtr target,
878 xmlDocPtr source, xmlXPathObjectPtr range) {
879 /* pointers to generated nodes */
William M. Brackf7eb7942003-12-31 07:59:17 +0000880 xmlNodePtr list = NULL, last = NULL, listParent = NULL;
881 xmlNodePtr tmp, tmp2;
Daniel Veillardc5f05ad2002-02-10 11:57:22 +0000882 /* pointers to traversal nodes */
883 xmlNodePtr start, cur, end;
884 int index1, index2;
William M. Brack6bdacd72004-02-07 08:53:23 +0000885 int level = 0, lastLevel = 0, endLevel = 0, endFlag = 0;
Daniel Veillardc5f05ad2002-02-10 11:57:22 +0000886
887 if ((ctxt == NULL) || (target == NULL) || (source == NULL) ||
888 (range == NULL))
889 return(NULL);
890 if (range->type != XPATH_RANGE)
891 return(NULL);
892 start = (xmlNodePtr) range->user;
893
894 if (start == NULL)
895 return(NULL);
896 end = range->user2;
897 if (end == NULL)
898 return(xmlDocCopyNode(start, target, 1));
899
900 cur = start;
901 index1 = range->index;
902 index2 = range->index2;
William M. Brackf7eb7942003-12-31 07:59:17 +0000903 /*
904 * level is depth of the current node under consideration
905 * list is the pointer to the root of the output tree
906 * listParent is a pointer to the parent of output tree (within
907 the included file) in case we need to add another level
908 * last is a pointer to the last node added to the output tree
909 * lastLevel is the depth of last (relative to the root)
910 */
Daniel Veillardc5f05ad2002-02-10 11:57:22 +0000911 while (cur != NULL) {
William M. Brackf7eb7942003-12-31 07:59:17 +0000912 /*
913 * Check if our output tree needs a parent
914 */
915 if (level < 0) {
916 while (level < 0) {
William M. Brack57e9e912004-03-09 16:19:02 +0000917 /* copy must include namespaces and properties */
918 tmp2 = xmlDocCopyNode(listParent, target, 2);
William M. Brackf7eb7942003-12-31 07:59:17 +0000919 xmlAddChild(tmp2, list);
920 list = tmp2;
921 listParent = listParent->parent;
922 level++;
923 }
924 last = list;
925 lastLevel = 0;
926 }
927 /*
928 * Check whether we need to change our insertion point
929 */
930 while (level < lastLevel) {
931 last = last->parent;
932 lastLevel --;
933 }
William M. Brack72ee48d2003-12-30 08:30:19 +0000934 if (cur == end) { /* Are we at the end of the range? */
Daniel Veillardc5f05ad2002-02-10 11:57:22 +0000935 if (cur->type == XML_TEXT_NODE) {
936 const xmlChar *content = cur->content;
937 int len;
938
939 if (content == NULL) {
940 tmp = xmlNewTextLen(NULL, 0);
941 } else {
942 len = index2;
943 if ((cur == start) && (index1 > 1)) {
944 content += (index1 - 1);
945 len -= (index1 - 1);
946 index1 = 0;
947 } else {
948 len = index2;
949 }
950 tmp = xmlNewTextLen(content, len);
951 }
952 /* single sub text node selection */
953 if (list == NULL)
954 return(tmp);
955 /* prune and return full set */
William M. Brackf7eb7942003-12-31 07:59:17 +0000956 if (level == lastLevel)
Daniel Veillardc5f05ad2002-02-10 11:57:22 +0000957 xmlAddNextSibling(last, tmp);
958 else
William M. Brackf7eb7942003-12-31 07:59:17 +0000959 xmlAddChild(last, tmp);
Daniel Veillardc5f05ad2002-02-10 11:57:22 +0000960 return(list);
William M. Brack72ee48d2003-12-30 08:30:19 +0000961 } else { /* ending node not a text node */
William M. Brack6bdacd72004-02-07 08:53:23 +0000962 endLevel = level; /* remember the level of the end node */
963 endFlag = 1;
William M. Brack57e9e912004-03-09 16:19:02 +0000964 /* last node - need to take care of properties + namespaces */
965 tmp = xmlDocCopyNode(cur, target, 2);
William M. Brackf7eb7942003-12-31 07:59:17 +0000966 if (list == NULL) {
Daniel Veillardc5f05ad2002-02-10 11:57:22 +0000967 list = tmp;
William M. Brackf7eb7942003-12-31 07:59:17 +0000968 listParent = cur->parent;
969 } else {
970 if (level == lastLevel)
Daniel Veillardc5f05ad2002-02-10 11:57:22 +0000971 xmlAddNextSibling(last, tmp);
William M. Brackf7eb7942003-12-31 07:59:17 +0000972 else {
973 xmlAddChild(last, tmp);
974 lastLevel = level;
975 }
Daniel Veillardc5f05ad2002-02-10 11:57:22 +0000976 }
William M. Brackf7eb7942003-12-31 07:59:17 +0000977 last = tmp;
Daniel Veillardc5f05ad2002-02-10 11:57:22 +0000978
979 if (index2 > 1) {
980 end = xmlXIncludeGetNthChild(cur, index2 - 1);
981 index2 = 0;
982 }
983 if ((cur == start) && (index1 > 1)) {
984 cur = xmlXIncludeGetNthChild(cur, index1 - 1);
985 index1 = 0;
William M. Brack6bdacd72004-02-07 08:53:23 +0000986 } else {
Daniel Veillardc5f05ad2002-02-10 11:57:22 +0000987 cur = cur->children;
988 }
William M. Brack6bdacd72004-02-07 08:53:23 +0000989 level++; /* increment level to show change */
Daniel Veillardc5f05ad2002-02-10 11:57:22 +0000990 /*
991 * Now gather the remaining nodes from cur to end
992 */
William M. Brack6bdacd72004-02-07 08:53:23 +0000993 continue; /* while */
Daniel Veillardc5f05ad2002-02-10 11:57:22 +0000994 }
William M. Brackf7eb7942003-12-31 07:59:17 +0000995 } else if (cur == start) { /* Not at the end, are we at start? */
Daniel Veillardc5f05ad2002-02-10 11:57:22 +0000996 if ((cur->type == XML_TEXT_NODE) ||
997 (cur->type == XML_CDATA_SECTION_NODE)) {
998 const xmlChar *content = cur->content;
999
1000 if (content == NULL) {
1001 tmp = xmlNewTextLen(NULL, 0);
1002 } else {
1003 if (index1 > 1) {
1004 content += (index1 - 1);
William M. Brack72ee48d2003-12-30 08:30:19 +00001005 index1 = 0;
Daniel Veillardc5f05ad2002-02-10 11:57:22 +00001006 }
1007 tmp = xmlNewText(content);
1008 }
1009 last = list = tmp;
William M. Brackf7eb7942003-12-31 07:59:17 +00001010 listParent = cur->parent;
William M. Brack72ee48d2003-12-30 08:30:19 +00001011 } else { /* Not text node */
William M. Brack57e9e912004-03-09 16:19:02 +00001012 /*
1013 * start of the range - need to take care of
1014 * properties and namespaces
1015 */
1016 tmp = xmlDocCopyNode(cur, target, 2);
William M. Brackf7eb7942003-12-31 07:59:17 +00001017 list = last = tmp;
1018 listParent = cur->parent;
William M. Brack72ee48d2003-12-30 08:30:19 +00001019 if (index1 > 1) { /* Do we need to position? */
Daniel Veillardc5f05ad2002-02-10 11:57:22 +00001020 cur = xmlXIncludeGetNthChild(cur, index1 - 1);
William M. Brackf7eb7942003-12-31 07:59:17 +00001021 level = lastLevel = 1;
Daniel Veillardc5f05ad2002-02-10 11:57:22 +00001022 index1 = 0;
1023 /*
1024 * Now gather the remaining nodes from cur to end
1025 */
1026 continue; /* while */
1027 }
Daniel Veillardc5f05ad2002-02-10 11:57:22 +00001028 }
1029 } else {
1030 tmp = NULL;
1031 switch (cur->type) {
1032 case XML_DTD_NODE:
1033 case XML_ELEMENT_DECL:
1034 case XML_ATTRIBUTE_DECL:
1035 case XML_ENTITY_NODE:
1036 /* Do not copy DTD informations */
1037 break;
1038 case XML_ENTITY_DECL:
1039 /* handle crossing entities -> stack needed */
1040 break;
1041 case XML_XINCLUDE_START:
1042 case XML_XINCLUDE_END:
1043 /* don't consider it part of the tree content */
1044 break;
1045 case XML_ATTRIBUTE_NODE:
1046 /* Humm, should not happen ! */
1047 break;
1048 default:
William M. Brack57e9e912004-03-09 16:19:02 +00001049 /*
1050 * Middle of the range - need to take care of
1051 * properties and namespaces
1052 */
1053 tmp = xmlDocCopyNode(cur, target, 2);
Daniel Veillardc5f05ad2002-02-10 11:57:22 +00001054 break;
1055 }
1056 if (tmp != NULL) {
William M. Brackf7eb7942003-12-31 07:59:17 +00001057 if (level == lastLevel)
Daniel Veillardc5f05ad2002-02-10 11:57:22 +00001058 xmlAddNextSibling(last, tmp);
1059 else {
William M. Brackf7eb7942003-12-31 07:59:17 +00001060 xmlAddChild(last, tmp);
1061 lastLevel = level;
Daniel Veillardc5f05ad2002-02-10 11:57:22 +00001062 }
William M. Brackf7eb7942003-12-31 07:59:17 +00001063 last = tmp;
Daniel Veillardc5f05ad2002-02-10 11:57:22 +00001064 }
1065 }
1066 /*
1067 * Skip to next node in document order
1068 */
William M. Brackf7eb7942003-12-31 07:59:17 +00001069 cur = xmlXPtrAdvanceNode(cur, &level);
William M. Brack6bdacd72004-02-07 08:53:23 +00001070 if (endFlag && (level >= endLevel))
1071 break;
Daniel Veillardc5f05ad2002-02-10 11:57:22 +00001072 }
1073 return(list);
1074}
1075
1076/**
1077 * xmlXIncludeBuildNodeList:
1078 * @ctxt: the XInclude context
1079 * @target: the document target
1080 * @source: the document source
1081 * @obj: the XPointer result from the evaluation.
1082 *
1083 * Build a node list tree copy of the XPointer result.
1084 * This will drop Attributes and Namespace declarations.
1085 *
1086 * Returns an xmlNodePtr list or NULL.
1087 * the caller has to free the node tree.
1088 */
1089static xmlNodePtr
1090xmlXIncludeCopyXPointer(xmlXIncludeCtxtPtr ctxt, xmlDocPtr target,
1091 xmlDocPtr source, xmlXPathObjectPtr obj) {
1092 xmlNodePtr list = NULL, last = NULL;
1093 int i;
1094
Daniel Veillardf4b4f982003-02-13 11:02:08 +00001095 if (source == NULL)
1096 source = ctxt->doc;
Daniel Veillardc5f05ad2002-02-10 11:57:22 +00001097 if ((ctxt == NULL) || (target == NULL) || (source == NULL) ||
1098 (obj == NULL))
1099 return(NULL);
1100 switch (obj->type) {
1101 case XPATH_NODESET: {
1102 xmlNodeSetPtr set = obj->nodesetval;
1103 if (set == NULL)
1104 return(NULL);
1105 for (i = 0;i < set->nodeNr;i++) {
1106 if (set->nodeTab[i] == NULL)
1107 continue;
1108 switch (set->nodeTab[i]->type) {
1109 case XML_TEXT_NODE:
1110 case XML_CDATA_SECTION_NODE:
1111 case XML_ELEMENT_NODE:
1112 case XML_ENTITY_REF_NODE:
1113 case XML_ENTITY_NODE:
1114 case XML_PI_NODE:
1115 case XML_COMMENT_NODE:
1116 case XML_DOCUMENT_NODE:
1117 case XML_HTML_DOCUMENT_NODE:
1118#ifdef LIBXML_DOCB_ENABLED
1119 case XML_DOCB_DOCUMENT_NODE:
1120#endif
Daniel Veillardc5f05ad2002-02-10 11:57:22 +00001121 case XML_XINCLUDE_END:
1122 break;
Daniel Veillardf4b4f982003-02-13 11:02:08 +00001123 case XML_XINCLUDE_START: {
1124 xmlNodePtr tmp, cur = set->nodeTab[i];
1125
1126 cur = cur->next;
1127 while (cur != NULL) {
1128 switch(cur->type) {
1129 case XML_TEXT_NODE:
1130 case XML_CDATA_SECTION_NODE:
1131 case XML_ELEMENT_NODE:
1132 case XML_ENTITY_REF_NODE:
1133 case XML_ENTITY_NODE:
1134 case XML_PI_NODE:
1135 case XML_COMMENT_NODE:
1136 tmp = xmlXIncludeCopyNode(ctxt, target,
1137 source, cur);
1138 if (last == NULL) {
1139 list = last = tmp;
1140 } else {
1141 xmlAddNextSibling(last, tmp);
1142 last = tmp;
1143 }
1144 cur = cur->next;
1145 continue;
1146 default:
1147 break;
1148 }
1149 break;
1150 }
1151 continue;
1152 }
Daniel Veillardc5f05ad2002-02-10 11:57:22 +00001153 case XML_ATTRIBUTE_NODE:
1154 case XML_NAMESPACE_DECL:
1155 case XML_DOCUMENT_TYPE_NODE:
1156 case XML_DOCUMENT_FRAG_NODE:
1157 case XML_NOTATION_NODE:
1158 case XML_DTD_NODE:
1159 case XML_ELEMENT_DECL:
1160 case XML_ATTRIBUTE_DECL:
1161 case XML_ENTITY_DECL:
1162 continue; /* for */
1163 }
1164 if (last == NULL)
1165 list = last = xmlXIncludeCopyNode(ctxt, target, source,
1166 set->nodeTab[i]);
1167 else {
1168 xmlAddNextSibling(last,
1169 xmlXIncludeCopyNode(ctxt, target, source,
1170 set->nodeTab[i]));
1171 if (last->next != NULL)
1172 last = last->next;
1173 }
1174 }
1175 break;
1176 }
1177 case XPATH_LOCATIONSET: {
1178 xmlLocationSetPtr set = (xmlLocationSetPtr) obj->user;
1179 if (set == NULL)
1180 return(NULL);
1181 for (i = 0;i < set->locNr;i++) {
1182 if (last == NULL)
1183 list = last = xmlXIncludeCopyXPointer(ctxt, target, source,
1184 set->locTab[i]);
1185 else
1186 xmlAddNextSibling(last,
1187 xmlXIncludeCopyXPointer(ctxt, target, source,
1188 set->locTab[i]));
1189 if (last != NULL) {
1190 while (last->next != NULL)
1191 last = last->next;
1192 }
1193 }
1194 break;
1195 }
Daniel Veillard10acc2f2003-09-01 20:59:40 +00001196#ifdef LIBXML_XPTR_ENABLED
Daniel Veillardc5f05ad2002-02-10 11:57:22 +00001197 case XPATH_RANGE:
1198 return(xmlXIncludeCopyRange(ctxt, target, source, obj));
Daniel Veillard10acc2f2003-09-01 20:59:40 +00001199#endif
Daniel Veillardc5f05ad2002-02-10 11:57:22 +00001200 case XPATH_POINT:
1201 /* points are ignored in XInclude */
1202 break;
1203 default:
1204 break;
1205 }
1206 return(list);
1207}
1208/************************************************************************
1209 * *
Owen Taylor3473f882001-02-23 17:55:21 +00001210 * XInclude I/O handling *
1211 * *
1212 ************************************************************************/
1213
Daniel Veillardf4b4f982003-02-13 11:02:08 +00001214typedef struct _xmlXIncludeMergeData xmlXIncludeMergeData;
1215typedef xmlXIncludeMergeData *xmlXIncludeMergeDataPtr;
1216struct _xmlXIncludeMergeData {
1217 xmlDocPtr doc;
1218 xmlXIncludeCtxtPtr ctxt;
1219};
1220
Owen Taylor3473f882001-02-23 17:55:21 +00001221/**
Daniel Veillard4287c572003-02-04 22:48:53 +00001222 * xmlXIncludeMergeOneEntity:
1223 * @ent: the entity
1224 * @doc: the including doc
1225 * @nr: the entity name
1226 *
1227 * Inplements the merge of one entity
1228 */
1229static void
Daniel Veillardf4b4f982003-02-13 11:02:08 +00001230xmlXIncludeMergeEntity(xmlEntityPtr ent, xmlXIncludeMergeDataPtr data,
Daniel Veillard4287c572003-02-04 22:48:53 +00001231 xmlChar *name ATTRIBUTE_UNUSED) {
Daniel Veillardf4b4f982003-02-13 11:02:08 +00001232 xmlEntityPtr ret, prev;
1233 xmlDocPtr doc;
1234 xmlXIncludeCtxtPtr ctxt;
Daniel Veillard4287c572003-02-04 22:48:53 +00001235
Daniel Veillardf4b4f982003-02-13 11:02:08 +00001236 if ((ent == NULL) || (data == NULL))
Daniel Veillard4287c572003-02-04 22:48:53 +00001237 return;
Daniel Veillardf4b4f982003-02-13 11:02:08 +00001238 ctxt = data->ctxt;
1239 doc = data->doc;
1240 if ((ctxt == NULL) || (doc == NULL))
1241 return;
1242 switch (ent->etype) {
1243 case XML_INTERNAL_PARAMETER_ENTITY:
1244 case XML_EXTERNAL_PARAMETER_ENTITY:
1245 case XML_INTERNAL_PREDEFINED_ENTITY:
1246 return;
1247 case XML_INTERNAL_GENERAL_ENTITY:
1248 case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
1249 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
1250 break;
1251 }
Daniel Veillard4287c572003-02-04 22:48:53 +00001252 ret = xmlAddDocEntity(doc, ent->name, ent->etype, ent->ExternalID,
1253 ent->SystemID, ent->content);
1254 if (ret != NULL) {
1255 if (ent->URI != NULL)
1256 ret->URI = xmlStrdup(ent->URI);
Daniel Veillardf4b4f982003-02-13 11:02:08 +00001257 } else {
1258 prev = xmlGetDocEntity(doc, ent->name);
1259 if (prev != NULL) {
1260 if (ent->etype != prev->etype)
1261 goto error;
1262
1263 if ((ent->SystemID != NULL) && (prev->SystemID != NULL)) {
1264 if (!xmlStrEqual(ent->SystemID, prev->SystemID))
1265 goto error;
Daniel Veillardb6c7f412003-03-29 16:41:55 +00001266 } else if ((ent->ExternalID != NULL) &&
1267 (prev->ExternalID != NULL)) {
Daniel Veillardf4b4f982003-02-13 11:02:08 +00001268 if (!xmlStrEqual(ent->ExternalID, prev->ExternalID))
1269 goto error;
Daniel Veillard2406abd2003-02-24 18:16:47 +00001270 } else if ((ent->content != NULL) && (prev->content != NULL)) {
1271 if (!xmlStrEqual(ent->content, prev->content))
1272 goto error;
Daniel Veillardf4b4f982003-02-13 11:02:08 +00001273 } else {
1274 goto error;
1275 }
1276
1277 }
Daniel Veillard4287c572003-02-04 22:48:53 +00001278 }
Daniel Veillardf4b4f982003-02-13 11:02:08 +00001279 return;
1280error:
Daniel Veillarda507fbf2003-03-31 16:09:37 +00001281 switch (ent->etype) {
1282 case XML_INTERNAL_PARAMETER_ENTITY:
1283 case XML_EXTERNAL_PARAMETER_ENTITY:
1284 case XML_INTERNAL_PREDEFINED_ENTITY:
1285 case XML_INTERNAL_GENERAL_ENTITY:
1286 case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
1287 return;
1288 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
1289 break;
1290 }
Daniel Veillardcd6ff282003-10-08 22:38:13 +00001291 xmlXIncludeErr(ctxt, (xmlNodePtr) ent, XML_XINCLUDE_ENTITY_DEF_MISMATCH,
1292 "mismatch in redefinition of entity %s\n",
1293 ent->name);
Daniel Veillard4287c572003-02-04 22:48:53 +00001294}
1295
1296/**
1297 * xmlXIncludeMergeEntities:
1298 * @ctxt: an XInclude context
1299 * @doc: the including doc
1300 * @from: the included doc
1301 *
1302 * Inplements the entity merge
1303 *
1304 * Returns 0 if merge succeeded, -1 if some processing failed
1305 */
1306static int
1307xmlXIncludeMergeEntities(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc,
1308 xmlDocPtr from) {
1309 xmlNodePtr cur;
1310 xmlDtdPtr target, source;
1311
1312 if (ctxt == NULL)
1313 return(-1);
1314
1315 if ((from == NULL) || (from->intSubset == NULL))
1316 return(0);
1317
1318 target = doc->intSubset;
1319 if (target == NULL) {
1320 cur = xmlDocGetRootElement(doc);
1321 if (cur == NULL)
1322 return(-1);
1323 target = xmlCreateIntSubset(doc, cur->name, NULL, NULL);
1324 if (target == NULL)
1325 return(-1);
1326 }
1327
1328 source = from->intSubset;
1329 if ((source != NULL) && (source->entities != NULL)) {
Daniel Veillardf4b4f982003-02-13 11:02:08 +00001330 xmlXIncludeMergeData data;
1331
1332 data.ctxt = ctxt;
1333 data.doc = doc;
1334
Daniel Veillard4287c572003-02-04 22:48:53 +00001335 xmlHashScan((xmlHashTablePtr) source->entities,
Daniel Veillardf4b4f982003-02-13 11:02:08 +00001336 (xmlHashScanner) xmlXIncludeMergeEntity, &data);
Daniel Veillard4287c572003-02-04 22:48:53 +00001337 }
1338 source = from->extSubset;
1339 if ((source != NULL) && (source->entities != NULL)) {
Daniel Veillardf4b4f982003-02-13 11:02:08 +00001340 xmlXIncludeMergeData data;
1341
1342 data.ctxt = ctxt;
1343 data.doc = doc;
1344
Daniel Veillard4287c572003-02-04 22:48:53 +00001345 /*
1346 * don't duplicate existing stuff when external subsets are the same
1347 */
1348 if ((!xmlStrEqual(target->ExternalID, source->ExternalID)) &&
1349 (!xmlStrEqual(target->SystemID, source->SystemID))) {
1350 xmlHashScan((xmlHashTablePtr) source->entities,
Daniel Veillardf4b4f982003-02-13 11:02:08 +00001351 (xmlHashScanner) xmlXIncludeMergeEntity, &data);
Daniel Veillard4287c572003-02-04 22:48:53 +00001352 }
1353 }
1354 return(0);
1355}
1356
1357/**
Owen Taylor3473f882001-02-23 17:55:21 +00001358 * xmlXIncludeLoadDoc:
1359 * @ctxt: the XInclude context
1360 * @url: the associated URL
1361 * @nr: the xinclude node number
1362 *
1363 * Load the document, and store the result in the XInclude context
Daniel Veillarde3b7d9a2002-08-14 14:11:30 +00001364 *
1365 * Returns 0 in case of success, -1 in case of failure
Owen Taylor3473f882001-02-23 17:55:21 +00001366 */
Daniel Veillarde3b7d9a2002-08-14 14:11:30 +00001367static int
Owen Taylor3473f882001-02-23 17:55:21 +00001368xmlXIncludeLoadDoc(xmlXIncludeCtxtPtr ctxt, const xmlChar *url, int nr) {
1369 xmlDocPtr doc;
1370 xmlURIPtr uri;
1371 xmlChar *URL;
1372 xmlChar *fragment = NULL;
Daniel Veillardbbc72c32002-09-05 10:52:10 +00001373 int i = 0;
William M. Brack4d59e222004-03-08 14:42:31 +00001374#ifdef LIBXML_XPTR_ENABLED
1375 int saveFlags;
1376#endif
Daniel Veillardbbc72c32002-09-05 10:52:10 +00001377
1378#ifdef DEBUG_XINCLUDE
1379 xmlGenericError(xmlGenericErrorContext, "Loading doc %s:%d\n", url, nr);
1380#endif
Owen Taylor3473f882001-02-23 17:55:21 +00001381 /*
1382 * Check the URL and remove any fragment identifier
1383 */
1384 uri = xmlParseURI((const char *)url);
1385 if (uri == NULL) {
Daniel Veillardcd6ff282003-10-08 22:38:13 +00001386 xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
1387 XML_XINCLUDE_HREF_URI,
1388 "invalid value URI %s\n", url);
Daniel Veillarde3b7d9a2002-08-14 14:11:30 +00001389 return(-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001390 }
1391 if (uri->fragment != NULL) {
1392 fragment = (xmlChar *) uri->fragment;
1393 uri->fragment = NULL;
1394 }
Daniel Veillardb98d0822003-12-24 11:06:25 +00001395 if ((ctxt->incTab != NULL) && (ctxt->incTab[nr] != NULL) &&
1396 (ctxt->incTab[nr]->fragment != NULL)) {
1397 if (fragment != NULL) xmlFree(fragment);
1398 fragment = xmlStrdup(ctxt->incTab[nr]->fragment);
1399 }
Owen Taylor3473f882001-02-23 17:55:21 +00001400 URL = xmlSaveUri(uri);
1401 xmlFreeURI(uri);
1402 if (URL == NULL) {
Daniel Veillardcd6ff282003-10-08 22:38:13 +00001403 xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
1404 XML_XINCLUDE_HREF_URI,
1405 "invalid value URI %s\n", url);
Owen Taylor3473f882001-02-23 17:55:21 +00001406 if (fragment != NULL)
1407 xmlFree(fragment);
Daniel Veillarde3b7d9a2002-08-14 14:11:30 +00001408 return(-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001409 }
1410
1411 /*
1412 * Handling of references to the local document are done
1413 * directly through ctxt->doc.
1414 */
Daniel Veillardf4b4f982003-02-13 11:02:08 +00001415 if ((URL[0] == 0) || (URL[0] == '#') ||
1416 ((ctxt->doc != NULL) && (xmlStrEqual(URL, ctxt->doc->URL)))) {
Owen Taylor3473f882001-02-23 17:55:21 +00001417 doc = NULL;
1418 goto loaded;
1419 }
1420
1421 /*
1422 * Prevent reloading twice the document.
1423 */
Daniel Veillardbbc72c32002-09-05 10:52:10 +00001424 for (i = 0; i < ctxt->incNr; i++) {
1425 if ((xmlStrEqual(URL, ctxt->incTab[i]->URI)) &&
1426 (ctxt->incTab[i]->doc != NULL)) {
1427 doc = ctxt->incTab[i]->doc;
1428#ifdef DEBUG_XINCLUDE
1429 printf("Already loaded %s\n", URL);
1430#endif
Owen Taylor3473f882001-02-23 17:55:21 +00001431 goto loaded;
1432 }
1433 }
Daniel Veillardbbc72c32002-09-05 10:52:10 +00001434
Owen Taylor3473f882001-02-23 17:55:21 +00001435 /*
1436 * Load it.
1437 */
Daniel Veillardbbc72c32002-09-05 10:52:10 +00001438#ifdef DEBUG_XINCLUDE
1439 printf("loading %s\n", URL);
1440#endif
William M. Brack4d59e222004-03-08 14:42:31 +00001441#ifdef LIBXML_XPTR_ENABLED
1442 /*
1443 * If this is an XPointer evaluation, we want to assure that
1444 * all entities have been resolved prior to processing the
1445 * referenced document
1446 */
1447 saveFlags = ctxt->parseFlags;
1448 if (fragment != NULL) { /* if this is an XPointer eval */
1449 ctxt->parseFlags |= XML_PARSE_NOENT;
1450 }
1451#endif
1452
Daniel Veillard98485322003-08-14 15:44:40 +00001453 doc = xmlXIncludeParseFile(ctxt, (const char *)URL);
William M. Brack4d59e222004-03-08 14:42:31 +00001454#ifdef LIBXML_XPTR_ENABLED
1455 ctxt->parseFlags = saveFlags;
1456#endif
Owen Taylor3473f882001-02-23 17:55:21 +00001457 if (doc == NULL) {
Owen Taylor3473f882001-02-23 17:55:21 +00001458 xmlFree(URL);
1459 if (fragment != NULL)
1460 xmlFree(fragment);
Daniel Veillarde3b7d9a2002-08-14 14:11:30 +00001461 return(-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001462 }
Daniel Veillardbbc72c32002-09-05 10:52:10 +00001463 ctxt->incTab[nr]->doc = doc;
Daniel Veillard98485322003-08-14 15:44:40 +00001464 for (i = nr + 1; i < ctxt->incNr; i++) {
1465 if (xmlStrEqual(URL, ctxt->incTab[i]->URI)) {
1466 ctxt->incTab[nr]->count++;
1467#ifdef DEBUG_XINCLUDE
1468 printf("Increasing %s count since reused\n", URL);
1469#endif
1470 break;
1471 }
1472 }
Daniel Veillardbbc72c32002-09-05 10:52:10 +00001473
1474 /*
Daniel Veillard4287c572003-02-04 22:48:53 +00001475 * Make sure we have all entities fixed up
Daniel Veillardbbc72c32002-09-05 10:52:10 +00001476 */
Daniel Veillard4287c572003-02-04 22:48:53 +00001477 xmlXIncludeMergeEntities(ctxt, ctxt->doc, doc);
Daniel Veillardbbc72c32002-09-05 10:52:10 +00001478
1479 /*
1480 * We don't need the DTD anymore, free up space
1481 if (doc->intSubset != NULL) {
1482 xmlUnlinkNode((xmlNodePtr) doc->intSubset);
1483 xmlFreeNode((xmlNodePtr) doc->intSubset);
1484 doc->intSubset = NULL;
1485 }
1486 if (doc->extSubset != NULL) {
1487 xmlUnlinkNode((xmlNodePtr) doc->extSubset);
1488 xmlFreeNode((xmlNodePtr) doc->extSubset);
1489 doc->extSubset = NULL;
1490 }
1491 */
1492 xmlXIncludeRecurseDoc(ctxt, doc, URL);
Owen Taylor3473f882001-02-23 17:55:21 +00001493
1494loaded:
1495 if (fragment == NULL) {
1496 /*
1497 * Add the top children list as the replacement copy.
Owen Taylor3473f882001-02-23 17:55:21 +00001498 */
1499 if (doc == NULL)
Daniel Veillard4497e692001-06-09 14:19:02 +00001500 {
1501 /* Hopefully a DTD declaration won't be copied from
1502 * the same document */
Daniel Veillardbbc72c32002-09-05 10:52:10 +00001503 ctxt->incTab[nr]->inc = xmlCopyNodeList(ctxt->doc->children);
Daniel Veillard4497e692001-06-09 14:19:02 +00001504 } else {
Daniel Veillardbbc72c32002-09-05 10:52:10 +00001505 ctxt->incTab[nr]->inc = xmlXIncludeCopyNodeList(ctxt, ctxt->doc,
Daniel Veillardc5f05ad2002-02-10 11:57:22 +00001506 doc, doc->children);
Daniel Veillard4497e692001-06-09 14:19:02 +00001507 }
Daniel Veillard10acc2f2003-09-01 20:59:40 +00001508 }
1509#ifdef LIBXML_XPTR_ENABLED
1510 else {
Owen Taylor3473f882001-02-23 17:55:21 +00001511 /*
1512 * Computes the XPointer expression and make a copy used
1513 * as the replacement copy.
1514 */
1515 xmlXPathObjectPtr xptr;
1516 xmlXPathContextPtr xptrctxt;
Daniel Veillard39196eb2001-06-19 18:09:42 +00001517 xmlNodeSetPtr set;
Owen Taylor3473f882001-02-23 17:55:21 +00001518
1519 if (doc == NULL) {
Daniel Veillardbbc72c32002-09-05 10:52:10 +00001520 xptrctxt = xmlXPtrNewContext(ctxt->doc, ctxt->incTab[nr]->ref,
1521 NULL);
Owen Taylor3473f882001-02-23 17:55:21 +00001522 } else {
1523 xptrctxt = xmlXPtrNewContext(doc, NULL, NULL);
1524 }
1525 if (xptrctxt == NULL) {
Daniel Veillardcd6ff282003-10-08 22:38:13 +00001526 xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
1527 XML_XINCLUDE_XPTR_FAILED,
Daniel Veillarda152c4d2003-11-19 16:24:26 +00001528 "could not create XPointer context\n", NULL);
Owen Taylor3473f882001-02-23 17:55:21 +00001529 xmlFree(URL);
1530 xmlFree(fragment);
Daniel Veillarde3b7d9a2002-08-14 14:11:30 +00001531 return(-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001532 }
1533 xptr = xmlXPtrEval(fragment, xptrctxt);
1534 if (xptr == NULL) {
Daniel Veillardcd6ff282003-10-08 22:38:13 +00001535 xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
1536 XML_XINCLUDE_XPTR_FAILED,
1537 "XPointer evaluation failed: #%s\n",
1538 fragment);
Owen Taylor3473f882001-02-23 17:55:21 +00001539 xmlXPathFreeContext(xptrctxt);
1540 xmlFree(URL);
1541 xmlFree(fragment);
Daniel Veillarde3b7d9a2002-08-14 14:11:30 +00001542 return(-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001543 }
Daniel Veillard39196eb2001-06-19 18:09:42 +00001544 switch (xptr->type) {
1545 case XPATH_UNDEFINED:
1546 case XPATH_BOOLEAN:
1547 case XPATH_NUMBER:
1548 case XPATH_STRING:
1549 case XPATH_POINT:
1550 case XPATH_USERS:
1551 case XPATH_XSLT_TREE:
Daniel Veillardcd6ff282003-10-08 22:38:13 +00001552 xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
1553 XML_XINCLUDE_XPTR_RESULT,
1554 "XPointer is not a range: #%s\n",
1555 fragment);
Daniel Veillard39196eb2001-06-19 18:09:42 +00001556 xmlXPathFreeContext(xptrctxt);
1557 xmlFree(URL);
1558 xmlFree(fragment);
Daniel Veillarde3b7d9a2002-08-14 14:11:30 +00001559 return(-1);
Daniel Veillard39196eb2001-06-19 18:09:42 +00001560 case XPATH_NODESET:
Daniel Veillard798ae542003-11-03 17:13:52 +00001561 if ((xptr->nodesetval == NULL) ||
1562 (xptr->nodesetval->nodeNr <= 0)) {
1563 xmlXPathFreeContext(xptrctxt);
1564 xmlFree(URL);
1565 xmlFree(fragment);
1566 return(-1);
1567 }
Daniel Veillard39196eb2001-06-19 18:09:42 +00001568 case XPATH_RANGE:
1569 case XPATH_LOCATIONSET:
1570 break;
1571 }
1572 set = xptr->nodesetval;
1573 if (set != NULL) {
1574 for (i = 0;i < set->nodeNr;i++) {
1575 if (set->nodeTab[i] == NULL)
1576 continue;
1577 switch (set->nodeTab[i]->type) {
1578 case XML_TEXT_NODE:
1579 case XML_CDATA_SECTION_NODE:
1580 case XML_ELEMENT_NODE:
1581 case XML_ENTITY_REF_NODE:
1582 case XML_ENTITY_NODE:
1583 case XML_PI_NODE:
1584 case XML_COMMENT_NODE:
1585 case XML_DOCUMENT_NODE:
1586 case XML_HTML_DOCUMENT_NODE:
1587#ifdef LIBXML_DOCB_ENABLED
1588 case XML_DOCB_DOCUMENT_NODE:
1589#endif
1590 continue;
1591 case XML_ATTRIBUTE_NODE:
Daniel Veillardcd6ff282003-10-08 22:38:13 +00001592 xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
1593 XML_XINCLUDE_XPTR_RESULT,
1594 "XPointer selects an attribute: #%s\n",
1595 fragment);
Daniel Veillard39196eb2001-06-19 18:09:42 +00001596 set->nodeTab[i] = NULL;
1597 continue;
1598 case XML_NAMESPACE_DECL:
Daniel Veillardcd6ff282003-10-08 22:38:13 +00001599 xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
1600 XML_XINCLUDE_XPTR_RESULT,
1601 "XPointer selects a namespace: #%s\n",
1602 fragment);
Daniel Veillard39196eb2001-06-19 18:09:42 +00001603 set->nodeTab[i] = NULL;
1604 continue;
1605 case XML_DOCUMENT_TYPE_NODE:
1606 case XML_DOCUMENT_FRAG_NODE:
1607 case XML_NOTATION_NODE:
1608 case XML_DTD_NODE:
1609 case XML_ELEMENT_DECL:
1610 case XML_ATTRIBUTE_DECL:
1611 case XML_ENTITY_DECL:
1612 case XML_XINCLUDE_START:
1613 case XML_XINCLUDE_END:
Daniel Veillardcd6ff282003-10-08 22:38:13 +00001614 xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
1615 XML_XINCLUDE_XPTR_RESULT,
1616 "XPointer selects unexpected nodes: #%s\n",
1617 fragment);
Daniel Veillard39196eb2001-06-19 18:09:42 +00001618 set->nodeTab[i] = NULL;
1619 set->nodeTab[i] = NULL;
1620 continue; /* for */
1621 }
1622 }
1623 }
Daniel Veillardf4b4f982003-02-13 11:02:08 +00001624 if (doc == NULL) {
1625 ctxt->incTab[nr]->xptr = xptr;
1626 ctxt->incTab[nr]->inc = NULL;
1627 } else {
1628 ctxt->incTab[nr]->inc =
1629 xmlXIncludeCopyXPointer(ctxt, ctxt->doc, doc, xptr);
1630 xmlXPathFreeObject(xptr);
1631 }
Owen Taylor3473f882001-02-23 17:55:21 +00001632 xmlXPathFreeContext(xptrctxt);
1633 xmlFree(fragment);
1634 }
Daniel Veillard10acc2f2003-09-01 20:59:40 +00001635#endif
Daniel Veillardc4bad4a2002-08-14 14:45:25 +00001636
1637 /*
1638 * Do the xml:base fixup if needed
1639 */
1640 if ((doc != NULL) && (URL != NULL) && (xmlStrchr(URL, (xmlChar) '/'))) {
1641 xmlNodePtr node;
1642
Daniel Veillardbbc72c32002-09-05 10:52:10 +00001643 node = ctxt->incTab[nr]->inc;
Daniel Veillardc4bad4a2002-08-14 14:45:25 +00001644 while (node != NULL) {
1645 if (node->type == XML_ELEMENT_NODE)
1646 xmlNodeSetBase(node, URL);
1647 node = node->next;
1648 }
1649 }
Daniel Veillardbbc72c32002-09-05 10:52:10 +00001650 if ((nr < ctxt->incNr) && (ctxt->incTab[nr]->doc != NULL) &&
1651 (ctxt->incTab[nr]->count <= 1)) {
1652#ifdef DEBUG_XINCLUDE
1653 printf("freeing %s\n", ctxt->incTab[nr]->doc->URL);
1654#endif
1655 xmlFreeDoc(ctxt->incTab[nr]->doc);
1656 ctxt->incTab[nr]->doc = NULL;
1657 }
Owen Taylor3473f882001-02-23 17:55:21 +00001658 xmlFree(URL);
Daniel Veillarde3b7d9a2002-08-14 14:11:30 +00001659 return(0);
Owen Taylor3473f882001-02-23 17:55:21 +00001660}
1661
1662/**
1663 * xmlXIncludeLoadTxt:
1664 * @ctxt: the XInclude context
1665 * @url: the associated URL
1666 * @nr: the xinclude node number
1667 *
1668 * Load the content, and store the result in the XInclude context
Daniel Veillarde3b7d9a2002-08-14 14:11:30 +00001669 *
1670 * Returns 0 in case of success, -1 in case of failure
Owen Taylor3473f882001-02-23 17:55:21 +00001671 */
Daniel Veillarde3b7d9a2002-08-14 14:11:30 +00001672static int
Owen Taylor3473f882001-02-23 17:55:21 +00001673xmlXIncludeLoadTxt(xmlXIncludeCtxtPtr ctxt, const xmlChar *url, int nr) {
1674 xmlParserInputBufferPtr buf;
1675 xmlNodePtr node;
1676 xmlURIPtr uri;
1677 xmlChar *URL;
1678 int i;
Daniel Veillardd076a202002-11-20 13:28:31 +00001679 xmlChar *encoding = NULL;
William M. Brack78637da2003-07-31 14:47:38 +00001680 xmlCharEncoding enc = (xmlCharEncoding) 0;
Daniel Veillardd076a202002-11-20 13:28:31 +00001681
Owen Taylor3473f882001-02-23 17:55:21 +00001682 /*
1683 * Check the URL and remove any fragment identifier
1684 */
1685 uri = xmlParseURI((const char *)url);
1686 if (uri == NULL) {
Daniel Veillardcd6ff282003-10-08 22:38:13 +00001687 xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref, XML_XINCLUDE_HREF_URI,
1688 "invalid value URI %s\n", url);
Daniel Veillarde3b7d9a2002-08-14 14:11:30 +00001689 return(-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001690 }
1691 if (uri->fragment != NULL) {
Daniel Veillardcd6ff282003-10-08 22:38:13 +00001692 xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref, XML_XINCLUDE_TEXT_FRAGMENT,
1693 "fragment identifier forbidden for text: %s\n",
1694 (const xmlChar *) uri->fragment);
Owen Taylor3473f882001-02-23 17:55:21 +00001695 xmlFreeURI(uri);
Daniel Veillarde3b7d9a2002-08-14 14:11:30 +00001696 return(-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001697 }
1698 URL = xmlSaveUri(uri);
1699 xmlFreeURI(uri);
1700 if (URL == NULL) {
Daniel Veillardcd6ff282003-10-08 22:38:13 +00001701 xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref, XML_XINCLUDE_HREF_URI,
1702 "invalid value URI %s\n", url);
Daniel Veillarde3b7d9a2002-08-14 14:11:30 +00001703 return(-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001704 }
1705
1706 /*
1707 * Handling of references to the local document are done
1708 * directly through ctxt->doc.
1709 */
1710 if (URL[0] == 0) {
Daniel Veillardcd6ff282003-10-08 22:38:13 +00001711 xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
1712 XML_XINCLUDE_TEXT_DOCUMENT,
1713 "text serialization of document not available\n", NULL);
Owen Taylor3473f882001-02-23 17:55:21 +00001714 xmlFree(URL);
Daniel Veillarde3b7d9a2002-08-14 14:11:30 +00001715 return(-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001716 }
1717
1718 /*
1719 * Prevent reloading twice the document.
1720 */
1721 for (i = 0; i < ctxt->txtNr; i++) {
1722 if (xmlStrEqual(URL, ctxt->txturlTab[i])) {
1723 node = xmlCopyNode(ctxt->txtTab[i], 1);
1724 goto loaded;
1725 }
1726 }
1727 /*
Daniel Veillardd076a202002-11-20 13:28:31 +00001728 * Try to get the encoding if available
Owen Taylor3473f882001-02-23 17:55:21 +00001729 */
Daniel Veillardd076a202002-11-20 13:28:31 +00001730 if ((ctxt->incTab[nr] != NULL) && (ctxt->incTab[nr]->ref != NULL)) {
1731 encoding = xmlGetProp(ctxt->incTab[nr]->ref, XINCLUDE_PARSE_ENCODING);
1732 }
1733 if (encoding != NULL) {
1734 /*
1735 * TODO: we should not have to remap to the xmlCharEncoding
1736 * predefined set, a better interface than
1737 * xmlParserInputBufferCreateFilename should allow any
1738 * encoding supported by iconv
1739 */
1740 enc = xmlParseCharEncoding((const char *) encoding);
1741 if (enc == XML_CHAR_ENCODING_ERROR) {
Daniel Veillardcd6ff282003-10-08 22:38:13 +00001742 xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
1743 XML_XINCLUDE_UNKNOWN_ENCODING,
1744 "encoding %s not supported\n", encoding);
Daniel Veillardd076a202002-11-20 13:28:31 +00001745 xmlFree(encoding);
1746 xmlFree(URL);
1747 return(-1);
1748 }
1749 xmlFree(encoding);
1750 }
1751
1752 /*
1753 * Load it.
1754 */
1755 buf = xmlParserInputBufferCreateFilename((const char *)URL, enc);
Owen Taylor3473f882001-02-23 17:55:21 +00001756 if (buf == NULL) {
Owen Taylor3473f882001-02-23 17:55:21 +00001757 xmlFree(URL);
Daniel Veillarde3b7d9a2002-08-14 14:11:30 +00001758 return(-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001759 }
1760 node = xmlNewText(NULL);
1761
1762 /*
1763 * Scan all chars from the resource and add the to the node
1764 */
1765 while (xmlParserInputBufferRead(buf, 128) > 0) {
1766 int len;
1767 const xmlChar *content;
1768
1769 content = xmlBufferContent(buf->buffer);
1770 len = xmlBufferLength(buf->buffer);
Daniel Veillardd076a202002-11-20 13:28:31 +00001771 for (i = 0;i < len;) {
1772 int cur;
1773 int l;
1774
1775 cur = xmlStringCurrentChar(NULL, &content[i], &l);
1776 if (!IS_CHAR(cur)) {
Daniel Veillardcd6ff282003-10-08 22:38:13 +00001777 xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
1778 XML_XINCLUDE_INVALID_CHAR,
1779 "%s contains invalid char\n", URL);
Owen Taylor3473f882001-02-23 17:55:21 +00001780 } else {
Daniel Veillardd076a202002-11-20 13:28:31 +00001781 xmlNodeAddContentLen(node, &content[i], l);
Owen Taylor3473f882001-02-23 17:55:21 +00001782 }
Daniel Veillardd076a202002-11-20 13:28:31 +00001783 i += l;
Owen Taylor3473f882001-02-23 17:55:21 +00001784 }
1785 xmlBufferShrink(buf->buffer, len);
1786 }
1787 xmlFreeParserInputBuffer(buf);
1788 xmlXIncludeAddTxt(ctxt, node, URL);
1789
1790loaded:
1791 /*
1792 * Add the element as the replacement copy.
1793 */
Daniel Veillardbbc72c32002-09-05 10:52:10 +00001794 ctxt->incTab[nr]->inc = node;
Owen Taylor3473f882001-02-23 17:55:21 +00001795 xmlFree(URL);
Daniel Veillarde3b7d9a2002-08-14 14:11:30 +00001796 return(0);
1797}
1798
1799/**
1800 * xmlXIncludeLoadFallback:
1801 * @ctxt: the XInclude context
1802 * @fallback: the fallback node
1803 * @nr: the xinclude node number
1804 *
Daniel Veillardbbc72c32002-09-05 10:52:10 +00001805 * Load the content of the fallback node, and store the result
Daniel Veillarde3b7d9a2002-08-14 14:11:30 +00001806 * in the XInclude context
1807 *
1808 * Returns 0 in case of success, -1 in case of failure
1809 */
1810static int
1811xmlXIncludeLoadFallback(xmlXIncludeCtxtPtr ctxt, xmlNodePtr fallback, int nr) {
William M. Brackaae10522004-01-02 14:59:41 +00001812 xmlXIncludeCtxtPtr newctxt;
1813 int ret = 0;
1814
Daniel Veillarde3b7d9a2002-08-14 14:11:30 +00001815 if ((fallback == NULL) || (ctxt == NULL))
1816 return(-1);
William M. Brackef245fd2004-02-06 09:33:59 +00001817 if (fallback->children != NULL) {
1818 /*
1819 * It's possible that the fallback also has 'includes'
1820 * (Bug 129969), so we re-process the fallback just in case
1821 */
1822 newctxt = xmlXIncludeNewContext(ctxt->doc);
1823 if (newctxt == NULL)
1824 return (-1);
1825 xmlXIncludeSetFlags(newctxt, ctxt->parseFlags);
1826 ret = xmlXIncludeDoProcess(newctxt, ctxt->doc, fallback->children);
1827 if ((ret >=0) && (ctxt->nbErrors > 0))
1828 ret = -1;
1829 xmlXIncludeFreeContext(newctxt);
Daniel Veillarde3b7d9a2002-08-14 14:11:30 +00001830
William M. Brackef245fd2004-02-06 09:33:59 +00001831 ctxt->incTab[nr]->inc = xmlCopyNodeList(fallback->children);
1832 } else {
1833 ctxt->incTab[nr]->inc = NULL;
William M. Brack95af5942004-02-08 04:12:49 +00001834 ctxt->incTab[nr]->emptyFb = 1; /* flag empty callback */
William M. Brackef245fd2004-02-06 09:33:59 +00001835 }
William M. Brackaae10522004-01-02 14:59:41 +00001836 return(ret);
Owen Taylor3473f882001-02-23 17:55:21 +00001837}
1838
1839/************************************************************************
1840 * *
1841 * XInclude Processing *
1842 * *
1843 ************************************************************************/
1844
1845/**
1846 * xmlXIncludePreProcessNode:
1847 * @ctxt: an XInclude context
1848 * @node: an XInclude node
1849 *
Daniel Veillardd16df9f2001-05-23 13:44:21 +00001850 * Implement the XInclude preprocessing, currently just adding the element
1851 * for further processing.
Owen Taylor3473f882001-02-23 17:55:21 +00001852 *
1853 * Returns the result list or NULL in case of error
1854 */
Daniel Veillard56a4cb82001-03-24 17:00:36 +00001855static xmlNodePtr
Owen Taylor3473f882001-02-23 17:55:21 +00001856xmlXIncludePreProcessNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node) {
1857 xmlXIncludeAddNode(ctxt, node);
1858 return(0);
1859}
1860
Daniel Veillardbbc72c32002-09-05 10:52:10 +00001861/**
Owen Taylor3473f882001-02-23 17:55:21 +00001862 * xmlXIncludeLoadNode:
1863 * @ctxt: an XInclude context
1864 * @nr: the node number
1865 *
1866 * Find and load the infoset replacement for the given node.
1867 *
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001868 * Returns 0 if substitution succeeded, -1 if some processing failed
Owen Taylor3473f882001-02-23 17:55:21 +00001869 */
Daniel Veillard56a4cb82001-03-24 17:00:36 +00001870static int
Owen Taylor3473f882001-02-23 17:55:21 +00001871xmlXIncludeLoadNode(xmlXIncludeCtxtPtr ctxt, int nr) {
1872 xmlNodePtr cur;
1873 xmlChar *href;
1874 xmlChar *parse;
1875 xmlChar *base;
1876 xmlChar *URI;
1877 int xml = 1; /* default Issue 64 */
Daniel Veillarde3b7d9a2002-08-14 14:11:30 +00001878 int ret;
Owen Taylor3473f882001-02-23 17:55:21 +00001879
1880 if (ctxt == NULL)
1881 return(-1);
1882 if ((nr < 0) || (nr >= ctxt->incNr))
1883 return(-1);
Daniel Veillardbbc72c32002-09-05 10:52:10 +00001884 cur = ctxt->incTab[nr]->ref;
Owen Taylor3473f882001-02-23 17:55:21 +00001885 if (cur == NULL)
1886 return(-1);
1887
Owen Taylor3473f882001-02-23 17:55:21 +00001888 /*
1889 * read the attributes
1890 */
Daniel Veillardb5fa0202003-12-08 17:41:29 +00001891 href = xmlXIncludeGetProp(ctxt, cur, XINCLUDE_HREF);
Owen Taylor3473f882001-02-23 17:55:21 +00001892 if (href == NULL) {
Daniel Veillard03c2f0a2004-01-25 19:54:59 +00001893 href = xmlStrdup(BAD_CAST ""); /* @@@@ href is now optional */
1894 if (href == NULL)
1895 return(-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001896 }
Daniel Veillardb5fa0202003-12-08 17:41:29 +00001897 parse = xmlXIncludeGetProp(ctxt, cur, XINCLUDE_PARSE);
Owen Taylor3473f882001-02-23 17:55:21 +00001898 if (parse != NULL) {
1899 if (xmlStrEqual(parse, XINCLUDE_PARSE_XML))
1900 xml = 1;
1901 else if (xmlStrEqual(parse, XINCLUDE_PARSE_TEXT))
1902 xml = 0;
1903 else {
Daniel Veillardcd6ff282003-10-08 22:38:13 +00001904 xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
1905 XML_XINCLUDE_PARSE_VALUE,
1906 "invalid value %s for 'parse'\n", parse);
Owen Taylor3473f882001-02-23 17:55:21 +00001907 if (href != NULL)
1908 xmlFree(href);
1909 if (parse != NULL)
1910 xmlFree(parse);
1911 return(-1);
1912 }
1913 }
1914
1915 /*
1916 * compute the URI
1917 */
1918 base = xmlNodeGetBase(ctxt->doc, cur);
1919 if (base == NULL) {
1920 URI = xmlBuildURI(href, ctxt->doc->URL);
1921 } else {
1922 URI = xmlBuildURI(href, base);
1923 }
1924 if (URI == NULL) {
1925 xmlChar *escbase;
1926 xmlChar *eschref;
1927 /*
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001928 * Some escaping may be needed
Owen Taylor3473f882001-02-23 17:55:21 +00001929 */
1930 escbase = xmlURIEscape(base);
1931 eschref = xmlURIEscape(href);
1932 URI = xmlBuildURI(eschref, escbase);
1933 if (escbase != NULL)
1934 xmlFree(escbase);
1935 if (eschref != NULL)
1936 xmlFree(eschref);
1937 }
1938 if (URI == NULL) {
Daniel Veillardcd6ff282003-10-08 22:38:13 +00001939 xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
1940 XML_XINCLUDE_HREF_URI, "failed build URL\n", NULL);
Owen Taylor3473f882001-02-23 17:55:21 +00001941 if (parse != NULL)
1942 xmlFree(parse);
1943 if (href != NULL)
1944 xmlFree(href);
1945 if (base != NULL)
1946 xmlFree(base);
1947 return(-1);
1948 }
1949#ifdef DEBUG_XINCLUDE
1950 xmlGenericError(xmlGenericErrorContext, "parse: %s\n",
1951 xml ? "xml": "text");
1952 xmlGenericError(xmlGenericErrorContext, "URI: %s\n", URI);
1953#endif
1954
1955 /*
1956 * Cleanup
1957 */
1958 if (xml) {
Daniel Veillarde3b7d9a2002-08-14 14:11:30 +00001959 ret = xmlXIncludeLoadDoc(ctxt, URI, nr);
Owen Taylor3473f882001-02-23 17:55:21 +00001960 /* xmlXIncludeGetFragment(ctxt, cur, URI); */
1961 } else {
Daniel Veillarde3b7d9a2002-08-14 14:11:30 +00001962 ret = xmlXIncludeLoadTxt(ctxt, URI, nr);
1963 }
1964 if (ret < 0) {
1965 xmlNodePtr children;
1966
1967 /*
1968 * Time to try a fallback if availble
1969 */
1970#ifdef DEBUG_XINCLUDE
1971 xmlGenericError(xmlGenericErrorContext, "error looking for fallback\n");
1972#endif
1973 children = cur->children;
1974 while (children != NULL) {
1975 if ((children->type == XML_ELEMENT_NODE) &&
1976 (children->ns != NULL) &&
1977 (xmlStrEqual(children->name, XINCLUDE_FALLBACK)) &&
Daniel Veillardb5fa0202003-12-08 17:41:29 +00001978 ((xmlStrEqual(children->ns->href, XINCLUDE_NS)) ||
1979 (xmlStrEqual(children->ns->href, XINCLUDE_OLD_NS)))) {
Daniel Veillarde3b7d9a2002-08-14 14:11:30 +00001980 ret = xmlXIncludeLoadFallback(ctxt, children, nr);
William M. Brack1ff42132003-12-31 14:05:15 +00001981 if (ret == 0)
Daniel Veillarde3b7d9a2002-08-14 14:11:30 +00001982 break;
1983 }
1984 children = children->next;
1985 }
1986 }
1987 if (ret < 0) {
Daniel Veillardcd6ff282003-10-08 22:38:13 +00001988 xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
1989 XML_XINCLUDE_NO_FALLBACK,
1990 "could not load %s, and no fallback was found\n",
1991 URI);
Owen Taylor3473f882001-02-23 17:55:21 +00001992 }
1993
1994 /*
1995 * Cleanup
1996 */
1997 if (URI != NULL)
1998 xmlFree(URI);
1999 if (parse != NULL)
2000 xmlFree(parse);
2001 if (href != NULL)
2002 xmlFree(href);
2003 if (base != NULL)
2004 xmlFree(base);
2005 return(0);
2006}
2007
2008/**
2009 * xmlXIncludeIncludeNode:
2010 * @ctxt: an XInclude context
2011 * @nr: the node number
2012 *
2013 * Inplement the infoset replacement for the given node
2014 *
Daniel Veillardcbaf3992001-12-31 16:16:02 +00002015 * Returns 0 if substitution succeeded, -1 if some processing failed
Owen Taylor3473f882001-02-23 17:55:21 +00002016 */
Daniel Veillard56a4cb82001-03-24 17:00:36 +00002017static int
Owen Taylor3473f882001-02-23 17:55:21 +00002018xmlXIncludeIncludeNode(xmlXIncludeCtxtPtr ctxt, int nr) {
Daniel Veillardf4b4f982003-02-13 11:02:08 +00002019 xmlNodePtr cur, end, list, tmp;
Owen Taylor3473f882001-02-23 17:55:21 +00002020
2021 if (ctxt == NULL)
2022 return(-1);
2023 if ((nr < 0) || (nr >= ctxt->incNr))
2024 return(-1);
Daniel Veillardbbc72c32002-09-05 10:52:10 +00002025 cur = ctxt->incTab[nr]->ref;
Owen Taylor3473f882001-02-23 17:55:21 +00002026 if (cur == NULL)
2027 return(-1);
2028
2029 /*
Daniel Veillardf4b4f982003-02-13 11:02:08 +00002030 * If we stored an XPointer a late computation may be needed
2031 */
2032 if ((ctxt->incTab[nr]->inc == NULL) &&
2033 (ctxt->incTab[nr]->xptr != NULL)) {
2034 ctxt->incTab[nr]->inc =
2035 xmlXIncludeCopyXPointer(ctxt, ctxt->doc, ctxt->doc,
2036 ctxt->incTab[nr]->xptr);
2037 xmlXPathFreeObject(ctxt->incTab[nr]->xptr);
2038 ctxt->incTab[nr]->xptr = NULL;
2039 }
2040 list = ctxt->incTab[nr]->inc;
2041 ctxt->incTab[nr]->inc = NULL;
2042
2043 /*
2044 * Check against the risk of generating a multi-rooted document
2045 */
2046 if ((cur->parent != NULL) &&
2047 (cur->parent->type != XML_ELEMENT_NODE)) {
2048 int nb_elem = 0;
2049
2050 tmp = list;
2051 while (tmp != NULL) {
2052 if (tmp->type == XML_ELEMENT_NODE)
2053 nb_elem++;
2054 tmp = tmp->next;
2055 }
2056 if (nb_elem > 1) {
Daniel Veillardcd6ff282003-10-08 22:38:13 +00002057 xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
2058 XML_XINCLUDE_MULTIPLE_ROOT,
2059 "XInclude error: would result in multiple root nodes\n",
2060 NULL);
Daniel Veillardf4b4f982003-02-13 11:02:08 +00002061 return(-1);
2062 }
2063 }
2064
2065 /*
Owen Taylor3473f882001-02-23 17:55:21 +00002066 * Change the current node as an XInclude start one, and add an
2067 * entity end one
2068 */
2069 cur->type = XML_XINCLUDE_START;
2070 end = xmlNewNode(cur->ns, cur->name);
2071 if (end == NULL) {
Daniel Veillardcd6ff282003-10-08 22:38:13 +00002072 xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref, XML_XINCLUDE_BUILD_FAILED,
2073 "failed to build node\n", NULL);
Owen Taylor3473f882001-02-23 17:55:21 +00002074 return(-1);
2075 }
2076 end->type = XML_XINCLUDE_END;
2077 xmlAddNextSibling(cur, end);
2078
2079 /*
2080 * Add the list of nodes
2081 */
Owen Taylor3473f882001-02-23 17:55:21 +00002082 while (list != NULL) {
2083 cur = list;
2084 list = list->next;
2085
2086 xmlAddPrevSibling(end, cur);
2087 }
Daniel Veillardc5f05ad2002-02-10 11:57:22 +00002088
2089
Owen Taylor3473f882001-02-23 17:55:21 +00002090 return(0);
2091}
2092
2093/**
2094 * xmlXIncludeTestNode:
Daniel Veillardf4b4f982003-02-13 11:02:08 +00002095 * @ctxt: the XInclude processing context
Owen Taylor3473f882001-02-23 17:55:21 +00002096 * @node: an XInclude node
2097 *
2098 * test if the node is an XInclude node
2099 *
2100 * Returns 1 true, 0 otherwise
2101 */
Daniel Veillard56a4cb82001-03-24 17:00:36 +00002102static int
Daniel Veillardf4b4f982003-02-13 11:02:08 +00002103xmlXIncludeTestNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node) {
Owen Taylor3473f882001-02-23 17:55:21 +00002104 if (node == NULL)
2105 return(0);
Daniel Veillardffe4f5e2003-07-06 17:35:43 +00002106 if (node->type != XML_ELEMENT_NODE)
2107 return(0);
Owen Taylor3473f882001-02-23 17:55:21 +00002108 if (node->ns == NULL)
2109 return(0);
Daniel Veillardb5fa0202003-12-08 17:41:29 +00002110 if ((xmlStrEqual(node->ns->href, XINCLUDE_NS)) ||
2111 (xmlStrEqual(node->ns->href, XINCLUDE_OLD_NS))) {
2112 if (xmlStrEqual(node->ns->href, XINCLUDE_OLD_NS)) {
2113 if (ctxt->legacy == 0) {
Daniel Veillard5bb9ccd2004-02-09 12:39:02 +00002114#if 0 /* wait for the XML Core Working Group to get something stable ! */
Daniel Veillardb5fa0202003-12-08 17:41:29 +00002115 xmlXIncludeWarn(ctxt, node, XML_XINCLUDE_DEPRECATED_NS,
2116 "Deprecated XInclude namespace found, use %s",
2117 XINCLUDE_NS);
Daniel Veillard5bb9ccd2004-02-09 12:39:02 +00002118#endif
Daniel Veillarde74d2e12003-12-09 11:35:37 +00002119 ctxt->legacy = 1;
Daniel Veillardb5fa0202003-12-08 17:41:29 +00002120 }
2121 }
Daniel Veillardf4b4f982003-02-13 11:02:08 +00002122 if (xmlStrEqual(node->name, XINCLUDE_NODE)) {
2123 xmlNodePtr child = node->children;
2124 int nb_fallback = 0;
2125
2126 while (child != NULL) {
2127 if ((child->type == XML_ELEMENT_NODE) &&
2128 (child->ns != NULL) &&
Daniel Veillardb5fa0202003-12-08 17:41:29 +00002129 ((xmlStrEqual(child->ns->href, XINCLUDE_NS)) ||
2130 (xmlStrEqual(child->ns->href, XINCLUDE_OLD_NS)))) {
Daniel Veillardf4b4f982003-02-13 11:02:08 +00002131 if (xmlStrEqual(child->name, XINCLUDE_NODE)) {
Daniel Veillardcd6ff282003-10-08 22:38:13 +00002132 xmlXIncludeErr(ctxt, node,
2133 XML_XINCLUDE_INCLUDE_IN_INCLUDE,
2134 "%s has an 'include' child\n",
2135 XINCLUDE_NODE);
Daniel Veillardf4b4f982003-02-13 11:02:08 +00002136 return(0);
2137 }
2138 if (xmlStrEqual(child->name, XINCLUDE_FALLBACK)) {
2139 nb_fallback++;
2140 }
2141 }
2142 child = child->next;
2143 }
2144 if (nb_fallback > 1) {
Daniel Veillardcd6ff282003-10-08 22:38:13 +00002145 xmlXIncludeErr(ctxt, node, XML_XINCLUDE_FALLBACKS_IN_INCLUDE,
2146 "%s has multiple fallback children\n",
2147 XINCLUDE_NODE);
Daniel Veillardf4b4f982003-02-13 11:02:08 +00002148 return(0);
2149 }
2150 return(1);
2151 }
2152 if (xmlStrEqual(node->name, XINCLUDE_FALLBACK)) {
2153 if ((node->parent == NULL) ||
2154 (node->parent->type != XML_ELEMENT_NODE) ||
2155 (node->parent->ns == NULL) ||
Daniel Veillardb5fa0202003-12-08 17:41:29 +00002156 ((!xmlStrEqual(node->parent->ns->href, XINCLUDE_NS)) &&
2157 (!xmlStrEqual(node->parent->ns->href, XINCLUDE_OLD_NS))) ||
Daniel Veillardf4b4f982003-02-13 11:02:08 +00002158 (!xmlStrEqual(node->parent->name, XINCLUDE_NODE))) {
Daniel Veillardcd6ff282003-10-08 22:38:13 +00002159 xmlXIncludeErr(ctxt, node,
2160 XML_XINCLUDE_FALLBACK_NOT_IN_INCLUDE,
2161 "%s is not the child of an 'include'\n",
2162 XINCLUDE_FALLBACK);
Daniel Veillardf4b4f982003-02-13 11:02:08 +00002163 }
2164 }
2165 }
Owen Taylor3473f882001-02-23 17:55:21 +00002166 return(0);
2167}
2168
2169/**
Daniel Veillardd16df9f2001-05-23 13:44:21 +00002170 * xmlXIncludeDoProcess:
Daniel Veillardf4b4f982003-02-13 11:02:08 +00002171 * @ctxt: the XInclude processing context
Owen Taylor3473f882001-02-23 17:55:21 +00002172 * @doc: an XML document
Daniel Veillard8edf1c52003-07-22 20:52:14 +00002173 * @tree: the top of the tree to process
Owen Taylor3473f882001-02-23 17:55:21 +00002174 *
2175 * Implement the XInclude substitution on the XML document @doc
2176 *
Daniel Veillardcbaf3992001-12-31 16:16:02 +00002177 * Returns 0 if no substitution were done, -1 if some processing failed
Owen Taylor3473f882001-02-23 17:55:21 +00002178 * or the number of substitutions done.
2179 */
Daniel Veillardd16df9f2001-05-23 13:44:21 +00002180static int
Daniel Veillard8edf1c52003-07-22 20:52:14 +00002181xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr tree) {
Owen Taylor3473f882001-02-23 17:55:21 +00002182 xmlNodePtr cur;
2183 int ret = 0;
2184 int i;
2185
Daniel Veillard8edf1c52003-07-22 20:52:14 +00002186 if ((doc == NULL) || (tree == NULL))
Owen Taylor3473f882001-02-23 17:55:21 +00002187 return(-1);
Owen Taylor3473f882001-02-23 17:55:21 +00002188 if (ctxt == NULL)
2189 return(-1);
2190
Daniel Veillardf4b4f982003-02-13 11:02:08 +00002191 if (doc->URL != NULL) {
2192 ret = xmlXIncludeURLPush(ctxt, doc->URL);
2193 if (ret < 0)
2194 return(-1);
2195 }
2196
Owen Taylor3473f882001-02-23 17:55:21 +00002197 /*
2198 * First phase: lookup the elements in the document
2199 */
Daniel Veillard8edf1c52003-07-22 20:52:14 +00002200 cur = tree;
Daniel Veillardf4b4f982003-02-13 11:02:08 +00002201 if (xmlXIncludeTestNode(ctxt, cur) == 1)
Owen Taylor3473f882001-02-23 17:55:21 +00002202 xmlXIncludePreProcessNode(ctxt, cur);
2203 while (cur != NULL) {
2204 /* TODO: need to work on entities -> stack */
2205 if ((cur->children != NULL) &&
Daniel Veillardffe4f5e2003-07-06 17:35:43 +00002206 (cur->children->type != XML_ENTITY_DECL) &&
2207 (cur->children->type != XML_XINCLUDE_START) &&
2208 (cur->children->type != XML_XINCLUDE_END)) {
Owen Taylor3473f882001-02-23 17:55:21 +00002209 cur = cur->children;
Daniel Veillardf4b4f982003-02-13 11:02:08 +00002210 if (xmlXIncludeTestNode(ctxt, cur))
Owen Taylor3473f882001-02-23 17:55:21 +00002211 xmlXIncludePreProcessNode(ctxt, cur);
2212 } else if (cur->next != NULL) {
2213 cur = cur->next;
Daniel Veillardf4b4f982003-02-13 11:02:08 +00002214 if (xmlXIncludeTestNode(ctxt, cur))
Owen Taylor3473f882001-02-23 17:55:21 +00002215 xmlXIncludePreProcessNode(ctxt, cur);
2216 } else {
2217 do {
2218 cur = cur->parent;
2219 if (cur == NULL) break; /* do */
2220 if (cur->next != NULL) {
2221 cur = cur->next;
Daniel Veillardf4b4f982003-02-13 11:02:08 +00002222 if (xmlXIncludeTestNode(ctxt, cur))
Owen Taylor3473f882001-02-23 17:55:21 +00002223 xmlXIncludePreProcessNode(ctxt, cur);
2224 break; /* do */
2225 }
2226 } while (cur != NULL);
2227 }
2228 }
2229
2230 /*
2231 * Second Phase : collect the infosets fragments
2232 */
Daniel Veillardbbc72c32002-09-05 10:52:10 +00002233 for (i = ctxt->incBase;i < ctxt->incNr; i++) {
Owen Taylor3473f882001-02-23 17:55:21 +00002234 xmlXIncludeLoadNode(ctxt, i);
Daniel Veillard97fd5672003-02-07 13:01:54 +00002235 ret++;
Owen Taylor3473f882001-02-23 17:55:21 +00002236 }
2237
2238 /*
2239 * Third phase: extend the original document infoset.
William M. Brack6b1a28d2004-02-06 11:24:44 +00002240 *
2241 * Originally we bypassed the inclusion if there were any errors
2242 * encountered on any of the XIncludes. A bug was raised (bug
2243 * 132588) requesting that we output the XIncludes without error,
2244 * so the check for inc!=NULL || xptr!=NULL was put in. This may
2245 * give some other problems in the future, but for now it seems to
2246 * work ok.
2247 *
Owen Taylor3473f882001-02-23 17:55:21 +00002248 */
William M. Brack6b1a28d2004-02-06 11:24:44 +00002249 for (i = ctxt->incBase;i < ctxt->incNr; i++) {
William M. Brack95af5942004-02-08 04:12:49 +00002250 if ((ctxt->incTab[i]->inc != NULL) ||
2251 (ctxt->incTab[i]->xptr != NULL) ||
2252 (ctxt->incTab[i]->emptyFb != 0)) /* (empty fallback) */
Daniel Veillardf4b4f982003-02-13 11:02:08 +00002253 xmlXIncludeIncludeNode(ctxt, i);
Owen Taylor3473f882001-02-23 17:55:21 +00002254 }
2255
Daniel Veillardf4b4f982003-02-13 11:02:08 +00002256 if (doc->URL != NULL)
2257 xmlXIncludeURLPop(ctxt);
Daniel Veillardd16df9f2001-05-23 13:44:21 +00002258 return(ret);
2259}
2260
2261/**
Daniel Veillarde74d2e12003-12-09 11:35:37 +00002262 * xmlXIncludeSetFlags:
2263 * @ctxt: an XInclude processing context
2264 * @flags: a set of xmlParserOption used for parsing XML includes
2265 *
2266 * Set the flags used for further processing of XML resources.
2267 *
2268 * Returns 0 in case of success and -1 in case of error.
2269 */
2270int
2271xmlXIncludeSetFlags(xmlXIncludeCtxtPtr ctxt, int flags) {
2272 if (ctxt == NULL)
2273 return(-1);
2274 ctxt->parseFlags = flags;
2275 return(0);
2276}
2277
2278/**
2279 * xmlXIncludeProcessFlags:
Daniel Veillardd16df9f2001-05-23 13:44:21 +00002280 * @doc: an XML document
Daniel Veillarde74d2e12003-12-09 11:35:37 +00002281 * @flags: a set of xmlParserOption used for parsing XML includes
Daniel Veillardd16df9f2001-05-23 13:44:21 +00002282 *
2283 * Implement the XInclude substitution on the XML document @doc
2284 *
Daniel Veillardcbaf3992001-12-31 16:16:02 +00002285 * Returns 0 if no substitution were done, -1 if some processing failed
Daniel Veillardd16df9f2001-05-23 13:44:21 +00002286 * or the number of substitutions done.
2287 */
2288int
Daniel Veillarde74d2e12003-12-09 11:35:37 +00002289xmlXIncludeProcessFlags(xmlDocPtr doc, int flags) {
Daniel Veillardd16df9f2001-05-23 13:44:21 +00002290 xmlXIncludeCtxtPtr ctxt;
Daniel Veillard8edf1c52003-07-22 20:52:14 +00002291 xmlNodePtr tree;
Daniel Veillardd16df9f2001-05-23 13:44:21 +00002292 int ret = 0;
2293
2294 if (doc == NULL)
2295 return(-1);
Daniel Veillard8edf1c52003-07-22 20:52:14 +00002296 tree = xmlDocGetRootElement(doc);
2297 if (tree == NULL)
2298 return(-1);
Daniel Veillardd16df9f2001-05-23 13:44:21 +00002299 ctxt = xmlXIncludeNewContext(doc);
2300 if (ctxt == NULL)
2301 return(-1);
Daniel Veillarde74d2e12003-12-09 11:35:37 +00002302 xmlXIncludeSetFlags(ctxt, flags);
Daniel Veillard8edf1c52003-07-22 20:52:14 +00002303 ret = xmlXIncludeDoProcess(ctxt, doc, tree);
2304 if ((ret >= 0) && (ctxt->nbErrors > 0))
2305 ret = -1;
2306
2307 xmlXIncludeFreeContext(ctxt);
2308 return(ret);
2309}
2310
2311/**
Daniel Veillarde74d2e12003-12-09 11:35:37 +00002312 * xmlXIncludeProcess:
2313 * @doc: an XML document
2314 *
2315 * Implement the XInclude substitution on the XML document @doc
2316 *
2317 * Returns 0 if no substitution were done, -1 if some processing failed
2318 * or the number of substitutions done.
2319 */
2320int
2321xmlXIncludeProcess(xmlDocPtr doc) {
2322 return(xmlXIncludeProcessFlags(doc, 0));
2323}
2324
2325/**
2326 * xmlXIncludeProcessTreeFlags:
2327 * @tree: a node in an XML document
2328 * @flags: a set of xmlParserOption used for parsing XML includes
2329 *
2330 * Implement the XInclude substitution for the given subtree
2331 *
2332 * Returns 0 if no substitution were done, -1 if some processing failed
2333 * or the number of substitutions done.
2334 */
2335int
2336xmlXIncludeProcessTreeFlags(xmlNodePtr tree, int flags) {
2337 xmlXIncludeCtxtPtr ctxt;
2338 int ret = 0;
2339
2340 if ((tree == NULL) || (tree->doc == NULL))
2341 return(-1);
2342 ctxt = xmlXIncludeNewContext(tree->doc);
2343 if (ctxt == NULL)
2344 return(-1);
2345 xmlXIncludeSetFlags(ctxt, flags);
2346 ret = xmlXIncludeDoProcess(ctxt, tree->doc, tree);
2347 if ((ret >= 0) && (ctxt->nbErrors > 0))
2348 ret = -1;
2349
2350 xmlXIncludeFreeContext(ctxt);
2351 return(ret);
2352}
2353
2354/**
Daniel Veillard8edf1c52003-07-22 20:52:14 +00002355 * xmlXIncludeProcessTree:
2356 * @tree: a node in an XML document
2357 *
2358 * Implement the XInclude substitution for the given subtree
2359 *
2360 * Returns 0 if no substitution were done, -1 if some processing failed
2361 * or the number of substitutions done.
2362 */
2363int
2364xmlXIncludeProcessTree(xmlNodePtr tree) {
Daniel Veillarde74d2e12003-12-09 11:35:37 +00002365 return(xmlXIncludeProcessTreeFlags(tree, 0));
Owen Taylor3473f882001-02-23 17:55:21 +00002366}
2367
Daniel Veillard7899c5c2003-11-03 12:31:38 +00002368/**
2369 * xmlXIncludeProcessNode:
2370 * @ctxt: an existing XInclude context
2371 * @node: a node in an XML document
2372 *
2373 * Implement the XInclude substitution for the given subtree reusing
2374 * the informations and data coming from the given context.
2375 *
2376 * Returns 0 if no substitution were done, -1 if some processing failed
2377 * or the number of substitutions done.
2378 */
2379int
2380xmlXIncludeProcessNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node) {
2381 int ret = 0;
2382
2383 if ((node == NULL) || (node->doc == NULL) || (ctxt == NULL))
2384 return(-1);
2385 ret = xmlXIncludeDoProcess(ctxt, node->doc, node);
2386 if ((ret >= 0) && (ctxt->nbErrors > 0))
2387 ret = -1;
2388 return(ret);
2389}
2390
Owen Taylor3473f882001-02-23 17:55:21 +00002391#else /* !LIBXML_XINCLUDE_ENABLED */
2392#endif