Annotation of XML/tree.c, revision 1.149

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.145     veillard    7:  *
                      8:  * 14 Nov 2000 ht - Changed the name of function xmlBufferWriteChar under VMS
                      9:  * as it was similar to xmlBufferWriteCHAR when compiling without case
                     10:  * sensitivity.
                     11:  *  
1.1       veillard   12:  */
                     13: 
1.59      daniel     14: #ifdef WIN32
1.80      daniel     15: #include "win32config.h"
1.59      daniel     16: #else
1.60      daniel     17: #include "config.h"
1.59      daniel     18: #endif
                     19: 
1.1       veillard   20: #include <stdio.h>
1.59      daniel     21: #include <string.h> /* for memset() only ! */
                     22: 
                     23: #ifdef HAVE_CTYPE_H
1.1       veillard   24: #include <ctype.h>
1.59      daniel     25: #endif
                     26: #ifdef HAVE_STDLIB_H
1.23      daniel     27: #include <stdlib.h>
1.59      daniel     28: #endif
1.23      daniel     29: #ifdef HAVE_ZLIB_H
                     30: #include <zlib.h>
                     31: #endif
                     32: 
1.101     daniel     33: #include <libxml/xmlmemory.h>
                     34: #include <libxml/tree.h>
                     35: #include <libxml/parser.h>
                     36: #include <libxml/entities.h>
                     37: #include <libxml/valid.h>
1.134     veillard   38: #include <libxml/xmlerror.h>
1.1       veillard   39: 
1.61      daniel     40: static xmlChar xmlStringText[] = { 't', 'e', 'x', 't', 0 };
1.90      daniel     41: static xmlChar xmlStringComment[] = { 'c', 'o', 'm', 'm', 'e', 'n', 't', 0 };
1.12      daniel     42: int oldXMLWDcompatibility = 0;
1.99      daniel     43: int xmlIndentTreeOutput = 0;
1.70      daniel     44: xmlBufferAllocationScheme xmlBufferAllocScheme = XML_BUFFER_ALLOC_EXACT;
1.7       veillard   45: 
1.23      daniel     46: static int xmlCompressMode = 0;
1.74      daniel     47: static int xmlCheckDTD = 1;
1.87      daniel     48: int xmlSaveNoEmptyTags = 0;
1.23      daniel     49: 
1.99      daniel     50: #define IS_BLANK(c)                                                    \
                     51:   (((c) == '\n') || ((c) == '\r') || ((c) == '\t') || ((c) == ' '))
                     52: 
1.140     veillard   53: #define UPDATE_LAST_CHILD_AND_PARENT(n) if ((n) != NULL) {             \
1.90      daniel     54:     xmlNodePtr ulccur = (n)->children;                                 \
1.32      daniel     55:     if (ulccur == NULL) {                                              \
                     56:         (n)->last = NULL;                                              \
                     57:     } else {                                                           \
1.140     veillard   58:         while (ulccur->next != NULL) {                                 \
                     59:                ulccur->parent = (n);                                   \
                     60:                ulccur = ulccur->next;                                  \
                     61:        }                                                               \
                     62:        ulccur->parent = (n);                                           \
1.32      daniel     63:        (n)->last = ulccur;                                             \
1.34      daniel     64: }}
1.32      daniel     65: 
1.86      daniel     66: /* #define DEBUG_BUFFER */
                     67: /* #define DEBUG_TREE */
                     68: 
1.1       veillard   69: /************************************************************************
                     70:  *                                                                     *
                     71:  *             Allocation and deallocation of basic structures         *
                     72:  *                                                                     *
                     73:  ************************************************************************/
                     74:  
1.23      daniel     75: /**
1.70      daniel     76:  * xmlSetBufferAllocationScheme:
                     77:  * @scheme:  allocation method to use
                     78:  * 
                     79:  * Set the buffer allocation method.  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: void
                     85: xmlSetBufferAllocationScheme(xmlBufferAllocationScheme scheme) {
                     86:     xmlBufferAllocScheme = scheme;
                     87: }
                     88: 
                     89: /**
                     90:  * xmlGetBufferAllocationScheme:
                     91:  *
                     92:  * Types are
                     93:  * XML_BUFFER_ALLOC_EXACT - use exact sizes, keeps memory usage down
                     94:  * XML_BUFFER_ALLOC_DOUBLEIT - double buffer when extra needed, 
                     95:  *                             improves performance
                     96:  * 
                     97:  * Returns the current allocation scheme
                     98:  */
                     99: xmlBufferAllocationScheme
                    100: xmlGetBufferAllocationScheme() {
                    101:     return xmlBufferAllocScheme;
                    102: }
                    103: 
                    104: /**
1.23      daniel    105:  * xmlNewNs:
                    106:  * @node:  the element carrying the namespace
                    107:  * @href:  the URI associated
                    108:  * @prefix:  the prefix for the namespace
                    109:  *
1.83      daniel    110:  * Creation of a new Namespace. This function will refuse to create
                    111:  * a namespace with a similar prefix than an existing one present on this
                    112:  * node.
1.120     veillard  113:  * We use href==NULL in the case of an element creation where the namespace
                    114:  * was not defined.
1.83      daniel    115:  * Returns returns a new namespace pointer or NULL
1.1       veillard  116:  */
1.28      daniel    117: xmlNsPtr
1.61      daniel    118: xmlNewNs(xmlNodePtr node, const xmlChar *href, const xmlChar *prefix) {
1.16      daniel    119:     xmlNsPtr cur;
1.1       veillard  120: 
                    121:     /*
1.90      daniel    122:      * Allocate a new Namespace and fill the fields.
1.1       veillard  123:      */
1.57      daniel    124:     cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
1.1       veillard  125:     if (cur == NULL) {
1.134     veillard  126:         xmlGenericError(xmlGenericErrorContext,
                    127:                "xmlNewNs : malloc failed\n");
1.1       veillard  128:        return(NULL);
                    129:     }
1.90      daniel    130:     memset(cur, 0, sizeof(xmlNs));
                    131:     cur->type = XML_LOCAL_NAMESPACE;
1.1       veillard  132: 
1.19      daniel    133:     if (href != NULL)
                    134:        cur->href = xmlStrdup(href); 
                    135:     if (prefix != NULL)
                    136:        cur->prefix = xmlStrdup(prefix); 
                    137: 
                    138:     /*
                    139:      * Add it at the end to preserve parsing order ...
1.83      daniel    140:      * and checks for existing use of the prefix
1.19      daniel    141:      */
                    142:     if (node != NULL) {
                    143:        if (node->nsDef == NULL) {
                    144:            node->nsDef = cur;
                    145:        } else {
                    146:            xmlNsPtr prev = node->nsDef;
                    147: 
1.86      daniel    148:            if (((prev->prefix == NULL) && (cur->prefix == NULL)) ||
1.128     veillard  149:                (xmlStrEqual(prev->prefix, cur->prefix))) {
1.86      daniel    150:                xmlFreeNs(cur);
                    151:                return(NULL);
                    152:            }    
1.83      daniel    153:            while (prev->next != NULL) {
1.86      daniel    154:                prev = prev->next;
1.83      daniel    155:                if (((prev->prefix == NULL) && (cur->prefix == NULL)) ||
1.128     veillard  156:                    (xmlStrEqual(prev->prefix, cur->prefix))) {
1.83      daniel    157:                    xmlFreeNs(cur);
                    158:                    return(NULL);
                    159:                }    
                    160:            }
1.19      daniel    161:            prev->next = cur;
                    162:        }
                    163:     }
                    164:     return(cur);
                    165: }
                    166: 
1.23      daniel    167: /**
                    168:  * xmlSetNs:
                    169:  * @node:  a node in the document
                    170:  * @ns:  a namespace pointer
                    171:  *
                    172:  * Associate a namespace to a node, a posteriori.
1.19      daniel    173:  */
1.28      daniel    174: void
                    175: xmlSetNs(xmlNodePtr node, xmlNsPtr ns) {
1.19      daniel    176:     if (node == NULL) {
1.86      daniel    177: #ifdef DEBUG_TREE
1.134     veillard  178:         xmlGenericError(xmlGenericErrorContext,
                    179:                "xmlSetNs: node == NULL\n");
1.94      daniel    180: #endif
1.19      daniel    181:        return;
                    182:     }
                    183:     node->ns = ns;
                    184: }
                    185: 
1.23      daniel    186: /**
                    187:  * xmlFreeNs:
                    188:  * @cur:  the namespace pointer
                    189:  *
                    190:  * Free up the structures associated to a namespace
1.1       veillard  191:  */
1.28      daniel    192: void
                    193: xmlFreeNs(xmlNsPtr cur) {
1.1       veillard  194:     if (cur == NULL) {
1.86      daniel    195: #ifdef DEBUG_TREE
1.134     veillard  196:         xmlGenericError(xmlGenericErrorContext,
                    197:                "xmlFreeNs : ns == NULL\n");
1.86      daniel    198: #endif
1.1       veillard  199:        return;
                    200:     }
1.57      daniel    201:     if (cur->href != NULL) xmlFree((char *) cur->href);
                    202:     if (cur->prefix != NULL) xmlFree((char *) cur->prefix);
1.16      daniel    203:     memset(cur, -1, sizeof(xmlNs));
1.57      daniel    204:     xmlFree(cur);
1.1       veillard  205: }
                    206: 
1.23      daniel    207: /**
                    208:  * xmlFreeNsList:
                    209:  * @cur:  the first namespace pointer
                    210:  *
                    211:  * Free up all the structures associated to the chained namespaces.
1.6       veillard  212:  */
1.28      daniel    213: void
                    214: xmlFreeNsList(xmlNsPtr cur) {
1.16      daniel    215:     xmlNsPtr next;
1.6       veillard  216:     if (cur == NULL) {
1.86      daniel    217: #ifdef DEBUG_TREE
1.134     veillard  218:         xmlGenericError(xmlGenericErrorContext,
                    219:                "xmlFreeNsList : ns == NULL\n");
1.86      daniel    220: #endif
1.6       veillard  221:        return;
                    222:     }
                    223:     while (cur != NULL) {
                    224:         next = cur->next;
1.16      daniel    225:         xmlFreeNs(cur);
1.6       veillard  226:        cur = next;
                    227:     }
                    228: }
                    229: 
1.23      daniel    230: /**
                    231:  * xmlNewDtd:
                    232:  * @doc:  the document pointer
                    233:  * @name:  the DTD name
                    234:  * @ExternalID:  the external ID
                    235:  * @SystemID:  the system ID
                    236:  *
1.94      daniel    237:  * Creation of a new DTD for the external subset. To create an
                    238:  * internal subset, use xmlCreateIntSubset().
                    239:  *
1.36      daniel    240:  * Returns a pointer to the new DTD structure
1.17      daniel    241:  */
1.28      daniel    242: xmlDtdPtr
1.61      daniel    243: xmlNewDtd(xmlDocPtr doc, const xmlChar *name,
                    244:                     const xmlChar *ExternalID, const xmlChar *SystemID) {
1.17      daniel    245:     xmlDtdPtr cur;
                    246: 
1.31      daniel    247:     if ((doc != NULL) && (doc->extSubset != NULL)) {
1.86      daniel    248: #ifdef DEBUG_TREE
1.134     veillard  249:         xmlGenericError(xmlGenericErrorContext,
                    250:                "xmlNewDtd(%s): document %s already have a DTD %s\n",
1.31      daniel    251:            /* !!! */ (char *) name, doc->name,
                    252:            /* !!! */ (char *)doc->extSubset->name);
1.86      daniel    253: #endif
                    254:        return(NULL);
1.17      daniel    255:     }
                    256: 
                    257:     /*
                    258:      * Allocate a new DTD and fill the fields.
                    259:      */
1.57      daniel    260:     cur = (xmlDtdPtr) xmlMalloc(sizeof(xmlDtd));
1.17      daniel    261:     if (cur == NULL) {
1.134     veillard  262:         xmlGenericError(xmlGenericErrorContext,
                    263:                "xmlNewDtd : malloc failed\n");
1.31      daniel    264:        return(NULL);
                    265:     }
1.90      daniel    266:     memset(cur, 0 , sizeof(xmlDtd));
                    267:     cur->type = XML_DTD_NODE;
1.31      daniel    268: 
                    269:     if (name != NULL)
                    270:        cur->name = xmlStrdup(name); 
                    271:     if (ExternalID != NULL)
                    272:        cur->ExternalID = xmlStrdup(ExternalID); 
                    273:     if (SystemID != NULL)
                    274:        cur->SystemID = xmlStrdup(SystemID); 
                    275:     if (doc != NULL)
                    276:        doc->extSubset = cur;
1.94      daniel    277:     cur->doc = doc;
1.31      daniel    278: 
                    279:     return(cur);
                    280: }
                    281: 
                    282: /**
1.92      daniel    283:  * xmlGetIntSubset:
                    284:  * @doc:  the document pointer
                    285:  *
                    286:  * Get the internal subset of a document
                    287:  * Returns a pointer to the DTD structure or NULL if not found
                    288:  */
                    289: 
                    290: xmlDtdPtr
                    291: xmlGetIntSubset(xmlDocPtr doc) {
                    292:     xmlNodePtr cur;
                    293: 
                    294:     if (doc == NULL)
                    295:        return(NULL);
                    296:     cur = doc->children;
                    297:     while (cur != NULL) {
                    298:        if (cur->type == XML_DTD_NODE)
                    299:            return((xmlDtdPtr) cur);
                    300:        cur = cur->next;
                    301:     }
                    302:     return((xmlDtdPtr) doc->intSubset);
                    303: }
                    304: 
                    305: /**
1.31      daniel    306:  * xmlCreateIntSubset:
                    307:  * @doc:  the document pointer
                    308:  * @name:  the DTD name
                    309:  * @ExternalID:  the external ID
                    310:  * @SystemID:  the system ID
                    311:  *
1.36      daniel    312:  * Create the internal subset of a document
                    313:  * Returns a pointer to the new DTD structure
1.31      daniel    314:  */
                    315: xmlDtdPtr
1.61      daniel    316: xmlCreateIntSubset(xmlDocPtr doc, const xmlChar *name,
                    317:                    const xmlChar *ExternalID, const xmlChar *SystemID) {
1.31      daniel    318:     xmlDtdPtr cur;
                    319: 
1.92      daniel    320:     if ((doc != NULL) && (xmlGetIntSubset(doc) != NULL)) {
1.86      daniel    321: #ifdef DEBUG_TREE
1.134     veillard  322:         xmlGenericError(xmlGenericErrorContext,
                    323: 
1.31      daniel    324:      "xmlCreateIntSubset(): document %s already have an internal subset\n",
                    325:            doc->name);
1.86      daniel    326: #endif
1.31      daniel    327:        return(NULL);
                    328:     }
                    329: 
                    330:     /*
                    331:      * Allocate a new DTD and fill the fields.
                    332:      */
1.57      daniel    333:     cur = (xmlDtdPtr) xmlMalloc(sizeof(xmlDtd));
1.31      daniel    334:     if (cur == NULL) {
1.134     veillard  335:         xmlGenericError(xmlGenericErrorContext,
                    336:                "xmlNewDtd : malloc failed\n");
1.17      daniel    337:        return(NULL);
                    338:     }
1.90      daniel    339:     memset(cur, 0, sizeof(xmlDtd));
                    340:     cur->type = XML_DTD_NODE;
1.17      daniel    341: 
                    342:     if (name != NULL)
                    343:        cur->name = xmlStrdup(name); 
                    344:     if (ExternalID != NULL)
                    345:        cur->ExternalID = xmlStrdup(ExternalID); 
                    346:     if (SystemID != NULL)
                    347:        cur->SystemID = xmlStrdup(SystemID); 
1.90      daniel    348:     if (doc != NULL) {
1.31      daniel    349:        doc->intSubset = cur;
1.90      daniel    350:        cur->parent = doc;
1.94      daniel    351:        cur->doc = doc;
1.92      daniel    352:        if (doc->children == NULL) {
                    353:            doc->children = (xmlNodePtr) cur;
                    354:            doc->last = (xmlNodePtr) cur;
                    355:        } else {
                    356:            xmlNodePtr prev;
                    357: 
1.119     veillard  358:            if (doc->type == XML_HTML_DOCUMENT_NODE) {
                    359:                prev = doc->children;
                    360:                prev->prev = (xmlNodePtr) cur;
                    361:                cur->next = prev;
                    362:                doc->children = (xmlNodePtr) cur;
                    363:            } else {
                    364:                prev = doc->last;
                    365:                prev->next = (xmlNodePtr) cur;
                    366:                cur->prev = prev;
                    367:                doc->last = (xmlNodePtr) cur;
                    368:            }
1.92      daniel    369:        }
1.90      daniel    370:     }
1.17      daniel    371:     return(cur);
                    372: }
                    373: 
1.23      daniel    374: /**
                    375:  * xmlFreeDtd:
                    376:  * @cur:  the DTD structure to free up
                    377:  *
                    378:  * Free a DTD structure.
1.17      daniel    379:  */
1.28      daniel    380: void
                    381: xmlFreeDtd(xmlDtdPtr cur) {
1.17      daniel    382:     if (cur == NULL) {
1.86      daniel    383: #ifdef DEBUG_TREE
1.134     veillard  384:         xmlGenericError(xmlGenericErrorContext,
                    385:                "xmlFreeDtd : DTD == NULL\n");
1.86      daniel    386: #endif
1.17      daniel    387:        return;
                    388:     }
1.97      daniel    389:     if (cur->children != NULL) {
                    390:        xmlNodePtr next, c = cur->children;
                    391: 
                    392:        /*
                    393:         * Cleanup all the DTD comments they are not in the Dtd
                    394:         * indexes.
                    395:         */
                    396:         while (c != NULL) {
                    397:            next = c->next;
                    398:            if (c->type == XML_COMMENT_NODE) {
                    399:                xmlUnlinkNode(c);
                    400:                xmlFreeNode(c);
                    401:            }
                    402:            c = next;
                    403:        }
                    404:     }
1.57      daniel    405:     if (cur->name != NULL) xmlFree((char *) cur->name);
                    406:     if (cur->SystemID != NULL) xmlFree((char *) cur->SystemID);
                    407:     if (cur->ExternalID != NULL) xmlFree((char *) cur->ExternalID);
1.97      daniel    408:     /* TODO !!! */
1.35      daniel    409:     if (cur->notations != NULL)
                    410:         xmlFreeNotationTable((xmlNotationTablePtr) cur->notations);
1.97      daniel    411:     
1.17      daniel    412:     if (cur->elements != NULL)
1.33      daniel    413:         xmlFreeElementTable((xmlElementTablePtr) cur->elements);
1.34      daniel    414:     if (cur->attributes != NULL)
                    415:         xmlFreeAttributeTable((xmlAttributeTablePtr) cur->attributes);
1.17      daniel    416:     if (cur->entities != NULL)
                    417:         xmlFreeEntitiesTable((xmlEntitiesTablePtr) cur->entities);
1.132     veillard  418:     if (cur->pentities != NULL)
                    419:         xmlFreeEntitiesTable((xmlEntitiesTablePtr) cur->pentities);
1.97      daniel    420: 
1.17      daniel    421:     memset(cur, -1, sizeof(xmlDtd));
1.57      daniel    422:     xmlFree(cur);
1.17      daniel    423: }
                    424: 
1.23      daniel    425: /**
                    426:  * xmlNewDoc:
1.61      daniel    427:  * @version:  xmlChar string giving the version of XML "1.0"
1.23      daniel    428:  *
1.36      daniel    429:  * Returns a new document
1.1       veillard  430:  */
1.28      daniel    431: xmlDocPtr
1.61      daniel    432: xmlNewDoc(const xmlChar *version) {
1.1       veillard  433:     xmlDocPtr cur;
                    434: 
1.130     veillard  435:     if (version == NULL)
                    436:        version = (const xmlChar *) "1.0";
1.1       veillard  437: 
                    438:     /*
                    439:      * Allocate a new document and fill the fields.
                    440:      */
1.57      daniel    441:     cur = (xmlDocPtr) xmlMalloc(sizeof(xmlDoc));
1.1       veillard  442:     if (cur == NULL) {
1.134     veillard  443:         xmlGenericError(xmlGenericErrorContext,
                    444:                "xmlNewDoc : malloc failed\n");
1.1       veillard  445:        return(NULL);
                    446:     }
1.90      daniel    447:     memset(cur, 0, sizeof(xmlDoc));
                    448:     cur->type = XML_DOCUMENT_NODE;
1.1       veillard  449: 
1.7       veillard  450:     cur->version = xmlStrdup(version); 
1.15      daniel    451:     cur->standalone = -1;
1.68      daniel    452:     cur->compression = -1; /* not initialized */
1.94      daniel    453:     cur->doc = cur;
1.1       veillard  454:     return(cur);
                    455: }
                    456: 
1.23      daniel    457: /**
                    458:  * xmlFreeDoc:
                    459:  * @cur:  pointer to the document
                    460:  * @:  
                    461:  *
                    462:  * Free up all the structures used by a document, tree included.
1.1       veillard  463:  */
1.28      daniel    464: void
                    465: xmlFreeDoc(xmlDocPtr cur) {
1.1       veillard  466:     if (cur == NULL) {
1.31      daniel    467: #ifdef DEBUG_TREE
1.134     veillard  468:         xmlGenericError(xmlGenericErrorContext,
                    469:                "xmlFreeDoc : document == NULL\n");
1.31      daniel    470: #endif
1.1       veillard  471:        return;
                    472:     }
1.57      daniel    473:     if (cur->version != NULL) xmlFree((char *) cur->version);
                    474:     if (cur->name != NULL) xmlFree((char *) cur->name);
                    475:     if (cur->encoding != NULL) xmlFree((char *) cur->encoding);
1.90      daniel    476:     if (cur->children != NULL) xmlFreeNodeList(cur->children);
1.31      daniel    477:     if (cur->intSubset != NULL) xmlFreeDtd(cur->intSubset);
                    478:     if (cur->extSubset != NULL) xmlFreeDtd(cur->extSubset);
                    479:     if (cur->oldNs != NULL) xmlFreeNsList(cur->oldNs);
1.52      daniel    480:     if (cur->ids != NULL) xmlFreeIDTable((xmlIDTablePtr) cur->ids);
1.58      daniel    481:     if (cur->refs != NULL) xmlFreeRefTable((xmlRefTablePtr) cur->refs);
1.100     daniel    482:     if (cur->URL != NULL) xmlFree((char *) cur->URL);
1.1       veillard  483:     memset(cur, -1, sizeof(xmlDoc));
1.57      daniel    484:     xmlFree(cur);
1.1       veillard  485: }
                    486: 
1.23      daniel    487: /**
1.28      daniel    488:  * xmlStringLenGetNodeList:
                    489:  * @doc:  the document
                    490:  * @value:  the value of the text
1.36      daniel    491:  * @len:  the length of the string value
1.28      daniel    492:  *
                    493:  * Parse the value string and build the node list associated. Should
                    494:  * produce a flat tree with only TEXTs and ENTITY_REFs.
1.36      daniel    495:  * Returns a pointer to the first child
1.28      daniel    496:  */
                    497: xmlNodePtr
1.61      daniel    498: xmlStringLenGetNodeList(xmlDocPtr doc, const xmlChar *value, int len) {
1.28      daniel    499:     xmlNodePtr ret = NULL, last = NULL;
                    500:     xmlNodePtr node;
1.61      daniel    501:     xmlChar *val;
                    502:     const xmlChar *cur = value;
                    503:     const xmlChar *q;
1.28      daniel    504:     xmlEntityPtr ent;
                    505: 
                    506:     if (value == NULL) return(NULL);
                    507: 
                    508:     q = cur;
                    509:     while ((*cur != 0) && (cur - value < len)) {
                    510:        if (*cur == '&') {
                    511:            /*
                    512:             * Save the current text.
                    513:             */
                    514:             if (cur != q) {
                    515:                if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
                    516:                    xmlNodeAddContentLen(last, q, cur - q);
                    517:                } else {
                    518:                    node = xmlNewDocTextLen(doc, q, cur - q);
                    519:                    if (node == NULL) return(ret);
                    520:                    if (last == NULL)
                    521:                        last = ret = node;
                    522:                    else {
                    523:                        last->next = node;
                    524:                        node->prev = last;
                    525:                        last = node;
                    526:                    }
                    527:                }
                    528:            }
                    529:            /*
                    530:             * Read the entity string
                    531:             */
                    532:            cur++;
                    533:            q = cur;
                    534:            while ((*cur != 0) && (cur - value < len) && (*cur != ';')) cur++;
                    535:            if ((*cur == 0) || (cur - value >= len)) {
1.86      daniel    536: #ifdef DEBUG_TREE
1.134     veillard  537:                xmlGenericError(xmlGenericErrorContext,
1.44      daniel    538:                    "xmlStringLenGetNodeList: unterminated entity %30s\n", q);
1.86      daniel    539: #endif
1.28      daniel    540:                return(ret);
                    541:            }
                    542:             if (cur != q) {
                    543:                /*
                    544:                 * Predefined entities don't generate nodes
                    545:                 */
                    546:                val = xmlStrndup(q, cur - q);
                    547:                ent = xmlGetDocEntity(doc, val);
                    548:                if ((ent != NULL) &&
1.95      daniel    549:                    (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
1.28      daniel    550:                    if (last == NULL) {
                    551:                        node = xmlNewDocText(doc, ent->content);
                    552:                        last = ret = node;
                    553:                    } else
                    554:                        xmlNodeAddContent(last, ent->content);
                    555:                        
                    556:                } else {
                    557:                    /*
                    558:                     * Create a new REFERENCE_REF node
                    559:                     */
                    560:                    node = xmlNewReference(doc, val);
1.30      daniel    561:                    if (node == NULL) {
1.57      daniel    562:                        if (val != NULL) xmlFree(val);
1.30      daniel    563:                        return(ret);
                    564:                    }
1.28      daniel    565:                    if (last == NULL)
                    566:                        last = ret = node;
                    567:                    else {
                    568:                        last->next = node;
                    569:                        node->prev = last;
                    570:                        last = node;
                    571:                    }
                    572:                }
1.57      daniel    573:                xmlFree(val);
1.28      daniel    574:            }
                    575:            cur++;
                    576:            q = cur;
                    577:        } else 
                    578:            cur++;
                    579:     }
                    580:     if (cur != q) {
                    581:         /*
                    582:         * Handle the last piece of text.
                    583:         */
                    584:        if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
                    585:            xmlNodeAddContentLen(last, q, cur - q);
                    586:        } else {
                    587:            node = xmlNewDocTextLen(doc, q, cur - q);
                    588:            if (node == NULL) return(ret);
                    589:            if (last == NULL)
                    590:                last = ret = node;
                    591:            else {
                    592:                last->next = node;
                    593:                node->prev = last;
                    594:                last = node;
                    595:            }
                    596:        }
                    597:     }
                    598:     return(ret);
                    599: }
                    600: 
                    601: /**
1.24      daniel    602:  * xmlStringGetNodeList:
                    603:  * @doc:  the document
1.23      daniel    604:  * @value:  the value of the attribute
                    605:  *
1.24      daniel    606:  * Parse the value string and build the node list associated. Should
                    607:  * produce a flat tree with only TEXTs and ENTITY_REFs.
1.36      daniel    608:  * Returns a pointer to the first child
1.23      daniel    609:  */
1.28      daniel    610: xmlNodePtr
1.61      daniel    611: xmlStringGetNodeList(xmlDocPtr doc, const xmlChar *value) {
1.23      daniel    612:     xmlNodePtr ret = NULL, last = NULL;
                    613:     xmlNodePtr node;
1.61      daniel    614:     xmlChar *val;
                    615:     const xmlChar *cur = value;
                    616:     const xmlChar *q;
1.28      daniel    617:     xmlEntityPtr ent;
1.23      daniel    618: 
                    619:     if (value == NULL) return(NULL);
                    620: 
                    621:     q = cur;
                    622:     while (*cur != 0) {
                    623:        if (*cur == '&') {
1.28      daniel    624:            /*
                    625:             * Save the current text.
                    626:             */
1.23      daniel    627:             if (cur != q) {
1.28      daniel    628:                if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
                    629:                    xmlNodeAddContentLen(last, q, cur - q);
                    630:                } else {
                    631:                    node = xmlNewDocTextLen(doc, q, cur - q);
                    632:                    if (node == NULL) return(ret);
                    633:                    if (last == NULL)
                    634:                        last = ret = node;
                    635:                    else {
                    636:                        last->next = node;
                    637:                        node->prev = last;
                    638:                        last = node;
                    639:                    }
1.23      daniel    640:                }
                    641:            }
1.28      daniel    642:            /*
                    643:             * Read the entity string
                    644:             */
1.23      daniel    645:            cur++;
                    646:            q = cur;
                    647:            while ((*cur != 0) && (*cur != ';')) cur++;
                    648:            if (*cur == 0) {
1.86      daniel    649: #ifdef DEBUG_TREE
1.134     veillard  650:                xmlGenericError(xmlGenericErrorContext,
1.24      daniel    651:                        "xmlStringGetNodeList: unterminated entity %30s\n", q);
1.86      daniel    652: #endif
1.23      daniel    653:                return(ret);
                    654:            }
                    655:             if (cur != q) {
1.28      daniel    656:                /*
                    657:                 * Predefined entities don't generate nodes
                    658:                 */
1.23      daniel    659:                val = xmlStrndup(q, cur - q);
1.28      daniel    660:                ent = xmlGetDocEntity(doc, val);
                    661:                if ((ent != NULL) &&
1.95      daniel    662:                    (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
1.28      daniel    663:                    if (last == NULL) {
                    664:                        node = xmlNewDocText(doc, ent->content);
                    665:                        last = ret = node;
                    666:                    } else
                    667:                        xmlNodeAddContent(last, ent->content);
                    668:                        
                    669:                } else {
                    670:                    /*
                    671:                     * Create a new REFERENCE_REF node
                    672:                     */
                    673:                    node = xmlNewReference(doc, val);
1.30      daniel    674:                    if (node == NULL) {
1.57      daniel    675:                        if (val != NULL) xmlFree(val);
1.30      daniel    676:                        return(ret);
                    677:                    }
1.28      daniel    678:                    if (last == NULL)
                    679:                        last = ret = node;
                    680:                    else {
                    681:                        last->next = node;
                    682:                        node->prev = last;
                    683:                        last = node;
                    684:                    }
1.23      daniel    685:                }
1.57      daniel    686:                xmlFree(val);
1.23      daniel    687:            }
                    688:            cur++;
                    689:            q = cur;
                    690:        } else 
                    691:            cur++;
                    692:     }
                    693:     if (cur != q) {
1.28      daniel    694:         /*
                    695:         * Handle the last piece of text.
                    696:         */
                    697:        if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
                    698:            xmlNodeAddContentLen(last, q, cur - q);
                    699:        } else {
                    700:            node = xmlNewDocTextLen(doc, q, cur - q);
                    701:            if (node == NULL) return(ret);
                    702:            if (last == NULL)
                    703:                last = ret = node;
                    704:            else {
                    705:                last->next = node;
                    706:                node->prev = last;
                    707:                last = node;
                    708:            }
1.23      daniel    709:        }
                    710:     }
                    711:     return(ret);
                    712: }
                    713: 
                    714: /**
1.24      daniel    715:  * xmlNodeListGetString:
1.23      daniel    716:  * @doc:  the document
1.24      daniel    717:  * @list:  a Node list
1.23      daniel    718:  * @inLine:  should we replace entity contents or show their external form
                    719:  *
1.24      daniel    720:  * Returns the string equivalent to the text contained in the Node list
                    721:  * made of TEXTs and ENTITY_REFs
1.36      daniel    722:  * Returns a pointer to the string copy, the calller must free it.
1.23      daniel    723:  */
1.61      daniel    724: xmlChar *
1.28      daniel    725: xmlNodeListGetString(xmlDocPtr doc, xmlNodePtr list, int inLine) {
1.24      daniel    726:     xmlNodePtr node = list;
1.61      daniel    727:     xmlChar *ret = NULL;
1.23      daniel    728:     xmlEntityPtr ent;
                    729: 
1.24      daniel    730:     if (list == NULL) return(NULL);
1.23      daniel    731: 
                    732:     while (node != NULL) {
1.118     veillard  733:         if ((node->type == XML_TEXT_NODE) ||
                    734:            (node->type == XML_CDATA_SECTION_NODE)) {
1.84      daniel    735:            if (inLine) {
1.70      daniel    736: #ifndef XML_USE_BUFFER_CONTENT
1.23      daniel    737:                ret = xmlStrcat(ret, node->content);
1.70      daniel    738: #else
                    739:                ret = xmlStrcat(ret, xmlBufferContent(node->content));
                    740: #endif
                    741:            } else {
1.61      daniel    742:                xmlChar *buffer;
1.45      daniel    743: 
1.70      daniel    744: #ifndef XML_USE_BUFFER_CONTENT
1.46      daniel    745:                buffer = xmlEncodeEntitiesReentrant(doc, node->content);
1.70      daniel    746: #else
                    747:                buffer = xmlEncodeEntitiesReentrant(doc,
                    748:                                            xmlBufferContent(node->content));
                    749: #endif
1.45      daniel    750:                if (buffer != NULL) {
                    751:                    ret = xmlStrcat(ret, buffer);
1.57      daniel    752:                    xmlFree(buffer);
1.45      daniel    753:                }
                    754:             }
1.23      daniel    755:        } else if (node->type == XML_ENTITY_REF_NODE) {
                    756:            if (inLine) {
                    757:                ent = xmlGetDocEntity(doc, node->name);
                    758:                if (ent != NULL)
                    759:                    ret = xmlStrcat(ret, ent->content);
1.70      daniel    760:                else {
                    761: #ifndef XML_USE_BUFFER_CONTENT
1.23      daniel    762:                    ret = xmlStrcat(ret, node->content);
1.70      daniel    763: #else
                    764:                    ret = xmlStrcat(ret, xmlBufferContent(node->content));
                    765: #endif
                    766:                }    
1.23      daniel    767:             } else {
1.61      daniel    768:                xmlChar buf[2];
1.23      daniel    769:                buf[0] = '&'; buf[1] = 0;
                    770:                ret = xmlStrncat(ret, buf, 1);
                    771:                ret = xmlStrcat(ret, node->name);
                    772:                buf[0] = ';'; buf[1] = 0;
                    773:                ret = xmlStrncat(ret, buf, 1);
                    774:            }
1.24      daniel    775:        }
                    776: #if 0
                    777:        else {
1.134     veillard  778:            xmlGenericError(xmlGenericErrorContext,
                    779:                    "xmlGetNodeListString : invalide node type %d\n",
1.23      daniel    780:                    node->type);
                    781:        }
1.24      daniel    782: #endif
1.23      daniel    783:        node = node->next;
                    784:     }
                    785:     return(ret);
                    786: }
                    787: 
                    788: /**
1.108     daniel    789:  * xmlNodeListGetRawString:
                    790:  * @doc:  the document
                    791:  * @list:  a Node list
                    792:  * @inLine:  should we replace entity contents or show their external form
                    793:  *
                    794:  * Returns the string equivalent to the text contained in the Node list
                    795:  * made of TEXTs and ENTITY_REFs, contrary to xmlNodeListGetString()
                    796:  * this function doesn't do any character encoding handling.
                    797:  *
                    798:  * Returns a pointer to the string copy, the calller must free it.
                    799:  */
                    800: xmlChar *
                    801: xmlNodeListGetRawString(xmlDocPtr doc, xmlNodePtr list, int inLine) {
                    802:     xmlNodePtr node = list;
                    803:     xmlChar *ret = NULL;
                    804:     xmlEntityPtr ent;
                    805: 
                    806:     if (list == NULL) return(NULL);
                    807: 
                    808:     while (node != NULL) {
                    809:         if (node->type == XML_TEXT_NODE) {
                    810:            if (inLine) {
                    811: #ifndef XML_USE_BUFFER_CONTENT
                    812:                ret = xmlStrcat(ret, node->content);
                    813: #else
                    814:                ret = xmlStrcat(ret, xmlBufferContent(node->content));
                    815: #endif
                    816:            } else {
                    817:                xmlChar *buffer;
                    818: 
                    819: #ifndef XML_USE_BUFFER_CONTENT
                    820:                buffer = xmlEncodeSpecialChars(doc, node->content);
                    821: #else
                    822:                buffer = xmlEncodeSpecialChars(doc,
                    823:                                            xmlBufferContent(node->content));
                    824: #endif
                    825:                if (buffer != NULL) {
                    826:                    ret = xmlStrcat(ret, buffer);
                    827:                    xmlFree(buffer);
                    828:                }
                    829:             }
                    830:        } else if (node->type == XML_ENTITY_REF_NODE) {
                    831:            if (inLine) {
                    832:                ent = xmlGetDocEntity(doc, node->name);
                    833:                if (ent != NULL)
                    834:                    ret = xmlStrcat(ret, ent->content);
                    835:                else {
                    836: #ifndef XML_USE_BUFFER_CONTENT
                    837:                    ret = xmlStrcat(ret, node->content);
                    838: #else
                    839:                    ret = xmlStrcat(ret, xmlBufferContent(node->content));
                    840: #endif
                    841:                }    
                    842:             } else {
                    843:                xmlChar buf[2];
                    844:                buf[0] = '&'; buf[1] = 0;
                    845:                ret = xmlStrncat(ret, buf, 1);
                    846:                ret = xmlStrcat(ret, node->name);
                    847:                buf[0] = ';'; buf[1] = 0;
                    848:                ret = xmlStrncat(ret, buf, 1);
                    849:            }
                    850:        }
                    851: #if 0
                    852:        else {
1.134     veillard  853:            xmlGenericError(xmlGenericErrorContext,
                    854:                    "xmlGetNodeListString : invalide node type %d\n",
1.108     daniel    855:                    node->type);
                    856:        }
                    857: #endif
                    858:        node = node->next;
                    859:     }
                    860:     return(ret);
                    861: }
                    862: 
                    863: /**
1.23      daniel    864:  * xmlNewProp:
                    865:  * @node:  the holding node
                    866:  * @name:  the name of the attribute
                    867:  * @value:  the value of the attribute
                    868:  *
                    869:  * Create a new property carried by a node.
1.36      daniel    870:  * Returns a pointer to the attribute
1.1       veillard  871:  */
1.28      daniel    872: xmlAttrPtr
1.61      daniel    873: xmlNewProp(xmlNodePtr node, const xmlChar *name, const xmlChar *value) {
1.20      daniel    874:     xmlAttrPtr cur;
1.1       veillard  875: 
                    876:     if (name == NULL) {
1.86      daniel    877: #ifdef DEBUG_TREE
1.134     veillard  878:         xmlGenericError(xmlGenericErrorContext,
                    879:                "xmlNewProp : name == NULL\n");
1.86      daniel    880: #endif
1.1       veillard  881:        return(NULL);
                    882:     }
                    883: 
                    884:     /*
                    885:      * Allocate a new property and fill the fields.
                    886:      */
1.57      daniel    887:     cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr));
1.1       veillard  888:     if (cur == NULL) {
1.134     veillard  889:         xmlGenericError(xmlGenericErrorContext,
                    890:                "xmlNewProp : malloc failed\n");
1.1       veillard  891:        return(NULL);
                    892:     }
