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