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

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

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