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>
50 int __xmlRegisterCallbacks
= 0;
52 /************************************************************************
54 * Forward declarations *
56 ************************************************************************/
59 xmlNewReconciledNs(xmlDocPtr doc
, xmlNodePtr tree
, xmlNsPtr ns
);
61 static xmlChar
* xmlGetPropNodeValueInternal(const xmlAttr
*prop
);
63 /************************************************************************
65 * Tree memory error handler *
67 ************************************************************************/
70 * @extra: extra information
72 * Handle an out of memory condition
75 xmlTreeErrMemory(const char *extra
)
77 __xmlSimpleError(XML_FROM_TREE
, XML_ERR_NO_MEMORY
, NULL
, NULL
, extra
);
82 * @code: the error number
83 * @extra: extra information
85 * Handle an out of memory condition
88 xmlTreeErr(int code
, xmlNodePtr node
, const char *extra
)
90 const char *msg
= NULL
;
93 case XML_TREE_INVALID_HEX
:
94 msg
= "invalid hexadecimal character value\n";
96 case XML_TREE_INVALID_DEC
:
97 msg
= "invalid decimal character value\n";
99 case XML_TREE_UNTERMINATED_ENTITY
:
100 msg
= "unterminated entity reference %15s\n";
102 case XML_TREE_NOT_UTF8
:
103 msg
= "string is not in UTF-8\n";
106 msg
= "unexpected error number\n";
108 __xmlSimpleError(XML_FROM_TREE
, code
, node
, msg
, extra
);
111 /************************************************************************
113 * A few static variables and macros *
115 ************************************************************************/
116 /* #undef xmlStringText */
117 const xmlChar xmlStringText
[] = { 't', 'e', 'x', 't', 0 };
118 /* #undef xmlStringTextNoenc */
119 const xmlChar xmlStringTextNoenc
[] =
120 { 't', 'e', 'x', 't', 'n', 'o', 'e', 'n', 'c', 0 };
121 /* #undef xmlStringComment */
122 const xmlChar xmlStringComment
[] = { 'c', 'o', 'm', 'm', 'e', 'n', 't', 0 };
124 static int xmlCompressMode
= 0;
125 static int xmlCheckDTD
= 1;
127 #define UPDATE_LAST_CHILD_AND_PARENT(n) if ((n) != NULL) { \
128 xmlNodePtr ulccur = (n)->children; \
129 if (ulccur == NULL) { \
132 while (ulccur->next != NULL) { \
133 ulccur->parent = (n); \
134 ulccur = ulccur->next; \
136 ulccur->parent = (n); \
137 (n)->last = ulccur; \
140 #define IS_STR_XML(str) ((str != NULL) && (str[0] == 'x') && \
141 (str[1] == 'm') && (str[2] == 'l') && (str[3] == 0))
143 /* #define DEBUG_BUFFER */
144 /* #define DEBUG_TREE */
146 /************************************************************************
148 * Functions to move to entities.c once the *
149 * API freeze is smoothen and they can be made public. *
151 ************************************************************************/
152 #include <libxml/hash.h>
154 #ifdef LIBXML_TREE_ENABLED
156 * xmlGetEntityFromDtd:
157 * @dtd: A pointer to the DTD to search
158 * @name: The entity name
160 * Do an entity lookup in the DTD entity hash table and
161 * return the corresponding entity, if found.
163 * Returns A pointer to the entity structure or NULL if not found.
166 xmlGetEntityFromDtd(const xmlDtd
*dtd
, const xmlChar
*name
) {
167 xmlEntitiesTablePtr table
;
169 if((dtd
!= NULL
) && (dtd
->entities
!= NULL
)) {
170 table
= (xmlEntitiesTablePtr
) dtd
->entities
;
171 return((xmlEntityPtr
) xmlHashLookup(table
, name
));
172 /* return(xmlGetEntityFromTable(table, name)); */
177 * xmlGetParameterEntityFromDtd:
178 * @dtd: A pointer to the DTD to search
179 * @name: The entity name
181 * Do an entity lookup in the DTD parameter entity hash table and
182 * return the corresponding entity, if found.
184 * Returns A pointer to the entity structure or NULL if not found.
187 xmlGetParameterEntityFromDtd(const xmlDtd
*dtd
, const xmlChar
*name
) {
188 xmlEntitiesTablePtr table
;
190 if ((dtd
!= NULL
) && (dtd
->pentities
!= NULL
)) {
191 table
= (xmlEntitiesTablePtr
) dtd
->pentities
;
192 return((xmlEntityPtr
) xmlHashLookup(table
, name
));
193 /* return(xmlGetEntityFromTable(table, name)); */
197 #endif /* LIBXML_TREE_ENABLED */
199 /************************************************************************
201 * QName handling helper *
203 ************************************************************************/
208 * @prefix: the prefix
209 * @memory: preallocated memory
210 * @len: preallocated memory length
212 * Builds the QName @prefix:@ncname in @memory if there is enough space
213 * and prefix is not NULL nor empty, otherwise allocate a new string.
214 * If prefix is NULL or empty it returns ncname.
216 * Returns the new string which must be freed by the caller if different from
217 * @memory and @ncname or NULL in case of error
220 xmlBuildQName(const xmlChar
*ncname
, const xmlChar
*prefix
,
221 xmlChar
*memory
, int len
) {
225 if (ncname
== NULL
) return(NULL
);
226 if (prefix
== NULL
) return((xmlChar
*) ncname
);
228 lenn
= strlen((char *) ncname
);
229 lenp
= strlen((char *) prefix
);
231 if ((memory
== NULL
) || (len
< lenn
+ lenp
+ 2)) {
232 ret
= (xmlChar
*) xmlMallocAtomic(lenn
+ lenp
+ 2);
234 xmlTreeErrMemory("building QName");
240 memcpy(&ret
[0], prefix
, lenp
);
242 memcpy(&ret
[lenp
+ 1], ncname
, lenn
);
243 ret
[lenn
+ lenp
+ 1] = 0;
249 * @name: the full QName
250 * @prefix: a xmlChar **
252 * parse an XML qualified name string
254 * [NS 5] QName ::= (Prefix ':')? LocalPart
256 * [NS 6] Prefix ::= NCName
258 * [NS 7] LocalPart ::= NCName
260 * Returns NULL if the name doesn't have a prefix. Otherwise, returns the
261 * local part, and prefix is updated to get the Prefix. Both the return value
262 * and the prefix must be freed by the caller.
265 xmlSplitQName2(const xmlChar
*name
, xmlChar
**prefix
) {
269 if (prefix
== NULL
) return(NULL
);
271 if (name
== NULL
) return(NULL
);
273 #ifndef XML_XML_NAMESPACE
274 /* xml: prefix is not really a namespace */
275 if ((name
[0] == 'x') && (name
[1] == 'm') &&
276 (name
[2] == 'l') && (name
[3] == ':'))
280 /* nasty but valid */
285 * we are not trying to validate but just to cut, and yes it will
286 * work even if this is as set of UTF-8 encoded chars
288 while ((name
[len
] != 0) && (name
[len
] != ':'))
294 *prefix
= xmlStrndup(name
, len
);
295 if (*prefix
== NULL
) {
296 xmlTreeErrMemory("QName split");
299 ret
= xmlStrdup(&name
[len
+ 1]);
301 xmlTreeErrMemory("QName split");
302 if (*prefix
!= NULL
) {
314 * @name: the full QName
317 * parse an XML qualified name string,i
319 * returns NULL if it is not a Qualified Name, otherwise, update len
320 * with the length in byte of the prefix and return a pointer
321 * to the start of the name without the prefix
325 xmlSplitQName3(const xmlChar
*name
, int *len
) {
328 if (name
== NULL
) return(NULL
);
329 if (len
== NULL
) return(NULL
);
331 /* nasty but valid */
336 * we are not trying to validate but just to cut, and yes it will
337 * work even if this is as set of UTF-8 encoded chars
339 while ((name
[l
] != 0) && (name
[l
] != ':'))
350 /************************************************************************
352 * Check Name, NCName and QName strings *
354 ************************************************************************/
356 #define CUR_SCHAR(s, l) xmlStringCurrentChar(NULL, s, &l)
358 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XPATH_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) || defined(LIBXML_DEBUG_ENABLED) || defined (LIBXML_HTML_ENABLED) || defined(LIBXML_SAX1_ENABLED) || defined(LIBXML_HTML_ENABLED) || defined(LIBXML_WRITER_ENABLED) || defined(LIBXML_LEGACY_ENABLED)
361 * @value: the value to check
362 * @space: allow spaces in front and end of the string
364 * Check that a value conforms to the lexical space of NCName
366 * Returns 0 if this validates, a positive error code number otherwise
367 * and -1 in case of internal or API error.
370 xmlValidateNCName(const xmlChar
*value
, int space
) {
371 const xmlChar
*cur
= value
;
378 * First quick algorithm for ASCII range
381 while (IS_BLANK_CH(*cur
)) cur
++;
382 if (((*cur
>= 'a') && (*cur
<= 'z')) || ((*cur
>= 'A') && (*cur
<= 'Z')) ||
387 while (((*cur
>= 'a') && (*cur
<= 'z')) ||
388 ((*cur
>= 'A') && (*cur
<= 'Z')) ||
389 ((*cur
>= '0') && (*cur
<= '9')) ||
390 (*cur
== '_') || (*cur
== '-') || (*cur
== '.'))
393 while (IS_BLANK_CH(*cur
)) cur
++;
399 * Second check for chars outside the ASCII range
402 c
= CUR_SCHAR(cur
, l
);
404 while (IS_BLANK(c
)) {
406 c
= CUR_SCHAR(cur
, l
);
409 if ((!IS_LETTER(c
)) && (c
!= '_'))
412 c
= CUR_SCHAR(cur
, l
);
413 while (IS_LETTER(c
) || IS_DIGIT(c
) || (c
== '.') ||
414 (c
== '-') || (c
== '_') || IS_COMBINING(c
) ||
417 c
= CUR_SCHAR(cur
, l
);
420 while (IS_BLANK(c
)) {
422 c
= CUR_SCHAR(cur
, l
);
432 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
435 * @value: the value to check
436 * @space: allow spaces in front and end of the string
438 * Check that a value conforms to the lexical space of QName
440 * Returns 0 if this validates, a positive error code number otherwise
441 * and -1 in case of internal or API error.
444 xmlValidateQName(const xmlChar
*value
, int space
) {
445 const xmlChar
*cur
= value
;
451 * First quick algorithm for ASCII range
454 while (IS_BLANK_CH(*cur
)) cur
++;
455 if (((*cur
>= 'a') && (*cur
<= 'z')) || ((*cur
>= 'A') && (*cur
<= 'Z')) ||
460 while (((*cur
>= 'a') && (*cur
<= 'z')) ||
461 ((*cur
>= 'A') && (*cur
<= 'Z')) ||
462 ((*cur
>= '0') && (*cur
<= '9')) ||
463 (*cur
== '_') || (*cur
== '-') || (*cur
== '.'))
467 if (((*cur
>= 'a') && (*cur
<= 'z')) ||
468 ((*cur
>= 'A') && (*cur
<= 'Z')) ||
473 while (((*cur
>= 'a') && (*cur
<= 'z')) ||
474 ((*cur
>= 'A') && (*cur
<= 'Z')) ||
475 ((*cur
>= '0') && (*cur
<= '9')) ||
476 (*cur
== '_') || (*cur
== '-') || (*cur
== '.'))
480 while (IS_BLANK_CH(*cur
)) cur
++;
486 * Second check for chars outside the ASCII range
489 c
= CUR_SCHAR(cur
, l
);
491 while (IS_BLANK(c
)) {
493 c
= CUR_SCHAR(cur
, l
);
496 if ((!IS_LETTER(c
)) && (c
!= '_'))
499 c
= CUR_SCHAR(cur
, l
);
500 while (IS_LETTER(c
) || IS_DIGIT(c
) || (c
== '.') ||
501 (c
== '-') || (c
== '_') || IS_COMBINING(c
) ||
504 c
= CUR_SCHAR(cur
, l
);
508 c
= CUR_SCHAR(cur
, l
);
509 if ((!IS_LETTER(c
)) && (c
!= '_'))
512 c
= CUR_SCHAR(cur
, l
);
513 while (IS_LETTER(c
) || IS_DIGIT(c
) || (c
== '.') ||
514 (c
== '-') || (c
== '_') || IS_COMBINING(c
) ||
517 c
= CUR_SCHAR(cur
, l
);
521 while (IS_BLANK(c
)) {
523 c
= CUR_SCHAR(cur
, l
);
533 * @value: the value to check
534 * @space: allow spaces in front and end of the string
536 * Check that a value conforms to the lexical space of Name
538 * Returns 0 if this validates, a positive error code number otherwise
539 * and -1 in case of internal or API error.
542 xmlValidateName(const xmlChar
*value
, int space
) {
543 const xmlChar
*cur
= value
;
549 * First quick algorithm for ASCII range
552 while (IS_BLANK_CH(*cur
)) cur
++;
553 if (((*cur
>= 'a') && (*cur
<= 'z')) || ((*cur
>= 'A') && (*cur
<= 'Z')) ||
554 (*cur
== '_') || (*cur
== ':'))
558 while (((*cur
>= 'a') && (*cur
<= 'z')) ||
559 ((*cur
>= 'A') && (*cur
<= 'Z')) ||
560 ((*cur
>= '0') && (*cur
<= '9')) ||
561 (*cur
== '_') || (*cur
== '-') || (*cur
== '.') || (*cur
== ':'))
564 while (IS_BLANK_CH(*cur
)) cur
++;
570 * Second check for chars outside the ASCII range
573 c
= CUR_SCHAR(cur
, l
);
575 while (IS_BLANK(c
)) {
577 c
= CUR_SCHAR(cur
, l
);
580 if ((!IS_LETTER(c
)) && (c
!= '_') && (c
!= ':'))
583 c
= CUR_SCHAR(cur
, l
);
584 while (IS_LETTER(c
) || IS_DIGIT(c
) || (c
== '.') || (c
== ':') ||
585 (c
== '-') || (c
== '_') || IS_COMBINING(c
) || IS_EXTENDER(c
)) {
587 c
= CUR_SCHAR(cur
, l
);
590 while (IS_BLANK(c
)) {
592 c
= CUR_SCHAR(cur
, l
);
601 * xmlValidateNMToken:
602 * @value: the value to check
603 * @space: allow spaces in front and end of the string
605 * Check that a value conforms to the lexical space of NMToken
607 * Returns 0 if this validates, a positive error code number otherwise
608 * and -1 in case of internal or API error.
611 xmlValidateNMToken(const xmlChar
*value
, int space
) {
612 const xmlChar
*cur
= value
;
618 * First quick algorithm for ASCII range
621 while (IS_BLANK_CH(*cur
)) cur
++;
622 if (((*cur
>= 'a') && (*cur
<= 'z')) ||
623 ((*cur
>= 'A') && (*cur
<= 'Z')) ||
624 ((*cur
>= '0') && (*cur
<= '9')) ||
625 (*cur
== '_') || (*cur
== '-') || (*cur
== '.') || (*cur
== ':'))
629 while (((*cur
>= 'a') && (*cur
<= 'z')) ||
630 ((*cur
>= 'A') && (*cur
<= 'Z')) ||
631 ((*cur
>= '0') && (*cur
<= '9')) ||
632 (*cur
== '_') || (*cur
== '-') || (*cur
== '.') || (*cur
== ':'))
635 while (IS_BLANK_CH(*cur
)) cur
++;
641 * Second check for chars outside the ASCII range
644 c
= CUR_SCHAR(cur
, l
);
646 while (IS_BLANK(c
)) {
648 c
= CUR_SCHAR(cur
, l
);
651 if (!(IS_LETTER(c
) || IS_DIGIT(c
) || (c
== '.') || (c
== ':') ||
652 (c
== '-') || (c
== '_') || IS_COMBINING(c
) || IS_EXTENDER(c
)))
655 c
= CUR_SCHAR(cur
, l
);
656 while (IS_LETTER(c
) || IS_DIGIT(c
) || (c
== '.') || (c
== ':') ||
657 (c
== '-') || (c
== '_') || IS_COMBINING(c
) || IS_EXTENDER(c
)) {
659 c
= CUR_SCHAR(cur
, l
);
662 while (IS_BLANK(c
)) {
664 c
= CUR_SCHAR(cur
, l
);
671 #endif /* LIBXML_TREE_ENABLED */
673 /************************************************************************
675 * Allocation and deallocation of basic structures *
677 ************************************************************************/
680 * xmlSetBufferAllocationScheme:
681 * @scheme: allocation method to use
683 * Set the buffer allocation method. Types are
684 * XML_BUFFER_ALLOC_EXACT - use exact sizes, keeps memory usage down
685 * XML_BUFFER_ALLOC_DOUBLEIT - double buffer when extra needed,
686 * improves performance
689 xmlSetBufferAllocationScheme(xmlBufferAllocationScheme scheme
) {
690 if ((scheme
== XML_BUFFER_ALLOC_EXACT
) ||
691 (scheme
== XML_BUFFER_ALLOC_DOUBLEIT
) ||
692 (scheme
== XML_BUFFER_ALLOC_HYBRID
))
693 xmlBufferAllocScheme
= scheme
;
697 * xmlGetBufferAllocationScheme:
700 * XML_BUFFER_ALLOC_EXACT - use exact sizes, keeps memory usage down
701 * XML_BUFFER_ALLOC_DOUBLEIT - double buffer when extra needed,
702 * improves performance
703 * XML_BUFFER_ALLOC_HYBRID - use exact sizes on small strings to keep memory usage tight
704 * in normal usage, and doubleit on large strings to avoid
705 * pathological performance.
707 * Returns the current allocation scheme
709 xmlBufferAllocationScheme
710 xmlGetBufferAllocationScheme(void) {
711 return(xmlBufferAllocScheme
);
716 * @node: the element carrying the namespace
717 * @href: the URI associated
718 * @prefix: the prefix for the namespace
720 * Creation of a new Namespace. This function will refuse to create
721 * a namespace with a similar prefix than an existing one present on this
723 * Note that for a default namespace, @prefix should be NULL.
725 * We use href==NULL in the case of an element creation where the namespace
728 * Returns a new namespace pointer or NULL
731 xmlNewNs(xmlNodePtr node
, const xmlChar
*href
, const xmlChar
*prefix
) {
734 if ((node
!= NULL
) && (node
->type
!= XML_ELEMENT_NODE
))
737 if ((prefix
!= NULL
) && (xmlStrEqual(prefix
, BAD_CAST
"xml"))) {
738 /* xml namespace is predefined, no need to add it */
739 if (xmlStrEqual(href
, XML_XML_NAMESPACE
))
743 * Problem, this is an attempt to bind xml prefix to a wrong
744 * namespace, which breaks
745 * Namespace constraint: Reserved Prefixes and Namespace Names
746 * from XML namespace. But documents authors may not care in
747 * their context so let's proceed.
752 * Allocate a new Namespace and fill the fields.
754 cur
= (xmlNsPtr
) xmlMalloc(sizeof(xmlNs
));
756 xmlTreeErrMemory("building namespace");
759 memset(cur
, 0, sizeof(xmlNs
));
760 cur
->type
= XML_LOCAL_NAMESPACE
;
763 cur
->href
= xmlStrdup(href
);
765 cur
->prefix
= xmlStrdup(prefix
);
768 * Add it at the end to preserve parsing order ...
769 * and checks for existing use of the prefix
772 if (node
->nsDef
== NULL
) {
775 xmlNsPtr prev
= node
->nsDef
;
777 if (((prev
->prefix
== NULL
) && (cur
->prefix
== NULL
)) ||
778 (xmlStrEqual(prev
->prefix
, cur
->prefix
))) {
782 while (prev
->next
!= NULL
) {
784 if (((prev
->prefix
== NULL
) && (cur
->prefix
== NULL
)) ||
785 (xmlStrEqual(prev
->prefix
, cur
->prefix
))) {
798 * @node: a node in the document
799 * @ns: a namespace pointer
801 * Associate a namespace to a node, a posteriori.
804 xmlSetNs(xmlNodePtr node
, xmlNsPtr ns
) {
807 xmlGenericError(xmlGenericErrorContext
,
808 "xmlSetNs: node == NULL\n");
812 if ((node
->type
== XML_ELEMENT_NODE
) ||
813 (node
->type
== XML_ATTRIBUTE_NODE
))
819 * @cur: the namespace pointer
821 * Free up the structures associated to a namespace
824 xmlFreeNs(xmlNsPtr cur
) {
827 xmlGenericError(xmlGenericErrorContext
,
828 "xmlFreeNs : ns == NULL\n");
832 if (cur
->href
!= NULL
) xmlFree((char *) cur
->href
);
833 if (cur
->prefix
!= NULL
) xmlFree((char *) cur
->prefix
);
839 * @cur: the first namespace pointer
841 * Free up all the structures associated to the chained namespaces.
844 xmlFreeNsList(xmlNsPtr cur
) {
848 xmlGenericError(xmlGenericErrorContext
,
849 "xmlFreeNsList : ns == NULL\n");
853 while (cur
!= NULL
) {
862 * @doc: the document pointer
863 * @name: the DTD name
864 * @ExternalID: the external ID
865 * @SystemID: the system ID
867 * Creation of a new DTD for the external subset. To create an
868 * internal subset, use xmlCreateIntSubset().
870 * Returns a pointer to the new DTD structure
873 xmlNewDtd(xmlDocPtr doc
, const xmlChar
*name
,
874 const xmlChar
*ExternalID
, const xmlChar
*SystemID
) {
877 if ((doc
!= NULL
) && (doc
->extSubset
!= NULL
)) {
879 xmlGenericError(xmlGenericErrorContext
,
880 "xmlNewDtd(%s): document %s already have a DTD %s\n",
881 /* !!! */ (char *) name
, doc
->name
,
882 /* !!! */ (char *)doc
->extSubset
->name
);
888 * Allocate a new DTD and fill the fields.
890 cur
= (xmlDtdPtr
) xmlMalloc(sizeof(xmlDtd
));
892 xmlTreeErrMemory("building DTD");
895 memset(cur
, 0 , sizeof(xmlDtd
));
896 cur
->type
= XML_DTD_NODE
;
899 cur
->name
= xmlStrdup(name
);
900 if (ExternalID
!= NULL
)
901 cur
->ExternalID
= xmlStrdup(ExternalID
);
902 if (SystemID
!= NULL
)
903 cur
->SystemID
= xmlStrdup(SystemID
);
905 doc
->extSubset
= cur
;
908 if ((__xmlRegisterCallbacks
) && (xmlRegisterNodeDefaultValue
))
909 xmlRegisterNodeDefaultValue((xmlNodePtr
)cur
);
915 * @doc: the document pointer
917 * Get the internal subset of a document
918 * Returns a pointer to the DTD structure or NULL if not found
922 xmlGetIntSubset(const xmlDoc
*doc
) {
928 while (cur
!= NULL
) {
929 if (cur
->type
== XML_DTD_NODE
)
930 return((xmlDtdPtr
) cur
);
933 return((xmlDtdPtr
) doc
->intSubset
);
937 * xmlCreateIntSubset:
938 * @doc: the document pointer
939 * @name: the DTD name
940 * @ExternalID: the external (PUBLIC) ID
941 * @SystemID: the system ID
943 * Create the internal subset of a document
944 * Returns a pointer to the new DTD structure
947 xmlCreateIntSubset(xmlDocPtr doc
, const xmlChar
*name
,
948 const xmlChar
*ExternalID
, const xmlChar
*SystemID
) {
951 if ((doc
!= NULL
) && (xmlGetIntSubset(doc
) != NULL
)) {
953 xmlGenericError(xmlGenericErrorContext
,
955 "xmlCreateIntSubset(): document %s already have an internal subset\n",
962 * Allocate a new DTD and fill the fields.
964 cur
= (xmlDtdPtr
) xmlMalloc(sizeof(xmlDtd
));
966 xmlTreeErrMemory("building internal subset");
969 memset(cur
, 0, sizeof(xmlDtd
));
970 cur
->type
= XML_DTD_NODE
;
973 cur
->name
= xmlStrdup(name
);
974 if (cur
->name
== NULL
) {
975 xmlTreeErrMemory("building internal subset");
980 if (ExternalID
!= NULL
) {
981 cur
->ExternalID
= xmlStrdup(ExternalID
);
982 if (cur
->ExternalID
== NULL
) {
983 xmlTreeErrMemory("building internal subset");
984 if (cur
->name
!= NULL
)
985 xmlFree((char *)cur
->name
);
990 if (SystemID
!= NULL
) {
991 cur
->SystemID
= xmlStrdup(SystemID
);
992 if (cur
->SystemID
== NULL
) {
993 xmlTreeErrMemory("building internal subset");
994 if (cur
->name
!= NULL
)
995 xmlFree((char *)cur
->name
);
996 if (cur
->ExternalID
!= NULL
)
997 xmlFree((char *)cur
->ExternalID
);
1003 doc
->intSubset
= cur
;
1006 if (doc
->children
== NULL
) {
1007 doc
->children
= (xmlNodePtr
) cur
;
1008 doc
->last
= (xmlNodePtr
) cur
;
1010 if (doc
->type
== XML_HTML_DOCUMENT_NODE
) {
1013 prev
= doc
->children
;
1014 prev
->prev
= (xmlNodePtr
) cur
;
1016 doc
->children
= (xmlNodePtr
) cur
;
1020 next
= doc
->children
;
1021 while ((next
!= NULL
) && (next
->type
!= XML_ELEMENT_NODE
))
1024 cur
->prev
= doc
->last
;
1025 cur
->prev
->next
= (xmlNodePtr
) cur
;
1027 doc
->last
= (xmlNodePtr
) cur
;
1030 cur
->prev
= next
->prev
;
1031 if (cur
->prev
== NULL
)
1032 doc
->children
= (xmlNodePtr
) cur
;
1034 cur
->prev
->next
= (xmlNodePtr
) cur
;
1035 next
->prev
= (xmlNodePtr
) cur
;
1041 if ((__xmlRegisterCallbacks
) && (xmlRegisterNodeDefaultValue
))
1042 xmlRegisterNodeDefaultValue((xmlNodePtr
)cur
);
1050 * Free a string if it is not owned by the "dict" dictionary in the
1053 #define DICT_FREE(str) \
1054 if ((str) && ((!dict) || \
1055 (xmlDictOwns(dict, (const xmlChar *)(str)) == 0))) \
1056 xmlFree((char *)(str));
1063 * Copy a string using a "dict" dictionary in the current scope,
1066 #define DICT_COPY(str, cpy) \
1069 if (xmlDictOwns(dict, (const xmlChar *)(str))) \
1070 cpy = (xmlChar *) (str); \
1072 cpy = (xmlChar *) xmlDictLookup((dict), (const xmlChar *)(str), -1); \
1074 cpy = xmlStrdup((const xmlChar *)(str)); }
1080 * Copy a string using a "dict" dictionary in the current scope,
1083 #define DICT_CONST_COPY(str, cpy) \
1086 if (xmlDictOwns(dict, (const xmlChar *)(str))) \
1087 cpy = (const xmlChar *) (str); \
1089 cpy = xmlDictLookup((dict), (const xmlChar *)(str), -1); \
1091 cpy = (const xmlChar *) xmlStrdup((const xmlChar *)(str)); }
1096 * @cur: the DTD structure to free up
1098 * Free a DTD structure.
1101 xmlFreeDtd(xmlDtdPtr cur
) {
1102 xmlDictPtr dict
= NULL
;
1107 if (cur
->doc
!= NULL
) dict
= cur
->doc
->dict
;
1109 if ((__xmlRegisterCallbacks
) && (xmlDeregisterNodeDefaultValue
))
1110 xmlDeregisterNodeDefaultValue((xmlNodePtr
)cur
);
1112 if (cur
->children
!= NULL
) {
1113 xmlNodePtr next
, c
= cur
->children
;
1116 * Cleanup all nodes which are not part of the specific lists
1117 * of notations, elements, attributes and entities.
1121 if ((c
->type
!= XML_NOTATION_NODE
) &&
1122 (c
->type
!= XML_ELEMENT_DECL
) &&
1123 (c
->type
!= XML_ATTRIBUTE_DECL
) &&
1124 (c
->type
!= XML_ENTITY_DECL
)) {
1131 DICT_FREE(cur
->name
)
1132 DICT_FREE(cur
->SystemID
)
1133 DICT_FREE(cur
->ExternalID
)
1135 if (cur
->notations
!= NULL
)
1136 xmlFreeNotationTable((xmlNotationTablePtr
) cur
->notations
);
1138 if (cur
->elements
!= NULL
)
1139 xmlFreeElementTable((xmlElementTablePtr
) cur
->elements
);
1140 if (cur
->attributes
!= NULL
)
1141 xmlFreeAttributeTable((xmlAttributeTablePtr
) cur
->attributes
);
1142 if (cur
->entities
!= NULL
)
1143 xmlFreeEntitiesTable((xmlEntitiesTablePtr
) cur
->entities
);
1144 if (cur
->pentities
!= NULL
)
1145 xmlFreeEntitiesTable((xmlEntitiesTablePtr
) cur
->pentities
);
1152 * @version: xmlChar string giving the version of XML "1.0"
1154 * Creates a new XML document
1156 * Returns a new document
1159 xmlNewDoc(const xmlChar
*version
) {
1162 if (version
== NULL
)
1163 version
= (const xmlChar
*) "1.0";
1166 * Allocate a new document and fill the fields.
1168 cur
= (xmlDocPtr
) xmlMalloc(sizeof(xmlDoc
));
1170 xmlTreeErrMemory("building doc");
1173 memset(cur
, 0, sizeof(xmlDoc
));
1174 cur
->type
= XML_DOCUMENT_NODE
;
1176 cur
->version
= xmlStrdup(version
);
1177 if (cur
->version
== NULL
) {
1178 xmlTreeErrMemory("building doc");
1182 cur
->standalone
= -1;
1183 cur
->compression
= -1; /* not initialized */
1185 cur
->parseFlags
= 0;
1186 cur
->properties
= XML_DOC_USERBUILT
;
1188 * The in memory encoding is always UTF8
1189 * This field will never change and would
1190 * be obsolete if not for binary compatibility.
1192 cur
->charset
= XML_CHAR_ENCODING_UTF8
;
1194 if ((__xmlRegisterCallbacks
) && (xmlRegisterNodeDefaultValue
))
1195 xmlRegisterNodeDefaultValue((xmlNodePtr
)cur
);
1201 * @cur: pointer to the document
1203 * Free up all the structures used by a document, tree included.
1206 xmlFreeDoc(xmlDocPtr cur
) {
1207 xmlDtdPtr extSubset
, intSubset
;
1208 xmlDictPtr dict
= NULL
;
1212 xmlGenericError(xmlGenericErrorContext
,
1213 "xmlFreeDoc : document == NULL\n");
1217 #ifdef LIBXML_DEBUG_RUNTIME
1218 #ifdef LIBXML_DEBUG_ENABLED
1219 xmlDebugCheckDocument(stderr
, cur
);
1223 if (cur
!= NULL
) dict
= cur
->dict
;
1225 if ((__xmlRegisterCallbacks
) && (xmlDeregisterNodeDefaultValue
))
1226 xmlDeregisterNodeDefaultValue((xmlNodePtr
)cur
);
1229 * Do this before freeing the children list to avoid ID lookups
1231 if (cur
->ids
!= NULL
) xmlFreeIDTable((xmlIDTablePtr
) cur
->ids
);
1233 if (cur
->refs
!= NULL
) xmlFreeRefTable((xmlRefTablePtr
) cur
->refs
);
1235 extSubset
= cur
->extSubset
;
1236 intSubset
= cur
->intSubset
;
1237 if (intSubset
== extSubset
)
1239 if (extSubset
!= NULL
) {
1240 xmlUnlinkNode((xmlNodePtr
) cur
->extSubset
);
1241 cur
->extSubset
= NULL
;
1242 xmlFreeDtd(extSubset
);
1244 if (intSubset
!= NULL
) {
1245 xmlUnlinkNode((xmlNodePtr
) cur
->intSubset
);
1246 cur
->intSubset
= NULL
;
1247 xmlFreeDtd(intSubset
);
1250 if (cur
->children
!= NULL
) xmlFreeNodeList(cur
->children
);
1251 if (cur
->oldNs
!= NULL
) xmlFreeNsList(cur
->oldNs
);
1253 DICT_FREE(cur
->version
)
1254 DICT_FREE(cur
->name
)
1255 DICT_FREE(cur
->encoding
)
1258 if (dict
) xmlDictFree(dict
);
1262 * xmlStringLenGetNodeList:
1263 * @doc: the document
1264 * @value: the value of the text
1265 * @len: the length of the string value
1267 * Parse the value string and build the node list associated. Should
1268 * produce a flat tree with only TEXTs and ENTITY_REFs.
1269 * Returns a pointer to the first child
1272 xmlStringLenGetNodeList(const xmlDoc
*doc
, const xmlChar
*value
, int len
) {
1273 xmlNodePtr ret
= NULL
, last
= NULL
;
1276 const xmlChar
*cur
, *end
;
1281 if (value
== NULL
) return(NULL
);
1285 buf
= xmlBufCreateSize(0);
1286 if (buf
== NULL
) return(NULL
);
1287 xmlBufSetAllocationScheme(buf
, XML_BUFFER_ALLOC_DOUBLEIT
);
1290 while ((cur
< end
) && (*cur
!= 0)) {
1291 if (cur
[0] == '&') {
1296 * Save the current text.
1299 if (xmlBufAdd(buf
, q
, cur
- q
))
1303 if ((cur
+ 2 < end
) && (cur
[1] == '#') && (cur
[2] == 'x')) {
1309 while (tmp
!= ';') { /* Non input consuming loop */
1311 * If you find an integer overflow here when fuzzing,
1312 * the bug is probably elsewhere. This function should
1313 * only receive entities that were already validated by
1314 * the parser, typically by xmlParseAttValueComplex
1315 * calling xmlStringDecodeEntities.
1317 * So it's better *not* to check for overflow to
1318 * potentially discover new bugs.
1320 if ((tmp
>= '0') && (tmp
<= '9'))
1321 charval
= charval
* 16 + (tmp
- '0');
1322 else if ((tmp
>= 'a') && (tmp
<= 'f'))
1323 charval
= charval
* 16 + (tmp
- 'a') + 10;
1324 else if ((tmp
>= 'A') && (tmp
<= 'F'))
1325 charval
= charval
* 16 + (tmp
- 'A') + 10;
1327 xmlTreeErr(XML_TREE_INVALID_HEX
, (xmlNodePtr
) doc
,
1341 } else if ((cur
+ 1 < end
) && (cur
[1] == '#')) {
1347 while (tmp
!= ';') { /* Non input consuming loops */
1348 /* Don't check for integer overflow, see above. */
1349 if ((tmp
>= '0') && (tmp
<= '9'))
1350 charval
= charval
* 10 + (tmp
- '0');
1352 xmlTreeErr(XML_TREE_INVALID_DEC
, (xmlNodePtr
) doc
,
1368 * Read the entity string
1372 while ((cur
< end
) && (*cur
!= 0) && (*cur
!= ';')) cur
++;
1373 if ((cur
>= end
) || (*cur
== 0)) {
1374 xmlTreeErr(XML_TREE_UNTERMINATED_ENTITY
, (xmlNodePtr
) doc
,
1380 * Predefined entities don't generate nodes
1382 val
= xmlStrndup(q
, cur
- q
);
1383 ent
= xmlGetDocEntity(doc
, val
);
1384 if ((ent
!= NULL
) &&
1385 (ent
->etype
== XML_INTERNAL_PREDEFINED_ENTITY
)) {
1387 if (xmlBufCat(buf
, ent
->content
))
1392 * Flush buffer so far
1394 if (!xmlBufIsEmpty(buf
)) {
1395 node
= xmlNewDocText(doc
, NULL
);
1397 if (val
!= NULL
) xmlFree(val
);
1400 node
->content
= xmlBufDetach(buf
);
1405 last
= xmlAddNextSibling(last
, node
);
1410 * Create a new REFERENCE_REF node
1412 node
= xmlNewReference(doc
, val
);
1414 if (val
!= NULL
) xmlFree(val
);
1417 else if ((ent
!= NULL
) && (ent
->children
== NULL
)) {
1420 /* Set to non-NULL value to avoid recursion. */
1421 ent
->children
= (xmlNodePtr
) -1;
1422 ent
->children
= xmlStringGetNodeList(doc
,
1423 (const xmlChar
*)node
->content
);
1425 temp
= ent
->children
;
1427 temp
->parent
= (xmlNodePtr
)ent
;
1435 last
= xmlAddNextSibling(last
, node
);
1447 l
= xmlCopyCharMultiByte(buffer
, charval
);
1450 if (xmlBufCat(buf
, buffer
))
1460 * Handle the last piece of text.
1462 if (xmlBufAdd(buf
, q
, cur
- q
))
1466 if (!xmlBufIsEmpty(buf
)) {
1467 node
= xmlNewDocText(doc
, NULL
);
1468 if (node
== NULL
) goto out
;
1469 node
->content
= xmlBufDetach(buf
);
1474 xmlAddNextSibling(last
, node
);
1476 } else if (ret
== NULL
) {
1477 ret
= xmlNewDocText(doc
, BAD_CAST
"");
1486 * xmlStringGetNodeList:
1487 * @doc: the document
1488 * @value: the value of the attribute
1490 * Parse the value string and build the node list associated. Should
1491 * produce a flat tree with only TEXTs and ENTITY_REFs.
1492 * Returns a pointer to the first child
1495 xmlStringGetNodeList(const xmlDoc
*doc
, const xmlChar
*value
) {
1496 xmlNodePtr ret
= NULL
, last
= NULL
;
1499 const xmlChar
*cur
= value
;
1504 if (value
== NULL
) return(NULL
);
1506 buf
= xmlBufCreateSize(0);
1507 if (buf
== NULL
) return(NULL
);
1508 xmlBufSetAllocationScheme(buf
, XML_BUFFER_ALLOC_DOUBLEIT
);
1512 if (cur
[0] == '&') {
1517 * Save the current text.
1520 if (xmlBufAdd(buf
, q
, cur
- q
))
1524 if ((cur
[1] == '#') && (cur
[2] == 'x')) {
1527 while (tmp
!= ';') { /* Non input consuming loop */
1528 /* Don't check for integer overflow, see above. */
1529 if ((tmp
>= '0') && (tmp
<= '9'))
1530 charval
= charval
* 16 + (tmp
- '0');
1531 else if ((tmp
>= 'a') && (tmp
<= 'f'))
1532 charval
= charval
* 16 + (tmp
- 'a') + 10;
1533 else if ((tmp
>= 'A') && (tmp
<= 'F'))
1534 charval
= charval
* 16 + (tmp
- 'A') + 10;
1536 xmlTreeErr(XML_TREE_INVALID_HEX
, (xmlNodePtr
) doc
,
1547 } else if (cur
[1] == '#') {
1550 while (tmp
!= ';') { /* Non input consuming loops */
1551 /* Don't check for integer overflow, see above. */
1552 if ((tmp
>= '0') && (tmp
<= '9'))
1553 charval
= charval
* 10 + (tmp
- '0');
1555 xmlTreeErr(XML_TREE_INVALID_DEC
, (xmlNodePtr
) doc
,
1568 * Read the entity string
1572 while ((*cur
!= 0) && (*cur
!= ';')) cur
++;
1574 xmlTreeErr(XML_TREE_UNTERMINATED_ENTITY
,
1575 (xmlNodePtr
) doc
, (const char *) q
);
1580 * Predefined entities don't generate nodes
1582 val
= xmlStrndup(q
, cur
- q
);
1583 ent
= xmlGetDocEntity(doc
, val
);
1584 if ((ent
!= NULL
) &&
1585 (ent
->etype
== XML_INTERNAL_PREDEFINED_ENTITY
)) {
1587 if (xmlBufCat(buf
, ent
->content
))
1592 * Flush buffer so far
1594 if (!xmlBufIsEmpty(buf
)) {
1595 node
= xmlNewDocText(doc
, NULL
);
1597 if (val
!= NULL
) xmlFree(val
);
1600 node
->content
= xmlBufDetach(buf
);
1605 last
= xmlAddNextSibling(last
, node
);
1610 * Create a new REFERENCE_REF node
1612 node
= xmlNewReference(doc
, val
);
1614 if (val
!= NULL
) xmlFree(val
);
1617 else if ((ent
!= NULL
) && (ent
->children
== NULL
)) {
1620 /* Set to non-NULL value to avoid recursion. */
1621 ent
->children
= (xmlNodePtr
) -1;
1622 ent
->children
= xmlStringGetNodeList(doc
,
1623 (const xmlChar
*)node
->content
);
1625 temp
= ent
->children
;
1627 temp
->parent
= (xmlNodePtr
)ent
;
1635 last
= xmlAddNextSibling(last
, node
);
1647 len
= xmlCopyCharMultiByte(buffer
, charval
);
1650 if (xmlBufCat(buf
, buffer
))
1657 if ((cur
!= q
) || (ret
== NULL
)) {
1659 * Handle the last piece of text.
1661 xmlBufAdd(buf
, q
, cur
- q
);
1664 if (!xmlBufIsEmpty(buf
)) {
1665 node
= xmlNewDocText(doc
, NULL
);
1670 node
->content
= xmlBufDetach(buf
);
1675 xmlAddNextSibling(last
, node
);
1685 * xmlNodeListGetString:
1686 * @doc: the document
1687 * @list: a Node list
1688 * @inLine: should we replace entity contents or show their external form
1690 * Build the string equivalent to the text contained in the Node list
1691 * made of TEXTs and ENTITY_REFs
1693 * Returns a pointer to the string copy, the caller must free it with xmlFree().
1696 xmlNodeListGetString(xmlDocPtr doc
, const xmlNode
*list
, int inLine
)
1698 const xmlNode
*node
= list
;
1699 xmlChar
*ret
= NULL
;
1705 if ((list
->parent
!= NULL
) && (list
->parent
->type
== XML_ATTRIBUTE_NODE
))
1710 while (node
!= NULL
) {
1711 if ((node
->type
== XML_TEXT_NODE
) ||
1712 (node
->type
== XML_CDATA_SECTION_NODE
)) {
1714 ret
= xmlStrcat(ret
, node
->content
);
1719 buffer
= xmlEncodeAttributeEntities(doc
, node
->content
);
1721 buffer
= xmlEncodeEntitiesReentrant(doc
, node
->content
);
1722 if (buffer
!= NULL
) {
1723 ret
= xmlStrcat(ret
, buffer
);
1727 } else if (node
->type
== XML_ENTITY_REF_NODE
) {
1729 ent
= xmlGetDocEntity(doc
, node
->name
);
1733 /* an entity content can be any "well balanced chunk",
1734 * i.e. the result of the content [43] production:
1735 * http://www.w3.org/TR/REC-xml#NT-content.
1736 * So it can contain text, CDATA section or nested
1737 * entity reference nodes (among others).
1738 * -> we recursive call xmlNodeListGetString()
1739 * which handles these types */
1740 buffer
= xmlNodeListGetString(doc
, ent
->children
, 1);
1741 if (buffer
!= NULL
) {
1742 ret
= xmlStrcat(ret
, buffer
);
1746 ret
= xmlStrcat(ret
, node
->content
);
1753 ret
= xmlStrncat(ret
, buf
, 1);
1754 ret
= xmlStrcat(ret
, node
->name
);
1757 ret
= xmlStrncat(ret
, buf
, 1);
1762 xmlGenericError(xmlGenericErrorContext
,
1763 "xmlGetNodeListString : invalid node type %d\n",
1772 #ifdef LIBXML_TREE_ENABLED
1774 * xmlNodeListGetRawString:
1775 * @doc: the document
1776 * @list: a Node list
1777 * @inLine: should we replace entity contents or show their external form
1779 * Builds the string equivalent to the text contained in the Node list
1780 * made of TEXTs and ENTITY_REFs, contrary to xmlNodeListGetString()
1781 * this function doesn't do any character encoding handling.
1783 * Returns a pointer to the string copy, the caller must free it with xmlFree().
1786 xmlNodeListGetRawString(const xmlDoc
*doc
, const xmlNode
*list
, int inLine
)
1788 const xmlNode
*node
= list
;
1789 xmlChar
*ret
= NULL
;
1795 while (node
!= NULL
) {
1796 if ((node
->type
== XML_TEXT_NODE
) ||
1797 (node
->type
== XML_CDATA_SECTION_NODE
)) {
1799 ret
= xmlStrcat(ret
, node
->content
);
1803 buffer
= xmlEncodeSpecialChars(doc
, node
->content
);
1804 if (buffer
!= NULL
) {
1805 ret
= xmlStrcat(ret
, buffer
);
1809 } else if (node
->type
== XML_ENTITY_REF_NODE
) {
1811 ent
= xmlGetDocEntity(doc
, node
->name
);
1815 /* an entity content can be any "well balanced chunk",
1816 * i.e. the result of the content [43] production:
1817 * http://www.w3.org/TR/REC-xml#NT-content.
1818 * So it can contain text, CDATA section or nested
1819 * entity reference nodes (among others).
1820 * -> we recursive call xmlNodeListGetRawString()
1821 * which handles these types */
1823 xmlNodeListGetRawString(doc
, ent
->children
, 1);
1824 if (buffer
!= NULL
) {
1825 ret
= xmlStrcat(ret
, buffer
);
1829 ret
= xmlStrcat(ret
, node
->content
);
1836 ret
= xmlStrncat(ret
, buf
, 1);
1837 ret
= xmlStrcat(ret
, node
->name
);
1840 ret
= xmlStrncat(ret
, buf
, 1);
1845 xmlGenericError(xmlGenericErrorContext
,
1846 "xmlGetNodeListString : invalid node type %d\n",
1854 #endif /* LIBXML_TREE_ENABLED */
1857 xmlNewPropInternal(xmlNodePtr node
, xmlNsPtr ns
,
1858 const xmlChar
* name
, const xmlChar
* value
,
1862 xmlDocPtr doc
= NULL
;
1864 if ((node
!= NULL
) && (node
->type
!= XML_ELEMENT_NODE
)) {
1865 if ((eatname
== 1) &&
1866 ((node
->doc
== NULL
) ||
1867 (!(xmlDictOwns(node
->doc
->dict
, name
)))))
1868 xmlFree((xmlChar
*) name
);
1873 * Allocate a new property and fill the fields.
1875 cur
= (xmlAttrPtr
) xmlMalloc(sizeof(xmlAttr
));
1877 if ((eatname
== 1) &&
1878 ((node
== NULL
) || (node
->doc
== NULL
) ||
1879 (!(xmlDictOwns(node
->doc
->dict
, name
)))))
1880 xmlFree((xmlChar
*) name
);
1881 xmlTreeErrMemory("building attribute");
1884 memset(cur
, 0, sizeof(xmlAttr
));
1885 cur
->type
= XML_ATTRIBUTE_NODE
;
1895 if ((doc
!= NULL
) && (doc
->dict
!= NULL
))
1896 cur
->name
= (xmlChar
*) xmlDictLookup(doc
->dict
, name
, -1);
1898 cur
->name
= xmlStrdup(name
);
1902 if (value
!= NULL
) {
1905 cur
->children
= xmlNewDocText(doc
, value
);
1907 tmp
= cur
->children
;
1908 while (tmp
!= NULL
) {
1909 tmp
->parent
= (xmlNodePtr
) cur
;
1910 if (tmp
->next
== NULL
)
1917 * Add it at the end to preserve parsing order ...
1920 if (node
->properties
== NULL
) {
1921 node
->properties
= cur
;
1923 xmlAttrPtr prev
= node
->properties
;
1925 while (prev
->next
!= NULL
)
1932 if ((value
!= NULL
) && (node
!= NULL
) &&
1933 (xmlIsID(node
->doc
, node
, cur
) == 1))
1934 xmlAddID(NULL
, node
->doc
, value
, cur
);
1936 if ((__xmlRegisterCallbacks
) && (xmlRegisterNodeDefaultValue
))
1937 xmlRegisterNodeDefaultValue((xmlNodePtr
) cur
);
1941 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_HTML_ENABLED) || \
1942 defined(LIBXML_SCHEMAS_ENABLED)
1945 * @node: the holding node
1946 * @name: the name of the attribute
1947 * @value: the value of the attribute
1949 * Create a new property carried by a node.
1950 * Returns a pointer to the attribute
1953 xmlNewProp(xmlNodePtr node
, const xmlChar
*name
, const xmlChar
*value
) {
1957 xmlGenericError(xmlGenericErrorContext
,
1958 "xmlNewProp : name == NULL\n");
1963 return xmlNewPropInternal(node
, NULL
, name
, value
, 0);
1965 #endif /* LIBXML_TREE_ENABLED */
1969 * @node: the holding node
1970 * @ns: the namespace
1971 * @name: the name of the attribute
1972 * @value: the value of the attribute
1974 * Create a new property tagged with a namespace and carried by a node.
1975 * Returns a pointer to the attribute
1978 xmlNewNsProp(xmlNodePtr node
, xmlNsPtr ns
, const xmlChar
*name
,
1979 const xmlChar
*value
) {
1983 xmlGenericError(xmlGenericErrorContext
,
1984 "xmlNewNsProp : name == NULL\n");
1989 return xmlNewPropInternal(node
, ns
, name
, value
, 0);
1993 * xmlNewNsPropEatName:
1994 * @node: the holding node
1995 * @ns: the namespace
1996 * @name: the name of the attribute
1997 * @value: the value of the attribute
1999 * Create a new property tagged with a namespace and carried by a node.
2000 * Returns a pointer to the attribute
2003 xmlNewNsPropEatName(xmlNodePtr node
, xmlNsPtr ns
, xmlChar
*name
,
2004 const xmlChar
*value
) {
2008 xmlGenericError(xmlGenericErrorContext
,
2009 "xmlNewNsPropEatName : name == NULL\n");
2014 return xmlNewPropInternal(node
, ns
, name
, value
, 1);
2019 * @doc: the document
2020 * @name: the name of the attribute
2021 * @value: the value of the attribute
2023 * Create a new property carried by a document.
2024 * NOTE: @value is supposed to be a piece of XML CDATA, so it allows entity
2025 * references, but XML special chars need to be escaped first by using
2026 * xmlEncodeEntitiesReentrant(). Use xmlNewProp() if you don't need
2029 * Returns a pointer to the attribute
2032 xmlNewDocProp(xmlDocPtr doc
, const xmlChar
*name
, const xmlChar
*value
) {
2037 xmlGenericError(xmlGenericErrorContext
,
2038 "xmlNewDocProp : name == NULL\n");
2044 * Allocate a new property and fill the fields.
2046 cur
= (xmlAttrPtr
) xmlMalloc(sizeof(xmlAttr
));
2048 xmlTreeErrMemory("building attribute");
2051 memset(cur
, 0, sizeof(xmlAttr
));
2052 cur
->type
= XML_ATTRIBUTE_NODE
;
2054 if ((doc
!= NULL
) && (doc
->dict
!= NULL
))
2055 cur
->name
= xmlDictLookup(doc
->dict
, name
, -1);
2057 cur
->name
= xmlStrdup(name
);
2059 if (value
!= NULL
) {
2062 cur
->children
= xmlStringGetNodeList(doc
, value
);
2065 tmp
= cur
->children
;
2066 while (tmp
!= NULL
) {
2067 tmp
->parent
= (xmlNodePtr
) cur
;
2068 if (tmp
->next
== NULL
)
2074 if ((__xmlRegisterCallbacks
) && (xmlRegisterNodeDefaultValue
))
2075 xmlRegisterNodeDefaultValue((xmlNodePtr
)cur
);
2081 * @cur: the first property in the list
2083 * Free a property and all its siblings, all the children are freed too.
2086 xmlFreePropList(xmlAttrPtr cur
) {
2088 if (cur
== NULL
) return;
2089 while (cur
!= NULL
) {
2098 * @cur: an attribute
2100 * Free one attribute, all the content is freed too
2103 xmlFreeProp(xmlAttrPtr cur
) {
2104 xmlDictPtr dict
= NULL
;
2105 if (cur
== NULL
) return;
2107 if (cur
->doc
!= NULL
) dict
= cur
->doc
->dict
;
2109 if ((__xmlRegisterCallbacks
) && (xmlDeregisterNodeDefaultValue
))
2110 xmlDeregisterNodeDefaultValue((xmlNodePtr
)cur
);
2112 /* Check for ID removal -> leading to invalid references ! */
2113 if ((cur
->doc
!= NULL
) && (cur
->atype
== XML_ATTRIBUTE_ID
)) {
2114 xmlRemoveID(cur
->doc
, cur
);
2116 if (cur
->children
!= NULL
) xmlFreeNodeList(cur
->children
);
2117 DICT_FREE(cur
->name
)
2123 * @cur: an attribute
2125 * Unlink and free one attribute, all the content is freed too
2126 * Note this doesn't work for namespace definition attributes
2128 * Returns 0 if success and -1 in case of error.
2131 xmlRemoveProp(xmlAttrPtr cur
) {
2135 xmlGenericError(xmlGenericErrorContext
,
2136 "xmlRemoveProp : cur == NULL\n");
2140 if (cur
->parent
== NULL
) {
2142 xmlGenericError(xmlGenericErrorContext
,
2143 "xmlRemoveProp : cur->parent == NULL\n");
2147 tmp
= cur
->parent
->properties
;
2149 cur
->parent
->properties
= cur
->next
;
2150 if (cur
->next
!= NULL
)
2151 cur
->next
->prev
= NULL
;
2155 while (tmp
!= NULL
) {
2156 if (tmp
->next
== cur
) {
2157 tmp
->next
= cur
->next
;
2158 if (tmp
->next
!= NULL
)
2159 tmp
->next
->prev
= tmp
;
2166 xmlGenericError(xmlGenericErrorContext
,
2167 "xmlRemoveProp : attribute not owned by its node\n");
2174 * @doc: the target document
2175 * @name: the processing instruction name
2176 * @content: the PI content
2178 * Creation of a processing instruction element.
2179 * Returns a pointer to the new node object.
2182 xmlNewDocPI(xmlDocPtr doc
, const xmlChar
*name
, const xmlChar
*content
) {
2187 xmlGenericError(xmlGenericErrorContext
,
2188 "xmlNewPI : name == NULL\n");
2194 * Allocate a new node and fill the fields.
2196 cur
= (xmlNodePtr
) xmlMalloc(sizeof(xmlNode
));
2198 xmlTreeErrMemory("building PI");
2201 memset(cur
, 0, sizeof(xmlNode
));
2202 cur
->type
= XML_PI_NODE
;
2204 if ((doc
!= NULL
) && (doc
->dict
!= NULL
))
2205 cur
->name
= xmlDictLookup(doc
->dict
, name
, -1);
2207 cur
->name
= xmlStrdup(name
);
2208 if (content
!= NULL
) {
2209 cur
->content
= xmlStrdup(content
);
2213 if ((__xmlRegisterCallbacks
) && (xmlRegisterNodeDefaultValue
))
2214 xmlRegisterNodeDefaultValue((xmlNodePtr
)cur
);
2220 * @name: the processing instruction name
2221 * @content: the PI content
2223 * Creation of a processing instruction element.
2225 * Use of this function is DISCOURAGED in favor of xmlNewDocPI.
2227 * Returns a pointer to the new node object.
2230 xmlNewPI(const xmlChar
*name
, const xmlChar
*content
) {
2231 return(xmlNewDocPI(NULL
, name
, content
));
2236 * @ns: namespace if any
2237 * @name: the node name
2239 * Creation of a new node element. @ns is optional (NULL).
2241 * Use of this function is DISCOURAGED in favor of xmlNewDocNode.
2243 * Returns a pointer to the new node object. Uses xmlStrdup() to make
2247 xmlNewNode(xmlNsPtr ns
, const xmlChar
*name
) {
2252 xmlGenericError(xmlGenericErrorContext
,
2253 "xmlNewNode : name == NULL\n");
2259 * Allocate a new node and fill the fields.
2261 cur
= (xmlNodePtr
) xmlMalloc(sizeof(xmlNode
));
2263 xmlTreeErrMemory("building node");
2266 memset(cur
, 0, sizeof(xmlNode
));
2267 cur
->type
= XML_ELEMENT_NODE
;
2269 cur
->name
= xmlStrdup(name
);
2272 if ((__xmlRegisterCallbacks
) && (xmlRegisterNodeDefaultValue
))
2273 xmlRegisterNodeDefaultValue(cur
);
2278 * xmlNewNodeEatName:
2279 * @ns: namespace if any
2280 * @name: the node name
2282 * Creation of a new node element. @ns is optional (NULL).
2284 * Use of this function is DISCOURAGED in favor of xmlNewDocNodeEatName.
2286 * Returns a pointer to the new node object, with pointer @name as
2287 * new node's name. Use xmlNewNode() if a copy of @name string is
2288 * is needed as new node's name.
2291 xmlNewNodeEatName(xmlNsPtr ns
, xmlChar
*name
) {
2296 xmlGenericError(xmlGenericErrorContext
,
2297 "xmlNewNode : name == NULL\n");
2303 * Allocate a new node and fill the fields.
2305 cur
= (xmlNodePtr
) xmlMalloc(sizeof(xmlNode
));
2307 xmlTreeErrMemory("building node");
2308 /* we can't check here that name comes from the doc dictionary */
2311 memset(cur
, 0, sizeof(xmlNode
));
2312 cur
->type
= XML_ELEMENT_NODE
;
2317 if ((__xmlRegisterCallbacks
) && (xmlRegisterNodeDefaultValue
))
2318 xmlRegisterNodeDefaultValue((xmlNodePtr
)cur
);
2324 * @doc: the document
2325 * @ns: namespace if any
2326 * @name: the node name
2327 * @content: the XML text content if any
2329 * Creation of a new node element within a document. @ns and @content
2330 * are optional (NULL).
2331 * NOTE: @content is supposed to be a piece of XML CDATA, so it allow entities
2332 * references, but XML special chars need to be escaped first by using
2333 * xmlEncodeEntitiesReentrant(). Use xmlNewDocRawNode() if you don't
2334 * need entities support.
2336 * Returns a pointer to the new node object.
2339 xmlNewDocNode(xmlDocPtr doc
, xmlNsPtr ns
,
2340 const xmlChar
*name
, const xmlChar
*content
) {
2343 if ((doc
!= NULL
) && (doc
->dict
!= NULL
))
2344 cur
= xmlNewNodeEatName(ns
, (xmlChar
*)
2345 xmlDictLookup(doc
->dict
, name
, -1));
2347 cur
= xmlNewNode(ns
, name
);
2350 if (content
!= NULL
) {
2351 cur
->children
= xmlStringGetNodeList(doc
, content
);
2352 UPDATE_LAST_CHILD_AND_PARENT(cur
)
2360 * xmlNewDocNodeEatName:
2361 * @doc: the document
2362 * @ns: namespace if any
2363 * @name: the node name
2364 * @content: the XML text content if any
2366 * Creation of a new node element within a document. @ns and @content
2367 * are optional (NULL).
2368 * NOTE: @content is supposed to be a piece of XML CDATA, so it allow entities
2369 * references, but XML special chars need to be escaped first by using
2370 * xmlEncodeEntitiesReentrant(). Use xmlNewDocRawNode() if you don't
2371 * need entities support.
2373 * Returns a pointer to the new node object.
2376 xmlNewDocNodeEatName(xmlDocPtr doc
, xmlNsPtr ns
,
2377 xmlChar
*name
, const xmlChar
*content
) {
2380 cur
= xmlNewNodeEatName(ns
, name
);
2383 if (content
!= NULL
) {
2384 cur
->children
= xmlStringGetNodeList(doc
, content
);
2385 UPDATE_LAST_CHILD_AND_PARENT(cur
)
2388 /* if name don't come from the doc dictionary free it here */
2389 if ((name
!= NULL
) && (doc
!= NULL
) &&
2390 (!(xmlDictOwns(doc
->dict
, name
))))
2396 #ifdef LIBXML_TREE_ENABLED
2399 * @doc: the document
2400 * @ns: namespace if any
2401 * @name: the node name
2402 * @content: the text content if any
2404 * Creation of a new node element within a document. @ns and @content
2405 * are optional (NULL).
2407 * Returns a pointer to the new node object.
2410 xmlNewDocRawNode(xmlDocPtr doc
, xmlNsPtr ns
,
2411 const xmlChar
*name
, const xmlChar
*content
) {
2414 cur
= xmlNewDocNode(doc
, ns
, name
, NULL
);
2417 if (content
!= NULL
) {
2418 cur
->children
= xmlNewDocText(doc
, content
);
2419 UPDATE_LAST_CHILD_AND_PARENT(cur
)
2426 * xmlNewDocFragment:
2427 * @doc: the document owning the fragment
2429 * Creation of a new Fragment node.
2430 * Returns a pointer to the new node object.
2433 xmlNewDocFragment(xmlDocPtr doc
) {
2437 * Allocate a new DocumentFragment node and fill the fields.
2439 cur
= (xmlNodePtr
) xmlMalloc(sizeof(xmlNode
));
2441 xmlTreeErrMemory("building fragment");
2444 memset(cur
, 0, sizeof(xmlNode
));
2445 cur
->type
= XML_DOCUMENT_FRAG_NODE
;
2449 if ((__xmlRegisterCallbacks
) && (xmlRegisterNodeDefaultValue
))
2450 xmlRegisterNodeDefaultValue(cur
);
2453 #endif /* LIBXML_TREE_ENABLED */
2457 * @content: the text content
2459 * Creation of a new text node.
2461 * Use of this function is DISCOURAGED in favor of xmlNewDocText.
2463 * Returns a pointer to the new node object.
2466 xmlNewText(const xmlChar
*content
) {
2470 * Allocate a new node and fill the fields.
2472 cur
= (xmlNodePtr
) xmlMalloc(sizeof(xmlNode
));
2474 xmlTreeErrMemory("building text");
2477 memset(cur
, 0, sizeof(xmlNode
));
2478 cur
->type
= XML_TEXT_NODE
;
2480 cur
->name
= xmlStringText
;
2481 if (content
!= NULL
) {
2482 cur
->content
= xmlStrdup(content
);
2485 if ((__xmlRegisterCallbacks
) && (xmlRegisterNodeDefaultValue
))
2486 xmlRegisterNodeDefaultValue(cur
);
2490 #ifdef LIBXML_TREE_ENABLED
2493 * @parent: the parent node
2494 * @ns: a namespace if any
2495 * @name: the name of the child
2496 * @content: the text content of the child if any.
2498 * Creation of a new child element, added at the end of @parent children list.
2499 * @ns and @content parameters are optional (NULL). If @ns is NULL, the newly
2500 * created element inherits the namespace of @parent. If @content is non NULL,
2501 * a child TEXT node will be created containing the string @content.
2502 * NOTE: Use xmlNewChild() if @content will contain entities that need to be
2503 * preserved. Use this function, xmlNewTextChild(), if you need to ensure that
2504 * reserved XML chars that might appear in @content, such as the ampersand,
2505 * greater-than or less-than signs, are automatically replaced by their XML
2506 * escaped entity representations.
2508 * Returns a pointer to the new node object.
2511 xmlNewTextChild(xmlNodePtr parent
, xmlNsPtr ns
,
2512 const xmlChar
*name
, const xmlChar
*content
) {
2513 xmlNodePtr cur
, prev
;
2515 if (parent
== NULL
) {
2517 xmlGenericError(xmlGenericErrorContext
,
2518 "xmlNewTextChild : parent == NULL\n");
2525 xmlGenericError(xmlGenericErrorContext
,
2526 "xmlNewTextChild : name == NULL\n");
2532 * Allocate a new node
2534 if (parent
->type
== XML_ELEMENT_NODE
) {
2536 cur
= xmlNewDocRawNode(parent
->doc
, parent
->ns
, name
, content
);
2538 cur
= xmlNewDocRawNode(parent
->doc
, ns
, name
, content
);
2539 } else if ((parent
->type
== XML_DOCUMENT_NODE
) ||
2540 (parent
->type
== XML_HTML_DOCUMENT_NODE
)) {
2542 cur
= xmlNewDocRawNode((xmlDocPtr
) parent
, NULL
, name
, content
);
2544 cur
= xmlNewDocRawNode((xmlDocPtr
) parent
, ns
, name
, content
);
2545 } else if (parent
->type
== XML_DOCUMENT_FRAG_NODE
) {
2546 cur
= xmlNewDocRawNode( parent
->doc
, ns
, name
, content
);
2550 if (cur
== NULL
) return(NULL
);
2553 * add the new element at the end of the children list.
2555 cur
->type
= XML_ELEMENT_NODE
;
2556 cur
->parent
= parent
;
2557 cur
->doc
= parent
->doc
;
2558 if (parent
->children
== NULL
) {
2559 parent
->children
= cur
;
2562 prev
= parent
->last
;
2570 #endif /* LIBXML_TREE_ENABLED */
2574 * @doc: the document
2575 * @name: the char ref string, starting with # or "&# ... ;"
2577 * Creation of a new character reference node.
2578 * Returns a pointer to the new node object.
2581 xmlNewCharRef(xmlDocPtr doc
, const xmlChar
*name
) {
2588 * Allocate a new node and fill the fields.
2590 cur
= (xmlNodePtr
) xmlMalloc(sizeof(xmlNode
));
2592 xmlTreeErrMemory("building character reference");
2595 memset(cur
, 0, sizeof(xmlNode
));
2596 cur
->type
= XML_ENTITY_REF_NODE
;
2599 if (name
[0] == '&') {
2602 len
= xmlStrlen(name
);
2603 if (name
[len
- 1] == ';')
2604 cur
->name
= xmlStrndup(name
, len
- 1);
2606 cur
->name
= xmlStrndup(name
, len
);
2608 cur
->name
= xmlStrdup(name
);
2610 if ((__xmlRegisterCallbacks
) && (xmlRegisterNodeDefaultValue
))
2611 xmlRegisterNodeDefaultValue(cur
);
2617 * @doc: the document
2618 * @name: the reference name, or the reference string with & and ;
2620 * Creation of a new reference node.
2621 * Returns a pointer to the new node object.
2624 xmlNewReference(const xmlDoc
*doc
, const xmlChar
*name
) {
2632 * Allocate a new node and fill the fields.
2634 cur
= (xmlNodePtr
) xmlMalloc(sizeof(xmlNode
));
2636 xmlTreeErrMemory("building reference");
2639 memset(cur
, 0, sizeof(xmlNode
));
2640 cur
->type
= XML_ENTITY_REF_NODE
;
2642 cur
->doc
= (xmlDoc
*)doc
;
2643 if (name
[0] == '&') {
2646 len
= xmlStrlen(name
);
2647 if (name
[len
- 1] == ';')
2648 cur
->name
= xmlStrndup(name
, len
- 1);
2650 cur
->name
= xmlStrndup(name
, len
);
2652 cur
->name
= xmlStrdup(name
);
2654 ent
= xmlGetDocEntity(doc
, cur
->name
);
2656 cur
->content
= ent
->content
;
2658 * The parent pointer in entity is a DTD pointer and thus is NOT
2659 * updated. Not sure if this is 100% correct.
2662 cur
->children
= (xmlNodePtr
) ent
;
2663 cur
->last
= (xmlNodePtr
) ent
;
2666 if ((__xmlRegisterCallbacks
) && (xmlRegisterNodeDefaultValue
))
2667 xmlRegisterNodeDefaultValue(cur
);
2673 * @doc: the document
2674 * @content: the text content
2676 * Creation of a new text node within a document.
2677 * Returns a pointer to the new node object.
2680 xmlNewDocText(const xmlDoc
*doc
, const xmlChar
*content
) {
2683 cur
= xmlNewText(content
);
2684 if (cur
!= NULL
) cur
->doc
= (xmlDoc
*)doc
;
2690 * @content: the text content
2691 * @len: the text len.
2693 * Use of this function is DISCOURAGED in favor of xmlNewDocTextLen.
2695 * Creation of a new text node with an extra parameter for the content's length
2696 * Returns a pointer to the new node object.
2699 xmlNewTextLen(const xmlChar
*content
, int len
) {
2703 * Allocate a new node and fill the fields.
2705 cur
= (xmlNodePtr
) xmlMalloc(sizeof(xmlNode
));
2707 xmlTreeErrMemory("building text");
2710 memset(cur
, 0, sizeof(xmlNode
));
2711 cur
->type
= XML_TEXT_NODE
;
2713 cur
->name
= xmlStringText
;
2714 if (content
!= NULL
) {
2715 cur
->content
= xmlStrndup(content
, len
);
2718 if ((__xmlRegisterCallbacks
) && (xmlRegisterNodeDefaultValue
))
2719 xmlRegisterNodeDefaultValue(cur
);
2725 * @doc: the document
2726 * @content: the text content
2727 * @len: the text len.
2729 * Creation of a new text node with an extra content length parameter. The
2730 * text node pertain to a given document.
2731 * Returns a pointer to the new node object.
2734 xmlNewDocTextLen(xmlDocPtr doc
, const xmlChar
*content
, int len
) {
2737 cur
= xmlNewTextLen(content
, len
);
2738 if (cur
!= NULL
) cur
->doc
= doc
;
2744 * @content: the comment content
2746 * Use of this function is DISCOURAGED in favor of xmlNewDocComment.
2748 * Creation of a new node containing a comment.
2749 * Returns a pointer to the new node object.
2752 xmlNewComment(const xmlChar
*content
) {
2756 * Allocate a new node and fill the fields.
2758 cur
= (xmlNodePtr
) xmlMalloc(sizeof(xmlNode
));
2760 xmlTreeErrMemory("building comment");
2763 memset(cur
, 0, sizeof(xmlNode
));
2764 cur
->type
= XML_COMMENT_NODE
;
2766 cur
->name
= xmlStringComment
;
2767 if (content
!= NULL
) {
2768 cur
->content
= xmlStrdup(content
);
2771 if ((__xmlRegisterCallbacks
) && (xmlRegisterNodeDefaultValue
))
2772 xmlRegisterNodeDefaultValue(cur
);
2778 * @doc: the document
2779 * @content: the CDATA block content content
2780 * @len: the length of the block
2782 * Creation of a new node containing a CDATA block.
2783 * Returns a pointer to the new node object.
2786 xmlNewCDataBlock(xmlDocPtr doc
, const xmlChar
*content
, int len
) {
2790 * Allocate a new node and fill the fields.
2792 cur
= (xmlNodePtr
) xmlMalloc(sizeof(xmlNode
));
2794 xmlTreeErrMemory("building CDATA");
2797 memset(cur
, 0, sizeof(xmlNode
));
2798 cur
->type
= XML_CDATA_SECTION_NODE
;
2801 if (content
!= NULL
) {
2802 cur
->content
= xmlStrndup(content
, len
);
2805 if ((__xmlRegisterCallbacks
) && (xmlRegisterNodeDefaultValue
))
2806 xmlRegisterNodeDefaultValue(cur
);
2812 * @doc: the document
2813 * @content: the comment content
2815 * Creation of a new node containing a comment within a document.
2816 * Returns a pointer to the new node object.
2819 xmlNewDocComment(xmlDocPtr doc
, const xmlChar
*content
) {
2822 cur
= xmlNewComment(content
);
2823 if (cur
!= NULL
) cur
->doc
= doc
;
2827 static const xmlChar
*_copyStringForNewDictIfNeeded(xmlDictPtr oldDict
, xmlDictPtr newDict
, const xmlChar
*oldValue
) {
2828 const xmlChar
*newValue
= oldValue
;
2830 int oldDictOwnsOldValue
= oldDict
&& (xmlDictOwns(oldDict
, oldValue
) == 1);
2831 if (oldDictOwnsOldValue
) {
2833 newValue
= xmlDictLookup(newDict
, oldValue
, -1);
2835 newValue
= xmlStrdup(oldValue
);
2843 * @tree: the top element
2844 * @doc: the document
2846 * update all nodes under the tree to point to the right document
2849 xmlSetTreeDoc(xmlNodePtr tree
, xmlDocPtr doc
) {
2852 if ((tree
== NULL
) || (tree
->type
== XML_NAMESPACE_DECL
))
2854 if (tree
->doc
!= doc
) {
2855 xmlDictPtr oldTreeDict
= tree
->doc
? tree
->doc
->dict
: NULL
;
2856 xmlDictPtr newDict
= doc
? doc
->dict
: NULL
;
2858 if(tree
->type
== XML_ELEMENT_NODE
) {
2859 prop
= tree
->properties
;
2860 while (prop
!= NULL
) {
2861 if (prop
->atype
== XML_ATTRIBUTE_ID
) {
2862 xmlRemoveID(tree
->doc
, prop
);
2865 if (prop
->doc
!= doc
) {
2866 xmlDictPtr oldPropDict
= prop
->doc
? prop
->doc
->dict
: NULL
;
2867 prop
->name
= _copyStringForNewDictIfNeeded(oldPropDict
, newDict
, prop
->name
);
2870 xmlSetListDoc(prop
->children
, doc
);
2873 * TODO: ID attributes should be also added to the new
2874 * document, but this breaks things like xmlReplaceNode.
2875 * The underlying problem is that xmlRemoveID is only called
2876 * if a node is destroyed, not if it's unlinked.
2879 if (xmlIsID(doc
, tree
, prop
)) {
2880 xmlChar
*idVal
= xmlNodeListGetString(doc
, prop
->children
,
2882 xmlAddID(NULL
, doc
, idVal
, prop
);
2889 if (tree
->type
== XML_ENTITY_REF_NODE
) {
2891 * Clear 'children' which points to the entity declaration
2892 * from the original document.
2894 tree
->children
= NULL
;
2895 } else if (tree
->children
!= NULL
) {
2896 xmlSetListDoc(tree
->children
, doc
);
2899 tree
->name
= _copyStringForNewDictIfNeeded(oldTreeDict
, newDict
, tree
->name
);
2900 tree
->content
= (xmlChar
*)_copyStringForNewDictIfNeeded(oldTreeDict
, NULL
, tree
->content
);
2901 /* FIXME: tree->ns should be updated as in xmlStaticCopyNode(). */
2908 * @list: the first element
2909 * @doc: the document
2911 * update all nodes in the list to point to the right document
2914 xmlSetListDoc(xmlNodePtr list
, xmlDocPtr doc
) {
2917 if ((list
== NULL
) || (list
->type
== XML_NAMESPACE_DECL
))
2920 while (cur
!= NULL
) {
2921 if (cur
->doc
!= doc
)
2922 xmlSetTreeDoc(cur
, doc
);
2927 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
2930 * @parent: the parent node
2931 * @ns: a namespace if any
2932 * @name: the name of the child
2933 * @content: the XML content of the child if any.
2935 * Creation of a new child element, added at the end of @parent children list.
2936 * @ns and @content parameters are optional (NULL). If @ns is NULL, the newly
2937 * created element inherits the namespace of @parent. If @content is non NULL,
2938 * a child list containing the TEXTs and ENTITY_REFs node will be created.
2939 * NOTE: @content is supposed to be a piece of XML CDATA, so it allows entity
2940 * references. XML special chars must be escaped first by using
2941 * xmlEncodeEntitiesReentrant(), or xmlNewTextChild() should be used.
2943 * Returns a pointer to the new node object.
2946 xmlNewChild(xmlNodePtr parent
, xmlNsPtr ns
,
2947 const xmlChar
*name
, const xmlChar
*content
) {
2948 xmlNodePtr cur
, prev
;
2950 if (parent
== NULL
) {
2952 xmlGenericError(xmlGenericErrorContext
,
2953 "xmlNewChild : parent == NULL\n");
2960 xmlGenericError(xmlGenericErrorContext
,
2961 "xmlNewChild : name == NULL\n");
2967 * Allocate a new node
2969 if (parent
->type
== XML_ELEMENT_NODE
) {
2971 cur
= xmlNewDocNode(parent
->doc
, parent
->ns
, name
, content
);
2973 cur
= xmlNewDocNode(parent
->doc
, ns
, name
, content
);
2974 } else if ((parent
->type
== XML_DOCUMENT_NODE
) ||
2975 (parent
->type
== XML_HTML_DOCUMENT_NODE
)) {
2977 cur
= xmlNewDocNode((xmlDocPtr
) parent
, NULL
, name
, content
);
2979 cur
= xmlNewDocNode((xmlDocPtr
) parent
, ns
, name
, content
);
2980 } else if (parent
->type
== XML_DOCUMENT_FRAG_NODE
) {
2981 cur
= xmlNewDocNode( parent
->doc
, ns
, name
, content
);
2985 if (cur
== NULL
) return(NULL
);
2988 * add the new element at the end of the children list.
2990 cur
->type
= XML_ELEMENT_NODE
;
2991 cur
->parent
= parent
;
2992 cur
->doc
= parent
->doc
;
2993 if (parent
->children
== NULL
) {
2994 parent
->children
= cur
;
2997 prev
= parent
->last
;
3005 #endif /* LIBXML_TREE_ENABLED */
3008 * xmlAddPropSibling:
3009 * @prev: the attribute to which @prop is added after
3010 * @cur: the base attribute passed to calling function
3011 * @prop: the new attribute
3013 * Add a new attribute after @prev using @cur as base attribute.
3014 * When inserting before @cur, @prev is passed as @cur->prev.
3015 * When inserting after @cur, @prev is passed as @cur.
3016 * If an existing attribute is found it is destroyed prior to adding @prop.
3018 * See the note regarding namespaces in xmlAddChild.
3020 * Returns the attribute being inserted or NULL in case of error.
3023 xmlAddPropSibling(xmlNodePtr prev
, xmlNodePtr cur
, xmlNodePtr prop
) {
3026 if ((cur
== NULL
) || (cur
->type
!= XML_ATTRIBUTE_NODE
) ||
3027 (prop
== NULL
) || (prop
->type
!= XML_ATTRIBUTE_NODE
) ||
3028 ((prev
!= NULL
) && (prev
->type
!= XML_ATTRIBUTE_NODE
)))
3031 /* check if an attribute with the same name exists */
3032 if (prop
->ns
== NULL
)
3033 attr
= xmlHasNsProp(cur
->parent
, prop
->name
, NULL
);
3035 attr
= xmlHasNsProp(cur
->parent
, prop
->name
, prop
->ns
->href
);
3037 if (prop
->doc
!= cur
->doc
) {
3038 xmlSetTreeDoc(prop
, cur
->doc
);
3040 prop
->parent
= cur
->parent
;
3043 prop
->next
= prev
->next
;
3046 prop
->next
->prev
= prop
;
3051 if (prop
->prev
== NULL
&& prop
->parent
!= NULL
)
3052 prop
->parent
->properties
= (xmlAttrPtr
) prop
;
3053 if ((attr
!= NULL
) && (attr
->type
!= XML_ATTRIBUTE_DECL
)) {
3054 /* different instance, destroy it (attributes must be unique) */
3055 xmlRemoveProp((xmlAttrPtr
) attr
);
3061 * xmlAddNextSibling:
3062 * @cur: the child node
3063 * @elem: the new node
3065 * Add a new node @elem as the next sibling of @cur
3066 * If the new node was already inserted in a document it is
3067 * first unlinked from its existing context.
3068 * As a result of text merging @elem may be freed.
3069 * If the new node is ATTRIBUTE, it is added into properties instead of children.
3070 * If there is an attribute with equal name, it is first destroyed.
3072 * See the note regarding namespaces in xmlAddChild.
3074 * Returns the new node or NULL in case of error.
3077 xmlAddNextSibling(xmlNodePtr cur
, xmlNodePtr elem
) {
3078 if ((cur
== NULL
) || (cur
->type
== XML_NAMESPACE_DECL
)) {
3080 xmlGenericError(xmlGenericErrorContext
,
3081 "xmlAddNextSibling : cur == NULL\n");
3085 if ((elem
== NULL
) || (elem
->type
== XML_NAMESPACE_DECL
)) {
3087 xmlGenericError(xmlGenericErrorContext
,
3088 "xmlAddNextSibling : elem == NULL\n");
3095 xmlGenericError(xmlGenericErrorContext
,
3096 "xmlAddNextSibling : cur == elem\n");
3101 xmlUnlinkNode(elem
);
3103 if (elem
->type
== XML_TEXT_NODE
) {
3104 if (cur
->type
== XML_TEXT_NODE
) {
3105 xmlNodeAddContent(cur
, elem
->content
);
3109 if ((cur
->next
!= NULL
) && (cur
->next
->type
== XML_TEXT_NODE
) &&
3110 (cur
->name
== cur
->next
->name
)) {
3113 tmp
= xmlStrdup(elem
->content
);
3114 tmp
= xmlStrcat(tmp
, cur
->next
->content
);
3115 xmlNodeSetContent(cur
->next
, tmp
);
3120 } else if (elem
->type
== XML_ATTRIBUTE_NODE
) {
3121 return xmlAddPropSibling(cur
, cur
, elem
);
3124 if (elem
->doc
!= cur
->doc
) {
3125 xmlSetTreeDoc(elem
, cur
->doc
);
3127 elem
->parent
= cur
->parent
;
3129 elem
->next
= cur
->next
;
3131 if (elem
->next
!= NULL
)
3132 elem
->next
->prev
= elem
;
3133 if ((elem
->parent
!= NULL
) && (elem
->parent
->last
== cur
))
3134 elem
->parent
->last
= elem
;
3138 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_HTML_ENABLED) || \
3139 defined(LIBXML_SCHEMAS_ENABLED) || defined(LIBXML_XINCLUDE_ENABLED)
3141 * xmlAddPrevSibling:
3142 * @cur: the child node
3143 * @elem: the new node
3145 * Add a new node @elem as the previous sibling of @cur
3146 * merging adjacent TEXT nodes (@elem may be freed)
3147 * If the new node was already inserted in a document it is
3148 * first unlinked from its existing context.
3149 * If the new node is ATTRIBUTE, it is added into properties instead of children.
3150 * If there is an attribute with equal name, it is first destroyed.
3152 * See the note regarding namespaces in xmlAddChild.
3154 * Returns the new node or NULL in case of error.
3157 xmlAddPrevSibling(xmlNodePtr cur
, xmlNodePtr elem
) {
3158 if ((cur
== NULL
) || (cur
->type
== XML_NAMESPACE_DECL
)) {
3160 xmlGenericError(xmlGenericErrorContext
,
3161 "xmlAddPrevSibling : cur == NULL\n");
3165 if ((elem
== NULL
) || (elem
->type
== XML_NAMESPACE_DECL
)) {
3167 xmlGenericError(xmlGenericErrorContext
,
3168 "xmlAddPrevSibling : elem == NULL\n");
3175 xmlGenericError(xmlGenericErrorContext
,
3176 "xmlAddPrevSibling : cur == elem\n");
3181 xmlUnlinkNode(elem
);
3183 if (elem
->type
== XML_TEXT_NODE
) {
3184 if (cur
->type
== XML_TEXT_NODE
) {
3187 tmp
= xmlStrdup(elem
->content
);
3188 tmp
= xmlStrcat(tmp
, cur
->content
);
3189 xmlNodeSetContent(cur
, tmp
);
3194 if ((cur
->prev
!= NULL
) && (cur
->prev
->type
== XML_TEXT_NODE
) &&
3195 (cur
->name
== cur
->prev
->name
)) {
3196 xmlNodeAddContent(cur
->prev
, elem
->content
);
3200 } else if (elem
->type
== XML_ATTRIBUTE_NODE
) {
3201 return xmlAddPropSibling(cur
->prev
, cur
, elem
);
3204 if (elem
->doc
!= cur
->doc
) {
3205 xmlSetTreeDoc(elem
, cur
->doc
);
3207 elem
->parent
= cur
->parent
;
3209 elem
->prev
= cur
->prev
;
3211 if (elem
->prev
!= NULL
)
3212 elem
->prev
->next
= elem
;
3213 if ((elem
->parent
!= NULL
) && (elem
->parent
->children
== cur
)) {
3214 elem
->parent
->children
= elem
;
3218 #endif /* LIBXML_TREE_ENABLED */
3222 * @cur: the child node
3223 * @elem: the new node
3225 * Add a new element @elem to the list of siblings of @cur
3226 * merging adjacent TEXT nodes (@elem may be freed)
3227 * If the new element was already inserted in a document it is
3228 * first unlinked from its existing context.
3230 * See the note regarding namespaces in xmlAddChild.
3232 * Returns the new element or NULL in case of error.
3235 xmlAddSibling(xmlNodePtr cur
, xmlNodePtr elem
) {
3238 if ((cur
== NULL
) || (cur
->type
== XML_NAMESPACE_DECL
)) {
3240 xmlGenericError(xmlGenericErrorContext
,
3241 "xmlAddSibling : cur == NULL\n");
3246 if ((elem
== NULL
) || (elem
->type
== XML_NAMESPACE_DECL
)) {
3248 xmlGenericError(xmlGenericErrorContext
,
3249 "xmlAddSibling : elem == NULL\n");
3256 xmlGenericError(xmlGenericErrorContext
,
3257 "xmlAddSibling : cur == elem\n");
3263 * Constant time is we can rely on the ->parent->last to find
3266 if ((cur
->type
!= XML_ATTRIBUTE_NODE
) && (cur
->parent
!= NULL
) &&
3267 (cur
->parent
->children
!= NULL
) &&
3268 (cur
->parent
->last
!= NULL
) &&
3269 (cur
->parent
->last
->next
== NULL
)) {
3270 cur
= cur
->parent
->last
;
3272 while (cur
->next
!= NULL
) cur
= cur
->next
;
3275 xmlUnlinkNode(elem
);
3277 if ((cur
->type
== XML_TEXT_NODE
) && (elem
->type
== XML_TEXT_NODE
) &&
3278 (cur
->name
== elem
->name
)) {
3279 xmlNodeAddContent(cur
, elem
->content
);
3282 } else if (elem
->type
== XML_ATTRIBUTE_NODE
) {
3283 return xmlAddPropSibling(cur
, cur
, elem
);
3286 if (elem
->doc
!= cur
->doc
) {
3287 xmlSetTreeDoc(elem
, cur
->doc
);
3289 parent
= cur
->parent
;
3292 elem
->parent
= parent
;
3295 parent
->last
= elem
;
3302 * @parent: the parent node
3303 * @cur: the first node in the list
3305 * Add a list of node at the end of the child list of the parent
3306 * merging adjacent TEXT nodes (@cur may be freed)
3308 * See the note regarding namespaces in xmlAddChild.
3310 * Returns the last child or NULL in case of error.
3313 xmlAddChildList(xmlNodePtr parent
, xmlNodePtr cur
) {
3316 if ((parent
== NULL
) || (parent
->type
== XML_NAMESPACE_DECL
)) {
3318 xmlGenericError(xmlGenericErrorContext
,
3319 "xmlAddChildList : parent == NULL\n");
3324 if ((cur
== NULL
) || (cur
->type
== XML_NAMESPACE_DECL
)) {
3326 xmlGenericError(xmlGenericErrorContext
,
3327 "xmlAddChildList : child == NULL\n");
3332 if ((cur
->doc
!= NULL
) && (parent
->doc
!= NULL
) &&
3333 (cur
->doc
!= parent
->doc
)) {
3335 xmlGenericError(xmlGenericErrorContext
,
3336 "Elements moved to a different document\n");
3341 * add the first element at the end of the children list.
3344 if (parent
->children
== NULL
) {
3345 parent
->children
= cur
;
3348 * If cur and parent->last both are TEXT nodes, then merge them.
3350 if ((cur
->type
== XML_TEXT_NODE
) &&
3351 (parent
->last
->type
== XML_TEXT_NODE
) &&
3352 (cur
->name
== parent
->last
->name
)) {
3353 xmlNodeAddContent(parent
->last
, cur
->content
);
3355 * if it's the only child, nothing more to be done.
3357 if (cur
->next
== NULL
) {
3359 return(parent
->last
);
3365 prev
= parent
->last
;
3369 while (cur
->next
!= NULL
) {
3370 cur
->parent
= parent
;
3371 if (cur
->doc
!= parent
->doc
) {
3372 xmlSetTreeDoc(cur
, parent
->doc
);
3376 cur
->parent
= parent
;
3377 /* the parent may not be linked to a doc ! */
3378 if (cur
->doc
!= parent
->doc
) {
3379 xmlSetTreeDoc(cur
, parent
->doc
);
3388 * @parent: the parent node
3389 * @cur: the child node
3391 * Add a new node to @parent, at the end of the child (or property) list
3392 * merging adjacent TEXT nodes (in which case @cur is freed)
3393 * If the new node is ATTRIBUTE, it is added into properties instead of children.
3394 * If there is an attribute with equal name, it is first destroyed.
3396 * All tree manipulation functions can safely move nodes within a document.
3397 * But when moving nodes from one document to another, references to
3398 * namespaces in element or attribute nodes are NOT fixed. In this case,
3399 * you MUST call xmlReconciliateNs after the move operation to avoid
3402 * Returns the child or NULL in case of error.
3405 xmlAddChild(xmlNodePtr parent
, xmlNodePtr cur
) {
3408 if ((parent
== NULL
) || (parent
->type
== XML_NAMESPACE_DECL
)) {
3410 xmlGenericError(xmlGenericErrorContext
,
3411 "xmlAddChild : parent == NULL\n");
3416 if ((cur
== NULL
) || (cur
->type
== XML_NAMESPACE_DECL
)) {
3418 xmlGenericError(xmlGenericErrorContext
,
3419 "xmlAddChild : child == NULL\n");
3424 if (parent
== cur
) {
3426 xmlGenericError(xmlGenericErrorContext
,
3427 "xmlAddChild : parent == cur\n");
3432 * If cur is a TEXT node, merge its content with adjacent TEXT nodes
3433 * cur is then freed.
3435 if (cur
->type
== XML_TEXT_NODE
) {
3436 if ((parent
->type
== XML_TEXT_NODE
) &&
3437 (parent
->content
!= NULL
) &&
3438 (parent
->name
== cur
->name
)) {
3439 xmlNodeAddContent(parent
, cur
->content
);
3443 if ((parent
->last
!= NULL
) && (parent
->last
->type
== XML_TEXT_NODE
) &&
3444 (parent
->last
->name
== cur
->name
) &&
3445 (parent
->last
!= cur
)) {
3446 xmlNodeAddContent(parent
->last
, cur
->content
);
3448 return(parent
->last
);
3453 * add the new element at the end of the children list.
3456 cur
->parent
= parent
;
3457 if (cur
->doc
!= parent
->doc
) {
3458 xmlSetTreeDoc(cur
, parent
->doc
);
3460 /* this check prevents a loop on tree-traversions if a developer
3461 * tries to add a node to its parent multiple times
3469 if ((parent
->type
== XML_TEXT_NODE
) &&
3470 (parent
->content
!= NULL
) &&
3472 xmlNodeAddContent(parent
, cur
->content
);
3476 if (cur
->type
== XML_ATTRIBUTE_NODE
) {
3477 if (parent
->type
!= XML_ELEMENT_NODE
)
3479 if (parent
->properties
!= NULL
) {
3480 /* check if an attribute with the same name exists */
3481 xmlAttrPtr lastattr
;
3483 if (cur
->ns
== NULL
)
3484 lastattr
= xmlHasNsProp(parent
, cur
->name
, NULL
);
3486 lastattr
= xmlHasNsProp(parent
, cur
->name
, cur
->ns
->href
);
3487 if ((lastattr
!= NULL
) && (lastattr
!= (xmlAttrPtr
) cur
) && (lastattr
->type
!= XML_ATTRIBUTE_DECL
)) {
3488 /* different instance, destroy it (attributes must be unique) */
3489 xmlUnlinkNode((xmlNodePtr
) lastattr
);
3490 xmlFreeProp(lastattr
);
3492 if (lastattr
== (xmlAttrPtr
) cur
)
3496 if (parent
->properties
== NULL
) {
3497 parent
->properties
= (xmlAttrPtr
) cur
;
3500 xmlAttrPtr lastattr
= parent
->properties
;
3501 while (lastattr
->next
!= NULL
) {
3502 lastattr
= lastattr
->next
;
3504 lastattr
->next
= (xmlAttrPtr
) cur
;
3505 ((xmlAttrPtr
) cur
)->prev
= lastattr
;
3508 if (parent
->children
== NULL
) {
3509 parent
->children
= cur
;
3512 prev
= parent
->last
;
3523 * @parent: the parent node
3525 * Search the last child of a node.
3526 * Returns the last child or NULL if none.
3529 xmlGetLastChild(const xmlNode
*parent
) {
3530 if ((parent
== NULL
) || (parent
->type
== XML_NAMESPACE_DECL
)) {
3532 xmlGenericError(xmlGenericErrorContext
,
3533 "xmlGetLastChild : parent == NULL\n");
3537 return(parent
->last
);
3540 #ifdef LIBXML_TREE_ENABLED
3542 * 5 interfaces from DOM ElementTraversal
3546 * xmlChildElementCount:
3547 * @parent: the parent node
3549 * Finds the current number of child nodes of that element which are
3551 * Note the handling of entities references is different than in
3552 * the W3C DOM element traversal spec since we don't have back reference
3553 * from entities content to entities references.
3555 * Returns the count of element child or 0 if not available
3558 xmlChildElementCount(xmlNodePtr parent
) {
3559 unsigned long ret
= 0;
3560 xmlNodePtr cur
= NULL
;
3564 switch (parent
->type
) {
3565 case XML_ELEMENT_NODE
:
3566 case XML_ENTITY_NODE
:
3567 case XML_DOCUMENT_NODE
:
3568 case XML_DOCUMENT_FRAG_NODE
:
3569 case XML_HTML_DOCUMENT_NODE
:
3570 cur
= parent
->children
;
3575 while (cur
!= NULL
) {
3576 if (cur
->type
== XML_ELEMENT_NODE
)
3584 * xmlFirstElementChild:
3585 * @parent: the parent node
3587 * Finds the first child node of that element which is a Element node
3588 * Note the handling of entities references is different than in
3589 * the W3C DOM element traversal spec since we don't have back reference
3590 * from entities content to entities references.
3592 * Returns the first element child or NULL if not available
3595 xmlFirstElementChild(xmlNodePtr parent
) {
3596 xmlNodePtr cur
= NULL
;
3600 switch (parent
->type
) {
3601 case XML_ELEMENT_NODE
:
3602 case XML_ENTITY_NODE
:
3603 case XML_DOCUMENT_NODE
:
3604 case XML_DOCUMENT_FRAG_NODE
:
3605 case XML_HTML_DOCUMENT_NODE
:
3606 cur
= parent
->children
;
3611 while (cur
!= NULL
) {
3612 if (cur
->type
== XML_ELEMENT_NODE
)
3620 * xmlLastElementChild:
3621 * @parent: the parent node
3623 * Finds the last child node of that element which is a Element node
3624 * Note the handling of entities references is different than in
3625 * the W3C DOM element traversal spec since we don't have back reference
3626 * from entities content to entities references.
3628 * Returns the last element child or NULL if not available
3631 xmlLastElementChild(xmlNodePtr parent
) {
3632 xmlNodePtr cur
= NULL
;
3636 switch (parent
->type
) {
3637 case XML_ELEMENT_NODE
:
3638 case XML_ENTITY_NODE
:
3639 case XML_DOCUMENT_NODE
:
3640 case XML_DOCUMENT_FRAG_NODE
:
3641 case XML_HTML_DOCUMENT_NODE
:
3647 while (cur
!= NULL
) {
3648 if (cur
->type
== XML_ELEMENT_NODE
)
3656 * xmlPreviousElementSibling:
3657 * @node: the current node
3659 * Finds the first closest previous sibling of the node which is an
3661 * Note the handling of entities references is different than in
3662 * the W3C DOM element traversal spec since we don't have back reference
3663 * from entities content to entities references.
3665 * Returns the previous element sibling or NULL if not available
3668 xmlPreviousElementSibling(xmlNodePtr node
) {
3671 switch (node
->type
) {
3672 case XML_ELEMENT_NODE
:
3674 case XML_CDATA_SECTION_NODE
:
3675 case XML_ENTITY_REF_NODE
:
3676 case XML_ENTITY_NODE
:
3678 case XML_COMMENT_NODE
:
3679 case XML_XINCLUDE_START
:
3680 case XML_XINCLUDE_END
:
3686 while (node
!= NULL
) {
3687 if (node
->type
== XML_ELEMENT_NODE
)
3695 * xmlNextElementSibling:
3696 * @node: the current node
3698 * Finds the first closest next sibling of the node which is an
3700 * Note the handling of entities references is different than in
3701 * the W3C DOM element traversal spec since we don't have back reference
3702 * from entities content to entities references.
3704 * Returns the next element sibling or NULL if not available
3707 xmlNextElementSibling(xmlNodePtr node
) {
3710 switch (node
->type
) {
3711 case XML_ELEMENT_NODE
:
3713 case XML_CDATA_SECTION_NODE
:
3714 case XML_ENTITY_REF_NODE
:
3715 case XML_ENTITY_NODE
:
3717 case XML_COMMENT_NODE
:
3719 case XML_XINCLUDE_START
:
3720 case XML_XINCLUDE_END
:
3726 while (node
!= NULL
) {
3727 if (node
->type
== XML_ELEMENT_NODE
)
3734 #endif /* LIBXML_TREE_ENABLED */
3738 * @cur: the first node in the list
3740 * Free a node and all its siblings, this is a recursive behaviour, all
3741 * the children are freed too.
3744 xmlFreeNodeList(xmlNodePtr cur
) {
3747 xmlDictPtr dict
= NULL
;
3750 if (cur
== NULL
) return;
3751 if (cur
->type
== XML_NAMESPACE_DECL
) {
3752 xmlFreeNsList((xmlNsPtr
) cur
);
3755 if (cur
->doc
!= NULL
) dict
= cur
->doc
->dict
;
3757 while ((cur
->children
!= NULL
) &&
3758 (cur
->type
!= XML_DOCUMENT_NODE
) &&
3759 (cur
->type
!= XML_HTML_DOCUMENT_NODE
) &&
3760 (cur
->type
!= XML_DTD_NODE
) &&
3761 (cur
->type
!= XML_ENTITY_REF_NODE
)) {
3762 cur
= cur
->children
;
3767 parent
= cur
->parent
;
3768 if ((cur
->type
== XML_DOCUMENT_NODE
) ||
3769 (cur
->type
== XML_HTML_DOCUMENT_NODE
)) {
3770 xmlFreeDoc((xmlDocPtr
) cur
);
3771 } else if (cur
->type
!= XML_DTD_NODE
) {
3773 if ((__xmlRegisterCallbacks
) && (xmlDeregisterNodeDefaultValue
))
3774 xmlDeregisterNodeDefaultValue(cur
);
3776 if (((cur
->type
== XML_ELEMENT_NODE
) ||
3777 (cur
->type
== XML_XINCLUDE_START
) ||
3778 (cur
->type
== XML_XINCLUDE_END
)) &&
3779 (cur
->properties
!= NULL
))
3780 xmlFreePropList(cur
->properties
);
3781 if ((cur
->type
!= XML_ELEMENT_NODE
) &&
3782 (cur
->type
!= XML_XINCLUDE_START
) &&
3783 (cur
->type
!= XML_XINCLUDE_END
) &&
3784 (cur
->type
!= XML_ENTITY_REF_NODE
) &&
3785 (cur
->content
!= (xmlChar
*) &(cur
->properties
))) {
3786 DICT_FREE(cur
->content
)
3788 if (((cur
->type
== XML_ELEMENT_NODE
) ||
3789 (cur
->type
== XML_XINCLUDE_START
) ||
3790 (cur
->type
== XML_XINCLUDE_END
)) &&
3791 (cur
->nsDef
!= NULL
))
3792 xmlFreeNsList(cur
->nsDef
);
3795 * When a node is a text node or a comment, it uses a global static
3796 * variable for the name of the node.
3797 * Otherwise the node name might come from the document's
3800 if ((cur
->name
!= NULL
) &&
3801 (cur
->type
!= XML_TEXT_NODE
) &&
3802 (cur
->type
!= XML_COMMENT_NODE
))
3803 DICT_FREE(cur
->name
)
3810 if ((depth
== 0) || (parent
== NULL
))
3814 cur
->children
= NULL
;
3823 * Free a node, this is a recursive behaviour, all the children are freed too.
3824 * This doesn't unlink the child from the list, use xmlUnlinkNode() first.
3827 xmlFreeNode(xmlNodePtr cur
) {
3828 xmlDictPtr dict
= NULL
;
3830 if (cur
== NULL
) return;
3832 /* use xmlFreeDtd for DTD nodes */
3833 if (cur
->type
== XML_DTD_NODE
) {
3834 xmlFreeDtd((xmlDtdPtr
) cur
);
3837 if (cur
->type
== XML_NAMESPACE_DECL
) {
3838 xmlFreeNs((xmlNsPtr
) cur
);
3841 if (cur
->type
== XML_ATTRIBUTE_NODE
) {
3842 xmlFreeProp((xmlAttrPtr
) cur
);
3846 if ((__xmlRegisterCallbacks
) && (xmlDeregisterNodeDefaultValue
))
3847 xmlDeregisterNodeDefaultValue(cur
);
3849 if (cur
->doc
!= NULL
) dict
= cur
->doc
->dict
;
3851 if (cur
->type
== XML_ENTITY_DECL
) {
3852 xmlEntityPtr ent
= (xmlEntityPtr
) cur
;
3853 DICT_FREE(ent
->SystemID
);
3854 DICT_FREE(ent
->ExternalID
);
3856 if ((cur
->children
!= NULL
) &&
3857 (cur
->type
!= XML_ENTITY_REF_NODE
))
3858 xmlFreeNodeList(cur
->children
);
3860 if ((cur
->type
== XML_ELEMENT_NODE
) ||
3861 (cur
->type
== XML_XINCLUDE_START
) ||
3862 (cur
->type
== XML_XINCLUDE_END
)) {
3863 if (cur
->properties
!= NULL
)
3864 xmlFreePropList(cur
->properties
);
3865 if (cur
->nsDef
!= NULL
)
3866 xmlFreeNsList(cur
->nsDef
);
3867 } else if ((cur
->content
!= NULL
) &&
3868 (cur
->type
!= XML_ENTITY_REF_NODE
) &&
3869 (cur
->content
!= (xmlChar
*) &(cur
->properties
))) {
3870 DICT_FREE(cur
->content
)
3874 * When a node is a text node or a comment, it uses a global static
3875 * variable for the name of the node.
3876 * Otherwise the node name might come from the document's dictionary
3878 if ((cur
->name
!= NULL
) &&
3879 (cur
->type
!= XML_TEXT_NODE
) &&
3880 (cur
->type
!= XML_COMMENT_NODE
))
3881 DICT_FREE(cur
->name
)
3890 * Unlink a node from it's current context, the node is not freed
3891 * If one need to free the node, use xmlFreeNode() routine after the
3892 * unlink to discard it.
3893 * Note that namespace nodes can't be unlinked as they do not have
3894 * pointer to their parent.
3897 xmlUnlinkNode(xmlNodePtr cur
) {
3900 xmlGenericError(xmlGenericErrorContext
,
3901 "xmlUnlinkNode : node == NULL\n");
3905 if (cur
->type
== XML_NAMESPACE_DECL
)
3907 if (cur
->type
== XML_DTD_NODE
) {
3911 if (doc
->intSubset
== (xmlDtdPtr
) cur
)
3912 doc
->intSubset
= NULL
;
3913 if (doc
->extSubset
== (xmlDtdPtr
) cur
)
3914 doc
->extSubset
= NULL
;
3917 if (cur
->type
== XML_ENTITY_DECL
) {
3921 if (doc
->intSubset
!= NULL
) {
3922 if (xmlHashLookup(doc
->intSubset
->entities
, cur
->name
) == cur
)
3923 xmlHashRemoveEntry(doc
->intSubset
->entities
, cur
->name
,
3925 if (xmlHashLookup(doc
->intSubset
->pentities
, cur
->name
) == cur
)
3926 xmlHashRemoveEntry(doc
->intSubset
->pentities
, cur
->name
,
3929 if (doc
->extSubset
!= NULL
) {
3930 if (xmlHashLookup(doc
->extSubset
->entities
, cur
->name
) == cur
)
3931 xmlHashRemoveEntry(doc
->extSubset
->entities
, cur
->name
,
3933 if (xmlHashLookup(doc
->extSubset
->pentities
, cur
->name
) == cur
)
3934 xmlHashRemoveEntry(doc
->extSubset
->pentities
, cur
->name
,
3939 if (cur
->parent
!= NULL
) {
3941 parent
= cur
->parent
;
3942 if (cur
->type
== XML_ATTRIBUTE_NODE
) {
3943 if (parent
->properties
== (xmlAttrPtr
) cur
)
3944 parent
->properties
= ((xmlAttrPtr
) cur
)->next
;
3946 if (parent
->children
== cur
)
3947 parent
->children
= cur
->next
;
3948 if (parent
->last
== cur
)
3949 parent
->last
= cur
->prev
;
3953 if (cur
->next
!= NULL
)
3954 cur
->next
->prev
= cur
->prev
;
3955 if (cur
->prev
!= NULL
)
3956 cur
->prev
->next
= cur
->next
;
3957 cur
->next
= cur
->prev
= NULL
;
3960 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_WRITER_ENABLED)
3963 * @old: the old node
3966 * Unlink the old node from its current context, prune the new one
3967 * at the same place. If @cur was already inserted in a document it is
3968 * first unlinked from its existing context.
3970 * See the note regarding namespaces in xmlAddChild.
3972 * Returns the @old node
3975 xmlReplaceNode(xmlNodePtr old
, xmlNodePtr cur
) {
3976 if (old
== cur
) return(NULL
);
3977 if ((old
== NULL
) || (old
->type
== XML_NAMESPACE_DECL
) ||
3978 (old
->parent
== NULL
)) {
3980 xmlGenericError(xmlGenericErrorContext
,
3981 "xmlReplaceNode : old == NULL or without parent\n");
3985 if ((cur
== NULL
) || (cur
->type
== XML_NAMESPACE_DECL
)) {
3992 if ((old
->type
==XML_ATTRIBUTE_NODE
) && (cur
->type
!=XML_ATTRIBUTE_NODE
)) {
3994 xmlGenericError(xmlGenericErrorContext
,
3995 "xmlReplaceNode : Trying to replace attribute node with other node type\n");
3999 if ((cur
->type
==XML_ATTRIBUTE_NODE
) && (old
->type
!=XML_ATTRIBUTE_NODE
)) {
4001 xmlGenericError(xmlGenericErrorContext
,
4002 "xmlReplaceNode : Trying to replace a non-attribute node with attribute node\n");
4007 xmlSetTreeDoc(cur
, old
->doc
);
4008 cur
->parent
= old
->parent
;
4009 cur
->next
= old
->next
;
4010 if (cur
->next
!= NULL
)
4011 cur
->next
->prev
= cur
;
4012 cur
->prev
= old
->prev
;
4013 if (cur
->prev
!= NULL
)
4014 cur
->prev
->next
= cur
;
4015 if (cur
->parent
!= NULL
) {
4016 if (cur
->type
== XML_ATTRIBUTE_NODE
) {
4017 if (cur
->parent
->properties
== (xmlAttrPtr
)old
)
4018 cur
->parent
->properties
= ((xmlAttrPtr
) cur
);
4020 if (cur
->parent
->children
== old
)
4021 cur
->parent
->children
= cur
;
4022 if (cur
->parent
->last
== old
)
4023 cur
->parent
->last
= cur
;
4026 old
->next
= old
->prev
= NULL
;
4030 #endif /* LIBXML_TREE_ENABLED */
4032 /************************************************************************
4036 ************************************************************************/
4040 * @cur: the namespace
4042 * Do a copy of the namespace.
4044 * Returns: a new #xmlNsPtr, or NULL in case of error.
4047 xmlCopyNamespace(xmlNsPtr cur
) {
4050 if (cur
== NULL
) return(NULL
);
4051 switch (cur
->type
) {
4052 case XML_LOCAL_NAMESPACE
:
4053 ret
= xmlNewNs(NULL
, cur
->href
, cur
->prefix
);
4057 xmlGenericError(xmlGenericErrorContext
,
4058 "xmlCopyNamespace: invalid type %d\n", cur
->type
);
4066 * xmlCopyNamespaceList:
4067 * @cur: the first namespace
4069 * Do a copy of an namespace list.
4071 * Returns: a new #xmlNsPtr, or NULL in case of error.
4074 xmlCopyNamespaceList(xmlNsPtr cur
) {
4075 xmlNsPtr ret
= NULL
;
4076 xmlNsPtr p
= NULL
,q
;
4078 while (cur
!= NULL
) {
4079 q
= xmlCopyNamespace(cur
);
4092 xmlStaticCopyNodeList(xmlNodePtr node
, xmlDocPtr doc
, xmlNodePtr parent
);
4095 xmlCopyPropInternal(xmlDocPtr doc
, xmlNodePtr target
, xmlAttrPtr cur
) {
4098 if (cur
== NULL
) return(NULL
);
4099 if ((target
!= NULL
) && (target
->type
!= XML_ELEMENT_NODE
))
4102 ret
= xmlNewDocProp(target
->doc
, cur
->name
, NULL
);
4103 else if (doc
!= NULL
)
4104 ret
= xmlNewDocProp(doc
, cur
->name
, NULL
);
4105 else if (cur
->parent
!= NULL
)
4106 ret
= xmlNewDocProp(cur
->parent
->doc
, cur
->name
, NULL
);
4107 else if (cur
->children
!= NULL
)
4108 ret
= xmlNewDocProp(cur
->children
->doc
, cur
->name
, NULL
);
4110 ret
= xmlNewDocProp(NULL
, cur
->name
, NULL
);
4111 if (ret
== NULL
) return(NULL
);
4112 ret
->parent
= target
;
4114 if ((cur
->ns
!= NULL
) && (target
!= NULL
)) {
4117 ns
= xmlSearchNs(target
->doc
, target
, cur
->ns
->prefix
);
4120 * Humm, we are copying an element whose namespace is defined
4121 * out of the new tree scope. Search it in the original tree
4122 * and add it at the top of the new tree
4124 ns
= xmlSearchNs(cur
->doc
, cur
->parent
, cur
->ns
->prefix
);
4126 xmlNodePtr root
= target
;
4127 xmlNodePtr pred
= NULL
;
4129 while (root
->parent
!= NULL
) {
4131 root
= root
->parent
;
4133 if (root
== (xmlNodePtr
) target
->doc
) {
4134 /* correct possibly cycling above the document elt */
4137 ret
->ns
= xmlNewNs(root
, ns
->href
, ns
->prefix
);
4141 * we have to find something appropriate here since
4142 * we can't be sure, that the namespace we found is identified
4145 if (xmlStrEqual(ns
->href
, cur
->ns
->href
)) {
4146 /* this is the nice case */
4150 * we are in trouble: we need a new reconciled namespace.
4153 ret
->ns
= xmlNewReconciledNs(target
->doc
, target
, cur
->ns
);
4160 if (cur
->children
!= NULL
) {
4163 ret
->children
= xmlStaticCopyNodeList(cur
->children
, ret
->doc
, (xmlNodePtr
) ret
);
4165 tmp
= ret
->children
;
4166 while (tmp
!= NULL
) {
4167 /* tmp->parent = (xmlNodePtr)ret; */
4168 if (tmp
->next
== NULL
)
4176 if ((target
!= NULL
) && (cur
!= NULL
) &&
4177 (target
->doc
!= NULL
) && (cur
->doc
!= NULL
) &&
4178 (cur
->doc
->ids
!= NULL
) && (cur
->parent
!= NULL
)) {
4179 if (xmlIsID(cur
->doc
, cur
->parent
, cur
)) {
4182 id
= xmlNodeListGetString(cur
->doc
, cur
->children
, 1);
4184 xmlAddID(NULL
, target
->doc
, id
, ret
);
4194 * @target: the element where the attribute will be grafted
4195 * @cur: the attribute
4197 * Do a copy of the attribute.
4199 * Returns: a new #xmlAttrPtr, or NULL in case of error.
4202 xmlCopyProp(xmlNodePtr target
, xmlAttrPtr cur
) {
4203 return xmlCopyPropInternal(NULL
, target
, cur
);
4208 * @target: the element where the attributes will be grafted
4209 * @cur: the first attribute
4211 * Do a copy of an attribute list.
4213 * Returns: a new #xmlAttrPtr, or NULL in case of error.
4216 xmlCopyPropList(xmlNodePtr target
, xmlAttrPtr cur
) {
4217 xmlAttrPtr ret
= NULL
;
4218 xmlAttrPtr p
= NULL
,q
;
4220 if ((target
!= NULL
) && (target
->type
!= XML_ELEMENT_NODE
))
4222 while (cur
!= NULL
) {
4223 q
= xmlCopyProp(target
, cur
);
4239 * NOTE about the CopyNode operations !
4241 * They are split into external and internal parts for one
4242 * tricky reason: namespaces. Doing a direct copy of a node
4243 * say RPM:Copyright without changing the namespace pointer to
4244 * something else can produce stale links. One way to do it is
4245 * to keep a reference counter but this doesn't work as soon
4246 * as one moves the element or the subtree out of the scope of
4247 * the existing namespace. The actual solution seems to be to add
4248 * a copy of the namespace at the top of the copied tree if
4249 * not available in the subtree.
4250 * Hence two functions, the public front-end call the inner ones
4251 * The argument "recursive" normally indicates a recursive copy
4252 * of the node with values 0 (no) and 1 (yes). For XInclude,
4253 * however, we allow a value of 2 to indicate copy properties and
4254 * namespace info, but don't recurse on children.
4258 xmlStaticCopyNode(xmlNodePtr node
, xmlDocPtr doc
, xmlNodePtr parent
,
4262 if (node
== NULL
) return(NULL
);
4263 switch (node
->type
) {
4265 case XML_CDATA_SECTION_NODE
:
4266 case XML_ELEMENT_NODE
:
4267 case XML_DOCUMENT_FRAG_NODE
:
4268 case XML_ENTITY_REF_NODE
:
4269 case XML_ENTITY_NODE
:
4271 case XML_COMMENT_NODE
:
4272 case XML_XINCLUDE_START
:
4273 case XML_XINCLUDE_END
:
4275 case XML_ATTRIBUTE_NODE
:
4276 return((xmlNodePtr
) xmlCopyPropInternal(doc
, parent
, (xmlAttrPtr
) node
));
4277 case XML_NAMESPACE_DECL
:
4278 return((xmlNodePtr
) xmlCopyNamespaceList((xmlNsPtr
) node
));
4280 case XML_DOCUMENT_NODE
:
4281 case XML_HTML_DOCUMENT_NODE
:
4282 #ifdef LIBXML_TREE_ENABLED
4283 return((xmlNodePtr
) xmlCopyDoc((xmlDocPtr
) node
, extended
));
4284 #endif /* LIBXML_TREE_ENABLED */
4285 case XML_DOCUMENT_TYPE_NODE
:
4286 case XML_NOTATION_NODE
:
4288 case XML_ELEMENT_DECL
:
4289 case XML_ATTRIBUTE_DECL
:
4290 case XML_ENTITY_DECL
:
4295 * Allocate a new node and fill the fields.
4297 ret
= (xmlNodePtr
) xmlMalloc(sizeof(xmlNode
));
4299 xmlTreeErrMemory("copying node");
4302 memset(ret
, 0, sizeof(xmlNode
));
4303 ret
->type
= node
->type
;
4306 ret
->parent
= parent
;
4307 if (node
->name
== xmlStringText
)
4308 ret
->name
= xmlStringText
;
4309 else if (node
->name
== xmlStringTextNoenc
)
4310 ret
->name
= xmlStringTextNoenc
;
4311 else if (node
->name
== xmlStringComment
)
4312 ret
->name
= xmlStringComment
;
4313 else if (node
->name
!= NULL
) {
4314 if ((doc
!= NULL
) && (doc
->dict
!= NULL
))
4315 ret
->name
= xmlDictLookup(doc
->dict
, node
->name
, -1);
4317 ret
->name
= xmlStrdup(node
->name
);
4319 if ((node
->type
!= XML_ELEMENT_NODE
) &&
4320 (node
->content
!= NULL
) &&
4321 (node
->type
!= XML_ENTITY_REF_NODE
) &&
4322 (node
->type
!= XML_XINCLUDE_END
) &&
4323 (node
->type
!= XML_XINCLUDE_START
)) {
4324 ret
->content
= xmlStrdup(node
->content
);
4326 if (node
->type
== XML_ELEMENT_NODE
)
4327 ret
->line
= node
->line
;
4329 if (parent
!= NULL
) {
4333 * this is a tricky part for the node register thing:
4334 * in case ret does get coalesced in xmlAddChild
4335 * the deregister-node callback is called; so we register ret now already
4337 if ((__xmlRegisterCallbacks
) && (xmlRegisterNodeDefaultValue
))
4338 xmlRegisterNodeDefaultValue((xmlNodePtr
)ret
);
4341 * Note that since ret->parent is already set, xmlAddChild will
4342 * return early and not actually insert the node. It will only
4343 * coalesce text nodes and unnecessarily call xmlSetTreeDoc.
4344 * Assuming that the subtree to be copied always has its text
4345 * nodes coalesced, the somewhat confusing call to xmlAddChild
4348 tmp
= xmlAddChild(parent
, ret
);
4349 /* node could have coalesced */
4356 if (((node
->type
== XML_ELEMENT_NODE
) ||
4357 (node
->type
== XML_XINCLUDE_START
)) && (node
->nsDef
!= NULL
))
4358 ret
->nsDef
= xmlCopyNamespaceList(node
->nsDef
);
4360 if (node
->ns
!= NULL
) {
4363 ns
= xmlSearchNs(doc
, ret
, node
->ns
->prefix
);
4366 * Humm, we are copying an element whose namespace is defined
4367 * out of the new tree scope. Search it in the original tree
4368 * and add it at the top of the new tree
4370 ns
= xmlSearchNs(node
->doc
, node
, node
->ns
->prefix
);
4372 xmlNodePtr root
= ret
;
4374 while (root
->parent
!= NULL
) root
= root
->parent
;
4375 ret
->ns
= xmlNewNs(root
, ns
->href
, ns
->prefix
);
4377 ret
->ns
= xmlNewReconciledNs(doc
, ret
, node
->ns
);
4381 * reference the existing namespace definition in our own tree.
4386 if (((node
->type
== XML_ELEMENT_NODE
) ||
4387 (node
->type
== XML_XINCLUDE_START
)) && (node
->properties
!= NULL
))
4388 ret
->properties
= xmlCopyPropList(ret
, node
->properties
);
4389 if (node
->type
== XML_ENTITY_REF_NODE
) {
4390 if ((doc
== NULL
) || (node
->doc
!= doc
)) {
4392 * The copied node will go into a separate document, so
4393 * to avoid dangling references to the ENTITY_DECL node
4394 * we cannot keep the reference. Try to find it in the
4397 ret
->children
= (xmlNodePtr
) xmlGetDocEntity(doc
, ret
->name
);
4399 ret
->children
= node
->children
;
4401 ret
->last
= ret
->children
;
4402 } else if ((node
->children
!= NULL
) && (extended
!= 2)) {
4403 xmlNodePtr cur
, insert
;
4405 cur
= node
->children
;
4407 while (cur
!= NULL
) {
4408 xmlNodePtr copy
= xmlStaticCopyNode(cur
, doc
, insert
, 2);
4414 /* Check for coalesced text nodes */
4415 if (insert
->last
!= copy
) {
4416 if (insert
->last
== NULL
) {
4417 insert
->children
= copy
;
4419 copy
->prev
= insert
->last
;
4420 insert
->last
->next
= copy
;
4422 insert
->last
= copy
;
4425 if ((cur
->type
!= XML_ENTITY_REF_NODE
) &&
4426 (cur
->children
!= NULL
)) {
4427 cur
= cur
->children
;
4433 if (cur
->next
!= NULL
) {
4439 insert
= insert
->parent
;
4449 /* if parent != NULL we already registered the node above */
4450 if ((parent
== NULL
) &&
4451 ((__xmlRegisterCallbacks
) && (xmlRegisterNodeDefaultValue
)))
4452 xmlRegisterNodeDefaultValue((xmlNodePtr
)ret
);
4457 xmlStaticCopyNodeList(xmlNodePtr node
, xmlDocPtr doc
, xmlNodePtr parent
) {
4458 xmlNodePtr ret
= NULL
;
4459 xmlNodePtr p
= NULL
,q
;
4461 while (node
!= NULL
) {
4462 #ifdef LIBXML_TREE_ENABLED
4463 if (node
->type
== XML_DTD_NODE
) {
4468 if (doc
->intSubset
== NULL
) {
4469 q
= (xmlNodePtr
) xmlCopyDtd( (xmlDtdPtr
) node
);
4470 if (q
== NULL
) return(NULL
);
4473 doc
->intSubset
= (xmlDtdPtr
) q
;
4474 xmlAddChild(parent
, q
);
4476 q
= (xmlNodePtr
) doc
->intSubset
;
4477 xmlAddChild(parent
, q
);
4480 #endif /* LIBXML_TREE_ENABLED */
4481 q
= xmlStaticCopyNode(node
, doc
, parent
, 1);
4482 if (q
== NULL
) return(NULL
);
4486 } else if (p
!= q
) {
4487 /* the test is required if xmlStaticCopyNode coalesced 2 text nodes */
4500 * @extended: if 1 do a recursive copy (properties, namespaces and children
4502 * if 2 copy properties and namespaces (when applicable)
4504 * Do a copy of the node.
4506 * Returns: a new #xmlNodePtr, or NULL in case of error.
4509 xmlCopyNode(xmlNodePtr node
, int extended
) {
4512 ret
= xmlStaticCopyNode(node
, NULL
, NULL
, extended
);
4519 * @doc: the document
4520 * @extended: if 1 do a recursive copy (properties, namespaces and children
4522 * if 2 copy properties and namespaces (when applicable)
4524 * Do a copy of the node to a given document.
4526 * Returns: a new #xmlNodePtr, or NULL in case of error.
4529 xmlDocCopyNode(xmlNodePtr node
, xmlDocPtr doc
, int extended
) {
4532 ret
= xmlStaticCopyNode(node
, doc
, NULL
, extended
);
4537 * xmlDocCopyNodeList:
4538 * @doc: the target document
4539 * @node: the first node in the list.
4541 * Do a recursive copy of the node list.
4543 * Returns: a new #xmlNodePtr, or NULL in case of error.
4545 xmlNodePtr
xmlDocCopyNodeList(xmlDocPtr doc
, xmlNodePtr node
) {
4546 xmlNodePtr ret
= xmlStaticCopyNodeList(node
, doc
, NULL
);
4552 * @node: the first node in the list.
4554 * Do a recursive copy of the node list.
4555 * Use xmlDocCopyNodeList() if possible to ensure string interning.
4557 * Returns: a new #xmlNodePtr, or NULL in case of error.
4559 xmlNodePtr
xmlCopyNodeList(xmlNodePtr node
) {
4560 xmlNodePtr ret
= xmlStaticCopyNodeList(node
, NULL
, NULL
);
4564 #if defined(LIBXML_TREE_ENABLED)
4569 * Do a copy of the dtd.
4571 * Returns: a new #xmlDtdPtr, or NULL in case of error.
4574 xmlCopyDtd(xmlDtdPtr dtd
) {
4576 xmlNodePtr cur
, p
= NULL
, q
;
4578 if (dtd
== NULL
) return(NULL
);
4579 ret
= xmlNewDtd(NULL
, dtd
->name
, dtd
->ExternalID
, dtd
->SystemID
);
4580 if (ret
== NULL
) return(NULL
);
4581 if (dtd
->entities
!= NULL
)
4582 ret
->entities
= (void *) xmlCopyEntitiesTable(
4583 (xmlEntitiesTablePtr
) dtd
->entities
);
4584 if (dtd
->notations
!= NULL
)
4585 ret
->notations
= (void *) xmlCopyNotationTable(
4586 (xmlNotationTablePtr
) dtd
->notations
);
4587 if (dtd
->elements
!= NULL
)
4588 ret
->elements
= (void *) xmlCopyElementTable(
4589 (xmlElementTablePtr
) dtd
->elements
);
4590 if (dtd
->attributes
!= NULL
)
4591 ret
->attributes
= (void *) xmlCopyAttributeTable(
4592 (xmlAttributeTablePtr
) dtd
->attributes
);
4593 if (dtd
->pentities
!= NULL
)
4594 ret
->pentities
= (void *) xmlCopyEntitiesTable(
4595 (xmlEntitiesTablePtr
) dtd
->pentities
);
4597 cur
= dtd
->children
;
4598 while (cur
!= NULL
) {
4601 if (cur
->type
== XML_ENTITY_DECL
) {
4602 xmlEntityPtr tmp
= (xmlEntityPtr
) cur
;
4603 switch (tmp
->etype
) {
4604 case XML_INTERNAL_GENERAL_ENTITY
:
4605 case XML_EXTERNAL_GENERAL_PARSED_ENTITY
:
4606 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY
:
4607 q
= (xmlNodePtr
) xmlGetEntityFromDtd(ret
, tmp
->name
);
4609 case XML_INTERNAL_PARAMETER_ENTITY
:
4610 case XML_EXTERNAL_PARAMETER_ENTITY
:
4612 xmlGetParameterEntityFromDtd(ret
, tmp
->name
);
4614 case XML_INTERNAL_PREDEFINED_ENTITY
:
4617 } else if (cur
->type
== XML_ELEMENT_DECL
) {
4618 xmlElementPtr tmp
= (xmlElementPtr
) cur
;
4620 xmlGetDtdQElementDesc(ret
, tmp
->name
, tmp
->prefix
);
4621 } else if (cur
->type
== XML_ATTRIBUTE_DECL
) {
4622 xmlAttributePtr tmp
= (xmlAttributePtr
) cur
;
4624 xmlGetDtdQAttrDesc(ret
, tmp
->elem
, tmp
->name
, tmp
->prefix
);
4625 } else if (cur
->type
== XML_COMMENT_NODE
) {
4626 q
= xmlCopyNode(cur
, 0);
4640 q
->parent
= (xmlNodePtr
) ret
;
4651 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
4654 * @doc: the document
4655 * @recursive: if not zero do a recursive copy.
4657 * Do a copy of the document info. If recursive, the content tree will
4658 * be copied too as well as DTD, namespaces and entities.
4660 * Returns: a new #xmlDocPtr, or NULL in case of error.
4663 xmlCopyDoc(xmlDocPtr doc
, int recursive
) {
4666 if (doc
== NULL
) return(NULL
);
4667 ret
= xmlNewDoc(doc
->version
);
4668 if (ret
== NULL
) return(NULL
);
4669 ret
->type
= doc
->type
;
4670 if (doc
->name
!= NULL
)
4671 ret
->name
= xmlMemStrdup(doc
->name
);
4672 if (doc
->encoding
!= NULL
)
4673 ret
->encoding
= xmlStrdup(doc
->encoding
);
4674 if (doc
->URL
!= NULL
)
4675 ret
->URL
= xmlStrdup(doc
->URL
);
4676 ret
->charset
= doc
->charset
;
4677 ret
->compression
= doc
->compression
;
4678 ret
->standalone
= doc
->standalone
;
4679 if (!recursive
) return(ret
);
4682 ret
->children
= NULL
;
4683 #ifdef LIBXML_TREE_ENABLED
4684 if (doc
->intSubset
!= NULL
) {
4685 ret
->intSubset
= xmlCopyDtd(doc
->intSubset
);
4686 if (ret
->intSubset
== NULL
) {
4690 xmlSetTreeDoc((xmlNodePtr
)ret
->intSubset
, ret
);
4691 ret
->intSubset
->parent
= ret
;
4694 if (doc
->oldNs
!= NULL
)
4695 ret
->oldNs
= xmlCopyNamespaceList(doc
->oldNs
);
4696 if (doc
->children
!= NULL
) {
4699 ret
->children
= xmlStaticCopyNodeList(doc
->children
, ret
,
4702 tmp
= ret
->children
;
4703 while (tmp
!= NULL
) {
4704 if (tmp
->next
== NULL
)
4711 #endif /* LIBXML_TREE_ENABLED */
4713 /************************************************************************
4715 * Content access functions *
4717 ************************************************************************/
4720 * xmlGetLineNoInternal:
4722 * @depth: used to limit any risk of recursion
4724 * Get line number of @node.
4725 * Try to override the limitation of lines being store in 16 bits ints
4727 * Returns the line number if successful, -1 otherwise
4730 xmlGetLineNoInternal(const xmlNode
*node
, int depth
)
4739 if ((node
->type
== XML_ELEMENT_NODE
) ||
4740 (node
->type
== XML_TEXT_NODE
) ||
4741 (node
->type
== XML_COMMENT_NODE
) ||
4742 (node
->type
== XML_PI_NODE
)) {
4743 if (node
->line
== 65535) {
4744 if ((node
->type
== XML_TEXT_NODE
) && (node
->psvi
!= NULL
))
4745 result
= (long) (ptrdiff_t) node
->psvi
;
4746 else if ((node
->type
== XML_ELEMENT_NODE
) &&
4747 (node
->children
!= NULL
))
4748 result
= xmlGetLineNoInternal(node
->children
, depth
+ 1);
4749 else if (node
->next
!= NULL
)
4750 result
= xmlGetLineNoInternal(node
->next
, depth
+ 1);
4751 else if (node
->prev
!= NULL
)
4752 result
= xmlGetLineNoInternal(node
->prev
, depth
+ 1);
4754 if ((result
== -1) || (result
== 65535))
4755 result
= (long) node
->line
;
4756 } else if ((node
->prev
!= NULL
) &&
4757 ((node
->prev
->type
== XML_ELEMENT_NODE
) ||
4758 (node
->prev
->type
== XML_TEXT_NODE
) ||
4759 (node
->prev
->type
== XML_COMMENT_NODE
) ||
4760 (node
->prev
->type
== XML_PI_NODE
)))
4761 result
= xmlGetLineNoInternal(node
->prev
, depth
+ 1);
4762 else if ((node
->parent
!= NULL
) &&
4763 (node
->parent
->type
== XML_ELEMENT_NODE
))
4764 result
= xmlGetLineNoInternal(node
->parent
, depth
+ 1);
4773 * Get line number of @node.
4774 * Try to override the limitation of lines being store in 16 bits ints
4775 * if XML_PARSE_BIG_LINES parser option was used
4777 * Returns the line number if successful, -1 otherwise
4780 xmlGetLineNo(const xmlNode
*node
)
4782 return(xmlGetLineNoInternal(node
, 0));
4785 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_DEBUG_ENABLED)
4790 * Build a structure based Path for the given node
4792 * Returns the new path or NULL in case of error. The caller must free
4793 * the returned string
4796 xmlGetNodePath(const xmlNode
*node
)
4798 const xmlNode
*cur
, *tmp
, *next
;
4799 xmlChar
*buffer
= NULL
, *temp
;
4805 int occur
= 0, generic
;
4807 if ((node
== NULL
) || (node
->type
== XML_NAMESPACE_DECL
))
4811 buffer
= (xmlChar
*) xmlMallocAtomic(buf_len
* sizeof(xmlChar
));
4812 if (buffer
== NULL
) {
4813 xmlTreeErrMemory("getting node path");
4816 buf
= (xmlChar
*) xmlMallocAtomic(buf_len
* sizeof(xmlChar
));
4818 xmlTreeErrMemory("getting node path");
4829 if ((cur
->type
== XML_DOCUMENT_NODE
) ||
4830 (cur
->type
== XML_HTML_DOCUMENT_NODE
)) {
4831 if (buffer
[0] == '/')
4835 } else if (cur
->type
== XML_ELEMENT_NODE
) {
4838 name
= (const char *) cur
->name
;
4840 if (cur
->ns
->prefix
!= NULL
) {
4841 snprintf(nametemp
, sizeof(nametemp
) - 1, "%s:%s",
4842 (char *)cur
->ns
->prefix
, (char *)cur
->name
);
4843 nametemp
[sizeof(nametemp
) - 1] = 0;
4847 * We cannot express named elements in the default
4848 * namespace, so use "*".
4857 * Thumbler index computation
4858 * TODO: the occurrence test seems bogus for namespaced names
4861 while (tmp
!= NULL
) {
4862 if ((tmp
->type
== XML_ELEMENT_NODE
) &&
4864 (xmlStrEqual(cur
->name
, tmp
->name
) &&
4865 ((tmp
->ns
== cur
->ns
) ||
4866 ((tmp
->ns
!= NULL
) && (cur
->ns
!= NULL
) &&
4867 (xmlStrEqual(cur
->ns
->prefix
, tmp
->ns
->prefix
)))))))
4873 while (tmp
!= NULL
&& occur
== 0) {
4874 if ((tmp
->type
== XML_ELEMENT_NODE
) &&
4876 (xmlStrEqual(cur
->name
, tmp
->name
) &&
4877 ((tmp
->ns
== cur
->ns
) ||
4878 ((tmp
->ns
!= NULL
) && (cur
->ns
!= NULL
) &&
4879 (xmlStrEqual(cur
->ns
->prefix
, tmp
->ns
->prefix
)))))))
4887 } else if (cur
->type
== XML_COMMENT_NODE
) {
4893 * Thumbler index computation
4896 while (tmp
!= NULL
) {
4897 if (tmp
->type
== XML_COMMENT_NODE
)
4903 while (tmp
!= NULL
&& occur
== 0) {
4904 if (tmp
->type
== XML_COMMENT_NODE
)
4912 } else if ((cur
->type
== XML_TEXT_NODE
) ||
4913 (cur
->type
== XML_CDATA_SECTION_NODE
)) {
4919 * Thumbler index computation
4922 while (tmp
!= NULL
) {
4923 if ((tmp
->type
== XML_TEXT_NODE
) ||
4924 (tmp
->type
== XML_CDATA_SECTION_NODE
))
4929 * Evaluate if this is the only text- or CDATA-section-node;
4930 * if yes, then we'll get "text()", otherwise "text()[1]".
4934 while (tmp
!= NULL
) {
4935 if ((tmp
->type
== XML_TEXT_NODE
) ||
4936 (tmp
->type
== XML_CDATA_SECTION_NODE
))
4945 } else if (cur
->type
== XML_PI_NODE
) {
4947 snprintf(nametemp
, sizeof(nametemp
) - 1,
4948 "processing-instruction('%s')", (char *)cur
->name
);
4949 nametemp
[sizeof(nametemp
) - 1] = 0;
4955 * Thumbler index computation
4958 while (tmp
!= NULL
) {
4959 if ((tmp
->type
== XML_PI_NODE
) &&
4960 (xmlStrEqual(cur
->name
, tmp
->name
)))
4966 while (tmp
!= NULL
&& occur
== 0) {
4967 if ((tmp
->type
== XML_PI_NODE
) &&
4968 (xmlStrEqual(cur
->name
, tmp
->name
)))
4977 } else if (cur
->type
== XML_ATTRIBUTE_NODE
) {
4979 name
= (const char *) (((xmlAttrPtr
) cur
)->name
);
4981 if (cur
->ns
->prefix
!= NULL
)
4982 snprintf(nametemp
, sizeof(nametemp
) - 1, "%s:%s",
4983 (char *)cur
->ns
->prefix
, (char *)cur
->name
);
4985 snprintf(nametemp
, sizeof(nametemp
) - 1, "%s",
4987 nametemp
[sizeof(nametemp
) - 1] = 0;
4990 next
= ((xmlAttrPtr
) cur
)->parent
;
4998 * Make sure there is enough room
5000 if (xmlStrlen(buffer
) + sizeof(nametemp
) + 20 > buf_len
) {
5002 2 * buf_len
+ xmlStrlen(buffer
) + sizeof(nametemp
) + 20;
5003 temp
= (xmlChar
*) xmlRealloc(buffer
, buf_len
);
5005 xmlTreeErrMemory("getting node path");
5011 temp
= (xmlChar
*) xmlRealloc(buf
, buf_len
);
5013 xmlTreeErrMemory("getting node path");
5021 snprintf((char *) buf
, buf_len
, "%s%s%s",
5022 sep
, name
, (char *) buffer
);
5024 snprintf((char *) buf
, buf_len
, "%s%s[%d]%s",
5025 sep
, name
, occur
, (char *) buffer
);
5026 snprintf((char *) buffer
, buf_len
, "%s", (char *)buf
);
5028 } while (cur
!= NULL
);
5032 #endif /* LIBXML_TREE_ENABLED */
5035 * xmlDocGetRootElement:
5036 * @doc: the document
5038 * Get the root element of the document (doc->children is a list
5039 * containing possibly comments, PIs, etc ...).
5041 * Returns the #xmlNodePtr for the root or NULL
5044 xmlDocGetRootElement(const xmlDoc
*doc
) {
5047 if (doc
== NULL
) return(NULL
);
5048 ret
= doc
->children
;
5049 while (ret
!= NULL
) {
5050 if (ret
->type
== XML_ELEMENT_NODE
)
5057 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_WRITER_ENABLED)
5059 * xmlDocSetRootElement:
5060 * @doc: the document
5061 * @root: the new document root element, if root is NULL no action is taken,
5062 * to remove a node from a document use xmlUnlinkNode(root) instead.
5064 * Set the root element of the document (doc->children is a list
5065 * containing possibly comments, PIs, etc ...).
5067 * Returns the old root element if any was found, NULL if root was NULL
5070 xmlDocSetRootElement(xmlDocPtr doc
, xmlNodePtr root
) {
5071 xmlNodePtr old
= NULL
;
5073 if (doc
== NULL
) return(NULL
);
5074 if ((root
== NULL
) || (root
->type
== XML_NAMESPACE_DECL
))
5076 xmlUnlinkNode(root
);
5077 xmlSetTreeDoc(root
, doc
);
5078 root
->parent
= (xmlNodePtr
) doc
;
5079 old
= doc
->children
;
5080 while (old
!= NULL
) {
5081 if (old
->type
== XML_ELEMENT_NODE
)
5086 if (doc
->children
== NULL
) {
5087 doc
->children
= root
;
5090 xmlAddSibling(doc
->children
, root
);
5093 xmlReplaceNode(old
, root
);
5099 #if defined(LIBXML_TREE_ENABLED)
5102 * @cur: the node being changed
5103 * @lang: the language description
5105 * Set the language of a node, i.e. the values of the xml:lang
5109 xmlNodeSetLang(xmlNodePtr cur
, const xmlChar
*lang
) {
5112 if (cur
== NULL
) return;
5115 case XML_CDATA_SECTION_NODE
:
5116 case XML_COMMENT_NODE
:
5117 case XML_DOCUMENT_NODE
:
5118 case XML_DOCUMENT_TYPE_NODE
:
5119 case XML_DOCUMENT_FRAG_NODE
:
5120 case XML_NOTATION_NODE
:
5121 case XML_HTML_DOCUMENT_NODE
:
5123 case XML_ELEMENT_DECL
:
5124 case XML_ATTRIBUTE_DECL
:
5125 case XML_ENTITY_DECL
:
5127 case XML_ENTITY_REF_NODE
:
5128 case XML_ENTITY_NODE
:
5129 case XML_NAMESPACE_DECL
:
5130 case XML_XINCLUDE_START
:
5131 case XML_XINCLUDE_END
:
5133 case XML_ELEMENT_NODE
:
5134 case XML_ATTRIBUTE_NODE
:
5137 ns
= xmlSearchNsByHref(cur
->doc
, cur
, XML_XML_NAMESPACE
);
5140 xmlSetNsProp(cur
, ns
, BAD_CAST
"lang", lang
);
5142 #endif /* LIBXML_TREE_ENABLED */
5146 * @cur: the node being checked
5148 * Searches the language of a node, i.e. the values of the xml:lang
5149 * attribute or the one carried by the nearest ancestor.
5151 * Returns a pointer to the lang value, or NULL if not found
5152 * It's up to the caller to free the memory with xmlFree().
5155 xmlNodeGetLang(const xmlNode
*cur
) {
5158 if ((cur
== NULL
) || (cur
->type
== XML_NAMESPACE_DECL
))
5160 while (cur
!= NULL
) {
5161 lang
= xmlGetNsProp(cur
, BAD_CAST
"lang", XML_XML_NAMESPACE
);
5170 #ifdef LIBXML_TREE_ENABLED
5172 * xmlNodeSetSpacePreserve:
5173 * @cur: the node being changed
5174 * @val: the xml:space value ("0": default, 1: "preserve")
5176 * Set (or reset) the space preserving behaviour of a node, i.e. the
5177 * value of the xml:space attribute.
5180 xmlNodeSetSpacePreserve(xmlNodePtr cur
, int val
) {
5183 if (cur
== NULL
) return;
5186 case XML_CDATA_SECTION_NODE
:
5187 case XML_COMMENT_NODE
:
5188 case XML_DOCUMENT_NODE
:
5189 case XML_DOCUMENT_TYPE_NODE
:
5190 case XML_DOCUMENT_FRAG_NODE
:
5191 case XML_NOTATION_NODE
:
5192 case XML_HTML_DOCUMENT_NODE
:
5194 case XML_ELEMENT_DECL
:
5195 case XML_ATTRIBUTE_DECL
:
5196 case XML_ENTITY_DECL
:
5198 case XML_ENTITY_REF_NODE
:
5199 case XML_ENTITY_NODE
:
5200 case XML_NAMESPACE_DECL
:
5201 case XML_XINCLUDE_START
:
5202 case XML_XINCLUDE_END
:
5204 case XML_ELEMENT_NODE
:
5205 case XML_ATTRIBUTE_NODE
:
5208 ns
= xmlSearchNsByHref(cur
->doc
, cur
, XML_XML_NAMESPACE
);
5213 xmlSetNsProp(cur
, ns
, BAD_CAST
"space", BAD_CAST
"default");
5216 xmlSetNsProp(cur
, ns
, BAD_CAST
"space", BAD_CAST
"preserve");
5220 #endif /* LIBXML_TREE_ENABLED */
5223 * xmlNodeGetSpacePreserve:
5224 * @cur: the node being checked
5226 * Searches the space preserving behaviour of a node, i.e. the values
5227 * of the xml:space attribute or the one carried by the nearest
5230 * Returns -1 if xml:space is not inherited, 0 if "default", 1 if "preserve"
5233 xmlNodeGetSpacePreserve(const xmlNode
*cur
) {
5236 if ((cur
== NULL
) || (cur
->type
!= XML_ELEMENT_NODE
))
5238 while (cur
!= NULL
) {
5239 space
= xmlGetNsProp(cur
, BAD_CAST
"space", XML_XML_NAMESPACE
);
5240 if (space
!= NULL
) {
5241 if (xmlStrEqual(space
, BAD_CAST
"preserve")) {
5245 if (xmlStrEqual(space
, BAD_CAST
"default")) {
5256 #ifdef LIBXML_TREE_ENABLED
5259 * @cur: the node being changed
5260 * @name: the new tag name
5262 * Set (or reset) the name of a node.
5265 xmlNodeSetName(xmlNodePtr cur
, const xmlChar
*name
) {
5268 const xmlChar
*freeme
= NULL
;
5270 if (cur
== NULL
) return;
5271 if (name
== NULL
) return;
5274 case XML_CDATA_SECTION_NODE
:
5275 case XML_COMMENT_NODE
:
5276 case XML_DOCUMENT_TYPE_NODE
:
5277 case XML_DOCUMENT_FRAG_NODE
:
5278 case XML_NOTATION_NODE
:
5279 case XML_HTML_DOCUMENT_NODE
:
5280 case XML_NAMESPACE_DECL
:
5281 case XML_XINCLUDE_START
:
5282 case XML_XINCLUDE_END
:
5284 case XML_ELEMENT_NODE
:
5285 case XML_ATTRIBUTE_NODE
:
5287 case XML_ENTITY_REF_NODE
:
5288 case XML_ENTITY_NODE
:
5290 case XML_DOCUMENT_NODE
:
5291 case XML_ELEMENT_DECL
:
5292 case XML_ATTRIBUTE_DECL
:
5293 case XML_ENTITY_DECL
:
5302 if ((cur
->name
!= NULL
) && (!xmlDictOwns(dict
, cur
->name
)))
5304 cur
->name
= xmlDictLookup(dict
, name
, -1);
5306 if (cur
->name
!= NULL
)
5308 cur
->name
= xmlStrdup(name
);
5312 xmlFree((xmlChar
*) freeme
);
5316 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XINCLUDE_ENABLED)
5319 * @cur: the node being changed
5320 * @uri: the new base URI
5322 * Set (or reset) the base URI of a node, i.e. the value of the
5323 * xml:base attribute.
5326 xmlNodeSetBase(xmlNodePtr cur
, const xmlChar
* uri
) {
5330 if (cur
== NULL
) return;
5333 case XML_CDATA_SECTION_NODE
:
5334 case XML_COMMENT_NODE
:
5335 case XML_DOCUMENT_TYPE_NODE
:
5336 case XML_DOCUMENT_FRAG_NODE
:
5337 case XML_NOTATION_NODE
:
5339 case XML_ELEMENT_DECL
:
5340 case XML_ATTRIBUTE_DECL
:
5341 case XML_ENTITY_DECL
:
5343 case XML_ENTITY_REF_NODE
:
5344 case XML_ENTITY_NODE
:
5345 case XML_NAMESPACE_DECL
:
5346 case XML_XINCLUDE_START
:
5347 case XML_XINCLUDE_END
:
5349 case XML_ELEMENT_NODE
:
5350 case XML_ATTRIBUTE_NODE
:
5352 case XML_DOCUMENT_NODE
:
5353 case XML_HTML_DOCUMENT_NODE
: {
5354 xmlDocPtr doc
= (xmlDocPtr
) cur
;
5356 if (doc
->URL
!= NULL
)
5357 xmlFree((xmlChar
*) doc
->URL
);
5361 doc
->URL
= xmlPathToURI(uri
);
5366 ns
= xmlSearchNsByHref(cur
->doc
, cur
, XML_XML_NAMESPACE
);
5369 fixed
= xmlPathToURI(uri
);
5370 if (fixed
!= NULL
) {
5371 xmlSetNsProp(cur
, ns
, BAD_CAST
"base", fixed
);
5374 xmlSetNsProp(cur
, ns
, BAD_CAST
"base", uri
);
5377 #endif /* LIBXML_TREE_ENABLED */
5381 * @doc: the document the node pertains to
5382 * @cur: the node being checked
5384 * Searches for the BASE URL. The code should work on both XML
5385 * and HTML document even if base mechanisms are completely different.
5386 * It returns the base as defined in RFC 2396 sections
5387 * 5.1.1. Base URI within Document Content
5389 * 5.1.2. Base URI from the Encapsulating Entity
5390 * However it does not return the document base (5.1.3), use
5391 * doc->URL in this case
5393 * Returns a pointer to the base URL, or NULL if not found
5394 * It's up to the caller to free the memory with xmlFree().
5397 xmlNodeGetBase(const xmlDoc
*doc
, const xmlNode
*cur
) {
5398 xmlChar
*oldbase
= NULL
;
5399 xmlChar
*base
, *newbase
;
5401 if ((cur
== NULL
) && (doc
== NULL
))
5403 if ((cur
!= NULL
) && (cur
->type
== XML_NAMESPACE_DECL
))
5405 if (doc
== NULL
) doc
= cur
->doc
;
5406 if ((doc
!= NULL
) && (doc
->type
== XML_HTML_DOCUMENT_NODE
)) {
5407 cur
= doc
->children
;
5408 while ((cur
!= NULL
) && (cur
->name
!= NULL
)) {
5409 if (cur
->type
!= XML_ELEMENT_NODE
) {
5413 if (!xmlStrcasecmp(cur
->name
, BAD_CAST
"html")) {
5414 cur
= cur
->children
;
5417 if (!xmlStrcasecmp(cur
->name
, BAD_CAST
"head")) {
5418 cur
= cur
->children
;
5421 if (!xmlStrcasecmp(cur
->name
, BAD_CAST
"base")) {
5422 return(xmlGetProp(cur
, BAD_CAST
"href"));
5428 while (cur
!= NULL
) {
5429 if (cur
->type
== XML_ENTITY_DECL
) {
5430 xmlEntityPtr ent
= (xmlEntityPtr
) cur
;
5431 return(xmlStrdup(ent
->URI
));
5433 if (cur
->type
== XML_ELEMENT_NODE
) {
5434 base
= xmlGetNsProp(cur
, BAD_CAST
"base", XML_XML_NAMESPACE
);
5436 if (oldbase
!= NULL
) {
5437 newbase
= xmlBuildURI(oldbase
, base
);
5438 if (newbase
!= NULL
) {
5450 if ((!xmlStrncmp(oldbase
, BAD_CAST
"http://", 7)) ||
5451 (!xmlStrncmp(oldbase
, BAD_CAST
"ftp://", 6)) ||
5452 (!xmlStrncmp(oldbase
, BAD_CAST
"urn:", 4)))
5458 if ((doc
!= NULL
) && (doc
->URL
!= NULL
)) {
5459 if (oldbase
== NULL
)
5460 return(xmlStrdup(doc
->URL
));
5461 newbase
= xmlBuildURI(oldbase
, doc
->URL
);
5469 * xmlNodeBufGetContent:
5471 * @cur: the node being read
5473 * Read the value of a node @cur, this can be either the text carried
5474 * directly by this node if it's a TEXT node or the aggregate string
5475 * of the values carried by this node child's (TEXT and ENTITY_REF).
5476 * Entity references are substituted.
5477 * Fills up the buffer @buffer with this value
5479 * Returns 0 in case of success and -1 in case of error.
5482 xmlNodeBufGetContent(xmlBufferPtr buffer
, const xmlNode
*cur
)
5487 if ((cur
== NULL
) || (buffer
== NULL
)) return(-1);
5488 buf
= xmlBufFromBuffer(buffer
);
5489 ret
= xmlBufGetNodeContent(buf
, cur
);
5490 buffer
= xmlBufBackToBuffer(buf
);
5491 if ((ret
< 0) || (buffer
== NULL
))
5497 * xmlBufGetNodeContent:
5498 * @buf: a buffer xmlBufPtr
5499 * @cur: the node being read
5501 * Read the value of a node @cur, this can be either the text carried
5502 * directly by this node if it's a TEXT node or the aggregate string
5503 * of the values carried by this node child's (TEXT and ENTITY_REF).
5504 * Entity references are substituted.
5505 * Fills up the buffer @buf with this value
5507 * Returns 0 in case of success and -1 in case of error.
5510 xmlBufGetNodeContent(xmlBufPtr buf
, const xmlNode
*cur
)
5512 if ((cur
== NULL
) || (buf
== NULL
)) return(-1);
5513 switch (cur
->type
) {
5514 case XML_CDATA_SECTION_NODE
:
5516 xmlBufCat(buf
, cur
->content
);
5518 case XML_DOCUMENT_FRAG_NODE
:
5519 case XML_ELEMENT_NODE
:{
5520 const xmlNode
*tmp
= cur
;
5522 while (tmp
!= NULL
) {
5523 switch (tmp
->type
) {
5524 case XML_CDATA_SECTION_NODE
:
5526 if (tmp
->content
!= NULL
)
5527 xmlBufCat(buf
, tmp
->content
);
5529 case XML_ENTITY_REF_NODE
:
5530 xmlBufGetNodeContent(buf
, tmp
);
5538 if (tmp
->children
!= NULL
) {
5539 if (tmp
->children
->type
!= XML_ENTITY_DECL
) {
5540 tmp
= tmp
->children
;
5547 if (tmp
->next
!= NULL
) {
5560 if (tmp
->next
!= NULL
) {
5564 } while (tmp
!= NULL
);
5568 case XML_ATTRIBUTE_NODE
:{
5569 xmlAttrPtr attr
= (xmlAttrPtr
) cur
;
5570 xmlNodePtr tmp
= attr
->children
;
5572 while (tmp
!= NULL
) {
5573 if (tmp
->type
== XML_TEXT_NODE
)
5574 xmlBufCat(buf
, tmp
->content
);
5576 xmlBufGetNodeContent(buf
, tmp
);
5581 case XML_COMMENT_NODE
:
5583 xmlBufCat(buf
, cur
->content
);
5585 case XML_ENTITY_REF_NODE
:{
5589 /* lookup entity declaration */
5590 ent
= xmlGetDocEntity(cur
->doc
, cur
->name
);
5594 /* an entity content can be any "well balanced chunk",
5595 * i.e. the result of the content [43] production:
5596 * http://www.w3.org/TR/REC-xml#NT-content
5597 * -> we iterate through child nodes and recursive call
5598 * xmlNodeGetContent() which handles all possible node types */
5599 tmp
= ent
->children
;
5601 xmlBufGetNodeContent(buf
, tmp
);
5606 case XML_ENTITY_NODE
:
5607 case XML_DOCUMENT_TYPE_NODE
:
5608 case XML_NOTATION_NODE
:
5610 case XML_XINCLUDE_START
:
5611 case XML_XINCLUDE_END
:
5613 case XML_DOCUMENT_NODE
:
5614 case XML_HTML_DOCUMENT_NODE
:
5615 cur
= cur
->children
;
5616 while (cur
!= NULL
) {
5617 if ((cur
->type
== XML_ELEMENT_NODE
) ||
5618 (cur
->type
== XML_TEXT_NODE
) ||
5619 (cur
->type
== XML_CDATA_SECTION_NODE
)) {
5620 xmlBufGetNodeContent(buf
, cur
);
5625 case XML_NAMESPACE_DECL
:
5626 xmlBufCat(buf
, ((xmlNsPtr
) cur
)->href
);
5628 case XML_ELEMENT_DECL
:
5629 case XML_ATTRIBUTE_DECL
:
5630 case XML_ENTITY_DECL
:
5637 * xmlNodeGetContent:
5638 * @cur: the node being read
5640 * Read the value of a node, this can be either the text carried
5641 * directly by this node if it's a TEXT node or the aggregate string
5642 * of the values carried by this node child's (TEXT and ENTITY_REF).
5643 * Entity references are substituted.
5644 * Returns a new #xmlChar * or NULL if no content is available.
5645 * It's up to the caller to free the memory with xmlFree().
5648 xmlNodeGetContent(const xmlNode
*cur
)
5652 switch (cur
->type
) {
5653 case XML_DOCUMENT_FRAG_NODE
:
5654 case XML_ELEMENT_NODE
:{
5658 buf
= xmlBufCreateSize(64);
5661 xmlBufSetAllocationScheme(buf
, XML_BUFFER_ALLOC_DOUBLEIT
);
5662 xmlBufGetNodeContent(buf
, cur
);
5663 ret
= xmlBufDetach(buf
);
5667 case XML_ATTRIBUTE_NODE
:
5668 return(xmlGetPropNodeValueInternal((xmlAttrPtr
) cur
));
5669 case XML_COMMENT_NODE
:
5671 if (cur
->content
!= NULL
)
5672 return (xmlStrdup(cur
->content
));
5674 case XML_ENTITY_REF_NODE
:{
5679 /* lookup entity declaration */
5680 ent
= xmlGetDocEntity(cur
->doc
, cur
->name
);
5684 buf
= xmlBufCreate();
5687 xmlBufSetAllocationScheme(buf
, XML_BUFFER_ALLOC_DOUBLEIT
);
5689 xmlBufGetNodeContent(buf
, cur
);
5691 ret
= xmlBufDetach(buf
);
5695 case XML_ENTITY_NODE
:
5696 case XML_DOCUMENT_TYPE_NODE
:
5697 case XML_NOTATION_NODE
:
5699 case XML_XINCLUDE_START
:
5700 case XML_XINCLUDE_END
:
5702 case XML_DOCUMENT_NODE
:
5703 case XML_HTML_DOCUMENT_NODE
: {
5707 buf
= xmlBufCreate();
5710 xmlBufSetAllocationScheme(buf
, XML_BUFFER_ALLOC_DOUBLEIT
);
5712 xmlBufGetNodeContent(buf
, (xmlNodePtr
) cur
);
5714 ret
= xmlBufDetach(buf
);
5718 case XML_NAMESPACE_DECL
: {
5721 tmp
= xmlStrdup(((xmlNsPtr
) cur
)->href
);
5724 case XML_ELEMENT_DECL
:
5727 case XML_ATTRIBUTE_DECL
:
5730 case XML_ENTITY_DECL
:
5733 case XML_CDATA_SECTION_NODE
:
5735 if (cur
->content
!= NULL
)
5736 return (xmlStrdup(cur
->content
));
5743 * xmlNodeSetContent:
5744 * @cur: the node being modified
5745 * @content: the new value of the content
5747 * Replace the content of a node.
5748 * NOTE: @content is supposed to be a piece of XML CDATA, so it allows entity
5749 * references, but XML special chars need to be escaped first by using
5750 * xmlEncodeEntitiesReentrant() resp. xmlEncodeSpecialChars().
5753 xmlNodeSetContent(xmlNodePtr cur
, const xmlChar
*content
) {
5756 xmlGenericError(xmlGenericErrorContext
,
5757 "xmlNodeSetContent : node == NULL\n");
5761 switch (cur
->type
) {
5762 case XML_DOCUMENT_FRAG_NODE
:
5763 case XML_ELEMENT_NODE
:
5764 case XML_ATTRIBUTE_NODE
:
5765 if (cur
->children
!= NULL
) xmlFreeNodeList(cur
->children
);
5766 cur
->children
= xmlStringGetNodeList(cur
->doc
, content
);
5767 UPDATE_LAST_CHILD_AND_PARENT(cur
)
5770 case XML_CDATA_SECTION_NODE
:
5771 case XML_ENTITY_REF_NODE
:
5772 case XML_ENTITY_NODE
:
5774 case XML_COMMENT_NODE
:
5775 if ((cur
->content
!= NULL
) &&
5776 (cur
->content
!= (xmlChar
*) &(cur
->properties
))) {
5777 if (!((cur
->doc
!= NULL
) && (cur
->doc
->dict
!= NULL
) &&
5778 (xmlDictOwns(cur
->doc
->dict
, cur
->content
))))
5779 xmlFree(cur
->content
);
5781 if (cur
->children
!= NULL
) xmlFreeNodeList(cur
->children
);
5782 cur
->last
= cur
->children
= NULL
;
5783 if (content
!= NULL
) {
5784 cur
->content
= xmlStrdup(content
);
5786 cur
->content
= NULL
;
5787 cur
->properties
= NULL
;
5789 case XML_DOCUMENT_NODE
:
5790 case XML_HTML_DOCUMENT_NODE
:
5791 case XML_DOCUMENT_TYPE_NODE
:
5792 case XML_XINCLUDE_START
:
5793 case XML_XINCLUDE_END
:
5795 case XML_NOTATION_NODE
:
5799 case XML_NAMESPACE_DECL
:
5801 case XML_ELEMENT_DECL
:
5804 case XML_ATTRIBUTE_DECL
:
5807 case XML_ENTITY_DECL
:
5813 #ifdef LIBXML_TREE_ENABLED
5815 * xmlNodeSetContentLen:
5816 * @cur: the node being modified
5817 * @content: the new value of the content
5818 * @len: the size of @content
5820 * Replace the content of a node.
5821 * NOTE: @content is supposed to be a piece of XML CDATA, so it allows entity
5822 * references, but XML special chars need to be escaped first by using
5823 * xmlEncodeEntitiesReentrant() resp. xmlEncodeSpecialChars().
5826 xmlNodeSetContentLen(xmlNodePtr cur
, const xmlChar
*content
, int len
) {
5829 xmlGenericError(xmlGenericErrorContext
,
5830 "xmlNodeSetContentLen : node == NULL\n");
5834 switch (cur
->type
) {
5835 case XML_DOCUMENT_FRAG_NODE
:
5836 case XML_ELEMENT_NODE
:
5837 case XML_ATTRIBUTE_NODE
:
5838 if (cur
->children
!= NULL
) xmlFreeNodeList(cur
->children
);
5839 cur
->children
= xmlStringLenGetNodeList(cur
->doc
, content
, len
);
5840 UPDATE_LAST_CHILD_AND_PARENT(cur
)
5843 case XML_CDATA_SECTION_NODE
:
5844 case XML_ENTITY_REF_NODE
:
5845 case XML_ENTITY_NODE
:
5847 case XML_COMMENT_NODE
:
5848 case XML_NOTATION_NODE
:
5849 if ((cur
->content
!= NULL
) &&
5850 (cur
->content
!= (xmlChar
*) &(cur
->properties
))) {
5851 if (!((cur
->doc
!= NULL
) && (cur
->doc
->dict
!= NULL
) &&
5852 (xmlDictOwns(cur
->doc
->dict
, cur
->content
))))
5853 xmlFree(cur
->content
);
5855 if (cur
->children
!= NULL
) xmlFreeNodeList(cur
->children
);
5856 cur
->children
= cur
->last
= NULL
;
5857 if (content
!= NULL
) {
5858 cur
->content
= xmlStrndup(content
, len
);
5860 cur
->content
= NULL
;
5861 cur
->properties
= NULL
;
5863 case XML_DOCUMENT_NODE
:
5865 case XML_HTML_DOCUMENT_NODE
:
5866 case XML_DOCUMENT_TYPE_NODE
:
5867 case XML_NAMESPACE_DECL
:
5868 case XML_XINCLUDE_START
:
5869 case XML_XINCLUDE_END
:
5871 case XML_ELEMENT_DECL
:
5874 case XML_ATTRIBUTE_DECL
:
5877 case XML_ENTITY_DECL
:
5882 #endif /* LIBXML_TREE_ENABLED */
5885 * xmlNodeAddContentLen:
5886 * @cur: the node being modified
5887 * @content: extra content
5888 * @len: the size of @content
5890 * Append the extra substring to the node content.
5891 * NOTE: In contrast to xmlNodeSetContentLen(), @content is supposed to be
5892 * raw text, so unescaped XML special chars are allowed, entity
5893 * references are not supported.
5896 xmlNodeAddContentLen(xmlNodePtr cur
, const xmlChar
*content
, int len
) {
5899 xmlGenericError(xmlGenericErrorContext
,
5900 "xmlNodeAddContentLen : node == NULL\n");
5904 if (len
<= 0) return;
5905 switch (cur
->type
) {
5906 case XML_DOCUMENT_FRAG_NODE
:
5907 case XML_ELEMENT_NODE
: {
5908 xmlNodePtr last
, newNode
, tmp
;
5911 newNode
= xmlNewDocTextLen(cur
->doc
, content
, len
);
5912 if (newNode
!= NULL
) {
5913 tmp
= xmlAddChild(cur
, newNode
);
5916 if ((last
!= NULL
) && (last
->next
== newNode
)) {
5917 xmlTextMerge(last
, newNode
);
5922 case XML_ATTRIBUTE_NODE
:
5925 case XML_CDATA_SECTION_NODE
:
5926 case XML_ENTITY_REF_NODE
:
5927 case XML_ENTITY_NODE
:
5929 case XML_COMMENT_NODE
:
5930 case XML_NOTATION_NODE
:
5931 if (content
!= NULL
) {
5932 if ((cur
->content
== (xmlChar
*) &(cur
->properties
)) ||
5933 ((cur
->doc
!= NULL
) && (cur
->doc
->dict
!= NULL
) &&
5934 xmlDictOwns(cur
->doc
->dict
, cur
->content
))) {
5935 cur
->content
= xmlStrncatNew(cur
->content
, content
, len
);
5936 cur
->properties
= NULL
;
5938 cur
->content
= xmlStrncat(cur
->content
, content
, len
);
5942 case XML_DOCUMENT_NODE
:
5944 case XML_HTML_DOCUMENT_NODE
:
5945 case XML_DOCUMENT_TYPE_NODE
:
5946 case XML_NAMESPACE_DECL
:
5947 case XML_XINCLUDE_START
:
5948 case XML_XINCLUDE_END
:
5950 case XML_ELEMENT_DECL
:
5951 case XML_ATTRIBUTE_DECL
:
5952 case XML_ENTITY_DECL
:
5958 * xmlNodeAddContent:
5959 * @cur: the node being modified
5960 * @content: extra content
5962 * Append the extra substring to the node content.
5963 * NOTE: In contrast to xmlNodeSetContent(), @content is supposed to be
5964 * raw text, so unescaped XML special chars are allowed, entity
5965 * references are not supported.
5968 xmlNodeAddContent(xmlNodePtr cur
, const xmlChar
*content
) {
5973 xmlGenericError(xmlGenericErrorContext
,
5974 "xmlNodeAddContent : node == NULL\n");
5978 if (content
== NULL
) return;
5979 len
= xmlStrlen(content
);
5980 xmlNodeAddContentLen(cur
, content
, len
);
5985 * @first: the first text node
5986 * @second: the second text node being merged
5988 * Merge two text nodes into one
5989 * Returns the first text node augmented
5992 xmlTextMerge(xmlNodePtr first
, xmlNodePtr second
) {
5993 if (first
== NULL
) return(second
);
5994 if (second
== NULL
) return(first
);
5995 if (first
->type
!= XML_TEXT_NODE
) return(first
);
5996 if (second
->type
!= XML_TEXT_NODE
) return(first
);
5997 if (second
->name
!= first
->name
)
5999 xmlNodeAddContent(first
, second
->content
);
6000 xmlUnlinkNode(second
);
6001 xmlFreeNode(second
);
6005 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XPATH_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
6008 * @doc: the document
6009 * @node: the current node
6011 * Search all the namespace applying to a given element.
6012 * Returns an NULL terminated array of all the #xmlNsPtr found
6013 * that need to be freed by the caller or NULL if no
6014 * namespace if defined
6017 xmlGetNsList(const xmlDoc
*doc ATTRIBUTE_UNUSED
, const xmlNode
*node
)
6020 xmlNsPtr
*ret
= NULL
;
6025 if ((node
== NULL
) || (node
->type
== XML_NAMESPACE_DECL
))
6028 while (node
!= NULL
) {
6029 if (node
->type
== XML_ELEMENT_NODE
) {
6031 while (cur
!= NULL
) {
6034 (xmlNsPtr
*) xmlMalloc((maxns
+ 1) *
6037 xmlTreeErrMemory("getting namespace list");
6042 for (i
= 0; i
< nbns
; i
++) {
6043 if ((cur
->prefix
== ret
[i
]->prefix
) ||
6044 (xmlStrEqual(cur
->prefix
, ret
[i
]->prefix
)))
6048 if (nbns
>= maxns
) {
6050 ret
= (xmlNsPtr
*) xmlRealloc(ret
,
6055 xmlTreeErrMemory("getting namespace list");
6066 node
= node
->parent
;
6070 #endif /* LIBXML_TREE_ENABLED */
6073 * xmlTreeEnsureXMLDecl:
6076 * Ensures that there is an XML namespace declaration on the doc.
6078 * Returns the XML ns-struct or NULL on API and internal errors.
6081 xmlTreeEnsureXMLDecl(xmlDocPtr doc
)
6085 if (doc
->oldNs
!= NULL
)
6086 return (doc
->oldNs
);
6089 ns
= (xmlNsPtr
) xmlMalloc(sizeof(xmlNs
));
6092 "allocating the XML namespace");
6095 memset(ns
, 0, sizeof(xmlNs
));
6096 ns
->type
= XML_LOCAL_NAMESPACE
;
6097 ns
->href
= xmlStrdup(XML_XML_NAMESPACE
);
6098 ns
->prefix
= xmlStrdup((const xmlChar
*)"xml");
6106 * @doc: the document
6107 * @node: the current node
6108 * @nameSpace: the namespace prefix
6110 * Search a Ns registered under a given name space for a document.
6111 * recurse on the parents until it finds the defined namespace
6112 * or return NULL otherwise.
6113 * @nameSpace can be NULL, this is a search for the default namespace.
6114 * We don't allow to cross entities boundaries. If you don't declare
6115 * the namespace within those you will be in troubles !!! A warning
6116 * is generated to cover this case.
6118 * Returns the namespace pointer or NULL.
6121 xmlSearchNs(xmlDocPtr doc
, xmlNodePtr node
, const xmlChar
*nameSpace
) {
6124 const xmlNode
*orig
= node
;
6126 if ((node
== NULL
) || (node
->type
== XML_NAMESPACE_DECL
)) return(NULL
);
6127 if ((nameSpace
!= NULL
) &&
6128 (xmlStrEqual(nameSpace
, (const xmlChar
*)"xml"))) {
6129 if ((doc
== NULL
) && (node
->type
== XML_ELEMENT_NODE
)) {
6131 * The XML-1.0 namespace is normally held on the root
6132 * element. In this case exceptionally create it on the
6135 cur
= (xmlNsPtr
) xmlMalloc(sizeof(xmlNs
));
6137 xmlTreeErrMemory("searching namespace");
6140 memset(cur
, 0, sizeof(xmlNs
));
6141 cur
->type
= XML_LOCAL_NAMESPACE
;
6142 cur
->href
= xmlStrdup(XML_XML_NAMESPACE
);
6143 cur
->prefix
= xmlStrdup((const xmlChar
*)"xml");
6144 cur
->next
= node
->nsDef
;
6154 * Return the XML namespace declaration held by the doc.
6156 if (doc
->oldNs
== NULL
)
6157 return(xmlTreeEnsureXMLDecl(doc
));
6161 while (node
!= NULL
) {
6162 if ((node
->type
== XML_ENTITY_REF_NODE
) ||
6163 (node
->type
== XML_ENTITY_NODE
) ||
6164 (node
->type
== XML_ENTITY_DECL
))
6166 if (node
->type
== XML_ELEMENT_NODE
) {
6168 while (cur
!= NULL
) {
6169 if ((cur
->prefix
== NULL
) && (nameSpace
== NULL
) &&
6170 (cur
->href
!= NULL
))
6172 if ((cur
->prefix
!= NULL
) && (nameSpace
!= NULL
) &&
6173 (cur
->href
!= NULL
) &&
6174 (xmlStrEqual(cur
->prefix
, nameSpace
)))
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
)))
6191 node
= node
->parent
;
6198 * @doc: the document
6199 * @node: the current node
6200 * @ancestor: the ancestor carrying the namespace
6201 * @prefix: the namespace prefix
6203 * Verify that the given namespace held on @ancestor is still in scope
6206 * Returns 1 if true, 0 if false and -1 in case of error.
6209 xmlNsInScope(xmlDocPtr doc ATTRIBUTE_UNUSED
, xmlNodePtr node
,
6210 xmlNodePtr ancestor
, const xmlChar
* prefix
)
6214 while ((node
!= NULL
) && (node
!= ancestor
)) {
6215 if ((node
->type
== XML_ENTITY_REF_NODE
) ||
6216 (node
->type
== XML_ENTITY_NODE
) ||
6217 (node
->type
== XML_ENTITY_DECL
))
6219 if (node
->type
== XML_ELEMENT_NODE
) {
6221 while (tst
!= NULL
) {
6222 if ((tst
->prefix
== NULL
)
6223 && (prefix
== NULL
))
6225 if ((tst
->prefix
!= NULL
)
6227 && (xmlStrEqual(tst
->prefix
, prefix
)))
6232 node
= node
->parent
;
6234 if (node
!= ancestor
)
6240 * xmlSearchNsByHref:
6241 * @doc: the document
6242 * @node: the current node
6243 * @href: the namespace value
6245 * Search a Ns aliasing a given URI. Recurse on the parents until it finds
6246 * the defined namespace or return NULL otherwise.
6247 * Returns the namespace pointer or NULL.
6250 xmlSearchNsByHref(xmlDocPtr doc
, xmlNodePtr node
, const xmlChar
* href
)
6253 xmlNodePtr orig
= node
;
6256 if ((node
== NULL
) || (node
->type
== XML_NAMESPACE_DECL
) || (href
== NULL
))
6258 if (xmlStrEqual(href
, XML_XML_NAMESPACE
)) {
6260 * Only the document can hold the XML spec namespace.
6262 if ((doc
== NULL
) && (node
->type
== XML_ELEMENT_NODE
)) {
6264 * The XML-1.0 namespace is normally held on the root
6265 * element. In this case exceptionally create it on the
6268 cur
= (xmlNsPtr
) xmlMalloc(sizeof(xmlNs
));
6270 xmlTreeErrMemory("searching namespace");
6273 memset(cur
, 0, sizeof(xmlNs
));
6274 cur
->type
= XML_LOCAL_NAMESPACE
;
6275 cur
->href
= xmlStrdup(XML_XML_NAMESPACE
);
6276 cur
->prefix
= xmlStrdup((const xmlChar
*) "xml");
6277 cur
->next
= node
->nsDef
;
6287 * Return the XML namespace declaration held by the doc.
6289 if (doc
->oldNs
== NULL
)
6290 return(xmlTreeEnsureXMLDecl(doc
));
6294 is_attr
= (node
->type
== XML_ATTRIBUTE_NODE
);
6295 while (node
!= NULL
) {
6296 if ((node
->type
== XML_ENTITY_REF_NODE
) ||
6297 (node
->type
== XML_ENTITY_NODE
) ||
6298 (node
->type
== XML_ENTITY_DECL
))
6300 if (node
->type
== XML_ELEMENT_NODE
) {
6302 while (cur
!= NULL
) {
6303 if ((cur
->href
!= NULL
) && (href
!= NULL
) &&
6304 (xmlStrEqual(cur
->href
, href
))) {
6305 if (((!is_attr
) || (cur
->prefix
!= NULL
)) &&
6306 (xmlNsInScope(doc
, orig
, node
, cur
->prefix
) == 1))
6314 if ((cur
->href
!= NULL
) && (href
!= NULL
) &&
6315 (xmlStrEqual(cur
->href
, href
))) {
6316 if (((!is_attr
) || (cur
->prefix
!= NULL
)) &&
6317 (xmlNsInScope(doc
, orig
, node
, cur
->prefix
) == 1))
6323 node
= node
->parent
;
6329 * xmlNewReconciledNs:
6330 * @doc: the document
6331 * @tree: a node expected to hold the new namespace
6332 * @ns: the original namespace
6334 * This function tries to locate a namespace definition in a tree
6335 * ancestors, or create a new namespace definition node similar to
6336 * @ns trying to reuse the same prefix. However if the given prefix is
6337 * null (default namespace) or reused within the subtree defined by
6338 * @tree or on one of its ancestors then a new prefix is generated.
6339 * Returns the (new) namespace definition or NULL in case of error
6342 xmlNewReconciledNs(xmlDocPtr doc
, xmlNodePtr tree
, xmlNsPtr ns
) {
6347 if ((tree
== NULL
) || (tree
->type
!= XML_ELEMENT_NODE
)) {
6349 xmlGenericError(xmlGenericErrorContext
,
6350 "xmlNewReconciledNs : tree == NULL\n");
6354 if ((ns
== NULL
) || (ns
->type
!= XML_NAMESPACE_DECL
)) {
6356 xmlGenericError(xmlGenericErrorContext
,
6357 "xmlNewReconciledNs : ns == NULL\n");
6362 * Search an existing namespace definition inherited.
6364 def
= xmlSearchNsByHref(doc
, tree
, ns
->href
);
6369 * Find a close prefix which is not already in use.
6370 * Let's strip namespace prefixes longer than 20 chars !
6372 if (ns
->prefix
== NULL
)
6373 snprintf((char *) prefix
, sizeof(prefix
), "default");
6375 snprintf((char *) prefix
, sizeof(prefix
), "%.20s", (char *)ns
->prefix
);
6377 def
= xmlSearchNs(doc
, tree
, prefix
);
6378 while (def
!= NULL
) {
6379 if (counter
> 1000) return(NULL
);
6380 if (ns
->prefix
== NULL
)
6381 snprintf((char *) prefix
, sizeof(prefix
), "default%d", counter
++);
6383 snprintf((char *) prefix
, sizeof(prefix
), "%.20s%d",
6384 (char *)ns
->prefix
, counter
++);
6385 def
= xmlSearchNs(doc
, tree
, prefix
);
6389 * OK, now we are ready to create a new one.
6391 def
= xmlNewNs(tree
, ns
->href
, prefix
);
6395 #ifdef LIBXML_TREE_ENABLED
6397 * xmlReconciliateNs:
6398 * @doc: the document
6399 * @tree: a node defining the subtree to reconciliate
6401 * This function checks that all the namespaces declared within the given
6402 * tree are properly declared. This is needed for example after Copy or Cut
6403 * and then paste operations. The subtree may still hold pointers to
6404 * namespace declarations outside the subtree or invalid/masked. As much
6405 * as possible the function try to reuse the existing namespaces found in
6406 * the new environment. If not possible the new namespaces are redeclared
6407 * on @tree at the top of the given subtree.
6408 * Returns the number of namespace declarations created or -1 in case of error.
6411 xmlReconciliateNs(xmlDocPtr doc
, xmlNodePtr tree
) {
6412 xmlNsPtr
*oldNs
= NULL
;
6413 xmlNsPtr
*newNs
= NULL
;
6418 xmlNodePtr node
= tree
;
6422 if ((node
== NULL
) || (node
->type
!= XML_ELEMENT_NODE
)) return(-1);
6423 if ((doc
== NULL
) || (doc
->type
!= XML_DOCUMENT_NODE
)) return(-1);
6424 if (node
->doc
!= doc
) return(-1);
6425 while (node
!= NULL
) {
6427 * Reconciliate the node namespace
6429 if (node
->ns
!= NULL
) {
6431 * initialize the cache if needed
6433 if (sizeCache
== 0) {
6435 oldNs
= (xmlNsPtr
*) xmlMalloc(sizeCache
*
6437 if (oldNs
== NULL
) {
6438 xmlTreeErrMemory("fixing namespaces");
6441 newNs
= (xmlNsPtr
*) xmlMalloc(sizeCache
*
6443 if (newNs
== NULL
) {
6444 xmlTreeErrMemory("fixing namespaces");
6449 for (i
= 0;i
< nbCache
;i
++) {
6450 if (oldNs
[i
] == node
->ns
) {
6451 node
->ns
= newNs
[i
];
6457 * OK we need to recreate a new namespace definition
6459 n
= xmlNewReconciledNs(doc
, tree
, node
->ns
);
6460 if (n
!= NULL
) { /* :-( what if else ??? */
6462 * check if we need to grow the cache buffers.
6464 if (sizeCache
<= nbCache
) {
6466 oldNs
= (xmlNsPtr
*) xmlRealloc(oldNs
, sizeCache
*
6468 if (oldNs
== NULL
) {
6469 xmlTreeErrMemory("fixing namespaces");
6473 newNs
= (xmlNsPtr
*) xmlRealloc(newNs
, sizeCache
*
6475 if (newNs
== NULL
) {
6476 xmlTreeErrMemory("fixing namespaces");
6482 oldNs
[nbCache
++] = node
->ns
;
6488 * now check for namespace held by attributes on the node.
6490 if (node
->type
== XML_ELEMENT_NODE
) {
6491 attr
= node
->properties
;
6492 while (attr
!= NULL
) {
6493 if (attr
->ns
!= NULL
) {
6495 * initialize the cache if needed
6497 if (sizeCache
== 0) {
6499 oldNs
= (xmlNsPtr
*) xmlMalloc(sizeCache
*
6501 if (oldNs
== NULL
) {
6502 xmlTreeErrMemory("fixing namespaces");
6505 newNs
= (xmlNsPtr
*) xmlMalloc(sizeCache
*
6507 if (newNs
== NULL
) {
6508 xmlTreeErrMemory("fixing namespaces");
6513 for (i
= 0;i
< nbCache
;i
++) {
6514 if (oldNs
[i
] == attr
->ns
) {
6515 attr
->ns
= newNs
[i
];
6521 * OK we need to recreate a new namespace definition
6523 n
= xmlNewReconciledNs(doc
, tree
, attr
->ns
);
6524 if (n
!= NULL
) { /* :-( what if else ??? */
6526 * check if we need to grow the cache buffers.
6528 if (sizeCache
<= nbCache
) {
6530 oldNs
= (xmlNsPtr
*) xmlRealloc(oldNs
,
6531 sizeCache
* sizeof(xmlNsPtr
));
6532 if (oldNs
== NULL
) {
6533 xmlTreeErrMemory("fixing namespaces");
6537 newNs
= (xmlNsPtr
*) xmlRealloc(newNs
,
6538 sizeCache
* sizeof(xmlNsPtr
));
6539 if (newNs
== NULL
) {
6540 xmlTreeErrMemory("fixing namespaces");
6546 oldNs
[nbCache
++] = attr
->ns
;
6556 * Browse the full subtree, deep first
6558 if ((node
->children
!= NULL
) && (node
->type
!= XML_ENTITY_REF_NODE
)) {
6560 node
= node
->children
;
6561 } else if ((node
!= tree
) && (node
->next
!= NULL
)) {
6564 } else if (node
!= tree
) {
6565 /* go up to parents->next if needed */
6566 while (node
!= tree
) {
6567 if (node
->parent
!= NULL
)
6568 node
= node
->parent
;
6569 if ((node
!= tree
) && (node
->next
!= NULL
)) {
6573 if (node
->parent
== NULL
) {
6578 /* exit condition */
6590 #endif /* LIBXML_TREE_ENABLED */
6593 xmlGetPropNodeInternal(const xmlNode
*node
, const xmlChar
*name
,
6594 const xmlChar
*nsName
, int useDTD
)
6598 /* Avoid unused variable warning if features are disabled. */
6601 if ((node
== NULL
) || (node
->type
!= XML_ELEMENT_NODE
) || (name
== NULL
))
6604 if (node
->properties
!= NULL
) {
6605 prop
= node
->properties
;
6606 if (nsName
== NULL
) {
6608 * We want the attr to be in no namespace.
6611 if ((prop
->ns
== NULL
) && xmlStrEqual(prop
->name
, name
)) {
6615 } while (prop
!= NULL
);
6618 * We want the attr to be in the specified namespace.
6621 if ((prop
->ns
!= NULL
) && xmlStrEqual(prop
->name
, name
) &&
6622 ((prop
->ns
->href
== nsName
) ||
6623 xmlStrEqual(prop
->ns
->href
, nsName
)))
6628 } while (prop
!= NULL
);
6632 #ifdef LIBXML_TREE_ENABLED
6636 * Check if there is a default/fixed attribute declaration in
6637 * the internal or external subset.
6639 if ((node
->doc
!= NULL
) && (node
->doc
->intSubset
!= NULL
)) {
6640 xmlDocPtr doc
= node
->doc
;
6641 xmlAttributePtr attrDecl
= NULL
;
6642 xmlChar
*elemQName
, *tmpstr
= NULL
;
6645 * We need the QName of the element for the DTD-lookup.
6647 if ((node
->ns
!= NULL
) && (node
->ns
->prefix
!= NULL
)) {
6648 tmpstr
= xmlStrdup(node
->ns
->prefix
);
6649 tmpstr
= xmlStrcat(tmpstr
, BAD_CAST
":");
6650 tmpstr
= xmlStrcat(tmpstr
, node
->name
);
6655 elemQName
= (xmlChar
*) node
->name
;
6656 if (nsName
== NULL
) {
6658 * The common and nice case: Attr in no namespace.
6660 attrDecl
= xmlGetDtdQAttrDesc(doc
->intSubset
,
6661 elemQName
, name
, NULL
);
6662 if ((attrDecl
== NULL
) && (doc
->extSubset
!= NULL
)) {
6663 attrDecl
= xmlGetDtdQAttrDesc(doc
->extSubset
,
6664 elemQName
, name
, NULL
);
6666 } else if (xmlStrEqual(nsName
, XML_XML_NAMESPACE
)) {
6668 * The XML namespace must be bound to prefix 'xml'.
6670 attrDecl
= xmlGetDtdQAttrDesc(doc
->intSubset
,
6671 elemQName
, name
, BAD_CAST
"xml");
6672 if ((attrDecl
== NULL
) && (doc
->extSubset
!= NULL
)) {
6673 attrDecl
= xmlGetDtdQAttrDesc(doc
->extSubset
,
6674 elemQName
, name
, BAD_CAST
"xml");
6677 xmlNsPtr
*nsList
, *cur
;
6680 * The ugly case: Search using the prefixes of in-scope
6681 * ns-decls corresponding to @nsName.
6683 nsList
= xmlGetNsList(node
->doc
, node
);
6684 if (nsList
== NULL
) {
6690 while (*cur
!= NULL
) {
6691 if (xmlStrEqual((*cur
)->href
, nsName
)) {
6692 attrDecl
= xmlGetDtdQAttrDesc(doc
->intSubset
, elemQName
,
6693 name
, (*cur
)->prefix
);
6696 if (doc
->extSubset
!= NULL
) {
6697 attrDecl
= xmlGetDtdQAttrDesc(doc
->extSubset
, elemQName
,
6698 name
, (*cur
)->prefix
);
6710 * Only default/fixed attrs are relevant.
6712 if ((attrDecl
!= NULL
) && (attrDecl
->defaultValue
!= NULL
))
6713 return((xmlAttrPtr
) attrDecl
);
6715 #endif /* LIBXML_TREE_ENABLED */
6720 xmlGetPropNodeValueInternal(const xmlAttr
*prop
)
6724 if (prop
->type
== XML_ATTRIBUTE_NODE
) {
6726 * Note that we return at least the empty string.
6727 * TODO: Do we really always want that?
6729 if (prop
->children
!= NULL
) {
6730 if ((prop
->children
->next
== NULL
) &&
6731 ((prop
->children
->type
== XML_TEXT_NODE
) ||
6732 (prop
->children
->type
== XML_CDATA_SECTION_NODE
)))
6735 * Optimization for the common case: only 1 text node.
6737 return(xmlStrdup(prop
->children
->content
));
6741 ret
= xmlNodeListGetString(prop
->doc
, prop
->children
, 1);
6746 return(xmlStrdup((xmlChar
*)""));
6747 } else if (prop
->type
== XML_ATTRIBUTE_DECL
) {
6748 return(xmlStrdup(((xmlAttributePtr
)prop
)->defaultValue
));
6756 * @name: the attribute name
6758 * Search an attribute associated to a node
6759 * This function also looks in DTD attribute declaration for #FIXED or
6760 * default declaration values unless DTD use has been turned off.
6762 * Returns the attribute or the attribute declaration or NULL if
6763 * neither was found.
6766 xmlHasProp(const xmlNode
*node
, const xmlChar
*name
) {
6770 if ((node
== NULL
) || (node
->type
!= XML_ELEMENT_NODE
) || (name
== NULL
))
6773 * Check on the properties attached to the node
6775 prop
= node
->properties
;
6776 while (prop
!= NULL
) {
6777 if (xmlStrEqual(prop
->name
, name
)) {
6782 if (!xmlCheckDTD
) return(NULL
);
6785 * Check if there is a default declaration in the internal
6786 * or external subsets
6790 xmlAttributePtr attrDecl
;
6791 if (doc
->intSubset
!= NULL
) {
6792 attrDecl
= xmlGetDtdAttrDesc(doc
->intSubset
, node
->name
, name
);
6793 if ((attrDecl
== NULL
) && (doc
->extSubset
!= NULL
))
6794 attrDecl
= xmlGetDtdAttrDesc(doc
->extSubset
, node
->name
, name
);
6795 if ((attrDecl
!= NULL
) && (attrDecl
->defaultValue
!= NULL
))
6796 /* return attribute declaration only if a default value is given
6797 (that includes #FIXED declarations) */
6798 return((xmlAttrPtr
) attrDecl
);
6807 * @name: the attribute name
6808 * @nameSpace: the URI of the namespace
6810 * Search for an attribute associated to a node
6811 * This attribute has to be anchored in the namespace specified.
6812 * This does the entity substitution.
6813 * This function looks in DTD attribute declaration for #FIXED or
6814 * default declaration values unless DTD use has been turned off.
6815 * Note that a namespace of NULL indicates to use the default namespace.
6817 * Returns the attribute or the attribute declaration or NULL
6818 * if neither was found.
6821 xmlHasNsProp(const xmlNode
*node
, const xmlChar
*name
, const xmlChar
*nameSpace
) {
6823 return(xmlGetPropNodeInternal(node
, name
, nameSpace
, xmlCheckDTD
));
6829 * @name: the attribute name
6831 * Search and get the value of an attribute associated to a node
6832 * This does the entity substitution.
6833 * This function looks in DTD attribute declaration for #FIXED or
6834 * default declaration values unless DTD use has been turned off.
6835 * NOTE: this function acts independently of namespaces associated
6836 * to the attribute. Use xmlGetNsProp() or xmlGetNoNsProp()
6837 * for namespace aware processing.
6839 * Returns the attribute value or NULL if not found.
6840 * It's up to the caller to free the memory with xmlFree().
6843 xmlGetProp(const xmlNode
*node
, const xmlChar
*name
) {
6846 prop
= xmlHasProp(node
, name
);
6849 return(xmlGetPropNodeValueInternal(prop
));
6855 * @name: the attribute name
6857 * Search and get the value of an attribute associated to a node
6858 * This does the entity substitution.
6859 * This function looks in DTD attribute declaration for #FIXED or
6860 * default declaration values unless DTD use has been turned off.
6861 * This function is similar to xmlGetProp except it will accept only
6862 * an attribute in no namespace.
6864 * Returns the attribute value or NULL if not found.
6865 * It's up to the caller to free the memory with xmlFree().
6868 xmlGetNoNsProp(const xmlNode
*node
, const xmlChar
*name
) {
6871 prop
= xmlGetPropNodeInternal(node
, name
, NULL
, xmlCheckDTD
);
6874 return(xmlGetPropNodeValueInternal(prop
));
6880 * @name: the attribute name
6881 * @nameSpace: the URI of the namespace
6883 * Search and get the value of an attribute associated to a node
6884 * This attribute has to be anchored in the namespace specified.
6885 * This does the entity substitution.
6886 * This function looks in DTD attribute declaration for #FIXED or
6887 * default declaration values unless DTD use has been turned off.
6889 * Returns the attribute value or NULL if not found.
6890 * It's up to the caller to free the memory with xmlFree().
6893 xmlGetNsProp(const xmlNode
*node
, const xmlChar
*name
, const xmlChar
*nameSpace
) {
6896 prop
= xmlGetPropNodeInternal(node
, name
, nameSpace
, xmlCheckDTD
);
6899 return(xmlGetPropNodeValueInternal(prop
));
6902 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
6906 * @name: the attribute name
6908 * Remove an attribute carried by a node.
6909 * This handles only attributes in no namespace.
6910 * Returns 0 if successful, -1 if not found
6913 xmlUnsetProp(xmlNodePtr node
, const xmlChar
*name
) {
6916 prop
= xmlGetPropNodeInternal(node
, name
, NULL
, 0);
6919 xmlUnlinkNode((xmlNodePtr
) prop
);
6927 * @ns: the namespace definition
6928 * @name: the attribute name
6930 * Remove an attribute carried by a node.
6931 * Returns 0 if successful, -1 if not found
6934 xmlUnsetNsProp(xmlNodePtr node
, xmlNsPtr ns
, const xmlChar
*name
) {
6937 prop
= xmlGetPropNodeInternal(node
, name
, (ns
!= NULL
) ? ns
->href
: NULL
, 0);
6940 xmlUnlinkNode((xmlNodePtr
) prop
);
6946 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XINCLUDE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) || defined(LIBXML_HTML_ENABLED)
6950 * @name: the attribute name (a QName)
6951 * @value: the attribute value
6953 * Set (or reset) an attribute carried by a node.
6954 * If @name has a prefix, then the corresponding
6955 * namespace-binding will be used, if in scope; it is an
6956 * error it there's no such ns-binding for the prefix in
6958 * Returns the attribute pointer.
6962 xmlSetProp(xmlNodePtr node
, const xmlChar
*name
, const xmlChar
*value
) {
6964 const xmlChar
*nqname
;
6966 if ((node
== NULL
) || (name
== NULL
) || (node
->type
!= XML_ELEMENT_NODE
))
6972 nqname
= xmlSplitQName3(name
, &len
);
6973 if (nqname
!= NULL
) {
6975 xmlChar
*prefix
= xmlStrndup(name
, len
);
6976 ns
= xmlSearchNs(node
->doc
, node
, prefix
);
6980 return(xmlSetNsProp(node
, ns
, nqname
, value
));
6982 return(xmlSetNsProp(node
, NULL
, name
, value
));
6988 * @ns: the namespace definition
6989 * @name: the attribute name
6990 * @value: the attribute value
6992 * Set (or reset) an attribute carried by a node.
6993 * The ns structure must be in scope, this is not checked
6995 * Returns the attribute pointer.
6998 xmlSetNsProp(xmlNodePtr node
, xmlNsPtr ns
, const xmlChar
*name
,
6999 const xmlChar
*value
)
7003 if (ns
&& (ns
->href
== NULL
))
7005 prop
= xmlGetPropNodeInternal(node
, name
, (ns
!= NULL
) ? ns
->href
: NULL
, 0);
7008 * Modify the attribute's value.
7010 if (prop
->atype
== XML_ATTRIBUTE_ID
) {
7011 xmlRemoveID(node
->doc
, prop
);
7012 prop
->atype
= XML_ATTRIBUTE_ID
;
7014 if (prop
->children
!= NULL
)
7015 xmlFreeNodeList(prop
->children
);
7016 prop
->children
= NULL
;
7019 if (value
!= NULL
) {
7022 prop
->children
= xmlNewDocText(node
->doc
, value
);
7024 tmp
= prop
->children
;
7025 while (tmp
!= NULL
) {
7026 tmp
->parent
= (xmlNodePtr
) prop
;
7027 if (tmp
->next
== NULL
)
7032 if (prop
->atype
== XML_ATTRIBUTE_ID
)
7033 xmlAddID(NULL
, node
->doc
, value
, prop
);
7037 * No equal attr found; create a new one.
7039 return(xmlNewPropInternal(node
, ns
, name
, value
, 0));
7042 #endif /* LIBXML_TREE_ENABLED */
7048 * Is this node a Text node ?
7049 * Returns 1 yes, 0 no
7052 xmlNodeIsText(const xmlNode
*node
) {
7053 if (node
== NULL
) return(0);
7055 if (node
->type
== XML_TEXT_NODE
) return(1);
7063 * Checks whether this node is an empty or whitespace only
7064 * (and possibly ignorable) text-node.
7066 * Returns 1 yes, 0 no
7069 xmlIsBlankNode(const xmlNode
*node
) {
7071 if (node
== NULL
) return(0);
7073 if ((node
->type
!= XML_TEXT_NODE
) &&
7074 (node
->type
!= XML_CDATA_SECTION_NODE
))
7076 if (node
->content
== NULL
) return(1);
7077 cur
= node
->content
;
7079 if (!IS_BLANK_CH(*cur
)) return(0);
7089 * @content: the content
7090 * @len: @content length
7092 * Concat the given string at the end of the existing node content
7094 * Returns -1 in case of error, 0 otherwise
7098 xmlTextConcat(xmlNodePtr node
, const xmlChar
*content
, int len
) {
7099 if (node
== NULL
) return(-1);
7101 if ((node
->type
!= XML_TEXT_NODE
) &&
7102 (node
->type
!= XML_CDATA_SECTION_NODE
) &&
7103 (node
->type
!= XML_COMMENT_NODE
) &&
7104 (node
->type
!= XML_PI_NODE
)) {
7106 xmlGenericError(xmlGenericErrorContext
,
7107 "xmlTextConcat: node is not text nor CDATA\n");
7111 /* need to check if content is currently in the dictionary */
7112 if ((node
->content
== (xmlChar
*) &(node
->properties
)) ||
7113 ((node
->doc
!= NULL
) && (node
->doc
->dict
!= NULL
) &&
7114 xmlDictOwns(node
->doc
->dict
, node
->content
))) {
7115 node
->content
= xmlStrncatNew(node
->content
, content
, len
);
7117 node
->content
= xmlStrncat(node
->content
, content
, len
);
7119 node
->properties
= NULL
;
7120 if (node
->content
== NULL
)
7125 /************************************************************************
7127 * Output : to a FILE or in memory *
7129 ************************************************************************/
7134 * routine to create an XML buffer.
7135 * returns the new structure.
7138 xmlBufferCreate(void) {
7141 ret
= (xmlBufferPtr
) xmlMalloc(sizeof(xmlBuffer
));
7143 xmlTreeErrMemory("creating buffer");
7147 ret
->size
= xmlDefaultBufferSize
;
7148 ret
->alloc
= xmlBufferAllocScheme
;
7149 ret
->content
= (xmlChar
*) xmlMallocAtomic(ret
->size
* sizeof(xmlChar
));
7150 if (ret
->content
== NULL
) {
7151 xmlTreeErrMemory("creating buffer");
7155 ret
->content
[0] = 0;
7156 ret
->contentIO
= NULL
;
7161 * xmlBufferCreateSize:
7162 * @size: initial size of buffer
7164 * routine to create an XML buffer.
7165 * returns the new structure.
7168 xmlBufferCreateSize(size_t size
) {
7171 if (size
>= UINT_MAX
)
7173 ret
= (xmlBufferPtr
) xmlMalloc(sizeof(xmlBuffer
));
7175 xmlTreeErrMemory("creating buffer");
7179 ret
->alloc
= xmlBufferAllocScheme
;
7180 ret
->size
= (size
? size
+ 1 : 0); /* +1 for ending null */
7182 ret
->content
= (xmlChar
*) xmlMallocAtomic(ret
->size
* sizeof(xmlChar
));
7183 if (ret
->content
== NULL
) {
7184 xmlTreeErrMemory("creating buffer");
7188 ret
->content
[0] = 0;
7190 ret
->content
= NULL
;
7191 ret
->contentIO
= NULL
;
7199 * Remove the string contained in a buffer and gie it back to the
7200 * caller. The buffer is reset to an empty content.
7201 * This doesn't work with immutable buffers as they can't be reset.
7203 * Returns the previous string contained by the buffer.
7206 xmlBufferDetach(xmlBufferPtr buf
) {
7211 if (buf
->alloc
== XML_BUFFER_ALLOC_IMMUTABLE
)
7215 buf
->content
= NULL
;
7224 * xmlBufferCreateStatic:
7225 * @mem: the memory area
7226 * @size: the size in byte
7228 * routine to create an XML buffer from an immutable memory area.
7229 * The area won't be modified nor copied, and is expected to be
7230 * present until the end of the buffer lifetime.
7232 * returns the new structure.
7235 xmlBufferCreateStatic(void *mem
, size_t size
) {
7238 if ((mem
== NULL
) || (size
== 0))
7240 if (size
> UINT_MAX
)
7243 ret
= (xmlBufferPtr
) xmlMalloc(sizeof(xmlBuffer
));
7245 xmlTreeErrMemory("creating buffer");
7250 ret
->alloc
= XML_BUFFER_ALLOC_IMMUTABLE
;
7251 ret
->content
= (xmlChar
*) mem
;
7256 * xmlBufferSetAllocationScheme:
7257 * @buf: the buffer to tune
7258 * @scheme: allocation scheme to use
7260 * Sets the allocation scheme for this buffer
7263 xmlBufferSetAllocationScheme(xmlBufferPtr buf
,
7264 xmlBufferAllocationScheme scheme
) {
7267 xmlGenericError(xmlGenericErrorContext
,
7268 "xmlBufferSetAllocationScheme: buf == NULL\n");
7272 if ((buf
->alloc
== XML_BUFFER_ALLOC_IMMUTABLE
) ||
7273 (buf
->alloc
== XML_BUFFER_ALLOC_IO
)) return;
7274 if ((scheme
== XML_BUFFER_ALLOC_DOUBLEIT
) ||
7275 (scheme
== XML_BUFFER_ALLOC_EXACT
) ||
7276 (scheme
== XML_BUFFER_ALLOC_HYBRID
) ||
7277 (scheme
== XML_BUFFER_ALLOC_IMMUTABLE
))
7278 buf
->alloc
= scheme
;
7283 * @buf: the buffer to free
7285 * Frees an XML buffer. It frees both the content and the structure which
7289 xmlBufferFree(xmlBufferPtr buf
) {
7292 xmlGenericError(xmlGenericErrorContext
,
7293 "xmlBufferFree: buf == NULL\n");
7298 if ((buf
->alloc
== XML_BUFFER_ALLOC_IO
) &&
7299 (buf
->contentIO
!= NULL
)) {
7300 xmlFree(buf
->contentIO
);
7301 } else if ((buf
->content
!= NULL
) &&
7302 (buf
->alloc
!= XML_BUFFER_ALLOC_IMMUTABLE
)) {
7303 xmlFree(buf
->content
);
7315 xmlBufferEmpty(xmlBufferPtr buf
) {
7316 if (buf
== NULL
) return;
7317 if (buf
->content
== NULL
) return;
7319 if (buf
->alloc
== XML_BUFFER_ALLOC_IMMUTABLE
) {
7320 buf
->content
= BAD_CAST
"";
7321 } else if ((buf
->alloc
== XML_BUFFER_ALLOC_IO
) &&
7322 (buf
->contentIO
!= NULL
)) {
7323 size_t start_buf
= buf
->content
- buf
->contentIO
;
7325 buf
->size
+= start_buf
;
7326 buf
->content
= buf
->contentIO
;
7327 buf
->content
[0] = 0;
7329 buf
->content
[0] = 0;
7335 * @buf: the buffer to dump
7336 * @len: the number of xmlChar to remove
7338 * Remove the beginning of an XML buffer.
7340 * Returns the number of #xmlChar removed, or -1 in case of failure.
7343 xmlBufferShrink(xmlBufferPtr buf
, unsigned int len
) {
7344 if (buf
== NULL
) return(-1);
7345 if (len
== 0) return(0);
7346 if (len
> buf
->use
) return(-1);
7349 if ((buf
->alloc
== XML_BUFFER_ALLOC_IMMUTABLE
) ||
7350 ((buf
->alloc
== XML_BUFFER_ALLOC_IO
) && (buf
->contentIO
!= NULL
))) {
7352 * we just move the content pointer, but also make sure
7353 * the perceived buffer size has shrunk accordingly
7355 buf
->content
+= len
;
7359 * sometimes though it maybe be better to really shrink
7362 if ((buf
->alloc
== XML_BUFFER_ALLOC_IO
) && (buf
->contentIO
!= NULL
)) {
7363 size_t start_buf
= buf
->content
- buf
->contentIO
;
7364 if (start_buf
>= buf
->size
) {
7365 memmove(buf
->contentIO
, &buf
->content
[0], buf
->use
);
7366 buf
->content
= buf
->contentIO
;
7367 buf
->content
[buf
->use
] = 0;
7368 buf
->size
+= start_buf
;
7372 memmove(buf
->content
, &buf
->content
[len
], buf
->use
);
7373 buf
->content
[buf
->use
] = 0;
7381 * @len: the minimum free size to allocate
7383 * Grow the available space of an XML buffer.
7385 * Returns the new available space or -1 in case of error
7388 xmlBufferGrow(xmlBufferPtr buf
, unsigned int len
) {
7392 if (buf
== NULL
) return(-1);
7394 if (buf
->alloc
== XML_BUFFER_ALLOC_IMMUTABLE
) return(0);
7395 if (len
< buf
->size
- buf
->use
)
7397 if (len
>= UINT_MAX
- buf
->use
) {
7398 xmlTreeErrMemory("growing buffer past UINT_MAX");
7402 if (buf
->size
> (size_t) len
) {
7403 size
= buf
->size
> UINT_MAX
/ 2 ? UINT_MAX
: buf
->size
* 2;
7405 size
= buf
->use
+ len
;
7406 size
= size
> UINT_MAX
- 100 ? UINT_MAX
: size
+ 100;
7409 if ((buf
->alloc
== XML_BUFFER_ALLOC_IO
) && (buf
->contentIO
!= NULL
)) {
7410 size_t start_buf
= buf
->content
- buf
->contentIO
;
7412 newbuf
= (xmlChar
*) xmlRealloc(buf
->contentIO
, start_buf
+ size
);
7413 if (newbuf
== NULL
) {
7414 xmlTreeErrMemory("growing buffer");
7417 buf
->contentIO
= newbuf
;
7418 buf
->content
= newbuf
+ start_buf
;
7420 newbuf
= (xmlChar
*) xmlRealloc(buf
->content
, size
);
7421 if (newbuf
== NULL
) {
7422 xmlTreeErrMemory("growing buffer");
7425 buf
->content
= newbuf
;
7428 return(buf
->size
- buf
->use
- 1);
7433 * @file: the file output
7434 * @buf: the buffer to dump
7436 * Dumps an XML buffer to a FILE *.
7437 * Returns the number of #xmlChar written
7440 xmlBufferDump(FILE *file
, xmlBufferPtr buf
) {
7445 xmlGenericError(xmlGenericErrorContext
,
7446 "xmlBufferDump: buf == NULL\n");
7450 if (buf
->content
== NULL
) {
7452 xmlGenericError(xmlGenericErrorContext
,
7453 "xmlBufferDump: buf->content == NULL\n");
7459 ret
= fwrite(buf
->content
, sizeof(xmlChar
), buf
->use
, file
);
7460 return(ret
> INT_MAX
? INT_MAX
: (int)ret
);
7467 * Function to extract the content of a buffer
7469 * Returns the internal content
7473 xmlBufferContent(const xmlBuffer
*buf
)
7478 return buf
->content
;
7485 * Function to get the length of a buffer
7487 * Returns the length of data in the internal content
7491 xmlBufferLength(const xmlBuffer
*buf
)
7501 * @buf: the buffer to resize
7502 * @size: the desired size
7504 * Resize a buffer to accommodate minimum size of @size.
7506 * Returns 0 in case of problems, 1 otherwise
7509 xmlBufferResize(xmlBufferPtr buf
, unsigned int size
)
7511 unsigned int newSize
;
7512 xmlChar
* rebuf
= NULL
;
7518 if (buf
->alloc
== XML_BUFFER_ALLOC_IMMUTABLE
) return(0);
7520 /* Don't resize if we don't have to */
7521 if (size
< buf
->size
)
7524 if (size
> UINT_MAX
- 10) {
7525 xmlTreeErrMemory("growing buffer past UINT_MAX");
7529 /* figure out new size */
7530 switch (buf
->alloc
){
7531 case XML_BUFFER_ALLOC_IO
:
7532 case XML_BUFFER_ALLOC_DOUBLEIT
:
7533 /*take care of empty case*/
7535 newSize
= (size
> UINT_MAX
- 10 ? UINT_MAX
: size
+ 10);
7537 newSize
= buf
->size
;
7538 while (size
> newSize
) {
7539 if (newSize
> UINT_MAX
/ 2) {
7540 xmlTreeErrMemory("growing buffer");
7546 case XML_BUFFER_ALLOC_EXACT
:
7547 newSize
= (size
> UINT_MAX
- 10 ? UINT_MAX
: size
+ 10);
7549 case XML_BUFFER_ALLOC_HYBRID
:
7550 if (buf
->use
< BASE_BUFFER_SIZE
)
7553 newSize
= buf
->size
;
7554 while (size
> newSize
) {
7555 if (newSize
> UINT_MAX
/ 2) {
7556 xmlTreeErrMemory("growing buffer");
7565 newSize
= (size
> UINT_MAX
- 10 ? UINT_MAX
: size
+ 10);
7569 if ((buf
->alloc
== XML_BUFFER_ALLOC_IO
) && (buf
->contentIO
!= NULL
)) {
7570 start_buf
= buf
->content
- buf
->contentIO
;
7572 if (start_buf
> newSize
) {
7573 /* move data back to start */
7574 memmove(buf
->contentIO
, buf
->content
, buf
->use
);
7575 buf
->content
= buf
->contentIO
;
7576 buf
->content
[buf
->use
] = 0;
7577 buf
->size
+= start_buf
;
7579 rebuf
= (xmlChar
*) xmlRealloc(buf
->contentIO
, start_buf
+ newSize
);
7580 if (rebuf
== NULL
) {
7581 xmlTreeErrMemory("growing buffer");
7584 buf
->contentIO
= rebuf
;
7585 buf
->content
= rebuf
+ start_buf
;
7588 if (buf
->content
== NULL
) {
7589 rebuf
= (xmlChar
*) xmlMallocAtomic(newSize
);
7591 rebuf
[buf
->use
] = 0;
7592 } else if (buf
->size
- buf
->use
< 100) {
7593 rebuf
= (xmlChar
*) xmlRealloc(buf
->content
, newSize
);
7596 * if we are reallocating a buffer far from being full, it's
7597 * better to make a new allocation and copy only the used range
7598 * and free the old one.
7600 rebuf
= (xmlChar
*) xmlMallocAtomic(newSize
);
7601 if (rebuf
!= NULL
) {
7602 memcpy(rebuf
, buf
->content
, buf
->use
);
7603 xmlFree(buf
->content
);
7604 rebuf
[buf
->use
] = 0;
7607 if (rebuf
== NULL
) {
7608 xmlTreeErrMemory("growing buffer");
7611 buf
->content
= rebuf
;
7613 buf
->size
= newSize
;
7620 * @buf: the buffer to dump
7621 * @str: the #xmlChar string
7622 * @len: the number of #xmlChar to add
7624 * Add a string range to an XML buffer. if len == -1, the length of
7625 * str is recomputed.
7627 * Returns 0 successful, a positive error code number otherwise
7628 * and -1 in case of internal or API error.
7631 xmlBufferAdd(xmlBufferPtr buf
, const xmlChar
*str
, int len
) {
7632 unsigned int needSize
;
7634 if ((str
== NULL
) || (buf
== NULL
)) {
7637 if (buf
->alloc
== XML_BUFFER_ALLOC_IMMUTABLE
) return -1;
7640 xmlGenericError(xmlGenericErrorContext
,
7641 "xmlBufferAdd: len < 0\n");
7645 if (len
== 0) return 0;
7648 len
= xmlStrlen(str
);
7650 if (len
< 0) return -1;
7651 if (len
== 0) return 0;
7653 /* Note that both buf->size and buf->use can be zero here. */
7654 if ((unsigned) len
>= buf
->size
- buf
->use
) {
7655 if ((unsigned) len
>= UINT_MAX
- buf
->use
) {
7656 xmlTreeErrMemory("growing buffer past UINT_MAX");
7657 return XML_ERR_NO_MEMORY
;
7659 needSize
= buf
->use
+ len
+ 1;
7660 if (!xmlBufferResize(buf
, needSize
)){
7661 xmlTreeErrMemory("growing buffer");
7662 return XML_ERR_NO_MEMORY
;
7666 memmove(&buf
->content
[buf
->use
], str
, len
*sizeof(xmlChar
));
7668 buf
->content
[buf
->use
] = 0;
7675 * @str: the #xmlChar string
7676 * @len: the number of #xmlChar to add
7678 * Add a string range to the beginning of an XML buffer.
7679 * if len == -1, the length of @str is recomputed.
7681 * Returns 0 successful, a positive error code number otherwise
7682 * and -1 in case of internal or API error.
7685 xmlBufferAddHead(xmlBufferPtr buf
, const xmlChar
*str
, int len
) {
7686 unsigned int needSize
;
7690 if (buf
->alloc
== XML_BUFFER_ALLOC_IMMUTABLE
) return -1;
7693 xmlGenericError(xmlGenericErrorContext
,
7694 "xmlBufferAddHead: str == NULL\n");
7700 xmlGenericError(xmlGenericErrorContext
,
7701 "xmlBufferAddHead: len < 0\n");
7705 if (len
== 0) return 0;
7708 len
= xmlStrlen(str
);
7710 if (len
<= 0) return -1;
7712 if ((buf
->alloc
== XML_BUFFER_ALLOC_IO
) && (buf
->contentIO
!= NULL
)) {
7713 size_t start_buf
= buf
->content
- buf
->contentIO
;
7715 if (start_buf
> (unsigned int) len
) {
7717 * We can add it in the space previously shrunk
7719 buf
->content
-= len
;
7720 memmove(&buf
->content
[0], str
, len
);
7723 buf
->content
[buf
->use
] = 0;
7727 /* Note that both buf->size and buf->use can be zero here. */
7728 if ((unsigned) len
>= buf
->size
- buf
->use
) {
7729 if ((unsigned) len
>= UINT_MAX
- buf
->use
) {
7730 xmlTreeErrMemory("growing buffer past UINT_MAX");
7733 needSize
= buf
->use
+ len
+ 1;
7734 if (!xmlBufferResize(buf
, needSize
)){
7735 xmlTreeErrMemory("growing buffer");
7736 return XML_ERR_NO_MEMORY
;
7740 memmove(&buf
->content
[len
], &buf
->content
[0], buf
->use
);
7741 memmove(&buf
->content
[0], str
, len
);
7743 buf
->content
[buf
->use
] = 0;
7749 * @buf: the buffer to add to
7750 * @str: the #xmlChar string
7752 * Append a zero terminated string to an XML buffer.
7754 * Returns 0 successful, a positive error code number otherwise
7755 * and -1 in case of internal or API error.
7758 xmlBufferCat(xmlBufferPtr buf
, const xmlChar
*str
) {
7761 if (buf
->alloc
== XML_BUFFER_ALLOC_IMMUTABLE
) return -1;
7762 if (str
== NULL
) return -1;
7763 return xmlBufferAdd(buf
, str
, -1);
7768 * @buf: the buffer to dump
7769 * @str: the C char string
7771 * Append a zero terminated C string to an XML buffer.
7773 * Returns 0 successful, a positive error code number otherwise
7774 * and -1 in case of internal or API error.
7777 xmlBufferCCat(xmlBufferPtr buf
, const char *str
) {
7778 return xmlBufferCat(buf
, (const xmlChar
*) str
);
7782 * xmlBufferWriteCHAR:
7783 * @buf: the XML buffer
7784 * @string: the string to add
7786 * routine which manages and grows an output buffer. This one adds
7787 * xmlChars at the end of the buffer.
7790 xmlBufferWriteCHAR(xmlBufferPtr buf
, const xmlChar
*string
) {
7793 if (buf
->alloc
== XML_BUFFER_ALLOC_IMMUTABLE
) return;
7794 xmlBufferCat(buf
, string
);
7798 * xmlBufferWriteChar:
7799 * @buf: the XML buffer output
7800 * @string: the string to add
7802 * routine which manage and grows an output buffer. This one add
7803 * C chars at the end of the array.
7806 xmlBufferWriteChar(xmlBufferPtr buf
, const char *string
) {
7809 if (buf
->alloc
== XML_BUFFER_ALLOC_IMMUTABLE
) return;
7810 xmlBufferCCat(buf
, string
);
7815 * xmlBufferWriteQuotedString:
7816 * @buf: the XML buffer output
7817 * @string: the string to add
7819 * routine which manage and grows an output buffer. This one writes
7820 * a quoted or double quoted #xmlChar string, checking first if it holds
7821 * quote or double-quotes internally
7824 xmlBufferWriteQuotedString(xmlBufferPtr buf
, const xmlChar
*string
) {
7825 const xmlChar
*cur
, *base
;
7828 if (buf
->alloc
== XML_BUFFER_ALLOC_IMMUTABLE
) return;
7829 if (xmlStrchr(string
, '\"')) {
7830 if (xmlStrchr(string
, '\'')) {
7832 xmlGenericError(xmlGenericErrorContext
,
7833 "xmlBufferWriteQuotedString: string contains quote and double-quotes !\n");
7835 xmlBufferCCat(buf
, "\"");
7836 base
= cur
= string
;
7840 xmlBufferAdd(buf
, base
, cur
- base
);
7841 xmlBufferAdd(buf
, BAD_CAST
""", 6);
7850 xmlBufferAdd(buf
, base
, cur
- base
);
7851 xmlBufferCCat(buf
, "\"");
7854 xmlBufferCCat(buf
, "\'");
7855 xmlBufferCat(buf
, string
);
7856 xmlBufferCCat(buf
, "\'");
7859 xmlBufferCCat(buf
, "\"");
7860 xmlBufferCat(buf
, string
);
7861 xmlBufferCCat(buf
, "\"");
7867 * xmlGetDocCompressMode:
7868 * @doc: the document
7870 * get the compression ratio for a document, ZLIB based
7871 * Returns 0 (uncompressed) to 9 (max compression)
7874 xmlGetDocCompressMode (const xmlDoc
*doc
) {
7875 if (doc
== NULL
) return(-1);
7876 return(doc
->compression
);
7880 * xmlSetDocCompressMode:
7881 * @doc: the document
7882 * @mode: the compression ratio
7884 * set the compression ratio for a document, ZLIB based
7885 * Correct values: 0 (uncompressed) to 9 (max compression)
7888 xmlSetDocCompressMode (xmlDocPtr doc
, int mode
) {
7889 if (doc
== NULL
) return;
7890 if (mode
< 0) doc
->compression
= 0;
7891 else if (mode
> 9) doc
->compression
= 9;
7892 else doc
->compression
= mode
;
7896 * xmlGetCompressMode:
7898 * get the default compression mode used, ZLIB based.
7899 * Returns 0 (uncompressed) to 9 (max compression)
7902 xmlGetCompressMode(void)
7904 return (xmlCompressMode
);
7908 * xmlSetCompressMode:
7909 * @mode: the compression ratio
7911 * set the default compression mode used, ZLIB based
7912 * Correct values: 0 (uncompressed) to 9 (max compression)
7915 xmlSetCompressMode(int mode
) {
7916 if (mode
< 0) xmlCompressMode
= 0;
7917 else if (mode
> 9) xmlCompressMode
= 9;
7918 else xmlCompressMode
= mode
;
7921 #define XML_TREE_NSMAP_PARENT -1
7922 #define XML_TREE_NSMAP_XML -2
7923 #define XML_TREE_NSMAP_DOC -3
7924 #define XML_TREE_NSMAP_CUSTOM -4
7926 typedef struct xmlNsMapItem
*xmlNsMapItemPtr
;
7927 struct xmlNsMapItem
{
7928 xmlNsMapItemPtr next
;
7929 xmlNsMapItemPtr prev
;
7930 xmlNsPtr oldNs
; /* old ns decl reference */
7931 xmlNsPtr newNs
; /* new ns decl reference */
7932 int shadowDepth
; /* Shadowed at this depth */
7935 * >= 0 == @node's ns-decls
7936 * -1 == @parent's ns-decls
7937 * -2 == the doc->oldNs XML ns-decl
7938 * -3 == the doc->oldNs storage ns-decls
7939 * -4 == ns-decls provided via custom ns-handling
7944 typedef struct xmlNsMap
*xmlNsMapPtr
;
7946 xmlNsMapItemPtr first
;
7947 xmlNsMapItemPtr last
;
7948 xmlNsMapItemPtr pool
;
7951 #define XML_NSMAP_NOTEMPTY(m) (((m) != NULL) && ((m)->first != NULL))
7952 #define XML_NSMAP_FOREACH(m, i) for (i = (m)->first; i != NULL; i = (i)->next)
7953 #define XML_NSMAP_POP(m, i) \
7955 (m)->last = (i)->prev; \
7956 if ((m)->last == NULL) \
7957 (m)->first = NULL; \
7959 (m)->last->next = NULL; \
7960 (i)->next = (m)->pool; \
7964 * xmlDOMWrapNsMapFree:
7970 xmlDOMWrapNsMapFree(xmlNsMapPtr nsmap
)
7972 xmlNsMapItemPtr cur
, tmp
;
7977 while (cur
!= NULL
) {
7983 while (cur
!= NULL
) {
7992 * xmlDOMWrapNsMapAddItem:
7994 * @oldNs: the old ns-struct
7995 * @newNs: the new ns-struct
7996 * @depth: depth and ns-kind information
7998 * Adds an ns-mapping item.
8000 static xmlNsMapItemPtr
8001 xmlDOMWrapNsMapAddItem(xmlNsMapPtr
*nsmap
, int position
,
8002 xmlNsPtr oldNs
, xmlNsPtr newNs
, int depth
)
8004 xmlNsMapItemPtr ret
;
8009 if ((position
!= -1) && (position
!= 0))
8015 * Create the ns-map.
8017 map
= (xmlNsMapPtr
) xmlMalloc(sizeof(struct xmlNsMap
));
8019 xmlTreeErrMemory("allocating namespace map");
8022 memset(map
, 0, sizeof(struct xmlNsMap
));
8026 if (map
->pool
!= NULL
) {
8028 * Reuse an item from the pool.
8031 map
->pool
= ret
->next
;
8032 memset(ret
, 0, sizeof(struct xmlNsMapItem
));
8035 * Create a new item.
8037 ret
= (xmlNsMapItemPtr
) xmlMalloc(sizeof(struct xmlNsMapItem
));
8039 xmlTreeErrMemory("allocating namespace map item");
8042 memset(ret
, 0, sizeof(struct xmlNsMapItem
));
8045 if (map
->first
== NULL
) {
8051 } else if (position
== -1) {
8055 ret
->prev
= map
->last
;
8056 map
->last
->next
= ret
;
8058 } else if (position
== 0) {
8060 * Set on first position.
8062 map
->first
->prev
= ret
;
8063 ret
->next
= map
->first
;
8069 ret
->shadowDepth
= -1;
8075 * xmlDOMWrapStoreNs:
8077 * @nsName: the namespace name
8078 * @prefix: the prefix
8080 * Creates or reuses an xmlNs struct on doc->oldNs with
8081 * the given prefix and namespace name.
8083 * Returns the acquired ns struct or NULL in case of an API
8084 * or internal error.
8087 xmlDOMWrapStoreNs(xmlDocPtr doc
,
8088 const xmlChar
*nsName
,
8089 const xmlChar
*prefix
)
8095 ns
= xmlTreeEnsureXMLDecl(doc
);
8098 if (ns
->next
!= NULL
) {
8101 while (ns
!= NULL
) {
8102 if (((ns
->prefix
== prefix
) ||
8103 xmlStrEqual(ns
->prefix
, prefix
)) &&
8104 xmlStrEqual(ns
->href
, nsName
)) {
8107 if (ns
->next
== NULL
)
8114 ns
->next
= xmlNewNs(NULL
, nsName
, prefix
);
8121 * xmlDOMWrapNewCtxt:
8123 * Allocates and initializes a new DOM-wrapper context.
8125 * Returns the xmlDOMWrapCtxtPtr or NULL in case of an internal error.
8128 xmlDOMWrapNewCtxt(void)
8130 xmlDOMWrapCtxtPtr ret
;
8132 ret
= xmlMalloc(sizeof(xmlDOMWrapCtxt
));
8134 xmlTreeErrMemory("allocating DOM-wrapper context");
8137 memset(ret
, 0, sizeof(xmlDOMWrapCtxt
));
8142 * xmlDOMWrapFreeCtxt:
8143 * @ctxt: the DOM-wrapper context
8145 * Frees the DOM-wrapper context.
8148 xmlDOMWrapFreeCtxt(xmlDOMWrapCtxtPtr ctxt
)
8152 if (ctxt
->namespaceMap
!= NULL
)
8153 xmlDOMWrapNsMapFree((xmlNsMapPtr
) ctxt
->namespaceMap
);
8155 * TODO: Store the namespace map in the context.
8161 * xmlTreeLookupNsListByPrefix:
8162 * @nsList: a list of ns-structs
8163 * @prefix: the searched prefix
8165 * Searches for a ns-decl with the given prefix in @nsList.
8167 * Returns the ns-decl if found, NULL if not found and on
8171 xmlTreeNSListLookupByPrefix(xmlNsPtr nsList
, const xmlChar
*prefix
)
8179 if ((prefix
== ns
->prefix
) ||
8180 xmlStrEqual(prefix
, ns
->prefix
)) {
8184 } while (ns
!= NULL
);
8191 * xmlDOMWrapNSNormGatherInScopeNs:
8192 * @map: the namespace map
8193 * @node: the node to start with
8195 * Puts in-scope namespaces into the ns-map.
8197 * Returns 0 on success, -1 on API or internal errors.
8200 xmlDOMWrapNSNormGatherInScopeNs(xmlNsMapPtr
*map
,
8208 if ((map
== NULL
) || (*map
!= NULL
))
8210 if ((node
== NULL
) || (node
->type
== XML_NAMESPACE_DECL
))
8213 * Get in-scope ns-decls of @parent.
8216 while ((cur
!= NULL
) && (cur
!= (xmlNodePtr
) cur
->doc
)) {
8217 if (cur
->type
== XML_ELEMENT_NODE
) {
8218 if (cur
->nsDef
!= NULL
) {
8222 if (XML_NSMAP_NOTEMPTY(*map
)) {
8224 * Skip shadowed prefixes.
8226 XML_NSMAP_FOREACH(*map
, mi
) {
8227 if ((ns
->prefix
== mi
->newNs
->prefix
) ||
8228 xmlStrEqual(ns
->prefix
, mi
->newNs
->prefix
)) {
8237 mi
= xmlDOMWrapNsMapAddItem(map
, 0, NULL
,
8238 ns
, XML_TREE_NSMAP_PARENT
);
8242 mi
->shadowDepth
= 0;
8244 } while (ns
!= NULL
);
8253 * XML_TREE_ADOPT_STR: If we have a dest-dict, put @str in the dict;
8254 * otherwise copy it, when it was in the source-dict.
8256 #define XML_TREE_ADOPT_STR(str) \
8257 if (adoptStr && (str != NULL)) { \
8258 if (destDoc->dict) { \
8259 const xmlChar *old = str; \
8260 str = xmlDictLookup(destDoc->dict, str, -1); \
8261 if ((sourceDoc == NULL) || (sourceDoc->dict == NULL) || \
8262 (!xmlDictOwns(sourceDoc->dict, old))) \
8263 xmlFree((char *)old); \
8264 } else if ((sourceDoc) && (sourceDoc->dict) && \
8265 xmlDictOwns(sourceDoc->dict, str)) { \
8266 str = BAD_CAST xmlStrdup(str); \
8271 * XML_TREE_ADOPT_STR_2: If @str was in the source-dict, then
8272 * put it in dest-dict or copy it.
8274 #define XML_TREE_ADOPT_STR_2(str) \
8275 if (adoptStr && (str != NULL) && (sourceDoc != NULL) && \
8276 (sourceDoc->dict != NULL) && \
8277 xmlDictOwns(sourceDoc->dict, cur->content)) { \
8278 if (destDoc->dict) \
8279 cur->content = (xmlChar *) \
8280 xmlDictLookup(destDoc->dict, cur->content, -1); \
8282 cur->content = xmlStrdup(BAD_CAST cur->content); \
8286 * xmlDOMWrapNSNormAddNsMapItem2:
8288 * For internal use. Adds a ns-decl mapping.
8290 * Returns 0 on success, -1 on internal errors.
8293 xmlDOMWrapNSNormAddNsMapItem2(xmlNsPtr
**list
, int *size
, int *number
,
8294 xmlNsPtr oldNs
, xmlNsPtr newNs
)
8296 if (*list
== NULL
) {
8297 *list
= (xmlNsPtr
*) xmlMalloc(6 * sizeof(xmlNsPtr
));
8298 if (*list
== NULL
) {
8299 xmlTreeErrMemory("alloc ns map item");
8304 } else if ((*number
) >= (*size
)) {
8306 *list
= (xmlNsPtr
*) xmlRealloc(*list
,
8307 (*size
) * 2 * sizeof(xmlNsPtr
));
8308 if (*list
== NULL
) {
8309 xmlTreeErrMemory("realloc ns map item");
8313 (*list
)[2 * (*number
)] = oldNs
;
8314 (*list
)[2 * (*number
) +1] = newNs
;
8320 * xmlDOMWrapRemoveNode:
8321 * @ctxt: a DOM wrapper context
8323 * @node: the node to be removed.
8324 * @options: set of options, unused at the moment
8326 * Unlinks the given node from its owner.
8327 * This will substitute ns-references to node->nsDef for
8328 * ns-references to doc->oldNs, thus ensuring the removed
8329 * branch to be autark wrt ns-references.
8331 * NOTE: This function was not intensively tested.
8333 * Returns 0 on success, 1 if the node is not supported,
8334 * -1 on API and internal errors.
8337 xmlDOMWrapRemoveNode(xmlDOMWrapCtxtPtr ctxt
, xmlDocPtr doc
,
8338 xmlNodePtr node
, int options ATTRIBUTE_UNUSED
)
8340 xmlNsPtr
*list
= NULL
;
8341 int sizeList
, nbList
, i
, j
;
8344 if ((node
== NULL
) || (doc
== NULL
) || (node
->doc
!= doc
))
8347 /* TODO: 0 or -1 ? */
8348 if (node
->parent
== NULL
)
8351 switch (node
->type
) {
8353 case XML_CDATA_SECTION_NODE
:
8354 case XML_ENTITY_REF_NODE
:
8356 case XML_COMMENT_NODE
:
8357 xmlUnlinkNode(node
);
8359 case XML_ELEMENT_NODE
:
8360 case XML_ATTRIBUTE_NODE
:
8365 xmlUnlinkNode(node
);
8367 * Save out-of-scope ns-references in doc->oldNs.
8370 switch (node
->type
) {
8371 case XML_ELEMENT_NODE
:
8372 if ((ctxt
== NULL
) && (node
->nsDef
!= NULL
)) {
8375 if (xmlDOMWrapNSNormAddNsMapItem2(&list
, &sizeList
,
8376 &nbList
, ns
, ns
) == -1)
8377 goto internal_error
;
8379 } while (ns
!= NULL
);
8381 /* Falls through. */
8382 case XML_ATTRIBUTE_NODE
:
8383 if (node
->ns
!= NULL
) {
8388 for (i
= 0, j
= 0; i
< nbList
; i
++, j
+= 2) {
8389 if (node
->ns
== list
[j
]) {
8390 node
->ns
= list
[++j
];
8402 * Add to doc's oldNs.
8404 ns
= xmlDOMWrapStoreNs(doc
, node
->ns
->href
,
8407 goto internal_error
;
8413 if (xmlDOMWrapNSNormAddNsMapItem2(&list
, &sizeList
,
8414 &nbList
, node
->ns
, ns
) == -1)
8415 goto internal_error
;
8419 if ((node
->type
== XML_ELEMENT_NODE
) &&
8420 (node
->properties
!= NULL
)) {
8421 node
= (xmlNodePtr
) node
->properties
;
8429 if ((node
->type
== XML_ELEMENT_NODE
) &&
8430 (node
->children
!= NULL
)) {
8431 node
= node
->children
;
8437 if (node
->next
!= NULL
)
8440 node
= node
->parent
;
8443 } while (node
!= NULL
);
8456 * xmlSearchNsByNamespaceStrict:
8457 * @doc: the document
8458 * @node: the start node
8459 * @nsName: the searched namespace name
8460 * @retNs: the resulting ns-decl
8461 * @prefixed: if the found ns-decl must have a prefix (for attributes)
8463 * Dynamically searches for a ns-declaration which matches
8464 * the given @nsName in the ancestor-or-self axis of @node.
8466 * Returns 1 if a ns-decl was found, 0 if not and -1 on API
8467 * and internal errors.
8470 xmlSearchNsByNamespaceStrict(xmlDocPtr doc
, xmlNodePtr node
,
8471 const xmlChar
* nsName
,
8472 xmlNsPtr
*retNs
, int prefixed
)
8474 xmlNodePtr cur
, prev
= NULL
, out
= NULL
;
8475 xmlNsPtr ns
, prevns
;
8477 if ((doc
== NULL
) || (nsName
== NULL
) || (retNs
== NULL
))
8479 if ((node
== NULL
) || (node
->type
== XML_NAMESPACE_DECL
))
8483 if (xmlStrEqual(nsName
, XML_XML_NAMESPACE
)) {
8484 *retNs
= xmlTreeEnsureXMLDecl(doc
);
8491 if (cur
->type
== XML_ELEMENT_NODE
) {
8492 if (cur
->nsDef
!= NULL
) {
8493 for (ns
= cur
->nsDef
; ns
!= NULL
; ns
= ns
->next
) {
8494 if (prefixed
&& (ns
->prefix
== NULL
))
8498 * Check the last level of ns-decls for a
8501 prevns
= prev
->nsDef
;
8503 if ((prevns
->prefix
== ns
->prefix
) ||
8504 ((prevns
->prefix
!= NULL
) &&
8505 (ns
->prefix
!= NULL
) &&
8506 xmlStrEqual(prevns
->prefix
, ns
->prefix
))) {
8512 prevns
= prevns
->next
;
8513 } while (prevns
!= NULL
);
8518 * Ns-name comparison.
8520 if ((nsName
== ns
->href
) ||
8521 xmlStrEqual(nsName
, ns
->href
)) {
8523 * At this point the prefix can only be shadowed,
8524 * if we are the the (at least) 3rd level of
8530 ret
= xmlNsInScope(doc
, node
, prev
, ns
->prefix
);
8534 * TODO: Should we try to find a matching ns-name
8535 * only once? This here keeps on searching.
8536 * I think we should try further since, there might
8537 * be an other matching ns-decl with an unshadowed
8550 } else if ((cur
->type
== XML_ENTITY_NODE
) ||
8551 (cur
->type
== XML_ENTITY_DECL
))
8554 } while ((cur
!= NULL
) && (cur
->doc
!= (xmlDocPtr
) cur
));
8559 * xmlSearchNsByPrefixStrict:
8560 * @doc: the document
8561 * @node: the start node
8562 * @prefix: the searched namespace prefix
8563 * @retNs: the resulting ns-decl
8565 * Dynamically searches for a ns-declaration which matches
8566 * the given @nsName in the ancestor-or-self axis of @node.
8568 * Returns 1 if a ns-decl was found, 0 if not and -1 on API
8569 * and internal errors.
8572 xmlSearchNsByPrefixStrict(xmlDocPtr doc
, xmlNodePtr node
,
8573 const xmlChar
* prefix
,
8579 if ((doc
== NULL
) || (node
== NULL
) || (node
->type
== XML_NAMESPACE_DECL
))
8584 if (IS_STR_XML(prefix
)) {
8586 *retNs
= xmlTreeEnsureXMLDecl(doc
);
8594 if (cur
->type
== XML_ELEMENT_NODE
) {
8595 if (cur
->nsDef
!= NULL
) {
8598 if ((prefix
== ns
->prefix
) ||
8599 xmlStrEqual(prefix
, ns
->prefix
))
8602 * Disabled namespaces, e.g. xmlns:abc="".
8604 if (ns
->href
== NULL
)
8611 } while (ns
!= NULL
);
8613 } else if ((cur
->type
== XML_ENTITY_NODE
) ||
8614 (cur
->type
== XML_ENTITY_DECL
))
8617 } while ((cur
!= NULL
) && (cur
->doc
!= (xmlDocPtr
) cur
));
8622 * xmlDOMWrapNSNormDeclareNsForced:
8624 * @elem: the element-node to declare on
8625 * @nsName: the namespace-name of the ns-decl
8626 * @prefix: the preferred prefix of the ns-decl
8627 * @checkShadow: ensure that the new ns-decl doesn't shadow ancestor ns-decls
8629 * Declares a new namespace on @elem. It tries to use the
8630 * given @prefix; if a ns-decl with the given prefix is already existent
8631 * on @elem, it will generate an other prefix.
8633 * Returns 1 if a ns-decl was found, 0 if not and -1 on API
8634 * and internal errors.
8637 xmlDOMWrapNSNormDeclareNsForced(xmlDocPtr doc
,
8639 const xmlChar
*nsName
,
8640 const xmlChar
*prefix
,
8646 const xmlChar
*pref
;
8649 if ((doc
== NULL
) || (elem
== NULL
) || (elem
->type
!= XML_ELEMENT_NODE
))
8652 * Create a ns-decl on @anchor.
8657 * Lookup whether the prefix is unused in elem's ns-decls.
8659 if ((elem
->nsDef
!= NULL
) &&
8660 (xmlTreeNSListLookupByPrefix(elem
->nsDef
, pref
) != NULL
))
8661 goto ns_next_prefix
;
8662 if (checkShadow
&& elem
->parent
&&
8663 ((xmlNodePtr
) elem
->parent
->doc
!= elem
->parent
)) {
8665 * Does it shadow ancestor ns-decls?
8667 if (xmlSearchNsByPrefixStrict(doc
, elem
->parent
, pref
, NULL
) == 1)
8668 goto ns_next_prefix
;
8670 ret
= xmlNewNs(NULL
, nsName
, pref
);
8673 if (elem
->nsDef
== NULL
)
8676 xmlNsPtr ns2
= elem
->nsDef
;
8677 while (ns2
->next
!= NULL
)
8686 if (prefix
== NULL
) {
8687 snprintf((char *) buf
, sizeof(buf
),
8690 snprintf((char *) buf
, sizeof(buf
),
8691 "%.30s_%d", (char *)prefix
, counter
);
8692 pref
= BAD_CAST buf
;
8697 * xmlDOMWrapNSNormAcquireNormalizedNs:
8699 * @elem: the element-node to declare namespaces on
8700 * @ns: the ns-struct to use for the search
8701 * @retNs: the found/created ns-struct
8702 * @nsMap: the ns-map
8703 * @depth: the current tree depth
8704 * @ancestorsOnly: search in ancestor ns-decls only
8705 * @prefixed: if the searched ns-decl must have a prefix (for attributes)
8707 * Searches for a matching ns-name in the ns-decls of @nsMap, if not
8708 * found it will either declare it on @elem, or store it in doc->oldNs.
8709 * If a new ns-decl needs to be declared on @elem, it tries to use the
8710 * @ns->prefix for it, if this prefix is already in use on @elem, it will
8711 * change the prefix or the new ns-decl.
8713 * Returns 0 if succeeded, -1 otherwise and on API/internal errors.
8716 xmlDOMWrapNSNormAcquireNormalizedNs(xmlDocPtr doc
,
8728 if ((doc
== NULL
) || (ns
== NULL
) || (retNs
== NULL
) ||
8734 * Handle XML namespace.
8736 if (IS_STR_XML(ns
->prefix
)) {
8738 * Insert XML namespace mapping.
8740 *retNs
= xmlTreeEnsureXMLDecl(doc
);
8746 * If the search should be done in ancestors only and no
8747 * @elem (the first ancestor) was specified, then skip the search.
8749 if ((XML_NSMAP_NOTEMPTY(*nsMap
)) &&
8750 (! (ancestorsOnly
&& (elem
== NULL
))))
8753 * Try to find an equal ns-name in in-scope ns-decls.
8755 XML_NSMAP_FOREACH(*nsMap
, mi
) {
8756 if ((mi
->depth
>= XML_TREE_NSMAP_PARENT
) &&
8758 * ancestorsOnly: This should be turned on to gain speed,
8759 * if one knows that the branch itself was already
8760 * ns-wellformed and no stale references existed.
8761 * I.e. it searches in the ancestor axis only.
8763 ((! ancestorsOnly
) || (mi
->depth
== XML_TREE_NSMAP_PARENT
)) &&
8764 /* Skip shadowed prefixes. */
8765 (mi
->shadowDepth
== -1) &&
8766 /* Skip xmlns="" or xmlns:foo="". */
8767 ((mi
->newNs
->href
!= NULL
) &&
8768 (mi
->newNs
->href
[0] != 0)) &&
8769 /* Ensure a prefix if wanted. */
8770 ((! prefixed
) || (mi
->newNs
->prefix
!= NULL
)) &&
8772 ((mi
->newNs
->href
== ns
->href
) ||
8773 xmlStrEqual(mi
->newNs
->href
, ns
->href
))) {
8774 /* Set the mapping. */
8782 * No luck, the namespace is out of scope or shadowed.
8788 * Store ns-decls in "oldNs" of the document-node.
8790 tmpns
= xmlDOMWrapStoreNs(doc
, ns
->href
, ns
->prefix
);
8796 if (xmlDOMWrapNsMapAddItem(nsMap
, -1, ns
,
8797 tmpns
, XML_TREE_NSMAP_DOC
) == NULL
) {
8805 tmpns
= xmlDOMWrapNSNormDeclareNsForced(doc
, elem
, ns
->href
,
8810 if (*nsMap
!= NULL
) {
8812 * Does it shadow ancestor ns-decls?
8814 XML_NSMAP_FOREACH(*nsMap
, mi
) {
8815 if ((mi
->depth
< depth
) &&
8816 (mi
->shadowDepth
== -1) &&
8817 ((ns
->prefix
== mi
->newNs
->prefix
) ||
8818 xmlStrEqual(ns
->prefix
, mi
->newNs
->prefix
))) {
8822 mi
->shadowDepth
= depth
;
8827 if (xmlDOMWrapNsMapAddItem(nsMap
, -1, ns
, tmpns
, depth
) == NULL
) {
8837 XML_DOM_RECONNS_REMOVEREDUND
= 1<<0
8838 } xmlDOMReconcileNSOptions
;
8841 * xmlDOMWrapReconcileNamespaces:
8842 * @ctxt: DOM wrapper context, unused at the moment
8843 * @elem: the element-node
8844 * @options: option flags
8846 * Ensures that ns-references point to ns-decls hold on element-nodes.
8847 * Ensures that the tree is namespace wellformed by creating additional
8848 * ns-decls where needed. Note that, since prefixes of already existent
8849 * ns-decls can be shadowed by this process, it could break QNames in
8850 * attribute values or element content.
8852 * NOTE: This function was not intensively tested.
8854 * Returns 0 if succeeded, -1 otherwise and on API/internal errors.
8858 xmlDOMWrapReconcileNamespaces(xmlDOMWrapCtxtPtr ctxt ATTRIBUTE_UNUSED
,
8862 int depth
= -1, adoptns
= 0, parnsdone
= 0;
8863 xmlNsPtr ns
, prevns
;
8865 xmlNodePtr cur
, curElem
= NULL
;
8866 xmlNsMapPtr nsMap
= NULL
;
8867 xmlNsMapItemPtr
/* topmi = NULL, */ mi
;
8868 /* @ancestorsOnly should be set by an option flag. */
8869 int ancestorsOnly
= 0;
8870 int optRemoveRedundantNS
=
8871 ((xmlDOMReconcileNSOptions
) options
& XML_DOM_RECONNS_REMOVEREDUND
) ? 1 : 0;
8872 xmlNsPtr
*listRedund
= NULL
;
8873 int sizeRedund
= 0, nbRedund
= 0, ret
, i
, j
;
8875 if ((elem
== NULL
) || (elem
->doc
== NULL
) ||
8876 (elem
->type
!= XML_ELEMENT_NODE
))
8882 switch (cur
->type
) {
8883 case XML_ELEMENT_NODE
:
8888 * Namespace declarations.
8890 if (cur
->nsDef
!= NULL
) {
8893 while (ns
!= NULL
) {
8895 if ((elem
->parent
) &&
8896 ((xmlNodePtr
) elem
->parent
->doc
!= elem
->parent
)) {
8898 * Gather ancestor in-scope ns-decls.
8900 if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap
,
8901 elem
->parent
) == -1)
8902 goto internal_error
;
8908 * Lookup the ns ancestor-axis for equal ns-decls in scope.
8910 if (optRemoveRedundantNS
&& XML_NSMAP_NOTEMPTY(nsMap
)) {
8911 XML_NSMAP_FOREACH(nsMap
, mi
) {
8912 if ((mi
->depth
>= XML_TREE_NSMAP_PARENT
) &&
8913 (mi
->shadowDepth
== -1) &&
8914 ((ns
->prefix
== mi
->newNs
->prefix
) ||
8915 xmlStrEqual(ns
->prefix
, mi
->newNs
->prefix
)) &&
8916 ((ns
->href
== mi
->newNs
->href
) ||
8917 xmlStrEqual(ns
->href
, mi
->newNs
->href
)))
8920 * A redundant ns-decl was found.
8921 * Add it to the list of redundant ns-decls.
8923 if (xmlDOMWrapNSNormAddNsMapItem2(&listRedund
,
8924 &sizeRedund
, &nbRedund
, ns
, mi
->newNs
) == -1)
8925 goto internal_error
;
8927 * Remove the ns-decl from the element-node.
8930 prevns
->next
= ns
->next
;
8932 cur
->nsDef
= ns
->next
;
8939 * Skip ns-references handling if the referenced
8940 * ns-decl is declared on the same element.
8942 if ((cur
->ns
!= NULL
) && adoptns
&& (cur
->ns
== ns
))
8945 * Does it shadow any ns-decl?
8947 if (XML_NSMAP_NOTEMPTY(nsMap
)) {
8948 XML_NSMAP_FOREACH(nsMap
, mi
) {
8949 if ((mi
->depth
>= XML_TREE_NSMAP_PARENT
) &&
8950 (mi
->shadowDepth
== -1) &&
8951 ((ns
->prefix
== mi
->newNs
->prefix
) ||
8952 xmlStrEqual(ns
->prefix
, mi
->newNs
->prefix
))) {
8954 mi
->shadowDepth
= depth
;
8961 if (xmlDOMWrapNsMapAddItem(&nsMap
, -1, ns
, ns
,
8963 goto internal_error
;
8972 /* Falls through. */
8973 case XML_ATTRIBUTE_NODE
:
8974 /* No ns, no fun. */
8975 if (cur
->ns
== NULL
)
8979 if ((elem
->parent
) &&
8980 ((xmlNodePtr
) elem
->parent
->doc
!= elem
->parent
)) {
8981 if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap
,
8982 elem
->parent
) == -1)
8983 goto internal_error
;
8988 * Adjust the reference if this was a redundant ns-decl.
8991 for (i
= 0, j
= 0; i
< nbRedund
; i
++, j
+= 2) {
8992 if (cur
->ns
== listRedund
[j
]) {
8993 cur
->ns
= listRedund
[++j
];
8999 * Adopt ns-references.
9001 if (XML_NSMAP_NOTEMPTY(nsMap
)) {
9003 * Search for a mapping.
9005 XML_NSMAP_FOREACH(nsMap
, mi
) {
9006 if ((mi
->shadowDepth
== -1) &&
9007 (cur
->ns
== mi
->oldNs
)) {
9009 cur
->ns
= mi
->newNs
;
9015 * Acquire a normalized ns-decl and add it to the map.
9017 if (xmlDOMWrapNSNormAcquireNormalizedNs(doc
, curElem
,
9021 (cur
->type
== XML_ATTRIBUTE_NODE
) ? 1 : 0) == -1)
9022 goto internal_error
;
9026 if ((cur
->type
== XML_ELEMENT_NODE
) &&
9027 (cur
->properties
!= NULL
)) {
9029 * Process attributes.
9031 cur
= (xmlNodePtr
) cur
->properties
;
9039 if ((cur
->type
== XML_ELEMENT_NODE
) &&
9040 (cur
->children
!= NULL
)) {
9042 * Process content of element-nodes only.
9044 cur
= cur
->children
;
9050 if (cur
->type
== XML_ELEMENT_NODE
) {
9051 if (XML_NSMAP_NOTEMPTY(nsMap
)) {
9055 while ((nsMap
->last
!= NULL
) &&
9056 (nsMap
->last
->depth
>= depth
))
9058 XML_NSMAP_POP(nsMap
, mi
)
9063 XML_NSMAP_FOREACH(nsMap
, mi
) {
9064 if (mi
->shadowDepth
>= depth
)
9065 mi
->shadowDepth
= -1;
9070 if (cur
->next
!= NULL
)
9073 if (cur
->type
== XML_ATTRIBUTE_NODE
) {
9080 } while (cur
!= NULL
);
9088 for (i
= 0, j
= 0; i
< nbRedund
; i
++, j
+= 2) {
9089 xmlFreeNs(listRedund
[j
]);
9091 xmlFree(listRedund
);
9094 xmlDOMWrapNsMapFree(nsMap
);
9099 * xmlDOMWrapAdoptBranch:
9100 * @ctxt: the optional context for custom processing
9101 * @sourceDoc: the optional sourceDoc
9102 * @node: the element-node to start with
9103 * @destDoc: the destination doc for adoption
9104 * @destParent: the optional new parent of @node in @destDoc
9105 * @options: option flags
9107 * Ensures that ns-references point to @destDoc: either to
9108 * elements->nsDef entries if @destParent is given, or to
9109 * @destDoc->oldNs otherwise.
9110 * If @destParent is given, it ensures that the tree is namespace
9111 * wellformed by creating additional ns-decls where needed.
9112 * Note that, since prefixes of already existent ns-decls can be
9113 * shadowed by this process, it could break QNames in attribute
9114 * values or element content.
9116 * NOTE: This function was not intensively tested.
9118 * Returns 0 if succeeded, -1 otherwise and on API/internal errors.
9121 xmlDOMWrapAdoptBranch(xmlDOMWrapCtxtPtr ctxt
,
9122 xmlDocPtr sourceDoc
,
9125 xmlNodePtr destParent
,
9126 int options ATTRIBUTE_UNUSED
)
9129 xmlNodePtr cur
, curElem
= NULL
;
9130 xmlNsMapPtr nsMap
= NULL
;
9133 int depth
= -1, adoptStr
= 1;
9134 /* gather @parent's ns-decls. */
9136 /* @ancestorsOnly should be set per option. */
9137 int ancestorsOnly
= 0;
9140 * Optimize string adoption for equal or none dicts.
9142 if ((sourceDoc
!= NULL
) &&
9143 (sourceDoc
->dict
== destDoc
->dict
))
9149 * Get the ns-map from the context if available.
9152 nsMap
= (xmlNsMapPtr
) ctxt
->namespaceMap
;
9154 * Disable search for ns-decls in the parent-axis of the
9155 * destination element, if:
9156 * 1) there's no destination parent
9157 * 2) custom ns-reference handling is used
9159 if ((destParent
== NULL
) ||
9160 (ctxt
&& ctxt
->getNsForNodeFunc
))
9167 if ((cur
!= NULL
) && (cur
->type
== XML_NAMESPACE_DECL
))
9168 goto internal_error
;
9170 while (cur
!= NULL
) {
9172 * Paranoid source-doc sanity check.
9174 if (cur
->doc
!= sourceDoc
) {
9176 * We'll assume XIncluded nodes if the doc differs.
9177 * TODO: Do we need to reconciliate XIncluded nodes?
9178 * This here skips XIncluded nodes and tries to handle
9181 if (cur
->next
== NULL
)
9185 if ((cur
->type
== XML_XINCLUDE_END
) ||
9186 (cur
->doc
== node
->doc
))
9188 } while (cur
->next
!= NULL
);
9190 if (cur
->doc
!= node
->doc
)
9194 switch (cur
->type
) {
9195 case XML_XINCLUDE_START
:
9196 case XML_XINCLUDE_END
:
9201 case XML_ELEMENT_NODE
:
9205 * Namespace declarations.
9206 * - ns->href and ns->prefix are never in the dict, so
9207 * we need not move the values over to the destination dict.
9208 * - Note that for custom handling of ns-references,
9209 * the ns-decls need not be stored in the ns-map,
9210 * since they won't be referenced by node->ns.
9213 ((ctxt
== NULL
) || (ctxt
->getNsForNodeFunc
== NULL
)))
9217 * Gather @parent's in-scope ns-decls.
9219 if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap
,
9221 goto internal_error
;
9224 for (ns
= cur
->nsDef
; ns
!= NULL
; ns
= ns
->next
) {
9226 * NOTE: ns->prefix and ns->href are never in the dict.
9227 * XML_TREE_ADOPT_STR(ns->prefix)
9228 * XML_TREE_ADOPT_STR(ns->href)
9231 * Does it shadow any ns-decl?
9233 if (XML_NSMAP_NOTEMPTY(nsMap
)) {
9234 XML_NSMAP_FOREACH(nsMap
, mi
) {
9235 if ((mi
->depth
>= XML_TREE_NSMAP_PARENT
) &&
9236 (mi
->shadowDepth
== -1) &&
9237 ((ns
->prefix
== mi
->newNs
->prefix
) ||
9238 xmlStrEqual(ns
->prefix
,
9239 mi
->newNs
->prefix
))) {
9241 mi
->shadowDepth
= depth
;
9248 if (xmlDOMWrapNsMapAddItem(&nsMap
, -1,
9249 ns
, ns
, depth
) == NULL
)
9250 goto internal_error
;
9253 /* Falls through. */
9254 case XML_ATTRIBUTE_NODE
:
9255 /* No namespace, no fun. */
9256 if (cur
->ns
== NULL
)
9260 if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap
,
9262 goto internal_error
;
9266 * Adopt ns-references.
9268 if (XML_NSMAP_NOTEMPTY(nsMap
)) {
9270 * Search for a mapping.
9272 XML_NSMAP_FOREACH(nsMap
, mi
) {
9273 if ((mi
->shadowDepth
== -1) &&
9274 (cur
->ns
== mi
->oldNs
)) {
9276 cur
->ns
= mi
->newNs
;
9282 * No matching namespace in scope. We need a new one.
9284 if ((ctxt
) && (ctxt
->getNsForNodeFunc
)) {
9286 * User-defined behaviour.
9288 ns
= ctxt
->getNsForNodeFunc(ctxt
, cur
,
9289 cur
->ns
->href
, cur
->ns
->prefix
);
9291 * Insert mapping if ns is available; it's the users fault
9294 if (xmlDOMWrapNsMapAddItem(&nsMap
, -1,
9295 cur
->ns
, ns
, XML_TREE_NSMAP_CUSTOM
) == NULL
)
9296 goto internal_error
;
9300 * Acquire a normalized ns-decl and add it to the map.
9302 if (xmlDOMWrapNSNormAcquireNormalizedNs(destDoc
,
9303 /* ns-decls on curElem or on destDoc->oldNs */
9304 destParent
? curElem
: NULL
,
9308 /* ns-decls must be prefixed for attributes. */
9309 (cur
->type
== XML_ATTRIBUTE_NODE
) ? 1 : 0) == -1)
9310 goto internal_error
;
9315 * Further node properties.
9316 * TODO: Is this all?
9318 XML_TREE_ADOPT_STR(cur
->name
)
9319 if (cur
->type
== XML_ELEMENT_NODE
) {
9326 if (cur
->properties
!= NULL
) {
9328 * Process first attribute node.
9330 cur
= (xmlNodePtr
) cur
->properties
;
9337 if ((sourceDoc
!= NULL
) &&
9338 (((xmlAttrPtr
) cur
)->atype
== XML_ATTRIBUTE_ID
))
9340 xmlRemoveID(sourceDoc
, (xmlAttrPtr
) cur
);
9342 ((xmlAttrPtr
) cur
)->atype
= 0;
9343 ((xmlAttrPtr
) cur
)->psvi
= NULL
;
9347 case XML_CDATA_SECTION_NODE
:
9349 * This puts the content in the dest dict, only if
9350 * it was previously in the source dict.
9352 XML_TREE_ADOPT_STR_2(cur
->content
)
9354 case XML_ENTITY_REF_NODE
:
9356 * Remove reference to the entity-node.
9358 cur
->content
= NULL
;
9359 cur
->children
= NULL
;
9361 if ((destDoc
->intSubset
) || (destDoc
->extSubset
)) {
9364 * Assign new entity-node if available.
9366 ent
= xmlGetDocEntity(destDoc
, cur
->name
);
9368 cur
->content
= ent
->content
;
9369 cur
->children
= (xmlNodePtr
) ent
;
9370 cur
->last
= (xmlNodePtr
) ent
;
9375 XML_TREE_ADOPT_STR(cur
->name
)
9376 XML_TREE_ADOPT_STR_2(cur
->content
)
9378 case XML_COMMENT_NODE
:
9381 goto internal_error
;
9386 if (cur
->children
!= NULL
) {
9387 cur
= cur
->children
;
9394 if ((cur
->type
== XML_ELEMENT_NODE
) ||
9395 (cur
->type
== XML_XINCLUDE_START
) ||
9396 (cur
->type
== XML_XINCLUDE_END
))
9399 * TODO: Do we expect nsDefs on XML_XINCLUDE_START?
9401 if (XML_NSMAP_NOTEMPTY(nsMap
)) {
9405 while ((nsMap
->last
!= NULL
) &&
9406 (nsMap
->last
->depth
>= depth
))
9408 XML_NSMAP_POP(nsMap
, mi
)
9413 XML_NSMAP_FOREACH(nsMap
, mi
) {
9414 if (mi
->shadowDepth
>= depth
)
9415 mi
->shadowDepth
= -1;
9420 if (cur
->next
!= NULL
)
9422 else if ((cur
->type
== XML_ATTRIBUTE_NODE
) &&
9423 (cur
->parent
->children
!= NULL
))
9425 cur
= cur
->parent
->children
;
9441 if (nsMap
!= NULL
) {
9442 if ((ctxt
) && (ctxt
->namespaceMap
== nsMap
)) {
9444 * Just cleanup the map but don't free.
9448 nsMap
->last
->next
= nsMap
->pool
;
9449 nsMap
->pool
= nsMap
->first
;
9450 nsMap
->first
= NULL
;
9453 xmlDOMWrapNsMapFree(nsMap
);
9459 * xmlDOMWrapCloneNode:
9460 * @ctxt: the optional context for custom processing
9461 * @sourceDoc: the optional sourceDoc
9462 * @node: the node to start with
9463 * @resNode: the clone of the given @node
9464 * @destDoc: the destination doc
9465 * @destParent: the optional new parent of @node in @destDoc
9466 * @deep: descend into child if set
9467 * @options: option flags
9469 * References of out-of scope ns-decls are remapped to point to @destDoc:
9470 * 1) If @destParent is given, then nsDef entries on element-nodes are used
9471 * 2) If *no* @destParent is given, then @destDoc->oldNs entries are used.
9472 * This is the case when you don't know already where the cloned branch
9475 * If @destParent is given, it ensures that the tree is namespace
9476 * wellformed by creating additional ns-decls where needed.
9477 * Note that, since prefixes of already existent ns-decls can be
9478 * shadowed by this process, it could break QNames in attribute
9479 * values or element content.
9481 * 1) What to do with XInclude? Currently this returns an error for XInclude.
9483 * Returns 0 if the operation succeeded,
9484 * 1 if a node of unsupported (or not yet supported) type was given,
9485 * -1 on API/internal errors.
9489 xmlDOMWrapCloneNode(xmlDOMWrapCtxtPtr ctxt
,
9490 xmlDocPtr sourceDoc
,
9492 xmlNodePtr
*resNode
,
9494 xmlNodePtr destParent
,
9496 int options ATTRIBUTE_UNUSED
)
9499 xmlNodePtr cur
, curElem
= NULL
;
9500 xmlNsMapPtr nsMap
= NULL
;
9504 /* int adoptStr = 1; */
9505 /* gather @parent's ns-decls. */
9509 * TODO: @ancestorsOnly should be set per option.
9512 int ancestorsOnly
= 0;
9513 xmlNodePtr resultClone
= NULL
, clone
= NULL
, parentClone
= NULL
, prevClone
= NULL
;
9514 xmlNsPtr cloneNs
= NULL
, *cloneNsDefSlot
= NULL
;
9515 xmlDictPtr dict
; /* The destination dict */
9517 if ((node
== NULL
) || (resNode
== NULL
) || (destDoc
== NULL
))
9520 * TODO: Initially we support only element-nodes.
9522 if (node
->type
!= XML_ELEMENT_NODE
)
9525 * Check node->doc sanity.
9527 if ((node
->doc
!= NULL
) && (sourceDoc
!= NULL
) &&
9528 (node
->doc
!= sourceDoc
)) {
9530 * Might be an XIncluded node.
9534 if (sourceDoc
== NULL
)
9535 sourceDoc
= node
->doc
;
9536 if (sourceDoc
== NULL
)
9539 dict
= destDoc
->dict
;
9541 * Reuse the namespace map of the context.
9544 nsMap
= (xmlNsMapPtr
) ctxt
->namespaceMap
;
9549 if ((cur
!= NULL
) && (cur
->type
== XML_NAMESPACE_DECL
))
9552 while (cur
!= NULL
) {
9553 if (cur
->doc
!= sourceDoc
) {
9555 * We'll assume XIncluded nodes if the doc differs.
9556 * TODO: Do we need to reconciliate XIncluded nodes?
9557 * TODO: This here returns -1 in this case.
9559 goto internal_error
;
9562 * Create a new node.
9564 switch (cur
->type
) {
9565 case XML_XINCLUDE_START
:
9566 case XML_XINCLUDE_END
:
9568 * TODO: What to do with XInclude?
9570 goto internal_error
;
9572 case XML_ELEMENT_NODE
:
9574 case XML_CDATA_SECTION_NODE
:
9575 case XML_COMMENT_NODE
:
9577 case XML_DOCUMENT_FRAG_NODE
:
9578 case XML_ENTITY_REF_NODE
:
9579 case XML_ENTITY_NODE
:
9581 * Nodes of xmlNode structure.
9583 clone
= (xmlNodePtr
) xmlMalloc(sizeof(xmlNode
));
9584 if (clone
== NULL
) {
9585 xmlTreeErrMemory("xmlDOMWrapCloneNode(): allocating a node");
9586 goto internal_error
;
9588 memset(clone
, 0, sizeof(xmlNode
));
9590 * Set hierarchical links.
9592 if (resultClone
!= NULL
) {
9593 clone
->parent
= parentClone
;
9595 prevClone
->next
= clone
;
9596 clone
->prev
= prevClone
;
9598 parentClone
->children
= clone
;
9600 resultClone
= clone
;
9603 case XML_ATTRIBUTE_NODE
:
9605 * Attributes (xmlAttr).
9607 clone
= (xmlNodePtr
) xmlMalloc(sizeof(xmlAttr
));
9608 if (clone
== NULL
) {
9609 xmlTreeErrMemory("xmlDOMWrapCloneNode(): allocating an attr-node");
9610 goto internal_error
;
9612 memset(clone
, 0, sizeof(xmlAttr
));
9614 * Set hierarchical links.
9615 * TODO: Change this to add to the end of attributes.
9617 if (resultClone
!= NULL
) {
9618 clone
->parent
= parentClone
;
9620 prevClone
->next
= clone
;
9621 clone
->prev
= prevClone
;
9623 parentClone
->properties
= (xmlAttrPtr
) clone
;
9625 resultClone
= clone
;
9629 * TODO QUESTION: Any other nodes expected?
9631 goto internal_error
;
9634 clone
->type
= cur
->type
;
9635 clone
->doc
= destDoc
;
9638 * Clone the name of the node if any.
9640 if (cur
->name
== xmlStringText
)
9641 clone
->name
= xmlStringText
;
9642 else if (cur
->name
== xmlStringTextNoenc
)
9644 * NOTE: Although xmlStringTextNoenc is never assigned to a node
9645 * in tree.c, it might be set in Libxslt via
9646 * "xsl:disable-output-escaping".
9648 clone
->name
= xmlStringTextNoenc
;
9649 else if (cur
->name
== xmlStringComment
)
9650 clone
->name
= xmlStringComment
;
9651 else if (cur
->name
!= NULL
) {
9652 DICT_CONST_COPY(cur
->name
, clone
->name
);
9655 switch (cur
->type
) {
9656 case XML_XINCLUDE_START
:
9657 case XML_XINCLUDE_END
:
9662 case XML_ELEMENT_NODE
:
9666 * Namespace declarations.
9668 if (cur
->nsDef
!= NULL
) {
9670 if (destParent
&& (ctxt
== NULL
)) {
9672 * Gather @parent's in-scope ns-decls.
9674 if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap
,
9676 goto internal_error
;
9681 * Clone namespace declarations.
9683 cloneNsDefSlot
= &(clone
->nsDef
);
9684 for (ns
= cur
->nsDef
; ns
!= NULL
; ns
= ns
->next
) {
9686 * Create a new xmlNs.
9688 cloneNs
= (xmlNsPtr
) xmlMalloc(sizeof(xmlNs
));
9689 if (cloneNs
== NULL
) {
9690 xmlTreeErrMemory("xmlDOMWrapCloneNode(): "
9691 "allocating namespace");
9694 memset(cloneNs
, 0, sizeof(xmlNs
));
9695 cloneNs
->type
= XML_LOCAL_NAMESPACE
;
9697 if (ns
->href
!= NULL
)
9698 cloneNs
->href
= xmlStrdup(ns
->href
);
9699 if (ns
->prefix
!= NULL
)
9700 cloneNs
->prefix
= xmlStrdup(ns
->prefix
);
9702 *cloneNsDefSlot
= cloneNs
;
9703 cloneNsDefSlot
= &(cloneNs
->next
);
9706 * Note that for custom handling of ns-references,
9707 * the ns-decls need not be stored in the ns-map,
9708 * since they won't be referenced by node->ns.
9710 if ((ctxt
== NULL
) ||
9711 (ctxt
->getNsForNodeFunc
== NULL
))
9714 * Does it shadow any ns-decl?
9716 if (XML_NSMAP_NOTEMPTY(nsMap
)) {
9717 XML_NSMAP_FOREACH(nsMap
, mi
) {
9718 if ((mi
->depth
>= XML_TREE_NSMAP_PARENT
) &&
9719 (mi
->shadowDepth
== -1) &&
9720 ((ns
->prefix
== mi
->newNs
->prefix
) ||
9721 xmlStrEqual(ns
->prefix
,
9722 mi
->newNs
->prefix
))) {
9724 * Mark as shadowed at the current
9727 mi
->shadowDepth
= depth
;
9734 if (xmlDOMWrapNsMapAddItem(&nsMap
, -1,
9735 ns
, cloneNs
, depth
) == NULL
)
9736 goto internal_error
;
9740 /* cur->ns will be processed further down. */
9742 case XML_ATTRIBUTE_NODE
:
9743 /* IDs will be processed further down. */
9744 /* cur->ns will be processed further down. */
9747 case XML_CDATA_SECTION_NODE
:
9749 * Note that this will also cover the values of attributes.
9751 DICT_COPY(cur
->content
, clone
->content
);
9753 case XML_ENTITY_NODE
:
9754 /* TODO: What to do here? */
9756 case XML_ENTITY_REF_NODE
:
9757 if (sourceDoc
!= destDoc
) {
9758 if ((destDoc
->intSubset
) || (destDoc
->extSubset
)) {
9761 * Different doc: Assign new entity-node if available.
9763 ent
= xmlGetDocEntity(destDoc
, cur
->name
);
9765 clone
->content
= ent
->content
;
9766 clone
->children
= (xmlNodePtr
) ent
;
9767 clone
->last
= (xmlNodePtr
) ent
;
9772 * Same doc: Use the current node's entity declaration
9775 clone
->content
= cur
->content
;
9776 clone
->children
= cur
->children
;
9777 clone
->last
= cur
->last
;
9781 DICT_COPY(cur
->content
, clone
->content
);
9783 case XML_COMMENT_NODE
:
9784 DICT_COPY(cur
->content
, clone
->content
);
9787 goto internal_error
;
9790 if (cur
->ns
== NULL
)
9791 goto end_ns_reference
;
9793 /* handle_ns_reference: */
9795 ** The following will take care of references to ns-decls ********
9796 ** and is intended only for element- and attribute-nodes.
9800 if (destParent
&& (ctxt
== NULL
)) {
9801 if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap
, destParent
) == -1)
9802 goto internal_error
;
9807 * Adopt ns-references.
9809 if (XML_NSMAP_NOTEMPTY(nsMap
)) {
9811 * Search for a mapping.
9813 XML_NSMAP_FOREACH(nsMap
, mi
) {
9814 if ((mi
->shadowDepth
== -1) &&
9815 (cur
->ns
== mi
->oldNs
)) {
9817 * This is the nice case: a mapping was found.
9819 clone
->ns
= mi
->newNs
;
9820 goto end_ns_reference
;
9825 * No matching namespace in scope. We need a new one.
9827 if ((ctxt
!= NULL
) && (ctxt
->getNsForNodeFunc
!= NULL
)) {
9829 * User-defined behaviour.
9831 ns
= ctxt
->getNsForNodeFunc(ctxt
, cur
,
9832 cur
->ns
->href
, cur
->ns
->prefix
);
9834 * Add user's mapping.
9836 if (xmlDOMWrapNsMapAddItem(&nsMap
, -1,
9837 cur
->ns
, ns
, XML_TREE_NSMAP_CUSTOM
) == NULL
)
9838 goto internal_error
;
9842 * Acquire a normalized ns-decl and add it to the map.
9844 if (xmlDOMWrapNSNormAcquireNormalizedNs(destDoc
,
9845 /* ns-decls on curElem or on destDoc->oldNs */
9846 destParent
? curElem
: NULL
,
9849 /* if we need to search only in the ancestor-axis */
9851 /* ns-decls must be prefixed for attributes. */
9852 (cur
->type
== XML_ATTRIBUTE_NODE
) ? 1 : 0) == -1)
9853 goto internal_error
;
9860 * Some post-processing.
9862 * Handle ID attributes.
9864 if ((clone
->type
== XML_ATTRIBUTE_NODE
) &&
9865 (clone
->parent
!= NULL
))
9867 if (xmlIsID(destDoc
, clone
->parent
, (xmlAttrPtr
) clone
)) {
9871 idVal
= xmlNodeListGetString(cur
->doc
, cur
->children
, 1);
9872 if (idVal
!= NULL
) {
9873 if (xmlAddID(NULL
, destDoc
, idVal
, (xmlAttrPtr
) cur
) == NULL
) {
9874 /* TODO: error message. */
9876 goto internal_error
;
9884 ** The following will traverse the tree **************************
9887 * Walk the element's attributes before descending into child-nodes.
9889 if ((cur
->type
== XML_ELEMENT_NODE
) && (cur
->properties
!= NULL
)) {
9891 parentClone
= clone
;
9892 cur
= (xmlNodePtr
) cur
->properties
;
9897 * Descend into child-nodes.
9899 if (cur
->children
!= NULL
) {
9900 if (deep
|| (cur
->type
== XML_ATTRIBUTE_NODE
)) {
9902 parentClone
= clone
;
9903 cur
= cur
->children
;
9910 * At this point we are done with the node, its content
9911 * and an element-nodes's attribute-nodes.
9915 if ((cur
->type
== XML_ELEMENT_NODE
) ||
9916 (cur
->type
== XML_XINCLUDE_START
) ||
9917 (cur
->type
== XML_XINCLUDE_END
)) {
9919 * TODO: Do we expect nsDefs on XML_XINCLUDE_START?
9921 if (XML_NSMAP_NOTEMPTY(nsMap
)) {
9925 while ((nsMap
->last
!= NULL
) &&
9926 (nsMap
->last
->depth
>= depth
))
9928 XML_NSMAP_POP(nsMap
, mi
)
9933 XML_NSMAP_FOREACH(nsMap
, mi
) {
9934 if (mi
->shadowDepth
>= depth
)
9935 mi
->shadowDepth
= -1;
9940 if (cur
->next
!= NULL
) {
9943 } else if (cur
->type
!= XML_ATTRIBUTE_NODE
) {
9947 if (clone
->parent
!= NULL
)
9948 clone
->parent
->last
= clone
;
9949 clone
= clone
->parent
;
9951 parentClone
= clone
->parent
;
9953 * Process parent --> next;
9958 /* This is for attributes only. */
9959 clone
= clone
->parent
;
9960 parentClone
= clone
->parent
;
9962 * Process parent-element --> children.
9977 if (nsMap
!= NULL
) {
9978 if ((ctxt
) && (ctxt
->namespaceMap
== nsMap
)) {
9980 * Just cleanup the map but don't free.
9984 nsMap
->last
->next
= nsMap
->pool
;
9985 nsMap
->pool
= nsMap
->first
;
9986 nsMap
->first
= NULL
;
9989 xmlDOMWrapNsMapFree(nsMap
);
9992 * TODO: Should we try a cleanup of the cloned node in case of a
9995 *resNode
= resultClone
;
10000 * xmlDOMWrapAdoptAttr:
10001 * @ctxt: the optional context for custom processing
10002 * @sourceDoc: the optional source document of attr
10003 * @attr: the attribute-node to be adopted
10004 * @destDoc: the destination doc for adoption
10005 * @destParent: the optional new parent of @attr in @destDoc
10006 * @options: option flags
10008 * @attr is adopted by @destDoc.
10009 * Ensures that ns-references point to @destDoc: either to
10010 * elements->nsDef entries if @destParent is given, or to
10011 * @destDoc->oldNs otherwise.
10013 * Returns 0 if succeeded, -1 otherwise and on API/internal errors.
10016 xmlDOMWrapAdoptAttr(xmlDOMWrapCtxtPtr ctxt
,
10017 xmlDocPtr sourceDoc
,
10020 xmlNodePtr destParent
,
10021 int options ATTRIBUTE_UNUSED
)
10026 if ((attr
== NULL
) || (destDoc
== NULL
))
10029 attr
->doc
= destDoc
;
10030 if (attr
->ns
!= NULL
) {
10031 xmlNsPtr ns
= NULL
;
10033 if (ctxt
!= NULL
) {
10034 /* TODO: User defined. */
10036 /* XML Namespace. */
10037 if (IS_STR_XML(attr
->ns
->prefix
)) {
10038 ns
= xmlTreeEnsureXMLDecl(destDoc
);
10039 } else if (destParent
== NULL
) {
10041 * Store in @destDoc->oldNs.
10043 ns
= xmlDOMWrapStoreNs(destDoc
, attr
->ns
->href
, attr
->ns
->prefix
);
10046 * Declare on @destParent.
10048 if (xmlSearchNsByNamespaceStrict(destDoc
, destParent
, attr
->ns
->href
,
10050 goto internal_error
;
10052 ns
= xmlDOMWrapNSNormDeclareNsForced(destDoc
, destParent
,
10053 attr
->ns
->href
, attr
->ns
->prefix
, 1);
10057 goto internal_error
;
10061 XML_TREE_ADOPT_STR(attr
->name
);
10067 if (attr
->children
== NULL
)
10069 cur
= attr
->children
;
10070 if ((cur
!= NULL
) && (cur
->type
== XML_NAMESPACE_DECL
))
10071 goto internal_error
;
10072 while (cur
!= NULL
) {
10073 cur
->doc
= destDoc
;
10074 switch (cur
->type
) {
10075 case XML_TEXT_NODE
:
10076 case XML_CDATA_SECTION_NODE
:
10077 XML_TREE_ADOPT_STR_2(cur
->content
)
10079 case XML_ENTITY_REF_NODE
:
10081 * Remove reference to the entity-node.
10083 cur
->content
= NULL
;
10084 cur
->children
= NULL
;
10086 if ((destDoc
->intSubset
) || (destDoc
->extSubset
)) {
10089 * Assign new entity-node if available.
10091 ent
= xmlGetDocEntity(destDoc
, cur
->name
);
10093 cur
->content
= ent
->content
;
10094 cur
->children
= (xmlNodePtr
) ent
;
10095 cur
->last
= (xmlNodePtr
) ent
;
10102 if (cur
->children
!= NULL
) {
10103 cur
= cur
->children
;
10107 if (cur
== (xmlNodePtr
) attr
)
10109 if (cur
->next
!= NULL
)
10122 * xmlDOMWrapAdoptNode:
10123 * @ctxt: the optional context for custom processing
10124 * @sourceDoc: the optional sourceDoc
10125 * @node: the node to start with
10126 * @destDoc: the destination doc
10127 * @destParent: the optional new parent of @node in @destDoc
10128 * @options: option flags
10130 * References of out-of scope ns-decls are remapped to point to @destDoc:
10131 * 1) If @destParent is given, then nsDef entries on element-nodes are used
10132 * 2) If *no* @destParent is given, then @destDoc->oldNs entries are used
10133 * This is the case when you have an unlinked node and just want to move it
10134 * to the context of
10136 * If @destParent is given, it ensures that the tree is namespace
10137 * wellformed by creating additional ns-decls where needed.
10138 * Note that, since prefixes of already existent ns-decls can be
10139 * shadowed by this process, it could break QNames in attribute
10140 * values or element content.
10141 * NOTE: This function was not intensively tested.
10143 * Returns 0 if the operation succeeded,
10144 * 1 if a node of unsupported type was given,
10145 * 2 if a node of not yet supported type was given and
10146 * -1 on API/internal errors.
10149 xmlDOMWrapAdoptNode(xmlDOMWrapCtxtPtr ctxt
,
10150 xmlDocPtr sourceDoc
,
10153 xmlNodePtr destParent
,
10156 if ((node
== NULL
) || (node
->type
== XML_NAMESPACE_DECL
) ||
10157 (destDoc
== NULL
) ||
10158 ((destParent
!= NULL
) && (destParent
->doc
!= destDoc
)))
10161 * Check node->doc sanity.
10163 if ((node
->doc
!= NULL
) && (sourceDoc
!= NULL
) &&
10164 (node
->doc
!= sourceDoc
)) {
10166 * Might be an XIncluded node.
10170 if (sourceDoc
== NULL
)
10171 sourceDoc
= node
->doc
;
10172 if (sourceDoc
== destDoc
)
10174 switch (node
->type
) {
10175 case XML_ELEMENT_NODE
:
10176 case XML_ATTRIBUTE_NODE
:
10177 case XML_TEXT_NODE
:
10178 case XML_CDATA_SECTION_NODE
:
10179 case XML_ENTITY_REF_NODE
:
10181 case XML_COMMENT_NODE
:
10183 case XML_DOCUMENT_FRAG_NODE
:
10184 /* TODO: Support document-fragment-nodes. */
10190 * Unlink only if @node was not already added to @destParent.
10192 if ((node
->parent
!= NULL
) && (destParent
!= node
->parent
))
10193 xmlUnlinkNode(node
);
10195 if (node
->type
== XML_ELEMENT_NODE
) {
10196 return (xmlDOMWrapAdoptBranch(ctxt
, sourceDoc
, node
,
10197 destDoc
, destParent
, options
));
10198 } else if (node
->type
== XML_ATTRIBUTE_NODE
) {
10199 return (xmlDOMWrapAdoptAttr(ctxt
, sourceDoc
,
10200 (xmlAttrPtr
) node
, destDoc
, destParent
, options
));
10202 xmlNodePtr cur
= node
;
10205 cur
->doc
= destDoc
;
10207 * Optimize string adoption.
10209 if ((sourceDoc
!= NULL
) &&
10210 (sourceDoc
->dict
== destDoc
->dict
))
10212 switch (node
->type
) {
10213 case XML_TEXT_NODE
:
10214 case XML_CDATA_SECTION_NODE
:
10215 XML_TREE_ADOPT_STR_2(node
->content
)
10217 case XML_ENTITY_REF_NODE
:
10219 * Remove reference to the entity-node.
10221 node
->content
= NULL
;
10222 node
->children
= NULL
;
10224 if ((destDoc
->intSubset
) || (destDoc
->extSubset
)) {
10227 * Assign new entity-node if available.
10229 ent
= xmlGetDocEntity(destDoc
, node
->name
);
10231 node
->content
= ent
->content
;
10232 node
->children
= (xmlNodePtr
) ent
;
10233 node
->last
= (xmlNodePtr
) ent
;
10236 XML_TREE_ADOPT_STR(node
->name
)
10238 case XML_PI_NODE
: {
10239 XML_TREE_ADOPT_STR(node
->name
)
10240 XML_TREE_ADOPT_STR_2(node
->content
)