Annotation of XML/tree.c, revision 1.54

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

Webmaster