Annotation of XML/tree.c, revision 1.103

1.1       veillard    1: /*
                      2:  * tree.c : implemetation of access function for an XML tree.
1.11      veillard    3:  *
                      4:  * See Copyright for the status of this software.
                      5:  *
1.32      daniel      6:  * Daniel.Veillard@w3.org
1.1       veillard    7:  */
                      8: 
1.59      daniel      9: #ifdef WIN32
1.80      daniel     10: #include "win32config.h"
1.59      daniel     11: #else
1.60      daniel     12: #include "config.h"
1.59      daniel     13: #endif
                     14: 
1.1       veillard   15: #include <stdio.h>
1.59      daniel     16: #include <string.h> /* for memset() only ! */
                     17: 
                     18: #ifdef HAVE_CTYPE_H
1.1       veillard   19: #include <ctype.h>
1.59      daniel     20: #endif
                     21: #ifdef HAVE_STDLIB_H
1.23      daniel     22: #include <stdlib.h>
1.59      daniel     23: #endif
1.23      daniel     24: #ifdef HAVE_ZLIB_H
                     25: #include <zlib.h>
                     26: #endif
                     27: 
1.101     daniel     28: #include <libxml/xmlmemory.h>
                     29: #include <libxml/tree.h>
                     30: #include <libxml/parser.h>
                     31: #include <libxml/entities.h>
                     32: #include <libxml/valid.h>
1.1       veillard   33: 
1.61      daniel     34: static xmlChar xmlStringText[] = { 't', 'e', 'x', 't', 0 };
1.90      daniel     35: static xmlChar xmlStringComment[] = { 'c', 'o', 'm', 'm', 'e', 'n', 't', 0 };
1.12      daniel     36: int oldXMLWDcompatibility = 0;
1.99      daniel     37: int xmlIndentTreeOutput = 0;
1.70      daniel     38: xmlBufferAllocationScheme xmlBufferAllocScheme = XML_BUFFER_ALLOC_EXACT;
1.7       veillard   39: 
1.23      daniel     40: static int xmlCompressMode = 0;
1.74      daniel     41: static int xmlCheckDTD = 1;
1.87      daniel     42: int xmlSaveNoEmptyTags = 0;
1.23      daniel     43: 
1.99      daniel     44: #define IS_BLANK(c)                                                    \
                     45:   (((c) == '\n') || ((c) == '\r') || ((c) == '\t') || ((c) == ' '))
                     46: 
1.32      daniel     47: #define UPDATE_LAST_CHILD(n) if ((n) != NULL) {                                \
1.90      daniel     48:     xmlNodePtr ulccur = (n)->children;                                 \
1.32      daniel     49:     if (ulccur == NULL) {                                              \
                     50:         (n)->last = NULL;                                              \
                     51:     } else {                                                           \
                     52:         while (ulccur->next != NULL) ulccur = ulccur->next;            \
                     53:        (n)->last = ulccur;                                             \
1.34      daniel     54: }}
1.32      daniel     55: 
1.86      daniel     56: /* #define DEBUG_BUFFER */
                     57: /* #define DEBUG_TREE */
                     58: 
1.1       veillard   59: /************************************************************************
                     60:  *                                                                     *
                     61:  *             Allocation and deallocation of basic structures         *
                     62:  *                                                                     *
                     63:  ************************************************************************/
                     64:  
1.23      daniel     65: /**
1.70      daniel     66:  * xmlSetBufferAllocationScheme:
                     67:  * @scheme:  allocation method to use
                     68:  * 
                     69:  * Set the buffer allocation method.  Types are
                     70:  * XML_BUFFER_ALLOC_EXACT - use exact sizes, keeps memory usage down
                     71:  * XML_BUFFER_ALLOC_DOUBLEIT - double buffer when extra needed, 
                     72:  *                             improves performance
                     73:  */
                     74: void
                     75: xmlSetBufferAllocationScheme(xmlBufferAllocationScheme scheme) {
                     76:     xmlBufferAllocScheme = scheme;
                     77: }
                     78: 
                     79: /**
                     80:  * xmlGetBufferAllocationScheme:
                     81:  *
                     82:  * Types are
                     83:  * XML_BUFFER_ALLOC_EXACT - use exact sizes, keeps memory usage down
                     84:  * XML_BUFFER_ALLOC_DOUBLEIT - double buffer when extra needed, 
                     85:  *                             improves performance
                     86:  * 
                     87:  * Returns the current allocation scheme
                     88:  */
                     89: xmlBufferAllocationScheme
                     90: xmlGetBufferAllocationScheme() {
                     91:     return xmlBufferAllocScheme;
                     92: }
                     93: 
                     94: /**
1.23      daniel     95:  * xmlUpgradeOldNs:
                     96:  * @doc:  a document pointer
                     97:  * 
                     98:  * Upgrade old style Namespaces (PI) and move them to the root of the document.
1.19      daniel     99:  */
1.28      daniel    100: void
                    101: xmlUpgradeOldNs(xmlDocPtr doc) {
1.19      daniel    102:     xmlNsPtr cur;
                    103: 
                    104:     if ((doc == NULL) || (doc->oldNs == NULL)) return;
1.90      daniel    105:     if (doc->children == NULL) {
1.86      daniel    106: #ifdef DEBUG_TREE
1.19      daniel    107:         fprintf(stderr, "xmlUpgradeOldNs: failed no root !\n");
1.86      daniel    108: #endif
1.19      daniel    109:        return;
                    110:     }
                    111: 
                    112:     cur = doc->oldNs;
                    113:     while (cur->next != NULL) {
                    114:        cur->type = XML_LOCAL_NAMESPACE;
                    115:         cur = cur->next;
                    116:     }
                    117:     cur->type = XML_LOCAL_NAMESPACE;
1.90      daniel    118:     cur->next = doc->children->nsDef;
                    119:     doc->children->nsDef = doc->oldNs;
1.19      daniel    120:     doc->oldNs = NULL;
                    121: }
                    122: 
1.23      daniel    123: /**
                    124:  * xmlNewNs:
                    125:  * @node:  the element carrying the namespace
                    126:  * @href:  the URI associated
                    127:  * @prefix:  the prefix for the namespace
                    128:  *
1.83      daniel    129:  * Creation of a new Namespace. This function will refuse to create
                    130:  * a namespace with a similar prefix than an existing one present on this
                    131:  * node.
                    132:  * Returns returns a new namespace pointer or NULL
1.1       veillard  133:  */
1.28      daniel    134: xmlNsPtr
1.61      daniel    135: xmlNewNs(xmlNodePtr node, const xmlChar *href, const xmlChar *prefix) {
1.16      daniel    136:     xmlNsPtr cur;
1.1       veillard  137: 
1.19      daniel    138:     if (href == NULL) {
1.86      daniel    139: #ifdef DEBUG_TREE
1.19      daniel    140:         fprintf(stderr, "xmlNewNs: href == NULL !\n");
1.86      daniel    141: #endif
1.19      daniel    142:        return(NULL);
                    143:     }
                    144: 
1.1       veillard  145:     /*
1.90      daniel    146:      * Allocate a new Namespace and fill the fields.
1.1       veillard  147:      */
1.57      daniel    148:     cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
1.1       veillard  149:     if (cur == NULL) {
1.16      daniel    150:         fprintf(stderr, "xmlNewNs : malloc failed\n");
1.1       veillard  151:        return(NULL);
                    152:     }
1.90      daniel    153:     memset(cur, 0, sizeof(xmlNs));
                    154:     cur->type = XML_LOCAL_NAMESPACE;
1.1       veillard  155: 
1.19      daniel    156:     if (href != NULL)
                    157:        cur->href = xmlStrdup(href); 
                    158:     if (prefix != NULL)
                    159:        cur->prefix = xmlStrdup(prefix); 
                    160: 
                    161:     /*
                    162:      * Add it at the end to preserve parsing order ...
1.83      daniel    163:      * and checks for existing use of the prefix
1.19      daniel    164:      */
                    165:     if (node != NULL) {
                    166:        if (node->nsDef == NULL) {
                    167:            node->nsDef = cur;
                    168:        } else {
                    169:            xmlNsPtr prev = node->nsDef;
                    170: 
1.86      daniel    171:            if (((prev->prefix == NULL) && (cur->prefix == NULL)) ||
                    172:                (!xmlStrcmp(prev->prefix, cur->prefix))) {
                    173:                xmlFreeNs(cur);
                    174:                return(NULL);
                    175:            }    
1.83      daniel    176:            while (prev->next != NULL) {
1.86      daniel    177:                prev = prev->next;
1.83      daniel    178:                if (((prev->prefix == NULL) && (cur->prefix == NULL)) ||
                    179:                    (!xmlStrcmp(prev->prefix, cur->prefix))) {
                    180:                    xmlFreeNs(cur);
                    181:                    return(NULL);
                    182:                }    
                    183:            }
1.19      daniel    184:            prev->next = cur;
                    185:        }
                    186:     }
                    187:     return(cur);
                    188: }
                    189: 
1.23      daniel    190: /**
                    191:  * xmlNewGlobalNs:
                    192:  * @doc:  the document carrying the namespace
                    193:  * @href:  the URI associated
                    194:  * @prefix:  the prefix for the namespace
                    195:  *
1.83      daniel    196:  * Creation of a Namespace, the old way using PI and without scoping
                    197:  *   DEPRECATED !!!
1.85      daniel    198:  * It now create a namespace on the root element of the document if found.
1.83      daniel    199:  * Returns NULL this functionnality had been removed
1.19      daniel    200:  */
1.28      daniel    201: xmlNsPtr
1.61      daniel    202: xmlNewGlobalNs(xmlDocPtr doc, const xmlChar *href, const xmlChar *prefix) {
1.85      daniel    203:     xmlNodePtr root;
                    204: 
1.86      daniel    205:     xmlNsPtr cur;
                    206:  
1.85      daniel    207:     root = xmlDocGetRootElement(doc);
                    208:     if (root != NULL)
                    209:        return(xmlNewNs(root, href, prefix));
1.86      daniel    210:        
                    211:     /*
                    212:      * if there is no root element yet, create an old Namespace type
                    213:      * and it will be moved to the root at save time.
                    214:      */
                    215:     cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
                    216:     if (cur == NULL) {
                    217:         fprintf(stderr, "xmlNewGlobalNs : malloc failed\n");
                    218:        return(NULL);
                    219:     }
1.90      daniel    220:     memset(cur, 0, sizeof(xmlNs));
                    221:     cur->type = XML_GLOBAL_NAMESPACE;
1.86      daniel    222: 
                    223:     if (href != NULL)
                    224:        cur->href = xmlStrdup(href); 
                    225:     if (prefix != NULL)
                    226:        cur->prefix = xmlStrdup(prefix); 
                    227: 
                    228:     /*
                    229:      * Add it at the end to preserve parsing order ...
                    230:      */
                    231:     if (doc != NULL) {
                    232:        if (doc->oldNs == NULL) {
                    233:            doc->oldNs = cur;
                    234:        } else {
                    235:            xmlNsPtr prev = doc->oldNs;
                    236: 
                    237:            while (prev->next != NULL) prev = prev->next;
                    238:            prev->next = cur;
                    239:        }
                    240:     }
                    241: 
                    242:   return(NULL);
1.1       veillard  243: }
                    244: 
1.23      daniel    245: /**
                    246:  * xmlSetNs:
                    247:  * @node:  a node in the document
                    248:  * @ns:  a namespace pointer
                    249:  *
                    250:  * Associate a namespace to a node, a posteriori.
1.19      daniel    251:  */
1.28      daniel    252: void
                    253: xmlSetNs(xmlNodePtr node, xmlNsPtr ns) {
1.19      daniel    254:     if (node == NULL) {
1.86      daniel    255: #ifdef DEBUG_TREE
1.19      daniel    256:         fprintf(stderr, "xmlSetNs: node == NULL\n");
1.94      daniel    257: #endif
1.19      daniel    258:        return;
                    259:     }
                    260:     node->ns = ns;
                    261: }
                    262: 
1.23      daniel    263: /**
                    264:  * xmlFreeNs:
                    265:  * @cur:  the namespace pointer
                    266:  *
                    267:  * Free up the structures associated to a namespace
1.1       veillard  268:  */
1.28      daniel    269: void
                    270: xmlFreeNs(xmlNsPtr cur) {
1.1       veillard  271:     if (cur == NULL) {
1.86      daniel    272: #ifdef DEBUG_TREE
1.17      daniel    273:         fprintf(stderr, "xmlFreeNs : ns == NULL\n");
1.86      daniel    274: #endif
1.1       veillard  275:        return;
                    276:     }
1.57      daniel    277:     if (cur->href != NULL) xmlFree((char *) cur->href);
                    278:     if (cur->prefix != NULL) xmlFree((char *) cur->prefix);
1.16      daniel    279:     memset(cur, -1, sizeof(xmlNs));
1.57      daniel    280:     xmlFree(cur);
1.1       veillard  281: }
                    282: 
1.23      daniel    283: /**
                    284:  * xmlFreeNsList:
                    285:  * @cur:  the first namespace pointer
                    286:  *
                    287:  * Free up all the structures associated to the chained namespaces.
1.6       veillard  288:  */
1.28      daniel    289: void
                    290: xmlFreeNsList(xmlNsPtr cur) {
1.16      daniel    291:     xmlNsPtr next;
1.6       veillard  292:     if (cur == NULL) {
1.86      daniel    293: #ifdef DEBUG_TREE
1.16      daniel    294:         fprintf(stderr, "xmlFreeNsList : ns == NULL\n");
1.86      daniel    295: #endif
1.6       veillard  296:        return;
                    297:     }
                    298:     while (cur != NULL) {
                    299:         next = cur->next;
1.16      daniel    300:         xmlFreeNs(cur);
1.6       veillard  301:        cur = next;
                    302:     }
                    303: }
                    304: 
1.23      daniel    305: /**
                    306:  * xmlNewDtd:
                    307:  * @doc:  the document pointer
                    308:  * @name:  the DTD name
                    309:  * @ExternalID:  the external ID
                    310:  * @SystemID:  the system ID
                    311:  *
1.94      daniel    312:  * Creation of a new DTD for the external subset. To create an
                    313:  * internal subset, use xmlCreateIntSubset().
                    314:  *
1.36      daniel    315:  * Returns a pointer to the new DTD structure
1.17      daniel    316:  */
1.28      daniel    317: xmlDtdPtr
1.61      daniel    318: xmlNewDtd(xmlDocPtr doc, const xmlChar *name,
                    319:                     const xmlChar *ExternalID, const xmlChar *SystemID) {
1.17      daniel    320:     xmlDtdPtr cur;
                    321: 
1.31      daniel    322:     if ((doc != NULL) && (doc->extSubset != NULL)) {
1.86      daniel    323: #ifdef DEBUG_TREE
1.17      daniel    324:         fprintf(stderr, "xmlNewDtd(%s): document %s already have a DTD %s\n",
1.31      daniel    325:            /* !!! */ (char *) name, doc->name,
                    326:            /* !!! */ (char *)doc->extSubset->name);
1.86      daniel    327: #endif
                    328:        return(NULL);
1.17      daniel    329:     }
                    330: 
                    331:     /*
                    332:      * Allocate a new DTD and fill the fields.
                    333:      */
1.57      daniel    334:     cur = (xmlDtdPtr) xmlMalloc(sizeof(xmlDtd));
1.17      daniel    335:     if (cur == NULL) {
1.31      daniel    336:         fprintf(stderr, "xmlNewDtd : malloc failed\n");
                    337:        return(NULL);
                    338:     }
1.90      daniel    339:     memset(cur, 0 , sizeof(xmlDtd));
                    340:     cur->type = XML_DTD_NODE;
1.31      daniel    341: 
                    342:     if (name != NULL)
                    343:        cur->name = xmlStrdup(name); 
                    344:     if (ExternalID != NULL)
                    345:        cur->ExternalID = xmlStrdup(ExternalID); 
                    346:     if (SystemID != NULL)
                    347:        cur->SystemID = xmlStrdup(SystemID); 
                    348:     if (doc != NULL)
                    349:        doc->extSubset = cur;
1.94      daniel    350:     cur->doc = doc;
1.31      daniel    351: 
                    352:     return(cur);
                    353: }
                    354: 
                    355: /**
1.92      daniel    356:  * xmlGetIntSubset:
                    357:  * @doc:  the document pointer
                    358:  *
                    359:  * Get the internal subset of a document
                    360:  * Returns a pointer to the DTD structure or NULL if not found
                    361:  */
                    362: 
                    363: xmlDtdPtr
                    364: xmlGetIntSubset(xmlDocPtr doc) {
                    365:     xmlNodePtr cur;
                    366: 
                    367:     if (doc == NULL)
                    368:        return(NULL);
                    369:     cur = doc->children;
                    370:     while (cur != NULL) {
                    371:        if (cur->type == XML_DTD_NODE)
                    372:            return((xmlDtdPtr) cur);
                    373:        cur = cur->next;
                    374:     }
                    375:     return((xmlDtdPtr) doc->intSubset);
                    376: }
                    377: 
                    378: /**
1.31      daniel    379:  * xmlCreateIntSubset:
                    380:  * @doc:  the document pointer
                    381:  * @name:  the DTD name
                    382:  * @ExternalID:  the external ID
                    383:  * @SystemID:  the system ID
                    384:  *
1.36      daniel    385:  * Create the internal subset of a document
                    386:  * Returns a pointer to the new DTD structure
1.31      daniel    387:  */
                    388: xmlDtdPtr
1.61      daniel    389: xmlCreateIntSubset(xmlDocPtr doc, const xmlChar *name,
                    390:                    const xmlChar *ExternalID, const xmlChar *SystemID) {
1.31      daniel    391:     xmlDtdPtr cur;
                    392: 
1.92      daniel    393:     if ((doc != NULL) && (xmlGetIntSubset(doc) != NULL)) {
1.86      daniel    394: #ifdef DEBUG_TREE
1.31      daniel    395:         fprintf(stderr, 
                    396:      "xmlCreateIntSubset(): document %s already have an internal subset\n",
                    397:            doc->name);
1.86      daniel    398: #endif
1.31      daniel    399:        return(NULL);
                    400:     }
                    401: 
                    402:     /*
                    403:      * Allocate a new DTD and fill the fields.
                    404:      */
1.57      daniel    405:     cur = (xmlDtdPtr) xmlMalloc(sizeof(xmlDtd));
1.31      daniel    406:     if (cur == NULL) {
                    407:         fprintf(stderr, "xmlNewDtd : malloc failed\n");
1.17      daniel    408:        return(NULL);
                    409:     }
1.90      daniel    410:     memset(cur, 0, sizeof(xmlDtd));
                    411:     cur->type = XML_DTD_NODE;
1.17      daniel    412: 
                    413:     if (name != NULL)
                    414:        cur->name = xmlStrdup(name); 
                    415:     if (ExternalID != NULL)
                    416:        cur->ExternalID = xmlStrdup(ExternalID); 
                    417:     if (SystemID != NULL)
                    418:        cur->SystemID = xmlStrdup(SystemID); 
1.90      daniel    419:     if (doc != NULL) {
1.31      daniel    420:        doc->intSubset = cur;
1.90      daniel    421:        cur->parent = doc;
1.94      daniel    422:        cur->doc = doc;
1.92      daniel    423:        if (doc->children == NULL) {
                    424:            doc->children = (xmlNodePtr) cur;
                    425:            doc->last = (xmlNodePtr) cur;
                    426:        } else {
                    427:            xmlNodePtr prev;
                    428: 
                    429:            prev = doc->last;
                    430:            prev->next = (xmlNodePtr) cur;
                    431:            cur->prev = prev;
                    432:            doc->last = (xmlNodePtr) cur;
                    433:        }
1.90      daniel    434:     }
1.17      daniel    435:     return(cur);
                    436: }
                    437: 
1.23      daniel    438: /**
                    439:  * xmlFreeDtd:
                    440:  * @cur:  the DTD structure to free up
                    441:  *
                    442:  * Free a DTD structure.
1.17      daniel    443:  */
1.28      daniel    444: void
                    445: xmlFreeDtd(xmlDtdPtr cur) {
1.17      daniel    446:     if (cur == NULL) {
1.86      daniel    447: #ifdef DEBUG_TREE
1.17      daniel    448:         fprintf(stderr, "xmlFreeDtd : DTD == NULL\n");
1.86      daniel    449: #endif
1.17      daniel    450:        return;
                    451:     }
1.97      daniel    452:     if (cur->children != NULL) {
                    453:        xmlNodePtr next, c = cur->children;
                    454: 
                    455:        /*
                    456:         * Cleanup all the DTD comments they are not in the Dtd
                    457:         * indexes.
                    458:         */
                    459:         while (c != NULL) {
                    460:            next = c->next;
                    461:            if (c->type == XML_COMMENT_NODE) {
                    462:                xmlUnlinkNode(c);
                    463:                xmlFreeNode(c);
                    464:            }
                    465:            c = next;
                    466:        }
                    467:     }
1.57      daniel    468:     if (cur->name != NULL) xmlFree((char *) cur->name);
                    469:     if (cur->SystemID != NULL) xmlFree((char *) cur->SystemID);
                    470:     if (cur->ExternalID != NULL) xmlFree((char *) cur->ExternalID);
1.97      daniel    471:     /* TODO !!! */
1.35      daniel    472:     if (cur->notations != NULL)
                    473:         xmlFreeNotationTable((xmlNotationTablePtr) cur->notations);
1.97      daniel    474:     
1.17      daniel    475:     if (cur->elements != NULL)
1.33      daniel    476:         xmlFreeElementTable((xmlElementTablePtr) cur->elements);
1.34      daniel    477:     if (cur->attributes != NULL)
                    478:         xmlFreeAttributeTable((xmlAttributeTablePtr) cur->attributes);
1.17      daniel    479:     if (cur->entities != NULL)
                    480:         xmlFreeEntitiesTable((xmlEntitiesTablePtr) cur->entities);
1.97      daniel    481: 
1.17      daniel    482:     memset(cur, -1, sizeof(xmlDtd));
1.57      daniel    483:     xmlFree(cur);
1.17      daniel    484: }
                    485: 
1.23      daniel    486: /**
                    487:  * xmlNewDoc:
1.61      daniel    488:  * @version:  xmlChar string giving the version of XML "1.0"
1.23      daniel    489:  *
1.36      daniel    490:  * Returns a new document
1.1       veillard  491:  */
1.28      daniel    492: xmlDocPtr
1.61      daniel    493: xmlNewDoc(const xmlChar *version) {
1.1       veillard  494:     xmlDocPtr cur;
                    495: 
                    496:     if (version == NULL) {
1.86      daniel    497: #ifdef DEBUG_TREE
1.1       veillard  498:         fprintf(stderr, "xmlNewDoc : version == NULL\n");
1.86      daniel    499: #endif
1.1       veillard  500:        return(NULL);
                    501:     }
                    502: 
                    503:     /*
                    504:      * Allocate a new document and fill the fields.
                    505:      */
1.57      daniel    506:     cur = (xmlDocPtr) xmlMalloc(sizeof(xmlDoc));
1.1       veillard  507:     if (cur == NULL) {
                    508:         fprintf(stderr, "xmlNewDoc : malloc failed\n");
                    509:        return(NULL);
                    510:     }
1.90      daniel    511:     memset(cur, 0, sizeof(xmlDoc));
                    512:     cur->type = XML_DOCUMENT_NODE;
1.1       veillard  513: 
1.7       veillard  514:     cur->version = xmlStrdup(version); 
1.15      daniel    515:     cur->standalone = -1;
1.68      daniel    516:     cur->compression = -1; /* not initialized */
1.94      daniel    517:     cur->doc = cur;
1.1       veillard  518:     return(cur);
                    519: }
                    520: 
1.23      daniel    521: /**
                    522:  * xmlFreeDoc:
                    523:  * @cur:  pointer to the document
                    524:  * @:  
                    525:  *
                    526:  * Free up all the structures used by a document, tree included.
1.1       veillard  527:  */
1.28      daniel    528: void
                    529: xmlFreeDoc(xmlDocPtr cur) {
1.1       veillard  530:     if (cur == NULL) {
1.31      daniel    531: #ifdef DEBUG_TREE
1.1       veillard  532:         fprintf(stderr, "xmlFreeDoc : document == NULL\n");
1.31      daniel    533: #endif
1.1       veillard  534:        return;
                    535:     }
1.57      daniel    536:     if (cur->version != NULL) xmlFree((char *) cur->version);
                    537:     if (cur->name != NULL) xmlFree((char *) cur->name);
                    538:     if (cur->encoding != NULL) xmlFree((char *) cur->encoding);
1.90      daniel    539:     if (cur->children != NULL) xmlFreeNodeList(cur->children);
1.31      daniel    540:     if (cur->intSubset != NULL) xmlFreeDtd(cur->intSubset);
                    541:     if (cur->extSubset != NULL) xmlFreeDtd(cur->extSubset);
                    542:     if (cur->oldNs != NULL) xmlFreeNsList(cur->oldNs);
1.52      daniel    543:     if (cur->ids != NULL) xmlFreeIDTable((xmlIDTablePtr) cur->ids);
1.58      daniel    544:     if (cur->refs != NULL) xmlFreeRefTable((xmlRefTablePtr) cur->refs);
1.100     daniel    545:     if (cur->URL != NULL) xmlFree((char *) cur->URL);
1.1       veillard  546:     memset(cur, -1, sizeof(xmlDoc));
1.57      daniel    547:     xmlFree(cur);
1.1       veillard  548: }
                    549: 
1.23      daniel    550: /**
1.28      daniel    551:  * xmlStringLenGetNodeList:
                    552:  * @doc:  the document
                    553:  * @value:  the value of the text
1.36      daniel    554:  * @len:  the length of the string value
1.28      daniel    555:  *
                    556:  * Parse the value string and build the node list associated. Should
                    557:  * produce a flat tree with only TEXTs and ENTITY_REFs.
1.36      daniel    558:  * Returns a pointer to the first child
1.28      daniel    559:  */
                    560: xmlNodePtr
