Annotation of XML/tree.c, revision 1.45

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:  * TODO Cleanup the Dump mechanism.
1.17      daniel      7:  *
1.32      daniel      8:  * Daniel.Veillard@w3.org
1.1       veillard    9:  */
                     10: 
1.23      daniel     11: #include "config.h"
1.1       veillard   12: #include <stdio.h>
                     13: #include <ctype.h>
1.23      daniel     14: #include <stdlib.h>
1.7       veillard   15: #include <string.h> /* for memset() only ! */
1.1       veillard   16: 
1.23      daniel     17: #ifdef HAVE_ZLIB_H
                     18: #include <zlib.h>
                     19: #endif
                     20: 
1.1       veillard   21: #include "tree.h"
1.6       veillard   22: #include "entities.h"
1.33      daniel     23: #include "valid.h"
1.1       veillard   24: 
1.7       veillard   25: static CHAR xmlStringText[] = { 't', 'e', 'x', 't', 0 };
1.12      daniel     26: int oldXMLWDcompatibility = 0;
1.21      daniel     27: int xmlIndentTreeOutput = 1;
1.7       veillard   28: 
1.23      daniel     29: static int xmlCompressMode = 0;
                     30: 
1.32      daniel     31: #define UPDATE_LAST_CHILD(n) if ((n) != NULL) {                                \
                     32:     xmlNodePtr ulccur = (n)->childs;                                   \
                     33:     if (ulccur == NULL) {                                              \
                     34:         (n)->last = NULL;                                              \
                     35:     } else {                                                           \
                     36:         while (ulccur->next != NULL) ulccur = ulccur->next;            \
                     37:        (n)->last = ulccur;                                             \
1.34      daniel     38: }}
1.32      daniel     39: 
1.1       veillard   40: /************************************************************************
                     41:  *                                                                     *
                     42:  *             Allocation and deallocation of basic structures         *
                     43:  *                                                                     *
                     44:  ************************************************************************/
                     45:  
1.23      daniel     46: /**
                     47:  * xmlUpgradeOldNs:
                     48:  * @doc:  a document pointer
                     49:  * 
                     50:  * Upgrade old style Namespaces (PI) and move them to the root of the document.
1.19      daniel     51:  */
1.28      daniel     52: void
                     53: xmlUpgradeOldNs(xmlDocPtr doc) {
1.19      daniel     54:     xmlNsPtr cur;
                     55: 
                     56:     if ((doc == NULL) || (doc->oldNs == NULL)) return;
                     57:     if (doc->root == NULL) {
                     58:         fprintf(stderr, "xmlUpgradeOldNs: failed no root !\n");
                     59:        return;
                     60:     }
                     61: 
                     62:     cur = doc->oldNs;
                     63:     while (cur->next != NULL) {
                     64:        cur->type = XML_LOCAL_NAMESPACE;
                     65:         cur = cur->next;
                     66:     }
                     67:     cur->type = XML_LOCAL_NAMESPACE;
                     68:     cur->next = doc->root->nsDef;
                     69:     doc->root->nsDef = doc->oldNs;
                     70:     doc->oldNs = NULL;
                     71: }
                     72: 
1.23      daniel     73: /**
                     74:  * xmlNewNs:
                     75:  * @node:  the element carrying the namespace
                     76:  * @href:  the URI associated
                     77:  * @prefix:  the prefix for the namespace
                     78:  *
1.17      daniel     79:  * Creation of a new Namespace.
1.36      daniel     80:  * Returns returns a new namespace pointer
1.1       veillard   81:  */
1.28      daniel     82: xmlNsPtr
                     83: xmlNewNs(xmlNodePtr node, const CHAR *href, const CHAR *prefix) {
1.16      daniel     84:     xmlNsPtr cur;
1.1       veillard   85: 
1.19      daniel     86:     if (href == NULL) {
                     87:         fprintf(stderr, "xmlNewNs: href == NULL !\n");
                     88:        return(NULL);
                     89:     }
                     90: 
1.1       veillard   91:     /*
                     92:      * Allocate a new DTD and fill the fields.
                     93:      */
1.16      daniel     94:     cur = (xmlNsPtr) malloc(sizeof(xmlNs));
1.1       veillard   95:     if (cur == NULL) {
1.16      daniel     96:         fprintf(stderr, "xmlNewNs : malloc failed\n");
1.1       veillard   97:        return(NULL);
                     98:     }
                     99: 
1.19      daniel    100:     cur->type = XML_LOCAL_NAMESPACE;
                    101:     if (href != NULL)
                    102:        cur->href = xmlStrdup(href); 
                    103:     else
                    104:         cur->href = NULL;
                    105:     if (prefix != NULL)
                    106:        cur->prefix = xmlStrdup(prefix); 
                    107:     else
                    108:         cur->prefix = NULL;
                    109: 
                    110:     /*
                    111:      * Add it at the end to preserve parsing order ...
                    112:      */
1.1       veillard  113:     cur->next = NULL;
1.19      daniel    114:     if (node != NULL) {
                    115:        if (node->nsDef == NULL) {
                    116:            node->nsDef = cur;
                    117:        } else {
                    118:            xmlNsPtr prev = node->nsDef;
                    119: 
                    120:            while (prev->next != NULL) prev = prev->next;
                    121:            prev->next = cur;
                    122:        }
                    123:     }
                    124: 
                    125:     return(cur);
                    126: }
                    127: 
1.23      daniel    128: /**
                    129:  * xmlNewGlobalNs:
                    130:  * @doc:  the document carrying the namespace
                    131:  * @href:  the URI associated
                    132:  * @prefix:  the prefix for the namespace
                    133:  *
                    134:  * Creation of a Namespace, the old way using PI and without scoping, to AVOID.
1.36      daniel    135:  * Returns returns a new namespace pointer
1.19      daniel    136:  */
1.28      daniel    137: xmlNsPtr
                    138: xmlNewGlobalNs(xmlDocPtr doc, const CHAR *href, const CHAR *prefix) {
1.19      daniel    139:     xmlNsPtr cur;
                    140: 
                    141:     /*
                    142:      * Allocate a new DTD and fill the fields.
                    143:      */
                    144:     cur = (xmlNsPtr) malloc(sizeof(xmlNs));
                    145:     if (cur == NULL) {
1.31      daniel    146:         fprintf(stderr, "xmlNewGlobalNs : malloc failed\n");
1.19      daniel    147:        return(NULL);
                    148:     }
                    149: 
                    150:     cur->type = XML_GLOBAL_NAMESPACE;
1.1       veillard  151:     if (href != NULL)
1.7       veillard  152:        cur->href = xmlStrdup(href); 
1.1       veillard  153:     else
                    154:         cur->href = NULL;
1.16      daniel    155:     if (prefix != NULL)
                    156:        cur->prefix = xmlStrdup(prefix); 
1.1       veillard  157:     else
1.16      daniel    158:         cur->prefix = NULL;
1.17      daniel    159: 
                    160:     /*
                    161:      * Add it at the end to preserve parsing order ...
                    162:      */
                    163:     cur->next = NULL;
1.1       veillard  164:     if (doc != NULL) {
1.19      daniel    165:        if (doc->oldNs == NULL) {
                    166:            doc->oldNs = cur;
1.17      daniel    167:        } else {
1.19      daniel    168:            xmlNsPtr prev = doc->oldNs;
1.17      daniel    169: 
                    170:            while (prev->next != NULL) prev = prev->next;
                    171:            prev->next = cur;
                    172:        }
1.1       veillard  173:     }
1.3       veillard  174: 
1.1       veillard  175:     return(cur);
                    176: }
                    177: 
1.23      daniel    178: /**
                    179:  * xmlSetNs:
                    180:  * @node:  a node in the document
                    181:  * @ns:  a namespace pointer
                    182:  *
                    183:  * Associate a namespace to a node, a posteriori.
1.19      daniel    184:  */
1.28      daniel    185: void
                    186: xmlSetNs(xmlNodePtr node, xmlNsPtr ns) {
1.19      daniel    187:     if (node == NULL) {
                    188:         fprintf(stderr, "xmlSetNs: node == NULL\n");
                    189:        return;
                    190:     }
                    191:     node->ns = ns;
                    192: }
                    193: 
1.23      daniel    194: /**
                    195:  * xmlFreeNs:
                    196:  * @cur:  the namespace pointer
                    197:  *
                    198:  * Free up the structures associated to a namespace
1.1       veillard  199:  */
1.28      daniel    200: void
                    201: xmlFreeNs(xmlNsPtr cur) {
1.1       veillard  202:     if (cur == NULL) {
1.17      daniel    203:         fprintf(stderr, "xmlFreeNs : ns == NULL\n");
1.1       veillard  204:        return;
                    205:     }
                    206:     if (cur->href != NULL) free((char *) cur->href);
1.16      daniel    207:     if (cur->prefix != NULL) free((char *) cur->prefix);
                    208:     memset(cur, -1, sizeof(xmlNs));
1.1       veillard  209:     free(cur);
                    210: }
                    211: 
1.23      daniel    212: /**
                    213:  * xmlFreeNsList:
                    214:  * @cur:  the first namespace pointer
                    215:  *
                    216:  * Free up all the structures associated to the chained namespaces.
1.6       veillard  217:  */
1.28      daniel    218: void
                    219: xmlFreeNsList(xmlNsPtr cur) {
1.16      daniel    220:     xmlNsPtr next;
1.6       veillard  221:     if (cur == NULL) {
1.16      daniel    222:         fprintf(stderr, "xmlFreeNsList : ns == NULL\n");
1.6       veillard  223:        return;
                    224:     }
                    225:     while (cur != NULL) {
                    226:         next = cur->next;
1.16      daniel    227:         xmlFreeNs(cur);
1.6       veillard  228:        cur = next;
                    229:     }
                    230: }
                    231: 
1.23      daniel    232: /**
                    233:  * xmlNewDtd:
                    234:  * @doc:  the document pointer
                    235:  * @name:  the DTD name
                    236:  * @ExternalID:  the external ID
                    237:  * @SystemID:  the system ID
                    238:  *
1.17      daniel    239:  * Creation of a new DTD.
1.36      daniel    240:  * Returns a pointer to the new DTD structure
1.17      daniel    241:  */
1.28      daniel    242: xmlDtdPtr
                    243: xmlNewDtd(xmlDocPtr doc, const CHAR *name,
1.17      daniel    244:                     const CHAR *ExternalID, const CHAR *SystemID) {
                    245:     xmlDtdPtr cur;
                    246: 
1.31      daniel    247:     if ((doc != NULL) && (doc->extSubset != NULL)) {
1.17      daniel    248:         fprintf(stderr, "xmlNewDtd(%s): document %s already have a DTD %s\n",
1.31      daniel    249:            /* !!! */ (char *) name, doc->name,
                    250:            /* !!! */ (char *)doc->extSubset->name);
1.17      daniel    251:     }
                    252: 
                    253:     /*
                    254:      * Allocate a new DTD and fill the fields.
                    255:      */
                    256:     cur = (xmlDtdPtr) malloc(sizeof(xmlDtd));
                    257:     if (cur == NULL) {
1.31      daniel    258:         fprintf(stderr, "xmlNewDtd : malloc failed\n");
                    259:        return(NULL);
                    260:     }
                    261: 
                    262:     if (name != NULL)
                    263:        cur->name = xmlStrdup(name); 
                    264:     else
                    265:         cur->name = NULL;
                    266:     if (ExternalID != NULL)
                    267:        cur->ExternalID = xmlStrdup(ExternalID); 
                    268:     else
                    269:         cur->ExternalID = NULL;
                    270:     if (SystemID != NULL)
                    271:        cur->SystemID = xmlStrdup(SystemID); 
                    272:     else
                    273:         cur->SystemID = NULL;
1.35      daniel    274:     cur->notations = NULL;
1.31      daniel    275:     cur->elements = NULL;
1.34      daniel    276:     cur->attributes = NULL;
1.31      daniel    277:     cur->entities = NULL;
                    278:     if (doc != NULL)
                    279:        doc->extSubset = cur;
                    280: 
                    281:     return(cur);
                    282: }
                    283: 
                    284: /**
                    285:  * xmlCreateIntSubset:
                    286:  * @doc:  the document pointer
                    287:  * @name:  the DTD name
                    288:  * @ExternalID:  the external ID
                    289:  * @SystemID:  the system ID
                    290:  *
1.36      daniel    291:  * Create the internal subset of a document
                    292:  * Returns a pointer to the new DTD structure
1.31      daniel    293:  */
                    294: xmlDtdPtr
                    295: xmlCreateIntSubset(xmlDocPtr doc, const CHAR *name,
                    296:                    const CHAR *ExternalID, const CHAR *SystemID) {
                    297:     xmlDtdPtr cur;
                    298: 
                    299:     if ((doc != NULL) && (doc->intSubset != NULL)) {
                    300:         fprintf(stderr, 
                    301:      "xmlCreateIntSubset(): document %s already have an internal subset\n",
                    302:            doc->name);
                    303:        return(NULL);
                    304:     }
                    305: 
                    306:     /*
                    307:      * Allocate a new DTD and fill the fields.
                    308:      */
                    309:     cur = (xmlDtdPtr) malloc(sizeof(xmlDtd));
                    310:     if (cur == NULL) {
                    311:         fprintf(stderr, "xmlNewDtd : malloc failed\n");
1.17      daniel    312:        return(NULL);
                    313:     }
                    314: 
                    315:     if (name != NULL)
                    316:        cur->name = xmlStrdup(name); 
                    317:     else
                    318:         cur->name = NULL;
                    319:     if (ExternalID != NULL)
                    320:        cur->ExternalID = xmlStrdup(ExternalID); 
                    321:     else
                    322:         cur->ExternalID = NULL;
                    323:     if (SystemID != NULL)
                    324:        cur->SystemID = xmlStrdup(SystemID); 
                    325:     else
                    326:         cur->SystemID = NULL;
1.35      daniel    327:     cur->notations = NULL;
1.17      daniel    328:     cur->elements = NULL;
1.34      daniel    329:     cur->attributes = NULL;
1.17      daniel    330:     cur->entities = NULL;
1.31      daniel    331:     if (doc != NULL)
                    332:        doc->intSubset = cur;
1.17      daniel    333: 
                    334:     return(cur);
                    335: }
                    336: 
1.23      daniel    337: /**
                    338:  * xmlFreeDtd:
                    339:  * @cur:  the DTD structure to free up
                    340:  *
                    341:  * Free a DTD structure.
1.17      daniel    342:  */
1.28      daniel    343: void
                    344: xmlFreeDtd(xmlDtdPtr cur) {
1.17      daniel    345:     if (cur == NULL) {
                    346:         fprintf(stderr, "xmlFreeDtd : DTD == NULL\n");
                    347:        return;
                    348:     }
                    349:     if (cur->name != NULL) free((char *) cur->name);
                    350:     if (cur->SystemID != NULL) free((char *) cur->SystemID);
                    351:     if (cur->ExternalID != NULL) free((char *) cur->ExternalID);
1.35      daniel    352:     if (cur->notations != NULL)
                    353:         xmlFreeNotationTable((xmlNotationTablePtr) cur->notations);
1.17      daniel    354:     if (cur->elements != NULL)
1.33      daniel    355:         xmlFreeElementTable((xmlElementTablePtr) cur->elements);
1.34      daniel    356:     if (cur->attributes != NULL)
                    357:         xmlFreeAttributeTable((xmlAttributeTablePtr) cur->attributes);
1.17      daniel    358:     if (cur->entities != NULL)
                    359:         xmlFreeEntitiesTable((xmlEntitiesTablePtr) cur->entities);
                    360:     memset(cur, -1, sizeof(xmlDtd));
                    361:     free(cur);
                    362: }
                    363: 
