Annotation of XML/tree.c, revision 1.64

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

Webmaster