Annotation of XML/xinclude.c, revision 1.2
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;
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) {
! 373: xmlFreeURI(uri);
! 374: xmlGenericError(xmlGenericErrorContext,
! 375: "XInclude: fragment identifier forbidden for text\n");
! 376: return;
! 377: }
! 378: URL = xmlSaveUri(uri);
! 379: xmlFreeURI(uri);
! 380: if (URL == NULL) {
! 381: xmlGenericError(xmlGenericErrorContext,
! 382: "XInclude: invalid value URI %s\n", url);
! 383: return;
! 384: }
! 385:
! 386: /*
! 387: * Handling of references to the local document are done
! 388: * directly through ctxt->doc.
! 389: */
! 390: if (URL[0] == 0) {
! 391: xmlGenericError(xmlGenericErrorContext,
! 392: "XInclude: text serialization of document not available\n");
! 393: xmlFree(URL);
! 394: return;
! 395: }
! 396:
! 397: /*
! 398: * Prevent reloading twice the document.
! 399: */
! 400: for (i = 0; i < ctxt->txtNr; i++) {
! 401: if (xmlStrEqual(URL, ctxt->txturlTab[i])) {
! 402: node = xmlCopyNode(ctxt->txtTab[i], 1);
! 403: goto loaded;
! 404: }
! 405: }
! 406: /*
! 407: * Load it.
! 408: * Issue 62: how to detect the encoding
! 409: */
! 410: buf = xmlParserInputBufferCreateFilename((const char *)URL, 0);
! 411: if (buf == NULL) {
! 412: xmlGenericError(xmlGenericErrorContext,
! 413: "XInclude: could not load %s\n", URL);
! 414: xmlFree(URL);
! 415: return;
! 416: }
! 417: node = xmlNewText(NULL);
! 418:
! 419: /*
! 420: * Scan all chars from the resource and add the to the node
! 421: */
! 422: while (xmlParserInputBufferRead(buf, 128) > 0) {
! 423: int len;
! 424: const xmlChar *content;
! 425:
! 426: content = xmlBufferContent(buf->buffer);
! 427: len = xmlBufferLength(buf->buffer);
! 428: for (i = 0;i < len; i++) {
! 429: /*
! 430: * TODO: if the encoding issue is solved, scan UTF8 chars instead
! 431: */
! 432: if (!IS_CHAR(content[i])) {
! 433: xmlGenericError(xmlGenericErrorContext,
! 434: "XInclude: %s contains invalid char %d\n", URL, content[i]);
! 435: } else {
! 436: xmlNodeAddContentLen(node, &content[i], 1);
! 437: }
! 438: }
! 439: xmlBufferShrink(buf->buffer, len);
! 440: }
! 441: xmlFreeParserInputBuffer(buf);
! 442: xmlXIncludeAddTxt(ctxt, node, URL);
! 443:
! 444: loaded:
! 445: /*
! 446: * Add the element as the replacement copy.
! 447: */
! 448: ctxt->repTab[nr] = node;
! 449: xmlFree(URL);
! 450: }
! 451:
! 452: /************************************************************************
! 453: * *
! 454: * XInclude Processing *
! 455: * *
! 456: ************************************************************************/
! 457:
1.1 veillard 458: /**
459: * xmlXIncludePreProcessNode:
460: * @ctxt: an XInclude context
461: * @node: an XInclude node
462: *
463: * Implement the infoset replacement lookup on the XML element @node
464: *
465: * Returns the result list or NULL in case of error
466: */
467: xmlNodePtr
468: xmlXIncludePreProcessNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node) {
469: xmlXIncludeAddNode(ctxt, node);
470: return(0);
471: }
472:
473: /**
474: * xmlXIncludeLoadNode:
475: * @ctxt: an XInclude context
476: * @nr: the node number
477: *
478: * Find and load the infoset replacement for the given node.
479: *
480: * Returns 0 if substition succeeded, -1 if some processing failed
481: */
482: int
1.2 ! veillard 483: xmlXIncludeLoadNode(xmlXIncludeCtxtPtr ctxt, int nr) {
1.1 veillard 484: xmlNodePtr cur;
485: xmlChar *href;
486: xmlChar *parse;
487: xmlChar *base;
488: xmlChar *URI;
489: int xml = 1; /* default Issue 64 */
490:
491: if (ctxt == NULL)
492: return(-1);
493: if ((nr < 0) || (nr >= ctxt->incNr))
494: return(-1);
495: cur = ctxt->incTab[nr];
496: if (cur == NULL)
497: return(-1);
498:
499: #ifdef DEBUG_XINCLUDE
500: xmlDebugDumpNode(stdout, cur, 0);
501: #endif
502: /*
1.2 ! veillard 503: * read the attributes
1.1 veillard 504: */
505: href = xmlGetNsProp(cur, XINCLUDE_NS, XINCLUDE_HREF);
506: if (href == NULL) {
1.2 ! veillard 507: href = xmlGetProp(cur, XINCLUDE_HREF);
! 508: if (href == NULL) {
! 509: xmlGenericError(xmlGenericErrorContext, "XInclude: no href\n");
! 510: return(-1);
! 511: }
! 512: }
! 513: parse = xmlGetNsProp(cur, XINCLUDE_NS, XINCLUDE_PARSE);
! 514: if (parse == NULL) {
! 515: parse = xmlGetProp(cur, XINCLUDE_PARSE);
! 516: }
! 517: if (parse != NULL) {
! 518: if (xmlStrEqual(parse, XINCLUDE_PARSE_XML))
! 519: xml = 1;
! 520: else if (xmlStrEqual(parse, XINCLUDE_PARSE_TEXT))
! 521: xml = 0;
! 522: else {
! 523: xmlGenericError(xmlGenericErrorContext,
! 524: "XInclude: invalid value %s for %s\n",
! 525: parse, XINCLUDE_PARSE);
! 526: if (href != NULL)
! 527: xmlFree(href);
! 528: if (parse != NULL)
! 529: xmlFree(parse);
! 530: return(-1);
! 531: }
! 532: }
! 533:
! 534: /*
! 535: * compute the URI
! 536: */
! 537: base = xmlNodeGetBase(ctxt->doc, cur);
! 538: URI = xmlBuildURI(href, base);
! 539: if (URI == NULL) {
! 540: xmlChar *escbase;
! 541: xmlChar *eschref;
! 542: /*
! 543: * Some escapeing may be needed
! 544: */
! 545: escbase = xmlURIEscape(base);
! 546: eschref = xmlURIEscape(href);
! 547: URI = xmlBuildURI(eschref, escbase);
! 548: if (escbase != NULL)
! 549: xmlFree(escbase);
! 550: if (eschref != NULL)
! 551: xmlFree(eschref);
! 552: }
! 553: if (URI == NULL) {
! 554: xmlGenericError(xmlGenericErrorContext, "XInclude: failed build URL\n");
! 555: if (parse != NULL)
! 556: xmlFree(parse);
! 557: if (href != NULL)
! 558: xmlFree(href);
! 559: if (base != NULL)
! 560: xmlFree(base);
! 561: return(-1);
! 562: }
! 563: #ifdef DEBUG_XINCLUDE
! 564: xmlGenericError(xmlGenericErrorContext, "parse: %s\n",
! 565: xml ? "xml": "text");
! 566: xmlGenericError(xmlGenericErrorContext, "URI: %s\n", URI);
! 567: #endif
! 568:
! 569: /*
! 570: * Cleanup
! 571: */
! 572: if (xml) {
! 573: xmlXIncludeLoadDoc(ctxt, URI, nr);
! 574: /* xmlXIncludeGetFragment(ctxt, cur, URI); */
! 575: } else {
! 576: xmlXIncludeLoadTxt(ctxt, URI, nr);
! 577: }
! 578:
! 579: /*
! 580: * Cleanup
! 581: */
! 582: if (URI != NULL)
! 583: xmlFree(URI);
! 584: if (parse != NULL)
! 585: xmlFree(parse);
! 586: if (href != NULL)
! 587: xmlFree(href);
! 588: if (base != NULL)
! 589: xmlFree(base);
! 590: return(0);
! 591: }
! 592:
! 593: /**
! 594: * xmlXIncludeIncludeNode:
! 595: * @ctxt: an XInclude context
! 596: * @nr: the node number
! 597: *
! 598: * Inplement the infoset replacement for the given node
! 599: *
! 600: * Returns 0 if substition succeeded, -1 if some processing failed
! 601: */
! 602: int
! 603: xmlXIncludeIncludeNode(xmlXIncludeCtxtPtr ctxt, int nr) {
! 604: xmlNodePtr cur, end, list;
! 605:
! 606: if (ctxt == NULL)
! 607: return(-1);
! 608: if ((nr < 0) || (nr >= ctxt->incNr))
! 609: return(-1);
! 610: cur = ctxt->incTab[nr];
! 611: if (cur == NULL)
! 612: return(-1);
! 613:
! 614: /*
! 615: * Change the current node as an XInclude start one, and add an
! 616: * entity end one
! 617: */
! 618: cur->type = XML_XINCLUDE_START;
! 619: end = xmlNewNode(cur->ns, cur->name);
! 620: if (end == NULL) {
! 621: xmlGenericError(xmlGenericErrorContext,
! 622: "XInclude: failed to build node\n");
1.1 veillard 623: return(-1);
624: }
1.2 ! veillard 625: cur->type = XML_XINCLUDE_END;
! 626: xmlAddSibling(cur, end);
! 627:
! 628: /*
! 629: * Add the list of nodes
! 630: */
! 631: list = ctxt->repTab[nr];
! 632: ctxt->repTab[nr] = NULL;
! 633: while (list != NULL) {
! 634: cur = list;
! 635: list = list->next;
1.1 veillard 636:
1.2 ! veillard 637: xmlAddPrevSibling(end, cur);
1.1 veillard 638: }
639: return(0);
640: }
641:
642: /**
643: * xmlXIncludeTestNode:
644: * @doc: an XML document
645: * @node: an XInclude node
646: *
647: * test if the node is an XInclude node
648: *
649: * Returns 1 true, 0 otherwise
650: */
651: int
652: xmlXIncludeTestNode(xmlDocPtr doc, xmlNodePtr node) {
653: if (node == NULL)
654: return(0);
655: if (node->ns == NULL)
656: return(0);
657: if ((xmlStrEqual(node->name, XINCLUDE_NODE)) &&
658: (xmlStrEqual(node->ns->href, XINCLUDE_NS))) return(1);
659: return(0);
660: }
661:
662: /**
663: * xmlXIncludeProcess:
664: * @doc: an XML document
665: *
666: * Implement the XInclude substitution on the XML document @doc
667: *
668: * Returns 0 if no substition were done, -1 if some processing failed
669: * or the number of substitutions done.
670: */
671: int
672: xmlXIncludeProcess(xmlDocPtr doc) {
673: xmlXIncludeCtxtPtr ctxt;
674: xmlNodePtr cur;
675: int ret = 0;
676: int i;
677:
678: if (doc == NULL)
679: return(-1);
680: ctxt = xmlXIncludeNewContext(doc);
681: if (ctxt == NULL)
682: return(-1);
683:
684: /*
685: * First phase: lookup the elements in the document
686: */
687: cur = xmlDocGetRootElement(doc);
688: if (xmlXIncludeTestNode(doc, cur))
689: xmlXIncludePreProcessNode(ctxt, cur);
690: while (cur != NULL) {
691: if (cur->children != NULL) {
692: if (cur->children->type != XML_ENTITY_DECL) {
693: cur = cur->children;
694: if (xmlXIncludeTestNode(doc, cur))
695: xmlXIncludePreProcessNode(ctxt, cur);
696: }
697: } else if (cur->next != NULL) {
698: cur = cur->next;
699: if (xmlXIncludeTestNode(doc, cur))
700: xmlXIncludePreProcessNode(ctxt, cur);
701: } else {
702: do {
703: cur = cur->parent;
704: if (cur == NULL) break; /* do */
705: if (cur->next != NULL) {
706: cur = cur->next;
707: if (xmlXIncludeTestNode(doc, cur))
708: xmlXIncludePreProcessNode(ctxt, cur);
709: break; /* do */
710: }
711: } while (cur != NULL);
712: }
713: }
714:
715: /*
716: * Second Phase : collect the infosets fragments
717: */
718: for (i = 0;i < ctxt->incNr; i++) {
1.2 ! veillard 719: xmlXIncludeLoadNode(ctxt, i);
1.1 veillard 720: }
721:
722: /*
723: * Third phase: extend the original document infoset.
724: */
1.2 ! veillard 725: for (i = 0;i < ctxt->incNr; i++) {
! 726: xmlXIncludeIncludeNode(ctxt, i);
! 727: }
1.1 veillard 728:
729: /*
730: * Cleanup
731: */
732: xmlXIncludeFreeContext(ctxt);
733: return(ret);
734: }
735:
736: #else /* !LIBXML_XINCLUDE_ENABLED */
737: #endif
Webmaster