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 ! */
30 #ifdef LIBXML_ZLIB_ENABLED
34 #include <libxml/xmlmemory.h>
35 #include <libxml/tree.h>
36 #include <libxml/parser.h>
37 #include <libxml/uri.h>
38 #include <libxml/entities.h>
39 #include <libxml/valid.h>
40 #include <libxml/xmlerror.h>
41 #include <libxml/parserInternals.h>
42 #include <libxml/globals.h>
43 #ifdef LIBXML_HTML_ENABLED
44 #include <libxml/HTMLtree.h>
46 #ifdef LIBXML_DEBUG_ENABLED
47 #include <libxml/debugXML.h>
53 int __xmlRegisterCallbacks
= 0;
55 /************************************************************************
57 * Forward declarations *
59 ************************************************************************/
62 xmlNewReconciledNs(xmlDocPtr doc
, xmlNodePtr tree
, xmlNsPtr ns
);
64 static xmlChar
* xmlGetPropNodeValueInternal(const xmlAttr
*prop
);
66 /************************************************************************
68 * Tree memory error handler *
70 ************************************************************************/
73 * @extra: extra information
75 * Handle an out of memory condition
78 xmlTreeErrMemory(const char *extra
)
80 __xmlSimpleError(XML_FROM_TREE
, XML_ERR_NO_MEMORY
, NULL
, NULL
, extra
);
85 * @code: the error number
86 * @extra: extra information
88 * Handle an out of memory condition
91 xmlTreeErr(int code
, xmlNodePtr node
, const char *extra
)
93 const char *msg
= NULL
;
96 case XML_TREE_INVALID_HEX
:
97 msg
= "invalid hexadecimal character value\n";
99 case XML_TREE_INVALID_DEC
:
100 msg
= "invalid decimal character value\n";
102 case XML_TREE_UNTERMINATED_ENTITY
:
103 msg
= "unterminated entity reference %15s\n";
105 case XML_TREE_NOT_UTF8
:
106 msg
= "string is not in UTF-8\n";
109 msg
= "unexpected error number\n";
111 __xmlSimpleError(XML_FROM_TREE
, code
, node
, msg
, extra
);
114 /************************************************************************
116 * A few static variables and macros *
118 ************************************************************************/
119 /* #undef xmlStringText */
120 const xmlChar xmlStringText
[] = { 't', 'e', 'x', 't', 0 };
121 /* #undef xmlStringTextNoenc */
122 const xmlChar xmlStringTextNoenc
[] =
123 { 't', 'e', 'x', 't', 'n', 'o', 'e', 'n', 'c', 0 };
124 /* #undef xmlStringComment */
125 const xmlChar xmlStringComment
[] = { 'c', 'o', 'm', 'm', 'e', 'n', 't', 0 };
127 static int xmlCompressMode
= 0;
128 static int xmlCheckDTD
= 1;
130 #define UPDATE_LAST_CHILD_AND_PARENT(n) if ((n) != NULL) { \
131 xmlNodePtr ulccur = (n)->children; \
132 if (ulccur == NULL) { \
135 while (ulccur->next != NULL) { \
136 ulccur->parent = (n); \
137 ulccur = ulccur->next; \
139 ulccur->parent = (n); \
140 (n)->last = ulccur; \
143 #define IS_STR_XML(str) ((str != NULL) && (str[0] == 'x') && \
144 (str[1] == 'm') && (str[2] == 'l') && (str[3] == 0))
146 /* #define DEBUG_BUFFER */
147 /* #define DEBUG_TREE */
149 /************************************************************************
151 * Functions to move to entities.c once the *
152 * API freeze is smoothen and they can be made public. *
154 ************************************************************************/
155 #include <libxml/hash.h>
157 #ifdef LIBXML_TREE_ENABLED
159 * xmlGetEntityFromDtd:
160 * @dtd: A pointer to the DTD to search
161 * @name: The entity name
163 * Do an entity lookup in the DTD entity hash table and
164 * return the corresponding entity, if found.
166 * Returns A pointer to the entity structure or NULL if not found.
169 xmlGetEntityFromDtd(const xmlDtd
*dtd
, const xmlChar
*name
) {
170 xmlEntitiesTablePtr table
;
172 if((dtd
!= NULL
) && (dtd
->entities
!= NULL
)) {
173 table
= (xmlEntitiesTablePtr
) dtd
->entities
;
174 return((xmlEntityPtr
) xmlHashLookup(table
, name
));
175 /* return(xmlGetEntityFromTable(table, name)); */
180 * xmlGetParameterEntityFromDtd:
181 * @dtd: A pointer to the DTD to search
182 * @name: The entity name
184 * Do an entity lookup in the DTD parameter entity hash table and
185 * return the corresponding entity, if found.
187 * Returns A pointer to the entity structure or NULL if not found.
190 xmlGetParameterEntityFromDtd(const xmlDtd
*dtd
, const xmlChar
*name
) {
191 xmlEntitiesTablePtr table
;
193 if ((dtd
!= NULL
) && (dtd
->pentities
!= NULL
)) {
194 table
= (xmlEntitiesTablePtr
) dtd
->pentities
;
195 return((xmlEntityPtr
) xmlHashLookup(table
, name
));
196 /* return(xmlGetEntityFromTable(table, name)); */
200 #endif /* LIBXML_TREE_ENABLED */
202 /************************************************************************
204 * QName handling helper *
206 ************************************************************************/
211 * @prefix: the prefix
212 * @memory: preallocated memory
213 * @len: preallocated memory length
215 * Builds the QName @prefix:@ncname in @memory if there is enough space
216 * and prefix is not NULL nor empty, otherwise allocate a new string.
217 * If prefix is NULL or empty it returns ncname.
219 * Returns the new string which must be freed by the caller if different from
220 * @memory and @ncname or NULL in case of error
223 xmlBuildQName(const xmlChar
*ncname
, const xmlChar
*prefix
,
224 xmlChar
*memory
, int len
) {
228 if (ncname
== NULL
) return(NULL
);
229 if (prefix
== NULL
) return((xmlChar
*) ncname
);
231 lenn
= strlen((char *) ncname
);
232 lenp
= strlen((char *) prefix
);
234 if ((memory
== NULL
) || (len
< lenn
+ lenp
+ 2)) {
235 ret
= (xmlChar
*) xmlMallocAtomic(lenn
+ lenp
+ 2);
237 xmlTreeErrMemory("building QName");
243 memcpy(&ret
[0], prefix
, lenp
);
245 memcpy(&ret
[lenp
+ 1], ncname
, lenn
);
246 ret
[lenn
+ lenp
+ 1] = 0;
252 * @name: the full QName
253 * @prefix: a xmlChar **
255 * parse an XML qualified name string
257 * [NS 5] QName ::= (Prefix ':')? LocalPart
259 * [NS 6] Prefix ::= NCName
261 * [NS 7] LocalPart ::= NCName
263 * Returns NULL if the name doesn't have a prefix. Otherwise, returns the
264 * local part, and prefix is updated to get the Prefix. Both the return value
265 * and the prefix must be freed by the caller.
268 xmlSplitQName2(const xmlChar
*name
, xmlChar
**prefix
) {
272 if (prefix
== NULL
) return(NULL
);
274 if (name
== NULL
) return(NULL
);
276 #ifndef XML_XML_NAMESPACE
277 /* xml: prefix is not really a namespace */
278 if ((name
[0] == 'x') && (name
[1] == 'm') &&
279 (name
[2] == 'l') && (name
[3] == ':'))
283 /* nasty but valid */
288 * we are not trying to validate but just to cut, and yes it will
289 * work even if this is as set of UTF-8 encoded chars
291 while ((name
[len
] != 0) && (name
[len
] != ':'))
297 *prefix
= xmlStrndup(name
, len
);
298 if (*prefix
== NULL
) {
299 xmlTreeErrMemory("QName split");
302 ret
= xmlStrdup(&name
[len
+ 1]);
304 xmlTreeErrMemory("QName split");
305 if (*prefix
!= NULL
) {
317 * @name: the full QName
320 * parse an XML qualified name string,i
322 * returns NULL if it is not a Qualified Name, otherwise, update len
323 * with the length in byte of the prefix and return a pointer
324 * to the start of the name without the prefix
328 xmlSplitQName3(const xmlChar
*name
, int *len
) {
331 if (name
== NULL
) return(NULL
);
332 if (len
== NULL
) return(NULL
);
334 /* nasty but valid */
339 * we are not trying to validate but just to cut, and yes it will
340 * work even if this is as set of UTF-8 encoded chars
342 while ((name
[l
] != 0) && (name
[l
] != ':'))
353 /************************************************************************
355 * Check Name, NCName and QName strings *
357 ************************************************************************/
359 #define CUR_SCHAR(s, l) xmlStringCurrentChar(NULL, s, &l)
361 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XPATH_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) || defined(LIBXML_DEBUG_ENABLED) || defined (LIBXML_HTML_ENABLED) || defined(LIBXML_SAX1_ENABLED) || defined(LIBXML_HTML_ENABLED) || defined(LIBXML_WRITER_ENABLED) || defined(LIBXML_DOCB_ENABLED) || defined(LIBXML_LEGACY_ENABLED)
364 * @value: the value to check
365 * @space: allow spaces in front and end of the string
367 * Check that a value conforms to the lexical space of NCName
369 * Returns 0 if this validates, a positive error code number otherwise
370 * and -1 in case of internal or API error.
373 xmlValidateNCName(const xmlChar
*value
, int space
) {
374 const xmlChar
*cur
= value
;
381 * First quick algorithm for ASCII range
384 while (IS_BLANK_CH(*cur
)) cur
++;
385 if (((*cur
>= 'a') && (*cur
<= 'z')) || ((*cur
>= 'A') && (*cur
<= 'Z')) ||
390 while (((*cur
>= 'a') && (*cur
<= 'z')) ||
391 ((*cur
>= 'A') && (*cur
<= 'Z')) ||
392 ((*cur
>= '0') && (*cur
<= '9')) ||
393 (*cur
== '_') || (*cur
== '-') || (*cur
== '.'))
396 while (IS_BLANK_CH(*cur
)) cur
++;
402 * Second check for chars outside the ASCII range
405 c
= CUR_SCHAR(cur
, l
);
407 while (IS_BLANK(c
)) {
409 c
= CUR_SCHAR(cur
, l
);
412 if ((!IS_LETTER(c
)) && (c
!= '_'))
415 c
= CUR_SCHAR(cur
, l
);
416 while (IS_LETTER(c
) || IS_DIGIT(c
) || (c
== '.') ||
417 (c
== '-') || (c
== '_') || IS_COMBINING(c
) ||
420 c
= CUR_SCHAR(cur
, l
);
423 while (IS_BLANK(c
)) {
425 c
= CUR_SCHAR(cur
, l
);
435 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
438 * @value: the value to check
439 * @space: allow spaces in front and end of the string
441 * Check that a value conforms to the lexical space of QName
443 * Returns 0 if this validates, a positive error code number otherwise
444 * and -1 in case of internal or API error.
447 xmlValidateQName(const xmlChar
*value
, int space
) {
448 const xmlChar
*cur
= value
;
454 * First quick algorithm for ASCII range
457 while (IS_BLANK_CH(*cur
)) cur
++;
458 if (((*cur
>= 'a') && (*cur
<= 'z')) || ((*cur
>= 'A') && (*cur
<= 'Z')) ||
463 while (((*cur
>= 'a') && (*cur
<= 'z')) ||
464 ((*cur
>= 'A') && (*cur
<= 'Z')) ||
465 ((*cur
>= '0') && (*cur
<= '9')) ||
466 (*cur
== '_') || (*cur
== '-') || (*cur
== '.'))
470 if (((*cur
>= 'a') && (*cur
<= 'z')) ||
471 ((*cur
>= 'A') && (*cur
<= 'Z')) ||
476 while (((*cur
>= 'a') && (*cur
<= 'z')) ||
477 ((*cur
>= 'A') && (*cur
<= 'Z')) ||
478 ((*cur
>= '0') && (*cur
<= '9')) ||
479 (*cur
== '_') || (*cur
== '-') || (*cur
== '.'))
483 while (IS_BLANK_CH(*cur
)) cur
++;
489 * Second check for chars outside the ASCII range
492 c
= CUR_SCHAR(cur
, l
);
494 while (IS_BLANK(c
)) {
496 c
= CUR_SCHAR(cur
, l
);
499 if ((!IS_LETTER(c
)) && (c
!= '_'))
502 c
= CUR_SCHAR(cur
, l
);
503 while (IS_LETTER(c
) || IS_DIGIT(c
) || (c
== '.') ||
504 (c
== '-') || (c
== '_') || IS_COMBINING(c
) ||
507 c
= CUR_SCHAR(cur
, l
);
511 c
= CUR_SCHAR(cur
, l
);
512 if ((!IS_LETTER(c
)) && (c
!= '_'))
515 c
= CUR_SCHAR(cur
, l
);
516 while (IS_LETTER(c
) || IS_DIGIT(c
) || (c
== '.') ||
517 (c
== '-') || (c
== '_') || IS_COMBINING(c
) ||
520 c
= CUR_SCHAR(cur
, l
);
524 while (IS_BLANK(c
)) {
526 c
= CUR_SCHAR(cur
, l
);
536 * @value: the value to check
537 * @space: allow spaces in front and end of the string
539 * Check that a value conforms to the lexical space of Name
541 * Returns 0 if this validates, a positive error code number otherwise
542 * and -1 in case of internal or API error.
545 xmlValidateName(const xmlChar
*value
, int space
) {
546 const xmlChar
*cur
= value
;
552 * First quick algorithm for ASCII range
555 while (IS_BLANK_CH(*cur
)) cur
++;
556 if (((*cur
>= 'a') && (*cur
<= 'z')) || ((*cur
>= 'A') && (*cur
<= 'Z')) ||
557 (*cur
== '_') || (*cur
== ':'))
561 while (((*cur
>= 'a') && (*cur
<= 'z')) ||
562 ((*cur
>= 'A') && (*cur
<= 'Z')) ||
563 ((*cur
>= '0') && (*cur
<= '9')) ||
564 (*cur
== '_') || (*cur
== '-') || (*cur
== '.') || (*cur
== ':'))
567 while (IS_BLANK_CH(*cur
)) cur
++;
573 * Second check for chars outside the ASCII range
576 c
= CUR_SCHAR(cur
, l
);
578 while (IS_BLANK(c
)) {
580 c
= CUR_SCHAR(cur
, l
);
583 if ((!IS_LETTER(c
)) && (c
!= '_') && (c
!= ':'))
586 c
= CUR_SCHAR(cur
, l
);
587 while (IS_LETTER(c
) || IS_DIGIT(c
) || (c
== '.') || (c
== ':') ||
588 (c
== '-') || (c
== '_') || IS_COMBINING(c
) || IS_EXTENDER(c
)) {
590 c
= CUR_SCHAR(cur
, l
);
593 while (IS_BLANK(c
)) {
595 c
= CUR_SCHAR(cur
, l
);
604 * xmlValidateNMToken:
605 * @value: the value to check
606 * @space: allow spaces in front and end of the string
608 * Check that a value conforms to the lexical space of NMToken
610 * Returns 0 if this validates, a positive error code number otherwise
611 * and -1 in case of internal or API error.
614 xmlValidateNMToken(const xmlChar
*value
, int space
) {
615 const xmlChar
*cur
= value
;
621 * First quick algorithm for ASCII range
624 while (IS_BLANK_CH(*cur
)) cur
++;
625 if (((*cur
>= 'a') && (*cur
<= 'z')) ||
626 ((*cur
>= 'A') && (*cur
<= 'Z')) ||
627 ((*cur
>= '0') && (*cur
<= '9')) ||
628 (*cur
== '_') || (*cur
== '-') || (*cur
== '.') || (*cur
== ':'))
632 while (((*cur
>= 'a') && (*cur
<= 'z')) ||
633 ((*cur
>= 'A') && (*cur
<= 'Z')) ||
634 ((*cur
>= '0') && (*cur
<= '9')) ||
635 (*cur
== '_') || (*cur
== '-') || (*cur
== '.') || (*cur
== ':'))
638 while (IS_BLANK_CH(*cur
)) cur
++;
644 * Second check for chars outside the ASCII range
647 c
= CUR_SCHAR(cur
, l
);
649 while (IS_BLANK(c
)) {
651 c
= CUR_SCHAR(cur
, l
);
654 if (!(IS_LETTER(c
) || IS_DIGIT(c
) || (c
== '.') || (c
== ':') ||
655 (c
== '-') || (c
== '_') || IS_COMBINING(c
) || IS_EXTENDER(c
)))
658 c
= CUR_SCHAR(cur
, l
);
659 while (IS_LETTER(c
) || IS_DIGIT(c
) || (c
== '.') || (c
== ':') ||
660 (c
== '-') || (c
== '_') || IS_COMBINING(c
) || IS_EXTENDER(c
)) {
662 c
= CUR_SCHAR(cur
, l
);
665 while (IS_BLANK(c
)) {
667 c
= CUR_SCHAR(cur
, l
);
674 #endif /* LIBXML_TREE_ENABLED */
676 /************************************************************************
678 * Allocation and deallocation of basic structures *
680 ************************************************************************/
683 * xmlSetBufferAllocationScheme:
684 * @scheme: allocation method to use
686 * Set the buffer allocation method. Types are
687 * XML_BUFFER_ALLOC_EXACT - use exact sizes, keeps memory usage down
688 * XML_BUFFER_ALLOC_DOUBLEIT - double buffer when extra needed,
689 * improves performance
692 xmlSetBufferAllocationScheme(xmlBufferAllocationScheme scheme
) {
693 if ((scheme
== XML_BUFFER_ALLOC_EXACT
) ||
694 (scheme
== XML_BUFFER_ALLOC_DOUBLEIT
) ||
695 (scheme
== XML_BUFFER_ALLOC_HYBRID
))
696 xmlBufferAllocScheme
= scheme
;
700 * xmlGetBufferAllocationScheme:
703 * XML_BUFFER_ALLOC_EXACT - use exact sizes, keeps memory usage down
704 * XML_BUFFER_ALLOC_DOUBLEIT - double buffer when extra needed,
705 * improves performance
706 * XML_BUFFER_ALLOC_HYBRID - use exact sizes on small strings to keep memory usage tight
707 * in normal usage, and doubleit on large strings to avoid
708 * pathological performance.
710 * Returns the current allocation scheme
712 xmlBufferAllocationScheme
713 xmlGetBufferAllocationScheme(void) {
714 return(xmlBufferAllocScheme
);
719 * @node: the element carrying the namespace
720 * @href: the URI associated
721 * @prefix: the prefix for the namespace
723 * Creation of a new Namespace. This function will refuse to create
724 * a namespace with a similar prefix than an existing one present on this
726 * Note that for a default namespace, @prefix should be NULL.
728 * We use href==NULL in the case of an element creation where the namespace
731 * Returns a new namespace pointer or NULL
734 xmlNewNs(xmlNodePtr node
, const xmlChar
*href
, const xmlChar
*prefix
) {
737 if ((node
!= NULL
) && (node
->type
!= XML_ELEMENT_NODE
))
740 if ((prefix
!= NULL
) && (xmlStrEqual(prefix
, BAD_CAST
"xml"))) {
741 /* xml namespace is predefined, no need to add it */
742 if (xmlStrEqual(href
, XML_XML_NAMESPACE
))
746 * Problem, this is an attempt to bind xml prefix to a wrong
747 * namespace, which breaks
748 * Namespace constraint: Reserved Prefixes and Namespace Names
749 * from XML namespace. But documents authors may not care in
750 * their context so let's proceed.
755 * Allocate a new Namespace and fill the fields.
757 cur
= (xmlNsPtr
) xmlMalloc(sizeof(xmlNs
));
759 xmlTreeErrMemory("building namespace");
762 memset(cur
, 0, sizeof(xmlNs
));
763 cur
->type
= XML_LOCAL_NAMESPACE
;
766 cur
->href
= xmlStrdup(href
);
768 cur
->prefix
= xmlStrdup(prefix
);
771 * Add it at the end to preserve parsing order ...
772 * and checks for existing use of the prefix
775 if (node
->nsDef
== NULL
) {
778 xmlNsPtr prev
= node
->nsDef
;
780 if (((prev
->prefix
== NULL
) && (cur
->prefix
== NULL
)) ||
781 (xmlStrEqual(prev
->prefix
, cur
->prefix
))) {
785 while (prev
->next
!= NULL
) {
787 if (((prev
->prefix
== NULL
) && (cur
->prefix
== NULL
)) ||
788 (xmlStrEqual(prev
->prefix
, cur
->prefix
))) {
801 * @node: a node in the document
802 * @ns: a namespace pointer
804 * Associate a namespace to a node, a posteriori.
807 xmlSetNs(xmlNodePtr node
, xmlNsPtr ns
) {
810 xmlGenericError(xmlGenericErrorContext
,
811 "xmlSetNs: node == NULL\n");
815 if ((node
->type
== XML_ELEMENT_NODE
) ||
816 (node
->type
== XML_ATTRIBUTE_NODE
))
822 * @cur: the namespace pointer
824 * Free up the structures associated to a namespace
827 xmlFreeNs(xmlNsPtr cur
) {
830 xmlGenericError(xmlGenericErrorContext
,
831 "xmlFreeNs : ns == NULL\n");
835 if (cur
->href
!= NULL
) xmlFree((char *) cur
->href
);
836 if (cur
->prefix
!= NULL
) xmlFree((char *) cur
->prefix
);
842 * @cur: the first namespace pointer
844 * Free up all the structures associated to the chained namespaces.
847 xmlFreeNsList(xmlNsPtr cur
) {
851 xmlGenericError(xmlGenericErrorContext
,
852 "xmlFreeNsList : ns == NULL\n");
856 while (cur
!= NULL
) {
865 * @doc: the document pointer
866 * @name: the DTD name
867 * @ExternalID: the external ID
868 * @SystemID: the system ID
870 * Creation of a new DTD for the external subset. To create an
871 * internal subset, use xmlCreateIntSubset().
873 * Returns a pointer to the new DTD structure
876 xmlNewDtd(xmlDocPtr doc
, const xmlChar
*name
,
877 const xmlChar
*ExternalID
, const xmlChar
*SystemID
) {
880 if ((doc
!= NULL
) && (doc
->extSubset
!= NULL
)) {
882 xmlGenericError(xmlGenericErrorContext
,
883 "xmlNewDtd(%s): document %s already have a DTD %s\n",
884 /* !!! */ (char *) name
, doc
->name
,
885 /* !!! */ (char *)doc
->extSubset
->name
);
891 * Allocate a new DTD and fill the fields.
893 cur
= (xmlDtdPtr
) xmlMalloc(sizeof(xmlDtd
));
895 xmlTreeErrMemory("building DTD");
898 memset(cur
, 0 , sizeof(xmlDtd
));
899 cur
->type
= XML_DTD_NODE
;
902 cur
->name
= xmlStrdup(name
);
903 if (ExternalID
!= NULL
)
904 cur
->ExternalID
= xmlStrdup(ExternalID
);
905 if (SystemID
!= NULL
)
906 cur
->SystemID
= xmlStrdup(SystemID
);
908 doc
->extSubset
= cur
;
911 if ((__xmlRegisterCallbacks
) && (xmlRegisterNodeDefaultValue
))
912 xmlRegisterNodeDefaultValue((xmlNodePtr
)cur
);
918 * @doc: the document pointer
920 * Get the internal subset of a document
921 * Returns a pointer to the DTD structure or NULL if not found
925 xmlGetIntSubset(const xmlDoc
*doc
) {
931 while (cur
!= NULL
) {
932 if (cur
->type
== XML_DTD_NODE
)
933 return((xmlDtdPtr
) cur
);
936 return((xmlDtdPtr
) doc
->intSubset
);
940 * xmlCreateIntSubset:
941 * @doc: the document pointer
942 * @name: the DTD name
943 * @ExternalID: the external (PUBLIC) ID
944 * @SystemID: the system ID
946 * Create the internal subset of a document
947 * Returns a pointer to the new DTD structure
950 xmlCreateIntSubset(xmlDocPtr doc
, const xmlChar
*name
,
951 const xmlChar
*ExternalID
, const xmlChar
*SystemID
) {
954 if ((doc
!= NULL
) && (xmlGetIntSubset(doc
) != NULL
)) {
956 xmlGenericError(xmlGenericErrorContext
,
958 "xmlCreateIntSubset(): document %s already have an internal subset\n",
965 * Allocate a new DTD and fill the fields.
967 cur
= (xmlDtdPtr
) xmlMalloc(sizeof(xmlDtd
));
969 xmlTreeErrMemory("building internal subset");
972 memset(cur
, 0, sizeof(xmlDtd
));
973 cur
->type
= XML_DTD_NODE
;
976 cur
->name
= xmlStrdup(name
);
977 if (cur
->name
== NULL
) {
978 xmlTreeErrMemory("building internal subset");
983 if (ExternalID
!= NULL
) {
984 cur
->ExternalID
= xmlStrdup(ExternalID
);
985 if (cur
->ExternalID
== NULL
) {
986 xmlTreeErrMemory("building internal subset");
987 if (cur
->name
!= NULL
)
988 xmlFree((char *)cur
->name
);
993 if (SystemID
!= NULL
) {
994 cur
->SystemID
= xmlStrdup(SystemID
);
995 if (cur
->SystemID
== NULL
) {
996 xmlTreeErrMemory("building internal subset");
997 if (cur
->name
!= NULL
)
998 xmlFree((char *)cur
->name
);
999 if (cur
->ExternalID
!= NULL
)
1000 xmlFree((char *)cur
->ExternalID
);
1006 doc
->intSubset
= cur
;
1009 if (doc
->children
== NULL
) {
1010 doc
->children
= (xmlNodePtr
) cur
;
1011 doc
->last
= (xmlNodePtr
) cur
;
1013 if (doc
->type
== XML_HTML_DOCUMENT_NODE
) {
1016 prev
= doc
->children
;
1017 prev
->prev
= (xmlNodePtr
) cur
;
1019 doc
->children
= (xmlNodePtr
) cur
;
1023 next
= doc
->children
;
1024 while ((next
!= NULL
) && (next
->type
!= XML_ELEMENT_NODE
))
1027 cur
->prev
= doc
->last
;
1028 cur
->prev
->next
= (xmlNodePtr
) cur
;
1030 doc
->last
= (xmlNodePtr
) cur
;
1033 cur
->prev
= next
->prev
;
1034 if (cur
->prev
== NULL
)
1035 doc
->children
= (xmlNodePtr
) cur
;
1037 cur
->prev
->next
= (xmlNodePtr
) cur
;
1038 next
->prev
= (xmlNodePtr
) cur
;
1044 if ((__xmlRegisterCallbacks
) && (xmlRegisterNodeDefaultValue
))
1045 xmlRegisterNodeDefaultValue((xmlNodePtr
)cur
);
1053 * Free a string if it is not owned by the "dict" dictionary in the
1056 #define DICT_FREE(str) \
1057 if ((str) && ((!dict) || \
1058 (xmlDictOwns(dict, (const xmlChar *)(str)) == 0))) \
1059 xmlFree((char *)(str));
1066 * Copy a string using a "dict" dictionary in the current scope,
1069 #define DICT_COPY(str, cpy) \
1072 if (xmlDictOwns(dict, (const xmlChar *)(str))) \
1073 cpy = (xmlChar *) (str); \
1075 cpy = (xmlChar *) xmlDictLookup((dict), (const xmlChar *)(str), -1); \
1077 cpy = xmlStrdup((const xmlChar *)(str)); }
1083 * Copy a string using a "dict" dictionary in the current scope,
1086 #define DICT_CONST_COPY(str, cpy) \
1089 if (xmlDictOwns(dict, (const xmlChar *)(str))) \
1090 cpy = (const xmlChar *) (str); \
1092 cpy = xmlDictLookup((dict), (const xmlChar *)(str), -1); \
1094 cpy = (const xmlChar *) xmlStrdup((const xmlChar *)(str)); }
1099 * @cur: the DTD structure to free up
1101 * Free a DTD structure.
1104 xmlFreeDtd(xmlDtdPtr cur
) {
1105 xmlDictPtr dict
= NULL
;
1110 if (cur
->doc
!= NULL
) dict
= cur
->doc
->dict
;
1112 if ((__xmlRegisterCallbacks
) && (xmlDeregisterNodeDefaultValue
))
1113 xmlDeregisterNodeDefaultValue((xmlNodePtr
)cur
);
1115 if (cur
->children
!= NULL
) {
1116 xmlNodePtr next
, c
= cur
->children
;
1119 * Cleanup all nodes which are not part of the specific lists
1120 * of notations, elements, attributes and entities.
1124 if ((c
->type
!= XML_NOTATION_NODE
) &&
1125 (c
->type
!= XML_ELEMENT_DECL
) &&
1126 (c
->type
!= XML_ATTRIBUTE_DECL
) &&
1127 (c
->type
!= XML_ENTITY_DECL
)) {
1134 DICT_FREE(cur
->name
)
1135 DICT_FREE(cur
->SystemID
)
1136 DICT_FREE(cur
->ExternalID
)
1138 if (cur
->notations
!= NULL
)
1139 xmlFreeNotationTable((xmlNotationTablePtr
) cur
->notations
);
1141 if (cur
->elements
!= NULL
)
1142 xmlFreeElementTable((xmlElementTablePtr
) cur
->elements
);
1143 if (cur
->attributes
!= NULL
)
1144 xmlFreeAttributeTable((xmlAttributeTablePtr
) cur
->attributes
);
1145 if (cur
->entities
!= NULL
)
1146 xmlFreeEntitiesTable((xmlEntitiesTablePtr
) cur
->entities
);
1147 if (cur
->pentities
!= NULL
)
1148 xmlFreeEntitiesTable((xmlEntitiesTablePtr
) cur
->pentities
);
1155 * @version: xmlChar string giving the version of XML "1.0"
1157 * Creates a new XML document
1159 * Returns a new document
1162 xmlNewDoc(const xmlChar
*version
) {
1165 if (version
== NULL
)
1166 version
= (const xmlChar
*) "1.0";
1169 * Allocate a new document and fill the fields.
1171 cur
= (xmlDocPtr
) xmlMalloc(sizeof(xmlDoc
));
1173 xmlTreeErrMemory("building doc");
1176 memset(cur
, 0, sizeof(xmlDoc
));
1177 cur
->type
= XML_DOCUMENT_NODE
;
1179 cur
->version
= xmlStrdup(version
);
1180 if (cur
->version
== NULL
) {
1181 xmlTreeErrMemory("building doc");
1185 cur
->standalone
= -1;
1186 cur
->compression
= -1; /* not initialized */
1188 cur
->parseFlags
= 0;
1189 cur
->properties
= XML_DOC_USERBUILT
;
1191 * The in memory encoding is always UTF8
1192 * This field will never change and would
1193 * be obsolete if not for binary compatibility.
1195 cur
->charset
= XML_CHAR_ENCODING_UTF8
;
1197 if ((__xmlRegisterCallbacks
) && (xmlRegisterNodeDefaultValue
))
1198 xmlRegisterNodeDefaultValue((xmlNodePtr
)cur
);
1204 * @cur: pointer to the document
1206 * Free up all the structures used by a document, tree included.
1209 xmlFreeDoc(xmlDocPtr cur
) {
1210 xmlDtdPtr extSubset
, intSubset
;
1211 xmlDictPtr dict
= NULL
;
1215 xmlGenericError(xmlGenericErrorContext
,
1216 "xmlFreeDoc : document == NULL\n");
1220 #ifdef LIBXML_DEBUG_RUNTIME
1221 #ifdef LIBXML_DEBUG_ENABLED
1222 xmlDebugCheckDocument(stderr
, cur
);
1226 if (cur
!= NULL
) dict
= cur
->dict
;
1228 if ((__xmlRegisterCallbacks
) && (xmlDeregisterNodeDefaultValue
))
1229 xmlDeregisterNodeDefaultValue((xmlNodePtr
)cur
);
1232 * Do this before freeing the children list to avoid ID lookups
1234 if (cur
->ids
!= NULL
) xmlFreeIDTable((xmlIDTablePtr
) cur
->ids
);
1236 if (cur
->refs
!= NULL
) xmlFreeRefTable((xmlRefTablePtr
) cur
->refs
);
1238 extSubset
= cur
->extSubset
;
1239 intSubset
= cur
->intSubset
;
1240 if (intSubset
== extSubset
)
1242 if (extSubset
!= NULL
) {
1243 xmlUnlinkNode((xmlNodePtr
) cur
->extSubset
);
1244 cur
->extSubset
= NULL
;
1245 xmlFreeDtd(extSubset
);
1247 if (intSubset
!= NULL
) {
1248 xmlUnlinkNode((xmlNodePtr
) cur
->intSubset
);
1249 cur
->intSubset
= NULL
;
1250 xmlFreeDtd(intSubset
);
1253 if (cur
->children
!= NULL
) xmlFreeNodeList(cur
->children
);
1254 if (cur
->oldNs
!= NULL
) xmlFreeNsList(cur
->oldNs
);
1256 DICT_FREE(cur
->version
)
1257 DICT_FREE(cur
->name
)
1258 DICT_FREE(cur
->encoding
)
1261 if (dict
) xmlDictFree(dict
);
1265 * xmlStringLenGetNodeList:
1266 * @doc: the document
1267 * @value: the value of the text
1268 * @len: the length of the string value
1270 * Parse the value string and build the node list associated. Should
1271 * produce a flat tree with only TEXTs and ENTITY_REFs.
1272 * Returns a pointer to the first child
1275 xmlStringLenGetNodeList(const xmlDoc
*doc
, const xmlChar
*value
, int len
) {
1276 xmlNodePtr ret
= NULL
, last
= NULL
;
1279 const xmlChar
*cur
, *end
;
1284 if (value
== NULL
) return(NULL
);
1288 buf
= xmlBufCreateSize(0);
1289 if (buf
== NULL
) return(NULL
);
1290 xmlBufSetAllocationScheme(buf
, XML_BUFFER_ALLOC_HYBRID
);
1293 while ((cur
< end
) && (*cur
!= 0)) {
1294 if (cur
[0] == '&') {
1299 * Save the current text.
1302 if (xmlBufAdd(buf
, q
, cur
- q
))
1306 if ((cur
+ 2 < end
) && (cur
[1] == '#') && (cur
[2] == 'x')) {
1312 while (tmp
!= ';') { /* Non input consuming loop */
1314 * If you find an integer overflow here when fuzzing,
1315 * the bug is probably elsewhere. This function should
1316 * only receive entities that were already validated by
1317 * the parser, typically by xmlParseAttValueComplex
1318 * calling xmlStringDecodeEntities.
1320 * So it's better *not* to check for overflow to
1321 * potentially discover new bugs.
1323 if ((tmp
>= '0') && (tmp
<= '9'))
1324 charval
= charval
* 16 + (tmp
- '0');
1325 else if ((tmp
>= 'a') && (tmp
<= 'f'))
1326 charval
= charval
* 16 + (tmp
- 'a') + 10;
1327 else if ((tmp
>= 'A') && (tmp
<= 'F'))
1328 charval
= charval
* 16 + (tmp
- 'A') + 10;
1330 xmlTreeErr(XML_TREE_INVALID_HEX
, (xmlNodePtr
) doc
,
1344 } else if ((cur
+ 1 < end
) && (cur
[1] == '#')) {
1350 while (tmp
!= ';') { /* Non input consuming loops */
1351 /* Don't check for integer overflow, see above. */
1352 if ((tmp
>= '0') && (tmp
<= '9'))
1353 charval
= charval
* 10 + (tmp
- '0');
1355 xmlTreeErr(XML_TREE_INVALID_DEC
, (xmlNodePtr
) doc
,
1371 * Read the entity string
1375 while ((cur
< end
) && (*cur
!= 0) && (*cur
!= ';')) cur
++;
1376 if ((cur
>= end
) || (*cur
== 0)) {
1377 xmlTreeErr(XML_TREE_UNTERMINATED_ENTITY
, (xmlNodePtr
) doc
,
1383 * Predefined entities don't generate nodes
1385 val
= xmlStrndup(q
, cur
- q
);
1386 ent
= xmlGetDocEntity(doc
, val
);
1387 if ((ent
!= NULL
) &&
1388 (ent
->etype
== XML_INTERNAL_PREDEFINED_ENTITY
)) {
1390 if (xmlBufCat(buf
, ent
->content
))
1395 * Flush buffer so far
1397 if (!xmlBufIsEmpty(buf
)) {
1398 node
= xmlNewDocText(doc
, NULL
);
1400 if (val
!= NULL
) xmlFree(val
);
1403 node
->content
= xmlBufDetach(buf
);
1408 last
= xmlAddNextSibling(last
, node
);
1413 * Create a new REFERENCE_REF node
1415 node
= xmlNewReference(doc
, val
);
1417 if (val
!= NULL
) xmlFree(val
);
1420 else if ((ent
!= NULL
) && (ent
->children
== NULL
)) {
1423 /* Set to non-NULL value to avoid recursion. */
1424 ent
->children
= (xmlNodePtr
) -1;
1425 ent
->children
= xmlStringGetNodeList(doc
,
1426 (const xmlChar
*)node
->content
);
1428 temp
= ent
->children
;
1430 temp
->parent
= (xmlNodePtr
)ent
;
1438 last
= xmlAddNextSibling(last
, node
);
1450 l
= xmlCopyCharMultiByte(buffer
, charval
);
1453 if (xmlBufCat(buf
, buffer
))
1463 * Handle the last piece of text.
1465 if (xmlBufAdd(buf
, q
, cur
- q
))
1469 if (!xmlBufIsEmpty(buf
)) {
1470 node
= xmlNewDocText(doc
, NULL
);
1471 if (node
== NULL
) goto out
;
1472 node
->content
= xmlBufDetach(buf
);
1477 xmlAddNextSibling(last
, node
);
1479 } else if (ret
== NULL
) {
1480 ret
= xmlNewDocText(doc
, BAD_CAST
"");
1489 * xmlStringGetNodeList:
1490 * @doc: the document
1491 * @value: the value of the attribute
1493 * Parse the value string and build the node list associated. Should
1494 * produce a flat tree with only TEXTs and ENTITY_REFs.
1495 * Returns a pointer to the first child
1498 xmlStringGetNodeList(const xmlDoc
*doc
, const xmlChar
*value
) {
1499 xmlNodePtr ret
= NULL
, last
= NULL
;
1502 const xmlChar
*cur
= value
;
1507 if (value
== NULL
) return(NULL
);
1509 buf
= xmlBufCreateSize(0);
1510 if (buf
== NULL
) return(NULL
);
1511 xmlBufSetAllocationScheme(buf
, XML_BUFFER_ALLOC_HYBRID
);
1515 if (cur
[0] == '&') {
1520 * Save the current text.
1523 if (xmlBufAdd(buf
, q
, cur
- q
))
1527 if ((cur
[1] == '#') && (cur
[2] == 'x')) {
1530 while (tmp
!= ';') { /* Non input consuming loop */
1531 /* Don't check for integer overflow, see above. */
1532 if ((tmp
>= '0') && (tmp
<= '9'))
1533 charval
= charval
* 16 + (tmp
- '0');
1534 else if ((tmp
>= 'a') && (tmp
<= 'f'))
1535 charval
= charval
* 16 + (tmp
- 'a') + 10;
1536 else if ((tmp
>= 'A') && (tmp
<= 'F'))
1537 charval
= charval
* 16 + (tmp
- 'A') + 10;
1539 xmlTreeErr(XML_TREE_INVALID_HEX
, (xmlNodePtr
) doc
,
1550 } else if (cur
[1] == '#') {
1553 while (tmp
!= ';') { /* Non input consuming loops */
1554 /* Don't check for integer overflow, see above. */
1555 if ((tmp
>= '0') && (tmp
<= '9'))
1556 charval
= charval
* 10 + (tmp
- '0');
1558 xmlTreeErr(XML_TREE_INVALID_DEC
, (xmlNodePtr
) doc
,
1571 * Read the entity string
1575 while ((*cur
!= 0) && (*cur
!= ';')) cur
++;
1577 xmlTreeErr(XML_TREE_UNTERMINATED_ENTITY
,
1578 (xmlNodePtr
) doc
, (const char *) q
);
1583 * Predefined entities don't generate nodes
1585 val
= xmlStrndup(q
, cur
- q
);
1586 ent
= xmlGetDocEntity(doc
, val
);
1587 if ((ent
!= NULL
) &&
1588 (ent
->etype
== XML_INTERNAL_PREDEFINED_ENTITY
)) {
1590 if (xmlBufCat(buf
, ent
->content
))
1595 * Flush buffer so far
1597 if (!xmlBufIsEmpty(buf
)) {
1598 node
= xmlNewDocText(doc
, NULL
);
1600 if (val
!= NULL
) xmlFree(val
);
1603 node
->content
= xmlBufDetach(buf
);
1608 last
= xmlAddNextSibling(last
, node
);
1613 * Create a new REFERENCE_REF node
1615 node
= xmlNewReference(doc
, val
);
1617 if (val
!= NULL
) xmlFree(val
);
1620 else if ((ent
!= NULL
) && (ent
->children
== NULL
)) {
1623 /* Set to non-NULL value to avoid recursion. */
1624 ent
->children
= (xmlNodePtr
) -1;
1625 ent
->children
= xmlStringGetNodeList(doc
,
1626 (const xmlChar
*)node
->content
);
1628 temp
= ent
->children
;
1630 temp
->parent
= (xmlNodePtr
)ent
;
1638 last
= xmlAddNextSibling(last
, node
);
1650 len
= xmlCopyCharMultiByte(buffer
, charval
);
1653 if (xmlBufCat(buf
, buffer
))
1660 if ((cur
!= q
) || (ret
== NULL
)) {
1662 * Handle the last piece of text.
1664 xmlBufAdd(buf
, q
, cur
- q
);
1667 if (!xmlBufIsEmpty(buf
)) {
1668 node
= xmlNewDocText(doc
, NULL
);
1673 node
->content
= xmlBufDetach(buf
);
1678 xmlAddNextSibling(last
, node
);
1688 * xmlNodeListGetString:
1689 * @doc: the document
1690 * @list: a Node list
1691 * @inLine: should we replace entity contents or show their external form
1693 * Build the string equivalent to the text contained in the Node list
1694 * made of TEXTs and ENTITY_REFs
1696 * Returns a pointer to the string copy, the caller must free it with xmlFree().
1699 xmlNodeListGetString(xmlDocPtr doc
, const xmlNode
*list
, int inLine
)
1701 const xmlNode
*node
= list
;
1702 xmlChar
*ret
= NULL
;
1708 if ((list
->parent
!= NULL
) && (list
->parent
->type
== XML_ATTRIBUTE_NODE
))
1713 while (node
!= NULL
) {
1714 if ((node
->type
== XML_TEXT_NODE
) ||
1715 (node
->type
== XML_CDATA_SECTION_NODE
)) {
1717 ret
= xmlStrcat(ret
, node
->content
);
1722 buffer
= xmlEncodeAttributeEntities(doc
, node
->content
);
1724 buffer
= xmlEncodeEntitiesReentrant(doc
, node
->content
);
1725 if (buffer
!= NULL
) {
1726 ret
= xmlStrcat(ret
, buffer
);
1730 } else if (node
->type
== XML_ENTITY_REF_NODE
) {
1732 ent
= xmlGetDocEntity(doc
, node
->name
);
1736 /* an entity content can be any "well balanced chunk",
1737 * i.e. the result of the content [43] production:
1738 * http://www.w3.org/TR/REC-xml#NT-content.
1739 * So it can contain text, CDATA section or nested
1740 * entity reference nodes (among others).
1741 * -> we recursive call xmlNodeListGetString()
1742 * which handles these types */
1743 buffer
= xmlNodeListGetString(doc
, ent
->children
, 1);
1744 if (buffer
!= NULL
) {
1745 ret
= xmlStrcat(ret
, buffer
);
1749 ret
= xmlStrcat(ret
, node
->content
);
1756 ret
= xmlStrncat(ret
, buf
, 1);
1757 ret
= xmlStrcat(ret
, node
->name
);
1760 ret
= xmlStrncat(ret
, buf
, 1);
1765 xmlGenericError(xmlGenericErrorContext
,
1766 "xmlGetNodeListString : invalid node type %d\n",
1775 #ifdef LIBXML_TREE_ENABLED
1777 * xmlNodeListGetRawString:
1778 * @doc: the document
1779 * @list: a Node list
1780 * @inLine: should we replace entity contents or show their external form
1782 * Builds the string equivalent to the text contained in the Node list
1783 * made of TEXTs and ENTITY_REFs, contrary to xmlNodeListGetString()
1784 * this function doesn't do any character encoding handling.
1786 * Returns a pointer to the string copy, the caller must free it with xmlFree().
1789 xmlNodeListGetRawString(const xmlDoc
*doc
, const xmlNode
*list
, int inLine
)
1791 const xmlNode
*node
= list
;
1792 xmlChar
*ret
= NULL
;
1798 while (node
!= NULL
) {
1799 if ((node
->type
== XML_TEXT_NODE
) ||
1800 (node
->type
== XML_CDATA_SECTION_NODE
)) {
1802 ret
= xmlStrcat(ret
, node
->content
);
1806 buffer
= xmlEncodeSpecialChars(doc
, node
->content
);
1807 if (buffer
!= NULL
) {
1808 ret
= xmlStrcat(ret
, buffer
);
1812 } else if (node
->type
== XML_ENTITY_REF_NODE
) {
1814 ent
= xmlGetDocEntity(doc
, node
->name
);
1818 /* an entity content can be any "well balanced chunk",
1819 * i.e. the result of the content [43] production:
1820 * http://www.w3.org/TR/REC-xml#NT-content.
1821 * So it can contain text, CDATA section or nested
1822 * entity reference nodes (among others).
1823 * -> we recursive call xmlNodeListGetRawString()
1824 * which handles these types */
1826 xmlNodeListGetRawString(doc
, ent
->children
, 1);
1827 if (buffer
!= NULL
) {
1828 ret
= xmlStrcat(ret
, buffer
);
1832 ret
= xmlStrcat(ret
, node
->content
);
1839 ret
= xmlStrncat(ret
, buf
, 1);
1840 ret
= xmlStrcat(ret
, node
->name
);
1843 ret
= xmlStrncat(ret
, buf
, 1);
1848 xmlGenericError(xmlGenericErrorContext
,
1849 "xmlGetNodeListString : invalid node type %d\n",
1857 #endif /* LIBXML_TREE_ENABLED */
1860 xmlNewPropInternal(xmlNodePtr node
, xmlNsPtr ns
,
1861 const xmlChar
* name
, const xmlChar
* value
,
1865 xmlDocPtr doc
= NULL
;
1867 if ((node
!= NULL
) && (node
->type
!= XML_ELEMENT_NODE
)) {
1868 if ((eatname
== 1) &&
1869 ((node
->doc
== NULL
) ||
1870 (!(xmlDictOwns(node
->doc
->dict
, name
)))))
1871 xmlFree((xmlChar
*) name
);
1876 * Allocate a new property and fill the fields.
1878 cur
= (xmlAttrPtr
) xmlMalloc(sizeof(xmlAttr
));
1880 if ((eatname
== 1) &&
1881 ((node
== NULL
) || (node
->doc
== NULL
) ||
1882 (!(xmlDictOwns(node
->doc
->dict
, name
)))))
1883 xmlFree((xmlChar
*) name
);
1884 xmlTreeErrMemory("building attribute");
1887 memset(cur
, 0, sizeof(xmlAttr
));
1888 cur
->type
= XML_ATTRIBUTE_NODE
;
1898 if ((doc
!= NULL
) && (doc
->dict
!= NULL
))
1899 cur
->name
= (xmlChar
*) xmlDictLookup(doc
->dict
, name
, -1);
1901 cur
->name
= xmlStrdup(name
);
1905 if (value
!= NULL
) {
1908 cur
->children
= xmlNewDocText(doc
, value
);
1910 tmp
= cur
->children
;
1911 while (tmp
!= NULL
) {
1912 tmp
->parent
= (xmlNodePtr
) cur
;
1913 if (tmp
->next
== NULL
)
1920 * Add it at the end to preserve parsing order ...
1923 if (node
->properties
== NULL
) {
1924 node
->properties
= cur
;
1926 xmlAttrPtr prev
= node
->properties
;
1928 while (prev
->next
!= NULL
)
1935 if ((value
!= NULL
) && (node
!= NULL
) &&
1936 (xmlIsID(node
->doc
, node
, cur
) == 1))
1937 xmlAddID(NULL
, node
->doc
, value
, cur
);
1939 if ((__xmlRegisterCallbacks
) && (xmlRegisterNodeDefaultValue
))
1940 xmlRegisterNodeDefaultValue((xmlNodePtr
) cur
);
1944 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_HTML_ENABLED) || \
1945 defined(LIBXML_SCHEMAS_ENABLED)
1948 * @node: the holding node
1949 * @name: the name of the attribute
1950 * @value: the value of the attribute
1952 * Create a new property carried by a node.
1953 * Returns a pointer to the attribute
1956 xmlNewProp(xmlNodePtr node
, const xmlChar
*name
, const xmlChar
*value
) {
1960 xmlGenericError(xmlGenericErrorContext
,
1961 "xmlNewProp : name == NULL\n");
1966 return xmlNewPropInternal(node
, NULL
, name
, value
, 0);
1968 #endif /* LIBXML_TREE_ENABLED */
1972 * @node: the holding node
1973 * @ns: the namespace
1974 * @name: the name of the attribute
1975 * @value: the value of the attribute
1977 * Create a new property tagged with a namespace and carried by a node.
1978 * Returns a pointer to the attribute
1981 xmlNewNsProp(xmlNodePtr node
, xmlNsPtr ns
, const xmlChar
*name
,
1982 const xmlChar
*value
) {
1986 xmlGenericError(xmlGenericErrorContext
,
1987 "xmlNewNsProp : name == NULL\n");
1992 return xmlNewPropInternal(node
, ns
, name
, value
, 0);
1996 * xmlNewNsPropEatName:
1997 * @node: the holding node
1998 * @ns: the namespace
1999 * @name: the name of the attribute
2000 * @value: the value of the attribute
2002 * Create a new property tagged with a namespace and carried by a node.
2003 * Returns a pointer to the attribute
2006 xmlNewNsPropEatName(xmlNodePtr node
, xmlNsPtr ns
, xmlChar
*name
,
2007 const xmlChar
*value
) {
2011 xmlGenericError(xmlGenericErrorContext
,
2012 "xmlNewNsPropEatName : name == NULL\n");
2017 return xmlNewPropInternal(node
, ns
, name
, value
, 1);
2022 * @doc: the document
2023 * @name: the name of the attribute
2024 * @value: the value of the attribute
2026 * Create a new property carried by a document.
2027 * NOTE: @value is supposed to be a piece of XML CDATA, so it allows entity
2028 * references, but XML special chars need to be escaped first by using
2029 * xmlEncodeEntitiesReentrant(). Use xmlNewProp() if you don't need
2032 * Returns a pointer to the attribute
2035 xmlNewDocProp(xmlDocPtr doc
, const xmlChar
*name
, const xmlChar
*value
) {
2040 xmlGenericError(xmlGenericErrorContext
,
2041 "xmlNewDocProp : name == NULL\n");
2047 * Allocate a new property and fill the fields.
2049 cur
= (xmlAttrPtr
) xmlMalloc(sizeof(xmlAttr
));
2051 xmlTreeErrMemory("building attribute");
2054 memset(cur
, 0, sizeof(xmlAttr
));
2055 cur
->type
= XML_ATTRIBUTE_NODE
;
2057 if ((doc
!= NULL
) && (doc
->dict
!= NULL
))
2058 cur
->name
= xmlDictLookup(doc
->dict
, name
, -1);
2060 cur
->name
= xmlStrdup(name
);
2062 if (value
!= NULL
) {
2065 cur
->children
= xmlStringGetNodeList(doc
, value
);
2068 tmp
= cur
->children
;
2069 while (tmp
!= NULL
) {
2070 tmp
->parent
= (xmlNodePtr
) cur
;
2071 if (tmp
->next
== NULL
)
2077 if ((__xmlRegisterCallbacks
) && (xmlRegisterNodeDefaultValue
))
2078 xmlRegisterNodeDefaultValue((xmlNodePtr
)cur
);
2084 * @cur: the first property in the list
2086 * Free a property and all its siblings, all the children are freed too.
2089 xmlFreePropList(xmlAttrPtr cur
) {
2091 if (cur
== NULL
) return;
2092 while (cur
!= NULL
) {
2101 * @cur: an attribute
2103 * Free one attribute, all the content is freed too
2106 xmlFreeProp(xmlAttrPtr cur
) {
2107 xmlDictPtr dict
= NULL
;
2108 if (cur
== NULL
) return;
2110 if (cur
->doc
!= NULL
) dict
= cur
->doc
->dict
;
2112 if ((__xmlRegisterCallbacks
) && (xmlDeregisterNodeDefaultValue
))
2113 xmlDeregisterNodeDefaultValue((xmlNodePtr
)cur
);
2115 /* Check for ID removal -> leading to invalid references ! */
2116 if ((cur
->doc
!= NULL
) && (cur
->atype
== XML_ATTRIBUTE_ID
)) {
2117 xmlRemoveID(cur
->doc
, cur
);
2119 if (cur
->children
!= NULL
) xmlFreeNodeList(cur
->children
);
2120 DICT_FREE(cur
->name
)
2126 * @cur: an attribute
2128 * Unlink and free one attribute, all the content is freed too
2129 * Note this doesn't work for namespace definition attributes
2131 * Returns 0 if success and -1 in case of error.
2134 xmlRemoveProp(xmlAttrPtr cur
) {
2138 xmlGenericError(xmlGenericErrorContext
,
2139 "xmlRemoveProp : cur == NULL\n");
2143 if (cur
->parent
== NULL
) {
2145 xmlGenericError(xmlGenericErrorContext
,
2146 "xmlRemoveProp : cur->parent == NULL\n");
2150 tmp
= cur
->parent
->properties
;
2152 cur
->parent
->properties
= cur
->next
;
2153 if (cur
->next
!= NULL
)
2154 cur
->next
->prev
= NULL
;
2158 while (tmp
!= NULL
) {
2159 if (tmp
->next
== cur
) {
2160 tmp
->next
= cur
->next
;
2161 if (tmp
->next
!= NULL
)
2162 tmp
->next
->prev
= tmp
;
2169 xmlGenericError(xmlGenericErrorContext
,
2170 "xmlRemoveProp : attribute not owned by its node\n");
2177 * @doc: the target document
2178 * @name: the processing instruction name
2179 * @content: the PI content
2181 * Creation of a processing instruction element.
2182 * Returns a pointer to the new node object.
2185 xmlNewDocPI(xmlDocPtr doc
, const xmlChar
*name
, const xmlChar
*content
) {
2190 xmlGenericError(xmlGenericErrorContext
,
2191 "xmlNewPI : name == NULL\n");
2197 * Allocate a new node and fill the fields.
2199 cur
= (xmlNodePtr
) xmlMalloc(sizeof(xmlNode
));
2201 xmlTreeErrMemory("building PI");
2204 memset(cur
, 0, sizeof(xmlNode
));
2205 cur
->type
= XML_PI_NODE
;
2207 if ((doc
!= NULL
) && (doc
->dict
!= NULL
))
2208 cur
->name
= xmlDictLookup(doc
->dict
, name
, -1);
2210 cur
->name
= xmlStrdup(name
);
2211 if (content
!= NULL
) {
2212 cur
->content
= xmlStrdup(content
);
2216 if ((__xmlRegisterCallbacks
) && (xmlRegisterNodeDefaultValue
))
2217 xmlRegisterNodeDefaultValue((xmlNodePtr
)cur
);
2223 * @name: the processing instruction name
2224 * @content: the PI content
2226 * Creation of a processing instruction element.
2227 * Use xmlDocNewPI preferably to get string interning
2229 * Returns a pointer to the new node object.
2232 xmlNewPI(const xmlChar
*name
, const xmlChar
*content
) {
2233 return(xmlNewDocPI(NULL
, name
, content
));
2238 * @ns: namespace if any
2239 * @name: the node name
2241 * Creation of a new node element. @ns is optional (NULL).
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 * Returns a pointer to the new node object, with pointer @name as
2285 * new node's name. Use xmlNewNode() if a copy of @name string is
2286 * is needed as new node's name.
2289 xmlNewNodeEatName(xmlNsPtr ns
, xmlChar
*name
) {
2294 xmlGenericError(xmlGenericErrorContext
,
2295 "xmlNewNode : name == NULL\n");
2301 * Allocate a new node and fill the fields.
2303 cur
= (xmlNodePtr
) xmlMalloc(sizeof(xmlNode
));
2305 xmlTreeErrMemory("building node");
2306 /* we can't check here that name comes from the doc dictionary */
2309 memset(cur
, 0, sizeof(xmlNode
));
2310 cur
->type
= XML_ELEMENT_NODE
;
2315 if ((__xmlRegisterCallbacks
) && (xmlRegisterNodeDefaultValue
))
2316 xmlRegisterNodeDefaultValue((xmlNodePtr
)cur
);
2322 * @doc: the document
2323 * @ns: namespace if any
2324 * @name: the node name
2325 * @content: the XML text content if any
2327 * Creation of a new node element within a document. @ns and @content
2328 * are optional (NULL).
2329 * NOTE: @content is supposed to be a piece of XML CDATA, so it allow entities
2330 * references, but XML special chars need to be escaped first by using
2331 * xmlEncodeEntitiesReentrant(). Use xmlNewDocRawNode() if you don't
2332 * need entities support.
2334 * Returns a pointer to the new node object.
2337 xmlNewDocNode(xmlDocPtr doc
, xmlNsPtr ns
,
2338 const xmlChar
*name
, const xmlChar
*content
) {
2341 if ((doc
!= NULL
) && (doc
->dict
!= NULL
))
2342 cur
= xmlNewNodeEatName(ns
, (xmlChar
*)
2343 xmlDictLookup(doc
->dict
, name
, -1));
2345 cur
= xmlNewNode(ns
, name
);
2348 if (content
!= NULL
) {
2349 cur
->children
= xmlStringGetNodeList(doc
, content
);
2350 UPDATE_LAST_CHILD_AND_PARENT(cur
)
2358 * xmlNewDocNodeEatName:
2359 * @doc: the document
2360 * @ns: namespace if any
2361 * @name: the node name
2362 * @content: the XML text content if any
2364 * Creation of a new node element within a document. @ns and @content
2365 * are optional (NULL).
2366 * NOTE: @content is supposed to be a piece of XML CDATA, so it allow entities
2367 * references, but XML special chars need to be escaped first by using
2368 * xmlEncodeEntitiesReentrant(). Use xmlNewDocRawNode() if you don't
2369 * need entities support.
2371 * Returns a pointer to the new node object.
2374 xmlNewDocNodeEatName(xmlDocPtr doc
, xmlNsPtr ns
,
2375 xmlChar
*name
, const xmlChar
*content
) {
2378 cur
= xmlNewNodeEatName(ns
, name
);
2381 if (content
!= NULL
) {
2382 cur
->children
= xmlStringGetNodeList(doc
, content
);
2383 UPDATE_LAST_CHILD_AND_PARENT(cur
)
2386 /* if name don't come from the doc dictionary free it here */
2387 if ((name
!= NULL
) && (doc
!= NULL
) &&
2388 (!(xmlDictOwns(doc
->dict
, name
))))
2394 #ifdef LIBXML_TREE_ENABLED
2397 * @doc: the document
2398 * @ns: namespace if any
2399 * @name: the node name
2400 * @content: the text content if any
2402 * Creation of a new node element within a document. @ns and @content
2403 * are optional (NULL).
2405 * Returns a pointer to the new node object.
2408 xmlNewDocRawNode(xmlDocPtr doc
, xmlNsPtr ns
,
2409 const xmlChar
*name
, const xmlChar
*content
) {
2412 cur
= xmlNewDocNode(doc
, ns
, name
, NULL
);
2415 if (content
!= NULL
) {
2416 cur
->children
= xmlNewDocText(doc
, content
);
2417 UPDATE_LAST_CHILD_AND_PARENT(cur
)
2424 * xmlNewDocFragment:
2425 * @doc: the document owning the fragment
2427 * Creation of a new Fragment node.
2428 * Returns a pointer to the new node object.
2431 xmlNewDocFragment(xmlDocPtr doc
) {
2435 * Allocate a new DocumentFragment node and fill the fields.
2437 cur
= (xmlNodePtr
) xmlMalloc(sizeof(xmlNode
));
2439 xmlTreeErrMemory("building fragment");
2442 memset(cur
, 0, sizeof(xmlNode
));
2443 cur
->type
= XML_DOCUMENT_FRAG_NODE
;
2447 if ((__xmlRegisterCallbacks
) && (xmlRegisterNodeDefaultValue
))
2448 xmlRegisterNodeDefaultValue(cur
);
2451 #endif /* LIBXML_TREE_ENABLED */
2455 * @content: the text content
2457 * Creation of a new text node.
2458 * Returns a pointer to the new node object.
2461 xmlNewText(const xmlChar
*content
) {
2465 * Allocate a new node and fill the fields.
2467 cur
= (xmlNodePtr
) xmlMalloc(sizeof(xmlNode
));
2469 xmlTreeErrMemory("building text");
2472 memset(cur
, 0, sizeof(xmlNode
));
2473 cur
->type
= XML_TEXT_NODE
;
2475 cur
->name
= xmlStringText
;
2476 if (content
!= NULL
) {
2477 cur
->content
= xmlStrdup(content
);
2480 if ((__xmlRegisterCallbacks
) && (xmlRegisterNodeDefaultValue
))
2481 xmlRegisterNodeDefaultValue(cur
);
2485 #ifdef LIBXML_TREE_ENABLED
2488 * @parent: the parent node
2489 * @ns: a namespace if any
2490 * @name: the name of the child
2491 * @content: the text content of the child if any.
2493 * Creation of a new child element, added at the end of @parent children list.
2494 * @ns and @content parameters are optional (NULL). If @ns is NULL, the newly
2495 * created element inherits the namespace of @parent. If @content is non NULL,
2496 * a child TEXT node will be created containing the string @content.
2497 * NOTE: Use xmlNewChild() if @content will contain entities that need to be
2498 * preserved. Use this function, xmlNewTextChild(), if you need to ensure that
2499 * reserved XML chars that might appear in @content, such as the ampersand,
2500 * greater-than or less-than signs, are automatically replaced by their XML
2501 * escaped entity representations.
2503 * Returns a pointer to the new node object.
2506 xmlNewTextChild(xmlNodePtr parent
, xmlNsPtr ns
,
2507 const xmlChar
*name
, const xmlChar
*content
) {
2508 xmlNodePtr cur
, prev
;
2510 if (parent
== NULL
) {
2512 xmlGenericError(xmlGenericErrorContext
,
2513 "xmlNewTextChild : parent == NULL\n");
2520 xmlGenericError(xmlGenericErrorContext
,
2521 "xmlNewTextChild : name == NULL\n");
2527 * Allocate a new node
2529 if (parent
->type
== XML_ELEMENT_NODE
) {
2531 cur
= xmlNewDocRawNode(parent
->doc
, parent
->ns
, name
, content
);
2533 cur
= xmlNewDocRawNode(parent
->doc
, ns
, name
, content
);
2534 } else if ((parent
->type
== XML_DOCUMENT_NODE
) ||
2535 (parent
->type
== XML_HTML_DOCUMENT_NODE
)) {
2537 cur
= xmlNewDocRawNode((xmlDocPtr
) parent
, NULL
, name
, content
);
2539 cur
= xmlNewDocRawNode((xmlDocPtr
) parent
, ns
, name
, content
);
2540 } else if (parent
->type
== XML_DOCUMENT_FRAG_NODE
) {
2541 cur
= xmlNewDocRawNode( parent
->doc
, ns
, name
, content
);
2545 if (cur
== NULL
) return(NULL
);
2548 * add the new element at the end of the children list.
2550 cur
->type
= XML_ELEMENT_NODE
;
2551 cur
->parent
= parent
;
2552 cur
->doc
= parent
->doc
;
2553 if (parent
->children
== NULL
) {
2554 parent
->children
= cur
;
2557 prev
= parent
->last
;
2565 #endif /* LIBXML_TREE_ENABLED */
2569 * @doc: the document
2570 * @name: the char ref string, starting with # or "&# ... ;"
2572 * Creation of a new character reference node.
2573 * Returns a pointer to the new node object.
2576 xmlNewCharRef(xmlDocPtr doc
, const xmlChar
*name
) {
2583 * Allocate a new node and fill the fields.
2585 cur
= (xmlNodePtr
) xmlMalloc(sizeof(xmlNode
));
2587 xmlTreeErrMemory("building character reference");
2590 memset(cur
, 0, sizeof(xmlNode
));
2591 cur
->type
= XML_ENTITY_REF_NODE
;
2594 if (name
[0] == '&') {
2597 len
= xmlStrlen(name
);
2598 if (name
[len
- 1] == ';')
2599 cur
->name
= xmlStrndup(name
, len
- 1);
2601 cur
->name
= xmlStrndup(name
, len
);
2603 cur
->name
= xmlStrdup(name
);
2605 if ((__xmlRegisterCallbacks
) && (xmlRegisterNodeDefaultValue
))
2606 xmlRegisterNodeDefaultValue(cur
);
2612 * @doc: the document
2613 * @name: the reference name, or the reference string with & and ;
2615 * Creation of a new reference node.
2616 * Returns a pointer to the new node object.
2619 xmlNewReference(const xmlDoc
*doc
, const xmlChar
*name
) {
2627 * Allocate a new node and fill the fields.
2629 cur
= (xmlNodePtr
) xmlMalloc(sizeof(xmlNode
));
2631 xmlTreeErrMemory("building reference");
2634 memset(cur
, 0, sizeof(xmlNode
));
2635 cur
->type
= XML_ENTITY_REF_NODE
;
2637 cur
->doc
= (xmlDoc
*)doc
;
2638 if (name
[0] == '&') {
2641 len
= xmlStrlen(name
);
2642 if (name
[len
- 1] == ';')
2643 cur
->name
= xmlStrndup(name
, len
- 1);
2645 cur
->name
= xmlStrndup(name
, len
);
2647 cur
->name
= xmlStrdup(name
);
2649 ent
= xmlGetDocEntity(doc
, cur
->name
);
2651 cur
->content
= ent
->content
;
2653 * The parent pointer in entity is a DTD pointer and thus is NOT
2654 * updated. Not sure if this is 100% correct.
2657 cur
->children
= (xmlNodePtr
) ent
;
2658 cur
->last
= (xmlNodePtr
) ent
;
2661 if ((__xmlRegisterCallbacks
) && (xmlRegisterNodeDefaultValue
))
2662 xmlRegisterNodeDefaultValue(cur
);
2668 * @doc: the document
2669 * @content: the text content
2671 * Creation of a new text node within a document.
2672 * Returns a pointer to the new node object.
2675 xmlNewDocText(const xmlDoc
*doc
, const xmlChar
*content
) {
2678 cur
= xmlNewText(content
);
2679 if (cur
!= NULL
) cur
->doc
= (xmlDoc
*)doc
;
2685 * @content: the text content
2686 * @len: the text len.
2688 * Creation of a new text node with an extra parameter for the content's length
2689 * Returns a pointer to the new node object.
2692 xmlNewTextLen(const xmlChar
*content
, int len
) {
2696 * Allocate a new node and fill the fields.
2698 cur
= (xmlNodePtr
) xmlMalloc(sizeof(xmlNode
));
2700 xmlTreeErrMemory("building text");
2703 memset(cur
, 0, sizeof(xmlNode
));
2704 cur
->type
= XML_TEXT_NODE
;
2706 cur
->name
= xmlStringText
;
2707 if (content
!= NULL
) {
2708 cur
->content
= xmlStrndup(content
, len
);
2711 if ((__xmlRegisterCallbacks
) && (xmlRegisterNodeDefaultValue
))
2712 xmlRegisterNodeDefaultValue(cur
);
2718 * @doc: the document
2719 * @content: the text content
2720 * @len: the text len.
2722 * Creation of a new text node with an extra content length parameter. The
2723 * text node pertain to a given document.
2724 * Returns a pointer to the new node object.
2727 xmlNewDocTextLen(xmlDocPtr doc
, const xmlChar
*content
, int len
) {
2730 cur
= xmlNewTextLen(content
, len
);
2731 if (cur
!= NULL
) cur
->doc
= doc
;
2737 * @content: the comment content
2739 * Creation of a new node containing a comment.
2740 * Returns a pointer to the new node object.
2743 xmlNewComment(const xmlChar
*content
) {
2747 * Allocate a new node and fill the fields.
2749 cur
= (xmlNodePtr
) xmlMalloc(sizeof(xmlNode
));
2751 xmlTreeErrMemory("building comment");
2754 memset(cur
, 0, sizeof(xmlNode
));
2755 cur
->type
= XML_COMMENT_NODE
;
2757 cur
->name
= xmlStringComment
;
2758 if (content
!= NULL
) {
2759 cur
->content
= xmlStrdup(content
);
2762 if ((__xmlRegisterCallbacks
) && (xmlRegisterNodeDefaultValue
))
2763 xmlRegisterNodeDefaultValue(cur
);
2769 * @doc: the document
2770 * @content: the CDATA block content content
2771 * @len: the length of the block
2773 * Creation of a new node containing a CDATA block.
2774 * Returns a pointer to the new node object.
2777 xmlNewCDataBlock(xmlDocPtr doc
, const xmlChar
*content
, int len
) {
2781 * Allocate a new node and fill the fields.
2783 cur
= (xmlNodePtr
) xmlMalloc(sizeof(xmlNode
));
2785 xmlTreeErrMemory("building CDATA");
2788 memset(cur
, 0, sizeof(xmlNode
));
2789 cur
->type
= XML_CDATA_SECTION_NODE
;
2792 if (content
!= NULL
) {
2793 cur
->content
= xmlStrndup(content
, len
);
2796 if ((__xmlRegisterCallbacks
) && (xmlRegisterNodeDefaultValue
))
2797 xmlRegisterNodeDefaultValue(cur
);
2803 * @doc: the document
2804 * @content: the comment content
2806 * Creation of a new node containing a comment within a document.
2807 * Returns a pointer to the new node object.
2810 xmlNewDocComment(xmlDocPtr doc
, const xmlChar
*content
) {
2813 cur
= xmlNewComment(content
);
2814 if (cur
!= NULL
) cur
->doc
= doc
;
2820 * @tree: the top element
2821 * @doc: the document
2823 * update all nodes under the tree to point to the right document
2826 xmlSetTreeDoc(xmlNodePtr tree
, xmlDocPtr doc
) {
2829 if ((tree
== NULL
) || (tree
->type
== XML_NAMESPACE_DECL
))
2831 if (tree
->doc
!= doc
) {
2832 if(tree
->type
== XML_ELEMENT_NODE
) {
2833 prop
= tree
->properties
;
2834 while (prop
!= NULL
) {
2835 if (prop
->atype
== XML_ATTRIBUTE_ID
) {
2836 xmlRemoveID(tree
->doc
, prop
);
2840 xmlSetListDoc(prop
->children
, doc
);
2843 * TODO: ID attributes should be also added to the new
2844 * document, but this breaks things like xmlReplaceNode.
2845 * The underlying problem is that xmlRemoveID is only called
2846 * if a node is destroyed, not if it's unlinked.
2849 if (xmlIsID(doc
, tree
, prop
)) {
2850 xmlChar
*idVal
= xmlNodeListGetString(doc
, prop
->children
,
2852 xmlAddID(NULL
, doc
, idVal
, prop
);
2859 if (tree
->type
== XML_ENTITY_REF_NODE
) {
2861 * Clear 'children' which points to the entity declaration
2862 * from the original document.
2864 tree
->children
= NULL
;
2865 } else if (tree
->children
!= NULL
) {
2866 xmlSetListDoc(tree
->children
, doc
);
2874 * @list: the first element
2875 * @doc: the document
2877 * update all nodes in the list to point to the right document
2880 xmlSetListDoc(xmlNodePtr list
, xmlDocPtr doc
) {
2883 if ((list
== NULL
) || (list
->type
== XML_NAMESPACE_DECL
))
2886 while (cur
!= NULL
) {
2887 if (cur
->doc
!= doc
)
2888 xmlSetTreeDoc(cur
, doc
);
2893 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
2896 * @parent: the parent node
2897 * @ns: a namespace if any
2898 * @name: the name of the child
2899 * @content: the XML content of the child if any.
2901 * Creation of a new child element, added at the end of @parent children list.
2902 * @ns and @content parameters are optional (NULL). If @ns is NULL, the newly
2903 * created element inherits the namespace of @parent. If @content is non NULL,
2904 * a child list containing the TEXTs and ENTITY_REFs node will be created.
2905 * NOTE: @content is supposed to be a piece of XML CDATA, so it allows entity
2906 * references. XML special chars must be escaped first by using
2907 * xmlEncodeEntitiesReentrant(), or xmlNewTextChild() should be used.
2909 * Returns a pointer to the new node object.
2912 xmlNewChild(xmlNodePtr parent
, xmlNsPtr ns
,
2913 const xmlChar
*name
, const xmlChar
*content
) {
2914 xmlNodePtr cur
, prev
;
2916 if (parent
== NULL
) {
2918 xmlGenericError(xmlGenericErrorContext
,
2919 "xmlNewChild : parent == NULL\n");
2926 xmlGenericError(xmlGenericErrorContext
,
2927 "xmlNewChild : name == NULL\n");
2933 * Allocate a new node
2935 if (parent
->type
== XML_ELEMENT_NODE
) {
2937 cur
= xmlNewDocNode(parent
->doc
, parent
->ns
, name
, content
);
2939 cur
= xmlNewDocNode(parent
->doc
, ns
, name
, content
);
2940 } else if ((parent
->type
== XML_DOCUMENT_NODE
) ||
2941 (parent
->type
== XML_HTML_DOCUMENT_NODE
)) {
2943 cur
= xmlNewDocNode((xmlDocPtr
) parent
, NULL
, name
, content
);
2945 cur
= xmlNewDocNode((xmlDocPtr
) parent
, ns
, name
, content
);
2946 } else if (parent
->type
== XML_DOCUMENT_FRAG_NODE
) {
2947 cur
= xmlNewDocNode( parent
->doc
, ns
, name
, content
);
2951 if (cur
== NULL
) return(NULL
);
2954 * add the new element at the end of the children list.
2956 cur
->type
= XML_ELEMENT_NODE
;
2957 cur
->parent
= parent
;
2958 cur
->doc
= parent
->doc
;
2959 if (parent
->children
== NULL
) {
2960 parent
->children
= cur
;
2963 prev
= parent
->last
;
2971 #endif /* LIBXML_TREE_ENABLED */
2974 * xmlAddPropSibling:
2975 * @prev: the attribute to which @prop is added after
2976 * @cur: the base attribute passed to calling function
2977 * @prop: the new attribute
2979 * Add a new attribute after @prev using @cur as base attribute.
2980 * When inserting before @cur, @prev is passed as @cur->prev.
2981 * When inserting after @cur, @prev is passed as @cur.
2982 * If an existing attribute is found it is destroyed prior to adding @prop.
2984 * Returns the attribute being inserted or NULL in case of error.
2987 xmlAddPropSibling(xmlNodePtr prev
, xmlNodePtr cur
, xmlNodePtr prop
) {
2990 if ((cur
== NULL
) || (cur
->type
!= XML_ATTRIBUTE_NODE
) ||
2991 (prop
== NULL
) || (prop
->type
!= XML_ATTRIBUTE_NODE
) ||
2992 ((prev
!= NULL
) && (prev
->type
!= XML_ATTRIBUTE_NODE
)))
2995 /* check if an attribute with the same name exists */
2996 if (prop
->ns
== NULL
)
2997 attr
= xmlHasNsProp(cur
->parent
, prop
->name
, NULL
);
2999 attr
= xmlHasNsProp(cur
->parent
, prop
->name
, prop
->ns
->href
);
3001 if (prop
->doc
!= cur
->doc
) {
3002 xmlSetTreeDoc(prop
, cur
->doc
);
3004 prop
->parent
= cur
->parent
;
3007 prop
->next
= prev
->next
;
3010 prop
->next
->prev
= prop
;
3015 if (prop
->prev
== NULL
&& prop
->parent
!= NULL
)
3016 prop
->parent
->properties
= (xmlAttrPtr
) prop
;
3017 if ((attr
!= NULL
) && (attr
->type
!= XML_ATTRIBUTE_DECL
)) {
3018 /* different instance, destroy it (attributes must be unique) */
3019 xmlRemoveProp((xmlAttrPtr
) attr
);
3025 * xmlAddNextSibling:
3026 * @cur: the child node
3027 * @elem: the new node
3029 * Add a new node @elem as the next sibling of @cur
3030 * If the new node was already inserted in a document it is
3031 * first unlinked from its existing context.
3032 * As a result of text merging @elem may be freed.
3033 * If the new node is ATTRIBUTE, it is added into properties instead of children.
3034 * If there is an attribute with equal name, it is first destroyed.
3036 * Returns the new node or NULL in case of error.
3039 xmlAddNextSibling(xmlNodePtr cur
, xmlNodePtr elem
) {
3040 if ((cur
== NULL
) || (cur
->type
== XML_NAMESPACE_DECL
)) {
3042 xmlGenericError(xmlGenericErrorContext
,
3043 "xmlAddNextSibling : cur == NULL\n");
3047 if ((elem
== NULL
) || (elem
->type
== XML_NAMESPACE_DECL
)) {
3049 xmlGenericError(xmlGenericErrorContext
,
3050 "xmlAddNextSibling : elem == NULL\n");
3057 xmlGenericError(xmlGenericErrorContext
,
3058 "xmlAddNextSibling : cur == elem\n");
3063 xmlUnlinkNode(elem
);
3065 if (elem
->type
== XML_TEXT_NODE
) {
3066 if (cur
->type
== XML_TEXT_NODE
) {
3067 xmlNodeAddContent(cur
, elem
->content
);
3071 if ((cur
->next
!= NULL
) && (cur
->next
->type
== XML_TEXT_NODE
) &&
3072 (cur
->name
== cur
->next
->name
)) {
3075 tmp
= xmlStrdup(elem
->content
);
3076 tmp
= xmlStrcat(tmp
, cur
->next
->content
);
3077 xmlNodeSetContent(cur
->next
, tmp
);
3082 } else if (elem
->type
== XML_ATTRIBUTE_NODE
) {
3083 return xmlAddPropSibling(cur
, cur
, elem
);
3086 if (elem
->doc
!= cur
->doc
) {
3087 xmlSetTreeDoc(elem
, cur
->doc
);
3089 elem
->parent
= cur
->parent
;
3091 elem
->next
= cur
->next
;
3093 if (elem
->next
!= NULL
)
3094 elem
->next
->prev
= elem
;
3095 if ((elem
->parent
!= NULL
) && (elem
->parent
->last
== cur
))
3096 elem
->parent
->last
= elem
;
3100 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_HTML_ENABLED) || \
3101 defined(LIBXML_SCHEMAS_ENABLED) || defined(LIBXML_XINCLUDE_ENABLED)
3103 * xmlAddPrevSibling:
3104 * @cur: the child node
3105 * @elem: the new node
3107 * Add a new node @elem as the previous sibling of @cur
3108 * merging adjacent TEXT nodes (@elem may be freed)
3109 * If the new node was already inserted in a document it is
3110 * first unlinked from its existing context.
3111 * If the new node is ATTRIBUTE, it is added into properties instead of children.
3112 * If there is an attribute with equal name, it is first destroyed.
3114 * Returns the new node or NULL in case of error.
3117 xmlAddPrevSibling(xmlNodePtr cur
, xmlNodePtr elem
) {
3118 if ((cur
== NULL
) || (cur
->type
== XML_NAMESPACE_DECL
)) {
3120 xmlGenericError(xmlGenericErrorContext
,
3121 "xmlAddPrevSibling : cur == NULL\n");
3125 if ((elem
== NULL
) || (elem
->type
== XML_NAMESPACE_DECL
)) {
3127 xmlGenericError(xmlGenericErrorContext
,
3128 "xmlAddPrevSibling : elem == NULL\n");
3135 xmlGenericError(xmlGenericErrorContext
,
3136 "xmlAddPrevSibling : cur == elem\n");
3141 xmlUnlinkNode(elem
);
3143 if (elem
->type
== XML_TEXT_NODE
) {
3144 if (cur
->type
== XML_TEXT_NODE
) {
3147 tmp
= xmlStrdup(elem
->content
);
3148 tmp
= xmlStrcat(tmp
, cur
->content
);
3149 xmlNodeSetContent(cur
, tmp
);
3154 if ((cur
->prev
!= NULL
) && (cur
->prev
->type
== XML_TEXT_NODE
) &&
3155 (cur
->name
== cur
->prev
->name
)) {
3156 xmlNodeAddContent(cur
->prev
, elem
->content
);
3160 } else if (elem
->type
== XML_ATTRIBUTE_NODE
) {
3161 return xmlAddPropSibling(cur
->prev
, cur
, elem
);
3164 if (elem
->doc
!= cur
->doc
) {
3165 xmlSetTreeDoc(elem
, cur
->doc
);
3167 elem
->parent
= cur
->parent
;
3169 elem
->prev
= cur
->prev
;
3171 if (elem
->prev
!= NULL
)
3172 elem
->prev
->next
= elem
;
3173 if ((elem
->parent
!= NULL
) && (elem
->parent
->children
== cur
)) {
3174 elem
->parent
->children
= elem
;
3178 #endif /* LIBXML_TREE_ENABLED */
3182 * @cur: the child node
3183 * @elem: the new node
3185 * Add a new element @elem to the list of siblings of @cur
3186 * merging adjacent TEXT nodes (@elem may be freed)
3187 * If the new element was already inserted in a document it is
3188 * first unlinked from its existing context.
3190 * Returns the new element or NULL in case of error.
3193 xmlAddSibling(xmlNodePtr cur
, xmlNodePtr elem
) {
3196 if ((cur
== NULL
) || (cur
->type
== XML_NAMESPACE_DECL
)) {
3198 xmlGenericError(xmlGenericErrorContext
,
3199 "xmlAddSibling : cur == NULL\n");
3204 if ((elem
== NULL
) || (elem
->type
== XML_NAMESPACE_DECL
)) {
3206 xmlGenericError(xmlGenericErrorContext
,
3207 "xmlAddSibling : elem == NULL\n");
3214 xmlGenericError(xmlGenericErrorContext
,
3215 "xmlAddSibling : cur == elem\n");
3221 * Constant time is we can rely on the ->parent->last to find
3224 if ((cur
->type
!= XML_ATTRIBUTE_NODE
) && (cur
->parent
!= NULL
) &&
3225 (cur
->parent
->children
!= NULL
) &&
3226 (cur
->parent
->last
!= NULL
) &&
3227 (cur
->parent
->last
->next
== NULL
)) {
3228 cur
= cur
->parent
->last
;
3230 while (cur
->next
!= NULL
) cur
= cur
->next
;
3233 xmlUnlinkNode(elem
);
3235 if ((cur
->type
== XML_TEXT_NODE
) && (elem
->type
== XML_TEXT_NODE
) &&
3236 (cur
->name
== elem
->name
)) {
3237 xmlNodeAddContent(cur
, elem
->content
);
3240 } else if (elem
->type
== XML_ATTRIBUTE_NODE
) {
3241 return xmlAddPropSibling(cur
, cur
, elem
);
3244 if (elem
->doc
!= cur
->doc
) {
3245 xmlSetTreeDoc(elem
, cur
->doc
);
3247 parent
= cur
->parent
;
3250 elem
->parent
= parent
;
3253 parent
->last
= elem
;
3260 * @parent: the parent node
3261 * @cur: the first node in the list
3263 * Add a list of node at the end of the child list of the parent
3264 * merging adjacent TEXT nodes (@cur may be freed)
3266 * Returns the last child or NULL in case of error.
3269 xmlAddChildList(xmlNodePtr parent
, xmlNodePtr cur
) {
3272 if ((parent
== NULL
) || (parent
->type
== XML_NAMESPACE_DECL
)) {
3274 xmlGenericError(xmlGenericErrorContext
,
3275 "xmlAddChildList : parent == NULL\n");
3280 if ((cur
== NULL
) || (cur
->type
== XML_NAMESPACE_DECL
)) {
3282 xmlGenericError(xmlGenericErrorContext
,
3283 "xmlAddChildList : child == NULL\n");
3288 if ((cur
->doc
!= NULL
) && (parent
->doc
!= NULL
) &&
3289 (cur
->doc
!= parent
->doc
)) {
3291 xmlGenericError(xmlGenericErrorContext
,
3292 "Elements moved to a different document\n");
3297 * add the first element at the end of the children list.
3300 if (parent
->children
== NULL
) {
3301 parent
->children
= cur
;
3304 * If cur and parent->last both are TEXT nodes, then merge them.
3306 if ((cur
->type
== XML_TEXT_NODE
) &&
3307 (parent
->last
->type
== XML_TEXT_NODE
) &&
3308 (cur
->name
== parent
->last
->name
)) {
3309 xmlNodeAddContent(parent
->last
, cur
->content
);
3311 * if it's the only child, nothing more to be done.
3313 if (cur
->next
== NULL
) {
3315 return(parent
->last
);
3321 prev
= parent
->last
;
3325 while (cur
->next
!= NULL
) {
3326 cur
->parent
= parent
;
3327 if (cur
->doc
!= parent
->doc
) {
3328 xmlSetTreeDoc(cur
, parent
->doc
);
3332 cur
->parent
= parent
;
3333 /* the parent may not be linked to a doc ! */
3334 if (cur
->doc
!= parent
->doc
) {
3335 xmlSetTreeDoc(cur
, parent
->doc
);
3344 * @parent: the parent node
3345 * @cur: the child node
3347 * Add a new node to @parent, at the end of the child (or property) list
3348 * merging adjacent TEXT nodes (in which case @cur is freed)
3349 * If the new node is ATTRIBUTE, it is added into properties instead of children.
3350 * If there is an attribute with equal name, it is first destroyed.
3352 * Returns the child or NULL in case of error.
3355 xmlAddChild(xmlNodePtr parent
, xmlNodePtr cur
) {
3358 if ((parent
== NULL
) || (parent
->type
== XML_NAMESPACE_DECL
)) {
3360 xmlGenericError(xmlGenericErrorContext
,
3361 "xmlAddChild : parent == NULL\n");
3366 if ((cur
== NULL
) || (cur
->type
== XML_NAMESPACE_DECL
)) {
3368 xmlGenericError(xmlGenericErrorContext
,
3369 "xmlAddChild : child == NULL\n");
3374 if (parent
== cur
) {
3376 xmlGenericError(xmlGenericErrorContext
,
3377 "xmlAddChild : parent == cur\n");
3382 * If cur is a TEXT node, merge its content with adjacent TEXT nodes
3383 * cur is then freed.
3385 if (cur
->type
== XML_TEXT_NODE
) {
3386 if ((parent
->type
== XML_TEXT_NODE
) &&
3387 (parent
->content
!= NULL
) &&
3388 (parent
->name
== cur
->name
)) {
3389 xmlNodeAddContent(parent
, cur
->content
);
3393 if ((parent
->last
!= NULL
) && (parent
->last
->type
== XML_TEXT_NODE
) &&
3394 (parent
->last
->name
== cur
->name
) &&
3395 (parent
->last
!= cur
)) {
3396 xmlNodeAddContent(parent
->last
, cur
->content
);
3398 return(parent
->last
);
3403 * add the new element at the end of the children list.
3406 cur
->parent
= parent
;
3407 if (cur
->doc
!= parent
->doc
) {
3408 xmlSetTreeDoc(cur
, parent
->doc
);
3410 /* this check prevents a loop on tree-traversions if a developer
3411 * tries to add a node to its parent multiple times
3419 if ((parent
->type
== XML_TEXT_NODE
) &&
3420 (parent
->content
!= NULL
) &&
3422 xmlNodeAddContent(parent
, cur
->content
);
3426 if (cur
->type
== XML_ATTRIBUTE_NODE
) {
3427 if (parent
->type
!= XML_ELEMENT_NODE
)
3429 if (parent
->properties
!= NULL
) {
3430 /* check if an attribute with the same name exists */
3431 xmlAttrPtr lastattr
;
3433 if (cur
->ns
== NULL
)
3434 lastattr
= xmlHasNsProp(parent
, cur
->name
, NULL
);
3436 lastattr
= xmlHasNsProp(parent
, cur
->name
, cur
->ns
->href
);
3437 if ((lastattr
!= NULL
) && (lastattr
!= (xmlAttrPtr
) cur
) && (lastattr
->type
!= XML_ATTRIBUTE_DECL
)) {
3438 /* different instance, destroy it (attributes must be unique) */
3439 xmlUnlinkNode((xmlNodePtr
) lastattr
);
3440 xmlFreeProp(lastattr
);
3442 if (lastattr
== (xmlAttrPtr
) cur
)
3446 if (parent
->properties
== NULL
) {
3447 parent
->properties
= (xmlAttrPtr
) cur
;
3450 xmlAttrPtr lastattr
= parent
->properties
;
3451 while (lastattr
->next
!= NULL
) {
3452 lastattr
= lastattr
->next
;
3454 lastattr
->next
= (xmlAttrPtr
) cur
;
3455 ((xmlAttrPtr
) cur
)->prev
= lastattr
;
3458 if (parent
->children
== NULL
) {
3459 parent
->children
= cur
;
3462 prev
= parent
->last
;
3473 * @parent: the parent node
3475 * Search the last child of a node.
3476 * Returns the last child or NULL if none.
3479 xmlGetLastChild(const xmlNode
*parent
) {
3480 if ((parent
== NULL
) || (parent
->type
== XML_NAMESPACE_DECL
)) {
3482 xmlGenericError(xmlGenericErrorContext
,
3483 "xmlGetLastChild : parent == NULL\n");
3487 return(parent
->last
);
3490 #ifdef LIBXML_TREE_ENABLED
3492 * 5 interfaces from DOM ElementTraversal
3496 * xmlChildElementCount:
3497 * @parent: the parent node
3499 * Finds the current number of child nodes of that element which are
3501 * Note the handling of entities references is different than in
3502 * the W3C DOM element traversal spec since we don't have back reference
3503 * from entities content to entities references.
3505 * Returns the count of element child or 0 if not available
3508 xmlChildElementCount(xmlNodePtr parent
) {
3509 unsigned long ret
= 0;
3510 xmlNodePtr cur
= NULL
;
3514 switch (parent
->type
) {
3515 case XML_ELEMENT_NODE
:
3516 case XML_ENTITY_NODE
:
3517 case XML_DOCUMENT_NODE
:
3518 case XML_DOCUMENT_FRAG_NODE
:
3519 case XML_HTML_DOCUMENT_NODE
:
3520 cur
= parent
->children
;
3525 while (cur
!= NULL
) {
3526 if (cur
->type
== XML_ELEMENT_NODE
)
3534 * xmlFirstElementChild:
3535 * @parent: the parent node
3537 * Finds the first child node of that element which is a Element node
3538 * Note the handling of entities references is different than in
3539 * the W3C DOM element traversal spec since we don't have back reference
3540 * from entities content to entities references.
3542 * Returns the first element child or NULL if not available
3545 xmlFirstElementChild(xmlNodePtr parent
) {
3546 xmlNodePtr cur
= NULL
;
3550 switch (parent
->type
) {
3551 case XML_ELEMENT_NODE
:
3552 case XML_ENTITY_NODE
:
3553 case XML_DOCUMENT_NODE
:
3554 case XML_DOCUMENT_FRAG_NODE
:
3555 case XML_HTML_DOCUMENT_NODE
:
3556 cur
= parent
->children
;
3561 while (cur
!= NULL
) {
3562 if (cur
->type
== XML_ELEMENT_NODE
)
3570 * xmlLastElementChild:
3571 * @parent: the parent node
3573 * Finds the last child node of that element which is a Element node
3574 * Note the handling of entities references is different than in
3575 * the W3C DOM element traversal spec since we don't have back reference
3576 * from entities content to entities references.
3578 * Returns the last element child or NULL if not available
3581 xmlLastElementChild(xmlNodePtr parent
) {
3582 xmlNodePtr cur
= NULL
;
3586 switch (parent
->type
) {
3587 case XML_ELEMENT_NODE
:
3588 case XML_ENTITY_NODE
:
3589 case XML_DOCUMENT_NODE
:
3590 case XML_DOCUMENT_FRAG_NODE
:
3591 case XML_HTML_DOCUMENT_NODE
:
3597 while (cur
!= NULL
) {
3598 if (cur
->type
== XML_ELEMENT_NODE
)
3606 * xmlPreviousElementSibling:
3607 * @node: the current node
3609 * Finds the first closest previous sibling of the node which is an
3611 * Note the handling of entities references is different than in
3612 * the W3C DOM element traversal spec since we don't have back reference
3613 * from entities content to entities references.
3615 * Returns the previous element sibling or NULL if not available
3618 xmlPreviousElementSibling(xmlNodePtr node
) {
3621 switch (node
->type
) {
3622 case XML_ELEMENT_NODE
:
3624 case XML_CDATA_SECTION_NODE
:
3625 case XML_ENTITY_REF_NODE
:
3626 case XML_ENTITY_NODE
:
3628 case XML_COMMENT_NODE
:
3629 case XML_XINCLUDE_START
:
3630 case XML_XINCLUDE_END
:
3636 while (node
!= NULL
) {
3637 if (node
->type
== XML_ELEMENT_NODE
)
3645 * xmlNextElementSibling:
3646 * @node: the current node
3648 * Finds the first closest next sibling of the node which is an
3650 * Note the handling of entities references is different than in
3651 * the W3C DOM element traversal spec since we don't have back reference
3652 * from entities content to entities references.
3654 * Returns the next element sibling or NULL if not available
3657 xmlNextElementSibling(xmlNodePtr node
) {
3660 switch (node
->type
) {
3661 case XML_ELEMENT_NODE
:
3663 case XML_CDATA_SECTION_NODE
:
3664 case XML_ENTITY_REF_NODE
:
3665 case XML_ENTITY_NODE
:
3667 case XML_COMMENT_NODE
:
3669 case XML_XINCLUDE_START
:
3670 case XML_XINCLUDE_END
:
3676 while (node
!= NULL
) {
3677 if (node
->type
== XML_ELEMENT_NODE
)
3684 #endif /* LIBXML_TREE_ENABLED */
3688 * @cur: the first node in the list
3690 * Free a node and all its siblings, this is a recursive behaviour, all
3691 * the children are freed too.
3694 xmlFreeNodeList(xmlNodePtr cur
) {
3697 xmlDictPtr dict
= NULL
;
3700 if (cur
== NULL
) return;
3701 if (cur
->type
== XML_NAMESPACE_DECL
) {
3702 xmlFreeNsList((xmlNsPtr
) cur
);
3705 if (cur
->doc
!= NULL
) dict
= cur
->doc
->dict
;
3707 while ((cur
->children
!= NULL
) &&
3708 (cur
->type
!= XML_DOCUMENT_NODE
) &&
3709 #ifdef LIBXML_DOCB_ENABLED
3710 (cur
->type
!= XML_DOCB_DOCUMENT_NODE
) &&
3712 (cur
->type
!= XML_HTML_DOCUMENT_NODE
) &&
3713 (cur
->type
!= XML_DTD_NODE
) &&
3714 (cur
->type
!= XML_ENTITY_REF_NODE
)) {
3715 cur
= cur
->children
;
3720 parent
= cur
->parent
;
3721 if ((cur
->type
== XML_DOCUMENT_NODE
) ||
3722 #ifdef LIBXML_DOCB_ENABLED
3723 (cur
->type
== XML_DOCB_DOCUMENT_NODE
) ||
3725 (cur
->type
== XML_HTML_DOCUMENT_NODE
)) {
3726 xmlFreeDoc((xmlDocPtr
) cur
);
3727 } else if (cur
->type
!= XML_DTD_NODE
) {
3729 if ((__xmlRegisterCallbacks
) && (xmlDeregisterNodeDefaultValue
))
3730 xmlDeregisterNodeDefaultValue(cur
);
3732 if (((cur
->type
== XML_ELEMENT_NODE
) ||
3733 (cur
->type
== XML_XINCLUDE_START
) ||
3734 (cur
->type
== XML_XINCLUDE_END
)) &&
3735 (cur
->properties
!= NULL
))
3736 xmlFreePropList(cur
->properties
);
3737 if ((cur
->type
!= XML_ELEMENT_NODE
) &&
3738 (cur
->type
!= XML_XINCLUDE_START
) &&
3739 (cur
->type
!= XML_XINCLUDE_END
) &&
3740 (cur
->type
!= XML_ENTITY_REF_NODE
) &&
3741 (cur
->content
!= (xmlChar
*) &(cur
->properties
))) {
3742 DICT_FREE(cur
->content
)
3744 if (((cur
->type
== XML_ELEMENT_NODE
) ||
3745 (cur
->type
== XML_XINCLUDE_START
) ||
3746 (cur
->type
== XML_XINCLUDE_END
)) &&
3747 (cur
->nsDef
!= NULL
))
3748 xmlFreeNsList(cur
->nsDef
);
3751 * When a node is a text node or a comment, it uses a global static
3752 * variable for the name of the node.
3753 * Otherwise the node name might come from the document's
3756 if ((cur
->name
!= NULL
) &&
3757 (cur
->type
!= XML_TEXT_NODE
) &&
3758 (cur
->type
!= XML_COMMENT_NODE
))
3759 DICT_FREE(cur
->name
)
3766 if ((depth
== 0) || (parent
== NULL
))
3770 cur
->children
= NULL
;
3779 * Free a node, this is a recursive behaviour, all the children are freed too.
3780 * This doesn't unlink the child from the list, use xmlUnlinkNode() first.
3783 xmlFreeNode(xmlNodePtr cur
) {
3784 xmlDictPtr dict
= NULL
;
3786 if (cur
== NULL
) return;
3788 /* use xmlFreeDtd for DTD nodes */
3789 if (cur
->type
== XML_DTD_NODE
) {
3790 xmlFreeDtd((xmlDtdPtr
) cur
);
3793 if (cur
->type
== XML_NAMESPACE_DECL
) {
3794 xmlFreeNs((xmlNsPtr
) cur
);
3797 if (cur
->type
== XML_ATTRIBUTE_NODE
) {
3798 xmlFreeProp((xmlAttrPtr
) cur
);
3802 if ((__xmlRegisterCallbacks
) && (xmlDeregisterNodeDefaultValue
))
3803 xmlDeregisterNodeDefaultValue(cur
);
3805 if (cur
->doc
!= NULL
) dict
= cur
->doc
->dict
;
3807 if (cur
->type
== XML_ENTITY_DECL
) {
3808 xmlEntityPtr ent
= (xmlEntityPtr
) cur
;
3809 DICT_FREE(ent
->SystemID
);
3810 DICT_FREE(ent
->ExternalID
);
3812 if ((cur
->children
!= NULL
) &&
3813 (cur
->type
!= XML_ENTITY_REF_NODE
))
3814 xmlFreeNodeList(cur
->children
);
3815 if (((cur
->type
== XML_ELEMENT_NODE
) ||
3816 (cur
->type
== XML_XINCLUDE_START
) ||
3817 (cur
->type
== XML_XINCLUDE_END
)) &&
3818 (cur
->properties
!= NULL
))
3819 xmlFreePropList(cur
->properties
);
3820 if ((cur
->type
!= XML_ELEMENT_NODE
) &&
3821 (cur
->content
!= NULL
) &&
3822 (cur
->type
!= XML_ENTITY_REF_NODE
) &&
3823 (cur
->type
!= XML_XINCLUDE_END
) &&
3824 (cur
->type
!= XML_XINCLUDE_START
) &&
3825 (cur
->content
!= (xmlChar
*) &(cur
->properties
))) {
3826 DICT_FREE(cur
->content
)
3830 * When a node is a text node or a comment, it uses a global static
3831 * variable for the name of the node.
3832 * Otherwise the node name might come from the document's dictionary
3834 if ((cur
->name
!= NULL
) &&
3835 (cur
->type
!= XML_TEXT_NODE
) &&
3836 (cur
->type
!= XML_COMMENT_NODE
))
3837 DICT_FREE(cur
->name
)
3839 if (((cur
->type
== XML_ELEMENT_NODE
) ||
3840 (cur
->type
== XML_XINCLUDE_START
) ||
3841 (cur
->type
== XML_XINCLUDE_END
)) &&
3842 (cur
->nsDef
!= NULL
))
3843 xmlFreeNsList(cur
->nsDef
);
3851 * Unlink a node from it's current context, the node is not freed
3852 * If one need to free the node, use xmlFreeNode() routine after the
3853 * unlink to discard it.
3854 * Note that namespace nodes can't be unlinked as they do not have
3855 * pointer to their parent.
3858 xmlUnlinkNode(xmlNodePtr cur
) {
3861 xmlGenericError(xmlGenericErrorContext
,
3862 "xmlUnlinkNode : node == NULL\n");
3866 if (cur
->type
== XML_NAMESPACE_DECL
)
3868 if (cur
->type
== XML_DTD_NODE
) {
3872 if (doc
->intSubset
== (xmlDtdPtr
) cur
)
3873 doc
->intSubset
= NULL
;
3874 if (doc
->extSubset
== (xmlDtdPtr
) cur
)
3875 doc
->extSubset
= NULL
;
3878 if (cur
->type
== XML_ENTITY_DECL
) {
3882 if (doc
->intSubset
!= NULL
) {
3883 if (xmlHashLookup(doc
->intSubset
->entities
, cur
->name
) == cur
)
3884 xmlHashRemoveEntry(doc
->intSubset
->entities
, cur
->name
,
3886 if (xmlHashLookup(doc
->intSubset
->pentities
, cur
->name
) == cur
)
3887 xmlHashRemoveEntry(doc
->intSubset
->pentities
, cur
->name
,
3890 if (doc
->extSubset
!= NULL
) {
3891 if (xmlHashLookup(doc
->extSubset
->entities
, cur
->name
) == cur
)
3892 xmlHashRemoveEntry(doc
->extSubset
->entities
, cur
->name
,
3894 if (xmlHashLookup(doc
->extSubset
->pentities
, cur
->name
) == cur
)
3895 xmlHashRemoveEntry(doc
->extSubset
->pentities
, cur
->name
,
3900 if (cur
->parent
!= NULL
) {
3902 parent
= cur
->parent
;
3903 if (cur
->type
== XML_ATTRIBUTE_NODE
) {
3904 if (parent
->properties
== (xmlAttrPtr
) cur
)
3905 parent
->properties
= ((xmlAttrPtr
) cur
)->next
;
3907 if (parent
->children
== cur
)
3908 parent
->children
= cur
->next
;
3909 if (parent
->last
== cur
)
3910 parent
->last
= cur
->prev
;
3914 if (cur
->next
!= NULL
)
3915 cur
->next
->prev
= cur
->prev
;
3916 if (cur
->prev
!= NULL
)
3917 cur
->prev
->next
= cur
->next
;
3918 cur
->next
= cur
->prev
= NULL
;
3921 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_WRITER_ENABLED)
3924 * @old: the old node
3927 * Unlink the old node from its current context, prune the new one
3928 * at the same place. If @cur was already inserted in a document it is
3929 * first unlinked from its existing context.
3931 * Returns the @old node
3934 xmlReplaceNode(xmlNodePtr old
, xmlNodePtr cur
) {
3935 if (old
== cur
) return(NULL
);
3936 if ((old
== NULL
) || (old
->type
== XML_NAMESPACE_DECL
) ||
3937 (old
->parent
== NULL
)) {
3939 xmlGenericError(xmlGenericErrorContext
,
3940 "xmlReplaceNode : old == NULL or without parent\n");
3944 if ((cur
== NULL
) || (cur
->type
== XML_NAMESPACE_DECL
)) {
3951 if ((old
->type
==XML_ATTRIBUTE_NODE
) && (cur
->type
!=XML_ATTRIBUTE_NODE
)) {
3953 xmlGenericError(xmlGenericErrorContext
,
3954 "xmlReplaceNode : Trying to replace attribute node with other node type\n");
3958 if ((cur
->type
==XML_ATTRIBUTE_NODE
) && (old
->type
!=XML_ATTRIBUTE_NODE
)) {
3960 xmlGenericError(xmlGenericErrorContext
,
3961 "xmlReplaceNode : Trying to replace a non-attribute node with attribute node\n");
3966 xmlSetTreeDoc(cur
, old
->doc
);
3967 cur
->parent
= old
->parent
;
3968 cur
->next
= old
->next
;
3969 if (cur
->next
!= NULL
)
3970 cur
->next
->prev
= cur
;
3971 cur
->prev
= old
->prev
;
3972 if (cur
->prev
!= NULL
)
3973 cur
->prev
->next
= cur
;
3974 if (cur
->parent
!= NULL
) {
3975 if (cur
->type
== XML_ATTRIBUTE_NODE
) {
3976 if (cur
->parent
->properties
== (xmlAttrPtr
)old
)
3977 cur
->parent
->properties
= ((xmlAttrPtr
) cur
);
3979 if (cur
->parent
->children
== old
)
3980 cur
->parent
->children
= cur
;
3981 if (cur
->parent
->last
== old
)
3982 cur
->parent
->last
= cur
;
3985 old
->next
= old
->prev
= NULL
;
3989 #endif /* LIBXML_TREE_ENABLED */
3991 /************************************************************************
3995 ************************************************************************/
3999 * @cur: the namespace
4001 * Do a copy of the namespace.
4003 * Returns: a new #xmlNsPtr, or NULL in case of error.
4006 xmlCopyNamespace(xmlNsPtr cur
) {
4009 if (cur
== NULL
) return(NULL
);
4010 switch (cur
->type
) {
4011 case XML_LOCAL_NAMESPACE
:
4012 ret
= xmlNewNs(NULL
, cur
->href
, cur
->prefix
);
4016 xmlGenericError(xmlGenericErrorContext
,
4017 "xmlCopyNamespace: invalid type %d\n", cur
->type
);
4025 * xmlCopyNamespaceList:
4026 * @cur: the first namespace
4028 * Do a copy of an namespace list.
4030 * Returns: a new #xmlNsPtr, or NULL in case of error.
4033 xmlCopyNamespaceList(xmlNsPtr cur
) {
4034 xmlNsPtr ret
= NULL
;
4035 xmlNsPtr p
= NULL
,q
;
4037 while (cur
!= NULL
) {
4038 q
= xmlCopyNamespace(cur
);
4051 xmlStaticCopyNodeList(xmlNodePtr node
, xmlDocPtr doc
, xmlNodePtr parent
);
4054 xmlCopyPropInternal(xmlDocPtr doc
, xmlNodePtr target
, xmlAttrPtr cur
) {
4057 if (cur
== NULL
) return(NULL
);
4058 if ((target
!= NULL
) && (target
->type
!= XML_ELEMENT_NODE
))
4061 ret
= xmlNewDocProp(target
->doc
, cur
->name
, NULL
);
4062 else if (doc
!= NULL
)
4063 ret
= xmlNewDocProp(doc
, cur
->name
, NULL
);
4064 else if (cur
->parent
!= NULL
)
4065 ret
= xmlNewDocProp(cur
->parent
->doc
, cur
->name
, NULL
);
4066 else if (cur
->children
!= NULL
)
4067 ret
= xmlNewDocProp(cur
->children
->doc
, cur
->name
, NULL
);
4069 ret
= xmlNewDocProp(NULL
, cur
->name
, NULL
);
4070 if (ret
== NULL
) return(NULL
);
4071 ret
->parent
= target
;
4073 if ((cur
->ns
!= NULL
) && (target
!= NULL
)) {
4076 ns
= xmlSearchNs(target
->doc
, target
, cur
->ns
->prefix
);
4079 * Humm, we are copying an element whose namespace is defined
4080 * out of the new tree scope. Search it in the original tree
4081 * and add it at the top of the new tree
4083 ns
= xmlSearchNs(cur
->doc
, cur
->parent
, cur
->ns
->prefix
);
4085 xmlNodePtr root
= target
;
4086 xmlNodePtr pred
= NULL
;
4088 while (root
->parent
!= NULL
) {
4090 root
= root
->parent
;
4092 if (root
== (xmlNodePtr
) target
->doc
) {
4093 /* correct possibly cycling above the document elt */
4096 ret
->ns
= xmlNewNs(root
, ns
->href
, ns
->prefix
);
4100 * we have to find something appropriate here since
4101 * we can't be sure, that the namespace we found is identified
4104 if (xmlStrEqual(ns
->href
, cur
->ns
->href
)) {
4105 /* this is the nice case */
4109 * we are in trouble: we need a new reconciled namespace.
4112 ret
->ns
= xmlNewReconciledNs(target
->doc
, target
, cur
->ns
);
4119 if (cur
->children
!= NULL
) {
4122 ret
->children
= xmlStaticCopyNodeList(cur
->children
, ret
->doc
, (xmlNodePtr
) ret
);
4124 tmp
= ret
->children
;
4125 while (tmp
!= NULL
) {
4126 /* tmp->parent = (xmlNodePtr)ret; */
4127 if (tmp
->next
== NULL
)
4135 if ((target
!= NULL
) && (cur
!= NULL
) &&
4136 (target
->doc
!= NULL
) && (cur
->doc
!= NULL
) &&
4137 (cur
->doc
->ids
!= NULL
) && (cur
->parent
!= NULL
)) {
4138 if (xmlIsID(cur
->doc
, cur
->parent
, cur
)) {
4141 id
= xmlNodeListGetString(cur
->doc
, cur
->children
, 1);
4143 xmlAddID(NULL
, target
->doc
, id
, ret
);
4153 * @target: the element where the attribute will be grafted
4154 * @cur: the attribute
4156 * Do a copy of the attribute.
4158 * Returns: a new #xmlAttrPtr, or NULL in case of error.
4161 xmlCopyProp(xmlNodePtr target
, xmlAttrPtr cur
) {
4162 return xmlCopyPropInternal(NULL
, target
, cur
);
4167 * @target: the element where the attributes will be grafted
4168 * @cur: the first attribute
4170 * Do a copy of an attribute list.
4172 * Returns: a new #xmlAttrPtr, or NULL in case of error.
4175 xmlCopyPropList(xmlNodePtr target
, xmlAttrPtr cur
) {
4176 xmlAttrPtr ret
= NULL
;
4177 xmlAttrPtr p
= NULL
,q
;
4179 if ((target
!= NULL
) && (target
->type
!= XML_ELEMENT_NODE
))
4181 while (cur
!= NULL
) {
4182 q
= xmlCopyProp(target
, cur
);
4198 * NOTE about the CopyNode operations !
4200 * They are split into external and internal parts for one
4201 * tricky reason: namespaces. Doing a direct copy of a node
4202 * say RPM:Copyright without changing the namespace pointer to
4203 * something else can produce stale links. One way to do it is
4204 * to keep a reference counter but this doesn't work as soon
4205 * as one moves the element or the subtree out of the scope of
4206 * the existing namespace. The actual solution seems to be to add
4207 * a copy of the namespace at the top of the copied tree if
4208 * not available in the subtree.
4209 * Hence two functions, the public front-end call the inner ones
4210 * The argument "recursive" normally indicates a recursive copy
4211 * of the node with values 0 (no) and 1 (yes). For XInclude,
4212 * however, we allow a value of 2 to indicate copy properties and
4213 * namespace info, but don't recurse on children.
4217 xmlStaticCopyNode(xmlNodePtr node
, xmlDocPtr doc
, xmlNodePtr parent
,
4221 if (node
== NULL
) return(NULL
);
4222 switch (node
->type
) {
4224 case XML_CDATA_SECTION_NODE
:
4225 case XML_ELEMENT_NODE
:
4226 case XML_DOCUMENT_FRAG_NODE
:
4227 case XML_ENTITY_REF_NODE
:
4228 case XML_ENTITY_NODE
:
4230 case XML_COMMENT_NODE
:
4231 case XML_XINCLUDE_START
:
4232 case XML_XINCLUDE_END
:
4234 case XML_ATTRIBUTE_NODE
:
4235 return((xmlNodePtr
) xmlCopyPropInternal(doc
, parent
, (xmlAttrPtr
) node
));
4236 case XML_NAMESPACE_DECL
:
4237 return((xmlNodePtr
) xmlCopyNamespaceList((xmlNsPtr
) node
));
4239 case XML_DOCUMENT_NODE
:
4240 case XML_HTML_DOCUMENT_NODE
:
4241 #ifdef LIBXML_DOCB_ENABLED
4242 case XML_DOCB_DOCUMENT_NODE
:
4244 #ifdef LIBXML_TREE_ENABLED
4245 return((xmlNodePtr
) xmlCopyDoc((xmlDocPtr
) node
, extended
));
4246 #endif /* LIBXML_TREE_ENABLED */
4247 case XML_DOCUMENT_TYPE_NODE
:
4248 case XML_NOTATION_NODE
:
4250 case XML_ELEMENT_DECL
:
4251 case XML_ATTRIBUTE_DECL
:
4252 case XML_ENTITY_DECL
:
4257 * Allocate a new node and fill the fields.
4259 ret
= (xmlNodePtr
) xmlMalloc(sizeof(xmlNode
));
4261 xmlTreeErrMemory("copying node");
4264 memset(ret
, 0, sizeof(xmlNode
));
4265 ret
->type
= node
->type
;
4268 ret
->parent
= parent
;
4269 if (node
->name
== xmlStringText
)
4270 ret
->name
= xmlStringText
;
4271 else if (node
->name
== xmlStringTextNoenc
)
4272 ret
->name
= xmlStringTextNoenc
;
4273 else if (node
->name
== xmlStringComment
)
4274 ret
->name
= xmlStringComment
;
4275 else if (node
->name
!= NULL
) {
4276 if ((doc
!= NULL
) && (doc
->dict
!= NULL
))
4277 ret
->name
= xmlDictLookup(doc
->dict
, node
->name
, -1);
4279 ret
->name
= xmlStrdup(node
->name
);
4281 if ((node
->type
!= XML_ELEMENT_NODE
) &&
4282 (node
->content
!= NULL
) &&
4283 (node
->type
!= XML_ENTITY_REF_NODE
) &&
4284 (node
->type
!= XML_XINCLUDE_END
) &&
4285 (node
->type
!= XML_XINCLUDE_START
)) {
4286 ret
->content
= xmlStrdup(node
->content
);
4288 if (node
->type
== XML_ELEMENT_NODE
)
4289 ret
->line
= node
->line
;
4291 if (parent
!= NULL
) {
4295 * this is a tricky part for the node register thing:
4296 * in case ret does get coalesced in xmlAddChild
4297 * the deregister-node callback is called; so we register ret now already
4299 if ((__xmlRegisterCallbacks
) && (xmlRegisterNodeDefaultValue
))
4300 xmlRegisterNodeDefaultValue((xmlNodePtr
)ret
);
4302 tmp
= xmlAddChild(parent
, ret
);
4303 /* node could have coalesced */
4310 if (((node
->type
== XML_ELEMENT_NODE
) ||
4311 (node
->type
== XML_XINCLUDE_START
)) && (node
->nsDef
!= NULL
))
4312 ret
->nsDef
= xmlCopyNamespaceList(node
->nsDef
);
4314 if (node
->ns
!= NULL
) {
4317 ns
= xmlSearchNs(doc
, ret
, node
->ns
->prefix
);
4320 * Humm, we are copying an element whose namespace is defined
4321 * out of the new tree scope. Search it in the original tree
4322 * and add it at the top of the new tree
4324 ns
= xmlSearchNs(node
->doc
, node
, node
->ns
->prefix
);
4326 xmlNodePtr root
= ret
;
4328 while (root
->parent
!= NULL
) root
= root
->parent
;
4329 ret
->ns
= xmlNewNs(root
, ns
->href
, ns
->prefix
);
4331 ret
->ns
= xmlNewReconciledNs(doc
, ret
, node
->ns
);
4335 * reference the existing namespace definition in our own tree.
4340 if (((node
->type
== XML_ELEMENT_NODE
) ||
4341 (node
->type
== XML_XINCLUDE_START
)) && (node
->properties
!= NULL
))
4342 ret
->properties
= xmlCopyPropList(ret
, node
->properties
);
4343 if (node
->type
== XML_ENTITY_REF_NODE
) {
4344 if ((doc
== NULL
) || (node
->doc
!= doc
)) {
4346 * The copied node will go into a separate document, so
4347 * to avoid dangling references to the ENTITY_DECL node
4348 * we cannot keep the reference. Try to find it in the
4351 ret
->children
= (xmlNodePtr
) xmlGetDocEntity(doc
, ret
->name
);
4353 ret
->children
= node
->children
;
4355 ret
->last
= ret
->children
;
4356 } else if ((node
->children
!= NULL
) && (extended
!= 2)) {
4357 ret
->children
= xmlStaticCopyNodeList(node
->children
, doc
, ret
);
4358 UPDATE_LAST_CHILD_AND_PARENT(ret
)
4362 /* if parent != NULL we already registered the node above */
4363 if ((parent
== NULL
) &&
4364 ((__xmlRegisterCallbacks
) && (xmlRegisterNodeDefaultValue
)))
4365 xmlRegisterNodeDefaultValue((xmlNodePtr
)ret
);
4370 xmlStaticCopyNodeList(xmlNodePtr node
, xmlDocPtr doc
, xmlNodePtr parent
) {
4371 xmlNodePtr ret
= NULL
;
4372 xmlNodePtr p
= NULL
,q
;
4374 while (node
!= NULL
) {
4375 #ifdef LIBXML_TREE_ENABLED
4376 if (node
->type
== XML_DTD_NODE
) {
4381 if (doc
->intSubset
== NULL
) {
4382 q
= (xmlNodePtr
) xmlCopyDtd( (xmlDtdPtr
) node
);
4383 if (q
== NULL
) return(NULL
);
4386 doc
->intSubset
= (xmlDtdPtr
) q
;
4387 xmlAddChild(parent
, q
);
4389 q
= (xmlNodePtr
) doc
->intSubset
;
4390 xmlAddChild(parent
, q
);
4393 #endif /* LIBXML_TREE_ENABLED */
4394 q
= xmlStaticCopyNode(node
, doc
, parent
, 1);
4395 if (q
== NULL
) return(NULL
);
4399 } else if (p
!= q
) {
4400 /* the test is required if xmlStaticCopyNode coalesced 2 text nodes */
4413 * @extended: if 1 do a recursive copy (properties, namespaces and children
4415 * if 2 copy properties and namespaces (when applicable)
4417 * Do a copy of the node.
4419 * Returns: a new #xmlNodePtr, or NULL in case of error.
4422 xmlCopyNode(xmlNodePtr node
, int extended
) {
4425 ret
= xmlStaticCopyNode(node
, NULL
, NULL
, extended
);
4432 * @doc: the document
4433 * @extended: if 1 do a recursive copy (properties, namespaces and children
4435 * if 2 copy properties and namespaces (when applicable)
4437 * Do a copy of the node to a given document.
4439 * Returns: a new #xmlNodePtr, or NULL in case of error.
4442 xmlDocCopyNode(xmlNodePtr node
, xmlDocPtr doc
, int extended
) {
4445 ret
= xmlStaticCopyNode(node
, doc
, NULL
, extended
);
4450 * xmlDocCopyNodeList:
4451 * @doc: the target document
4452 * @node: the first node in the list.
4454 * Do a recursive copy of the node list.
4456 * Returns: a new #xmlNodePtr, or NULL in case of error.
4458 xmlNodePtr
xmlDocCopyNodeList(xmlDocPtr doc
, xmlNodePtr node
) {
4459 xmlNodePtr ret
= xmlStaticCopyNodeList(node
, doc
, NULL
);
4465 * @node: the first node in the list.
4467 * Do a recursive copy of the node list.
4468 * Use xmlDocCopyNodeList() if possible to ensure string interning.
4470 * Returns: a new #xmlNodePtr, or NULL in case of error.
4472 xmlNodePtr
xmlCopyNodeList(xmlNodePtr node
) {
4473 xmlNodePtr ret
= xmlStaticCopyNodeList(node
, NULL
, NULL
);
4477 #if defined(LIBXML_TREE_ENABLED)
4482 * Do a copy of the dtd.
4484 * Returns: a new #xmlDtdPtr, or NULL in case of error.
4487 xmlCopyDtd(xmlDtdPtr dtd
) {
4489 xmlNodePtr cur
, p
= NULL
, q
;
4491 if (dtd
== NULL
) return(NULL
);
4492 ret
= xmlNewDtd(NULL
, dtd
->name
, dtd
->ExternalID
, dtd
->SystemID
);
4493 if (ret
== NULL
) return(NULL
);
4494 if (dtd
->entities
!= NULL
)
4495 ret
->entities
= (void *) xmlCopyEntitiesTable(
4496 (xmlEntitiesTablePtr
) dtd
->entities
);
4497 if (dtd
->notations
!= NULL
)
4498 ret
->notations
= (void *) xmlCopyNotationTable(
4499 (xmlNotationTablePtr
) dtd
->notations
);
4500 if (dtd
->elements
!= NULL
)
4501 ret
->elements
= (void *) xmlCopyElementTable(
4502 (xmlElementTablePtr
) dtd
->elements
);
4503 if (dtd
->attributes
!= NULL
)
4504 ret
->attributes
= (void *) xmlCopyAttributeTable(
4505 (xmlAttributeTablePtr
) dtd
->attributes
);
4506 if (dtd
->pentities
!= NULL
)
4507 ret
->pentities
= (void *) xmlCopyEntitiesTable(
4508 (xmlEntitiesTablePtr
) dtd
->pentities
);
4510 cur
= dtd
->children
;
4511 while (cur
!= NULL
) {
4514 if (cur
->type
== XML_ENTITY_DECL
) {
4515 xmlEntityPtr tmp
= (xmlEntityPtr
) cur
;
4516 switch (tmp
->etype
) {
4517 case XML_INTERNAL_GENERAL_ENTITY
:
4518 case XML_EXTERNAL_GENERAL_PARSED_ENTITY
:
4519 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY
:
4520 q
= (xmlNodePtr
) xmlGetEntityFromDtd(ret
, tmp
->name
);
4522 case XML_INTERNAL_PARAMETER_ENTITY
:
4523 case XML_EXTERNAL_PARAMETER_ENTITY
:
4525 xmlGetParameterEntityFromDtd(ret
, tmp
->name
);
4527 case XML_INTERNAL_PREDEFINED_ENTITY
:
4530 } else if (cur
->type
== XML_ELEMENT_DECL
) {
4531 xmlElementPtr tmp
= (xmlElementPtr
) cur
;
4533 xmlGetDtdQElementDesc(ret
, tmp
->name
, tmp
->prefix
);
4534 } else if (cur
->type
== XML_ATTRIBUTE_DECL
) {
4535 xmlAttributePtr tmp
= (xmlAttributePtr
) cur
;
4537 xmlGetDtdQAttrDesc(ret
, tmp
->elem
, tmp
->name
, tmp
->prefix
);
4538 } else if (cur
->type
== XML_COMMENT_NODE
) {
4539 q
= xmlCopyNode(cur
, 0);
4553 q
->parent
= (xmlNodePtr
) ret
;
4564 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
4567 * @doc: the document
4568 * @recursive: if not zero do a recursive copy.
4570 * Do a copy of the document info. If recursive, the content tree will
4571 * be copied too as well as DTD, namespaces and entities.
4573 * Returns: a new #xmlDocPtr, or NULL in case of error.
4576 xmlCopyDoc(xmlDocPtr doc
, int recursive
) {
4579 if (doc
== NULL
) return(NULL
);
4580 ret
= xmlNewDoc(doc
->version
);
4581 if (ret
== NULL
) return(NULL
);
4582 ret
->type
= doc
->type
;
4583 if (doc
->name
!= NULL
)
4584 ret
->name
= xmlMemStrdup(doc
->name
);
4585 if (doc
->encoding
!= NULL
)
4586 ret
->encoding
= xmlStrdup(doc
->encoding
);
4587 if (doc
->URL
!= NULL
)
4588 ret
->URL
= xmlStrdup(doc
->URL
);
4589 ret
->charset
= doc
->charset
;
4590 ret
->compression
= doc
->compression
;
4591 ret
->standalone
= doc
->standalone
;
4592 if (!recursive
) return(ret
);
4595 ret
->children
= NULL
;
4596 #ifdef LIBXML_TREE_ENABLED
4597 if (doc
->intSubset
!= NULL
) {
4598 ret
->intSubset
= xmlCopyDtd(doc
->intSubset
);
4599 if (ret
->intSubset
== NULL
) {
4603 xmlSetTreeDoc((xmlNodePtr
)ret
->intSubset
, ret
);
4604 ret
->intSubset
->parent
= ret
;
4607 if (doc
->oldNs
!= NULL
)
4608 ret
->oldNs
= xmlCopyNamespaceList(doc
->oldNs
);
4609 if (doc
->children
!= NULL
) {
4612 ret
->children
= xmlStaticCopyNodeList(doc
->children
, ret
,
4615 tmp
= ret
->children
;
4616 while (tmp
!= NULL
) {
4617 if (tmp
->next
== NULL
)
4624 #endif /* LIBXML_TREE_ENABLED */
4626 /************************************************************************
4628 * Content access functions *
4630 ************************************************************************/
4633 * xmlGetLineNoInternal:
4635 * @depth: used to limit any risk of recursion
4637 * Get line number of @node.
4638 * Try to override the limitation of lines being store in 16 bits ints
4640 * Returns the line number if successful, -1 otherwise
4643 xmlGetLineNoInternal(const xmlNode
*node
, int depth
)
4652 if ((node
->type
== XML_ELEMENT_NODE
) ||
4653 (node
->type
== XML_TEXT_NODE
) ||
4654 (node
->type
== XML_COMMENT_NODE
) ||
4655 (node
->type
== XML_PI_NODE
)) {
4656 if (node
->line
== 65535) {
4657 if ((node
->type
== XML_TEXT_NODE
) && (node
->psvi
!= NULL
))
4658 result
= (long) (ptrdiff_t) node
->psvi
;
4659 else if ((node
->type
== XML_ELEMENT_NODE
) &&
4660 (node
->children
!= NULL
))
4661 result
= xmlGetLineNoInternal(node
->children
, depth
+ 1);
4662 else if (node
->next
!= NULL
)
4663 result
= xmlGetLineNoInternal(node
->next
, depth
+ 1);
4664 else if (node
->prev
!= NULL
)
4665 result
= xmlGetLineNoInternal(node
->prev
, depth
+ 1);
4667 if ((result
== -1) || (result
== 65535))
4668 result
= (long) node
->line
;
4669 } else if ((node
->prev
!= NULL
) &&
4670 ((node
->prev
->type
== XML_ELEMENT_NODE
) ||
4671 (node
->prev
->type
== XML_TEXT_NODE
) ||
4672 (node
->prev
->type
== XML_COMMENT_NODE
) ||
4673 (node
->prev
->type
== XML_PI_NODE
)))
4674 result
= xmlGetLineNoInternal(node
->prev
, depth
+ 1);
4675 else if ((node
->parent
!= NULL
) &&
4676 (node
->parent
->type
== XML_ELEMENT_NODE
))
4677 result
= xmlGetLineNoInternal(node
->parent
, depth
+ 1);
4686 * Get line number of @node.
4687 * Try to override the limitation of lines being store in 16 bits ints
4688 * if XML_PARSE_BIG_LINES parser option was used
4690 * Returns the line number if successful, -1 otherwise
4693 xmlGetLineNo(const xmlNode
*node
)
4695 return(xmlGetLineNoInternal(node
, 0));
4698 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_DEBUG_ENABLED)
4703 * Build a structure based Path for the given node
4705 * Returns the new path or NULL in case of error. The caller must free
4706 * the returned string
4709 xmlGetNodePath(const xmlNode
*node
)
4711 const xmlNode
*cur
, *tmp
, *next
;
4712 xmlChar
*buffer
= NULL
, *temp
;
4718 int occur
= 0, generic
;
4720 if ((node
== NULL
) || (node
->type
== XML_NAMESPACE_DECL
))
4724 buffer
= (xmlChar
*) xmlMallocAtomic(buf_len
* sizeof(xmlChar
));
4725 if (buffer
== NULL
) {
4726 xmlTreeErrMemory("getting node path");
4729 buf
= (xmlChar
*) xmlMallocAtomic(buf_len
* sizeof(xmlChar
));
4731 xmlTreeErrMemory("getting node path");
4742 if ((cur
->type
== XML_DOCUMENT_NODE
) ||
4743 (cur
->type
== XML_HTML_DOCUMENT_NODE
)) {
4744 if (buffer
[0] == '/')
4748 } else if (cur
->type
== XML_ELEMENT_NODE
) {
4751 name
= (const char *) cur
->name
;
4753 if (cur
->ns
->prefix
!= NULL
) {
4754 snprintf(nametemp
, sizeof(nametemp
) - 1, "%s:%s",
4755 (char *)cur
->ns
->prefix
, (char *)cur
->name
);
4756 nametemp
[sizeof(nametemp
) - 1] = 0;
4760 * We cannot express named elements in the default
4761 * namespace, so use "*".
4770 * Thumbler index computation
4771 * TODO: the occurrence test seems bogus for namespaced names
4774 while (tmp
!= NULL
) {
4775 if ((tmp
->type
== XML_ELEMENT_NODE
) &&
4777 (xmlStrEqual(cur
->name
, tmp
->name
) &&
4778 ((tmp
->ns
== cur
->ns
) ||
4779 ((tmp
->ns
!= NULL
) && (cur
->ns
!= NULL
) &&
4780 (xmlStrEqual(cur
->ns
->prefix
, tmp
->ns
->prefix
)))))))
4786 while (tmp
!= NULL
&& occur
== 0) {
4787 if ((tmp
->type
== XML_ELEMENT_NODE
) &&
4789 (xmlStrEqual(cur
->name
, tmp
->name
) &&
4790 ((tmp
->ns
== cur
->ns
) ||
4791 ((tmp
->ns
!= NULL
) && (cur
->ns
!= NULL
) &&
4792 (xmlStrEqual(cur
->ns
->prefix
, tmp
->ns
->prefix
)))))))
4800 } else if (cur
->type
== XML_COMMENT_NODE
) {
4806 * Thumbler index computation
4809 while (tmp
!= NULL
) {
4810 if (tmp
->type
== XML_COMMENT_NODE
)
4816 while (tmp
!= NULL
&& occur
== 0) {
4817 if (tmp
->type
== XML_COMMENT_NODE
)
4825 } else if ((cur
->type
== XML_TEXT_NODE
) ||
4826 (cur
->type
== XML_CDATA_SECTION_NODE
)) {
4832 * Thumbler index computation
4835 while (tmp
!= NULL
) {
4836 if ((tmp
->type
== XML_TEXT_NODE
) ||
4837 (tmp
->type
== XML_CDATA_SECTION_NODE
))
4842 * Evaluate if this is the only text- or CDATA-section-node;
4843 * if yes, then we'll get "text()", otherwise "text()[1]".
4847 while (tmp
!= NULL
) {
4848 if ((tmp
->type
== XML_TEXT_NODE
) ||
4849 (tmp
->type
== XML_CDATA_SECTION_NODE
))
4858 } else if (cur
->type
== XML_PI_NODE
) {
4860 snprintf(nametemp
, sizeof(nametemp
) - 1,
4861 "processing-instruction('%s')", (char *)cur
->name
);
4862 nametemp
[sizeof(nametemp
) - 1] = 0;
4868 * Thumbler index computation
4871 while (tmp
!= NULL
) {
4872 if ((tmp
->type
== XML_PI_NODE
) &&
4873 (xmlStrEqual(cur
->name
, tmp
->name
)))
4879 while (tmp
!= NULL
&& occur
== 0) {
4880 if ((tmp
->type
== XML_PI_NODE
) &&
4881 (xmlStrEqual(cur
->name
, tmp
->name
)))
4890 } else if (cur
->type
== XML_ATTRIBUTE_NODE
) {
4892 name
= (const char *) (((xmlAttrPtr
) cur
)->name
);
4894 if (cur
->ns
->prefix
!= NULL
)
4895 snprintf(nametemp
, sizeof(nametemp
) - 1, "%s:%s",
4896 (char *)cur
->ns
->prefix
, (char *)cur
->name
);
4898 snprintf(nametemp
, sizeof(nametemp
) - 1, "%s",
4900 nametemp
[sizeof(nametemp
) - 1] = 0;
4903 next
= ((xmlAttrPtr
) cur
)->parent
;
4911 * Make sure there is enough room
4913 if (xmlStrlen(buffer
) + sizeof(nametemp
) + 20 > buf_len
) {
4915 2 * buf_len
+ xmlStrlen(buffer
) + sizeof(nametemp
) + 20;
4916 temp
= (xmlChar
*) xmlRealloc(buffer
, buf_len
);
4918 xmlTreeErrMemory("getting node path");
4924 temp
= (xmlChar
*) xmlRealloc(buf
, buf_len
);
4926 xmlTreeErrMemory("getting node path");
4934 snprintf((char *) buf
, buf_len
, "%s%s%s",
4935 sep
, name
, (char *) buffer
);
4937 snprintf((char *) buf
, buf_len
, "%s%s[%d]%s",
4938 sep
, name
, occur
, (char *) buffer
);
4939 snprintf((char *) buffer
, buf_len
, "%s", (char *)buf
);
4941 } while (cur
!= NULL
);
4945 #endif /* LIBXML_TREE_ENABLED */
4948 * xmlDocGetRootElement:
4949 * @doc: the document
4951 * Get the root element of the document (doc->children is a list
4952 * containing possibly comments, PIs, etc ...).
4954 * Returns the #xmlNodePtr for the root or NULL
4957 xmlDocGetRootElement(const xmlDoc
*doc
) {
4960 if (doc
== NULL
) return(NULL
);
4961 ret
= doc
->children
;
4962 while (ret
!= NULL
) {
4963 if (ret
->type
== XML_ELEMENT_NODE
)
4970 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_WRITER_ENABLED)
4972 * xmlDocSetRootElement:
4973 * @doc: the document
4974 * @root: the new document root element, if root is NULL no action is taken,
4975 * to remove a node from a document use xmlUnlinkNode(root) instead.
4977 * Set the root element of the document (doc->children is a list
4978 * containing possibly comments, PIs, etc ...).
4980 * Returns the old root element if any was found, NULL if root was NULL
4983 xmlDocSetRootElement(xmlDocPtr doc
, xmlNodePtr root
) {
4984 xmlNodePtr old
= NULL
;
4986 if (doc
== NULL
) return(NULL
);
4987 if ((root
== NULL
) || (root
->type
== XML_NAMESPACE_DECL
))
4989 xmlUnlinkNode(root
);
4990 xmlSetTreeDoc(root
, doc
);
4991 root
->parent
= (xmlNodePtr
) doc
;
4992 old
= doc
->children
;
4993 while (old
!= NULL
) {
4994 if (old
->type
== XML_ELEMENT_NODE
)
4999 if (doc
->children
== NULL
) {
5000 doc
->children
= root
;
5003 xmlAddSibling(doc
->children
, root
);
5006 xmlReplaceNode(old
, root
);
5012 #if defined(LIBXML_TREE_ENABLED)
5015 * @cur: the node being changed
5016 * @lang: the language description
5018 * Set the language of a node, i.e. the values of the xml:lang
5022 xmlNodeSetLang(xmlNodePtr cur
, const xmlChar
*lang
) {
5025 if (cur
== NULL
) return;
5028 case XML_CDATA_SECTION_NODE
:
5029 case XML_COMMENT_NODE
:
5030 case XML_DOCUMENT_NODE
:
5031 case XML_DOCUMENT_TYPE_NODE
:
5032 case XML_DOCUMENT_FRAG_NODE
:
5033 case XML_NOTATION_NODE
:
5034 case XML_HTML_DOCUMENT_NODE
:
5036 case XML_ELEMENT_DECL
:
5037 case XML_ATTRIBUTE_DECL
:
5038 case XML_ENTITY_DECL
:
5040 case XML_ENTITY_REF_NODE
:
5041 case XML_ENTITY_NODE
:
5042 case XML_NAMESPACE_DECL
:
5043 #ifdef LIBXML_DOCB_ENABLED
5044 case XML_DOCB_DOCUMENT_NODE
:
5046 case XML_XINCLUDE_START
:
5047 case XML_XINCLUDE_END
:
5049 case XML_ELEMENT_NODE
:
5050 case XML_ATTRIBUTE_NODE
:
5053 ns
= xmlSearchNsByHref(cur
->doc
, cur
, XML_XML_NAMESPACE
);
5056 xmlSetNsProp(cur
, ns
, BAD_CAST
"lang", lang
);
5058 #endif /* LIBXML_TREE_ENABLED */
5062 * @cur: the node being checked
5064 * Searches the language of a node, i.e. the values of the xml:lang
5065 * attribute or the one carried by the nearest ancestor.
5067 * Returns a pointer to the lang value, or NULL if not found
5068 * It's up to the caller to free the memory with xmlFree().
5071 xmlNodeGetLang(const xmlNode
*cur
) {
5074 if ((cur
== NULL
) || (cur
->type
== XML_NAMESPACE_DECL
))
5076 while (cur
!= NULL
) {
5077 lang
= xmlGetNsProp(cur
, BAD_CAST
"lang", XML_XML_NAMESPACE
);
5086 #ifdef LIBXML_TREE_ENABLED
5088 * xmlNodeSetSpacePreserve:
5089 * @cur: the node being changed
5090 * @val: the xml:space value ("0": default, 1: "preserve")
5092 * Set (or reset) the space preserving behaviour of a node, i.e. the
5093 * value of the xml:space attribute.
5096 xmlNodeSetSpacePreserve(xmlNodePtr cur
, int val
) {
5099 if (cur
== NULL
) return;
5102 case XML_CDATA_SECTION_NODE
:
5103 case XML_COMMENT_NODE
:
5104 case XML_DOCUMENT_NODE
:
5105 case XML_DOCUMENT_TYPE_NODE
:
5106 case XML_DOCUMENT_FRAG_NODE
:
5107 case XML_NOTATION_NODE
:
5108 case XML_HTML_DOCUMENT_NODE
:
5110 case XML_ELEMENT_DECL
:
5111 case XML_ATTRIBUTE_DECL
:
5112 case XML_ENTITY_DECL
:
5114 case XML_ENTITY_REF_NODE
:
5115 case XML_ENTITY_NODE
:
5116 case XML_NAMESPACE_DECL
:
5117 case XML_XINCLUDE_START
:
5118 case XML_XINCLUDE_END
:
5119 #ifdef LIBXML_DOCB_ENABLED
5120 case XML_DOCB_DOCUMENT_NODE
:
5123 case XML_ELEMENT_NODE
:
5124 case XML_ATTRIBUTE_NODE
:
5127 ns
= xmlSearchNsByHref(cur
->doc
, cur
, XML_XML_NAMESPACE
);
5132 xmlSetNsProp(cur
, ns
, BAD_CAST
"space", BAD_CAST
"default");
5135 xmlSetNsProp(cur
, ns
, BAD_CAST
"space", BAD_CAST
"preserve");
5139 #endif /* LIBXML_TREE_ENABLED */
5142 * xmlNodeGetSpacePreserve:
5143 * @cur: the node being checked
5145 * Searches the space preserving behaviour of a node, i.e. the values
5146 * of the xml:space attribute or the one carried by the nearest
5149 * Returns -1 if xml:space is not inherited, 0 if "default", 1 if "preserve"
5152 xmlNodeGetSpacePreserve(const xmlNode
*cur
) {
5155 if ((cur
== NULL
) || (cur
->type
!= XML_ELEMENT_NODE
))
5157 while (cur
!= NULL
) {
5158 space
= xmlGetNsProp(cur
, BAD_CAST
"space", XML_XML_NAMESPACE
);
5159 if (space
!= NULL
) {
5160 if (xmlStrEqual(space
, BAD_CAST
"preserve")) {
5164 if (xmlStrEqual(space
, BAD_CAST
"default")) {
5175 #ifdef LIBXML_TREE_ENABLED
5178 * @cur: the node being changed
5179 * @name: the new tag name
5181 * Set (or reset) the name of a node.
5184 xmlNodeSetName(xmlNodePtr cur
, const xmlChar
*name
) {
5187 const xmlChar
*freeme
= NULL
;
5189 if (cur
== NULL
) return;
5190 if (name
== NULL
) return;
5193 case XML_CDATA_SECTION_NODE
:
5194 case XML_COMMENT_NODE
:
5195 case XML_DOCUMENT_TYPE_NODE
:
5196 case XML_DOCUMENT_FRAG_NODE
:
5197 case XML_NOTATION_NODE
:
5198 case XML_HTML_DOCUMENT_NODE
:
5199 case XML_NAMESPACE_DECL
:
5200 case XML_XINCLUDE_START
:
5201 case XML_XINCLUDE_END
:
5202 #ifdef LIBXML_DOCB_ENABLED
5203 case XML_DOCB_DOCUMENT_NODE
:
5206 case XML_ELEMENT_NODE
:
5207 case XML_ATTRIBUTE_NODE
:
5209 case XML_ENTITY_REF_NODE
:
5210 case XML_ENTITY_NODE
:
5212 case XML_DOCUMENT_NODE
:
5213 case XML_ELEMENT_DECL
:
5214 case XML_ATTRIBUTE_DECL
:
5215 case XML_ENTITY_DECL
:
5224 if ((cur
->name
!= NULL
) && (!xmlDictOwns(dict
, cur
->name
)))
5226 cur
->name
= xmlDictLookup(dict
, name
, -1);
5228 if (cur
->name
!= NULL
)
5230 cur
->name
= xmlStrdup(name
);
5234 xmlFree((xmlChar
*) freeme
);
5238 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XINCLUDE_ENABLED)
5241 * @cur: the node being changed
5242 * @uri: the new base URI
5244 * Set (or reset) the base URI of a node, i.e. the value of the
5245 * xml:base attribute.
5248 xmlNodeSetBase(xmlNodePtr cur
, const xmlChar
* uri
) {
5252 if (cur
== NULL
) return;
5255 case XML_CDATA_SECTION_NODE
:
5256 case XML_COMMENT_NODE
:
5257 case XML_DOCUMENT_TYPE_NODE
:
5258 case XML_DOCUMENT_FRAG_NODE
:
5259 case XML_NOTATION_NODE
:
5261 case XML_ELEMENT_DECL
:
5262 case XML_ATTRIBUTE_DECL
:
5263 case XML_ENTITY_DECL
:
5265 case XML_ENTITY_REF_NODE
:
5266 case XML_ENTITY_NODE
:
5267 case XML_NAMESPACE_DECL
:
5268 case XML_XINCLUDE_START
:
5269 case XML_XINCLUDE_END
:
5271 case XML_ELEMENT_NODE
:
5272 case XML_ATTRIBUTE_NODE
:
5274 case XML_DOCUMENT_NODE
:
5275 #ifdef LIBXML_DOCB_ENABLED
5276 case XML_DOCB_DOCUMENT_NODE
:
5278 case XML_HTML_DOCUMENT_NODE
: {
5279 xmlDocPtr doc
= (xmlDocPtr
) cur
;
5281 if (doc
->URL
!= NULL
)
5282 xmlFree((xmlChar
*) doc
->URL
);
5286 doc
->URL
= xmlPathToURI(uri
);
5291 ns
= xmlSearchNsByHref(cur
->doc
, cur
, XML_XML_NAMESPACE
);
5294 fixed
= xmlPathToURI(uri
);
5295 if (fixed
!= NULL
) {
5296 xmlSetNsProp(cur
, ns
, BAD_CAST
"base", fixed
);
5299 xmlSetNsProp(cur
, ns
, BAD_CAST
"base", uri
);
5302 #endif /* LIBXML_TREE_ENABLED */
5306 * @doc: the document the node pertains to
5307 * @cur: the node being checked
5309 * Searches for the BASE URL. The code should work on both XML
5310 * and HTML document even if base mechanisms are completely different.
5311 * It returns the base as defined in RFC 2396 sections
5312 * 5.1.1. Base URI within Document Content
5314 * 5.1.2. Base URI from the Encapsulating Entity
5315 * However it does not return the document base (5.1.3), use
5316 * doc->URL in this case
5318 * Returns a pointer to the base URL, or NULL if not found
5319 * It's up to the caller to free the memory with xmlFree().
5322 xmlNodeGetBase(const xmlDoc
*doc
, const xmlNode
*cur
) {
5323 xmlChar
*oldbase
= NULL
;
5324 xmlChar
*base
, *newbase
;
5326 if ((cur
== NULL
) && (doc
== NULL
))
5328 if ((cur
!= NULL
) && (cur
->type
== XML_NAMESPACE_DECL
))
5330 if (doc
== NULL
) doc
= cur
->doc
;
5331 if ((doc
!= NULL
) && (doc
->type
== XML_HTML_DOCUMENT_NODE
)) {
5332 cur
= doc
->children
;
5333 while ((cur
!= NULL
) && (cur
->name
!= NULL
)) {
5334 if (cur
->type
!= XML_ELEMENT_NODE
) {
5338 if (!xmlStrcasecmp(cur
->name
, BAD_CAST
"html")) {
5339 cur
= cur
->children
;
5342 if (!xmlStrcasecmp(cur
->name
, BAD_CAST
"head")) {
5343 cur
= cur
->children
;
5346 if (!xmlStrcasecmp(cur
->name
, BAD_CAST
"base")) {
5347 return(xmlGetProp(cur
, BAD_CAST
"href"));
5353 while (cur
!= NULL
) {
5354 if (cur
->type
== XML_ENTITY_DECL
) {
5355 xmlEntityPtr ent
= (xmlEntityPtr
) cur
;
5356 return(xmlStrdup(ent
->URI
));
5358 if (cur
->type
== XML_ELEMENT_NODE
) {
5359 base
= xmlGetNsProp(cur
, BAD_CAST
"base", XML_XML_NAMESPACE
);
5361 if (oldbase
!= NULL
) {
5362 newbase
= xmlBuildURI(oldbase
, base
);
5363 if (newbase
!= NULL
) {
5375 if ((!xmlStrncmp(oldbase
, BAD_CAST
"http://", 7)) ||
5376 (!xmlStrncmp(oldbase
, BAD_CAST
"ftp://", 6)) ||
5377 (!xmlStrncmp(oldbase
, BAD_CAST
"urn:", 4)))
5383 if ((doc
!= NULL
) && (doc
->URL
!= NULL
)) {
5384 if (oldbase
== NULL
)
5385 return(xmlStrdup(doc
->URL
));
5386 newbase
= xmlBuildURI(oldbase
, doc
->URL
);
5394 * xmlNodeBufGetContent:
5396 * @cur: the node being read
5398 * Read the value of a node @cur, this can be either the text carried
5399 * directly by this node if it's a TEXT node or the aggregate string
5400 * of the values carried by this node child's (TEXT and ENTITY_REF).
5401 * Entity references are substituted.
5402 * Fills up the buffer @buffer with this value
5404 * Returns 0 in case of success and -1 in case of error.
5407 xmlNodeBufGetContent(xmlBufferPtr buffer
, const xmlNode
*cur
)
5412 if ((cur
== NULL
) || (buffer
== NULL
)) return(-1);
5413 buf
= xmlBufFromBuffer(buffer
);
5414 ret
= xmlBufGetNodeContent(buf
, cur
);
5415 buffer
= xmlBufBackToBuffer(buf
);
5416 if ((ret
< 0) || (buffer
== NULL
))
5422 * xmlBufGetNodeContent:
5423 * @buf: a buffer xmlBufPtr
5424 * @cur: the node being read
5426 * Read the value of a node @cur, this can be either the text carried
5427 * directly by this node if it's a TEXT node or the aggregate string
5428 * of the values carried by this node child's (TEXT and ENTITY_REF).
5429 * Entity references are substituted.
5430 * Fills up the buffer @buf with this value
5432 * Returns 0 in case of success and -1 in case of error.
5435 xmlBufGetNodeContent(xmlBufPtr buf
, const xmlNode
*cur
)
5437 if ((cur
== NULL
) || (buf
== NULL
)) return(-1);
5438 switch (cur
->type
) {
5439 case XML_CDATA_SECTION_NODE
:
5441 xmlBufCat(buf
, cur
->content
);
5443 case XML_DOCUMENT_FRAG_NODE
:
5444 case XML_ELEMENT_NODE
:{
5445 const xmlNode
*tmp
= cur
;
5447 while (tmp
!= NULL
) {
5448 switch (tmp
->type
) {
5449 case XML_CDATA_SECTION_NODE
:
5451 if (tmp
->content
!= NULL
)
5452 xmlBufCat(buf
, tmp
->content
);
5454 case XML_ENTITY_REF_NODE
:
5455 xmlBufGetNodeContent(buf
, tmp
);
5463 if (tmp
->children
!= NULL
) {
5464 if (tmp
->children
->type
!= XML_ENTITY_DECL
) {
5465 tmp
= tmp
->children
;
5472 if (tmp
->next
!= NULL
) {
5485 if (tmp
->next
!= NULL
) {
5489 } while (tmp
!= NULL
);
5493 case XML_ATTRIBUTE_NODE
:{
5494 xmlAttrPtr attr
= (xmlAttrPtr
) cur
;
5495 xmlNodePtr tmp
= attr
->children
;
5497 while (tmp
!= NULL
) {
5498 if (tmp
->type
== XML_TEXT_NODE
)
5499 xmlBufCat(buf
, tmp
->content
);
5501 xmlBufGetNodeContent(buf
, tmp
);
5506 case XML_COMMENT_NODE
:
5508 xmlBufCat(buf
, cur
->content
);
5510 case XML_ENTITY_REF_NODE
:{
5514 /* lookup entity declaration */
5515 ent
= xmlGetDocEntity(cur
->doc
, cur
->name
);
5519 /* an entity content can be any "well balanced chunk",
5520 * i.e. the result of the content [43] production:
5521 * http://www.w3.org/TR/REC-xml#NT-content
5522 * -> we iterate through child nodes and recursive call
5523 * xmlNodeGetContent() which handles all possible node types */
5524 tmp
= ent
->children
;
5526 xmlBufGetNodeContent(buf
, tmp
);
5531 case XML_ENTITY_NODE
:
5532 case XML_DOCUMENT_TYPE_NODE
:
5533 case XML_NOTATION_NODE
:
5535 case XML_XINCLUDE_START
:
5536 case XML_XINCLUDE_END
:
5538 case XML_DOCUMENT_NODE
:
5539 #ifdef LIBXML_DOCB_ENABLED
5540 case XML_DOCB_DOCUMENT_NODE
:
5542 case XML_HTML_DOCUMENT_NODE
:
5543 cur
= cur
->children
;
5544 while (cur
!= NULL
) {
5545 if ((cur
->type
== XML_ELEMENT_NODE
) ||
5546 (cur
->type
== XML_TEXT_NODE
) ||
5547 (cur
->type
== XML_CDATA_SECTION_NODE
)) {
5548 xmlBufGetNodeContent(buf
, cur
);
5553 case XML_NAMESPACE_DECL
:
5554 xmlBufCat(buf
, ((xmlNsPtr
) cur
)->href
);
5556 case XML_ELEMENT_DECL
:
5557 case XML_ATTRIBUTE_DECL
:
5558 case XML_ENTITY_DECL
:
5565 * xmlNodeGetContent:
5566 * @cur: the node being read
5568 * Read the value of a node, this can be either the text carried
5569 * directly by this node if it's a TEXT node or the aggregate string
5570 * of the values carried by this node child's (TEXT and ENTITY_REF).
5571 * Entity references are substituted.
5572 * Returns a new #xmlChar * or NULL if no content is available.
5573 * It's up to the caller to free the memory with xmlFree().
5576 xmlNodeGetContent(const xmlNode
*cur
)
5580 switch (cur
->type
) {
5581 case XML_DOCUMENT_FRAG_NODE
:
5582 case XML_ELEMENT_NODE
:{
5586 buf
= xmlBufCreateSize(64);
5589 xmlBufGetNodeContent(buf
, cur
);
5590 ret
= xmlBufDetach(buf
);
5594 case XML_ATTRIBUTE_NODE
:
5595 return(xmlGetPropNodeValueInternal((xmlAttrPtr
) cur
));
5596 case XML_COMMENT_NODE
:
5598 if (cur
->content
!= NULL
)
5599 return (xmlStrdup(cur
->content
));
5601 case XML_ENTITY_REF_NODE
:{
5606 /* lookup entity declaration */
5607 ent
= xmlGetDocEntity(cur
->doc
, cur
->name
);
5611 buf
= xmlBufCreate();
5615 xmlBufGetNodeContent(buf
, cur
);
5617 ret
= xmlBufDetach(buf
);
5621 case XML_ENTITY_NODE
:
5622 case XML_DOCUMENT_TYPE_NODE
:
5623 case XML_NOTATION_NODE
:
5625 case XML_XINCLUDE_START
:
5626 case XML_XINCLUDE_END
:
5628 case XML_DOCUMENT_NODE
:
5629 #ifdef LIBXML_DOCB_ENABLED
5630 case XML_DOCB_DOCUMENT_NODE
:
5632 case XML_HTML_DOCUMENT_NODE
: {
5636 buf
= xmlBufCreate();
5640 xmlBufGetNodeContent(buf
, (xmlNodePtr
) cur
);
5642 ret
= xmlBufDetach(buf
);
5646 case XML_NAMESPACE_DECL
: {
5649 tmp
= xmlStrdup(((xmlNsPtr
) cur
)->href
);
5652 case XML_ELEMENT_DECL
:
5655 case XML_ATTRIBUTE_DECL
:
5658 case XML_ENTITY_DECL
:
5661 case XML_CDATA_SECTION_NODE
:
5663 if (cur
->content
!= NULL
)
5664 return (xmlStrdup(cur
->content
));
5671 * xmlNodeSetContent:
5672 * @cur: the node being modified
5673 * @content: the new value of the content
5675 * Replace the content of a node.
5676 * NOTE: @content is supposed to be a piece of XML CDATA, so it allows entity
5677 * references, but XML special chars need to be escaped first by using
5678 * xmlEncodeEntitiesReentrant() resp. xmlEncodeSpecialChars().
5681 xmlNodeSetContent(xmlNodePtr cur
, const xmlChar
*content
) {
5684 xmlGenericError(xmlGenericErrorContext
,
5685 "xmlNodeSetContent : node == NULL\n");
5689 switch (cur
->type
) {
5690 case XML_DOCUMENT_FRAG_NODE
:
5691 case XML_ELEMENT_NODE
:
5692 case XML_ATTRIBUTE_NODE
:
5693 if (cur
->children
!= NULL
) xmlFreeNodeList(cur
->children
);
5694 cur
->children
= xmlStringGetNodeList(cur
->doc
, content
);
5695 UPDATE_LAST_CHILD_AND_PARENT(cur
)
5698 case XML_CDATA_SECTION_NODE
:
5699 case XML_ENTITY_REF_NODE
:
5700 case XML_ENTITY_NODE
:
5702 case XML_COMMENT_NODE
:
5703 if ((cur
->content
!= NULL
) &&
5704 (cur
->content
!= (xmlChar
*) &(cur
->properties
))) {
5705 if (!((cur
->doc
!= NULL
) && (cur
->doc
->dict
!= NULL
) &&
5706 (xmlDictOwns(cur
->doc
->dict
, cur
->content
))))
5707 xmlFree(cur
->content
);
5709 if (cur
->children
!= NULL
) xmlFreeNodeList(cur
->children
);
5710 cur
->last
= cur
->children
= NULL
;
5711 if (content
!= NULL
) {
5712 cur
->content
= xmlStrdup(content
);
5714 cur
->content
= NULL
;
5715 cur
->properties
= NULL
;
5718 case XML_DOCUMENT_NODE
:
5719 case XML_HTML_DOCUMENT_NODE
:
5720 case XML_DOCUMENT_TYPE_NODE
:
5721 case XML_XINCLUDE_START
:
5722 case XML_XINCLUDE_END
:
5723 #ifdef LIBXML_DOCB_ENABLED
5724 case XML_DOCB_DOCUMENT_NODE
:
5727 case XML_NOTATION_NODE
:
5731 case XML_NAMESPACE_DECL
:
5733 case XML_ELEMENT_DECL
:
5736 case XML_ATTRIBUTE_DECL
:
5739 case XML_ENTITY_DECL
:
5745 #ifdef LIBXML_TREE_ENABLED
5747 * xmlNodeSetContentLen:
5748 * @cur: the node being modified
5749 * @content: the new value of the content
5750 * @len: the size of @content
5752 * Replace the content of a node.
5753 * NOTE: @content is supposed to be a piece of XML CDATA, so it allows entity
5754 * references, but XML special chars need to be escaped first by using
5755 * xmlEncodeEntitiesReentrant() resp. xmlEncodeSpecialChars().
5758 xmlNodeSetContentLen(xmlNodePtr cur
, const xmlChar
*content
, int len
) {
5761 xmlGenericError(xmlGenericErrorContext
,
5762 "xmlNodeSetContentLen : node == NULL\n");
5766 switch (cur
->type
) {
5767 case XML_DOCUMENT_FRAG_NODE
:
5768 case XML_ELEMENT_NODE
:
5769 case XML_ATTRIBUTE_NODE
:
5770 if (cur
->children
!= NULL
) xmlFreeNodeList(cur
->children
);
5771 cur
->children
= xmlStringLenGetNodeList(cur
->doc
, content
, len
);
5772 UPDATE_LAST_CHILD_AND_PARENT(cur
)
5775 case XML_CDATA_SECTION_NODE
:
5776 case XML_ENTITY_REF_NODE
:
5777 case XML_ENTITY_NODE
:
5779 case XML_COMMENT_NODE
:
5780 case XML_NOTATION_NODE
:
5781 if ((cur
->content
!= NULL
) &&
5782 (cur
->content
!= (xmlChar
*) &(cur
->properties
))) {
5783 if (!((cur
->doc
!= NULL
) && (cur
->doc
->dict
!= NULL
) &&
5784 (xmlDictOwns(cur
->doc
->dict
, cur
->content
))))
5785 xmlFree(cur
->content
);
5787 if (cur
->children
!= NULL
) xmlFreeNodeList(cur
->children
);
5788 cur
->children
= cur
->last
= NULL
;
5789 if (content
!= NULL
) {
5790 cur
->content
= xmlStrndup(content
, len
);
5792 cur
->content
= NULL
;
5793 cur
->properties
= NULL
;
5796 case XML_DOCUMENT_NODE
:
5798 case XML_HTML_DOCUMENT_NODE
:
5799 case XML_DOCUMENT_TYPE_NODE
:
5800 case XML_NAMESPACE_DECL
:
5801 case XML_XINCLUDE_START
:
5802 case XML_XINCLUDE_END
:
5803 #ifdef LIBXML_DOCB_ENABLED
5804 case XML_DOCB_DOCUMENT_NODE
:
5807 case XML_ELEMENT_DECL
:
5810 case XML_ATTRIBUTE_DECL
:
5813 case XML_ENTITY_DECL
:
5818 #endif /* LIBXML_TREE_ENABLED */
5821 * xmlNodeAddContentLen:
5822 * @cur: the node being modified
5823 * @content: extra content
5824 * @len: the size of @content
5826 * Append the extra substring to the node content.
5827 * NOTE: In contrast to xmlNodeSetContentLen(), @content is supposed to be
5828 * raw text, so unescaped XML special chars are allowed, entity
5829 * references are not supported.
5832 xmlNodeAddContentLen(xmlNodePtr cur
, const xmlChar
*content
, int len
) {
5835 xmlGenericError(xmlGenericErrorContext
,
5836 "xmlNodeAddContentLen : node == NULL\n");
5840 if (len
<= 0) return;
5841 switch (cur
->type
) {
5842 case XML_DOCUMENT_FRAG_NODE
:
5843 case XML_ELEMENT_NODE
: {
5844 xmlNodePtr last
, newNode
, tmp
;
5847 newNode
= xmlNewTextLen(content
, len
);
5848 if (newNode
!= NULL
) {
5849 tmp
= xmlAddChild(cur
, newNode
);
5852 if ((last
!= NULL
) && (last
->next
== newNode
)) {
5853 xmlTextMerge(last
, newNode
);
5858 case XML_ATTRIBUTE_NODE
:
5861 case XML_CDATA_SECTION_NODE
:
5862 case XML_ENTITY_REF_NODE
:
5863 case XML_ENTITY_NODE
:
5865 case XML_COMMENT_NODE
:
5866 case XML_NOTATION_NODE
:
5867 if (content
!= NULL
) {
5868 if ((cur
->content
== (xmlChar
*) &(cur
->properties
)) ||
5869 ((cur
->doc
!= NULL
) && (cur
->doc
->dict
!= NULL
) &&
5870 xmlDictOwns(cur
->doc
->dict
, cur
->content
))) {
5871 cur
->content
= xmlStrncatNew(cur
->content
, content
, len
);
5872 cur
->properties
= NULL
;
5876 cur
->content
= xmlStrncat(cur
->content
, content
, len
);
5878 case XML_DOCUMENT_NODE
:
5880 case XML_HTML_DOCUMENT_NODE
:
5881 case XML_DOCUMENT_TYPE_NODE
:
5882 case XML_NAMESPACE_DECL
:
5883 case XML_XINCLUDE_START
:
5884 case XML_XINCLUDE_END
:
5885 #ifdef LIBXML_DOCB_ENABLED
5886 case XML_DOCB_DOCUMENT_NODE
:
5889 case XML_ELEMENT_DECL
:
5890 case XML_ATTRIBUTE_DECL
:
5891 case XML_ENTITY_DECL
:
5897 * xmlNodeAddContent:
5898 * @cur: the node being modified
5899 * @content: extra content
5901 * Append the extra substring to the node content.
5902 * NOTE: In contrast to xmlNodeSetContent(), @content is supposed to be
5903 * raw text, so unescaped XML special chars are allowed, entity
5904 * references are not supported.
5907 xmlNodeAddContent(xmlNodePtr cur
, const xmlChar
*content
) {
5912 xmlGenericError(xmlGenericErrorContext
,
5913 "xmlNodeAddContent : node == NULL\n");
5917 if (content
== NULL
) return;
5918 len
= xmlStrlen(content
);
5919 xmlNodeAddContentLen(cur
, content
, len
);
5924 * @first: the first text node
5925 * @second: the second text node being merged
5927 * Merge two text nodes into one
5928 * Returns the first text node augmented
5931 xmlTextMerge(xmlNodePtr first
, xmlNodePtr second
) {
5932 if (first
== NULL
) return(second
);
5933 if (second
== NULL
) return(first
);
5934 if (first
->type
!= XML_TEXT_NODE
) return(first
);
5935 if (second
->type
!= XML_TEXT_NODE
) return(first
);
5936 if (second
->name
!= first
->name
)
5938 xmlNodeAddContent(first
, second
->content
);
5939 xmlUnlinkNode(second
);
5940 xmlFreeNode(second
);
5944 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XPATH_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
5947 * @doc: the document
5948 * @node: the current node
5950 * Search all the namespace applying to a given element.
5951 * Returns an NULL terminated array of all the #xmlNsPtr found
5952 * that need to be freed by the caller or NULL if no
5953 * namespace if defined
5956 xmlGetNsList(const xmlDoc
*doc ATTRIBUTE_UNUSED
, const xmlNode
*node
)
5959 xmlNsPtr
*ret
= NULL
;
5964 if ((node
== NULL
) || (node
->type
== XML_NAMESPACE_DECL
))
5967 while (node
!= NULL
) {
5968 if (node
->type
== XML_ELEMENT_NODE
) {
5970 while (cur
!= NULL
) {
5973 (xmlNsPtr
*) xmlMalloc((maxns
+ 1) *
5976 xmlTreeErrMemory("getting namespace list");
5981 for (i
= 0; i
< nbns
; i
++) {
5982 if ((cur
->prefix
== ret
[i
]->prefix
) ||
5983 (xmlStrEqual(cur
->prefix
, ret
[i
]->prefix
)))
5987 if (nbns
>= maxns
) {
5989 ret
= (xmlNsPtr
*) xmlRealloc(ret
,
5994 xmlTreeErrMemory("getting namespace list");
6005 node
= node
->parent
;
6009 #endif /* LIBXML_TREE_ENABLED */
6012 * xmlTreeEnsureXMLDecl:
6015 * Ensures that there is an XML namespace declaration on the doc.
6017 * Returns the XML ns-struct or NULL on API and internal errors.
6020 xmlTreeEnsureXMLDecl(xmlDocPtr doc
)
6024 if (doc
->oldNs
!= NULL
)
6025 return (doc
->oldNs
);
6028 ns
= (xmlNsPtr
) xmlMalloc(sizeof(xmlNs
));
6031 "allocating the XML namespace");
6034 memset(ns
, 0, sizeof(xmlNs
));
6035 ns
->type
= XML_LOCAL_NAMESPACE
;
6036 ns
->href
= xmlStrdup(XML_XML_NAMESPACE
);
6037 ns
->prefix
= xmlStrdup((const xmlChar
*)"xml");
6045 * @doc: the document
6046 * @node: the current node
6047 * @nameSpace: the namespace prefix
6049 * Search a Ns registered under a given name space for a document.
6050 * recurse on the parents until it finds the defined namespace
6051 * or return NULL otherwise.
6052 * @nameSpace can be NULL, this is a search for the default namespace.
6053 * We don't allow to cross entities boundaries. If you don't declare
6054 * the namespace within those you will be in troubles !!! A warning
6055 * is generated to cover this case.
6057 * Returns the namespace pointer or NULL.
6060 xmlSearchNs(xmlDocPtr doc
, xmlNodePtr node
, const xmlChar
*nameSpace
) {
6063 const xmlNode
*orig
= node
;
6065 if ((node
== NULL
) || (node
->type
== XML_NAMESPACE_DECL
)) return(NULL
);
6066 if ((nameSpace
!= NULL
) &&
6067 (xmlStrEqual(nameSpace
, (const xmlChar
*)"xml"))) {
6068 if ((doc
== NULL
) && (node
->type
== XML_ELEMENT_NODE
)) {
6070 * The XML-1.0 namespace is normally held on the root
6071 * element. In this case exceptionally create it on the
6074 cur
= (xmlNsPtr
) xmlMalloc(sizeof(xmlNs
));
6076 xmlTreeErrMemory("searching namespace");
6079 memset(cur
, 0, sizeof(xmlNs
));
6080 cur
->type
= XML_LOCAL_NAMESPACE
;
6081 cur
->href
= xmlStrdup(XML_XML_NAMESPACE
);
6082 cur
->prefix
= xmlStrdup((const xmlChar
*)"xml");
6083 cur
->next
= node
->nsDef
;
6093 * Return the XML namespace declaration held by the doc.
6095 if (doc
->oldNs
== NULL
)
6096 return(xmlTreeEnsureXMLDecl(doc
));
6100 while (node
!= NULL
) {
6101 if ((node
->type
== XML_ENTITY_REF_NODE
) ||
6102 (node
->type
== XML_ENTITY_NODE
) ||
6103 (node
->type
== XML_ENTITY_DECL
))
6105 if (node
->type
== XML_ELEMENT_NODE
) {
6107 while (cur
!= NULL
) {
6108 if ((cur
->prefix
== NULL
) && (nameSpace
== NULL
) &&
6109 (cur
->href
!= NULL
))
6111 if ((cur
->prefix
!= NULL
) && (nameSpace
!= NULL
) &&
6112 (cur
->href
!= NULL
) &&
6113 (xmlStrEqual(cur
->prefix
, nameSpace
)))
6120 if ((cur
->prefix
== NULL
) && (nameSpace
== NULL
) &&
6121 (cur
->href
!= NULL
))
6123 if ((cur
->prefix
!= NULL
) && (nameSpace
!= NULL
) &&
6124 (cur
->href
!= NULL
) &&
6125 (xmlStrEqual(cur
->prefix
, nameSpace
)))
6130 node
= node
->parent
;
6137 * @doc: the document
6138 * @node: the current node
6139 * @ancestor: the ancestor carrying the namespace
6140 * @prefix: the namespace prefix
6142 * Verify that the given namespace held on @ancestor is still in scope
6145 * Returns 1 if true, 0 if false and -1 in case of error.
6148 xmlNsInScope(xmlDocPtr doc ATTRIBUTE_UNUSED
, xmlNodePtr node
,
6149 xmlNodePtr ancestor
, const xmlChar
* prefix
)
6153 while ((node
!= NULL
) && (node
!= ancestor
)) {
6154 if ((node
->type
== XML_ENTITY_REF_NODE
) ||
6155 (node
->type
== XML_ENTITY_NODE
) ||
6156 (node
->type
== XML_ENTITY_DECL
))
6158 if (node
->type
== XML_ELEMENT_NODE
) {
6160 while (tst
!= NULL
) {
6161 if ((tst
->prefix
== NULL
)
6162 && (prefix
== NULL
))
6164 if ((tst
->prefix
!= NULL
)
6166 && (xmlStrEqual(tst
->prefix
, prefix
)))
6171 node
= node
->parent
;
6173 if (node
!= ancestor
)
6179 * xmlSearchNsByHref:
6180 * @doc: the document
6181 * @node: the current node
6182 * @href: the namespace value
6184 * Search a Ns aliasing a given URI. Recurse on the parents until it finds
6185 * the defined namespace or return NULL otherwise.
6186 * Returns the namespace pointer or NULL.
6189 xmlSearchNsByHref(xmlDocPtr doc
, xmlNodePtr node
, const xmlChar
* href
)
6192 xmlNodePtr orig
= node
;
6195 if ((node
== NULL
) || (node
->type
== XML_NAMESPACE_DECL
) || (href
== NULL
))
6197 if (xmlStrEqual(href
, XML_XML_NAMESPACE
)) {
6199 * Only the document can hold the XML spec namespace.
6201 if ((doc
== NULL
) && (node
->type
== XML_ELEMENT_NODE
)) {
6203 * The XML-1.0 namespace is normally held on the root
6204 * element. In this case exceptionally create it on the
6207 cur
= (xmlNsPtr
) xmlMalloc(sizeof(xmlNs
));
6209 xmlTreeErrMemory("searching namespace");
6212 memset(cur
, 0, sizeof(xmlNs
));
6213 cur
->type
= XML_LOCAL_NAMESPACE
;
6214 cur
->href
= xmlStrdup(XML_XML_NAMESPACE
);
6215 cur
->prefix
= xmlStrdup((const xmlChar
*) "xml");
6216 cur
->next
= node
->nsDef
;
6226 * Return the XML namespace declaration held by the doc.
6228 if (doc
->oldNs
== NULL
)
6229 return(xmlTreeEnsureXMLDecl(doc
));
6233 is_attr
= (node
->type
== XML_ATTRIBUTE_NODE
);
6234 while (node
!= NULL
) {
6235 if ((node
->type
== XML_ENTITY_REF_NODE
) ||
6236 (node
->type
== XML_ENTITY_NODE
) ||
6237 (node
->type
== XML_ENTITY_DECL
))
6239 if (node
->type
== XML_ELEMENT_NODE
) {
6241 while (cur
!= NULL
) {
6242 if ((cur
->href
!= NULL
) && (href
!= NULL
) &&
6243 (xmlStrEqual(cur
->href
, href
))) {
6244 if (((!is_attr
) || (cur
->prefix
!= NULL
)) &&
6245 (xmlNsInScope(doc
, orig
, node
, cur
->prefix
) == 1))
6253 if ((cur
->href
!= NULL
) && (href
!= NULL
) &&
6254 (xmlStrEqual(cur
->href
, href
))) {
6255 if (((!is_attr
) || (cur
->prefix
!= NULL
)) &&
6256 (xmlNsInScope(doc
, orig
, node
, cur
->prefix
) == 1))
6262 node
= node
->parent
;
6268 * xmlNewReconciledNs:
6269 * @doc: the document
6270 * @tree: a node expected to hold the new namespace
6271 * @ns: the original namespace
6273 * This function tries to locate a namespace definition in a tree
6274 * ancestors, or create a new namespace definition node similar to
6275 * @ns trying to reuse the same prefix. However if the given prefix is
6276 * null (default namespace) or reused within the subtree defined by
6277 * @tree or on one of its ancestors then a new prefix is generated.
6278 * Returns the (new) namespace definition or NULL in case of error
6281 xmlNewReconciledNs(xmlDocPtr doc
, xmlNodePtr tree
, xmlNsPtr ns
) {
6286 if ((tree
== NULL
) || (tree
->type
!= XML_ELEMENT_NODE
)) {
6288 xmlGenericError(xmlGenericErrorContext
,
6289 "xmlNewReconciledNs : tree == NULL\n");
6293 if ((ns
== NULL
) || (ns
->type
!= XML_NAMESPACE_DECL
)) {
6295 xmlGenericError(xmlGenericErrorContext
,
6296 "xmlNewReconciledNs : ns == NULL\n");
6301 * Search an existing namespace definition inherited.
6303 def
= xmlSearchNsByHref(doc
, tree
, ns
->href
);
6308 * Find a close prefix which is not already in use.
6309 * Let's strip namespace prefixes longer than 20 chars !
6311 if (ns
->prefix
== NULL
)
6312 snprintf((char *) prefix
, sizeof(prefix
), "default");
6314 snprintf((char *) prefix
, sizeof(prefix
), "%.20s", (char *)ns
->prefix
);
6316 def
= xmlSearchNs(doc
, tree
, prefix
);
6317 while (def
!= NULL
) {
6318 if (counter
> 1000) return(NULL
);
6319 if (ns
->prefix
== NULL
)
6320 snprintf((char *) prefix
, sizeof(prefix
), "default%d", counter
++);
6322 snprintf((char *) prefix
, sizeof(prefix
), "%.20s%d",
6323 (char *)ns
->prefix
, counter
++);
6324 def
= xmlSearchNs(doc
, tree
, prefix
);
6328 * OK, now we are ready to create a new one.
6330 def
= xmlNewNs(tree
, ns
->href
, prefix
);
6334 #ifdef LIBXML_TREE_ENABLED
6336 * xmlReconciliateNs:
6337 * @doc: the document
6338 * @tree: a node defining the subtree to reconciliate
6340 * This function checks that all the namespaces declared within the given
6341 * tree are properly declared. This is needed for example after Copy or Cut
6342 * and then paste operations. The subtree may still hold pointers to
6343 * namespace declarations outside the subtree or invalid/masked. As much
6344 * as possible the function try to reuse the existing namespaces found in
6345 * the new environment. If not possible the new namespaces are redeclared
6346 * on @tree at the top of the given subtree.
6347 * Returns the number of namespace declarations created or -1 in case of error.
6350 xmlReconciliateNs(xmlDocPtr doc
, xmlNodePtr tree
) {
6351 xmlNsPtr
*oldNs
= NULL
;
6352 xmlNsPtr
*newNs
= NULL
;
6357 xmlNodePtr node
= tree
;
6361 if ((node
== NULL
) || (node
->type
!= XML_ELEMENT_NODE
)) return(-1);
6362 if ((doc
== NULL
) || (doc
->type
!= XML_DOCUMENT_NODE
)) return(-1);
6363 if (node
->doc
!= doc
) return(-1);
6364 while (node
!= NULL
) {
6366 * Reconciliate the node namespace
6368 if (node
->ns
!= NULL
) {
6370 * initialize the cache if needed
6372 if (sizeCache
== 0) {
6374 oldNs
= (xmlNsPtr
*) xmlMalloc(sizeCache
*
6376 if (oldNs
== NULL
) {
6377 xmlTreeErrMemory("fixing namespaces");
6380 newNs
= (xmlNsPtr
*) xmlMalloc(sizeCache
*
6382 if (newNs
== NULL
) {
6383 xmlTreeErrMemory("fixing namespaces");
6388 for (i
= 0;i
< nbCache
;i
++) {
6389 if (oldNs
[i
] == node
->ns
) {
6390 node
->ns
= newNs
[i
];
6396 * OK we need to recreate a new namespace definition
6398 n
= xmlNewReconciledNs(doc
, tree
, node
->ns
);
6399 if (n
!= NULL
) { /* :-( what if else ??? */
6401 * check if we need to grow the cache buffers.
6403 if (sizeCache
<= nbCache
) {
6405 oldNs
= (xmlNsPtr
*) xmlRealloc(oldNs
, sizeCache
*
6407 if (oldNs
== NULL
) {
6408 xmlTreeErrMemory("fixing namespaces");
6412 newNs
= (xmlNsPtr
*) xmlRealloc(newNs
, sizeCache
*
6414 if (newNs
== NULL
) {
6415 xmlTreeErrMemory("fixing namespaces");
6421 oldNs
[nbCache
++] = node
->ns
;
6427 * now check for namespace held by attributes on the node.
6429 if (node
->type
== XML_ELEMENT_NODE
) {
6430 attr
= node
->properties
;
6431 while (attr
!= NULL
) {
6432 if (attr
->ns
!= NULL
) {
6434 * initialize the cache if needed
6436 if (sizeCache
== 0) {
6438 oldNs
= (xmlNsPtr
*) xmlMalloc(sizeCache
*
6440 if (oldNs
== NULL
) {
6441 xmlTreeErrMemory("fixing namespaces");
6444 newNs
= (xmlNsPtr
*) xmlMalloc(sizeCache
*
6446 if (newNs
== NULL
) {
6447 xmlTreeErrMemory("fixing namespaces");
6452 for (i
= 0;i
< nbCache
;i
++) {
6453 if (oldNs
[i
] == attr
->ns
) {
6454 attr
->ns
= newNs
[i
];
6460 * OK we need to recreate a new namespace definition
6462 n
= xmlNewReconciledNs(doc
, tree
, attr
->ns
);
6463 if (n
!= NULL
) { /* :-( what if else ??? */
6465 * check if we need to grow the cache buffers.
6467 if (sizeCache
<= nbCache
) {
6469 oldNs
= (xmlNsPtr
*) xmlRealloc(oldNs
,
6470 sizeCache
* sizeof(xmlNsPtr
));
6471 if (oldNs
== NULL
) {
6472 xmlTreeErrMemory("fixing namespaces");
6476 newNs
= (xmlNsPtr
*) xmlRealloc(newNs
,
6477 sizeCache
* sizeof(xmlNsPtr
));
6478 if (newNs
== NULL
) {
6479 xmlTreeErrMemory("fixing namespaces");
6485 oldNs
[nbCache
++] = attr
->ns
;
6495 * Browse the full subtree, deep first
6497 if ((node
->children
!= NULL
) && (node
->type
!= XML_ENTITY_REF_NODE
)) {
6499 node
= node
->children
;
6500 } else if ((node
!= tree
) && (node
->next
!= NULL
)) {
6503 } else if (node
!= tree
) {
6504 /* go up to parents->next if needed */
6505 while (node
!= tree
) {
6506 if (node
->parent
!= NULL
)
6507 node
= node
->parent
;
6508 if ((node
!= tree
) && (node
->next
!= NULL
)) {
6512 if (node
->parent
== NULL
) {
6517 /* exit condition */
6529 #endif /* LIBXML_TREE_ENABLED */
6532 xmlGetPropNodeInternal(const xmlNode
*node
, const xmlChar
*name
,
6533 const xmlChar
*nsName
, int useDTD
)
6537 if ((node
== NULL
) || (node
->type
!= XML_ELEMENT_NODE
) || (name
== NULL
))
6540 if (node
->properties
!= NULL
) {
6541 prop
= node
->properties
;
6542 if (nsName
== NULL
) {
6544 * We want the attr to be in no namespace.
6547 if ((prop
->ns
== NULL
) && xmlStrEqual(prop
->name
, name
)) {
6551 } while (prop
!= NULL
);
6554 * We want the attr to be in the specified namespace.
6557 if ((prop
->ns
!= NULL
) && xmlStrEqual(prop
->name
, name
) &&
6558 ((prop
->ns
->href
== nsName
) ||
6559 xmlStrEqual(prop
->ns
->href
, nsName
)))
6564 } while (prop
!= NULL
);
6568 #ifdef LIBXML_TREE_ENABLED
6572 * Check if there is a default/fixed attribute declaration in
6573 * the internal or external subset.
6575 if ((node
->doc
!= NULL
) && (node
->doc
->intSubset
!= NULL
)) {
6576 xmlDocPtr doc
= node
->doc
;
6577 xmlAttributePtr attrDecl
= NULL
;
6578 xmlChar
*elemQName
, *tmpstr
= NULL
;
6581 * We need the QName of the element for the DTD-lookup.
6583 if ((node
->ns
!= NULL
) && (node
->ns
->prefix
!= NULL
)) {
6584 tmpstr
= xmlStrdup(node
->ns
->prefix
);
6585 tmpstr
= xmlStrcat(tmpstr
, BAD_CAST
":");
6586 tmpstr
= xmlStrcat(tmpstr
, node
->name
);
6591 elemQName
= (xmlChar
*) node
->name
;
6592 if (nsName
== NULL
) {
6594 * The common and nice case: Attr in no namespace.
6596 attrDecl
= xmlGetDtdQAttrDesc(doc
->intSubset
,
6597 elemQName
, name
, NULL
);
6598 if ((attrDecl
== NULL
) && (doc
->extSubset
!= NULL
)) {
6599 attrDecl
= xmlGetDtdQAttrDesc(doc
->extSubset
,
6600 elemQName
, name
, NULL
);
6602 } else if (xmlStrEqual(nsName
, XML_XML_NAMESPACE
)) {
6604 * The XML namespace must be bound to prefix 'xml'.
6606 attrDecl
= xmlGetDtdQAttrDesc(doc
->intSubset
,
6607 elemQName
, name
, BAD_CAST
"xml");
6608 if ((attrDecl
== NULL
) && (doc
->extSubset
!= NULL
)) {
6609 attrDecl
= xmlGetDtdQAttrDesc(doc
->extSubset
,
6610 elemQName
, name
, BAD_CAST
"xml");
6613 xmlNsPtr
*nsList
, *cur
;
6616 * The ugly case: Search using the prefixes of in-scope
6617 * ns-decls corresponding to @nsName.
6619 nsList
= xmlGetNsList(node
->doc
, node
);
6620 if (nsList
== NULL
) {
6626 while (*cur
!= NULL
) {
6627 if (xmlStrEqual((*cur
)->href
, nsName
)) {
6628 attrDecl
= xmlGetDtdQAttrDesc(doc
->intSubset
, elemQName
,
6629 name
, (*cur
)->prefix
);
6632 if (doc
->extSubset
!= NULL
) {
6633 attrDecl
= xmlGetDtdQAttrDesc(doc
->extSubset
, elemQName
,
6634 name
, (*cur
)->prefix
);
6646 * Only default/fixed attrs are relevant.
6648 if ((attrDecl
!= NULL
) && (attrDecl
->defaultValue
!= NULL
))
6649 return((xmlAttrPtr
) attrDecl
);
6651 #endif /* LIBXML_TREE_ENABLED */
6656 xmlGetPropNodeValueInternal(const xmlAttr
*prop
)
6660 if (prop
->type
== XML_ATTRIBUTE_NODE
) {
6662 * Note that we return at least the empty string.
6663 * TODO: Do we really always want that?
6665 if (prop
->children
!= NULL
) {
6666 if ((prop
->children
->next
== NULL
) &&
6667 ((prop
->children
->type
== XML_TEXT_NODE
) ||
6668 (prop
->children
->type
== XML_CDATA_SECTION_NODE
)))
6671 * Optimization for the common case: only 1 text node.
6673 return(xmlStrdup(prop
->children
->content
));
6677 ret
= xmlNodeListGetString(prop
->doc
, prop
->children
, 1);
6682 return(xmlStrdup((xmlChar
*)""));
6683 } else if (prop
->type
== XML_ATTRIBUTE_DECL
) {
6684 return(xmlStrdup(((xmlAttributePtr
)prop
)->defaultValue
));
6692 * @name: the attribute name
6694 * Search an attribute associated to a node
6695 * This function also looks in DTD attribute declaration for #FIXED or
6696 * default declaration values unless DTD use has been turned off.
6698 * Returns the attribute or the attribute declaration or NULL if
6699 * neither was found.
6702 xmlHasProp(const xmlNode
*node
, const xmlChar
*name
) {
6706 if ((node
== NULL
) || (node
->type
!= XML_ELEMENT_NODE
) || (name
== NULL
))
6709 * Check on the properties attached to the node
6711 prop
= node
->properties
;
6712 while (prop
!= NULL
) {
6713 if (xmlStrEqual(prop
->name
, name
)) {
6718 if (!xmlCheckDTD
) return(NULL
);
6721 * Check if there is a default declaration in the internal
6722 * or external subsets
6726 xmlAttributePtr attrDecl
;
6727 if (doc
->intSubset
!= NULL
) {
6728 attrDecl
= xmlGetDtdAttrDesc(doc
->intSubset
, node
->name
, name
);
6729 if ((attrDecl
== NULL
) && (doc
->extSubset
!= NULL
))
6730 attrDecl
= xmlGetDtdAttrDesc(doc
->extSubset
, node
->name
, name
);
6731 if ((attrDecl
!= NULL
) && (attrDecl
->defaultValue
!= NULL
))
6732 /* return attribute declaration only if a default value is given
6733 (that includes #FIXED declarations) */
6734 return((xmlAttrPtr
) attrDecl
);
6743 * @name: the attribute name
6744 * @nameSpace: the URI of the namespace
6746 * Search for an attribute associated to a node
6747 * This attribute has to be anchored in the namespace specified.
6748 * This does the entity substitution.
6749 * This function looks in DTD attribute declaration for #FIXED or
6750 * default declaration values unless DTD use has been turned off.
6751 * Note that a namespace of NULL indicates to use the default namespace.
6753 * Returns the attribute or the attribute declaration or NULL
6754 * if neither was found.
6757 xmlHasNsProp(const xmlNode
*node
, const xmlChar
*name
, const xmlChar
*nameSpace
) {
6759 return(xmlGetPropNodeInternal(node
, name
, nameSpace
, xmlCheckDTD
));
6765 * @name: the attribute name
6767 * Search and get the value of an attribute associated to a node
6768 * This does the entity substitution.
6769 * This function looks in DTD attribute declaration for #FIXED or
6770 * default declaration values unless DTD use has been turned off.
6771 * NOTE: this function acts independently of namespaces associated
6772 * to the attribute. Use xmlGetNsProp() or xmlGetNoNsProp()
6773 * for namespace aware processing.
6775 * Returns the attribute value or NULL if not found.
6776 * It's up to the caller to free the memory with xmlFree().
6779 xmlGetProp(const xmlNode
*node
, const xmlChar
*name
) {
6782 prop
= xmlHasProp(node
, name
);
6785 return(xmlGetPropNodeValueInternal(prop
));
6791 * @name: the attribute name
6793 * Search and get the value of an attribute associated to a node
6794 * This does the entity substitution.
6795 * This function looks in DTD attribute declaration for #FIXED or
6796 * default declaration values unless DTD use has been turned off.
6797 * This function is similar to xmlGetProp except it will accept only
6798 * an attribute in no namespace.
6800 * Returns the attribute value or NULL if not found.
6801 * It's up to the caller to free the memory with xmlFree().
6804 xmlGetNoNsProp(const xmlNode
*node
, const xmlChar
*name
) {
6807 prop
= xmlGetPropNodeInternal(node
, name
, NULL
, xmlCheckDTD
);
6810 return(xmlGetPropNodeValueInternal(prop
));
6816 * @name: the attribute name
6817 * @nameSpace: the URI of the namespace
6819 * Search and get the value of an attribute associated to a node
6820 * This attribute has to be anchored in the namespace specified.
6821 * This does the entity substitution.
6822 * This function looks in DTD attribute declaration for #FIXED or
6823 * default declaration values unless DTD use has been turned off.
6825 * Returns the attribute value or NULL if not found.
6826 * It's up to the caller to free the memory with xmlFree().
6829 xmlGetNsProp(const xmlNode
*node
, const xmlChar
*name
, const xmlChar
*nameSpace
) {
6832 prop
= xmlGetPropNodeInternal(node
, name
, nameSpace
, xmlCheckDTD
);
6835 return(xmlGetPropNodeValueInternal(prop
));
6838 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
6842 * @name: the attribute name
6844 * Remove an attribute carried by a node.
6845 * This handles only attributes in no namespace.
6846 * Returns 0 if successful, -1 if not found
6849 xmlUnsetProp(xmlNodePtr node
, const xmlChar
*name
) {
6852 prop
= xmlGetPropNodeInternal(node
, name
, NULL
, 0);
6855 xmlUnlinkNode((xmlNodePtr
) prop
);
6863 * @ns: the namespace definition
6864 * @name: the attribute name
6866 * Remove an attribute carried by a node.
6867 * Returns 0 if successful, -1 if not found
6870 xmlUnsetNsProp(xmlNodePtr node
, xmlNsPtr ns
, const xmlChar
*name
) {
6873 prop
= xmlGetPropNodeInternal(node
, name
, (ns
!= NULL
) ? ns
->href
: NULL
, 0);
6876 xmlUnlinkNode((xmlNodePtr
) prop
);
6882 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XINCLUDE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) || defined(LIBXML_HTML_ENABLED)
6886 * @name: the attribute name (a QName)
6887 * @value: the attribute value
6889 * Set (or reset) an attribute carried by a node.
6890 * If @name has a prefix, then the corresponding
6891 * namespace-binding will be used, if in scope; it is an
6892 * error it there's no such ns-binding for the prefix in
6894 * Returns the attribute pointer.
6898 xmlSetProp(xmlNodePtr node
, const xmlChar
*name
, const xmlChar
*value
) {
6900 const xmlChar
*nqname
;
6902 if ((node
== NULL
) || (name
== NULL
) || (node
->type
!= XML_ELEMENT_NODE
))
6908 nqname
= xmlSplitQName3(name
, &len
);
6909 if (nqname
!= NULL
) {
6911 xmlChar
*prefix
= xmlStrndup(name
, len
);
6912 ns
= xmlSearchNs(node
->doc
, node
, prefix
);
6916 return(xmlSetNsProp(node
, ns
, nqname
, value
));
6918 return(xmlSetNsProp(node
, NULL
, name
, value
));
6924 * @ns: the namespace definition
6925 * @name: the attribute name
6926 * @value: the attribute value
6928 * Set (or reset) an attribute carried by a node.
6929 * The ns structure must be in scope, this is not checked
6931 * Returns the attribute pointer.
6934 xmlSetNsProp(xmlNodePtr node
, xmlNsPtr ns
, const xmlChar
*name
,
6935 const xmlChar
*value
)
6939 if (ns
&& (ns
->href
== NULL
))
6941 prop
= xmlGetPropNodeInternal(node
, name
, (ns
!= NULL
) ? ns
->href
: NULL
, 0);
6944 * Modify the attribute's value.
6946 if (prop
->atype
== XML_ATTRIBUTE_ID
) {
6947 xmlRemoveID(node
->doc
, prop
);
6948 prop
->atype
= XML_ATTRIBUTE_ID
;
6950 if (prop
->children
!= NULL
)
6951 xmlFreeNodeList(prop
->children
);
6952 prop
->children
= NULL
;
6955 if (value
!= NULL
) {
6958 prop
->children
= xmlNewDocText(node
->doc
, value
);
6960 tmp
= prop
->children
;
6961 while (tmp
!= NULL
) {
6962 tmp
->parent
= (xmlNodePtr
) prop
;
6963 if (tmp
->next
== NULL
)
6968 if (prop
->atype
== XML_ATTRIBUTE_ID
)
6969 xmlAddID(NULL
, node
->doc
, value
, prop
);
6973 * No equal attr found; create a new one.
6975 return(xmlNewPropInternal(node
, ns
, name
, value
, 0));
6978 #endif /* LIBXML_TREE_ENABLED */
6984 * Is this node a Text node ?
6985 * Returns 1 yes, 0 no
6988 xmlNodeIsText(const xmlNode
*node
) {
6989 if (node
== NULL
) return(0);
6991 if (node
->type
== XML_TEXT_NODE
) return(1);
6999 * Checks whether this node is an empty or whitespace only
7000 * (and possibly ignorable) text-node.
7002 * Returns 1 yes, 0 no
7005 xmlIsBlankNode(const xmlNode
*node
) {
7007 if (node
== NULL
) return(0);
7009 if ((node
->type
!= XML_TEXT_NODE
) &&
7010 (node
->type
!= XML_CDATA_SECTION_NODE
))
7012 if (node
->content
== NULL
) return(1);
7013 cur
= node
->content
;
7015 if (!IS_BLANK_CH(*cur
)) return(0);
7025 * @content: the content
7026 * @len: @content length
7028 * Concat the given string at the end of the existing node content
7030 * Returns -1 in case of error, 0 otherwise
7034 xmlTextConcat(xmlNodePtr node
, const xmlChar
*content
, int len
) {
7035 if (node
== NULL
) return(-1);
7037 if ((node
->type
!= XML_TEXT_NODE
) &&
7038 (node
->type
!= XML_CDATA_SECTION_NODE
) &&
7039 (node
->type
!= XML_COMMENT_NODE
) &&
7040 (node
->type
!= XML_PI_NODE
)) {
7042 xmlGenericError(xmlGenericErrorContext
,
7043 "xmlTextConcat: node is not text nor CDATA\n");
7047 /* need to check if content is currently in the dictionary */
7048 if ((node
->content
== (xmlChar
*) &(node
->properties
)) ||
7049 ((node
->doc
!= NULL
) && (node
->doc
->dict
!= NULL
) &&
7050 xmlDictOwns(node
->doc
->dict
, node
->content
))) {
7051 node
->content
= xmlStrncatNew(node
->content
, content
, len
);
7053 node
->content
= xmlStrncat(node
->content
, content
, len
);
7055 node
->properties
= NULL
;
7056 if (node
->content
== NULL
)
7061 /************************************************************************
7063 * Output : to a FILE or in memory *
7065 ************************************************************************/
7070 * routine to create an XML buffer.
7071 * returns the new structure.
7074 xmlBufferCreate(void) {
7077 ret
= (xmlBufferPtr
) xmlMalloc(sizeof(xmlBuffer
));
7079 xmlTreeErrMemory("creating buffer");
7083 ret
->size
= xmlDefaultBufferSize
;
7084 ret
->alloc
= xmlBufferAllocScheme
;
7085 ret
->content
= (xmlChar
*) xmlMallocAtomic(ret
->size
* sizeof(xmlChar
));
7086 if (ret
->content
== NULL
) {
7087 xmlTreeErrMemory("creating buffer");
7091 ret
->content
[0] = 0;
7092 ret
->contentIO
= NULL
;
7097 * xmlBufferCreateSize:
7098 * @size: initial size of buffer
7100 * routine to create an XML buffer.
7101 * returns the new structure.
7104 xmlBufferCreateSize(size_t size
) {
7107 if (size
>= UINT_MAX
)
7109 ret
= (xmlBufferPtr
) xmlMalloc(sizeof(xmlBuffer
));
7111 xmlTreeErrMemory("creating buffer");
7115 ret
->alloc
= xmlBufferAllocScheme
;
7116 ret
->size
= (size
? size
+ 1 : 0); /* +1 for ending null */
7118 ret
->content
= (xmlChar
*) xmlMallocAtomic(ret
->size
* sizeof(xmlChar
));
7119 if (ret
->content
== NULL
) {
7120 xmlTreeErrMemory("creating buffer");
7124 ret
->content
[0] = 0;
7126 ret
->content
= NULL
;
7127 ret
->contentIO
= NULL
;
7135 * Remove the string contained in a buffer and gie it back to the
7136 * caller. The buffer is reset to an empty content.
7137 * This doesn't work with immutable buffers as they can't be reset.
7139 * Returns the previous string contained by the buffer.
7142 xmlBufferDetach(xmlBufferPtr buf
) {
7147 if (buf
->alloc
== XML_BUFFER_ALLOC_IMMUTABLE
)
7151 buf
->content
= NULL
;
7160 * xmlBufferCreateStatic:
7161 * @mem: the memory area
7162 * @size: the size in byte
7164 * routine to create an XML buffer from an immutable memory area.
7165 * The area won't be modified nor copied, and is expected to be
7166 * present until the end of the buffer lifetime.
7168 * returns the new structure.
7171 xmlBufferCreateStatic(void *mem
, size_t size
) {
7174 if ((mem
== NULL
) || (size
== 0))
7176 if (size
> UINT_MAX
)
7179 ret
= (xmlBufferPtr
) xmlMalloc(sizeof(xmlBuffer
));
7181 xmlTreeErrMemory("creating buffer");
7186 ret
->alloc
= XML_BUFFER_ALLOC_IMMUTABLE
;
7187 ret
->content
= (xmlChar
*) mem
;
7192 * xmlBufferSetAllocationScheme:
7193 * @buf: the buffer to tune
7194 * @scheme: allocation scheme to use
7196 * Sets the allocation scheme for this buffer
7199 xmlBufferSetAllocationScheme(xmlBufferPtr buf
,
7200 xmlBufferAllocationScheme scheme
) {
7203 xmlGenericError(xmlGenericErrorContext
,
7204 "xmlBufferSetAllocationScheme: buf == NULL\n");
7208 if ((buf
->alloc
== XML_BUFFER_ALLOC_IMMUTABLE
) ||
7209 (buf
->alloc
== XML_BUFFER_ALLOC_IO
)) return;
7210 if ((scheme
== XML_BUFFER_ALLOC_DOUBLEIT
) ||
7211 (scheme
== XML_BUFFER_ALLOC_EXACT
) ||
7212 (scheme
== XML_BUFFER_ALLOC_HYBRID
) ||
7213 (scheme
== XML_BUFFER_ALLOC_IMMUTABLE
))
7214 buf
->alloc
= scheme
;
7219 * @buf: the buffer to free
7221 * Frees an XML buffer. It frees both the content and the structure which
7225 xmlBufferFree(xmlBufferPtr buf
) {
7228 xmlGenericError(xmlGenericErrorContext
,
7229 "xmlBufferFree: buf == NULL\n");
7234 if ((buf
->alloc
== XML_BUFFER_ALLOC_IO
) &&
7235 (buf
->contentIO
!= NULL
)) {
7236 xmlFree(buf
->contentIO
);
7237 } else if ((buf
->content
!= NULL
) &&
7238 (buf
->alloc
!= XML_BUFFER_ALLOC_IMMUTABLE
)) {
7239 xmlFree(buf
->content
);
7251 xmlBufferEmpty(xmlBufferPtr buf
) {
7252 if (buf
== NULL
) return;
7253 if (buf
->content
== NULL
) return;
7255 if (buf
->alloc
== XML_BUFFER_ALLOC_IMMUTABLE
) {
7256 buf
->content
= BAD_CAST
"";
7257 } else if ((buf
->alloc
== XML_BUFFER_ALLOC_IO
) &&
7258 (buf
->contentIO
!= NULL
)) {
7259 size_t start_buf
= buf
->content
- buf
->contentIO
;
7261 buf
->size
+= start_buf
;
7262 buf
->content
= buf
->contentIO
;
7263 buf
->content
[0] = 0;
7265 buf
->content
[0] = 0;
7271 * @buf: the buffer to dump
7272 * @len: the number of xmlChar to remove
7274 * Remove the beginning of an XML buffer.
7276 * Returns the number of #xmlChar removed, or -1 in case of failure.
7279 xmlBufferShrink(xmlBufferPtr buf
, unsigned int len
) {
7280 if (buf
== NULL
) return(-1);
7281 if (len
== 0) return(0);
7282 if (len
> buf
->use
) return(-1);
7285 if ((buf
->alloc
== XML_BUFFER_ALLOC_IMMUTABLE
) ||
7286 ((buf
->alloc
== XML_BUFFER_ALLOC_IO
) && (buf
->contentIO
!= NULL
))) {
7288 * we just move the content pointer, but also make sure
7289 * the perceived buffer size has shrunk accordingly
7291 buf
->content
+= len
;
7295 * sometimes though it maybe be better to really shrink
7298 if ((buf
->alloc
== XML_BUFFER_ALLOC_IO
) && (buf
->contentIO
!= NULL
)) {
7299 size_t start_buf
= buf
->content
- buf
->contentIO
;
7300 if (start_buf
>= buf
->size
) {
7301 memmove(buf
->contentIO
, &buf
->content
[0], buf
->use
);
7302 buf
->content
= buf
->contentIO
;
7303 buf
->content
[buf
->use
] = 0;
7304 buf
->size
+= start_buf
;
7308 memmove(buf
->content
, &buf
->content
[len
], buf
->use
);
7309 buf
->content
[buf
->use
] = 0;
7317 * @len: the minimum free size to allocate
7319 * Grow the available space of an XML buffer.
7321 * Returns the new available space or -1 in case of error
7324 xmlBufferGrow(xmlBufferPtr buf
, unsigned int len
) {
7328 if (buf
== NULL
) return(-1);
7330 if (buf
->alloc
== XML_BUFFER_ALLOC_IMMUTABLE
) return(0);
7331 if (len
< buf
->size
- buf
->use
)
7333 if (len
> UINT_MAX
- buf
->use
)
7336 if (buf
->size
> (size_t) len
) {
7337 size
= buf
->size
> UINT_MAX
/ 2 ? UINT_MAX
: buf
->size
* 2;
7339 size
= buf
->use
+ len
;
7340 size
= size
> UINT_MAX
- 100 ? UINT_MAX
: size
+ 100;
7343 if ((buf
->alloc
== XML_BUFFER_ALLOC_IO
) && (buf
->contentIO
!= NULL
)) {
7344 size_t start_buf
= buf
->content
- buf
->contentIO
;
7346 newbuf
= (xmlChar
*) xmlRealloc(buf
->contentIO
, start_buf
+ size
);
7347 if (newbuf
== NULL
) {
7348 xmlTreeErrMemory("growing buffer");
7351 buf
->contentIO
= newbuf
;
7352 buf
->content
= newbuf
+ start_buf
;
7354 newbuf
= (xmlChar
*) xmlRealloc(buf
->content
, size
);
7355 if (newbuf
== NULL
) {
7356 xmlTreeErrMemory("growing buffer");
7359 buf
->content
= newbuf
;
7362 return(buf
->size
- buf
->use
);
7367 * @file: the file output
7368 * @buf: the buffer to dump
7370 * Dumps an XML buffer to a FILE *.
7371 * Returns the number of #xmlChar written
7374 xmlBufferDump(FILE *file
, xmlBufferPtr buf
) {
7379 xmlGenericError(xmlGenericErrorContext
,
7380 "xmlBufferDump: buf == NULL\n");
7384 if (buf
->content
== NULL
) {
7386 xmlGenericError(xmlGenericErrorContext
,
7387 "xmlBufferDump: buf->content == NULL\n");
7393 ret
= fwrite(buf
->content
, sizeof(xmlChar
), buf
->use
, file
);
7401 * Function to extract the content of a buffer
7403 * Returns the internal content
7407 xmlBufferContent(const xmlBuffer
*buf
)
7412 return buf
->content
;
7419 * Function to get the length of a buffer
7421 * Returns the length of data in the internal content
7425 xmlBufferLength(const xmlBuffer
*buf
)
7435 * @buf: the buffer to resize
7436 * @size: the desired size
7438 * Resize a buffer to accommodate minimum size of @size.
7440 * Returns 0 in case of problems, 1 otherwise
7443 xmlBufferResize(xmlBufferPtr buf
, unsigned int size
)
7445 unsigned int newSize
;
7446 xmlChar
* rebuf
= NULL
;
7452 if (buf
->alloc
== XML_BUFFER_ALLOC_IMMUTABLE
) return(0);
7454 /* Don't resize if we don't have to */
7455 if (size
< buf
->size
)
7458 if (size
> UINT_MAX
- 10) {
7459 xmlTreeErrMemory("growing buffer");
7463 /* figure out new size */
7464 switch (buf
->alloc
){
7465 case XML_BUFFER_ALLOC_IO
:
7466 case XML_BUFFER_ALLOC_DOUBLEIT
:
7467 /*take care of empty case*/
7469 newSize
= (size
> UINT_MAX
- 10 ? UINT_MAX
: size
+ 10);
7471 newSize
= buf
->size
;
7472 while (size
> newSize
) {
7473 if (newSize
> UINT_MAX
/ 2) {
7474 xmlTreeErrMemory("growing buffer");
7480 case XML_BUFFER_ALLOC_EXACT
:
7481 newSize
= (size
> UINT_MAX
- 10 ? UINT_MAX
: size
+ 10);;
7483 case XML_BUFFER_ALLOC_HYBRID
:
7484 if (buf
->use
< BASE_BUFFER_SIZE
)
7487 newSize
= buf
->size
;
7488 while (size
> newSize
) {
7489 if (newSize
> UINT_MAX
/ 2) {
7490 xmlTreeErrMemory("growing buffer");
7499 newSize
= (size
> UINT_MAX
- 10 ? UINT_MAX
: size
+ 10);;
7503 if ((buf
->alloc
== XML_BUFFER_ALLOC_IO
) && (buf
->contentIO
!= NULL
)) {
7504 start_buf
= buf
->content
- buf
->contentIO
;
7506 if (start_buf
> newSize
) {
7507 /* move data back to start */
7508 memmove(buf
->contentIO
, buf
->content
, buf
->use
);
7509 buf
->content
= buf
->contentIO
;
7510 buf
->content
[buf
->use
] = 0;
7511 buf
->size
+= start_buf
;
7513 rebuf
= (xmlChar
*) xmlRealloc(buf
->contentIO
, start_buf
+ newSize
);
7514 if (rebuf
== NULL
) {
7515 xmlTreeErrMemory("growing buffer");
7518 buf
->contentIO
= rebuf
;
7519 buf
->content
= rebuf
+ start_buf
;
7522 if (buf
->content
== NULL
) {
7523 rebuf
= (xmlChar
*) xmlMallocAtomic(newSize
);
7524 } else if (buf
->size
- buf
->use
< 100) {
7525 rebuf
= (xmlChar
*) xmlRealloc(buf
->content
, newSize
);
7528 * if we are reallocating a buffer far from being full, it's
7529 * better to make a new allocation and copy only the used range
7530 * and free the old one.
7532 rebuf
= (xmlChar
*) xmlMallocAtomic(newSize
);
7533 if (rebuf
!= NULL
) {
7534 memcpy(rebuf
, buf
->content
, buf
->use
);
7535 xmlFree(buf
->content
);
7536 rebuf
[buf
->use
] = 0;
7539 if (rebuf
== NULL
) {
7540 xmlTreeErrMemory("growing buffer");
7543 buf
->content
= rebuf
;
7545 buf
->size
= newSize
;
7552 * @buf: the buffer to dump
7553 * @str: the #xmlChar string
7554 * @len: the number of #xmlChar to add
7556 * Add a string range to an XML buffer. if len == -1, the length of
7557 * str is recomputed.
7559 * Returns 0 successful, a positive error code number otherwise
7560 * and -1 in case of internal or API error.
7563 xmlBufferAdd(xmlBufferPtr buf
, const xmlChar
*str
, int len
) {
7564 unsigned int needSize
;
7566 if ((str
== NULL
) || (buf
== NULL
)) {
7569 if (buf
->alloc
== XML_BUFFER_ALLOC_IMMUTABLE
) return -1;
7572 xmlGenericError(xmlGenericErrorContext
,
7573 "xmlBufferAdd: len < 0\n");
7577 if (len
== 0) return 0;
7580 len
= xmlStrlen(str
);
7582 if (len
< 0) return -1;
7583 if (len
== 0) return 0;
7585 if ((unsigned) len
>= buf
->size
- buf
->use
) {
7586 if ((unsigned) len
>= UINT_MAX
- buf
->use
)
7587 return XML_ERR_NO_MEMORY
;
7588 needSize
= buf
->use
+ len
+ 1;
7589 if (!xmlBufferResize(buf
, needSize
)){
7590 xmlTreeErrMemory("growing buffer");
7591 return XML_ERR_NO_MEMORY
;
7595 memmove(&buf
->content
[buf
->use
], str
, len
*sizeof(xmlChar
));
7597 buf
->content
[buf
->use
] = 0;
7604 * @str: the #xmlChar string
7605 * @len: the number of #xmlChar to add
7607 * Add a string range to the beginning of an XML buffer.
7608 * if len == -1, the length of @str is recomputed.
7610 * Returns 0 successful, a positive error code number otherwise
7611 * and -1 in case of internal or API error.
7614 xmlBufferAddHead(xmlBufferPtr buf
, const xmlChar
*str
, int len
) {
7615 unsigned int needSize
;
7619 if (buf
->alloc
== XML_BUFFER_ALLOC_IMMUTABLE
) return -1;
7622 xmlGenericError(xmlGenericErrorContext
,
7623 "xmlBufferAddHead: str == NULL\n");
7629 xmlGenericError(xmlGenericErrorContext
,
7630 "xmlBufferAddHead: len < 0\n");
7634 if (len
== 0) return 0;
7637 len
= xmlStrlen(str
);
7639 if (len
<= 0) return -1;
7641 if ((buf
->alloc
== XML_BUFFER_ALLOC_IO
) && (buf
->contentIO
!= NULL
)) {
7642 size_t start_buf
= buf
->content
- buf
->contentIO
;
7644 if (start_buf
> (unsigned int) len
) {
7646 * We can add it in the space previously shrunk
7648 buf
->content
-= len
;
7649 memmove(&buf
->content
[0], str
, len
);
7655 needSize
= buf
->use
+ len
+ 2;
7656 if (needSize
> buf
->size
){
7657 if (!xmlBufferResize(buf
, needSize
)){
7658 xmlTreeErrMemory("growing buffer");
7659 return XML_ERR_NO_MEMORY
;
7663 memmove(&buf
->content
[len
], &buf
->content
[0], buf
->use
);
7664 memmove(&buf
->content
[0], str
, len
);
7666 buf
->content
[buf
->use
] = 0;
7672 * @buf: the buffer to add to
7673 * @str: the #xmlChar string
7675 * Append a zero terminated string to an XML buffer.
7677 * Returns 0 successful, a positive error code number otherwise
7678 * and -1 in case of internal or API error.
7681 xmlBufferCat(xmlBufferPtr buf
, const xmlChar
*str
) {
7684 if (buf
->alloc
== XML_BUFFER_ALLOC_IMMUTABLE
) return -1;
7685 if (str
== NULL
) return -1;
7686 return xmlBufferAdd(buf
, str
, -1);
7691 * @buf: the buffer to dump
7692 * @str: the C char string
7694 * Append a zero terminated C string to an XML buffer.
7696 * Returns 0 successful, a positive error code number otherwise
7697 * and -1 in case of internal or API error.
7700 xmlBufferCCat(xmlBufferPtr buf
, const char *str
) {
7701 return xmlBufferCat(buf
, (const xmlChar
*) str
);
7705 * xmlBufferWriteCHAR:
7706 * @buf: the XML buffer
7707 * @string: the string to add
7709 * routine which manages and grows an output buffer. This one adds
7710 * xmlChars at the end of the buffer.
7713 xmlBufferWriteCHAR(xmlBufferPtr buf
, const xmlChar
*string
) {
7716 if (buf
->alloc
== XML_BUFFER_ALLOC_IMMUTABLE
) return;
7717 xmlBufferCat(buf
, string
);
7721 * xmlBufferWriteChar:
7722 * @buf: the XML buffer output
7723 * @string: the string to add
7725 * routine which manage and grows an output buffer. This one add
7726 * C chars at the end of the array.
7729 xmlBufferWriteChar(xmlBufferPtr buf
, const char *string
) {
7732 if (buf
->alloc
== XML_BUFFER_ALLOC_IMMUTABLE
) return;
7733 xmlBufferCCat(buf
, string
);
7738 * xmlBufferWriteQuotedString:
7739 * @buf: the XML buffer output
7740 * @string: the string to add
7742 * routine which manage and grows an output buffer. This one writes
7743 * a quoted or double quoted #xmlChar string, checking first if it holds
7744 * quote or double-quotes internally
7747 xmlBufferWriteQuotedString(xmlBufferPtr buf
, const xmlChar
*string
) {
7748 const xmlChar
*cur
, *base
;
7751 if (buf
->alloc
== XML_BUFFER_ALLOC_IMMUTABLE
) return;
7752 if (xmlStrchr(string
, '\"')) {
7753 if (xmlStrchr(string
, '\'')) {
7755 xmlGenericError(xmlGenericErrorContext
,
7756 "xmlBufferWriteQuotedString: string contains quote and double-quotes !\n");
7758 xmlBufferCCat(buf
, "\"");
7759 base
= cur
= string
;
7763 xmlBufferAdd(buf
, base
, cur
- base
);
7764 xmlBufferAdd(buf
, BAD_CAST
""", 6);
7773 xmlBufferAdd(buf
, base
, cur
- base
);
7774 xmlBufferCCat(buf
, "\"");
7777 xmlBufferCCat(buf
, "\'");
7778 xmlBufferCat(buf
, string
);
7779 xmlBufferCCat(buf
, "\'");
7782 xmlBufferCCat(buf
, "\"");
7783 xmlBufferCat(buf
, string
);
7784 xmlBufferCCat(buf
, "\"");
7790 * xmlGetDocCompressMode:
7791 * @doc: the document
7793 * get the compression ratio for a document, ZLIB based
7794 * Returns 0 (uncompressed) to 9 (max compression)
7797 xmlGetDocCompressMode (const xmlDoc
*doc
) {
7798 if (doc
== NULL
) return(-1);
7799 return(doc
->compression
);
7803 * xmlSetDocCompressMode:
7804 * @doc: the document
7805 * @mode: the compression ratio
7807 * set the compression ratio for a document, ZLIB based
7808 * Correct values: 0 (uncompressed) to 9 (max compression)
7811 xmlSetDocCompressMode (xmlDocPtr doc
, int mode
) {
7812 if (doc
== NULL
) return;
7813 if (mode
< 0) doc
->compression
= 0;
7814 else if (mode
> 9) doc
->compression
= 9;
7815 else doc
->compression
= mode
;
7819 * xmlGetCompressMode:
7821 * get the default compression mode used, ZLIB based.
7822 * Returns 0 (uncompressed) to 9 (max compression)
7825 xmlGetCompressMode(void)
7827 return (xmlCompressMode
);
7831 * xmlSetCompressMode:
7832 * @mode: the compression ratio
7834 * set the default compression mode used, ZLIB based
7835 * Correct values: 0 (uncompressed) to 9 (max compression)
7838 xmlSetCompressMode(int mode
) {
7839 if (mode
< 0) xmlCompressMode
= 0;
7840 else if (mode
> 9) xmlCompressMode
= 9;
7841 else xmlCompressMode
= mode
;
7844 #define XML_TREE_NSMAP_PARENT -1
7845 #define XML_TREE_NSMAP_XML -2
7846 #define XML_TREE_NSMAP_DOC -3
7847 #define XML_TREE_NSMAP_CUSTOM -4
7849 typedef struct xmlNsMapItem
*xmlNsMapItemPtr
;
7850 struct xmlNsMapItem
{
7851 xmlNsMapItemPtr next
;
7852 xmlNsMapItemPtr prev
;
7853 xmlNsPtr oldNs
; /* old ns decl reference */
7854 xmlNsPtr newNs
; /* new ns decl reference */
7855 int shadowDepth
; /* Shadowed at this depth */
7858 * >= 0 == @node's ns-decls
7859 * -1 == @parent's ns-decls
7860 * -2 == the doc->oldNs XML ns-decl
7861 * -3 == the doc->oldNs storage ns-decls
7862 * -4 == ns-decls provided via custom ns-handling
7867 typedef struct xmlNsMap
*xmlNsMapPtr
;
7869 xmlNsMapItemPtr first
;
7870 xmlNsMapItemPtr last
;
7871 xmlNsMapItemPtr pool
;
7874 #define XML_NSMAP_NOTEMPTY(m) (((m) != NULL) && ((m)->first != NULL))
7875 #define XML_NSMAP_FOREACH(m, i) for (i = (m)->first; i != NULL; i = (i)->next)
7876 #define XML_NSMAP_POP(m, i) \
7878 (m)->last = (i)->prev; \
7879 if ((m)->last == NULL) \
7880 (m)->first = NULL; \
7882 (m)->last->next = NULL; \
7883 (i)->next = (m)->pool; \
7887 * xmlDOMWrapNsMapFree:
7893 xmlDOMWrapNsMapFree(xmlNsMapPtr nsmap
)
7895 xmlNsMapItemPtr cur
, tmp
;
7900 while (cur
!= NULL
) {
7906 while (cur
!= NULL
) {
7915 * xmlDOMWrapNsMapAddItem:
7917 * @oldNs: the old ns-struct
7918 * @newNs: the new ns-struct
7919 * @depth: depth and ns-kind information
7921 * Adds an ns-mapping item.
7923 static xmlNsMapItemPtr
7924 xmlDOMWrapNsMapAddItem(xmlNsMapPtr
*nsmap
, int position
,
7925 xmlNsPtr oldNs
, xmlNsPtr newNs
, int depth
)
7927 xmlNsMapItemPtr ret
;
7932 if ((position
!= -1) && (position
!= 0))
7938 * Create the ns-map.
7940 map
= (xmlNsMapPtr
) xmlMalloc(sizeof(struct xmlNsMap
));
7942 xmlTreeErrMemory("allocating namespace map");
7945 memset(map
, 0, sizeof(struct xmlNsMap
));
7949 if (map
->pool
!= NULL
) {
7951 * Reuse an item from the pool.
7954 map
->pool
= ret
->next
;
7955 memset(ret
, 0, sizeof(struct xmlNsMapItem
));
7958 * Create a new item.
7960 ret
= (xmlNsMapItemPtr
) xmlMalloc(sizeof(struct xmlNsMapItem
));
7962 xmlTreeErrMemory("allocating namespace map item");
7965 memset(ret
, 0, sizeof(struct xmlNsMapItem
));
7968 if (map
->first
== NULL
) {
7974 } else if (position
== -1) {
7978 ret
->prev
= map
->last
;
7979 map
->last
->next
= ret
;
7981 } else if (position
== 0) {
7983 * Set on first position.
7985 map
->first
->prev
= ret
;
7986 ret
->next
= map
->first
;
7992 ret
->shadowDepth
= -1;
7998 * xmlDOMWrapStoreNs:
8000 * @nsName: the namespace name
8001 * @prefix: the prefix
8003 * Creates or reuses an xmlNs struct on doc->oldNs with
8004 * the given prefix and namespace name.
8006 * Returns the acquired ns struct or NULL in case of an API
8007 * or internal error.
8010 xmlDOMWrapStoreNs(xmlDocPtr doc
,
8011 const xmlChar
*nsName
,
8012 const xmlChar
*prefix
)
8018 ns
= xmlTreeEnsureXMLDecl(doc
);
8021 if (ns
->next
!= NULL
) {
8024 while (ns
!= NULL
) {
8025 if (((ns
->prefix
== prefix
) ||
8026 xmlStrEqual(ns
->prefix
, prefix
)) &&
8027 xmlStrEqual(ns
->href
, nsName
)) {
8030 if (ns
->next
== NULL
)
8037 ns
->next
= xmlNewNs(NULL
, nsName
, prefix
);
8044 * xmlDOMWrapNewCtxt:
8046 * Allocates and initializes a new DOM-wrapper context.
8048 * Returns the xmlDOMWrapCtxtPtr or NULL in case of an internal error.
8051 xmlDOMWrapNewCtxt(void)
8053 xmlDOMWrapCtxtPtr ret
;
8055 ret
= xmlMalloc(sizeof(xmlDOMWrapCtxt
));
8057 xmlTreeErrMemory("allocating DOM-wrapper context");
8060 memset(ret
, 0, sizeof(xmlDOMWrapCtxt
));
8065 * xmlDOMWrapFreeCtxt:
8066 * @ctxt: the DOM-wrapper context
8068 * Frees the DOM-wrapper context.
8071 xmlDOMWrapFreeCtxt(xmlDOMWrapCtxtPtr ctxt
)
8075 if (ctxt
->namespaceMap
!= NULL
)
8076 xmlDOMWrapNsMapFree((xmlNsMapPtr
) ctxt
->namespaceMap
);
8078 * TODO: Store the namespace map in the context.
8084 * xmlTreeLookupNsListByPrefix:
8085 * @nsList: a list of ns-structs
8086 * @prefix: the searched prefix
8088 * Searches for a ns-decl with the given prefix in @nsList.
8090 * Returns the ns-decl if found, NULL if not found and on
8094 xmlTreeNSListLookupByPrefix(xmlNsPtr nsList
, const xmlChar
*prefix
)
8102 if ((prefix
== ns
->prefix
) ||
8103 xmlStrEqual(prefix
, ns
->prefix
)) {
8107 } while (ns
!= NULL
);
8114 * xmlDOMWrapNSNormGatherInScopeNs:
8115 * @map: the namespace map
8116 * @node: the node to start with
8118 * Puts in-scope namespaces into the ns-map.
8120 * Returns 0 on success, -1 on API or internal errors.
8123 xmlDOMWrapNSNormGatherInScopeNs(xmlNsMapPtr
*map
,
8131 if ((map
== NULL
) || (*map
!= NULL
))
8133 if ((node
== NULL
) || (node
->type
== XML_NAMESPACE_DECL
))
8136 * Get in-scope ns-decls of @parent.
8139 while ((cur
!= NULL
) && (cur
!= (xmlNodePtr
) cur
->doc
)) {
8140 if (cur
->type
== XML_ELEMENT_NODE
) {
8141 if (cur
->nsDef
!= NULL
) {
8145 if (XML_NSMAP_NOTEMPTY(*map
)) {
8147 * Skip shadowed prefixes.
8149 XML_NSMAP_FOREACH(*map
, mi
) {
8150 if ((ns
->prefix
== mi
->newNs
->prefix
) ||
8151 xmlStrEqual(ns
->prefix
, mi
->newNs
->prefix
)) {
8160 mi
= xmlDOMWrapNsMapAddItem(map
, 0, NULL
,
8161 ns
, XML_TREE_NSMAP_PARENT
);
8165 mi
->shadowDepth
= 0;
8167 } while (ns
!= NULL
);
8176 * XML_TREE_ADOPT_STR: If we have a dest-dict, put @str in the dict;
8177 * otherwise copy it, when it was in the source-dict.
8179 #define XML_TREE_ADOPT_STR(str) \
8180 if (adoptStr && (str != NULL)) { \
8181 if (destDoc->dict) { \
8182 const xmlChar *old = str; \
8183 str = xmlDictLookup(destDoc->dict, str, -1); \
8184 if ((sourceDoc == NULL) || (sourceDoc->dict == NULL) || \
8185 (!xmlDictOwns(sourceDoc->dict, old))) \
8186 xmlFree((char *)old); \
8187 } else if ((sourceDoc) && (sourceDoc->dict) && \
8188 xmlDictOwns(sourceDoc->dict, str)) { \
8189 str = BAD_CAST xmlStrdup(str); \
8194 * XML_TREE_ADOPT_STR_2: If @str was in the source-dict, then
8195 * put it in dest-dict or copy it.
8197 #define XML_TREE_ADOPT_STR_2(str) \
8198 if (adoptStr && (str != NULL) && (sourceDoc != NULL) && \
8199 (sourceDoc->dict != NULL) && \
8200 xmlDictOwns(sourceDoc->dict, cur->content)) { \
8201 if (destDoc->dict) \
8202 cur->content = (xmlChar *) \
8203 xmlDictLookup(destDoc->dict, cur->content, -1); \
8205 cur->content = xmlStrdup(BAD_CAST cur->content); \
8209 * xmlDOMWrapNSNormAddNsMapItem2:
8211 * For internal use. Adds a ns-decl mapping.
8213 * Returns 0 on success, -1 on internal errors.
8216 xmlDOMWrapNSNormAddNsMapItem2(xmlNsPtr
**list
, int *size
, int *number
,
8217 xmlNsPtr oldNs
, xmlNsPtr newNs
)
8219 if (*list
== NULL
) {
8220 *list
= (xmlNsPtr
*) xmlMalloc(6 * sizeof(xmlNsPtr
));
8221 if (*list
== NULL
) {
8222 xmlTreeErrMemory("alloc ns map item");
8227 } else if ((*number
) >= (*size
)) {
8229 *list
= (xmlNsPtr
*) xmlRealloc(*list
,
8230 (*size
) * 2 * sizeof(xmlNsPtr
));
8231 if (*list
== NULL
) {
8232 xmlTreeErrMemory("realloc ns map item");
8236 (*list
)[2 * (*number
)] = oldNs
;
8237 (*list
)[2 * (*number
) +1] = newNs
;
8243 * xmlDOMWrapRemoveNode:
8244 * @ctxt: a DOM wrapper context
8246 * @node: the node to be removed.
8247 * @options: set of options, unused at the moment
8249 * Unlinks the given node from its owner.
8250 * This will substitute ns-references to node->nsDef for
8251 * ns-references to doc->oldNs, thus ensuring the removed
8252 * branch to be autark wrt ns-references.
8254 * NOTE: This function was not intensively tested.
8256 * Returns 0 on success, 1 if the node is not supported,
8257 * -1 on API and internal errors.
8260 xmlDOMWrapRemoveNode(xmlDOMWrapCtxtPtr ctxt
, xmlDocPtr doc
,
8261 xmlNodePtr node
, int options ATTRIBUTE_UNUSED
)
8263 xmlNsPtr
*list
= NULL
;
8264 int sizeList
, nbList
, i
, j
;
8267 if ((node
== NULL
) || (doc
== NULL
) || (node
->doc
!= doc
))
8270 /* TODO: 0 or -1 ? */
8271 if (node
->parent
== NULL
)
8274 switch (node
->type
) {
8276 case XML_CDATA_SECTION_NODE
:
8277 case XML_ENTITY_REF_NODE
:
8279 case XML_COMMENT_NODE
:
8280 xmlUnlinkNode(node
);
8282 case XML_ELEMENT_NODE
:
8283 case XML_ATTRIBUTE_NODE
:
8288 xmlUnlinkNode(node
);
8290 * Save out-of-scope ns-references in doc->oldNs.
8293 switch (node
->type
) {
8294 case XML_ELEMENT_NODE
:
8295 if ((ctxt
== NULL
) && (node
->nsDef
!= NULL
)) {
8298 if (xmlDOMWrapNSNormAddNsMapItem2(&list
, &sizeList
,
8299 &nbList
, ns
, ns
) == -1)
8300 goto internal_error
;
8302 } while (ns
!= NULL
);
8304 /* Falls through. */
8305 case XML_ATTRIBUTE_NODE
:
8306 if (node
->ns
!= NULL
) {
8311 for (i
= 0, j
= 0; i
< nbList
; i
++, j
+= 2) {
8312 if (node
->ns
== list
[j
]) {
8313 node
->ns
= list
[++j
];
8325 * Add to doc's oldNs.
8327 ns
= xmlDOMWrapStoreNs(doc
, node
->ns
->href
,
8330 goto internal_error
;
8336 if (xmlDOMWrapNSNormAddNsMapItem2(&list
, &sizeList
,
8337 &nbList
, node
->ns
, ns
) == -1)
8338 goto internal_error
;
8342 if ((node
->type
== XML_ELEMENT_NODE
) &&
8343 (node
->properties
!= NULL
)) {
8344 node
= (xmlNodePtr
) node
->properties
;
8352 if ((node
->type
== XML_ELEMENT_NODE
) &&
8353 (node
->children
!= NULL
)) {
8354 node
= node
->children
;
8360 if (node
->next
!= NULL
)
8363 node
= node
->parent
;
8366 } while (node
!= NULL
);
8379 * xmlSearchNsByNamespaceStrict:
8380 * @doc: the document
8381 * @node: the start node
8382 * @nsName: the searched namespace name
8383 * @retNs: the resulting ns-decl
8384 * @prefixed: if the found ns-decl must have a prefix (for attributes)
8386 * Dynamically searches for a ns-declaration which matches
8387 * the given @nsName in the ancestor-or-self axis of @node.
8389 * Returns 1 if a ns-decl was found, 0 if not and -1 on API
8390 * and internal errors.
8393 xmlSearchNsByNamespaceStrict(xmlDocPtr doc
, xmlNodePtr node
,
8394 const xmlChar
* nsName
,
8395 xmlNsPtr
*retNs
, int prefixed
)
8397 xmlNodePtr cur
, prev
= NULL
, out
= NULL
;
8398 xmlNsPtr ns
, prevns
;
8400 if ((doc
== NULL
) || (nsName
== NULL
) || (retNs
== NULL
))
8402 if ((node
== NULL
) || (node
->type
== XML_NAMESPACE_DECL
))
8406 if (xmlStrEqual(nsName
, XML_XML_NAMESPACE
)) {
8407 *retNs
= xmlTreeEnsureXMLDecl(doc
);
8414 if (cur
->type
== XML_ELEMENT_NODE
) {
8415 if (cur
->nsDef
!= NULL
) {
8416 for (ns
= cur
->nsDef
; ns
!= NULL
; ns
= ns
->next
) {
8417 if (prefixed
&& (ns
->prefix
== NULL
))
8421 * Check the last level of ns-decls for a
8424 prevns
= prev
->nsDef
;
8426 if ((prevns
->prefix
== ns
->prefix
) ||
8427 ((prevns
->prefix
!= NULL
) &&
8428 (ns
->prefix
!= NULL
) &&
8429 xmlStrEqual(prevns
->prefix
, ns
->prefix
))) {
8435 prevns
= prevns
->next
;
8436 } while (prevns
!= NULL
);
8441 * Ns-name comparison.
8443 if ((nsName
== ns
->href
) ||
8444 xmlStrEqual(nsName
, ns
->href
)) {
8446 * At this point the prefix can only be shadowed,
8447 * if we are the the (at least) 3rd level of
8453 ret
= xmlNsInScope(doc
, node
, prev
, ns
->prefix
);
8457 * TODO: Should we try to find a matching ns-name
8458 * only once? This here keeps on searching.
8459 * I think we should try further since, there might
8460 * be an other matching ns-decl with an unshadowed
8473 } else if ((cur
->type
== XML_ENTITY_NODE
) ||
8474 (cur
->type
== XML_ENTITY_DECL
))
8477 } while ((cur
!= NULL
) && (cur
->doc
!= (xmlDocPtr
) cur
));
8482 * xmlSearchNsByPrefixStrict:
8483 * @doc: the document
8484 * @node: the start node
8485 * @prefix: the searched namespace prefix
8486 * @retNs: the resulting ns-decl
8488 * Dynamically searches for a ns-declaration which matches
8489 * the given @nsName in the ancestor-or-self axis of @node.
8491 * Returns 1 if a ns-decl was found, 0 if not and -1 on API
8492 * and internal errors.
8495 xmlSearchNsByPrefixStrict(xmlDocPtr doc
, xmlNodePtr node
,
8496 const xmlChar
* prefix
,
8502 if ((doc
== NULL
) || (node
== NULL
) || (node
->type
== XML_NAMESPACE_DECL
))
8507 if (IS_STR_XML(prefix
)) {
8509 *retNs
= xmlTreeEnsureXMLDecl(doc
);
8517 if (cur
->type
== XML_ELEMENT_NODE
) {
8518 if (cur
->nsDef
!= NULL
) {
8521 if ((prefix
== ns
->prefix
) ||
8522 xmlStrEqual(prefix
, ns
->prefix
))
8525 * Disabled namespaces, e.g. xmlns:abc="".
8527 if (ns
->href
== NULL
)
8534 } while (ns
!= NULL
);
8536 } else if ((cur
->type
== XML_ENTITY_NODE
) ||
8537 (cur
->type
== XML_ENTITY_DECL
))
8540 } while ((cur
!= NULL
) && (cur
->doc
!= (xmlDocPtr
) cur
));
8545 * xmlDOMWrapNSNormDeclareNsForced:
8547 * @elem: the element-node to declare on
8548 * @nsName: the namespace-name of the ns-decl
8549 * @prefix: the preferred prefix of the ns-decl
8550 * @checkShadow: ensure that the new ns-decl doesn't shadow ancestor ns-decls
8552 * Declares a new namespace on @elem. It tries to use the
8553 * given @prefix; if a ns-decl with the given prefix is already existent
8554 * on @elem, it will generate an other prefix.
8556 * Returns 1 if a ns-decl was found, 0 if not and -1 on API
8557 * and internal errors.
8560 xmlDOMWrapNSNormDeclareNsForced(xmlDocPtr doc
,
8562 const xmlChar
*nsName
,
8563 const xmlChar
*prefix
,
8569 const xmlChar
*pref
;
8572 if ((doc
== NULL
) || (elem
== NULL
) || (elem
->type
!= XML_ELEMENT_NODE
))
8575 * Create a ns-decl on @anchor.
8580 * Lookup whether the prefix is unused in elem's ns-decls.
8582 if ((elem
->nsDef
!= NULL
) &&
8583 (xmlTreeNSListLookupByPrefix(elem
->nsDef
, pref
) != NULL
))
8584 goto ns_next_prefix
;
8585 if (checkShadow
&& elem
->parent
&&
8586 ((xmlNodePtr
) elem
->parent
->doc
!= elem
->parent
)) {
8588 * Does it shadow ancestor ns-decls?
8590 if (xmlSearchNsByPrefixStrict(doc
, elem
->parent
, pref
, NULL
) == 1)
8591 goto ns_next_prefix
;
8593 ret
= xmlNewNs(NULL
, nsName
, pref
);
8596 if (elem
->nsDef
== NULL
)
8599 xmlNsPtr ns2
= elem
->nsDef
;
8600 while (ns2
->next
!= NULL
)
8609 if (prefix
== NULL
) {
8610 snprintf((char *) buf
, sizeof(buf
),
8613 snprintf((char *) buf
, sizeof(buf
),
8614 "%.30s_%d", (char *)prefix
, counter
);
8615 pref
= BAD_CAST buf
;
8620 * xmlDOMWrapNSNormAcquireNormalizedNs:
8622 * @elem: the element-node to declare namespaces on
8623 * @ns: the ns-struct to use for the search
8624 * @retNs: the found/created ns-struct
8625 * @nsMap: the ns-map
8626 * @depth: the current tree depth
8627 * @ancestorsOnly: search in ancestor ns-decls only
8628 * @prefixed: if the searched ns-decl must have a prefix (for attributes)
8630 * Searches for a matching ns-name in the ns-decls of @nsMap, if not
8631 * found it will either declare it on @elem, or store it in doc->oldNs.
8632 * If a new ns-decl needs to be declared on @elem, it tries to use the
8633 * @ns->prefix for it, if this prefix is already in use on @elem, it will
8634 * change the prefix or the new ns-decl.
8636 * Returns 0 if succeeded, -1 otherwise and on API/internal errors.
8639 xmlDOMWrapNSNormAcquireNormalizedNs(xmlDocPtr doc
,
8651 if ((doc
== NULL
) || (ns
== NULL
) || (retNs
== NULL
) ||
8657 * Handle XML namespace.
8659 if (IS_STR_XML(ns
->prefix
)) {
8661 * Insert XML namespace mapping.
8663 *retNs
= xmlTreeEnsureXMLDecl(doc
);
8669 * If the search should be done in ancestors only and no
8670 * @elem (the first ancestor) was specified, then skip the search.
8672 if ((XML_NSMAP_NOTEMPTY(*nsMap
)) &&
8673 (! (ancestorsOnly
&& (elem
== NULL
))))
8676 * Try to find an equal ns-name in in-scope ns-decls.
8678 XML_NSMAP_FOREACH(*nsMap
, mi
) {
8679 if ((mi
->depth
>= XML_TREE_NSMAP_PARENT
) &&
8681 * ancestorsOnly: This should be turned on to gain speed,
8682 * if one knows that the branch itself was already
8683 * ns-wellformed and no stale references existed.
8684 * I.e. it searches in the ancestor axis only.
8686 ((! ancestorsOnly
) || (mi
->depth
== XML_TREE_NSMAP_PARENT
)) &&
8687 /* Skip shadowed prefixes. */
8688 (mi
->shadowDepth
== -1) &&
8689 /* Skip xmlns="" or xmlns:foo="". */
8690 ((mi
->newNs
->href
!= NULL
) &&
8691 (mi
->newNs
->href
[0] != 0)) &&
8692 /* Ensure a prefix if wanted. */
8693 ((! prefixed
) || (mi
->newNs
->prefix
!= NULL
)) &&
8695 ((mi
->newNs
->href
== ns
->href
) ||
8696 xmlStrEqual(mi
->newNs
->href
, ns
->href
))) {
8697 /* Set the mapping. */
8705 * No luck, the namespace is out of scope or shadowed.
8711 * Store ns-decls in "oldNs" of the document-node.
8713 tmpns
= xmlDOMWrapStoreNs(doc
, ns
->href
, ns
->prefix
);
8719 if (xmlDOMWrapNsMapAddItem(nsMap
, -1, ns
,
8720 tmpns
, XML_TREE_NSMAP_DOC
) == NULL
) {
8728 tmpns
= xmlDOMWrapNSNormDeclareNsForced(doc
, elem
, ns
->href
,
8733 if (*nsMap
!= NULL
) {
8735 * Does it shadow ancestor ns-decls?
8737 XML_NSMAP_FOREACH(*nsMap
, mi
) {
8738 if ((mi
->depth
< depth
) &&
8739 (mi
->shadowDepth
== -1) &&
8740 ((ns
->prefix
== mi
->newNs
->prefix
) ||
8741 xmlStrEqual(ns
->prefix
, mi
->newNs
->prefix
))) {
8745 mi
->shadowDepth
= depth
;
8750 if (xmlDOMWrapNsMapAddItem(nsMap
, -1, ns
, tmpns
, depth
) == NULL
) {
8760 XML_DOM_RECONNS_REMOVEREDUND
= 1<<0
8761 } xmlDOMReconcileNSOptions
;
8764 * xmlDOMWrapReconcileNamespaces:
8765 * @ctxt: DOM wrapper context, unused at the moment
8766 * @elem: the element-node
8767 * @options: option flags
8769 * Ensures that ns-references point to ns-decls hold on element-nodes.
8770 * Ensures that the tree is namespace wellformed by creating additional
8771 * ns-decls where needed. Note that, since prefixes of already existent
8772 * ns-decls can be shadowed by this process, it could break QNames in
8773 * attribute values or element content.
8775 * NOTE: This function was not intensively tested.
8777 * Returns 0 if succeeded, -1 otherwise and on API/internal errors.
8781 xmlDOMWrapReconcileNamespaces(xmlDOMWrapCtxtPtr ctxt ATTRIBUTE_UNUSED
,
8785 int depth
= -1, adoptns
= 0, parnsdone
= 0;
8786 xmlNsPtr ns
, prevns
;
8788 xmlNodePtr cur
, curElem
= NULL
;
8789 xmlNsMapPtr nsMap
= NULL
;
8790 xmlNsMapItemPtr
/* topmi = NULL, */ mi
;
8791 /* @ancestorsOnly should be set by an option flag. */
8792 int ancestorsOnly
= 0;
8793 int optRemoveRedundantNS
=
8794 ((xmlDOMReconcileNSOptions
) options
& XML_DOM_RECONNS_REMOVEREDUND
) ? 1 : 0;
8795 xmlNsPtr
*listRedund
= NULL
;
8796 int sizeRedund
= 0, nbRedund
= 0, ret
, i
, j
;
8798 if ((elem
== NULL
) || (elem
->doc
== NULL
) ||
8799 (elem
->type
!= XML_ELEMENT_NODE
))
8805 switch (cur
->type
) {
8806 case XML_ELEMENT_NODE
:
8811 * Namespace declarations.
8813 if (cur
->nsDef
!= NULL
) {
8816 while (ns
!= NULL
) {
8818 if ((elem
->parent
) &&
8819 ((xmlNodePtr
) elem
->parent
->doc
!= elem
->parent
)) {
8821 * Gather ancestor in-scope ns-decls.
8823 if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap
,
8824 elem
->parent
) == -1)
8825 goto internal_error
;
8831 * Lookup the ns ancestor-axis for equal ns-decls in scope.
8833 if (optRemoveRedundantNS
&& XML_NSMAP_NOTEMPTY(nsMap
)) {
8834 XML_NSMAP_FOREACH(nsMap
, mi
) {
8835 if ((mi
->depth
>= XML_TREE_NSMAP_PARENT
) &&
8836 (mi
->shadowDepth
== -1) &&
8837 ((ns
->prefix
== mi
->newNs
->prefix
) ||
8838 xmlStrEqual(ns
->prefix
, mi
->newNs
->prefix
)) &&
8839 ((ns
->href
== mi
->newNs
->href
) ||
8840 xmlStrEqual(ns
->href
, mi
->newNs
->href
)))
8843 * A redundant ns-decl was found.
8844 * Add it to the list of redundant ns-decls.
8846 if (xmlDOMWrapNSNormAddNsMapItem2(&listRedund
,
8847 &sizeRedund
, &nbRedund
, ns
, mi
->newNs
) == -1)
8848 goto internal_error
;
8850 * Remove the ns-decl from the element-node.
8853 prevns
->next
= ns
->next
;
8855 cur
->nsDef
= ns
->next
;
8862 * Skip ns-references handling if the referenced
8863 * ns-decl is declared on the same element.
8865 if ((cur
->ns
!= NULL
) && adoptns
&& (cur
->ns
== ns
))
8868 * Does it shadow any ns-decl?
8870 if (XML_NSMAP_NOTEMPTY(nsMap
)) {
8871 XML_NSMAP_FOREACH(nsMap
, mi
) {
8872 if ((mi
->depth
>= XML_TREE_NSMAP_PARENT
) &&
8873 (mi
->shadowDepth
== -1) &&
8874 ((ns
->prefix
== mi
->newNs
->prefix
) ||
8875 xmlStrEqual(ns
->prefix
, mi
->newNs
->prefix
))) {
8877 mi
->shadowDepth
= depth
;
8884 if (xmlDOMWrapNsMapAddItem(&nsMap
, -1, ns
, ns
,
8886 goto internal_error
;
8895 /* Falls through. */
8896 case XML_ATTRIBUTE_NODE
:
8897 /* No ns, no fun. */
8898 if (cur
->ns
== NULL
)
8902 if ((elem
->parent
) &&
8903 ((xmlNodePtr
) elem
->parent
->doc
!= elem
->parent
)) {
8904 if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap
,
8905 elem
->parent
) == -1)
8906 goto internal_error
;
8911 * Adjust the reference if this was a redundant ns-decl.
8914 for (i
= 0, j
= 0; i
< nbRedund
; i
++, j
+= 2) {
8915 if (cur
->ns
== listRedund
[j
]) {
8916 cur
->ns
= listRedund
[++j
];
8922 * Adopt ns-references.
8924 if (XML_NSMAP_NOTEMPTY(nsMap
)) {
8926 * Search for a mapping.
8928 XML_NSMAP_FOREACH(nsMap
, mi
) {
8929 if ((mi
->shadowDepth
== -1) &&
8930 (cur
->ns
== mi
->oldNs
)) {
8932 cur
->ns
= mi
->newNs
;
8938 * Acquire a normalized ns-decl and add it to the map.
8940 if (xmlDOMWrapNSNormAcquireNormalizedNs(doc
, curElem
,
8944 (cur
->type
== XML_ATTRIBUTE_NODE
) ? 1 : 0) == -1)
8945 goto internal_error
;
8949 if ((cur
->type
== XML_ELEMENT_NODE
) &&
8950 (cur
->properties
!= NULL
)) {
8952 * Process attributes.
8954 cur
= (xmlNodePtr
) cur
->properties
;
8962 if ((cur
->type
== XML_ELEMENT_NODE
) &&
8963 (cur
->children
!= NULL
)) {
8965 * Process content of element-nodes only.
8967 cur
= cur
->children
;
8973 if (cur
->type
== XML_ELEMENT_NODE
) {
8974 if (XML_NSMAP_NOTEMPTY(nsMap
)) {
8978 while ((nsMap
->last
!= NULL
) &&
8979 (nsMap
->last
->depth
>= depth
))
8981 XML_NSMAP_POP(nsMap
, mi
)
8986 XML_NSMAP_FOREACH(nsMap
, mi
) {
8987 if (mi
->shadowDepth
>= depth
)
8988 mi
->shadowDepth
= -1;
8993 if (cur
->next
!= NULL
)
8996 if (cur
->type
== XML_ATTRIBUTE_NODE
) {
9003 } while (cur
!= NULL
);
9011 for (i
= 0, j
= 0; i
< nbRedund
; i
++, j
+= 2) {
9012 xmlFreeNs(listRedund
[j
]);
9014 xmlFree(listRedund
);
9017 xmlDOMWrapNsMapFree(nsMap
);
9022 * xmlDOMWrapAdoptBranch:
9023 * @ctxt: the optional context for custom processing
9024 * @sourceDoc: the optional sourceDoc
9025 * @node: the element-node to start with
9026 * @destDoc: the destination doc for adoption
9027 * @destParent: the optional new parent of @node in @destDoc
9028 * @options: option flags
9030 * Ensures that ns-references point to @destDoc: either to
9031 * elements->nsDef entries if @destParent is given, or to
9032 * @destDoc->oldNs otherwise.
9033 * If @destParent is given, it ensures that the tree is namespace
9034 * wellformed by creating additional ns-decls where needed.
9035 * Note that, since prefixes of already existent ns-decls can be
9036 * shadowed by this process, it could break QNames in attribute
9037 * values or element content.
9039 * NOTE: This function was not intensively tested.
9041 * Returns 0 if succeeded, -1 otherwise and on API/internal errors.
9044 xmlDOMWrapAdoptBranch(xmlDOMWrapCtxtPtr ctxt
,
9045 xmlDocPtr sourceDoc
,
9048 xmlNodePtr destParent
,
9049 int options ATTRIBUTE_UNUSED
)
9052 xmlNodePtr cur
, curElem
= NULL
;
9053 xmlNsMapPtr nsMap
= NULL
;
9056 int depth
= -1, adoptStr
= 1;
9057 /* gather @parent's ns-decls. */
9059 /* @ancestorsOnly should be set per option. */
9060 int ancestorsOnly
= 0;
9063 * Optimize string adoption for equal or none dicts.
9065 if ((sourceDoc
!= NULL
) &&
9066 (sourceDoc
->dict
== destDoc
->dict
))
9072 * Get the ns-map from the context if available.
9075 nsMap
= (xmlNsMapPtr
) ctxt
->namespaceMap
;
9077 * Disable search for ns-decls in the parent-axis of the
9078 * destination element, if:
9079 * 1) there's no destination parent
9080 * 2) custom ns-reference handling is used
9082 if ((destParent
== NULL
) ||
9083 (ctxt
&& ctxt
->getNsForNodeFunc
))
9090 if ((cur
!= NULL
) && (cur
->type
== XML_NAMESPACE_DECL
))
9091 goto internal_error
;
9093 while (cur
!= NULL
) {
9095 * Paranoid source-doc sanity check.
9097 if (cur
->doc
!= sourceDoc
) {
9099 * We'll assume XIncluded nodes if the doc differs.
9100 * TODO: Do we need to reconciliate XIncluded nodes?
9101 * This here skips XIncluded nodes and tries to handle
9104 if (cur
->next
== NULL
)
9108 if ((cur
->type
== XML_XINCLUDE_END
) ||
9109 (cur
->doc
== node
->doc
))
9111 } while (cur
->next
!= NULL
);
9113 if (cur
->doc
!= node
->doc
)
9117 switch (cur
->type
) {
9118 case XML_XINCLUDE_START
:
9119 case XML_XINCLUDE_END
:
9124 case XML_ELEMENT_NODE
:
9128 * Namespace declarations.
9129 * - ns->href and ns->prefix are never in the dict, so
9130 * we need not move the values over to the destination dict.
9131 * - Note that for custom handling of ns-references,
9132 * the ns-decls need not be stored in the ns-map,
9133 * since they won't be referenced by node->ns.
9136 ((ctxt
== NULL
) || (ctxt
->getNsForNodeFunc
== NULL
)))
9140 * Gather @parent's in-scope ns-decls.
9142 if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap
,
9144 goto internal_error
;
9147 for (ns
= cur
->nsDef
; ns
!= NULL
; ns
= ns
->next
) {
9149 * NOTE: ns->prefix and ns->href are never in the dict.
9150 * XML_TREE_ADOPT_STR(ns->prefix)
9151 * XML_TREE_ADOPT_STR(ns->href)
9154 * Does it shadow any ns-decl?
9156 if (XML_NSMAP_NOTEMPTY(nsMap
)) {
9157 XML_NSMAP_FOREACH(nsMap
, mi
) {
9158 if ((mi
->depth
>= XML_TREE_NSMAP_PARENT
) &&
9159 (mi
->shadowDepth
== -1) &&
9160 ((ns
->prefix
== mi
->newNs
->prefix
) ||
9161 xmlStrEqual(ns
->prefix
,
9162 mi
->newNs
->prefix
))) {
9164 mi
->shadowDepth
= depth
;
9171 if (xmlDOMWrapNsMapAddItem(&nsMap
, -1,
9172 ns
, ns
, depth
) == NULL
)
9173 goto internal_error
;
9176 /* Falls through. */
9177 case XML_ATTRIBUTE_NODE
:
9178 /* No namespace, no fun. */
9179 if (cur
->ns
== NULL
)
9183 if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap
,
9185 goto internal_error
;
9189 * Adopt ns-references.
9191 if (XML_NSMAP_NOTEMPTY(nsMap
)) {
9193 * Search for a mapping.
9195 XML_NSMAP_FOREACH(nsMap
, mi
) {
9196 if ((mi
->shadowDepth
== -1) &&
9197 (cur
->ns
== mi
->oldNs
)) {
9199 cur
->ns
= mi
->newNs
;
9205 * No matching namespace in scope. We need a new one.
9207 if ((ctxt
) && (ctxt
->getNsForNodeFunc
)) {
9209 * User-defined behaviour.
9211 ns
= ctxt
->getNsForNodeFunc(ctxt
, cur
,
9212 cur
->ns
->href
, cur
->ns
->prefix
);
9214 * Insert mapping if ns is available; it's the users fault
9217 if (xmlDOMWrapNsMapAddItem(&nsMap
, -1,
9218 cur
->ns
, ns
, XML_TREE_NSMAP_CUSTOM
) == NULL
)
9219 goto internal_error
;
9223 * Acquire a normalized ns-decl and add it to the map.
9225 if (xmlDOMWrapNSNormAcquireNormalizedNs(destDoc
,
9226 /* ns-decls on curElem or on destDoc->oldNs */
9227 destParent
? curElem
: NULL
,
9231 /* ns-decls must be prefixed for attributes. */
9232 (cur
->type
== XML_ATTRIBUTE_NODE
) ? 1 : 0) == -1)
9233 goto internal_error
;
9238 * Further node properties.
9239 * TODO: Is this all?
9241 XML_TREE_ADOPT_STR(cur
->name
)
9242 if (cur
->type
== XML_ELEMENT_NODE
) {
9249 if (cur
->properties
!= NULL
) {
9251 * Process first attribute node.
9253 cur
= (xmlNodePtr
) cur
->properties
;
9260 if ((sourceDoc
!= NULL
) &&
9261 (((xmlAttrPtr
) cur
)->atype
== XML_ATTRIBUTE_ID
))
9263 xmlRemoveID(sourceDoc
, (xmlAttrPtr
) cur
);
9265 ((xmlAttrPtr
) cur
)->atype
= 0;
9266 ((xmlAttrPtr
) cur
)->psvi
= NULL
;
9270 case XML_CDATA_SECTION_NODE
:
9272 * This puts the content in the dest dict, only if
9273 * it was previously in the source dict.
9275 XML_TREE_ADOPT_STR_2(cur
->content
)
9277 case XML_ENTITY_REF_NODE
:
9279 * Remove reference to the entity-node.
9281 cur
->content
= NULL
;
9282 cur
->children
= NULL
;
9284 if ((destDoc
->intSubset
) || (destDoc
->extSubset
)) {
9287 * Assign new entity-node if available.
9289 ent
= xmlGetDocEntity(destDoc
, cur
->name
);
9291 cur
->content
= ent
->content
;
9292 cur
->children
= (xmlNodePtr
) ent
;
9293 cur
->last
= (xmlNodePtr
) ent
;
9298 XML_TREE_ADOPT_STR(cur
->name
)
9299 XML_TREE_ADOPT_STR_2(cur
->content
)
9301 case XML_COMMENT_NODE
:
9304 goto internal_error
;
9309 if (cur
->children
!= NULL
) {
9310 cur
= cur
->children
;
9317 if ((cur
->type
== XML_ELEMENT_NODE
) ||
9318 (cur
->type
== XML_XINCLUDE_START
) ||
9319 (cur
->type
== XML_XINCLUDE_END
))
9322 * TODO: Do we expect nsDefs on XML_XINCLUDE_START?
9324 if (XML_NSMAP_NOTEMPTY(nsMap
)) {
9328 while ((nsMap
->last
!= NULL
) &&
9329 (nsMap
->last
->depth
>= depth
))
9331 XML_NSMAP_POP(nsMap
, mi
)
9336 XML_NSMAP_FOREACH(nsMap
, mi
) {
9337 if (mi
->shadowDepth
>= depth
)
9338 mi
->shadowDepth
= -1;
9343 if (cur
->next
!= NULL
)
9345 else if ((cur
->type
== XML_ATTRIBUTE_NODE
) &&
9346 (cur
->parent
->children
!= NULL
))
9348 cur
= cur
->parent
->children
;
9364 if (nsMap
!= NULL
) {
9365 if ((ctxt
) && (ctxt
->namespaceMap
== nsMap
)) {
9367 * Just cleanup the map but don't free.
9371 nsMap
->last
->next
= nsMap
->pool
;
9372 nsMap
->pool
= nsMap
->first
;
9373 nsMap
->first
= NULL
;
9376 xmlDOMWrapNsMapFree(nsMap
);
9382 * xmlDOMWrapCloneNode:
9383 * @ctxt: the optional context for custom processing
9384 * @sourceDoc: the optional sourceDoc
9385 * @node: the node to start with
9386 * @resNode: the clone of the given @node
9387 * @destDoc: the destination doc
9388 * @destParent: the optional new parent of @node in @destDoc
9389 * @deep: descend into child if set
9390 * @options: option flags
9392 * References of out-of scope ns-decls are remapped to point to @destDoc:
9393 * 1) If @destParent is given, then nsDef entries on element-nodes are used
9394 * 2) If *no* @destParent is given, then @destDoc->oldNs entries are used.
9395 * This is the case when you don't know already where the cloned branch
9398 * If @destParent is given, it ensures that the tree is namespace
9399 * wellformed by creating additional ns-decls where needed.
9400 * Note that, since prefixes of already existent ns-decls can be
9401 * shadowed by this process, it could break QNames in attribute
9402 * values or element content.
9404 * 1) What to do with XInclude? Currently this returns an error for XInclude.
9406 * Returns 0 if the operation succeeded,
9407 * 1 if a node of unsupported (or not yet supported) type was given,
9408 * -1 on API/internal errors.
9412 xmlDOMWrapCloneNode(xmlDOMWrapCtxtPtr ctxt
,
9413 xmlDocPtr sourceDoc
,
9415 xmlNodePtr
*resNode
,
9417 xmlNodePtr destParent
,
9419 int options ATTRIBUTE_UNUSED
)
9422 xmlNodePtr cur
, curElem
= NULL
;
9423 xmlNsMapPtr nsMap
= NULL
;
9427 /* int adoptStr = 1; */
9428 /* gather @parent's ns-decls. */
9432 * TODO: @ancestorsOnly should be set per option.
9435 int ancestorsOnly
= 0;
9436 xmlNodePtr resultClone
= NULL
, clone
= NULL
, parentClone
= NULL
, prevClone
= NULL
;
9437 xmlNsPtr cloneNs
= NULL
, *cloneNsDefSlot
= NULL
;
9438 xmlDictPtr dict
; /* The destination dict */
9440 if ((node
== NULL
) || (resNode
== NULL
) || (destDoc
== NULL
))
9443 * TODO: Initially we support only element-nodes.
9445 if (node
->type
!= XML_ELEMENT_NODE
)
9448 * Check node->doc sanity.
9450 if ((node
->doc
!= NULL
) && (sourceDoc
!= NULL
) &&
9451 (node
->doc
!= sourceDoc
)) {
9453 * Might be an XIncluded node.
9457 if (sourceDoc
== NULL
)
9458 sourceDoc
= node
->doc
;
9459 if (sourceDoc
== NULL
)
9462 dict
= destDoc
->dict
;
9464 * Reuse the namespace map of the context.
9467 nsMap
= (xmlNsMapPtr
) ctxt
->namespaceMap
;
9472 if ((cur
!= NULL
) && (cur
->type
== XML_NAMESPACE_DECL
))
9475 while (cur
!= NULL
) {
9476 if (cur
->doc
!= sourceDoc
) {
9478 * We'll assume XIncluded nodes if the doc differs.
9479 * TODO: Do we need to reconciliate XIncluded nodes?
9480 * TODO: This here returns -1 in this case.
9482 goto internal_error
;
9485 * Create a new node.
9487 switch (cur
->type
) {
9488 case XML_XINCLUDE_START
:
9489 case XML_XINCLUDE_END
:
9491 * TODO: What to do with XInclude?
9493 goto internal_error
;
9495 case XML_ELEMENT_NODE
:
9497 case XML_CDATA_SECTION_NODE
:
9498 case XML_COMMENT_NODE
:
9500 case XML_DOCUMENT_FRAG_NODE
:
9501 case XML_ENTITY_REF_NODE
:
9502 case XML_ENTITY_NODE
:
9504 * Nodes of xmlNode structure.
9506 clone
= (xmlNodePtr
) xmlMalloc(sizeof(xmlNode
));
9507 if (clone
== NULL
) {
9508 xmlTreeErrMemory("xmlDOMWrapCloneNode(): allocating a node");
9509 goto internal_error
;
9511 memset(clone
, 0, sizeof(xmlNode
));
9513 * Set hierarchical links.
9515 if (resultClone
!= NULL
) {
9516 clone
->parent
= parentClone
;
9518 prevClone
->next
= clone
;
9519 clone
->prev
= prevClone
;
9521 parentClone
->children
= clone
;
9523 resultClone
= clone
;
9526 case XML_ATTRIBUTE_NODE
:
9528 * Attributes (xmlAttr).
9530 clone
= (xmlNodePtr
) xmlMalloc(sizeof(xmlAttr
));
9531 if (clone
== NULL
) {
9532 xmlTreeErrMemory("xmlDOMWrapCloneNode(): allocating an attr-node");
9533 goto internal_error
;
9535 memset(clone
, 0, sizeof(xmlAttr
));
9537 * Set hierarchical links.
9538 * TODO: Change this to add to the end of attributes.
9540 if (resultClone
!= NULL
) {
9541 clone
->parent
= parentClone
;
9543 prevClone
->next
= clone
;
9544 clone
->prev
= prevClone
;
9546 parentClone
->properties
= (xmlAttrPtr
) clone
;
9548 resultClone
= clone
;
9552 * TODO QUESTION: Any other nodes expected?
9554 goto internal_error
;
9557 clone
->type
= cur
->type
;
9558 clone
->doc
= destDoc
;
9561 * Clone the name of the node if any.
9563 if (cur
->name
== xmlStringText
)
9564 clone
->name
= xmlStringText
;
9565 else if (cur
->name
== xmlStringTextNoenc
)
9567 * NOTE: Although xmlStringTextNoenc is never assigned to a node
9568 * in tree.c, it might be set in Libxslt via
9569 * "xsl:disable-output-escaping".
9571 clone
->name
= xmlStringTextNoenc
;
9572 else if (cur
->name
== xmlStringComment
)
9573 clone
->name
= xmlStringComment
;
9574 else if (cur
->name
!= NULL
) {
9575 DICT_CONST_COPY(cur
->name
, clone
->name
);
9578 switch (cur
->type
) {
9579 case XML_XINCLUDE_START
:
9580 case XML_XINCLUDE_END
:
9585 case XML_ELEMENT_NODE
:
9589 * Namespace declarations.
9591 if (cur
->nsDef
!= NULL
) {
9593 if (destParent
&& (ctxt
== NULL
)) {
9595 * Gather @parent's in-scope ns-decls.
9597 if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap
,
9599 goto internal_error
;
9604 * Clone namespace declarations.
9606 cloneNsDefSlot
= &(clone
->nsDef
);
9607 for (ns
= cur
->nsDef
; ns
!= NULL
; ns
= ns
->next
) {
9609 * Create a new xmlNs.
9611 cloneNs
= (xmlNsPtr
) xmlMalloc(sizeof(xmlNs
));
9612 if (cloneNs
== NULL
) {
9613 xmlTreeErrMemory("xmlDOMWrapCloneNode(): "
9614 "allocating namespace");
9617 memset(cloneNs
, 0, sizeof(xmlNs
));
9618 cloneNs
->type
= XML_LOCAL_NAMESPACE
;
9620 if (ns
->href
!= NULL
)
9621 cloneNs
->href
= xmlStrdup(ns
->href
);
9622 if (ns
->prefix
!= NULL
)
9623 cloneNs
->prefix
= xmlStrdup(ns
->prefix
);
9625 *cloneNsDefSlot
= cloneNs
;
9626 cloneNsDefSlot
= &(cloneNs
->next
);
9629 * Note that for custom handling of ns-references,
9630 * the ns-decls need not be stored in the ns-map,
9631 * since they won't be referenced by node->ns.
9633 if ((ctxt
== NULL
) ||
9634 (ctxt
->getNsForNodeFunc
== NULL
))
9637 * Does it shadow any ns-decl?
9639 if (XML_NSMAP_NOTEMPTY(nsMap
)) {
9640 XML_NSMAP_FOREACH(nsMap
, mi
) {
9641 if ((mi
->depth
>= XML_TREE_NSMAP_PARENT
) &&
9642 (mi
->shadowDepth
== -1) &&
9643 ((ns
->prefix
== mi
->newNs
->prefix
) ||
9644 xmlStrEqual(ns
->prefix
,
9645 mi
->newNs
->prefix
))) {
9647 * Mark as shadowed at the current
9650 mi
->shadowDepth
= depth
;
9657 if (xmlDOMWrapNsMapAddItem(&nsMap
, -1,
9658 ns
, cloneNs
, depth
) == NULL
)
9659 goto internal_error
;
9663 /* cur->ns will be processed further down. */
9665 case XML_ATTRIBUTE_NODE
:
9666 /* IDs will be processed further down. */
9667 /* cur->ns will be processed further down. */
9670 case XML_CDATA_SECTION_NODE
:
9672 * Note that this will also cover the values of attributes.
9674 DICT_COPY(cur
->content
, clone
->content
);
9676 case XML_ENTITY_NODE
:
9677 /* TODO: What to do here? */
9679 case XML_ENTITY_REF_NODE
:
9680 if (sourceDoc
!= destDoc
) {
9681 if ((destDoc
->intSubset
) || (destDoc
->extSubset
)) {
9684 * Different doc: Assign new entity-node if available.
9686 ent
= xmlGetDocEntity(destDoc
, cur
->name
);
9688 clone
->content
= ent
->content
;
9689 clone
->children
= (xmlNodePtr
) ent
;
9690 clone
->last
= (xmlNodePtr
) ent
;
9695 * Same doc: Use the current node's entity declaration
9698 clone
->content
= cur
->content
;
9699 clone
->children
= cur
->children
;
9700 clone
->last
= cur
->last
;
9704 DICT_COPY(cur
->content
, clone
->content
);
9706 case XML_COMMENT_NODE
:
9707 DICT_COPY(cur
->content
, clone
->content
);
9710 goto internal_error
;
9713 if (cur
->ns
== NULL
)
9714 goto end_ns_reference
;
9716 /* handle_ns_reference: */
9718 ** The following will take care of references to ns-decls ********
9719 ** and is intended only for element- and attribute-nodes.
9723 if (destParent
&& (ctxt
== NULL
)) {
9724 if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap
, destParent
) == -1)
9725 goto internal_error
;
9730 * Adopt ns-references.
9732 if (XML_NSMAP_NOTEMPTY(nsMap
)) {
9734 * Search for a mapping.
9736 XML_NSMAP_FOREACH(nsMap
, mi
) {
9737 if ((mi
->shadowDepth
== -1) &&
9738 (cur
->ns
== mi
->oldNs
)) {
9740 * This is the nice case: a mapping was found.
9742 clone
->ns
= mi
->newNs
;
9743 goto end_ns_reference
;
9748 * No matching namespace in scope. We need a new one.
9750 if ((ctxt
!= NULL
) && (ctxt
->getNsForNodeFunc
!= NULL
)) {
9752 * User-defined behaviour.
9754 ns
= ctxt
->getNsForNodeFunc(ctxt
, cur
,
9755 cur
->ns
->href
, cur
->ns
->prefix
);
9757 * Add user's mapping.
9759 if (xmlDOMWrapNsMapAddItem(&nsMap
, -1,
9760 cur
->ns
, ns
, XML_TREE_NSMAP_CUSTOM
) == NULL
)
9761 goto internal_error
;
9765 * Acquire a normalized ns-decl and add it to the map.
9767 if (xmlDOMWrapNSNormAcquireNormalizedNs(destDoc
,
9768 /* ns-decls on curElem or on destDoc->oldNs */
9769 destParent
? curElem
: NULL
,
9772 /* if we need to search only in the ancestor-axis */
9774 /* ns-decls must be prefixed for attributes. */
9775 (cur
->type
== XML_ATTRIBUTE_NODE
) ? 1 : 0) == -1)
9776 goto internal_error
;
9783 * Some post-processing.
9785 * Handle ID attributes.
9787 if ((clone
->type
== XML_ATTRIBUTE_NODE
) &&
9788 (clone
->parent
!= NULL
))
9790 if (xmlIsID(destDoc
, clone
->parent
, (xmlAttrPtr
) clone
)) {
9794 idVal
= xmlNodeListGetString(cur
->doc
, cur
->children
, 1);
9795 if (idVal
!= NULL
) {
9796 if (xmlAddID(NULL
, destDoc
, idVal
, (xmlAttrPtr
) cur
) == NULL
) {
9797 /* TODO: error message. */
9799 goto internal_error
;
9807 ** The following will traverse the tree **************************
9810 * Walk the element's attributes before descending into child-nodes.
9812 if ((cur
->type
== XML_ELEMENT_NODE
) && (cur
->properties
!= NULL
)) {
9814 parentClone
= clone
;
9815 cur
= (xmlNodePtr
) cur
->properties
;
9820 * Descend into child-nodes.
9822 if (cur
->children
!= NULL
) {
9823 if (deep
|| (cur
->type
== XML_ATTRIBUTE_NODE
)) {
9825 parentClone
= clone
;
9826 cur
= cur
->children
;
9833 * At this point we are done with the node, its content
9834 * and an element-nodes's attribute-nodes.
9838 if ((cur
->type
== XML_ELEMENT_NODE
) ||
9839 (cur
->type
== XML_XINCLUDE_START
) ||
9840 (cur
->type
== XML_XINCLUDE_END
)) {
9842 * TODO: Do we expect nsDefs on XML_XINCLUDE_START?
9844 if (XML_NSMAP_NOTEMPTY(nsMap
)) {
9848 while ((nsMap
->last
!= NULL
) &&
9849 (nsMap
->last
->depth
>= depth
))
9851 XML_NSMAP_POP(nsMap
, mi
)
9856 XML_NSMAP_FOREACH(nsMap
, mi
) {
9857 if (mi
->shadowDepth
>= depth
)
9858 mi
->shadowDepth
= -1;
9863 if (cur
->next
!= NULL
) {
9866 } else if (cur
->type
!= XML_ATTRIBUTE_NODE
) {
9870 if (clone
->parent
!= NULL
)
9871 clone
->parent
->last
= clone
;
9872 clone
= clone
->parent
;
9874 parentClone
= clone
->parent
;
9876 * Process parent --> next;
9881 /* This is for attributes only. */
9882 clone
= clone
->parent
;
9883 parentClone
= clone
->parent
;
9885 * Process parent-element --> children.
9900 if (nsMap
!= NULL
) {
9901 if ((ctxt
) && (ctxt
->namespaceMap
== nsMap
)) {
9903 * Just cleanup the map but don't free.
9907 nsMap
->last
->next
= nsMap
->pool
;
9908 nsMap
->pool
= nsMap
->first
;
9909 nsMap
->first
= NULL
;
9912 xmlDOMWrapNsMapFree(nsMap
);
9915 * TODO: Should we try a cleanup of the cloned node in case of a
9918 *resNode
= resultClone
;
9923 * xmlDOMWrapAdoptAttr:
9924 * @ctxt: the optional context for custom processing
9925 * @sourceDoc: the optional source document of attr
9926 * @attr: the attribute-node to be adopted
9927 * @destDoc: the destination doc for adoption
9928 * @destParent: the optional new parent of @attr in @destDoc
9929 * @options: option flags
9931 * @attr is adopted by @destDoc.
9932 * Ensures that ns-references point to @destDoc: either to
9933 * elements->nsDef entries if @destParent is given, or to
9934 * @destDoc->oldNs otherwise.
9936 * Returns 0 if succeeded, -1 otherwise and on API/internal errors.
9939 xmlDOMWrapAdoptAttr(xmlDOMWrapCtxtPtr ctxt
,
9940 xmlDocPtr sourceDoc
,
9943 xmlNodePtr destParent
,
9944 int options ATTRIBUTE_UNUSED
)
9949 if ((attr
== NULL
) || (destDoc
== NULL
))
9952 attr
->doc
= destDoc
;
9953 if (attr
->ns
!= NULL
) {
9957 /* TODO: User defined. */
9959 /* XML Namespace. */
9960 if (IS_STR_XML(attr
->ns
->prefix
)) {
9961 ns
= xmlTreeEnsureXMLDecl(destDoc
);
9962 } else if (destParent
== NULL
) {
9964 * Store in @destDoc->oldNs.
9966 ns
= xmlDOMWrapStoreNs(destDoc
, attr
->ns
->href
, attr
->ns
->prefix
);
9969 * Declare on @destParent.
9971 if (xmlSearchNsByNamespaceStrict(destDoc
, destParent
, attr
->ns
->href
,
9973 goto internal_error
;
9975 ns
= xmlDOMWrapNSNormDeclareNsForced(destDoc
, destParent
,
9976 attr
->ns
->href
, attr
->ns
->prefix
, 1);
9980 goto internal_error
;
9984 XML_TREE_ADOPT_STR(attr
->name
);
9990 if (attr
->children
== NULL
)
9992 cur
= attr
->children
;
9993 if ((cur
!= NULL
) && (cur
->type
== XML_NAMESPACE_DECL
))
9994 goto internal_error
;
9995 while (cur
!= NULL
) {
9997 switch (cur
->type
) {
9999 case XML_CDATA_SECTION_NODE
:
10000 XML_TREE_ADOPT_STR_2(cur
->content
)
10002 case XML_ENTITY_REF_NODE
:
10004 * Remove reference to the entity-node.
10006 cur
->content
= NULL
;
10007 cur
->children
= NULL
;
10009 if ((destDoc
->intSubset
) || (destDoc
->extSubset
)) {
10012 * Assign new entity-node if available.
10014 ent
= xmlGetDocEntity(destDoc
, cur
->name
);
10016 cur
->content
= ent
->content
;
10017 cur
->children
= (xmlNodePtr
) ent
;
10018 cur
->last
= (xmlNodePtr
) ent
;
10025 if (cur
->children
!= NULL
) {
10026 cur
= cur
->children
;
10030 if (cur
== (xmlNodePtr
) attr
)
10032 if (cur
->next
!= NULL
)
10045 * xmlDOMWrapAdoptNode:
10046 * @ctxt: the optional context for custom processing
10047 * @sourceDoc: the optional sourceDoc
10048 * @node: the node to start with
10049 * @destDoc: the destination doc
10050 * @destParent: the optional new parent of @node in @destDoc
10051 * @options: option flags
10053 * References of out-of scope ns-decls are remapped to point to @destDoc:
10054 * 1) If @destParent is given, then nsDef entries on element-nodes are used
10055 * 2) If *no* @destParent is given, then @destDoc->oldNs entries are used
10056 * This is the case when you have an unlinked node and just want to move it
10057 * to the context of
10059 * If @destParent is given, it ensures that the tree is namespace
10060 * wellformed by creating additional ns-decls where needed.
10061 * Note that, since prefixes of already existent ns-decls can be
10062 * shadowed by this process, it could break QNames in attribute
10063 * values or element content.
10064 * NOTE: This function was not intensively tested.
10066 * Returns 0 if the operation succeeded,
10067 * 1 if a node of unsupported type was given,
10068 * 2 if a node of not yet supported type was given and
10069 * -1 on API/internal errors.
10072 xmlDOMWrapAdoptNode(xmlDOMWrapCtxtPtr ctxt
,
10073 xmlDocPtr sourceDoc
,
10076 xmlNodePtr destParent
,
10079 if ((node
== NULL
) || (node
->type
== XML_NAMESPACE_DECL
) ||
10080 (destDoc
== NULL
) ||
10081 ((destParent
!= NULL
) && (destParent
->doc
!= destDoc
)))
10084 * Check node->doc sanity.
10086 if ((node
->doc
!= NULL
) && (sourceDoc
!= NULL
) &&
10087 (node
->doc
!= sourceDoc
)) {
10089 * Might be an XIncluded node.
10093 if (sourceDoc
== NULL
)
10094 sourceDoc
= node
->doc
;
10095 if (sourceDoc
== destDoc
)
10097 switch (node
->type
) {
10098 case XML_ELEMENT_NODE
:
10099 case XML_ATTRIBUTE_NODE
:
10100 case XML_TEXT_NODE
:
10101 case XML_CDATA_SECTION_NODE
:
10102 case XML_ENTITY_REF_NODE
:
10104 case XML_COMMENT_NODE
:
10106 case XML_DOCUMENT_FRAG_NODE
:
10107 /* TODO: Support document-fragment-nodes. */
10113 * Unlink only if @node was not already added to @destParent.
10115 if ((node
->parent
!= NULL
) && (destParent
!= node
->parent
))
10116 xmlUnlinkNode(node
);
10118 if (node
->type
== XML_ELEMENT_NODE
) {
10119 return (xmlDOMWrapAdoptBranch(ctxt
, sourceDoc
, node
,
10120 destDoc
, destParent
, options
));
10121 } else if (node
->type
== XML_ATTRIBUTE_NODE
) {
10122 return (xmlDOMWrapAdoptAttr(ctxt
, sourceDoc
,
10123 (xmlAttrPtr
) node
, destDoc
, destParent
, options
));
10125 xmlNodePtr cur
= node
;
10128 cur
->doc
= destDoc
;
10130 * Optimize string adoption.
10132 if ((sourceDoc
!= NULL
) &&
10133 (sourceDoc
->dict
== destDoc
->dict
))
10135 switch (node
->type
) {
10136 case XML_TEXT_NODE
:
10137 case XML_CDATA_SECTION_NODE
:
10138 XML_TREE_ADOPT_STR_2(node
->content
)
10140 case XML_ENTITY_REF_NODE
:
10142 * Remove reference to the entity-node.
10144 node
->content
= NULL
;
10145 node
->children
= NULL
;
10147 if ((destDoc
->intSubset
) || (destDoc
->extSubset
)) {
10150 * Assign new entity-node if available.
10152 ent
= xmlGetDocEntity(destDoc
, node
->name
);
10154 node
->content
= ent
->content
;
10155 node
->children
= (xmlNodePtr
) ent
;
10156 node
->last
= (xmlNodePtr
) ent
;
10159 XML_TREE_ADOPT_STR(node
->name
)
10161 case XML_PI_NODE
: {
10162 XML_TREE_ADOPT_STR(node
->name
)
10163 XML_TREE_ADOPT_STR_2(node
->content
)
10173 #define bottom_tree
10174 #include "elfgcchack.h"