Annotation of XML/tree.c, revision 1.83

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

Webmaster