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