1.90      daniel    893:     memset(cur, 0, sizeof(xmlAttr));
                    894:     cur->type = XML_ATTRIBUTE_NODE;
1.1       veillard  895: 
1.90      daniel    896:     cur->parent = node; 
1.56      daniel    897:     cur->name = xmlStrdup(name);
1.67      daniel    898:     if (value != NULL) {
                    899:        xmlChar *buffer;
1.94      daniel    900:        xmlNodePtr tmp;
                    901: 
1.67      daniel    902:        buffer = xmlEncodeEntitiesReentrant(node->doc, value);
1.90      daniel    903:        cur->children = xmlStringGetNodeList(node->doc, buffer);
1.140     veillard  904:        cur->last = NULL;
1.94      daniel    905:        tmp = cur->children;
                    906:        while (tmp != NULL) {
                    907:            tmp->parent = (xmlNodePtr) cur;
                    908:            if (tmp->next == NULL)
                    909:                cur->last = tmp;
                    910:            tmp = tmp->next;
                    911:        }
1.67      daniel    912:        xmlFree(buffer);
                    913:     }  
1.56      daniel    914: 
                    915:     /*
                    916:      * Add it at the end to preserve parsing order ...
                    917:      */
                    918:     if (node != NULL) {
                    919:        if (node->properties == NULL) {
                    920:            node->properties = cur;
                    921:        } else {
                    922:            xmlAttrPtr prev = node->properties;
                    923: 
                    924:            while (prev->next != NULL) prev = prev->next;
                    925:            prev->next = cur;
1.94      daniel    926:            cur->prev = prev;
1.56      daniel    927:        }
                    928:     }
                    929:     return(cur);
                    930: }
                    931: 
                    932: /**
                    933:  * xmlNewNsProp:
                    934:  * @node:  the holding node
                    935:  * @ns:  the namespace
                    936:  * @name:  the name of the attribute
                    937:  * @value:  the value of the attribute
                    938:  *
                    939:  * Create a new property tagged with a namespace and carried by a node.
                    940:  * Returns a pointer to the attribute
                    941:  */
                    942: xmlAttrPtr
1.61      daniel    943: xmlNewNsProp(xmlNodePtr node, xmlNsPtr ns, const xmlChar *name,
                    944:            const xmlChar *value) {
1.56      daniel    945:     xmlAttrPtr cur;
                    946: 
                    947:     if (name == NULL) {
1.86      daniel    948: #ifdef DEBUG_TREE
1.134     veillard  949:         xmlGenericError(xmlGenericErrorContext,
                    950:                "xmlNewProp : name == NULL\n");
1.86      daniel    951: #endif
1.56      daniel    952:        return(NULL);
                    953:     }
                    954: 
                    955:     /*
                    956:      * Allocate a new property and fill the fields.
                    957:      */
1.57      daniel    958:     cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr));
1.56      daniel    959:     if (cur == NULL) {
1.134     veillard  960:         xmlGenericError(xmlGenericErrorContext,
                    961:                "xmlNewProp : malloc failed\n");
1.56      daniel    962:        return(NULL);
                    963:     }
1.90      daniel    964:     memset(cur, 0, sizeof(xmlAttr));
                    965:     cur->type = XML_ATTRIBUTE_NODE;
1.56      daniel    966: 
1.90      daniel    967:     cur->parent = node; 
1.94      daniel    968:     if (node != NULL)
                    969:        cur->doc = node->doc; 
1.56      daniel    970:     cur->ns = ns;
1.7       veillard  971:     cur->name = xmlStrdup(name);
1.94      daniel    972:     if (value != NULL) {
                    973:        xmlChar *buffer;
                    974:        xmlNodePtr tmp;
                    975: 
                    976:        buffer = xmlEncodeEntitiesReentrant(node->doc, value);
                    977:        cur->children = xmlStringGetNodeList(node->doc, buffer);
1.140     veillard  978:        cur->last = NULL;
1.94      daniel    979:        tmp = cur->children;
                    980:        while (tmp != NULL) {
                    981:            tmp->parent = (xmlNodePtr) cur;
                    982:            if (tmp->next == NULL)
                    983:                cur->last = tmp;
                    984:            tmp = tmp->next;
                    985:        }
                    986:        xmlFree(buffer);
                    987:     }
1.17      daniel    988: 
                    989:     /*
                    990:      * Add it at the end to preserve parsing order ...
                    991:      */
1.1       veillard  992:     if (node != NULL) {
1.17      daniel    993:        if (node->properties == NULL) {
                    994:            node->properties = cur;
                    995:        } else {
1.20      daniel    996:            xmlAttrPtr prev = node->properties;
1.17      daniel    997: 
                    998:            while (prev->next != NULL) prev = prev->next;
                    999:            prev->next = cur;
1.94      daniel   1000:            cur->prev = prev;
1.17      daniel   1001:        }
                   1002:     }
1.1       veillard 1003:     return(cur);
                   1004: }
                   1005: 
1.23      daniel   1006: /**
                   1007:  * xmlNewDocProp:
                   1008:  * @doc:  the document
                   1009:  * @name:  the name of the attribute
                   1010:  * @value:  the value of the attribute
                   1011:  *
                   1012:  * Create a new property carried by a document.
1.36      daniel   1013:  * Returns a pointer to the attribute
1.23      daniel   1014:  */
1.28      daniel   1015: xmlAttrPtr
1.61      daniel   1016: xmlNewDocProp(xmlDocPtr doc, const xmlChar *name, const xmlChar *value) {
1.23      daniel   1017:     xmlAttrPtr cur;
                   1018: 
                   1019:     if (name == NULL) {
1.86      daniel   1020: #ifdef DEBUG_TREE
1.134     veillard 1021:         xmlGenericError(xmlGenericErrorContext,
                   1022:                "xmlNewProp : name == NULL\n");
1.86      daniel   1023: #endif
1.23      daniel   1024:        return(NULL);
                   1025:     }
                   1026: 
                   1027:     /*
                   1028:      * Allocate a new property and fill the fields.
                   1029:      */
1.57      daniel   1030:     cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr));
1.23      daniel   1031:     if (cur == NULL) {
1.134     veillard 1032:         xmlGenericError(xmlGenericErrorContext,
                   1033:                "xmlNewProp : malloc failed\n");
1.23      daniel   1034:        return(NULL);
                   1035:     }
1.90      daniel   1036:     memset(cur, 0, sizeof(xmlAttr));
                   1037:     cur->type = XML_ATTRIBUTE_NODE;
1.23      daniel   1038: 
                   1039:     cur->name = xmlStrdup(name);
1.94      daniel   1040:     cur->doc = doc; 
1.140     veillard 1041:     if (value != NULL) {
                   1042:        xmlNodePtr tmp;
                   1043: 
1.90      daniel   1044:        cur->children = xmlStringGetNodeList(doc, value);
1.140     veillard 1045:        cur->last = NULL;
                   1046: 
                   1047:        tmp = cur->children;
                   1048:        while (tmp != NULL) {
                   1049:            tmp->parent = (xmlNodePtr) cur;
                   1050:            if (tmp->next == NULL)
                   1051:                cur->last = tmp;
                   1052:            tmp = tmp->next;
                   1053:        }
                   1054:     }
1.23      daniel   1055:     return(cur);
                   1056: }
                   1057: 
                   1058: /**
                   1059:  * xmlFreePropList:
                   1060:  * @cur:  the first property in the list
                   1061:  *
1.90      daniel   1062:  * Free a property and all its siblings, all the children are freed too.
1.1       veillard 1063:  */
1.28      daniel   1064: void
                   1065: xmlFreePropList(xmlAttrPtr cur) {
1.20      daniel   1066:     xmlAttrPtr next;
1.1       veillard 1067:     if (cur == NULL) {
1.86      daniel   1068: #ifdef DEBUG_TREE
1.134     veillard 1069:         xmlGenericError(xmlGenericErrorContext,
                   1070:                "xmlFreePropList : property == NULL\n");
1.86      daniel   1071: #endif
1.1       veillard 1072:        return;
                   1073:     }
                   1074:     while (cur != NULL) {
                   1075:         next = cur->next;
                   1076:         xmlFreeProp(cur);
                   1077:        cur = next;
                   1078:     }
                   1079: }
                   1080: 
1.23      daniel   1081: /**
                   1082:  * xmlFreeProp:
1.83      daniel   1083:  * @cur:  an attribute
1.23      daniel   1084:  *
1.83      daniel   1085:  * Free one attribute, all the content is freed too
1.1       veillard 1086:  */
1.28      daniel   1087: void
                   1088: xmlFreeProp(xmlAttrPtr cur) {
1.1       veillard 1089:     if (cur == NULL) {
1.86      daniel   1090: #ifdef DEBUG_TREE
1.134     veillard 1091:         xmlGenericError(xmlGenericErrorContext,
                   1092:                "xmlFreeProp : property == NULL\n");
1.86      daniel   1093: #endif
1.1       veillard 1094:        return;
                   1095:     }
1.84      daniel   1096:     /* Check for ID removal -> leading to invalid references ! */
1.90      daniel   1097:     if ((cur->parent != NULL) && 
                   1098:         (xmlIsID(cur->parent->doc, cur->parent, cur)))
                   1099:         xmlRemoveID(cur->parent->doc, cur);
1.57      daniel   1100:     if (cur->name != NULL) xmlFree((char *) cur->name);
1.90      daniel   1101:     if (cur->children != NULL) xmlFreeNodeList(cur->children);
1.20      daniel   1102:     memset(cur, -1, sizeof(xmlAttr));
1.57      daniel   1103:     xmlFree(cur);
1.83      daniel   1104: }
                   1105: 
                   1106: /**
                   1107:  * xmlRemoveProp:
                   1108:  * @cur:  an attribute
                   1109:  *
                   1110:  * Unlink and free one attribute, all the content is freed too
                   1111:  * Note this doesn't work for namespace definition attributes
                   1112:  *
                   1113:  * Returns 0 if success and -1 in case of error.
                   1114:  */
                   1115: int
                   1116: xmlRemoveProp(xmlAttrPtr cur) {
                   1117:     xmlAttrPtr tmp;
                   1118:     if (cur == NULL) {
1.86      daniel   1119: #ifdef DEBUG_TREE
1.134     veillard 1120:         xmlGenericError(xmlGenericErrorContext,
                   1121:                "xmlRemoveProp : cur == NULL\n");
1.86      daniel   1122: #endif
1.83      daniel   1123:        return(-1);
                   1124:     }
1.90      daniel   1125:     if (cur->parent == NULL) {
1.94      daniel   1126: #ifdef DEBUG_TREE
1.134     veillard 1127:         xmlGenericError(xmlGenericErrorContext,
                   1128:                "xmlRemoveProp : cur->parent == NULL\n");
1.86      daniel   1129: #endif
1.83      daniel   1130:        return(-1);
                   1131:     }
1.90      daniel   1132:     tmp = cur->parent->properties;
1.83      daniel   1133:     if (tmp == cur) {
1.90      daniel   1134:         cur->parent->properties = cur->next;
1.83      daniel   1135:        xmlFreeProp(cur);
                   1136:        return(0);
                   1137:     }
                   1138:     while (tmp != NULL) {
                   1139:        if (tmp->next == cur) {
                   1140:            tmp->next = cur->next;
1.94      daniel   1141:            if (tmp->next != NULL)
                   1142:                tmp->next->prev = tmp;
1.83      daniel   1143:            xmlFreeProp(cur);
                   1144:            return(0);
                   1145:        }
                   1146:         tmp = tmp->next;
                   1147:     }
1.86      daniel   1148: #ifdef DEBUG_TREE
1.134     veillard 1149:     xmlGenericError(xmlGenericErrorContext,
                   1150:            "xmlRemoveProp : attribute not owned by its node\n");
1.86      daniel   1151: #endif
1.83      daniel   1152:     return(-1);
1.1       veillard 1153: }
                   1154: 
1.23      daniel   1155: /**
1.52      daniel   1156:  * xmlNewPI:
                   1157:  * @name:  the processing instruction name
                   1158:  * @content:  the PI content
                   1159:  *
                   1160:  * Creation of a processing instruction element.
                   1161:  * Returns a pointer to the new node object.
                   1162:  */
                   1163: xmlNodePtr
1.61      daniel   1164: xmlNewPI(const xmlChar *name, const xmlChar *content) {
1.52      daniel   1165:     xmlNodePtr cur;
                   1166: 
                   1167:     if (name == NULL) {
1.86      daniel   1168: #ifdef DEBUG_TREE
1.134     veillard 1169:         xmlGenericError(xmlGenericErrorContext,
                   1170:                "xmlNewPI : name == NULL\n");
1.86      daniel   1171: #endif
1.52      daniel   1172:        return(NULL);
                   1173:     }
                   1174: 
                   1175:     /*
                   1176:      * Allocate a new node and fill the fields.
                   1177:      */
1.57      daniel   1178:     cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
1.52      daniel   1179:     if (cur == NULL) {
1.134     veillard 1180:         xmlGenericError(xmlGenericErrorContext,
                   1181:                "xmlNewPI : malloc failed\n");
1.52      daniel   1182:        return(NULL);
                   1183:     }
1.90      daniel   1184:     memset(cur, 0, sizeof(xmlNode));
                   1185:     cur->type = XML_PI_NODE;
1.52      daniel   1186: 
                   1187:     cur->name = xmlStrdup(name);
1.70      daniel   1188:     if (content != NULL) {
                   1189: #ifndef XML_USE_BUFFER_CONTENT
1.52      daniel   1190:        cur->content = xmlStrdup(content);
1.70      daniel   1191: #else
                   1192:        cur->content = xmlBufferCreateSize(0);
                   1193:        xmlBufferSetAllocationScheme(cur->content,
                   1194:                                     xmlGetBufferAllocationScheme());
                   1195:        xmlBufferAdd(cur->content, content, -1);
                   1196: #endif
1.90      daniel   1197:     }
1.52      daniel   1198:     return(cur);
                   1199: }
                   1200: 
                   1201: /**
1.23      daniel   1202:  * xmlNewNode:
                   1203:  * @ns:  namespace if any
                   1204:  * @name:  the node name
                   1205:  *
1.120     veillard 1206:  * Creation of a new node element. @ns is optionnal (NULL).
                   1207:  *
1.36      daniel   1208:  * Returns a pointer to the new node object.
1.1       veillard 1209:  */
1.28      daniel   1210: xmlNodePtr
1.61      daniel   1211: xmlNewNode(xmlNsPtr ns, const xmlChar *name) {
1.1       veillard 1212:     xmlNodePtr cur;
                   1213: 
                   1214:     if (name == NULL) {
1.86      daniel   1215: #ifdef DEBUG_TREE
1.134     veillard 1216:         xmlGenericError(xmlGenericErrorContext,
                   1217:                "xmlNewNode : name == NULL\n");
1.86      daniel   1218: #endif
1.1       veillard 1219:        return(NULL);
                   1220:     }
                   1221: 
                   1222:     /*
                   1223:      * Allocate a new node and fill the fields.
                   1224:      */
1.57      daniel   1225:     cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
1.1       veillard 1226:     if (cur == NULL) {
1.134     veillard 1227:         xmlGenericError(xmlGenericErrorContext,
                   1228:                "xmlNewNode : malloc failed\n");
1.1       veillard 1229:        return(NULL);
                   1230:     }
1.90      daniel   1231:     memset(cur, 0, sizeof(xmlNode));
1.23      daniel   1232:     cur->type = XML_ELEMENT_NODE;
1.90      daniel   1233:     
1.22      daniel   1234:     cur->name = xmlStrdup(name);
1.16      daniel   1235:     cur->ns = ns;
1.1       veillard 1236:     return(cur);
                   1237: }
                   1238: 
1.23      daniel   1239: /**
                   1240:  * xmlNewDocNode:
                   1241:  * @doc:  the document
                   1242:  * @ns:  namespace if any
                   1243:  * @name:  the node name
1.68      daniel   1244:  * @content:  the XML text content if any
1.23      daniel   1245:  *
                   1246:  * Creation of a new node element within a document. @ns and @content
                   1247:  * are optionnal (NULL).
1.68      daniel   1248:  * NOTE: @content is supposed to be a piece of XML CDATA, so it allow entities
                   1249:  *       references, but XML special chars need to be escaped first by using
                   1250:  *       xmlEncodeEntitiesReentrant(). Use xmlNewDocRawNode() if you don't
                   1251:  *       need entities support.
                   1252:  *
1.36      daniel   1253:  * Returns a pointer to the new node object.
1.23      daniel   1254:  */
1.28      daniel   1255: xmlNodePtr
                   1256: xmlNewDocNode(xmlDocPtr doc, xmlNsPtr ns,
1.68      daniel   1257:               const xmlChar *name, const xmlChar *content) {
1.23      daniel   1258:     xmlNodePtr cur;
                   1259: 
1.24      daniel   1260:     cur = xmlNewNode(ns, name);
                   1261:     if (cur != NULL) {
                   1262:         cur->doc = doc;
1.32      daniel   1263:        if (content != NULL) {
1.90      daniel   1264:            cur->children = xmlStringGetNodeList(doc, content);
1.140     veillard 1265:            UPDATE_LAST_CHILD_AND_PARENT(cur)
1.32      daniel   1266:        }
1.24      daniel   1267:     }
1.23      daniel   1268:     return(cur);
                   1269: }
                   1270: 
                   1271: 
                   1272: /**
1.68      daniel   1273:  * xmlNewDocRawNode:
                   1274:  * @doc:  the document
                   1275:  * @ns:  namespace if any
                   1276:  * @name:  the node name
                   1277:  * @content:  the text content if any
                   1278:  *
                   1279:  * Creation of a new node element within a document. @ns and @content
                   1280:  * are optionnal (NULL).
                   1281:  *
                   1282:  * Returns a pointer to the new node object.
                   1283:  */
                   1284: xmlNodePtr
                   1285: xmlNewDocRawNode(xmlDocPtr doc, xmlNsPtr ns,
                   1286:                  const xmlChar *name, const xmlChar *content) {
                   1287:     xmlNodePtr cur;
                   1288: 
                   1289:     cur = xmlNewNode(ns, name);
                   1290:     if (cur != NULL) {
                   1291:         cur->doc = doc;
                   1292:        if (content != NULL) {
1.90      daniel   1293:            cur->children = xmlNewDocText(doc, content);
1.140     veillard 1294:            UPDATE_LAST_CHILD_AND_PARENT(cur)
1.68      daniel   1295:        }
                   1296:     }
                   1297:     return(cur);
                   1298: }
                   1299: 
1.85      daniel   1300: /**
                   1301:  * xmlNewDocFragment:
                   1302:  * @doc:  the document owning the fragment
                   1303:  *
                   1304:  * Creation of a new Fragment node.
                   1305:  * Returns a pointer to the new node object.
                   1306:  */
                   1307: xmlNodePtr
                   1308: xmlNewDocFragment(xmlDocPtr doc) {
                   1309:     xmlNodePtr cur;
                   1310: 
                   1311:     /*
                   1312:      * Allocate a new DocumentFragment node and fill the fields.
                   1313:      */
                   1314:     cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
                   1315:     if (cur == NULL) {
1.134     veillard 1316:         xmlGenericError(xmlGenericErrorContext,
                   1317:                "xmlNewDocFragment : malloc failed\n");
1.85      daniel   1318:        return(NULL);
                   1319:     }
1.90      daniel   1320:     memset(cur, 0, sizeof(xmlNode));
                   1321:     cur->type = XML_DOCUMENT_FRAG_NODE;
1.85      daniel   1322: 
                   1323:     cur->doc = doc;
                   1324:     return(cur);
                   1325: }
1.68      daniel   1326: 
                   1327: /**
1.23      daniel   1328:  * xmlNewText:
                   1329:  * @content:  the text content
                   1330:  *
                   1331:  * Creation of a new text node.
1.36      daniel   1332:  * Returns a pointer to the new node object.
1.3       veillard 1333:  */
1.28      daniel   1334: xmlNodePtr
1.61      daniel   1335: xmlNewText(const xmlChar *content) {
1.3       veillard 1336:     xmlNodePtr cur;
                   1337: 
                   1338:     /*
                   1339:      * Allocate a new node and fill the fields.
                   1340:      */
1.57      daniel   1341:     cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
1.3       veillard 1342:     if (cur == NULL) {
1.134     veillard 1343:         xmlGenericError(xmlGenericErrorContext,
                   1344:                "xmlNewText : malloc failed\n");
1.3       veillard 1345:        return(NULL);
                   1346:     }
1.90      daniel   1347:     memset(cur, 0, sizeof(xmlNode));
                   1348:     cur->type = XML_TEXT_NODE;
1.3       veillard 1349: 
1.18      daniel   1350:     cur->name = xmlStrdup(xmlStringText);
1.70      daniel   1351:     if (content != NULL) {
                   1352: #ifndef XML_USE_BUFFER_CONTENT
1.7       veillard 1353:        cur->content = xmlStrdup(content);
1.70      daniel   1354: #else
                   1355:        cur->content = xmlBufferCreateSize(0);
                   1356:        xmlBufferSetAllocationScheme(cur->content,
                   1357:                                     xmlGetBufferAllocationScheme());
                   1358:        xmlBufferAdd(cur->content, content, -1);
                   1359: #endif
1.90      daniel   1360:     }
1.3       veillard 1361:     return(cur);
                   1362: }
                   1363: 
1.23      daniel   1364: /**
1.68      daniel   1365:  * xmlNewTextChild:
                   1366:  * @parent:  the parent node
                   1367:  * @ns:  a namespace if any
                   1368:  * @name:  the name of the child
                   1369:  * @content:  the text content of the child if any.
                   1370:  *
1.90      daniel   1371:  * Creation of a new child element, added at the end of @parent children list.
1.68      daniel   1372:  * @ns and @content parameters are optionnal (NULL). If content is non NULL,
                   1373:  * a child TEXT node will be created containing the string content.
                   1374:  *
                   1375:  * Returns a pointer to the new node object.
                   1376:  */
                   1377: xmlNodePtr
                   1378: xmlNewTextChild(xmlNodePtr parent, xmlNsPtr ns,
                   1379:             const xmlChar *name, const xmlChar *content) {
                   1380:     xmlNodePtr cur, prev;
                   1381: 
                   1382:     if (parent == NULL) {
1.86      daniel   1383: #ifdef DEBUG_TREE
1.134     veillard 1384:         xmlGenericError(xmlGenericErrorContext,
                   1385:                "xmlNewTextChild : parent == NULL\n");
1.86      daniel   1386: #endif
1.68      daniel   1387:        return(NULL);
                   1388:     }
                   1389: 
                   1390:     if (name == NULL) {
1.86      daniel   1391: #ifdef DEBUG_TREE
1.134     veillard 1392:         xmlGenericError(xmlGenericErrorContext,
                   1393:                "xmlNewTextChild : name == NULL\n");
1.86      daniel   1394: #endif
1.68      daniel   1395:        return(NULL);
                   1396:     }
                   1397: 
                   1398:     /*
                   1399:      * Allocate a new node
                   1400:      */
                   1401:     if (ns == NULL)
                   1402:        cur = xmlNewDocRawNode(parent->doc, parent->ns, name, content);
                   1403:     else
                   1404:        cur = xmlNewDocRawNode(parent->doc, ns, name, content);
                   1405:     if (cur == NULL) return(NULL);
                   1406: 
                   1407:     /*
1.90      daniel   1408:      * add the new element at the end of the children list.
1.68      daniel   1409:      */
                   1410:     cur->type = XML_ELEMENT_NODE;
                   1411:     cur->parent = parent;
                   1412:     cur->doc = parent->doc;
1.90      daniel   1413:     if (parent->children == NULL) {
                   1414:         parent->children = cur;
1.68      daniel   1415:        parent->last = cur;
                   1416:     } else {
                   1417:         prev = parent->last;
                   1418:        prev->next = cur;
                   1419:        cur->prev = prev;
                   1420:        parent->last = cur;
                   1421:     }
                   1422: 
                   1423:     return(cur);
                   1424: }
                   1425: 
                   1426: /**
1.88      daniel   1427:  * xmlNewCharRef:
                   1428:  * @doc: the document
                   1429:  * @name:  the char ref string, starting with # or "&# ... ;"
                   1430:  *
                   1431:  * Creation of a new character reference node.
                   1432:  * Returns a pointer to the new node object.
                   1433:  */
                   1434: xmlNodePtr
                   1435: xmlNewCharRef(xmlDocPtr doc, const xmlChar *name) {
                   1436:     xmlNodePtr cur;
                   1437: 
                   1438:     /*
                   1439:      * Allocate a new node and fill the fields.
                   1440:      */
                   1441:     cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
                   1442:     if (cur == NULL) {
1.134     veillard 1443:         xmlGenericError(xmlGenericErrorContext,
                   1444:                "xmlNewText : malloc failed\n");
1.88      daniel   1445:        return(NULL);
                   1446:     }
1.90      daniel   1447:     memset(cur, 0, sizeof(xmlNode));
                   1448:     cur->type = XML_ENTITY_REF_NODE;
1.88      daniel   1449: 
                   1450:     cur->doc = doc;
                   1451:     if (name[0] == '&') {
                   1452:         int len;
                   1453:         name++;
                   1454:        len = xmlStrlen(name);
                   1455:        if (name[len - 1] == ';')
                   1456:            cur->name = xmlStrndup(name, len - 1);
                   1457:        else
                   1458:            cur->name = xmlStrndup(name, len);
                   1459:     } else
                   1460:        cur->name = xmlStrdup(name);
                   1461:     return(cur);
                   1462: }
                   1463: 
                   1464: /**
1.23      daniel   1465:  * xmlNewReference:
                   1466:  * @doc: the document
                   1467:  * @name:  the reference name, or the reference string with & and ;
                   1468:  *
                   1469:  * Creation of a new reference node.
1.36      daniel   1470:  * Returns a pointer to the new node object.
1.23      daniel   1471:  */
1.28      daniel   1472: xmlNodePtr
1.61      daniel   1473: xmlNewReference(xmlDocPtr doc, const xmlChar *name) {
1.23      daniel   1474:     xmlNodePtr cur;
                   1475:     xmlEntityPtr ent;
                   1476: 
                   1477:     /*
                   1478:      * Allocate a new node and fill the fields.
                   1479:      */
1.57      daniel   1480:     cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
1.23      daniel   1481:     if (cur == NULL) {
1.134     veillard 1482:         xmlGenericError(xmlGenericErrorContext,
                   1483:                "xmlNewText : malloc failed\n");
1.23      daniel   1484:        return(NULL);
                   1485:     }
1.90      daniel   1486:     memset(cur, 0, sizeof(xmlNode));
                   1487:     cur->type = XML_ENTITY_REF_NODE;
1.23      daniel   1488: 
1.28      daniel   1489:     cur->doc = doc;
1.23      daniel   1490:     if (name[0] == '&') {
                   1491:         int len;
                   1492:         name++;
                   1493:        len = xmlStrlen(name);
                   1494:        if (name[len - 1] == ';')
                   1495:            cur->name = xmlStrndup(name, len - 1);
                   1496:        else
                   1497:            cur->name = xmlStrndup(name, len);
                   1498:     } else
                   1499:        cur->name = xmlStrdup(name);
                   1500: 
                   1501:     ent = xmlGetDocEntity(doc, cur->name);
1.70      daniel   1502:     if (ent != NULL) {
                   1503: #ifndef XML_USE_BUFFER_CONTENT
1.23      daniel   1504:        cur->content = ent->content;
1.70      daniel   1505: #else
                   1506:        /*
                   1507:         * CJN 11.18.99 this might be a problem, since the xmlBuffer gets
                   1508:         * a copy of this pointer.  Let's hope we don't manipulate it
                   1509:         * later 
                   1510:         */
                   1511:        cur->content = xmlBufferCreateSize(0);
                   1512:        xmlBufferSetAllocationScheme(cur->content,
                   1513:                                     xmlGetBufferAllocationScheme());
                   1514:        if (ent->content != NULL)
                   1515:            xmlBufferAdd(cur->content, ent->content, -1);
                   1516: #endif
1.140     veillard 1517:        /*
                   1518:         * The parent pointer in entity is a Dtd pointer and thus is NOT
                   1519:         * updated.  Not sure if this is 100% correct.
                   1520:         *  -George
                   1521:         */
1.99      daniel   1522:        cur->children = (xmlNodePtr) ent;
1.140     veillard 1523:        cur->last = (xmlNodePtr) ent;
1.90      daniel   1524:     }
1.23      daniel   1525:     return(cur);
                   1526: }
                   1527: 
                   1528: /**
                   1529:  * xmlNewDocText:
                   1530:  * @doc: the document
                   1531:  * @content:  the text content
                   1532:  *
                   1533:  * Creation of a new text node within a document.
1.36      daniel   1534:  * Returns a pointer to the new node object.
1.23      daniel   1535:  */
1.28      daniel   1536: xmlNodePtr
1.61      daniel   1537: xmlNewDocText(xmlDocPtr doc, const xmlChar *content) {
1.23      daniel   1538:     xmlNodePtr cur;
                   1539: 
                   1540:     cur = xmlNewText(content);
                   1541:     if (cur != NULL) cur->doc = doc;
                   1542:     return(cur);
                   1543: }
                   1544: 
                   1545: /**
                   1546:  * xmlNewTextLen:
                   1547:  * @content:  the text content
                   1548:  * @len:  the text len.
                   1549:  *
                   1550:  * Creation of a new text node with an extra parameter for the content's lenght
1.36      daniel   1551:  * Returns a pointer to the new node object.
1.21      daniel   1552:  */
1.28      daniel   1553: xmlNodePtr
1.61      daniel   1554: xmlNewTextLen(const xmlChar *content, int len) {
1.21      daniel   1555:     xmlNodePtr cur;
                   1556: 
                   1557:     /*
                   1558:      * Allocate a new node and fill the fields.
                   1559:      */
1.57      daniel   1560:     cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
1.21      daniel   1561:     if (cur == NULL) {
1.134     veillard 1562:         xmlGenericError(xmlGenericErrorContext,
                   1563:                "xmlNewText : malloc failed\n");
1.21      daniel   1564:        return(NULL);
                   1565:     }
1.90      daniel   1566:     memset(cur, 0, sizeof(xmlNode));
                   1567:     cur->type = XML_TEXT_NODE;
1.21      daniel   1568: 
                   1569:     cur->name = xmlStrdup(xmlStringText);
1.70      daniel   1570:     if (content != NULL) {
                   1571: #ifndef XML_USE_BUFFER_CONTENT
1.21      daniel   1572:        cur->content = xmlStrndup(content, len);
1.70      daniel   1573: #else
                   1574:        cur->content = xmlBufferCreateSize(len);
                   1575:        xmlBufferSetAllocationScheme(cur->content,
                   1576:                                     xmlGetBufferAllocationScheme());
                   1577:        xmlBufferAdd(cur->content, content, len);
                   1578: #endif
1.90      daniel   1579:     }
1.21      daniel   1580:     return(cur);
                   1581: }
                   1582: 