1.23      daniel    364: /**
                    365:  * xmlNewDoc:
                    366:  * @version:  CHAR string giving the version of XML "1.0"
                    367:  *
1.36      daniel    368:  * Returns a new document
1.1       veillard  369:  */
1.28      daniel    370: xmlDocPtr
                    371: xmlNewDoc(const CHAR *version) {
1.1       veillard  372:     xmlDocPtr cur;
                    373: 
                    374:     if (version == NULL) {
                    375:         fprintf(stderr, "xmlNewDoc : version == NULL\n");
                    376:        return(NULL);
                    377:     }
                    378: 
                    379:     /*
                    380:      * Allocate a new document and fill the fields.
                    381:      */
                    382:     cur = (xmlDocPtr) malloc(sizeof(xmlDoc));
                    383:     if (cur == NULL) {
                    384:         fprintf(stderr, "xmlNewDoc : malloc failed\n");
                    385:        return(NULL);
                    386:     }
                    387: 
1.23      daniel    388:     cur->type = XML_DOCUMENT_NODE;
1.7       veillard  389:     cur->version = xmlStrdup(version); 
1.18      daniel    390:     cur->name = NULL;
1.1       veillard  391:     cur->root = NULL; 
1.31      daniel    392:     cur->intSubset = NULL;
                    393:     cur->extSubset = NULL;
1.19      daniel    394:     cur->oldNs = NULL;
1.15      daniel    395:     cur->encoding = NULL;
                    396:     cur->standalone = -1;
1.23      daniel    397:     cur->compression = xmlCompressMode;
1.39      daniel    398: #ifndef XML_WITHOUT_CORBA
1.23      daniel    399:     cur->_private = NULL;
                    400:     cur->vepv = NULL;
                    401: #endif
1.1       veillard  402:     return(cur);
                    403: }
                    404: 
1.23      daniel    405: /**
                    406:  * xmlFreeDoc:
                    407:  * @cur:  pointer to the document
                    408:  * @:  
                    409:  *
                    410:  * Free up all the structures used by a document, tree included.
1.1       veillard  411:  */
1.28      daniel    412: void
                    413: xmlFreeDoc(xmlDocPtr cur) {
1.1       veillard  414:     if (cur == NULL) {
1.31      daniel    415: #ifdef DEBUG_TREE
1.1       veillard  416:         fprintf(stderr, "xmlFreeDoc : document == NULL\n");
1.31      daniel    417: #endif
1.1       veillard  418:        return;
                    419:     }
                    420:     free((char *) cur->version);
1.17      daniel    421:     if (cur->name != NULL) free((char *) cur->name);
1.15      daniel    422:     if (cur->encoding != NULL) free((char *) cur->encoding);
1.1       veillard  423:     if (cur->root != NULL) xmlFreeNode(cur->root);
1.31      daniel    424:     if (cur->intSubset != NULL) xmlFreeDtd(cur->intSubset);
                    425:     if (cur->extSubset != NULL) xmlFreeDtd(cur->extSubset);
                    426:     if (cur->oldNs != NULL) xmlFreeNsList(cur->oldNs);
1.1       veillard  427:     memset(cur, -1, sizeof(xmlDoc));
                    428:     free(cur);
                    429: }
                    430: 
1.23      daniel    431: /**
1.28      daniel    432:  * xmlStringLenGetNodeList:
                    433:  * @doc:  the document
                    434:  * @value:  the value of the text
1.36      daniel    435:  * @len:  the length of the string value
1.28      daniel    436:  *
                    437:  * Parse the value string and build the node list associated. Should
                    438:  * produce a flat tree with only TEXTs and ENTITY_REFs.
1.36      daniel    439:  * Returns a pointer to the first child
1.28      daniel    440:  */
                    441: xmlNodePtr
                    442: xmlStringLenGetNodeList(xmlDocPtr doc, const CHAR *value, int len) {
                    443:     xmlNodePtr ret = NULL, last = NULL;
                    444:     xmlNodePtr node;
                    445:     CHAR *val;
                    446:     const CHAR *cur = value;
                    447:     const CHAR *q;
                    448:     xmlEntityPtr ent;
                    449: 
                    450:     if (value == NULL) return(NULL);
                    451: 
                    452:     q = cur;
                    453:     while ((*cur != 0) && (cur - value < len)) {
                    454:        if (*cur == '&') {
                    455:            /*
                    456:             * Save the current text.
                    457:             */
                    458:             if (cur != q) {
                    459:                if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
                    460:                    xmlNodeAddContentLen(last, q, cur - q);
                    461:                } else {
                    462:                    node = xmlNewDocTextLen(doc, q, cur - q);
                    463:                    if (node == NULL) return(ret);
                    464:                    if (last == NULL)
                    465:                        last = ret = node;
                    466:                    else {
                    467:                        last->next = node;
                    468:                        node->prev = last;
                    469:                        last = node;
                    470:                    }
                    471:                }
                    472:            }
                    473:            /*
                    474:             * Read the entity string
                    475:             */
                    476:            cur++;
                    477:            q = cur;
                    478:            while ((*cur != 0) && (cur - value < len) && (*cur != ';')) cur++;
                    479:            if ((*cur == 0) || (cur - value >= len)) {
                    480:                fprintf(stderr,
1.44      daniel    481:                    "xmlStringLenGetNodeList: unterminated entity %30s\n", q);
1.28      daniel    482:                return(ret);
                    483:            }
                    484:             if (cur != q) {
                    485:                /*
                    486:                 * Predefined entities don't generate nodes
                    487:                 */
                    488:                val = xmlStrndup(q, cur - q);
                    489:                ent = xmlGetDocEntity(doc, val);
                    490:                if ((ent != NULL) &&
                    491:                    (ent->type == XML_INTERNAL_PREDEFINED_ENTITY)) {
                    492:                    if (last == NULL) {
                    493:                        node = xmlNewDocText(doc, ent->content);
                    494:                        last = ret = node;
                    495:                    } else
                    496:                        xmlNodeAddContent(last, ent->content);
                    497:                        
                    498:                } else {
                    499:                    /*
                    500:                     * Create a new REFERENCE_REF node
                    501:                     */
                    502:                    node = xmlNewReference(doc, val);
1.30      daniel    503:                    if (node == NULL) {
                    504:                        if (val != NULL) free(val);
                    505:                        return(ret);
                    506:                    }
1.28      daniel    507:                    if (last == NULL)
                    508:                        last = ret = node;
                    509:                    else {
                    510:                        last->next = node;
                    511:                        node->prev = last;
                    512:                        last = node;
                    513:                    }
                    514:                }
                    515:                free(val);
                    516:            }
                    517:            cur++;
                    518:            q = cur;
                    519:        } else 
                    520:            cur++;
                    521:     }
                    522:     if (cur != q) {
                    523:         /*
                    524:         * Handle the last piece of text.
                    525:         */
                    526:        if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
                    527:            xmlNodeAddContentLen(last, q, cur - q);
                    528:        } else {
                    529:            node = xmlNewDocTextLen(doc, q, cur - q);
                    530:            if (node == NULL) return(ret);
                    531:            if (last == NULL)
                    532:                last = ret = node;
                    533:            else {
                    534:                last->next = node;
                    535:                node->prev = last;
                    536:                last = node;
                    537:            }
                    538:        }
                    539:     }
                    540:     return(ret);
                    541: }
                    542: 
                    543: /**
1.24      daniel    544:  * xmlStringGetNodeList:
                    545:  * @doc:  the document
1.23      daniel    546:  * @value:  the value of the attribute
                    547:  *
1.24      daniel    548:  * Parse the value string and build the node list associated. Should
                    549:  * produce a flat tree with only TEXTs and ENTITY_REFs.
1.36      daniel    550:  * Returns a pointer to the first child
1.23      daniel    551:  */
1.28      daniel    552: xmlNodePtr
                    553: xmlStringGetNodeList(xmlDocPtr doc, const CHAR *value) {
1.23      daniel    554:     xmlNodePtr ret = NULL, last = NULL;
                    555:     xmlNodePtr node;
                    556:     CHAR *val;
                    557:     const CHAR *cur = value;
                    558:     const CHAR *q;
1.28      daniel    559:     xmlEntityPtr ent;
1.23      daniel    560: 
                    561:     if (value == NULL) return(NULL);
                    562: 
                    563:     q = cur;
                    564:     while (*cur != 0) {
                    565:        if (*cur == '&') {
1.28      daniel    566:            /*
                    567:             * Save the current text.
                    568:             */
1.23      daniel    569:             if (cur != q) {
1.28      daniel    570:                if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
                    571:                    xmlNodeAddContentLen(last, q, cur - q);
                    572:                } else {
                    573:                    node = xmlNewDocTextLen(doc, q, cur - q);
                    574:                    if (node == NULL) return(ret);
                    575:                    if (last == NULL)
                    576:                        last = ret = node;
                    577:                    else {
                    578:                        last->next = node;
                    579:                        node->prev = last;
                    580:                        last = node;
                    581:                    }
1.23      daniel    582:                }
                    583:            }
1.28      daniel    584:            /*
                    585:             * Read the entity string
                    586:             */
1.23      daniel    587:            cur++;
                    588:            q = cur;
                    589:            while ((*cur != 0) && (*cur != ';')) cur++;
                    590:            if (*cur == 0) {
1.24      daniel    591:                fprintf(stderr,
                    592:                        "xmlStringGetNodeList: unterminated entity %30s\n", q);
1.23      daniel    593:                return(ret);
                    594:            }
                    595:             if (cur != q) {
1.28      daniel    596:                /*
                    597:                 * Predefined entities don't generate nodes
                    598:                 */
1.23      daniel    599:                val = xmlStrndup(q, cur - q);
1.28      daniel    600:                ent = xmlGetDocEntity(doc, val);
                    601:                if ((ent != NULL) &&
                    602:                    (ent->type == XML_INTERNAL_PREDEFINED_ENTITY)) {
                    603:                    if (last == NULL) {
                    604:                        node = xmlNewDocText(doc, ent->content);
                    605:                        last = ret = node;
                    606:                    } else
                    607:                        xmlNodeAddContent(last, ent->content);
                    608:                        
                    609:                } else {
                    610:                    /*
                    611:                     * Create a new REFERENCE_REF node
                    612:                     */
                    613:                    node = xmlNewReference(doc, val);
1.30      daniel    614:                    if (node == NULL) {
                    615:                        if (val != NULL) free(val);
                    616:                        return(ret);
                    617:                    }
1.28      daniel    618:                    if (last == NULL)
                    619:                        last = ret = node;
                    620:                    else {
                    621:                        last->next = node;
                    622:                        node->prev = last;
                    623:                        last = node;
                    624:                    }
1.23      daniel    625:                }
                    626:                free(val);
                    627:            }
                    628:            cur++;
                    629:            q = cur;
                    630:        } else 
                    631:            cur++;
                    632:     }
                    633:     if (cur != q) {
1.28      daniel    634:         /*
                    635:         * Handle the last piece of text.
                    636:         */
                    637:        if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
                    638:            xmlNodeAddContentLen(last, q, cur - q);
                    639:        } else {
                    640:            node = xmlNewDocTextLen(doc, q, cur - q);
                    641:            if (node == NULL) return(ret);
                    642:            if (last == NULL)
                    643:                last = ret = node;
                    644:            else {
                    645:                last->next = node;
                    646:                node->prev = last;
                    647:                last = node;
                    648:            }
1.23      daniel    649:        }
                    650:     }
                    651:     return(ret);
                    652: }
                    653: 
                    654: /**
1.24      daniel    655:  * xmlNodeListGetString:
1.23      daniel    656:  * @doc:  the document
1.24      daniel    657:  * @list:  a Node list
1.23      daniel    658:  * @inLine:  should we replace entity contents or show their external form
                    659:  *
1.24      daniel    660:  * Returns the string equivalent to the text contained in the Node list
                    661:  * made of TEXTs and ENTITY_REFs
1.36      daniel    662:  * Returns a pointer to the string copy, the calller must free it.
1.23      daniel    663:  */
1.28      daniel    664: CHAR *
                    665: xmlNodeListGetString(xmlDocPtr doc, xmlNodePtr list, int inLine) {
1.24      daniel    666:     xmlNodePtr node = list;
1.23      daniel    667:     CHAR *ret = NULL;
                    668:     xmlEntityPtr ent;
                    669: 
1.24      daniel    670:     if (list == NULL) return(NULL);
1.23      daniel    671: 
                    672:     while (node != NULL) {
                    673:         if (node->type == XML_TEXT_NODE) {
                    674:            if (inLine)
                    675:                ret = xmlStrcat(ret, node->content);
1.45    ! daniel    676:            else {
        !           677:                CHAR *buffer;
        !           678: 
        !           679:                buffer = xmlEncodeEntities(doc, node->content);
        !           680:                if (buffer != NULL) {
        !           681:                    ret = xmlStrcat(ret, buffer);
        !           682:                    free(buffer);
        !           683:                }
        !           684:             }
1.23      daniel    685:        } else if (node->type == XML_ENTITY_REF_NODE) {
                    686:            if (inLine) {
                    687:                ent = xmlGetDocEntity(doc, node->name);
                    688:                if (ent != NULL)
                    689:                    ret = xmlStrcat(ret, ent->content);
                    690:                else
                    691:                    ret = xmlStrcat(ret, node->content);
                    692:             } else {
                    693:                CHAR buf[2];
                    694:                buf[0] = '&'; buf[1] = 0;
                    695:                ret = xmlStrncat(ret, buf, 1);
                    696:                ret = xmlStrcat(ret, node->name);
                    697:                buf[0] = ';'; buf[1] = 0;
                    698:                ret = xmlStrncat(ret, buf, 1);
                    699:            }
1.24      daniel    700:        }
                    701: #if 0
                    702:        else {
                    703:            fprintf(stderr, "xmlGetNodeListString : invalide node type %d\n",
1.23      daniel    704:                    node->type);
                    705:        }
1.24      daniel    706: #endif
1.23      daniel    707:        node = node->next;
                    708:     }
                    709:     return(ret);
                    710: }
                    711: 
                    712: /**
                    713:  * xmlNewProp:
                    714:  * @node:  the holding node
                    715:  * @name:  the name of the attribute
                    716:  * @value:  the value of the attribute
                    717:  *
                    718:  * Create a new property carried by a node.
1.36      daniel    719:  * Returns a pointer to the attribute
1.1       veillard  720:  */
1.28      daniel    721: xmlAttrPtr
                    722: xmlNewProp(xmlNodePtr node, const CHAR *name, const CHAR *value) {
1.20      daniel    723:     xmlAttrPtr cur;
1.1       veillard  724: 
                    725:     if (name == NULL) {
                    726:         fprintf(stderr, "xmlNewProp : name == NULL\n");
                    727:        return(NULL);
                    728:     }
                    729: 
                    730:     /*
                    731:      * Allocate a new property and fill the fields.
                    732:      */
1.20      daniel    733:     cur = (xmlAttrPtr) malloc(sizeof(xmlAttr));
1.1       veillard  734:     if (cur == NULL) {
                    735:         fprintf(stderr, "xmlNewProp : malloc failed\n");
                    736:        return(NULL);
                    737:     }
                    738: 
1.23      daniel    739:     cur->type = XML_ATTRIBUTE_NODE;
1.1       veillard  740:     cur->node = node; 
1.7       veillard  741:     cur->name = xmlStrdup(name);
1.1       veillard  742:     if (value != NULL)
1.24      daniel    743:        cur->val = xmlStringGetNodeList(node->doc, value);
1.1       veillard  744:     else 
1.23      daniel    745:        cur->val = NULL;
1.39      daniel    746: #ifndef XML_WITHOUT_CORBA
1.23      daniel    747:     cur->_private = NULL;
                    748:     cur->vepv = NULL;
                    749: #endif
1.17      daniel    750: 
                    751:     /*
                    752:      * Add it at the end to preserve parsing order ...
                    753:      */
                    754:     cur->next = NULL;
1.1       veillard  755:     if (node != NULL) {
1.17      daniel    756:        if (node->properties == NULL) {
                    757:            node->properties = cur;
                    758:        } else {
1.20      daniel    759:            xmlAttrPtr prev = node->properties;
1.17      daniel    760: 
                    761:            while (prev->next != NULL) prev = prev->next;
                    762:            prev->next = cur;
                    763:        }
                    764:     }
1.1       veillard  765:     return(cur);
                    766: }
                    767: 
