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