1.61      daniel    561: xmlStringLenGetNodeList(xmlDocPtr doc, const xmlChar *value, int len) {
1.28      daniel    562:     xmlNodePtr ret = NULL, last = NULL;
                    563:     xmlNodePtr node;
1.61      daniel    564:     xmlChar *val;
                    565:     const xmlChar *cur = value;
                    566:     const xmlChar *q;
1.28      daniel    567:     xmlEntityPtr ent;
                    568: 
                    569:     if (value == NULL) return(NULL);
                    570: 
                    571:     q = cur;
                    572:     while ((*cur != 0) && (cur - value < len)) {
                    573:        if (*cur == '&') {
                    574:            /*
                    575:             * Save the current text.
                    576:             */
                    577:             if (cur != q) {
                    578:                if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
                    579:                    xmlNodeAddContentLen(last, q, cur - q);
                    580:                } else {
                    581:                    node = xmlNewDocTextLen(doc, q, cur - q);
                    582:                    if (node == NULL) return(ret);
                    583:                    if (last == NULL)
                    584:                        last = ret = node;
                    585:                    else {
                    586:                        last->next = node;
                    587:                        node->prev = last;
                    588:                        last = node;
                    589:                    }
                    590:                }
                    591:            }
                    592:            /*
                    593:             * Read the entity string
                    594:             */
                    595:            cur++;
                    596:            q = cur;
                    597:            while ((*cur != 0) && (cur - value < len) && (*cur != ';')) cur++;
                    598:            if ((*cur == 0) || (cur - value >= len)) {
1.86      daniel    599: #ifdef DEBUG_TREE
1.28      daniel    600:                fprintf(stderr,
1.44      daniel    601:                    "xmlStringLenGetNodeList: unterminated entity %30s\n", q);
1.86      daniel    602: #endif
1.28      daniel    603:                return(ret);
                    604:            }
                    605:             if (cur != q) {
                    606:                /*
                    607:                 * Predefined entities don't generate nodes
                    608:                 */
                    609:                val = xmlStrndup(q, cur - q);
                    610:                ent = xmlGetDocEntity(doc, val);
                    611:                if ((ent != NULL) &&
1.95      daniel    612:                    (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
1.28      daniel    613:                    if (last == NULL) {
                    614:                        node = xmlNewDocText(doc, ent->content);
                    615:                        last = ret = node;
                    616:                    } else
                    617:                        xmlNodeAddContent(last, ent->content);
                    618:                        
                    619:                } else {
                    620:                    /*
                    621:                     * Create a new REFERENCE_REF node
                    622:                     */
                    623:                    node = xmlNewReference(doc, val);
1.30      daniel    624:                    if (node == NULL) {
1.57      daniel    625:                        if (val != NULL) xmlFree(val);
1.30      daniel    626:                        return(ret);
                    627:                    }
1.28      daniel    628:                    if (last == NULL)
                    629:                        last = ret = node;
                    630:                    else {
                    631:                        last->next = node;
                    632:                        node->prev = last;
                    633:                        last = node;
                    634:                    }
                    635:                }
1.57      daniel    636:                xmlFree(val);
1.28      daniel    637:            }
                    638:            cur++;
                    639:            q = cur;
                    640:        } else 
                    641:            cur++;
                    642:     }
                    643:     if (cur != q) {
                    644:         /*
                    645:         * Handle the last piece of text.
                    646:         */
                    647:        if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
                    648:            xmlNodeAddContentLen(last, q, cur - q);
                    649:        } else {
                    650:            node = xmlNewDocTextLen(doc, q, cur - q);
                    651:            if (node == NULL) return(ret);
                    652:            if (last == NULL)
                    653:                last = ret = node;
                    654:            else {
                    655:                last->next = node;
                    656:                node->prev = last;
                    657:                last = node;
                    658:            }
                    659:        }
                    660:     }
                    661:     return(ret);
                    662: }
                    663: 
                    664: /**
1.24      daniel    665:  * xmlStringGetNodeList:
                    666:  * @doc:  the document
1.23      daniel    667:  * @value:  the value of the attribute
                    668:  *
1.24      daniel    669:  * Parse the value string and build the node list associated. Should
                    670:  * produce a flat tree with only TEXTs and ENTITY_REFs.
1.36      daniel    671:  * Returns a pointer to the first child
1.23      daniel    672:  */
1.28      daniel    673: xmlNodePtr
1.61      daniel    674: xmlStringGetNodeList(xmlDocPtr doc, const xmlChar *value) {
1.23      daniel    675:     xmlNodePtr ret = NULL, last = NULL;
                    676:     xmlNodePtr node;
1.61      daniel    677:     xmlChar *val;
                    678:     const xmlChar *cur = value;
                    679:     const xmlChar *q;
1.28      daniel    680:     xmlEntityPtr ent;
1.23      daniel    681: 
                    682:     if (value == NULL) return(NULL);
                    683: 
                    684:     q = cur;
                    685:     while (*cur != 0) {
                    686:        if (*cur == '&') {
1.28      daniel    687:            /*
                    688:             * Save the current text.
                    689:             */
1.23      daniel    690:             if (cur != q) {
1.28      daniel    691:                if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
                    692:                    xmlNodeAddContentLen(last, q, cur - q);
                    693:                } else {
                    694:                    node = xmlNewDocTextLen(doc, q, cur - q);
                    695:                    if (node == NULL) return(ret);
                    696:                    if (last == NULL)
                    697:                        last = ret = node;
                    698:                    else {
                    699:                        last->next = node;
                    700:                        node->prev = last;
                    701:                        last = node;
                    702:                    }
1.23      daniel    703:                }
                    704:            }
1.28      daniel    705:            /*
                    706:             * Read the entity string
                    707:             */
1.23      daniel    708:            cur++;
                    709:            q = cur;
                    710:            while ((*cur != 0) && (*cur != ';')) cur++;
                    711:            if (*cur == 0) {
1.86      daniel    712: #ifdef DEBUG_TREE
1.24      daniel    713:                fprintf(stderr,
                    714:                        "xmlStringGetNodeList: unterminated entity %30s\n", q);
1.86      daniel    715: #endif
1.23      daniel    716:                return(ret);
                    717:            }
                    718:             if (cur != q) {
1.28      daniel    719:                /*
                    720:                 * Predefined entities don't generate nodes
                    721:                 */
1.23      daniel    722:                val = xmlStrndup(q, cur - q);
1.28      daniel    723:                ent = xmlGetDocEntity(doc, val);
                    724:                if ((ent != NULL) &&
1.95      daniel    725:                    (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
1.28      daniel    726:                    if (last == NULL) {
                    727:                        node = xmlNewDocText(doc, ent->content);
                    728:                        last = ret = node;
                    729:                    } else
                    730:                        xmlNodeAddContent(last, ent->content);
                    731:                        
                    732:                } else {
                    733:                    /*
                    734:                     * Create a new REFERENCE_REF node
                    735:                     */
                    736:                    node = xmlNewReference(doc, val);
1.30      daniel    737:                    if (node == NULL) {
1.57      daniel    738:                        if (val != NULL) xmlFree(val);
1.30      daniel    739:                        return(ret);
                    740:                    }
1.28      daniel    741:                    if (last == NULL)
                    742:                        last = ret = node;
                    743:                    else {
                    744:                        last->next = node;
                    745:                        node->prev = last;
                    746:                        last = node;
                    747:                    }
1.23      daniel    748:                }
1.57      daniel    749:                xmlFree(val);
1.23      daniel    750:            }
                    751:            cur++;
                    752:            q = cur;
                    753:        } else 
                    754:            cur++;
                    755:     }
                    756:     if (cur != q) {
1.28      daniel    757:         /*
                    758:         * Handle the last piece of text.
                    759:         */
                    760:        if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
                    761:            xmlNodeAddContentLen(last, q, cur - q);
                    762:        } else {
                    763:            node = xmlNewDocTextLen(doc, q, cur - q);
                    764:            if (node == NULL) return(ret);
                    765:            if (last == NULL)
                    766:                last = ret = node;
                    767:            else {
                    768:                last->next = node;
                    769:                node->prev = last;
                    770:                last = node;
                    771:            }
1.23      daniel    772:        }
                    773:     }
                    774:     return(ret);
                    775: }
                    776: 
                    777: /**
1.24      daniel    778:  * xmlNodeListGetString:
1.23      daniel    779:  * @doc:  the document
1.24      daniel    780:  * @list:  a Node list
1.23      daniel    781:  * @inLine:  should we replace entity contents or show their external form
                    782:  *
1.24      daniel    783:  * Returns the string equivalent to the text contained in the Node list
                    784:  * made of TEXTs and ENTITY_REFs
1.36      daniel    785:  * Returns a pointer to the string copy, the calller must free it.
1.23      daniel    786:  */
1.61      daniel    787: xmlChar *
1.28      daniel    788: xmlNodeListGetString(xmlDocPtr doc, xmlNodePtr list, int inLine) {
1.24      daniel    789:     xmlNodePtr node = list;
1.61      daniel    790:     xmlChar *ret = NULL;
1.23      daniel    791:     xmlEntityPtr ent;
                    792: 
1.24      daniel    793:     if (list == NULL) return(NULL);
1.23      daniel    794: 
                    795:     while (node != NULL) {
                    796:         if (node->type == XML_TEXT_NODE) {
1.84      daniel    797:            if (inLine) {
1.70      daniel    798: #ifndef XML_USE_BUFFER_CONTENT
1.23      daniel    799:                ret = xmlStrcat(ret, node->content);
1.70      daniel    800: #else
                    801:                ret = xmlStrcat(ret, xmlBufferContent(node->content));
                    802: #endif
                    803:            } else {
1.61      daniel    804:                xmlChar *buffer;
1.45      daniel    805: 
1.70      daniel    806: #ifndef XML_USE_BUFFER_CONTENT
1.46      daniel    807:                buffer = xmlEncodeEntitiesReentrant(doc, node->content);
1.70      daniel    808: #else
                    809:                buffer = xmlEncodeEntitiesReentrant(doc,
                    810:                                            xmlBufferContent(node->content));
                    811: #endif
1.45      daniel    812:                if (buffer != NULL) {
                    813:                    ret = xmlStrcat(ret, buffer);
1.57      daniel    814:                    xmlFree(buffer);
1.45      daniel    815:                }
                    816:             }
1.23      daniel    817:        } else if (node->type == XML_ENTITY_REF_NODE) {
                    818:            if (inLine) {
                    819:                ent = xmlGetDocEntity(doc, node->name);
                    820:                if (ent != NULL)
                    821:                    ret = xmlStrcat(ret, ent->content);
1.70      daniel    822:                else {
                    823: #ifndef XML_USE_BUFFER_CONTENT
1.23      daniel    824:                    ret = xmlStrcat(ret, node->content);
1.70      daniel    825: #else
                    826:                    ret = xmlStrcat(ret, xmlBufferContent(node->content));
                    827: #endif
                    828:                }    
1.23      daniel    829:             } else {
1.61      daniel    830:                xmlChar buf[2];
1.23      daniel    831:                buf[0] = '&'; buf[1] = 0;
                    832:                ret = xmlStrncat(ret, buf, 1);
                    833:                ret = xmlStrcat(ret, node->name);
                    834:                buf[0] = ';'; buf[1] = 0;
                    835:                ret = xmlStrncat(ret, buf, 1);
                    836:            }
1.24      daniel    837:        }
                    838: #if 0
                    839:        else {
                    840:            fprintf(stderr, "xmlGetNodeListString : invalide node type %d\n",
1.23      daniel    841:                    node->type);
                    842:        }
1.24      daniel    843: #endif
1.23      daniel    844:        node = node->next;
                    845:     }
                    846:     return(ret);
                    847: }
                    848: 
                    849: /**
                    850:  * xmlNewProp:
                    851:  * @node:  the holding node
                    852:  * @name:  the name of the attribute
                    853:  * @value:  the value of the attribute
                    854:  *
                    855:  * Create a new property carried by a node.
1.36      daniel    856:  * Returns a pointer to the attribute
1.1       veillard  857:  */
1.28      daniel    858: xmlAttrPtr
1.61      daniel    859: xmlNewProp(xmlNodePtr node, const xmlChar *name, const xmlChar *value) {
1.20      daniel    860:     xmlAttrPtr cur;
1.1       veillard  861: 
                    862:     if (name == NULL) {
1.86      daniel    863: #ifdef DEBUG_TREE
1.1       veillard  864:         fprintf(stderr, "xmlNewProp : name == NULL\n");
1.86      daniel    865: #endif
1.1       veillard  866:        return(NULL);
                    867:     }
                    868: 
                    869:     /*
                    870:      * Allocate a new property and fill the fields.
                    871:      */
1.57      daniel    872:     cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr));
1.1       veillard  873:     if (cur == NULL) {
                    874:         fprintf(stderr, "xmlNewProp : malloc failed\n");
                    875:        return(NULL);
                    876:     }
1.90      daniel    877:     memset(cur, 0, sizeof(xmlAttr));
                    878:     cur->type = XML_ATTRIBUTE_NODE;
1.1       veillard  879: 
1.90      daniel    880:     cur->parent = node; 
1.56      daniel    881:     cur->name = xmlStrdup(name);
1.67      daniel    882:     if (value != NULL) {
                    883:        xmlChar *buffer;
1.94      daniel    884:        xmlNodePtr tmp;
                    885: 
1.67      daniel    886:        buffer = xmlEncodeEntitiesReentrant(node->doc, value);
1.90      daniel    887:        cur->children = xmlStringGetNodeList(node->doc, buffer);
1.94      daniel    888:        tmp = cur->children;
                    889:        while (tmp != NULL) {
                    890:            tmp->parent = (xmlNodePtr) cur;
                    891:            if (tmp->next == NULL)
                    892:                cur->last = tmp;
                    893:            tmp = tmp->next;
                    894:        }
1.67      daniel    895:        xmlFree(buffer);
                    896:     }  
1.56      daniel    897: 
                    898:     /*
                    899:      * Add it at the end to preserve parsing order ...
                    900:      */
                    901:     if (node != NULL) {
                    902:        if (node->properties == NULL) {
                    903:            node->properties = cur;
                    904:        } else {
                    905:            xmlAttrPtr prev = node->properties;
                    906: 
                    907:            while (prev->next != NULL) prev = prev->next;
                    908:            prev->next = cur;
1.94      daniel    909:            cur->prev = prev;
1.56      daniel    910:        }
                    911:     }
                    912:     return(cur);
                    913: }
                    914: 
                    915: /**
                    916:  * xmlNewNsProp:
                    917:  * @node:  the holding node
                    918:  * @ns:  the namespace
                    919:  * @name:  the name of the attribute
                    920:  * @value:  the value of the attribute
                    921:  *
                    922:  * Create a new property tagged with a namespace and carried by a node.
                    923:  * Returns a pointer to the attribute
                    924:  */
                    925: xmlAttrPtr
1.61      daniel    926: xmlNewNsProp(xmlNodePtr node, xmlNsPtr ns, const xmlChar *name,
                    927:            const xmlChar *value) {
1.56      daniel    928:     xmlAttrPtr cur;
                    929: 
                    930:     if (name == NULL) {
1.86      daniel    931: #ifdef DEBUG_TREE
1.56      daniel    932:         fprintf(stderr, "xmlNewProp : name == NULL\n");
1.86      daniel    933: #endif
1.56      daniel    934:        return(NULL);
                    935:     }
                    936: 
                    937:     /*
                    938:      * Allocate a new property and fill the fields.
                    939:      */
1.57      daniel    940:     cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr));
1.56      daniel    941:     if (cur == NULL) {
                    942:         fprintf(stderr, "xmlNewProp : malloc failed\n");
                    943:        return(NULL);
                    944:     }
1.90      daniel    945:     memset(cur, 0, sizeof(xmlAttr));
                    946:     cur->type = XML_ATTRIBUTE_NODE;
1.56      daniel    947: 
1.90      daniel    948:     cur->parent = node; 
1.94      daniel    949:     if (node != NULL)
                    950:        cur->doc = node->doc; 
1.56      daniel    951:     cur->ns = ns;
1.7       veillard  952:     cur->name = xmlStrdup(name);
1.94      daniel    953:     if (value != NULL) {
                    954:        xmlChar *buffer;
                    955:        xmlNodePtr tmp;
                    956: 
                    957:        buffer = xmlEncodeEntitiesReentrant(node->doc, value);
                    958:        cur->children = xmlStringGetNodeList(node->doc, buffer);
                    959:        tmp = cur->children;
                    960:        while (tmp != NULL) {
                    961:            tmp->parent = (xmlNodePtr) cur;
                    962:            if (tmp->next == NULL)
                    963:                cur->last = tmp;
                    964:            tmp = tmp->next;
                    965:        }
                    966:        xmlFree(buffer);
                    967:     }
1.17      daniel    968: 
                    969:     /*
                    970:      * Add it at the end to preserve parsing order ...
                    971:      */
1.1       veillard  972:     if (node != NULL) {
1.17      daniel    973:        if (node->properties == NULL) {
                    974:            node->properties = cur;
                    975:        } else {
1.20      daniel    976:            xmlAttrPtr prev = node->properties;
1.17      daniel    977: 
                    978:            while (prev->next != NULL) prev = prev->next;
                    979:            prev->next = cur;
1.94      daniel    980:            cur->prev = prev;
1.17      daniel    981:        }
                    982:     }
1.1       veillard  983:     return(cur);
                    984: }
                    985: 
1.23      daniel    986: /**
                    987:  * xmlNewDocProp:
                    988:  * @doc:  the document
                    989:  * @name:  the name of the attribute
                    990:  * @value:  the value of the attribute
                    991:  *
                    992:  * Create a new property carried by a document.
1.36      daniel    993:  * Returns a pointer to the attribute
1.23      daniel    994:  */
1.28      daniel    995: xmlAttrPtr
1.61      daniel    996: xmlNewDocProp(xmlDocPtr doc, const xmlChar *name, const xmlChar *value) {
1.23      daniel    997:     xmlAttrPtr cur;
                    998: 
                    999:     if (name == NULL) {
1.86      daniel   1000: #ifdef DEBUG_TREE
1.23      daniel   1001:         fprintf(stderr, "xmlNewProp : name == NULL\n");
1.86      daniel   1002: #endif
1.23      daniel   1003:        return(NULL);
                   1004:     }
                   1005: 
                   1006:     /*
                   1007:      * Allocate a new property and fill the fields.
                   1008:      */
1.57      daniel   1009:     cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr));
1.23      daniel   1010:     if (cur == NULL) {
                   1011:         fprintf(stderr, "xmlNewProp : malloc failed\n");
                   1012:        return(NULL);
                   1013:     }
1.90      daniel   1014:     memset(cur, 0, sizeof(xmlAttr));
                   1015:     cur->type = XML_ATTRIBUTE_NODE;
1.23      daniel   1016: 
                   1017:     cur->name = xmlStrdup(name);
1.94      daniel   1018:     cur->doc = doc; 
1.23      daniel   1019:     if (value != NULL)
1.90      daniel   1020:        cur->children = xmlStringGetNodeList(doc, value);
1.23      daniel   1021:     return(cur);
                   1022: }
                   1023: 
                   1024: /**
                   1025:  * xmlFreePropList:
                   1026:  * @cur:  the first property in the list
                   1027:  *
1.90      daniel   1028:  * Free a property and all its siblings, all the children are freed too.
1.1       veillard 1029:  */
1.28      daniel   1030: void
                   1031: xmlFreePropList(xmlAttrPtr cur) {
1.20      daniel   1032:     xmlAttrPtr next;
1.1       veillard 1033:     if (cur == NULL) {
1.86      daniel   1034: #ifdef DEBUG_TREE
1.1       veillard 1035:         fprintf(stderr, "xmlFreePropList : property == NULL\n");
1.86      daniel   1036: #endif
1.1       veillard 1037:        return;
                   1038:     }
                   1039:     while (cur != NULL) {
                   1040:         next = cur->next;
                   1041:         xmlFreeProp(cur);
                   1042:        cur = next;
                   1043:     }
                   1044: }
                   1045: 
1.23      daniel   1046: /**
                   1047:  * xmlFreeProp:
1.83      daniel   1048:  * @cur:  an attribute
1.23      daniel   1049:  *
1.83      daniel   1050:  * Free one attribute, all the content is freed too
1.1       veillard 1051:  */
1.28      daniel   1052: void
                   1053: xmlFreeProp(xmlAttrPtr cur) {
1.1       veillard 1054:     if (cur == NULL) {
1.86      daniel   1055: #ifdef DEBUG_TREE
1.1       veillard 1056:         fprintf(stderr, "xmlFreeProp : property == NULL\n");
1.86      daniel   1057: #endif
1.1       veillard 1058:        return;
                   1059:     }
1.84      daniel   1060:     /* Check for ID removal -> leading to invalid references ! */
1.90      daniel   1061:     if ((cur->parent != NULL) && 
                   1062:         (xmlIsID(cur->parent->doc, cur->parent, cur)))
                   1063:         xmlRemoveID(cur->parent->doc, cur);
1.57      daniel   1064:     if (cur->name != NULL) xmlFree((char *) cur->name);
1.90      daniel   1065:     if (cur->children != NULL) xmlFreeNodeList(cur->children);
1.20      daniel   1066:     memset(cur, -1, sizeof(xmlAttr));
1.57      daniel   1067:     xmlFree(cur);
1.83      daniel   1068: }
                   1069: 
                   1070: /**
                   1071:  * xmlRemoveProp:
                   1072:  * @cur:  an attribute
                   1073:  *
                   1074:  * Unlink and free one attribute, all the content is freed too
                   1075:  * Note this doesn't work for namespace definition attributes
                   1076:  *
                   1077:  * Returns 0 if success and -1 in case of error.
                   1078:  */
                   1079: int
                   1080: xmlRemoveProp(xmlAttrPtr cur) {
                   1081:     xmlAttrPtr tmp;
                   1082:     if (cur == NULL) {
1.86      daniel   1083: #ifdef DEBUG_TREE
1.83      daniel   1084:         fprintf(stderr, "xmlRemoveProp : cur == NULL\n");
1.86      daniel   1085: #endif
1.83      daniel   1086:        return(-1);
                   1087:     }
1.90      daniel   1088:     if (cur->parent == NULL) {
1.94      daniel   1089: #ifdef DEBUG_TREE
1.90      daniel   1090:         fprintf(stderr, "xmlRemoveProp : cur->parent == NULL\n");
1.86      daniel   1091: #endif
1.83      daniel   1092:        return(-1);
                   1093:     }
1.90      daniel   1094:     tmp = cur->parent->properties;
1.83      daniel   1095:     if (tmp == cur) {
1.90      daniel   1096:         cur->parent->properties = cur->next;
1.83      daniel   1097:        xmlFreeProp(cur);
                   1098:        return(0);
                   1099:     }
                   1100:     while (tmp != NULL) {
                   1101:        if (tmp->next == cur) {
                   1102:            tmp->next = cur->next;
1.94      daniel   1103:            if (tmp->next != NULL)
                   1104:                tmp->next->prev = tmp;
1.83      daniel   1105:            xmlFreeProp(cur);
                   1106:            return(0);
                   1107:        }
                   1108:         tmp = tmp->next;
                   1109:     }
1.86      daniel   1110: #ifdef DEBUG_TREE
1.83      daniel   1111:     fprintf(stderr, "xmlRemoveProp : attribute not owned by its node\n");
1.86      daniel   1112: #endif
1.83      daniel   1113:     return(-1);
1.1       veillard 1114: }
                   1115: 
1.23      daniel   1116: /**
1.52      daniel   1117:  * xmlNewPI:
                   1118:  * @name:  the processing instruction name
                   1119:  * @content:  the PI content
                   1120:  *
                   1121:  * Creation of a processing instruction element.
                   1122:  * Returns a pointer to the new node object.
                   1123:  */
                   1124: xmlNodePtr
1.61      daniel   1125: xmlNewPI(const xmlChar *name, const xmlChar *content) {
1.52      daniel   1126:     xmlNodePtr cur;
                   1127: 
                   1128:     if (name == NULL) {
1.86      daniel   1129: #ifdef DEBUG_TREE
1.52      daniel   1130:         fprintf(stderr, "xmlNewPI : name == NULL\n");
1.86      daniel   1131: #endif
1.52      daniel   1132:        return(NULL);
                   1133:     }
                   1134: 
                   1135:     /*
                   1136:      * Allocate a new node and fill the fields.
                   1137:      */
1.57      daniel   1138:     cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
1.52      daniel   1139:     if (cur == NULL) {
                   1140:         fprintf(stderr, "xmlNewPI : malloc failed\n");
                   1141:        return(NULL);
                   1142:     }
1.90      daniel   1143:     memset(cur, 0, sizeof(xmlNode));
                   1144:     cur->type = XML_PI_NODE;
1.52      daniel   1145: 
                   1146:     cur->name = xmlStrdup(name);
1.70      daniel   1147:     if (content != NULL) {
                   1148: #ifndef XML_USE_BUFFER_CONTENT
1.52      daniel   1149:        cur->content = xmlStrdup(content);
1.70      daniel   1150: #else
                   1151:        cur->content = xmlBufferCreateSize(0);
                   1152:        xmlBufferSetAllocationScheme(cur->content,
                   1153:                                     xmlGetBufferAllocationScheme());
                   1154:        xmlBufferAdd(cur->content, content, -1);
                   1155: #endif
1.90      daniel   1156:     }
1.52      daniel   1157:     return(cur);
                   1158: }
                   1159: 
                   1160: /**
1.23      daniel   1161:  * xmlNewNode:
                   1162:  * @ns:  namespace if any
                   1163:  * @name:  the node name
                   1164:  *
                   1165:  * Creation of a new node element. @ns and @content are optionnal (NULL).
1.24      daniel   1166:  * If content is non NULL, a child list containing the TEXTs and
                   1167:  * ENTITY_REFs node will be created.
1.36      daniel   1168:  * Returns a pointer to the new node object.
1.1       veillard 1169:  */
1.28      daniel   1170: xmlNodePtr
1.61      daniel   1171: xmlNewNode(xmlNsPtr ns, const xmlChar *name) {
1.1       veillard 1172:     xmlNodePtr cur;
                   1173: 
                   1174:     if (name == NULL) {
1.86      daniel   1175: #ifdef DEBUG_TREE
1.1       veillard 1176:         fprintf(stderr, "xmlNewNode : name == NULL\n");
1.86      daniel   1177: #endif
1.1       veillard 1178:        return(NULL);
                   1179:     }
                   1180: 
                   1181:     /*
                   1182:      * Allocate a new node and fill the fields.
                   1183:      */
1.57      daniel   1184:     cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
1.1       veillard 1185:     if (cur == NULL) {
                   1186:         fprintf(stderr, "xmlNewNode : malloc failed\n");
                   1187:        return(NULL);
                   1188:     }
1.90      daniel   1189:     memset(cur, 0, sizeof(xmlNode));
1.23      daniel   1190:     cur->type = XML_ELEMENT_NODE;
1.90      daniel   1191:     
1.22      daniel   1192:     cur->name = xmlStrdup(name);
1.16      daniel   1193:     cur->ns = ns;
1.1       veillard 1194:     return(cur);
                   1195: }
                   1196: 
