Annotation of XML/tree.c, revision 1.34

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

Webmaster