Annotation of embedaddon/libxml2/tree.c, revision 1.1.1.3

1.1       misho       1: /*
                      2:  * tree.c : implementation of access function for an XML tree.
                      3:  *
                      4:  * References:
                      5:  *   XHTML 1.0 W3C REC: http://www.w3.org/TR/2002/REC-xhtml1-20020801/
                      6:  *
                      7:  * See Copyright for the status of this software.
                      8:  *
                      9:  * daniel@veillard.com
                     10:  *
                     11:  */
                     12: 
                     13: #define IN_LIBXML
                     14: #include "libxml.h"
                     15: 
                     16: #include <string.h> /* for memset() only ! */
                     17: #include <limits.h>
                     18: #ifdef HAVE_CTYPE_H
                     19: #include <ctype.h>
                     20: #endif
                     21: #ifdef HAVE_STDLIB_H
                     22: #include <stdlib.h>
                     23: #endif
                     24: #ifdef HAVE_ZLIB_H
                     25: #include <zlib.h>
                     26: #endif
                     27: 
                     28: #include <libxml/xmlmemory.h>
                     29: #include <libxml/tree.h>
                     30: #include <libxml/parser.h>
                     31: #include <libxml/uri.h>
                     32: #include <libxml/entities.h>
                     33: #include <libxml/valid.h>
                     34: #include <libxml/xmlerror.h>
                     35: #include <libxml/parserInternals.h>
                     36: #include <libxml/globals.h>
                     37: #ifdef LIBXML_HTML_ENABLED
                     38: #include <libxml/HTMLtree.h>
                     39: #endif
                     40: #ifdef LIBXML_DEBUG_ENABLED
                     41: #include <libxml/debugXML.h>
                     42: #endif
                     43: 
1.1.1.3 ! misho      44: #include "buf.h"
        !            45: #include "save.h"
        !            46: 
1.1       misho      47: int __xmlRegisterCallbacks = 0;
                     48: 
                     49: /************************************************************************
                     50:  *                                                                     *
                     51:  *             Forward declarations                                    *
                     52:  *                                                                     *
                     53:  ************************************************************************/
                     54: 
                     55: static xmlNsPtr
                     56: xmlNewReconciliedNs(xmlDocPtr doc, xmlNodePtr tree, xmlNsPtr ns);
                     57: 
                     58: static xmlChar* xmlGetPropNodeValueInternal(xmlAttrPtr prop);
                     59: 
                     60: /************************************************************************
                     61:  *                                                                     *
                     62:  *             Tree memory error handler                               *
                     63:  *                                                                     *
                     64:  ************************************************************************/
                     65: /**
                     66:  * xmlTreeErrMemory:
                     67:  * @extra:  extra informations
                     68:  *
                     69:  * Handle an out of memory condition
                     70:  */
                     71: static void
                     72: xmlTreeErrMemory(const char *extra)
                     73: {
                     74:     __xmlSimpleError(XML_FROM_TREE, XML_ERR_NO_MEMORY, NULL, NULL, extra);
                     75: }
                     76: 
                     77: /**
                     78:  * xmlTreeErr:
                     79:  * @code:  the error number
                     80:  * @extra:  extra informations
                     81:  *
                     82:  * Handle an out of memory condition
                     83:  */
                     84: static void
                     85: xmlTreeErr(int code, xmlNodePtr node, const char *extra)
                     86: {
                     87:     const char *msg = NULL;
                     88: 
                     89:     switch(code) {
                     90:         case XML_TREE_INVALID_HEX:
                     91:            msg = "invalid hexadecimal character value\n";
                     92:            break;
                     93:        case XML_TREE_INVALID_DEC:
                     94:            msg = "invalid decimal character value\n";
                     95:            break;
                     96:        case XML_TREE_UNTERMINATED_ENTITY:
                     97:            msg = "unterminated entity reference %15s\n";
                     98:            break;
                     99:        case XML_TREE_NOT_UTF8:
                    100:            msg = "string is not in UTF-8\n";
                    101:            break;
                    102:        default:
                    103:            msg = "unexpected error number\n";
                    104:     }
                    105:     __xmlSimpleError(XML_FROM_TREE, code, node, msg, extra);
                    106: }
                    107: 
                    108: /************************************************************************
                    109:  *                                                                     *
                    110:  *             A few static variables and macros                       *
                    111:  *                                                                     *
                    112:  ************************************************************************/
                    113: /* #undef xmlStringText */
                    114: const xmlChar xmlStringText[] = { 't', 'e', 'x', 't', 0 };
                    115: /* #undef xmlStringTextNoenc */
                    116: const xmlChar xmlStringTextNoenc[] =
                    117:               { 't', 'e', 'x', 't', 'n', 'o', 'e', 'n', 'c', 0 };
                    118: /* #undef xmlStringComment */
                    119: const xmlChar xmlStringComment[] = { 'c', 'o', 'm', 'm', 'e', 'n', 't', 0 };
                    120: 
                    121: static int xmlCompressMode = 0;
                    122: static int xmlCheckDTD = 1;
                    123: 
                    124: #define UPDATE_LAST_CHILD_AND_PARENT(n) if ((n) != NULL) {             \
                    125:     xmlNodePtr ulccur = (n)->children;                                 \
                    126:     if (ulccur == NULL) {                                              \
                    127:         (n)->last = NULL;                                              \
                    128:     } else {                                                           \
                    129:         while (ulccur->next != NULL) {                                 \
                    130:                ulccur->parent = (n);                                   \
                    131:                ulccur = ulccur->next;                                  \
                    132:        }                                                               \
                    133:        ulccur->parent = (n);                                           \
                    134:        (n)->last = ulccur;                                             \
                    135: }}
                    136: 
                    137: #define IS_STR_XML(str) ((str != NULL) && (str[0] == 'x') && \
                    138:   (str[1] == 'm') && (str[2] == 'l') && (str[3] == 0))
                    139: 
                    140: /* #define DEBUG_BUFFER */
                    141: /* #define DEBUG_TREE */
                    142: 
                    143: /************************************************************************
                    144:  *                                                                     *
                    145:  *             Functions to move to entities.c once the                *
                    146:  *             API freeze is smoothen and they can be made public.     *
                    147:  *                                                                     *
                    148:  ************************************************************************/
                    149: #include <libxml/hash.h>
                    150: 
                    151: #ifdef LIBXML_TREE_ENABLED
                    152: /**
                    153:  * xmlGetEntityFromDtd:
                    154:  * @dtd:  A pointer to the DTD to search
                    155:  * @name:  The entity name
                    156:  *
                    157:  * Do an entity lookup in the DTD entity hash table and
                    158:  * return the corresponding entity, if found.
                    159:  *
                    160:  * Returns A pointer to the entity structure or NULL if not found.
                    161:  */
                    162: static xmlEntityPtr
                    163: xmlGetEntityFromDtd(xmlDtdPtr dtd, const xmlChar *name) {
                    164:     xmlEntitiesTablePtr table;
                    165: 
                    166:     if((dtd != NULL) && (dtd->entities != NULL)) {
                    167:        table = (xmlEntitiesTablePtr) dtd->entities;
                    168:        return((xmlEntityPtr) xmlHashLookup(table, name));
                    169:        /* return(xmlGetEntityFromTable(table, name)); */
                    170:     }
                    171:     return(NULL);
                    172: }
                    173: /**
                    174:  * xmlGetParameterEntityFromDtd:
                    175:  * @dtd:  A pointer to the DTD to search
                    176:  * @name:  The entity name
                    177:  *
                    178:  * Do an entity lookup in the DTD pararmeter entity hash table and
                    179:  * return the corresponding entity, if found.
                    180:  *
                    181:  * Returns A pointer to the entity structure or NULL if not found.
                    182:  */
                    183: static xmlEntityPtr
                    184: xmlGetParameterEntityFromDtd(xmlDtdPtr dtd, const xmlChar *name) {
                    185:     xmlEntitiesTablePtr table;
                    186: 
                    187:     if ((dtd != NULL) && (dtd->pentities != NULL)) {
                    188:        table = (xmlEntitiesTablePtr) dtd->pentities;
                    189:        return((xmlEntityPtr) xmlHashLookup(table, name));
                    190:        /* return(xmlGetEntityFromTable(table, name)); */
                    191:     }
                    192:     return(NULL);
                    193: }
                    194: #endif /* LIBXML_TREE_ENABLED */
                    195: 
                    196: /************************************************************************
                    197:  *                                                                     *
                    198:  *                     QName handling helper                           *
                    199:  *                                                                     *
                    200:  ************************************************************************/
                    201: 
                    202: /**
                    203:  * xmlBuildQName:
                    204:  * @ncname:  the Name
                    205:  * @prefix:  the prefix
                    206:  * @memory:  preallocated memory
                    207:  * @len:  preallocated memory length
                    208:  *
                    209:  * Builds the QName @prefix:@ncname in @memory if there is enough space
                    210:  * and prefix is not NULL nor empty, otherwise allocate a new string.
                    211:  * If prefix is NULL or empty it returns ncname.
                    212:  *
                    213:  * Returns the new string which must be freed by the caller if different from
                    214:  *         @memory and @ncname or NULL in case of error
                    215:  */
                    216: xmlChar *
                    217: xmlBuildQName(const xmlChar *ncname, const xmlChar *prefix,
                    218:              xmlChar *memory, int len) {
                    219:     int lenn, lenp;
                    220:     xmlChar *ret;
                    221: 
                    222:     if (ncname == NULL) return(NULL);
                    223:     if (prefix == NULL) return((xmlChar *) ncname);
                    224: 
                    225:     lenn = strlen((char *) ncname);
                    226:     lenp = strlen((char *) prefix);
                    227: 
                    228:     if ((memory == NULL) || (len < lenn + lenp + 2)) {
                    229:        ret = (xmlChar *) xmlMallocAtomic(lenn + lenp + 2);
                    230:        if (ret == NULL) {
                    231:            xmlTreeErrMemory("building QName");
                    232:            return(NULL);
                    233:        }
                    234:     } else {
                    235:        ret = memory;
                    236:     }
                    237:     memcpy(&ret[0], prefix, lenp);
                    238:     ret[lenp] = ':';
                    239:     memcpy(&ret[lenp + 1], ncname, lenn);
                    240:     ret[lenn + lenp + 1] = 0;
                    241:     return(ret);
                    242: }
                    243: 
                    244: /**
                    245:  * xmlSplitQName2:
                    246:  * @name:  the full QName
                    247:  * @prefix:  a xmlChar **
                    248:  *
                    249:  * parse an XML qualified name string
                    250:  *
                    251:  * [NS 5] QName ::= (Prefix ':')? LocalPart
                    252:  *
                    253:  * [NS 6] Prefix ::= NCName
                    254:  *
                    255:  * [NS 7] LocalPart ::= NCName
                    256:  *
                    257:  * Returns NULL if not a QName, otherwise the local part, and prefix
                    258:  *   is updated to get the Prefix if any.
                    259:  */
                    260: 
                    261: xmlChar *
                    262: xmlSplitQName2(const xmlChar *name, xmlChar **prefix) {
                    263:     int len = 0;
                    264:     xmlChar *ret = NULL;
                    265: 
                    266:     if (prefix == NULL) return(NULL);
                    267:     *prefix = NULL;
                    268:     if (name == NULL) return(NULL);
                    269: 
                    270: #ifndef XML_XML_NAMESPACE
                    271:     /* xml: prefix is not really a namespace */
                    272:     if ((name[0] == 'x') && (name[1] == 'm') &&
                    273:         (name[2] == 'l') && (name[3] == ':'))
                    274:        return(NULL);
                    275: #endif
                    276: 
                    277:     /* nasty but valid */
                    278:     if (name[0] == ':')
                    279:        return(NULL);
                    280: 
                    281:     /*
                    282:      * we are not trying to validate but just to cut, and yes it will
                    283:      * work even if this is as set of UTF-8 encoded chars
                    284:      */
                    285:     while ((name[len] != 0) && (name[len] != ':'))
                    286:        len++;
                    287: 
                    288:     if (name[len] == 0)
                    289:        return(NULL);
                    290: 
                    291:     *prefix = xmlStrndup(name, len);
                    292:     if (*prefix == NULL) {
                    293:        xmlTreeErrMemory("QName split");
                    294:        return(NULL);
                    295:     }
                    296:     ret = xmlStrdup(&name[len + 1]);
                    297:     if (ret == NULL) {
                    298:        xmlTreeErrMemory("QName split");
                    299:        if (*prefix != NULL) {
                    300:            xmlFree(*prefix);
                    301:            *prefix = NULL;
                    302:        }
                    303:        return(NULL);
                    304:     }
                    305: 
                    306:     return(ret);
                    307: }
                    308: 
                    309: /**
                    310:  * xmlSplitQName3:
                    311:  * @name:  the full QName
                    312:  * @len: an int *
                    313:  *
                    314:  * parse an XML qualified name string,i
                    315:  *
                    316:  * returns NULL if it is not a Qualified Name, otherwise, update len
1.1.1.3 ! misho     317:  *         with the length in byte of the prefix and return a pointer
1.1       misho     318:  *         to the start of the name without the prefix
                    319:  */
                    320: 
                    321: const xmlChar *
                    322: xmlSplitQName3(const xmlChar *name, int *len) {
                    323:     int l = 0;
                    324: 
                    325:     if (name == NULL) return(NULL);
                    326:     if (len == NULL) return(NULL);
                    327: 
                    328:     /* nasty but valid */
                    329:     if (name[0] == ':')
                    330:        return(NULL);
                    331: 
                    332:     /*
                    333:      * we are not trying to validate but just to cut, and yes it will
                    334:      * work even if this is as set of UTF-8 encoded chars
                    335:      */
                    336:     while ((name[l] != 0) && (name[l] != ':'))
                    337:        l++;
                    338: 
                    339:     if (name[l] == 0)
                    340:        return(NULL);
                    341: 
                    342:     *len = l;
                    343: 
                    344:     return(&name[l+1]);
                    345: }
                    346: 
                    347: /************************************************************************
                    348:  *                                                                     *
                    349:  *             Check Name, NCName and QName strings                    *
                    350:  *                                                                     *
                    351:  ************************************************************************/
                    352: 
                    353: #define CUR_SCHAR(s, l) xmlStringCurrentChar(NULL, s, &l)
                    354: 
                    355: #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XPATH_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) || defined(LIBXML_DEBUG_ENABLED) || defined (LIBXML_HTML_ENABLED) || defined(LIBXML_SAX1_ENABLED) || defined(LIBXML_HTML_ENABLED) || defined(LIBXML_WRITER_ENABLED) || defined(LIBXML_DOCB_ENABLED)
                    356: /**
                    357:  * xmlValidateNCName:
                    358:  * @value: the value to check
                    359:  * @space: allow spaces in front and end of the string
                    360:  *
                    361:  * Check that a value conforms to the lexical space of NCName
                    362:  *
                    363:  * Returns 0 if this validates, a positive error code number otherwise
                    364:  *         and -1 in case of internal or API error.
                    365:  */
                    366: int
                    367: xmlValidateNCName(const xmlChar *value, int space) {
                    368:     const xmlChar *cur = value;
                    369:     int c,l;
                    370: 
                    371:     if (value == NULL)
                    372:         return(-1);
                    373: 
                    374:     /*
                    375:      * First quick algorithm for ASCII range
                    376:      */
                    377:     if (space)
                    378:        while (IS_BLANK_CH(*cur)) cur++;
                    379:     if (((*cur >= 'a') && (*cur <= 'z')) || ((*cur >= 'A') && (*cur <= 'Z')) ||
                    380:        (*cur == '_'))
                    381:        cur++;
                    382:     else
                    383:        goto try_complex;
                    384:     while (((*cur >= 'a') && (*cur <= 'z')) ||
                    385:           ((*cur >= 'A') && (*cur <= 'Z')) ||
                    386:           ((*cur >= '0') && (*cur <= '9')) ||
                    387:           (*cur == '_') || (*cur == '-') || (*cur == '.'))
                    388:        cur++;
                    389:     if (space)
                    390:        while (IS_BLANK_CH(*cur)) cur++;
                    391:     if (*cur == 0)
                    392:        return(0);
                    393: 
                    394: try_complex:
                    395:     /*
                    396:      * Second check for chars outside the ASCII range
                    397:      */
                    398:     cur = value;
                    399:     c = CUR_SCHAR(cur, l);
                    400:     if (space) {
                    401:        while (IS_BLANK(c)) {
                    402:            cur += l;
                    403:            c = CUR_SCHAR(cur, l);
                    404:        }
                    405:     }
                    406:     if ((!IS_LETTER(c)) && (c != '_'))
                    407:        return(1);
                    408:     cur += l;
                    409:     c = CUR_SCHAR(cur, l);
                    410:     while (IS_LETTER(c) || IS_DIGIT(c) || (c == '.') ||
                    411:           (c == '-') || (c == '_') || IS_COMBINING(c) ||
                    412:           IS_EXTENDER(c)) {
                    413:        cur += l;
                    414:        c = CUR_SCHAR(cur, l);
                    415:     }
                    416:     if (space) {
                    417:        while (IS_BLANK(c)) {
                    418:            cur += l;
                    419:            c = CUR_SCHAR(cur, l);
                    420:        }
                    421:     }
                    422:     if (c != 0)
                    423:        return(1);
                    424: 
                    425:     return(0);
                    426: }
                    427: #endif
                    428: 
                    429: #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
                    430: /**
                    431:  * xmlValidateQName:
                    432:  * @value: the value to check
                    433:  * @space: allow spaces in front and end of the string
                    434:  *
                    435:  * Check that a value conforms to the lexical space of QName
                    436:  *
                    437:  * Returns 0 if this validates, a positive error code number otherwise
                    438:  *         and -1 in case of internal or API error.
                    439:  */
                    440: int
                    441: xmlValidateQName(const xmlChar *value, int space) {
                    442:     const xmlChar *cur = value;
                    443:     int c,l;
                    444: 
                    445:     if (value == NULL)
                    446:         return(-1);
                    447:     /*
                    448:      * First quick algorithm for ASCII range
                    449:      */
                    450:     if (space)
                    451:        while (IS_BLANK_CH(*cur)) cur++;
                    452:     if (((*cur >= 'a') && (*cur <= 'z')) || ((*cur >= 'A') && (*cur <= 'Z')) ||
                    453:        (*cur == '_'))
                    454:        cur++;
                    455:     else
                    456:        goto try_complex;
                    457:     while (((*cur >= 'a') && (*cur <= 'z')) ||
                    458:           ((*cur >= 'A') && (*cur <= 'Z')) ||
                    459:           ((*cur >= '0') && (*cur <= '9')) ||
                    460:           (*cur == '_') || (*cur == '-') || (*cur == '.'))
                    461:        cur++;
                    462:     if (*cur == ':') {
                    463:        cur++;
                    464:        if (((*cur >= 'a') && (*cur <= 'z')) ||
                    465:            ((*cur >= 'A') && (*cur <= 'Z')) ||
                    466:            (*cur == '_'))
                    467:            cur++;
                    468:        else
                    469:            goto try_complex;
                    470:        while (((*cur >= 'a') && (*cur <= 'z')) ||
                    471:               ((*cur >= 'A') && (*cur <= 'Z')) ||
                    472:               ((*cur >= '0') && (*cur <= '9')) ||
                    473:               (*cur == '_') || (*cur == '-') || (*cur == '.'))
                    474:            cur++;
                    475:     }
                    476:     if (space)
                    477:        while (IS_BLANK_CH(*cur)) cur++;
                    478:     if (*cur == 0)
                    479:        return(0);
                    480: 
                    481: try_complex:
                    482:     /*
                    483:      * Second check for chars outside the ASCII range
                    484:      */
                    485:     cur = value;
                    486:     c = CUR_SCHAR(cur, l);
                    487:     if (space) {
                    488:        while (IS_BLANK(c)) {
                    489:            cur += l;
                    490:            c = CUR_SCHAR(cur, l);
                    491:        }
                    492:     }
                    493:     if ((!IS_LETTER(c)) && (c != '_'))
                    494:        return(1);
                    495:     cur += l;
                    496:     c = CUR_SCHAR(cur, l);
                    497:     while (IS_LETTER(c) || IS_DIGIT(c) || (c == '.') ||
                    498:           (c == '-') || (c == '_') || IS_COMBINING(c) ||
                    499:           IS_EXTENDER(c)) {
                    500:        cur += l;
                    501:        c = CUR_SCHAR(cur, l);
                    502:     }
                    503:     if (c == ':') {
                    504:        cur += l;
                    505:        c = CUR_SCHAR(cur, l);
                    506:        if ((!IS_LETTER(c)) && (c != '_'))
                    507:            return(1);
                    508:        cur += l;
                    509:        c = CUR_SCHAR(cur, l);
                    510:        while (IS_LETTER(c) || IS_DIGIT(c) || (c == '.') ||
                    511:               (c == '-') || (c == '_') || IS_COMBINING(c) ||
                    512:               IS_EXTENDER(c)) {
                    513:            cur += l;
                    514:            c = CUR_SCHAR(cur, l);
                    515:        }
                    516:     }
                    517:     if (space) {
                    518:        while (IS_BLANK(c)) {
                    519:            cur += l;
                    520:            c = CUR_SCHAR(cur, l);
                    521:        }
                    522:     }
                    523:     if (c != 0)
                    524:        return(1);
                    525:     return(0);
                    526: }
                    527: 
                    528: /**
                    529:  * xmlValidateName:
                    530:  * @value: the value to check
                    531:  * @space: allow spaces in front and end of the string
                    532:  *
                    533:  * Check that a value conforms to the lexical space of Name
                    534:  *
                    535:  * Returns 0 if this validates, a positive error code number otherwise
                    536:  *         and -1 in case of internal or API error.
                    537:  */
                    538: int
                    539: xmlValidateName(const xmlChar *value, int space) {
                    540:     const xmlChar *cur = value;
                    541:     int c,l;
                    542: 
                    543:     if (value == NULL)
                    544:         return(-1);
                    545:     /*
                    546:      * First quick algorithm for ASCII range
                    547:      */
                    548:     if (space)
                    549:        while (IS_BLANK_CH(*cur)) cur++;
                    550:     if (((*cur >= 'a') && (*cur <= 'z')) || ((*cur >= 'A') && (*cur <= 'Z')) ||
                    551:        (*cur == '_') || (*cur == ':'))
                    552:        cur++;
                    553:     else
                    554:        goto try_complex;
                    555:     while (((*cur >= 'a') && (*cur <= 'z')) ||
                    556:           ((*cur >= 'A') && (*cur <= 'Z')) ||
                    557:           ((*cur >= '0') && (*cur <= '9')) ||
                    558:           (*cur == '_') || (*cur == '-') || (*cur == '.') || (*cur == ':'))
                    559:        cur++;
                    560:     if (space)
                    561:        while (IS_BLANK_CH(*cur)) cur++;
                    562:     if (*cur == 0)
                    563:        return(0);
                    564: 
                    565: try_complex:
                    566:     /*
                    567:      * Second check for chars outside the ASCII range
                    568:      */
                    569:     cur = value;
                    570:     c = CUR_SCHAR(cur, l);
                    571:     if (space) {
                    572:        while (IS_BLANK(c)) {
                    573:            cur += l;
                    574:            c = CUR_SCHAR(cur, l);
                    575:        }
                    576:     }
                    577:     if ((!IS_LETTER(c)) && (c != '_') && (c != ':'))
                    578:        return(1);
                    579:     cur += l;
                    580:     c = CUR_SCHAR(cur, l);
                    581:     while (IS_LETTER(c) || IS_DIGIT(c) || (c == '.') || (c == ':') ||
                    582:           (c == '-') || (c == '_') || IS_COMBINING(c) || IS_EXTENDER(c)) {
                    583:        cur += l;
                    584:        c = CUR_SCHAR(cur, l);
                    585:     }
                    586:     if (space) {
                    587:        while (IS_BLANK(c)) {
                    588:            cur += l;
                    589:            c = CUR_SCHAR(cur, l);
                    590:        }
                    591:     }
                    592:     if (c != 0)
                    593:        return(1);
                    594:     return(0);
                    595: }
                    596: 
                    597: /**
                    598:  * xmlValidateNMToken:
                    599:  * @value: the value to check
                    600:  * @space: allow spaces in front and end of the string
                    601:  *
                    602:  * Check that a value conforms to the lexical space of NMToken
                    603:  *
                    604:  * Returns 0 if this validates, a positive error code number otherwise
                    605:  *         and -1 in case of internal or API error.
                    606:  */
                    607: int
                    608: xmlValidateNMToken(const xmlChar *value, int space) {
                    609:     const xmlChar *cur = value;
                    610:     int c,l;
                    611: 
                    612:     if (value == NULL)
                    613:         return(-1);
                    614:     /*
                    615:      * First quick algorithm for ASCII range
                    616:      */
                    617:     if (space)
                    618:        while (IS_BLANK_CH(*cur)) cur++;
                    619:     if (((*cur >= 'a') && (*cur <= 'z')) ||
                    620:         ((*cur >= 'A') && (*cur <= 'Z')) ||
                    621:         ((*cur >= '0') && (*cur <= '9')) ||
                    622:         (*cur == '_') || (*cur == '-') || (*cur == '.') || (*cur == ':'))
                    623:        cur++;
                    624:     else
                    625:        goto try_complex;
                    626:     while (((*cur >= 'a') && (*cur <= 'z')) ||
                    627:           ((*cur >= 'A') && (*cur <= 'Z')) ||
                    628:           ((*cur >= '0') && (*cur <= '9')) ||
                    629:           (*cur == '_') || (*cur == '-') || (*cur == '.') || (*cur == ':'))
                    630:        cur++;
                    631:     if (space)
                    632:        while (IS_BLANK_CH(*cur)) cur++;
                    633:     if (*cur == 0)
                    634:        return(0);
                    635: 
                    636: try_complex:
                    637:     /*
                    638:      * Second check for chars outside the ASCII range
                    639:      */
                    640:     cur = value;
                    641:     c = CUR_SCHAR(cur, l);
                    642:     if (space) {
                    643:        while (IS_BLANK(c)) {
                    644:            cur += l;
                    645:            c = CUR_SCHAR(cur, l);
                    646:        }
                    647:     }
                    648:     if (!(IS_LETTER(c) || IS_DIGIT(c) || (c == '.') || (c == ':') ||
                    649:         (c == '-') || (c == '_') || IS_COMBINING(c) || IS_EXTENDER(c)))
                    650:        return(1);
                    651:     cur += l;
                    652:     c = CUR_SCHAR(cur, l);
                    653:     while (IS_LETTER(c) || IS_DIGIT(c) || (c == '.') || (c == ':') ||
                    654:           (c == '-') || (c == '_') || IS_COMBINING(c) || IS_EXTENDER(c)) {
                    655:        cur += l;
                    656:        c = CUR_SCHAR(cur, l);
                    657:     }
                    658:     if (space) {
                    659:        while (IS_BLANK(c)) {
                    660:            cur += l;
                    661:            c = CUR_SCHAR(cur, l);
                    662:        }
                    663:     }
                    664:     if (c != 0)
                    665:        return(1);
                    666:     return(0);
                    667: }
                    668: #endif /* LIBXML_TREE_ENABLED */
                    669: 
                    670: /************************************************************************
                    671:  *                                                                     *
                    672:  *             Allocation and deallocation of basic structures         *
                    673:  *                                                                     *
                    674:  ************************************************************************/
                    675: 
                    676: /**
                    677:  * xmlSetBufferAllocationScheme:
                    678:  * @scheme:  allocation method to use
                    679:  *
                    680:  * Set the buffer allocation method.  Types are
                    681:  * XML_BUFFER_ALLOC_EXACT - use exact sizes, keeps memory usage down
                    682:  * XML_BUFFER_ALLOC_DOUBLEIT - double buffer when extra needed,
                    683:  *                             improves performance
                    684:  */
                    685: void
                    686: xmlSetBufferAllocationScheme(xmlBufferAllocationScheme scheme) {
                    687:     if ((scheme == XML_BUFFER_ALLOC_EXACT) ||
1.1.1.2   misho     688:         (scheme == XML_BUFFER_ALLOC_DOUBLEIT) ||
                    689:         (scheme == XML_BUFFER_ALLOC_HYBRID))
1.1       misho     690:        xmlBufferAllocScheme = scheme;
                    691: }
                    692: 
                    693: /**
                    694:  * xmlGetBufferAllocationScheme:
                    695:  *
                    696:  * Types are
                    697:  * XML_BUFFER_ALLOC_EXACT - use exact sizes, keeps memory usage down
                    698:  * XML_BUFFER_ALLOC_DOUBLEIT - double buffer when extra needed,
                    699:  *                             improves performance
1.1.1.2   misho     700:  * XML_BUFFER_ALLOC_HYBRID - use exact sizes on small strings to keep memory usage tight
                    701:  *                            in normal usage, and doubleit on large strings to avoid
                    702:  *                            pathological performance.
1.1       misho     703:  *
                    704:  * Returns the current allocation scheme
                    705:  */
                    706: xmlBufferAllocationScheme
                    707: xmlGetBufferAllocationScheme(void) {
                    708:     return(xmlBufferAllocScheme);
                    709: }
                    710: 
                    711: /**
                    712:  * xmlNewNs:
                    713:  * @node:  the element carrying the namespace
                    714:  * @href:  the URI associated
                    715:  * @prefix:  the prefix for the namespace
                    716:  *
                    717:  * Creation of a new Namespace. This function will refuse to create
                    718:  * a namespace with a similar prefix than an existing one present on this
                    719:  * node.
                    720:  * We use href==NULL in the case of an element creation where the namespace
                    721:  * was not defined.
                    722:  * Returns a new namespace pointer or NULL
                    723:  */
                    724: xmlNsPtr
                    725: xmlNewNs(xmlNodePtr node, const xmlChar *href, const xmlChar *prefix) {
                    726:     xmlNsPtr cur;
                    727: 
                    728:     if ((node != NULL) && (node->type != XML_ELEMENT_NODE))
                    729:        return(NULL);
                    730: 
                    731:     if ((prefix != NULL) && (xmlStrEqual(prefix, BAD_CAST "xml"))) {
                    732:         /* xml namespace is predefined, no need to add it */
                    733:         if (xmlStrEqual(href, XML_XML_NAMESPACE))
                    734:             return(NULL);
                    735: 
                    736:         /*
                    737:          * Problem, this is an attempt to bind xml prefix to a wrong
                    738:          * namespace, which breaks
                    739:          * Namespace constraint: Reserved Prefixes and Namespace Names
                    740:          * from XML namespace. But documents authors may not care in
                    741:          * their context so let's proceed.
                    742:          */
                    743:     }
                    744: 
                    745:     /*
                    746:      * Allocate a new Namespace and fill the fields.
                    747:      */
                    748:     cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
                    749:     if (cur == NULL) {
                    750:        xmlTreeErrMemory("building namespace");
                    751:        return(NULL);
                    752:     }
                    753:     memset(cur, 0, sizeof(xmlNs));
                    754:     cur->type = XML_LOCAL_NAMESPACE;
                    755: 
                    756:     if (href != NULL)
                    757:        cur->href = xmlStrdup(href);
                    758:     if (prefix != NULL)
                    759:        cur->prefix = xmlStrdup(prefix);
                    760: 
                    761:     /*
                    762:      * Add it at the end to preserve parsing order ...
                    763:      * and checks for existing use of the prefix
                    764:      */
                    765:     if (node != NULL) {
                    766:        if (node->nsDef == NULL) {
                    767:            node->nsDef = cur;
                    768:        } else {
                    769:            xmlNsPtr prev = node->nsDef;
                    770: 
                    771:            if (((prev->prefix == NULL) && (cur->prefix == NULL)) ||
                    772:                (xmlStrEqual(prev->prefix, cur->prefix))) {
                    773:                xmlFreeNs(cur);
                    774:                return(NULL);
                    775:            }
                    776:            while (prev->next != NULL) {
                    777:                prev = prev->next;
                    778:                if (((prev->prefix == NULL) && (cur->prefix == NULL)) ||
                    779:                    (xmlStrEqual(prev->prefix, cur->prefix))) {
                    780:                    xmlFreeNs(cur);
                    781:                    return(NULL);
                    782:                }
                    783:            }
                    784:            prev->next = cur;
                    785:        }
                    786:     }
                    787:     return(cur);
                    788: }
                    789: 
                    790: /**
                    791:  * xmlSetNs:
                    792:  * @node:  a node in the document
                    793:  * @ns:  a namespace pointer
                    794:  *
                    795:  * Associate a namespace to a node, a posteriori.
                    796:  */
                    797: void
                    798: xmlSetNs(xmlNodePtr node, xmlNsPtr ns) {
                    799:     if (node == NULL) {
                    800: #ifdef DEBUG_TREE
                    801:         xmlGenericError(xmlGenericErrorContext,
                    802:                "xmlSetNs: node == NULL\n");
                    803: #endif
                    804:        return;
                    805:     }
                    806:     node->ns = ns;
                    807: }
                    808: 
                    809: /**
                    810:  * xmlFreeNs:
                    811:  * @cur:  the namespace pointer
                    812:  *
                    813:  * Free up the structures associated to a namespace
                    814:  */
                    815: void
                    816: xmlFreeNs(xmlNsPtr cur) {
                    817:     if (cur == NULL) {
                    818: #ifdef DEBUG_TREE
                    819:         xmlGenericError(xmlGenericErrorContext,
                    820:                "xmlFreeNs : ns == NULL\n");
                    821: #endif
                    822:        return;
                    823:     }
                    824:     if (cur->href != NULL) xmlFree((char *) cur->href);
                    825:     if (cur->prefix != NULL) xmlFree((char *) cur->prefix);
                    826:     xmlFree(cur);
                    827: }
                    828: 
                    829: /**
                    830:  * xmlFreeNsList:
                    831:  * @cur:  the first namespace pointer
                    832:  *
                    833:  * Free up all the structures associated to the chained namespaces.
                    834:  */
                    835: void
                    836: xmlFreeNsList(xmlNsPtr cur) {
                    837:     xmlNsPtr next;
                    838:     if (cur == NULL) {
                    839: #ifdef DEBUG_TREE
                    840:         xmlGenericError(xmlGenericErrorContext,
                    841:                "xmlFreeNsList : ns == NULL\n");
                    842: #endif
                    843:        return;
                    844:     }
                    845:     while (cur != NULL) {
                    846:         next = cur->next;
                    847:         xmlFreeNs(cur);
                    848:        cur = next;
                    849:     }
                    850: }
                    851: 
                    852: /**
                    853:  * xmlNewDtd:
                    854:  * @doc:  the document pointer
                    855:  * @name:  the DTD name
                    856:  * @ExternalID:  the external ID
                    857:  * @SystemID:  the system ID
                    858:  *
                    859:  * Creation of a new DTD for the external subset. To create an
                    860:  * internal subset, use xmlCreateIntSubset().
                    861:  *
                    862:  * Returns a pointer to the new DTD structure
                    863:  */
                    864: xmlDtdPtr
                    865: xmlNewDtd(xmlDocPtr doc, const xmlChar *name,
                    866:                     const xmlChar *ExternalID, const xmlChar *SystemID) {
                    867:     xmlDtdPtr cur;
                    868: 
                    869:     if ((doc != NULL) && (doc->extSubset != NULL)) {
                    870: #ifdef DEBUG_TREE
                    871:         xmlGenericError(xmlGenericErrorContext,
                    872:                "xmlNewDtd(%s): document %s already have a DTD %s\n",
                    873:            /* !!! */ (char *) name, doc->name,
                    874:            /* !!! */ (char *)doc->extSubset->name);
                    875: #endif
                    876:        return(NULL);
                    877:     }
                    878: 
                    879:     /*
                    880:      * Allocate a new DTD and fill the fields.
                    881:      */
                    882:     cur = (xmlDtdPtr) xmlMalloc(sizeof(xmlDtd));
                    883:     if (cur == NULL) {
                    884:        xmlTreeErrMemory("building DTD");
                    885:        return(NULL);
                    886:     }
                    887:     memset(cur, 0 , sizeof(xmlDtd));
                    888:     cur->type = XML_DTD_NODE;
                    889: 
                    890:     if (name != NULL)
                    891:        cur->name = xmlStrdup(name);
                    892:     if (ExternalID != NULL)
                    893:        cur->ExternalID = xmlStrdup(ExternalID);
                    894:     if (SystemID != NULL)
                    895:        cur->SystemID = xmlStrdup(SystemID);
                    896:     if (doc != NULL)
                    897:        doc->extSubset = cur;
                    898:     cur->doc = doc;
                    899: 
                    900:     if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
                    901:        xmlRegisterNodeDefaultValue((xmlNodePtr)cur);
                    902:     return(cur);
                    903: }
                    904: 
                    905: /**
                    906:  * xmlGetIntSubset:
                    907:  * @doc:  the document pointer
                    908:  *
                    909:  * Get the internal subset of a document
                    910:  * Returns a pointer to the DTD structure or NULL if not found
                    911:  */
                    912: 
                    913: xmlDtdPtr
                    914: xmlGetIntSubset(xmlDocPtr doc) {
                    915:     xmlNodePtr cur;
                    916: 
                    917:     if (doc == NULL)
                    918:        return(NULL);
                    919:     cur = doc->children;
                    920:     while (cur != NULL) {
                    921:        if (cur->type == XML_DTD_NODE)
                    922:            return((xmlDtdPtr) cur);
                    923:        cur = cur->next;
                    924:     }
                    925:     return((xmlDtdPtr) doc->intSubset);
                    926: }
                    927: 
                    928: /**
                    929:  * xmlCreateIntSubset:
                    930:  * @doc:  the document pointer
                    931:  * @name:  the DTD name
                    932:  * @ExternalID:  the external (PUBLIC) ID
                    933:  * @SystemID:  the system ID
                    934:  *
                    935:  * Create the internal subset of a document
                    936:  * Returns a pointer to the new DTD structure
                    937:  */
                    938: xmlDtdPtr
                    939: xmlCreateIntSubset(xmlDocPtr doc, const xmlChar *name,
                    940:                    const xmlChar *ExternalID, const xmlChar *SystemID) {
                    941:     xmlDtdPtr cur;
                    942: 
                    943:     if ((doc != NULL) && (xmlGetIntSubset(doc) != NULL)) {
                    944: #ifdef DEBUG_TREE
                    945:         xmlGenericError(xmlGenericErrorContext,
                    946: 
                    947:      "xmlCreateIntSubset(): document %s already have an internal subset\n",
                    948:            doc->name);
                    949: #endif
                    950:        return(NULL);
                    951:     }
                    952: 
                    953:     /*
                    954:      * Allocate a new DTD and fill the fields.
                    955:      */
                    956:     cur = (xmlDtdPtr) xmlMalloc(sizeof(xmlDtd));
                    957:     if (cur == NULL) {
                    958:        xmlTreeErrMemory("building internal subset");
                    959:        return(NULL);
                    960:     }
                    961:     memset(cur, 0, sizeof(xmlDtd));
                    962:     cur->type = XML_DTD_NODE;
                    963: 
                    964:     if (name != NULL) {
                    965:        cur->name = xmlStrdup(name);
                    966:        if (cur->name == NULL) {
                    967:            xmlTreeErrMemory("building internal subset");
                    968:            xmlFree(cur);
                    969:            return(NULL);
                    970:        }
                    971:     }
                    972:     if (ExternalID != NULL) {
                    973:        cur->ExternalID = xmlStrdup(ExternalID);
                    974:        if (cur->ExternalID  == NULL) {
                    975:            xmlTreeErrMemory("building internal subset");
                    976:            if (cur->name != NULL)
                    977:                xmlFree((char *)cur->name);
                    978:            xmlFree(cur);
                    979:            return(NULL);
                    980:        }
                    981:     }
                    982:     if (SystemID != NULL) {
                    983:        cur->SystemID = xmlStrdup(SystemID);
                    984:        if (cur->SystemID == NULL) {
                    985:            xmlTreeErrMemory("building internal subset");
                    986:            if (cur->name != NULL)
                    987:                xmlFree((char *)cur->name);
                    988:            if (cur->ExternalID != NULL)
                    989:                xmlFree((char *)cur->ExternalID);
                    990:            xmlFree(cur);
                    991:            return(NULL);
                    992:        }
                    993:     }
                    994:     if (doc != NULL) {
                    995:        doc->intSubset = cur;
                    996:        cur->parent = doc;
                    997:        cur->doc = doc;
                    998:        if (doc->children == NULL) {
                    999:            doc->children = (xmlNodePtr) cur;
                   1000:            doc->last = (xmlNodePtr) cur;
                   1001:        } else {
                   1002:            if (doc->type == XML_HTML_DOCUMENT_NODE) {
                   1003:                xmlNodePtr prev;
                   1004: 
                   1005:                prev = doc->children;
                   1006:                prev->prev = (xmlNodePtr) cur;
                   1007:                cur->next = prev;
                   1008:                doc->children = (xmlNodePtr) cur;
                   1009:            } else {
                   1010:                xmlNodePtr next;
                   1011: 
                   1012:                next = doc->children;
                   1013:                while ((next != NULL) && (next->type != XML_ELEMENT_NODE))
                   1014:                    next = next->next;
                   1015:                if (next == NULL) {
                   1016:                    cur->prev = doc->last;
                   1017:                    cur->prev->next = (xmlNodePtr) cur;
                   1018:                    cur->next = NULL;
                   1019:                    doc->last = (xmlNodePtr) cur;
                   1020:                } else {
                   1021:                    cur->next = next;
                   1022:                    cur->prev = next->prev;
                   1023:                    if (cur->prev == NULL)
                   1024:                        doc->children = (xmlNodePtr) cur;
                   1025:                    else
                   1026:                        cur->prev->next = (xmlNodePtr) cur;
                   1027:                    next->prev = (xmlNodePtr) cur;
                   1028:                }
                   1029:            }
                   1030:        }
                   1031:     }
                   1032: 
                   1033:     if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
                   1034:        xmlRegisterNodeDefaultValue((xmlNodePtr)cur);
                   1035:     return(cur);
                   1036: }
                   1037: 
                   1038: /**
                   1039:  * DICT_FREE:
                   1040:  * @str:  a string
                   1041:  *
                   1042:  * Free a string if it is not owned by the "dict" dictionnary in the
                   1043:  * current scope
                   1044:  */
                   1045: #define DICT_FREE(str)                                         \
                   1046:        if ((str) && ((!dict) ||                                \
                   1047:            (xmlDictOwns(dict, (const xmlChar *)(str)) == 0)))  \
                   1048:            xmlFree((char *)(str));
                   1049: 
                   1050: 
                   1051: /**
                   1052:  * DICT_COPY:
                   1053:  * @str:  a string
                   1054:  *
                   1055:  * Copy a string using a "dict" dictionnary in the current scope,
                   1056:  * if availabe.
                   1057:  */
                   1058: #define DICT_COPY(str, cpy) \
                   1059:     if (str) { \
                   1060:        if (dict) { \
                   1061:            if (xmlDictOwns(dict, (const xmlChar *)(str))) \
                   1062:                cpy = (xmlChar *) (str); \
                   1063:            else \
                   1064:                cpy = (xmlChar *) xmlDictLookup((dict), (const xmlChar *)(str), -1); \
                   1065:        } else \
                   1066:            cpy = xmlStrdup((const xmlChar *)(str)); }
                   1067: 
                   1068: /**
                   1069:  * DICT_CONST_COPY:
                   1070:  * @str:  a string
                   1071:  *
                   1072:  * Copy a string using a "dict" dictionnary in the current scope,
                   1073:  * if availabe.
                   1074:  */
                   1075: #define DICT_CONST_COPY(str, cpy) \
                   1076:     if (str) { \
                   1077:        if (dict) { \
                   1078:            if (xmlDictOwns(dict, (const xmlChar *)(str))) \
                   1079:                cpy = (const xmlChar *) (str); \
                   1080:            else \
                   1081:                cpy = xmlDictLookup((dict), (const xmlChar *)(str), -1); \
                   1082:        } else \
                   1083:            cpy = (const xmlChar *) xmlStrdup((const xmlChar *)(str)); }
                   1084: 
                   1085: 
                   1086: /**
                   1087:  * xmlFreeDtd:
                   1088:  * @cur:  the DTD structure to free up
                   1089:  *
                   1090:  * Free a DTD structure.
                   1091:  */
                   1092: void
                   1093: xmlFreeDtd(xmlDtdPtr cur) {
                   1094:     xmlDictPtr dict = NULL;
                   1095: 
                   1096:     if (cur == NULL) {
                   1097:        return;
                   1098:     }
                   1099:     if (cur->doc != NULL) dict = cur->doc->dict;
                   1100: 
                   1101:     if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
                   1102:        xmlDeregisterNodeDefaultValue((xmlNodePtr)cur);
                   1103: 
                   1104:     if (cur->children != NULL) {
                   1105:        xmlNodePtr next, c = cur->children;
                   1106: 
                   1107:        /*
                   1108:         * Cleanup all nodes which are not part of the specific lists
                   1109:         * of notations, elements, attributes and entities.
                   1110:         */
                   1111:         while (c != NULL) {
                   1112:            next = c->next;
                   1113:            if ((c->type != XML_NOTATION_NODE) &&
                   1114:                (c->type != XML_ELEMENT_DECL) &&
                   1115:                (c->type != XML_ATTRIBUTE_DECL) &&
                   1116:                (c->type != XML_ENTITY_DECL)) {
                   1117:                xmlUnlinkNode(c);
                   1118:                xmlFreeNode(c);
                   1119:            }
                   1120:            c = next;
                   1121:        }
                   1122:     }
                   1123:     DICT_FREE(cur->name)
                   1124:     DICT_FREE(cur->SystemID)
                   1125:     DICT_FREE(cur->ExternalID)
                   1126:     /* TODO !!! */
                   1127:     if (cur->notations != NULL)
                   1128:         xmlFreeNotationTable((xmlNotationTablePtr) cur->notations);
                   1129: 
                   1130:     if (cur->elements != NULL)
                   1131:         xmlFreeElementTable((xmlElementTablePtr) cur->elements);
                   1132:     if (cur->attributes != NULL)
                   1133:         xmlFreeAttributeTable((xmlAttributeTablePtr) cur->attributes);
                   1134:     if (cur->entities != NULL)
                   1135:         xmlFreeEntitiesTable((xmlEntitiesTablePtr) cur->entities);
                   1136:     if (cur->pentities != NULL)
                   1137:         xmlFreeEntitiesTable((xmlEntitiesTablePtr) cur->pentities);
                   1138: 
                   1139:     xmlFree(cur);
                   1140: }
                   1141: 
                   1142: /**
                   1143:  * xmlNewDoc:
                   1144:  * @version:  xmlChar string giving the version of XML "1.0"
                   1145:  *
                   1146:  * Creates a new XML document
                   1147:  *
                   1148:  * Returns a new document
                   1149:  */
                   1150: xmlDocPtr
                   1151: xmlNewDoc(const xmlChar *version) {
                   1152:     xmlDocPtr cur;
                   1153: 
                   1154:     if (version == NULL)
                   1155:        version = (const xmlChar *) "1.0";
                   1156: 
                   1157:     /*
                   1158:      * Allocate a new document and fill the fields.
                   1159:      */
                   1160:     cur = (xmlDocPtr) xmlMalloc(sizeof(xmlDoc));
                   1161:     if (cur == NULL) {
                   1162:        xmlTreeErrMemory("building doc");
                   1163:        return(NULL);
                   1164:     }
                   1165:     memset(cur, 0, sizeof(xmlDoc));
                   1166:     cur->type = XML_DOCUMENT_NODE;
                   1167: 
                   1168:     cur->version = xmlStrdup(version);
                   1169:     if (cur->version == NULL) {
                   1170:        xmlTreeErrMemory("building doc");
                   1171:        xmlFree(cur);
                   1172:        return(NULL);
                   1173:     }
                   1174:     cur->standalone = -1;
                   1175:     cur->compression = -1; /* not initialized */
                   1176:     cur->doc = cur;
                   1177:     cur->parseFlags = 0;
                   1178:     cur->properties = XML_DOC_USERBUILT;
                   1179:     /*
                   1180:      * The in memory encoding is always UTF8
                   1181:      * This field will never change and would
                   1182:      * be obsolete if not for binary compatibility.
                   1183:      */
                   1184:     cur->charset = XML_CHAR_ENCODING_UTF8;
                   1185: 
                   1186:     if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
                   1187:        xmlRegisterNodeDefaultValue((xmlNodePtr)cur);
                   1188:     return(cur);
                   1189: }
                   1190: 
                   1191: /**
                   1192:  * xmlFreeDoc:
                   1193:  * @cur:  pointer to the document
                   1194:  *
                   1195:  * Free up all the structures used by a document, tree included.
                   1196:  */
                   1197: void
                   1198: xmlFreeDoc(xmlDocPtr cur) {
                   1199:     xmlDtdPtr extSubset, intSubset;
                   1200:     xmlDictPtr dict = NULL;
                   1201: 
                   1202:     if (cur == NULL) {
                   1203: #ifdef DEBUG_TREE
                   1204:         xmlGenericError(xmlGenericErrorContext,
                   1205:                "xmlFreeDoc : document == NULL\n");
                   1206: #endif
                   1207:        return;
                   1208:     }
                   1209: #ifdef LIBXML_DEBUG_RUNTIME
                   1210: #ifdef LIBXML_DEBUG_ENABLED
                   1211:     xmlDebugCheckDocument(stderr, cur);
                   1212: #endif
                   1213: #endif
                   1214: 
                   1215:     if (cur != NULL) dict = cur->dict;
                   1216: 
                   1217:     if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
                   1218:        xmlDeregisterNodeDefaultValue((xmlNodePtr)cur);
                   1219: 
                   1220:     /*
                   1221:      * Do this before freeing the children list to avoid ID lookups
                   1222:      */
                   1223:     if (cur->ids != NULL) xmlFreeIDTable((xmlIDTablePtr) cur->ids);
                   1224:     cur->ids = NULL;
                   1225:     if (cur->refs != NULL) xmlFreeRefTable((xmlRefTablePtr) cur->refs);
                   1226:     cur->refs = NULL;
                   1227:     extSubset = cur->extSubset;
                   1228:     intSubset = cur->intSubset;
                   1229:     if (intSubset == extSubset)
                   1230:        extSubset = NULL;
                   1231:     if (extSubset != NULL) {
                   1232:        xmlUnlinkNode((xmlNodePtr) cur->extSubset);
                   1233:        cur->extSubset = NULL;
                   1234:        xmlFreeDtd(extSubset);
                   1235:     }
                   1236:     if (intSubset != NULL) {
                   1237:        xmlUnlinkNode((xmlNodePtr) cur->intSubset);
                   1238:        cur->intSubset = NULL;
                   1239:        xmlFreeDtd(intSubset);
                   1240:     }
                   1241: 
                   1242:     if (cur->children != NULL) xmlFreeNodeList(cur->children);
                   1243:     if (cur->oldNs != NULL) xmlFreeNsList(cur->oldNs);
                   1244: 
                   1245:     DICT_FREE(cur->version)
                   1246:     DICT_FREE(cur->name)
                   1247:     DICT_FREE(cur->encoding)
                   1248:     DICT_FREE(cur->URL)
                   1249:     xmlFree(cur);
                   1250:     if (dict) xmlDictFree(dict);
                   1251: }
                   1252: 
                   1253: /**
                   1254:  * xmlStringLenGetNodeList:
                   1255:  * @doc:  the document
                   1256:  * @value:  the value of the text
                   1257:  * @len:  the length of the string value
                   1258:  *
                   1259:  * Parse the value string and build the node list associated. Should
                   1260:  * produce a flat tree with only TEXTs and ENTITY_REFs.
                   1261:  * Returns a pointer to the first child
                   1262:  */
                   1263: xmlNodePtr
                   1264: xmlStringLenGetNodeList(xmlDocPtr doc, const xmlChar *value, int len) {
                   1265:     xmlNodePtr ret = NULL, last = NULL;
                   1266:     xmlNodePtr node;
                   1267:     xmlChar *val;
                   1268:     const xmlChar *cur = value, *end = cur + len;
                   1269:     const xmlChar *q;
                   1270:     xmlEntityPtr ent;
1.1.1.3 ! misho    1271:     xmlBufPtr buf;
1.1       misho    1272: 
                   1273:     if (value == NULL) return(NULL);
                   1274: 
1.1.1.3 ! misho    1275:     buf = xmlBufCreateSize(0);
        !          1276:     if (buf == NULL) return(NULL);
        !          1277:     xmlBufSetAllocationScheme(buf, XML_BUFFER_ALLOC_HYBRID);
1.1.1.2   misho    1278: 
1.1       misho    1279:     q = cur;
                   1280:     while ((cur < end) && (*cur != 0)) {
                   1281:        if (cur[0] == '&') {
                   1282:            int charval = 0;
                   1283:            xmlChar tmp;
                   1284: 
                   1285:            /*
                   1286:             * Save the current text.
                   1287:             */
                   1288:             if (cur != q) {
1.1.1.3 ! misho    1289:                if (xmlBufAdd(buf, q, cur - q))
1.1.1.2   misho    1290:                    goto out;
1.1       misho    1291:            }
                   1292:            q = cur;
                   1293:            if ((cur + 2 < end) && (cur[1] == '#') && (cur[2] == 'x')) {
                   1294:                cur += 3;
                   1295:                if (cur < end)
                   1296:                    tmp = *cur;
                   1297:                else
                   1298:                    tmp = 0;
                   1299:                while (tmp != ';') { /* Non input consuming loop */
                   1300:                    if ((tmp >= '0') && (tmp <= '9'))
                   1301:                        charval = charval * 16 + (tmp - '0');
                   1302:                    else if ((tmp >= 'a') && (tmp <= 'f'))
                   1303:                        charval = charval * 16 + (tmp - 'a') + 10;
                   1304:                    else if ((tmp >= 'A') && (tmp <= 'F'))
                   1305:                        charval = charval * 16 + (tmp - 'A') + 10;
                   1306:                    else {
                   1307:                        xmlTreeErr(XML_TREE_INVALID_HEX, (xmlNodePtr) doc,
                   1308:                                   NULL);
                   1309:                        charval = 0;
                   1310:                        break;
                   1311:                    }
                   1312:                    cur++;
                   1313:                    if (cur < end)
                   1314:                        tmp = *cur;
                   1315:                    else
                   1316:                        tmp = 0;
                   1317:                }
                   1318:                if (tmp == ';')
                   1319:                    cur++;
                   1320:                q = cur;
                   1321:            } else if ((cur + 1 < end) && (cur[1] == '#')) {
                   1322:                cur += 2;
                   1323:                if (cur < end)
                   1324:                    tmp = *cur;
                   1325:                else
                   1326:                    tmp = 0;
                   1327:                while (tmp != ';') { /* Non input consuming loops */
                   1328:                    if ((tmp >= '0') && (tmp <= '9'))
                   1329:                        charval = charval * 10 + (tmp - '0');
                   1330:                    else {
                   1331:                        xmlTreeErr(XML_TREE_INVALID_DEC, (xmlNodePtr) doc,
                   1332:                                   NULL);
                   1333:                        charval = 0;
                   1334:                        break;
                   1335:                    }
                   1336:                    cur++;
                   1337:                    if (cur < end)
                   1338:                        tmp = *cur;
                   1339:                    else
                   1340:                        tmp = 0;
                   1341:                }
                   1342:                if (tmp == ';')
                   1343:                    cur++;
                   1344:                q = cur;
                   1345:            } else {
                   1346:                /*
                   1347:                 * Read the entity string
                   1348:                 */
                   1349:                cur++;
                   1350:                q = cur;
                   1351:                while ((cur < end) && (*cur != 0) && (*cur != ';')) cur++;
                   1352:                if ((cur >= end) || (*cur == 0)) {
                   1353:                    xmlTreeErr(XML_TREE_UNTERMINATED_ENTITY, (xmlNodePtr) doc,
                   1354:                               (const char *) q);
1.1.1.2   misho    1355:                    goto out;
1.1       misho    1356:                }
                   1357:                if (cur != q) {
                   1358:                    /*
                   1359:                     * Predefined entities don't generate nodes
                   1360:                     */
                   1361:                    val = xmlStrndup(q, cur - q);
                   1362:                    ent = xmlGetDocEntity(doc, val);
                   1363:                    if ((ent != NULL) &&
                   1364:                        (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
1.1.1.2   misho    1365: 
1.1.1.3 ! misho    1366:                        if (xmlBufCat(buf, ent->content))
1.1.1.2   misho    1367:                            goto out;
1.1       misho    1368: 
                   1369:                    } else {
                   1370:                        /*
1.1.1.2   misho    1371:                         * Flush buffer so far
                   1372:                         */
1.1.1.3 ! misho    1373:                        if (!xmlBufIsEmpty(buf)) {
1.1.1.2   misho    1374:                            node = xmlNewDocText(doc, NULL);
                   1375:                            if (node == NULL) {
                   1376:                                if (val != NULL) xmlFree(val);
                   1377:                                goto out;
                   1378:                            }
1.1.1.3 ! misho    1379:                            node->content = xmlBufDetach(buf);
1.1.1.2   misho    1380: 
                   1381:                            if (last == NULL) {
                   1382:                                last = ret = node;
                   1383:                            } else {
                   1384:                                last = xmlAddNextSibling(last, node);
                   1385:                            }
                   1386:                        }
                   1387: 
                   1388:                        /*
1.1       misho    1389:                         * Create a new REFERENCE_REF node
                   1390:                         */
                   1391:                        node = xmlNewReference(doc, val);
                   1392:                        if (node == NULL) {
                   1393:                            if (val != NULL) xmlFree(val);
1.1.1.2   misho    1394:                            goto out;
1.1       misho    1395:                        }
                   1396:                        else if ((ent != NULL) && (ent->children == NULL)) {
                   1397:                            xmlNodePtr temp;
                   1398: 
                   1399:                            ent->children = xmlStringGetNodeList(doc,
                   1400:                                    (const xmlChar*)node->content);
                   1401:                            ent->owner = 1;
                   1402:                            temp = ent->children;
                   1403:                            while (temp) {
                   1404:                                temp->parent = (xmlNodePtr)ent;
                   1405:                                ent->last = temp;
                   1406:                                temp = temp->next;
                   1407:                            }
                   1408:                        }
                   1409:                        if (last == NULL) {
                   1410:                            last = ret = node;
                   1411:                        } else {
                   1412:                            last = xmlAddNextSibling(last, node);
                   1413:                        }
                   1414:                    }
                   1415:                    xmlFree(val);
                   1416:                }
                   1417:                cur++;
                   1418:                q = cur;
                   1419:            }
                   1420:            if (charval != 0) {
1.1.1.3 ! misho    1421:                xmlChar buffer[10];
1.1       misho    1422:                int l;
                   1423: 
1.1.1.3 ! misho    1424:                l = xmlCopyCharMultiByte(buffer, charval);
        !          1425:                buffer[l] = 0;
1.1.1.2   misho    1426: 
1.1.1.3 ! misho    1427:                if (xmlBufCat(buf, buffer))
1.1.1.2   misho    1428:                    goto out;
1.1       misho    1429:                charval = 0;
                   1430:            }
                   1431:        } else
                   1432:            cur++;
                   1433:     }
1.1.1.2   misho    1434: 
                   1435:     if (cur != q) {
1.1       misho    1436:         /*
                   1437:         * Handle the last piece of text.
                   1438:         */
1.1.1.3 ! misho    1439:        if (xmlBufAdd(buf, q, cur - q))
1.1.1.2   misho    1440:            goto out;
                   1441:     }
                   1442: 
1.1.1.3 ! misho    1443:     if (!xmlBufIsEmpty(buf)) {
1.1.1.2   misho    1444:        node = xmlNewDocText(doc, NULL);
                   1445:        if (node == NULL) goto out;
1.1.1.3 ! misho    1446:        node->content = xmlBufDetach(buf);
1.1.1.2   misho    1447: 
                   1448:        if (last == NULL) {
                   1449:            last = ret = node;
1.1       misho    1450:        } else {
1.1.1.2   misho    1451:            last = xmlAddNextSibling(last, node);
1.1       misho    1452:        }
1.1.1.2   misho    1453:     } else if (ret == NULL) {
                   1454:         ret = xmlNewDocText(doc, BAD_CAST "");
1.1       misho    1455:     }
1.1.1.2   misho    1456: 
                   1457: out:
1.1.1.3 ! misho    1458:     xmlBufFree(buf);
1.1       misho    1459:     return(ret);
                   1460: }
                   1461: 
                   1462: /**
                   1463:  * xmlStringGetNodeList:
                   1464:  * @doc:  the document
                   1465:  * @value:  the value of the attribute
                   1466:  *
                   1467:  * Parse the value string and build the node list associated. Should
                   1468:  * produce a flat tree with only TEXTs and ENTITY_REFs.
                   1469:  * Returns a pointer to the first child
                   1470:  */
                   1471: xmlNodePtr
                   1472: xmlStringGetNodeList(xmlDocPtr doc, const xmlChar *value) {
                   1473:     xmlNodePtr ret = NULL, last = NULL;
                   1474:     xmlNodePtr node;
                   1475:     xmlChar *val;
                   1476:     const xmlChar *cur = value;
                   1477:     const xmlChar *q;
                   1478:     xmlEntityPtr ent;
1.1.1.3 ! misho    1479:     xmlBufPtr buf;
1.1       misho    1480: 
                   1481:     if (value == NULL) return(NULL);
                   1482: 
1.1.1.3 ! misho    1483:     buf = xmlBufCreateSize(0);
        !          1484:     if (buf == NULL) return(NULL);
        !          1485:     xmlBufSetAllocationScheme(buf, XML_BUFFER_ALLOC_HYBRID);
1.1.1.2   misho    1486: 
1.1       misho    1487:     q = cur;
                   1488:     while (*cur != 0) {
                   1489:        if (cur[0] == '&') {
                   1490:            int charval = 0;
                   1491:            xmlChar tmp;
                   1492: 
                   1493:            /*
                   1494:             * Save the current text.
                   1495:             */
                   1496:             if (cur != q) {
1.1.1.3 ! misho    1497:                if (xmlBufAdd(buf, q, cur - q))
1.1.1.2   misho    1498:                    goto out;
1.1       misho    1499:            }
                   1500:            q = cur;
                   1501:            if ((cur[1] == '#') && (cur[2] == 'x')) {
                   1502:                cur += 3;
                   1503:                tmp = *cur;
                   1504:                while (tmp != ';') { /* Non input consuming loop */
                   1505:                    if ((tmp >= '0') && (tmp <= '9'))
                   1506:                        charval = charval * 16 + (tmp - '0');
                   1507:                    else if ((tmp >= 'a') && (tmp <= 'f'))
                   1508:                        charval = charval * 16 + (tmp - 'a') + 10;
                   1509:                    else if ((tmp >= 'A') && (tmp <= 'F'))
                   1510:                        charval = charval * 16 + (tmp - 'A') + 10;
                   1511:                    else {
                   1512:                        xmlTreeErr(XML_TREE_INVALID_HEX, (xmlNodePtr) doc,
                   1513:                                   NULL);
                   1514:                        charval = 0;
                   1515:                        break;
                   1516:                    }
                   1517:                    cur++;
                   1518:                    tmp = *cur;
                   1519:                }
                   1520:                if (tmp == ';')
                   1521:                    cur++;
                   1522:                q = cur;
                   1523:            } else if  (cur[1] == '#') {
                   1524:                cur += 2;
                   1525:                tmp = *cur;
                   1526:                while (tmp != ';') { /* Non input consuming loops */
                   1527:                    if ((tmp >= '0') && (tmp <= '9'))
                   1528:                        charval = charval * 10 + (tmp - '0');
                   1529:                    else {
                   1530:                        xmlTreeErr(XML_TREE_INVALID_DEC, (xmlNodePtr) doc,
                   1531:                                   NULL);
                   1532:                        charval = 0;
                   1533:                        break;
                   1534:                    }
                   1535:                    cur++;
                   1536:                    tmp = *cur;
                   1537:                }
                   1538:                if (tmp == ';')
                   1539:                    cur++;
                   1540:                q = cur;
                   1541:            } else {
                   1542:                /*
                   1543:                 * Read the entity string
                   1544:                 */
                   1545:                cur++;
                   1546:                q = cur;
                   1547:                while ((*cur != 0) && (*cur != ';')) cur++;
                   1548:                if (*cur == 0) {
                   1549:                    xmlTreeErr(XML_TREE_UNTERMINATED_ENTITY,
                   1550:                               (xmlNodePtr) doc, (const char *) q);
1.1.1.2   misho    1551:                    goto out;
1.1       misho    1552:                }
                   1553:                if (cur != q) {
                   1554:                    /*
                   1555:                     * Predefined entities don't generate nodes
                   1556:                     */
                   1557:                    val = xmlStrndup(q, cur - q);
                   1558:                    ent = xmlGetDocEntity(doc, val);
                   1559:                    if ((ent != NULL) &&
                   1560:                        (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
1.1.1.2   misho    1561: 
1.1.1.3 ! misho    1562:                        if (xmlBufCat(buf, ent->content))
1.1.1.2   misho    1563:                            goto out;
1.1       misho    1564: 
                   1565:                    } else {
                   1566:                        /*
1.1.1.2   misho    1567:                         * Flush buffer so far
                   1568:                         */
1.1.1.3 ! misho    1569:                        if (!xmlBufIsEmpty(buf)) {
1.1.1.2   misho    1570:                            node = xmlNewDocText(doc, NULL);
1.1.1.3 ! misho    1571:                            node->content = xmlBufDetach(buf);
1.1.1.2   misho    1572: 
                   1573:                            if (last == NULL) {
                   1574:                                last = ret = node;
                   1575:                            } else {
                   1576:                                last = xmlAddNextSibling(last, node);
                   1577:                            }
                   1578:                        }
                   1579: 
                   1580:                        /*
1.1       misho    1581:                         * Create a new REFERENCE_REF node
                   1582:                         */
                   1583:                        node = xmlNewReference(doc, val);
                   1584:                        if (node == NULL) {
                   1585:                            if (val != NULL) xmlFree(val);
1.1.1.2   misho    1586:                            goto out;
1.1       misho    1587:                        }
                   1588:                        else if ((ent != NULL) && (ent->children == NULL)) {
                   1589:                            xmlNodePtr temp;
                   1590: 
                   1591:                            ent->children = xmlStringGetNodeList(doc,
                   1592:                                    (const xmlChar*)node->content);
                   1593:                            ent->owner = 1;
                   1594:                            temp = ent->children;
                   1595:                            while (temp) {
                   1596:                                temp->parent = (xmlNodePtr)ent;
                   1597:                                temp = temp->next;
                   1598:                            }
                   1599:                        }
                   1600:                        if (last == NULL) {
                   1601:                            last = ret = node;
                   1602:                        } else {
                   1603:                            last = xmlAddNextSibling(last, node);
                   1604:                        }
                   1605:                    }
                   1606:                    xmlFree(val);
                   1607:                }
                   1608:                cur++;
                   1609:                q = cur;
                   1610:            }
                   1611:            if (charval != 0) {
1.1.1.3 ! misho    1612:                xmlChar buffer[10];
1.1       misho    1613:                int len;
                   1614: 
1.1.1.3 ! misho    1615:                len = xmlCopyCharMultiByte(buffer, charval);
        !          1616:                buffer[len] = 0;
1.1.1.2   misho    1617: 
1.1.1.3 ! misho    1618:                if (xmlBufCat(buf, buffer))
1.1.1.2   misho    1619:                    goto out;
                   1620:                charval = 0;
1.1       misho    1621:            }
                   1622:        } else
                   1623:            cur++;
                   1624:     }
                   1625:     if ((cur != q) || (ret == NULL)) {
                   1626:         /*
                   1627:         * Handle the last piece of text.
                   1628:         */
1.1.1.3 ! misho    1629:        xmlBufAdd(buf, q, cur - q);
1.1.1.2   misho    1630:     }
                   1631: 
1.1.1.3 ! misho    1632:     if (!xmlBufIsEmpty(buf)) {
1.1.1.2   misho    1633:        node = xmlNewDocText(doc, NULL);
1.1.1.3 ! misho    1634:        node->content = xmlBufDetach(buf);
1.1.1.2   misho    1635: 
                   1636:        if (last == NULL) {
                   1637:            last = ret = node;
1.1       misho    1638:        } else {
1.1.1.2   misho    1639:            last = xmlAddNextSibling(last, node);
1.1       misho    1640:        }
                   1641:     }
1.1.1.2   misho    1642: 
                   1643: out:
1.1.1.3 ! misho    1644:     xmlBufFree(buf);
1.1       misho    1645:     return(ret);
                   1646: }
                   1647: 
                   1648: /**
                   1649:  * xmlNodeListGetString:
                   1650:  * @doc:  the document
                   1651:  * @list:  a Node list
                   1652:  * @inLine:  should we replace entity contents or show their external form
                   1653:  *
                   1654:  * Build the string equivalent to the text contained in the Node list
                   1655:  * made of TEXTs and ENTITY_REFs
                   1656:  *
                   1657:  * Returns a pointer to the string copy, the caller must free it with xmlFree().
                   1658:  */
                   1659: xmlChar *
                   1660: xmlNodeListGetString(xmlDocPtr doc, xmlNodePtr list, int inLine)
                   1661: {
                   1662:     xmlNodePtr node = list;
                   1663:     xmlChar *ret = NULL;
                   1664:     xmlEntityPtr ent;
1.1.1.3 ! misho    1665:     int attr;
1.1       misho    1666: 
                   1667:     if (list == NULL)
                   1668:         return (NULL);
1.1.1.3 ! misho    1669:     if ((list->parent != NULL) && (list->parent->type == XML_ATTRIBUTE_NODE))
        !          1670:         attr = 1;
        !          1671:     else
        !          1672:         attr = 0;
1.1       misho    1673: 
                   1674:     while (node != NULL) {
                   1675:         if ((node->type == XML_TEXT_NODE) ||
                   1676:             (node->type == XML_CDATA_SECTION_NODE)) {
                   1677:             if (inLine) {
                   1678:                 ret = xmlStrcat(ret, node->content);
                   1679:             } else {
                   1680:                 xmlChar *buffer;
                   1681: 
1.1.1.3 ! misho    1682:                if (attr)
        !          1683:                    buffer = xmlEncodeAttributeEntities(doc, node->content);
        !          1684:                else
        !          1685:                    buffer = xmlEncodeEntitiesReentrant(doc, node->content);
1.1       misho    1686:                 if (buffer != NULL) {
                   1687:                     ret = xmlStrcat(ret, buffer);
                   1688:                     xmlFree(buffer);
                   1689:                 }
                   1690:             }
                   1691:         } else if (node->type == XML_ENTITY_REF_NODE) {
                   1692:             if (inLine) {
                   1693:                 ent = xmlGetDocEntity(doc, node->name);
                   1694:                 if (ent != NULL) {
                   1695:                     xmlChar *buffer;
                   1696: 
                   1697:                     /* an entity content can be any "well balanced chunk",
                   1698:                      * i.e. the result of the content [43] production:
                   1699:                      * http://www.w3.org/TR/REC-xml#NT-content.
                   1700:                      * So it can contain text, CDATA section or nested
                   1701:                      * entity reference nodes (among others).
                   1702:                      * -> we recursive  call xmlNodeListGetString()
                   1703:                      * which handles these types */
                   1704:                     buffer = xmlNodeListGetString(doc, ent->children, 1);
                   1705:                     if (buffer != NULL) {
                   1706:                         ret = xmlStrcat(ret, buffer);
                   1707:                         xmlFree(buffer);
                   1708:                     }
                   1709:                 } else {
                   1710:                     ret = xmlStrcat(ret, node->content);
                   1711:                 }
                   1712:             } else {
                   1713:                 xmlChar buf[2];
                   1714: 
                   1715:                 buf[0] = '&';
                   1716:                 buf[1] = 0;
                   1717:                 ret = xmlStrncat(ret, buf, 1);
                   1718:                 ret = xmlStrcat(ret, node->name);
                   1719:                 buf[0] = ';';
                   1720:                 buf[1] = 0;
                   1721:                 ret = xmlStrncat(ret, buf, 1);
                   1722:             }
                   1723:         }
                   1724: #if 0
                   1725:         else {
                   1726:             xmlGenericError(xmlGenericErrorContext,
                   1727:                             "xmlGetNodeListString : invalid node type %d\n",
                   1728:                             node->type);
                   1729:         }
                   1730: #endif
                   1731:         node = node->next;
                   1732:     }
                   1733:     return (ret);
                   1734: }
                   1735: 
                   1736: #ifdef LIBXML_TREE_ENABLED
                   1737: /**
                   1738:  * xmlNodeListGetRawString:
                   1739:  * @doc:  the document
                   1740:  * @list:  a Node list
                   1741:  * @inLine:  should we replace entity contents or show their external form
                   1742:  *
                   1743:  * Builds the string equivalent to the text contained in the Node list
                   1744:  * made of TEXTs and ENTITY_REFs, contrary to xmlNodeListGetString()
                   1745:  * this function doesn't do any character encoding handling.
                   1746:  *
                   1747:  * Returns a pointer to the string copy, the caller must free it with xmlFree().
                   1748:  */
                   1749: xmlChar *
                   1750: xmlNodeListGetRawString(xmlDocPtr doc, xmlNodePtr list, int inLine)
                   1751: {
                   1752:     xmlNodePtr node = list;
                   1753:     xmlChar *ret = NULL;
                   1754:     xmlEntityPtr ent;
                   1755: 
                   1756:     if (list == NULL)
                   1757:         return (NULL);
                   1758: 
                   1759:     while (node != NULL) {
                   1760:         if ((node->type == XML_TEXT_NODE) ||
                   1761:             (node->type == XML_CDATA_SECTION_NODE)) {
                   1762:             if (inLine) {
                   1763:                 ret = xmlStrcat(ret, node->content);
                   1764:             } else {
                   1765:                 xmlChar *buffer;
                   1766: 
                   1767:                 buffer = xmlEncodeSpecialChars(doc, node->content);
                   1768:                 if (buffer != NULL) {
                   1769:                     ret = xmlStrcat(ret, buffer);
                   1770:                     xmlFree(buffer);
                   1771:                 }
                   1772:             }
                   1773:         } else if (node->type == XML_ENTITY_REF_NODE) {
                   1774:             if (inLine) {
                   1775:                 ent = xmlGetDocEntity(doc, node->name);
                   1776:                 if (ent != NULL) {
                   1777:                     xmlChar *buffer;
                   1778: 
                   1779:                     /* an entity content can be any "well balanced chunk",
                   1780:                      * i.e. the result of the content [43] production:
                   1781:                      * http://www.w3.org/TR/REC-xml#NT-content.
                   1782:                      * So it can contain text, CDATA section or nested
                   1783:                      * entity reference nodes (among others).
                   1784:                      * -> we recursive  call xmlNodeListGetRawString()
                   1785:                      * which handles these types */
                   1786:                     buffer =
                   1787:                         xmlNodeListGetRawString(doc, ent->children, 1);
                   1788:                     if (buffer != NULL) {
                   1789:                         ret = xmlStrcat(ret, buffer);
                   1790:                         xmlFree(buffer);
                   1791:                     }
                   1792:                 } else {
                   1793:                     ret = xmlStrcat(ret, node->content);
                   1794:                 }
                   1795:             } else {
                   1796:                 xmlChar buf[2];
                   1797: 
                   1798:                 buf[0] = '&';
                   1799:                 buf[1] = 0;
                   1800:                 ret = xmlStrncat(ret, buf, 1);
                   1801:                 ret = xmlStrcat(ret, node->name);
                   1802:                 buf[0] = ';';
                   1803:                 buf[1] = 0;
                   1804:                 ret = xmlStrncat(ret, buf, 1);
                   1805:             }
                   1806:         }
                   1807: #if 0
                   1808:         else {
                   1809:             xmlGenericError(xmlGenericErrorContext,
                   1810:                             "xmlGetNodeListString : invalid node type %d\n",
                   1811:                             node->type);
                   1812:         }
                   1813: #endif
                   1814:         node = node->next;
                   1815:     }
                   1816:     return (ret);
                   1817: }
                   1818: #endif /* LIBXML_TREE_ENABLED */
                   1819: 
                   1820: static xmlAttrPtr
                   1821: xmlNewPropInternal(xmlNodePtr node, xmlNsPtr ns,
                   1822:                    const xmlChar * name, const xmlChar * value,
                   1823:                    int eatname)
                   1824: {
                   1825:     xmlAttrPtr cur;
                   1826:     xmlDocPtr doc = NULL;
                   1827: 
                   1828:     if ((node != NULL) && (node->type != XML_ELEMENT_NODE)) {
                   1829:         if ((eatname == 1) &&
                   1830:            ((node->doc == NULL) ||
                   1831:             (!(xmlDictOwns(node->doc->dict, name)))))
                   1832:             xmlFree((xmlChar *) name);
                   1833:         return (NULL);
                   1834:     }
                   1835: 
                   1836:     /*
                   1837:      * Allocate a new property and fill the fields.
                   1838:      */
                   1839:     cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr));
                   1840:     if (cur == NULL) {
                   1841:         if ((eatname == 1) &&
                   1842:            ((node == NULL) || (node->doc == NULL) ||
                   1843:             (!(xmlDictOwns(node->doc->dict, name)))))
                   1844:             xmlFree((xmlChar *) name);
                   1845:         xmlTreeErrMemory("building attribute");
                   1846:         return (NULL);
                   1847:     }
                   1848:     memset(cur, 0, sizeof(xmlAttr));
                   1849:     cur->type = XML_ATTRIBUTE_NODE;
                   1850: 
                   1851:     cur->parent = node;
                   1852:     if (node != NULL) {
                   1853:         doc = node->doc;
                   1854:         cur->doc = doc;
                   1855:     }
                   1856:     cur->ns = ns;
                   1857: 
                   1858:     if (eatname == 0) {
                   1859:         if ((doc != NULL) && (doc->dict != NULL))
                   1860:             cur->name = (xmlChar *) xmlDictLookup(doc->dict, name, -1);
                   1861:         else
                   1862:             cur->name = xmlStrdup(name);
                   1863:     } else
                   1864:         cur->name = name;
                   1865: 
                   1866:     if (value != NULL) {
                   1867:         xmlNodePtr tmp;
                   1868: 
                   1869:         if(!xmlCheckUTF8(value)) {
                   1870:             xmlTreeErr(XML_TREE_NOT_UTF8, (xmlNodePtr) doc,
                   1871:                        NULL);
                   1872:             if (doc != NULL)
                   1873:                 doc->encoding = xmlStrdup(BAD_CAST "ISO-8859-1");
                   1874:         }
                   1875:         cur->children = xmlNewDocText(doc, value);
                   1876:         cur->last = NULL;
                   1877:         tmp = cur->children;
                   1878:         while (tmp != NULL) {
                   1879:             tmp->parent = (xmlNodePtr) cur;
                   1880:             if (tmp->next == NULL)
                   1881:                 cur->last = tmp;
                   1882:             tmp = tmp->next;
                   1883:         }
                   1884:     }
                   1885: 
                   1886:     /*
                   1887:      * Add it at the end to preserve parsing order ...
                   1888:      */
                   1889:     if (node != NULL) {
                   1890:         if (node->properties == NULL) {
                   1891:             node->properties = cur;
                   1892:         } else {
                   1893:             xmlAttrPtr prev = node->properties;
                   1894: 
                   1895:             while (prev->next != NULL)
                   1896:                 prev = prev->next;
                   1897:             prev->next = cur;
                   1898:             cur->prev = prev;
                   1899:         }
                   1900:     }
                   1901: 
                   1902:     if ((value != NULL) && (node != NULL) &&
                   1903:         (xmlIsID(node->doc, node, cur) == 1))
                   1904:         xmlAddID(NULL, node->doc, value, cur);
                   1905: 
                   1906:     if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
                   1907:         xmlRegisterNodeDefaultValue((xmlNodePtr) cur);
                   1908:     return (cur);
                   1909: }
                   1910: 
                   1911: #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_HTML_ENABLED) || \
                   1912:     defined(LIBXML_SCHEMAS_ENABLED)
                   1913: /**
                   1914:  * xmlNewProp:
                   1915:  * @node:  the holding node
                   1916:  * @name:  the name of the attribute
                   1917:  * @value:  the value of the attribute
                   1918:  *
                   1919:  * Create a new property carried by a node.
                   1920:  * Returns a pointer to the attribute
                   1921:  */
                   1922: xmlAttrPtr
                   1923: xmlNewProp(xmlNodePtr node, const xmlChar *name, const xmlChar *value) {
                   1924: 
                   1925:     if (name == NULL) {
                   1926: #ifdef DEBUG_TREE
                   1927:         xmlGenericError(xmlGenericErrorContext,
                   1928:                "xmlNewProp : name == NULL\n");
                   1929: #endif
                   1930:        return(NULL);
                   1931:     }
                   1932: 
                   1933:        return xmlNewPropInternal(node, NULL, name, value, 0);
                   1934: }
                   1935: #endif /* LIBXML_TREE_ENABLED */
                   1936: 
                   1937: /**
                   1938:  * xmlNewNsProp:
                   1939:  * @node:  the holding node
                   1940:  * @ns:  the namespace
                   1941:  * @name:  the name of the attribute
                   1942:  * @value:  the value of the attribute
                   1943:  *
                   1944:  * Create a new property tagged with a namespace and carried by a node.
                   1945:  * Returns a pointer to the attribute
                   1946:  */
                   1947: xmlAttrPtr
                   1948: xmlNewNsProp(xmlNodePtr node, xmlNsPtr ns, const xmlChar *name,
                   1949:            const xmlChar *value) {
                   1950: 
                   1951:     if (name == NULL) {
                   1952: #ifdef DEBUG_TREE
                   1953:         xmlGenericError(xmlGenericErrorContext,
                   1954:                "xmlNewNsProp : name == NULL\n");
                   1955: #endif
                   1956:        return(NULL);
                   1957:     }
                   1958: 
                   1959:     return xmlNewPropInternal(node, ns, name, value, 0);
                   1960: }
                   1961: 
                   1962: /**
                   1963:  * xmlNewNsPropEatName:
                   1964:  * @node:  the holding node
                   1965:  * @ns:  the namespace
                   1966:  * @name:  the name of the attribute
                   1967:  * @value:  the value of the attribute
                   1968:  *
                   1969:  * Create a new property tagged with a namespace and carried by a node.
                   1970:  * Returns a pointer to the attribute
                   1971:  */
                   1972: xmlAttrPtr
                   1973: xmlNewNsPropEatName(xmlNodePtr node, xmlNsPtr ns, xmlChar *name,
                   1974:            const xmlChar *value) {
                   1975: 
                   1976:     if (name == NULL) {
                   1977: #ifdef DEBUG_TREE
                   1978:         xmlGenericError(xmlGenericErrorContext,
                   1979:                "xmlNewNsPropEatName : name == NULL\n");
                   1980: #endif
                   1981:        return(NULL);
                   1982:     }
                   1983: 
                   1984:     return xmlNewPropInternal(node, ns, name, value, 1);
                   1985: }
                   1986: 
                   1987: /**
                   1988:  * xmlNewDocProp:
                   1989:  * @doc:  the document
                   1990:  * @name:  the name of the attribute
                   1991:  * @value:  the value of the attribute
                   1992:  *
                   1993:  * Create a new property carried by a document.
                   1994:  * Returns a pointer to the attribute
                   1995:  */
                   1996: xmlAttrPtr
                   1997: xmlNewDocProp(xmlDocPtr doc, const xmlChar *name, const xmlChar *value) {
                   1998:     xmlAttrPtr cur;
                   1999: 
                   2000:     if (name == NULL) {
                   2001: #ifdef DEBUG_TREE
                   2002:         xmlGenericError(xmlGenericErrorContext,
                   2003:                "xmlNewDocProp : name == NULL\n");
                   2004: #endif
                   2005:        return(NULL);
                   2006:     }
                   2007: 
                   2008:     /*
                   2009:      * Allocate a new property and fill the fields.
                   2010:      */
                   2011:     cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr));
                   2012:     if (cur == NULL) {
                   2013:        xmlTreeErrMemory("building attribute");
                   2014:        return(NULL);
                   2015:     }
                   2016:     memset(cur, 0, sizeof(xmlAttr));
                   2017:     cur->type = XML_ATTRIBUTE_NODE;
                   2018: 
                   2019:     if ((doc != NULL) && (doc->dict != NULL))
                   2020:        cur->name = xmlDictLookup(doc->dict, name, -1);
                   2021:     else
                   2022:        cur->name = xmlStrdup(name);
                   2023:     cur->doc = doc;
                   2024:     if (value != NULL) {
                   2025:        xmlNodePtr tmp;
                   2026: 
                   2027:        cur->children = xmlStringGetNodeList(doc, value);
                   2028:        cur->last = NULL;
                   2029: 
                   2030:        tmp = cur->children;
                   2031:        while (tmp != NULL) {
                   2032:            tmp->parent = (xmlNodePtr) cur;
                   2033:            if (tmp->next == NULL)
                   2034:                cur->last = tmp;
                   2035:            tmp = tmp->next;
                   2036:        }
                   2037:     }
                   2038: 
                   2039:     if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
                   2040:        xmlRegisterNodeDefaultValue((xmlNodePtr)cur);
                   2041:     return(cur);
                   2042: }
                   2043: 
                   2044: /**
                   2045:  * xmlFreePropList:
                   2046:  * @cur:  the first property in the list
                   2047:  *
                   2048:  * Free a property and all its siblings, all the children are freed too.
                   2049:  */
                   2050: void
                   2051: xmlFreePropList(xmlAttrPtr cur) {
                   2052:     xmlAttrPtr next;
                   2053:     if (cur == NULL) return;
                   2054:     while (cur != NULL) {
                   2055:         next = cur->next;
                   2056:         xmlFreeProp(cur);
                   2057:        cur = next;
                   2058:     }
                   2059: }
                   2060: 
                   2061: /**
                   2062:  * xmlFreeProp:
                   2063:  * @cur:  an attribute
                   2064:  *
                   2065:  * Free one attribute, all the content is freed too
                   2066:  */
                   2067: void
                   2068: xmlFreeProp(xmlAttrPtr cur) {
                   2069:     xmlDictPtr dict = NULL;
                   2070:     if (cur == NULL) return;
                   2071: 
                   2072:     if (cur->doc != NULL) dict = cur->doc->dict;
                   2073: 
                   2074:     if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
                   2075:        xmlDeregisterNodeDefaultValue((xmlNodePtr)cur);
                   2076: 
                   2077:     /* Check for ID removal -> leading to invalid references ! */
                   2078:     if ((cur->doc != NULL) && (cur->atype == XML_ATTRIBUTE_ID)) {
                   2079:            xmlRemoveID(cur->doc, cur);
                   2080:     }
                   2081:     if (cur->children != NULL) xmlFreeNodeList(cur->children);
                   2082:     DICT_FREE(cur->name)
                   2083:     xmlFree(cur);
                   2084: }
                   2085: 
                   2086: /**
                   2087:  * xmlRemoveProp:
                   2088:  * @cur:  an attribute
                   2089:  *
                   2090:  * Unlink and free one attribute, all the content is freed too
                   2091:  * Note this doesn't work for namespace definition attributes
                   2092:  *
                   2093:  * Returns 0 if success and -1 in case of error.
                   2094:  */
                   2095: int
                   2096: xmlRemoveProp(xmlAttrPtr cur) {
                   2097:     xmlAttrPtr tmp;
                   2098:     if (cur == NULL) {
                   2099: #ifdef DEBUG_TREE
                   2100:         xmlGenericError(xmlGenericErrorContext,
                   2101:                "xmlRemoveProp : cur == NULL\n");
                   2102: #endif
                   2103:        return(-1);
                   2104:     }
                   2105:     if (cur->parent == NULL) {
                   2106: #ifdef DEBUG_TREE
                   2107:         xmlGenericError(xmlGenericErrorContext,
                   2108:                "xmlRemoveProp : cur->parent == NULL\n");
                   2109: #endif
                   2110:        return(-1);
                   2111:     }
                   2112:     tmp = cur->parent->properties;
                   2113:     if (tmp == cur) {
                   2114:         cur->parent->properties = cur->next;
                   2115:                if (cur->next != NULL)
                   2116:                        cur->next->prev = NULL;
                   2117:        xmlFreeProp(cur);
                   2118:        return(0);
                   2119:     }
                   2120:     while (tmp != NULL) {
                   2121:        if (tmp->next == cur) {
                   2122:            tmp->next = cur->next;
                   2123:            if (tmp->next != NULL)
                   2124:                tmp->next->prev = tmp;
                   2125:            xmlFreeProp(cur);
                   2126:            return(0);
                   2127:        }
                   2128:         tmp = tmp->next;
                   2129:     }
                   2130: #ifdef DEBUG_TREE
                   2131:     xmlGenericError(xmlGenericErrorContext,
                   2132:            "xmlRemoveProp : attribute not owned by its node\n");
                   2133: #endif
                   2134:     return(-1);
                   2135: }
                   2136: 
                   2137: /**
                   2138:  * xmlNewDocPI:
                   2139:  * @doc:  the target document
                   2140:  * @name:  the processing instruction name
                   2141:  * @content:  the PI content
                   2142:  *
                   2143:  * Creation of a processing instruction element.
                   2144:  * Returns a pointer to the new node object.
                   2145:  */
                   2146: xmlNodePtr
                   2147: xmlNewDocPI(xmlDocPtr doc, const xmlChar *name, const xmlChar *content) {
                   2148:     xmlNodePtr cur;
                   2149: 
                   2150:     if (name == NULL) {
                   2151: #ifdef DEBUG_TREE
                   2152:         xmlGenericError(xmlGenericErrorContext,
                   2153:                "xmlNewPI : name == NULL\n");
                   2154: #endif
                   2155:        return(NULL);
                   2156:     }
                   2157: 
                   2158:     /*
                   2159:      * Allocate a new node and fill the fields.
                   2160:      */
                   2161:     cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
                   2162:     if (cur == NULL) {
                   2163:        xmlTreeErrMemory("building PI");
                   2164:        return(NULL);
                   2165:     }
                   2166:     memset(cur, 0, sizeof(xmlNode));
                   2167:     cur->type = XML_PI_NODE;
                   2168: 
                   2169:     if ((doc != NULL) && (doc->dict != NULL))
                   2170:         cur->name = xmlDictLookup(doc->dict, name, -1);
                   2171:     else
                   2172:        cur->name = xmlStrdup(name);
                   2173:     if (content != NULL) {
                   2174:        cur->content = xmlStrdup(content);
                   2175:     }
                   2176:     cur->doc = doc;
                   2177: 
                   2178:     if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
                   2179:        xmlRegisterNodeDefaultValue((xmlNodePtr)cur);
                   2180:     return(cur);
                   2181: }
                   2182: 
                   2183: /**
                   2184:  * xmlNewPI:
                   2185:  * @name:  the processing instruction name
                   2186:  * @content:  the PI content
                   2187:  *
                   2188:  * Creation of a processing instruction element.
                   2189:  * Use xmlDocNewPI preferably to get string interning
                   2190:  *
                   2191:  * Returns a pointer to the new node object.
                   2192:  */
                   2193: xmlNodePtr
                   2194: xmlNewPI(const xmlChar *name, const xmlChar *content) {
                   2195:     return(xmlNewDocPI(NULL, name, content));
                   2196: }
                   2197: 
                   2198: /**
                   2199:  * xmlNewNode:
                   2200:  * @ns:  namespace if any
                   2201:  * @name:  the node name
                   2202:  *
                   2203:  * Creation of a new node element. @ns is optional (NULL).
                   2204:  *
                   2205:  * Returns a pointer to the new node object. Uses xmlStrdup() to make
                   2206:  * copy of @name.
                   2207:  */
                   2208: xmlNodePtr
                   2209: xmlNewNode(xmlNsPtr ns, const xmlChar *name) {
                   2210:     xmlNodePtr cur;
                   2211: 
                   2212:     if (name == NULL) {
                   2213: #ifdef DEBUG_TREE
                   2214:         xmlGenericError(xmlGenericErrorContext,
                   2215:                "xmlNewNode : name == NULL\n");
                   2216: #endif
                   2217:        return(NULL);
                   2218:     }
                   2219: 
                   2220:     /*
                   2221:      * Allocate a new node and fill the fields.
                   2222:      */
                   2223:     cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
                   2224:     if (cur == NULL) {
                   2225:        xmlTreeErrMemory("building node");
                   2226:        return(NULL);
                   2227:     }
                   2228:     memset(cur, 0, sizeof(xmlNode));
                   2229:     cur->type = XML_ELEMENT_NODE;
                   2230: 
                   2231:     cur->name = xmlStrdup(name);
                   2232:     cur->ns = ns;
                   2233: 
                   2234:     if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
                   2235:        xmlRegisterNodeDefaultValue(cur);
                   2236:     return(cur);
                   2237: }
                   2238: 
                   2239: /**
                   2240:  * xmlNewNodeEatName:
                   2241:  * @ns:  namespace if any
                   2242:  * @name:  the node name
                   2243:  *
                   2244:  * Creation of a new node element. @ns is optional (NULL).
                   2245:  *
                   2246:  * Returns a pointer to the new node object, with pointer @name as
                   2247:  * new node's name. Use xmlNewNode() if a copy of @name string is
                   2248:  * is needed as new node's name.
                   2249:  */
                   2250: xmlNodePtr
                   2251: xmlNewNodeEatName(xmlNsPtr ns, xmlChar *name) {
                   2252:     xmlNodePtr cur;
                   2253: 
                   2254:     if (name == NULL) {
                   2255: #ifdef DEBUG_TREE
                   2256:         xmlGenericError(xmlGenericErrorContext,
                   2257:                "xmlNewNode : name == NULL\n");
                   2258: #endif
                   2259:        return(NULL);
                   2260:     }
                   2261: 
                   2262:     /*
                   2263:      * Allocate a new node and fill the fields.
                   2264:      */
                   2265:     cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
                   2266:     if (cur == NULL) {
                   2267:        xmlTreeErrMemory("building node");
                   2268:        /* we can't check here that name comes from the doc dictionnary */
                   2269:        return(NULL);
                   2270:     }
                   2271:     memset(cur, 0, sizeof(xmlNode));
                   2272:     cur->type = XML_ELEMENT_NODE;
                   2273: 
                   2274:     cur->name = name;
                   2275:     cur->ns = ns;
                   2276: 
                   2277:     if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
                   2278:        xmlRegisterNodeDefaultValue((xmlNodePtr)cur);
                   2279:     return(cur);
                   2280: }
                   2281: 
                   2282: /**
                   2283:  * xmlNewDocNode:
                   2284:  * @doc:  the document
                   2285:  * @ns:  namespace if any
                   2286:  * @name:  the node name
                   2287:  * @content:  the XML text content if any
                   2288:  *
                   2289:  * Creation of a new node element within a document. @ns and @content
                   2290:  * are optional (NULL).
                   2291:  * NOTE: @content is supposed to be a piece of XML CDATA, so it allow entities
                   2292:  *       references, but XML special chars need to be escaped first by using
                   2293:  *       xmlEncodeEntitiesReentrant(). Use xmlNewDocRawNode() if you don't
                   2294:  *       need entities support.
                   2295:  *
                   2296:  * Returns a pointer to the new node object.
                   2297:  */
                   2298: xmlNodePtr
                   2299: xmlNewDocNode(xmlDocPtr doc, xmlNsPtr ns,
                   2300:               const xmlChar *name, const xmlChar *content) {
                   2301:     xmlNodePtr cur;
                   2302: 
                   2303:     if ((doc != NULL) && (doc->dict != NULL))
                   2304:         cur = xmlNewNodeEatName(ns, (xmlChar *)
                   2305:                                xmlDictLookup(doc->dict, name, -1));
                   2306:     else
                   2307:        cur = xmlNewNode(ns, name);
                   2308:     if (cur != NULL) {
                   2309:         cur->doc = doc;
                   2310:        if (content != NULL) {
                   2311:            cur->children = xmlStringGetNodeList(doc, content);
                   2312:            UPDATE_LAST_CHILD_AND_PARENT(cur)
                   2313:        }
                   2314:     }
                   2315: 
                   2316:     return(cur);
                   2317: }
                   2318: 
                   2319: /**
                   2320:  * xmlNewDocNodeEatName:
                   2321:  * @doc:  the document
                   2322:  * @ns:  namespace if any
                   2323:  * @name:  the node name
                   2324:  * @content:  the XML text content if any
                   2325:  *
                   2326:  * Creation of a new node element within a document. @ns and @content
                   2327:  * are optional (NULL).
                   2328:  * NOTE: @content is supposed to be a piece of XML CDATA, so it allow entities
                   2329:  *       references, but XML special chars need to be escaped first by using
                   2330:  *       xmlEncodeEntitiesReentrant(). Use xmlNewDocRawNode() if you don't
                   2331:  *       need entities support.
                   2332:  *
                   2333:  * Returns a pointer to the new node object.
                   2334:  */
                   2335: xmlNodePtr
                   2336: xmlNewDocNodeEatName(xmlDocPtr doc, xmlNsPtr ns,
                   2337:               xmlChar *name, const xmlChar *content) {
                   2338:     xmlNodePtr cur;
                   2339: 
                   2340:     cur = xmlNewNodeEatName(ns, name);
                   2341:     if (cur != NULL) {
                   2342:         cur->doc = doc;
                   2343:        if (content != NULL) {
                   2344:            cur->children = xmlStringGetNodeList(doc, content);
                   2345:            UPDATE_LAST_CHILD_AND_PARENT(cur)
                   2346:        }
                   2347:     } else {
                   2348:         /* if name don't come from the doc dictionnary free it here */
                   2349:         if ((name != NULL) && (doc != NULL) &&
                   2350:            (!(xmlDictOwns(doc->dict, name))))
                   2351:            xmlFree(name);
                   2352:     }
                   2353:     return(cur);
                   2354: }
                   2355: 
                   2356: #ifdef LIBXML_TREE_ENABLED
                   2357: /**
                   2358:  * xmlNewDocRawNode:
                   2359:  * @doc:  the document
                   2360:  * @ns:  namespace if any
                   2361:  * @name:  the node name
                   2362:  * @content:  the text content if any
                   2363:  *
                   2364:  * Creation of a new node element within a document. @ns and @content
                   2365:  * are optional (NULL).
                   2366:  *
                   2367:  * Returns a pointer to the new node object.
                   2368:  */
                   2369: xmlNodePtr
                   2370: xmlNewDocRawNode(xmlDocPtr doc, xmlNsPtr ns,
                   2371:                  const xmlChar *name, const xmlChar *content) {
                   2372:     xmlNodePtr cur;
                   2373: 
                   2374:     cur = xmlNewDocNode(doc, ns, name, NULL);
                   2375:     if (cur != NULL) {
                   2376:         cur->doc = doc;
                   2377:        if (content != NULL) {
                   2378:            cur->children = xmlNewDocText(doc, content);
                   2379:            UPDATE_LAST_CHILD_AND_PARENT(cur)
                   2380:        }
                   2381:     }
                   2382:     return(cur);
                   2383: }
                   2384: 
                   2385: /**
                   2386:  * xmlNewDocFragment:
                   2387:  * @doc:  the document owning the fragment
                   2388:  *
                   2389:  * Creation of a new Fragment node.
                   2390:  * Returns a pointer to the new node object.
                   2391:  */
                   2392: xmlNodePtr
                   2393: xmlNewDocFragment(xmlDocPtr doc) {
                   2394:     xmlNodePtr cur;
                   2395: 
                   2396:     /*
                   2397:      * Allocate a new DocumentFragment node and fill the fields.
                   2398:      */
                   2399:     cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
                   2400:     if (cur == NULL) {
                   2401:        xmlTreeErrMemory("building fragment");
                   2402:        return(NULL);
                   2403:     }
                   2404:     memset(cur, 0, sizeof(xmlNode));
                   2405:     cur->type = XML_DOCUMENT_FRAG_NODE;
                   2406: 
                   2407:     cur->doc = doc;
                   2408: 
                   2409:     if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
                   2410:        xmlRegisterNodeDefaultValue(cur);
                   2411:     return(cur);
                   2412: }
                   2413: #endif /* LIBXML_TREE_ENABLED */
                   2414: 
                   2415: /**
                   2416:  * xmlNewText:
                   2417:  * @content:  the text content
                   2418:  *
                   2419:  * Creation of a new text node.
                   2420:  * Returns a pointer to the new node object.
                   2421:  */
                   2422: xmlNodePtr
                   2423: xmlNewText(const xmlChar *content) {
                   2424:     xmlNodePtr cur;
                   2425: 
                   2426:     /*
                   2427:      * Allocate a new node and fill the fields.
                   2428:      */
                   2429:     cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
                   2430:     if (cur == NULL) {
                   2431:        xmlTreeErrMemory("building text");
                   2432:        return(NULL);
                   2433:     }
                   2434:     memset(cur, 0, sizeof(xmlNode));
                   2435:     cur->type = XML_TEXT_NODE;
                   2436: 
                   2437:     cur->name = xmlStringText;
                   2438:     if (content != NULL) {
                   2439:        cur->content = xmlStrdup(content);
                   2440:     }
                   2441: 
                   2442:     if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
                   2443:        xmlRegisterNodeDefaultValue(cur);
                   2444:     return(cur);
                   2445: }
                   2446: 
                   2447: #ifdef LIBXML_TREE_ENABLED
                   2448: /**
                   2449:  * xmlNewTextChild:
                   2450:  * @parent:  the parent node
                   2451:  * @ns:  a namespace if any
                   2452:  * @name:  the name of the child
                   2453:  * @content:  the text content of the child if any.
                   2454:  *
                   2455:  * Creation of a new child element, added at the end of @parent children list.
                   2456:  * @ns and @content parameters are optional (NULL). If @ns is NULL, the newly
                   2457:  * created element inherits the namespace of @parent. If @content is non NULL,
                   2458:  * a child TEXT node will be created containing the string @content.
                   2459:  * NOTE: Use xmlNewChild() if @content will contain entities that need to be
                   2460:  * preserved. Use this function, xmlNewTextChild(), if you need to ensure that
                   2461:  * reserved XML chars that might appear in @content, such as the ampersand,
                   2462:  * greater-than or less-than signs, are automatically replaced by their XML
                   2463:  * escaped entity representations.
                   2464:  *
                   2465:  * Returns a pointer to the new node object.
                   2466:  */
                   2467: xmlNodePtr
                   2468: xmlNewTextChild(xmlNodePtr parent, xmlNsPtr ns,
                   2469:             const xmlChar *name, const xmlChar *content) {
                   2470:     xmlNodePtr cur, prev;
                   2471: 
                   2472:     if (parent == NULL) {
                   2473: #ifdef DEBUG_TREE
                   2474:         xmlGenericError(xmlGenericErrorContext,
                   2475:                "xmlNewTextChild : parent == NULL\n");
                   2476: #endif
                   2477:        return(NULL);
                   2478:     }
                   2479: 
                   2480:     if (name == NULL) {
                   2481: #ifdef DEBUG_TREE
                   2482:         xmlGenericError(xmlGenericErrorContext,
                   2483:                "xmlNewTextChild : name == NULL\n");
                   2484: #endif
                   2485:        return(NULL);
                   2486:     }
                   2487: 
                   2488:     /*
                   2489:      * Allocate a new node
                   2490:      */
                   2491:     if (parent->type == XML_ELEMENT_NODE) {
                   2492:        if (ns == NULL)
                   2493:            cur = xmlNewDocRawNode(parent->doc, parent->ns, name, content);
                   2494:        else
                   2495:            cur = xmlNewDocRawNode(parent->doc, ns, name, content);
                   2496:     } else if ((parent->type == XML_DOCUMENT_NODE) ||
                   2497:               (parent->type == XML_HTML_DOCUMENT_NODE)) {
                   2498:        if (ns == NULL)
                   2499:            cur = xmlNewDocRawNode((xmlDocPtr) parent, NULL, name, content);
                   2500:        else
                   2501:            cur = xmlNewDocRawNode((xmlDocPtr) parent, ns, name, content);
                   2502:     } else if (parent->type == XML_DOCUMENT_FRAG_NODE) {
                   2503:            cur = xmlNewDocRawNode( parent->doc, ns, name, content);
                   2504:     } else {
                   2505:        return(NULL);
                   2506:     }
                   2507:     if (cur == NULL) return(NULL);
                   2508: 
                   2509:     /*
                   2510:      * add the new element at the end of the children list.
                   2511:      */
                   2512:     cur->type = XML_ELEMENT_NODE;
                   2513:     cur->parent = parent;
                   2514:     cur->doc = parent->doc;
                   2515:     if (parent->children == NULL) {
                   2516:         parent->children = cur;
                   2517:        parent->last = cur;
                   2518:     } else {
                   2519:         prev = parent->last;
                   2520:        prev->next = cur;
                   2521:        cur->prev = prev;
                   2522:        parent->last = cur;
                   2523:     }
                   2524: 
                   2525:     return(cur);
                   2526: }
                   2527: #endif /* LIBXML_TREE_ENABLED */
                   2528: 
                   2529: /**
                   2530:  * xmlNewCharRef:
                   2531:  * @doc: the document
                   2532:  * @name:  the char ref string, starting with # or "&# ... ;"
                   2533:  *
                   2534:  * Creation of a new character reference node.
                   2535:  * Returns a pointer to the new node object.
                   2536:  */
                   2537: xmlNodePtr
                   2538: xmlNewCharRef(xmlDocPtr doc, const xmlChar *name) {
                   2539:     xmlNodePtr cur;
                   2540: 
                   2541:     if (name == NULL)
                   2542:         return(NULL);
                   2543: 
                   2544:     /*
                   2545:      * Allocate a new node and fill the fields.
                   2546:      */
                   2547:     cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
                   2548:     if (cur == NULL) {
                   2549:        xmlTreeErrMemory("building character reference");
                   2550:        return(NULL);
                   2551:     }
                   2552:     memset(cur, 0, sizeof(xmlNode));
                   2553:     cur->type = XML_ENTITY_REF_NODE;
                   2554: 
                   2555:     cur->doc = doc;
                   2556:     if (name[0] == '&') {
                   2557:         int len;
                   2558:         name++;
                   2559:        len = xmlStrlen(name);
                   2560:        if (name[len - 1] == ';')
                   2561:            cur->name = xmlStrndup(name, len - 1);
                   2562:        else
                   2563:            cur->name = xmlStrndup(name, len);
                   2564:     } else
                   2565:        cur->name = xmlStrdup(name);
                   2566: 
                   2567:     if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
                   2568:        xmlRegisterNodeDefaultValue(cur);
                   2569:     return(cur);
                   2570: }
                   2571: 
                   2572: /**
                   2573:  * xmlNewReference:
                   2574:  * @doc: the document
                   2575:  * @name:  the reference name, or the reference string with & and ;
                   2576:  *
                   2577:  * Creation of a new reference node.
                   2578:  * Returns a pointer to the new node object.
                   2579:  */
                   2580: xmlNodePtr
                   2581: xmlNewReference(xmlDocPtr doc, const xmlChar *name) {
                   2582:     xmlNodePtr cur;
                   2583:     xmlEntityPtr ent;
                   2584: 
                   2585:     if (name == NULL)
                   2586:         return(NULL);
                   2587: 
                   2588:     /*
                   2589:      * Allocate a new node and fill the fields.
                   2590:      */
                   2591:     cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
                   2592:     if (cur == NULL) {
                   2593:        xmlTreeErrMemory("building reference");
                   2594:        return(NULL);
                   2595:     }
                   2596:     memset(cur, 0, sizeof(xmlNode));
                   2597:     cur->type = XML_ENTITY_REF_NODE;
                   2598: 
                   2599:     cur->doc = doc;
                   2600:     if (name[0] == '&') {
                   2601:         int len;
                   2602:         name++;
                   2603:        len = xmlStrlen(name);
                   2604:        if (name[len - 1] == ';')
                   2605:            cur->name = xmlStrndup(name, len - 1);
                   2606:        else
                   2607:            cur->name = xmlStrndup(name, len);
                   2608:     } else
                   2609:        cur->name = xmlStrdup(name);
                   2610: 
                   2611:     ent = xmlGetDocEntity(doc, cur->name);
                   2612:     if (ent != NULL) {
                   2613:        cur->content = ent->content;
                   2614:        /*
                   2615:         * The parent pointer in entity is a DTD pointer and thus is NOT
                   2616:         * updated.  Not sure if this is 100% correct.
                   2617:         *  -George
                   2618:         */
                   2619:        cur->children = (xmlNodePtr) ent;
                   2620:        cur->last = (xmlNodePtr) ent;
                   2621:     }
                   2622: 
                   2623:     if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
                   2624:        xmlRegisterNodeDefaultValue(cur);
                   2625:     return(cur);
                   2626: }
                   2627: 
                   2628: /**
                   2629:  * xmlNewDocText:
                   2630:  * @doc: the document
                   2631:  * @content:  the text content
                   2632:  *
                   2633:  * Creation of a new text node within a document.
                   2634:  * Returns a pointer to the new node object.
                   2635:  */
                   2636: xmlNodePtr
                   2637: xmlNewDocText(xmlDocPtr doc, const xmlChar *content) {
                   2638:     xmlNodePtr cur;
                   2639: 
                   2640:     cur = xmlNewText(content);
                   2641:     if (cur != NULL) cur->doc = doc;
                   2642:     return(cur);
                   2643: }
                   2644: 
                   2645: /**
                   2646:  * xmlNewTextLen:
                   2647:  * @content:  the text content
                   2648:  * @len:  the text len.
                   2649:  *
                   2650:  * Creation of a new text node with an extra parameter for the content's length
                   2651:  * Returns a pointer to the new node object.
                   2652:  */
                   2653: xmlNodePtr
                   2654: xmlNewTextLen(const xmlChar *content, int len) {
                   2655:     xmlNodePtr cur;
                   2656: 
                   2657:     /*
                   2658:      * Allocate a new node and fill the fields.
                   2659:      */
                   2660:     cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
                   2661:     if (cur == NULL) {
                   2662:        xmlTreeErrMemory("building text");
                   2663:        return(NULL);
                   2664:     }
                   2665:     memset(cur, 0, sizeof(xmlNode));
                   2666:     cur->type = XML_TEXT_NODE;
                   2667: 
                   2668:     cur->name = xmlStringText;
                   2669:     if (content != NULL) {
                   2670:        cur->content = xmlStrndup(content, len);
                   2671:     }
                   2672: 
                   2673:     if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
                   2674:        xmlRegisterNodeDefaultValue(cur);
                   2675:     return(cur);
                   2676: }
                   2677: 
                   2678: /**
                   2679:  * xmlNewDocTextLen:
                   2680:  * @doc: the document
                   2681:  * @content:  the text content
                   2682:  * @len:  the text len.
                   2683:  *
                   2684:  * Creation of a new text node with an extra content length parameter. The
                   2685:  * text node pertain to a given document.
                   2686:  * Returns a pointer to the new node object.
                   2687:  */
                   2688: xmlNodePtr
                   2689: xmlNewDocTextLen(xmlDocPtr doc, const xmlChar *content, int len) {
                   2690:     xmlNodePtr cur;
                   2691: 
                   2692:     cur = xmlNewTextLen(content, len);
                   2693:     if (cur != NULL) cur->doc = doc;
                   2694:     return(cur);
                   2695: }
                   2696: 
                   2697: /**
                   2698:  * xmlNewComment:
                   2699:  * @content:  the comment content
                   2700:  *
                   2701:  * Creation of a new node containing a comment.
                   2702:  * Returns a pointer to the new node object.
                   2703:  */
                   2704: xmlNodePtr
                   2705: xmlNewComment(const xmlChar *content) {
                   2706:     xmlNodePtr cur;
                   2707: 
                   2708:     /*
                   2709:      * Allocate a new node and fill the fields.
                   2710:      */
                   2711:     cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
                   2712:     if (cur == NULL) {
                   2713:        xmlTreeErrMemory("building comment");
                   2714:        return(NULL);
                   2715:     }
                   2716:     memset(cur, 0, sizeof(xmlNode));
                   2717:     cur->type = XML_COMMENT_NODE;
                   2718: 
                   2719:     cur->name = xmlStringComment;
                   2720:     if (content != NULL) {
                   2721:        cur->content = xmlStrdup(content);
                   2722:     }
                   2723: 
                   2724:     if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
                   2725:        xmlRegisterNodeDefaultValue(cur);
                   2726:     return(cur);
                   2727: }
                   2728: 
                   2729: /**
                   2730:  * xmlNewCDataBlock:
                   2731:  * @doc:  the document
                   2732:  * @content:  the CDATA block content content
                   2733:  * @len:  the length of the block
                   2734:  *
                   2735:  * Creation of a new node containing a CDATA block.
                   2736:  * Returns a pointer to the new node object.
                   2737:  */
                   2738: xmlNodePtr
                   2739: xmlNewCDataBlock(xmlDocPtr doc, const xmlChar *content, int len) {
                   2740:     xmlNodePtr cur;
                   2741: 
                   2742:     /*
                   2743:      * Allocate a new node and fill the fields.
                   2744:      */
                   2745:     cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
                   2746:     if (cur == NULL) {
                   2747:        xmlTreeErrMemory("building CDATA");
                   2748:        return(NULL);
                   2749:     }
                   2750:     memset(cur, 0, sizeof(xmlNode));
                   2751:     cur->type = XML_CDATA_SECTION_NODE;
                   2752:     cur->doc = doc;
                   2753: 
                   2754:     if (content != NULL) {
                   2755:        cur->content = xmlStrndup(content, len);
                   2756:     }
                   2757: 
                   2758:     if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
                   2759:        xmlRegisterNodeDefaultValue(cur);
                   2760:     return(cur);
                   2761: }
                   2762: 
                   2763: /**
                   2764:  * xmlNewDocComment:
                   2765:  * @doc:  the document
                   2766:  * @content:  the comment content
                   2767:  *
                   2768:  * Creation of a new node containing a comment within a document.
                   2769:  * Returns a pointer to the new node object.
                   2770:  */
                   2771: xmlNodePtr
                   2772: xmlNewDocComment(xmlDocPtr doc, const xmlChar *content) {
                   2773:     xmlNodePtr cur;
                   2774: 
                   2775:     cur = xmlNewComment(content);
                   2776:     if (cur != NULL) cur->doc = doc;
                   2777:     return(cur);
                   2778: }
                   2779: 
                   2780: /**
                   2781:  * xmlSetTreeDoc:
                   2782:  * @tree:  the top element
                   2783:  * @doc:  the document
                   2784:  *
                   2785:  * update all nodes under the tree to point to the right document
                   2786:  */
                   2787: void
                   2788: xmlSetTreeDoc(xmlNodePtr tree, xmlDocPtr doc) {
                   2789:     xmlAttrPtr prop;
                   2790: 
1.1.1.3 ! misho    2791:     if ((tree == NULL) || (tree->type == XML_NAMESPACE_DECL))
1.1       misho    2792:        return;
                   2793:     if (tree->doc != doc) {
                   2794:        if(tree->type == XML_ELEMENT_NODE) {
                   2795:            prop = tree->properties;
                   2796:            while (prop != NULL) {
                   2797:                prop->doc = doc;
                   2798:                xmlSetListDoc(prop->children, doc);
                   2799:                prop = prop->next;
                   2800:            }
                   2801:        }
                   2802:        if (tree->children != NULL)
                   2803:            xmlSetListDoc(tree->children, doc);
                   2804:        tree->doc = doc;
                   2805:     }
                   2806: }
                   2807: 
                   2808: /**
                   2809:  * xmlSetListDoc:
                   2810:  * @list:  the first element
                   2811:  * @doc:  the document
                   2812:  *
                   2813:  * update all nodes in the list to point to the right document
                   2814:  */
                   2815: void
                   2816: xmlSetListDoc(xmlNodePtr list, xmlDocPtr doc) {
                   2817:     xmlNodePtr cur;
                   2818: 
1.1.1.3 ! misho    2819:     if ((list == NULL) || (list->type == XML_NAMESPACE_DECL))
1.1       misho    2820:        return;
                   2821:     cur = list;
                   2822:     while (cur != NULL) {
                   2823:        if (cur->doc != doc)
                   2824:            xmlSetTreeDoc(cur, doc);
                   2825:        cur = cur->next;
                   2826:     }
                   2827: }
                   2828: 
                   2829: #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
                   2830: /**
                   2831:  * xmlNewChild:
                   2832:  * @parent:  the parent node
                   2833:  * @ns:  a namespace if any
                   2834:  * @name:  the name of the child
                   2835:  * @content:  the XML content of the child if any.
                   2836:  *
                   2837:  * Creation of a new child element, added at the end of @parent children list.
                   2838:  * @ns and @content parameters are optional (NULL). If @ns is NULL, the newly
                   2839:  * created element inherits the namespace of @parent. If @content is non NULL,
                   2840:  * a child list containing the TEXTs and ENTITY_REFs node will be created.
                   2841:  * NOTE: @content is supposed to be a piece of XML CDATA, so it allows entity
                   2842:  *       references. XML special chars must be escaped first by using
                   2843:  *       xmlEncodeEntitiesReentrant(), or xmlNewTextChild() should be used.
                   2844:  *
                   2845:  * Returns a pointer to the new node object.
                   2846:  */
                   2847: xmlNodePtr
                   2848: xmlNewChild(xmlNodePtr parent, xmlNsPtr ns,
                   2849:             const xmlChar *name, const xmlChar *content) {
                   2850:     xmlNodePtr cur, prev;
                   2851: 
                   2852:     if (parent == NULL) {
                   2853: #ifdef DEBUG_TREE
                   2854:         xmlGenericError(xmlGenericErrorContext,
                   2855:                "xmlNewChild : parent == NULL\n");
                   2856: #endif
                   2857:        return(NULL);
                   2858:     }
                   2859: 
                   2860:     if (name == NULL) {
                   2861: #ifdef DEBUG_TREE
                   2862:         xmlGenericError(xmlGenericErrorContext,
                   2863:                "xmlNewChild : name == NULL\n");
                   2864: #endif
                   2865:        return(NULL);
                   2866:     }
                   2867: 
                   2868:     /*
                   2869:      * Allocate a new node
                   2870:      */
                   2871:     if (parent->type == XML_ELEMENT_NODE) {
                   2872:        if (ns == NULL)
                   2873:            cur = xmlNewDocNode(parent->doc, parent->ns, name, content);
                   2874:        else
                   2875:            cur = xmlNewDocNode(parent->doc, ns, name, content);
                   2876:     } else if ((parent->type == XML_DOCUMENT_NODE) ||
                   2877:               (parent->type == XML_HTML_DOCUMENT_NODE)) {
                   2878:        if (ns == NULL)
                   2879:            cur = xmlNewDocNode((xmlDocPtr) parent, NULL, name, content);
                   2880:        else
                   2881:            cur = xmlNewDocNode((xmlDocPtr) parent, ns, name, content);
                   2882:     } else if (parent->type == XML_DOCUMENT_FRAG_NODE) {
                   2883:            cur = xmlNewDocNode( parent->doc, ns, name, content);
                   2884:     } else {
                   2885:        return(NULL);
                   2886:     }
                   2887:     if (cur == NULL) return(NULL);
                   2888: 
                   2889:     /*
                   2890:      * add the new element at the end of the children list.
                   2891:      */
                   2892:     cur->type = XML_ELEMENT_NODE;
                   2893:     cur->parent = parent;
                   2894:     cur->doc = parent->doc;
                   2895:     if (parent->children == NULL) {
                   2896:         parent->children = cur;
                   2897:        parent->last = cur;
                   2898:     } else {
                   2899:         prev = parent->last;
                   2900:        prev->next = cur;
                   2901:        cur->prev = prev;
                   2902:        parent->last = cur;
                   2903:     }
                   2904: 
                   2905:     return(cur);
                   2906: }
                   2907: #endif /* LIBXML_TREE_ENABLED */
                   2908: 
                   2909: /**
                   2910:  * xmlAddPropSibling:
                   2911:  * @prev:  the attribute to which @prop is added after
                   2912:  * @cur:   the base attribute passed to calling function
                   2913:  * @prop:  the new attribute
                   2914:  *
                   2915:  * Add a new attribute after @prev using @cur as base attribute.
                   2916:  * When inserting before @cur, @prev is passed as @cur->prev.
                   2917:  * When inserting after @cur, @prev is passed as @cur.
                   2918:  * If an existing attribute is found it is detroyed prior to adding @prop.
                   2919:  *
                   2920:  * Returns the attribute being inserted or NULL in case of error.
                   2921:  */
                   2922: static xmlNodePtr
                   2923: xmlAddPropSibling(xmlNodePtr prev, xmlNodePtr cur, xmlNodePtr prop) {
                   2924:        xmlAttrPtr attr;
                   2925: 
1.1.1.3 ! misho    2926:        if ((cur == NULL) || (cur->type != XML_ATTRIBUTE_NODE) ||
        !          2927:            (prop == NULL) || (prop->type != XML_ATTRIBUTE_NODE) ||
        !          2928:            ((prev != NULL) && (prev->type != XML_ATTRIBUTE_NODE)))
1.1       misho    2929:                return(NULL);
                   2930: 
                   2931:        /* check if an attribute with the same name exists */
                   2932:        if (prop->ns == NULL)
                   2933:                attr = xmlHasNsProp(cur->parent, prop->name, NULL);
                   2934:        else
                   2935:                attr = xmlHasNsProp(cur->parent, prop->name, prop->ns->href);
                   2936: 
                   2937:        if (prop->doc != cur->doc) {
                   2938:                xmlSetTreeDoc(prop, cur->doc);
                   2939:        }
                   2940:        prop->parent = cur->parent;
                   2941:        prop->prev = prev;
                   2942:        if (prev != NULL) {
                   2943:                prop->next = prev->next;
                   2944:                prev->next = prop;
                   2945:                if (prop->next)
                   2946:                        prop->next->prev = prop;
                   2947:        } else {
                   2948:                prop->next = cur;
                   2949:                cur->prev = prop;
                   2950:        }
                   2951:        if (prop->prev == NULL && prop->parent != NULL)
                   2952:                prop->parent->properties = (xmlAttrPtr) prop;
                   2953:        if ((attr != NULL) && (attr->type != XML_ATTRIBUTE_DECL)) {
                   2954:                /* different instance, destroy it (attributes must be unique) */
                   2955:                xmlRemoveProp((xmlAttrPtr) attr);
                   2956:        }
                   2957:        return prop;
                   2958: }
                   2959: 
                   2960: /**
                   2961:  * xmlAddNextSibling:
                   2962:  * @cur:  the child node
                   2963:  * @elem:  the new node
                   2964:  *
                   2965:  * Add a new node @elem as the next sibling of @cur
                   2966:  * If the new node was already inserted in a document it is
                   2967:  * first unlinked from its existing context.
                   2968:  * As a result of text merging @elem may be freed.
                   2969:  * If the new node is ATTRIBUTE, it is added into properties instead of children.
                   2970:  * If there is an attribute with equal name, it is first destroyed.
                   2971:  *
                   2972:  * Returns the new node or NULL in case of error.
                   2973:  */
                   2974: xmlNodePtr
                   2975: xmlAddNextSibling(xmlNodePtr cur, xmlNodePtr elem) {
1.1.1.3 ! misho    2976:     if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL)) {
1.1       misho    2977: #ifdef DEBUG_TREE
                   2978:         xmlGenericError(xmlGenericErrorContext,
                   2979:                "xmlAddNextSibling : cur == NULL\n");
                   2980: #endif
                   2981:        return(NULL);
                   2982:     }
1.1.1.3 ! misho    2983:     if ((elem == NULL) || (elem->type == XML_NAMESPACE_DECL)) {
1.1       misho    2984: #ifdef DEBUG_TREE
                   2985:         xmlGenericError(xmlGenericErrorContext,
                   2986:                "xmlAddNextSibling : elem == NULL\n");
                   2987: #endif
                   2988:        return(NULL);
                   2989:     }
                   2990: 
                   2991:     if (cur == elem) {
                   2992: #ifdef DEBUG_TREE
                   2993:         xmlGenericError(xmlGenericErrorContext,
                   2994:                "xmlAddNextSibling : cur == elem\n");
                   2995: #endif
                   2996:        return(NULL);
                   2997:     }
                   2998: 
                   2999:     xmlUnlinkNode(elem);
                   3000: 
                   3001:     if (elem->type == XML_TEXT_NODE) {
                   3002:        if (cur->type == XML_TEXT_NODE) {
                   3003:            xmlNodeAddContent(cur, elem->content);
                   3004:            xmlFreeNode(elem);
                   3005:            return(cur);
                   3006:        }
                   3007:        if ((cur->next != NULL) && (cur->next->type == XML_TEXT_NODE) &&
                   3008:             (cur->name == cur->next->name)) {
                   3009:            xmlChar *tmp;
                   3010: 
                   3011:            tmp = xmlStrdup(elem->content);
                   3012:            tmp = xmlStrcat(tmp, cur->next->content);
                   3013:            xmlNodeSetContent(cur->next, tmp);
                   3014:            xmlFree(tmp);
                   3015:            xmlFreeNode(elem);
                   3016:            return(cur->next);
                   3017:        }
                   3018:     } else if (elem->type == XML_ATTRIBUTE_NODE) {
                   3019:                return xmlAddPropSibling(cur, cur, elem);
                   3020:     }
                   3021: 
                   3022:     if (elem->doc != cur->doc) {
                   3023:        xmlSetTreeDoc(elem, cur->doc);
                   3024:     }
                   3025:     elem->parent = cur->parent;
                   3026:     elem->prev = cur;
                   3027:     elem->next = cur->next;
                   3028:     cur->next = elem;
                   3029:     if (elem->next != NULL)
                   3030:        elem->next->prev = elem;
                   3031:     if ((elem->parent != NULL) && (elem->parent->last == cur))
                   3032:        elem->parent->last = elem;
                   3033:     return(elem);
                   3034: }
                   3035: 
                   3036: #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_HTML_ENABLED) || \
                   3037:     defined(LIBXML_SCHEMAS_ENABLED)
                   3038: /**
                   3039:  * xmlAddPrevSibling:
                   3040:  * @cur:  the child node
                   3041:  * @elem:  the new node
                   3042:  *
                   3043:  * Add a new node @elem as the previous sibling of @cur
                   3044:  * merging adjacent TEXT nodes (@elem may be freed)
                   3045:  * If the new node was already inserted in a document it is
                   3046:  * first unlinked from its existing context.
                   3047:  * If the new node is ATTRIBUTE, it is added into properties instead of children.
                   3048:  * If there is an attribute with equal name, it is first destroyed.
                   3049:  *
                   3050:  * Returns the new node or NULL in case of error.
                   3051:  */
                   3052: xmlNodePtr
                   3053: xmlAddPrevSibling(xmlNodePtr cur, xmlNodePtr elem) {
1.1.1.3 ! misho    3054:     if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL)) {
1.1       misho    3055: #ifdef DEBUG_TREE
                   3056:         xmlGenericError(xmlGenericErrorContext,
                   3057:                "xmlAddPrevSibling : cur == NULL\n");
                   3058: #endif
                   3059:        return(NULL);
                   3060:     }
1.1.1.3 ! misho    3061:     if ((elem == NULL) || (elem->type == XML_NAMESPACE_DECL)) {
1.1       misho    3062: #ifdef DEBUG_TREE
                   3063:         xmlGenericError(xmlGenericErrorContext,
                   3064:                "xmlAddPrevSibling : elem == NULL\n");
                   3065: #endif
                   3066:        return(NULL);
                   3067:     }
                   3068: 
                   3069:     if (cur == elem) {
                   3070: #ifdef DEBUG_TREE
                   3071:         xmlGenericError(xmlGenericErrorContext,
                   3072:                "xmlAddPrevSibling : cur == elem\n");
                   3073: #endif
                   3074:        return(NULL);
                   3075:     }
                   3076: 
                   3077:     xmlUnlinkNode(elem);
                   3078: 
                   3079:     if (elem->type == XML_TEXT_NODE) {
                   3080:        if (cur->type == XML_TEXT_NODE) {
                   3081:            xmlChar *tmp;
                   3082: 
                   3083:            tmp = xmlStrdup(elem->content);
                   3084:            tmp = xmlStrcat(tmp, cur->content);
                   3085:            xmlNodeSetContent(cur, tmp);
                   3086:            xmlFree(tmp);
                   3087:            xmlFreeNode(elem);
                   3088:            return(cur);
                   3089:        }
                   3090:        if ((cur->prev != NULL) && (cur->prev->type == XML_TEXT_NODE) &&
                   3091:             (cur->name == cur->prev->name)) {
                   3092:            xmlNodeAddContent(cur->prev, elem->content);
                   3093:            xmlFreeNode(elem);
                   3094:            return(cur->prev);
                   3095:        }
                   3096:     } else if (elem->type == XML_ATTRIBUTE_NODE) {
                   3097:                return xmlAddPropSibling(cur->prev, cur, elem);
                   3098:     }
                   3099: 
                   3100:     if (elem->doc != cur->doc) {
                   3101:        xmlSetTreeDoc(elem, cur->doc);
                   3102:     }
                   3103:     elem->parent = cur->parent;
                   3104:     elem->next = cur;
                   3105:     elem->prev = cur->prev;
                   3106:     cur->prev = elem;
                   3107:     if (elem->prev != NULL)
                   3108:        elem->prev->next = elem;
                   3109:     if ((elem->parent != NULL) && (elem->parent->children == cur)) {
                   3110:                elem->parent->children = elem;
                   3111:     }
                   3112:     return(elem);
                   3113: }
                   3114: #endif /* LIBXML_TREE_ENABLED */
                   3115: 
                   3116: /**
                   3117:  * xmlAddSibling:
                   3118:  * @cur:  the child node
                   3119:  * @elem:  the new node
                   3120:  *
                   3121:  * Add a new element @elem to the list of siblings of @cur
                   3122:  * merging adjacent TEXT nodes (@elem may be freed)
                   3123:  * If the new element was already inserted in a document it is
                   3124:  * first unlinked from its existing context.
                   3125:  *
                   3126:  * Returns the new element or NULL in case of error.
                   3127:  */
                   3128: xmlNodePtr
                   3129: xmlAddSibling(xmlNodePtr cur, xmlNodePtr elem) {
                   3130:     xmlNodePtr parent;
                   3131: 
1.1.1.3 ! misho    3132:     if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL)) {
1.1       misho    3133: #ifdef DEBUG_TREE
                   3134:         xmlGenericError(xmlGenericErrorContext,
                   3135:                "xmlAddSibling : cur == NULL\n");
                   3136: #endif
                   3137:        return(NULL);
                   3138:     }
                   3139: 
1.1.1.3 ! misho    3140:     if ((elem == NULL) || (elem->type == XML_NAMESPACE_DECL)) {
1.1       misho    3141: #ifdef DEBUG_TREE
                   3142:         xmlGenericError(xmlGenericErrorContext,
                   3143:                "xmlAddSibling : elem == NULL\n");
                   3144: #endif
                   3145:        return(NULL);
                   3146:     }
                   3147: 
                   3148:     if (cur == elem) {
                   3149: #ifdef DEBUG_TREE
                   3150:         xmlGenericError(xmlGenericErrorContext,
                   3151:                "xmlAddSibling : cur == elem\n");
                   3152: #endif
                   3153:        return(NULL);
                   3154:     }
                   3155: 
                   3156:     /*
                   3157:      * Constant time is we can rely on the ->parent->last to find
                   3158:      * the last sibling.
                   3159:      */
                   3160:     if ((cur->type != XML_ATTRIBUTE_NODE) && (cur->parent != NULL) &&
                   3161:        (cur->parent->children != NULL) &&
                   3162:        (cur->parent->last != NULL) &&
                   3163:        (cur->parent->last->next == NULL)) {
                   3164:        cur = cur->parent->last;
                   3165:     } else {
                   3166:        while (cur->next != NULL) cur = cur->next;
                   3167:     }
                   3168: 
                   3169:     xmlUnlinkNode(elem);
                   3170: 
                   3171:     if ((cur->type == XML_TEXT_NODE) && (elem->type == XML_TEXT_NODE) &&
                   3172:         (cur->name == elem->name)) {
                   3173:        xmlNodeAddContent(cur, elem->content);
                   3174:        xmlFreeNode(elem);
                   3175:        return(cur);
                   3176:     } else if (elem->type == XML_ATTRIBUTE_NODE) {
                   3177:                return xmlAddPropSibling(cur, cur, elem);
                   3178:     }
                   3179: 
                   3180:     if (elem->doc != cur->doc) {
                   3181:        xmlSetTreeDoc(elem, cur->doc);
                   3182:     }
                   3183:     parent = cur->parent;
                   3184:     elem->prev = cur;
                   3185:     elem->next = NULL;
                   3186:     elem->parent = parent;
                   3187:     cur->next = elem;
                   3188:     if (parent != NULL)
                   3189:        parent->last = elem;
                   3190: 
                   3191:     return(elem);
                   3192: }
                   3193: 
                   3194: /**
                   3195:  * xmlAddChildList:
                   3196:  * @parent:  the parent node
                   3197:  * @cur:  the first node in the list
                   3198:  *
                   3199:  * Add a list of node at the end of the child list of the parent
                   3200:  * merging adjacent TEXT nodes (@cur may be freed)
                   3201:  *
                   3202:  * Returns the last child or NULL in case of error.
                   3203:  */
                   3204: xmlNodePtr
                   3205: xmlAddChildList(xmlNodePtr parent, xmlNodePtr cur) {
                   3206:     xmlNodePtr prev;
                   3207: 
1.1.1.3 ! misho    3208:     if ((parent == NULL) || (parent->type == XML_NAMESPACE_DECL)) {
1.1       misho    3209: #ifdef DEBUG_TREE
                   3210:         xmlGenericError(xmlGenericErrorContext,
                   3211:                "xmlAddChildList : parent == NULL\n");
                   3212: #endif
                   3213:        return(NULL);
                   3214:     }
                   3215: 
1.1.1.3 ! misho    3216:     if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL)) {
1.1       misho    3217: #ifdef DEBUG_TREE
                   3218:         xmlGenericError(xmlGenericErrorContext,
                   3219:                "xmlAddChildList : child == NULL\n");
                   3220: #endif
                   3221:        return(NULL);
                   3222:     }
                   3223: 
                   3224:     if ((cur->doc != NULL) && (parent->doc != NULL) &&
                   3225:         (cur->doc != parent->doc)) {
                   3226: #ifdef DEBUG_TREE
                   3227:        xmlGenericError(xmlGenericErrorContext,
                   3228:                "Elements moved to a different document\n");
                   3229: #endif
                   3230:     }
                   3231: 
                   3232:     /*
                   3233:      * add the first element at the end of the children list.
                   3234:      */
                   3235: 
                   3236:     if (parent->children == NULL) {
                   3237:         parent->children = cur;
                   3238:     } else {
                   3239:        /*
                   3240:         * If cur and parent->last both are TEXT nodes, then merge them.
                   3241:         */
                   3242:        if ((cur->type == XML_TEXT_NODE) &&
                   3243:            (parent->last->type == XML_TEXT_NODE) &&
                   3244:            (cur->name == parent->last->name)) {
                   3245:            xmlNodeAddContent(parent->last, cur->content);
                   3246:            /*
                   3247:             * if it's the only child, nothing more to be done.
                   3248:             */
                   3249:            if (cur->next == NULL) {
                   3250:                xmlFreeNode(cur);
                   3251:                return(parent->last);
                   3252:            }
                   3253:            prev = cur;
                   3254:            cur = cur->next;
                   3255:            xmlFreeNode(prev);
                   3256:        }
                   3257:         prev = parent->last;
                   3258:        prev->next = cur;
                   3259:        cur->prev = prev;
                   3260:     }
                   3261:     while (cur->next != NULL) {
                   3262:        cur->parent = parent;
                   3263:        if (cur->doc != parent->doc) {
                   3264:            xmlSetTreeDoc(cur, parent->doc);
                   3265:        }
                   3266:         cur = cur->next;
                   3267:     }
                   3268:     cur->parent = parent;
                   3269:     /* the parent may not be linked to a doc ! */
                   3270:     if (cur->doc != parent->doc) {
                   3271:         xmlSetTreeDoc(cur, parent->doc);
                   3272:     }
                   3273:     parent->last = cur;
                   3274: 
                   3275:     return(cur);
                   3276: }
                   3277: 
                   3278: /**
                   3279:  * xmlAddChild:
                   3280:  * @parent:  the parent node
                   3281:  * @cur:  the child node
                   3282:  *
                   3283:  * Add a new node to @parent, at the end of the child (or property) list
                   3284:  * merging adjacent TEXT nodes (in which case @cur is freed)
                   3285:  * If the new node is ATTRIBUTE, it is added into properties instead of children.
                   3286:  * If there is an attribute with equal name, it is first destroyed.
                   3287:  *
                   3288:  * Returns the child or NULL in case of error.
                   3289:  */
                   3290: xmlNodePtr
                   3291: xmlAddChild(xmlNodePtr parent, xmlNodePtr cur) {
                   3292:     xmlNodePtr prev;
                   3293: 
1.1.1.3 ! misho    3294:     if ((parent == NULL) || (parent->type == XML_NAMESPACE_DECL)) {
1.1       misho    3295: #ifdef DEBUG_TREE
                   3296:         xmlGenericError(xmlGenericErrorContext,
                   3297:                "xmlAddChild : parent == NULL\n");
                   3298: #endif
                   3299:        return(NULL);
                   3300:     }
                   3301: 
1.1.1.3 ! misho    3302:     if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL)) {
1.1       misho    3303: #ifdef DEBUG_TREE
                   3304:         xmlGenericError(xmlGenericErrorContext,
                   3305:                "xmlAddChild : child == NULL\n");
                   3306: #endif
                   3307:        return(NULL);
                   3308:     }
                   3309: 
                   3310:     if (parent == cur) {
                   3311: #ifdef DEBUG_TREE
                   3312:         xmlGenericError(xmlGenericErrorContext,
                   3313:                "xmlAddChild : parent == cur\n");
                   3314: #endif
                   3315:        return(NULL);
                   3316:     }
                   3317:     /*
                   3318:      * If cur is a TEXT node, merge its content with adjacent TEXT nodes
                   3319:      * cur is then freed.
                   3320:      */
                   3321:     if (cur->type == XML_TEXT_NODE) {
                   3322:        if ((parent->type == XML_TEXT_NODE) &&
                   3323:            (parent->content != NULL) &&
                   3324:            (parent->name == cur->name)) {
                   3325:            xmlNodeAddContent(parent, cur->content);
                   3326:            xmlFreeNode(cur);
                   3327:            return(parent);
                   3328:        }
                   3329:        if ((parent->last != NULL) && (parent->last->type == XML_TEXT_NODE) &&
                   3330:            (parent->last->name == cur->name) &&
                   3331:            (parent->last != cur)) {
                   3332:            xmlNodeAddContent(parent->last, cur->content);
                   3333:            xmlFreeNode(cur);
                   3334:            return(parent->last);
                   3335:        }
                   3336:     }
                   3337: 
                   3338:     /*
                   3339:      * add the new element at the end of the children list.
                   3340:      */
                   3341:     prev = cur->parent;
                   3342:     cur->parent = parent;
                   3343:     if (cur->doc != parent->doc) {
                   3344:        xmlSetTreeDoc(cur, parent->doc);
                   3345:     }
                   3346:     /* this check prevents a loop on tree-traversions if a developer
                   3347:      * tries to add a node to its parent multiple times
                   3348:      */
                   3349:     if (prev == parent)
                   3350:        return(cur);
                   3351: 
                   3352:     /*
                   3353:      * Coalescing
                   3354:      */
                   3355:     if ((parent->type == XML_TEXT_NODE) &&
                   3356:        (parent->content != NULL) &&
                   3357:        (parent != cur)) {
                   3358:        xmlNodeAddContent(parent, cur->content);
                   3359:        xmlFreeNode(cur);
                   3360:        return(parent);
                   3361:     }
                   3362:     if (cur->type == XML_ATTRIBUTE_NODE) {
                   3363:                if (parent->type != XML_ELEMENT_NODE)
                   3364:                        return(NULL);
                   3365:        if (parent->properties != NULL) {
                   3366:            /* check if an attribute with the same name exists */
                   3367:            xmlAttrPtr lastattr;
                   3368: 
                   3369:            if (cur->ns == NULL)
                   3370:                lastattr = xmlHasNsProp(parent, cur->name, NULL);
                   3371:            else
                   3372:                lastattr = xmlHasNsProp(parent, cur->name, cur->ns->href);
                   3373:            if ((lastattr != NULL) && (lastattr != (xmlAttrPtr) cur) && (lastattr->type != XML_ATTRIBUTE_DECL)) {
                   3374:                /* different instance, destroy it (attributes must be unique) */
                   3375:                        xmlUnlinkNode((xmlNodePtr) lastattr);
                   3376:                xmlFreeProp(lastattr);
                   3377:            }
                   3378:                if (lastattr == (xmlAttrPtr) cur)
                   3379:                        return(cur);
                   3380: 
                   3381:        }
                   3382:        if (parent->properties == NULL) {
                   3383:            parent->properties = (xmlAttrPtr) cur;
                   3384:        } else {
                   3385:            /* find the end */
                   3386:            xmlAttrPtr lastattr = parent->properties;
                   3387:            while (lastattr->next != NULL) {
                   3388:                lastattr = lastattr->next;
                   3389:            }
                   3390:            lastattr->next = (xmlAttrPtr) cur;
                   3391:            ((xmlAttrPtr) cur)->prev = lastattr;
                   3392:        }
                   3393:     } else {
                   3394:        if (parent->children == NULL) {
                   3395:            parent->children = cur;
                   3396:            parent->last = cur;
                   3397:        } else {
                   3398:            prev = parent->last;
                   3399:            prev->next = cur;
                   3400:            cur->prev = prev;
                   3401:            parent->last = cur;
                   3402:        }
                   3403:     }
                   3404:     return(cur);
                   3405: }
                   3406: 
                   3407: /**
                   3408:  * xmlGetLastChild:
                   3409:  * @parent:  the parent node
                   3410:  *
                   3411:  * Search the last child of a node.
                   3412:  * Returns the last child or NULL if none.
                   3413:  */
                   3414: xmlNodePtr
                   3415: xmlGetLastChild(xmlNodePtr parent) {
1.1.1.3 ! misho    3416:     if ((parent == NULL) || (parent->type == XML_NAMESPACE_DECL)) {
1.1       misho    3417: #ifdef DEBUG_TREE
                   3418:         xmlGenericError(xmlGenericErrorContext,
                   3419:                "xmlGetLastChild : parent == NULL\n");
                   3420: #endif
                   3421:        return(NULL);
                   3422:     }
                   3423:     return(parent->last);
                   3424: }
                   3425: 
                   3426: #ifdef LIBXML_TREE_ENABLED
                   3427: /*
                   3428:  * 5 interfaces from DOM ElementTraversal
                   3429:  */
                   3430: 
                   3431: /**
                   3432:  * xmlChildElementCount:
                   3433:  * @parent: the parent node
                   3434:  *
                   3435:  * Finds the current number of child nodes of that element which are
                   3436:  * element nodes.
                   3437:  * Note the handling of entities references is different than in
                   3438:  * the W3C DOM element traversal spec since we don't have back reference
                   3439:  * from entities content to entities references.
                   3440:  *
                   3441:  * Returns the count of element child or 0 if not available
                   3442:  */
                   3443: unsigned long
                   3444: xmlChildElementCount(xmlNodePtr parent) {
                   3445:     unsigned long ret = 0;
                   3446:     xmlNodePtr cur = NULL;
                   3447: 
                   3448:     if (parent == NULL)
                   3449:         return(0);
                   3450:     switch (parent->type) {
                   3451:         case XML_ELEMENT_NODE:
                   3452:         case XML_ENTITY_NODE:
                   3453:         case XML_DOCUMENT_NODE:
                   3454:         case XML_HTML_DOCUMENT_NODE:
                   3455:             cur = parent->children;
                   3456:             break;
                   3457:         default:
                   3458:             return(0);
                   3459:     }
                   3460:     while (cur != NULL) {
                   3461:         if (cur->type == XML_ELEMENT_NODE)
                   3462:             ret++;
                   3463:         cur = cur->next;
                   3464:     }
                   3465:     return(ret);
                   3466: }
                   3467: 
                   3468: /**
                   3469:  * xmlFirstElementChild:
                   3470:  * @parent: the parent node
                   3471:  *
                   3472:  * Finds the first child node of that element which is a Element node
                   3473:  * Note the handling of entities references is different than in
                   3474:  * the W3C DOM element traversal spec since we don't have back reference
                   3475:  * from entities content to entities references.
                   3476:  *
                   3477:  * Returns the first element child or NULL if not available
                   3478:  */
                   3479: xmlNodePtr
                   3480: xmlFirstElementChild(xmlNodePtr parent) {
                   3481:     xmlNodePtr cur = NULL;
                   3482: 
                   3483:     if (parent == NULL)
                   3484:         return(NULL);
                   3485:     switch (parent->type) {
                   3486:         case XML_ELEMENT_NODE:
                   3487:         case XML_ENTITY_NODE:
                   3488:         case XML_DOCUMENT_NODE:
                   3489:         case XML_HTML_DOCUMENT_NODE:
                   3490:             cur = parent->children;
                   3491:             break;
                   3492:         default:
                   3493:             return(NULL);
                   3494:     }
                   3495:     while (cur != NULL) {
                   3496:         if (cur->type == XML_ELEMENT_NODE)
                   3497:             return(cur);
                   3498:         cur = cur->next;
                   3499:     }
                   3500:     return(NULL);
                   3501: }
                   3502: 
                   3503: /**
                   3504:  * xmlLastElementChild:
                   3505:  * @parent: the parent node
                   3506:  *
                   3507:  * Finds the last child node of that element which is a Element node
                   3508:  * Note the handling of entities references is different than in
                   3509:  * the W3C DOM element traversal spec since we don't have back reference
                   3510:  * from entities content to entities references.
                   3511:  *
                   3512:  * Returns the last element child or NULL if not available
                   3513:  */
                   3514: xmlNodePtr
                   3515: xmlLastElementChild(xmlNodePtr parent) {
                   3516:     xmlNodePtr cur = NULL;
                   3517: 
                   3518:     if (parent == NULL)
                   3519:         return(NULL);
                   3520:     switch (parent->type) {
                   3521:         case XML_ELEMENT_NODE:
                   3522:         case XML_ENTITY_NODE:
                   3523:         case XML_DOCUMENT_NODE:
                   3524:         case XML_HTML_DOCUMENT_NODE:
                   3525:             cur = parent->last;
                   3526:             break;
                   3527:         default:
                   3528:             return(NULL);
                   3529:     }
                   3530:     while (cur != NULL) {
                   3531:         if (cur->type == XML_ELEMENT_NODE)
                   3532:             return(cur);
                   3533:         cur = cur->prev;
                   3534:     }
                   3535:     return(NULL);
                   3536: }
                   3537: 
                   3538: /**
                   3539:  * xmlPreviousElementSibling:
                   3540:  * @node: the current node
                   3541:  *
                   3542:  * Finds the first closest previous sibling of the node which is an
                   3543:  * element node.
                   3544:  * Note the handling of entities references is different than in
                   3545:  * the W3C DOM element traversal spec since we don't have back reference
                   3546:  * from entities content to entities references.
                   3547:  *
                   3548:  * Returns the previous element sibling or NULL if not available
                   3549:  */
                   3550: xmlNodePtr
                   3551: xmlPreviousElementSibling(xmlNodePtr node) {
                   3552:     if (node == NULL)
                   3553:         return(NULL);
                   3554:     switch (node->type) {
                   3555:         case XML_ELEMENT_NODE:
                   3556:         case XML_TEXT_NODE:
                   3557:         case XML_CDATA_SECTION_NODE:
                   3558:         case XML_ENTITY_REF_NODE:
                   3559:         case XML_ENTITY_NODE:
                   3560:         case XML_PI_NODE:
                   3561:         case XML_COMMENT_NODE:
                   3562:         case XML_XINCLUDE_START:
                   3563:         case XML_XINCLUDE_END:
                   3564:             node = node->prev;
                   3565:             break;
                   3566:         default:
                   3567:             return(NULL);
                   3568:     }
                   3569:     while (node != NULL) {
                   3570:         if (node->type == XML_ELEMENT_NODE)
                   3571:             return(node);
                   3572:         node = node->prev;
                   3573:     }
                   3574:     return(NULL);
                   3575: }
                   3576: 
                   3577: /**
                   3578:  * xmlNextElementSibling:
                   3579:  * @node: the current node
                   3580:  *
                   3581:  * Finds the first closest next sibling of the node which is an
                   3582:  * element node.
                   3583:  * Note the handling of entities references is different than in
                   3584:  * the W3C DOM element traversal spec since we don't have back reference
                   3585:  * from entities content to entities references.
                   3586:  *
                   3587:  * Returns the next element sibling or NULL if not available
                   3588:  */
                   3589: xmlNodePtr
                   3590: xmlNextElementSibling(xmlNodePtr node) {
                   3591:     if (node == NULL)
                   3592:         return(NULL);
                   3593:     switch (node->type) {
                   3594:         case XML_ELEMENT_NODE:
                   3595:         case XML_TEXT_NODE:
                   3596:         case XML_CDATA_SECTION_NODE:
                   3597:         case XML_ENTITY_REF_NODE:
                   3598:         case XML_ENTITY_NODE:
                   3599:         case XML_PI_NODE:
                   3600:         case XML_COMMENT_NODE:
                   3601:         case XML_DTD_NODE:
                   3602:         case XML_XINCLUDE_START:
                   3603:         case XML_XINCLUDE_END:
                   3604:             node = node->next;
                   3605:             break;
                   3606:         default:
                   3607:             return(NULL);
                   3608:     }
                   3609:     while (node != NULL) {
                   3610:         if (node->type == XML_ELEMENT_NODE)
                   3611:             return(node);
                   3612:         node = node->next;
                   3613:     }
                   3614:     return(NULL);
                   3615: }
                   3616: 
                   3617: #endif /* LIBXML_TREE_ENABLED */
                   3618: 
                   3619: /**
                   3620:  * xmlFreeNodeList:
                   3621:  * @cur:  the first node in the list
                   3622:  *
                   3623:  * Free a node and all its siblings, this is a recursive behaviour, all
                   3624:  * the children are freed too.
                   3625:  */
                   3626: void
                   3627: xmlFreeNodeList(xmlNodePtr cur) {
                   3628:     xmlNodePtr next;
                   3629:     xmlDictPtr dict = NULL;
                   3630: 
                   3631:     if (cur == NULL) return;
                   3632:     if (cur->type == XML_NAMESPACE_DECL) {
                   3633:        xmlFreeNsList((xmlNsPtr) cur);
                   3634:        return;
                   3635:     }
                   3636:     if ((cur->type == XML_DOCUMENT_NODE) ||
                   3637: #ifdef LIBXML_DOCB_ENABLED
                   3638:        (cur->type == XML_DOCB_DOCUMENT_NODE) ||
                   3639: #endif
                   3640:        (cur->type == XML_HTML_DOCUMENT_NODE)) {
                   3641:        xmlFreeDoc((xmlDocPtr) cur);
                   3642:        return;
                   3643:     }
                   3644:     if (cur->doc != NULL) dict = cur->doc->dict;
                   3645:     while (cur != NULL) {
                   3646:         next = cur->next;
                   3647:        if (cur->type != XML_DTD_NODE) {
                   3648: 
                   3649:            if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
                   3650:                xmlDeregisterNodeDefaultValue(cur);
                   3651: 
                   3652:            if ((cur->children != NULL) &&
                   3653:                (cur->type != XML_ENTITY_REF_NODE))
                   3654:                xmlFreeNodeList(cur->children);
                   3655:            if (((cur->type == XML_ELEMENT_NODE) ||
                   3656:                 (cur->type == XML_XINCLUDE_START) ||
                   3657:                 (cur->type == XML_XINCLUDE_END)) &&
                   3658:                (cur->properties != NULL))
                   3659:                xmlFreePropList(cur->properties);
                   3660:            if ((cur->type != XML_ELEMENT_NODE) &&
                   3661:                (cur->type != XML_XINCLUDE_START) &&
                   3662:                (cur->type != XML_XINCLUDE_END) &&
                   3663:                (cur->type != XML_ENTITY_REF_NODE) &&
                   3664:                (cur->content != (xmlChar *) &(cur->properties))) {
                   3665:                DICT_FREE(cur->content)
                   3666:            }
                   3667:            if (((cur->type == XML_ELEMENT_NODE) ||
                   3668:                 (cur->type == XML_XINCLUDE_START) ||
                   3669:                 (cur->type == XML_XINCLUDE_END)) &&
                   3670:                (cur->nsDef != NULL))
                   3671:                xmlFreeNsList(cur->nsDef);
                   3672: 
                   3673:            /*
                   3674:             * When a node is a text node or a comment, it uses a global static
                   3675:             * variable for the name of the node.
                   3676:             * Otherwise the node name might come from the document's
                   3677:             * dictionnary
                   3678:             */
                   3679:            if ((cur->name != NULL) &&
                   3680:                (cur->type != XML_TEXT_NODE) &&
                   3681:                (cur->type != XML_COMMENT_NODE))
                   3682:                DICT_FREE(cur->name)
                   3683:            xmlFree(cur);
                   3684:        }
                   3685:        cur = next;
                   3686:     }
                   3687: }
                   3688: 
                   3689: /**
                   3690:  * xmlFreeNode:
                   3691:  * @cur:  the node
                   3692:  *
                   3693:  * Free a node, this is a recursive behaviour, all the children are freed too.
                   3694:  * This doesn't unlink the child from the list, use xmlUnlinkNode() first.
                   3695:  */
                   3696: void
                   3697: xmlFreeNode(xmlNodePtr cur) {
                   3698:     xmlDictPtr dict = NULL;
                   3699: 
                   3700:     if (cur == NULL) return;
                   3701: 
                   3702:     /* use xmlFreeDtd for DTD nodes */
                   3703:     if (cur->type == XML_DTD_NODE) {
                   3704:        xmlFreeDtd((xmlDtdPtr) cur);
                   3705:        return;
                   3706:     }
                   3707:     if (cur->type == XML_NAMESPACE_DECL) {
                   3708:        xmlFreeNs((xmlNsPtr) cur);
                   3709:         return;
                   3710:     }
                   3711:     if (cur->type == XML_ATTRIBUTE_NODE) {
                   3712:        xmlFreeProp((xmlAttrPtr) cur);
                   3713:        return;
                   3714:     }
                   3715: 
                   3716:     if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
                   3717:        xmlDeregisterNodeDefaultValue(cur);
                   3718: 
                   3719:     if (cur->doc != NULL) dict = cur->doc->dict;
                   3720: 
                   3721:     if (cur->type == XML_ENTITY_DECL) {
                   3722:         xmlEntityPtr ent = (xmlEntityPtr) cur;
                   3723:        DICT_FREE(ent->SystemID);
                   3724:        DICT_FREE(ent->ExternalID);
                   3725:     }
                   3726:     if ((cur->children != NULL) &&
                   3727:        (cur->type != XML_ENTITY_REF_NODE))
                   3728:        xmlFreeNodeList(cur->children);
                   3729:     if (((cur->type == XML_ELEMENT_NODE) ||
                   3730:         (cur->type == XML_XINCLUDE_START) ||
                   3731:         (cur->type == XML_XINCLUDE_END)) &&
                   3732:        (cur->properties != NULL))
                   3733:        xmlFreePropList(cur->properties);
                   3734:     if ((cur->type != XML_ELEMENT_NODE) &&
                   3735:        (cur->content != NULL) &&
                   3736:        (cur->type != XML_ENTITY_REF_NODE) &&
                   3737:        (cur->type != XML_XINCLUDE_END) &&
                   3738:        (cur->type != XML_XINCLUDE_START) &&
                   3739:        (cur->content != (xmlChar *) &(cur->properties))) {
                   3740:        DICT_FREE(cur->content)
                   3741:     }
                   3742: 
                   3743:     /*
                   3744:      * When a node is a text node or a comment, it uses a global static
                   3745:      * variable for the name of the node.
                   3746:      * Otherwise the node name might come from the document's dictionnary
                   3747:      */
                   3748:     if ((cur->name != NULL) &&
                   3749:         (cur->type != XML_TEXT_NODE) &&
                   3750:         (cur->type != XML_COMMENT_NODE))
                   3751:        DICT_FREE(cur->name)
                   3752: 
                   3753:     if (((cur->type == XML_ELEMENT_NODE) ||
                   3754:         (cur->type == XML_XINCLUDE_START) ||
                   3755:         (cur->type == XML_XINCLUDE_END)) &&
                   3756:        (cur->nsDef != NULL))
                   3757:        xmlFreeNsList(cur->nsDef);
                   3758:     xmlFree(cur);
                   3759: }
                   3760: 
                   3761: /**
                   3762:  * xmlUnlinkNode:
                   3763:  * @cur:  the node
                   3764:  *
                   3765:  * Unlink a node from it's current context, the node is not freed
1.1.1.2   misho    3766:  * If one need to free the node, use xmlFreeNode() routine after the
                   3767:  * unlink to discard it.
1.1.1.3 ! misho    3768:  * Note that namespace nodes can't be unlinked as they do not have
        !          3769:  * pointer to their parent.
1.1       misho    3770:  */
                   3771: void
                   3772: xmlUnlinkNode(xmlNodePtr cur) {
                   3773:     if (cur == NULL) {
                   3774: #ifdef DEBUG_TREE
                   3775:         xmlGenericError(xmlGenericErrorContext,
                   3776:                "xmlUnlinkNode : node == NULL\n");
                   3777: #endif
                   3778:        return;
                   3779:     }
1.1.1.3 ! misho    3780:     if (cur->type == XML_NAMESPACE_DECL)
        !          3781:         return;
1.1       misho    3782:     if (cur->type == XML_DTD_NODE) {
                   3783:        xmlDocPtr doc;
                   3784:        doc = cur->doc;
                   3785:        if (doc != NULL) {
                   3786:            if (doc->intSubset == (xmlDtdPtr) cur)
                   3787:                doc->intSubset = NULL;
                   3788:            if (doc->extSubset == (xmlDtdPtr) cur)
                   3789:                doc->extSubset = NULL;
                   3790:        }
                   3791:     }
                   3792:     if (cur->type == XML_ENTITY_DECL) {
                   3793:         xmlDocPtr doc;
                   3794:        doc = cur->doc;
                   3795:        if (doc != NULL) {
                   3796:            if (doc->intSubset != NULL) {
                   3797:                if (xmlHashLookup(doc->intSubset->entities, cur->name) == cur)
                   3798:                    xmlHashRemoveEntry(doc->intSubset->entities, cur->name,
                   3799:                                       NULL);
                   3800:                if (xmlHashLookup(doc->intSubset->pentities, cur->name) == cur)
                   3801:                    xmlHashRemoveEntry(doc->intSubset->pentities, cur->name,
                   3802:                                       NULL);
                   3803:            }
                   3804:            if (doc->extSubset != NULL) {
                   3805:                if (xmlHashLookup(doc->extSubset->entities, cur->name) == cur)
                   3806:                    xmlHashRemoveEntry(doc->extSubset->entities, cur->name,
                   3807:                                       NULL);
                   3808:                if (xmlHashLookup(doc->extSubset->pentities, cur->name) == cur)
                   3809:                    xmlHashRemoveEntry(doc->extSubset->pentities, cur->name,
                   3810:                                       NULL);
                   3811:            }
                   3812:        }
                   3813:     }
                   3814:     if (cur->parent != NULL) {
                   3815:        xmlNodePtr parent;
                   3816:        parent = cur->parent;
                   3817:        if (cur->type == XML_ATTRIBUTE_NODE) {
                   3818:            if (parent->properties == (xmlAttrPtr) cur)
                   3819:                parent->properties = ((xmlAttrPtr) cur)->next;
                   3820:        } else {
                   3821:            if (parent->children == cur)
                   3822:                parent->children = cur->next;
                   3823:            if (parent->last == cur)
                   3824:                parent->last = cur->prev;
                   3825:        }
                   3826:        cur->parent = NULL;
                   3827:     }
                   3828:     if (cur->next != NULL)
                   3829:         cur->next->prev = cur->prev;
                   3830:     if (cur->prev != NULL)
                   3831:         cur->prev->next = cur->next;
                   3832:     cur->next = cur->prev = NULL;
                   3833: }
                   3834: 
                   3835: #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_WRITER_ENABLED)
                   3836: /**
                   3837:  * xmlReplaceNode:
                   3838:  * @old:  the old node
                   3839:  * @cur:  the node
                   3840:  *
                   3841:  * Unlink the old node from its current context, prune the new one
                   3842:  * at the same place. If @cur was already inserted in a document it is
                   3843:  * first unlinked from its existing context.
                   3844:  *
                   3845:  * Returns the @old node
                   3846:  */
                   3847: xmlNodePtr
                   3848: xmlReplaceNode(xmlNodePtr old, xmlNodePtr cur) {
                   3849:     if (old == cur) return(NULL);
1.1.1.3 ! misho    3850:     if ((old == NULL) || (old->type == XML_NAMESPACE_DECL) ||
        !          3851:         (old->parent == NULL)) {
1.1       misho    3852: #ifdef DEBUG_TREE
                   3853:         xmlGenericError(xmlGenericErrorContext,
                   3854:                "xmlReplaceNode : old == NULL or without parent\n");
                   3855: #endif
                   3856:        return(NULL);
                   3857:     }
1.1.1.3 ! misho    3858:     if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL)) {
1.1       misho    3859:        xmlUnlinkNode(old);
                   3860:        return(old);
                   3861:     }
                   3862:     if (cur == old) {
                   3863:        return(old);
                   3864:     }
                   3865:     if ((old->type==XML_ATTRIBUTE_NODE) && (cur->type!=XML_ATTRIBUTE_NODE)) {
                   3866: #ifdef DEBUG_TREE
                   3867:         xmlGenericError(xmlGenericErrorContext,
                   3868:                "xmlReplaceNode : Trying to replace attribute node with other node type\n");
                   3869: #endif
                   3870:        return(old);
                   3871:     }
                   3872:     if ((cur->type==XML_ATTRIBUTE_NODE) && (old->type!=XML_ATTRIBUTE_NODE)) {
                   3873: #ifdef DEBUG_TREE
                   3874:         xmlGenericError(xmlGenericErrorContext,
                   3875:                "xmlReplaceNode : Trying to replace a non-attribute node with attribute node\n");
                   3876: #endif
                   3877:        return(old);
                   3878:     }
                   3879:     xmlUnlinkNode(cur);
                   3880:     xmlSetTreeDoc(cur, old->doc);
                   3881:     cur->parent = old->parent;
                   3882:     cur->next = old->next;
                   3883:     if (cur->next != NULL)
                   3884:        cur->next->prev = cur;
                   3885:     cur->prev = old->prev;
                   3886:     if (cur->prev != NULL)
                   3887:        cur->prev->next = cur;
                   3888:     if (cur->parent != NULL) {
                   3889:        if (cur->type == XML_ATTRIBUTE_NODE) {
                   3890:            if (cur->parent->properties == (xmlAttrPtr)old)
                   3891:                cur->parent->properties = ((xmlAttrPtr) cur);
                   3892:        } else {
                   3893:            if (cur->parent->children == old)
                   3894:                cur->parent->children = cur;
                   3895:            if (cur->parent->last == old)
                   3896:                cur->parent->last = cur;
                   3897:        }
                   3898:     }
                   3899:     old->next = old->prev = NULL;
                   3900:     old->parent = NULL;
                   3901:     return(old);
                   3902: }
                   3903: #endif /* LIBXML_TREE_ENABLED */
                   3904: 
                   3905: /************************************************************************
                   3906:  *                                                                     *
                   3907:  *             Copy operations                                         *
                   3908:  *                                                                     *
                   3909:  ************************************************************************/
                   3910: 
                   3911: /**
                   3912:  * xmlCopyNamespace:
                   3913:  * @cur:  the namespace
                   3914:  *
                   3915:  * Do a copy of the namespace.
                   3916:  *
                   3917:  * Returns: a new #xmlNsPtr, or NULL in case of error.
                   3918:  */
                   3919: xmlNsPtr
                   3920: xmlCopyNamespace(xmlNsPtr cur) {
                   3921:     xmlNsPtr ret;
                   3922: 
                   3923:     if (cur == NULL) return(NULL);
                   3924:     switch (cur->type) {
                   3925:        case XML_LOCAL_NAMESPACE:
                   3926:            ret = xmlNewNs(NULL, cur->href, cur->prefix);
                   3927:            break;
                   3928:        default:
                   3929: #ifdef DEBUG_TREE
                   3930:            xmlGenericError(xmlGenericErrorContext,
                   3931:                    "xmlCopyNamespace: invalid type %d\n", cur->type);
                   3932: #endif
                   3933:            return(NULL);
                   3934:     }
                   3935:     return(ret);
                   3936: }
                   3937: 
                   3938: /**
                   3939:  * xmlCopyNamespaceList:
                   3940:  * @cur:  the first namespace
                   3941:  *
                   3942:  * Do a copy of an namespace list.
                   3943:  *
                   3944:  * Returns: a new #xmlNsPtr, or NULL in case of error.
                   3945:  */
                   3946: xmlNsPtr
                   3947: xmlCopyNamespaceList(xmlNsPtr cur) {
                   3948:     xmlNsPtr ret = NULL;
                   3949:     xmlNsPtr p = NULL,q;
                   3950: 
                   3951:     while (cur != NULL) {
                   3952:         q = xmlCopyNamespace(cur);
                   3953:        if (p == NULL) {
                   3954:            ret = p = q;
                   3955:        } else {
                   3956:            p->next = q;
                   3957:            p = q;
                   3958:        }
                   3959:        cur = cur->next;
                   3960:     }
                   3961:     return(ret);
                   3962: }
                   3963: 
                   3964: static xmlNodePtr
                   3965: xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent);
                   3966: 
                   3967: static xmlAttrPtr
                   3968: xmlCopyPropInternal(xmlDocPtr doc, xmlNodePtr target, xmlAttrPtr cur) {
                   3969:     xmlAttrPtr ret;
                   3970: 
                   3971:     if (cur == NULL) return(NULL);
1.1.1.3 ! misho    3972:     if ((target != NULL) && (target->type != XML_ELEMENT_NODE))
        !          3973:         return(NULL);
1.1       misho    3974:     if (target != NULL)
                   3975:        ret = xmlNewDocProp(target->doc, cur->name, NULL);
                   3976:     else if (doc != NULL)
                   3977:        ret = xmlNewDocProp(doc, cur->name, NULL);
                   3978:     else if (cur->parent != NULL)
                   3979:        ret = xmlNewDocProp(cur->parent->doc, cur->name, NULL);
                   3980:     else if (cur->children != NULL)
                   3981:        ret = xmlNewDocProp(cur->children->doc, cur->name, NULL);
                   3982:     else
                   3983:        ret = xmlNewDocProp(NULL, cur->name, NULL);
                   3984:     if (ret == NULL) return(NULL);
                   3985:     ret->parent = target;
                   3986: 
                   3987:     if ((cur->ns != NULL) && (target != NULL)) {
                   3988:       xmlNsPtr ns;
                   3989: 
                   3990:       ns = xmlSearchNs(target->doc, target, cur->ns->prefix);
                   3991:       if (ns == NULL) {
                   3992:         /*
                   3993:          * Humm, we are copying an element whose namespace is defined
                   3994:          * out of the new tree scope. Search it in the original tree
                   3995:          * and add it at the top of the new tree
                   3996:          */
                   3997:         ns = xmlSearchNs(cur->doc, cur->parent, cur->ns->prefix);
                   3998:         if (ns != NULL) {
                   3999:           xmlNodePtr root = target;
                   4000:           xmlNodePtr pred = NULL;
                   4001: 
                   4002:           while (root->parent != NULL) {
                   4003:             pred = root;
                   4004:             root = root->parent;
                   4005:           }
                   4006:           if (root == (xmlNodePtr) target->doc) {
                   4007:             /* correct possibly cycling above the document elt */
                   4008:             root = pred;
                   4009:           }
                   4010:           ret->ns = xmlNewNs(root, ns->href, ns->prefix);
                   4011:         }
                   4012:       } else {
                   4013:         /*
                   4014:          * we have to find something appropriate here since
                   4015:          * we cant be sure, that the namespce we found is identified
                   4016:          * by the prefix
                   4017:          */
                   4018:         if (xmlStrEqual(ns->href, cur->ns->href)) {
                   4019:           /* this is the nice case */
                   4020:           ret->ns = ns;
                   4021:         } else {
                   4022:           /*
                   4023:            * we are in trouble: we need a new reconcilied namespace.
                   4024:            * This is expensive
                   4025:            */
                   4026:           ret->ns = xmlNewReconciliedNs(target->doc, target, cur->ns);
                   4027:         }
                   4028:       }
                   4029: 
                   4030:     } else
                   4031:         ret->ns = NULL;
                   4032: 
                   4033:     if (cur->children != NULL) {
                   4034:        xmlNodePtr tmp;
                   4035: 
                   4036:        ret->children = xmlStaticCopyNodeList(cur->children, ret->doc, (xmlNodePtr) ret);
                   4037:        ret->last = NULL;
                   4038:        tmp = ret->children;
                   4039:        while (tmp != NULL) {
                   4040:            /* tmp->parent = (xmlNodePtr)ret; */
                   4041:            if (tmp->next == NULL)
                   4042:                ret->last = tmp;
                   4043:            tmp = tmp->next;
                   4044:        }
                   4045:     }
                   4046:     /*
                   4047:      * Try to handle IDs
                   4048:      */
                   4049:     if ((target!= NULL) && (cur!= NULL) &&
                   4050:        (target->doc != NULL) && (cur->doc != NULL) &&
                   4051:        (cur->doc->ids != NULL) && (cur->parent != NULL)) {
                   4052:        if (xmlIsID(cur->doc, cur->parent, cur)) {
                   4053:            xmlChar *id;
                   4054: 
                   4055:            id = xmlNodeListGetString(cur->doc, cur->children, 1);
                   4056:            if (id != NULL) {
                   4057:                xmlAddID(NULL, target->doc, id, ret);
                   4058:                xmlFree(id);
                   4059:            }
                   4060:        }
                   4061:     }
                   4062:     return(ret);
                   4063: }
                   4064: 
                   4065: /**
                   4066:  * xmlCopyProp:
                   4067:  * @target:  the element where the attribute will be grafted
                   4068:  * @cur:  the attribute
                   4069:  *
                   4070:  * Do a copy of the attribute.
                   4071:  *
                   4072:  * Returns: a new #xmlAttrPtr, or NULL in case of error.
                   4073:  */
                   4074: xmlAttrPtr
                   4075: xmlCopyProp(xmlNodePtr target, xmlAttrPtr cur) {
                   4076:        return xmlCopyPropInternal(NULL, target, cur);
                   4077: }
                   4078: 
                   4079: /**
                   4080:  * xmlCopyPropList:
                   4081:  * @target:  the element where the attributes will be grafted
                   4082:  * @cur:  the first attribute
                   4083:  *
                   4084:  * Do a copy of an attribute list.
                   4085:  *
                   4086:  * Returns: a new #xmlAttrPtr, or NULL in case of error.
                   4087:  */
                   4088: xmlAttrPtr
                   4089: xmlCopyPropList(xmlNodePtr target, xmlAttrPtr cur) {
                   4090:     xmlAttrPtr ret = NULL;
                   4091:     xmlAttrPtr p = NULL,q;
                   4092: 
1.1.1.3 ! misho    4093:     if ((target != NULL) && (target->type != XML_ELEMENT_NODE))
        !          4094:         return(NULL);
1.1       misho    4095:     while (cur != NULL) {
                   4096:         q = xmlCopyProp(target, cur);
                   4097:        if (q == NULL)
                   4098:            return(NULL);
                   4099:        if (p == NULL) {
                   4100:            ret = p = q;
                   4101:        } else {
                   4102:            p->next = q;
                   4103:            q->prev = p;
                   4104:            p = q;
                   4105:        }
                   4106:        cur = cur->next;
                   4107:     }
                   4108:     return(ret);
                   4109: }
                   4110: 
                   4111: /*
                   4112:  * NOTE about the CopyNode operations !
                   4113:  *
                   4114:  * They are split into external and internal parts for one
                   4115:  * tricky reason: namespaces. Doing a direct copy of a node
                   4116:  * say RPM:Copyright without changing the namespace pointer to
                   4117:  * something else can produce stale links. One way to do it is
                   4118:  * to keep a reference counter but this doesn't work as soon
                   4119:  * as one move the element or the subtree out of the scope of
                   4120:  * the existing namespace. The actual solution seems to add
                   4121:  * a copy of the namespace at the top of the copied tree if
                   4122:  * not available in the subtree.
                   4123:  * Hence two functions, the public front-end call the inner ones
                   4124:  * The argument "recursive" normally indicates a recursive copy
                   4125:  * of the node with values 0 (no) and 1 (yes).  For XInclude,
                   4126:  * however, we allow a value of 2 to indicate copy properties and
                   4127:  * namespace info, but don't recurse on children.
                   4128:  */
                   4129: 
                   4130: static xmlNodePtr
                   4131: xmlStaticCopyNode(const xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent,
                   4132:                   int extended) {
                   4133:     xmlNodePtr ret;
                   4134: 
                   4135:     if (node == NULL) return(NULL);
                   4136:     switch (node->type) {
                   4137:         case XML_TEXT_NODE:
                   4138:         case XML_CDATA_SECTION_NODE:
                   4139:         case XML_ELEMENT_NODE:
                   4140:         case XML_DOCUMENT_FRAG_NODE:
                   4141:         case XML_ENTITY_REF_NODE:
                   4142:         case XML_ENTITY_NODE:
                   4143:         case XML_PI_NODE:
                   4144:         case XML_COMMENT_NODE:
                   4145:         case XML_XINCLUDE_START:
                   4146:         case XML_XINCLUDE_END:
                   4147:            break;
                   4148:         case XML_ATTRIBUTE_NODE:
                   4149:                return((xmlNodePtr) xmlCopyPropInternal(doc, parent, (xmlAttrPtr) node));
                   4150:         case XML_NAMESPACE_DECL:
                   4151:            return((xmlNodePtr) xmlCopyNamespaceList((xmlNsPtr) node));
                   4152: 
                   4153:         case XML_DOCUMENT_NODE:
                   4154:         case XML_HTML_DOCUMENT_NODE:
                   4155: #ifdef LIBXML_DOCB_ENABLED
                   4156:         case XML_DOCB_DOCUMENT_NODE:
                   4157: #endif
                   4158: #ifdef LIBXML_TREE_ENABLED
                   4159:            return((xmlNodePtr) xmlCopyDoc((xmlDocPtr) node, extended));
                   4160: #endif /* LIBXML_TREE_ENABLED */
                   4161:         case XML_DOCUMENT_TYPE_NODE:
                   4162:         case XML_NOTATION_NODE:
                   4163:         case XML_DTD_NODE:
                   4164:         case XML_ELEMENT_DECL:
                   4165:         case XML_ATTRIBUTE_DECL:
                   4166:         case XML_ENTITY_DECL:
                   4167:             return(NULL);
                   4168:     }
                   4169: 
                   4170:     /*
                   4171:      * Allocate a new node and fill the fields.
                   4172:      */
                   4173:     ret = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
                   4174:     if (ret == NULL) {
                   4175:        xmlTreeErrMemory("copying node");
                   4176:        return(NULL);
                   4177:     }
                   4178:     memset(ret, 0, sizeof(xmlNode));
                   4179:     ret->type = node->type;
                   4180: 
                   4181:     ret->doc = doc;
                   4182:     ret->parent = parent;
                   4183:     if (node->name == xmlStringText)
                   4184:        ret->name = xmlStringText;
                   4185:     else if (node->name == xmlStringTextNoenc)
                   4186:        ret->name = xmlStringTextNoenc;
                   4187:     else if (node->name == xmlStringComment)
                   4188:        ret->name = xmlStringComment;
                   4189:     else if (node->name != NULL) {
                   4190:         if ((doc != NULL) && (doc->dict != NULL))
                   4191:            ret->name = xmlDictLookup(doc->dict, node->name, -1);
                   4192:        else
                   4193:            ret->name = xmlStrdup(node->name);
                   4194:     }
                   4195:     if ((node->type != XML_ELEMENT_NODE) &&
                   4196:        (node->content != NULL) &&
                   4197:        (node->type != XML_ENTITY_REF_NODE) &&
                   4198:        (node->type != XML_XINCLUDE_END) &&
                   4199:        (node->type != XML_XINCLUDE_START)) {
                   4200:        ret->content = xmlStrdup(node->content);
                   4201:     }else{
                   4202:       if (node->type == XML_ELEMENT_NODE)
                   4203:         ret->line = node->line;
                   4204:     }
                   4205:     if (parent != NULL) {
                   4206:        xmlNodePtr tmp;
                   4207: 
                   4208:        /*
                   4209:         * this is a tricky part for the node register thing:
                   4210:         * in case ret does get coalesced in xmlAddChild
                   4211:         * the deregister-node callback is called; so we register ret now already
                   4212:         */
                   4213:        if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
                   4214:            xmlRegisterNodeDefaultValue((xmlNodePtr)ret);
                   4215: 
                   4216:         tmp = xmlAddChild(parent, ret);
                   4217:        /* node could have coalesced */
                   4218:        if (tmp != ret)
                   4219:            return(tmp);
                   4220:     }
                   4221: 
                   4222:     if (!extended)
                   4223:        goto out;
                   4224:     if (((node->type == XML_ELEMENT_NODE) ||
                   4225:          (node->type == XML_XINCLUDE_START)) && (node->nsDef != NULL))
                   4226:         ret->nsDef = xmlCopyNamespaceList(node->nsDef);
                   4227: 
                   4228:     if (node->ns != NULL) {
                   4229:         xmlNsPtr ns;
                   4230: 
                   4231:        ns = xmlSearchNs(doc, ret, node->ns->prefix);
                   4232:        if (ns == NULL) {
                   4233:            /*
                   4234:             * Humm, we are copying an element whose namespace is defined
                   4235:             * out of the new tree scope. Search it in the original tree
                   4236:             * and add it at the top of the new tree
                   4237:             */
                   4238:            ns = xmlSearchNs(node->doc, node, node->ns->prefix);
                   4239:            if (ns != NULL) {
                   4240:                xmlNodePtr root = ret;
                   4241: 
                   4242:                while (root->parent != NULL) root = root->parent;
                   4243:                ret->ns = xmlNewNs(root, ns->href, ns->prefix);
                   4244:                } else {
                   4245:                        ret->ns = xmlNewReconciliedNs(doc, ret, node->ns);
                   4246:            }
                   4247:        } else {
                   4248:            /*
                   4249:             * reference the existing namespace definition in our own tree.
                   4250:             */
                   4251:            ret->ns = ns;
                   4252:        }
                   4253:     }
                   4254:     if (((node->type == XML_ELEMENT_NODE) ||
                   4255:          (node->type == XML_XINCLUDE_START)) && (node->properties != NULL))
                   4256:         ret->properties = xmlCopyPropList(ret, node->properties);
                   4257:     if (node->type == XML_ENTITY_REF_NODE) {
                   4258:        if ((doc == NULL) || (node->doc != doc)) {
                   4259:            /*
                   4260:             * The copied node will go into a separate document, so
                   4261:             * to avoid dangling references to the ENTITY_DECL node
                   4262:             * we cannot keep the reference. Try to find it in the
                   4263:             * target document.
                   4264:             */
                   4265:            ret->children = (xmlNodePtr) xmlGetDocEntity(doc, ret->name);
                   4266:        } else {
                   4267:             ret->children = node->children;
                   4268:        }
                   4269:        ret->last = ret->children;
                   4270:     } else if ((node->children != NULL) && (extended != 2)) {
                   4271:         ret->children = xmlStaticCopyNodeList(node->children, doc, ret);
                   4272:        UPDATE_LAST_CHILD_AND_PARENT(ret)
                   4273:     }
                   4274: 
                   4275: out:
                   4276:     /* if parent != NULL we already registered the node above */
                   4277:     if ((parent == NULL) &&
                   4278:         ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue)))
                   4279:        xmlRegisterNodeDefaultValue((xmlNodePtr)ret);
                   4280:     return(ret);
                   4281: }
                   4282: 
                   4283: static xmlNodePtr
                   4284: xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent) {
                   4285:     xmlNodePtr ret = NULL;
                   4286:     xmlNodePtr p = NULL,q;
                   4287: 
                   4288:     while (node != NULL) {
                   4289: #ifdef LIBXML_TREE_ENABLED
                   4290:        if (node->type == XML_DTD_NODE ) {
                   4291:            if (doc == NULL) {
                   4292:                node = node->next;
                   4293:                continue;
                   4294:            }
                   4295:            if (doc->intSubset == NULL) {
                   4296:                q = (xmlNodePtr) xmlCopyDtd( (xmlDtdPtr) node );
                   4297:                q->doc = doc;
                   4298:                q->parent = parent;
                   4299:                doc->intSubset = (xmlDtdPtr) q;
                   4300:                xmlAddChild(parent, q);
                   4301:            } else {
                   4302:                q = (xmlNodePtr) doc->intSubset;
                   4303:                xmlAddChild(parent, q);
                   4304:            }
                   4305:        } else
                   4306: #endif /* LIBXML_TREE_ENABLED */
                   4307:            q = xmlStaticCopyNode(node, doc, parent, 1);
                   4308:        if (ret == NULL) {
                   4309:            q->prev = NULL;
                   4310:            ret = p = q;
                   4311:        } else if (p != q) {
                   4312:        /* the test is required if xmlStaticCopyNode coalesced 2 text nodes */
                   4313:            p->next = q;
                   4314:            q->prev = p;
                   4315:            p = q;
                   4316:        }
                   4317:        node = node->next;
                   4318:     }
                   4319:     return(ret);
                   4320: }
                   4321: 
                   4322: /**
                   4323:  * xmlCopyNode:
                   4324:  * @node:  the node
                   4325:  * @extended:   if 1 do a recursive copy (properties, namespaces and children
                   4326:  *                     when applicable)
                   4327:  *             if 2 copy properties and namespaces (when applicable)
                   4328:  *
                   4329:  * Do a copy of the node.
                   4330:  *
                   4331:  * Returns: a new #xmlNodePtr, or NULL in case of error.
                   4332:  */
                   4333: xmlNodePtr
                   4334: xmlCopyNode(const xmlNodePtr node, int extended) {
                   4335:     xmlNodePtr ret;
                   4336: 
                   4337:     ret = xmlStaticCopyNode(node, NULL, NULL, extended);
                   4338:     return(ret);
                   4339: }
                   4340: 
                   4341: /**
                   4342:  * xmlDocCopyNode:
                   4343:  * @node:  the node
                   4344:  * @doc:  the document
                   4345:  * @extended:   if 1 do a recursive copy (properties, namespaces and children
                   4346:  *                     when applicable)
                   4347:  *             if 2 copy properties and namespaces (when applicable)
                   4348:  *
                   4349:  * Do a copy of the node to a given document.
                   4350:  *
                   4351:  * Returns: a new #xmlNodePtr, or NULL in case of error.
                   4352:  */
                   4353: xmlNodePtr
                   4354: xmlDocCopyNode(const xmlNodePtr node, xmlDocPtr doc, int extended) {
                   4355:     xmlNodePtr ret;
                   4356: 
                   4357:     ret = xmlStaticCopyNode(node, doc, NULL, extended);
                   4358:     return(ret);
                   4359: }
                   4360: 
                   4361: /**
                   4362:  * xmlDocCopyNodeList:
                   4363:  * @doc: the target document
                   4364:  * @node:  the first node in the list.
                   4365:  *
                   4366:  * Do a recursive copy of the node list.
                   4367:  *
                   4368:  * Returns: a new #xmlNodePtr, or NULL in case of error.
                   4369:  */
                   4370: xmlNodePtr xmlDocCopyNodeList(xmlDocPtr doc, const xmlNodePtr node) {
                   4371:     xmlNodePtr ret = xmlStaticCopyNodeList(node, doc, NULL);
                   4372:     return(ret);
                   4373: }
                   4374: 
                   4375: /**
                   4376:  * xmlCopyNodeList:
                   4377:  * @node:  the first node in the list.
                   4378:  *
                   4379:  * Do a recursive copy of the node list.
                   4380:  * Use xmlDocCopyNodeList() if possible to ensure string interning.
                   4381:  *
                   4382:  * Returns: a new #xmlNodePtr, or NULL in case of error.
                   4383:  */
                   4384: xmlNodePtr xmlCopyNodeList(const xmlNodePtr node) {
                   4385:     xmlNodePtr ret = xmlStaticCopyNodeList(node, NULL, NULL);
                   4386:     return(ret);
                   4387: }
                   4388: 
                   4389: #if defined(LIBXML_TREE_ENABLED)
                   4390: /**
                   4391:  * xmlCopyDtd:
                   4392:  * @dtd:  the dtd
                   4393:  *
                   4394:  * Do a copy of the dtd.
                   4395:  *
                   4396:  * Returns: a new #xmlDtdPtr, or NULL in case of error.
                   4397:  */
                   4398: xmlDtdPtr
                   4399: xmlCopyDtd(xmlDtdPtr dtd) {
                   4400:     xmlDtdPtr ret;
                   4401:     xmlNodePtr cur, p = NULL, q;
                   4402: 
                   4403:     if (dtd == NULL) return(NULL);
                   4404:     ret = xmlNewDtd(NULL, dtd->name, dtd->ExternalID, dtd->SystemID);
                   4405:     if (ret == NULL) return(NULL);
                   4406:     if (dtd->entities != NULL)
                   4407:         ret->entities = (void *) xmlCopyEntitiesTable(
                   4408:                            (xmlEntitiesTablePtr) dtd->entities);
                   4409:     if (dtd->notations != NULL)
                   4410:         ret->notations = (void *) xmlCopyNotationTable(
                   4411:                            (xmlNotationTablePtr) dtd->notations);
                   4412:     if (dtd->elements != NULL)
                   4413:         ret->elements = (void *) xmlCopyElementTable(
                   4414:                            (xmlElementTablePtr) dtd->elements);
                   4415:     if (dtd->attributes != NULL)
                   4416:         ret->attributes = (void *) xmlCopyAttributeTable(
                   4417:                            (xmlAttributeTablePtr) dtd->attributes);
                   4418:     if (dtd->pentities != NULL)
                   4419:        ret->pentities = (void *) xmlCopyEntitiesTable(
                   4420:                            (xmlEntitiesTablePtr) dtd->pentities);
                   4421: 
                   4422:     cur = dtd->children;
                   4423:     while (cur != NULL) {
                   4424:        q = NULL;
                   4425: 
                   4426:        if (cur->type == XML_ENTITY_DECL) {
                   4427:            xmlEntityPtr tmp = (xmlEntityPtr) cur;
                   4428:            switch (tmp->etype) {
                   4429:                case XML_INTERNAL_GENERAL_ENTITY:
                   4430:                case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
                   4431:                case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
                   4432:                    q = (xmlNodePtr) xmlGetEntityFromDtd(ret, tmp->name);
                   4433:                    break;
                   4434:                case XML_INTERNAL_PARAMETER_ENTITY:
                   4435:                case XML_EXTERNAL_PARAMETER_ENTITY:
                   4436:                    q = (xmlNodePtr)
                   4437:                        xmlGetParameterEntityFromDtd(ret, tmp->name);
                   4438:                    break;
                   4439:                case XML_INTERNAL_PREDEFINED_ENTITY:
                   4440:                    break;
                   4441:            }
                   4442:        } else if (cur->type == XML_ELEMENT_DECL) {
                   4443:            xmlElementPtr tmp = (xmlElementPtr) cur;
                   4444:            q = (xmlNodePtr)
                   4445:                xmlGetDtdQElementDesc(ret, tmp->name, tmp->prefix);
                   4446:        } else if (cur->type == XML_ATTRIBUTE_DECL) {
                   4447:            xmlAttributePtr tmp = (xmlAttributePtr) cur;
                   4448:            q = (xmlNodePtr)
                   4449:                xmlGetDtdQAttrDesc(ret, tmp->elem, tmp->name, tmp->prefix);
                   4450:        } else if (cur->type == XML_COMMENT_NODE) {
                   4451:            q = xmlCopyNode(cur, 0);
                   4452:        }
                   4453: 
                   4454:        if (q == NULL) {
                   4455:            cur = cur->next;
                   4456:            continue;
                   4457:        }
                   4458: 
                   4459:        if (p == NULL)
                   4460:            ret->children = q;
                   4461:        else
                   4462:            p->next = q;
                   4463: 
                   4464:        q->prev = p;
                   4465:        q->parent = (xmlNodePtr) ret;
                   4466:        q->next = NULL;
                   4467:        ret->last = q;
                   4468:        p = q;
                   4469:        cur = cur->next;
                   4470:     }
                   4471: 
                   4472:     return(ret);
                   4473: }
                   4474: #endif
                   4475: 
                   4476: #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
                   4477: /**
                   4478:  * xmlCopyDoc:
                   4479:  * @doc:  the document
                   4480:  * @recursive:  if not zero do a recursive copy.
                   4481:  *
                   4482:  * Do a copy of the document info. If recursive, the content tree will
                   4483:  * be copied too as well as DTD, namespaces and entities.
                   4484:  *
                   4485:  * Returns: a new #xmlDocPtr, or NULL in case of error.
                   4486:  */
                   4487: xmlDocPtr
                   4488: xmlCopyDoc(xmlDocPtr doc, int recursive) {
                   4489:     xmlDocPtr ret;
                   4490: 
                   4491:     if (doc == NULL) return(NULL);
                   4492:     ret = xmlNewDoc(doc->version);
                   4493:     if (ret == NULL) return(NULL);
                   4494:     if (doc->name != NULL)
                   4495:         ret->name = xmlMemStrdup(doc->name);
                   4496:     if (doc->encoding != NULL)
                   4497:         ret->encoding = xmlStrdup(doc->encoding);
                   4498:     if (doc->URL != NULL)
                   4499:         ret->URL = xmlStrdup(doc->URL);
                   4500:     ret->charset = doc->charset;
                   4501:     ret->compression = doc->compression;
                   4502:     ret->standalone = doc->standalone;
                   4503:     if (!recursive) return(ret);
                   4504: 
                   4505:     ret->last = NULL;
                   4506:     ret->children = NULL;
                   4507: #ifdef LIBXML_TREE_ENABLED
                   4508:     if (doc->intSubset != NULL) {
                   4509:         ret->intSubset = xmlCopyDtd(doc->intSubset);
                   4510:        xmlSetTreeDoc((xmlNodePtr)ret->intSubset, ret);
                   4511:        ret->intSubset->parent = ret;
                   4512:     }
                   4513: #endif
                   4514:     if (doc->oldNs != NULL)
                   4515:         ret->oldNs = xmlCopyNamespaceList(doc->oldNs);
                   4516:     if (doc->children != NULL) {
                   4517:        xmlNodePtr tmp;
                   4518: 
                   4519:        ret->children = xmlStaticCopyNodeList(doc->children, ret,
                   4520:                                               (xmlNodePtr)ret);
                   4521:        ret->last = NULL;
                   4522:        tmp = ret->children;
                   4523:        while (tmp != NULL) {
                   4524:            if (tmp->next == NULL)
                   4525:                ret->last = tmp;
                   4526:            tmp = tmp->next;
                   4527:        }
                   4528:     }
                   4529:     return(ret);
                   4530: }
                   4531: #endif /* LIBXML_TREE_ENABLED */
                   4532: 
                   4533: /************************************************************************
                   4534:  *                                                                     *
                   4535:  *             Content access functions                                *
                   4536:  *                                                                     *
                   4537:  ************************************************************************/
                   4538: 
                   4539: /**
1.1.1.3 ! misho    4540:  * xmlGetLineNoInternal:
1.1       misho    4541:  * @node: valid node
1.1.1.3 ! misho    4542:  * @depth: used to limit any risk of recursion
1.1       misho    4543:  *
1.1.1.3 ! misho    4544:  * Get line number of @node.
        !          4545:  * Try to override the limitation of lines being store in 16 bits ints
1.1       misho    4546:  *
                   4547:  * Returns the line number if successful, -1 otherwise
                   4548:  */
1.1.1.3 ! misho    4549: static long
        !          4550: xmlGetLineNoInternal(xmlNodePtr node, int depth)
1.1       misho    4551: {
                   4552:     long result = -1;
                   4553: 
1.1.1.3 ! misho    4554:     if (depth >= 5)
        !          4555:         return(-1);
        !          4556: 
1.1       misho    4557:     if (!node)
                   4558:         return result;
                   4559:     if ((node->type == XML_ELEMENT_NODE) ||
                   4560:         (node->type == XML_TEXT_NODE) ||
                   4561:        (node->type == XML_COMMENT_NODE) ||
1.1.1.3 ! misho    4562:        (node->type == XML_PI_NODE)) {
        !          4563:        if (node->line == 65535) {
        !          4564:            if ((node->type == XML_TEXT_NODE) && (node->psvi != NULL))
        !          4565:                result = (long) node->psvi;
        !          4566:            else if ((node->type == XML_ELEMENT_NODE) &&
        !          4567:                     (node->children != NULL))
        !          4568:                result = xmlGetLineNoInternal(node->children, depth + 1);
        !          4569:            else if (node->next != NULL)
        !          4570:                result = xmlGetLineNoInternal(node->next, depth + 1);
        !          4571:            else if (node->prev != NULL)
        !          4572:                result = xmlGetLineNoInternal(node->prev, depth + 1);
        !          4573:        }
        !          4574:        if ((result == -1) || (result == 65535))
        !          4575:            result = (long) node->line;
        !          4576:     } else if ((node->prev != NULL) &&
1.1       misho    4577:              ((node->prev->type == XML_ELEMENT_NODE) ||
                   4578:              (node->prev->type == XML_TEXT_NODE) ||
                   4579:              (node->prev->type == XML_COMMENT_NODE) ||
                   4580:              (node->prev->type == XML_PI_NODE)))
1.1.1.3 ! misho    4581:         result = xmlGetLineNoInternal(node->prev, depth + 1);
1.1       misho    4582:     else if ((node->parent != NULL) &&
                   4583:              (node->parent->type == XML_ELEMENT_NODE))
1.1.1.3 ! misho    4584:         result = xmlGetLineNoInternal(node->parent, depth + 1);
1.1       misho    4585: 
                   4586:     return result;
                   4587: }
                   4588: 
1.1.1.3 ! misho    4589: /**
        !          4590:  * xmlGetLineNo:
        !          4591:  * @node: valid node
        !          4592:  *
        !          4593:  * Get line number of @node.
        !          4594:  * Try to override the limitation of lines being store in 16 bits ints
        !          4595:  * if XML_PARSE_BIG_LINES parser option was used
        !          4596:  *
        !          4597:  * Returns the line number if successful, -1 otherwise
        !          4598:  */
        !          4599: long
        !          4600: xmlGetLineNo(xmlNodePtr node)
        !          4601: {
        !          4602:     return(xmlGetLineNoInternal(node, 0));
        !          4603: }
        !          4604: 
1.1       misho    4605: #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_DEBUG_ENABLED)
                   4606: /**
                   4607:  * xmlGetNodePath:
                   4608:  * @node: a node
                   4609:  *
                   4610:  * Build a structure based Path for the given node
                   4611:  *
                   4612:  * Returns the new path or NULL in case of error. The caller must free
                   4613:  *     the returned string
                   4614:  */
                   4615: xmlChar *
                   4616: xmlGetNodePath(xmlNodePtr node)
                   4617: {
                   4618:     xmlNodePtr cur, tmp, next;
                   4619:     xmlChar *buffer = NULL, *temp;
                   4620:     size_t buf_len;
                   4621:     xmlChar *buf;
                   4622:     const char *sep;
                   4623:     const char *name;
                   4624:     char nametemp[100];
                   4625:     int occur = 0, generic;
                   4626: 
1.1.1.3 ! misho    4627:     if ((node == NULL) || (node->type == XML_NAMESPACE_DECL))
1.1       misho    4628:         return (NULL);
                   4629: 
                   4630:     buf_len = 500;
                   4631:     buffer = (xmlChar *) xmlMallocAtomic(buf_len * sizeof(xmlChar));
                   4632:     if (buffer == NULL) {
                   4633:        xmlTreeErrMemory("getting node path");
                   4634:         return (NULL);
                   4635:     }
                   4636:     buf = (xmlChar *) xmlMallocAtomic(buf_len * sizeof(xmlChar));
                   4637:     if (buf == NULL) {
                   4638:        xmlTreeErrMemory("getting node path");
                   4639:         xmlFree(buffer);
                   4640:         return (NULL);
                   4641:     }
                   4642: 
                   4643:     buffer[0] = 0;
                   4644:     cur = node;
                   4645:     do {
                   4646:         name = "";
                   4647:         sep = "?";
                   4648:         occur = 0;
                   4649:         if ((cur->type == XML_DOCUMENT_NODE) ||
                   4650:             (cur->type == XML_HTML_DOCUMENT_NODE)) {
                   4651:             if (buffer[0] == '/')
                   4652:                 break;
                   4653:             sep = "/";
                   4654:             next = NULL;
                   4655:         } else if (cur->type == XML_ELEMENT_NODE) {
                   4656:            generic = 0;
                   4657:             sep = "/";
                   4658:             name = (const char *) cur->name;
                   4659:             if (cur->ns) {
                   4660:                if (cur->ns->prefix != NULL) {
                   4661:                     snprintf(nametemp, sizeof(nametemp) - 1, "%s:%s",
                   4662:                        (char *)cur->ns->prefix, (char *)cur->name);
                   4663:                    nametemp[sizeof(nametemp) - 1] = 0;
                   4664:                    name = nametemp;
                   4665:                } else {
                   4666:                    /*
                   4667:                    * We cannot express named elements in the default
                   4668:                    * namespace, so use "*".
                   4669:                    */
                   4670:                    generic = 1;
                   4671:                    name = "*";
                   4672:                }
                   4673:             }
                   4674:             next = cur->parent;
                   4675: 
                   4676:             /*
                   4677:              * Thumbler index computation
                   4678:             * TODO: the ocurence test seems bogus for namespaced names
                   4679:              */
                   4680:             tmp = cur->prev;
                   4681:             while (tmp != NULL) {
                   4682:                 if ((tmp->type == XML_ELEMENT_NODE) &&
                   4683:                    (generic ||
                   4684:                     (xmlStrEqual(cur->name, tmp->name) &&
                   4685:                     ((tmp->ns == cur->ns) ||
                   4686:                      ((tmp->ns != NULL) && (cur->ns != NULL) &&
                   4687:                       (xmlStrEqual(cur->ns->prefix, tmp->ns->prefix)))))))
                   4688:                     occur++;
                   4689:                 tmp = tmp->prev;
                   4690:             }
                   4691:             if (occur == 0) {
                   4692:                 tmp = cur->next;
                   4693:                 while (tmp != NULL && occur == 0) {
                   4694:                     if ((tmp->type == XML_ELEMENT_NODE) &&
                   4695:                        (generic ||
                   4696:                         (xmlStrEqual(cur->name, tmp->name) &&
                   4697:                         ((tmp->ns == cur->ns) ||
                   4698:                          ((tmp->ns != NULL) && (cur->ns != NULL) &&
                   4699:                           (xmlStrEqual(cur->ns->prefix, tmp->ns->prefix)))))))
                   4700:                         occur++;
                   4701:                     tmp = tmp->next;
                   4702:                 }
                   4703:                 if (occur != 0)
                   4704:                     occur = 1;
                   4705:             } else
                   4706:                 occur++;
                   4707:         } else if (cur->type == XML_COMMENT_NODE) {
                   4708:             sep = "/";
                   4709:            name = "comment()";
                   4710:             next = cur->parent;
                   4711: 
                   4712:             /*
                   4713:              * Thumbler index computation
                   4714:              */
                   4715:             tmp = cur->prev;
                   4716:             while (tmp != NULL) {
                   4717:                 if (tmp->type == XML_COMMENT_NODE)
                   4718:                    occur++;
                   4719:                 tmp = tmp->prev;
                   4720:             }
                   4721:             if (occur == 0) {
                   4722:                 tmp = cur->next;
                   4723:                 while (tmp != NULL && occur == 0) {
                   4724:                  if (tmp->type == XML_COMMENT_NODE)
                   4725:                    occur++;
                   4726:                     tmp = tmp->next;
                   4727:                 }
                   4728:                 if (occur != 0)
                   4729:                     occur = 1;
                   4730:             } else
                   4731:                 occur++;
                   4732:         } else if ((cur->type == XML_TEXT_NODE) ||
                   4733:                    (cur->type == XML_CDATA_SECTION_NODE)) {
                   4734:             sep = "/";
                   4735:            name = "text()";
                   4736:             next = cur->parent;
                   4737: 
                   4738:             /*
                   4739:              * Thumbler index computation
                   4740:              */
                   4741:             tmp = cur->prev;
                   4742:             while (tmp != NULL) {
                   4743:                 if ((tmp->type == XML_TEXT_NODE) ||
                   4744:                    (tmp->type == XML_CDATA_SECTION_NODE))
                   4745:                    occur++;
                   4746:                 tmp = tmp->prev;
                   4747:             }
                   4748:            /*
                   4749:            * Evaluate if this is the only text- or CDATA-section-node;
                   4750:            * if yes, then we'll get "text()", otherwise "text()[1]".
                   4751:            */
                   4752:             if (occur == 0) {
                   4753:                 tmp = cur->next;
                   4754:                 while (tmp != NULL) {
                   4755:                    if ((tmp->type == XML_TEXT_NODE) ||
                   4756:                        (tmp->type == XML_CDATA_SECTION_NODE))
                   4757:                    {
                   4758:                        occur = 1;
                   4759:                        break;
                   4760:                    }
                   4761:                    tmp = tmp->next;
                   4762:                }
                   4763:             } else
                   4764:                 occur++;
                   4765:         } else if (cur->type == XML_PI_NODE) {
                   4766:             sep = "/";
                   4767:            snprintf(nametemp, sizeof(nametemp) - 1,
                   4768:                     "processing-instruction('%s')", (char *)cur->name);
                   4769:             nametemp[sizeof(nametemp) - 1] = 0;
                   4770:             name = nametemp;
                   4771: 
                   4772:            next = cur->parent;
                   4773: 
                   4774:             /*
                   4775:              * Thumbler index computation
                   4776:              */
                   4777:             tmp = cur->prev;
                   4778:             while (tmp != NULL) {
                   4779:                 if ((tmp->type == XML_PI_NODE) &&
                   4780:                    (xmlStrEqual(cur->name, tmp->name)))
                   4781:                     occur++;
                   4782:                 tmp = tmp->prev;
                   4783:             }
                   4784:             if (occur == 0) {
                   4785:                 tmp = cur->next;
                   4786:                 while (tmp != NULL && occur == 0) {
                   4787:                     if ((tmp->type == XML_PI_NODE) &&
                   4788:                        (xmlStrEqual(cur->name, tmp->name)))
                   4789:                         occur++;
                   4790:                     tmp = tmp->next;
                   4791:                 }
                   4792:                 if (occur != 0)
                   4793:                     occur = 1;
                   4794:             } else
                   4795:                 occur++;
                   4796: 
                   4797:         } else if (cur->type == XML_ATTRIBUTE_NODE) {
                   4798:             sep = "/@";
                   4799:             name = (const char *) (((xmlAttrPtr) cur)->name);
                   4800:             if (cur->ns) {
                   4801:                if (cur->ns->prefix != NULL)
                   4802:                     snprintf(nametemp, sizeof(nametemp) - 1, "%s:%s",
                   4803:                        (char *)cur->ns->prefix, (char *)cur->name);
                   4804:                else
                   4805:                    snprintf(nametemp, sizeof(nametemp) - 1, "%s",
                   4806:                        (char *)cur->name);
                   4807:                 nametemp[sizeof(nametemp) - 1] = 0;
                   4808:                 name = nametemp;
                   4809:             }
                   4810:             next = ((xmlAttrPtr) cur)->parent;
                   4811:         } else {
                   4812:             next = cur->parent;
                   4813:         }
                   4814: 
                   4815:         /*
                   4816:          * Make sure there is enough room
                   4817:          */
                   4818:         if (xmlStrlen(buffer) + sizeof(nametemp) + 20 > buf_len) {
                   4819:             buf_len =
                   4820:                 2 * buf_len + xmlStrlen(buffer) + sizeof(nametemp) + 20;
                   4821:             temp = (xmlChar *) xmlRealloc(buffer, buf_len);
                   4822:             if (temp == NULL) {
                   4823:                xmlTreeErrMemory("getting node path");
                   4824:                 xmlFree(buf);
                   4825:                 xmlFree(buffer);
                   4826:                 return (NULL);
                   4827:             }
                   4828:             buffer = temp;
                   4829:             temp = (xmlChar *) xmlRealloc(buf, buf_len);
                   4830:             if (temp == NULL) {
                   4831:                xmlTreeErrMemory("getting node path");
                   4832:                 xmlFree(buf);
                   4833:                 xmlFree(buffer);
                   4834:                 return (NULL);
                   4835:             }
                   4836:             buf = temp;
                   4837:         }
                   4838:         if (occur == 0)
                   4839:             snprintf((char *) buf, buf_len, "%s%s%s",
                   4840:                      sep, name, (char *) buffer);
                   4841:         else
                   4842:             snprintf((char *) buf, buf_len, "%s%s[%d]%s",
                   4843:                      sep, name, occur, (char *) buffer);
                   4844:         snprintf((char *) buffer, buf_len, "%s", (char *)buf);
                   4845:         cur = next;
                   4846:     } while (cur != NULL);
                   4847:     xmlFree(buf);
                   4848:     return (buffer);
                   4849: }
                   4850: #endif /* LIBXML_TREE_ENABLED */
                   4851: 
                   4852: /**
                   4853:  * xmlDocGetRootElement:
                   4854:  * @doc:  the document
                   4855:  *
                   4856:  * Get the root element of the document (doc->children is a list
                   4857:  * containing possibly comments, PIs, etc ...).
                   4858:  *
                   4859:  * Returns the #xmlNodePtr for the root or NULL
                   4860:  */
                   4861: xmlNodePtr
                   4862: xmlDocGetRootElement(xmlDocPtr doc) {
                   4863:     xmlNodePtr ret;
                   4864: 
                   4865:     if (doc == NULL) return(NULL);
                   4866:     ret = doc->children;
                   4867:     while (ret != NULL) {
                   4868:        if (ret->type == XML_ELEMENT_NODE)
                   4869:            return(ret);
                   4870:         ret = ret->next;
                   4871:     }
                   4872:     return(ret);
                   4873: }
                   4874: 
                   4875: #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_WRITER_ENABLED)
                   4876: /**
                   4877:  * xmlDocSetRootElement:
                   4878:  * @doc:  the document
                   4879:  * @root:  the new document root element, if root is NULL no action is taken,
                   4880:  *         to remove a node from a document use xmlUnlinkNode(root) instead.
                   4881:  *
                   4882:  * Set the root element of the document (doc->children is a list
                   4883:  * containing possibly comments, PIs, etc ...).
                   4884:  *
                   4885:  * Returns the old root element if any was found, NULL if root was NULL
                   4886:  */
                   4887: xmlNodePtr
                   4888: xmlDocSetRootElement(xmlDocPtr doc, xmlNodePtr root) {
                   4889:     xmlNodePtr old = NULL;
                   4890: 
                   4891:     if (doc == NULL) return(NULL);
1.1.1.3 ! misho    4892:     if ((root == NULL) || (root->type == XML_NAMESPACE_DECL))
1.1       misho    4893:        return(NULL);
                   4894:     xmlUnlinkNode(root);
                   4895:     xmlSetTreeDoc(root, doc);
                   4896:     root->parent = (xmlNodePtr) doc;
                   4897:     old = doc->children;
                   4898:     while (old != NULL) {
                   4899:        if (old->type == XML_ELEMENT_NODE)
                   4900:            break;
                   4901:         old = old->next;
                   4902:     }
                   4903:     if (old == NULL) {
                   4904:        if (doc->children == NULL) {
                   4905:            doc->children = root;
                   4906:            doc->last = root;
                   4907:        } else {
                   4908:            xmlAddSibling(doc->children, root);
                   4909:        }
                   4910:     } else {
                   4911:        xmlReplaceNode(old, root);
                   4912:     }
                   4913:     return(old);
                   4914: }
                   4915: #endif
                   4916: 
                   4917: #if defined(LIBXML_TREE_ENABLED)
                   4918: /**
                   4919:  * xmlNodeSetLang:
                   4920:  * @cur:  the node being changed
                   4921:  * @lang:  the language description
                   4922:  *
                   4923:  * Set the language of a node, i.e. the values of the xml:lang
                   4924:  * attribute.
                   4925:  */
                   4926: void
                   4927: xmlNodeSetLang(xmlNodePtr cur, const xmlChar *lang) {
                   4928:     xmlNsPtr ns;
                   4929: 
                   4930:     if (cur == NULL) return;
                   4931:     switch(cur->type) {
                   4932:         case XML_TEXT_NODE:
                   4933:         case XML_CDATA_SECTION_NODE:
                   4934:         case XML_COMMENT_NODE:
                   4935:         case XML_DOCUMENT_NODE:
                   4936:         case XML_DOCUMENT_TYPE_NODE:
                   4937:         case XML_DOCUMENT_FRAG_NODE:
                   4938:         case XML_NOTATION_NODE:
                   4939:         case XML_HTML_DOCUMENT_NODE:
                   4940:         case XML_DTD_NODE:
                   4941:         case XML_ELEMENT_DECL:
                   4942:         case XML_ATTRIBUTE_DECL:
                   4943:         case XML_ENTITY_DECL:
                   4944:         case XML_PI_NODE:
                   4945:         case XML_ENTITY_REF_NODE:
                   4946:         case XML_ENTITY_NODE:
                   4947:        case XML_NAMESPACE_DECL:
                   4948: #ifdef LIBXML_DOCB_ENABLED
                   4949:        case XML_DOCB_DOCUMENT_NODE:
                   4950: #endif
                   4951:        case XML_XINCLUDE_START:
                   4952:        case XML_XINCLUDE_END:
                   4953:            return;
                   4954:         case XML_ELEMENT_NODE:
                   4955:         case XML_ATTRIBUTE_NODE:
                   4956:            break;
                   4957:     }
                   4958:     ns = xmlSearchNsByHref(cur->doc, cur, XML_XML_NAMESPACE);
                   4959:     if (ns == NULL)
                   4960:        return;
                   4961:     xmlSetNsProp(cur, ns, BAD_CAST "lang", lang);
                   4962: }
                   4963: #endif /* LIBXML_TREE_ENABLED */
                   4964: 
                   4965: /**
                   4966:  * xmlNodeGetLang:
                   4967:  * @cur:  the node being checked
                   4968:  *
                   4969:  * Searches the language of a node, i.e. the values of the xml:lang
                   4970:  * attribute or the one carried by the nearest ancestor.
                   4971:  *
                   4972:  * Returns a pointer to the lang value, or NULL if not found
                   4973:  *     It's up to the caller to free the memory with xmlFree().
                   4974:  */
                   4975: xmlChar *
                   4976: xmlNodeGetLang(xmlNodePtr cur) {
                   4977:     xmlChar *lang;
                   4978: 
1.1.1.3 ! misho    4979:     if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL))
        !          4980:         return(NULL);
1.1       misho    4981:     while (cur != NULL) {
                   4982:         lang = xmlGetNsProp(cur, BAD_CAST "lang", XML_XML_NAMESPACE);
                   4983:        if (lang != NULL)
                   4984:            return(lang);
                   4985:        cur = cur->parent;
                   4986:     }
                   4987:     return(NULL);
                   4988: }
                   4989: 
                   4990: 
                   4991: #ifdef LIBXML_TREE_ENABLED
                   4992: /**
                   4993:  * xmlNodeSetSpacePreserve:
                   4994:  * @cur:  the node being changed
                   4995:  * @val:  the xml:space value ("0": default, 1: "preserve")
                   4996:  *
                   4997:  * Set (or reset) the space preserving behaviour of a node, i.e. the
                   4998:  * value of the xml:space attribute.
                   4999:  */
                   5000: void
                   5001: xmlNodeSetSpacePreserve(xmlNodePtr cur, int val) {
                   5002:     xmlNsPtr ns;
                   5003: 
                   5004:     if (cur == NULL) return;
                   5005:     switch(cur->type) {
                   5006:         case XML_TEXT_NODE:
                   5007:         case XML_CDATA_SECTION_NODE:
                   5008:         case XML_COMMENT_NODE:
                   5009:         case XML_DOCUMENT_NODE:
                   5010:         case XML_DOCUMENT_TYPE_NODE:
                   5011:         case XML_DOCUMENT_FRAG_NODE:
                   5012:         case XML_NOTATION_NODE:
                   5013:         case XML_HTML_DOCUMENT_NODE:
                   5014:         case XML_DTD_NODE:
                   5015:         case XML_ELEMENT_DECL:
                   5016:         case XML_ATTRIBUTE_DECL:
                   5017:         case XML_ENTITY_DECL:
                   5018:         case XML_PI_NODE:
                   5019:         case XML_ENTITY_REF_NODE:
                   5020:         case XML_ENTITY_NODE:
                   5021:        case XML_NAMESPACE_DECL:
                   5022:        case XML_XINCLUDE_START:
                   5023:        case XML_XINCLUDE_END:
                   5024: #ifdef LIBXML_DOCB_ENABLED
                   5025:        case XML_DOCB_DOCUMENT_NODE:
                   5026: #endif
                   5027:            return;
                   5028:         case XML_ELEMENT_NODE:
                   5029:         case XML_ATTRIBUTE_NODE:
                   5030:            break;
                   5031:     }
                   5032:     ns = xmlSearchNsByHref(cur->doc, cur, XML_XML_NAMESPACE);
                   5033:     if (ns == NULL)
                   5034:        return;
                   5035:     switch (val) {
                   5036:     case 0:
                   5037:        xmlSetNsProp(cur, ns, BAD_CAST "space", BAD_CAST "default");
                   5038:        break;
                   5039:     case 1:
                   5040:        xmlSetNsProp(cur, ns, BAD_CAST "space", BAD_CAST "preserve");
                   5041:        break;
                   5042:     }
                   5043: }
                   5044: #endif /* LIBXML_TREE_ENABLED */
                   5045: 
                   5046: /**
                   5047:  * xmlNodeGetSpacePreserve:
                   5048:  * @cur:  the node being checked
                   5049:  *
                   5050:  * Searches the space preserving behaviour of a node, i.e. the values
                   5051:  * of the xml:space attribute or the one carried by the nearest
                   5052:  * ancestor.
                   5053:  *
                   5054:  * Returns -1 if xml:space is not inherited, 0 if "default", 1 if "preserve"
                   5055:  */
                   5056: int
                   5057: xmlNodeGetSpacePreserve(xmlNodePtr cur) {
                   5058:     xmlChar *space;
                   5059: 
1.1.1.3 ! misho    5060:     if ((cur == NULL) || (cur->type != XML_ELEMENT_NODE))
        !          5061:         return(-1);
1.1       misho    5062:     while (cur != NULL) {
                   5063:        space = xmlGetNsProp(cur, BAD_CAST "space", XML_XML_NAMESPACE);
                   5064:        if (space != NULL) {
                   5065:            if (xmlStrEqual(space, BAD_CAST "preserve")) {
                   5066:                xmlFree(space);
                   5067:                return(1);
                   5068:            }
                   5069:            if (xmlStrEqual(space, BAD_CAST "default")) {
                   5070:                xmlFree(space);
                   5071:                return(0);
                   5072:            }
                   5073:            xmlFree(space);
                   5074:        }
                   5075:        cur = cur->parent;
                   5076:     }
                   5077:     return(-1);
                   5078: }
                   5079: 
                   5080: #ifdef LIBXML_TREE_ENABLED
                   5081: /**
                   5082:  * xmlNodeSetName:
                   5083:  * @cur:  the node being changed
                   5084:  * @name:  the new tag name
                   5085:  *
                   5086:  * Set (or reset) the name of a node.
                   5087:  */
                   5088: void
                   5089: xmlNodeSetName(xmlNodePtr cur, const xmlChar *name) {
                   5090:     xmlDocPtr doc;
                   5091:     xmlDictPtr dict;
                   5092: 
                   5093:     if (cur == NULL) return;
                   5094:     if (name == NULL) return;
                   5095:     switch(cur->type) {
                   5096:         case XML_TEXT_NODE:
                   5097:         case XML_CDATA_SECTION_NODE:
                   5098:         case XML_COMMENT_NODE:
                   5099:         case XML_DOCUMENT_TYPE_NODE:
                   5100:         case XML_DOCUMENT_FRAG_NODE:
                   5101:         case XML_NOTATION_NODE:
                   5102:         case XML_HTML_DOCUMENT_NODE:
                   5103:        case XML_NAMESPACE_DECL:
                   5104:        case XML_XINCLUDE_START:
                   5105:        case XML_XINCLUDE_END:
                   5106: #ifdef LIBXML_DOCB_ENABLED
                   5107:        case XML_DOCB_DOCUMENT_NODE:
                   5108: #endif
                   5109:            return;
                   5110:         case XML_ELEMENT_NODE:
                   5111:         case XML_ATTRIBUTE_NODE:
                   5112:         case XML_PI_NODE:
                   5113:         case XML_ENTITY_REF_NODE:
                   5114:         case XML_ENTITY_NODE:
                   5115:         case XML_DTD_NODE:
                   5116:         case XML_DOCUMENT_NODE:
                   5117:         case XML_ELEMENT_DECL:
                   5118:         case XML_ATTRIBUTE_DECL:
                   5119:         case XML_ENTITY_DECL:
                   5120:            break;
                   5121:     }
                   5122:     doc = cur->doc;
                   5123:     if (doc != NULL)
                   5124:        dict = doc->dict;
                   5125:     else
                   5126:         dict = NULL;
                   5127:     if (dict != NULL) {
                   5128:         if ((cur->name != NULL) && (!xmlDictOwns(dict, cur->name)))
                   5129:            xmlFree((xmlChar *) cur->name);
                   5130:        cur->name = xmlDictLookup(dict, name, -1);
                   5131:     } else {
                   5132:        if (cur->name != NULL) xmlFree((xmlChar *) cur->name);
                   5133:        cur->name = xmlStrdup(name);
                   5134:     }
                   5135: }
                   5136: #endif
                   5137: 
                   5138: #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XINCLUDE_ENABLED)
                   5139: /**
                   5140:  * xmlNodeSetBase:
                   5141:  * @cur:  the node being changed
                   5142:  * @uri:  the new base URI
                   5143:  *
                   5144:  * Set (or reset) the base URI of a node, i.e. the value of the
                   5145:  * xml:base attribute.
                   5146:  */
                   5147: void
                   5148: xmlNodeSetBase(xmlNodePtr cur, const xmlChar* uri) {
                   5149:     xmlNsPtr ns;
                   5150:     xmlChar* fixed;
                   5151: 
                   5152:     if (cur == NULL) return;
                   5153:     switch(cur->type) {
                   5154:         case XML_TEXT_NODE:
                   5155:         case XML_CDATA_SECTION_NODE:
                   5156:         case XML_COMMENT_NODE:
                   5157:         case XML_DOCUMENT_TYPE_NODE:
                   5158:         case XML_DOCUMENT_FRAG_NODE:
                   5159:         case XML_NOTATION_NODE:
                   5160:         case XML_DTD_NODE:
                   5161:         case XML_ELEMENT_DECL:
                   5162:         case XML_ATTRIBUTE_DECL:
                   5163:         case XML_ENTITY_DECL:
                   5164:         case XML_PI_NODE:
                   5165:         case XML_ENTITY_REF_NODE:
                   5166:         case XML_ENTITY_NODE:
                   5167:        case XML_NAMESPACE_DECL:
                   5168:        case XML_XINCLUDE_START:
                   5169:        case XML_XINCLUDE_END:
                   5170:            return;
                   5171:         case XML_ELEMENT_NODE:
                   5172:         case XML_ATTRIBUTE_NODE:
                   5173:            break;
                   5174:         case XML_DOCUMENT_NODE:
                   5175: #ifdef LIBXML_DOCB_ENABLED
                   5176:        case XML_DOCB_DOCUMENT_NODE:
                   5177: #endif
                   5178:         case XML_HTML_DOCUMENT_NODE: {
                   5179:            xmlDocPtr doc = (xmlDocPtr) cur;
                   5180: 
                   5181:            if (doc->URL != NULL)
                   5182:                xmlFree((xmlChar *) doc->URL);
                   5183:            if (uri == NULL)
                   5184:                doc->URL = NULL;
                   5185:            else
                   5186:                doc->URL = xmlPathToURI(uri);
                   5187:            return;
                   5188:        }
                   5189:     }
                   5190: 
                   5191:     ns = xmlSearchNsByHref(cur->doc, cur, XML_XML_NAMESPACE);
                   5192:     if (ns == NULL)
                   5193:        return;
                   5194:     fixed = xmlPathToURI(uri);
                   5195:     if (fixed != NULL) {
                   5196:        xmlSetNsProp(cur, ns, BAD_CAST "base", fixed);
                   5197:        xmlFree(fixed);
                   5198:     } else {
                   5199:        xmlSetNsProp(cur, ns, BAD_CAST "base", uri);
                   5200:     }
                   5201: }
                   5202: #endif /* LIBXML_TREE_ENABLED */
                   5203: 
                   5204: /**
                   5205:  * xmlNodeGetBase:
                   5206:  * @doc:  the document the node pertains to
                   5207:  * @cur:  the node being checked
                   5208:  *
                   5209:  * Searches for the BASE URL. The code should work on both XML
                   5210:  * and HTML document even if base mechanisms are completely different.
                   5211:  * It returns the base as defined in RFC 2396 sections
                   5212:  * 5.1.1. Base URI within Document Content
                   5213:  * and
                   5214:  * 5.1.2. Base URI from the Encapsulating Entity
                   5215:  * However it does not return the document base (5.1.3), use
                   5216:  * doc->URL in this case
                   5217:  *
                   5218:  * Returns a pointer to the base URL, or NULL if not found
                   5219:  *     It's up to the caller to free the memory with xmlFree().
                   5220:  */
                   5221: xmlChar *
                   5222: xmlNodeGetBase(xmlDocPtr doc, xmlNodePtr cur) {
                   5223:     xmlChar *oldbase = NULL;
                   5224:     xmlChar *base, *newbase;
                   5225: 
                   5226:     if ((cur == NULL) && (doc == NULL))
                   5227:         return(NULL);
1.1.1.3 ! misho    5228:     if ((cur != NULL) && (cur->type == XML_NAMESPACE_DECL))
        !          5229:         return(NULL);
1.1       misho    5230:     if (doc == NULL) doc = cur->doc;
                   5231:     if ((doc != NULL) && (doc->type == XML_HTML_DOCUMENT_NODE)) {
                   5232:         cur = doc->children;
                   5233:        while ((cur != NULL) && (cur->name != NULL)) {
                   5234:            if (cur->type != XML_ELEMENT_NODE) {
                   5235:                cur = cur->next;
                   5236:                continue;
                   5237:            }
                   5238:            if (!xmlStrcasecmp(cur->name, BAD_CAST "html")) {
                   5239:                cur = cur->children;
                   5240:                continue;
                   5241:            }
                   5242:            if (!xmlStrcasecmp(cur->name, BAD_CAST "head")) {
                   5243:                cur = cur->children;
                   5244:                continue;
                   5245:            }
                   5246:            if (!xmlStrcasecmp(cur->name, BAD_CAST "base")) {
                   5247:                 return(xmlGetProp(cur, BAD_CAST "href"));
                   5248:            }
                   5249:            cur = cur->next;
                   5250:        }
                   5251:        return(NULL);
                   5252:     }
                   5253:     while (cur != NULL) {
                   5254:        if (cur->type == XML_ENTITY_DECL) {
                   5255:            xmlEntityPtr ent = (xmlEntityPtr) cur;
                   5256:            return(xmlStrdup(ent->URI));
                   5257:        }
                   5258:        if (cur->type == XML_ELEMENT_NODE) {
                   5259:            base = xmlGetNsProp(cur, BAD_CAST "base", XML_XML_NAMESPACE);
                   5260:            if (base != NULL) {
                   5261:                if (oldbase != NULL) {
                   5262:                    newbase = xmlBuildURI(oldbase, base);
                   5263:                    if (newbase != NULL) {
                   5264:                        xmlFree(oldbase);
                   5265:                        xmlFree(base);
                   5266:                        oldbase = newbase;
                   5267:                    } else {
                   5268:                        xmlFree(oldbase);
                   5269:                        xmlFree(base);
                   5270:                        return(NULL);
                   5271:                    }
                   5272:                } else {
                   5273:                    oldbase = base;
                   5274:                }
                   5275:                if ((!xmlStrncmp(oldbase, BAD_CAST "http://", 7)) ||
                   5276:                    (!xmlStrncmp(oldbase, BAD_CAST "ftp://", 6)) ||
                   5277:                    (!xmlStrncmp(oldbase, BAD_CAST "urn:", 4)))
                   5278:                    return(oldbase);
                   5279:            }
                   5280:        }
                   5281:        cur = cur->parent;
                   5282:     }
                   5283:     if ((doc != NULL) && (doc->URL != NULL)) {
                   5284:        if (oldbase == NULL)
                   5285:            return(xmlStrdup(doc->URL));
                   5286:        newbase = xmlBuildURI(oldbase, doc->URL);
                   5287:        xmlFree(oldbase);
                   5288:        return(newbase);
                   5289:     }
                   5290:     return(oldbase);
                   5291: }
                   5292: 
                   5293: /**
                   5294:  * xmlNodeBufGetContent:
                   5295:  * @buffer:  a buffer
                   5296:  * @cur:  the node being read
                   5297:  *
                   5298:  * Read the value of a node @cur, this can be either the text carried
                   5299:  * directly by this node if it's a TEXT node or the aggregate string
                   5300:  * of the values carried by this node child's (TEXT and ENTITY_REF).
                   5301:  * Entity references are substituted.
                   5302:  * Fills up the buffer @buffer with this value
                   5303:  *
                   5304:  * Returns 0 in case of success and -1 in case of error.
                   5305:  */
                   5306: int
                   5307: xmlNodeBufGetContent(xmlBufferPtr buffer, xmlNodePtr cur)
                   5308: {
1.1.1.3 ! misho    5309:     xmlBufPtr buf;
        !          5310:     int ret;
        !          5311: 
1.1       misho    5312:     if ((cur == NULL) || (buffer == NULL)) return(-1);
1.1.1.3 ! misho    5313:     buf = xmlBufFromBuffer(buffer);
        !          5314:     ret = xmlBufGetNodeContent(buf, cur);
        !          5315:     buffer = xmlBufBackToBuffer(buf);
        !          5316:     if ((ret < 0) || (buffer == NULL))
        !          5317:         return(-1);
        !          5318:     return(0);
        !          5319: }
        !          5320: 
        !          5321: /**
        !          5322:  * xmlBufGetNodeContent:
        !          5323:  * @buf:  a buffer xmlBufPtr
        !          5324:  * @cur:  the node being read
        !          5325:  *
        !          5326:  * Read the value of a node @cur, this can be either the text carried
        !          5327:  * directly by this node if it's a TEXT node or the aggregate string
        !          5328:  * of the values carried by this node child's (TEXT and ENTITY_REF).
        !          5329:  * Entity references are substituted.
        !          5330:  * Fills up the buffer @buffer with this value
        !          5331:  *
        !          5332:  * Returns 0 in case of success and -1 in case of error.
        !          5333:  */
        !          5334: int
        !          5335: xmlBufGetNodeContent(xmlBufPtr buf, xmlNodePtr cur)
        !          5336: {
        !          5337:     if ((cur == NULL) || (buf == NULL)) return(-1);
1.1       misho    5338:     switch (cur->type) {
                   5339:         case XML_CDATA_SECTION_NODE:
                   5340:         case XML_TEXT_NODE:
1.1.1.3 ! misho    5341:            xmlBufCat(buf, cur->content);
1.1       misho    5342:             break;
                   5343:         case XML_DOCUMENT_FRAG_NODE:
                   5344:         case XML_ELEMENT_NODE:{
                   5345:                 xmlNodePtr tmp = cur;
                   5346: 
                   5347:                 while (tmp != NULL) {
                   5348:                     switch (tmp->type) {
                   5349:                         case XML_CDATA_SECTION_NODE:
                   5350:                         case XML_TEXT_NODE:
                   5351:                             if (tmp->content != NULL)
1.1.1.3 ! misho    5352:                                 xmlBufCat(buf, tmp->content);
1.1       misho    5353:                             break;
                   5354:                         case XML_ENTITY_REF_NODE:
1.1.1.3 ! misho    5355:                             xmlBufGetNodeContent(buf, tmp);
1.1       misho    5356:                             break;
                   5357:                         default:
                   5358:                             break;
                   5359:                     }
                   5360:                     /*
                   5361:                      * Skip to next node
                   5362:                      */
                   5363:                     if (tmp->children != NULL) {
                   5364:                         if (tmp->children->type != XML_ENTITY_DECL) {
                   5365:                             tmp = tmp->children;
                   5366:                             continue;
                   5367:                         }
                   5368:                     }
                   5369:                     if (tmp == cur)
                   5370:                         break;
                   5371: 
                   5372:                     if (tmp->next != NULL) {
                   5373:                         tmp = tmp->next;
                   5374:                         continue;
                   5375:                     }
                   5376: 
                   5377:                     do {
                   5378:                         tmp = tmp->parent;
                   5379:                         if (tmp == NULL)
                   5380:                             break;
                   5381:                         if (tmp == cur) {
                   5382:                             tmp = NULL;
                   5383:                             break;
                   5384:                         }
                   5385:                         if (tmp->next != NULL) {
                   5386:                             tmp = tmp->next;
                   5387:                             break;
                   5388:                         }
                   5389:                     } while (tmp != NULL);
                   5390:                 }
                   5391:                break;
                   5392:             }
                   5393:         case XML_ATTRIBUTE_NODE:{
                   5394:                 xmlAttrPtr attr = (xmlAttrPtr) cur;
                   5395:                xmlNodePtr tmp = attr->children;
                   5396: 
                   5397:                while (tmp != NULL) {
                   5398:                    if (tmp->type == XML_TEXT_NODE)
1.1.1.3 ! misho    5399:                        xmlBufCat(buf, tmp->content);
1.1       misho    5400:                    else
1.1.1.3 ! misho    5401:                        xmlBufGetNodeContent(buf, tmp);
1.1       misho    5402:                    tmp = tmp->next;
                   5403:                }
                   5404:                 break;
                   5405:             }
                   5406:         case XML_COMMENT_NODE:
                   5407:         case XML_PI_NODE:
1.1.1.3 ! misho    5408:            xmlBufCat(buf, cur->content);
1.1       misho    5409:             break;
                   5410:         case XML_ENTITY_REF_NODE:{
                   5411:                 xmlEntityPtr ent;
                   5412:                 xmlNodePtr tmp;
                   5413: 
                   5414:                 /* lookup entity declaration */
                   5415:                 ent = xmlGetDocEntity(cur->doc, cur->name);
                   5416:                 if (ent == NULL)
                   5417:                     return(-1);
                   5418: 
                   5419:                 /* an entity content can be any "well balanced chunk",
                   5420:                  * i.e. the result of the content [43] production:
                   5421:                  * http://www.w3.org/TR/REC-xml#NT-content
                   5422:                  * -> we iterate through child nodes and recursive call
                   5423:                  * xmlNodeGetContent() which handles all possible node types */
                   5424:                 tmp = ent->children;
                   5425:                 while (tmp) {
1.1.1.3 ! misho    5426:                    xmlBufGetNodeContent(buf, tmp);
1.1       misho    5427:                     tmp = tmp->next;
                   5428:                 }
                   5429:                break;
                   5430:             }
                   5431:         case XML_ENTITY_NODE:
                   5432:         case XML_DOCUMENT_TYPE_NODE:
                   5433:         case XML_NOTATION_NODE:
                   5434:         case XML_DTD_NODE:
                   5435:         case XML_XINCLUDE_START:
                   5436:         case XML_XINCLUDE_END:
                   5437:             break;
                   5438:         case XML_DOCUMENT_NODE:
                   5439: #ifdef LIBXML_DOCB_ENABLED
                   5440:         case XML_DOCB_DOCUMENT_NODE:
                   5441: #endif
                   5442:         case XML_HTML_DOCUMENT_NODE:
                   5443:            cur = cur->children;
                   5444:            while (cur!= NULL) {
                   5445:                if ((cur->type == XML_ELEMENT_NODE) ||
                   5446:                    (cur->type == XML_TEXT_NODE) ||
                   5447:                    (cur->type == XML_CDATA_SECTION_NODE)) {
1.1.1.3 ! misho    5448:                    xmlBufGetNodeContent(buf, cur);
1.1       misho    5449:                }
                   5450:                cur = cur->next;
                   5451:            }
                   5452:            break;
                   5453:         case XML_NAMESPACE_DECL:
1.1.1.3 ! misho    5454:            xmlBufCat(buf, ((xmlNsPtr) cur)->href);
1.1       misho    5455:            break;
                   5456:         case XML_ELEMENT_DECL:
                   5457:         case XML_ATTRIBUTE_DECL:
                   5458:         case XML_ENTITY_DECL:
                   5459:             break;
                   5460:     }
                   5461:     return(0);
                   5462: }
1.1.1.3 ! misho    5463: 
1.1       misho    5464: /**
                   5465:  * xmlNodeGetContent:
                   5466:  * @cur:  the node being read
                   5467:  *
                   5468:  * Read the value of a node, this can be either the text carried
                   5469:  * directly by this node if it's a TEXT node or the aggregate string
                   5470:  * of the values carried by this node child's (TEXT and ENTITY_REF).
                   5471:  * Entity references are substituted.
                   5472:  * Returns a new #xmlChar * or NULL if no content is available.
                   5473:  *     It's up to the caller to free the memory with xmlFree().
                   5474:  */
                   5475: xmlChar *
                   5476: xmlNodeGetContent(xmlNodePtr cur)
                   5477: {
                   5478:     if (cur == NULL)
                   5479:         return (NULL);
                   5480:     switch (cur->type) {
                   5481:         case XML_DOCUMENT_FRAG_NODE:
                   5482:         case XML_ELEMENT_NODE:{
1.1.1.3 ! misho    5483:                 xmlBufPtr buf;
1.1       misho    5484:                 xmlChar *ret;
                   5485: 
1.1.1.3 ! misho    5486:                 buf = xmlBufCreateSize(64);
        !          5487:                 if (buf == NULL)
1.1       misho    5488:                     return (NULL);
1.1.1.3 ! misho    5489:                xmlBufGetNodeContent(buf, cur);
        !          5490:                 ret = xmlBufDetach(buf);
        !          5491:                 xmlBufFree(buf);
1.1       misho    5492:                 return (ret);
                   5493:             }
                   5494:         case XML_ATTRIBUTE_NODE:
                   5495:            return(xmlGetPropNodeValueInternal((xmlAttrPtr) cur));
                   5496:         case XML_COMMENT_NODE:
                   5497:         case XML_PI_NODE:
                   5498:             if (cur->content != NULL)
                   5499:                 return (xmlStrdup(cur->content));
                   5500:             return (NULL);
                   5501:         case XML_ENTITY_REF_NODE:{
                   5502:                 xmlEntityPtr ent;
1.1.1.3 ! misho    5503:                 xmlBufPtr buf;
1.1       misho    5504:                 xmlChar *ret;
                   5505: 
                   5506:                 /* lookup entity declaration */
                   5507:                 ent = xmlGetDocEntity(cur->doc, cur->name);
                   5508:                 if (ent == NULL)
                   5509:                     return (NULL);
                   5510: 
1.1.1.3 ! misho    5511:                 buf = xmlBufCreate();
        !          5512:                 if (buf == NULL)
1.1       misho    5513:                     return (NULL);
                   5514: 
1.1.1.3 ! misho    5515:                 xmlBufGetNodeContent(buf, cur);
1.1       misho    5516: 
1.1.1.3 ! misho    5517:                 ret = xmlBufDetach(buf);
        !          5518:                 xmlBufFree(buf);
1.1       misho    5519:                 return (ret);
                   5520:             }
                   5521:         case XML_ENTITY_NODE:
                   5522:         case XML_DOCUMENT_TYPE_NODE:
                   5523:         case XML_NOTATION_NODE:
                   5524:         case XML_DTD_NODE:
                   5525:         case XML_XINCLUDE_START:
                   5526:         case XML_XINCLUDE_END:
                   5527:             return (NULL);
                   5528:         case XML_DOCUMENT_NODE:
                   5529: #ifdef LIBXML_DOCB_ENABLED
                   5530:         case XML_DOCB_DOCUMENT_NODE:
                   5531: #endif
                   5532:         case XML_HTML_DOCUMENT_NODE: {
1.1.1.3 ! misho    5533:            xmlBufPtr buf;
1.1       misho    5534:            xmlChar *ret;
                   5535: 
1.1.1.3 ! misho    5536:            buf = xmlBufCreate();
        !          5537:            if (buf == NULL)
1.1       misho    5538:                return (NULL);
                   5539: 
1.1.1.3 ! misho    5540:            xmlBufGetNodeContent(buf, (xmlNodePtr) cur);
1.1       misho    5541: 
1.1.1.3 ! misho    5542:            ret = xmlBufDetach(buf);
        !          5543:            xmlBufFree(buf);
1.1       misho    5544:            return (ret);
                   5545:        }
                   5546:         case XML_NAMESPACE_DECL: {
                   5547:            xmlChar *tmp;
                   5548: 
                   5549:            tmp = xmlStrdup(((xmlNsPtr) cur)->href);
                   5550:             return (tmp);
                   5551:        }
                   5552:         case XML_ELEMENT_DECL:
                   5553:             /* TODO !!! */
                   5554:             return (NULL);
                   5555:         case XML_ATTRIBUTE_DECL:
                   5556:             /* TODO !!! */
                   5557:             return (NULL);
                   5558:         case XML_ENTITY_DECL:
                   5559:             /* TODO !!! */
                   5560:             return (NULL);
                   5561:         case XML_CDATA_SECTION_NODE:
                   5562:         case XML_TEXT_NODE:
                   5563:             if (cur->content != NULL)
                   5564:                 return (xmlStrdup(cur->content));
                   5565:             return (NULL);
                   5566:     }
                   5567:     return (NULL);
                   5568: }
                   5569: 
                   5570: /**
                   5571:  * xmlNodeSetContent:
                   5572:  * @cur:  the node being modified
                   5573:  * @content:  the new value of the content
                   5574:  *
                   5575:  * Replace the content of a node.
                   5576:  * NOTE: @content is supposed to be a piece of XML CDATA, so it allows entity
                   5577:  *       references, but XML special chars need to be escaped first by using
                   5578:  *       xmlEncodeEntitiesReentrant() resp. xmlEncodeSpecialChars().
                   5579:  */
                   5580: void
                   5581: xmlNodeSetContent(xmlNodePtr cur, const xmlChar *content) {
                   5582:     if (cur == NULL) {
                   5583: #ifdef DEBUG_TREE
                   5584:         xmlGenericError(xmlGenericErrorContext,
                   5585:                "xmlNodeSetContent : node == NULL\n");
                   5586: #endif
                   5587:        return;
                   5588:     }
                   5589:     switch (cur->type) {
                   5590:         case XML_DOCUMENT_FRAG_NODE:
                   5591:         case XML_ELEMENT_NODE:
                   5592:         case XML_ATTRIBUTE_NODE:
                   5593:            if (cur->children != NULL) xmlFreeNodeList(cur->children);
                   5594:            cur->children = xmlStringGetNodeList(cur->doc, content);
                   5595:            UPDATE_LAST_CHILD_AND_PARENT(cur)
                   5596:            break;
                   5597:         case XML_TEXT_NODE:
                   5598:         case XML_CDATA_SECTION_NODE:
                   5599:         case XML_ENTITY_REF_NODE:
                   5600:         case XML_ENTITY_NODE:
                   5601:         case XML_PI_NODE:
                   5602:         case XML_COMMENT_NODE:
                   5603:            if ((cur->content != NULL) &&
                   5604:                (cur->content != (xmlChar *) &(cur->properties))) {
                   5605:                if (!((cur->doc != NULL) && (cur->doc->dict != NULL) &&
                   5606:                    (xmlDictOwns(cur->doc->dict, cur->content))))
                   5607:                    xmlFree(cur->content);
                   5608:            }
                   5609:            if (cur->children != NULL) xmlFreeNodeList(cur->children);
                   5610:            cur->last = cur->children = NULL;
                   5611:            if (content != NULL) {
                   5612:                cur->content = xmlStrdup(content);
                   5613:            } else
                   5614:                cur->content = NULL;
                   5615:            cur->properties = NULL;
                   5616:            cur->nsDef = NULL;
                   5617:            break;
                   5618:         case XML_DOCUMENT_NODE:
                   5619:         case XML_HTML_DOCUMENT_NODE:
                   5620:         case XML_DOCUMENT_TYPE_NODE:
                   5621:        case XML_XINCLUDE_START:
                   5622:        case XML_XINCLUDE_END:
                   5623: #ifdef LIBXML_DOCB_ENABLED
                   5624:        case XML_DOCB_DOCUMENT_NODE:
                   5625: #endif
                   5626:            break;
                   5627:         case XML_NOTATION_NODE:
                   5628:            break;
                   5629:         case XML_DTD_NODE:
                   5630:            break;
                   5631:        case XML_NAMESPACE_DECL:
                   5632:            break;
                   5633:         case XML_ELEMENT_DECL:
                   5634:            /* TODO !!! */
                   5635:            break;
                   5636:         case XML_ATTRIBUTE_DECL:
                   5637:            /* TODO !!! */
                   5638:            break;
                   5639:         case XML_ENTITY_DECL:
                   5640:            /* TODO !!! */
                   5641:            break;
                   5642:     }
                   5643: }
                   5644: 
                   5645: #ifdef LIBXML_TREE_ENABLED
                   5646: /**
                   5647:  * xmlNodeSetContentLen:
                   5648:  * @cur:  the node being modified
                   5649:  * @content:  the new value of the content
                   5650:  * @len:  the size of @content
                   5651:  *
                   5652:  * Replace the content of a node.
                   5653:  * NOTE: @content is supposed to be a piece of XML CDATA, so it allows entity
                   5654:  *       references, but XML special chars need to be escaped first by using
                   5655:  *       xmlEncodeEntitiesReentrant() resp. xmlEncodeSpecialChars().
                   5656:  */
                   5657: void
                   5658: xmlNodeSetContentLen(xmlNodePtr cur, const xmlChar *content, int len) {
                   5659:     if (cur == NULL) {
                   5660: #ifdef DEBUG_TREE
                   5661:         xmlGenericError(xmlGenericErrorContext,
                   5662:                "xmlNodeSetContentLen : node == NULL\n");
                   5663: #endif
                   5664:        return;
                   5665:     }
                   5666:     switch (cur->type) {
                   5667:         case XML_DOCUMENT_FRAG_NODE:
                   5668:         case XML_ELEMENT_NODE:
                   5669:         case XML_ATTRIBUTE_NODE:
                   5670:            if (cur->children != NULL) xmlFreeNodeList(cur->children);
                   5671:            cur->children = xmlStringLenGetNodeList(cur->doc, content, len);
                   5672:            UPDATE_LAST_CHILD_AND_PARENT(cur)
                   5673:            break;
                   5674:         case XML_TEXT_NODE:
                   5675:         case XML_CDATA_SECTION_NODE:
                   5676:         case XML_ENTITY_REF_NODE:
                   5677:         case XML_ENTITY_NODE:
                   5678:         case XML_PI_NODE:
                   5679:         case XML_COMMENT_NODE:
                   5680:         case XML_NOTATION_NODE:
                   5681:            if ((cur->content != NULL) &&
                   5682:                (cur->content != (xmlChar *) &(cur->properties))) {
                   5683:                if (!((cur->doc != NULL) && (cur->doc->dict != NULL) &&
                   5684:                    (xmlDictOwns(cur->doc->dict, cur->content))))
                   5685:                    xmlFree(cur->content);
                   5686:            }
                   5687:            if (cur->children != NULL) xmlFreeNodeList(cur->children);
                   5688:            cur->children = cur->last = NULL;
                   5689:            if (content != NULL) {
                   5690:                cur->content = xmlStrndup(content, len);
                   5691:            } else
                   5692:                cur->content = NULL;
                   5693:            cur->properties = NULL;
                   5694:            cur->nsDef = NULL;
                   5695:            break;
                   5696:         case XML_DOCUMENT_NODE:
                   5697:         case XML_DTD_NODE:
                   5698:         case XML_HTML_DOCUMENT_NODE:
                   5699:         case XML_DOCUMENT_TYPE_NODE:
                   5700:        case XML_NAMESPACE_DECL:
                   5701:        case XML_XINCLUDE_START:
                   5702:        case XML_XINCLUDE_END:
                   5703: #ifdef LIBXML_DOCB_ENABLED
                   5704:        case XML_DOCB_DOCUMENT_NODE:
                   5705: #endif
                   5706:            break;
                   5707:         case XML_ELEMENT_DECL:
                   5708:            /* TODO !!! */
                   5709:            break;
                   5710:         case XML_ATTRIBUTE_DECL:
                   5711:            /* TODO !!! */
                   5712:            break;
                   5713:         case XML_ENTITY_DECL:
                   5714:            /* TODO !!! */
                   5715:            break;
                   5716:     }
                   5717: }
                   5718: #endif /* LIBXML_TREE_ENABLED */
                   5719: 
                   5720: /**
                   5721:  * xmlNodeAddContentLen:
                   5722:  * @cur:  the node being modified
                   5723:  * @content:  extra content
                   5724:  * @len:  the size of @content
                   5725:  *
                   5726:  * Append the extra substring to the node content.
                   5727:  * NOTE: In contrast to xmlNodeSetContentLen(), @content is supposed to be
                   5728:  *       raw text, so unescaped XML special chars are allowed, entity
                   5729:  *       references are not supported.
                   5730:  */
                   5731: void
                   5732: xmlNodeAddContentLen(xmlNodePtr cur, const xmlChar *content, int len) {
                   5733:     if (cur == NULL) {
                   5734: #ifdef DEBUG_TREE
                   5735:         xmlGenericError(xmlGenericErrorContext,
                   5736:                "xmlNodeAddContentLen : node == NULL\n");
                   5737: #endif
                   5738:        return;
                   5739:     }
                   5740:     if (len <= 0) return;
                   5741:     switch (cur->type) {
                   5742:         case XML_DOCUMENT_FRAG_NODE:
                   5743:         case XML_ELEMENT_NODE: {
                   5744:            xmlNodePtr last, newNode, tmp;
                   5745: 
                   5746:            last = cur->last;
                   5747:            newNode = xmlNewTextLen(content, len);
                   5748:            if (newNode != NULL) {
                   5749:                tmp = xmlAddChild(cur, newNode);
                   5750:                if (tmp != newNode)
                   5751:                    return;
                   5752:                if ((last != NULL) && (last->next == newNode)) {
                   5753:                    xmlTextMerge(last, newNode);
                   5754:                }
                   5755:            }
                   5756:            break;
                   5757:        }
                   5758:         case XML_ATTRIBUTE_NODE:
                   5759:            break;
                   5760:         case XML_TEXT_NODE:
                   5761:         case XML_CDATA_SECTION_NODE:
                   5762:         case XML_ENTITY_REF_NODE:
                   5763:         case XML_ENTITY_NODE:
                   5764:         case XML_PI_NODE:
                   5765:         case XML_COMMENT_NODE:
                   5766:         case XML_NOTATION_NODE:
                   5767:            if (content != NULL) {
                   5768:                if ((cur->content == (xmlChar *) &(cur->properties)) ||
                   5769:                    ((cur->doc != NULL) && (cur->doc->dict != NULL) &&
                   5770:                            xmlDictOwns(cur->doc->dict, cur->content))) {
                   5771:                    cur->content = xmlStrncatNew(cur->content, content, len);
                   5772:                    cur->properties = NULL;
                   5773:                    cur->nsDef = NULL;
                   5774:                    break;
                   5775:                }
                   5776:                cur->content = xmlStrncat(cur->content, content, len);
                   5777:             }
                   5778:         case XML_DOCUMENT_NODE:
                   5779:         case XML_DTD_NODE:
                   5780:         case XML_HTML_DOCUMENT_NODE:
                   5781:         case XML_DOCUMENT_TYPE_NODE:
                   5782:        case XML_NAMESPACE_DECL:
                   5783:        case XML_XINCLUDE_START:
                   5784:        case XML_XINCLUDE_END:
                   5785: #ifdef LIBXML_DOCB_ENABLED
                   5786:        case XML_DOCB_DOCUMENT_NODE:
                   5787: #endif
                   5788:            break;
                   5789:         case XML_ELEMENT_DECL:
                   5790:         case XML_ATTRIBUTE_DECL:
                   5791:         case XML_ENTITY_DECL:
                   5792:            break;
                   5793:     }
                   5794: }
                   5795: 
                   5796: /**
                   5797:  * xmlNodeAddContent:
                   5798:  * @cur:  the node being modified
                   5799:  * @content:  extra content
                   5800:  *
                   5801:  * Append the extra substring to the node content.
                   5802:  * NOTE: In contrast to xmlNodeSetContent(), @content is supposed to be
                   5803:  *       raw text, so unescaped XML special chars are allowed, entity
                   5804:  *       references are not supported.
                   5805:  */
                   5806: void
                   5807: xmlNodeAddContent(xmlNodePtr cur, const xmlChar *content) {
                   5808:     int len;
                   5809: 
                   5810:     if (cur == NULL) {
                   5811: #ifdef DEBUG_TREE
                   5812:         xmlGenericError(xmlGenericErrorContext,
                   5813:                "xmlNodeAddContent : node == NULL\n");
                   5814: #endif
                   5815:        return;
                   5816:     }
                   5817:     if (content == NULL) return;
                   5818:     len = xmlStrlen(content);
                   5819:     xmlNodeAddContentLen(cur, content, len);
                   5820: }
                   5821: 
                   5822: /**
                   5823:  * xmlTextMerge:
                   5824:  * @first:  the first text node
                   5825:  * @second:  the second text node being merged
                   5826:  *
                   5827:  * Merge two text nodes into one
                   5828:  * Returns the first text node augmented
                   5829:  */
                   5830: xmlNodePtr
                   5831: xmlTextMerge(xmlNodePtr first, xmlNodePtr second) {
                   5832:     if (first == NULL) return(second);
                   5833:     if (second == NULL) return(first);
                   5834:     if (first->type != XML_TEXT_NODE) return(first);
                   5835:     if (second->type != XML_TEXT_NODE) return(first);
                   5836:     if (second->name != first->name)
                   5837:        return(first);
                   5838:     xmlNodeAddContent(first, second->content);
                   5839:     xmlUnlinkNode(second);
                   5840:     xmlFreeNode(second);
                   5841:     return(first);
                   5842: }
                   5843: 
                   5844: #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XPATH_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
                   5845: /**
                   5846:  * xmlGetNsList:
                   5847:  * @doc:  the document
                   5848:  * @node:  the current node
                   5849:  *
                   5850:  * Search all the namespace applying to a given element.
                   5851:  * Returns an NULL terminated array of all the #xmlNsPtr found
                   5852:  *         that need to be freed by the caller or NULL if no
                   5853:  *         namespace if defined
                   5854:  */
                   5855: xmlNsPtr *
                   5856: xmlGetNsList(xmlDocPtr doc ATTRIBUTE_UNUSED, xmlNodePtr node)
                   5857: {
                   5858:     xmlNsPtr cur;
                   5859:     xmlNsPtr *ret = NULL;
                   5860:     int nbns = 0;
                   5861:     int maxns = 10;
                   5862:     int i;
                   5863: 
1.1.1.3 ! misho    5864:     if ((node == NULL) || (node->type == XML_NAMESPACE_DECL))
        !          5865:         return(NULL);
        !          5866: 
1.1       misho    5867:     while (node != NULL) {
                   5868:         if (node->type == XML_ELEMENT_NODE) {
                   5869:             cur = node->nsDef;
                   5870:             while (cur != NULL) {
                   5871:                 if (ret == NULL) {
                   5872:                     ret =
                   5873:                         (xmlNsPtr *) xmlMalloc((maxns + 1) *
                   5874:                                                sizeof(xmlNsPtr));
                   5875:                     if (ret == NULL) {
                   5876:                        xmlTreeErrMemory("getting namespace list");
                   5877:                         return (NULL);
                   5878:                     }
                   5879:                     ret[nbns] = NULL;
                   5880:                 }
                   5881:                 for (i = 0; i < nbns; i++) {
                   5882:                     if ((cur->prefix == ret[i]->prefix) ||
                   5883:                         (xmlStrEqual(cur->prefix, ret[i]->prefix)))
                   5884:                         break;
                   5885:                 }
                   5886:                 if (i >= nbns) {
                   5887:                     if (nbns >= maxns) {
                   5888:                         maxns *= 2;
                   5889:                         ret = (xmlNsPtr *) xmlRealloc(ret,
                   5890:                                                       (maxns +
                   5891:                                                        1) *
                   5892:                                                       sizeof(xmlNsPtr));
                   5893:                         if (ret == NULL) {
                   5894:                            xmlTreeErrMemory("getting namespace list");
                   5895:                             return (NULL);
                   5896:                         }
                   5897:                     }
                   5898:                     ret[nbns++] = cur;
                   5899:                     ret[nbns] = NULL;
                   5900:                 }
                   5901: 
                   5902:                 cur = cur->next;
                   5903:             }
                   5904:         }
                   5905:         node = node->parent;
                   5906:     }
                   5907:     return (ret);
                   5908: }
                   5909: #endif /* LIBXML_TREE_ENABLED */
                   5910: 
                   5911: /*
                   5912: * xmlTreeEnsureXMLDecl:
                   5913: * @doc: the doc
                   5914: *
                   5915: * Ensures that there is an XML namespace declaration on the doc.
                   5916: *
                   5917: * Returns the XML ns-struct or NULL on API and internal errors.
                   5918: */
                   5919: static xmlNsPtr
                   5920: xmlTreeEnsureXMLDecl(xmlDocPtr doc)
                   5921: {
                   5922:     if (doc == NULL)
                   5923:        return (NULL);
                   5924:     if (doc->oldNs != NULL)
                   5925:        return (doc->oldNs);
                   5926:     {
                   5927:        xmlNsPtr ns;
                   5928:        ns = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
                   5929:        if (ns == NULL) {
                   5930:            xmlTreeErrMemory(
                   5931:                "allocating the XML namespace");
                   5932:            return (NULL);
                   5933:        }
                   5934:        memset(ns, 0, sizeof(xmlNs));
                   5935:        ns->type = XML_LOCAL_NAMESPACE;
                   5936:        ns->href = xmlStrdup(XML_XML_NAMESPACE);
                   5937:        ns->prefix = xmlStrdup((const xmlChar *)"xml");
                   5938:        doc->oldNs = ns;
                   5939:        return (ns);
                   5940:     }
                   5941: }
                   5942: 
                   5943: /**
                   5944:  * xmlSearchNs:
                   5945:  * @doc:  the document
                   5946:  * @node:  the current node
                   5947:  * @nameSpace:  the namespace prefix
                   5948:  *
                   5949:  * Search a Ns registered under a given name space for a document.
                   5950:  * recurse on the parents until it finds the defined namespace
                   5951:  * or return NULL otherwise.
                   5952:  * @nameSpace can be NULL, this is a search for the default namespace.
                   5953:  * We don't allow to cross entities boundaries. If you don't declare
                   5954:  * the namespace within those you will be in troubles !!! A warning
                   5955:  * is generated to cover this case.
                   5956:  *
                   5957:  * Returns the namespace pointer or NULL.
                   5958:  */
                   5959: xmlNsPtr
                   5960: xmlSearchNs(xmlDocPtr doc, xmlNodePtr node, const xmlChar *nameSpace) {
                   5961: 
                   5962:     xmlNsPtr cur;
                   5963:     xmlNodePtr orig = node;
                   5964: 
1.1.1.3 ! misho    5965:     if ((node == NULL) || (node->type == XML_NAMESPACE_DECL)) return(NULL);
1.1       misho    5966:     if ((nameSpace != NULL) &&
                   5967:        (xmlStrEqual(nameSpace, (const xmlChar *)"xml"))) {
                   5968:        if ((doc == NULL) && (node->type == XML_ELEMENT_NODE)) {
                   5969:            /*
                   5970:             * The XML-1.0 namespace is normally held on the root
                   5971:             * element. In this case exceptionally create it on the
                   5972:             * node element.
                   5973:             */
                   5974:            cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
                   5975:            if (cur == NULL) {
                   5976:                xmlTreeErrMemory("searching namespace");
                   5977:                return(NULL);
                   5978:            }
                   5979:            memset(cur, 0, sizeof(xmlNs));
                   5980:            cur->type = XML_LOCAL_NAMESPACE;
                   5981:            cur->href = xmlStrdup(XML_XML_NAMESPACE);
                   5982:            cur->prefix = xmlStrdup((const xmlChar *)"xml");
                   5983:            cur->next = node->nsDef;
                   5984:            node->nsDef = cur;
                   5985:            return(cur);
                   5986:        }
                   5987:        if (doc == NULL) {
                   5988:            doc = node->doc;
                   5989:            if (doc == NULL)
                   5990:                return(NULL);
                   5991:        }
                   5992:        /*
                   5993:        * Return the XML namespace declaration held by the doc.
                   5994:        */
                   5995:        if (doc->oldNs == NULL)
                   5996:            return(xmlTreeEnsureXMLDecl(doc));
                   5997:        else
                   5998:            return(doc->oldNs);
                   5999:     }
                   6000:     while (node != NULL) {
                   6001:        if ((node->type == XML_ENTITY_REF_NODE) ||
                   6002:            (node->type == XML_ENTITY_NODE) ||
                   6003:            (node->type == XML_ENTITY_DECL))
                   6004:            return(NULL);
                   6005:        if (node->type == XML_ELEMENT_NODE) {
                   6006:            cur = node->nsDef;
                   6007:            while (cur != NULL) {
                   6008:                if ((cur->prefix == NULL) && (nameSpace == NULL) &&
                   6009:                    (cur->href != NULL))
                   6010:                    return(cur);
                   6011:                if ((cur->prefix != NULL) && (nameSpace != NULL) &&
                   6012:                    (cur->href != NULL) &&
                   6013:                    (xmlStrEqual(cur->prefix, nameSpace)))
                   6014:                    return(cur);
                   6015:                cur = cur->next;
                   6016:            }
                   6017:            if (orig != node) {
                   6018:                cur = node->ns;
                   6019:                if (cur != NULL) {
                   6020:                    if ((cur->prefix == NULL) && (nameSpace == NULL) &&
                   6021:                        (cur->href != NULL))
                   6022:                        return(cur);
                   6023:                    if ((cur->prefix != NULL) && (nameSpace != NULL) &&
                   6024:                        (cur->href != NULL) &&
                   6025:                        (xmlStrEqual(cur->prefix, nameSpace)))
                   6026:                        return(cur);
                   6027:                }
                   6028:            }
                   6029:        }
                   6030:        node = node->parent;
                   6031:     }
                   6032:     return(NULL);
                   6033: }
                   6034: 
                   6035: /**
                   6036:  * xmlNsInScope:
                   6037:  * @doc:  the document
                   6038:  * @node:  the current node
                   6039:  * @ancestor:  the ancestor carrying the namespace
                   6040:  * @prefix:  the namespace prefix
                   6041:  *
                   6042:  * Verify that the given namespace held on @ancestor is still in scope
                   6043:  * on node.
                   6044:  *
                   6045:  * Returns 1 if true, 0 if false and -1 in case of error.
                   6046:  */
                   6047: static int
                   6048: xmlNsInScope(xmlDocPtr doc ATTRIBUTE_UNUSED, xmlNodePtr node,
                   6049:              xmlNodePtr ancestor, const xmlChar * prefix)
                   6050: {
                   6051:     xmlNsPtr tst;
                   6052: 
                   6053:     while ((node != NULL) && (node != ancestor)) {
                   6054:         if ((node->type == XML_ENTITY_REF_NODE) ||
                   6055:             (node->type == XML_ENTITY_NODE) ||
                   6056:             (node->type == XML_ENTITY_DECL))
                   6057:             return (-1);
                   6058:         if (node->type == XML_ELEMENT_NODE) {
                   6059:             tst = node->nsDef;
                   6060:             while (tst != NULL) {
                   6061:                 if ((tst->prefix == NULL)
                   6062:                     && (prefix == NULL))
                   6063:                     return (0);
                   6064:                 if ((tst->prefix != NULL)
                   6065:                     && (prefix != NULL)
                   6066:                     && (xmlStrEqual(tst->prefix, prefix)))
                   6067:                     return (0);
                   6068:                 tst = tst->next;
                   6069:             }
                   6070:         }
                   6071:         node = node->parent;
                   6072:     }
                   6073:     if (node != ancestor)
                   6074:         return (-1);
                   6075:     return (1);
                   6076: }
                   6077: 
                   6078: /**
                   6079:  * xmlSearchNsByHref:
                   6080:  * @doc:  the document
                   6081:  * @node:  the current node
                   6082:  * @href:  the namespace value
                   6083:  *
                   6084:  * Search a Ns aliasing a given URI. Recurse on the parents until it finds
                   6085:  * the defined namespace or return NULL otherwise.
                   6086:  * Returns the namespace pointer or NULL.
                   6087:  */
                   6088: xmlNsPtr
                   6089: xmlSearchNsByHref(xmlDocPtr doc, xmlNodePtr node, const xmlChar * href)
                   6090: {
                   6091:     xmlNsPtr cur;
                   6092:     xmlNodePtr orig = node;
                   6093:     int is_attr;
                   6094: 
1.1.1.3 ! misho    6095:     if ((node == NULL) || (node->type == XML_NAMESPACE_DECL) || (href == NULL))
1.1       misho    6096:         return (NULL);
                   6097:     if (xmlStrEqual(href, XML_XML_NAMESPACE)) {
                   6098:         /*
                   6099:          * Only the document can hold the XML spec namespace.
                   6100:          */
                   6101:         if ((doc == NULL) && (node->type == XML_ELEMENT_NODE)) {
                   6102:             /*
                   6103:              * The XML-1.0 namespace is normally held on the root
                   6104:              * element. In this case exceptionally create it on the
                   6105:              * node element.
                   6106:              */
                   6107:             cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
                   6108:             if (cur == NULL) {
                   6109:                xmlTreeErrMemory("searching namespace");
                   6110:                 return (NULL);
                   6111:             }
                   6112:             memset(cur, 0, sizeof(xmlNs));
                   6113:             cur->type = XML_LOCAL_NAMESPACE;
                   6114:             cur->href = xmlStrdup(XML_XML_NAMESPACE);
                   6115:             cur->prefix = xmlStrdup((const xmlChar *) "xml");
                   6116:             cur->next = node->nsDef;
                   6117:             node->nsDef = cur;
                   6118:             return (cur);
                   6119:         }
                   6120:        if (doc == NULL) {
                   6121:            doc = node->doc;
                   6122:            if (doc == NULL)
                   6123:                return(NULL);
                   6124:        }
                   6125:        /*
                   6126:        * Return the XML namespace declaration held by the doc.
                   6127:        */
                   6128:        if (doc->oldNs == NULL)
                   6129:            return(xmlTreeEnsureXMLDecl(doc));
                   6130:        else
                   6131:            return(doc->oldNs);
                   6132:     }
                   6133:     is_attr = (node->type == XML_ATTRIBUTE_NODE);
                   6134:     while (node != NULL) {
                   6135:         if ((node->type == XML_ENTITY_REF_NODE) ||
                   6136:             (node->type == XML_ENTITY_NODE) ||
                   6137:             (node->type == XML_ENTITY_DECL))
                   6138:             return (NULL);
                   6139:         if (node->type == XML_ELEMENT_NODE) {
                   6140:             cur = node->nsDef;
                   6141:             while (cur != NULL) {
                   6142:                 if ((cur->href != NULL) && (href != NULL) &&
                   6143:                     (xmlStrEqual(cur->href, href))) {
                   6144:                    if (((!is_attr) || (cur->prefix != NULL)) &&
                   6145:                        (xmlNsInScope(doc, orig, node, cur->prefix) == 1))
                   6146:                        return (cur);
                   6147:                 }
                   6148:                 cur = cur->next;
                   6149:             }
                   6150:             if (orig != node) {
                   6151:                 cur = node->ns;
                   6152:                 if (cur != NULL) {
                   6153:                     if ((cur->href != NULL) && (href != NULL) &&
                   6154:                         (xmlStrEqual(cur->href, href))) {
                   6155:                        if (((!is_attr) || (cur->prefix != NULL)) &&
                   6156:                            (xmlNsInScope(doc, orig, node, cur->prefix) == 1))
                   6157:                            return (cur);
                   6158:                     }
                   6159:                 }
                   6160:             }
                   6161:         }
                   6162:         node = node->parent;
                   6163:     }
                   6164:     return (NULL);
                   6165: }
                   6166: 
                   6167: /**
                   6168:  * xmlNewReconciliedNs:
                   6169:  * @doc:  the document
                   6170:  * @tree:  a node expected to hold the new namespace
                   6171:  * @ns:  the original namespace
                   6172:  *
                   6173:  * This function tries to locate a namespace definition in a tree
                   6174:  * ancestors, or create a new namespace definition node similar to
                   6175:  * @ns trying to reuse the same prefix. However if the given prefix is
                   6176:  * null (default namespace) or reused within the subtree defined by
                   6177:  * @tree or on one of its ancestors then a new prefix is generated.
                   6178:  * Returns the (new) namespace definition or NULL in case of error
                   6179:  */
                   6180: static xmlNsPtr
                   6181: xmlNewReconciliedNs(xmlDocPtr doc, xmlNodePtr tree, xmlNsPtr ns) {
                   6182:     xmlNsPtr def;
                   6183:     xmlChar prefix[50];
                   6184:     int counter = 1;
                   6185: 
1.1.1.3 ! misho    6186:     if ((tree == NULL) || (tree->type != XML_ELEMENT_NODE)) {
1.1       misho    6187: #ifdef DEBUG_TREE
                   6188:         xmlGenericError(xmlGenericErrorContext,
                   6189:                "xmlNewReconciliedNs : tree == NULL\n");
                   6190: #endif
                   6191:        return(NULL);
                   6192:     }
                   6193:     if ((ns == NULL) || (ns->type != XML_NAMESPACE_DECL)) {
                   6194: #ifdef DEBUG_TREE
                   6195:         xmlGenericError(xmlGenericErrorContext,
                   6196:                "xmlNewReconciliedNs : ns == NULL\n");
                   6197: #endif
                   6198:        return(NULL);
                   6199:     }
                   6200:     /*
                   6201:      * Search an existing namespace definition inherited.
                   6202:      */
                   6203:     def = xmlSearchNsByHref(doc, tree, ns->href);
                   6204:     if (def != NULL)
                   6205:         return(def);
                   6206: 
                   6207:     /*
                   6208:      * Find a close prefix which is not already in use.
                   6209:      * Let's strip namespace prefixes longer than 20 chars !
                   6210:      */
                   6211:     if (ns->prefix == NULL)
                   6212:        snprintf((char *) prefix, sizeof(prefix), "default");
                   6213:     else
                   6214:        snprintf((char *) prefix, sizeof(prefix), "%.20s", (char *)ns->prefix);
                   6215: 
                   6216:     def = xmlSearchNs(doc, tree, prefix);
                   6217:     while (def != NULL) {
                   6218:         if (counter > 1000) return(NULL);
                   6219:        if (ns->prefix == NULL)
                   6220:            snprintf((char *) prefix, sizeof(prefix), "default%d", counter++);
                   6221:        else
                   6222:            snprintf((char *) prefix, sizeof(prefix), "%.20s%d",
                   6223:                (char *)ns->prefix, counter++);
                   6224:        def = xmlSearchNs(doc, tree, prefix);
                   6225:     }
                   6226: 
                   6227:     /*
                   6228:      * OK, now we are ready to create a new one.
                   6229:      */
                   6230:     def = xmlNewNs(tree, ns->href, prefix);
                   6231:     return(def);
                   6232: }
                   6233: 
                   6234: #ifdef LIBXML_TREE_ENABLED
                   6235: /**
                   6236:  * xmlReconciliateNs:
                   6237:  * @doc:  the document
                   6238:  * @tree:  a node defining the subtree to reconciliate
                   6239:  *
                   6240:  * This function checks that all the namespaces declared within the given
                   6241:  * tree are properly declared. This is needed for example after Copy or Cut
                   6242:  * and then paste operations. The subtree may still hold pointers to
                   6243:  * namespace declarations outside the subtree or invalid/masked. As much
                   6244:  * as possible the function try to reuse the existing namespaces found in
                   6245:  * the new environment. If not possible the new namespaces are redeclared
                   6246:  * on @tree at the top of the given subtree.
                   6247:  * Returns the number of namespace declarations created or -1 in case of error.
                   6248:  */
                   6249: int
                   6250: xmlReconciliateNs(xmlDocPtr doc, xmlNodePtr tree) {
                   6251:     xmlNsPtr *oldNs = NULL;
                   6252:     xmlNsPtr *newNs = NULL;
                   6253:     int sizeCache = 0;
                   6254:     int nbCache = 0;
                   6255: 
                   6256:     xmlNsPtr n;
                   6257:     xmlNodePtr node = tree;
                   6258:     xmlAttrPtr attr;
                   6259:     int ret = 0, i;
                   6260: 
                   6261:     if ((node == NULL) || (node->type != XML_ELEMENT_NODE)) return(-1);
                   6262:     if ((doc == NULL) || (doc->type != XML_DOCUMENT_NODE)) return(-1);
                   6263:     if (node->doc != doc) return(-1);
                   6264:     while (node != NULL) {
                   6265:         /*
                   6266:         * Reconciliate the node namespace
                   6267:         */
                   6268:        if (node->ns != NULL) {
                   6269:            /*
                   6270:             * initialize the cache if needed
                   6271:             */
                   6272:            if (sizeCache == 0) {
                   6273:                sizeCache = 10;
                   6274:                oldNs = (xmlNsPtr *) xmlMalloc(sizeCache *
                   6275:                                               sizeof(xmlNsPtr));
                   6276:                if (oldNs == NULL) {
                   6277:                    xmlTreeErrMemory("fixing namespaces");
                   6278:                    return(-1);
                   6279:                }
                   6280:                newNs = (xmlNsPtr *) xmlMalloc(sizeCache *
                   6281:                                               sizeof(xmlNsPtr));
                   6282:                if (newNs == NULL) {
                   6283:                    xmlTreeErrMemory("fixing namespaces");
                   6284:                    xmlFree(oldNs);
                   6285:                    return(-1);
                   6286:                }
                   6287:            }
                   6288:            for (i = 0;i < nbCache;i++) {
                   6289:                if (oldNs[i] == node->ns) {
                   6290:                    node->ns = newNs[i];
                   6291:                    break;
                   6292:                }
                   6293:            }
                   6294:            if (i == nbCache) {
                   6295:                /*
                   6296:                 * OK we need to recreate a new namespace definition
                   6297:                 */
                   6298:                n = xmlNewReconciliedNs(doc, tree, node->ns);
                   6299:                if (n != NULL) { /* :-( what if else ??? */
                   6300:                    /*
                   6301:                     * check if we need to grow the cache buffers.
                   6302:                     */
                   6303:                    if (sizeCache <= nbCache) {
                   6304:                        sizeCache *= 2;
                   6305:                        oldNs = (xmlNsPtr *) xmlRealloc(oldNs, sizeCache *
                   6306:                                                       sizeof(xmlNsPtr));
                   6307:                        if (oldNs == NULL) {
                   6308:                            xmlTreeErrMemory("fixing namespaces");
                   6309:                            xmlFree(newNs);
                   6310:                            return(-1);
                   6311:                        }
                   6312:                        newNs = (xmlNsPtr *) xmlRealloc(newNs, sizeCache *
                   6313:                                                       sizeof(xmlNsPtr));
                   6314:                        if (newNs == NULL) {
                   6315:                            xmlTreeErrMemory("fixing namespaces");
                   6316:                            xmlFree(oldNs);
                   6317:                            return(-1);
                   6318:                        }
                   6319:                    }
                   6320:                    newNs[nbCache] = n;
                   6321:                    oldNs[nbCache++] = node->ns;
                   6322:                    node->ns = n;
                   6323:                 }
                   6324:            }
                   6325:        }
                   6326:        /*
                   6327:         * now check for namespace hold by attributes on the node.
                   6328:         */
                   6329:        if (node->type == XML_ELEMENT_NODE) {
                   6330:            attr = node->properties;
                   6331:            while (attr != NULL) {
                   6332:                if (attr->ns != NULL) {
                   6333:                    /*
                   6334:                     * initialize the cache if needed
                   6335:                     */
                   6336:                    if (sizeCache == 0) {
                   6337:                        sizeCache = 10;
                   6338:                        oldNs = (xmlNsPtr *) xmlMalloc(sizeCache *
                   6339:                                                       sizeof(xmlNsPtr));
                   6340:                        if (oldNs == NULL) {
                   6341:                            xmlTreeErrMemory("fixing namespaces");
                   6342:                            return(-1);
                   6343:                        }
                   6344:                        newNs = (xmlNsPtr *) xmlMalloc(sizeCache *
                   6345:                                                       sizeof(xmlNsPtr));
                   6346:                        if (newNs == NULL) {
                   6347:                            xmlTreeErrMemory("fixing namespaces");
                   6348:                            xmlFree(oldNs);
                   6349:                            return(-1);
                   6350:                        }
                   6351:                    }
                   6352:                    for (i = 0;i < nbCache;i++) {
                   6353:                        if (oldNs[i] == attr->ns) {
                   6354:                            attr->ns = newNs[i];
                   6355:                            break;
                   6356:                        }
                   6357:                    }
                   6358:                    if (i == nbCache) {
                   6359:                        /*
                   6360:                         * OK we need to recreate a new namespace definition
                   6361:                         */
                   6362:                        n = xmlNewReconciliedNs(doc, tree, attr->ns);
                   6363:                        if (n != NULL) { /* :-( what if else ??? */
                   6364:                            /*
                   6365:                             * check if we need to grow the cache buffers.
                   6366:                             */
                   6367:                            if (sizeCache <= nbCache) {
                   6368:                                sizeCache *= 2;
                   6369:                                oldNs = (xmlNsPtr *) xmlRealloc(oldNs,
                   6370:                                           sizeCache * sizeof(xmlNsPtr));
                   6371:                                if (oldNs == NULL) {
                   6372:                                    xmlTreeErrMemory("fixing namespaces");
                   6373:                                    xmlFree(newNs);
                   6374:                                    return(-1);
                   6375:                                }
                   6376:                                newNs = (xmlNsPtr *) xmlRealloc(newNs,
                   6377:                                           sizeCache * sizeof(xmlNsPtr));
                   6378:                                if (newNs == NULL) {
                   6379:                                    xmlTreeErrMemory("fixing namespaces");
                   6380:                                    xmlFree(oldNs);
                   6381:                                    return(-1);
                   6382:                                }
                   6383:                            }
                   6384:                            newNs[nbCache] = n;
                   6385:                            oldNs[nbCache++] = attr->ns;
                   6386:                            attr->ns = n;
                   6387:                        }
                   6388:                    }
                   6389:                }
                   6390:                attr = attr->next;
                   6391:            }
                   6392:        }
                   6393: 
                   6394:        /*
                   6395:         * Browse the full subtree, deep first
                   6396:         */
                   6397:         if ((node->children != NULL) && (node->type != XML_ENTITY_REF_NODE)) {
                   6398:            /* deep first */
                   6399:            node = node->children;
                   6400:        } else if ((node != tree) && (node->next != NULL)) {
                   6401:            /* then siblings */
                   6402:            node = node->next;
                   6403:        } else if (node != tree) {
                   6404:            /* go up to parents->next if needed */
                   6405:            while (node != tree) {
                   6406:                if (node->parent != NULL)
                   6407:                    node = node->parent;
                   6408:                if ((node != tree) && (node->next != NULL)) {
                   6409:                    node = node->next;
                   6410:                    break;
                   6411:                }
                   6412:                if (node->parent == NULL) {
                   6413:                    node = NULL;
                   6414:                    break;
                   6415:                }
                   6416:            }
                   6417:            /* exit condition */
                   6418:            if (node == tree)
                   6419:                node = NULL;
                   6420:        } else
                   6421:            break;
                   6422:     }
                   6423:     if (oldNs != NULL)
                   6424:        xmlFree(oldNs);
                   6425:     if (newNs != NULL)
                   6426:        xmlFree(newNs);
                   6427:     return(ret);
                   6428: }
                   6429: #endif /* LIBXML_TREE_ENABLED */
                   6430: 
                   6431: static xmlAttrPtr
                   6432: xmlGetPropNodeInternal(xmlNodePtr node, const xmlChar *name,
                   6433:                       const xmlChar *nsName, int useDTD)
                   6434: {
                   6435:     xmlAttrPtr prop;
                   6436: 
                   6437:     if ((node == NULL) || (node->type != XML_ELEMENT_NODE) || (name == NULL))
                   6438:        return(NULL);
                   6439: 
                   6440:     if (node->properties != NULL) {
                   6441:        prop = node->properties;
                   6442:        if (nsName == NULL) {
                   6443:            /*
                   6444:            * We want the attr to be in no namespace.
                   6445:            */
                   6446:            do {
                   6447:                if ((prop->ns == NULL) && xmlStrEqual(prop->name, name)) {
                   6448:                    return(prop);
                   6449:                }
                   6450:                prop = prop->next;
                   6451:            } while (prop != NULL);
                   6452:        } else {
                   6453:            /*
                   6454:            * We want the attr to be in the specified namespace.
                   6455:            */
                   6456:            do {
                   6457:                if ((prop->ns != NULL) && xmlStrEqual(prop->name, name) &&
                   6458:                    ((prop->ns->href == nsName) ||
                   6459:                     xmlStrEqual(prop->ns->href, nsName)))
                   6460:                {
                   6461:                    return(prop);
                   6462:                }
                   6463:                prop = prop->next;
                   6464:            } while (prop != NULL);
                   6465:        }
                   6466:     }
                   6467: 
                   6468: #ifdef LIBXML_TREE_ENABLED
                   6469:     if (! useDTD)
                   6470:        return(NULL);
                   6471:     /*
                   6472:      * Check if there is a default/fixed attribute declaration in
                   6473:      * the internal or external subset.
                   6474:      */
                   6475:     if ((node->doc != NULL) && (node->doc->intSubset != NULL)) {
                   6476:        xmlDocPtr doc = node->doc;
                   6477:        xmlAttributePtr attrDecl = NULL;
                   6478:        xmlChar *elemQName, *tmpstr = NULL;
                   6479: 
                   6480:        /*
                   6481:        * We need the QName of the element for the DTD-lookup.
                   6482:        */
                   6483:        if ((node->ns != NULL) && (node->ns->prefix != NULL)) {
                   6484:            tmpstr = xmlStrdup(node->ns->prefix);
                   6485:            tmpstr = xmlStrcat(tmpstr, BAD_CAST ":");
                   6486:            tmpstr = xmlStrcat(tmpstr, node->name);
                   6487:            if (tmpstr == NULL)
                   6488:                return(NULL);
                   6489:            elemQName = tmpstr;
                   6490:        } else
                   6491:            elemQName = (xmlChar *) node->name;
                   6492:        if (nsName == NULL) {
                   6493:            /*
                   6494:            * The common and nice case: Attr in no namespace.
                   6495:            */
                   6496:            attrDecl = xmlGetDtdQAttrDesc(doc->intSubset,
                   6497:                elemQName, name, NULL);
                   6498:            if ((attrDecl == NULL) && (doc->extSubset != NULL)) {
                   6499:                attrDecl = xmlGetDtdQAttrDesc(doc->extSubset,
                   6500:                    elemQName, name, NULL);
                   6501:            }
                   6502:        } else {
                   6503:            xmlNsPtr *nsList, *cur;
                   6504: 
                   6505:            /*
                   6506:            * The ugly case: Search using the prefixes of in-scope
                   6507:            * ns-decls corresponding to @nsName.
                   6508:            */
                   6509:            nsList = xmlGetNsList(node->doc, node);
                   6510:            if (nsList == NULL) {
                   6511:                if (tmpstr != NULL)
                   6512:                    xmlFree(tmpstr);
                   6513:                return(NULL);
                   6514:            }
                   6515:            cur = nsList;
                   6516:            while (*cur != NULL) {
                   6517:                if (xmlStrEqual((*cur)->href, nsName)) {
                   6518:                    attrDecl = xmlGetDtdQAttrDesc(doc->intSubset, elemQName,
                   6519:                        name, (*cur)->prefix);
                   6520:                    if (attrDecl)
                   6521:                        break;
                   6522:                    if (doc->extSubset != NULL) {
                   6523:                        attrDecl = xmlGetDtdQAttrDesc(doc->extSubset, elemQName,
                   6524:                            name, (*cur)->prefix);
                   6525:                        if (attrDecl)
                   6526:                            break;
                   6527:                    }
                   6528:                }
                   6529:                cur++;
                   6530:            }
                   6531:            xmlFree(nsList);
                   6532:        }
                   6533:        if (tmpstr != NULL)
                   6534:            xmlFree(tmpstr);
                   6535:        /*
                   6536:        * Only default/fixed attrs are relevant.
                   6537:        */
                   6538:        if ((attrDecl != NULL) && (attrDecl->defaultValue != NULL))
                   6539:            return((xmlAttrPtr) attrDecl);
                   6540:     }
                   6541: #endif /* LIBXML_TREE_ENABLED */
                   6542:     return(NULL);
                   6543: }
                   6544: 
                   6545: static xmlChar*
                   6546: xmlGetPropNodeValueInternal(xmlAttrPtr prop)
                   6547: {
                   6548:     if (prop == NULL)
                   6549:        return(NULL);
                   6550:     if (prop->type == XML_ATTRIBUTE_NODE) {
                   6551:        /*
                   6552:        * Note that we return at least the empty string.
                   6553:        *   TODO: Do we really always want that?
                   6554:        */
                   6555:        if (prop->children != NULL) {
                   6556:            if ((prop->children->next == NULL) &&
                   6557:                ((prop->children->type == XML_TEXT_NODE) ||
                   6558:                (prop->children->type == XML_CDATA_SECTION_NODE)))
                   6559:            {
                   6560:                /*
                   6561:                * Optimization for the common case: only 1 text node.
                   6562:                */
                   6563:                return(xmlStrdup(prop->children->content));
                   6564:            } else {
                   6565:                xmlChar *ret;
                   6566: 
                   6567:                ret = xmlNodeListGetString(prop->doc, prop->children, 1);
                   6568:                if (ret != NULL)
                   6569:                    return(ret);
                   6570:            }
                   6571:        }
                   6572:        return(xmlStrdup((xmlChar *)""));
                   6573:     } else if (prop->type == XML_ATTRIBUTE_DECL) {
                   6574:        return(xmlStrdup(((xmlAttributePtr)prop)->defaultValue));
                   6575:     }
                   6576:     return(NULL);
                   6577: }
                   6578: 
                   6579: /**
                   6580:  * xmlHasProp:
                   6581:  * @node:  the node
                   6582:  * @name:  the attribute name
                   6583:  *
                   6584:  * Search an attribute associated to a node
                   6585:  * This function also looks in DTD attribute declaration for #FIXED or
                   6586:  * default declaration values unless DTD use has been turned off.
                   6587:  *
                   6588:  * Returns the attribute or the attribute declaration or NULL if
                   6589:  *         neither was found.
                   6590:  */
                   6591: xmlAttrPtr
                   6592: xmlHasProp(xmlNodePtr node, const xmlChar *name) {
                   6593:     xmlAttrPtr prop;
                   6594:     xmlDocPtr doc;
                   6595: 
                   6596:     if ((node == NULL) || (node->type != XML_ELEMENT_NODE) || (name == NULL))
                   6597:         return(NULL);
                   6598:     /*
                   6599:      * Check on the properties attached to the node
                   6600:      */
                   6601:     prop = node->properties;
                   6602:     while (prop != NULL) {
                   6603:         if (xmlStrEqual(prop->name, name))  {
                   6604:            return(prop);
                   6605:         }
                   6606:        prop = prop->next;
                   6607:     }
                   6608:     if (!xmlCheckDTD) return(NULL);
                   6609: 
                   6610:     /*
                   6611:      * Check if there is a default declaration in the internal
                   6612:      * or external subsets
                   6613:      */
                   6614:     doc =  node->doc;
                   6615:     if (doc != NULL) {
                   6616:         xmlAttributePtr attrDecl;
                   6617:         if (doc->intSubset != NULL) {
                   6618:            attrDecl = xmlGetDtdAttrDesc(doc->intSubset, node->name, name);
                   6619:            if ((attrDecl == NULL) && (doc->extSubset != NULL))
                   6620:                attrDecl = xmlGetDtdAttrDesc(doc->extSubset, node->name, name);
                   6621:             if ((attrDecl != NULL) && (attrDecl->defaultValue != NULL))
                   6622:               /* return attribute declaration only if a default value is given
                   6623:                  (that includes #FIXED declarations) */
                   6624:                return((xmlAttrPtr) attrDecl);
                   6625:        }
                   6626:     }
                   6627:     return(NULL);
                   6628: }
                   6629: 
                   6630: /**
                   6631:  * xmlHasNsProp:
                   6632:  * @node:  the node
                   6633:  * @name:  the attribute name
                   6634:  * @nameSpace:  the URI of the namespace
                   6635:  *
                   6636:  * Search for an attribute associated to a node
                   6637:  * This attribute has to be anchored in the namespace specified.
                   6638:  * This does the entity substitution.
                   6639:  * This function looks in DTD attribute declaration for #FIXED or
                   6640:  * default declaration values unless DTD use has been turned off.
                   6641:  * Note that a namespace of NULL indicates to use the default namespace.
                   6642:  *
                   6643:  * Returns the attribute or the attribute declaration or NULL
                   6644:  *     if neither was found.
                   6645:  */
                   6646: xmlAttrPtr
                   6647: xmlHasNsProp(xmlNodePtr node, const xmlChar *name, const xmlChar *nameSpace) {
                   6648: 
                   6649:     return(xmlGetPropNodeInternal(node, name, nameSpace, xmlCheckDTD));
                   6650: }
                   6651: 
                   6652: /**
                   6653:  * xmlGetProp:
                   6654:  * @node:  the node
                   6655:  * @name:  the attribute name
                   6656:  *
                   6657:  * Search and get the value of an attribute associated to a node
                   6658:  * This does the entity substitution.
                   6659:  * This function looks in DTD attribute declaration for #FIXED or
                   6660:  * default declaration values unless DTD use has been turned off.
                   6661:  * NOTE: this function acts independently of namespaces associated
                   6662:  *       to the attribute. Use xmlGetNsProp() or xmlGetNoNsProp()
                   6663:  *       for namespace aware processing.
                   6664:  *
                   6665:  * Returns the attribute value or NULL if not found.
                   6666:  *     It's up to the caller to free the memory with xmlFree().
                   6667:  */
                   6668: xmlChar *
                   6669: xmlGetProp(xmlNodePtr node, const xmlChar *name) {
                   6670:     xmlAttrPtr prop;
                   6671: 
                   6672:     prop = xmlHasProp(node, name);
                   6673:     if (prop == NULL)
                   6674:        return(NULL);
                   6675:     return(xmlGetPropNodeValueInternal(prop));
                   6676: }
                   6677: 
                   6678: /**
                   6679:  * xmlGetNoNsProp:
                   6680:  * @node:  the node
                   6681:  * @name:  the attribute name
                   6682:  *
                   6683:  * Search and get the value of an attribute associated to a node
                   6684:  * This does the entity substitution.
                   6685:  * This function looks in DTD attribute declaration for #FIXED or
                   6686:  * default declaration values unless DTD use has been turned off.
                   6687:  * This function is similar to xmlGetProp except it will accept only
                   6688:  * an attribute in no namespace.
                   6689:  *
                   6690:  * Returns the attribute value or NULL if not found.
                   6691:  *     It's up to the caller to free the memory with xmlFree().
                   6692:  */
                   6693: xmlChar *
                   6694: xmlGetNoNsProp(xmlNodePtr node, const xmlChar *name) {
                   6695:     xmlAttrPtr prop;
                   6696: 
                   6697:     prop = xmlGetPropNodeInternal(node, name, NULL, xmlCheckDTD);
                   6698:     if (prop == NULL)
                   6699:        return(NULL);
                   6700:     return(xmlGetPropNodeValueInternal(prop));
                   6701: }
                   6702: 
                   6703: /**
                   6704:  * xmlGetNsProp:
                   6705:  * @node:  the node
                   6706:  * @name:  the attribute name
                   6707:  * @nameSpace:  the URI of the namespace
                   6708:  *
                   6709:  * Search and get the value of an attribute associated to a node
                   6710:  * This attribute has to be anchored in the namespace specified.
                   6711:  * This does the entity substitution.
                   6712:  * This function looks in DTD attribute declaration for #FIXED or
                   6713:  * default declaration values unless DTD use has been turned off.
                   6714:  *
                   6715:  * Returns the attribute value or NULL if not found.
                   6716:  *     It's up to the caller to free the memory with xmlFree().
                   6717:  */
                   6718: xmlChar *
                   6719: xmlGetNsProp(xmlNodePtr node, const xmlChar *name, const xmlChar *nameSpace) {
                   6720:     xmlAttrPtr prop;
                   6721: 
                   6722:     prop = xmlGetPropNodeInternal(node, name, nameSpace, xmlCheckDTD);
                   6723:     if (prop == NULL)
                   6724:        return(NULL);
                   6725:     return(xmlGetPropNodeValueInternal(prop));
                   6726: }
                   6727: 
                   6728: #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
                   6729: /**
                   6730:  * xmlUnsetProp:
                   6731:  * @node:  the node
                   6732:  * @name:  the attribute name
                   6733:  *
                   6734:  * Remove an attribute carried by a node.
                   6735:  * This handles only attributes in no namespace.
                   6736:  * Returns 0 if successful, -1 if not found
                   6737:  */
                   6738: int
                   6739: xmlUnsetProp(xmlNodePtr node, const xmlChar *name) {
                   6740:     xmlAttrPtr prop;
                   6741: 
                   6742:     prop = xmlGetPropNodeInternal(node, name, NULL, 0);
                   6743:     if (prop == NULL)
                   6744:        return(-1);
                   6745:     xmlUnlinkNode((xmlNodePtr) prop);
                   6746:     xmlFreeProp(prop);
                   6747:     return(0);
                   6748: }
                   6749: 
                   6750: /**
                   6751:  * xmlUnsetNsProp:
                   6752:  * @node:  the node
                   6753:  * @ns:  the namespace definition
                   6754:  * @name:  the attribute name
                   6755:  *
                   6756:  * Remove an attribute carried by a node.
                   6757:  * Returns 0 if successful, -1 if not found
                   6758:  */
                   6759: int
                   6760: xmlUnsetNsProp(xmlNodePtr node, xmlNsPtr ns, const xmlChar *name) {
                   6761:     xmlAttrPtr prop;
                   6762: 
                   6763:     prop = xmlGetPropNodeInternal(node, name, (ns != NULL) ? ns->href : NULL, 0);
                   6764:     if (prop == NULL)
                   6765:        return(-1);
                   6766:     xmlUnlinkNode((xmlNodePtr) prop);
                   6767:     xmlFreeProp(prop);
                   6768:     return(0);
                   6769: }
                   6770: #endif
                   6771: 
                   6772: #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XINCLUDE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) || defined(LIBXML_HTML_ENABLED)
                   6773: /**
                   6774:  * xmlSetProp:
                   6775:  * @node:  the node
                   6776:  * @name:  the attribute name (a QName)
                   6777:  * @value:  the attribute value
                   6778:  *
                   6779:  * Set (or reset) an attribute carried by a node.
                   6780:  * If @name has a prefix, then the corresponding
                   6781:  * namespace-binding will be used, if in scope; it is an
                   6782:  * error it there's no such ns-binding for the prefix in
                   6783:  * scope.
                   6784:  * Returns the attribute pointer.
                   6785:  *
                   6786:  */
                   6787: xmlAttrPtr
                   6788: xmlSetProp(xmlNodePtr node, const xmlChar *name, const xmlChar *value) {
                   6789:     int len;
                   6790:     const xmlChar *nqname;
                   6791: 
                   6792:     if ((node == NULL) || (name == NULL) || (node->type != XML_ELEMENT_NODE))
                   6793:        return(NULL);
                   6794: 
                   6795:     /*
                   6796:      * handle QNames
                   6797:      */
                   6798:     nqname = xmlSplitQName3(name, &len);
                   6799:     if (nqname != NULL) {
                   6800:         xmlNsPtr ns;
                   6801:        xmlChar *prefix = xmlStrndup(name, len);
                   6802:        ns = xmlSearchNs(node->doc, node, prefix);
                   6803:        if (prefix != NULL)
                   6804:            xmlFree(prefix);
                   6805:        if (ns != NULL)
                   6806:            return(xmlSetNsProp(node, ns, nqname, value));
                   6807:     }
                   6808:     return(xmlSetNsProp(node, NULL, name, value));
                   6809: }
                   6810: 
                   6811: /**
                   6812:  * xmlSetNsProp:
                   6813:  * @node:  the node
                   6814:  * @ns:  the namespace definition
                   6815:  * @name:  the attribute name
                   6816:  * @value:  the attribute value
                   6817:  *
                   6818:  * Set (or reset) an attribute carried by a node.
                   6819:  * The ns structure must be in scope, this is not checked
                   6820:  *
                   6821:  * Returns the attribute pointer.
                   6822:  */
                   6823: xmlAttrPtr
                   6824: xmlSetNsProp(xmlNodePtr node, xmlNsPtr ns, const xmlChar *name,
                   6825:             const xmlChar *value)
                   6826: {
                   6827:     xmlAttrPtr prop;
                   6828: 
                   6829:     if (ns && (ns->href == NULL))
                   6830:        return(NULL);
                   6831:     prop = xmlGetPropNodeInternal(node, name, (ns != NULL) ? ns->href : NULL, 0);
                   6832:     if (prop != NULL) {
                   6833:        /*
                   6834:        * Modify the attribute's value.
                   6835:        */
                   6836:        if (prop->atype == XML_ATTRIBUTE_ID) {
                   6837:            xmlRemoveID(node->doc, prop);
                   6838:            prop->atype = XML_ATTRIBUTE_ID;
                   6839:        }
                   6840:        if (prop->children != NULL)
                   6841:            xmlFreeNodeList(prop->children);
                   6842:        prop->children = NULL;
                   6843:        prop->last = NULL;
                   6844:        prop->ns = ns;
                   6845:        if (value != NULL) {
                   6846:            xmlNodePtr tmp;
                   6847: 
                   6848:            if(!xmlCheckUTF8(value)) {
                   6849:                xmlTreeErr(XML_TREE_NOT_UTF8, (xmlNodePtr) node->doc,
                   6850:                           NULL);
                   6851:                 if (node->doc != NULL)
                   6852:                     node->doc->encoding = xmlStrdup(BAD_CAST "ISO-8859-1");
                   6853:            }
                   6854:            prop->children = xmlNewDocText(node->doc, value);
                   6855:            prop->last = NULL;
                   6856:            tmp = prop->children;
                   6857:            while (tmp != NULL) {
                   6858:                tmp->parent = (xmlNodePtr) prop;
                   6859:                if (tmp->next == NULL)
                   6860:                    prop->last = tmp;
                   6861:                tmp = tmp->next;
                   6862:            }
                   6863:        }
                   6864:        if (prop->atype == XML_ATTRIBUTE_ID)
                   6865:            xmlAddID(NULL, node->doc, value, prop);
                   6866:        return(prop);
                   6867:     }
                   6868:     /*
                   6869:     * No equal attr found; create a new one.
                   6870:     */
                   6871:     return(xmlNewPropInternal(node, ns, name, value, 0));
                   6872: }
                   6873: 
                   6874: #endif /* LIBXML_TREE_ENABLED */
                   6875: 
                   6876: /**
                   6877:  * xmlNodeIsText:
                   6878:  * @node:  the node
                   6879:  *
                   6880:  * Is this node a Text node ?
                   6881:  * Returns 1 yes, 0 no
                   6882:  */
                   6883: int
                   6884: xmlNodeIsText(xmlNodePtr node) {
                   6885:     if (node == NULL) return(0);
                   6886: 
                   6887:     if (node->type == XML_TEXT_NODE) return(1);
                   6888:     return(0);
                   6889: }
                   6890: 
                   6891: /**
                   6892:  * xmlIsBlankNode:
                   6893:  * @node:  the node
                   6894:  *
                   6895:  * Checks whether this node is an empty or whitespace only
                   6896:  * (and possibly ignorable) text-node.
                   6897:  *
                   6898:  * Returns 1 yes, 0 no
                   6899:  */
                   6900: int
                   6901: xmlIsBlankNode(xmlNodePtr node) {
                   6902:     const xmlChar *cur;
                   6903:     if (node == NULL) return(0);
                   6904: 
                   6905:     if ((node->type != XML_TEXT_NODE) &&
                   6906:         (node->type != XML_CDATA_SECTION_NODE))
                   6907:        return(0);
                   6908:     if (node->content == NULL) return(1);
                   6909:     cur = node->content;
                   6910:     while (*cur != 0) {
                   6911:        if (!IS_BLANK_CH(*cur)) return(0);
                   6912:        cur++;
                   6913:     }
                   6914: 
                   6915:     return(1);
                   6916: }
                   6917: 
                   6918: /**
                   6919:  * xmlTextConcat:
                   6920:  * @node:  the node
                   6921:  * @content:  the content
                   6922:  * @len:  @content length
                   6923:  *
                   6924:  * Concat the given string at the end of the existing node content
                   6925:  *
                   6926:  * Returns -1 in case of error, 0 otherwise
                   6927:  */
                   6928: 
                   6929: int
                   6930: xmlTextConcat(xmlNodePtr node, const xmlChar *content, int len) {
                   6931:     if (node == NULL) return(-1);
                   6932: 
                   6933:     if ((node->type != XML_TEXT_NODE) &&
                   6934:         (node->type != XML_CDATA_SECTION_NODE) &&
                   6935:        (node->type != XML_COMMENT_NODE) &&
                   6936:        (node->type != XML_PI_NODE)) {
                   6937: #ifdef DEBUG_TREE
                   6938:        xmlGenericError(xmlGenericErrorContext,
                   6939:                "xmlTextConcat: node is not text nor CDATA\n");
                   6940: #endif
                   6941:         return(-1);
                   6942:     }
                   6943:     /* need to check if content is currently in the dictionary */
                   6944:     if ((node->content == (xmlChar *) &(node->properties)) ||
                   6945:         ((node->doc != NULL) && (node->doc->dict != NULL) &&
                   6946:                xmlDictOwns(node->doc->dict, node->content))) {
                   6947:        node->content = xmlStrncatNew(node->content, content, len);
                   6948:     } else {
                   6949:         node->content = xmlStrncat(node->content, content, len);
                   6950:     }
                   6951:     node->properties = NULL;
                   6952:     if (node->content == NULL)
                   6953:         return(-1);
                   6954:     return(0);
                   6955: }
                   6956: 
                   6957: /************************************************************************
                   6958:  *                                                                     *
                   6959:  *                     Output : to a FILE or in memory                 *
                   6960:  *                                                                     *
                   6961:  ************************************************************************/
                   6962: 
                   6963: /**
                   6964:  * xmlBufferCreate:
                   6965:  *
                   6966:  * routine to create an XML buffer.
                   6967:  * returns the new structure.
                   6968:  */
                   6969: xmlBufferPtr
                   6970: xmlBufferCreate(void) {
                   6971:     xmlBufferPtr ret;
                   6972: 
                   6973:     ret = (xmlBufferPtr) xmlMalloc(sizeof(xmlBuffer));
                   6974:     if (ret == NULL) {
                   6975:        xmlTreeErrMemory("creating buffer");
                   6976:         return(NULL);
                   6977:     }
                   6978:     ret->use = 0;
                   6979:     ret->size = xmlDefaultBufferSize;
                   6980:     ret->alloc = xmlBufferAllocScheme;
                   6981:     ret->content = (xmlChar *) xmlMallocAtomic(ret->size * sizeof(xmlChar));
                   6982:     if (ret->content == NULL) {
                   6983:        xmlTreeErrMemory("creating buffer");
                   6984:        xmlFree(ret);
                   6985:         return(NULL);
                   6986:     }
                   6987:     ret->content[0] = 0;
                   6988:     ret->contentIO = NULL;
                   6989:     return(ret);
                   6990: }
                   6991: 
                   6992: /**
                   6993:  * xmlBufferCreateSize:
                   6994:  * @size: initial size of buffer
                   6995:  *
                   6996:  * routine to create an XML buffer.
                   6997:  * returns the new structure.
                   6998:  */
                   6999: xmlBufferPtr
                   7000: xmlBufferCreateSize(size_t size) {
                   7001:     xmlBufferPtr ret;
                   7002: 
                   7003:     ret = (xmlBufferPtr) xmlMalloc(sizeof(xmlBuffer));
                   7004:     if (ret == NULL) {
                   7005:        xmlTreeErrMemory("creating buffer");
                   7006:         return(NULL);
                   7007:     }
                   7008:     ret->use = 0;
                   7009:     ret->alloc = xmlBufferAllocScheme;
                   7010:     ret->size = (size ? size+2 : 0);         /* +1 for ending null */
                   7011:     if (ret->size){
                   7012:         ret->content = (xmlChar *) xmlMallocAtomic(ret->size * sizeof(xmlChar));
                   7013:         if (ret->content == NULL) {
                   7014:            xmlTreeErrMemory("creating buffer");
                   7015:             xmlFree(ret);
                   7016:             return(NULL);
                   7017:         }
                   7018:         ret->content[0] = 0;
                   7019:     } else
                   7020:        ret->content = NULL;
                   7021:     ret->contentIO = NULL;
                   7022:     return(ret);
                   7023: }
                   7024: 
                   7025: /**
1.1.1.2   misho    7026:  * xmlBufferDetach:
                   7027:  * @buf:  the buffer
                   7028:  *
                   7029:  * Remove the string contained in a buffer and gie it back to the
                   7030:  * caller. The buffer is reset to an empty content.
                   7031:  * This doesn't work with immutable buffers as they can't be reset.
                   7032:  *
                   7033:  * Returns the previous string contained by the buffer.
                   7034:  */
                   7035: xmlChar *
                   7036: xmlBufferDetach(xmlBufferPtr buf) {
                   7037:     xmlChar *ret;
                   7038: 
                   7039:     if (buf == NULL)
                   7040:         return(NULL);
                   7041:     if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE)
                   7042:         return(NULL);
                   7043: 
                   7044:     ret = buf->content;
                   7045:     buf->content = NULL;
                   7046:     buf->size = 0;
                   7047:     buf->use = 0;
                   7048: 
                   7049:     return ret;
                   7050: }
                   7051: 
                   7052: 
                   7053: /**
1.1       misho    7054:  * xmlBufferCreateStatic:
                   7055:  * @mem: the memory area
                   7056:  * @size:  the size in byte
                   7057:  *
                   7058:  * routine to create an XML buffer from an immutable memory area.
                   7059:  * The area won't be modified nor copied, and is expected to be
                   7060:  * present until the end of the buffer lifetime.
                   7061:  *
                   7062:  * returns the new structure.
                   7063:  */
                   7064: xmlBufferPtr
                   7065: xmlBufferCreateStatic(void *mem, size_t size) {
                   7066:     xmlBufferPtr ret;
                   7067: 
                   7068:     if ((mem == NULL) || (size == 0))
                   7069:         return(NULL);
                   7070: 
                   7071:     ret = (xmlBufferPtr) xmlMalloc(sizeof(xmlBuffer));
                   7072:     if (ret == NULL) {
                   7073:        xmlTreeErrMemory("creating buffer");
                   7074:         return(NULL);
                   7075:     }
                   7076:     ret->use = size;
                   7077:     ret->size = size;
                   7078:     ret->alloc = XML_BUFFER_ALLOC_IMMUTABLE;
                   7079:     ret->content = (xmlChar *) mem;
                   7080:     return(ret);
                   7081: }
                   7082: 
                   7083: /**
                   7084:  * xmlBufferSetAllocationScheme:
                   7085:  * @buf:  the buffer to tune
                   7086:  * @scheme:  allocation scheme to use
                   7087:  *
                   7088:  * Sets the allocation scheme for this buffer
                   7089:  */
                   7090: void
                   7091: xmlBufferSetAllocationScheme(xmlBufferPtr buf,
                   7092:                              xmlBufferAllocationScheme scheme) {
                   7093:     if (buf == NULL) {
                   7094: #ifdef DEBUG_BUFFER
                   7095:         xmlGenericError(xmlGenericErrorContext,
                   7096:                "xmlBufferSetAllocationScheme: buf == NULL\n");
                   7097: #endif
                   7098:         return;
                   7099:     }
                   7100:     if ((buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) ||
                   7101:         (buf->alloc == XML_BUFFER_ALLOC_IO)) return;
                   7102:     if ((scheme == XML_BUFFER_ALLOC_DOUBLEIT) ||
                   7103:         (scheme == XML_BUFFER_ALLOC_EXACT) ||
1.1.1.2   misho    7104:         (scheme == XML_BUFFER_ALLOC_HYBRID) ||
1.1       misho    7105:         (scheme == XML_BUFFER_ALLOC_IMMUTABLE))
                   7106:        buf->alloc = scheme;
                   7107: }
                   7108: 
                   7109: /**
                   7110:  * xmlBufferFree:
                   7111:  * @buf:  the buffer to free
                   7112:  *
                   7113:  * Frees an XML buffer. It frees both the content and the structure which
                   7114:  * encapsulate it.
                   7115:  */
                   7116: void
                   7117: xmlBufferFree(xmlBufferPtr buf) {
                   7118:     if (buf == NULL) {
                   7119: #ifdef DEBUG_BUFFER
                   7120:         xmlGenericError(xmlGenericErrorContext,
                   7121:                "xmlBufferFree: buf == NULL\n");
                   7122: #endif
                   7123:        return;
                   7124:     }
                   7125: 
                   7126:     if ((buf->alloc == XML_BUFFER_ALLOC_IO) &&
                   7127:         (buf->contentIO != NULL)) {
                   7128:         xmlFree(buf->contentIO);
                   7129:     } else if ((buf->content != NULL) &&
                   7130:         (buf->alloc != XML_BUFFER_ALLOC_IMMUTABLE)) {
                   7131:         xmlFree(buf->content);
                   7132:     }
                   7133:     xmlFree(buf);
                   7134: }
                   7135: 
                   7136: /**
                   7137:  * xmlBufferEmpty:
                   7138:  * @buf:  the buffer
                   7139:  *
                   7140:  * empty a buffer.
                   7141:  */
                   7142: void
                   7143: xmlBufferEmpty(xmlBufferPtr buf) {
                   7144:     if (buf == NULL) return;
                   7145:     if (buf->content == NULL) return;
                   7146:     buf->use = 0;
                   7147:     if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) {
                   7148:         buf->content = BAD_CAST "";
                   7149:     } else if ((buf->alloc == XML_BUFFER_ALLOC_IO) &&
                   7150:                (buf->contentIO != NULL)) {
                   7151:         size_t start_buf = buf->content - buf->contentIO;
                   7152: 
                   7153:        buf->size += start_buf;
                   7154:         buf->content = buf->contentIO;
                   7155:         buf->content[0] = 0;
                   7156:     } else {
                   7157:         buf->content[0] = 0;
                   7158:     }
                   7159: }
                   7160: 
                   7161: /**
                   7162:  * xmlBufferShrink:
                   7163:  * @buf:  the buffer to dump
                   7164:  * @len:  the number of xmlChar to remove
                   7165:  *
                   7166:  * Remove the beginning of an XML buffer.
                   7167:  *
                   7168:  * Returns the number of #xmlChar removed, or -1 in case of failure.
                   7169:  */
                   7170: int
                   7171: xmlBufferShrink(xmlBufferPtr buf, unsigned int len) {
                   7172:     if (buf == NULL) return(-1);
                   7173:     if (len == 0) return(0);
                   7174:     if (len > buf->use) return(-1);
                   7175: 
                   7176:     buf->use -= len;
                   7177:     if ((buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) ||
                   7178:         ((buf->alloc == XML_BUFFER_ALLOC_IO) && (buf->contentIO != NULL))) {
                   7179:        /*
                   7180:         * we just move the content pointer, but also make sure
                   7181:         * the perceived buffer size has shrinked accordingly
                   7182:         */
                   7183:         buf->content += len;
                   7184:        buf->size -= len;
                   7185: 
                   7186:         /*
                   7187:         * sometimes though it maybe be better to really shrink
                   7188:         * on IO buffers
                   7189:         */
                   7190:        if ((buf->alloc == XML_BUFFER_ALLOC_IO) && (buf->contentIO != NULL)) {
                   7191:            size_t start_buf = buf->content - buf->contentIO;
                   7192:            if (start_buf >= buf->size) {
                   7193:                memmove(buf->contentIO, &buf->content[0], buf->use);
                   7194:                buf->content = buf->contentIO;
                   7195:                buf->content[buf->use] = 0;
                   7196:                buf->size += start_buf;
                   7197:            }
                   7198:        }
                   7199:     } else {
                   7200:        memmove(buf->content, &buf->content[len], buf->use);
                   7201:        buf->content[buf->use] = 0;
                   7202:     }
                   7203:     return(len);
                   7204: }
                   7205: 
                   7206: /**
                   7207:  * xmlBufferGrow:
                   7208:  * @buf:  the buffer
                   7209:  * @len:  the minimum free size to allocate
                   7210:  *
                   7211:  * Grow the available space of an XML buffer.
                   7212:  *
                   7213:  * Returns the new available space or -1 in case of error
                   7214:  */
                   7215: int
                   7216: xmlBufferGrow(xmlBufferPtr buf, unsigned int len) {
                   7217:     int size;
                   7218:     xmlChar *newbuf;
                   7219: 
                   7220:     if (buf == NULL) return(-1);
                   7221: 
                   7222:     if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return(0);
                   7223:     if (len + buf->use < buf->size) return(0);
                   7224: 
                   7225:     /*
                   7226:      * Windows has a BIG problem on realloc timing, so we try to double
                   7227:      * the buffer size (if that's enough) (bug 146697)
                   7228:      * Apparently BSD too, and it's probably best for linux too
                   7229:      * On an embedded system this may be something to change
                   7230:      */
                   7231: #if 1
                   7232:     if (buf->size > len)
                   7233:         size = buf->size * 2;
                   7234:     else
                   7235:         size = buf->use + len + 100;
                   7236: #else
                   7237:     size = buf->use + len + 100;
                   7238: #endif
                   7239: 
                   7240:     if ((buf->alloc == XML_BUFFER_ALLOC_IO) && (buf->contentIO != NULL)) {
                   7241:         size_t start_buf = buf->content - buf->contentIO;
                   7242: 
                   7243:        newbuf = (xmlChar *) xmlRealloc(buf->contentIO, start_buf + size);
                   7244:        if (newbuf == NULL) {
                   7245:            xmlTreeErrMemory("growing buffer");
                   7246:            return(-1);
                   7247:        }
                   7248:        buf->contentIO = newbuf;
                   7249:        buf->content = newbuf + start_buf;
                   7250:     } else {
                   7251:        newbuf = (xmlChar *) xmlRealloc(buf->content, size);
                   7252:        if (newbuf == NULL) {
                   7253:            xmlTreeErrMemory("growing buffer");
                   7254:            return(-1);
                   7255:        }
                   7256:        buf->content = newbuf;
                   7257:     }
                   7258:     buf->size = size;
                   7259:     return(buf->size - buf->use);
                   7260: }
                   7261: 
                   7262: /**
                   7263:  * xmlBufferDump:
                   7264:  * @file:  the file output
                   7265:  * @buf:  the buffer to dump
                   7266:  *
                   7267:  * Dumps an XML buffer to  a FILE *.
                   7268:  * Returns the number of #xmlChar written
                   7269:  */
                   7270: int
                   7271: xmlBufferDump(FILE *file, xmlBufferPtr buf) {
                   7272:     int ret;
                   7273: 
                   7274:     if (buf == NULL) {
                   7275: #ifdef DEBUG_BUFFER
                   7276:         xmlGenericError(xmlGenericErrorContext,
                   7277:                "xmlBufferDump: buf == NULL\n");
                   7278: #endif
                   7279:        return(0);
                   7280:     }
                   7281:     if (buf->content == NULL) {
                   7282: #ifdef DEBUG_BUFFER
                   7283:         xmlGenericError(xmlGenericErrorContext,
                   7284:                "xmlBufferDump: buf->content == NULL\n");
                   7285: #endif
                   7286:        return(0);
                   7287:     }
                   7288:     if (file == NULL)
                   7289:        file = stdout;
                   7290:     ret = fwrite(buf->content, sizeof(xmlChar), buf->use, file);
                   7291:     return(ret);
                   7292: }
                   7293: 
                   7294: /**
                   7295:  * xmlBufferContent:
                   7296:  * @buf:  the buffer
                   7297:  *
                   7298:  * Function to extract the content of a buffer
                   7299:  *
                   7300:  * Returns the internal content
                   7301:  */
                   7302: 
                   7303: const xmlChar *
                   7304: xmlBufferContent(const xmlBufferPtr buf)
                   7305: {
                   7306:     if(!buf)
                   7307:         return NULL;
                   7308: 
                   7309:     return buf->content;
                   7310: }
                   7311: 
                   7312: /**
                   7313:  * xmlBufferLength:
                   7314:  * @buf:  the buffer
                   7315:  *
                   7316:  * Function to get the length of a buffer
                   7317:  *
                   7318:  * Returns the length of data in the internal content
                   7319:  */
                   7320: 
                   7321: int
                   7322: xmlBufferLength(const xmlBufferPtr buf)
                   7323: {
                   7324:     if(!buf)
                   7325:         return 0;
                   7326: 
                   7327:     return buf->use;
                   7328: }
                   7329: 
                   7330: /**
                   7331:  * xmlBufferResize:
                   7332:  * @buf:  the buffer to resize
                   7333:  * @size:  the desired size
                   7334:  *
                   7335:  * Resize a buffer to accommodate minimum size of @size.
                   7336:  *
                   7337:  * Returns  0 in case of problems, 1 otherwise
                   7338:  */
                   7339: int
                   7340: xmlBufferResize(xmlBufferPtr buf, unsigned int size)
                   7341: {
                   7342:     unsigned int newSize;
                   7343:     xmlChar* rebuf = NULL;
                   7344:     size_t start_buf;
                   7345: 
                   7346:     if (buf == NULL)
                   7347:         return(0);
                   7348: 
                   7349:     if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return(0);
                   7350: 
                   7351:     /* Don't resize if we don't have to */
                   7352:     if (size < buf->size)
                   7353:         return 1;
                   7354: 
                   7355:     /* figure out new size */
                   7356:     switch (buf->alloc){
                   7357:        case XML_BUFFER_ALLOC_IO:
                   7358:        case XML_BUFFER_ALLOC_DOUBLEIT:
                   7359:            /*take care of empty case*/
                   7360:            newSize = (buf->size ? buf->size*2 : size + 10);
                   7361:            while (size > newSize) {
                   7362:                if (newSize > UINT_MAX / 2) {
                   7363:                    xmlTreeErrMemory("growing buffer");
                   7364:                    return 0;
                   7365:                }
                   7366:                newSize *= 2;
                   7367:            }
                   7368:            break;
                   7369:        case XML_BUFFER_ALLOC_EXACT:
                   7370:            newSize = size+10;
                   7371:            break;
1.1.1.2   misho    7372:         case XML_BUFFER_ALLOC_HYBRID:
                   7373:             if (buf->use < BASE_BUFFER_SIZE)
                   7374:                 newSize = size;
                   7375:             else {
                   7376:                 newSize = buf->size * 2;
                   7377:                 while (size > newSize) {
                   7378:                     if (newSize > UINT_MAX / 2) {
                   7379:                         xmlTreeErrMemory("growing buffer");
                   7380:                         return 0;
                   7381:                     }
                   7382:                     newSize *= 2;
                   7383:                 }
                   7384:             }
                   7385:             break;
                   7386: 
1.1       misho    7387:        default:
                   7388:            newSize = size+10;
                   7389:            break;
                   7390:     }
                   7391: 
                   7392:     if ((buf->alloc == XML_BUFFER_ALLOC_IO) && (buf->contentIO != NULL)) {
                   7393:         start_buf = buf->content - buf->contentIO;
                   7394: 
                   7395:         if (start_buf > newSize) {
                   7396:            /* move data back to start */
                   7397:            memmove(buf->contentIO, buf->content, buf->use);
                   7398:            buf->content = buf->contentIO;
                   7399:            buf->content[buf->use] = 0;
                   7400:            buf->size += start_buf;
                   7401:        } else {
                   7402:            rebuf = (xmlChar *) xmlRealloc(buf->contentIO, start_buf + newSize);
                   7403:            if (rebuf == NULL) {
                   7404:                xmlTreeErrMemory("growing buffer");
                   7405:                return 0;
                   7406:            }
                   7407:            buf->contentIO = rebuf;
                   7408:            buf->content = rebuf + start_buf;
                   7409:        }
                   7410:     } else {
                   7411:        if (buf->content == NULL) {
                   7412:            rebuf = (xmlChar *) xmlMallocAtomic(newSize);
                   7413:        } else if (buf->size - buf->use < 100) {
                   7414:            rebuf = (xmlChar *) xmlRealloc(buf->content, newSize);
                   7415:         } else {
                   7416:            /*
                   7417:             * if we are reallocating a buffer far from being full, it's
                   7418:             * better to make a new allocation and copy only the used range
                   7419:             * and free the old one.
                   7420:             */
                   7421:            rebuf = (xmlChar *) xmlMallocAtomic(newSize);
                   7422:            if (rebuf != NULL) {
                   7423:                memcpy(rebuf, buf->content, buf->use);
                   7424:                xmlFree(buf->content);
                   7425:                rebuf[buf->use] = 0;
                   7426:            }
                   7427:        }
                   7428:        if (rebuf == NULL) {
                   7429:            xmlTreeErrMemory("growing buffer");
                   7430:            return 0;
                   7431:        }
                   7432:        buf->content = rebuf;
                   7433:     }
                   7434:     buf->size = newSize;
                   7435: 
                   7436:     return 1;
                   7437: }
                   7438: 
                   7439: /**
                   7440:  * xmlBufferAdd:
                   7441:  * @buf:  the buffer to dump
                   7442:  * @str:  the #xmlChar string
                   7443:  * @len:  the number of #xmlChar to add
                   7444:  *
                   7445:  * Add a string range to an XML buffer. if len == -1, the length of
                   7446:  * str is recomputed.
                   7447:  *
                   7448:  * Returns 0 successful, a positive error code number otherwise
                   7449:  *         and -1 in case of internal or API error.
                   7450:  */
                   7451: int
                   7452: xmlBufferAdd(xmlBufferPtr buf, const xmlChar *str, int len) {
                   7453:     unsigned int needSize;
                   7454: 
                   7455:     if ((str == NULL) || (buf == NULL)) {
                   7456:        return -1;
                   7457:     }
                   7458:     if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return -1;
                   7459:     if (len < -1) {
                   7460: #ifdef DEBUG_BUFFER
                   7461:         xmlGenericError(xmlGenericErrorContext,
                   7462:                "xmlBufferAdd: len < 0\n");
                   7463: #endif
                   7464:        return -1;
                   7465:     }
                   7466:     if (len == 0) return 0;
                   7467: 
                   7468:     if (len < 0)
                   7469:         len = xmlStrlen(str);
                   7470: 
                   7471:     if (len < 0) return -1;
                   7472:     if (len == 0) return 0;
                   7473: 
                   7474:     needSize = buf->use + len + 2;
                   7475:     if (needSize > buf->size){
                   7476:         if (!xmlBufferResize(buf, needSize)){
                   7477:            xmlTreeErrMemory("growing buffer");
                   7478:             return XML_ERR_NO_MEMORY;
                   7479:         }
                   7480:     }
                   7481: 
                   7482:     memmove(&buf->content[buf->use], str, len*sizeof(xmlChar));
                   7483:     buf->use += len;
                   7484:     buf->content[buf->use] = 0;
                   7485:     return 0;
                   7486: }
                   7487: 
                   7488: /**
                   7489:  * xmlBufferAddHead:
                   7490:  * @buf:  the buffer
                   7491:  * @str:  the #xmlChar string
                   7492:  * @len:  the number of #xmlChar to add
                   7493:  *
                   7494:  * Add a string range to the beginning of an XML buffer.
                   7495:  * if len == -1, the length of @str is recomputed.
                   7496:  *
                   7497:  * Returns 0 successful, a positive error code number otherwise
                   7498:  *         and -1 in case of internal or API error.
                   7499:  */
                   7500: int
                   7501: xmlBufferAddHead(xmlBufferPtr buf, const xmlChar *str, int len) {
                   7502:     unsigned int needSize;
                   7503: 
                   7504:     if (buf == NULL)
                   7505:         return(-1);
                   7506:     if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return -1;
                   7507:     if (str == NULL) {
                   7508: #ifdef DEBUG_BUFFER
                   7509:         xmlGenericError(xmlGenericErrorContext,
                   7510:                "xmlBufferAddHead: str == NULL\n");
                   7511: #endif
                   7512:        return -1;
                   7513:     }
                   7514:     if (len < -1) {
                   7515: #ifdef DEBUG_BUFFER
                   7516:         xmlGenericError(xmlGenericErrorContext,
                   7517:                "xmlBufferAddHead: len < 0\n");
                   7518: #endif
                   7519:        return -1;
                   7520:     }
                   7521:     if (len == 0) return 0;
                   7522: 
                   7523:     if (len < 0)
                   7524:         len = xmlStrlen(str);
                   7525: 
                   7526:     if (len <= 0) return -1;
                   7527: 
                   7528:     if ((buf->alloc == XML_BUFFER_ALLOC_IO) && (buf->contentIO != NULL)) {
                   7529:         size_t start_buf = buf->content - buf->contentIO;
                   7530: 
                   7531:        if (start_buf > (unsigned int) len) {
                   7532:            /*
                   7533:             * We can add it in the space previously shrinked
                   7534:             */
                   7535:            buf->content -= len;
                   7536:             memmove(&buf->content[0], str, len);
                   7537:            buf->use += len;
                   7538:            buf->size += len;
                   7539:            return(0);
                   7540:        }
                   7541:     }
                   7542:     needSize = buf->use + len + 2;
                   7543:     if (needSize > buf->size){
                   7544:         if (!xmlBufferResize(buf, needSize)){
                   7545:            xmlTreeErrMemory("growing buffer");
                   7546:             return XML_ERR_NO_MEMORY;
                   7547:         }
                   7548:     }
                   7549: 
                   7550:     memmove(&buf->content[len], &buf->content[0], buf->use);
                   7551:     memmove(&buf->content[0], str, len);
                   7552:     buf->use += len;
                   7553:     buf->content[buf->use] = 0;
                   7554:     return 0;
                   7555: }
                   7556: 
                   7557: /**
                   7558:  * xmlBufferCat:
                   7559:  * @buf:  the buffer to add to
                   7560:  * @str:  the #xmlChar string
                   7561:  *
                   7562:  * Append a zero terminated string to an XML buffer.
                   7563:  *
                   7564:  * Returns 0 successful, a positive error code number otherwise
                   7565:  *         and -1 in case of internal or API error.
                   7566:  */
                   7567: int
                   7568: xmlBufferCat(xmlBufferPtr buf, const xmlChar *str) {
                   7569:     if (buf == NULL)
                   7570:         return(-1);
                   7571:     if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return -1;
                   7572:     if (str == NULL) return -1;
                   7573:     return xmlBufferAdd(buf, str, -1);
                   7574: }
                   7575: 
                   7576: /**
                   7577:  * xmlBufferCCat:
                   7578:  * @buf:  the buffer to dump
                   7579:  * @str:  the C char string
                   7580:  *
                   7581:  * Append a zero terminated C string to an XML buffer.
                   7582:  *
                   7583:  * Returns 0 successful, a positive error code number otherwise
                   7584:  *         and -1 in case of internal or API error.
                   7585:  */
                   7586: int
                   7587: xmlBufferCCat(xmlBufferPtr buf, const char *str) {
                   7588:     const char *cur;
                   7589: 
                   7590:     if (buf == NULL)
                   7591:         return(-1);
                   7592:     if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return -1;
                   7593:     if (str == NULL) {
                   7594: #ifdef DEBUG_BUFFER
                   7595:         xmlGenericError(xmlGenericErrorContext,
                   7596:                "xmlBufferCCat: str == NULL\n");
                   7597: #endif
                   7598:        return -1;
                   7599:     }
                   7600:     for (cur = str;*cur != 0;cur++) {
                   7601:         if (buf->use  + 10 >= buf->size) {
                   7602:             if (!xmlBufferResize(buf, buf->use+10)){
                   7603:                xmlTreeErrMemory("growing buffer");
                   7604:                 return XML_ERR_NO_MEMORY;
                   7605:             }
                   7606:         }
                   7607:         buf->content[buf->use++] = *cur;
                   7608:     }
                   7609:     buf->content[buf->use] = 0;
                   7610:     return 0;
                   7611: }
                   7612: 
                   7613: /**
                   7614:  * xmlBufferWriteCHAR:
                   7615:  * @buf:  the XML buffer
                   7616:  * @string:  the string to add
                   7617:  *
                   7618:  * routine which manages and grows an output buffer. This one adds
                   7619:  * xmlChars at the end of the buffer.
                   7620:  */
                   7621: void
                   7622: xmlBufferWriteCHAR(xmlBufferPtr buf, const xmlChar *string) {
                   7623:     if (buf == NULL)
                   7624:         return;
                   7625:     if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return;
                   7626:     xmlBufferCat(buf, string);
                   7627: }
                   7628: 
                   7629: /**
                   7630:  * xmlBufferWriteChar:
                   7631:  * @buf:  the XML buffer output
                   7632:  * @string:  the string to add
                   7633:  *
                   7634:  * routine which manage and grows an output buffer. This one add
                   7635:  * C chars at the end of the array.
                   7636:  */
                   7637: void
                   7638: xmlBufferWriteChar(xmlBufferPtr buf, const char *string) {
                   7639:     if (buf == NULL)
                   7640:         return;
                   7641:     if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return;
                   7642:     xmlBufferCCat(buf, string);
                   7643: }
                   7644: 
                   7645: 
                   7646: /**
                   7647:  * xmlBufferWriteQuotedString:
                   7648:  * @buf:  the XML buffer output
                   7649:  * @string:  the string to add
                   7650:  *
                   7651:  * routine which manage and grows an output buffer. This one writes
                   7652:  * a quoted or double quoted #xmlChar string, checking first if it holds
                   7653:  * quote or double-quotes internally
                   7654:  */
                   7655: void
                   7656: xmlBufferWriteQuotedString(xmlBufferPtr buf, const xmlChar *string) {
                   7657:     const xmlChar *cur, *base;
                   7658:     if (buf == NULL)
                   7659:         return;
                   7660:     if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return;
                   7661:     if (xmlStrchr(string, '\"')) {
                   7662:         if (xmlStrchr(string, '\'')) {
                   7663: #ifdef DEBUG_BUFFER
                   7664:            xmlGenericError(xmlGenericErrorContext,
                   7665:  "xmlBufferWriteQuotedString: string contains quote and double-quotes !\n");
                   7666: #endif
                   7667:            xmlBufferCCat(buf, "\"");
                   7668:             base = cur = string;
                   7669:             while(*cur != 0){
                   7670:                 if(*cur == '"'){
                   7671:                     if (base != cur)
                   7672:                         xmlBufferAdd(buf, base, cur - base);
                   7673:                     xmlBufferAdd(buf, BAD_CAST "&quot;", 6);
                   7674:                     cur++;
                   7675:                     base = cur;
                   7676:                 }
                   7677:                 else {
                   7678:                     cur++;
                   7679:                 }
                   7680:             }
                   7681:             if (base != cur)
                   7682:                 xmlBufferAdd(buf, base, cur - base);
                   7683:            xmlBufferCCat(buf, "\"");
                   7684:        }
                   7685:         else{
                   7686:            xmlBufferCCat(buf, "\'");
                   7687:             xmlBufferCat(buf, string);
                   7688:            xmlBufferCCat(buf, "\'");
                   7689:         }
                   7690:     } else {
                   7691:         xmlBufferCCat(buf, "\"");
                   7692:         xmlBufferCat(buf, string);
                   7693:         xmlBufferCCat(buf, "\"");
                   7694:     }
                   7695: }
                   7696: 
                   7697: 
                   7698: /**
                   7699:  * xmlGetDocCompressMode:
                   7700:  * @doc:  the document
                   7701:  *
                   7702:  * get the compression ratio for a document, ZLIB based
                   7703:  * Returns 0 (uncompressed) to 9 (max compression)
                   7704:  */
                   7705: int
                   7706: xmlGetDocCompressMode (xmlDocPtr doc) {
                   7707:     if (doc == NULL) return(-1);
                   7708:     return(doc->compression);
                   7709: }
                   7710: 
                   7711: /**
                   7712:  * xmlSetDocCompressMode:
                   7713:  * @doc:  the document
                   7714:  * @mode:  the compression ratio
                   7715:  *
                   7716:  * set the compression ratio for a document, ZLIB based
                   7717:  * Correct values: 0 (uncompressed) to 9 (max compression)
                   7718:  */
                   7719: void
                   7720: xmlSetDocCompressMode (xmlDocPtr doc, int mode) {
                   7721:     if (doc == NULL) return;
                   7722:     if (mode < 0) doc->compression = 0;
                   7723:     else if (mode > 9) doc->compression = 9;
                   7724:     else doc->compression = mode;
                   7725: }
                   7726: 
                   7727: /**
                   7728:  * xmlGetCompressMode:
                   7729:  *
                   7730:  * get the default compression mode used, ZLIB based.
                   7731:  * Returns 0 (uncompressed) to 9 (max compression)
                   7732:  */
                   7733: int
                   7734: xmlGetCompressMode(void)
                   7735: {
                   7736:     return (xmlCompressMode);
                   7737: }
                   7738: 
                   7739: /**
                   7740:  * xmlSetCompressMode:
                   7741:  * @mode:  the compression ratio
                   7742:  *
                   7743:  * set the default compression mode used, ZLIB based
                   7744:  * Correct values: 0 (uncompressed) to 9 (max compression)
                   7745:  */
                   7746: void
                   7747: xmlSetCompressMode(int mode) {
                   7748:     if (mode < 0) xmlCompressMode = 0;
                   7749:     else if (mode > 9) xmlCompressMode = 9;
                   7750:     else xmlCompressMode = mode;
                   7751: }
                   7752: 
                   7753: #define XML_TREE_NSMAP_PARENT -1
                   7754: #define XML_TREE_NSMAP_XML -2
                   7755: #define XML_TREE_NSMAP_DOC -3
                   7756: #define XML_TREE_NSMAP_CUSTOM -4
                   7757: 
                   7758: typedef struct xmlNsMapItem *xmlNsMapItemPtr;
                   7759: struct xmlNsMapItem {
                   7760:     xmlNsMapItemPtr next;
                   7761:     xmlNsMapItemPtr prev;
                   7762:     xmlNsPtr oldNs; /* old ns decl reference */
                   7763:     xmlNsPtr newNs; /* new ns decl reference */
                   7764:     int shadowDepth; /* Shadowed at this depth */
                   7765:     /*
                   7766:     * depth:
                   7767:     * >= 0 == @node's ns-decls
                   7768:     * -1   == @parent's ns-decls
                   7769:     * -2   == the doc->oldNs XML ns-decl
                   7770:     * -3   == the doc->oldNs storage ns-decls
                   7771:     * -4   == ns-decls provided via custom ns-handling
                   7772:     */
                   7773:     int depth;
                   7774: };
                   7775: 
                   7776: typedef struct xmlNsMap *xmlNsMapPtr;
                   7777: struct xmlNsMap {
                   7778:     xmlNsMapItemPtr first;
                   7779:     xmlNsMapItemPtr last;
                   7780:     xmlNsMapItemPtr pool;
                   7781: };
                   7782: 
                   7783: #define XML_NSMAP_NOTEMPTY(m) (((m) != NULL) && ((m)->first != NULL))
                   7784: #define XML_NSMAP_FOREACH(m, i) for (i = (m)->first; i != NULL; i = (i)->next)
                   7785: #define XML_NSMAP_POP(m, i) \
                   7786:     i = (m)->last; \
                   7787:     (m)->last = (i)->prev; \
                   7788:     if ((m)->last == NULL) \
                   7789:        (m)->first = NULL; \
                   7790:     else \
                   7791:        (m)->last->next = NULL; \
                   7792:     (i)->next = (m)->pool; \
                   7793:     (m)->pool = i;
                   7794: 
                   7795: /*
                   7796: * xmlDOMWrapNsMapFree:
                   7797: * @map: the ns-map
                   7798: *
                   7799: * Frees the ns-map
                   7800: */
                   7801: static void
                   7802: xmlDOMWrapNsMapFree(xmlNsMapPtr nsmap)
                   7803: {
                   7804:     xmlNsMapItemPtr cur, tmp;
                   7805: 
                   7806:     if (nsmap == NULL)
                   7807:        return;
                   7808:     cur = nsmap->pool;
                   7809:     while (cur != NULL) {
                   7810:        tmp = cur;
                   7811:        cur = cur->next;
                   7812:        xmlFree(tmp);
                   7813:     }
                   7814:     cur = nsmap->first;
                   7815:     while (cur != NULL) {
                   7816:        tmp = cur;
                   7817:        cur = cur->next;
                   7818:        xmlFree(tmp);
                   7819:     }
                   7820:     xmlFree(nsmap);
                   7821: }
                   7822: 
                   7823: /*
                   7824: * xmlDOMWrapNsMapAddItem:
                   7825: * @map: the ns-map
                   7826: * @oldNs: the old ns-struct
                   7827: * @newNs: the new ns-struct
                   7828: * @depth: depth and ns-kind information
                   7829: *
                   7830: * Adds an ns-mapping item.
                   7831: */
                   7832: static xmlNsMapItemPtr
                   7833: xmlDOMWrapNsMapAddItem(xmlNsMapPtr *nsmap, int position,
                   7834:                       xmlNsPtr oldNs, xmlNsPtr newNs, int depth)
                   7835: {
                   7836:     xmlNsMapItemPtr ret;
                   7837:     xmlNsMapPtr map;
                   7838: 
                   7839:     if (nsmap == NULL)
                   7840:        return(NULL);
                   7841:     if ((position != -1) && (position != 0))
                   7842:        return(NULL);
                   7843:     map = *nsmap;
                   7844: 
                   7845:     if (map == NULL) {
                   7846:        /*
                   7847:        * Create the ns-map.
                   7848:        */
                   7849:        map = (xmlNsMapPtr) xmlMalloc(sizeof(struct xmlNsMap));
                   7850:        if (map == NULL) {
                   7851:            xmlTreeErrMemory("allocating namespace map");
                   7852:            return (NULL);
                   7853:        }
                   7854:        memset(map, 0, sizeof(struct xmlNsMap));
                   7855:        *nsmap = map;
                   7856:     }
                   7857: 
                   7858:     if (map->pool != NULL) {
                   7859:        /*
                   7860:        * Reuse an item from the pool.
                   7861:        */
                   7862:        ret = map->pool;
                   7863:        map->pool = ret->next;
                   7864:        memset(ret, 0, sizeof(struct xmlNsMapItem));
                   7865:     } else {
                   7866:        /*
                   7867:        * Create a new item.
                   7868:        */
                   7869:        ret = (xmlNsMapItemPtr) xmlMalloc(sizeof(struct xmlNsMapItem));
                   7870:        if (ret == NULL) {
                   7871:            xmlTreeErrMemory("allocating namespace map item");
                   7872:            return (NULL);
                   7873:        }
                   7874:        memset(ret, 0, sizeof(struct xmlNsMapItem));
                   7875:     }
                   7876: 
                   7877:     if (map->first == NULL) {
                   7878:        /*
                   7879:        * First ever.
                   7880:        */
                   7881:        map->first = ret;
                   7882:        map->last = ret;
                   7883:     } else if (position == -1) {
                   7884:        /*
                   7885:        * Append.
                   7886:        */
                   7887:        ret->prev = map->last;
                   7888:        map->last->next = ret;
                   7889:        map->last = ret;
                   7890:     } else if (position == 0) {
                   7891:        /*
                   7892:        * Set on first position.
                   7893:        */
                   7894:        map->first->prev = ret;
                   7895:        ret->next = map->first;
                   7896:        map->first = ret;
                   7897:     } else
                   7898:        return(NULL);
                   7899: 
                   7900:     ret->oldNs = oldNs;
                   7901:     ret->newNs = newNs;
                   7902:     ret->shadowDepth = -1;
                   7903:     ret->depth = depth;
                   7904:     return (ret);
                   7905: }
                   7906: 
                   7907: /*
                   7908: * xmlDOMWrapStoreNs:
                   7909: * @doc: the doc
                   7910: * @nsName: the namespace name
                   7911: * @prefix: the prefix
                   7912: *
                   7913: * Creates or reuses an xmlNs struct on doc->oldNs with
                   7914: * the given prefix and namespace name.
                   7915: *
                   7916: * Returns the aquired ns struct or NULL in case of an API
                   7917: *         or internal error.
                   7918: */
                   7919: static xmlNsPtr
                   7920: xmlDOMWrapStoreNs(xmlDocPtr doc,
                   7921:                   const xmlChar *nsName,
                   7922:                   const xmlChar *prefix)
                   7923: {
                   7924:     xmlNsPtr ns;
                   7925: 
                   7926:     if (doc == NULL)
                   7927:        return (NULL);
                   7928:     ns = xmlTreeEnsureXMLDecl(doc);
                   7929:     if (ns == NULL)
                   7930:        return (NULL);
                   7931:     if (ns->next != NULL) {
                   7932:        /* Reuse. */
                   7933:        ns = ns->next;
                   7934:        while (ns != NULL) {
                   7935:            if (((ns->prefix == prefix) ||
                   7936:                xmlStrEqual(ns->prefix, prefix)) &&
                   7937:                xmlStrEqual(ns->href, nsName)) {
                   7938:                return (ns);
                   7939:            }
                   7940:            if (ns->next == NULL)
                   7941:                break;
                   7942:            ns = ns->next;
                   7943:        }
                   7944:     }
                   7945:     /* Create. */
                   7946:     if (ns != NULL) {
                   7947:         ns->next = xmlNewNs(NULL, nsName, prefix);
                   7948:         return (ns->next);
                   7949:     }
                   7950:     return(NULL);
                   7951: }
                   7952: 
                   7953: /*
                   7954: * xmlDOMWrapNewCtxt:
                   7955: *
                   7956: * Allocates and initializes a new DOM-wrapper context.
                   7957: *
                   7958: * Returns the xmlDOMWrapCtxtPtr or NULL in case of an internal errror.
                   7959: */
                   7960: xmlDOMWrapCtxtPtr
                   7961: xmlDOMWrapNewCtxt(void)
                   7962: {
                   7963:     xmlDOMWrapCtxtPtr ret;
                   7964: 
                   7965:     ret = xmlMalloc(sizeof(xmlDOMWrapCtxt));
                   7966:     if (ret == NULL) {
                   7967:        xmlTreeErrMemory("allocating DOM-wrapper context");
                   7968:        return (NULL);
                   7969:     }
                   7970:     memset(ret, 0, sizeof(xmlDOMWrapCtxt));
                   7971:     return (ret);
                   7972: }
                   7973: 
                   7974: /*
                   7975: * xmlDOMWrapFreeCtxt:
                   7976: * @ctxt: the DOM-wrapper context
                   7977: *
                   7978: * Frees the DOM-wrapper context.
                   7979: */
                   7980: void
                   7981: xmlDOMWrapFreeCtxt(xmlDOMWrapCtxtPtr ctxt)
                   7982: {
                   7983:     if (ctxt == NULL)
                   7984:        return;
                   7985:     if (ctxt->namespaceMap != NULL)
                   7986:        xmlDOMWrapNsMapFree((xmlNsMapPtr) ctxt->namespaceMap);
                   7987:     /*
                   7988:     * TODO: Store the namespace map in the context.
                   7989:     */
                   7990:     xmlFree(ctxt);
                   7991: }
                   7992: 
                   7993: /*
                   7994: * xmlTreeLookupNsListByPrefix:
                   7995: * @nsList: a list of ns-structs
                   7996: * @prefix: the searched prefix
                   7997: *
                   7998: * Searches for a ns-decl with the given prefix in @nsList.
                   7999: *
                   8000: * Returns the ns-decl if found, NULL if not found and on
                   8001: *         API errors.
                   8002: */
                   8003: static xmlNsPtr
                   8004: xmlTreeNSListLookupByPrefix(xmlNsPtr nsList, const xmlChar *prefix)
                   8005: {
                   8006:     if (nsList == NULL)
                   8007:        return (NULL);
                   8008:     {
                   8009:        xmlNsPtr ns;
                   8010:        ns = nsList;
                   8011:        do {
                   8012:            if ((prefix == ns->prefix) ||
                   8013:                xmlStrEqual(prefix, ns->prefix)) {
                   8014:                return (ns);
                   8015:            }
                   8016:            ns = ns->next;
                   8017:        } while (ns != NULL);
                   8018:     }
                   8019:     return (NULL);
                   8020: }
                   8021: 
                   8022: /*
                   8023: *
                   8024: * xmlDOMWrapNSNormGatherInScopeNs:
                   8025: * @map: the namespace map
                   8026: * @node: the node to start with
                   8027: *
                   8028: * Puts in-scope namespaces into the ns-map.
                   8029: *
                   8030: * Returns 0 on success, -1 on API or internal errors.
                   8031: */
                   8032: static int
                   8033: xmlDOMWrapNSNormGatherInScopeNs(xmlNsMapPtr *map,
                   8034:                                xmlNodePtr node)
                   8035: {
                   8036:     xmlNodePtr cur;
                   8037:     xmlNsPtr ns;
                   8038:     xmlNsMapItemPtr mi;
                   8039:     int shadowed;
                   8040: 
                   8041:     if ((map == NULL) || (*map != NULL))
                   8042:        return (-1);
1.1.1.3 ! misho    8043:     if ((node == NULL) || (node->type == XML_NAMESPACE_DECL))
        !          8044:         return (-1);
1.1       misho    8045:     /*
                   8046:     * Get in-scope ns-decls of @parent.
                   8047:     */
                   8048:     cur = node;
                   8049:     while ((cur != NULL) && (cur != (xmlNodePtr) cur->doc)) {
                   8050:        if (cur->type == XML_ELEMENT_NODE) {
                   8051:            if (cur->nsDef != NULL) {
                   8052:                ns = cur->nsDef;
                   8053:                do {
                   8054:                    shadowed = 0;
                   8055:                    if (XML_NSMAP_NOTEMPTY(*map)) {
                   8056:                        /*
                   8057:                        * Skip shadowed prefixes.
                   8058:                        */
                   8059:                        XML_NSMAP_FOREACH(*map, mi) {
                   8060:                            if ((ns->prefix == mi->newNs->prefix) ||
                   8061:                                xmlStrEqual(ns->prefix, mi->newNs->prefix)) {
                   8062:                                shadowed = 1;
                   8063:                                break;
                   8064:                            }
                   8065:                        }
                   8066:                    }
                   8067:                    /*
                   8068:                    * Insert mapping.
                   8069:                    */
                   8070:                    mi = xmlDOMWrapNsMapAddItem(map, 0, NULL,
                   8071:                        ns, XML_TREE_NSMAP_PARENT);
                   8072:                    if (mi == NULL)
                   8073:                        return (-1);
                   8074:                    if (shadowed)
                   8075:                        mi->shadowDepth = 0;
                   8076:                    ns = ns->next;
                   8077:                } while (ns != NULL);
                   8078:            }
                   8079:        }
                   8080:        cur = cur->parent;
                   8081:     }
                   8082:     return (0);
                   8083: }
                   8084: 
                   8085: /*
                   8086: * XML_TREE_ADOPT_STR: If we have a dest-dict, put @str in the dict;
                   8087: * otherwise copy it, when it was in the source-dict.
                   8088: */
                   8089: #define XML_TREE_ADOPT_STR(str) \
                   8090:     if (adoptStr && (str != NULL)) { \
                   8091:        if (destDoc->dict) { \
                   8092:            const xmlChar *old = str;   \
                   8093:            str = xmlDictLookup(destDoc->dict, str, -1); \
                   8094:            if ((sourceDoc == NULL) || (sourceDoc->dict == NULL) || \
                   8095:                (!xmlDictOwns(sourceDoc->dict, old))) \
                   8096:                xmlFree((char *)old); \
                   8097:        } else if ((sourceDoc) && (sourceDoc->dict) && \
                   8098:            xmlDictOwns(sourceDoc->dict, str)) { \
                   8099:            str = BAD_CAST xmlStrdup(str); \
                   8100:        } \
                   8101:     }
                   8102: 
                   8103: /*
                   8104: * XML_TREE_ADOPT_STR_2: If @str was in the source-dict, then
                   8105: * put it in dest-dict or copy it.
                   8106: */
                   8107: #define XML_TREE_ADOPT_STR_2(str) \
                   8108:     if (adoptStr && (str != NULL) && (sourceDoc != NULL) && \
                   8109:        (sourceDoc->dict != NULL) && \
                   8110:        xmlDictOwns(sourceDoc->dict, cur->content)) { \
                   8111:        if (destDoc->dict) \
                   8112:            cur->content = (xmlChar *) \
                   8113:                xmlDictLookup(destDoc->dict, cur->content, -1); \
                   8114:        else \
                   8115:            cur->content = xmlStrdup(BAD_CAST cur->content); \
                   8116:     }
                   8117: 
                   8118: /*
                   8119: * xmlDOMWrapNSNormAddNsMapItem2:
                   8120: *
                   8121: * For internal use. Adds a ns-decl mapping.
                   8122: *
                   8123: * Returns 0 on success, -1 on internal errors.
                   8124: */
                   8125: static int
                   8126: xmlDOMWrapNSNormAddNsMapItem2(xmlNsPtr **list, int *size, int *number,
                   8127:                        xmlNsPtr oldNs, xmlNsPtr newNs)
                   8128: {
                   8129:     if (*list == NULL) {
                   8130:        *list = (xmlNsPtr *) xmlMalloc(6 * sizeof(xmlNsPtr));
                   8131:        if (*list == NULL) {
                   8132:            xmlTreeErrMemory("alloc ns map item");
                   8133:            return(-1);
                   8134:        }
                   8135:        *size = 3;
                   8136:        *number = 0;
                   8137:     } else if ((*number) >= (*size)) {
                   8138:        *size *= 2;
                   8139:        *list = (xmlNsPtr *) xmlRealloc(*list,
                   8140:            (*size) * 2 * sizeof(xmlNsPtr));
                   8141:        if (*list == NULL) {
                   8142:            xmlTreeErrMemory("realloc ns map item");
                   8143:            return(-1);
                   8144:        }
                   8145:     }
                   8146:     (*list)[2 * (*number)] = oldNs;
                   8147:     (*list)[2 * (*number) +1] = newNs;
                   8148:     (*number)++;
                   8149:     return (0);
                   8150: }
                   8151: 
                   8152: /*
                   8153: * xmlDOMWrapRemoveNode:
                   8154: * @ctxt: a DOM wrapper context
                   8155: * @doc: the doc
                   8156: * @node: the node to be removed.
                   8157: * @options: set of options, unused at the moment
                   8158: *
                   8159: * Unlinks the given node from its owner.
                   8160: * This will substitute ns-references to node->nsDef for
                   8161: * ns-references to doc->oldNs, thus ensuring the removed
                   8162: * branch to be autark wrt ns-references.
                   8163: *
                   8164: * NOTE: This function was not intensively tested.
                   8165: *
                   8166: * Returns 0 on success, 1 if the node is not supported,
                   8167: *         -1 on API and internal errors.
                   8168: */
                   8169: int
                   8170: xmlDOMWrapRemoveNode(xmlDOMWrapCtxtPtr ctxt, xmlDocPtr doc,
                   8171:                     xmlNodePtr node, int options ATTRIBUTE_UNUSED)
                   8172: {
                   8173:     xmlNsPtr *list = NULL;
                   8174:     int sizeList, nbList, i, j;
                   8175:     xmlNsPtr ns;
                   8176: 
                   8177:     if ((node == NULL) || (doc == NULL) || (node->doc != doc))
                   8178:        return (-1);
                   8179: 
                   8180:     /* TODO: 0 or -1 ? */
                   8181:     if (node->parent == NULL)
                   8182:        return (0);
                   8183: 
                   8184:     switch (node->type) {
                   8185:        case XML_TEXT_NODE:
                   8186:        case XML_CDATA_SECTION_NODE:
                   8187:        case XML_ENTITY_REF_NODE:
                   8188:        case XML_PI_NODE:
                   8189:        case XML_COMMENT_NODE:
                   8190:            xmlUnlinkNode(node);
                   8191:            return (0);
                   8192:        case XML_ELEMENT_NODE:
                   8193:        case XML_ATTRIBUTE_NODE:
                   8194:            break;
                   8195:        default:
                   8196:            return (1);
                   8197:     }
                   8198:     xmlUnlinkNode(node);
                   8199:     /*
                   8200:     * Save out-of-scope ns-references in doc->oldNs.
                   8201:     */
                   8202:     do {
                   8203:        switch (node->type) {
                   8204:            case XML_ELEMENT_NODE:
                   8205:                if ((ctxt == NULL) && (node->nsDef != NULL)) {
                   8206:                    ns = node->nsDef;
                   8207:                    do {
                   8208:                        if (xmlDOMWrapNSNormAddNsMapItem2(&list, &sizeList,
                   8209:                            &nbList, ns, ns) == -1)
                   8210:                            goto internal_error;
                   8211:                        ns = ns->next;
                   8212:                    } while (ns != NULL);
                   8213:                }
                   8214:                /* No break on purpose. */
                   8215:            case XML_ATTRIBUTE_NODE:
                   8216:                if (node->ns != NULL) {
                   8217:                    /*
                   8218:                    * Find a mapping.
                   8219:                    */
                   8220:                    if (list != NULL) {
                   8221:                        for (i = 0, j = 0; i < nbList; i++, j += 2) {
                   8222:                            if (node->ns == list[j]) {
                   8223:                                node->ns = list[++j];
                   8224:                                goto next_node;
                   8225:                            }
                   8226:                        }
                   8227:                    }
                   8228:                    ns = NULL;
                   8229:                    if (ctxt != NULL) {
                   8230:                        /*
                   8231:                        * User defined.
                   8232:                        */
                   8233:                    } else {
                   8234:                        /*
                   8235:                        * Add to doc's oldNs.
                   8236:                        */
                   8237:                        ns = xmlDOMWrapStoreNs(doc, node->ns->href,
                   8238:                            node->ns->prefix);
                   8239:                        if (ns == NULL)
                   8240:                            goto internal_error;
                   8241:                    }
                   8242:                    if (ns != NULL) {
                   8243:                        /*
                   8244:                        * Add mapping.
                   8245:                        */
                   8246:                        if (xmlDOMWrapNSNormAddNsMapItem2(&list, &sizeList,
                   8247:                            &nbList, node->ns, ns) == -1)
                   8248:                            goto internal_error;
                   8249:                    }
                   8250:                    node->ns = ns;
                   8251:                }
                   8252:                if ((node->type == XML_ELEMENT_NODE) &&
                   8253:                    (node->properties != NULL)) {
                   8254:                    node = (xmlNodePtr) node->properties;
                   8255:                    continue;
                   8256:                }
                   8257:                break;
                   8258:            default:
                   8259:                goto next_sibling;
                   8260:        }
                   8261: next_node:
                   8262:        if ((node->type == XML_ELEMENT_NODE) &&
                   8263:            (node->children != NULL)) {
                   8264:            node = node->children;
                   8265:            continue;
                   8266:        }
                   8267: next_sibling:
                   8268:        if (node == NULL)
                   8269:            break;
                   8270:        if (node->next != NULL)
                   8271:            node = node->next;
                   8272:        else {
                   8273:            node = node->parent;
                   8274:            goto next_sibling;
                   8275:        }
                   8276:     } while (node != NULL);
                   8277: 
                   8278:     if (list != NULL)
                   8279:        xmlFree(list);
                   8280:     return (0);
                   8281: 
                   8282: internal_error:
                   8283:     if (list != NULL)
                   8284:        xmlFree(list);
                   8285:     return (-1);
                   8286: }
                   8287: 
                   8288: /*
                   8289: * xmlSearchNsByNamespaceStrict:
                   8290: * @doc: the document
                   8291: * @node: the start node
                   8292: * @nsName: the searched namespace name
                   8293: * @retNs: the resulting ns-decl
                   8294: * @prefixed: if the found ns-decl must have a prefix (for attributes)
                   8295: *
                   8296: * Dynamically searches for a ns-declaration which matches
                   8297: * the given @nsName in the ancestor-or-self axis of @node.
                   8298: *
                   8299: * Returns 1 if a ns-decl was found, 0 if not and -1 on API
                   8300: *         and internal errors.
                   8301: */
                   8302: static int
                   8303: xmlSearchNsByNamespaceStrict(xmlDocPtr doc, xmlNodePtr node,
                   8304:                             const xmlChar* nsName,
                   8305:                             xmlNsPtr *retNs, int prefixed)
                   8306: {
                   8307:     xmlNodePtr cur, prev = NULL, out = NULL;
                   8308:     xmlNsPtr ns, prevns;
                   8309: 
                   8310:     if ((doc == NULL) || (nsName == NULL) || (retNs == NULL))
                   8311:        return (-1);
1.1.1.3 ! misho    8312:     if ((node == NULL) || (node->type == XML_NAMESPACE_DECL))
        !          8313:         return(-1);
1.1       misho    8314: 
                   8315:     *retNs = NULL;
                   8316:     if (xmlStrEqual(nsName, XML_XML_NAMESPACE)) {
                   8317:        *retNs = xmlTreeEnsureXMLDecl(doc);
                   8318:        if (*retNs == NULL)
                   8319:            return (-1);
                   8320:        return (1);
                   8321:     }
                   8322:     cur = node;
                   8323:     do {
                   8324:        if (cur->type == XML_ELEMENT_NODE) {
                   8325:            if (cur->nsDef != NULL) {
                   8326:                for (ns = cur->nsDef; ns != NULL; ns = ns->next) {
                   8327:                    if (prefixed && (ns->prefix == NULL))
                   8328:                        continue;
                   8329:                    if (prev != NULL) {
                   8330:                        /*
                   8331:                        * Check the last level of ns-decls for a
                   8332:                        * shadowing prefix.
                   8333:                        */
                   8334:                        prevns = prev->nsDef;
                   8335:                        do {
                   8336:                            if ((prevns->prefix == ns->prefix) ||
                   8337:                                ((prevns->prefix != NULL) &&
                   8338:                                (ns->prefix != NULL) &&
                   8339:                                xmlStrEqual(prevns->prefix, ns->prefix))) {
                   8340:                                /*
                   8341:                                * Shadowed.
                   8342:                                */
                   8343:                                break;
                   8344:                            }
                   8345:                            prevns = prevns->next;
                   8346:                        } while (prevns != NULL);
                   8347:                        if (prevns != NULL)
                   8348:                            continue;
                   8349:                    }
                   8350:                    /*
                   8351:                    * Ns-name comparison.
                   8352:                    */
                   8353:                    if ((nsName == ns->href) ||
                   8354:                        xmlStrEqual(nsName, ns->href)) {
                   8355:                        /*
                   8356:                        * At this point the prefix can only be shadowed,
                   8357:                        * if we are the the (at least) 3rd level of
                   8358:                        * ns-decls.
                   8359:                        */
                   8360:                        if (out) {
                   8361:                            int ret;
                   8362: 
                   8363:                            ret = xmlNsInScope(doc, node, prev, ns->prefix);
                   8364:                            if (ret < 0)
                   8365:                                return (-1);
                   8366:                            /*
                   8367:                            * TODO: Should we try to find a matching ns-name
                   8368:                            * only once? This here keeps on searching.
                   8369:                            * I think we should try further since, there might
                   8370:                            * be an other matching ns-decl with an unshadowed
                   8371:                            * prefix.
                   8372:                            */
                   8373:                            if (! ret)
                   8374:                                continue;
                   8375:                        }
                   8376:                        *retNs = ns;
                   8377:                        return (1);
                   8378:                    }
                   8379:                }
                   8380:                out = prev;
                   8381:                prev = cur;
                   8382:            }
                   8383:        } else if ((cur->type == XML_ENTITY_NODE) ||
                   8384:             (cur->type == XML_ENTITY_DECL))
                   8385:            return (0);
                   8386:        cur = cur->parent;
                   8387:     } while ((cur != NULL) && (cur->doc != (xmlDocPtr) cur));
                   8388:     return (0);
                   8389: }
                   8390: 
                   8391: /*
                   8392: * xmlSearchNsByPrefixStrict:
                   8393: * @doc: the document
                   8394: * @node: the start node
                   8395: * @prefix: the searched namespace prefix
                   8396: * @retNs: the resulting ns-decl
                   8397: *
                   8398: * Dynamically searches for a ns-declaration which matches
                   8399: * the given @nsName in the ancestor-or-self axis of @node.
                   8400: *
                   8401: * Returns 1 if a ns-decl was found, 0 if not and -1 on API
                   8402: *         and internal errors.
                   8403: */
                   8404: static int
                   8405: xmlSearchNsByPrefixStrict(xmlDocPtr doc, xmlNodePtr node,
                   8406:                          const xmlChar* prefix,
                   8407:                          xmlNsPtr *retNs)
                   8408: {
                   8409:     xmlNodePtr cur;
                   8410:     xmlNsPtr ns;
                   8411: 
1.1.1.3 ! misho    8412:     if ((doc == NULL) || (node == NULL) || (node->type == XML_NAMESPACE_DECL))
        !          8413:         return(-1);
1.1       misho    8414: 
                   8415:     if (retNs)
                   8416:        *retNs = NULL;
                   8417:     if (IS_STR_XML(prefix)) {
                   8418:        if (retNs) {
                   8419:            *retNs = xmlTreeEnsureXMLDecl(doc);
                   8420:            if (*retNs == NULL)
                   8421:                return (-1);
                   8422:        }
                   8423:        return (1);
                   8424:     }
                   8425:     cur = node;
                   8426:     do {
                   8427:        if (cur->type == XML_ELEMENT_NODE) {
                   8428:            if (cur->nsDef != NULL) {
                   8429:                ns = cur->nsDef;
                   8430:                do {
                   8431:                    if ((prefix == ns->prefix) ||
                   8432:                        xmlStrEqual(prefix, ns->prefix))
                   8433:                    {
                   8434:                        /*
                   8435:                        * Disabled namespaces, e.g. xmlns:abc="".
                   8436:                        */
                   8437:                        if (ns->href == NULL)
                   8438:                            return(0);
                   8439:                        if (retNs)
                   8440:                            *retNs = ns;
                   8441:                        return (1);
                   8442:                    }
                   8443:                    ns = ns->next;
                   8444:                } while (ns != NULL);
                   8445:            }
                   8446:        } else if ((cur->type == XML_ENTITY_NODE) ||
                   8447:             (cur->type == XML_ENTITY_DECL))
                   8448:            return (0);
                   8449:        cur = cur->parent;
                   8450:     } while ((cur != NULL) && (cur->doc != (xmlDocPtr) cur));
                   8451:     return (0);
                   8452: }
                   8453: 
                   8454: /*
                   8455: * xmlDOMWrapNSNormDeclareNsForced:
                   8456: * @doc: the doc
                   8457: * @elem: the element-node to declare on
                   8458: * @nsName: the namespace-name of the ns-decl
                   8459: * @prefix: the preferred prefix of the ns-decl
                   8460: * @checkShadow: ensure that the new ns-decl doesn't shadow ancestor ns-decls
                   8461: *
                   8462: * Declares a new namespace on @elem. It tries to use the
                   8463: * given @prefix; if a ns-decl with the given prefix is already existent
                   8464: * on @elem, it will generate an other prefix.
                   8465: *
                   8466: * Returns 1 if a ns-decl was found, 0 if not and -1 on API
                   8467: *         and internal errors.
                   8468: */
                   8469: static xmlNsPtr
                   8470: xmlDOMWrapNSNormDeclareNsForced(xmlDocPtr doc,
                   8471:                                xmlNodePtr elem,
                   8472:                                const xmlChar *nsName,
                   8473:                                const xmlChar *prefix,
                   8474:                                int checkShadow)
                   8475: {
                   8476: 
                   8477:     xmlNsPtr ret;
                   8478:     char buf[50];
                   8479:     const xmlChar *pref;
                   8480:     int counter = 0;
1.1.1.3 ! misho    8481: 
        !          8482:     if ((doc == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
        !          8483:         return(NULL);
1.1       misho    8484:     /*
                   8485:     * Create a ns-decl on @anchor.
                   8486:     */
                   8487:     pref = prefix;
                   8488:     while (1) {
                   8489:        /*
                   8490:        * Lookup whether the prefix is unused in elem's ns-decls.
                   8491:        */
                   8492:        if ((elem->nsDef != NULL) &&
                   8493:            (xmlTreeNSListLookupByPrefix(elem->nsDef, pref) != NULL))
                   8494:            goto ns_next_prefix;
                   8495:        if (checkShadow && elem->parent &&
                   8496:            ((xmlNodePtr) elem->parent->doc != elem->parent)) {
                   8497:            /*
                   8498:            * Does it shadow ancestor ns-decls?
                   8499:            */
                   8500:            if (xmlSearchNsByPrefixStrict(doc, elem->parent, pref, NULL) == 1)
                   8501:                goto ns_next_prefix;
                   8502:        }
                   8503:        ret = xmlNewNs(NULL, nsName, pref);
                   8504:        if (ret == NULL)
                   8505:            return (NULL);
                   8506:        if (elem->nsDef == NULL)
                   8507:            elem->nsDef = ret;
                   8508:        else {
                   8509:            xmlNsPtr ns2 = elem->nsDef;
                   8510:            while (ns2->next != NULL)
                   8511:                ns2 = ns2->next;
                   8512:            ns2->next = ret;
                   8513:        }
                   8514:        return (ret);
                   8515: ns_next_prefix:
                   8516:        counter++;
                   8517:        if (counter > 1000)
                   8518:            return (NULL);
                   8519:        if (prefix == NULL) {
                   8520:            snprintf((char *) buf, sizeof(buf),
                   8521:                "ns_%d", counter);
                   8522:        } else
                   8523:            snprintf((char *) buf, sizeof(buf),
                   8524:            "%.30s_%d", (char *)prefix, counter);
                   8525:        pref = BAD_CAST buf;
                   8526:     }
                   8527: }
                   8528: 
                   8529: /*
                   8530: * xmlDOMWrapNSNormAquireNormalizedNs:
                   8531: * @doc: the doc
                   8532: * @elem: the element-node to declare namespaces on
                   8533: * @ns: the ns-struct to use for the search
                   8534: * @retNs: the found/created ns-struct
                   8535: * @nsMap: the ns-map
                   8536: * @depth: the current tree depth
                   8537: * @ancestorsOnly: search in ancestor ns-decls only
                   8538: * @prefixed: if the searched ns-decl must have a prefix (for attributes)
                   8539: *
                   8540: * Searches for a matching ns-name in the ns-decls of @nsMap, if not
                   8541: * found it will either declare it on @elem, or store it in doc->oldNs.
                   8542: * If a new ns-decl needs to be declared on @elem, it tries to use the
                   8543: * @ns->prefix for it, if this prefix is already in use on @elem, it will
                   8544: * change the prefix or the new ns-decl.
                   8545: *
                   8546: * Returns 0 if succeeded, -1 otherwise and on API/internal errors.
                   8547: */
                   8548: static int
                   8549: xmlDOMWrapNSNormAquireNormalizedNs(xmlDocPtr doc,
                   8550:                                   xmlNodePtr elem,
                   8551:                                   xmlNsPtr ns,
                   8552:                                   xmlNsPtr *retNs,
                   8553:                                   xmlNsMapPtr *nsMap,
                   8554: 
                   8555:                                   int depth,
                   8556:                                   int ancestorsOnly,
                   8557:                                   int prefixed)
                   8558: {
                   8559:     xmlNsMapItemPtr mi;
                   8560: 
                   8561:     if ((doc == NULL) || (ns == NULL) || (retNs == NULL) ||
                   8562:        (nsMap == NULL))
                   8563:        return (-1);
                   8564: 
                   8565:     *retNs = NULL;
                   8566:     /*
                   8567:     * Handle XML namespace.
                   8568:     */
                   8569:     if (IS_STR_XML(ns->prefix)) {
                   8570:        /*
                   8571:        * Insert XML namespace mapping.
                   8572:        */
                   8573:        *retNs = xmlTreeEnsureXMLDecl(doc);
                   8574:        if (*retNs == NULL)
                   8575:            return (-1);
                   8576:        return (0);
                   8577:     }
                   8578:     /*
                   8579:     * If the search should be done in ancestors only and no
                   8580:     * @elem (the first ancestor) was specified, then skip the search.
                   8581:     */
                   8582:     if ((XML_NSMAP_NOTEMPTY(*nsMap)) &&
                   8583:        (! (ancestorsOnly && (elem == NULL))))
                   8584:     {
                   8585:        /*
                   8586:        * Try to find an equal ns-name in in-scope ns-decls.
                   8587:        */
                   8588:        XML_NSMAP_FOREACH(*nsMap, mi) {
                   8589:            if ((mi->depth >= XML_TREE_NSMAP_PARENT) &&
                   8590:                /*
                   8591:                * ancestorsOnly: This should be turned on to gain speed,
                   8592:                * if one knows that the branch itself was already
                   8593:                * ns-wellformed and no stale references existed.
                   8594:                * I.e. it searches in the ancestor axis only.
                   8595:                */
                   8596:                ((! ancestorsOnly) || (mi->depth == XML_TREE_NSMAP_PARENT)) &&
                   8597:                /* Skip shadowed prefixes. */
                   8598:                (mi->shadowDepth == -1) &&
                   8599:                /* Skip xmlns="" or xmlns:foo="". */
                   8600:                ((mi->newNs->href != NULL) &&
                   8601:                (mi->newNs->href[0] != 0)) &&
                   8602:                /* Ensure a prefix if wanted. */
                   8603:                ((! prefixed) || (mi->newNs->prefix != NULL)) &&
                   8604:                /* Equal ns name */
                   8605:                ((mi->newNs->href == ns->href) ||
                   8606:                xmlStrEqual(mi->newNs->href, ns->href))) {
                   8607:                /* Set the mapping. */
                   8608:                mi->oldNs = ns;
                   8609:                *retNs = mi->newNs;
                   8610:                return (0);
                   8611:            }
                   8612:        }
                   8613:     }
                   8614:     /*
                   8615:     * No luck, the namespace is out of scope or shadowed.
                   8616:     */
                   8617:     if (elem == NULL) {
                   8618:        xmlNsPtr tmpns;
                   8619: 
                   8620:        /*
                   8621:        * Store ns-decls in "oldNs" of the document-node.
                   8622:        */
                   8623:        tmpns = xmlDOMWrapStoreNs(doc, ns->href, ns->prefix);
                   8624:        if (tmpns == NULL)
                   8625:            return (-1);
                   8626:        /*
                   8627:        * Insert mapping.
                   8628:        */
                   8629:        if (xmlDOMWrapNsMapAddItem(nsMap, -1, ns,
                   8630:                tmpns, XML_TREE_NSMAP_DOC) == NULL) {
                   8631:            xmlFreeNs(tmpns);
                   8632:            return (-1);
                   8633:        }
                   8634:        *retNs = tmpns;
                   8635:     } else {
                   8636:        xmlNsPtr tmpns;
                   8637: 
                   8638:        tmpns = xmlDOMWrapNSNormDeclareNsForced(doc, elem, ns->href,
                   8639:            ns->prefix, 0);
                   8640:        if (tmpns == NULL)
                   8641:            return (-1);
                   8642: 
                   8643:        if (*nsMap != NULL) {
                   8644:            /*
                   8645:            * Does it shadow ancestor ns-decls?
                   8646:            */
                   8647:            XML_NSMAP_FOREACH(*nsMap, mi) {
                   8648:                if ((mi->depth < depth) &&
                   8649:                    (mi->shadowDepth == -1) &&
                   8650:                    ((ns->prefix == mi->newNs->prefix) ||
                   8651:                    xmlStrEqual(ns->prefix, mi->newNs->prefix))) {
                   8652:                    /*
                   8653:                    * Shadows.
                   8654:                    */
                   8655:                    mi->shadowDepth = depth;
                   8656:                    break;
                   8657:                }
                   8658:            }
                   8659:        }
                   8660:        if (xmlDOMWrapNsMapAddItem(nsMap, -1, ns, tmpns, depth) == NULL) {
                   8661:            xmlFreeNs(tmpns);
                   8662:            return (-1);
                   8663:        }
                   8664:        *retNs = tmpns;
                   8665:     }
                   8666:     return (0);
                   8667: }
                   8668: 
                   8669: typedef enum {
                   8670:     XML_DOM_RECONNS_REMOVEREDUND = 1<<0
                   8671: } xmlDOMReconcileNSOptions;
                   8672: 
                   8673: /*
                   8674: * xmlDOMWrapReconcileNamespaces:
                   8675: * @ctxt: DOM wrapper context, unused at the moment
                   8676: * @elem: the element-node
                   8677: * @options: option flags
                   8678: *
                   8679: * Ensures that ns-references point to ns-decls hold on element-nodes.
                   8680: * Ensures that the tree is namespace wellformed by creating additional
                   8681: * ns-decls where needed. Note that, since prefixes of already existent
                   8682: * ns-decls can be shadowed by this process, it could break QNames in
                   8683: * attribute values or element content.
                   8684: *
                   8685: * NOTE: This function was not intensively tested.
                   8686: *
                   8687: * Returns 0 if succeeded, -1 otherwise and on API/internal errors.
                   8688: */
                   8689: 
                   8690: int
                   8691: xmlDOMWrapReconcileNamespaces(xmlDOMWrapCtxtPtr ctxt ATTRIBUTE_UNUSED,
                   8692:                              xmlNodePtr elem,
                   8693:                              int options)
                   8694: {
                   8695:     int depth = -1, adoptns = 0, parnsdone = 0;
                   8696:     xmlNsPtr ns, prevns;
                   8697:     xmlDocPtr doc;
                   8698:     xmlNodePtr cur, curElem = NULL;
                   8699:     xmlNsMapPtr nsMap = NULL;
                   8700:     xmlNsMapItemPtr /* topmi = NULL, */ mi;
                   8701:     /* @ancestorsOnly should be set by an option flag. */
                   8702:     int ancestorsOnly = 0;
                   8703:     int optRemoveRedundantNS =
                   8704:        ((xmlDOMReconcileNSOptions) options & XML_DOM_RECONNS_REMOVEREDUND) ? 1 : 0;
                   8705:     xmlNsPtr *listRedund = NULL;
                   8706:     int sizeRedund = 0, nbRedund = 0, ret, i, j;
                   8707: 
                   8708:     if ((elem == NULL) || (elem->doc == NULL) ||
                   8709:        (elem->type != XML_ELEMENT_NODE))
                   8710:        return (-1);
                   8711: 
                   8712:     doc = elem->doc;
                   8713:     cur = elem;
                   8714:     do {
                   8715:        switch (cur->type) {
                   8716:            case XML_ELEMENT_NODE:
                   8717:                adoptns = 1;
                   8718:                curElem = cur;
                   8719:                depth++;
                   8720:                /*
                   8721:                * Namespace declarations.
                   8722:                */
                   8723:                if (cur->nsDef != NULL) {
                   8724:                    prevns = NULL;
                   8725:                    ns = cur->nsDef;
                   8726:                    while (ns != NULL) {
                   8727:                        if (! parnsdone) {
                   8728:                            if ((elem->parent) &&
                   8729:                                ((xmlNodePtr) elem->parent->doc != elem->parent)) {
                   8730:                                /*
                   8731:                                * Gather ancestor in-scope ns-decls.
                   8732:                                */
                   8733:                                if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap,
                   8734:                                    elem->parent) == -1)
                   8735:                                    goto internal_error;
                   8736:                            }
                   8737:                            parnsdone = 1;
                   8738:                        }
                   8739: 
                   8740:                        /*
                   8741:                        * Lookup the ns ancestor-axis for equal ns-decls in scope.
                   8742:                        */
                   8743:                        if (optRemoveRedundantNS && XML_NSMAP_NOTEMPTY(nsMap)) {
                   8744:                            XML_NSMAP_FOREACH(nsMap, mi) {
                   8745:                                if ((mi->depth >= XML_TREE_NSMAP_PARENT) &&
                   8746:                                    (mi->shadowDepth == -1) &&
                   8747:                                    ((ns->prefix == mi->newNs->prefix) ||
                   8748:                                      xmlStrEqual(ns->prefix, mi->newNs->prefix)) &&
                   8749:                                    ((ns->href == mi->newNs->href) ||
                   8750:                                      xmlStrEqual(ns->href, mi->newNs->href)))
                   8751:                                {
                   8752:                                    /*
                   8753:                                    * A redundant ns-decl was found.
                   8754:                                    * Add it to the list of redundant ns-decls.
                   8755:                                    */
                   8756:                                    if (xmlDOMWrapNSNormAddNsMapItem2(&listRedund,
                   8757:                                        &sizeRedund, &nbRedund, ns, mi->newNs) == -1)
                   8758:                                        goto internal_error;
                   8759:                                    /*
                   8760:                                    * Remove the ns-decl from the element-node.
                   8761:                                    */
                   8762:                                    if (prevns)
                   8763:                                        prevns->next = ns->next;
                   8764:                                    else
                   8765:                                        cur->nsDef = ns->next;
                   8766:                                    goto next_ns_decl;
                   8767:                                }
                   8768:                            }
                   8769:                        }
                   8770: 
                   8771:                        /*
                   8772:                        * Skip ns-references handling if the referenced
                   8773:                        * ns-decl is declared on the same element.
                   8774:                        */
                   8775:                        if ((cur->ns != NULL) && adoptns && (cur->ns == ns))
                   8776:                            adoptns = 0;
                   8777:                        /*
                   8778:                        * Does it shadow any ns-decl?
                   8779:                        */
                   8780:                        if (XML_NSMAP_NOTEMPTY(nsMap)) {
                   8781:                            XML_NSMAP_FOREACH(nsMap, mi) {
                   8782:                                if ((mi->depth >= XML_TREE_NSMAP_PARENT) &&
                   8783:                                    (mi->shadowDepth == -1) &&
                   8784:                                    ((ns->prefix == mi->newNs->prefix) ||
                   8785:                                    xmlStrEqual(ns->prefix, mi->newNs->prefix))) {
                   8786: 
                   8787:                                    mi->shadowDepth = depth;
                   8788:                                }
                   8789:                            }
                   8790:                        }
                   8791:                        /*
                   8792:                        * Push mapping.
                   8793:                        */
                   8794:                        if (xmlDOMWrapNsMapAddItem(&nsMap, -1, ns, ns,
                   8795:                            depth) == NULL)
                   8796:                            goto internal_error;
                   8797: 
                   8798:                        prevns = ns;
                   8799: next_ns_decl:
                   8800:                        ns = ns->next;
                   8801:                    }
                   8802:                }
                   8803:                if (! adoptns)
                   8804:                    goto ns_end;
                   8805:                /* No break on purpose. */
                   8806:            case XML_ATTRIBUTE_NODE:
                   8807:                /* No ns, no fun. */
                   8808:                if (cur->ns == NULL)
                   8809:                    goto ns_end;
                   8810: 
                   8811:                if (! parnsdone) {
                   8812:                    if ((elem->parent) &&
                   8813:                        ((xmlNodePtr) elem->parent->doc != elem->parent)) {
                   8814:                        if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap,
                   8815:                                elem->parent) == -1)
                   8816:                            goto internal_error;
                   8817:                    }
                   8818:                    parnsdone = 1;
                   8819:                }
                   8820:                /*
                   8821:                * Adjust the reference if this was a redundant ns-decl.
                   8822:                */
                   8823:                if (listRedund) {
                   8824:                   for (i = 0, j = 0; i < nbRedund; i++, j += 2) {
                   8825:                       if (cur->ns == listRedund[j]) {
                   8826:                           cur->ns = listRedund[++j];
                   8827:                           break;
                   8828:                       }
                   8829:                   }
                   8830:                }
                   8831:                /*
                   8832:                * Adopt ns-references.
                   8833:                */
                   8834:                if (XML_NSMAP_NOTEMPTY(nsMap)) {
                   8835:                    /*
                   8836:                    * Search for a mapping.
                   8837:                    */
                   8838:                    XML_NSMAP_FOREACH(nsMap, mi) {
                   8839:                        if ((mi->shadowDepth == -1) &&
                   8840:                            (cur->ns == mi->oldNs)) {
                   8841: 
                   8842:                            cur->ns = mi->newNs;
                   8843:                            goto ns_end;
                   8844:                        }
                   8845:                    }
                   8846:                }
                   8847:                /*
                   8848:                * Aquire a normalized ns-decl and add it to the map.
                   8849:                */
                   8850:                if (xmlDOMWrapNSNormAquireNormalizedNs(doc, curElem,
                   8851:                        cur->ns, &ns,
                   8852:                        &nsMap, depth,
                   8853:                        ancestorsOnly,
                   8854:                        (cur->type == XML_ATTRIBUTE_NODE) ? 1 : 0) == -1)
                   8855:                    goto internal_error;
                   8856:                cur->ns = ns;
                   8857: 
                   8858: ns_end:
                   8859:                if ((cur->type == XML_ELEMENT_NODE) &&
                   8860:                    (cur->properties != NULL)) {
                   8861:                    /*
                   8862:                    * Process attributes.
                   8863:                    */
                   8864:                    cur = (xmlNodePtr) cur->properties;
                   8865:                    continue;
                   8866:                }
                   8867:                break;
                   8868:            default:
                   8869:                goto next_sibling;
                   8870:        }
                   8871: into_content:
                   8872:        if ((cur->type == XML_ELEMENT_NODE) &&
                   8873:            (cur->children != NULL)) {
                   8874:            /*
                   8875:            * Process content of element-nodes only.
                   8876:            */
                   8877:            cur = cur->children;
                   8878:            continue;
                   8879:        }
                   8880: next_sibling:
                   8881:        if (cur == elem)
                   8882:            break;
                   8883:        if (cur->type == XML_ELEMENT_NODE) {
                   8884:            if (XML_NSMAP_NOTEMPTY(nsMap)) {
                   8885:                /*
                   8886:                * Pop mappings.
                   8887:                */
                   8888:                while ((nsMap->last != NULL) &&
                   8889:                    (nsMap->last->depth >= depth))
                   8890:                {
                   8891:                    XML_NSMAP_POP(nsMap, mi)
                   8892:                }
                   8893:                /*
                   8894:                * Unshadow.
                   8895:                */
                   8896:                XML_NSMAP_FOREACH(nsMap, mi) {
                   8897:                    if (mi->shadowDepth >= depth)
                   8898:                        mi->shadowDepth = -1;
                   8899:                }
                   8900:            }
                   8901:            depth--;
                   8902:        }
                   8903:        if (cur->next != NULL)
                   8904:            cur = cur->next;
                   8905:        else {
                   8906:            if (cur->type == XML_ATTRIBUTE_NODE) {
                   8907:                cur = cur->parent;
                   8908:                goto into_content;
                   8909:            }
                   8910:            cur = cur->parent;
                   8911:            goto next_sibling;
                   8912:        }
                   8913:     } while (cur != NULL);
                   8914: 
                   8915:     ret = 0;
                   8916:     goto exit;
                   8917: internal_error:
                   8918:     ret = -1;
                   8919: exit:
                   8920:     if (listRedund) {
                   8921:        for (i = 0, j = 0; i < nbRedund; i++, j += 2) {
                   8922:            xmlFreeNs(listRedund[j]);
                   8923:        }
                   8924:        xmlFree(listRedund);
                   8925:     }
                   8926:     if (nsMap != NULL)
                   8927:        xmlDOMWrapNsMapFree(nsMap);
                   8928:     return (ret);
                   8929: }
                   8930: 
                   8931: /*
                   8932: * xmlDOMWrapAdoptBranch:
                   8933: * @ctxt: the optional context for custom processing
                   8934: * @sourceDoc: the optional sourceDoc
                   8935: * @node: the element-node to start with
                   8936: * @destDoc: the destination doc for adoption
                   8937: * @destParent: the optional new parent of @node in @destDoc
                   8938: * @options: option flags
                   8939: *
                   8940: * Ensures that ns-references point to @destDoc: either to
                   8941: * elements->nsDef entries if @destParent is given, or to
                   8942: * @destDoc->oldNs otherwise.
                   8943: * If @destParent is given, it ensures that the tree is namespace
                   8944: * wellformed by creating additional ns-decls where needed.
                   8945: * Note that, since prefixes of already existent ns-decls can be
                   8946: * shadowed by this process, it could break QNames in attribute
                   8947: * values or element content.
                   8948: *
                   8949: * NOTE: This function was not intensively tested.
                   8950: *
                   8951: * Returns 0 if succeeded, -1 otherwise and on API/internal errors.
                   8952: */
                   8953: static int
                   8954: xmlDOMWrapAdoptBranch(xmlDOMWrapCtxtPtr ctxt,
                   8955:                      xmlDocPtr sourceDoc,
                   8956:                      xmlNodePtr node,
                   8957:                      xmlDocPtr destDoc,
                   8958:                      xmlNodePtr destParent,
                   8959:                      int options ATTRIBUTE_UNUSED)
                   8960: {
                   8961:     int ret = 0;
                   8962:     xmlNodePtr cur, curElem = NULL;
                   8963:     xmlNsMapPtr nsMap = NULL;
                   8964:     xmlNsMapItemPtr mi;
                   8965:     xmlNsPtr ns = NULL;
                   8966:     int depth = -1, adoptStr = 1;
                   8967:     /* gather @parent's ns-decls. */
                   8968:     int parnsdone;
                   8969:     /* @ancestorsOnly should be set per option. */
                   8970:     int ancestorsOnly = 0;
                   8971: 
                   8972:     /*
                   8973:     * Optimize string adoption for equal or none dicts.
                   8974:     */
                   8975:     if ((sourceDoc != NULL) &&
                   8976:        (sourceDoc->dict == destDoc->dict))
                   8977:        adoptStr = 0;
                   8978:     else
                   8979:        adoptStr = 1;
                   8980: 
                   8981:     /*
                   8982:     * Get the ns-map from the context if available.
                   8983:     */
                   8984:     if (ctxt)
                   8985:        nsMap = (xmlNsMapPtr) ctxt->namespaceMap;
                   8986:     /*
                   8987:     * Disable search for ns-decls in the parent-axis of the
                   8988:     * desination element, if:
                   8989:     * 1) there's no destination parent
                   8990:     * 2) custom ns-reference handling is used
                   8991:     */
                   8992:     if ((destParent == NULL) ||
                   8993:        (ctxt && ctxt->getNsForNodeFunc))
                   8994:     {
                   8995:        parnsdone = 1;
                   8996:     } else
                   8997:        parnsdone = 0;
                   8998: 
                   8999:     cur = node;
1.1.1.3 ! misho    9000:     if ((cur != NULL) && (cur->type == XML_NAMESPACE_DECL))
        !          9001:        goto internal_error;
        !          9002: 
1.1       misho    9003:     while (cur != NULL) {
                   9004:        /*
                   9005:        * Paranoid source-doc sanity check.
                   9006:        */
                   9007:        if (cur->doc != sourceDoc) {
                   9008:            /*
                   9009:            * We'll assume XIncluded nodes if the doc differs.
                   9010:            * TODO: Do we need to reconciliate XIncluded nodes?
                   9011:            * This here skips XIncluded nodes and tries to handle
                   9012:            * broken sequences.
                   9013:            */
                   9014:            if (cur->next == NULL)
                   9015:                goto leave_node;
                   9016:            do {
                   9017:                cur = cur->next;
                   9018:                if ((cur->type == XML_XINCLUDE_END) ||
                   9019:                    (cur->doc == node->doc))
                   9020:                    break;
                   9021:            } while (cur->next != NULL);
                   9022: 
                   9023:            if (cur->doc != node->doc)
                   9024:                goto leave_node;
                   9025:        }
                   9026:        cur->doc = destDoc;
                   9027:        switch (cur->type) {
                   9028:            case XML_XINCLUDE_START:
                   9029:            case XML_XINCLUDE_END:
                   9030:                /*
                   9031:                * TODO
                   9032:                */
                   9033:                return (-1);
                   9034:            case XML_ELEMENT_NODE:
                   9035:                curElem = cur;
                   9036:                depth++;
                   9037:                /*
                   9038:                * Namespace declarations.
                   9039:                * - ns->href and ns->prefix are never in the dict, so
                   9040:                *   we need not move the values over to the destination dict.
                   9041:                * - Note that for custom handling of ns-references,
                   9042:                *   the ns-decls need not be stored in the ns-map,
                   9043:                *   since they won't be referenced by node->ns.
                   9044:                */
                   9045:                if ((cur->nsDef) &&
                   9046:                    ((ctxt == NULL) || (ctxt->getNsForNodeFunc == NULL)))
                   9047:                {
                   9048:                    if (! parnsdone) {
                   9049:                        /*
                   9050:                        * Gather @parent's in-scope ns-decls.
                   9051:                        */
                   9052:                        if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap,
                   9053:                            destParent) == -1)
                   9054:                            goto internal_error;
                   9055:                        parnsdone = 1;
                   9056:                    }
                   9057:                    for (ns = cur->nsDef; ns != NULL; ns = ns->next) {
                   9058:                        /*
                   9059:                        * NOTE: ns->prefix and ns->href are never in the dict.
                   9060:                        * XML_TREE_ADOPT_STR(ns->prefix)
                   9061:                        * XML_TREE_ADOPT_STR(ns->href)
                   9062:                        */
                   9063:                        /*
                   9064:                        * Does it shadow any ns-decl?
                   9065:                        */
                   9066:                        if (XML_NSMAP_NOTEMPTY(nsMap)) {
                   9067:                            XML_NSMAP_FOREACH(nsMap, mi) {
                   9068:                                if ((mi->depth >= XML_TREE_NSMAP_PARENT) &&
                   9069:                                    (mi->shadowDepth == -1) &&
                   9070:                                    ((ns->prefix == mi->newNs->prefix) ||
                   9071:                                    xmlStrEqual(ns->prefix,
                   9072:                                    mi->newNs->prefix))) {
                   9073: 
                   9074:                                    mi->shadowDepth = depth;
                   9075:                                }
                   9076:                            }
                   9077:                        }
                   9078:                        /*
                   9079:                        * Push mapping.
                   9080:                        */
                   9081:                        if (xmlDOMWrapNsMapAddItem(&nsMap, -1,
                   9082:                            ns, ns, depth) == NULL)
                   9083:                            goto internal_error;
                   9084:                    }
                   9085:                }
                   9086:                /* No break on purpose. */
                   9087:            case XML_ATTRIBUTE_NODE:
                   9088:                /* No namespace, no fun. */
                   9089:                if (cur->ns == NULL)
                   9090:                    goto ns_end;
                   9091: 
                   9092:                if (! parnsdone) {
                   9093:                    if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap,
                   9094:                        destParent) == -1)
                   9095:                        goto internal_error;
                   9096:                    parnsdone = 1;
                   9097:                }
                   9098:                /*
                   9099:                * Adopt ns-references.
                   9100:                */
                   9101:                if (XML_NSMAP_NOTEMPTY(nsMap)) {
                   9102:                    /*
                   9103:                    * Search for a mapping.
                   9104:                    */
                   9105:                    XML_NSMAP_FOREACH(nsMap, mi) {
                   9106:                        if ((mi->shadowDepth == -1) &&
                   9107:                            (cur->ns == mi->oldNs)) {
                   9108: 
                   9109:                            cur->ns = mi->newNs;
                   9110:                            goto ns_end;
                   9111:                        }
                   9112:                    }
                   9113:                }
                   9114:                /*
                   9115:                * No matching namespace in scope. We need a new one.
                   9116:                */
                   9117:                if ((ctxt) && (ctxt->getNsForNodeFunc)) {
                   9118:                    /*
                   9119:                    * User-defined behaviour.
                   9120:                    */
                   9121:                    ns = ctxt->getNsForNodeFunc(ctxt, cur,
                   9122:                        cur->ns->href, cur->ns->prefix);
                   9123:                    /*
                   9124:                    * Insert mapping if ns is available; it's the users fault
                   9125:                    * if not.
                   9126:                    */
                   9127:                    if (xmlDOMWrapNsMapAddItem(&nsMap, -1,
                   9128:                            cur->ns, ns, XML_TREE_NSMAP_CUSTOM) == NULL)
                   9129:                        goto internal_error;
                   9130:                    cur->ns = ns;
                   9131:                } else {
                   9132:                    /*
                   9133:                    * Aquire a normalized ns-decl and add it to the map.
                   9134:                    */
                   9135:                    if (xmlDOMWrapNSNormAquireNormalizedNs(destDoc,
                   9136:                        /* ns-decls on curElem or on destDoc->oldNs */
                   9137:                        destParent ? curElem : NULL,
                   9138:                        cur->ns, &ns,
                   9139:                        &nsMap, depth,
                   9140:                        ancestorsOnly,
                   9141:                        /* ns-decls must be prefixed for attributes. */
                   9142:                        (cur->type == XML_ATTRIBUTE_NODE) ? 1 : 0) == -1)
                   9143:                        goto internal_error;
                   9144:                    cur->ns = ns;
                   9145:                }
                   9146: ns_end:
                   9147:                /*
                   9148:                * Further node properties.
                   9149:                * TODO: Is this all?
                   9150:                */
                   9151:                XML_TREE_ADOPT_STR(cur->name)
                   9152:                if (cur->type == XML_ELEMENT_NODE) {
                   9153:                    cur->psvi = NULL;
                   9154:                    cur->line = 0;
                   9155:                    cur->extra = 0;
                   9156:                    /*
                   9157:                    * Walk attributes.
                   9158:                    */
                   9159:                    if (cur->properties != NULL) {
                   9160:                        /*
                   9161:                        * Process first attribute node.
                   9162:                        */
                   9163:                        cur = (xmlNodePtr) cur->properties;
                   9164:                        continue;
                   9165:                    }
                   9166:                } else {
                   9167:                    /*
                   9168:                    * Attributes.
                   9169:                    */
                   9170:                    if ((sourceDoc != NULL) &&
                   9171:                        (((xmlAttrPtr) cur)->atype == XML_ATTRIBUTE_ID))
                   9172:                    {
                   9173:                        xmlRemoveID(sourceDoc, (xmlAttrPtr) cur);
                   9174:                    }
                   9175:                    ((xmlAttrPtr) cur)->atype = 0;
                   9176:                    ((xmlAttrPtr) cur)->psvi = NULL;
                   9177:                }
                   9178:                break;
                   9179:            case XML_TEXT_NODE:
                   9180:            case XML_CDATA_SECTION_NODE:
                   9181:                /*
                   9182:                * This puts the content in the dest dict, only if
                   9183:                * it was previously in the source dict.
                   9184:                */
                   9185:                XML_TREE_ADOPT_STR_2(cur->content)
                   9186:                goto leave_node;
                   9187:            case XML_ENTITY_REF_NODE:
                   9188:                /*
                   9189:                * Remove reference to the entitity-node.
                   9190:                */
                   9191:                cur->content = NULL;
                   9192:                cur->children = NULL;
                   9193:                cur->last = NULL;
                   9194:                if ((destDoc->intSubset) || (destDoc->extSubset)) {
                   9195:                    xmlEntityPtr ent;
                   9196:                    /*
                   9197:                    * Assign new entity-node if available.
                   9198:                    */
                   9199:                    ent = xmlGetDocEntity(destDoc, cur->name);
                   9200:                    if (ent != NULL) {
                   9201:                        cur->content = ent->content;
                   9202:                        cur->children = (xmlNodePtr) ent;
                   9203:                        cur->last = (xmlNodePtr) ent;
                   9204:                    }
                   9205:                }
                   9206:                goto leave_node;
                   9207:            case XML_PI_NODE:
                   9208:                XML_TREE_ADOPT_STR(cur->name)
                   9209:                XML_TREE_ADOPT_STR_2(cur->content)
                   9210:                break;
                   9211:            case XML_COMMENT_NODE:
                   9212:                break;
                   9213:            default:
                   9214:                goto internal_error;
                   9215:        }
                   9216:        /*
                   9217:        * Walk the tree.
                   9218:        */
                   9219:        if (cur->children != NULL) {
                   9220:            cur = cur->children;
                   9221:            continue;
                   9222:        }
                   9223: 
                   9224: leave_node:
                   9225:        if (cur == node)
                   9226:            break;
                   9227:        if ((cur->type == XML_ELEMENT_NODE) ||
                   9228:            (cur->type == XML_XINCLUDE_START) ||
                   9229:            (cur->type == XML_XINCLUDE_END))
                   9230:        {
                   9231:            /*
                   9232:            * TODO: Do we expect nsDefs on XML_XINCLUDE_START?
                   9233:            */
                   9234:            if (XML_NSMAP_NOTEMPTY(nsMap)) {
                   9235:                /*
                   9236:                * Pop mappings.
                   9237:                */
                   9238:                while ((nsMap->last != NULL) &&
                   9239:                    (nsMap->last->depth >= depth))
                   9240:                {
                   9241:                    XML_NSMAP_POP(nsMap, mi)
                   9242:                }
                   9243:                /*
                   9244:                * Unshadow.
                   9245:                */
                   9246:                XML_NSMAP_FOREACH(nsMap, mi) {
                   9247:                    if (mi->shadowDepth >= depth)
                   9248:                        mi->shadowDepth = -1;
                   9249:                }
                   9250:            }
                   9251:            depth--;
                   9252:        }
                   9253:        if (cur->next != NULL)
                   9254:            cur = cur->next;
                   9255:        else if ((cur->type == XML_ATTRIBUTE_NODE) &&
                   9256:            (cur->parent->children != NULL))
                   9257:        {
                   9258:            cur = cur->parent->children;
                   9259:        } else {
                   9260:            cur = cur->parent;
                   9261:            goto leave_node;
                   9262:        }
                   9263:     }
                   9264: 
                   9265:     goto exit;
                   9266: 
                   9267: internal_error:
                   9268:     ret = -1;
                   9269: 
                   9270: exit:
                   9271:     /*
                   9272:     * Cleanup.
                   9273:     */
                   9274:     if (nsMap != NULL) {
                   9275:        if ((ctxt) && (ctxt->namespaceMap == nsMap)) {
                   9276:            /*
                   9277:            * Just cleanup the map but don't free.
                   9278:            */
                   9279:            if (nsMap->first) {
                   9280:                if (nsMap->pool)
                   9281:                    nsMap->last->next = nsMap->pool;
                   9282:                nsMap->pool = nsMap->first;
                   9283:                nsMap->first = NULL;
                   9284:            }
                   9285:        } else
                   9286:            xmlDOMWrapNsMapFree(nsMap);
                   9287:     }
                   9288:     return(ret);
                   9289: }
                   9290: 
                   9291: /*
                   9292: * xmlDOMWrapCloneNode:
                   9293: * @ctxt: the optional context for custom processing
                   9294: * @sourceDoc: the optional sourceDoc
                   9295: * @node: the node to start with
                   9296: * @resNode: the clone of the given @node
                   9297: * @destDoc: the destination doc
                   9298: * @destParent: the optional new parent of @node in @destDoc
                   9299: * @deep: descend into child if set
                   9300: * @options: option flags
                   9301: *
                   9302: * References of out-of scope ns-decls are remapped to point to @destDoc:
                   9303: * 1) If @destParent is given, then nsDef entries on element-nodes are used
                   9304: * 2) If *no* @destParent is given, then @destDoc->oldNs entries are used.
                   9305: *    This is the case when you don't know already where the cloned branch
                   9306: *    will be added to.
                   9307: *
                   9308: * If @destParent is given, it ensures that the tree is namespace
                   9309: * wellformed by creating additional ns-decls where needed.
                   9310: * Note that, since prefixes of already existent ns-decls can be
                   9311: * shadowed by this process, it could break QNames in attribute
                   9312: * values or element content.
                   9313: * TODO:
                   9314: *   1) What to do with XInclude? Currently this returns an error for XInclude.
                   9315: *
                   9316: * Returns 0 if the operation succeeded,
                   9317: *         1 if a node of unsupported (or not yet supported) type was given,
                   9318: *         -1 on API/internal errors.
                   9319: */
                   9320: 
                   9321: int
                   9322: xmlDOMWrapCloneNode(xmlDOMWrapCtxtPtr ctxt,
                   9323:                      xmlDocPtr sourceDoc,
                   9324:                      xmlNodePtr node,
                   9325:                      xmlNodePtr *resNode,
                   9326:                      xmlDocPtr destDoc,
                   9327:                      xmlNodePtr destParent,
                   9328:                      int deep,
                   9329:                      int options ATTRIBUTE_UNUSED)
                   9330: {
                   9331:     int ret = 0;
                   9332:     xmlNodePtr cur, curElem = NULL;
                   9333:     xmlNsMapPtr nsMap = NULL;
                   9334:     xmlNsMapItemPtr mi;
                   9335:     xmlNsPtr ns;
                   9336:     int depth = -1;
                   9337:     /* int adoptStr = 1; */
                   9338:     /* gather @parent's ns-decls. */
                   9339:     int parnsdone = 0;
                   9340:     /*
                   9341:     * @ancestorsOnly:
                   9342:     * TODO: @ancestorsOnly should be set per option.
                   9343:     *
                   9344:     */
                   9345:     int ancestorsOnly = 0;
                   9346:     xmlNodePtr resultClone = NULL, clone = NULL, parentClone = NULL, prevClone = NULL;
                   9347:     xmlNsPtr cloneNs = NULL, *cloneNsDefSlot = NULL;
                   9348:     xmlDictPtr dict; /* The destination dict */
                   9349: 
                   9350:     if ((node == NULL) || (resNode == NULL) || (destDoc == NULL))
                   9351:        return(-1);
                   9352:     /*
                   9353:     * TODO: Initially we support only element-nodes.
                   9354:     */
                   9355:     if (node->type != XML_ELEMENT_NODE)
                   9356:        return(1);
                   9357:     /*
                   9358:     * Check node->doc sanity.
                   9359:     */
                   9360:     if ((node->doc != NULL) && (sourceDoc != NULL) &&
                   9361:        (node->doc != sourceDoc)) {
                   9362:        /*
                   9363:        * Might be an XIncluded node.
                   9364:        */
                   9365:        return (-1);
                   9366:     }
                   9367:     if (sourceDoc == NULL)
                   9368:        sourceDoc = node->doc;
                   9369:     if (sourceDoc == NULL)
                   9370:         return (-1);
                   9371: 
                   9372:     dict = destDoc->dict;
                   9373:     /*
                   9374:     * Reuse the namespace map of the context.
                   9375:     */
                   9376:     if (ctxt)
                   9377:        nsMap = (xmlNsMapPtr) ctxt->namespaceMap;
                   9378: 
                   9379:     *resNode = NULL;
                   9380: 
                   9381:     cur = node;
1.1.1.3 ! misho    9382:     if ((cur != NULL) && (cur->type == XML_NAMESPACE_DECL))
        !          9383:         return(-1);
        !          9384: 
1.1       misho    9385:     while (cur != NULL) {
                   9386:        if (cur->doc != sourceDoc) {
                   9387:            /*
                   9388:            * We'll assume XIncluded nodes if the doc differs.
                   9389:            * TODO: Do we need to reconciliate XIncluded nodes?
                   9390:            * TODO: This here returns -1 in this case.
                   9391:            */
                   9392:            goto internal_error;
                   9393:        }
                   9394:        /*
                   9395:        * Create a new node.
                   9396:        */
                   9397:        switch (cur->type) {
                   9398:            case XML_XINCLUDE_START:
                   9399:            case XML_XINCLUDE_END:
                   9400:                /*
                   9401:                * TODO: What to do with XInclude?
                   9402:                */
                   9403:                goto internal_error;
                   9404:                break;
                   9405:            case XML_ELEMENT_NODE:
                   9406:            case XML_TEXT_NODE:
                   9407:            case XML_CDATA_SECTION_NODE:
                   9408:            case XML_COMMENT_NODE:
                   9409:            case XML_PI_NODE:
                   9410:            case XML_DOCUMENT_FRAG_NODE:
                   9411:            case XML_ENTITY_REF_NODE:
                   9412:            case XML_ENTITY_NODE:
                   9413:                /*
                   9414:                * Nodes of xmlNode structure.
                   9415:                */
                   9416:                clone = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
                   9417:                if (clone == NULL) {
                   9418:                    xmlTreeErrMemory("xmlDOMWrapCloneNode(): allocating a node");
                   9419:                    goto internal_error;
                   9420:                }
                   9421:                memset(clone, 0, sizeof(xmlNode));
                   9422:                /*
                   9423:                * Set hierachical links.
                   9424:                */
                   9425:                if (resultClone != NULL) {
                   9426:                    clone->parent = parentClone;
                   9427:                    if (prevClone) {
                   9428:                        prevClone->next = clone;
                   9429:                        clone->prev = prevClone;
                   9430:                    } else
                   9431:                        parentClone->children = clone;
                   9432:                } else
                   9433:                    resultClone = clone;
                   9434: 
                   9435:                break;
                   9436:            case XML_ATTRIBUTE_NODE:
                   9437:                /*
                   9438:                * Attributes (xmlAttr).
                   9439:                */
                   9440:                clone = (xmlNodePtr) xmlMalloc(sizeof(xmlAttr));
                   9441:                if (clone == NULL) {
                   9442:                    xmlTreeErrMemory("xmlDOMWrapCloneNode(): allocating an attr-node");
                   9443:                    goto internal_error;
                   9444:                }
                   9445:                memset(clone, 0, sizeof(xmlAttr));
                   9446:                /*
                   9447:                * Set hierachical links.
                   9448:                * TODO: Change this to add to the end of attributes.
                   9449:                */
                   9450:                if (resultClone != NULL) {
                   9451:                    clone->parent = parentClone;
                   9452:                    if (prevClone) {
                   9453:                        prevClone->next = clone;
                   9454:                        clone->prev = prevClone;
                   9455:                    } else
                   9456:                        parentClone->properties = (xmlAttrPtr) clone;
                   9457:                } else
                   9458:                    resultClone = clone;
                   9459:                break;
                   9460:            default:
                   9461:                /*
                   9462:                * TODO QUESTION: Any other nodes expected?
                   9463:                */
                   9464:                goto internal_error;
                   9465:        }
                   9466: 
                   9467:        clone->type = cur->type;
                   9468:        clone->doc = destDoc;
                   9469: 
                   9470:        /*
                   9471:        * Clone the name of the node if any.
                   9472:        */
                   9473:        if (cur->name == xmlStringText)
                   9474:            clone->name = xmlStringText;
                   9475:        else if (cur->name == xmlStringTextNoenc)
                   9476:            /*
                   9477:            * NOTE: Although xmlStringTextNoenc is never assigned to a node
                   9478:            *   in tree.c, it might be set in Libxslt via
                   9479:            *   "xsl:disable-output-escaping".
                   9480:            */
                   9481:            clone->name = xmlStringTextNoenc;
                   9482:        else if (cur->name == xmlStringComment)
                   9483:            clone->name = xmlStringComment;
                   9484:        else if (cur->name != NULL) {
                   9485:            DICT_CONST_COPY(cur->name, clone->name);
                   9486:        }
                   9487: 
                   9488:        switch (cur->type) {
                   9489:            case XML_XINCLUDE_START:
                   9490:            case XML_XINCLUDE_END:
                   9491:                /*
                   9492:                * TODO
                   9493:                */
                   9494:                return (-1);
                   9495:            case XML_ELEMENT_NODE:
                   9496:                curElem = cur;
                   9497:                depth++;
                   9498:                /*
                   9499:                * Namespace declarations.
                   9500:                */
                   9501:                if (cur->nsDef != NULL) {
                   9502:                    if (! parnsdone) {
                   9503:                        if (destParent && (ctxt == NULL)) {
                   9504:                            /*
                   9505:                            * Gather @parent's in-scope ns-decls.
                   9506:                            */
                   9507:                            if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap,
                   9508:                                destParent) == -1)
                   9509:                                goto internal_error;
                   9510:                        }
                   9511:                        parnsdone = 1;
                   9512:                    }
                   9513:                    /*
                   9514:                    * Clone namespace declarations.
                   9515:                    */
                   9516:                    cloneNsDefSlot = &(clone->nsDef);
                   9517:                    for (ns = cur->nsDef; ns != NULL; ns = ns->next) {
                   9518:                        /*
                   9519:                        * Create a new xmlNs.
                   9520:                        */
                   9521:                        cloneNs = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
                   9522:                        if (cloneNs == NULL) {
                   9523:                            xmlTreeErrMemory("xmlDOMWrapCloneNode(): "
                   9524:                                "allocating namespace");
                   9525:                            return(-1);
                   9526:                        }
                   9527:                        memset(cloneNs, 0, sizeof(xmlNs));
                   9528:                        cloneNs->type = XML_LOCAL_NAMESPACE;
                   9529: 
                   9530:                        if (ns->href != NULL)
                   9531:                            cloneNs->href = xmlStrdup(ns->href);
                   9532:                        if (ns->prefix != NULL)
                   9533:                            cloneNs->prefix = xmlStrdup(ns->prefix);
                   9534: 
                   9535:                        *cloneNsDefSlot = cloneNs;
                   9536:                        cloneNsDefSlot = &(cloneNs->next);
                   9537: 
                   9538:                        /*
                   9539:                        * Note that for custom handling of ns-references,
                   9540:                        * the ns-decls need not be stored in the ns-map,
                   9541:                        * since they won't be referenced by node->ns.
                   9542:                        */
                   9543:                        if ((ctxt == NULL) ||
                   9544:                            (ctxt->getNsForNodeFunc == NULL))
                   9545:                        {
                   9546:                            /*
                   9547:                            * Does it shadow any ns-decl?
                   9548:                            */
                   9549:                            if (XML_NSMAP_NOTEMPTY(nsMap)) {
                   9550:                                XML_NSMAP_FOREACH(nsMap, mi) {
                   9551:                                    if ((mi->depth >= XML_TREE_NSMAP_PARENT) &&
                   9552:                                        (mi->shadowDepth == -1) &&
                   9553:                                        ((ns->prefix == mi->newNs->prefix) ||
                   9554:                                        xmlStrEqual(ns->prefix,
                   9555:                                        mi->newNs->prefix))) {
                   9556:                                        /*
                   9557:                                        * Mark as shadowed at the current
                   9558:                                        * depth.
                   9559:                                        */
                   9560:                                        mi->shadowDepth = depth;
                   9561:                                    }
                   9562:                                }
                   9563:                            }
                   9564:                            /*
                   9565:                            * Push mapping.
                   9566:                            */
                   9567:                            if (xmlDOMWrapNsMapAddItem(&nsMap, -1,
                   9568:                                ns, cloneNs, depth) == NULL)
                   9569:                                goto internal_error;
                   9570:                        }
                   9571:                    }
                   9572:                }
                   9573:                /* cur->ns will be processed further down. */
                   9574:                break;
                   9575:            case XML_ATTRIBUTE_NODE:
                   9576:                /* IDs will be processed further down. */
                   9577:                /* cur->ns will be processed further down. */
                   9578:                break;
                   9579:            case XML_TEXT_NODE:
                   9580:            case XML_CDATA_SECTION_NODE:
                   9581:                /*
                   9582:                * Note that this will also cover the values of attributes.
                   9583:                */
                   9584:                DICT_COPY(cur->content, clone->content);
                   9585:                goto leave_node;
                   9586:            case XML_ENTITY_NODE:
                   9587:                /* TODO: What to do here? */
                   9588:                goto leave_node;
                   9589:            case XML_ENTITY_REF_NODE:
                   9590:                if (sourceDoc != destDoc) {
                   9591:                    if ((destDoc->intSubset) || (destDoc->extSubset)) {
                   9592:                        xmlEntityPtr ent;
                   9593:                        /*
                   9594:                        * Different doc: Assign new entity-node if available.
                   9595:                        */
                   9596:                        ent = xmlGetDocEntity(destDoc, cur->name);
                   9597:                        if (ent != NULL) {
                   9598:                            clone->content = ent->content;
                   9599:                            clone->children = (xmlNodePtr) ent;
                   9600:                            clone->last = (xmlNodePtr) ent;
                   9601:                        }
                   9602:                    }
                   9603:                } else {
                   9604:                    /*
                   9605:                    * Same doc: Use the current node's entity declaration
                   9606:                    * and value.
                   9607:                    */
                   9608:                    clone->content = cur->content;
                   9609:                    clone->children = cur->children;
                   9610:                    clone->last = cur->last;
                   9611:                }
                   9612:                goto leave_node;
                   9613:            case XML_PI_NODE:
                   9614:                DICT_COPY(cur->content, clone->content);
                   9615:                goto leave_node;
                   9616:            case XML_COMMENT_NODE:
                   9617:                DICT_COPY(cur->content, clone->content);
                   9618:                goto leave_node;
                   9619:            default:
                   9620:                goto internal_error;
                   9621:        }
                   9622: 
                   9623:        if (cur->ns == NULL)
                   9624:            goto end_ns_reference;
                   9625: 
                   9626: /* handle_ns_reference: */
                   9627:        /*
                   9628:        ** The following will take care of references to ns-decls ********
                   9629:        ** and is intended only for element- and attribute-nodes.
                   9630:        **
                   9631:        */
                   9632:        if (! parnsdone) {
                   9633:            if (destParent && (ctxt == NULL)) {
                   9634:                if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap, destParent) == -1)
                   9635:                    goto internal_error;
                   9636:            }
                   9637:            parnsdone = 1;
                   9638:        }
                   9639:        /*
                   9640:        * Adopt ns-references.
                   9641:        */
                   9642:        if (XML_NSMAP_NOTEMPTY(nsMap)) {
                   9643:            /*
                   9644:            * Search for a mapping.
                   9645:            */
                   9646:            XML_NSMAP_FOREACH(nsMap, mi) {
                   9647:                if ((mi->shadowDepth == -1) &&
                   9648:                    (cur->ns == mi->oldNs)) {
                   9649:                    /*
                   9650:                    * This is the nice case: a mapping was found.
                   9651:                    */
                   9652:                    clone->ns = mi->newNs;
                   9653:                    goto end_ns_reference;
                   9654:                }
                   9655:            }
                   9656:        }
                   9657:        /*
                   9658:        * No matching namespace in scope. We need a new one.
                   9659:        */
                   9660:        if ((ctxt != NULL) && (ctxt->getNsForNodeFunc != NULL)) {
                   9661:            /*
                   9662:            * User-defined behaviour.
                   9663:            */
                   9664:            ns = ctxt->getNsForNodeFunc(ctxt, cur,
                   9665:                cur->ns->href, cur->ns->prefix);
                   9666:            /*
                   9667:            * Add user's mapping.
                   9668:            */
                   9669:            if (xmlDOMWrapNsMapAddItem(&nsMap, -1,
                   9670:                cur->ns, ns, XML_TREE_NSMAP_CUSTOM) == NULL)
                   9671:                goto internal_error;
                   9672:            clone->ns = ns;
                   9673:        } else {
                   9674:            /*
                   9675:            * Aquire a normalized ns-decl and add it to the map.
                   9676:            */
                   9677:            if (xmlDOMWrapNSNormAquireNormalizedNs(destDoc,
                   9678:                /* ns-decls on curElem or on destDoc->oldNs */
                   9679:                destParent ? curElem : NULL,
                   9680:                cur->ns, &ns,
                   9681:                &nsMap, depth,
                   9682:                /* if we need to search only in the ancestor-axis */
                   9683:                ancestorsOnly,
                   9684:                /* ns-decls must be prefixed for attributes. */
                   9685:                (cur->type == XML_ATTRIBUTE_NODE) ? 1 : 0) == -1)
                   9686:                goto internal_error;
                   9687:            clone->ns = ns;
                   9688:        }
                   9689: 
                   9690: end_ns_reference:
                   9691: 
                   9692:        /*
                   9693:        * Some post-processing.
                   9694:        *
                   9695:        * Handle ID attributes.
                   9696:        */
                   9697:        if ((clone->type == XML_ATTRIBUTE_NODE) &&
                   9698:            (clone->parent != NULL))
                   9699:        {
                   9700:            if (xmlIsID(destDoc, clone->parent, (xmlAttrPtr) clone)) {
                   9701: 
                   9702:                xmlChar *idVal;
                   9703: 
                   9704:                idVal = xmlNodeListGetString(cur->doc, cur->children, 1);
                   9705:                if (idVal != NULL) {
                   9706:                    if (xmlAddID(NULL, destDoc, idVal, (xmlAttrPtr) cur) == NULL) {
                   9707:                        /* TODO: error message. */
                   9708:                        xmlFree(idVal);
                   9709:                        goto internal_error;
                   9710:                    }
                   9711:                    xmlFree(idVal);
                   9712:                }
                   9713:            }
                   9714:        }
                   9715:        /*
                   9716:        **
                   9717:        ** The following will traverse the tree **************************
                   9718:        **
                   9719:        *
                   9720:        * Walk the element's attributes before descending into child-nodes.
                   9721:        */
                   9722:        if ((cur->type == XML_ELEMENT_NODE) && (cur->properties != NULL)) {
                   9723:            prevClone = NULL;
                   9724:            parentClone = clone;
                   9725:            cur = (xmlNodePtr) cur->properties;
                   9726:            continue;
                   9727:        }
                   9728: into_content:
                   9729:        /*
                   9730:        * Descend into child-nodes.
                   9731:        */
                   9732:        if (cur->children != NULL) {
                   9733:            if (deep || (cur->type == XML_ATTRIBUTE_NODE)) {
                   9734:                prevClone = NULL;
                   9735:                parentClone = clone;
                   9736:                cur = cur->children;
                   9737:                continue;
                   9738:            }
                   9739:        }
                   9740: 
                   9741: leave_node:
                   9742:        /*
                   9743:        * At this point we are done with the node, its content
                   9744:        * and an element-nodes's attribute-nodes.
                   9745:        */
                   9746:        if (cur == node)
                   9747:            break;
                   9748:        if ((cur->type == XML_ELEMENT_NODE) ||
                   9749:            (cur->type == XML_XINCLUDE_START) ||
                   9750:            (cur->type == XML_XINCLUDE_END)) {
                   9751:            /*
                   9752:            * TODO: Do we expect nsDefs on XML_XINCLUDE_START?
                   9753:            */
                   9754:            if (XML_NSMAP_NOTEMPTY(nsMap)) {
                   9755:                /*
                   9756:                * Pop mappings.
                   9757:                */
                   9758:                while ((nsMap->last != NULL) &&
                   9759:                    (nsMap->last->depth >= depth))
                   9760:                {
                   9761:                    XML_NSMAP_POP(nsMap, mi)
                   9762:                }
                   9763:                /*
                   9764:                * Unshadow.
                   9765:                */
                   9766:                XML_NSMAP_FOREACH(nsMap, mi) {
                   9767:                    if (mi->shadowDepth >= depth)
                   9768:                        mi->shadowDepth = -1;
                   9769:                }
                   9770:            }
                   9771:            depth--;
                   9772:        }
                   9773:        if (cur->next != NULL) {
                   9774:            prevClone = clone;
                   9775:            cur = cur->next;
                   9776:        } else if (cur->type != XML_ATTRIBUTE_NODE) {
                   9777:            /*
                   9778:            * Set clone->last.
                   9779:            */
                   9780:            if (clone->parent != NULL)
                   9781:                clone->parent->last = clone;
                   9782:            clone = clone->parent;
                   9783:            parentClone = clone->parent;
                   9784:            /*
                   9785:            * Process parent --> next;
                   9786:            */
                   9787:            cur = cur->parent;
                   9788:            goto leave_node;
                   9789:        } else {
                   9790:            /* This is for attributes only. */
                   9791:            clone = clone->parent;
                   9792:            parentClone = clone->parent;
                   9793:            /*
                   9794:            * Process parent-element --> children.
                   9795:            */
                   9796:            cur = cur->parent;
                   9797:            goto into_content;
                   9798:        }
                   9799:     }
                   9800:     goto exit;
                   9801: 
                   9802: internal_error:
                   9803:     ret = -1;
                   9804: 
                   9805: exit:
                   9806:     /*
                   9807:     * Cleanup.
                   9808:     */
                   9809:     if (nsMap != NULL) {
                   9810:        if ((ctxt) && (ctxt->namespaceMap == nsMap)) {
                   9811:            /*
                   9812:            * Just cleanup the map but don't free.
                   9813:            */
                   9814:            if (nsMap->first) {
                   9815:                if (nsMap->pool)
                   9816:                    nsMap->last->next = nsMap->pool;
                   9817:                nsMap->pool = nsMap->first;
                   9818:                nsMap->first = NULL;
                   9819:            }
                   9820:        } else
                   9821:            xmlDOMWrapNsMapFree(nsMap);
                   9822:     }
                   9823:     /*
                   9824:     * TODO: Should we try a cleanup of the cloned node in case of a
                   9825:     * fatal error?
                   9826:     */
                   9827:     *resNode = resultClone;
                   9828:     return (ret);
                   9829: }
                   9830: 
                   9831: /*
                   9832: * xmlDOMWrapAdoptAttr:
                   9833: * @ctxt: the optional context for custom processing
                   9834: * @sourceDoc: the optional source document of attr
                   9835: * @attr: the attribute-node to be adopted
                   9836: * @destDoc: the destination doc for adoption
                   9837: * @destParent: the optional new parent of @attr in @destDoc
                   9838: * @options: option flags
                   9839: *
                   9840: * @attr is adopted by @destDoc.
                   9841: * Ensures that ns-references point to @destDoc: either to
                   9842: * elements->nsDef entries if @destParent is given, or to
                   9843: * @destDoc->oldNs otherwise.
                   9844: *
                   9845: * Returns 0 if succeeded, -1 otherwise and on API/internal errors.
                   9846: */
                   9847: static int
                   9848: xmlDOMWrapAdoptAttr(xmlDOMWrapCtxtPtr ctxt,
                   9849:                    xmlDocPtr sourceDoc,
                   9850:                    xmlAttrPtr attr,
                   9851:                    xmlDocPtr destDoc,
                   9852:                    xmlNodePtr destParent,
                   9853:                    int options ATTRIBUTE_UNUSED)
                   9854: {
                   9855:     xmlNodePtr cur;
                   9856:     int adoptStr = 1;
                   9857: 
                   9858:     if ((attr == NULL) || (destDoc == NULL))
                   9859:        return (-1);
                   9860: 
                   9861:     attr->doc = destDoc;
                   9862:     if (attr->ns != NULL) {
                   9863:        xmlNsPtr ns = NULL;
                   9864: 
                   9865:        if (ctxt != NULL) {
                   9866:            /* TODO: User defined. */
                   9867:        }
                   9868:        /* XML Namespace. */
                   9869:        if (IS_STR_XML(attr->ns->prefix)) {
                   9870:            ns = xmlTreeEnsureXMLDecl(destDoc);
                   9871:        } else if (destParent == NULL) {
                   9872:            /*
                   9873:            * Store in @destDoc->oldNs.
                   9874:            */
                   9875:            ns = xmlDOMWrapStoreNs(destDoc, attr->ns->href, attr->ns->prefix);
                   9876:        } else {
                   9877:            /*
                   9878:            * Declare on @destParent.
                   9879:            */
                   9880:            if (xmlSearchNsByNamespaceStrict(destDoc, destParent, attr->ns->href,
                   9881:                &ns, 1) == -1)
                   9882:                goto internal_error;
                   9883:            if (ns == NULL) {
                   9884:                ns = xmlDOMWrapNSNormDeclareNsForced(destDoc, destParent,
                   9885:                    attr->ns->href, attr->ns->prefix, 1);
                   9886:            }
                   9887:        }
                   9888:        if (ns == NULL)
                   9889:            goto internal_error;
                   9890:        attr->ns = ns;
                   9891:     }
                   9892: 
                   9893:     XML_TREE_ADOPT_STR(attr->name);
                   9894:     attr->atype = 0;
                   9895:     attr->psvi = NULL;
                   9896:     /*
                   9897:     * Walk content.
                   9898:     */
                   9899:     if (attr->children == NULL)
                   9900:        return (0);
                   9901:     cur = attr->children;
1.1.1.3 ! misho    9902:     if ((cur != NULL) && (cur->type == XML_NAMESPACE_DECL))
        !          9903:         goto internal_error;
1.1       misho    9904:     while (cur != NULL) {
                   9905:        cur->doc = destDoc;
                   9906:        switch (cur->type) {
                   9907:            case XML_TEXT_NODE:
                   9908:            case XML_CDATA_SECTION_NODE:
                   9909:                XML_TREE_ADOPT_STR_2(cur->content)
                   9910:                break;
                   9911:            case XML_ENTITY_REF_NODE:
                   9912:                /*
                   9913:                * Remove reference to the entitity-node.
                   9914:                */
                   9915:                cur->content = NULL;
                   9916:                cur->children = NULL;
                   9917:                cur->last = NULL;
                   9918:                if ((destDoc->intSubset) || (destDoc->extSubset)) {
                   9919:                    xmlEntityPtr ent;
                   9920:                    /*
                   9921:                    * Assign new entity-node if available.
                   9922:                    */
                   9923:                    ent = xmlGetDocEntity(destDoc, cur->name);
                   9924:                    if (ent != NULL) {
                   9925:                        cur->content = ent->content;
                   9926:                        cur->children = (xmlNodePtr) ent;
                   9927:                        cur->last = (xmlNodePtr) ent;
                   9928:                    }
                   9929:                }
                   9930:                break;
                   9931:            default:
                   9932:                break;
                   9933:        }
                   9934:        if (cur->children != NULL) {
                   9935:            cur = cur->children;
                   9936:            continue;
                   9937:        }
                   9938: next_sibling:
                   9939:        if (cur == (xmlNodePtr) attr)
                   9940:            break;
                   9941:        if (cur->next != NULL)
                   9942:            cur = cur->next;
                   9943:        else {
                   9944:            cur = cur->parent;
                   9945:            goto next_sibling;
                   9946:        }
                   9947:     }
                   9948:     return (0);
                   9949: internal_error:
                   9950:     return (-1);
                   9951: }
                   9952: 
                   9953: /*
                   9954: * xmlDOMWrapAdoptNode:
                   9955: * @ctxt: the optional context for custom processing
                   9956: * @sourceDoc: the optional sourceDoc
                   9957: * @node: the node to start with
                   9958: * @destDoc: the destination doc
                   9959: * @destParent: the optional new parent of @node in @destDoc
                   9960: * @options: option flags
                   9961: *
                   9962: * References of out-of scope ns-decls are remapped to point to @destDoc:
                   9963: * 1) If @destParent is given, then nsDef entries on element-nodes are used
                   9964: * 2) If *no* @destParent is given, then @destDoc->oldNs entries are used
                   9965: *    This is the case when you have an unliked node and just want to move it
                   9966: *    to the context of
                   9967: *
                   9968: * If @destParent is given, it ensures that the tree is namespace
                   9969: * wellformed by creating additional ns-decls where needed.
                   9970: * Note that, since prefixes of already existent ns-decls can be
                   9971: * shadowed by this process, it could break QNames in attribute
                   9972: * values or element content.
                   9973: * NOTE: This function was not intensively tested.
                   9974: *
                   9975: * Returns 0 if the operation succeeded,
                   9976: *         1 if a node of unsupported type was given,
                   9977: *         2 if a node of not yet supported type was given and
                   9978: *         -1 on API/internal errors.
                   9979: */
                   9980: int
                   9981: xmlDOMWrapAdoptNode(xmlDOMWrapCtxtPtr ctxt,
                   9982:                    xmlDocPtr sourceDoc,
                   9983:                    xmlNodePtr node,
                   9984:                    xmlDocPtr destDoc,
                   9985:                    xmlNodePtr destParent,
                   9986:                    int options)
                   9987: {
1.1.1.3 ! misho    9988:     if ((node == NULL) || (node->type == XML_NAMESPACE_DECL) ||
        !          9989:         (destDoc == NULL) ||
1.1       misho    9990:        ((destParent != NULL) && (destParent->doc != destDoc)))
                   9991:        return(-1);
                   9992:     /*
                   9993:     * Check node->doc sanity.
                   9994:     */
                   9995:     if ((node->doc != NULL) && (sourceDoc != NULL) &&
                   9996:        (node->doc != sourceDoc)) {
                   9997:        /*
                   9998:        * Might be an XIncluded node.
                   9999:        */
                   10000:        return (-1);
                   10001:     }
                   10002:     if (sourceDoc == NULL)
                   10003:        sourceDoc = node->doc;
                   10004:     if (sourceDoc == destDoc)
                   10005:        return (-1);
                   10006:     switch (node->type) {
                   10007:        case XML_ELEMENT_NODE:
                   10008:        case XML_ATTRIBUTE_NODE:
                   10009:        case XML_TEXT_NODE:
                   10010:        case XML_CDATA_SECTION_NODE:
                   10011:        case XML_ENTITY_REF_NODE:
                   10012:        case XML_PI_NODE:
                   10013:        case XML_COMMENT_NODE:
                   10014:            break;
                   10015:        case XML_DOCUMENT_FRAG_NODE:
                   10016:            /* TODO: Support document-fragment-nodes. */
                   10017:            return (2);
                   10018:        default:
                   10019:            return (1);
                   10020:     }
                   10021:     /*
                   10022:     * Unlink only if @node was not already added to @destParent.
                   10023:     */
                   10024:     if ((node->parent != NULL) && (destParent != node->parent))
                   10025:        xmlUnlinkNode(node);
                   10026: 
                   10027:     if (node->type == XML_ELEMENT_NODE) {
                   10028:            return (xmlDOMWrapAdoptBranch(ctxt, sourceDoc, node,
                   10029:                    destDoc, destParent, options));
                   10030:     } else if (node->type == XML_ATTRIBUTE_NODE) {
                   10031:            return (xmlDOMWrapAdoptAttr(ctxt, sourceDoc,
                   10032:                (xmlAttrPtr) node, destDoc, destParent, options));
                   10033:     } else {
                   10034:        xmlNodePtr cur = node;
                   10035:        int adoptStr = 1;
                   10036: 
                   10037:        cur->doc = destDoc;
                   10038:        /*
                   10039:        * Optimize string adoption.
                   10040:        */
                   10041:        if ((sourceDoc != NULL) &&
                   10042:            (sourceDoc->dict == destDoc->dict))
                   10043:                adoptStr = 0;
                   10044:        switch (node->type) {
                   10045:            case XML_TEXT_NODE:
                   10046:            case XML_CDATA_SECTION_NODE:
                   10047:                XML_TREE_ADOPT_STR_2(node->content)
                   10048:                    break;
                   10049:            case XML_ENTITY_REF_NODE:
                   10050:                /*
                   10051:                * Remove reference to the entitity-node.
                   10052:                */
                   10053:                node->content = NULL;
                   10054:                node->children = NULL;
                   10055:                node->last = NULL;
                   10056:                if ((destDoc->intSubset) || (destDoc->extSubset)) {
                   10057:                    xmlEntityPtr ent;
                   10058:                    /*
                   10059:                    * Assign new entity-node if available.
                   10060:                    */
                   10061:                    ent = xmlGetDocEntity(destDoc, node->name);
                   10062:                    if (ent != NULL) {
                   10063:                        node->content = ent->content;
                   10064:                        node->children = (xmlNodePtr) ent;
                   10065:                        node->last = (xmlNodePtr) ent;
                   10066:                    }
                   10067:                }
                   10068:                XML_TREE_ADOPT_STR(node->name)
                   10069:                break;
                   10070:            case XML_PI_NODE: {
                   10071:                XML_TREE_ADOPT_STR(node->name)
                   10072:                XML_TREE_ADOPT_STR_2(node->content)
                   10073:                break;
                   10074:            }
                   10075:            default:
                   10076:                break;
                   10077:        }
                   10078:     }
                   10079:     return (0);
                   10080: }
                   10081: 
                   10082: #define bottom_tree
                   10083: #include "elfgcchack.h"

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>