1.23      daniel   1197: /**
                   1198:  * xmlNewDocNode:
                   1199:  * @doc:  the document
                   1200:  * @ns:  namespace if any
                   1201:  * @name:  the node name
1.68      daniel   1202:  * @content:  the XML text content if any
1.23      daniel   1203:  *
                   1204:  * Creation of a new node element within a document. @ns and @content
                   1205:  * are optionnal (NULL).
1.68      daniel   1206:  * NOTE: @content is supposed to be a piece of XML CDATA, so it allow entities
                   1207:  *       references, but XML special chars need to be escaped first by using
                   1208:  *       xmlEncodeEntitiesReentrant(). Use xmlNewDocRawNode() if you don't
                   1209:  *       need entities support.
                   1210:  *
1.36      daniel   1211:  * Returns a pointer to the new node object.
1.23      daniel   1212:  */
1.28      daniel   1213: xmlNodePtr
                   1214: xmlNewDocNode(xmlDocPtr doc, xmlNsPtr ns,
1.68      daniel   1215:               const xmlChar *name, const xmlChar *content) {
1.23      daniel   1216:     xmlNodePtr cur;
                   1217: 
1.24      daniel   1218:     cur = xmlNewNode(ns, name);
                   1219:     if (cur != NULL) {
                   1220:         cur->doc = doc;
1.32      daniel   1221:        if (content != NULL) {
1.90      daniel   1222:            cur->children = xmlStringGetNodeList(doc, content);
1.34      daniel   1223:            UPDATE_LAST_CHILD(cur)
1.32      daniel   1224:        }
1.24      daniel   1225:     }
1.23      daniel   1226:     return(cur);
                   1227: }
                   1228: 
                   1229: 
                   1230: /**
1.68      daniel   1231:  * xmlNewDocRawNode:
                   1232:  * @doc:  the document
                   1233:  * @ns:  namespace if any
                   1234:  * @name:  the node name
                   1235:  * @content:  the text content if any
                   1236:  *
                   1237:  * Creation of a new node element within a document. @ns and @content
                   1238:  * are optionnal (NULL).
                   1239:  *
                   1240:  * Returns a pointer to the new node object.
                   1241:  */
                   1242: xmlNodePtr
                   1243: xmlNewDocRawNode(xmlDocPtr doc, xmlNsPtr ns,
                   1244:                  const xmlChar *name, const xmlChar *content) {
                   1245:     xmlNodePtr cur;
                   1246: 
                   1247:     cur = xmlNewNode(ns, name);
                   1248:     if (cur != NULL) {
                   1249:         cur->doc = doc;
                   1250:        if (content != NULL) {
1.90      daniel   1251:            cur->children = xmlNewDocText(doc, content);
1.68      daniel   1252:            UPDATE_LAST_CHILD(cur)
                   1253:        }
                   1254:     }
                   1255:     return(cur);
                   1256: }
                   1257: 
1.85      daniel   1258: /**
                   1259:  * xmlNewDocFragment:
                   1260:  * @doc:  the document owning the fragment
                   1261:  *
                   1262:  * Creation of a new Fragment node.
                   1263:  * Returns a pointer to the new node object.
                   1264:  */
                   1265: xmlNodePtr
                   1266: xmlNewDocFragment(xmlDocPtr doc) {
                   1267:     xmlNodePtr cur;
                   1268: 
                   1269:     /*
                   1270:      * Allocate a new DocumentFragment node and fill the fields.
                   1271:      */
                   1272:     cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
                   1273:     if (cur == NULL) {
                   1274:         fprintf(stderr, "xmlNewDocFragment : malloc failed\n");
                   1275:        return(NULL);
                   1276:     }
1.90      daniel   1277:     memset(cur, 0, sizeof(xmlNode));
                   1278:     cur->type = XML_DOCUMENT_FRAG_NODE;
1.85      daniel   1279: 
                   1280:     cur->doc = doc;
                   1281:     return(cur);
                   1282: }
1.68      daniel   1283: 
                   1284: /**
1.23      daniel   1285:  * xmlNewText:
                   1286:  * @content:  the text content
                   1287:  *
                   1288:  * Creation of a new text node.
1.36      daniel   1289:  * Returns a pointer to the new node object.
1.3       veillard 1290:  */
1.28      daniel   1291: xmlNodePtr
1.61      daniel   1292: xmlNewText(const xmlChar *content) {
1.3       veillard 1293:     xmlNodePtr cur;
                   1294: 
                   1295:     /*
                   1296:      * Allocate a new node and fill the fields.
                   1297:      */
1.57      daniel   1298:     cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
1.3       veillard 1299:     if (cur == NULL) {
1.19      daniel   1300:         fprintf(stderr, "xmlNewText : malloc failed\n");
1.3       veillard 1301:        return(NULL);
                   1302:     }
1.90      daniel   1303:     memset(cur, 0, sizeof(xmlNode));
                   1304:     cur->type = XML_TEXT_NODE;
1.3       veillard 1305: 
1.18      daniel   1306:     cur->name = xmlStrdup(xmlStringText);
1.70      daniel   1307:     if (content != NULL) {
                   1308: #ifndef XML_USE_BUFFER_CONTENT
1.7       veillard 1309:        cur->content = xmlStrdup(content);
1.70      daniel   1310: #else
                   1311:        cur->content = xmlBufferCreateSize(0);
                   1312:        xmlBufferSetAllocationScheme(cur->content,
                   1313:                                     xmlGetBufferAllocationScheme());
                   1314:        xmlBufferAdd(cur->content, content, -1);
                   1315: #endif
1.90      daniel   1316:     }
1.3       veillard 1317:     return(cur);
                   1318: }
                   1319: 
1.23      daniel   1320: /**
1.68      daniel   1321:  * xmlNewTextChild:
                   1322:  * @parent:  the parent node
                   1323:  * @ns:  a namespace if any
                   1324:  * @name:  the name of the child
                   1325:  * @content:  the text content of the child if any.
                   1326:  *
1.90      daniel   1327:  * Creation of a new child element, added at the end of @parent children list.
1.68      daniel   1328:  * @ns and @content parameters are optionnal (NULL). If content is non NULL,
                   1329:  * a child TEXT node will be created containing the string content.
                   1330:  *
                   1331:  * Returns a pointer to the new node object.
                   1332:  */
                   1333: xmlNodePtr
                   1334: xmlNewTextChild(xmlNodePtr parent, xmlNsPtr ns,
                   1335:             const xmlChar *name, const xmlChar *content) {
                   1336:     xmlNodePtr cur, prev;
                   1337: 
                   1338:     if (parent == NULL) {
1.86      daniel   1339: #ifdef DEBUG_TREE
1.68      daniel   1340:         fprintf(stderr, "xmlNewTextChild : parent == NULL\n");
1.86      daniel   1341: #endif
1.68      daniel   1342:        return(NULL);
                   1343:     }
                   1344: 
                   1345:     if (name == NULL) {
1.86      daniel   1346: #ifdef DEBUG_TREE
1.68      daniel   1347:         fprintf(stderr, "xmlNewTextChild : name == NULL\n");
1.86      daniel   1348: #endif
1.68      daniel   1349:        return(NULL);
                   1350:     }
                   1351: 
                   1352:     /*
                   1353:      * Allocate a new node
                   1354:      */
                   1355:     if (ns == NULL)
                   1356:        cur = xmlNewDocRawNode(parent->doc, parent->ns, name, content);
                   1357:     else
                   1358:        cur = xmlNewDocRawNode(parent->doc, ns, name, content);
                   1359:     if (cur == NULL) return(NULL);
                   1360: 
                   1361:     /*
1.90      daniel   1362:      * add the new element at the end of the children list.
1.68      daniel   1363:      */
                   1364:     cur->type = XML_ELEMENT_NODE;
                   1365:     cur->parent = parent;
                   1366:     cur->doc = parent->doc;
1.90      daniel   1367:     if (parent->children == NULL) {
                   1368:         parent->children = cur;
1.68      daniel   1369:        parent->last = cur;
                   1370:     } else {
                   1371:         prev = parent->last;
                   1372:        prev->next = cur;
                   1373:        cur->prev = prev;
                   1374:        parent->last = cur;
                   1375:     }
                   1376: 
                   1377:     return(cur);
                   1378: }
                   1379: 
                   1380: /**
1.88      daniel   1381:  * xmlNewCharRef:
                   1382:  * @doc: the document
                   1383:  * @name:  the char ref string, starting with # or "&# ... ;"
                   1384:  *
                   1385:  * Creation of a new character reference node.
                   1386:  * Returns a pointer to the new node object.
                   1387:  */
                   1388: xmlNodePtr
                   1389: xmlNewCharRef(xmlDocPtr doc, const xmlChar *name) {
                   1390:     xmlNodePtr cur;
                   1391: 
                   1392:     /*
                   1393:      * Allocate a new node and fill the fields.
                   1394:      */
                   1395:     cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
                   1396:     if (cur == NULL) {
                   1397:         fprintf(stderr, "xmlNewText : malloc failed\n");
                   1398:        return(NULL);
                   1399:     }
1.90      daniel   1400:     memset(cur, 0, sizeof(xmlNode));
                   1401:     cur->type = XML_ENTITY_REF_NODE;
1.88      daniel   1402: 
                   1403:     cur->doc = doc;
                   1404:     if (name[0] == '&') {
                   1405:         int len;
                   1406:         name++;
                   1407:        len = xmlStrlen(name);
                   1408:        if (name[len - 1] == ';')
                   1409:            cur->name = xmlStrndup(name, len - 1);
                   1410:        else
                   1411:            cur->name = xmlStrndup(name, len);
                   1412:     } else
                   1413:        cur->name = xmlStrdup(name);
                   1414:     return(cur);
                   1415: }
                   1416: 
                   1417: /**
1.23      daniel   1418:  * xmlNewReference:
                   1419:  * @doc: the document
                   1420:  * @name:  the reference name, or the reference string with & and ;
                   1421:  *
                   1422:  * Creation of a new reference node.
1.36      daniel   1423:  * Returns a pointer to the new node object.
1.23      daniel   1424:  */
1.28      daniel   1425: xmlNodePtr
1.61      daniel   1426: xmlNewReference(xmlDocPtr doc, const xmlChar *name) {
1.23      daniel   1427:     xmlNodePtr cur;
                   1428:     xmlEntityPtr ent;
                   1429: 
                   1430:     /*
                   1431:      * Allocate a new node and fill the fields.
                   1432:      */
1.57      daniel   1433:     cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
1.23      daniel   1434:     if (cur == NULL) {
                   1435:         fprintf(stderr, "xmlNewText : malloc failed\n");
                   1436:        return(NULL);
                   1437:     }
1.90      daniel   1438:     memset(cur, 0, sizeof(xmlNode));
                   1439:     cur->type = XML_ENTITY_REF_NODE;
1.23      daniel   1440: 
1.28      daniel   1441:     cur->doc = doc;
1.23      daniel   1442:     if (name[0] == '&') {
                   1443:         int len;
                   1444:         name++;
                   1445:        len = xmlStrlen(name);
                   1446:        if (name[len - 1] == ';')
                   1447:            cur->name = xmlStrndup(name, len - 1);
                   1448:        else
                   1449:            cur->name = xmlStrndup(name, len);
                   1450:     } else
                   1451:        cur->name = xmlStrdup(name);
                   1452: 
                   1453:     ent = xmlGetDocEntity(doc, cur->name);
1.70      daniel   1454:     if (ent != NULL) {
                   1455: #ifndef XML_USE_BUFFER_CONTENT
1.23      daniel   1456:        cur->content = ent->content;
1.70      daniel   1457: #else
                   1458:        /*
                   1459:         * CJN 11.18.99 this might be a problem, since the xmlBuffer gets
                   1460:         * a copy of this pointer.  Let's hope we don't manipulate it
                   1461:         * later 
                   1462:         */
                   1463:        cur->content = xmlBufferCreateSize(0);
                   1464:        xmlBufferSetAllocationScheme(cur->content,
                   1465:                                     xmlGetBufferAllocationScheme());
                   1466:        if (ent->content != NULL)
                   1467:            xmlBufferAdd(cur->content, ent->content, -1);
                   1468: #endif
1.99      daniel   1469:        cur->children = (xmlNodePtr) ent;
1.90      daniel   1470:     }
1.23      daniel   1471:     return(cur);
                   1472: }
                   1473: 
                   1474: /**
                   1475:  * xmlNewDocText:
                   1476:  * @doc: the document
                   1477:  * @content:  the text content
                   1478:  *
                   1479:  * Creation of a new text node within a document.
1.36      daniel   1480:  * Returns a pointer to the new node object.
1.23      daniel   1481:  */
1.28      daniel   1482: xmlNodePtr
1.61      daniel   1483: xmlNewDocText(xmlDocPtr doc, const xmlChar *content) {
1.23      daniel   1484:     xmlNodePtr cur;
                   1485: 
                   1486:     cur = xmlNewText(content);
                   1487:     if (cur != NULL) cur->doc = doc;
                   1488:     return(cur);
                   1489: }
                   1490: 
                   1491: /**
                   1492:  * xmlNewTextLen:
                   1493:  * @content:  the text content
                   1494:  * @len:  the text len.
                   1495:  *
                   1496:  * Creation of a new text node with an extra parameter for the content's lenght
1.36      daniel   1497:  * Returns a pointer to the new node object.
1.21      daniel   1498:  */
1.28      daniel   1499: xmlNodePtr
1.61      daniel   1500: xmlNewTextLen(const xmlChar *content, int len) {
1.21      daniel   1501:     xmlNodePtr cur;
                   1502: 
                   1503:     /*
                   1504:      * Allocate a new node and fill the fields.
                   1505:      */
1.57      daniel   1506:     cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
1.21      daniel   1507:     if (cur == NULL) {
                   1508:         fprintf(stderr, "xmlNewText : malloc failed\n");
                   1509:        return(NULL);
                   1510:     }
1.90      daniel   1511:     memset(cur, 0, sizeof(xmlNode));
                   1512:     cur->type = XML_TEXT_NODE;
1.21      daniel   1513: 
                   1514:     cur->name = xmlStrdup(xmlStringText);
1.70      daniel   1515:     if (content != NULL) {
                   1516: #ifndef XML_USE_BUFFER_CONTENT
1.21      daniel   1517:        cur->content = xmlStrndup(content, len);
1.70      daniel   1518: #else
                   1519:        cur->content = xmlBufferCreateSize(len);
                   1520:        xmlBufferSetAllocationScheme(cur->content,
                   1521:                                     xmlGetBufferAllocationScheme());
                   1522:        xmlBufferAdd(cur->content, content, len);
                   1523: #endif
1.90      daniel   1524:     }
1.21      daniel   1525:     return(cur);
                   1526: }
                   1527: 
1.23      daniel   1528: /**
                   1529:  * xmlNewDocTextLen:
                   1530:  * @doc: the document
                   1531:  * @content:  the text content
                   1532:  * @len:  the text len.
                   1533:  *
                   1534:  * Creation of a new text node with an extra content lenght parameter. The
                   1535:  * text node pertain to a given document.
1.36      daniel   1536:  * Returns a pointer to the new node object.
1.23      daniel   1537:  */
1.28      daniel   1538: xmlNodePtr
1.61      daniel   1539: xmlNewDocTextLen(xmlDocPtr doc, const xmlChar *content, int len) {
1.23      daniel   1540:     xmlNodePtr cur;
                   1541: 
                   1542:     cur = xmlNewTextLen(content, len);
                   1543:     if (cur != NULL) cur->doc = doc;
                   1544:     return(cur);
                   1545: }
                   1546: 
                   1547: /**
                   1548:  * xmlNewComment:
                   1549:  * @content:  the comment content
                   1550:  *
                   1551:  * Creation of a new node containing a comment.
1.36      daniel   1552:  * Returns a pointer to the new node object.
1.14      daniel   1553:  */
1.28      daniel   1554: xmlNodePtr
1.61      daniel   1555: xmlNewComment(const xmlChar *content) {
1.14      daniel   1556:     xmlNodePtr cur;
                   1557: 
                   1558:     /*
                   1559:      * Allocate a new node and fill the fields.
                   1560:      */
1.57      daniel   1561:     cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
1.14      daniel   1562:     if (cur == NULL) {
1.19      daniel   1563:         fprintf(stderr, "xmlNewComment : malloc failed\n");
1.14      daniel   1564:        return(NULL);
                   1565:     }
1.90      daniel   1566:     memset(cur, 0, sizeof(xmlNode));
                   1567:     cur->type = XML_COMMENT_NODE;
1.14      daniel   1568: 
1.90      daniel   1569:     cur->name = xmlStrdup(xmlStringComment);
1.70      daniel   1570:     if (content != NULL) {
                   1571: #ifndef XML_USE_BUFFER_CONTENT
1.14      daniel   1572:        cur->content = xmlStrdup(content);
1.70      daniel   1573: #else
                   1574:        cur->content = xmlBufferCreateSize(0);
                   1575:        xmlBufferSetAllocationScheme(cur->content,
                   1576:                                     xmlGetBufferAllocationScheme());
                   1577:        xmlBufferAdd(cur->content, content, -1);
                   1578: #endif
1.90      daniel   1579:     }
1.14      daniel   1580:     return(cur);
                   1581: }
                   1582: 
1.23      daniel   1583: /**
1.50      daniel   1584:  * xmlNewCDataBlock:
                   1585:  * @doc:  the document
                   1586:  * @content:  the CData block content content
                   1587:  * @len:  the length of the block
                   1588:  *
                   1589:  * Creation of a new node containing a CData block.
                   1590:  * Returns a pointer to the new node object.
                   1591:  */
                   1592: xmlNodePtr
1.61      daniel   1593: xmlNewCDataBlock(xmlDocPtr doc, const xmlChar *content, int len) {
1.50      daniel   1594:     xmlNodePtr cur;
                   1595: 
                   1596:     /*
                   1597:      * Allocate a new node and fill the fields.
                   1598:      */
1.57      daniel   1599:     cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
1.50      daniel   1600:     if (cur == NULL) {
                   1601:         fprintf(stderr, "xmlNewCDataBlock : malloc failed\n");
                   1602:        return(NULL);
                   1603:     }
1.90      daniel   1604:     memset(cur, 0, sizeof(xmlNode));
                   1605:     cur->type = XML_CDATA_SECTION_NODE;
1.50      daniel   1606: 
1.70      daniel   1607:     if (content != NULL) {
                   1608: #ifndef XML_USE_BUFFER_CONTENT
1.50      daniel   1609:        cur->content = xmlStrndup(content, len);
1.70      daniel   1610: #else
                   1611:        cur->content = xmlBufferCreateSize(len);
                   1612:        xmlBufferSetAllocationScheme(cur->content,
                   1613:                                     xmlGetBufferAllocationScheme());
                   1614:        xmlBufferAdd(cur->content, content, len);
                   1615: #endif
1.90      daniel   1616:     }
1.50      daniel   1617:     return(cur);
                   1618: }
                   1619: 
                   1620: /**
1.36      daniel   1621:  * xmlNewDocComment:
1.23      daniel   1622:  * @doc:  the document
                   1623:  * @content:  the comment content
                   1624:  *
                   1625:  * Creation of a new node containing a commentwithin a document.
1.36      daniel   1626:  * Returns a pointer to the new node object.
1.23      daniel   1627:  */
1.28      daniel   1628: xmlNodePtr
1.61      daniel   1629: xmlNewDocComment(xmlDocPtr doc, const xmlChar *content) {
1.23      daniel   1630:     xmlNodePtr cur;
                   1631: 
                   1632:     cur = xmlNewComment(content);
                   1633:     if (cur != NULL) cur->doc = doc;
                   1634:     return(cur);
                   1635: }
                   1636: 
1.68      daniel   1637: 
1.23      daniel   1638: /**
                   1639:  * xmlNewChild:
                   1640:  * @parent:  the parent node
                   1641:  * @ns:  a namespace if any
                   1642:  * @name:  the name of the child
1.68      daniel   1643:  * @content:  the XML content of the child if any.
1.23      daniel   1644:  *
1.90      daniel   1645:  * Creation of a new child element, added at the end of @parent children list.
1.24      daniel   1646:  * @ns and @content parameters are optionnal (NULL). If content is non NULL,
                   1647:  * a child list containing the TEXTs and ENTITY_REFs node will be created.
1.68      daniel   1648:  * NOTE: @content is supposed to be a piece of XML CDATA, so it allow entities
                   1649:  *       references, but XML special chars need to be escaped first by using
                   1650:  *       xmlEncodeEntitiesReentrant(). Use xmlNewTextChild() if entities
                   1651:  *       support is not needed.
                   1652:  *
1.36      daniel   1653:  * Returns a pointer to the new node object.
1.1       veillard 1654:  */
1.28      daniel   1655: xmlNodePtr
                   1656: xmlNewChild(xmlNodePtr parent, xmlNsPtr ns,
1.68      daniel   1657:             const xmlChar *name, const xmlChar *content) {
1.1       veillard 1658:     xmlNodePtr cur, prev;
                   1659: 
                   1660:     if (parent == NULL) {
1.86      daniel   1661: #ifdef DEBUG_TREE
1.1       veillard 1662:         fprintf(stderr, "xmlNewChild : parent == NULL\n");
1.86      daniel   1663: #endif
1.1       veillard 1664:        return(NULL);
                   1665:     }
                   1666: 
                   1667:     if (name == NULL) {
1.86      daniel   1668: #ifdef DEBUG_TREE
1.1       veillard 1669:         fprintf(stderr, "xmlNewChild : name == NULL\n");
1.86      daniel   1670: #endif
1.1       veillard 1671:        return(NULL);
                   1672:     }
                   1673: 
                   1674:     /*
                   1675:      * Allocate a new node
                   1676:      */
1.16      daniel   1677:     if (ns == NULL)
1.24      daniel   1678:        cur = xmlNewDocNode(parent->doc, parent->ns, name, content);
1.1       veillard 1679:     else
1.24      daniel   1680:        cur = xmlNewDocNode(parent->doc, ns, name, content);
1.1       veillard 1681:     if (cur == NULL) return(NULL);
                   1682: 
                   1683:     /*
1.90      daniel   1684:      * add the new element at the end of the children list.
1.1       veillard 1685:      */
1.25      daniel   1686:     cur->type = XML_ELEMENT_NODE;
1.1       veillard 1687:     cur->parent = parent;
1.23      daniel   1688:     cur->doc = parent->doc;
1.90      daniel   1689:     if (parent->children == NULL) {
                   1690:         parent->children = cur;
1.32      daniel   1691:        parent->last = cur;
1.1       veillard 1692:     } else {
1.32      daniel   1693:         prev = parent->last;
1.1       veillard 1694:        prev->next = cur;
1.23      daniel   1695:        cur->prev = prev;
1.32      daniel   1696:        parent->last = cur;
1.1       veillard 1697:     }
                   1698: 
                   1699:     return(cur);
                   1700: }
                   1701: 
