Annotation of XML/tree.c, revision 1.133

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

Webmaster