1.23      daniel    768: /**
                    769:  * xmlNewDocProp:
                    770:  * @doc:  the document
                    771:  * @name:  the name of the attribute
                    772:  * @value:  the value of the attribute
                    773:  *
                    774:  * Create a new property carried by a document.
1.36      daniel    775:  * Returns a pointer to the attribute
1.23      daniel    776:  */
1.28      daniel    777: xmlAttrPtr
                    778: xmlNewDocProp(xmlDocPtr doc, const CHAR *name, const CHAR *value) {
1.23      daniel    779:     xmlAttrPtr cur;
                    780: 
                    781:     if (name == NULL) {
                    782:         fprintf(stderr, "xmlNewProp : name == NULL\n");
                    783:        return(NULL);
                    784:     }
                    785: 
                    786:     /*
                    787:      * Allocate a new property and fill the fields.
                    788:      */
                    789:     cur = (xmlAttrPtr) malloc(sizeof(xmlAttr));
                    790:     if (cur == NULL) {
                    791:         fprintf(stderr, "xmlNewProp : malloc failed\n");
                    792:        return(NULL);
                    793:     }
                    794: 
                    795:     cur->type = XML_ATTRIBUTE_NODE;
                    796:     cur->node = NULL; 
                    797:     cur->name = xmlStrdup(name);
                    798:     if (value != NULL)
1.24      daniel    799:        cur->val = xmlStringGetNodeList(doc, value);
1.23      daniel    800:     else 
                    801:        cur->val = NULL;
1.39      daniel    802: #ifndef XML_WITHOUT_CORBA
1.23      daniel    803:     cur->_private = NULL;
                    804:     cur->vepv = NULL;
                    805: #endif
                    806: 
                    807:     cur->next = NULL;
                    808:     return(cur);
                    809: }
                    810: 
                    811: /**
                    812:  * xmlFreePropList:
                    813:  * @cur:  the first property in the list
                    814:  *
                    815:  * Free a property and all its siblings, all the childs are freed too.
1.1       veillard  816:  */
1.28      daniel    817: void
                    818: xmlFreePropList(xmlAttrPtr cur) {
1.20      daniel    819:     xmlAttrPtr next;
1.1       veillard  820:     if (cur == NULL) {
                    821:         fprintf(stderr, "xmlFreePropList : property == NULL\n");
                    822:        return;
                    823:     }
                    824:     while (cur != NULL) {
                    825:         next = cur->next;
                    826:         xmlFreeProp(cur);
                    827:        cur = next;
                    828:     }
                    829: }
                    830: 
1.23      daniel    831: /**
                    832:  * xmlFreeProp:
                    833:  * @cur:  the first property in the list
                    834:  *
                    835:  * Free one property, all the childs are freed too.
1.1       veillard  836:  */
1.28      daniel    837: void
                    838: xmlFreeProp(xmlAttrPtr cur) {
1.1       veillard  839:     if (cur == NULL) {
                    840:         fprintf(stderr, "xmlFreeProp : property == NULL\n");
                    841:        return;
                    842:     }
                    843:     if (cur->name != NULL) free((char *) cur->name);
1.23      daniel    844:     if (cur->val != NULL) xmlFreeNodeList(cur->val);
1.20      daniel    845:     memset(cur, -1, sizeof(xmlAttr));
1.1       veillard  846:     free(cur);
                    847: }
                    848: 
1.23      daniel    849: /**
                    850:  * xmlNewNode:
                    851:  * @ns:  namespace if any
                    852:  * @name:  the node name
                    853:  *
                    854:  * Creation of a new node element. @ns and @content are optionnal (NULL).
1.24      daniel    855:  * If content is non NULL, a child list containing the TEXTs and
                    856:  * ENTITY_REFs node will be created.
1.36      daniel    857:  * Returns a pointer to the new node object.
1.1       veillard  858:  */
1.28      daniel    859: xmlNodePtr
                    860: xmlNewNode(xmlNsPtr ns, const CHAR *name) {
1.1       veillard  861:     xmlNodePtr cur;
                    862: 
                    863:     if (name == NULL) {
                    864:         fprintf(stderr, "xmlNewNode : name == NULL\n");
                    865:        return(NULL);
                    866:     }
                    867: 
                    868:     /*
                    869:      * Allocate a new node and fill the fields.
                    870:      */
                    871:     cur = (xmlNodePtr) malloc(sizeof(xmlNode));
                    872:     if (cur == NULL) {
                    873:         fprintf(stderr, "xmlNewNode : malloc failed\n");
                    874:        return(NULL);
                    875:     }
                    876: 
1.23      daniel    877:     cur->type = XML_ELEMENT_NODE;
                    878:     cur->doc = NULL;
1.1       veillard  879:     cur->parent = NULL; 
1.23      daniel    880:     cur->next = NULL;
                    881:     cur->prev = NULL;
                    882:     cur->childs = NULL;
1.32      daniel    883:     cur->last = NULL;
1.23      daniel    884:     cur->properties = NULL;
1.22      daniel    885:     cur->name = xmlStrdup(name);
1.16      daniel    886:     cur->ns = ns;
1.19      daniel    887:     cur->nsDef = NULL;
1.24      daniel    888:     cur->content = NULL;
1.39      daniel    889: #ifndef XML_WITHOUT_CORBA
1.23      daniel    890:     cur->_private = NULL;
                    891:     cur->vepv = NULL;
                    892: #endif
1.1       veillard  893:     return(cur);
                    894: }
                    895: 
1.23      daniel    896: /**
                    897:  * xmlNewDocNode:
                    898:  * @doc:  the document
                    899:  * @ns:  namespace if any
                    900:  * @name:  the node name
                    901:  * @content:  the text content if any
                    902:  *
                    903:  * Creation of a new node element within a document. @ns and @content
                    904:  * are optionnal (NULL).
1.36      daniel    905:  * Returns a pointer to the new node object.
1.23      daniel    906:  */
1.28      daniel    907: xmlNodePtr
                    908: xmlNewDocNode(xmlDocPtr doc, xmlNsPtr ns,
1.23      daniel    909:                          const CHAR *name, CHAR *content) {
                    910:     xmlNodePtr cur;
                    911: 
1.24      daniel    912:     cur = xmlNewNode(ns, name);
                    913:     if (cur != NULL) {
                    914:         cur->doc = doc;
1.32      daniel    915:        if (content != NULL) {
1.24      daniel    916:            cur->childs = xmlStringGetNodeList(doc, content);
1.34      daniel    917:            UPDATE_LAST_CHILD(cur)
1.32      daniel    918:        }
1.24      daniel    919:     }
1.23      daniel    920:     return(cur);
                    921: }
                    922: 
                    923: 
                    924: /**
                    925:  * xmlNewText:
                    926:  * @content:  the text content
                    927:  *
                    928:  * Creation of a new text node.
1.36      daniel    929:  * Returns a pointer to the new node object.
1.3       veillard  930:  */
1.28      daniel    931: xmlNodePtr
                    932: xmlNewText(const CHAR *content) {
1.3       veillard  933:     xmlNodePtr cur;
                    934: 
                    935:     /*
                    936:      * Allocate a new node and fill the fields.
                    937:      */
                    938:     cur = (xmlNodePtr) malloc(sizeof(xmlNode));
                    939:     if (cur == NULL) {
1.19      daniel    940:         fprintf(stderr, "xmlNewText : malloc failed\n");
1.3       veillard  941:        return(NULL);
                    942:     }
                    943: 
1.23      daniel    944:     cur->type = XML_TEXT_NODE;
                    945:     cur->doc = NULL;
1.3       veillard  946:     cur->parent = NULL; 
                    947:     cur->next = NULL; 
1.23      daniel    948:     cur->prev = NULL; 
1.3       veillard  949:     cur->childs = NULL; 
1.32      daniel    950:     cur->last = NULL; 
1.3       veillard  951:     cur->properties = NULL; 
1.23      daniel    952:     cur->type = XML_TEXT_NODE;
1.18      daniel    953:     cur->name = xmlStrdup(xmlStringText);
1.16      daniel    954:     cur->ns = NULL;
1.19      daniel    955:     cur->nsDef = NULL;
1.3       veillard  956:     if (content != NULL)
1.7       veillard  957:        cur->content = xmlStrdup(content);
1.3       veillard  958:     else 
                    959:        cur->content = NULL;
                    960:     return(cur);
                    961: }
                    962: 
1.23      daniel    963: /**
                    964:  * xmlNewReference:
                    965:  * @doc: the document
                    966:  * @name:  the reference name, or the reference string with & and ;
                    967:  *
                    968:  * Creation of a new reference node.
1.36      daniel    969:  * Returns a pointer to the new node object.
1.23      daniel    970:  */
1.28      daniel    971: xmlNodePtr
                    972: xmlNewReference(xmlDocPtr doc, const CHAR *name) {
1.23      daniel    973:     xmlNodePtr cur;
                    974:     xmlEntityPtr ent;
                    975: 
                    976:     /*
                    977:      * Allocate a new node and fill the fields.
                    978:      */
                    979:     cur = (xmlNodePtr) malloc(sizeof(xmlNode));
                    980:     if (cur == NULL) {
                    981:         fprintf(stderr, "xmlNewText : malloc failed\n");
                    982:        return(NULL);
                    983:     }
                    984: 
                    985:     cur->type = XML_ENTITY_REF_NODE;
1.28      daniel    986:     cur->doc = doc;
1.23      daniel    987:     cur->parent = NULL; 
                    988:     cur->next = NULL; 
                    989:     cur->prev = NULL; 
                    990:     cur->childs = NULL; 
1.32      daniel    991:     cur->last = NULL; 
1.23      daniel    992:     cur->properties = NULL; 
                    993:     if (name[0] == '&') {
                    994:         int len;
                    995:         name++;
                    996:        len = xmlStrlen(name);
                    997:        if (name[len - 1] == ';')
                    998:            cur->name = xmlStrndup(name, len - 1);
                    999:        else
                   1000:            cur->name = xmlStrndup(name, len);
                   1001:     } else
                   1002:        cur->name = xmlStrdup(name);
                   1003:     cur->ns = NULL;
                   1004:     cur->nsDef = NULL;
                   1005: 
                   1006:     ent = xmlGetDocEntity(doc, cur->name);
                   1007:     if (ent != NULL)
                   1008:        cur->content = ent->content;
                   1009:     else
                   1010:         cur->content = NULL;
                   1011:     return(cur);
                   1012: }
                   1013: 
                   1014: /**
                   1015:  * xmlNewDocText:
                   1016:  * @doc: the document
                   1017:  * @content:  the text content
                   1018:  *
                   1019:  * Creation of a new text node within a document.
1.36      daniel   1020:  * Returns a pointer to the new node object.
1.23      daniel   1021:  */
1.28      daniel   1022: xmlNodePtr
                   1023: xmlNewDocText(xmlDocPtr doc, const CHAR *content) {
1.23      daniel   1024:     xmlNodePtr cur;
                   1025: 
                   1026:     cur = xmlNewText(content);
                   1027:     if (cur != NULL) cur->doc = doc;
                   1028:     return(cur);
                   1029: }
                   1030: 
                   1031: /**
                   1032:  * xmlNewTextLen:
                   1033:  * @content:  the text content
                   1034:  * @len:  the text len.
                   1035:  *
                   1036:  * Creation of a new text node with an extra parameter for the content's lenght
1.36      daniel   1037:  * Returns a pointer to the new node object.
1.21      daniel   1038:  */
1.28      daniel   1039: xmlNodePtr
                   1040: xmlNewTextLen(const CHAR *content, int len) {
1.21      daniel   1041:     xmlNodePtr cur;
                   1042: 
                   1043:     /*
                   1044:      * Allocate a new node and fill the fields.
                   1045:      */
                   1046:     cur = (xmlNodePtr) malloc(sizeof(xmlNode));
                   1047:     if (cur == NULL) {
                   1048:         fprintf(stderr, "xmlNewText : malloc failed\n");
                   1049:        return(NULL);
                   1050:     }
                   1051: 
1.23      daniel   1052:     cur->type = XML_TEXT_NODE;
                   1053:     cur->doc = NULL; 
1.21      daniel   1054:     cur->parent = NULL; 
1.23      daniel   1055:     cur->prev = NULL; 
1.21      daniel   1056:     cur->next = NULL; 
                   1057:     cur->childs = NULL; 
1.32      daniel   1058:     cur->last = NULL; 
1.21      daniel   1059:     cur->properties = NULL; 
1.23      daniel   1060:     cur->type = XML_TEXT_NODE;
1.21      daniel   1061:     cur->name = xmlStrdup(xmlStringText);
                   1062:     cur->ns = NULL;
                   1063:     cur->nsDef = NULL;
                   1064:     if (content != NULL)
                   1065:        cur->content = xmlStrndup(content, len);
                   1066:     else 
                   1067:        cur->content = NULL;
                   1068:     return(cur);
                   1069: }
                   1070: 
1.23      daniel   1071: /**
                   1072:  * xmlNewDocTextLen:
                   1073:  * @doc: the document
                   1074:  * @content:  the text content
                   1075:  * @len:  the text len.
                   1076:  *
                   1077:  * Creation of a new text node with an extra content lenght parameter. The
                   1078:  * text node pertain to a given document.
1.36      daniel   1079:  * Returns a pointer to the new node object.
1.23      daniel   1080:  */
1.28      daniel   1081: xmlNodePtr
                   1082: xmlNewDocTextLen(xmlDocPtr doc, const CHAR *content, int len) {
1.23      daniel   1083:     xmlNodePtr cur;
                   1084: 
                   1085:     cur = xmlNewTextLen(content, len);
                   1086:     if (cur != NULL) cur->doc = doc;
                   1087:     return(cur);
                   1088: }
                   1089: 
                   1090: /**
                   1091:  * xmlNewComment:
                   1092:  * @content:  the comment content
                   1093:  *
                   1094:  * Creation of a new node containing a comment.
1.36      daniel   1095:  * Returns a pointer to the new node object.
1.14      daniel   1096:  */
1.28      daniel   1097: xmlNodePtr
1.37      daniel   1098: xmlNewComment(const CHAR *content) {
1.14      daniel   1099:     xmlNodePtr cur;
                   1100: 
                   1101:     /*
                   1102:      * Allocate a new node and fill the fields.
                   1103:      */
                   1104:     cur = (xmlNodePtr) malloc(sizeof(xmlNode));
                   1105:     if (cur == NULL) {
1.19      daniel   1106:         fprintf(stderr, "xmlNewComment : malloc failed\n");
1.14      daniel   1107:        return(NULL);
                   1108:     }
                   1109: 
1.23      daniel   1110:     cur->type = XML_COMMENT_NODE;
                   1111:     cur->doc = NULL; 
1.14      daniel   1112:     cur->parent = NULL; 
1.23      daniel   1113:     cur->prev = NULL; 
1.14      daniel   1114:     cur->next = NULL; 
                   1115:     cur->childs = NULL; 
1.32      daniel   1116:     cur->last = NULL; 
1.14      daniel   1117:     cur->properties = NULL; 
1.23      daniel   1118:     cur->type = XML_COMMENT_NODE;
1.18      daniel   1119:     cur->name = xmlStrdup(xmlStringText);
1.16      daniel   1120:     cur->ns = NULL;
1.19      daniel   1121:     cur->nsDef = NULL;
1.14      daniel   1122:     if (content != NULL)
                   1123:        cur->content = xmlStrdup(content);
                   1124:     else 
                   1125:        cur->content = NULL;
                   1126:     return(cur);
                   1127: }
                   1128: 
