Annotation of XML/tree.c, revision 1.94

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

Webmaster