Annotation of XML/tree.c, revision 1.125

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

Webmaster