1.23      daniel   1129: /**
1.36      daniel   1130:  * xmlNewDocComment:
1.23      daniel   1131:  * @doc:  the document
                   1132:  * @content:  the comment content
                   1133:  *
                   1134:  * Creation of a new node containing a commentwithin a document.
1.36      daniel   1135:  * Returns a pointer to the new node object.
1.23      daniel   1136:  */
1.28      daniel   1137: xmlNodePtr
1.37      daniel   1138: xmlNewDocComment(xmlDocPtr doc, const CHAR *content) {
1.23      daniel   1139:     xmlNodePtr cur;
                   1140: 
                   1141:     cur = xmlNewComment(content);
                   1142:     if (cur != NULL) cur->doc = doc;
                   1143:     return(cur);
                   1144: }
                   1145: 
                   1146: /**
                   1147:  * xmlNewChild:
                   1148:  * @parent:  the parent node
                   1149:  * @ns:  a namespace if any
                   1150:  * @name:  the name of the child
                   1151:  * @content:  the content of the child if any.
                   1152:  *
                   1153:  * 
                   1154:  * Creation of a new child element, added at the end of @parent childs list.
1.24      daniel   1155:  * @ns and @content parameters are optionnal (NULL). If content is non NULL,
                   1156:  * a child list containing the TEXTs and ENTITY_REFs node will be created.
1.36      daniel   1157:  * Returns a pointer to the new node object.
1.1       veillard 1158:  */
1.28      daniel   1159: xmlNodePtr
                   1160: xmlNewChild(xmlNodePtr parent, xmlNsPtr ns,
1.7       veillard 1161:                        const CHAR *name, CHAR *content) {
1.1       veillard 1162:     xmlNodePtr cur, prev;
                   1163: 
                   1164:     if (parent == NULL) {
                   1165:         fprintf(stderr, "xmlNewChild : parent == NULL\n");
                   1166:        return(NULL);
                   1167:     }
                   1168: 
                   1169:     if (name == NULL) {
                   1170:         fprintf(stderr, "xmlNewChild : name == NULL\n");
                   1171:        return(NULL);
                   1172:     }
                   1173: 
                   1174:     /*
                   1175:      * Allocate a new node
                   1176:      */
1.16      daniel   1177:     if (ns == NULL)
1.24      daniel   1178:        cur = xmlNewDocNode(parent->doc, parent->ns, name, content);
1.1       veillard 1179:     else
1.24      daniel   1180:        cur = xmlNewDocNode(parent->doc, ns, name, content);
1.1       veillard 1181:     if (cur == NULL) return(NULL);
                   1182: 
                   1183:     /*
                   1184:      * add the new element at the end of the childs list.
                   1185:      */
1.25      daniel   1186:     cur->type = XML_ELEMENT_NODE;
1.1       veillard 1187:     cur->parent = parent;
1.23      daniel   1188:     cur->doc = parent->doc;
1.1       veillard 1189:     if (parent->childs == NULL) {
                   1190:         parent->childs = cur;
1.32      daniel   1191:        parent->last = cur;
1.1       veillard 1192:     } else {
1.32      daniel   1193:         prev = parent->last;
1.1       veillard 1194:        prev->next = cur;
1.23      daniel   1195:        cur->prev = prev;
1.32      daniel   1196:        parent->last = cur;
1.1       veillard 1197:     }
                   1198: 
                   1199:     return(cur);
                   1200: }
                   1201: 
1.23      daniel   1202: /**
                   1203:  * xmlAddChild:
                   1204:  * @parent:  the parent node
                   1205:  * @cur:  the child node
                   1206:  *
                   1207:  * Add a new child element, to @parent, at the end of the child list.
1.36      daniel   1208:  * Returns the child or NULL in case of error.
1.2       veillard 1209:  */
1.28      daniel   1210: xmlNodePtr
                   1211: xmlAddChild(xmlNodePtr parent, xmlNodePtr cur) {
1.2       veillard 1212:     xmlNodePtr prev;
                   1213: 
                   1214:     if (parent == NULL) {
                   1215:         fprintf(stderr, "xmladdChild : parent == NULL\n");
                   1216:        return(NULL);
                   1217:     }
                   1218: 
                   1219:     if (cur == NULL) {
                   1220:         fprintf(stderr, "xmladdChild : child == NULL\n");
                   1221:        return(NULL);
                   1222:     }
                   1223: 
1.23      daniel   1224:     if ((cur->doc != NULL) && (parent->doc != NULL) &&
                   1225:         (cur->doc != parent->doc)) {
                   1226:        fprintf(stderr, "Elements moved to a different document\n");
                   1227:     }
                   1228: 
1.2       veillard 1229:     /*
                   1230:      * add the new element at the end of the childs list.
                   1231:      */
                   1232:     cur->parent = parent;
1.23      daniel   1233:     cur->doc = parent->doc; /* the parent may not be linked to a doc ! */
1.32      daniel   1234: 
1.24      daniel   1235:     /*
                   1236:      * Handle the case where parent->content != NULL, in that case it will
                   1237:      * create a intermediate TEXT node.
                   1238:      */
                   1239:     if (parent->content != NULL) {
                   1240:         xmlNodePtr text;
                   1241:        
                   1242:        text = xmlNewDocText(parent->doc, parent->content);
                   1243:        if (text != NULL) {
                   1244:            text->next = parent->childs;
                   1245:            if (text->next != NULL)
                   1246:                text->next->prev = text;
                   1247:            parent->childs = text;
1.34      daniel   1248:            UPDATE_LAST_CHILD(parent)
1.24      daniel   1249:            free(parent->content);
                   1250:            parent->content = NULL;
                   1251:        }
                   1252:     }
1.2       veillard 1253:     if (parent->childs == NULL) {
                   1254:         parent->childs = cur;
1.32      daniel   1255:        parent->last = cur;
1.2       veillard 1256:     } else {
1.32      daniel   1257:         prev = parent->last;
1.2       veillard 1258:        prev->next = cur;
1.23      daniel   1259:        cur->prev = prev;
1.32      daniel   1260:        parent->last = cur;
1.2       veillard 1261:     }
                   1262: 
                   1263:     return(cur);
                   1264: }
                   1265: 
1.23      daniel   1266: /**
                   1267:  * xmlGetLastChild:
                   1268:  * @parent:  the parent node
                   1269:  *
                   1270:  * Search the last child of a node.
1.36      daniel   1271:  * Returns the last child or NULL if none.
1.21      daniel   1272:  */
1.28      daniel   1273: xmlNodePtr
                   1274: xmlGetLastChild(xmlNodePtr parent) {
1.21      daniel   1275:     if (parent == NULL) {
                   1276:         fprintf(stderr, "xmlGetLastChild : parent == NULL\n");
                   1277:        return(NULL);
                   1278:     }
1.32      daniel   1279:     return(parent->last);
1.21      daniel   1280: }
                   1281: 
1.23      daniel   1282: /**
                   1283:  * xmlFreeNodeList:
                   1284:  * @cur:  the first node in the list
                   1285:  *
                   1286:  * Free a node and all its siblings, this is a recursive behaviour, all
                   1287:  * the childs are freed too.
1.1       veillard 1288:  */
1.28      daniel   1289: void
                   1290: xmlFreeNodeList(xmlNodePtr cur) {
1.1       veillard 1291:     xmlNodePtr next;
                   1292:     if (cur == NULL) {
                   1293:         fprintf(stderr, "xmlFreeNodeList : node == NULL\n");
                   1294:        return;
                   1295:     }
                   1296:     while (cur != NULL) {
                   1297:         next = cur->next;
                   1298:         xmlFreeNode(cur);
                   1299:        cur = next;
                   1300:     }
                   1301: }
                   1302: 
1.23      daniel   1303: /**
                   1304:  * xmlFreeNode:
                   1305:  * @cur:  the node
                   1306:  *
                   1307:  * Free a node, this is a recursive behaviour, all the childs are freed too.
1.1       veillard 1308:  */
1.28      daniel   1309: void
                   1310: xmlFreeNode(xmlNodePtr cur) {
1.1       veillard 1311:     if (cur == NULL) {
                   1312:         fprintf(stderr, "xmlFreeNode : node == NULL\n");
                   1313:        return;
                   1314:     }
1.23      daniel   1315:     cur->doc = NULL;
                   1316:     cur->parent = NULL;
                   1317:     cur->next = NULL;
                   1318:     cur->prev = NULL;
                   1319:     if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
1.1       veillard 1320:     if (cur->properties != NULL) xmlFreePropList(cur->properties);
1.23      daniel   1321:     if (cur->type != XML_ENTITY_REF_NODE)
                   1322:        if (cur->content != NULL) free(cur->content);
1.7       veillard 1323:     if (cur->name != NULL) free((char *) cur->name);
1.19      daniel   1324:     if (cur->nsDef != NULL) xmlFreeNsList(cur->nsDef);
1.1       veillard 1325:     memset(cur, -1, sizeof(xmlNode));
                   1326:     free(cur);
                   1327: }
                   1328: 
1.28      daniel   1329: /**
                   1330:  * xmlUnlinkNode:
                   1331:  * @cur:  the node
                   1332:  *
                   1333:  * Unlink a node from it's current context, the node is not freed
                   1334:  */
                   1335: void
                   1336: xmlUnlinkNode(xmlNodePtr cur) {
                   1337:     if (cur == NULL) {
                   1338:         fprintf(stderr, "xmlUnlinkNode : node == NULL\n");
                   1339:        return;
                   1340:     }
                   1341:     if ((cur->parent != NULL) && (cur->parent->childs == cur))
                   1342:         cur->parent->childs = cur->next;
1.32      daniel   1343:     if ((cur->parent != NULL) && (cur->parent->last == cur))
                   1344:         cur->parent->last = cur->prev;
1.28      daniel   1345:     if (cur->next != NULL)
                   1346:         cur->next->prev = cur->prev;
                   1347:     if (cur->prev != NULL)
                   1348:         cur->prev->next = cur->next;
                   1349:     cur->next = cur->prev = NULL;
                   1350:     cur->parent = NULL;
                   1351: }
                   1352: 
