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.
16 #include <string.h> /* for memset() only ! */
28 #include <libxml/xmlmemory.h>
29 #include <libxml/tree.h>
30 #include <libxml/parser.h>
31 #include <libxml/uri.h>
32 #include <libxml/entities.h>
33 #include <libxml/valid.h>
34 #include <libxml/xmlerror.h>
35 #include <libxml/parserInternals.h>
36 #include <libxml/globals.h>
37 #ifdef LIBXML_HTML_ENABLED
38 #include <libxml/HTMLtree.h>
40 #ifdef LIBXML_DEBUG_ENABLED
41 #include <libxml/debugXML.h>
44 int __xmlRegisterCallbacks
= 0;
46 /************************************************************************
48 * Forward declarations *
50 ************************************************************************/
53 xmlNewReconciliedNs(xmlDocPtr doc
, xmlNodePtr tree
, xmlNsPtr ns
);
55 static xmlChar
* xmlGetPropNodeValueInternal(xmlAttrPtr prop
);
57 /************************************************************************
59 * Tree memory error handler *
61 ************************************************************************/
64 * @extra: extra informations
66 * Handle an out of memory condition
69 xmlTreeErrMemory(const char *extra
)
71 __xmlSimpleError(XML_FROM_TREE
, XML_ERR_NO_MEMORY
, NULL
, NULL
, extra
);
76 * @code: the error number
77 * @extra: extra informations
79 * Handle an out of memory condition
82 xmlTreeErr(int code
, xmlNodePtr node
, const char *extra
)
84 const char *msg
= NULL
;
87 case XML_TREE_INVALID_HEX
:
88 msg
= "invalid hexadecimal character value\n";
90 case XML_TREE_INVALID_DEC
:
91 msg
= "invalid decimal character value\n";
93 case XML_TREE_UNTERMINATED_ENTITY
:
94 msg
= "unterminated entity reference %15s\n";
96 case XML_TREE_NOT_UTF8
:
97 msg
= "string is not in UTF-8\n";
100 msg
= "unexpected error number\n";
102 __xmlSimpleError(XML_FROM_TREE
, code
, node
, msg
, extra
);
105 /************************************************************************
107 * A few static variables and macros *
109 ************************************************************************/
110 /* #undef xmlStringText */
111 const xmlChar xmlStringText
[] = { 't', 'e', 'x', 't', 0 };
112 /* #undef xmlStringTextNoenc */
113 const xmlChar xmlStringTextNoenc
[] =
114 { 't', 'e', 'x', 't', 'n', 'o', 'e', 'n', 'c', 0 };
115 /* #undef xmlStringComment */
116 const xmlChar xmlStringComment
[] = { 'c', 'o', 'm', 'm', 'e', 'n', 't', 0 };
118 static int xmlCompressMode
= 0;
119 static int xmlCheckDTD
= 1;
121 #define UPDATE_LAST_CHILD_AND_PARENT(n) if ((n) != NULL) { \
122 xmlNodePtr ulccur = (n)->children; \
123 if (ulccur == NULL) { \
126 while (ulccur->next != NULL) { \
127 ulccur->parent = (n); \
128 ulccur = ulccur->next; \
130 ulccur->parent = (n); \
131 (n)->last = ulccur; \
134 #define IS_STR_XML(str) ((str != NULL) && (str[0] == 'x') && \
135 (str[1] == 'm') && (str[2] == 'l') && (str[3] == 0))
137 /* #define DEBUG_BUFFER */
138 /* #define DEBUG_TREE */
140 /************************************************************************
142 * Functions to move to entities.c once the *
143 * API freeze is smoothen and they can be made public. *
145 ************************************************************************/
146 #include <libxml/hash.h>
148 #ifdef LIBXML_TREE_ENABLED
150 * xmlGetEntityFromDtd:
151 * @dtd: A pointer to the DTD to search
152 * @name: The entity name
154 * Do an entity lookup in the DTD entity hash table and
155 * return the corresponding entity, if found.
157 * Returns A pointer to the entity structure or NULL if not found.
160 xmlGetEntityFromDtd(xmlDtdPtr dtd
, const xmlChar
*name
) {
161 xmlEntitiesTablePtr table
;
163 if((dtd
!= NULL
) && (dtd
->entities
!= NULL
)) {
164 table
= (xmlEntitiesTablePtr
) dtd
->entities
;
165 return((xmlEntityPtr
) xmlHashLookup(table
, name
));
166 /* return(xmlGetEntityFromTable(table, name)); */
171 * xmlGetParameterEntityFromDtd:
172 * @dtd: A pointer to the DTD to search
173 * @name: The entity name
175 * Do an entity lookup in the DTD pararmeter entity hash table and
176 * return the corresponding entity, if found.
178 * Returns A pointer to the entity structure or NULL if not found.
181 xmlGetParameterEntityFromDtd(xmlDtdPtr dtd
, const xmlChar
*name
) {
182 xmlEntitiesTablePtr table
;
184 if ((dtd
!= NULL
) && (dtd
->pentities
!= NULL
)) {
185 table
= (xmlEntitiesTablePtr
) dtd
->pentities
;
186 return((xmlEntityPtr
) xmlHashLookup(table
, name
));
187 /* return(xmlGetEntityFromTable(table, name)); */
191 #endif /* LIBXML_TREE_ENABLED */
193 /************************************************************************
195 * QName handling helper *
197 ************************************************************************/
202 * @prefix: the prefix
203 * @memory: preallocated memory
204 * @len: preallocated memory length
206 * Builds the QName @prefix:@ncname in @memory if there is enough space
207 * and prefix is not NULL nor empty, otherwise allocate a new string.
208 * If prefix is NULL or empty it returns ncname.
210 * Returns the new string which must be freed by the caller if different from
211 * @memory and @ncname or NULL in case of error
214 xmlBuildQName(const xmlChar
*ncname
, const xmlChar
*prefix
,
215 xmlChar
*memory
, int len
) {
219 if (ncname
== NULL
) return(NULL
);
220 if (prefix
== NULL
) return((xmlChar
*) ncname
);
222 lenn
= strlen((char *) ncname
);
223 lenp
= strlen((char *) prefix
);
225 if ((memory
== NULL
) || (len
< lenn
+ lenp
+ 2)) {
226 ret
= (xmlChar
*) xmlMallocAtomic(lenn
+ lenp
+ 2);
228 xmlTreeErrMemory("building QName");
234 memcpy(&ret
[0], prefix
, lenp
);
236 memcpy(&ret
[lenp
+ 1], ncname
, lenn
);
237 ret
[lenn
+ lenp
+ 1] = 0;
243 * @name: the full QName
244 * @prefix: a xmlChar **
246 * parse an XML qualified name string
248 * [NS 5] QName ::= (Prefix ':')? LocalPart
250 * [NS 6] Prefix ::= NCName
252 * [NS 7] LocalPart ::= NCName
254 * Returns NULL if not a QName, otherwise the local part, and prefix
255 * is updated to get the Prefix if any.
259 xmlSplitQName2(const xmlChar
*name
, xmlChar
**prefix
) {
263 if (prefix
== NULL
) return(NULL
);
265 if (name
== NULL
) return(NULL
);
267 #ifndef XML_XML_NAMESPACE
268 /* xml: prefix is not really a namespace */
269 if ((name
[0] == 'x') && (name
[1] == 'm') &&
270 (name
[2] == 'l') && (name
[3] == ':'))
274 /* nasty but valid */
279 * we are not trying to validate but just to cut, and yes it will
280 * work even if this is as set of UTF-8 encoded chars
282 while ((name
[len
] != 0) && (name
[len
] != ':'))
288 *prefix
= xmlStrndup(name
, len
);
289 if (*prefix
== NULL
) {
290 xmlTreeErrMemory("QName split");
293 ret
= xmlStrdup(&name
[len
+ 1]);
295 xmlTreeErrMemory("QName split");
296 if (*prefix
!= NULL
) {
308 * @name: the full QName
311 * parse an XML qualified name string,i
313 * returns NULL if it is not a Qualified Name, otherwise, update len
314 * with the lenght in byte of the prefix and return a pointer
315 * to the start of the name without the prefix
319 xmlSplitQName3(const xmlChar
*name
, int *len
) {
322 if (name
== NULL
) return(NULL
);
323 if (len
== NULL
) return(NULL
);
325 /* nasty but valid */
330 * we are not trying to validate but just to cut, and yes it will
331 * work even if this is as set of UTF-8 encoded chars
333 while ((name
[l
] != 0) && (name
[l
] != ':'))
344 /************************************************************************
346 * Check Name, NCName and QName strings *
348 ************************************************************************/
350 #define CUR_SCHAR(s, l) xmlStringCurrentChar(NULL, s, &l)
352 #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)
355 * @value: the value to check
356 * @space: allow spaces in front and end of the string
358 * Check that a value conforms to the lexical space of NCName
360 * Returns 0 if this validates, a positive error code number otherwise
361 * and -1 in case of internal or API error.
364 xmlValidateNCName(const xmlChar
*value
, int space
) {
365 const xmlChar
*cur
= value
;
372 * First quick algorithm for ASCII range
375 while (IS_BLANK_CH(*cur
)) cur
++;
376 if (((*cur
>= 'a') && (*cur
<= 'z')) || ((*cur
>= 'A') && (*cur
<= 'Z')) ||
381 while (((*cur
>= 'a') && (*cur
<= 'z')) ||
382 ((*cur
>= 'A') && (*cur
<= 'Z')) ||
383 ((*cur
>= '0') && (*cur
<= '9')) ||
384 (*cur
== '_') || (*cur
== '-') || (*cur
== '.'))
387 while (IS_BLANK_CH(*cur
)) cur
++;
393 * Second check for chars outside the ASCII range
396 c
= CUR_SCHAR(cur
, l
);
398 while (IS_BLANK(c
)) {
400 c
= CUR_SCHAR(cur
, l
);
403 if ((!IS_LETTER(c
)) && (c
!= '_'))
406 c
= CUR_SCHAR(cur
, l
);
407 while (IS_LETTER(c
) || IS_DIGIT(c
) || (c
== '.') ||
408 (c
== '-') || (c
== '_') || IS_COMBINING(c
) ||
411 c
= CUR_SCHAR(cur
, l
);
414 while (IS_BLANK(c
)) {
416 c
= CUR_SCHAR(cur
, l
);
426 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
429 * @value: the value to check
430 * @space: allow spaces in front and end of the string
432 * Check that a value conforms to the lexical space of QName
434 * Returns 0 if this validates, a positive error code number otherwise
435 * and -1 in case of internal or API error.
438 xmlValidateQName(const xmlChar
*value
, int space
) {
439 const xmlChar
*cur
= value
;
445 * First quick algorithm for ASCII range
448 while (IS_BLANK_CH(*cur
)) cur
++;
449 if (((*cur
>= 'a') && (*cur
<= 'z')) || ((*cur
>= 'A') && (*cur
<= 'Z')) ||
454 while (((*cur
>= 'a') && (*cur
<= 'z')) ||
455 ((*cur
>= 'A') && (*cur
<= 'Z')) ||
456 ((*cur
>= '0') && (*cur
<= '9')) ||
457 (*cur
== '_') || (*cur
== '-') || (*cur
== '.'))
461 if (((*cur
>= 'a') && (*cur
<= 'z')) ||
462 ((*cur
>= 'A') && (*cur
<= 'Z')) ||
467 while (((*cur
>= 'a') && (*cur
<= 'z')) ||
468 ((*cur
>= 'A') && (*cur
<= 'Z')) ||
469 ((*cur
>= '0') && (*cur
<= '9')) ||
470 (*cur
== '_') || (*cur
== '-') || (*cur
== '.'))
474 while (IS_BLANK_CH(*cur
)) cur
++;
480 * Second check for chars outside the ASCII range
483 c
= CUR_SCHAR(cur
, l
);
485 while (IS_BLANK(c
)) {
487 c
= CUR_SCHAR(cur
, l
);
490 if ((!IS_LETTER(c
)) && (c
!= '_'))
493 c
= CUR_SCHAR(cur
, l
);
494 while (IS_LETTER(c
) || IS_DIGIT(c
) || (c
== '.') ||
495 (c
== '-') || (c
== '_') || IS_COMBINING(c
) ||
498 c
= CUR_SCHAR(cur
, l
);
502 c
= CUR_SCHAR(cur
, l
);
503 if ((!IS_LETTER(c
)) && (c
!= '_'))
506 c
= CUR_SCHAR(cur
, l
);
507 while (IS_LETTER(c
) || IS_DIGIT(c
) || (c
== '.') ||
508 (c
== '-') || (c
== '_') || IS_COMBINING(c
) ||
511 c
= CUR_SCHAR(cur
, l
);
515 while (IS_BLANK(c
)) {
517 c
= CUR_SCHAR(cur
, l
);
527 * @value: the value to check
528 * @space: allow spaces in front and end of the string
530 * Check that a value conforms to the lexical space of Name
532 * Returns 0 if this validates, a positive error code number otherwise
533 * and -1 in case of internal or API error.
536 xmlValidateName(const xmlChar
*value
, int space
) {
537 const xmlChar
*cur
= value
;
543 * First quick algorithm for ASCII range
546 while (IS_BLANK_CH(*cur
)) cur
++;
547 if (((*cur
>= 'a') && (*cur
<= 'z')) || ((*cur
>= 'A') && (*cur
<= 'Z')) ||
548 (*cur
== '_') || (*cur
== ':'))
552 while (((*cur
>= 'a') && (*cur
<= 'z')) ||
553 ((*cur
>= 'A') && (*cur
<= 'Z')) ||
554 ((*cur
>= '0') && (*cur
<= '9')) ||
555 (*cur
== '_') || (*cur
== '-') || (*cur
== '.') || (*cur
== ':'))
558 while (IS_BLANK_CH(*cur
)) cur
++;
564 * Second check for chars outside the ASCII range
567 c
= CUR_SCHAR(cur
, l
);
569 while (IS_BLANK(c
)) {
571 c
= CUR_SCHAR(cur
, l
);
574 if ((!IS_LETTER(c
)) && (c
!= '_') && (c
!= ':'))
577 c
= CUR_SCHAR(cur
, l
);
578 while (IS_LETTER(c
) || IS_DIGIT(c
) || (c
== '.') || (c
== ':') ||
579 (c
== '-') || (c
== '_') || IS_COMBINING(c
) || IS_EXTENDER(c
)) {
581 c
= CUR_SCHAR(cur
, l
);
584 while (IS_BLANK(c
)) {
586 c
= CUR_SCHAR(cur
, l
);
595 * xmlValidateNMToken:
596 * @value: the value to check
597 * @space: allow spaces in front and end of the string
599 * Check that a value conforms to the lexical space of NMToken
601 * Returns 0 if this validates, a positive error code number otherwise
602 * and -1 in case of internal or API error.
605 xmlValidateNMToken(const xmlChar
*value
, int space
) {
606 const xmlChar
*cur
= value
;
612 * First quick algorithm for ASCII range
615 while (IS_BLANK_CH(*cur
)) cur
++;
616 if (((*cur
>= 'a') && (*cur
<= 'z')) ||
617 ((*cur
>= 'A') && (*cur
<= 'Z')) ||
618 ((*cur
>= '0') && (*cur
<= '9')) ||
619 (*cur
== '_') || (*cur
== '-') || (*cur
== '.') || (*cur
== ':'))
623 while (((*cur
>= 'a') && (*cur
<= 'z')) ||
624 ((*cur
>= 'A') && (*cur
<= 'Z')) ||
625 ((*cur
>= '0') && (*cur
<= '9')) ||
626 (*cur
== '_') || (*cur
== '-') || (*cur
== '.') || (*cur
== ':'))
629 while (IS_BLANK_CH(*cur
)) cur
++;
635 * Second check for chars outside the ASCII range
638 c
= CUR_SCHAR(cur
, l
);
640 while (IS_BLANK(c
)) {
642 c
= CUR_SCHAR(cur
, l
);
645 if (!(IS_LETTER(c
) || IS_DIGIT(c
) || (c
== '.') || (c
== ':') ||
646 (c
== '-') || (c
== '_') || IS_COMBINING(c
) || IS_EXTENDER(c
)))
649 c
= CUR_SCHAR(cur
, l
);
650 while (IS_LETTER(c
) || IS_DIGIT(c
) || (c
== '.') || (c
== ':') ||
651 (c
== '-') || (c
== '_') || IS_COMBINING(c
) || IS_EXTENDER(c
)) {
653 c
= CUR_SCHAR(cur
, l
);
656 while (IS_BLANK(c
)) {
658 c
= CUR_SCHAR(cur
, l
);
665 #endif /* LIBXML_TREE_ENABLED */
667 /************************************************************************
669 * Allocation and deallocation of basic structures *
671 ************************************************************************/
674 * xmlSetBufferAllocationScheme:
675 * @scheme: allocation method to use
677 * Set the buffer allocation method. Types are
678 * XML_BUFFER_ALLOC_EXACT - use exact sizes, keeps memory usage down
679 * XML_BUFFER_ALLOC_DOUBLEIT - double buffer when extra needed,
680 * improves performance
683 xmlSetBufferAllocationScheme(xmlBufferAllocationScheme scheme
) {
684 if ((scheme
== XML_BUFFER_ALLOC_EXACT
) ||
685 (scheme
== XML_BUFFER_ALLOC_DOUBLEIT
))
686 xmlBufferAllocScheme
= scheme
;
690 * xmlGetBufferAllocationScheme:
693 * XML_BUFFER_ALLOC_EXACT - use exact sizes, keeps memory usage down
694 * XML_BUFFER_ALLOC_DOUBLEIT - double buffer when extra needed,
695 * improves performance
697 * Returns the current allocation scheme
699 xmlBufferAllocationScheme
700 xmlGetBufferAllocationScheme(void) {
701 return(xmlBufferAllocScheme
);
706 * @node: the element carrying the namespace
707 * @href: the URI associated
708 * @prefix: the prefix for the namespace
710 * Creation of a new Namespace. This function will refuse to create
711 * a namespace with a similar prefix than an existing one present on this
713 * We use href==NULL in the case of an element creation where the namespace
715 * Returns a new namespace pointer or NULL
718 xmlNewNs(xmlNodePtr node
, const xmlChar
*href
, const xmlChar
*prefix
) {
721 if ((node
!= NULL
) && (node
->type
!= XML_ELEMENT_NODE
))
724 if ((prefix
!= NULL
) && (xmlStrEqual(prefix
, BAD_CAST
"xml")))
728 * Allocate a new Namespace and fill the fields.
730 cur
= (xmlNsPtr
) xmlMalloc(sizeof(xmlNs
));
732 xmlTreeErrMemory("building namespace");
735 memset(cur
, 0, sizeof(xmlNs
));
736 cur
->type
= XML_LOCAL_NAMESPACE
;
739 cur
->href
= xmlStrdup(href
);
741 cur
->prefix
= xmlStrdup(prefix
);
744 * Add it at the end to preserve parsing order ...
745 * and checks for existing use of the prefix
748 if (node
->nsDef
== NULL
) {
751 xmlNsPtr prev
= node
->nsDef
;
753 if (((prev
->prefix
== NULL
) && (cur
->prefix
== NULL
)) ||
754 (xmlStrEqual(prev
->prefix
, cur
->prefix
))) {
758 while (prev
->next
!= NULL
) {
760 if (((prev
->prefix
== NULL
) && (cur
->prefix
== NULL
)) ||
761 (xmlStrEqual(prev
->prefix
, cur
->prefix
))) {
774 * @node: a node in the document
775 * @ns: a namespace pointer
777 * Associate a namespace to a node, a posteriori.
780 xmlSetNs(xmlNodePtr node
, xmlNsPtr ns
) {
783 xmlGenericError(xmlGenericErrorContext
,
784 "xmlSetNs: node == NULL\n");
793 * @cur: the namespace pointer
795 * Free up the structures associated to a namespace
798 xmlFreeNs(xmlNsPtr cur
) {
801 xmlGenericError(xmlGenericErrorContext
,
802 "xmlFreeNs : ns == NULL\n");
806 if (cur
->href
!= NULL
) xmlFree((char *) cur
->href
);
807 if (cur
->prefix
!= NULL
) xmlFree((char *) cur
->prefix
);
813 * @cur: the first namespace pointer
815 * Free up all the structures associated to the chained namespaces.
818 xmlFreeNsList(xmlNsPtr cur
) {
822 xmlGenericError(xmlGenericErrorContext
,
823 "xmlFreeNsList : ns == NULL\n");
827 while (cur
!= NULL
) {
836 * @doc: the document pointer
837 * @name: the DTD name
838 * @ExternalID: the external ID
839 * @SystemID: the system ID
841 * Creation of a new DTD for the external subset. To create an
842 * internal subset, use xmlCreateIntSubset().
844 * Returns a pointer to the new DTD structure
847 xmlNewDtd(xmlDocPtr doc
, const xmlChar
*name
,
848 const xmlChar
*ExternalID
, const xmlChar
*SystemID
) {
851 if ((doc
!= NULL
) && (doc
->extSubset
!= NULL
)) {
853 xmlGenericError(xmlGenericErrorContext
,
854 "xmlNewDtd(%s): document %s already have a DTD %s\n",
855 /* !!! */ (char *) name
, doc
->name
,
856 /* !!! */ (char *)doc
->extSubset
->name
);
862 * Allocate a new DTD and fill the fields.
864 cur
= (xmlDtdPtr
) xmlMalloc(sizeof(xmlDtd
));
866 xmlTreeErrMemory("building DTD");
869 memset(cur
, 0 , sizeof(xmlDtd
));
870 cur
->type
= XML_DTD_NODE
;
873 cur
->name
= xmlStrdup(name
);
874 if (ExternalID
!= NULL
)
875 cur
->ExternalID
= xmlStrdup(ExternalID
);
876 if (SystemID
!= NULL
)
877 cur
->SystemID
= xmlStrdup(SystemID
);
879 doc
->extSubset
= cur
;
882 if ((__xmlRegisterCallbacks
) && (xmlRegisterNodeDefaultValue
))
883 xmlRegisterNodeDefaultValue((xmlNodePtr
)cur
);
889 * @doc: the document pointer
891 * Get the internal subset of a document
892 * Returns a pointer to the DTD structure or NULL if not found
896 xmlGetIntSubset(xmlDocPtr doc
) {
902 while (cur
!= NULL
) {
903 if (cur
->type
== XML_DTD_NODE
)
904 return((xmlDtdPtr
) cur
);
907 return((xmlDtdPtr
) doc
->intSubset
);
911 * xmlCreateIntSubset:
912 * @doc: the document pointer
913 * @name: the DTD name
914 * @ExternalID: the external (PUBLIC) ID
915 * @SystemID: the system ID
917 * Create the internal subset of a document
918 * Returns a pointer to the new DTD structure
921 xmlCreateIntSubset(xmlDocPtr doc
, const xmlChar
*name
,
922 const xmlChar
*ExternalID
, const xmlChar
*SystemID
) {
925 if ((doc
!= NULL
) && (xmlGetIntSubset(doc
) != NULL
)) {
927 xmlGenericError(xmlGenericErrorContext
,
929 "xmlCreateIntSubset(): document %s already have an internal subset\n",
936 * Allocate a new DTD and fill the fields.
938 cur
= (xmlDtdPtr
) xmlMalloc(sizeof(xmlDtd
));
940 xmlTreeErrMemory("building internal subset");
943 memset(cur
, 0, sizeof(xmlDtd
));
944 cur
->type
= XML_DTD_NODE
;
947 cur
->name
= xmlStrdup(name
);
948 if (cur
->name
== NULL
) {
949 xmlTreeErrMemory("building internal subset");
954 if (ExternalID
!= NULL
) {
955 cur
->ExternalID
= xmlStrdup(ExternalID
);
956 if (cur
->ExternalID
== NULL
) {
957 xmlTreeErrMemory("building internal subset");
958 if (cur
->name
!= NULL
)
959 xmlFree((char *)cur
->name
);
964 if (SystemID
!= NULL
) {
965 cur
->SystemID
= xmlStrdup(SystemID
);
966 if (cur
->SystemID
== NULL
) {
967 xmlTreeErrMemory("building internal subset");
968 if (cur
->name
!= NULL
)
969 xmlFree((char *)cur
->name
);
970 if (cur
->ExternalID
!= NULL
)
971 xmlFree((char *)cur
->ExternalID
);
977 doc
->intSubset
= cur
;
980 if (doc
->children
== NULL
) {
981 doc
->children
= (xmlNodePtr
) cur
;
982 doc
->last
= (xmlNodePtr
) cur
;
984 if (doc
->type
== XML_HTML_DOCUMENT_NODE
) {
987 prev
= doc
->children
;
988 prev
->prev
= (xmlNodePtr
) cur
;
990 doc
->children
= (xmlNodePtr
) cur
;
994 next
= doc
->children
;
995 while ((next
!= NULL
) && (next
->type
!= XML_ELEMENT_NODE
))
998 cur
->prev
= doc
->last
;
999 cur
->prev
->next
= (xmlNodePtr
) cur
;
1001 doc
->last
= (xmlNodePtr
) cur
;
1004 cur
->prev
= next
->prev
;
1005 if (cur
->prev
== NULL
)
1006 doc
->children
= (xmlNodePtr
) cur
;
1008 cur
->prev
->next
= (xmlNodePtr
) cur
;
1009 next
->prev
= (xmlNodePtr
) cur
;
1015 if ((__xmlRegisterCallbacks
) && (xmlRegisterNodeDefaultValue
))
1016 xmlRegisterNodeDefaultValue((xmlNodePtr
)cur
);
1024 * Free a string if it is not owned by the "dict" dictionnary in the
1027 #define DICT_FREE(str) \
1028 if ((str) && ((!dict) || \
1029 (xmlDictOwns(dict, (const xmlChar *)(str)) == 0))) \
1030 xmlFree((char *)(str));
1037 * Copy a string using a "dict" dictionnary in the current scope,
1040 #define DICT_COPY(str, cpy) \
1043 if (xmlDictOwns(dict, (const xmlChar *)(str))) \
1044 cpy = (xmlChar *) (str); \
1046 cpy = (xmlChar *) xmlDictLookup((dict), (const xmlChar *)(str), -1); \
1048 cpy = xmlStrdup((const xmlChar *)(str)); }
1054 * Copy a string using a "dict" dictionnary in the current scope,
1057 #define DICT_CONST_COPY(str, cpy) \
1060 if (xmlDictOwns(dict, (const xmlChar *)(str))) \
1061 cpy = (const xmlChar *) (str); \
1063 cpy = xmlDictLookup((dict), (const xmlChar *)(str), -1); \
1065 cpy = (const xmlChar *) xmlStrdup((const xmlChar *)(str)); }
1070 * @cur: the DTD structure to free up
1072 * Free a DTD structure.
1075 xmlFreeDtd(xmlDtdPtr cur
) {
1076 xmlDictPtr dict
= NULL
;
1081 if (cur
->doc
!= NULL
) dict
= cur
->doc
->dict
;
1083 if ((__xmlRegisterCallbacks
) && (xmlDeregisterNodeDefaultValue
))
1084 xmlDeregisterNodeDefaultValue((xmlNodePtr
)cur
);
1086 if (cur
->children
!= NULL
) {
1087 xmlNodePtr next
, c
= cur
->children
;
1090 * Cleanup all nodes which are not part of the specific lists
1091 * of notations, elements, attributes and entities.
1095 if ((c
->type
!= XML_NOTATION_NODE
) &&
1096 (c
->type
!= XML_ELEMENT_DECL
) &&
1097 (c
->type
!= XML_ATTRIBUTE_DECL
) &&
1098 (c
->type
!= XML_ENTITY_DECL
)) {
1105 DICT_FREE(cur
->name
)
1106 DICT_FREE(cur
->SystemID
)
1107 DICT_FREE(cur
->ExternalID
)
1109 if (cur
->notations
!= NULL
)
1110 xmlFreeNotationTable((xmlNotationTablePtr
) cur
->notations
);
1112 if (cur
->elements
!= NULL
)
1113 xmlFreeElementTable((xmlElementTablePtr
) cur
->elements
);
1114 if (cur
->attributes
!= NULL
)
1115 xmlFreeAttributeTable((xmlAttributeTablePtr
) cur
->attributes
);
1116 if (cur
->entities
!= NULL
)
1117 xmlFreeEntitiesTable((xmlEntitiesTablePtr
) cur
->entities
);
1118 if (cur
->pentities
!= NULL
)
1119 xmlFreeEntitiesTable((xmlEntitiesTablePtr
) cur
->pentities
);
1126 * @version: xmlChar string giving the version of XML "1.0"
1128 * Creates a new XML document
1130 * Returns a new document
1133 xmlNewDoc(const xmlChar
*version
) {
1136 if (version
== NULL
)
1137 version
= (const xmlChar
*) "1.0";
1140 * Allocate a new document and fill the fields.
1142 cur
= (xmlDocPtr
) xmlMalloc(sizeof(xmlDoc
));
1144 xmlTreeErrMemory("building doc");
1147 memset(cur
, 0, sizeof(xmlDoc
));
1148 cur
->type
= XML_DOCUMENT_NODE
;
1150 cur
->version
= xmlStrdup(version
);
1151 if (cur
->version
== NULL
) {
1152 xmlTreeErrMemory("building doc");
1156 cur
->standalone
= -1;
1157 cur
->compression
= -1; /* not initialized */
1159 cur
->parseFlags
= 0;
1160 cur
->properties
= XML_DOC_USERBUILT
;
1162 * The in memory encoding is always UTF8
1163 * This field will never change and would
1164 * be obsolete if not for binary compatibility.
1166 cur
->charset
= XML_CHAR_ENCODING_UTF8
;
1168 if ((__xmlRegisterCallbacks
) && (xmlRegisterNodeDefaultValue
))
1169 xmlRegisterNodeDefaultValue((xmlNodePtr
)cur
);
1175 * @cur: pointer to the document
1177 * Free up all the structures used by a document, tree included.
1180 xmlFreeDoc(xmlDocPtr cur
) {
1181 xmlDtdPtr extSubset
, intSubset
;
1182 xmlDictPtr dict
= NULL
;
1186 xmlGenericError(xmlGenericErrorContext
,
1187 "xmlFreeDoc : document == NULL\n");
1191 #ifdef LIBXML_DEBUG_RUNTIME
1192 #ifdef LIBXML_DEBUG_ENABLED
1193 xmlDebugCheckDocument(stderr
, cur
);
1197 if (cur
!= NULL
) dict
= cur
->dict
;
1199 if ((__xmlRegisterCallbacks
) && (xmlDeregisterNodeDefaultValue
))
1200 xmlDeregisterNodeDefaultValue((xmlNodePtr
)cur
);
1203 * Do this before freeing the children list to avoid ID lookups
1205 if (cur
->ids
!= NULL
) xmlFreeIDTable((xmlIDTablePtr
) cur
->ids
);
1207 if (cur
->refs
!= NULL
) xmlFreeRefTable((xmlRefTablePtr
) cur
->refs
);
1209 extSubset
= cur
->extSubset
;
1210 intSubset
= cur
->intSubset
;
1211 if (intSubset
== extSubset
)
1213 if (extSubset
!= NULL
) {
1214 xmlUnlinkNode((xmlNodePtr
) cur
->extSubset
);
1215 cur
->extSubset
= NULL
;
1216 xmlFreeDtd(extSubset
);
1218 if (intSubset
!= NULL
) {
1219 xmlUnlinkNode((xmlNodePtr
) cur
->intSubset
);
1220 cur
->intSubset
= NULL
;
1221 xmlFreeDtd(intSubset
);
1224 if (cur
->children
!= NULL
) xmlFreeNodeList(cur
->children
);
1225 if (cur
->oldNs
!= NULL
) xmlFreeNsList(cur
->oldNs
);
1227 DICT_FREE(cur
->version
)
1228 DICT_FREE(cur
->name
)
1229 DICT_FREE(cur
->encoding
)
1232 if (dict
) xmlDictFree(dict
);
1236 * xmlStringLenGetNodeList:
1237 * @doc: the document
1238 * @value: the value of the text
1239 * @len: the length of the string value
1241 * Parse the value string and build the node list associated. Should
1242 * produce a flat tree with only TEXTs and ENTITY_REFs.
1243 * Returns a pointer to the first child
1246 xmlStringLenGetNodeList(xmlDocPtr doc
, const xmlChar
*value
, int len
) {
1247 xmlNodePtr ret
= NULL
, last
= NULL
;
1250 const xmlChar
*cur
= value
, *end
= cur
+ len
;
1254 if (value
== NULL
) return(NULL
);
1257 while ((cur
< end
) && (*cur
!= 0)) {
1258 if (cur
[0] == '&') {
1263 * Save the current text.
1266 if ((last
!= NULL
) && (last
->type
== XML_TEXT_NODE
)) {
1267 xmlNodeAddContentLen(last
, q
, cur
- q
);
1269 node
= xmlNewDocTextLen(doc
, q
, cur
- q
);
1270 if (node
== NULL
) return(ret
);
1281 if ((cur
+ 2 < end
) && (cur
[1] == '#') && (cur
[2] == 'x')) {
1287 while (tmp
!= ';') { /* Non input consuming loop */
1288 if ((tmp
>= '0') && (tmp
<= '9'))
1289 charval
= charval
* 16 + (tmp
- '0');
1290 else if ((tmp
>= 'a') && (tmp
<= 'f'))
1291 charval
= charval
* 16 + (tmp
- 'a') + 10;
1292 else if ((tmp
>= 'A') && (tmp
<= 'F'))
1293 charval
= charval
* 16 + (tmp
- 'A') + 10;
1295 xmlTreeErr(XML_TREE_INVALID_HEX
, (xmlNodePtr
) doc
,
1309 } else if ((cur
+ 1 < end
) && (cur
[1] == '#')) {
1315 while (tmp
!= ';') { /* Non input consuming loops */
1316 if ((tmp
>= '0') && (tmp
<= '9'))
1317 charval
= charval
* 10 + (tmp
- '0');
1319 xmlTreeErr(XML_TREE_INVALID_DEC
, (xmlNodePtr
) doc
,
1335 * Read the entity string
1339 while ((cur
< end
) && (*cur
!= 0) && (*cur
!= ';')) cur
++;
1340 if ((cur
>= end
) || (*cur
== 0)) {
1341 xmlTreeErr(XML_TREE_UNTERMINATED_ENTITY
, (xmlNodePtr
) doc
,
1347 * Predefined entities don't generate nodes
1349 val
= xmlStrndup(q
, cur
- q
);
1350 ent
= xmlGetDocEntity(doc
, val
);
1351 if ((ent
!= NULL
) &&
1352 (ent
->etype
== XML_INTERNAL_PREDEFINED_ENTITY
)) {
1354 node
= xmlNewDocText(doc
, ent
->content
);
1356 } else if (last
->type
!= XML_TEXT_NODE
) {
1357 node
= xmlNewDocText(doc
, ent
->content
);
1358 last
= xmlAddNextSibling(last
, node
);
1360 xmlNodeAddContent(last
, ent
->content
);
1364 * Create a new REFERENCE_REF node
1366 node
= xmlNewReference(doc
, val
);
1368 if (val
!= NULL
) xmlFree(val
);
1371 else if ((ent
!= NULL
) && (ent
->children
== NULL
)) {
1374 ent
->children
= xmlStringGetNodeList(doc
,
1375 (const xmlChar
*)node
->content
);
1377 temp
= ent
->children
;
1379 temp
->parent
= (xmlNodePtr
)ent
;
1387 last
= xmlAddNextSibling(last
, node
);
1399 l
= xmlCopyCharMultiByte(buf
, charval
);
1401 node
= xmlNewDocText(doc
, buf
);
1406 last
= xmlAddNextSibling(last
, node
);
1414 if ((cur
!= q
) || (ret
== NULL
)) {
1416 * Handle the last piece of text.
1418 if ((last
!= NULL
) && (last
->type
== XML_TEXT_NODE
)) {
1419 xmlNodeAddContentLen(last
, q
, cur
- q
);
1421 node
= xmlNewDocTextLen(doc
, q
, cur
- q
);
1422 if (node
== NULL
) return(ret
);
1426 xmlAddNextSibling(last
, node
);
1434 * xmlStringGetNodeList:
1435 * @doc: the document
1436 * @value: the value of the attribute
1438 * Parse the value string and build the node list associated. Should
1439 * produce a flat tree with only TEXTs and ENTITY_REFs.
1440 * Returns a pointer to the first child
1443 xmlStringGetNodeList(xmlDocPtr doc
, const xmlChar
*value
) {
1444 xmlNodePtr ret
= NULL
, last
= NULL
;
1447 const xmlChar
*cur
= value
;
1451 if (value
== NULL
) return(NULL
);
1455 if (cur
[0] == '&') {
1460 * Save the current text.
1463 if ((last
!= NULL
) && (last
->type
== XML_TEXT_NODE
)) {
1464 xmlNodeAddContentLen(last
, q
, cur
- q
);
1466 node
= xmlNewDocTextLen(doc
, q
, cur
- q
);
1467 if (node
== NULL
) return(ret
);
1478 if ((cur
[1] == '#') && (cur
[2] == 'x')) {
1481 while (tmp
!= ';') { /* Non input consuming loop */
1482 if ((tmp
>= '0') && (tmp
<= '9'))
1483 charval
= charval
* 16 + (tmp
- '0');
1484 else if ((tmp
>= 'a') && (tmp
<= 'f'))
1485 charval
= charval
* 16 + (tmp
- 'a') + 10;
1486 else if ((tmp
>= 'A') && (tmp
<= 'F'))
1487 charval
= charval
* 16 + (tmp
- 'A') + 10;
1489 xmlTreeErr(XML_TREE_INVALID_HEX
, (xmlNodePtr
) doc
,
1500 } else if (cur
[1] == '#') {
1503 while (tmp
!= ';') { /* Non input consuming loops */
1504 if ((tmp
>= '0') && (tmp
<= '9'))
1505 charval
= charval
* 10 + (tmp
- '0');
1507 xmlTreeErr(XML_TREE_INVALID_DEC
, (xmlNodePtr
) doc
,
1520 * Read the entity string
1524 while ((*cur
!= 0) && (*cur
!= ';')) cur
++;
1526 xmlTreeErr(XML_TREE_UNTERMINATED_ENTITY
,
1527 (xmlNodePtr
) doc
, (const char *) q
);
1532 * Predefined entities don't generate nodes
1534 val
= xmlStrndup(q
, cur
- q
);
1535 ent
= xmlGetDocEntity(doc
, val
);
1536 if ((ent
!= NULL
) &&
1537 (ent
->etype
== XML_INTERNAL_PREDEFINED_ENTITY
)) {
1539 node
= xmlNewDocText(doc
, ent
->content
);
1541 } else if (last
->type
!= XML_TEXT_NODE
) {
1542 node
= xmlNewDocText(doc
, ent
->content
);
1543 last
= xmlAddNextSibling(last
, node
);
1545 xmlNodeAddContent(last
, ent
->content
);
1549 * Create a new REFERENCE_REF node
1551 node
= xmlNewReference(doc
, val
);
1553 if (val
!= NULL
) xmlFree(val
);
1556 else if ((ent
!= NULL
) && (ent
->children
== NULL
)) {
1559 ent
->children
= xmlStringGetNodeList(doc
,
1560 (const xmlChar
*)node
->content
);
1562 temp
= ent
->children
;
1564 temp
->parent
= (xmlNodePtr
)ent
;
1571 last
= xmlAddNextSibling(last
, node
);
1583 len
= xmlCopyCharMultiByte(buf
, charval
);
1585 node
= xmlNewDocText(doc
, buf
);
1590 last
= xmlAddNextSibling(last
, node
);
1597 if ((cur
!= q
) || (ret
== NULL
)) {
1599 * Handle the last piece of text.
1601 if ((last
!= NULL
) && (last
->type
== XML_TEXT_NODE
)) {
1602 xmlNodeAddContentLen(last
, q
, cur
- q
);
1604 node
= xmlNewDocTextLen(doc
, q
, cur
- q
);
1605 if (node
== NULL
) return(ret
);
1609 last
= xmlAddNextSibling(last
, node
);
1617 * xmlNodeListGetString:
1618 * @doc: the document
1619 * @list: a Node list
1620 * @inLine: should we replace entity contents or show their external form
1622 * Build the string equivalent to the text contained in the Node list
1623 * made of TEXTs and ENTITY_REFs
1625 * Returns a pointer to the string copy, the caller must free it with xmlFree().
1628 xmlNodeListGetString(xmlDocPtr doc
, xmlNodePtr list
, int inLine
)
1630 xmlNodePtr node
= list
;
1631 xmlChar
*ret
= NULL
;
1637 while (node
!= NULL
) {
1638 if ((node
->type
== XML_TEXT_NODE
) ||
1639 (node
->type
== XML_CDATA_SECTION_NODE
)) {
1641 ret
= xmlStrcat(ret
, node
->content
);
1645 buffer
= xmlEncodeEntitiesReentrant(doc
, node
->content
);
1646 if (buffer
!= NULL
) {
1647 ret
= xmlStrcat(ret
, buffer
);
1651 } else if (node
->type
== XML_ENTITY_REF_NODE
) {
1653 ent
= xmlGetDocEntity(doc
, node
->name
);
1657 /* an entity content can be any "well balanced chunk",
1658 * i.e. the result of the content [43] production:
1659 * http://www.w3.org/TR/REC-xml#NT-content.
1660 * So it can contain text, CDATA section or nested
1661 * entity reference nodes (among others).
1662 * -> we recursive call xmlNodeListGetString()
1663 * which handles these types */
1664 buffer
= xmlNodeListGetString(doc
, ent
->children
, 1);
1665 if (buffer
!= NULL
) {
1666 ret
= xmlStrcat(ret
, buffer
);
1670 ret
= xmlStrcat(ret
, node
->content
);
1677 ret
= xmlStrncat(ret
, buf
, 1);
1678 ret
= xmlStrcat(ret
, node
->name
);
1681 ret
= xmlStrncat(ret
, buf
, 1);
1686 xmlGenericError(xmlGenericErrorContext
,
1687 "xmlGetNodeListString : invalid node type %d\n",
1696 #ifdef LIBXML_TREE_ENABLED
1698 * xmlNodeListGetRawString:
1699 * @doc: the document
1700 * @list: a Node list
1701 * @inLine: should we replace entity contents or show their external form
1703 * Builds the string equivalent to the text contained in the Node list
1704 * made of TEXTs and ENTITY_REFs, contrary to xmlNodeListGetString()
1705 * this function doesn't do any character encoding handling.
1707 * Returns a pointer to the string copy, the caller must free it with xmlFree().
1710 xmlNodeListGetRawString(xmlDocPtr doc
, xmlNodePtr list
, int inLine
)
1712 xmlNodePtr node
= list
;
1713 xmlChar
*ret
= NULL
;
1719 while (node
!= NULL
) {
1720 if ((node
->type
== XML_TEXT_NODE
) ||
1721 (node
->type
== XML_CDATA_SECTION_NODE
)) {
1723 ret
= xmlStrcat(ret
, node
->content
);
1727 buffer
= xmlEncodeSpecialChars(doc
, node
->content
);
1728 if (buffer
!= NULL
) {
1729 ret
= xmlStrcat(ret
, buffer
);
1733 } else if (node
->type
== XML_ENTITY_REF_NODE
) {
1735 ent
= xmlGetDocEntity(doc
, node
->name
);
1739 /* an entity content can be any "well balanced chunk",
1740 * i.e. the result of the content [43] production:
1741 * http://www.w3.org/TR/REC-xml#NT-content.
1742 * So it can contain text, CDATA section or nested
1743 * entity reference nodes (among others).
1744 * -> we recursive call xmlNodeListGetRawString()
1745 * which handles these types */
1747 xmlNodeListGetRawString(doc
, ent
->children
, 1);
1748 if (buffer
!= NULL
) {
1749 ret
= xmlStrcat(ret
, buffer
);
1753 ret
= xmlStrcat(ret
, node
->content
);
1760 ret
= xmlStrncat(ret
, buf
, 1);
1761 ret
= xmlStrcat(ret
, node
->name
);
1764 ret
= xmlStrncat(ret
, buf
, 1);
1769 xmlGenericError(xmlGenericErrorContext
,
1770 "xmlGetNodeListString : invalid node type %d\n",
1778 #endif /* LIBXML_TREE_ENABLED */
1781 xmlNewPropInternal(xmlNodePtr node
, xmlNsPtr ns
,
1782 const xmlChar
* name
, const xmlChar
* value
,
1786 xmlDocPtr doc
= NULL
;
1788 if ((node
!= NULL
) && (node
->type
!= XML_ELEMENT_NODE
)) {
1789 if ((eatname
== 1) &&
1790 ((node
->doc
== NULL
) ||
1791 (!(xmlDictOwns(node
->doc
->dict
, name
)))))
1792 xmlFree((xmlChar
*) name
);
1797 * Allocate a new property and fill the fields.
1799 cur
= (xmlAttrPtr
) xmlMalloc(sizeof(xmlAttr
));
1801 if ((eatname
== 1) &&
1802 ((node
== NULL
) || (node
->doc
== NULL
) ||
1803 (!(xmlDictOwns(node
->doc
->dict
, name
)))))
1804 xmlFree((xmlChar
*) name
);
1805 xmlTreeErrMemory("building attribute");
1808 memset(cur
, 0, sizeof(xmlAttr
));
1809 cur
->type
= XML_ATTRIBUTE_NODE
;
1819 if ((doc
!= NULL
) && (doc
->dict
!= NULL
))
1820 cur
->name
= (xmlChar
*) xmlDictLookup(doc
->dict
, name
, -1);
1822 cur
->name
= xmlStrdup(name
);
1826 if (value
!= NULL
) {
1829 if(!xmlCheckUTF8(value
)) {
1830 xmlTreeErr(XML_TREE_NOT_UTF8
, (xmlNodePtr
) doc
,
1833 doc
->encoding
= xmlStrdup(BAD_CAST
"ISO-8859-1");
1835 cur
->children
= xmlNewDocText(doc
, value
);
1837 tmp
= cur
->children
;
1838 while (tmp
!= NULL
) {
1839 tmp
->parent
= (xmlNodePtr
) cur
;
1840 if (tmp
->next
== NULL
)
1847 * Add it at the end to preserve parsing order ...
1850 if (node
->properties
== NULL
) {
1851 node
->properties
= cur
;
1853 xmlAttrPtr prev
= node
->properties
;
1855 while (prev
->next
!= NULL
)
1862 if ((value
!= NULL
) && (node
!= NULL
) &&
1863 (xmlIsID(node
->doc
, node
, cur
) == 1))
1864 xmlAddID(NULL
, node
->doc
, value
, cur
);
1866 if ((__xmlRegisterCallbacks
) && (xmlRegisterNodeDefaultValue
))
1867 xmlRegisterNodeDefaultValue((xmlNodePtr
) cur
);
1871 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_HTML_ENABLED) || \
1872 defined(LIBXML_SCHEMAS_ENABLED)
1875 * @node: the holding node
1876 * @name: the name of the attribute
1877 * @value: the value of the attribute
1879 * Create a new property carried by a node.
1880 * Returns a pointer to the attribute
1883 xmlNewProp(xmlNodePtr node
, const xmlChar
*name
, const xmlChar
*value
) {
1887 xmlGenericError(xmlGenericErrorContext
,
1888 "xmlNewProp : name == NULL\n");
1893 return xmlNewPropInternal(node
, NULL
, name
, value
, 0);
1895 #endif /* LIBXML_TREE_ENABLED */
1899 * @node: the holding node
1900 * @ns: the namespace
1901 * @name: the name of the attribute
1902 * @value: the value of the attribute
1904 * Create a new property tagged with a namespace and carried by a node.
1905 * Returns a pointer to the attribute
1908 xmlNewNsProp(xmlNodePtr node
, xmlNsPtr ns
, const xmlChar
*name
,
1909 const xmlChar
*value
) {
1913 xmlGenericError(xmlGenericErrorContext
,
1914 "xmlNewNsProp : name == NULL\n");
1919 return xmlNewPropInternal(node
, ns
, name
, value
, 0);
1923 * xmlNewNsPropEatName:
1924 * @node: the holding node
1925 * @ns: the namespace
1926 * @name: the name of the attribute
1927 * @value: the value of the attribute
1929 * Create a new property tagged with a namespace and carried by a node.
1930 * Returns a pointer to the attribute
1933 xmlNewNsPropEatName(xmlNodePtr node
, xmlNsPtr ns
, xmlChar
*name
,
1934 const xmlChar
*value
) {
1938 xmlGenericError(xmlGenericErrorContext
,
1939 "xmlNewNsPropEatName : name == NULL\n");
1944 return xmlNewPropInternal(node
, ns
, name
, value
, 1);
1949 * @doc: the document
1950 * @name: the name of the attribute
1951 * @value: the value of the attribute
1953 * Create a new property carried by a document.
1954 * Returns a pointer to the attribute
1957 xmlNewDocProp(xmlDocPtr doc
, const xmlChar
*name
, const xmlChar
*value
) {
1962 xmlGenericError(xmlGenericErrorContext
,
1963 "xmlNewDocProp : name == NULL\n");
1969 * Allocate a new property and fill the fields.
1971 cur
= (xmlAttrPtr
) xmlMalloc(sizeof(xmlAttr
));
1973 xmlTreeErrMemory("building attribute");
1976 memset(cur
, 0, sizeof(xmlAttr
));
1977 cur
->type
= XML_ATTRIBUTE_NODE
;
1979 if ((doc
!= NULL
) && (doc
->dict
!= NULL
))
1980 cur
->name
= xmlDictLookup(doc
->dict
, name
, -1);
1982 cur
->name
= xmlStrdup(name
);
1984 if (value
!= NULL
) {
1987 cur
->children
= xmlStringGetNodeList(doc
, value
);
1990 tmp
= cur
->children
;
1991 while (tmp
!= NULL
) {
1992 tmp
->parent
= (xmlNodePtr
) cur
;
1993 if (tmp
->next
== NULL
)
1999 if ((__xmlRegisterCallbacks
) && (xmlRegisterNodeDefaultValue
))
2000 xmlRegisterNodeDefaultValue((xmlNodePtr
)cur
);
2006 * @cur: the first property in the list
2008 * Free a property and all its siblings, all the children are freed too.
2011 xmlFreePropList(xmlAttrPtr cur
) {
2013 if (cur
== NULL
) return;
2014 while (cur
!= NULL
) {
2023 * @cur: an attribute
2025 * Free one attribute, all the content is freed too
2028 xmlFreeProp(xmlAttrPtr cur
) {
2029 xmlDictPtr dict
= NULL
;
2030 if (cur
== NULL
) return;
2032 if (cur
->doc
!= NULL
) dict
= cur
->doc
->dict
;
2034 if ((__xmlRegisterCallbacks
) && (xmlDeregisterNodeDefaultValue
))
2035 xmlDeregisterNodeDefaultValue((xmlNodePtr
)cur
);
2037 /* Check for ID removal -> leading to invalid references ! */
2038 if ((cur
->doc
!= NULL
) && (cur
->atype
== XML_ATTRIBUTE_ID
)) {
2039 xmlRemoveID(cur
->doc
, cur
);
2041 if (cur
->children
!= NULL
) xmlFreeNodeList(cur
->children
);
2042 DICT_FREE(cur
->name
)
2048 * @cur: an attribute
2050 * Unlink and free one attribute, all the content is freed too
2051 * Note this doesn't work for namespace definition attributes
2053 * Returns 0 if success and -1 in case of error.
2056 xmlRemoveProp(xmlAttrPtr cur
) {
2060 xmlGenericError(xmlGenericErrorContext
,
2061 "xmlRemoveProp : cur == NULL\n");
2065 if (cur
->parent
== NULL
) {
2067 xmlGenericError(xmlGenericErrorContext
,
2068 "xmlRemoveProp : cur->parent == NULL\n");
2072 tmp
= cur
->parent
->properties
;
2074 cur
->parent
->properties
= cur
->next
;
2075 if (cur
->next
!= NULL
)
2076 cur
->next
->prev
= NULL
;
2080 while (tmp
!= NULL
) {
2081 if (tmp
->next
== cur
) {
2082 tmp
->next
= cur
->next
;
2083 if (tmp
->next
!= NULL
)
2084 tmp
->next
->prev
= tmp
;
2091 xmlGenericError(xmlGenericErrorContext
,
2092 "xmlRemoveProp : attribute not owned by its node\n");
2099 * @doc: the target document
2100 * @name: the processing instruction name
2101 * @content: the PI content
2103 * Creation of a processing instruction element.
2104 * Returns a pointer to the new node object.
2107 xmlNewDocPI(xmlDocPtr doc
, const xmlChar
*name
, const xmlChar
*content
) {
2112 xmlGenericError(xmlGenericErrorContext
,
2113 "xmlNewPI : name == NULL\n");
2119 * Allocate a new node and fill the fields.
2121 cur
= (xmlNodePtr
) xmlMalloc(sizeof(xmlNode
));
2123 xmlTreeErrMemory("building PI");
2126 memset(cur
, 0, sizeof(xmlNode
));
2127 cur
->type
= XML_PI_NODE
;
2129 if ((doc
!= NULL
) && (doc
->dict
!= NULL
))
2130 cur
->name
= xmlDictLookup(doc
->dict
, name
, -1);
2132 cur
->name
= xmlStrdup(name
);
2133 if (content
!= NULL
) {
2134 cur
->content
= xmlStrdup(content
);
2138 if ((__xmlRegisterCallbacks
) && (xmlRegisterNodeDefaultValue
))
2139 xmlRegisterNodeDefaultValue((xmlNodePtr
)cur
);
2145 * @name: the processing instruction name
2146 * @content: the PI content
2148 * Creation of a processing instruction element.
2149 * Use xmlDocNewPI preferably to get string interning
2151 * Returns a pointer to the new node object.
2154 xmlNewPI(const xmlChar
*name
, const xmlChar
*content
) {
2155 return(xmlNewDocPI(NULL
, name
, content
));
2160 * @ns: namespace if any
2161 * @name: the node name
2163 * Creation of a new node element. @ns is optional (NULL).
2165 * Returns a pointer to the new node object. Uses xmlStrdup() to make
2169 xmlNewNode(xmlNsPtr ns
, const xmlChar
*name
) {
2174 xmlGenericError(xmlGenericErrorContext
,
2175 "xmlNewNode : name == NULL\n");
2181 * Allocate a new node and fill the fields.
2183 cur
= (xmlNodePtr
) xmlMalloc(sizeof(xmlNode
));
2185 xmlTreeErrMemory("building node");
2188 memset(cur
, 0, sizeof(xmlNode
));
2189 cur
->type
= XML_ELEMENT_NODE
;
2191 cur
->name
= xmlStrdup(name
);
2194 if ((__xmlRegisterCallbacks
) && (xmlRegisterNodeDefaultValue
))
2195 xmlRegisterNodeDefaultValue(cur
);
2200 * xmlNewNodeEatName:
2201 * @ns: namespace if any
2202 * @name: the node name
2204 * Creation of a new node element. @ns is optional (NULL).
2206 * Returns a pointer to the new node object, with pointer @name as
2207 * new node's name. Use xmlNewNode() if a copy of @name string is
2208 * is needed as new node's name.
2211 xmlNewNodeEatName(xmlNsPtr ns
, xmlChar
*name
) {
2216 xmlGenericError(xmlGenericErrorContext
,
2217 "xmlNewNode : name == NULL\n");
2223 * Allocate a new node and fill the fields.
2225 cur
= (xmlNodePtr
) xmlMalloc(sizeof(xmlNode
));
2227 xmlTreeErrMemory("building node");
2228 /* we can't check here that name comes from the doc dictionnary */
2231 memset(cur
, 0, sizeof(xmlNode
));
2232 cur
->type
= XML_ELEMENT_NODE
;
2237 if ((__xmlRegisterCallbacks
) && (xmlRegisterNodeDefaultValue
))
2238 xmlRegisterNodeDefaultValue((xmlNodePtr
)cur
);
2244 * @doc: the document
2245 * @ns: namespace if any
2246 * @name: the node name
2247 * @content: the XML text content if any
2249 * Creation of a new node element within a document. @ns and @content
2250 * are optional (NULL).
2251 * NOTE: @content is supposed to be a piece of XML CDATA, so it allow entities
2252 * references, but XML special chars need to be escaped first by using
2253 * xmlEncodeEntitiesReentrant(). Use xmlNewDocRawNode() if you don't
2254 * need entities support.
2256 * Returns a pointer to the new node object.
2259 xmlNewDocNode(xmlDocPtr doc
, xmlNsPtr ns
,
2260 const xmlChar
*name
, const xmlChar
*content
) {
2263 if ((doc
!= NULL
) && (doc
->dict
!= NULL
))
2264 cur
= xmlNewNodeEatName(ns
, (xmlChar
*)
2265 xmlDictLookup(doc
->dict
, name
, -1));
2267 cur
= xmlNewNode(ns
, name
);
2270 if (content
!= NULL
) {
2271 cur
->children
= xmlStringGetNodeList(doc
, content
);
2272 UPDATE_LAST_CHILD_AND_PARENT(cur
)
2280 * xmlNewDocNodeEatName:
2281 * @doc: the document
2282 * @ns: namespace if any
2283 * @name: the node name
2284 * @content: the XML text content if any
2286 * Creation of a new node element within a document. @ns and @content
2287 * are optional (NULL).
2288 * NOTE: @content is supposed to be a piece of XML CDATA, so it allow entities
2289 * references, but XML special chars need to be escaped first by using
2290 * xmlEncodeEntitiesReentrant(). Use xmlNewDocRawNode() if you don't
2291 * need entities support.
2293 * Returns a pointer to the new node object.
2296 xmlNewDocNodeEatName(xmlDocPtr doc
, xmlNsPtr ns
,
2297 xmlChar
*name
, const xmlChar
*content
) {
2300 cur
= xmlNewNodeEatName(ns
, name
);
2303 if (content
!= NULL
) {
2304 cur
->children
= xmlStringGetNodeList(doc
, content
);
2305 UPDATE_LAST_CHILD_AND_PARENT(cur
)
2308 /* if name don't come from the doc dictionnary free it here */
2309 if ((name
!= NULL
) && (doc
!= NULL
) &&
2310 (!(xmlDictOwns(doc
->dict
, name
))))
2316 #ifdef LIBXML_TREE_ENABLED
2319 * @doc: the document
2320 * @ns: namespace if any
2321 * @name: the node name
2322 * @content: the text content if any
2324 * Creation of a new node element within a document. @ns and @content
2325 * are optional (NULL).
2327 * Returns a pointer to the new node object.
2330 xmlNewDocRawNode(xmlDocPtr doc
, xmlNsPtr ns
,
2331 const xmlChar
*name
, const xmlChar
*content
) {
2334 cur
= xmlNewDocNode(doc
, ns
, name
, NULL
);
2337 if (content
!= NULL
) {
2338 cur
->children
= xmlNewDocText(doc
, content
);
2339 UPDATE_LAST_CHILD_AND_PARENT(cur
)
2346 * xmlNewDocFragment:
2347 * @doc: the document owning the fragment
2349 * Creation of a new Fragment node.
2350 * Returns a pointer to the new node object.
2353 xmlNewDocFragment(xmlDocPtr doc
) {
2357 * Allocate a new DocumentFragment node and fill the fields.
2359 cur
= (xmlNodePtr
) xmlMalloc(sizeof(xmlNode
));
2361 xmlTreeErrMemory("building fragment");
2364 memset(cur
, 0, sizeof(xmlNode
));
2365 cur
->type
= XML_DOCUMENT_FRAG_NODE
;
2369 if ((__xmlRegisterCallbacks
) && (xmlRegisterNodeDefaultValue
))
2370 xmlRegisterNodeDefaultValue(cur
);
2373 #endif /* LIBXML_TREE_ENABLED */
2377 * @content: the text content
2379 * Creation of a new text node.
2380 * Returns a pointer to the new node object.
2383 xmlNewText(const xmlChar
*content
) {
2387 * Allocate a new node and fill the fields.
2389 cur
= (xmlNodePtr
) xmlMalloc(sizeof(xmlNode
));
2391 xmlTreeErrMemory("building text");
2394 memset(cur
, 0, sizeof(xmlNode
));
2395 cur
->type
= XML_TEXT_NODE
;
2397 cur
->name
= xmlStringText
;
2398 if (content
!= NULL
) {
2399 cur
->content
= xmlStrdup(content
);
2402 if ((__xmlRegisterCallbacks
) && (xmlRegisterNodeDefaultValue
))
2403 xmlRegisterNodeDefaultValue(cur
);
2407 #ifdef LIBXML_TREE_ENABLED
2410 * @parent: the parent node
2411 * @ns: a namespace if any
2412 * @name: the name of the child
2413 * @content: the text content of the child if any.
2415 * Creation of a new child element, added at the end of @parent children list.
2416 * @ns and @content parameters are optional (NULL). If @ns is NULL, the newly
2417 * created element inherits the namespace of @parent. If @content is non NULL,
2418 * a child TEXT node will be created containing the string @content.
2419 * NOTE: Use xmlNewChild() if @content will contain entities that need to be
2420 * preserved. Use this function, xmlNewTextChild(), if you need to ensure that
2421 * reserved XML chars that might appear in @content, such as the ampersand,
2422 * greater-than or less-than signs, are automatically replaced by their XML
2423 * escaped entity representations.
2425 * Returns a pointer to the new node object.
2428 xmlNewTextChild(xmlNodePtr parent
, xmlNsPtr ns
,
2429 const xmlChar
*name
, const xmlChar
*content
) {
2430 xmlNodePtr cur
, prev
;
2432 if (parent
== NULL
) {
2434 xmlGenericError(xmlGenericErrorContext
,
2435 "xmlNewTextChild : parent == NULL\n");
2442 xmlGenericError(xmlGenericErrorContext
,
2443 "xmlNewTextChild : name == NULL\n");
2449 * Allocate a new node
2451 if (parent
->type
== XML_ELEMENT_NODE
) {
2453 cur
= xmlNewDocRawNode(parent
->doc
, parent
->ns
, name
, content
);
2455 cur
= xmlNewDocRawNode(parent
->doc
, ns
, name
, content
);
2456 } else if ((parent
->type
== XML_DOCUMENT_NODE
) ||
2457 (parent
->type
== XML_HTML_DOCUMENT_NODE
)) {
2459 cur
= xmlNewDocRawNode((xmlDocPtr
) parent
, NULL
, name
, content
);
2461 cur
= xmlNewDocRawNode((xmlDocPtr
) parent
, ns
, name
, content
);
2462 } else if (parent
->type
== XML_DOCUMENT_FRAG_NODE
) {
2463 cur
= xmlNewDocRawNode( parent
->doc
, ns
, name
, content
);
2467 if (cur
== NULL
) return(NULL
);
2470 * add the new element at the end of the children list.
2472 cur
->type
= XML_ELEMENT_NODE
;
2473 cur
->parent
= parent
;
2474 cur
->doc
= parent
->doc
;
2475 if (parent
->children
== NULL
) {
2476 parent
->children
= cur
;
2479 prev
= parent
->last
;
2487 #endif /* LIBXML_TREE_ENABLED */
2491 * @doc: the document
2492 * @name: the char ref string, starting with # or "&# ... ;"
2494 * Creation of a new character reference node.
2495 * Returns a pointer to the new node object.
2498 xmlNewCharRef(xmlDocPtr doc
, const xmlChar
*name
) {
2505 * Allocate a new node and fill the fields.
2507 cur
= (xmlNodePtr
) xmlMalloc(sizeof(xmlNode
));
2509 xmlTreeErrMemory("building character reference");
2512 memset(cur
, 0, sizeof(xmlNode
));
2513 cur
->type
= XML_ENTITY_REF_NODE
;
2516 if (name
[0] == '&') {
2519 len
= xmlStrlen(name
);
2520 if (name
[len
- 1] == ';')
2521 cur
->name
= xmlStrndup(name
, len
- 1);
2523 cur
->name
= xmlStrndup(name
, len
);
2525 cur
->name
= xmlStrdup(name
);
2527 if ((__xmlRegisterCallbacks
) && (xmlRegisterNodeDefaultValue
))
2528 xmlRegisterNodeDefaultValue(cur
);
2534 * @doc: the document
2535 * @name: the reference name, or the reference string with & and ;
2537 * Creation of a new reference node.
2538 * Returns a pointer to the new node object.
2541 xmlNewReference(xmlDocPtr doc
, const xmlChar
*name
) {
2549 * Allocate a new node and fill the fields.
2551 cur
= (xmlNodePtr
) xmlMalloc(sizeof(xmlNode
));
2553 xmlTreeErrMemory("building reference");
2556 memset(cur
, 0, sizeof(xmlNode
));
2557 cur
->type
= XML_ENTITY_REF_NODE
;
2560 if (name
[0] == '&') {
2563 len
= xmlStrlen(name
);
2564 if (name
[len
- 1] == ';')
2565 cur
->name
= xmlStrndup(name
, len
- 1);
2567 cur
->name
= xmlStrndup(name
, len
);
2569 cur
->name
= xmlStrdup(name
);
2571 ent
= xmlGetDocEntity(doc
, cur
->name
);
2573 cur
->content
= ent
->content
;
2575 * The parent pointer in entity is a DTD pointer and thus is NOT
2576 * updated. Not sure if this is 100% correct.
2579 cur
->children
= (xmlNodePtr
) ent
;
2580 cur
->last
= (xmlNodePtr
) ent
;
2583 if ((__xmlRegisterCallbacks
) && (xmlRegisterNodeDefaultValue
))
2584 xmlRegisterNodeDefaultValue(cur
);
2590 * @doc: the document
2591 * @content: the text content
2593 * Creation of a new text node within a document.
2594 * Returns a pointer to the new node object.
2597 xmlNewDocText(xmlDocPtr doc
, const xmlChar
*content
) {
2600 cur
= xmlNewText(content
);
2601 if (cur
!= NULL
) cur
->doc
= doc
;
2607 * @content: the text content
2608 * @len: the text len.
2610 * Creation of a new text node with an extra parameter for the content's length
2611 * Returns a pointer to the new node object.
2614 xmlNewTextLen(const xmlChar
*content
, int len
) {
2618 * Allocate a new node and fill the fields.
2620 cur
= (xmlNodePtr
) xmlMalloc(sizeof(xmlNode
));
2622 xmlTreeErrMemory("building text");
2625 memset(cur
, 0, sizeof(xmlNode
));
2626 cur
->type
= XML_TEXT_NODE
;
2628 cur
->name
= xmlStringText
;
2629 if (content
!= NULL
) {
2630 cur
->content
= xmlStrndup(content
, len
);
2633 if ((__xmlRegisterCallbacks
) && (xmlRegisterNodeDefaultValue
))
2634 xmlRegisterNodeDefaultValue(cur
);
2640 * @doc: the document
2641 * @content: the text content
2642 * @len: the text len.
2644 * Creation of a new text node with an extra content length parameter. The
2645 * text node pertain to a given document.
2646 * Returns a pointer to the new node object.
2649 xmlNewDocTextLen(xmlDocPtr doc
, const xmlChar
*content
, int len
) {
2652 cur
= xmlNewTextLen(content
, len
);
2653 if (cur
!= NULL
) cur
->doc
= doc
;
2659 * @content: the comment content
2661 * Creation of a new node containing a comment.
2662 * Returns a pointer to the new node object.
2665 xmlNewComment(const xmlChar
*content
) {
2669 * Allocate a new node and fill the fields.
2671 cur
= (xmlNodePtr
) xmlMalloc(sizeof(xmlNode
));
2673 xmlTreeErrMemory("building comment");
2676 memset(cur
, 0, sizeof(xmlNode
));
2677 cur
->type
= XML_COMMENT_NODE
;
2679 cur
->name
= xmlStringComment
;
2680 if (content
!= NULL
) {
2681 cur
->content
= xmlStrdup(content
);
2684 if ((__xmlRegisterCallbacks
) && (xmlRegisterNodeDefaultValue
))
2685 xmlRegisterNodeDefaultValue(cur
);
2691 * @doc: the document
2692 * @content: the CDATA block content content
2693 * @len: the length of the block
2695 * Creation of a new node containing a CDATA block.
2696 * Returns a pointer to the new node object.
2699 xmlNewCDataBlock(xmlDocPtr doc
, const xmlChar
*content
, int len
) {
2703 * Allocate a new node and fill the fields.
2705 cur
= (xmlNodePtr
) xmlMalloc(sizeof(xmlNode
));
2707 xmlTreeErrMemory("building CDATA");
2710 memset(cur
, 0, sizeof(xmlNode
));
2711 cur
->type
= XML_CDATA_SECTION_NODE
;
2714 if (content
!= NULL
) {
2715 cur
->content
= xmlStrndup(content
, len
);
2718 if ((__xmlRegisterCallbacks
) && (xmlRegisterNodeDefaultValue
))
2719 xmlRegisterNodeDefaultValue(cur
);
2725 * @doc: the document
2726 * @content: the comment content
2728 * Creation of a new node containing a comment within a document.
2729 * Returns a pointer to the new node object.
2732 xmlNewDocComment(xmlDocPtr doc
, const xmlChar
*content
) {
2735 cur
= xmlNewComment(content
);
2736 if (cur
!= NULL
) cur
->doc
= doc
;
2742 * @tree: the top element
2743 * @doc: the document
2745 * update all nodes under the tree to point to the right document
2748 xmlSetTreeDoc(xmlNodePtr tree
, xmlDocPtr doc
) {
2753 if (tree
->doc
!= doc
) {
2754 if(tree
->type
== XML_ELEMENT_NODE
) {
2755 prop
= tree
->properties
;
2756 while (prop
!= NULL
) {
2758 xmlSetListDoc(prop
->children
, doc
);
2762 if (tree
->children
!= NULL
)
2763 xmlSetListDoc(tree
->children
, doc
);
2770 * @list: the first element
2771 * @doc: the document
2773 * update all nodes in the list to point to the right document
2776 xmlSetListDoc(xmlNodePtr list
, xmlDocPtr doc
) {
2782 while (cur
!= NULL
) {
2783 if (cur
->doc
!= doc
)
2784 xmlSetTreeDoc(cur
, doc
);
2789 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
2792 * @parent: the parent node
2793 * @ns: a namespace if any
2794 * @name: the name of the child
2795 * @content: the XML content of the child if any.
2797 * Creation of a new child element, added at the end of @parent children list.
2798 * @ns and @content parameters are optional (NULL). If @ns is NULL, the newly
2799 * created element inherits the namespace of @parent. If @content is non NULL,
2800 * a child list containing the TEXTs and ENTITY_REFs node will be created.
2801 * NOTE: @content is supposed to be a piece of XML CDATA, so it allows entity
2802 * references. XML special chars must be escaped first by using
2803 * xmlEncodeEntitiesReentrant(), or xmlNewTextChild() should be used.
2805 * Returns a pointer to the new node object.
2808 xmlNewChild(xmlNodePtr parent
, xmlNsPtr ns
,
2809 const xmlChar
*name
, const xmlChar
*content
) {
2810 xmlNodePtr cur
, prev
;
2812 if (parent
== NULL
) {
2814 xmlGenericError(xmlGenericErrorContext
,
2815 "xmlNewChild : parent == NULL\n");
2822 xmlGenericError(xmlGenericErrorContext
,
2823 "xmlNewChild : name == NULL\n");
2829 * Allocate a new node
2831 if (parent
->type
== XML_ELEMENT_NODE
) {
2833 cur
= xmlNewDocNode(parent
->doc
, parent
->ns
, name
, content
);
2835 cur
= xmlNewDocNode(parent
->doc
, ns
, name
, content
);
2836 } else if ((parent
->type
== XML_DOCUMENT_NODE
) ||
2837 (parent
->type
== XML_HTML_DOCUMENT_NODE
)) {
2839 cur
= xmlNewDocNode((xmlDocPtr
) parent
, NULL
, name
, content
);
2841 cur
= xmlNewDocNode((xmlDocPtr
) parent
, ns
, name
, content
);
2842 } else if (parent
->type
== XML_DOCUMENT_FRAG_NODE
) {
2843 cur
= xmlNewDocNode( parent
->doc
, ns
, name
, content
);
2847 if (cur
== NULL
) return(NULL
);
2850 * add the new element at the end of the children list.
2852 cur
->type
= XML_ELEMENT_NODE
;
2853 cur
->parent
= parent
;
2854 cur
->doc
= parent
->doc
;
2855 if (parent
->children
== NULL
) {
2856 parent
->children
= cur
;
2859 prev
= parent
->last
;
2867 #endif /* LIBXML_TREE_ENABLED */
2870 * xmlAddPropSibling:
2871 * @prev: the attribute to which @prop is added after
2872 * @cur: the base attribute passed to calling function
2873 * @prop: the new attribute
2875 * Add a new attribute after @prev using @cur as base attribute.
2876 * When inserting before @cur, @prev is passed as @cur->prev.
2877 * When inserting after @cur, @prev is passed as @cur.
2878 * If an existing attribute is found it is detroyed prior to adding @prop.
2880 * Returns the attribute being inserted or NULL in case of error.
2883 xmlAddPropSibling(xmlNodePtr prev
, xmlNodePtr cur
, xmlNodePtr prop
) {
2886 if (cur
->type
!= XML_ATTRIBUTE_NODE
)
2889 /* check if an attribute with the same name exists */
2890 if (prop
->ns
== NULL
)
2891 attr
= xmlHasNsProp(cur
->parent
, prop
->name
, NULL
);
2893 attr
= xmlHasNsProp(cur
->parent
, prop
->name
, prop
->ns
->href
);
2895 if (prop
->doc
!= cur
->doc
) {
2896 xmlSetTreeDoc(prop
, cur
->doc
);
2898 prop
->parent
= cur
->parent
;
2901 prop
->next
= prev
->next
;
2904 prop
->next
->prev
= prop
;
2909 if (prop
->prev
== NULL
&& prop
->parent
!= NULL
)
2910 prop
->parent
->properties
= (xmlAttrPtr
) prop
;
2911 if ((attr
!= NULL
) && (attr
->type
!= XML_ATTRIBUTE_DECL
)) {
2912 /* different instance, destroy it (attributes must be unique) */
2913 xmlRemoveProp((xmlAttrPtr
) attr
);
2919 * xmlAddNextSibling:
2920 * @cur: the child node
2921 * @elem: the new node
2923 * Add a new node @elem as the next sibling of @cur
2924 * If the new node was already inserted in a document it is
2925 * first unlinked from its existing context.
2926 * As a result of text merging @elem may be freed.
2927 * If the new node is ATTRIBUTE, it is added into properties instead of children.
2928 * If there is an attribute with equal name, it is first destroyed.
2930 * Returns the new node or NULL in case of error.
2933 xmlAddNextSibling(xmlNodePtr cur
, xmlNodePtr elem
) {
2936 xmlGenericError(xmlGenericErrorContext
,
2937 "xmlAddNextSibling : cur == NULL\n");
2943 xmlGenericError(xmlGenericErrorContext
,
2944 "xmlAddNextSibling : elem == NULL\n");
2951 xmlGenericError(xmlGenericErrorContext
,
2952 "xmlAddNextSibling : cur == elem\n");
2957 xmlUnlinkNode(elem
);
2959 if (elem
->type
== XML_TEXT_NODE
) {
2960 if (cur
->type
== XML_TEXT_NODE
) {
2961 xmlNodeAddContent(cur
, elem
->content
);
2965 if ((cur
->next
!= NULL
) && (cur
->next
->type
== XML_TEXT_NODE
) &&
2966 (cur
->name
== cur
->next
->name
)) {
2969 tmp
= xmlStrdup(elem
->content
);
2970 tmp
= xmlStrcat(tmp
, cur
->next
->content
);
2971 xmlNodeSetContent(cur
->next
, tmp
);
2976 } else if (elem
->type
== XML_ATTRIBUTE_NODE
) {
2977 return xmlAddPropSibling(cur
, cur
, elem
);
2980 if (elem
->doc
!= cur
->doc
) {
2981 xmlSetTreeDoc(elem
, cur
->doc
);
2983 elem
->parent
= cur
->parent
;
2985 elem
->next
= cur
->next
;
2987 if (elem
->next
!= NULL
)
2988 elem
->next
->prev
= elem
;
2989 if ((elem
->parent
!= NULL
) && (elem
->parent
->last
== cur
))
2990 elem
->parent
->last
= elem
;
2994 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_HTML_ENABLED) || \
2995 defined(LIBXML_SCHEMAS_ENABLED)
2997 * xmlAddPrevSibling:
2998 * @cur: the child node
2999 * @elem: the new node
3001 * Add a new node @elem as the previous sibling of @cur
3002 * merging adjacent TEXT nodes (@elem may be freed)
3003 * If the new node was already inserted in a document it is
3004 * first unlinked from its existing context.
3005 * If the new node is ATTRIBUTE, it is added into properties instead of children.
3006 * If there is an attribute with equal name, it is first destroyed.
3008 * Returns the new node or NULL in case of error.
3011 xmlAddPrevSibling(xmlNodePtr cur
, xmlNodePtr elem
) {
3014 xmlGenericError(xmlGenericErrorContext
,
3015 "xmlAddPrevSibling : cur == NULL\n");
3021 xmlGenericError(xmlGenericErrorContext
,
3022 "xmlAddPrevSibling : elem == NULL\n");
3029 xmlGenericError(xmlGenericErrorContext
,
3030 "xmlAddPrevSibling : cur == elem\n");
3035 xmlUnlinkNode(elem
);
3037 if (elem
->type
== XML_TEXT_NODE
) {
3038 if (cur
->type
== XML_TEXT_NODE
) {
3041 tmp
= xmlStrdup(elem
->content
);
3042 tmp
= xmlStrcat(tmp
, cur
->content
);
3043 xmlNodeSetContent(cur
, tmp
);
3048 if ((cur
->prev
!= NULL
) && (cur
->prev
->type
== XML_TEXT_NODE
) &&
3049 (cur
->name
== cur
->prev
->name
)) {
3050 xmlNodeAddContent(cur
->prev
, elem
->content
);
3054 } else if (elem
->type
== XML_ATTRIBUTE_NODE
) {
3055 return xmlAddPropSibling(cur
->prev
, cur
, elem
);
3058 if (elem
->doc
!= cur
->doc
) {
3059 xmlSetTreeDoc(elem
, cur
->doc
);
3061 elem
->parent
= cur
->parent
;
3063 elem
->prev
= cur
->prev
;
3065 if (elem
->prev
!= NULL
)
3066 elem
->prev
->next
= elem
;
3067 if ((elem
->parent
!= NULL
) && (elem
->parent
->children
== cur
)) {
3068 elem
->parent
->children
= elem
;
3072 #endif /* LIBXML_TREE_ENABLED */
3076 * @cur: the child node
3077 * @elem: the new node
3079 * Add a new element @elem to the list of siblings of @cur
3080 * merging adjacent TEXT nodes (@elem may be freed)
3081 * If the new element was already inserted in a document it is
3082 * first unlinked from its existing context.
3084 * Returns the new element or NULL in case of error.
3087 xmlAddSibling(xmlNodePtr cur
, xmlNodePtr elem
) {
3092 xmlGenericError(xmlGenericErrorContext
,
3093 "xmlAddSibling : cur == NULL\n");
3100 xmlGenericError(xmlGenericErrorContext
,
3101 "xmlAddSibling : elem == NULL\n");
3108 xmlGenericError(xmlGenericErrorContext
,
3109 "xmlAddSibling : cur == elem\n");
3115 * Constant time is we can rely on the ->parent->last to find
3118 if ((cur
->type
!= XML_ATTRIBUTE_NODE
) && (cur
->parent
!= NULL
) &&
3119 (cur
->parent
->children
!= NULL
) &&
3120 (cur
->parent
->last
!= NULL
) &&
3121 (cur
->parent
->last
->next
== NULL
)) {
3122 cur
= cur
->parent
->last
;
3124 while (cur
->next
!= NULL
) cur
= cur
->next
;
3127 xmlUnlinkNode(elem
);
3129 if ((cur
->type
== XML_TEXT_NODE
) && (elem
->type
== XML_TEXT_NODE
) &&
3130 (cur
->name
== elem
->name
)) {
3131 xmlNodeAddContent(cur
, elem
->content
);
3134 } else if (elem
->type
== XML_ATTRIBUTE_NODE
) {
3135 return xmlAddPropSibling(cur
, cur
, elem
);
3138 if (elem
->doc
!= cur
->doc
) {
3139 xmlSetTreeDoc(elem
, cur
->doc
);
3141 parent
= cur
->parent
;
3144 elem
->parent
= parent
;
3147 parent
->last
= elem
;
3154 * @parent: the parent node
3155 * @cur: the first node in the list
3157 * Add a list of node at the end of the child list of the parent
3158 * merging adjacent TEXT nodes (@cur may be freed)
3160 * Returns the last child or NULL in case of error.
3163 xmlAddChildList(xmlNodePtr parent
, xmlNodePtr cur
) {
3166 if (parent
== NULL
) {
3168 xmlGenericError(xmlGenericErrorContext
,
3169 "xmlAddChildList : parent == NULL\n");
3176 xmlGenericError(xmlGenericErrorContext
,
3177 "xmlAddChildList : child == NULL\n");
3182 if ((cur
->doc
!= NULL
) && (parent
->doc
!= NULL
) &&
3183 (cur
->doc
!= parent
->doc
)) {
3185 xmlGenericError(xmlGenericErrorContext
,
3186 "Elements moved to a different document\n");
3191 * add the first element at the end of the children list.
3194 if (parent
->children
== NULL
) {
3195 parent
->children
= cur
;
3198 * If cur and parent->last both are TEXT nodes, then merge them.
3200 if ((cur
->type
== XML_TEXT_NODE
) &&
3201 (parent
->last
->type
== XML_TEXT_NODE
) &&
3202 (cur
->name
== parent
->last
->name
)) {
3203 xmlNodeAddContent(parent
->last
, cur
->content
);
3205 * if it's the only child, nothing more to be done.
3207 if (cur
->next
== NULL
) {
3209 return(parent
->last
);
3215 prev
= parent
->last
;
3219 while (cur
->next
!= NULL
) {
3220 cur
->parent
= parent
;
3221 if (cur
->doc
!= parent
->doc
) {
3222 xmlSetTreeDoc(cur
, parent
->doc
);
3226 cur
->parent
= parent
;
3227 /* the parent may not be linked to a doc ! */
3228 if (cur
->doc
!= parent
->doc
) {
3229 xmlSetTreeDoc(cur
, parent
->doc
);
3238 * @parent: the parent node
3239 * @cur: the child node
3241 * Add a new node to @parent, at the end of the child (or property) list
3242 * merging adjacent TEXT nodes (in which case @cur is freed)
3243 * If the new node is ATTRIBUTE, it is added into properties instead of children.
3244 * If there is an attribute with equal name, it is first destroyed.
3246 * Returns the child or NULL in case of error.
3249 xmlAddChild(xmlNodePtr parent
, xmlNodePtr cur
) {
3252 if (parent
== NULL
) {
3254 xmlGenericError(xmlGenericErrorContext
,
3255 "xmlAddChild : parent == NULL\n");
3262 xmlGenericError(xmlGenericErrorContext
,
3263 "xmlAddChild : child == NULL\n");
3268 if (parent
== cur
) {
3270 xmlGenericError(xmlGenericErrorContext
,
3271 "xmlAddChild : parent == cur\n");
3276 * If cur is a TEXT node, merge its content with adjacent TEXT nodes
3277 * cur is then freed.
3279 if (cur
->type
== XML_TEXT_NODE
) {
3280 if ((parent
->type
== XML_TEXT_NODE
) &&
3281 (parent
->content
!= NULL
) &&
3282 (parent
->name
== cur
->name
)) {
3283 xmlNodeAddContent(parent
, cur
->content
);
3287 if ((parent
->last
!= NULL
) && (parent
->last
->type
== XML_TEXT_NODE
) &&
3288 (parent
->last
->name
== cur
->name
) &&
3289 (parent
->last
!= cur
)) {
3290 xmlNodeAddContent(parent
->last
, cur
->content
);
3292 return(parent
->last
);
3297 * add the new element at the end of the children list.
3300 cur
->parent
= parent
;
3301 if (cur
->doc
!= parent
->doc
) {
3302 xmlSetTreeDoc(cur
, parent
->doc
);
3304 /* this check prevents a loop on tree-traversions if a developer
3305 * tries to add a node to its parent multiple times
3313 if ((parent
->type
== XML_TEXT_NODE
) &&
3314 (parent
->content
!= NULL
) &&
3316 xmlNodeAddContent(parent
, cur
->content
);
3320 if (cur
->type
== XML_ATTRIBUTE_NODE
) {
3321 if (parent
->type
!= XML_ELEMENT_NODE
)
3323 if (parent
->properties
!= NULL
) {
3324 /* check if an attribute with the same name exists */
3325 xmlAttrPtr lastattr
;
3327 if (cur
->ns
== NULL
)
3328 lastattr
= xmlHasNsProp(parent
, cur
->name
, NULL
);
3330 lastattr
= xmlHasNsProp(parent
, cur
->name
, cur
->ns
->href
);
3331 if ((lastattr
!= NULL
) && (lastattr
!= (xmlAttrPtr
) cur
) && (lastattr
->type
!= XML_ATTRIBUTE_DECL
)) {
3332 /* different instance, destroy it (attributes must be unique) */
3333 xmlUnlinkNode((xmlNodePtr
) lastattr
);
3334 xmlFreeProp(lastattr
);
3336 if (lastattr
== (xmlAttrPtr
) cur
)
3340 if (parent
->properties
== NULL
) {
3341 parent
->properties
= (xmlAttrPtr
) cur
;
3344 xmlAttrPtr lastattr
= parent
->properties
;
3345 while (lastattr
->next
!= NULL
) {
3346 lastattr
= lastattr
->next
;
3348 lastattr
->next
= (xmlAttrPtr
) cur
;
3349 ((xmlAttrPtr
) cur
)->prev
= lastattr
;
3352 if (parent
->children
== NULL
) {
3353 parent
->children
= cur
;
3356 prev
= parent
->last
;
3367 * @parent: the parent node
3369 * Search the last child of a node.
3370 * Returns the last child or NULL if none.
3373 xmlGetLastChild(xmlNodePtr parent
) {
3374 if (parent
== NULL
) {
3376 xmlGenericError(xmlGenericErrorContext
,
3377 "xmlGetLastChild : parent == NULL\n");
3381 return(parent
->last
);
3384 #ifdef LIBXML_TREE_ENABLED
3386 * 5 interfaces from DOM ElementTraversal
3390 * xmlChildElementCount:
3391 * @parent: the parent node
3393 * Finds the current number of child nodes of that element which are
3395 * Note the handling of entities references is different than in
3396 * the W3C DOM element traversal spec since we don't have back reference
3397 * from entities content to entities references.
3399 * Returns the count of element child or 0 if not available
3402 xmlChildElementCount(xmlNodePtr parent
) {
3403 unsigned long ret
= 0;
3404 xmlNodePtr cur
= NULL
;
3408 switch (parent
->type
) {
3409 case XML_ELEMENT_NODE
:
3410 case XML_ENTITY_NODE
:
3411 case XML_DOCUMENT_NODE
:
3412 case XML_HTML_DOCUMENT_NODE
:
3413 cur
= parent
->children
;
3418 while (cur
!= NULL
) {
3419 if (cur
->type
== XML_ELEMENT_NODE
)
3427 * xmlFirstElementChild:
3428 * @parent: the parent node
3430 * Finds the first child node of that element which is a Element node
3431 * Note the handling of entities references is different than in
3432 * the W3C DOM element traversal spec since we don't have back reference
3433 * from entities content to entities references.
3435 * Returns the first element child or NULL if not available
3438 xmlFirstElementChild(xmlNodePtr parent
) {
3439 xmlNodePtr cur
= NULL
;
3443 switch (parent
->type
) {
3444 case XML_ELEMENT_NODE
:
3445 case XML_ENTITY_NODE
:
3446 case XML_DOCUMENT_NODE
:
3447 case XML_HTML_DOCUMENT_NODE
:
3448 cur
= parent
->children
;
3453 while (cur
!= NULL
) {
3454 if (cur
->type
== XML_ELEMENT_NODE
)
3462 * xmlLastElementChild:
3463 * @parent: the parent node
3465 * Finds the last child node of that element which is a Element node
3466 * Note the handling of entities references is different than in
3467 * the W3C DOM element traversal spec since we don't have back reference
3468 * from entities content to entities references.
3470 * Returns the last element child or NULL if not available
3473 xmlLastElementChild(xmlNodePtr parent
) {
3474 xmlNodePtr cur
= NULL
;
3478 switch (parent
->type
) {
3479 case XML_ELEMENT_NODE
:
3480 case XML_ENTITY_NODE
:
3481 case XML_DOCUMENT_NODE
:
3482 case XML_HTML_DOCUMENT_NODE
:
3488 while (cur
!= NULL
) {
3489 if (cur
->type
== XML_ELEMENT_NODE
)
3497 * xmlPreviousElementSibling:
3498 * @node: the current node
3500 * Finds the first closest previous sibling of the node which is an
3502 * Note the handling of entities references is different than in
3503 * the W3C DOM element traversal spec since we don't have back reference
3504 * from entities content to entities references.
3506 * Returns the previous element sibling or NULL if not available
3509 xmlPreviousElementSibling(xmlNodePtr node
) {
3512 switch (node
->type
) {
3513 case XML_ELEMENT_NODE
:
3515 case XML_CDATA_SECTION_NODE
:
3516 case XML_ENTITY_REF_NODE
:
3517 case XML_ENTITY_NODE
:
3519 case XML_COMMENT_NODE
:
3520 case XML_XINCLUDE_START
:
3521 case XML_XINCLUDE_END
:
3527 while (node
!= NULL
) {
3528 if (node
->type
== XML_ELEMENT_NODE
)
3536 * xmlNextElementSibling:
3537 * @node: the current node
3539 * Finds the first closest next sibling of the node which is an
3541 * Note the handling of entities references is different than in
3542 * the W3C DOM element traversal spec since we don't have back reference
3543 * from entities content to entities references.
3545 * Returns the next element sibling or NULL if not available
3548 xmlNextElementSibling(xmlNodePtr node
) {
3551 switch (node
->type
) {
3552 case XML_ELEMENT_NODE
:
3554 case XML_CDATA_SECTION_NODE
:
3555 case XML_ENTITY_REF_NODE
:
3556 case XML_ENTITY_NODE
:
3558 case XML_COMMENT_NODE
:
3560 case XML_XINCLUDE_START
:
3561 case XML_XINCLUDE_END
:
3567 while (node
!= NULL
) {
3568 if (node
->type
== XML_ELEMENT_NODE
)
3575 #endif /* LIBXML_TREE_ENABLED */
3579 * @cur: the first node in the list
3581 * Free a node and all its siblings, this is a recursive behaviour, all
3582 * the children are freed too.
3585 xmlFreeNodeList(xmlNodePtr cur
) {
3587 xmlDictPtr dict
= NULL
;
3589 if (cur
== NULL
) return;
3590 if (cur
->type
== XML_NAMESPACE_DECL
) {
3591 xmlFreeNsList((xmlNsPtr
) cur
);
3594 if ((cur
->type
== XML_DOCUMENT_NODE
) ||
3595 #ifdef LIBXML_DOCB_ENABLED
3596 (cur
->type
== XML_DOCB_DOCUMENT_NODE
) ||
3598 (cur
->type
== XML_HTML_DOCUMENT_NODE
)) {
3599 xmlFreeDoc((xmlDocPtr
) cur
);
3602 if (cur
->doc
!= NULL
) dict
= cur
->doc
->dict
;
3603 while (cur
!= NULL
) {
3605 if (cur
->type
!= XML_DTD_NODE
) {
3607 if ((__xmlRegisterCallbacks
) && (xmlDeregisterNodeDefaultValue
))
3608 xmlDeregisterNodeDefaultValue(cur
);
3610 if ((cur
->children
!= NULL
) &&
3611 (cur
->type
!= XML_ENTITY_REF_NODE
))
3612 xmlFreeNodeList(cur
->children
);
3613 if (((cur
->type
== XML_ELEMENT_NODE
) ||
3614 (cur
->type
== XML_XINCLUDE_START
) ||
3615 (cur
->type
== XML_XINCLUDE_END
)) &&
3616 (cur
->properties
!= NULL
))
3617 xmlFreePropList(cur
->properties
);
3618 if ((cur
->type
!= XML_ELEMENT_NODE
) &&
3619 (cur
->type
!= XML_XINCLUDE_START
) &&
3620 (cur
->type
!= XML_XINCLUDE_END
) &&
3621 (cur
->type
!= XML_ENTITY_REF_NODE
) &&
3622 (cur
->content
!= (xmlChar
*) &(cur
->properties
))) {
3623 DICT_FREE(cur
->content
)
3625 if (((cur
->type
== XML_ELEMENT_NODE
) ||
3626 (cur
->type
== XML_XINCLUDE_START
) ||
3627 (cur
->type
== XML_XINCLUDE_END
)) &&
3628 (cur
->nsDef
!= NULL
))
3629 xmlFreeNsList(cur
->nsDef
);
3632 * When a node is a text node or a comment, it uses a global static
3633 * variable for the name of the node.
3634 * Otherwise the node name might come from the document's
3637 if ((cur
->name
!= NULL
) &&
3638 (cur
->type
!= XML_TEXT_NODE
) &&
3639 (cur
->type
!= XML_COMMENT_NODE
))
3640 DICT_FREE(cur
->name
)
3651 * Free a node, this is a recursive behaviour, all the children are freed too.
3652 * This doesn't unlink the child from the list, use xmlUnlinkNode() first.
3655 xmlFreeNode(xmlNodePtr cur
) {
3656 xmlDictPtr dict
= NULL
;
3658 if (cur
== NULL
) return;
3660 /* use xmlFreeDtd for DTD nodes */
3661 if (cur
->type
== XML_DTD_NODE
) {
3662 xmlFreeDtd((xmlDtdPtr
) cur
);
3665 if (cur
->type
== XML_NAMESPACE_DECL
) {
3666 xmlFreeNs((xmlNsPtr
) cur
);
3669 if (cur
->type
== XML_ATTRIBUTE_NODE
) {
3670 xmlFreeProp((xmlAttrPtr
) cur
);
3674 if ((__xmlRegisterCallbacks
) && (xmlDeregisterNodeDefaultValue
))
3675 xmlDeregisterNodeDefaultValue(cur
);
3677 if (cur
->doc
!= NULL
) dict
= cur
->doc
->dict
;
3679 if (cur
->type
== XML_ENTITY_DECL
) {
3680 xmlEntityPtr ent
= (xmlEntityPtr
) cur
;
3681 DICT_FREE(ent
->SystemID
);
3682 DICT_FREE(ent
->ExternalID
);
3684 if ((cur
->children
!= NULL
) &&
3685 (cur
->type
!= XML_ENTITY_REF_NODE
))
3686 xmlFreeNodeList(cur
->children
);
3687 if (((cur
->type
== XML_ELEMENT_NODE
) ||
3688 (cur
->type
== XML_XINCLUDE_START
) ||
3689 (cur
->type
== XML_XINCLUDE_END
)) &&
3690 (cur
->properties
!= NULL
))
3691 xmlFreePropList(cur
->properties
);
3692 if ((cur
->type
!= XML_ELEMENT_NODE
) &&
3693 (cur
->content
!= NULL
) &&
3694 (cur
->type
!= XML_ENTITY_REF_NODE
) &&
3695 (cur
->type
!= XML_XINCLUDE_END
) &&
3696 (cur
->type
!= XML_XINCLUDE_START
) &&
3697 (cur
->content
!= (xmlChar
*) &(cur
->properties
))) {
3698 DICT_FREE(cur
->content
)
3702 * When a node is a text node or a comment, it uses a global static
3703 * variable for the name of the node.
3704 * Otherwise the node name might come from the document's dictionnary
3706 if ((cur
->name
!= NULL
) &&
3707 (cur
->type
!= XML_TEXT_NODE
) &&
3708 (cur
->type
!= XML_COMMENT_NODE
))
3709 DICT_FREE(cur
->name
)
3711 if (((cur
->type
== XML_ELEMENT_NODE
) ||
3712 (cur
->type
== XML_XINCLUDE_START
) ||
3713 (cur
->type
== XML_XINCLUDE_END
)) &&
3714 (cur
->nsDef
!= NULL
))
3715 xmlFreeNsList(cur
->nsDef
);
3723 * Unlink a node from it's current context, the node is not freed
3726 xmlUnlinkNode(xmlNodePtr cur
) {
3729 xmlGenericError(xmlGenericErrorContext
,
3730 "xmlUnlinkNode : node == NULL\n");
3734 if (cur
->type
== XML_DTD_NODE
) {
3738 if (doc
->intSubset
== (xmlDtdPtr
) cur
)
3739 doc
->intSubset
= NULL
;
3740 if (doc
->extSubset
== (xmlDtdPtr
) cur
)
3741 doc
->extSubset
= NULL
;
3744 if (cur
->type
== XML_ENTITY_DECL
) {
3748 if (doc
->intSubset
!= NULL
) {
3749 if (xmlHashLookup(doc
->intSubset
->entities
, cur
->name
) == cur
)
3750 xmlHashRemoveEntry(doc
->intSubset
->entities
, cur
->name
,
3752 if (xmlHashLookup(doc
->intSubset
->pentities
, cur
->name
) == cur
)
3753 xmlHashRemoveEntry(doc
->intSubset
->pentities
, cur
->name
,
3756 if (doc
->extSubset
!= NULL
) {
3757 if (xmlHashLookup(doc
->extSubset
->entities
, cur
->name
) == cur
)
3758 xmlHashRemoveEntry(doc
->extSubset
->entities
, cur
->name
,
3760 if (xmlHashLookup(doc
->extSubset
->pentities
, cur
->name
) == cur
)
3761 xmlHashRemoveEntry(doc
->extSubset
->pentities
, cur
->name
,
3766 if (cur
->parent
!= NULL
) {
3768 parent
= cur
->parent
;
3769 if (cur
->type
== XML_ATTRIBUTE_NODE
) {
3770 if (parent
->properties
== (xmlAttrPtr
) cur
)
3771 parent
->properties
= ((xmlAttrPtr
) cur
)->next
;
3773 if (parent
->children
== cur
)
3774 parent
->children
= cur
->next
;
3775 if (parent
->last
== cur
)
3776 parent
->last
= cur
->prev
;
3780 if (cur
->next
!= NULL
)
3781 cur
->next
->prev
= cur
->prev
;
3782 if (cur
->prev
!= NULL
)
3783 cur
->prev
->next
= cur
->next
;
3784 cur
->next
= cur
->prev
= NULL
;
3787 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_WRITER_ENABLED)
3790 * @old: the old node
3793 * Unlink the old node from its current context, prune the new one
3794 * at the same place. If @cur was already inserted in a document it is
3795 * first unlinked from its existing context.
3797 * Returns the @old node
3800 xmlReplaceNode(xmlNodePtr old
, xmlNodePtr cur
) {
3801 if (old
== cur
) return(NULL
);
3802 if ((old
== NULL
) || (old
->parent
== NULL
)) {
3804 xmlGenericError(xmlGenericErrorContext
,
3805 "xmlReplaceNode : old == NULL or without parent\n");
3816 if ((old
->type
==XML_ATTRIBUTE_NODE
) && (cur
->type
!=XML_ATTRIBUTE_NODE
)) {
3818 xmlGenericError(xmlGenericErrorContext
,
3819 "xmlReplaceNode : Trying to replace attribute node with other node type\n");
3823 if ((cur
->type
==XML_ATTRIBUTE_NODE
) && (old
->type
!=XML_ATTRIBUTE_NODE
)) {
3825 xmlGenericError(xmlGenericErrorContext
,
3826 "xmlReplaceNode : Trying to replace a non-attribute node with attribute node\n");
3831 xmlSetTreeDoc(cur
, old
->doc
);
3832 cur
->parent
= old
->parent
;
3833 cur
->next
= old
->next
;
3834 if (cur
->next
!= NULL
)
3835 cur
->next
->prev
= cur
;
3836 cur
->prev
= old
->prev
;
3837 if (cur
->prev
!= NULL
)
3838 cur
->prev
->next
= cur
;
3839 if (cur
->parent
!= NULL
) {
3840 if (cur
->type
== XML_ATTRIBUTE_NODE
) {
3841 if (cur
->parent
->properties
== (xmlAttrPtr
)old
)
3842 cur
->parent
->properties
= ((xmlAttrPtr
) cur
);
3844 if (cur
->parent
->children
== old
)
3845 cur
->parent
->children
= cur
;
3846 if (cur
->parent
->last
== old
)
3847 cur
->parent
->last
= cur
;
3850 old
->next
= old
->prev
= NULL
;
3854 #endif /* LIBXML_TREE_ENABLED */
3856 /************************************************************************
3860 ************************************************************************/
3864 * @cur: the namespace
3866 * Do a copy of the namespace.
3868 * Returns: a new #xmlNsPtr, or NULL in case of error.
3871 xmlCopyNamespace(xmlNsPtr cur
) {
3874 if (cur
== NULL
) return(NULL
);
3875 switch (cur
->type
) {
3876 case XML_LOCAL_NAMESPACE
:
3877 ret
= xmlNewNs(NULL
, cur
->href
, cur
->prefix
);
3881 xmlGenericError(xmlGenericErrorContext
,
3882 "xmlCopyNamespace: invalid type %d\n", cur
->type
);
3890 * xmlCopyNamespaceList:
3891 * @cur: the first namespace
3893 * Do a copy of an namespace list.
3895 * Returns: a new #xmlNsPtr, or NULL in case of error.
3898 xmlCopyNamespaceList(xmlNsPtr cur
) {
3899 xmlNsPtr ret
= NULL
;
3900 xmlNsPtr p
= NULL
,q
;
3902 while (cur
!= NULL
) {
3903 q
= xmlCopyNamespace(cur
);
3916 xmlStaticCopyNodeList(xmlNodePtr node
, xmlDocPtr doc
, xmlNodePtr parent
);
3919 xmlCopyPropInternal(xmlDocPtr doc
, xmlNodePtr target
, xmlAttrPtr cur
) {
3922 if (cur
== NULL
) return(NULL
);
3924 ret
= xmlNewDocProp(target
->doc
, cur
->name
, NULL
);
3925 else if (doc
!= NULL
)
3926 ret
= xmlNewDocProp(doc
, cur
->name
, NULL
);
3927 else if (cur
->parent
!= NULL
)
3928 ret
= xmlNewDocProp(cur
->parent
->doc
, cur
->name
, NULL
);
3929 else if (cur
->children
!= NULL
)
3930 ret
= xmlNewDocProp(cur
->children
->doc
, cur
->name
, NULL
);
3932 ret
= xmlNewDocProp(NULL
, cur
->name
, NULL
);
3933 if (ret
== NULL
) return(NULL
);
3934 ret
->parent
= target
;
3936 if ((cur
->ns
!= NULL
) && (target
!= NULL
)) {
3939 ns
= xmlSearchNs(target
->doc
, target
, cur
->ns
->prefix
);
3942 * Humm, we are copying an element whose namespace is defined
3943 * out of the new tree scope. Search it in the original tree
3944 * and add it at the top of the new tree
3946 ns
= xmlSearchNs(cur
->doc
, cur
->parent
, cur
->ns
->prefix
);
3948 xmlNodePtr root
= target
;
3949 xmlNodePtr pred
= NULL
;
3951 while (root
->parent
!= NULL
) {
3953 root
= root
->parent
;
3955 if (root
== (xmlNodePtr
) target
->doc
) {
3956 /* correct possibly cycling above the document elt */
3959 ret
->ns
= xmlNewNs(root
, ns
->href
, ns
->prefix
);
3963 * we have to find something appropriate here since
3964 * we cant be sure, that the namespce we found is identified
3967 if (xmlStrEqual(ns
->href
, cur
->ns
->href
)) {
3968 /* this is the nice case */
3972 * we are in trouble: we need a new reconcilied namespace.
3975 ret
->ns
= xmlNewReconciliedNs(target
->doc
, target
, cur
->ns
);
3982 if (cur
->children
!= NULL
) {
3985 ret
->children
= xmlStaticCopyNodeList(cur
->children
, ret
->doc
, (xmlNodePtr
) ret
);
3987 tmp
= ret
->children
;
3988 while (tmp
!= NULL
) {
3989 /* tmp->parent = (xmlNodePtr)ret; */
3990 if (tmp
->next
== NULL
)
3998 if ((target
!= NULL
) && (cur
!= NULL
) &&
3999 (target
->doc
!= NULL
) && (cur
->doc
!= NULL
) &&
4000 (cur
->doc
->ids
!= NULL
) && (cur
->parent
!= NULL
)) {
4001 if (xmlIsID(cur
->doc
, cur
->parent
, cur
)) {
4004 id
= xmlNodeListGetString(cur
->doc
, cur
->children
, 1);
4006 xmlAddID(NULL
, target
->doc
, id
, ret
);
4016 * @target: the element where the attribute will be grafted
4017 * @cur: the attribute
4019 * Do a copy of the attribute.
4021 * Returns: a new #xmlAttrPtr, or NULL in case of error.
4024 xmlCopyProp(xmlNodePtr target
, xmlAttrPtr cur
) {
4025 return xmlCopyPropInternal(NULL
, target
, cur
);
4030 * @target: the element where the attributes will be grafted
4031 * @cur: the first attribute
4033 * Do a copy of an attribute list.
4035 * Returns: a new #xmlAttrPtr, or NULL in case of error.
4038 xmlCopyPropList(xmlNodePtr target
, xmlAttrPtr cur
) {
4039 xmlAttrPtr ret
= NULL
;
4040 xmlAttrPtr p
= NULL
,q
;
4042 while (cur
!= NULL
) {
4043 q
= xmlCopyProp(target
, cur
);
4059 * NOTE about the CopyNode operations !
4061 * They are split into external and internal parts for one
4062 * tricky reason: namespaces. Doing a direct copy of a node
4063 * say RPM:Copyright without changing the namespace pointer to
4064 * something else can produce stale links. One way to do it is
4065 * to keep a reference counter but this doesn't work as soon
4066 * as one move the element or the subtree out of the scope of
4067 * the existing namespace. The actual solution seems to add
4068 * a copy of the namespace at the top of the copied tree if
4069 * not available in the subtree.
4070 * Hence two functions, the public front-end call the inner ones
4071 * The argument "recursive" normally indicates a recursive copy
4072 * of the node with values 0 (no) and 1 (yes). For XInclude,
4073 * however, we allow a value of 2 to indicate copy properties and
4074 * namespace info, but don't recurse on children.
4078 xmlStaticCopyNode(const xmlNodePtr node
, xmlDocPtr doc
, xmlNodePtr parent
,
4082 if (node
== NULL
) return(NULL
);
4083 switch (node
->type
) {
4085 case XML_CDATA_SECTION_NODE
:
4086 case XML_ELEMENT_NODE
:
4087 case XML_DOCUMENT_FRAG_NODE
:
4088 case XML_ENTITY_REF_NODE
:
4089 case XML_ENTITY_NODE
:
4091 case XML_COMMENT_NODE
:
4092 case XML_XINCLUDE_START
:
4093 case XML_XINCLUDE_END
:
4095 case XML_ATTRIBUTE_NODE
:
4096 return((xmlNodePtr
) xmlCopyPropInternal(doc
, parent
, (xmlAttrPtr
) node
));
4097 case XML_NAMESPACE_DECL
:
4098 return((xmlNodePtr
) xmlCopyNamespaceList((xmlNsPtr
) node
));
4100 case XML_DOCUMENT_NODE
:
4101 case XML_HTML_DOCUMENT_NODE
:
4102 #ifdef LIBXML_DOCB_ENABLED
4103 case XML_DOCB_DOCUMENT_NODE
:
4105 #ifdef LIBXML_TREE_ENABLED
4106 return((xmlNodePtr
) xmlCopyDoc((xmlDocPtr
) node
, extended
));
4107 #endif /* LIBXML_TREE_ENABLED */
4108 case XML_DOCUMENT_TYPE_NODE
:
4109 case XML_NOTATION_NODE
:
4111 case XML_ELEMENT_DECL
:
4112 case XML_ATTRIBUTE_DECL
:
4113 case XML_ENTITY_DECL
:
4118 * Allocate a new node and fill the fields.
4120 ret
= (xmlNodePtr
) xmlMalloc(sizeof(xmlNode
));
4122 xmlTreeErrMemory("copying node");
4125 memset(ret
, 0, sizeof(xmlNode
));
4126 ret
->type
= node
->type
;
4129 ret
->parent
= parent
;
4130 if (node
->name
== xmlStringText
)
4131 ret
->name
= xmlStringText
;
4132 else if (node
->name
== xmlStringTextNoenc
)
4133 ret
->name
= xmlStringTextNoenc
;
4134 else if (node
->name
== xmlStringComment
)
4135 ret
->name
= xmlStringComment
;
4136 else if (node
->name
!= NULL
) {
4137 if ((doc
!= NULL
) && (doc
->dict
!= NULL
))
4138 ret
->name
= xmlDictLookup(doc
->dict
, node
->name
, -1);
4140 ret
->name
= xmlStrdup(node
->name
);
4142 if ((node
->type
!= XML_ELEMENT_NODE
) &&
4143 (node
->content
!= NULL
) &&
4144 (node
->type
!= XML_ENTITY_REF_NODE
) &&
4145 (node
->type
!= XML_XINCLUDE_END
) &&
4146 (node
->type
!= XML_XINCLUDE_START
)) {
4147 ret
->content
= xmlStrdup(node
->content
);
4149 if (node
->type
== XML_ELEMENT_NODE
)
4150 ret
->line
= node
->line
;
4152 if (parent
!= NULL
) {
4156 * this is a tricky part for the node register thing:
4157 * in case ret does get coalesced in xmlAddChild
4158 * the deregister-node callback is called; so we register ret now already
4160 if ((__xmlRegisterCallbacks
) && (xmlRegisterNodeDefaultValue
))
4161 xmlRegisterNodeDefaultValue((xmlNodePtr
)ret
);
4163 tmp
= xmlAddChild(parent
, ret
);
4164 /* node could have coalesced */
4171 if (((node
->type
== XML_ELEMENT_NODE
) ||
4172 (node
->type
== XML_XINCLUDE_START
)) && (node
->nsDef
!= NULL
))
4173 ret
->nsDef
= xmlCopyNamespaceList(node
->nsDef
);
4175 if (node
->ns
!= NULL
) {
4178 ns
= xmlSearchNs(doc
, ret
, node
->ns
->prefix
);
4181 * Humm, we are copying an element whose namespace is defined
4182 * out of the new tree scope. Search it in the original tree
4183 * and add it at the top of the new tree
4185 ns
= xmlSearchNs(node
->doc
, node
, node
->ns
->prefix
);
4187 xmlNodePtr root
= ret
;
4189 while (root
->parent
!= NULL
) root
= root
->parent
;
4190 ret
->ns
= xmlNewNs(root
, ns
->href
, ns
->prefix
);
4194 * reference the existing namespace definition in our own tree.
4199 if (((node
->type
== XML_ELEMENT_NODE
) ||
4200 (node
->type
== XML_XINCLUDE_START
)) && (node
->properties
!= NULL
))
4201 ret
->properties
= xmlCopyPropList(ret
, node
->properties
);
4202 if (node
->type
== XML_ENTITY_REF_NODE
) {
4203 if ((doc
== NULL
) || (node
->doc
!= doc
)) {
4205 * The copied node will go into a separate document, so
4206 * to avoid dangling references to the ENTITY_DECL node
4207 * we cannot keep the reference. Try to find it in the
4210 ret
->children
= (xmlNodePtr
) xmlGetDocEntity(doc
, ret
->name
);
4212 ret
->children
= node
->children
;
4214 ret
->last
= ret
->children
;
4215 } else if ((node
->children
!= NULL
) && (extended
!= 2)) {
4216 ret
->children
= xmlStaticCopyNodeList(node
->children
, doc
, ret
);
4217 UPDATE_LAST_CHILD_AND_PARENT(ret
)
4221 /* if parent != NULL we already registered the node above */
4222 if ((parent
== NULL
) &&
4223 ((__xmlRegisterCallbacks
) && (xmlRegisterNodeDefaultValue
)))
4224 xmlRegisterNodeDefaultValue((xmlNodePtr
)ret
);
4229 xmlStaticCopyNodeList(xmlNodePtr node
, xmlDocPtr doc
, xmlNodePtr parent
) {
4230 xmlNodePtr ret
= NULL
;
4231 xmlNodePtr p
= NULL
,q
;
4233 while (node
!= NULL
) {
4234 #ifdef LIBXML_TREE_ENABLED
4235 if (node
->type
== XML_DTD_NODE
) {
4240 if (doc
->intSubset
== NULL
) {
4241 q
= (xmlNodePtr
) xmlCopyDtd( (xmlDtdPtr
) node
);
4244 doc
->intSubset
= (xmlDtdPtr
) q
;
4245 xmlAddChild(parent
, q
);
4247 q
= (xmlNodePtr
) doc
->intSubset
;
4248 xmlAddChild(parent
, q
);
4251 #endif /* LIBXML_TREE_ENABLED */
4252 q
= xmlStaticCopyNode(node
, doc
, parent
, 1);
4256 } else if (p
!= q
) {
4257 /* the test is required if xmlStaticCopyNode coalesced 2 text nodes */
4270 * @extended: if 1 do a recursive copy (properties, namespaces and children
4272 * if 2 copy properties and namespaces (when applicable)
4274 * Do a copy of the node.
4276 * Returns: a new #xmlNodePtr, or NULL in case of error.
4279 xmlCopyNode(const xmlNodePtr node
, int extended
) {
4282 ret
= xmlStaticCopyNode(node
, NULL
, NULL
, extended
);
4289 * @doc: the document
4290 * @extended: if 1 do a recursive copy (properties, namespaces and children
4292 * if 2 copy properties and namespaces (when applicable)
4294 * Do a copy of the node to a given document.
4296 * Returns: a new #xmlNodePtr, or NULL in case of error.
4299 xmlDocCopyNode(const xmlNodePtr node
, xmlDocPtr doc
, int extended
) {
4302 ret
= xmlStaticCopyNode(node
, doc
, NULL
, extended
);
4307 * xmlDocCopyNodeList:
4308 * @doc: the target document
4309 * @node: the first node in the list.
4311 * Do a recursive copy of the node list.
4313 * Returns: a new #xmlNodePtr, or NULL in case of error.
4315 xmlNodePtr
xmlDocCopyNodeList(xmlDocPtr doc
, const xmlNodePtr node
) {
4316 xmlNodePtr ret
= xmlStaticCopyNodeList(node
, doc
, NULL
);
4322 * @node: the first node in the list.
4324 * Do a recursive copy of the node list.
4325 * Use xmlDocCopyNodeList() if possible to ensure string interning.
4327 * Returns: a new #xmlNodePtr, or NULL in case of error.
4329 xmlNodePtr
xmlCopyNodeList(const xmlNodePtr node
) {
4330 xmlNodePtr ret
= xmlStaticCopyNodeList(node
, NULL
, NULL
);
4334 #if defined(LIBXML_TREE_ENABLED)
4339 * Do a copy of the dtd.
4341 * Returns: a new #xmlDtdPtr, or NULL in case of error.
4344 xmlCopyDtd(xmlDtdPtr dtd
) {
4346 xmlNodePtr cur
, p
= NULL
, q
;
4348 if (dtd
== NULL
) return(NULL
);
4349 ret
= xmlNewDtd(NULL
, dtd
->name
, dtd
->ExternalID
, dtd
->SystemID
);
4350 if (ret
== NULL
) return(NULL
);
4351 if (dtd
->entities
!= NULL
)
4352 ret
->entities
= (void *) xmlCopyEntitiesTable(
4353 (xmlEntitiesTablePtr
) dtd
->entities
);
4354 if (dtd
->notations
!= NULL
)
4355 ret
->notations
= (void *) xmlCopyNotationTable(
4356 (xmlNotationTablePtr
) dtd
->notations
);
4357 if (dtd
->elements
!= NULL
)
4358 ret
->elements
= (void *) xmlCopyElementTable(
4359 (xmlElementTablePtr
) dtd
->elements
);
4360 if (dtd
->attributes
!= NULL
)
4361 ret
->attributes
= (void *) xmlCopyAttributeTable(
4362 (xmlAttributeTablePtr
) dtd
->attributes
);
4363 if (dtd
->pentities
!= NULL
)
4364 ret
->pentities
= (void *) xmlCopyEntitiesTable(
4365 (xmlEntitiesTablePtr
) dtd
->pentities
);
4367 cur
= dtd
->children
;
4368 while (cur
!= NULL
) {
4371 if (cur
->type
== XML_ENTITY_DECL
) {
4372 xmlEntityPtr tmp
= (xmlEntityPtr
) cur
;
4373 switch (tmp
->etype
) {
4374 case XML_INTERNAL_GENERAL_ENTITY
:
4375 case XML_EXTERNAL_GENERAL_PARSED_ENTITY
:
4376 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY
:
4377 q
= (xmlNodePtr
) xmlGetEntityFromDtd(ret
, tmp
->name
);
4379 case XML_INTERNAL_PARAMETER_ENTITY
:
4380 case XML_EXTERNAL_PARAMETER_ENTITY
:
4382 xmlGetParameterEntityFromDtd(ret
, tmp
->name
);
4384 case XML_INTERNAL_PREDEFINED_ENTITY
:
4387 } else if (cur
->type
== XML_ELEMENT_DECL
) {
4388 xmlElementPtr tmp
= (xmlElementPtr
) cur
;
4390 xmlGetDtdQElementDesc(ret
, tmp
->name
, tmp
->prefix
);
4391 } else if (cur
->type
== XML_ATTRIBUTE_DECL
) {
4392 xmlAttributePtr tmp
= (xmlAttributePtr
) cur
;
4394 xmlGetDtdQAttrDesc(ret
, tmp
->elem
, tmp
->name
, tmp
->prefix
);
4395 } else if (cur
->type
== XML_COMMENT_NODE
) {
4396 q
= xmlCopyNode(cur
, 0);
4410 q
->parent
= (xmlNodePtr
) ret
;
4421 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
4424 * @doc: the document
4425 * @recursive: if not zero do a recursive copy.
4427 * Do a copy of the document info. If recursive, the content tree will
4428 * be copied too as well as DTD, namespaces and entities.
4430 * Returns: a new #xmlDocPtr, or NULL in case of error.
4433 xmlCopyDoc(xmlDocPtr doc
, int recursive
) {
4436 if (doc
== NULL
) return(NULL
);
4437 ret
= xmlNewDoc(doc
->version
);
4438 if (ret
== NULL
) return(NULL
);
4439 if (doc
->name
!= NULL
)
4440 ret
->name
= xmlMemStrdup(doc
->name
);
4441 if (doc
->encoding
!= NULL
)
4442 ret
->encoding
= xmlStrdup(doc
->encoding
);
4443 if (doc
->URL
!= NULL
)
4444 ret
->URL
= xmlStrdup(doc
->URL
);
4445 ret
->charset
= doc
->charset
;
4446 ret
->compression
= doc
->compression
;
4447 ret
->standalone
= doc
->standalone
;
4448 if (!recursive
) return(ret
);
4451 ret
->children
= NULL
;
4452 #ifdef LIBXML_TREE_ENABLED
4453 if (doc
->intSubset
!= NULL
) {
4454 ret
->intSubset
= xmlCopyDtd(doc
->intSubset
);
4455 xmlSetTreeDoc((xmlNodePtr
)ret
->intSubset
, ret
);
4456 ret
->intSubset
->parent
= ret
;
4459 if (doc
->oldNs
!= NULL
)
4460 ret
->oldNs
= xmlCopyNamespaceList(doc
->oldNs
);
4461 if (doc
->children
!= NULL
) {
4464 ret
->children
= xmlStaticCopyNodeList(doc
->children
, ret
,
4467 tmp
= ret
->children
;
4468 while (tmp
!= NULL
) {
4469 if (tmp
->next
== NULL
)
4476 #endif /* LIBXML_TREE_ENABLED */
4478 /************************************************************************
4480 * Content access functions *
4482 ************************************************************************/
4488 * Get line number of @node. This requires activation of this option
4489 * before invoking the parser by calling xmlLineNumbersDefault(1)
4491 * Returns the line number if successful, -1 otherwise
4494 xmlGetLineNo(xmlNodePtr node
)
4500 if ((node
->type
== XML_ELEMENT_NODE
) ||
4501 (node
->type
== XML_TEXT_NODE
) ||
4502 (node
->type
== XML_COMMENT_NODE
) ||
4503 (node
->type
== XML_PI_NODE
))
4504 result
= (long) node
->line
;
4505 else if ((node
->prev
!= NULL
) &&
4506 ((node
->prev
->type
== XML_ELEMENT_NODE
) ||
4507 (node
->prev
->type
== XML_TEXT_NODE
) ||
4508 (node
->prev
->type
== XML_COMMENT_NODE
) ||
4509 (node
->prev
->type
== XML_PI_NODE
)))
4510 result
= xmlGetLineNo(node
->prev
);
4511 else if ((node
->parent
!= NULL
) &&
4512 (node
->parent
->type
== XML_ELEMENT_NODE
))
4513 result
= xmlGetLineNo(node
->parent
);
4518 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_DEBUG_ENABLED)
4523 * Build a structure based Path for the given node
4525 * Returns the new path or NULL in case of error. The caller must free
4526 * the returned string
4529 xmlGetNodePath(xmlNodePtr node
)
4531 xmlNodePtr cur
, tmp
, next
;
4532 xmlChar
*buffer
= NULL
, *temp
;
4538 int occur
= 0, generic
;
4544 buffer
= (xmlChar
*) xmlMallocAtomic(buf_len
* sizeof(xmlChar
));
4545 if (buffer
== NULL
) {
4546 xmlTreeErrMemory("getting node path");
4549 buf
= (xmlChar
*) xmlMallocAtomic(buf_len
* sizeof(xmlChar
));
4551 xmlTreeErrMemory("getting node path");
4562 if ((cur
->type
== XML_DOCUMENT_NODE
) ||
4563 (cur
->type
== XML_HTML_DOCUMENT_NODE
)) {
4564 if (buffer
[0] == '/')
4568 } else if (cur
->type
== XML_ELEMENT_NODE
) {
4571 name
= (const char *) cur
->name
;
4573 if (cur
->ns
->prefix
!= NULL
) {
4574 snprintf(nametemp
, sizeof(nametemp
) - 1, "%s:%s",
4575 (char *)cur
->ns
->prefix
, (char *)cur
->name
);
4576 nametemp
[sizeof(nametemp
) - 1] = 0;
4580 * We cannot express named elements in the default
4581 * namespace, so use "*".
4590 * Thumbler index computation
4591 * TODO: the ocurence test seems bogus for namespaced names
4594 while (tmp
!= NULL
) {
4595 if ((tmp
->type
== XML_ELEMENT_NODE
) &&
4597 (xmlStrEqual(cur
->name
, tmp
->name
) &&
4598 ((tmp
->ns
== cur
->ns
) ||
4599 ((tmp
->ns
!= NULL
) && (cur
->ns
!= NULL
) &&
4600 (xmlStrEqual(cur
->ns
->prefix
, tmp
->ns
->prefix
)))))))
4606 while (tmp
!= NULL
&& occur
== 0) {
4607 if ((tmp
->type
== XML_ELEMENT_NODE
) &&
4609 (xmlStrEqual(cur
->name
, tmp
->name
) &&
4610 ((tmp
->ns
== cur
->ns
) ||
4611 ((tmp
->ns
!= NULL
) && (cur
->ns
!= NULL
) &&
4612 (xmlStrEqual(cur
->ns
->prefix
, tmp
->ns
->prefix
)))))))
4620 } else if (cur
->type
== XML_COMMENT_NODE
) {
4626 * Thumbler index computation
4629 while (tmp
!= NULL
) {
4630 if (tmp
->type
== XML_COMMENT_NODE
)
4636 while (tmp
!= NULL
&& occur
== 0) {
4637 if (tmp
->type
== XML_COMMENT_NODE
)
4645 } else if ((cur
->type
== XML_TEXT_NODE
) ||
4646 (cur
->type
== XML_CDATA_SECTION_NODE
)) {
4652 * Thumbler index computation
4655 while (tmp
!= NULL
) {
4656 if ((tmp
->type
== XML_TEXT_NODE
) ||
4657 (tmp
->type
== XML_CDATA_SECTION_NODE
))
4662 * Evaluate if this is the only text- or CDATA-section-node;
4663 * if yes, then we'll get "text()", otherwise "text()[1]".
4667 while (tmp
!= NULL
) {
4668 if ((tmp
->type
== XML_TEXT_NODE
) ||
4669 (tmp
->type
== XML_CDATA_SECTION_NODE
))
4678 } else if (cur
->type
== XML_PI_NODE
) {
4680 snprintf(nametemp
, sizeof(nametemp
) - 1,
4681 "processing-instruction('%s')", (char *)cur
->name
);
4682 nametemp
[sizeof(nametemp
) - 1] = 0;
4688 * Thumbler index computation
4691 while (tmp
!= NULL
) {
4692 if ((tmp
->type
== XML_PI_NODE
) &&
4693 (xmlStrEqual(cur
->name
, tmp
->name
)))
4699 while (tmp
!= NULL
&& occur
== 0) {
4700 if ((tmp
->type
== XML_PI_NODE
) &&
4701 (xmlStrEqual(cur
->name
, tmp
->name
)))
4710 } else if (cur
->type
== XML_ATTRIBUTE_NODE
) {
4712 name
= (const char *) (((xmlAttrPtr
) cur
)->name
);
4714 if (cur
->ns
->prefix
!= NULL
)
4715 snprintf(nametemp
, sizeof(nametemp
) - 1, "%s:%s",
4716 (char *)cur
->ns
->prefix
, (char *)cur
->name
);
4718 snprintf(nametemp
, sizeof(nametemp
) - 1, "%s",
4720 nametemp
[sizeof(nametemp
) - 1] = 0;
4723 next
= ((xmlAttrPtr
) cur
)->parent
;
4729 * Make sure there is enough room
4731 if (xmlStrlen(buffer
) + sizeof(nametemp
) + 20 > buf_len
) {
4733 2 * buf_len
+ xmlStrlen(buffer
) + sizeof(nametemp
) + 20;
4734 temp
= (xmlChar
*) xmlRealloc(buffer
, buf_len
);
4736 xmlTreeErrMemory("getting node path");
4742 temp
= (xmlChar
*) xmlRealloc(buf
, buf_len
);
4744 xmlTreeErrMemory("getting node path");
4752 snprintf((char *) buf
, buf_len
, "%s%s%s",
4753 sep
, name
, (char *) buffer
);
4755 snprintf((char *) buf
, buf_len
, "%s%s[%d]%s",
4756 sep
, name
, occur
, (char *) buffer
);
4757 snprintf((char *) buffer
, buf_len
, "%s", (char *)buf
);
4759 } while (cur
!= NULL
);
4763 #endif /* LIBXML_TREE_ENABLED */
4766 * xmlDocGetRootElement:
4767 * @doc: the document
4769 * Get the root element of the document (doc->children is a list
4770 * containing possibly comments, PIs, etc ...).
4772 * Returns the #xmlNodePtr for the root or NULL
4775 xmlDocGetRootElement(xmlDocPtr doc
) {
4778 if (doc
== NULL
) return(NULL
);
4779 ret
= doc
->children
;
4780 while (ret
!= NULL
) {
4781 if (ret
->type
== XML_ELEMENT_NODE
)
4788 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_WRITER_ENABLED)
4790 * xmlDocSetRootElement:
4791 * @doc: the document
4792 * @root: the new document root element, if root is NULL no action is taken,
4793 * to remove a node from a document use xmlUnlinkNode(root) instead.
4795 * Set the root element of the document (doc->children is a list
4796 * containing possibly comments, PIs, etc ...).
4798 * Returns the old root element if any was found, NULL if root was NULL
4801 xmlDocSetRootElement(xmlDocPtr doc
, xmlNodePtr root
) {
4802 xmlNodePtr old
= NULL
;
4804 if (doc
== NULL
) return(NULL
);
4807 xmlUnlinkNode(root
);
4808 xmlSetTreeDoc(root
, doc
);
4809 root
->parent
= (xmlNodePtr
) doc
;
4810 old
= doc
->children
;
4811 while (old
!= NULL
) {
4812 if (old
->type
== XML_ELEMENT_NODE
)
4817 if (doc
->children
== NULL
) {
4818 doc
->children
= root
;
4821 xmlAddSibling(doc
->children
, root
);
4824 xmlReplaceNode(old
, root
);
4830 #if defined(LIBXML_TREE_ENABLED)
4833 * @cur: the node being changed
4834 * @lang: the language description
4836 * Set the language of a node, i.e. the values of the xml:lang
4840 xmlNodeSetLang(xmlNodePtr cur
, const xmlChar
*lang
) {
4843 if (cur
== NULL
) return;
4846 case XML_CDATA_SECTION_NODE
:
4847 case XML_COMMENT_NODE
:
4848 case XML_DOCUMENT_NODE
:
4849 case XML_DOCUMENT_TYPE_NODE
:
4850 case XML_DOCUMENT_FRAG_NODE
:
4851 case XML_NOTATION_NODE
:
4852 case XML_HTML_DOCUMENT_NODE
:
4854 case XML_ELEMENT_DECL
:
4855 case XML_ATTRIBUTE_DECL
:
4856 case XML_ENTITY_DECL
:
4858 case XML_ENTITY_REF_NODE
:
4859 case XML_ENTITY_NODE
:
4860 case XML_NAMESPACE_DECL
:
4861 #ifdef LIBXML_DOCB_ENABLED
4862 case XML_DOCB_DOCUMENT_NODE
:
4864 case XML_XINCLUDE_START
:
4865 case XML_XINCLUDE_END
:
4867 case XML_ELEMENT_NODE
:
4868 case XML_ATTRIBUTE_NODE
:
4871 ns
= xmlSearchNsByHref(cur
->doc
, cur
, XML_XML_NAMESPACE
);
4874 xmlSetNsProp(cur
, ns
, BAD_CAST
"lang", lang
);
4876 #endif /* LIBXML_TREE_ENABLED */
4880 * @cur: the node being checked
4882 * Searches the language of a node, i.e. the values of the xml:lang
4883 * attribute or the one carried by the nearest ancestor.
4885 * Returns a pointer to the lang value, or NULL if not found
4886 * It's up to the caller to free the memory with xmlFree().
4889 xmlNodeGetLang(xmlNodePtr cur
) {
4892 while (cur
!= NULL
) {
4893 lang
= xmlGetNsProp(cur
, BAD_CAST
"lang", XML_XML_NAMESPACE
);
4902 #ifdef LIBXML_TREE_ENABLED
4904 * xmlNodeSetSpacePreserve:
4905 * @cur: the node being changed
4906 * @val: the xml:space value ("0": default, 1: "preserve")
4908 * Set (or reset) the space preserving behaviour of a node, i.e. the
4909 * value of the xml:space attribute.
4912 xmlNodeSetSpacePreserve(xmlNodePtr cur
, int val
) {
4915 if (cur
== NULL
) return;
4918 case XML_CDATA_SECTION_NODE
:
4919 case XML_COMMENT_NODE
:
4920 case XML_DOCUMENT_NODE
:
4921 case XML_DOCUMENT_TYPE_NODE
:
4922 case XML_DOCUMENT_FRAG_NODE
:
4923 case XML_NOTATION_NODE
:
4924 case XML_HTML_DOCUMENT_NODE
:
4926 case XML_ELEMENT_DECL
:
4927 case XML_ATTRIBUTE_DECL
:
4928 case XML_ENTITY_DECL
:
4930 case XML_ENTITY_REF_NODE
:
4931 case XML_ENTITY_NODE
:
4932 case XML_NAMESPACE_DECL
:
4933 case XML_XINCLUDE_START
:
4934 case XML_XINCLUDE_END
:
4935 #ifdef LIBXML_DOCB_ENABLED
4936 case XML_DOCB_DOCUMENT_NODE
:
4939 case XML_ELEMENT_NODE
:
4940 case XML_ATTRIBUTE_NODE
:
4943 ns
= xmlSearchNsByHref(cur
->doc
, cur
, XML_XML_NAMESPACE
);
4948 xmlSetNsProp(cur
, ns
, BAD_CAST
"space", BAD_CAST
"default");
4951 xmlSetNsProp(cur
, ns
, BAD_CAST
"space", BAD_CAST
"preserve");
4955 #endif /* LIBXML_TREE_ENABLED */
4958 * xmlNodeGetSpacePreserve:
4959 * @cur: the node being checked
4961 * Searches the space preserving behaviour of a node, i.e. the values
4962 * of the xml:space attribute or the one carried by the nearest
4965 * Returns -1 if xml:space is not inherited, 0 if "default", 1 if "preserve"
4968 xmlNodeGetSpacePreserve(xmlNodePtr cur
) {
4971 while (cur
!= NULL
) {
4972 space
= xmlGetNsProp(cur
, BAD_CAST
"space", XML_XML_NAMESPACE
);
4973 if (space
!= NULL
) {
4974 if (xmlStrEqual(space
, BAD_CAST
"preserve")) {
4978 if (xmlStrEqual(space
, BAD_CAST
"default")) {
4989 #ifdef LIBXML_TREE_ENABLED
4992 * @cur: the node being changed
4993 * @name: the new tag name
4995 * Set (or reset) the name of a node.
4998 xmlNodeSetName(xmlNodePtr cur
, const xmlChar
*name
) {
5002 if (cur
== NULL
) return;
5003 if (name
== NULL
) return;
5006 case XML_CDATA_SECTION_NODE
:
5007 case XML_COMMENT_NODE
:
5008 case XML_DOCUMENT_TYPE_NODE
:
5009 case XML_DOCUMENT_FRAG_NODE
:
5010 case XML_NOTATION_NODE
:
5011 case XML_HTML_DOCUMENT_NODE
:
5012 case XML_NAMESPACE_DECL
:
5013 case XML_XINCLUDE_START
:
5014 case XML_XINCLUDE_END
:
5015 #ifdef LIBXML_DOCB_ENABLED
5016 case XML_DOCB_DOCUMENT_NODE
:
5019 case XML_ELEMENT_NODE
:
5020 case XML_ATTRIBUTE_NODE
:
5022 case XML_ENTITY_REF_NODE
:
5023 case XML_ENTITY_NODE
:
5025 case XML_DOCUMENT_NODE
:
5026 case XML_ELEMENT_DECL
:
5027 case XML_ATTRIBUTE_DECL
:
5028 case XML_ENTITY_DECL
:
5037 if ((cur
->name
!= NULL
) && (!xmlDictOwns(dict
, cur
->name
)))
5038 xmlFree((xmlChar
*) cur
->name
);
5039 cur
->name
= xmlDictLookup(dict
, name
, -1);
5041 if (cur
->name
!= NULL
) xmlFree((xmlChar
*) cur
->name
);
5042 cur
->name
= xmlStrdup(name
);
5047 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XINCLUDE_ENABLED)
5050 * @cur: the node being changed
5051 * @uri: the new base URI
5053 * Set (or reset) the base URI of a node, i.e. the value of the
5054 * xml:base attribute.
5057 xmlNodeSetBase(xmlNodePtr cur
, const xmlChar
* uri
) {
5059 const xmlChar
* fixed
;
5061 if (cur
== NULL
) return;
5064 case XML_CDATA_SECTION_NODE
:
5065 case XML_COMMENT_NODE
:
5066 case XML_DOCUMENT_TYPE_NODE
:
5067 case XML_DOCUMENT_FRAG_NODE
:
5068 case XML_NOTATION_NODE
:
5070 case XML_ELEMENT_DECL
:
5071 case XML_ATTRIBUTE_DECL
:
5072 case XML_ENTITY_DECL
:
5074 case XML_ENTITY_REF_NODE
:
5075 case XML_ENTITY_NODE
:
5076 case XML_NAMESPACE_DECL
:
5077 case XML_XINCLUDE_START
:
5078 case XML_XINCLUDE_END
:
5080 case XML_ELEMENT_NODE
:
5081 case XML_ATTRIBUTE_NODE
:
5083 case XML_DOCUMENT_NODE
:
5084 #ifdef LIBXML_DOCB_ENABLED
5085 case XML_DOCB_DOCUMENT_NODE
:
5087 case XML_HTML_DOCUMENT_NODE
: {
5088 xmlDocPtr doc
= (xmlDocPtr
) cur
;
5090 if (doc
->URL
!= NULL
)
5091 xmlFree((xmlChar
*) doc
->URL
);
5095 doc
->URL
= xmlPathToURI(uri
);
5100 ns
= xmlSearchNsByHref(cur
->doc
, cur
, XML_XML_NAMESPACE
);
5103 fixed
= xmlPathToURI(uri
);
5104 if (fixed
!= NULL
) {
5105 xmlSetNsProp(cur
, ns
, BAD_CAST
"base", fixed
);
5106 xmlFree((xmlChar
*)fixed
);
5108 xmlSetNsProp(cur
, ns
, BAD_CAST
"base", uri
);
5111 #endif /* LIBXML_TREE_ENABLED */
5115 * @doc: the document the node pertains to
5116 * @cur: the node being checked
5118 * Searches for the BASE URL. The code should work on both XML
5119 * and HTML document even if base mechanisms are completely different.
5120 * It returns the base as defined in RFC 2396 sections
5121 * 5.1.1. Base URI within Document Content
5123 * 5.1.2. Base URI from the Encapsulating Entity
5124 * However it does not return the document base (5.1.3), use
5125 * xmlDocumentGetBase() for this
5127 * Returns a pointer to the base URL, or NULL if not found
5128 * It's up to the caller to free the memory with xmlFree().
5131 xmlNodeGetBase(xmlDocPtr doc
, xmlNodePtr cur
) {
5132 xmlChar
*oldbase
= NULL
;
5133 xmlChar
*base
, *newbase
;
5135 if ((cur
== NULL
) && (doc
== NULL
))
5137 if (doc
== NULL
) doc
= cur
->doc
;
5138 if ((doc
!= NULL
) && (doc
->type
== XML_HTML_DOCUMENT_NODE
)) {
5139 cur
= doc
->children
;
5140 while ((cur
!= NULL
) && (cur
->name
!= NULL
)) {
5141 if (cur
->type
!= XML_ELEMENT_NODE
) {
5145 if (!xmlStrcasecmp(cur
->name
, BAD_CAST
"html")) {
5146 cur
= cur
->children
;
5149 if (!xmlStrcasecmp(cur
->name
, BAD_CAST
"head")) {
5150 cur
= cur
->children
;
5153 if (!xmlStrcasecmp(cur
->name
, BAD_CAST
"base")) {
5154 return(xmlGetProp(cur
, BAD_CAST
"href"));
5160 while (cur
!= NULL
) {
5161 if (cur
->type
== XML_ENTITY_DECL
) {
5162 xmlEntityPtr ent
= (xmlEntityPtr
) cur
;
5163 return(xmlStrdup(ent
->URI
));
5165 if (cur
->type
== XML_ELEMENT_NODE
) {
5166 base
= xmlGetNsProp(cur
, BAD_CAST
"base", XML_XML_NAMESPACE
);
5168 if (oldbase
!= NULL
) {
5169 newbase
= xmlBuildURI(oldbase
, base
);
5170 if (newbase
!= NULL
) {
5182 if ((!xmlStrncmp(oldbase
, BAD_CAST
"http://", 7)) ||
5183 (!xmlStrncmp(oldbase
, BAD_CAST
"ftp://", 6)) ||
5184 (!xmlStrncmp(oldbase
, BAD_CAST
"urn:", 4)))
5190 if ((doc
!= NULL
) && (doc
->URL
!= NULL
)) {
5191 if (oldbase
== NULL
)
5192 return(xmlStrdup(doc
->URL
));
5193 newbase
= xmlBuildURI(oldbase
, doc
->URL
);
5201 * xmlNodeBufGetContent:
5203 * @cur: the node being read
5205 * Read the value of a node @cur, this can be either the text carried
5206 * directly by this node if it's a TEXT node or the aggregate string
5207 * of the values carried by this node child's (TEXT and ENTITY_REF).
5208 * Entity references are substituted.
5209 * Fills up the buffer @buffer with this value
5211 * Returns 0 in case of success and -1 in case of error.
5214 xmlNodeBufGetContent(xmlBufferPtr buffer
, xmlNodePtr cur
)
5216 if ((cur
== NULL
) || (buffer
== NULL
)) return(-1);
5217 switch (cur
->type
) {
5218 case XML_CDATA_SECTION_NODE
:
5220 xmlBufferCat(buffer
, cur
->content
);
5222 case XML_DOCUMENT_FRAG_NODE
:
5223 case XML_ELEMENT_NODE
:{
5224 xmlNodePtr tmp
= cur
;
5226 while (tmp
!= NULL
) {
5227 switch (tmp
->type
) {
5228 case XML_CDATA_SECTION_NODE
:
5230 if (tmp
->content
!= NULL
)
5231 xmlBufferCat(buffer
, tmp
->content
);
5233 case XML_ENTITY_REF_NODE
:
5234 xmlNodeBufGetContent(buffer
, tmp
);
5242 if (tmp
->children
!= NULL
) {
5243 if (tmp
->children
->type
!= XML_ENTITY_DECL
) {
5244 tmp
= tmp
->children
;
5251 if (tmp
->next
!= NULL
) {
5264 if (tmp
->next
!= NULL
) {
5268 } while (tmp
!= NULL
);
5272 case XML_ATTRIBUTE_NODE
:{
5273 xmlAttrPtr attr
= (xmlAttrPtr
) cur
;
5274 xmlNodePtr tmp
= attr
->children
;
5276 while (tmp
!= NULL
) {
5277 if (tmp
->type
== XML_TEXT_NODE
)
5278 xmlBufferCat(buffer
, tmp
->content
);
5280 xmlNodeBufGetContent(buffer
, tmp
);
5285 case XML_COMMENT_NODE
:
5287 xmlBufferCat(buffer
, cur
->content
);
5289 case XML_ENTITY_REF_NODE
:{
5293 /* lookup entity declaration */
5294 ent
= xmlGetDocEntity(cur
->doc
, cur
->name
);
5298 /* an entity content can be any "well balanced chunk",
5299 * i.e. the result of the content [43] production:
5300 * http://www.w3.org/TR/REC-xml#NT-content
5301 * -> we iterate through child nodes and recursive call
5302 * xmlNodeGetContent() which handles all possible node types */
5303 tmp
= ent
->children
;
5305 xmlNodeBufGetContent(buffer
, tmp
);
5310 case XML_ENTITY_NODE
:
5311 case XML_DOCUMENT_TYPE_NODE
:
5312 case XML_NOTATION_NODE
:
5314 case XML_XINCLUDE_START
:
5315 case XML_XINCLUDE_END
:
5317 case XML_DOCUMENT_NODE
:
5318 #ifdef LIBXML_DOCB_ENABLED
5319 case XML_DOCB_DOCUMENT_NODE
:
5321 case XML_HTML_DOCUMENT_NODE
:
5322 cur
= cur
->children
;
5323 while (cur
!= NULL
) {
5324 if ((cur
->type
== XML_ELEMENT_NODE
) ||
5325 (cur
->type
== XML_TEXT_NODE
) ||
5326 (cur
->type
== XML_CDATA_SECTION_NODE
)) {
5327 xmlNodeBufGetContent(buffer
, cur
);
5332 case XML_NAMESPACE_DECL
:
5333 xmlBufferCat(buffer
, ((xmlNsPtr
) cur
)->href
);
5335 case XML_ELEMENT_DECL
:
5336 case XML_ATTRIBUTE_DECL
:
5337 case XML_ENTITY_DECL
:
5343 * xmlNodeGetContent:
5344 * @cur: the node being read
5346 * Read the value of a node, this can be either the text carried
5347 * directly by this node if it's a TEXT node or the aggregate string
5348 * of the values carried by this node child's (TEXT and ENTITY_REF).
5349 * Entity references are substituted.
5350 * Returns a new #xmlChar * or NULL if no content is available.
5351 * It's up to the caller to free the memory with xmlFree().
5354 xmlNodeGetContent(xmlNodePtr cur
)
5358 switch (cur
->type
) {
5359 case XML_DOCUMENT_FRAG_NODE
:
5360 case XML_ELEMENT_NODE
:{
5361 xmlBufferPtr buffer
;
5364 buffer
= xmlBufferCreateSize(64);
5367 xmlNodeBufGetContent(buffer
, cur
);
5368 ret
= buffer
->content
;
5369 buffer
->content
= NULL
;
5370 xmlBufferFree(buffer
);
5373 case XML_ATTRIBUTE_NODE
:
5374 return(xmlGetPropNodeValueInternal((xmlAttrPtr
) cur
));
5375 case XML_COMMENT_NODE
:
5377 if (cur
->content
!= NULL
)
5378 return (xmlStrdup(cur
->content
));
5380 case XML_ENTITY_REF_NODE
:{
5382 xmlBufferPtr buffer
;
5385 /* lookup entity declaration */
5386 ent
= xmlGetDocEntity(cur
->doc
, cur
->name
);
5390 buffer
= xmlBufferCreate();
5394 xmlNodeBufGetContent(buffer
, cur
);
5396 ret
= buffer
->content
;
5397 buffer
->content
= NULL
;
5398 xmlBufferFree(buffer
);
5401 case XML_ENTITY_NODE
:
5402 case XML_DOCUMENT_TYPE_NODE
:
5403 case XML_NOTATION_NODE
:
5405 case XML_XINCLUDE_START
:
5406 case XML_XINCLUDE_END
:
5408 case XML_DOCUMENT_NODE
:
5409 #ifdef LIBXML_DOCB_ENABLED
5410 case XML_DOCB_DOCUMENT_NODE
:
5412 case XML_HTML_DOCUMENT_NODE
: {
5413 xmlBufferPtr buffer
;
5416 buffer
= xmlBufferCreate();
5420 xmlNodeBufGetContent(buffer
, (xmlNodePtr
) cur
);
5422 ret
= buffer
->content
;
5423 buffer
->content
= NULL
;
5424 xmlBufferFree(buffer
);
5427 case XML_NAMESPACE_DECL
: {
5430 tmp
= xmlStrdup(((xmlNsPtr
) cur
)->href
);
5433 case XML_ELEMENT_DECL
:
5436 case XML_ATTRIBUTE_DECL
:
5439 case XML_ENTITY_DECL
:
5442 case XML_CDATA_SECTION_NODE
:
5444 if (cur
->content
!= NULL
)
5445 return (xmlStrdup(cur
->content
));
5452 * xmlNodeSetContent:
5453 * @cur: the node being modified
5454 * @content: the new value of the content
5456 * Replace the content of a node.
5457 * NOTE: @content is supposed to be a piece of XML CDATA, so it allows entity
5458 * references, but XML special chars need to be escaped first by using
5459 * xmlEncodeEntitiesReentrant() resp. xmlEncodeSpecialChars().
5462 xmlNodeSetContent(xmlNodePtr cur
, const xmlChar
*content
) {
5465 xmlGenericError(xmlGenericErrorContext
,
5466 "xmlNodeSetContent : node == NULL\n");
5470 switch (cur
->type
) {
5471 case XML_DOCUMENT_FRAG_NODE
:
5472 case XML_ELEMENT_NODE
:
5473 case XML_ATTRIBUTE_NODE
:
5474 if (cur
->children
!= NULL
) xmlFreeNodeList(cur
->children
);
5475 cur
->children
= xmlStringGetNodeList(cur
->doc
, content
);
5476 UPDATE_LAST_CHILD_AND_PARENT(cur
)
5479 case XML_CDATA_SECTION_NODE
:
5480 case XML_ENTITY_REF_NODE
:
5481 case XML_ENTITY_NODE
:
5483 case XML_COMMENT_NODE
:
5484 if ((cur
->content
!= NULL
) &&
5485 (cur
->content
!= (xmlChar
*) &(cur
->properties
))) {
5486 if (!((cur
->doc
!= NULL
) && (cur
->doc
->dict
!= NULL
) &&
5487 (xmlDictOwns(cur
->doc
->dict
, cur
->content
))))
5488 xmlFree(cur
->content
);
5490 if (cur
->children
!= NULL
) xmlFreeNodeList(cur
->children
);
5491 cur
->last
= cur
->children
= NULL
;
5492 if (content
!= NULL
) {
5493 cur
->content
= xmlStrdup(content
);
5495 cur
->content
= NULL
;
5496 cur
->properties
= NULL
;
5499 case XML_DOCUMENT_NODE
:
5500 case XML_HTML_DOCUMENT_NODE
:
5501 case XML_DOCUMENT_TYPE_NODE
:
5502 case XML_XINCLUDE_START
:
5503 case XML_XINCLUDE_END
:
5504 #ifdef LIBXML_DOCB_ENABLED
5505 case XML_DOCB_DOCUMENT_NODE
:
5508 case XML_NOTATION_NODE
:
5512 case XML_NAMESPACE_DECL
:
5514 case XML_ELEMENT_DECL
:
5517 case XML_ATTRIBUTE_DECL
:
5520 case XML_ENTITY_DECL
:
5526 #ifdef LIBXML_TREE_ENABLED
5528 * xmlNodeSetContentLen:
5529 * @cur: the node being modified
5530 * @content: the new value of the content
5531 * @len: the size of @content
5533 * Replace the content of a node.
5534 * NOTE: @content is supposed to be a piece of XML CDATA, so it allows entity
5535 * references, but XML special chars need to be escaped first by using
5536 * xmlEncodeEntitiesReentrant() resp. xmlEncodeSpecialChars().
5539 xmlNodeSetContentLen(xmlNodePtr cur
, const xmlChar
*content
, int len
) {
5542 xmlGenericError(xmlGenericErrorContext
,
5543 "xmlNodeSetContentLen : node == NULL\n");
5547 switch (cur
->type
) {
5548 case XML_DOCUMENT_FRAG_NODE
:
5549 case XML_ELEMENT_NODE
:
5550 case XML_ATTRIBUTE_NODE
:
5551 if (cur
->children
!= NULL
) xmlFreeNodeList(cur
->children
);
5552 cur
->children
= xmlStringLenGetNodeList(cur
->doc
, content
, len
);
5553 UPDATE_LAST_CHILD_AND_PARENT(cur
)
5556 case XML_CDATA_SECTION_NODE
:
5557 case XML_ENTITY_REF_NODE
:
5558 case XML_ENTITY_NODE
:
5560 case XML_COMMENT_NODE
:
5561 case XML_NOTATION_NODE
:
5562 if ((cur
->content
!= NULL
) &&
5563 (cur
->content
!= (xmlChar
*) &(cur
->properties
))) {
5564 if (!((cur
->doc
!= NULL
) && (cur
->doc
->dict
!= NULL
) &&
5565 (xmlDictOwns(cur
->doc
->dict
, cur
->content
))))
5566 xmlFree(cur
->content
);
5568 if (cur
->children
!= NULL
) xmlFreeNodeList(cur
->children
);
5569 cur
->children
= cur
->last
= NULL
;
5570 if (content
!= NULL
) {
5571 cur
->content
= xmlStrndup(content
, len
);
5573 cur
->content
= NULL
;
5574 cur
->properties
= NULL
;
5577 case XML_DOCUMENT_NODE
:
5579 case XML_HTML_DOCUMENT_NODE
:
5580 case XML_DOCUMENT_TYPE_NODE
:
5581 case XML_NAMESPACE_DECL
:
5582 case XML_XINCLUDE_START
:
5583 case XML_XINCLUDE_END
:
5584 #ifdef LIBXML_DOCB_ENABLED
5585 case XML_DOCB_DOCUMENT_NODE
:
5588 case XML_ELEMENT_DECL
:
5591 case XML_ATTRIBUTE_DECL
:
5594 case XML_ENTITY_DECL
:
5599 #endif /* LIBXML_TREE_ENABLED */
5602 * xmlNodeAddContentLen:
5603 * @cur: the node being modified
5604 * @content: extra content
5605 * @len: the size of @content
5607 * Append the extra substring to the node content.
5608 * NOTE: In contrast to xmlNodeSetContentLen(), @content is supposed to be
5609 * raw text, so unescaped XML special chars are allowed, entity
5610 * references are not supported.
5613 xmlNodeAddContentLen(xmlNodePtr cur
, const xmlChar
*content
, int len
) {
5616 xmlGenericError(xmlGenericErrorContext
,
5617 "xmlNodeAddContentLen : node == NULL\n");
5621 if (len
<= 0) return;
5622 switch (cur
->type
) {
5623 case XML_DOCUMENT_FRAG_NODE
:
5624 case XML_ELEMENT_NODE
: {
5625 xmlNodePtr last
, newNode
, tmp
;
5628 newNode
= xmlNewTextLen(content
, len
);
5629 if (newNode
!= NULL
) {
5630 tmp
= xmlAddChild(cur
, newNode
);
5633 if ((last
!= NULL
) && (last
->next
== newNode
)) {
5634 xmlTextMerge(last
, newNode
);
5639 case XML_ATTRIBUTE_NODE
:
5642 case XML_CDATA_SECTION_NODE
:
5643 case XML_ENTITY_REF_NODE
:
5644 case XML_ENTITY_NODE
:
5646 case XML_COMMENT_NODE
:
5647 case XML_NOTATION_NODE
:
5648 if (content
!= NULL
) {
5649 if ((cur
->content
== (xmlChar
*) &(cur
->properties
)) ||
5650 ((cur
->doc
!= NULL
) && (cur
->doc
->dict
!= NULL
) &&
5651 xmlDictOwns(cur
->doc
->dict
, cur
->content
))) {
5652 cur
->content
= xmlStrncatNew(cur
->content
, content
, len
);
5653 cur
->properties
= NULL
;
5657 cur
->content
= xmlStrncat(cur
->content
, content
, len
);
5659 case XML_DOCUMENT_NODE
:
5661 case XML_HTML_DOCUMENT_NODE
:
5662 case XML_DOCUMENT_TYPE_NODE
:
5663 case XML_NAMESPACE_DECL
:
5664 case XML_XINCLUDE_START
:
5665 case XML_XINCLUDE_END
:
5666 #ifdef LIBXML_DOCB_ENABLED
5667 case XML_DOCB_DOCUMENT_NODE
:
5670 case XML_ELEMENT_DECL
:
5671 case XML_ATTRIBUTE_DECL
:
5672 case XML_ENTITY_DECL
:
5678 * xmlNodeAddContent:
5679 * @cur: the node being modified
5680 * @content: extra content
5682 * Append the extra substring to the node content.
5683 * NOTE: In contrast to xmlNodeSetContent(), @content is supposed to be
5684 * raw text, so unescaped XML special chars are allowed, entity
5685 * references are not supported.
5688 xmlNodeAddContent(xmlNodePtr cur
, const xmlChar
*content
) {
5693 xmlGenericError(xmlGenericErrorContext
,
5694 "xmlNodeAddContent : node == NULL\n");
5698 if (content
== NULL
) return;
5699 len
= xmlStrlen(content
);
5700 xmlNodeAddContentLen(cur
, content
, len
);
5705 * @first: the first text node
5706 * @second: the second text node being merged
5708 * Merge two text nodes into one
5709 * Returns the first text node augmented
5712 xmlTextMerge(xmlNodePtr first
, xmlNodePtr second
) {
5713 if (first
== NULL
) return(second
);
5714 if (second
== NULL
) return(first
);
5715 if (first
->type
!= XML_TEXT_NODE
) return(first
);
5716 if (second
->type
!= XML_TEXT_NODE
) return(first
);
5717 if (second
->name
!= first
->name
)
5719 xmlNodeAddContent(first
, second
->content
);
5720 xmlUnlinkNode(second
);
5721 xmlFreeNode(second
);
5725 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XPATH_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
5728 * @doc: the document
5729 * @node: the current node
5731 * Search all the namespace applying to a given element.
5732 * Returns an NULL terminated array of all the #xmlNsPtr found
5733 * that need to be freed by the caller or NULL if no
5734 * namespace if defined
5737 xmlGetNsList(xmlDocPtr doc ATTRIBUTE_UNUSED
, xmlNodePtr node
)
5740 xmlNsPtr
*ret
= NULL
;
5745 while (node
!= NULL
) {
5746 if (node
->type
== XML_ELEMENT_NODE
) {
5748 while (cur
!= NULL
) {
5751 (xmlNsPtr
*) xmlMalloc((maxns
+ 1) *
5754 xmlTreeErrMemory("getting namespace list");
5759 for (i
= 0; i
< nbns
; i
++) {
5760 if ((cur
->prefix
== ret
[i
]->prefix
) ||
5761 (xmlStrEqual(cur
->prefix
, ret
[i
]->prefix
)))
5765 if (nbns
>= maxns
) {
5767 ret
= (xmlNsPtr
*) xmlRealloc(ret
,
5772 xmlTreeErrMemory("getting namespace list");
5783 node
= node
->parent
;
5787 #endif /* LIBXML_TREE_ENABLED */
5790 * xmlTreeEnsureXMLDecl:
5793 * Ensures that there is an XML namespace declaration on the doc.
5795 * Returns the XML ns-struct or NULL on API and internal errors.
5798 xmlTreeEnsureXMLDecl(xmlDocPtr doc
)
5802 if (doc
->oldNs
!= NULL
)
5803 return (doc
->oldNs
);
5806 ns
= (xmlNsPtr
) xmlMalloc(sizeof(xmlNs
));
5809 "allocating the XML namespace");
5812 memset(ns
, 0, sizeof(xmlNs
));
5813 ns
->type
= XML_LOCAL_NAMESPACE
;
5814 ns
->href
= xmlStrdup(XML_XML_NAMESPACE
);
5815 ns
->prefix
= xmlStrdup((const xmlChar
*)"xml");
5823 * @doc: the document
5824 * @node: the current node
5825 * @nameSpace: the namespace prefix
5827 * Search a Ns registered under a given name space for a document.
5828 * recurse on the parents until it finds the defined namespace
5829 * or return NULL otherwise.
5830 * @nameSpace can be NULL, this is a search for the default namespace.
5831 * We don't allow to cross entities boundaries. If you don't declare
5832 * the namespace within those you will be in troubles !!! A warning
5833 * is generated to cover this case.
5835 * Returns the namespace pointer or NULL.
5838 xmlSearchNs(xmlDocPtr doc
, xmlNodePtr node
, const xmlChar
*nameSpace
) {
5841 xmlNodePtr orig
= node
;
5843 if (node
== NULL
) return(NULL
);
5844 if ((nameSpace
!= NULL
) &&
5845 (xmlStrEqual(nameSpace
, (const xmlChar
*)"xml"))) {
5846 if ((doc
== NULL
) && (node
->type
== XML_ELEMENT_NODE
)) {
5848 * The XML-1.0 namespace is normally held on the root
5849 * element. In this case exceptionally create it on the
5852 cur
= (xmlNsPtr
) xmlMalloc(sizeof(xmlNs
));
5854 xmlTreeErrMemory("searching namespace");
5857 memset(cur
, 0, sizeof(xmlNs
));
5858 cur
->type
= XML_LOCAL_NAMESPACE
;
5859 cur
->href
= xmlStrdup(XML_XML_NAMESPACE
);
5860 cur
->prefix
= xmlStrdup((const xmlChar
*)"xml");
5861 cur
->next
= node
->nsDef
;
5871 * Return the XML namespace declaration held by the doc.
5873 if (doc
->oldNs
== NULL
)
5874 return(xmlTreeEnsureXMLDecl(doc
));
5878 while (node
!= NULL
) {
5879 if ((node
->type
== XML_ENTITY_REF_NODE
) ||
5880 (node
->type
== XML_ENTITY_NODE
) ||
5881 (node
->type
== XML_ENTITY_DECL
))
5883 if (node
->type
== XML_ELEMENT_NODE
) {
5885 while (cur
!= NULL
) {
5886 if ((cur
->prefix
== NULL
) && (nameSpace
== NULL
) &&
5887 (cur
->href
!= NULL
))
5889 if ((cur
->prefix
!= NULL
) && (nameSpace
!= NULL
) &&
5890 (cur
->href
!= NULL
) &&
5891 (xmlStrEqual(cur
->prefix
, nameSpace
)))
5898 if ((cur
->prefix
== NULL
) && (nameSpace
== NULL
) &&
5899 (cur
->href
!= NULL
))
5901 if ((cur
->prefix
!= NULL
) && (nameSpace
!= NULL
) &&
5902 (cur
->href
!= NULL
) &&
5903 (xmlStrEqual(cur
->prefix
, nameSpace
)))
5908 node
= node
->parent
;
5915 * @doc: the document
5916 * @node: the current node
5917 * @ancestor: the ancestor carrying the namespace
5918 * @prefix: the namespace prefix
5920 * Verify that the given namespace held on @ancestor is still in scope
5923 * Returns 1 if true, 0 if false and -1 in case of error.
5926 xmlNsInScope(xmlDocPtr doc ATTRIBUTE_UNUSED
, xmlNodePtr node
,
5927 xmlNodePtr ancestor
, const xmlChar
* prefix
)
5931 while ((node
!= NULL
) && (node
!= ancestor
)) {
5932 if ((node
->type
== XML_ENTITY_REF_NODE
) ||
5933 (node
->type
== XML_ENTITY_NODE
) ||
5934 (node
->type
== XML_ENTITY_DECL
))
5936 if (node
->type
== XML_ELEMENT_NODE
) {
5938 while (tst
!= NULL
) {
5939 if ((tst
->prefix
== NULL
)
5940 && (prefix
== NULL
))
5942 if ((tst
->prefix
!= NULL
)
5944 && (xmlStrEqual(tst
->prefix
, prefix
)))
5949 node
= node
->parent
;
5951 if (node
!= ancestor
)
5957 * xmlSearchNsByHref:
5958 * @doc: the document
5959 * @node: the current node
5960 * @href: the namespace value
5962 * Search a Ns aliasing a given URI. Recurse on the parents until it finds
5963 * the defined namespace or return NULL otherwise.
5964 * Returns the namespace pointer or NULL.
5967 xmlSearchNsByHref(xmlDocPtr doc
, xmlNodePtr node
, const xmlChar
* href
)
5970 xmlNodePtr orig
= node
;
5973 if ((node
== NULL
) || (href
== NULL
))
5975 if (xmlStrEqual(href
, XML_XML_NAMESPACE
)) {
5977 * Only the document can hold the XML spec namespace.
5979 if ((doc
== NULL
) && (node
->type
== XML_ELEMENT_NODE
)) {
5981 * The XML-1.0 namespace is normally held on the root
5982 * element. In this case exceptionally create it on the
5985 cur
= (xmlNsPtr
) xmlMalloc(sizeof(xmlNs
));
5987 xmlTreeErrMemory("searching namespace");
5990 memset(cur
, 0, sizeof(xmlNs
));
5991 cur
->type
= XML_LOCAL_NAMESPACE
;
5992 cur
->href
= xmlStrdup(XML_XML_NAMESPACE
);
5993 cur
->prefix
= xmlStrdup((const xmlChar
*) "xml");
5994 cur
->next
= node
->nsDef
;
6004 * Return the XML namespace declaration held by the doc.
6006 if (doc
->oldNs
== NULL
)
6007 return(xmlTreeEnsureXMLDecl(doc
));
6011 is_attr
= (node
->type
== XML_ATTRIBUTE_NODE
);
6012 while (node
!= NULL
) {
6013 if ((node
->type
== XML_ENTITY_REF_NODE
) ||
6014 (node
->type
== XML_ENTITY_NODE
) ||
6015 (node
->type
== XML_ENTITY_DECL
))
6017 if (node
->type
== XML_ELEMENT_NODE
) {
6019 while (cur
!= NULL
) {
6020 if ((cur
->href
!= NULL
) && (href
!= NULL
) &&
6021 (xmlStrEqual(cur
->href
, href
))) {
6022 if (((!is_attr
) || (cur
->prefix
!= NULL
)) &&
6023 (xmlNsInScope(doc
, orig
, node
, cur
->prefix
) == 1))
6031 if ((cur
->href
!= NULL
) && (href
!= NULL
) &&
6032 (xmlStrEqual(cur
->href
, href
))) {
6033 if (((!is_attr
) || (cur
->prefix
!= NULL
)) &&
6034 (xmlNsInScope(doc
, orig
, node
, cur
->prefix
) == 1))
6040 node
= node
->parent
;
6046 * xmlNewReconciliedNs:
6047 * @doc: the document
6048 * @tree: a node expected to hold the new namespace
6049 * @ns: the original namespace
6051 * This function tries to locate a namespace definition in a tree
6052 * ancestors, or create a new namespace definition node similar to
6053 * @ns trying to reuse the same prefix. However if the given prefix is
6054 * null (default namespace) or reused within the subtree defined by
6055 * @tree or on one of its ancestors then a new prefix is generated.
6056 * Returns the (new) namespace definition or NULL in case of error
6059 xmlNewReconciliedNs(xmlDocPtr doc
, xmlNodePtr tree
, xmlNsPtr ns
) {
6066 xmlGenericError(xmlGenericErrorContext
,
6067 "xmlNewReconciliedNs : tree == NULL\n");
6071 if ((ns
== NULL
) || (ns
->type
!= XML_NAMESPACE_DECL
)) {
6073 xmlGenericError(xmlGenericErrorContext
,
6074 "xmlNewReconciliedNs : ns == NULL\n");
6079 * Search an existing namespace definition inherited.
6081 def
= xmlSearchNsByHref(doc
, tree
, ns
->href
);
6086 * Find a close prefix which is not already in use.
6087 * Let's strip namespace prefixes longer than 20 chars !
6089 if (ns
->prefix
== NULL
)
6090 snprintf((char *) prefix
, sizeof(prefix
), "default");
6092 snprintf((char *) prefix
, sizeof(prefix
), "%.20s", (char *)ns
->prefix
);
6094 def
= xmlSearchNs(doc
, tree
, prefix
);
6095 while (def
!= NULL
) {
6096 if (counter
> 1000) return(NULL
);
6097 if (ns
->prefix
== NULL
)
6098 snprintf((char *) prefix
, sizeof(prefix
), "default%d", counter
++);
6100 snprintf((char *) prefix
, sizeof(prefix
), "%.20s%d",
6101 (char *)ns
->prefix
, counter
++);
6102 def
= xmlSearchNs(doc
, tree
, prefix
);
6106 * OK, now we are ready to create a new one.
6108 def
= xmlNewNs(tree
, ns
->href
, prefix
);
6112 #ifdef LIBXML_TREE_ENABLED
6114 * xmlReconciliateNs:
6115 * @doc: the document
6116 * @tree: a node defining the subtree to reconciliate
6118 * This function checks that all the namespaces declared within the given
6119 * tree are properly declared. This is needed for example after Copy or Cut
6120 * and then paste operations. The subtree may still hold pointers to
6121 * namespace declarations outside the subtree or invalid/masked. As much
6122 * as possible the function try to reuse the existing namespaces found in
6123 * the new environment. If not possible the new namespaces are redeclared
6124 * on @tree at the top of the given subtree.
6125 * Returns the number of namespace declarations created or -1 in case of error.
6128 xmlReconciliateNs(xmlDocPtr doc
, xmlNodePtr tree
) {
6129 xmlNsPtr
*oldNs
= NULL
;
6130 xmlNsPtr
*newNs
= NULL
;
6135 xmlNodePtr node
= tree
;
6139 if ((node
== NULL
) || (node
->type
!= XML_ELEMENT_NODE
)) return(-1);
6140 if ((doc
== NULL
) || (doc
->type
!= XML_DOCUMENT_NODE
)) return(-1);
6141 if (node
->doc
!= doc
) return(-1);
6142 while (node
!= NULL
) {
6144 * Reconciliate the node namespace
6146 if (node
->ns
!= NULL
) {
6148 * initialize the cache if needed
6150 if (sizeCache
== 0) {
6152 oldNs
= (xmlNsPtr
*) xmlMalloc(sizeCache
*
6154 if (oldNs
== NULL
) {
6155 xmlTreeErrMemory("fixing namespaces");
6158 newNs
= (xmlNsPtr
*) xmlMalloc(sizeCache
*
6160 if (newNs
== NULL
) {
6161 xmlTreeErrMemory("fixing namespaces");
6166 for (i
= 0;i
< nbCache
;i
++) {
6167 if (oldNs
[i
] == node
->ns
) {
6168 node
->ns
= newNs
[i
];
6174 * OK we need to recreate a new namespace definition
6176 n
= xmlNewReconciliedNs(doc
, tree
, node
->ns
);
6177 if (n
!= NULL
) { /* :-( what if else ??? */
6179 * check if we need to grow the cache buffers.
6181 if (sizeCache
<= nbCache
) {
6183 oldNs
= (xmlNsPtr
*) xmlRealloc(oldNs
, sizeCache
*
6185 if (oldNs
== NULL
) {
6186 xmlTreeErrMemory("fixing namespaces");
6190 newNs
= (xmlNsPtr
*) xmlRealloc(newNs
, sizeCache
*
6192 if (newNs
== NULL
) {
6193 xmlTreeErrMemory("fixing namespaces");
6199 oldNs
[nbCache
++] = node
->ns
;
6205 * now check for namespace hold by attributes on the node.
6207 if (node
->type
== XML_ELEMENT_NODE
) {
6208 attr
= node
->properties
;
6209 while (attr
!= NULL
) {
6210 if (attr
->ns
!= NULL
) {
6212 * initialize the cache if needed
6214 if (sizeCache
== 0) {
6216 oldNs
= (xmlNsPtr
*) xmlMalloc(sizeCache
*
6218 if (oldNs
== NULL
) {
6219 xmlTreeErrMemory("fixing namespaces");
6222 newNs
= (xmlNsPtr
*) xmlMalloc(sizeCache
*
6224 if (newNs
== NULL
) {
6225 xmlTreeErrMemory("fixing namespaces");
6230 for (i
= 0;i
< nbCache
;i
++) {
6231 if (oldNs
[i
] == attr
->ns
) {
6232 attr
->ns
= newNs
[i
];
6238 * OK we need to recreate a new namespace definition
6240 n
= xmlNewReconciliedNs(doc
, tree
, attr
->ns
);
6241 if (n
!= NULL
) { /* :-( what if else ??? */
6243 * check if we need to grow the cache buffers.
6245 if (sizeCache
<= nbCache
) {
6247 oldNs
= (xmlNsPtr
*) xmlRealloc(oldNs
,
6248 sizeCache
* sizeof(xmlNsPtr
));
6249 if (oldNs
== NULL
) {
6250 xmlTreeErrMemory("fixing namespaces");
6254 newNs
= (xmlNsPtr
*) xmlRealloc(newNs
,
6255 sizeCache
* sizeof(xmlNsPtr
));
6256 if (newNs
== NULL
) {
6257 xmlTreeErrMemory("fixing namespaces");
6263 oldNs
[nbCache
++] = attr
->ns
;
6273 * Browse the full subtree, deep first
6275 if ((node
->children
!= NULL
) && (node
->type
!= XML_ENTITY_REF_NODE
)) {
6277 node
= node
->children
;
6278 } else if ((node
!= tree
) && (node
->next
!= NULL
)) {
6281 } else if (node
!= tree
) {
6282 /* go up to parents->next if needed */
6283 while (node
!= tree
) {
6284 if (node
->parent
!= NULL
)
6285 node
= node
->parent
;
6286 if ((node
!= tree
) && (node
->next
!= NULL
)) {
6290 if (node
->parent
== NULL
) {
6295 /* exit condition */
6307 #endif /* LIBXML_TREE_ENABLED */
6310 xmlGetPropNodeInternal(xmlNodePtr node
, const xmlChar
*name
,
6311 const xmlChar
*nsName
, int useDTD
)
6315 if ((node
== NULL
) || (node
->type
!= XML_ELEMENT_NODE
) || (name
== NULL
))
6318 if (node
->properties
!= NULL
) {
6319 prop
= node
->properties
;
6320 if (nsName
== NULL
) {
6322 * We want the attr to be in no namespace.
6325 if ((prop
->ns
== NULL
) && xmlStrEqual(prop
->name
, name
)) {
6329 } while (prop
!= NULL
);
6332 * We want the attr to be in the specified namespace.
6335 if ((prop
->ns
!= NULL
) && xmlStrEqual(prop
->name
, name
) &&
6336 ((prop
->ns
->href
== nsName
) ||
6337 xmlStrEqual(prop
->ns
->href
, nsName
)))
6342 } while (prop
!= NULL
);
6346 #ifdef LIBXML_TREE_ENABLED
6350 * Check if there is a default/fixed attribute declaration in
6351 * the internal or external subset.
6353 if ((node
->doc
!= NULL
) && (node
->doc
->intSubset
!= NULL
)) {
6354 xmlDocPtr doc
= node
->doc
;
6355 xmlAttributePtr attrDecl
= NULL
;
6356 xmlChar
*elemQName
, *tmpstr
= NULL
;
6359 * We need the QName of the element for the DTD-lookup.
6361 if ((node
->ns
!= NULL
) && (node
->ns
->prefix
!= NULL
)) {
6362 tmpstr
= xmlStrdup(node
->ns
->prefix
);
6363 tmpstr
= xmlStrcat(tmpstr
, BAD_CAST
":");
6364 tmpstr
= xmlStrcat(tmpstr
, node
->name
);
6369 elemQName
= (xmlChar
*) node
->name
;
6370 if (nsName
== NULL
) {
6372 * The common and nice case: Attr in no namespace.
6374 attrDecl
= xmlGetDtdQAttrDesc(doc
->intSubset
,
6375 elemQName
, name
, NULL
);
6376 if ((attrDecl
== NULL
) && (doc
->extSubset
!= NULL
)) {
6377 attrDecl
= xmlGetDtdQAttrDesc(doc
->extSubset
,
6378 elemQName
, name
, NULL
);
6381 xmlNsPtr
*nsList
, *cur
;
6384 * The ugly case: Search using the prefixes of in-scope
6385 * ns-decls corresponding to @nsName.
6387 nsList
= xmlGetNsList(node
->doc
, node
);
6388 if (nsList
== NULL
) {
6394 while (*cur
!= NULL
) {
6395 if (xmlStrEqual((*cur
)->href
, nsName
)) {
6396 attrDecl
= xmlGetDtdQAttrDesc(doc
->intSubset
, elemQName
,
6397 name
, (*cur
)->prefix
);
6400 if (doc
->extSubset
!= NULL
) {
6401 attrDecl
= xmlGetDtdQAttrDesc(doc
->extSubset
, elemQName
,
6402 name
, (*cur
)->prefix
);
6414 * Only default/fixed attrs are relevant.
6416 if ((attrDecl
!= NULL
) && (attrDecl
->defaultValue
!= NULL
))
6417 return((xmlAttrPtr
) attrDecl
);
6419 #endif /* LIBXML_TREE_ENABLED */
6424 xmlGetPropNodeValueInternal(xmlAttrPtr prop
)
6428 if (prop
->type
== XML_ATTRIBUTE_NODE
) {
6430 * Note that we return at least the empty string.
6431 * TODO: Do we really always want that?
6433 if (prop
->children
!= NULL
) {
6434 if ((prop
->children
->next
== NULL
) &&
6435 ((prop
->children
->type
== XML_TEXT_NODE
) ||
6436 (prop
->children
->type
== XML_CDATA_SECTION_NODE
)))
6439 * Optimization for the common case: only 1 text node.
6441 return(xmlStrdup(prop
->children
->content
));
6445 ret
= xmlNodeListGetString(prop
->doc
, prop
->children
, 1);
6450 return(xmlStrdup((xmlChar
*)""));
6451 } else if (prop
->type
== XML_ATTRIBUTE_DECL
) {
6452 return(xmlStrdup(((xmlAttributePtr
)prop
)->defaultValue
));
6460 * @name: the attribute name
6462 * Search an attribute associated to a node
6463 * This function also looks in DTD attribute declaration for #FIXED or
6464 * default declaration values unless DTD use has been turned off.
6466 * Returns the attribute or the attribute declaration or NULL if
6467 * neither was found.
6470 xmlHasProp(xmlNodePtr node
, const xmlChar
*name
) {
6474 if ((node
== NULL
) || (node
->type
!= XML_ELEMENT_NODE
) || (name
== NULL
))
6477 * Check on the properties attached to the node
6479 prop
= node
->properties
;
6480 while (prop
!= NULL
) {
6481 if (xmlStrEqual(prop
->name
, name
)) {
6486 if (!xmlCheckDTD
) return(NULL
);
6489 * Check if there is a default declaration in the internal
6490 * or external subsets
6494 xmlAttributePtr attrDecl
;
6495 if (doc
->intSubset
!= NULL
) {
6496 attrDecl
= xmlGetDtdAttrDesc(doc
->intSubset
, node
->name
, name
);
6497 if ((attrDecl
== NULL
) && (doc
->extSubset
!= NULL
))
6498 attrDecl
= xmlGetDtdAttrDesc(doc
->extSubset
, node
->name
, name
);
6499 if ((attrDecl
!= NULL
) && (attrDecl
->defaultValue
!= NULL
))
6500 /* return attribute declaration only if a default value is given
6501 (that includes #FIXED declarations) */
6502 return((xmlAttrPtr
) attrDecl
);
6511 * @name: the attribute name
6512 * @nameSpace: the URI of the namespace
6514 * Search for an attribute associated to a node
6515 * This attribute has to be anchored in the namespace specified.
6516 * This does the entity substitution.
6517 * This function looks in DTD attribute declaration for #FIXED or
6518 * default declaration values unless DTD use has been turned off.
6519 * Note that a namespace of NULL indicates to use the default namespace.
6521 * Returns the attribute or the attribute declaration or NULL
6522 * if neither was found.
6525 xmlHasNsProp(xmlNodePtr node
, const xmlChar
*name
, const xmlChar
*nameSpace
) {
6527 return(xmlGetPropNodeInternal(node
, name
, nameSpace
, xmlCheckDTD
));
6533 * @name: the attribute name
6535 * Search and get the value of an attribute associated to a node
6536 * This does the entity substitution.
6537 * This function looks in DTD attribute declaration for #FIXED or
6538 * default declaration values unless DTD use has been turned off.
6539 * NOTE: this function acts independently of namespaces associated
6540 * to the attribute. Use xmlGetNsProp() or xmlGetNoNsProp()
6541 * for namespace aware processing.
6543 * Returns the attribute value or NULL if not found.
6544 * It's up to the caller to free the memory with xmlFree().
6547 xmlGetProp(xmlNodePtr node
, const xmlChar
*name
) {
6550 prop
= xmlHasProp(node
, name
);
6553 return(xmlGetPropNodeValueInternal(prop
));
6559 * @name: the attribute name
6561 * Search and get the value of an attribute associated to a node
6562 * This does the entity substitution.
6563 * This function looks in DTD attribute declaration for #FIXED or
6564 * default declaration values unless DTD use has been turned off.
6565 * This function is similar to xmlGetProp except it will accept only
6566 * an attribute in no namespace.
6568 * Returns the attribute value or NULL if not found.
6569 * It's up to the caller to free the memory with xmlFree().
6572 xmlGetNoNsProp(xmlNodePtr node
, const xmlChar
*name
) {
6575 prop
= xmlGetPropNodeInternal(node
, name
, NULL
, xmlCheckDTD
);
6578 return(xmlGetPropNodeValueInternal(prop
));
6584 * @name: the attribute name
6585 * @nameSpace: the URI of the namespace
6587 * Search and get the value of an attribute associated to a node
6588 * This attribute has to be anchored in the namespace specified.
6589 * This does the entity substitution.
6590 * This function looks in DTD attribute declaration for #FIXED or
6591 * default declaration values unless DTD use has been turned off.
6593 * Returns the attribute value or NULL if not found.
6594 * It's up to the caller to free the memory with xmlFree().
6597 xmlGetNsProp(xmlNodePtr node
, const xmlChar
*name
, const xmlChar
*nameSpace
) {
6600 prop
= xmlGetPropNodeInternal(node
, name
, nameSpace
, xmlCheckDTD
);
6603 return(xmlGetPropNodeValueInternal(prop
));
6606 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
6610 * @name: the attribute name
6612 * Remove an attribute carried by a node.
6613 * This handles only attributes in no namespace.
6614 * Returns 0 if successful, -1 if not found
6617 xmlUnsetProp(xmlNodePtr node
, const xmlChar
*name
) {
6620 prop
= xmlGetPropNodeInternal(node
, name
, NULL
, 0);
6623 xmlUnlinkNode((xmlNodePtr
) prop
);
6631 * @ns: the namespace definition
6632 * @name: the attribute name
6634 * Remove an attribute carried by a node.
6635 * Returns 0 if successful, -1 if not found
6638 xmlUnsetNsProp(xmlNodePtr node
, xmlNsPtr ns
, const xmlChar
*name
) {
6641 prop
= xmlGetPropNodeInternal(node
, name
, (ns
!= NULL
) ? ns
->href
: NULL
, 0);
6644 xmlUnlinkNode((xmlNodePtr
) prop
);
6650 #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XINCLUDE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) || defined(LIBXML_HTML_ENABLED)
6654 * @name: the attribute name (a QName)
6655 * @value: the attribute value
6657 * Set (or reset) an attribute carried by a node.
6658 * If @name has a prefix, then the corresponding
6659 * namespace-binding will be used, if in scope; it is an
6660 * error it there's no such ns-binding for the prefix in
6662 * Returns the attribute pointer.
6666 xmlSetProp(xmlNodePtr node
, const xmlChar
*name
, const xmlChar
*value
) {
6668 const xmlChar
*nqname
;
6670 if ((node
== NULL
) || (name
== NULL
) || (node
->type
!= XML_ELEMENT_NODE
))
6676 nqname
= xmlSplitQName3(name
, &len
);
6677 if (nqname
!= NULL
) {
6679 xmlChar
*prefix
= xmlStrndup(name
, len
);
6680 ns
= xmlSearchNs(node
->doc
, node
, prefix
);
6684 return(xmlSetNsProp(node
, ns
, nqname
, value
));
6686 return(xmlSetNsProp(node
, NULL
, name
, value
));
6692 * @ns: the namespace definition
6693 * @name: the attribute name
6694 * @value: the attribute value
6696 * Set (or reset) an attribute carried by a node.
6697 * The ns structure must be in scope, this is not checked
6699 * Returns the attribute pointer.
6702 xmlSetNsProp(xmlNodePtr node
, xmlNsPtr ns
, const xmlChar
*name
,
6703 const xmlChar
*value
)
6707 if (ns
&& (ns
->href
== NULL
))
6709 prop
= xmlGetPropNodeInternal(node
, name
, (ns
!= NULL
) ? ns
->href
: NULL
, 0);
6712 * Modify the attribute's value.
6714 if (prop
->atype
== XML_ATTRIBUTE_ID
) {
6715 xmlRemoveID(node
->doc
, prop
);
6716 prop
->atype
= XML_ATTRIBUTE_ID
;
6718 if (prop
->children
!= NULL
)
6719 xmlFreeNodeList(prop
->children
);
6720 prop
->children
= NULL
;
6723 if (value
!= NULL
) {
6726 if(!xmlCheckUTF8(value
)) {
6727 xmlTreeErr(XML_TREE_NOT_UTF8
, (xmlNodePtr
) node
->doc
,
6729 if (node
->doc
!= NULL
)
6730 node
->doc
->encoding
= xmlStrdup(BAD_CAST
"ISO-8859-1");
6732 prop
->children
= xmlNewDocText(node
->doc
, value
);
6734 tmp
= prop
->children
;
6735 while (tmp
!= NULL
) {
6736 tmp
->parent
= (xmlNodePtr
) prop
;
6737 if (tmp
->next
== NULL
)
6742 if (prop
->atype
== XML_ATTRIBUTE_ID
)
6743 xmlAddID(NULL
, node
->doc
, value
, prop
);
6747 * No equal attr found; create a new one.
6749 return(xmlNewPropInternal(node
, ns
, name
, value
, 0));
6752 #endif /* LIBXML_TREE_ENABLED */
6758 * Is this node a Text node ?
6759 * Returns 1 yes, 0 no
6762 xmlNodeIsText(xmlNodePtr node
) {
6763 if (node
== NULL
) return(0);
6765 if (node
->type
== XML_TEXT_NODE
) return(1);
6773 * Checks whether this node is an empty or whitespace only
6774 * (and possibly ignorable) text-node.
6776 * Returns 1 yes, 0 no
6779 xmlIsBlankNode(xmlNodePtr node
) {
6781 if (node
== NULL
) return(0);
6783 if ((node
->type
!= XML_TEXT_NODE
) &&
6784 (node
->type
!= XML_CDATA_SECTION_NODE
))
6786 if (node
->content
== NULL
) return(1);
6787 cur
= node
->content
;
6789 if (!IS_BLANK_CH(*cur
)) return(0);
6799 * @content: the content
6800 * @len: @content length
6802 * Concat the given string at the end of the existing node content
6804 * Returns -1 in case of error, 0 otherwise
6808 xmlTextConcat(xmlNodePtr node
, const xmlChar
*content
, int len
) {
6809 if (node
== NULL
) return(-1);
6811 if ((node
->type
!= XML_TEXT_NODE
) &&
6812 (node
->type
!= XML_CDATA_SECTION_NODE
) &&
6813 (node
->type
!= XML_COMMENT_NODE
) &&
6814 (node
->type
!= XML_PI_NODE
)) {
6816 xmlGenericError(xmlGenericErrorContext
,
6817 "xmlTextConcat: node is not text nor CDATA\n");
6821 /* need to check if content is currently in the dictionary */
6822 if ((node
->content
== (xmlChar
*) &(node
->properties
)) ||
6823 ((node
->doc
!= NULL
) && (node
->doc
->dict
!= NULL
) &&
6824 xmlDictOwns(node
->doc
->dict
, node
->content
))) {
6825 node
->content
= xmlStrncatNew(node
->content
, content
, len
);
6827 node
->content
= xmlStrncat(node
->content
, content
, len
);
6829 node
->properties
= NULL
;
6830 if (node
->content
== NULL
)
6835 /************************************************************************
6837 * Output : to a FILE or in memory *
6839 ************************************************************************/
6844 * routine to create an XML buffer.
6845 * returns the new structure.
6848 xmlBufferCreate(void) {
6851 ret
= (xmlBufferPtr
) xmlMalloc(sizeof(xmlBuffer
));
6853 xmlTreeErrMemory("creating buffer");
6857 ret
->size
= xmlDefaultBufferSize
;
6858 ret
->alloc
= xmlBufferAllocScheme
;
6859 ret
->content
= (xmlChar
*) xmlMallocAtomic(ret
->size
* sizeof(xmlChar
));
6860 if (ret
->content
== NULL
) {
6861 xmlTreeErrMemory("creating buffer");
6865 ret
->content
[0] = 0;
6866 ret
->contentIO
= NULL
;
6871 * xmlBufferCreateSize:
6872 * @size: initial size of buffer
6874 * routine to create an XML buffer.
6875 * returns the new structure.
6878 xmlBufferCreateSize(size_t size
) {
6881 ret
= (xmlBufferPtr
) xmlMalloc(sizeof(xmlBuffer
));
6883 xmlTreeErrMemory("creating buffer");
6887 ret
->alloc
= xmlBufferAllocScheme
;
6888 ret
->size
= (size
? size
+2 : 0); /* +1 for ending null */
6890 ret
->content
= (xmlChar
*) xmlMallocAtomic(ret
->size
* sizeof(xmlChar
));
6891 if (ret
->content
== NULL
) {
6892 xmlTreeErrMemory("creating buffer");
6896 ret
->content
[0] = 0;
6898 ret
->content
= NULL
;
6899 ret
->contentIO
= NULL
;
6904 * xmlBufferCreateStatic:
6905 * @mem: the memory area
6906 * @size: the size in byte
6908 * routine to create an XML buffer from an immutable memory area.
6909 * The area won't be modified nor copied, and is expected to be
6910 * present until the end of the buffer lifetime.
6912 * returns the new structure.
6915 xmlBufferCreateStatic(void *mem
, size_t size
) {
6918 if ((mem
== NULL
) || (size
== 0))
6921 ret
= (xmlBufferPtr
) xmlMalloc(sizeof(xmlBuffer
));
6923 xmlTreeErrMemory("creating buffer");
6928 ret
->alloc
= XML_BUFFER_ALLOC_IMMUTABLE
;
6929 ret
->content
= (xmlChar
*) mem
;
6934 * xmlBufferSetAllocationScheme:
6935 * @buf: the buffer to tune
6936 * @scheme: allocation scheme to use
6938 * Sets the allocation scheme for this buffer
6941 xmlBufferSetAllocationScheme(xmlBufferPtr buf
,
6942 xmlBufferAllocationScheme scheme
) {
6945 xmlGenericError(xmlGenericErrorContext
,
6946 "xmlBufferSetAllocationScheme: buf == NULL\n");
6950 if ((buf
->alloc
== XML_BUFFER_ALLOC_IMMUTABLE
) ||
6951 (buf
->alloc
== XML_BUFFER_ALLOC_IO
)) return;
6952 if ((scheme
== XML_BUFFER_ALLOC_DOUBLEIT
) ||
6953 (scheme
== XML_BUFFER_ALLOC_EXACT
) ||
6954 (scheme
== XML_BUFFER_ALLOC_IMMUTABLE
))
6955 buf
->alloc
= scheme
;
6960 * @buf: the buffer to free
6962 * Frees an XML buffer. It frees both the content and the structure which
6966 xmlBufferFree(xmlBufferPtr buf
) {
6969 xmlGenericError(xmlGenericErrorContext
,
6970 "xmlBufferFree: buf == NULL\n");
6975 if ((buf
->alloc
== XML_BUFFER_ALLOC_IO
) &&
6976 (buf
->contentIO
!= NULL
)) {
6977 xmlFree(buf
->contentIO
);
6978 } else if ((buf
->content
!= NULL
) &&
6979 (buf
->alloc
!= XML_BUFFER_ALLOC_IMMUTABLE
)) {
6980 xmlFree(buf
->content
);
6992 xmlBufferEmpty(xmlBufferPtr buf
) {
6993 if (buf
== NULL
) return;
6994 if (buf
->content
== NULL
) return;
6996 if (buf
->alloc
== XML_BUFFER_ALLOC_IMMUTABLE
) {
6997 buf
->content
= BAD_CAST
"";
6998 } else if ((buf
->alloc
== XML_BUFFER_ALLOC_IO
) &&
6999 (buf
->contentIO
!= NULL
)) {
7000 size_t start_buf
= buf
->content
- buf
->contentIO
;
7002 buf
->size
+= start_buf
;
7003 buf
->content
= buf
->contentIO
;
7004 buf
->content
[0] = 0;
7006 buf
->content
[0] = 0;
7012 * @buf: the buffer to dump
7013 * @len: the number of xmlChar to remove
7015 * Remove the beginning of an XML buffer.
7017 * Returns the number of #xmlChar removed, or -1 in case of failure.
7020 xmlBufferShrink(xmlBufferPtr buf
, unsigned int len
) {
7021 if (buf
== NULL
) return(-1);
7022 if (len
== 0) return(0);
7023 if (len
> buf
->use
) return(-1);
7026 if ((buf
->alloc
== XML_BUFFER_ALLOC_IMMUTABLE
) ||
7027 ((buf
->alloc
== XML_BUFFER_ALLOC_IO
) && (buf
->contentIO
!= NULL
))) {
7029 * we just move the content pointer, but also make sure
7030 * the perceived buffer size has shrinked accordingly
7032 buf
->content
+= len
;
7036 * sometimes though it maybe be better to really shrink
7039 if ((buf
->alloc
== XML_BUFFER_ALLOC_IO
) && (buf
->contentIO
!= NULL
)) {
7040 size_t start_buf
= buf
->content
- buf
->contentIO
;
7041 if (start_buf
>= buf
->size
) {
7042 memmove(buf
->contentIO
, &buf
->content
[0], buf
->use
);
7043 buf
->content
= buf
->contentIO
;
7044 buf
->content
[buf
->use
] = 0;
7045 buf
->size
+= start_buf
;
7049 memmove(buf
->content
, &buf
->content
[len
], buf
->use
);
7050 buf
->content
[buf
->use
] = 0;
7058 * @len: the minimum free size to allocate
7060 * Grow the available space of an XML buffer.
7062 * Returns the new available space or -1 in case of error
7065 xmlBufferGrow(xmlBufferPtr buf
, unsigned int len
) {
7069 if (buf
== NULL
) return(-1);
7071 if (buf
->alloc
== XML_BUFFER_ALLOC_IMMUTABLE
) return(0);
7072 if (len
+ buf
->use
< buf
->size
) return(0);
7075 * Windows has a BIG problem on realloc timing, so we try to double
7076 * the buffer size (if that's enough) (bug 146697)
7077 * Apparently BSD too, and it's probably best for linux too
7078 * On an embedded system this may be something to change
7081 if (buf
->size
> len
)
7082 size
= buf
->size
* 2;
7084 size
= buf
->use
+ len
+ 100;
7086 size
= buf
->use
+ len
+ 100;
7089 if ((buf
->alloc
== XML_BUFFER_ALLOC_IO
) && (buf
->contentIO
!= NULL
)) {
7090 size_t start_buf
= buf
->content
- buf
->contentIO
;
7092 newbuf
= (xmlChar
*) xmlRealloc(buf
->contentIO
, start_buf
+ size
);
7093 if (newbuf
== NULL
) {
7094 xmlTreeErrMemory("growing buffer");
7097 buf
->contentIO
= newbuf
;
7098 buf
->content
= newbuf
+ start_buf
;
7100 newbuf
= (xmlChar
*) xmlRealloc(buf
->content
, size
);
7101 if (newbuf
== NULL
) {
7102 xmlTreeErrMemory("growing buffer");
7105 buf
->content
= newbuf
;
7108 return(buf
->size
- buf
->use
);
7113 * @file: the file output
7114 * @buf: the buffer to dump
7116 * Dumps an XML buffer to a FILE *.
7117 * Returns the number of #xmlChar written
7120 xmlBufferDump(FILE *file
, xmlBufferPtr buf
) {
7125 xmlGenericError(xmlGenericErrorContext
,
7126 "xmlBufferDump: buf == NULL\n");
7130 if (buf
->content
== NULL
) {
7132 xmlGenericError(xmlGenericErrorContext
,
7133 "xmlBufferDump: buf->content == NULL\n");
7139 ret
= fwrite(buf
->content
, sizeof(xmlChar
), buf
->use
, file
);
7147 * Function to extract the content of a buffer
7149 * Returns the internal content
7153 xmlBufferContent(const xmlBufferPtr buf
)
7158 return buf
->content
;
7165 * Function to get the length of a buffer
7167 * Returns the length of data in the internal content
7171 xmlBufferLength(const xmlBufferPtr buf
)
7181 * @buf: the buffer to resize
7182 * @size: the desired size
7184 * Resize a buffer to accommodate minimum size of @size.
7186 * Returns 0 in case of problems, 1 otherwise
7189 xmlBufferResize(xmlBufferPtr buf
, unsigned int size
)
7191 unsigned int newSize
;
7192 xmlChar
* rebuf
= NULL
;
7198 if (buf
->alloc
== XML_BUFFER_ALLOC_IMMUTABLE
) return(0);
7200 /* Don't resize if we don't have to */
7201 if (size
< buf
->size
)
7204 /* figure out new size */
7205 switch (buf
->alloc
){
7206 case XML_BUFFER_ALLOC_IO
:
7207 case XML_BUFFER_ALLOC_DOUBLEIT
:
7208 /*take care of empty case*/
7209 newSize
= (buf
->size
? buf
->size
*2 : size
+ 10);
7210 while (size
> newSize
) {
7211 if (newSize
> UINT_MAX
/ 2) {
7212 xmlTreeErrMemory("growing buffer");
7218 case XML_BUFFER_ALLOC_EXACT
:
7226 if ((buf
->alloc
== XML_BUFFER_ALLOC_IO
) && (buf
->contentIO
!= NULL
)) {
7227 start_buf
= buf
->content
- buf
->contentIO
;
7229 if (start_buf
> newSize
) {
7230 /* move data back to start */
7231 memmove(buf
->contentIO
, buf
->content
, buf
->use
);
7232 buf
->content
= buf
->contentIO
;
7233 buf
->content
[buf
->use
] = 0;
7234 buf
->size
+= start_buf
;
7236 rebuf
= (xmlChar
*) xmlRealloc(buf
->contentIO
, start_buf
+ newSize
);
7237 if (rebuf
== NULL
) {
7238 xmlTreeErrMemory("growing buffer");
7241 buf
->contentIO
= rebuf
;
7242 buf
->content
= rebuf
+ start_buf
;
7245 if (buf
->content
== NULL
) {
7246 rebuf
= (xmlChar
*) xmlMallocAtomic(newSize
);
7247 } else if (buf
->size
- buf
->use
< 100) {
7248 rebuf
= (xmlChar
*) xmlRealloc(buf
->content
, newSize
);
7251 * if we are reallocating a buffer far from being full, it's
7252 * better to make a new allocation and copy only the used range
7253 * and free the old one.
7255 rebuf
= (xmlChar
*) xmlMallocAtomic(newSize
);
7256 if (rebuf
!= NULL
) {
7257 memcpy(rebuf
, buf
->content
, buf
->use
);
7258 xmlFree(buf
->content
);
7259 rebuf
[buf
->use
] = 0;
7262 if (rebuf
== NULL
) {
7263 xmlTreeErrMemory("growing buffer");
7266 buf
->content
= rebuf
;
7268 buf
->size
= newSize
;
7275 * @buf: the buffer to dump
7276 * @str: the #xmlChar string
7277 * @len: the number of #xmlChar to add
7279 * Add a string range to an XML buffer. if len == -1, the length of
7280 * str is recomputed.
7282 * Returns 0 successful, a positive error code number otherwise
7283 * and -1 in case of internal or API error.
7286 xmlBufferAdd(xmlBufferPtr buf
, const xmlChar
*str
, int len
) {
7287 unsigned int needSize
;
7289 if ((str
== NULL
) || (buf
== NULL
)) {
7292 if (buf
->alloc
== XML_BUFFER_ALLOC_IMMUTABLE
) return -1;
7295 xmlGenericError(xmlGenericErrorContext
,
7296 "xmlBufferAdd: len < 0\n");
7300 if (len
== 0) return 0;
7303 len
= xmlStrlen(str
);
7305 if (len
< 0) return -1;
7306 if (len
== 0) return 0;
7308 needSize
= buf
->use
+ len
+ 2;
7309 if (needSize
> buf
->size
){
7310 if (!xmlBufferResize(buf
, needSize
)){
7311 xmlTreeErrMemory("growing buffer");
7312 return XML_ERR_NO_MEMORY
;
7316 memmove(&buf
->content
[buf
->use
], str
, len
*sizeof(xmlChar
));
7318 buf
->content
[buf
->use
] = 0;
7325 * @str: the #xmlChar string
7326 * @len: the number of #xmlChar to add
7328 * Add a string range to the beginning of an XML buffer.
7329 * if len == -1, the length of @str is recomputed.
7331 * Returns 0 successful, a positive error code number otherwise
7332 * and -1 in case of internal or API error.
7335 xmlBufferAddHead(xmlBufferPtr buf
, const xmlChar
*str
, int len
) {
7336 unsigned int needSize
;
7340 if (buf
->alloc
== XML_BUFFER_ALLOC_IMMUTABLE
) return -1;
7343 xmlGenericError(xmlGenericErrorContext
,
7344 "xmlBufferAddHead: str == NULL\n");
7350 xmlGenericError(xmlGenericErrorContext
,
7351 "xmlBufferAddHead: len < 0\n");
7355 if (len
== 0) return 0;
7358 len
= xmlStrlen(str
);
7360 if (len
<= 0) return -1;
7362 if ((buf
->alloc
== XML_BUFFER_ALLOC_IO
) && (buf
->contentIO
!= NULL
)) {
7363 size_t start_buf
= buf
->content
- buf
->contentIO
;
7365 if (start_buf
> (unsigned int) len
) {
7367 * We can add it in the space previously shrinked
7369 buf
->content
-= len
;
7370 memmove(&buf
->content
[0], str
, len
);
7376 needSize
= buf
->use
+ len
+ 2;
7377 if (needSize
> buf
->size
){
7378 if (!xmlBufferResize(buf
, needSize
)){
7379 xmlTreeErrMemory("growing buffer");
7380 return XML_ERR_NO_MEMORY
;
7384 memmove(&buf
->content
[len
], &buf
->content
[0], buf
->use
);
7385 memmove(&buf
->content
[0], str
, len
);
7387 buf
->content
[buf
->use
] = 0;
7393 * @buf: the buffer to add to
7394 * @str: the #xmlChar string
7396 * Append a zero terminated string to an XML buffer.
7398 * Returns 0 successful, a positive error code number otherwise
7399 * and -1 in case of internal or API error.
7402 xmlBufferCat(xmlBufferPtr buf
, const xmlChar
*str
) {
7405 if (buf
->alloc
== XML_BUFFER_ALLOC_IMMUTABLE
) return -1;
7406 if (str
== NULL
) return -1;
7407 return xmlBufferAdd(buf
, str
, -1);
7412 * @buf: the buffer to dump
7413 * @str: the C char string
7415 * Append a zero terminated C string to an XML buffer.
7417 * Returns 0 successful, a positive error code number otherwise
7418 * and -1 in case of internal or API error.
7421 xmlBufferCCat(xmlBufferPtr buf
, const char *str
) {
7426 if (buf
->alloc
== XML_BUFFER_ALLOC_IMMUTABLE
) return -1;
7429 xmlGenericError(xmlGenericErrorContext
,
7430 "xmlBufferCCat: str == NULL\n");
7434 for (cur
= str
;*cur
!= 0;cur
++) {
7435 if (buf
->use
+ 10 >= buf
->size
) {
7436 if (!xmlBufferResize(buf
, buf
->use
+10)){
7437 xmlTreeErrMemory("growing buffer");
7438 return XML_ERR_NO_MEMORY
;
7441 buf
->content
[buf
->use
++] = *cur
;
7443 buf
->content
[buf
->use
] = 0;
7448 * xmlBufferWriteCHAR:
7449 * @buf: the XML buffer
7450 * @string: the string to add
7452 * routine which manages and grows an output buffer. This one adds
7453 * xmlChars at the end of the buffer.
7456 xmlBufferWriteCHAR(xmlBufferPtr buf
, const xmlChar
*string
) {
7459 if (buf
->alloc
== XML_BUFFER_ALLOC_IMMUTABLE
) return;
7460 xmlBufferCat(buf
, string
);
7464 * xmlBufferWriteChar:
7465 * @buf: the XML buffer output
7466 * @string: the string to add
7468 * routine which manage and grows an output buffer. This one add
7469 * C chars at the end of the array.
7472 xmlBufferWriteChar(xmlBufferPtr buf
, const char *string
) {
7475 if (buf
->alloc
== XML_BUFFER_ALLOC_IMMUTABLE
) return;
7476 xmlBufferCCat(buf
, string
);
7481 * xmlBufferWriteQuotedString:
7482 * @buf: the XML buffer output
7483 * @string: the string to add
7485 * routine which manage and grows an output buffer. This one writes
7486 * a quoted or double quoted #xmlChar string, checking first if it holds
7487 * quote or double-quotes internally
7490 xmlBufferWriteQuotedString(xmlBufferPtr buf
, const xmlChar
*string
) {
7491 const xmlChar
*cur
, *base
;
7494 if (buf
->alloc
== XML_BUFFER_ALLOC_IMMUTABLE
) return;
7495 if (xmlStrchr(string
, '\"')) {
7496 if (xmlStrchr(string
, '\'')) {
7498 xmlGenericError(xmlGenericErrorContext
,
7499 "xmlBufferWriteQuotedString: string contains quote and double-quotes !\n");
7501 xmlBufferCCat(buf
, "\"");
7502 base
= cur
= string
;
7506 xmlBufferAdd(buf
, base
, cur
- base
);
7507 xmlBufferAdd(buf
, BAD_CAST
""", 6);
7516 xmlBufferAdd(buf
, base
, cur
- base
);
7517 xmlBufferCCat(buf
, "\"");
7520 xmlBufferCCat(buf
, "\'");
7521 xmlBufferCat(buf
, string
);
7522 xmlBufferCCat(buf
, "\'");
7525 xmlBufferCCat(buf
, "\"");
7526 xmlBufferCat(buf
, string
);
7527 xmlBufferCCat(buf
, "\"");
7533 * xmlGetDocCompressMode:
7534 * @doc: the document
7536 * get the compression ratio for a document, ZLIB based
7537 * Returns 0 (uncompressed) to 9 (max compression)
7540 xmlGetDocCompressMode (xmlDocPtr doc
) {
7541 if (doc
== NULL
) return(-1);
7542 return(doc
->compression
);
7546 * xmlSetDocCompressMode:
7547 * @doc: the document
7548 * @mode: the compression ratio
7550 * set the compression ratio for a document, ZLIB based
7551 * Correct values: 0 (uncompressed) to 9 (max compression)
7554 xmlSetDocCompressMode (xmlDocPtr doc
, int mode
) {
7555 if (doc
== NULL
) return;
7556 if (mode
< 0) doc
->compression
= 0;
7557 else if (mode
> 9) doc
->compression
= 9;
7558 else doc
->compression
= mode
;
7562 * xmlGetCompressMode:
7564 * get the default compression mode used, ZLIB based.
7565 * Returns 0 (uncompressed) to 9 (max compression)
7568 xmlGetCompressMode(void)
7570 return (xmlCompressMode
);
7574 * xmlSetCompressMode:
7575 * @mode: the compression ratio
7577 * set the default compression mode used, ZLIB based
7578 * Correct values: 0 (uncompressed) to 9 (max compression)
7581 xmlSetCompressMode(int mode
) {
7582 if (mode
< 0) xmlCompressMode
= 0;
7583 else if (mode
> 9) xmlCompressMode
= 9;
7584 else xmlCompressMode
= mode
;
7587 #define XML_TREE_NSMAP_PARENT -1
7588 #define XML_TREE_NSMAP_XML -2
7589 #define XML_TREE_NSMAP_DOC -3
7590 #define XML_TREE_NSMAP_CUSTOM -4
7592 typedef struct xmlNsMapItem
*xmlNsMapItemPtr
;
7593 struct xmlNsMapItem
{
7594 xmlNsMapItemPtr next
;
7595 xmlNsMapItemPtr prev
;
7596 xmlNsPtr oldNs
; /* old ns decl reference */
7597 xmlNsPtr newNs
; /* new ns decl reference */
7598 int shadowDepth
; /* Shadowed at this depth */
7601 * >= 0 == @node's ns-decls
7602 * -1 == @parent's ns-decls
7603 * -2 == the doc->oldNs XML ns-decl
7604 * -3 == the doc->oldNs storage ns-decls
7605 * -4 == ns-decls provided via custom ns-handling
7610 typedef struct xmlNsMap
*xmlNsMapPtr
;
7612 xmlNsMapItemPtr first
;
7613 xmlNsMapItemPtr last
;
7614 xmlNsMapItemPtr pool
;
7617 #define XML_NSMAP_NOTEMPTY(m) (((m) != NULL) && ((m)->first != NULL))
7618 #define XML_NSMAP_FOREACH(m, i) for (i = (m)->first; i != NULL; i = (i)->next)
7619 #define XML_NSMAP_POP(m, i) \
7621 (m)->last = (i)->prev; \
7622 if ((m)->last == NULL) \
7623 (m)->first = NULL; \
7625 (m)->last->next = NULL; \
7626 (i)->next = (m)->pool; \
7630 * xmlDOMWrapNsMapFree:
7636 xmlDOMWrapNsMapFree(xmlNsMapPtr nsmap
)
7638 xmlNsMapItemPtr cur
, tmp
;
7643 while (cur
!= NULL
) {
7649 while (cur
!= NULL
) {
7658 * xmlDOMWrapNsMapAddItem:
7660 * @oldNs: the old ns-struct
7661 * @newNs: the new ns-struct
7662 * @depth: depth and ns-kind information
7664 * Adds an ns-mapping item.
7666 static xmlNsMapItemPtr
7667 xmlDOMWrapNsMapAddItem(xmlNsMapPtr
*nsmap
, int position
,
7668 xmlNsPtr oldNs
, xmlNsPtr newNs
, int depth
)
7670 xmlNsMapItemPtr ret
;
7675 if ((position
!= -1) && (position
!= 0))
7681 * Create the ns-map.
7683 map
= (xmlNsMapPtr
) xmlMalloc(sizeof(struct xmlNsMap
));
7685 xmlTreeErrMemory("allocating namespace map");
7688 memset(map
, 0, sizeof(struct xmlNsMap
));
7692 if (map
->pool
!= NULL
) {
7694 * Reuse an item from the pool.
7697 map
->pool
= ret
->next
;
7698 memset(ret
, 0, sizeof(struct xmlNsMapItem
));
7701 * Create a new item.
7703 ret
= (xmlNsMapItemPtr
) xmlMalloc(sizeof(struct xmlNsMapItem
));
7705 xmlTreeErrMemory("allocating namespace map item");
7708 memset(ret
, 0, sizeof(struct xmlNsMapItem
));
7711 if (map
->first
== NULL
) {
7717 } else if (position
== -1) {
7721 ret
->prev
= map
->last
;
7722 map
->last
->next
= ret
;
7724 } else if (position
== 0) {
7726 * Set on first position.
7728 map
->first
->prev
= ret
;
7729 ret
->next
= map
->first
;
7736 ret
->shadowDepth
= -1;
7742 * xmlDOMWrapStoreNs:
7744 * @nsName: the namespace name
7745 * @prefix: the prefix
7747 * Creates or reuses an xmlNs struct on doc->oldNs with
7748 * the given prefix and namespace name.
7750 * Returns the aquired ns struct or NULL in case of an API
7751 * or internal error.
7754 xmlDOMWrapStoreNs(xmlDocPtr doc
,
7755 const xmlChar
*nsName
,
7756 const xmlChar
*prefix
)
7762 ns
= xmlTreeEnsureXMLDecl(doc
);
7765 if (ns
->next
!= NULL
) {
7768 while (ns
!= NULL
) {
7769 if (((ns
->prefix
== prefix
) ||
7770 xmlStrEqual(ns
->prefix
, prefix
)) &&
7771 xmlStrEqual(ns
->href
, nsName
)) {
7774 if (ns
->next
== NULL
)
7781 ns
->next
= xmlNewNs(NULL
, nsName
, prefix
);
7788 * xmlDOMWrapNewCtxt:
7790 * Allocates and initializes a new DOM-wrapper context.
7792 * Returns the xmlDOMWrapCtxtPtr or NULL in case of an internal errror.
7795 xmlDOMWrapNewCtxt(void)
7797 xmlDOMWrapCtxtPtr ret
;
7799 ret
= xmlMalloc(sizeof(xmlDOMWrapCtxt
));
7801 xmlTreeErrMemory("allocating DOM-wrapper context");
7804 memset(ret
, 0, sizeof(xmlDOMWrapCtxt
));
7809 * xmlDOMWrapFreeCtxt:
7810 * @ctxt: the DOM-wrapper context
7812 * Frees the DOM-wrapper context.
7815 xmlDOMWrapFreeCtxt(xmlDOMWrapCtxtPtr ctxt
)
7819 if (ctxt
->namespaceMap
!= NULL
)
7820 xmlDOMWrapNsMapFree((xmlNsMapPtr
) ctxt
->namespaceMap
);
7822 * TODO: Store the namespace map in the context.
7828 * xmlTreeLookupNsListByPrefix:
7829 * @nsList: a list of ns-structs
7830 * @prefix: the searched prefix
7832 * Searches for a ns-decl with the given prefix in @nsList.
7834 * Returns the ns-decl if found, NULL if not found and on
7838 xmlTreeNSListLookupByPrefix(xmlNsPtr nsList
, const xmlChar
*prefix
)
7846 if ((prefix
== ns
->prefix
) ||
7847 xmlStrEqual(prefix
, ns
->prefix
)) {
7851 } while (ns
!= NULL
);
7858 * xmlDOMWrapNSNormGatherInScopeNs:
7859 * @map: the namespace map
7860 * @node: the node to start with
7862 * Puts in-scope namespaces into the ns-map.
7864 * Returns 0 on success, -1 on API or internal errors.
7867 xmlDOMWrapNSNormGatherInScopeNs(xmlNsMapPtr
*map
,
7875 if ((map
== NULL
) || (*map
!= NULL
))
7878 * Get in-scope ns-decls of @parent.
7881 while ((cur
!= NULL
) && (cur
!= (xmlNodePtr
) cur
->doc
)) {
7882 if (cur
->type
== XML_ELEMENT_NODE
) {
7883 if (cur
->nsDef
!= NULL
) {
7887 if (XML_NSMAP_NOTEMPTY(*map
)) {
7889 * Skip shadowed prefixes.
7891 XML_NSMAP_FOREACH(*map
, mi
) {
7892 if ((ns
->prefix
== mi
->newNs
->prefix
) ||
7893 xmlStrEqual(ns
->prefix
, mi
->newNs
->prefix
)) {
7902 mi
= xmlDOMWrapNsMapAddItem(map
, 0, NULL
,
7903 ns
, XML_TREE_NSMAP_PARENT
);
7907 mi
->shadowDepth
= 0;
7909 } while (ns
!= NULL
);
7918 * XML_TREE_ADOPT_STR: If we have a dest-dict, put @str in the dict;
7919 * otherwise copy it, when it was in the source-dict.
7921 #define XML_TREE_ADOPT_STR(str) \
7922 if (adoptStr && (str != NULL)) { \
7923 if (destDoc->dict) { \
7924 const xmlChar *old = str; \
7925 str = xmlDictLookup(destDoc->dict, str, -1); \
7926 if ((sourceDoc == NULL) || (sourceDoc->dict == NULL) || \
7927 (!xmlDictOwns(sourceDoc->dict, old))) \
7928 xmlFree((char *)old); \
7929 } else if ((sourceDoc) && (sourceDoc->dict) && \
7930 xmlDictOwns(sourceDoc->dict, str)) { \
7931 str = BAD_CAST xmlStrdup(str); \
7936 * XML_TREE_ADOPT_STR_2: If @str was in the source-dict, then
7937 * put it in dest-dict or copy it.
7939 #define XML_TREE_ADOPT_STR_2(str) \
7940 if (adoptStr && (str != NULL) && (sourceDoc != NULL) && \
7941 (sourceDoc->dict != NULL) && \
7942 xmlDictOwns(sourceDoc->dict, cur->content)) { \
7943 if (destDoc->dict) \
7944 cur->content = (xmlChar *) \
7945 xmlDictLookup(destDoc->dict, cur->content, -1); \
7947 cur->content = xmlStrdup(BAD_CAST cur->content); \
7951 * xmlDOMWrapNSNormAddNsMapItem2:
7953 * For internal use. Adds a ns-decl mapping.
7955 * Returns 0 on success, -1 on internal errors.
7958 xmlDOMWrapNSNormAddNsMapItem2(xmlNsPtr
**list
, int *size
, int *number
,
7959 xmlNsPtr oldNs
, xmlNsPtr newNs
)
7961 if (*list
== NULL
) {
7962 *list
= (xmlNsPtr
*) xmlMalloc(6 * sizeof(xmlNsPtr
));
7963 if (*list
== NULL
) {
7964 xmlTreeErrMemory("alloc ns map item");
7969 } else if ((*number
) >= (*size
)) {
7971 *list
= (xmlNsPtr
*) xmlRealloc(*list
,
7972 (*size
) * 2 * sizeof(xmlNsPtr
));
7973 if (*list
== NULL
) {
7974 xmlTreeErrMemory("realloc ns map item");
7978 (*list
)[2 * (*number
)] = oldNs
;
7979 (*list
)[2 * (*number
) +1] = newNs
;
7985 * xmlDOMWrapRemoveNode:
7986 * @ctxt: a DOM wrapper context
7988 * @node: the node to be removed.
7989 * @options: set of options, unused at the moment
7991 * Unlinks the given node from its owner.
7992 * This will substitute ns-references to node->nsDef for
7993 * ns-references to doc->oldNs, thus ensuring the removed
7994 * branch to be autark wrt ns-references.
7996 * NOTE: This function was not intensively tested.
7998 * Returns 0 on success, 1 if the node is not supported,
7999 * -1 on API and internal errors.
8002 xmlDOMWrapRemoveNode(xmlDOMWrapCtxtPtr ctxt
, xmlDocPtr doc
,
8003 xmlNodePtr node
, int options ATTRIBUTE_UNUSED
)
8005 xmlNsPtr
*list
= NULL
;
8006 int sizeList
, nbList
, i
, j
;
8009 if ((node
== NULL
) || (doc
== NULL
) || (node
->doc
!= doc
))
8012 /* TODO: 0 or -1 ? */
8013 if (node
->parent
== NULL
)
8016 switch (node
->type
) {
8018 case XML_CDATA_SECTION_NODE
:
8019 case XML_ENTITY_REF_NODE
:
8021 case XML_COMMENT_NODE
:
8022 xmlUnlinkNode(node
);
8024 case XML_ELEMENT_NODE
:
8025 case XML_ATTRIBUTE_NODE
:
8030 xmlUnlinkNode(node
);
8032 * Save out-of-scope ns-references in doc->oldNs.
8035 switch (node
->type
) {
8036 case XML_ELEMENT_NODE
:
8037 if ((ctxt
== NULL
) && (node
->nsDef
!= NULL
)) {
8040 if (xmlDOMWrapNSNormAddNsMapItem2(&list
, &sizeList
,
8041 &nbList
, ns
, ns
) == -1)
8042 goto internal_error
;
8044 } while (ns
!= NULL
);
8046 /* No break on purpose. */
8047 case XML_ATTRIBUTE_NODE
:
8048 if (node
->ns
!= NULL
) {
8053 for (i
= 0, j
= 0; i
< nbList
; i
++, j
+= 2) {
8054 if (node
->ns
== list
[j
]) {
8055 node
->ns
= list
[++j
];
8067 * Add to doc's oldNs.
8069 ns
= xmlDOMWrapStoreNs(doc
, node
->ns
->href
,
8072 goto internal_error
;
8078 if (xmlDOMWrapNSNormAddNsMapItem2(&list
, &sizeList
,
8079 &nbList
, node
->ns
, ns
) == -1)
8080 goto internal_error
;
8084 if ((node
->type
== XML_ELEMENT_NODE
) &&
8085 (node
->properties
!= NULL
)) {
8086 node
= (xmlNodePtr
) node
->properties
;
8094 if ((node
->type
== XML_ELEMENT_NODE
) &&
8095 (node
->children
!= NULL
)) {
8096 node
= node
->children
;
8102 if (node
->next
!= NULL
)
8105 node
= node
->parent
;
8108 } while (node
!= NULL
);
8121 * xmlSearchNsByNamespaceStrict:
8122 * @doc: the document
8123 * @node: the start node
8124 * @nsName: the searched namespace name
8125 * @retNs: the resulting ns-decl
8126 * @prefixed: if the found ns-decl must have a prefix (for attributes)
8128 * Dynamically searches for a ns-declaration which matches
8129 * the given @nsName in the ancestor-or-self axis of @node.
8131 * Returns 1 if a ns-decl was found, 0 if not and -1 on API
8132 * and internal errors.
8135 xmlSearchNsByNamespaceStrict(xmlDocPtr doc
, xmlNodePtr node
,
8136 const xmlChar
* nsName
,
8137 xmlNsPtr
*retNs
, int prefixed
)
8139 xmlNodePtr cur
, prev
= NULL
, out
= NULL
;
8140 xmlNsPtr ns
, prevns
;
8142 if ((doc
== NULL
) || (nsName
== NULL
) || (retNs
== NULL
))
8146 if (xmlStrEqual(nsName
, XML_XML_NAMESPACE
)) {
8147 *retNs
= xmlTreeEnsureXMLDecl(doc
);
8154 if (cur
->type
== XML_ELEMENT_NODE
) {
8155 if (cur
->nsDef
!= NULL
) {
8156 for (ns
= cur
->nsDef
; ns
!= NULL
; ns
= ns
->next
) {
8157 if (prefixed
&& (ns
->prefix
== NULL
))
8161 * Check the last level of ns-decls for a
8164 prevns
= prev
->nsDef
;
8166 if ((prevns
->prefix
== ns
->prefix
) ||
8167 ((prevns
->prefix
!= NULL
) &&
8168 (ns
->prefix
!= NULL
) &&
8169 xmlStrEqual(prevns
->prefix
, ns
->prefix
))) {
8175 prevns
= prevns
->next
;
8176 } while (prevns
!= NULL
);
8181 * Ns-name comparison.
8183 if ((nsName
== ns
->href
) ||
8184 xmlStrEqual(nsName
, ns
->href
)) {
8186 * At this point the prefix can only be shadowed,
8187 * if we are the the (at least) 3rd level of
8193 ret
= xmlNsInScope(doc
, node
, prev
, ns
->prefix
);
8197 * TODO: Should we try to find a matching ns-name
8198 * only once? This here keeps on searching.
8199 * I think we should try further since, there might
8200 * be an other matching ns-decl with an unshadowed
8213 } else if ((cur
->type
== XML_ENTITY_NODE
) ||
8214 (cur
->type
== XML_ENTITY_DECL
))
8217 } while ((cur
!= NULL
) && (cur
->doc
!= (xmlDocPtr
) cur
));
8222 * xmlSearchNsByPrefixStrict:
8223 * @doc: the document
8224 * @node: the start node
8225 * @prefix: the searched namespace prefix
8226 * @retNs: the resulting ns-decl
8228 * Dynamically searches for a ns-declaration which matches
8229 * the given @nsName in the ancestor-or-self axis of @node.
8231 * Returns 1 if a ns-decl was found, 0 if not and -1 on API
8232 * and internal errors.
8235 xmlSearchNsByPrefixStrict(xmlDocPtr doc
, xmlNodePtr node
,
8236 const xmlChar
* prefix
,
8242 if ((doc
== NULL
) || (node
== NULL
))
8247 if (IS_STR_XML(prefix
)) {
8249 *retNs
= xmlTreeEnsureXMLDecl(doc
);
8257 if (cur
->type
== XML_ELEMENT_NODE
) {
8258 if (cur
->nsDef
!= NULL
) {
8261 if ((prefix
== ns
->prefix
) ||
8262 xmlStrEqual(prefix
, ns
->prefix
))
8265 * Disabled namespaces, e.g. xmlns:abc="".
8267 if (ns
->href
== NULL
)
8274 } while (ns
!= NULL
);
8276 } else if ((cur
->type
== XML_ENTITY_NODE
) ||
8277 (cur
->type
== XML_ENTITY_DECL
))
8280 } while ((cur
!= NULL
) && (cur
->doc
!= (xmlDocPtr
) cur
));
8285 * xmlDOMWrapNSNormDeclareNsForced:
8287 * @elem: the element-node to declare on
8288 * @nsName: the namespace-name of the ns-decl
8289 * @prefix: the preferred prefix of the ns-decl
8290 * @checkShadow: ensure that the new ns-decl doesn't shadow ancestor ns-decls
8292 * Declares a new namespace on @elem. It tries to use the
8293 * given @prefix; if a ns-decl with the given prefix is already existent
8294 * on @elem, it will generate an other prefix.
8296 * Returns 1 if a ns-decl was found, 0 if not and -1 on API
8297 * and internal errors.
8300 xmlDOMWrapNSNormDeclareNsForced(xmlDocPtr doc
,
8302 const xmlChar
*nsName
,
8303 const xmlChar
*prefix
,
8309 const xmlChar
*pref
;
8312 * Create a ns-decl on @anchor.
8317 * Lookup whether the prefix is unused in elem's ns-decls.
8319 if ((elem
->nsDef
!= NULL
) &&
8320 (xmlTreeNSListLookupByPrefix(elem
->nsDef
, pref
) != NULL
))
8321 goto ns_next_prefix
;
8322 if (checkShadow
&& elem
->parent
&&
8323 ((xmlNodePtr
) elem
->parent
->doc
!= elem
->parent
)) {
8325 * Does it shadow ancestor ns-decls?
8327 if (xmlSearchNsByPrefixStrict(doc
, elem
->parent
, pref
, NULL
) == 1)
8328 goto ns_next_prefix
;
8330 ret
= xmlNewNs(NULL
, nsName
, pref
);
8333 if (elem
->nsDef
== NULL
)
8336 xmlNsPtr ns2
= elem
->nsDef
;
8337 while (ns2
->next
!= NULL
)
8346 if (prefix
== NULL
) {
8347 snprintf((char *) buf
, sizeof(buf
),
8350 snprintf((char *) buf
, sizeof(buf
),
8351 "%.30s_%d", (char *)prefix
, counter
);
8352 pref
= BAD_CAST buf
;
8357 * xmlDOMWrapNSNormAquireNormalizedNs:
8359 * @elem: the element-node to declare namespaces on
8360 * @ns: the ns-struct to use for the search
8361 * @retNs: the found/created ns-struct
8362 * @nsMap: the ns-map
8363 * @depth: the current tree depth
8364 * @ancestorsOnly: search in ancestor ns-decls only
8365 * @prefixed: if the searched ns-decl must have a prefix (for attributes)
8367 * Searches for a matching ns-name in the ns-decls of @nsMap, if not
8368 * found it will either declare it on @elem, or store it in doc->oldNs.
8369 * If a new ns-decl needs to be declared on @elem, it tries to use the
8370 * @ns->prefix for it, if this prefix is already in use on @elem, it will
8371 * change the prefix or the new ns-decl.
8373 * Returns 0 if succeeded, -1 otherwise and on API/internal errors.
8376 xmlDOMWrapNSNormAquireNormalizedNs(xmlDocPtr doc
,
8388 if ((doc
== NULL
) || (ns
== NULL
) || (retNs
== NULL
) ||
8394 * Handle XML namespace.
8396 if (IS_STR_XML(ns
->prefix
)) {
8398 * Insert XML namespace mapping.
8400 *retNs
= xmlTreeEnsureXMLDecl(doc
);
8406 * If the search should be done in ancestors only and no
8407 * @elem (the first ancestor) was specified, then skip the search.
8409 if ((XML_NSMAP_NOTEMPTY(*nsMap
)) &&
8410 (! (ancestorsOnly
&& (elem
== NULL
))))
8413 * Try to find an equal ns-name in in-scope ns-decls.
8415 XML_NSMAP_FOREACH(*nsMap
, mi
) {
8416 if ((mi
->depth
>= XML_TREE_NSMAP_PARENT
) &&
8418 * ancestorsOnly: This should be turned on to gain speed,
8419 * if one knows that the branch itself was already
8420 * ns-wellformed and no stale references existed.
8421 * I.e. it searches in the ancestor axis only.
8423 ((! ancestorsOnly
) || (mi
->depth
== XML_TREE_NSMAP_PARENT
)) &&
8424 /* Skip shadowed prefixes. */
8425 (mi
->shadowDepth
== -1) &&
8426 /* Skip xmlns="" or xmlns:foo="". */
8427 ((mi
->newNs
->href
!= NULL
) &&
8428 (mi
->newNs
->href
[0] != 0)) &&
8429 /* Ensure a prefix if wanted. */
8430 ((! prefixed
) || (mi
->newNs
->prefix
!= NULL
)) &&
8432 ((mi
->newNs
->href
== ns
->href
) ||
8433 xmlStrEqual(mi
->newNs
->href
, ns
->href
))) {
8434 /* Set the mapping. */
8442 * No luck, the namespace is out of scope or shadowed.
8448 * Store ns-decls in "oldNs" of the document-node.
8450 tmpns
= xmlDOMWrapStoreNs(doc
, ns
->href
, ns
->prefix
);
8456 if (xmlDOMWrapNsMapAddItem(nsMap
, -1, ns
,
8457 tmpns
, XML_TREE_NSMAP_DOC
) == NULL
) {
8465 tmpns
= xmlDOMWrapNSNormDeclareNsForced(doc
, elem
, ns
->href
,
8470 if (*nsMap
!= NULL
) {
8472 * Does it shadow ancestor ns-decls?
8474 XML_NSMAP_FOREACH(*nsMap
, mi
) {
8475 if ((mi
->depth
< depth
) &&
8476 (mi
->shadowDepth
== -1) &&
8477 ((ns
->prefix
== mi
->newNs
->prefix
) ||
8478 xmlStrEqual(ns
->prefix
, mi
->newNs
->prefix
))) {
8482 mi
->shadowDepth
= depth
;
8487 if (xmlDOMWrapNsMapAddItem(nsMap
, -1, ns
, tmpns
, depth
) == NULL
) {
8497 XML_DOM_RECONNS_REMOVEREDUND
= 1<<0
8498 } xmlDOMReconcileNSOptions
;
8501 * xmlDOMWrapReconcileNamespaces:
8502 * @ctxt: DOM wrapper context, unused at the moment
8503 * @elem: the element-node
8504 * @options: option flags
8506 * Ensures that ns-references point to ns-decls hold on element-nodes.
8507 * Ensures that the tree is namespace wellformed by creating additional
8508 * ns-decls where needed. Note that, since prefixes of already existent
8509 * ns-decls can be shadowed by this process, it could break QNames in
8510 * attribute values or element content.
8512 * NOTE: This function was not intensively tested.
8514 * Returns 0 if succeeded, -1 otherwise and on API/internal errors.
8518 xmlDOMWrapReconcileNamespaces(xmlDOMWrapCtxtPtr ctxt ATTRIBUTE_UNUSED
,
8522 int depth
= -1, adoptns
= 0, parnsdone
= 0;
8523 xmlNsPtr ns
, prevns
;
8525 xmlNodePtr cur
, curElem
= NULL
;
8526 xmlNsMapPtr nsMap
= NULL
;
8527 xmlNsMapItemPtr
/* topmi = NULL, */ mi
;
8528 /* @ancestorsOnly should be set by an option flag. */
8529 int ancestorsOnly
= 0;
8530 int optRemoveRedundantNS
=
8531 ((xmlDOMReconcileNSOptions
) options
& XML_DOM_RECONNS_REMOVEREDUND
) ? 1 : 0;
8532 xmlNsPtr
*listRedund
= NULL
;
8533 int sizeRedund
= 0, nbRedund
= 0, ret
, i
, j
;
8535 if ((elem
== NULL
) || (elem
->doc
== NULL
) ||
8536 (elem
->type
!= XML_ELEMENT_NODE
))
8542 switch (cur
->type
) {
8543 case XML_ELEMENT_NODE
:
8548 * Namespace declarations.
8550 if (cur
->nsDef
!= NULL
) {
8553 while (ns
!= NULL
) {
8555 if ((elem
->parent
) &&
8556 ((xmlNodePtr
) elem
->parent
->doc
!= elem
->parent
)) {
8558 * Gather ancestor in-scope ns-decls.
8560 if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap
,
8561 elem
->parent
) == -1)
8562 goto internal_error
;
8568 * Lookup the ns ancestor-axis for equal ns-decls in scope.
8570 if (optRemoveRedundantNS
&& XML_NSMAP_NOTEMPTY(nsMap
)) {
8571 XML_NSMAP_FOREACH(nsMap
, mi
) {
8572 if ((mi
->depth
>= XML_TREE_NSMAP_PARENT
) &&
8573 (mi
->shadowDepth
== -1) &&
8574 ((ns
->prefix
== mi
->newNs
->prefix
) ||
8575 xmlStrEqual(ns
->prefix
, mi
->newNs
->prefix
)) &&
8576 ((ns
->href
== mi
->newNs
->href
) ||
8577 xmlStrEqual(ns
->href
, mi
->newNs
->href
)))
8580 * A redundant ns-decl was found.
8581 * Add it to the list of redundant ns-decls.
8583 if (xmlDOMWrapNSNormAddNsMapItem2(&listRedund
,
8584 &sizeRedund
, &nbRedund
, ns
, mi
->newNs
) == -1)
8585 goto internal_error
;
8587 * Remove the ns-decl from the element-node.
8590 prevns
->next
= ns
->next
;
8592 cur
->nsDef
= ns
->next
;
8599 * Skip ns-references handling if the referenced
8600 * ns-decl is declared on the same element.
8602 if ((cur
->ns
!= NULL
) && adoptns
&& (cur
->ns
== ns
))
8605 * Does it shadow any ns-decl?
8607 if (XML_NSMAP_NOTEMPTY(nsMap
)) {
8608 XML_NSMAP_FOREACH(nsMap
, mi
) {
8609 if ((mi
->depth
>= XML_TREE_NSMAP_PARENT
) &&
8610 (mi
->shadowDepth
== -1) &&
8611 ((ns
->prefix
== mi
->newNs
->prefix
) ||
8612 xmlStrEqual(ns
->prefix
, mi
->newNs
->prefix
))) {
8614 mi
->shadowDepth
= depth
;
8621 if (xmlDOMWrapNsMapAddItem(&nsMap
, -1, ns
, ns
,
8623 goto internal_error
;
8632 /* No break on purpose. */
8633 case XML_ATTRIBUTE_NODE
:
8634 /* No ns, no fun. */
8635 if (cur
->ns
== NULL
)
8639 if ((elem
->parent
) &&
8640 ((xmlNodePtr
) elem
->parent
->doc
!= elem
->parent
)) {
8641 if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap
,
8642 elem
->parent
) == -1)
8643 goto internal_error
;
8648 * Adjust the reference if this was a redundant ns-decl.
8651 for (i
= 0, j
= 0; i
< nbRedund
; i
++, j
+= 2) {
8652 if (cur
->ns
== listRedund
[j
]) {
8653 cur
->ns
= listRedund
[++j
];
8659 * Adopt ns-references.
8661 if (XML_NSMAP_NOTEMPTY(nsMap
)) {
8663 * Search for a mapping.
8665 XML_NSMAP_FOREACH(nsMap
, mi
) {
8666 if ((mi
->shadowDepth
== -1) &&
8667 (cur
->ns
== mi
->oldNs
)) {
8669 cur
->ns
= mi
->newNs
;
8675 * Aquire a normalized ns-decl and add it to the map.
8677 if (xmlDOMWrapNSNormAquireNormalizedNs(doc
, curElem
,
8681 (cur
->type
== XML_ATTRIBUTE_NODE
) ? 1 : 0) == -1)
8682 goto internal_error
;
8686 if ((cur
->type
== XML_ELEMENT_NODE
) &&
8687 (cur
->properties
!= NULL
)) {
8689 * Process attributes.
8691 cur
= (xmlNodePtr
) cur
->properties
;
8699 if ((cur
->type
== XML_ELEMENT_NODE
) &&
8700 (cur
->children
!= NULL
)) {
8702 * Process content of element-nodes only.
8704 cur
= cur
->children
;
8710 if (cur
->type
== XML_ELEMENT_NODE
) {
8711 if (XML_NSMAP_NOTEMPTY(nsMap
)) {
8715 while ((nsMap
->last
!= NULL
) &&
8716 (nsMap
->last
->depth
>= depth
))
8718 XML_NSMAP_POP(nsMap
, mi
)
8723 XML_NSMAP_FOREACH(nsMap
, mi
) {
8724 if (mi
->shadowDepth
>= depth
)
8725 mi
->shadowDepth
= -1;
8730 if (cur
->next
!= NULL
)
8733 if (cur
->type
== XML_ATTRIBUTE_NODE
) {
8740 } while (cur
!= NULL
);
8748 for (i
= 0, j
= 0; i
< nbRedund
; i
++, j
+= 2) {
8749 xmlFreeNs(listRedund
[j
]);
8751 xmlFree(listRedund
);
8754 xmlDOMWrapNsMapFree(nsMap
);
8759 * xmlDOMWrapAdoptBranch:
8760 * @ctxt: the optional context for custom processing
8761 * @sourceDoc: the optional sourceDoc
8762 * @node: the element-node to start with
8763 * @destDoc: the destination doc for adoption
8764 * @destParent: the optional new parent of @node in @destDoc
8765 * @options: option flags
8767 * Ensures that ns-references point to @destDoc: either to
8768 * elements->nsDef entries if @destParent is given, or to
8769 * @destDoc->oldNs otherwise.
8770 * If @destParent is given, it ensures that the tree is namespace
8771 * wellformed by creating additional ns-decls where needed.
8772 * Note that, since prefixes of already existent ns-decls can be
8773 * shadowed by this process, it could break QNames in attribute
8774 * values or element content.
8776 * NOTE: This function was not intensively tested.
8778 * Returns 0 if succeeded, -1 otherwise and on API/internal errors.
8781 xmlDOMWrapAdoptBranch(xmlDOMWrapCtxtPtr ctxt
,
8782 xmlDocPtr sourceDoc
,
8785 xmlNodePtr destParent
,
8786 int options ATTRIBUTE_UNUSED
)
8789 xmlNodePtr cur
, curElem
= NULL
;
8790 xmlNsMapPtr nsMap
= NULL
;
8793 int depth
= -1, adoptStr
= 1;
8794 /* gather @parent's ns-decls. */
8796 /* @ancestorsOnly should be set per option. */
8797 int ancestorsOnly
= 0;
8800 * Optimize string adoption for equal or none dicts.
8802 if ((sourceDoc
!= NULL
) &&
8803 (sourceDoc
->dict
== destDoc
->dict
))
8809 * Get the ns-map from the context if available.
8812 nsMap
= (xmlNsMapPtr
) ctxt
->namespaceMap
;
8814 * Disable search for ns-decls in the parent-axis of the
8815 * desination element, if:
8816 * 1) there's no destination parent
8817 * 2) custom ns-reference handling is used
8819 if ((destParent
== NULL
) ||
8820 (ctxt
&& ctxt
->getNsForNodeFunc
))
8827 while (cur
!= NULL
) {
8829 * Paranoid source-doc sanity check.
8831 if (cur
->doc
!= sourceDoc
) {
8833 * We'll assume XIncluded nodes if the doc differs.
8834 * TODO: Do we need to reconciliate XIncluded nodes?
8835 * This here skips XIncluded nodes and tries to handle
8838 if (cur
->next
== NULL
)
8842 if ((cur
->type
== XML_XINCLUDE_END
) ||
8843 (cur
->doc
== node
->doc
))
8845 } while (cur
->next
!= NULL
);
8847 if (cur
->doc
!= node
->doc
)
8851 switch (cur
->type
) {
8852 case XML_XINCLUDE_START
:
8853 case XML_XINCLUDE_END
:
8858 case XML_ELEMENT_NODE
:
8862 * Namespace declarations.
8863 * - ns->href and ns->prefix are never in the dict, so
8864 * we need not move the values over to the destination dict.
8865 * - Note that for custom handling of ns-references,
8866 * the ns-decls need not be stored in the ns-map,
8867 * since they won't be referenced by node->ns.
8870 ((ctxt
== NULL
) || (ctxt
->getNsForNodeFunc
== NULL
)))
8874 * Gather @parent's in-scope ns-decls.
8876 if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap
,
8878 goto internal_error
;
8881 for (ns
= cur
->nsDef
; ns
!= NULL
; ns
= ns
->next
) {
8883 * NOTE: ns->prefix and ns->href are never in the dict.
8884 * XML_TREE_ADOPT_STR(ns->prefix)
8885 * XML_TREE_ADOPT_STR(ns->href)
8888 * Does it shadow any ns-decl?
8890 if (XML_NSMAP_NOTEMPTY(nsMap
)) {
8891 XML_NSMAP_FOREACH(nsMap
, mi
) {
8892 if ((mi
->depth
>= XML_TREE_NSMAP_PARENT
) &&
8893 (mi
->shadowDepth
== -1) &&
8894 ((ns
->prefix
== mi
->newNs
->prefix
) ||
8895 xmlStrEqual(ns
->prefix
,
8896 mi
->newNs
->prefix
))) {
8898 mi
->shadowDepth
= depth
;
8905 if (xmlDOMWrapNsMapAddItem(&nsMap
, -1,
8906 ns
, ns
, depth
) == NULL
)
8907 goto internal_error
;
8910 /* No break on purpose. */
8911 case XML_ATTRIBUTE_NODE
:
8912 /* No namespace, no fun. */
8913 if (cur
->ns
== NULL
)
8917 if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap
,
8919 goto internal_error
;
8923 * Adopt ns-references.
8925 if (XML_NSMAP_NOTEMPTY(nsMap
)) {
8927 * Search for a mapping.
8929 XML_NSMAP_FOREACH(nsMap
, mi
) {
8930 if ((mi
->shadowDepth
== -1) &&
8931 (cur
->ns
== mi
->oldNs
)) {
8933 cur
->ns
= mi
->newNs
;
8939 * No matching namespace in scope. We need a new one.
8941 if ((ctxt
) && (ctxt
->getNsForNodeFunc
)) {
8943 * User-defined behaviour.
8945 ns
= ctxt
->getNsForNodeFunc(ctxt
, cur
,
8946 cur
->ns
->href
, cur
->ns
->prefix
);
8948 * Insert mapping if ns is available; it's the users fault
8951 if (xmlDOMWrapNsMapAddItem(&nsMap
, -1,
8952 cur
->ns
, ns
, XML_TREE_NSMAP_CUSTOM
) == NULL
)
8953 goto internal_error
;
8957 * Aquire a normalized ns-decl and add it to the map.
8959 if (xmlDOMWrapNSNormAquireNormalizedNs(destDoc
,
8960 /* ns-decls on curElem or on destDoc->oldNs */
8961 destParent
? curElem
: NULL
,
8965 /* ns-decls must be prefixed for attributes. */
8966 (cur
->type
== XML_ATTRIBUTE_NODE
) ? 1 : 0) == -1)
8967 goto internal_error
;
8972 * Further node properties.
8973 * TODO: Is this all?
8975 XML_TREE_ADOPT_STR(cur
->name
)
8976 if (cur
->type
== XML_ELEMENT_NODE
) {
8983 if (cur
->properties
!= NULL
) {
8985 * Process first attribute node.
8987 cur
= (xmlNodePtr
) cur
->properties
;
8994 if ((sourceDoc
!= NULL
) &&
8995 (((xmlAttrPtr
) cur
)->atype
== XML_ATTRIBUTE_ID
))
8997 xmlRemoveID(sourceDoc
, (xmlAttrPtr
) cur
);
8999 ((xmlAttrPtr
) cur
)->atype
= 0;
9000 ((xmlAttrPtr
) cur
)->psvi
= NULL
;
9004 case XML_CDATA_SECTION_NODE
:
9006 * This puts the content in the dest dict, only if
9007 * it was previously in the source dict.
9009 XML_TREE_ADOPT_STR_2(cur
->content
)
9011 case XML_ENTITY_REF_NODE
:
9013 * Remove reference to the entitity-node.
9015 cur
->content
= NULL
;
9016 cur
->children
= NULL
;
9018 if ((destDoc
->intSubset
) || (destDoc
->extSubset
)) {
9021 * Assign new entity-node if available.
9023 ent
= xmlGetDocEntity(destDoc
, cur
->name
);
9025 cur
->content
= ent
->content
;
9026 cur
->children
= (xmlNodePtr
) ent
;
9027 cur
->last
= (xmlNodePtr
) ent
;
9032 XML_TREE_ADOPT_STR(cur
->name
)
9033 XML_TREE_ADOPT_STR_2(cur
->content
)
9035 case XML_COMMENT_NODE
:
9038 goto internal_error
;
9043 if (cur
->children
!= NULL
) {
9044 cur
= cur
->children
;
9051 if ((cur
->type
== XML_ELEMENT_NODE
) ||
9052 (cur
->type
== XML_XINCLUDE_START
) ||
9053 (cur
->type
== XML_XINCLUDE_END
))
9056 * TODO: Do we expect nsDefs on XML_XINCLUDE_START?
9058 if (XML_NSMAP_NOTEMPTY(nsMap
)) {
9062 while ((nsMap
->last
!= NULL
) &&
9063 (nsMap
->last
->depth
>= depth
))
9065 XML_NSMAP_POP(nsMap
, mi
)
9070 XML_NSMAP_FOREACH(nsMap
, mi
) {
9071 if (mi
->shadowDepth
>= depth
)
9072 mi
->shadowDepth
= -1;
9077 if (cur
->next
!= NULL
)
9079 else if ((cur
->type
== XML_ATTRIBUTE_NODE
) &&
9080 (cur
->parent
->children
!= NULL
))
9082 cur
= cur
->parent
->children
;
9098 if (nsMap
!= NULL
) {
9099 if ((ctxt
) && (ctxt
->namespaceMap
== nsMap
)) {
9101 * Just cleanup the map but don't free.
9105 nsMap
->last
->next
= nsMap
->pool
;
9106 nsMap
->pool
= nsMap
->first
;
9107 nsMap
->first
= NULL
;
9110 xmlDOMWrapNsMapFree(nsMap
);
9116 * xmlDOMWrapCloneNode:
9117 * @ctxt: the optional context for custom processing
9118 * @sourceDoc: the optional sourceDoc
9119 * @node: the node to start with
9120 * @resNode: the clone of the given @node
9121 * @destDoc: the destination doc
9122 * @destParent: the optional new parent of @node in @destDoc
9123 * @deep: descend into child if set
9124 * @options: option flags
9126 * References of out-of scope ns-decls are remapped to point to @destDoc:
9127 * 1) If @destParent is given, then nsDef entries on element-nodes are used
9128 * 2) If *no* @destParent is given, then @destDoc->oldNs entries are used.
9129 * This is the case when you don't know already where the cloned branch
9132 * If @destParent is given, it ensures that the tree is namespace
9133 * wellformed by creating additional ns-decls where needed.
9134 * Note that, since prefixes of already existent ns-decls can be
9135 * shadowed by this process, it could break QNames in attribute
9136 * values or element content.
9138 * 1) What to do with XInclude? Currently this returns an error for XInclude.
9140 * Returns 0 if the operation succeeded,
9141 * 1 if a node of unsupported (or not yet supported) type was given,
9142 * -1 on API/internal errors.
9146 xmlDOMWrapCloneNode(xmlDOMWrapCtxtPtr ctxt
,
9147 xmlDocPtr sourceDoc
,
9149 xmlNodePtr
*resNode
,
9151 xmlNodePtr destParent
,
9153 int options ATTRIBUTE_UNUSED
)
9156 xmlNodePtr cur
, curElem
= NULL
;
9157 xmlNsMapPtr nsMap
= NULL
;
9161 /* int adoptStr = 1; */
9162 /* gather @parent's ns-decls. */
9166 * TODO: @ancestorsOnly should be set per option.
9169 int ancestorsOnly
= 0;
9170 xmlNodePtr resultClone
= NULL
, clone
= NULL
, parentClone
= NULL
, prevClone
= NULL
;
9171 xmlNsPtr cloneNs
= NULL
, *cloneNsDefSlot
= NULL
;
9172 xmlDictPtr dict
; /* The destination dict */
9174 if ((node
== NULL
) || (resNode
== NULL
) || (destDoc
== NULL
))
9177 * TODO: Initially we support only element-nodes.
9179 if (node
->type
!= XML_ELEMENT_NODE
)
9182 * Check node->doc sanity.
9184 if ((node
->doc
!= NULL
) && (sourceDoc
!= NULL
) &&
9185 (node
->doc
!= sourceDoc
)) {
9187 * Might be an XIncluded node.
9191 if (sourceDoc
== NULL
)
9192 sourceDoc
= node
->doc
;
9193 if (sourceDoc
== NULL
)
9196 dict
= destDoc
->dict
;
9198 * Reuse the namespace map of the context.
9201 nsMap
= (xmlNsMapPtr
) ctxt
->namespaceMap
;
9206 while (cur
!= NULL
) {
9207 if (cur
->doc
!= sourceDoc
) {
9209 * We'll assume XIncluded nodes if the doc differs.
9210 * TODO: Do we need to reconciliate XIncluded nodes?
9211 * TODO: This here returns -1 in this case.
9213 goto internal_error
;
9216 * Create a new node.
9218 switch (cur
->type
) {
9219 case XML_XINCLUDE_START
:
9220 case XML_XINCLUDE_END
:
9222 * TODO: What to do with XInclude?
9224 goto internal_error
;
9226 case XML_ELEMENT_NODE
:
9228 case XML_CDATA_SECTION_NODE
:
9229 case XML_COMMENT_NODE
:
9231 case XML_DOCUMENT_FRAG_NODE
:
9232 case XML_ENTITY_REF_NODE
:
9233 case XML_ENTITY_NODE
:
9235 * Nodes of xmlNode structure.
9237 clone
= (xmlNodePtr
) xmlMalloc(sizeof(xmlNode
));
9238 if (clone
== NULL
) {
9239 xmlTreeErrMemory("xmlDOMWrapCloneNode(): allocating a node");
9240 goto internal_error
;
9242 memset(clone
, 0, sizeof(xmlNode
));
9244 * Set hierachical links.
9246 if (resultClone
!= NULL
) {
9247 clone
->parent
= parentClone
;
9249 prevClone
->next
= clone
;
9250 clone
->prev
= prevClone
;
9252 parentClone
->children
= clone
;
9254 resultClone
= clone
;
9257 case XML_ATTRIBUTE_NODE
:
9259 * Attributes (xmlAttr).
9261 clone
= (xmlNodePtr
) xmlMalloc(sizeof(xmlAttr
));
9262 if (clone
== NULL
) {
9263 xmlTreeErrMemory("xmlDOMWrapCloneNode(): allocating an attr-node");
9264 goto internal_error
;
9266 memset(clone
, 0, sizeof(xmlAttr
));
9268 * Set hierachical links.
9269 * TODO: Change this to add to the end of attributes.
9271 if (resultClone
!= NULL
) {
9272 clone
->parent
= parentClone
;
9274 prevClone
->next
= clone
;
9275 clone
->prev
= prevClone
;
9277 parentClone
->properties
= (xmlAttrPtr
) clone
;
9279 resultClone
= clone
;
9283 * TODO QUESTION: Any other nodes expected?
9285 goto internal_error
;
9288 clone
->type
= cur
->type
;
9289 clone
->doc
= destDoc
;
9292 * Clone the name of the node if any.
9294 if (cur
->name
== xmlStringText
)
9295 clone
->name
= xmlStringText
;
9296 else if (cur
->name
== xmlStringTextNoenc
)
9298 * NOTE: Although xmlStringTextNoenc is never assigned to a node
9299 * in tree.c, it might be set in Libxslt via
9300 * "xsl:disable-output-escaping".
9302 clone
->name
= xmlStringTextNoenc
;
9303 else if (cur
->name
== xmlStringComment
)
9304 clone
->name
= xmlStringComment
;
9305 else if (cur
->name
!= NULL
) {
9306 DICT_CONST_COPY(cur
->name
, clone
->name
);
9309 switch (cur
->type
) {
9310 case XML_XINCLUDE_START
:
9311 case XML_XINCLUDE_END
:
9316 case XML_ELEMENT_NODE
:
9320 * Namespace declarations.
9322 if (cur
->nsDef
!= NULL
) {
9324 if (destParent
&& (ctxt
== NULL
)) {
9326 * Gather @parent's in-scope ns-decls.
9328 if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap
,
9330 goto internal_error
;
9335 * Clone namespace declarations.
9337 cloneNsDefSlot
= &(clone
->nsDef
);
9338 for (ns
= cur
->nsDef
; ns
!= NULL
; ns
= ns
->next
) {
9340 * Create a new xmlNs.
9342 cloneNs
= (xmlNsPtr
) xmlMalloc(sizeof(xmlNs
));
9343 if (cloneNs
== NULL
) {
9344 xmlTreeErrMemory("xmlDOMWrapCloneNode(): "
9345 "allocating namespace");
9348 memset(cloneNs
, 0, sizeof(xmlNs
));
9349 cloneNs
->type
= XML_LOCAL_NAMESPACE
;
9351 if (ns
->href
!= NULL
)
9352 cloneNs
->href
= xmlStrdup(ns
->href
);
9353 if (ns
->prefix
!= NULL
)
9354 cloneNs
->prefix
= xmlStrdup(ns
->prefix
);
9356 *cloneNsDefSlot
= cloneNs
;
9357 cloneNsDefSlot
= &(cloneNs
->next
);
9360 * Note that for custom handling of ns-references,
9361 * the ns-decls need not be stored in the ns-map,
9362 * since they won't be referenced by node->ns.
9364 if ((ctxt
== NULL
) ||
9365 (ctxt
->getNsForNodeFunc
== NULL
))
9368 * Does it shadow any ns-decl?
9370 if (XML_NSMAP_NOTEMPTY(nsMap
)) {
9371 XML_NSMAP_FOREACH(nsMap
, mi
) {
9372 if ((mi
->depth
>= XML_TREE_NSMAP_PARENT
) &&
9373 (mi
->shadowDepth
== -1) &&
9374 ((ns
->prefix
== mi
->newNs
->prefix
) ||
9375 xmlStrEqual(ns
->prefix
,
9376 mi
->newNs
->prefix
))) {
9378 * Mark as shadowed at the current
9381 mi
->shadowDepth
= depth
;
9388 if (xmlDOMWrapNsMapAddItem(&nsMap
, -1,
9389 ns
, cloneNs
, depth
) == NULL
)
9390 goto internal_error
;
9394 /* cur->ns will be processed further down. */
9396 case XML_ATTRIBUTE_NODE
:
9397 /* IDs will be processed further down. */
9398 /* cur->ns will be processed further down. */
9401 case XML_CDATA_SECTION_NODE
:
9403 * Note that this will also cover the values of attributes.
9405 DICT_COPY(cur
->content
, clone
->content
);
9407 case XML_ENTITY_NODE
:
9408 /* TODO: What to do here? */
9410 case XML_ENTITY_REF_NODE
:
9411 if (sourceDoc
!= destDoc
) {
9412 if ((destDoc
->intSubset
) || (destDoc
->extSubset
)) {
9415 * Different doc: Assign new entity-node if available.
9417 ent
= xmlGetDocEntity(destDoc
, cur
->name
);
9419 clone
->content
= ent
->content
;
9420 clone
->children
= (xmlNodePtr
) ent
;
9421 clone
->last
= (xmlNodePtr
) ent
;
9426 * Same doc: Use the current node's entity declaration
9429 clone
->content
= cur
->content
;
9430 clone
->children
= cur
->children
;
9431 clone
->last
= cur
->last
;
9435 DICT_COPY(cur
->content
, clone
->content
);
9437 case XML_COMMENT_NODE
:
9438 DICT_COPY(cur
->content
, clone
->content
);
9441 goto internal_error
;
9444 if (cur
->ns
== NULL
)
9445 goto end_ns_reference
;
9447 /* handle_ns_reference: */
9449 ** The following will take care of references to ns-decls ********
9450 ** and is intended only for element- and attribute-nodes.
9454 if (destParent
&& (ctxt
== NULL
)) {
9455 if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap
, destParent
) == -1)
9456 goto internal_error
;
9461 * Adopt ns-references.
9463 if (XML_NSMAP_NOTEMPTY(nsMap
)) {
9465 * Search for a mapping.
9467 XML_NSMAP_FOREACH(nsMap
, mi
) {
9468 if ((mi
->shadowDepth
== -1) &&
9469 (cur
->ns
== mi
->oldNs
)) {
9471 * This is the nice case: a mapping was found.
9473 clone
->ns
= mi
->newNs
;
9474 goto end_ns_reference
;
9479 * No matching namespace in scope. We need a new one.
9481 if ((ctxt
!= NULL
) && (ctxt
->getNsForNodeFunc
!= NULL
)) {
9483 * User-defined behaviour.
9485 ns
= ctxt
->getNsForNodeFunc(ctxt
, cur
,
9486 cur
->ns
->href
, cur
->ns
->prefix
);
9488 * Add user's mapping.
9490 if (xmlDOMWrapNsMapAddItem(&nsMap
, -1,
9491 cur
->ns
, ns
, XML_TREE_NSMAP_CUSTOM
) == NULL
)
9492 goto internal_error
;
9496 * Aquire a normalized ns-decl and add it to the map.
9498 if (xmlDOMWrapNSNormAquireNormalizedNs(destDoc
,
9499 /* ns-decls on curElem or on destDoc->oldNs */
9500 destParent
? curElem
: NULL
,
9503 /* if we need to search only in the ancestor-axis */
9505 /* ns-decls must be prefixed for attributes. */
9506 (cur
->type
== XML_ATTRIBUTE_NODE
) ? 1 : 0) == -1)
9507 goto internal_error
;
9514 * Some post-processing.
9516 * Handle ID attributes.
9518 if ((clone
->type
== XML_ATTRIBUTE_NODE
) &&
9519 (clone
->parent
!= NULL
))
9521 if (xmlIsID(destDoc
, clone
->parent
, (xmlAttrPtr
) clone
)) {
9525 idVal
= xmlNodeListGetString(cur
->doc
, cur
->children
, 1);
9526 if (idVal
!= NULL
) {
9527 if (xmlAddID(NULL
, destDoc
, idVal
, (xmlAttrPtr
) cur
) == NULL
) {
9528 /* TODO: error message. */
9530 goto internal_error
;
9538 ** The following will traverse the tree **************************
9541 * Walk the element's attributes before descending into child-nodes.
9543 if ((cur
->type
== XML_ELEMENT_NODE
) && (cur
->properties
!= NULL
)) {
9545 parentClone
= clone
;
9546 cur
= (xmlNodePtr
) cur
->properties
;
9551 * Descend into child-nodes.
9553 if (cur
->children
!= NULL
) {
9554 if (deep
|| (cur
->type
== XML_ATTRIBUTE_NODE
)) {
9556 parentClone
= clone
;
9557 cur
= cur
->children
;
9564 * At this point we are done with the node, its content
9565 * and an element-nodes's attribute-nodes.
9569 if ((cur
->type
== XML_ELEMENT_NODE
) ||
9570 (cur
->type
== XML_XINCLUDE_START
) ||
9571 (cur
->type
== XML_XINCLUDE_END
)) {
9573 * TODO: Do we expect nsDefs on XML_XINCLUDE_START?
9575 if (XML_NSMAP_NOTEMPTY(nsMap
)) {
9579 while ((nsMap
->last
!= NULL
) &&
9580 (nsMap
->last
->depth
>= depth
))
9582 XML_NSMAP_POP(nsMap
, mi
)
9587 XML_NSMAP_FOREACH(nsMap
, mi
) {
9588 if (mi
->shadowDepth
>= depth
)
9589 mi
->shadowDepth
= -1;
9594 if (cur
->next
!= NULL
) {
9597 } else if (cur
->type
!= XML_ATTRIBUTE_NODE
) {
9601 if (clone
->parent
!= NULL
)
9602 clone
->parent
->last
= clone
;
9603 clone
= clone
->parent
;
9604 parentClone
= clone
->parent
;
9606 * Process parent --> next;
9611 /* This is for attributes only. */
9612 clone
= clone
->parent
;
9613 parentClone
= clone
->parent
;
9615 * Process parent-element --> children.
9630 if (nsMap
!= NULL
) {
9631 if ((ctxt
) && (ctxt
->namespaceMap
== nsMap
)) {
9633 * Just cleanup the map but don't free.
9637 nsMap
->last
->next
= nsMap
->pool
;
9638 nsMap
->pool
= nsMap
->first
;
9639 nsMap
->first
= NULL
;
9642 xmlDOMWrapNsMapFree(nsMap
);
9645 * TODO: Should we try a cleanup of the cloned node in case of a
9648 *resNode
= resultClone
;
9653 * xmlDOMWrapAdoptAttr:
9654 * @ctxt: the optional context for custom processing
9655 * @sourceDoc: the optional source document of attr
9656 * @attr: the attribute-node to be adopted
9657 * @destDoc: the destination doc for adoption
9658 * @destParent: the optional new parent of @attr in @destDoc
9659 * @options: option flags
9661 * @attr is adopted by @destDoc.
9662 * Ensures that ns-references point to @destDoc: either to
9663 * elements->nsDef entries if @destParent is given, or to
9664 * @destDoc->oldNs otherwise.
9666 * Returns 0 if succeeded, -1 otherwise and on API/internal errors.
9669 xmlDOMWrapAdoptAttr(xmlDOMWrapCtxtPtr ctxt
,
9670 xmlDocPtr sourceDoc
,
9673 xmlNodePtr destParent
,
9674 int options ATTRIBUTE_UNUSED
)
9679 if ((attr
== NULL
) || (destDoc
== NULL
))
9682 attr
->doc
= destDoc
;
9683 if (attr
->ns
!= NULL
) {
9687 /* TODO: User defined. */
9689 /* XML Namespace. */
9690 if (IS_STR_XML(attr
->ns
->prefix
)) {
9691 ns
= xmlTreeEnsureXMLDecl(destDoc
);
9692 } else if (destParent
== NULL
) {
9694 * Store in @destDoc->oldNs.
9696 ns
= xmlDOMWrapStoreNs(destDoc
, attr
->ns
->href
, attr
->ns
->prefix
);
9699 * Declare on @destParent.
9701 if (xmlSearchNsByNamespaceStrict(destDoc
, destParent
, attr
->ns
->href
,
9703 goto internal_error
;
9705 ns
= xmlDOMWrapNSNormDeclareNsForced(destDoc
, destParent
,
9706 attr
->ns
->href
, attr
->ns
->prefix
, 1);
9710 goto internal_error
;
9714 XML_TREE_ADOPT_STR(attr
->name
);
9720 if (attr
->children
== NULL
)
9722 cur
= attr
->children
;
9723 while (cur
!= NULL
) {
9725 switch (cur
->type
) {
9727 case XML_CDATA_SECTION_NODE
:
9728 XML_TREE_ADOPT_STR_2(cur
->content
)
9730 case XML_ENTITY_REF_NODE
:
9732 * Remove reference to the entitity-node.
9734 cur
->content
= NULL
;
9735 cur
->children
= NULL
;
9737 if ((destDoc
->intSubset
) || (destDoc
->extSubset
)) {
9740 * Assign new entity-node if available.
9742 ent
= xmlGetDocEntity(destDoc
, cur
->name
);
9744 cur
->content
= ent
->content
;
9745 cur
->children
= (xmlNodePtr
) ent
;
9746 cur
->last
= (xmlNodePtr
) ent
;
9753 if (cur
->children
!= NULL
) {
9754 cur
= cur
->children
;
9758 if (cur
== (xmlNodePtr
) attr
)
9760 if (cur
->next
!= NULL
)
9773 * xmlDOMWrapAdoptNode:
9774 * @ctxt: the optional context for custom processing
9775 * @sourceDoc: the optional sourceDoc
9776 * @node: the node to start with
9777 * @destDoc: the destination doc
9778 * @destParent: the optional new parent of @node in @destDoc
9779 * @options: option flags
9781 * References of out-of scope ns-decls are remapped to point to @destDoc:
9782 * 1) If @destParent is given, then nsDef entries on element-nodes are used
9783 * 2) If *no* @destParent is given, then @destDoc->oldNs entries are used
9784 * This is the case when you have an unliked node and just want to move it
9787 * If @destParent is given, it ensures that the tree is namespace
9788 * wellformed by creating additional ns-decls where needed.
9789 * Note that, since prefixes of already existent ns-decls can be
9790 * shadowed by this process, it could break QNames in attribute
9791 * values or element content.
9792 * NOTE: This function was not intensively tested.
9794 * Returns 0 if the operation succeeded,
9795 * 1 if a node of unsupported type was given,
9796 * 2 if a node of not yet supported type was given and
9797 * -1 on API/internal errors.
9800 xmlDOMWrapAdoptNode(xmlDOMWrapCtxtPtr ctxt
,
9801 xmlDocPtr sourceDoc
,
9804 xmlNodePtr destParent
,
9807 if ((node
== NULL
) || (destDoc
== NULL
) ||
9808 ((destParent
!= NULL
) && (destParent
->doc
!= destDoc
)))
9811 * Check node->doc sanity.
9813 if ((node
->doc
!= NULL
) && (sourceDoc
!= NULL
) &&
9814 (node
->doc
!= sourceDoc
)) {
9816 * Might be an XIncluded node.
9820 if (sourceDoc
== NULL
)
9821 sourceDoc
= node
->doc
;
9822 if (sourceDoc
== destDoc
)
9824 switch (node
->type
) {
9825 case XML_ELEMENT_NODE
:
9826 case XML_ATTRIBUTE_NODE
:
9828 case XML_CDATA_SECTION_NODE
:
9829 case XML_ENTITY_REF_NODE
:
9831 case XML_COMMENT_NODE
:
9833 case XML_DOCUMENT_FRAG_NODE
:
9834 /* TODO: Support document-fragment-nodes. */
9840 * Unlink only if @node was not already added to @destParent.
9842 if ((node
->parent
!= NULL
) && (destParent
!= node
->parent
))
9843 xmlUnlinkNode(node
);
9845 if (node
->type
== XML_ELEMENT_NODE
) {
9846 return (xmlDOMWrapAdoptBranch(ctxt
, sourceDoc
, node
,
9847 destDoc
, destParent
, options
));
9848 } else if (node
->type
== XML_ATTRIBUTE_NODE
) {
9849 return (xmlDOMWrapAdoptAttr(ctxt
, sourceDoc
,
9850 (xmlAttrPtr
) node
, destDoc
, destParent
, options
));
9852 xmlNodePtr cur
= node
;
9857 * Optimize string adoption.
9859 if ((sourceDoc
!= NULL
) &&
9860 (sourceDoc
->dict
== destDoc
->dict
))
9862 switch (node
->type
) {
9864 case XML_CDATA_SECTION_NODE
:
9865 XML_TREE_ADOPT_STR_2(node
->content
)
9867 case XML_ENTITY_REF_NODE
:
9869 * Remove reference to the entitity-node.
9871 node
->content
= NULL
;
9872 node
->children
= NULL
;
9874 if ((destDoc
->intSubset
) || (destDoc
->extSubset
)) {
9877 * Assign new entity-node if available.
9879 ent
= xmlGetDocEntity(destDoc
, node
->name
);
9881 node
->content
= ent
->content
;
9882 node
->children
= (xmlNodePtr
) ent
;
9883 node
->last
= (xmlNodePtr
) ent
;
9886 XML_TREE_ADOPT_STR(node
->name
)
9889 XML_TREE_ADOPT_STR(node
->name
)
9890 XML_TREE_ADOPT_STR_2(node
->content
)
9901 #include "elfgcchack.h"