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

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

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