1.1       veillard 1353: /************************************************************************
                   1354:  *                                                                     *
1.31      daniel   1355:  *             Copy operations                                         *
                   1356:  *                                                                     *
                   1357:  ************************************************************************/
                   1358:  
                   1359: /**
                   1360:  * xmlCopyNamespace:
                   1361:  * @cur:  the namespace
                   1362:  *
                   1363:  * Do a copy of the namespace.
                   1364:  *
                   1365:  * Returns: a new xmlNsPtr, or NULL in case of error.
                   1366:  */
                   1367: xmlNsPtr
                   1368: xmlCopyNamespace(xmlNsPtr cur) {
                   1369:     xmlNsPtr ret;
                   1370: 
                   1371:     if (cur == NULL) return(NULL);
                   1372:     switch (cur->type) {
                   1373:         case XML_GLOBAL_NAMESPACE:
                   1374:            ret = xmlNewGlobalNs(NULL, cur->href, cur->prefix);
                   1375:            break;
                   1376:        case XML_LOCAL_NAMESPACE:
                   1377:            ret = xmlNewNs(NULL, cur->href, cur->prefix);
                   1378:            break;
                   1379:        default:
                   1380:            fprintf(stderr, "xmlCopyNamespace: unknown type %d\n", cur->type);
                   1381:            return(NULL);
                   1382:     }
                   1383:     return(ret);
                   1384: }
                   1385: 
                   1386: /**
                   1387:  * xmlCopyNamespaceList:
                   1388:  * @cur:  the first namespace
                   1389:  *
                   1390:  * Do a copy of an namespace list.
                   1391:  *
                   1392:  * Returns: a new xmlNsPtr, or NULL in case of error.
                   1393:  */
                   1394: xmlNsPtr
                   1395: xmlCopyNamespaceList(xmlNsPtr cur) {
                   1396:     xmlNsPtr ret = NULL;
                   1397:     xmlNsPtr p = NULL,q;
                   1398: 
                   1399:     while (cur != NULL) {
                   1400:         q = xmlCopyNamespace(cur);
                   1401:        if (p == NULL) {
                   1402:            ret = p = q;
                   1403:        } else {
                   1404:            p->next = q;
                   1405:            p = q;
                   1406:        }
                   1407:        cur = cur->next;
                   1408:     }
                   1409:     return(ret);
                   1410: }
                   1411: 
                   1412: /**
                   1413:  * xmlCopyProp:
                   1414:  * @cur:  the attribute
                   1415:  *
                   1416:  * Do a copy of the attribute.
                   1417:  *
                   1418:  * Returns: a new xmlAttrPtr, or NULL in case of error.
                   1419:  */
                   1420: xmlAttrPtr
                   1421: xmlCopyProp(xmlAttrPtr cur) {
                   1422:     xmlAttrPtr ret;
                   1423: 
                   1424:     if (cur == NULL) return(NULL);
                   1425:     if (cur->val != NULL)
                   1426:        ret = xmlNewDocProp(cur->val->doc, cur->name, NULL);
                   1427:     else
                   1428:        ret = xmlNewDocProp(NULL, cur->name, NULL);
                   1429:     if (ret == NULL) return(NULL);
                   1430:     if (cur->val != NULL)
                   1431:        ret->val = xmlCopyNodeList(cur->val);
                   1432:     return(ret);
                   1433: }
                   1434: 
                   1435: /**
                   1436:  * xmlCopyPropList:
                   1437:  * @cur:  the first attribute
                   1438:  *
                   1439:  * Do a copy of an attribute list.
                   1440:  *
                   1441:  * Returns: a new xmlAttrPtr, or NULL in case of error.
                   1442:  */
                   1443: xmlAttrPtr
                   1444: xmlCopyPropList(xmlAttrPtr cur) {
                   1445:     xmlAttrPtr ret = NULL;
                   1446:     xmlAttrPtr p = NULL,q;
                   1447: 
                   1448:     while (cur != NULL) {
                   1449:         q = xmlCopyProp(cur);
                   1450:        if (p == NULL) {
                   1451:            ret = p = q;
                   1452:        } else {
                   1453:            p->next = q;
                   1454:            p = q;
                   1455:        }
                   1456:        cur = cur->next;
                   1457:     }
                   1458:     return(ret);
                   1459: }
                   1460: 
                   1461: /*
                   1462:  * NOTE about the CopyNode operations !
                   1463:  *
                   1464:  * They are splitted into external and internal parts for one
                   1465:  * tricky reason: namespaces. Doing a direct copy of a node
                   1466:  * say RPM:Copyright without changing the namespace pointer to
                   1467:  * something else can produce stale links. One way to do it is
                   1468:  * to keep a reference counter but this doesn't work as soon
                   1469:  * as one move the element or the subtree out of the scope of
                   1470:  * the existing namespace. The actual solution seems to add
                   1471:  * a copy of the namespace at the top of the copied tree if
                   1472:  * not available in the subtree.
                   1473:  * Hence two functions, the public front-end call the inner ones
                   1474:  */
                   1475: 
                   1476: static xmlNodePtr
                   1477: xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent);
                   1478: 
                   1479: static xmlNodePtr
                   1480: xmlStaticCopyNode(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent,
                   1481:                   int recursive) {
                   1482:     xmlNodePtr ret;
                   1483: 
                   1484:     if (node == NULL) return(NULL);
                   1485:     /*
                   1486:      * Allocate a new node and fill the fields.
                   1487:      */
                   1488:     ret = (xmlNodePtr) malloc(sizeof(xmlNode));
                   1489:     if (ret == NULL) {
                   1490:         fprintf(stderr, "xmlStaticCopyNode : malloc failed\n");
                   1491:        return(NULL);
                   1492:     }
                   1493: 
                   1494:     ret->type = node->type;
                   1495:     ret->doc = doc;
                   1496:     ret->parent = parent; 
                   1497:     ret->next = NULL;
                   1498:     ret->prev = NULL;
                   1499:     ret->childs = NULL;
1.32      daniel   1500:     ret->last = NULL;
1.31      daniel   1501:     ret->properties = NULL;
                   1502:     if (node->name != NULL)
                   1503:        ret->name = xmlStrdup(node->name);
                   1504:     else
                   1505:         ret->name = NULL;
                   1506:     ret->ns = NULL;
                   1507:     ret->nsDef = NULL;
                   1508:     if ((node->content != NULL) && (node->type != XML_ENTITY_REF_NODE))
                   1509:        ret->content = xmlStrdup(node->content);
                   1510:     else
                   1511:        ret->content = NULL;
1.39      daniel   1512: #ifndef XML_WITHOUT_CORBA
1.31      daniel   1513:     ret->_private = NULL;
                   1514:     ret->vepv = NULL;
                   1515: #endif
                   1516:     if (parent != NULL)
                   1517:         xmlAddChild(parent, ret);
                   1518:     
                   1519:     if (!recursive) return(ret);
                   1520:     if (node->properties != NULL)
                   1521:         ret->properties = xmlCopyPropList(node->properties);
                   1522:     if (node->nsDef != NULL)
                   1523:         ret->nsDef = xmlCopyNamespaceList(node->nsDef);
                   1524: 
                   1525:     if (node->ns != NULL) {
                   1526:         xmlNsPtr ns;
                   1527: 
                   1528:        ns = xmlSearchNs(doc, ret, node->ns->prefix);
                   1529:        if (ns == NULL) {
                   1530:            /*
                   1531:             * Humm, we are copying an element whose namespace is defined
                   1532:             * out of the new tree scope. Search it in the original tree
                   1533:             * and add it at the top of the new tree
                   1534:             */
                   1535:            ns = xmlSearchNs(node->doc, node, node->ns->prefix);
                   1536:            if (ns != NULL) {
                   1537:                xmlNodePtr root = ret;
                   1538: 
                   1539:                while (root->parent != NULL) root = root->parent;
                   1540:                xmlNewNs(root, ns->href, ns->prefix);
                   1541:            }
                   1542:        } else {
                   1543:            /*
                   1544:             * reference the existing namespace definition in our own tree.
                   1545:             */
                   1546:            ret->ns = ns;
                   1547:        }
                   1548:     }
                   1549:     if (node->childs != NULL)
                   1550:         ret->childs = xmlStaticCopyNodeList(node->childs, doc, ret);
1.34      daniel   1551:     UPDATE_LAST_CHILD(ret)
1.31      daniel   1552:     return(ret);
                   1553: }
                   1554: 
                   1555: static xmlNodePtr
                   1556: xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent) {
                   1557:     xmlNodePtr ret = NULL;
                   1558:     xmlNodePtr p = NULL,q;
                   1559: 
                   1560:     while (node != NULL) {
                   1561:         q = xmlStaticCopyNode(node, doc, parent, 1);
                   1562:        if (parent == NULL) {
                   1563:            if (ret == NULL) ret = q;
                   1564:        } else {
                   1565:            if (ret == NULL) {
                   1566:                q->prev = NULL;
                   1567:                ret = p = q;
                   1568:            } else {
                   1569:                p->next = q;
                   1570:                q->prev = p;
                   1571:                p = q;
                   1572:            }
                   1573:        }
                   1574:        node = node->next;
                   1575:     }
                   1576:     return(ret);
                   1577: }
                   1578: 
                   1579: /**
                   1580:  * xmlCopyNode:
                   1581:  * @node:  the node
                   1582:  * @recursive:  if 1 do a recursive copy.
                   1583:  *
                   1584:  * Do a copy of the node.
                   1585:  *
                   1586:  * Returns: a new xmlNodePtr, or NULL in case of error.
                   1587:  */
                   1588: xmlNodePtr
                   1589: xmlCopyNode(xmlNodePtr node, int recursive) {
                   1590:     xmlNodePtr ret;
                   1591: 
                   1592:     ret = xmlStaticCopyNode(node, NULL, NULL, recursive);
                   1593:     return(ret);
                   1594: }
                   1595: 
                   1596: /**
                   1597:  * xmlCopyNodeList:
                   1598:  * @node:  the first node in the list.
                   1599:  *
                   1600:  * Do a recursive copy of the node list.
                   1601:  *
                   1602:  * Returns: a new xmlNodePtr, or NULL in case of error.
                   1603:  */
                   1604: xmlNodePtr xmlCopyNodeList(xmlNodePtr node) {
                   1605:     xmlNodePtr ret = xmlStaticCopyNodeList(node, NULL, NULL);
                   1606:     return(ret);
                   1607: }
                   1608: 
                   1609: /**
                   1610:  * xmlCopyElement:
                   1611:  * @elem:  the element
                   1612:  *
                   1613:  * Do a copy of the element definition.
                   1614:  *
                   1615:  * Returns: a new xmlElementPtr, or NULL in case of error.
                   1616: xmlElementPtr
                   1617: xmlCopyElement(xmlElementPtr elem) {
                   1618:     xmlElementPtr ret;
                   1619: 
                   1620:     if (elem == NULL) return(NULL);
                   1621:     ret = xmlNewDocElement(elem->doc, elem->ns, elem->name, elem->content);
                   1622:     if (ret == NULL) return(NULL);
                   1623:     if (!recursive) return(ret);
                   1624:     if (elem->properties != NULL)
                   1625:         ret->properties = xmlCopyPropList(elem->properties);
                   1626:     
                   1627:     if (elem->nsDef != NULL)
                   1628:         ret->nsDef = xmlCopyNamespaceList(elem->nsDef);
                   1629:     if (elem->childs != NULL)
                   1630:         ret->childs = xmlCopyElementList(elem->childs);
                   1631:     return(ret);
                   1632: }
                   1633:  */
                   1634: 
                   1635: /**
                   1636:  * xmlCopyDtd:
                   1637:  * @dtd:  the dtd
                   1638:  *
                   1639:  * Do a copy of the dtd.
                   1640:  *
                   1641:  * Returns: a new xmlDtdPtr, or NULL in case of error.
                   1642:  */
                   1643: xmlDtdPtr
                   1644: xmlCopyDtd(xmlDtdPtr dtd) {
                   1645:     xmlDtdPtr ret;
                   1646: 
                   1647:     if (dtd == NULL) return(NULL);
                   1648:     ret = xmlNewDtd(NULL, dtd->name, dtd->ExternalID, dtd->SystemID);
                   1649:     if (ret == NULL) return(NULL);
                   1650:     if (dtd->entities != NULL)
                   1651:         ret->entities = (void *) xmlCopyEntitiesTable(
                   1652:                            (xmlEntitiesTablePtr) dtd->entities);
1.35      daniel   1653:     if (dtd->notations != NULL)
                   1654:         ret->notations = (void *) xmlCopyNotationTable(
                   1655:                            (xmlNotationTablePtr) dtd->notations);
                   1656:     if (dtd->elements != NULL)
                   1657:         ret->elements = (void *) xmlCopyElementTable(
                   1658:                            (xmlElementTablePtr) dtd->elements);
                   1659:     if (dtd->attributes != NULL)
                   1660:         ret->attributes = (void *) xmlCopyAttributeTable(
                   1661:                            (xmlAttributeTablePtr) dtd->attributes);
1.31      daniel   1662:     /*
                   1663:      * TODO: support for Element definitions.
                   1664:      */
                   1665:     return(ret);
                   1666: }
                   1667: 
                   1668: /**
                   1669:  * xmlCopyDoc:
                   1670:  * @doc:  the document
                   1671:  * @recursive:  if 1 do a recursive copy.
                   1672:  *
                   1673:  * Do a copy of the document info. If recursive, the content tree will
                   1674:  * be copied too as well as Dtd, namespaces and entities.
                   1675:  *
                   1676:  * Returns: a new xmlDocPtr, or NULL in case of error.
                   1677:  */
                   1678: xmlDocPtr
                   1679: xmlCopyDoc(xmlDocPtr doc, int recursive) {
                   1680:     xmlDocPtr ret;
                   1681: 
                   1682:     if (doc == NULL) return(NULL);
                   1683:     ret = xmlNewDoc(doc->version);
                   1684:     if (ret == NULL) return(NULL);
                   1685:     if (doc->name != NULL)
                   1686:         ret->name = strdup(doc->name);
                   1687:     if (doc->encoding != NULL)
                   1688:         ret->encoding = xmlStrdup(doc->encoding);
                   1689:     ret->compression = doc->compression;
                   1690:     ret->standalone = doc->standalone;
                   1691:     if (!recursive) return(ret);
                   1692: 
                   1693:     if (doc->intSubset != NULL)
                   1694:         ret->intSubset = xmlCopyDtd(doc->intSubset);
                   1695:     if (doc->oldNs != NULL)
                   1696:         ret->oldNs = xmlCopyNamespaceList(doc->oldNs);
                   1697:     if (doc->root != NULL)
                   1698:         ret->root = xmlStaticCopyNodeList(doc->root, ret, NULL);
                   1699:     return(ret);
                   1700: }
                   1701: 
                   1702: /************************************************************************
                   1703:  *                                                                     *
1.1       veillard 1704:  *             Content access functions                                *
                   1705:  *                                                                     *
                   1706:  ************************************************************************/
                   1707:  
1.23      daniel   1708: /**
1.28      daniel   1709:  * xmlNodeGetContent:
                   1710:  * @cur:  the node being read
                   1711:  *
                   1712:  * Read the value of a node, this can be either the text carried
                   1713:  * directly by this node if it's a TEXT node or the aggregate string
                   1714:  * of the values carried by this node child's (TEXT and ENTITY_REF).
                   1715:  * Entity references are substitued.
1.36      daniel   1716:  * Returns a new CHAR * or NULL if no content is available.
1.38      daniel   1717:  *     It's up to the caller to free the memory.
1.28      daniel   1718:  */
                   1719: CHAR *
                   1720: xmlNodeGetContent(xmlNodePtr cur) {
                   1721:     if (cur == NULL) return(NULL);
                   1722:     switch (cur->type) {
                   1723:         case XML_DOCUMENT_FRAG_NODE:
                   1724:         case XML_ELEMENT_NODE:
                   1725:             return(xmlNodeListGetString(cur->doc, cur->childs, 1));
                   1726:            break;
                   1727:         case XML_ATTRIBUTE_NODE:
                   1728:         case XML_CDATA_SECTION_NODE:
                   1729:         case XML_ENTITY_REF_NODE:
                   1730:         case XML_ENTITY_NODE:
                   1731:         case XML_PI_NODE:
                   1732:         case XML_COMMENT_NODE:
                   1733:         case XML_DOCUMENT_NODE:
                   1734:         case XML_DOCUMENT_TYPE_NODE:
                   1735:         case XML_NOTATION_NODE:
                   1736:            return(NULL);
                   1737:         case XML_TEXT_NODE:
                   1738:            if (cur->content != NULL)
                   1739:                return(xmlStrdup(cur->content));
                   1740:             return(NULL);
                   1741:     }
                   1742:     return(NULL);
                   1743: }
                   1744:  
                   1745: /**
1.23      daniel   1746:  * xmlNodeSetContent:
                   1747:  * @cur:  the node being modified
                   1748:  * @content:  the new value of the content
                   1749:  *
                   1750:  * Replace the content of a node.
1.1       veillard 1751:  */
1.28      daniel   1752: void
                   1753: xmlNodeSetContent(xmlNodePtr cur, const CHAR *content) {
1.1       veillard 1754:     if (cur == NULL) {
                   1755:         fprintf(stderr, "xmlNodeSetContent : node == NULL\n");
                   1756:        return;
                   1757:     }
1.28      daniel   1758:     switch (cur->type) {
                   1759:         case XML_DOCUMENT_FRAG_NODE:
                   1760:         case XML_ELEMENT_NODE:
                   1761:            if (cur->content != NULL) {
                   1762:                free(cur->content);
                   1763:                cur->content = NULL;
                   1764:            }
                   1765:            if (cur->childs != NULL) xmlFreeNode(cur->childs);
                   1766:            cur->childs = xmlStringGetNodeList(cur->doc, content);
1.34      daniel   1767:            UPDATE_LAST_CHILD(cur)
1.28      daniel   1768:            break;
                   1769:         case XML_ATTRIBUTE_NODE:
                   1770:            break;
                   1771:         case XML_TEXT_NODE:
                   1772:         case XML_CDATA_SECTION_NODE:
                   1773:         case XML_ENTITY_REF_NODE:
                   1774:         case XML_ENTITY_NODE:
                   1775:         case XML_PI_NODE:
                   1776:         case XML_COMMENT_NODE:
                   1777:            if (cur->content != NULL) free(cur->content);
                   1778:            if (cur->childs != NULL) xmlFreeNode(cur->childs);
1.32      daniel   1779:            cur->last = cur->childs = NULL;
1.28      daniel   1780:            if (content != NULL)
                   1781:                cur->content = xmlStrdup(content);
                   1782:            else 
                   1783:                cur->content = NULL;
                   1784:         case XML_DOCUMENT_NODE:
                   1785:         case XML_DOCUMENT_TYPE_NODE:
                   1786:            break;
                   1787:         case XML_NOTATION_NODE:
                   1788:            break;
                   1789:     }
1.1       veillard 1790: }
                   1791: 
1.23      daniel   1792: /**
                   1793:  * xmlNodeSetContentLen:
                   1794:  * @cur:  the node being modified
                   1795:  * @content:  the new value of the content
                   1796:  * @len:  the size of @content
                   1797:  *
                   1798:  * Replace the content of a node.
1.21      daniel   1799:  */
1.28      daniel   1800: void
                   1801: xmlNodeSetContentLen(xmlNodePtr cur, const CHAR *content, int len) {
1.21      daniel   1802:     if (cur == NULL) {
1.28      daniel   1803:         fprintf(stderr, "xmlNodeSetContentLen : node == NULL\n");
1.21      daniel   1804:        return;
                   1805:     }
1.28      daniel   1806:     switch (cur->type) {
                   1807:         case XML_DOCUMENT_FRAG_NODE:
                   1808:         case XML_ELEMENT_NODE:
                   1809:            if (cur->content != NULL) {
                   1810:                free(cur->content);
                   1811:                cur->content = NULL;
                   1812:            }
                   1813:            if (cur->childs != NULL) xmlFreeNode(cur->childs);
                   1814:            cur->childs = xmlStringLenGetNodeList(cur->doc, content, len);
1.34      daniel   1815:            UPDATE_LAST_CHILD(cur)
1.28      daniel   1816:            break;
                   1817:         case XML_ATTRIBUTE_NODE:
                   1818:            break;
                   1819:         case XML_TEXT_NODE:
                   1820:         case XML_CDATA_SECTION_NODE:
                   1821:         case XML_ENTITY_REF_NODE:
                   1822:         case XML_ENTITY_NODE:
                   1823:         case XML_PI_NODE:
                   1824:         case XML_COMMENT_NODE:
                   1825:            if (cur->content != NULL) free(cur->content);
                   1826:            if (cur->childs != NULL) xmlFreeNode(cur->childs);
1.32      daniel   1827:            cur->childs = cur->last = NULL;
1.28      daniel   1828:            if (content != NULL)
                   1829:                cur->content = xmlStrndup(content, len);
                   1830:            else 
                   1831:                cur->content = NULL;
                   1832:         case XML_DOCUMENT_NODE:
                   1833:         case XML_DOCUMENT_TYPE_NODE:
                   1834:            break;
                   1835:         case XML_NOTATION_NODE:
                   1836:            if (cur->content != NULL) free(cur->content);
1.32      daniel   1837:            if (cur->childs != NULL) xmlFreeNode(cur->childs);
                   1838:            cur->childs = cur->last = NULL;
1.28      daniel   1839:            if (content != NULL)
                   1840:                cur->content = xmlStrndup(content, len);
                   1841:            else 
                   1842:                cur->content = NULL;
                   1843:            break;
                   1844:     }
1.21      daniel   1845: }
                   1846: 