1.23      daniel   1583: /**
                   1584:  * xmlNewDocTextLen:
                   1585:  * @doc: the document
                   1586:  * @content:  the text content
                   1587:  * @len:  the text len.
                   1588:  *
                   1589:  * Creation of a new text node with an extra content lenght parameter. The
                   1590:  * text node pertain to a given document.
1.36      daniel   1591:  * Returns a pointer to the new node object.
1.23      daniel   1592:  */
1.28      daniel   1593: xmlNodePtr
1.61      daniel   1594: xmlNewDocTextLen(xmlDocPtr doc, const xmlChar *content, int len) {
1.23      daniel   1595:     xmlNodePtr cur;
                   1596: 
                   1597:     cur = xmlNewTextLen(content, len);
                   1598:     if (cur != NULL) cur->doc = doc;
                   1599:     return(cur);
                   1600: }
                   1601: 
                   1602: /**
                   1603:  * xmlNewComment:
                   1604:  * @content:  the comment content
                   1605:  *
                   1606:  * Creation of a new node containing a comment.
1.36      daniel   1607:  * Returns a pointer to the new node object.
1.14      daniel   1608:  */
1.28      daniel   1609: xmlNodePtr
1.61      daniel   1610: xmlNewComment(const xmlChar *content) {
1.14      daniel   1611:     xmlNodePtr cur;
                   1612: 
                   1613:     /*
                   1614:      * Allocate a new node and fill the fields.
                   1615:      */
1.57      daniel   1616:     cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
1.14      daniel   1617:     if (cur == NULL) {
1.134     veillard 1618:         xmlGenericError(xmlGenericErrorContext,
                   1619:                "xmlNewComment : malloc failed\n");
1.14      daniel   1620:        return(NULL);
                   1621:     }
1.90      daniel   1622:     memset(cur, 0, sizeof(xmlNode));
                   1623:     cur->type = XML_COMMENT_NODE;
1.14      daniel   1624: 
1.90      daniel   1625:     cur->name = xmlStrdup(xmlStringComment);
1.70      daniel   1626:     if (content != NULL) {
                   1627: #ifndef XML_USE_BUFFER_CONTENT
1.14      daniel   1628:        cur->content = xmlStrdup(content);
1.70      daniel   1629: #else
                   1630:        cur->content = xmlBufferCreateSize(0);
                   1631:        xmlBufferSetAllocationScheme(cur->content,
                   1632:                                     xmlGetBufferAllocationScheme());
                   1633:        xmlBufferAdd(cur->content, content, -1);
                   1634: #endif
1.90      daniel   1635:     }
1.14      daniel   1636:     return(cur);
                   1637: }
                   1638: 
1.23      daniel   1639: /**
1.50      daniel   1640:  * xmlNewCDataBlock:
                   1641:  * @doc:  the document
                   1642:  * @content:  the CData block content content
                   1643:  * @len:  the length of the block
                   1644:  *
                   1645:  * Creation of a new node containing a CData block.
                   1646:  * Returns a pointer to the new node object.
                   1647:  */
                   1648: xmlNodePtr
1.61      daniel   1649: xmlNewCDataBlock(xmlDocPtr doc, const xmlChar *content, int len) {
1.50      daniel   1650:     xmlNodePtr cur;
                   1651: 
                   1652:     /*
                   1653:      * Allocate a new node and fill the fields.
                   1654:      */
1.57      daniel   1655:     cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
1.50      daniel   1656:     if (cur == NULL) {
1.134     veillard 1657:         xmlGenericError(xmlGenericErrorContext,
                   1658:                "xmlNewCDataBlock : malloc failed\n");
1.50      daniel   1659:        return(NULL);
                   1660:     }
1.90      daniel   1661:     memset(cur, 0, sizeof(xmlNode));
                   1662:     cur->type = XML_CDATA_SECTION_NODE;
1.50      daniel   1663: 
1.70      daniel   1664:     if (content != NULL) {
                   1665: #ifndef XML_USE_BUFFER_CONTENT
1.50      daniel   1666:        cur->content = xmlStrndup(content, len);
1.70      daniel   1667: #else
                   1668:        cur->content = xmlBufferCreateSize(len);
                   1669:        xmlBufferSetAllocationScheme(cur->content,
                   1670:                                     xmlGetBufferAllocationScheme());
                   1671:        xmlBufferAdd(cur->content, content, len);
                   1672: #endif
1.90      daniel   1673:     }
1.50      daniel   1674:     return(cur);
                   1675: }
                   1676: 
                   1677: /**
1.36      daniel   1678:  * xmlNewDocComment:
1.23      daniel   1679:  * @doc:  the document
                   1680:  * @content:  the comment content
                   1681:  *
                   1682:  * Creation of a new node containing a commentwithin a document.
1.36      daniel   1683:  * Returns a pointer to the new node object.
1.23      daniel   1684:  */
1.28      daniel   1685: xmlNodePtr
1.61      daniel   1686: xmlNewDocComment(xmlDocPtr doc, const xmlChar *content) {
1.23      daniel   1687:     xmlNodePtr cur;
                   1688: 
                   1689:     cur = xmlNewComment(content);
                   1690:     if (cur != NULL) cur->doc = doc;
                   1691:     return(cur);
                   1692: }
                   1693: 
1.141     veillard 1694: /**
                   1695:  * xmlSetTreeDoc:
                   1696:  * @tree:  the top element
                   1697:  * @doc:  the document
                   1698:  *
                   1699:  * update all nodes under the tree to point to the right document
                   1700:  */
                   1701: void
                   1702: xmlSetTreeDoc(xmlNodePtr tree, xmlDocPtr doc) {
                   1703:     if (tree == NULL)
                   1704:        return;
                   1705:     if (tree->type == XML_ENTITY_DECL)
                   1706:        return;
                   1707:     if (tree->doc != doc) {
                   1708:        if (tree->children != NULL)
                   1709:            xmlSetListDoc(tree->children, doc);
                   1710:        tree->doc = doc;
                   1711:     }
                   1712: }
                   1713: 
                   1714: /**
                   1715:  * xmlSetListDoc:
                   1716:  * @tree:  the first element
                   1717:  * @doc:  the document
                   1718:  *
                   1719:  * update all nodes in the list to point to the right document
                   1720:  */
                   1721: void
                   1722: xmlSetListDoc(xmlNodePtr list, xmlDocPtr doc) {
                   1723:     xmlNodePtr cur;
                   1724: 
                   1725:     if (list == NULL)
                   1726:        return;
                   1727:     cur = list;
                   1728:     while (cur != NULL) {
                   1729:        if (cur->doc != doc)
                   1730:            xmlSetTreeDoc(cur, doc);
                   1731:        cur = cur->next;
                   1732:     }
                   1733: }
                   1734: 
1.68      daniel   1735: 
1.23      daniel   1736: /**
                   1737:  * xmlNewChild:
                   1738:  * @parent:  the parent node
                   1739:  * @ns:  a namespace if any
                   1740:  * @name:  the name of the child
1.68      daniel   1741:  * @content:  the XML content of the child if any.
1.23      daniel   1742:  *
1.90      daniel   1743:  * Creation of a new child element, added at the end of @parent children list.
1.24      daniel   1744:  * @ns and @content parameters are optionnal (NULL). If content is non NULL,
                   1745:  * a child list containing the TEXTs and ENTITY_REFs node will be created.
1.68      daniel   1746:  * NOTE: @content is supposed to be a piece of XML CDATA, so it allow entities
                   1747:  *       references, but XML special chars need to be escaped first by using
                   1748:  *       xmlEncodeEntitiesReentrant(). Use xmlNewTextChild() if entities
                   1749:  *       support is not needed.
                   1750:  *
1.36      daniel   1751:  * Returns a pointer to the new node object.
1.1       veillard 1752:  */
1.28      daniel   1753: xmlNodePtr
                   1754: xmlNewChild(xmlNodePtr parent, xmlNsPtr ns,
1.68      daniel   1755:             const xmlChar *name, const xmlChar *content) {
1.1       veillard 1756:     xmlNodePtr cur, prev;
                   1757: 
                   1758:     if (parent == NULL) {
1.86      daniel   1759: #ifdef DEBUG_TREE
1.134     veillard 1760:         xmlGenericError(xmlGenericErrorContext,
                   1761:                "xmlNewChild : parent == NULL\n");
1.86      daniel   1762: #endif
1.1       veillard 1763:        return(NULL);
                   1764:     }
                   1765: 
                   1766:     if (name == NULL) {
1.86      daniel   1767: #ifdef DEBUG_TREE
1.134     veillard 1768:         xmlGenericError(xmlGenericErrorContext,
                   1769:                "xmlNewChild : name == NULL\n");
1.86      daniel   1770: #endif
1.1       veillard 1771:        return(NULL);
                   1772:     }
                   1773: 
                   1774:     /*
                   1775:      * Allocate a new node
                   1776:      */
1.16      daniel   1777:     if (ns == NULL)
1.24      daniel   1778:        cur = xmlNewDocNode(parent->doc, parent->ns, name, content);
1.1       veillard 1779:     else
1.24      daniel   1780:        cur = xmlNewDocNode(parent->doc, ns, name, content);
1.1       veillard 1781:     if (cur == NULL) return(NULL);
                   1782: 
                   1783:     /*
1.90      daniel   1784:      * add the new element at the end of the children list.
1.1       veillard 1785:      */
1.25      daniel   1786:     cur->type = XML_ELEMENT_NODE;
1.1       veillard 1787:     cur->parent = parent;
1.23      daniel   1788:     cur->doc = parent->doc;
1.90      daniel   1789:     if (parent->children == NULL) {
                   1790:         parent->children = cur;
1.32      daniel   1791:        parent->last = cur;
1.1       veillard 1792:     } else {
1.32      daniel   1793:         prev = parent->last;
1.1       veillard 1794:        prev->next = cur;
1.23      daniel   1795:        cur->prev = prev;
1.32      daniel   1796:        parent->last = cur;
1.1       veillard 1797:     }
                   1798: 
                   1799:     return(cur);
                   1800: }
                   1801: 
1.23      daniel   1802: /**
1.78      daniel   1803:  * xmlAddNextSibling:
                   1804:  * @cur:  the child node
                   1805:  * @elem:  the new node
                   1806:  *
                   1807:  * Add a new element @elem as the next siblings of @cur
                   1808:  * If the new element was already inserted in a document it is
                   1809:  * first unlinked from its existing context.
1.131     veillard 1810:  * As a result of text merging @elem may be freed.
1.78      daniel   1811:  *
                   1812:  * Returns the new element or NULL in case of error.
                   1813:  */
                   1814: xmlNodePtr
                   1815: xmlAddNextSibling(xmlNodePtr cur, xmlNodePtr elem) {
                   1816:     if (cur == NULL) {
1.86      daniel   1817: #ifdef DEBUG_TREE
1.134     veillard 1818:         xmlGenericError(xmlGenericErrorContext,
                   1819:                "xmlAddNextSibling : cur == NULL\n");
1.86      daniel   1820: #endif
1.78      daniel   1821:        return(NULL);
                   1822:     }
                   1823:     if (elem == NULL) {
1.86      daniel   1824: #ifdef DEBUG_TREE
1.134     veillard 1825:         xmlGenericError(xmlGenericErrorContext,
                   1826:                "xmlAddNextSibling : elem == NULL\n");
1.86      daniel   1827: #endif
1.78      daniel   1828:        return(NULL);
                   1829:     }
                   1830: 
                   1831:     xmlUnlinkNode(elem);
1.131     veillard 1832: 
                   1833:     if (elem->type == XML_TEXT_NODE) {
                   1834:        if (cur->type == XML_TEXT_NODE) {
                   1835: #ifndef XML_USE_BUFFER_CONTENT
                   1836:            xmlNodeAddContent(cur, elem->content);
                   1837: #else
                   1838:            xmlNodeAddContent(cur, xmlBufferContent(elem->content));
                   1839: #endif
                   1840:            xmlFreeNode(elem);
                   1841:            return(cur);
                   1842:        }
                   1843:        if ((cur->next != NULL) && (cur->type == XML_TEXT_NODE)) {
                   1844: #ifndef XML_USE_BUFFER_CONTENT
                   1845:            xmlChar *tmp;
                   1846: 
                   1847:            tmp = xmlStrdup(elem->content);
                   1848:            tmp = xmlStrcat(tmp, cur->next->content);
                   1849:            xmlNodeSetContent(cur->next, tmp);
                   1850:            xmlFree(tmp);
                   1851: #else
1.137     veillard 1852:            xmlBufferAddHead(cur->next->content,
                   1853:                             xmlBufferContent(elem->content),
1.131     veillard 1854:                             xmlBufferLength(elem->content));
                   1855: #endif
                   1856:            xmlFreeNode(elem);
                   1857:            return(cur->next);
                   1858:        }
                   1859:     }
                   1860: 
1.141     veillard 1861:     if (elem->doc != cur->doc) {
                   1862:        xmlSetTreeDoc(elem, cur->doc);
                   1863:     }
1.78      daniel   1864:     elem->parent = cur->parent;
1.102     daniel   1865:     elem->prev = cur;
                   1866:     elem->next = cur->next;
                   1867:     cur->next = elem;
                   1868:     if (elem->next != NULL)
                   1869:        elem->next->prev = elem;
                   1870:     if ((elem->parent != NULL) && (elem->parent->last == cur))
                   1871:        elem->parent->last = elem;
1.78      daniel   1872:     return(elem);
                   1873: }
                   1874: 
                   1875: /**
                   1876:  * xmlAddPrevSibling:
                   1877:  * @cur:  the child node
                   1878:  * @elem:  the new node
                   1879:  *
                   1880:  * Add a new element @elem as the previous siblings of @cur
1.131     veillard 1881:  * merging adjacent TEXT nodes (@elem may be freed)
1.78      daniel   1882:  * If the new element was already inserted in a document it is
                   1883:  * first unlinked from its existing context.
                   1884:  *
                   1885:  * Returns the new element or NULL in case of error.
                   1886:  */
                   1887: xmlNodePtr
                   1888: xmlAddPrevSibling(xmlNodePtr cur, xmlNodePtr elem) {
                   1889:     if (cur == NULL) {
1.86      daniel   1890: #ifdef DEBUG_TREE
1.134     veillard 1891:         xmlGenericError(xmlGenericErrorContext,
                   1892:                "xmlAddPrevSibling : cur == NULL\n");
1.86      daniel   1893: #endif
1.78      daniel   1894:        return(NULL);
                   1895:     }
                   1896:     if (elem == NULL) {
1.86      daniel   1897: #ifdef DEBUG_TREE
1.134     veillard 1898:         xmlGenericError(xmlGenericErrorContext,
                   1899:                "xmlAddPrevSibling : elem == NULL\n");
1.86      daniel   1900: #endif
1.78      daniel   1901:        return(NULL);
                   1902:     }
                   1903: 
                   1904:     xmlUnlinkNode(elem);
1.131     veillard 1905: 
                   1906:     if (elem->type == XML_TEXT_NODE) {
                   1907:        if (cur->type == XML_TEXT_NODE) {
                   1908: #ifndef XML_USE_BUFFER_CONTENT
                   1909:            xmlChar *tmp;
                   1910: 
                   1911:            tmp = xmlStrdup(elem->content);
                   1912:            tmp = xmlStrcat(tmp, cur->content);
                   1913:            xmlNodeSetContent(cur, tmp);
                   1914:            xmlFree(tmp);
                   1915: #else
                   1916:            xmlBufferAddHead(cur->content, xmlBufferContent(elem->content), 
                   1917:                             xmlBufferLength(elem->content));
                   1918: #endif
                   1919:            xmlFreeNode(elem);
                   1920:            return(cur);
                   1921:        }
                   1922:        if ((cur->prev != NULL) && (cur->prev->type == XML_TEXT_NODE)) {
                   1923: #ifndef XML_USE_BUFFER_CONTENT
                   1924:            xmlNodeAddContent(cur->prev, elem->content);
                   1925: #else
                   1926:            xmlNodeAddContent(cur->prev, xmlBufferContent(elem->content));
                   1927: #endif
                   1928:            xmlFreeNode(elem);
                   1929:            return(cur->prev);
                   1930:        }
                   1931:     }
                   1932: 
1.141     veillard 1933:     if (elem->doc != cur->doc) {
                   1934:        xmlSetTreeDoc(elem, cur->doc);
                   1935:     }
1.78      daniel   1936:     elem->parent = cur->parent;
1.102     daniel   1937:     elem->next = cur;
                   1938:     elem->prev = cur->prev;
                   1939:     cur->prev = elem;
                   1940:     if (elem->prev != NULL)
                   1941:        elem->prev->next = elem;
                   1942:     if ((elem->parent != NULL) && (elem->parent->children == cur))
                   1943:        elem->parent->children = elem;
1.78      daniel   1944:     return(elem);
                   1945: }
                   1946: 
                   1947: /**
1.52      daniel   1948:  * xmlAddSibling:
                   1949:  * @cur:  the child node
                   1950:  * @elem:  the new node
                   1951:  *
1.78      daniel   1952:  * Add a new element @elem to the list of siblings of @cur
1.131     veillard 1953:  * merging adjacent TEXT nodes (@elem may be freed)
1.78      daniel   1954:  * If the new element was already inserted in a document it is
                   1955:  * first unlinked from its existing context.
                   1956:  *
                   1957:  * Returns the new element or NULL in case of error.
1.52      daniel   1958:  */
                   1959: xmlNodePtr
                   1960: xmlAddSibling(xmlNodePtr cur, xmlNodePtr elem) {
                   1961:     xmlNodePtr parent;
                   1962: 
                   1963:     if (cur == NULL) {
1.86      daniel   1964: #ifdef DEBUG_TREE
1.134     veillard 1965:         xmlGenericError(xmlGenericErrorContext,
                   1966:                "xmlAddSibling : cur == NULL\n");
1.86      daniel   1967: #endif
1.52      daniel   1968:        return(NULL);
                   1969:     }
                   1970: 
                   1971:     if (elem == NULL) {
1.86      daniel   1972: #ifdef DEBUG_TREE
1.134     veillard 1973:         xmlGenericError(xmlGenericErrorContext,
                   1974:                "xmlAddSibling : elem == NULL\n");
1.86      daniel   1975: #endif
1.52      daniel   1976:        return(NULL);
                   1977:     }
                   1978: 
1.78      daniel   1979:     /*
                   1980:      * Constant time is we can rely on the ->parent->last to find
                   1981:      * the last sibling.
                   1982:      */
                   1983:     if ((cur->parent != NULL) && 
1.90      daniel   1984:        (cur->parent->children != NULL) &&
1.78      daniel   1985:        (cur->parent->last != NULL) &&
                   1986:        (cur->parent->last->next == NULL)) {
                   1987:        cur = cur->parent->last;
                   1988:     } else {
                   1989:        while (cur->next != NULL) cur = cur->next;
1.52      daniel   1990:     }
                   1991: 
1.78      daniel   1992:     xmlUnlinkNode(elem);
1.131     veillard 1993: 
                   1994:     if ((cur->type == XML_TEXT_NODE) && (elem->type == XML_TEXT_NODE)) {
                   1995: #ifndef XML_USE_BUFFER_CONTENT
                   1996:        xmlNodeAddContent(cur, elem->content);
                   1997: #else
                   1998:        xmlNodeAddContent(cur, xmlBufferContent(elem->content));
                   1999: #endif
                   2000:        xmlFreeNode(elem);
                   2001:        return(cur);
                   2002:     }
                   2003: 
1.141     veillard 2004:     if (elem->doc != cur->doc) {
                   2005:        xmlSetTreeDoc(elem, cur->doc);
                   2006:     }
1.52      daniel   2007:     parent = cur->parent;
                   2008:     elem->prev = cur;
                   2009:     elem->next = NULL;
                   2010:     elem->parent = parent;
                   2011:     cur->next = elem;
                   2012:     if (parent != NULL)
                   2013:        parent->last = elem;
                   2014: 
                   2015:     return(elem);
                   2016: }
                   2017: 
                   2018: /**
1.117     veillard 2019:  * xmlAddChildList:
                   2020:  * @parent:  the parent node
                   2021:  * @cur:  the first node in the list
                   2022:  *
                   2023:  * Add a list of node at the end of the child list of the parent
1.131     veillard 2024:  * merging adjacent TEXT nodes (@cur may be freed)
1.117     veillard 2025:  *
                   2026:  * Returns the last child or NULL in case of error.
                   2027:  */
                   2028: xmlNodePtr
                   2029: xmlAddChildList(xmlNodePtr parent, xmlNodePtr cur) {
                   2030:     xmlNodePtr prev;
                   2031: 
                   2032:     if (parent == NULL) {
                   2033: #ifdef DEBUG_TREE
1.134     veillard 2034:         xmlGenericError(xmlGenericErrorContext,
                   2035:                "xmlAddChild : parent == NULL\n");
1.117     veillard 2036: #endif
                   2037:        return(NULL);
                   2038:     }
                   2039: 
                   2040:     if (cur == NULL) {
                   2041: #ifdef DEBUG_TREE
1.134     veillard 2042:         xmlGenericError(xmlGenericErrorContext,
                   2043:                "xmlAddChild : child == NULL\n");
1.117     veillard 2044: #endif
                   2045:        return(NULL);
                   2046:     }
                   2047: 
                   2048:     if ((cur->doc != NULL) && (parent->doc != NULL) &&
                   2049:         (cur->doc != parent->doc)) {
                   2050: #ifdef DEBUG_TREE
1.134     veillard 2051:        xmlGenericError(xmlGenericErrorContext,
                   2052:                "Elements moved to a different document\n");
1.117     veillard 2053: #endif
                   2054:     }
                   2055: 
                   2056:     /*
                   2057:      * add the first element at the end of the children list.
                   2058:      */
                   2059:     if (parent->children == NULL) {
                   2060:         parent->children = cur;
                   2061:     } else {
1.131     veillard 2062:        /*
                   2063:         * If cur and parent->last both are TEXT nodes, then merge them.
                   2064:         */
                   2065:        if ((cur->type == XML_TEXT_NODE) && 
                   2066:            (parent->last->type == XML_TEXT_NODE)) {
                   2067: #ifndef XML_USE_BUFFER_CONTENT
                   2068:            xmlNodeAddContent(parent->last, cur->content);
                   2069: #else
                   2070:            xmlNodeAddContent(parent->last, xmlBufferContent(cur->content));
                   2071: #endif
                   2072:            /*
                   2073:             * if it's the only child, nothing more to be done.
                   2074:             */
                   2075:            if (cur->next == NULL) {
                   2076:                xmlFreeNode(cur);
                   2077:                return(parent->last);
                   2078:            }
                   2079:            prev = cur;
                   2080:            cur = cur->next;
                   2081:            xmlFreeNode(prev);
                   2082:        }
1.117     veillard 2083:         prev = parent->last;
                   2084:        prev->next = cur;
                   2085:        cur->prev = prev;
                   2086:     }
                   2087:     while (cur->next != NULL) {
                   2088:        cur->parent = parent;
1.141     veillard 2089:        if (cur->doc != parent->doc) {
                   2090:            xmlSetTreeDoc(cur, parent->doc);
                   2091:        }
1.117     veillard 2092:         cur = cur->next;
                   2093:     }
                   2094:     cur->parent = parent;
                   2095:     cur->doc = parent->doc; /* the parent may not be linked to a doc ! */
                   2096:     parent->last = cur;
                   2097: 
                   2098:     return(cur);
                   2099: }
                   2100: 
                   2101: /**
1.23      daniel   2102:  * xmlAddChild:
                   2103:  * @parent:  the parent node
                   2104:  * @cur:  the child node
                   2105:  *
1.131     veillard 2106:  * Add a new child element, to @parent, at the end of the child list
                   2107:  * merging adjacent TEXT nodes (in which case @cur is freed)
1.36      daniel   2108:  * Returns the child or NULL in case of error.
1.2       veillard 2109:  */
1.28      daniel   2110: xmlNodePtr
                   2111: xmlAddChild(xmlNodePtr parent, xmlNodePtr cur) {
1.2       veillard 2112:     xmlNodePtr prev;
                   2113: 
                   2114:     if (parent == NULL) {
1.86      daniel   2115: #ifdef DEBUG_TREE
1.134     veillard 2116:         xmlGenericError(xmlGenericErrorContext,
                   2117:                "xmlAddChild : parent == NULL\n");
1.86      daniel   2118: #endif
1.2       veillard 2119:        return(NULL);
                   2120:     }
                   2121: 
                   2122:     if (cur == NULL) {
1.86      daniel   2123: #ifdef DEBUG_TREE
1.134     veillard 2124:         xmlGenericError(xmlGenericErrorContext,
                   2125:                "xmlAddChild : child == NULL\n");
1.86      daniel   2126: #endif
1.2       veillard 2127:        return(NULL);
                   2128:     }
                   2129: 
1.23      daniel   2130:     if ((cur->doc != NULL) && (parent->doc != NULL) &&
                   2131:         (cur->doc != parent->doc)) {
1.86      daniel   2132: #ifdef DEBUG_TREE
1.134     veillard 2133:        xmlGenericError(xmlGenericErrorContext,
                   2134:                "Elements moved to a different document\n");
1.86      daniel   2135: #endif
1.131     veillard 2136:     }
                   2137: 
                   2138:     /*
                   2139:      * If cur is a TEXT node, merge its content with adjacent TEXT nodes
                   2140:      * or with parent->content if parent->content != NULL.
                   2141:      * cur is then freed.
                   2142:      */
                   2143:     if (cur->type == XML_TEXT_NODE) {
                   2144:        if (((parent->type == XML_ELEMENT_NODE) || 
                   2145:             (parent->type == XML_TEXT_NODE)) &&
                   2146:            (parent->content != NULL)) {
                   2147: #ifndef XML_USE_BUFFER_CONTENT
                   2148:            xmlNodeAddContent(parent, cur->content);
                   2149: #else
                   2150:            xmlNodeAddContent(parent, xmlBufferContent(cur->content));
                   2151: #endif
                   2152:            xmlFreeNode(cur);
                   2153:            return(parent);
                   2154:        }
                   2155:        if ((parent->last != NULL) && (parent->last->type == XML_TEXT_NODE)) {
                   2156: #ifndef XML_USE_BUFFER_CONTENT
                   2157:            xmlNodeAddContent(parent->last, cur->content);
                   2158: #else
                   2159:            xmlNodeAddContent(parent->last, xmlBufferContent(cur->content));
                   2160: #endif
                   2161:            xmlFreeNode(cur);
                   2162:            return(parent->last);
                   2163:        }
1.23      daniel   2164:     }
                   2165: 
1.2       veillard 2166:     /*
1.90      daniel   2167:      * add the new element at the end of the children list.
1.2       veillard 2168:      */
                   2169:     cur->parent = parent;
1.141     veillard 2170:     if (cur->doc != parent->doc) {
                   2171:        xmlSetTreeDoc(cur, parent->doc);
                   2172:     }
1.32      daniel   2173: 
1.24      daniel   2174:     /*
                   2175:      * Handle the case where parent->content != NULL, in that case it will
                   2176:      * create a intermediate TEXT node.
                   2177:      */
1.93      daniel   2178:     if (((parent->type == XML_ELEMENT_NODE) || (parent->type == XML_TEXT_NODE)) &&
                   2179:        (parent->content != NULL)) {
1.24      daniel   2180:         xmlNodePtr text;
                   2181:        
1.70      daniel   2182: #ifndef XML_USE_BUFFER_CONTENT
1.24      daniel   2183:        text = xmlNewDocText(parent->doc, parent->content);
1.70      daniel   2184: #else
                   2185:        text = xmlNewDocText(parent->doc, xmlBufferContent(parent->content));
                   2186: #endif
1.24      daniel   2187:        if (text != NULL) {
1.90      daniel   2188:            text->next = parent->children;
1.24      daniel   2189:            if (text->next != NULL)
                   2190:                text->next->prev = text;
1.90      daniel   2191:            parent->children = text;
1.140     veillard 2192:            UPDATE_LAST_CHILD_AND_PARENT(parent)
1.70      daniel   2193: #ifndef XML_USE_BUFFER_CONTENT
1.57      daniel   2194:            xmlFree(parent->content);
1.70      daniel   2195: #else
                   2196:            xmlBufferFree(parent->content);
                   2197: #endif
1.24      daniel   2198:            parent->content = NULL;
                   2199:        }
                   2200:     }
1.90      daniel   2201:     if (parent->children == NULL) {
                   2202:         parent->children = cur;
1.32      daniel   2203:        parent->last = cur;
1.2       veillard 2204:     } else {
1.32      daniel   2205:         prev = parent->last;
1.2       veillard 2206:        prev->next = cur;
1.23      daniel   2207:        cur->prev = prev;
1.32      daniel   2208:        parent->last = cur;
1.2       veillard 2209:     }
                   2210: 
                   2211:     return(cur);
                   2212: }
                   2213: 
1.23      daniel   2214: /**
                   2215:  * xmlGetLastChild:
                   2216:  * @parent:  the parent node
                   2217:  *
                   2218:  * Search the last child of a node.
1.36      daniel   2219:  * Returns the last child or NULL if none.
1.21      daniel   2220:  */
1.28      daniel   2221: xmlNodePtr
                   2222: xmlGetLastChild(xmlNodePtr parent) {
1.21      daniel   2223:     if (parent == NULL) {
1.86      daniel   2224: #ifdef DEBUG_TREE
1.134     veillard 2225:         xmlGenericError(xmlGenericErrorContext,
                   2226:                "xmlGetLastChild : parent == NULL\n");
1.86      daniel   2227: #endif
1.21      daniel   2228:        return(NULL);
                   2229:     }
1.32      daniel   2230:     return(parent->last);
1.21      daniel   2231: }
                   2232: 
1.23      daniel   2233: /**
                   2234:  * xmlFreeNodeList:
                   2235:  * @cur:  the first node in the list
                   2236:  *
                   2237:  * Free a node and all its siblings, this is a recursive behaviour, all
1.90      daniel   2238:  * the children are freed too.
1.1       veillard 2239:  */
1.28      daniel   2240: void
                   2241: xmlFreeNodeList(xmlNodePtr cur) {
1.1       veillard 2242:     xmlNodePtr next;
                   2243:     if (cur == NULL) {
1.86      daniel   2244: #ifdef DEBUG_TREE
1.134     veillard 2245:         xmlGenericError(xmlGenericErrorContext,
                   2246:                "xmlFreeNodeList : node == NULL\n");
1.86      daniel   2247: #endif
1.1       veillard 2248:        return;
                   2249:     }
                   2250:     while (cur != NULL) {
                   2251:         next = cur->next;
                   2252:         xmlFreeNode(cur);
                   2253:        cur = next;
                   2254:     }
                   2255: }
                   2256: 
1.23      daniel   2257: /**
                   2258:  * xmlFreeNode:
                   2259:  * @cur:  the node
                   2260:  *
1.90      daniel   2261:  * Free a node, this is a recursive behaviour, all the children are freed too.
1.97      daniel   2262:  * This doesn't unlink the child from the list, use xmlUnlinkNode() first.
1.1       veillard 2263:  */
1.28      daniel   2264: void
                   2265: xmlFreeNode(xmlNodePtr cur) {
1.1       veillard 2266:     if (cur == NULL) {
1.86      daniel   2267: #ifdef DEBUG_TREE
1.134     veillard 2268:         xmlGenericError(xmlGenericErrorContext,
                   2269:                "xmlFreeNode : node == NULL\n");
1.86      daniel   2270: #endif
1.1       veillard 2271:        return;
                   2272:     }
1.92      daniel   2273:     if (cur->type == XML_DTD_NODE)
                   2274:        return;
1.23      daniel   2275:     cur->doc = NULL;
                   2276:     cur->parent = NULL;
                   2277:     cur->next = NULL;
                   2278:     cur->prev = NULL;
1.99      daniel   2279:     if ((cur->children != NULL) &&
                   2280:        (cur->type != XML_ENTITY_REF_NODE))
                   2281:        xmlFreeNodeList(cur->children);
1.1       veillard 2282:     if (cur->properties != NULL) xmlFreePropList(cur->properties);
1.23      daniel   2283:     if (cur->type != XML_ENTITY_REF_NODE)
1.70      daniel   2284: #ifndef XML_USE_BUFFER_CONTENT
1.57      daniel   2285:        if (cur->content != NULL) xmlFree(cur->content);
1.70      daniel   2286: #else
                   2287:        if (cur->content != NULL) xmlBufferFree(cur->content);
                   2288: #endif
1.57      daniel   2289:     if (cur->name != NULL) xmlFree((char *) cur->name);
1.19      daniel   2290:     if (cur->nsDef != NULL) xmlFreeNsList(cur->nsDef);
1.1       veillard 2291:     memset(cur, -1, sizeof(xmlNode));
1.57      daniel   2292:     xmlFree(cur);
1.1       veillard 2293: }
                   2294: 