1.23      daniel   1702: /**
1.78      daniel   1703:  * xmlAddNextSibling:
                   1704:  * @cur:  the child node
                   1705:  * @elem:  the new node
                   1706:  *
                   1707:  * Add a new element @elem as the next siblings of @cur
                   1708:  * If the new element was already inserted in a document it is
                   1709:  * first unlinked from its existing context.
                   1710:  *
                   1711:  * Returns the new element or NULL in case of error.
                   1712:  */
                   1713: xmlNodePtr
                   1714: xmlAddNextSibling(xmlNodePtr cur, xmlNodePtr elem) {
                   1715:     if (cur == NULL) {
1.86      daniel   1716: #ifdef DEBUG_TREE
1.78      daniel   1717:         fprintf(stderr, "xmlAddNextSibling : cur == NULL\n");
1.86      daniel   1718: #endif
1.78      daniel   1719:        return(NULL);
                   1720:     }
                   1721:     if (elem == NULL) {
1.86      daniel   1722: #ifdef DEBUG_TREE
1.78      daniel   1723:         fprintf(stderr, "xmlAddNextSibling : elem == NULL\n");
1.86      daniel   1724: #endif
1.78      daniel   1725:        return(NULL);
                   1726:     }
                   1727: 
                   1728:     xmlUnlinkNode(elem);
                   1729:     elem->doc = cur->doc;
                   1730:     elem->parent = cur->parent;
1.102     daniel   1731:     elem->prev = cur;
                   1732:     elem->next = cur->next;
                   1733:     cur->next = elem;
                   1734:     if (elem->next != NULL)
                   1735:        elem->next->prev = elem;
                   1736:     if ((elem->parent != NULL) && (elem->parent->last == cur))
                   1737:        elem->parent->last = elem;
1.78      daniel   1738:     return(elem);
                   1739: }
                   1740: 
                   1741: /**
                   1742:  * xmlAddPrevSibling:
                   1743:  * @cur:  the child node
                   1744:  * @elem:  the new node
                   1745:  *
                   1746:  * Add a new element @elem as the previous siblings of @cur
                   1747:  * If the new element was already inserted in a document it is
                   1748:  * first unlinked from its existing context.
                   1749:  *
                   1750:  * Returns the new element or NULL in case of error.
                   1751:  */
                   1752: xmlNodePtr
                   1753: xmlAddPrevSibling(xmlNodePtr cur, xmlNodePtr elem) {
                   1754:     if (cur == NULL) {
1.86      daniel   1755: #ifdef DEBUG_TREE
1.78      daniel   1756:         fprintf(stderr, "xmlAddPrevSibling : cur == NULL\n");
1.86      daniel   1757: #endif
1.78      daniel   1758:        return(NULL);
                   1759:     }
                   1760:     if (elem == NULL) {
1.86      daniel   1761: #ifdef DEBUG_TREE
1.78      daniel   1762:         fprintf(stderr, "xmlAddPrevSibling : elem == NULL\n");
1.86      daniel   1763: #endif
1.78      daniel   1764:        return(NULL);
                   1765:     }
                   1766: 
                   1767:     xmlUnlinkNode(elem);
                   1768:     elem->doc = cur->doc;
                   1769:     elem->parent = cur->parent;
1.102     daniel   1770:     elem->next = cur;
                   1771:     elem->prev = cur->prev;
                   1772:     cur->prev = elem;
                   1773:     if (elem->prev != NULL)
                   1774:        elem->prev->next = elem;
                   1775:     if ((elem->parent != NULL) && (elem->parent->children == cur))
                   1776:        elem->parent->children = elem;
1.78      daniel   1777:     return(elem);
                   1778: }
                   1779: 
                   1780: /**
1.52      daniel   1781:  * xmlAddSibling:
                   1782:  * @cur:  the child node
                   1783:  * @elem:  the new node
                   1784:  *
1.78      daniel   1785:  * Add a new element @elem to the list of siblings of @cur
                   1786:  * If the new element was already inserted in a document it is
                   1787:  * first unlinked from its existing context.
                   1788:  *
                   1789:  * Returns the new element or NULL in case of error.
1.52      daniel   1790:  */
                   1791: xmlNodePtr
                   1792: xmlAddSibling(xmlNodePtr cur, xmlNodePtr elem) {
                   1793:     xmlNodePtr parent;
                   1794: 
                   1795:     if (cur == NULL) {
1.86      daniel   1796: #ifdef DEBUG_TREE
1.52      daniel   1797:         fprintf(stderr, "xmlAddSibling : cur == NULL\n");
1.86      daniel   1798: #endif
1.52      daniel   1799:        return(NULL);
                   1800:     }
                   1801: 
                   1802:     if (elem == NULL) {
1.86      daniel   1803: #ifdef DEBUG_TREE
1.52      daniel   1804:         fprintf(stderr, "xmlAddSibling : elem == NULL\n");
1.86      daniel   1805: #endif
1.52      daniel   1806:        return(NULL);
                   1807:     }
                   1808: 
1.78      daniel   1809:     /*
                   1810:      * Constant time is we can rely on the ->parent->last to find
                   1811:      * the last sibling.
                   1812:      */
                   1813:     if ((cur->parent != NULL) && 
1.90      daniel   1814:        (cur->parent->children != NULL) &&
1.78      daniel   1815:        (cur->parent->last != NULL) &&
                   1816:        (cur->parent->last->next == NULL)) {
                   1817:        cur = cur->parent->last;
                   1818:     } else {
                   1819:        while (cur->next != NULL) cur = cur->next;
1.52      daniel   1820:     }
                   1821: 
1.78      daniel   1822:     xmlUnlinkNode(elem);
1.52      daniel   1823:     if (elem->doc == NULL)
                   1824:        elem->doc = cur->doc; /* the parent may not be linked to a doc ! */
                   1825: 
                   1826:     parent = cur->parent;
                   1827:     elem->prev = cur;
                   1828:     elem->next = NULL;
                   1829:     elem->parent = parent;
                   1830:     cur->next = elem;
                   1831:     if (parent != NULL)
                   1832:        parent->last = elem;
                   1833: 
                   1834:     return(elem);
                   1835: }
                   1836: 
                   1837: /**
1.23      daniel   1838:  * xmlAddChild:
                   1839:  * @parent:  the parent node
                   1840:  * @cur:  the child node
                   1841:  *
                   1842:  * Add a new child element, to @parent, at the end of the child list.
1.36      daniel   1843:  * Returns the child or NULL in case of error.
1.2       veillard 1844:  */
1.28      daniel   1845: xmlNodePtr
                   1846: xmlAddChild(xmlNodePtr parent, xmlNodePtr cur) {
1.2       veillard 1847:     xmlNodePtr prev;
                   1848: 
                   1849:     if (parent == NULL) {
1.86      daniel   1850: #ifdef DEBUG_TREE
1.73      daniel   1851:         fprintf(stderr, "xmlAddChild : parent == NULL\n");
1.86      daniel   1852: #endif
1.2       veillard 1853:        return(NULL);
                   1854:     }
                   1855: 
                   1856:     if (cur == NULL) {
1.86      daniel   1857: #ifdef DEBUG_TREE
1.73      daniel   1858:         fprintf(stderr, "xmlAddChild : child == NULL\n");
1.86      daniel   1859: #endif
1.2       veillard 1860:        return(NULL);
                   1861:     }
                   1862: 
1.23      daniel   1863:     if ((cur->doc != NULL) && (parent->doc != NULL) &&
                   1864:         (cur->doc != parent->doc)) {
1.86      daniel   1865: #ifdef DEBUG_TREE
1.23      daniel   1866:        fprintf(stderr, "Elements moved to a different document\n");
1.86      daniel   1867: #endif
1.23      daniel   1868:     }
                   1869: 
1.2       veillard 1870:     /*
1.90      daniel   1871:      * add the new element at the end of the children list.
1.2       veillard 1872:      */
                   1873:     cur->parent = parent;
1.23      daniel   1874:     cur->doc = parent->doc; /* the parent may not be linked to a doc ! */
1.32      daniel   1875: 
1.24      daniel   1876:     /*
                   1877:      * Handle the case where parent->content != NULL, in that case it will
                   1878:      * create a intermediate TEXT node.
                   1879:      */
1.93      daniel   1880:     if (((parent->type == XML_ELEMENT_NODE) || (parent->type == XML_TEXT_NODE)) &&
                   1881:        (parent->content != NULL)) {
1.24      daniel   1882:         xmlNodePtr text;
                   1883:        
1.70      daniel   1884: #ifndef XML_USE_BUFFER_CONTENT
1.24      daniel   1885:        text = xmlNewDocText(parent->doc, parent->content);
1.70      daniel   1886: #else
                   1887:        text = xmlNewDocText(parent->doc, xmlBufferContent(parent->content));
                   1888: #endif
1.24      daniel   1889:        if (text != NULL) {
1.90      daniel   1890:            text->next = parent->children;
1.24      daniel   1891:            if (text->next != NULL)
                   1892:                text->next->prev = text;
1.90      daniel   1893:            parent->children = text;
1.34      daniel   1894:            UPDATE_LAST_CHILD(parent)
1.70      daniel   1895: #ifndef XML_USE_BUFFER_CONTENT
1.57      daniel   1896:            xmlFree(parent->content);
1.70      daniel   1897: #else
                   1898:            xmlBufferFree(parent->content);
                   1899: #endif
1.24      daniel   1900:            parent->content = NULL;
                   1901:        }
                   1902:     }
1.90      daniel   1903:     if (parent->children == NULL) {
                   1904:         parent->children = cur;
1.32      daniel   1905:        parent->last = cur;
1.2       veillard 1906:     } else {
1.32      daniel   1907:         prev = parent->last;
1.2       veillard 1908:        prev->next = cur;
1.23      daniel   1909:        cur->prev = prev;
1.32      daniel   1910:        parent->last = cur;
1.2       veillard 1911:     }
                   1912: 
                   1913:     return(cur);
                   1914: }
                   1915: 
1.23      daniel   1916: /**
                   1917:  * xmlGetLastChild:
                   1918:  * @parent:  the parent node
                   1919:  *
                   1920:  * Search the last child of a node.
1.36      daniel   1921:  * Returns the last child or NULL if none.
1.21      daniel   1922:  */
1.28      daniel   1923: xmlNodePtr
                   1924: xmlGetLastChild(xmlNodePtr parent) {
1.21      daniel   1925:     if (parent == NULL) {
1.86      daniel   1926: #ifdef DEBUG_TREE
1.21      daniel   1927:         fprintf(stderr, "xmlGetLastChild : parent == NULL\n");
1.86      daniel   1928: #endif
1.21      daniel   1929:        return(NULL);
                   1930:     }
1.32      daniel   1931:     return(parent->last);
1.21      daniel   1932: }
                   1933: 
1.23      daniel   1934: /**
                   1935:  * xmlFreeNodeList:
                   1936:  * @cur:  the first node in the list
                   1937:  *
                   1938:  * Free a node and all its siblings, this is a recursive behaviour, all
1.90      daniel   1939:  * the children are freed too.
1.1       veillard 1940:  */
1.28      daniel   1941: void
                   1942: xmlFreeNodeList(xmlNodePtr cur) {
1.1       veillard 1943:     xmlNodePtr next;
                   1944:     if (cur == NULL) {
1.86      daniel   1945: #ifdef DEBUG_TREE
1.1       veillard 1946:         fprintf(stderr, "xmlFreeNodeList : node == NULL\n");
1.86      daniel   1947: #endif
1.1       veillard 1948:        return;
                   1949:     }
                   1950:     while (cur != NULL) {
                   1951:         next = cur->next;
                   1952:         xmlFreeNode(cur);
                   1953:        cur = next;
                   1954:     }
                   1955: }
                   1956: 
1.23      daniel   1957: /**
                   1958:  * xmlFreeNode:
                   1959:  * @cur:  the node
                   1960:  *
1.90      daniel   1961:  * Free a node, this is a recursive behaviour, all the children are freed too.
1.97      daniel   1962:  * This doesn't unlink the child from the list, use xmlUnlinkNode() first.
1.1       veillard 1963:  */
1.28      daniel   1964: void
                   1965: xmlFreeNode(xmlNodePtr cur) {
1.1       veillard 1966:     if (cur == NULL) {
1.86      daniel   1967: #ifdef DEBUG_TREE
1.1       veillard 1968:         fprintf(stderr, "xmlFreeNode : node == NULL\n");
1.86      daniel   1969: #endif
1.1       veillard 1970:        return;
                   1971:     }
1.92      daniel   1972:     if (cur->type == XML_DTD_NODE)
                   1973:        return;
1.23      daniel   1974:     cur->doc = NULL;
                   1975:     cur->parent = NULL;
                   1976:     cur->next = NULL;
                   1977:     cur->prev = NULL;
1.99      daniel   1978:     if ((cur->children != NULL) &&
                   1979:        (cur->type != XML_ENTITY_REF_NODE))
                   1980:        xmlFreeNodeList(cur->children);
1.1       veillard 1981:     if (cur->properties != NULL) xmlFreePropList(cur->properties);
1.23      daniel   1982:     if (cur->type != XML_ENTITY_REF_NODE)
1.70      daniel   1983: #ifndef XML_USE_BUFFER_CONTENT
1.57      daniel   1984:        if (cur->content != NULL) xmlFree(cur->content);
1.70      daniel   1985: #else
                   1986:        if (cur->content != NULL) xmlBufferFree(cur->content);
                   1987: #endif
1.57      daniel   1988:     if (cur->name != NULL) xmlFree((char *) cur->name);
1.19      daniel   1989:     if (cur->nsDef != NULL) xmlFreeNsList(cur->nsDef);
1.1       veillard 1990:     memset(cur, -1, sizeof(xmlNode));
1.57      daniel   1991:     xmlFree(cur);
1.1       veillard 1992: }
                   1993: 
1.28      daniel   1994: /**
                   1995:  * xmlUnlinkNode:
                   1996:  * @cur:  the node
                   1997:  *
                   1998:  * Unlink a node from it's current context, the node is not freed
                   1999:  */
                   2000: void
                   2001: xmlUnlinkNode(xmlNodePtr cur) {
                   2002:     if (cur == NULL) {
1.86      daniel   2003: #ifdef DEBUG_TREE
1.28      daniel   2004:         fprintf(stderr, "xmlUnlinkNode : node == NULL\n");
1.86      daniel   2005: #endif
1.28      daniel   2006:        return;
                   2007:     }
1.90      daniel   2008:     if ((cur->parent != NULL) && (cur->parent->children == cur))
                   2009:         cur->parent->children = cur->next;
1.32      daniel   2010:     if ((cur->parent != NULL) && (cur->parent->last == cur))
                   2011:         cur->parent->last = cur->prev;
1.28      daniel   2012:     if (cur->next != NULL)
                   2013:         cur->next->prev = cur->prev;
                   2014:     if (cur->prev != NULL)
                   2015:         cur->prev->next = cur->next;
                   2016:     cur->next = cur->prev = NULL;
                   2017:     cur->parent = NULL;
                   2018: }
                   2019: 
1.78      daniel   2020: /**
                   2021:  * xmlReplaceNode:
                   2022:  * @old:  the old node
                   2023:  * @cur:  the node
                   2024:  *
                   2025:  * Unlink the old node from it's current context, prune the new one
                   2026:  * at the same place. If cur was already inserted in a document it is
                   2027:  * first unlinked from its existing context.
                   2028:  *
                   2029:  * Returns the old node
                   2030:  */
                   2031: xmlNodePtr
                   2032: xmlReplaceNode(xmlNodePtr old, xmlNodePtr cur) {
                   2033:     if (old == NULL) {
1.86      daniel   2034: #ifdef DEBUG_TREE
1.78      daniel   2035:         fprintf(stderr, "xmlReplaceNode : old == NULL\n");
1.86      daniel   2036: #endif
1.78      daniel   2037:        return(NULL);
                   2038:     }
                   2039:     if (cur == NULL) {
                   2040:        xmlUnlinkNode(old);
                   2041:        return(old);
                   2042:     }
                   2043:     xmlUnlinkNode(cur);
                   2044:     cur->doc = old->doc;
                   2045:     cur->parent = old->parent;
                   2046:     cur->next = old->next;
                   2047:     if (cur->next != NULL)
                   2048:        cur->next->prev = cur;
                   2049:     cur->prev = old->prev;
                   2050:     if (cur->prev != NULL)
                   2051:        cur->prev->next = cur;
                   2052:     if (cur->parent != NULL) {
1.90      daniel   2053:        if (cur->parent->children == old)
                   2054:            cur->parent->children = cur;
1.78      daniel   2055:        if (cur->parent->last == old)
                   2056:            cur->parent->last = cur;
                   2057:     }
                   2058:     old->next = old->prev = NULL;
                   2059:     old->parent = NULL;
                   2060:     return(old);
                   2061: }
                   2062: 
1.1       veillard 2063: /************************************************************************
                   2064:  *                                                                     *
1.31      daniel   2065:  *             Copy operations                                         *
                   2066:  *                                                                     *
                   2067:  ************************************************************************/
                   2068:  
                   2069: /**
                   2070:  * xmlCopyNamespace:
                   2071:  * @cur:  the namespace
                   2072:  *
                   2073:  * Do a copy of the namespace.
                   2074:  *
                   2075:  * Returns: a new xmlNsPtr, or NULL in case of error.
                   2076:  */
                   2077: xmlNsPtr
                   2078: xmlCopyNamespace(xmlNsPtr cur) {
                   2079:     xmlNsPtr ret;
                   2080: 
                   2081:     if (cur == NULL) return(NULL);
                   2082:     switch (cur->type) {
                   2083:         case XML_GLOBAL_NAMESPACE:
                   2084:            ret = xmlNewGlobalNs(NULL, cur->href, cur->prefix);
                   2085:            break;
                   2086:        case XML_LOCAL_NAMESPACE:
                   2087:            ret = xmlNewNs(NULL, cur->href, cur->prefix);
                   2088:            break;
                   2089:        default:
1.86      daniel   2090: #ifdef DEBUG_TREE
1.31      daniel   2091:            fprintf(stderr, "xmlCopyNamespace: unknown type %d\n", cur->type);
1.86      daniel   2092: #endif
1.31      daniel   2093:            return(NULL);
                   2094:     }
                   2095:     return(ret);
                   2096: }
                   2097: 
                   2098: /**
                   2099:  * xmlCopyNamespaceList:
                   2100:  * @cur:  the first namespace
                   2101:  *
                   2102:  * Do a copy of an namespace list.
                   2103:  *
                   2104:  * Returns: a new xmlNsPtr, or NULL in case of error.
                   2105:  */
                   2106: xmlNsPtr
                   2107: xmlCopyNamespaceList(xmlNsPtr cur) {
                   2108:     xmlNsPtr ret = NULL;
                   2109:     xmlNsPtr p = NULL,q;
                   2110: 
                   2111:     while (cur != NULL) {
                   2112:         q = xmlCopyNamespace(cur);
                   2113:        if (p == NULL) {
                   2114:            ret = p = q;
                   2115:        } else {
                   2116:            p->next = q;
                   2117:            p = q;
                   2118:        }
                   2119:        cur = cur->next;
                   2120:     }
                   2121:     return(ret);
                   2122: }
                   2123: 
                   2124: /**
                   2125:  * xmlCopyProp:
1.56      daniel   2126:  * @target:  the element where the attribute will be grafted
1.31      daniel   2127:  * @cur:  the attribute
                   2128:  *
                   2129:  * Do a copy of the attribute.
                   2130:  *
                   2131:  * Returns: a new xmlAttrPtr, or NULL in case of error.
                   2132:  */
                   2133: xmlAttrPtr
1.56      daniel   2134: xmlCopyProp(xmlNodePtr target, xmlAttrPtr cur) {
1.31      daniel   2135:     xmlAttrPtr ret;
                   2136: 
                   2137:     if (cur == NULL) return(NULL);
1.94      daniel   2138:     if (cur->parent != NULL)
                   2139:        ret = xmlNewDocProp(cur->parent->doc, cur->name, NULL);
                   2140:     else if (cur->children != NULL)
1.90      daniel   2141:        ret = xmlNewDocProp(cur->children->doc, cur->name, NULL);
1.31      daniel   2142:     else
                   2143:        ret = xmlNewDocProp(NULL, cur->name, NULL);
                   2144:     if (ret == NULL) return(NULL);
1.94      daniel   2145:     ret->parent = target;
1.56      daniel   2146:     
                   2147:     if ((cur->ns != NULL) && (target != NULL)) {
                   2148:         xmlNsPtr ns;
                   2149: 
                   2150:        ns = xmlSearchNs(target->doc, target, cur->ns->prefix);
                   2151:        ret->ns = ns;
                   2152:     } else
                   2153:         ret->ns = NULL;
                   2154: 
1.90      daniel   2155:     if (cur->children != NULL)
                   2156:        ret->children = xmlCopyNodeList(cur->children);
1.31      daniel   2157:     return(ret);
                   2158: }
                   2159: 
                   2160: /**
                   2161:  * xmlCopyPropList:
1.56      daniel   2162:  * @target:  the element where the attributes will be grafted
1.31      daniel   2163:  * @cur:  the first attribute
                   2164:  *
                   2165:  * Do a copy of an attribute list.
                   2166:  *
                   2167:  * Returns: a new xmlAttrPtr, or NULL in case of error.
                   2168:  */
                   2169: xmlAttrPtr
1.56      daniel   2170: xmlCopyPropList(xmlNodePtr target, xmlAttrPtr cur) {
1.31      daniel   2171:     xmlAttrPtr ret = NULL;
                   2172:     xmlAttrPtr p = NULL,q;
                   2173: 
                   2174:     while (cur != NULL) {
1.56      daniel   2175:         q = xmlCopyProp(target, cur);
1.31      daniel   2176:        if (p == NULL) {
                   2177:            ret = p = q;
                   2178:        } else {
                   2179:            p->next = q;
1.94      daniel   2180:            q->prev = p;
1.31      daniel   2181:            p = q;
                   2182:        }
                   2183:        cur = cur->next;
                   2184:     }
                   2185:     return(ret);
                   2186: }
                   2187: 
                   2188: /*
1.68      daniel   2189:  * NOTE abeut the CopyNode operations !
1.31      daniel   2190:  *
                   2191:  * They are splitted into external and internal parts for one
                   2192:  * tricky reason: namespaces. Doing a direct copy of a node
                   2193:  * say RPM:Copyright without changing the namespace pointer to
                   2194:  * something else can produce stale links. One way to do it is
                   2195:  * to keep a reference counter but this doesn't work as soon
                   2196:  * as one move the element or the subtree out of the scope of
                   2197:  * the existing namespace. The actual solution seems to add
                   2198:  * a copy of the namespace at the top of the copied tree if
                   2199:  * not available in the subtree.
                   2200:  * Hence two functions, the public front-end call the inner ones
                   2201:  */
                   2202: 
                   2203: static xmlNodePtr
                   2204: xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent);
                   2205: 
                   2206: static xmlNodePtr
                   2207: xmlStaticCopyNode(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent,
                   2208:                   int recursive) {
                   2209:     xmlNodePtr ret;
                   2210: 
                   2211:     if (node == NULL) return(NULL);
                   2212:     /*
                   2213:      * Allocate a new node and fill the fields.
                   2214:      */
1.57      daniel   2215:     ret = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
1.31      daniel   2216:     if (ret == NULL) {
                   2217:         fprintf(stderr, "xmlStaticCopyNode : malloc failed\n");
                   2218:        return(NULL);
                   2219:     }
1.90      daniel   2220:     memset(ret, 0, sizeof(xmlNode));
                   2221:     ret->type = node->type;
1.31      daniel   2222: 
                   2223:     ret->doc = doc;
                   2224:     ret->parent = parent; 
                   2225:     if (node->name != NULL)
                   2226:        ret->name = xmlStrdup(node->name);
1.70      daniel   2227:     if ((node->content != NULL) && (node->type != XML_ENTITY_REF_NODE)) {
                   2228: #ifndef XML_USE_BUFFER_CONTENT
1.31      daniel   2229:        ret->content = xmlStrdup(node->content);
1.70      daniel   2230: #else
                   2231:        ret->content = xmlBufferCreateSize(xmlBufferLength(node->content));
                   2232:        xmlBufferSetAllocationScheme(ret->content,
                   2233:                                     xmlGetBufferAllocationScheme());
                   2234:        xmlBufferAdd(ret->content,
                   2235:                     xmlBufferContent(node->content),
                   2236:                     xmlBufferLength(node->content));
                   2237: #endif
1.90      daniel   2238:     }
1.31      daniel   2239:     if (parent != NULL)
                   2240:         xmlAddChild(parent, ret);
                   2241:     
                   2242:     if (!recursive) return(ret);
                   2243:     if (node->nsDef != NULL)
                   2244:         ret->nsDef = xmlCopyNamespaceList(node->nsDef);
                   2245: 
                   2246:     if (node->ns != NULL) {
                   2247:         xmlNsPtr ns;
                   2248: 
                   2249:        ns = xmlSearchNs(doc, ret, node->ns->prefix);
                   2250:        if (ns == NULL) {
                   2251:            /*
                   2252:             * Humm, we are copying an element whose namespace is defined
                   2253:             * out of the new tree scope. Search it in the original tree
                   2254:             * and add it at the top of the new tree
                   2255:             */
                   2256:            ns = xmlSearchNs(node->doc, node, node->ns->prefix);
                   2257:            if (ns != NULL) {
                   2258:                xmlNodePtr root = ret;
                   2259: 
                   2260:                while (root->parent != NULL) root = root->parent;
                   2261:                xmlNewNs(root, ns->href, ns->prefix);
                   2262:            }
                   2263:        } else {
                   2264:            /*
                   2265:             * reference the existing namespace definition in our own tree.
                   2266:             */
                   2267:            ret->ns = ns;
                   2268:        }
                   2269:     }
1.56      daniel   2270:     if (node->properties != NULL)
                   2271:         ret->properties = xmlCopyPropList(ret, node->properties);
1.90      daniel   2272:     if (node->children != NULL)
                   2273:         ret->children = xmlStaticCopyNodeList(node->children, doc, ret);
1.34      daniel   2274:     UPDATE_LAST_CHILD(ret)
1.31      daniel   2275:     return(ret);
                   2276: }
                   2277: 
                   2278: static xmlNodePtr
                   2279: xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent) {
                   2280:     xmlNodePtr ret = NULL;
                   2281:     xmlNodePtr p = NULL,q;
                   2282: 
                   2283:     while (node != NULL) {
                   2284:         q = xmlStaticCopyNode(node, doc, parent, 1);
1.103   ! daniel   2285:        if (ret == NULL) {
        !          2286:            q->prev = NULL;
        !          2287:            ret = p = q;
1.31      daniel   2288:        } else {
1.103   ! daniel   2289:            p->next = q;
        !          2290:            q->prev = p;
        !          2291:            p = q;
1.31      daniel   2292:        }
                   2293:        node = node->next;
                   2294:     }
                   2295:     return(ret);
                   2296: }
                   2297: 
                   2298: /**
                   2299:  * xmlCopyNode:
                   2300:  * @node:  the node
                   2301:  * @recursive:  if 1 do a recursive copy.
                   2302:  *
                   2303:  * Do a copy of the node.
                   2304:  *
                   2305:  * Returns: a new xmlNodePtr, or NULL in case of error.
                   2306:  */
                   2307: xmlNodePtr
                   2308: xmlCopyNode(xmlNodePtr node, int recursive) {
                   2309:     xmlNodePtr ret;
                   2310: 
                   2311:     ret = xmlStaticCopyNode(node, NULL, NULL, recursive);
                   2312:     return(ret);
                   2313: }
                   2314: 
                   2315: /**
                   2316:  * xmlCopyNodeList:
                   2317:  * @node:  the first node in the list.
                   2318:  *
                   2319:  * Do a recursive copy of the node list.
                   2320:  *
                   2321:  * Returns: a new xmlNodePtr, or NULL in case of error.
                   2322:  */
                   2323: xmlNodePtr xmlCopyNodeList(xmlNodePtr node) {
                   2324:     xmlNodePtr ret = xmlStaticCopyNodeList(node, NULL, NULL);
                   2325:     return(ret);
                   2326: }
                   2327: 
                   2328: /**
                   2329:  * xmlCopyElement:
                   2330:  * @elem:  the element
                   2331:  *
                   2332:  * Do a copy of the element definition.
                   2333:  *
                   2334:  * Returns: a new xmlElementPtr, or NULL in case of error.
                   2335: xmlElementPtr
                   2336: xmlCopyElement(xmlElementPtr elem) {
                   2337:     xmlElementPtr ret;
                   2338: 
                   2339:     if (elem == NULL) return(NULL);
                   2340:     ret = xmlNewDocElement(elem->doc, elem->ns, elem->name, elem->content);
                   2341:     if (ret == NULL) return(NULL);
                   2342:     if (!recursive) return(ret);
                   2343:     if (elem->properties != NULL)
                   2344:         ret->properties = xmlCopyPropList(elem->properties);
                   2345:     
                   2346:     if (elem->nsDef != NULL)
                   2347:         ret->nsDef = xmlCopyNamespaceList(elem->nsDef);
1.90      daniel   2348:     if (elem->children != NULL)
                   2349:         ret->children = xmlCopyElementList(elem->children);
1.31      daniel   2350:     return(ret);
                   2351: }
                   2352:  */
                   2353: 
                   2354: /**
                   2355:  * xmlCopyDtd:
                   2356:  * @dtd:  the dtd
                   2357:  *
                   2358:  * Do a copy of the dtd.
                   2359:  *
                   2360:  * Returns: a new xmlDtdPtr, or NULL in case of error.
                   2361:  */
                   2362: xmlDtdPtr
                   2363: xmlCopyDtd(xmlDtdPtr dtd) {
                   2364:     xmlDtdPtr ret;
                   2365: 
                   2366:     if (dtd == NULL) return(NULL);
                   2367:     ret = xmlNewDtd(NULL, dtd->name, dtd->ExternalID, dtd->SystemID);
                   2368:     if (ret == NULL) return(NULL);
                   2369:     if (dtd->entities != NULL)
                   2370:         ret->entities = (void *) xmlCopyEntitiesTable(
                   2371:                            (xmlEntitiesTablePtr) dtd->entities);
1.35      daniel   2372:     if (dtd->notations != NULL)
                   2373:         ret->notations = (void *) xmlCopyNotationTable(
                   2374:                            (xmlNotationTablePtr) dtd->notations);
                   2375:     if (dtd->elements != NULL)
                   2376:         ret->elements = (void *) xmlCopyElementTable(
                   2377:                            (xmlElementTablePtr) dtd->elements);
                   2378:     if (dtd->attributes != NULL)
                   2379:         ret->attributes = (void *) xmlCopyAttributeTable(
                   2380:                            (xmlAttributeTablePtr) dtd->attributes);
1.31      daniel   2381:     return(ret);
                   2382: }
                   2383: 
                   2384: /**
                   2385:  * xmlCopyDoc:
                   2386:  * @doc:  the document
                   2387:  * @recursive:  if 1 do a recursive copy.
                   2388:  *
                   2389:  * Do a copy of the document info. If recursive, the content tree will
                   2390:  * be copied too as well as Dtd, namespaces and entities.
                   2391:  *
                   2392:  * Returns: a new xmlDocPtr, or NULL in case of error.
                   2393:  */
                   2394: xmlDocPtr
                   2395: xmlCopyDoc(xmlDocPtr doc, int recursive) {
                   2396:     xmlDocPtr ret;
                   2397: 
                   2398:     if (doc == NULL) return(NULL);
                   2399:     ret = xmlNewDoc(doc->version);
                   2400:     if (ret == NULL) return(NULL);
                   2401:     if (doc->name != NULL)
1.57      daniel   2402:         ret->name = xmlMemStrdup(doc->name);
1.31      daniel   2403:     if (doc->encoding != NULL)
                   2404:         ret->encoding = xmlStrdup(doc->encoding);
                   2405:     ret->compression = doc->compression;
                   2406:     ret->standalone = doc->standalone;
                   2407:     if (!recursive) return(ret);
                   2408: 
                   2409:     if (doc->intSubset != NULL)
                   2410:         ret->intSubset = xmlCopyDtd(doc->intSubset);
                   2411:     if (doc->oldNs != NULL)
                   2412:         ret->oldNs = xmlCopyNamespaceList(doc->oldNs);
1.90      daniel   2413:     if (doc->children != NULL)
1.103   ! daniel   2414:         ret->children = xmlStaticCopyNodeList(doc->children, ret,
        !          2415:                                              (xmlNodePtr)ret);
1.31      daniel   2416:     return(ret);
                   2417: }
                   2418: 
                   2419: /************************************************************************
                   2420:  *                                                                     *
1.1       veillard 2421:  *             Content access functions                                *
                   2422:  *                                                                     *
                   2423:  ************************************************************************/
                   2424:  