1.23      daniel   1847: /**
1.28      daniel   1848:  * xmlNodeAddContentLen:
1.23      daniel   1849:  * @cur:  the node being modified
                   1850:  * @content:  extra content
1.28      daniel   1851:  * @len:  the size of @content
1.23      daniel   1852:  * 
                   1853:  * Append the extra substring to the node content.
1.21      daniel   1854:  */
1.28      daniel   1855: void
                   1856: xmlNodeAddContentLen(xmlNodePtr cur, const CHAR *content, int len) {
1.21      daniel   1857:     if (cur == NULL) {
1.28      daniel   1858:         fprintf(stderr, "xmlNodeAddContentLen : node == NULL\n");
1.21      daniel   1859:        return;
                   1860:     }
1.28      daniel   1861:     if (len <= 0) return;
                   1862:     switch (cur->type) {
                   1863:         case XML_DOCUMENT_FRAG_NODE:
                   1864:         case XML_ELEMENT_NODE: {
                   1865:            xmlNodePtr last = NULL, new;
                   1866: 
                   1867:            if (cur->childs != NULL) {
1.32      daniel   1868:                last = cur->last;
1.28      daniel   1869:            } else {
                   1870:                if (cur->content != NULL) {
                   1871:                    cur->childs = xmlStringGetNodeList(cur->doc, cur->content);
1.34      daniel   1872:                    UPDATE_LAST_CHILD(cur)
1.28      daniel   1873:                    free(cur->content);
                   1874:                    cur->content = NULL;
1.32      daniel   1875:                    last = cur->last;
1.28      daniel   1876:                }
                   1877:            }
1.31      daniel   1878:            new = xmlNewTextLen(content, len);
1.28      daniel   1879:            if (new != NULL) {
                   1880:                xmlAddChild(cur, new);
1.32      daniel   1881:                if ((last != NULL) && (last->next == new)) {
1.28      daniel   1882:                    xmlTextMerge(last, new);
1.32      daniel   1883:                }
1.28      daniel   1884:            }
                   1885:            break;
                   1886:        }
                   1887:         case XML_ATTRIBUTE_NODE:
                   1888:            break;
                   1889:         case XML_TEXT_NODE:
                   1890:         case XML_CDATA_SECTION_NODE:
                   1891:         case XML_ENTITY_REF_NODE:
                   1892:         case XML_ENTITY_NODE:
                   1893:         case XML_PI_NODE:
                   1894:         case XML_COMMENT_NODE:
                   1895:            if (content != NULL)
                   1896:                cur->content = xmlStrncat(cur->content, content, len);
                   1897:         case XML_DOCUMENT_NODE:
                   1898:         case XML_DOCUMENT_TYPE_NODE:
                   1899:            break;
                   1900:         case XML_NOTATION_NODE:
                   1901:            if (content != NULL)
                   1902:                cur->content = xmlStrncat(cur->content, content, len);
                   1903:            break;
                   1904:     }
1.21      daniel   1905: }
                   1906: 
1.23      daniel   1907: /**
1.28      daniel   1908:  * xmlNodeAddContent:
1.23      daniel   1909:  * @cur:  the node being modified
                   1910:  * @content:  extra content
                   1911:  * 
                   1912:  * Append the extra substring to the node content.
1.21      daniel   1913:  */
1.28      daniel   1914: void
                   1915: xmlNodeAddContent(xmlNodePtr cur, const CHAR *content) {
                   1916:     int len;
                   1917: 
1.21      daniel   1918:     if (cur == NULL) {
                   1919:         fprintf(stderr, "xmlNodeAddContent : node == NULL\n");
                   1920:        return;
                   1921:     }
1.28      daniel   1922:     if (content == NULL) return;
                   1923:     len = xmlStrlen(content);
                   1924:     xmlNodeAddContentLen(cur, content, len);
                   1925: }
                   1926: 
                   1927: /**
                   1928:  * xmlTextMerge:
                   1929:  * @first:  the first text node
                   1930:  * @second:  the second text node being merged
                   1931:  * 
                   1932:  * Merge two text nodes into one
1.36      daniel   1933:  * Returns the first text node augmented
1.28      daniel   1934:  */
                   1935: xmlNodePtr
                   1936: xmlTextMerge(xmlNodePtr first, xmlNodePtr second) {
                   1937:     if (first == NULL) return(second);
                   1938:     if (second == NULL) return(first);
                   1939:     if (first->type != XML_TEXT_NODE) return(first);
                   1940:     if (second->type != XML_TEXT_NODE) return(first);
                   1941:     xmlNodeAddContent(first, second->content);
                   1942:     xmlUnlinkNode(second);
                   1943:     xmlFreeNode(second);
                   1944:     return(first);
1.21      daniel   1945: }
                   1946: 
1.23      daniel   1947: /**
                   1948:  * xmlSearchNs:
                   1949:  * @doc:  the document
                   1950:  * @node:  the current node
                   1951:  * @nameSpace:  the namespace string
                   1952:  *
1.16      daniel   1953:  * Search a Ns registered under a given name space for a document.
1.23      daniel   1954:  * recurse on the parents until it finds the defined namespace
                   1955:  * or return NULL otherwise.
                   1956:  * @nameSpace can be NULL, this is a search for the default namespace.
1.36      daniel   1957:  * Returns the namespace pointer or NULL.
1.3       veillard 1958:  */
1.28      daniel   1959: xmlNsPtr
                   1960: xmlSearchNs(xmlDocPtr doc, xmlNodePtr node, const CHAR *nameSpace) {
1.16      daniel   1961:     xmlNsPtr cur;
1.3       veillard 1962: 
1.19      daniel   1963:     while (node != NULL) {
                   1964:        cur = node->nsDef;
                   1965:        while (cur != NULL) {
                   1966:            if ((cur->prefix == NULL) && (nameSpace == NULL))
                   1967:                return(cur);
                   1968:            if ((cur->prefix != NULL) && (nameSpace != NULL) &&
                   1969:                (!xmlStrcmp(cur->prefix, nameSpace)))
                   1970:                return(cur);
                   1971:            cur = cur->next;
                   1972:        }
                   1973:        node = node->parent;
                   1974:     }
                   1975:     if (doc != NULL) {
                   1976:         cur = doc->oldNs;
                   1977:        while (cur != NULL) {
                   1978:            if ((cur->prefix != NULL) && (nameSpace != NULL) &&
                   1979:                (!xmlStrcmp(cur->prefix, nameSpace)))
                   1980:                return(cur);
                   1981:            cur = cur->next;
                   1982:        }
                   1983:     }
                   1984:     return(NULL);
                   1985: }
1.3       veillard 1986: 
1.23      daniel   1987: /**
                   1988:  * xmlSearchNsByHref:
                   1989:  * @doc:  the document
                   1990:  * @node:  the current node
                   1991:  * @href:  the namespace value
                   1992:  *
                   1993:  * Search a Ns aliasing a given URI. Recurse on the parents until it finds
                   1994:  * the defined namespace or return NULL otherwise.
1.36      daniel   1995:  * Returns the namespace pointer or NULL.
1.19      daniel   1996:  */
1.28      daniel   1997: xmlNsPtr
                   1998: xmlSearchNsByHref(xmlDocPtr doc, xmlNodePtr node, const CHAR *href) {
1.19      daniel   1999:     xmlNsPtr cur;
                   2000: 
                   2001:     while (node != NULL) {
                   2002:        cur = node->nsDef;
                   2003:        while (cur != NULL) {
                   2004:            if ((cur->href != NULL) && (href != NULL) &&
                   2005:                (!xmlStrcmp(cur->href, href)))
                   2006:                return(cur);
                   2007:            cur = cur->next;
                   2008:        }
                   2009:        node = node->parent;
                   2010:     }
                   2011:     if (doc != NULL) {
                   2012:         cur = doc->oldNs;
                   2013:        while (cur != NULL) {
                   2014:            if ((cur->href != NULL) && (href != NULL) &&
                   2015:                (!xmlStrcmp(cur->href, href)))
                   2016:                return(cur);
                   2017:            cur = cur->next;
                   2018:        }
1.3       veillard 2019:     }
                   2020:     return(NULL);
                   2021: }
                   2022: 
1.23      daniel   2023: /**
                   2024:  * xmlGetProp:
                   2025:  * @node:  the node
                   2026:  * @name:  the attribute name
                   2027:  *
                   2028:  * Search and get the value of an attribute associated to a node
                   2029:  * This does the entity substitution.
1.36      daniel   2030:  * Returns the attribute value or NULL if not found.
1.9       veillard 2031:  */
1.31      daniel   2032: CHAR *xmlGetProp(xmlNodePtr node, const CHAR *name) {
1.20      daniel   2033:     xmlAttrPtr prop = node->properties;
1.9       veillard 2034: 
                   2035:     while (prop != NULL) {
1.34      daniel   2036:         if (!xmlStrcmp(prop->name, name))  {
                   2037:            CHAR *ret;
                   2038: 
                   2039:            ret = xmlNodeListGetString(node->doc, prop->val, 1);
                   2040:            if (ret == NULL) return(xmlStrdup(""));
                   2041:            return(ret);
                   2042:         }
1.9       veillard 2043:        prop = prop->next;
                   2044:     }
1.10      veillard 2045:     return(NULL);
1.13      daniel   2046: }
                   2047: 
1.23      daniel   2048: /**
                   2049:  * xmlSetProp:
                   2050:  * @node:  the node
                   2051:  * @name:  the attribute name
                   2052:  * @value:  the attribute value
                   2053:  *
                   2054:  * Set (or reset) an attribute carried by a node.
1.36      daniel   2055:  * Returns the attribute pointer.
1.13      daniel   2056:  */
1.28      daniel   2057: xmlAttrPtr
                   2058: xmlSetProp(xmlNodePtr node, const CHAR *name, const CHAR *value) {
1.20      daniel   2059:     xmlAttrPtr prop = node->properties;
1.13      daniel   2060: 
                   2061:     while (prop != NULL) {
                   2062:         if (!xmlStrcmp(prop->name, name)) {
1.23      daniel   2063:            if (prop->val != NULL) 
                   2064:                xmlFreeNode(prop->val);
                   2065:            prop->val = NULL;
1.13      daniel   2066:            if (value != NULL)
1.24      daniel   2067:                prop->val = xmlStringGetNodeList(node->doc, value);
1.13      daniel   2068:            return(prop);
                   2069:        }
                   2070:        prop = prop->next;
                   2071:     }
                   2072:     prop = xmlNewProp(node, name, value);
                   2073:     return(prop);
1.9       veillard 2074: }
                   2075: 
1.23      daniel   2076: /**
                   2077:  * xmlNodeIsText:
                   2078:  * @node:  the node
                   2079:  * 
                   2080:  * Is this node a Text node ?
1.36      daniel   2081:  * Returns 1 yes, 0 no
1.21      daniel   2082:  */
1.28      daniel   2083: int
                   2084: xmlNodeIsText(xmlNodePtr node) {
1.21      daniel   2085:     if (node == NULL) return(0);
                   2086: 
1.23      daniel   2087:     if (node->type == XML_TEXT_NODE) return(1);
1.21      daniel   2088:     return(0);
                   2089: }
                   2090: 
1.23      daniel   2091: /**
1.36      daniel   2092:  * xmlTextConcat:
1.23      daniel   2093:  * @node:  the node
                   2094:  * @content:  the content
                   2095:  * @len:  @content lenght
                   2096:  * 
                   2097:  * Concat the given string at the end of the existing node content
1.21      daniel   2098:  */
1.23      daniel   2099: 
1.28      daniel   2100: void
                   2101: xmlTextConcat(xmlNodePtr node, const CHAR *content, int len) {
1.21      daniel   2102:     if (node == NULL) return;
                   2103: 
1.23      daniel   2104:     if (node->type != XML_TEXT_NODE) {
1.21      daniel   2105:        fprintf(stderr, "xmlTextConcat: node is not text\n");
                   2106:         return;
                   2107:     }
                   2108:     node->content = xmlStrncat(node->content, content, len);
                   2109: }
                   2110: 
1.1       veillard 2111: /************************************************************************
                   2112:  *                                                                     *
1.8       veillard 2113:  *                     Output : to a FILE or in memory                 *
1.1       veillard 2114:  *                                                                     *
                   2115:  ************************************************************************/
                   2116: 
1.38      daniel   2117: #define BASE_BUFFER_SIZE 4000
1.8       veillard 2118: 
1.23      daniel   2119: /**
1.38      daniel   2120:  * xmlBufferCreate:
                   2121:  *
                   2122:  * routine to create an XML buffer.
                   2123:  * returns the new structure.
                   2124:  */
                   2125: xmlBufferPtr
                   2126: xmlBufferCreate(void) {
                   2127:     xmlBufferPtr ret;
                   2128: 
                   2129:     ret = (xmlBufferPtr) malloc(sizeof(xmlBuffer));
                   2130:     if (ret == NULL) {
                   2131:        fprintf(stderr, "xmlBufferCreate : out of memory!\n");
                   2132:         return(NULL);
                   2133:     }
                   2134:     ret->use = 0;
                   2135:     ret->size = BASE_BUFFER_SIZE;
                   2136:     ret->content = (CHAR *) malloc(ret->size * sizeof(CHAR));
                   2137:     if (ret->content == NULL) {
                   2138:        fprintf(stderr, "xmlBufferCreate : out of memory!\n");
                   2139:        free(ret);
                   2140:         return(NULL);
                   2141:     }
                   2142:     ret->content[0] = 0;
                   2143:     return(ret);
                   2144: }
                   2145: 
                   2146: /**
                   2147:  * xmlBufferFree:
                   2148:  * @buf:  the buffer to free
                   2149:  *
                   2150:  * Frees an XML buffer.
                   2151:  */
                   2152: void
                   2153: xmlBufferFree(xmlBufferPtr buf) {
                   2154:     if (buf == NULL) {
                   2155:         fprintf(stderr, "xmlBufferFree: buf == NULL\n");
                   2156:        return;
                   2157:     }
                   2158:     if (buf->content == NULL) {
                   2159:         fprintf(stderr, "xmlBufferFree: buf->content == NULL\n");
                   2160:     } else {
                   2161:         memset(buf->content, -1, BASE_BUFFER_SIZE);
                   2162:         free(buf->content);
                   2163:     }
                   2164:     memset(buf, -1, sizeof(xmlBuffer));
                   2165:     free(buf);
                   2166: }
                   2167: 
                   2168: /**
                   2169:  * xmlBufferDump:
                   2170:  * @file:  the file output
                   2171:  * @buf:  the buffer to dump
                   2172:  *
                   2173:  * Dumps an XML buffer to  a FILE *.
                   2174:  * Returns the number of CHAR written
                   2175:  */
                   2176: int
                   2177: xmlBufferDump(FILE *file, xmlBufferPtr buf) {
                   2178:     int ret;
                   2179: 
                   2180:     if (buf == NULL) {
                   2181:         fprintf(stderr, "xmlBufferDump: buf == NULL\n");
                   2182:        return(0);
                   2183:     }
                   2184:     if (buf->content == NULL) {
                   2185:         fprintf(stderr, "xmlBufferDump: buf->content == NULL\n");
                   2186:        return(0);
                   2187:     }
                   2188:     if (file == NULL) file = stdout;
                   2189:     ret = fwrite(buf->content, sizeof(CHAR), buf->use, file);
                   2190:     return(ret);
                   2191: }
                   2192: 
                   2193: /**
                   2194:  * xmlBufferAdd:
                   2195:  * @buf:  the buffer to dump
                   2196:  * @str:  the CHAR string
                   2197:  * @len:  the number of CHAR to add
                   2198:  *
                   2199:  * Add a string range to an XML buffer.
                   2200:  */
                   2201: void
                   2202: xmlBufferAdd(xmlBufferPtr buf, const CHAR *str, int len) {
                   2203:     const CHAR *cur;
                   2204: 
                   2205:     if (str == NULL) {
                   2206:         fprintf(stderr, "xmlBufferAdd: str == NULL\n");
                   2207:        return;
                   2208:     }
                   2209:     for (cur = str;(len > 0) && (*cur != 0);cur++, len--) {
                   2210:         if (buf->use  + 10 >= buf->size) {
                   2211:            CHAR *rebuf;
                   2212: 
                   2213:            buf->size *= 2;
                   2214:            rebuf = (CHAR *) realloc(buf->content, buf->size * sizeof(CHAR));
                   2215:            if (rebuf == NULL) {
                   2216:                fprintf(stderr, "xmlBufferAdd : out of memory!\n");
                   2217:                return;
                   2218:            }
                   2219:            buf->content = rebuf;
                   2220:        }
                   2221:         buf->content[buf->use++] = *cur;
                   2222:     }
                   2223: }
                   2224: 
                   2225: /**
                   2226:  * xmlBufferCat:
                   2227:  * @buf:  the buffer to dump
                   2228:  * @str:  the CHAR string
1.23      daniel   2229:  *
1.38      daniel   2230:  * Append a zero terminated string to an XML buffer.
1.23      daniel   2231:  */
1.28      daniel   2232: void
1.38      daniel   2233: xmlBufferCat(xmlBufferPtr buf, const CHAR *str) {
1.8       veillard 2234:     const CHAR *cur;
                   2235: 
1.38      daniel   2236:     if (str == NULL) {
                   2237:         fprintf(stderr, "xmlBufferAdd: str == NULL\n");
                   2238:        return;
                   2239:     }
                   2240:     for (cur = str;*cur != 0;cur++) {
                   2241:         if (buf->use  + 10 >= buf->size) {
                   2242:            CHAR *rebuf;
                   2243: 
                   2244:            buf->size *= 2;
                   2245:            rebuf = (CHAR *) realloc(buf->content, buf->size * sizeof(CHAR));
                   2246:            if (rebuf == NULL) {
                   2247:                fprintf(stderr, "xmlBufferAdd : out of memory!\n");
                   2248:                return;
1.8       veillard 2249:            }
1.38      daniel   2250:            buf->content = rebuf;
1.8       veillard 2251:        }
1.38      daniel   2252:         buf->content[buf->use++] = *cur;
1.8       veillard 2253:     }
                   2254: }
                   2255: 
