Annotation of XML/tree.c, revision 1.57

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

Webmaster