ReactOS 0.4.15-dev-7842-g558ab78
tree.c
Go to the documentation of this file.
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/* To avoid EBCDIC trouble when parsing on zOS */
14#if defined(__MVS__)
15#pragma convert("ISO8859-1")
16#endif
17
18#define IN_LIBXML
19#include "libxml.h"
20
21#include <string.h> /* for memset() only ! */
22#include <stddef.h>
23#include <limits.h>
24#include <ctype.h>
25#include <stdlib.h>
26
27#ifdef LIBXML_ZLIB_ENABLED
28#include <zlib.h>
29#endif
30
31#include <libxml/xmlmemory.h>
32#include <libxml/tree.h>
33#include <libxml/parser.h>
34#include <libxml/uri.h>
35#include <libxml/entities.h>
36#include <libxml/valid.h>
37#include <libxml/xmlerror.h>
39#include <libxml/globals.h>
40#ifdef LIBXML_HTML_ENABLED
41#include <libxml/HTMLtree.h>
42#endif
43#ifdef LIBXML_DEBUG_ENABLED
44#include <libxml/debugXML.h>
45#endif
46
47#include "buf.h"
48#include "save.h"
49
51
52/************************************************************************
53 * *
54 * Forward declarations *
55 * *
56 ************************************************************************/
57
58static xmlNsPtr
60
62
63/************************************************************************
64 * *
65 * Tree memory error handler *
66 * *
67 ************************************************************************/
74static void
76{
77 __xmlSimpleError(XML_FROM_TREE, XML_ERR_NO_MEMORY, NULL, NULL, extra);
78}
79
87static void
88xmlTreeErr(int code, xmlNodePtr node, const char *extra)
89{
90 const char *msg = NULL;
91
92 switch(code) {
94 msg = "invalid hexadecimal character value\n";
95 break;
97 msg = "invalid decimal character value\n";
98 break;
100 msg = "unterminated entity reference %15s\n";
101 break;
103 msg = "string is not in UTF-8\n";
104 break;
105 default:
106 msg = "unexpected error number\n";
107 }
108 __xmlSimpleError(XML_FROM_TREE, code, node, msg, extra);
109}
110
111/************************************************************************
112 * *
113 * A few static variables and macros *
114 * *
115 ************************************************************************/
116/* #undef xmlStringText */
117const xmlChar xmlStringText[] = { 't', 'e', 'x', 't', 0 };
118/* #undef xmlStringTextNoenc */
120 { 't', 'e', 'x', 't', 'n', 'o', 'e', 'n', 'c', 0 };
121/* #undef xmlStringComment */
122const xmlChar xmlStringComment[] = { 'c', 'o', 'm', 'm', 'e', 'n', 't', 0 };
123
124static int xmlCompressMode = 0;
125static int xmlCheckDTD = 1;
126
127#define UPDATE_LAST_CHILD_AND_PARENT(n) if ((n) != NULL) { \
128 xmlNodePtr ulccur = (n)->children; \
129 if (ulccur == NULL) { \
130 (n)->last = NULL; \
131 } else { \
132 while (ulccur->next != NULL) { \
133 ulccur->parent = (n); \
134 ulccur = ulccur->next; \
135 } \
136 ulccur->parent = (n); \
137 (n)->last = ulccur; \
138}}
139
140#define IS_STR_XML(str) ((str != NULL) && (str[0] == 'x') && \
141 (str[1] == 'm') && (str[2] == 'l') && (str[3] == 0))
142
143/* #define DEBUG_BUFFER */
144/* #define DEBUG_TREE */
145
146/************************************************************************
147 * *
148 * Functions to move to entities.c once the *
149 * API freeze is smoothen and they can be made public. *
150 * *
151 ************************************************************************/
152#include <libxml/hash.h>
153
154#ifdef LIBXML_TREE_ENABLED
165static xmlEntityPtr
166xmlGetEntityFromDtd(const xmlDtd *dtd, const xmlChar *name) {
168
169 if((dtd != NULL) && (dtd->entities != NULL)) {
172 /* return(xmlGetEntityFromTable(table, name)); */
173 }
174 return(NULL);
175}
186static xmlEntityPtr
187xmlGetParameterEntityFromDtd(const xmlDtd *dtd, const xmlChar *name) {
189
190 if ((dtd != NULL) && (dtd->pentities != NULL)) {
193 /* return(xmlGetEntityFromTable(table, name)); */
194 }
195 return(NULL);
196}
197#endif /* LIBXML_TREE_ENABLED */
198
199/************************************************************************
200 * *
201 * QName handling helper *
202 * *
203 ************************************************************************/
204
219xmlChar *
220xmlBuildQName(const xmlChar *ncname, const xmlChar *prefix,
221 xmlChar *memory, int len) {
222 int lenn, lenp;
223 xmlChar *ret;
224
225 if (ncname == NULL) return(NULL);
226 if (prefix == NULL) return((xmlChar *) ncname);
227
228 lenn = strlen((char *) ncname);
229 lenp = strlen((char *) prefix);
230
231 if ((memory == NULL) || (len < lenn + lenp + 2)) {
232 ret = (xmlChar *) xmlMallocAtomic(lenn + lenp + 2);
233 if (ret == NULL) {
234 xmlTreeErrMemory("building QName");
235 return(NULL);
236 }
237 } else {
238 ret = memory;
239 }
240 memcpy(&ret[0], prefix, lenp);
241 ret[lenp] = ':';
242 memcpy(&ret[lenp + 1], ncname, lenn);
243 ret[lenn + lenp + 1] = 0;
244 return(ret);
245}
246
264xmlChar *
265xmlSplitQName2(const xmlChar *name, xmlChar **prefix) {
266 int len = 0;
267 xmlChar *ret = NULL;
268
269 if (prefix == NULL) return(NULL);
270 *prefix = NULL;
271 if (name == NULL) return(NULL);
272
273#ifndef XML_XML_NAMESPACE
274 /* xml: prefix is not really a namespace */
275 if ((name[0] == 'x') && (name[1] == 'm') &&
276 (name[2] == 'l') && (name[3] == ':'))
277 return(NULL);
278#endif
279
280 /* nasty but valid */
281 if (name[0] == ':')
282 return(NULL);
283
284 /*
285 * we are not trying to validate but just to cut, and yes it will
286 * work even if this is as set of UTF-8 encoded chars
287 */
288 while ((name[len] != 0) && (name[len] != ':'))
289 len++;
290
291 if (name[len] == 0)
292 return(NULL);
293
294 *prefix = xmlStrndup(name, len);
295 if (*prefix == NULL) {
296 xmlTreeErrMemory("QName split");
297 return(NULL);
298 }
299 ret = xmlStrdup(&name[len + 1]);
300 if (ret == NULL) {
301 xmlTreeErrMemory("QName split");
302 if (*prefix != NULL) {
303 xmlFree(*prefix);
304 *prefix = NULL;
305 }
306 return(NULL);
307 }
308
309 return(ret);
310}
311
324const xmlChar *
325xmlSplitQName3(const xmlChar *name, int *len) {
326 int l = 0;
327
328 if (name == NULL) return(NULL);
329 if (len == NULL) return(NULL);
330
331 /* nasty but valid */
332 if (name[0] == ':')
333 return(NULL);
334
335 /*
336 * we are not trying to validate but just to cut, and yes it will
337 * work even if this is as set of UTF-8 encoded chars
338 */
339 while ((name[l] != 0) && (name[l] != ':'))
340 l++;
341
342 if (name[l] == 0)
343 return(NULL);
344
345 *len = l;
346
347 return(&name[l+1]);
348}
349
350/************************************************************************
351 * *
352 * Check Name, NCName and QName strings *
353 * *
354 ************************************************************************/
355
356#define CUR_SCHAR(s, l) xmlStringCurrentChar(NULL, s, &l)
357
358#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_LEGACY_ENABLED)
369int
370xmlValidateNCName(const xmlChar *value, int space) {
371 const xmlChar *cur = value;
372 int c,l;
373
374 if (value == NULL)
375 return(-1);
376
377 /*
378 * First quick algorithm for ASCII range
379 */
380 if (space)
381 while (IS_BLANK_CH(*cur)) cur++;
382 if (((*cur >= 'a') && (*cur <= 'z')) || ((*cur >= 'A') && (*cur <= 'Z')) ||
383 (*cur == '_'))
384 cur++;
385 else
386 goto try_complex;
387 while (((*cur >= 'a') && (*cur <= 'z')) ||
388 ((*cur >= 'A') && (*cur <= 'Z')) ||
389 ((*cur >= '0') && (*cur <= '9')) ||
390 (*cur == '_') || (*cur == '-') || (*cur == '.'))
391 cur++;
392 if (space)
393 while (IS_BLANK_CH(*cur)) cur++;
394 if (*cur == 0)
395 return(0);
396
397try_complex:
398 /*
399 * Second check for chars outside the ASCII range
400 */
401 cur = value;
402 c = CUR_SCHAR(cur, l);
403 if (space) {
404 while (IS_BLANK(c)) {
405 cur += l;
406 c = CUR_SCHAR(cur, l);
407 }
408 }
409 if ((!IS_LETTER(c)) && (c != '_'))
410 return(1);
411 cur += l;
412 c = CUR_SCHAR(cur, l);
413 while (IS_LETTER(c) || IS_DIGIT(c) || (c == '.') ||
414 (c == '-') || (c == '_') || IS_COMBINING(c) ||
415 IS_EXTENDER(c)) {
416 cur += l;
417 c = CUR_SCHAR(cur, l);
418 }
419 if (space) {
420 while (IS_BLANK(c)) {
421 cur += l;
422 c = CUR_SCHAR(cur, l);
423 }
424 }
425 if (c != 0)
426 return(1);
427
428 return(0);
429}
430#endif
431
432#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
443int
444xmlValidateQName(const xmlChar *value, int space) {
445 const xmlChar *cur = value;
446 int c,l;
447
448 if (value == NULL)
449 return(-1);
450 /*
451 * First quick algorithm for ASCII range
452 */
453 if (space)
454 while (IS_BLANK_CH(*cur)) cur++;
455 if (((*cur >= 'a') && (*cur <= 'z')) || ((*cur >= 'A') && (*cur <= 'Z')) ||
456 (*cur == '_'))
457 cur++;
458 else
459 goto try_complex;
460 while (((*cur >= 'a') && (*cur <= 'z')) ||
461 ((*cur >= 'A') && (*cur <= 'Z')) ||
462 ((*cur >= '0') && (*cur <= '9')) ||
463 (*cur == '_') || (*cur == '-') || (*cur == '.'))
464 cur++;
465 if (*cur == ':') {
466 cur++;
467 if (((*cur >= 'a') && (*cur <= 'z')) ||
468 ((*cur >= 'A') && (*cur <= 'Z')) ||
469 (*cur == '_'))
470 cur++;
471 else
472 goto try_complex;
473 while (((*cur >= 'a') && (*cur <= 'z')) ||
474 ((*cur >= 'A') && (*cur <= 'Z')) ||
475 ((*cur >= '0') && (*cur <= '9')) ||
476 (*cur == '_') || (*cur == '-') || (*cur == '.'))
477 cur++;
478 }
479 if (space)
480 while (IS_BLANK_CH(*cur)) cur++;
481 if (*cur == 0)
482 return(0);
483
484try_complex:
485 /*
486 * Second check for chars outside the ASCII range
487 */
488 cur = value;
489 c = CUR_SCHAR(cur, l);
490 if (space) {
491 while (IS_BLANK(c)) {
492 cur += l;
493 c = CUR_SCHAR(cur, l);
494 }
495 }
496 if ((!IS_LETTER(c)) && (c != '_'))
497 return(1);
498 cur += l;
499 c = CUR_SCHAR(cur, l);
500 while (IS_LETTER(c) || IS_DIGIT(c) || (c == '.') ||
501 (c == '-') || (c == '_') || IS_COMBINING(c) ||
502 IS_EXTENDER(c)) {
503 cur += l;
504 c = CUR_SCHAR(cur, l);
505 }
506 if (c == ':') {
507 cur += l;
508 c = CUR_SCHAR(cur, l);
509 if ((!IS_LETTER(c)) && (c != '_'))
510 return(1);
511 cur += l;
512 c = CUR_SCHAR(cur, l);
513 while (IS_LETTER(c) || IS_DIGIT(c) || (c == '.') ||
514 (c == '-') || (c == '_') || IS_COMBINING(c) ||
515 IS_EXTENDER(c)) {
516 cur += l;
517 c = CUR_SCHAR(cur, l);
518 }
519 }
520 if (space) {
521 while (IS_BLANK(c)) {
522 cur += l;
523 c = CUR_SCHAR(cur, l);
524 }
525 }
526 if (c != 0)
527 return(1);
528 return(0);
529}
530
541int
542xmlValidateName(const xmlChar *value, int space) {
543 const xmlChar *cur = value;
544 int c,l;
545
546 if (value == NULL)
547 return(-1);
548 /*
549 * First quick algorithm for ASCII range
550 */
551 if (space)
552 while (IS_BLANK_CH(*cur)) cur++;
553 if (((*cur >= 'a') && (*cur <= 'z')) || ((*cur >= 'A') && (*cur <= 'Z')) ||
554 (*cur == '_') || (*cur == ':'))
555 cur++;
556 else
557 goto try_complex;
558 while (((*cur >= 'a') && (*cur <= 'z')) ||
559 ((*cur >= 'A') && (*cur <= 'Z')) ||
560 ((*cur >= '0') && (*cur <= '9')) ||
561 (*cur == '_') || (*cur == '-') || (*cur == '.') || (*cur == ':'))
562 cur++;
563 if (space)
564 while (IS_BLANK_CH(*cur)) cur++;
565 if (*cur == 0)
566 return(0);
567
568try_complex:
569 /*
570 * Second check for chars outside the ASCII range
571 */
572 cur = value;
573 c = CUR_SCHAR(cur, l);
574 if (space) {
575 while (IS_BLANK(c)) {
576 cur += l;
577 c = CUR_SCHAR(cur, l);
578 }
579 }
580 if ((!IS_LETTER(c)) && (c != '_') && (c != ':'))
581 return(1);
582 cur += l;
583 c = CUR_SCHAR(cur, l);
584 while (IS_LETTER(c) || IS_DIGIT(c) || (c == '.') || (c == ':') ||
585 (c == '-') || (c == '_') || IS_COMBINING(c) || IS_EXTENDER(c)) {
586 cur += l;
587 c = CUR_SCHAR(cur, l);
588 }
589 if (space) {
590 while (IS_BLANK(c)) {
591 cur += l;
592 c = CUR_SCHAR(cur, l);
593 }
594 }
595 if (c != 0)
596 return(1);
597 return(0);
598}
599
610int
611xmlValidateNMToken(const xmlChar *value, int space) {
612 const xmlChar *cur = value;
613 int c,l;
614
615 if (value == NULL)
616 return(-1);
617 /*
618 * First quick algorithm for ASCII range
619 */
620 if (space)
621 while (IS_BLANK_CH(*cur)) cur++;
622 if (((*cur >= 'a') && (*cur <= 'z')) ||
623 ((*cur >= 'A') && (*cur <= 'Z')) ||
624 ((*cur >= '0') && (*cur <= '9')) ||
625 (*cur == '_') || (*cur == '-') || (*cur == '.') || (*cur == ':'))
626 cur++;
627 else
628 goto try_complex;
629 while (((*cur >= 'a') && (*cur <= 'z')) ||
630 ((*cur >= 'A') && (*cur <= 'Z')) ||
631 ((*cur >= '0') && (*cur <= '9')) ||
632 (*cur == '_') || (*cur == '-') || (*cur == '.') || (*cur == ':'))
633 cur++;
634 if (space)
635 while (IS_BLANK_CH(*cur)) cur++;
636 if (*cur == 0)
637 return(0);
638
639try_complex:
640 /*
641 * Second check for chars outside the ASCII range
642 */
643 cur = value;
644 c = CUR_SCHAR(cur, l);
645 if (space) {
646 while (IS_BLANK(c)) {
647 cur += l;
648 c = CUR_SCHAR(cur, l);
649 }
650 }
651 if (!(IS_LETTER(c) || IS_DIGIT(c) || (c == '.') || (c == ':') ||
652 (c == '-') || (c == '_') || IS_COMBINING(c) || IS_EXTENDER(c)))
653 return(1);
654 cur += l;
655 c = CUR_SCHAR(cur, l);
656 while (IS_LETTER(c) || IS_DIGIT(c) || (c == '.') || (c == ':') ||
657 (c == '-') || (c == '_') || IS_COMBINING(c) || IS_EXTENDER(c)) {
658 cur += l;
659 c = CUR_SCHAR(cur, l);
660 }
661 if (space) {
662 while (IS_BLANK(c)) {
663 cur += l;
664 c = CUR_SCHAR(cur, l);
665 }
666 }
667 if (c != 0)
668 return(1);
669 return(0);
670}
671#endif /* LIBXML_TREE_ENABLED */
672
673/************************************************************************
674 * *
675 * Allocation and deallocation of basic structures *
676 * *
677 ************************************************************************/
678
688void
694}
695
711 return(xmlBufferAllocScheme);
712}
713
731xmlNewNs(xmlNodePtr node, const xmlChar *href, const xmlChar *prefix) {
733
734 if ((node != NULL) && (node->type != XML_ELEMENT_NODE))
735 return(NULL);
736
737 if ((prefix != NULL) && (xmlStrEqual(prefix, BAD_CAST "xml"))) {
738 /* xml namespace is predefined, no need to add it */
740 return(NULL);
741
742 /*
743 * Problem, this is an attempt to bind xml prefix to a wrong
744 * namespace, which breaks
745 * Namespace constraint: Reserved Prefixes and Namespace Names
746 * from XML namespace. But documents authors may not care in
747 * their context so let's proceed.
748 */
749 }
750
751 /*
752 * Allocate a new Namespace and fill the fields.
753 */
754 cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
755 if (cur == NULL) {
756 xmlTreeErrMemory("building namespace");
757 return(NULL);
758 }
759 memset(cur, 0, sizeof(xmlNs));
760 cur->type = XML_LOCAL_NAMESPACE;
761
762 if (href != NULL)
763 cur->href = xmlStrdup(href);
764 if (prefix != NULL)
765 cur->prefix = xmlStrdup(prefix);
766
767 /*
768 * Add it at the end to preserve parsing order ...
769 * and checks for existing use of the prefix
770 */
771 if (node != NULL) {
772 if (node->nsDef == NULL) {
773 node->nsDef = cur;
774 } else {
775 xmlNsPtr prev = node->nsDef;
776
777 if (((prev->prefix == NULL) && (cur->prefix == NULL)) ||
778 (xmlStrEqual(prev->prefix, cur->prefix))) {
779 xmlFreeNs(cur);
780 return(NULL);
781 }
782 while (prev->next != NULL) {
783 prev = prev->next;
784 if (((prev->prefix == NULL) && (cur->prefix == NULL)) ||
785 (xmlStrEqual(prev->prefix, cur->prefix))) {
786 xmlFreeNs(cur);
787 return(NULL);
788 }
789 }
790 prev->next = cur;
791 }
792 }
793 return(cur);
794}
795
803void
805 if (node == NULL) {
806#ifdef DEBUG_TREE
808 "xmlSetNs: node == NULL\n");
809#endif
810 return;
811 }
812 if ((node->type == XML_ELEMENT_NODE) ||
813 (node->type == XML_ATTRIBUTE_NODE))
814 node->ns = ns;
815}
816
823void
825 if (cur == NULL) {
826#ifdef DEBUG_TREE
828 "xmlFreeNs : ns == NULL\n");
829#endif
830 return;
831 }
832 if (cur->href != NULL) xmlFree((char *) cur->href);
833 if (cur->prefix != NULL) xmlFree((char *) cur->prefix);
834 xmlFree(cur);
835}
836
843void
846 if (cur == NULL) {
847#ifdef DEBUG_TREE
849 "xmlFreeNsList : ns == NULL\n");
850#endif
851 return;
852 }
853 while (cur != NULL) {
854 next = cur->next;
855 xmlFreeNs(cur);
856 cur = next;
857 }
858}
859
873xmlNewDtd(xmlDocPtr doc, const xmlChar *name,
874 const xmlChar *ExternalID, const xmlChar *SystemID) {
876
877 if ((doc != NULL) && (doc->extSubset != NULL)) {
878#ifdef DEBUG_TREE
880 "xmlNewDtd(%s): document %s already have a DTD %s\n",
881 /* !!! */ (char *) name, doc->name,
882 /* !!! */ (char *)doc->extSubset->name);
883#endif
884 return(NULL);
885 }
886
887 /*
888 * Allocate a new DTD and fill the fields.
889 */
890 cur = (xmlDtdPtr) xmlMalloc(sizeof(xmlDtd));
891 if (cur == NULL) {
892 xmlTreeErrMemory("building DTD");
893 return(NULL);
894 }
895 memset(cur, 0 , sizeof(xmlDtd));
896 cur->type = XML_DTD_NODE;
897
898 if (name != NULL)
899 cur->name = xmlStrdup(name);
900 if (ExternalID != NULL)
901 cur->ExternalID = xmlStrdup(ExternalID);
902 if (SystemID != NULL)
903 cur->SystemID = xmlStrdup(SystemID);
904 if (doc != NULL)
905 doc->extSubset = cur;
906 cur->doc = doc;
907
910 return(cur);
911}
912
922xmlGetIntSubset(const xmlDoc *doc) {
924
925 if (doc == NULL)
926 return(NULL);
927 cur = doc->children;
928 while (cur != NULL) {
929 if (cur->type == XML_DTD_NODE)
930 return((xmlDtdPtr) cur);
931 cur = cur->next;
932 }
933 return((xmlDtdPtr) doc->intSubset);
934}
935
948 const xmlChar *ExternalID, const xmlChar *SystemID) {
950
951 if ((doc != NULL) && (xmlGetIntSubset(doc) != NULL)) {
952#ifdef DEBUG_TREE
954
955 "xmlCreateIntSubset(): document %s already have an internal subset\n",
956 doc->name);
957#endif
958 return(NULL);
959 }
960
961 /*
962 * Allocate a new DTD and fill the fields.
963 */
964 cur = (xmlDtdPtr) xmlMalloc(sizeof(xmlDtd));
965 if (cur == NULL) {
966 xmlTreeErrMemory("building internal subset");
967 return(NULL);
968 }
969 memset(cur, 0, sizeof(xmlDtd));
970 cur->type = XML_DTD_NODE;
971
972 if (name != NULL) {
973 cur->name = xmlStrdup(name);
974 if (cur->name == NULL) {
975 xmlTreeErrMemory("building internal subset");
976 xmlFree(cur);
977 return(NULL);
978 }
979 }
980 if (ExternalID != NULL) {
981 cur->ExternalID = xmlStrdup(ExternalID);
982 if (cur->ExternalID == NULL) {
983 xmlTreeErrMemory("building internal subset");
984 if (cur->name != NULL)
985 xmlFree((char *)cur->name);
986 xmlFree(cur);
987 return(NULL);
988 }
989 }
990 if (SystemID != NULL) {
991 cur->SystemID = xmlStrdup(SystemID);
992 if (cur->SystemID == NULL) {
993 xmlTreeErrMemory("building internal subset");
994 if (cur->name != NULL)
995 xmlFree((char *)cur->name);
996 if (cur->ExternalID != NULL)
997 xmlFree((char *)cur->ExternalID);
998 xmlFree(cur);
999 return(NULL);
1000 }
1001 }
1002 if (doc != NULL) {
1003 doc->intSubset = cur;
1004 cur->parent = doc;
1005 cur->doc = doc;
1006 if (doc->children == NULL) {
1007 doc->children = (xmlNodePtr) cur;
1008 doc->last = (xmlNodePtr) cur;
1009 } else {
1010 if (doc->type == XML_HTML_DOCUMENT_NODE) {
1011 xmlNodePtr prev;
1012
1013 prev = doc->children;
1014 prev->prev = (xmlNodePtr) cur;
1015 cur->next = prev;
1016 doc->children = (xmlNodePtr) cur;
1017 } else {
1019
1020 next = doc->children;
1021 while ((next != NULL) && (next->type != XML_ELEMENT_NODE))
1022 next = next->next;
1023 if (next == NULL) {
1024 cur->prev = doc->last;
1025 cur->prev->next = (xmlNodePtr) cur;
1026 cur->next = NULL;
1027 doc->last = (xmlNodePtr) cur;
1028 } else {
1029 cur->next = next;
1030 cur->prev = next->prev;
1031 if (cur->prev == NULL)
1032 doc->children = (xmlNodePtr) cur;
1033 else
1034 cur->prev->next = (xmlNodePtr) cur;
1035 next->prev = (xmlNodePtr) cur;
1036 }
1037 }
1038 }
1039 }
1040
1043 return(cur);
1044}
1045
1053#define DICT_FREE(str) \
1054 if ((str) && ((!dict) || \
1055 (xmlDictOwns(dict, (const xmlChar *)(str)) == 0))) \
1056 xmlFree((char *)(str));
1057
1058
1066#define DICT_COPY(str, cpy) \
1067 if (str) { \
1068 if (dict) { \
1069 if (xmlDictOwns(dict, (const xmlChar *)(str))) \
1070 cpy = (xmlChar *) (str); \
1071 else \
1072 cpy = (xmlChar *) xmlDictLookup((dict), (const xmlChar *)(str), -1); \
1073 } else \
1074 cpy = xmlStrdup((const xmlChar *)(str)); }
1075
1083#define DICT_CONST_COPY(str, cpy) \
1084 if (str) { \
1085 if (dict) { \
1086 if (xmlDictOwns(dict, (const xmlChar *)(str))) \
1087 cpy = (const xmlChar *) (str); \
1088 else \
1089 cpy = xmlDictLookup((dict), (const xmlChar *)(str), -1); \
1090 } else \
1091 cpy = (const xmlChar *) xmlStrdup((const xmlChar *)(str)); }
1092
1093
1100void
1102 xmlDictPtr dict = NULL;
1103
1104 if (cur == NULL) {
1105 return;
1106 }
1107 if (cur->doc != NULL) dict = cur->doc->dict;
1108
1111
1112 if (cur->children != NULL) {
1113 xmlNodePtr next, c = cur->children;
1114
1115 /*
1116 * Cleanup all nodes which are not part of the specific lists
1117 * of notations, elements, attributes and entities.
1118 */
1119 while (c != NULL) {
1120 next = c->next;
1121 if ((c->type != XML_NOTATION_NODE) &&
1122 (c->type != XML_ELEMENT_DECL) &&
1123 (c->type != XML_ATTRIBUTE_DECL) &&
1124 (c->type != XML_ENTITY_DECL)) {
1126 xmlFreeNode(c);
1127 }
1128 c = next;
1129 }
1130 }
1131 DICT_FREE(cur->name)
1132 DICT_FREE(cur->SystemID)
1133 DICT_FREE(cur->ExternalID)
1134 /* TODO !!! */
1135 if (cur->notations != NULL)
1137
1138 if (cur->elements != NULL)
1140 if (cur->attributes != NULL)
1142 if (cur->entities != NULL)
1144 if (cur->pentities != NULL)
1146
1147 xmlFree(cur);
1148}
1149
1160 xmlDocPtr cur;
1161
1162 if (version == NULL)
1163 version = (const xmlChar *) "1.0";
1164
1165 /*
1166 * Allocate a new document and fill the fields.
1167 */
1168 cur = (xmlDocPtr) xmlMalloc(sizeof(xmlDoc));
1169 if (cur == NULL) {
1170 xmlTreeErrMemory("building doc");
1171 return(NULL);
1172 }
1173 memset(cur, 0, sizeof(xmlDoc));
1174 cur->type = XML_DOCUMENT_NODE;
1175
1176 cur->version = xmlStrdup(version);
1177 if (cur->version == NULL) {
1178 xmlTreeErrMemory("building doc");
1179 xmlFree(cur);
1180 return(NULL);
1181 }
1182 cur->standalone = -1;
1183 cur->compression = -1; /* not initialized */
1184 cur->doc = cur;
1185 cur->parseFlags = 0;
1186 cur->properties = XML_DOC_USERBUILT;
1187 /*
1188 * The in memory encoding is always UTF8
1189 * This field will never change and would
1190 * be obsolete if not for binary compatibility.
1191 */
1192 cur->charset = XML_CHAR_ENCODING_UTF8;
1193
1196 return(cur);
1197}
1198
1205void
1207 xmlDtdPtr extSubset, intSubset;
1208 xmlDictPtr dict = NULL;
1209
1210 if (cur == NULL) {
1211#ifdef DEBUG_TREE
1213 "xmlFreeDoc : document == NULL\n");
1214#endif
1215 return;
1216 }
1217#ifdef LIBXML_DEBUG_RUNTIME
1218#ifdef LIBXML_DEBUG_ENABLED
1219 xmlDebugCheckDocument(stderr, cur);
1220#endif
1221#endif
1222
1223 if (cur != NULL) dict = cur->dict;
1224
1227
1228 /*
1229 * Do this before freeing the children list to avoid ID lookups
1230 */
1231 if (cur->ids != NULL) xmlFreeIDTable((xmlIDTablePtr) cur->ids);
1232 cur->ids = NULL;
1233 if (cur->refs != NULL) xmlFreeRefTable((xmlRefTablePtr) cur->refs);
1234 cur->refs = NULL;
1235 extSubset = cur->extSubset;
1236 intSubset = cur->intSubset;
1237 if (intSubset == extSubset)
1238 extSubset = NULL;
1239 if (extSubset != NULL) {
1240 xmlUnlinkNode((xmlNodePtr) cur->extSubset);
1241 cur->extSubset = NULL;
1242 xmlFreeDtd(extSubset);
1243 }
1244 if (intSubset != NULL) {
1245 xmlUnlinkNode((xmlNodePtr) cur->intSubset);
1246 cur->intSubset = NULL;
1247 xmlFreeDtd(intSubset);
1248 }
1249
1250 if (cur->children != NULL) xmlFreeNodeList(cur->children);
1251 if (cur->oldNs != NULL) xmlFreeNsList(cur->oldNs);
1252
1253 DICT_FREE(cur->version)
1256 DICT_FREE(cur->URL)
1257 xmlFree(cur);
1258 if (dict) xmlDictFree(dict);
1259}
1260
1275 xmlChar *val;
1276 const xmlChar *cur, *end;
1277 const xmlChar *q;
1278 xmlEntityPtr ent;
1279 xmlBufPtr buf;
1280
1281 if (value == NULL) return(NULL);
1282 cur = value;
1283 end = cur + len;
1284
1285 buf = xmlBufCreateSize(0);
1286 if (buf == NULL) return(NULL);
1288
1289 q = cur;
1290 while ((cur < end) && (*cur != 0)) {
1291 if (cur[0] == '&') {
1292 int charval = 0;
1293 xmlChar tmp;
1294
1295 /*
1296 * Save the current text.
1297 */
1298 if (cur != q) {
1299 if (xmlBufAdd(buf, q, cur - q))
1300 goto out;
1301 }
1302 q = cur;
1303 if ((cur + 2 < end) && (cur[1] == '#') && (cur[2] == 'x')) {
1304 cur += 3;
1305 if (cur < end)
1306 tmp = *cur;
1307 else
1308 tmp = 0;
1309 while (tmp != ';') { /* Non input consuming loop */
1310 /*
1311 * If you find an integer overflow here when fuzzing,
1312 * the bug is probably elsewhere. This function should
1313 * only receive entities that were already validated by
1314 * the parser, typically by xmlParseAttValueComplex
1315 * calling xmlStringDecodeEntities.
1316 *
1317 * So it's better *not* to check for overflow to
1318 * potentially discover new bugs.
1319 */
1320 if ((tmp >= '0') && (tmp <= '9'))
1321 charval = charval * 16 + (tmp - '0');
1322 else if ((tmp >= 'a') && (tmp <= 'f'))
1323 charval = charval * 16 + (tmp - 'a') + 10;
1324 else if ((tmp >= 'A') && (tmp <= 'F'))
1325 charval = charval * 16 + (tmp - 'A') + 10;
1326 else {
1327 xmlTreeErr(XML_TREE_INVALID_HEX, (xmlNodePtr) doc,
1328 NULL);
1329 charval = 0;
1330 break;
1331 }
1332 cur++;
1333 if (cur < end)
1334 tmp = *cur;
1335 else
1336 tmp = 0;
1337 }
1338 if (tmp == ';')
1339 cur++;
1340 q = cur;
1341 } else if ((cur + 1 < end) && (cur[1] == '#')) {
1342 cur += 2;
1343 if (cur < end)
1344 tmp = *cur;
1345 else
1346 tmp = 0;
1347 while (tmp != ';') { /* Non input consuming loops */
1348 /* Don't check for integer overflow, see above. */
1349 if ((tmp >= '0') && (tmp <= '9'))
1350 charval = charval * 10 + (tmp - '0');
1351 else {
1352 xmlTreeErr(XML_TREE_INVALID_DEC, (xmlNodePtr) doc,
1353 NULL);
1354 charval = 0;
1355 break;
1356 }
1357 cur++;
1358 if (cur < end)
1359 tmp = *cur;
1360 else
1361 tmp = 0;
1362 }
1363 if (tmp == ';')
1364 cur++;
1365 q = cur;
1366 } else {
1367 /*
1368 * Read the entity string
1369 */
1370 cur++;
1371 q = cur;
1372 while ((cur < end) && (*cur != 0) && (*cur != ';')) cur++;
1373 if ((cur >= end) || (*cur == 0)) {
1374 xmlTreeErr(XML_TREE_UNTERMINATED_ENTITY, (xmlNodePtr) doc,
1375 (const char *) q);
1376 goto out;
1377 }
1378 if (cur != q) {
1379 /*
1380 * Predefined entities don't generate nodes
1381 */
1382 val = xmlStrndup(q, cur - q);
1383 ent = xmlGetDocEntity(doc, val);
1384 if ((ent != NULL) &&
1386
1387 if (xmlBufCat(buf, ent->content))
1388 goto out;
1389
1390 } else {
1391 /*
1392 * Flush buffer so far
1393 */
1394 if (!xmlBufIsEmpty(buf)) {
1395 node = xmlNewDocText(doc, NULL);
1396 if (node == NULL) {
1397 if (val != NULL) xmlFree(val);
1398 goto out;
1399 }
1400 node->content = xmlBufDetach(buf);
1401
1402 if (last == NULL) {
1403 last = ret = node;
1404 } else {
1406 }
1407 }
1408
1409 /*
1410 * Create a new REFERENCE_REF node
1411 */
1412 node = xmlNewReference(doc, val);
1413 if (node == NULL) {
1414 if (val != NULL) xmlFree(val);
1415 goto out;
1416 }
1417 else if ((ent != NULL) && (ent->children == NULL)) {
1419
1420 /* Set to non-NULL value to avoid recursion. */
1421 ent->children = (xmlNodePtr) -1;
1422 ent->children = xmlStringGetNodeList(doc,
1423 (const xmlChar*)node->content);
1424 ent->owner = 1;
1425 temp = ent->children;
1426 while (temp) {
1427 temp->parent = (xmlNodePtr)ent;
1428 ent->last = temp;
1429 temp = temp->next;
1430 }
1431 }
1432 if (last == NULL) {
1433 last = ret = node;
1434 } else {
1436 }
1437 }
1438 xmlFree(val);
1439 }
1440 cur++;
1441 q = cur;
1442 }
1443 if (charval != 0) {
1444 xmlChar buffer[10];
1445 int l;
1446
1447 l = xmlCopyCharMultiByte(buffer, charval);
1448 buffer[l] = 0;
1449
1450 if (xmlBufCat(buf, buffer))
1451 goto out;
1452 charval = 0;
1453 }
1454 } else
1455 cur++;
1456 }
1457
1458 if (cur != q) {
1459 /*
1460 * Handle the last piece of text.
1461 */
1462 if (xmlBufAdd(buf, q, cur - q))
1463 goto out;
1464 }
1465
1466 if (!xmlBufIsEmpty(buf)) {
1467 node = xmlNewDocText(doc, NULL);
1468 if (node == NULL) goto out;
1469 node->content = xmlBufDetach(buf);
1470
1471 if (last == NULL) {
1472 ret = node;
1473 } else {
1475 }
1476 } else if (ret == NULL) {
1477 ret = xmlNewDocText(doc, BAD_CAST "");
1478 }
1479
1480out:
1481 xmlBufFree(buf);
1482 return(ret);
1483}
1484
1495xmlStringGetNodeList(const xmlDoc *doc, const xmlChar *value) {
1498 xmlChar *val;
1499 const xmlChar *cur = value;
1500 const xmlChar *q;
1501 xmlEntityPtr ent;
1502 xmlBufPtr buf;
1503
1504 if (value == NULL) return(NULL);
1505
1506 buf = xmlBufCreateSize(0);
1507 if (buf == NULL) return(NULL);
1509
1510 q = cur;
1511 while (*cur != 0) {
1512 if (cur[0] == '&') {
1513 int charval = 0;
1514 xmlChar tmp;
1515
1516 /*
1517 * Save the current text.
1518 */
1519 if (cur != q) {
1520 if (xmlBufAdd(buf, q, cur - q))
1521 goto out;
1522 }
1523 q = cur;
1524 if ((cur[1] == '#') && (cur[2] == 'x')) {
1525 cur += 3;
1526 tmp = *cur;
1527 while (tmp != ';') { /* Non input consuming loop */
1528 /* Don't check for integer overflow, see above. */
1529 if ((tmp >= '0') && (tmp <= '9'))
1530 charval = charval * 16 + (tmp - '0');
1531 else if ((tmp >= 'a') && (tmp <= 'f'))
1532 charval = charval * 16 + (tmp - 'a') + 10;
1533 else if ((tmp >= 'A') && (tmp <= 'F'))
1534 charval = charval * 16 + (tmp - 'A') + 10;
1535 else {
1536 xmlTreeErr(XML_TREE_INVALID_HEX, (xmlNodePtr) doc,
1537 NULL);
1538 charval = 0;
1539 break;
1540 }
1541 cur++;
1542 tmp = *cur;
1543 }
1544 if (tmp == ';')
1545 cur++;
1546 q = cur;
1547 } else if (cur[1] == '#') {
1548 cur += 2;
1549 tmp = *cur;
1550 while (tmp != ';') { /* Non input consuming loops */
1551 /* Don't check for integer overflow, see above. */
1552 if ((tmp >= '0') && (tmp <= '9'))
1553 charval = charval * 10 + (tmp - '0');
1554 else {
1555 xmlTreeErr(XML_TREE_INVALID_DEC, (xmlNodePtr) doc,
1556 NULL);
1557 charval = 0;
1558 break;
1559 }
1560 cur++;
1561 tmp = *cur;
1562 }
1563 if (tmp == ';')
1564 cur++;
1565 q = cur;
1566 } else {
1567 /*
1568 * Read the entity string
1569 */
1570 cur++;
1571 q = cur;
1572 while ((*cur != 0) && (*cur != ';')) cur++;
1573 if (*cur == 0) {
1575 (xmlNodePtr) doc, (const char *) q);
1576 goto out;
1577 }
1578 if (cur != q) {
1579 /*
1580 * Predefined entities don't generate nodes
1581 */
1582 val = xmlStrndup(q, cur - q);
1583 ent = xmlGetDocEntity(doc, val);
1584 if ((ent != NULL) &&
1586
1587 if (xmlBufCat(buf, ent->content))
1588 goto out;
1589
1590 } else {
1591 /*
1592 * Flush buffer so far
1593 */
1594 if (!xmlBufIsEmpty(buf)) {
1595 node = xmlNewDocText(doc, NULL);
1596 if (node == NULL) {
1597 if (val != NULL) xmlFree(val);
1598 goto out;
1599 }
1600 node->content = xmlBufDetach(buf);
1601
1602 if (last == NULL) {
1603 last = ret = node;
1604 } else {
1606 }
1607 }
1608
1609 /*
1610 * Create a new REFERENCE_REF node
1611 */
1612 node = xmlNewReference(doc, val);
1613 if (node == NULL) {
1614 if (val != NULL) xmlFree(val);
1615 goto out;
1616 }
1617 else if ((ent != NULL) && (ent->children == NULL)) {
1619
1620 /* Set to non-NULL value to avoid recursion. */
1621 ent->children = (xmlNodePtr) -1;
1622 ent->children = xmlStringGetNodeList(doc,
1623 (const xmlChar*)node->content);
1624 ent->owner = 1;
1625 temp = ent->children;
1626 while (temp) {
1627 temp->parent = (xmlNodePtr)ent;
1628 ent->last = temp;
1629 temp = temp->next;
1630 }
1631 }
1632 if (last == NULL) {
1633 last = ret = node;
1634 } else {
1636 }
1637 }
1638 xmlFree(val);
1639 }
1640 cur++;
1641 q = cur;
1642 }
1643 if (charval != 0) {
1644 xmlChar buffer[10];
1645 int len;
1646
1647 len = xmlCopyCharMultiByte(buffer, charval);
1648 buffer[len] = 0;
1649
1650 if (xmlBufCat(buf, buffer))
1651 goto out;
1652 charval = 0;
1653 }
1654 } else
1655 cur++;
1656 }
1657 if ((cur != q) || (ret == NULL)) {
1658 /*
1659 * Handle the last piece of text.
1660 */
1661 xmlBufAdd(buf, q, cur - q);
1662 }
1663
1664 if (!xmlBufIsEmpty(buf)) {
1665 node = xmlNewDocText(doc, NULL);
1666 if (node == NULL) {
1667 xmlBufFree(buf);
1668 return(NULL);
1669 }
1670 node->content = xmlBufDetach(buf);
1671
1672 if (last == NULL) {
1673 ret = node;
1674 } else {
1676 }
1677 }
1678
1679out:
1680 xmlBufFree(buf);
1681 return(ret);
1682}
1683
1695xmlChar *
1696xmlNodeListGetString(xmlDocPtr doc, const xmlNode *list, int inLine)
1697{
1698 const xmlNode *node = list;
1699 xmlChar *ret = NULL;
1700 xmlEntityPtr ent;
1701 int attr;
1702
1703 if (list == NULL)
1704 return (NULL);
1705 if ((list->parent != NULL) && (list->parent->type == XML_ATTRIBUTE_NODE))
1706 attr = 1;
1707 else
1708 attr = 0;
1709
1710 while (node != NULL) {
1711 if ((node->type == XML_TEXT_NODE) ||
1712 (node->type == XML_CDATA_SECTION_NODE)) {
1713 if (inLine) {
1714 ret = xmlStrcat(ret, node->content);
1715 } else {
1716 xmlChar *buffer;
1717
1718 if (attr)
1719 buffer = xmlEncodeAttributeEntities(doc, node->content);
1720 else
1721 buffer = xmlEncodeEntitiesReentrant(doc, node->content);
1722 if (buffer != NULL) {
1723 ret = xmlStrcat(ret, buffer);
1724 xmlFree(buffer);
1725 }
1726 }
1727 } else if (node->type == XML_ENTITY_REF_NODE) {
1728 if (inLine) {
1729 ent = xmlGetDocEntity(doc, node->name);
1730 if (ent != NULL) {
1731 xmlChar *buffer;
1732
1733 /* an entity content can be any "well balanced chunk",
1734 * i.e. the result of the content [43] production:
1735 * http://www.w3.org/TR/REC-xml#NT-content.
1736 * So it can contain text, CDATA section or nested
1737 * entity reference nodes (among others).
1738 * -> we recursive call xmlNodeListGetString()
1739 * which handles these types */
1740 buffer = xmlNodeListGetString(doc, ent->children, 1);
1741 if (buffer != NULL) {
1742 ret = xmlStrcat(ret, buffer);
1743 xmlFree(buffer);
1744 }
1745 } else {
1746 ret = xmlStrcat(ret, node->content);
1747 }
1748 } else {
1749 xmlChar buf[2];
1750
1751 buf[0] = '&';
1752 buf[1] = 0;
1753 ret = xmlStrncat(ret, buf, 1);
1754 ret = xmlStrcat(ret, node->name);
1755 buf[0] = ';';
1756 buf[1] = 0;
1757 ret = xmlStrncat(ret, buf, 1);
1758 }
1759 }
1760#if 0
1761 else {
1763 "xmlGetNodeListString : invalid node type %d\n",
1764 node->type);
1765 }
1766#endif
1767 node = node->next;
1768 }
1769 return (ret);
1770}
1771
1772#ifdef LIBXML_TREE_ENABLED
1785xmlChar *
1786xmlNodeListGetRawString(const xmlDoc *doc, const xmlNode *list, int inLine)
1787{
1788 const xmlNode *node = list;
1789 xmlChar *ret = NULL;
1790 xmlEntityPtr ent;
1791
1792 if (list == NULL)
1793 return (NULL);
1794
1795 while (node != NULL) {
1796 if ((node->type == XML_TEXT_NODE) ||
1797 (node->type == XML_CDATA_SECTION_NODE)) {
1798 if (inLine) {
1799 ret = xmlStrcat(ret, node->content);
1800 } else {
1801 xmlChar *buffer;
1802
1803 buffer = xmlEncodeSpecialChars(doc, node->content);
1804 if (buffer != NULL) {
1805 ret = xmlStrcat(ret, buffer);
1806 xmlFree(buffer);
1807 }
1808 }
1809 } else if (node->type == XML_ENTITY_REF_NODE) {
1810 if (inLine) {
1811 ent = xmlGetDocEntity(doc, node->name);
1812 if (ent != NULL) {
1813 xmlChar *buffer;
1814
1815 /* an entity content can be any "well balanced chunk",
1816 * i.e. the result of the content [43] production:
1817 * http://www.w3.org/TR/REC-xml#NT-content.
1818 * So it can contain text, CDATA section or nested
1819 * entity reference nodes (among others).
1820 * -> we recursive call xmlNodeListGetRawString()
1821 * which handles these types */
1822 buffer =
1823 xmlNodeListGetRawString(doc, ent->children, 1);
1824 if (buffer != NULL) {
1825 ret = xmlStrcat(ret, buffer);
1826 xmlFree(buffer);
1827 }
1828 } else {
1829 ret = xmlStrcat(ret, node->content);
1830 }
1831 } else {
1832 xmlChar buf[2];
1833
1834 buf[0] = '&';
1835 buf[1] = 0;
1836 ret = xmlStrncat(ret, buf, 1);
1837 ret = xmlStrcat(ret, node->name);
1838 buf[0] = ';';
1839 buf[1] = 0;
1840 ret = xmlStrncat(ret, buf, 1);
1841 }
1842 }
1843#if 0
1844 else {
1846 "xmlGetNodeListString : invalid node type %d\n",
1847 node->type);
1848 }
1849#endif
1850 node = node->next;
1851 }
1852 return (ret);
1853}
1854#endif /* LIBXML_TREE_ENABLED */
1855
1856static xmlAttrPtr
1857xmlNewPropInternal(xmlNodePtr node, xmlNsPtr ns,
1858 const xmlChar * name, const xmlChar * value,
1859 int eatname)
1860{
1862 xmlDocPtr doc = NULL;
1863
1864 if ((node != NULL) && (node->type != XML_ELEMENT_NODE)) {
1865 if ((eatname == 1) &&
1866 ((node->doc == NULL) ||
1867 (!(xmlDictOwns(node->doc->dict, name)))))
1868 xmlFree((xmlChar *) name);
1869 return (NULL);
1870 }
1871
1872 /*
1873 * Allocate a new property and fill the fields.
1874 */
1875 cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr));
1876 if (cur == NULL) {
1877 if ((eatname == 1) &&
1878 ((node == NULL) || (node->doc == NULL) ||
1879 (!(xmlDictOwns(node->doc->dict, name)))))
1880 xmlFree((xmlChar *) name);
1881 xmlTreeErrMemory("building attribute");
1882 return (NULL);
1883 }
1884 memset(cur, 0, sizeof(xmlAttr));
1885 cur->type = XML_ATTRIBUTE_NODE;
1886
1887 cur->parent = node;
1888 if (node != NULL) {
1889 doc = node->doc;
1890 cur->doc = doc;
1891 }
1892 cur->ns = ns;
1893
1894 if (eatname == 0) {
1895 if ((doc != NULL) && (doc->dict != NULL))
1896 cur->name = (xmlChar *) xmlDictLookup(doc->dict, name, -1);
1897 else
1898 cur->name = xmlStrdup(name);
1899 } else
1900 cur->name = name;
1901
1902 if (value != NULL) {
1903 xmlNodePtr tmp;
1904
1905 cur->children = xmlNewDocText(doc, value);
1906 cur->last = NULL;
1907 tmp = cur->children;
1908 while (tmp != NULL) {
1909 tmp->parent = (xmlNodePtr) cur;
1910 if (tmp->next == NULL)
1911 cur->last = tmp;
1912 tmp = tmp->next;
1913 }
1914 }
1915
1916 /*
1917 * Add it at the end to preserve parsing order ...
1918 */
1919 if (node != NULL) {
1920 if (node->properties == NULL) {
1921 node->properties = cur;
1922 } else {
1923 xmlAttrPtr prev = node->properties;
1924
1925 while (prev->next != NULL)
1926 prev = prev->next;
1927 prev->next = cur;
1928 cur->prev = prev;
1929 }
1930 }
1931
1932 if ((value != NULL) && (node != NULL) &&
1933 (xmlIsID(node->doc, node, cur) == 1))
1934 xmlAddID(NULL, node->doc, value, cur);
1935
1938 return (cur);
1939}
1940
1941#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_HTML_ENABLED) || \
1942 defined(LIBXML_SCHEMAS_ENABLED)
1953xmlNewProp(xmlNodePtr node, const xmlChar *name, const xmlChar *value) {
1954
1955 if (name == NULL) {
1956#ifdef DEBUG_TREE
1958 "xmlNewProp : name == NULL\n");
1959#endif
1960 return(NULL);
1961 }
1962
1963 return xmlNewPropInternal(node, NULL, name, value, 0);
1964}
1965#endif /* LIBXML_TREE_ENABLED */
1966
1979 const xmlChar *value) {
1980
1981 if (name == NULL) {
1982#ifdef DEBUG_TREE
1984 "xmlNewNsProp : name == NULL\n");
1985#endif
1986 return(NULL);
1987 }
1988
1989 return xmlNewPropInternal(node, ns, name, value, 0);
1990}
1991
2004 const xmlChar *value) {
2005
2006 if (name == NULL) {
2007#ifdef DEBUG_TREE
2009 "xmlNewNsPropEatName : name == NULL\n");
2010#endif
2011 return(NULL);
2012 }
2013
2014 return xmlNewPropInternal(node, ns, name, value, 1);
2015}
2016
2032xmlNewDocProp(xmlDocPtr doc, const xmlChar *name, const xmlChar *value) {
2034
2035 if (name == NULL) {
2036#ifdef DEBUG_TREE
2038 "xmlNewDocProp : name == NULL\n");
2039#endif
2040 return(NULL);
2041 }
2042
2043 /*
2044 * Allocate a new property and fill the fields.
2045 */
2046 cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr));
2047 if (cur == NULL) {
2048 xmlTreeErrMemory("building attribute");
2049 return(NULL);
2050 }
2051 memset(cur, 0, sizeof(xmlAttr));
2052 cur->type = XML_ATTRIBUTE_NODE;
2053
2054 if ((doc != NULL) && (doc->dict != NULL))
2055 cur->name = xmlDictLookup(doc->dict, name, -1);
2056 else
2057 cur->name = xmlStrdup(name);
2058 cur->doc = doc;
2059 if (value != NULL) {
2060 xmlNodePtr tmp;
2061
2062 cur->children = xmlStringGetNodeList(doc, value);
2063 cur->last = NULL;
2064
2065 tmp = cur->children;
2066 while (tmp != NULL) {
2067 tmp->parent = (xmlNodePtr) cur;
2068 if (tmp->next == NULL)
2069 cur->last = tmp;
2070 tmp = tmp->next;
2071 }
2072 }
2073
2076 return(cur);
2077}
2078
2085void
2088 if (cur == NULL) return;
2089 while (cur != NULL) {
2090 next = cur->next;
2092 cur = next;
2093 }
2094}
2095
2102void
2104 xmlDictPtr dict = NULL;
2105 if (cur == NULL) return;
2106
2107 if (cur->doc != NULL) dict = cur->doc->dict;
2108
2111
2112 /* Check for ID removal -> leading to invalid references ! */
2113 if ((cur->doc != NULL) && (cur->atype == XML_ATTRIBUTE_ID)) {
2114 xmlRemoveID(cur->doc, cur);
2115 }
2116 if (cur->children != NULL) xmlFreeNodeList(cur->children);
2117 DICT_FREE(cur->name)
2118 xmlFree(cur);
2119}
2120
2130int
2132 xmlAttrPtr tmp;
2133 if (cur == NULL) {
2134#ifdef DEBUG_TREE
2136 "xmlRemoveProp : cur == NULL\n");
2137#endif
2138 return(-1);
2139 }
2140 if (cur->parent == NULL) {
2141#ifdef DEBUG_TREE
2143 "xmlRemoveProp : cur->parent == NULL\n");
2144#endif
2145 return(-1);
2146 }
2147 tmp = cur->parent->properties;
2148 if (tmp == cur) {
2149 cur->parent->properties = cur->next;
2150 if (cur->next != NULL)
2151 cur->next->prev = NULL;
2153 return(0);
2154 }
2155 while (tmp != NULL) {
2156 if (tmp->next == cur) {
2157 tmp->next = cur->next;
2158 if (tmp->next != NULL)
2159 tmp->next->prev = tmp;
2161 return(0);
2162 }
2163 tmp = tmp->next;
2164 }
2165#ifdef DEBUG_TREE
2167 "xmlRemoveProp : attribute not owned by its node\n");
2168#endif
2169 return(-1);
2170}
2171
2182xmlNewDocPI(xmlDocPtr doc, const xmlChar *name, const xmlChar *content) {
2184
2185 if (name == NULL) {
2186#ifdef DEBUG_TREE
2188 "xmlNewPI : name == NULL\n");
2189#endif
2190 return(NULL);
2191 }
2192
2193 /*
2194 * Allocate a new node and fill the fields.
2195 */
2196 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
2197 if (cur == NULL) {
2198 xmlTreeErrMemory("building PI");
2199 return(NULL);
2200 }
2201 memset(cur, 0, sizeof(xmlNode));
2202 cur->type = XML_PI_NODE;
2203
2204 if ((doc != NULL) && (doc->dict != NULL))
2205 cur->name = xmlDictLookup(doc->dict, name, -1);
2206 else
2207 cur->name = xmlStrdup(name);
2208 if (content != NULL) {
2209 cur->content = xmlStrdup(content);
2210 }
2211 cur->doc = doc;
2212
2215 return(cur);
2216}
2217
2230xmlNewPI(const xmlChar *name, const xmlChar *content) {
2231 return(xmlNewDocPI(NULL, name, content));
2232}
2233
2249
2250 if (name == NULL) {
2251#ifdef DEBUG_TREE
2253 "xmlNewNode : name == NULL\n");
2254#endif
2255 return(NULL);
2256 }
2257
2258 /*
2259 * Allocate a new node and fill the fields.
2260 */
2261 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
2262 if (cur == NULL) {
2263 xmlTreeErrMemory("building node");
2264 return(NULL);
2265 }
2266 memset(cur, 0, sizeof(xmlNode));
2267 cur->type = XML_ELEMENT_NODE;
2268
2269 cur->name = xmlStrdup(name);
2270 cur->ns = ns;
2271
2274 return(cur);
2275}
2276
2293
2294 if (name == NULL) {
2295#ifdef DEBUG_TREE
2297 "xmlNewNode : name == NULL\n");
2298#endif
2299 return(NULL);
2300 }
2301
2302 /*
2303 * Allocate a new node and fill the fields.
2304 */
2305 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
2306 if (cur == NULL) {
2307 xmlTreeErrMemory("building node");
2308 /* we can't check here that name comes from the doc dictionary */
2309 return(NULL);
2310 }
2311 memset(cur, 0, sizeof(xmlNode));
2312 cur->type = XML_ELEMENT_NODE;
2313
2314 cur->name = name;
2315 cur->ns = ns;
2316
2319 return(cur);
2320}
2321
2340 const xmlChar *name, const xmlChar *content) {
2342
2343 if ((doc != NULL) && (doc->dict != NULL))
2345 xmlDictLookup(doc->dict, name, -1));
2346 else
2347 cur = xmlNewNode(ns, name);
2348 if (cur != NULL) {
2349 cur->doc = doc;
2350 if (content != NULL) {
2351 cur->children = xmlStringGetNodeList(doc, content);
2353 }
2354 }
2355
2356 return(cur);
2357}
2358
2377 xmlChar *name, const xmlChar *content) {
2379
2381 if (cur != NULL) {
2382 cur->doc = doc;
2383 if (content != NULL) {
2384 cur->children = xmlStringGetNodeList(doc, content);
2386 }
2387 } else {
2388 /* if name don't come from the doc dictionary free it here */
2389 if ((name != NULL) && (doc != NULL) &&
2390 (!(xmlDictOwns(doc->dict, name))))
2391 xmlFree(name);
2392 }
2393 return(cur);
2394}
2395
2396#ifdef LIBXML_TREE_ENABLED
2410xmlNewDocRawNode(xmlDocPtr doc, xmlNsPtr ns,
2411 const xmlChar *name, const xmlChar *content) {
2413
2414 cur = xmlNewDocNode(doc, ns, name, NULL);
2415 if (cur != NULL) {
2416 cur->doc = doc;
2417 if (content != NULL) {
2418 cur->children = xmlNewDocText(doc, content);
2420 }
2421 }
2422 return(cur);
2423}
2424
2433xmlNewDocFragment(xmlDocPtr doc) {
2435
2436 /*
2437 * Allocate a new DocumentFragment node and fill the fields.
2438 */
2439 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
2440 if (cur == NULL) {
2441 xmlTreeErrMemory("building fragment");
2442 return(NULL);
2443 }
2444 memset(cur, 0, sizeof(xmlNode));
2446
2447 cur->doc = doc;
2448
2451 return(cur);
2452}
2453#endif /* LIBXML_TREE_ENABLED */
2454
2466xmlNewText(const xmlChar *content) {
2468
2469 /*
2470 * Allocate a new node and fill the fields.
2471 */
2472 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
2473 if (cur == NULL) {
2474 xmlTreeErrMemory("building text");
2475 return(NULL);
2476 }
2477 memset(cur, 0, sizeof(xmlNode));
2478 cur->type = XML_TEXT_NODE;
2479
2480 cur->name = xmlStringText;
2481 if (content != NULL) {
2482 cur->content = xmlStrdup(content);
2483 }
2484
2487 return(cur);
2488}
2489
2490#ifdef LIBXML_TREE_ENABLED
2511xmlNewTextChild(xmlNodePtr parent, xmlNsPtr ns,
2512 const xmlChar *name, const xmlChar *content) {
2513 xmlNodePtr cur, prev;
2514
2515 if (parent == NULL) {
2516#ifdef DEBUG_TREE
2518 "xmlNewTextChild : parent == NULL\n");
2519#endif
2520 return(NULL);
2521 }
2522
2523 if (name == NULL) {
2524#ifdef DEBUG_TREE
2526 "xmlNewTextChild : name == NULL\n");
2527#endif
2528 return(NULL);
2529 }
2530
2531 /*
2532 * Allocate a new node
2533 */
2534 if (parent->type == XML_ELEMENT_NODE) {
2535 if (ns == NULL)
2536 cur = xmlNewDocRawNode(parent->doc, parent->ns, name, content);
2537 else
2538 cur = xmlNewDocRawNode(parent->doc, ns, name, content);
2539 } else if ((parent->type == XML_DOCUMENT_NODE) ||
2540 (parent->type == XML_HTML_DOCUMENT_NODE)) {
2541 if (ns == NULL)
2542 cur = xmlNewDocRawNode((xmlDocPtr) parent, NULL, name, content);
2543 else
2544 cur = xmlNewDocRawNode((xmlDocPtr) parent, ns, name, content);
2545 } else if (parent->type == XML_DOCUMENT_FRAG_NODE) {
2546 cur = xmlNewDocRawNode( parent->doc, ns, name, content);
2547 } else {
2548 return(NULL);
2549 }
2550 if (cur == NULL) return(NULL);
2551
2552 /*
2553 * add the new element at the end of the children list.
2554 */
2555 cur->type = XML_ELEMENT_NODE;
2556 cur->parent = parent;
2557 cur->doc = parent->doc;
2558 if (parent->children == NULL) {
2559 parent->children = cur;
2560 parent->last = cur;
2561 } else {
2562 prev = parent->last;
2563 prev->next = cur;
2564 cur->prev = prev;
2565 parent->last = cur;
2566 }
2567
2568 return(cur);
2569}
2570#endif /* LIBXML_TREE_ENABLED */
2571
2581xmlNewCharRef(xmlDocPtr doc, const xmlChar *name) {
2583
2584 if (name == NULL)
2585 return(NULL);
2586
2587 /*
2588 * Allocate a new node and fill the fields.
2589 */
2590 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
2591 if (cur == NULL) {
2592 xmlTreeErrMemory("building character reference");
2593 return(NULL);
2594 }
2595 memset(cur, 0, sizeof(xmlNode));
2596 cur->type = XML_ENTITY_REF_NODE;
2597
2598 cur->doc = doc;
2599 if (name[0] == '&') {
2600 int len;
2601 name++;
2602 len = xmlStrlen(name);
2603 if (name[len - 1] == ';')
2604 cur->name = xmlStrndup(name, len - 1);
2605 else
2606 cur->name = xmlStrndup(name, len);
2607 } else
2608 cur->name = xmlStrdup(name);
2609
2612 return(cur);
2613}
2614
2624xmlNewReference(const xmlDoc *doc, const xmlChar *name) {
2626 xmlEntityPtr ent;
2627
2628 if (name == NULL)
2629 return(NULL);
2630
2631 /*
2632 * Allocate a new node and fill the fields.
2633 */
2634 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
2635 if (cur == NULL) {
2636 xmlTreeErrMemory("building reference");
2637 return(NULL);
2638 }
2639 memset(cur, 0, sizeof(xmlNode));
2640 cur->type = XML_ENTITY_REF_NODE;
2641
2642 cur->doc = (xmlDoc *)doc;
2643 if (name[0] == '&') {
2644 int len;
2645 name++;
2646 len = xmlStrlen(name);
2647 if (name[len - 1] == ';')
2648 cur->name = xmlStrndup(name, len - 1);
2649 else
2650 cur->name = xmlStrndup(name, len);
2651 } else
2652 cur->name = xmlStrdup(name);
2653
2654 ent = xmlGetDocEntity(doc, cur->name);
2655 if (ent != NULL) {
2656 cur->content = ent->content;
2657 /*
2658 * The parent pointer in entity is a DTD pointer and thus is NOT
2659 * updated. Not sure if this is 100% correct.
2660 * -George
2661 */
2662 cur->children = (xmlNodePtr) ent;
2663 cur->last = (xmlNodePtr) ent;
2664 }
2665
2668 return(cur);
2669}
2670
2680xmlNewDocText(const xmlDoc *doc, const xmlChar *content) {
2682
2684 if (cur != NULL) cur->doc = (xmlDoc *)doc;
2685 return(cur);
2686}
2687
2699xmlNewTextLen(const xmlChar *content, int len) {
2701
2702 /*
2703 * Allocate a new node and fill the fields.
2704 */
2705 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
2706 if (cur == NULL) {
2707 xmlTreeErrMemory("building text");
2708 return(NULL);
2709 }
2710 memset(cur, 0, sizeof(xmlNode));
2711 cur->type = XML_TEXT_NODE;
2712
2713 cur->name = xmlStringText;
2714 if (content != NULL) {
2715 cur->content = xmlStrndup(content, len);
2716 }
2717
2720 return(cur);
2721}
2722
2734xmlNewDocTextLen(xmlDocPtr doc, const xmlChar *content, int len) {
2736
2738 if (cur != NULL) cur->doc = doc;
2739 return(cur);
2740}
2741
2754
2755 /*
2756 * Allocate a new node and fill the fields.
2757 */
2758 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
2759 if (cur == NULL) {
2760 xmlTreeErrMemory("building comment");
2761 return(NULL);
2762 }
2763 memset(cur, 0, sizeof(xmlNode));
2764 cur->type = XML_COMMENT_NODE;
2765
2766 cur->name = xmlStringComment;
2767 if (content != NULL) {
2768 cur->content = xmlStrdup(content);
2769 }
2770
2773 return(cur);
2774}
2775
2786xmlNewCDataBlock(xmlDocPtr doc, const xmlChar *content, int len) {
2788
2789 /*
2790 * Allocate a new node and fill the fields.
2791 */
2792 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
2793 if (cur == NULL) {
2794 xmlTreeErrMemory("building CDATA");
2795 return(NULL);
2796 }
2797 memset(cur, 0, sizeof(xmlNode));
2799 cur->doc = doc;
2800
2801 if (content != NULL) {
2802 cur->content = xmlStrndup(content, len);
2803 }
2804
2807 return(cur);
2808}
2809
2821
2823 if (cur != NULL) cur->doc = doc;
2824 return(cur);
2825}
2826
2827static const xmlChar *_copyStringForNewDictIfNeeded(xmlDictPtr oldDict, xmlDictPtr newDict, const xmlChar *oldValue) {
2828 const xmlChar *newValue = oldValue;
2829 if (oldValue) {
2830 int oldDictOwnsOldValue = oldDict && (xmlDictOwns(oldDict, oldValue) == 1);
2831 if (oldDictOwnsOldValue) {
2832 if (newDict)
2833 newValue = xmlDictLookup(newDict, oldValue, -1);
2834 else
2835 newValue = xmlStrdup(oldValue);
2836 }
2837 }
2838 return newValue;
2839}
2840
2848void
2850 xmlAttrPtr prop;
2851
2852 if ((tree == NULL) || (tree->type == XML_NAMESPACE_DECL))
2853 return;
2854 if (tree->doc != doc) {
2855 xmlDictPtr oldTreeDict = tree->doc ? tree->doc->dict : NULL;
2856 xmlDictPtr newDict = doc ? doc->dict : NULL;
2857
2858 if(tree->type == XML_ELEMENT_NODE) {
2859 prop = tree->properties;
2860 while (prop != NULL) {
2861 if (prop->atype == XML_ATTRIBUTE_ID) {
2862 xmlRemoveID(tree->doc, prop);
2863 }
2864
2865 if (prop->doc != doc) {
2866 xmlDictPtr oldPropDict = prop->doc ? prop->doc->dict : NULL;
2867 prop->name = _copyStringForNewDictIfNeeded(oldPropDict, newDict, prop->name);
2868 prop->doc = doc;
2869 }
2870 xmlSetListDoc(prop->children, doc);
2871
2872 /*
2873 * TODO: ID attributes should be also added to the new
2874 * document, but this breaks things like xmlReplaceNode.
2875 * The underlying problem is that xmlRemoveID is only called
2876 * if a node is destroyed, not if it's unlinked.
2877 */
2878#if 0
2879 if (xmlIsID(doc, tree, prop)) {
2880 xmlChar *idVal = xmlNodeListGetString(doc, prop->children,
2881 1);
2882 xmlAddID(NULL, doc, idVal, prop);
2883 }
2884#endif
2885
2886 prop = prop->next;
2887 }
2888 }
2889 if (tree->type == XML_ENTITY_REF_NODE) {
2890 /*
2891 * Clear 'children' which points to the entity declaration
2892 * from the original document.
2893 */
2894 tree->children = NULL;
2895 } else if (tree->children != NULL) {
2896 xmlSetListDoc(tree->children, doc);
2897 }
2898
2899 tree->name = _copyStringForNewDictIfNeeded(oldTreeDict, newDict, tree->name);
2900 tree->content = (xmlChar *)_copyStringForNewDictIfNeeded(oldTreeDict, NULL, tree->content);
2901 /* FIXME: tree->ns should be updated as in xmlStaticCopyNode(). */
2902 tree->doc = doc;
2903 }
2904}
2905
2913void
2916
2917 if ((list == NULL) || (list->type == XML_NAMESPACE_DECL))
2918 return;
2919 cur = list;
2920 while (cur != NULL) {
2921 if (cur->doc != doc)
2922 xmlSetTreeDoc(cur, doc);
2923 cur = cur->next;
2924 }
2925}
2926
2927#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
2946xmlNewChild(xmlNodePtr parent, xmlNsPtr ns,
2947 const xmlChar *name, const xmlChar *content) {
2948 xmlNodePtr cur, prev;
2949
2950 if (parent == NULL) {
2951#ifdef DEBUG_TREE
2953 "xmlNewChild : parent == NULL\n");
2954#endif
2955 return(NULL);
2956 }
2957
2958 if (name == NULL) {
2959#ifdef DEBUG_TREE
2961 "xmlNewChild : name == NULL\n");
2962#endif
2963 return(NULL);
2964 }
2965
2966 /*
2967 * Allocate a new node
2968 */
2969 if (parent->type == XML_ELEMENT_NODE) {
2970 if (ns == NULL)
2971 cur = xmlNewDocNode(parent->doc, parent->ns, name, content);
2972 else
2974 } else if ((parent->type == XML_DOCUMENT_NODE) ||
2975 (parent->type == XML_HTML_DOCUMENT_NODE)) {
2976 if (ns == NULL)
2978 else
2980 } else if (parent->type == XML_DOCUMENT_FRAG_NODE) {
2981 cur = xmlNewDocNode( parent->doc, ns, name, content);
2982 } else {
2983 return(NULL);
2984 }
2985 if (cur == NULL) return(NULL);
2986
2987 /*
2988 * add the new element at the end of the children list.
2989 */
2990 cur->type = XML_ELEMENT_NODE;
2991 cur->parent = parent;
2992 cur->doc = parent->doc;
2993 if (parent->children == NULL) {
2994 parent->children = cur;
2995 parent->last = cur;
2996 } else {
2997 prev = parent->last;
2998 prev->next = cur;
2999 cur->prev = prev;
3000 parent->last = cur;
3001 }
3002
3003 return(cur);
3004}
3005#endif /* LIBXML_TREE_ENABLED */
3006
3022static xmlNodePtr
3023xmlAddPropSibling(xmlNodePtr prev, xmlNodePtr cur, xmlNodePtr prop) {
3025
3026 if ((cur == NULL) || (cur->type != XML_ATTRIBUTE_NODE) ||
3027 (prop == NULL) || (prop->type != XML_ATTRIBUTE_NODE) ||
3028 ((prev != NULL) && (prev->type != XML_ATTRIBUTE_NODE)))
3029 return(NULL);
3030
3031 /* check if an attribute with the same name exists */
3032 if (prop->ns == NULL)
3033 attr = xmlHasNsProp(cur->parent, prop->name, NULL);
3034 else
3035 attr = xmlHasNsProp(cur->parent, prop->name, prop->ns->href);
3036
3037 if (prop->doc != cur->doc) {
3038 xmlSetTreeDoc(prop, cur->doc);
3039 }
3040 prop->parent = cur->parent;
3041 prop->prev = prev;
3042 if (prev != NULL) {
3043 prop->next = prev->next;
3044 prev->next = prop;
3045 if (prop->next)
3046 prop->next->prev = prop;
3047 } else {
3048 prop->next = cur;
3049 cur->prev = prop;
3050 }
3051 if (prop->prev == NULL && prop->parent != NULL)
3052 prop->parent->properties = (xmlAttrPtr) prop;
3053 if ((attr != NULL) && (attr->type != XML_ATTRIBUTE_DECL)) {
3054 /* different instance, destroy it (attributes must be unique) */
3056 }
3057 return prop;
3058}
3059
3078 if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL)) {
3079#ifdef DEBUG_TREE
3081 "xmlAddNextSibling : cur == NULL\n");
3082#endif
3083 return(NULL);
3084 }
3085 if ((elem == NULL) || (elem->type == XML_NAMESPACE_DECL)) {
3086#ifdef DEBUG_TREE
3088 "xmlAddNextSibling : elem == NULL\n");
3089#endif
3090 return(NULL);
3091 }
3092
3093 if (cur == elem) {
3094#ifdef DEBUG_TREE
3096 "xmlAddNextSibling : cur == elem\n");
3097#endif
3098 return(NULL);
3099 }
3100
3102
3103 if (elem->type == XML_TEXT_NODE) {
3104 if (cur->type == XML_TEXT_NODE) {
3105 xmlNodeAddContent(cur, elem->content);
3107 return(cur);
3108 }
3109 if ((cur->next != NULL) && (cur->next->type == XML_TEXT_NODE) &&
3110 (cur->name == cur->next->name)) {
3111 xmlChar *tmp;
3112
3113 tmp = xmlStrdup(elem->content);
3114 tmp = xmlStrcat(tmp, cur->next->content);
3115 xmlNodeSetContent(cur->next, tmp);
3116 xmlFree(tmp);
3118 return(cur->next);
3119 }
3120 } else if (elem->type == XML_ATTRIBUTE_NODE) {
3121 return xmlAddPropSibling(cur, cur, elem);
3122 }
3123
3124 if (elem->doc != cur->doc) {
3125 xmlSetTreeDoc(elem, cur->doc);
3126 }
3127 elem->parent = cur->parent;
3128 elem->prev = cur;
3129 elem->next = cur->next;
3130 cur->next = elem;
3131 if (elem->next != NULL)
3132 elem->next->prev = elem;
3133 if ((elem->parent != NULL) && (elem->parent->last == cur))
3134 elem->parent->last = elem;
3135 return(elem);
3136}
3137
3138#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_HTML_ENABLED) || \
3139 defined(LIBXML_SCHEMAS_ENABLED) || defined(LIBXML_XINCLUDE_ENABLED)
3157xmlAddPrevSibling(xmlNodePtr cur, xmlNodePtr elem) {
3158 if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL)) {
3159#ifdef DEBUG_TREE
3161 "xmlAddPrevSibling : cur == NULL\n");
3162#endif
3163 return(NULL);
3164 }
3165 if ((elem == NULL) || (elem->type == XML_NAMESPACE_DECL)) {
3166#ifdef DEBUG_TREE
3168 "xmlAddPrevSibling : elem == NULL\n");
3169#endif
3170 return(NULL);
3171 }
3172
3173 if (cur == elem) {
3174#ifdef DEBUG_TREE
3176 "xmlAddPrevSibling : cur == elem\n");
3177#endif
3178 return(NULL);
3179 }
3180
3182
3183 if (elem->type == XML_TEXT_NODE) {
3184 if (cur->type == XML_TEXT_NODE) {
3185 xmlChar *tmp;
3186
3187 tmp = xmlStrdup(elem->content);
3188 tmp = xmlStrcat(tmp, cur->content);
3189 xmlNodeSetContent(cur, tmp);
3190 xmlFree(tmp);
3192 return(cur);
3193 }
3194 if ((cur->prev != NULL) && (cur->prev->type == XML_TEXT_NODE) &&
3195 (cur->name == cur->prev->name)) {
3196 xmlNodeAddContent(cur->prev, elem->content);
3198 return(cur->prev);
3199 }
3200 } else if (elem->type == XML_ATTRIBUTE_NODE) {
3201 return xmlAddPropSibling(cur->prev, cur, elem);
3202 }
3203
3204 if (elem->doc != cur->doc) {
3205 xmlSetTreeDoc(elem, cur->doc);
3206 }
3207 elem->parent = cur->parent;
3208 elem->next = cur;
3209 elem->prev = cur->prev;
3210 cur->prev = elem;
3211 if (elem->prev != NULL)
3212 elem->prev->next = elem;
3213 if ((elem->parent != NULL) && (elem->parent->children == cur)) {
3214 elem->parent->children = elem;
3215 }
3216 return(elem);
3217}
3218#endif /* LIBXML_TREE_ENABLED */
3219
3237
3238 if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL)) {
3239#ifdef DEBUG_TREE
3241 "xmlAddSibling : cur == NULL\n");
3242#endif
3243 return(NULL);
3244 }
3245
3246 if ((elem == NULL) || (elem->type == XML_NAMESPACE_DECL)) {
3247#ifdef DEBUG_TREE
3249 "xmlAddSibling : elem == NULL\n");
3250#endif
3251 return(NULL);
3252 }
3253
3254 if (cur == elem) {
3255#ifdef DEBUG_TREE
3257 "xmlAddSibling : cur == elem\n");
3258#endif
3259 return(NULL);
3260 }
3261
3262 /*
3263 * Constant time is we can rely on the ->parent->last to find
3264 * the last sibling.
3265 */
3266 if ((cur->type != XML_ATTRIBUTE_NODE) && (cur->parent != NULL) &&
3267 (cur->parent->children != NULL) &&
3268 (cur->parent->last != NULL) &&
3269 (cur->parent->last->next == NULL)) {
3270 cur = cur->parent->last;
3271 } else {
3272 while (cur->next != NULL) cur = cur->next;
3273 }
3274
3276
3277 if ((cur->type == XML_TEXT_NODE) && (elem->type == XML_TEXT_NODE) &&
3278 (cur->name == elem->name)) {
3279 xmlNodeAddContent(cur, elem->content);
3281 return(cur);
3282 } else if (elem->type == XML_ATTRIBUTE_NODE) {
3283 return xmlAddPropSibling(cur, cur, elem);
3284 }
3285
3286 if (elem->doc != cur->doc) {
3287 xmlSetTreeDoc(elem, cur->doc);
3288 }
3289 parent = cur->parent;
3290 elem->prev = cur;
3291 elem->next = NULL;
3292 elem->parent = parent;
3293 cur->next = elem;
3294 if (parent != NULL)
3295 parent->last = elem;
3296
3297 return(elem);
3298}
3299
3314 xmlNodePtr prev;
3315
3316 if ((parent == NULL) || (parent->type == XML_NAMESPACE_DECL)) {
3317#ifdef DEBUG_TREE
3319 "xmlAddChildList : parent == NULL\n");
3320#endif
3321 return(NULL);
3322 }
3323
3324 if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL)) {
3325#ifdef DEBUG_TREE
3327 "xmlAddChildList : child == NULL\n");
3328#endif
3329 return(NULL);
3330 }
3331
3332 if ((cur->doc != NULL) && (parent->doc != NULL) &&
3333 (cur->doc != parent->doc)) {
3334#ifdef DEBUG_TREE
3336 "Elements moved to a different document\n");
3337#endif
3338 }
3339
3340 /*
3341 * add the first element at the end of the children list.
3342 */
3343
3344 if (parent->children == NULL) {
3345 parent->children = cur;
3346 } else {
3347 /*
3348 * If cur and parent->last both are TEXT nodes, then merge them.
3349 */
3350 if ((cur->type == XML_TEXT_NODE) &&
3351 (parent->last->type == XML_TEXT_NODE) &&
3352 (cur->name == parent->last->name)) {
3353 xmlNodeAddContent(parent->last, cur->content);
3354 /*
3355 * if it's the only child, nothing more to be done.
3356 */
3357 if (cur->next == NULL) {
3359 return(parent->last);
3360 }
3361 prev = cur;
3362 cur = cur->next;
3363 xmlFreeNode(prev);
3364 }
3365 prev = parent->last;
3366 prev->next = cur;
3367 cur->prev = prev;
3368 }
3369 while (cur->next != NULL) {
3370 cur->parent = parent;
3371 if (cur->doc != parent->doc) {
3372 xmlSetTreeDoc(cur, parent->doc);
3373 }
3374 cur = cur->next;
3375 }
3376 cur->parent = parent;
3377 /* the parent may not be linked to a doc ! */
3378 if (cur->doc != parent->doc) {
3379 xmlSetTreeDoc(cur, parent->doc);
3380 }
3381 parent->last = cur;
3382
3383 return(cur);
3384}
3385
3406 xmlNodePtr prev;
3407
3408 if ((parent == NULL) || (parent->type == XML_NAMESPACE_DECL)) {
3409#ifdef DEBUG_TREE
3411 "xmlAddChild : parent == NULL\n");
3412#endif
3413 return(NULL);
3414 }
3415
3416 if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL)) {
3417#ifdef DEBUG_TREE
3419 "xmlAddChild : child == NULL\n");
3420#endif
3421 return(NULL);
3422 }
3423
3424 if (parent == cur) {
3425#ifdef DEBUG_TREE
3427 "xmlAddChild : parent == cur\n");
3428#endif
3429 return(NULL);
3430 }
3431 /*
3432 * If cur is a TEXT node, merge its content with adjacent TEXT nodes
3433 * cur is then freed.
3434 */
3435 if (cur->type == XML_TEXT_NODE) {
3436 if ((parent->type == XML_TEXT_NODE) &&
3437 (parent->content != NULL) &&
3438 (parent->name == cur->name)) {
3439 xmlNodeAddContent(parent, cur->content);
3441 return(parent);
3442 }
3443 if ((parent->last != NULL) && (parent->last->type == XML_TEXT_NODE) &&
3444 (parent->last->name == cur->name) &&
3445 (parent->last != cur)) {
3446 xmlNodeAddContent(parent->last, cur->content);
3448 return(parent->last);
3449 }
3450 }
3451
3452 /*
3453 * add the new element at the end of the children list.
3454 */
3455 prev = cur->parent;
3456 cur->parent = parent;
3457 if (cur->doc != parent->doc) {
3458 xmlSetTreeDoc(cur, parent->doc);
3459 }
3460 /* this check prevents a loop on tree-traversions if a developer
3461 * tries to add a node to its parent multiple times
3462 */
3463 if (prev == parent)
3464 return(cur);
3465
3466 /*
3467 * Coalescing
3468 */
3469 if ((parent->type == XML_TEXT_NODE) &&
3470 (parent->content != NULL) &&
3471 (parent != cur)) {
3472 xmlNodeAddContent(parent, cur->content);
3474 return(parent);
3475 }
3476 if (cur->type == XML_ATTRIBUTE_NODE) {
3477 if (parent->type != XML_ELEMENT_NODE)
3478 return(NULL);
3479 if (parent->properties != NULL) {
3480 /* check if an attribute with the same name exists */
3481 xmlAttrPtr lastattr;
3482
3483 if (cur->ns == NULL)
3484 lastattr = xmlHasNsProp(parent, cur->name, NULL);
3485 else
3486 lastattr = xmlHasNsProp(parent, cur->name, cur->ns->href);
3487 if ((lastattr != NULL) && (lastattr != (xmlAttrPtr) cur) && (lastattr->type != XML_ATTRIBUTE_DECL)) {
3488 /* different instance, destroy it (attributes must be unique) */
3489 xmlUnlinkNode((xmlNodePtr) lastattr);
3490 xmlFreeProp(lastattr);
3491 }
3492 if (lastattr == (xmlAttrPtr) cur)
3493 return(cur);
3494
3495 }
3496 if (parent->properties == NULL) {
3497 parent->properties = (xmlAttrPtr) cur;
3498 } else {
3499 /* find the end */
3500 xmlAttrPtr lastattr = parent->properties;
3501 while (lastattr->next != NULL) {
3502 lastattr = lastattr->next;
3503 }
3504 lastattr->next = (xmlAttrPtr) cur;
3505 ((xmlAttrPtr) cur)->prev = lastattr;
3506 }
3507 } else {
3508 if (parent->children == NULL) {
3509 parent->children = cur;
3510 parent->last = cur;
3511 } else {
3512 prev = parent->last;
3513 prev->next = cur;
3514 cur->prev = prev;
3515 parent->last = cur;
3516 }
3517 }
3518 return(cur);
3519}
3520
3530 if ((parent == NULL) || (parent->type == XML_NAMESPACE_DECL)) {
3531#ifdef DEBUG_TREE
3533 "xmlGetLastChild : parent == NULL\n");
3534#endif
3535 return(NULL);
3536 }
3537 return(parent->last);
3538}
3539
3540#ifdef LIBXML_TREE_ENABLED
3541/*
3542 * 5 interfaces from DOM ElementTraversal
3543 */
3544
3557unsigned long
3558xmlChildElementCount(xmlNodePtr parent) {
3559 unsigned long ret = 0;
3561
3562 if (parent == NULL)
3563 return(0);
3564 switch (parent->type) {
3565 case XML_ELEMENT_NODE:
3566 case XML_ENTITY_NODE:
3567 case XML_DOCUMENT_NODE:
3570 cur = parent->children;
3571 break;
3572 default:
3573 return(0);
3574 }
3575 while (cur != NULL) {
3576 if (cur->type == XML_ELEMENT_NODE)
3577 ret++;
3578 cur = cur->next;
3579 }
3580 return(ret);
3581}
3582
3595xmlFirstElementChild(xmlNodePtr parent) {
3597
3598 if (parent == NULL)
3599 return(NULL);
3600 switch (parent->type) {
3601 case XML_ELEMENT_NODE:
3602 case XML_ENTITY_NODE:
3603 case XML_DOCUMENT_NODE:
3606 cur = parent->children;
3607 break;
3608 default:
3609 return(NULL);
3610 }
3611 while (cur != NULL) {
3612 if (cur->type == XML_ELEMENT_NODE)
3613 return(cur);
3614 cur = cur->next;
3615 }
3616 return(NULL);
3617}
3618
3631xmlLastElementChild(xmlNodePtr parent) {
3633
3634 if (parent == NULL)
3635 return(NULL);
3636 switch (parent->type) {
3637 case XML_ELEMENT_NODE:
3638 case XML_ENTITY_NODE:
3639 case XML_DOCUMENT_NODE:
3642 cur = parent->last;
3643 break;
3644 default:
3645 return(NULL);
3646 }
3647 while (cur != NULL) {
3648 if (cur->type == XML_ELEMENT_NODE)
3649 return(cur);
3650 cur = cur->prev;
3651 }
3652 return(NULL);
3653}
3654
3668xmlPreviousElementSibling(xmlNodePtr node) {
3669 if (node == NULL)
3670 return(NULL);
3671 switch (node->type) {
3672 case XML_ELEMENT_NODE:
3673 case XML_TEXT_NODE:
3676 case XML_ENTITY_NODE:
3677 case XML_PI_NODE:
3678 case XML_COMMENT_NODE:
3679 case XML_XINCLUDE_START:
3680 case XML_XINCLUDE_END:
3681 node = node->prev;
3682 break;
3683 default:
3684 return(NULL);
3685 }
3686 while (node != NULL) {
3687 if (node->type == XML_ELEMENT_NODE)
3688 return(node);
3689 node = node->prev;
3690 }
3691 return(NULL);
3692}
3693
3707xmlNextElementSibling(xmlNodePtr node) {
3708 if (node == NULL)
3709 return(NULL);
3710 switch (node->type) {
3711 case XML_ELEMENT_NODE:
3712 case XML_TEXT_NODE:
3715 case XML_ENTITY_NODE:
3716 case XML_PI_NODE:
3717 case XML_COMMENT_NODE:
3718 case XML_DTD_NODE:
3719 case XML_XINCLUDE_START:
3720 case XML_XINCLUDE_END:
3721 node = node->next;
3722 break;
3723 default:
3724 return(NULL);
3725 }
3726 while (node != NULL) {
3727 if (node->type == XML_ELEMENT_NODE)
3728 return(node);
3729 node = node->next;
3730 }
3731 return(NULL);
3732}
3733
3734#endif /* LIBXML_TREE_ENABLED */
3735
3743void
3747 xmlDictPtr dict = NULL;
3748 size_t depth = 0;
3749
3750 if (cur == NULL) return;
3751 if (cur->type == XML_NAMESPACE_DECL) {
3753 return;
3754 }
3755 if (cur->doc != NULL) dict = cur->doc->dict;
3756 while (1) {
3757 while ((cur->children != NULL) &&
3758 (cur->type != XML_DOCUMENT_NODE) &&
3759 (cur->type != XML_HTML_DOCUMENT_NODE) &&
3760 (cur->type != XML_DTD_NODE) &&
3761 (cur->type != XML_ENTITY_REF_NODE)) {
3762 cur = cur->children;
3763 depth += 1;
3764 }
3765
3766 next = cur->next;
3767 parent = cur->parent;
3768 if ((cur->type == XML_DOCUMENT_NODE) ||
3769 (cur->type == XML_HTML_DOCUMENT_NODE)) {
3771 } else if (cur->type != XML_DTD_NODE) {
3772
3775
3776 if (((cur->type == XML_ELEMENT_NODE) ||
3777 (cur->type == XML_XINCLUDE_START) ||
3778 (cur->type == XML_XINCLUDE_END)) &&
3779 (cur->properties != NULL))
3780 xmlFreePropList(cur->properties);
3781 if ((cur->type != XML_ELEMENT_NODE) &&
3782 (cur->type != XML_XINCLUDE_START) &&
3783 (cur->type != XML_XINCLUDE_END) &&
3784 (cur->type != XML_ENTITY_REF_NODE) &&
3785 (cur->content != (xmlChar *) &(cur->properties))) {
3786 DICT_FREE(cur->content)
3787 }
3788 if (((cur->type == XML_ELEMENT_NODE) ||
3789 (cur->type == XML_XINCLUDE_START) ||
3790 (cur->type == XML_XINCLUDE_END)) &&
3791 (cur->nsDef != NULL))
3792 xmlFreeNsList(cur->nsDef);
3793
3794 /*
3795 * When a node is a text node or a comment, it uses a global static
3796 * variable for the name of the node.
3797 * Otherwise the node name might come from the document's
3798 * dictionary
3799 */
3800 if ((cur->name != NULL) &&
3801 (cur->type != XML_TEXT_NODE) &&
3802 (cur->type != XML_COMMENT_NODE))
3803 DICT_FREE(cur->name)
3804 xmlFree(cur);
3805 }
3806
3807 if (next != NULL) {
3808 cur = next;
3809 } else {
3810 if ((depth == 0) || (parent == NULL))
3811 break;
3812 depth -= 1;
3813 cur = parent;
3814 cur->children = NULL;
3815 }
3816 }
3817}
3818
3826void
3828 xmlDictPtr dict = NULL;
3829
3830 if (cur == NULL) return;
3831
3832 /* use xmlFreeDtd for DTD nodes */
3833 if (cur->type == XML_DTD_NODE) {
3835 return;
3836 }
3837 if (cur->type == XML_NAMESPACE_DECL) {
3839 return;
3840 }
3841 if (cur->type == XML_ATTRIBUTE_NODE) {
3843 return;
3844 }
3845
3848
3849 if (cur->doc != NULL) dict = cur->doc->dict;
3850
3851 if (cur->type == XML_ENTITY_DECL) {
3853 DICT_FREE(ent->SystemID);
3854 DICT_FREE(ent->ExternalID);
3855 }
3856 if ((cur->children != NULL) &&
3857 (cur->type != XML_ENTITY_REF_NODE))
3858 xmlFreeNodeList(cur->children);
3859
3860 if ((cur->type == XML_ELEMENT_NODE) ||
3861 (cur->type == XML_XINCLUDE_START) ||
3862 (cur->type == XML_XINCLUDE_END)) {
3863 if (cur->properties != NULL)
3864 xmlFreePropList(cur->properties);
3865 if (cur->nsDef != NULL)
3866 xmlFreeNsList(cur->nsDef);
3867 } else if ((cur->content != NULL) &&
3868 (cur->type != XML_ENTITY_REF_NODE) &&
3869 (cur->content != (xmlChar *) &(cur->properties))) {
3870 DICT_FREE(cur->content)
3871 }
3872
3873 /*
3874 * When a node is a text node or a comment, it uses a global static
3875 * variable for the name of the node.
3876 * Otherwise the node name might come from the document's dictionary
3877 */
3878 if ((cur->name != NULL) &&
3879 (cur->type != XML_TEXT_NODE) &&
3880 (cur->type != XML_COMMENT_NODE))
3881 DICT_FREE(cur->name)
3882
3883 xmlFree(cur);
3884}
3885
3896void
3898 if (cur == NULL) {
3899#ifdef DEBUG_TREE
3901 "xmlUnlinkNode : node == NULL\n");
3902#endif
3903 return;
3904 }
3905 if (cur->type == XML_NAMESPACE_DECL)
3906 return;
3907 if (cur->type == XML_DTD_NODE) {
3908 xmlDocPtr doc;
3909 doc = cur->doc;
3910 if (doc != NULL) {
3911 if (doc->intSubset == (xmlDtdPtr) cur)
3912 doc->intSubset = NULL;
3913 if (doc->extSubset == (xmlDtdPtr) cur)
3914 doc->extSubset = NULL;
3915 }
3916 }
3917 if (cur->type == XML_ENTITY_DECL) {
3918 xmlDocPtr doc;
3919 doc = cur->doc;
3920 if (doc != NULL) {
3921 if (doc->intSubset != NULL) {
3922 if (xmlHashLookup(doc->intSubset->entities, cur->name) == cur)
3923 xmlHashRemoveEntry(doc->intSubset->entities, cur->name,
3924 NULL);
3925 if (xmlHashLookup(doc->intSubset->pentities, cur->name) == cur)
3926 xmlHashRemoveEntry(doc->intSubset->pentities, cur->name,
3927 NULL);
3928 }
3929 if (doc->extSubset != NULL) {
3930 if (xmlHashLookup(doc->extSubset->entities, cur->name) == cur)
3931 xmlHashRemoveEntry(doc->extSubset->entities, cur->name,
3932 NULL);
3933 if (xmlHashLookup(doc->extSubset->pentities, cur->name) == cur)
3934 xmlHashRemoveEntry(doc->extSubset->pentities, cur->name,
3935 NULL);
3936 }
3937 }
3938 }
3939 if (cur->parent != NULL) {
3941 parent = cur->parent;
3942 if (cur->type == XML_ATTRIBUTE_NODE) {
3943 if (parent->properties == (xmlAttrPtr) cur)
3944 parent->properties = ((xmlAttrPtr) cur)->next;
3945 } else {
3946 if (parent->children == cur)
3947 parent->children = cur->next;
3948 if (parent->last == cur)
3949 parent->last = cur->prev;
3950 }
3951 cur->parent = NULL;
3952 }
3953 if (cur->next != NULL)
3954 cur->next->prev = cur->prev;
3955 if (cur->prev != NULL)
3956 cur->prev->next = cur->next;
3957 cur->next = cur->prev = NULL;
3958}
3959
3960#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_WRITER_ENABLED)
3975xmlReplaceNode(xmlNodePtr old, xmlNodePtr cur) {
3976 if (old == cur) return(NULL);
3977 if ((old == NULL) || (old->type == XML_NAMESPACE_DECL) ||
3978 (old->parent == NULL)) {
3979#ifdef DEBUG_TREE
3981 "xmlReplaceNode : old == NULL or without parent\n");
3982#endif
3983 return(NULL);
3984 }
3985 if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL)) {
3986 xmlUnlinkNode(old);
3987 return(old);
3988 }
3989 if (cur == old) {
3990 return(old);
3991 }
3992 if ((old->type==XML_ATTRIBUTE_NODE) && (cur->type!=XML_ATTRIBUTE_NODE)) {
3993#ifdef DEBUG_TREE
3995 "xmlReplaceNode : Trying to replace attribute node with other node type\n");
3996#endif
3997 return(old);
3998 }
3999 if ((cur->type==XML_ATTRIBUTE_NODE) && (old->type!=XML_ATTRIBUTE_NODE)) {
4000#ifdef DEBUG_TREE
4002 "xmlReplaceNode : Trying to replace a non-attribute node with attribute node\n");
4003#endif
4004 return(old);
4005 }
4007 xmlSetTreeDoc(cur, old->doc);
4008 cur->parent = old->parent;
4009 cur->next = old->next;
4010 if (cur->next != NULL)
4011 cur->next->prev = cur;
4012 cur->prev = old->prev;
4013 if (cur->prev != NULL)
4014 cur->prev->next = cur;
4015 if (cur->parent != NULL) {
4016 if (cur->type == XML_ATTRIBUTE_NODE) {
4017 if (cur->parent->properties == (xmlAttrPtr)old)
4018 cur->parent->properties = ((xmlAttrPtr) cur);
4019 } else {
4020 if (cur->parent->children == old)
4021 cur->parent->children = cur;
4022 if (cur->parent->last == old)
4023 cur->parent->last = cur;
4024 }
4025 }
4026 old->next = old->prev = NULL;
4027 old->parent = NULL;
4028 return(old);
4029}
4030#endif /* LIBXML_TREE_ENABLED */
4031
4032/************************************************************************
4033 * *
4034 * Copy operations *
4035 * *
4036 ************************************************************************/
4037
4048 xmlNsPtr ret;
4049
4050 if (cur == NULL) return(NULL);
4051 switch (cur->type) {
4053 ret = xmlNewNs(NULL, cur->href, cur->prefix);
4054 break;
4055 default:
4056#ifdef DEBUG_TREE
4058 "xmlCopyNamespace: invalid type %d\n", cur->type);
4059#endif
4060 return(NULL);
4061 }
4062 return(ret);
4063}
4064
4075 xmlNsPtr ret = NULL;
4076 xmlNsPtr p = NULL,q;
4077
4078 while (cur != NULL) {
4080 if (p == NULL) {
4081 ret = p = q;
4082 } else {
4083 p->next = q;
4084 p = q;
4085 }
4086 cur = cur->next;
4087 }
4088 return(ret);
4089}
4090
4091static xmlNodePtr
4092xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent);
4093
4094static xmlAttrPtr
4095xmlCopyPropInternal(xmlDocPtr doc, xmlNodePtr target, xmlAttrPtr cur) {
4097
4098 if (cur == NULL) return(NULL);
4099 if ((target != NULL) && (target->type != XML_ELEMENT_NODE))
4100 return(NULL);
4101 if (target != NULL)
4102 ret = xmlNewDocProp(target->doc, cur->name, NULL);
4103 else if (doc != NULL)
4104 ret = xmlNewDocProp(doc, cur->name, NULL);
4105 else if (cur->parent != NULL)
4106 ret = xmlNewDocProp(cur->parent->doc, cur->name, NULL);
4107 else if (cur->children != NULL)
4108 ret = xmlNewDocProp(cur->children->doc, cur->name, NULL);
4109 else
4110 ret = xmlNewDocProp(NULL, cur->name, NULL);
4111 if (ret == NULL) return(NULL);
4112 ret->parent = target;
4113
4114 if ((cur->ns != NULL) && (target != NULL)) {
4115 xmlNsPtr ns;
4116
4117 ns = xmlSearchNs(target->doc, target, cur->ns->prefix);
4118 if (ns == NULL) {
4119 /*
4120 * Humm, we are copying an element whose namespace is defined
4121 * out of the new tree scope. Search it in the original tree
4122 * and add it at the top of the new tree
4123 */
4124 ns = xmlSearchNs(cur->doc, cur->parent, cur->ns->prefix);
4125 if (ns != NULL) {
4127 xmlNodePtr pred = NULL;
4128
4129 while (root->parent != NULL) {
4130 pred = root;
4131 root = root->parent;
4132 }
4133 if (root == (xmlNodePtr) target->doc) {
4134 /* correct possibly cycling above the document elt */
4135 root = pred;
4136 }
4137 ret->ns = xmlNewNs(root, ns->href, ns->prefix);
4138 }
4139 } else {
4140 /*
4141 * we have to find something appropriate here since
4142 * we can't be sure, that the namespace we found is identified
4143 * by the prefix
4144 */
4145 if (xmlStrEqual(ns->href, cur->ns->href)) {
4146 /* this is the nice case */
4147 ret->ns = ns;
4148 } else {
4149 /*
4150 * we are in trouble: we need a new reconciled namespace.
4151 * This is expensive
4152 */
4153 ret->ns = xmlNewReconciledNs(target->doc, target, cur->ns);
4154 }
4155 }
4156
4157 } else
4158 ret->ns = NULL;
4159
4160 if (cur->children != NULL) {
4161 xmlNodePtr tmp;
4162
4163 ret->children = xmlStaticCopyNodeList(cur->children, ret->doc, (xmlNodePtr) ret);
4164 ret->last = NULL;
4165 tmp = ret->children;
4166 while (tmp != NULL) {
4167 /* tmp->parent = (xmlNodePtr)ret; */
4168 if (tmp->next == NULL)
4169 ret->last = tmp;
4170 tmp = tmp->next;
4171 }
4172 }
4173 /*
4174 * Try to handle IDs
4175 */
4176 if ((target!= NULL) && (cur!= NULL) &&
4177 (target->doc != NULL) && (cur->doc != NULL) &&
4178 (cur->doc->ids != NULL) && (cur->parent != NULL)) {
4179 if (xmlIsID(cur->doc, cur->parent, cur)) {
4180 xmlChar *id;
4181
4182 id = xmlNodeListGetString(cur->doc, cur->children, 1);
4183 if (id != NULL) {
4184 xmlAddID(NULL, target->doc, id, ret);
4185 xmlFree(id);
4186 }
4187 }
4188 }
4189 return(ret);
4190}
4191
4203 return xmlCopyPropInternal(NULL, target, cur);
4204}
4205
4218 xmlAttrPtr p = NULL,q;
4219
4220 if ((target != NULL) && (target->type != XML_ELEMENT_NODE))
4221 return(NULL);
4222 while (cur != NULL) {
4223 q = xmlCopyProp(target, cur);
4224 if (q == NULL)
4225 return(NULL);
4226 if (p == NULL) {
4227 ret = p = q;
4228 } else {
4229 p->next = q;
4230 q->prev = p;
4231 p = q;
4232 }
4233 cur = cur->next;
4234 }
4235 return(ret);
4236}
4237
4238/*
4239 * NOTE about the CopyNode operations !
4240 *
4241 * They are split into external and internal parts for one
4242 * tricky reason: namespaces. Doing a direct copy of a node
4243 * say RPM:Copyright without changing the namespace pointer to
4244 * something else can produce stale links. One way to do it is
4245 * to keep a reference counter but this doesn't work as soon
4246 * as one moves the element or the subtree out of the scope of
4247 * the existing namespace. The actual solution seems to be to add
4248 * a copy of the namespace at the top of the copied tree if
4249 * not available in the subtree.
4250 * Hence two functions, the public front-end call the inner ones
4251 * The argument "recursive" normally indicates a recursive copy
4252 * of the node with values 0 (no) and 1 (yes). For XInclude,
4253 * however, we allow a value of 2 to indicate copy properties and
4254 * namespace info, but don't recurse on children.
4255 */
4256
4257static xmlNodePtr
4258xmlStaticCopyNode(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent,
4259 int extended) {
4261
4262 if (node == NULL) return(NULL);
4263 switch (node->type) {
4264 case XML_TEXT_NODE:
4266 case XML_ELEMENT_NODE:
4269 case XML_ENTITY_NODE:
4270 case XML_PI_NODE:
4271 case XML_COMMENT_NODE:
4272 case XML_XINCLUDE_START:
4273 case XML_XINCLUDE_END:
4274 break;
4275 case XML_ATTRIBUTE_NODE:
4276 return((xmlNodePtr) xmlCopyPropInternal(doc, parent, (xmlAttrPtr) node));
4277 case XML_NAMESPACE_DECL:
4279
4280 case XML_DOCUMENT_NODE:
4282#ifdef LIBXML_TREE_ENABLED
4283 return((xmlNodePtr) xmlCopyDoc((xmlDocPtr) node, extended));
4284#endif /* LIBXML_TREE_ENABLED */
4286 case XML_NOTATION_NODE:
4287 case XML_DTD_NODE:
4288 case XML_ELEMENT_DECL:
4289 case XML_ATTRIBUTE_DECL:
4290 case XML_ENTITY_DECL:
4291 return(NULL);
4292 }
4293
4294 /*
4295 * Allocate a new node and fill the fields.
4296 */
4297 ret = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
4298 if (ret == NULL) {
4299 xmlTreeErrMemory("copying node");
4300 return(NULL);
4301 }
4302 memset(ret, 0, sizeof(xmlNode));
4303 ret->type = node->type;
4304
4305 ret->doc = doc;
4306 ret->parent = parent;
4307 if (node->name == xmlStringText)
4308 ret->name = xmlStringText;
4309 else if (node->name == xmlStringTextNoenc)
4310 ret->name = xmlStringTextNoenc;
4311 else if (node->name == xmlStringComment)
4312 ret->name = xmlStringComment;
4313 else if (node->name != NULL) {
4314 if ((doc != NULL) && (doc->dict != NULL))
4315 ret->name = xmlDictLookup(doc->dict, node->name, -1);
4316 else
4317 ret->name = xmlStrdup(node->name);
4318 }
4319 if ((node->type != XML_ELEMENT_NODE) &&
4320 (node->content != NULL) &&
4321 (node->type != XML_ENTITY_REF_NODE) &&
4322 (node->type != XML_XINCLUDE_END) &&
4323 (node->type != XML_XINCLUDE_START)) {
4324 ret->content = xmlStrdup(node->content);
4325 }else{
4326 if (node->type == XML_ELEMENT_NODE)
4327 ret->line = node->line;
4328 }
4329 if (parent != NULL) {
4330 xmlNodePtr tmp;
4331
4332 /*
4333 * this is a tricky part for the node register thing:
4334 * in case ret does get coalesced in xmlAddChild
4335 * the deregister-node callback is called; so we register ret now already
4336 */
4339
4340 /*
4341 * Note that since ret->parent is already set, xmlAddChild will
4342 * return early and not actually insert the node. It will only
4343 * coalesce text nodes and unnecessarily call xmlSetTreeDoc.
4344 * Assuming that the subtree to be copied always has its text
4345 * nodes coalesced, the somewhat confusing call to xmlAddChild
4346 * could be removed.
4347 */
4348 tmp = xmlAddChild(parent, ret);
4349 /* node could have coalesced */
4350 if (tmp != ret)
4351 return(tmp);
4352 }
4353
4354 if (!extended)
4355 goto out;
4356 if (((node->type == XML_ELEMENT_NODE) ||
4357 (node->type == XML_XINCLUDE_START)) && (node->nsDef != NULL))
4358 ret->nsDef = xmlCopyNamespaceList(node->nsDef);
4359
4360 if (node->ns != NULL) {
4361 xmlNsPtr ns;
4362
4363 ns = xmlSearchNs(doc, ret, node->ns->prefix);
4364 if (ns == NULL) {
4365 /*
4366 * Humm, we are copying an element whose namespace is defined
4367 * out of the new tree scope. Search it in the original tree
4368 * and add it at the top of the new tree
4369 */
4370 ns = xmlSearchNs(node->doc, node, node->ns->prefix);
4371 if (ns != NULL) {
4373
4374 while (root->parent != NULL) root = root->parent;
4375 ret->ns = xmlNewNs(root, ns->href, ns->prefix);
4376 } else {
4377 ret->ns = xmlNewReconciledNs(doc, ret, node->ns);
4378 }
4379 } else {
4380 /*
4381 * reference the existing namespace definition in our own tree.
4382 */
4383 ret->ns = ns;
4384 }
4385 }
4386 if (((node->type == XML_ELEMENT_NODE) ||
4387 (node->type == XML_XINCLUDE_START)) && (node->properties != NULL))
4388 ret->properties = xmlCopyPropList(ret, node->properties);
4389 if (node->type == XML_ENTITY_REF_NODE) {
4390 if ((doc == NULL) || (node->doc != doc)) {
4391 /*
4392 * The copied node will go into a separate document, so
4393 * to avoid dangling references to the ENTITY_DECL node
4394 * we cannot keep the reference. Try to find it in the
4395 * target document.
4396 */
4397 ret->children = (xmlNodePtr) xmlGetDocEntity(doc, ret->name);
4398 } else {
4399 ret->children = node->children;
4400 }
4401 ret->last = ret->children;
4402 } else if ((node->children != NULL) && (extended != 2)) {
4404
4405 cur = node->children;
4406 insert = ret;
4407 while (cur != NULL) {
4408 xmlNodePtr copy = xmlStaticCopyNode(cur, doc, insert, 2);
4409 if (copy == NULL) {
4411 return(NULL);
4412 }
4413
4414 /* Check for coalesced text nodes */
4415 if (insert->last != copy) {
4416 if (insert->last == NULL) {
4417 insert->children = copy;
4418 } else {
4419 copy->prev = insert->last;
4420 insert->last->next = copy;
4421 }
4422 insert->last = copy;
4423 }
4424
4425 if ((cur->type != XML_ENTITY_REF_NODE) &&
4426 (cur->children != NULL)) {
4427 cur = cur->children;
4428 insert = copy;
4429 continue;
4430 }
4431
4432 while (1) {
4433 if (cur->next != NULL) {
4434 cur = cur->next;
4435 break;
4436 }
4437
4438 cur = cur->parent;
4439 insert = insert->parent;
4440 if (cur == node) {
4441 cur = NULL;
4442 break;
4443 }
4444 }
4445 }
4446 }
4447
4448out:
4449 /* if parent != NULL we already registered the node above */
4450 if ((parent == NULL) &&
4453 return(ret);
4454}
4455
4456static xmlNodePtr
4457xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent) {
4459 xmlNodePtr p = NULL,q;
4460
4461 while (node != NULL) {
4462#ifdef LIBXML_TREE_ENABLED
4463 if (node->type == XML_DTD_NODE ) {
4464 if (doc == NULL) {
4465 node = node->next;
4466 continue;
4467 }
4468 if (doc->intSubset == NULL) {
4469 q = (xmlNodePtr) xmlCopyDtd( (xmlDtdPtr) node );
4470 if (q == NULL) return(NULL);
4471 q->doc = doc;
4472 q->parent = parent;
4473 doc->intSubset = (xmlDtdPtr) q;
4475 } else {
4476 q = (xmlNodePtr) doc->intSubset;
4478 }
4479 } else
4480#endif /* LIBXML_TREE_ENABLED */
4481 q = xmlStaticCopyNode(node, doc, parent, 1);
4482 if (q == NULL) return(NULL);
4483 if (ret == NULL) {
4484 q->prev = NULL;
4485 ret = p = q;
4486 } else if (p != q) {
4487 /* the test is required if xmlStaticCopyNode coalesced 2 text nodes */
4488 p->next = q;
4489 q->prev = p;
4490 p = q;
4491 }
4492 node = node->next;
4493 }
4494 return(ret);
4495}
4496
4509xmlCopyNode(xmlNodePtr node, int extended) {
4511
4512 ret = xmlStaticCopyNode(node, NULL, NULL, extended);
4513 return(ret);
4514}
4515
4529xmlDocCopyNode(xmlNodePtr node, xmlDocPtr doc, int extended) {
4531
4532 ret = xmlStaticCopyNode(node, doc, NULL, extended);
4533 return(ret);
4534}
4535
4546 xmlNodePtr ret = xmlStaticCopyNodeList(node, doc, NULL);
4547 return(ret);
4548}
4549
4560 xmlNodePtr ret = xmlStaticCopyNodeList(node, NULL, NULL);
4561 return(ret);
4562}
4563
4564#if defined(LIBXML_TREE_ENABLED)
4574xmlCopyDtd(xmlDtdPtr dtd) {
4575 xmlDtdPtr ret;
4576 xmlNodePtr cur, p = NULL, q;
4577
4578 if (dtd == NULL) return(NULL);
4579 ret = xmlNewDtd(NULL, dtd->name, dtd->ExternalID, dtd->SystemID);
4580 if (ret == NULL) return(NULL);
4581 if (dtd->entities != NULL)
4582 ret->entities = (void *) xmlCopyEntitiesTable(
4584 if (dtd->notations != NULL)
4585 ret->notations = (void *) xmlCopyNotationTable(
4587 if (dtd->elements != NULL)
4588 ret->elements = (void *) xmlCopyElementTable(
4590 if (dtd->attributes != NULL)
4591 ret->attributes = (void *) xmlCopyAttributeTable(
4593 if (dtd->pentities != NULL)
4594 ret->pentities = (void *) xmlCopyEntitiesTable(
4596
4597 cur = dtd->children;
4598 while (cur != NULL) {
4599 q = NULL;
4600
4601 if (cur->type == XML_ENTITY_DECL) {
4603 switch (tmp->etype) {
4607 q = (xmlNodePtr) xmlGetEntityFromDtd(ret, tmp->name);
4608 break;
4611 q = (xmlNodePtr)
4612 xmlGetParameterEntityFromDtd(ret, tmp->name);
4613 break;
4615 break;
4616 }
4617 } else if (cur->type == XML_ELEMENT_DECL) {
4619 q = (xmlNodePtr)
4620 xmlGetDtdQElementDesc(ret, tmp->name, tmp->prefix);
4621 } else if (cur->type == XML_ATTRIBUTE_DECL) {
4623 q = (xmlNodePtr)
4624 xmlGetDtdQAttrDesc(ret, tmp->elem, tmp->name, tmp->prefix);
4625 } else if (cur->type == XML_COMMENT_NODE) {
4626 q = xmlCopyNode(cur, 0);
4627 }
4628
4629 if (q == NULL) {
4630 cur = cur->next;
4631 continue;
4632 }
4633
4634 if (p == NULL)
4635 ret->children = q;
4636 else
4637 p->next = q;
4638
4639 q->prev = p;
4640 q->parent = (xmlNodePtr) ret;
4641 q->next = NULL;
4642 ret->last = q;
4643 p = q;
4644 cur = cur->next;
4645 }
4646
4647 return(ret);
4648}
4649#endif
4650
4651#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
4663xmlCopyDoc(xmlDocPtr doc, int recursive) {
4664 xmlDocPtr ret;
4665
4666 if (doc == NULL) return(NULL);
4667 ret = xmlNewDoc(doc->version);
4668 if (ret == NULL) return(NULL);
4669 ret->type = doc->type;
4670 if (doc->name != NULL)
4671 ret->name = xmlMemStrdup(doc->name);
4672 if (doc->encoding != NULL)
4673 ret->encoding = xmlStrdup(doc->encoding);
4674 if (doc->URL != NULL)
4675 ret->URL = xmlStrdup(doc->URL);
4676 ret->charset = doc->charset;
4677 ret->compression = doc->compression;
4678 ret->standalone = doc->standalone;
4679 if (!recursive) return(ret);
4680
4681 ret->last = NULL;
4682 ret->children = NULL;
4683#ifdef LIBXML_TREE_ENABLED
4684 if (doc->intSubset != NULL) {
4685 ret->intSubset = xmlCopyDtd(doc->intSubset);
4686 if (ret->intSubset == NULL) {
4687 xmlFreeDoc(ret);
4688 return(NULL);
4689 }
4690 xmlSetTreeDoc((xmlNodePtr)ret->intSubset, ret);
4691 ret->intSubset->parent = ret;
4692 }
4693#endif
4694 if (doc->oldNs != NULL)
4695 ret->oldNs = xmlCopyNamespaceList(doc->oldNs);
4696 if (doc->children != NULL) {
4697 xmlNodePtr tmp;
4698
4699 ret->children = xmlStaticCopyNodeList(doc->children, ret,
4700 (xmlNodePtr)ret);
4701 ret->last = NULL;
4702 tmp = ret->children;
4703 while (tmp != NULL) {
4704 if (tmp->next == NULL)
4705 ret->last = tmp;
4706 tmp = tmp->next;
4707 }
4708 }
4709 return(ret);
4710}
4711#endif /* LIBXML_TREE_ENABLED */
4712
4713/************************************************************************
4714 * *
4715 * Content access functions *
4716 * *
4717 ************************************************************************/
4718
4729static long
4730xmlGetLineNoInternal(const xmlNode *node, int depth)
4731{
4732 long result = -1;
4733
4734 if (depth >= 5)
4735 return(-1);
4736
4737 if (!node)
4738 return result;
4739 if ((node->type == XML_ELEMENT_NODE) ||
4740 (node->type == XML_TEXT_NODE) ||
4741 (node->type == XML_COMMENT_NODE) ||
4742 (node->type == XML_PI_NODE)) {
4743 if (node->line == 65535) {
4744 if ((node->type == XML_TEXT_NODE) && (node->psvi != NULL))
4745 result = (long) (ptrdiff_t) node->psvi;
4746 else if ((node->type == XML_ELEMENT_NODE) &&
4747 (node->children != NULL))
4748 result = xmlGetLineNoInternal(node->children, depth + 1);
4749 else if (node->next != NULL)
4750 result = xmlGetLineNoInternal(node->next, depth + 1);
4751 else if (node->prev != NULL)
4752 result = xmlGetLineNoInternal(node->prev, depth + 1);
4753 }
4754 if ((result == -1) || (result == 65535))
4755 result = (long) node->line;
4756 } else if ((node->prev != NULL) &&
4757 ((node->prev->type == XML_ELEMENT_NODE) ||
4758 (node->prev->type == XML_TEXT_NODE) ||
4759 (node->prev->type == XML_COMMENT_NODE) ||
4760 (node->prev->type == XML_PI_NODE)))
4761 result = xmlGetLineNoInternal(node->prev, depth + 1);
4762 else if ((node->parent != NULL) &&
4763 (node->parent->type == XML_ELEMENT_NODE))
4764 result = xmlGetLineNoInternal(node->parent, depth + 1);
4765
4766 return result;
4767}
4768
4779long
4781{
4782 return(xmlGetLineNoInternal(node, 0));
4783}
4784
4785#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_DEBUG_ENABLED)
4795xmlChar *
4796xmlGetNodePath(const xmlNode *node)
4797{
4798 const xmlNode *cur, *tmp, *next;
4799 xmlChar *buffer = NULL, *temp;
4800 size_t buf_len;
4801 xmlChar *buf;
4802 const char *sep;
4803 const char *name;
4804 char nametemp[100];
4805 int occur = 0, generic;
4806
4807 if ((node == NULL) || (node->type == XML_NAMESPACE_DECL))
4808 return (NULL);
4809
4810 buf_len = 500;
4811 buffer = (xmlChar *) xmlMallocAtomic(buf_len * sizeof(xmlChar));
4812 if (buffer == NULL) {
4813 xmlTreeErrMemory("getting node path");
4814 return (NULL);
4815 }
4816 buf = (xmlChar *) xmlMallocAtomic(buf_len * sizeof(xmlChar));
4817 if (buf == NULL) {
4818 xmlTreeErrMemory("getting node path");
4819 xmlFree(buffer);
4820 return (NULL);
4821 }
4822
4823 buffer[0] = 0;
4824 cur = node;
4825 do {
4826 name = "";
4827 sep = "?";
4828 occur = 0;
4829 if ((cur->type == XML_DOCUMENT_NODE) ||
4830 (cur->type == XML_HTML_DOCUMENT_NODE)) {
4831 if (buffer[0] == '/')
4832 break;
4833 sep = "/";
4834 next = NULL;
4835 } else if (cur->type == XML_ELEMENT_NODE) {
4836 generic = 0;
4837 sep = "/";
4838 name = (const char *) cur->name;
4839 if (cur->ns) {
4840 if (cur->ns->prefix != NULL) {
4841 snprintf(nametemp, sizeof(nametemp) - 1, "%s:%s",
4842 (char *)cur->ns->prefix, (char *)cur->name);
4843 nametemp[sizeof(nametemp) - 1] = 0;
4844 name = nametemp;
4845 } else {
4846 /*
4847 * We cannot express named elements in the default
4848 * namespace, so use "*".
4849 */
4850 generic = 1;
4851 name = "*";
4852 }
4853 }
4854 next = cur->parent;
4855
4856 /*
4857 * Thumbler index computation
4858 * TODO: the occurrence test seems bogus for namespaced names
4859 */
4860 tmp = cur->prev;
4861 while (tmp != NULL) {
4862 if ((tmp->type == XML_ELEMENT_NODE) &&
4863 (generic ||
4864 (xmlStrEqual(cur->name, tmp->name) &&
4865 ((tmp->ns == cur->ns) ||
4866 ((tmp->ns != NULL) && (cur->ns != NULL) &&
4867 (xmlStrEqual(cur->ns->prefix, tmp->ns->prefix)))))))
4868 occur++;
4869 tmp = tmp->prev;
4870 }
4871 if (occur == 0) {
4872 tmp = cur->next;
4873 while (tmp != NULL && occur == 0) {
4874 if ((tmp->type == XML_ELEMENT_NODE) &&
4875 (generic ||
4876 (xmlStrEqual(cur->name, tmp->name) &&
4877 ((tmp->ns == cur->ns) ||
4878 ((tmp->ns != NULL) && (cur->ns != NULL) &&
4879 (xmlStrEqual(cur->ns->prefix, tmp->ns->prefix)))))))
4880 occur++;
4881 tmp = tmp->next;
4882 }
4883 if (occur != 0)
4884 occur = 1;
4885 } else
4886 occur++;
4887 } else if (cur->type == XML_COMMENT_NODE) {
4888 sep = "/";
4889 name = "comment()";
4890 next = cur->parent;
4891
4892 /*
4893 * Thumbler index computation
4894 */
4895 tmp = cur->prev;
4896 while (tmp != NULL) {
4897 if (tmp->type == XML_COMMENT_NODE)
4898 occur++;
4899 tmp = tmp->prev;
4900 }
4901 if (occur == 0) {
4902 tmp = cur->next;
4903 while (tmp != NULL && occur == 0) {
4904 if (tmp->type == XML_COMMENT_NODE)
4905 occur++;
4906 tmp = tmp->next;
4907 }
4908 if (occur != 0)
4909 occur = 1;
4910 } else
4911 occur++;
4912 } else if ((cur->type == XML_TEXT_NODE) ||
4913 (cur->type == XML_CDATA_SECTION_NODE)) {
4914 sep = "/";
4915 name = "text()";
4916 next = cur->parent;
4917
4918 /*
4919 * Thumbler index computation
4920 */
4921 tmp = cur->prev;
4922 while (tmp != NULL) {
4923 if ((tmp->type == XML_TEXT_NODE) ||
4924 (tmp->type == XML_CDATA_SECTION_NODE))
4925 occur++;
4926 tmp = tmp->prev;
4927 }
4928 /*
4929 * Evaluate if this is the only text- or CDATA-section-node;
4930 * if yes, then we'll get "text()", otherwise "text()[1]".
4931 */
4932 if (occur == 0) {
4933 tmp = cur->next;
4934 while (tmp != NULL) {
4935 if ((tmp->type == XML_TEXT_NODE) ||
4936 (tmp->type == XML_CDATA_SECTION_NODE))
4937 {
4938 occur = 1;
4939 break;
4940 }
4941 tmp = tmp->next;
4942 }
4943 } else
4944 occur++;
4945 } else if (cur->type == XML_PI_NODE) {
4946 sep = "/";
4947 snprintf(nametemp, sizeof(nametemp) - 1,
4948 "processing-instruction('%s')", (char *)cur->name);
4949 nametemp[sizeof(nametemp) - 1] = 0;
4950 name = nametemp;
4951
4952 next = cur->parent;
4953
4954 /*
4955 * Thumbler index computation
4956 */
4957 tmp = cur->prev;
4958 while (tmp != NULL) {
4959 if ((tmp->type == XML_PI_NODE) &&
4960 (xmlStrEqual(cur->name, tmp->name)))
4961 occur++;
4962 tmp = tmp->prev;
4963 }
4964 if (occur == 0) {
4965 tmp = cur->next;
4966 while (tmp != NULL && occur == 0) {
4967 if ((tmp->type == XML_PI_NODE) &&
4968 (xmlStrEqual(cur->name, tmp->name)))
4969 occur++;
4970 tmp = tmp->next;
4971 }
4972 if (occur != 0)
4973 occur = 1;
4974 } else
4975 occur++;
4976
4977 } else if (cur->type == XML_ATTRIBUTE_NODE) {
4978 sep = "/@";
4979 name = (const char *) (((xmlAttrPtr) cur)->name);
4980 if (cur->ns) {
4981 if (cur->ns->prefix != NULL)
4982 snprintf(nametemp, sizeof(nametemp) - 1, "%s:%s",
4983 (char *)cur->ns->prefix, (char *)cur->name);
4984 else
4985 snprintf(nametemp, sizeof(nametemp) - 1, "%s",
4986 (char *)cur->name);
4987 nametemp[sizeof(nametemp) - 1] = 0;
4988 name = nametemp;
4989 }
4990 next = ((xmlAttrPtr) cur)->parent;
4991 } else {
4992 xmlFree(buf);
4993 xmlFree(buffer);
4994 return (NULL);
4995 }
4996
4997 /*
4998 * Make sure there is enough room
4999 */
5000 if (xmlStrlen(buffer) + sizeof(nametemp) + 20 > buf_len) {
5001 buf_len =
5002 2 * buf_len + xmlStrlen(buffer) + sizeof(nametemp) + 20;
5003 temp = (xmlChar *) xmlRealloc(buffer, buf_len);
5004 if (temp == NULL) {
5005 xmlTreeErrMemory("getting node path");
5006 xmlFree(buf);
5007 xmlFree(buffer);
5008 return (NULL);
5009 }
5010 buffer = temp;
5011 temp = (xmlChar *) xmlRealloc(buf, buf_len);
5012 if (temp == NULL) {
5013 xmlTreeErrMemory("getting node path");
5014 xmlFree(buf);
5015 xmlFree(buffer);
5016 return (NULL);
5017 }
5018 buf = temp;
5019 }
5020 if (occur == 0)
5021 snprintf((char *) buf, buf_len, "%s%s%s",
5022 sep, name, (char *) buffer);
5023 else
5024 snprintf((char *) buf, buf_len, "%s%s[%d]%s",
5025 sep, name, occur, (char *) buffer);
5026 snprintf((char *) buffer, buf_len, "%s", (char *)buf);
5027 cur = next;
5028 } while (cur != NULL);
5029 xmlFree(buf);
5030 return (buffer);
5031}
5032#endif /* LIBXML_TREE_ENABLED */
5033
5044xmlDocGetRootElement(const xmlDoc *doc) {
5046
5047 if (doc == NULL) return(NULL);
5048 ret = doc->children;
5049 while (ret != NULL) {
5050 if (ret->type == XML_ELEMENT_NODE)
5051 return(ret);
5052 ret = ret->next;
5053 }
5054 return(ret);
5055}
5056
5057#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_WRITER_ENABLED)
5070xmlDocSetRootElement(xmlDocPtr doc, xmlNodePtr root) {
5071 xmlNodePtr old = NULL;
5072
5073 if (doc == NULL) return(NULL);
5074 if ((root == NULL) || (root->type == XML_NAMESPACE_DECL))
5075 return(NULL);
5077 xmlSetTreeDoc(root, doc);
5078 root->parent = (xmlNodePtr) doc;
5079 old = doc->children;
5080 while (old != NULL) {
5081 if (old->type == XML_ELEMENT_NODE)
5082 break;
5083 old = old->next;
5084 }
5085 if (old == NULL) {
5086 if (doc->children == NULL) {
5087 doc->children = root;
5088 doc->last = root;
5089 } else {
5091 }
5092 } else {
5093 xmlReplaceNode(old, root);
5094 }
5095 return(old);
5096}
5097#endif
5098
5099#if defined(LIBXML_TREE_ENABLED)
5108void
5109xmlNodeSetLang(xmlNodePtr cur, const xmlChar *lang) {
5110 xmlNsPtr ns;
5111
5112 if (cur == NULL) return;
5113 switch(cur->type) {
5114 case XML_TEXT_NODE:
5116 case XML_COMMENT_NODE:
5117 case XML_DOCUMENT_NODE:
5120 case XML_NOTATION_NODE:
5122 case XML_DTD_NODE:
5123 case XML_ELEMENT_DECL:
5124 case XML_ATTRIBUTE_DECL:
5125 case XML_ENTITY_DECL:
5126 case XML_PI_NODE:
5128 case XML_ENTITY_NODE:
5129 case XML_NAMESPACE_DECL:
5130 case XML_XINCLUDE_START:
5131 case XML_XINCLUDE_END:
5132 return;
5133 case XML_ELEMENT_NODE:
5134 case XML_ATTRIBUTE_NODE:
5135 break;
5136 }
5138 if (ns == NULL)
5139 return;
5140 xmlSetNsProp(cur, ns, BAD_CAST "lang", lang);
5141}
5142#endif /* LIBXML_TREE_ENABLED */
5143
5154xmlChar *
5155xmlNodeGetLang(const xmlNode *cur) {
5156 xmlChar *lang;
5157
5158 if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL))
5159 return(NULL);
5160 while (cur != NULL) {
5162 if (lang != NULL)
5163 return(lang);
5164 cur = cur->parent;
5165 }
5166 return(NULL);
5167}
5168
5169
5170#ifdef LIBXML_TREE_ENABLED
5179void
5180xmlNodeSetSpacePreserve(xmlNodePtr cur, int val) {
5181 xmlNsPtr ns;
5182
5183 if (cur == NULL) return;
5184 switch(cur->type) {
5185 case XML_TEXT_NODE:
5187 case XML_COMMENT_NODE:
5188 case XML_DOCUMENT_NODE:
5191 case XML_NOTATION_NODE:
5193 case XML_DTD_NODE:
5194 case XML_ELEMENT_DECL:
5195 case XML_ATTRIBUTE_DECL:
5196 case XML_ENTITY_DECL:
5197 case XML_PI_NODE:
5199 case XML_ENTITY_NODE:
5200 case XML_NAMESPACE_DECL:
5201 case XML_XINCLUDE_START:
5202 case XML_XINCLUDE_END:
5203 return;
5204 case XML_ELEMENT_NODE:
5205 case XML_ATTRIBUTE_NODE:
5206 break;
5207 }
5209 if (ns == NULL)
5210 return;
5211 switch (val) {
5212 case 0:
5213 xmlSetNsProp(cur, ns, BAD_CAST "space", BAD_CAST "default");
5214 break;
5215 case 1:
5216 xmlSetNsProp(cur, ns, BAD_CAST "space", BAD_CAST "preserve");
5217 break;
5218 }
5219}
5220#endif /* LIBXML_TREE_ENABLED */
5221
5232int
5234 xmlChar *space;
5235
5236 if ((cur == NULL) || (cur->type != XML_ELEMENT_NODE))
5237 return(-1);
5238 while (cur != NULL) {
5240 if (space != NULL) {
5241 if (xmlStrEqual(space, BAD_CAST "preserve")) {
5242 xmlFree(space);
5243 return(1);
5244 }
5245 if (xmlStrEqual(space, BAD_CAST "default")) {
5246 xmlFree(space);
5247 return(0);
5248 }
5249 xmlFree(space);
5250 }
5251 cur = cur->parent;
5252 }
5253 return(-1);
5254}
5255
5256#ifdef LIBXML_TREE_ENABLED
5264void
5265xmlNodeSetName(xmlNodePtr cur, const xmlChar *name) {
5266 xmlDocPtr doc;
5267 xmlDictPtr dict;
5268 const xmlChar *freeme = NULL;
5269
5270 if (cur == NULL) return;
5271 if (name == NULL) return;
5272 switch(cur->type) {
5273 case XML_TEXT_NODE:
5275 case XML_COMMENT_NODE:
5278 case XML_NOTATION_NODE:
5280 case XML_NAMESPACE_DECL:
5281 case XML_XINCLUDE_START:
5282 case XML_XINCLUDE_END:
5283 return;
5284 case XML_ELEMENT_NODE:
5285 case XML_ATTRIBUTE_NODE:
5286 case XML_PI_NODE:
5288 case XML_ENTITY_NODE:
5289 case XML_DTD_NODE:
5290 case XML_DOCUMENT_NODE:
5291 case XML_ELEMENT_DECL:
5292 case XML_ATTRIBUTE_DECL:
5293 case XML_ENTITY_DECL:
5294 break;
5295 }
5296 doc = cur->doc;
5297 if (doc != NULL)
5298 dict = doc->dict;
5299 else
5300 dict = NULL;
5301 if (dict != NULL) {
5302 if ((cur->name != NULL) && (!xmlDictOwns(dict, cur->name)))
5303 freeme = cur->name;
5304 cur->name = xmlDictLookup(dict, name, -1);
5305 } else {
5306 if (cur->name != NULL)
5307 freeme = cur->name;
5308 cur->name = xmlStrdup(name);
5309 }
5310
5311 if (freeme)
5312 xmlFree((xmlChar *) freeme);
5313}
5314#endif
5315
5316#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XINCLUDE_ENABLED)
5325void
5326xmlNodeSetBase(xmlNodePtr cur, const xmlChar* uri) {
5327 xmlNsPtr ns;
5328 xmlChar* fixed;
5329
5330 if (cur == NULL) return;
5331 switch(cur->type) {
5332 case XML_TEXT_NODE:
5334 case XML_COMMENT_NODE:
5337 case XML_NOTATION_NODE:
5338 case XML_DTD_NODE:
5339 case XML_ELEMENT_DECL:
5340 case XML_ATTRIBUTE_DECL:
5341 case XML_ENTITY_DECL:
5342 case XML_PI_NODE:
5344 case XML_ENTITY_NODE:
5345 case XML_NAMESPACE_DECL:
5346 case XML_XINCLUDE_START:
5347 case XML_XINCLUDE_END:
5348 return;
5349 case XML_ELEMENT_NODE:
5350 case XML_ATTRIBUTE_NODE:
5351 break;
5352 case XML_DOCUMENT_NODE:
5354 xmlDocPtr doc = (xmlDocPtr) cur;
5355
5356 if (doc->URL != NULL)
5357 xmlFree((xmlChar *) doc->URL);
5358 if (uri == NULL)
5359 doc->URL = NULL;
5360 else
5361 doc->URL = xmlPathToURI(uri);
5362 return;
5363 }
5364 }
5365
5367 if (ns == NULL)
5368 return;
5370 if (fixed != NULL) {
5371 xmlSetNsProp(cur, ns, BAD_CAST "base", fixed);
5372 xmlFree(fixed);
5373 } else {
5374 xmlSetNsProp(cur, ns, BAD_CAST "base", uri);
5375 }
5376}
5377#endif /* LIBXML_TREE_ENABLED */
5378
5396xmlChar *
5397xmlNodeGetBase(const xmlDoc *doc, const xmlNode *cur) {
5398 xmlChar *oldbase = NULL;
5399 xmlChar *base, *newbase;
5400
5401 if ((cur == NULL) && (doc == NULL))
5402 return(NULL);
5403 if ((cur != NULL) && (cur->type == XML_NAMESPACE_DECL))
5404 return(NULL);
5405 if (doc == NULL) doc = cur->doc;
5406 if ((doc != NULL) && (doc->type == XML_HTML_DOCUMENT_NODE)) {
5407 cur = doc->children;
5408 while ((cur != NULL) && (cur->name != NULL)) {
5409 if (cur->type != XML_ELEMENT_NODE) {
5410 cur = cur->next;
5411 continue;
5412 }
5413 if (!xmlStrcasecmp(cur->name, BAD_CAST "html")) {
5414 cur = cur->children;
5415 continue;
5416 }
5417 if (!xmlStrcasecmp(cur->name, BAD_CAST "head")) {
5418 cur = cur->children;
5419 continue;
5420 }
5421 if (!xmlStrcasecmp(cur->name, BAD_CAST "base")) {
5422 return(xmlGetProp(cur, BAD_CAST "href"));
5423 }
5424 cur = cur->next;
5425 }
5426 return(NULL);
5427 }
5428 while (cur != NULL) {
5429 if (cur->type == XML_ENTITY_DECL) {
5431 return(xmlStrdup(ent->URI));
5432 }
5433 if (cur->type == XML_ELEMENT_NODE) {
5435 if (base != NULL) {
5436 if (oldbase != NULL) {
5437 newbase = xmlBuildURI(oldbase, base);
5438 if (newbase != NULL) {
5439 xmlFree(oldbase);
5440 xmlFree(base);
5441 oldbase = newbase;
5442 } else {
5443 xmlFree(oldbase);
5444 xmlFree(base);
5445 return(NULL);
5446 }
5447 } else {
5448 oldbase = base;
5449 }
5450 if ((!xmlStrncmp(oldbase, BAD_CAST "http://", 7)) ||
5451 (!xmlStrncmp(oldbase, BAD_CAST "ftp://", 6)) ||
5452 (!xmlStrncmp(oldbase, BAD_CAST "urn:", 4)))
5453 return(oldbase);
5454 }
5455 }
5456 cur = cur->parent;
5457 }
5458 if ((doc != NULL) && (doc->URL != NULL)) {
5459 if (oldbase == NULL)
5460 return(xmlStrdup(doc->URL));
5461 newbase = xmlBuildURI(oldbase, doc->URL);
5462 xmlFree(oldbase);
5463 return(newbase);
5464 }
5465 return(oldbase);
5466}
5467
5481int
5483{
5484 xmlBufPtr buf;
5485 int ret;
5486
5487 if ((cur == NULL) || (buffer == NULL)) return(-1);
5491 if ((ret < 0) || (buffer == NULL))
5492 return(-1);
5493 return(0);
5494}
5495
5509int
5511{
5512 if ((cur == NULL) || (buf == NULL)) return(-1);
5513 switch (cur->type) {
5515 case XML_TEXT_NODE:
5516 xmlBufCat(buf, cur->content);
5517 break;
5519 case XML_ELEMENT_NODE:{
5520 const xmlNode *tmp = cur;
5521
5522 while (tmp != NULL) {
5523 switch (tmp->type) {
5525 case XML_TEXT_NODE:
5526 if (tmp->content != NULL)
5527 xmlBufCat(buf, tmp->content);
5528 break;
5531 break;
5532 default:
5533 break;
5534 }
5535 /*
5536 * Skip to next node
5537 */
5538 if (tmp->children != NULL) {
5539 if (tmp->children->type != XML_ENTITY_DECL) {
5540 tmp = tmp->children;
5541 continue;
5542 }
5543 }
5544 if (tmp == cur)
5545 break;
5546
5547 if (tmp->next != NULL) {
5548 tmp = tmp->next;
5549 continue;
5550 }
5551
5552 do {
5553 tmp = tmp->parent;
5554 if (tmp == NULL)
5555 break;
5556 if (tmp == cur) {
5557 tmp = NULL;
5558 break;
5559 }
5560 if (tmp->next != NULL) {
5561 tmp = tmp->next;
5562 break;
5563 }
5564 } while (tmp != NULL);
5565 }
5566 break;
5567 }
5568 case XML_ATTRIBUTE_NODE:{
5570 xmlNodePtr tmp = attr->children;
5571
5572 while (tmp != NULL) {
5573 if (tmp->type == XML_TEXT_NODE)
5574 xmlBufCat(buf, tmp->content);
5575 else
5577 tmp = tmp->next;
5578 }
5579 break;
5580 }
5581 case XML_COMMENT_NODE:
5582 case XML_PI_NODE:
5583 xmlBufCat(buf, cur->content);
5584 break;
5585 case XML_ENTITY_REF_NODE:{
5586 xmlEntityPtr ent;
5587 xmlNodePtr tmp;
5588
5589 /* lookup entity declaration */
5590 ent = xmlGetDocEntity(cur->doc, cur->name);
5591 if (ent == NULL)
5592 return(-1);
5593
5594 /* an entity content can be any "well balanced chunk",
5595 * i.e. the result of the content [43] production:
5596 * http://www.w3.org/TR/REC-xml#NT-content
5597 * -> we iterate through child nodes and recursive call
5598 * xmlNodeGetContent() which handles all possible node types */
5599 tmp = ent->children;
5600 while (tmp) {
5602 tmp = tmp->next;
5603 }
5604 break;
5605 }
5606 case XML_ENTITY_NODE:
5608 case XML_NOTATION_NODE:
5609 case XML_DTD_NODE:
5610 case XML_XINCLUDE_START:
5611 case XML_XINCLUDE_END:
5612 break;
5613 case XML_DOCUMENT_NODE:
5615 cur = cur->children;
5616 while (cur!= NULL) {
5617 if ((cur->type == XML_ELEMENT_NODE) ||
5618 (cur->type == XML_TEXT_NODE) ||
5619 (cur->type == XML_CDATA_SECTION_NODE)) {
5621 }
5622 cur = cur->next;
5623 }
5624 break;
5625 case XML_NAMESPACE_DECL:
5626 xmlBufCat(buf, ((xmlNsPtr) cur)->href);
5627 break;
5628 case XML_ELEMENT_DECL:
5629 case XML_ATTRIBUTE_DECL:
5630 case XML_ENTITY_DECL:
5631 break;
5632 }
5633 return(0);
5634}
5635
5647xmlChar *
5649{
5650 if (cur == NULL)
5651 return (NULL);
5652 switch (cur->type) {
5654 case XML_ELEMENT_NODE:{
5655 xmlBufPtr buf;
5656 xmlChar *ret;
5657
5658 buf = xmlBufCreateSize(64);
5659 if (buf == NULL)
5660 return (NULL);
5663 ret = xmlBufDetach(buf);
5664 xmlBufFree(buf);
5665 return (ret);
5666 }
5667 case XML_ATTRIBUTE_NODE:
5669 case XML_COMMENT_NODE:
5670 case XML_PI_NODE:
5671 if (cur->content != NULL)
5672 return (xmlStrdup(cur->content));
5673 return (NULL);
5674 case XML_ENTITY_REF_NODE:{
5675 xmlEntityPtr ent;
5676 xmlBufPtr buf;
5677 xmlChar *ret;
5678
5679 /* lookup entity declaration */
5680 ent = xmlGetDocEntity(cur->doc, cur->name);
5681 if (ent == NULL)
5682 return (NULL);
5683
5684 buf = xmlBufCreate();
5685 if (buf == NULL)
5686 return (NULL);
5688
5690
5691 ret = xmlBufDetach(buf);
5692 xmlBufFree(buf);
5693 return (ret);
5694 }
5695 case XML_ENTITY_NODE:
5697 case XML_NOTATION_NODE:
5698 case XML_DTD_NODE:
5699 case XML_XINCLUDE_START:
5700 case XML_XINCLUDE_END:
5701 return (NULL);
5702 case XML_DOCUMENT_NODE:
5704 xmlBufPtr buf;
5705 xmlChar *ret;
5706
5707 buf = xmlBufCreate();
5708 if (buf == NULL)
5709 return (NULL);
5711
5713
5714 ret = xmlBufDetach(buf);
5715 xmlBufFree(buf);
5716 return (ret);
5717 }
5718 case XML_NAMESPACE_DECL: {
5719 xmlChar *tmp;
5720
5721 tmp = xmlStrdup(((xmlNsPtr) cur)->href);
5722 return (tmp);
5723 }
5724 case XML_ELEMENT_DECL:
5725 /* TODO !!! */
5726 return (NULL);
5727 case XML_ATTRIBUTE_DECL:
5728 /* TODO !!! */
5729 return (NULL);
5730 case XML_ENTITY_DECL:
5731 /* TODO !!! */
5732 return (NULL);
5734 case XML_TEXT_NODE:
5735 if (cur->content != NULL)
5736 return (xmlStrdup(cur->content));
5737 return (NULL);
5738 }
5739 return (NULL);
5740}
5741
5752void
5754 if (cur == NULL) {
5755#ifdef DEBUG_TREE
5757 "xmlNodeSetContent : node == NULL\n");
5758#endif
5759 return;
5760 }
5761 switch (cur->type) {
5763 case XML_ELEMENT_NODE:
5764 case XML_ATTRIBUTE_NODE:
5765 if (cur->children != NULL) xmlFreeNodeList(cur->children);
5766 cur->children = xmlStringGetNodeList(cur->doc, content);
5768 break;
5769 case XML_TEXT_NODE:
5772 case XML_ENTITY_NODE:
5773 case XML_PI_NODE:
5774 case XML_COMMENT_NODE:
5775 if ((cur->content != NULL) &&
5776 (cur->content != (xmlChar *) &(cur->properties))) {
5777 if (!((cur->doc != NULL) && (cur->doc->dict != NULL) &&
5778 (xmlDictOwns(cur->doc->dict, cur->content))))
5779 xmlFree(cur->content);
5780 }
5781 if (cur->children != NULL) xmlFreeNodeList(cur->children);
5782 cur->last = cur->children = NULL;
5783 if (content != NULL) {
5784 cur->content = xmlStrdup(content);
5785 } else
5786 cur->content = NULL;
5787 cur->properties = NULL;
5788 break;
5789 case XML_DOCUMENT_NODE:
5792 case XML_XINCLUDE_START:
5793 case XML_XINCLUDE_END:
5794 break;
5795 case XML_NOTATION_NODE:
5796 break;
5797 case XML_DTD_NODE:
5798 break;
5799 case XML_NAMESPACE_DECL:
5800 break;
5801 case XML_ELEMENT_DECL:
5802 /* TODO !!! */
5803 break;
5804 case XML_ATTRIBUTE_DECL:
5805 /* TODO !!! */
5806 break;
5807 case XML_ENTITY_DECL:
5808 /* TODO !!! */
5809 break;
5810 }
5811}
5812
5813#ifdef LIBXML_TREE_ENABLED
5825void
5826xmlNodeSetContentLen(xmlNodePtr cur, const xmlChar *content, int len) {
5827 if (cur == NULL) {
5828#ifdef DEBUG_TREE
5830 "xmlNodeSetContentLen : node == NULL\n");
5831#endif
5832 return;
5833 }
5834 switch (cur->type) {
5836 case XML_ELEMENT_NODE:
5837 case XML_ATTRIBUTE_NODE:
5838 if (cur->children != NULL) xmlFreeNodeList(cur->children);
5839 cur->children = xmlStringLenGetNodeList(cur->doc, content, len);
5841 break;
5842 case XML_TEXT_NODE:
5845 case XML_ENTITY_NODE:
5846 case XML_PI_NODE:
5847 case XML_COMMENT_NODE:
5848 case XML_NOTATION_NODE:
5849 if ((cur->content != NULL) &&
5850 (cur->content != (xmlChar *) &(cur->properties))) {
5851 if (!((cur->doc != NULL) && (cur->doc->dict != NULL) &&
5852 (xmlDictOwns(cur->doc->dict, cur->content))))
5853 xmlFree(cur->content);
5854 }
5855 if (cur->children != NULL) xmlFreeNodeList(cur->children);
5856 cur->children = cur->last = NULL;
5857 if (content != NULL) {
5858 cur->content = xmlStrndup(content, len);
5859 } else
5860 cur->content = NULL;
5861 cur->properties = NULL;
5862 break;
5863 case XML_DOCUMENT_NODE:
5864 case XML_DTD_NODE:
5867 case XML_NAMESPACE_DECL:
5868 case XML_XINCLUDE_START:
5869 case XML_XINCLUDE_END:
5870 break;
5871 case XML_ELEMENT_DECL:
5872 /* TODO !!! */
5873 break;
5874 case XML_ATTRIBUTE_DECL:
5875 /* TODO !!! */
5876 break;
5877 case XML_ENTITY_DECL:
5878 /* TODO !!! */
5879 break;
5880 }
5881}
5882#endif /* LIBXML_TREE_ENABLED */
5883
5895void
5897 if (cur == NULL) {
5898#ifdef DEBUG_TREE
5900 "xmlNodeAddContentLen : node == NULL\n");
5901#endif
5902 return;
5903 }
5904 if (len <= 0) return;
5905 switch (cur->type) {
5907 case XML_ELEMENT_NODE: {
5908 xmlNodePtr last, newNode, tmp;
5909
5910 last = cur->last;
5911 newNode = xmlNewDocTextLen(cur->doc, content, len);
5912 if (newNode != NULL) {
5913 tmp = xmlAddChild(cur, newNode);
5914 if (tmp != newNode)
5915 return;
5916 if ((last != NULL) && (last->next == newNode)) {
5917 xmlTextMerge(last, newNode);
5918 }
5919 }
5920 break;
5921 }
5922 case XML_ATTRIBUTE_NODE:
5923 break;
5924 case XML_TEXT_NODE:
5927 case XML_ENTITY_NODE:
5928 case XML_PI_NODE:
5929 case XML_COMMENT_NODE:
5930 case XML_NOTATION_NODE:
5931 if (content != NULL) {
5932 if ((cur->content == (xmlChar *) &(cur->properties)) ||
5933 ((cur->doc != NULL) && (cur->doc->dict != NULL) &&
5934 xmlDictOwns(cur->doc->dict, cur->content))) {
5935 cur->content = xmlStrncatNew(cur->content, content, len);
5936 cur->properties = NULL;
5937 } else {
5938 cur->content = xmlStrncat(cur->content, content, len);
5939 }
5940 }
5941 break;
5942 case XML_DOCUMENT_NODE:
5943 case XML_DTD_NODE:
5946 case XML_NAMESPACE_DECL:
5947 case XML_XINCLUDE_START:
5948 case XML_XINCLUDE_END:
5949 break;
5950 case XML_ELEMENT_DECL:
5951 case XML_ATTRIBUTE_DECL:
5952 case XML_ENTITY_DECL:
5953 break;
5954 }
5955}
5956
5967void
5969 int len;
5970
5971 if (cur == NULL) {
5972#ifdef DEBUG_TREE
5974 "xmlNodeAddContent : node == NULL\n");
5975#endif
5976 return;
5977 }
5978 if (content == NULL) return;
5981}
5982
5993 if (first == NULL) return(second);
5994 if (second == NULL) return(first);
5995 if (first->type != XML_TEXT_NODE) return(first);
5996 if (second->type != XML_TEXT_NODE) return(first);
5997 if (second->name != first->name)
5998 return(first);
6000 xmlUnlinkNode(second);
6001 xmlFreeNode(second);
6002 return(first);
6003}
6004
6005#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XPATH_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
6016xmlNsPtr *
6017xmlGetNsList(const xmlDoc *doc ATTRIBUTE_UNUSED, const xmlNode *node)
6018{
6019 xmlNsPtr cur;
6020 xmlNsPtr *ret = NULL;
6021 int nbns = 0;
6022 int maxns = 10;
6023 int i;
6024
6025 if ((node == NULL) || (node->type == XML_NAMESPACE_DECL))
6026 return(NULL);
6027
6028 while (node != NULL) {
6029 if (node->type == XML_ELEMENT_NODE) {
6030 cur = node->nsDef;
6031 while (cur != NULL) {
6032 if (ret == NULL) {
6033 ret =
6034 (xmlNsPtr *) xmlMalloc((maxns + 1) *
6035 sizeof(xmlNsPtr));
6036 if (ret == NULL) {
6037 xmlTreeErrMemory("getting namespace list");
6038 return (NULL);
6039 }
6040 ret[nbns] = NULL;
6041 }
6042 for (i = 0; i < nbns; i++) {
6043 if ((cur->prefix == ret[i]->prefix) ||
6044 (xmlStrEqual(cur->prefix, ret[i]->prefix)))
6045 break;
6046 }
6047 if (i >= nbns) {
6048 if (nbns >= maxns) {
6049 maxns *= 2;
6050 ret = (xmlNsPtr *) xmlRealloc(ret,
6051 (maxns +
6052 1) *
6053 sizeof(xmlNsPtr));
6054 if (ret == NULL) {
6055 xmlTreeErrMemory("getting namespace list");
6056 return (NULL);
6057 }
6058 }
6059 ret[nbns++] = cur;
6060 ret[nbns] = NULL;
6061 }
6062
6063 cur = cur->next;
6064 }
6065 }
6066 node = node->parent;
6067 }
6068 return (ret);
6069}
6070#endif /* LIBXML_TREE_ENABLED */
6071
6072/*
6073* xmlTreeEnsureXMLDecl:
6074* @doc: the doc
6075*
6076* Ensures that there is an XML namespace declaration on the doc.
6077*
6078* Returns the XML ns-struct or NULL on API and internal errors.
6079*/
6080static xmlNsPtr
6081xmlTreeEnsureXMLDecl(xmlDocPtr doc)
6082{
6083 if (doc == NULL)
6084 return (NULL);
6085 if (doc->oldNs != NULL)
6086 return (doc->oldNs);
6087 {
6088 xmlNsPtr ns;
6089 ns = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
6090 if (ns == NULL) {
6092 "allocating the XML namespace");
6093 return (NULL);
6094 }
6095 memset(ns, 0, sizeof(xmlNs));
6096 ns->type = XML_LOCAL_NAMESPACE;
6098 ns->prefix = xmlStrdup((const xmlChar *)"xml");
6099 doc->oldNs = ns;
6100 return (ns);
6101 }
6102}
6103
6121xmlSearchNs(xmlDocPtr doc, xmlNodePtr node, const xmlChar *nameSpace) {
6122
6123 xmlNsPtr cur;
6124 const xmlNode *orig = node;
6125
6126 if ((node == NULL) || (node->type == XML_NAMESPACE_DECL)) return(NULL);
6127 if ((nameSpace != NULL) &&
6128 (xmlStrEqual(nameSpace, (const xmlChar *)"xml"))) {
6129 if ((doc == NULL) && (node->type == XML_ELEMENT_NODE)) {
6130 /*
6131 * The XML-1.0 namespace is normally held on the root
6132 * element. In this case exceptionally create it on the
6133 * node element.
6134 */
6135 cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
6136 if (cur == NULL) {
6137 xmlTreeErrMemory("searching namespace");
6138 return(NULL);
6139 }
6140 memset(cur, 0, sizeof(xmlNs));
6141 cur->type = XML_LOCAL_NAMESPACE;
6143 cur->prefix = xmlStrdup((const xmlChar *)"xml");
6144 cur->next = node->nsDef;
6145 node->nsDef = cur;
6146 return(cur);
6147 }
6148 if (doc == NULL) {
6149 doc = node->doc;
6150 if (doc == NULL)
6151 return(NULL);
6152 }
6153 /*
6154 * Return the XML namespace declaration held by the doc.
6155 */
6156 if (doc->oldNs == NULL)
6157 return(xmlTreeEnsureXMLDecl(doc));
6158 else
6159 return(doc->oldNs);
6160 }
6161 while (node != NULL) {
6162 if ((node->type == XML_ENTITY_REF_NODE) ||
6163 (node->type == XML_ENTITY_NODE) ||
6164 (node->type == XML_ENTITY_DECL))
6165 return(NULL);
6166 if (node->type == XML_ELEMENT_NODE) {
6167 cur = node->nsDef;
6168 while (cur != NULL) {
6169 if ((cur->prefix == NULL) && (nameSpace == NULL) &&
6170 (cur->href != NULL))
6171 return(cur);
6172 if ((cur->prefix != NULL) && (nameSpace != NULL) &&
6173 (cur->href != NULL) &&
6174 (xmlStrEqual(cur->prefix, nameSpace)))
6175 return(cur);
6176 cur = cur->next;
6177 }
6178 if (orig != node) {
6179 cur = node->ns;
6180 if (cur != NULL) {
6181 if ((cur->prefix == NULL) && (nameSpace == NULL) &&
6182 (cur->href != NULL))
6183 return(cur);
6184 if ((cur->prefix != NULL) && (nameSpace != NULL) &&
6185 (cur->href != NULL) &&
6186 (xmlStrEqual(cur->prefix, nameSpace)))
6187 return(cur);
6188 }
6189 }
6190 }
6191 node = node->parent;
6192 }
6193 return(NULL);
6194}
6195
6208static int
6209xmlNsInScope(xmlDocPtr doc ATTRIBUTE_UNUSED, xmlNodePtr node,
6210 xmlNodePtr ancestor, const xmlChar * prefix)
6211{
6212 xmlNsPtr tst;
6213
6214 while ((node != NULL) && (node != ancestor)) {
6215 if ((node->type == XML_ENTITY_REF_NODE) ||
6216 (node->type == XML_ENTITY_NODE) ||
6217 (node->type == XML_ENTITY_DECL))
6218 return (-1);
6219 if (node->type == XML_ELEMENT_NODE) {
6220 tst = node->nsDef;
6221 while (tst != NULL) {
6222 if ((tst->prefix == NULL)
6223 && (prefix == NULL))
6224 return (0);
6225 if ((tst->prefix != NULL)
6226 && (prefix != NULL)
6227 && (xmlStrEqual(tst->prefix, prefix)))
6228 return (0);
6229 tst = tst->next;
6230 }
6231 }
6232 node = node->parent;
6233 }
6234 if (node != ancestor)
6235 return (-1);
6236 return (1);
6237}
6238
6251{
6252 xmlNsPtr cur;
6253 xmlNodePtr orig = node;
6254 int is_attr;
6255
6256 if ((node == NULL) || (node->type == XML_NAMESPACE_DECL) || (href == NULL))
6257 return (NULL);
6258 if (xmlStrEqual(href, XML_XML_NAMESPACE)) {
6259 /*
6260 * Only the document can hold the XML spec namespace.
6261 */
6262 if ((doc == NULL) && (node->type == XML_ELEMENT_NODE)) {
6263 /*
6264 * The XML-1.0 namespace is normally held on the root
6265 * element. In this case exceptionally create it on the
6266 * node element.
6267 */
6268 cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
6269 if (cur == NULL) {
6270 xmlTreeErrMemory("searching namespace");
6271 return (NULL);
6272 }
6273 memset(cur, 0, sizeof(xmlNs));
6274 cur->type = XML_LOCAL_NAMESPACE;
6276 cur->prefix = xmlStrdup((const xmlChar *) "xml");
6277 cur->next = node->nsDef;
6278 node->nsDef = cur;
6279 return (cur);
6280 }
6281 if (doc == NULL) {
6282 doc = node->doc;
6283 if (doc == NULL)
6284 return(NULL);
6285 }
6286 /*
6287 * Return the XML namespace declaration held by the doc.
6288 */
6289 if (doc->oldNs == NULL)
6290 return(xmlTreeEnsureXMLDecl(doc));
6291 else
6292 return(doc->oldNs);
6293 }
6294 is_attr = (node->type == XML_ATTRIBUTE_NODE);
6295 while (node != NULL) {
6296 if ((node->type == XML_ENTITY_REF_NODE) ||
6297 (node->type == XML_ENTITY_NODE) ||
6298 (node->type == XML_ENTITY_DECL))
6299 return (NULL);
6300 if (node->type == XML_ELEMENT_NODE) {
6301 cur = node->nsDef;
6302 while (cur != NULL) {
6303 if ((cur->href != NULL) && (href != NULL) &&
6304 (xmlStrEqual(cur->href, href))) {
6305 if (((!is_attr) || (cur->prefix != NULL)) &&
6306 (xmlNsInScope(doc, orig, node, cur->prefix) == 1))
6307 return (cur);
6308 }
6309 cur = cur->next;
6310 }
6311 if (orig != node) {
6312 cur = node->ns;
6313 if (cur != NULL) {
6314 if ((cur->href != NULL) && (href != NULL) &&
6315 (xmlStrEqual(cur->href, href))) {
6316 if (((!is_attr) || (cur->prefix != NULL)) &&
6317 (xmlNsInScope(doc, orig, node, cur->prefix) == 1))
6318 return (cur);
6319 }
6320 }
6321 }
6322 }
6323 node = node->parent;
6324 }
6325 return (NULL);
6326}
6327
6341static xmlNsPtr
6343 xmlNsPtr def;
6344 xmlChar prefix[50];
6345 int counter = 1;
6346
6347 if ((tree == NULL) || (tree->type != XML_ELEMENT_NODE)) {
6348#ifdef DEBUG_TREE
6350 "xmlNewReconciledNs : tree == NULL\n");
6351#endif
6352 return(NULL);
6353 }
6354 if ((ns == NULL) || (ns->type != XML_NAMESPACE_DECL)) {
6355#ifdef DEBUG_TREE
6357 "xmlNewReconciledNs : ns == NULL\n");
6358#endif
6359 return(NULL);
6360 }
6361 /*
6362 * Search an existing namespace definition inherited.
6363 */
6364 def = xmlSearchNsByHref(doc, tree, ns->href);
6365 if (def != NULL)
6366 return(def);
6367
6368 /*
6369 * Find a close prefix which is not already in use.
6370 * Let's strip namespace prefixes longer than 20 chars !
6371 */
6372 if (ns->prefix == NULL)
6373 snprintf((char *) prefix, sizeof(prefix), "default");
6374 else
6375 snprintf((char *) prefix, sizeof(prefix), "%.20s", (char *)ns->prefix);
6376
6377 def = xmlSearchNs(doc, tree, prefix);
6378 while (def != NULL) {
6379 if (counter > 1000) return(NULL);
6380 if (ns->prefix == NULL)
6381 snprintf((char *) prefix, sizeof(prefix), "default%d", counter++);
6382 else
6383 snprintf((char *) prefix, sizeof(prefix), "%.20s%d",
6384 (char *)ns->prefix, counter++);
6385 def = xmlSearchNs(doc, tree, prefix);
6386 }
6387
6388 /*
6389 * OK, now we are ready to create a new one.
6390 */
6391 def = xmlNewNs(tree, ns->href, prefix);
6392 return(def);
6393}
6394
6395#ifdef LIBXML_TREE_ENABLED
6410int
6411xmlReconciliateNs(xmlDocPtr doc, xmlNodePtr tree) {
6412 xmlNsPtr *oldNs = NULL;
6413 xmlNsPtr *newNs = NULL;
6414 int sizeCache = 0;
6415 int nbCache = 0;
6416
6417 xmlNsPtr n;
6420 int ret = 0, i;
6421
6422 if ((node == NULL) || (node->type != XML_ELEMENT_NODE)) return(-1);
6423 if ((doc == NULL) || (doc->type != XML_DOCUMENT_NODE)) return(-1);
6424 if (node->doc != doc) return(-1);
6425 while (node != NULL) {
6426 /*
6427 * Reconciliate the node namespace
6428 */
6429 if (node->ns != NULL) {
6430 /*
6431 * initialize the cache if needed
6432 */
6433 if (sizeCache == 0) {
6434 sizeCache = 10;
6435 oldNs = (xmlNsPtr *) xmlMalloc(sizeCache *
6436 sizeof(xmlNsPtr));
6437 if (oldNs == NULL) {
6438 xmlTreeErrMemory("fixing namespaces");
6439 return(-1);
6440 }
6441 newNs = (xmlNsPtr *) xmlMalloc(sizeCache *
6442 sizeof(xmlNsPtr));
6443 if (newNs == NULL) {
6444 xmlTreeErrMemory("fixing namespaces");
6445 xmlFree(oldNs);
6446 return(-1);
6447 }
6448 }
6449 for (i = 0;i < nbCache;i++) {
6450 if (oldNs[i] == node->ns) {
6451 node->ns = newNs[i];
6452 break;
6453 }
6454 }
6455 if (i == nbCache) {
6456 /*
6457 * OK we need to recreate a new namespace definition
6458 */
6459 n = xmlNewReconciledNs(doc, tree, node->ns);
6460 if (n != NULL) { /* :-( what if else ??? */
6461 /*
6462 * check if we need to grow the cache buffers.
6463 */
6464 if (sizeCache <= nbCache) {
6465 sizeCache *= 2;
6466 oldNs = (xmlNsPtr *) xmlRealloc(oldNs, sizeCache *
6467 sizeof(xmlNsPtr));
6468 if (oldNs == NULL) {
6469 xmlTreeErrMemory("fixing namespaces");
6470 xmlFree(newNs);
6471 return(-1);
6472 }
6473 newNs = (xmlNsPtr *) xmlRealloc(newNs, sizeCache *
6474 sizeof(xmlNsPtr));
6475 if (newNs == NULL) {
6476 xmlTreeErrMemory("fixing namespaces");
6477 xmlFree(oldNs);
6478 return(-1);
6479 }
6480 }
6481 newNs[nbCache] = n;
6482 oldNs[nbCache++] = node->ns;
6483 node->ns = n;
6484 }
6485 }
6486 }
6487 /*
6488 * now check for namespace held by attributes on the node.
6489 */
6490 if (node->type == XML_ELEMENT_NODE) {
6491 attr = node->properties;
6492 while (attr != NULL) {
6493 if (attr->ns != NULL) {
6494 /*
6495 * initialize the cache if needed
6496 */
6497 if (sizeCache == 0) {
6498 sizeCache = 10;
6499 oldNs = (xmlNsPtr *) xmlMalloc(sizeCache *
6500 sizeof(xmlNsPtr));
6501 if (oldNs == NULL) {
6502 xmlTreeErrMemory("fixing namespaces");
6503 return(-1);
6504 }
6505 newNs = (xmlNsPtr *) xmlMalloc(sizeCache *
6506 sizeof(xmlNsPtr));
6507 if (newNs == NULL) {
6508 xmlTreeErrMemory("fixing namespaces");
6509 xmlFree(oldNs);
6510 return(-1);
6511 }
6512 }
6513 for (i = 0;i < nbCache;i++) {
6514 if (oldNs[i] == attr->ns) {
6515 attr->ns = newNs[i];
6516 break;
6517 }
6518 }
6519 if (i == nbCache) {
6520 /*
6521 * OK we need to recreate a new namespace definition
6522 */
6523 n = xmlNewReconciledNs(doc, tree, attr->ns);
6524 if (n != NULL) { /* :-( what if else ??? */
6525 /*
6526 * check if we need to grow the cache buffers.
6527 */
6528 if (sizeCache <= nbCache) {
6529 sizeCache *= 2;
6530 oldNs = (xmlNsPtr *) xmlRealloc(oldNs,
6531 sizeCache * sizeof(xmlNsPtr));
6532 if (oldNs == NULL) {
6533 xmlTreeErrMemory("fixing namespaces");
6534 xmlFree(newNs);
6535 return(-1);
6536 }
6537 newNs = (xmlNsPtr *) xmlRealloc(newNs,
6538 sizeCache * sizeof(xmlNsPtr));
6539 if (newNs == NULL) {
6540 xmlTreeErrMemory("fixing namespaces");
6541 xmlFree(oldNs);
6542 return(-1);
6543 }
6544 }
6545 newNs[nbCache] = n;
6546 oldNs[nbCache++] = attr->ns;
6547 attr->ns = n;
6548 }
6549 }
6550 }
6551 attr = attr->next;
6552 }
6553 }
6554
6555 /*
6556 * Browse the full subtree, deep first
6557 */
6558 if ((node->children != NULL) && (node->type != XML_ENTITY_REF_NODE)) {
6559 /* deep first */
6560 node = node->children;
6561 } else if ((node != tree) && (node->next != NULL)) {
6562 /* then siblings */
6563 node = node->next;
6564 } else if (node != tree) {
6565 /* go up to parents->next if needed */
6566 while (node != tree) {
6567 if (node->parent != NULL)
6568 node = node->parent;
6569 if ((node != tree) && (node->next != NULL)) {
6570 node = node->next;
6571 break;
6572 }
6573 if (node->parent == NULL) {
6574 node = NULL;
6575 break;
6576 }
6577 }
6578 /* exit condition */
6579 if (node == tree)
6580 node = NULL;
6581 } else
6582 break;
6583 }
6584 if (oldNs != NULL)
6585 xmlFree(oldNs);
6586 if (newNs != NULL)
6587 xmlFree(newNs);
6588 return(ret);
6589}
6590#endif /* LIBXML_TREE_ENABLED */
6591
6592static xmlAttrPtr
6593xmlGetPropNodeInternal(const xmlNode *node, const xmlChar *name,
6594 const xmlChar *nsName, int useDTD)
6595{
6596 xmlAttrPtr prop;
6597
6598 /* Avoid unused variable warning if features are disabled. */
6599 (void) useDTD;
6600
6601 if ((node == NULL) || (node->type != XML_ELEMENT_NODE) || (name == NULL))
6602 return(NULL);
6603
6604 if (node->properties != NULL) {
6605 prop = node->properties;
6606 if (nsName == NULL) {
6607 /*
6608 * We want the attr to be in no namespace.
6609 */
6610 do {
6611 if ((prop->ns == NULL) && xmlStrEqual(prop->name, name)) {
6612 return(prop);
6613 }
6614 prop = prop->next;
6615 } while (prop != NULL);
6616 } else {
6617 /*
6618 * We want the attr to be in the specified namespace.
6619 */
6620 do {
6621 if ((prop->ns != NULL) && xmlStrEqual(prop->name, name) &&
6622 ((prop->ns->href == nsName) ||
6623 xmlStrEqual(prop->ns->href, nsName)))
6624 {
6625 return(prop);
6626 }
6627 prop = prop->next;
6628 } while (prop != NULL);
6629 }
6630 }
6631
6632#ifdef LIBXML_TREE_ENABLED
6633 if (! useDTD)
6634 return(NULL);
6635 /*
6636 * Check if there is a default/fixed attribute declaration in
6637 * the internal or external subset.
6638 */
6639 if ((node->doc != NULL) && (node->doc->intSubset != NULL)) {
6640 xmlDocPtr doc = node->doc;
6641 xmlAttributePtr attrDecl = NULL;
6642 xmlChar *elemQName, *tmpstr = NULL;
6643
6644 /*
6645 * We need the QName of the element for the DTD-lookup.
6646 */
6647 if ((node->ns != NULL) && (node->ns->prefix != NULL)) {
6648 tmpstr = xmlStrdup(node->ns->prefix);
6649 tmpstr = xmlStrcat(tmpstr, BAD_CAST ":");
6650 tmpstr = xmlStrcat(tmpstr, node->name);
6651 if (tmpstr == NULL)
6652 return(NULL);
6653 elemQName = tmpstr;
6654 } else
6655 elemQName = (xmlChar *) node->name;
6656 if (nsName == NULL) {
6657 /*
6658 * The common and nice case: Attr in no namespace.
6659 */
6660 attrDecl = xmlGetDtdQAttrDesc(doc->intSubset,
6661 elemQName, name, NULL);
6662 if ((attrDecl == NULL) && (doc->extSubset != NULL)) {
6663 attrDecl = xmlGetDtdQAttrDesc(doc->extSubset,
6664 elemQName, name, NULL);
6665 }
6666 } else if (xmlStrEqual(nsName, XML_XML_NAMESPACE)) {
6667 /*
6668 * The XML namespace must be bound to prefix 'xml'.
6669 */
6670 attrDecl = xmlGetDtdQAttrDesc(doc->intSubset,
6671 elemQName, name, BAD_CAST "xml");
6672 if ((attrDecl == NULL) && (doc->extSubset != NULL)) {
6673 attrDecl = xmlGetDtdQAttrDesc(doc->extSubset,
6674 elemQName, name, BAD_CAST "xml");
6675 }
6676 } else {
6677 xmlNsPtr *nsList, *cur;
6678
6679 /*
6680 * The ugly case: Search using the prefixes of in-scope
6681 * ns-decls corresponding to @nsName.
6682 */
6683 nsList = xmlGetNsList(node->doc, node);
6684 if (nsList == NULL) {
6685 if (tmpstr != NULL)
6686 xmlFree(tmpstr);
6687 return(NULL);
6688 }
6689 cur = nsList;
6690 while (*cur != NULL) {
6691 if (xmlStrEqual((*cur)->href, nsName)) {
6692 attrDecl = xmlGetDtdQAttrDesc(doc->intSubset, elemQName,
6693 name, (*cur)->prefix);
6694 if (attrDecl)
6695 break;
6696 if (doc->extSubset != NULL) {
6697 attrDecl = xmlGetDtdQAttrDesc(doc->extSubset, elemQName,
6698 name, (*cur)->prefix);
6699 if (attrDecl)
6700 break;
6701 }
6702 }
6703 cur++;
6704 }
6705 xmlFree(nsList);
6706 }
6707 if (tmpstr != NULL)
6708 xmlFree(tmpstr);
6709 /*
6710 * Only default/fixed attrs are relevant.
6711 */
6712 if ((attrDecl != NULL) && (attrDecl->defaultValue != NULL))
6713 return((xmlAttrPtr) attrDecl);
6714 }
6715#endif /* LIBXML_TREE_ENABLED */
6716 return(NULL);
6717}
6718
6719static xmlChar*
6721{
6722 if (prop == NULL)
6723 return(NULL);
6724 if (prop->type == XML_ATTRIBUTE_NODE) {
6725 /*
6726 * Note that we return at least the empty string.
6727 * TODO: Do we really always want that?
6728 */
6729 if (prop->children != NULL) {
6730 if ((prop->children->next == NULL) &&
6731 ((prop->children->type == XML_TEXT_NODE) ||
6732 (prop->children->type == XML_CDATA_SECTION_NODE)))
6733 {
6734 /*
6735 * Optimization for the common case: only 1 text node.
6736 */
6737 return(xmlStrdup(prop->children->content));
6738 } else {
6739 xmlChar *ret;
6740
6741 ret = xmlNodeListGetString(prop->doc, prop->children, 1);
6742 if (ret != NULL)
6743 return(ret);
6744 }
6745 }
6746 return(xmlStrdup((xmlChar *)""));
6747 } else if (prop->type == XML_ATTRIBUTE_DECL) {
6748 return(xmlStrdup(((xmlAttributePtr)prop)->defaultValue));
6749 }
6750 return(NULL);
6751}
6752
6766xmlHasProp(const xmlNode *node, const xmlChar *name) {
6767 xmlAttrPtr prop;
6768 xmlDocPtr doc;
6769
6770 if ((node == NULL) || (node->type != XML_ELEMENT_NODE) || (name == NULL))
6771 return(NULL);
6772 /*
6773 * Check on the properties attached to the node
6774 */
6775 prop = node->properties;
6776 while (prop != NULL) {
6777 if (xmlStrEqual(prop->name, name)) {
6778 return(prop);
6779 }
6780 prop = prop->next;
6781 }
6782 if (!xmlCheckDTD) return(NULL);
6783
6784 /*
6785 * Check if there is a default declaration in the internal
6786 * or external subsets
6787 */
6788 doc = node->doc;
6789 if (doc != NULL) {
6790 xmlAttributePtr attrDecl;
6791 if (doc->intSubset != NULL) {
6792 attrDecl = xmlGetDtdAttrDesc(doc->intSubset, node->name, name);
6793 if ((attrDecl == NULL) && (doc->extSubset != NULL))
6794 attrDecl = xmlGetDtdAttrDesc(doc->extSubset, node->name, name);
6795 if ((attrDecl != NULL) && (attrDecl->defaultValue != NULL))
6796 /* return attribute declaration only if a default value is given
6797 (that includes #FIXED declarations) */
6798 return((xmlAttrPtr) attrDecl);
6799 }
6800 }
6801 return(NULL);
6802}
6803
6821xmlHasNsProp(const xmlNode *node, const xmlChar *name, const xmlChar *nameSpace) {
6822
6823 return(xmlGetPropNodeInternal(node, name, nameSpace, xmlCheckDTD));
6824}
6825
6842xmlChar *
6843xmlGetProp(const xmlNode *node, const xmlChar *name) {
6844 xmlAttrPtr prop;
6845
6846 prop = xmlHasProp(node, name);
6847 if (prop == NULL)
6848 return(NULL);
6849 return(xmlGetPropNodeValueInternal(prop));
6850}
6851
6867xmlChar *
6868xmlGetNoNsProp(const xmlNode *node, const xmlChar *name) {
6869 xmlAttrPtr prop;
6870
6871 prop = xmlGetPropNodeInternal(node, name, NULL, xmlCheckDTD);
6872 if (prop == NULL)
6873 return(NULL);
6874 return(xmlGetPropNodeValueInternal(prop));
6875}
6876
6892xmlChar *
6893xmlGetNsProp(const xmlNode *node, const xmlChar *name, const xmlChar *nameSpace) {
6894 xmlAttrPtr prop;
6895
6896 prop = xmlGetPropNodeInternal(node, name, nameSpace, xmlCheckDTD);
6897 if (prop == NULL)
6898 return(NULL);
6899 return(xmlGetPropNodeValueInternal(prop));
6900}
6901
6902#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
6912int
6913xmlUnsetProp(xmlNodePtr node, const xmlChar *name) {
6914 xmlAttrPtr prop;
6915
6916 prop = xmlGetPropNodeInternal(node, name, NULL, 0);
6917 if (prop == NULL)
6918 return(-1);
6919 xmlUnlinkNode((xmlNodePtr) prop);
6920 xmlFreeProp(prop);
6921 return(0);
6922}
6923
6933int
6934xmlUnsetNsProp(xmlNodePtr node, xmlNsPtr ns, const xmlChar *name) {
6935 xmlAttrPtr prop;
6936
6937 prop = xmlGetPropNodeInternal(node, name, (ns != NULL) ? ns->href : NULL, 0);
6938 if (prop == NULL)
6939 return(-1);
6940 xmlUnlinkNode((xmlNodePtr) prop);
6941 xmlFreeProp(prop);
6942 return(0);
6943}
6944#endif
6945
6946#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XINCLUDE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) || defined(LIBXML_HTML_ENABLED)
6962xmlSetProp(xmlNodePtr node, const xmlChar *name, const xmlChar *value) {
6963 int len;
6964 const xmlChar *nqname;
6965
6966 if ((node == NULL) || (name == NULL) || (node->type != XML_ELEMENT_NODE))
6967 return(NULL);
6968
6969 /*
6970 * handle QNames
6971 */
6972 nqname = xmlSplitQName3(name, &len);
6973 if (nqname != NULL) {
6974 xmlNsPtr ns;
6975 xmlChar *prefix = xmlStrndup(name, len);
6976 ns = xmlSearchNs(node->doc, node, prefix);
6977 if (prefix != NULL)
6978 xmlFree(prefix);
6979 if (ns != NULL)
6980 return(xmlSetNsProp(node, ns, nqname, value));
6981 }
6982 return(xmlSetNsProp(node, NULL, name, value));
6983}
6984
6998xmlSetNsProp(xmlNodePtr node, xmlNsPtr ns, const xmlChar *name,
6999 const xmlChar *value)
7000{
7001 xmlAttrPtr prop;
7002
7003 if (ns && (ns->href == NULL))
7004 return(NULL);
7005 prop = xmlGetPropNodeInternal(node, name, (ns != NULL) ? ns->href : NULL, 0);
7006 if (prop != NULL) {
7007 /*
7008 * Modify the attribute's value.
7009 */
7010 if (prop->atype == XML_ATTRIBUTE_ID) {
7011 xmlRemoveID(node->doc, prop);
7012 prop->atype = XML_ATTRIBUTE_ID;
7013 }
7014 if (prop->children != NULL)
7016 prop->children = NULL;
7017 prop->last = NULL;
7018 prop->ns = ns;
7019 if (value != NULL) {
7020 xmlNodePtr tmp;
7021
7022 prop->children = xmlNewDocText(node->doc, value);
7023 prop->last = NULL;
7024 tmp = prop->children;
7025 while (tmp != NULL) {
7026 tmp->parent = (xmlNodePtr) prop;
7027 if (tmp->next == NULL)
7028 prop->last = tmp;
7029 tmp = tmp->next;
7030 }
7031 }
7032 if (prop->atype == XML_ATTRIBUTE_ID)
7033 xmlAddID(NULL, node->doc, value, prop);
7034 return(prop);
7035 }
7036 /*
7037 * No equal attr found; create a new one.
7038 */
7039 return(xmlNewPropInternal(node, ns, name, value, 0));
7040}
7041
7042#endif /* LIBXML_TREE_ENABLED */
7043
7051int
7052xmlNodeIsText(const xmlNode *node) {
7053 if (node == NULL) return(0);
7054
7055 if (node->type == XML_TEXT_NODE) return(1);
7056 return(0);
7057}
7058
7068int
7069xmlIsBlankNode(const xmlNode *node) {
7070 const xmlChar *cur;
7071 if (node == NULL) return(0);
7072
7073 if ((node->type != XML_TEXT_NODE) &&
7074 (node->type != XML_CDATA_SECTION_NODE))
7075 return(0);
7076 if (node->content == NULL) return(1);
7077 cur = node->content;
7078 while (*cur != 0) {
7079 if (!IS_BLANK_CH(*cur)) return(0);
7080 cur++;
7081 }
7082
7083 return(1);
7084}
7085
7097int
7099 if (node == NULL) return(-1);
7100
7101 if ((node->type != XML_TEXT_NODE) &&
7102 (node->type != XML_CDATA_SECTION_NODE) &&
7103 (node->type != XML_COMMENT_NODE) &&
7104 (node->type != XML_PI_NODE)) {
7105#ifdef DEBUG_TREE
7107 "xmlTextConcat: node is not text nor CDATA\n");
7108#endif
7109 return(-1);
7110 }
7111 /* need to check if content is currently in the dictionary */
7112 if ((node->content == (xmlChar *) &(node->properties)) ||
7113 ((node->doc != NULL) && (node->doc->dict != NULL) &&
7114 xmlDictOwns(node->doc->dict, node->content))) {
7115 node->content = xmlStrncatNew(node->content, content, len);
7116 } else {
7117 node->content = xmlStrncat(node->content, content, len);
7118 }
7119 node->properties = NULL;
7120 if (node->content == NULL)
7121 return(-1);
7122 return(0);
7123}
7124
7125/************************************************************************
7126 * *
7127 * Output : to a FILE or in memory *
7128 * *
7129 ************************************************************************/
7130
7138xmlBufferCreate(void) {
7140
7141 ret = (xmlBufferPtr) xmlMalloc(sizeof(xmlBuffer));
7142 if (ret == NULL) {
7143 xmlTreeErrMemory("creating buffer");
7144 return(NULL);
7145 }
7146 ret->use = 0;
7147 ret->size = xmlDefaultBufferSize;
7148 ret->alloc = xmlBufferAllocScheme;
7149 ret->content = (xmlChar *) xmlMallocAtomic(ret->size * sizeof(xmlChar));
7150 if (ret->content == NULL) {
7151 xmlTreeErrMemory("creating buffer");
7152 xmlFree(ret);
7153 return(NULL);
7154 }
7155 ret->content[0] = 0;
7156 ret->contentIO = NULL;
7157 return(ret);
7158}
7159
7168xmlBufferCreateSize(size_t size) {
7170
7171 if (size >= UINT_MAX)
7172 return(NULL);
7173 ret = (xmlBufferPtr) xmlMalloc(sizeof(xmlBuffer));
7174 if (ret == NULL) {
7175 xmlTreeErrMemory("creating buffer");
7176 return(NULL);
7177 }
7178 ret->use = 0;
7179 ret->alloc = xmlBufferAllocScheme;
7180 ret->size = (size ? size + 1 : 0); /* +1 for ending null */
7181 if (ret->size){
7182 ret->content = (xmlChar *) xmlMallocAtomic(ret->size * sizeof(xmlChar));
7183 if (ret->content == NULL) {
7184 xmlTreeErrMemory("creating buffer");
7185 xmlFree(ret);
7186 return(NULL);
7187 }
7188 ret->content[0] = 0;
7189 } else
7190 ret->content = NULL;
7191 ret->contentIO = NULL;
7192 return(ret);
7193}
7194
7205xmlChar *
7207 xmlChar *ret;
7208
7209 if (buf == NULL)
7210 return(NULL);
7211 if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE)
7212 return(NULL);
7213
7214 ret = buf->content;
7215 buf->content = NULL;
7216 buf->size = 0;
7217 buf->use = 0;
7218
7219 return ret;
7220}
7221
7222
7235xmlBufferCreateStatic(void *mem, size_t size) {
7237
7238 if ((mem == NULL) || (size == 0))
7239 return(NULL);
7240 if (size > UINT_MAX)
7241 return(NULL);
7242
7243 ret = (xmlBufferPtr) xmlMalloc(sizeof(xmlBuffer));
7244 if (ret == NULL) {
7245 xmlTreeErrMemory("creating buffer");
7246 return(NULL);
7247 }
7248 ret->use = size;
7249 ret->size = size;
7251 ret->content = (xmlChar *) mem;
7252 return(ret);
7253}
7254
7262void
7265 if (buf == NULL) {
7266#ifdef DEBUG_BUFFER
7268 "xmlBufferSetAllocationScheme: buf == NULL\n");
7269#endif
7270 return;
7271 }
7272 if ((buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) ||
7273 (buf->alloc == XML_BUFFER_ALLOC_IO)) return;
7278 buf->alloc = scheme;
7279}
7280
7288void
7290 if (buf == NULL) {
7291#ifdef DEBUG_BUFFER
7293 "xmlBufferFree: buf == NULL\n");
7294#endif
7295 return;
7296 }
7297
7298 if ((buf->alloc == XML_BUFFER_ALLOC_IO) &&
7299 (buf->contentIO != NULL)) {
7300 xmlFree(buf->contentIO);
7301 } else if ((buf->content != NULL) &&
7302 (buf->alloc != XML_BUFFER_ALLOC_IMMUTABLE)) {
7303 xmlFree(buf->content);
7304 }
7305 xmlFree(buf);
7306}
7307
7314void
7316 if (buf == NULL) return;
7317 if (buf->content == NULL) return;
7318 buf->use = 0;
7319 if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) {
7320 buf->content = BAD_CAST "";
7321 } else if ((buf->alloc == XML_BUFFER_ALLOC_IO) &&
7322 (buf->contentIO != NULL)) {
7323 size_t start_buf = buf->content - buf->contentIO;
7324
7325 buf->size += start_buf;
7326 buf->content = buf->contentIO;
7327 buf->content[0] = 0;
7328 } else {
7329 buf->content[0] = 0;
7330 }
7331}
7332
7342int
7343xmlBufferShrink(xmlBufferPtr buf, unsigned int len) {
7344 if (buf == NULL) return(-1);
7345 if (len == 0) return(0);
7346 if (len > buf->use) return(-1);
7347
7348 buf->use -= len;
7349 if ((buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) ||
7350 ((buf->alloc == XML_BUFFER_ALLOC_IO) && (buf->contentIO != NULL))) {
7351 /*
7352 * we just move the content pointer, but also make sure
7353 * the perceived buffer size has shrunk accordingly
7354 */
7355 buf->content += len;
7356 buf->size -= len;
7357
7358 /*
7359 * sometimes though it maybe be better to really shrink
7360 * on IO buffers
7361 */
7362 if ((buf->alloc == XML_BUFFER_ALLOC_IO) && (buf->contentIO != NULL)) {
7363 size_t start_buf = buf->content - buf->contentIO;
7364 if (start_buf >= buf->size) {
7365 memmove(buf->contentIO, &buf->content[0], buf->use);
7366 buf->content = buf->contentIO;
7367 buf->content[buf->use] = 0;
7368 buf->size += start_buf;
7369 }
7370 }
7371 } else {
7372 memmove(buf->content, &buf->content[len], buf->use);
7373 buf->content[buf->use] = 0;
7374 }
7375 return(len);
7376}
7377
7387int
7388xmlBufferGrow(xmlBufferPtr buf, unsigned int len) {
7389 unsigned int size;
7390 xmlChar *newbuf;
7391
7392 if (buf == NULL) return(-1);
7393
7394 if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return(0);
7395 if (len < buf->size - buf->use)
7396 return(0);
7397 if (len >= UINT_MAX - buf->use) {
7398 xmlTreeErrMemory("growing buffer past UINT_MAX");
7399 return(-1);
7400 }
7401
7402 if (buf->size > (size_t) len) {
7403 size = buf->size > UINT_MAX / 2 ? UINT_MAX : buf->size * 2;
7404 } else {
7405 size = buf->use + len;
7406 size = size > UINT_MAX - 100 ? UINT_MAX : size + 100;
7407 }
7408
7409 if ((buf->alloc == XML_BUFFER_ALLOC_IO) && (buf->contentIO != NULL)) {
7410 size_t start_buf = buf->content - buf->contentIO;
7411
7412 newbuf = (xmlChar *) xmlRealloc(buf->contentIO, start_buf + size);
7413 if (newbuf == NULL) {
7414 xmlTreeErrMemory("growing buffer");
7415 return(-1);
7416 }
7417 buf->contentIO = newbuf;
7418 buf->content = newbuf + start_buf;
7419 } else {
7420 newbuf = (xmlChar *) xmlRealloc(buf->content, size);
7421 if (newbuf == NULL) {
7422 xmlTreeErrMemory("growing buffer");
7423 return(-1);
7424 }
7425 buf->content = newbuf;
7426 }
7427 buf->size = size;
7428 return(buf->size - buf->use - 1);
7429}
7430
7439int
7441 size_t ret;
7442
7443 if (buf == NULL) {
7444#ifdef DEBUG_BUFFER
7446 "xmlBufferDump: buf == NULL\n");
7447#endif
7448 return(0);
7449 }
7450 if (buf->content == NULL) {
7451#ifdef DEBUG_BUFFER
7453 "xmlBufferDump: buf->content == NULL\n");
7454#endif
7455 return(0);
7456 }
7457 if (file == NULL)
7458 file = stdout;
7459 ret = fwrite(buf->content, sizeof(xmlChar), buf->use, file);
7460 return(ret > INT_MAX ? INT_MAX : (int)ret);
7461}
7462
7472const xmlChar *
7474{
7475 if(!buf)
7476 return NULL;
7477
7478 return buf->content;
7479}
7480
7490int
7492{
7493 if(!buf)
7494 return 0;
7495
7496 return buf->use;
7497}
7498
7508int
7509xmlBufferResize(xmlBufferPtr buf, unsigned int size)
7510{
7511 unsigned int newSize;
7512 xmlChar* rebuf = NULL;
7513 size_t start_buf;
7514
7515 if (buf == NULL)
7516 return(0);
7517
7518 if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return(0);
7519
7520 /* Don't resize if we don't have to */
7521 if (size < buf->size)
7522 return 1;
7523
7524 if (size > UINT_MAX - 10) {
7525 xmlTreeErrMemory("growing buffer past UINT_MAX");
7526 return 0;
7527 }
7528
7529 /* figure out new size */
7530 switch (buf->alloc){
7533 /*take care of empty case*/
7534 if (buf->size == 0)
7535 newSize = (size > UINT_MAX - 10 ? UINT_MAX : size + 10);
7536 else
7537 newSize = buf->size;
7538 while (size > newSize) {
7539 if (newSize > UINT_MAX / 2) {
7540 xmlTreeErrMemory("growing buffer");
7541 return 0;
7542 }
7543 newSize *= 2;
7544 }
7545 break;
7547 newSize = (size > UINT_MAX - 10 ? UINT_MAX : size + 10);
7548 break;
7550 if (buf->use < BASE_BUFFER_SIZE)
7551 newSize = size;
7552 else {
7553 newSize = buf->size;
7554 while (size > newSize) {
7555 if (newSize > UINT_MAX / 2) {
7556 xmlTreeErrMemory("growing buffer");
7557 return 0;
7558 }
7559 newSize *= 2;
7560 }
7561 }
7562 break;
7563
7564 default:
7565 newSize = (size > UINT_MAX - 10 ? UINT_MAX : size + 10);
7566 break;
7567 }
7568
7569 if ((buf->alloc == XML_BUFFER_ALLOC_IO) && (buf->contentIO != NULL)) {
7570 start_buf = buf->content - buf->contentIO;
7571
7572 if (start_buf > newSize) {
7573 /* move data back to start */
7574 memmove(buf->contentIO, buf->content, buf->use);
7575 buf->content = buf->contentIO;
7576 buf->content[buf->use] = 0;
7577 buf->size += start_buf;
7578 } else {
7579 rebuf = (xmlChar *) xmlRealloc(buf->contentIO, start_buf + newSize);
7580 if (rebuf == NULL) {
7581 xmlTreeErrMemory("growing buffer");
7582 return 0;
7583 }
7584 buf->contentIO = rebuf;
7585 buf->content = rebuf + start_buf;
7586 }
7587 } else {
7588 if (buf->content == NULL) {
7589 rebuf = (xmlChar *) xmlMallocAtomic(newSize);
7590 buf->use = 0;
7591 rebuf[buf->use] = 0;
7592 } else if (buf->size - buf->use < 100) {
7593 rebuf = (xmlChar *) xmlRealloc(buf->content, newSize);
7594 } else {
7595 /*
7596 * if we are reallocating a buffer far from being full, it's
7597 * better to make a new allocation and copy only the used range
7598 * and free the old one.
7599 */
7600 rebuf = (xmlChar *) xmlMallocAtomic(newSize);
7601 if (rebuf != NULL) {
7602 memcpy(rebuf, buf->content, buf->use);
7603 xmlFree(buf->content);
7604 rebuf[buf->use] = 0;
7605 }
7606 }
7607 if (rebuf == NULL) {
7608 xmlTreeErrMemory("growing buffer");
7609 return 0;
7610 }
7611 buf->content = rebuf;
7612 }
7613 buf->size = newSize;
7614
7615 return 1;
7616}
7617
7630int
7632 unsigned int needSize;
7633
7634 if ((str == NULL) || (buf == NULL)) {
7635 return -1;
7636 }
7637 if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return -1;
7638 if (len < -1) {
7639#ifdef DEBUG_BUFFER
7641 "xmlBufferAdd: len < 0\n");
7642#endif
7643 return -1;
7644 }
7645 if (len == 0) return 0;
7646
7647 if (len < 0)
7648 len = xmlStrlen(str);
7649
7650 if (len < 0) return -1;
7651 if (len == 0) return 0;
7652
7653 /* Note that both buf->size and buf->use can be zero here. */
7654 if ((unsigned) len >= buf->size - buf->use) {
7655 if ((unsigned) len >= UINT_MAX - buf->use) {
7656 xmlTreeErrMemory("growing buffer past UINT_MAX");
7657 return XML_ERR_NO_MEMORY;
7658 }
7659 needSize = buf->use + len + 1;
7660 if (!xmlBufferResize(buf, needSize)){
7661 xmlTreeErrMemory("growing buffer");
7662 return XML_ERR_NO_MEMORY;
7663 }
7664 }
7665
7666 memmove(&buf->content[buf->use], str, len*sizeof(xmlChar));
7667 buf->use += len;
7668 buf->content[buf->use] = 0;
7669 return 0;
7670}
7671
7684int
7686 unsigned int needSize;
7687
7688 if (buf == NULL)
7689 return(-1);
7690 if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return -1;
7691 if (str == NULL) {
7692#ifdef DEBUG_BUFFER
7694 "xmlBufferAddHead: str == NULL\n");
7695#endif
7696 return -1;
7697 }
7698 if (len < -1) {
7699#ifdef DEBUG_BUFFER
7701 "xmlBufferAddHead: len < 0\n");
7702#endif
7703 return -1;
7704 }
7705 if (len == 0) return 0;
7706
7707 if (len < 0)
7708 len = xmlStrlen(str);
7709
7710 if (len <= 0) return -1;
7711
7712 if ((buf->alloc == XML_BUFFER_ALLOC_IO) && (buf->contentIO != NULL)) {
7713 size_t start_buf = buf->content - buf->contentIO;
7714
7715 if (start_buf > (unsigned int) len) {
7716 /*
7717 * We can add it in the space previously shrunk
7718 */
7719 buf->content -= len;
7720 memmove(&buf->content[0], str, len);
7721 buf->use += len;
7722 buf->size += len;
7723 buf->content[buf->use] = 0;
7724 return(0);
7725 }
7726 }
7727 /* Note that both buf->size and buf->use can be zero here. */
7728 if ((unsigned) len >= buf->size - buf->use) {
7729 if ((unsigned) len >= UINT_MAX - buf->use) {
7730 xmlTreeErrMemory("growing buffer past UINT_MAX");
7731 return(-1);
7732 }
7733 needSize = buf->use + len + 1;
7734 if (!xmlBufferResize(buf, needSize)){
7735 xmlTreeErrMemory("growing buffer");
7736 return XML_ERR_NO_MEMORY;
7737 }
7738 }
7739
7740 memmove(&buf->content[len], &buf->content[0], buf->use);
7741 memmove(&buf->content[0], str, len);
7742 buf->use += len;
7743 buf->content[buf->use] = 0;
7744 return 0;
7745}
7746
7757int
7759 if (buf == NULL)
7760 return(-1);
7761 if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return -1;
7762 if (str == NULL) return -1;
7763 return xmlBufferAdd(buf, str, -1);
7764}
7765
7776int
7777xmlBufferCCat(xmlBufferPtr buf, const char *str) {
7778 return xmlBufferCat(buf, (const xmlChar *) str);
7779}
7780
7789void
7791 if (buf == NULL)
7792 return;
7793 if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return;
7794 xmlBufferCat(buf, string);
7795}
7796
7805void
7806xmlBufferWriteChar(xmlBufferPtr buf, const char *string) {
7807 if (buf == NULL)
7808 return;
7809 if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return;
7810 xmlBufferCCat(buf, string);
7811}
7812
7813
7823void
7825 const xmlChar *cur, *base;
7826 if (buf == NULL)
7827 return;
7828 if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return;
7829 if (xmlStrchr(string, '\"')) {
7830 if (xmlStrchr(string, '\'')) {
7831#ifdef DEBUG_BUFFER
7833 "xmlBufferWriteQuotedString: string contains quote and double-quotes !\n");
7834#endif
7835 xmlBufferCCat(buf, "\"");
7836 base = cur = string;
7837 while(*cur != 0){
7838 if(*cur == '"'){
7839 if (base != cur)
7841 xmlBufferAdd(buf, BAD_CAST "&quot;", 6);
7842 cur++;
7843 base = cur;
7844 }
7845 else {
7846 cur++;
7847 }
7848 }
7849 if (base != cur)
7851 xmlBufferCCat(buf, "\"");
7852 }
7853 else{
7854 xmlBufferCCat(buf, "\'");
7855 xmlBufferCat(buf, string);
7856 xmlBufferCCat(buf, "\'");
7857 }
7858 } else {
7859 xmlBufferCCat(buf, "\"");
7860 xmlBufferCat(buf, string);
7861 xmlBufferCCat(buf, "\"");
7862 }
7863}
7864
7865
7873int
7874xmlGetDocCompressMode (const xmlDoc *doc) {
7875 if (doc == NULL) return(-1);
7876 return(doc->compression);
7877}
7878
7887void
7889 if (doc == NULL) return;
7890 if (mode < 0) doc->compression = 0;
7891 else if (mode > 9) doc->compression = 9;
7892 else doc->compression = mode;
7893}
7894
7901int
7903{
7904 return (xmlCompressMode);
7905}
7906
7914void
7916 if (mode < 0) xmlCompressMode = 0;
7917 else if (mode > 9) xmlCompressMode = 9;
7918 else xmlCompressMode = mode;
7919}
7920
7921#define XML_TREE_NSMAP_PARENT -1
7922#define XML_TREE_NSMAP_XML -2
7923#define XML_TREE_NSMAP_DOC -3
7924#define XML_TREE_NSMAP_CUSTOM -4
7925
7926typedef struct xmlNsMapItem *xmlNsMapItemPtr;
7927struct xmlNsMapItem {
7928 xmlNsMapItemPtr next;
7929 xmlNsMapItemPtr prev;
7930 xmlNsPtr oldNs; /* old ns decl reference */
7931 xmlNsPtr newNs; /* new ns decl reference */
7932 int shadowDepth; /* Shadowed at this depth */
7933 /*
7934 * depth:
7935 * >= 0 == @node's ns-decls
7936 * -1 == @parent's ns-decls
7937 * -2 == the doc->oldNs XML ns-decl
7938 * -3 == the doc->oldNs storage ns-decls
7939 * -4 == ns-decls provided via custom ns-handling
7940 */
7941 int depth;
7942};
7943
7944typedef struct xmlNsMap *xmlNsMapPtr;
7945struct xmlNsMap {
7946 xmlNsMapItemPtr first;
7947 xmlNsMapItemPtr last;
7948 xmlNsMapItemPtr pool;
7949};
7950
7951#define XML_NSMAP_NOTEMPTY(m) (((m) != NULL) && ((m)->first != NULL))
7952#define XML_NSMAP_FOREACH(m, i) for (i = (m)->first; i != NULL; i = (i)->next)
7953#define XML_NSMAP_POP(m, i) \
7954 i = (m)->last; \
7955 (m)->last = (i)->prev; \
7956 if ((m)->last == NULL) \
7957 (m)->first = NULL; \
7958 else \
7959 (m)->last->next = NULL; \
7960 (i)->next = (m)->pool; \
7961 (m)->pool = i;
7962
7963/*
7964* xmlDOMWrapNsMapFree:
7965* @map: the ns-map
7966*
7967* Frees the ns-map
7968*/
7969static void
7970xmlDOMWrapNsMapFree(xmlNsMapPtr nsmap)
7971{
7972 xmlNsMapItemPtr cur, tmp;
7973
7974 if (nsmap == NULL)
7975 return;
7976 cur = nsmap->pool;
7977 while (cur != NULL) {
7978 tmp = cur;
7979 cur = cur->next;
7980 xmlFree(tmp);
7981 }
7982 cur = nsmap->first;
7983 while (cur != NULL) {
7984 tmp = cur;
7985 cur = cur->next;
7986 xmlFree(tmp);
7987 }
7988 xmlFree(nsmap);
7989}
7990
7991/*
7992* xmlDOMWrapNsMapAddItem:
7993* @map: the ns-map
7994* @oldNs: the old ns-struct
7995* @newNs: the new ns-struct
7996* @depth: depth and ns-kind information
7997*
7998* Adds an ns-mapping item.
7999*/
8000static xmlNsMapItemPtr
8001xmlDOMWrapNsMapAddItem(xmlNsMapPtr *nsmap, int position,
8002 xmlNsPtr oldNs, xmlNsPtr newNs, int depth)
8003{
8004 xmlNsMapItemPtr ret;
8005 xmlNsMapPtr map;
8006
8007 if (nsmap == NULL)
8008 return(NULL);
8009 if ((position != -1) && (position != 0))
8010 return(NULL);
8011 map = *nsmap;
8012
8013 if (map == NULL) {
8014 /*
8015 * Create the ns-map.
8016 */
8017 map = (xmlNsMapPtr) xmlMalloc(sizeof(struct xmlNsMap));
8018 if (map == NULL) {
8019 xmlTreeErrMemory("allocating namespace map");
8020 return (NULL);
8021 }
8022 memset(map, 0, sizeof(struct xmlNsMap));
8023 *nsmap = map;
8024 }
8025
8026 if (map->pool != NULL) {
8027 /*
8028 * Reuse an item from the pool.
8029 */
8030 ret = map->pool;
8031 map->pool = ret->next;
8032 memset(ret, 0, sizeof(struct xmlNsMapItem));
8033 } else {
8034 /*
8035 * Create a new item.
8036 */
8037 ret = (xmlNsMapItemPtr) xmlMalloc(sizeof(struct xmlNsMapItem));
8038 if (ret == NULL) {
8039 xmlTreeErrMemory("allocating namespace map item");
8040 return (NULL);
8041 }
8042 memset(ret, 0, sizeof(struct xmlNsMapItem));
8043 }
8044
8045 if (map->first == NULL) {
8046 /*
8047 * First ever.
8048 */
8049 map->first = ret;
8050 map->last = ret;
8051 } else if (position == -1) {
8052 /*
8053 * Append.
8054 */
8055 ret->prev = map->last;
8056 map->last->next = ret;
8057 map->last = ret;
8058 } else if (position == 0) {
8059 /*
8060 * Set on first position.
8061 */
8062 map->first->prev = ret;
8063 ret->next = map->first;
8064 map->first = ret;
8065 }
8066
8067 ret->oldNs = oldNs;
8068 ret->newNs = newNs;
8069 ret->shadowDepth = -1;
8070 ret->depth = depth;
8071 return (ret);
8072}
8073
8074/*
8075* xmlDOMWrapStoreNs:
8076* @doc: the doc
8077* @nsName: the namespace name
8078* @prefix: the prefix
8079*
8080* Creates or reuses an xmlNs struct on doc->oldNs with
8081* the given prefix and namespace name.
8082*
8083* Returns the acquired ns struct or NULL in case of an API
8084* or internal error.
8085*/
8086static xmlNsPtr
8087xmlDOMWrapStoreNs(xmlDocPtr doc,
8088 const xmlChar *nsName,
8089 const xmlChar *prefix)
8090{
8091 xmlNsPtr ns;
8092
8093 if (doc == NULL)
8094 return (NULL);
8095 ns = xmlTreeEnsureXMLDecl(doc);
8096 if (ns == NULL)
8097 return (NULL);
8098 if (ns->next != NULL) {
8099 /* Reuse. */
8100 ns = ns->next;
8101 while (ns != NULL) {
8102 if (((ns->prefix == prefix) ||
8103 xmlStrEqual(ns->prefix, prefix)) &&
8104 xmlStrEqual(ns->href, nsName)) {
8105 return (ns);
8106 }
8107 if (ns->next == NULL)
8108 break;
8109 ns = ns->next;
8110 }
8111 }
8112 /* Create. */
8113 if (ns != NULL) {
8114 ns->next = xmlNewNs(NULL, nsName, prefix);
8115 return (ns->next);
8116 }
8117 return(NULL);
8118}
8119
8120/*
8121* xmlDOMWrapNewCtxt:
8122*
8123* Allocates and initializes a new DOM-wrapper context.
8124*
8125* Returns the xmlDOMWrapCtxtPtr or NULL in case of an internal error.
8126*/
8129{
8131
8132 ret = xmlMalloc(sizeof(xmlDOMWrapCtxt));
8133 if (ret == NULL) {
8134 xmlTreeErrMemory("allocating DOM-wrapper context");
8135 return (NULL);
8136 }
8137 memset(ret, 0, sizeof(xmlDOMWrapCtxt));
8138 return (ret);
8139}
8140
8141/*
8142* xmlDOMWrapFreeCtxt:
8143* @ctxt: the DOM-wrapper context
8144*
8145* Frees the DOM-wrapper context.
8146*/
8147void
8149{
8150 if (ctxt == NULL)
8151 return;
8152 if (ctxt->namespaceMap != NULL)
8153 xmlDOMWrapNsMapFree((xmlNsMapPtr) ctxt->namespaceMap);
8154 /*
8155 * TODO: Store the namespace map in the context.
8156 */
8157 xmlFree(ctxt);
8158}
8159
8160/*
8161* xmlTreeLookupNsListByPrefix:
8162* @nsList: a list of ns-structs
8163* @prefix: the searched prefix
8164*
8165* Searches for a ns-decl with the given prefix in @nsList.
8166*
8167* Returns the ns-decl if found, NULL if not found and on
8168* API errors.
8169*/
8170static xmlNsPtr
8171xmlTreeNSListLookupByPrefix(xmlNsPtr nsList, const xmlChar *prefix)
8172{
8173 if (nsList == NULL)
8174 return (NULL);
8175 {
8176 xmlNsPtr ns;
8177 ns = nsList;
8178 do {
8179 if ((prefix == ns->prefix) ||
8180 xmlStrEqual(prefix, ns->prefix)) {
8181 return (ns);
8182 }
8183 ns = ns->next;
8184 } while (ns != NULL);
8185 }
8186 return (NULL);
8187}
8188
8189/*
8190*
8191* xmlDOMWrapNSNormGatherInScopeNs:
8192* @map: the namespace map
8193* @node: the node to start with
8194*
8195* Puts in-scope namespaces into the ns-map.
8196*
8197* Returns 0 on success, -1 on API or internal errors.
8198*/
8199static int
8200xmlDOMWrapNSNormGatherInScopeNs(xmlNsMapPtr *map,
8202{
8204 xmlNsPtr ns;
8205 xmlNsMapItemPtr mi;
8206 int shadowed;
8207
8208 if ((map == NULL) || (*map != NULL))
8209 return (-1);
8210 if ((node == NULL) || (node->type == XML_NAMESPACE_DECL))
8211 return (-1);
8212 /*
8213 * Get in-scope ns-decls of @parent.
8214 */
8215 cur = node;
8216 while ((cur != NULL) && (cur != (xmlNodePtr) cur->doc)) {
8217 if (cur->type == XML_ELEMENT_NODE) {
8218 if (cur->nsDef != NULL) {
8219 ns = cur->nsDef;
8220 do {
8221 shadowed = 0;
8222 if (XML_NSMAP_NOTEMPTY(*map)) {
8223 /*
8224 * Skip shadowed prefixes.
8225 */
8227 if ((ns->prefix == mi->newNs->prefix) ||
8228 xmlStrEqual(ns->prefix, mi->newNs->prefix)) {
8229 shadowed = 1;
8230 break;
8231 }
8232 }
8233 }
8234 /*
8235 * Insert mapping.
8236 */
8237 mi = xmlDOMWrapNsMapAddItem(map, 0, NULL,
8239 if (mi == NULL)
8240 return (-1);
8241 if (shadowed)
8242 mi->shadowDepth = 0;
8243 ns = ns->next;
8244 } while (ns != NULL);
8245 }
8246 }
8247 cur = cur->parent;
8248 }
8249 return (0);
8250}
8251
8252/*
8253* XML_TREE_ADOPT_STR: If we have a dest-dict, put @str in the dict;
8254* otherwise copy it, when it was in the source-dict.
8255*/
8256#define XML_TREE_ADOPT_STR(str) \
8257 if (adoptStr && (str != NULL)) { \
8258 if (destDoc->dict) { \
8259 const xmlChar *old = str; \
8260 str = xmlDictLookup(destDoc->dict, str, -1); \
8261 if ((sourceDoc == NULL) || (sourceDoc->dict == NULL) || \
8262 (!xmlDictOwns(sourceDoc->dict, old))) \
8263 xmlFree((char *)old); \
8264 } else if ((sourceDoc) && (sourceDoc->dict) && \
8265 xmlDictOwns(sourceDoc->dict, str)) { \
8266 str = BAD_CAST xmlStrdup(str); \
8267 } \
8268 }
8269
8270/*
8271* XML_TREE_ADOPT_STR_2: If @str was in the source-dict, then
8272* put it in dest-dict or copy it.
8273*/
8274#define XML_TREE_ADOPT_STR_2(str) \
8275 if (adoptStr && (str != NULL) && (sourceDoc != NULL) && \
8276 (sourceDoc->dict != NULL) && \
8277 xmlDictOwns(sourceDoc->dict, cur->content)) { \
8278 if (destDoc->dict) \
8279 cur->content = (xmlChar *) \
8280 xmlDictLookup(destDoc->dict, cur->content, -1); \
8281 else \
8282 cur->content = xmlStrdup(BAD_CAST cur->content); \
8283 }
8284
8285/*
8286* xmlDOMWrapNSNormAddNsMapItem2:
8287*
8288* For internal use. Adds a ns-decl mapping.
8289*
8290* Returns 0 on success, -1 on internal errors.
8291*/
8292static int
8293xmlDOMWrapNSNormAddNsMapItem2(xmlNsPtr **list, int *size, int *number,
8294 xmlNsPtr oldNs, xmlNsPtr newNs)
8295{
8296 if (*list == NULL) {
8297 *list = (xmlNsPtr *) xmlMalloc(6 * sizeof(xmlNsPtr));
8298 if (*list == NULL) {
8299 xmlTreeErrMemory("alloc ns map item");
8300 return(-1);
8301 }
8302 *size = 3;
8303 *number = 0;
8304 } else if ((*number) >= (*size)) {
8305 *size *= 2;
8306 *list = (xmlNsPtr *) xmlRealloc(*list,
8307 (*size) * 2 * sizeof(xmlNsPtr));
8308 if (*list == NULL) {
8309 xmlTreeErrMemory("realloc ns map item");
8310 return(-1);
8311 }
8312 }
8313 (*list)[2 * (*number)] = oldNs;
8314 (*list)[2 * (*number) +1] = newNs;
8315 (*number)++;
8316 return (0);
8317}
8318
8319/*
8320* xmlDOMWrapRemoveNode:
8321* @ctxt: a DOM wrapper context
8322* @doc: the doc
8323* @node: the node to be removed.
8324* @options: set of options, unused at the moment
8325*
8326* Unlinks the given node from its owner.
8327* This will substitute ns-references to node->nsDef for
8328* ns-references to doc->oldNs, thus ensuring the removed
8329* branch to be autark wrt ns-references.
8330*
8331* NOTE: This function was not intensively tested.
8332*
8333* Returns 0 on success, 1 if the node is not supported,
8334* -1 on API and internal errors.
8335*/
8336int
8339{
8340 xmlNsPtr *list = NULL;
8341 int sizeList, nbList, i, j;
8342 xmlNsPtr ns;
8343
8344 if ((node == NULL) || (doc == NULL) || (node->doc != doc))
8345 return (-1);
8346
8347 /* TODO: 0 or -1 ? */
8348 if (node->parent == NULL)
8349 return (0);
8350
8351 switch (node->type) {
8352 case XML_TEXT_NODE:
8355 case XML_PI_NODE:
8356 case XML_COMMENT_NODE:
8358 return (0);
8359 case XML_ELEMENT_NODE:
8360 case XML_ATTRIBUTE_NODE:
8361 break;
8362 default:
8363 return (1);
8364 }
8366 /*
8367 * Save out-of-scope ns-references in doc->oldNs.
8368 */
8369 do {
8370 switch (node->type) {
8371 case XML_ELEMENT_NODE:
8372 if ((ctxt == NULL) && (node->nsDef != NULL)) {
8373 ns = node->nsDef;
8374 do {
8375 if (xmlDOMWrapNSNormAddNsMapItem2(&list, &sizeList,
8376 &nbList, ns, ns) == -1)
8377 goto internal_error;
8378 ns = ns->next;
8379 } while (ns != NULL);
8380 }
8381 /* Falls through. */
8382 case XML_ATTRIBUTE_NODE:
8383 if (node->ns != NULL) {
8384 /*
8385 * Find a mapping.
8386 */
8387 if (list != NULL) {
8388 for (i = 0, j = 0; i < nbList; i++, j += 2) {
8389 if (node->ns == list[j]) {
8390 node->ns = list[++j];
8391 goto next_node;
8392 }
8393 }
8394 }
8395 ns = NULL;
8396 if (ctxt != NULL) {
8397 /*
8398 * User defined.
8399 */
8400 } else {
8401 /*
8402 * Add to doc's oldNs.
8403 */
8404 ns = xmlDOMWrapStoreNs(doc, node->ns->href,
8405 node->ns->prefix);
8406 if (ns == NULL)
8407 goto internal_error;
8408 }
8409 if (ns != NULL) {
8410 /*
8411 * Add mapping.
8412 */
8413 if (xmlDOMWrapNSNormAddNsMapItem2(&list, &sizeList,
8414 &nbList, node->ns, ns) == -1)
8415 goto internal_error;
8416 }
8417 node->ns = ns;
8418 }
8419 if ((node->type == XML_ELEMENT_NODE) &&
8420 (node->properties != NULL)) {
8421 node = (xmlNodePtr) node->properties;
8422 continue;
8423 }
8424 break;
8425 default:
8426 goto next_sibling;
8427 }
8428next_node:
8429 if ((node->type == XML_ELEMENT_NODE) &&
8430 (node->children != NULL)) {
8431 node = node->children;
8432 continue;
8433 }
8434next_sibling:
8435 if (node == NULL)
8436 break;
8437 if (node->next != NULL)
8438 node = node->next;
8439 else {
8440 node = node->parent;
8441 goto next_sibling;
8442 }
8443 } while (node != NULL);
8444
8445 if (list != NULL)
8446 xmlFree(list);
8447 return (0);
8448
8449internal_error:
8450 if (list != NULL)
8451 xmlFree(list);
8452 return (-1);
8453}
8454
8455/*
8456* xmlSearchNsByNamespaceStrict:
8457* @doc: the document
8458* @node: the start node
8459* @nsName: the searched namespace name
8460* @retNs: the resulting ns-decl
8461* @prefixed: if the found ns-decl must have a prefix (for attributes)
8462*
8463* Dynamically searches for a ns-declaration which matches
8464* the given @nsName in the ancestor-or-self axis of @node.
8465*
8466* Returns 1 if a ns-decl was found, 0 if not and -1 on API
8467* and internal errors.
8468*/
8469static int
8470xmlSearchNsByNamespaceStrict(xmlDocPtr doc, xmlNodePtr node,
8471 const xmlChar* nsName,
8472 xmlNsPtr *retNs, int prefixed)
8473{
8474 xmlNodePtr cur, prev = NULL, out = NULL;
8475 xmlNsPtr ns, prevns;
8476
8477 if ((doc == NULL) || (nsName == NULL) || (retNs == NULL))
8478 return (-1);
8479 if ((node == NULL) || (node->type == XML_NAMESPACE_DECL))
8480 return(-1);
8481
8482 *retNs = NULL;
8483 if (xmlStrEqual(nsName, XML_XML_NAMESPACE)) {
8484 *retNs = xmlTreeEnsureXMLDecl(doc);
8485 if (*retNs == NULL)
8486 return (-1);
8487 return (1);
8488 }
8489 cur = node;
8490 do {
8491 if (cur->type == XML_ELEMENT_NODE) {
8492 if (cur->nsDef != NULL) {
8493 for (ns = cur->nsDef; ns != NULL; ns = ns->next) {
8494 if (prefixed && (ns->prefix == NULL))
8495 continue;
8496 if (prev != NULL) {
8497 /*
8498 * Check the last level of ns-decls for a
8499 * shadowing prefix.
8500 */
8501 prevns = prev->nsDef;
8502 do {
8503 if ((prevns->prefix == ns->prefix) ||
8504 ((prevns->prefix != NULL) &&
8505 (ns->prefix != NULL) &&
8506 xmlStrEqual(prevns->prefix, ns->prefix))) {
8507 /*
8508 * Shadowed.
8509 */
8510 break;
8511 }
8512 prevns = prevns->next;
8513 } while (prevns != NULL);
8514 if (prevns != NULL)
8515 continue;
8516 }
8517 /*
8518 * Ns-name comparison.
8519 */
8520 if ((nsName == ns->href) ||
8521 xmlStrEqual(nsName, ns->href)) {
8522 /*
8523 * At this point the prefix can only be shadowed,
8524 * if we are the the (at least) 3rd level of
8525 * ns-decls.
8526 */
8527 if (out) {
8528 int ret;
8529
8530 ret = xmlNsInScope(doc, node, prev, ns->prefix);
8531 if (ret < 0)
8532 return (-1);
8533 /*
8534 * TODO: Should we try to find a matching ns-name
8535 * only once? This here keeps on searching.
8536 * I think we should try further since, there might
8537 * be an other matching ns-decl with an unshadowed
8538 * prefix.
8539 */
8540 if (! ret)
8541 continue;
8542 }
8543 *retNs = ns;
8544 return (1);
8545 }
8546 }
8547 out = prev;
8548 prev = cur;
8549 }
8550 } else if ((cur->type == XML_ENTITY_NODE) ||
8551 (cur->type == XML_ENTITY_DECL))
8552 return (0);
8553 cur = cur->parent;
8554 } while ((cur != NULL) && (cur->doc != (xmlDocPtr) cur));
8555 return (0);
8556}
8557
8558/*
8559* xmlSearchNsByPrefixStrict:
8560* @doc: the document
8561* @node: the start node
8562* @prefix: the searched namespace prefix
8563* @retNs: the resulting ns-decl
8564*
8565* Dynamically searches for a ns-declaration which matches
8566* the given @nsName in the ancestor-or-self axis of @node.
8567*
8568* Returns 1 if a ns-decl was found, 0 if not and -1 on API
8569* and internal errors.
8570*/
8571static int
8572xmlSearchNsByPrefixStrict(xmlDocPtr doc, xmlNodePtr node,
8573 const xmlChar* prefix,
8574 xmlNsPtr *retNs)
8575{
8577 xmlNsPtr ns;
8578
8579 if ((doc == NULL) || (node == NULL) || (node->type == XML_NAMESPACE_DECL))
8580 return(-1);
8581
8582 if (retNs)
8583 *retNs = NULL;
8584 if (IS_STR_XML(prefix)) {
8585 if (retNs) {
8586 *retNs = xmlTreeEnsureXMLDecl(doc);
8587 if (*retNs == NULL)
8588 return (-1);
8589 }
8590 return (1);
8591 }
8592 cur = node;
8593 do {
8594 if (cur->type == XML_ELEMENT_NODE) {
8595 if (cur->nsDef != NULL) {
8596 ns = cur->nsDef;
8597 do {
8598 if ((prefix == ns->prefix) ||
8599 xmlStrEqual(prefix, ns->prefix))
8600 {
8601 /*
8602 * Disabled namespaces, e.g. xmlns:abc="".
8603 */
8604 if (ns->href == NULL)
8605 return(0);
8606 if (retNs)
8607 *retNs = ns;
8608 return (1);
8609 }
8610 ns = ns->next;
8611 } while (ns != NULL);
8612 }
8613 } else if ((cur->type == XML_ENTITY_NODE) ||
8614 (cur->type == XML_ENTITY_DECL))
8615 return (0);
8616 cur = cur->parent;
8617 } while ((cur != NULL) && (cur->doc != (xmlDocPtr) cur));
8618 return (0);
8619}
8620
8621/*
8622* xmlDOMWrapNSNormDeclareNsForced:
8623* @doc: the doc
8624* @elem: the element-node to declare on
8625* @nsName: the namespace-name of the ns-decl
8626* @prefix: the preferred prefix of the ns-decl
8627* @checkShadow: ensure that the new ns-decl doesn't shadow ancestor ns-decls
8628*
8629* Declares a new namespace on @elem. It tries to use the
8630* given @prefix; if a ns-decl with the given prefix is already existent
8631* on @elem, it will generate an other prefix.
8632*
8633* Returns 1 if a ns-decl was found, 0 if not and -1 on API
8634* and internal errors.
8635*/
8636static xmlNsPtr
8637xmlDOMWrapNSNormDeclareNsForced(xmlDocPtr doc,
8639 const xmlChar *nsName,
8640 const xmlChar *prefix,
8641 int checkShadow)
8642{
8643
8644 xmlNsPtr ret;
8645 char buf[50];
8646 const xmlChar *pref;
8647 int counter = 0;
8648
8649 if ((doc == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
8650 return(NULL);
8651 /*
8652 * Create a ns-decl on @anchor.
8653 */
8654 pref = prefix;
8655 while (1) {
8656 /*
8657 * Lookup whether the prefix is unused in elem's ns-decls.
8658 */
8659 if ((elem->nsDef != NULL) &&
8660 (xmlTreeNSListLookupByPrefix(elem->nsDef, pref) != NULL))
8661 goto ns_next_prefix;
8662 if (checkShadow && elem->parent &&
8663 ((xmlNodePtr) elem->parent->doc != elem->parent)) {
8664 /*
8665 * Does it shadow ancestor ns-decls?
8666 */
8667 if (xmlSearchNsByPrefixStrict(doc, elem->parent, pref, NULL) == 1)
8668 goto ns_next_prefix;
8669 }
8670 ret = xmlNewNs(NULL, nsName, pref);
8671 if (ret == NULL)
8672 return (NULL);
8673 if (elem->nsDef == NULL)
8674 elem->nsDef = ret;
8675 else {
8676 xmlNsPtr ns2 = elem->nsDef;
8677 while (ns2->next != NULL)
8678 ns2 = ns2->next;
8679 ns2->next = ret;
8680 }
8681 return (ret);
8682ns_next_prefix:
8683 counter++;
8684 if (counter > 1000)
8685 return (NULL);
8686 if (prefix == NULL) {
8687 snprintf((char *) buf, sizeof(buf),
8688 "ns_%d", counter);
8689 } else
8690 snprintf((char *) buf, sizeof(buf),
8691 "%.30s_%d", (char *)prefix, counter);
8692 pref = BAD_CAST buf;
8693 }
8694}
8695
8696/*
8697* xmlDOMWrapNSNormAcquireNormalizedNs:
8698* @doc: the doc
8699* @elem: the element-node to declare namespaces on
8700* @ns: the ns-struct to use for the search
8701* @retNs: the found/created ns-struct
8702* @nsMap: the ns-map
8703* @depth: the current tree depth
8704* @ancestorsOnly: search in ancestor ns-decls only
8705* @prefixed: if the searched ns-decl must have a prefix (for attributes)
8706*
8707* Searches for a matching ns-name in the ns-decls of @nsMap, if not
8708* found it will either declare it on @elem, or store it in doc->oldNs.
8709* If a new ns-decl needs to be declared on @elem, it tries to use the
8710* @ns->prefix for it, if this prefix is already in use on @elem, it will
8711* change the prefix or the new ns-decl.
8712*
8713* Returns 0 if succeeded, -1 otherwise and on API/internal errors.
8714*/
8715static int
8716xmlDOMWrapNSNormAcquireNormalizedNs(xmlDocPtr doc,
8718 xmlNsPtr ns,
8719 xmlNsPtr *retNs,
8720 xmlNsMapPtr *nsMap,
8721
8722 int depth,
8723 int ancestorsOnly,
8724 int prefixed)
8725{
8726 xmlNsMapItemPtr mi;
8727
8728 if ((doc == NULL) || (ns == NULL) || (retNs == NULL) ||
8729 (nsMap == NULL))
8730 return (-1);
8731
8732 *retNs = NULL;
8733 /*
8734 * Handle XML namespace.
8735 */
8736 if (IS_STR_XML(ns->prefix)) {
8737 /*
8738 * Insert XML namespace mapping.
8739 */
8740 *retNs = xmlTreeEnsureXMLDecl(doc);
8741 if (*retNs == NULL)
8742 return (-1);
8743 return (0);
8744 }
8745 /*
8746 * If the search should be done in ancestors only and no
8747 * @elem (the first ancestor) was specified, then skip the search.
8748 */
8749 if ((XML_NSMAP_NOTEMPTY(*nsMap)) &&
8750 (! (ancestorsOnly && (elem == NULL))))
8751 {
8752 /*
8753 * Try to find an equal ns-name in in-scope ns-decls.
8754 */
8755 XML_NSMAP_FOREACH(*nsMap, mi) {
8756 if ((mi->depth >= XML_TREE_NSMAP_PARENT) &&
8757 /*
8758 * ancestorsOnly: This should be turned on to gain speed,
8759 * if one knows that the branch itself was already
8760 * ns-wellformed and no stale references existed.
8761 * I.e. it searches in the ancestor axis only.
8762 */
8763 ((! ancestorsOnly) || (mi->depth == XML_TREE_NSMAP_PARENT)) &&
8764 /* Skip shadowed prefixes. */
8765 (mi->shadowDepth == -1) &&
8766 /* Skip xmlns="" or xmlns:foo="". */
8767 ((mi->newNs->href != NULL) &&
8768 (mi->newNs->href[0] != 0)) &&
8769 /* Ensure a prefix if wanted. */
8770 ((! prefixed) || (mi->newNs->prefix != NULL)) &&
8771 /* Equal ns name */
8772 ((mi->newNs->href == ns->href) ||
8773 xmlStrEqual(mi->newNs->href, ns->href))) {
8774 /* Set the mapping. */
8775 mi->oldNs = ns;
8776 *retNs = mi->newNs;
8777 return (0);
8778 }
8779 }
8780 }
8781 /*
8782 * No luck, the namespace is out of scope or shadowed.
8783 */
8784 if (elem == NULL) {
8785 xmlNsPtr tmpns;
8786
8787 /*
8788 * Store ns-decls in "oldNs" of the document-node.
8789 */
8790 tmpns = xmlDOMWrapStoreNs(doc, ns->href, ns->prefix);
8791 if (tmpns == NULL)
8792 return (-1);
8793 /*
8794 * Insert mapping.
8795 */
8796 if (xmlDOMWrapNsMapAddItem(nsMap, -1, ns,
8797 tmpns, XML_TREE_NSMAP_DOC) == NULL) {
8798 xmlFreeNs(tmpns);
8799 return (-1);
8800 }
8801 *retNs = tmpns;
8802 } else {
8803 xmlNsPtr tmpns;
8804
8805 tmpns = xmlDOMWrapNSNormDeclareNsForced(doc, elem, ns->href,
8806 ns->prefix, 0);
8807 if (tmpns == NULL)
8808 return (-1);
8809
8810 if (*nsMap != NULL) {
8811 /*
8812 * Does it shadow ancestor ns-decls?
8813 */
8814 XML_NSMAP_FOREACH(*nsMap, mi) {
8815 if ((mi->depth < depth) &&
8816 (mi->shadowDepth == -1) &&
8817 ((ns->prefix == mi->newNs->prefix) ||
8818 xmlStrEqual(ns->prefix, mi->newNs->prefix))) {
8819 /*
8820 * Shadows.
8821 */
8822 mi->shadowDepth = depth;
8823 break;
8824 }
8825 }
8826 }
8827 if (xmlDOMWrapNsMapAddItem(nsMap, -1, ns, tmpns, depth) == NULL) {
8828 xmlFreeNs(tmpns);
8829 return (-1);
8830 }
8831 *retNs = tmpns;
8832 }
8833 return (0);
8834}
8835
8836typedef enum {
8837 XML_DOM_RECONNS_REMOVEREDUND = 1<<0
8838} xmlDOMReconcileNSOptions;
8839
8840/*
8841* xmlDOMWrapReconcileNamespaces:
8842* @ctxt: DOM wrapper context, unused at the moment
8843* @elem: the element-node
8844* @options: option flags
8845*
8846* Ensures that ns-references point to ns-decls hold on element-nodes.
8847* Ensures that the tree is namespace wellformed by creating additional
8848* ns-decls where needed. Note that, since prefixes of already existent
8849* ns-decls can be shadowed by this process, it could break QNames in
8850* attribute values or element content.
8851*
8852* NOTE: This function was not intensively tested.
8853*
8854* Returns 0 if succeeded, -1 otherwise and on API/internal errors.
8855*/
8856
8857int
8860 int options)
8861{
8862 int depth = -1, adoptns = 0, parnsdone = 0;
8863 xmlNsPtr ns, prevns;
8864 xmlDocPtr doc;
8865 xmlNodePtr cur, curElem = NULL;
8866 xmlNsMapPtr nsMap = NULL;
8867 xmlNsMapItemPtr /* topmi = NULL, */ mi;
8868 /* @ancestorsOnly should be set by an option flag. */
8869 int ancestorsOnly = 0;
8870 int optRemoveRedundantNS =
8871 ((xmlDOMReconcileNSOptions) options & XML_DOM_RECONNS_REMOVEREDUND) ? 1 : 0;
8872 xmlNsPtr *listRedund = NULL;
8873 int sizeRedund = 0, nbRedund = 0, ret, i, j;
8874
8875 if ((elem == NULL) || (elem->doc == NULL) ||
8876 (elem->type != XML_ELEMENT_NODE))
8877 return (-1);
8878
8879 doc = elem->doc;
8880 cur = elem;
8881 do {
8882 switch (cur->type) {
8883 case XML_ELEMENT_NODE:
8884 adoptns = 1;
8885 curElem = cur;
8886 depth++;
8887 /*
8888 * Namespace declarations.
8889 */
8890 if (cur->nsDef != NULL) {
8891 prevns = NULL;
8892 ns = cur->nsDef;
8893 while (ns != NULL) {
8894 if (! parnsdone) {
8895 if ((elem->parent) &&
8896 ((xmlNodePtr) elem->parent->doc != elem->parent)) {
8897 /*
8898 * Gather ancestor in-scope ns-decls.
8899 */
8900 if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap,
8901 elem->parent) == -1)
8902 goto internal_error;
8903 }
8904 parnsdone = 1;
8905 }
8906
8907 /*
8908 * Lookup the ns ancestor-axis for equal ns-decls in scope.
8909 */
8910 if (optRemoveRedundantNS && XML_NSMAP_NOTEMPTY(nsMap)) {
8911 XML_NSMAP_FOREACH(nsMap, mi) {
8912 if ((mi->depth >= XML_TREE_NSMAP_PARENT) &&
8913 (mi->shadowDepth == -1) &&
8914 ((ns->prefix == mi->newNs->prefix) ||
8915 xmlStrEqual(ns->prefix, mi->newNs->prefix)) &&
8916 ((ns->href == mi->newNs->href) ||
8917 xmlStrEqual(ns->href, mi->newNs->href)))
8918 {
8919 /*
8920 * A redundant ns-decl was found.
8921 * Add it to the list of redundant ns-decls.
8922 */
8923 if (xmlDOMWrapNSNormAddNsMapItem2(&listRedund,
8924 &sizeRedund, &nbRedund, ns, mi->newNs) == -1)
8925 goto internal_error;
8926 /*
8927 * Remove the ns-decl from the element-node.
8928 */
8929 if (prevns)
8930 prevns->next = ns->next;
8931 else
8932 cur->nsDef = ns->next;
8933 goto next_ns_decl;
8934 }
8935 }
8936 }
8937
8938 /*
8939 * Skip ns-references handling if the referenced
8940 * ns-decl is declared on the same element.
8941 */
8942 if ((cur->ns != NULL) && adoptns && (cur->ns == ns))
8943 adoptns = 0;
8944 /*
8945 * Does it shadow any ns-decl?
8946 */
8947 if (XML_NSMAP_NOTEMPTY(nsMap)) {
8948 XML_NSMAP_FOREACH(nsMap, mi) {
8949 if ((mi->depth >= XML_TREE_NSMAP_PARENT) &&
8950 (mi->shadowDepth == -1) &&
8951 ((ns->prefix == mi->newNs->prefix) ||
8952 xmlStrEqual(ns->prefix, mi->newNs->prefix))) {
8953
8954 mi->shadowDepth = depth;
8955 }
8956 }
8957 }
8958 /*
8959 * Push mapping.
8960 */
8961 if (xmlDOMWrapNsMapAddItem(&nsMap, -1, ns, ns,
8962 depth) == NULL)
8963 goto internal_error;
8964
8965 prevns = ns;
8966next_ns_decl:
8967 ns = ns->next;
8968 }
8969 }
8970 if (! adoptns)
8971 goto ns_end;
8972 /* Falls through. */
8973 case XML_ATTRIBUTE_NODE:
8974 /* No ns, no fun. */
8975 if (cur->ns == NULL)
8976 goto ns_end;
8977
8978 if (! parnsdone) {
8979 if ((elem->parent) &&
8980 ((xmlNodePtr) elem->parent->doc != elem->parent)) {
8981 if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap,
8982 elem->parent) == -1)
8983 goto internal_error;
8984 }
8985 parnsdone = 1;
8986 }
8987 /*
8988 * Adjust the reference if this was a redundant ns-decl.
8989 */
8990 if (listRedund) {
8991 for (i = 0, j = 0; i < nbRedund; i++, j += 2) {
8992 if (cur->ns == listRedund[j]) {
8993 cur->ns = listRedund[++j];
8994 break;
8995 }
8996 }
8997 }
8998 /*
8999 * Adopt ns-references.
9000 */
9001 if (XML_NSMAP_NOTEMPTY(nsMap)) {
9002 /*
9003 * Search for a mapping.
9004 */
9005 XML_NSMAP_FOREACH(nsMap, mi) {
9006 if ((mi->shadowDepth == -1) &&
9007 (cur->ns == mi->oldNs)) {
9008
9009 cur->ns = mi->newNs;
9010 goto ns_end;
9011 }
9012 }
9013 }
9014 /*
9015 * Acquire a normalized ns-decl and add it to the map.
9016 */
9017 if (xmlDOMWrapNSNormAcquireNormalizedNs(doc, curElem,
9018 cur->ns, &ns,
9019 &nsMap, depth,
9020 ancestorsOnly,
9021 (cur->type == XML_ATTRIBUTE_NODE) ? 1 : 0) == -1)
9022 goto internal_error;
9023 cur->ns = ns;
9024
9025ns_end:
9026 if ((cur->type == XML_ELEMENT_NODE) &&
9027 (cur->properties != NULL)) {
9028 /*
9029 * Process attributes.
9030 */
9031 cur = (xmlNodePtr) cur->properties;
9032 continue;
9033 }
9034 break;
9035 default:
9036 goto next_sibling;
9037 }
9038into_content:
9039 if ((cur->type == XML_ELEMENT_NODE) &&
9040 (cur->children != NULL)) {
9041 /*
9042 * Process content of element-nodes only.
9043 */
9044 cur = cur->children;
9045 continue;
9046 }
9047next_sibling:
9048 if (cur == elem)
9049 break;
9050 if (cur->type == XML_ELEMENT_NODE) {
9051 if (XML_NSMAP_NOTEMPTY(nsMap)) {
9052 /*
9053 * Pop mappings.
9054 */
9055 while ((nsMap->last != NULL) &&
9056 (nsMap->last->depth >= depth))
9057 {
9058 XML_NSMAP_POP(nsMap, mi)
9059 }
9060 /*
9061 * Unshadow.
9062 */
9063 XML_NSMAP_FOREACH(nsMap, mi) {
9064 if (mi->shadowDepth >= depth)
9065 mi->shadowDepth = -1;
9066 }
9067 }
9068 depth--;
9069 }
9070 if (cur->next != NULL)
9071 cur = cur->next;
9072 else {
9073 if (cur->type == XML_ATTRIBUTE_NODE) {
9074 cur = cur->parent;
9075 goto into_content;
9076 }
9077 cur = cur->parent;
9078 goto next_sibling;
9079 }
9080 } while (cur != NULL);
9081
9082 ret = 0;
9083 goto exit;
9084internal_error:
9085 ret = -1;
9086exit:
9087 if (listRedund) {
9088 for (i = 0, j = 0; i < nbRedund; i++, j += 2) {
9089 xmlFreeNs(listRedund[j]);
9090 }
9091 xmlFree(listRedund);
9092 }
9093 if (nsMap != NULL)
9094 xmlDOMWrapNsMapFree(nsMap);
9095 return (ret);
9096}
9097
9098/*
9099* xmlDOMWrapAdoptBranch:
9100* @ctxt: the optional context for custom processing
9101* @sourceDoc: the optional sourceDoc
9102* @node: the element-node to start with
9103* @destDoc: the destination doc for adoption
9104* @destParent: the optional new parent of @node in @destDoc
9105* @options: option flags
9106*
9107* Ensures that ns-references point to @destDoc: either to
9108* elements->nsDef entries if @destParent is given, or to
9109* @destDoc->oldNs otherwise.
9110* If @destParent is given, it ensures that the tree is namespace
9111* wellformed by creating additional ns-decls where needed.
9112* Note that, since prefixes of already existent ns-decls can be
9113* shadowed by this process, it could break QNames in attribute
9114* values or element content.
9115*
9116* NOTE: This function was not intensively tested.
9117*
9118* Returns 0 if succeeded, -1 otherwise and on API/internal errors.
9119*/
9120static int
9121xmlDOMWrapAdoptBranch(xmlDOMWrapCtxtPtr ctxt,
9122 xmlDocPtr sourceDoc,
9124 xmlDocPtr destDoc,
9125 xmlNodePtr destParent,
9127{
9128 int ret = 0;
9129 xmlNodePtr cur, curElem = NULL;
9130 xmlNsMapPtr nsMap = NULL;
9131 xmlNsMapItemPtr mi;
9132 xmlNsPtr ns = NULL;
9133 int depth = -1, adoptStr = 1;
9134 /* gather @parent's ns-decls. */
9135 int parnsdone;
9136 /* @ancestorsOnly should be set per option. */
9137 int ancestorsOnly = 0;
9138
9139 /*
9140 * Optimize string adoption for equal or none dicts.
9141 */
9142 if ((sourceDoc != NULL) &&
9143 (sourceDoc->dict == destDoc->dict))
9144 adoptStr = 0;
9145 else
9146 adoptStr = 1;
9147
9148 /*
9149 * Get the ns-map from the context if available.
9150 */
9151 if (ctxt)
9152 nsMap = (xmlNsMapPtr) ctxt->namespaceMap;
9153 /*
9154 * Disable search for ns-decls in the parent-axis of the
9155 * destination element, if:
9156 * 1) there's no destination parent
9157 * 2) custom ns-reference handling is used
9158 */
9159 if ((destParent == NULL) ||
9160 (ctxt && ctxt->getNsForNodeFunc))
9161 {
9162 parnsdone = 1;
9163 } else
9164 parnsdone = 0;
9165
9166 cur = node;
9167 if ((cur != NULL) && (cur->type == XML_NAMESPACE_DECL))
9168 goto internal_error;
9169
9170 while (cur != NULL) {
9171 /*
9172 * Paranoid source-doc sanity check.
9173 */
9174 if (cur->doc != sourceDoc) {
9175 /*
9176 * We'll assume XIncluded nodes if the doc differs.
9177 * TODO: Do we need to reconciliate XIncluded nodes?
9178 * This here skips XIncluded nodes and tries to handle
9179 * broken sequences.
9180 */
9181 if (cur->next == NULL)
9182 goto leave_node;
9183 do {
9184 cur = cur->next;
9185 if ((cur->type == XML_XINCLUDE_END) ||
9186 (cur->doc == node->doc))
9187 break;
9188 } while (cur->next != NULL);
9189
9190 if (cur->doc != node->doc)
9191 goto leave_node;
9192 }
9193 cur->doc = destDoc;
9194 switch (cur->type) {
9195 case XML_XINCLUDE_START:
9196 case XML_XINCLUDE_END:
9197 /*
9198 * TODO
9199 */
9200 return (-1);
9201 case XML_ELEMENT_NODE:
9202 curElem = cur;
9203 depth++;
9204 /*
9205 * Namespace declarations.
9206 * - ns->href and ns->prefix are never in the dict, so
9207 * we need not move the values over to the destination dict.
9208 * - Note that for custom handling of ns-references,
9209 * the ns-decls need not be stored in the ns-map,
9210 * since they won't be referenced by node->ns.
9211 */
9212 if ((cur->nsDef) &&
9213 ((ctxt == NULL) || (ctxt->getNsForNodeFunc == NULL)))
9214 {
9215 if (! parnsdone) {
9216 /*
9217 * Gather @parent's in-scope ns-decls.
9218 */
9219 if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap,
9220 destParent) == -1)
9221 goto internal_error;
9222 parnsdone = 1;
9223 }
9224 for (ns = cur->nsDef; ns != NULL; ns = ns->next) {
9225 /*
9226 * NOTE: ns->prefix and ns->href are never in the dict.
9227 * XML_TREE_ADOPT_STR(ns->prefix)
9228 * XML_TREE_ADOPT_STR(ns->href)
9229 */
9230 /*
9231 * Does it shadow any ns-decl?
9232 */
9233 if (XML_NSMAP_NOTEMPTY(nsMap)) {
9234 XML_NSMAP_FOREACH(nsMap, mi) {
9235 if ((mi->depth >= XML_TREE_NSMAP_PARENT) &&
9236 (mi->shadowDepth == -1) &&
9237 ((ns->prefix == mi->newNs->prefix) ||
9239 mi->newNs->prefix))) {
9240
9241 mi->shadowDepth = depth;
9242 }
9243 }
9244 }
9245 /*
9246 * Push mapping.
9247 */
9248 if (xmlDOMWrapNsMapAddItem(&nsMap, -1,
9249 ns, ns, depth) == NULL)
9250 goto internal_error;
9251 }
9252 }
9253 /* Falls through. */
9254 case XML_ATTRIBUTE_NODE:
9255 /* No namespace, no fun. */
9256 if (cur->ns == NULL)
9257 goto ns_end;
9258
9259 if (! parnsdone) {
9260 if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap,
9261 destParent) == -1)
9262 goto internal_error;
9263 parnsdone = 1;
9264 }
9265 /*
9266 * Adopt ns-references.
9267 */
9268 if (XML_NSMAP_NOTEMPTY(nsMap)) {
9269 /*
9270 * Search for a mapping.
9271 */
9272 XML_NSMAP_FOREACH(nsMap, mi) {
9273 if ((mi->shadowDepth == -1) &&
9274 (cur->ns == mi->oldNs)) {
9275
9276 cur->ns = mi->newNs;
9277 goto ns_end;
9278 }
9279 }
9280 }
9281 /*
9282 * No matching namespace in scope. We need a new one.
9283 */
9284 if ((ctxt) && (ctxt->getNsForNodeFunc)) {
9285 /*
9286 * User-defined behaviour.
9287 */
9288 ns = ctxt->getNsForNodeFunc(ctxt, cur,
9289 cur->ns->href, cur->ns->prefix);
9290 /*
9291 * Insert mapping if ns is available; it's the users fault
9292 * if not.
9293 */
9294 if (xmlDOMWrapNsMapAddItem(&nsMap, -1,
9295 cur->ns, ns, XML_TREE_NSMAP_CUSTOM) == NULL)
9296 goto internal_error;
9297 cur->ns = ns;
9298 } else {
9299 /*
9300 * Acquire a normalized ns-decl and add it to the map.
9301 */
9302 if (xmlDOMWrapNSNormAcquireNormalizedNs(destDoc,
9303 /* ns-decls on curElem or on destDoc->oldNs */
9304 destParent ? curElem : NULL,
9305 cur->ns, &ns,
9306 &nsMap, depth,
9307 ancestorsOnly,
9308 /* ns-decls must be prefixed for attributes. */
9309 (cur->type == XML_ATTRIBUTE_NODE) ? 1 : 0) == -1)
9310 goto internal_error;
9311 cur->ns = ns;
9312 }
9313ns_end:
9314 /*
9315 * Further node properties.
9316 * TODO: Is this all?
9317 */
9318 XML_TREE_ADOPT_STR(cur->name)
9319 if (cur->type == XML_ELEMENT_NODE) {
9320 cur->psvi = NULL;
9321 cur->line = 0;
9322 cur->extra = 0;
9323 /*
9324 * Walk attributes.
9325 */
9326 if (cur->properties != NULL) {
9327 /*
9328 * Process first attribute node.
9329 */
9330 cur = (xmlNodePtr) cur->properties;
9331 continue;
9332 }
9333 } else {
9334 /*
9335 * Attributes.
9336 */
9337 if ((sourceDoc != NULL) &&
9338 (((xmlAttrPtr) cur)->atype == XML_ATTRIBUTE_ID))
9339 {
9340 xmlRemoveID(sourceDoc, (xmlAttrPtr) cur);
9341 }
9342 ((xmlAttrPtr) cur)->atype = 0;
9343 ((xmlAttrPtr) cur)->psvi = NULL;
9344 }
9345 break;
9346 case XML_TEXT_NODE:
9348 /*
9349 * This puts the content in the dest dict, only if
9350 * it was previously in the source dict.
9351 */
9352 XML_TREE_ADOPT_STR_2(cur->content)
9353 goto leave_node;
9355 /*
9356 * Remove reference to the entity-node.
9357 */
9358 cur->content = NULL;
9359 cur->children = NULL;
9360 cur->last = NULL;
9361 if ((destDoc->intSubset) || (destDoc->extSubset)) {
9362 xmlEntityPtr ent;
9363 /*
9364 * Assign new entity-node if available.
9365 */
9366 ent = xmlGetDocEntity(destDoc, cur->name);
9367 if (ent != NULL) {
9368 cur->content = ent->content;
9369 cur->children = (xmlNodePtr) ent;
9370 cur->last = (xmlNodePtr) ent;
9371 }
9372 }
9373 goto leave_node;
9374 case XML_PI_NODE:
9375 XML_TREE_ADOPT_STR(cur->name)
9377 break;
9378 case XML_COMMENT_NODE:
9379 break;
9380 default:
9381 goto internal_error;
9382 }
9383 /*
9384 * Walk the tree.
9385 */
9386 if (cur->children != NULL) {
9387 cur = cur->children;
9388 continue;
9389 }
9390
9391leave_node:
9392 if (cur == node)
9393 break;
9394 if ((cur->type == XML_ELEMENT_NODE) ||
9395 (cur->type == XML_XINCLUDE_START) ||
9396 (cur->type == XML_XINCLUDE_END))
9397 {
9398 /*
9399 * TODO: Do we expect nsDefs on XML_XINCLUDE_START?
9400 */
9401 if (XML_NSMAP_NOTEMPTY(nsMap)) {
9402 /*
9403 * Pop mappings.
9404 */
9405 while ((nsMap->last != NULL) &&
9406 (nsMap->last->depth >= depth))
9407 {
9408 XML_NSMAP_POP(nsMap, mi)
9409 }
9410 /*
9411 * Unshadow.
9412 */
9413 XML_NSMAP_FOREACH(nsMap, mi) {
9414 if (mi->shadowDepth >= depth)
9415 mi->shadowDepth = -1;
9416 }
9417 }
9418 depth--;
9419 }
9420 if (cur->next != NULL)
9421 cur = cur->next;
9422 else if ((cur->type == XML_ATTRIBUTE_NODE) &&
9423 (cur->parent->children != NULL))
9424 {
9425 cur = cur->parent->children;
9426 } else {
9427 cur = cur->parent;
9428 goto leave_node;
9429 }
9430 }
9431
9432 goto exit;
9433
9434internal_error:
9435 ret = -1;
9436
9437exit:
9438 /*
9439 * Cleanup.
9440 */
9441 if (nsMap != NULL) {
9442 if ((ctxt) && (ctxt->namespaceMap == nsMap)) {
9443 /*
9444 * Just cleanup the map but don't free.
9445 */
9446 if (nsMap->first) {
9447 if (nsMap->pool)
9448 nsMap->last->next = nsMap->pool;
9449 nsMap->pool = nsMap->first;
9450 nsMap->first = NULL;
9451 }
9452 } else
9453 xmlDOMWrapNsMapFree(nsMap);
9454 }
9455 return(ret);
9456}
9457
9458/*
9459* xmlDOMWrapCloneNode:
9460* @ctxt: the optional context for custom processing
9461* @sourceDoc: the optional sourceDoc
9462* @node: the node to start with
9463* @resNode: the clone of the given @node
9464* @destDoc: the destination doc
9465* @destParent: the optional new parent of @node in @destDoc
9466* @deep: descend into child if set
9467* @options: option flags
9468*
9469* References of out-of scope ns-decls are remapped to point to @destDoc:
9470* 1) If @destParent is given, then nsDef entries on element-nodes are used
9471* 2) If *no* @destParent is given, then @destDoc->oldNs entries are used.
9472* This is the case when you don't know already where the cloned branch
9473* will be added to.
9474*
9475* If @destParent is given, it ensures that the tree is namespace
9476* wellformed by creating additional ns-decls where needed.
9477* Note that, since prefixes of already existent ns-decls can be
9478* shadowed by this process, it could break QNames in attribute
9479* values or element content.
9480* TODO:
9481* 1) What to do with XInclude? Currently this returns an error for XInclude.
9482*
9483* Returns 0 if the operation succeeded,
9484* 1 if a node of unsupported (or not yet supported) type was given,
9485* -1 on API/internal errors.
9486*/
9487
9488int
9490 xmlDocPtr sourceDoc,
9492 xmlNodePtr *resNode,
9493 xmlDocPtr destDoc,
9494 xmlNodePtr destParent,
9495 int deep,
9497{
9498 int ret = 0;
9499 xmlNodePtr cur, curElem = NULL;
9500 xmlNsMapPtr nsMap = NULL;
9501 xmlNsMapItemPtr mi;
9502 xmlNsPtr ns;
9503 int depth = -1;
9504 /* int adoptStr = 1; */
9505 /* gather @parent's ns-decls. */
9506 int parnsdone = 0;
9507 /*
9508 * @ancestorsOnly:
9509 * TODO: @ancestorsOnly should be set per option.
9510 *
9511 */
9512 int ancestorsOnly = 0;
9513 xmlNodePtr resultClone = NULL, clone = NULL, parentClone = NULL, prevClone = NULL;
9514 xmlNsPtr cloneNs = NULL, *cloneNsDefSlot = NULL;
9515 xmlDictPtr dict; /* The destination dict */
9516
9517 if ((node == NULL) || (resNode == NULL) || (destDoc == NULL))
9518 return(-1);
9519 /*
9520 * TODO: Initially we support only element-nodes.
9521 */
9522 if (node->type != XML_ELEMENT_NODE)
9523 return(1);
9524 /*
9525 * Check node->doc sanity.
9526 */
9527 if ((node->doc != NULL) && (sourceDoc != NULL) &&
9528 (node->doc != sourceDoc)) {
9529 /*
9530 * Might be an XIncluded node.
9531 */
9532 return (-1);
9533 }
9534 if (sourceDoc == NULL)
9535 sourceDoc = node->doc;
9536 if (sourceDoc == NULL)
9537 return (-1);
9538
9539 dict = destDoc->dict;
9540 /*
9541 * Reuse the namespace map of the context.
9542 */
9543 if (ctxt)
9544 nsMap = (xmlNsMapPtr) ctxt->namespaceMap;
9545
9546 *resNode = NULL;
9547
9548 cur = node;
9549 if ((cur != NULL) && (cur->type == XML_NAMESPACE_DECL))
9550 return(-1);
9551
9552 while (cur != NULL) {
9553 if (cur->doc != sourceDoc) {
9554 /*
9555 * We'll assume XIncluded nodes if the doc differs.
9556 * TODO: Do we need to reconciliate XIncluded nodes?
9557 * TODO: This here returns -1 in this case.
9558 */
9559 goto internal_error;
9560 }
9561 /*
9562 * Create a new node.
9563 */
9564 switch (cur->type) {
9565 case XML_XINCLUDE_START:
9566 case XML_XINCLUDE_END:
9567 /*
9568 * TODO: What to do with XInclude?
9569 */
9570 goto internal_error;
9571 break;
9572 case XML_ELEMENT_NODE:
9573 case XML_TEXT_NODE:
9575 case XML_COMMENT_NODE:
9576 case XML_PI_NODE:
9579 case XML_ENTITY_NODE:
9580 /*
9581 * Nodes of xmlNode structure.
9582 */
9583 clone = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
9584 if (clone == NULL) {
9585 xmlTreeErrMemory("xmlDOMWrapCloneNode(): allocating a node");
9586 goto internal_error;
9587 }
9588 memset(clone, 0, sizeof(xmlNode));
9589 /*
9590 * Set hierarchical links.
9591 */
9592 if (resultClone != NULL) {
9593 clone->parent = parentClone;
9594 if (prevClone) {
9595 prevClone->next = clone;
9596 clone->prev = prevClone;
9597 } else
9598 parentClone->children = clone;
9599 } else
9600 resultClone = clone;
9601
9602 break;
9603 case XML_ATTRIBUTE_NODE:
9604 /*
9605 * Attributes (xmlAttr).
9606 */
9607 /* Use xmlRealloc to avoid -Warray-bounds warning */
9608 clone = (xmlNodePtr) xmlRealloc(NULL, sizeof(xmlAttr));
9609 if (clone == NULL) {
9610 xmlTreeErrMemory("xmlDOMWrapCloneNode(): allocating an attr-node");
9611 goto internal_error;
9612 }
9613 memset(clone, 0, sizeof(xmlAttr));
9614 /*
9615 * Set hierarchical links.
9616 * TODO: Change this to add to the end of attributes.
9617 */
9618 if (resultClone != NULL) {
9619 clone->parent = parentClone;
9620 if (prevClone) {
9621 prevClone->next = clone;
9622 clone->prev = prevClone;
9623 } else
9624 parentClone->properties = (xmlAttrPtr) clone;
9625 } else
9626 resultClone = clone;
9627 break;
9628 default:
9629 /*
9630 * TODO QUESTION: Any other nodes expected?
9631 */
9632 goto internal_error;
9633 }
9634
9635 clone->type = cur->type;
9636 clone->doc = destDoc;
9637
9638 /*
9639 * Clone the name of the node if any.
9640 */
9641 if (cur->name == xmlStringText)
9642 clone->name = xmlStringText;
9643 else if (cur->name == xmlStringTextNoenc)
9644 /*
9645 * NOTE: Although xmlStringTextNoenc is never assigned to a node
9646 * in tree.c, it might be set in Libxslt via
9647 * "xsl:disable-output-escaping".
9648 */
9649 clone->name = xmlStringTextNoenc;
9650 else if (cur->name == xmlStringComment)
9651 clone->name = xmlStringComment;
9652 else if (cur->name != NULL) {
9653 DICT_CONST_COPY(cur->name, clone->name);
9654 }
9655
9656 switch (cur->type) {
9657 case XML_XINCLUDE_START:
9658 case XML_XINCLUDE_END:
9659 /*
9660 * TODO
9661 */
9662 return (-1);
9663 case XML_ELEMENT_NODE:
9664 curElem = cur;
9665 depth++;
9666 /*
9667 * Namespace declarations.
9668 */
9669 if (cur->nsDef != NULL) {
9670 if (! parnsdone) {
9671 if (destParent && (ctxt == NULL)) {
9672 /*
9673 * Gather @parent's in-scope ns-decls.
9674 */
9675 if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap,
9676 destParent) == -1)
9677 goto internal_error;
9678 }
9679 parnsdone = 1;
9680 }
9681 /*
9682 * Clone namespace declarations.
9683 */
9684 cloneNsDefSlot = &(clone->nsDef);
9685 for (ns = cur->nsDef; ns != NULL; ns = ns->next) {
9686 /*
9687 * Create a new xmlNs.
9688 */
9689 cloneNs = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
9690 if (cloneNs == NULL) {
9691 xmlTreeErrMemory("xmlDOMWrapCloneNode(): "
9692 "allocating namespace");
9693 return(-1);
9694 }
9695 memset(cloneNs, 0, sizeof(xmlNs));
9696 cloneNs->type = XML_LOCAL_NAMESPACE;
9697
9698 if (ns->href != NULL)
9699 cloneNs->href = xmlStrdup(ns->href);
9700 if (ns->prefix != NULL)
9701 cloneNs->prefix = xmlStrdup(ns->prefix);
9702
9703 *cloneNsDefSlot = cloneNs;
9704 cloneNsDefSlot = &(cloneNs->next);
9705
9706 /*
9707 * Note that for custom handling of ns-references,
9708 * the ns-decls need not be stored in the ns-map,
9709 * since they won't be referenced by node->ns.
9710 */
9711 if ((ctxt == NULL) ||
9712 (ctxt->getNsForNodeFunc == NULL))
9713 {
9714 /*
9715 * Does it shadow any ns-decl?
9716 */
9717 if (XML_NSMAP_NOTEMPTY(nsMap)) {
9718 XML_NSMAP_FOREACH(nsMap, mi) {
9719 if ((mi->depth >= XML_TREE_NSMAP_PARENT) &&
9720 (mi->shadowDepth == -1) &&
9721 ((ns->prefix == mi->newNs->prefix) ||
9723 mi->newNs->prefix))) {
9724 /*
9725 * Mark as shadowed at the current
9726 * depth.
9727 */
9728 mi->shadowDepth = depth;
9729 }
9730 }
9731 }
9732 /*
9733 * Push mapping.
9734 */
9735 if (xmlDOMWrapNsMapAddItem(&nsMap, -1,
9736 ns, cloneNs, depth) == NULL)
9737 goto internal_error;
9738 }
9739 }
9740 }
9741 /* cur->ns will be processed further down. */
9742 break;
9743 case XML_ATTRIBUTE_NODE:
9744 /* IDs will be processed further down. */
9745 /* cur->ns will be processed further down. */
9746 break;
9747 case XML_TEXT_NODE:
9749 /*
9750 * Note that this will also cover the values of attributes.
9751 */
9752 DICT_COPY(cur->content, clone->content);
9753 goto leave_node;
9754 case XML_ENTITY_NODE:
9755 /* TODO: What to do here? */
9756 goto leave_node;
9758 if (sourceDoc != destDoc) {
9759 if ((destDoc->intSubset) || (destDoc->extSubset)) {
9760 xmlEntityPtr ent;
9761 /*
9762 * Different doc: Assign new entity-node if available.
9763 */
9764 ent = xmlGetDocEntity(destDoc, cur->name);
9765 if (ent != NULL) {
9766 clone->content = ent->content;
9767 clone->children = (xmlNodePtr) ent;
9768 clone->last = (xmlNodePtr) ent;
9769 }
9770 }
9771 } else {
9772 /*
9773 * Same doc: Use the current node's entity declaration
9774 * and value.
9775 */
9776 clone->content = cur->content;
9777 clone->children = cur->children;
9778 clone->last = cur->last;
9779 }
9780 goto leave_node;
9781 case XML_PI_NODE:
9782 DICT_COPY(cur->content, clone->content);
9783 goto leave_node;
9784 case XML_COMMENT_NODE:
9785 DICT_COPY(cur->content, clone->content);
9786 goto leave_node;
9787 default:
9788 goto internal_error;
9789 }
9790
9791 if (cur->ns == NULL)
9792 goto end_ns_reference;
9793
9794/* handle_ns_reference: */
9795 /*
9796 ** The following will take care of references to ns-decls ********
9797 ** and is intended only for element- and attribute-nodes.
9798 **
9799 */
9800 if (! parnsdone) {
9801 if (destParent && (ctxt == NULL)) {
9802 if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap, destParent) == -1)
9803 goto internal_error;
9804 }
9805 parnsdone = 1;
9806 }
9807 /*
9808 * Adopt ns-references.
9809 */
9810 if (XML_NSMAP_NOTEMPTY(nsMap)) {
9811 /*
9812 * Search for a mapping.
9813 */
9814 XML_NSMAP_FOREACH(nsMap, mi) {
9815 if ((mi->shadowDepth == -1) &&
9816 (cur->ns == mi->oldNs)) {
9817 /*
9818 * This is the nice case: a mapping was found.
9819 */
9820 clone->ns = mi->newNs;
9821 goto end_ns_reference;
9822 }
9823 }
9824 }
9825 /*
9826 * No matching namespace in scope. We need a new one.
9827 */
9828 if ((ctxt != NULL) && (ctxt->getNsForNodeFunc != NULL)) {
9829 /*
9830 * User-defined behaviour.
9831 */
9832 ns = ctxt->getNsForNodeFunc(ctxt, cur,
9833 cur->ns->href, cur->ns->prefix);
9834 /*
9835 * Add user's mapping.
9836 */
9837 if (xmlDOMWrapNsMapAddItem(&nsMap, -1,
9838 cur->ns, ns, XML_TREE_NSMAP_CUSTOM) == NULL)
9839 goto internal_error;
9840 clone->ns = ns;
9841 } else {
9842 /*
9843 * Acquire a normalized ns-decl and add it to the map.
9844 */
9845 if (xmlDOMWrapNSNormAcquireNormalizedNs(destDoc,
9846 /* ns-decls on curElem or on destDoc->oldNs */
9847 destParent ? curElem : NULL,
9848 cur->ns, &ns,
9849 &nsMap, depth,
9850 /* if we need to search only in the ancestor-axis */
9851 ancestorsOnly,
9852 /* ns-decls must be prefixed for attributes. */
9853 (cur->type == XML_ATTRIBUTE_NODE) ? 1 : 0) == -1)
9854 goto internal_error;
9855 clone->ns = ns;
9856 }
9857
9858end_ns_reference:
9859
9860 /*
9861 * Some post-processing.
9862 *
9863 * Handle ID attributes.
9864 */
9865 if ((clone->type == XML_ATTRIBUTE_NODE) &&
9866 (clone->parent != NULL))
9867 {
9868 if (xmlIsID(destDoc, clone->parent, (xmlAttrPtr) clone)) {
9869
9870 xmlChar *idVal;
9871
9872 idVal = xmlNodeListGetString(cur->doc, cur->children, 1);
9873 if (idVal != NULL) {
9874 if (xmlAddID(NULL, destDoc, idVal, (xmlAttrPtr) cur) == NULL) {
9875 /* TODO: error message. */
9876 xmlFree(idVal);
9877 goto internal_error;
9878 }
9879 xmlFree(idVal);
9880 }
9881 }
9882 }
9883 /*
9884 **
9885 ** The following will traverse the tree **************************
9886 **
9887 *
9888 * Walk the element's attributes before descending into child-nodes.
9889 */
9890 if ((cur->type == XML_ELEMENT_NODE) && (cur->properties != NULL)) {
9891 prevClone = NULL;
9892 parentClone = clone;
9893 cur = (xmlNodePtr) cur->properties;
9894 continue;
9895 }
9896into_content:
9897 /*
9898 * Descend into child-nodes.
9899 */
9900 if (cur->children != NULL) {
9901 if (deep || (cur->type == XML_ATTRIBUTE_NODE)) {
9902 prevClone = NULL;
9903 parentClone = clone;
9904 cur = cur->children;
9905 continue;
9906 }
9907 }
9908
9909leave_node:
9910 /*
9911 * At this point we are done with the node, its content
9912 * and an element-nodes's attribute-nodes.
9913 */
9914 if (cur == node)
9915 break;
9916 if ((cur->type == XML_ELEMENT_NODE) ||
9917 (cur->type == XML_XINCLUDE_START) ||
9918 (cur->type == XML_XINCLUDE_END)) {
9919 /*
9920 * TODO: Do we expect nsDefs on XML_XINCLUDE_START?
9921 */
9922 if (XML_NSMAP_NOTEMPTY(nsMap)) {
9923 /*
9924 * Pop mappings.
9925 */
9926 while ((nsMap->last != NULL) &&
9927 (nsMap->last->depth >= depth))
9928 {
9929 XML_NSMAP_POP(nsMap, mi)
9930 }
9931 /*
9932 * Unshadow.
9933 */
9934 XML_NSMAP_FOREACH(nsMap, mi) {
9935 if (mi->shadowDepth >= depth)
9936 mi->shadowDepth = -1;
9937 }
9938 }
9939 depth--;
9940 }
9941 if (cur->next != NULL) {
9942 prevClone = clone;
9943 cur = cur->next;
9944 } else if (cur->type != XML_ATTRIBUTE_NODE) {
9945 /*
9946 * Set clone->last.
9947 */
9948 if (clone->parent != NULL)
9949 clone->parent->last = clone;
9950 clone = clone->parent;
9951 if (clone != NULL)
9952 parentClone = clone->parent;
9953 /*
9954 * Process parent --> next;
9955 */
9956 cur = cur->parent;
9957 goto leave_node;
9958 } else {
9959 /* This is for attributes only. */
9960 clone = clone->parent;
9961 parentClone = clone->parent;
9962 /*
9963 * Process parent-element --> children.
9964 */
9965 cur = cur->parent;
9966 goto into_content;
9967 }
9968 }
9969 goto exit;
9970
9971internal_error:
9972 ret = -1;
9973
9974exit:
9975 /*
9976 * Cleanup.
9977 */
9978 if (nsMap != NULL) {
9979 if ((ctxt) && (ctxt->namespaceMap == nsMap)) {
9980 /*
9981 * Just cleanup the map but don't free.
9982 */
9983 if (nsMap->first) {
9984 if (nsMap->pool)
9985 nsMap->last->next = nsMap->pool;
9986 nsMap->pool = nsMap->first;
9987 nsMap->first = NULL;
9988 }
9989 } else
9990 xmlDOMWrapNsMapFree(nsMap);
9991 }
9992 /*
9993 * TODO: Should we try a cleanup of the cloned node in case of a
9994 * fatal error?
9995 */
9996 *resNode = resultClone;
9997 return (ret);
9998}
9999
10000/*
10001* xmlDOMWrapAdoptAttr:
10002* @ctxt: the optional context for custom processing
10003* @sourceDoc: the optional source document of attr
10004* @attr: the attribute-node to be adopted
10005* @destDoc: the destination doc for adoption
10006* @destParent: the optional new parent of @attr in @destDoc
10007* @options: option flags
10008*
10009* @attr is adopted by @destDoc.
10010* Ensures that ns-references point to @destDoc: either to
10011* elements->nsDef entries if @destParent is given, or to
10012* @destDoc->oldNs otherwise.
10013*
10014* Returns 0 if succeeded, -1 otherwise and on API/internal errors.
10015*/
10016static int
10017xmlDOMWrapAdoptAttr(xmlDOMWrapCtxtPtr ctxt,
10018 xmlDocPtr sourceDoc,
10020 xmlDocPtr destDoc,
10021 xmlNodePtr destParent,
10023{
10025 int adoptStr = 1;
10026
10027 if ((attr == NULL) || (destDoc == NULL))
10028 return (-1);
10029
10030 attr->doc = destDoc;
10031 if (attr->ns != NULL) {
10032 xmlNsPtr ns = NULL;
10033
10034 if (ctxt != NULL) {
10035 /* TODO: User defined. */
10036 }
10037 /* XML Namespace. */
10038 if (IS_STR_XML(attr->ns->prefix)) {
10039 ns = xmlTreeEnsureXMLDecl(destDoc);
10040 } else if (destParent == NULL) {
10041 /*
10042 * Store in @destDoc->oldNs.
10043 */
10044 ns = xmlDOMWrapStoreNs(destDoc, attr->ns->href, attr->ns->prefix);
10045 } else {
10046 /*
10047 * Declare on @destParent.
10048 */
10049 if (xmlSearchNsByNamespaceStrict(destDoc, destParent, attr->ns->href,
10050 &ns, 1) == -1)
10051 goto internal_error;
10052 if (ns == NULL) {
10053 ns = xmlDOMWrapNSNormDeclareNsForced(destDoc, destParent,
10054 attr->ns->href, attr->ns->prefix, 1);
10055 }
10056 }
10057 if (ns == NULL)
10058 goto internal_error;
10059 attr->ns = ns;
10060 }
10061
10063 attr->atype = 0;
10064 attr->psvi = NULL;
10065 /*
10066 * Walk content.
10067 */
10068 if (attr->children == NULL)
10069 return (0);
10070 cur = attr->children;
10071 if ((cur != NULL) && (cur->type == XML_NAMESPACE_DECL))
10072 goto internal_error;
10073 while (cur != NULL) {
10074 cur->doc = destDoc;
10075 switch (cur->type) {
10076 case XML_TEXT_NODE:
10078 XML_TREE_ADOPT_STR_2(cur->content)
10079 break;
10081 /*
10082 * Remove reference to the entity-node.
10083 */
10084 cur->content = NULL;
10085 cur->children = NULL;
10086 cur->last = NULL;
10087 if ((destDoc->intSubset) || (destDoc->extSubset)) {
10088 xmlEntityPtr ent;
10089 /*
10090 * Assign new entity-node if available.
10091 */
10092 ent = xmlGetDocEntity(destDoc, cur->name);
10093 if (ent != NULL) {
10094 cur->content = ent->content;
10095 cur->children = (xmlNodePtr) ent;
10096 cur->last = (xmlNodePtr) ent;
10097 }
10098 }
10099 break;
10100 default:
10101 break;
10102 }
10103 if (cur->children != NULL) {
10104 cur = cur->children;
10105 continue;
10106 }
10107next_sibling:
10108 if (cur == (xmlNodePtr) attr)
10109 break;
10110 if (cur->next != NULL)
10111 cur = cur->next;
10112 else {
10113 cur = cur->parent;
10114 goto next_sibling;
10115 }
10116 }
10117 return (0);
10118internal_error:
10119 return (-1);
10120}
10121
10122/*
10123* xmlDOMWrapAdoptNode:
10124* @ctxt: the optional context for custom processing
10125* @sourceDoc: the optional sourceDoc
10126* @node: the node to start with
10127* @destDoc: the destination doc
10128* @destParent: the optional new parent of @node in @destDoc
10129* @options: option flags
10130*
10131* References of out-of scope ns-decls are remapped to point to @destDoc:
10132* 1) If @destParent is given, then nsDef entries on element-nodes are used
10133* 2) If *no* @destParent is given, then @destDoc->oldNs entries are used
10134* This is the case when you have an unlinked node and just want to move it
10135* to the context of
10136*
10137* If @destParent is given, it ensures that the tree is namespace
10138* wellformed by creating additional ns-decls where needed.
10139* Note that, since prefixes of already existent ns-decls can be
10140* shadowed by this process, it could break QNames in attribute
10141* values or element content.
10142* NOTE: This function was not intensively tested.
10143*
10144* Returns 0 if the operation succeeded,
10145* 1 if a node of unsupported type was given,
10146* 2 if a node of not yet supported type was given and
10147* -1 on API/internal errors.
10148*/
10149int
10151 xmlDocPtr sourceDoc,
10153 xmlDocPtr destDoc,
10154 xmlNodePtr destParent,
10155 int options)
10156{
10157 if ((node == NULL) || (node->type == XML_NAMESPACE_DECL) ||
10158 (destDoc == NULL) ||
10159 ((destParent != NULL) && (destParent->doc != destDoc)))
10160 return(-1);
10161 /*
10162 * Check node->doc sanity.
10163 */
10164 if ((node->doc != NULL) && (sourceDoc != NULL) &&
10165 (node->doc != sourceDoc)) {
10166 /*
10167 * Might be an XIncluded node.
10168 */
10169 return (-1);
10170 }
10171 if (sourceDoc == NULL)
10172 sourceDoc = node->doc;
10173 if (sourceDoc == destDoc)
10174 return (-1);
10175 switch (node->type) {
10176 case XML_ELEMENT_NODE:
10177 case XML_ATTRIBUTE_NODE:
10178 case XML_TEXT_NODE:
10181 case XML_PI_NODE:
10182 case XML_COMMENT_NODE:
10183 break;
10185 /* TODO: Support document-fragment-nodes. */
10186 return (2);
10187 default:
10188 return (1);
10189 }
10190 /*
10191 * Unlink only if @node was not already added to @destParent.
10192 */
10193 if ((node->parent != NULL) && (destParent != node->parent))
10195
10196 if (node->type == XML_ELEMENT_NODE) {
10197 return (xmlDOMWrapAdoptBranch(ctxt, sourceDoc, node,
10198 destDoc, destParent, options));
10199 } else if (node->type == XML_ATTRIBUTE_NODE) {
10200 return (xmlDOMWrapAdoptAttr(ctxt, sourceDoc,
10201 (xmlAttrPtr) node, destDoc, destParent, options));
10202 } else {
10204 int adoptStr = 1;
10205
10206 cur->doc = destDoc;
10207 /*
10208 * Optimize string adoption.
10209 */
10210 if ((sourceDoc != NULL) &&
10211 (sourceDoc->dict == destDoc->dict))
10212 adoptStr = 0;
10213 switch (node->type) {
10214 case XML_TEXT_NODE:
10216 XML_TREE_ADOPT_STR_2(node->content)
10217 break;
10219 /*
10220 * Remove reference to the entity-node.
10221 */
10222 node->content = NULL;
10223 node->children = NULL;
10224 node->last = NULL;
10225 if ((destDoc->intSubset) || (destDoc->extSubset)) {
10226 xmlEntityPtr ent;
10227 /*
10228 * Assign new entity-node if available.
10229 */
10230 ent = xmlGetDocEntity(destDoc, node->name);
10231 if (ent != NULL) {
10232 node->content = ent->content;
10233 node->children = (xmlNodePtr) ent;
10234 node->last = (xmlNodePtr) ent;
10235 }
10236 }
10238 break;
10239 case XML_PI_NODE: {
10242 break;
10243 }
10244 default:
10245 break;
10246 }
10247 }
10248 return (0);
10249}
10250
ios_base &_STLP_CALL fixed(ios_base &__s)
Definition: _ios_base.h:332
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
#define msg(x)
Definition: auth_time.c:54
INT copy(TCHAR source[MAX_PATH], TCHAR dest[MAX_PATH], INT append, DWORD lpdwFlags, BOOL bTouch)
Definition: copy.c:51
struct _root root
struct _tree tree
xmlBufPtr xmlBufFromBuffer(xmlBufferPtr buffer)
Definition: buf.c:977
int xmlBufIsEmpty(const xmlBufPtr buf)
Definition: buf.c:673
void xmlBufFree(xmlBufPtr buf)
Definition: buf.c:322
xmlChar * xmlBufDetach(xmlBufPtr buf)
Definition: buf.c:196
xmlBufPtr xmlBufCreateSize(size_t size)
Definition: buf.c:155
xmlBufPtr xmlBufCreate(void)
Definition: buf.c:122
int xmlBufSetAllocationScheme(xmlBufPtr buf, xmlBufferAllocationScheme scheme)
Definition: buf.c:281
xmlBufferPtr xmlBufBackToBuffer(xmlBufPtr buf)
Definition: buf.c:1013
int xmlBufAdd(xmlBufPtr buf, const xmlChar *str, int len)
Definition: buf.c:821
int xmlBufCat(xmlBufPtr buf, const xmlChar *str)
Definition: buf.c:884
r l[0]
Definition: byte_order.h:168
return
Definition: dirsup.c:529
Definition: list.h:37
Definition: _map.h:48
#define NULL
Definition: types.h:112
#define IS_BLANK(c)
Definition: attributes.c:26
content
Definition: atl_ax.c:994
static const WCHAR version[]
Definition: asmname.c:66
BOOL next_node(stream_t *stream, strbuf_t *buf)
Definition: stream.c:140
r parent
Definition: btrfs.c:3010
__kernel_ptrdiff_t ptrdiff_t
Definition: linux.h:247
@ XML_CHAR_ENCODING_UTF8
Definition: encoding.h:59
XMLPUBFUN xmlChar *XMLCALL xmlEncodeSpecialChars(const xmlDoc *doc, const xmlChar *input)
XMLPUBFUN xmlEntityPtr XMLCALL xmlGetDocEntity(const xmlDoc *doc, const xmlChar *name)
XMLPUBFUN void XMLCALL xmlFreeEntitiesTable(xmlEntitiesTablePtr table)
@ XML_EXTERNAL_GENERAL_PARSED_ENTITY
Definition: entities.h:26
@ XML_INTERNAL_PREDEFINED_ENTITY
Definition: entities.h:30
@ XML_EXTERNAL_GENERAL_UNPARSED_ENTITY
Definition: entities.h:27
@ XML_INTERNAL_GENERAL_ENTITY
Definition: entities.h:25
@ XML_INTERNAL_PARAMETER_ENTITY
Definition: entities.h:28
@ XML_EXTERNAL_PARAMETER_ENTITY
Definition: entities.h:29
XMLPUBFUN xmlChar *XMLCALL xmlEncodeEntitiesReentrant(xmlDocPtr doc, const xmlChar *input)
xmlEntitiesTable * xmlEntitiesTablePtr
Definition: entities.h:71
FxCollectionEntry * cur
GLint GLint GLsizei GLsizei GLsizei depth
Definition: gl.h:1546
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLuint GLuint end
Definition: gl.h:1545
GLdouble GLdouble GLdouble GLdouble q
Definition: gl.h:2063
GLsizeiptr size
Definition: glext.h:5919
GLdouble n
Definition: glext.h:7729
GLuint buffer
Definition: glext.h:5915
const GLubyte * c
Definition: glext.h:8905
GLenum mode
Definition: glext.h:6217
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
const GLint * first
Definition: glext.h:5794
GLuint GLfloat * val
Definition: glext.h:7180
GLfloat GLfloat p
Definition: glext.h:8902
GLenum GLsizei len
Definition: glext.h:6722
GLuint64EXT * result
Definition: glext.h:11304
GLuint id
Definition: glext.h:5910
GLenum target
Definition: glext.h:7315
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
#define ATTRIBUTE_UNUSED
Definition: i386-dis.c:36
@ extra
Definition: id3.c:95
#define INT_MAX
Definition: limits.h:40
#define UINT_MAX
Definition: limits.h:41
#define stdout
Definition: stdio.h:99
#define stderr
Definition: stdio.h:100
_Check_return_opt_ _CRTIMP size_t __cdecl fwrite(_In_reads_bytes_(_Size *_Count) const void *_Str, _In_ size_t _Size, _In_ size_t _Count, _Inout_ FILE *_File)
#define c
Definition: ke_i.h:80
if(dx< 0)
Definition: linetemp.h:194
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define memmove(s1, s2, n)
Definition: mkisofs.h:881
char string[160]
Definition: util.h:11
static unsigned int number
Definition: dsound.c:1479
static UINT UINT last
Definition: font.c:45
static char memory[1024 *256]
Definition: process.c:116
static size_t elem
Definition: string.c:68
const char * uri
Definition: sec_mgr.c:1588
#define IS_COMBINING(c)
XMLPUBVAR const xmlChar xmlStringComment[]
#define IS_DIGIT(c)
XMLPUBVAR const xmlChar xmlStringTextNoenc[]
#define IS_EXTENDER(c)
#define IS_LETTER(c)
XMLPUBFUN int XMLCALL xmlCopyCharMultiByte(xmlChar *out, int val)
XMLPUBVAR const xmlChar xmlStringText[]
#define IS_BLANK_CH(c)
#define long
Definition: qsort.c:33
static unsigned __int64 next
Definition: rand_nt.c:6
static FILE * out
Definition: regtests2xml.c:44
#define list
Definition: rosglue.h:35
const WCHAR * str
DWORD scheme
static calc_node_t temp
Definition: rpn_ieee.c:38
xmlChar * xmlEncodeAttributeEntities(xmlDocPtr doc, const xmlChar *input)
XMLPUBFUN const xmlChar *XMLCALL xmlDictLookup(xmlDictPtr dict, const xmlChar *name, int len)
Definition: dict.c:867
XMLPUBFUN int XMLCALL xmlDictOwns(xmlDictPtr dict, const xmlChar *str)
Definition: dict.c:1220
XMLPUBFUN void XMLCALL xmlDictFree(xmlDictPtr dict)
Definition: dict.c:802
XMLPUBVAR xmlBufferAllocationScheme xmlBufferAllocScheme
Definition: globals.h:293
XMLPUBVAR xmlMallocFunc xmlMallocAtomic
Definition: globals.h:249
XMLPUBVAR xmlStrdupFunc xmlMemStrdup
Definition: globals.h:252
XMLPUBVAR xmlMallocFunc xmlMalloc
Definition: globals.h:248
XMLPUBVAR int xmlDefaultBufferSize
Definition: globals.h:303
XMLPUBVAR xmlDeregisterNodeFunc xmlDeregisterNodeDefaultValue
Definition: globals.h:475
XMLPUBVAR xmlRegisterNodeFunc xmlRegisterNodeDefaultValue
Definition: globals.h:467
XMLPUBVAR xmlFreeFunc xmlFree
Definition: globals.h:251
XMLPUBVAR void * xmlGenericErrorContext
Definition: globals.h:353
XMLPUBVAR xmlReallocFunc xmlRealloc
Definition: globals.h:250
XMLPUBVAR xmlGenericErrorFunc xmlGenericError
Definition: globals.h:337
XMLPUBFUN void *XMLCALL xmlHashLookup(xmlHashTablePtr table, const xmlChar *name)
Definition: hash.c:461
XMLPUBFUN int XMLCALL xmlHashRemoveEntry(xmlHashTablePtr table, const xmlChar *name, xmlHashDeallocator f)
Definition: hash.c:1052
XMLPUBFUN xmlNodePtr XMLCALL xmlAddChild(xmlNodePtr parent, xmlNodePtr cur)
XMLPUBFUN xmlNodePtr XMLCALL xmlNewReference(const xmlDoc *doc, const xmlChar *name)
XMLPUBFUN void XMLCALL xmlSetBufferAllocationScheme(xmlBufferAllocationScheme scheme)
XMLPUBFUN int XMLCALL xmlGetDocCompressMode(const xmlDoc *doc)
XMLPUBFUN void XMLCALL xmlBufferFree(xmlBufferPtr buf)
XMLPUBFUN xmlChar *XMLCALL xmlNodeGetContent(const xmlNode *cur)
XMLPUBFUN xmlNodePtr XMLCALL xmlNewComment(const xmlChar *content)
XMLPUBFUN xmlNsPtr XMLCALL xmlCopyNamespace(xmlNsPtr cur)
XMLPUBFUN xmlDtdPtr XMLCALL xmlNewDtd(xmlDocPtr doc, const xmlChar *name, const xmlChar *ExternalID, const xmlChar *SystemID)
XMLPUBFUN xmlNodePtr XMLCALL xmlDocGetRootElement(const xmlDoc *doc)
XMLPUBFUN int XMLCALL xmlDOMWrapCloneNode(xmlDOMWrapCtxtPtr ctxt, xmlDocPtr sourceDoc, xmlNodePtr node, xmlNodePtr *clonedNode, xmlDocPtr destDoc, xmlNodePtr destParent, int deep, int options)
XMLPUBFUN void XMLCALL xmlSetListDoc(xmlNodePtr list, xmlDocPtr doc)
XMLPUBFUN xmlDtdPtr XMLCALL xmlCreateIntSubset(xmlDocPtr doc, const xmlChar *name, const xmlChar *ExternalID, const xmlChar *SystemID)
@ XML_ATTRIBUTE_ID
Definition: tree.h:208
XMLPUBFUN xmlNodePtr XMLCALL xmlGetLastChild(const xmlNode *parent)
XMLPUBFUN void XMLCALL xmlSetCompressMode(int mode)
XMLPUBFUN void XMLCALL xmlFreeDtd(xmlDtdPtr cur)
XMLPUBFUN void XMLCALL xmlBufferWriteChar(xmlBufferPtr buf, const char *string)
XMLPUBFUN void XMLCALL xmlFreeDoc(xmlDocPtr cur)
XMLPUBFUN xmlAttrPtr XMLCALL xmlHasProp(const xmlNode *node, const xmlChar *name)
XMLPUBFUN int XMLCALL xmlBufferResize(xmlBufferPtr buf, unsigned int size)
XMLPUBFUN int XMLCALL xmlBufferAdd(xmlBufferPtr buf, const xmlChar *str, int len)
XMLPUBFUN xmlChar *XMLCALL xmlGetProp(const xmlNode *node, const xmlChar *name)
XMLPUBFUN xmlNsPtr XMLCALL xmlSearchNs(xmlDocPtr doc, xmlNodePtr node, const xmlChar *nameSpace)
XMLPUBFUN xmlAttrPtr XMLCALL xmlCopyPropList(xmlNodePtr target, xmlAttrPtr cur)
XMLPUBFUN xmlNodePtr XMLCALL xmlNewDocNode(xmlDocPtr doc, xmlNsPtr ns, const xmlChar *name, const xmlChar *content)
XMLPUBFUN int XMLCALL xmlDOMWrapReconcileNamespaces(xmlDOMWrapCtxtPtr ctxt, xmlNodePtr elem, int options)
XMLPUBFUN int XMLCALL xmlNodeBufGetContent(xmlBufferPtr buffer, const xmlNode *cur)
XMLPUBFUN int XMLCALL xmlTextConcat(xmlNodePtr node, const xmlChar *content, int len)
XMLPUBFUN xmlNodePtr XMLCALL xmlCopyNode(xmlNodePtr node, int recursive)
XMLPUBFUN xmlBufferPtr XMLCALL xmlBufferCreateStatic(void *mem, size_t size)
XMLPUBFUN xmlNodePtr XMLCALL xmlStringGetNodeList(const xmlDoc *doc, const xmlChar *value)
XMLPUBFUN int XMLCALL xmlNodeIsText(const xmlNode *node)
XMLPUBFUN int XMLCALL xmlNodeGetSpacePreserve(const xmlNode *cur)
XMLPUBFUN xmlChar *XMLCALL xmlGetNoNsProp(const xmlNode *node, const xmlChar *name)
XMLPUBFUN void XMLCALL xmlDOMWrapFreeCtxt(xmlDOMWrapCtxtPtr ctxt)
XMLPUBFUN void XMLCALL xmlNodeAddContent(xmlNodePtr cur, const xmlChar *content)
XMLPUBFUN xmlChar *XMLCALL xmlBuildQName(const xmlChar *ncname, const xmlChar *prefix, xmlChar *memory, int len)
xmlElement * xmlElementPtr
Definition: tree.h:345
XMLPUBFUN void XMLCALL xmlNodeAddContentLen(xmlNodePtr cur, const xmlChar *content, int len)
XMLPUBFUN xmlNodePtr XMLCALL xmlNewTextLen(const xmlChar *content, int len)
xmlNode * xmlNodePtr
Definition: tree.h:488
XMLPUBFUN xmlDocPtr XMLCALL xmlNewDoc(const xmlChar *version)
XMLPUBFUN int XMLCALL xmlRemoveProp(xmlAttrPtr cur)
XMLPUBFUN xmlChar *XMLCALL xmlGetNsProp(const xmlNode *node, const xmlChar *name, const xmlChar *nameSpace)
XMLPUBFUN void XMLCALL xmlSetNs(xmlNodePtr node, xmlNsPtr ns)
XMLPUBFUN xmlNodePtr XMLCALL xmlNewCharRef(xmlDocPtr doc, const xmlChar *name)
xmlDoc * xmlDocPtr
Definition: tree.h:550
XMLPUBFUN xmlAttrPtr XMLCALL xmlNewDocProp(xmlDocPtr doc, const xmlChar *name, const xmlChar *value)
XMLPUBFUN xmlNodePtr XMLCALL xmlCopyNodeList(xmlNodePtr node)
XMLPUBFUN xmlNodePtr XMLCALL xmlNewPI(const xmlChar *name, const xmlChar *content)
XMLPUBFUN xmlAttrPtr XMLCALL xmlCopyProp(xmlNodePtr target, xmlAttrPtr cur)
XMLPUBFUN xmlDOMWrapCtxtPtr XMLCALL xmlDOMWrapNewCtxt(void)
XMLPUBFUN xmlNodePtr XMLCALL xmlTextMerge(xmlNodePtr first, xmlNodePtr second)
XMLPUBFUN xmlNodePtr XMLCALL xmlNewText(const xmlChar *content)
XMLPUBFUN void XMLCALL xmlFreeNsList(xmlNsPtr cur)
XMLPUBFUN int XMLCALL xmlBufferCCat(xmlBufferPtr buf, const char *str)
XMLPUBFUN xmlNodePtr XMLCALL xmlAddNextSibling(xmlNodePtr cur, xmlNodePtr elem)
XMLPUBFUN void XMLCALL xmlBufferWriteCHAR(xmlBufferPtr buf, const xmlChar *string)
XMLPUBFUN xmlDtdPtr XMLCALL xmlGetIntSubset(const xmlDoc *doc)
@ XML_DOCUMENT_TYPE_NODE
Definition: tree.h:169
@ XML_ATTRIBUTE_NODE
Definition: tree.h:161
@ XML_ENTITY_DECL
Definition: tree.h:176
@ XML_DOCUMENT_NODE
Definition: tree.h:168
@ XML_CDATA_SECTION_NODE
Definition: tree.h:163
@ XML_TEXT_NODE
Definition: tree.h:162
@ XML_XINCLUDE_START
Definition: tree.h:178
@ XML_ENTITY_NODE
Definition: tree.h:165
@ XML_PI_NODE
Definition: tree.h:166
@ XML_XINCLUDE_END
Definition: tree.h:179
@ XML_DOCUMENT_FRAG_NODE
Definition: tree.h:170
@ XML_COMMENT_NODE
Definition: tree.h:167
@ XML_DTD_NODE
Definition: tree.h:173
@ XML_NAMESPACE_DECL
Definition: tree.h:177
@ XML_HTML_DOCUMENT_NODE
Definition: tree.h:172
@ XML_ELEMENT_NODE
Definition: tree.h:160
@ XML_ELEMENT_DECL
Definition: tree.h:174
@ XML_ENTITY_REF_NODE
Definition: tree.h:164
@ XML_NOTATION_NODE
Definition: tree.h:171
@ XML_ATTRIBUTE_DECL
Definition: tree.h:175
XMLPUBFUN int XMLCALL xmlGetCompressMode(void)
XMLPUBFUN void XMLCALL xmlUnlinkNode(xmlNodePtr cur)
XMLPUBFUN xmlBufferPtr XMLCALL xmlBufferCreate(void)
XMLPUBFUN xmlNodePtr XMLCALL xmlNewDocPI(xmlDocPtr doc, const xmlChar *name, const xmlChar *content)
xmlAttr * xmlAttrPtr
Definition: tree.h:433
XMLPUBFUN xmlNsPtr XMLCALL xmlSearchNsByHref(xmlDocPtr doc, xmlNodePtr node, const xmlChar *href)
XMLPUBFUN void XMLCALL xmlSetTreeDoc(xmlNodePtr tree, xmlDocPtr doc)
XMLPUBFUN xmlNodePtr XMLCALL xmlAddSibling(xmlNodePtr cur, xmlNodePtr elem)
XMLPUBFUN xmlChar *XMLCALL xmlNodeGetBase(const xmlDoc *doc, const xmlNode *cur)
XMLPUBFUN int XMLCALL xmlBufferShrink(xmlBufferPtr buf, unsigned int len)
XMLPUBFUN xmlNodePtr XMLCALL xmlNewDocTextLen(xmlDocPtr doc, const xmlChar *content, int len)
XMLPUBFUN xmlBufferAllocationScheme XMLCALL xmlGetBufferAllocationScheme(void)
XMLPUBFUN int XMLCALL xmlDOMWrapAdoptNode(xmlDOMWrapCtxtPtr ctxt, xmlDocPtr sourceDoc, xmlNodePtr node, xmlDocPtr destDoc, xmlNodePtr destParent, int options)
XMLPUBFUN int XMLCALL xmlBufferGrow(xmlBufferPtr buf, unsigned int len)
xmlBufferAllocationScheme
Definition: tree.h:74
@ XML_BUFFER_ALLOC_EXACT
Definition: tree.h:76
@ XML_BUFFER_ALLOC_IMMUTABLE
Definition: tree.h:77
@ XML_BUFFER_ALLOC_IO
Definition: tree.h:78
@ XML_BUFFER_ALLOC_DOUBLEIT
Definition: tree.h:75
@ XML_BUFFER_ALLOC_HYBRID
Definition: tree.h:79
#define XML_XML_NAMESPACE
Definition: tree.h:140
XMLPUBFUN xmlBufferPtr XMLCALL xmlBufferCreateSize(size_t size)
XMLPUBFUN int XMLCALL xmlBufGetNodeContent(xmlBufPtr buf, const xmlNode *cur)
@ XML_DOC_USERBUILT
Definition: tree.h:538
XMLPUBFUN void XMLCALL xmlFreeProp(xmlAttrPtr cur)
XMLPUBFUN void XMLCALL xmlFreePropList(xmlAttrPtr cur)
XMLPUBFUN xmlAttrPtr XMLCALL xmlNewNsPropEatName(xmlNodePtr node, xmlNsPtr ns, xmlChar *name, const xmlChar *value)
XMLPUBFUN void XMLCALL xmlNodeSetContent(xmlNodePtr cur, const xmlChar *content)
XMLPUBFUN int XMLCALL xmlIsBlankNode(const xmlNode *node)
XMLPUBFUN xmlNodePtr XMLCALL xmlNewDocText(const xmlDoc *doc, const xmlChar *content)
xmlEntity * xmlEntityPtr
Definition: tree.h:49
XMLPUBFUN int XMLCALL xmlDOMWrapRemoveNode(xmlDOMWrapCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr node, int options)
XMLPUBFUN void XMLCALL xmlFreeNs(xmlNsPtr cur)
XMLPUBFUN xmlNodePtr XMLCALL xmlNewDocComment(xmlDocPtr doc, const xmlChar *content)
XMLPUBFUN long XMLCALL xmlGetLineNo(const xmlNode *node)
XMLPUBFUN const xmlChar *XMLCALL xmlBufferContent(const xmlBuffer *buf)
XMLPUBFUN xmlNodePtr XMLCALL xmlDocCopyNodeList(xmlDocPtr doc, xmlNodePtr node)
XMLPUBFUN void XMLCALL xmlFreeNodeList(xmlNodePtr cur)
XMLPUBFUN xmlAttrPtr XMLCALL xmlHasNsProp(const xmlNode *node, const xmlChar *name, const xmlChar *nameSpace)
xmlNs * xmlNsPtr
Definition: tree.h:388
XMLPUBFUN xmlNodePtr XMLCALL xmlNewNodeEatName(xmlNsPtr ns, xmlChar *name)
XMLPUBFUN xmlNodePtr XMLCALL xmlNewDocNodeEatName(xmlDocPtr doc, xmlNsPtr ns, xmlChar *name, const xmlChar *content)
XMLPUBFUN xmlChar *XMLCALL xmlBufferDetach(xmlBufferPtr buf)
XMLPUBFUN void XMLCALL xmlBufferWriteQuotedString(xmlBufferPtr buf, const xmlChar *string)
XMLPUBFUN void XMLCALL xmlFreeNode(xmlNodePtr cur)
XMLPUBFUN int XMLCALL xmlBufferLength(const xmlBuffer *buf)
XMLPUBFUN xmlChar *XMLCALL xmlNodeGetLang(const xmlNode *cur)
XMLPUBFUN const xmlChar *XMLCALL xmlSplitQName3(const xmlChar *name, int *len)
XMLPUBFUN xmlNodePtr XMLCALL xmlAddChildList(xmlNodePtr parent, xmlNodePtr cur)
XMLPUBFUN xmlNsPtr XMLCALL xmlNewNs(xmlNodePtr node, const xmlChar *href, const xmlChar *prefix)
xmlDtd * xmlDtdPtr
Definition: tree.h:405
XMLPUBFUN int XMLCALL xmlBufferCat(xmlBufferPtr buf, const xmlChar *str)
XMLPUBFUN xmlChar *XMLCALL xmlSplitQName2(const xmlChar *name, xmlChar **prefix)
XMLPUBFUN xmlAttrPtr XMLCALL xmlNewNsProp(xmlNodePtr node, xmlNsPtr ns, const xmlChar *name, const xmlChar *value)
XMLPUBFUN xmlNodePtr XMLCALL xmlNewCDataBlock(xmlDocPtr doc, const xmlChar *content, int len)
xmlAttribute * xmlAttributePtr
Definition: tree.h:252
XMLPUBFUN xmlNsPtr XMLCALL xmlCopyNamespaceList(xmlNsPtr cur)
XMLPUBFUN int XMLCALL xmlBufferDump(FILE *file, xmlBufferPtr buf)
XMLPUBFUN int XMLCALL xmlBufferAddHead(xmlBufferPtr buf, const xmlChar *str, int len)
xmlBuffer * xmlBufferPtr
Definition: tree.h:90
XMLPUBFUN xmlNodePtr XMLCALL xmlNewNode(xmlNsPtr ns, const xmlChar *name)
XMLPUBFUN void XMLCALL xmlBufferSetAllocationScheme(xmlBufferPtr buf, xmlBufferAllocationScheme scheme)
#define BASE_BUFFER_SIZE
Definition: tree.h:56
XMLPUBFUN void XMLCALL xmlSetDocCompressMode(xmlDocPtr doc, int mode)
#define XML_LOCAL_NAMESPACE
Definition: tree.h:374
XMLPUBFUN void XMLCALL xmlBufferEmpty(xmlBufferPtr buf)
XMLPUBFUN xmlChar *XMLCALL xmlNodeListGetString(xmlDocPtr doc, const xmlNode *list, int inLine)
XMLPUBFUN xmlNodePtr XMLCALL xmlDocCopyNode(xmlNodePtr node, xmlDocPtr doc, int recursive)
XMLPUBFUN xmlNodePtr XMLCALL xmlStringLenGetNodeList(const xmlDoc *doc, const xmlChar *value, int len)
#define exit(n)
Definition: config.h:202
int __xmlRegisterCallbacks
Definition: tree.c:50
static xmlNsPtr xmlNewReconciledNs(xmlDocPtr doc, xmlNodePtr tree, xmlNsPtr ns)
#define DICT_FREE(str)
#define XML_NSMAP_POP(m, i)
#define CUR_SCHAR(s, l)
static void xmlTreeErrMemory(const char *extra)
Definition: tree.c:75
#define DICT_CONST_COPY(str, cpy)
#define XML_TREE_ADOPT_STR_2(str)
#define UPDATE_LAST_CHILD_AND_PARENT(n)
#define XML_TREE_NSMAP_DOC
#define IS_STR_XML(str)
#define XML_TREE_NSMAP_CUSTOM
#define XML_NSMAP_NOTEMPTY(m)
#define DICT_COPY(str, cpy)
static xmlChar * xmlGetPropNodeValueInternal(const xmlAttr *prop)
#define XML_TREE_NSMAP_PARENT
#define XML_NSMAP_FOREACH(m, i)
#define XML_TREE_ADOPT_STR(str)
#define memset(x, y, z)
Definition: compat.h:39
int is_attr(const attr_list_t *list, enum attr_type t)
Definition: header.c:99
uint64_t parent
Definition: btrfs_drv.h:459
Definition: tree.h:434
xmlNs * ns
Definition: tree.h:444
struct _xmlNode * children
Definition: tree.h:438
struct _xmlNode * last
Definition: tree.h:439
struct _xmlAttr * next
Definition: tree.h:441
xmlElementType type
Definition: tree.h:436
xmlAttributeType atype
Definition: tree.h:445
struct _xmlNode * parent
Definition: tree.h:440
struct _xmlDoc * doc
Definition: tree.h:443
const xmlChar * name
Definition: tree.h:437
const xmlChar * defaultValue
Definition: tree.h:267
const xmlChar * name
Definition: tree.h:256
const xmlChar * prefix
Definition: tree.h:269
const xmlChar * elem
Definition: tree.h:270
Definition: buf.c:43
xmlDOMWrapAcquireNsFunction getNsForNodeFunc
Definition: tree.h:628
void * namespaceMap
Definition: tree.h:623
Definition: dict.c:111
Definition: tree.h:551
const xmlChar * URL
Definition: tree.h:577
char * name
Definition: tree.h:554
struct _xmlDtd * intSubset
Definition: tree.h:570
int charset
Definition: tree.h:578
const xmlChar * encoding
Definition: tree.h:574
const xmlChar * version
Definition: tree.h:573
struct _xmlNode * parent
Definition: tree.h:557
struct _xmlNs * oldNs
Definition: tree.h:572
struct _xmlNode * last
Definition: tree.h:556
int standalone
Definition: tree.h:564
struct _xmlDict * dict
Definition: tree.h:580
struct _xmlNode * children
Definition: tree.h:555
int compression
Definition: tree.h:563
xmlElementType type
Definition: tree.h:553
struct _xmlDtd * extSubset
Definition: tree.h:571
Definition: tree.h:406
void * pentities
Definition: tree.h:424
const xmlChar * name
Definition: tree.h:409
void * elements
Definition: tree.h:419
void * entities
Definition: tree.h:421
struct _xmlNode * children
Definition: tree.h:410
void * notations
Definition: tree.h:418
const xmlChar * SystemID
Definition: tree.h:423
const xmlChar * ExternalID
Definition: tree.h:422
void * attributes
Definition: tree.h:420
const xmlChar * name
Definition: tree.h:349
const xmlChar * prefix
Definition: tree.h:360
const xmlChar * SystemID
Definition: entities.h:54
xmlChar * content
Definition: entities.h:50
const xmlChar * URI
Definition: entities.h:57
xmlEntityType etype
Definition: entities.h:52
const xmlChar * name
Definition: entities.h:41
const xmlChar * ExternalID
Definition: entities.h:53
struct _xmlNode * last
Definition: entities.h:43
struct _xmlNode * children
Definition: entities.h:42
int owner
Definition: entities.h:58
Definition: tree.h:489
xmlChar * content
Definition: tree.h:502
struct _xmlNode * children
Definition: tree.h:493
struct _xmlNode * next
Definition: tree.h:496
struct _xmlDoc * doc
Definition: tree.h:498
xmlNs * nsDef
Definition: tree.h:504
const xmlChar * name
Definition: tree.h:492
xmlElementType type
Definition: tree.h:491
struct _xmlNode * parent
Definition: tree.h:495
struct _xmlNode * prev
Definition: tree.h:497
xmlNs * ns
Definition: tree.h:501
Definition: tree.h:389
const xmlChar * href
Definition: tree.h:392
xmlNsType type
Definition: tree.h:391
const xmlChar * prefix
Definition: tree.h:393
struct _xmlNs * next
Definition: tree.h:390
Definition: cookie.c:202
WCHAR * name
Definition: cookie.c:203
Definition: inflate.c:139
struct define * next
Definition: compiler.c:65
Definition: fci.c:127
Definition: mem.c:156
Definition: name.c:39
Definition: mxnamespace.c:45
BSTR prefix
Definition: mxnamespace.c:46
Definition: dlist.c:348
void * next
Definition: dlist.c:360
Definition: pdh_main.c:94
XMLPUBFUN xmlChar *XMLCALL xmlPathToURI(const xmlChar *path)
Definition: uri.c:2521
XMLPUBFUN xmlChar *XMLCALL xmlBuildURI(const xmlChar *URI, const xmlChar *base)
Definition: uri.c:1892
XML_DEPRECATED XMLPUBFUN void XMLCALL xmlFreeRefTable(xmlRefTablePtr table)
Definition: valid.c:3103
XMLPUBFUN xmlIDPtr XMLCALL xmlAddID(xmlValidCtxtPtr ctxt, xmlDocPtr doc, const xmlChar *value, xmlAttrPtr attr)
Definition: valid.c:2672
XMLPUBFUN xmlElementPtr XMLCALL xmlGetDtdQElementDesc(xmlDtdPtr dtd, const xmlChar *name, const xmlChar *prefix)
Definition: valid.c:3355
XMLPUBFUN void XMLCALL xmlFreeIDTable(xmlIDTablePtr table)
Definition: valid.c:2756
XMLPUBFUN xmlAttributePtr XMLCALL xmlGetDtdQAttrDesc(xmlDtdPtr dtd, const xmlChar *elem, const xmlChar *name, const xmlChar *prefix)
Definition: valid.c:3416
XMLPUBFUN int XMLCALL xmlRemoveID(xmlDocPtr doc, xmlAttrPtr attr)
Definition: valid.c:2835
XMLPUBFUN void XMLCALL xmlFreeNotationTable(xmlNotationTablePtr table)
Definition: valid.c:2471
XMLPUBFUN int XMLCALL xmlIsID(xmlDocPtr doc, xmlNodePtr elem, xmlAttrPtr attr)
Definition: valid.c:2774
XMLPUBFUN void XMLCALL xmlFreeElementTable(xmlElementTablePtr table)
Definition: valid.c:1641
XMLPUBFUN xmlAttributePtr XMLCALL xmlGetDtdAttrDesc(xmlDtdPtr dtd, const xmlChar *elem, const xmlChar *name)
Definition: valid.c:3379
XMLPUBFUN void XMLCALL xmlFreeAttributeTable(xmlAttributeTablePtr table)
Definition: valid.c:2193
static const WCHAR lang[]
Definition: wbemdisp.c:287
int ret
static MONITORINFO mi
Definition: win.c:7338
#define snprintf
Definition: wintirpc.h:48
@ XML_FROM_TREE
Definition: xmlerror.h:39
@ XML_TREE_UNTERMINATED_ENTITY
Definition: xmlerror.h:411
@ XML_TREE_INVALID_DEC
Definition: xmlerror.h:410
@ XML_TREE_NOT_UTF8
Definition: xmlerror.h:412
@ XML_TREE_INVALID_HEX
Definition: xmlerror.h:409
@ XML_ERR_NO_MEMORY
Definition: xmlerror.h:102
static char * encoding
Definition: xmllint.c:155
static int insert
Definition: xmllint.c:138
XMLPUBFUN const xmlChar *XMLCALL xmlStrchr(const xmlChar *str, xmlChar val)
Definition: xmlstring.c:325
XMLPUBFUN xmlChar *XMLCALL xmlStrndup(const xmlChar *cur, int len)
Definition: xmlstring.c:42
XMLPUBFUN int XMLCALL xmlStrcasecmp(const xmlChar *str1, const xmlChar *str2)
Definition: xmlstring.c:275
XMLPUBFUN xmlChar *XMLCALL xmlStrcat(xmlChar *cur, const xmlChar *add)
Definition: xmlstring.c:524
XMLPUBFUN xmlChar *XMLCALL xmlStrncat(xmlChar *cur, const xmlChar *add, int len)
Definition: xmlstring.c:446
XMLPUBFUN int XMLCALL xmlStrncmp(const xmlChar *str1, const xmlChar *str2, int len)
Definition: xmlstring.c:213
XMLPUBFUN xmlChar *XMLCALL xmlStrdup(const xmlChar *cur)
Definition: xmlstring.c:67
XMLPUBFUN xmlChar *XMLCALL xmlStrncatNew(const xmlChar *str1, const xmlChar *str2, int len)
Definition: xmlstring.c:483
#define BAD_CAST
Definition: xmlstring.h:35
XMLPUBFUN int XMLCALL xmlStrEqual(const xmlChar *str1, const xmlChar *str2)
Definition: xmlstring.c:160
XMLPUBFUN int XMLCALL xmlStrlen(const xmlChar *str)
Definition: xmlstring.c:426
unsigned char xmlChar
Definition: xmlstring.h:28
#define const
Definition: zconf.h:233