2 * tree.c : implementation of access function for an XML tree.
5 * XHTML 1.0 W3C REC: http://www.w3.org/TR/2002/REC-xhtml1-20020801/
7 * See Copyright for the status of this software.
13 /* To avoid EBCDIC trouble when parsing on zOS */
15 #pragma convert("ISO8859-1")
21 #include <string.h> /* for memset() only ! */
27 #ifdef LIBXML_ZLIB_ENABLED
31 #include <libxml/xmlmemory.h>
32 #include <libxml/tree.h>
33 #include <libxml/parser.h>
34 #include <libxml/uri.h>
35 #include <libxml/entities.h>
36 #include <libxml/valid.h>
37 #include <libxml/xmlerror.h>
38 #include <libxml/parserInternals.h>
39 #include <libxml/globals.h>
40 #ifdef LIBXML_HTML_ENABLED
41 #include <libxml/HTMLtree.h>
43 #ifdef LIBXML_DEBUG_ENABLED
44 #include <libxml/debugXML.h>
47 #include "private/buf.h"
48 #include "private/entities.h"
49 #include "private/error.h"
50 #include "private/tree.h"
52 int __xmlRegisterCallbacks
= 0;
54 /************************************************************************
56 * Forward declarations *
58 ************************************************************************/
61 xmlNewReconciledNs(xmlDocPtr doc
, xmlNodePtr tree
, xmlNsPtr ns
);
63 static xmlChar
* xmlGetPropNodeValueInternal(const xmlAttr
*prop
);
65 /************************************************************************
67 * Tree memory error handler *
69 ************************************************************************/
72 * @extra: extra information
74 * Handle an out of memory condition
77 xmlTreeErrMemory(const char *extra
)
79 __xmlSimpleError(XML_FROM_TREE
, XML_ERR_NO_MEMORY
, NULL
, NULL
, extra
);
84 * @code: the error number
85 * @extra: extra information
87 * Handle an out of memory condition
90 xmlTreeErr(int code
, xmlNodePtr node
, const char *extra
)
92 const char *msg
= NULL
;
95 case XML_TREE_INVALID_HEX
:
96 msg
= "invalid hexadecimal character value\n";
98 case XML_TREE_INVALID_DEC
:
99 msg
= "invalid decimal character value\n";
101 case XML_TREE_UNTERMINATED_ENTITY
:
102 msg
= "unterminated entity reference %15s\n";
104 case XML_TREE_NOT_UTF8
:
105 msg
= "string is not in UTF-8\n";
108 msg
= "unexpected error number\n";
110 __xmlSimpleError(XML_FROM_TREE
, code
, node
, msg
, extra
);
113 /************************************************************************
115 * A few static variables and macros *
117 ************************************************************************/
118 /* #undef xmlStringText */
119 const xmlChar xmlStringText
[] = { 't', 'e', 'x', 't', 0 };
120 /* #undef xmlStringTextNoenc */
121 const xmlChar xmlStringTextNoenc
[] =
122 { 't', 'e', 'x', 't', 'n', 'o', 'e', 'n', 'c', 0 };
123 /* #undef xmlStringComment */
124 const xmlChar xmlStringComment
[] = { 'c', 'o', 'm', 'm', 'e', 'n', 't', 0 };
126 static int xmlCompressMode
= 0;
127 static int xmlCheckDTD
= 1;
129 #define UPDATE_LAST_CHILD_AND_PARENT(n) if ((n) != NULL) { \
130 xmlNodePtr ulccur = (n)->children; \
131 if (ulccur == NULL) { \
134 while (ulccur->next != NULL) { \
135 ulccur->parent = (n); \
136 ulccur = ulccur->next; \
138 ulccur->parent = (n); \
139 (n)->last = ulccur; \
142 #define IS_STR_XML(str) ((str != NULL) && (str[0] == 'x') && \
143 (str[1] == 'm') && (str[2] == 'l') && (str[3] == 0))
145 /* #define DEBUG_BUFFER */
146 /* #define DEBUG_TREE */
148 /************************************************************************
150 * Functions to move to entities.c once the *
151 * API freeze is smoothen and they can be made public. *
153 ************************************************************************/
154 #include <libxml/hash.h>
156 #ifdef LIBXML_TREE_ENABLED
158 * xmlGetEntityFromDtd:
159 * @dtd: A pointer to the DTD to search
160 * @name: The entity name
162 * Do an entity lookup in the DTD entity hash table and
163 * return the corresponding entity, if found.
165 * Returns A pointer to the entity structure or NULL if not found.
168 xmlGetEntityFromDtd(const xmlDtd
*dtd
, const xmlChar
*name
) {
169 xmlEntitiesTablePtr table
;
171 if((dtd
!= NULL
) && (dtd
->entities
!= NULL
)) {
172 table
= (xmlEntitiesTablePtr
) dtd
->entities
;
173 return((xmlEntityPtr
) xmlHashLookup(table
, name
));
174 /* return(xmlGetEntityFromTable(table, name)); */
179 * xmlGetParameterEntityFromDtd:
180 * @dtd: A pointer to the DTD to search
181 * @name: The entity name
183 * Do an entity lookup in the DTD parameter entity hash table and
184 * return the corresponding entity, if found.
186 * Returns A pointer to the entity structure or NULL if not found.
189 xmlGetParameterEntityFromDtd(const xmlDtd
*dtd
, const xmlChar
*name
) {
190 xmlEntitiesTablePtr table
;
192 if ((dtd
!= NULL
) && (dtd
->pentities
!= NULL
)) {
193 table
= (xmlEntitiesTablePtr
) dtd
->pentities
;
194 return((xmlEntityPtr
) xmlHashLookup(table
, name
));
195 /* return(xmlGetEntityFromTable(table, name)); */
199 #endif /* LIBXML_TREE_ENABLED */
201 /************************************************************************
203 * QName handling helper *
205 ************************************************************************/
210 * @prefix: the prefix
211 * @memory: preallocated memory
212 * @len: preallocated memory length
214 * Builds the QName @prefix:@ncname in @memory if there is enough space
215 * and prefix is not NULL nor empty, otherwise allocate a new string.
216 * If prefix is NULL or empty it returns ncname.
218 * Returns the new string which must be freed by the caller if different from
219 * @memory and @ncname or NULL in case of error
222 xmlBuildQName(const xmlChar
*ncname
, const xmlChar
*prefix
,
223 xmlChar
*memory
, int len
) {
227 if (ncname
== NULL
) return(NULL
);
228 if (prefix
== NULL
) return((xmlChar
*) ncname
);
230 lenn
= strlen((char *) ncname
);
231 lenp
= strlen((char *) prefix
);
233 if ((memory
== NULL
) || (len
< lenn
+ lenp
+ 2)) {
234 ret
= (xmlChar
*) xmlMallocAtomic(lenn
+ lenp
+ 2);
236 xmlTreeErrMemory("building QName");
242 memcpy(&ret
[0], prefix
, lenp
);
244 memcpy(&ret
[lenp
+ 1], ncname
, lenn
);
245 ret
[lenn
+ lenp
+ 1] = 0;
251 * @name: the full QName
252 * @prefix: a xmlChar **
254 * parse an XML qualified name string
256 * [NS 5] QName ::= (Prefix ':')? LocalPart
258 * [NS 6] Prefix ::= NCName
260 * [NS 7] LocalPart ::= NCName
262 * Returns NULL if the name doesn't have a prefix. Otherwise, returns the
263 * local part, and prefix is updated to get the Prefix. Both the return value
264 * and the prefix must be freed by the caller.
267 xmlSplitQName2(const xmlChar
*name
, xmlChar
**prefix
) {
271 if (prefix
== NULL
) return(NULL
);
273 if (name
== NULL
) return(NULL
);
275 #ifndef XML_XML_NAMESPACE
276 /* xml: prefix is not really a namespace */
277 if ((name
[0] == 'x') && (name
[1] == 'm') &&
278 (name
[2] == 'l') && (name
[3] == ':'))
282 /* nasty but valid */
287 * we are not trying to validate but just to cut, and yes it will
288 * work even if this is as set of UTF-8 encoded chars
290 while ((name
[len
] != 0) && (name
[len
] != ':'))
296 *prefix
= xmlStrndup(name
, len
);
297 if (*prefix
== NULL
) {
298 xmlTreeErrMemory("QName split");
301 ret
= xmlStrdup(&name
[len
+ 1]);
303 xmlTreeErrMemory("QName split");
304 if (*prefix
!= NULL
) {
316 * @name: the full QName
319 * parse an XML qualified name string,i
321 * returns NULL if it is not a Qualified Name, otherwise, update len
322 * with the length in byte of the prefix and return a pointer
323 * to the start of the name without the prefix
327 xmlSplitQName3(const xmlChar
*name
, int *len
) {
330 if (name
== NULL
) return(NULL
);
331 if (len
== NULL
) return(NULL
);
333 /* nasty but valid */
338 * we are not trying to validate but just to cut, and yes it will
339 * work even if this is as set of UTF-8 encoded chars
341 while ((name
[l
] != 0) && (name
[l
] != ':'))
352 /************************************************************************
354 * Check Name, NCName and QName strings *
356 ************************************************************************/
358 #define CUR_SCHAR(s, l) xmlStringCurrentChar(NULL, s, &l)
360 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XPATH_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) || defined(LIBXML_DEBUG_ENABLED) || defined (LIBXML_HTML_ENABLED) || defined(LIBXML_SAX1_ENABLED) || defined(LIBXML_HTML_ENABLED) || defined(LIBXML_WRITER_ENABLED) || defined(LIBXML_LEGACY_ENABLED)
363 * @value: the value to check
364 * @space: allow spaces in front and end of the string
366 * Check that a value conforms to the lexical space of NCName
368 * Returns 0 if this validates, a positive error code number otherwise
369 * and -1 in case of internal or API error.
372 xmlValidateNCName(const xmlChar
*value
, int space
) {
373 const xmlChar
*cur
= value
;
380 * First quick algorithm for ASCII range
383 while (IS_BLANK_CH(*cur
)) cur
++;
384 if (((*cur
>= 'a') && (*cur
<= 'z')) || ((*cur
>= 'A') && (*cur
<= 'Z')) ||
389 while (((*cur
>= 'a') && (*cur
<= 'z')) ||
390 ((*cur
>= 'A') && (*cur
<= 'Z')) ||
391 ((*cur
>= '0') && (*cur
<= '9')) ||
392 (*cur
== '_') || (*cur
== '-') || (*cur
== '.'))
395 while (IS_BLANK_CH(*cur
)) cur
++;
401 * Second check for chars outside the ASCII range
404 c
= CUR_SCHAR(cur
, l
);
406 while (IS_BLANK(c
)) {
408 c
= CUR_SCHAR(cur
, l
);
411 if ((!IS_LETTER(c
)) && (c
!= '_'))
414 c
= CUR_SCHAR(cur
, l
);
415 while (IS_LETTER(c
) || IS_DIGIT(c
) || (c
== '.') ||
416 (c
== '-') || (c
== '_') || IS_COMBINING(c
) ||
419 c
= CUR_SCHAR(cur
, l
);
422 while (IS_BLANK(c
)) {
424 c
= CUR_SCHAR(cur
, l
);
434 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
437 * @value: the value to check
438 * @space: allow spaces in front and end of the string
440 * Check that a value conforms to the lexical space of QName
442 * Returns 0 if this validates, a positive error code number otherwise
443 * and -1 in case of internal or API error.
446 xmlValidateQName(const xmlChar
*value
, int space
) {
447 const xmlChar
*cur
= value
;
453 * First quick algorithm for ASCII range
456 while (IS_BLANK_CH(*cur
)) cur
++;
457 if (((*cur
>= 'a') && (*cur
<= 'z')) || ((*cur
>= 'A') && (*cur
<= 'Z')) ||
462 while (((*cur
>= 'a') && (*cur
<= 'z')) ||
463 ((*cur
>= 'A') && (*cur
<= 'Z')) ||
464 ((*cur
>= '0') && (*cur
<= '9')) ||
465 (*cur
== '_') || (*cur
== '-') || (*cur
== '.'))
469 if (((*cur
>= 'a') && (*cur
<= 'z')) ||
470 ((*cur
>= 'A') && (*cur
<= 'Z')) ||
475 while (((*cur
>= 'a') && (*cur
<= 'z')) ||
476 ((*cur
>= 'A') && (*cur
<= 'Z')) ||
477 ((*cur
>= '0') && (*cur
<= '9')) ||
478 (*cur
== '_') || (*cur
== '-') || (*cur
== '.'))
482 while (IS_BLANK_CH(*cur
)) cur
++;
488 * Second check for chars outside the ASCII range
491 c
= CUR_SCHAR(cur
, l
);
493 while (IS_BLANK(c
)) {
495 c
= CUR_SCHAR(cur
, l
);
498 if ((!IS_LETTER(c
)) && (c
!= '_'))
501 c
= CUR_SCHAR(cur
, l
);
502 while (IS_LETTER(c
) || IS_DIGIT(c
) || (c
== '.') ||
503 (c
== '-') || (c
== '_') || IS_COMBINING(c
) ||
506 c
= CUR_SCHAR(cur
, l
);
510 c
= CUR_SCHAR(cur
, l
);
511 if ((!IS_LETTER(c
)) && (c
!= '_'))
514 c
= CUR_SCHAR(cur
, l
);
515 while (IS_LETTER(c
) || IS_DIGIT(c
) || (c
== '.') ||
516 (c
== '-') || (c
== '_') || IS_COMBINING(c
) ||
519 c
= CUR_SCHAR(cur
, l
);
523 while (IS_BLANK(c
)) {
525 c
= CUR_SCHAR(cur
, l
);
535 * @value: the value to check
536 * @space: allow spaces in front and end of the string
538 * Check that a value conforms to the lexical space of Name
540 * Returns 0 if this validates, a positive error code number otherwise
541 * and -1 in case of internal or API error.
544 xmlValidateName(const xmlChar
*value
, int space
) {
545 const xmlChar
*cur
= value
;
551 * First quick algorithm for ASCII range
554 while (IS_BLANK_CH(*cur
)) cur
++;
555 if (((*cur
>= 'a') && (*cur
<= 'z')) || ((*cur
>= 'A') && (*cur
<= 'Z')) ||
556 (*cur
== '_') || (*cur
== ':'))
560 while (((*cur
>= 'a') && (*cur
<= 'z')) ||
561 ((*cur
>= 'A') && (*cur
<= 'Z')) ||
562 ((*cur
>= '0') && (*cur
<= '9')) ||
563 (*cur
== '_') || (*cur
== '-') || (*cur
== '.') || (*cur
== ':'))
566 while (IS_BLANK_CH(*cur
)) cur
++;
572 * Second check for chars outside the ASCII range
575 c
= CUR_SCHAR(cur
, l
);
577 while (IS_BLANK(c
)) {
579 c
= CUR_SCHAR(cur
, l
);
582 if ((!IS_LETTER(c
)) && (c
!= '_') && (c
!= ':'))
585 c
= CUR_SCHAR(cur
, l
);
586 while (IS_LETTER(c
) || IS_DIGIT(c
) || (c
== '.') || (c
== ':') ||
587 (c
== '-') || (c
== '_') || IS_COMBINING(c
) || IS_EXTENDER(c
)) {
589 c
= CUR_SCHAR(cur
, l
);
592 while (IS_BLANK(c
)) {
594 c
= CUR_SCHAR(cur
, l
);
603 * xmlValidateNMToken:
604 * @value: the value to check
605 * @space: allow spaces in front and end of the string
607 * Check that a value conforms to the lexical space of NMToken
609 * Returns 0 if this validates, a positive error code number otherwise
610 * and -1 in case of internal or API error.
613 xmlValidateNMToken(const xmlChar
*value
, int space
) {
614 const xmlChar
*cur
= value
;
620 * First quick algorithm for ASCII range
623 while (IS_BLANK_CH(*cur
)) cur
++;
624 if (((*cur
>= 'a') && (*cur
<= 'z')) ||
625 ((*cur
>= 'A') && (*cur
<= 'Z')) ||
626 ((*cur
>= '0') && (*cur
<= '9')) ||
627 (*cur
== '_') || (*cur
== '-') || (*cur
== '.') || (*cur
== ':'))
631 while (((*cur
>= 'a') && (*cur
<= 'z')) ||
632 ((*cur
>= 'A') && (*cur
<= 'Z')) ||
633 ((*cur
>= '0') && (*cur
<= '9')) ||
634 (*cur
== '_') || (*cur
== '-') || (*cur
== '.') || (*cur
== ':'))
637 while (IS_BLANK_CH(*cur
)) cur
++;
643 * Second check for chars outside the ASCII range
646 c
= CUR_SCHAR(cur
, l
);
648 while (IS_BLANK(c
)) {
650 c
= CUR_SCHAR(cur
, l
);
653 if (!(IS_LETTER(c
) || IS_DIGIT(c
) || (c
== '.') || (c
== ':') ||
654 (c
== '-') || (c
== '_') || IS_COMBINING(c
) || IS_EXTENDER(c
)))
657 c
= CUR_SCHAR(cur
, l
);
658 while (IS_LETTER(c
) || IS_DIGIT(c
) || (c
== '.') || (c
== ':') ||
659 (c
== '-') || (c
== '_') || IS_COMBINING(c
) || IS_EXTENDER(c
)) {
661 c
= CUR_SCHAR(cur
, l
);
664 while (IS_BLANK(c
)) {
666 c
= CUR_SCHAR(cur
, l
);
673 #endif /* LIBXML_TREE_ENABLED */
675 /************************************************************************
677 * Allocation and deallocation of basic structures *
679 ************************************************************************/
682 * xmlSetBufferAllocationScheme:
683 * @scheme: allocation method to use
685 * Set the buffer allocation method. Types are
686 * XML_BUFFER_ALLOC_EXACT - use exact sizes, keeps memory usage down
687 * XML_BUFFER_ALLOC_DOUBLEIT - double buffer when extra needed,
688 * improves performance
691 xmlSetBufferAllocationScheme(xmlBufferAllocationScheme scheme
) {
692 if ((scheme
== XML_BUFFER_ALLOC_EXACT
) ||
693 (scheme
== XML_BUFFER_ALLOC_DOUBLEIT
) ||
694 (scheme
== XML_BUFFER_ALLOC_HYBRID
))
695 xmlBufferAllocScheme
= scheme
;
699 * xmlGetBufferAllocationScheme:
702 * XML_BUFFER_ALLOC_EXACT - use exact sizes, keeps memory usage down
703 * XML_BUFFER_ALLOC_DOUBLEIT - double buffer when extra needed,
704 * improves performance
705 * XML_BUFFER_ALLOC_HYBRID - use exact sizes on small strings to keep memory usage tight
706 * in normal usage, and doubleit on large strings to avoid
707 * pathological performance.
709 * Returns the current allocation scheme
711 xmlBufferAllocationScheme
712 xmlGetBufferAllocationScheme(void) {
713 return(xmlBufferAllocScheme
);
718 * @node: the element carrying the namespace
719 * @href: the URI associated
720 * @prefix: the prefix for the namespace
722 * Creation of a new Namespace. This function will refuse to create
723 * a namespace with a similar prefix than an existing one present on this
725 * Note that for a default namespace, @prefix should be NULL.
727 * We use href==NULL in the case of an element creation where the namespace
730 * Returns a new namespace pointer or NULL
733 xmlNewNs(xmlNodePtr node
, const xmlChar
*href
, const xmlChar
*prefix
) {
736 if ((node
!= NULL
) && (node
->type
!= XML_ELEMENT_NODE
))
739 if ((prefix
!= NULL
) && (xmlStrEqual(prefix
, BAD_CAST
"xml"))) {
740 /* xml namespace is predefined, no need to add it */
741 if (xmlStrEqual(href
, XML_XML_NAMESPACE
))
745 * Problem, this is an attempt to bind xml prefix to a wrong
746 * namespace, which breaks
747 * Namespace constraint: Reserved Prefixes and Namespace Names
748 * from XML namespace. But documents authors may not care in
749 * their context so let's proceed.
754 * Allocate a new Namespace and fill the fields.
756 cur
= (xmlNsPtr
) xmlMalloc(sizeof(xmlNs
));
758 xmlTreeErrMemory("building namespace");
761 memset(cur
, 0, sizeof(xmlNs
));
762 cur
->type
= XML_LOCAL_NAMESPACE
;
765 cur
->href
= xmlStrdup(href
);
767 cur
->prefix
= xmlStrdup(prefix
);
770 * Add it at the end to preserve parsing order ...
771 * and checks for existing use of the prefix
774 if (node
->nsDef
== NULL
) {
777 xmlNsPtr prev
= node
->nsDef
;
779 if (((prev
->prefix
== NULL
) && (cur
->prefix
== NULL
)) ||
780 (xmlStrEqual(prev
->prefix
, cur
->prefix
))) {
784 while (prev
->next
!= NULL
) {
786 if (((prev
->prefix
== NULL
) && (cur
->prefix
== NULL
)) ||
787 (xmlStrEqual(prev
->prefix
, cur
->prefix
))) {
800 * @node: a node in the document
801 * @ns: a namespace pointer
803 * Associate a namespace to a node, a posteriori.
806 xmlSetNs(xmlNodePtr node
, xmlNsPtr ns
) {
809 xmlGenericError(xmlGenericErrorContext
,
810 "xmlSetNs: node == NULL\n");
814 if ((node
->type
== XML_ELEMENT_NODE
) ||
815 (node
->type
== XML_ATTRIBUTE_NODE
))
821 * @cur: the namespace pointer
823 * Free up the structures associated to a namespace
826 xmlFreeNs(xmlNsPtr cur
) {
829 xmlGenericError(xmlGenericErrorContext
,
830 "xmlFreeNs : ns == NULL\n");
834 if (cur
->href
!= NULL
) xmlFree((char *) cur
->href
);
835 if (cur
->prefix
!= NULL
) xmlFree((char *) cur
->prefix
);
841 * @cur: the first namespace pointer
843 * Free up all the structures associated to the chained namespaces.
846 xmlFreeNsList(xmlNsPtr cur
) {
850 xmlGenericError(xmlGenericErrorContext
,
851 "xmlFreeNsList : ns == NULL\n");
855 while (cur
!= NULL
) {
864 * @doc: the document pointer
865 * @name: the DTD name
866 * @ExternalID: the external ID
867 * @SystemID: the system ID
869 * Creation of a new DTD for the external subset. To create an
870 * internal subset, use xmlCreateIntSubset().
872 * Returns a pointer to the new DTD structure
875 xmlNewDtd(xmlDocPtr doc
, const xmlChar
*name
,
876 const xmlChar
*ExternalID
, const xmlChar
*SystemID
) {
879 if ((doc
!= NULL
) && (doc
->extSubset
!= NULL
)) {
881 xmlGenericError(xmlGenericErrorContext
,
882 "xmlNewDtd(%s): document %s already have a DTD %s\n",
883 /* !!! */ (char *) name
, doc
->name
,
884 /* !!! */ (char *)doc
->extSubset
->name
);
890 * Allocate a new DTD and fill the fields.
892 cur
= (xmlDtdPtr
) xmlMalloc(sizeof(xmlDtd
));
894 xmlTreeErrMemory("building DTD");
897 memset(cur
, 0 , sizeof(xmlDtd
));
898 cur
->type
= XML_DTD_NODE
;
901 cur
->name
= xmlStrdup(name
);
902 if (ExternalID
!= NULL
)
903 cur
->ExternalID
= xmlStrdup(ExternalID
);
904 if (SystemID
!= NULL
)
905 cur
->SystemID
= xmlStrdup(SystemID
);
907 doc
->extSubset
= cur
;
910 if ((__xmlRegisterCallbacks
) && (xmlRegisterNodeDefaultValue
))
911 xmlRegisterNodeDefaultValue((xmlNodePtr
)cur
);
917 * @doc: the document pointer
919 * Get the internal subset of a document
920 * Returns a pointer to the DTD structure or NULL if not found
924 xmlGetIntSubset(const xmlDoc
*doc
) {
930 while (cur
!= NULL
) {
931 if (cur
->type
== XML_DTD_NODE
)
932 return((xmlDtdPtr
) cur
);
935 return((xmlDtdPtr
) doc
->intSubset
);
939 * xmlCreateIntSubset:
940 * @doc: the document pointer
941 * @name: the DTD name
942 * @ExternalID: the external (PUBLIC) ID
943 * @SystemID: the system ID
945 * Create the internal subset of a document
946 * Returns a pointer to the new DTD structure
949 xmlCreateIntSubset(xmlDocPtr doc
, const xmlChar
*name
,
950 const xmlChar
*ExternalID
, const xmlChar
*SystemID
) {
953 if ((doc
!= NULL
) && (xmlGetIntSubset(doc
) != NULL
)) {
955 xmlGenericError(xmlGenericErrorContext
,
957 "xmlCreateIntSubset(): document %s already have an internal subset\n",
964 * Allocate a new DTD and fill the fields.
966 cur
= (xmlDtdPtr
) xmlMalloc(sizeof(xmlDtd
));
968 xmlTreeErrMemory("building internal subset");
971 memset(cur
, 0, sizeof(xmlDtd
));
972 cur
->type
= XML_DTD_NODE
;
975 cur
->name
= xmlStrdup(name
);
976 if (cur
->name
== NULL
) {
977 xmlTreeErrMemory("building internal subset");
982 if (ExternalID
!= NULL
) {
983 cur
->ExternalID
= xmlStrdup(ExternalID
);
984 if (cur
->ExternalID
== NULL
) {
985 xmlTreeErrMemory("building internal subset");
986 if (cur
->name
!= NULL
)
987 xmlFree((char *)cur
->name
);
992 if (SystemID
!= NULL
) {
993 cur
->SystemID
= xmlStrdup(SystemID
);
994 if (cur
->SystemID
== NULL
) {
995 xmlTreeErrMemory("building internal subset");
996 if (cur
->name
!= NULL
)
997 xmlFree((char *)cur
->name
);
998 if (cur
->ExternalID
!= NULL
)
999 xmlFree((char *)cur
->ExternalID
);
1005 doc
->intSubset
= cur
;
1008 if (doc
->children
== NULL
) {
1009 doc
->children
= (xmlNodePtr
) cur
;
1010 doc
->last
= (xmlNodePtr
) cur
;
1012 if (doc
->type
== XML_HTML_DOCUMENT_NODE
) {
1015 prev
= doc
->children
;
1016 prev
->prev
= (xmlNodePtr
) cur
;
1018 doc
->children
= (xmlNodePtr
) cur
;
1022 next
= doc
->children
;
1023 while ((next
!= NULL
) && (next
->type
!= XML_ELEMENT_NODE
))
1026 cur
->prev
= doc
->last
;
1027 cur
->prev
->next
= (xmlNodePtr
) cur
;
1029 doc
->last
= (xmlNodePtr
) cur
;
1032 cur
->prev
= next
->prev
;
1033 if (cur
->prev
== NULL
)
1034 doc
->children
= (xmlNodePtr
) cur
;
1036 cur
->prev
->next
= (xmlNodePtr
) cur
;
1037 next
->prev
= (xmlNodePtr
) cur
;
1043 if ((__xmlRegisterCallbacks
) && (xmlRegisterNodeDefaultValue
))
1044 xmlRegisterNodeDefaultValue((xmlNodePtr
)cur
);
1052 * Free a string if it is not owned by the "dict" dictionary in the
1055 #define DICT_FREE(str) \
1056 if ((str) && ((!dict) || \
1057 (xmlDictOwns(dict, (const xmlChar *)(str)) == 0))) \
1058 xmlFree((char *)(str));
1065 * Copy a string using a "dict" dictionary in the current scope,
1068 #define DICT_COPY(str, cpy) \
1071 if (xmlDictOwns(dict, (const xmlChar *)(str))) \
1072 cpy = (xmlChar *) (str); \
1074 cpy = (xmlChar *) xmlDictLookup((dict), (const xmlChar *)(str), -1); \
1076 cpy = xmlStrdup((const xmlChar *)(str)); }
1082 * Copy a string using a "dict" dictionary in the current scope,
1085 #define DICT_CONST_COPY(str, cpy) \
1088 if (xmlDictOwns(dict, (const xmlChar *)(str))) \
1089 cpy = (const xmlChar *) (str); \
1091 cpy = xmlDictLookup((dict), (const xmlChar *)(str), -1); \
1093 cpy = (const xmlChar *) xmlStrdup((const xmlChar *)(str)); }
1098 * @cur: the DTD structure to free up
1100 * Free a DTD structure.
1103 xmlFreeDtd(xmlDtdPtr cur
) {
1104 xmlDictPtr dict
= NULL
;
1109 if (cur
->doc
!= NULL
) dict
= cur
->doc
->dict
;
1111 if ((__xmlRegisterCallbacks
) && (xmlDeregisterNodeDefaultValue
))
1112 xmlDeregisterNodeDefaultValue((xmlNodePtr
)cur
);
1114 if (cur
->children
!= NULL
) {
1115 xmlNodePtr next
, c
= cur
->children
;
1118 * Cleanup all nodes which are not part of the specific lists
1119 * of notations, elements, attributes and entities.
1123 if ((c
->type
!= XML_NOTATION_NODE
) &&
1124 (c
->type
!= XML_ELEMENT_DECL
) &&
1125 (c
->type
!= XML_ATTRIBUTE_DECL
) &&
1126 (c
->type
!= XML_ENTITY_DECL
)) {
1133 DICT_FREE(cur
->name
)
1134 DICT_FREE(cur
->SystemID
)
1135 DICT_FREE(cur
->ExternalID
)
1137 if (cur
->notations
!= NULL
)
1138 xmlFreeNotationTable((xmlNotationTablePtr
) cur
->notations
);
1140 if (cur
->elements
!= NULL
)
1141 xmlFreeElementTable((xmlElementTablePtr
) cur
->elements
);
1142 if (cur
->attributes
!= NULL
)
1143 xmlFreeAttributeTable((xmlAttributeTablePtr
) cur
->attributes
);
1144 if (cur
->entities
!= NULL
)
1145 xmlFreeEntitiesTable((xmlEntitiesTablePtr
) cur
->entities
);
1146 if (cur
->pentities
!= NULL
)
1147 xmlFreeEntitiesTable((xmlEntitiesTablePtr
) cur
->pentities
);
1154 * @version: xmlChar string giving the version of XML "1.0"
1156 * Creates a new XML document
1158 * Returns a new document
1161 xmlNewDoc(const xmlChar
*version
) {
1164 if (version
== NULL
)
1165 version
= (const xmlChar
*) "1.0";
1168 * Allocate a new document and fill the fields.
1170 cur
= (xmlDocPtr
) xmlMalloc(sizeof(xmlDoc
));
1172 xmlTreeErrMemory("building doc");
1175 memset(cur
, 0, sizeof(xmlDoc
));
1176 cur
->type
= XML_DOCUMENT_NODE
;
1178 cur
->version
= xmlStrdup(version
);
1179 if (cur
->version
== NULL
) {
1180 xmlTreeErrMemory("building doc");
1184 cur
->standalone
= -1;
1185 cur
->compression
= -1; /* not initialized */
1187 cur
->parseFlags
= 0;
1188 cur
->properties
= XML_DOC_USERBUILT
;
1190 * The in memory encoding is always UTF8
1191 * This field will never change and would
1192 * be obsolete if not for binary compatibility.
1194 cur
->charset
= XML_CHAR_ENCODING_UTF8
;
1196 if ((__xmlRegisterCallbacks
) && (xmlRegisterNodeDefaultValue
))
1197 xmlRegisterNodeDefaultValue((xmlNodePtr
)cur
);
1203 * @cur: pointer to the document
1205 * Free up all the structures used by a document, tree included.
1208 xmlFreeDoc(xmlDocPtr cur
) {
1209 xmlDtdPtr extSubset
, intSubset
;
1210 xmlDictPtr dict
= NULL
;
1214 xmlGenericError(xmlGenericErrorContext
,
1215 "xmlFreeDoc : document == NULL\n");
1220 if (cur
!= NULL
) dict
= cur
->dict
;
1222 if ((__xmlRegisterCallbacks
) && (xmlDeregisterNodeDefaultValue
))
1223 xmlDeregisterNodeDefaultValue((xmlNodePtr
)cur
);
1226 * Do this before freeing the children list to avoid ID lookups
1228 if (cur
->ids
!= NULL
) xmlFreeIDTable((xmlIDTablePtr
) cur
->ids
);
1230 if (cur
->refs
!= NULL
) xmlFreeRefTable((xmlRefTablePtr
) cur
->refs
);
1232 extSubset
= cur
->extSubset
;
1233 intSubset
= cur
->intSubset
;
1234 if (intSubset
== extSubset
)
1236 if (extSubset
!= NULL
) {
1237 xmlUnlinkNode((xmlNodePtr
) cur
->extSubset
);
1238 cur
->extSubset
= NULL
;
1239 xmlFreeDtd(extSubset
);
1241 if (intSubset
!= NULL
) {
1242 xmlUnlinkNode((xmlNodePtr
) cur
->intSubset
);
1243 cur
->intSubset
= NULL
;
1244 xmlFreeDtd(intSubset
);
1247 if (cur
->children
!= NULL
) xmlFreeNodeList(cur
->children
);
1248 if (cur
->oldNs
!= NULL
) xmlFreeNsList(cur
->oldNs
);
1250 DICT_FREE(cur
->version
)
1251 DICT_FREE(cur
->name
)
1252 DICT_FREE(cur
->encoding
)
1255 if (dict
) xmlDictFree(dict
);
1259 * xmlStringLenGetNodeList:
1260 * @doc: the document
1261 * @value: the value of the text
1262 * @len: the length of the string value
1264 * Parse the value string and build the node list associated. Should
1265 * produce a flat tree with only TEXTs and ENTITY_REFs.
1266 * Returns a pointer to the first child
1269 xmlStringLenGetNodeList(const xmlDoc
*doc
, const xmlChar
*value
, int len
) {
1270 xmlNodePtr ret
= NULL
, last
= NULL
;
1273 const xmlChar
*cur
, *end
;
1278 if (value
== NULL
) return(NULL
);
1282 buf
= xmlBufCreateSize(0);
1283 if (buf
== NULL
) return(NULL
);
1284 xmlBufSetAllocationScheme(buf
, XML_BUFFER_ALLOC_DOUBLEIT
);
1287 while ((cur
< end
) && (*cur
!= 0)) {
1288 if (cur
[0] == '&') {
1293 * Save the current text.
1296 if (xmlBufAdd(buf
, q
, cur
- q
))
1300 if ((cur
+ 2 < end
) && (cur
[1] == '#') && (cur
[2] == 'x')) {
1306 while (tmp
!= ';') { /* Non input consuming loop */
1308 * If you find an integer overflow here when fuzzing,
1309 * the bug is probably elsewhere. This function should
1310 * only receive entities that were already validated by
1311 * the parser, typically by xmlParseAttValueComplex
1312 * calling xmlStringDecodeEntities.
1314 * So it's better *not* to check for overflow to
1315 * potentially discover new bugs.
1317 if ((tmp
>= '0') && (tmp
<= '9'))
1318 charval
= charval
* 16 + (tmp
- '0');
1319 else if ((tmp
>= 'a') && (tmp
<= 'f'))
1320 charval
= charval
* 16 + (tmp
- 'a') + 10;
1321 else if ((tmp
>= 'A') && (tmp
<= 'F'))
1322 charval
= charval
* 16 + (tmp
- 'A') + 10;
1324 xmlTreeErr(XML_TREE_INVALID_HEX
, (xmlNodePtr
) doc
,
1338 } else if ((cur
+ 1 < end
) && (cur
[1] == '#')) {
1344 while (tmp
!= ';') { /* Non input consuming loops */
1345 /* Don't check for integer overflow, see above. */
1346 if ((tmp
>= '0') && (tmp
<= '9'))
1347 charval
= charval
* 10 + (tmp
- '0');
1349 xmlTreeErr(XML_TREE_INVALID_DEC
, (xmlNodePtr
) doc
,
1365 * Read the entity string
1369 while ((cur
< end
) && (*cur
!= 0) && (*cur
!= ';')) cur
++;
1370 if ((cur
>= end
) || (*cur
== 0)) {
1371 xmlTreeErr(XML_TREE_UNTERMINATED_ENTITY
, (xmlNodePtr
) doc
,
1377 * Predefined entities don't generate nodes
1379 val
= xmlStrndup(q
, cur
- q
);
1380 ent
= xmlGetDocEntity(doc
, val
);
1381 if ((ent
!= NULL
) &&
1382 (ent
->etype
== XML_INTERNAL_PREDEFINED_ENTITY
)) {
1384 if (xmlBufCat(buf
, ent
->content
))
1389 * Flush buffer so far
1391 if (!xmlBufIsEmpty(buf
)) {
1392 node
= xmlNewDocText(doc
, NULL
);
1394 if (val
!= NULL
) xmlFree(val
);
1397 node
->content
= xmlBufDetach(buf
);
1402 last
= xmlAddNextSibling(last
, node
);
1407 * Create a new REFERENCE_REF node
1409 node
= xmlNewReference(doc
, val
);
1411 if (val
!= NULL
) xmlFree(val
);
1414 else if ((ent
!= NULL
) &&
1415 ((ent
->flags
& XML_ENT_PARSED
) == 0) &&
1416 ((ent
->flags
& XML_ENT_EXPANDING
) == 0)) {
1420 * The entity should have been checked already,
1421 * but set the flag anyway to avoid recursion.
1423 ent
->flags
|= XML_ENT_EXPANDING
;
1424 ent
->children
= xmlStringGetNodeList(doc
,
1425 (const xmlChar
*)node
->content
);
1427 ent
->flags
&= ~XML_ENT_EXPANDING
;
1428 ent
->flags
|= XML_ENT_PARSED
;
1429 temp
= ent
->children
;
1431 temp
->parent
= (xmlNodePtr
)ent
;
1439 last
= xmlAddNextSibling(last
, node
);
1451 l
= xmlCopyCharMultiByte(buffer
, charval
);
1454 if (xmlBufCat(buf
, buffer
))
1464 * Handle the last piece of text.
1466 if (xmlBufAdd(buf
, q
, cur
- q
))
1470 if (!xmlBufIsEmpty(buf
)) {
1471 node
= xmlNewDocText(doc
, NULL
);
1472 if (node
== NULL
) goto out
;
1473 node
->content
= xmlBufDetach(buf
);
1478 xmlAddNextSibling(last
, node
);
1480 } else if (ret
== NULL
) {
1481 ret
= xmlNewDocText(doc
, BAD_CAST
"");
1490 * xmlStringGetNodeList:
1491 * @doc: the document
1492 * @value: the value of the attribute
1494 * Parse the value string and build the node list associated. Should
1495 * produce a flat tree with only TEXTs and ENTITY_REFs.
1496 * Returns a pointer to the first child
1499 xmlStringGetNodeList(const xmlDoc
*doc
, const xmlChar
*value
) {
1500 xmlNodePtr ret
= NULL
, head
= NULL
, last
= NULL
;
1502 xmlChar
*val
= NULL
;
1503 const xmlChar
*cur
= value
;
1508 if (value
== NULL
) return(NULL
);
1510 buf
= xmlBufCreateSize(0);
1511 if (buf
== NULL
) return(NULL
);
1512 xmlBufSetAllocationScheme(buf
, XML_BUFFER_ALLOC_DOUBLEIT
);
1516 if (cur
[0] == '&') {
1521 * Save the current text.
1524 if (xmlBufAdd(buf
, q
, cur
- q
))
1528 if ((cur
[1] == '#') && (cur
[2] == 'x')) {
1531 while (tmp
!= ';') { /* Non input consuming loop */
1532 /* Don't check for integer overflow, see above. */
1533 if ((tmp
>= '0') && (tmp
<= '9'))
1534 charval
= charval
* 16 + (tmp
- '0');
1535 else if ((tmp
>= 'a') && (tmp
<= 'f'))
1536 charval
= charval
* 16 + (tmp
- 'a') + 10;
1537 else if ((tmp
>= 'A') && (tmp
<= 'F'))
1538 charval
= charval
* 16 + (tmp
- 'A') + 10;
1540 xmlTreeErr(XML_TREE_INVALID_HEX
, (xmlNodePtr
) doc
,
1551 } else if (cur
[1] == '#') {
1554 while (tmp
!= ';') { /* Non input consuming loops */
1555 /* Don't check for integer overflow, see above. */
1556 if ((tmp
>= '0') && (tmp
<= '9'))
1557 charval
= charval
* 10 + (tmp
- '0');
1559 xmlTreeErr(XML_TREE_INVALID_DEC
, (xmlNodePtr
) doc
,
1572 * Read the entity string
1576 while ((*cur
!= 0) && (*cur
!= ';')) cur
++;
1578 xmlTreeErr(XML_TREE_UNTERMINATED_ENTITY
,
1579 (xmlNodePtr
) doc
, (const char *) q
);
1584 * Predefined entities don't generate nodes
1586 val
= xmlStrndup(q
, cur
- q
);
1587 ent
= xmlGetDocEntity(doc
, val
);
1588 if ((ent
!= NULL
) &&
1589 (ent
->etype
== XML_INTERNAL_PREDEFINED_ENTITY
)) {
1591 if (xmlBufCat(buf
, ent
->content
))
1596 * Flush buffer so far
1598 if (!xmlBufIsEmpty(buf
)) {
1599 node
= xmlNewDocText(doc
, NULL
);
1602 node
->content
= xmlBufDetach(buf
);
1607 last
= xmlAddNextSibling(last
, node
);
1612 * Create a new REFERENCE_REF node
1614 node
= xmlNewReference(doc
, val
);
1617 if ((ent
!= NULL
) &&
1618 ((ent
->flags
& XML_ENT_PARSED
) == 0) &&
1619 ((ent
->flags
& XML_ENT_EXPANDING
) == 0)) {
1623 * The entity should have been checked already,
1624 * but set the flag anyway to avoid recursion.
1626 ent
->flags
|= XML_ENT_EXPANDING
;
1627 ent
->children
= xmlStringGetNodeList(doc
,
1628 (const xmlChar
*)node
->content
);
1630 ent
->flags
&= ~XML_ENT_EXPANDING
;
1631 ent
->flags
|= XML_ENT_PARSED
;
1632 temp
= ent
->children
;
1634 temp
->parent
= (xmlNodePtr
)ent
;
1642 last
= xmlAddNextSibling(last
, node
);
1655 len
= xmlCopyCharMultiByte(buffer
, charval
);
1658 if (xmlBufCat(buf
, buffer
))
1665 if ((cur
!= q
) || (head
== NULL
)) {
1667 * Handle the last piece of text.
1669 xmlBufAdd(buf
, q
, cur
- q
);
1672 if (!xmlBufIsEmpty(buf
)) {
1673 node
= xmlNewDocText(doc
, NULL
);
1676 node
->content
= xmlBufDetach(buf
);
1681 xmlAddNextSibling(last
, node
);
1690 if (val
!= NULL
) xmlFree(val
);
1691 if (head
!= NULL
) xmlFreeNodeList(head
);
1696 * xmlNodeListGetString:
1697 * @doc: the document
1698 * @list: a Node list
1699 * @inLine: should we replace entity contents or show their external form
1701 * Build the string equivalent to the text contained in the Node list
1702 * made of TEXTs and ENTITY_REFs
1704 * Returns a pointer to the string copy, the caller must free it with xmlFree().
1707 xmlNodeListGetString(xmlDocPtr doc
, const xmlNode
*list
, int inLine
)
1709 const xmlNode
*node
= list
;
1710 xmlChar
*ret
= NULL
;
1716 if ((list
->parent
!= NULL
) && (list
->parent
->type
== XML_ATTRIBUTE_NODE
))
1721 while (node
!= NULL
) {
1722 if ((node
->type
== XML_TEXT_NODE
) ||
1723 (node
->type
== XML_CDATA_SECTION_NODE
)) {
1725 ret
= xmlStrcat(ret
, node
->content
);
1730 buffer
= xmlEncodeAttributeEntities(doc
, node
->content
);
1732 buffer
= xmlEncodeEntitiesReentrant(doc
, node
->content
);
1733 if (buffer
!= NULL
) {
1734 ret
= xmlStrcat(ret
, buffer
);
1738 } else if (node
->type
== XML_ENTITY_REF_NODE
) {
1740 ent
= xmlGetDocEntity(doc
, node
->name
);
1744 /* an entity content can be any "well balanced chunk",
1745 * i.e. the result of the content [43] production:
1746 * http://www.w3.org/TR/REC-xml#NT-content.
1747 * So it can contain text, CDATA section or nested
1748 * entity reference nodes (among others).
1749 * -> we recursive call xmlNodeListGetString()
1750 * which handles these types */
1751 buffer
= xmlNodeListGetString(doc
, ent
->children
, 1);
1752 if (buffer
!= NULL
) {
1753 ret
= xmlStrcat(ret
, buffer
);
1757 ret
= xmlStrcat(ret
, node
->content
);
1764 ret
= xmlStrncat(ret
, buf
, 1);
1765 ret
= xmlStrcat(ret
, node
->name
);
1768 ret
= xmlStrncat(ret
, buf
, 1);
1773 xmlGenericError(xmlGenericErrorContext
,
1774 "xmlGetNodeListString : invalid node type %d\n",
1783 #ifdef LIBXML_TREE_ENABLED
1785 * xmlNodeListGetRawString:
1786 * @doc: the document
1787 * @list: a Node list
1788 * @inLine: should we replace entity contents or show their external form
1790 * Builds the string equivalent to the text contained in the Node list
1791 * made of TEXTs and ENTITY_REFs, contrary to xmlNodeListGetString()
1792 * this function doesn't do any character encoding handling.
1794 * Returns a pointer to the string copy, the caller must free it with xmlFree().
1797 xmlNodeListGetRawString(const xmlDoc
*doc
, const xmlNode
*list
, int inLine
)
1799 const xmlNode
*node
= list
;
1800 xmlChar
*ret
= NULL
;
1806 while (node
!= NULL
) {
1807 if ((node
->type
== XML_TEXT_NODE
) ||
1808 (node
->type
== XML_CDATA_SECTION_NODE
)) {
1810 ret
= xmlStrcat(ret
, node
->content
);
1814 buffer
= xmlEncodeSpecialChars(doc
, node
->content
);
1815 if (buffer
!= NULL
) {
1816 ret
= xmlStrcat(ret
, buffer
);
1820 } else if (node
->type
== XML_ENTITY_REF_NODE
) {
1822 ent
= xmlGetDocEntity(doc
, node
->name
);
1826 /* an entity content can be any "well balanced chunk",
1827 * i.e. the result of the content [43] production:
1828 * http://www.w3.org/TR/REC-xml#NT-content.
1829 * So it can contain text, CDATA section or nested
1830 * entity reference nodes (among others).
1831 * -> we recursive call xmlNodeListGetRawString()
1832 * which handles these types */
1834 xmlNodeListGetRawString(doc
, ent
->children
, 1);
1835 if (buffer
!= NULL
) {
1836 ret
= xmlStrcat(ret
, buffer
);
1840 ret
= xmlStrcat(ret
, node
->content
);
1847 ret
= xmlStrncat(ret
, buf
, 1);
1848 ret
= xmlStrcat(ret
, node
->name
);
1851 ret
= xmlStrncat(ret
, buf
, 1);
1856 xmlGenericError(xmlGenericErrorContext
,
1857 "xmlGetNodeListString : invalid node type %d\n",
1865 #endif /* LIBXML_TREE_ENABLED */
1868 xmlNewPropInternal(xmlNodePtr node
, xmlNsPtr ns
,
1869 const xmlChar
* name
, const xmlChar
* value
,
1873 xmlDocPtr doc
= NULL
;
1875 if ((node
!= NULL
) && (node
->type
!= XML_ELEMENT_NODE
)) {
1876 if ((eatname
== 1) &&
1877 ((node
->doc
== NULL
) || (node
->doc
->dict
== NULL
) ||
1878 (!(xmlDictOwns(node
->doc
->dict
, name
)))))
1879 xmlFree((xmlChar
*) name
);
1884 * Allocate a new property and fill the fields.
1886 cur
= (xmlAttrPtr
) xmlMalloc(sizeof(xmlAttr
));
1888 if ((eatname
== 1) &&
1889 ((node
== NULL
) || (node
->doc
== NULL
) ||
1890 (node
->doc
->dict
== NULL
) ||
1891 (!(xmlDictOwns(node
->doc
->dict
, name
)))))
1892 xmlFree((xmlChar
*) name
);
1893 xmlTreeErrMemory("building attribute");
1896 memset(cur
, 0, sizeof(xmlAttr
));
1897 cur
->type
= XML_ATTRIBUTE_NODE
;
1907 if ((doc
!= NULL
) && (doc
->dict
!= NULL
))
1908 cur
->name
= (xmlChar
*) xmlDictLookup(doc
->dict
, name
, -1);
1910 cur
->name
= xmlStrdup(name
);
1914 if (value
!= NULL
) {
1917 cur
->children
= xmlNewDocText(doc
, value
);
1919 tmp
= cur
->children
;
1920 while (tmp
!= NULL
) {
1921 tmp
->parent
= (xmlNodePtr
) cur
;
1922 if (tmp
->next
== NULL
)
1929 * Add it at the end to preserve parsing order ...
1932 if (node
->properties
== NULL
) {
1933 node
->properties
= cur
;
1935 xmlAttrPtr prev
= node
->properties
;
1937 while (prev
->next
!= NULL
)
1944 if ((value
!= NULL
) && (node
!= NULL
) &&
1945 (xmlIsID(node
->doc
, node
, cur
) == 1))
1946 xmlAddID(NULL
, node
->doc
, value
, cur
);
1948 if ((__xmlRegisterCallbacks
) && (xmlRegisterNodeDefaultValue
))
1949 xmlRegisterNodeDefaultValue((xmlNodePtr
) cur
);
1953 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_HTML_ENABLED) || \
1954 defined(LIBXML_SCHEMAS_ENABLED)
1957 * @node: the holding node
1958 * @name: the name of the attribute
1959 * @value: the value of the attribute
1961 * Create a new property carried by a node.
1962 * Returns a pointer to the attribute
1965 xmlNewProp(xmlNodePtr node
, const xmlChar
*name
, const xmlChar
*value
) {
1969 xmlGenericError(xmlGenericErrorContext
,
1970 "xmlNewProp : name == NULL\n");
1975 return xmlNewPropInternal(node
, NULL
, name
, value
, 0);
1977 #endif /* LIBXML_TREE_ENABLED */
1981 * @node: the holding node
1982 * @ns: the namespace
1983 * @name: the name of the attribute
1984 * @value: the value of the attribute
1986 * Create a new property tagged with a namespace and carried by a node.
1987 * Returns a pointer to the attribute
1990 xmlNewNsProp(xmlNodePtr node
, xmlNsPtr ns
, const xmlChar
*name
,
1991 const xmlChar
*value
) {
1995 xmlGenericError(xmlGenericErrorContext
,
1996 "xmlNewNsProp : name == NULL\n");
2001 return xmlNewPropInternal(node
, ns
, name
, value
, 0);
2005 * xmlNewNsPropEatName:
2006 * @node: the holding node
2007 * @ns: the namespace
2008 * @name: the name of the attribute
2009 * @value: the value of the attribute
2011 * Create a new property tagged with a namespace and carried by a node.
2012 * Returns a pointer to the attribute
2015 xmlNewNsPropEatName(xmlNodePtr node
, xmlNsPtr ns
, xmlChar
*name
,
2016 const xmlChar
*value
) {
2020 xmlGenericError(xmlGenericErrorContext
,
2021 "xmlNewNsPropEatName : name == NULL\n");
2026 return xmlNewPropInternal(node
, ns
, name
, value
, 1);
2031 * @doc: the document
2032 * @name: the name of the attribute
2033 * @value: the value of the attribute
2035 * Create a new property carried by a document.
2036 * NOTE: @value is supposed to be a piece of XML CDATA, so it allows entity
2037 * references, but XML special chars need to be escaped first by using
2038 * xmlEncodeEntitiesReentrant(). Use xmlNewProp() if you don't need
2041 * Returns a pointer to the attribute
2044 xmlNewDocProp(xmlDocPtr doc
, const xmlChar
*name
, const xmlChar
*value
) {
2049 xmlGenericError(xmlGenericErrorContext
,
2050 "xmlNewDocProp : name == NULL\n");
2056 * Allocate a new property and fill the fields.
2058 cur
= (xmlAttrPtr
) xmlMalloc(sizeof(xmlAttr
));
2060 xmlTreeErrMemory("building attribute");
2063 memset(cur
, 0, sizeof(xmlAttr
));
2064 cur
->type
= XML_ATTRIBUTE_NODE
;
2066 if ((doc
!= NULL
) && (doc
->dict
!= NULL
))
2067 cur
->name
= xmlDictLookup(doc
->dict
, name
, -1);
2069 cur
->name
= xmlStrdup(name
);
2071 if (value
!= NULL
) {
2074 cur
->children
= xmlStringGetNodeList(doc
, value
);
2077 tmp
= cur
->children
;
2078 while (tmp
!= NULL
) {
2079 tmp
->parent
= (xmlNodePtr
) cur
;
2080 if (tmp
->next
== NULL
)
2086 if ((__xmlRegisterCallbacks
) && (xmlRegisterNodeDefaultValue
))
2087 xmlRegisterNodeDefaultValue((xmlNodePtr
)cur
);
2093 * @cur: the first property in the list
2095 * Free a property and all its siblings, all the children are freed too.
2098 xmlFreePropList(xmlAttrPtr cur
) {
2100 if (cur
== NULL
) return;
2101 while (cur
!= NULL
) {
2110 * @cur: an attribute
2112 * Free one attribute, all the content is freed too
2115 xmlFreeProp(xmlAttrPtr cur
) {
2116 xmlDictPtr dict
= NULL
;
2117 if (cur
== NULL
) return;
2119 if (cur
->doc
!= NULL
) dict
= cur
->doc
->dict
;
2121 if ((__xmlRegisterCallbacks
) && (xmlDeregisterNodeDefaultValue
))
2122 xmlDeregisterNodeDefaultValue((xmlNodePtr
)cur
);
2124 /* Check for ID removal -> leading to invalid references ! */
2125 if ((cur
->doc
!= NULL
) && (cur
->atype
== XML_ATTRIBUTE_ID
)) {
2126 xmlRemoveID(cur
->doc
, cur
);
2128 if (cur
->children
!= NULL
) xmlFreeNodeList(cur
->children
);
2129 DICT_FREE(cur
->name
)
2135 * @cur: an attribute
2137 * Unlink and free one attribute, all the content is freed too
2138 * Note this doesn't work for namespace definition attributes
2140 * Returns 0 if success and -1 in case of error.
2143 xmlRemoveProp(xmlAttrPtr cur
) {
2147 xmlGenericError(xmlGenericErrorContext
,
2148 "xmlRemoveProp : cur == NULL\n");
2152 if (cur
->parent
== NULL
) {
2154 xmlGenericError(xmlGenericErrorContext
,
2155 "xmlRemoveProp : cur->parent == NULL\n");
2159 tmp
= cur
->parent
->properties
;
2161 cur
->parent
->properties
= cur
->next
;
2162 if (cur
->next
!= NULL
)
2163 cur
->next
->prev
= NULL
;
2167 while (tmp
!= NULL
) {
2168 if (tmp
->next
== cur
) {
2169 tmp
->next
= cur
->next
;
2170 if (tmp
->next
!= NULL
)
2171 tmp
->next
->prev
= tmp
;
2178 xmlGenericError(xmlGenericErrorContext
,
2179 "xmlRemoveProp : attribute not owned by its node\n");
2186 * @doc: the target document
2187 * @name: the processing instruction name
2188 * @content: the PI content
2190 * Creation of a processing instruction element.
2191 * Returns a pointer to the new node object.
2194 xmlNewDocPI(xmlDocPtr doc
, const xmlChar
*name
, const xmlChar
*content
) {
2199 xmlGenericError(xmlGenericErrorContext
,
2200 "xmlNewPI : name == NULL\n");
2206 * Allocate a new node and fill the fields.
2208 cur
= (xmlNodePtr
) xmlMalloc(sizeof(xmlNode
));
2210 xmlTreeErrMemory("building PI");
2213 memset(cur
, 0, sizeof(xmlNode
));
2214 cur
->type
= XML_PI_NODE
;
2216 if ((doc
!= NULL
) && (doc
->dict
!= NULL
))
2217 cur
->name
= xmlDictLookup(doc
->dict
, name
, -1);
2219 cur
->name
= xmlStrdup(name
);
2220 if (content
!= NULL
) {
2221 cur
->content
= xmlStrdup(content
);
2225 if ((__xmlRegisterCallbacks
) && (xmlRegisterNodeDefaultValue
))
2226 xmlRegisterNodeDefaultValue((xmlNodePtr
)cur
);
2232 * @name: the processing instruction name
2233 * @content: the PI content
2235 * Creation of a processing instruction element.
2237 * Use of this function is DISCOURAGED in favor of xmlNewDocPI.
2239 * Returns a pointer to the new node object.
2242 xmlNewPI(const xmlChar
*name
, const xmlChar
*content
) {
2243 return(xmlNewDocPI(NULL
, name
, content
));
2248 * @ns: namespace if any
2249 * @name: the node name
2251 * Creation of a new node element. @ns is optional (NULL).
2253 * Use of this function is DISCOURAGED in favor of xmlNewDocNode.
2255 * Returns a pointer to the new node object. Uses xmlStrdup() to make
2259 xmlNewNode(xmlNsPtr ns
, const xmlChar
*name
) {
2264 xmlGenericError(xmlGenericErrorContext
,
2265 "xmlNewNode : name == NULL\n");
2271 * Allocate a new node and fill the fields.
2273 cur
= (xmlNodePtr
) xmlMalloc(sizeof(xmlNode
));
2275 xmlTreeErrMemory("building node");
2278 memset(cur
, 0, sizeof(xmlNode
));
2279 cur
->type
= XML_ELEMENT_NODE
;
2281 cur
->name
= xmlStrdup(name
);
2284 if ((__xmlRegisterCallbacks
) && (xmlRegisterNodeDefaultValue
))
2285 xmlRegisterNodeDefaultValue(cur
);
2290 * xmlNewNodeEatName:
2291 * @ns: namespace if any
2292 * @name: the node name
2294 * Creation of a new node element. @ns is optional (NULL).
2296 * Use of this function is DISCOURAGED in favor of xmlNewDocNodeEatName.
2298 * Returns a pointer to the new node object, with pointer @name as
2299 * new node's name. Use xmlNewNode() if a copy of @name string is
2300 * is needed as new node's name.
2303 xmlNewNodeEatName(xmlNsPtr ns
, xmlChar
*name
) {
2308 xmlGenericError(xmlGenericErrorContext
,
2309 "xmlNewNode : name == NULL\n");
2315 * Allocate a new node and fill the fields.
2317 cur
= (xmlNodePtr
) xmlMalloc(sizeof(xmlNode
));
2319 xmlTreeErrMemory("building node");
2320 /* we can't check here that name comes from the doc dictionary */
2323 memset(cur
, 0, sizeof(xmlNode
));
2324 cur
->type
= XML_ELEMENT_NODE
;
2329 if ((__xmlRegisterCallbacks
) && (xmlRegisterNodeDefaultValue
))
2330 xmlRegisterNodeDefaultValue((xmlNodePtr
)cur
);
2336 * @doc: the document
2337 * @ns: namespace if any
2338 * @name: the node name
2339 * @content: the XML text content if any
2341 * Creation of a new node element within a document. @ns and @content
2342 * are optional (NULL).
2343 * NOTE: @content is supposed to be a piece of XML CDATA, so it allow entities
2344 * references, but XML special chars need to be escaped first by using
2345 * xmlEncodeEntitiesReentrant(). Use xmlNewDocRawNode() if you don't
2346 * need entities support.
2348 * Returns a pointer to the new node object.
2351 xmlNewDocNode(xmlDocPtr doc
, xmlNsPtr ns
,
2352 const xmlChar
*name
, const xmlChar
*content
) {
2355 if ((doc
!= NULL
) && (doc
->dict
!= NULL
))
2356 cur
= xmlNewNodeEatName(ns
, (xmlChar
*)
2357 xmlDictLookup(doc
->dict
, name
, -1));
2359 cur
= xmlNewNode(ns
, name
);
2362 if (content
!= NULL
) {
2363 cur
->children
= xmlStringGetNodeList(doc
, content
);
2364 UPDATE_LAST_CHILD_AND_PARENT(cur
)
2372 * xmlNewDocNodeEatName:
2373 * @doc: the document
2374 * @ns: namespace if any
2375 * @name: the node name
2376 * @content: the XML text content if any
2378 * Creation of a new node element within a document. @ns and @content
2379 * are optional (NULL).
2380 * NOTE: @content is supposed to be a piece of XML CDATA, so it allow entities
2381 * references, but XML special chars need to be escaped first by using
2382 * xmlEncodeEntitiesReentrant(). Use xmlNewDocRawNode() if you don't
2383 * need entities support.
2385 * Returns a pointer to the new node object.
2388 xmlNewDocNodeEatName(xmlDocPtr doc
, xmlNsPtr ns
,
2389 xmlChar
*name
, const xmlChar
*content
) {
2392 cur
= xmlNewNodeEatName(ns
, name
);
2395 if (content
!= NULL
) {
2396 cur
->children
= xmlStringGetNodeList(doc
, content
);
2397 UPDATE_LAST_CHILD_AND_PARENT(cur
)
2400 /* if name don't come from the doc dictionary free it here */
2401 if ((name
!= NULL
) &&
2402 ((doc
== NULL
) || (doc
->dict
== NULL
) ||
2403 (!(xmlDictOwns(doc
->dict
, name
)))))
2409 #ifdef LIBXML_TREE_ENABLED
2412 * @doc: the document
2413 * @ns: namespace if any
2414 * @name: the node name
2415 * @content: the text content if any
2417 * Creation of a new node element within a document. @ns and @content
2418 * are optional (NULL).
2420 * Returns a pointer to the new node object.
2423 xmlNewDocRawNode(xmlDocPtr doc
, xmlNsPtr ns
,
2424 const xmlChar
*name
, const xmlChar
*content
) {
2427 cur
= xmlNewDocNode(doc
, ns
, name
, NULL
);
2430 if (content
!= NULL
) {
2431 cur
->children
= xmlNewDocText(doc
, content
);
2432 UPDATE_LAST_CHILD_AND_PARENT(cur
)
2439 * xmlNewDocFragment:
2440 * @doc: the document owning the fragment
2442 * Creation of a new Fragment node.
2443 * Returns a pointer to the new node object.
2446 xmlNewDocFragment(xmlDocPtr doc
) {
2450 * Allocate a new DocumentFragment node and fill the fields.
2452 cur
= (xmlNodePtr
) xmlMalloc(sizeof(xmlNode
));
2454 xmlTreeErrMemory("building fragment");
2457 memset(cur
, 0, sizeof(xmlNode
));
2458 cur
->type
= XML_DOCUMENT_FRAG_NODE
;
2462 if ((__xmlRegisterCallbacks
) && (xmlRegisterNodeDefaultValue
))
2463 xmlRegisterNodeDefaultValue(cur
);
2466 #endif /* LIBXML_TREE_ENABLED */
2470 * @content: the text content
2472 * Creation of a new text node.
2474 * Use of this function is DISCOURAGED in favor of xmlNewDocText.
2476 * Returns a pointer to the new node object.
2479 xmlNewText(const xmlChar
*content
) {
2483 * Allocate a new node and fill the fields.
2485 cur
= (xmlNodePtr
) xmlMalloc(sizeof(xmlNode
));
2487 xmlTreeErrMemory("building text");
2490 memset(cur
, 0, sizeof(xmlNode
));
2491 cur
->type
= XML_TEXT_NODE
;
2493 cur
->name
= xmlStringText
;
2494 if (content
!= NULL
) {
2495 cur
->content
= xmlStrdup(content
);
2498 if ((__xmlRegisterCallbacks
) && (xmlRegisterNodeDefaultValue
))
2499 xmlRegisterNodeDefaultValue(cur
);
2503 #ifdef LIBXML_TREE_ENABLED
2506 * @parent: the parent node
2507 * @ns: a namespace if any
2508 * @name: the name of the child
2509 * @content: the text content of the child if any.
2511 * Creation of a new child element, added at the end of @parent children list.
2512 * @ns and @content parameters are optional (NULL). If @ns is NULL, the newly
2513 * created element inherits the namespace of @parent. If @content is non NULL,
2514 * a child TEXT node will be created containing the string @content.
2515 * NOTE: Use xmlNewChild() if @content will contain entities that need to be
2516 * preserved. Use this function, xmlNewTextChild(), if you need to ensure that
2517 * reserved XML chars that might appear in @content, such as the ampersand,
2518 * greater-than or less-than signs, are automatically replaced by their XML
2519 * escaped entity representations.
2521 * Returns a pointer to the new node object.
2524 xmlNewTextChild(xmlNodePtr parent
, xmlNsPtr ns
,
2525 const xmlChar
*name
, const xmlChar
*content
) {
2526 xmlNodePtr cur
, prev
;
2528 if (parent
== NULL
) {
2530 xmlGenericError(xmlGenericErrorContext
,
2531 "xmlNewTextChild : parent == NULL\n");
2538 xmlGenericError(xmlGenericErrorContext
,
2539 "xmlNewTextChild : name == NULL\n");
2545 * Allocate a new node
2547 if (parent
->type
== XML_ELEMENT_NODE
) {
2549 cur
= xmlNewDocRawNode(parent
->doc
, parent
->ns
, name
, content
);
2551 cur
= xmlNewDocRawNode(parent
->doc
, ns
, name
, content
);
2552 } else if ((parent
->type
== XML_DOCUMENT_NODE
) ||
2553 (parent
->type
== XML_HTML_DOCUMENT_NODE
)) {
2555 cur
= xmlNewDocRawNode((xmlDocPtr
) parent
, NULL
, name
, content
);
2557 cur
= xmlNewDocRawNode((xmlDocPtr
) parent
, ns
, name
, content
);
2558 } else if (parent
->type
== XML_DOCUMENT_FRAG_NODE
) {
2559 cur
= xmlNewDocRawNode( parent
->doc
, ns
, name
, content
);
2563 if (cur
== NULL
) return(NULL
);
2566 * add the new element at the end of the children list.
2568 cur
->type
= XML_ELEMENT_NODE
;
2569 cur
->parent
= parent
;
2570 cur
->doc
= parent
->doc
;
2571 if (parent
->children
== NULL
) {
2572 parent
->children
= cur
;
2575 prev
= parent
->last
;
2583 #endif /* LIBXML_TREE_ENABLED */
2587 * @doc: the document
2588 * @name: the char ref string, starting with # or "&# ... ;"
2590 * Creation of a new character reference node.
2591 * Returns a pointer to the new node object.
2594 xmlNewCharRef(xmlDocPtr doc
, const xmlChar
*name
) {
2601 * Allocate a new node and fill the fields.
2603 cur
= (xmlNodePtr
) xmlMalloc(sizeof(xmlNode
));
2605 xmlTreeErrMemory("building character reference");
2608 memset(cur
, 0, sizeof(xmlNode
));
2609 cur
->type
= XML_ENTITY_REF_NODE
;
2612 if (name
[0] == '&') {
2615 len
= xmlStrlen(name
);
2616 if (name
[len
- 1] == ';')
2617 cur
->name
= xmlStrndup(name
, len
- 1);
2619 cur
->name
= xmlStrndup(name
, len
);
2621 cur
->name
= xmlStrdup(name
);
2623 if ((__xmlRegisterCallbacks
) && (xmlRegisterNodeDefaultValue
))
2624 xmlRegisterNodeDefaultValue(cur
);
2630 * @doc: the document
2631 * @name: the reference name, or the reference string with & and ;
2633 * Creation of a new reference node.
2634 * Returns a pointer to the new node object.
2637 xmlNewReference(const xmlDoc
*doc
, const xmlChar
*name
) {
2645 * Allocate a new node and fill the fields.
2647 cur
= (xmlNodePtr
) xmlMalloc(sizeof(xmlNode
));
2649 xmlTreeErrMemory("building reference");
2652 memset(cur
, 0, sizeof(xmlNode
));
2653 cur
->type
= XML_ENTITY_REF_NODE
;
2655 cur
->doc
= (xmlDoc
*)doc
;
2656 if (name
[0] == '&') {
2659 len
= xmlStrlen(name
);
2660 if (name
[len
- 1] == ';')
2661 cur
->name
= xmlStrndup(name
, len
- 1);
2663 cur
->name
= xmlStrndup(name
, len
);
2665 cur
->name
= xmlStrdup(name
);
2667 ent
= xmlGetDocEntity(doc
, cur
->name
);
2669 cur
->content
= ent
->content
;
2671 * The parent pointer in entity is a DTD pointer and thus is NOT
2672 * updated. Not sure if this is 100% correct.
2675 cur
->children
= (xmlNodePtr
) ent
;
2676 cur
->last
= (xmlNodePtr
) ent
;
2679 if ((__xmlRegisterCallbacks
) && (xmlRegisterNodeDefaultValue
))
2680 xmlRegisterNodeDefaultValue(cur
);
2686 * @doc: the document
2687 * @content: the text content
2689 * Creation of a new text node within a document.
2690 * Returns a pointer to the new node object.
2693 xmlNewDocText(const xmlDoc
*doc
, const xmlChar
*content
) {
2696 cur
= xmlNewText(content
);
2697 if (cur
!= NULL
) cur
->doc
= (xmlDoc
*)doc
;
2703 * @content: the text content
2704 * @len: the text len.
2706 * Use of this function is DISCOURAGED in favor of xmlNewDocTextLen.
2708 * Creation of a new text node with an extra parameter for the content's length
2709 * Returns a pointer to the new node object.
2712 xmlNewTextLen(const xmlChar
*content
, int len
) {
2716 * Allocate a new node and fill the fields.
2718 cur
= (xmlNodePtr
) xmlMalloc(sizeof(xmlNode
));
2720 xmlTreeErrMemory("building text");
2723 memset(cur
, 0, sizeof(xmlNode
));
2724 cur
->type
= XML_TEXT_NODE
;
2726 cur
->name
= xmlStringText
;
2727 if (content
!= NULL
) {
2728 cur
->content
= xmlStrndup(content
, len
);
2731 if ((__xmlRegisterCallbacks
) && (xmlRegisterNodeDefaultValue
))
2732 xmlRegisterNodeDefaultValue(cur
);
2738 * @doc: the document
2739 * @content: the text content
2740 * @len: the text len.
2742 * Creation of a new text node with an extra content length parameter. The
2743 * text node pertain to a given document.
2744 * Returns a pointer to the new node object.
2747 xmlNewDocTextLen(xmlDocPtr doc
, const xmlChar
*content
, int len
) {
2750 cur
= xmlNewTextLen(content
, len
);
2751 if (cur
!= NULL
) cur
->doc
= doc
;
2757 * @content: the comment content
2759 * Use of this function is DISCOURAGED in favor of xmlNewDocComment.
2761 * Creation of a new node containing a comment.
2762 * Returns a pointer to the new node object.
2765 xmlNewComment(const xmlChar
*content
) {
2769 * Allocate a new node and fill the fields.
2771 cur
= (xmlNodePtr
) xmlMalloc(sizeof(xmlNode
));
2773 xmlTreeErrMemory("building comment");
2776 memset(cur
, 0, sizeof(xmlNode
));
2777 cur
->type
= XML_COMMENT_NODE
;
2779 cur
->name
= xmlStringComment
;
2780 if (content
!= NULL
) {
2781 cur
->content
= xmlStrdup(content
);
2784 if ((__xmlRegisterCallbacks
) && (xmlRegisterNodeDefaultValue
))
2785 xmlRegisterNodeDefaultValue(cur
);
2791 * @doc: the document
2792 * @content: the CDATA block content content
2793 * @len: the length of the block
2795 * Creation of a new node containing a CDATA block.
2796 * Returns a pointer to the new node object.
2799 xmlNewCDataBlock(xmlDocPtr doc
, const xmlChar
*content
, int len
) {
2803 * Allocate a new node and fill the fields.
2805 cur
= (xmlNodePtr
) xmlMalloc(sizeof(xmlNode
));
2807 xmlTreeErrMemory("building CDATA");
2810 memset(cur
, 0, sizeof(xmlNode
));
2811 cur
->type
= XML_CDATA_SECTION_NODE
;
2814 if (content
!= NULL
) {
2815 cur
->content
= xmlStrndup(content
, len
);
2818 if ((__xmlRegisterCallbacks
) && (xmlRegisterNodeDefaultValue
))
2819 xmlRegisterNodeDefaultValue(cur
);
2825 * @doc: the document
2826 * @content: the comment content
2828 * Creation of a new node containing a comment within a document.
2829 * Returns a pointer to the new node object.
2832 xmlNewDocComment(xmlDocPtr doc
, const xmlChar
*content
) {
2835 cur
= xmlNewComment(content
);
2836 if (cur
!= NULL
) cur
->doc
= doc
;
2840 static const xmlChar
*_copyStringForNewDictIfNeeded(xmlDictPtr oldDict
, xmlDictPtr newDict
, const xmlChar
*oldValue
) {
2841 const xmlChar
*newValue
= oldValue
;
2843 int oldDictOwnsOldValue
= oldDict
&& (xmlDictOwns(oldDict
, oldValue
) == 1);
2844 if (oldDictOwnsOldValue
) {
2846 newValue
= xmlDictLookup(newDict
, oldValue
, -1);
2848 newValue
= xmlStrdup(oldValue
);
2856 * @tree: the top element
2857 * @doc: the document
2859 * update all nodes under the tree to point to the right document
2862 xmlSetTreeDoc(xmlNodePtr tree
, xmlDocPtr doc
) {
2865 if ((tree
== NULL
) || (tree
->type
== XML_NAMESPACE_DECL
))
2867 if (tree
->doc
!= doc
) {
2868 xmlDictPtr oldTreeDict
= tree
->doc
? tree
->doc
->dict
: NULL
;
2869 xmlDictPtr newDict
= doc
? doc
->dict
: NULL
;
2871 if(tree
->type
== XML_ELEMENT_NODE
) {
2872 prop
= tree
->properties
;
2873 while (prop
!= NULL
) {
2874 if (prop
->atype
== XML_ATTRIBUTE_ID
) {
2875 xmlRemoveID(tree
->doc
, prop
);
2878 if (prop
->doc
!= doc
) {
2879 xmlDictPtr oldPropDict
= prop
->doc
? prop
->doc
->dict
: NULL
;
2880 prop
->name
= _copyStringForNewDictIfNeeded(oldPropDict
, newDict
, prop
->name
);
2883 xmlSetListDoc(prop
->children
, doc
);
2886 * TODO: ID attributes should be also added to the new
2887 * document, but this breaks things like xmlReplaceNode.
2888 * The underlying problem is that xmlRemoveID is only called
2889 * if a node is destroyed, not if it's unlinked.
2892 if (xmlIsID(doc
, tree
, prop
)) {
2893 xmlChar
*idVal
= xmlNodeListGetString(doc
, prop
->children
,
2895 xmlAddID(NULL
, doc
, idVal
, prop
);
2902 if (tree
->type
== XML_ENTITY_REF_NODE
) {
2904 * Clear 'children' which points to the entity declaration
2905 * from the original document.
2907 tree
->children
= NULL
;
2908 } else if (tree
->children
!= NULL
) {
2909 xmlSetListDoc(tree
->children
, doc
);
2912 tree
->name
= _copyStringForNewDictIfNeeded(oldTreeDict
, newDict
, tree
->name
);
2913 tree
->content
= (xmlChar
*)_copyStringForNewDictIfNeeded(oldTreeDict
, NULL
, tree
->content
);
2914 /* FIXME: tree->ns should be updated as in xmlStaticCopyNode(). */
2921 * @list: the first element
2922 * @doc: the document
2924 * update all nodes in the list to point to the right document
2927 xmlSetListDoc(xmlNodePtr list
, xmlDocPtr doc
) {
2930 if ((list
== NULL
) || (list
->type
== XML_NAMESPACE_DECL
))
2933 while (cur
!= NULL
) {
2934 if (cur
->doc
!= doc
)
2935 xmlSetTreeDoc(cur
, doc
);
2940 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
2943 * @parent: the parent node
2944 * @ns: a namespace if any
2945 * @name: the name of the child
2946 * @content: the XML content of the child if any.
2948 * Creation of a new child element, added at the end of @parent children list.
2949 * @ns and @content parameters are optional (NULL). If @ns is NULL, the newly
2950 * created element inherits the namespace of @parent. If @content is non NULL,
2951 * a child list containing the TEXTs and ENTITY_REFs node will be created.
2952 * NOTE: @content is supposed to be a piece of XML CDATA, so it allows entity
2953 * references. XML special chars must be escaped first by using
2954 * xmlEncodeEntitiesReentrant(), or xmlNewTextChild() should be used.
2956 * Returns a pointer to the new node object.
2959 xmlNewChild(xmlNodePtr parent
, xmlNsPtr ns
,
2960 const xmlChar
*name
, const xmlChar
*content
) {
2961 xmlNodePtr cur
, prev
;
2963 if (parent
== NULL
) {
2965 xmlGenericError(xmlGenericErrorContext
,
2966 "xmlNewChild : parent == NULL\n");
2973 xmlGenericError(xmlGenericErrorContext
,
2974 "xmlNewChild : name == NULL\n");
2980 * Allocate a new node
2982 if (parent
->type
== XML_ELEMENT_NODE
) {
2984 cur
= xmlNewDocNode(parent
->doc
, parent
->ns
, name
, content
);
2986 cur
= xmlNewDocNode(parent
->doc
, ns
, name
, content
);
2987 } else if ((parent
->type
== XML_DOCUMENT_NODE
) ||
2988 (parent
->type
== XML_HTML_DOCUMENT_NODE
)) {
2990 cur
= xmlNewDocNode((xmlDocPtr
) parent
, NULL
, name
, content
);
2992 cur
= xmlNewDocNode((xmlDocPtr
) parent
, ns
, name
, content
);
2993 } else if (parent
->type
== XML_DOCUMENT_FRAG_NODE
) {
2994 cur
= xmlNewDocNode( parent
->doc
, ns
, name
, content
);
2998 if (cur
== NULL
) return(NULL
);
3001 * add the new element at the end of the children list.
3003 cur
->type
= XML_ELEMENT_NODE
;
3004 cur
->parent
= parent
;
3005 cur
->doc
= parent
->doc
;
3006 if (parent
->children
== NULL
) {
3007 parent
->children
= cur
;
3010 prev
= parent
->last
;
3018 #endif /* LIBXML_TREE_ENABLED */
3021 * xmlAddPropSibling:
3022 * @prev: the attribute to which @prop is added after
3023 * @cur: the base attribute passed to calling function
3024 * @prop: the new attribute
3026 * Add a new attribute after @prev using @cur as base attribute.
3027 * When inserting before @cur, @prev is passed as @cur->prev.
3028 * When inserting after @cur, @prev is passed as @cur.
3029 * If an existing attribute is found it is destroyed prior to adding @prop.
3031 * See the note regarding namespaces in xmlAddChild.
3033 * Returns the attribute being inserted or NULL in case of error.
3036 xmlAddPropSibling(xmlNodePtr prev
, xmlNodePtr cur
, xmlNodePtr prop
) {
3039 if ((cur
== NULL
) || (cur
->type
!= XML_ATTRIBUTE_NODE
) ||
3040 (prop
== NULL
) || (prop
->type
!= XML_ATTRIBUTE_NODE
) ||
3041 ((prev
!= NULL
) && (prev
->type
!= XML_ATTRIBUTE_NODE
)))
3044 /* check if an attribute with the same name exists */
3045 if (prop
->ns
== NULL
)
3046 attr
= xmlHasNsProp(cur
->parent
, prop
->name
, NULL
);
3048 attr
= xmlHasNsProp(cur
->parent
, prop
->name
, prop
->ns
->href
);
3050 if (prop
->doc
!= cur
->doc
) {
3051 xmlSetTreeDoc(prop
, cur
->doc
);
3053 prop
->parent
= cur
->parent
;
3056 prop
->next
= prev
->next
;
3059 prop
->next
->prev
= prop
;
3064 if (prop
->prev
== NULL
&& prop
->parent
!= NULL
)
3065 prop
->parent
->properties
= (xmlAttrPtr
) prop
;
3066 if ((attr
!= NULL
) && (attr
->type
!= XML_ATTRIBUTE_DECL
)) {
3067 /* different instance, destroy it (attributes must be unique) */
3068 xmlRemoveProp((xmlAttrPtr
) attr
);
3074 * xmlAddNextSibling:
3075 * @cur: the child node
3076 * @elem: the new node
3078 * Add a new node @elem as the next sibling of @cur
3079 * If the new node was already inserted in a document it is
3080 * first unlinked from its existing context.
3081 * As a result of text merging @elem may be freed.
3082 * If the new node is ATTRIBUTE, it is added into properties instead of children.
3083 * If there is an attribute with equal name, it is first destroyed.
3085 * See the note regarding namespaces in xmlAddChild.
3087 * Returns the new node or NULL in case of error.
3090 xmlAddNextSibling(xmlNodePtr cur
, xmlNodePtr elem
) {
3091 if ((cur
== NULL
) || (cur
->type
== XML_NAMESPACE_DECL
)) {
3093 xmlGenericError(xmlGenericErrorContext
,
3094 "xmlAddNextSibling : cur == NULL\n");
3098 if ((elem
== NULL
) || (elem
->type
== XML_NAMESPACE_DECL
)) {
3100 xmlGenericError(xmlGenericErrorContext
,
3101 "xmlAddNextSibling : elem == NULL\n");
3108 xmlGenericError(xmlGenericErrorContext
,
3109 "xmlAddNextSibling : cur == elem\n");
3114 xmlUnlinkNode(elem
);
3116 if (elem
->type
== XML_TEXT_NODE
) {
3117 if (cur
->type
== XML_TEXT_NODE
) {
3118 xmlNodeAddContent(cur
, elem
->content
);
3122 if ((cur
->next
!= NULL
) && (cur
->next
->type
== XML_TEXT_NODE
) &&
3123 (cur
->name
== cur
->next
->name
)) {
3126 tmp
= xmlStrdup(elem
->content
);
3127 tmp
= xmlStrcat(tmp
, cur
->next
->content
);
3128 xmlNodeSetContent(cur
->next
, tmp
);
3133 } else if (elem
->type
== XML_ATTRIBUTE_NODE
) {
3134 return xmlAddPropSibling(cur
, cur
, elem
);
3137 if (elem
->doc
!= cur
->doc
) {
3138 xmlSetTreeDoc(elem
, cur
->doc
);
3140 elem
->parent
= cur
->parent
;
3142 elem
->next
= cur
->next
;
3144 if (elem
->next
!= NULL
)
3145 elem
->next
->prev
= elem
;
3146 if ((elem
->parent
!= NULL
) && (elem
->parent
->last
== cur
))
3147 elem
->parent
->last
= elem
;
3151 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_HTML_ENABLED) || \
3152 defined(LIBXML_SCHEMAS_ENABLED) || defined(LIBXML_XINCLUDE_ENABLED)
3154 * xmlAddPrevSibling:
3155 * @cur: the child node
3156 * @elem: the new node
3158 * Add a new node @elem as the previous sibling of @cur
3159 * merging adjacent TEXT nodes (@elem may be freed)
3160 * If the new node was already inserted in a document it is
3161 * first unlinked from its existing context.
3162 * If the new node is ATTRIBUTE, it is added into properties instead of children.
3163 * If there is an attribute with equal name, it is first destroyed.
3165 * See the note regarding namespaces in xmlAddChild.
3167 * Returns the new node or NULL in case of error.
3170 xmlAddPrevSibling(xmlNodePtr cur
, xmlNodePtr elem
) {
3171 if ((cur
== NULL
) || (cur
->type
== XML_NAMESPACE_DECL
)) {
3173 xmlGenericError(xmlGenericErrorContext
,
3174 "xmlAddPrevSibling : cur == NULL\n");
3178 if ((elem
== NULL
) || (elem
->type
== XML_NAMESPACE_DECL
)) {
3180 xmlGenericError(xmlGenericErrorContext
,
3181 "xmlAddPrevSibling : elem == NULL\n");
3188 xmlGenericError(xmlGenericErrorContext
,
3189 "xmlAddPrevSibling : cur == elem\n");
3194 xmlUnlinkNode(elem
);
3196 if (elem
->type
== XML_TEXT_NODE
) {
3197 if (cur
->type
== XML_TEXT_NODE
) {
3200 tmp
= xmlStrdup(elem
->content
);
3201 tmp
= xmlStrcat(tmp
, cur
->content
);
3202 xmlNodeSetContent(cur
, tmp
);
3207 if ((cur
->prev
!= NULL
) && (cur
->prev
->type
== XML_TEXT_NODE
) &&
3208 (cur
->name
== cur
->prev
->name
)) {
3209 xmlNodeAddContent(cur
->prev
, elem
->content
);
3213 } else if (elem
->type
== XML_ATTRIBUTE_NODE
) {
3214 return xmlAddPropSibling(cur
->prev
, cur
, elem
);
3217 if (elem
->doc
!= cur
->doc
) {
3218 xmlSetTreeDoc(elem
, cur
->doc
);
3220 elem
->parent
= cur
->parent
;
3222 elem
->prev
= cur
->prev
;
3224 if (elem
->prev
!= NULL
)
3225 elem
->prev
->next
= elem
;
3226 if ((elem
->parent
!= NULL
) && (elem
->parent
->children
== cur
)) {
3227 elem
->parent
->children
= elem
;
3231 #endif /* LIBXML_TREE_ENABLED */
3235 * @cur: the child node
3236 * @elem: the new node
3238 * Add a new element @elem to the list of siblings of @cur
3239 * merging adjacent TEXT nodes (@elem may be freed)
3240 * If the new element was already inserted in a document it is
3241 * first unlinked from its existing context.
3243 * See the note regarding namespaces in xmlAddChild.
3245 * Returns the new element or NULL in case of error.
3248 xmlAddSibling(xmlNodePtr cur
, xmlNodePtr elem
) {
3251 if ((cur
== NULL
) || (cur
->type
== XML_NAMESPACE_DECL
)) {
3253 xmlGenericError(xmlGenericErrorContext
,
3254 "xmlAddSibling : cur == NULL\n");
3259 if ((elem
== NULL
) || (elem
->type
== XML_NAMESPACE_DECL
)) {
3261 xmlGenericError(xmlGenericErrorContext
,
3262 "xmlAddSibling : elem == NULL\n");
3269 xmlGenericError(xmlGenericErrorContext
,
3270 "xmlAddSibling : cur == elem\n");
3276 * Constant time is we can rely on the ->parent->last to find
3279 if ((cur
->type
!= XML_ATTRIBUTE_NODE
) && (cur
->parent
!= NULL
) &&
3280 (cur
->parent
->children
!= NULL
) &&
3281 (cur
->parent
->last
!= NULL
) &&
3282 (cur
->parent
->last
->next
== NULL
)) {
3283 cur
= cur
->parent
->last
;
3285 while (cur
->next
!= NULL
) cur
= cur
->next
;
3288 xmlUnlinkNode(elem
);
3290 if ((cur
->type
== XML_TEXT_NODE
) && (elem
->type
== XML_TEXT_NODE
) &&
3291 (cur
->name
== elem
->name
)) {
3292 xmlNodeAddContent(cur
, elem
->content
);
3295 } else if (elem
->type
== XML_ATTRIBUTE_NODE
) {
3296 return xmlAddPropSibling(cur
, cur
, elem
);
3299 if (elem
->doc
!= cur
->doc
) {
3300 xmlSetTreeDoc(elem
, cur
->doc
);
3302 parent
= cur
->parent
;
3305 elem
->parent
= parent
;
3308 parent
->last
= elem
;
3315 * @parent: the parent node
3316 * @cur: the first node in the list
3318 * Add a list of node at the end of the child list of the parent
3319 * merging adjacent TEXT nodes (@cur may be freed)
3321 * See the note regarding namespaces in xmlAddChild.
3323 * Returns the last child or NULL in case of error.
3326 xmlAddChildList(xmlNodePtr parent
, xmlNodePtr cur
) {
3329 if ((parent
== NULL
) || (parent
->type
== XML_NAMESPACE_DECL
)) {
3331 xmlGenericError(xmlGenericErrorContext
,
3332 "xmlAddChildList : parent == NULL\n");
3337 if ((cur
== NULL
) || (cur
->type
== XML_NAMESPACE_DECL
)) {
3339 xmlGenericError(xmlGenericErrorContext
,
3340 "xmlAddChildList : child == NULL\n");
3345 if ((cur
->doc
!= NULL
) && (parent
->doc
!= NULL
) &&
3346 (cur
->doc
!= parent
->doc
)) {
3348 xmlGenericError(xmlGenericErrorContext
,
3349 "Elements moved to a different document\n");
3354 * add the first element at the end of the children list.
3357 if (parent
->children
== NULL
) {
3358 parent
->children
= cur
;
3361 * If cur and parent->last both are TEXT nodes, then merge them.
3363 if ((cur
->type
== XML_TEXT_NODE
) &&
3364 (parent
->last
->type
== XML_TEXT_NODE
) &&
3365 (cur
->name
== parent
->last
->name
)) {
3366 xmlNodeAddContent(parent
->last
, cur
->content
);
3368 * if it's the only child, nothing more to be done.
3370 if (cur
->next
== NULL
) {
3372 return(parent
->last
);
3378 prev
= parent
->last
;
3382 while (cur
->next
!= NULL
) {
3383 cur
->parent
= parent
;
3384 if (cur
->doc
!= parent
->doc
) {
3385 xmlSetTreeDoc(cur
, parent
->doc
);
3389 cur
->parent
= parent
;
3390 /* the parent may not be linked to a doc ! */
3391 if (cur
->doc
!= parent
->doc
) {
3392 xmlSetTreeDoc(cur
, parent
->doc
);
3401 * @parent: the parent node
3402 * @cur: the child node
3404 * Add a new node to @parent, at the end of the child (or property) list
3405 * merging adjacent TEXT nodes (in which case @cur is freed)
3406 * If the new node is ATTRIBUTE, it is added into properties instead of children.
3407 * If there is an attribute with equal name, it is first destroyed.
3409 * All tree manipulation functions can safely move nodes within a document.
3410 * But when moving nodes from one document to another, references to
3411 * namespaces in element or attribute nodes are NOT fixed. In this case,
3412 * you MUST call xmlReconciliateNs after the move operation to avoid
3415 * Returns the child or NULL in case of error.
3418 xmlAddChild(xmlNodePtr parent
, xmlNodePtr cur
) {
3421 if ((parent
== NULL
) || (parent
->type
== XML_NAMESPACE_DECL
)) {
3423 xmlGenericError(xmlGenericErrorContext
,
3424 "xmlAddChild : parent == NULL\n");
3429 if ((cur
== NULL
) || (cur
->type
== XML_NAMESPACE_DECL
)) {
3431 xmlGenericError(xmlGenericErrorContext
,
3432 "xmlAddChild : child == NULL\n");
3437 if (parent
== cur
) {
3439 xmlGenericError(xmlGenericErrorContext
,
3440 "xmlAddChild : parent == cur\n");
3445 * If cur is a TEXT node, merge its content with adjacent TEXT nodes
3446 * cur is then freed.
3448 if (cur
->type
== XML_TEXT_NODE
) {
3449 if ((parent
->type
== XML_TEXT_NODE
) &&
3450 (parent
->content
!= NULL
) &&
3451 (parent
->name
== cur
->name
)) {
3452 xmlNodeAddContent(parent
, cur
->content
);
3456 if ((parent
->last
!= NULL
) && (parent
->last
->type
== XML_TEXT_NODE
) &&
3457 (parent
->last
->name
== cur
->name
) &&
3458 (parent
->last
!= cur
)) {
3459 xmlNodeAddContent(parent
->last
, cur
->content
);
3461 return(parent
->last
);
3466 * add the new element at the end of the children list.
3469 cur
->parent
= parent
;
3470 if (cur
->doc
!= parent
->doc
) {
3471 xmlSetTreeDoc(cur
, parent
->doc
);
3473 /* this check prevents a loop on tree-traversions if a developer
3474 * tries to add a node to its parent multiple times
3482 if ((parent
->type
== XML_TEXT_NODE
) &&
3483 (parent
->content
!= NULL
) &&
3485 xmlNodeAddContent(parent
, cur
->content
);
3489 if (cur
->type
== XML_ATTRIBUTE_NODE
) {
3490 if (parent
->type
!= XML_ELEMENT_NODE
)
3492 if (parent
->properties
!= NULL
) {
3493 /* check if an attribute with the same name exists */
3494 xmlAttrPtr lastattr
;
3496 if (cur
->ns
== NULL
)
3497 lastattr
= xmlHasNsProp(parent
, cur
->name
, NULL
);
3499 lastattr
= xmlHasNsProp(parent
, cur
->name
, cur
->ns
->href
);
3500 if ((lastattr
!= NULL
) && (lastattr
!= (xmlAttrPtr
) cur
) && (lastattr
->type
!= XML_ATTRIBUTE_DECL
)) {
3501 /* different instance, destroy it (attributes must be unique) */
3502 xmlUnlinkNode((xmlNodePtr
) lastattr
);
3503 xmlFreeProp(lastattr
);
3505 if (lastattr
== (xmlAttrPtr
) cur
)
3509 if (parent
->properties
== NULL
) {
3510 parent
->properties
= (xmlAttrPtr
) cur
;
3513 xmlAttrPtr lastattr
= parent
->properties
;
3514 while (lastattr
->next
!= NULL
) {
3515 lastattr
= lastattr
->next
;
3517 lastattr
->next
= (xmlAttrPtr
) cur
;
3518 ((xmlAttrPtr
) cur
)->prev
= lastattr
;
3521 if (parent
->children
== NULL
) {
3522 parent
->children
= cur
;
3525 prev
= parent
->last
;
3536 * @parent: the parent node
3538 * Search the last child of a node.
3539 * Returns the last child or NULL if none.
3542 xmlGetLastChild(const xmlNode
*parent
) {
3543 if ((parent
== NULL
) || (parent
->type
== XML_NAMESPACE_DECL
)) {
3545 xmlGenericError(xmlGenericErrorContext
,
3546 "xmlGetLastChild : parent == NULL\n");
3550 return(parent
->last
);
3553 #ifdef LIBXML_TREE_ENABLED
3555 * 5 interfaces from DOM ElementTraversal
3559 * xmlChildElementCount:
3560 * @parent: the parent node
3562 * Finds the current number of child nodes of that element which are
3564 * Note the handling of entities references is different than in
3565 * the W3C DOM element traversal spec since we don't have back reference
3566 * from entities content to entities references.
3568 * Returns the count of element child or 0 if not available
3571 xmlChildElementCount(xmlNodePtr parent
) {
3572 unsigned long ret
= 0;
3573 xmlNodePtr cur
= NULL
;
3577 switch (parent
->type
) {
3578 case XML_ELEMENT_NODE
:
3579 case XML_ENTITY_NODE
:
3580 case XML_DOCUMENT_NODE
:
3581 case XML_DOCUMENT_FRAG_NODE
:
3582 case XML_HTML_DOCUMENT_NODE
:
3583 cur
= parent
->children
;
3588 while (cur
!= NULL
) {
3589 if (cur
->type
== XML_ELEMENT_NODE
)
3597 * xmlFirstElementChild:
3598 * @parent: the parent node
3600 * Finds the first child node of that element which is a Element node
3601 * Note the handling of entities references is different than in
3602 * the W3C DOM element traversal spec since we don't have back reference
3603 * from entities content to entities references.
3605 * Returns the first element child or NULL if not available
3608 xmlFirstElementChild(xmlNodePtr parent
) {
3609 xmlNodePtr cur
= NULL
;
3613 switch (parent
->type
) {
3614 case XML_ELEMENT_NODE
:
3615 case XML_ENTITY_NODE
:
3616 case XML_DOCUMENT_NODE
:
3617 case XML_DOCUMENT_FRAG_NODE
:
3618 case XML_HTML_DOCUMENT_NODE
:
3619 cur
= parent
->children
;
3624 while (cur
!= NULL
) {
3625 if (cur
->type
== XML_ELEMENT_NODE
)
3633 * xmlLastElementChild:
3634 * @parent: the parent node
3636 * Finds the last child node of that element which is a Element node
3637 * Note the handling of entities references is different than in
3638 * the W3C DOM element traversal spec since we don't have back reference
3639 * from entities content to entities references.
3641 * Returns the last element child or NULL if not available
3644 xmlLastElementChild(xmlNodePtr parent
) {
3645 xmlNodePtr cur
= NULL
;
3649 switch (parent
->type
) {
3650 case XML_ELEMENT_NODE
:
3651 case XML_ENTITY_NODE
:
3652 case XML_DOCUMENT_NODE
:
3653 case XML_DOCUMENT_FRAG_NODE
:
3654 case XML_HTML_DOCUMENT_NODE
:
3660 while (cur
!= NULL
) {
3661 if (cur
->type
== XML_ELEMENT_NODE
)
3669 * xmlPreviousElementSibling:
3670 * @node: the current node
3672 * Finds the first closest previous sibling of the node which is an
3674 * Note the handling of entities references is different than in
3675 * the W3C DOM element traversal spec since we don't have back reference
3676 * from entities content to entities references.
3678 * Returns the previous element sibling or NULL if not available
3681 xmlPreviousElementSibling(xmlNodePtr node
) {
3684 switch (node
->type
) {
3685 case XML_ELEMENT_NODE
:
3687 case XML_CDATA_SECTION_NODE
:
3688 case XML_ENTITY_REF_NODE
:
3689 case XML_ENTITY_NODE
:
3691 case XML_COMMENT_NODE
:
3692 case XML_XINCLUDE_START
:
3693 case XML_XINCLUDE_END
:
3699 while (node
!= NULL
) {
3700 if (node
->type
== XML_ELEMENT_NODE
)
3708 * xmlNextElementSibling:
3709 * @node: the current node
3711 * Finds the first closest next sibling of the node which is an
3713 * Note the handling of entities references is different than in
3714 * the W3C DOM element traversal spec since we don't have back reference
3715 * from entities content to entities references.
3717 * Returns the next element sibling or NULL if not available
3720 xmlNextElementSibling(xmlNodePtr node
) {
3723 switch (node
->type
) {
3724 case XML_ELEMENT_NODE
:
3726 case XML_CDATA_SECTION_NODE
:
3727 case XML_ENTITY_REF_NODE
:
3728 case XML_ENTITY_NODE
:
3730 case XML_COMMENT_NODE
:
3732 case XML_XINCLUDE_START
:
3733 case XML_XINCLUDE_END
:
3739 while (node
!= NULL
) {
3740 if (node
->type
== XML_ELEMENT_NODE
)
3747 #endif /* LIBXML_TREE_ENABLED */
3751 * @cur: the first node in the list
3753 * Free a node and all its siblings, this is a recursive behaviour, all
3754 * the children are freed too.
3757 xmlFreeNodeList(xmlNodePtr cur
) {
3760 xmlDictPtr dict
= NULL
;
3763 if (cur
== NULL
) return;
3764 if (cur
->type
== XML_NAMESPACE_DECL
) {
3765 xmlFreeNsList((xmlNsPtr
) cur
);
3768 if (cur
->doc
!= NULL
) dict
= cur
->doc
->dict
;
3770 while ((cur
->children
!= NULL
) &&
3771 (cur
->type
!= XML_DOCUMENT_NODE
) &&
3772 (cur
->type
!= XML_HTML_DOCUMENT_NODE
) &&
3773 (cur
->type
!= XML_DTD_NODE
) &&
3774 (cur
->type
!= XML_ENTITY_REF_NODE
)) {
3775 cur
= cur
->children
;
3780 parent
= cur
->parent
;
3781 if ((cur
->type
== XML_DOCUMENT_NODE
) ||
3782 (cur
->type
== XML_HTML_DOCUMENT_NODE
)) {
3783 xmlFreeDoc((xmlDocPtr
) cur
);
3784 } else if (cur
->type
!= XML_DTD_NODE
) {
3786 if ((__xmlRegisterCallbacks
) && (xmlDeregisterNodeDefaultValue
))
3787 xmlDeregisterNodeDefaultValue(cur
);
3789 if (((cur
->type
== XML_ELEMENT_NODE
) ||
3790 (cur
->type
== XML_XINCLUDE_START
) ||
3791 (cur
->type
== XML_XINCLUDE_END
)) &&
3792 (cur
->properties
!= NULL
))
3793 xmlFreePropList(cur
->properties
);
3794 if ((cur
->type
!= XML_ELEMENT_NODE
) &&
3795 (cur
->type
!= XML_XINCLUDE_START
) &&
3796 (cur
->type
!= XML_XINCLUDE_END
) &&
3797 (cur
->type
!= XML_ENTITY_REF_NODE
) &&
3798 (cur
->content
!= (xmlChar
*) &(cur
->properties
))) {
3799 DICT_FREE(cur
->content
)
3801 if (((cur
->type
== XML_ELEMENT_NODE
) ||
3802 (cur
->type
== XML_XINCLUDE_START
) ||
3803 (cur
->type
== XML_XINCLUDE_END
)) &&
3804 (cur
->nsDef
!= NULL
))
3805 xmlFreeNsList(cur
->nsDef
);
3808 * When a node is a text node or a comment, it uses a global static
3809 * variable for the name of the node.
3810 * Otherwise the node name might come from the document's
3813 if ((cur
->name
!= NULL
) &&
3814 (cur
->type
!= XML_TEXT_NODE
) &&
3815 (cur
->type
!= XML_COMMENT_NODE
))
3816 DICT_FREE(cur
->name
)
3823 if ((depth
== 0) || (parent
== NULL
))
3827 cur
->children
= NULL
;
3836 * Free a node, this is a recursive behaviour, all the children are freed too.
3837 * This doesn't unlink the child from the list, use xmlUnlinkNode() first.
3840 xmlFreeNode(xmlNodePtr cur
) {
3841 xmlDictPtr dict
= NULL
;
3843 if (cur
== NULL
) return;
3845 /* use xmlFreeDtd for DTD nodes */
3846 if (cur
->type
== XML_DTD_NODE
) {
3847 xmlFreeDtd((xmlDtdPtr
) cur
);
3850 if (cur
->type
== XML_NAMESPACE_DECL
) {
3851 xmlFreeNs((xmlNsPtr
) cur
);
3854 if (cur
->type
== XML_ATTRIBUTE_NODE
) {
3855 xmlFreeProp((xmlAttrPtr
) cur
);
3859 if ((__xmlRegisterCallbacks
) && (xmlDeregisterNodeDefaultValue
))
3860 xmlDeregisterNodeDefaultValue(cur
);
3862 if (cur
->doc
!= NULL
) dict
= cur
->doc
->dict
;
3864 if (cur
->type
== XML_ENTITY_DECL
) {
3865 xmlEntityPtr ent
= (xmlEntityPtr
) cur
;
3866 DICT_FREE(ent
->SystemID
);
3867 DICT_FREE(ent
->ExternalID
);
3869 if ((cur
->children
!= NULL
) &&
3870 (cur
->type
!= XML_ENTITY_REF_NODE
))
3871 xmlFreeNodeList(cur
->children
);
3873 if ((cur
->type
== XML_ELEMENT_NODE
) ||
3874 (cur
->type
== XML_XINCLUDE_START
) ||
3875 (cur
->type
== XML_XINCLUDE_END
)) {
3876 if (cur
->properties
!= NULL
)
3877 xmlFreePropList(cur
->properties
);
3878 if (cur
->nsDef
!= NULL
)
3879 xmlFreeNsList(cur
->nsDef
);
3880 } else if ((cur
->content
!= NULL
) &&
3881 (cur
->type
!= XML_ENTITY_REF_NODE
) &&
3882 (cur
->content
!= (xmlChar
*) &(cur
->properties
))) {
3883 DICT_FREE(cur
->content
)
3887 * When a node is a text node or a comment, it uses a global static
3888 * variable for the name of the node.
3889 * Otherwise the node name might come from the document's dictionary
3891 if ((cur
->name
!= NULL
) &&
3892 (cur
->type
!= XML_TEXT_NODE
) &&
3893 (cur
->type
!= XML_COMMENT_NODE
))
3894 DICT_FREE(cur
->name
)
3903 * Unlink a node from it's current context, the node is not freed
3904 * If one need to free the node, use xmlFreeNode() routine after the
3905 * unlink to discard it.
3906 * Note that namespace nodes can't be unlinked as they do not have
3907 * pointer to their parent.
3910 xmlUnlinkNode(xmlNodePtr cur
) {
3913 xmlGenericError(xmlGenericErrorContext
,
3914 "xmlUnlinkNode : node == NULL\n");
3918 if (cur
->type
== XML_NAMESPACE_DECL
)
3920 if (cur
->type
== XML_DTD_NODE
) {
3924 if (doc
->intSubset
== (xmlDtdPtr
) cur
)
3925 doc
->intSubset
= NULL
;
3926 if (doc
->extSubset
== (xmlDtdPtr
) cur
)
3927 doc
->extSubset
= NULL
;
3930 if (cur
->type
== XML_ENTITY_DECL
) {
3934 if (doc
->intSubset
!= NULL
) {
3935 if (xmlHashLookup(doc
->intSubset
->entities
, cur
->name
) == cur
)
3936 xmlHashRemoveEntry(doc
->intSubset
->entities
, cur
->name
,
3938 if (xmlHashLookup(doc
->intSubset
->pentities
, cur
->name
) == cur
)
3939 xmlHashRemoveEntry(doc
->intSubset
->pentities
, cur
->name
,
3942 if (doc
->extSubset
!= NULL
) {
3943 if (xmlHashLookup(doc
->extSubset
->entities
, cur
->name
) == cur
)
3944 xmlHashRemoveEntry(doc
->extSubset
->entities
, cur
->name
,
3946 if (xmlHashLookup(doc
->extSubset
->pentities
, cur
->name
) == cur
)
3947 xmlHashRemoveEntry(doc
->extSubset
->pentities
, cur
->name
,
3952 if (cur
->parent
!= NULL
) {
3954 parent
= cur
->parent
;
3955 if (cur
->type
== XML_ATTRIBUTE_NODE
) {
3956 if (parent
->properties
== (xmlAttrPtr
) cur
)
3957 parent
->properties
= ((xmlAttrPtr
) cur
)->next
;
3959 if (parent
->children
== cur
)
3960 parent
->children
= cur
->next
;
3961 if (parent
->last
== cur
)
3962 parent
->last
= cur
->prev
;
3966 if (cur
->next
!= NULL
)
3967 cur
->next
->prev
= cur
->prev
;
3968 if (cur
->prev
!= NULL
)
3969 cur
->prev
->next
= cur
->next
;
3970 cur
->next
= cur
->prev
= NULL
;
3973 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_WRITER_ENABLED)
3976 * @old: the old node
3979 * Unlink the old node from its current context, prune the new one
3980 * at the same place. If @cur was already inserted in a document it is
3981 * first unlinked from its existing context.
3983 * See the note regarding namespaces in xmlAddChild.
3985 * Returns the @old node
3988 xmlReplaceNode(xmlNodePtr old
, xmlNodePtr cur
) {
3989 if (old
== cur
) return(NULL
);
3990 if ((old
== NULL
) || (old
->type
== XML_NAMESPACE_DECL
) ||
3991 (old
->parent
== NULL
)) {
3993 xmlGenericError(xmlGenericErrorContext
,
3994 "xmlReplaceNode : old == NULL or without parent\n");
3998 if ((cur
== NULL
) || (cur
->type
== XML_NAMESPACE_DECL
)) {
4005 if ((old
->type
==XML_ATTRIBUTE_NODE
) && (cur
->type
!=XML_ATTRIBUTE_NODE
)) {
4007 xmlGenericError(xmlGenericErrorContext
,
4008 "xmlReplaceNode : Trying to replace attribute node with other node type\n");
4012 if ((cur
->type
==XML_ATTRIBUTE_NODE
) && (old
->type
!=XML_ATTRIBUTE_NODE
)) {
4014 xmlGenericError(xmlGenericErrorContext
,
4015 "xmlReplaceNode : Trying to replace a non-attribute node with attribute node\n");
4020 xmlSetTreeDoc(cur
, old
->doc
);
4021 cur
->parent
= old
->parent
;
4022 cur
->next
= old
->next
;
4023 if (cur
->next
!= NULL
)
4024 cur
->next
->prev
= cur
;
4025 cur
->prev
= old
->prev
;
4026 if (cur
->prev
!= NULL
)
4027 cur
->prev
->next
= cur
;
4028 if (cur
->parent
!= NULL
) {
4029 if (cur
->type
== XML_ATTRIBUTE_NODE
) {
4030 if (cur
->parent
->properties
== (xmlAttrPtr
)old
)
4031 cur
->parent
->properties
= ((xmlAttrPtr
) cur
);
4033 if (cur
->parent
->children
== old
)
4034 cur
->parent
->children
= cur
;
4035 if (cur
->parent
->last
== old
)
4036 cur
->parent
->last
= cur
;
4039 old
->next
= old
->prev
= NULL
;
4043 #endif /* LIBXML_TREE_ENABLED */
4045 /************************************************************************
4049 ************************************************************************/
4053 * @cur: the namespace
4055 * Do a copy of the namespace.
4057 * Returns: a new #xmlNsPtr, or NULL in case of error.
4060 xmlCopyNamespace(xmlNsPtr cur
) {
4063 if (cur
== NULL
) return(NULL
);
4064 switch (cur
->type
) {
4065 case XML_LOCAL_NAMESPACE
:
4066 ret
= xmlNewNs(NULL
, cur
->href
, cur
->prefix
);
4070 xmlGenericError(xmlGenericErrorContext
,
4071 "xmlCopyNamespace: invalid type %d\n", cur
->type
);
4079 * xmlCopyNamespaceList:
4080 * @cur: the first namespace
4082 * Do a copy of an namespace list.
4084 * Returns: a new #xmlNsPtr, or NULL in case of error.
4087 xmlCopyNamespaceList(xmlNsPtr cur
) {
4088 xmlNsPtr ret
= NULL
;
4089 xmlNsPtr p
= NULL
,q
;
4091 while (cur
!= NULL
) {
4092 q
= xmlCopyNamespace(cur
);
4109 xmlCopyPropInternal(xmlDocPtr doc
, xmlNodePtr target
, xmlAttrPtr cur
) {
4112 if (cur
== NULL
) return(NULL
);
4113 if ((target
!= NULL
) && (target
->type
!= XML_ELEMENT_NODE
))
4116 ret
= xmlNewDocProp(target
->doc
, cur
->name
, NULL
);
4117 else if (doc
!= NULL
)
4118 ret
= xmlNewDocProp(doc
, cur
->name
, NULL
);
4119 else if (cur
->parent
!= NULL
)
4120 ret
= xmlNewDocProp(cur
->parent
->doc
, cur
->name
, NULL
);
4121 else if (cur
->children
!= NULL
)
4122 ret
= xmlNewDocProp(cur
->children
->doc
, cur
->name
, NULL
);
4124 ret
= xmlNewDocProp(NULL
, cur
->name
, NULL
);
4125 if (ret
== NULL
) return(NULL
);
4126 ret
->parent
= target
;
4128 if ((cur
->ns
!= NULL
) && (target
!= NULL
)) {
4131 ns
= xmlSearchNs(target
->doc
, target
, cur
->ns
->prefix
);
4134 * Humm, we are copying an element whose namespace is defined
4135 * out of the new tree scope. Search it in the original tree
4136 * and add it at the top of the new tree
4138 ns
= xmlSearchNs(cur
->doc
, cur
->parent
, cur
->ns
->prefix
);
4140 xmlNodePtr root
= target
;
4141 xmlNodePtr pred
= NULL
;
4143 while (root
->parent
!= NULL
) {
4145 root
= root
->parent
;
4147 if (root
== (xmlNodePtr
) target
->doc
) {
4148 /* correct possibly cycling above the document elt */
4151 ret
->ns
= xmlNewNs(root
, ns
->href
, ns
->prefix
);
4155 * we have to find something appropriate here since
4156 * we can't be sure, that the namespace we found is identified
4159 if (xmlStrEqual(ns
->href
, cur
->ns
->href
)) {
4160 /* this is the nice case */
4164 * we are in trouble: we need a new reconciled namespace.
4167 ret
->ns
= xmlNewReconciledNs(target
->doc
, target
, cur
->ns
);
4174 if (cur
->children
!= NULL
) {
4177 ret
->children
= xmlStaticCopyNodeList(cur
->children
, ret
->doc
, (xmlNodePtr
) ret
);
4179 tmp
= ret
->children
;
4180 while (tmp
!= NULL
) {
4181 /* tmp->parent = (xmlNodePtr)ret; */
4182 if (tmp
->next
== NULL
)
4190 if ((target
!= NULL
) && (cur
!= NULL
) &&
4191 (target
->doc
!= NULL
) && (cur
->doc
!= NULL
) &&
4192 (cur
->doc
->ids
!= NULL
) && (cur
->parent
!= NULL
)) {
4193 if (xmlIsID(cur
->doc
, cur
->parent
, cur
)) {
4196 id
= xmlNodeListGetString(cur
->doc
, cur
->children
, 1);
4198 xmlAddID(NULL
, target
->doc
, id
, ret
);
4208 * @target: the element where the attribute will be grafted
4209 * @cur: the attribute
4211 * Do a copy of the attribute.
4213 * Returns: a new #xmlAttrPtr, or NULL in case of error.
4216 xmlCopyProp(xmlNodePtr target
, xmlAttrPtr cur
) {
4217 return xmlCopyPropInternal(NULL
, target
, cur
);
4222 * @target: the element where the attributes will be grafted
4223 * @cur: the first attribute
4225 * Do a copy of an attribute list.
4227 * Returns: a new #xmlAttrPtr, or NULL in case of error.
4230 xmlCopyPropList(xmlNodePtr target
, xmlAttrPtr cur
) {
4231 xmlAttrPtr ret
= NULL
;
4232 xmlAttrPtr p
= NULL
,q
;
4234 if ((target
!= NULL
) && (target
->type
!= XML_ELEMENT_NODE
))
4236 while (cur
!= NULL
) {
4237 q
= xmlCopyProp(target
, cur
);
4239 xmlFreePropList(ret
);
4255 * NOTE about the CopyNode operations !
4257 * They are split into external and internal parts for one
4258 * tricky reason: namespaces. Doing a direct copy of a node
4259 * say RPM:Copyright without changing the namespace pointer to
4260 * something else can produce stale links. One way to do it is
4261 * to keep a reference counter but this doesn't work as soon
4262 * as one moves the element or the subtree out of the scope of
4263 * the existing namespace. The actual solution seems to be to add
4264 * a copy of the namespace at the top of the copied tree if
4265 * not available in the subtree.
4266 * Hence two functions, the public front-end call the inner ones
4267 * The argument "recursive" normally indicates a recursive copy
4268 * of the node with values 0 (no) and 1 (yes). For XInclude,
4269 * however, we allow a value of 2 to indicate copy properties and
4270 * namespace info, but don't recurse on children.
4274 xmlStaticCopyNode(xmlNodePtr node
, xmlDocPtr doc
, xmlNodePtr parent
,
4278 if (node
== NULL
) return(NULL
);
4279 switch (node
->type
) {
4281 case XML_CDATA_SECTION_NODE
:
4282 case XML_ELEMENT_NODE
:
4283 case XML_DOCUMENT_FRAG_NODE
:
4284 case XML_ENTITY_REF_NODE
:
4285 case XML_ENTITY_NODE
:
4287 case XML_COMMENT_NODE
:
4288 case XML_XINCLUDE_START
:
4289 case XML_XINCLUDE_END
:
4291 case XML_ATTRIBUTE_NODE
:
4292 return((xmlNodePtr
) xmlCopyPropInternal(doc
, parent
, (xmlAttrPtr
) node
));
4293 case XML_NAMESPACE_DECL
:
4294 return((xmlNodePtr
) xmlCopyNamespaceList((xmlNsPtr
) node
));
4296 case XML_DOCUMENT_NODE
:
4297 case XML_HTML_DOCUMENT_NODE
:
4298 #ifdef LIBXML_TREE_ENABLED
4299 return((xmlNodePtr
) xmlCopyDoc((xmlDocPtr
) node
, extended
));
4300 #endif /* LIBXML_TREE_ENABLED */
4301 case XML_DOCUMENT_TYPE_NODE
:
4302 case XML_NOTATION_NODE
:
4304 case XML_ELEMENT_DECL
:
4305 case XML_ATTRIBUTE_DECL
:
4306 case XML_ENTITY_DECL
:
4311 * Allocate a new node and fill the fields.
4313 ret
= (xmlNodePtr
) xmlMalloc(sizeof(xmlNode
));
4315 xmlTreeErrMemory("copying node");
4318 memset(ret
, 0, sizeof(xmlNode
));
4319 ret
->type
= node
->type
;
4322 ret
->parent
= parent
;
4323 if (node
->name
== xmlStringText
)
4324 ret
->name
= xmlStringText
;
4325 else if (node
->name
== xmlStringTextNoenc
)
4326 ret
->name
= xmlStringTextNoenc
;
4327 else if (node
->name
== xmlStringComment
)
4328 ret
->name
= xmlStringComment
;
4329 else if (node
->name
!= NULL
) {
4330 if ((doc
!= NULL
) && (doc
->dict
!= NULL
))
4331 ret
->name
= xmlDictLookup(doc
->dict
, node
->name
, -1);
4333 ret
->name
= xmlStrdup(node
->name
);
4335 if ((node
->type
!= XML_ELEMENT_NODE
) &&
4336 (node
->content
!= NULL
) &&
4337 (node
->type
!= XML_ENTITY_REF_NODE
) &&
4338 (node
->type
!= XML_XINCLUDE_END
) &&
4339 (node
->type
!= XML_XINCLUDE_START
)) {
4340 ret
->content
= xmlStrdup(node
->content
);
4342 if (node
->type
== XML_ELEMENT_NODE
)
4343 ret
->line
= node
->line
;
4345 if (parent
!= NULL
) {
4349 * this is a tricky part for the node register thing:
4350 * in case ret does get coalesced in xmlAddChild
4351 * the deregister-node callback is called; so we register ret now already
4353 if ((__xmlRegisterCallbacks
) && (xmlRegisterNodeDefaultValue
))
4354 xmlRegisterNodeDefaultValue((xmlNodePtr
)ret
);
4357 * Note that since ret->parent is already set, xmlAddChild will
4358 * return early and not actually insert the node. It will only
4359 * coalesce text nodes and unnecessarily call xmlSetTreeDoc.
4360 * Assuming that the subtree to be copied always has its text
4361 * nodes coalesced, the somewhat confusing call to xmlAddChild
4364 tmp
= xmlAddChild(parent
, ret
);
4365 /* node could have coalesced */
4372 if (((node
->type
== XML_ELEMENT_NODE
) ||
4373 (node
->type
== XML_XINCLUDE_START
)) && (node
->nsDef
!= NULL
))
4374 ret
->nsDef
= xmlCopyNamespaceList(node
->nsDef
);
4376 if (node
->ns
!= NULL
) {
4379 ns
= xmlSearchNs(doc
, ret
, node
->ns
->prefix
);
4382 * Humm, we are copying an element whose namespace is defined
4383 * out of the new tree scope. Search it in the original tree
4384 * and add it at the top of the new tree
4386 ns
= xmlSearchNs(node
->doc
, node
, node
->ns
->prefix
);
4388 xmlNodePtr root
= ret
;
4390 while (root
->parent
!= NULL
) root
= root
->parent
;
4391 ret
->ns
= xmlNewNs(root
, ns
->href
, ns
->prefix
);
4393 ret
->ns
= xmlNewReconciledNs(doc
, ret
, node
->ns
);
4397 * reference the existing namespace definition in our own tree.
4402 if (((node
->type
== XML_ELEMENT_NODE
) ||
4403 (node
->type
== XML_XINCLUDE_START
)) && (node
->properties
!= NULL
))
4404 ret
->properties
= xmlCopyPropList(ret
, node
->properties
);
4405 if (node
->type
== XML_ENTITY_REF_NODE
) {
4406 if ((doc
== NULL
) || (node
->doc
!= doc
)) {
4408 * The copied node will go into a separate document, so
4409 * to avoid dangling references to the ENTITY_DECL node
4410 * we cannot keep the reference. Try to find it in the
4413 ret
->children
= (xmlNodePtr
) xmlGetDocEntity(doc
, ret
->name
);
4415 ret
->children
= node
->children
;
4417 ret
->last
= ret
->children
;
4418 } else if ((node
->children
!= NULL
) && (extended
!= 2)) {
4419 xmlNodePtr cur
, insert
;
4421 cur
= node
->children
;
4423 while (cur
!= NULL
) {
4424 xmlNodePtr copy
= xmlStaticCopyNode(cur
, doc
, insert
, 2);
4430 /* Check for coalesced text nodes */
4431 if (insert
->last
!= copy
) {
4432 if (insert
->last
== NULL
) {
4433 insert
->children
= copy
;
4435 copy
->prev
= insert
->last
;
4436 insert
->last
->next
= copy
;
4438 insert
->last
= copy
;
4441 if ((cur
->type
!= XML_ENTITY_REF_NODE
) &&
4442 (cur
->children
!= NULL
)) {
4443 cur
= cur
->children
;
4449 if (cur
->next
!= NULL
) {
4455 insert
= insert
->parent
;
4465 /* if parent != NULL we already registered the node above */
4466 if ((parent
== NULL
) &&
4467 ((__xmlRegisterCallbacks
) && (xmlRegisterNodeDefaultValue
)))
4468 xmlRegisterNodeDefaultValue((xmlNodePtr
)ret
);
4473 xmlStaticCopyNodeList(xmlNodePtr node
, xmlDocPtr doc
, xmlNodePtr parent
) {
4474 xmlNodePtr ret
= NULL
;
4475 xmlNodePtr p
= NULL
,q
;
4477 while (node
!= NULL
) {
4478 #ifdef LIBXML_TREE_ENABLED
4479 if (node
->type
== XML_DTD_NODE
) {
4484 if (doc
->intSubset
== NULL
) {
4485 q
= (xmlNodePtr
) xmlCopyDtd( (xmlDtdPtr
) node
);
4486 if (q
== NULL
) goto error
;
4489 doc
->intSubset
= (xmlDtdPtr
) q
;
4490 xmlAddChild(parent
, q
);
4492 q
= (xmlNodePtr
) doc
->intSubset
;
4493 xmlAddChild(parent
, q
);
4496 #endif /* LIBXML_TREE_ENABLED */
4497 q
= xmlStaticCopyNode(node
, doc
, parent
, 1);
4498 if (q
== NULL
) goto error
;
4502 } else if (p
!= q
) {
4503 /* the test is required if xmlStaticCopyNode coalesced 2 text nodes */
4512 xmlFreeNodeList(ret
);
4519 * @extended: if 1 do a recursive copy (properties, namespaces and children
4521 * if 2 copy properties and namespaces (when applicable)
4523 * Do a copy of the node.
4525 * Returns: a new #xmlNodePtr, or NULL in case of error.
4528 xmlCopyNode(xmlNodePtr node
, int extended
) {
4531 ret
= xmlStaticCopyNode(node
, NULL
, NULL
, extended
);
4538 * @doc: the document
4539 * @extended: if 1 do a recursive copy (properties, namespaces and children
4541 * if 2 copy properties and namespaces (when applicable)
4543 * Do a copy of the node to a given document.
4545 * Returns: a new #xmlNodePtr, or NULL in case of error.
4548 xmlDocCopyNode(xmlNodePtr node
, xmlDocPtr doc
, int extended
) {
4551 ret
= xmlStaticCopyNode(node
, doc
, NULL
, extended
);
4556 * xmlDocCopyNodeList:
4557 * @doc: the target document
4558 * @node: the first node in the list.
4560 * Do a recursive copy of the node list.
4562 * Returns: a new #xmlNodePtr, or NULL in case of error.
4564 xmlNodePtr
xmlDocCopyNodeList(xmlDocPtr doc
, xmlNodePtr node
) {
4565 xmlNodePtr ret
= xmlStaticCopyNodeList(node
, doc
, NULL
);
4571 * @node: the first node in the list.
4573 * Do a recursive copy of the node list.
4574 * Use xmlDocCopyNodeList() if possible to ensure string interning.
4576 * Returns: a new #xmlNodePtr, or NULL in case of error.
4578 xmlNodePtr
xmlCopyNodeList(xmlNodePtr node
) {
4579 xmlNodePtr ret
= xmlStaticCopyNodeList(node
, NULL
, NULL
);
4583 #if defined(LIBXML_TREE_ENABLED)
4588 * Do a copy of the dtd.
4590 * Returns: a new #xmlDtdPtr, or NULL in case of error.
4593 xmlCopyDtd(xmlDtdPtr dtd
) {
4595 xmlNodePtr cur
, p
= NULL
, q
;
4597 if (dtd
== NULL
) return(NULL
);
4598 ret
= xmlNewDtd(NULL
, dtd
->name
, dtd
->ExternalID
, dtd
->SystemID
);
4599 if (ret
== NULL
) return(NULL
);
4600 if (dtd
->entities
!= NULL
)
4601 ret
->entities
= (void *) xmlCopyEntitiesTable(
4602 (xmlEntitiesTablePtr
) dtd
->entities
);
4603 if (dtd
->notations
!= NULL
)
4604 ret
->notations
= (void *) xmlCopyNotationTable(
4605 (xmlNotationTablePtr
) dtd
->notations
);
4606 if (dtd
->elements
!= NULL
)
4607 ret
->elements
= (void *) xmlCopyElementTable(
4608 (xmlElementTablePtr
) dtd
->elements
);
4609 if (dtd
->attributes
!= NULL
)
4610 ret
->attributes
= (void *) xmlCopyAttributeTable(
4611 (xmlAttributeTablePtr
) dtd
->attributes
);
4612 if (dtd
->pentities
!= NULL
)
4613 ret
->pentities
= (void *) xmlCopyEntitiesTable(
4614 (xmlEntitiesTablePtr
) dtd
->pentities
);
4616 cur
= dtd
->children
;
4617 while (cur
!= NULL
) {
4620 if (cur
->type
== XML_ENTITY_DECL
) {
4621 xmlEntityPtr tmp
= (xmlEntityPtr
) cur
;
4622 switch (tmp
->etype
) {
4623 case XML_INTERNAL_GENERAL_ENTITY
:
4624 case XML_EXTERNAL_GENERAL_PARSED_ENTITY
:
4625 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY
:
4626 q
= (xmlNodePtr
) xmlGetEntityFromDtd(ret
, tmp
->name
);
4628 case XML_INTERNAL_PARAMETER_ENTITY
:
4629 case XML_EXTERNAL_PARAMETER_ENTITY
:
4631 xmlGetParameterEntityFromDtd(ret
, tmp
->name
);
4633 case XML_INTERNAL_PREDEFINED_ENTITY
:
4636 } else if (cur
->type
== XML_ELEMENT_DECL
) {
4637 xmlElementPtr tmp
= (xmlElementPtr
) cur
;
4639 xmlGetDtdQElementDesc(ret
, tmp
->name
, tmp
->prefix
);
4640 } else if (cur
->type
== XML_ATTRIBUTE_DECL
) {
4641 xmlAttributePtr tmp
= (xmlAttributePtr
) cur
;
4643 xmlGetDtdQAttrDesc(ret
, tmp
->elem
, tmp
->name
, tmp
->prefix
);
4644 } else if (cur
->type
== XML_COMMENT_NODE
) {
4645 q
= xmlCopyNode(cur
, 0);
4659 q
->parent
= (xmlNodePtr
) ret
;
4670 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
4673 * @doc: the document
4674 * @recursive: if not zero do a recursive copy.
4676 * Do a copy of the document info. If recursive, the content tree will
4677 * be copied too as well as DTD, namespaces and entities.
4679 * Returns: a new #xmlDocPtr, or NULL in case of error.
4682 xmlCopyDoc(xmlDocPtr doc
, int recursive
) {
4685 if (doc
== NULL
) return(NULL
);
4686 ret
= xmlNewDoc(doc
->version
);
4687 if (ret
== NULL
) return(NULL
);
4688 ret
->type
= doc
->type
;
4689 if (doc
->name
!= NULL
)
4690 ret
->name
= xmlMemStrdup(doc
->name
);
4691 if (doc
->encoding
!= NULL
)
4692 ret
->encoding
= xmlStrdup(doc
->encoding
);
4693 if (doc
->URL
!= NULL
)
4694 ret
->URL
= xmlStrdup(doc
->URL
);
4695 ret
->charset
= doc
->charset
;
4696 ret
->compression
= doc
->compression
;
4697 ret
->standalone
= doc
->standalone
;
4698 if (!recursive
) return(ret
);
4701 ret
->children
= NULL
;
4702 #ifdef LIBXML_TREE_ENABLED
4703 if (doc
->intSubset
!= NULL
) {
4704 ret
->intSubset
= xmlCopyDtd(doc
->intSubset
);
4705 if (ret
->intSubset
== NULL
) {
4709 xmlSetTreeDoc((xmlNodePtr
)ret
->intSubset
, ret
);
4710 ret
->intSubset
->parent
= ret
;
4713 if (doc
->oldNs
!= NULL
)
4714 ret
->oldNs
= xmlCopyNamespaceList(doc
->oldNs
);
4715 if (doc
->children
!= NULL
) {
4718 ret
->children
= xmlStaticCopyNodeList(doc
->children
, ret
,
4721 tmp
= ret
->children
;
4722 while (tmp
!= NULL
) {
4723 if (tmp
->next
== NULL
)
4730 #endif /* LIBXML_TREE_ENABLED */
4732 /************************************************************************
4734 * Content access functions *
4736 ************************************************************************/
4739 * xmlGetLineNoInternal:
4741 * @depth: used to limit any risk of recursion
4743 * Get line number of @node.
4744 * Try to override the limitation of lines being store in 16 bits ints
4746 * Returns the line number if successful, -1 otherwise
4749 xmlGetLineNoInternal(const xmlNode
*node
, int depth
)
4758 if ((node
->type
== XML_ELEMENT_NODE
) ||
4759 (node
->type
== XML_TEXT_NODE
) ||
4760 (node
->type
== XML_COMMENT_NODE
) ||
4761 (node
->type
== XML_PI_NODE
)) {
4762 if (node
->line
== 65535) {
4763 if ((node
->type
== XML_TEXT_NODE
) && (node
->psvi
!= NULL
))
4764 result
= (long) (ptrdiff_t) node
->psvi
;
4765 else if ((node
->type
== XML_ELEMENT_NODE
) &&
4766 (node
->children
!= NULL
))
4767 result
= xmlGetLineNoInternal(node
->children
, depth
+ 1);
4768 else if (node
->next
!= NULL
)
4769 result
= xmlGetLineNoInternal(node
->next
, depth
+ 1);
4770 else if (node
->prev
!= NULL
)
4771 result
= xmlGetLineNoInternal(node
->prev
, depth
+ 1);
4773 if ((result
== -1) || (result
== 65535))
4774 result
= (long) node
->line
;
4775 } else if ((node
->prev
!= NULL
) &&
4776 ((node
->prev
->type
== XML_ELEMENT_NODE
) ||
4777 (node
->prev
->type
== XML_TEXT_NODE
) ||
4778 (node
->prev
->type
== XML_COMMENT_NODE
) ||
4779 (node
->prev
->type
== XML_PI_NODE
)))
4780 result
= xmlGetLineNoInternal(node
->prev
, depth
+ 1);
4781 else if ((node
->parent
!= NULL
) &&
4782 (node
->parent
->type
== XML_ELEMENT_NODE
))
4783 result
= xmlGetLineNoInternal(node
->parent
, depth
+ 1);
4792 * Get line number of @node.
4793 * Try to override the limitation of lines being store in 16 bits ints
4794 * if XML_PARSE_BIG_LINES parser option was used
4796 * Returns the line number if successful, -1 otherwise
4799 xmlGetLineNo(const xmlNode
*node
)
4801 return(xmlGetLineNoInternal(node
, 0));
4804 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_DEBUG_ENABLED)
4809 * Build a structure based Path for the given node
4811 * Returns the new path or NULL in case of error. The caller must free
4812 * the returned string
4815 xmlGetNodePath(const xmlNode
*node
)
4817 const xmlNode
*cur
, *tmp
, *next
;
4818 xmlChar
*buffer
= NULL
, *temp
;
4824 int occur
= 0, generic
;
4826 if ((node
== NULL
) || (node
->type
== XML_NAMESPACE_DECL
))
4830 buffer
= (xmlChar
*) xmlMallocAtomic(buf_len
);
4831 if (buffer
== NULL
) {
4832 xmlTreeErrMemory("getting node path");
4835 buf
= (xmlChar
*) xmlMallocAtomic(buf_len
);
4837 xmlTreeErrMemory("getting node path");
4848 if ((cur
->type
== XML_DOCUMENT_NODE
) ||
4849 (cur
->type
== XML_HTML_DOCUMENT_NODE
)) {
4850 if (buffer
[0] == '/')
4854 } else if (cur
->type
== XML_ELEMENT_NODE
) {
4857 name
= (const char *) cur
->name
;
4859 if (cur
->ns
->prefix
!= NULL
) {
4860 snprintf(nametemp
, sizeof(nametemp
) - 1, "%s:%s",
4861 (char *)cur
->ns
->prefix
, (char *)cur
->name
);
4862 nametemp
[sizeof(nametemp
) - 1] = 0;
4866 * We cannot express named elements in the default
4867 * namespace, so use "*".
4876 * Thumbler index computation
4877 * TODO: the occurrence test seems bogus for namespaced names
4880 while (tmp
!= NULL
) {
4881 if ((tmp
->type
== XML_ELEMENT_NODE
) &&
4883 (xmlStrEqual(cur
->name
, tmp
->name
) &&
4884 ((tmp
->ns
== cur
->ns
) ||
4885 ((tmp
->ns
!= NULL
) && (cur
->ns
!= NULL
) &&
4886 (xmlStrEqual(cur
->ns
->prefix
, tmp
->ns
->prefix
)))))))
4892 while (tmp
!= NULL
&& occur
== 0) {
4893 if ((tmp
->type
== XML_ELEMENT_NODE
) &&
4895 (xmlStrEqual(cur
->name
, tmp
->name
) &&
4896 ((tmp
->ns
== cur
->ns
) ||
4897 ((tmp
->ns
!= NULL
) && (cur
->ns
!= NULL
) &&
4898 (xmlStrEqual(cur
->ns
->prefix
, tmp
->ns
->prefix
)))))))
4906 } else if (cur
->type
== XML_COMMENT_NODE
) {
4912 * Thumbler index computation
4915 while (tmp
!= NULL
) {
4916 if (tmp
->type
== XML_COMMENT_NODE
)
4922 while (tmp
!= NULL
&& occur
== 0) {
4923 if (tmp
->type
== XML_COMMENT_NODE
)
4931 } else if ((cur
->type
== XML_TEXT_NODE
) ||
4932 (cur
->type
== XML_CDATA_SECTION_NODE
)) {
4938 * Thumbler index computation
4941 while (tmp
!= NULL
) {
4942 if ((tmp
->type
== XML_TEXT_NODE
) ||
4943 (tmp
->type
== XML_CDATA_SECTION_NODE
))
4948 * Evaluate if this is the only text- or CDATA-section-node;
4949 * if yes, then we'll get "text()", otherwise "text()[1]".
4953 while (tmp
!= NULL
) {
4954 if ((tmp
->type
== XML_TEXT_NODE
) ||
4955 (tmp
->type
== XML_CDATA_SECTION_NODE
))
4964 } else if (cur
->type
== XML_PI_NODE
) {
4966 snprintf(nametemp
, sizeof(nametemp
) - 1,
4967 "processing-instruction('%s')", (char *)cur
->name
);
4968 nametemp
[sizeof(nametemp
) - 1] = 0;
4974 * Thumbler index computation
4977 while (tmp
!= NULL
) {
4978 if ((tmp
->type
== XML_PI_NODE
) &&
4979 (xmlStrEqual(cur
->name
, tmp
->name
)))
4985 while (tmp
!= NULL
&& occur
== 0) {
4986 if ((tmp
->type
== XML_PI_NODE
) &&
4987 (xmlStrEqual(cur
->name
, tmp
->name
)))
4996 } else if (cur
->type
== XML_ATTRIBUTE_NODE
) {
4998 name
= (const char *) (((xmlAttrPtr
) cur
)->name
);
5000 if (cur
->ns
->prefix
!= NULL
)
5001 snprintf(nametemp
, sizeof(nametemp
) - 1, "%s:%s",
5002 (char *)cur
->ns
->prefix
, (char *)cur
->name
);
5004 snprintf(nametemp
, sizeof(nametemp
) - 1, "%s",
5006 nametemp
[sizeof(nametemp
) - 1] = 0;
5009 next
= ((xmlAttrPtr
) cur
)->parent
;
5017 * Make sure there is enough room
5019 if (xmlStrlen(buffer
) + sizeof(nametemp
) + 20 > buf_len
) {
5021 2 * buf_len
+ xmlStrlen(buffer
) + sizeof(nametemp
) + 20;
5022 temp
= (xmlChar
*) xmlRealloc(buffer
, buf_len
);
5024 xmlTreeErrMemory("getting node path");
5030 temp
= (xmlChar
*) xmlRealloc(buf
, buf_len
);
5032 xmlTreeErrMemory("getting node path");
5040 snprintf((char *) buf
, buf_len
, "%s%s%s",
5041 sep
, name
, (char *) buffer
);
5043 snprintf((char *) buf
, buf_len
, "%s%s[%d]%s",
5044 sep
, name
, occur
, (char *) buffer
);
5045 snprintf((char *) buffer
, buf_len
, "%s", (char *)buf
);
5047 } while (cur
!= NULL
);
5051 #endif /* LIBXML_TREE_ENABLED */
5054 * xmlDocGetRootElement:
5055 * @doc: the document
5057 * Get the root element of the document (doc->children is a list
5058 * containing possibly comments, PIs, etc ...).
5060 * Returns the #xmlNodePtr for the root or NULL
5063 xmlDocGetRootElement(const xmlDoc
*doc
) {
5066 if (doc
== NULL
) return(NULL
);
5067 ret
= doc
->children
;
5068 while (ret
!= NULL
) {
5069 if (ret
->type
== XML_ELEMENT_NODE
)
5076 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_WRITER_ENABLED)
5078 * xmlDocSetRootElement:
5079 * @doc: the document
5080 * @root: the new document root element, if root is NULL no action is taken,
5081 * to remove a node from a document use xmlUnlinkNode(root) instead.
5083 * Set the root element of the document (doc->children is a list
5084 * containing possibly comments, PIs, etc ...).
5086 * Returns the old root element if any was found, NULL if root was NULL
5089 xmlDocSetRootElement(xmlDocPtr doc
, xmlNodePtr root
) {
5090 xmlNodePtr old
= NULL
;
5092 if (doc
== NULL
) return(NULL
);
5093 if ((root
== NULL
) || (root
->type
== XML_NAMESPACE_DECL
))
5095 xmlUnlinkNode(root
);
5096 xmlSetTreeDoc(root
, doc
);
5097 root
->parent
= (xmlNodePtr
) doc
;
5098 old
= doc
->children
;
5099 while (old
!= NULL
) {
5100 if (old
->type
== XML_ELEMENT_NODE
)
5105 if (doc
->children
== NULL
) {
5106 doc
->children
= root
;
5109 xmlAddSibling(doc
->children
, root
);
5112 xmlReplaceNode(old
, root
);
5118 #if defined(LIBXML_TREE_ENABLED)
5121 * @cur: the node being changed
5122 * @lang: the language description
5124 * Set the language of a node, i.e. the values of the xml:lang
5128 xmlNodeSetLang(xmlNodePtr cur
, const xmlChar
*lang
) {
5131 if (cur
== NULL
) return;
5134 case XML_CDATA_SECTION_NODE
:
5135 case XML_COMMENT_NODE
:
5136 case XML_DOCUMENT_NODE
:
5137 case XML_DOCUMENT_TYPE_NODE
:
5138 case XML_DOCUMENT_FRAG_NODE
:
5139 case XML_NOTATION_NODE
:
5140 case XML_HTML_DOCUMENT_NODE
:
5142 case XML_ELEMENT_DECL
:
5143 case XML_ATTRIBUTE_DECL
:
5144 case XML_ENTITY_DECL
:
5146 case XML_ENTITY_REF_NODE
:
5147 case XML_ENTITY_NODE
:
5148 case XML_NAMESPACE_DECL
:
5149 case XML_XINCLUDE_START
:
5150 case XML_XINCLUDE_END
:
5152 case XML_ELEMENT_NODE
:
5153 case XML_ATTRIBUTE_NODE
:
5156 ns
= xmlSearchNsByHref(cur
->doc
, cur
, XML_XML_NAMESPACE
);
5159 xmlSetNsProp(cur
, ns
, BAD_CAST
"lang", lang
);
5161 #endif /* LIBXML_TREE_ENABLED */
5165 * @cur: the node being checked
5167 * Searches the language of a node, i.e. the values of the xml:lang
5168 * attribute or the one carried by the nearest ancestor.
5170 * Returns a pointer to the lang value, or NULL if not found
5171 * It's up to the caller to free the memory with xmlFree().
5174 xmlNodeGetLang(const xmlNode
*cur
) {
5177 if ((cur
== NULL
) || (cur
->type
== XML_NAMESPACE_DECL
))
5179 while (cur
!= NULL
) {
5180 lang
= xmlGetNsProp(cur
, BAD_CAST
"lang", XML_XML_NAMESPACE
);
5189 #ifdef LIBXML_TREE_ENABLED
5191 * xmlNodeSetSpacePreserve:
5192 * @cur: the node being changed
5193 * @val: the xml:space value ("0": default, 1: "preserve")
5195 * Set (or reset) the space preserving behaviour of a node, i.e. the
5196 * value of the xml:space attribute.
5199 xmlNodeSetSpacePreserve(xmlNodePtr cur
, int val
) {
5202 if (cur
== NULL
) return;
5205 case XML_CDATA_SECTION_NODE
:
5206 case XML_COMMENT_NODE
:
5207 case XML_DOCUMENT_NODE
:
5208 case XML_DOCUMENT_TYPE_NODE
:
5209 case XML_DOCUMENT_FRAG_NODE
:
5210 case XML_NOTATION_NODE
:
5211 case XML_HTML_DOCUMENT_NODE
:
5213 case XML_ELEMENT_DECL
:
5214 case XML_ATTRIBUTE_DECL
:
5215 case XML_ENTITY_DECL
:
5217 case XML_ENTITY_REF_NODE
:
5218 case XML_ENTITY_NODE
:
5219 case XML_NAMESPACE_DECL
:
5220 case XML_XINCLUDE_START
:
5221 case XML_XINCLUDE_END
:
5223 case XML_ELEMENT_NODE
:
5224 case XML_ATTRIBUTE_NODE
:
5227 ns
= xmlSearchNsByHref(cur
->doc
, cur
, XML_XML_NAMESPACE
);
5232 xmlSetNsProp(cur
, ns
, BAD_CAST
"space", BAD_CAST
"default");
5235 xmlSetNsProp(cur
, ns
, BAD_CAST
"space", BAD_CAST
"preserve");
5239 #endif /* LIBXML_TREE_ENABLED */
5242 * xmlNodeGetSpacePreserve:
5243 * @cur: the node being checked
5245 * Searches the space preserving behaviour of a node, i.e. the values
5246 * of the xml:space attribute or the one carried by the nearest
5249 * Returns -1 if xml:space is not inherited, 0 if "default", 1 if "preserve"
5252 xmlNodeGetSpacePreserve(const xmlNode
*cur
) {
5255 if ((cur
== NULL
) || (cur
->type
!= XML_ELEMENT_NODE
))
5257 while (cur
!= NULL
) {
5258 space
= xmlGetNsProp(cur
, BAD_CAST
"space", XML_XML_NAMESPACE
);
5259 if (space
!= NULL
) {
5260 if (xmlStrEqual(space
, BAD_CAST
"preserve")) {
5264 if (xmlStrEqual(space
, BAD_CAST
"default")) {
5275 #ifdef LIBXML_TREE_ENABLED
5278 * @cur: the node being changed
5279 * @name: the new tag name
5281 * Set (or reset) the name of a node.
5284 xmlNodeSetName(xmlNodePtr cur
, const xmlChar
*name
) {
5287 const xmlChar
*freeme
= NULL
;
5289 if (cur
== NULL
) return;
5290 if (name
== NULL
) return;
5293 case XML_CDATA_SECTION_NODE
:
5294 case XML_COMMENT_NODE
:
5295 case XML_DOCUMENT_TYPE_NODE
:
5296 case XML_DOCUMENT_FRAG_NODE
:
5297 case XML_NOTATION_NODE
:
5298 case XML_HTML_DOCUMENT_NODE
:
5299 case XML_NAMESPACE_DECL
:
5300 case XML_XINCLUDE_START
:
5301 case XML_XINCLUDE_END
:
5303 case XML_ELEMENT_NODE
:
5304 case XML_ATTRIBUTE_NODE
:
5306 case XML_ENTITY_REF_NODE
:
5307 case XML_ENTITY_NODE
:
5309 case XML_DOCUMENT_NODE
:
5310 case XML_ELEMENT_DECL
:
5311 case XML_ATTRIBUTE_DECL
:
5312 case XML_ENTITY_DECL
:
5321 if ((cur
->name
!= NULL
) && (!xmlDictOwns(dict
, cur
->name
)))
5323 cur
->name
= xmlDictLookup(dict
, name
, -1);
5325 if (cur
->name
!= NULL
)
5327 cur
->name
= xmlStrdup(name
);
5331 xmlFree((xmlChar
*) freeme
);
5335 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XINCLUDE_ENABLED)
5338 * @cur: the node being changed
5339 * @uri: the new base URI
5341 * Set (or reset) the base URI of a node, i.e. the value of the
5342 * xml:base attribute.
5345 xmlNodeSetBase(xmlNodePtr cur
, const xmlChar
* uri
) {
5349 if (cur
== NULL
) return;
5352 case XML_CDATA_SECTION_NODE
:
5353 case XML_COMMENT_NODE
:
5354 case XML_DOCUMENT_TYPE_NODE
:
5355 case XML_DOCUMENT_FRAG_NODE
:
5356 case XML_NOTATION_NODE
:
5358 case XML_ELEMENT_DECL
:
5359 case XML_ATTRIBUTE_DECL
:
5360 case XML_ENTITY_DECL
:
5362 case XML_ENTITY_REF_NODE
:
5363 case XML_ENTITY_NODE
:
5364 case XML_NAMESPACE_DECL
:
5365 case XML_XINCLUDE_START
:
5366 case XML_XINCLUDE_END
:
5368 case XML_ELEMENT_NODE
:
5369 case XML_ATTRIBUTE_NODE
:
5371 case XML_DOCUMENT_NODE
:
5372 case XML_HTML_DOCUMENT_NODE
: {
5373 xmlDocPtr doc
= (xmlDocPtr
) cur
;
5375 if (doc
->URL
!= NULL
)
5376 xmlFree((xmlChar
*) doc
->URL
);
5380 doc
->URL
= xmlPathToURI(uri
);
5385 ns
= xmlSearchNsByHref(cur
->doc
, cur
, XML_XML_NAMESPACE
);
5388 fixed
= xmlPathToURI(uri
);
5389 if (fixed
!= NULL
) {
5390 xmlSetNsProp(cur
, ns
, BAD_CAST
"base", fixed
);
5393 xmlSetNsProp(cur
, ns
, BAD_CAST
"base", uri
);
5396 #endif /* LIBXML_TREE_ENABLED */
5400 * @doc: the document the node pertains to
5401 * @cur: the node being checked
5403 * Searches for the BASE URL. The code should work on both XML
5404 * and HTML document even if base mechanisms are completely different.
5405 * It returns the base as defined in RFC 2396 sections
5406 * 5.1.1. Base URI within Document Content
5408 * 5.1.2. Base URI from the Encapsulating Entity
5409 * However it does not return the document base (5.1.3), use
5410 * doc->URL in this case
5412 * Returns a pointer to the base URL, or NULL if not found
5413 * It's up to the caller to free the memory with xmlFree().
5416 xmlNodeGetBase(const xmlDoc
*doc
, const xmlNode
*cur
) {
5417 xmlChar
*oldbase
= NULL
;
5418 xmlChar
*base
, *newbase
;
5420 if ((cur
== NULL
) && (doc
== NULL
))
5422 if ((cur
!= NULL
) && (cur
->type
== XML_NAMESPACE_DECL
))
5424 if (doc
== NULL
) doc
= cur
->doc
;
5425 if ((doc
!= NULL
) && (doc
->type
== XML_HTML_DOCUMENT_NODE
)) {
5426 cur
= doc
->children
;
5427 while ((cur
!= NULL
) && (cur
->name
!= NULL
)) {
5428 if (cur
->type
!= XML_ELEMENT_NODE
) {
5432 if (!xmlStrcasecmp(cur
->name
, BAD_CAST
"html")) {
5433 cur
= cur
->children
;
5436 if (!xmlStrcasecmp(cur
->name
, BAD_CAST
"head")) {
5437 cur
= cur
->children
;
5440 if (!xmlStrcasecmp(cur
->name
, BAD_CAST
"base")) {
5441 return(xmlGetProp(cur
, BAD_CAST
"href"));
5447 while (cur
!= NULL
) {
5448 if (cur
->type
== XML_ENTITY_DECL
) {
5449 xmlEntityPtr ent
= (xmlEntityPtr
) cur
;
5450 return(xmlStrdup(ent
->URI
));
5452 if (cur
->type
== XML_ELEMENT_NODE
) {
5453 base
= xmlGetNsProp(cur
, BAD_CAST
"base", XML_XML_NAMESPACE
);
5455 if (oldbase
!= NULL
) {
5456 newbase
= xmlBuildURI(oldbase
, base
);
5457 if (newbase
!= NULL
) {
5469 if ((!xmlStrncmp(oldbase
, BAD_CAST
"http://", 7)) ||
5470 (!xmlStrncmp(oldbase
, BAD_CAST
"ftp://", 6)) ||
5471 (!xmlStrncmp(oldbase
, BAD_CAST
"urn:", 4)))
5477 if ((doc
!= NULL
) && (doc
->URL
!= NULL
)) {
5478 if (oldbase
== NULL
)
5479 return(xmlStrdup(doc
->URL
));
5480 newbase
= xmlBuildURI(oldbase
, doc
->URL
);
5488 * xmlNodeBufGetContent:
5490 * @cur: the node being read
5492 * Read the value of a node @cur, this can be either the text carried
5493 * directly by this node if it's a TEXT node or the aggregate string
5494 * of the values carried by this node child's (TEXT and ENTITY_REF).
5495 * Entity references are substituted.
5496 * Fills up the buffer @buffer with this value
5498 * Returns 0 in case of success and -1 in case of error.
5501 xmlNodeBufGetContent(xmlBufferPtr buffer
, const xmlNode
*cur
)
5506 if ((cur
== NULL
) || (buffer
== NULL
)) return(-1);
5507 buf
= xmlBufFromBuffer(buffer
);
5508 ret
= xmlBufGetNodeContent(buf
, cur
);
5509 buffer
= xmlBufBackToBuffer(buf
);
5510 if ((ret
< 0) || (buffer
== NULL
))
5516 * xmlBufGetNodeContent:
5517 * @buf: a buffer xmlBufPtr
5518 * @cur: the node being read
5520 * Read the value of a node @cur, this can be either the text carried
5521 * directly by this node if it's a TEXT node or the aggregate string
5522 * of the values carried by this node child's (TEXT and ENTITY_REF).
5523 * Entity references are substituted.
5524 * Fills up the buffer @buf with this value
5526 * Returns 0 in case of success and -1 in case of error.
5529 xmlBufGetNodeContent(xmlBufPtr buf
, const xmlNode
*cur
)
5531 if ((cur
== NULL
) || (buf
== NULL
)) return(-1);
5532 switch (cur
->type
) {
5533 case XML_CDATA_SECTION_NODE
:
5535 xmlBufCat(buf
, cur
->content
);
5537 case XML_DOCUMENT_FRAG_NODE
:
5538 case XML_ELEMENT_NODE
:{
5539 const xmlNode
*tmp
= cur
;
5541 while (tmp
!= NULL
) {
5542 switch (tmp
->type
) {
5543 case XML_CDATA_SECTION_NODE
:
5545 if (tmp
->content
!= NULL
)
5546 xmlBufCat(buf
, tmp
->content
);
5548 case XML_ENTITY_REF_NODE
:
5549 xmlBufGetNodeContent(buf
, tmp
);
5557 if (tmp
->children
!= NULL
) {
5558 if (tmp
->children
->type
!= XML_ENTITY_DECL
) {
5559 tmp
= tmp
->children
;
5566 if (tmp
->next
!= NULL
) {
5579 if (tmp
->next
!= NULL
) {
5583 } while (tmp
!= NULL
);
5587 case XML_ATTRIBUTE_NODE
:{
5588 xmlAttrPtr attr
= (xmlAttrPtr
) cur
;
5589 xmlNodePtr tmp
= attr
->children
;
5591 while (tmp
!= NULL
) {
5592 if (tmp
->type
== XML_TEXT_NODE
)
5593 xmlBufCat(buf
, tmp
->content
);
5595 xmlBufGetNodeContent(buf
, tmp
);
5600 case XML_COMMENT_NODE
:
5602 xmlBufCat(buf
, cur
->content
);
5604 case XML_ENTITY_REF_NODE
:{
5608 /* lookup entity declaration */
5609 ent
= xmlGetDocEntity(cur
->doc
, cur
->name
);
5613 /* an entity content can be any "well balanced chunk",
5614 * i.e. the result of the content [43] production:
5615 * http://www.w3.org/TR/REC-xml#NT-content
5616 * -> we iterate through child nodes and recursive call
5617 * xmlNodeGetContent() which handles all possible node types */
5618 tmp
= ent
->children
;
5620 xmlBufGetNodeContent(buf
, tmp
);
5625 case XML_ENTITY_NODE
:
5626 case XML_DOCUMENT_TYPE_NODE
:
5627 case XML_NOTATION_NODE
:
5629 case XML_XINCLUDE_START
:
5630 case XML_XINCLUDE_END
:
5632 case XML_DOCUMENT_NODE
:
5633 case XML_HTML_DOCUMENT_NODE
:
5634 cur
= cur
->children
;
5635 while (cur
!= NULL
) {
5636 if ((cur
->type
== XML_ELEMENT_NODE
) ||
5637 (cur
->type
== XML_TEXT_NODE
) ||
5638 (cur
->type
== XML_CDATA_SECTION_NODE
)) {
5639 xmlBufGetNodeContent(buf
, cur
);
5644 case XML_NAMESPACE_DECL
:
5645 xmlBufCat(buf
, ((xmlNsPtr
) cur
)->href
);
5647 case XML_ELEMENT_DECL
:
5648 case XML_ATTRIBUTE_DECL
:
5649 case XML_ENTITY_DECL
:
5656 * xmlNodeGetContent:
5657 * @cur: the node being read
5659 * Read the value of a node, this can be either the text carried
5660 * directly by this node if it's a TEXT node or the aggregate string
5661 * of the values carried by this node child's (TEXT and ENTITY_REF).
5662 * Entity references are substituted.
5663 * Returns a new #xmlChar * or NULL if no content is available.
5664 * It's up to the caller to free the memory with xmlFree().
5667 xmlNodeGetContent(const xmlNode
*cur
)
5671 switch (cur
->type
) {
5672 case XML_DOCUMENT_FRAG_NODE
:
5673 case XML_ELEMENT_NODE
:{
5677 buf
= xmlBufCreateSize(64);
5680 xmlBufSetAllocationScheme(buf
, XML_BUFFER_ALLOC_DOUBLEIT
);
5681 xmlBufGetNodeContent(buf
, cur
);
5682 ret
= xmlBufDetach(buf
);
5686 case XML_ATTRIBUTE_NODE
:
5687 return(xmlGetPropNodeValueInternal((xmlAttrPtr
) cur
));
5688 case XML_COMMENT_NODE
:
5690 if (cur
->content
!= NULL
)
5691 return (xmlStrdup(cur
->content
));
5693 case XML_ENTITY_REF_NODE
:{
5698 /* lookup entity declaration */
5699 ent
= xmlGetDocEntity(cur
->doc
, cur
->name
);
5703 buf
= xmlBufCreate();
5706 xmlBufSetAllocationScheme(buf
, XML_BUFFER_ALLOC_DOUBLEIT
);
5708 xmlBufGetNodeContent(buf
, cur
);
5710 ret
= xmlBufDetach(buf
);
5714 case XML_ENTITY_NODE
:
5715 case XML_DOCUMENT_TYPE_NODE
:
5716 case XML_NOTATION_NODE
:
5718 case XML_XINCLUDE_START
:
5719 case XML_XINCLUDE_END
:
5721 case XML_DOCUMENT_NODE
:
5722 case XML_HTML_DOCUMENT_NODE
: {
5726 buf
= xmlBufCreate();
5729 xmlBufSetAllocationScheme(buf
, XML_BUFFER_ALLOC_DOUBLEIT
);
5731 xmlBufGetNodeContent(buf
, (xmlNodePtr
) cur
);
5733 ret
= xmlBufDetach(buf
);
5737 case XML_NAMESPACE_DECL
: {
5740 tmp
= xmlStrdup(((xmlNsPtr
) cur
)->href
);
5743 case XML_ELEMENT_DECL
:
5746 case XML_ATTRIBUTE_DECL
:
5749 case XML_ENTITY_DECL
:
5752 case XML_CDATA_SECTION_NODE
:
5754 if (cur
->content
!= NULL
)
5755 return (xmlStrdup(cur
->content
));
5762 * xmlNodeSetContent:
5763 * @cur: the node being modified
5764 * @content: the new value of the content
5766 * Replace the content of a node.
5767 * NOTE: @content is supposed to be a piece of XML CDATA, so it allows entity
5768 * references, but XML special chars need to be escaped first by using
5769 * xmlEncodeEntitiesReentrant() resp. xmlEncodeSpecialChars().
5772 xmlNodeSetContent(xmlNodePtr cur
, const xmlChar
*content
) {
5775 xmlGenericError(xmlGenericErrorContext
,
5776 "xmlNodeSetContent : node == NULL\n");
5780 switch (cur
->type
) {
5781 case XML_DOCUMENT_FRAG_NODE
:
5782 case XML_ELEMENT_NODE
:
5783 case XML_ATTRIBUTE_NODE
:
5784 if (cur
->children
!= NULL
) xmlFreeNodeList(cur
->children
);
5785 cur
->children
= xmlStringGetNodeList(cur
->doc
, content
);
5786 UPDATE_LAST_CHILD_AND_PARENT(cur
)
5789 case XML_CDATA_SECTION_NODE
:
5790 case XML_ENTITY_REF_NODE
:
5791 case XML_ENTITY_NODE
:
5793 case XML_COMMENT_NODE
:
5794 if ((cur
->content
!= NULL
) &&
5795 (cur
->content
!= (xmlChar
*) &(cur
->properties
))) {
5796 if (!((cur
->doc
!= NULL
) && (cur
->doc
->dict
!= NULL
) &&
5797 (xmlDictOwns(cur
->doc
->dict
, cur
->content
))))
5798 xmlFree(cur
->content
);
5800 if (cur
->children
!= NULL
) xmlFreeNodeList(cur
->children
);
5801 cur
->last
= cur
->children
= NULL
;
5802 if (content
!= NULL
) {
5803 cur
->content
= xmlStrdup(content
);
5805 cur
->content
= NULL
;
5806 cur
->properties
= NULL
;
5808 case XML_DOCUMENT_NODE
:
5809 case XML_HTML_DOCUMENT_NODE
:
5810 case XML_DOCUMENT_TYPE_NODE
:
5811 case XML_XINCLUDE_START
:
5812 case XML_XINCLUDE_END
:
5814 case XML_NOTATION_NODE
:
5818 case XML_NAMESPACE_DECL
:
5820 case XML_ELEMENT_DECL
:
5823 case XML_ATTRIBUTE_DECL
:
5826 case XML_ENTITY_DECL
:
5832 #ifdef LIBXML_TREE_ENABLED
5834 * xmlNodeSetContentLen:
5835 * @cur: the node being modified
5836 * @content: the new value of the content
5837 * @len: the size of @content
5839 * Replace the content of a node.
5840 * NOTE: @content is supposed to be a piece of XML CDATA, so it allows entity
5841 * references, but XML special chars need to be escaped first by using
5842 * xmlEncodeEntitiesReentrant() resp. xmlEncodeSpecialChars().
5845 xmlNodeSetContentLen(xmlNodePtr cur
, const xmlChar
*content
, int len
) {
5848 xmlGenericError(xmlGenericErrorContext
,
5849 "xmlNodeSetContentLen : node == NULL\n");
5853 switch (cur
->type
) {
5854 case XML_DOCUMENT_FRAG_NODE
:
5855 case XML_ELEMENT_NODE
:
5856 case XML_ATTRIBUTE_NODE
:
5857 if (cur
->children
!= NULL
) xmlFreeNodeList(cur
->children
);
5858 cur
->children
= xmlStringLenGetNodeList(cur
->doc
, content
, len
);
5859 UPDATE_LAST_CHILD_AND_PARENT(cur
)
5862 case XML_CDATA_SECTION_NODE
:
5863 case XML_ENTITY_REF_NODE
:
5864 case XML_ENTITY_NODE
:
5866 case XML_COMMENT_NODE
:
5867 case XML_NOTATION_NODE
:
5868 if ((cur
->content
!= NULL
) &&
5869 (cur
->content
!= (xmlChar
*) &(cur
->properties
))) {
5870 if (!((cur
->doc
!= NULL
) && (cur
->doc
->dict
!= NULL
) &&
5871 (xmlDictOwns(cur
->doc
->dict
, cur
->content
))))
5872 xmlFree(cur
->content
);
5874 if (cur
->children
!= NULL
) xmlFreeNodeList(cur
->children
);
5875 cur
->children
= cur
->last
= NULL
;
5876 if (content
!= NULL
) {
5877 cur
->content
= xmlStrndup(content
, len
);
5879 cur
->content
= NULL
;
5880 cur
->properties
= NULL
;
5882 case XML_DOCUMENT_NODE
:
5884 case XML_HTML_DOCUMENT_NODE
:
5885 case XML_DOCUMENT_TYPE_NODE
:
5886 case XML_NAMESPACE_DECL
:
5887 case XML_XINCLUDE_START
:
5888 case XML_XINCLUDE_END
:
5890 case XML_ELEMENT_DECL
:
5893 case XML_ATTRIBUTE_DECL
:
5896 case XML_ENTITY_DECL
:
5901 #endif /* LIBXML_TREE_ENABLED */
5904 * xmlNodeAddContentLen:
5905 * @cur: the node being modified
5906 * @content: extra content
5907 * @len: the size of @content
5909 * Append the extra substring to the node content.
5910 * NOTE: In contrast to xmlNodeSetContentLen(), @content is supposed to be
5911 * raw text, so unescaped XML special chars are allowed, entity
5912 * references are not supported.
5915 xmlNodeAddContentLen(xmlNodePtr cur
, const xmlChar
*content
, int len
) {
5918 xmlGenericError(xmlGenericErrorContext
,
5919 "xmlNodeAddContentLen : node == NULL\n");
5923 if (len
<= 0) return;
5924 switch (cur
->type
) {
5925 case XML_DOCUMENT_FRAG_NODE
:
5926 case XML_ELEMENT_NODE
: {
5927 xmlNodePtr last
, newNode
, tmp
;
5930 newNode
= xmlNewDocTextLen(cur
->doc
, content
, len
);
5931 if (newNode
!= NULL
) {
5932 tmp
= xmlAddChild(cur
, newNode
);
5935 if ((last
!= NULL
) && (last
->next
== newNode
)) {
5936 xmlTextMerge(last
, newNode
);
5941 case XML_ATTRIBUTE_NODE
:
5944 case XML_CDATA_SECTION_NODE
:
5945 case XML_ENTITY_REF_NODE
:
5946 case XML_ENTITY_NODE
:
5948 case XML_COMMENT_NODE
:
5949 case XML_NOTATION_NODE
:
5950 if (content
!= NULL
) {
5951 if ((cur
->content
== (xmlChar
*) &(cur
->properties
)) ||
5952 ((cur
->doc
!= NULL
) && (cur
->doc
->dict
!= NULL
) &&
5953 xmlDictOwns(cur
->doc
->dict
, cur
->content
))) {
5954 cur
->content
= xmlStrncatNew(cur
->content
, content
, len
);
5955 cur
->properties
= NULL
;
5957 cur
->content
= xmlStrncat(cur
->content
, content
, len
);
5961 case XML_DOCUMENT_NODE
:
5963 case XML_HTML_DOCUMENT_NODE
:
5964 case XML_DOCUMENT_TYPE_NODE
:
5965 case XML_NAMESPACE_DECL
:
5966 case XML_XINCLUDE_START
:
5967 case XML_XINCLUDE_END
:
5969 case XML_ELEMENT_DECL
:
5970 case XML_ATTRIBUTE_DECL
:
5971 case XML_ENTITY_DECL
:
5977 * xmlNodeAddContent:
5978 * @cur: the node being modified
5979 * @content: extra content
5981 * Append the extra substring to the node content.
5982 * NOTE: In contrast to xmlNodeSetContent(), @content is supposed to be
5983 * raw text, so unescaped XML special chars are allowed, entity
5984 * references are not supported.
5987 xmlNodeAddContent(xmlNodePtr cur
, const xmlChar
*content
) {
5992 xmlGenericError(xmlGenericErrorContext
,
5993 "xmlNodeAddContent : node == NULL\n");
5997 if (content
== NULL
) return;
5998 len
= xmlStrlen(content
);
5999 xmlNodeAddContentLen(cur
, content
, len
);
6004 * @first: the first text node
6005 * @second: the second text node being merged
6007 * Merge two text nodes into one
6008 * Returns the first text node augmented
6011 xmlTextMerge(xmlNodePtr first
, xmlNodePtr second
) {
6012 if (first
== NULL
) return(second
);
6013 if (second
== NULL
) return(first
);
6014 if (first
->type
!= XML_TEXT_NODE
) return(first
);
6015 if (second
->type
!= XML_TEXT_NODE
) return(first
);
6016 if (second
->name
!= first
->name
)
6018 xmlNodeAddContent(first
, second
->content
);
6019 xmlUnlinkNode(second
);
6020 xmlFreeNode(second
);
6024 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XPATH_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
6027 * @doc: the document
6028 * @node: the current node
6030 * Search all the namespace applying to a given element.
6031 * Returns an NULL terminated array of all the #xmlNsPtr found
6032 * that need to be freed by the caller or NULL if no
6033 * namespace if defined
6036 xmlGetNsList(const xmlDoc
*doc ATTRIBUTE_UNUSED
, const xmlNode
*node
)
6039 xmlNsPtr
*ret
= NULL
;
6044 if ((node
== NULL
) || (node
->type
== XML_NAMESPACE_DECL
))
6047 while (node
!= NULL
) {
6048 if (node
->type
== XML_ELEMENT_NODE
) {
6050 while (cur
!= NULL
) {
6051 for (i
= 0; i
< nbns
; i
++) {
6052 if ((cur
->prefix
== ret
[i
]->prefix
) ||
6053 (xmlStrEqual(cur
->prefix
, ret
[i
]->prefix
)))
6057 if (nbns
>= maxns
) {
6060 maxns
= maxns
? maxns
* 2 : 10;
6061 tmp
= (xmlNsPtr
*) xmlRealloc(ret
,
6065 xmlTreeErrMemory("getting namespace list");
6078 node
= node
->parent
;
6082 #endif /* LIBXML_TREE_ENABLED */
6085 * xmlTreeEnsureXMLDecl:
6088 * Ensures that there is an XML namespace declaration on the doc.
6090 * Returns the XML ns-struct or NULL on API and internal errors.
6093 xmlTreeEnsureXMLDecl(xmlDocPtr doc
)
6097 if (doc
->oldNs
!= NULL
)
6098 return (doc
->oldNs
);
6101 ns
= (xmlNsPtr
) xmlMalloc(sizeof(xmlNs
));
6104 "allocating the XML namespace");
6107 memset(ns
, 0, sizeof(xmlNs
));
6108 ns
->type
= XML_LOCAL_NAMESPACE
;
6109 ns
->href
= xmlStrdup(XML_XML_NAMESPACE
);
6110 ns
->prefix
= xmlStrdup((const xmlChar
*)"xml");
6118 * @doc: the document
6119 * @node: the current node
6120 * @nameSpace: the namespace prefix
6122 * Search a Ns registered under a given name space for a document.
6123 * recurse on the parents until it finds the defined namespace
6124 * or return NULL otherwise.
6125 * @nameSpace can be NULL, this is a search for the default namespace.
6126 * We don't allow to cross entities boundaries. If you don't declare
6127 * the namespace within those you will be in troubles !!! A warning
6128 * is generated to cover this case.
6130 * Returns the namespace pointer or NULL.
6133 xmlSearchNs(xmlDocPtr doc
, xmlNodePtr node
, const xmlChar
*nameSpace
) {
6136 const xmlNode
*orig
= node
;
6138 if ((node
== NULL
) || (node
->type
== XML_NAMESPACE_DECL
)) return(NULL
);
6139 if ((nameSpace
!= NULL
) &&
6140 (xmlStrEqual(nameSpace
, (const xmlChar
*)"xml"))) {
6141 if ((doc
== NULL
) && (node
->type
== XML_ELEMENT_NODE
)) {
6143 * The XML-1.0 namespace is normally held on the root
6144 * element. In this case exceptionally create it on the
6147 cur
= (xmlNsPtr
) xmlMalloc(sizeof(xmlNs
));
6149 xmlTreeErrMemory("searching namespace");
6152 memset(cur
, 0, sizeof(xmlNs
));
6153 cur
->type
= XML_LOCAL_NAMESPACE
;
6154 cur
->href
= xmlStrdup(XML_XML_NAMESPACE
);
6155 cur
->prefix
= xmlStrdup((const xmlChar
*)"xml");
6156 cur
->next
= node
->nsDef
;
6166 * Return the XML namespace declaration held by the doc.
6168 if (doc
->oldNs
== NULL
)
6169 return(xmlTreeEnsureXMLDecl(doc
));
6173 while (node
!= NULL
) {
6174 if ((node
->type
== XML_ENTITY_REF_NODE
) ||
6175 (node
->type
== XML_ENTITY_NODE
) ||
6176 (node
->type
== XML_ENTITY_DECL
))
6178 if (node
->type
== XML_ELEMENT_NODE
) {
6180 while (cur
!= NULL
) {
6181 if ((cur
->prefix
== NULL
) && (nameSpace
== NULL
) &&
6182 (cur
->href
!= NULL
))
6184 if ((cur
->prefix
!= NULL
) && (nameSpace
!= NULL
) &&
6185 (cur
->href
!= NULL
) &&
6186 (xmlStrEqual(cur
->prefix
, nameSpace
)))
6193 if ((cur
->prefix
== NULL
) && (nameSpace
== NULL
) &&
6194 (cur
->href
!= NULL
))
6196 if ((cur
->prefix
!= NULL
) && (nameSpace
!= NULL
) &&
6197 (cur
->href
!= NULL
) &&
6198 (xmlStrEqual(cur
->prefix
, nameSpace
)))
6203 node
= node
->parent
;
6210 * @doc: the document
6211 * @node: the current node
6212 * @ancestor: the ancestor carrying the namespace
6213 * @prefix: the namespace prefix
6215 * Verify that the given namespace held on @ancestor is still in scope
6218 * Returns 1 if true, 0 if false and -1 in case of error.
6221 xmlNsInScope(xmlDocPtr doc ATTRIBUTE_UNUSED
, xmlNodePtr node
,
6222 xmlNodePtr ancestor
, const xmlChar
* prefix
)
6226 while ((node
!= NULL
) && (node
!= ancestor
)) {
6227 if ((node
->type
== XML_ENTITY_REF_NODE
) ||
6228 (node
->type
== XML_ENTITY_NODE
) ||
6229 (node
->type
== XML_ENTITY_DECL
))
6231 if (node
->type
== XML_ELEMENT_NODE
) {
6233 while (tst
!= NULL
) {
6234 if ((tst
->prefix
== NULL
)
6235 && (prefix
== NULL
))
6237 if ((tst
->prefix
!= NULL
)
6239 && (xmlStrEqual(tst
->prefix
, prefix
)))
6244 node
= node
->parent
;
6246 if (node
!= ancestor
)
6252 * xmlSearchNsByHref:
6253 * @doc: the document
6254 * @node: the current node
6255 * @href: the namespace value
6257 * Search a Ns aliasing a given URI. Recurse on the parents until it finds
6258 * the defined namespace or return NULL otherwise.
6259 * Returns the namespace pointer or NULL.
6262 xmlSearchNsByHref(xmlDocPtr doc
, xmlNodePtr node
, const xmlChar
* href
)
6265 xmlNodePtr orig
= node
;
6268 if ((node
== NULL
) || (node
->type
== XML_NAMESPACE_DECL
) || (href
== NULL
))
6270 if (xmlStrEqual(href
, XML_XML_NAMESPACE
)) {
6272 * Only the document can hold the XML spec namespace.
6274 if ((doc
== NULL
) && (node
->type
== XML_ELEMENT_NODE
)) {
6276 * The XML-1.0 namespace is normally held on the root
6277 * element. In this case exceptionally create it on the
6280 cur
= (xmlNsPtr
) xmlMalloc(sizeof(xmlNs
));
6282 xmlTreeErrMemory("searching namespace");
6285 memset(cur
, 0, sizeof(xmlNs
));
6286 cur
->type
= XML_LOCAL_NAMESPACE
;
6287 cur
->href
= xmlStrdup(XML_XML_NAMESPACE
);
6288 cur
->prefix
= xmlStrdup((const xmlChar
*) "xml");
6289 cur
->next
= node
->nsDef
;
6299 * Return the XML namespace declaration held by the doc.
6301 if (doc
->oldNs
== NULL
)
6302 return(xmlTreeEnsureXMLDecl(doc
));
6306 is_attr
= (node
->type
== XML_ATTRIBUTE_NODE
);
6307 while (node
!= NULL
) {
6308 if ((node
->type
== XML_ENTITY_REF_NODE
) ||
6309 (node
->type
== XML_ENTITY_NODE
) ||
6310 (node
->type
== XML_ENTITY_DECL
))
6312 if (node
->type
== XML_ELEMENT_NODE
) {
6314 while (cur
!= NULL
) {
6315 if ((cur
->href
!= NULL
) && (href
!= NULL
) &&
6316 (xmlStrEqual(cur
->href
, href
))) {
6317 if (((!is_attr
) || (cur
->prefix
!= NULL
)) &&
6318 (xmlNsInScope(doc
, orig
, node
, cur
->prefix
) == 1))
6326 if ((cur
->href
!= NULL
) && (href
!= NULL
) &&
6327 (xmlStrEqual(cur
->href
, href
))) {
6328 if (((!is_attr
) || (cur
->prefix
!= NULL
)) &&
6329 (xmlNsInScope(doc
, orig
, node
, cur
->prefix
) == 1))
6335 node
= node
->parent
;
6341 * xmlNewReconciledNs:
6342 * @doc: the document
6343 * @tree: a node expected to hold the new namespace
6344 * @ns: the original namespace
6346 * This function tries to locate a namespace definition in a tree
6347 * ancestors, or create a new namespace definition node similar to
6348 * @ns trying to reuse the same prefix. However if the given prefix is
6349 * null (default namespace) or reused within the subtree defined by
6350 * @tree or on one of its ancestors then a new prefix is generated.
6351 * Returns the (new) namespace definition or NULL in case of error
6354 xmlNewReconciledNs(xmlDocPtr doc
, xmlNodePtr tree
, xmlNsPtr ns
) {
6359 if ((tree
== NULL
) || (tree
->type
!= XML_ELEMENT_NODE
)) {
6361 xmlGenericError(xmlGenericErrorContext
,
6362 "xmlNewReconciledNs : tree == NULL\n");
6366 if ((ns
== NULL
) || (ns
->type
!= XML_NAMESPACE_DECL
)) {
6368 xmlGenericError(xmlGenericErrorContext
,
6369 "xmlNewReconciledNs : ns == NULL\n");
6374 * Search an existing namespace definition inherited.
6376 def
= xmlSearchNsByHref(doc
, tree
, ns
->href
);
6381 * Find a close prefix which is not already in use.
6382 * Let's strip namespace prefixes longer than 20 chars !
6384 if (ns
->prefix
== NULL
)
6385 snprintf((char *) prefix
, sizeof(prefix
), "default");
6387 snprintf((char *) prefix
, sizeof(prefix
), "%.20s", (char *)ns
->prefix
);
6389 def
= xmlSearchNs(doc
, tree
, prefix
);
6390 while (def
!= NULL
) {
6391 if (counter
> 1000) return(NULL
);
6392 if (ns
->prefix
== NULL
)
6393 snprintf((char *) prefix
, sizeof(prefix
), "default%d", counter
++);
6395 snprintf((char *) prefix
, sizeof(prefix
), "%.20s%d",
6396 (char *)ns
->prefix
, counter
++);
6397 def
= xmlSearchNs(doc
, tree
, prefix
);
6401 * OK, now we are ready to create a new one.
6403 def
= xmlNewNs(tree
, ns
->href
, prefix
);
6407 #ifdef LIBXML_TREE_ENABLED
6409 * xmlReconciliateNs:
6410 * @doc: the document
6411 * @tree: a node defining the subtree to reconciliate
6413 * This function checks that all the namespaces declared within the given
6414 * tree are properly declared. This is needed for example after Copy or Cut
6415 * and then paste operations. The subtree may still hold pointers to
6416 * namespace declarations outside the subtree or invalid/masked. As much
6417 * as possible the function try to reuse the existing namespaces found in
6418 * the new environment. If not possible the new namespaces are redeclared
6419 * on @tree at the top of the given subtree.
6420 * Returns the number of namespace declarations created or -1 in case of error.
6423 xmlReconciliateNs(xmlDocPtr doc
, xmlNodePtr tree
) {
6424 xmlNsPtr
*oldNs
= NULL
;
6425 xmlNsPtr
*newNs
= NULL
;
6430 xmlNodePtr node
= tree
;
6434 if ((node
== NULL
) || (node
->type
!= XML_ELEMENT_NODE
)) return(-1);
6435 if ((doc
== NULL
) || (doc
->type
!= XML_DOCUMENT_NODE
)) return(-1);
6436 if (node
->doc
!= doc
) return(-1);
6437 while (node
!= NULL
) {
6439 * Reconciliate the node namespace
6441 if (node
->ns
!= NULL
) {
6443 * initialize the cache if needed
6445 if (sizeCache
== 0) {
6447 oldNs
= (xmlNsPtr
*) xmlMalloc(sizeCache
*
6449 if (oldNs
== NULL
) {
6450 xmlTreeErrMemory("fixing namespaces");
6453 newNs
= (xmlNsPtr
*) xmlMalloc(sizeCache
*
6455 if (newNs
== NULL
) {
6456 xmlTreeErrMemory("fixing namespaces");
6461 for (i
= 0;i
< nbCache
;i
++) {
6462 if (oldNs
[i
] == node
->ns
) {
6463 node
->ns
= newNs
[i
];
6469 * OK we need to recreate a new namespace definition
6471 n
= xmlNewReconciledNs(doc
, tree
, node
->ns
);
6472 if (n
!= NULL
) { /* :-( what if else ??? */
6474 * check if we need to grow the cache buffers.
6476 if (sizeCache
<= nbCache
) {
6478 oldNs
= (xmlNsPtr
*) xmlRealloc(oldNs
, sizeCache
*
6480 if (oldNs
== NULL
) {
6481 xmlTreeErrMemory("fixing namespaces");
6485 newNs
= (xmlNsPtr
*) xmlRealloc(newNs
, sizeCache
*
6487 if (newNs
== NULL
) {
6488 xmlTreeErrMemory("fixing namespaces");
6494 oldNs
[nbCache
++] = node
->ns
;
6500 * now check for namespace held by attributes on the node.
6502 if (node
->type
== XML_ELEMENT_NODE
) {
6503 attr
= node
->properties
;
6504 while (attr
!= NULL
) {
6505 if (attr
->ns
!= NULL
) {
6507 * initialize the cache if needed
6509 if (sizeCache
== 0) {
6511 oldNs
= (xmlNsPtr
*) xmlMalloc(sizeCache
*
6513 if (oldNs
== NULL
) {
6514 xmlTreeErrMemory("fixing namespaces");
6517 newNs
= (xmlNsPtr
*) xmlMalloc(sizeCache
*
6519 if (newNs
== NULL
) {
6520 xmlTreeErrMemory("fixing namespaces");
6525 for (i
= 0;i
< nbCache
;i
++) {
6526 if (oldNs
[i
] == attr
->ns
) {
6527 attr
->ns
= newNs
[i
];
6533 * OK we need to recreate a new namespace definition
6535 n
= xmlNewReconciledNs(doc
, tree
, attr
->ns
);
6536 if (n
!= NULL
) { /* :-( what if else ??? */
6538 * check if we need to grow the cache buffers.
6540 if (sizeCache
<= nbCache
) {
6542 oldNs
= (xmlNsPtr
*) xmlRealloc(oldNs
,
6543 sizeCache
* sizeof(xmlNsPtr
));
6544 if (oldNs
== NULL
) {
6545 xmlTreeErrMemory("fixing namespaces");
6549 newNs
= (xmlNsPtr
*) xmlRealloc(newNs
,
6550 sizeCache
* sizeof(xmlNsPtr
));
6551 if (newNs
== NULL
) {
6552 xmlTreeErrMemory("fixing namespaces");
6558 oldNs
[nbCache
++] = attr
->ns
;
6568 * Browse the full subtree, deep first
6570 if ((node
->children
!= NULL
) && (node
->type
!= XML_ENTITY_REF_NODE
)) {
6572 node
= node
->children
;
6573 } else if ((node
!= tree
) && (node
->next
!= NULL
)) {
6576 } else if (node
!= tree
) {
6577 /* go up to parents->next if needed */
6578 while (node
!= tree
) {
6579 if (node
->parent
!= NULL
)
6580 node
= node
->parent
;
6581 if ((node
!= tree
) && (node
->next
!= NULL
)) {
6585 if (node
->parent
== NULL
) {
6590 /* exit condition */
6602 #endif /* LIBXML_TREE_ENABLED */
6605 xmlGetPropNodeInternal(const xmlNode
*node
, const xmlChar
*name
,
6606 const xmlChar
*nsName
, int useDTD
)
6610 /* Avoid unused variable warning if features are disabled. */
6613 if ((node
== NULL
) || (node
->type
!= XML_ELEMENT_NODE
) || (name
== NULL
))
6616 if (node
->properties
!= NULL
) {
6617 prop
= node
->properties
;
6618 if (nsName
== NULL
) {
6620 * We want the attr to be in no namespace.
6623 if ((prop
->ns
== NULL
) && xmlStrEqual(prop
->name
, name
)) {
6627 } while (prop
!= NULL
);
6630 * We want the attr to be in the specified namespace.
6633 if ((prop
->ns
!= NULL
) && xmlStrEqual(prop
->name
, name
) &&
6634 ((prop
->ns
->href
== nsName
) ||
6635 xmlStrEqual(prop
->ns
->href
, nsName
)))
6640 } while (prop
!= NULL
);
6644 #ifdef LIBXML_TREE_ENABLED
6648 * Check if there is a default/fixed attribute declaration in
6649 * the internal or external subset.
6651 if ((node
->doc
!= NULL
) && (node
->doc
->intSubset
!= NULL
)) {
6652 xmlDocPtr doc
= node
->doc
;
6653 xmlAttributePtr attrDecl
= NULL
;
6654 xmlChar
*elemQName
, *tmpstr
= NULL
;
6657 * We need the QName of the element for the DTD-lookup.
6659 if ((node
->ns
!= NULL
) && (node
->ns
->prefix
!= NULL
)) {
6660 tmpstr
= xmlStrdup(node
->ns
->prefix
);
6661 tmpstr
= xmlStrcat(tmpstr
, BAD_CAST
":");
6662 tmpstr
= xmlStrcat(tmpstr
, node
->name
);
6667 elemQName
= (xmlChar
*) node
->name
;
6668 if (nsName
== NULL
) {
6670 * The common and nice case: Attr in no namespace.
6672 attrDecl
= xmlGetDtdQAttrDesc(doc
->intSubset
,
6673 elemQName
, name
, NULL
);
6674 if ((attrDecl
== NULL
) && (doc
->extSubset
!= NULL
)) {
6675 attrDecl
= xmlGetDtdQAttrDesc(doc
->extSubset
,
6676 elemQName
, name
, NULL
);
6678 } else if (xmlStrEqual(nsName
, XML_XML_NAMESPACE
)) {
6680 * The XML namespace must be bound to prefix 'xml'.
6682 attrDecl
= xmlGetDtdQAttrDesc(doc
->intSubset
,
6683 elemQName
, name
, BAD_CAST
"xml");
6684 if ((attrDecl
== NULL
) && (doc
->extSubset
!= NULL
)) {
6685 attrDecl
= xmlGetDtdQAttrDesc(doc
->extSubset
,
6686 elemQName
, name
, BAD_CAST
"xml");
6689 xmlNsPtr
*nsList
, *cur
;
6692 * The ugly case: Search using the prefixes of in-scope
6693 * ns-decls corresponding to @nsName.
6695 nsList
= xmlGetNsList(node
->doc
, node
);
6696 if (nsList
== NULL
) {
6702 while (*cur
!= NULL
) {
6703 if (xmlStrEqual((*cur
)->href
, nsName
)) {
6704 attrDecl
= xmlGetDtdQAttrDesc(doc
->intSubset
, elemQName
,
6705 name
, (*cur
)->prefix
);
6708 if (doc
->extSubset
!= NULL
) {
6709 attrDecl
= xmlGetDtdQAttrDesc(doc
->extSubset
, elemQName
,
6710 name
, (*cur
)->prefix
);
6722 * Only default/fixed attrs are relevant.
6724 if ((attrDecl
!= NULL
) && (attrDecl
->defaultValue
!= NULL
))
6725 return((xmlAttrPtr
) attrDecl
);
6727 #endif /* LIBXML_TREE_ENABLED */
6732 xmlGetPropNodeValueInternal(const xmlAttr
*prop
)
6736 if (prop
->type
== XML_ATTRIBUTE_NODE
) {
6738 * Note that we return at least the empty string.
6739 * TODO: Do we really always want that?
6741 if (prop
->children
!= NULL
) {
6742 if ((prop
->children
->next
== NULL
) &&
6743 ((prop
->children
->type
== XML_TEXT_NODE
) ||
6744 (prop
->children
->type
== XML_CDATA_SECTION_NODE
)))
6747 * Optimization for the common case: only 1 text node.
6749 return(xmlStrdup(prop
->children
->content
));
6753 ret
= xmlNodeListGetString(prop
->doc
, prop
->children
, 1);
6758 return(xmlStrdup((xmlChar
*)""));
6759 } else if (prop
->type
== XML_ATTRIBUTE_DECL
) {
6760 return(xmlStrdup(((xmlAttributePtr
)prop
)->defaultValue
));
6768 * @name: the attribute name
6770 * Search an attribute associated to a node
6771 * This function also looks in DTD attribute declaration for #FIXED or
6772 * default declaration values unless DTD use has been turned off.
6774 * Returns the attribute or the attribute declaration or NULL if
6775 * neither was found.
6778 xmlHasProp(const xmlNode
*node
, const xmlChar
*name
) {
6782 if ((node
== NULL
) || (node
->type
!= XML_ELEMENT_NODE
) || (name
== NULL
))
6785 * Check on the properties attached to the node
6787 prop
= node
->properties
;
6788 while (prop
!= NULL
) {
6789 if (xmlStrEqual(prop
->name
, name
)) {
6794 if (!xmlCheckDTD
) return(NULL
);
6797 * Check if there is a default declaration in the internal
6798 * or external subsets
6802 xmlAttributePtr attrDecl
;
6803 if (doc
->intSubset
!= NULL
) {
6804 attrDecl
= xmlGetDtdAttrDesc(doc
->intSubset
, node
->name
, name
);
6805 if ((attrDecl
== NULL
) && (doc
->extSubset
!= NULL
))
6806 attrDecl
= xmlGetDtdAttrDesc(doc
->extSubset
, node
->name
, name
);
6807 if ((attrDecl
!= NULL
) && (attrDecl
->defaultValue
!= NULL
))
6808 /* return attribute declaration only if a default value is given
6809 (that includes #FIXED declarations) */
6810 return((xmlAttrPtr
) attrDecl
);
6819 * @name: the attribute name
6820 * @nameSpace: the URI of the namespace
6822 * Search for an attribute associated to a node
6823 * This attribute has to be anchored in the namespace specified.
6824 * This does the entity substitution.
6825 * This function looks in DTD attribute declaration for #FIXED or
6826 * default declaration values unless DTD use has been turned off.
6827 * Note that a namespace of NULL indicates to use the default namespace.
6829 * Returns the attribute or the attribute declaration or NULL
6830 * if neither was found.
6833 xmlHasNsProp(const xmlNode
*node
, const xmlChar
*name
, const xmlChar
*nameSpace
) {
6835 return(xmlGetPropNodeInternal(node
, name
, nameSpace
, xmlCheckDTD
));
6841 * @name: the attribute name
6843 * Search and get the value of an attribute associated to a node
6844 * This does the entity substitution.
6845 * This function looks in DTD attribute declaration for #FIXED or
6846 * default declaration values unless DTD use has been turned off.
6847 * NOTE: this function acts independently of namespaces associated
6848 * to the attribute. Use xmlGetNsProp() or xmlGetNoNsProp()
6849 * for namespace aware processing.
6851 * Returns the attribute value or NULL if not found.
6852 * It's up to the caller to free the memory with xmlFree().
6855 xmlGetProp(const xmlNode
*node
, const xmlChar
*name
) {
6858 prop
= xmlHasProp(node
, name
);
6861 return(xmlGetPropNodeValueInternal(prop
));
6867 * @name: the attribute name
6869 * Search and get the value of an attribute associated to a node
6870 * This does the entity substitution.
6871 * This function looks in DTD attribute declaration for #FIXED or
6872 * default declaration values unless DTD use has been turned off.
6873 * This function is similar to xmlGetProp except it will accept only
6874 * an attribute in no namespace.
6876 * Returns the attribute value or NULL if not found.
6877 * It's up to the caller to free the memory with xmlFree().
6880 xmlGetNoNsProp(const xmlNode
*node
, const xmlChar
*name
) {
6883 prop
= xmlGetPropNodeInternal(node
, name
, NULL
, xmlCheckDTD
);
6886 return(xmlGetPropNodeValueInternal(prop
));
6892 * @name: the attribute name
6893 * @nameSpace: the URI of the namespace
6895 * Search and get the value of an attribute associated to a node
6896 * This attribute has to be anchored in the namespace specified.
6897 * This does the entity substitution.
6898 * This function looks in DTD attribute declaration for #FIXED or
6899 * default declaration values unless DTD use has been turned off.
6901 * Returns the attribute value or NULL if not found.
6902 * It's up to the caller to free the memory with xmlFree().
6905 xmlGetNsProp(const xmlNode
*node
, const xmlChar
*name
, const xmlChar
*nameSpace
) {
6908 prop
= xmlGetPropNodeInternal(node
, name
, nameSpace
, xmlCheckDTD
);
6911 return(xmlGetPropNodeValueInternal(prop
));
6914 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
6918 * @name: the attribute name
6920 * Remove an attribute carried by a node.
6921 * This handles only attributes in no namespace.
6922 * Returns 0 if successful, -1 if not found
6925 xmlUnsetProp(xmlNodePtr node
, const xmlChar
*name
) {
6928 prop
= xmlGetPropNodeInternal(node
, name
, NULL
, 0);
6931 xmlUnlinkNode((xmlNodePtr
) prop
);
6939 * @ns: the namespace definition
6940 * @name: the attribute name
6942 * Remove an attribute carried by a node.
6943 * Returns 0 if successful, -1 if not found
6946 xmlUnsetNsProp(xmlNodePtr node
, xmlNsPtr ns
, const xmlChar
*name
) {
6949 prop
= xmlGetPropNodeInternal(node
, name
, (ns
!= NULL
) ? ns
->href
: NULL
, 0);
6952 xmlUnlinkNode((xmlNodePtr
) prop
);
6958 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XINCLUDE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) || defined(LIBXML_HTML_ENABLED)
6962 * @name: the attribute name (a QName)
6963 * @value: the attribute value
6965 * Set (or reset) an attribute carried by a node.
6966 * If @name has a prefix, then the corresponding
6967 * namespace-binding will be used, if in scope; it is an
6968 * error it there's no such ns-binding for the prefix in
6970 * Returns the attribute pointer.
6974 xmlSetProp(xmlNodePtr node
, const xmlChar
*name
, const xmlChar
*value
) {
6976 const xmlChar
*nqname
;
6978 if ((node
== NULL
) || (name
== NULL
) || (node
->type
!= XML_ELEMENT_NODE
))
6984 nqname
= xmlSplitQName3(name
, &len
);
6985 if (nqname
!= NULL
) {
6987 xmlChar
*prefix
= xmlStrndup(name
, len
);
6988 ns
= xmlSearchNs(node
->doc
, node
, prefix
);
6992 return(xmlSetNsProp(node
, ns
, nqname
, value
));
6994 return(xmlSetNsProp(node
, NULL
, name
, value
));
7000 * @ns: the namespace definition
7001 * @name: the attribute name
7002 * @value: the attribute value
7004 * Set (or reset) an attribute carried by a node.
7005 * The ns structure must be in scope, this is not checked
7007 * Returns the attribute pointer.
7010 xmlSetNsProp(xmlNodePtr node
, xmlNsPtr ns
, const xmlChar
*name
,
7011 const xmlChar
*value
)
7015 if (ns
&& (ns
->href
== NULL
))
7017 prop
= xmlGetPropNodeInternal(node
, name
, (ns
!= NULL
) ? ns
->href
: NULL
, 0);
7020 * Modify the attribute's value.
7022 if (prop
->atype
== XML_ATTRIBUTE_ID
) {
7023 xmlRemoveID(node
->doc
, prop
);
7024 prop
->atype
= XML_ATTRIBUTE_ID
;
7026 if (prop
->children
!= NULL
)
7027 xmlFreeNodeList(prop
->children
);
7028 prop
->children
= NULL
;
7031 if (value
!= NULL
) {
7034 prop
->children
= xmlNewDocText(node
->doc
, value
);
7036 tmp
= prop
->children
;
7037 while (tmp
!= NULL
) {
7038 tmp
->parent
= (xmlNodePtr
) prop
;
7039 if (tmp
->next
== NULL
)
7044 if (prop
->atype
== XML_ATTRIBUTE_ID
)
7045 xmlAddID(NULL
, node
->doc
, value
, prop
);
7049 * No equal attr found; create a new one.
7051 return(xmlNewPropInternal(node
, ns
, name
, value
, 0));
7054 #endif /* LIBXML_TREE_ENABLED */
7060 * Is this node a Text node ?
7061 * Returns 1 yes, 0 no
7064 xmlNodeIsText(const xmlNode
*node
) {
7065 if (node
== NULL
) return(0);
7067 if (node
->type
== XML_TEXT_NODE
) return(1);
7075 * Checks whether this node is an empty or whitespace only
7076 * (and possibly ignorable) text-node.
7078 * Returns 1 yes, 0 no
7081 xmlIsBlankNode(const xmlNode
*node
) {
7083 if (node
== NULL
) return(0);
7085 if ((node
->type
!= XML_TEXT_NODE
) &&
7086 (node
->type
!= XML_CDATA_SECTION_NODE
))
7088 if (node
->content
== NULL
) return(1);
7089 cur
= node
->content
;
7091 if (!IS_BLANK_CH(*cur
)) return(0);
7101 * @content: the content
7102 * @len: @content length
7104 * Concat the given string at the end of the existing node content
7106 * Returns -1 in case of error, 0 otherwise
7110 xmlTextConcat(xmlNodePtr node
, const xmlChar
*content
, int len
) {
7111 if (node
== NULL
) return(-1);
7113 if ((node
->type
!= XML_TEXT_NODE
) &&
7114 (node
->type
!= XML_CDATA_SECTION_NODE
) &&
7115 (node
->type
!= XML_COMMENT_NODE
) &&
7116 (node
->type
!= XML_PI_NODE
)) {
7118 xmlGenericError(xmlGenericErrorContext
,
7119 "xmlTextConcat: node is not text nor CDATA\n");
7123 /* need to check if content is currently in the dictionary */
7124 if ((node
->content
== (xmlChar
*) &(node
->properties
)) ||
7125 ((node
->doc
!= NULL
) && (node
->doc
->dict
!= NULL
) &&
7126 xmlDictOwns(node
->doc
->dict
, node
->content
))) {
7127 node
->content
= xmlStrncatNew(node
->content
, content
, len
);
7129 node
->content
= xmlStrncat(node
->content
, content
, len
);
7131 node
->properties
= NULL
;
7132 if (node
->content
== NULL
)
7137 /************************************************************************
7139 * Output : to a FILE or in memory *
7141 ************************************************************************/
7146 * routine to create an XML buffer.
7147 * returns the new structure.
7150 xmlBufferCreate(void) {
7153 ret
= (xmlBufferPtr
) xmlMalloc(sizeof(xmlBuffer
));
7155 xmlTreeErrMemory("creating buffer");
7159 ret
->size
= xmlDefaultBufferSize
;
7160 ret
->alloc
= xmlBufferAllocScheme
;
7161 ret
->content
= (xmlChar
*) xmlMallocAtomic(ret
->size
);
7162 if (ret
->content
== NULL
) {
7163 xmlTreeErrMemory("creating buffer");
7167 ret
->content
[0] = 0;
7168 ret
->contentIO
= NULL
;
7173 * xmlBufferCreateSize:
7174 * @size: initial size of buffer
7176 * routine to create an XML buffer.
7177 * returns the new structure.
7180 xmlBufferCreateSize(size_t size
) {
7183 if (size
>= UINT_MAX
)
7185 ret
= (xmlBufferPtr
) xmlMalloc(sizeof(xmlBuffer
));
7187 xmlTreeErrMemory("creating buffer");
7191 ret
->alloc
= xmlBufferAllocScheme
;
7192 ret
->size
= (size
? size
+ 1 : 0); /* +1 for ending null */
7194 ret
->content
= (xmlChar
*) xmlMallocAtomic(ret
->size
);
7195 if (ret
->content
== NULL
) {
7196 xmlTreeErrMemory("creating buffer");
7200 ret
->content
[0] = 0;
7202 ret
->content
= NULL
;
7203 ret
->contentIO
= NULL
;
7211 * Remove the string contained in a buffer and gie it back to the
7212 * caller. The buffer is reset to an empty content.
7213 * This doesn't work with immutable buffers as they can't be reset.
7215 * Returns the previous string contained by the buffer.
7218 xmlBufferDetach(xmlBufferPtr buf
) {
7225 buf
->content
= NULL
;
7234 * xmlBufferCreateStatic:
7235 * @mem: the memory area
7236 * @size: the size in byte
7238 * Create an XML buffer initialized with bytes.
7241 xmlBufferCreateStatic(void *mem
, size_t size
) {
7242 xmlBufferPtr buf
= xmlBufferCreateSize(size
);
7244 xmlBufferAdd(buf
, mem
, size
);
7249 * xmlBufferSetAllocationScheme:
7250 * @buf: the buffer to tune
7251 * @scheme: allocation scheme to use
7253 * Sets the allocation scheme for this buffer
7256 xmlBufferSetAllocationScheme(xmlBufferPtr buf
,
7257 xmlBufferAllocationScheme scheme
) {
7260 xmlGenericError(xmlGenericErrorContext
,
7261 "xmlBufferSetAllocationScheme: buf == NULL\n");
7265 if (buf
->alloc
== XML_BUFFER_ALLOC_IO
) return;
7266 if ((scheme
== XML_BUFFER_ALLOC_DOUBLEIT
) ||
7267 (scheme
== XML_BUFFER_ALLOC_EXACT
) ||
7268 (scheme
== XML_BUFFER_ALLOC_HYBRID
))
7269 buf
->alloc
= scheme
;
7274 * @buf: the buffer to free
7276 * Frees an XML buffer. It frees both the content and the structure which
7280 xmlBufferFree(xmlBufferPtr buf
) {
7283 xmlGenericError(xmlGenericErrorContext
,
7284 "xmlBufferFree: buf == NULL\n");
7289 if ((buf
->alloc
== XML_BUFFER_ALLOC_IO
) &&
7290 (buf
->contentIO
!= NULL
)) {
7291 xmlFree(buf
->contentIO
);
7292 } else if (buf
->content
!= NULL
) {
7293 xmlFree(buf
->content
);
7305 xmlBufferEmpty(xmlBufferPtr buf
) {
7306 if (buf
== NULL
) return;
7307 if (buf
->content
== NULL
) return;
7309 if ((buf
->alloc
== XML_BUFFER_ALLOC_IO
) && (buf
->contentIO
!= NULL
)) {
7310 size_t start_buf
= buf
->content
- buf
->contentIO
;
7312 buf
->size
+= start_buf
;
7313 buf
->content
= buf
->contentIO
;
7314 buf
->content
[0] = 0;
7316 buf
->content
[0] = 0;
7322 * @buf: the buffer to dump
7323 * @len: the number of xmlChar to remove
7325 * Remove the beginning of an XML buffer.
7327 * Returns the number of #xmlChar removed, or -1 in case of failure.
7330 xmlBufferShrink(xmlBufferPtr buf
, unsigned int len
) {
7331 if (buf
== NULL
) return(-1);
7332 if (len
== 0) return(0);
7333 if (len
> buf
->use
) return(-1);
7336 if ((buf
->alloc
== XML_BUFFER_ALLOC_IO
) && (buf
->contentIO
!= NULL
)) {
7338 * we just move the content pointer, but also make sure
7339 * the perceived buffer size has shrunk accordingly
7341 buf
->content
+= len
;
7345 * sometimes though it maybe be better to really shrink
7348 if ((buf
->alloc
== XML_BUFFER_ALLOC_IO
) && (buf
->contentIO
!= NULL
)) {
7349 size_t start_buf
= buf
->content
- buf
->contentIO
;
7350 if (start_buf
>= buf
->size
) {
7351 memmove(buf
->contentIO
, &buf
->content
[0], buf
->use
);
7352 buf
->content
= buf
->contentIO
;
7353 buf
->content
[buf
->use
] = 0;
7354 buf
->size
+= start_buf
;
7358 memmove(buf
->content
, &buf
->content
[len
], buf
->use
);
7359 buf
->content
[buf
->use
] = 0;
7367 * @len: the minimum free size to allocate
7369 * Grow the available space of an XML buffer.
7371 * Returns the new available space or -1 in case of error
7374 xmlBufferGrow(xmlBufferPtr buf
, unsigned int len
) {
7378 if (buf
== NULL
) return(-1);
7380 if (len
< buf
->size
- buf
->use
)
7382 if (len
>= UINT_MAX
- buf
->use
) {
7383 xmlTreeErrMemory("growing buffer past UINT_MAX");
7387 if (buf
->size
> (size_t) len
) {
7388 size
= buf
->size
> UINT_MAX
/ 2 ? UINT_MAX
: buf
->size
* 2;
7390 size
= buf
->use
+ len
;
7391 size
= size
> UINT_MAX
- 100 ? UINT_MAX
: size
+ 100;
7394 if ((buf
->alloc
== XML_BUFFER_ALLOC_IO
) && (buf
->contentIO
!= NULL
)) {
7395 size_t start_buf
= buf
->content
- buf
->contentIO
;
7397 newbuf
= (xmlChar
*) xmlRealloc(buf
->contentIO
, start_buf
+ size
);
7398 if (newbuf
== NULL
) {
7399 xmlTreeErrMemory("growing buffer");
7402 buf
->contentIO
= newbuf
;
7403 buf
->content
= newbuf
+ start_buf
;
7405 newbuf
= (xmlChar
*) xmlRealloc(buf
->content
, size
);
7406 if (newbuf
== NULL
) {
7407 xmlTreeErrMemory("growing buffer");
7410 buf
->content
= newbuf
;
7413 return(buf
->size
- buf
->use
- 1);
7418 * @file: the file output
7419 * @buf: the buffer to dump
7421 * Dumps an XML buffer to a FILE *.
7422 * Returns the number of #xmlChar written
7425 xmlBufferDump(FILE *file
, xmlBufferPtr buf
) {
7430 xmlGenericError(xmlGenericErrorContext
,
7431 "xmlBufferDump: buf == NULL\n");
7435 if (buf
->content
== NULL
) {
7437 xmlGenericError(xmlGenericErrorContext
,
7438 "xmlBufferDump: buf->content == NULL\n");
7444 ret
= fwrite(buf
->content
, 1, buf
->use
, file
);
7445 return(ret
> INT_MAX
? INT_MAX
: ret
);
7452 * Function to extract the content of a buffer
7454 * Returns the internal content
7458 xmlBufferContent(const xmlBuffer
*buf
)
7463 return buf
->content
;
7470 * Function to get the length of a buffer
7472 * Returns the length of data in the internal content
7476 xmlBufferLength(const xmlBuffer
*buf
)
7486 * @buf: the buffer to resize
7487 * @size: the desired size
7489 * Resize a buffer to accommodate minimum size of @size.
7491 * Returns 0 in case of problems, 1 otherwise
7494 xmlBufferResize(xmlBufferPtr buf
, unsigned int size
)
7496 unsigned int newSize
;
7497 xmlChar
* rebuf
= NULL
;
7503 /* Don't resize if we don't have to */
7504 if (size
< buf
->size
)
7507 if (size
> UINT_MAX
- 10) {
7508 xmlTreeErrMemory("growing buffer past UINT_MAX");
7512 /* figure out new size */
7513 switch (buf
->alloc
){
7514 case XML_BUFFER_ALLOC_IO
:
7515 case XML_BUFFER_ALLOC_DOUBLEIT
:
7516 /*take care of empty case*/
7518 newSize
= (size
> UINT_MAX
- 10 ? UINT_MAX
: size
+ 10);
7520 newSize
= buf
->size
;
7521 while (size
> newSize
) {
7522 if (newSize
> UINT_MAX
/ 2) {
7523 xmlTreeErrMemory("growing buffer");
7529 case XML_BUFFER_ALLOC_EXACT
:
7530 newSize
= (size
> UINT_MAX
- 10 ? UINT_MAX
: size
+ 10);
7532 case XML_BUFFER_ALLOC_HYBRID
:
7533 if (buf
->use
< BASE_BUFFER_SIZE
)
7536 newSize
= buf
->size
;
7537 while (size
> newSize
) {
7538 if (newSize
> UINT_MAX
/ 2) {
7539 xmlTreeErrMemory("growing buffer");
7548 newSize
= (size
> UINT_MAX
- 10 ? UINT_MAX
: size
+ 10);
7552 if ((buf
->alloc
== XML_BUFFER_ALLOC_IO
) && (buf
->contentIO
!= NULL
)) {
7553 start_buf
= buf
->content
- buf
->contentIO
;
7555 if (start_buf
> newSize
) {
7556 /* move data back to start */
7557 memmove(buf
->contentIO
, buf
->content
, buf
->use
);
7558 buf
->content
= buf
->contentIO
;
7559 buf
->content
[buf
->use
] = 0;
7560 buf
->size
+= start_buf
;
7562 rebuf
= (xmlChar
*) xmlRealloc(buf
->contentIO
, start_buf
+ newSize
);
7563 if (rebuf
== NULL
) {
7564 xmlTreeErrMemory("growing buffer");
7567 buf
->contentIO
= rebuf
;
7568 buf
->content
= rebuf
+ start_buf
;
7571 if (buf
->content
== NULL
) {
7572 rebuf
= (xmlChar
*) xmlMallocAtomic(newSize
);
7574 rebuf
[buf
->use
] = 0;
7575 } else if (buf
->size
- buf
->use
< 100) {
7576 rebuf
= (xmlChar
*) xmlRealloc(buf
->content
, newSize
);
7579 * if we are reallocating a buffer far from being full, it's
7580 * better to make a new allocation and copy only the used range
7581 * and free the old one.
7583 rebuf
= (xmlChar
*) xmlMallocAtomic(newSize
);
7584 if (rebuf
!= NULL
) {
7585 memcpy(rebuf
, buf
->content
, buf
->use
);
7586 xmlFree(buf
->content
);
7587 rebuf
[buf
->use
] = 0;
7590 if (rebuf
== NULL
) {
7591 xmlTreeErrMemory("growing buffer");
7594 buf
->content
= rebuf
;
7596 buf
->size
= newSize
;
7603 * @buf: the buffer to dump
7604 * @str: the #xmlChar string
7605 * @len: the number of #xmlChar to add
7607 * Add a string range to an XML buffer. if len == -1, the length of
7608 * str is recomputed.
7610 * Returns 0 successful, a positive error code number otherwise
7611 * and -1 in case of internal or API error.
7614 xmlBufferAdd(xmlBufferPtr buf
, const xmlChar
*str
, int len
) {
7615 unsigned int needSize
;
7617 if ((str
== NULL
) || (buf
== NULL
)) {
7622 xmlGenericError(xmlGenericErrorContext
,
7623 "xmlBufferAdd: len < 0\n");
7627 if (len
== 0) return 0;
7630 len
= xmlStrlen(str
);
7632 if (len
< 0) return -1;
7633 if (len
== 0) return 0;
7635 /* Note that both buf->size and buf->use can be zero here. */
7636 if ((unsigned) len
>= buf
->size
- buf
->use
) {
7637 if ((unsigned) len
>= UINT_MAX
- buf
->use
) {
7638 xmlTreeErrMemory("growing buffer past UINT_MAX");
7639 return XML_ERR_NO_MEMORY
;
7641 needSize
= buf
->use
+ len
+ 1;
7642 if (!xmlBufferResize(buf
, needSize
)){
7643 xmlTreeErrMemory("growing buffer");
7644 return XML_ERR_NO_MEMORY
;
7648 memmove(&buf
->content
[buf
->use
], str
, len
);
7650 buf
->content
[buf
->use
] = 0;
7657 * @str: the #xmlChar string
7658 * @len: the number of #xmlChar to add
7660 * Add a string range to the beginning of an XML buffer.
7661 * if len == -1, the length of @str is recomputed.
7663 * Returns 0 successful, a positive error code number otherwise
7664 * and -1 in case of internal or API error.
7667 xmlBufferAddHead(xmlBufferPtr buf
, const xmlChar
*str
, int len
) {
7668 unsigned int needSize
;
7674 xmlGenericError(xmlGenericErrorContext
,
7675 "xmlBufferAddHead: str == NULL\n");
7681 xmlGenericError(xmlGenericErrorContext
,
7682 "xmlBufferAddHead: len < 0\n");
7686 if (len
== 0) return 0;
7689 len
= xmlStrlen(str
);
7691 if (len
<= 0) return -1;
7693 if ((buf
->alloc
== XML_BUFFER_ALLOC_IO
) && (buf
->contentIO
!= NULL
)) {
7694 size_t start_buf
= buf
->content
- buf
->contentIO
;
7696 if (start_buf
> (unsigned int) len
) {
7698 * We can add it in the space previously shrunk
7700 buf
->content
-= len
;
7701 memmove(&buf
->content
[0], str
, len
);
7704 buf
->content
[buf
->use
] = 0;
7708 /* Note that both buf->size and buf->use can be zero here. */
7709 if ((unsigned) len
>= buf
->size
- buf
->use
) {
7710 if ((unsigned) len
>= UINT_MAX
- buf
->use
) {
7711 xmlTreeErrMemory("growing buffer past UINT_MAX");
7714 needSize
= buf
->use
+ len
+ 1;
7715 if (!xmlBufferResize(buf
, needSize
)){
7716 xmlTreeErrMemory("growing buffer");
7717 return XML_ERR_NO_MEMORY
;
7721 memmove(&buf
->content
[len
], &buf
->content
[0], buf
->use
);
7722 memmove(&buf
->content
[0], str
, len
);
7724 buf
->content
[buf
->use
] = 0;
7730 * @buf: the buffer to add to
7731 * @str: the #xmlChar string
7733 * Append a zero terminated string to an XML buffer.
7735 * Returns 0 successful, a positive error code number otherwise
7736 * and -1 in case of internal or API error.
7739 xmlBufferCat(xmlBufferPtr buf
, const xmlChar
*str
) {
7742 if (str
== NULL
) return -1;
7743 return xmlBufferAdd(buf
, str
, -1);
7748 * @buf: the buffer to dump
7749 * @str: the C char string
7751 * Append a zero terminated C string to an XML buffer.
7753 * Returns 0 successful, a positive error code number otherwise
7754 * and -1 in case of internal or API error.
7757 xmlBufferCCat(xmlBufferPtr buf
, const char *str
) {
7758 return xmlBufferCat(buf
, (const xmlChar
*) str
);
7762 * xmlBufferWriteCHAR:
7763 * @buf: the XML buffer
7764 * @string: the string to add
7766 * routine which manages and grows an output buffer. This one adds
7767 * xmlChars at the end of the buffer.
7770 xmlBufferWriteCHAR(xmlBufferPtr buf
, const xmlChar
*string
) {
7773 xmlBufferCat(buf
, string
);
7777 * xmlBufferWriteChar:
7778 * @buf: the XML buffer output
7779 * @string: the string to add
7781 * routine which manage and grows an output buffer. This one add
7782 * C chars at the end of the array.
7785 xmlBufferWriteChar(xmlBufferPtr buf
, const char *string
) {
7788 xmlBufferCCat(buf
, string
);
7793 * xmlBufferWriteQuotedString:
7794 * @buf: the XML buffer output
7795 * @string: the string to add
7797 * routine which manage and grows an output buffer. This one writes
7798 * a quoted or double quoted #xmlChar string, checking first if it holds
7799 * quote or double-quotes internally
7802 xmlBufferWriteQuotedString(xmlBufferPtr buf
, const xmlChar
*string
) {
7803 const xmlChar
*cur
, *base
;
7806 if (xmlStrchr(string
, '\"')) {
7807 if (xmlStrchr(string
, '\'')) {
7809 xmlGenericError(xmlGenericErrorContext
,
7810 "xmlBufferWriteQuotedString: string contains quote and double-quotes !\n");
7812 xmlBufferCCat(buf
, "\"");
7813 base
= cur
= string
;
7817 xmlBufferAdd(buf
, base
, cur
- base
);
7818 xmlBufferAdd(buf
, BAD_CAST
""", 6);
7827 xmlBufferAdd(buf
, base
, cur
- base
);
7828 xmlBufferCCat(buf
, "\"");
7831 xmlBufferCCat(buf
, "\'");
7832 xmlBufferCat(buf
, string
);
7833 xmlBufferCCat(buf
, "\'");
7836 xmlBufferCCat(buf
, "\"");
7837 xmlBufferCat(buf
, string
);
7838 xmlBufferCCat(buf
, "\"");
7844 * xmlGetDocCompressMode:
7845 * @doc: the document
7847 * get the compression ratio for a document, ZLIB based
7848 * Returns 0 (uncompressed) to 9 (max compression)
7851 xmlGetDocCompressMode (const xmlDoc
*doc
) {
7852 if (doc
== NULL
) return(-1);
7853 return(doc
->compression
);
7857 * xmlSetDocCompressMode:
7858 * @doc: the document
7859 * @mode: the compression ratio
7861 * set the compression ratio for a document, ZLIB based
7862 * Correct values: 0 (uncompressed) to 9 (max compression)
7865 xmlSetDocCompressMode (xmlDocPtr doc
, int mode
) {
7866 if (doc
== NULL
) return;
7867 if (mode
< 0) doc
->compression
= 0;
7868 else if (mode
> 9) doc
->compression
= 9;
7869 else doc
->compression
= mode
;
7873 * xmlGetCompressMode:
7875 * get the default compression mode used, ZLIB based.
7876 * Returns 0 (uncompressed) to 9 (max compression)
7879 xmlGetCompressMode(void)
7881 return (xmlCompressMode
);
7885 * xmlSetCompressMode:
7886 * @mode: the compression ratio
7888 * set the default compression mode used, ZLIB based
7889 * Correct values: 0 (uncompressed) to 9 (max compression)
7892 xmlSetCompressMode(int mode
) {
7893 if (mode
< 0) xmlCompressMode
= 0;
7894 else if (mode
> 9) xmlCompressMode
= 9;
7895 else xmlCompressMode
= mode
;
7898 #define XML_TREE_NSMAP_PARENT -1
7899 #define XML_TREE_NSMAP_XML -2
7900 #define XML_TREE_NSMAP_DOC -3
7901 #define XML_TREE_NSMAP_CUSTOM -4
7903 typedef struct xmlNsMapItem
*xmlNsMapItemPtr
;
7904 struct xmlNsMapItem
{
7905 xmlNsMapItemPtr next
;
7906 xmlNsMapItemPtr prev
;
7907 xmlNsPtr oldNs
; /* old ns decl reference */
7908 xmlNsPtr newNs
; /* new ns decl reference */
7909 int shadowDepth
; /* Shadowed at this depth */
7912 * >= 0 == @node's ns-decls
7913 * -1 == @parent's ns-decls
7914 * -2 == the doc->oldNs XML ns-decl
7915 * -3 == the doc->oldNs storage ns-decls
7916 * -4 == ns-decls provided via custom ns-handling
7921 typedef struct xmlNsMap
*xmlNsMapPtr
;
7923 xmlNsMapItemPtr first
;
7924 xmlNsMapItemPtr last
;
7925 xmlNsMapItemPtr pool
;
7928 #define XML_NSMAP_NOTEMPTY(m) (((m) != NULL) && ((m)->first != NULL))
7929 #define XML_NSMAP_FOREACH(m, i) for (i = (m)->first; i != NULL; i = (i)->next)
7930 #define XML_NSMAP_POP(m, i) \
7932 (m)->last = (i)->prev; \
7933 if ((m)->last == NULL) \
7934 (m)->first = NULL; \
7936 (m)->last->next = NULL; \
7937 (i)->next = (m)->pool; \
7941 * xmlDOMWrapNsMapFree:
7947 xmlDOMWrapNsMapFree(xmlNsMapPtr nsmap
)
7949 xmlNsMapItemPtr cur
, tmp
;
7954 while (cur
!= NULL
) {
7960 while (cur
!= NULL
) {
7969 * xmlDOMWrapNsMapAddItem:
7971 * @oldNs: the old ns-struct
7972 * @newNs: the new ns-struct
7973 * @depth: depth and ns-kind information
7975 * Adds an ns-mapping item.
7977 static xmlNsMapItemPtr
7978 xmlDOMWrapNsMapAddItem(xmlNsMapPtr
*nsmap
, int position
,
7979 xmlNsPtr oldNs
, xmlNsPtr newNs
, int depth
)
7981 xmlNsMapItemPtr ret
;
7986 if ((position
!= -1) && (position
!= 0))
7992 * Create the ns-map.
7994 map
= (xmlNsMapPtr
) xmlMalloc(sizeof(struct xmlNsMap
));
7996 xmlTreeErrMemory("allocating namespace map");
7999 memset(map
, 0, sizeof(struct xmlNsMap
));
8003 if (map
->pool
!= NULL
) {
8005 * Reuse an item from the pool.
8008 map
->pool
= ret
->next
;
8009 memset(ret
, 0, sizeof(struct xmlNsMapItem
));
8012 * Create a new item.
8014 ret
= (xmlNsMapItemPtr
) xmlMalloc(sizeof(struct xmlNsMapItem
));
8016 xmlTreeErrMemory("allocating namespace map item");
8019 memset(ret
, 0, sizeof(struct xmlNsMapItem
));
8022 if (map
->first
== NULL
) {
8028 } else if (position
== -1) {
8032 ret
->prev
= map
->last
;
8033 map
->last
->next
= ret
;
8035 } else if (position
== 0) {
8037 * Set on first position.
8039 map
->first
->prev
= ret
;
8040 ret
->next
= map
->first
;
8046 ret
->shadowDepth
= -1;
8052 * xmlDOMWrapStoreNs:
8054 * @nsName: the namespace name
8055 * @prefix: the prefix
8057 * Creates or reuses an xmlNs struct on doc->oldNs with
8058 * the given prefix and namespace name.
8060 * Returns the acquired ns struct or NULL in case of an API
8061 * or internal error.
8064 xmlDOMWrapStoreNs(xmlDocPtr doc
,
8065 const xmlChar
*nsName
,
8066 const xmlChar
*prefix
)
8072 ns
= xmlTreeEnsureXMLDecl(doc
);
8075 if (ns
->next
!= NULL
) {
8078 while (ns
!= NULL
) {
8079 if (((ns
->prefix
== prefix
) ||
8080 xmlStrEqual(ns
->prefix
, prefix
)) &&
8081 xmlStrEqual(ns
->href
, nsName
)) {
8084 if (ns
->next
== NULL
)
8091 ns
->next
= xmlNewNs(NULL
, nsName
, prefix
);
8098 * xmlDOMWrapNewCtxt:
8100 * Allocates and initializes a new DOM-wrapper context.
8102 * Returns the xmlDOMWrapCtxtPtr or NULL in case of an internal error.
8105 xmlDOMWrapNewCtxt(void)
8107 xmlDOMWrapCtxtPtr ret
;
8109 ret
= xmlMalloc(sizeof(xmlDOMWrapCtxt
));
8111 xmlTreeErrMemory("allocating DOM-wrapper context");
8114 memset(ret
, 0, sizeof(xmlDOMWrapCtxt
));
8119 * xmlDOMWrapFreeCtxt:
8120 * @ctxt: the DOM-wrapper context
8122 * Frees the DOM-wrapper context.
8125 xmlDOMWrapFreeCtxt(xmlDOMWrapCtxtPtr ctxt
)
8129 if (ctxt
->namespaceMap
!= NULL
)
8130 xmlDOMWrapNsMapFree((xmlNsMapPtr
) ctxt
->namespaceMap
);
8132 * TODO: Store the namespace map in the context.
8138 * xmlTreeLookupNsListByPrefix:
8139 * @nsList: a list of ns-structs
8140 * @prefix: the searched prefix
8142 * Searches for a ns-decl with the given prefix in @nsList.
8144 * Returns the ns-decl if found, NULL if not found and on
8148 xmlTreeNSListLookupByPrefix(xmlNsPtr nsList
, const xmlChar
*prefix
)
8156 if ((prefix
== ns
->prefix
) ||
8157 xmlStrEqual(prefix
, ns
->prefix
)) {
8161 } while (ns
!= NULL
);
8168 * xmlDOMWrapNSNormGatherInScopeNs:
8169 * @map: the namespace map
8170 * @node: the node to start with
8172 * Puts in-scope namespaces into the ns-map.
8174 * Returns 0 on success, -1 on API or internal errors.
8177 xmlDOMWrapNSNormGatherInScopeNs(xmlNsMapPtr
*map
,
8185 if ((map
== NULL
) || (*map
!= NULL
))
8187 if ((node
== NULL
) || (node
->type
== XML_NAMESPACE_DECL
))
8190 * Get in-scope ns-decls of @parent.
8193 while ((cur
!= NULL
) && (cur
!= (xmlNodePtr
) cur
->doc
)) {
8194 if (cur
->type
== XML_ELEMENT_NODE
) {
8195 if (cur
->nsDef
!= NULL
) {
8199 if (XML_NSMAP_NOTEMPTY(*map
)) {
8201 * Skip shadowed prefixes.
8203 XML_NSMAP_FOREACH(*map
, mi
) {
8204 if ((ns
->prefix
== mi
->newNs
->prefix
) ||
8205 xmlStrEqual(ns
->prefix
, mi
->newNs
->prefix
)) {
8214 mi
= xmlDOMWrapNsMapAddItem(map
, 0, NULL
,
8215 ns
, XML_TREE_NSMAP_PARENT
);
8219 mi
->shadowDepth
= 0;
8221 } while (ns
!= NULL
);
8230 * XML_TREE_ADOPT_STR: If we have a dest-dict, put @str in the dict;
8231 * otherwise copy it, when it was in the source-dict.
8233 #define XML_TREE_ADOPT_STR(str) \
8234 if (adoptStr && (str != NULL)) { \
8235 if (destDoc->dict) { \
8236 const xmlChar *old = str; \
8237 str = xmlDictLookup(destDoc->dict, str, -1); \
8238 if ((sourceDoc == NULL) || (sourceDoc->dict == NULL) || \
8239 (!xmlDictOwns(sourceDoc->dict, old))) \
8240 xmlFree((char *)old); \
8241 } else if ((sourceDoc) && (sourceDoc->dict) && \
8242 xmlDictOwns(sourceDoc->dict, str)) { \
8243 str = BAD_CAST xmlStrdup(str); \
8248 * XML_TREE_ADOPT_STR_2: If @str was in the source-dict, then
8249 * put it in dest-dict or copy it.
8251 #define XML_TREE_ADOPT_STR_2(str) \
8252 if (adoptStr && (str != NULL) && (sourceDoc != NULL) && \
8253 (sourceDoc->dict != NULL) && \
8254 xmlDictOwns(sourceDoc->dict, cur->content)) { \
8255 if (destDoc->dict) \
8256 cur->content = (xmlChar *) \
8257 xmlDictLookup(destDoc->dict, cur->content, -1); \
8259 cur->content = xmlStrdup(BAD_CAST cur->content); \
8263 * xmlDOMWrapNSNormAddNsMapItem2:
8265 * For internal use. Adds a ns-decl mapping.
8267 * Returns 0 on success, -1 on internal errors.
8270 xmlDOMWrapNSNormAddNsMapItem2(xmlNsPtr
**list
, int *size
, int *number
,
8271 xmlNsPtr oldNs
, xmlNsPtr newNs
)
8273 if (*list
== NULL
) {
8274 *list
= (xmlNsPtr
*) xmlMalloc(6 * sizeof(xmlNsPtr
));
8275 if (*list
== NULL
) {
8276 xmlTreeErrMemory("alloc ns map item");
8281 } else if ((*number
) >= (*size
)) {
8283 *list
= (xmlNsPtr
*) xmlRealloc(*list
,
8284 (*size
) * 2 * sizeof(xmlNsPtr
));
8285 if (*list
== NULL
) {
8286 xmlTreeErrMemory("realloc ns map item");
8290 (*list
)[2 * (*number
)] = oldNs
;
8291 (*list
)[2 * (*number
) +1] = newNs
;
8297 * xmlDOMWrapRemoveNode:
8298 * @ctxt: a DOM wrapper context
8300 * @node: the node to be removed.
8301 * @options: set of options, unused at the moment
8303 * Unlinks the given node from its owner.
8304 * This will substitute ns-references to node->nsDef for
8305 * ns-references to doc->oldNs, thus ensuring the removed
8306 * branch to be autark wrt ns-references.
8308 * NOTE: This function was not intensively tested.
8310 * Returns 0 on success, 1 if the node is not supported,
8311 * -1 on API and internal errors.
8314 xmlDOMWrapRemoveNode(xmlDOMWrapCtxtPtr ctxt
, xmlDocPtr doc
,
8315 xmlNodePtr node
, int options ATTRIBUTE_UNUSED
)
8317 xmlNsPtr
*list
= NULL
;
8318 int sizeList
, nbList
, i
, j
;
8321 if ((node
== NULL
) || (doc
== NULL
) || (node
->doc
!= doc
))
8324 /* TODO: 0 or -1 ? */
8325 if (node
->parent
== NULL
)
8328 switch (node
->type
) {
8330 case XML_CDATA_SECTION_NODE
:
8331 case XML_ENTITY_REF_NODE
:
8333 case XML_COMMENT_NODE
:
8334 xmlUnlinkNode(node
);
8336 case XML_ELEMENT_NODE
:
8337 case XML_ATTRIBUTE_NODE
:
8342 xmlUnlinkNode(node
);
8344 * Save out-of-scope ns-references in doc->oldNs.
8347 switch (node
->type
) {
8348 case XML_ELEMENT_NODE
:
8349 if ((ctxt
== NULL
) && (node
->nsDef
!= NULL
)) {
8352 if (xmlDOMWrapNSNormAddNsMapItem2(&list
, &sizeList
,
8353 &nbList
, ns
, ns
) == -1)
8354 goto internal_error
;
8356 } while (ns
!= NULL
);
8358 /* Falls through. */
8359 case XML_ATTRIBUTE_NODE
:
8360 if (node
->ns
!= NULL
) {
8365 for (i
= 0, j
= 0; i
< nbList
; i
++, j
+= 2) {
8366 if (node
->ns
== list
[j
]) {
8367 node
->ns
= list
[++j
];
8379 * Add to doc's oldNs.
8381 ns
= xmlDOMWrapStoreNs(doc
, node
->ns
->href
,
8384 goto internal_error
;
8390 if (xmlDOMWrapNSNormAddNsMapItem2(&list
, &sizeList
,
8391 &nbList
, node
->ns
, ns
) == -1)
8392 goto internal_error
;
8396 if ((node
->type
== XML_ELEMENT_NODE
) &&
8397 (node
->properties
!= NULL
)) {
8398 node
= (xmlNodePtr
) node
->properties
;
8406 if ((node
->type
== XML_ELEMENT_NODE
) &&
8407 (node
->children
!= NULL
)) {
8408 node
= node
->children
;
8414 if (node
->next
!= NULL
)
8417 node
= node
->parent
;
8420 } while (node
!= NULL
);
8433 * xmlSearchNsByNamespaceStrict:
8434 * @doc: the document
8435 * @node: the start node
8436 * @nsName: the searched namespace name
8437 * @retNs: the resulting ns-decl
8438 * @prefixed: if the found ns-decl must have a prefix (for attributes)
8440 * Dynamically searches for a ns-declaration which matches
8441 * the given @nsName in the ancestor-or-self axis of @node.
8443 * Returns 1 if a ns-decl was found, 0 if not and -1 on API
8444 * and internal errors.
8447 xmlSearchNsByNamespaceStrict(xmlDocPtr doc
, xmlNodePtr node
,
8448 const xmlChar
* nsName
,
8449 xmlNsPtr
*retNs
, int prefixed
)
8451 xmlNodePtr cur
, prev
= NULL
, out
= NULL
;
8452 xmlNsPtr ns
, prevns
;
8454 if ((doc
== NULL
) || (nsName
== NULL
) || (retNs
== NULL
))
8456 if ((node
== NULL
) || (node
->type
== XML_NAMESPACE_DECL
))
8460 if (xmlStrEqual(nsName
, XML_XML_NAMESPACE
)) {
8461 *retNs
= xmlTreeEnsureXMLDecl(doc
);
8468 if (cur
->type
== XML_ELEMENT_NODE
) {
8469 if (cur
->nsDef
!= NULL
) {
8470 for (ns
= cur
->nsDef
; ns
!= NULL
; ns
= ns
->next
) {
8471 if (prefixed
&& (ns
->prefix
== NULL
))
8475 * Check the last level of ns-decls for a
8478 prevns
= prev
->nsDef
;
8480 if ((prevns
->prefix
== ns
->prefix
) ||
8481 ((prevns
->prefix
!= NULL
) &&
8482 (ns
->prefix
!= NULL
) &&
8483 xmlStrEqual(prevns
->prefix
, ns
->prefix
))) {
8489 prevns
= prevns
->next
;
8490 } while (prevns
!= NULL
);
8495 * Ns-name comparison.
8497 if ((nsName
== ns
->href
) ||
8498 xmlStrEqual(nsName
, ns
->href
)) {
8500 * At this point the prefix can only be shadowed,
8501 * if we are the the (at least) 3rd level of
8507 ret
= xmlNsInScope(doc
, node
, prev
, ns
->prefix
);
8511 * TODO: Should we try to find a matching ns-name
8512 * only once? This here keeps on searching.
8513 * I think we should try further since, there might
8514 * be an other matching ns-decl with an unshadowed
8527 } else if ((cur
->type
== XML_ENTITY_NODE
) ||
8528 (cur
->type
== XML_ENTITY_DECL
))
8531 } while ((cur
!= NULL
) && (cur
->doc
!= (xmlDocPtr
) cur
));
8536 * xmlSearchNsByPrefixStrict:
8537 * @doc: the document
8538 * @node: the start node
8539 * @prefix: the searched namespace prefix
8540 * @retNs: the resulting ns-decl
8542 * Dynamically searches for a ns-declaration which matches
8543 * the given @nsName in the ancestor-or-self axis of @node.
8545 * Returns 1 if a ns-decl was found, 0 if not and -1 on API
8546 * and internal errors.
8549 xmlSearchNsByPrefixStrict(xmlDocPtr doc
, xmlNodePtr node
,
8550 const xmlChar
* prefix
,
8556 if ((doc
== NULL
) || (node
== NULL
) || (node
->type
== XML_NAMESPACE_DECL
))
8561 if (IS_STR_XML(prefix
)) {
8563 *retNs
= xmlTreeEnsureXMLDecl(doc
);
8571 if (cur
->type
== XML_ELEMENT_NODE
) {
8572 if (cur
->nsDef
!= NULL
) {
8575 if ((prefix
== ns
->prefix
) ||
8576 xmlStrEqual(prefix
, ns
->prefix
))
8579 * Disabled namespaces, e.g. xmlns:abc="".
8581 if (ns
->href
== NULL
)
8588 } while (ns
!= NULL
);
8590 } else if ((cur
->type
== XML_ENTITY_NODE
) ||
8591 (cur
->type
== XML_ENTITY_DECL
))
8594 } while ((cur
!= NULL
) && (cur
->doc
!= (xmlDocPtr
) cur
));
8599 * xmlDOMWrapNSNormDeclareNsForced:
8601 * @elem: the element-node to declare on
8602 * @nsName: the namespace-name of the ns-decl
8603 * @prefix: the preferred prefix of the ns-decl
8604 * @checkShadow: ensure that the new ns-decl doesn't shadow ancestor ns-decls
8606 * Declares a new namespace on @elem. It tries to use the
8607 * given @prefix; if a ns-decl with the given prefix is already existent
8608 * on @elem, it will generate an other prefix.
8610 * Returns 1 if a ns-decl was found, 0 if not and -1 on API
8611 * and internal errors.
8614 xmlDOMWrapNSNormDeclareNsForced(xmlDocPtr doc
,
8616 const xmlChar
*nsName
,
8617 const xmlChar
*prefix
,
8623 const xmlChar
*pref
;
8626 if ((doc
== NULL
) || (elem
== NULL
) || (elem
->type
!= XML_ELEMENT_NODE
))
8629 * Create a ns-decl on @anchor.
8634 * Lookup whether the prefix is unused in elem's ns-decls.
8636 if ((elem
->nsDef
!= NULL
) &&
8637 (xmlTreeNSListLookupByPrefix(elem
->nsDef
, pref
) != NULL
))
8638 goto ns_next_prefix
;
8639 if (checkShadow
&& elem
->parent
&&
8640 ((xmlNodePtr
) elem
->parent
->doc
!= elem
->parent
)) {
8642 * Does it shadow ancestor ns-decls?
8644 if (xmlSearchNsByPrefixStrict(doc
, elem
->parent
, pref
, NULL
) == 1)
8645 goto ns_next_prefix
;
8647 ret
= xmlNewNs(NULL
, nsName
, pref
);
8650 if (elem
->nsDef
== NULL
)
8653 xmlNsPtr ns2
= elem
->nsDef
;
8654 while (ns2
->next
!= NULL
)
8663 if (prefix
== NULL
) {
8664 snprintf((char *) buf
, sizeof(buf
),
8667 snprintf((char *) buf
, sizeof(buf
),
8668 "%.30s_%d", (char *)prefix
, counter
);
8669 pref
= BAD_CAST buf
;
8674 * xmlDOMWrapNSNormAcquireNormalizedNs:
8676 * @elem: the element-node to declare namespaces on
8677 * @ns: the ns-struct to use for the search
8678 * @retNs: the found/created ns-struct
8679 * @nsMap: the ns-map
8680 * @depth: the current tree depth
8681 * @ancestorsOnly: search in ancestor ns-decls only
8682 * @prefixed: if the searched ns-decl must have a prefix (for attributes)
8684 * Searches for a matching ns-name in the ns-decls of @nsMap, if not
8685 * found it will either declare it on @elem, or store it in doc->oldNs.
8686 * If a new ns-decl needs to be declared on @elem, it tries to use the
8687 * @ns->prefix for it, if this prefix is already in use on @elem, it will
8688 * change the prefix or the new ns-decl.
8690 * Returns 0 if succeeded, -1 otherwise and on API/internal errors.
8693 xmlDOMWrapNSNormAcquireNormalizedNs(xmlDocPtr doc
,
8705 if ((doc
== NULL
) || (ns
== NULL
) || (retNs
== NULL
) ||
8711 * Handle XML namespace.
8713 if (IS_STR_XML(ns
->prefix
)) {
8715 * Insert XML namespace mapping.
8717 *retNs
= xmlTreeEnsureXMLDecl(doc
);
8723 * If the search should be done in ancestors only and no
8724 * @elem (the first ancestor) was specified, then skip the search.
8726 if ((XML_NSMAP_NOTEMPTY(*nsMap
)) &&
8727 (! (ancestorsOnly
&& (elem
== NULL
))))
8730 * Try to find an equal ns-name in in-scope ns-decls.
8732 XML_NSMAP_FOREACH(*nsMap
, mi
) {
8733 if ((mi
->depth
>= XML_TREE_NSMAP_PARENT
) &&
8735 * ancestorsOnly: This should be turned on to gain speed,
8736 * if one knows that the branch itself was already
8737 * ns-wellformed and no stale references existed.
8738 * I.e. it searches in the ancestor axis only.
8740 ((! ancestorsOnly
) || (mi
->depth
== XML_TREE_NSMAP_PARENT
)) &&
8741 /* Skip shadowed prefixes. */
8742 (mi
->shadowDepth
== -1) &&
8743 /* Skip xmlns="" or xmlns:foo="". */
8744 ((mi
->newNs
->href
!= NULL
) &&
8745 (mi
->newNs
->href
[0] != 0)) &&
8746 /* Ensure a prefix if wanted. */
8747 ((! prefixed
) || (mi
->newNs
->prefix
!= NULL
)) &&
8749 ((mi
->newNs
->href
== ns
->href
) ||
8750 xmlStrEqual(mi
->newNs
->href
, ns
->href
))) {
8751 /* Set the mapping. */
8759 * No luck, the namespace is out of scope or shadowed.
8765 * Store ns-decls in "oldNs" of the document-node.
8767 tmpns
= xmlDOMWrapStoreNs(doc
, ns
->href
, ns
->prefix
);
8773 if (xmlDOMWrapNsMapAddItem(nsMap
, -1, ns
,
8774 tmpns
, XML_TREE_NSMAP_DOC
) == NULL
) {
8782 tmpns
= xmlDOMWrapNSNormDeclareNsForced(doc
, elem
, ns
->href
,
8787 if (*nsMap
!= NULL
) {
8789 * Does it shadow ancestor ns-decls?
8791 XML_NSMAP_FOREACH(*nsMap
, mi
) {
8792 if ((mi
->depth
< depth
) &&
8793 (mi
->shadowDepth
== -1) &&
8794 ((ns
->prefix
== mi
->newNs
->prefix
) ||
8795 xmlStrEqual(ns
->prefix
, mi
->newNs
->prefix
))) {
8799 mi
->shadowDepth
= depth
;
8804 if (xmlDOMWrapNsMapAddItem(nsMap
, -1, ns
, tmpns
, depth
) == NULL
) {
8814 XML_DOM_RECONNS_REMOVEREDUND
= 1<<0
8815 } xmlDOMReconcileNSOptions
;
8818 * xmlDOMWrapReconcileNamespaces:
8819 * @ctxt: DOM wrapper context, unused at the moment
8820 * @elem: the element-node
8821 * @options: option flags
8823 * Ensures that ns-references point to ns-decls hold on element-nodes.
8824 * Ensures that the tree is namespace wellformed by creating additional
8825 * ns-decls where needed. Note that, since prefixes of already existent
8826 * ns-decls can be shadowed by this process, it could break QNames in
8827 * attribute values or element content.
8829 * NOTE: This function was not intensively tested.
8831 * Returns 0 if succeeded, -1 otherwise and on API/internal errors.
8835 xmlDOMWrapReconcileNamespaces(xmlDOMWrapCtxtPtr ctxt ATTRIBUTE_UNUSED
,
8839 int depth
= -1, adoptns
= 0, parnsdone
= 0;
8840 xmlNsPtr ns
, prevns
;
8842 xmlNodePtr cur
, curElem
= NULL
;
8843 xmlNsMapPtr nsMap
= NULL
;
8844 xmlNsMapItemPtr
/* topmi = NULL, */ mi
;
8845 /* @ancestorsOnly should be set by an option flag. */
8846 int ancestorsOnly
= 0;
8847 int optRemoveRedundantNS
=
8848 ((xmlDOMReconcileNSOptions
) options
& XML_DOM_RECONNS_REMOVEREDUND
) ? 1 : 0;
8849 xmlNsPtr
*listRedund
= NULL
;
8850 int sizeRedund
= 0, nbRedund
= 0, ret
, i
, j
;
8852 if ((elem
== NULL
) || (elem
->doc
== NULL
) ||
8853 (elem
->type
!= XML_ELEMENT_NODE
))
8859 switch (cur
->type
) {
8860 case XML_ELEMENT_NODE
:
8865 * Namespace declarations.
8867 if (cur
->nsDef
!= NULL
) {
8870 while (ns
!= NULL
) {
8872 if ((elem
->parent
) &&
8873 ((xmlNodePtr
) elem
->parent
->doc
!= elem
->parent
)) {
8875 * Gather ancestor in-scope ns-decls.
8877 if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap
,
8878 elem
->parent
) == -1)
8879 goto internal_error
;
8885 * Lookup the ns ancestor-axis for equal ns-decls in scope.
8887 if (optRemoveRedundantNS
&& XML_NSMAP_NOTEMPTY(nsMap
)) {
8888 XML_NSMAP_FOREACH(nsMap
, mi
) {
8889 if ((mi
->depth
>= XML_TREE_NSMAP_PARENT
) &&
8890 (mi
->shadowDepth
== -1) &&
8891 ((ns
->prefix
== mi
->newNs
->prefix
) ||
8892 xmlStrEqual(ns
->prefix
, mi
->newNs
->prefix
)) &&
8893 ((ns
->href
== mi
->newNs
->href
) ||
8894 xmlStrEqual(ns
->href
, mi
->newNs
->href
)))
8897 * A redundant ns-decl was found.
8898 * Add it to the list of redundant ns-decls.
8900 if (xmlDOMWrapNSNormAddNsMapItem2(&listRedund
,
8901 &sizeRedund
, &nbRedund
, ns
, mi
->newNs
) == -1)
8902 goto internal_error
;
8904 * Remove the ns-decl from the element-node.
8907 prevns
->next
= ns
->next
;
8909 cur
->nsDef
= ns
->next
;
8916 * Skip ns-references handling if the referenced
8917 * ns-decl is declared on the same element.
8919 if ((cur
->ns
!= NULL
) && adoptns
&& (cur
->ns
== ns
))
8922 * Does it shadow any ns-decl?
8924 if (XML_NSMAP_NOTEMPTY(nsMap
)) {
8925 XML_NSMAP_FOREACH(nsMap
, mi
) {
8926 if ((mi
->depth
>= XML_TREE_NSMAP_PARENT
) &&
8927 (mi
->shadowDepth
== -1) &&
8928 ((ns
->prefix
== mi
->newNs
->prefix
) ||
8929 xmlStrEqual(ns
->prefix
, mi
->newNs
->prefix
))) {
8931 mi
->shadowDepth
= depth
;
8938 if (xmlDOMWrapNsMapAddItem(&nsMap
, -1, ns
, ns
,
8940 goto internal_error
;
8949 /* Falls through. */
8950 case XML_ATTRIBUTE_NODE
:
8951 /* No ns, no fun. */
8952 if (cur
->ns
== NULL
)
8956 if ((elem
->parent
) &&
8957 ((xmlNodePtr
) elem
->parent
->doc
!= elem
->parent
)) {
8958 if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap
,
8959 elem
->parent
) == -1)
8960 goto internal_error
;
8965 * Adjust the reference if this was a redundant ns-decl.
8968 for (i
= 0, j
= 0; i
< nbRedund
; i
++, j
+= 2) {
8969 if (cur
->ns
== listRedund
[j
]) {
8970 cur
->ns
= listRedund
[++j
];
8976 * Adopt ns-references.
8978 if (XML_NSMAP_NOTEMPTY(nsMap
)) {
8980 * Search for a mapping.
8982 XML_NSMAP_FOREACH(nsMap
, mi
) {
8983 if ((mi
->shadowDepth
== -1) &&
8984 (cur
->ns
== mi
->oldNs
)) {
8986 cur
->ns
= mi
->newNs
;
8992 * Acquire a normalized ns-decl and add it to the map.
8994 if (xmlDOMWrapNSNormAcquireNormalizedNs(doc
, curElem
,
8998 (cur
->type
== XML_ATTRIBUTE_NODE
) ? 1 : 0) == -1)
8999 goto internal_error
;
9003 if ((cur
->type
== XML_ELEMENT_NODE
) &&
9004 (cur
->properties
!= NULL
)) {
9006 * Process attributes.
9008 cur
= (xmlNodePtr
) cur
->properties
;
9016 if ((cur
->type
== XML_ELEMENT_NODE
) &&
9017 (cur
->children
!= NULL
)) {
9019 * Process content of element-nodes only.
9021 cur
= cur
->children
;
9027 if (cur
->type
== XML_ELEMENT_NODE
) {
9028 if (XML_NSMAP_NOTEMPTY(nsMap
)) {
9032 while ((nsMap
->last
!= NULL
) &&
9033 (nsMap
->last
->depth
>= depth
))
9035 XML_NSMAP_POP(nsMap
, mi
)
9040 XML_NSMAP_FOREACH(nsMap
, mi
) {
9041 if (mi
->shadowDepth
>= depth
)
9042 mi
->shadowDepth
= -1;
9047 if (cur
->next
!= NULL
)
9050 if (cur
->type
== XML_ATTRIBUTE_NODE
) {
9057 } while (cur
!= NULL
);
9065 for (i
= 0, j
= 0; i
< nbRedund
; i
++, j
+= 2) {
9066 xmlFreeNs(listRedund
[j
]);
9068 xmlFree(listRedund
);
9071 xmlDOMWrapNsMapFree(nsMap
);
9076 * xmlDOMWrapAdoptBranch:
9077 * @ctxt: the optional context for custom processing
9078 * @sourceDoc: the optional sourceDoc
9079 * @node: the element-node to start with
9080 * @destDoc: the destination doc for adoption
9081 * @destParent: the optional new parent of @node in @destDoc
9082 * @options: option flags
9084 * Ensures that ns-references point to @destDoc: either to
9085 * elements->nsDef entries if @destParent is given, or to
9086 * @destDoc->oldNs otherwise.
9087 * If @destParent is given, it ensures that the tree is namespace
9088 * wellformed by creating additional ns-decls where needed.
9089 * Note that, since prefixes of already existent ns-decls can be
9090 * shadowed by this process, it could break QNames in attribute
9091 * values or element content.
9093 * NOTE: This function was not intensively tested.
9095 * Returns 0 if succeeded, -1 otherwise and on API/internal errors.
9098 xmlDOMWrapAdoptBranch(xmlDOMWrapCtxtPtr ctxt
,
9099 xmlDocPtr sourceDoc
,
9102 xmlNodePtr destParent
,
9103 int options ATTRIBUTE_UNUSED
)
9106 xmlNodePtr cur
, curElem
= NULL
;
9107 xmlNsMapPtr nsMap
= NULL
;
9110 int depth
= -1, adoptStr
= 1;
9111 /* gather @parent's ns-decls. */
9113 /* @ancestorsOnly should be set per option. */
9114 int ancestorsOnly
= 0;
9117 * Optimize string adoption for equal or none dicts.
9119 if ((sourceDoc
!= NULL
) &&
9120 (sourceDoc
->dict
== destDoc
->dict
))
9126 * Get the ns-map from the context if available.
9129 nsMap
= (xmlNsMapPtr
) ctxt
->namespaceMap
;
9131 * Disable search for ns-decls in the parent-axis of the
9132 * destination element, if:
9133 * 1) there's no destination parent
9134 * 2) custom ns-reference handling is used
9136 if ((destParent
== NULL
) ||
9137 (ctxt
&& ctxt
->getNsForNodeFunc
))
9144 if ((cur
!= NULL
) && (cur
->type
== XML_NAMESPACE_DECL
))
9145 goto internal_error
;
9147 while (cur
!= NULL
) {
9149 * Paranoid source-doc sanity check.
9151 if (cur
->doc
!= sourceDoc
) {
9153 * We'll assume XIncluded nodes if the doc differs.
9154 * TODO: Do we need to reconciliate XIncluded nodes?
9155 * This here skips XIncluded nodes and tries to handle
9158 if (cur
->next
== NULL
)
9162 if ((cur
->type
== XML_XINCLUDE_END
) ||
9163 (cur
->doc
== node
->doc
))
9165 } while (cur
->next
!= NULL
);
9167 if (cur
->doc
!= node
->doc
)
9171 switch (cur
->type
) {
9172 case XML_XINCLUDE_START
:
9173 case XML_XINCLUDE_END
:
9178 case XML_ELEMENT_NODE
:
9182 * Namespace declarations.
9183 * - ns->href and ns->prefix are never in the dict, so
9184 * we need not move the values over to the destination dict.
9185 * - Note that for custom handling of ns-references,
9186 * the ns-decls need not be stored in the ns-map,
9187 * since they won't be referenced by node->ns.
9190 ((ctxt
== NULL
) || (ctxt
->getNsForNodeFunc
== NULL
)))
9194 * Gather @parent's in-scope ns-decls.
9196 if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap
,
9198 goto internal_error
;
9201 for (ns
= cur
->nsDef
; ns
!= NULL
; ns
= ns
->next
) {
9203 * NOTE: ns->prefix and ns->href are never in the dict.
9204 * XML_TREE_ADOPT_STR(ns->prefix)
9205 * XML_TREE_ADOPT_STR(ns->href)
9208 * Does it shadow any ns-decl?
9210 if (XML_NSMAP_NOTEMPTY(nsMap
)) {
9211 XML_NSMAP_FOREACH(nsMap
, mi
) {
9212 if ((mi
->depth
>= XML_TREE_NSMAP_PARENT
) &&
9213 (mi
->shadowDepth
== -1) &&
9214 ((ns
->prefix
== mi
->newNs
->prefix
) ||
9215 xmlStrEqual(ns
->prefix
,
9216 mi
->newNs
->prefix
))) {
9218 mi
->shadowDepth
= depth
;
9225 if (xmlDOMWrapNsMapAddItem(&nsMap
, -1,
9226 ns
, ns
, depth
) == NULL
)
9227 goto internal_error
;
9230 /* Falls through. */
9231 case XML_ATTRIBUTE_NODE
:
9232 /* No namespace, no fun. */
9233 if (cur
->ns
== NULL
)
9237 if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap
,
9239 goto internal_error
;
9243 * Adopt ns-references.
9245 if (XML_NSMAP_NOTEMPTY(nsMap
)) {
9247 * Search for a mapping.
9249 XML_NSMAP_FOREACH(nsMap
, mi
) {
9250 if ((mi
->shadowDepth
== -1) &&
9251 (cur
->ns
== mi
->oldNs
)) {
9253 cur
->ns
= mi
->newNs
;
9259 * No matching namespace in scope. We need a new one.
9261 if ((ctxt
) && (ctxt
->getNsForNodeFunc
)) {
9263 * User-defined behaviour.
9265 ns
= ctxt
->getNsForNodeFunc(ctxt
, cur
,
9266 cur
->ns
->href
, cur
->ns
->prefix
);
9268 * Insert mapping if ns is available; it's the users fault
9271 if (xmlDOMWrapNsMapAddItem(&nsMap
, -1,
9272 cur
->ns
, ns
, XML_TREE_NSMAP_CUSTOM
) == NULL
)
9273 goto internal_error
;
9277 * Acquire a normalized ns-decl and add it to the map.
9279 if (xmlDOMWrapNSNormAcquireNormalizedNs(destDoc
,
9280 /* ns-decls on curElem or on destDoc->oldNs */
9281 destParent
? curElem
: NULL
,
9285 /* ns-decls must be prefixed for attributes. */
9286 (cur
->type
== XML_ATTRIBUTE_NODE
) ? 1 : 0) == -1)
9287 goto internal_error
;
9292 * Further node properties.
9293 * TODO: Is this all?
9295 XML_TREE_ADOPT_STR(cur
->name
)
9296 if (cur
->type
== XML_ELEMENT_NODE
) {
9303 if (cur
->properties
!= NULL
) {
9305 * Process first attribute node.
9307 cur
= (xmlNodePtr
) cur
->properties
;
9314 if ((sourceDoc
!= NULL
) &&
9315 (((xmlAttrPtr
) cur
)->atype
== XML_ATTRIBUTE_ID
))
9317 xmlRemoveID(sourceDoc
, (xmlAttrPtr
) cur
);
9319 ((xmlAttrPtr
) cur
)->atype
= 0;
9320 ((xmlAttrPtr
) cur
)->psvi
= NULL
;
9324 case XML_CDATA_SECTION_NODE
:
9326 * This puts the content in the dest dict, only if
9327 * it was previously in the source dict.
9329 XML_TREE_ADOPT_STR_2(cur
->content
)
9331 case XML_ENTITY_REF_NODE
:
9333 * Remove reference to the entity-node.
9335 cur
->content
= NULL
;
9336 cur
->children
= NULL
;
9338 if ((destDoc
->intSubset
) || (destDoc
->extSubset
)) {
9341 * Assign new entity-node if available.
9343 ent
= xmlGetDocEntity(destDoc
, cur
->name
);
9345 cur
->content
= ent
->content
;
9346 cur
->children
= (xmlNodePtr
) ent
;
9347 cur
->last
= (xmlNodePtr
) ent
;
9352 XML_TREE_ADOPT_STR(cur
->name
)
9353 XML_TREE_ADOPT_STR_2(cur
->content
)
9355 case XML_COMMENT_NODE
:
9358 goto internal_error
;
9363 if (cur
->children
!= NULL
) {
9364 cur
= cur
->children
;
9371 if ((cur
->type
== XML_ELEMENT_NODE
) ||
9372 (cur
->type
== XML_XINCLUDE_START
) ||
9373 (cur
->type
== XML_XINCLUDE_END
))
9376 * TODO: Do we expect nsDefs on XML_XINCLUDE_START?
9378 if (XML_NSMAP_NOTEMPTY(nsMap
)) {
9382 while ((nsMap
->last
!= NULL
) &&
9383 (nsMap
->last
->depth
>= depth
))
9385 XML_NSMAP_POP(nsMap
, mi
)
9390 XML_NSMAP_FOREACH(nsMap
, mi
) {
9391 if (mi
->shadowDepth
>= depth
)
9392 mi
->shadowDepth
= -1;
9397 if (cur
->next
!= NULL
)
9399 else if ((cur
->type
== XML_ATTRIBUTE_NODE
) &&
9400 (cur
->parent
->children
!= NULL
))
9402 cur
= cur
->parent
->children
;
9418 if (nsMap
!= NULL
) {
9419 if ((ctxt
) && (ctxt
->namespaceMap
== nsMap
)) {
9421 * Just cleanup the map but don't free.
9425 nsMap
->last
->next
= nsMap
->pool
;
9426 nsMap
->pool
= nsMap
->first
;
9427 nsMap
->first
= NULL
;
9430 xmlDOMWrapNsMapFree(nsMap
);
9436 * xmlDOMWrapCloneNode:
9437 * @ctxt: the optional context for custom processing
9438 * @sourceDoc: the optional sourceDoc
9439 * @node: the node to start with
9440 * @resNode: the clone of the given @node
9441 * @destDoc: the destination doc
9442 * @destParent: the optional new parent of @node in @destDoc
9443 * @deep: descend into child if set
9444 * @options: option flags
9446 * References of out-of scope ns-decls are remapped to point to @destDoc:
9447 * 1) If @destParent is given, then nsDef entries on element-nodes are used
9448 * 2) If *no* @destParent is given, then @destDoc->oldNs entries are used.
9449 * This is the case when you don't know already where the cloned branch
9452 * If @destParent is given, it ensures that the tree is namespace
9453 * wellformed by creating additional ns-decls where needed.
9454 * Note that, since prefixes of already existent ns-decls can be
9455 * shadowed by this process, it could break QNames in attribute
9456 * values or element content.
9458 * 1) What to do with XInclude? Currently this returns an error for XInclude.
9460 * Returns 0 if the operation succeeded,
9461 * 1 if a node of unsupported (or not yet supported) type was given,
9462 * -1 on API/internal errors.
9466 xmlDOMWrapCloneNode(xmlDOMWrapCtxtPtr ctxt
,
9467 xmlDocPtr sourceDoc
,
9469 xmlNodePtr
*resNode
,
9471 xmlNodePtr destParent
,
9473 int options ATTRIBUTE_UNUSED
)
9476 xmlNodePtr cur
, curElem
= NULL
;
9477 xmlNsMapPtr nsMap
= NULL
;
9481 /* int adoptStr = 1; */
9482 /* gather @parent's ns-decls. */
9486 * TODO: @ancestorsOnly should be set per option.
9489 int ancestorsOnly
= 0;
9490 xmlNodePtr resultClone
= NULL
, clone
= NULL
, parentClone
= NULL
, prevClone
= NULL
;
9491 xmlNsPtr cloneNs
= NULL
, *cloneNsDefSlot
= NULL
;
9492 xmlDictPtr dict
; /* The destination dict */
9494 if ((node
== NULL
) || (resNode
== NULL
) || (destDoc
== NULL
))
9497 * TODO: Initially we support only element-nodes.
9499 if (node
->type
!= XML_ELEMENT_NODE
)
9502 * Check node->doc sanity.
9504 if ((node
->doc
!= NULL
) && (sourceDoc
!= NULL
) &&
9505 (node
->doc
!= sourceDoc
)) {
9507 * Might be an XIncluded node.
9511 if (sourceDoc
== NULL
)
9512 sourceDoc
= node
->doc
;
9513 if (sourceDoc
== NULL
)
9516 dict
= destDoc
->dict
;
9518 * Reuse the namespace map of the context.
9521 nsMap
= (xmlNsMapPtr
) ctxt
->namespaceMap
;
9526 if ((cur
!= NULL
) && (cur
->type
== XML_NAMESPACE_DECL
))
9529 while (cur
!= NULL
) {
9530 if (cur
->doc
!= sourceDoc
) {
9532 * We'll assume XIncluded nodes if the doc differs.
9533 * TODO: Do we need to reconciliate XIncluded nodes?
9534 * TODO: This here returns -1 in this case.
9536 goto internal_error
;
9539 * Create a new node.
9541 switch (cur
->type
) {
9542 case XML_XINCLUDE_START
:
9543 case XML_XINCLUDE_END
:
9545 * TODO: What to do with XInclude?
9547 goto internal_error
;
9549 case XML_ELEMENT_NODE
:
9551 case XML_CDATA_SECTION_NODE
:
9552 case XML_COMMENT_NODE
:
9554 case XML_DOCUMENT_FRAG_NODE
:
9555 case XML_ENTITY_REF_NODE
:
9556 case XML_ENTITY_NODE
:
9558 * Nodes of xmlNode structure.
9560 clone
= (xmlNodePtr
) xmlMalloc(sizeof(xmlNode
));
9561 if (clone
== NULL
) {
9562 xmlTreeErrMemory("xmlDOMWrapCloneNode(): allocating a node");
9563 goto internal_error
;
9565 memset(clone
, 0, sizeof(xmlNode
));
9567 * Set hierarchical links.
9569 if (resultClone
!= NULL
) {
9570 clone
->parent
= parentClone
;
9572 prevClone
->next
= clone
;
9573 clone
->prev
= prevClone
;
9575 parentClone
->children
= clone
;
9577 resultClone
= clone
;
9580 case XML_ATTRIBUTE_NODE
:
9582 * Attributes (xmlAttr).
9584 /* Use xmlRealloc to avoid -Warray-bounds warning */
9585 clone
= (xmlNodePtr
) xmlRealloc(NULL
, sizeof(xmlAttr
));
9586 if (clone
== NULL
) {
9587 xmlTreeErrMemory("xmlDOMWrapCloneNode(): allocating an attr-node");
9588 goto internal_error
;
9590 memset(clone
, 0, sizeof(xmlAttr
));
9592 * Set hierarchical links.
9593 * TODO: Change this to add to the end of attributes.
9595 if (resultClone
!= NULL
) {
9596 clone
->parent
= parentClone
;
9598 prevClone
->next
= clone
;
9599 clone
->prev
= prevClone
;
9601 parentClone
->properties
= (xmlAttrPtr
) clone
;
9603 resultClone
= clone
;
9607 * TODO QUESTION: Any other nodes expected?
9609 goto internal_error
;
9612 clone
->type
= cur
->type
;
9613 clone
->doc
= destDoc
;
9616 * Clone the name of the node if any.
9618 if (cur
->name
== xmlStringText
)
9619 clone
->name
= xmlStringText
;
9620 else if (cur
->name
== xmlStringTextNoenc
)
9622 * NOTE: Although xmlStringTextNoenc is never assigned to a node
9623 * in tree.c, it might be set in Libxslt via
9624 * "xsl:disable-output-escaping".
9626 clone
->name
= xmlStringTextNoenc
;
9627 else if (cur
->name
== xmlStringComment
)
9628 clone
->name
= xmlStringComment
;
9629 else if (cur
->name
!= NULL
) {
9630 DICT_CONST_COPY(cur
->name
, clone
->name
);
9633 switch (cur
->type
) {
9634 case XML_XINCLUDE_START
:
9635 case XML_XINCLUDE_END
:
9640 case XML_ELEMENT_NODE
:
9644 * Namespace declarations.
9646 if (cur
->nsDef
!= NULL
) {
9648 if (destParent
&& (ctxt
== NULL
)) {
9650 * Gather @parent's in-scope ns-decls.
9652 if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap
,
9654 goto internal_error
;
9659 * Clone namespace declarations.
9661 cloneNsDefSlot
= &(clone
->nsDef
);
9662 for (ns
= cur
->nsDef
; ns
!= NULL
; ns
= ns
->next
) {
9664 * Create a new xmlNs.
9666 cloneNs
= (xmlNsPtr
) xmlMalloc(sizeof(xmlNs
));
9667 if (cloneNs
== NULL
) {
9668 xmlTreeErrMemory("xmlDOMWrapCloneNode(): "
9669 "allocating namespace");
9672 memset(cloneNs
, 0, sizeof(xmlNs
));
9673 cloneNs
->type
= XML_LOCAL_NAMESPACE
;
9675 if (ns
->href
!= NULL
)
9676 cloneNs
->href
= xmlStrdup(ns
->href
);
9677 if (ns
->prefix
!= NULL
)
9678 cloneNs
->prefix
= xmlStrdup(ns
->prefix
);
9680 *cloneNsDefSlot
= cloneNs
;
9681 cloneNsDefSlot
= &(cloneNs
->next
);
9684 * Note that for custom handling of ns-references,
9685 * the ns-decls need not be stored in the ns-map,
9686 * since they won't be referenced by node->ns.
9688 if ((ctxt
== NULL
) ||
9689 (ctxt
->getNsForNodeFunc
== NULL
))
9692 * Does it shadow any ns-decl?
9694 if (XML_NSMAP_NOTEMPTY(nsMap
)) {
9695 XML_NSMAP_FOREACH(nsMap
, mi
) {
9696 if ((mi
->depth
>= XML_TREE_NSMAP_PARENT
) &&
9697 (mi
->shadowDepth
== -1) &&
9698 ((ns
->prefix
== mi
->newNs
->prefix
) ||
9699 xmlStrEqual(ns
->prefix
,
9700 mi
->newNs
->prefix
))) {
9702 * Mark as shadowed at the current
9705 mi
->shadowDepth
= depth
;
9712 if (xmlDOMWrapNsMapAddItem(&nsMap
, -1,
9713 ns
, cloneNs
, depth
) == NULL
)
9714 goto internal_error
;
9718 /* cur->ns will be processed further down. */
9720 case XML_ATTRIBUTE_NODE
:
9721 /* IDs will be processed further down. */
9722 /* cur->ns will be processed further down. */
9725 case XML_CDATA_SECTION_NODE
:
9727 * Note that this will also cover the values of attributes.
9729 DICT_COPY(cur
->content
, clone
->content
);
9731 case XML_ENTITY_NODE
:
9732 /* TODO: What to do here? */
9734 case XML_ENTITY_REF_NODE
:
9735 if (sourceDoc
!= destDoc
) {
9736 if ((destDoc
->intSubset
) || (destDoc
->extSubset
)) {
9739 * Different doc: Assign new entity-node if available.
9741 ent
= xmlGetDocEntity(destDoc
, cur
->name
);
9743 clone
->content
= ent
->content
;
9744 clone
->children
= (xmlNodePtr
) ent
;
9745 clone
->last
= (xmlNodePtr
) ent
;
9750 * Same doc: Use the current node's entity declaration
9753 clone
->content
= cur
->content
;
9754 clone
->children
= cur
->children
;
9755 clone
->last
= cur
->last
;
9759 DICT_COPY(cur
->content
, clone
->content
);
9761 case XML_COMMENT_NODE
:
9762 DICT_COPY(cur
->content
, clone
->content
);
9765 goto internal_error
;
9768 if (cur
->ns
== NULL
)
9769 goto end_ns_reference
;
9771 /* handle_ns_reference: */
9773 ** The following will take care of references to ns-decls ********
9774 ** and is intended only for element- and attribute-nodes.
9778 if (destParent
&& (ctxt
== NULL
)) {
9779 if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap
, destParent
) == -1)
9780 goto internal_error
;
9785 * Adopt ns-references.
9787 if (XML_NSMAP_NOTEMPTY(nsMap
)) {
9789 * Search for a mapping.
9791 XML_NSMAP_FOREACH(nsMap
, mi
) {
9792 if ((mi
->shadowDepth
== -1) &&
9793 (cur
->ns
== mi
->oldNs
)) {
9795 * This is the nice case: a mapping was found.
9797 clone
->ns
= mi
->newNs
;
9798 goto end_ns_reference
;
9803 * No matching namespace in scope. We need a new one.
9805 if ((ctxt
!= NULL
) && (ctxt
->getNsForNodeFunc
!= NULL
)) {
9807 * User-defined behaviour.
9809 ns
= ctxt
->getNsForNodeFunc(ctxt
, cur
,
9810 cur
->ns
->href
, cur
->ns
->prefix
);
9812 * Add user's mapping.
9814 if (xmlDOMWrapNsMapAddItem(&nsMap
, -1,
9815 cur
->ns
, ns
, XML_TREE_NSMAP_CUSTOM
) == NULL
)
9816 goto internal_error
;
9820 * Acquire a normalized ns-decl and add it to the map.
9822 if (xmlDOMWrapNSNormAcquireNormalizedNs(destDoc
,
9823 /* ns-decls on curElem or on destDoc->oldNs */
9824 destParent
? curElem
: NULL
,
9827 /* if we need to search only in the ancestor-axis */
9829 /* ns-decls must be prefixed for attributes. */
9830 (cur
->type
== XML_ATTRIBUTE_NODE
) ? 1 : 0) == -1)
9831 goto internal_error
;
9838 * Some post-processing.
9840 * Handle ID attributes.
9842 if ((clone
->type
== XML_ATTRIBUTE_NODE
) &&
9843 (clone
->parent
!= NULL
))
9845 if (xmlIsID(destDoc
, clone
->parent
, (xmlAttrPtr
) clone
)) {
9849 idVal
= xmlNodeListGetString(cur
->doc
, cur
->children
, 1);
9850 if (idVal
!= NULL
) {
9851 if (xmlAddID(NULL
, destDoc
, idVal
, (xmlAttrPtr
) cur
) == NULL
) {
9852 /* TODO: error message. */
9854 goto internal_error
;
9862 ** The following will traverse the tree **************************
9865 * Walk the element's attributes before descending into child-nodes.
9867 if ((cur
->type
== XML_ELEMENT_NODE
) && (cur
->properties
!= NULL
)) {
9869 parentClone
= clone
;
9870 cur
= (xmlNodePtr
) cur
->properties
;
9875 * Descend into child-nodes.
9877 if (cur
->children
!= NULL
) {
9878 if (deep
|| (cur
->type
== XML_ATTRIBUTE_NODE
)) {
9880 parentClone
= clone
;
9881 cur
= cur
->children
;
9888 * At this point we are done with the node, its content
9889 * and an element-nodes's attribute-nodes.
9893 if ((cur
->type
== XML_ELEMENT_NODE
) ||
9894 (cur
->type
== XML_XINCLUDE_START
) ||
9895 (cur
->type
== XML_XINCLUDE_END
)) {
9897 * TODO: Do we expect nsDefs on XML_XINCLUDE_START?
9899 if (XML_NSMAP_NOTEMPTY(nsMap
)) {
9903 while ((nsMap
->last
!= NULL
) &&
9904 (nsMap
->last
->depth
>= depth
))
9906 XML_NSMAP_POP(nsMap
, mi
)
9911 XML_NSMAP_FOREACH(nsMap
, mi
) {
9912 if (mi
->shadowDepth
>= depth
)
9913 mi
->shadowDepth
= -1;
9918 if (cur
->next
!= NULL
) {
9921 } else if (cur
->type
!= XML_ATTRIBUTE_NODE
) {
9925 if (clone
->parent
!= NULL
)
9926 clone
->parent
->last
= clone
;
9927 clone
= clone
->parent
;
9929 parentClone
= clone
->parent
;
9931 * Process parent --> next;
9936 /* This is for attributes only. */
9937 clone
= clone
->parent
;
9938 parentClone
= clone
->parent
;
9940 * Process parent-element --> children.
9955 if (nsMap
!= NULL
) {
9956 if ((ctxt
) && (ctxt
->namespaceMap
== nsMap
)) {
9958 * Just cleanup the map but don't free.
9962 nsMap
->last
->next
= nsMap
->pool
;
9963 nsMap
->pool
= nsMap
->first
;
9964 nsMap
->first
= NULL
;
9967 xmlDOMWrapNsMapFree(nsMap
);
9970 * TODO: Should we try a cleanup of the cloned node in case of a
9973 *resNode
= resultClone
;
9978 * xmlDOMWrapAdoptAttr:
9979 * @ctxt: the optional context for custom processing
9980 * @sourceDoc: the optional source document of attr
9981 * @attr: the attribute-node to be adopted
9982 * @destDoc: the destination doc for adoption
9983 * @destParent: the optional new parent of @attr in @destDoc
9984 * @options: option flags
9986 * @attr is adopted by @destDoc.
9987 * Ensures that ns-references point to @destDoc: either to
9988 * elements->nsDef entries if @destParent is given, or to
9989 * @destDoc->oldNs otherwise.
9991 * Returns 0 if succeeded, -1 otherwise and on API/internal errors.
9994 xmlDOMWrapAdoptAttr(xmlDOMWrapCtxtPtr ctxt
,
9995 xmlDocPtr sourceDoc
,
9998 xmlNodePtr destParent
,
9999 int options ATTRIBUTE_UNUSED
)
10004 if ((attr
== NULL
) || (destDoc
== NULL
))
10007 attr
->doc
= destDoc
;
10008 if (attr
->ns
!= NULL
) {
10009 xmlNsPtr ns
= NULL
;
10011 if (ctxt
!= NULL
) {
10012 /* TODO: User defined. */
10014 /* XML Namespace. */
10015 if (IS_STR_XML(attr
->ns
->prefix
)) {
10016 ns
= xmlTreeEnsureXMLDecl(destDoc
);
10017 } else if (destParent
== NULL
) {
10019 * Store in @destDoc->oldNs.
10021 ns
= xmlDOMWrapStoreNs(destDoc
, attr
->ns
->href
, attr
->ns
->prefix
);
10024 * Declare on @destParent.
10026 if (xmlSearchNsByNamespaceStrict(destDoc
, destParent
, attr
->ns
->href
,
10028 goto internal_error
;
10030 ns
= xmlDOMWrapNSNormDeclareNsForced(destDoc
, destParent
,
10031 attr
->ns
->href
, attr
->ns
->prefix
, 1);
10035 goto internal_error
;
10039 XML_TREE_ADOPT_STR(attr
->name
);
10045 if (attr
->children
== NULL
)
10047 cur
= attr
->children
;
10048 if ((cur
!= NULL
) && (cur
->type
== XML_NAMESPACE_DECL
))
10049 goto internal_error
;
10050 while (cur
!= NULL
) {
10051 cur
->doc
= destDoc
;
10052 switch (cur
->type
) {
10053 case XML_TEXT_NODE
:
10054 case XML_CDATA_SECTION_NODE
:
10055 XML_TREE_ADOPT_STR_2(cur
->content
)
10057 case XML_ENTITY_REF_NODE
:
10059 * Remove reference to the entity-node.
10061 cur
->content
= NULL
;
10062 cur
->children
= NULL
;
10064 if ((destDoc
->intSubset
) || (destDoc
->extSubset
)) {
10067 * Assign new entity-node if available.
10069 ent
= xmlGetDocEntity(destDoc
, cur
->name
);
10071 cur
->content
= ent
->content
;
10072 cur
->children
= (xmlNodePtr
) ent
;
10073 cur
->last
= (xmlNodePtr
) ent
;
10080 if (cur
->children
!= NULL
) {
10081 cur
= cur
->children
;
10085 if (cur
== (xmlNodePtr
) attr
)
10087 if (cur
->next
!= NULL
)
10100 * xmlDOMWrapAdoptNode:
10101 * @ctxt: the optional context for custom processing
10102 * @sourceDoc: the optional sourceDoc
10103 * @node: the node to start with
10104 * @destDoc: the destination doc
10105 * @destParent: the optional new parent of @node in @destDoc
10106 * @options: option flags
10108 * References of out-of scope ns-decls are remapped to point to @destDoc:
10109 * 1) If @destParent is given, then nsDef entries on element-nodes are used
10110 * 2) If *no* @destParent is given, then @destDoc->oldNs entries are used
10111 * This is the case when you have an unlinked node and just want to move it
10112 * to the context of
10114 * If @destParent is given, it ensures that the tree is namespace
10115 * wellformed by creating additional ns-decls where needed.
10116 * Note that, since prefixes of already existent ns-decls can be
10117 * shadowed by this process, it could break QNames in attribute
10118 * values or element content.
10119 * NOTE: This function was not intensively tested.
10121 * Returns 0 if the operation succeeded,
10122 * 1 if a node of unsupported type was given,
10123 * 2 if a node of not yet supported type was given and
10124 * -1 on API/internal errors.
10127 xmlDOMWrapAdoptNode(xmlDOMWrapCtxtPtr ctxt
,
10128 xmlDocPtr sourceDoc
,
10131 xmlNodePtr destParent
,
10134 if ((node
== NULL
) || (node
->type
== XML_NAMESPACE_DECL
) ||
10135 (destDoc
== NULL
) ||
10136 ((destParent
!= NULL
) && (destParent
->doc
!= destDoc
)))
10139 * Check node->doc sanity.
10141 if ((node
->doc
!= NULL
) && (sourceDoc
!= NULL
) &&
10142 (node
->doc
!= sourceDoc
)) {
10144 * Might be an XIncluded node.
10148 if (sourceDoc
== NULL
)
10149 sourceDoc
= node
->doc
;
10150 if (sourceDoc
== destDoc
)
10152 switch (node
->type
) {
10153 case XML_ELEMENT_NODE
:
10154 case XML_ATTRIBUTE_NODE
:
10155 case XML_TEXT_NODE
:
10156 case XML_CDATA_SECTION_NODE
:
10157 case XML_ENTITY_REF_NODE
:
10159 case XML_COMMENT_NODE
:
10161 case XML_DOCUMENT_FRAG_NODE
:
10162 /* TODO: Support document-fragment-nodes. */
10168 * Unlink only if @node was not already added to @destParent.
10170 if ((node
->parent
!= NULL
) && (destParent
!= node
->parent
))
10171 xmlUnlinkNode(node
);
10173 if (node
->type
== XML_ELEMENT_NODE
) {
10174 return (xmlDOMWrapAdoptBranch(ctxt
, sourceDoc
, node
,
10175 destDoc
, destParent
, options
));
10176 } else if (node
->type
== XML_ATTRIBUTE_NODE
) {
10177 return (xmlDOMWrapAdoptAttr(ctxt
, sourceDoc
,
10178 (xmlAttrPtr
) node
, destDoc
, destParent
, options
));
10180 xmlNodePtr cur
= node
;
10183 cur
->doc
= destDoc
;
10185 * Optimize string adoption.
10187 if ((sourceDoc
!= NULL
) &&
10188 (sourceDoc
->dict
== destDoc
->dict
))
10190 switch (node
->type
) {
10191 case XML_TEXT_NODE
:
10192 case XML_CDATA_SECTION_NODE
:
10193 XML_TREE_ADOPT_STR_2(node
->content
)
10195 case XML_ENTITY_REF_NODE
:
10197 * Remove reference to the entity-node.
10199 node
->content
= NULL
;
10200 node
->children
= NULL
;
10202 if ((destDoc
->intSubset
) || (destDoc
->extSubset
)) {
10205 * Assign new entity-node if available.
10207 ent
= xmlGetDocEntity(destDoc
, node
->name
);
10209 node
->content
= ent
->content
;
10210 node
->children
= (xmlNodePtr
) ent
;
10211 node
->last
= (xmlNodePtr
) ent
;
10214 XML_TREE_ADOPT_STR(node
->name
)
10216 case XML_PI_NODE
: {
10217 XML_TREE_ADOPT_STR(node
->name
)
10218 XML_TREE_ADOPT_STR_2(node
->content
)
10228 /************************************************************************
10230 * XHTML detection *
10232 ************************************************************************/
10234 #define XHTML_STRICT_PUBLIC_ID BAD_CAST \
10235 "-//W3C//DTD XHTML 1.0 Strict//EN"
10236 #define XHTML_STRICT_SYSTEM_ID BAD_CAST \
10237 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
10238 #define XHTML_FRAME_PUBLIC_ID BAD_CAST \
10239 "-//W3C//DTD XHTML 1.0 Frameset//EN"
10240 #define XHTML_FRAME_SYSTEM_ID BAD_CAST \
10241 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd"
10242 #define XHTML_TRANS_PUBLIC_ID BAD_CAST \
10243 "-//W3C//DTD XHTML 1.0 Transitional//EN"
10244 #define XHTML_TRANS_SYSTEM_ID BAD_CAST \
10245 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
10249 * @systemID: the system identifier
10250 * @publicID: the public identifier
10252 * Try to find if the document correspond to an XHTML DTD
10254 * Returns 1 if true, 0 if not and -1 in case of error
10257 xmlIsXHTML(const xmlChar
*systemID
, const xmlChar
*publicID
) {
10258 if ((systemID
== NULL
) && (publicID
== NULL
))
10260 if (publicID
!= NULL
) {
10261 if (xmlStrEqual(publicID
, XHTML_STRICT_PUBLIC_ID
)) return(1);
10262 if (xmlStrEqual(publicID
, XHTML_FRAME_PUBLIC_ID
)) return(1);
10263 if (xmlStrEqual(publicID
, XHTML_TRANS_PUBLIC_ID
)) return(1);
10265 if (systemID
!= NULL
) {
10266 if (xmlStrEqual(systemID
, XHTML_STRICT_SYSTEM_ID
)) return(1);
10267 if (xmlStrEqual(systemID
, XHTML_FRAME_SYSTEM_ID
)) return(1);
10268 if (xmlStrEqual(systemID
, XHTML_TRANS_SYSTEM_ID
)) return(1);