1.23      daniel   2425: /**
1.75      daniel   2426:  * xmlDocGetRootElement:
                   2427:  * @doc:  the document
                   2428:  *
1.90      daniel   2429:  * Get the root element of the document (doc->children is a list
1.75      daniel   2430:  * containing possibly comments, PIs, etc ...).
                   2431:  *
                   2432:  * Returns the xmlNodePtr for the root or NULL
                   2433:  */
                   2434: xmlNodePtr
                   2435: xmlDocGetRootElement(xmlDocPtr doc) {
                   2436:     xmlNodePtr ret;
                   2437: 
                   2438:     if (doc == NULL) return(NULL);
1.90      daniel   2439:     ret = doc->children;
1.75      daniel   2440:     while (ret != NULL) {
                   2441:        if (ret->type == XML_ELEMENT_NODE)
                   2442:            return(ret);
                   2443:         ret = ret->next;
                   2444:     }
                   2445:     return(ret);
                   2446: }
                   2447:  
                   2448: /**
1.78      daniel   2449:  * xmlDocSetRootElement:
                   2450:  * @doc:  the document
                   2451:  * @root:  the new document root element
                   2452:  *
1.90      daniel   2453:  * Set the root element of the document (doc->children is a list
1.78      daniel   2454:  * containing possibly comments, PIs, etc ...).
                   2455:  *
                   2456:  * Returns the old root element if any was found
                   2457:  */
                   2458: xmlNodePtr
                   2459: xmlDocSetRootElement(xmlDocPtr doc, xmlNodePtr root) {
                   2460:     xmlNodePtr old = NULL;
                   2461: 
                   2462:     if (doc == NULL) return(NULL);
1.90      daniel   2463:     old = doc->children;
1.78      daniel   2464:     while (old != NULL) {
                   2465:        if (old->type == XML_ELEMENT_NODE)
                   2466:            break;
                   2467:         old = old->next;
                   2468:     }
                   2469:     if (old == NULL) {
1.90      daniel   2470:        if (doc->children == NULL) {
                   2471:            doc->children = root;
1.78      daniel   2472:        } else {
1.90      daniel   2473:            xmlAddSibling(doc->children, root);
1.78      daniel   2474:        }
                   2475:     } else {
                   2476:        xmlReplaceNode(old, root);
                   2477:     }
                   2478:     return(old);
                   2479: }
                   2480:  
                   2481: /**
1.52      daniel   2482:  * xmlNodeSetLang:
                   2483:  * @cur:  the node being changed
                   2484:  * @lang:  the langage description
                   2485:  *
1.78      daniel   2486:  * Set the language of a node, i.e. the values of the xml:lang
                   2487:  * attribute.
1.52      daniel   2488:  */
                   2489: void
1.61      daniel   2490: xmlNodeSetLang(xmlNodePtr cur, const xmlChar *lang) {
1.78      daniel   2491:     if (cur == NULL) return;
                   2492:     switch(cur->type) {
                   2493:         case XML_TEXT_NODE:
                   2494:         case XML_CDATA_SECTION_NODE:
                   2495:         case XML_COMMENT_NODE:
                   2496:         case XML_DOCUMENT_NODE:
                   2497:         case XML_DOCUMENT_TYPE_NODE:
                   2498:         case XML_DOCUMENT_FRAG_NODE:
                   2499:         case XML_NOTATION_NODE:
                   2500:         case XML_HTML_DOCUMENT_NODE:
1.90      daniel   2501:         case XML_DTD_NODE:
1.91      daniel   2502:         case XML_ELEMENT_DECL:
                   2503:         case XML_ATTRIBUTE_DECL:
1.96      daniel   2504:         case XML_ENTITY_DECL:
1.78      daniel   2505:            return;
                   2506:         case XML_ELEMENT_NODE:
                   2507:         case XML_ATTRIBUTE_NODE:
                   2508:         case XML_PI_NODE:
                   2509:         case XML_ENTITY_REF_NODE:
                   2510:         case XML_ENTITY_NODE:
                   2511:            break;
                   2512:     }
1.54      daniel   2513:     xmlSetProp(cur, BAD_CAST "xml:lang", lang);
1.52      daniel   2514: }
                   2515:  
                   2516: /**
                   2517:  * xmlNodeGetLang:
                   2518:  * @cur:  the node being checked
                   2519:  *
                   2520:  * Searches the language of a node, i.e. the values of the xml:lang
                   2521:  * attribute or the one carried by the nearest ancestor.
                   2522:  *
                   2523:  * Returns a pointer to the lang value, or NULL if not found
1.69      daniel   2524:  *     It's up to the caller to free the memory.
1.52      daniel   2525:  */
1.69      daniel   2526: xmlChar *
1.52      daniel   2527: xmlNodeGetLang(xmlNodePtr cur) {
1.69      daniel   2528:     xmlChar *lang;
1.52      daniel   2529: 
                   2530:     while (cur != NULL) {
1.54      daniel   2531:         lang = xmlGetProp(cur, BAD_CAST "xml:lang");
1.52      daniel   2532:        if (lang != NULL)
                   2533:            return(lang);
                   2534:        cur = cur->parent;
                   2535:     }
                   2536:     return(NULL);
1.78      daniel   2537: }
                   2538:  
                   2539: /**
1.98      daniel   2540:  * xmlNodeGetSpacePreserve:
                   2541:  * @cur:  the node being checked
                   2542:  *
                   2543:  * Searches the language of a node, i.e. the values of the xml:space
                   2544:  * attribute or the one carried by the nearest ancestor.
                   2545:  *
                   2546:  * Returns -1 if xml:space is not inheried, 0 if "default", 1 if "preserve"
                   2547:  */
                   2548: int
                   2549: xmlNodeGetSpacePreserve(xmlNodePtr cur) {
                   2550:     xmlChar *space;
                   2551: 
                   2552:     while (cur != NULL) {
                   2553:         space = xmlGetProp(cur, BAD_CAST "xml:space");
                   2554:        if (space != NULL) {
                   2555:            if (!xmlStrcmp(space, BAD_CAST "preserve")) {
                   2556:                xmlFree(space);
                   2557:                return(1);
                   2558:            }
                   2559:            if (!xmlStrcmp(space, BAD_CAST "default")) {
                   2560:                xmlFree(space);
                   2561:                return(0);
                   2562:            }
                   2563:            xmlFree(space);
                   2564:        }
                   2565:        cur = cur->parent;
                   2566:     }
                   2567:     return(-1);
                   2568: }
                   2569:  
                   2570: /**
1.78      daniel   2571:  * xmlNodeSetName:
                   2572:  * @cur:  the node being changed
                   2573:  * @name:  the new tag name
                   2574:  *
                   2575:  * Searches the language of a node, i.e. the values of the xml:lang
                   2576:  * attribute or the one carried by the nearest ancestor.
                   2577:  */
                   2578: void
                   2579: xmlNodeSetName(xmlNodePtr cur, const xmlChar *name) {
                   2580:     if (cur == NULL) return;
                   2581:     if (name == NULL) return;
                   2582:     switch(cur->type) {
                   2583:         case XML_TEXT_NODE:
                   2584:         case XML_CDATA_SECTION_NODE:
                   2585:         case XML_COMMENT_NODE:
                   2586:         case XML_DOCUMENT_TYPE_NODE:
                   2587:         case XML_DOCUMENT_FRAG_NODE:
                   2588:         case XML_NOTATION_NODE:
                   2589:         case XML_HTML_DOCUMENT_NODE:
                   2590:            return;
                   2591:         case XML_ELEMENT_NODE:
                   2592:         case XML_ATTRIBUTE_NODE:
                   2593:         case XML_PI_NODE:
                   2594:         case XML_ENTITY_REF_NODE:
                   2595:         case XML_ENTITY_NODE:
1.90      daniel   2596:         case XML_DTD_NODE:
                   2597:         case XML_DOCUMENT_NODE:
1.96      daniel   2598:         case XML_ELEMENT_DECL:
                   2599:         case XML_ATTRIBUTE_DECL:
                   2600:         case XML_ENTITY_DECL:
1.78      daniel   2601:            break;
                   2602:     }
                   2603:     if (cur->name != NULL) xmlFree((xmlChar *) cur->name);
                   2604:     cur->name = xmlStrdup(name);
1.52      daniel   2605: }
                   2606:  
                   2607: /**
1.73      daniel   2608:  * xmlNodeGetBase:
                   2609:  * @doc:  the document the node pertains to
                   2610:  * @cur:  the node being checked
                   2611:  *
                   2612:  * Searches for the BASE URL. The code should work on both XML
                   2613:  * and HTML document even if base mechanisms are completely different.
                   2614:  *
                   2615:  * Returns a pointer to the base URL, or NULL if not found
                   2616:  *     It's up to the caller to free the memory.
                   2617:  */
                   2618: xmlChar *
                   2619: xmlNodeGetBase(xmlDocPtr doc, xmlNodePtr cur) {
                   2620:     xmlChar *base;
                   2621: 
                   2622:     if ((cur == NULL) && (doc == NULL)) 
                   2623:         return(NULL);
                   2624:     if (doc == NULL) doc = cur->doc;   
                   2625:     if ((doc != NULL) && (doc->type == XML_HTML_DOCUMENT_NODE)) {
1.90      daniel   2626:         cur = doc->children;
1.73      daniel   2627:        while ((cur != NULL) && (cur->name != NULL)) {
                   2628:            if (cur->type != XML_ELEMENT_NODE) {
                   2629:                cur = cur->next;
                   2630:                continue;
                   2631:            }
                   2632:            if ((!xmlStrcmp(cur->name, BAD_CAST "html")) ||
                   2633:                (!xmlStrcmp(cur->name, BAD_CAST "HTML"))) {
1.90      daniel   2634:                cur = cur->children;
1.73      daniel   2635:                continue;
                   2636:            }
                   2637:            if ((!xmlStrcmp(cur->name, BAD_CAST "head")) ||
                   2638:                (!xmlStrcmp(cur->name, BAD_CAST "HEAD"))) {
1.90      daniel   2639:                cur = cur->children;
1.73      daniel   2640:                continue;
                   2641:            }
                   2642:            if ((!xmlStrcmp(cur->name, BAD_CAST "base")) ||
                   2643:                (!xmlStrcmp(cur->name, BAD_CAST "BASE"))) {
                   2644:                 base = xmlGetProp(cur, BAD_CAST "href");
                   2645:                if (base != NULL) return(base);
                   2646:                 return(xmlGetProp(cur, BAD_CAST "HREF"));
                   2647:            }
1.100     daniel   2648:            cur = cur->next;
1.73      daniel   2649:        }
1.100     daniel   2650:        if ((doc != NULL) && (doc->URL != NULL))
                   2651:            return(xmlStrdup(doc->URL));
1.73      daniel   2652:        return(NULL);
                   2653:     }
                   2654:     while (cur != NULL) {
                   2655:         base = xmlGetProp(cur, BAD_CAST "xml:base");
                   2656:        if (base != NULL)
                   2657:            return(base);
                   2658:        cur = cur->parent;
                   2659:     }
1.100     daniel   2660:     if ((doc != NULL) && (doc->URL != NULL))
                   2661:        return(xmlStrdup(doc->URL));
1.73      daniel   2662:     return(NULL);
                   2663: }
                   2664:  
                   2665: /**
1.28      daniel   2666:  * xmlNodeGetContent:
                   2667:  * @cur:  the node being read
                   2668:  *
                   2669:  * Read the value of a node, this can be either the text carried
                   2670:  * directly by this node if it's a TEXT node or the aggregate string
                   2671:  * of the values carried by this node child's (TEXT and ENTITY_REF).
                   2672:  * Entity references are substitued.
1.61      daniel   2673:  * Returns a new xmlChar * or NULL if no content is available.
1.38      daniel   2674:  *     It's up to the caller to free the memory.
1.28      daniel   2675:  */
1.61      daniel   2676: xmlChar *
1.28      daniel   2677: xmlNodeGetContent(xmlNodePtr cur) {
                   2678:     if (cur == NULL) return(NULL);
                   2679:     switch (cur->type) {
                   2680:         case XML_DOCUMENT_FRAG_NODE:
                   2681:         case XML_ELEMENT_NODE:
1.90      daniel   2682:             return(xmlNodeListGetString(cur->doc, cur->children, 1));
1.28      daniel   2683:            break;
1.52      daniel   2684:         case XML_ATTRIBUTE_NODE: {
                   2685:            xmlAttrPtr attr = (xmlAttrPtr) cur;
1.90      daniel   2686:            if (attr->parent != NULL)
                   2687:                return(xmlNodeListGetString(attr->parent->doc, attr->children, 1));
1.52      daniel   2688:            else
1.90      daniel   2689:                return(xmlNodeListGetString(NULL, attr->children, 1));
1.52      daniel   2690:            break;
                   2691:        }
1.82      daniel   2692:         case XML_COMMENT_NODE:
1.52      daniel   2693:         case XML_PI_NODE:
                   2694:            if (cur->content != NULL)
1.70      daniel   2695: #ifndef XML_USE_BUFFER_CONTENT
1.52      daniel   2696:                return(xmlStrdup(cur->content));
1.70      daniel   2697: #else
                   2698:                return(xmlStrdup(xmlBufferContent(cur->content)));
                   2699: #endif
1.52      daniel   2700:            return(NULL);
1.28      daniel   2701:         case XML_ENTITY_REF_NODE:
1.82      daniel   2702:            /*
                   2703:             * Locate the entity, and get it's content
                   2704:             * @@@
                   2705:             */
                   2706:             return(NULL);
1.28      daniel   2707:         case XML_ENTITY_NODE:
                   2708:         case XML_DOCUMENT_NODE:
1.65      daniel   2709:         case XML_HTML_DOCUMENT_NODE:
1.28      daniel   2710:         case XML_DOCUMENT_TYPE_NODE:
                   2711:         case XML_NOTATION_NODE:
1.90      daniel   2712:         case XML_DTD_NODE:
1.28      daniel   2713:            return(NULL);
1.91      daniel   2714:         case XML_ELEMENT_DECL:
                   2715:            /* TODO !!! */
                   2716:            return(NULL);
                   2717:         case XML_ATTRIBUTE_DECL:
                   2718:            /* TODO !!! */
                   2719:            return(NULL);
1.96      daniel   2720:         case XML_ENTITY_DECL:
                   2721:            /* TODO !!! */
                   2722:            return(NULL);
1.50      daniel   2723:         case XML_CDATA_SECTION_NODE:
1.28      daniel   2724:         case XML_TEXT_NODE:
                   2725:            if (cur->content != NULL)
1.70      daniel   2726: #ifndef XML_USE_BUFFER_CONTENT
1.28      daniel   2727:                return(xmlStrdup(cur->content));
1.70      daniel   2728: #else
                   2729:                return(xmlStrdup(xmlBufferContent(cur->content)));
                   2730: #endif
1.28      daniel   2731:             return(NULL);
                   2732:     }
                   2733:     return(NULL);
                   2734: }
                   2735:  
                   2736: /**
1.23      daniel   2737:  * xmlNodeSetContent:
                   2738:  * @cur:  the node being modified
                   2739:  * @content:  the new value of the content
                   2740:  *
                   2741:  * Replace the content of a node.
1.1       veillard 2742:  */
1.28      daniel   2743: void
1.61      daniel   2744: xmlNodeSetContent(xmlNodePtr cur, const xmlChar *content) {
1.1       veillard 2745:     if (cur == NULL) {
1.86      daniel   2746: #ifdef DEBUG_TREE
1.1       veillard 2747:         fprintf(stderr, "xmlNodeSetContent : node == NULL\n");
1.86      daniel   2748: #endif
1.1       veillard 2749:        return;
                   2750:     }
1.28      daniel   2751:     switch (cur->type) {
                   2752:         case XML_DOCUMENT_FRAG_NODE:
                   2753:         case XML_ELEMENT_NODE:
                   2754:            if (cur->content != NULL) {
1.70      daniel   2755: #ifndef XML_USE_BUFFER_CONTENT
1.57      daniel   2756:                xmlFree(cur->content);
1.70      daniel   2757: #else
                   2758:                xmlBufferFree(cur->content);
                   2759: #endif
1.28      daniel   2760:                cur->content = NULL;
                   2761:            }
1.90      daniel   2762:            if (cur->children != NULL) xmlFreeNodeList(cur->children);
                   2763:            cur->children = xmlStringGetNodeList(cur->doc, content);
1.34      daniel   2764:            UPDATE_LAST_CHILD(cur)
1.28      daniel   2765:            break;
                   2766:         case XML_ATTRIBUTE_NODE:
                   2767:            break;
                   2768:         case XML_TEXT_NODE:
                   2769:         case XML_CDATA_SECTION_NODE:
                   2770:         case XML_ENTITY_REF_NODE:
                   2771:         case XML_ENTITY_NODE:
                   2772:         case XML_PI_NODE:
                   2773:         case XML_COMMENT_NODE:
1.70      daniel   2774:            if (cur->content != NULL) {
                   2775: #ifndef XML_USE_BUFFER_CONTENT
                   2776:                xmlFree(cur->content);
                   2777: #else
                   2778:                xmlBufferFree(cur->content);
                   2779: #endif
                   2780:            }   
1.90      daniel   2781:            if (cur->children != NULL) xmlFreeNodeList(cur->children);
                   2782:            cur->last = cur->children = NULL;
1.70      daniel   2783:            if (content != NULL) {
                   2784: #ifndef XML_USE_BUFFER_CONTENT
1.28      daniel   2785:                cur->content = xmlStrdup(content);
1.70      daniel   2786: #else
                   2787:                cur->content = xmlBufferCreateSize(0);
                   2788:                xmlBufferSetAllocationScheme(cur->content,
                   2789:                                             xmlGetBufferAllocationScheme());
                   2790:                xmlBufferAdd(cur->content, content, -1);
                   2791: #endif
                   2792:            } else 
1.28      daniel   2793:                cur->content = NULL;
1.53      daniel   2794:            break;
1.28      daniel   2795:         case XML_DOCUMENT_NODE:
1.65      daniel   2796:         case XML_HTML_DOCUMENT_NODE:
1.28      daniel   2797:         case XML_DOCUMENT_TYPE_NODE:
                   2798:            break;
                   2799:         case XML_NOTATION_NODE:
                   2800:            break;
1.90      daniel   2801:         case XML_DTD_NODE:
                   2802:            break;
1.91      daniel   2803:         case XML_ELEMENT_DECL:
                   2804:            /* TODO !!! */
                   2805:            break;
                   2806:         case XML_ATTRIBUTE_DECL:
                   2807:            /* TODO !!! */
                   2808:            break;
1.96      daniel   2809:         case XML_ENTITY_DECL:
                   2810:            /* TODO !!! */
                   2811:            break;
1.28      daniel   2812:     }
1.1       veillard 2813: }
                   2814: 
1.23      daniel   2815: /**
                   2816:  * xmlNodeSetContentLen:
                   2817:  * @cur:  the node being modified
                   2818:  * @content:  the new value of the content
                   2819:  * @len:  the size of @content
                   2820:  *
                   2821:  * Replace the content of a node.
1.21      daniel   2822:  */
1.28      daniel   2823: void
1.61      daniel   2824: xmlNodeSetContentLen(xmlNodePtr cur, const xmlChar *content, int len) {
1.21      daniel   2825:     if (cur == NULL) {
1.86      daniel   2826: #ifdef DEBUG_TREE
1.28      daniel   2827:         fprintf(stderr, "xmlNodeSetContentLen : node == NULL\n");
1.86      daniel   2828: #endif
1.21      daniel   2829:        return;
                   2830:     }
1.28      daniel   2831:     switch (cur->type) {
                   2832:         case XML_DOCUMENT_FRAG_NODE:
                   2833:         case XML_ELEMENT_NODE:
                   2834:            if (cur->content != NULL) {
1.70      daniel   2835: #ifndef XML_USE_BUFFER_CONTENT
1.57      daniel   2836:                xmlFree(cur->content);
1.70      daniel   2837: #else
                   2838:                xmlBufferFree(cur->content);
                   2839: #endif
1.28      daniel   2840:                cur->content = NULL;
                   2841:            }
1.90      daniel   2842:            if (cur->children != NULL) xmlFreeNodeList(cur->children);
                   2843:            cur->children = xmlStringLenGetNodeList(cur->doc, content, len);
1.34      daniel   2844:            UPDATE_LAST_CHILD(cur)
1.28      daniel   2845:            break;
                   2846:         case XML_ATTRIBUTE_NODE:
                   2847:            break;
                   2848:         case XML_TEXT_NODE:
                   2849:         case XML_CDATA_SECTION_NODE:
                   2850:         case XML_ENTITY_REF_NODE:
                   2851:         case XML_ENTITY_NODE:
                   2852:         case XML_PI_NODE:
                   2853:         case XML_COMMENT_NODE:
1.70      daniel   2854:         case XML_NOTATION_NODE:
                   2855:            if (cur->content != NULL) {
                   2856: #ifndef XML_USE_BUFFER_CONTENT
                   2857:                xmlFree(cur->content);
                   2858: #else
                   2859:                xmlBufferFree(cur->content);
                   2860: #endif
                   2861:            }   
1.90      daniel   2862:            if (cur->children != NULL) xmlFreeNodeList(cur->children);
                   2863:            cur->children = cur->last = NULL;
1.70      daniel   2864:            if (content != NULL) {
                   2865: #ifndef XML_USE_BUFFER_CONTENT
1.28      daniel   2866:                cur->content = xmlStrndup(content, len);
1.70      daniel   2867: #else
                   2868:                cur->content = xmlBufferCreateSize(len);
                   2869:                xmlBufferSetAllocationScheme(cur->content,
                   2870:                                             xmlGetBufferAllocationScheme());
                   2871:                xmlBufferAdd(cur->content, content, len);
                   2872: #endif
                   2873:            } else 
1.28      daniel   2874:                cur->content = NULL;
1.53      daniel   2875:            break;
1.28      daniel   2876:         case XML_DOCUMENT_NODE:
1.90      daniel   2877:         case XML_DTD_NODE:
1.65      daniel   2878:         case XML_HTML_DOCUMENT_NODE:
1.28      daniel   2879:         case XML_DOCUMENT_TYPE_NODE:
                   2880:            break;
1.91      daniel   2881:         case XML_ELEMENT_DECL:
                   2882:            /* TODO !!! */
                   2883:            break;
                   2884:         case XML_ATTRIBUTE_DECL:
                   2885:            /* TODO !!! */
                   2886:            break;
1.96      daniel   2887:         case XML_ENTITY_DECL:
                   2888:            /* TODO !!! */
                   2889:            break;
1.28      daniel   2890:     }
1.21      daniel   2891: }
                   2892: 
1.23      daniel   2893: /**
1.28      daniel   2894:  * xmlNodeAddContentLen:
1.23      daniel   2895:  * @cur:  the node being modified
                   2896:  * @content:  extra content
1.28      daniel   2897:  * @len:  the size of @content
1.23      daniel   2898:  * 
                   2899:  * Append the extra substring to the node content.
1.21      daniel   2900:  */
1.28      daniel   2901: void
1.61      daniel   2902: xmlNodeAddContentLen(xmlNodePtr cur, const xmlChar *content, int len) {
1.21      daniel   2903:     if (cur == NULL) {
1.86      daniel   2904: #ifdef DEBUG_TREE
1.28      daniel   2905:         fprintf(stderr, "xmlNodeAddContentLen : node == NULL\n");
1.86      daniel   2906: #endif
1.21      daniel   2907:        return;
                   2908:     }
1.28      daniel   2909:     if (len <= 0) return;
                   2910:     switch (cur->type) {
                   2911:         case XML_DOCUMENT_FRAG_NODE:
                   2912:         case XML_ELEMENT_NODE: {
                   2913:            xmlNodePtr last = NULL, new;
                   2914: 
1.90      daniel   2915:            if (cur->children != NULL) {
1.32      daniel   2916:                last = cur->last;
1.28      daniel   2917:            } else {
                   2918:                if (cur->content != NULL) {
1.70      daniel   2919: #ifndef XML_USE_BUFFER_CONTENT
1.90      daniel   2920:                    cur->children = xmlStringGetNodeList(cur->doc, cur->content);
1.70      daniel   2921: #else
1.90      daniel   2922:                    cur->children = xmlStringGetNodeList(cur->doc,
1.70      daniel   2923:                                               xmlBufferContent(cur->content));
                   2924: #endif
1.34      daniel   2925:                    UPDATE_LAST_CHILD(cur)
1.70      daniel   2926: #ifndef XML_USE_BUFFER_CONTENT
1.57      daniel   2927:                    xmlFree(cur->content);
1.70      daniel   2928: #else
                   2929:                    xmlBufferFree(cur->content);
                   2930: #endif
1.28      daniel   2931:                    cur->content = NULL;
1.32      daniel   2932:                    last = cur->last;
1.28      daniel   2933:                }
                   2934:            }
1.31      daniel   2935:            new = xmlNewTextLen(content, len);
1.28      daniel   2936:            if (new != NULL) {
                   2937:                xmlAddChild(cur, new);
1.32      daniel   2938:                if ((last != NULL) && (last->next == new)) {
1.28      daniel   2939:                    xmlTextMerge(last, new);
1.32      daniel   2940:                }
1.28      daniel   2941:            }
                   2942:            break;
                   2943:        }
                   2944:         case XML_ATTRIBUTE_NODE:
                   2945:            break;
                   2946:         case XML_TEXT_NODE:
                   2947:         case XML_CDATA_SECTION_NODE:
                   2948:         case XML_ENTITY_REF_NODE:
                   2949:         case XML_ENTITY_NODE:
                   2950:         case XML_PI_NODE:
                   2951:         case XML_COMMENT_NODE:
1.70      daniel   2952:         case XML_NOTATION_NODE:
                   2953:            if (content != NULL) {
                   2954: #ifndef XML_USE_BUFFER_CONTENT
1.28      daniel   2955:                cur->content = xmlStrncat(cur->content, content, len);
1.70      daniel   2956: #else
                   2957:                xmlBufferAdd(cur->content, content, len);
                   2958: #endif
                   2959:             }
1.28      daniel   2960:         case XML_DOCUMENT_NODE:
1.90      daniel   2961:         case XML_DTD_NODE:
1.65      daniel   2962:         case XML_HTML_DOCUMENT_NODE:
1.28      daniel   2963:         case XML_DOCUMENT_TYPE_NODE:
                   2964:            break;
1.91      daniel   2965:         case XML_ELEMENT_DECL:
                   2966:         case XML_ATTRIBUTE_DECL:
1.96      daniel   2967:         case XML_ENTITY_DECL:
1.91      daniel   2968:            break;
1.28      daniel   2969:     }
1.21      daniel   2970: }
                   2971: 
