Annotation of XML/xinclude.c, revision 1.3
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: /*
13: * TODO: xmlXIncludeCtxt with document caches, stack of nodes to handle
14: * and their associated infoset.
15: */
16:
17: #ifdef WIN32
18: #include "win32config.h"
19: #else
20: #include "config.h"
21: #endif
22:
23: #include <stdio.h>
24: #include <string.h>
25: #include <libxml/xmlmemory.h>
26: #include <libxml/tree.h>
27: #include <libxml/parser.h>
28: #include <libxml/uri.h>
29: #include <libxml/xpointer.h>
1.2 veillard 30: #include <libxml/parserInternals.h>
1.1 veillard 31: #ifdef LIBXML_DEBUG_ENABLED
32: #include <libxml/debugXML.h>
33: #endif
34: #include <libxml/xmlerror.h>
35:
36: #ifdef LIBXML_XINCLUDE_ENABLED
37: #include <libxml/xinclude.h>
38:
39: #define XINCLUDE_NS (const xmlChar *) "http://www.w3.org/1999/XML/xinclude"
40: #define XINCLUDE_NODE (const xmlChar *) "include"
41: #define XINCLUDE_HREF (const xmlChar *) "href"
42: #define XINCLUDE_PARSE (const xmlChar *) "parse"
1.2 veillard 43: #define XINCLUDE_PARSE_XML (const xmlChar *) "xml"
44: #define XINCLUDE_PARSE_TEXT (const xmlChar *) "text"
1.1 veillard 45:
46: #define DEBUG_XINCLUDE
47:
1.2 veillard 48: /************************************************************************
49: * *
50: * XInclude contexts handling *
51: * *
52: ************************************************************************/
53:
1.1 veillard 54: /*
55: * An XInclude context
56: */
57: typedef xmlChar *URL;
58: typedef struct _xmlXIncludeCtxt xmlXIncludeCtxt;
59: typedef xmlXIncludeCtxt *xmlXIncludeCtxtPtr;
60: struct _xmlXIncludeCtxt {
61: xmlDocPtr doc; /* the source document */
62: int incNr; /* number of includes */
63: int incMax; /* size of includes tab */
64: xmlNodePtr *incTab; /* array of include nodes */
65: xmlNodePtr *repTab; /* array of replacement node lists */
1.2 veillard 66: int docNr; /* number of parsed documents */
67: int docMax; /* size of parsed documents tab */
68: xmlDocPtr *docTab; /* array of parsed documents */
69: URL *urlTab; /* array of parsed documents URLs */
70: int txtNr; /* number of unparsed documents */
71: int txtMax; /* size of unparsed documents tab */
72: xmlNodePtr *txtTab; /* array of unparsed text nodes */
73: URL *txturlTab; /* array of unparsed txtuments URLs */
1.1 veillard 74: };
75:
76: /**
77: * xmlXIncludeAddNode:
78: * @ctxt: the XInclude context
79: * @node: the new node
80: *
81: * Add a new node to process to an XInclude context
82: */
83: void
84: xmlXIncludeAddNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node) {
85: if (ctxt->incMax == 0) {
86: ctxt->incMax = 4;
87: ctxt->incTab = (xmlNodePtr *) xmlMalloc(ctxt->incMax *
88: sizeof(ctxt->incTab[0]));
89: if (ctxt->incTab == NULL) {
90: xmlGenericError(xmlGenericErrorContext,
91: "malloc failed !\n");
92: return;
93: }
94: ctxt->repTab = (xmlNodePtr *) xmlMalloc(ctxt->incMax *
95: sizeof(ctxt->repTab[0]));
96: if (ctxt->repTab == NULL) {
97: xmlGenericError(xmlGenericErrorContext,
98: "malloc failed !\n");
99: return;
100: }
101: }
102: if (ctxt->incNr >= ctxt->incMax) {
103: ctxt->incMax *= 2;
104: ctxt->incTab = (xmlNodePtr *) xmlRealloc(ctxt->incTab,
105: ctxt->incMax * sizeof(ctxt->incTab[0]));
106: if (ctxt->incTab == NULL) {
107: xmlGenericError(xmlGenericErrorContext,
108: "realloc failed !\n");
109: return;
110: }
111: ctxt->repTab = (xmlNodePtr *) xmlRealloc(ctxt->repTab,
112: ctxt->incMax * sizeof(ctxt->repTab[0]));
113: if (ctxt->repTab == NULL) {
114: xmlGenericError(xmlGenericErrorContext,
115: "realloc failed !\n");
116: return;
117: }
118: }
119: ctxt->incTab[ctxt->incNr] = node;
1.3 ! veillard 120: ctxt->repTab[ctxt->incNr] = NULL;
1.1 veillard 121: ctxt->incNr++;
122: }
123:
124: /**
125: * xmlXIncludeAddDoc:
126: * @ctxt: the XInclude context
127: * @doc: the new document
128: * @url: the associated URL
129: *
130: * Add a new document to the list
131: */
132: void
133: xmlXIncludeAddDoc(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, const URL url) {
134: if (ctxt->docMax == 0) {
135: ctxt->docMax = 4;
136: ctxt->docTab = (xmlDocPtr *) xmlMalloc(ctxt->docMax *
137: sizeof(ctxt->docTab[0]));
138: if (ctxt->docTab == NULL) {
139: xmlGenericError(xmlGenericErrorContext,
140: "malloc failed !\n");
141: return;
142: }
143: ctxt->urlTab = (URL *) xmlMalloc(ctxt->docMax *
144: sizeof(ctxt->urlTab[0]));
145: if (ctxt->urlTab == NULL) {
146: xmlGenericError(xmlGenericErrorContext,
147: "malloc failed !\n");
148: return;
149: }
150: }
151: if (ctxt->docNr >= ctxt->docMax) {
152: ctxt->docMax *= 2;
153: ctxt->docTab = (xmlDocPtr *) xmlRealloc(ctxt->docTab,
154: ctxt->docMax * sizeof(ctxt->docTab[0]));
155: if (ctxt->docTab == NULL) {
156: xmlGenericError(xmlGenericErrorContext,
157: "realloc failed !\n");
158: return;
159: }
160: ctxt->urlTab = (URL *) xmlRealloc(ctxt->urlTab,
161: ctxt->docMax * sizeof(ctxt->urlTab[0]));
162: if (ctxt->urlTab == NULL) {
163: xmlGenericError(xmlGenericErrorContext,
164: "realloc failed !\n");
165: return;
166: }
167: }
168: ctxt->docTab[ctxt->docNr] = doc;
169: ctxt->urlTab[ctxt->docNr] = xmlStrdup(url);
170: ctxt->docNr++;
171: }
172:
173: /**
1.2 veillard 174: * xmlXIncludeAddTxt:
175: * @ctxt: the XInclude context
176: * @txt: the new text node
177: * @url: the associated URL
178: *
179: * Add a new txtument to the list
180: */
181: void
182: xmlXIncludeAddTxt(xmlXIncludeCtxtPtr ctxt, xmlNodePtr txt, const URL url) {
183: if (ctxt->txtMax == 0) {
184: ctxt->txtMax = 4;
185: ctxt->txtTab = (xmlNodePtr *) xmlMalloc(ctxt->txtMax *
186: sizeof(ctxt->txtTab[0]));
187: if (ctxt->txtTab == NULL) {
188: xmlGenericError(xmlGenericErrorContext,
189: "malloc failed !\n");
190: return;
191: }
192: ctxt->txturlTab = (URL *) xmlMalloc(ctxt->txtMax *
193: sizeof(ctxt->txturlTab[0]));
194: if (ctxt->txturlTab == NULL) {
195: xmlGenericError(xmlGenericErrorContext,
196: "malloc failed !\n");
197: return;
198: }
199: }
200: if (ctxt->txtNr >= ctxt->txtMax) {
201: ctxt->txtMax *= 2;
202: ctxt->txtTab = (xmlNodePtr *) xmlRealloc(ctxt->txtTab,
203: ctxt->txtMax * sizeof(ctxt->txtTab[0]));
204: if (ctxt->txtTab == NULL) {
205: xmlGenericError(xmlGenericErrorContext,
206: "realloc failed !\n");
207: return;
208: }
209: ctxt->txturlTab = (URL *) xmlRealloc(ctxt->txturlTab,
210: ctxt->txtMax * sizeof(ctxt->urlTab[0]));
211: if (ctxt->txturlTab == NULL) {
212: xmlGenericError(xmlGenericErrorContext,
213: "realloc failed !\n");
214: return;
215: }
216: }
217: ctxt->txtTab[ctxt->txtNr] = txt;
218: ctxt->txturlTab[ctxt->txtNr] = xmlStrdup(url);
219: ctxt->txtNr++;
220: }
221:
222: /**
1.1 veillard 223: * xmlXIncludeNewContext:
224: * @doc: an XML Document
225: *
226: * Creates a new XInclude context
227: *
228: * Returns the new set
229: */
230: xmlXIncludeCtxtPtr
231: xmlXIncludeNewContext(xmlDocPtr doc) {
232: xmlXIncludeCtxtPtr ret;
233:
234: if (doc == NULL)
235: return(NULL);
236: ret = (xmlXIncludeCtxtPtr) xmlMalloc(sizeof(xmlXIncludeCtxt));
237: if (ret == NULL)
238: return(NULL);
239: memset(ret, 0, sizeof(xmlXIncludeCtxt));
240: ret->doc = doc;
241: ret->incNr = 0;
242: ret->incMax = 0;
243: ret->incTab = NULL;
244: ret->repTab = NULL;
245: ret->docNr = 0;
246: ret->docMax = 0;
247: ret->docTab = NULL;
248: ret->urlTab = NULL;
249: return(ret);
250: }
251:
252: /**
253: * xmlXIncludeFreeContext:
254: * @ctxt: the XInclude context
255: *
256: * Free an XInclude context
257: */
258: void
259: xmlXIncludeFreeContext(xmlXIncludeCtxtPtr ctxt) {
260: if (ctxt == NULL)
261: return;
262: if (ctxt->incTab != NULL)
263: xmlFree(ctxt->incTab);
264: if (ctxt->repTab != NULL)
265: xmlFree(ctxt->repTab);
266: memset(ctxt, 0xeb, sizeof(xmlXIncludeCtxt));
267: xmlFree(ctxt);
268: }
269:
1.2 veillard 270: /************************************************************************
271: * *
272: * XInclude I/O handling *
273: * *
274: ************************************************************************/
275:
276: /**
277: * xmlXIncludeLoadDoc:
278: * @ctxt: the XInclude context
279: * @url: the associated URL
280: * @nr: the xinclude node number
281: *
282: * Load the document, and store the result in the XInclude context
283: */
284: void
285: xmlXIncludeLoadDoc(xmlXIncludeCtxtPtr ctxt, const xmlChar *url, int nr) {
286: xmlDocPtr doc;
287: xmlURIPtr uri;
288: xmlChar *URL;
289: int i;
290: /*
291: * Check the URL and remove any fragment identifier
292: */
293: uri = xmlParseURI((const char *)url);
294: if (uri == NULL) {
295: xmlGenericError(xmlGenericErrorContext,
296: "XInclude: invalid value URI %s\n", url);
297: return;
298: }
299: if (uri->fragment != NULL) {
300: xmlFree(uri->fragment);
301: uri->fragment = NULL; /* TODO: kkep it for later processing */
302: }
303: URL = xmlSaveUri(uri);
304: xmlFreeURI(uri);
305: if (URL == NULL) {
306: xmlGenericError(xmlGenericErrorContext,
307: "XInclude: invalid value URI %s\n", url);
308: return;
309: }
310:
311: /*
312: * Handling of references to the local document are done
313: * directly through ctxt->doc.
314: */
315: if (URL[0] == 0) {
316: xmlFree(URL);
317: return;
318: }
319:
320: /*
321: * Prevent reloading twice the document.
322: */
323: for (i = 0; i < ctxt->docNr; i++) {
324: if (xmlStrEqual(URL, ctxt->urlTab[i])) {
325: doc = ctxt->docTab[i];
326: goto loaded;
327: }
328: }
329: /*
330: * Load it.
331: */
332: doc = xmlParseFile((const char *)URL);
333: if (doc == NULL) {
334: xmlGenericError(xmlGenericErrorContext,
335: "XInclude: could not load %s\n", URL);
336: xmlFree(URL);
337: return;
338: }
339: xmlXIncludeAddDoc(ctxt, doc, URL);
340:
341: loaded:
342: /*
343: * Add the top children list as the replacement copy.
344: */
345: ctxt->repTab[nr] = xmlCopyNodeList(doc->children);
346: xmlFree(URL);
347: }
348:
349: /**
350: * xmlXIncludeLoadTxt:
351: * @ctxt: the XInclude context
352: * @url: the associated URL
353: * @nr: the xinclude node number
354: *
355: * Load the content, and store the result in the XInclude context
356: */
357: void
358: xmlXIncludeLoadTxt(xmlXIncludeCtxtPtr ctxt, const xmlChar *url, int nr) {
359: xmlParserInputBufferPtr buf;
360: xmlNodePtr node;
361: xmlURIPtr uri;
362: xmlChar *URL;
363: int i;
364: /*
365: * Check the URL and remove any fragment identifier
366: */
367: uri = xmlParseURI((const char *)url);
368: if (uri == NULL) {
369: xmlGenericError(xmlGenericErrorContext,
370: "XInclude: invalid value URI %s\n", url);
371: return;
372: }
373: if (uri->fragment != NULL) {
374: xmlFreeURI(uri);
375: xmlGenericError(xmlGenericErrorContext,
376: "XInclude: fragment identifier forbidden for text\n");
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