1.28      daniel   2295: /**
                   2296:  * xmlUnlinkNode:
                   2297:  * @cur:  the node
                   2298:  *
                   2299:  * Unlink a node from it's current context, the node is not freed
                   2300:  */
                   2301: void
                   2302: xmlUnlinkNode(xmlNodePtr cur) {
                   2303:     if (cur == NULL) {
1.86      daniel   2304: #ifdef DEBUG_TREE
1.134     veillard 2305:         xmlGenericError(xmlGenericErrorContext,
                   2306:                "xmlUnlinkNode : node == NULL\n");
1.86      daniel   2307: #endif
1.28      daniel   2308:        return;
                   2309:     }
1.90      daniel   2310:     if ((cur->parent != NULL) && (cur->parent->children == cur))
                   2311:         cur->parent->children = cur->next;
1.32      daniel   2312:     if ((cur->parent != NULL) && (cur->parent->last == cur))
                   2313:         cur->parent->last = cur->prev;
1.28      daniel   2314:     if (cur->next != NULL)
                   2315:         cur->next->prev = cur->prev;
                   2316:     if (cur->prev != NULL)
                   2317:         cur->prev->next = cur->next;
                   2318:     cur->next = cur->prev = NULL;
                   2319:     cur->parent = NULL;
                   2320: }
                   2321: 
1.78      daniel   2322: /**
                   2323:  * xmlReplaceNode:
                   2324:  * @old:  the old node
                   2325:  * @cur:  the node
                   2326:  *
                   2327:  * Unlink the old node from it's current context, prune the new one
                   2328:  * at the same place. If cur was already inserted in a document it is
                   2329:  * first unlinked from its existing context.
                   2330:  *
                   2331:  * Returns the old node
                   2332:  */
                   2333: xmlNodePtr
                   2334: xmlReplaceNode(xmlNodePtr old, xmlNodePtr cur) {
                   2335:     if (old == NULL) {
1.86      daniel   2336: #ifdef DEBUG_TREE
1.134     veillard 2337:         xmlGenericError(xmlGenericErrorContext,
                   2338:                "xmlReplaceNode : old == NULL\n");
1.86      daniel   2339: #endif
1.78      daniel   2340:        return(NULL);
                   2341:     }
                   2342:     if (cur == NULL) {
                   2343:        xmlUnlinkNode(old);
                   2344:        return(old);
                   2345:     }
1.140     veillard 2346:     if (cur == old) {
                   2347:        return(old);
                   2348:     }
1.78      daniel   2349:     xmlUnlinkNode(cur);
                   2350:     cur->doc = old->doc;
                   2351:     cur->parent = old->parent;
                   2352:     cur->next = old->next;
                   2353:     if (cur->next != NULL)
                   2354:        cur->next->prev = cur;
                   2355:     cur->prev = old->prev;
                   2356:     if (cur->prev != NULL)
                   2357:        cur->prev->next = cur;
                   2358:     if (cur->parent != NULL) {
1.90      daniel   2359:        if (cur->parent->children == old)
                   2360:            cur->parent->children = cur;
1.78      daniel   2361:        if (cur->parent->last == old)
                   2362:            cur->parent->last = cur;
                   2363:     }
                   2364:     old->next = old->prev = NULL;
                   2365:     old->parent = NULL;
                   2366:     return(old);
                   2367: }
                   2368: 
1.1       veillard 2369: /************************************************************************
                   2370:  *                                                                     *
1.31      daniel   2371:  *             Copy operations                                         *
                   2372:  *                                                                     *
                   2373:  ************************************************************************/
                   2374:  
                   2375: /**
                   2376:  * xmlCopyNamespace:
                   2377:  * @cur:  the namespace
                   2378:  *
                   2379:  * Do a copy of the namespace.
                   2380:  *
                   2381:  * Returns: a new xmlNsPtr, or NULL in case of error.
                   2382:  */
                   2383: xmlNsPtr
                   2384: xmlCopyNamespace(xmlNsPtr cur) {
                   2385:     xmlNsPtr ret;
                   2386: 
                   2387:     if (cur == NULL) return(NULL);
                   2388:     switch (cur->type) {
                   2389:        case XML_LOCAL_NAMESPACE:
                   2390:            ret = xmlNewNs(NULL, cur->href, cur->prefix);
                   2391:            break;
                   2392:        default:
1.86      daniel   2393: #ifdef DEBUG_TREE
1.134     veillard 2394:            xmlGenericError(xmlGenericErrorContext,
1.136     veillard 2395:                    "xmlCopyNamespace: invalid type %d\n", cur->type);
1.86      daniel   2396: #endif
1.31      daniel   2397:            return(NULL);
                   2398:     }
                   2399:     return(ret);
                   2400: }
                   2401: 
                   2402: /**
                   2403:  * xmlCopyNamespaceList:
                   2404:  * @cur:  the first namespace
                   2405:  *
                   2406:  * Do a copy of an namespace list.
                   2407:  *
                   2408:  * Returns: a new xmlNsPtr, or NULL in case of error.
                   2409:  */
                   2410: xmlNsPtr
                   2411: xmlCopyNamespaceList(xmlNsPtr cur) {
                   2412:     xmlNsPtr ret = NULL;
                   2413:     xmlNsPtr p = NULL,q;
                   2414: 
                   2415:     while (cur != NULL) {
                   2416:         q = xmlCopyNamespace(cur);
                   2417:        if (p == NULL) {
                   2418:            ret = p = q;
                   2419:        } else {
                   2420:            p->next = q;
                   2421:            p = q;
                   2422:        }
                   2423:        cur = cur->next;
                   2424:     }
                   2425:     return(ret);
                   2426: }
                   2427: 
                   2428: /**
                   2429:  * xmlCopyProp:
1.56      daniel   2430:  * @target:  the element where the attribute will be grafted
1.31      daniel   2431:  * @cur:  the attribute
                   2432:  *
                   2433:  * Do a copy of the attribute.
                   2434:  *
                   2435:  * Returns: a new xmlAttrPtr, or NULL in case of error.
                   2436:  */
                   2437: xmlAttrPtr
1.56      daniel   2438: xmlCopyProp(xmlNodePtr target, xmlAttrPtr cur) {
1.31      daniel   2439:     xmlAttrPtr ret;
                   2440: 
                   2441:     if (cur == NULL) return(NULL);
1.94      daniel   2442:     if (cur->parent != NULL)
                   2443:        ret = xmlNewDocProp(cur->parent->doc, cur->name, NULL);
                   2444:     else if (cur->children != NULL)
1.90      daniel   2445:        ret = xmlNewDocProp(cur->children->doc, cur->name, NULL);
1.31      daniel   2446:     else
                   2447:        ret = xmlNewDocProp(NULL, cur->name, NULL);
                   2448:     if (ret == NULL) return(NULL);
1.94      daniel   2449:     ret->parent = target;
1.56      daniel   2450:     
                   2451:     if ((cur->ns != NULL) && (target != NULL)) {
                   2452:         xmlNsPtr ns;
                   2453: 
                   2454:        ns = xmlSearchNs(target->doc, target, cur->ns->prefix);
                   2455:        ret->ns = ns;
                   2456:     } else
                   2457:         ret->ns = NULL;
                   2458: 
1.140     veillard 2459:     if (cur->children != NULL) {
                   2460:        xmlNodePtr tmp;
                   2461: 
1.90      daniel   2462:        ret->children = xmlCopyNodeList(cur->children);
1.140     veillard 2463:        ret->last = NULL;
                   2464:        tmp = ret->children;
                   2465:        while (tmp != NULL) {
                   2466:            tmp->parent = (xmlNodePtr)ret;
                   2467:            if (tmp->next == NULL)
                   2468:                ret->last = tmp;
                   2469:            tmp = tmp->next;
                   2470:        }
                   2471:     }
1.31      daniel   2472:     return(ret);
                   2473: }
                   2474: 
                   2475: /**
                   2476:  * xmlCopyPropList:
1.56      daniel   2477:  * @target:  the element where the attributes will be grafted
1.31      daniel   2478:  * @cur:  the first attribute
                   2479:  *
                   2480:  * Do a copy of an attribute list.
                   2481:  *
                   2482:  * Returns: a new xmlAttrPtr, or NULL in case of error.
                   2483:  */
                   2484: xmlAttrPtr
1.56      daniel   2485: xmlCopyPropList(xmlNodePtr target, xmlAttrPtr cur) {
1.31      daniel   2486:     xmlAttrPtr ret = NULL;
                   2487:     xmlAttrPtr p = NULL,q;
                   2488: 
                   2489:     while (cur != NULL) {
1.56      daniel   2490:         q = xmlCopyProp(target, cur);
1.31      daniel   2491:        if (p == NULL) {
                   2492:            ret = p = q;
                   2493:        } else {
                   2494:            p->next = q;
1.94      daniel   2495:            q->prev = p;
1.31      daniel   2496:            p = q;
                   2497:        }
                   2498:        cur = cur->next;
                   2499:     }
                   2500:     return(ret);
                   2501: }
                   2502: 
                   2503: /*
1.68      daniel   2504:  * NOTE abeut the CopyNode operations !
1.31      daniel   2505:  *
                   2506:  * They are splitted into external and internal parts for one
                   2507:  * tricky reason: namespaces. Doing a direct copy of a node
                   2508:  * say RPM:Copyright without changing the namespace pointer to
                   2509:  * something else can produce stale links. One way to do it is
                   2510:  * to keep a reference counter but this doesn't work as soon
                   2511:  * as one move the element or the subtree out of the scope of
                   2512:  * the existing namespace. The actual solution seems to add
                   2513:  * a copy of the namespace at the top of the copied tree if
                   2514:  * not available in the subtree.
                   2515:  * Hence two functions, the public front-end call the inner ones
                   2516:  */
                   2517: 
                   2518: static xmlNodePtr
                   2519: xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent);
                   2520: 
                   2521: static xmlNodePtr
                   2522: xmlStaticCopyNode(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent,
                   2523:                   int recursive) {
                   2524:     xmlNodePtr ret;
                   2525: 
                   2526:     if (node == NULL) return(NULL);
                   2527:     /*
                   2528:      * Allocate a new node and fill the fields.
                   2529:      */
1.57      daniel   2530:     ret = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
1.31      daniel   2531:     if (ret == NULL) {
1.134     veillard 2532:         xmlGenericError(xmlGenericErrorContext,
                   2533:                "xmlStaticCopyNode : malloc failed\n");
1.31      daniel   2534:        return(NULL);
                   2535:     }
1.90      daniel   2536:     memset(ret, 0, sizeof(xmlNode));
                   2537:     ret->type = node->type;
1.31      daniel   2538: 
                   2539:     ret->doc = doc;
                   2540:     ret->parent = parent; 
                   2541:     if (node->name != NULL)
                   2542:        ret->name = xmlStrdup(node->name);
1.70      daniel   2543:     if ((node->content != NULL) && (node->type != XML_ENTITY_REF_NODE)) {
                   2544: #ifndef XML_USE_BUFFER_CONTENT
1.31      daniel   2545:        ret->content = xmlStrdup(node->content);
1.70      daniel   2546: #else
                   2547:        ret->content = xmlBufferCreateSize(xmlBufferLength(node->content));
                   2548:        xmlBufferSetAllocationScheme(ret->content,
                   2549:                                     xmlGetBufferAllocationScheme());
                   2550:        xmlBufferAdd(ret->content,
                   2551:                     xmlBufferContent(node->content),
                   2552:                     xmlBufferLength(node->content));
                   2553: #endif
1.90      daniel   2554:     }
1.31      daniel   2555:     if (parent != NULL)
                   2556:         xmlAddChild(parent, ret);
                   2557:     
                   2558:     if (!recursive) return(ret);
                   2559:     if (node->nsDef != NULL)
                   2560:         ret->nsDef = xmlCopyNamespaceList(node->nsDef);
                   2561: 
                   2562:     if (node->ns != NULL) {
                   2563:         xmlNsPtr ns;
                   2564: 
                   2565:        ns = xmlSearchNs(doc, ret, node->ns->prefix);
                   2566:        if (ns == NULL) {
                   2567:            /*
                   2568:             * Humm, we are copying an element whose namespace is defined
                   2569:             * out of the new tree scope. Search it in the original tree
                   2570:             * and add it at the top of the new tree
                   2571:             */
                   2572:            ns = xmlSearchNs(node->doc, node, node->ns->prefix);
                   2573:            if (ns != NULL) {
                   2574:                xmlNodePtr root = ret;
                   2575: 
                   2576:                while (root->parent != NULL) root = root->parent;
                   2577:                xmlNewNs(root, ns->href, ns->prefix);
                   2578:            }
                   2579:        } else {
                   2580:            /*
                   2581:             * reference the existing namespace definition in our own tree.
                   2582:             */
                   2583:            ret->ns = ns;
                   2584:        }
                   2585:     }
1.56      daniel   2586:     if (node->properties != NULL)
                   2587:         ret->properties = xmlCopyPropList(ret, node->properties);
1.90      daniel   2588:     if (node->children != NULL)
                   2589:         ret->children = xmlStaticCopyNodeList(node->children, doc, ret);
1.140     veillard 2590:     UPDATE_LAST_CHILD_AND_PARENT(ret)
1.31      daniel   2591:     return(ret);
                   2592: }
                   2593: 
                   2594: static xmlNodePtr
                   2595: xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent) {
                   2596:     xmlNodePtr ret = NULL;
                   2597:     xmlNodePtr p = NULL,q;
                   2598: 
                   2599:     while (node != NULL) {
                   2600:         q = xmlStaticCopyNode(node, doc, parent, 1);
1.103     daniel   2601:        if (ret == NULL) {
                   2602:            q->prev = NULL;
                   2603:            ret = p = q;
1.31      daniel   2604:        } else {
1.103     daniel   2605:            p->next = q;
                   2606:            q->prev = p;
                   2607:            p = q;
1.31      daniel   2608:        }
                   2609:        node = node->next;
                   2610:     }
                   2611:     return(ret);
                   2612: }
                   2613: 
                   2614: /**
                   2615:  * xmlCopyNode:
                   2616:  * @node:  the node
                   2617:  * @recursive:  if 1 do a recursive copy.
                   2618:  *
                   2619:  * Do a copy of the node.
                   2620:  *
                   2621:  * Returns: a new xmlNodePtr, or NULL in case of error.
                   2622:  */
                   2623: xmlNodePtr
                   2624: xmlCopyNode(xmlNodePtr node, int recursive) {
                   2625:     xmlNodePtr ret;
                   2626: 
                   2627:     ret = xmlStaticCopyNode(node, NULL, NULL, recursive);
                   2628:     return(ret);
                   2629: }
                   2630: 
                   2631: /**
                   2632:  * xmlCopyNodeList:
                   2633:  * @node:  the first node in the list.
                   2634:  *
                   2635:  * Do a recursive copy of the node list.
                   2636:  *
                   2637:  * Returns: a new xmlNodePtr, or NULL in case of error.
                   2638:  */
                   2639: xmlNodePtr xmlCopyNodeList(xmlNodePtr node) {
                   2640:     xmlNodePtr ret = xmlStaticCopyNodeList(node, NULL, NULL);
                   2641:     return(ret);
                   2642: }
                   2643: 
                   2644: /**
                   2645:  * xmlCopyElement:
                   2646:  * @elem:  the element
                   2647:  *
                   2648:  * Do a copy of the element definition.
                   2649:  *
                   2650:  * Returns: a new xmlElementPtr, or NULL in case of error.
                   2651: xmlElementPtr
                   2652: xmlCopyElement(xmlElementPtr elem) {
                   2653:     xmlElementPtr ret;
                   2654: 
                   2655:     if (elem == NULL) return(NULL);
                   2656:     ret = xmlNewDocElement(elem->doc, elem->ns, elem->name, elem->content);
                   2657:     if (ret == NULL) return(NULL);
                   2658:     if (!recursive) return(ret);
                   2659:     if (elem->properties != NULL)
                   2660:         ret->properties = xmlCopyPropList(elem->properties);
                   2661:     
                   2662:     if (elem->nsDef != NULL)
                   2663:         ret->nsDef = xmlCopyNamespaceList(elem->nsDef);
1.90      daniel   2664:     if (elem->children != NULL)
                   2665:         ret->children = xmlCopyElementList(elem->children);
1.31      daniel   2666:     return(ret);
                   2667: }
                   2668:  */
                   2669: 
                   2670: /**
                   2671:  * xmlCopyDtd:
                   2672:  * @dtd:  the dtd
                   2673:  *
                   2674:  * Do a copy of the dtd.
                   2675:  *
                   2676:  * Returns: a new xmlDtdPtr, or NULL in case of error.
                   2677:  */
                   2678: xmlDtdPtr
                   2679: xmlCopyDtd(xmlDtdPtr dtd) {
                   2680:     xmlDtdPtr ret;
                   2681: 
                   2682:     if (dtd == NULL) return(NULL);
                   2683:     ret = xmlNewDtd(NULL, dtd->name, dtd->ExternalID, dtd->SystemID);
                   2684:     if (ret == NULL) return(NULL);
                   2685:     if (dtd->entities != NULL)
                   2686:         ret->entities = (void *) xmlCopyEntitiesTable(
                   2687:                            (xmlEntitiesTablePtr) dtd->entities);
1.35      daniel   2688:     if (dtd->notations != NULL)
                   2689:         ret->notations = (void *) xmlCopyNotationTable(
                   2690:                            (xmlNotationTablePtr) dtd->notations);
                   2691:     if (dtd->elements != NULL)
                   2692:         ret->elements = (void *) xmlCopyElementTable(
                   2693:                            (xmlElementTablePtr) dtd->elements);
                   2694:     if (dtd->attributes != NULL)
                   2695:         ret->attributes = (void *) xmlCopyAttributeTable(
                   2696:                            (xmlAttributeTablePtr) dtd->attributes);
1.31      daniel   2697:     return(ret);
                   2698: }
                   2699: 
                   2700: /**
                   2701:  * xmlCopyDoc:
                   2702:  * @doc:  the document
                   2703:  * @recursive:  if 1 do a recursive copy.
                   2704:  *
                   2705:  * Do a copy of the document info. If recursive, the content tree will
                   2706:  * be copied too as well as Dtd, namespaces and entities.
                   2707:  *
                   2708:  * Returns: a new xmlDocPtr, or NULL in case of error.
                   2709:  */
                   2710: xmlDocPtr
                   2711: xmlCopyDoc(xmlDocPtr doc, int recursive) {
                   2712:     xmlDocPtr ret;
                   2713: 
                   2714:     if (doc == NULL) return(NULL);
                   2715:     ret = xmlNewDoc(doc->version);
                   2716:     if (ret == NULL) return(NULL);
                   2717:     if (doc->name != NULL)
1.57      daniel   2718:         ret->name = xmlMemStrdup(doc->name);
1.31      daniel   2719:     if (doc->encoding != NULL)
                   2720:         ret->encoding = xmlStrdup(doc->encoding);
                   2721:     ret->compression = doc->compression;
                   2722:     ret->standalone = doc->standalone;
                   2723:     if (!recursive) return(ret);
                   2724: 
                   2725:     if (doc->intSubset != NULL)
                   2726:         ret->intSubset = xmlCopyDtd(doc->intSubset);
                   2727:     if (doc->oldNs != NULL)
                   2728:         ret->oldNs = xmlCopyNamespaceList(doc->oldNs);
1.140     veillard 2729:     if (doc->children != NULL) {
                   2730:        xmlNodePtr tmp;
1.103     daniel   2731:         ret->children = xmlStaticCopyNodeList(doc->children, ret,
                   2732:                                              (xmlNodePtr)ret);
1.140     veillard 2733:        ret->last = NULL;
                   2734:        tmp = ret->children;
                   2735:        while (tmp != NULL) {
                   2736:            if (tmp->next == NULL)
                   2737:                ret->last = tmp;
                   2738:            tmp = tmp->next;
                   2739:        }
                   2740:     }
1.31      daniel   2741:     return(ret);
                   2742: }
                   2743: 
                   2744: /************************************************************************
                   2745:  *                                                                     *
1.1       veillard 2746:  *             Content access functions                                *
                   2747:  *                                                                     *
                   2748:  ************************************************************************/
                   2749:  
1.23      daniel   2750: /**
1.75      daniel   2751:  * xmlDocGetRootElement:
                   2752:  * @doc:  the document
                   2753:  *
1.90      daniel   2754:  * Get the root element of the document (doc->children is a list
1.75      daniel   2755:  * containing possibly comments, PIs, etc ...).
                   2756:  *
                   2757:  * Returns the xmlNodePtr for the root or NULL
                   2758:  */
                   2759: xmlNodePtr
                   2760: xmlDocGetRootElement(xmlDocPtr doc) {
                   2761:     xmlNodePtr ret;
                   2762: 
                   2763:     if (doc == NULL) return(NULL);
1.90      daniel   2764:     ret = doc->children;
1.75      daniel   2765:     while (ret != NULL) {
                   2766:        if (ret->type == XML_ELEMENT_NODE)
                   2767:            return(ret);
                   2768:         ret = ret->next;
                   2769:     }
                   2770:     return(ret);
                   2771: }
                   2772:  
                   2773: /**
1.78      daniel   2774:  * xmlDocSetRootElement:
                   2775:  * @doc:  the document
                   2776:  * @root:  the new document root element
                   2777:  *
1.90      daniel   2778:  * Set the root element of the document (doc->children is a list
1.78      daniel   2779:  * containing possibly comments, PIs, etc ...).
                   2780:  *
                   2781:  * Returns the old root element if any was found
                   2782:  */
                   2783: xmlNodePtr
                   2784: xmlDocSetRootElement(xmlDocPtr doc, xmlNodePtr root) {
                   2785:     xmlNodePtr old = NULL;
                   2786: 
                   2787:     if (doc == NULL) return(NULL);
1.90      daniel   2788:     old = doc->children;
1.78      daniel   2789:     while (old != NULL) {
                   2790:        if (old->type == XML_ELEMENT_NODE)
                   2791:            break;
                   2792:         old = old->next;
                   2793:     }
                   2794:     if (old == NULL) {
1.90      daniel   2795:        if (doc->children == NULL) {
                   2796:            doc->children = root;
1.140     veillard 2797:            doc->last = root;
1.78      daniel   2798:        } else {
1.90      daniel   2799:            xmlAddSibling(doc->children, root);
1.78      daniel   2800:        }
                   2801:     } else {
                   2802:        xmlReplaceNode(old, root);
                   2803:     }
                   2804:     return(old);
                   2805: }
                   2806:  
                   2807: /**
1.52      daniel   2808:  * xmlNodeSetLang:
                   2809:  * @cur:  the node being changed
                   2810:  * @lang:  the langage description
                   2811:  *
1.78      daniel   2812:  * Set the language of a node, i.e. the values of the xml:lang
                   2813:  * attribute.
1.52      daniel   2814:  */
                   2815: void
1.61      daniel   2816: xmlNodeSetLang(xmlNodePtr cur, const xmlChar *lang) {
1.78      daniel   2817:     if (cur == NULL) return;
                   2818:     switch(cur->type) {
                   2819:         case XML_TEXT_NODE:
                   2820:         case XML_CDATA_SECTION_NODE:
                   2821:         case XML_COMMENT_NODE:
                   2822:         case XML_DOCUMENT_NODE:
                   2823:         case XML_DOCUMENT_TYPE_NODE:
                   2824:         case XML_DOCUMENT_FRAG_NODE:
                   2825:         case XML_NOTATION_NODE:
                   2826:         case XML_HTML_DOCUMENT_NODE:
1.90      daniel   2827:         case XML_DTD_NODE:
1.91      daniel   2828:         case XML_ELEMENT_DECL:
                   2829:         case XML_ATTRIBUTE_DECL:
1.96      daniel   2830:         case XML_ENTITY_DECL:
1.121     veillard 2831:         case XML_PI_NODE:
                   2832:         case XML_ENTITY_REF_NODE:
                   2833:         case XML_ENTITY_NODE:
1.136     veillard 2834:        case XML_NAMESPACE_DECL:
1.123     veillard 2835: #ifdef LIBXML_SGML_ENABLED
                   2836:        case XML_SGML_DOCUMENT_NODE:
                   2837: #endif
1.138     veillard 2838:        case XML_XINCLUDE_START:
                   2839:        case XML_XINCLUDE_END:
1.78      daniel   2840:            return;
                   2841:         case XML_ELEMENT_NODE:
                   2842:         case XML_ATTRIBUTE_NODE:
                   2843:            break;
                   2844:     }
1.54      daniel   2845:     xmlSetProp(cur, BAD_CAST "xml:lang", lang);
1.52      daniel   2846: }
                   2847:  
                   2848: /**
                   2849:  * xmlNodeGetLang:
                   2850:  * @cur:  the node being checked
                   2851:  *
                   2852:  * Searches the language of a node, i.e. the values of the xml:lang
                   2853:  * attribute or the one carried by the nearest ancestor.
                   2854:  *
                   2855:  * Returns a pointer to the lang value, or NULL if not found
1.69      daniel   2856:  *     It's up to the caller to free the memory.
1.52      daniel   2857:  */
1.69      daniel   2858: xmlChar *
1.52      daniel   2859: xmlNodeGetLang(xmlNodePtr cur) {
1.69      daniel   2860:     xmlChar *lang;
1.52      daniel   2861: 
                   2862:     while (cur != NULL) {
1.54      daniel   2863:         lang = xmlGetProp(cur, BAD_CAST "xml:lang");
1.52      daniel   2864:        if (lang != NULL)
                   2865:            return(lang);
                   2866:        cur = cur->parent;
                   2867:     }
                   2868:     return(NULL);
1.78      daniel   2869: }
                   2870:  
1.133     veillard 2871: 
                   2872: /**
                   2873:  * xmlNodeSetSpacePreserve:
                   2874:  * @cur:  the node being changed
                   2875:  * @val:  the xml:space value ("0": default, 1: "preserve")
                   2876:  *
                   2877:  * Set (or reset) the space preserving behaviour of a node, i.e. the
                   2878:  * value of the xml:space attribute.
                   2879:  */
                   2880: void
                   2881: xmlNodeSetSpacePreserve(xmlNodePtr cur, int val) {
                   2882:     if (cur == NULL) return;
                   2883:     switch(cur->type) {
                   2884:         case XML_TEXT_NODE:
                   2885:         case XML_CDATA_SECTION_NODE:
                   2886:         case XML_COMMENT_NODE:
                   2887:         case XML_DOCUMENT_NODE:
                   2888:         case XML_DOCUMENT_TYPE_NODE:
                   2889:         case XML_DOCUMENT_FRAG_NODE:
                   2890:         case XML_NOTATION_NODE:
                   2891:         case XML_HTML_DOCUMENT_NODE:
                   2892:         case XML_DTD_NODE:
                   2893:         case XML_ELEMENT_DECL:
                   2894:         case XML_ATTRIBUTE_DECL:
                   2895:         case XML_ENTITY_DECL:
                   2896:         case XML_PI_NODE:
                   2897:         case XML_ENTITY_REF_NODE:
                   2898:         case XML_ENTITY_NODE:
1.136     veillard 2899:        case XML_NAMESPACE_DECL:
1.138     veillard 2900:        case XML_XINCLUDE_START:
                   2901:        case XML_XINCLUDE_END:
1.133     veillard 2902: #ifdef LIBXML_SGML_ENABLED
                   2903:        case XML_SGML_DOCUMENT_NODE:
                   2904: #endif
                   2905:            return;
                   2906:         case XML_ELEMENT_NODE:
                   2907:         case XML_ATTRIBUTE_NODE:
                   2908:            break;
                   2909:     }
                   2910:     switch (val) {
                   2911:     case 0:
                   2912:        xmlSetProp(cur, BAD_CAST "xml:space", BAD_CAST "default");
                   2913:        break;
                   2914:     case 1:
                   2915:        xmlSetProp(cur, BAD_CAST "xml:space", 
                   2916:                       BAD_CAST "preserve");
                   2917:        break;
                   2918:     }
                   2919: }
                   2920: 
1.78      daniel   2921: /**
1.98      daniel   2922:  * xmlNodeGetSpacePreserve:
                   2923:  * @cur:  the node being checked
                   2924:  *
1.133     veillard 2925:  * Searches the space preserving behaviour of a node, i.e. the values
                   2926:  * of the xml:space attribute or the one carried by the nearest
                   2927:  * ancestor.
1.98      daniel   2928:  *
                   2929:  * Returns -1 if xml:space is not inheried, 0 if "default", 1 if "preserve"
                   2930:  */
                   2931: int
                   2932: xmlNodeGetSpacePreserve(xmlNodePtr cur) {
                   2933:     xmlChar *space;
                   2934: 
                   2935:     while (cur != NULL) {
                   2936:         space = xmlGetProp(cur, BAD_CAST "xml:space");
                   2937:        if (space != NULL) {
1.128     veillard 2938:            if (xmlStrEqual(space, BAD_CAST "preserve")) {
1.98      daniel   2939:                xmlFree(space);
                   2940:                return(1);
                   2941:            }
1.128     veillard 2942:            if (xmlStrEqual(space, BAD_CAST "default")) {
1.98      daniel   2943:                xmlFree(space);
                   2944:                return(0);
                   2945:            }
                   2946:            xmlFree(space);
                   2947:        }
                   2948:        cur = cur->parent;
                   2949:     }
                   2950:     return(-1);
                   2951: }
                   2952:  
                   2953: /**
1.78      daniel   2954:  * xmlNodeSetName:
                   2955:  * @cur:  the node being changed
                   2956:  * @name:  the new tag name
                   2957:  *
1.133     veillard 2958:  * Set (or reset) the name of a node.
1.78      daniel   2959:  */
                   2960: void
                   2961: xmlNodeSetName(xmlNodePtr cur, const xmlChar *name) {
                   2962:     if (cur == NULL) return;
                   2963:     if (name == NULL) return;
                   2964:     switch(cur->type) {
                   2965:         case XML_TEXT_NODE:
                   2966:         case XML_CDATA_SECTION_NODE:
                   2967:         case XML_COMMENT_NODE:
                   2968:         case XML_DOCUMENT_TYPE_NODE:
                   2969:         case XML_DOCUMENT_FRAG_NODE:
                   2970:         case XML_NOTATION_NODE:
                   2971:         case XML_HTML_DOCUMENT_NODE:
1.136     veillard 2972:        case XML_NAMESPACE_DECL:
1.138     veillard 2973:        case XML_XINCLUDE_START:
                   2974:        case XML_XINCLUDE_END:
1.123     veillard 2975: #ifdef LIBXML_SGML_ENABLED
                   2976:        case XML_SGML_DOCUMENT_NODE:
                   2977: #endif
1.78      daniel   2978:            return;
                   2979:         case XML_ELEMENT_NODE:
                   2980:         case XML_ATTRIBUTE_NODE:
                   2981:         case XML_PI_NODE:
                   2982:         case XML_ENTITY_REF_NODE:
                   2983:         case XML_ENTITY_NODE:
1.90      daniel   2984:         case XML_DTD_NODE:
                   2985:         case XML_DOCUMENT_NODE:
1.96      daniel   2986:         case XML_ELEMENT_DECL:
                   2987:         case XML_ATTRIBUTE_DECL:
                   2988:         case XML_ENTITY_DECL:
1.78      daniel   2989:            break;
                   2990:     }
                   2991:     if (cur->name != NULL) xmlFree((xmlChar *) cur->name);
                   2992:     cur->name = xmlStrdup(name);
1.52      daniel   2993: }
                   2994:  
1.133     veillard 2995: /**
                   2996:  * xmlNodeSetBase:
                   2997:  * @cur:  the node being changed
                   2998:  * @uri:  the new base URI
                   2999:  *
                   3000:  * Set (or reset) the base URI of a node, i.e. the value of the
                   3001:  * xml:base attribute.
                   3002:  */
                   3003: void
                   3004: xmlNodeSetBase(xmlNodePtr cur, xmlChar* uri) {
                   3005:     if (cur == NULL) return;
                   3006:     switch(cur->type) {
                   3007:         case XML_TEXT_NODE:
                   3008:         case XML_CDATA_SECTION_NODE:
                   3009:         case XML_COMMENT_NODE:
                   3010:         case XML_DOCUMENT_NODE:
                   3011:         case XML_DOCUMENT_TYPE_NODE:
                   3012:         case XML_DOCUMENT_FRAG_NODE:
                   3013:         case XML_NOTATION_NODE:
                   3014:         case XML_HTML_DOCUMENT_NODE:
                   3015:         case XML_DTD_NODE:
                   3016:         case XML_ELEMENT_DECL:
                   3017:         case XML_ATTRIBUTE_DECL:
                   3018:         case XML_ENTITY_DECL:
                   3019:         case XML_PI_NODE:
                   3020:         case XML_ENTITY_REF_NODE:
                   3021:         case XML_ENTITY_NODE:
1.136     veillard 3022:        case XML_NAMESPACE_DECL:
1.138     veillard 3023:        case XML_XINCLUDE_START:
                   3024:        case XML_XINCLUDE_END:
1.133     veillard 3025: #ifdef LIBXML_SGML_ENABLED
                   3026:        case XML_SGML_DOCUMENT_NODE:
                   3027: #endif
                   3028:            return;
                   3029:         case XML_ELEMENT_NODE:
                   3030:         case XML_ATTRIBUTE_NODE:
                   3031:            break;
                   3032:     }
                   3033:     xmlSetProp(cur, BAD_CAST "xml:base", uri);
                   3034: }
                   3035: 
