Annotation of XML/xinclude.c, revision 1.5
1.1 veillard 1: /*
2: * xinclude.c : Code to implement XInclude processing
3: *
4: * World Wide Web Consortium Working Draft 26 October 2000
5: * http://www.w3.org/TR/2000/WD-xinclude-20001026
6: *
7: * See Copyright for the status of this software.
8: *
9: * Daniel.Veillard@w3.org
10: */
11:
12: /*
1.4 veillard 13: * TODO: compute XPointers nodesets
1.1 veillard 14: */
15:
16: #ifdef WIN32
17: #include "win32config.h"
18: #else
19: #include "config.h"
20: #endif
21:
22: #include <stdio.h>
23: #include <string.h>
24: #include <libxml/xmlmemory.h>
25: #include <libxml/tree.h>
26: #include <libxml/parser.h>
27: #include <libxml/uri.h>
28: #include <libxml/xpointer.h>
1.2 veillard 29: #include <libxml/parserInternals.h>
1.1 veillard 30: #ifdef LIBXML_DEBUG_ENABLED
31: #include <libxml/debugXML.h>
32: #endif
33: #include <libxml/xmlerror.h>
34:
35: #ifdef LIBXML_XINCLUDE_ENABLED
36: #include <libxml/xinclude.h>
37:
38: #define XINCLUDE_NS (const xmlChar *) "http://www.w3.org/1999/XML/xinclude"
39: #define XINCLUDE_NODE (const xmlChar *) "include"
40: #define XINCLUDE_HREF (const xmlChar *) "href"
41: #define XINCLUDE_PARSE (const xmlChar *) "parse"
1.2 veillard 42: #define XINCLUDE_PARSE_XML (const xmlChar *) "xml"
43: #define XINCLUDE_PARSE_TEXT (const xmlChar *) "text"
1.1 veillard 44:
1.4 veillard 45: /* #define DEBUG_XINCLUDE */
1.1 veillard 46:
1.2 veillard 47: /************************************************************************
48: * *
49: * XInclude contexts handling *
50: * *
51: ************************************************************************/
52:
1.1 veillard 53: /*
54: * An XInclude context
55: */
56: typedef xmlChar *URL;
57: typedef struct _xmlXIncludeCtxt xmlXIncludeCtxt;
58: typedef xmlXIncludeCtxt *xmlXIncludeCtxtPtr;
59: struct _xmlXIncludeCtxt {
60: xmlDocPtr doc; /* the source document */
61: int incNr; /* number of includes */
62: int incMax; /* size of includes tab */
63: xmlNodePtr *incTab; /* array of include nodes */
64: xmlNodePtr *repTab; /* array of replacement node lists */
1.2 veillard 65: int docNr; /* number of parsed documents */
66: int docMax; /* size of parsed documents tab */
67: xmlDocPtr *docTab; /* array of parsed documents */
68: URL *urlTab; /* array of parsed documents URLs */
69: int txtNr; /* number of unparsed documents */
70: int txtMax; /* size of unparsed documents tab */
71: xmlNodePtr *txtTab; /* array of unparsed text nodes */
72: URL *txturlTab; /* array of unparsed txtuments URLs */
1.1 veillard 73: };
74:
75: /**
76: * xmlXIncludeAddNode:
77: * @ctxt: the XInclude context
78: * @node: the new node
79: *
80: * Add a new node to process to an XInclude context
81: */
82: void
83: xmlXIncludeAddNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node) {
84: if (ctxt->incMax == 0) {
85: ctxt->incMax = 4;
86: ctxt->incTab = (xmlNodePtr *) xmlMalloc(ctxt->incMax *
87: sizeof(ctxt->incTab[0]));
88: if (ctxt->incTab == NULL) {
89: xmlGenericError(xmlGenericErrorContext,
90: "malloc failed !\n");
91: return;
92: }
93: ctxt->repTab = (xmlNodePtr *) xmlMalloc(ctxt->incMax *
94: sizeof(ctxt->repTab[0]));
95: if (ctxt->repTab == NULL) {
96: xmlGenericError(xmlGenericErrorContext,
97: "malloc failed !\n");
98: return;
99: }
100: }
101: if (ctxt->incNr >= ctxt->incMax) {
102: ctxt->incMax *= 2;
103: ctxt->incTab = (xmlNodePtr *) xmlRealloc(ctxt->incTab,
104: ctxt->incMax * sizeof(ctxt->incTab[0]));
105: if (ctxt->incTab == NULL) {
106: xmlGenericError(xmlGenericErrorContext,
107: "realloc failed !\n");
108: return;
109: }
110: ctxt->repTab = (xmlNodePtr *) xmlRealloc(ctxt->repTab,
111: ctxt->incMax * sizeof(ctxt->repTab[0]));
112: if (ctxt->repTab == NULL) {
113: xmlGenericError(xmlGenericErrorContext,
114: "realloc failed !\n");
115: return;
116: }
117: }
118: ctxt->incTab[ctxt->incNr] = node;
1.3 veillard 119: ctxt->repTab[ctxt->incNr] = NULL;
1.1 veillard 120: ctxt->incNr++;
121: }
122:
123: /**
124: * xmlXIncludeAddDoc:
125: * @ctxt: the XInclude context
126: * @doc: the new document
127: * @url: the associated URL
128: *
129: * Add a new document to the list
130: */
131: void
132: xmlXIncludeAddDoc(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, const URL url) {
133: if (ctxt->docMax == 0) {
134: ctxt->docMax = 4;
135: ctxt->docTab = (xmlDocPtr *) xmlMalloc(ctxt->docMax *
136: sizeof(ctxt->docTab[0]));
137: if (ctxt->docTab == NULL) {
138: xmlGenericError(xmlGenericErrorContext,
139: "malloc failed !\n");
140: return;
141: }
142: ctxt->urlTab = (URL *) xmlMalloc(ctxt->docMax *
143: sizeof(ctxt->urlTab[0]));
144: if (ctxt->urlTab == NULL) {
145: xmlGenericError(xmlGenericErrorContext,
146: "malloc failed !\n");
147: return;
148: }
149: }
150: if (ctxt->docNr >= ctxt->docMax) {
151: ctxt->docMax *= 2;
152: ctxt->docTab = (xmlDocPtr *) xmlRealloc(ctxt->docTab,
153: ctxt->docMax * sizeof(ctxt->docTab[0]));
154: if (ctxt->docTab == NULL) {
155: xmlGenericError(xmlGenericErrorContext,
156: "realloc failed !\n");
157: return;
158: }
159: ctxt->urlTab = (URL *) xmlRealloc(ctxt->urlTab,
160: ctxt->docMax * sizeof(ctxt->urlTab[0]));
161: if (ctxt->urlTab == NULL) {
162: xmlGenericError(xmlGenericErrorContext,
163: "realloc failed !\n");
164: return;
165: }
166: }
167: ctxt->docTab[ctxt->docNr] = doc;
168: ctxt->urlTab[ctxt->docNr] = xmlStrdup(url);
169: ctxt->docNr++;
170: }
171:
172: /**
1.2 veillard 173: * xmlXIncludeAddTxt:
174: * @ctxt: the XInclude context
175: * @txt: the new text node
176: * @url: the associated URL
177: *
178: * Add a new txtument to the list
179: */
180: void
181: xmlXIncludeAddTxt(xmlXIncludeCtxtPtr ctxt, xmlNodePtr txt, const URL url) {
182: if (ctxt->txtMax == 0) {
183: ctxt->txtMax = 4;
184: ctxt->txtTab = (xmlNodePtr *) xmlMalloc(ctxt->txtMax *
185: sizeof(ctxt->txtTab[0]));
186: if (ctxt->txtTab == NULL) {
187: xmlGenericError(xmlGenericErrorContext,
188: "malloc failed !\n");
189: return;
190: }
191: ctxt->txturlTab = (URL *) xmlMalloc(ctxt->txtMax *
192: sizeof(ctxt->txturlTab[0]));
193: if (ctxt->txturlTab == NULL) {
194: xmlGenericError(xmlGenericErrorContext,
195: "malloc failed !\n");
196: return;
197: }
198: }
199: if (ctxt->txtNr >= ctxt->txtMax) {
200: ctxt->txtMax *= 2;
201: ctxt->txtTab = (xmlNodePtr *) xmlRealloc(ctxt->txtTab,
202: ctxt->txtMax * sizeof(ctxt->txtTab[0]));
203: if (ctxt->txtTab == NULL) {
204: xmlGenericError(xmlGenericErrorContext,
205: "realloc failed !\n");
206: return;
207: }
208: ctxt->txturlTab = (URL *) xmlRealloc(ctxt->txturlTab,
209: ctxt->txtMax * sizeof(ctxt->urlTab[0]));
210: if (ctxt->txturlTab == NULL) {
211: xmlGenericError(xmlGenericErrorContext,
212: "realloc failed !\n");
213: return;
214: }
215: }
216: ctxt->txtTab[ctxt->txtNr] = txt;
217: ctxt->txturlTab[ctxt->txtNr] = xmlStrdup(url);
218: ctxt->txtNr++;
219: }
220:
221: /**
1.1 veillard 222: * xmlXIncludeNewContext:
223: * @doc: an XML Document
224: *
225: * Creates a new XInclude context
226: *
227: * Returns the new set
228: */
229: xmlXIncludeCtxtPtr
230: xmlXIncludeNewContext(xmlDocPtr doc) {
231: xmlXIncludeCtxtPtr ret;
232:
233: if (doc == NULL)
234: return(NULL);
235: ret = (xmlXIncludeCtxtPtr) xmlMalloc(sizeof(xmlXIncludeCtxt));
236: if (ret == NULL)
237: return(NULL);
238: memset(ret, 0, sizeof(xmlXIncludeCtxt));
239: ret->doc = doc;
240: ret->incNr = 0;
241: ret->incMax = 0;
242: ret->incTab = NULL;
243: ret->repTab = NULL;
244: ret->docNr = 0;
245: ret->docMax = 0;
246: ret->docTab = NULL;
247: ret->urlTab = NULL;
248: return(ret);
249: }
250:
251: /**
252: * xmlXIncludeFreeContext:
253: * @ctxt: the XInclude context
254: *
255: * Free an XInclude context
256: */
257: void
258: xmlXIncludeFreeContext(xmlXIncludeCtxtPtr ctxt) {
259: if (ctxt == NULL)
260: return;
261: if (ctxt->incTab != NULL)
262: xmlFree(ctxt->incTab);
263: if (ctxt->repTab != NULL)
264: xmlFree(ctxt->repTab);
265: memset(ctxt, 0xeb, sizeof(xmlXIncludeCtxt));
266: xmlFree(ctxt);
267: }
268:
1.2 veillard 269: /************************************************************************
270: * *
271: * XInclude I/O handling *
272: * *
273: ************************************************************************/
274:
275: /**
276: * xmlXIncludeLoadDoc:
277: * @ctxt: the XInclude context
278: * @url: the associated URL
279: * @nr: the xinclude node number
280: *
281: * Load the document, and store the result in the XInclude context
282: */
283: void
284: xmlXIncludeLoadDoc(xmlXIncludeCtxtPtr ctxt, const xmlChar *url, int nr) {
285: xmlDocPtr doc;
286: xmlURIPtr uri;
287: xmlChar *URL;
288: int i;
289: /*
290: * Check the URL and remove any fragment identifier
291: */
292: uri = xmlParseURI((const char *)url);
293: if (uri == NULL) {
294: xmlGenericError(xmlGenericErrorContext,
295: "XInclude: invalid value URI %s\n", url);
296: return;
297: }
298: if (uri->fragment != NULL) {
299: xmlFree(uri->fragment);
300: uri->fragment = NULL; /* TODO: kkep it for later processing */
301: }
302: URL = xmlSaveUri(uri);
303: xmlFreeURI(uri);
304: if (URL == NULL) {
305: xmlGenericError(xmlGenericErrorContext,
306: "XInclude: invalid value URI %s\n", url);
307: return;
308: }
309:
310: /*
311: * Handling of references to the local document are done
312: * directly through ctxt->doc.
313: */
314: if (URL[0] == 0) {
315: xmlFree(URL);
316: return;
317: }
318:
319: /*
320: * Prevent reloading twice the document.
321: */
322: for (i = 0; i < ctxt->docNr; i++) {
323: if (xmlStrEqual(URL, ctxt->urlTab[i])) {
324: doc = ctxt->docTab[i];
325: goto loaded;
326: }
327: }
328: /*
329: * Load it.
330: */
331: doc = xmlParseFile((const char *)URL);
332: if (doc == NULL) {
333: xmlGenericError(xmlGenericErrorContext,
334: "XInclude: could not load %s\n", URL);
335: xmlFree(URL);
336: return;
337: }
338: xmlXIncludeAddDoc(ctxt, doc, URL);
339:
340: loaded:
341: /*
342: * Add the top children list as the replacement copy.
343: */
344: ctxt->repTab[nr] = xmlCopyNodeList(doc->children);
345: xmlFree(URL);
346: }
347:
348: /**
349: * xmlXIncludeLoadTxt:
350: * @ctxt: the XInclude context
351: * @url: the associated URL
352: * @nr: the xinclude node number
353: *
354: * Load the content, and store the result in the XInclude context
355: */
356: void
357: xmlXIncludeLoadTxt(xmlXIncludeCtxtPtr ctxt, const xmlChar *url, int nr) {
358: xmlParserInputBufferPtr buf;
359: xmlNodePtr node;
360: xmlURIPtr uri;
361: xmlChar *URL;
362: int i;
363: /*
364: * Check the URL and remove any fragment identifier
365: */
366: uri = xmlParseURI((const char *)url);
367: if (uri == NULL) {
368: xmlGenericError(xmlGenericErrorContext,
369: "XInclude: invalid value URI %s\n", url);
370: return;
371: }
372: if (uri->fragment != NULL) {
1.5 ! veillard 373: xmlGenericError(xmlGenericErrorContext,
! 374: "XInclude: fragment identifier forbidden for text: %s\n",
! 375: uri->fragment);
1.2 veillard 376: xmlFreeURI(uri);
377: return;
378: }
379: URL = xmlSaveUri(uri);
380: xmlFreeURI(uri);
381: if (URL == NULL) {
382: xmlGenericError(xmlGenericErrorContext,
383: "XInclude: invalid value URI %s\n", url);
384: return;
385: }
386:
387: /*
388: * Handling of references to the local document are done
389: * directly through ctxt->doc.
390: */
391: if (URL[0] == 0) {
392: xmlGenericError(xmlGenericErrorContext,
393: "XInclude: text serialization of document not available\n");
394: xmlFree(URL);
395: return;
396: }
397:
398: /*
399: * Prevent reloading twice the document.
400: */
401: for (i = 0; i < ctxt->txtNr; i++) {
402: if (xmlStrEqual(URL, ctxt->txturlTab[i])) {
403: node = xmlCopyNode(ctxt->txtTab[i], 1);
404: goto loaded;
405: }
406: }
407: /*
408: * Load it.
409: * Issue 62: how to detect the encoding
410: */
411: buf = xmlParserInputBufferCreateFilename((const char *)URL, 0);
412: if (buf == NULL) {
413: xmlGenericError(xmlGenericErrorContext,
414: "XInclude: could not load %s\n", URL);
415: xmlFree(URL);
416: return;
417: }
418: node = xmlNewText(NULL);
419:
420: /*
421: * Scan all chars from the resource and add the to the node
422: */
423: while (xmlParserInputBufferRead(buf, 128) > 0) {
424: int len;
425: const xmlChar *content;
426:
427: content = xmlBufferContent(buf->buffer);
428: len = xmlBufferLength(buf->buffer);
429: for (i = 0;i < len; i++) {
430: /*
431: * TODO: if the encoding issue is solved, scan UTF8 chars instead
432: */
433: if (!IS_CHAR(content[i])) {
434: xmlGenericError(xmlGenericErrorContext,
435: "XInclude: %s contains invalid char %d\n", URL, content[i]);
436: } else {
437: xmlNodeAddContentLen(node, &content[i], 1);
438: }
439: }
440: xmlBufferShrink(buf->buffer, len);
441: }
442: xmlFreeParserInputBuffer(buf);
443: xmlXIncludeAddTxt(ctxt, node, URL);
444:
445: loaded:
446: /*
447: * Add the element as the replacement copy.
448: */
449: ctxt->repTab[nr] = node;
450: xmlFree(URL);
451: }
452:
453: /************************************************************************
454: * *
455: * XInclude Processing *
456: * *
457: ************************************************************************/
458:
1.1 veillard 459: /**
460: * xmlXIncludePreProcessNode:
461: * @ctxt: an XInclude context
462: * @node: an XInclude node
463: *
464: * Implement the infoset replacement lookup on the XML element @node
465: *
466: * Returns the result list or NULL in case of error
467: */
468: xmlNodePtr
469: xmlXIncludePreProcessNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node) {
470: xmlXIncludeAddNode(ctxt, node);
471: return(0);
472: }
473:
474: /**
475: * xmlXIncludeLoadNode:
476: * @ctxt: an XInclude context
477: * @nr: the node number
478: *
479: * Find and load the infoset replacement for the given node.
480: *
481: * Returns 0 if substition succeeded, -1 if some processing failed
482: */
483: int
1.2 veillard 484: xmlXIncludeLoadNode(xmlXIncludeCtxtPtr ctxt, int nr) {
1.1 veillard 485: xmlNodePtr cur;
486: xmlChar *href;
487: xmlChar *parse;
488: xmlChar *base;
489: xmlChar *URI;
490: int xml = 1; /* default Issue 64 */
491:
492: if (ctxt == NULL)
493: return(-1);
494: if ((nr < 0) || (nr >= ctxt->incNr))
495: return(-1);
496: cur = ctxt->incTab[nr];
497: if (cur == NULL)
498: return(-1);
499:
500: #ifdef DEBUG_XINCLUDE
501: xmlDebugDumpNode(stdout, cur, 0);
502: #endif
503: /*
1.2 veillard 504: * read the attributes
1.1 veillard 505: */
506: href = xmlGetNsProp(cur, XINCLUDE_NS, XINCLUDE_HREF);
507: if (href == NULL) {
1.2 veillard 508: href = xmlGetProp(cur, XINCLUDE_HREF);
509: if (href == NULL) {
510: xmlGenericError(xmlGenericErrorContext, "XInclude: no href\n");
511: return(-1);
512: }
513: }
514: parse = xmlGetNsProp(cur, XINCLUDE_NS, XINCLUDE_PARSE);
515: if (parse == NULL) {
516: parse = xmlGetProp(cur, XINCLUDE_PARSE);
517: }
518: if (parse != NULL) {
519: if (xmlStrEqual(parse, XINCLUDE_PARSE_XML))
520: xml = 1;
521: else if (xmlStrEqual(parse, XINCLUDE_PARSE_TEXT))
522: xml = 0;
523: else {
524: xmlGenericError(xmlGenericErrorContext,
525: "XInclude: invalid value %s for %s\n",
526: parse, XINCLUDE_PARSE);
527: if (href != NULL)
528: xmlFree(href);
529: if (parse != NULL)
530: xmlFree(parse);
531: return(-1);
532: }
533: }
534:
535: /*
536: * compute the URI
537: */
538: base = xmlNodeGetBase(ctxt->doc, cur);
539: URI = xmlBuildURI(href, base);
540: if (URI == NULL) {
541: xmlChar *escbase;
542: xmlChar *eschref;
543: /*
544: * Some escapeing may be needed
545: */
546: escbase = xmlURIEscape(base);
547: eschref = xmlURIEscape(href);
548: URI = xmlBuildURI(eschref, escbase);
549: if (escbase != NULL)
550: xmlFree(escbase);
551: if (eschref != NULL)
552: xmlFree(eschref);
553: }
554: if (URI == NULL) {
555: xmlGenericError(xmlGenericErrorContext, "XInclude: failed build URL\n");
556: if (parse != NULL)
557: xmlFree(parse);
558: if (href != NULL)
559: xmlFree(href);
560: if (base != NULL)
561: xmlFree(base);
562: return(-1);
563: }
564: #ifdef DEBUG_XINCLUDE
565: xmlGenericError(xmlGenericErrorContext, "parse: %s\n",
566: xml ? "xml": "text");
567: xmlGenericError(xmlGenericErrorContext, "URI: %s\n", URI);
568: #endif
569:
570: /*
571: * Cleanup
572: */
573: if (xml) {
574: xmlXIncludeLoadDoc(ctxt, URI, nr);
575: /* xmlXIncludeGetFragment(ctxt, cur, URI); */
576: } else {
577: xmlXIncludeLoadTxt(ctxt, URI, nr);
578: }
579:
580: /*
581: * Cleanup
582: */
583: if (URI != NULL)
584: xmlFree(URI);
585: if (parse != NULL)
586: xmlFree(parse);
587: if (href != NULL)
588: xmlFree(href);
589: if (base != NULL)
590: xmlFree(base);
591: return(0);
592: }
593:
594: /**
595: * xmlXIncludeIncludeNode:
596: * @ctxt: an XInclude context
597: * @nr: the node number
598: *
599: * Inplement the infoset replacement for the given node
600: *
601: * Returns 0 if substition succeeded, -1 if some processing failed
602: */
603: int
604: xmlXIncludeIncludeNode(xmlXIncludeCtxtPtr ctxt, int nr) {
605: xmlNodePtr cur, end, list;
606:
607: if (ctxt == NULL)
608: return(-1);
609: if ((nr < 0) || (nr >= ctxt->incNr))
610: return(-1);
611: cur = ctxt->incTab[nr];
612: if (cur == NULL)
613: return(-1);
614:
615: /*
616: * Change the current node as an XInclude start one, and add an
617: * entity end one
618: */
619: cur->type = XML_XINCLUDE_START;
620: end = xmlNewNode(cur->ns, cur->name);
621: if (end == NULL) {
622: xmlGenericError(xmlGenericErrorContext,
623: "XInclude: failed to build node\n");
1.1 veillard 624: return(-1);
625: }
1.3 veillard 626: end->type = XML_XINCLUDE_END;
627: xmlAddNextSibling(cur, end);
1.2 veillard 628:
629: /*
630: * Add the list of nodes
631: */
632: list = ctxt->repTab[nr];
633: ctxt->repTab[nr] = NULL;
634: while (list != NULL) {
635: cur = list;
636: list = list->next;
1.1 veillard 637:
1.2 veillard 638: xmlAddPrevSibling(end, cur);
1.1 veillard 639: }
640: return(0);
641: }
642:
643: /**
644: * xmlXIncludeTestNode:
645: * @doc: an XML document
646: * @node: an XInclude node
647: *
648: * test if the node is an XInclude node
649: *
650: * Returns 1 true, 0 otherwise
651: */
652: int
653: xmlXIncludeTestNode(xmlDocPtr doc, xmlNodePtr node) {
654: if (node == NULL)
655: return(0);
656: if (node->ns == NULL)
657: return(0);
658: if ((xmlStrEqual(node->name, XINCLUDE_NODE)) &&
659: (xmlStrEqual(node->ns->href, XINCLUDE_NS))) return(1);
660: return(0);
661: }
662:
663: /**
664: * xmlXIncludeProcess:
665: * @doc: an XML document
666: *
667: * Implement the XInclude substitution on the XML document @doc
668: *
669: * Returns 0 if no substition were done, -1 if some processing failed
670: * or the number of substitutions done.
671: */
672: int
673: xmlXIncludeProcess(xmlDocPtr doc) {
674: xmlXIncludeCtxtPtr ctxt;
675: xmlNodePtr cur;
676: int ret = 0;
677: int i;
678:
679: if (doc == NULL)
680: return(-1);
681: ctxt = xmlXIncludeNewContext(doc);
682: if (ctxt == NULL)
683: return(-1);
684:
685: /*
686: * First phase: lookup the elements in the document
687: */
688: cur = xmlDocGetRootElement(doc);
689: if (xmlXIncludeTestNode(doc, cur))
690: xmlXIncludePreProcessNode(ctxt, cur);
691: while (cur != NULL) {
1.3 veillard 692: /* TODO: need to work on entities -> stack */
693: if ((cur->children != NULL) &&
694: (cur->children->type != XML_ENTITY_DECL)) {
695: cur = cur->children;
696: if (xmlXIncludeTestNode(doc, cur))
697: xmlXIncludePreProcessNode(ctxt, cur);
1.1 veillard 698: } else if (cur->next != NULL) {
699: cur = cur->next;
700: if (xmlXIncludeTestNode(doc, cur))
701: xmlXIncludePreProcessNode(ctxt, cur);
702: } else {
703: do {
704: cur = cur->parent;
705: if (cur == NULL) break; /* do */
706: if (cur->next != NULL) {
707: cur = cur->next;
708: if (xmlXIncludeTestNode(doc, cur))
709: xmlXIncludePreProcessNode(ctxt, cur);
710: break; /* do */
711: }
712: } while (cur != NULL);
713: }
714: }
715:
716: /*
717: * Second Phase : collect the infosets fragments
718: */
719: for (i = 0;i < ctxt->incNr; i++) {
1.2 veillard 720: xmlXIncludeLoadNode(ctxt, i);
1.1 veillard 721: }
722:
723: /*
724: * Third phase: extend the original document infoset.
725: */
1.2 veillard 726: for (i = 0;i < ctxt->incNr; i++) {
727: xmlXIncludeIncludeNode(ctxt, i);
728: }
1.1 veillard 729:
730: /*
731: * Cleanup
732: */
733: xmlXIncludeFreeContext(ctxt);
734: return(ret);
735: }
736:
737: #else /* !LIBXML_XINCLUDE_ENABLED */
738: #endif
Webmaster