1.23      daniel   2256: /**
1.38      daniel   2257:  * xmlBufferCCat:
                   2258:  * @buf:  the buffer to dump
                   2259:  * @str:  the C char string
1.23      daniel   2260:  *
1.38      daniel   2261:  * Append a zero terminated C string to an XML buffer.
1.23      daniel   2262:  */
1.28      daniel   2263: void
1.38      daniel   2264: xmlBufferCCat(xmlBufferPtr buf, const char *str) {
1.21      daniel   2265:     const char *cur;
1.8       veillard 2266: 
1.38      daniel   2267:     if (str == NULL) {
                   2268:         fprintf(stderr, "xmlBufferAdd: str == NULL\n");
                   2269:        return;
                   2270:     }
                   2271:     for (cur = str;*cur != 0;cur++) {
                   2272:         if (buf->use  + 10 >= buf->size) {
                   2273:            CHAR *rebuf;
                   2274: 
                   2275:            buf->size *= 2;
                   2276:            rebuf = (CHAR *) realloc(buf->content, buf->size * sizeof(CHAR));
                   2277:            if (rebuf == NULL) {
                   2278:                fprintf(stderr, "xmlBufferAdd : out of memory!\n");
                   2279:                return;
1.8       veillard 2280:            }
1.38      daniel   2281:            buf->content = rebuf;
1.8       veillard 2282:        }
1.38      daniel   2283:         buf->content[buf->use++] = *cur;
1.8       veillard 2284:     }
                   2285: }
                   2286: 
1.23      daniel   2287: /**
1.38      daniel   2288:  * xmlBufferWriteCHAR:
                   2289:  * @buf:  the XML buffer
                   2290:  * @string:  the string to add
                   2291:  *
                   2292:  * routine which manage and grows an output buffer. This one add
                   2293:  * CHARs at the end of the buffer.
                   2294:  */
                   2295: void
                   2296: xmlBufferWriteCHAR(xmlBufferPtr buf, const CHAR *string) {
                   2297:     xmlBufferCat(buf, string);
                   2298: }
                   2299: 
                   2300: /**
                   2301:  * xmlBufferWriteChar:
1.42      daniel   2302:  * @buf:  the XML buffer output
1.38      daniel   2303:  * @string:  the string to add
                   2304:  *
                   2305:  * routine which manage and grows an output buffer. This one add
                   2306:  * C chars at the end of the array.
                   2307:  */
                   2308: void
                   2309: xmlBufferWriteChar(xmlBufferPtr buf, const char *string) {
                   2310:     xmlBufferCCat(buf, string);
                   2311: }
                   2312: 
                   2313: 
                   2314: /**
1.43      daniel   2315:  * xmlBufferWriteQuotedString:
                   2316:  * @buf:  the XML buffer output
                   2317:  * @string:  the string to add
                   2318:  *
                   2319:  * routine which manage and grows an output buffer. This one writes
                   2320:  * a quoted or double quoted CHAR string, checking first if it holds
                   2321:  * quote or double-quotes internally
                   2322:  */
                   2323: void
                   2324: xmlBufferWriteQuotedString(xmlBufferPtr buf, const CHAR *string) {
                   2325:     /*
                   2326:      * TODO: fix strchr by xmlStrchr to work coreectly on UTF-8 !!!
                   2327:      */
                   2328:     if (strchr(string, '"')) {
                   2329:         if (strchr(string, '\'')) {
                   2330:            fprintf(stderr,
                   2331:  "xmlBufferWriteQuotedString: string contains quote and double-quotes !\n");
                   2332:        }
                   2333:         xmlBufferCCat(buf, "'");
                   2334:         xmlBufferCat(buf, string);
                   2335:         xmlBufferCCat(buf, "'");
                   2336:     } else {
                   2337:         xmlBufferCCat(buf, "\"");
                   2338:         xmlBufferCat(buf, string);
                   2339:         xmlBufferCCat(buf, "\"");
                   2340:     }
                   2341: }
                   2342: 
                   2343: 
                   2344: /**
1.23      daniel   2345:  * xmlGlobalNsDump:
1.42      daniel   2346:  * @buf:  the XML buffer output
1.23      daniel   2347:  * @cur:  a namespace
                   2348:  *
                   2349:  * Dump a global Namespace, this is the old version based on PIs.
1.1       veillard 2350:  */
1.28      daniel   2351: static void
1.38      daniel   2352: xmlGlobalNsDump(xmlBufferPtr buf, xmlNsPtr cur) {
1.1       veillard 2353:     if (cur == NULL) {
1.19      daniel   2354:         fprintf(stderr, "xmlGlobalNsDump : Ns == NULL\n");
1.1       veillard 2355:        return;
                   2356:     }
1.19      daniel   2357:     if (cur->type == XML_GLOBAL_NAMESPACE) {
1.38      daniel   2358:        xmlBufferWriteChar(buf, "<?namespace");
1.12      daniel   2359:        if (cur->href != NULL) {
1.43      daniel   2360:            xmlBufferWriteChar(buf, " href=");
                   2361:            xmlBufferWriteQuotedString(buf, cur->href);
1.12      daniel   2362:        }
1.16      daniel   2363:        if (cur->prefix != NULL) {
1.43      daniel   2364:            xmlBufferWriteChar(buf, " AS=");
                   2365:            xmlBufferWriteQuotedString(buf, cur->prefix);
1.12      daniel   2366:        }
1.38      daniel   2367:        xmlBufferWriteChar(buf, "?>\n");
1.19      daniel   2368:     }
                   2369: }
                   2370: 
1.23      daniel   2371: /**
                   2372:  * xmlGlobalNsListDump:
1.42      daniel   2373:  * @buf:  the XML buffer output
1.23      daniel   2374:  * @cur:  the first namespace
                   2375:  *
                   2376:  * Dump a list of global Namespace, this is the old version based on PIs.
1.19      daniel   2377:  */
1.28      daniel   2378: static void
1.38      daniel   2379: xmlGlobalNsListDump(xmlBufferPtr buf, xmlNsPtr cur) {
1.19      daniel   2380:     while (cur != NULL) {
1.38      daniel   2381:         xmlGlobalNsDump(buf, cur);
1.19      daniel   2382:        cur = cur->next;
                   2383:     }
                   2384: }
                   2385: 
1.23      daniel   2386: /**
                   2387:  * xmlNsDump:
1.42      daniel   2388:  * @buf:  the XML buffer output
1.23      daniel   2389:  * @cur:  a namespace
                   2390:  *
1.19      daniel   2391:  * Dump a local Namespace definition.
1.23      daniel   2392:  * Should be called in the context of attributes dumps.
1.19      daniel   2393:  */
1.28      daniel   2394: static void
1.38      daniel   2395: xmlNsDump(xmlBufferPtr buf, xmlNsPtr cur) {
1.19      daniel   2396:     if (cur == NULL) {
                   2397:         fprintf(stderr, "xmlNsDump : Ns == NULL\n");
                   2398:        return;
                   2399:     }
                   2400:     if (cur->type == XML_LOCAL_NAMESPACE) {
                   2401:         /* Within the context of an element attributes */
1.16      daniel   2402:        if (cur->prefix != NULL) {
1.38      daniel   2403:            xmlBufferWriteChar(buf, " xmlns:");
                   2404:            xmlBufferWriteCHAR(buf, cur->prefix);
1.19      daniel   2405:        } else
1.38      daniel   2406:            xmlBufferWriteChar(buf, " xmlns");
1.43      daniel   2407:        xmlBufferWriteChar(buf, "=");
                   2408:        xmlBufferWriteQuotedString(buf, cur->href);
1.19      daniel   2409:     }
                   2410: }
                   2411: 
1.23      daniel   2412: /**
                   2413:  * xmlNsListDump:
1.42      daniel   2414:  * @buf:  the XML buffer output
1.23      daniel   2415:  * @cur:  the first namespace
                   2416:  *
                   2417:  * Dump a list of local Namespace definitions.
                   2418:  * Should be called in the context of attributes dumps.
1.19      daniel   2419:  */
1.28      daniel   2420: static void
1.38      daniel   2421: xmlNsListDump(xmlBufferPtr buf, xmlNsPtr cur) {
1.19      daniel   2422:     while (cur != NULL) {
1.38      daniel   2423:         xmlNsDump(buf, cur);
1.19      daniel   2424:        cur = cur->next;
1.8       veillard 2425:     }
1.1       veillard 2426: }
                   2427: 
1.23      daniel   2428: /**
                   2429:  * xmlDtdDump:
1.42      daniel   2430:  * @buf:  the XML buffer output
1.23      daniel   2431:  * @doc:  the document
                   2432:  * 
                   2433:  * Dump the XML document DTD, if any.
1.17      daniel   2434:  */
1.28      daniel   2435: static void
1.38      daniel   2436: xmlDtdDump(xmlBufferPtr buf, xmlDocPtr doc) {
1.31      daniel   2437:     xmlDtdPtr cur = doc->intSubset;
1.21      daniel   2438: 
1.17      daniel   2439:     if (cur == NULL) {
1.31      daniel   2440:         fprintf(stderr, "xmlDtdDump : no internal subset\n");
1.17      daniel   2441:        return;
                   2442:     }
1.38      daniel   2443:     xmlBufferWriteChar(buf, "<!DOCTYPE ");
                   2444:     xmlBufferWriteCHAR(buf, cur->name);
1.17      daniel   2445:     if (cur->ExternalID != NULL) {
1.43      daniel   2446:        xmlBufferWriteChar(buf, " PUBLIC ");
                   2447:        xmlBufferWriteQuotedString(buf, cur->ExternalID);
                   2448:        xmlBufferWriteChar(buf, " ");
                   2449:        xmlBufferWriteQuotedString(buf, cur->SystemID);
1.17      daniel   2450:     }  else if (cur->SystemID != NULL) {
1.43      daniel   2451:        xmlBufferWriteChar(buf, " SYSTEM ");
                   2452:        xmlBufferWriteQuotedString(buf, cur->SystemID);
1.17      daniel   2453:     }
1.34      daniel   2454:     if ((cur->entities == NULL) && (cur->elements == NULL) &&
1.35      daniel   2455:         (cur->attributes == NULL) && (cur->notations == NULL)) {
1.38      daniel   2456:        xmlBufferWriteChar(buf, ">\n");
1.21      daniel   2457:        return;
                   2458:     }
1.38      daniel   2459:     xmlBufferWriteChar(buf, " [\n");
1.21      daniel   2460:     if (cur->entities != NULL)
1.38      daniel   2461:        xmlDumpEntitiesTable(buf, (xmlEntitiesTablePtr) cur->entities);
1.35      daniel   2462:     if (cur->notations != NULL)
1.38      daniel   2463:        xmlDumpNotationTable(buf, (xmlNotationTablePtr) cur->notations);
1.33      daniel   2464:     if (cur->elements != NULL)
1.38      daniel   2465:        xmlDumpElementTable(buf, (xmlElementTablePtr) cur->elements);
1.34      daniel   2466:     if (cur->attributes != NULL)
1.38      daniel   2467:        xmlDumpAttributeTable(buf, (xmlAttributeTablePtr) cur->attributes);
                   2468:     xmlBufferWriteChar(buf, "]");
1.21      daniel   2469: 
1.17      daniel   2470:     /* TODO !!! a lot more things to dump ... */
1.38      daniel   2471:     xmlBufferWriteChar(buf, ">\n");
1.17      daniel   2472: }
                   2473: 
1.23      daniel   2474: /**
                   2475:  * xmlAttrDump:
1.42      daniel   2476:  * @buf:  the XML buffer output
1.23      daniel   2477:  * @doc:  the document
                   2478:  * @cur:  the attribute pointer
                   2479:  *
                   2480:  * Dump an XML attribute
1.1       veillard 2481:  */
1.28      daniel   2482: static void
1.38      daniel   2483: xmlAttrDump(xmlBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur) {
1.23      daniel   2484:     CHAR *value;
1.1       veillard 2485: 
                   2486:     if (cur == NULL) {
1.20      daniel   2487:         fprintf(stderr, "xmlAttrDump : property == NULL\n");
1.1       veillard 2488:        return;
                   2489:     }
1.38      daniel   2490:     xmlBufferWriteChar(buf, " ");
                   2491:     xmlBufferWriteCHAR(buf, cur->name);
1.24      daniel   2492:     value = xmlNodeListGetString(doc, cur->val, 0);
1.23      daniel   2493:     if (value) {
1.43      daniel   2494:        xmlBufferWriteChar(buf, "=");
                   2495:        xmlBufferWriteQuotedString(buf, value);
1.23      daniel   2496:        free(value);
1.34      daniel   2497:     } else  {
1.38      daniel   2498:        xmlBufferWriteChar(buf, "=\"\"");
1.3       veillard 2499:     }
1.8       veillard 2500: }
                   2501: 