1.52      daniel   3036: /**
1.139     veillard 3037:  * xmlDocumentGetBase:
                   3038:  * @doc:  the document
                   3039:  *
                   3040:  * Searches for the Document BASE URL. The code should work on both XML
                   3041:  * and HTML document.
                   3042:  * It returns the base as defined in RFC 2396 section
                   3043:  * 5.1.3. Base URI from the Retrieval URI
                   3044:  * However it does not return the computed base (5.1.1 and 5.1.2), use
                   3045:  * xmlNodeGetBase() for this
                   3046:  *
                   3047:  * Returns a pointer to the base URL, or NULL if not found
                   3048:  *     It's up to the caller to free the memory.
                   3049:  */
                   3050: xmlChar *
                   3051: xmlDocumentGetBase(xmlDocPtr doc) {
                   3052:     if (doc == NULL)
                   3053:         return(NULL);
                   3054:     if (doc->type == XML_HTML_DOCUMENT_NODE) {
                   3055:        if (doc->URL != NULL)
                   3056:            return(xmlStrdup(doc->URL));
                   3057:        return(NULL);
                   3058:     }
                   3059:     if (doc->URL != NULL)
                   3060:        return(xmlStrdup(doc->URL));
                   3061:     return(NULL);
                   3062: }
                   3063: 
                   3064: /**
1.73      daniel   3065:  * xmlNodeGetBase:
                   3066:  * @doc:  the document the node pertains to
                   3067:  * @cur:  the node being checked
                   3068:  *
                   3069:  * Searches for the BASE URL. The code should work on both XML
                   3070:  * and HTML document even if base mechanisms are completely different.
1.139     veillard 3071:  * It returns the base as defined in RFC 2396 sections
                   3072:  * 5.1.1. Base URI within Document Content
                   3073:  * and
                   3074:  * 5.1.2. Base URI from the Encapsulating Entity
                   3075:  * However it does not return the document base (5.1.3), use
                   3076:  * xmlDocumentGetBase() for this
1.73      daniel   3077:  *
                   3078:  * Returns a pointer to the base URL, or NULL if not found
                   3079:  *     It's up to the caller to free the memory.
                   3080:  */
                   3081: xmlChar *
                   3082: xmlNodeGetBase(xmlDocPtr doc, xmlNodePtr cur) {
                   3083:     xmlChar *base;
                   3084: 
                   3085:     if ((cur == NULL) && (doc == NULL)) 
                   3086:         return(NULL);
                   3087:     if (doc == NULL) doc = cur->doc;   
                   3088:     if ((doc != NULL) && (doc->type == XML_HTML_DOCUMENT_NODE)) {
1.90      daniel   3089:         cur = doc->children;
1.73      daniel   3090:        while ((cur != NULL) && (cur->name != NULL)) {
                   3091:            if (cur->type != XML_ELEMENT_NODE) {
                   3092:                cur = cur->next;
                   3093:                continue;
                   3094:            }
1.126     veillard 3095:            if (!xmlStrcasecmp(cur->name, BAD_CAST "html")) {
1.90      daniel   3096:                cur = cur->children;
1.73      daniel   3097:                continue;
                   3098:            }
1.126     veillard 3099:            if (!xmlStrcasecmp(cur->name, BAD_CAST "head")) {
1.90      daniel   3100:                cur = cur->children;
1.73      daniel   3101:                continue;
                   3102:            }
1.126     veillard 3103:            if (!xmlStrcasecmp(cur->name, BAD_CAST "base")) {
                   3104:                 return(xmlGetProp(cur, BAD_CAST "href"));
1.73      daniel   3105:            }
1.100     daniel   3106:            cur = cur->next;
1.73      daniel   3107:        }
                   3108:        return(NULL);
                   3109:     }
                   3110:     while (cur != NULL) {
1.139     veillard 3111:        if (cur->type == XML_ENTITY_DECL) {
                   3112:            xmlEntityPtr ent = (xmlEntityPtr) cur;
                   3113:            return(xmlStrdup(ent->URI));
                   3114:        }
1.73      daniel   3115:         base = xmlGetProp(cur, BAD_CAST "xml:base");
                   3116:        if (base != NULL)
                   3117:            return(base);
                   3118:        cur = cur->parent;
                   3119:     }
                   3120:     return(NULL);
                   3121: }
                   3122:  
                   3123: /**
1.28      daniel   3124:  * xmlNodeGetContent:
                   3125:  * @cur:  the node being read
                   3126:  *
                   3127:  * Read the value of a node, this can be either the text carried
                   3128:  * directly by this node if it's a TEXT node or the aggregate string
                   3129:  * of the values carried by this node child's (TEXT and ENTITY_REF).
                   3130:  * Entity references are substitued.
1.61      daniel   3131:  * Returns a new xmlChar * or NULL if no content is available.
1.38      daniel   3132:  *     It's up to the caller to free the memory.
1.28      daniel   3133:  */
1.61      daniel   3134: xmlChar *
1.28      daniel   3135: xmlNodeGetContent(xmlNodePtr cur) {
                   3136:     if (cur == NULL) return(NULL);
                   3137:     switch (cur->type) {
                   3138:         case XML_DOCUMENT_FRAG_NODE:
                   3139:         case XML_ELEMENT_NODE:
1.90      daniel   3140:             return(xmlNodeListGetString(cur->doc, cur->children, 1));
1.28      daniel   3141:            break;
1.52      daniel   3142:         case XML_ATTRIBUTE_NODE: {
                   3143:            xmlAttrPtr attr = (xmlAttrPtr) cur;
1.90      daniel   3144:            if (attr->parent != NULL)
                   3145:                return(xmlNodeListGetString(attr->parent->doc, attr->children, 1));
1.52      daniel   3146:            else
1.90      daniel   3147:                return(xmlNodeListGetString(NULL, attr->children, 1));
1.52      daniel   3148:            break;
                   3149:        }
1.82      daniel   3150:         case XML_COMMENT_NODE:
1.52      daniel   3151:         case XML_PI_NODE:
                   3152:            if (cur->content != NULL)
1.70      daniel   3153: #ifndef XML_USE_BUFFER_CONTENT
1.52      daniel   3154:                return(xmlStrdup(cur->content));
1.70      daniel   3155: #else
                   3156:                return(xmlStrdup(xmlBufferContent(cur->content)));
                   3157: #endif
1.52      daniel   3158:            return(NULL);
1.28      daniel   3159:         case XML_ENTITY_REF_NODE:
1.82      daniel   3160:            /*
                   3161:             * Locate the entity, and get it's content
                   3162:             * @@@
                   3163:             */
                   3164:             return(NULL);
1.28      daniel   3165:         case XML_ENTITY_NODE:
                   3166:         case XML_DOCUMENT_NODE:
1.65      daniel   3167:         case XML_HTML_DOCUMENT_NODE:
1.28      daniel   3168:         case XML_DOCUMENT_TYPE_NODE:
                   3169:         case XML_NOTATION_NODE:
1.90      daniel   3170:         case XML_DTD_NODE:
1.138     veillard 3171:        case XML_XINCLUDE_START:
                   3172:        case XML_XINCLUDE_END:
1.123     veillard 3173: #ifdef LIBXML_SGML_ENABLED
                   3174:        case XML_SGML_DOCUMENT_NODE:
                   3175: #endif
1.28      daniel   3176:            return(NULL);
1.136     veillard 3177:        case XML_NAMESPACE_DECL:
1.142     veillard 3178:            return(xmlStrdup(((xmlNsPtr)cur)->href));
1.91      daniel   3179:         case XML_ELEMENT_DECL:
                   3180:            /* TODO !!! */
                   3181:            return(NULL);
                   3182:         case XML_ATTRIBUTE_DECL:
                   3183:            /* TODO !!! */
                   3184:            return(NULL);
1.96      daniel   3185:         case XML_ENTITY_DECL:
                   3186:            /* TODO !!! */
                   3187:            return(NULL);
1.50      daniel   3188:         case XML_CDATA_SECTION_NODE:
1.28      daniel   3189:         case XML_TEXT_NODE:
                   3190:            if (cur->content != NULL)
1.70      daniel   3191: #ifndef XML_USE_BUFFER_CONTENT
1.28      daniel   3192:                return(xmlStrdup(cur->content));
1.70      daniel   3193: #else
                   3194:                return(xmlStrdup(xmlBufferContent(cur->content)));
                   3195: #endif
1.28      daniel   3196:             return(NULL);
                   3197:     }
                   3198:     return(NULL);
                   3199: }
                   3200:  
                   3201: /**
1.23      daniel   3202:  * xmlNodeSetContent:
                   3203:  * @cur:  the node being modified
                   3204:  * @content:  the new value of the content
                   3205:  *
                   3206:  * Replace the content of a node.
1.1       veillard 3207:  */
1.28      daniel   3208: void
1.61      daniel   3209: xmlNodeSetContent(xmlNodePtr cur, const xmlChar *content) {
1.1       veillard 3210:     if (cur == NULL) {
1.86      daniel   3211: #ifdef DEBUG_TREE
1.134     veillard 3212:         xmlGenericError(xmlGenericErrorContext,
                   3213:                "xmlNodeSetContent : node == NULL\n");
1.86      daniel   3214: #endif
1.1       veillard 3215:        return;
                   3216:     }
1.28      daniel   3217:     switch (cur->type) {
                   3218:         case XML_DOCUMENT_FRAG_NODE:
                   3219:         case XML_ELEMENT_NODE:
                   3220:            if (cur->content != NULL) {
1.70      daniel   3221: #ifndef XML_USE_BUFFER_CONTENT
1.57      daniel   3222:                xmlFree(cur->content);
1.70      daniel   3223: #else
                   3224:                xmlBufferFree(cur->content);
                   3225: #endif
1.28      daniel   3226:                cur->content = NULL;
                   3227:            }
1.90      daniel   3228:            if (cur->children != NULL) xmlFreeNodeList(cur->children);
                   3229:            cur->children = xmlStringGetNodeList(cur->doc, content);
1.140     veillard 3230:            UPDATE_LAST_CHILD_AND_PARENT(cur)
1.28      daniel   3231:            break;
                   3232:         case XML_ATTRIBUTE_NODE:
                   3233:            break;
                   3234:         case XML_TEXT_NODE:
                   3235:         case XML_CDATA_SECTION_NODE:
                   3236:         case XML_ENTITY_REF_NODE:
                   3237:         case XML_ENTITY_NODE:
                   3238:         case XML_PI_NODE:
                   3239:         case XML_COMMENT_NODE:
1.70      daniel   3240:            if (cur->content != NULL) {
                   3241: #ifndef XML_USE_BUFFER_CONTENT
                   3242:                xmlFree(cur->content);
                   3243: #else
                   3244:                xmlBufferFree(cur->content);
                   3245: #endif
                   3246:            }   
1.90      daniel   3247:            if (cur->children != NULL) xmlFreeNodeList(cur->children);
                   3248:            cur->last = cur->children = NULL;
1.70      daniel   3249:            if (content != NULL) {
                   3250: #ifndef XML_USE_BUFFER_CONTENT
1.28      daniel   3251:                cur->content = xmlStrdup(content);
1.70      daniel   3252: #else
                   3253:                cur->content = xmlBufferCreateSize(0);
                   3254:                xmlBufferSetAllocationScheme(cur->content,
                   3255:                                             xmlGetBufferAllocationScheme());
                   3256:                xmlBufferAdd(cur->content, content, -1);
                   3257: #endif
                   3258:            } else 
1.28      daniel   3259:                cur->content = NULL;
1.53      daniel   3260:            break;
1.28      daniel   3261:         case XML_DOCUMENT_NODE:
1.65      daniel   3262:         case XML_HTML_DOCUMENT_NODE:
1.28      daniel   3263:         case XML_DOCUMENT_TYPE_NODE:
1.138     veillard 3264:        case XML_XINCLUDE_START:
                   3265:        case XML_XINCLUDE_END:
1.123     veillard 3266: #ifdef LIBXML_SGML_ENABLED
                   3267:        case XML_SGML_DOCUMENT_NODE:
                   3268: #endif
1.28      daniel   3269:            break;
                   3270:         case XML_NOTATION_NODE:
                   3271:            break;
1.90      daniel   3272:         case XML_DTD_NODE:
                   3273:            break;
1.136     veillard 3274:        case XML_NAMESPACE_DECL:
                   3275:            break;
1.91      daniel   3276:         case XML_ELEMENT_DECL:
                   3277:            /* TODO !!! */
                   3278:            break;
                   3279:         case XML_ATTRIBUTE_DECL:
                   3280:            /* TODO !!! */
                   3281:            break;
1.96      daniel   3282:         case XML_ENTITY_DECL:
                   3283:            /* TODO !!! */
                   3284:            break;
1.28      daniel   3285:     }
1.1       veillard 3286: }
                   3287: 
1.23      daniel   3288: /**
                   3289:  * xmlNodeSetContentLen:
                   3290:  * @cur:  the node being modified
                   3291:  * @content:  the new value of the content
                   3292:  * @len:  the size of @content
                   3293:  *
                   3294:  * Replace the content of a node.
1.21      daniel   3295:  */
1.28      daniel   3296: void
1.61      daniel   3297: xmlNodeSetContentLen(xmlNodePtr cur, const xmlChar *content, int len) {
1.21      daniel   3298:     if (cur == NULL) {
1.86      daniel   3299: #ifdef DEBUG_TREE
1.134     veillard 3300:         xmlGenericError(xmlGenericErrorContext,
                   3301:                "xmlNodeSetContentLen : node == NULL\n");
1.86      daniel   3302: #endif
1.21      daniel   3303:        return;
                   3304:     }
1.28      daniel   3305:     switch (cur->type) {
                   3306:         case XML_DOCUMENT_FRAG_NODE:
                   3307:         case XML_ELEMENT_NODE:
                   3308:            if (cur->content != NULL) {
1.70      daniel   3309: #ifndef XML_USE_BUFFER_CONTENT
1.57      daniel   3310:                xmlFree(cur->content);
1.70      daniel   3311: #else
                   3312:                xmlBufferFree(cur->content);
                   3313: #endif
1.28      daniel   3314:                cur->content = NULL;
                   3315:            }
1.90      daniel   3316:            if (cur->children != NULL) xmlFreeNodeList(cur->children);
                   3317:            cur->children = xmlStringLenGetNodeList(cur->doc, content, len);
1.140     veillard 3318:            UPDATE_LAST_CHILD_AND_PARENT(cur)
1.28      daniel   3319:            break;
                   3320:         case XML_ATTRIBUTE_NODE:
                   3321:            break;
                   3322:         case XML_TEXT_NODE:
                   3323:         case XML_CDATA_SECTION_NODE:
                   3324:         case XML_ENTITY_REF_NODE:
                   3325:         case XML_ENTITY_NODE:
                   3326:         case XML_PI_NODE:
                   3327:         case XML_COMMENT_NODE:
1.70      daniel   3328:         case XML_NOTATION_NODE:
                   3329:            if (cur->content != NULL) {
                   3330: #ifndef XML_USE_BUFFER_CONTENT
                   3331:                xmlFree(cur->content);
                   3332: #else
                   3333:                xmlBufferFree(cur->content);
                   3334: #endif
                   3335:            }   
1.90      daniel   3336:            if (cur->children != NULL) xmlFreeNodeList(cur->children);
                   3337:            cur->children = cur->last = NULL;
1.70      daniel   3338:            if (content != NULL) {
                   3339: #ifndef XML_USE_BUFFER_CONTENT
1.28      daniel   3340:                cur->content = xmlStrndup(content, len);
1.70      daniel   3341: #else
                   3342:                cur->content = xmlBufferCreateSize(len);
                   3343:                xmlBufferSetAllocationScheme(cur->content,
                   3344:                                             xmlGetBufferAllocationScheme());
                   3345:                xmlBufferAdd(cur->content, content, len);
                   3346: #endif
                   3347:            } else 
1.28      daniel   3348:                cur->content = NULL;
1.53      daniel   3349:            break;
1.28      daniel   3350:         case XML_DOCUMENT_NODE:
1.90      daniel   3351:         case XML_DTD_NODE:
1.65      daniel   3352:         case XML_HTML_DOCUMENT_NODE:
1.28      daniel   3353:         case XML_DOCUMENT_TYPE_NODE:
1.136     veillard 3354:        case XML_NAMESPACE_DECL:
1.138     veillard 3355:        case XML_XINCLUDE_START:
                   3356:        case XML_XINCLUDE_END:
1.123     veillard 3357: #ifdef LIBXML_SGML_ENABLED
                   3358:        case XML_SGML_DOCUMENT_NODE:
                   3359: #endif
1.28      daniel   3360:            break;
1.91      daniel   3361:         case XML_ELEMENT_DECL:
                   3362:            /* TODO !!! */
                   3363:            break;
                   3364:         case XML_ATTRIBUTE_DECL:
                   3365:            /* TODO !!! */
                   3366:            break;
1.96      daniel   3367:         case XML_ENTITY_DECL:
                   3368:            /* TODO !!! */
                   3369:            break;
1.28      daniel   3370:     }
1.21      daniel   3371: }
                   3372: 
1.23      daniel   3373: /**
1.28      daniel   3374:  * xmlNodeAddContentLen:
1.23      daniel   3375:  * @cur:  the node being modified
                   3376:  * @content:  extra content
1.28      daniel   3377:  * @len:  the size of @content
1.23      daniel   3378:  * 
                   3379:  * Append the extra substring to the node content.
1.21      daniel   3380:  */
1.28      daniel   3381: void
1.61      daniel   3382: xmlNodeAddContentLen(xmlNodePtr cur, const xmlChar *content, int len) {
1.21      daniel   3383:     if (cur == NULL) {
1.86      daniel   3384: #ifdef DEBUG_TREE
1.134     veillard 3385:         xmlGenericError(xmlGenericErrorContext,
                   3386:                "xmlNodeAddContentLen : node == NULL\n");
1.86      daniel   3387: #endif
1.21      daniel   3388:        return;
                   3389:     }
1.28      daniel   3390:     if (len <= 0) return;
                   3391:     switch (cur->type) {
                   3392:         case XML_DOCUMENT_FRAG_NODE:
                   3393:         case XML_ELEMENT_NODE: {
1.112     veillard 3394:            xmlNodePtr last = NULL, newNode;
1.28      daniel   3395: 
1.90      daniel   3396:            if (cur->children != NULL) {
1.32      daniel   3397:                last = cur->last;
1.28      daniel   3398:            } else {
                   3399:                if (cur->content != NULL) {
1.70      daniel   3400: #ifndef XML_USE_BUFFER_CONTENT
1.90      daniel   3401:                    cur->children = xmlStringGetNodeList(cur->doc, cur->content);
1.70      daniel   3402: #else
1.90      daniel   3403:                    cur->children = xmlStringGetNodeList(cur->doc,
1.70      daniel   3404:                                               xmlBufferContent(cur->content));
                   3405: #endif
1.140     veillard 3406:                    UPDATE_LAST_CHILD_AND_PARENT(cur)
1.70      daniel   3407: #ifndef XML_USE_BUFFER_CONTENT
1.57      daniel   3408:                    xmlFree(cur->content);
1.70      daniel   3409: #else
                   3410:                    xmlBufferFree(cur->content);
                   3411: #endif
1.28      daniel   3412:                    cur->content = NULL;
1.32      daniel   3413:                    last = cur->last;
1.28      daniel   3414:                }
                   3415:            }
1.112     veillard 3416:            newNode = xmlNewTextLen(content, len);
                   3417:            if (newNode != NULL) {
                   3418:                xmlAddChild(cur, newNode);
                   3419:                if ((last != NULL) && (last->next == newNode)) {
                   3420:                    xmlTextMerge(last, newNode);
1.32      daniel   3421:                }
1.28      daniel   3422:            }
                   3423:            break;
                   3424:        }
                   3425:         case XML_ATTRIBUTE_NODE:
                   3426:            break;
                   3427:         case XML_TEXT_NODE:
                   3428:         case XML_CDATA_SECTION_NODE:
                   3429:         case XML_ENTITY_REF_NODE:
                   3430:         case XML_ENTITY_NODE:
                   3431:         case XML_PI_NODE:
                   3432:         case XML_COMMENT_NODE:
1.70      daniel   3433:         case XML_NOTATION_NODE:
                   3434:            if (content != NULL) {
                   3435: #ifndef XML_USE_BUFFER_CONTENT
1.28      daniel   3436:                cur->content = xmlStrncat(cur->content, content, len);
1.70      daniel   3437: #else
                   3438:                xmlBufferAdd(cur->content, content, len);
                   3439: #endif
                   3440:             }
1.28      daniel   3441:         case XML_DOCUMENT_NODE:
1.90      daniel   3442:         case XML_DTD_NODE:
1.65      daniel   3443:         case XML_HTML_DOCUMENT_NODE:
1.28      daniel   3444:         case XML_DOCUMENT_TYPE_NODE:
1.136     veillard 3445:        case XML_NAMESPACE_DECL:
1.138     veillard 3446:        case XML_XINCLUDE_START:
                   3447:        case XML_XINCLUDE_END:
1.123     veillard 3448: #ifdef LIBXML_SGML_ENABLED
                   3449:        case XML_SGML_DOCUMENT_NODE:
                   3450: #endif
1.28      daniel   3451:            break;
1.91      daniel   3452:         case XML_ELEMENT_DECL:
                   3453:         case XML_ATTRIBUTE_DECL:
1.96      daniel   3454:         case XML_ENTITY_DECL:
1.91      daniel   3455:            break;
1.28      daniel   3456:     }
1.21      daniel   3457: }
                   3458: 
1.23      daniel   3459: /**
1.28      daniel   3460:  * xmlNodeAddContent:
1.23      daniel   3461:  * @cur:  the node being modified
                   3462:  * @content:  extra content
                   3463:  * 
                   3464:  * Append the extra substring to the node content.
1.21      daniel   3465:  */
1.28      daniel   3466: void
1.61      daniel   3467: xmlNodeAddContent(xmlNodePtr cur, const xmlChar *content) {
1.28      daniel   3468:     int len;
                   3469: 
1.21      daniel   3470:     if (cur == NULL) {
1.86      daniel   3471: #ifdef DEBUG_TREE
1.134     veillard 3472:         xmlGenericError(xmlGenericErrorContext,
                   3473:                "xmlNodeAddContent : node == NULL\n");
1.86      daniel   3474: #endif
1.21      daniel   3475:        return;
                   3476:     }
1.28      daniel   3477:     if (content == NULL) return;
                   3478:     len = xmlStrlen(content);
                   3479:     xmlNodeAddContentLen(cur, content, len);
                   3480: }
                   3481: 
                   3482: /**
                   3483:  * xmlTextMerge:
                   3484:  * @first:  the first text node
                   3485:  * @second:  the second text node being merged
                   3486:  * 
                   3487:  * Merge two text nodes into one
1.36      daniel   3488:  * Returns the first text node augmented
1.28      daniel   3489:  */
                   3490: xmlNodePtr
                   3491: xmlTextMerge(xmlNodePtr first, xmlNodePtr second) {
                   3492:     if (first == NULL) return(second);
                   3493:     if (second == NULL) return(first);
                   3494:     if (first->type != XML_TEXT_NODE) return(first);
                   3495:     if (second->type != XML_TEXT_NODE) return(first);
1.70      daniel   3496: #ifndef XML_USE_BUFFER_CONTENT
1.28      daniel   3497:     xmlNodeAddContent(first, second->content);
1.70      daniel   3498: #else
                   3499:     xmlNodeAddContent(first, xmlBufferContent(second->content));
                   3500: #endif
1.28      daniel   3501:     xmlUnlinkNode(second);
                   3502:     xmlFreeNode(second);
                   3503:     return(first);
1.21      daniel   3504: }
                   3505: 
1.23      daniel   3506: /**
1.52      daniel   3507:  * xmlGetNsList:
                   3508:  * @doc:  the document
                   3509:  * @node:  the current node
                   3510:  *
                   3511:  * Search all the namespace applying to a given element.
                   3512:  * Returns an NULL terminated array of all the xmlNsPtr found
                   3513:  *         that need to be freed by the caller or NULL if no
                   3514:  *         namespace if defined
                   3515:  */
                   3516: xmlNsPtr *
                   3517: xmlGetNsList(xmlDocPtr doc, xmlNodePtr node) {
                   3518:     xmlNsPtr cur;
                   3519:     xmlNsPtr *ret = NULL;
                   3520:     int nbns = 0;
                   3521:     int maxns = 10;
                   3522:     int i;
                   3523: 
                   3524:     while (node != NULL) {
                   3525:        cur = node->nsDef;
                   3526:        while (cur != NULL) {
                   3527:            if (ret == NULL) {
1.57      daniel   3528:                ret = (xmlNsPtr *) xmlMalloc((maxns + 1) * sizeof(xmlNsPtr));
1.52      daniel   3529:                if (ret == NULL) {
1.134     veillard 3530:                    xmlGenericError(xmlGenericErrorContext,
                   3531:                            "xmlGetNsList : out of memory!\n");
1.52      daniel   3532:                    return(NULL);
                   3533:                }
                   3534:                ret[nbns] = NULL;
                   3535:            }
                   3536:            for (i = 0;i < nbns;i++) {
                   3537:                if ((cur->prefix == ret[i]->prefix) ||
1.128     veillard 3538:                    (xmlStrEqual(cur->prefix, ret[i]->prefix))) break;
1.52      daniel   3539:            }
                   3540:            if (i >= nbns) {
                   3541:                if (nbns >= maxns) {
                   3542:                    maxns *= 2;
1.57      daniel   3543:                    ret = (xmlNsPtr *) xmlRealloc(ret,
1.52      daniel   3544:                                         (maxns + 1) * sizeof(xmlNsPtr));
                   3545:                    if (ret == NULL) {
1.134     veillard 3546:                        xmlGenericError(xmlGenericErrorContext,
                   3547:                                "xmlGetNsList : realloc failed!\n");
1.52      daniel   3548:                        return(NULL);
                   3549:                    }
                   3550:                }
                   3551:                ret[nbns++] = cur;
                   3552:                ret[nbns] = NULL;
                   3553:            }
                   3554: 
                   3555:            cur = cur->next;
                   3556:        }
                   3557:        node = node->parent;
                   3558:     }
                   3559:     return(ret);
                   3560: }
                   3561: 
                   3562: /**
1.23      daniel   3563:  * xmlSearchNs:
                   3564:  * @doc:  the document
                   3565:  * @node:  the current node
                   3566:  * @nameSpace:  the namespace string
                   3567:  *
1.16      daniel   3568:  * Search a Ns registered under a given name space for a document.
1.23      daniel   3569:  * recurse on the parents until it finds the defined namespace
                   3570:  * or return NULL otherwise.
                   3571:  * @nameSpace can be NULL, this is a search for the default namespace.
1.120     veillard 3572:  * We don't allow to cross entities boundaries. If you don't declare
                   3573:  * the namespace within those you will be in troubles !!! A warning
                   3574:  * is generated to cover this case.
                   3575:  *
1.36      daniel   3576:  * Returns the namespace pointer or NULL.
1.3       veillard 3577:  */
1.28      daniel   3578: xmlNsPtr
1.61      daniel   3579: xmlSearchNs(xmlDocPtr doc, xmlNodePtr node, const xmlChar *nameSpace) {
1.16      daniel   3580:     xmlNsPtr cur;
1.3       veillard 3581: 
1.76      daniel   3582:     if (node == NULL) return(NULL);
1.19      daniel   3583:     while (node != NULL) {
1.120     veillard 3584:        if ((node->type == XML_ENTITY_REF_NODE) ||
                   3585:            (node->type == XML_ENTITY_NODE) ||
                   3586:            (node->type == XML_ENTITY_DECL))
                   3587:            return(NULL);
1.92      daniel   3588:        if (node->type == XML_ELEMENT_NODE) {
                   3589:            cur = node->nsDef;
                   3590:            while (cur != NULL) {
1.120     veillard 3591:                if ((cur->prefix == NULL) && (nameSpace == NULL) &&
                   3592:                    (cur->href != NULL))
1.92      daniel   3593:                    return(cur);
                   3594:                if ((cur->prefix != NULL) && (nameSpace != NULL) &&
1.120     veillard 3595:                    (cur->href != NULL) &&
1.128     veillard 3596:                    (xmlStrEqual(cur->prefix, nameSpace)))
1.92      daniel   3597:                    return(cur);
                   3598:                cur = cur->next;
                   3599:            }
1.19      daniel   3600:        }
                   3601:        node = node->parent;
                   3602:     }
                   3603:     return(NULL);
                   3604: }