1.23      daniel   2972: /**
1.28      daniel   2973:  * xmlNodeAddContent:
1.23      daniel   2974:  * @cur:  the node being modified
                   2975:  * @content:  extra content
                   2976:  * 
                   2977:  * Append the extra substring to the node content.
1.21      daniel   2978:  */
1.28      daniel   2979: void
1.61      daniel   2980: xmlNodeAddContent(xmlNodePtr cur, const xmlChar *content) {
1.28      daniel   2981:     int len;
                   2982: 
1.21      daniel   2983:     if (cur == NULL) {
1.86      daniel   2984: #ifdef DEBUG_TREE
1.21      daniel   2985:         fprintf(stderr, "xmlNodeAddContent : node == NULL\n");
1.86      daniel   2986: #endif
1.21      daniel   2987:        return;
                   2988:     }
1.28      daniel   2989:     if (content == NULL) return;
                   2990:     len = xmlStrlen(content);
                   2991:     xmlNodeAddContentLen(cur, content, len);
                   2992: }
                   2993: 
                   2994: /**
                   2995:  * xmlTextMerge:
                   2996:  * @first:  the first text node
                   2997:  * @second:  the second text node being merged
                   2998:  * 
                   2999:  * Merge two text nodes into one
1.36      daniel   3000:  * Returns the first text node augmented
1.28      daniel   3001:  */
                   3002: xmlNodePtr
                   3003: xmlTextMerge(xmlNodePtr first, xmlNodePtr second) {
                   3004:     if (first == NULL) return(second);
                   3005:     if (second == NULL) return(first);
                   3006:     if (first->type != XML_TEXT_NODE) return(first);
                   3007:     if (second->type != XML_TEXT_NODE) return(first);
1.70      daniel   3008: #ifndef XML_USE_BUFFER_CONTENT
1.28      daniel   3009:     xmlNodeAddContent(first, second->content);
1.70      daniel   3010: #else
                   3011:     xmlNodeAddContent(first, xmlBufferContent(second->content));
                   3012: #endif
1.28      daniel   3013:     xmlUnlinkNode(second);
                   3014:     xmlFreeNode(second);
                   3015:     return(first);
1.21      daniel   3016: }
                   3017: 
1.23      daniel   3018: /**
1.52      daniel   3019:  * xmlGetNsList:
                   3020:  * @doc:  the document
                   3021:  * @node:  the current node
                   3022:  *
                   3023:  * Search all the namespace applying to a given element.
                   3024:  * Returns an NULL terminated array of all the xmlNsPtr found
                   3025:  *         that need to be freed by the caller or NULL if no
                   3026:  *         namespace if defined
                   3027:  */
                   3028: xmlNsPtr *
                   3029: xmlGetNsList(xmlDocPtr doc, xmlNodePtr node) {
                   3030:     xmlNsPtr cur;
                   3031:     xmlNsPtr *ret = NULL;
                   3032:     int nbns = 0;
                   3033:     int maxns = 10;
                   3034:     int i;
                   3035: 
                   3036:     while (node != NULL) {
                   3037:        cur = node->nsDef;
                   3038:        while (cur != NULL) {
                   3039:            if (ret == NULL) {
1.57      daniel   3040:                ret = (xmlNsPtr *) xmlMalloc((maxns + 1) * sizeof(xmlNsPtr));
1.52      daniel   3041:                if (ret == NULL) {
                   3042:                    fprintf(stderr, "xmlGetNsList : out of memory!\n");
                   3043:                    return(NULL);
                   3044:                }
                   3045:                ret[nbns] = NULL;
                   3046:            }
                   3047:            for (i = 0;i < nbns;i++) {
                   3048:                if ((cur->prefix == ret[i]->prefix) ||
                   3049:                    (!xmlStrcmp(cur->prefix, ret[i]->prefix))) break;
                   3050:            }
                   3051:            if (i >= nbns) {
                   3052:                if (nbns >= maxns) {
                   3053:                    maxns *= 2;
1.57      daniel   3054:                    ret = (xmlNsPtr *) xmlRealloc(ret,
1.52      daniel   3055:                                         (maxns + 1) * sizeof(xmlNsPtr));
                   3056:                    if (ret == NULL) {
                   3057:                        fprintf(stderr, "xmlGetNsList : realloc failed!\n");
                   3058:                        return(NULL);
                   3059:                    }
                   3060:                }
                   3061:                ret[nbns++] = cur;
                   3062:                ret[nbns] = NULL;
                   3063:            }
                   3064: 
                   3065:            cur = cur->next;
                   3066:        }
                   3067:        node = node->parent;
                   3068:     }
                   3069:     return(ret);
                   3070: }
                   3071: 
                   3072: /**
1.23      daniel   3073:  * xmlSearchNs:
                   3074:  * @doc:  the document
                   3075:  * @node:  the current node
                   3076:  * @nameSpace:  the namespace string
                   3077:  *
1.16      daniel   3078:  * Search a Ns registered under a given name space for a document.
1.23      daniel   3079:  * recurse on the parents until it finds the defined namespace
                   3080:  * or return NULL otherwise.
                   3081:  * @nameSpace can be NULL, this is a search for the default namespace.
1.36      daniel   3082:  * Returns the namespace pointer or NULL.
1.3       veillard 3083:  */
1.28      daniel   3084: xmlNsPtr
1.61      daniel   3085: xmlSearchNs(xmlDocPtr doc, xmlNodePtr node, const xmlChar *nameSpace) {
1.16      daniel   3086:     xmlNsPtr cur;
1.3       veillard 3087: 
1.76      daniel   3088:     if (node == NULL) return(NULL);
1.19      daniel   3089:     while (node != NULL) {
1.92      daniel   3090:        if (node->type == XML_ELEMENT_NODE) {
                   3091:            cur = node->nsDef;
                   3092:            while (cur != NULL) {
                   3093:                if ((cur->prefix == NULL) && (nameSpace == NULL))
                   3094:                    return(cur);
                   3095:                if ((cur->prefix != NULL) && (nameSpace != NULL) &&
                   3096:                    (!xmlStrcmp(cur->prefix, nameSpace)))
                   3097:                    return(cur);
                   3098:                cur = cur->next;
                   3099:            }
1.19      daniel   3100:        }
                   3101:        node = node->parent;
                   3102:     }
                   3103:     return(NULL);
                   3104: }
1.3       veillard 3105: 
1.23      daniel   3106: /**
                   3107:  * xmlSearchNsByHref:
                   3108:  * @doc:  the document
                   3109:  * @node:  the current node
                   3110:  * @href:  the namespace value
                   3111:  *
                   3112:  * Search a Ns aliasing a given URI. Recurse on the parents until it finds
                   3113:  * the defined namespace or return NULL otherwise.
1.36      daniel   3114:  * Returns the namespace pointer or NULL.
1.19      daniel   3115:  */
1.28      daniel   3116: xmlNsPtr
1.61      daniel   3117: xmlSearchNsByHref(xmlDocPtr doc, xmlNodePtr node, const xmlChar *href) {
1.19      daniel   3118:     xmlNsPtr cur;
1.82      daniel   3119:     xmlNodePtr orig = node;
1.19      daniel   3120: 
1.74      daniel   3121:     if ((node == NULL) || (href == NULL)) return(NULL);
1.19      daniel   3122:     while (node != NULL) {
                   3123:        cur = node->nsDef;
                   3124:        while (cur != NULL) {
                   3125:            if ((cur->href != NULL) && (href != NULL) &&
1.82      daniel   3126:                (!xmlStrcmp(cur->href, href))) {
                   3127:                /*
                   3128:                 * Check that the prefix is not shadowed between orig and node
                   3129:                 */
                   3130:                xmlNodePtr check = orig;
                   3131:                xmlNsPtr tst;
                   3132: 
                   3133:                while (check != node) {
                   3134:                    tst = check->nsDef;
                   3135:                    while (tst != NULL) {
                   3136:                        if ((tst->prefix == NULL) && (cur->prefix == NULL))
                   3137:                            goto shadowed;
                   3138:                        if ((tst->prefix != NULL) && (cur->prefix != NULL) &&
                   3139:                            (!xmlStrcmp(tst->prefix, cur->prefix)))
                   3140:                            goto shadowed;
                   3141:                        tst = tst->next;
                   3142:                    }
                   3143:                }
1.19      daniel   3144:                return(cur);
1.82      daniel   3145:            }
                   3146: shadowed:                  
1.19      daniel   3147:            cur = cur->next;
                   3148:        }
                   3149:        node = node->parent;
                   3150:     }
1.82      daniel   3151:     return(NULL);
                   3152: }
                   3153: 
                   3154: /**
                   3155:  * xmlNewReconciliedNs
                   3156:  * @doc:  the document
                   3157:  * @tree:  a node expected to hold the new namespace
                   3158:  * @ns:  the original namespace
                   3159:  *
                   3160:  * This function tries to locate a namespace definition in a tree
                   3161:  * ancestors, or create a new namespace definition node similar to
                   3162:  * @ns trying to reuse the same prefix. However if the given prefix is
                   3163:  * null (default namespace) or reused within the subtree defined by
                   3164:  * @tree or on one of its ancestors then a new prefix is generated.
                   3165:  * Returns the (new) namespace definition or NULL in case of error
                   3166:  */
                   3167: xmlNsPtr
                   3168: xmlNewReconciliedNs(xmlDocPtr doc, xmlNodePtr tree, xmlNsPtr ns) {
                   3169:     xmlNsPtr def;
                   3170:     xmlChar prefix[50];
                   3171:     int counter = 1;
                   3172: 
                   3173:     if (tree == NULL) {
                   3174: #ifdef DEBUG_TREE
                   3175:         fprintf(stderr, "xmlNewReconciliedNs : tree == NULL\n");
                   3176: #endif
                   3177:        return(NULL);
                   3178:     }
                   3179:     if (ns == NULL) {
                   3180: #ifdef DEBUG_TREE
                   3181:         fprintf(stderr, "xmlNewReconciliedNs : ns == NULL\n");
                   3182: #endif
                   3183:        return(NULL);
                   3184:     }
                   3185:     /*
                   3186:      * Search an existing namespace definition inherited.
                   3187:      */
                   3188:     def = xmlSearchNsByHref(doc, tree, ns->href);
                   3189:     if (def != NULL)
                   3190:         return(def);
                   3191: 
                   3192:     /*
                   3193:      * Find a close prefix which is not already in use.
                   3194:      * Let's strip namespace prefixes longer than 20 chars !
                   3195:      */
                   3196:     sprintf((char *) prefix, "%.20s", ns->prefix);
                   3197:     def = xmlSearchNs(doc, tree, prefix);
                   3198:     while (def != NULL) {
                   3199:         if (counter > 1000) return(NULL);
                   3200:         sprintf((char *) prefix, "%.20s%d", ns->prefix, counter++);
                   3201:        def = xmlSearchNs(doc, tree, prefix);
                   3202:     }
                   3203: 
                   3204:     /*
                   3205:      * Ok, now we are ready to create a new one.
                   3206:      */
                   3207:     def = xmlNewNs(tree, ns->href, prefix);
                   3208:     return(def);
                   3209: }
                   3210: 
                   3211: /**
                   3212:  * xmlReconciliateNs
                   3213:  * @doc:  the document
                   3214:  * @tree:  a node defining the subtree to reconciliate
                   3215:  *
                   3216:  * This function checks that all the namespaces declared within the given
                   3217:  * tree are properly declared. This is needed for example after Copy or Cut
                   3218:  * and then paste operations. The subtree may still hold pointers to
                   3219:  * namespace declarations outside the subtree or invalid/masked. As much
                   3220:  * as possible the function try tu reuse the existing namespaces found in
                   3221:  * the new environment. If not possible the new namespaces are redeclared
                   3222:  * on @tree at the top of the given subtree.
                   3223:  * Returns the number of namespace declarations created or -1 in case of error.
                   3224:  */
                   3225: int
                   3226: xmlReconciliateNs(xmlDocPtr doc, xmlNodePtr tree) {
                   3227:     xmlNsPtr *oldNs = NULL;
                   3228:     xmlNsPtr *newNs = NULL;
                   3229:     int sizeCache = 0;
                   3230:     int nbCache = 0;
                   3231: 
                   3232:     xmlNsPtr n;
                   3233:     xmlNodePtr node = tree;
                   3234:     xmlAttrPtr attr;
                   3235:     int ret = 0, i;
                   3236: 
                   3237:     while (node != NULL) {
                   3238:         /*
                   3239:         * Reconciliate the node namespace
                   3240:         */
                   3241:        if (node->ns != NULL) {
                   3242:            /*
                   3243:             * initialize the cache if needed
                   3244:             */
                   3245:            if (sizeCache == 0) {
                   3246:                sizeCache = 10;
                   3247:                oldNs = (xmlNsPtr *) xmlMalloc(sizeCache *
                   3248:                                               sizeof(xmlNsPtr));
                   3249:                if (oldNs == NULL) {
                   3250:                    fprintf(stderr, "xmlReconciliateNs : memory pbm\n");
                   3251:                    return(-1);
                   3252:                }
                   3253:                newNs = (xmlNsPtr *) xmlMalloc(sizeCache *
                   3254:                                               sizeof(xmlNsPtr));
                   3255:                if (newNs == NULL) {
                   3256:                    fprintf(stderr, "xmlReconciliateNs : memory pbm\n");
                   3257:                    xmlFree(oldNs);
                   3258:                    return(-1);
                   3259:                }
                   3260:            }
                   3261:            for (i = 0;i < nbCache;i++) {
                   3262:                if (oldNs[i] == node->ns) {
                   3263:                    node->ns = newNs[i];
                   3264:                    break;
                   3265:                }
                   3266:            }
                   3267:            if (i == nbCache) {
                   3268:                /*
                   3269:                 * Ok we need to recreate a new namespace definition
                   3270:                 */
                   3271:                n = xmlNewReconciliedNs(doc, tree, node->ns);
                   3272:                if (n != NULL) { /* :-( what if else ??? */
                   3273:                    /*
                   3274:                     * check if we need to grow the cache buffers.
                   3275:                     */
                   3276:                    if (sizeCache <= nbCache) {
                   3277:                        sizeCache *= 2;
                   3278:                        oldNs = (xmlNsPtr *) xmlRealloc(oldNs, sizeCache *
                   3279:                                                       sizeof(xmlNsPtr));
                   3280:                        if (oldNs == NULL) {
                   3281:                            fprintf(stderr, "xmlReconciliateNs : memory pbm\n");
                   3282:                            xmlFree(newNs);
                   3283:                            return(-1);
                   3284:                        }
                   3285:                        newNs = (xmlNsPtr *) xmlRealloc(newNs, sizeCache *
                   3286:                                                       sizeof(xmlNsPtr));
                   3287:                        if (newNs == NULL) {
                   3288:                            fprintf(stderr, "xmlReconciliateNs : memory pbm\n");
                   3289:                            xmlFree(oldNs);
                   3290:                            return(-1);
                   3291:                        }
                   3292:                    }
                   3293:                    newNs[nbCache] = n;
                   3294:                    oldNs[nbCache++] = node->ns;
                   3295:                    node->ns = n;
                   3296:                 }
                   3297:            }
                   3298:        }
                   3299:        /*
                   3300:         * now check for namespace hold by attributes on the node.
                   3301:         */
                   3302:        attr = node->properties;
                   3303:        while (attr != NULL) {
                   3304:            if (attr->ns != NULL) {
                   3305:                /*
                   3306:                 * initialize the cache if needed
                   3307:                 */
                   3308:                if (sizeCache == 0) {
                   3309:                    sizeCache = 10;
                   3310:                    oldNs = (xmlNsPtr *) xmlMalloc(sizeCache *
                   3311:                                                   sizeof(xmlNsPtr));
                   3312:                    if (oldNs == NULL) {
                   3313:                        fprintf(stderr, "xmlReconciliateNs : memory pbm\n");
                   3314:                        return(-1);
                   3315:                    }
                   3316:                    newNs = (xmlNsPtr *) xmlMalloc(sizeCache *
                   3317:                                                   sizeof(xmlNsPtr));
                   3318:                    if (newNs == NULL) {
                   3319:                        fprintf(stderr, "xmlReconciliateNs : memory pbm\n");
                   3320:                        xmlFree(oldNs);
                   3321:                        return(-1);
                   3322:                    }
                   3323:                }
                   3324:                for (i = 0;i < nbCache;i++) {
                   3325:                    if (oldNs[i] == attr->ns) {
                   3326:                        node->ns = newNs[i];
                   3327:                        break;
                   3328:                    }
                   3329:                }
                   3330:                if (i == nbCache) {
                   3331:                    /*
                   3332:                     * Ok we need to recreate a new namespace definition
                   3333:                     */
                   3334:                    n = xmlNewReconciliedNs(doc, tree, attr->ns);
                   3335:                    if (n != NULL) { /* :-( what if else ??? */
                   3336:                        /*
                   3337:                         * check if we need to grow the cache buffers.
                   3338:                         */
                   3339:                        if (sizeCache <= nbCache) {
                   3340:                            sizeCache *= 2;
                   3341:                            oldNs = (xmlNsPtr *) xmlRealloc(oldNs, sizeCache *
                   3342:                                                           sizeof(xmlNsPtr));
                   3343:                            if (oldNs == NULL) {
                   3344:                                fprintf(stderr,
                   3345:                                        "xmlReconciliateNs : memory pbm\n");
                   3346:                                xmlFree(newNs);
                   3347:                                return(-1);
                   3348:                            }
                   3349:                            newNs = (xmlNsPtr *) xmlRealloc(newNs, sizeCache *
                   3350:                                                           sizeof(xmlNsPtr));
                   3351:                            if (newNs == NULL) {
                   3352:                                fprintf(stderr,
                   3353:                                        "xmlReconciliateNs : memory pbm\n");
                   3354:                                xmlFree(oldNs);
                   3355:                                return(-1);
                   3356:                            }
                   3357:                        }
                   3358:                        newNs[nbCache] = n;
                   3359:                        oldNs[nbCache++] = attr->ns;
                   3360:                        attr->ns = n;
                   3361:                    }
                   3362:                }
                   3363:            }
                   3364:            attr = attr->next;
                   3365:        }
                   3366: 
                   3367:        /*
                   3368:         * Browse the full subtree, deep first
                   3369:         */
1.90      daniel   3370:         if (node->children != NULL) {
1.82      daniel   3371:            /* deep first */
1.90      daniel   3372:            node = node->children;
1.82      daniel   3373:        } else if ((node != tree) && (node->next != NULL)) {
                   3374:            /* then siblings */
                   3375:            node = node->next;
                   3376:        } else if (node != tree) {
                   3377:            /* go up to parents->next if needed */
                   3378:            while (node != tree) {
                   3379:                if (node->parent != NULL)
                   3380:                    node = node->parent;
                   3381:                if ((node != tree) && (node->next != NULL)) {
                   3382:                    node = node->next;
                   3383:                    break;
                   3384:                }
                   3385:                if (node->parent == NULL) {
                   3386:                    node = NULL;
                   3387:                    break;
                   3388:                }
                   3389:            }
                   3390:            /* exit condition */
                   3391:            if (node == tree) 
                   3392:                node = NULL;
1.19      daniel   3393:        }
1.3       veillard 3394:     }
1.82      daniel   3395:     return(ret);
1.3       veillard 3396: }
                   3397: 
1.23      daniel   3398: /**
                   3399:  * xmlGetProp:
                   3400:  * @node:  the node
                   3401:  * @name:  the attribute name
                   3402:  *
                   3403:  * Search and get the value of an attribute associated to a node
                   3404:  * This does the entity substitution.
1.74      daniel   3405:  * This function looks in DTD attribute declaration for #FIXED or
                   3406:  * default declaration values unless DTD use has been turned off.
                   3407:  *
1.36      daniel   3408:  * Returns the attribute value or NULL if not found.
1.69      daniel   3409:  *     It's up to the caller to free the memory.
1.9       veillard 3410:  */
1.69      daniel   3411: xmlChar *
                   3412: xmlGetProp(xmlNodePtr node, const xmlChar *name) {
1.74      daniel   3413:     xmlAttrPtr prop;
                   3414:     xmlDocPtr doc;
1.9       veillard 3415: 
1.74      daniel   3416:     if ((node == NULL) || (name == NULL)) return(NULL);
                   3417:     /*
                   3418:      * Check on the properties attached to the node
                   3419:      */
                   3420:     prop = node->properties;
1.9       veillard 3421:     while (prop != NULL) {
1.34      daniel   3422:         if (!xmlStrcmp(prop->name, name))  {
1.61      daniel   3423:            xmlChar *ret;
1.34      daniel   3424: 
1.90      daniel   3425:            ret = xmlNodeListGetString(node->doc, prop->children, 1);
1.61      daniel   3426:            if (ret == NULL) return(xmlStrdup((xmlChar *)""));
1.34      daniel   3427:            return(ret);
                   3428:         }
1.9       veillard 3429:        prop = prop->next;
                   3430:     }
1.74      daniel   3431:     if (!xmlCheckDTD) return(NULL);
                   3432: 
                   3433:     /*
                   3434:      * Check if there is a default declaration in the internal
                   3435:      * or external subsets
                   3436:      */
                   3437:     doc =  node->doc;
                   3438:     if (doc != NULL) {
                   3439:         xmlAttributePtr attrDecl;
                   3440:         if (doc->intSubset != NULL) {
                   3441:            attrDecl = xmlGetDtdAttrDesc(doc->intSubset, node->name, name);
                   3442:            if ((attrDecl == NULL) && (doc->extSubset != NULL))
                   3443:                attrDecl = xmlGetDtdAttrDesc(doc->extSubset, node->name, name);
1.86      daniel   3444:            if (attrDecl != NULL)
                   3445:                return(xmlStrdup(attrDecl->defaultValue));
1.74      daniel   3446:        }
                   3447:     }
1.10      veillard 3448:     return(NULL);
1.13      daniel   3449: }
                   3450: 
1.23      daniel   3451: /**
1.73      daniel   3452:  * xmlGetNsProp:
                   3453:  * @node:  the node
                   3454:  * @name:  the attribute name
                   3455:  * @namespace:  the URI of the namespace
                   3456:  *
                   3457:  * Search and get the value of an attribute associated to a node
                   3458:  * This attribute has to be anchored in the namespace specified.
                   3459:  * This does the entity substitution.
1.74      daniel   3460:  * This function looks in DTD attribute declaration for #FIXED or
                   3461:  * default declaration values unless DTD use has been turned off.
1.73      daniel   3462:  *
                   3463:  * Returns the attribute value or NULL if not found.
                   3464:  *     It's up to the caller to free the memory.
                   3465:  */
                   3466: xmlChar *
                   3467: xmlGetNsProp(xmlNodePtr node, const xmlChar *name, const xmlChar *namespace) {
                   3468:     xmlAttrPtr prop = node->properties;
1.74      daniel   3469:     xmlDocPtr doc;
                   3470:     xmlNsPtr ns;
1.73      daniel   3471: 
                   3472:     if (namespace == NULL)
                   3473:        return(xmlGetProp(node, name));
                   3474:     while (prop != NULL) {
1.79      daniel   3475:        /*
                   3476:         * One need to have
                   3477:         *   - same attribute names
                   3478:         *   - and the attribute carrying that namespace
                   3479:         *         or
                   3480:         *         no namespace on the attribute and the element carrying it
                   3481:         */
1.73      daniel   3482:         if ((!xmlStrcmp(prop->name, name)) &&
1.79      daniel   3483:            (((prop->ns == NULL) && (node->ns != NULL) &&
                   3484:              (!xmlStrcmp(node->ns->href, namespace))) ||
1.81      daniel   3485:             ((prop->ns != NULL) && (!xmlStrcmp(prop->ns->href, namespace))))) {
1.73      daniel   3486:            xmlChar *ret;
                   3487: 
1.90      daniel   3488:            ret = xmlNodeListGetString(node->doc, prop->children, 1);
1.73      daniel   3489:            if (ret == NULL) return(xmlStrdup((xmlChar *)""));
                   3490:            return(ret);
                   3491:         }
                   3492:        prop = prop->next;
                   3493:     }
1.74      daniel   3494:     if (!xmlCheckDTD) return(NULL);
                   3495: 
                   3496:     /*
                   3497:      * Check if there is a default declaration in the internal
                   3498:      * or external subsets
                   3499:      */
                   3500:     doc =  node->doc;
                   3501:     if (doc != NULL) {
                   3502:         xmlAttributePtr attrDecl;
                   3503:         if (doc->intSubset != NULL) {
                   3504:            attrDecl = xmlGetDtdAttrDesc(doc->intSubset, node->name, name);
                   3505:            if ((attrDecl == NULL) && (doc->extSubset != NULL))
                   3506:                attrDecl = xmlGetDtdAttrDesc(doc->extSubset, node->name, name);
                   3507:                
                   3508:            if (attrDecl->prefix != NULL) {
                   3509:                /*
                   3510:                 * The DTD declaration only allows a prefix search
                   3511:                 */
                   3512:                ns = xmlSearchNs(doc, node, attrDecl->prefix);
                   3513:                if ((ns != NULL) && (!xmlStrcmp(ns->href, namespace)))
                   3514:                    return(xmlStrdup(attrDecl->defaultValue));
                   3515:            }
                   3516:        }
                   3517:     }
1.73      daniel   3518:     return(NULL);
                   3519: }
                   3520: 
                   3521: /**
1.23      daniel   3522:  * xmlSetProp:
                   3523:  * @node:  the node
                   3524:  * @name:  the attribute name
                   3525:  * @value:  the attribute value
                   3526:  *
                   3527:  * Set (or reset) an attribute carried by a node.
1.36      daniel   3528:  * Returns the attribute pointer.
1.13      daniel   3529:  */
1.28      daniel   3530: xmlAttrPtr
1.61      daniel   3531: xmlSetProp(xmlNodePtr node, const xmlChar *name, const xmlChar *value) {
1.20      daniel   3532:     xmlAttrPtr prop = node->properties;
1.13      daniel   3533: 
                   3534:     while (prop != NULL) {
                   3535:         if (!xmlStrcmp(prop->name, name)) {
1.90      daniel   3536:            if (prop->children != NULL) 
                   3537:                xmlFreeNodeList(prop->children);
                   3538:            prop->children = NULL;
1.67      daniel   3539:            if (value != NULL) {
                   3540:                xmlChar *buffer;
1.94      daniel   3541:                xmlNodePtr tmp;
                   3542: 
1.67      daniel   3543:                buffer = xmlEncodeEntitiesReentrant(node->doc, value);
1.90      daniel   3544:                prop->children = xmlStringGetNodeList(node->doc, buffer);
1.94      daniel   3545:                tmp = prop->children;
                   3546:                while (tmp != NULL) {
                   3547:                    tmp->parent = (xmlNodePtr) prop;
                   3548:                    if (tmp->next == NULL)
                   3549:                        prop->last = tmp;
                   3550:                    tmp = tmp->next;
                   3551:                }
1.67      daniel   3552:                xmlFree(buffer);
                   3553:            }   
1.13      daniel   3554:            return(prop);
                   3555:        }
                   3556:        prop = prop->next;
                   3557:     }
                   3558:     prop = xmlNewProp(node, name, value);
                   3559:     return(prop);
1.9       veillard 3560: }
                   3561: 
