blob: 347e0ad8e1bed0318ff5630c9b758e099283c860 [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 }
Daniel Veillard98485322003-08-14 15:44:40 +0000457 else {
458 ret = NULL;
Daniel Veillard500a1de2004-03-22 15:22:58 +0000459 if (pctxt->myDoc != NULL)
Daniel Veillard4773df22004-01-23 13:15:13 +0000460 xmlFreeDoc(pctxt->myDoc);
Daniel Veillard98485322003-08-14 15:44:40 +0000461 pctxt->myDoc = NULL;
462 }
463 xmlFreeParserCtxt(pctxt);
464
465 return(ret);
466}
467
468/**
Daniel Veillardd16df9f2001-05-23 13:44:21 +0000469 * xmlXIncludeAddNode:
470 * @ctxt: the XInclude context
Daniel Veillardbbc72c32002-09-05 10:52:10 +0000471 * @cur: the new node
Daniel Veillardd16df9f2001-05-23 13:44:21 +0000472 *
473 * Add a new node to process to an XInclude context
474 */
Daniel Veillardbbc72c32002-09-05 10:52:10 +0000475static int
476xmlXIncludeAddNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr cur) {
477 xmlXIncludeRefPtr ref;
478 xmlURIPtr uri;
479 xmlChar *URL;
480 xmlChar *fragment = NULL;
481 xmlChar *href;
482 xmlChar *parse;
483 xmlChar *base;
484 xmlChar *URI;
Daniel Veillardf4b4f982003-02-13 11:02:08 +0000485 int xml = 1, i; /* default Issue 64 */
486 int local = 0;
Daniel Veillardbbc72c32002-09-05 10:52:10 +0000487
488
489 if (ctxt == NULL)
490 return(-1);
491 if (cur == NULL)
492 return(-1);
493
494#ifdef DEBUG_XINCLUDE
495 xmlGenericError(xmlGenericErrorContext, "Add node\n");
496#endif
497 /*
498 * read the attributes
499 */
Daniel Veillardb5fa0202003-12-08 17:41:29 +0000500 href = xmlXIncludeGetProp(ctxt, cur, XINCLUDE_HREF);
Daniel Veillardbbc72c32002-09-05 10:52:10 +0000501 if (href == NULL) {
Daniel Veillardb5fa0202003-12-08 17:41:29 +0000502 href = xmlStrdup(BAD_CAST ""); /* @@@@ href is now optional */
503 if (href == NULL)
Daniel Veillardbbc72c32002-09-05 10:52:10 +0000504 return(-1);
Daniel Veillardb5fa0202003-12-08 17:41:29 +0000505 local = 1;
Daniel Veillardd16df9f2001-05-23 13:44:21 +0000506 }
Daniel Veillardf4b4f982003-02-13 11:02:08 +0000507 if (href[0] == '#')
508 local = 1;
Daniel Veillardb5fa0202003-12-08 17:41:29 +0000509 parse = xmlXIncludeGetProp(ctxt, cur, XINCLUDE_PARSE);
Daniel Veillardbbc72c32002-09-05 10:52:10 +0000510 if (parse != NULL) {
511 if (xmlStrEqual(parse, XINCLUDE_PARSE_XML))
512 xml = 1;
513 else if (xmlStrEqual(parse, XINCLUDE_PARSE_TEXT))
514 xml = 0;
515 else {
Daniel Veillardcd6ff282003-10-08 22:38:13 +0000516 xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_PARSE_VALUE,
517 "invalid value %s for 'parse'\n", parse);
Daniel Veillardbbc72c32002-09-05 10:52:10 +0000518 if (href != NULL)
519 xmlFree(href);
520 if (parse != NULL)
521 xmlFree(parse);
522 return(-1);
Daniel Veillardd16df9f2001-05-23 13:44:21 +0000523 }
524 }
Daniel Veillardbbc72c32002-09-05 10:52:10 +0000525
526 /*
527 * compute the URI
528 */
529 base = xmlNodeGetBase(ctxt->doc, cur);
530 if (base == NULL) {
531 URI = xmlBuildURI(href, ctxt->doc->URL);
532 } else {
533 URI = xmlBuildURI(href, base);
534 }
535 if (URI == NULL) {
536 xmlChar *escbase;
537 xmlChar *eschref;
538 /*
539 * Some escaping may be needed
540 */
541 escbase = xmlURIEscape(base);
542 eschref = xmlURIEscape(href);
543 URI = xmlBuildURI(eschref, escbase);
544 if (escbase != NULL)
545 xmlFree(escbase);
546 if (eschref != NULL)
547 xmlFree(eschref);
548 }
549 if (parse != NULL)
550 xmlFree(parse);
551 if (href != NULL)
552 xmlFree(href);
553 if (base != NULL)
554 xmlFree(base);
555 if (URI == NULL) {
Daniel Veillardcd6ff282003-10-08 22:38:13 +0000556 xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_HREF_URI,
557 "failed build URL\n", NULL);
Daniel Veillardbbc72c32002-09-05 10:52:10 +0000558 return(-1);
559 }
Daniel Veillarde74d2e12003-12-09 11:35:37 +0000560 fragment = xmlXIncludeGetProp(ctxt, cur, XINCLUDE_PARSE_XPOINTER);
Daniel Veillardbbc72c32002-09-05 10:52:10 +0000561
562 /*
563 * Check the URL and remove any fragment identifier
564 */
565 uri = xmlParseURI((const char *)URI);
566 if (uri == NULL) {
Daniel Veillardcd6ff282003-10-08 22:38:13 +0000567 xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_HREF_URI,
568 "invalid value URI %s\n", URI);
Daniel Veillarde74d2e12003-12-09 11:35:37 +0000569 if (fragment != NULL)
570 xmlFree(fragment);
571 xmlFree(URI);
Daniel Veillardbbc72c32002-09-05 10:52:10 +0000572 return(-1);
573 }
Daniel Veillarde74d2e12003-12-09 11:35:37 +0000574
Daniel Veillardbbc72c32002-09-05 10:52:10 +0000575 if (uri->fragment != NULL) {
Daniel Veillarde74d2e12003-12-09 11:35:37 +0000576 if (ctxt->legacy != 0) {
577 if (fragment == NULL) {
578 fragment = (xmlChar *) uri->fragment;
579 } else {
580 xmlFree(uri->fragment);
581 }
582 } else {
583 xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_FRAGMENT_ID,
584 "Invalid fragment identifier in URI %s use the xpointer attribute\n",
585 URI);
586 if (fragment != NULL)
587 xmlFree(fragment);
588 xmlFreeURI(uri);
589 xmlFree(URI);
590 return(-1);
591 }
Daniel Veillardbbc72c32002-09-05 10:52:10 +0000592 uri->fragment = NULL;
593 }
594 URL = xmlSaveUri(uri);
595 xmlFreeURI(uri);
596 xmlFree(URI);
597 if (URL == NULL) {
Daniel Veillardcd6ff282003-10-08 22:38:13 +0000598 xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_HREF_URI,
599 "invalid value URI %s\n", URI);
Daniel Veillardbbc72c32002-09-05 10:52:10 +0000600 if (fragment != NULL)
601 xmlFree(fragment);
602 return(-1);
603 }
604
Daniel Veillardf4b4f982003-02-13 11:02:08 +0000605 /*
606 * Check the URL against the stack for recursions
607 */
608 if (!local) {
609 for (i = 0;i < ctxt->urlNr;i++) {
610 if (xmlStrEqual(URL, ctxt->urlTab[i])) {
Daniel Veillardcd6ff282003-10-08 22:38:13 +0000611 xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_RECURSION,
612 "detected a recursion in %s\n", URL);
Daniel Veillardf4b4f982003-02-13 11:02:08 +0000613 return(-1);
614 }
615 }
616 }
617
Daniel Veillardbbc72c32002-09-05 10:52:10 +0000618 ref = xmlXIncludeNewRef(ctxt, URL, cur);
619 if (ref == NULL) {
620 return(-1);
621 }
622 ref->fragment = fragment;
623 ref->doc = NULL;
624 ref->xml = xml;
625 ref->count = 1;
626 xmlFree(URL);
627 return(0);
Daniel Veillardd16df9f2001-05-23 13:44:21 +0000628}
629
630/**
Daniel Veillardbbc72c32002-09-05 10:52:10 +0000631 * xmlXIncludeRecurseDoc:
Daniel Veillardd16df9f2001-05-23 13:44:21 +0000632 * @ctxt: the XInclude context
633 * @doc: the new document
634 * @url: the associated URL
635 *
Daniel Veillardbbc72c32002-09-05 10:52:10 +0000636 * The XInclude recursive nature is handled at this point.
Daniel Veillardd16df9f2001-05-23 13:44:21 +0000637 */
638static void
Daniel Veillard118aed72002-09-24 14:13:13 +0000639xmlXIncludeRecurseDoc(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc,
Daniel Veillarddda8f1b2002-09-26 09:47:36 +0000640 const xmlURL url ATTRIBUTE_UNUSED) {
Daniel Veillardd16df9f2001-05-23 13:44:21 +0000641 xmlXIncludeCtxtPtr newctxt;
642 int i;
643
Daniel Veillardf4b4f982003-02-13 11:02:08 +0000644 /*
645 * Avoid recursion in already substitued resources
646 for (i = 0;i < ctxt->urlNr;i++) {
647 if (xmlStrEqual(doc->URL, ctxt->urlTab[i]))
648 return;
649 }
650 */
651
Daniel Veillardbbc72c32002-09-05 10:52:10 +0000652#ifdef DEBUG_XINCLUDE
653 xmlGenericError(xmlGenericErrorContext, "Recursing in doc %s\n", doc->URL);
654#endif
Daniel Veillardd16df9f2001-05-23 13:44:21 +0000655 /*
656 * Handle recursion here.
657 */
658
659 newctxt = xmlXIncludeNewContext(doc);
660 if (newctxt != NULL) {
661 /*
662 * Copy the existing document set
663 */
Daniel Veillardbbc72c32002-09-05 10:52:10 +0000664 newctxt->incMax = ctxt->incMax;
665 newctxt->incNr = ctxt->incNr;
666 newctxt->incTab = (xmlXIncludeRefPtr *) xmlMalloc(newctxt->incMax *
667 sizeof(newctxt->incTab[0]));
668 if (newctxt->incTab == NULL) {
Daniel Veillardcd6ff282003-10-08 22:38:13 +0000669 xmlXIncludeErrMemory(ctxt, (xmlNodePtr) doc, "processing doc");
Daniel Veillardd16df9f2001-05-23 13:44:21 +0000670 xmlFree(newctxt);
671 return;
672 }
Daniel Veillardf4b4f982003-02-13 11:02:08 +0000673 /*
674 * copy the urlTab
675 */
676 newctxt->urlMax = ctxt->urlMax;
677 newctxt->urlNr = ctxt->urlNr;
678 newctxt->urlTab = ctxt->urlTab;
Daniel Veillardd16df9f2001-05-23 13:44:21 +0000679
Daniel Veillardbbc72c32002-09-05 10:52:10 +0000680 /*
William M. Brack72ee48d2003-12-30 08:30:19 +0000681 * Inherit the documents already in use by other includes
Daniel Veillardbbc72c32002-09-05 10:52:10 +0000682 */
683 newctxt->incBase = ctxt->incNr;
684 for (i = 0;i < ctxt->incNr;i++) {
685 newctxt->incTab[i] = ctxt->incTab[i];
686 newctxt->incTab[i]->count++; /* prevent the recursion from
687 freeing it */
Daniel Veillardd16df9f2001-05-23 13:44:21 +0000688 }
William M. Bracka11e4832004-03-07 11:03:43 +0000689 /*
690 * The new context should also inherit the Parse Flags
691 * (bug 132597)
692 */
693 newctxt->parseFlags = ctxt->parseFlags;
Daniel Veillard8edf1c52003-07-22 20:52:14 +0000694 xmlXIncludeDoProcess(newctxt, doc, xmlDocGetRootElement(doc));
Daniel Veillardbbc72c32002-09-05 10:52:10 +0000695 for (i = 0;i < ctxt->incNr;i++) {
696 newctxt->incTab[i]->count--;
697 newctxt->incTab[i] = NULL;
Daniel Veillardd16df9f2001-05-23 13:44:21 +0000698 }
Daniel Veillardd9b72832003-03-27 14:24:00 +0000699
700 /* urlTab may have been reallocated */
701 ctxt->urlTab = newctxt->urlTab;
702 ctxt->urlMax = newctxt->urlMax;
703
Daniel Veillardf4b4f982003-02-13 11:02:08 +0000704 newctxt->urlMax = 0;
705 newctxt->urlNr = 0;
706 newctxt->urlTab = NULL;
707
Daniel Veillardd16df9f2001-05-23 13:44:21 +0000708 xmlXIncludeFreeContext(newctxt);
709 }
Daniel Veillardbbc72c32002-09-05 10:52:10 +0000710#ifdef DEBUG_XINCLUDE
711 xmlGenericError(xmlGenericErrorContext, "Done recursing in doc %s\n", url);
712#endif
Daniel Veillardd16df9f2001-05-23 13:44:21 +0000713}
714
715/**
716 * xmlXIncludeAddTxt:
717 * @ctxt: the XInclude context
718 * @txt: the new text node
719 * @url: the associated URL
720 *
721 * Add a new txtument to the list
722 */
723static void
724xmlXIncludeAddTxt(xmlXIncludeCtxtPtr ctxt, xmlNodePtr txt, const xmlURL url) {
Daniel Veillardbbc72c32002-09-05 10:52:10 +0000725#ifdef DEBUG_XINCLUDE
726 xmlGenericError(xmlGenericErrorContext, "Adding text %s\n", url);
727#endif
Daniel Veillardd16df9f2001-05-23 13:44:21 +0000728 if (ctxt->txtMax == 0) {
729 ctxt->txtMax = 4;
730 ctxt->txtTab = (xmlNodePtr *) xmlMalloc(ctxt->txtMax *
731 sizeof(ctxt->txtTab[0]));
732 if (ctxt->txtTab == NULL) {
Daniel Veillardcd6ff282003-10-08 22:38:13 +0000733 xmlXIncludeErrMemory(ctxt, NULL, "processing text");
Daniel Veillardd16df9f2001-05-23 13:44:21 +0000734 return;
735 }
736 ctxt->txturlTab = (xmlURL *) xmlMalloc(ctxt->txtMax *
737 sizeof(ctxt->txturlTab[0]));
738 if (ctxt->txturlTab == NULL) {
Daniel Veillardcd6ff282003-10-08 22:38:13 +0000739 xmlXIncludeErrMemory(ctxt, NULL, "processing text");
Daniel Veillardd16df9f2001-05-23 13:44:21 +0000740 return;
741 }
742 }
743 if (ctxt->txtNr >= ctxt->txtMax) {
744 ctxt->txtMax *= 2;
745 ctxt->txtTab = (xmlNodePtr *) xmlRealloc(ctxt->txtTab,
746 ctxt->txtMax * sizeof(ctxt->txtTab[0]));
747 if (ctxt->txtTab == NULL) {
Daniel Veillardcd6ff282003-10-08 22:38:13 +0000748 xmlXIncludeErrMemory(ctxt, NULL, "processing text");
Daniel Veillardd16df9f2001-05-23 13:44:21 +0000749 return;
750 }
751 ctxt->txturlTab = (xmlURL *) xmlRealloc(ctxt->txturlTab,
Daniel Veillardbbc72c32002-09-05 10:52:10 +0000752 ctxt->txtMax * sizeof(ctxt->txturlTab[0]));
Daniel Veillardd16df9f2001-05-23 13:44:21 +0000753 if (ctxt->txturlTab == NULL) {
Daniel Veillardcd6ff282003-10-08 22:38:13 +0000754 xmlXIncludeErrMemory(ctxt, NULL, "processing text");
Daniel Veillardd16df9f2001-05-23 13:44:21 +0000755 return;
756 }
757 }
758 ctxt->txtTab[ctxt->txtNr] = txt;
759 ctxt->txturlTab[ctxt->txtNr] = xmlStrdup(url);
760 ctxt->txtNr++;
761}
762
Owen Taylor3473f882001-02-23 17:55:21 +0000763/************************************************************************
764 * *
Daniel Veillardc5f05ad2002-02-10 11:57:22 +0000765 * Node copy with specific semantic *
766 * *
767 ************************************************************************/
768
769/**
770 * xmlXIncludeCopyNode:
771 * @ctxt: the XInclude context
772 * @target: the document target
773 * @source: the document source
774 * @elem: the element
775 *
776 * Make a copy of the node while preserving the XInclude semantic
777 * of the Infoset copy
778 */
779static xmlNodePtr
780xmlXIncludeCopyNode(xmlXIncludeCtxtPtr ctxt, xmlDocPtr target,
781 xmlDocPtr source, xmlNodePtr elem) {
782 xmlNodePtr result = NULL;
783
784 if ((ctxt == NULL) || (target == NULL) || (source == NULL) ||
785 (elem == NULL))
786 return(NULL);
787 if (elem->type == XML_DTD_NODE)
788 return(NULL);
789 result = xmlDocCopyNode(elem, target, 1);
790 return(result);
791}
792
793/**
794 * xmlXIncludeCopyNodeList:
795 * @ctxt: the XInclude context
796 * @target: the document target
797 * @source: the document source
798 * @elem: the element list
799 *
800 * Make a copy of the node list while preserving the XInclude semantic
801 * of the Infoset copy
802 */
803static xmlNodePtr
804xmlXIncludeCopyNodeList(xmlXIncludeCtxtPtr ctxt, xmlDocPtr target,
805 xmlDocPtr source, xmlNodePtr elem) {
806 xmlNodePtr cur, res, result = NULL, last = NULL;
807
808 if ((ctxt == NULL) || (target == NULL) || (source == NULL) ||
809 (elem == NULL))
810 return(NULL);
811 cur = elem;
812 while (cur != NULL) {
813 res = xmlXIncludeCopyNode(ctxt, target, source, cur);
814 if (res != NULL) {
815 if (result == NULL) {
816 result = last = res;
817 } else {
818 last->next = res;
819 res->prev = last;
820 last = res;
821 }
822 }
823 cur = cur->next;
824 }
825 return(result);
826}
827
828/**
William M. Brack72ee48d2003-12-30 08:30:19 +0000829 * xmlXIncludeGetNthChild:
Daniel Veillardc5f05ad2002-02-10 11:57:22 +0000830 * @cur: the node
831 * @no: the child number
832 *
William M. Brack72ee48d2003-12-30 08:30:19 +0000833 * Returns the @n'th element child of @cur or NULL
Daniel Veillardc5f05ad2002-02-10 11:57:22 +0000834 */
835static xmlNodePtr
836xmlXIncludeGetNthChild(xmlNodePtr cur, int no) {
837 int i;
838 if (cur == NULL)
839 return(cur);
840 cur = cur->children;
841 for (i = 0;i <= no;cur = cur->next) {
842 if (cur == NULL)
843 return(cur);
844 if ((cur->type == XML_ELEMENT_NODE) ||
845 (cur->type == XML_DOCUMENT_NODE) ||
846 (cur->type == XML_HTML_DOCUMENT_NODE)) {
847 i++;
848 if (i == no)
849 break;
850 }
851 }
852 return(cur);
853}
854
William M. Brackf7eb7942003-12-31 07:59:17 +0000855xmlNodePtr xmlXPtrAdvanceNode(xmlNodePtr cur, int *level); /* in xpointer.c */
Daniel Veillardc5f05ad2002-02-10 11:57:22 +0000856/**
857 * xmlXIncludeCopyRange:
858 * @ctxt: the XInclude context
859 * @target: the document target
860 * @source: the document source
861 * @obj: the XPointer result from the evaluation.
862 *
863 * Build a node list tree copy of the XPointer result.
864 *
865 * Returns an xmlNodePtr list or NULL.
William M. Brack72ee48d2003-12-30 08:30:19 +0000866 * The caller has to free the node tree.
Daniel Veillardc5f05ad2002-02-10 11:57:22 +0000867 */
868static xmlNodePtr
869xmlXIncludeCopyRange(xmlXIncludeCtxtPtr ctxt, xmlDocPtr target,
870 xmlDocPtr source, xmlXPathObjectPtr range) {
871 /* pointers to generated nodes */
William M. Brackf7eb7942003-12-31 07:59:17 +0000872 xmlNodePtr list = NULL, last = NULL, listParent = NULL;
873 xmlNodePtr tmp, tmp2;
Daniel Veillardc5f05ad2002-02-10 11:57:22 +0000874 /* pointers to traversal nodes */
875 xmlNodePtr start, cur, end;
876 int index1, index2;
William M. Brack6bdacd72004-02-07 08:53:23 +0000877 int level = 0, lastLevel = 0, endLevel = 0, endFlag = 0;
Daniel Veillardc5f05ad2002-02-10 11:57:22 +0000878
879 if ((ctxt == NULL) || (target == NULL) || (source == NULL) ||
880 (range == NULL))
881 return(NULL);
882 if (range->type != XPATH_RANGE)
883 return(NULL);
884 start = (xmlNodePtr) range->user;
885
886 if (start == NULL)
887 return(NULL);
888 end = range->user2;
889 if (end == NULL)
890 return(xmlDocCopyNode(start, target, 1));
891
892 cur = start;
893 index1 = range->index;
894 index2 = range->index2;
William M. Brackf7eb7942003-12-31 07:59:17 +0000895 /*
896 * level is depth of the current node under consideration
897 * list is the pointer to the root of the output tree
898 * listParent is a pointer to the parent of output tree (within
899 the included file) in case we need to add another level
900 * last is a pointer to the last node added to the output tree
901 * lastLevel is the depth of last (relative to the root)
902 */
Daniel Veillardc5f05ad2002-02-10 11:57:22 +0000903 while (cur != NULL) {
William M. Brackf7eb7942003-12-31 07:59:17 +0000904 /*
905 * Check if our output tree needs a parent
906 */
907 if (level < 0) {
908 while (level < 0) {
William M. Brack57e9e912004-03-09 16:19:02 +0000909 /* copy must include namespaces and properties */
910 tmp2 = xmlDocCopyNode(listParent, target, 2);
William M. Brackf7eb7942003-12-31 07:59:17 +0000911 xmlAddChild(tmp2, list);
912 list = tmp2;
913 listParent = listParent->parent;
914 level++;
915 }
916 last = list;
917 lastLevel = 0;
918 }
919 /*
920 * Check whether we need to change our insertion point
921 */
922 while (level < lastLevel) {
923 last = last->parent;
924 lastLevel --;
925 }
William M. Brack72ee48d2003-12-30 08:30:19 +0000926 if (cur == end) { /* Are we at the end of the range? */
Daniel Veillardc5f05ad2002-02-10 11:57:22 +0000927 if (cur->type == XML_TEXT_NODE) {
928 const xmlChar *content = cur->content;
929 int len;
930
931 if (content == NULL) {
932 tmp = xmlNewTextLen(NULL, 0);
933 } else {
934 len = index2;
935 if ((cur == start) && (index1 > 1)) {
936 content += (index1 - 1);
937 len -= (index1 - 1);
938 index1 = 0;
939 } else {
940 len = index2;
941 }
942 tmp = xmlNewTextLen(content, len);
943 }
944 /* single sub text node selection */
945 if (list == NULL)
946 return(tmp);
947 /* prune and return full set */
William M. Brackf7eb7942003-12-31 07:59:17 +0000948 if (level == lastLevel)
Daniel Veillardc5f05ad2002-02-10 11:57:22 +0000949 xmlAddNextSibling(last, tmp);
950 else
William M. Brackf7eb7942003-12-31 07:59:17 +0000951 xmlAddChild(last, tmp);
Daniel Veillardc5f05ad2002-02-10 11:57:22 +0000952 return(list);
William M. Brack72ee48d2003-12-30 08:30:19 +0000953 } else { /* ending node not a text node */
William M. Brack6bdacd72004-02-07 08:53:23 +0000954 endLevel = level; /* remember the level of the end node */
955 endFlag = 1;
William M. Brack57e9e912004-03-09 16:19:02 +0000956 /* last node - need to take care of properties + namespaces */
957 tmp = xmlDocCopyNode(cur, target, 2);
William M. Brackf7eb7942003-12-31 07:59:17 +0000958 if (list == NULL) {
Daniel Veillardc5f05ad2002-02-10 11:57:22 +0000959 list = tmp;
William M. Brackf7eb7942003-12-31 07:59:17 +0000960 listParent = cur->parent;
961 } else {
962 if (level == lastLevel)
Daniel Veillardc5f05ad2002-02-10 11:57:22 +0000963 xmlAddNextSibling(last, tmp);
William M. Brackf7eb7942003-12-31 07:59:17 +0000964 else {
965 xmlAddChild(last, tmp);
966 lastLevel = level;
967 }
Daniel Veillardc5f05ad2002-02-10 11:57:22 +0000968 }
William M. Brackf7eb7942003-12-31 07:59:17 +0000969 last = tmp;
Daniel Veillardc5f05ad2002-02-10 11:57:22 +0000970
971 if (index2 > 1) {
972 end = xmlXIncludeGetNthChild(cur, index2 - 1);
973 index2 = 0;
974 }
975 if ((cur == start) && (index1 > 1)) {
976 cur = xmlXIncludeGetNthChild(cur, index1 - 1);
977 index1 = 0;
William M. Brack6bdacd72004-02-07 08:53:23 +0000978 } else {
Daniel Veillardc5f05ad2002-02-10 11:57:22 +0000979 cur = cur->children;
980 }
William M. Brack6bdacd72004-02-07 08:53:23 +0000981 level++; /* increment level to show change */
Daniel Veillardc5f05ad2002-02-10 11:57:22 +0000982 /*
983 * Now gather the remaining nodes from cur to end
984 */
William M. Brack6bdacd72004-02-07 08:53:23 +0000985 continue; /* while */
Daniel Veillardc5f05ad2002-02-10 11:57:22 +0000986 }
William M. Brackf7eb7942003-12-31 07:59:17 +0000987 } else if (cur == start) { /* Not at the end, are we at start? */
Daniel Veillardc5f05ad2002-02-10 11:57:22 +0000988 if ((cur->type == XML_TEXT_NODE) ||
989 (cur->type == XML_CDATA_SECTION_NODE)) {
990 const xmlChar *content = cur->content;
991
992 if (content == NULL) {
993 tmp = xmlNewTextLen(NULL, 0);
994 } else {
995 if (index1 > 1) {
996 content += (index1 - 1);
William M. Brack72ee48d2003-12-30 08:30:19 +0000997 index1 = 0;
Daniel Veillardc5f05ad2002-02-10 11:57:22 +0000998 }
999 tmp = xmlNewText(content);
1000 }
1001 last = list = tmp;
William M. Brackf7eb7942003-12-31 07:59:17 +00001002 listParent = cur->parent;
William M. Brack72ee48d2003-12-30 08:30:19 +00001003 } else { /* Not text node */
William M. Brack57e9e912004-03-09 16:19:02 +00001004 /*
1005 * start of the range - need to take care of
1006 * properties and namespaces
1007 */
1008 tmp = xmlDocCopyNode(cur, target, 2);
William M. Brackf7eb7942003-12-31 07:59:17 +00001009 list = last = tmp;
1010 listParent = cur->parent;
William M. Brack72ee48d2003-12-30 08:30:19 +00001011 if (index1 > 1) { /* Do we need to position? */
Daniel Veillardc5f05ad2002-02-10 11:57:22 +00001012 cur = xmlXIncludeGetNthChild(cur, index1 - 1);
William M. Brackf7eb7942003-12-31 07:59:17 +00001013 level = lastLevel = 1;
Daniel Veillardc5f05ad2002-02-10 11:57:22 +00001014 index1 = 0;
1015 /*
1016 * Now gather the remaining nodes from cur to end
1017 */
1018 continue; /* while */
1019 }
Daniel Veillardc5f05ad2002-02-10 11:57:22 +00001020 }
1021 } else {
1022 tmp = NULL;
1023 switch (cur->type) {
1024 case XML_DTD_NODE:
1025 case XML_ELEMENT_DECL:
1026 case XML_ATTRIBUTE_DECL:
1027 case XML_ENTITY_NODE:
1028 /* Do not copy DTD informations */
1029 break;
1030 case XML_ENTITY_DECL:
1031 /* handle crossing entities -> stack needed */
1032 break;
1033 case XML_XINCLUDE_START:
1034 case XML_XINCLUDE_END:
1035 /* don't consider it part of the tree content */
1036 break;
1037 case XML_ATTRIBUTE_NODE:
1038 /* Humm, should not happen ! */
1039 break;
1040 default:
William M. Brack57e9e912004-03-09 16:19:02 +00001041 /*
1042 * Middle of the range - need to take care of
1043 * properties and namespaces
1044 */
1045 tmp = xmlDocCopyNode(cur, target, 2);
Daniel Veillardc5f05ad2002-02-10 11:57:22 +00001046 break;
1047 }
1048 if (tmp != NULL) {
William M. Brackf7eb7942003-12-31 07:59:17 +00001049 if (level == lastLevel)
Daniel Veillardc5f05ad2002-02-10 11:57:22 +00001050 xmlAddNextSibling(last, tmp);
1051 else {
William M. Brackf7eb7942003-12-31 07:59:17 +00001052 xmlAddChild(last, tmp);
1053 lastLevel = level;
Daniel Veillardc5f05ad2002-02-10 11:57:22 +00001054 }
William M. Brackf7eb7942003-12-31 07:59:17 +00001055 last = tmp;
Daniel Veillardc5f05ad2002-02-10 11:57:22 +00001056 }
1057 }
1058 /*
1059 * Skip to next node in document order
1060 */
William M. Brackf7eb7942003-12-31 07:59:17 +00001061 cur = xmlXPtrAdvanceNode(cur, &level);
William M. Brack6bdacd72004-02-07 08:53:23 +00001062 if (endFlag && (level >= endLevel))
1063 break;
Daniel Veillardc5f05ad2002-02-10 11:57:22 +00001064 }
1065 return(list);
1066}
1067
1068/**
1069 * xmlXIncludeBuildNodeList:
1070 * @ctxt: the XInclude context
1071 * @target: the document target
1072 * @source: the document source
1073 * @obj: the XPointer result from the evaluation.
1074 *
1075 * Build a node list tree copy of the XPointer result.
1076 * This will drop Attributes and Namespace declarations.
1077 *
1078 * Returns an xmlNodePtr list or NULL.
1079 * the caller has to free the node tree.
1080 */
1081static xmlNodePtr
1082xmlXIncludeCopyXPointer(xmlXIncludeCtxtPtr ctxt, xmlDocPtr target,
1083 xmlDocPtr source, xmlXPathObjectPtr obj) {
1084 xmlNodePtr list = NULL, last = NULL;
1085 int i;
1086
Daniel Veillardf4b4f982003-02-13 11:02:08 +00001087 if (source == NULL)
1088 source = ctxt->doc;
Daniel Veillardc5f05ad2002-02-10 11:57:22 +00001089 if ((ctxt == NULL) || (target == NULL) || (source == NULL) ||
1090 (obj == NULL))
1091 return(NULL);
1092 switch (obj->type) {
1093 case XPATH_NODESET: {
1094 xmlNodeSetPtr set = obj->nodesetval;
1095 if (set == NULL)
1096 return(NULL);
1097 for (i = 0;i < set->nodeNr;i++) {
1098 if (set->nodeTab[i] == NULL)
1099 continue;
1100 switch (set->nodeTab[i]->type) {
1101 case XML_TEXT_NODE:
1102 case XML_CDATA_SECTION_NODE:
1103 case XML_ELEMENT_NODE:
1104 case XML_ENTITY_REF_NODE:
1105 case XML_ENTITY_NODE:
1106 case XML_PI_NODE:
1107 case XML_COMMENT_NODE:
1108 case XML_DOCUMENT_NODE:
1109 case XML_HTML_DOCUMENT_NODE:
1110#ifdef LIBXML_DOCB_ENABLED
1111 case XML_DOCB_DOCUMENT_NODE:
1112#endif
Daniel Veillardc5f05ad2002-02-10 11:57:22 +00001113 case XML_XINCLUDE_END:
1114 break;
Daniel Veillardf4b4f982003-02-13 11:02:08 +00001115 case XML_XINCLUDE_START: {
1116 xmlNodePtr tmp, cur = set->nodeTab[i];
1117
1118 cur = cur->next;
1119 while (cur != NULL) {
1120 switch(cur->type) {
1121 case XML_TEXT_NODE:
1122 case XML_CDATA_SECTION_NODE:
1123 case XML_ELEMENT_NODE:
1124 case XML_ENTITY_REF_NODE:
1125 case XML_ENTITY_NODE:
1126 case XML_PI_NODE:
1127 case XML_COMMENT_NODE:
1128 tmp = xmlXIncludeCopyNode(ctxt, target,
1129 source, cur);
1130 if (last == NULL) {
1131 list = last = tmp;
1132 } else {
1133 xmlAddNextSibling(last, tmp);
1134 last = tmp;
1135 }
1136 cur = cur->next;
1137 continue;
1138 default:
1139 break;
1140 }
1141 break;
1142 }
1143 continue;
1144 }
Daniel Veillardc5f05ad2002-02-10 11:57:22 +00001145 case XML_ATTRIBUTE_NODE:
1146 case XML_NAMESPACE_DECL:
1147 case XML_DOCUMENT_TYPE_NODE:
1148 case XML_DOCUMENT_FRAG_NODE:
1149 case XML_NOTATION_NODE:
1150 case XML_DTD_NODE:
1151 case XML_ELEMENT_DECL:
1152 case XML_ATTRIBUTE_DECL:
1153 case XML_ENTITY_DECL:
1154 continue; /* for */
1155 }
1156 if (last == NULL)
1157 list = last = xmlXIncludeCopyNode(ctxt, target, source,
1158 set->nodeTab[i]);
1159 else {
1160 xmlAddNextSibling(last,
1161 xmlXIncludeCopyNode(ctxt, target, source,
1162 set->nodeTab[i]));
1163 if (last->next != NULL)
1164 last = last->next;
1165 }
1166 }
1167 break;
1168 }
1169 case XPATH_LOCATIONSET: {
1170 xmlLocationSetPtr set = (xmlLocationSetPtr) obj->user;
1171 if (set == NULL)
1172 return(NULL);
1173 for (i = 0;i < set->locNr;i++) {
1174 if (last == NULL)
1175 list = last = xmlXIncludeCopyXPointer(ctxt, target, source,
1176 set->locTab[i]);
1177 else
1178 xmlAddNextSibling(last,
1179 xmlXIncludeCopyXPointer(ctxt, target, source,
1180 set->locTab[i]));
1181 if (last != NULL) {
1182 while (last->next != NULL)
1183 last = last->next;
1184 }
1185 }
1186 break;
1187 }
Daniel Veillard10acc2f2003-09-01 20:59:40 +00001188#ifdef LIBXML_XPTR_ENABLED
Daniel Veillardc5f05ad2002-02-10 11:57:22 +00001189 case XPATH_RANGE:
1190 return(xmlXIncludeCopyRange(ctxt, target, source, obj));
Daniel Veillard10acc2f2003-09-01 20:59:40 +00001191#endif
Daniel Veillardc5f05ad2002-02-10 11:57:22 +00001192 case XPATH_POINT:
1193 /* points are ignored in XInclude */
1194 break;
1195 default:
1196 break;
1197 }
1198 return(list);
1199}
1200/************************************************************************
1201 * *
Owen Taylor3473f882001-02-23 17:55:21 +00001202 * XInclude I/O handling *
1203 * *
1204 ************************************************************************/
1205
Daniel Veillardf4b4f982003-02-13 11:02:08 +00001206typedef struct _xmlXIncludeMergeData xmlXIncludeMergeData;
1207typedef xmlXIncludeMergeData *xmlXIncludeMergeDataPtr;
1208struct _xmlXIncludeMergeData {
1209 xmlDocPtr doc;
1210 xmlXIncludeCtxtPtr ctxt;
1211};
1212
Owen Taylor3473f882001-02-23 17:55:21 +00001213/**
Daniel Veillard4287c572003-02-04 22:48:53 +00001214 * xmlXIncludeMergeOneEntity:
1215 * @ent: the entity
1216 * @doc: the including doc
1217 * @nr: the entity name
1218 *
1219 * Inplements the merge of one entity
1220 */
1221static void
Daniel Veillardf4b4f982003-02-13 11:02:08 +00001222xmlXIncludeMergeEntity(xmlEntityPtr ent, xmlXIncludeMergeDataPtr data,
Daniel Veillard4287c572003-02-04 22:48:53 +00001223 xmlChar *name ATTRIBUTE_UNUSED) {
Daniel Veillardf4b4f982003-02-13 11:02:08 +00001224 xmlEntityPtr ret, prev;
1225 xmlDocPtr doc;
1226 xmlXIncludeCtxtPtr ctxt;
Daniel Veillard4287c572003-02-04 22:48:53 +00001227
Daniel Veillardf4b4f982003-02-13 11:02:08 +00001228 if ((ent == NULL) || (data == NULL))
Daniel Veillard4287c572003-02-04 22:48:53 +00001229 return;
Daniel Veillardf4b4f982003-02-13 11:02:08 +00001230 ctxt = data->ctxt;
1231 doc = data->doc;
1232 if ((ctxt == NULL) || (doc == NULL))
1233 return;
1234 switch (ent->etype) {
1235 case XML_INTERNAL_PARAMETER_ENTITY:
1236 case XML_EXTERNAL_PARAMETER_ENTITY:
1237 case XML_INTERNAL_PREDEFINED_ENTITY:
1238 return;
1239 case XML_INTERNAL_GENERAL_ENTITY:
1240 case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
1241 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
1242 break;
1243 }
Daniel Veillard4287c572003-02-04 22:48:53 +00001244 ret = xmlAddDocEntity(doc, ent->name, ent->etype, ent->ExternalID,
1245 ent->SystemID, ent->content);
1246 if (ret != NULL) {
1247 if (ent->URI != NULL)
1248 ret->URI = xmlStrdup(ent->URI);
Daniel Veillardf4b4f982003-02-13 11:02:08 +00001249 } else {
1250 prev = xmlGetDocEntity(doc, ent->name);
1251 if (prev != NULL) {
1252 if (ent->etype != prev->etype)
1253 goto error;
1254
1255 if ((ent->SystemID != NULL) && (prev->SystemID != NULL)) {
1256 if (!xmlStrEqual(ent->SystemID, prev->SystemID))
1257 goto error;
Daniel Veillardb6c7f412003-03-29 16:41:55 +00001258 } else if ((ent->ExternalID != NULL) &&
1259 (prev->ExternalID != NULL)) {
Daniel Veillardf4b4f982003-02-13 11:02:08 +00001260 if (!xmlStrEqual(ent->ExternalID, prev->ExternalID))
1261 goto error;
Daniel Veillard2406abd2003-02-24 18:16:47 +00001262 } else if ((ent->content != NULL) && (prev->content != NULL)) {
1263 if (!xmlStrEqual(ent->content, prev->content))
1264 goto error;
Daniel Veillardf4b4f982003-02-13 11:02:08 +00001265 } else {
1266 goto error;
1267 }
1268
1269 }
Daniel Veillard4287c572003-02-04 22:48:53 +00001270 }
Daniel Veillardf4b4f982003-02-13 11:02:08 +00001271 return;
1272error:
Daniel Veillarda507fbf2003-03-31 16:09:37 +00001273 switch (ent->etype) {
1274 case XML_INTERNAL_PARAMETER_ENTITY:
1275 case XML_EXTERNAL_PARAMETER_ENTITY:
1276 case XML_INTERNAL_PREDEFINED_ENTITY:
1277 case XML_INTERNAL_GENERAL_ENTITY:
1278 case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
1279 return;
1280 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
1281 break;
1282 }
Daniel Veillardcd6ff282003-10-08 22:38:13 +00001283 xmlXIncludeErr(ctxt, (xmlNodePtr) ent, XML_XINCLUDE_ENTITY_DEF_MISMATCH,
1284 "mismatch in redefinition of entity %s\n",
1285 ent->name);
Daniel Veillard4287c572003-02-04 22:48:53 +00001286}
1287
1288/**
1289 * xmlXIncludeMergeEntities:
1290 * @ctxt: an XInclude context
1291 * @doc: the including doc
1292 * @from: the included doc
1293 *
1294 * Inplements the entity merge
1295 *
1296 * Returns 0 if merge succeeded, -1 if some processing failed
1297 */
1298static int
1299xmlXIncludeMergeEntities(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc,
1300 xmlDocPtr from) {
1301 xmlNodePtr cur;
1302 xmlDtdPtr target, source;
1303
1304 if (ctxt == NULL)
1305 return(-1);
1306
1307 if ((from == NULL) || (from->intSubset == NULL))
1308 return(0);
1309
1310 target = doc->intSubset;
1311 if (target == NULL) {
1312 cur = xmlDocGetRootElement(doc);
1313 if (cur == NULL)
1314 return(-1);
1315 target = xmlCreateIntSubset(doc, cur->name, NULL, NULL);
1316 if (target == NULL)
1317 return(-1);
1318 }
1319
1320 source = from->intSubset;
1321 if ((source != NULL) && (source->entities != NULL)) {
Daniel Veillardf4b4f982003-02-13 11:02:08 +00001322 xmlXIncludeMergeData data;
1323
1324 data.ctxt = ctxt;
1325 data.doc = doc;
1326
Daniel Veillard4287c572003-02-04 22:48:53 +00001327 xmlHashScan((xmlHashTablePtr) source->entities,
Daniel Veillardf4b4f982003-02-13 11:02:08 +00001328 (xmlHashScanner) xmlXIncludeMergeEntity, &data);
Daniel Veillard4287c572003-02-04 22:48:53 +00001329 }
1330 source = from->extSubset;
1331 if ((source != NULL) && (source->entities != NULL)) {
Daniel Veillardf4b4f982003-02-13 11:02:08 +00001332 xmlXIncludeMergeData data;
1333
1334 data.ctxt = ctxt;
1335 data.doc = doc;
1336
Daniel Veillard4287c572003-02-04 22:48:53 +00001337 /*
1338 * don't duplicate existing stuff when external subsets are the same
1339 */
1340 if ((!xmlStrEqual(target->ExternalID, source->ExternalID)) &&
1341 (!xmlStrEqual(target->SystemID, source->SystemID))) {
1342 xmlHashScan((xmlHashTablePtr) source->entities,
Daniel Veillardf4b4f982003-02-13 11:02:08 +00001343 (xmlHashScanner) xmlXIncludeMergeEntity, &data);
Daniel Veillard4287c572003-02-04 22:48:53 +00001344 }
1345 }
1346 return(0);
1347}
1348
1349/**
Owen Taylor3473f882001-02-23 17:55:21 +00001350 * xmlXIncludeLoadDoc:
1351 * @ctxt: the XInclude context
1352 * @url: the associated URL
1353 * @nr: the xinclude node number
1354 *
1355 * Load the document, and store the result in the XInclude context
Daniel Veillarde3b7d9a2002-08-14 14:11:30 +00001356 *
1357 * Returns 0 in case of success, -1 in case of failure
Owen Taylor3473f882001-02-23 17:55:21 +00001358 */
Daniel Veillarde3b7d9a2002-08-14 14:11:30 +00001359static int
Owen Taylor3473f882001-02-23 17:55:21 +00001360xmlXIncludeLoadDoc(xmlXIncludeCtxtPtr ctxt, const xmlChar *url, int nr) {
1361 xmlDocPtr doc;
1362 xmlURIPtr uri;
1363 xmlChar *URL;
1364 xmlChar *fragment = NULL;
Daniel Veillardbbc72c32002-09-05 10:52:10 +00001365 int i = 0;
William M. Brack4d59e222004-03-08 14:42:31 +00001366#ifdef LIBXML_XPTR_ENABLED
1367 int saveFlags;
1368#endif
Daniel Veillardbbc72c32002-09-05 10:52:10 +00001369
1370#ifdef DEBUG_XINCLUDE
1371 xmlGenericError(xmlGenericErrorContext, "Loading doc %s:%d\n", url, nr);
1372#endif
Owen Taylor3473f882001-02-23 17:55:21 +00001373 /*
1374 * Check the URL and remove any fragment identifier
1375 */
1376 uri = xmlParseURI((const char *)url);
1377 if (uri == NULL) {
Daniel Veillardcd6ff282003-10-08 22:38:13 +00001378 xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
1379 XML_XINCLUDE_HREF_URI,
1380 "invalid value URI %s\n", url);
Daniel Veillarde3b7d9a2002-08-14 14:11:30 +00001381 return(-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001382 }
1383 if (uri->fragment != NULL) {
1384 fragment = (xmlChar *) uri->fragment;
1385 uri->fragment = NULL;
1386 }
Daniel Veillardb98d0822003-12-24 11:06:25 +00001387 if ((ctxt->incTab != NULL) && (ctxt->incTab[nr] != NULL) &&
1388 (ctxt->incTab[nr]->fragment != NULL)) {
1389 if (fragment != NULL) xmlFree(fragment);
1390 fragment = xmlStrdup(ctxt->incTab[nr]->fragment);
1391 }
Owen Taylor3473f882001-02-23 17:55:21 +00001392 URL = xmlSaveUri(uri);
1393 xmlFreeURI(uri);
1394 if (URL == NULL) {
Daniel Veillardcd6ff282003-10-08 22:38:13 +00001395 xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
1396 XML_XINCLUDE_HREF_URI,
1397 "invalid value URI %s\n", url);
Owen Taylor3473f882001-02-23 17:55:21 +00001398 if (fragment != NULL)
1399 xmlFree(fragment);
Daniel Veillarde3b7d9a2002-08-14 14:11:30 +00001400 return(-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001401 }
1402
1403 /*
1404 * Handling of references to the local document are done
1405 * directly through ctxt->doc.
1406 */
Daniel Veillardf4b4f982003-02-13 11:02:08 +00001407 if ((URL[0] == 0) || (URL[0] == '#') ||
1408 ((ctxt->doc != NULL) && (xmlStrEqual(URL, ctxt->doc->URL)))) {
Owen Taylor3473f882001-02-23 17:55:21 +00001409 doc = NULL;
1410 goto loaded;
1411 }
1412
1413 /*
1414 * Prevent reloading twice the document.
1415 */
Daniel Veillardbbc72c32002-09-05 10:52:10 +00001416 for (i = 0; i < ctxt->incNr; i++) {
1417 if ((xmlStrEqual(URL, ctxt->incTab[i]->URI)) &&
1418 (ctxt->incTab[i]->doc != NULL)) {
1419 doc = ctxt->incTab[i]->doc;
1420#ifdef DEBUG_XINCLUDE
1421 printf("Already loaded %s\n", URL);
1422#endif
Owen Taylor3473f882001-02-23 17:55:21 +00001423 goto loaded;
1424 }
1425 }
Daniel Veillardbbc72c32002-09-05 10:52:10 +00001426
Owen Taylor3473f882001-02-23 17:55:21 +00001427 /*
1428 * Load it.
1429 */
Daniel Veillardbbc72c32002-09-05 10:52:10 +00001430#ifdef DEBUG_XINCLUDE
1431 printf("loading %s\n", URL);
1432#endif
William M. Brack4d59e222004-03-08 14:42:31 +00001433#ifdef LIBXML_XPTR_ENABLED
1434 /*
1435 * If this is an XPointer evaluation, we want to assure that
1436 * all entities have been resolved prior to processing the
1437 * referenced document
1438 */
1439 saveFlags = ctxt->parseFlags;
1440 if (fragment != NULL) { /* if this is an XPointer eval */
1441 ctxt->parseFlags |= XML_PARSE_NOENT;
1442 }
1443#endif
1444
Daniel Veillard98485322003-08-14 15:44:40 +00001445 doc = xmlXIncludeParseFile(ctxt, (const char *)URL);
William M. Brack4d59e222004-03-08 14:42:31 +00001446#ifdef LIBXML_XPTR_ENABLED
1447 ctxt->parseFlags = saveFlags;
1448#endif
Owen Taylor3473f882001-02-23 17:55:21 +00001449 if (doc == NULL) {
Owen Taylor3473f882001-02-23 17:55:21 +00001450 xmlFree(URL);
1451 if (fragment != NULL)
1452 xmlFree(fragment);
Daniel Veillarde3b7d9a2002-08-14 14:11:30 +00001453 return(-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001454 }
Daniel Veillardbbc72c32002-09-05 10:52:10 +00001455 ctxt->incTab[nr]->doc = doc;
Daniel Veillard98485322003-08-14 15:44:40 +00001456 for (i = nr + 1; i < ctxt->incNr; i++) {
1457 if (xmlStrEqual(URL, ctxt->incTab[i]->URI)) {
1458 ctxt->incTab[nr]->count++;
1459#ifdef DEBUG_XINCLUDE
1460 printf("Increasing %s count since reused\n", URL);
1461#endif
1462 break;
1463 }
1464 }
Daniel Veillardbbc72c32002-09-05 10:52:10 +00001465
1466 /*
Daniel Veillard4287c572003-02-04 22:48:53 +00001467 * Make sure we have all entities fixed up
Daniel Veillardbbc72c32002-09-05 10:52:10 +00001468 */
Daniel Veillard4287c572003-02-04 22:48:53 +00001469 xmlXIncludeMergeEntities(ctxt, ctxt->doc, doc);
Daniel Veillardbbc72c32002-09-05 10:52:10 +00001470
1471 /*
1472 * We don't need the DTD anymore, free up space
1473 if (doc->intSubset != NULL) {
1474 xmlUnlinkNode((xmlNodePtr) doc->intSubset);
1475 xmlFreeNode((xmlNodePtr) doc->intSubset);
1476 doc->intSubset = NULL;
1477 }
1478 if (doc->extSubset != NULL) {
1479 xmlUnlinkNode((xmlNodePtr) doc->extSubset);
1480 xmlFreeNode((xmlNodePtr) doc->extSubset);
1481 doc->extSubset = NULL;
1482 }
1483 */
1484 xmlXIncludeRecurseDoc(ctxt, doc, URL);
Owen Taylor3473f882001-02-23 17:55:21 +00001485
1486loaded:
1487 if (fragment == NULL) {
1488 /*
1489 * Add the top children list as the replacement copy.
Owen Taylor3473f882001-02-23 17:55:21 +00001490 */
1491 if (doc == NULL)
Daniel Veillard4497e692001-06-09 14:19:02 +00001492 {
1493 /* Hopefully a DTD declaration won't be copied from
1494 * the same document */
Daniel Veillardbbc72c32002-09-05 10:52:10 +00001495 ctxt->incTab[nr]->inc = xmlCopyNodeList(ctxt->doc->children);
Daniel Veillard4497e692001-06-09 14:19:02 +00001496 } else {
Daniel Veillardbbc72c32002-09-05 10:52:10 +00001497 ctxt->incTab[nr]->inc = xmlXIncludeCopyNodeList(ctxt, ctxt->doc,
Daniel Veillardc5f05ad2002-02-10 11:57:22 +00001498 doc, doc->children);
Daniel Veillard4497e692001-06-09 14:19:02 +00001499 }
Daniel Veillard10acc2f2003-09-01 20:59:40 +00001500 }
1501#ifdef LIBXML_XPTR_ENABLED
1502 else {
Owen Taylor3473f882001-02-23 17:55:21 +00001503 /*
1504 * Computes the XPointer expression and make a copy used
1505 * as the replacement copy.
1506 */
1507 xmlXPathObjectPtr xptr;
1508 xmlXPathContextPtr xptrctxt;
Daniel Veillard39196eb2001-06-19 18:09:42 +00001509 xmlNodeSetPtr set;
Owen Taylor3473f882001-02-23 17:55:21 +00001510
1511 if (doc == NULL) {
Daniel Veillardbbc72c32002-09-05 10:52:10 +00001512 xptrctxt = xmlXPtrNewContext(ctxt->doc, ctxt->incTab[nr]->ref,
1513 NULL);
Owen Taylor3473f882001-02-23 17:55:21 +00001514 } else {
1515 xptrctxt = xmlXPtrNewContext(doc, NULL, NULL);
1516 }
1517 if (xptrctxt == NULL) {
Daniel Veillardcd6ff282003-10-08 22:38:13 +00001518 xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
1519 XML_XINCLUDE_XPTR_FAILED,
Daniel Veillarda152c4d2003-11-19 16:24:26 +00001520 "could not create XPointer context\n", NULL);
Owen Taylor3473f882001-02-23 17:55:21 +00001521 xmlFree(URL);
1522 xmlFree(fragment);
Daniel Veillarde3b7d9a2002-08-14 14:11:30 +00001523 return(-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001524 }
1525 xptr = xmlXPtrEval(fragment, xptrctxt);
1526 if (xptr == NULL) {
Daniel Veillardcd6ff282003-10-08 22:38:13 +00001527 xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
1528 XML_XINCLUDE_XPTR_FAILED,
1529 "XPointer evaluation failed: #%s\n",
1530 fragment);
Owen Taylor3473f882001-02-23 17:55:21 +00001531 xmlXPathFreeContext(xptrctxt);
1532 xmlFree(URL);
1533 xmlFree(fragment);
Daniel Veillarde3b7d9a2002-08-14 14:11:30 +00001534 return(-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001535 }
Daniel Veillard39196eb2001-06-19 18:09:42 +00001536 switch (xptr->type) {
1537 case XPATH_UNDEFINED:
1538 case XPATH_BOOLEAN:
1539 case XPATH_NUMBER:
1540 case XPATH_STRING:
1541 case XPATH_POINT:
1542 case XPATH_USERS:
1543 case XPATH_XSLT_TREE:
Daniel Veillardcd6ff282003-10-08 22:38:13 +00001544 xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
1545 XML_XINCLUDE_XPTR_RESULT,
1546 "XPointer is not a range: #%s\n",
1547 fragment);
Daniel Veillard39196eb2001-06-19 18:09:42 +00001548 xmlXPathFreeContext(xptrctxt);
1549 xmlFree(URL);
1550 xmlFree(fragment);
Daniel Veillarde3b7d9a2002-08-14 14:11:30 +00001551 return(-1);
Daniel Veillard39196eb2001-06-19 18:09:42 +00001552 case XPATH_NODESET:
Daniel Veillard798ae542003-11-03 17:13:52 +00001553 if ((xptr->nodesetval == NULL) ||
1554 (xptr->nodesetval->nodeNr <= 0)) {
1555 xmlXPathFreeContext(xptrctxt);
1556 xmlFree(URL);
1557 xmlFree(fragment);
1558 return(-1);
1559 }
Daniel Veillard39196eb2001-06-19 18:09:42 +00001560 case XPATH_RANGE:
1561 case XPATH_LOCATIONSET:
1562 break;
1563 }
1564 set = xptr->nodesetval;
1565 if (set != NULL) {
1566 for (i = 0;i < set->nodeNr;i++) {
1567 if (set->nodeTab[i] == NULL)
1568 continue;
1569 switch (set->nodeTab[i]->type) {
1570 case XML_TEXT_NODE:
1571 case XML_CDATA_SECTION_NODE:
1572 case XML_ELEMENT_NODE:
1573 case XML_ENTITY_REF_NODE:
1574 case XML_ENTITY_NODE:
1575 case XML_PI_NODE:
1576 case XML_COMMENT_NODE:
1577 case XML_DOCUMENT_NODE:
1578 case XML_HTML_DOCUMENT_NODE:
1579#ifdef LIBXML_DOCB_ENABLED
1580 case XML_DOCB_DOCUMENT_NODE:
1581#endif
1582 continue;
1583 case XML_ATTRIBUTE_NODE:
Daniel Veillardcd6ff282003-10-08 22:38:13 +00001584 xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
1585 XML_XINCLUDE_XPTR_RESULT,
1586 "XPointer selects an attribute: #%s\n",
1587 fragment);
Daniel Veillard39196eb2001-06-19 18:09:42 +00001588 set->nodeTab[i] = NULL;
1589 continue;
1590 case XML_NAMESPACE_DECL:
Daniel Veillardcd6ff282003-10-08 22:38:13 +00001591 xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
1592 XML_XINCLUDE_XPTR_RESULT,
1593 "XPointer selects a namespace: #%s\n",
1594 fragment);
Daniel Veillard39196eb2001-06-19 18:09:42 +00001595 set->nodeTab[i] = NULL;
1596 continue;
1597 case XML_DOCUMENT_TYPE_NODE:
1598 case XML_DOCUMENT_FRAG_NODE:
1599 case XML_NOTATION_NODE:
1600 case XML_DTD_NODE:
1601 case XML_ELEMENT_DECL:
1602 case XML_ATTRIBUTE_DECL:
1603 case XML_ENTITY_DECL:
1604 case XML_XINCLUDE_START:
1605 case XML_XINCLUDE_END:
Daniel Veillardcd6ff282003-10-08 22:38:13 +00001606 xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
1607 XML_XINCLUDE_XPTR_RESULT,
1608 "XPointer selects unexpected nodes: #%s\n",
1609 fragment);
Daniel Veillard39196eb2001-06-19 18:09:42 +00001610 set->nodeTab[i] = NULL;
1611 set->nodeTab[i] = NULL;
1612 continue; /* for */
1613 }
1614 }
1615 }
Daniel Veillardf4b4f982003-02-13 11:02:08 +00001616 if (doc == NULL) {
1617 ctxt->incTab[nr]->xptr = xptr;
1618 ctxt->incTab[nr]->inc = NULL;
1619 } else {
1620 ctxt->incTab[nr]->inc =
1621 xmlXIncludeCopyXPointer(ctxt, ctxt->doc, doc, xptr);
1622 xmlXPathFreeObject(xptr);
1623 }
Owen Taylor3473f882001-02-23 17:55:21 +00001624 xmlXPathFreeContext(xptrctxt);
1625 xmlFree(fragment);
1626 }
Daniel Veillard10acc2f2003-09-01 20:59:40 +00001627#endif
Daniel Veillardc4bad4a2002-08-14 14:45:25 +00001628
1629 /*
1630 * Do the xml:base fixup if needed
1631 */
1632 if ((doc != NULL) && (URL != NULL) && (xmlStrchr(URL, (xmlChar) '/'))) {
1633 xmlNodePtr node;
1634
Daniel Veillardbbc72c32002-09-05 10:52:10 +00001635 node = ctxt->incTab[nr]->inc;
Daniel Veillardc4bad4a2002-08-14 14:45:25 +00001636 while (node != NULL) {
1637 if (node->type == XML_ELEMENT_NODE)
1638 xmlNodeSetBase(node, URL);
1639 node = node->next;
1640 }
1641 }
Daniel Veillardbbc72c32002-09-05 10:52:10 +00001642 if ((nr < ctxt->incNr) && (ctxt->incTab[nr]->doc != NULL) &&
1643 (ctxt->incTab[nr]->count <= 1)) {
1644#ifdef DEBUG_XINCLUDE
1645 printf("freeing %s\n", ctxt->incTab[nr]->doc->URL);
1646#endif
1647 xmlFreeDoc(ctxt->incTab[nr]->doc);
1648 ctxt->incTab[nr]->doc = NULL;
1649 }
Owen Taylor3473f882001-02-23 17:55:21 +00001650 xmlFree(URL);
Daniel Veillarde3b7d9a2002-08-14 14:11:30 +00001651 return(0);
Owen Taylor3473f882001-02-23 17:55:21 +00001652}
1653
1654/**
1655 * xmlXIncludeLoadTxt:
1656 * @ctxt: the XInclude context
1657 * @url: the associated URL
1658 * @nr: the xinclude node number
1659 *
1660 * Load the content, and store the result in the XInclude context
Daniel Veillarde3b7d9a2002-08-14 14:11:30 +00001661 *
1662 * Returns 0 in case of success, -1 in case of failure
Owen Taylor3473f882001-02-23 17:55:21 +00001663 */
Daniel Veillarde3b7d9a2002-08-14 14:11:30 +00001664static int
Owen Taylor3473f882001-02-23 17:55:21 +00001665xmlXIncludeLoadTxt(xmlXIncludeCtxtPtr ctxt, const xmlChar *url, int nr) {
1666 xmlParserInputBufferPtr buf;
1667 xmlNodePtr node;
1668 xmlURIPtr uri;
1669 xmlChar *URL;
1670 int i;
Daniel Veillardd076a202002-11-20 13:28:31 +00001671 xmlChar *encoding = NULL;
William M. Brack78637da2003-07-31 14:47:38 +00001672 xmlCharEncoding enc = (xmlCharEncoding) 0;
Daniel Veillardd076a202002-11-20 13:28:31 +00001673
Owen Taylor3473f882001-02-23 17:55:21 +00001674 /*
1675 * Check the URL and remove any fragment identifier
1676 */
1677 uri = xmlParseURI((const char *)url);
1678 if (uri == NULL) {
Daniel Veillardcd6ff282003-10-08 22:38:13 +00001679 xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref, XML_XINCLUDE_HREF_URI,
1680 "invalid value URI %s\n", url);
Daniel Veillarde3b7d9a2002-08-14 14:11:30 +00001681 return(-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001682 }
1683 if (uri->fragment != NULL) {
Daniel Veillardcd6ff282003-10-08 22:38:13 +00001684 xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref, XML_XINCLUDE_TEXT_FRAGMENT,
1685 "fragment identifier forbidden for text: %s\n",
1686 (const xmlChar *) uri->fragment);
Owen Taylor3473f882001-02-23 17:55:21 +00001687 xmlFreeURI(uri);
Daniel Veillarde3b7d9a2002-08-14 14:11:30 +00001688 return(-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001689 }
1690 URL = xmlSaveUri(uri);
1691 xmlFreeURI(uri);
1692 if (URL == NULL) {
Daniel Veillardcd6ff282003-10-08 22:38:13 +00001693 xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref, XML_XINCLUDE_HREF_URI,
1694 "invalid value URI %s\n", url);
Daniel Veillarde3b7d9a2002-08-14 14:11:30 +00001695 return(-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001696 }
1697
1698 /*
1699 * Handling of references to the local document are done
1700 * directly through ctxt->doc.
1701 */
1702 if (URL[0] == 0) {
Daniel Veillardcd6ff282003-10-08 22:38:13 +00001703 xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
1704 XML_XINCLUDE_TEXT_DOCUMENT,
1705 "text serialization of document not available\n", NULL);
Owen Taylor3473f882001-02-23 17:55:21 +00001706 xmlFree(URL);
Daniel Veillarde3b7d9a2002-08-14 14:11:30 +00001707 return(-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001708 }
1709
1710 /*
1711 * Prevent reloading twice the document.
1712 */
1713 for (i = 0; i < ctxt->txtNr; i++) {
1714 if (xmlStrEqual(URL, ctxt->txturlTab[i])) {
1715 node = xmlCopyNode(ctxt->txtTab[i], 1);
1716 goto loaded;
1717 }
1718 }
1719 /*
Daniel Veillardd076a202002-11-20 13:28:31 +00001720 * Try to get the encoding if available
Owen Taylor3473f882001-02-23 17:55:21 +00001721 */
Daniel Veillardd076a202002-11-20 13:28:31 +00001722 if ((ctxt->incTab[nr] != NULL) && (ctxt->incTab[nr]->ref != NULL)) {
1723 encoding = xmlGetProp(ctxt->incTab[nr]->ref, XINCLUDE_PARSE_ENCODING);
1724 }
1725 if (encoding != NULL) {
1726 /*
1727 * TODO: we should not have to remap to the xmlCharEncoding
1728 * predefined set, a better interface than
1729 * xmlParserInputBufferCreateFilename should allow any
1730 * encoding supported by iconv
1731 */
1732 enc = xmlParseCharEncoding((const char *) encoding);
1733 if (enc == XML_CHAR_ENCODING_ERROR) {
Daniel Veillardcd6ff282003-10-08 22:38:13 +00001734 xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
1735 XML_XINCLUDE_UNKNOWN_ENCODING,
1736 "encoding %s not supported\n", encoding);
Daniel Veillardd076a202002-11-20 13:28:31 +00001737 xmlFree(encoding);
1738 xmlFree(URL);
1739 return(-1);
1740 }
1741 xmlFree(encoding);
1742 }
1743
1744 /*
1745 * Load it.
1746 */
1747 buf = xmlParserInputBufferCreateFilename((const char *)URL, enc);
Owen Taylor3473f882001-02-23 17:55:21 +00001748 if (buf == NULL) {
Owen Taylor3473f882001-02-23 17:55:21 +00001749 xmlFree(URL);
Daniel Veillarde3b7d9a2002-08-14 14:11:30 +00001750 return(-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001751 }
1752 node = xmlNewText(NULL);
1753
1754 /*
1755 * Scan all chars from the resource and add the to the node
1756 */
1757 while (xmlParserInputBufferRead(buf, 128) > 0) {
1758 int len;
1759 const xmlChar *content;
1760
1761 content = xmlBufferContent(buf->buffer);
1762 len = xmlBufferLength(buf->buffer);
Daniel Veillardd076a202002-11-20 13:28:31 +00001763 for (i = 0;i < len;) {
1764 int cur;
1765 int l;
1766
1767 cur = xmlStringCurrentChar(NULL, &content[i], &l);
1768 if (!IS_CHAR(cur)) {
Daniel Veillardcd6ff282003-10-08 22:38:13 +00001769 xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
1770 XML_XINCLUDE_INVALID_CHAR,
1771 "%s contains invalid char\n", URL);
Owen Taylor3473f882001-02-23 17:55:21 +00001772 } else {
Daniel Veillardd076a202002-11-20 13:28:31 +00001773 xmlNodeAddContentLen(node, &content[i], l);
Owen Taylor3473f882001-02-23 17:55:21 +00001774 }
Daniel Veillardd076a202002-11-20 13:28:31 +00001775 i += l;
Owen Taylor3473f882001-02-23 17:55:21 +00001776 }
1777 xmlBufferShrink(buf->buffer, len);
1778 }
1779 xmlFreeParserInputBuffer(buf);
1780 xmlXIncludeAddTxt(ctxt, node, URL);
1781
1782loaded:
1783 /*
1784 * Add the element as the replacement copy.
1785 */
Daniel Veillardbbc72c32002-09-05 10:52:10 +00001786 ctxt->incTab[nr]->inc = node;
Owen Taylor3473f882001-02-23 17:55:21 +00001787 xmlFree(URL);
Daniel Veillarde3b7d9a2002-08-14 14:11:30 +00001788 return(0);
1789}
1790
1791/**
1792 * xmlXIncludeLoadFallback:
1793 * @ctxt: the XInclude context
1794 * @fallback: the fallback node
1795 * @nr: the xinclude node number
1796 *
Daniel Veillardbbc72c32002-09-05 10:52:10 +00001797 * Load the content of the fallback node, and store the result
Daniel Veillarde3b7d9a2002-08-14 14:11:30 +00001798 * in the XInclude context
1799 *
1800 * Returns 0 in case of success, -1 in case of failure
1801 */
1802static int
1803xmlXIncludeLoadFallback(xmlXIncludeCtxtPtr ctxt, xmlNodePtr fallback, int nr) {
William M. Brackaae10522004-01-02 14:59:41 +00001804 xmlXIncludeCtxtPtr newctxt;
1805 int ret = 0;
1806
Daniel Veillarde3b7d9a2002-08-14 14:11:30 +00001807 if ((fallback == NULL) || (ctxt == NULL))
1808 return(-1);
William M. Brackef245fd2004-02-06 09:33:59 +00001809 if (fallback->children != NULL) {
1810 /*
1811 * It's possible that the fallback also has 'includes'
1812 * (Bug 129969), so we re-process the fallback just in case
1813 */
1814 newctxt = xmlXIncludeNewContext(ctxt->doc);
1815 if (newctxt == NULL)
1816 return (-1);
1817 xmlXIncludeSetFlags(newctxt, ctxt->parseFlags);
1818 ret = xmlXIncludeDoProcess(newctxt, ctxt->doc, fallback->children);
William M. Brack87640d52004-04-17 14:58:15 +00001819 if (ctxt->nbErrors > 0)
William M. Brackef245fd2004-02-06 09:33:59 +00001820 ret = -1;
William M. Brack87640d52004-04-17 14:58:15 +00001821 else if (ret > 0)
1822 ret = 0; /* xmlXIncludeDoProcess can return +ve number */
William M. Brackef245fd2004-02-06 09:33:59 +00001823 xmlXIncludeFreeContext(newctxt);
Daniel Veillarde3b7d9a2002-08-14 14:11:30 +00001824
William M. Brackef245fd2004-02-06 09:33:59 +00001825 ctxt->incTab[nr]->inc = xmlCopyNodeList(fallback->children);
1826 } else {
1827 ctxt->incTab[nr]->inc = NULL;
William M. Brack95af5942004-02-08 04:12:49 +00001828 ctxt->incTab[nr]->emptyFb = 1; /* flag empty callback */
William M. Brackef245fd2004-02-06 09:33:59 +00001829 }
William M. Brackaae10522004-01-02 14:59:41 +00001830 return(ret);
Owen Taylor3473f882001-02-23 17:55:21 +00001831}
1832
1833/************************************************************************
1834 * *
1835 * XInclude Processing *
1836 * *
1837 ************************************************************************/
1838
1839/**
1840 * xmlXIncludePreProcessNode:
1841 * @ctxt: an XInclude context
1842 * @node: an XInclude node
1843 *
Daniel Veillardd16df9f2001-05-23 13:44:21 +00001844 * Implement the XInclude preprocessing, currently just adding the element
1845 * for further processing.
Owen Taylor3473f882001-02-23 17:55:21 +00001846 *
1847 * Returns the result list or NULL in case of error
1848 */
Daniel Veillard56a4cb82001-03-24 17:00:36 +00001849static xmlNodePtr
Owen Taylor3473f882001-02-23 17:55:21 +00001850xmlXIncludePreProcessNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node) {
1851 xmlXIncludeAddNode(ctxt, node);
1852 return(0);
1853}
1854
Daniel Veillardbbc72c32002-09-05 10:52:10 +00001855/**
Owen Taylor3473f882001-02-23 17:55:21 +00001856 * xmlXIncludeLoadNode:
1857 * @ctxt: an XInclude context
1858 * @nr: the node number
1859 *
1860 * Find and load the infoset replacement for the given node.
1861 *
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001862 * Returns 0 if substitution succeeded, -1 if some processing failed
Owen Taylor3473f882001-02-23 17:55:21 +00001863 */
Daniel Veillard56a4cb82001-03-24 17:00:36 +00001864static int
Owen Taylor3473f882001-02-23 17:55:21 +00001865xmlXIncludeLoadNode(xmlXIncludeCtxtPtr ctxt, int nr) {
1866 xmlNodePtr cur;
1867 xmlChar *href;
1868 xmlChar *parse;
1869 xmlChar *base;
1870 xmlChar *URI;
1871 int xml = 1; /* default Issue 64 */
Daniel Veillarde3b7d9a2002-08-14 14:11:30 +00001872 int ret;
Owen Taylor3473f882001-02-23 17:55:21 +00001873
1874 if (ctxt == NULL)
1875 return(-1);
1876 if ((nr < 0) || (nr >= ctxt->incNr))
1877 return(-1);
Daniel Veillardbbc72c32002-09-05 10:52:10 +00001878 cur = ctxt->incTab[nr]->ref;
Owen Taylor3473f882001-02-23 17:55:21 +00001879 if (cur == NULL)
1880 return(-1);
1881
Owen Taylor3473f882001-02-23 17:55:21 +00001882 /*
1883 * read the attributes
1884 */
Daniel Veillardb5fa0202003-12-08 17:41:29 +00001885 href = xmlXIncludeGetProp(ctxt, cur, XINCLUDE_HREF);
Owen Taylor3473f882001-02-23 17:55:21 +00001886 if (href == NULL) {
Daniel Veillard03c2f0a2004-01-25 19:54:59 +00001887 href = xmlStrdup(BAD_CAST ""); /* @@@@ href is now optional */
1888 if (href == NULL)
1889 return(-1);
Owen Taylor3473f882001-02-23 17:55:21 +00001890 }
Daniel Veillardb5fa0202003-12-08 17:41:29 +00001891 parse = xmlXIncludeGetProp(ctxt, cur, XINCLUDE_PARSE);
Owen Taylor3473f882001-02-23 17:55:21 +00001892 if (parse != NULL) {
1893 if (xmlStrEqual(parse, XINCLUDE_PARSE_XML))
1894 xml = 1;
1895 else if (xmlStrEqual(parse, XINCLUDE_PARSE_TEXT))
1896 xml = 0;
1897 else {
Daniel Veillardcd6ff282003-10-08 22:38:13 +00001898 xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
1899 XML_XINCLUDE_PARSE_VALUE,
1900 "invalid value %s for 'parse'\n", parse);
Owen Taylor3473f882001-02-23 17:55:21 +00001901 if (href != NULL)
1902 xmlFree(href);
1903 if (parse != NULL)
1904 xmlFree(parse);
1905 return(-1);
1906 }
1907 }
1908
1909 /*
1910 * compute the URI
1911 */
1912 base = xmlNodeGetBase(ctxt->doc, cur);
1913 if (base == NULL) {
1914 URI = xmlBuildURI(href, ctxt->doc->URL);
1915 } else {
1916 URI = xmlBuildURI(href, base);
1917 }
1918 if (URI == NULL) {
1919 xmlChar *escbase;
1920 xmlChar *eschref;
1921 /*
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001922 * Some escaping may be needed
Owen Taylor3473f882001-02-23 17:55:21 +00001923 */
1924 escbase = xmlURIEscape(base);
1925 eschref = xmlURIEscape(href);
1926 URI = xmlBuildURI(eschref, escbase);
1927 if (escbase != NULL)
1928 xmlFree(escbase);
1929 if (eschref != NULL)
1930 xmlFree(eschref);
1931 }
1932 if (URI == NULL) {
Daniel Veillardcd6ff282003-10-08 22:38:13 +00001933 xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
1934 XML_XINCLUDE_HREF_URI, "failed build URL\n", NULL);
Owen Taylor3473f882001-02-23 17:55:21 +00001935 if (parse != NULL)
1936 xmlFree(parse);
1937 if (href != NULL)
1938 xmlFree(href);
1939 if (base != NULL)
1940 xmlFree(base);
1941 return(-1);
1942 }
1943#ifdef DEBUG_XINCLUDE
1944 xmlGenericError(xmlGenericErrorContext, "parse: %s\n",
1945 xml ? "xml": "text");
1946 xmlGenericError(xmlGenericErrorContext, "URI: %s\n", URI);
1947#endif
1948
1949 /*
1950 * Cleanup
1951 */
1952 if (xml) {
Daniel Veillarde3b7d9a2002-08-14 14:11:30 +00001953 ret = xmlXIncludeLoadDoc(ctxt, URI, nr);
Owen Taylor3473f882001-02-23 17:55:21 +00001954 /* xmlXIncludeGetFragment(ctxt, cur, URI); */
1955 } else {
Daniel Veillarde3b7d9a2002-08-14 14:11:30 +00001956 ret = xmlXIncludeLoadTxt(ctxt, URI, nr);
1957 }
1958 if (ret < 0) {
1959 xmlNodePtr children;
1960
1961 /*
1962 * Time to try a fallback if availble
1963 */
1964#ifdef DEBUG_XINCLUDE
1965 xmlGenericError(xmlGenericErrorContext, "error looking for fallback\n");
1966#endif
1967 children = cur->children;
1968 while (children != NULL) {
1969 if ((children->type == XML_ELEMENT_NODE) &&
1970 (children->ns != NULL) &&
1971 (xmlStrEqual(children->name, XINCLUDE_FALLBACK)) &&
Daniel Veillardb5fa0202003-12-08 17:41:29 +00001972 ((xmlStrEqual(children->ns->href, XINCLUDE_NS)) ||
1973 (xmlStrEqual(children->ns->href, XINCLUDE_OLD_NS)))) {
Daniel Veillarde3b7d9a2002-08-14 14:11:30 +00001974 ret = xmlXIncludeLoadFallback(ctxt, children, nr);
William M. Brack1ff42132003-12-31 14:05:15 +00001975 if (ret == 0)
Daniel Veillarde3b7d9a2002-08-14 14:11:30 +00001976 break;
1977 }
1978 children = children->next;
1979 }
1980 }
1981 if (ret < 0) {
Daniel Veillardcd6ff282003-10-08 22:38:13 +00001982 xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
1983 XML_XINCLUDE_NO_FALLBACK,
1984 "could not load %s, and no fallback was found\n",
1985 URI);
Owen Taylor3473f882001-02-23 17:55:21 +00001986 }
1987
1988 /*
1989 * Cleanup
1990 */
1991 if (URI != NULL)
1992 xmlFree(URI);
1993 if (parse != NULL)
1994 xmlFree(parse);
1995 if (href != NULL)
1996 xmlFree(href);
1997 if (base != NULL)
1998 xmlFree(base);
1999 return(0);
2000}
2001
2002/**
2003 * xmlXIncludeIncludeNode:
2004 * @ctxt: an XInclude context
2005 * @nr: the node number
2006 *
2007 * Inplement the infoset replacement for the given node
2008 *
Daniel Veillardcbaf3992001-12-31 16:16:02 +00002009 * Returns 0 if substitution succeeded, -1 if some processing failed
Owen Taylor3473f882001-02-23 17:55:21 +00002010 */
Daniel Veillard56a4cb82001-03-24 17:00:36 +00002011static int
Owen Taylor3473f882001-02-23 17:55:21 +00002012xmlXIncludeIncludeNode(xmlXIncludeCtxtPtr ctxt, int nr) {
Daniel Veillardf4b4f982003-02-13 11:02:08 +00002013 xmlNodePtr cur, end, list, tmp;
Owen Taylor3473f882001-02-23 17:55:21 +00002014
2015 if (ctxt == NULL)
2016 return(-1);
2017 if ((nr < 0) || (nr >= ctxt->incNr))
2018 return(-1);
Daniel Veillardbbc72c32002-09-05 10:52:10 +00002019 cur = ctxt->incTab[nr]->ref;
Owen Taylor3473f882001-02-23 17:55:21 +00002020 if (cur == NULL)
2021 return(-1);
2022
2023 /*
Daniel Veillardf4b4f982003-02-13 11:02:08 +00002024 * If we stored an XPointer a late computation may be needed
2025 */
2026 if ((ctxt->incTab[nr]->inc == NULL) &&
2027 (ctxt->incTab[nr]->xptr != NULL)) {
2028 ctxt->incTab[nr]->inc =
2029 xmlXIncludeCopyXPointer(ctxt, ctxt->doc, ctxt->doc,
2030 ctxt->incTab[nr]->xptr);
2031 xmlXPathFreeObject(ctxt->incTab[nr]->xptr);
2032 ctxt->incTab[nr]->xptr = NULL;
2033 }
2034 list = ctxt->incTab[nr]->inc;
2035 ctxt->incTab[nr]->inc = NULL;
2036
2037 /*
2038 * Check against the risk of generating a multi-rooted document
2039 */
2040 if ((cur->parent != NULL) &&
2041 (cur->parent->type != XML_ELEMENT_NODE)) {
2042 int nb_elem = 0;
2043
2044 tmp = list;
2045 while (tmp != NULL) {
2046 if (tmp->type == XML_ELEMENT_NODE)
2047 nb_elem++;
2048 tmp = tmp->next;
2049 }
2050 if (nb_elem > 1) {
Daniel Veillardcd6ff282003-10-08 22:38:13 +00002051 xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
2052 XML_XINCLUDE_MULTIPLE_ROOT,
2053 "XInclude error: would result in multiple root nodes\n",
2054 NULL);
Daniel Veillardf4b4f982003-02-13 11:02:08 +00002055 return(-1);
2056 }
2057 }
2058
2059 /*
Owen Taylor3473f882001-02-23 17:55:21 +00002060 * Change the current node as an XInclude start one, and add an
2061 * entity end one
2062 */
2063 cur->type = XML_XINCLUDE_START;
2064 end = xmlNewNode(cur->ns, cur->name);
2065 if (end == NULL) {
Daniel Veillardcd6ff282003-10-08 22:38:13 +00002066 xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref, XML_XINCLUDE_BUILD_FAILED,
2067 "failed to build node\n", NULL);
Owen Taylor3473f882001-02-23 17:55:21 +00002068 return(-1);
2069 }
2070 end->type = XML_XINCLUDE_END;
2071 xmlAddNextSibling(cur, end);
2072
2073 /*
2074 * Add the list of nodes
2075 */
Owen Taylor3473f882001-02-23 17:55:21 +00002076 while (list != NULL) {
2077 cur = list;
2078 list = list->next;
2079
2080 xmlAddPrevSibling(end, cur);
2081 }
Daniel Veillardc5f05ad2002-02-10 11:57:22 +00002082
2083
Owen Taylor3473f882001-02-23 17:55:21 +00002084 return(0);
2085}
2086
2087/**
2088 * xmlXIncludeTestNode:
Daniel Veillardf4b4f982003-02-13 11:02:08 +00002089 * @ctxt: the XInclude processing context
Owen Taylor3473f882001-02-23 17:55:21 +00002090 * @node: an XInclude node
2091 *
2092 * test if the node is an XInclude node
2093 *
2094 * Returns 1 true, 0 otherwise
2095 */
Daniel Veillard56a4cb82001-03-24 17:00:36 +00002096static int
Daniel Veillardf4b4f982003-02-13 11:02:08 +00002097xmlXIncludeTestNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node) {
Owen Taylor3473f882001-02-23 17:55:21 +00002098 if (node == NULL)
2099 return(0);
Daniel Veillardffe4f5e2003-07-06 17:35:43 +00002100 if (node->type != XML_ELEMENT_NODE)
2101 return(0);
Owen Taylor3473f882001-02-23 17:55:21 +00002102 if (node->ns == NULL)
2103 return(0);
Daniel Veillardb5fa0202003-12-08 17:41:29 +00002104 if ((xmlStrEqual(node->ns->href, XINCLUDE_NS)) ||
2105 (xmlStrEqual(node->ns->href, XINCLUDE_OLD_NS))) {
2106 if (xmlStrEqual(node->ns->href, XINCLUDE_OLD_NS)) {
2107 if (ctxt->legacy == 0) {
Daniel Veillard5bb9ccd2004-02-09 12:39:02 +00002108#if 0 /* wait for the XML Core Working Group to get something stable ! */
Daniel Veillardb5fa0202003-12-08 17:41:29 +00002109 xmlXIncludeWarn(ctxt, node, XML_XINCLUDE_DEPRECATED_NS,
2110 "Deprecated XInclude namespace found, use %s",
2111 XINCLUDE_NS);
Daniel Veillard5bb9ccd2004-02-09 12:39:02 +00002112#endif
Daniel Veillarde74d2e12003-12-09 11:35:37 +00002113 ctxt->legacy = 1;
Daniel Veillardb5fa0202003-12-08 17:41:29 +00002114 }
2115 }
Daniel Veillardf4b4f982003-02-13 11:02:08 +00002116 if (xmlStrEqual(node->name, XINCLUDE_NODE)) {
2117 xmlNodePtr child = node->children;
2118 int nb_fallback = 0;
2119
2120 while (child != NULL) {
2121 if ((child->type == XML_ELEMENT_NODE) &&
2122 (child->ns != NULL) &&
Daniel Veillardb5fa0202003-12-08 17:41:29 +00002123 ((xmlStrEqual(child->ns->href, XINCLUDE_NS)) ||
2124 (xmlStrEqual(child->ns->href, XINCLUDE_OLD_NS)))) {
Daniel Veillardf4b4f982003-02-13 11:02:08 +00002125 if (xmlStrEqual(child->name, XINCLUDE_NODE)) {
Daniel Veillardcd6ff282003-10-08 22:38:13 +00002126 xmlXIncludeErr(ctxt, node,
2127 XML_XINCLUDE_INCLUDE_IN_INCLUDE,
2128 "%s has an 'include' child\n",
2129 XINCLUDE_NODE);
Daniel Veillardf4b4f982003-02-13 11:02:08 +00002130 return(0);
2131 }
2132 if (xmlStrEqual(child->name, XINCLUDE_FALLBACK)) {
2133 nb_fallback++;
2134 }
2135 }
2136 child = child->next;
2137 }
2138 if (nb_fallback > 1) {
Daniel Veillardcd6ff282003-10-08 22:38:13 +00002139 xmlXIncludeErr(ctxt, node, XML_XINCLUDE_FALLBACKS_IN_INCLUDE,
2140 "%s has multiple fallback children\n",
2141 XINCLUDE_NODE);
Daniel Veillardf4b4f982003-02-13 11:02:08 +00002142 return(0);
2143 }
2144 return(1);
2145 }
2146 if (xmlStrEqual(node->name, XINCLUDE_FALLBACK)) {
2147 if ((node->parent == NULL) ||
2148 (node->parent->type != XML_ELEMENT_NODE) ||
2149 (node->parent->ns == NULL) ||
Daniel Veillardb5fa0202003-12-08 17:41:29 +00002150 ((!xmlStrEqual(node->parent->ns->href, XINCLUDE_NS)) &&
2151 (!xmlStrEqual(node->parent->ns->href, XINCLUDE_OLD_NS))) ||
Daniel Veillardf4b4f982003-02-13 11:02:08 +00002152 (!xmlStrEqual(node->parent->name, XINCLUDE_NODE))) {
Daniel Veillardcd6ff282003-10-08 22:38:13 +00002153 xmlXIncludeErr(ctxt, node,
2154 XML_XINCLUDE_FALLBACK_NOT_IN_INCLUDE,
2155 "%s is not the child of an 'include'\n",
2156 XINCLUDE_FALLBACK);
Daniel Veillardf4b4f982003-02-13 11:02:08 +00002157 }
2158 }
2159 }
Owen Taylor3473f882001-02-23 17:55:21 +00002160 return(0);
2161}
2162
2163/**
Daniel Veillardd16df9f2001-05-23 13:44:21 +00002164 * xmlXIncludeDoProcess:
Daniel Veillardf4b4f982003-02-13 11:02:08 +00002165 * @ctxt: the XInclude processing context
Owen Taylor3473f882001-02-23 17:55:21 +00002166 * @doc: an XML document
Daniel Veillard8edf1c52003-07-22 20:52:14 +00002167 * @tree: the top of the tree to process
Owen Taylor3473f882001-02-23 17:55:21 +00002168 *
2169 * Implement the XInclude substitution on the XML document @doc
2170 *
Daniel Veillardcbaf3992001-12-31 16:16:02 +00002171 * Returns 0 if no substitution were done, -1 if some processing failed
Owen Taylor3473f882001-02-23 17:55:21 +00002172 * or the number of substitutions done.
2173 */
Daniel Veillardd16df9f2001-05-23 13:44:21 +00002174static int
Daniel Veillard8edf1c52003-07-22 20:52:14 +00002175xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr tree) {
Owen Taylor3473f882001-02-23 17:55:21 +00002176 xmlNodePtr cur;
2177 int ret = 0;
2178 int i;
2179
Daniel Veillard8edf1c52003-07-22 20:52:14 +00002180 if ((doc == NULL) || (tree == NULL))
Owen Taylor3473f882001-02-23 17:55:21 +00002181 return(-1);
Owen Taylor3473f882001-02-23 17:55:21 +00002182 if (ctxt == NULL)
2183 return(-1);
2184
Daniel Veillardf4b4f982003-02-13 11:02:08 +00002185 if (doc->URL != NULL) {
2186 ret = xmlXIncludeURLPush(ctxt, doc->URL);
2187 if (ret < 0)
2188 return(-1);
2189 }
2190
Owen Taylor3473f882001-02-23 17:55:21 +00002191 /*
2192 * First phase: lookup the elements in the document
2193 */
Daniel Veillard8edf1c52003-07-22 20:52:14 +00002194 cur = tree;
Daniel Veillardf4b4f982003-02-13 11:02:08 +00002195 if (xmlXIncludeTestNode(ctxt, cur) == 1)
Owen Taylor3473f882001-02-23 17:55:21 +00002196 xmlXIncludePreProcessNode(ctxt, cur);
William M. Brack7b0e2762004-05-12 09:33:23 +00002197 while ((cur != NULL) && (cur != tree->parent)) {
Owen Taylor3473f882001-02-23 17:55:21 +00002198 /* TODO: need to work on entities -> stack */
2199 if ((cur->children != NULL) &&
Daniel Veillardffe4f5e2003-07-06 17:35:43 +00002200 (cur->children->type != XML_ENTITY_DECL) &&
2201 (cur->children->type != XML_XINCLUDE_START) &&
2202 (cur->children->type != XML_XINCLUDE_END)) {
Owen Taylor3473f882001-02-23 17:55:21 +00002203 cur = cur->children;
Daniel Veillardf4b4f982003-02-13 11:02:08 +00002204 if (xmlXIncludeTestNode(ctxt, cur))
Owen Taylor3473f882001-02-23 17:55:21 +00002205 xmlXIncludePreProcessNode(ctxt, cur);
2206 } else if (cur->next != NULL) {
2207 cur = cur->next;
Daniel Veillardf4b4f982003-02-13 11:02:08 +00002208 if (xmlXIncludeTestNode(ctxt, cur))
Owen Taylor3473f882001-02-23 17:55:21 +00002209 xmlXIncludePreProcessNode(ctxt, cur);
2210 } else {
William M. Brack5d8d10b2004-04-16 08:11:26 +00002211 if (cur == tree)
2212 break;
Owen Taylor3473f882001-02-23 17:55:21 +00002213 do {
2214 cur = cur->parent;
William M. Brack7b0e2762004-05-12 09:33:23 +00002215 if ((cur == NULL) || (cur == tree->parent))
2216 break; /* do */
Owen Taylor3473f882001-02-23 17:55:21 +00002217 if (cur->next != NULL) {
2218 cur = cur->next;
Daniel Veillardf4b4f982003-02-13 11:02:08 +00002219 if (xmlXIncludeTestNode(ctxt, cur))
Owen Taylor3473f882001-02-23 17:55:21 +00002220 xmlXIncludePreProcessNode(ctxt, cur);
2221 break; /* do */
2222 }
2223 } while (cur != NULL);
2224 }
2225 }
2226
2227 /*
2228 * Second Phase : collect the infosets fragments
2229 */
Daniel Veillardbbc72c32002-09-05 10:52:10 +00002230 for (i = ctxt->incBase;i < ctxt->incNr; i++) {
Owen Taylor3473f882001-02-23 17:55:21 +00002231 xmlXIncludeLoadNode(ctxt, i);
Daniel Veillard97fd5672003-02-07 13:01:54 +00002232 ret++;
Owen Taylor3473f882001-02-23 17:55:21 +00002233 }
2234
2235 /*
2236 * Third phase: extend the original document infoset.
William M. Brack6b1a28d2004-02-06 11:24:44 +00002237 *
2238 * Originally we bypassed the inclusion if there were any errors
2239 * encountered on any of the XIncludes. A bug was raised (bug
2240 * 132588) requesting that we output the XIncludes without error,
2241 * so the check for inc!=NULL || xptr!=NULL was put in. This may
2242 * give some other problems in the future, but for now it seems to
2243 * work ok.
2244 *
Owen Taylor3473f882001-02-23 17:55:21 +00002245 */
William M. Brack6b1a28d2004-02-06 11:24:44 +00002246 for (i = ctxt->incBase;i < ctxt->incNr; i++) {
William M. Brack95af5942004-02-08 04:12:49 +00002247 if ((ctxt->incTab[i]->inc != NULL) ||
2248 (ctxt->incTab[i]->xptr != NULL) ||
2249 (ctxt->incTab[i]->emptyFb != 0)) /* (empty fallback) */
Daniel Veillardf4b4f982003-02-13 11:02:08 +00002250 xmlXIncludeIncludeNode(ctxt, i);
Owen Taylor3473f882001-02-23 17:55:21 +00002251 }
2252
Daniel Veillardf4b4f982003-02-13 11:02:08 +00002253 if (doc->URL != NULL)
2254 xmlXIncludeURLPop(ctxt);
Daniel Veillardd16df9f2001-05-23 13:44:21 +00002255 return(ret);
2256}
2257
2258/**
Daniel Veillarde74d2e12003-12-09 11:35:37 +00002259 * xmlXIncludeSetFlags:
2260 * @ctxt: an XInclude processing context
2261 * @flags: a set of xmlParserOption used for parsing XML includes
2262 *
2263 * Set the flags used for further processing of XML resources.
2264 *
2265 * Returns 0 in case of success and -1 in case of error.
2266 */
2267int
2268xmlXIncludeSetFlags(xmlXIncludeCtxtPtr ctxt, int flags) {
2269 if (ctxt == NULL)
2270 return(-1);
2271 ctxt->parseFlags = flags;
2272 return(0);
2273}
2274
2275/**
2276 * xmlXIncludeProcessFlags:
Daniel Veillardd16df9f2001-05-23 13:44:21 +00002277 * @doc: an XML document
Daniel Veillarde74d2e12003-12-09 11:35:37 +00002278 * @flags: a set of xmlParserOption used for parsing XML includes
Daniel Veillardd16df9f2001-05-23 13:44:21 +00002279 *
2280 * Implement the XInclude substitution on the XML document @doc
2281 *
Daniel Veillardcbaf3992001-12-31 16:16:02 +00002282 * Returns 0 if no substitution were done, -1 if some processing failed
Daniel Veillardd16df9f2001-05-23 13:44:21 +00002283 * or the number of substitutions done.
2284 */
2285int
Daniel Veillarde74d2e12003-12-09 11:35:37 +00002286xmlXIncludeProcessFlags(xmlDocPtr doc, int flags) {
Daniel Veillardd16df9f2001-05-23 13:44:21 +00002287 xmlXIncludeCtxtPtr ctxt;
Daniel Veillard8edf1c52003-07-22 20:52:14 +00002288 xmlNodePtr tree;
Daniel Veillardd16df9f2001-05-23 13:44:21 +00002289 int ret = 0;
2290
2291 if (doc == NULL)
2292 return(-1);
Daniel Veillard8edf1c52003-07-22 20:52:14 +00002293 tree = xmlDocGetRootElement(doc);
2294 if (tree == NULL)
2295 return(-1);
Daniel Veillardd16df9f2001-05-23 13:44:21 +00002296 ctxt = xmlXIncludeNewContext(doc);
2297 if (ctxt == NULL)
2298 return(-1);
Daniel Veillarde74d2e12003-12-09 11:35:37 +00002299 xmlXIncludeSetFlags(ctxt, flags);
Daniel Veillard8edf1c52003-07-22 20:52:14 +00002300 ret = xmlXIncludeDoProcess(ctxt, doc, tree);
2301 if ((ret >= 0) && (ctxt->nbErrors > 0))
2302 ret = -1;
2303
2304 xmlXIncludeFreeContext(ctxt);
2305 return(ret);
2306}
2307
2308/**
Daniel Veillarde74d2e12003-12-09 11:35:37 +00002309 * xmlXIncludeProcess:
2310 * @doc: an XML document
2311 *
2312 * Implement the XInclude substitution on the XML document @doc
2313 *
2314 * Returns 0 if no substitution were done, -1 if some processing failed
2315 * or the number of substitutions done.
2316 */
2317int
2318xmlXIncludeProcess(xmlDocPtr doc) {
2319 return(xmlXIncludeProcessFlags(doc, 0));
2320}
2321
2322/**
2323 * xmlXIncludeProcessTreeFlags:
2324 * @tree: a node in an XML document
2325 * @flags: a set of xmlParserOption used for parsing XML includes
2326 *
2327 * Implement the XInclude substitution for the given subtree
2328 *
2329 * Returns 0 if no substitution were done, -1 if some processing failed
2330 * or the number of substitutions done.
2331 */
2332int
2333xmlXIncludeProcessTreeFlags(xmlNodePtr tree, int flags) {
2334 xmlXIncludeCtxtPtr ctxt;
2335 int ret = 0;
2336
2337 if ((tree == NULL) || (tree->doc == NULL))
2338 return(-1);
2339 ctxt = xmlXIncludeNewContext(tree->doc);
2340 if (ctxt == NULL)
2341 return(-1);
2342 xmlXIncludeSetFlags(ctxt, flags);
2343 ret = xmlXIncludeDoProcess(ctxt, tree->doc, tree);
2344 if ((ret >= 0) && (ctxt->nbErrors > 0))
2345 ret = -1;
2346
2347 xmlXIncludeFreeContext(ctxt);
2348 return(ret);
2349}
2350
2351/**
Daniel Veillard8edf1c52003-07-22 20:52:14 +00002352 * xmlXIncludeProcessTree:
2353 * @tree: a node in an XML document
2354 *
2355 * Implement the XInclude substitution for the given subtree
2356 *
2357 * Returns 0 if no substitution were done, -1 if some processing failed
2358 * or the number of substitutions done.
2359 */
2360int
2361xmlXIncludeProcessTree(xmlNodePtr tree) {
Daniel Veillarde74d2e12003-12-09 11:35:37 +00002362 return(xmlXIncludeProcessTreeFlags(tree, 0));
Owen Taylor3473f882001-02-23 17:55:21 +00002363}
2364
Daniel Veillard7899c5c2003-11-03 12:31:38 +00002365/**
2366 * xmlXIncludeProcessNode:
2367 * @ctxt: an existing XInclude context
2368 * @node: a node in an XML document
2369 *
2370 * Implement the XInclude substitution for the given subtree reusing
2371 * the informations and data coming from the given context.
2372 *
2373 * Returns 0 if no substitution were done, -1 if some processing failed
2374 * or the number of substitutions done.
2375 */
2376int
2377xmlXIncludeProcessNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node) {
2378 int ret = 0;
2379
2380 if ((node == NULL) || (node->doc == NULL) || (ctxt == NULL))
2381 return(-1);
2382 ret = xmlXIncludeDoProcess(ctxt, node->doc, node);
2383 if ((ret >= 0) && (ctxt->nbErrors > 0))
2384 ret = -1;
2385 return(ret);
2386}
2387
Owen Taylor3473f882001-02-23 17:55:21 +00002388#else /* !LIBXML_XINCLUDE_ENABLED */
2389#endif