1.3       veillard 3605: 
1.23      daniel   3606: /**
                   3607:  * xmlSearchNsByHref:
                   3608:  * @doc:  the document
                   3609:  * @node:  the current node
                   3610:  * @href:  the namespace value
                   3611:  *
                   3612:  * Search a Ns aliasing a given URI. Recurse on the parents until it finds
                   3613:  * the defined namespace or return NULL otherwise.
1.36      daniel   3614:  * Returns the namespace pointer or NULL.
1.19      daniel   3615:  */
1.28      daniel   3616: xmlNsPtr
1.61      daniel   3617: xmlSearchNsByHref(xmlDocPtr doc, xmlNodePtr node, const xmlChar *href) {
1.19      daniel   3618:     xmlNsPtr cur;
1.82      daniel   3619:     xmlNodePtr orig = node;
1.19      daniel   3620: 
1.74      daniel   3621:     if ((node == NULL) || (href == NULL)) return(NULL);
1.19      daniel   3622:     while (node != NULL) {
                   3623:        cur = node->nsDef;
                   3624:        while (cur != NULL) {
                   3625:            if ((cur->href != NULL) && (href != NULL) &&
1.128     veillard 3626:                (xmlStrEqual(cur->href, href))) {
1.82      daniel   3627:                /*
                   3628:                 * Check that the prefix is not shadowed between orig and node
                   3629:                 */
                   3630:                xmlNodePtr check = orig;
                   3631:                xmlNsPtr tst;
                   3632: 
                   3633:                while (check != node) {
                   3634:                    tst = check->nsDef;
                   3635:                    while (tst != NULL) {
                   3636:                        if ((tst->prefix == NULL) && (cur->prefix == NULL))
                   3637:                            goto shadowed;
                   3638:                        if ((tst->prefix != NULL) && (cur->prefix != NULL) &&
1.128     veillard 3639:                            (xmlStrEqual(tst->prefix, cur->prefix)))
1.82      daniel   3640:                            goto shadowed;
                   3641:                        tst = tst->next;
                   3642:                    }
1.135     veillard 3643:                    check = check->parent;
1.82      daniel   3644:                }
1.19      daniel   3645:                return(cur);
1.82      daniel   3646:            }
                   3647: shadowed:                  
1.19      daniel   3648:            cur = cur->next;
                   3649:        }
                   3650:        node = node->parent;
                   3651:     }
1.82      daniel   3652:     return(NULL);
                   3653: }
                   3654: 
                   3655: /**
                   3656:  * xmlNewReconciliedNs
                   3657:  * @doc:  the document
                   3658:  * @tree:  a node expected to hold the new namespace
                   3659:  * @ns:  the original namespace
                   3660:  *
                   3661:  * This function tries to locate a namespace definition in a tree
                   3662:  * ancestors, or create a new namespace definition node similar to
                   3663:  * @ns trying to reuse the same prefix. However if the given prefix is
                   3664:  * null (default namespace) or reused within the subtree defined by
                   3665:  * @tree or on one of its ancestors then a new prefix is generated.
                   3666:  * Returns the (new) namespace definition or NULL in case of error
                   3667:  */
                   3668: xmlNsPtr
                   3669: xmlNewReconciliedNs(xmlDocPtr doc, xmlNodePtr tree, xmlNsPtr ns) {
                   3670:     xmlNsPtr def;
                   3671:     xmlChar prefix[50];
                   3672:     int counter = 1;
                   3673: 
                   3674:     if (tree == NULL) {
                   3675: #ifdef DEBUG_TREE
1.134     veillard 3676:         xmlGenericError(xmlGenericErrorContext,
                   3677:                "xmlNewReconciliedNs : tree == NULL\n");
1.82      daniel   3678: #endif
                   3679:        return(NULL);
                   3680:     }
                   3681:     if (ns == NULL) {
                   3682: #ifdef DEBUG_TREE
1.134     veillard 3683:         xmlGenericError(xmlGenericErrorContext,
                   3684:                "xmlNewReconciliedNs : ns == NULL\n");
1.82      daniel   3685: #endif
                   3686:        return(NULL);
                   3687:     }
                   3688:     /*
                   3689:      * Search an existing namespace definition inherited.
                   3690:      */
                   3691:     def = xmlSearchNsByHref(doc, tree, ns->href);
                   3692:     if (def != NULL)
                   3693:         return(def);
                   3694: 
                   3695:     /*
                   3696:      * Find a close prefix which is not already in use.
                   3697:      * Let's strip namespace prefixes longer than 20 chars !
                   3698:      */
                   3699:     sprintf((char *) prefix, "%.20s", ns->prefix);
                   3700:     def = xmlSearchNs(doc, tree, prefix);
                   3701:     while (def != NULL) {
                   3702:         if (counter > 1000) return(NULL);
                   3703:         sprintf((char *) prefix, "%.20s%d", ns->prefix, counter++);
                   3704:        def = xmlSearchNs(doc, tree, prefix);
                   3705:     }
                   3706: 
                   3707:     /*
                   3708:      * Ok, now we are ready to create a new one.
                   3709:      */
                   3710:     def = xmlNewNs(tree, ns->href, prefix);
                   3711:     return(def);
                   3712: }
                   3713: 
                   3714: /**
                   3715:  * xmlReconciliateNs
                   3716:  * @doc:  the document
                   3717:  * @tree:  a node defining the subtree to reconciliate
                   3718:  *
                   3719:  * This function checks that all the namespaces declared within the given
                   3720:  * tree are properly declared. This is needed for example after Copy or Cut
                   3721:  * and then paste operations. The subtree may still hold pointers to
                   3722:  * namespace declarations outside the subtree or invalid/masked. As much
                   3723:  * as possible the function try tu reuse the existing namespaces found in
                   3724:  * the new environment. If not possible the new namespaces are redeclared
                   3725:  * on @tree at the top of the given subtree.
                   3726:  * Returns the number of namespace declarations created or -1 in case of error.
                   3727:  */
                   3728: int
                   3729: xmlReconciliateNs(xmlDocPtr doc, xmlNodePtr tree) {
                   3730:     xmlNsPtr *oldNs = NULL;
                   3731:     xmlNsPtr *newNs = NULL;
                   3732:     int sizeCache = 0;
                   3733:     int nbCache = 0;
                   3734: 
                   3735:     xmlNsPtr n;
                   3736:     xmlNodePtr node = tree;
                   3737:     xmlAttrPtr attr;
                   3738:     int ret = 0, i;
                   3739: 
                   3740:     while (node != NULL) {
                   3741:         /*
                   3742:         * Reconciliate the node namespace
                   3743:         */
                   3744:        if (node->ns != NULL) {
                   3745:            /*
                   3746:             * initialize the cache if needed
                   3747:             */
                   3748:            if (sizeCache == 0) {
                   3749:                sizeCache = 10;
                   3750:                oldNs = (xmlNsPtr *) xmlMalloc(sizeCache *
                   3751:                                               sizeof(xmlNsPtr));
                   3752:                if (oldNs == NULL) {
1.134     veillard 3753:                    xmlGenericError(xmlGenericErrorContext,
                   3754:                            "xmlReconciliateNs : memory pbm\n");
1.82      daniel   3755:                    return(-1);
                   3756:                }
                   3757:                newNs = (xmlNsPtr *) xmlMalloc(sizeCache *
                   3758:                                               sizeof(xmlNsPtr));
                   3759:                if (newNs == NULL) {
1.134     veillard 3760:                    xmlGenericError(xmlGenericErrorContext,
                   3761:                            "xmlReconciliateNs : memory pbm\n");
1.82      daniel   3762:                    xmlFree(oldNs);
                   3763:                    return(-1);
                   3764:                }
                   3765:            }
                   3766:            for (i = 0;i < nbCache;i++) {
                   3767:                if (oldNs[i] == node->ns) {
                   3768:                    node->ns = newNs[i];
                   3769:                    break;
                   3770:                }
                   3771:            }
                   3772:            if (i == nbCache) {
                   3773:                /*
                   3774:                 * Ok we need to recreate a new namespace definition
                   3775:                 */
                   3776:                n = xmlNewReconciliedNs(doc, tree, node->ns);
                   3777:                if (n != NULL) { /* :-( what if else ??? */
                   3778:                    /*
                   3779:                     * check if we need to grow the cache buffers.
                   3780:                     */
                   3781:                    if (sizeCache <= nbCache) {
                   3782:                        sizeCache *= 2;
                   3783:                        oldNs = (xmlNsPtr *) xmlRealloc(oldNs, sizeCache *
                   3784:                                                       sizeof(xmlNsPtr));
                   3785:                        if (oldNs == NULL) {
1.134     veillard 3786:                            xmlGenericError(xmlGenericErrorContext,
                   3787:                                    "xmlReconciliateNs : memory pbm\n");
1.82      daniel   3788:                            xmlFree(newNs);
                   3789:                            return(-1);
                   3790:                        }
                   3791:                        newNs = (xmlNsPtr *) xmlRealloc(newNs, sizeCache *
                   3792:                                                       sizeof(xmlNsPtr));
                   3793:                        if (newNs == NULL) {
1.134     veillard 3794:                            xmlGenericError(xmlGenericErrorContext,
                   3795:                                    "xmlReconciliateNs : memory pbm\n");
1.82      daniel   3796:                            xmlFree(oldNs);
                   3797:                            return(-1);
                   3798:                        }
                   3799:                    }
                   3800:                    newNs[nbCache] = n;
                   3801:                    oldNs[nbCache++] = node->ns;
                   3802:                    node->ns = n;
                   3803:                 }
                   3804:            }
                   3805:        }
                   3806:        /*
                   3807:         * now check for namespace hold by attributes on the node.
                   3808:         */
                   3809:        attr = node->properties;
                   3810:        while (attr != NULL) {
                   3811:            if (attr->ns != NULL) {
                   3812:                /*
                   3813:                 * initialize the cache if needed
                   3814:                 */
                   3815:                if (sizeCache == 0) {
                   3816:                    sizeCache = 10;
                   3817:                    oldNs = (xmlNsPtr *) xmlMalloc(sizeCache *
                   3818:                                                   sizeof(xmlNsPtr));
                   3819:                    if (oldNs == NULL) {
1.134     veillard 3820:                        xmlGenericError(xmlGenericErrorContext,
                   3821:                                "xmlReconciliateNs : memory pbm\n");
1.82      daniel   3822:                        return(-1);
                   3823:                    }
                   3824:                    newNs = (xmlNsPtr *) xmlMalloc(sizeCache *
                   3825:                                                   sizeof(xmlNsPtr));
                   3826:                    if (newNs == NULL) {
1.134     veillard 3827:                        xmlGenericError(xmlGenericErrorContext,
                   3828:                                "xmlReconciliateNs : memory pbm\n");
1.82      daniel   3829:                        xmlFree(oldNs);
                   3830:                        return(-1);
                   3831:                    }
                   3832:                }
                   3833:                for (i = 0;i < nbCache;i++) {
                   3834:                    if (oldNs[i] == attr->ns) {
                   3835:                        node->ns = newNs[i];
                   3836:                        break;
                   3837:                    }
                   3838:                }
                   3839:                if (i == nbCache) {
                   3840:                    /*
                   3841:                     * Ok we need to recreate a new namespace definition
                   3842:                     */
                   3843:                    n = xmlNewReconciliedNs(doc, tree, attr->ns);
                   3844:                    if (n != NULL) { /* :-( what if else ??? */
                   3845:                        /*
                   3846:                         * check if we need to grow the cache buffers.
                   3847:                         */
                   3848:                        if (sizeCache <= nbCache) {
                   3849:                            sizeCache *= 2;
                   3850:                            oldNs = (xmlNsPtr *) xmlRealloc(oldNs, sizeCache *
                   3851:                                                           sizeof(xmlNsPtr));
                   3852:                            if (oldNs == NULL) {
1.134     veillard 3853:                                xmlGenericError(xmlGenericErrorContext,
1.82      daniel   3854:                                        "xmlReconciliateNs : memory pbm\n");
                   3855:                                xmlFree(newNs);
                   3856:                                return(-1);
                   3857:                            }
                   3858:                            newNs = (xmlNsPtr *) xmlRealloc(newNs, sizeCache *
                   3859:                                                           sizeof(xmlNsPtr));
                   3860:                            if (newNs == NULL) {
1.134     veillard 3861:                                xmlGenericError(xmlGenericErrorContext,
1.82      daniel   3862:                                        "xmlReconciliateNs : memory pbm\n");
                   3863:                                xmlFree(oldNs);
                   3864:                                return(-1);
                   3865:                            }
                   3866:                        }
                   3867:                        newNs[nbCache] = n;
                   3868:                        oldNs[nbCache++] = attr->ns;
                   3869:                        attr->ns = n;
                   3870:                    }
                   3871:                }
                   3872:            }
                   3873:            attr = attr->next;
                   3874:        }
                   3875: 
                   3876:        /*
                   3877:         * Browse the full subtree, deep first
                   3878:         */
1.90      daniel   3879:         if (node->children != NULL) {
1.82      daniel   3880:            /* deep first */
1.90      daniel   3881:            node = node->children;
1.82      daniel   3882:        } else if ((node != tree) && (node->next != NULL)) {
                   3883:            /* then siblings */
                   3884:            node = node->next;
                   3885:        } else if (node != tree) {
                   3886:            /* go up to parents->next if needed */
                   3887:            while (node != tree) {
                   3888:                if (node->parent != NULL)
                   3889:                    node = node->parent;
                   3890:                if ((node != tree) && (node->next != NULL)) {
                   3891:                    node = node->next;
                   3892:                    break;
                   3893:                }
                   3894:                if (node->parent == NULL) {
                   3895:                    node = NULL;
                   3896:                    break;
                   3897:                }
                   3898:            }
                   3899:            /* exit condition */
                   3900:            if (node == tree) 
                   3901:                node = NULL;
1.19      daniel   3902:        }
1.3       veillard 3903:     }
1.82      daniel   3904:     return(ret);
1.3       veillard 3905: }
                   3906: 
1.23      daniel   3907: /**
1.116     veillard 3908:  * xmlHasProp:
                   3909:  * @node:  the node
                   3910:  * @name:  the attribute name
                   3911:  *
                   3912:  * Search an attribute associated to a node
                   3913:  * This function also looks in DTD attribute declaration for #FIXED or
                   3914:  * default declaration values unless DTD use has been turned off.
                   3915:  *
                   3916:  * Returns the attribute or the attribute declaration or NULL if 
                   3917:  *         neither was found.
                   3918:  */
                   3919: xmlAttrPtr
                   3920: xmlHasProp(xmlNodePtr node, const xmlChar *name) {
                   3921:     xmlAttrPtr prop;
                   3922:     xmlDocPtr doc;
                   3923: 
                   3924:     if ((node == NULL) || (name == NULL)) return(NULL);
                   3925:     /*
                   3926:      * Check on the properties attached to the node
                   3927:      */
                   3928:     prop = node->properties;
                   3929:     while (prop != NULL) {
1.128     veillard 3930:         if (xmlStrEqual(prop->name, name))  {
1.116     veillard 3931:            return(prop);
                   3932:         }
                   3933:        prop = prop->next;
                   3934:     }
                   3935:     if (!xmlCheckDTD) return(NULL);
                   3936: 
                   3937:     /*
                   3938:      * Check if there is a default declaration in the internal
                   3939:      * or external subsets
                   3940:      */
                   3941:     doc =  node->doc;
                   3942:     if (doc != NULL) {
                   3943:         xmlAttributePtr attrDecl;
                   3944:         if (doc->intSubset != NULL) {
                   3945:            attrDecl = xmlGetDtdAttrDesc(doc->intSubset, node->name, name);
                   3946:            if ((attrDecl == NULL) && (doc->extSubset != NULL))
                   3947:                attrDecl = xmlGetDtdAttrDesc(doc->extSubset, node->name, name);
                   3948:            if (attrDecl != NULL)
                   3949:                return((xmlAttrPtr) attrDecl);
                   3950:        }
                   3951:     }
                   3952:     return(NULL);
                   3953: }
                   3954: 
                   3955: /**
1.23      daniel   3956:  * xmlGetProp:
                   3957:  * @node:  the node
                   3958:  * @name:  the attribute name
                   3959:  *
                   3960:  * Search and get the value of an attribute associated to a node
                   3961:  * This does the entity substitution.
1.74      daniel   3962:  * This function looks in DTD attribute declaration for #FIXED or
                   3963:  * default declaration values unless DTD use has been turned off.
                   3964:  *
1.36      daniel   3965:  * Returns the attribute value or NULL if not found.
1.69      daniel   3966:  *     It's up to the caller to free the memory.
1.9       veillard 3967:  */
1.69      daniel   3968: xmlChar *
                   3969: xmlGetProp(xmlNodePtr node, const xmlChar *name) {
1.74      daniel   3970:     xmlAttrPtr prop;
                   3971:     xmlDocPtr doc;
1.9       veillard 3972: 
1.74      daniel   3973:     if ((node == NULL) || (name == NULL)) return(NULL);
                   3974:     /*
                   3975:      * Check on the properties attached to the node
                   3976:      */
                   3977:     prop = node->properties;
1.9       veillard 3978:     while (prop != NULL) {
1.128     veillard 3979:         if (xmlStrEqual(prop->name, name))  {
1.61      daniel   3980:            xmlChar *ret;
1.34      daniel   3981: 
1.90      daniel   3982:            ret = xmlNodeListGetString(node->doc, prop->children, 1);
1.61      daniel   3983:            if (ret == NULL) return(xmlStrdup((xmlChar *)""));
1.34      daniel   3984:            return(ret);
                   3985:         }
1.9       veillard 3986:        prop = prop->next;
                   3987:     }
1.74      daniel   3988:     if (!xmlCheckDTD) return(NULL);
                   3989: 
                   3990:     /*
                   3991:      * Check if there is a default declaration in the internal
                   3992:      * or external subsets
                   3993:      */
                   3994:     doc =  node->doc;
                   3995:     if (doc != NULL) {
                   3996:         xmlAttributePtr attrDecl;
                   3997:         if (doc->intSubset != NULL) {
                   3998:            attrDecl = xmlGetDtdAttrDesc(doc->intSubset, node->name, name);
                   3999:            if ((attrDecl == NULL) && (doc->extSubset != NULL))
                   4000:                attrDecl = xmlGetDtdAttrDesc(doc->extSubset, node->name, name);
1.86      daniel   4001:            if (attrDecl != NULL)
                   4002:                return(xmlStrdup(attrDecl->defaultValue));
1.74      daniel   4003:        }
                   4004:     }
1.10      veillard 4005:     return(NULL);
1.13      daniel   4006: }
                   4007: 
1.23      daniel   4008: /**
1.73      daniel   4009:  * xmlGetNsProp:
                   4010:  * @node:  the node
                   4011:  * @name:  the attribute name
                   4012:  * @namespace:  the URI of the namespace
                   4013:  *
                   4014:  * Search and get the value of an attribute associated to a node
                   4015:  * This attribute has to be anchored in the namespace specified.
                   4016:  * This does the entity substitution.
1.74      daniel   4017:  * This function looks in DTD attribute declaration for #FIXED or
                   4018:  * default declaration values unless DTD use has been turned off.
1.73      daniel   4019:  *
                   4020:  * Returns the attribute value or NULL if not found.
                   4021:  *     It's up to the caller to free the memory.
                   4022:  */
                   4023: xmlChar *
                   4024: xmlGetNsProp(xmlNodePtr node, const xmlChar *name, const xmlChar *namespace) {
                   4025:     xmlAttrPtr prop = node->properties;
1.74      daniel   4026:     xmlDocPtr doc;
                   4027:     xmlNsPtr ns;
1.73      daniel   4028: 
                   4029:     if (namespace == NULL)
                   4030:        return(xmlGetProp(node, name));
                   4031:     while (prop != NULL) {
1.79      daniel   4032:        /*
                   4033:         * One need to have
                   4034:         *   - same attribute names
                   4035:         *   - and the attribute carrying that namespace
                   4036:         *         or
                   4037:         *         no namespace on the attribute and the element carrying it
                   4038:         */
1.128     veillard 4039:         if ((xmlStrEqual(prop->name, name)) &&
1.79      daniel   4040:            (((prop->ns == NULL) && (node->ns != NULL) &&
1.128     veillard 4041:              (xmlStrEqual(node->ns->href, namespace))) ||
                   4042:             ((prop->ns != NULL) && (xmlStrEqual(prop->ns->href, namespace))))) {
1.73      daniel   4043:            xmlChar *ret;
                   4044: 
1.90      daniel   4045:            ret = xmlNodeListGetString(node->doc, prop->children, 1);
1.73      daniel   4046:            if (ret == NULL) return(xmlStrdup((xmlChar *)""));
                   4047:            return(ret);
                   4048:         }
                   4049:        prop = prop->next;
                   4050:     }
1.74      daniel   4051:     if (!xmlCheckDTD) return(NULL);
                   4052: 
                   4053:     /*
                   4054:      * Check if there is a default declaration in the internal
                   4055:      * or external subsets
                   4056:      */
                   4057:     doc =  node->doc;
                   4058:     if (doc != NULL) {
                   4059:         xmlAttributePtr attrDecl;
                   4060:         if (doc->intSubset != NULL) {
                   4061:            attrDecl = xmlGetDtdAttrDesc(doc->intSubset, node->name, name);
                   4062:            if ((attrDecl == NULL) && (doc->extSubset != NULL))
                   4063:                attrDecl = xmlGetDtdAttrDesc(doc->extSubset, node->name, name);
                   4064:                
                   4065:            if (attrDecl->prefix != NULL) {
                   4066:                /*
                   4067:                 * The DTD declaration only allows a prefix search
                   4068:                 */
                   4069:                ns = xmlSearchNs(doc, node, attrDecl->prefix);
1.128     veillard 4070:                if ((ns != NULL) && (xmlStrEqual(ns->href, namespace)))
1.74      daniel   4071:                    return(xmlStrdup(attrDecl->defaultValue));
                   4072:            }
                   4073:        }
                   4074:     }
1.73      daniel   4075:     return(NULL);
                   4076: }
                   4077: 
                   4078: /**
1.23      daniel   4079:  * xmlSetProp:
                   4080:  * @node:  the node
                   4081:  * @name:  the attribute name
                   4082:  * @value:  the attribute value
                   4083:  *
                   4084:  * Set (or reset) an attribute carried by a node.
1.36      daniel   4085:  * Returns the attribute pointer.
1.13      daniel   4086:  */
1.28      daniel   4087: xmlAttrPtr
1.61      daniel   4088: xmlSetProp(xmlNodePtr node, const xmlChar *name, const xmlChar *value) {
1.20      daniel   4089:     xmlAttrPtr prop = node->properties;
1.13      daniel   4090: 
                   4091:     while (prop != NULL) {
1.128     veillard 4092:         if (xmlStrEqual(prop->name, name)) {
1.90      daniel   4093:            if (prop->children != NULL) 
                   4094:                xmlFreeNodeList(prop->children);
                   4095:            prop->children = NULL;
1.140     veillard 4096:            prop->last = NULL;
1.67      daniel   4097:            if (value != NULL) {
                   4098:                xmlChar *buffer;
1.94      daniel   4099:                xmlNodePtr tmp;
                   4100: 
1.67      daniel   4101:                buffer = xmlEncodeEntitiesReentrant(node->doc, value);
1.90      daniel   4102:                prop->children = xmlStringGetNodeList(node->doc, buffer);
1.140     veillard 4103:                prop->last = NULL;
1.94      daniel   4104:                tmp = prop->children;
                   4105:                while (tmp != NULL) {
                   4106:                    tmp->parent = (xmlNodePtr) prop;
                   4107:                    if (tmp->next == NULL)
                   4108:                        prop->last = tmp;
                   4109:                    tmp = tmp->next;
                   4110:                }
1.67      daniel   4111:                xmlFree(buffer);
                   4112:            }   
1.13      daniel   4113:            return(prop);
                   4114:        }
                   4115:        prop = prop->next;
                   4116:     }
                   4117:     prop = xmlNewProp(node, name, value);
                   4118:     return(prop);
1.9       veillard 4119: }
                   4120: 
1.23      daniel   4121: /**
                   4122:  * xmlNodeIsText:
                   4123:  * @node:  the node
                   4124:  * 
                   4125:  * Is this node a Text node ?
1.36      daniel   4126:  * Returns 1 yes, 0 no
1.21      daniel   4127:  */
1.28      daniel   4128: int
                   4129: xmlNodeIsText(xmlNodePtr node) {
1.21      daniel   4130:     if (node == NULL) return(0);
                   4131: 
1.23      daniel   4132:     if (node->type == XML_TEXT_NODE) return(1);
1.21      daniel   4133:     return(0);
                   4134: }
                   4135: 
1.23      daniel   4136: /**
1.99      daniel   4137:  * xmlIsBlankNode:
                   4138:  * @node:  the node
                   4139:  * 
1.113     veillard 4140:  * Checks whether this node is an empty or whitespace only
                   4141:  * (and possibly ignorable) text-node.
                   4142:  *
1.99      daniel   4143:  * Returns 1 yes, 0 no
                   4144:  */
                   4145: int
                   4146: xmlIsBlankNode(xmlNodePtr node) {
1.137     veillard 4147:     const xmlChar *cur;
1.99      daniel   4148:     if (node == NULL) return(0);
                   4149: 
                   4150:     if (node->type != XML_TEXT_NODE) return(0);
1.129     veillard 4151:     if (node->content == NULL) return(1);
1.137     veillard 4152: #ifndef XML_USE_BUFFER_CONTENT
1.99      daniel   4153:     cur = node->content;
1.137     veillard 4154: #else
                   4155:     cur = xmlBufferContent(node->content);
                   4156: #endif
1.99      daniel   4157:     while (*cur != 0) {
                   4158:        if (!IS_BLANK(*cur)) return(0);
                   4159:        cur++;
                   4160:     }
                   4161: 
                   4162:     return(1);
                   4163: }
                   4164: 
                   4165: /**
1.36      daniel   4166:  * xmlTextConcat:
1.23      daniel   4167:  * @node:  the node
                   4168:  * @content:  the content
                   4169:  * @len:  @content lenght
                   4170:  * 
                   4171:  * Concat the given string at the end of the existing node content
1.21      daniel   4172:  */
1.23      daniel   4173: 
1.28      daniel   4174: void
1.61      daniel   4175: xmlTextConcat(xmlNodePtr node, const xmlChar *content, int len) {
1.21      daniel   4176:     if (node == NULL) return;
                   4177: 
1.82      daniel   4178:     if ((node->type != XML_TEXT_NODE) &&
                   4179:         (node->type != XML_CDATA_SECTION_NODE)) {
1.86      daniel   4180: #ifdef DEBUG_TREE
1.134     veillard 4181:        xmlGenericError(xmlGenericErrorContext,
                   4182:                "xmlTextConcat: node is not text nor cdata\n");
1.86      daniel   4183: #endif
1.21      daniel   4184:         return;
                   4185:     }
1.70      daniel   4186: #ifndef XML_USE_BUFFER_CONTENT
1.21      daniel   4187:     node->content = xmlStrncat(node->content, content, len);
1.70      daniel   4188: #else
                   4189:     xmlBufferAdd(node->content, content, len);
                   4190: #endif
1.21      daniel   4191: }
                   4192: 
1.1       veillard 4193: /************************************************************************
                   4194:  *                                                                     *
1.8       veillard 4195:  *                     Output : to a FILE or in memory                 *
1.1       veillard 4196:  *                                                                     *
                   4197:  ************************************************************************/
                   4198: 
1.38      daniel   4199: #define BASE_BUFFER_SIZE 4000
1.8       veillard 4200: 
1.23      daniel   4201: /**
1.38      daniel   4202:  * xmlBufferCreate:
                   4203:  *
                   4204:  * routine to create an XML buffer.
                   4205:  * returns the new structure.
                   4206:  */
                   4207: xmlBufferPtr
                   4208: xmlBufferCreate(void) {
                   4209:     xmlBufferPtr ret;
                   4210: 
1.57      daniel   4211:     ret = (xmlBufferPtr) xmlMalloc(sizeof(xmlBuffer));
1.38      daniel   4212:     if (ret == NULL) {
1.134     veillard 4213:        xmlGenericError(xmlGenericErrorContext,
                   4214:                "xmlBufferCreate : out of memory!\n");
1.38      daniel   4215:         return(NULL);
                   4216:     }
                   4217:     ret->use = 0;
                   4218:     ret->size = BASE_BUFFER_SIZE;
1.72      daniel   4219:     ret->alloc = xmlBufferAllocScheme;
1.61      daniel   4220:     ret->content = (xmlChar *) xmlMalloc(ret->size * sizeof(xmlChar));
1.38      daniel   4221:     if (ret->content == NULL) {
1.134     veillard 4222:        xmlGenericError(xmlGenericErrorContext,
                   4223:                "xmlBufferCreate : out of memory!\n");
1.57      daniel   4224:        xmlFree(ret);
1.38      daniel   4225:         return(NULL);
                   4226:     }
                   4227:     ret->content[0] = 0;
                   4228:     return(ret);
                   4229: }
                   4230: 
                   4231: /**
1.70      daniel   4232:  * xmlBufferCreateSize:
                   4233:  * @size: initial size of buffer
                   4234:  *
                   4235:  * routine to create an XML buffer.
                   4236:  * returns the new structure.
                   4237:  */
                   4238: xmlBufferPtr
                   4239: xmlBufferCreateSize(size_t size) {
                   4240:     xmlBufferPtr ret;
                   4241: 
                   4242:     ret = (xmlBufferPtr) xmlMalloc(sizeof(xmlBuffer));
                   4243:     if (ret == NULL) {
1.134     veillard 4244:         xmlGenericError(xmlGenericErrorContext,
                   4245:                "xmlBufferCreate : out of memory!\n");
1.70      daniel   4246:         return(NULL);
                   4247:     }
                   4248:     ret->use = 0;
1.72      daniel   4249:     ret->alloc = xmlBufferAllocScheme;
1.70      daniel   4250:     ret->size = (size ? size+2 : 0);         /* +1 for ending null */
1.72      daniel   4251:     if (ret->size){
1.70      daniel   4252:         ret->content = (xmlChar *) xmlMalloc(ret->size * sizeof(xmlChar));
                   4253:         if (ret->content == NULL) {
1.134     veillard 4254:             xmlGenericError(xmlGenericErrorContext,
                   4255:                    "xmlBufferCreate : out of memory!\n");
1.70      daniel   4256:             xmlFree(ret);
                   4257:             return(NULL);
                   4258:         }
                   4259:         ret->content[0] = 0;
                   4260:     } else
                   4261:        ret->content = NULL;
                   4262:     return(ret);
                   4263: }
                   4264: 
                   4265: /**
1.104     daniel   4266:  * xmlBufferSetAllocationScheme:
1.70      daniel   4267:  * @buf:  the buffer to free
                   4268:  * @scheme:  allocation scheme to use
                   4269:  *
                   4270:  * Sets the allocation scheme for this buffer
                   4271:  */
                   4272: void
                   4273: xmlBufferSetAllocationScheme(xmlBufferPtr buf, 
                   4274:                              xmlBufferAllocationScheme scheme) {
                   4275:     if (buf == NULL) {
1.86      daniel   4276: #ifdef DEBUG_BUFFER
1.134     veillard 4277:         xmlGenericError(xmlGenericErrorContext,
                   4278:                "xmlBufferSetAllocationScheme: buf == NULL\n");
1.86      daniel   4279: #endif
1.70      daniel   4280:         return;
                   4281:     }
                   4282: 
                   4283:     buf->alloc = scheme;
                   4284: }
                   4285: 
                   4286: /**
1.38      daniel   4287:  * xmlBufferFree:
                   4288:  * @buf:  the buffer to free
                   4289:  *
                   4290:  * Frees an XML buffer.
                   4291:  */
                   4292: void
                   4293: xmlBufferFree(xmlBufferPtr buf) {
                   4294:     if (buf == NULL) {
1.86      daniel   4295: #ifdef DEBUG_BUFFER
1.134     veillard 4296:         xmlGenericError(xmlGenericErrorContext,
                   4297:                "xmlBufferFree: buf == NULL\n");
1.86      daniel   4298: #endif
1.38      daniel   4299:        return;
                   4300:     }
1.71      daniel   4301:     if (buf->content != NULL) {
1.70      daniel   4302: #ifndef XML_USE_BUFFER_CONTENT
1.38      daniel   4303:         memset(buf->content, -1, BASE_BUFFER_SIZE);
1.70      daniel   4304: #else
                   4305:         memset(buf->content, -1, buf->size);
                   4306: #endif
1.57      daniel   4307:         xmlFree(buf->content);
1.38      daniel   4308:     }
                   4309:     memset(buf, -1, sizeof(xmlBuffer));
1.57      daniel   4310:     xmlFree(buf);
1.38      daniel   4311: }
                   4312: 
                   4313: /**
1.47      daniel   4314:  * xmlBufferEmpty:
                   4315:  * @buf:  the buffer
                   4316:  *
                   4317:  * empty a buffer.
                   4318:  */
                   4319: void
                   4320: xmlBufferEmpty(xmlBufferPtr buf) {
1.124     veillard 4321:     if (buf->content == NULL) return;
1.47      daniel   4322:     buf->use = 0;
                   4323:     memset(buf->content, -1, buf->size);/* just for debug */
                   4324: }
                   4325: 
                   4326: /**
                   4327:  * xmlBufferShrink:
                   4328:  * @buf:  the buffer to dump
1.61      daniel   4329:  * @len:  the number of xmlChar to remove
1.47      daniel   4330:  *
                   4331:  * Remove the beginning of an XML buffer.
                   4332:  *
1.61      daniel   4333:  * Returns the number of xmlChar removed, or -1 in case of failure.
1.47      daniel   4334:  */
                   4335: int
1.127     veillard 4336: xmlBufferShrink(xmlBufferPtr buf, unsigned int len) {
1.47      daniel   4337:     if (len == 0) return(0);
                   4338:     if (len > buf->use) return(-1);
                   4339: 
                   4340:     buf->use -= len;
1.61      daniel   4341:     memmove(buf->content, &buf->content[len], buf->use * sizeof(xmlChar));
1.47      daniel   4342: 
                   4343:     buf->content[buf->use] = 0;
                   4344:     return(len);
                   4345: }
                   4346: 
                   4347: /**
1.105     daniel   4348:  * xmlBufferGrow:
                   4349:  * @buf:  the buffer
1.148     veillard 4350:  * @len:  the minimum free size to allocate
1.105     daniel   4351:  *
                   4352:  * Grow the available space of an XML buffer.
                   4353:  *
                   4354:  * Returns the new available space or -1 in case of error
                   4355:  */
                   4356: int
1.127     veillard 4357: xmlBufferGrow(xmlBufferPtr buf, unsigned int len) {
1.105     daniel   4358:     int size;
                   4359:     xmlChar *newbuf;
                   4360: 
1.148     veillard 4361:     if (len + buf->use < buf->size) return(0);
1.105     daniel   4362: 
1.109     daniel   4363:     size = buf->use + len + 100;
1.105     daniel   4364: 
1.112     veillard 4365:     newbuf = (xmlChar *) xmlRealloc(buf->content, size);
1.105     daniel   4366:     if (newbuf == NULL) return(-1);
                   4367:     buf->content = newbuf;
                   4368:     buf->size = size;
                   4369:     return(buf->size - buf->use);
                   4370: }
                   4371: 
                   4372: /**
1.38      daniel   4373:  * xmlBufferDump:
                   4374:  * @file:  the file output
                   4375:  * @buf:  the buffer to dump
                   4376:  *
                   4377:  * Dumps an XML buffer to  a FILE *.
1.61      daniel   4378:  * Returns the number of xmlChar written
1.38      daniel   4379:  */
                   4380: int
                   4381: xmlBufferDump(FILE *file, xmlBufferPtr buf) {
                   4382:     int ret;
                   4383: 
                   4384:     if (buf == NULL) {
1.86      daniel   4385: #ifdef DEBUG_BUFFER
1.134     veillard 4386:         xmlGenericError(xmlGenericErrorContext,
                   4387:                "xmlBufferDump: buf == NULL\n");
1.86      daniel   4388: #endif
1.38      daniel   4389:        return(0);
                   4390:     }
                   4391:     if (buf->content == NULL) {
1.86      daniel   4392: #ifdef DEBUG_BUFFER
1.134     veillard 4393:         xmlGenericError(xmlGenericErrorContext,
                   4394:                "xmlBufferDump: buf->content == NULL\n");
1.86      daniel   4395: #endif
1.38      daniel   4396:        return(0);
                   4397:     }
                   4398:     if (file == NULL) file = stdout;
1.61      daniel   4399:     ret = fwrite(buf->content, sizeof(xmlChar), buf->use, file);
1.38      daniel   4400:     return(ret);
                   4401: }
                   4402: 
                   4403: /**
1.70      daniel   4404:  * xmlBufferContent:
                   4405:  * @buf:  the buffer to resize
                   4406:  *
                   4407:  * Returns the internal content
                   4408:  */
                   4409: 
                   4410: const xmlChar* 
                   4411: xmlBufferContent(const xmlBufferPtr buf)
                   4412: {
                   4413:     if(!buf)
                   4414:         return NULL;
                   4415: 
                   4416:     return buf->content;
                   4417: }
                   4418: 
                   4419: /**
                   4420:  * xmlBufferLength:
                   4421:  * @buf:  the buffer 
                   4422:  *
                   4423:  * Returns the length of data in the internal content
                   4424:  */
                   4425: 
                   4426: int
                   4427: xmlBufferLength(const xmlBufferPtr buf)
                   4428: {
                   4429:     if(!buf)
                   4430:         return 0;
                   4431: 
                   4432:     return buf->use;
                   4433: }
                   4434: 
                   4435: /**
                   4436:  * xmlBufferResize:
                   4437:  * @buf:  the buffer to resize
1.127     veillard 4438:  * @size:  the desired size
1.70      daniel   4439:  *
1.127     veillard 4440:  * Resize a buffer to accomodate minimum size of @size.
1.70      daniel   4441:  *
                   4442:  * Returns  0 in case of problems, 1 otherwise
                   4443:  */
                   4444: int
1.127     veillard 4445: xmlBufferResize(xmlBufferPtr buf, unsigned int size)
1.70      daniel   4446: {
1.127     veillard 4447:     unsigned int newSize;
1.70      daniel   4448:     xmlChar* rebuf = NULL;
                   4449: 
1.127     veillard 4450:     /*take care of empty case*/
                   4451:     newSize = (buf->size ? buf->size*2 : size);
                   4452: 
1.70      daniel   4453:     /* Don't resize if we don't have to */
1.127     veillard 4454:     if (size < buf->size)
1.70      daniel   4455:         return 1;
                   4456: 
                   4457:     /* figure out new size */
1.127     veillard 4458:     switch (buf->alloc){
1.70      daniel   4459:     case XML_BUFFER_ALLOC_DOUBLEIT:
1.127     veillard 4460:         while (size > newSize) newSize *= 2;
1.70      daniel   4461:         break;
                   4462:     case XML_BUFFER_ALLOC_EXACT:
                   4463:         newSize = size+10;
                   4464:         break;
                   4465:     default:
                   4466:         newSize = size+10;
                   4467:         break;
                   4468:     }
                   4469: 
                   4470:     if (buf->content == NULL)
                   4471:        rebuf = (xmlChar *) xmlMalloc(newSize * sizeof(xmlChar));
                   4472:     else
                   4473:        rebuf = (xmlChar *) xmlRealloc(buf->content, 
                   4474:                                       newSize * sizeof(xmlChar));
                   4475:     if (rebuf == NULL) {
1.134     veillard 4476:         xmlGenericError(xmlGenericErrorContext,
                   4477:                "xmlBufferAdd : out of memory!\n");
1.70      daniel   4478:         return 0;
                   4479:     }
                   4480:     buf->content = rebuf;
                   4481:     buf->size = newSize;
                   4482: 
                   4483:     return 1;
                   4484: }
1.127     veillard 4485: 
1.70      daniel   4486: /**
1.38      daniel   4487:  * xmlBufferAdd:
                   4488:  * @buf:  the buffer to dump
1.61      daniel   4489:  * @str:  the xmlChar string
                   4490:  * @len:  the number of xmlChar to add
1.38      daniel   4491:  *
1.74      daniel   4492:  * Add a string range to an XML buffer. if len == -1, the lenght of
                   4493:  * str is recomputed.
1.38      daniel   4494:  */
                   4495: void