1.23      daniel   3562: /**
                   3563:  * xmlNodeIsText:
                   3564:  * @node:  the node
                   3565:  * 
                   3566:  * Is this node a Text node ?
1.36      daniel   3567:  * Returns 1 yes, 0 no
1.21      daniel   3568:  */
1.28      daniel   3569: int
                   3570: xmlNodeIsText(xmlNodePtr node) {
1.21      daniel   3571:     if (node == NULL) return(0);
                   3572: 
1.23      daniel   3573:     if (node->type == XML_TEXT_NODE) return(1);
1.21      daniel   3574:     return(0);
                   3575: }
                   3576: 
1.23      daniel   3577: /**
1.99      daniel   3578:  * xmlIsBlankNode:
                   3579:  * @node:  the node
                   3580:  * 
                   3581:  * Is this node a Text node ?
                   3582:  * Returns 1 yes, 0 no
                   3583:  */
                   3584: int
                   3585: xmlIsBlankNode(xmlNodePtr node) {
                   3586:     xmlChar *cur;
                   3587:     if (node == NULL) return(0);
                   3588: 
                   3589:     if (node->type != XML_TEXT_NODE) return(0);
                   3590:     if (node->content == NULL) return(0);
                   3591:     cur = node->content;
                   3592:     while (*cur != 0) {
                   3593:        if (!IS_BLANK(*cur)) return(0);
                   3594:        cur++;
                   3595:     }
                   3596: 
                   3597:     return(1);
                   3598: }
                   3599: 
                   3600: /**
1.36      daniel   3601:  * xmlTextConcat:
1.23      daniel   3602:  * @node:  the node
                   3603:  * @content:  the content
                   3604:  * @len:  @content lenght
                   3605:  * 
                   3606:  * Concat the given string at the end of the existing node content
1.21      daniel   3607:  */
1.23      daniel   3608: 
1.28      daniel   3609: void
1.61      daniel   3610: xmlTextConcat(xmlNodePtr node, const xmlChar *content, int len) {
1.21      daniel   3611:     if (node == NULL) return;
                   3612: 
1.82      daniel   3613:     if ((node->type != XML_TEXT_NODE) &&
                   3614:         (node->type != XML_CDATA_SECTION_NODE)) {
1.86      daniel   3615: #ifdef DEBUG_TREE
1.82      daniel   3616:        fprintf(stderr, "xmlTextConcat: node is not text nor cdata\n");
1.86      daniel   3617: #endif
1.21      daniel   3618:         return;
                   3619:     }
1.70      daniel   3620: #ifndef XML_USE_BUFFER_CONTENT
1.21      daniel   3621:     node->content = xmlStrncat(node->content, content, len);
1.70      daniel   3622: #else
                   3623:     xmlBufferAdd(node->content, content, len);
                   3624: #endif
1.21      daniel   3625: }
                   3626: 
1.1       veillard 3627: /************************************************************************
                   3628:  *                                                                     *
1.8       veillard 3629:  *                     Output : to a FILE or in memory                 *
1.1       veillard 3630:  *                                                                     *
                   3631:  ************************************************************************/
                   3632: 
1.38      daniel   3633: #define BASE_BUFFER_SIZE 4000
1.8       veillard 3634: 
1.23      daniel   3635: /**
1.38      daniel   3636:  * xmlBufferCreate:
                   3637:  *
                   3638:  * routine to create an XML buffer.
                   3639:  * returns the new structure.
                   3640:  */
                   3641: xmlBufferPtr
                   3642: xmlBufferCreate(void) {
                   3643:     xmlBufferPtr ret;
                   3644: 
1.57      daniel   3645:     ret = (xmlBufferPtr) xmlMalloc(sizeof(xmlBuffer));
1.38      daniel   3646:     if (ret == NULL) {
                   3647:        fprintf(stderr, "xmlBufferCreate : out of memory!\n");
                   3648:         return(NULL);
                   3649:     }
                   3650:     ret->use = 0;
                   3651:     ret->size = BASE_BUFFER_SIZE;
1.72      daniel   3652:     ret->alloc = xmlBufferAllocScheme;
1.61      daniel   3653:     ret->content = (xmlChar *) xmlMalloc(ret->size * sizeof(xmlChar));
1.38      daniel   3654:     if (ret->content == NULL) {
                   3655:        fprintf(stderr, "xmlBufferCreate : out of memory!\n");
1.57      daniel   3656:        xmlFree(ret);
1.38      daniel   3657:         return(NULL);
                   3658:     }
                   3659:     ret->content[0] = 0;
                   3660:     return(ret);
                   3661: }
                   3662: 
                   3663: /**
1.70      daniel   3664:  * xmlBufferCreateSize:
                   3665:  * @size: initial size of buffer
                   3666:  *
                   3667:  * routine to create an XML buffer.
                   3668:  * returns the new structure.
                   3669:  */
                   3670: xmlBufferPtr
                   3671: xmlBufferCreateSize(size_t size) {
                   3672:     xmlBufferPtr ret;
                   3673: 
                   3674:     ret = (xmlBufferPtr) xmlMalloc(sizeof(xmlBuffer));
                   3675:     if (ret == NULL) {
                   3676:         fprintf(stderr, "xmlBufferCreate : out of memory!\n");
                   3677:         return(NULL);
                   3678:     }
                   3679:     ret->use = 0;
1.72      daniel   3680:     ret->alloc = xmlBufferAllocScheme;
1.70      daniel   3681:     ret->size = (size ? size+2 : 0);         /* +1 for ending null */
1.72      daniel   3682:     if (ret->size){
1.70      daniel   3683:         ret->content = (xmlChar *) xmlMalloc(ret->size * sizeof(xmlChar));
                   3684:         if (ret->content == NULL) {
                   3685:             fprintf(stderr, "xmlBufferCreate : out of memory!\n");
                   3686:             xmlFree(ret);
                   3687:             return(NULL);
                   3688:         }
                   3689:         ret->content[0] = 0;
                   3690:     } else
                   3691:        ret->content = NULL;
                   3692:     return(ret);
                   3693: }
                   3694: 
                   3695: /**
                   3696:  * xmlBufferAllocationScheme:
                   3697:  * @buf:  the buffer to free
                   3698:  * @scheme:  allocation scheme to use
                   3699:  *
                   3700:  * Sets the allocation scheme for this buffer
                   3701:  */
                   3702: void
                   3703: xmlBufferSetAllocationScheme(xmlBufferPtr buf, 
                   3704:                              xmlBufferAllocationScheme scheme) {
                   3705:     if (buf == NULL) {
1.86      daniel   3706: #ifdef DEBUG_BUFFER
1.70      daniel   3707:         fprintf(stderr, "xmlBufferSetAllocationScheme: buf == NULL\n");
1.86      daniel   3708: #endif
1.70      daniel   3709:         return;
                   3710:     }
                   3711: 
                   3712:     buf->alloc = scheme;
                   3713: }
                   3714: 
                   3715: /**
1.38      daniel   3716:  * xmlBufferFree:
                   3717:  * @buf:  the buffer to free
                   3718:  *
                   3719:  * Frees an XML buffer.
                   3720:  */
                   3721: void
                   3722: xmlBufferFree(xmlBufferPtr buf) {
                   3723:     if (buf == NULL) {
1.86      daniel   3724: #ifdef DEBUG_BUFFER
1.38      daniel   3725:         fprintf(stderr, "xmlBufferFree: buf == NULL\n");
1.86      daniel   3726: #endif
1.38      daniel   3727:        return;
                   3728:     }
1.71      daniel   3729:     if (buf->content != NULL) {
1.70      daniel   3730: #ifndef XML_USE_BUFFER_CONTENT
1.38      daniel   3731:         memset(buf->content, -1, BASE_BUFFER_SIZE);
1.70      daniel   3732: #else
                   3733:         memset(buf->content, -1, buf->size);
                   3734: #endif
1.57      daniel   3735:         xmlFree(buf->content);
1.38      daniel   3736:     }
                   3737:     memset(buf, -1, sizeof(xmlBuffer));
1.57      daniel   3738:     xmlFree(buf);
1.38      daniel   3739: }
                   3740: 
                   3741: /**
1.47      daniel   3742:  * xmlBufferEmpty:
                   3743:  * @buf:  the buffer
                   3744:  *
                   3745:  * empty a buffer.
                   3746:  */
                   3747: void
                   3748: xmlBufferEmpty(xmlBufferPtr buf) {
                   3749:     buf->use = 0;
                   3750:     memset(buf->content, -1, buf->size);/* just for debug */
                   3751: }
                   3752: 
                   3753: /**
                   3754:  * xmlBufferShrink:
                   3755:  * @buf:  the buffer to dump
1.61      daniel   3756:  * @len:  the number of xmlChar to remove
1.47      daniel   3757:  *
                   3758:  * Remove the beginning of an XML buffer.
                   3759:  *
1.61      daniel   3760:  * Returns the number of xmlChar removed, or -1 in case of failure.
1.47      daniel   3761:  */
                   3762: int
                   3763: xmlBufferShrink(xmlBufferPtr buf, int len) {
                   3764:     if (len == 0) return(0);
                   3765:     if (len > buf->use) return(-1);
                   3766: 
                   3767:     buf->use -= len;
1.61      daniel   3768:     memmove(buf->content, &buf->content[len], buf->use * sizeof(xmlChar));
1.47      daniel   3769: 
                   3770:     buf->content[buf->use] = 0;
                   3771:     return(len);
                   3772: }
                   3773: 
                   3774: /**
1.38      daniel   3775:  * xmlBufferDump:
                   3776:  * @file:  the file output
                   3777:  * @buf:  the buffer to dump
                   3778:  *
                   3779:  * Dumps an XML buffer to  a FILE *.
1.61      daniel   3780:  * Returns the number of xmlChar written
1.38      daniel   3781:  */
                   3782: int
                   3783: xmlBufferDump(FILE *file, xmlBufferPtr buf) {
                   3784:     int ret;
                   3785: 
                   3786:     if (buf == NULL) {
1.86      daniel   3787: #ifdef DEBUG_BUFFER
1.38      daniel   3788:         fprintf(stderr, "xmlBufferDump: buf == NULL\n");
1.86      daniel   3789: #endif
1.38      daniel   3790:        return(0);
                   3791:     }
                   3792:     if (buf->content == NULL) {
1.86      daniel   3793: #ifdef DEBUG_BUFFER
1.38      daniel   3794:         fprintf(stderr, "xmlBufferDump: buf->content == NULL\n");
1.86      daniel   3795: #endif
1.38      daniel   3796:        return(0);
                   3797:     }
                   3798:     if (file == NULL) file = stdout;
1.61      daniel   3799:     ret = fwrite(buf->content, sizeof(xmlChar), buf->use, file);
1.38      daniel   3800:     return(ret);
                   3801: }
                   3802: 
                   3803: /**
1.70      daniel   3804:  * xmlBufferContent:
                   3805:  * @buf:  the buffer to resize
                   3806:  *
                   3807:  * Returns the internal content
                   3808:  */
                   3809: 
                   3810: const xmlChar* 
                   3811: xmlBufferContent(const xmlBufferPtr buf)
                   3812: {
                   3813:     if(!buf)
                   3814:         return NULL;
                   3815: 
                   3816:     return buf->content;
                   3817: }
                   3818: 
                   3819: /**
                   3820:  * xmlBufferLength:
                   3821:  * @buf:  the buffer 
                   3822:  *
                   3823:  * Returns the length of data in the internal content
                   3824:  */
                   3825: 
                   3826: int
                   3827: xmlBufferLength(const xmlBufferPtr buf)
                   3828: {
                   3829:     if(!buf)
                   3830:         return 0;
                   3831: 
                   3832:     return buf->use;
                   3833: }
                   3834: 
                   3835: /**
                   3836:  * xmlBufferResize:
                   3837:  * @buf:  the buffer to resize
                   3838:  * @len:  the desired size
                   3839:  *
                   3840:  * Resize a buffer to accomodate minimum size of <len>.
                   3841:  *
                   3842:  * Returns  0 in case of problems, 1 otherwise
                   3843:  */
                   3844: int
                   3845: xmlBufferResize(xmlBufferPtr buf, int size)
                   3846: {
                   3847:     int newSize = (buf->size ? buf->size*2 : size);/*take care of empty case*/
                   3848:     xmlChar* rebuf = NULL;
                   3849: 
                   3850:     /* Don't resize if we don't have to */
                   3851:     if(size < buf->size)
                   3852:         return 1;
                   3853: 
                   3854:     /* figure out new size */
                   3855:     switch(buf->alloc){
                   3856:     case XML_BUFFER_ALLOC_DOUBLEIT:
                   3857:         while(size > newSize) newSize *= 2;
                   3858:         break;
                   3859:     case XML_BUFFER_ALLOC_EXACT:
                   3860:         newSize = size+10;
                   3861:         break;
                   3862:     default:
                   3863:         newSize = size+10;
                   3864:         break;
                   3865:     }
                   3866: 
                   3867:     if (buf->content == NULL)
                   3868:        rebuf = (xmlChar *) xmlMalloc(newSize * sizeof(xmlChar));
                   3869:     else
                   3870:        rebuf = (xmlChar *) xmlRealloc(buf->content, 
                   3871:                                       newSize * sizeof(xmlChar));
                   3872:     if (rebuf == NULL) {
                   3873:         fprintf(stderr, "xmlBufferAdd : out of memory!\n");
                   3874:         return 0;
                   3875:     }
                   3876:     buf->content = rebuf;
                   3877:     buf->size = newSize;
                   3878: 
                   3879:     return 1;
                   3880: }
                   3881: /**
1.38      daniel   3882:  * xmlBufferAdd:
                   3883:  * @buf:  the buffer to dump
1.61      daniel   3884:  * @str:  the xmlChar string
                   3885:  * @len:  the number of xmlChar to add
1.38      daniel   3886:  *
1.74      daniel   3887:  * Add a string range to an XML buffer. if len == -1, the lenght of
                   3888:  * str is recomputed.
1.38      daniel   3889:  */
                   3890: void
1.61      daniel   3891: xmlBufferAdd(xmlBufferPtr buf, const xmlChar *str, int len) {
1.89      daniel   3892:     int needSize;
1.38      daniel   3893: 
                   3894:     if (str == NULL) {
1.86      daniel   3895: #ifdef DEBUG_BUFFER
1.38      daniel   3896:         fprintf(stderr, "xmlBufferAdd: str == NULL\n");
1.86      daniel   3897: #endif
1.38      daniel   3898:        return;
                   3899:     }
1.74      daniel   3900:     if (len < -1) {
1.86      daniel   3901: #ifdef DEBUG_BUFFER
1.74      daniel   3902:         fprintf(stderr, "xmlBufferAdd: len < 0\n");
1.86      daniel   3903: #endif
1.74      daniel   3904:        return;
                   3905:     }
                   3906:     if (len == 0) return;
1.70      daniel   3907: 
1.82      daniel   3908:     if (len < 0)
1.89      daniel   3909:         len = xmlStrlen(str);
1.70      daniel   3910: 
1.47      daniel   3911:     if (len <= 0) return;
                   3912: 
1.70      daniel   3913:     needSize = buf->use + len + 2;
                   3914:     if(needSize > buf->size){
                   3915:         if(!xmlBufferResize(buf, needSize)){
                   3916:             fprintf(stderr, "xmlBufferAdd : out of memory!\n");
                   3917:             return;
                   3918:         }
                   3919:     }
1.47      daniel   3920: 
1.70      daniel   3921:     memmove(&buf->content[buf->use], str, len*sizeof(xmlChar));
1.47      daniel   3922:     buf->use += len;
                   3923:     buf->content[buf->use] = 0;
1.38      daniel   3924: }
                   3925: 
                   3926: /**
                   3927:  * xmlBufferCat:
                   3928:  * @buf:  the buffer to dump
1.61      daniel   3929:  * @str:  the xmlChar string
1.23      daniel   3930:  *
1.38      daniel   3931:  * Append a zero terminated string to an XML buffer.
1.23      daniel   3932:  */
1.28      daniel   3933: void
1.61      daniel   3934: xmlBufferCat(xmlBufferPtr buf, const xmlChar *str) {
1.70      daniel   3935:     if (str != NULL)
                   3936:        xmlBufferAdd(buf, str, -1);
1.8       veillard 3937: }
                   3938: 
1.23      daniel   3939: /**
1.38      daniel   3940:  * xmlBufferCCat:
                   3941:  * @buf:  the buffer to dump
                   3942:  * @str:  the C char string
1.23      daniel   3943:  *
1.38      daniel   3944:  * Append a zero terminated C string to an XML buffer.
1.23      daniel   3945:  */
1.28      daniel   3946: void
1.38      daniel   3947: xmlBufferCCat(xmlBufferPtr buf, const char *str) {
1.21      daniel   3948:     const char *cur;
1.8       veillard 3949: 
1.38      daniel   3950:     if (str == NULL) {
1.86      daniel   3951: #ifdef DEBUG_BUFFER
1.38      daniel   3952:         fprintf(stderr, "xmlBufferAdd: str == NULL\n");
1.86      daniel   3953: #endif
1.38      daniel   3954:        return;
                   3955:     }
                   3956:     for (cur = str;*cur != 0;cur++) {
                   3957:         if (buf->use  + 10 >= buf->size) {
1.70      daniel   3958:             if(!xmlBufferResize(buf, buf->use+10)){
                   3959:                 fprintf(stderr, "xmlBufferCCat : out of memory!\n");
                   3960:                 return;
                   3961:             }
                   3962:         }
1.38      daniel   3963:         buf->content[buf->use++] = *cur;
1.8       veillard 3964:     }
                   3965: }
                   3966: 
1.23      daniel   3967: /**
1.38      daniel   3968:  * xmlBufferWriteCHAR:
                   3969:  * @buf:  the XML buffer
                   3970:  * @string:  the string to add
                   3971:  *
                   3972:  * routine which manage and grows an output buffer. This one add
1.61      daniel   3973:  * xmlChars at the end of the buffer.
1.38      daniel   3974:  */
                   3975: void
1.61      daniel   3976: xmlBufferWriteCHAR(xmlBufferPtr buf, const xmlChar *string) {
1.38      daniel   3977:     xmlBufferCat(buf, string);
                   3978: }
                   3979: 
                   3980: /**
                   3981:  * xmlBufferWriteChar:
1.42      daniel   3982:  * @buf:  the XML buffer output
1.38      daniel   3983:  * @string:  the string to add
                   3984:  *
                   3985:  * routine which manage and grows an output buffer. This one add
                   3986:  * C chars at the end of the array.
                   3987:  */
                   3988: void
                   3989: xmlBufferWriteChar(xmlBufferPtr buf, const char *string) {
                   3990:     xmlBufferCCat(buf, string);
                   3991: }
                   3992: 
                   3993: 
                   3994: /**
1.43      daniel   3995:  * xmlBufferWriteQuotedString:
                   3996:  * @buf:  the XML buffer output
                   3997:  * @string:  the string to add
                   3998:  *
                   3999:  * routine which manage and grows an output buffer. This one writes
1.61      daniel   4000:  * a quoted or double quoted xmlChar string, checking first if it holds
1.43      daniel   4001:  * quote or double-quotes internally
                   4002:  */
                   4003: void
1.61      daniel   4004: xmlBufferWriteQuotedString(xmlBufferPtr buf, const xmlChar *string) {
1.53      daniel   4005:     if (xmlStrchr(string, '"')) {
                   4006:         if (xmlStrchr(string, '\'')) {
1.86      daniel   4007: #ifdef DEBUG_BUFFER
1.43      daniel   4008:            fprintf(stderr,
                   4009:  "xmlBufferWriteQuotedString: string contains quote and double-quotes !\n");
1.86      daniel   4010: #endif
1.43      daniel   4011:        }
                   4012:         xmlBufferCCat(buf, "'");
                   4013:         xmlBufferCat(buf, string);
                   4014:         xmlBufferCCat(buf, "'");
                   4015:     } else {
                   4016:         xmlBufferCCat(buf, "\"");
                   4017:         xmlBufferCat(buf, string);
                   4018:         xmlBufferCCat(buf, "\"");
                   4019:     }
                   4020: }
                   4021: 
                   4022: 
1.99      daniel   4023: static void
                   4024: xmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
                   4025:             int format);
                   4026: static void
                   4027: xmlNodeListDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
                   4028:                 int format);
                   4029: void
                   4030: htmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur);
                   4031: 
1.43      daniel   4032: /**
1.23      daniel   4033:  * xmlGlobalNsDump:
1.42      daniel   4034:  * @buf:  the XML buffer output
1.23      daniel   4035:  * @cur:  a namespace
                   4036:  *
                   4037:  * Dump a global Namespace, this is the old version based on PIs.
1.1       veillard 4038:  */
1.28      daniel   4039: static void
1.38      daniel   4040: xmlGlobalNsDump(xmlBufferPtr buf, xmlNsPtr cur) {
1.1       veillard 4041:     if (cur == NULL) {
1.86      daniel   4042: #ifdef DEBUG_TREE
1.19      daniel   4043:         fprintf(stderr, "xmlGlobalNsDump : Ns == NULL\n");
1.86      daniel   4044: #endif
1.1       veillard 4045:        return;
                   4046:     }
1.19      daniel   4047:     if (cur->type == XML_GLOBAL_NAMESPACE) {
1.38      daniel   4048:        xmlBufferWriteChar(buf, "<?namespace");
1.12      daniel   4049:        if (cur->href != NULL) {
1.43      daniel   4050:            xmlBufferWriteChar(buf, " href=");
                   4051:            xmlBufferWriteQuotedString(buf, cur->href);
1.12      daniel   4052:        }
1.16      daniel   4053:        if (cur->prefix != NULL) {
1.43      daniel   4054:            xmlBufferWriteChar(buf, " AS=");
                   4055:            xmlBufferWriteQuotedString(buf, cur->prefix);
1.12      daniel   4056:        }
1.38      daniel   4057:        xmlBufferWriteChar(buf, "?>\n");
1.19      daniel   4058:     }
                   4059: }
                   4060: 
1.23      daniel   4061: /**
                   4062:  * xmlGlobalNsListDump:
1.42      daniel   4063:  * @buf:  the XML buffer output
1.23      daniel   4064:  * @cur:  the first namespace
                   4065:  *
                   4066:  * Dump a list of global Namespace, this is the old version based on PIs.
1.19      daniel   4067:  */
1.28      daniel   4068: static void
1.38      daniel   4069: xmlGlobalNsListDump(xmlBufferPtr buf, xmlNsPtr cur) {
1.19      daniel   4070:     while (cur != NULL) {
1.38      daniel   4071:         xmlGlobalNsDump(buf, cur);
1.19      daniel   4072:        cur = cur->next;
                   4073:     }
                   4074: }
                   4075: 
1.23      daniel   4076: /**
                   4077:  * xmlNsDump:
1.42      daniel   4078:  * @buf:  the XML buffer output
1.23      daniel   4079:  * @cur:  a namespace
                   4080:  *
1.19      daniel   4081:  * Dump a local Namespace definition.
1.23      daniel   4082:  * Should be called in the context of attributes dumps.
1.19      daniel   4083:  */
1.28      daniel   4084: static void
1.38      daniel   4085: xmlNsDump(xmlBufferPtr buf, xmlNsPtr cur) {
1.19      daniel   4086:     if (cur == NULL) {
1.86      daniel   4087: #ifdef DEBUG_TREE
1.19      daniel   4088:         fprintf(stderr, "xmlNsDump : Ns == NULL\n");
1.86      daniel   4089: #endif
1.19      daniel   4090:        return;
                   4091:     }
                   4092:     if (cur->type == XML_LOCAL_NAMESPACE) {
                   4093:         /* Within the context of an element attributes */
1.16      daniel   4094:        if (cur->prefix != NULL) {
1.38      daniel   4095:            xmlBufferWriteChar(buf, " xmlns:");
                   4096:            xmlBufferWriteCHAR(buf, cur->prefix);
1.19      daniel   4097:        } else
1.38      daniel   4098:            xmlBufferWriteChar(buf, " xmlns");
1.43      daniel   4099:        xmlBufferWriteChar(buf, "=");
                   4100:        xmlBufferWriteQuotedString(buf, cur->href);
1.19      daniel   4101:     }
                   4102: }
                   4103: 
1.23      daniel   4104: /**
                   4105:  * xmlNsListDump:
1.42      daniel   4106:  * @buf:  the XML buffer output
1.23      daniel   4107:  * @cur:  the first namespace
                   4108:  *
                   4109:  * Dump a list of local Namespace definitions.
                   4110:  * Should be called in the context of attributes dumps.
1.19      daniel   4111:  */
1.28      daniel   4112: static void
1.38      daniel   4113: xmlNsListDump(xmlBufferPtr buf, xmlNsPtr cur) {
1.19      daniel   4114:     while (cur != NULL) {
1.38      daniel   4115:         xmlNsDump(buf, cur);
1.19      daniel   4116:        cur = cur->next;
1.8       veillard 4117:     }
1.1       veillard 4118: }
                   4119: 
