File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / libxml2 / tree.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Mon Jul 22 01:22:19 2013 UTC (11 years, 2 months ago) by misho
Branches: libxml2, MAIN
CVS tags: v2_8_0p0, v2_8_0, HEAD
2.8.0

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

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