Annotation of embedaddon/libxml2/tree.c, revision 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>