1.23      daniel   4120: /**
                   4121:  * xmlDtdDump:
1.42      daniel   4122:  * @buf:  the XML buffer output
1.23      daniel   4123:  * @doc:  the document
                   4124:  * 
                   4125:  * Dump the XML document DTD, if any.
1.17      daniel   4126:  */
1.28      daniel   4127: static void
1.92      daniel   4128: xmlDtdDump(xmlBufferPtr buf, xmlDtdPtr dtd) {
                   4129:     if (dtd == NULL) {
1.86      daniel   4130: #ifdef DEBUG_TREE
1.31      daniel   4131:         fprintf(stderr, "xmlDtdDump : no internal subset\n");
1.86      daniel   4132: #endif
1.17      daniel   4133:        return;
                   4134:     }
1.38      daniel   4135:     xmlBufferWriteChar(buf, "<!DOCTYPE ");
1.92      daniel   4136:     xmlBufferWriteCHAR(buf, dtd->name);
                   4137:     if (dtd->ExternalID != NULL) {
1.43      daniel   4138:        xmlBufferWriteChar(buf, " PUBLIC ");
1.92      daniel   4139:        xmlBufferWriteQuotedString(buf, dtd->ExternalID);
1.43      daniel   4140:        xmlBufferWriteChar(buf, " ");
1.92      daniel   4141:        xmlBufferWriteQuotedString(buf, dtd->SystemID);
                   4142:     }  else if (dtd->SystemID != NULL) {
1.43      daniel   4143:        xmlBufferWriteChar(buf, " SYSTEM ");
1.92      daniel   4144:        xmlBufferWriteQuotedString(buf, dtd->SystemID);
1.17      daniel   4145:     }
1.92      daniel   4146:     if ((dtd->entities == NULL) && (dtd->elements == NULL) &&
                   4147:         (dtd->attributes == NULL) && (dtd->notations == NULL)) {
                   4148:        xmlBufferWriteChar(buf, ">");
1.21      daniel   4149:        return;
                   4150:     }
1.38      daniel   4151:     xmlBufferWriteChar(buf, " [\n");
1.99      daniel   4152:     xmlNodeListDump(buf, dtd->doc, dtd->children, -1, 0);
                   4153: #if 0
1.92      daniel   4154:     if (dtd->entities != NULL)
                   4155:        xmlDumpEntitiesTable(buf, (xmlEntitiesTablePtr) dtd->entities);
                   4156:     if (dtd->notations != NULL)
                   4157:        xmlDumpNotationTable(buf, (xmlNotationTablePtr) dtd->notations);
                   4158:     if (dtd->elements != NULL)
                   4159:        xmlDumpElementTable(buf, (xmlElementTablePtr) dtd->elements);
                   4160:     if (dtd->attributes != NULL)
                   4161:        xmlDumpAttributeTable(buf, (xmlAttributeTablePtr) dtd->attributes);
1.99      daniel   4162: #endif
                   4163:     xmlBufferWriteChar(buf, "]>");
1.17      daniel   4164: }
                   4165: 
1.23      daniel   4166: /**
                   4167:  * xmlAttrDump:
1.42      daniel   4168:  * @buf:  the XML buffer output
1.23      daniel   4169:  * @doc:  the document
                   4170:  * @cur:  the attribute pointer
                   4171:  *
                   4172:  * Dump an XML attribute
1.1       veillard 4173:  */
1.28      daniel   4174: static void
1.38      daniel   4175: xmlAttrDump(xmlBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur) {
1.61      daniel   4176:     xmlChar *value;
1.1       veillard 4177: 
                   4178:     if (cur == NULL) {
1.86      daniel   4179: #ifdef DEBUG_TREE
1.20      daniel   4180:         fprintf(stderr, "xmlAttrDump : property == NULL\n");
1.86      daniel   4181: #endif
1.1       veillard 4182:        return;
                   4183:     }
1.38      daniel   4184:     xmlBufferWriteChar(buf, " ");
1.56      daniel   4185:     if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
                   4186:         xmlBufferWriteCHAR(buf, cur->ns->prefix);
                   4187:        xmlBufferWriteChar(buf, ":");
                   4188:     }
1.38      daniel   4189:     xmlBufferWriteCHAR(buf, cur->name);
1.90      daniel   4190:     value = xmlNodeListGetString(doc, cur->children, 0);
1.23      daniel   4191:     if (value) {
1.43      daniel   4192:        xmlBufferWriteChar(buf, "=");
                   4193:        xmlBufferWriteQuotedString(buf, value);
1.57      daniel   4194:        xmlFree(value);
1.34      daniel   4195:     } else  {
1.38      daniel   4196:        xmlBufferWriteChar(buf, "=\"\"");
1.3       veillard 4197:     }
1.8       veillard 4198: }
                   4199: 
1.23      daniel   4200: /**
                   4201:  * xmlAttrListDump:
1.42      daniel   4202:  * @buf:  the XML buffer output
1.23      daniel   4203:  * @doc:  the document
                   4204:  * @cur:  the first attribute pointer
                   4205:  *
                   4206:  * Dump a list of XML attributes
1.8       veillard 4207:  */
1.28      daniel   4208: static void
1.38      daniel   4209: xmlAttrListDump(xmlBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur) {
1.8       veillard 4210:     if (cur == NULL) {
1.86      daniel   4211: #ifdef DEBUG_TREE
1.20      daniel   4212:         fprintf(stderr, "xmlAttrListDump : property == NULL\n");
1.86      daniel   4213: #endif
1.1       veillard 4214:        return;
                   4215:     }
1.8       veillard 4216:     while (cur != NULL) {
1.38      daniel   4217:         xmlAttrDump(buf, doc, cur);
1.8       veillard 4218:        cur = cur->next;
1.1       veillard 4219:     }
                   4220: }
                   4221: 
                   4222: 
1.82      daniel   4223: 
1.23      daniel   4224: /**
                   4225:  * xmlNodeListDump:
1.42      daniel   4226:  * @buf:  the XML buffer output
1.23      daniel   4227:  * @doc:  the document
                   4228:  * @cur:  the first node
                   4229:  * @level: the imbrication level for indenting
1.64      daniel   4230:  * @format: is formatting allowed
1.23      daniel   4231:  *
                   4232:  * Dump an XML node list, recursive behaviour,children are printed too.
                   4233:  */
1.28      daniel   4234: static void
1.64      daniel   4235: xmlNodeListDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
                   4236:                 int format) {
                   4237:     int i;
1.25      daniel   4238: 
1.1       veillard 4239:     if (cur == NULL) {
1.86      daniel   4240: #ifdef DEBUG_TREE
1.8       veillard 4241:         fprintf(stderr, "xmlNodeListDump : node == NULL\n");
1.86      daniel   4242: #endif
1.1       veillard 4243:        return;
                   4244:     }
1.8       veillard 4245:     while (cur != NULL) {
1.64      daniel   4246:        if ((format) && (xmlIndentTreeOutput) &&
                   4247:            (cur->type == XML_ELEMENT_NODE))
                   4248:            for (i = 0;i < level;i++)
                   4249:                xmlBufferWriteChar(buf, "  ");
                   4250:         xmlNodeDump(buf, doc, cur, level, format);
                   4251:        if (format) {
                   4252:            xmlBufferWriteChar(buf, "\n");
1.25      daniel   4253:        }
1.8       veillard 4254:        cur = cur->next;
1.3       veillard 4255:     }
1.1       veillard 4256: }
                   4257: 
1.23      daniel   4258: /**
1.25      daniel   4259:  * xmlNodeDump:
1.42      daniel   4260:  * @buf:  the XML buffer output
1.23      daniel   4261:  * @doc:  the document
                   4262:  * @cur:  the current node
                   4263:  * @level: the imbrication level for indenting
1.64      daniel   4264:  * @format: is formatting allowed
1.23      daniel   4265:  *
                   4266:  * Dump an XML node, recursive behaviour,children are printed too.
1.1       veillard 4267:  */
1.28      daniel   4268: static void
1.64      daniel   4269: xmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
                   4270:             int format) {
1.8       veillard 4271:     int i;
1.64      daniel   4272:     xmlNodePtr tmp;
1.8       veillard 4273: 
1.1       veillard 4274:     if (cur == NULL) {
1.86      daniel   4275: #ifdef DEBUG_TREE
1.8       veillard 4276:         fprintf(stderr, "xmlNodeDump : node == NULL\n");
1.86      daniel   4277: #endif
1.8       veillard 4278:        return;
                   4279:     }
1.92      daniel   4280:     if (cur->type == XML_DTD_NODE) {
                   4281:         xmlDtdDump(buf, (xmlDtdPtr) cur);
                   4282:        return;
                   4283:     }
1.99      daniel   4284:     if (cur->type == XML_ELEMENT_DECL) {
                   4285:         xmlDumpElementDecl(buf, (xmlElementPtr) cur);
                   4286:        return;
                   4287:     }
                   4288:     if (cur->type == XML_ATTRIBUTE_DECL) {
                   4289:         xmlDumpAttributeDecl(buf, (xmlAttributePtr) cur);
                   4290:        return;
                   4291:     }
                   4292:     if (cur->type == XML_ENTITY_DECL) {
                   4293:         xmlDumpEntityDecl(buf, (xmlEntityPtr) cur);
                   4294:        return;
                   4295:     }
1.23      daniel   4296:     if (cur->type == XML_TEXT_NODE) {
1.45      daniel   4297:        if (cur->content != NULL) {
1.61      daniel   4298:             xmlChar *buffer;
1.45      daniel   4299: 
1.70      daniel   4300: #ifndef XML_USE_BUFFER_CONTENT
1.46      daniel   4301:             buffer = xmlEncodeEntitiesReentrant(doc, cur->content);
1.70      daniel   4302: #else
                   4303:            buffer = xmlEncodeEntitiesReentrant(doc, 
                   4304:                                            xmlBufferContent(cur->content));
                   4305: #endif
1.45      daniel   4306:            if (buffer != NULL) {
                   4307:                xmlBufferWriteCHAR(buf, buffer);
1.57      daniel   4308:                xmlFree(buffer);
1.45      daniel   4309:            }
                   4310:        }
1.14      daniel   4311:        return;
                   4312:     }
1.52      daniel   4313:     if (cur->type == XML_PI_NODE) {
                   4314:        if (cur->content != NULL) {
                   4315:            xmlBufferWriteChar(buf, "<?");
                   4316:            xmlBufferWriteCHAR(buf, cur->name);
                   4317:            if (cur->content != NULL) {
                   4318:                xmlBufferWriteChar(buf, " ");
1.70      daniel   4319: #ifndef XML_USE_BUFFER_CONTENT
1.52      daniel   4320:                xmlBufferWriteCHAR(buf, cur->content);
1.70      daniel   4321: #else
                   4322:                xmlBufferWriteCHAR(buf, xmlBufferContent(cur->content));
                   4323: #endif
1.52      daniel   4324:            }
1.89      daniel   4325:            xmlBufferWriteChar(buf, "?>");
                   4326:        } else {
                   4327:            xmlBufferWriteChar(buf, "<?");
                   4328:            xmlBufferWriteCHAR(buf, cur->name);
1.64      daniel   4329:            xmlBufferWriteChar(buf, "?>");
1.52      daniel   4330:        }
                   4331:        return;
                   4332:     }
1.23      daniel   4333:     if (cur->type == XML_COMMENT_NODE) {
1.14      daniel   4334:        if (cur->content != NULL) {
1.38      daniel   4335:            xmlBufferWriteChar(buf, "<!--");
1.70      daniel   4336: #ifndef XML_USE_BUFFER_CONTENT
1.38      daniel   4337:            xmlBufferWriteCHAR(buf, cur->content);
1.70      daniel   4338: #else
                   4339:            xmlBufferWriteCHAR(buf, xmlBufferContent(cur->content));
                   4340: #endif
1.64      daniel   4341:            xmlBufferWriteChar(buf, "-->");
1.14      daniel   4342:        }
1.8       veillard 4343:        return;
                   4344:     }
1.23      daniel   4345:     if (cur->type == XML_ENTITY_REF_NODE) {
1.38      daniel   4346:         xmlBufferWriteChar(buf, "&");
                   4347:        xmlBufferWriteCHAR(buf, cur->name);
                   4348:         xmlBufferWriteChar(buf, ";");
1.50      daniel   4349:        return;
                   4350:     }
                   4351:     if (cur->type == XML_CDATA_SECTION_NODE) {
                   4352:         xmlBufferWriteChar(buf, "<![CDATA[");
                   4353:        if (cur->content != NULL)
1.70      daniel   4354: #ifndef XML_USE_BUFFER_CONTENT
1.50      daniel   4355:            xmlBufferWriteCHAR(buf, cur->content);
1.70      daniel   4356: #else
                   4357:            xmlBufferWriteCHAR(buf, xmlBufferContent(cur->content));
                   4358: #endif
1.50      daniel   4359:         xmlBufferWriteChar(buf, "]]>");
1.23      daniel   4360:        return;
                   4361:     }
1.8       veillard 4362: 
1.64      daniel   4363:     if (format == 1) {
1.91      daniel   4364:        tmp = cur->children;
1.64      daniel   4365:        while (tmp != NULL) {
                   4366:            if ((tmp->type == XML_TEXT_NODE) || 
                   4367:                (tmp->type == XML_ENTITY_REF_NODE)) {
                   4368:                format = 0;
                   4369:                break;
                   4370:            }
                   4371:            tmp = tmp->next;
                   4372:        }
                   4373:     }
1.38      daniel   4374:     xmlBufferWriteChar(buf, "<");
1.16      daniel   4375:     if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
1.38      daniel   4376:         xmlBufferWriteCHAR(buf, cur->ns->prefix);
                   4377:        xmlBufferWriteChar(buf, ":");
1.8       veillard 4378:     }
                   4379: 
1.38      daniel   4380:     xmlBufferWriteCHAR(buf, cur->name);
1.19      daniel   4381:     if (cur->nsDef)
1.38      daniel   4382:         xmlNsListDump(buf, cur->nsDef);
1.8       veillard 4383:     if (cur->properties != NULL)
1.38      daniel   4384:         xmlAttrListDump(buf, doc, cur->properties);
1.8       veillard 4385: 
1.90      daniel   4386:     if ((cur->content == NULL) && (cur->children == NULL) &&
1.87      daniel   4387:        (!xmlSaveNoEmptyTags)) {
1.64      daniel   4388:         xmlBufferWriteChar(buf, "/>");
1.1       veillard 4389:        return;
                   4390:     }
1.38      daniel   4391:     xmlBufferWriteChar(buf, ">");
1.46      daniel   4392:     if (cur->content != NULL) {
1.61      daniel   4393:        xmlChar *buffer;
1.46      daniel   4394: 
1.70      daniel   4395: #ifndef XML_USE_BUFFER_CONTENT
1.46      daniel   4396:        buffer = xmlEncodeEntitiesReentrant(doc, cur->content);
1.70      daniel   4397: #else
                   4398:        buffer = xmlEncodeEntitiesReentrant(doc, 
                   4399:                                            xmlBufferContent(cur->content));
                   4400: #endif
1.46      daniel   4401:        if (buffer != NULL) {
                   4402:            xmlBufferWriteCHAR(buf, buffer);
1.57      daniel   4403:            xmlFree(buffer);
1.46      daniel   4404:        }
                   4405:     }
1.90      daniel   4406:     if (cur->children != NULL) {
1.64      daniel   4407:        if (format) xmlBufferWriteChar(buf, "\n");
1.99      daniel   4408:        xmlNodeListDump(buf, doc, cur->children,
                   4409:                        (level >= 0?level+1:-1), format);
1.64      daniel   4410:        if ((xmlIndentTreeOutput) && (format))
                   4411:            for (i = 0;i < level;i++)
                   4412:                xmlBufferWriteChar(buf, "  ");
1.8       veillard 4413:     }
1.38      daniel   4414:     xmlBufferWriteChar(buf, "</");
1.16      daniel   4415:     if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
1.38      daniel   4416:         xmlBufferWriteCHAR(buf, cur->ns->prefix);
                   4417:        xmlBufferWriteChar(buf, ":");
1.1       veillard 4418:     }
1.8       veillard 4419: 
1.38      daniel   4420:     xmlBufferWriteCHAR(buf, cur->name);
1.64      daniel   4421:     xmlBufferWriteChar(buf, ">");
1.1       veillard 4422: }
                   4423: 
1.23      daniel   4424: /**
1.82      daniel   4425:  * xmlElemDump:
                   4426:  * @buf:  the XML buffer output
                   4427:  * @doc:  the document
                   4428:  * @cur:  the current node
                   4429:  *
                   4430:  * Dump an XML/HTML node, recursive behaviour,children are printed too.
                   4431:  */
                   4432: void
                   4433: xmlElemDump(FILE *f, xmlDocPtr doc, xmlNodePtr cur) {
                   4434:     xmlBufferPtr buf;
                   4435: 
                   4436:     if (cur == NULL) {
                   4437: #ifdef DEBUG_TREE
                   4438:         fprintf(stderr, "xmlElemDump : cur == NULL\n");
                   4439: #endif
                   4440:        return;
                   4441:     }
                   4442:     if (doc == NULL) {
                   4443: #ifdef DEBUG_TREE
                   4444:         fprintf(stderr, "xmlElemDump : doc == NULL\n");
                   4445: #endif
                   4446:     }
                   4447:     buf = xmlBufferCreate();
                   4448:     if (buf == NULL) return;
                   4449:     if ((doc != NULL) && 
                   4450:         (doc->type == XML_HTML_DOCUMENT_NODE)) {
1.101     daniel   4451: #ifdef LIBXML_HTML_ENABLED
1.82      daniel   4452:         htmlNodeDump(buf, doc, cur);
1.101     daniel   4453: #else  
                   4454:        printf("HTML support not compiled in\n");
                   4455: #endif /* LIBXML_HTML_ENABLED */
1.82      daniel   4456:     } else
                   4457:         xmlNodeDump(buf, doc, cur, 0, 1);
                   4458:     xmlBufferDump(f, buf);
                   4459:     xmlBufferFree(buf);
                   4460: }
                   4461: 
                   4462: /**
1.23      daniel   4463:  * xmlDocContentDump:
1.42      daniel   4464:  * @buf:  the XML buffer output
1.23      daniel   4465:  * @cur:  the document
                   4466:  *
                   4467:  * Dump an XML document.
1.1       veillard 4468:  */
1.28      daniel   4469: static void
1.38      daniel   4470: xmlDocContentDump(xmlBufferPtr buf, xmlDocPtr cur) {
1.46      daniel   4471:     xmlBufferWriteChar(buf, "<?xml version=");
                   4472:     if (cur->version != NULL) 
                   4473:        xmlBufferWriteQuotedString(buf, cur->version);
                   4474:     else
                   4475:        xmlBufferWriteChar(buf, "\"1.0\"");
1.15      daniel   4476:     if (cur->encoding != NULL) {
1.43      daniel   4477:         xmlBufferWriteChar(buf, " encoding=");
                   4478:        xmlBufferWriteQuotedString(buf, cur->encoding);
1.15      daniel   4479:     }
                   4480:     switch (cur->standalone) {
                   4481:         case 0:
1.38      daniel   4482:            xmlBufferWriteChar(buf, " standalone=\"no\"");
1.15      daniel   4483:            break;
                   4484:         case 1:
1.38      daniel   4485:            xmlBufferWriteChar(buf, " standalone=\"yes\"");
1.15      daniel   4486:            break;
                   4487:     }
1.38      daniel   4488:     xmlBufferWriteChar(buf, "?>\n");
1.90      daniel   4489:     if (cur->children != NULL) {
                   4490:         xmlNodePtr child = cur->children;
1.52      daniel   4491: 
1.19      daniel   4492:        /* global namespace definitions, the old way */
                   4493:        if (oldXMLWDcompatibility)
1.38      daniel   4494:            xmlGlobalNsListDump(buf, cur->oldNs);
1.19      daniel   4495:        else 
                   4496:            xmlUpgradeOldNs(cur);
1.52      daniel   4497:        
                   4498:        while (child != NULL) {
1.64      daniel   4499:            xmlNodeDump(buf, cur, child, 0, 1);
                   4500:            xmlBufferWriteChar(buf, "\n");
1.52      daniel   4501:            child = child->next;
                   4502:        }
1.19      daniel   4503:     }
                   4504: }
                   4505: 
1.23      daniel   4506: /**
                   4507:  * xmlDocDumpMemory:
                   4508:  * @cur:  the document
                   4509:  * @mem:  OUT: the memory pointer
                   4510:  * @size:  OUT: the memory lenght
                   4511:  *
1.61      daniel   4512:  * Dump an XML document in memory and return the xmlChar * and it's size.
1.23      daniel   4513:  * It's up to the caller to free the memory.
1.19      daniel   4514:  */
1.28      daniel   4515: void
1.61      daniel   4516: xmlDocDumpMemory(xmlDocPtr cur, xmlChar**mem, int *size) {
1.38      daniel   4517:     xmlBufferPtr buf;
                   4518: 
1.19      daniel   4519:     if (cur == NULL) {
1.31      daniel   4520: #ifdef DEBUG_TREE
                   4521:         fprintf(stderr, "xmlDocDumpMemory : document == NULL\n");
                   4522: #endif
1.19      daniel   4523:        *mem = NULL;
                   4524:        *size = 0;
                   4525:        return;
                   4526:     }
1.38      daniel   4527:     buf = xmlBufferCreate();
                   4528:     if (buf == NULL) {
                   4529:        *mem = NULL;
                   4530:        *size = 0;
                   4531:        return;
                   4532:     }
                   4533:     xmlDocContentDump(buf, cur);
1.51      daniel   4534:     *mem = xmlStrndup(buf->content, buf->use);
1.38      daniel   4535:     *size = buf->use;
1.51      daniel   4536:     xmlBufferFree(buf);
1.1       veillard 4537: }
                   4538: 
1.23      daniel   4539: /**
                   4540:  * xmlGetDocCompressMode:
                   4541:  * @doc:  the document
                   4542:  *
                   4543:  * get the compression ratio for a document, ZLIB based
1.36      daniel   4544:  * Returns 0 (uncompressed) to 9 (max compression)
1.23      daniel   4545:  */
1.28      daniel   4546: int
1.82      daniel   4547: xmlGetDocCompressMode (xmlDocPtr doc) {
1.23      daniel   4548:     if (doc == NULL) return(-1);
                   4549:     return(doc->compression);
                   4550: }
                   4551: 
                   4552: /**
                   4553:  * xmlSetDocCompressMode:
                   4554:  * @doc:  the document
                   4555:  * @mode:  the compression ratio
                   4556:  *
                   4557:  * set the compression ratio for a document, ZLIB based
                   4558:  * Correct values: 0 (uncompressed) to 9 (max compression)
                   4559:  */
1.28      daniel   4560: void
                   4561: xmlSetDocCompressMode (xmlDocPtr doc, int mode) {
1.23      daniel   4562:     if (doc == NULL) return;
                   4563:     if (mode < 0) doc->compression = 0;
                   4564:     else if (mode > 9) doc->compression = 9;
                   4565:     else doc->compression = mode;
                   4566: }
                   4567: 
                   4568: /**
                   4569:  * xmlGetCompressMode:
                   4570:  *
                   4571:  * get the default compression mode used, ZLIB based.
1.36      daniel   4572:  * Returns 0 (uncompressed) to 9 (max compression)
1.23      daniel   4573:  */
1.28      daniel   4574: int
                   4575:  xmlGetCompressMode(void) {
1.23      daniel   4576:     return(xmlCompressMode);
                   4577: }
                   4578: 
                   4579: /**
                   4580:  * xmlSetCompressMode:
                   4581:  * @mode:  the compression ratio
                   4582:  *
                   4583:  * set the default compression mode used, ZLIB based
                   4584:  * Correct values: 0 (uncompressed) to 9 (max compression)
1.1       veillard 4585:  */
1.28      daniel   4586: void
                   4587: xmlSetCompressMode(int mode) {
1.23      daniel   4588:     if (mode < 0) xmlCompressMode = 0;
                   4589:     else if (mode > 9) xmlCompressMode = 9;
                   4590:     else xmlCompressMode = mode;
                   4591: }
1.1       veillard 4592: 
1.23      daniel   4593: /**
                   4594:  * xmlDocDump:
                   4595:  * @f:  the FILE*
                   4596:  * @cur:  the document
                   4597:  *
                   4598:  * Dump an XML document to an open FILE.
                   4599:  */
1.28      daniel   4600: void
                   4601: xmlDocDump(FILE *f, xmlDocPtr cur) {
1.38      daniel   4602:     xmlBufferPtr buf;
                   4603: 
1.1       veillard 4604:     if (cur == NULL) {
1.31      daniel   4605: #ifdef DEBUG_TREE
1.1       veillard 4606:         fprintf(stderr, "xmlDocDump : document == NULL\n");
1.31      daniel   4607: #endif
1.1       veillard 4608:        return;
                   4609:     }
1.38      daniel   4610:     buf = xmlBufferCreate();
                   4611:     if (buf == NULL) return;
                   4612:     xmlDocContentDump(buf, cur);
                   4613:     xmlBufferDump(f, buf);
                   4614:     xmlBufferFree(buf);
1.23      daniel   4615: }
                   4616: 
                   4617: /**
                   4618:  * xmlSaveFile:
                   4619:  * @filename:  the filename
                   4620:  * @cur:  the document
                   4621:  *
                   4622:  * Dump an XML document to a file. Will use compression if
1.68      daniel   4623:  * compiled in and enabled. If @filename is "-" the stdout file is
                   4624:  * used.
1.23      daniel   4625:  * returns: the number of file written or -1 in case of failure.
                   4626:  */
1.28      daniel   4627: int
                   4628: xmlSaveFile(const char *filename, xmlDocPtr cur) {
1.38      daniel   4629:     xmlBufferPtr buf;
1.23      daniel   4630: #ifdef HAVE_ZLIB_H
                   4631:     gzFile zoutput = NULL;
                   4632:     char mode[15];
                   4633: #endif
1.24      daniel   4634:     FILE *output = NULL;
1.23      daniel   4635:     int ret;
                   4636: 
1.38      daniel   4637:     /* 
                   4638:      * save the content to a temp buffer.
                   4639:      */
                   4640:     buf = xmlBufferCreate();
                   4641:     if (buf == NULL) return(0);
                   4642:     xmlDocContentDump(buf, cur);
                   4643: 
1.23      daniel   4644: #ifdef HAVE_ZLIB_H
1.68      daniel   4645:     if (cur->compression < 0) cur->compression = xmlCompressMode;
1.23      daniel   4646:     if ((cur->compression > 0) && (cur->compression <= 9)) {
                   4647:         sprintf(mode, "w%d", cur->compression);
1.68      daniel   4648:        if (!strcmp(filename, "-")) 
                   4649:            zoutput = gzdopen(1, mode);
                   4650:        else
                   4651:            zoutput = gzopen(filename, mode);
1.23      daniel   4652:     }
                   4653:     if (zoutput == NULL) {
                   4654: #endif
                   4655:         output = fopen(filename, "w");
1.73      daniel   4656:        if (output == NULL) {
                   4657:            xmlBufferFree(buf);
                   4658:            return(-1);
                   4659:        }
1.23      daniel   4660: #ifdef HAVE_ZLIB_H
                   4661:     }
                   4662: 
                   4663:     if (zoutput != NULL) {
1.61      daniel   4664:         ret = gzwrite(zoutput, buf->content, sizeof(xmlChar) * buf->use);
1.23      daniel   4665:        gzclose(zoutput);
1.38      daniel   4666:     } else {
                   4667: #endif
                   4668:         ret = xmlBufferDump(output, buf);
                   4669:        fclose(output);
                   4670: #ifdef HAVE_ZLIB_H
1.23      daniel   4671:     }
                   4672: #endif
1.41      daniel   4673:     xmlBufferFree(buf);
1.61      daniel   4674:     return(ret * sizeof(xmlChar));
1.1       veillard 4675: }
                   4676: 

Webmaster