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