1.61      daniel   4496: xmlBufferAdd(xmlBufferPtr buf, const xmlChar *str, int len) {
1.127     veillard 4497:     unsigned int needSize;
1.38      daniel   4498: 
                   4499:     if (str == NULL) {
1.86      daniel   4500: #ifdef DEBUG_BUFFER
1.134     veillard 4501:         xmlGenericError(xmlGenericErrorContext,
                   4502:                "xmlBufferAdd: str == NULL\n");
1.86      daniel   4503: #endif
1.38      daniel   4504:        return;
                   4505:     }
1.74      daniel   4506:     if (len < -1) {
1.86      daniel   4507: #ifdef DEBUG_BUFFER
1.134     veillard 4508:         xmlGenericError(xmlGenericErrorContext,
                   4509:                "xmlBufferAdd: len < 0\n");
1.86      daniel   4510: #endif
1.74      daniel   4511:        return;
                   4512:     }
                   4513:     if (len == 0) return;
1.70      daniel   4514: 
1.82      daniel   4515:     if (len < 0)
1.89      daniel   4516:         len = xmlStrlen(str);
1.70      daniel   4517: 
1.47      daniel   4518:     if (len <= 0) return;
                   4519: 
1.70      daniel   4520:     needSize = buf->use + len + 2;
1.127     veillard 4521:     if (needSize > buf->size){
                   4522:         if (!xmlBufferResize(buf, needSize)){
1.134     veillard 4523:             xmlGenericError(xmlGenericErrorContext,
                   4524:                    "xmlBufferAdd : out of memory!\n");
1.70      daniel   4525:             return;
                   4526:         }
                   4527:     }
1.47      daniel   4528: 
1.70      daniel   4529:     memmove(&buf->content[buf->use], str, len*sizeof(xmlChar));
1.47      daniel   4530:     buf->use += len;
                   4531:     buf->content[buf->use] = 0;
1.38      daniel   4532: }
                   4533: 
                   4534: /**
1.109     daniel   4535:  * xmlBufferAddHead:
                   4536:  * @buf:  the buffer
                   4537:  * @str:  the xmlChar string
                   4538:  * @len:  the number of xmlChar to add
                   4539:  *
                   4540:  * Add a string range to the beginning of an XML buffer.
                   4541:  * if len == -1, the lenght of @str is recomputed.
                   4542:  */
                   4543: void
                   4544: xmlBufferAddHead(xmlBufferPtr buf, const xmlChar *str, int len) {
1.127     veillard 4545:     unsigned int needSize;
1.109     daniel   4546: 
                   4547:     if (str == NULL) {
                   4548: #ifdef DEBUG_BUFFER
1.134     veillard 4549:         xmlGenericError(xmlGenericErrorContext,
                   4550:                "xmlBufferAdd: str == NULL\n");
1.109     daniel   4551: #endif
                   4552:        return;
                   4553:     }
                   4554:     if (len < -1) {
                   4555: #ifdef DEBUG_BUFFER
1.134     veillard 4556:         xmlGenericError(xmlGenericErrorContext,
                   4557:                "xmlBufferAdd: len < 0\n");
1.109     daniel   4558: #endif
                   4559:        return;
                   4560:     }
                   4561:     if (len == 0) return;
                   4562: 
                   4563:     if (len < 0)
                   4564:         len = xmlStrlen(str);
                   4565: 
                   4566:     if (len <= 0) return;
                   4567: 
                   4568:     needSize = buf->use + len + 2;
1.127     veillard 4569:     if (needSize > buf->size){
                   4570:         if (!xmlBufferResize(buf, needSize)){
1.134     veillard 4571:             xmlGenericError(xmlGenericErrorContext,
                   4572:                    "xmlBufferAddHead : out of memory!\n");
1.109     daniel   4573:             return;
                   4574:         }
                   4575:     }
                   4576: 
                   4577:     memmove(&buf->content[len], &buf->content[0], buf->use * sizeof(xmlChar));
                   4578:     memmove(&buf->content[0], str, len * sizeof(xmlChar));
                   4579:     buf->use += len;
                   4580:     buf->content[buf->use] = 0;
                   4581: }
                   4582: 
                   4583: /**
1.38      daniel   4584:  * xmlBufferCat:
                   4585:  * @buf:  the buffer to dump
1.61      daniel   4586:  * @str:  the xmlChar string
1.23      daniel   4587:  *
1.38      daniel   4588:  * Append a zero terminated string to an XML buffer.
1.23      daniel   4589:  */
1.28      daniel   4590: void
1.61      daniel   4591: xmlBufferCat(xmlBufferPtr buf, const xmlChar *str) {
1.70      daniel   4592:     if (str != NULL)
                   4593:        xmlBufferAdd(buf, str, -1);
1.8       veillard 4594: }
                   4595: 
1.23      daniel   4596: /**
1.38      daniel   4597:  * xmlBufferCCat:
                   4598:  * @buf:  the buffer to dump
                   4599:  * @str:  the C char string
1.23      daniel   4600:  *
1.38      daniel   4601:  * Append a zero terminated C string to an XML buffer.
1.23      daniel   4602:  */
1.28      daniel   4603: void
1.38      daniel   4604: xmlBufferCCat(xmlBufferPtr buf, const char *str) {
1.21      daniel   4605:     const char *cur;
1.8       veillard 4606: 
1.38      daniel   4607:     if (str == NULL) {
1.86      daniel   4608: #ifdef DEBUG_BUFFER
1.134     veillard 4609:         xmlGenericError(xmlGenericErrorContext,
                   4610:                "xmlBufferAdd: str == NULL\n");
1.86      daniel   4611: #endif
1.38      daniel   4612:        return;
                   4613:     }
                   4614:     for (cur = str;*cur != 0;cur++) {
                   4615:         if (buf->use  + 10 >= buf->size) {
1.127     veillard 4616:             if (!xmlBufferResize(buf, buf->use+10)){
1.134     veillard 4617:                 xmlGenericError(xmlGenericErrorContext,
                   4618:                        "xmlBufferCCat : out of memory!\n");
1.70      daniel   4619:                 return;
                   4620:             }
                   4621:         }
1.38      daniel   4622:         buf->content[buf->use++] = *cur;
1.8       veillard 4623:     }
                   4624: }
                   4625: 
1.23      daniel   4626: /**
1.38      daniel   4627:  * xmlBufferWriteCHAR:
                   4628:  * @buf:  the XML buffer
                   4629:  * @string:  the string to add
                   4630:  *
1.145     veillard 4631:  * routine which manages and grows an output buffer. This one adds
1.61      daniel   4632:  * xmlChars at the end of the buffer.
1.38      daniel   4633:  */
                   4634: void
1.145     veillard 4635: #ifdef VMS
                   4636: xmlBufferWriteXmlCHAR
                   4637: #else
                   4638: xmlBufferWriteCHAR
                   4639: #endif
                   4640: (xmlBufferPtr buf, const xmlChar *string) {
1.38      daniel   4641:     xmlBufferCat(buf, string);
                   4642: }
                   4643: 
                   4644: /**
                   4645:  * xmlBufferWriteChar:
1.42      daniel   4646:  * @buf:  the XML buffer output
1.38      daniel   4647:  * @string:  the string to add
                   4648:  *
                   4649:  * routine which manage and grows an output buffer. This one add
                   4650:  * C chars at the end of the array.
                   4651:  */
                   4652: void
                   4653: xmlBufferWriteChar(xmlBufferPtr buf, const char *string) {
                   4654:     xmlBufferCCat(buf, string);
                   4655: }
                   4656: 
                   4657: 
                   4658: /**
1.43      daniel   4659:  * xmlBufferWriteQuotedString:
                   4660:  * @buf:  the XML buffer output
                   4661:  * @string:  the string to add
                   4662:  *
                   4663:  * routine which manage and grows an output buffer. This one writes
1.61      daniel   4664:  * a quoted or double quoted xmlChar string, checking first if it holds
1.43      daniel   4665:  * quote or double-quotes internally
                   4666:  */
                   4667: void
1.61      daniel   4668: xmlBufferWriteQuotedString(xmlBufferPtr buf, const xmlChar *string) {
1.53      daniel   4669:     if (xmlStrchr(string, '"')) {
                   4670:         if (xmlStrchr(string, '\'')) {
1.86      daniel   4671: #ifdef DEBUG_BUFFER
1.134     veillard 4672:            xmlGenericError(xmlGenericErrorContext,
1.43      daniel   4673:  "xmlBufferWriteQuotedString: string contains quote and double-quotes !\n");
1.86      daniel   4674: #endif
1.43      daniel   4675:        }
                   4676:         xmlBufferCCat(buf, "'");
                   4677:         xmlBufferCat(buf, string);
                   4678:         xmlBufferCCat(buf, "'");
                   4679:     } else {
                   4680:         xmlBufferCCat(buf, "\"");
                   4681:         xmlBufferCat(buf, string);
                   4682:         xmlBufferCCat(buf, "\"");
                   4683:     }
                   4684: }
                   4685: 
                   4686: 
1.106     daniel   4687: /************************************************************************
                   4688:  *                                                                     *
                   4689:  *             Dumping XML tree content to a simple buffer             *
                   4690:  *                                                                     *
                   4691:  ************************************************************************/
                   4692: 
1.125     veillard 4693: void
1.99      daniel   4694: xmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
                   4695:             int format);
                   4696: static void
                   4697: xmlNodeListDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
                   4698:                 int format);
                   4699: void
                   4700: htmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur);
                   4701: 
1.43      daniel   4702: /**
1.23      daniel   4703:  * xmlNsDump:
1.42      daniel   4704:  * @buf:  the XML buffer output
1.23      daniel   4705:  * @cur:  a namespace
                   4706:  *
1.19      daniel   4707:  * Dump a local Namespace definition.
1.23      daniel   4708:  * Should be called in the context of attributes dumps.
1.19      daniel   4709:  */
1.28      daniel   4710: static void
1.38      daniel   4711: xmlNsDump(xmlBufferPtr buf, xmlNsPtr cur) {
1.19      daniel   4712:     if (cur == NULL) {
1.86      daniel   4713: #ifdef DEBUG_TREE
1.134     veillard 4714:         xmlGenericError(xmlGenericErrorContext,
                   4715:                "xmlNsDump : Ns == NULL\n");
1.86      daniel   4716: #endif
1.19      daniel   4717:        return;
                   4718:     }
                   4719:     if (cur->type == XML_LOCAL_NAMESPACE) {
                   4720:         /* Within the context of an element attributes */
1.16      daniel   4721:        if (cur->prefix != NULL) {
1.38      daniel   4722:            xmlBufferWriteChar(buf, " xmlns:");
                   4723:            xmlBufferWriteCHAR(buf, cur->prefix);
1.19      daniel   4724:        } else
1.38      daniel   4725:            xmlBufferWriteChar(buf, " xmlns");
1.43      daniel   4726:        xmlBufferWriteChar(buf, "=");
                   4727:        xmlBufferWriteQuotedString(buf, cur->href);
1.19      daniel   4728:     }
                   4729: }
                   4730: 
1.23      daniel   4731: /**
                   4732:  * xmlNsListDump:
1.42      daniel   4733:  * @buf:  the XML buffer output
1.23      daniel   4734:  * @cur:  the first namespace
                   4735:  *
                   4736:  * Dump a list of local Namespace definitions.
                   4737:  * Should be called in the context of attributes dumps.
1.19      daniel   4738:  */
1.28      daniel   4739: static void
1.38      daniel   4740: xmlNsListDump(xmlBufferPtr buf, xmlNsPtr cur) {
1.19      daniel   4741:     while (cur != NULL) {
1.38      daniel   4742:         xmlNsDump(buf, cur);
1.19      daniel   4743:        cur = cur->next;
1.8       veillard 4744:     }
1.1       veillard 4745: }
                   4746: 
1.23      daniel   4747: /**
                   4748:  * xmlDtdDump:
1.42      daniel   4749:  * @buf:  the XML buffer output
1.23      daniel   4750:  * @doc:  the document
                   4751:  * 
                   4752:  * Dump the XML document DTD, if any.
1.17      daniel   4753:  */
1.28      daniel   4754: static void
1.92      daniel   4755: xmlDtdDump(xmlBufferPtr buf, xmlDtdPtr dtd) {
                   4756:     if (dtd == NULL) {
1.86      daniel   4757: #ifdef DEBUG_TREE
1.134     veillard 4758:         xmlGenericError(xmlGenericErrorContext,
                   4759:                "xmlDtdDump : no internal subset\n");
1.86      daniel   4760: #endif
1.17      daniel   4761:        return;
                   4762:     }
1.38      daniel   4763:     xmlBufferWriteChar(buf, "<!DOCTYPE ");
1.92      daniel   4764:     xmlBufferWriteCHAR(buf, dtd->name);
                   4765:     if (dtd->ExternalID != NULL) {
1.43      daniel   4766:        xmlBufferWriteChar(buf, " PUBLIC ");
1.92      daniel   4767:        xmlBufferWriteQuotedString(buf, dtd->ExternalID);
1.43      daniel   4768:        xmlBufferWriteChar(buf, " ");
1.92      daniel   4769:        xmlBufferWriteQuotedString(buf, dtd->SystemID);
                   4770:     }  else if (dtd->SystemID != NULL) {
1.43      daniel   4771:        xmlBufferWriteChar(buf, " SYSTEM ");
1.92      daniel   4772:        xmlBufferWriteQuotedString(buf, dtd->SystemID);
1.17      daniel   4773:     }
1.92      daniel   4774:     if ((dtd->entities == NULL) && (dtd->elements == NULL) &&
                   4775:         (dtd->attributes == NULL) && (dtd->notations == NULL)) {
                   4776:        xmlBufferWriteChar(buf, ">");
1.21      daniel   4777:        return;
                   4778:     }
1.38      daniel   4779:     xmlBufferWriteChar(buf, " [\n");
1.99      daniel   4780:     xmlNodeListDump(buf, dtd->doc, dtd->children, -1, 0);
                   4781: #if 0
1.92      daniel   4782:     if (dtd->entities != NULL)
                   4783:        xmlDumpEntitiesTable(buf, (xmlEntitiesTablePtr) dtd->entities);
                   4784:     if (dtd->notations != NULL)
                   4785:        xmlDumpNotationTable(buf, (xmlNotationTablePtr) dtd->notations);
                   4786:     if (dtd->elements != NULL)
                   4787:        xmlDumpElementTable(buf, (xmlElementTablePtr) dtd->elements);
                   4788:     if (dtd->attributes != NULL)
                   4789:        xmlDumpAttributeTable(buf, (xmlAttributeTablePtr) dtd->attributes);
1.99      daniel   4790: #endif
                   4791:     xmlBufferWriteChar(buf, "]>");
1.17      daniel   4792: }
                   4793: 
1.23      daniel   4794: /**
                   4795:  * xmlAttrDump:
1.42      daniel   4796:  * @buf:  the XML buffer output
1.23      daniel   4797:  * @doc:  the document
                   4798:  * @cur:  the attribute pointer
                   4799:  *
                   4800:  * Dump an XML attribute
1.1       veillard 4801:  */
1.28      daniel   4802: static void
1.38      daniel   4803: xmlAttrDump(xmlBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur) {
1.61      daniel   4804:     xmlChar *value;
1.1       veillard 4805: 
                   4806:     if (cur == NULL) {
1.86      daniel   4807: #ifdef DEBUG_TREE
1.134     veillard 4808:         xmlGenericError(xmlGenericErrorContext,
                   4809:                "xmlAttrDump : property == NULL\n");
1.86      daniel   4810: #endif
1.1       veillard 4811:        return;
                   4812:     }
1.38      daniel   4813:     xmlBufferWriteChar(buf, " ");
1.56      daniel   4814:     if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
                   4815:         xmlBufferWriteCHAR(buf, cur->ns->prefix);
                   4816:        xmlBufferWriteChar(buf, ":");
                   4817:     }
1.38      daniel   4818:     xmlBufferWriteCHAR(buf, cur->name);
1.90      daniel   4819:     value = xmlNodeListGetString(doc, cur->children, 0);
1.149   ! veillard 4820:     if (value != NULL) {
1.43      daniel   4821:        xmlBufferWriteChar(buf, "=");
                   4822:        xmlBufferWriteQuotedString(buf, value);
1.57      daniel   4823:        xmlFree(value);
1.34      daniel   4824:     } else  {
1.38      daniel   4825:        xmlBufferWriteChar(buf, "=\"\"");
1.3       veillard 4826:     }
1.8       veillard 4827: }
                   4828: 
1.23      daniel   4829: /**
                   4830:  * xmlAttrListDump:
1.42      daniel   4831:  * @buf:  the XML buffer output
1.23      daniel   4832:  * @doc:  the document
                   4833:  * @cur:  the first attribute pointer
                   4834:  *
                   4835:  * Dump a list of XML attributes
1.8       veillard 4836:  */
1.28      daniel   4837: static void
1.38      daniel   4838: xmlAttrListDump(xmlBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur) {
1.8       veillard 4839:     if (cur == NULL) {
1.86      daniel   4840: #ifdef DEBUG_TREE
1.134     veillard 4841:         xmlGenericError(xmlGenericErrorContext,
                   4842:                "xmlAttrListDump : property == NULL\n");
1.86      daniel   4843: #endif
1.1       veillard 4844:        return;
                   4845:     }
1.8       veillard 4846:     while (cur != NULL) {
1.38      daniel   4847:         xmlAttrDump(buf, doc, cur);
1.8       veillard 4848:        cur = cur->next;
1.1       veillard 4849:     }
                   4850: }
                   4851: 
                   4852: 
1.82      daniel   4853: 
1.23      daniel   4854: /**
                   4855:  * xmlNodeListDump:
1.42      daniel   4856:  * @buf:  the XML buffer output
1.23      daniel   4857:  * @doc:  the document
                   4858:  * @cur:  the first node
                   4859:  * @level: the imbrication level for indenting
1.64      daniel   4860:  * @format: is formatting allowed
1.23      daniel   4861:  *
                   4862:  * Dump an XML node list, recursive behaviour,children are printed too.
                   4863:  */
1.28      daniel   4864: static void
1.64      daniel   4865: xmlNodeListDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
                   4866:                 int format) {
                   4867:     int i;
1.25      daniel   4868: 
1.1       veillard 4869:     if (cur == NULL) {
1.86      daniel   4870: #ifdef DEBUG_TREE
1.134     veillard 4871:         xmlGenericError(xmlGenericErrorContext,
                   4872:                "xmlNodeListDump : node == NULL\n");
1.86      daniel   4873: #endif
1.1       veillard 4874:        return;
                   4875:     }
1.8       veillard 4876:     while (cur != NULL) {
1.64      daniel   4877:        if ((format) && (xmlIndentTreeOutput) &&
                   4878:            (cur->type == XML_ELEMENT_NODE))
                   4879:            for (i = 0;i < level;i++)
                   4880:                xmlBufferWriteChar(buf, "  ");
                   4881:         xmlNodeDump(buf, doc, cur, level, format);
                   4882:        if (format) {
                   4883:            xmlBufferWriteChar(buf, "\n");
1.25      daniel   4884:        }
1.8       veillard 4885:        cur = cur->next;
1.3       veillard 4886:     }
1.1       veillard 4887: }
                   4888: 
1.23      daniel   4889: /**
1.25      daniel   4890:  * xmlNodeDump:
1.42      daniel   4891:  * @buf:  the XML buffer output
1.23      daniel   4892:  * @doc:  the document
                   4893:  * @cur:  the current node
                   4894:  * @level: the imbrication level for indenting
1.64      daniel   4895:  * @format: is formatting allowed
1.23      daniel   4896:  *
                   4897:  * Dump an XML node, recursive behaviour,children are printed too.
1.1       veillard 4898:  */
1.125     veillard 4899: void
1.64      daniel   4900: xmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
                   4901:             int format) {
1.8       veillard 4902:     int i;
1.64      daniel   4903:     xmlNodePtr tmp;
1.8       veillard 4904: 
1.1       veillard 4905:     if (cur == NULL) {
1.86      daniel   4906: #ifdef DEBUG_TREE
1.134     veillard 4907:         xmlGenericError(xmlGenericErrorContext,
                   4908:                "xmlNodeDump : node == NULL\n");
1.86      daniel   4909: #endif
1.8       veillard 4910:        return;
                   4911:     }
1.141     veillard 4912:     if (cur->type == XML_XINCLUDE_START)
                   4913:        return;
                   4914:     if (cur->type == XML_XINCLUDE_END)
                   4915:        return;
1.92      daniel   4916:     if (cur->type == XML_DTD_NODE) {
                   4917:         xmlDtdDump(buf, (xmlDtdPtr) cur);
                   4918:        return;
                   4919:     }
1.99      daniel   4920:     if (cur->type == XML_ELEMENT_DECL) {
                   4921:         xmlDumpElementDecl(buf, (xmlElementPtr) cur);
                   4922:        return;
                   4923:     }
                   4924:     if (cur->type == XML_ATTRIBUTE_DECL) {
                   4925:         xmlDumpAttributeDecl(buf, (xmlAttributePtr) cur);
                   4926:        return;
                   4927:     }
                   4928:     if (cur->type == XML_ENTITY_DECL) {
                   4929:         xmlDumpEntityDecl(buf, (xmlEntityPtr) cur);
                   4930:        return;
                   4931:     }
1.23      daniel   4932:     if (cur->type == XML_TEXT_NODE) {
1.45      daniel   4933:        if (cur->content != NULL) {
1.61      daniel   4934:             xmlChar *buffer;
1.45      daniel   4935: 
1.70      daniel   4936: #ifndef XML_USE_BUFFER_CONTENT
1.46      daniel   4937:             buffer = xmlEncodeEntitiesReentrant(doc, cur->content);
1.70      daniel   4938: #else
                   4939:            buffer = xmlEncodeEntitiesReentrant(doc, 
                   4940:                                            xmlBufferContent(cur->content));
                   4941: #endif
1.45      daniel   4942:            if (buffer != NULL) {
                   4943:                xmlBufferWriteCHAR(buf, buffer);
1.57      daniel   4944:                xmlFree(buffer);
1.45      daniel   4945:            }
                   4946:        }
1.14      daniel   4947:        return;
                   4948:     }
1.52      daniel   4949:     if (cur->type == XML_PI_NODE) {
                   4950:        if (cur->content != NULL) {
                   4951:            xmlBufferWriteChar(buf, "<?");
                   4952:            xmlBufferWriteCHAR(buf, cur->name);
                   4953:            if (cur->content != NULL) {
                   4954:                xmlBufferWriteChar(buf, " ");
1.70      daniel   4955: #ifndef XML_USE_BUFFER_CONTENT
1.52      daniel   4956:                xmlBufferWriteCHAR(buf, cur->content);
1.70      daniel   4957: #else
                   4958:                xmlBufferWriteCHAR(buf, xmlBufferContent(cur->content));
                   4959: #endif
1.52      daniel   4960:            }
1.89      daniel   4961:            xmlBufferWriteChar(buf, "?>");
                   4962:        } else {
                   4963:            xmlBufferWriteChar(buf, "<?");
                   4964:            xmlBufferWriteCHAR(buf, cur->name);
1.64      daniel   4965:            xmlBufferWriteChar(buf, "?>");
1.52      daniel   4966:        }
                   4967:        return;
                   4968:     }
1.23      daniel   4969:     if (cur->type == XML_COMMENT_NODE) {
1.14      daniel   4970:        if (cur->content != NULL) {
1.38      daniel   4971:            xmlBufferWriteChar(buf, "<!--");
1.70      daniel   4972: #ifndef XML_USE_BUFFER_CONTENT
1.38      daniel   4973:            xmlBufferWriteCHAR(buf, cur->content);
1.70      daniel   4974: #else
                   4975:            xmlBufferWriteCHAR(buf, xmlBufferContent(cur->content));
                   4976: #endif
1.64      daniel   4977:            xmlBufferWriteChar(buf, "-->");
1.14      daniel   4978:        }
1.8       veillard 4979:        return;
                   4980:     }
1.23      daniel   4981:     if (cur->type == XML_ENTITY_REF_NODE) {
1.38      daniel   4982:         xmlBufferWriteChar(buf, "&");
                   4983:        xmlBufferWriteCHAR(buf, cur->name);
                   4984:         xmlBufferWriteChar(buf, ";");
1.50      daniel   4985:        return;
                   4986:     }
                   4987:     if (cur->type == XML_CDATA_SECTION_NODE) {
                   4988:         xmlBufferWriteChar(buf, "<![CDATA[");
                   4989:        if (cur->content != NULL)
1.70      daniel   4990: #ifndef XML_USE_BUFFER_CONTENT
1.50      daniel   4991:            xmlBufferWriteCHAR(buf, cur->content);
1.70      daniel   4992: #else
                   4993:            xmlBufferWriteCHAR(buf, xmlBufferContent(cur->content));
                   4994: #endif
1.50      daniel   4995:         xmlBufferWriteChar(buf, "]]>");
1.23      daniel   4996:        return;
                   4997:     }
1.8       veillard 4998: 
1.64      daniel   4999:     if (format == 1) {
1.91      daniel   5000:        tmp = cur->children;
1.64      daniel   5001:        while (tmp != NULL) {
                   5002:            if ((tmp->type == XML_TEXT_NODE) || 
                   5003:                (tmp->type == XML_ENTITY_REF_NODE)) {
                   5004:                format = 0;
                   5005:                break;
                   5006:            }
                   5007:            tmp = tmp->next;
                   5008:        }
                   5009:     }
1.38      daniel   5010:     xmlBufferWriteChar(buf, "<");
1.16      daniel   5011:     if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
1.38      daniel   5012:         xmlBufferWriteCHAR(buf, cur->ns->prefix);
                   5013:        xmlBufferWriteChar(buf, ":");
1.8       veillard 5014:     }
                   5015: 
1.38      daniel   5016:     xmlBufferWriteCHAR(buf, cur->name);
1.19      daniel   5017:     if (cur->nsDef)
1.38      daniel   5018:         xmlNsListDump(buf, cur->nsDef);
1.8       veillard 5019:     if (cur->properties != NULL)
1.38      daniel   5020:         xmlAttrListDump(buf, doc, cur->properties);
1.8       veillard 5021: 
1.90      daniel   5022:     if ((cur->content == NULL) && (cur->children == NULL) &&
1.87      daniel   5023:        (!xmlSaveNoEmptyTags)) {
1.64      daniel   5024:         xmlBufferWriteChar(buf, "/>");
1.1       veillard 5025:        return;
                   5026:     }
1.38      daniel   5027:     xmlBufferWriteChar(buf, ">");
1.46      daniel   5028:     if (cur->content != NULL) {
1.61      daniel   5029:        xmlChar *buffer;
1.46      daniel   5030: 
1.70      daniel   5031: #ifndef XML_USE_BUFFER_CONTENT
1.46      daniel   5032:        buffer = xmlEncodeEntitiesReentrant(doc, cur->content);
1.70      daniel   5033: #else
                   5034:        buffer = xmlEncodeEntitiesReentrant(doc, 
                   5035:                                            xmlBufferContent(cur->content));
                   5036: #endif
1.46      daniel   5037:        if (buffer != NULL) {
                   5038:            xmlBufferWriteCHAR(buf, buffer);
1.57      daniel   5039:            xmlFree(buffer);
1.46      daniel   5040:        }
                   5041:     }
1.90      daniel   5042:     if (cur->children != NULL) {
1.64      daniel   5043:        if (format) xmlBufferWriteChar(buf, "\n");
1.99      daniel   5044:        xmlNodeListDump(buf, doc, cur->children,
                   5045:                        (level >= 0?level+1:-1), format);
1.64      daniel   5046:        if ((xmlIndentTreeOutput) && (format))
                   5047:            for (i = 0;i < level;i++)
                   5048:                xmlBufferWriteChar(buf, "  ");
1.8       veillard 5049:     }
1.38      daniel   5050:     xmlBufferWriteChar(buf, "</");
1.16      daniel   5051:     if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
1.38      daniel   5052:         xmlBufferWriteCHAR(buf, cur->ns->prefix);
                   5053:        xmlBufferWriteChar(buf, ":");
1.1       veillard 5054:     }
1.8       veillard 5055: 
1.38      daniel   5056:     xmlBufferWriteCHAR(buf, cur->name);
1.64      daniel   5057:     xmlBufferWriteChar(buf, ">");
1.1       veillard 5058: }
                   5059: 
1.23      daniel   5060: /**
1.82      daniel   5061:  * xmlElemDump:
1.104     daniel   5062:  * @f:  the FILE * for the output
1.82      daniel   5063:  * @doc:  the document
                   5064:  * @cur:  the current node
                   5065:  *
                   5066:  * Dump an XML/HTML node, recursive behaviour,children are printed too.
                   5067:  */
                   5068: void
                   5069: xmlElemDump(FILE *f, xmlDocPtr doc, xmlNodePtr cur) {
                   5070:     xmlBufferPtr buf;
                   5071: 
                   5072:     if (cur == NULL) {
                   5073: #ifdef DEBUG_TREE
1.134     veillard 5074:         xmlGenericError(xmlGenericErrorContext,
                   5075:                "xmlElemDump : cur == NULL\n");
1.82      daniel   5076: #endif
                   5077:        return;
                   5078:     }
                   5079:     if (doc == NULL) {
                   5080: #ifdef DEBUG_TREE
1.134     veillard 5081:         xmlGenericError(xmlGenericErrorContext,
                   5082:                "xmlElemDump : doc == NULL\n");
1.82      daniel   5083: #endif
                   5084:     }
                   5085:     buf = xmlBufferCreate();
                   5086:     if (buf == NULL) return;
                   5087:     if ((doc != NULL) && 
                   5088:         (doc->type == XML_HTML_DOCUMENT_NODE)) {
1.101     daniel   5089: #ifdef LIBXML_HTML_ENABLED
1.82      daniel   5090:         htmlNodeDump(buf, doc, cur);
1.101     daniel   5091: #else  
1.134     veillard 5092:        xmlGenericError(xmlGenericErrorContext,
                   5093:                "HTML support not compiled in\n");
1.101     daniel   5094: #endif /* LIBXML_HTML_ENABLED */
1.82      daniel   5095:     } else
                   5096:         xmlNodeDump(buf, doc, cur, 0, 1);
                   5097:     xmlBufferDump(f, buf);
                   5098:     xmlBufferFree(buf);
                   5099: }
                   5100: 
1.106     daniel   5101: /************************************************************************
                   5102:  *                                                                     *
                   5103:  *             Dumping XML tree content to an I/O output buffer        *
                   5104:  *                                                                     *
                   5105:  ************************************************************************/
                   5106: 
1.125     veillard 5107: void
1.106     daniel   5108: xmlNodeDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur,
1.108     daniel   5109:                   int level, int format, const char *encoding);
1.106     daniel   5110: static void
                   5111: xmlNodeListDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur,
1.108     daniel   5112:                   int level, int format, const char *encoding);
1.106     daniel   5113: /**
                   5114:  * xmlNsDumpOutput:
                   5115:  * @buf:  the XML buffer output
                   5116:  * @cur:  a namespace
                   5117:  *
                   5118:  * Dump a local Namespace definition.
                   5119:  * Should be called in the context of attributes dumps.
                   5120:  */
                   5121: static void
                   5122: xmlNsDumpOutput(xmlOutputBufferPtr buf, xmlNsPtr cur) {
                   5123:     if (cur == NULL) {
                   5124: #ifdef DEBUG_TREE
1.134     veillard 5125:         xmlGenericError(xmlGenericErrorContext,
                   5126:                "xmlNsDump : Ns == NULL\n");
1.106     daniel   5127: #endif
                   5128:        return;
                   5129:     }
1.120     veillard 5130:     if ((cur->type == XML_LOCAL_NAMESPACE) && (cur->href != NULL)) {
1.106     daniel   5131:         /* Within the context of an element attributes */
                   5132:        if (cur->prefix != NULL) {
                   5133:            xmlOutputBufferWriteString(buf, " xmlns:");
                   5134:            xmlOutputBufferWriteString(buf, (const char *)cur->prefix);
                   5135:        } else
                   5136:            xmlOutputBufferWriteString(buf, " xmlns");
                   5137:        xmlOutputBufferWriteString(buf, "=");
                   5138:        xmlBufferWriteQuotedString(buf->buffer, cur->href);
                   5139:     }
                   5140: }
                   5141: 
                   5142: /**
                   5143:  * xmlNsListDumpOutput:
                   5144:  * @buf:  the XML buffer output
                   5145:  * @cur:  the first namespace
                   5146:  *
                   5147:  * Dump a list of local Namespace definitions.
                   5148:  * Should be called in the context of attributes dumps.
                   5149:  */
                   5150: static void
                   5151: xmlNsListDumpOutput(xmlOutputBufferPtr buf, xmlNsPtr cur) {
                   5152:     while (cur != NULL) {
                   5153:         xmlNsDumpOutput(buf, cur);
                   5154:        cur = cur->next;
                   5155:     }
                   5156: }
                   5157: 
                   5158: /**
                   5159:  * xmlDtdDumpOutput:
                   5160:  * @buf:  the XML buffer output
                   5161:  * @doc:  the document
1.108     daniel   5162:  * @encoding:  an optional encoding string
1.106     daniel   5163:  * 
                   5164:  * Dump the XML document DTD, if any.
                   5165:  */
                   5166: static void
1.108     daniel   5167: xmlDtdDumpOutput(xmlOutputBufferPtr buf, xmlDtdPtr dtd, const char *encoding) {
1.106     daniel   5168:     if (dtd == NULL) {
                   5169: #ifdef DEBUG_TREE
1.134     veillard 5170:         xmlGenericError(xmlGenericErrorContext,
                   5171:                "xmlDtdDump : no internal subset\n");
1.106     daniel   5172: #endif
                   5173:        return;
                   5174:     }
                   5175:     xmlOutputBufferWriteString(buf, "<!DOCTYPE ");
                   5176:     xmlOutputBufferWriteString(buf, (const char *)dtd->name);
                   5177:     if (dtd->ExternalID != NULL) {
                   5178:        xmlOutputBufferWriteString(buf, " PUBLIC ");
                   5179:        xmlBufferWriteQuotedString(buf->buffer, dtd->ExternalID);
                   5180:        xmlOutputBufferWriteString(buf, " ");
                   5181:        xmlBufferWriteQuotedString(buf->buffer, dtd->SystemID);
                   5182:     }  else if (dtd->SystemID != NULL) {
                   5183:        xmlOutputBufferWriteString(buf, " SYSTEM ");
                   5184:        xmlBufferWriteQuotedString(buf->buffer, dtd->SystemID);
                   5185:     }
                   5186:     if ((dtd->entities == NULL) && (dtd->elements == NULL) &&
                   5187:         (dtd->attributes == NULL) && (dtd->notations == NULL)) {
                   5188:        xmlOutputBufferWriteString(buf, ">");
                   5189:        return;
                   5190:     }
                   5191:     xmlOutputBufferWriteString(buf, " [\n");
1.108     daniel   5192:     xmlNodeListDumpOutput(buf, dtd->doc, dtd->children, -1, 0, encoding);
1.106     daniel   5193:     xmlOutputBufferWriteString(buf, "]>");
                   5194: }
                   5195: 
                   5196: /**
                   5197:  * xmlAttrDumpOutput:
                   5198:  * @buf:  the XML buffer output
                   5199:  * @doc:  the document
                   5200:  * @cur:  the attribute pointer
1.108     daniel   5201:  * @encoding:  an optional encoding string
1.106     daniel   5202:  *
                   5203:  * Dump an XML attribute
                   5204:  */
                   5205: static void