1.23      daniel   2502: /**
                   2503:  * xmlAttrListDump:
1.42      daniel   2504:  * @buf:  the XML buffer output
1.23      daniel   2505:  * @doc:  the document
                   2506:  * @cur:  the first attribute pointer
                   2507:  *
                   2508:  * Dump a list of XML attributes
1.8       veillard 2509:  */
1.28      daniel   2510: static void
1.38      daniel   2511: xmlAttrListDump(xmlBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur) {
1.8       veillard 2512:     if (cur == NULL) {
1.20      daniel   2513:         fprintf(stderr, "xmlAttrListDump : property == NULL\n");
1.1       veillard 2514:        return;
                   2515:     }
1.8       veillard 2516:     while (cur != NULL) {
1.38      daniel   2517:         xmlAttrDump(buf, doc, cur);
1.8       veillard 2518:        cur = cur->next;
1.1       veillard 2519:     }
                   2520: }
                   2521: 
                   2522: 
1.28      daniel   2523: static void
1.38      daniel   2524: xmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level);
1.23      daniel   2525: /**
                   2526:  * xmlNodeListDump:
1.42      daniel   2527:  * @buf:  the XML buffer output
1.23      daniel   2528:  * @doc:  the document
                   2529:  * @cur:  the first node
                   2530:  * @level: the imbrication level for indenting
                   2531:  *
                   2532:  * Dump an XML node list, recursive behaviour,children are printed too.
                   2533:  */
1.28      daniel   2534: static void
1.38      daniel   2535: xmlNodeListDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level) {
1.25      daniel   2536:     int needIndent = 0, i;
                   2537: 
1.1       veillard 2538:     if (cur == NULL) {
1.8       veillard 2539:         fprintf(stderr, "xmlNodeListDump : node == NULL\n");
1.1       veillard 2540:        return;
                   2541:     }
1.8       veillard 2542:     while (cur != NULL) {
1.25      daniel   2543:         if ((cur->type != XML_TEXT_NODE) &&
                   2544:            (cur->type != XML_ENTITY_REF_NODE)) {
                   2545:            if (!needIndent) {
                   2546:                needIndent = 1;
1.38      daniel   2547:                xmlBufferWriteChar(buf, "\n");
1.25      daniel   2548:            }
                   2549:        }
1.38      daniel   2550:         xmlNodeDump(buf, doc, cur, level);
1.8       veillard 2551:        cur = cur->next;
1.3       veillard 2552:     }
1.25      daniel   2553:     if ((xmlIndentTreeOutput) && (needIndent))
                   2554:        for (i = 1;i < level;i++)
1.38      daniel   2555:            xmlBufferWriteChar(buf, "  ");
1.1       veillard 2556: }
                   2557: 
1.23      daniel   2558: /**
1.25      daniel   2559:  * xmlNodeDump:
1.42      daniel   2560:  * @buf:  the XML buffer output
1.23      daniel   2561:  * @doc:  the document
                   2562:  * @cur:  the current node
                   2563:  * @level: the imbrication level for indenting
                   2564:  *
                   2565:  * Dump an XML node, recursive behaviour,children are printed too.
1.1       veillard 2566:  */
1.28      daniel   2567: static void
1.38      daniel   2568: xmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level) {
1.8       veillard 2569:     int i;
                   2570: 
1.1       veillard 2571:     if (cur == NULL) {
1.8       veillard 2572:         fprintf(stderr, "xmlNodeDump : node == NULL\n");
                   2573:        return;
                   2574:     }
1.23      daniel   2575:     if (cur->type == XML_TEXT_NODE) {
1.45    ! daniel   2576:        if (cur->content != NULL) {
        !          2577:             CHAR *buffer;
        !          2578: 
        !          2579:             buffer = xmlEncodeEntities(doc, cur->content);
        !          2580:            if (buffer != NULL) {
        !          2581:                xmlBufferWriteCHAR(buf, buffer);
        !          2582:                free(buffer);
        !          2583:            }
        !          2584:        }
1.14      daniel   2585:        return;
                   2586:     }
1.23      daniel   2587:     if (cur->type == XML_COMMENT_NODE) {
1.14      daniel   2588:        if (cur->content != NULL) {
1.38      daniel   2589:            xmlBufferWriteChar(buf, "<!--");
                   2590:            xmlBufferWriteCHAR(buf, cur->content);
                   2591:            xmlBufferWriteChar(buf, "-->");
1.14      daniel   2592:        }
1.8       veillard 2593:        return;
                   2594:     }
1.23      daniel   2595:     if (cur->type == XML_ENTITY_REF_NODE) {
1.38      daniel   2596:         xmlBufferWriteChar(buf, "&");
                   2597:        xmlBufferWriteCHAR(buf, cur->name);
                   2598:         xmlBufferWriteChar(buf, ";");
1.23      daniel   2599:        return;
                   2600:     }
1.21      daniel   2601:     if (xmlIndentTreeOutput)
                   2602:        for (i = 0;i < level;i++)
1.38      daniel   2603:            xmlBufferWriteChar(buf, "  ");
1.8       veillard 2604: 
1.38      daniel   2605:     xmlBufferWriteChar(buf, "<");
1.16      daniel   2606:     if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
1.38      daniel   2607:         xmlBufferWriteCHAR(buf, cur->ns->prefix);
                   2608:        xmlBufferWriteChar(buf, ":");
1.8       veillard 2609:     }
                   2610: 
1.38      daniel   2611:     xmlBufferWriteCHAR(buf, cur->name);
1.19      daniel   2612:     if (cur->nsDef)
1.38      daniel   2613:         xmlNsListDump(buf, cur->nsDef);
1.8       veillard 2614:     if (cur->properties != NULL)
1.38      daniel   2615:         xmlAttrListDump(buf, doc, cur->properties);
1.8       veillard 2616: 
                   2617:     if ((cur->content == NULL) && (cur->childs == NULL)) {
1.38      daniel   2618:         xmlBufferWriteChar(buf, "/>\n");
1.1       veillard 2619:        return;
                   2620:     }
1.38      daniel   2621:     xmlBufferWriteChar(buf, ">");
1.8       veillard 2622:     if (cur->content != NULL)
1.38      daniel   2623:        xmlBufferWriteCHAR(buf, xmlEncodeEntities(doc, cur->content));
1.8       veillard 2624:     if (cur->childs != NULL) {
1.38      daniel   2625:        xmlNodeListDump(buf, doc, cur->childs, level + 1);
1.8       veillard 2626:     }
1.38      daniel   2627:     xmlBufferWriteChar(buf, "</");
1.16      daniel   2628:     if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
1.38      daniel   2629:         xmlBufferWriteCHAR(buf, cur->ns->prefix);
                   2630:        xmlBufferWriteChar(buf, ":");
1.1       veillard 2631:     }
1.8       veillard 2632: 
1.38      daniel   2633:     xmlBufferWriteCHAR(buf, cur->name);
                   2634:     xmlBufferWriteChar(buf, ">\n");
1.1       veillard 2635: }
                   2636: 
1.23      daniel   2637: /**
                   2638:  * xmlDocContentDump:
1.42      daniel   2639:  * @buf:  the XML buffer output
1.23      daniel   2640:  * @cur:  the document
                   2641:  *
                   2642:  * Dump an XML document.
1.1       veillard 2643:  */
1.28      daniel   2644: static void
1.38      daniel   2645: xmlDocContentDump(xmlBufferPtr buf, xmlDocPtr cur) {
1.12      daniel   2646:     if (oldXMLWDcompatibility)
1.43      daniel   2647:        xmlBufferWriteChar(buf, "<?XML version=");
1.12      daniel   2648:     else 
1.43      daniel   2649:        xmlBufferWriteChar(buf, "<?xml version=");
                   2650:     xmlBufferWriteQuotedString(buf, cur->version);
1.15      daniel   2651:     if (cur->encoding != NULL) {
1.43      daniel   2652:         xmlBufferWriteChar(buf, " encoding=");
                   2653:        xmlBufferWriteQuotedString(buf, cur->encoding);
1.15      daniel   2654:     }
                   2655:     switch (cur->standalone) {
                   2656:         case 0:
1.38      daniel   2657:            xmlBufferWriteChar(buf, " standalone=\"no\"");
1.15      daniel   2658:            break;
                   2659:         case 1:
1.38      daniel   2660:            xmlBufferWriteChar(buf, " standalone=\"yes\"");
1.15      daniel   2661:            break;
                   2662:     }
1.38      daniel   2663:     xmlBufferWriteChar(buf, "?>\n");
1.31      daniel   2664:     if (cur->intSubset != NULL)
1.38      daniel   2665:         xmlDtdDump(buf, cur);
1.19      daniel   2666:     if (cur->root != NULL) {
                   2667:        /* global namespace definitions, the old way */
                   2668:        if (oldXMLWDcompatibility)
1.38      daniel   2669:            xmlGlobalNsListDump(buf, cur->oldNs);
1.19      daniel   2670:        else 
                   2671:            xmlUpgradeOldNs(cur);
1.38      daniel   2672:         xmlNodeDump(buf, cur, cur->root, 0);
1.19      daniel   2673:     }
                   2674: }
                   2675: 
1.23      daniel   2676: /**
                   2677:  * xmlDocDumpMemory:
                   2678:  * @cur:  the document
                   2679:  * @mem:  OUT: the memory pointer
                   2680:  * @size:  OUT: the memory lenght
                   2681:  *
                   2682:  * Dump an XML document in memory and return the CHAR * and it's size.
                   2683:  * It's up to the caller to free the memory.
1.19      daniel   2684:  */
1.28      daniel   2685: void
                   2686: xmlDocDumpMemory(xmlDocPtr cur, CHAR**mem, int *size) {
1.38      daniel   2687:     xmlBufferPtr buf;
                   2688: 
1.19      daniel   2689:     if (cur == NULL) {
1.31      daniel   2690: #ifdef DEBUG_TREE
                   2691:         fprintf(stderr, "xmlDocDumpMemory : document == NULL\n");
                   2692: #endif
1.19      daniel   2693:        *mem = NULL;
                   2694:        *size = 0;
                   2695:        return;
                   2696:     }
1.38      daniel   2697:     buf = xmlBufferCreate();
                   2698:     if (buf == NULL) {
                   2699:        *mem = NULL;
                   2700:        *size = 0;
                   2701:        return;
                   2702:     }
                   2703:     xmlDocContentDump(buf, cur);
                   2704:     *mem = buf->content;
                   2705:     *size = buf->use;
                   2706:     memset(buf, -1, sizeof(xmlBuffer));
                   2707:     free(buf);
1.1       veillard 2708: }
                   2709: 
1.23      daniel   2710: /**
                   2711:  * xmlGetDocCompressMode:
                   2712:  * @doc:  the document
                   2713:  *
                   2714:  * get the compression ratio for a document, ZLIB based
1.36      daniel   2715:  * Returns 0 (uncompressed) to 9 (max compression)
1.23      daniel   2716:  */
1.28      daniel   2717: int
                   2718:  xmlGetDocCompressMode (xmlDocPtr doc) {
1.23      daniel   2719:     if (doc == NULL) return(-1);
                   2720:     return(doc->compression);
                   2721: }
                   2722: 
                   2723: /**
                   2724:  * xmlSetDocCompressMode:
                   2725:  * @doc:  the document
                   2726:  * @mode:  the compression ratio
                   2727:  *
                   2728:  * set the compression ratio for a document, ZLIB based
                   2729:  * Correct values: 0 (uncompressed) to 9 (max compression)
                   2730:  */
1.28      daniel   2731: void
                   2732: xmlSetDocCompressMode (xmlDocPtr doc, int mode) {
1.23      daniel   2733:     if (doc == NULL) return;
                   2734:     if (mode < 0) doc->compression = 0;
                   2735:     else if (mode > 9) doc->compression = 9;
                   2736:     else doc->compression = mode;
                   2737: }
                   2738: 
                   2739: /**
                   2740:  * xmlGetCompressMode:
                   2741:  *
                   2742:  * get the default compression mode used, ZLIB based.
1.36      daniel   2743:  * Returns 0 (uncompressed) to 9 (max compression)
1.23      daniel   2744:  */
1.28      daniel   2745: int
                   2746:  xmlGetCompressMode(void) {
1.23      daniel   2747:     return(xmlCompressMode);
                   2748: }
                   2749: 
                   2750: /**
                   2751:  * xmlSetCompressMode:
                   2752:  * @mode:  the compression ratio
                   2753:  *
                   2754:  * set the default compression mode used, ZLIB based
                   2755:  * Correct values: 0 (uncompressed) to 9 (max compression)
1.1       veillard 2756:  */
1.28      daniel   2757: void
                   2758: xmlSetCompressMode(int mode) {
1.23      daniel   2759:     if (mode < 0) xmlCompressMode = 0;
                   2760:     else if (mode > 9) xmlCompressMode = 9;
                   2761:     else xmlCompressMode = mode;
                   2762: }
1.1       veillard 2763: 
1.23      daniel   2764: /**
                   2765:  * xmlDocDump:
                   2766:  * @f:  the FILE*
                   2767:  * @cur:  the document
                   2768:  *
                   2769:  * Dump an XML document to an open FILE.
                   2770:  */
1.28      daniel   2771: void
                   2772: xmlDocDump(FILE *f, xmlDocPtr cur) {
1.38      daniel   2773:     xmlBufferPtr buf;
                   2774: 
1.1       veillard 2775:     if (cur == NULL) {
1.31      daniel   2776: #ifdef DEBUG_TREE
1.1       veillard 2777:         fprintf(stderr, "xmlDocDump : document == NULL\n");
1.31      daniel   2778: #endif
1.1       veillard 2779:        return;
                   2780:     }
1.38      daniel   2781:     buf = xmlBufferCreate();
                   2782:     if (buf == NULL) return;
                   2783:     xmlDocContentDump(buf, cur);
                   2784:     xmlBufferDump(f, buf);
                   2785:     xmlBufferFree(buf);
1.23      daniel   2786: }
                   2787: 
                   2788: /**
                   2789:  * xmlSaveFile:
                   2790:  * @filename:  the filename
                   2791:  * @cur:  the document
                   2792:  *
                   2793:  * Dump an XML document to a file. Will use compression if
                   2794:  * compiled in and enabled.
                   2795:  * returns: the number of file written or -1 in case of failure.
                   2796:  */
1.28      daniel   2797: int
                   2798: xmlSaveFile(const char *filename, xmlDocPtr cur) {
1.38      daniel   2799:     xmlBufferPtr buf;
1.23      daniel   2800: #ifdef HAVE_ZLIB_H
                   2801:     gzFile zoutput = NULL;
                   2802:     char mode[15];
                   2803: #endif
1.24      daniel   2804:     FILE *output = NULL;
1.23      daniel   2805:     int ret;
                   2806: 
1.38      daniel   2807:     /* 
                   2808:      * save the content to a temp buffer.
                   2809:      */
                   2810:     buf = xmlBufferCreate();
                   2811:     if (buf == NULL) return(0);
                   2812:     xmlDocContentDump(buf, cur);
                   2813: 
1.23      daniel   2814: #ifdef HAVE_ZLIB_H
                   2815:     if ((cur->compression > 0) && (cur->compression <= 9)) {
                   2816:         sprintf(mode, "w%d", cur->compression);
                   2817:        zoutput = gzopen(filename, mode);
                   2818:     }
                   2819:     if (zoutput == NULL) {
                   2820: #endif
                   2821:         output = fopen(filename, "w");
                   2822:        if (output == NULL) return(-1);
                   2823: #ifdef HAVE_ZLIB_H
                   2824:     }
                   2825: 
                   2826:     if (zoutput != NULL) {
1.38      daniel   2827:         ret = gzwrite(zoutput, buf->content, sizeof(CHAR) * buf->use);
1.23      daniel   2828:        gzclose(zoutput);
1.38      daniel   2829:     } else {
                   2830: #endif
                   2831:         ret = xmlBufferDump(output, buf);
                   2832:        fclose(output);
                   2833: #ifdef HAVE_ZLIB_H
1.23      daniel   2834:     }
                   2835: #endif
1.41      daniel   2836:     xmlBufferFree(buf);
1.23      daniel   2837:     return(ret * sizeof(CHAR));
1.1       veillard 2838: }
                   2839: 

Webmaster