File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / libxml2 / tree.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 23:37:57 2012 UTC (12 years, 4 months ago) by misho
Branches: libxml2, MAIN
CVS tags: v2_7_8, HEAD
libxml2

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

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