1.108     daniel   5206: xmlAttrDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur,
                   5207:                  const char *encoding) {
1.106     daniel   5208:     xmlChar *value;
                   5209: 
                   5210:     if (cur == NULL) {
                   5211: #ifdef DEBUG_TREE
1.134     veillard 5212:         xmlGenericError(xmlGenericErrorContext,
                   5213:                "xmlAttrDump : property == NULL\n");
1.106     daniel   5214: #endif
                   5215:        return;
                   5216:     }
                   5217:     xmlOutputBufferWriteString(buf, " ");
                   5218:     if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
                   5219:         xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
                   5220:        xmlOutputBufferWriteString(buf, ":");
                   5221:     }
                   5222:     xmlOutputBufferWriteString(buf, (const char *)cur->name);
                   5223:     value = xmlNodeListGetString(doc, cur->children, 0);
                   5224:     if (value) {
                   5225:        xmlOutputBufferWriteString(buf, "=");
                   5226:        xmlBufferWriteQuotedString(buf->buffer, value);
                   5227:        xmlFree(value);
                   5228:     } else  {
                   5229:        xmlOutputBufferWriteString(buf, "=\"\"");
                   5230:     }
                   5231: }
                   5232: 
                   5233: /**
                   5234:  * xmlAttrListDumpOutput:
                   5235:  * @buf:  the XML buffer output
                   5236:  * @doc:  the document
                   5237:  * @cur:  the first attribute pointer
1.108     daniel   5238:  * @encoding:  an optional encoding string
1.106     daniel   5239:  *
                   5240:  * Dump a list of XML attributes
                   5241:  */
                   5242: static void
1.108     daniel   5243: xmlAttrListDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc,
                   5244:                      xmlAttrPtr cur, const char *encoding) {
1.106     daniel   5245:     if (cur == NULL) {
                   5246: #ifdef DEBUG_TREE
1.134     veillard 5247:         xmlGenericError(xmlGenericErrorContext,
                   5248:                "xmlAttrListDump : property == NULL\n");
1.106     daniel   5249: #endif
                   5250:        return;
                   5251:     }
                   5252:     while (cur != NULL) {
1.108     daniel   5253:         xmlAttrDumpOutput(buf, doc, cur, encoding);
1.106     daniel   5254:        cur = cur->next;
                   5255:     }
                   5256: }
                   5257: 
                   5258: 
                   5259: 
                   5260: /**
                   5261:  * xmlNodeListDumpOutput:
                   5262:  * @buf:  the XML buffer output
                   5263:  * @doc:  the document
                   5264:  * @cur:  the first node
                   5265:  * @level: the imbrication level for indenting
                   5266:  * @format: is formatting allowed
1.108     daniel   5267:  * @encoding:  an optional encoding string
1.106     daniel   5268:  *
                   5269:  * Dump an XML node list, recursive behaviour,children are printed too.
                   5270:  */
                   5271: static void
                   5272: xmlNodeListDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc,
1.108     daniel   5273:                 xmlNodePtr cur, int level, int format, const char *encoding) {
1.106     daniel   5274:     int i;
                   5275: 
                   5276:     if (cur == NULL) {
                   5277: #ifdef DEBUG_TREE
1.134     veillard 5278:         xmlGenericError(xmlGenericErrorContext,
                   5279:                "xmlNodeListDump : node == NULL\n");
1.106     daniel   5280: #endif
                   5281:        return;
                   5282:     }
                   5283:     while (cur != NULL) {
                   5284:        if ((format) && (xmlIndentTreeOutput) &&
                   5285:            (cur->type == XML_ELEMENT_NODE))
                   5286:            for (i = 0;i < level;i++)
                   5287:                xmlOutputBufferWriteString(buf, "  ");
1.108     daniel   5288:         xmlNodeDumpOutput(buf, doc, cur, level, format, encoding);
1.106     daniel   5289:        if (format) {
                   5290:            xmlOutputBufferWriteString(buf, "\n");
                   5291:        }
                   5292:        cur = cur->next;
                   5293:     }
                   5294: }
                   5295: 
                   5296: /**
                   5297:  * xmlNodeDumpOutput:
                   5298:  * @buf:  the XML buffer output
                   5299:  * @doc:  the document
                   5300:  * @cur:  the current node
                   5301:  * @level: the imbrication level for indenting
                   5302:  * @format: is formatting allowed
1.108     daniel   5303:  * @encoding:  an optional encoding string
1.106     daniel   5304:  *
                   5305:  * Dump an XML node, recursive behaviour,children are printed too.
                   5306:  */
1.125     veillard 5307: void
1.106     daniel   5308: xmlNodeDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur,
1.108     daniel   5309:             int level, int format, const char *encoding) {
1.106     daniel   5310:     int i;
                   5311:     xmlNodePtr tmp;
                   5312: 
                   5313:     if (cur == NULL) {
                   5314: #ifdef DEBUG_TREE
1.134     veillard 5315:         xmlGenericError(xmlGenericErrorContext,
                   5316:                "xmlNodeDump : node == NULL\n");
1.106     daniel   5317: #endif
                   5318:        return;
                   5319:     }
1.141     veillard 5320:     if (cur->type == XML_XINCLUDE_START)
                   5321:        return;
                   5322:     if (cur->type == XML_XINCLUDE_END)
                   5323:        return;
1.106     daniel   5324:     if (cur->type == XML_DTD_NODE) {
1.108     daniel   5325:         xmlDtdDumpOutput(buf, (xmlDtdPtr) cur, encoding);
1.106     daniel   5326:        return;
                   5327:     }
                   5328:     if (cur->type == XML_ELEMENT_DECL) {
                   5329:         xmlDumpElementDecl(buf->buffer, (xmlElementPtr) cur);
                   5330:        return;
                   5331:     }
                   5332:     if (cur->type == XML_ATTRIBUTE_DECL) {
                   5333:         xmlDumpAttributeDecl(buf->buffer, (xmlAttributePtr) cur);
                   5334:        return;
                   5335:     }
                   5336:     if (cur->type == XML_ENTITY_DECL) {
                   5337:         xmlDumpEntityDecl(buf->buffer, (xmlEntityPtr) cur);
                   5338:        return;
                   5339:     }
                   5340:     if (cur->type == XML_TEXT_NODE) {
                   5341:        if (cur->content != NULL) {
                   5342:             xmlChar *buffer;
                   5343: 
                   5344: #ifndef XML_USE_BUFFER_CONTENT
1.108     daniel   5345:            if (encoding == NULL)
                   5346:                buffer = xmlEncodeEntitiesReentrant(doc, cur->content);
                   5347:            else
                   5348:                buffer = xmlEncodeSpecialChars(doc, cur->content);
1.106     daniel   5349: #else
1.108     daniel   5350:            if (encoding == NULL)
                   5351:                buffer = xmlEncodeEntitiesReentrant(doc, 
                   5352:                                    xmlBufferContent(cur->content));
                   5353:            else
                   5354:                buffer = xmlEncodeSpecialChars(doc, 
                   5355:                                    xmlBufferContent(cur->content));
1.106     daniel   5356: #endif
                   5357:            if (buffer != NULL) {
                   5358:                xmlOutputBufferWriteString(buf, (const char *)buffer);
                   5359:                xmlFree(buffer);
                   5360:            }
                   5361:        }
                   5362:        return;
                   5363:     }
                   5364:     if (cur->type == XML_PI_NODE) {
                   5365:        if (cur->content != NULL) {
                   5366:            xmlOutputBufferWriteString(buf, "<?");
                   5367:            xmlOutputBufferWriteString(buf, (const char *)cur->name);
                   5368:            if (cur->content != NULL) {
                   5369:                xmlOutputBufferWriteString(buf, " ");
                   5370: #ifndef XML_USE_BUFFER_CONTENT
                   5371:                xmlOutputBufferWriteString(buf, (const char *)cur->content);
                   5372: #else
                   5373:                xmlOutputBufferWriteString(buf, (const char *)xmlBufferContent(cur->content));
                   5374: #endif
                   5375:            }
                   5376:            xmlOutputBufferWriteString(buf, "?>");
                   5377:        } else {
                   5378:            xmlOutputBufferWriteString(buf, "<?");
                   5379:            xmlOutputBufferWriteString(buf, (const char *)cur->name);
                   5380:            xmlOutputBufferWriteString(buf, "?>");
                   5381:        }
                   5382:        return;
                   5383:     }
                   5384:     if (cur->type == XML_COMMENT_NODE) {
                   5385:        if (cur->content != NULL) {
                   5386:            xmlOutputBufferWriteString(buf, "<!--");
                   5387: #ifndef XML_USE_BUFFER_CONTENT
                   5388:            xmlOutputBufferWriteString(buf, (const char *)cur->content);
                   5389: #else
                   5390:            xmlOutputBufferWriteString(buf, (const char *)xmlBufferContent(cur->content));
                   5391: #endif
                   5392:            xmlOutputBufferWriteString(buf, "-->");
                   5393:        }
                   5394:        return;
                   5395:     }
                   5396:     if (cur->type == XML_ENTITY_REF_NODE) {
                   5397:         xmlOutputBufferWriteString(buf, "&");
                   5398:        xmlOutputBufferWriteString(buf, (const char *)cur->name);
                   5399:         xmlOutputBufferWriteString(buf, ";");
                   5400:        return;
                   5401:     }
                   5402:     if (cur->type == XML_CDATA_SECTION_NODE) {
                   5403:         xmlOutputBufferWriteString(buf, "<![CDATA[");
                   5404:        if (cur->content != NULL)
                   5405: #ifndef XML_USE_BUFFER_CONTENT
                   5406:            xmlOutputBufferWriteString(buf, (const char *)cur->content);
                   5407: #else
                   5408:            xmlOutputBufferWriteString(buf, (const char *)xmlBufferContent(cur->content));
                   5409: #endif
                   5410:         xmlOutputBufferWriteString(buf, "]]>");
                   5411:        return;
                   5412:     }
                   5413: 
                   5414:     if (format == 1) {
                   5415:        tmp = cur->children;
                   5416:        while (tmp != NULL) {
                   5417:            if ((tmp->type == XML_TEXT_NODE) || 
                   5418:                (tmp->type == XML_ENTITY_REF_NODE)) {
                   5419:                format = 0;
                   5420:                break;
                   5421:            }
                   5422:            tmp = tmp->next;
                   5423:        }
                   5424:     }
                   5425:     xmlOutputBufferWriteString(buf, "<");
                   5426:     if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
                   5427:         xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
                   5428:        xmlOutputBufferWriteString(buf, ":");
                   5429:     }
                   5430: 
                   5431:     xmlOutputBufferWriteString(buf, (const char *)cur->name);
                   5432:     if (cur->nsDef)
                   5433:         xmlNsListDumpOutput(buf, cur->nsDef);
                   5434:     if (cur->properties != NULL)
1.108     daniel   5435:         xmlAttrListDumpOutput(buf, doc, cur->properties, encoding);
1.106     daniel   5436: 
                   5437:     if ((cur->content == NULL) && (cur->children == NULL) &&
                   5438:        (!xmlSaveNoEmptyTags)) {
                   5439:         xmlOutputBufferWriteString(buf, "/>");
                   5440:        return;
                   5441:     }
                   5442:     xmlOutputBufferWriteString(buf, ">");
                   5443:     if (cur->content != NULL) {
                   5444:        xmlChar *buffer;
                   5445: 
                   5446: #ifndef XML_USE_BUFFER_CONTENT
1.108     daniel   5447:        if (encoding == NULL)
                   5448:            buffer = xmlEncodeEntitiesReentrant(doc, cur->content);
                   5449:        else
                   5450:            buffer = xmlEncodeSpecialChars(doc, cur->content);
1.106     daniel   5451: #else
1.108     daniel   5452:        if (encoding == NULL)
                   5453:            buffer = xmlEncodeEntitiesReentrant(doc, 
                   5454:                                xmlBufferContent(cur->content));
                   5455:        else
                   5456:            buffer = xmlEncodeSpecialChars(doc, 
                   5457:                                xmlBufferContent(cur->content));
1.106     daniel   5458: #endif
                   5459:        if (buffer != NULL) {
                   5460:            xmlOutputBufferWriteString(buf, (const char *)buffer);
                   5461:            xmlFree(buffer);
                   5462:        }
                   5463:     }
                   5464:     if (cur->children != NULL) {
                   5465:        if (format) xmlOutputBufferWriteString(buf, "\n");
                   5466:        xmlNodeListDumpOutput(buf, doc, cur->children,
1.108     daniel   5467:                        (level >= 0?level+1:-1), format, encoding);
1.106     daniel   5468:        if ((xmlIndentTreeOutput) && (format))
                   5469:            for (i = 0;i < level;i++)
                   5470:                xmlOutputBufferWriteString(buf, "  ");
                   5471:     }
                   5472:     xmlOutputBufferWriteString(buf, "</");
                   5473:     if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
                   5474:         xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
                   5475:        xmlOutputBufferWriteString(buf, ":");
                   5476:     }
                   5477: 
                   5478:     xmlOutputBufferWriteString(buf, (const char *)cur->name);
                   5479:     xmlOutputBufferWriteString(buf, ">");
                   5480: }
                   5481: 
                   5482: /**
                   5483:  * xmlDocContentDumpOutput:
                   5484:  * @buf:  the XML buffer output
                   5485:  * @cur:  the document
1.107     daniel   5486:  * @encoding:  an optional encoding string
1.146     veillard 5487:  * @format:  should formatting spaces been added
1.106     daniel   5488:  *
                   5489:  * Dump an XML document.
                   5490:  */
                   5491: static void
1.107     daniel   5492: xmlDocContentDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr cur,
1.146     veillard 5493:                        const char *encoding, int format) {
1.106     daniel   5494:     xmlOutputBufferWriteString(buf, "<?xml version=");
                   5495:     if (cur->version != NULL) 
                   5496:        xmlBufferWriteQuotedString(buf->buffer, cur->version);
                   5497:     else
                   5498:        xmlOutputBufferWriteString(buf, "\"1.0\"");
1.109     daniel   5499:     if (encoding == NULL) {
                   5500:        if (cur->encoding != NULL)
                   5501:            encoding = (const char *) cur->encoding;
                   5502:        else if (cur->charset != XML_CHAR_ENCODING_UTF8)
1.112     veillard 5503:            encoding = xmlGetCharEncodingName((xmlCharEncoding) cur->charset);
1.109     daniel   5504:     }
1.107     daniel   5505:     if (encoding != NULL) {
1.106     daniel   5506:         xmlOutputBufferWriteString(buf, " encoding=");
1.107     daniel   5507:        xmlBufferWriteQuotedString(buf->buffer, (xmlChar *) encoding);
1.106     daniel   5508:     }
                   5509:     switch (cur->standalone) {
                   5510:         case 0:
                   5511:            xmlOutputBufferWriteString(buf, " standalone=\"no\"");
                   5512:            break;
                   5513:         case 1:
                   5514:            xmlOutputBufferWriteString(buf, " standalone=\"yes\"");
                   5515:            break;
                   5516:     }
                   5517:     xmlOutputBufferWriteString(buf, "?>\n");
                   5518:     if (cur->children != NULL) {
                   5519:         xmlNodePtr child = cur->children;
                   5520: 
                   5521:        while (child != NULL) {
1.146     veillard 5522:            xmlNodeDumpOutput(buf, cur, child, 0, format, encoding);
1.106     daniel   5523:            xmlOutputBufferWriteString(buf, "\n");
                   5524:            child = child->next;
                   5525:        }
                   5526:     }
                   5527: }
                   5528: 
                   5529: /************************************************************************
                   5530:  *                                                                     *
                   5531:  *             Saving functions front-ends                             *
                   5532:  *                                                                     *
                   5533:  ************************************************************************/
                   5534: 
1.23      daniel   5535: /**
1.144     veillard 5536:  * xmlDocDumpMemoryEnc:
                   5537:  * @out_doc:  Document to generate XML text from
                   5538:  * @doc_txt_ptr:  Memory pointer for allocated XML text
                   5539:  * @doc_txt_len:  Length of the generated XML text
                   5540:  * @txt_encoding:  Character encoding to use when generating XML text
1.146     veillard 5541:  * @format:  should formatting spaces been added
1.144     veillard 5542:  *
                   5543:  * Dump the current DOM tree into memory using the character encoding specified
                   5544:  * by the caller.  Note it is up to the caller of this function to free the
                   5545:  * allocated memory.
                   5546:  */
                   5547: 
                   5548: void
1.146     veillard 5549: xmlDocDumpFormatMemoryEnc(xmlDocPtr out_doc, xmlChar **doc_txt_ptr,
                   5550:                int * doc_txt_len, const char * txt_encoding, int format) {
1.144     veillard 5551:     int                         dummy = 0;
                   5552: 
                   5553:     xmlCharEncoding             doc_charset;
                   5554:     xmlOutputBufferPtr          out_buff = NULL;
                   5555:     xmlCharEncodingHandlerPtr   conv_hdlr = NULL;
                   5556: 
                   5557:     if (doc_txt_len == NULL) {
                   5558:         doc_txt_len = &dummy;   /*  Continue, caller just won't get length */
                   5559:     }
                   5560: 
                   5561:     if (doc_txt_ptr == NULL) {
                   5562:         *doc_txt_len = 0;
                   5563:         xmlGenericError(xmlGenericErrorContext,
1.146     veillard 5564:                     "xmlDocDumpFormatMemoryEnc:  Null return buffer pointer.");
1.144     veillard 5565:         return;
                   5566:     }
                   5567: 
                   5568:     *doc_txt_ptr = NULL;
                   5569:     *doc_txt_len = 0;
                   5570: 
                   5571:     if (out_doc == NULL) {
                   5572:         /*  No document, no output  */
                   5573:         xmlGenericError(xmlGenericErrorContext,
1.146     veillard 5574:                 "xmlDocDumpFormatMemoryEnc:  Null DOM tree document pointer.\n");
1.144     veillard 5575:         return;
                   5576:     }
                   5577: 
                   5578:     /*
                   5579:      *  Validate the encoding value, if provided.
                   5580:      *  This logic is copied from xmlSaveFileEnc.
                   5581:      */
                   5582: 
1.147     veillard 5583:     if (txt_encoding == NULL)
                   5584:        txt_encoding = (const char *) out_doc->encoding;
1.144     veillard 5585:     if (txt_encoding != NULL) {
                   5586:         doc_charset = xmlParseCharEncoding(txt_encoding);
                   5587: 
                   5588:         if (out_doc->charset != XML_CHAR_ENCODING_UTF8) {
                   5589:             xmlGenericError(xmlGenericErrorContext,
1.146     veillard 5590:                     "xmlDocDumpFormatMemoryEnc: Source document not in UTF8\n");
1.144     veillard 5591:             return;
                   5592: 
                   5593:         } else if (doc_charset != XML_CHAR_ENCODING_UTF8) {
                   5594:             conv_hdlr = xmlFindCharEncodingHandler(txt_encoding);
                   5595:             if ( conv_hdlr == NULL ) {
                   5596:                 xmlGenericError(xmlGenericErrorContext,
                   5597:                                 "%s:  %s %s '%s'\n",
1.146     veillard 5598:                                 "xmlDocDumpFormatMemoryEnc",
1.144     veillard 5599:                                 "Failed to identify encoding handler for",
                   5600:                                 "character set",
                   5601:                                 txt_encoding);
                   5602:                 return;
                   5603:             }
                   5604:         }
                   5605:     }
                   5606: 
                   5607:     if ((out_buff = xmlAllocOutputBuffer(conv_hdlr)) == NULL ) {
                   5608:         xmlGenericError(xmlGenericErrorContext,
1.146     veillard 5609:            "xmlDocDumpFormatMemoryEnc: Failed to allocate output buffer.\n");
1.144     veillard 5610:         return;
                   5611:     }
                   5612: 
1.146     veillard 5613:     xmlDocContentDumpOutput(out_buff, out_doc, txt_encoding, 1);
1.147     veillard 5614:     xmlOutputBufferFlush(out_buff);
                   5615:     if (out_buff->conv != NULL) {
                   5616:        *doc_txt_len = out_buff->conv->use;
                   5617:        *doc_txt_ptr = xmlStrndup(out_buff->conv->content, *doc_txt_len);
                   5618:     } else {
                   5619:        *doc_txt_len = out_buff->buffer->use;
                   5620:        *doc_txt_ptr = xmlStrndup(out_buff->buffer->content, *doc_txt_len);
                   5621:     }
1.144     veillard 5622:     (void)xmlOutputBufferClose(out_buff);
                   5623: 
                   5624:     if ((*doc_txt_ptr == NULL) && (*doc_txt_len > 0)) {
                   5625:         *doc_txt_len = 0;
                   5626:         xmlGenericError(xmlGenericErrorContext,
1.146     veillard 5627:                 "xmlDocDumpFormatMemoryEnc:  %s\n",
1.144     veillard 5628:                 "Failed to allocate memory for document text representation.");
                   5629:     }
                   5630: 
                   5631:     return;
1.147     veillard 5632: }
                   5633: 
                   5634: /**
                   5635:  * xmlDocDumpMemory:
                   5636:  * @cur:  the document
                   5637:  * @mem:  OUT: the memory pointer
                   5638:  * @size:  OUT: the memory lenght
                   5639:  *
                   5640:  * Dump an XML document in memory and return the xmlChar * and it's size.
                   5641:  * It's up to the caller to free the memory.
                   5642:  */
                   5643: void
                   5644: xmlDocDumpMemory(xmlDocPtr cur, xmlChar**mem, int *size) {
                   5645:     xmlDocDumpFormatMemoryEnc(cur, mem, size, NULL, 0);
                   5646: }
                   5647: 
                   5648: /**
                   5649:  * xmlDocDumpFormatMemory:
                   5650:  * @cur:  the document
                   5651:  * @mem:  OUT: the memory pointer
                   5652:  * @size:  OUT: the memory lenght
                   5653:  * @format:  should formatting spaces been added
                   5654:  *
                   5655:  *
                   5656:  * Dump an XML document in memory and return the xmlChar * and it's size.
                   5657:  * It's up to the caller to free the memory.
                   5658:  */
                   5659: void
                   5660: xmlDocDumpFormatMemory(xmlDocPtr cur, xmlChar**mem, int *size, int format) {
                   5661:     xmlDocDumpFormatMemoryEnc(cur, mem, size, NULL, format);
1.144     veillard 5662: }
                   5663: 
                   5664: /**
1.146     veillard 5665:  * xmlDocDumpMemoryEnc:
                   5666:  * @out_doc:  Document to generate XML text from
                   5667:  * @doc_txt_ptr:  Memory pointer for allocated XML text
                   5668:  * @doc_txt_len:  Length of the generated XML text
                   5669:  * @txt_encoding:  Character encoding to use when generating XML text
                   5670:  *
                   5671:  * Dump the current DOM tree into memory using the character encoding specified
                   5672:  * by the caller.  Note it is up to the caller of this function to free the
                   5673:  * allocated memory.
                   5674:  */
                   5675: 
                   5676: void
                   5677: xmlDocDumpMemoryEnc(xmlDocPtr out_doc, xmlChar **doc_txt_ptr,
                   5678:                    int * doc_txt_len, const char * txt_encoding) {
                   5679:     xmlDocDumpFormatMemoryEnc(out_doc, doc_txt_ptr, doc_txt_len,
                   5680:                              txt_encoding, 1);
                   5681: }
                   5682: 
                   5683: /**
1.23      daniel   5684:  * xmlGetDocCompressMode:
                   5685:  * @doc:  the document
                   5686:  *
                   5687:  * get the compression ratio for a document, ZLIB based
1.36      daniel   5688:  * Returns 0 (uncompressed) to 9 (max compression)
1.23      daniel   5689:  */
1.28      daniel   5690: int
1.82      daniel   5691: xmlGetDocCompressMode (xmlDocPtr doc) {
1.23      daniel   5692:     if (doc == NULL) return(-1);
                   5693:     return(doc->compression);
                   5694: }
                   5695: 
                   5696: /**
                   5697:  * xmlSetDocCompressMode:
                   5698:  * @doc:  the document
                   5699:  * @mode:  the compression ratio
                   5700:  *
                   5701:  * set the compression ratio for a document, ZLIB based
                   5702:  * Correct values: 0 (uncompressed) to 9 (max compression)
                   5703:  */
1.28      daniel   5704: void
                   5705: xmlSetDocCompressMode (xmlDocPtr doc, int mode) {
1.23      daniel   5706:     if (doc == NULL) return;
                   5707:     if (mode < 0) doc->compression = 0;
                   5708:     else if (mode > 9) doc->compression = 9;
                   5709:     else doc->compression = mode;
                   5710: }
                   5711: 
                   5712: /**
                   5713:  * xmlGetCompressMode:
                   5714:  *
                   5715:  * get the default compression mode used, ZLIB based.
1.36      daniel   5716:  * Returns 0 (uncompressed) to 9 (max compression)
1.23      daniel   5717:  */
1.28      daniel   5718: int
                   5719:  xmlGetCompressMode(void) {
1.23      daniel   5720:     return(xmlCompressMode);
                   5721: }
                   5722: 
                   5723: /**
                   5724:  * xmlSetCompressMode:
                   5725:  * @mode:  the compression ratio
                   5726:  *
                   5727:  * set the default compression mode used, ZLIB based
                   5728:  * Correct values: 0 (uncompressed) to 9 (max compression)
1.1       veillard 5729:  */
1.28      daniel   5730: void
                   5731: xmlSetCompressMode(int mode) {
1.23      daniel   5732:     if (mode < 0) xmlCompressMode = 0;
                   5733:     else if (mode > 9) xmlCompressMode = 9;
                   5734:     else xmlCompressMode = mode;
                   5735: }
1.1       veillard 5736: 
1.106     daniel   5737: /**
                   5738:  * xmlDocDump:
                   5739:  * @f:  the FILE*
                   5740:  * @cur:  the document
                   5741:  *
                   5742:  * Dump an XML document to an open FILE.
                   5743:  *
1.111     veillard 5744:  * returns: the number of byte written or -1 in case of failure.
1.106     daniel   5745:  */
                   5746: int
                   5747: xmlDocDump(FILE *f, xmlDocPtr cur) {
                   5748:     xmlOutputBufferPtr buf;
1.114     veillard 5749:     const char * encoding;
                   5750:     xmlCharEncodingHandlerPtr handler = NULL;
1.106     daniel   5751:     int ret;
                   5752: 
                   5753:     if (cur == NULL) {
                   5754: #ifdef DEBUG_TREE
1.134     veillard 5755:         xmlGenericError(xmlGenericErrorContext,
                   5756:                "xmlDocDump : document == NULL\n");
1.106     daniel   5757: #endif
                   5758:        return(-1);
                   5759:     }
1.114     veillard 5760:     encoding = (const char *) cur->encoding;
1.106     daniel   5761: 
1.114     veillard 5762:     if (encoding != NULL) {
                   5763:        xmlCharEncoding enc;
1.106     daniel   5764: 
1.114     veillard 5765:        enc = xmlParseCharEncoding(encoding);
1.106     daniel   5766: 
1.114     veillard 5767:        if (cur->charset != XML_CHAR_ENCODING_UTF8) {
1.134     veillard 5768:            xmlGenericError(xmlGenericErrorContext,
                   5769:                    "xmlDocDump: document not in UTF8\n");
1.114     veillard 5770:            return(-1);
                   5771:        }
1.115     veillard 5772:        if (enc != XML_CHAR_ENCODING_UTF8) {
                   5773:            handler = xmlFindCharEncodingHandler(encoding);
                   5774:            if (handler == NULL) {
                   5775:                xmlFree((char *) cur->encoding);
                   5776:                cur->encoding = NULL;
                   5777:            }
1.114     veillard 5778:        }
                   5779:     }
                   5780:     buf = xmlOutputBufferCreateFile(f, handler);
                   5781:     if (buf == NULL) return(-1);
1.146     veillard 5782:     xmlDocContentDumpOutput(buf, cur, NULL, 1);
1.106     daniel   5783: 
                   5784:     ret = xmlOutputBufferClose(buf);
                   5785:     return(ret);
                   5786: }
1.1       veillard 5787: 
1.106     daniel   5788: /**
                   5789:  * xmlSaveFileTo:
                   5790:  * @buf:  an output I/O buffer
                   5791:  * @cur:  the document
1.107     daniel   5792:  * @encoding:  the encoding if any assuming the i/O layer handles the trancoding
1.106     daniel   5793:  *
                   5794:  * Dump an XML document to an I/O buffer.
                   5795:  *
1.111     veillard 5796:  * returns: the number of byte written or -1 in case of failure.
1.106     daniel   5797:  */
                   5798: int
1.107     daniel   5799: xmlSaveFileTo(xmlOutputBuffer *buf, xmlDocPtr cur, const char *encoding) {
1.106     daniel   5800:     int ret;
                   5801: 
                   5802:     if (buf == NULL) return(0);
1.146     veillard 5803:     xmlDocContentDumpOutput(buf, cur, encoding, 1);
1.106     daniel   5804:     ret = xmlOutputBufferClose(buf);
                   5805:     return(ret);
                   5806: }
                   5807: 
                   5808: /**
                   5809:  * xmlSaveFileEnc:
                   5810:  * @filename:  the filename (or URL)
                   5811:  * @cur:  the document
                   5812:  * @encoding:  the name of an encoding (or NULL)
                   5813:  *
                   5814:  * Dump an XML document, converting it to the given encoding
                   5815:  *
1.111     veillard 5816:  * returns: the number of byte written or -1 in case of failure.
1.106     daniel   5817:  */
                   5818: int
                   5819: xmlSaveFileEnc(const char *filename, xmlDocPtr cur, const char *encoding) {
                   5820:     xmlOutputBufferPtr buf;
                   5821:     xmlCharEncodingHandlerPtr handler = NULL;
                   5822:     int ret;
                   5823: 
                   5824:     if (encoding != NULL) {
1.110     daniel   5825:        xmlCharEncoding enc;
                   5826: 
                   5827:        enc = xmlParseCharEncoding(encoding);
1.114     veillard 5828:        if (cur->charset != XML_CHAR_ENCODING_UTF8) {
1.134     veillard 5829:            xmlGenericError(xmlGenericErrorContext,
                   5830:                    "xmlSaveFileEnc: document not in UTF8\n");
1.114     veillard 5831:            return(-1);
                   5832:        }
1.115     veillard 5833:        if (enc != XML_CHAR_ENCODING_UTF8) {
                   5834:            handler = xmlFindCharEncodingHandler(encoding);
                   5835:            if (handler == NULL) {
                   5836:                return(-1);
                   5837:            }
1.110     daniel   5838:        }
1.106     daniel   5839:     }
                   5840: 
                   5841:     /* 
                   5842:      * save the content to a temp buffer.
                   5843:      */
                   5844:     buf = xmlOutputBufferCreateFilename(filename, handler, 0);
                   5845:     if (buf == NULL) return(0);
                   5846: 
1.146     veillard 5847:     xmlDocContentDumpOutput(buf, cur, encoding, 1);
1.106     daniel   5848: 
                   5849:     ret = xmlOutputBufferClose(buf);
                   5850:     return(ret);
                   5851: }
1.114     veillard 5852: 
                   5853: /**
                   5854:  * xmlSaveFile:
                   5855:  * @filename:  the filename (or URL)
                   5856:  * @cur:  the document
                   5857:  *
                   5858:  * Dump an XML document to a file. Will use compression if
                   5859:  * compiled in and enabled. If @filename is "-" the stdout file is
                   5860:  * used.
                   5861:  * returns: the number of byte written or -1 in case of failure.
                   5862:  */
                   5863: int
                   5864: xmlSaveFile(const char *filename, xmlDocPtr cur) {
                   5865:     xmlOutputBufferPtr buf;
                   5866:     const char *encoding;
                   5867:     xmlCharEncodingHandlerPtr handler = NULL;
                   5868:     int ret;
                   5869: 
                   5870:     if (cur == NULL)
                   5871:        return(-1);
                   5872:     encoding = (const char *) cur->encoding;
                   5873: 
                   5874:     /* 
                   5875:      * save the content to a temp buffer.
                   5876:      */
                   5877: #ifdef HAVE_ZLIB_H
                   5878:     if (cur->compression < 0) cur->compression = xmlCompressMode;
1.106     daniel   5879: #endif
1.114     veillard 5880:     if (encoding != NULL) {
                   5881:        xmlCharEncoding enc;
                   5882: 
                   5883:        enc = xmlParseCharEncoding(encoding);
                   5884: 
                   5885:        if (cur->charset != XML_CHAR_ENCODING_UTF8) {
1.134     veillard 5886:            xmlGenericError(xmlGenericErrorContext,
                   5887:                    "xmlSaveFile: document not in UTF8\n");
1.114     veillard 5888:            return(-1);
                   5889:        }
1.115     veillard 5890:        if (enc != XML_CHAR_ENCODING_UTF8) {
                   5891:            handler = xmlFindCharEncodingHandler(encoding);
                   5892:            if (handler == NULL) {
                   5893:                xmlFree((char *) cur->encoding);
                   5894:                cur->encoding = NULL;
                   5895:            }
1.114     veillard 5896:        }
                   5897:     }
                   5898: 
                   5899:     buf = xmlOutputBufferCreateFilename(filename, handler, cur->compression);
                   5900:     if (buf == NULL) return(0);
                   5901: 
1.146     veillard 5902:     xmlDocContentDumpOutput(buf, cur, NULL, 1);
1.114     veillard 5903: 
                   5904:     ret = xmlOutputBufferClose(buf);
                   5905:     return(ret);
                   5906: }
                   5907: 

Webmaster