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>
41 xmlNsPtr
xmlNewReconciliedNs(xmlDocPtr doc
, xmlNodePtr tree
, xmlNsPtr ns
);
43 /************************************************************************
45 * A few static variables and macros *
47 ************************************************************************/
48 /* #undef xmlStringText */
49 const xmlChar xmlStringText
[] = { 't', 'e', 'x', 't', 0 };
50 /* #undef xmlStringTextNoenc */
51 const xmlChar xmlStringTextNoenc
[] =
52 { 't', 'e', 'x', 't', 'n', 'o', 'e', 'n', 'c', 0 };
53 /* #undef xmlStringComment */
54 const xmlChar xmlStringComment
[] = { 'c', 'o', 'm', 'm', 'e', 'n', 't', 0 };
56 static int xmlCompressMode
= 0;
57 static int xmlCheckDTD
= 1;
59 #define UPDATE_LAST_CHILD_AND_PARENT(n) if ((n) != NULL) { \
60 xmlNodePtr ulccur = (n)->children; \
61 if (ulccur == NULL) { \
64 while (ulccur->next != NULL) { \
65 ulccur->parent = (n); \
66 ulccur = ulccur->next; \
68 ulccur->parent = (n); \
72 /* #define DEBUG_BUFFER */
73 /* #define DEBUG_TREE */
75 /************************************************************************
77 * Functions to move to entities.c once the *
78 * API freeze is smoothen and they can be made public. *
80 ************************************************************************/
81 #include <libxml/hash.h>
84 * xmlGetEntityFromDtd:
85 * @dtd: A pointer to the DTD to search
86 * @name: The entity name
88 * Do an entity lookup in the DTD entity hash table and
89 * return the corresponding entity, if found.
91 * Returns A pointer to the entity structure or NULL if not found.
94 xmlGetEntityFromDtd(xmlDtdPtr dtd
, const xmlChar
*name
) {
95 xmlEntitiesTablePtr table
;
97 if((dtd
!= NULL
) && (dtd
->entities
!= NULL
)) {
98 table
= (xmlEntitiesTablePtr
) dtd
->entities
;
99 return((xmlEntityPtr
) xmlHashLookup(table
, name
));
100 /* return(xmlGetEntityFromTable(table, name)); */
105 * xmlGetParameterEntityFromDtd:
106 * @dtd: A pointer to the DTD to search
107 * @name: The entity name
109 * Do an entity lookup in the DTD pararmeter entity hash table and
110 * return the corresponding entity, if found.
112 * Returns A pointer to the entity structure or NULL if not found.
115 xmlGetParameterEntityFromDtd(xmlDtdPtr dtd
, const xmlChar
*name
) {
116 xmlEntitiesTablePtr table
;
118 if ((dtd
!= NULL
) && (dtd
->pentities
!= NULL
)) {
119 table
= (xmlEntitiesTablePtr
) dtd
->pentities
;
120 return((xmlEntityPtr
) xmlHashLookup(table
, name
));
121 /* return(xmlGetEntityFromTable(table, name)); */
126 /************************************************************************
128 * Allocation and deallocation of basic structures *
130 ************************************************************************/
133 * xmlSetBufferAllocationScheme:
134 * @scheme: allocation method to use
136 * Set the buffer allocation method. Types are
137 * XML_BUFFER_ALLOC_EXACT - use exact sizes, keeps memory usage down
138 * XML_BUFFER_ALLOC_DOUBLEIT - double buffer when extra needed,
139 * improves performance
142 xmlSetBufferAllocationScheme(xmlBufferAllocationScheme scheme
) {
143 xmlBufferAllocScheme
= scheme
;
147 * xmlGetBufferAllocationScheme:
150 * XML_BUFFER_ALLOC_EXACT - use exact sizes, keeps memory usage down
151 * XML_BUFFER_ALLOC_DOUBLEIT - double buffer when extra needed,
152 * improves performance
154 * Returns the current allocation scheme
156 xmlBufferAllocationScheme
157 xmlGetBufferAllocationScheme(void) {
158 return(xmlBufferAllocScheme
);
163 * @node: the element carrying the namespace
164 * @href: the URI associated
165 * @prefix: the prefix for the namespace
167 * Creation of a new Namespace. This function will refuse to create
168 * a namespace with a similar prefix than an existing one present on this
170 * We use href==NULL in the case of an element creation where the namespace
172 * Returns a new namespace pointer or NULL
175 xmlNewNs(xmlNodePtr node
, const xmlChar
*href
, const xmlChar
*prefix
) {
178 if ((node
!= NULL
) && (node
->type
!= XML_ELEMENT_NODE
))
181 if ((prefix
!= NULL
) && (xmlStrEqual(prefix
, BAD_CAST
"xml")))
185 * Allocate a new Namespace and fill the fields.
187 cur
= (xmlNsPtr
) xmlMalloc(sizeof(xmlNs
));
189 xmlGenericError(xmlGenericErrorContext
,
190 "xmlNewNs : malloc failed\n");
193 memset(cur
, 0, sizeof(xmlNs
));
194 cur
->type
= XML_LOCAL_NAMESPACE
;
197 cur
->href
= xmlStrdup(href
);
199 cur
->prefix
= xmlStrdup(prefix
);
202 * Add it at the end to preserve parsing order ...
203 * and checks for existing use of the prefix
206 if (node
->nsDef
== NULL
) {
209 xmlNsPtr prev
= node
->nsDef
;
211 if (((prev
->prefix
== NULL
) && (cur
->prefix
== NULL
)) ||
212 (xmlStrEqual(prev
->prefix
, cur
->prefix
))) {
216 while (prev
->next
!= NULL
) {
218 if (((prev
->prefix
== NULL
) && (cur
->prefix
== NULL
)) ||
219 (xmlStrEqual(prev
->prefix
, cur
->prefix
))) {
232 * @node: a node in the document
233 * @ns: a namespace pointer
235 * Associate a namespace to a node, a posteriori.
238 xmlSetNs(xmlNodePtr node
, xmlNsPtr ns
) {
241 xmlGenericError(xmlGenericErrorContext
,
242 "xmlSetNs: node == NULL\n");
251 * @cur: the namespace pointer
253 * Free up the structures associated to a namespace
256 xmlFreeNs(xmlNsPtr cur
) {
259 xmlGenericError(xmlGenericErrorContext
,
260 "xmlFreeNs : ns == NULL\n");
264 if (cur
->href
!= NULL
) xmlFree((char *) cur
->href
);
265 if (cur
->prefix
!= NULL
) xmlFree((char *) cur
->prefix
);
271 * @cur: the first namespace pointer
273 * Free up all the structures associated to the chained namespaces.
276 xmlFreeNsList(xmlNsPtr cur
) {
280 xmlGenericError(xmlGenericErrorContext
,
281 "xmlFreeNsList : ns == NULL\n");
285 while (cur
!= NULL
) {
294 * @doc: the document pointer
295 * @name: the DTD name
296 * @ExternalID: the external ID
297 * @SystemID: the system ID
299 * Creation of a new DTD for the external subset. To create an
300 * internal subset, use xmlCreateIntSubset().
302 * Returns a pointer to the new DTD structure
305 xmlNewDtd(xmlDocPtr doc
, const xmlChar
*name
,
306 const xmlChar
*ExternalID
, const xmlChar
*SystemID
) {
309 if ((doc
!= NULL
) && (doc
->extSubset
!= NULL
)) {
311 xmlGenericError(xmlGenericErrorContext
,
312 "xmlNewDtd(%s): document %s already have a DTD %s\n",
313 /* !!! */ (char *) name
, doc
->name
,
314 /* !!! */ (char *)doc
->extSubset
->name
);
320 * Allocate a new DTD and fill the fields.
322 cur
= (xmlDtdPtr
) xmlMalloc(sizeof(xmlDtd
));
324 xmlGenericError(xmlGenericErrorContext
,
325 "xmlNewDtd : malloc failed\n");
328 memset(cur
, 0 , sizeof(xmlDtd
));
329 cur
->type
= XML_DTD_NODE
;
332 cur
->name
= xmlStrdup(name
);
333 if (ExternalID
!= NULL
)
334 cur
->ExternalID
= xmlStrdup(ExternalID
);
335 if (SystemID
!= NULL
)
336 cur
->SystemID
= xmlStrdup(SystemID
);
338 doc
->extSubset
= cur
;
346 * @doc: the document pointer
348 * Get the internal subset of a document
349 * Returns a pointer to the DTD structure or NULL if not found
353 xmlGetIntSubset(xmlDocPtr doc
) {
359 while (cur
!= NULL
) {
360 if (cur
->type
== XML_DTD_NODE
)
361 return((xmlDtdPtr
) cur
);
364 return((xmlDtdPtr
) doc
->intSubset
);
368 * xmlCreateIntSubset:
369 * @doc: the document pointer
370 * @name: the DTD name
371 * @ExternalID: the external (PUBLIC) ID
372 * @SystemID: the system ID
374 * Create the internal subset of a document
375 * Returns a pointer to the new DTD structure
378 xmlCreateIntSubset(xmlDocPtr doc
, const xmlChar
*name
,
379 const xmlChar
*ExternalID
, const xmlChar
*SystemID
) {
382 if ((doc
!= NULL
) && (xmlGetIntSubset(doc
) != NULL
)) {
384 xmlGenericError(xmlGenericErrorContext
,
386 "xmlCreateIntSubset(): document %s already have an internal subset\n",
393 * Allocate a new DTD and fill the fields.
395 cur
= (xmlDtdPtr
) xmlMalloc(sizeof(xmlDtd
));
397 xmlGenericError(xmlGenericErrorContext
,
398 "xmlCreateIntSubset : malloc failed\n");
401 memset(cur
, 0, sizeof(xmlDtd
));
402 cur
->type
= XML_DTD_NODE
;
405 cur
->name
= xmlStrdup(name
);
406 if (ExternalID
!= NULL
)
407 cur
->ExternalID
= xmlStrdup(ExternalID
);
408 if (SystemID
!= NULL
)
409 cur
->SystemID
= xmlStrdup(SystemID
);
411 doc
->intSubset
= cur
;
414 if (doc
->children
== NULL
) {
415 doc
->children
= (xmlNodePtr
) cur
;
416 doc
->last
= (xmlNodePtr
) cur
;
418 if (doc
->type
== XML_HTML_DOCUMENT_NODE
) {
421 prev
= doc
->children
;
422 prev
->prev
= (xmlNodePtr
) cur
;
424 doc
->children
= (xmlNodePtr
) cur
;
428 next
= doc
->children
;
429 while ((next
!= NULL
) && (next
->type
!= XML_ELEMENT_NODE
))
432 cur
->prev
= doc
->last
;
433 cur
->prev
->next
= (xmlNodePtr
) cur
;
435 doc
->last
= (xmlNodePtr
) cur
;
438 cur
->prev
= next
->prev
;
439 if (cur
->prev
== NULL
)
440 doc
->children
= (xmlNodePtr
) cur
;
442 cur
->prev
->next
= (xmlNodePtr
) cur
;
443 next
->prev
= (xmlNodePtr
) cur
;
453 * @cur: the DTD structure to free up
455 * Free a DTD structure.
458 xmlFreeDtd(xmlDtdPtr cur
) {
461 xmlGenericError(xmlGenericErrorContext
,
462 "xmlFreeDtd : DTD == NULL\n");
466 if (cur
->children
!= NULL
) {
467 xmlNodePtr next
, c
= cur
->children
;
470 * Cleanup all the DTD comments they are not in the DTD
475 if (c
->type
== XML_COMMENT_NODE
) {
482 if (cur
->name
!= NULL
) xmlFree((char *) cur
->name
);
483 if (cur
->SystemID
!= NULL
) xmlFree((char *) cur
->SystemID
);
484 if (cur
->ExternalID
!= NULL
) xmlFree((char *) cur
->ExternalID
);
486 if (cur
->notations
!= NULL
)
487 xmlFreeNotationTable((xmlNotationTablePtr
) cur
->notations
);
489 if (cur
->elements
!= NULL
)
490 xmlFreeElementTable((xmlElementTablePtr
) cur
->elements
);
491 if (cur
->attributes
!= NULL
)
492 xmlFreeAttributeTable((xmlAttributeTablePtr
) cur
->attributes
);
493 if (cur
->entities
!= NULL
)
494 xmlFreeEntitiesTable((xmlEntitiesTablePtr
) cur
->entities
);
495 if (cur
->pentities
!= NULL
)
496 xmlFreeEntitiesTable((xmlEntitiesTablePtr
) cur
->pentities
);
503 * @version: xmlChar string giving the version of XML "1.0"
505 * Creates a new XML document
507 * Returns a new document
510 xmlNewDoc(const xmlChar
*version
) {
514 version
= (const xmlChar
*) "1.0";
517 * Allocate a new document and fill the fields.
519 cur
= (xmlDocPtr
) xmlMalloc(sizeof(xmlDoc
));
521 xmlGenericError(xmlGenericErrorContext
,
522 "xmlNewDoc : malloc failed\n");
525 memset(cur
, 0, sizeof(xmlDoc
));
526 cur
->type
= XML_DOCUMENT_NODE
;
528 cur
->version
= xmlStrdup(version
);
529 cur
->standalone
= -1;
530 cur
->compression
= -1; /* not initialized */
532 cur
->charset
= XML_CHAR_ENCODING_UTF8
;
538 * @cur: pointer to the document
540 * Free up all the structures used by a document, tree included.
543 xmlFreeDoc(xmlDocPtr cur
) {
544 xmlDtdPtr extSubset
, intSubset
;
548 xmlGenericError(xmlGenericErrorContext
,
549 "xmlFreeDoc : document == NULL\n");
554 * Do this before freeing the children list to avoid ID lookups
556 if (cur
->ids
!= NULL
) xmlFreeIDTable((xmlIDTablePtr
) cur
->ids
);
558 if (cur
->refs
!= NULL
) xmlFreeRefTable((xmlRefTablePtr
) cur
->refs
);
560 extSubset
= cur
->extSubset
;
561 intSubset
= cur
->intSubset
;
562 if (intSubset
== extSubset
)
564 if (extSubset
!= NULL
) {
565 xmlUnlinkNode((xmlNodePtr
) cur
->extSubset
);
566 cur
->extSubset
= NULL
;
567 xmlFreeDtd(extSubset
);
569 if (intSubset
!= NULL
) {
570 xmlUnlinkNode((xmlNodePtr
) cur
->intSubset
);
571 cur
->intSubset
= NULL
;
572 xmlFreeDtd(intSubset
);
575 if (cur
->children
!= NULL
) xmlFreeNodeList(cur
->children
);
577 if (cur
->version
!= NULL
) xmlFree((char *) cur
->version
);
578 if (cur
->name
!= NULL
) xmlFree((char *) cur
->name
);
579 if (cur
->encoding
!= NULL
) xmlFree((char *) cur
->encoding
);
580 if (cur
->oldNs
!= NULL
) xmlFreeNsList(cur
->oldNs
);
581 if (cur
->URL
!= NULL
) xmlFree((char *) cur
->URL
);
586 * xmlStringLenGetNodeList:
588 * @value: the value of the text
589 * @len: the length of the string value
591 * Parse the value string and build the node list associated. Should
592 * produce a flat tree with only TEXTs and ENTITY_REFs.
593 * Returns a pointer to the first child
596 xmlStringLenGetNodeList(xmlDocPtr doc
, const xmlChar
*value
, int len
) {
597 xmlNodePtr ret
= NULL
, last
= NULL
;
600 const xmlChar
*cur
= value
;
604 if (value
== NULL
) return(NULL
);
607 while ((*cur
!= 0) && (cur
- value
< len
)) {
610 * Save the current text.
613 if ((last
!= NULL
) && (last
->type
== XML_TEXT_NODE
)) {
614 xmlNodeAddContentLen(last
, q
, cur
- q
);
616 node
= xmlNewDocTextLen(doc
, q
, cur
- q
);
617 if (node
== NULL
) return(ret
);
628 * Read the entity string
632 while ((*cur
!= 0) && (cur
- value
< len
) && (*cur
!= ';')) cur
++;
633 if ((*cur
== 0) || (cur
- value
>= len
)) {
635 xmlGenericError(xmlGenericErrorContext
,
636 "xmlStringLenGetNodeList: unterminated entity %30s\n", q
);
642 * Predefined entities don't generate nodes
644 val
= xmlStrndup(q
, cur
- q
);
645 ent
= xmlGetDocEntity(doc
, val
);
647 (ent
->etype
== XML_INTERNAL_PREDEFINED_ENTITY
)) {
649 node
= xmlNewDocText(doc
, ent
->content
);
652 xmlNodeAddContent(last
, ent
->content
);
656 * Create a new REFERENCE_REF node
658 node
= xmlNewReference(doc
, val
);
660 if (val
!= NULL
) xmlFree(val
);
663 else if ((ent
!= NULL
) && (ent
->children
== NULL
)) {
667 xmlStringGetNodeList(doc
, (const xmlChar
*)node
->content
);
670 tmp
->parent
= (xmlNodePtr
)ent
;
691 * Handle the last piece of text.
693 if ((last
!= NULL
) && (last
->type
== XML_TEXT_NODE
)) {
694 xmlNodeAddContentLen(last
, q
, cur
- q
);
696 node
= xmlNewDocTextLen(doc
, q
, cur
- q
);
697 if (node
== NULL
) return(ret
);
711 * xmlStringGetNodeList:
713 * @value: the value of the attribute
715 * Parse the value string and build the node list associated. Should
716 * produce a flat tree with only TEXTs and ENTITY_REFs.
717 * Returns a pointer to the first child
720 xmlStringGetNodeList(xmlDocPtr doc
, const xmlChar
*value
) {
721 xmlNodePtr ret
= NULL
, last
= NULL
;
724 const xmlChar
*cur
= value
;
728 if (value
== NULL
) return(NULL
);
737 * Save the current text.
740 if ((last
!= NULL
) && (last
->type
== XML_TEXT_NODE
)) {
741 xmlNodeAddContentLen(last
, q
, cur
- q
);
743 node
= xmlNewDocTextLen(doc
, q
, cur
- q
);
744 if (node
== NULL
) return(ret
);
755 if ((cur
[1] == '#') && (cur
[2] == 'x')) {
758 while (tmp
!= ';') { /* Non input consuming loop */
759 if ((tmp
>= '0') && (tmp
<= '9'))
760 charval
= charval
* 16 + (tmp
- '0');
761 else if ((tmp
>= 'a') && (tmp
<= 'f'))
762 charval
= charval
* 16 + (tmp
- 'a') + 10;
763 else if ((tmp
>= 'A') && (tmp
<= 'F'))
764 charval
= charval
* 16 + (tmp
- 'A') + 10;
766 xmlGenericError(xmlGenericErrorContext
,
767 "xmlStringGetNodeList: invalid hexadecimal charvalue\n");
777 } else if (cur
[1] == '#') {
780 while (tmp
!= ';') { /* Non input consuming loops */
781 if ((tmp
>= '0') && (tmp
<= '9'))
782 charval
= charval
* 10 + (tmp
- '0');
784 xmlGenericError(xmlGenericErrorContext
,
785 "xmlStringGetNodeList: invalid decimal charvalue\n");
797 * Read the entity string
801 while ((*cur
!= 0) && (*cur
!= ';')) cur
++;
804 xmlGenericError(xmlGenericErrorContext
,
805 "xmlStringGetNodeList: unterminated entity %30s\n", q
);
811 * Predefined entities don't generate nodes
813 val
= xmlStrndup(q
, cur
- q
);
814 ent
= xmlGetDocEntity(doc
, val
);
816 (ent
->etype
== XML_INTERNAL_PREDEFINED_ENTITY
)) {
818 node
= xmlNewDocText(doc
, ent
->content
);
820 } else if (last
->type
!= XML_TEXT_NODE
) {
821 node
= xmlNewDocText(doc
, ent
->content
);
822 last
= xmlAddNextSibling(last
, node
);
824 xmlNodeAddContent(last
, ent
->content
);
828 * Create a new REFERENCE_REF node
830 node
= xmlNewReference(doc
, val
);
832 if (val
!= NULL
) xmlFree(val
);
835 else if ((ent
!= NULL
) && (ent
->children
== NULL
)) {
838 ent
->children
= xmlStringGetNodeList(doc
,
839 (const xmlChar
*)node
->content
);
840 temp
= ent
->children
;
842 temp
->parent
= (xmlNodePtr
)ent
;
849 last
= xmlAddNextSibling(last
, node
);
861 len
= xmlCopyCharMultiByte(buf
, charval
);
863 node
= xmlNewDocText(doc
, buf
);
868 last
= xmlAddNextSibling(last
, node
);
877 if ((cur
!= q
) || (ret
== NULL
)) {
879 * Handle the last piece of text.
881 if ((last
!= NULL
) && (last
->type
== XML_TEXT_NODE
)) {
882 xmlNodeAddContentLen(last
, q
, cur
- q
);
884 node
= xmlNewDocTextLen(doc
, q
, cur
- q
);
885 if (node
== NULL
) return(ret
);
889 last
= xmlAddNextSibling(last
, node
);
897 * xmlNodeListGetString:
900 * @inLine: should we replace entity contents or show their external form
902 * Returns the string equivalent to the text contained in the Node list
903 * made of TEXTs and ENTITY_REFs
904 * Returns a pointer to the string copy, the caller must free it with xmlFree().
907 xmlNodeListGetString(xmlDocPtr doc
, xmlNodePtr list
, int inLine
)
909 xmlNodePtr node
= list
;
916 while (node
!= NULL
) {
917 if ((node
->type
== XML_TEXT_NODE
) ||
918 (node
->type
== XML_CDATA_SECTION_NODE
)) {
920 ret
= xmlStrcat(ret
, node
->content
);
924 buffer
= xmlEncodeEntitiesReentrant(doc
, node
->content
);
925 if (buffer
!= NULL
) {
926 ret
= xmlStrcat(ret
, buffer
);
930 } else if (node
->type
== XML_ENTITY_REF_NODE
) {
932 ent
= xmlGetDocEntity(doc
, node
->name
);
936 /* an entity content can be any "well balanced chunk",
937 * i.e. the result of the content [43] production:
938 * http://www.w3.org/TR/REC-xml#NT-content.
939 * So it can contain text, CDATA section or nested
940 * entity reference nodes (among others).
941 * -> we recursive call xmlNodeListGetString()
942 * which handles these types */
943 buffer
= xmlNodeListGetString(doc
, ent
->children
, 1);
944 if (buffer
!= NULL
) {
945 ret
= xmlStrcat(ret
, buffer
);
949 ret
= xmlStrcat(ret
, node
->content
);
956 ret
= xmlStrncat(ret
, buf
, 1);
957 ret
= xmlStrcat(ret
, node
->name
);
960 ret
= xmlStrncat(ret
, buf
, 1);
965 xmlGenericError(xmlGenericErrorContext
,
966 "xmlGetNodeListString : invalid node type %d\n",
975 * xmlNodeListGetRawString:
978 * @inLine: should we replace entity contents or show their external form
980 * Returns the string equivalent to the text contained in the Node list
981 * made of TEXTs and ENTITY_REFs, contrary to xmlNodeListGetString()
982 * this function doesn't do any character encoding handling.
984 * Returns a pointer to the string copy, the caller must free it with xmlFree().
987 xmlNodeListGetRawString(xmlDocPtr doc
, xmlNodePtr list
, int inLine
)
989 xmlNodePtr node
= list
;
996 while (node
!= NULL
) {
997 if ((node
->type
== XML_TEXT_NODE
) ||
998 (node
->type
== XML_CDATA_SECTION_NODE
)) {
1000 ret
= xmlStrcat(ret
, node
->content
);
1004 buffer
= xmlEncodeSpecialChars(doc
, node
->content
);
1005 if (buffer
!= NULL
) {
1006 ret
= xmlStrcat(ret
, buffer
);
1010 } else if (node
->type
== XML_ENTITY_REF_NODE
) {
1012 ent
= xmlGetDocEntity(doc
, node
->name
);
1016 /* an entity content can be any "well balanced chunk",
1017 * i.e. the result of the content [43] production:
1018 * http://www.w3.org/TR/REC-xml#NT-content.
1019 * So it can contain text, CDATA section or nested
1020 * entity reference nodes (among others).
1021 * -> we recursive call xmlNodeListGetRawString()
1022 * which handles these types */
1024 xmlNodeListGetRawString(doc
, ent
->children
, 1);
1025 if (buffer
!= NULL
) {
1026 ret
= xmlStrcat(ret
, buffer
);
1030 ret
= xmlStrcat(ret
, node
->content
);
1037 ret
= xmlStrncat(ret
, buf
, 1);
1038 ret
= xmlStrcat(ret
, node
->name
);
1041 ret
= xmlStrncat(ret
, buf
, 1);
1046 xmlGenericError(xmlGenericErrorContext
,
1047 "xmlGetNodeListString : invalid node type %d\n",
1058 * @node: the holding node
1059 * @name: the name of the attribute
1060 * @value: the value of the attribute
1062 * Create a new property carried by a node.
1063 * Returns a pointer to the attribute
1066 xmlNewProp(xmlNodePtr node
, const xmlChar
*name
, const xmlChar
*value
) {
1068 xmlDocPtr doc
= NULL
;
1072 xmlGenericError(xmlGenericErrorContext
,
1073 "xmlNewProp : name == NULL\n");
1079 * Allocate a new property and fill the fields.
1081 cur
= (xmlAttrPtr
) xmlMalloc(sizeof(xmlAttr
));
1083 xmlGenericError(xmlGenericErrorContext
,
1084 "xmlNewProp : malloc failed\n");
1087 memset(cur
, 0, sizeof(xmlAttr
));
1088 cur
->type
= XML_ATTRIBUTE_NODE
;
1095 cur
->name
= xmlStrdup(name
);
1096 if (value
!= NULL
) {
1100 buffer
= xmlEncodeEntitiesReentrant(doc
, value
);
1101 cur
->children
= xmlStringGetNodeList(doc
, buffer
);
1103 tmp
= cur
->children
;
1104 while (tmp
!= NULL
) {
1105 tmp
->parent
= (xmlNodePtr
) cur
;
1107 if (tmp
->next
== NULL
)
1115 * Add it at the end to preserve parsing order ...
1118 if (node
->properties
== NULL
) {
1119 node
->properties
= cur
;
1121 xmlAttrPtr prev
= node
->properties
;
1123 while (prev
->next
!= NULL
) prev
= prev
->next
;
1133 * @node: the holding node
1134 * @ns: the namespace
1135 * @name: the name of the attribute
1136 * @value: the value of the attribute
1138 * Create a new property tagged with a namespace and carried by a node.
1139 * Returns a pointer to the attribute
1142 xmlNewNsProp(xmlNodePtr node
, xmlNsPtr ns
, const xmlChar
*name
,
1143 const xmlChar
*value
) {
1145 xmlDocPtr doc
= NULL
;
1149 xmlGenericError(xmlGenericErrorContext
,
1150 "xmlNewNsProp : name == NULL\n");
1156 * Allocate a new property and fill the fields.
1158 cur
= (xmlAttrPtr
) xmlMalloc(sizeof(xmlAttr
));
1160 xmlGenericError(xmlGenericErrorContext
,
1161 "xmlNewNsProp : malloc failed\n");
1164 memset(cur
, 0, sizeof(xmlAttr
));
1165 cur
->type
= XML_ATTRIBUTE_NODE
;
1173 cur
->name
= xmlStrdup(name
);
1174 if (value
!= NULL
) {
1178 buffer
= xmlEncodeEntitiesReentrant(doc
, value
);
1179 cur
->children
= xmlStringGetNodeList(doc
, buffer
);
1181 tmp
= cur
->children
;
1182 while (tmp
!= NULL
) {
1183 tmp
->parent
= (xmlNodePtr
) cur
;
1184 if (tmp
->next
== NULL
)
1192 * Add it at the end to preserve parsing order ...
1195 if (node
->properties
== NULL
) {
1196 node
->properties
= cur
;
1198 xmlAttrPtr prev
= node
->properties
;
1200 while (prev
->next
!= NULL
) prev
= prev
->next
;
1209 * xmlNewNsPropEatName:
1210 * @node: the holding node
1211 * @ns: the namespace
1212 * @name: the name of the attribute
1213 * @value: the value of the attribute
1215 * Create a new property tagged with a namespace and carried by a node.
1216 * Returns a pointer to the attribute
1219 xmlNewNsPropEatName(xmlNodePtr node
, xmlNsPtr ns
, xmlChar
*name
,
1220 const xmlChar
*value
) {
1222 xmlDocPtr doc
= NULL
;
1226 xmlGenericError(xmlGenericErrorContext
,
1227 "xmlNewNsPropEatName : name == NULL\n");
1233 * Allocate a new property and fill the fields.
1235 cur
= (xmlAttrPtr
) xmlMalloc(sizeof(xmlAttr
));
1237 xmlGenericError(xmlGenericErrorContext
,
1238 "xmlNewNsPropEatName : malloc failed\n");
1241 memset(cur
, 0, sizeof(xmlAttr
));
1242 cur
->type
= XML_ATTRIBUTE_NODE
;
1251 if (value
!= NULL
) {
1255 buffer
= xmlEncodeEntitiesReentrant(doc
, value
);
1256 cur
->children
= xmlStringGetNodeList(doc
, buffer
);
1258 tmp
= cur
->children
;
1259 while (tmp
!= NULL
) {
1260 tmp
->parent
= (xmlNodePtr
) cur
;
1261 if (tmp
->next
== NULL
)
1269 * Add it at the end to preserve parsing order ...
1272 if (node
->properties
== NULL
) {
1273 node
->properties
= cur
;
1275 xmlAttrPtr prev
= node
->properties
;
1277 while (prev
->next
!= NULL
) prev
= prev
->next
;
1287 * @doc: the document
1288 * @name: the name of the attribute
1289 * @value: the value of the attribute
1291 * Create a new property carried by a document.
1292 * Returns a pointer to the attribute
1295 xmlNewDocProp(xmlDocPtr doc
, const xmlChar
*name
, const xmlChar
*value
) {
1300 xmlGenericError(xmlGenericErrorContext
,
1301 "xmlNewDocProp : name == NULL\n");
1307 * Allocate a new property and fill the fields.
1309 cur
= (xmlAttrPtr
) xmlMalloc(sizeof(xmlAttr
));
1311 xmlGenericError(xmlGenericErrorContext
,
1312 "xmlNewDocProp : malloc failed\n");
1315 memset(cur
, 0, sizeof(xmlAttr
));
1316 cur
->type
= XML_ATTRIBUTE_NODE
;
1318 cur
->name
= xmlStrdup(name
);
1320 if (value
!= NULL
) {
1323 cur
->children
= xmlStringGetNodeList(doc
, value
);
1326 tmp
= cur
->children
;
1327 while (tmp
!= NULL
) {
1328 tmp
->parent
= (xmlNodePtr
) cur
;
1329 if (tmp
->next
== NULL
)
1339 * @cur: the first property in the list
1341 * Free a property and all its siblings, all the children are freed too.
1344 xmlFreePropList(xmlAttrPtr cur
) {
1348 xmlGenericError(xmlGenericErrorContext
,
1349 "xmlFreePropList : property == NULL\n");
1353 while (cur
!= NULL
) {
1362 * @cur: an attribute
1364 * Free one attribute, all the content is freed too
1367 xmlFreeProp(xmlAttrPtr cur
) {
1370 xmlGenericError(xmlGenericErrorContext
,
1371 "xmlFreeProp : property == NULL\n");
1375 /* Check for ID removal -> leading to invalid references ! */
1376 if ((cur
->parent
!= NULL
) && (cur
->parent
->doc
!= NULL
) &&
1377 ((cur
->parent
->doc
->intSubset
!= NULL
) ||
1378 (cur
->parent
->doc
->extSubset
!= NULL
))) {
1379 if (xmlIsID(cur
->parent
->doc
, cur
->parent
, cur
))
1380 xmlRemoveID(cur
->parent
->doc
, cur
);
1382 if (cur
->name
!= NULL
) xmlFree((char *) cur
->name
);
1383 if (cur
->children
!= NULL
) xmlFreeNodeList(cur
->children
);
1389 * @cur: an attribute
1391 * Unlink and free one attribute, all the content is freed too
1392 * Note this doesn't work for namespace definition attributes
1394 * Returns 0 if success and -1 in case of error.
1397 xmlRemoveProp(xmlAttrPtr cur
) {
1401 xmlGenericError(xmlGenericErrorContext
,
1402 "xmlRemoveProp : cur == NULL\n");
1406 if (cur
->parent
== NULL
) {
1408 xmlGenericError(xmlGenericErrorContext
,
1409 "xmlRemoveProp : cur->parent == NULL\n");
1413 tmp
= cur
->parent
->properties
;
1415 cur
->parent
->properties
= cur
->next
;
1419 while (tmp
!= NULL
) {
1420 if (tmp
->next
== cur
) {
1421 tmp
->next
= cur
->next
;
1422 if (tmp
->next
!= NULL
)
1423 tmp
->next
->prev
= tmp
;
1430 xmlGenericError(xmlGenericErrorContext
,
1431 "xmlRemoveProp : attribute not owned by its node\n");
1438 * @name: the processing instruction name
1439 * @content: the PI content
1441 * Creation of a processing instruction element.
1442 * Returns a pointer to the new node object.
1445 xmlNewPI(const xmlChar
*name
, const xmlChar
*content
) {
1450 xmlGenericError(xmlGenericErrorContext
,
1451 "xmlNewPI : name == NULL\n");
1457 * Allocate a new node and fill the fields.
1459 cur
= (xmlNodePtr
) xmlMalloc(sizeof(xmlNode
));
1461 xmlGenericError(xmlGenericErrorContext
,
1462 "xmlNewPI : malloc failed\n");
1465 memset(cur
, 0, sizeof(xmlNode
));
1466 cur
->type
= XML_PI_NODE
;
1468 cur
->name
= xmlStrdup(name
);
1469 if (content
!= NULL
) {
1470 cur
->content
= xmlStrdup(content
);
1477 * @ns: namespace if any
1478 * @name: the node name
1480 * Creation of a new node element. @ns is optional (NULL).
1482 * Returns a pointer to the new node object.
1485 xmlNewNode(xmlNsPtr ns
, const xmlChar
*name
) {
1490 xmlGenericError(xmlGenericErrorContext
,
1491 "xmlNewNode : name == NULL\n");
1497 * Allocate a new node and fill the fields.
1499 cur
= (xmlNodePtr
) xmlMalloc(sizeof(xmlNode
));
1501 xmlGenericError(xmlGenericErrorContext
,
1502 "xmlNewNode : malloc failed\n");
1505 memset(cur
, 0, sizeof(xmlNode
));
1506 cur
->type
= XML_ELEMENT_NODE
;
1508 cur
->name
= xmlStrdup(name
);
1514 * xmlNewNodeEatName:
1515 * @ns: namespace if any
1516 * @name: the node name
1518 * Creation of a new node element. @ns is optional (NULL).
1520 * Returns a pointer to the new node object.
1523 xmlNewNodeEatName(xmlNsPtr ns
, xmlChar
*name
) {
1528 xmlGenericError(xmlGenericErrorContext
,
1529 "xmlNewNode : name == NULL\n");
1535 * Allocate a new node and fill the fields.
1537 cur
= (xmlNodePtr
) xmlMalloc(sizeof(xmlNode
));
1539 xmlGenericError(xmlGenericErrorContext
,
1540 "xmlNewNode : malloc failed\n");
1543 memset(cur
, 0, sizeof(xmlNode
));
1544 cur
->type
= XML_ELEMENT_NODE
;
1553 * @doc: the document
1554 * @ns: namespace if any
1555 * @name: the node name
1556 * @content: the XML text content if any
1558 * Creation of a new node element within a document. @ns and @content
1559 * are optional (NULL).
1560 * NOTE: @content is supposed to be a piece of XML CDATA, so it allow entities
1561 * references, but XML special chars need to be escaped first by using
1562 * xmlEncodeEntitiesReentrant(). Use xmlNewDocRawNode() if you don't
1563 * need entities support.
1565 * Returns a pointer to the new node object.
1568 xmlNewDocNode(xmlDocPtr doc
, xmlNsPtr ns
,
1569 const xmlChar
*name
, const xmlChar
*content
) {
1572 cur
= xmlNewNode(ns
, name
);
1575 if (content
!= NULL
) {
1576 cur
->children
= xmlStringGetNodeList(doc
, content
);
1577 UPDATE_LAST_CHILD_AND_PARENT(cur
)
1584 * xmlNewDocNodeEatName:
1585 * @doc: the document
1586 * @ns: namespace if any
1587 * @name: the node name
1588 * @content: the XML text content if any
1590 * Creation of a new node element within a document. @ns and @content
1591 * are optional (NULL).
1592 * NOTE: @content is supposed to be a piece of XML CDATA, so it allow entities
1593 * references, but XML special chars need to be escaped first by using
1594 * xmlEncodeEntitiesReentrant(). Use xmlNewDocRawNode() if you don't
1595 * need entities support.
1597 * Returns a pointer to the new node object.
1600 xmlNewDocNodeEatName(xmlDocPtr doc
, xmlNsPtr ns
,
1601 xmlChar
*name
, const xmlChar
*content
) {
1604 cur
= xmlNewNodeEatName(ns
, name
);
1607 if (content
!= NULL
) {
1608 cur
->children
= xmlStringGetNodeList(doc
, content
);
1609 UPDATE_LAST_CHILD_AND_PARENT(cur
)
1618 * @doc: the document
1619 * @ns: namespace if any
1620 * @name: the node name
1621 * @content: the text content if any
1623 * Creation of a new node element within a document. @ns and @content
1624 * are optional (NULL).
1626 * Returns a pointer to the new node object.
1629 xmlNewDocRawNode(xmlDocPtr doc
, xmlNsPtr ns
,
1630 const xmlChar
*name
, const xmlChar
*content
) {
1633 cur
= xmlNewNode(ns
, name
);
1636 if (content
!= NULL
) {
1637 cur
->children
= xmlNewDocText(doc
, content
);
1638 UPDATE_LAST_CHILD_AND_PARENT(cur
)
1645 * xmlNewDocFragment:
1646 * @doc: the document owning the fragment
1648 * Creation of a new Fragment node.
1649 * Returns a pointer to the new node object.
1652 xmlNewDocFragment(xmlDocPtr doc
) {
1656 * Allocate a new DocumentFragment node and fill the fields.
1658 cur
= (xmlNodePtr
) xmlMalloc(sizeof(xmlNode
));
1660 xmlGenericError(xmlGenericErrorContext
,
1661 "xmlNewDocFragment : malloc failed\n");
1664 memset(cur
, 0, sizeof(xmlNode
));
1665 cur
->type
= XML_DOCUMENT_FRAG_NODE
;
1673 * @content: the text content
1675 * Creation of a new text node.
1676 * Returns a pointer to the new node object.
1679 xmlNewText(const xmlChar
*content
) {
1683 * Allocate a new node and fill the fields.
1685 cur
= (xmlNodePtr
) xmlMalloc(sizeof(xmlNode
));
1687 xmlGenericError(xmlGenericErrorContext
,
1688 "xmlNewText : malloc failed\n");
1691 memset(cur
, 0, sizeof(xmlNode
));
1692 cur
->type
= XML_TEXT_NODE
;
1694 cur
->name
= xmlStringText
;
1695 if (content
!= NULL
) {
1696 cur
->content
= xmlStrdup(content
);
1703 * @parent: the parent node
1704 * @ns: a namespace if any
1705 * @name: the name of the child
1706 * @content: the text content of the child if any.
1708 * Creation of a new child element, added at the end of @parent children list.
1709 * @ns and @content parameters are optional (NULL). If content is non NULL,
1710 * a child TEXT node will be created containing the string content.
1712 * Returns a pointer to the new node object.
1715 xmlNewTextChild(xmlNodePtr parent
, xmlNsPtr ns
,
1716 const xmlChar
*name
, const xmlChar
*content
) {
1717 xmlNodePtr cur
, prev
;
1719 if (parent
== NULL
) {
1721 xmlGenericError(xmlGenericErrorContext
,
1722 "xmlNewTextChild : parent == NULL\n");
1729 xmlGenericError(xmlGenericErrorContext
,
1730 "xmlNewTextChild : name == NULL\n");
1736 * Allocate a new node
1739 cur
= xmlNewDocRawNode(parent
->doc
, parent
->ns
, name
, content
);
1741 cur
= xmlNewDocRawNode(parent
->doc
, ns
, name
, content
);
1742 if (cur
== NULL
) return(NULL
);
1745 * add the new element at the end of the children list.
1747 cur
->type
= XML_ELEMENT_NODE
;
1748 cur
->parent
= parent
;
1749 cur
->doc
= parent
->doc
;
1750 if (parent
->children
== NULL
) {
1751 parent
->children
= cur
;
1754 prev
= parent
->last
;
1765 * @doc: the document
1766 * @name: the char ref string, starting with # or "&# ... ;"
1768 * Creation of a new character reference node.
1769 * Returns a pointer to the new node object.
1772 xmlNewCharRef(xmlDocPtr doc
, const xmlChar
*name
) {
1776 * Allocate a new node and fill the fields.
1778 cur
= (xmlNodePtr
) xmlMalloc(sizeof(xmlNode
));
1780 xmlGenericError(xmlGenericErrorContext
,
1781 "xmlNewCharRef : malloc failed\n");
1784 memset(cur
, 0, sizeof(xmlNode
));
1785 cur
->type
= XML_ENTITY_REF_NODE
;
1788 if (name
[0] == '&') {
1791 len
= xmlStrlen(name
);
1792 if (name
[len
- 1] == ';')
1793 cur
->name
= xmlStrndup(name
, len
- 1);
1795 cur
->name
= xmlStrndup(name
, len
);
1797 cur
->name
= xmlStrdup(name
);
1803 * @doc: the document
1804 * @name: the reference name, or the reference string with & and ;
1806 * Creation of a new reference node.
1807 * Returns a pointer to the new node object.
1810 xmlNewReference(xmlDocPtr doc
, const xmlChar
*name
) {
1815 * Allocate a new node and fill the fields.
1817 cur
= (xmlNodePtr
) xmlMalloc(sizeof(xmlNode
));
1819 xmlGenericError(xmlGenericErrorContext
,
1820 "xmlNewReference : malloc failed\n");
1823 memset(cur
, 0, sizeof(xmlNode
));
1824 cur
->type
= XML_ENTITY_REF_NODE
;
1827 if (name
[0] == '&') {
1830 len
= xmlStrlen(name
);
1831 if (name
[len
- 1] == ';')
1832 cur
->name
= xmlStrndup(name
, len
- 1);
1834 cur
->name
= xmlStrndup(name
, len
);
1836 cur
->name
= xmlStrdup(name
);
1838 ent
= xmlGetDocEntity(doc
, cur
->name
);
1840 cur
->content
= ent
->content
;
1842 * The parent pointer in entity is a DTD pointer and thus is NOT
1843 * updated. Not sure if this is 100% correct.
1846 cur
->children
= (xmlNodePtr
) ent
;
1847 cur
->last
= (xmlNodePtr
) ent
;
1854 * @doc: the document
1855 * @content: the text content
1857 * Creation of a new text node within a document.
1858 * Returns a pointer to the new node object.
1861 xmlNewDocText(xmlDocPtr doc
, const xmlChar
*content
) {
1864 cur
= xmlNewText(content
);
1865 if (cur
!= NULL
) cur
->doc
= doc
;
1871 * @content: the text content
1872 * @len: the text len.
1874 * Creation of a new text node with an extra parameter for the content's length
1875 * Returns a pointer to the new node object.
1878 xmlNewTextLen(const xmlChar
*content
, int len
) {
1882 * Allocate a new node and fill the fields.
1884 cur
= (xmlNodePtr
) xmlMalloc(sizeof(xmlNode
));
1886 xmlGenericError(xmlGenericErrorContext
,
1887 "xmlNewTextLen : malloc failed\n");
1890 memset(cur
, 0, sizeof(xmlNode
));
1891 cur
->type
= XML_TEXT_NODE
;
1893 cur
->name
= xmlStringText
;
1894 if (content
!= NULL
) {
1895 cur
->content
= xmlStrndup(content
, len
);
1902 * @doc: the document
1903 * @content: the text content
1904 * @len: the text len.
1906 * Creation of a new text node with an extra content length parameter. The
1907 * text node pertain to a given document.
1908 * Returns a pointer to the new node object.
1911 xmlNewDocTextLen(xmlDocPtr doc
, const xmlChar
*content
, int len
) {
1914 cur
= xmlNewTextLen(content
, len
);
1915 if (cur
!= NULL
) cur
->doc
= doc
;
1921 * @content: the comment content
1923 * Creation of a new node containing a comment.
1924 * Returns a pointer to the new node object.
1927 xmlNewComment(const xmlChar
*content
) {
1931 * Allocate a new node and fill the fields.
1933 cur
= (xmlNodePtr
) xmlMalloc(sizeof(xmlNode
));
1935 xmlGenericError(xmlGenericErrorContext
,
1936 "xmlNewComment : malloc failed\n");
1939 memset(cur
, 0, sizeof(xmlNode
));
1940 cur
->type
= XML_COMMENT_NODE
;
1942 cur
->name
= xmlStringComment
;
1943 if (content
!= NULL
) {
1944 cur
->content
= xmlStrdup(content
);
1951 * @doc: the document
1952 * @content: the CDATA block content content
1953 * @len: the length of the block
1955 * Creation of a new node containing a CDATA block.
1956 * Returns a pointer to the new node object.
1959 xmlNewCDataBlock(xmlDocPtr doc
, const xmlChar
*content
, int len
) {
1963 * Allocate a new node and fill the fields.
1965 cur
= (xmlNodePtr
) xmlMalloc(sizeof(xmlNode
));
1967 xmlGenericError(xmlGenericErrorContext
,
1968 "xmlNewCDataBlock : malloc failed\n");
1971 memset(cur
, 0, sizeof(xmlNode
));
1972 cur
->type
= XML_CDATA_SECTION_NODE
;
1975 if (content
!= NULL
) {
1976 cur
->content
= xmlStrndup(content
, len
);
1983 * @doc: the document
1984 * @content: the comment content
1986 * Creation of a new node containing a comment within a document.
1987 * Returns a pointer to the new node object.
1990 xmlNewDocComment(xmlDocPtr doc
, const xmlChar
*content
) {
1993 cur
= xmlNewComment(content
);
1994 if (cur
!= NULL
) cur
->doc
= doc
;
2000 * @tree: the top element
2001 * @doc: the document
2003 * update all nodes under the tree to point to the right document
2006 xmlSetTreeDoc(xmlNodePtr tree
, xmlDocPtr doc
) {
2011 if (tree
->doc
!= doc
) {
2012 if(tree
->type
== XML_ELEMENT_NODE
) {
2013 prop
= tree
->properties
;
2014 while (prop
!= NULL
) {
2016 xmlSetListDoc(prop
->children
, doc
);
2020 if (tree
->children
!= NULL
)
2021 xmlSetListDoc(tree
->children
, doc
);
2028 * @list: the first element
2029 * @doc: the document
2031 * update all nodes in the list to point to the right document
2034 xmlSetListDoc(xmlNodePtr list
, xmlDocPtr doc
) {
2040 while (cur
!= NULL
) {
2041 if (cur
->doc
!= doc
)
2042 xmlSetTreeDoc(cur
, doc
);
2050 * @parent: the parent node
2051 * @ns: a namespace if any
2052 * @name: the name of the child
2053 * @content: the XML content of the child if any.
2055 * Creation of a new child element, added at the end of @parent children list.
2056 * @ns and @content parameters are optional (NULL). If content is non NULL,
2057 * a child list containing the TEXTs and ENTITY_REFs node will be created.
2058 * NOTE: @content is supposed to be a piece of XML CDATA, so it allow entities
2059 * references, but XML special chars need to be escaped first by using
2060 * xmlEncodeEntitiesReentrant(). Use xmlNewTextChild() if entities
2061 * support is not needed.
2063 * Returns a pointer to the new node object.
2066 xmlNewChild(xmlNodePtr parent
, xmlNsPtr ns
,
2067 const xmlChar
*name
, const xmlChar
*content
) {
2068 xmlNodePtr cur
, prev
;
2070 if (parent
== NULL
) {
2072 xmlGenericError(xmlGenericErrorContext
,
2073 "xmlNewChild : parent == NULL\n");
2080 xmlGenericError(xmlGenericErrorContext
,
2081 "xmlNewChild : name == NULL\n");
2087 * Allocate a new node
2089 if (parent
->type
== XML_ELEMENT_NODE
) {
2091 cur
= xmlNewDocNode(parent
->doc
, parent
->ns
, name
, content
);
2093 cur
= xmlNewDocNode(parent
->doc
, ns
, name
, content
);
2094 } else if ((parent
->type
== XML_DOCUMENT_NODE
) ||
2095 (parent
->type
== XML_HTML_DOCUMENT_NODE
)) {
2097 cur
= xmlNewDocNode((xmlDocPtr
) parent
, NULL
, name
, content
);
2099 cur
= xmlNewDocNode((xmlDocPtr
) parent
, ns
, name
, content
);
2100 } else if (parent
->type
== XML_DOCUMENT_FRAG_NODE
) {
2101 cur
= xmlNewDocNode( parent
->doc
, ns
, name
, content
);
2105 if (cur
== NULL
) return(NULL
);
2108 * add the new element at the end of the children list.
2110 cur
->type
= XML_ELEMENT_NODE
;
2111 cur
->parent
= parent
;
2112 cur
->doc
= parent
->doc
;
2113 if (parent
->children
== NULL
) {
2114 parent
->children
= cur
;
2117 prev
= parent
->last
;
2127 * xmlAddNextSibling:
2128 * @cur: the child node
2129 * @elem: the new node
2131 * Add a new node @elem as the next sibling of @cur
2132 * If the new node was already inserted in a document it is
2133 * first unlinked from its existing context.
2134 * As a result of text merging @elem may be freed.
2135 * If the new node is ATTRIBUTE, it is added into properties instead of children.
2136 * If there is an attribute with equal name, it is first destroyed.
2138 * Returns the new node or NULL in case of error.
2141 xmlAddNextSibling(xmlNodePtr cur
, xmlNodePtr elem
) {
2144 xmlGenericError(xmlGenericErrorContext
,
2145 "xmlAddNextSibling : cur == NULL\n");
2151 xmlGenericError(xmlGenericErrorContext
,
2152 "xmlAddNextSibling : elem == NULL\n");
2157 xmlUnlinkNode(elem
);
2159 if (elem
->type
== XML_TEXT_NODE
) {
2160 if (cur
->type
== XML_TEXT_NODE
) {
2161 xmlNodeAddContent(cur
, elem
->content
);
2165 if ((cur
->next
!= NULL
) && (cur
->next
->type
== XML_TEXT_NODE
) &&
2166 (cur
->name
== cur
->next
->name
)) {
2169 tmp
= xmlStrdup(elem
->content
);
2170 tmp
= xmlStrcat(tmp
, cur
->next
->content
);
2171 xmlNodeSetContent(cur
->next
, tmp
);
2176 } else if (elem
->type
== XML_ATTRIBUTE_NODE
) {
2177 /* check if an attribute with the same name exists */
2180 if (elem
->ns
== NULL
)
2181 attr
= xmlHasProp(cur
->parent
, elem
->name
);
2183 attr
= xmlHasNsProp(cur
->parent
, elem
->name
, elem
->ns
->href
);
2184 if ((attr
!= NULL
) && (attr
!= (xmlAttrPtr
) elem
)) {
2185 /* different instance, destroy it (attributes must be unique) */
2190 if (elem
->doc
!= cur
->doc
) {
2191 xmlSetTreeDoc(elem
, cur
->doc
);
2193 elem
->parent
= cur
->parent
;
2195 elem
->next
= cur
->next
;
2197 if (elem
->next
!= NULL
)
2198 elem
->next
->prev
= elem
;
2199 if ((elem
->parent
!= NULL
) && (elem
->parent
->last
== cur
) && (elem
->type
!= XML_ATTRIBUTE_NODE
))
2200 elem
->parent
->last
= elem
;
2205 * xmlAddPrevSibling:
2206 * @cur: the child node
2207 * @elem: the new node
2209 * Add a new node @elem as the previous sibling of @cur
2210 * merging adjacent TEXT nodes (@elem may be freed)
2211 * If the new node was already inserted in a document it is
2212 * first unlinked from its existing context.
2213 * If the new node is ATTRIBUTE, it is added into properties instead of children.
2214 * If there is an attribute with equal name, it is first destroyed.
2216 * Returns the new node or NULL in case of error.
2219 xmlAddPrevSibling(xmlNodePtr cur
, xmlNodePtr elem
) {
2222 xmlGenericError(xmlGenericErrorContext
,
2223 "xmlAddPrevSibling : cur == NULL\n");
2229 xmlGenericError(xmlGenericErrorContext
,
2230 "xmlAddPrevSibling : elem == NULL\n");
2235 xmlUnlinkNode(elem
);
2237 if (elem
->type
== XML_TEXT_NODE
) {
2238 if (cur
->type
== XML_TEXT_NODE
) {
2241 tmp
= xmlStrdup(elem
->content
);
2242 tmp
= xmlStrcat(tmp
, cur
->content
);
2243 xmlNodeSetContent(cur
, tmp
);
2248 if ((cur
->prev
!= NULL
) && (cur
->prev
->type
== XML_TEXT_NODE
) &&
2249 (cur
->name
== cur
->prev
->name
)) {
2250 xmlNodeAddContent(cur
->prev
, elem
->content
);
2254 } else if (elem
->type
== XML_ATTRIBUTE_NODE
) {
2255 /* check if an attribute with the same name exists */
2258 if (elem
->ns
== NULL
)
2259 attr
= xmlHasProp(cur
->parent
, elem
->name
);
2261 attr
= xmlHasNsProp(cur
->parent
, elem
->name
, elem
->ns
->href
);
2262 if ((attr
!= NULL
) && (attr
!= (xmlAttrPtr
) elem
)) {
2263 /* different instance, destroy it (attributes must be unique) */
2268 if (elem
->doc
!= cur
->doc
) {
2269 xmlSetTreeDoc(elem
, cur
->doc
);
2271 elem
->parent
= cur
->parent
;
2273 elem
->prev
= cur
->prev
;
2275 if (elem
->prev
!= NULL
)
2276 elem
->prev
->next
= elem
;
2277 if (elem
->parent
!= NULL
) {
2278 if (elem
->type
== XML_ATTRIBUTE_NODE
) {
2279 if (elem
->parent
->properties
== (xmlAttrPtr
) cur
) {
2280 elem
->parent
->properties
= (xmlAttrPtr
) elem
;
2283 if (elem
->parent
->children
== cur
) {
2284 elem
->parent
->children
= elem
;
2293 * @cur: the child node
2294 * @elem: the new node
2296 * Add a new element @elem to the list of siblings of @cur
2297 * merging adjacent TEXT nodes (@elem may be freed)
2298 * If the new element was already inserted in a document it is
2299 * first unlinked from its existing context.
2301 * Returns the new element or NULL in case of error.
2304 xmlAddSibling(xmlNodePtr cur
, xmlNodePtr elem
) {
2309 xmlGenericError(xmlGenericErrorContext
,
2310 "xmlAddSibling : cur == NULL\n");
2317 xmlGenericError(xmlGenericErrorContext
,
2318 "xmlAddSibling : elem == NULL\n");
2324 * Constant time is we can rely on the ->parent->last to find
2327 if ((cur
->parent
!= NULL
) &&
2328 (cur
->parent
->children
!= NULL
) &&
2329 (cur
->parent
->last
!= NULL
) &&
2330 (cur
->parent
->last
->next
== NULL
)) {
2331 cur
= cur
->parent
->last
;
2333 while (cur
->next
!= NULL
) cur
= cur
->next
;
2336 xmlUnlinkNode(elem
);
2338 if ((cur
->type
== XML_TEXT_NODE
) && (elem
->type
== XML_TEXT_NODE
)) {
2339 xmlNodeAddContent(cur
, elem
->content
);
2344 if (elem
->doc
!= cur
->doc
) {
2345 xmlSetTreeDoc(elem
, cur
->doc
);
2347 parent
= cur
->parent
;
2350 elem
->parent
= parent
;
2353 parent
->last
= elem
;
2360 * @parent: the parent node
2361 * @cur: the first node in the list
2363 * Add a list of node at the end of the child list of the parent
2364 * merging adjacent TEXT nodes (@cur may be freed)
2366 * Returns the last child or NULL in case of error.
2369 xmlAddChildList(xmlNodePtr parent
, xmlNodePtr cur
) {
2372 if (parent
== NULL
) {
2374 xmlGenericError(xmlGenericErrorContext
,
2375 "xmlAddChildList : parent == NULL\n");
2382 xmlGenericError(xmlGenericErrorContext
,
2383 "xmlAddChildList : child == NULL\n");
2388 if ((cur
->doc
!= NULL
) && (parent
->doc
!= NULL
) &&
2389 (cur
->doc
!= parent
->doc
)) {
2391 xmlGenericError(xmlGenericErrorContext
,
2392 "Elements moved to a different document\n");
2397 * add the first element at the end of the children list.
2399 if (parent
->children
== NULL
) {
2400 parent
->children
= cur
;
2403 * If cur and parent->last both are TEXT nodes, then merge them.
2405 if ((cur
->type
== XML_TEXT_NODE
) &&
2406 (parent
->last
->type
== XML_TEXT_NODE
) &&
2407 (cur
->name
== parent
->last
->name
)) {
2408 xmlNodeAddContent(parent
->last
, cur
->content
);
2410 * if it's the only child, nothing more to be done.
2412 if (cur
->next
== NULL
) {
2414 return(parent
->last
);
2420 prev
= parent
->last
;
2424 while (cur
->next
!= NULL
) {
2425 cur
->parent
= parent
;
2426 if (cur
->doc
!= parent
->doc
) {
2427 xmlSetTreeDoc(cur
, parent
->doc
);
2431 cur
->parent
= parent
;
2432 cur
->doc
= parent
->doc
; /* the parent may not be linked to a doc ! */
2440 * @parent: the parent node
2441 * @cur: the child node
2443 * Add a new node to @parent, at the end of the child (or property) list
2444 * merging adjacent TEXT nodes (in which case @cur is freed)
2445 * If the new node was already inserted in a document it is
2446 * first unlinked from its existing context.
2447 * If the new node is ATTRIBUTE, it is added into properties instead of children.
2448 * If there is an attribute with equal name, it is first destroyed.
2450 * Returns the child or NULL in case of error.
2453 xmlAddChild(xmlNodePtr parent
, xmlNodePtr cur
) {
2456 if (parent
== NULL
) {
2458 xmlGenericError(xmlGenericErrorContext
,
2459 "xmlAddChild : parent == NULL\n");
2466 xmlGenericError(xmlGenericErrorContext
,
2467 "xmlAddChild : child == NULL\n");
2473 * If cur is a TEXT node, merge its content with adjacent TEXT nodes
2474 * cur is then freed.
2476 if (cur
->type
== XML_TEXT_NODE
) {
2477 if ((parent
->type
== XML_TEXT_NODE
) &&
2478 (parent
->content
!= NULL
)) {
2479 xmlNodeAddContent(parent
, cur
->content
);
2483 if ((parent
->last
!= NULL
) && (parent
->last
->type
== XML_TEXT_NODE
) &&
2484 (parent
->last
->name
== cur
->name
)) {
2485 xmlNodeAddContent(parent
->last
, cur
->content
);
2487 return(parent
->last
);
2492 * add the new element at the end of the children list.
2494 cur
->parent
= parent
;
2495 if (cur
->doc
!= parent
->doc
) {
2496 xmlSetTreeDoc(cur
, parent
->doc
);
2502 if ((parent
->type
== XML_TEXT_NODE
) &&
2503 (parent
->content
!= NULL
)) {
2504 xmlNodeAddContent(parent
, cur
->content
);
2508 if (cur
->type
== XML_ATTRIBUTE_NODE
) {
2509 if (parent
->properties
== NULL
) {
2510 parent
->properties
= (xmlAttrPtr
) cur
;
2512 /* check if an attribute with the same name exists */
2513 xmlAttrPtr lastattr
;
2515 if (cur
->ns
== NULL
)
2516 lastattr
= xmlHasProp(parent
, cur
->name
);
2518 lastattr
= xmlHasNsProp(parent
, cur
->name
, cur
->ns
->href
);
2519 if ((lastattr
!= NULL
) && (lastattr
!= (xmlAttrPtr
) cur
)) {
2520 /* different instance, destroy it (attributes must be unique) */
2521 xmlFreeProp(lastattr
);
2524 lastattr
= parent
->properties
;
2525 while (lastattr
->next
!= NULL
) {
2526 lastattr
= lastattr
->next
;
2528 lastattr
->next
= (xmlAttrPtr
) cur
;
2529 ((xmlAttrPtr
) cur
)->prev
= lastattr
;
2532 if (parent
->children
== NULL
) {
2533 parent
->children
= cur
;
2536 prev
= parent
->last
;
2547 * @parent: the parent node
2549 * Search the last child of a node.
2550 * Returns the last child or NULL if none.
2553 xmlGetLastChild(xmlNodePtr parent
) {
2554 if (parent
== NULL
) {
2556 xmlGenericError(xmlGenericErrorContext
,
2557 "xmlGetLastChild : parent == NULL\n");
2561 return(parent
->last
);
2566 * @cur: the first node in the list
2568 * Free a node and all its siblings, this is a recursive behaviour, all
2569 * the children are freed too.
2572 xmlFreeNodeList(xmlNodePtr cur
) {
2576 xmlGenericError(xmlGenericErrorContext
,
2577 "xmlFreeNodeList : node == NULL\n");
2581 if (cur
->type
== XML_NAMESPACE_DECL
) {
2582 xmlFreeNsList((xmlNsPtr
) cur
);
2585 while (cur
!= NULL
) {
2587 /* unroll to speed up freeing the document */
2588 if (cur
->type
!= XML_DTD_NODE
) {
2589 if ((cur
->children
!= NULL
) &&
2590 (cur
->type
!= XML_ENTITY_REF_NODE
))
2591 xmlFreeNodeList(cur
->children
);
2592 if (cur
->properties
!= NULL
)
2593 xmlFreePropList(cur
->properties
);
2594 if ((cur
->type
!= XML_ELEMENT_NODE
) &&
2595 (cur
->type
!= XML_XINCLUDE_START
) &&
2596 (cur
->type
!= XML_XINCLUDE_END
) &&
2597 (cur
->type
!= XML_ENTITY_REF_NODE
)) {
2598 if (cur
->content
!= NULL
) xmlFree(cur
->content
);
2600 if (((cur
->type
== XML_ELEMENT_NODE
) ||
2601 (cur
->type
== XML_XINCLUDE_START
) ||
2602 (cur
->type
== XML_XINCLUDE_END
)) &&
2603 (cur
->nsDef
!= NULL
))
2604 xmlFreeNsList(cur
->nsDef
);
2607 * When a node is a text node or a comment, it uses a global static
2608 * variable for the name of the node.
2610 * The xmlStrEqual comparisons need to be done when (happened with
2611 * XML::libXML and XML::libXSLT) the library is included twice
2612 * statically in the binary and a tree allocated by one occurrence
2613 * of the lib gets freed by the other occurrence, in this case
2614 * the string addresses compare are not sufficient.
2616 if ((cur
->name
!= NULL
) &&
2617 (cur
->name
!= xmlStringText
) &&
2618 (cur
->name
!= xmlStringTextNoenc
) &&
2619 (cur
->name
!= xmlStringComment
)) {
2620 if (cur
->type
== XML_TEXT_NODE
) {
2621 if ((!xmlStrEqual(cur
->name
, xmlStringText
)) &&
2622 (!xmlStrEqual(cur
->name
, xmlStringTextNoenc
)))
2623 xmlFree((char *) cur
->name
);
2624 } else if (cur
->type
== XML_COMMENT_NODE
) {
2625 if (!xmlStrEqual(cur
->name
, xmlStringComment
))
2626 xmlFree((char *) cur
->name
);
2628 xmlFree((char *) cur
->name
);
2630 /* TODO : derecursivate this function */
2641 * Free a node, this is a recursive behaviour, all the children are freed too.
2642 * This doesn't unlink the child from the list, use xmlUnlinkNode() first.
2645 xmlFreeNode(xmlNodePtr cur
) {
2648 xmlGenericError(xmlGenericErrorContext
,
2649 "xmlFreeNode : node == NULL\n");
2653 /* use xmlFreeDtd for DTD nodes */
2654 if (cur
->type
== XML_DTD_NODE
) {
2655 xmlFreeDtd((xmlDtdPtr
) cur
);
2658 if (cur
->type
== XML_NAMESPACE_DECL
) {
2659 xmlFreeNs((xmlNsPtr
) cur
);
2662 if (cur
->type
== XML_ATTRIBUTE_NODE
) {
2663 xmlFreeProp((xmlAttrPtr
) cur
);
2666 if ((cur
->children
!= NULL
) &&
2667 (cur
->type
!= XML_ENTITY_REF_NODE
))
2668 xmlFreeNodeList(cur
->children
);
2669 if (cur
->properties
!= NULL
)
2670 xmlFreePropList(cur
->properties
);
2671 if ((cur
->type
!= XML_ELEMENT_NODE
) &&
2672 (cur
->content
!= NULL
) &&
2673 (cur
->type
!= XML_ENTITY_REF_NODE
) &&
2674 (cur
->type
!= XML_XINCLUDE_END
) &&
2675 (cur
->type
!= XML_XINCLUDE_START
)) {
2676 xmlFree(cur
->content
);
2680 * When a node is a text node or a comment, it uses a global static
2681 * variable for the name of the node.
2683 * The xmlStrEqual comparisons need to be done when (happened with
2684 * XML::libXML and XML::libXSLT) the library is included twice statically
2685 * in the binary and a tree allocated by one occurence of the lib gets
2686 * freed by the other occurrence, in this case the string addresses compare
2687 * are not sufficient.
2689 if ((cur
->name
!= NULL
) &&
2690 (cur
->name
!= xmlStringText
) &&
2691 (cur
->name
!= xmlStringTextNoenc
) &&
2692 (cur
->name
!= xmlStringComment
)) {
2693 if (cur
->type
== XML_TEXT_NODE
) {
2694 if ((!xmlStrEqual(cur
->name
, xmlStringText
)) &&
2695 (!xmlStrEqual(cur
->name
, xmlStringTextNoenc
)))
2696 xmlFree((char *) cur
->name
);
2697 } else if (cur
->type
== XML_COMMENT_NODE
) {
2698 if (!xmlStrEqual(cur
->name
, xmlStringComment
))
2699 xmlFree((char *) cur
->name
);
2701 xmlFree((char *) cur
->name
);
2704 if (cur
->nsDef
!= NULL
) xmlFreeNsList(cur
->nsDef
);
2712 * Unlink a node from it's current context, the node is not freed
2715 xmlUnlinkNode(xmlNodePtr cur
) {
2718 xmlGenericError(xmlGenericErrorContext
,
2719 "xmlUnlinkNode : node == NULL\n");
2723 if (cur
->type
== XML_DTD_NODE
) {
2726 if (doc
->intSubset
== (xmlDtdPtr
) cur
)
2727 doc
->intSubset
= NULL
;
2728 if (doc
->extSubset
== (xmlDtdPtr
) cur
)
2729 doc
->extSubset
= NULL
;
2731 if (cur
->parent
!= NULL
) {
2733 parent
= cur
->parent
;
2734 if (cur
->type
== XML_ATTRIBUTE_NODE
) {
2735 if (parent
->properties
== (xmlAttrPtr
) cur
)
2736 parent
->properties
= ((xmlAttrPtr
) cur
)->next
;
2738 if (parent
->children
== cur
)
2739 parent
->children
= cur
->next
;
2740 if (parent
->last
== cur
)
2741 parent
->last
= cur
->prev
;
2745 if (cur
->next
!= NULL
)
2746 cur
->next
->prev
= cur
->prev
;
2747 if (cur
->prev
!= NULL
)
2748 cur
->prev
->next
= cur
->next
;
2749 cur
->next
= cur
->prev
= NULL
;
2754 * @old: the old node
2757 * Unlink the old node from it's current context, prune the new one
2758 * at the same place. If @cur was already inserted in a document it is
2759 * first unlinked from its existing context.
2761 * Returns the @old node
2764 xmlReplaceNode(xmlNodePtr old
, xmlNodePtr cur
) {
2767 xmlGenericError(xmlGenericErrorContext
,
2768 "xmlReplaceNode : old == NULL\n");
2779 if ((old
->type
==XML_ATTRIBUTE_NODE
) && (cur
->type
!=XML_ATTRIBUTE_NODE
)) {
2781 xmlGenericError(xmlGenericErrorContext
,
2782 "xmlReplaceNode : Trying to replace attribute node with other node type\n");
2786 if ((cur
->type
==XML_ATTRIBUTE_NODE
) && (old
->type
!=XML_ATTRIBUTE_NODE
)) {
2788 xmlGenericError(xmlGenericErrorContext
,
2789 "xmlReplaceNode : Trying to replace a non-attribute node with attribute node\n");
2793 if ((old
->type
==XML_ATTRIBUTE_NODE
) && (cur
->type
!=XML_ATTRIBUTE_NODE
)) {
2795 xmlGenericError(xmlGenericErrorContext
,
2796 "xmlReplaceNode : Trying to replace attribute node with other node type\n");
2800 if ((cur
->type
==XML_ATTRIBUTE_NODE
) && (old
->type
!=XML_ATTRIBUTE_NODE
)) {
2802 xmlGenericError(xmlGenericErrorContext
,
2803 "xmlReplaceNode : Trying to replace a non-attribute node with attribute node\n");
2808 cur
->doc
= old
->doc
;
2809 cur
->parent
= old
->parent
;
2810 cur
->next
= old
->next
;
2811 if (cur
->next
!= NULL
)
2812 cur
->next
->prev
= cur
;
2813 cur
->prev
= old
->prev
;
2814 if (cur
->prev
!= NULL
)
2815 cur
->prev
->next
= cur
;
2816 if (cur
->parent
!= NULL
) {
2817 if (cur
->type
== XML_ATTRIBUTE_NODE
) {
2818 if (cur
->parent
->properties
== (xmlAttrPtr
)old
)
2819 cur
->parent
->properties
= ((xmlAttrPtr
) cur
);
2821 if (cur
->parent
->children
== old
)
2822 cur
->parent
->children
= cur
;
2823 if (cur
->parent
->last
== old
)
2824 cur
->parent
->last
= cur
;
2827 old
->next
= old
->prev
= NULL
;
2832 /************************************************************************
2836 ************************************************************************/
2840 * @cur: the namespace
2842 * Do a copy of the namespace.
2844 * Returns: a new #xmlNsPtr, or NULL in case of error.
2847 xmlCopyNamespace(xmlNsPtr cur
) {
2850 if (cur
== NULL
) return(NULL
);
2851 switch (cur
->type
) {
2852 case XML_LOCAL_NAMESPACE
:
2853 ret
= xmlNewNs(NULL
, cur
->href
, cur
->prefix
);
2857 xmlGenericError(xmlGenericErrorContext
,
2858 "xmlCopyNamespace: invalid type %d\n", cur
->type
);
2866 * xmlCopyNamespaceList:
2867 * @cur: the first namespace
2869 * Do a copy of an namespace list.
2871 * Returns: a new #xmlNsPtr, or NULL in case of error.
2874 xmlCopyNamespaceList(xmlNsPtr cur
) {
2875 xmlNsPtr ret
= NULL
;
2876 xmlNsPtr p
= NULL
,q
;
2878 while (cur
!= NULL
) {
2879 q
= xmlCopyNamespace(cur
);
2892 xmlStaticCopyNodeList(xmlNodePtr node
, xmlDocPtr doc
, xmlNodePtr parent
);
2895 * @target: the element where the attribute will be grafted
2896 * @cur: the attribute
2898 * Do a copy of the attribute.
2900 * Returns: a new #xmlAttrPtr, or NULL in case of error.
2903 xmlCopyProp(xmlNodePtr target
, xmlAttrPtr cur
) {
2906 if (cur
== NULL
) return(NULL
);
2908 ret
= xmlNewDocProp(target
->doc
, cur
->name
, NULL
);
2909 else if (cur
->parent
!= NULL
)
2910 ret
= xmlNewDocProp(cur
->parent
->doc
, cur
->name
, NULL
);
2911 else if (cur
->children
!= NULL
)
2912 ret
= xmlNewDocProp(cur
->children
->doc
, cur
->name
, NULL
);
2914 ret
= xmlNewDocProp(NULL
, cur
->name
, NULL
);
2915 if (ret
== NULL
) return(NULL
);
2916 ret
->parent
= target
;
2918 if ((cur
->ns
!= NULL
) && (target
!= NULL
)) {
2922 * ns = xmlSearchNs(target->doc, target, cur->ns->prefix);
2923 * else if (cur->doc) / * target may not yet have a doc : KPI * /
2924 * ns = xmlSearchNs(cur->doc, target, cur->ns->prefix);
2929 ns
= xmlSearchNs(target
->doc
, target
, cur
->ns
->prefix
);
2932 * Humm, we are copying an element whose namespace is defined
2933 * out of the new tree scope. Search it in the original tree
2934 * and add it at the top of the new tree
2936 ns
= xmlSearchNs(cur
->doc
, cur
->parent
, cur
->ns
->prefix
);
2938 xmlNodePtr root
= target
;
2939 xmlNodePtr pred
= NULL
;
2941 while (root
->parent
!= NULL
) {
2943 root
= root
->parent
;
2945 if (root
== (xmlNodePtr
) target
->doc
) {
2946 /* correct possibly cycling above the document elt */
2949 ret
->ns
= xmlNewNs(root
, ns
->href
, ns
->prefix
);
2953 * we have to find something appropriate here since
2954 * we cant be sure, that the namespce we found is identified
2957 if (xmlStrEqual(ns
->href
, cur
->ns
->href
)) {
2958 /* this is the nice case */
2962 * we are in trouble: we need a new reconcilied namespace.
2965 ret
->ns
= xmlNewReconciliedNs(target
->doc
, target
, cur
->ns
);
2972 if (cur
->children
!= NULL
) {
2975 ret
->children
= xmlStaticCopyNodeList(cur
->children
, ret
->doc
, (xmlNodePtr
) ret
);
2977 tmp
= ret
->children
;
2978 while (tmp
!= NULL
) {
2979 /* tmp->parent = (xmlNodePtr)ret; */
2980 if (tmp
->next
== NULL
)
2988 if ((target
!= NULL
) && (cur
!= NULL
) &&
2989 (target
->doc
!= NULL
) && (cur
->doc
!= NULL
) &&
2990 (cur
->doc
->ids
!= NULL
) && (cur
->parent
!= NULL
)) {
2991 if (xmlIsID(cur
->doc
, cur
->parent
, cur
)) {
2994 id
= xmlNodeListGetString(cur
->doc
, cur
->children
, 1);
2996 xmlAddID(NULL
, target
->doc
, id
, ret
);
3006 * @target: the element where the attributes will be grafted
3007 * @cur: the first attribute
3009 * Do a copy of an attribute list.
3011 * Returns: a new #xmlAttrPtr, or NULL in case of error.
3014 xmlCopyPropList(xmlNodePtr target
, xmlAttrPtr cur
) {
3015 xmlAttrPtr ret
= NULL
;
3016 xmlAttrPtr p
= NULL
,q
;
3018 while (cur
!= NULL
) {
3019 q
= xmlCopyProp(target
, cur
);
3033 * NOTE about the CopyNode operations !
3035 * They are split into external and internal parts for one
3036 * tricky reason: namespaces. Doing a direct copy of a node
3037 * say RPM:Copyright without changing the namespace pointer to
3038 * something else can produce stale links. One way to do it is
3039 * to keep a reference counter but this doesn't work as soon
3040 * as one move the element or the subtree out of the scope of
3041 * the existing namespace. The actual solution seems to add
3042 * a copy of the namespace at the top of the copied tree if
3043 * not available in the subtree.
3044 * Hence two functions, the public front-end call the inner ones
3048 xmlStaticCopyNode(const xmlNodePtr node
, xmlDocPtr doc
, xmlNodePtr parent
,
3052 if (node
== NULL
) return(NULL
);
3053 switch (node
->type
) {
3055 case XML_CDATA_SECTION_NODE
:
3056 case XML_ELEMENT_NODE
:
3057 case XML_DOCUMENT_FRAG_NODE
:
3058 case XML_ENTITY_REF_NODE
:
3059 case XML_ENTITY_NODE
:
3061 case XML_COMMENT_NODE
:
3062 case XML_XINCLUDE_START
:
3063 case XML_XINCLUDE_END
:
3065 case XML_ATTRIBUTE_NODE
:
3066 return((xmlNodePtr
) xmlCopyProp(parent
, (xmlAttrPtr
) node
));
3067 case XML_NAMESPACE_DECL
:
3068 return((xmlNodePtr
) xmlCopyNamespaceList((xmlNsPtr
) node
));
3070 case XML_DOCUMENT_NODE
:
3071 case XML_HTML_DOCUMENT_NODE
:
3072 #ifdef LIBXML_DOCB_ENABLED
3073 case XML_DOCB_DOCUMENT_NODE
:
3075 return((xmlNodePtr
) xmlCopyDoc((xmlDocPtr
) node
, recursive
));
3076 case XML_DOCUMENT_TYPE_NODE
:
3077 case XML_NOTATION_NODE
:
3079 case XML_ELEMENT_DECL
:
3080 case XML_ATTRIBUTE_DECL
:
3081 case XML_ENTITY_DECL
:
3086 * Allocate a new node and fill the fields.
3088 ret
= (xmlNodePtr
) xmlMalloc(sizeof(xmlNode
));
3090 xmlGenericError(xmlGenericErrorContext
,
3091 "xmlStaticCopyNode : malloc failed\n");
3094 memset(ret
, 0, sizeof(xmlNode
));
3095 ret
->type
= node
->type
;
3098 ret
->parent
= parent
;
3099 if (node
->name
== xmlStringText
)
3100 ret
->name
= xmlStringText
;
3101 else if (node
->name
== xmlStringTextNoenc
)
3102 ret
->name
= xmlStringTextNoenc
;
3103 else if (node
->name
== xmlStringComment
)
3104 ret
->name
= xmlStringComment
;
3105 else if (node
->name
!= NULL
)
3106 ret
->name
= xmlStrdup(node
->name
);
3107 if ((node
->type
!= XML_ELEMENT_NODE
) &&
3108 (node
->content
!= NULL
) &&
3109 (node
->type
!= XML_ENTITY_REF_NODE
) &&
3110 (node
->type
!= XML_XINCLUDE_END
) &&
3111 (node
->type
!= XML_XINCLUDE_START
)) {
3112 ret
->content
= xmlStrdup(node
->content
);
3114 if (node
->type
== XML_ELEMENT_NODE
)
3115 ret
->content
= (void*)(long) node
->content
;
3117 if (parent
!= NULL
) {
3120 tmp
= xmlAddChild(parent
, ret
);
3121 /* node could have coalesced */
3126 if (!recursive
) return(ret
);
3127 if (node
->nsDef
!= NULL
)
3128 ret
->nsDef
= xmlCopyNamespaceList(node
->nsDef
);
3130 if (node
->ns
!= NULL
) {
3133 ns
= xmlSearchNs(doc
, ret
, node
->ns
->prefix
);
3136 * Humm, we are copying an element whose namespace is defined
3137 * out of the new tree scope. Search it in the original tree
3138 * and add it at the top of the new tree
3140 ns
= xmlSearchNs(node
->doc
, node
, node
->ns
->prefix
);
3142 xmlNodePtr root
= ret
;
3144 while (root
->parent
!= NULL
) root
= root
->parent
;
3145 ret
->ns
= xmlNewNs(root
, ns
->href
, ns
->prefix
);
3149 * reference the existing namespace definition in our own tree.
3154 if (node
->properties
!= NULL
)
3155 ret
->properties
= xmlCopyPropList(ret
, node
->properties
);
3156 if (node
->type
== XML_ENTITY_REF_NODE
) {
3157 if ((doc
== NULL
) || (node
->doc
!= doc
)) {
3159 * The copied node will go into a separate document, so
3160 * to avoid dangling references to the ENTITY_DECL node
3161 * we cannot keep the reference. Try to find it in the
3164 ret
->children
= (xmlNodePtr
) xmlGetDocEntity(doc
, ret
->name
);
3166 ret
->children
= node
->children
;
3168 ret
->last
= ret
->children
;
3169 } else if (node
->children
!= NULL
) {
3170 ret
->children
= xmlStaticCopyNodeList(node
->children
, doc
, ret
);
3171 UPDATE_LAST_CHILD_AND_PARENT(ret
)
3177 xmlStaticCopyNodeList(xmlNodePtr node
, xmlDocPtr doc
, xmlNodePtr parent
) {
3178 xmlNodePtr ret
= NULL
;
3179 xmlNodePtr p
= NULL
,q
;
3181 while (node
!= NULL
) {
3182 if (node
->type
== XML_DTD_NODE
) {
3187 if (doc
->intSubset
== NULL
) {
3188 q
= (xmlNodePtr
) xmlCopyDtd( (xmlDtdPtr
) node
);
3191 doc
->intSubset
= (xmlDtdPtr
) q
;
3192 xmlAddChild(parent
, q
);
3194 q
= (xmlNodePtr
) doc
->intSubset
;
3195 xmlAddChild(parent
, q
);
3198 q
= xmlStaticCopyNode(node
, doc
, parent
, 1);
3202 } else if (p
!= q
) {
3203 /* the test is required if xmlStaticCopyNode coalesced 2 text nodes */
3216 * @recursive: if 1 do a recursive copy.
3218 * Do a copy of the node.
3220 * Returns: a new #xmlNodePtr, or NULL in case of error.
3223 xmlCopyNode(const xmlNodePtr node
, int recursive
) {
3226 ret
= xmlStaticCopyNode(node
, NULL
, NULL
, recursive
);
3233 * @doc: the document
3234 * @recursive: if 1 do a recursive copy.
3236 * Do a copy of the node to a given document.
3238 * Returns: a new #xmlNodePtr, or NULL in case of error.
3241 xmlDocCopyNode(const xmlNodePtr node
, xmlDocPtr doc
, int recursive
) {
3244 ret
= xmlStaticCopyNode(node
, doc
, NULL
, recursive
);
3250 * @node: the first node in the list.
3252 * Do a recursive copy of the node list.
3254 * Returns: a new #xmlNodePtr, or NULL in case of error.
3256 xmlNodePtr
xmlCopyNodeList(const xmlNodePtr node
) {
3257 xmlNodePtr ret
= xmlStaticCopyNodeList(node
, NULL
, NULL
);
3265 * Do a copy of the dtd.
3267 * Returns: a new #xmlDtdPtr, or NULL in case of error.
3270 xmlCopyDtd(xmlDtdPtr dtd
) {
3272 xmlNodePtr cur
, p
= NULL
, q
;
3274 if (dtd
== NULL
) return(NULL
);
3275 ret
= xmlNewDtd(NULL
, dtd
->name
, dtd
->ExternalID
, dtd
->SystemID
);
3276 if (ret
== NULL
) return(NULL
);
3277 if (dtd
->entities
!= NULL
)
3278 ret
->entities
= (void *) xmlCopyEntitiesTable(
3279 (xmlEntitiesTablePtr
) dtd
->entities
);
3280 if (dtd
->notations
!= NULL
)
3281 ret
->notations
= (void *) xmlCopyNotationTable(
3282 (xmlNotationTablePtr
) dtd
->notations
);
3283 if (dtd
->elements
!= NULL
)
3284 ret
->elements
= (void *) xmlCopyElementTable(
3285 (xmlElementTablePtr
) dtd
->elements
);
3286 if (dtd
->attributes
!= NULL
)
3287 ret
->attributes
= (void *) xmlCopyAttributeTable(
3288 (xmlAttributeTablePtr
) dtd
->attributes
);
3289 if (dtd
->pentities
!= NULL
)
3290 ret
->pentities
= (void *) xmlCopyEntitiesTable(
3291 (xmlEntitiesTablePtr
) dtd
->pentities
);
3293 cur
= dtd
->children
;
3294 while (cur
!= NULL
) {
3297 if (cur
->type
== XML_ENTITY_DECL
) {
3298 xmlEntityPtr tmp
= (xmlEntityPtr
) cur
;
3299 switch (tmp
->etype
) {
3300 case XML_INTERNAL_GENERAL_ENTITY
:
3301 case XML_EXTERNAL_GENERAL_PARSED_ENTITY
:
3302 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY
:
3303 q
= (xmlNodePtr
) xmlGetEntityFromDtd(ret
, tmp
->name
);
3305 case XML_INTERNAL_PARAMETER_ENTITY
:
3306 case XML_EXTERNAL_PARAMETER_ENTITY
:
3308 xmlGetParameterEntityFromDtd(ret
, tmp
->name
);
3310 case XML_INTERNAL_PREDEFINED_ENTITY
:
3313 } else if (cur
->type
== XML_ELEMENT_DECL
) {
3314 xmlElementPtr tmp
= (xmlElementPtr
) cur
;
3316 xmlGetDtdQElementDesc(ret
, tmp
->name
, tmp
->prefix
);
3317 } else if (cur
->type
== XML_ATTRIBUTE_DECL
) {
3318 xmlAttributePtr tmp
= (xmlAttributePtr
) cur
;
3320 xmlGetDtdQAttrDesc(ret
, tmp
->elem
, tmp
->name
, tmp
->prefix
);
3321 } else if (cur
->type
== XML_COMMENT_NODE
) {
3322 q
= xmlCopyNode(cur
, 0);
3336 q
->parent
= (xmlNodePtr
) ret
;
3348 * @doc: the document
3349 * @recursive: if 1 do a recursive copy.
3351 * Do a copy of the document info. If recursive, the content tree will
3352 * be copied too as well as DTD, namespaces and entities.
3354 * Returns: a new #xmlDocPtr, or NULL in case of error.
3357 xmlCopyDoc(xmlDocPtr doc
, int recursive
) {
3360 if (doc
== NULL
) return(NULL
);
3361 ret
= xmlNewDoc(doc
->version
);
3362 if (ret
== NULL
) return(NULL
);
3363 if (doc
->name
!= NULL
)
3364 ret
->name
= xmlMemStrdup(doc
->name
);
3365 if (doc
->encoding
!= NULL
)
3366 ret
->encoding
= xmlStrdup(doc
->encoding
);
3367 ret
->charset
= doc
->charset
;
3368 ret
->compression
= doc
->compression
;
3369 ret
->standalone
= doc
->standalone
;
3370 if (!recursive
) return(ret
);
3373 ret
->children
= NULL
;
3374 if (doc
->intSubset
!= NULL
) {
3375 ret
->intSubset
= xmlCopyDtd(doc
->intSubset
);
3376 xmlSetTreeDoc((xmlNodePtr
)ret
->intSubset
, ret
);
3377 ret
->intSubset
->parent
= ret
;
3379 if (doc
->oldNs
!= NULL
)
3380 ret
->oldNs
= xmlCopyNamespaceList(doc
->oldNs
);
3381 if (doc
->children
!= NULL
) {
3384 ret
->children
= xmlStaticCopyNodeList(doc
->children
, ret
,
3387 tmp
= ret
->children
;
3388 while (tmp
!= NULL
) {
3389 if (tmp
->next
== NULL
)
3397 /************************************************************************
3399 * Content access functions *
3401 ************************************************************************/
3405 * @node : valid node
3407 * Get line number of node. this requires activation of this option
3408 * before invoking the parser by calling xmlLineNumbersDefault(1)
3410 * Returns the line number if successful, -1 otherwise
3413 xmlGetLineNo(xmlNodePtr node
)
3419 if (node
->type
== XML_ELEMENT_NODE
)
3420 result
= (long) node
->content
;
3421 else if ((node
->prev
!= NULL
) &&
3422 ((node
->prev
->type
== XML_ELEMENT_NODE
) ||
3423 (node
->prev
->type
== XML_TEXT_NODE
)))
3424 result
= xmlGetLineNo(node
->prev
);
3425 else if ((node
->parent
!= NULL
) &&
3426 ((node
->parent
->type
== XML_ELEMENT_NODE
) ||
3427 (node
->parent
->type
== XML_TEXT_NODE
)))
3428 result
= xmlGetLineNo(node
->parent
);
3437 * Build a structure based Path for the given node
3439 * Returns the new path or NULL in case of error. The caller must free
3440 * the returned string
3443 xmlGetNodePath(xmlNodePtr node
)
3445 xmlNodePtr cur
, tmp
, next
;
3446 xmlChar
*buffer
= NULL
, *temp
;
3458 buffer
= (xmlChar
*) xmlMalloc(buf_len
* sizeof(xmlChar
));
3461 buf
= (xmlChar
*) xmlMalloc(buf_len
* sizeof(xmlChar
));
3473 if ((cur
->type
== XML_DOCUMENT_NODE
) ||
3474 (cur
->type
== XML_HTML_DOCUMENT_NODE
)) {
3475 if (buffer
[0] == '/')
3479 } else if (cur
->type
== XML_ELEMENT_NODE
) {
3481 name
= (const char *) cur
->name
;
3483 snprintf(nametemp
, sizeof(nametemp
) - 1,
3484 "%s:%s", cur
->ns
->prefix
, cur
->name
);
3485 nametemp
[sizeof(nametemp
) - 1] = 0;
3491 * Thumbler index computation
3494 while (tmp
!= NULL
) {
3495 if ((tmp
->type
== XML_ELEMENT_NODE
) &&
3496 (xmlStrEqual(cur
->name
, tmp
->name
)))
3502 while (tmp
!= NULL
&& occur
== 0) {
3503 if ((tmp
->type
== XML_ELEMENT_NODE
) &&
3504 (xmlStrEqual(cur
->name
, tmp
->name
)))
3512 } else if (cur
->type
== XML_COMMENT_NODE
) {
3518 * Thumbler index computation
3521 while (tmp
!= NULL
) {
3522 if (tmp
->type
== XML_COMMENT_NODE
)
3528 while (tmp
!= NULL
&& occur
== 0) {
3529 if (tmp
->type
== XML_COMMENT_NODE
)
3537 } else if ((cur
->type
== XML_TEXT_NODE
) ||
3538 (cur
->type
== XML_CDATA_SECTION_NODE
)) {
3544 * Thumbler index computation
3547 while (tmp
!= NULL
) {
3548 if ((cur
->type
== XML_TEXT_NODE
) ||
3549 (cur
->type
== XML_CDATA_SECTION_NODE
))
3555 while (tmp
!= NULL
&& occur
== 0) {
3556 if ((cur
->type
== XML_TEXT_NODE
) ||
3557 (cur
->type
== XML_CDATA_SECTION_NODE
))
3565 } else if (cur
->type
== XML_PI_NODE
) {
3567 snprintf(nametemp
, sizeof(nametemp
) - 1,
3568 "processing-instruction('%s')", cur
->name
);
3569 nametemp
[sizeof(nametemp
) - 1] = 0;
3575 * Thumbler index computation
3578 while (tmp
!= NULL
) {
3579 if ((tmp
->type
== XML_PI_NODE
) &&
3580 (xmlStrEqual(cur
->name
, tmp
->name
)))
3586 while (tmp
!= NULL
&& occur
== 0) {
3587 if ((tmp
->type
== XML_PI_NODE
) &&
3588 (xmlStrEqual(cur
->name
, tmp
->name
)))
3597 } else if (cur
->type
== XML_ATTRIBUTE_NODE
) {
3599 name
= (const char *) (((xmlAttrPtr
) cur
)->name
);
3600 next
= ((xmlAttrPtr
) cur
)->parent
;
3606 * Make sure there is enough room
3608 if (xmlStrlen(buffer
) + sizeof(nametemp
) + 20 > buf_len
) {
3610 2 * buf_len
+ xmlStrlen(buffer
) + sizeof(nametemp
) + 20;
3611 temp
= (xmlChar
*) xmlRealloc(buffer
, buf_len
);
3618 temp
= (xmlChar
*) xmlRealloc(buf
, buf_len
);
3627 snprintf((char *) buf
, buf_len
, "%s%s%s",
3628 sep
, name
, (char *) buffer
);
3630 snprintf((char *) buf
, buf_len
, "%s%s[%d]%s",
3631 sep
, name
, occur
, (char *) buffer
);
3632 snprintf((char *) buffer
, buf_len
, "%s", buf
);
3634 } while (cur
!= NULL
);
3640 * xmlDocGetRootElement:
3641 * @doc: the document
3643 * Get the root element of the document (doc->children is a list
3644 * containing possibly comments, PIs, etc ...).
3646 * Returns the #xmlNodePtr for the root or NULL
3649 xmlDocGetRootElement(xmlDocPtr doc
) {
3652 if (doc
== NULL
) return(NULL
);
3653 ret
= doc
->children
;
3654 while (ret
!= NULL
) {
3655 if (ret
->type
== XML_ELEMENT_NODE
)
3663 * xmlDocSetRootElement:
3664 * @doc: the document
3665 * @root: the new document root element
3667 * Set the root element of the document (doc->children is a list
3668 * containing possibly comments, PIs, etc ...).
3670 * Returns the old root element if any was found
3673 xmlDocSetRootElement(xmlDocPtr doc
, xmlNodePtr root
) {
3674 xmlNodePtr old
= NULL
;
3676 if (doc
== NULL
) return(NULL
);
3679 xmlUnlinkNode(root
);
3681 root
->parent
= (xmlNodePtr
) doc
;
3682 old
= doc
->children
;
3683 while (old
!= NULL
) {
3684 if (old
->type
== XML_ELEMENT_NODE
)
3689 if (doc
->children
== NULL
) {
3690 doc
->children
= root
;
3693 xmlAddSibling(doc
->children
, root
);
3696 xmlReplaceNode(old
, root
);
3703 * @cur: the node being changed
3704 * @lang: the language description
3706 * Set the language of a node, i.e. the values of the xml:lang
3710 xmlNodeSetLang(xmlNodePtr cur
, const xmlChar
*lang
) {
3713 if (cur
== NULL
) return;
3716 case XML_CDATA_SECTION_NODE
:
3717 case XML_COMMENT_NODE
:
3718 case XML_DOCUMENT_NODE
:
3719 case XML_DOCUMENT_TYPE_NODE
:
3720 case XML_DOCUMENT_FRAG_NODE
:
3721 case XML_NOTATION_NODE
:
3722 case XML_HTML_DOCUMENT_NODE
:
3724 case XML_ELEMENT_DECL
:
3725 case XML_ATTRIBUTE_DECL
:
3726 case XML_ENTITY_DECL
:
3728 case XML_ENTITY_REF_NODE
:
3729 case XML_ENTITY_NODE
:
3730 case XML_NAMESPACE_DECL
:
3731 #ifdef LIBXML_DOCB_ENABLED
3732 case XML_DOCB_DOCUMENT_NODE
:
3734 case XML_XINCLUDE_START
:
3735 case XML_XINCLUDE_END
:
3737 case XML_ELEMENT_NODE
:
3738 case XML_ATTRIBUTE_NODE
:
3741 ns
= xmlSearchNsByHref(cur
->doc
, cur
, XML_XML_NAMESPACE
);
3744 xmlSetNsProp(cur
, ns
, BAD_CAST
"lang", lang
);
3749 * @cur: the node being checked
3751 * Searches the language of a node, i.e. the values of the xml:lang
3752 * attribute or the one carried by the nearest ancestor.
3754 * Returns a pointer to the lang value, or NULL if not found
3755 * It's up to the caller to free the memory with xmlFree().
3758 xmlNodeGetLang(xmlNodePtr cur
) {
3761 while (cur
!= NULL
) {
3762 lang
= xmlGetNsProp(cur
, BAD_CAST
"lang", XML_XML_NAMESPACE
);
3772 * xmlNodeSetSpacePreserve:
3773 * @cur: the node being changed
3774 * @val: the xml:space value ("0": default, 1: "preserve")
3776 * Set (or reset) the space preserving behaviour of a node, i.e. the
3777 * value of the xml:space attribute.
3780 xmlNodeSetSpacePreserve(xmlNodePtr cur
, int val
) {
3783 if (cur
== NULL
) return;
3786 case XML_CDATA_SECTION_NODE
:
3787 case XML_COMMENT_NODE
:
3788 case XML_DOCUMENT_NODE
:
3789 case XML_DOCUMENT_TYPE_NODE
:
3790 case XML_DOCUMENT_FRAG_NODE
:
3791 case XML_NOTATION_NODE
:
3792 case XML_HTML_DOCUMENT_NODE
:
3794 case XML_ELEMENT_DECL
:
3795 case XML_ATTRIBUTE_DECL
:
3796 case XML_ENTITY_DECL
:
3798 case XML_ENTITY_REF_NODE
:
3799 case XML_ENTITY_NODE
:
3800 case XML_NAMESPACE_DECL
:
3801 case XML_XINCLUDE_START
:
3802 case XML_XINCLUDE_END
:
3803 #ifdef LIBXML_DOCB_ENABLED
3804 case XML_DOCB_DOCUMENT_NODE
:
3807 case XML_ELEMENT_NODE
:
3808 case XML_ATTRIBUTE_NODE
:
3811 ns
= xmlSearchNsByHref(cur
->doc
, cur
, XML_XML_NAMESPACE
);
3816 xmlSetNsProp(cur
, ns
, BAD_CAST
"space", BAD_CAST
"default");
3819 xmlSetNsProp(cur
, ns
, BAD_CAST
"space", BAD_CAST
"preserve");
3825 * xmlNodeGetSpacePreserve:
3826 * @cur: the node being checked
3828 * Searches the space preserving behaviour of a node, i.e. the values
3829 * of the xml:space attribute or the one carried by the nearest
3832 * Returns -1 if xml:space is not inherited, 0 if "default", 1 if "preserve"
3835 xmlNodeGetSpacePreserve(xmlNodePtr cur
) {
3838 while (cur
!= NULL
) {
3839 space
= xmlGetNsProp(cur
, BAD_CAST
"space", XML_XML_NAMESPACE
);
3840 if (space
!= NULL
) {
3841 if (xmlStrEqual(space
, BAD_CAST
"preserve")) {
3845 if (xmlStrEqual(space
, BAD_CAST
"default")) {
3858 * @cur: the node being changed
3859 * @name: the new tag name
3861 * Set (or reset) the name of a node.
3864 xmlNodeSetName(xmlNodePtr cur
, const xmlChar
*name
) {
3865 if (cur
== NULL
) return;
3866 if (name
== NULL
) return;
3869 case XML_CDATA_SECTION_NODE
:
3870 case XML_COMMENT_NODE
:
3871 case XML_DOCUMENT_TYPE_NODE
:
3872 case XML_DOCUMENT_FRAG_NODE
:
3873 case XML_NOTATION_NODE
:
3874 case XML_HTML_DOCUMENT_NODE
:
3875 case XML_NAMESPACE_DECL
:
3876 case XML_XINCLUDE_START
:
3877 case XML_XINCLUDE_END
:
3878 #ifdef LIBXML_DOCB_ENABLED
3879 case XML_DOCB_DOCUMENT_NODE
:
3882 case XML_ELEMENT_NODE
:
3883 case XML_ATTRIBUTE_NODE
:
3885 case XML_ENTITY_REF_NODE
:
3886 case XML_ENTITY_NODE
:
3888 case XML_DOCUMENT_NODE
:
3889 case XML_ELEMENT_DECL
:
3890 case XML_ATTRIBUTE_DECL
:
3891 case XML_ENTITY_DECL
:
3894 if (cur
->name
!= NULL
) xmlFree((xmlChar
*) cur
->name
);
3895 cur
->name
= xmlStrdup(name
);
3900 * @cur: the node being changed
3901 * @uri: the new base URI
3903 * Set (or reset) the base URI of a node, i.e. the value of the
3904 * xml:base attribute.
3907 xmlNodeSetBase(xmlNodePtr cur
, xmlChar
* uri
) {
3910 if (cur
== NULL
) return;
3913 case XML_CDATA_SECTION_NODE
:
3914 case XML_COMMENT_NODE
:
3915 case XML_DOCUMENT_TYPE_NODE
:
3916 case XML_DOCUMENT_FRAG_NODE
:
3917 case XML_NOTATION_NODE
:
3919 case XML_ELEMENT_DECL
:
3920 case XML_ATTRIBUTE_DECL
:
3921 case XML_ENTITY_DECL
:
3923 case XML_ENTITY_REF_NODE
:
3924 case XML_ENTITY_NODE
:
3925 case XML_NAMESPACE_DECL
:
3926 case XML_XINCLUDE_START
:
3927 case XML_XINCLUDE_END
:
3929 case XML_ELEMENT_NODE
:
3930 case XML_ATTRIBUTE_NODE
:
3932 case XML_DOCUMENT_NODE
:
3933 #ifdef LIBXML_DOCB_ENABLED
3934 case XML_DOCB_DOCUMENT_NODE
:
3936 case XML_HTML_DOCUMENT_NODE
: {
3937 xmlDocPtr doc
= (xmlDocPtr
) cur
;
3939 if (doc
->URL
!= NULL
)
3940 xmlFree((xmlChar
*) doc
->URL
);
3944 doc
->URL
= xmlStrdup(uri
);
3949 ns
= xmlSearchNsByHref(cur
->doc
, cur
, XML_XML_NAMESPACE
);
3952 xmlSetNsProp(cur
, ns
, BAD_CAST
"base", uri
);
3957 * @doc: the document the node pertains to
3958 * @cur: the node being checked
3960 * Searches for the BASE URL. The code should work on both XML
3961 * and HTML document even if base mechanisms are completely different.
3962 * It returns the base as defined in RFC 2396 sections
3963 * 5.1.1. Base URI within Document Content
3965 * 5.1.2. Base URI from the Encapsulating Entity
3966 * However it does not return the document base (5.1.3), use
3967 * xmlDocumentGetBase() for this
3969 * Returns a pointer to the base URL, or NULL if not found
3970 * It's up to the caller to free the memory with xmlFree().
3973 xmlNodeGetBase(xmlDocPtr doc
, xmlNodePtr cur
) {
3974 xmlChar
*oldbase
= NULL
;
3975 xmlChar
*base
, *newbase
;
3977 if ((cur
== NULL
) && (doc
== NULL
))
3979 if (doc
== NULL
) doc
= cur
->doc
;
3980 if ((doc
!= NULL
) && (doc
->type
== XML_HTML_DOCUMENT_NODE
)) {
3981 cur
= doc
->children
;
3982 while ((cur
!= NULL
) && (cur
->name
!= NULL
)) {
3983 if (cur
->type
!= XML_ELEMENT_NODE
) {
3987 if (!xmlStrcasecmp(cur
->name
, BAD_CAST
"html")) {
3988 cur
= cur
->children
;
3991 if (!xmlStrcasecmp(cur
->name
, BAD_CAST
"head")) {
3992 cur
= cur
->children
;
3995 if (!xmlStrcasecmp(cur
->name
, BAD_CAST
"base")) {
3996 return(xmlGetProp(cur
, BAD_CAST
"href"));
4002 while (cur
!= NULL
) {
4003 if (cur
->type
== XML_ENTITY_DECL
) {
4004 xmlEntityPtr ent
= (xmlEntityPtr
) cur
;
4005 return(xmlStrdup(ent
->URI
));
4007 if (cur
->type
== XML_ELEMENT_NODE
) {
4008 base
= xmlGetNsProp(cur
, BAD_CAST
"base", XML_XML_NAMESPACE
);
4010 if (oldbase
!= NULL
) {
4011 newbase
= xmlBuildURI(oldbase
, base
);
4012 if (newbase
!= NULL
) {
4024 if ((!xmlStrncmp(oldbase
, BAD_CAST
"http://", 7)) ||
4025 (!xmlStrncmp(oldbase
, BAD_CAST
"ftp://", 6)) ||
4026 (!xmlStrncmp(oldbase
, BAD_CAST
"urn:", 4)))
4032 if ((doc
!= NULL
) && (doc
->URL
!= NULL
)) {
4033 if (oldbase
== NULL
)
4034 return(xmlStrdup(doc
->URL
));
4035 newbase
= xmlBuildURI(oldbase
, doc
->URL
);
4043 * xmlNodeGetContent:
4044 * @cur: the node being read
4046 * Read the value of a node, this can be either the text carried
4047 * directly by this node if it's a TEXT node or the aggregate string
4048 * of the values carried by this node child's (TEXT and ENTITY_REF).
4049 * Entity references are substituted.
4050 * Returns a new #xmlChar * or NULL if no content is available.
4051 * It's up to the caller to free the memory with xmlFree().
4054 xmlNodeGetContent(xmlNodePtr cur
)
4058 switch (cur
->type
) {
4059 case XML_DOCUMENT_FRAG_NODE
:
4060 case XML_ELEMENT_NODE
:{
4061 xmlNodePtr tmp
= cur
;
4062 xmlBufferPtr buffer
;
4065 buffer
= xmlBufferCreate();
4068 while (tmp
!= NULL
) {
4069 switch (tmp
->type
) {
4070 case XML_CDATA_SECTION_NODE
:
4072 if (tmp
->content
!= NULL
)
4073 xmlBufferCat(buffer
, tmp
->content
);
4075 case XML_ENTITY_REF_NODE
:{
4076 /* recursive substitution of entity references */
4077 xmlChar
*cont
= xmlNodeGetContent(tmp
);
4080 xmlBufferCat(buffer
,
4081 (const xmlChar
*) cont
);
4092 if (tmp
->children
!= NULL
) {
4093 if (tmp
->children
->type
!= XML_ENTITY_DECL
) {
4094 tmp
= tmp
->children
;
4101 if (tmp
->next
!= NULL
) {
4114 if (tmp
->next
!= NULL
) {
4118 } while (tmp
!= NULL
);
4120 ret
= buffer
->content
;
4121 buffer
->content
= NULL
;
4122 xmlBufferFree(buffer
);
4125 case XML_ATTRIBUTE_NODE
:{
4126 xmlAttrPtr attr
= (xmlAttrPtr
) cur
;
4128 if (attr
->parent
!= NULL
)
4129 return (xmlNodeListGetString
4130 (attr
->parent
->doc
, attr
->children
, 1));
4132 return (xmlNodeListGetString(NULL
, attr
->children
, 1));
4135 case XML_COMMENT_NODE
:
4137 if (cur
->content
!= NULL
)
4138 return (xmlStrdup(cur
->content
));
4140 case XML_ENTITY_REF_NODE
:{
4143 xmlBufferPtr buffer
;
4146 /* lookup entity declaration */
4147 ent
= xmlGetDocEntity(cur
->doc
, cur
->name
);
4151 buffer
= xmlBufferCreate();
4155 /* an entity content can be any "well balanced chunk",
4156 * i.e. the result of the content [43] production:
4157 * http://www.w3.org/TR/REC-xml#NT-content
4158 * -> we iterate through child nodes and recursive call
4159 * xmlNodeGetContent() which handles all possible node types */
4160 tmp
= ent
->children
;
4162 xmlChar
*cont
= xmlNodeGetContent(tmp
);
4165 xmlBufferCat(buffer
, (const xmlChar
*) cont
);
4171 ret
= buffer
->content
;
4172 buffer
->content
= NULL
;
4173 xmlBufferFree(buffer
);
4176 case XML_ENTITY_NODE
:
4177 case XML_DOCUMENT_NODE
:
4178 case XML_HTML_DOCUMENT_NODE
:
4179 case XML_DOCUMENT_TYPE_NODE
:
4180 case XML_NOTATION_NODE
:
4182 case XML_XINCLUDE_START
:
4183 case XML_XINCLUDE_END
:
4184 #ifdef LIBXML_DOCB_ENABLED
4185 case XML_DOCB_DOCUMENT_NODE
:
4188 case XML_NAMESPACE_DECL
: {
4191 tmp
= xmlStrdup(((xmlNsPtr
) cur
)->href
);
4194 case XML_ELEMENT_DECL
:
4197 case XML_ATTRIBUTE_DECL
:
4200 case XML_ENTITY_DECL
:
4203 case XML_CDATA_SECTION_NODE
:
4205 if (cur
->content
!= NULL
)
4206 return (xmlStrdup(cur
->content
));
4212 * xmlNodeSetContent:
4213 * @cur: the node being modified
4214 * @content: the new value of the content
4216 * Replace the content of a node.
4219 xmlNodeSetContent(xmlNodePtr cur
, const xmlChar
*content
) {
4222 xmlGenericError(xmlGenericErrorContext
,
4223 "xmlNodeSetContent : node == NULL\n");
4227 switch (cur
->type
) {
4228 case XML_DOCUMENT_FRAG_NODE
:
4229 case XML_ELEMENT_NODE
:
4230 case XML_ATTRIBUTE_NODE
:
4231 if (cur
->children
!= NULL
) xmlFreeNodeList(cur
->children
);
4232 cur
->children
= xmlStringGetNodeList(cur
->doc
, content
);
4233 UPDATE_LAST_CHILD_AND_PARENT(cur
)
4236 case XML_CDATA_SECTION_NODE
:
4237 case XML_ENTITY_REF_NODE
:
4238 case XML_ENTITY_NODE
:
4240 case XML_COMMENT_NODE
:
4241 if (cur
->content
!= NULL
) {
4242 xmlFree(cur
->content
);
4244 if (cur
->children
!= NULL
) xmlFreeNodeList(cur
->children
);
4245 cur
->last
= cur
->children
= NULL
;
4246 if (content
!= NULL
) {
4247 cur
->content
= xmlStrdup(content
);
4249 cur
->content
= NULL
;
4251 case XML_DOCUMENT_NODE
:
4252 case XML_HTML_DOCUMENT_NODE
:
4253 case XML_DOCUMENT_TYPE_NODE
:
4254 case XML_XINCLUDE_START
:
4255 case XML_XINCLUDE_END
:
4256 #ifdef LIBXML_DOCB_ENABLED
4257 case XML_DOCB_DOCUMENT_NODE
:
4260 case XML_NOTATION_NODE
:
4264 case XML_NAMESPACE_DECL
:
4266 case XML_ELEMENT_DECL
:
4269 case XML_ATTRIBUTE_DECL
:
4272 case XML_ENTITY_DECL
:
4279 * xmlNodeSetContentLen:
4280 * @cur: the node being modified
4281 * @content: the new value of the content
4282 * @len: the size of @content
4284 * Replace the content of a node.
4287 xmlNodeSetContentLen(xmlNodePtr cur
, const xmlChar
*content
, int len
) {
4290 xmlGenericError(xmlGenericErrorContext
,
4291 "xmlNodeSetContentLen : node == NULL\n");
4295 switch (cur
->type
) {
4296 case XML_DOCUMENT_FRAG_NODE
:
4297 case XML_ELEMENT_NODE
:
4298 case XML_ATTRIBUTE_NODE
:
4299 if (cur
->children
!= NULL
) xmlFreeNodeList(cur
->children
);
4300 cur
->children
= xmlStringLenGetNodeList(cur
->doc
, content
, len
);
4301 UPDATE_LAST_CHILD_AND_PARENT(cur
)
4304 case XML_CDATA_SECTION_NODE
:
4305 case XML_ENTITY_REF_NODE
:
4306 case XML_ENTITY_NODE
:
4308 case XML_COMMENT_NODE
:
4309 case XML_NOTATION_NODE
:
4310 if (cur
->content
!= NULL
) {
4311 xmlFree(cur
->content
);
4313 if (cur
->children
!= NULL
) xmlFreeNodeList(cur
->children
);
4314 cur
->children
= cur
->last
= NULL
;
4315 if (content
!= NULL
) {
4316 cur
->content
= xmlStrndup(content
, len
);
4318 cur
->content
= NULL
;
4320 case XML_DOCUMENT_NODE
:
4322 case XML_HTML_DOCUMENT_NODE
:
4323 case XML_DOCUMENT_TYPE_NODE
:
4324 case XML_NAMESPACE_DECL
:
4325 case XML_XINCLUDE_START
:
4326 case XML_XINCLUDE_END
:
4327 #ifdef LIBXML_DOCB_ENABLED
4328 case XML_DOCB_DOCUMENT_NODE
:
4331 case XML_ELEMENT_DECL
:
4334 case XML_ATTRIBUTE_DECL
:
4337 case XML_ENTITY_DECL
:
4344 * xmlNodeAddContentLen:
4345 * @cur: the node being modified
4346 * @content: extra content
4347 * @len: the size of @content
4349 * Append the extra substring to the node content.
4352 xmlNodeAddContentLen(xmlNodePtr cur
, const xmlChar
*content
, int len
) {
4355 xmlGenericError(xmlGenericErrorContext
,
4356 "xmlNodeAddContentLen : node == NULL\n");
4360 if (len
<= 0) return;
4361 switch (cur
->type
) {
4362 case XML_DOCUMENT_FRAG_NODE
:
4363 case XML_ELEMENT_NODE
: {
4364 xmlNodePtr last
, newNode
, tmp
;
4367 newNode
= xmlNewTextLen(content
, len
);
4368 if (newNode
!= NULL
) {
4369 tmp
= xmlAddChild(cur
, newNode
);
4372 if ((last
!= NULL
) && (last
->next
== newNode
)) {
4373 xmlTextMerge(last
, newNode
);
4378 case XML_ATTRIBUTE_NODE
:
4381 case XML_CDATA_SECTION_NODE
:
4382 case XML_ENTITY_REF_NODE
:
4383 case XML_ENTITY_NODE
:
4385 case XML_COMMENT_NODE
:
4386 case XML_NOTATION_NODE
:
4387 if (content
!= NULL
) {
4388 cur
->content
= xmlStrncat(cur
->content
, content
, len
);
4390 case XML_DOCUMENT_NODE
:
4392 case XML_HTML_DOCUMENT_NODE
:
4393 case XML_DOCUMENT_TYPE_NODE
:
4394 case XML_NAMESPACE_DECL
:
4395 case XML_XINCLUDE_START
:
4396 case XML_XINCLUDE_END
:
4397 #ifdef LIBXML_DOCB_ENABLED
4398 case XML_DOCB_DOCUMENT_NODE
:
4401 case XML_ELEMENT_DECL
:
4402 case XML_ATTRIBUTE_DECL
:
4403 case XML_ENTITY_DECL
:
4409 * xmlNodeAddContent:
4410 * @cur: the node being modified
4411 * @content: extra content
4413 * Append the extra substring to the node content.
4416 xmlNodeAddContent(xmlNodePtr cur
, const xmlChar
*content
) {
4421 xmlGenericError(xmlGenericErrorContext
,
4422 "xmlNodeAddContent : node == NULL\n");
4426 if (content
== NULL
) return;
4427 len
= xmlStrlen(content
);
4428 xmlNodeAddContentLen(cur
, content
, len
);
4433 * @first: the first text node
4434 * @second: the second text node being merged
4436 * Merge two text nodes into one
4437 * Returns the first text node augmented
4440 xmlTextMerge(xmlNodePtr first
, xmlNodePtr second
) {
4441 if (first
== NULL
) return(second
);
4442 if (second
== NULL
) return(first
);
4443 if (first
->type
!= XML_TEXT_NODE
) return(first
);
4444 if (second
->type
!= XML_TEXT_NODE
) return(first
);
4445 if (second
->name
!= first
->name
)
4447 xmlNodeAddContent(first
, second
->content
);
4448 xmlUnlinkNode(second
);
4449 xmlFreeNode(second
);
4455 * @doc: the document
4456 * @node: the current node
4458 * Search all the namespace applying to a given element.
4459 * Returns an NULL terminated array of all the #xmlNsPtr found
4460 * that need to be freed by the caller or NULL if no
4461 * namespace if defined
4464 xmlGetNsList(xmlDocPtr doc ATTRIBUTE_UNUSED
, xmlNodePtr node
)
4467 xmlNsPtr
*ret
= NULL
;
4472 while (node
!= NULL
) {
4473 if (node
->type
== XML_ELEMENT_NODE
) {
4475 while (cur
!= NULL
) {
4478 (xmlNsPtr
*) xmlMalloc((maxns
+ 1) *
4481 xmlGenericError(xmlGenericErrorContext
,
4482 "xmlGetNsList : out of memory!\n");
4487 for (i
= 0; i
< nbns
; i
++) {
4488 if ((cur
->prefix
== ret
[i
]->prefix
) ||
4489 (xmlStrEqual(cur
->prefix
, ret
[i
]->prefix
)))
4493 if (nbns
>= maxns
) {
4495 ret
= (xmlNsPtr
*) xmlRealloc(ret
,
4500 xmlGenericError(xmlGenericErrorContext
,
4501 "xmlGetNsList : realloc failed!\n");
4512 node
= node
->parent
;
4519 * @doc: the document
4520 * @node: the current node
4521 * @nameSpace: the namespace prefix
4523 * Search a Ns registered under a given name space for a document.
4524 * recurse on the parents until it finds the defined namespace
4525 * or return NULL otherwise.
4526 * @nameSpace can be NULL, this is a search for the default namespace.
4527 * We don't allow to cross entities boundaries. If you don't declare
4528 * the namespace within those you will be in troubles !!! A warning
4529 * is generated to cover this case.
4531 * Returns the namespace pointer or NULL.
4534 xmlSearchNs(xmlDocPtr doc
, xmlNodePtr node
, const xmlChar
*nameSpace
) {
4537 if (node
== NULL
) return(NULL
);
4538 if ((nameSpace
!= NULL
) &&
4539 (xmlStrEqual(nameSpace
, (const xmlChar
*)"xml"))) {
4540 if ((doc
== NULL
) && (node
->type
== XML_ELEMENT_NODE
)) {
4542 * The XML-1.0 namespace is normally held on the root
4543 * element. In this case exceptionally create it on the
4546 cur
= (xmlNsPtr
) xmlMalloc(sizeof(xmlNs
));
4548 xmlGenericError(xmlGenericErrorContext
,
4549 "xmlSearchNs : malloc failed\n");
4552 memset(cur
, 0, sizeof(xmlNs
));
4553 cur
->type
= XML_LOCAL_NAMESPACE
;
4554 cur
->href
= xmlStrdup(XML_XML_NAMESPACE
);
4555 cur
->prefix
= xmlStrdup((const xmlChar
*)"xml");
4556 cur
->next
= node
->nsDef
;
4560 if (doc
->oldNs
== NULL
) {
4562 * Allocate a new Namespace and fill the fields.
4564 doc
->oldNs
= (xmlNsPtr
) xmlMalloc(sizeof(xmlNs
));
4565 if (doc
->oldNs
== NULL
) {
4566 xmlGenericError(xmlGenericErrorContext
,
4567 "xmlSearchNs : malloc failed\n");
4570 memset(doc
->oldNs
, 0, sizeof(xmlNs
));
4571 doc
->oldNs
->type
= XML_LOCAL_NAMESPACE
;
4573 doc
->oldNs
->href
= xmlStrdup(XML_XML_NAMESPACE
);
4574 doc
->oldNs
->prefix
= xmlStrdup((const xmlChar
*)"xml");
4578 while (node
!= NULL
) {
4579 if ((node
->type
== XML_ENTITY_REF_NODE
) ||
4580 (node
->type
== XML_ENTITY_NODE
) ||
4581 (node
->type
== XML_ENTITY_DECL
))
4583 if (node
->type
== XML_ELEMENT_NODE
) {
4585 while (cur
!= NULL
) {
4586 if ((cur
->prefix
== NULL
) && (nameSpace
== NULL
) &&
4587 (cur
->href
!= NULL
))
4589 if ((cur
->prefix
!= NULL
) && (nameSpace
!= NULL
) &&
4590 (cur
->href
!= NULL
) &&
4591 (xmlStrEqual(cur
->prefix
, nameSpace
)))
4596 node
= node
->parent
;
4602 * xmlSearchNsByHref:
4603 * @doc: the document
4604 * @node: the current node
4605 * @href: the namespace value
4607 * Search a Ns aliasing a given URI. Recurse on the parents until it finds
4608 * the defined namespace or return NULL otherwise.
4609 * Returns the namespace pointer or NULL.
4612 xmlSearchNsByHref(xmlDocPtr doc
, xmlNodePtr node
, const xmlChar
*href
) {
4614 xmlNodePtr orig
= node
;
4616 if ((node
== NULL
) || (href
== NULL
)) return(NULL
);
4617 if (xmlStrEqual(href
, XML_XML_NAMESPACE
)) {
4619 * Only the document can hold the XML spec namespace.
4621 if ((doc
== NULL
) && (node
->type
== XML_ELEMENT_NODE
)) {
4623 * The XML-1.0 namespace is normally held on the root
4624 * element. In this case exceptionally create it on the
4627 cur
= (xmlNsPtr
) xmlMalloc(sizeof(xmlNs
));
4629 xmlGenericError(xmlGenericErrorContext
,
4630 "xmlSearchNs : malloc failed\n");
4633 memset(cur
, 0, sizeof(xmlNs
));
4634 cur
->type
= XML_LOCAL_NAMESPACE
;
4635 cur
->href
= xmlStrdup(XML_XML_NAMESPACE
);
4636 cur
->prefix
= xmlStrdup((const xmlChar
*)"xml");
4637 cur
->next
= node
->nsDef
;
4641 if (doc
->oldNs
== NULL
) {
4643 * Allocate a new Namespace and fill the fields.
4645 doc
->oldNs
= (xmlNsPtr
) xmlMalloc(sizeof(xmlNs
));
4646 if (doc
->oldNs
== NULL
) {
4647 xmlGenericError(xmlGenericErrorContext
,
4648 "xmlSearchNsByHref : malloc failed\n");
4651 memset(doc
->oldNs
, 0, sizeof(xmlNs
));
4652 doc
->oldNs
->type
= XML_LOCAL_NAMESPACE
;
4654 doc
->oldNs
->href
= xmlStrdup(XML_XML_NAMESPACE
);
4655 doc
->oldNs
->prefix
= xmlStrdup((const xmlChar
*)"xml");
4659 while (node
!= NULL
) {
4661 while (cur
!= NULL
) {
4662 if ((cur
->href
!= NULL
) && (href
!= NULL
) &&
4663 (xmlStrEqual(cur
->href
, href
))) {
4665 * Check that the prefix is not shadowed between orig and node
4667 xmlNodePtr check
= orig
;
4670 while (check
!= node
) {
4672 while (tst
!= NULL
) {
4673 if ((tst
->prefix
== NULL
) && (cur
->prefix
== NULL
))
4675 if ((tst
->prefix
!= NULL
) && (cur
->prefix
!= NULL
) &&
4676 (xmlStrEqual(tst
->prefix
, cur
->prefix
)))
4680 check
= check
->parent
;
4687 node
= node
->parent
;
4693 * xmlNewReconciliedNs
4694 * @doc: the document
4695 * @tree: a node expected to hold the new namespace
4696 * @ns: the original namespace
4698 * This function tries to locate a namespace definition in a tree
4699 * ancestors, or create a new namespace definition node similar to
4700 * @ns trying to reuse the same prefix. However if the given prefix is
4701 * null (default namespace) or reused within the subtree defined by
4702 * @tree or on one of its ancestors then a new prefix is generated.
4703 * Returns the (new) namespace definition or NULL in case of error
4706 xmlNewReconciliedNs(xmlDocPtr doc
, xmlNodePtr tree
, xmlNsPtr ns
) {
4713 xmlGenericError(xmlGenericErrorContext
,
4714 "xmlNewReconciliedNs : tree == NULL\n");
4720 xmlGenericError(xmlGenericErrorContext
,
4721 "xmlNewReconciliedNs : ns == NULL\n");
4726 * Search an existing namespace definition inherited.
4728 def
= xmlSearchNsByHref(doc
, tree
, ns
->href
);
4733 * Find a close prefix which is not already in use.
4734 * Let's strip namespace prefixes longer than 20 chars !
4736 if (ns
->prefix
== NULL
)
4737 snprintf((char *) prefix
, sizeof(prefix
), "default");
4739 snprintf((char *) prefix
, sizeof(prefix
), "%.20s", ns
->prefix
);
4741 def
= xmlSearchNs(doc
, tree
, prefix
);
4742 while (def
!= NULL
) {
4743 if (counter
> 1000) return(NULL
);
4744 if (ns
->prefix
== NULL
)
4745 snprintf((char *) prefix
, sizeof(prefix
), "default%d", counter
++);
4747 snprintf((char *) prefix
, sizeof(prefix
), "%.20s%d", ns
->prefix
, counter
++);
4748 def
= xmlSearchNs(doc
, tree
, prefix
);
4752 * OK, now we are ready to create a new one.
4754 def
= xmlNewNs(tree
, ns
->href
, prefix
);
4760 * @doc: the document
4761 * @tree: a node defining the subtree to reconciliate
4763 * This function checks that all the namespaces declared within the given
4764 * tree are properly declared. This is needed for example after Copy or Cut
4765 * and then paste operations. The subtree may still hold pointers to
4766 * namespace declarations outside the subtree or invalid/masked. As much
4767 * as possible the function try to reuse the existing namespaces found in
4768 * the new environment. If not possible the new namespaces are redeclared
4769 * on @tree at the top of the given subtree.
4770 * Returns the number of namespace declarations created or -1 in case of error.
4773 xmlReconciliateNs(xmlDocPtr doc
, xmlNodePtr tree
) {
4774 xmlNsPtr
*oldNs
= NULL
;
4775 xmlNsPtr
*newNs
= NULL
;
4780 xmlNodePtr node
= tree
;
4784 while (node
!= NULL
) {
4786 * Reconciliate the node namespace
4788 if (node
->ns
!= NULL
) {
4790 * initialize the cache if needed
4792 if (sizeCache
== 0) {
4794 oldNs
= (xmlNsPtr
*) xmlMalloc(sizeCache
*
4796 if (oldNs
== NULL
) {
4797 xmlGenericError(xmlGenericErrorContext
,
4798 "xmlReconciliateNs : memory pbm\n");
4801 newNs
= (xmlNsPtr
*) xmlMalloc(sizeCache
*
4803 if (newNs
== NULL
) {
4804 xmlGenericError(xmlGenericErrorContext
,
4805 "xmlReconciliateNs : memory pbm\n");
4810 for (i
= 0;i
< nbCache
;i
++) {
4811 if (oldNs
[i
] == node
->ns
) {
4812 node
->ns
= newNs
[i
];
4818 * OK we need to recreate a new namespace definition
4820 n
= xmlNewReconciliedNs(doc
, tree
, node
->ns
);
4821 if (n
!= NULL
) { /* :-( what if else ??? */
4823 * check if we need to grow the cache buffers.
4825 if (sizeCache
<= nbCache
) {
4827 oldNs
= (xmlNsPtr
*) xmlRealloc(oldNs
, sizeCache
*
4829 if (oldNs
== NULL
) {
4830 xmlGenericError(xmlGenericErrorContext
,
4831 "xmlReconciliateNs : memory pbm\n");
4835 newNs
= (xmlNsPtr
*) xmlRealloc(newNs
, sizeCache
*
4837 if (newNs
== NULL
) {
4838 xmlGenericError(xmlGenericErrorContext
,
4839 "xmlReconciliateNs : memory pbm\n");
4845 oldNs
[nbCache
++] = node
->ns
;
4851 * now check for namespace hold by attributes on the node.
4853 attr
= node
->properties
;
4854 while (attr
!= NULL
) {
4855 if (attr
->ns
!= NULL
) {
4857 * initialize the cache if needed
4859 if (sizeCache
== 0) {
4861 oldNs
= (xmlNsPtr
*) xmlMalloc(sizeCache
*
4863 if (oldNs
== NULL
) {
4864 xmlGenericError(xmlGenericErrorContext
,
4865 "xmlReconciliateNs : memory pbm\n");
4868 newNs
= (xmlNsPtr
*) xmlMalloc(sizeCache
*
4870 if (newNs
== NULL
) {
4871 xmlGenericError(xmlGenericErrorContext
,
4872 "xmlReconciliateNs : memory pbm\n");
4877 for (i
= 0;i
< nbCache
;i
++) {
4878 if (oldNs
[i
] == attr
->ns
) {
4879 attr
->ns
= newNs
[i
];
4885 * OK we need to recreate a new namespace definition
4887 n
= xmlNewReconciliedNs(doc
, tree
, attr
->ns
);
4888 if (n
!= NULL
) { /* :-( what if else ??? */
4890 * check if we need to grow the cache buffers.
4892 if (sizeCache
<= nbCache
) {
4894 oldNs
= (xmlNsPtr
*) xmlRealloc(oldNs
, sizeCache
*
4896 if (oldNs
== NULL
) {
4897 xmlGenericError(xmlGenericErrorContext
,
4898 "xmlReconciliateNs : memory pbm\n");
4902 newNs
= (xmlNsPtr
*) xmlRealloc(newNs
, sizeCache
*
4904 if (newNs
== NULL
) {
4905 xmlGenericError(xmlGenericErrorContext
,
4906 "xmlReconciliateNs : memory pbm\n");
4912 oldNs
[nbCache
++] = attr
->ns
;
4921 * Browse the full subtree, deep first
4923 if (node
->children
!= NULL
) {
4925 node
= node
->children
;
4926 } else if ((node
!= tree
) && (node
->next
!= NULL
)) {
4929 } else if (node
!= tree
) {
4930 /* go up to parents->next if needed */
4931 while (node
!= tree
) {
4932 if (node
->parent
!= NULL
)
4933 node
= node
->parent
;
4934 if ((node
!= tree
) && (node
->next
!= NULL
)) {
4938 if (node
->parent
== NULL
) {
4943 /* exit condition */
4959 * @name: the attribute name
4961 * Search an attribute associated to a node
4962 * This function also looks in DTD attribute declaration for #FIXED or
4963 * default declaration values unless DTD use has been turned off.
4965 * Returns the attribute or the attribute declaration or NULL if
4966 * neither was found.
4969 xmlHasProp(xmlNodePtr node
, const xmlChar
*name
) {
4973 if ((node
== NULL
) || (name
== NULL
)) return(NULL
);
4975 * Check on the properties attached to the node
4977 prop
= node
->properties
;
4978 while (prop
!= NULL
) {
4979 if (xmlStrEqual(prop
->name
, name
)) {
4984 if (!xmlCheckDTD
) return(NULL
);
4987 * Check if there is a default declaration in the internal
4988 * or external subsets
4992 xmlAttributePtr attrDecl
;
4993 if (doc
->intSubset
!= NULL
) {
4994 attrDecl
= xmlGetDtdAttrDesc(doc
->intSubset
, node
->name
, name
);
4995 if ((attrDecl
== NULL
) && (doc
->extSubset
!= NULL
))
4996 attrDecl
= xmlGetDtdAttrDesc(doc
->extSubset
, node
->name
, name
);
4997 if (attrDecl
!= NULL
)
4998 return((xmlAttrPtr
) attrDecl
);
5007 * @name: the attribute name
5008 * @nameSpace: the URI of the namespace
5010 * Search for an attribute associated to a node
5011 * This attribute has to be anchored in the namespace specified.
5012 * This does the entity substitution.
5013 * This function looks in DTD attribute declaration for #FIXED or
5014 * default declaration values unless DTD use has been turned off.
5016 * Returns the attribute or the attribute declaration or NULL
5017 * if neither was found.
5020 xmlHasNsProp(xmlNodePtr node
, const xmlChar
*name
, const xmlChar
*nameSpace
) {
5027 prop
= node
->properties
;
5028 if (nameSpace
== NULL
)
5029 return(xmlHasProp(node
, name
));
5030 while (prop
!= NULL
) {
5033 * - same attribute names
5034 * - and the attribute carrying that namespace
5036 if ((xmlStrEqual(prop
->name
, name
)) &&
5037 ((prop
->ns
!= NULL
) && (xmlStrEqual(prop
->ns
->href
, nameSpace
)))) {
5042 if (!xmlCheckDTD
) return(NULL
);
5045 * Check if there is a default declaration in the internal
5046 * or external subsets
5050 if (doc
->intSubset
!= NULL
) {
5051 xmlAttributePtr attrDecl
= NULL
;
5052 xmlNsPtr
*nsList
, *cur
;
5055 nsList
= xmlGetNsList(node
->doc
, node
);
5058 if ((node
->ns
!= NULL
) && (node
->ns
->prefix
!= NULL
)) {
5059 ename
= xmlStrdup(node
->ns
->prefix
);
5060 ename
= xmlStrcat(ename
, BAD_CAST
":");
5061 ename
= xmlStrcat(ename
, node
->name
);
5063 ename
= xmlStrdup(node
->name
);
5065 if (ename
== NULL
) {
5071 while (*cur
!= NULL
) {
5072 if (xmlStrEqual((*cur
)->href
, nameSpace
)) {
5073 attrDecl
= xmlGetDtdQAttrDesc(doc
->intSubset
, ename
,
5074 name
, (*cur
)->prefix
);
5075 if ((attrDecl
== NULL
) && (doc
->extSubset
!= NULL
))
5076 attrDecl
= xmlGetDtdQAttrDesc(doc
->extSubset
, ename
,
5077 name
, (*cur
)->prefix
);
5083 return((xmlAttrPtr
) attrDecl
);
5092 * @name: the attribute name
5094 * Search and get the value of an attribute associated to a node
5095 * This does the entity substitution.
5096 * This function looks in DTD attribute declaration for #FIXED or
5097 * default declaration values unless DTD use has been turned off.
5099 * Returns the attribute value or NULL if not found.
5100 * It's up to the caller to free the memory with xmlFree().
5103 xmlGetProp(xmlNodePtr node
, const xmlChar
*name
) {
5107 if ((node
== NULL
) || (name
== NULL
)) return(NULL
);
5109 * Check on the properties attached to the node
5111 prop
= node
->properties
;
5112 while (prop
!= NULL
) {
5113 if (xmlStrEqual(prop
->name
, name
)) {
5116 ret
= xmlNodeListGetString(node
->doc
, prop
->children
, 1);
5117 if (ret
== NULL
) return(xmlStrdup((xmlChar
*)""));
5122 if (!xmlCheckDTD
) return(NULL
);
5125 * Check if there is a default declaration in the internal
5126 * or external subsets
5130 xmlAttributePtr attrDecl
;
5131 if (doc
->intSubset
!= NULL
) {
5132 attrDecl
= xmlGetDtdAttrDesc(doc
->intSubset
, node
->name
, name
);
5133 if ((attrDecl
== NULL
) && (doc
->extSubset
!= NULL
))
5134 attrDecl
= xmlGetDtdAttrDesc(doc
->extSubset
, node
->name
, name
);
5135 if (attrDecl
!= NULL
)
5136 return(xmlStrdup(attrDecl
->defaultValue
));
5145 * @name: the attribute name
5146 * @nameSpace: the URI of the namespace
5148 * Search and get the value of an attribute associated to a node
5149 * This attribute has to be anchored in the namespace specified.
5150 * This does the entity substitution.
5151 * This function looks in DTD attribute declaration for #FIXED or
5152 * default declaration values unless DTD use has been turned off.
5154 * Returns the attribute value or NULL if not found.
5155 * It's up to the caller to free the memory with xmlFree().
5158 xmlGetNsProp(xmlNodePtr node
, const xmlChar
*name
, const xmlChar
*nameSpace
) {
5166 prop
= node
->properties
;
5167 if (nameSpace
== NULL
)
5168 return(xmlGetProp(node
, name
));
5169 while (prop
!= NULL
) {
5172 * - same attribute names
5173 * - and the attribute carrying that namespace
5175 if ((xmlStrEqual(prop
->name
, name
)) &&
5176 ((prop
->ns
!= NULL
) &&
5177 (xmlStrEqual(prop
->ns
->href
, nameSpace
)))) {
5180 ret
= xmlNodeListGetString(node
->doc
, prop
->children
, 1);
5181 if (ret
== NULL
) return(xmlStrdup((xmlChar
*)""));
5186 if (!xmlCheckDTD
) return(NULL
);
5189 * Check if there is a default declaration in the internal
5190 * or external subsets
5194 if (doc
->intSubset
!= NULL
) {
5195 xmlAttributePtr attrDecl
;
5197 attrDecl
= xmlGetDtdAttrDesc(doc
->intSubset
, node
->name
, name
);
5198 if ((attrDecl
== NULL
) && (doc
->extSubset
!= NULL
))
5199 attrDecl
= xmlGetDtdAttrDesc(doc
->extSubset
, node
->name
, name
);
5201 if ((attrDecl
!= NULL
) && (attrDecl
->prefix
!= NULL
)) {
5203 * The DTD declaration only allows a prefix search
5205 ns
= xmlSearchNs(doc
, node
, attrDecl
->prefix
);
5206 if ((ns
!= NULL
) && (xmlStrEqual(ns
->href
, nameSpace
)))
5207 return(xmlStrdup(attrDecl
->defaultValue
));
5217 * @name: the attribute name
5218 * @value: the attribute value
5220 * Set (or reset) an attribute carried by a node.
5221 * Returns the attribute pointer.
5224 xmlSetProp(xmlNodePtr node
, const xmlChar
*name
, const xmlChar
*value
) {
5228 if ((node
== NULL
) || (name
== NULL
))
5231 prop
= node
->properties
;
5232 while (prop
!= NULL
) {
5233 if ((xmlStrEqual(prop
->name
, name
)) &&
5234 (prop
->ns
== NULL
)){
5235 xmlNodePtr oldprop
= prop
->children
;
5237 prop
->children
= NULL
;
5239 if (value
!= NULL
) {
5243 buffer
= xmlEncodeEntitiesReentrant(node
->doc
, value
);
5244 prop
->children
= xmlStringGetNodeList(node
->doc
, buffer
);
5247 tmp
= prop
->children
;
5248 while (tmp
!= NULL
) {
5249 tmp
->parent
= (xmlNodePtr
) prop
;
5251 if (tmp
->next
== NULL
)
5257 if (oldprop
!= NULL
)
5258 xmlFreeNodeList(oldprop
);
5263 prop
= xmlNewProp(node
, name
, value
);
5270 * @name: the attribute name
5272 * Remove an attribute carried by a node.
5273 * Returns 0 if successful, -1 if not found
5276 xmlUnsetProp(xmlNodePtr node
, const xmlChar
*name
) {
5277 xmlAttrPtr prop
= node
->properties
, prev
= NULL
;;
5279 if ((node
== NULL
) || (name
== NULL
))
5281 while (prop
!= NULL
) {
5282 if ((xmlStrEqual(prop
->name
, name
)) &&
5283 (prop
->ns
== NULL
)) {
5285 node
->properties
= prop
->next
;
5287 prev
->next
= prop
->next
;
5300 * @ns: the namespace definition
5301 * @name: the attribute name
5302 * @value: the attribute value
5304 * Set (or reset) an attribute carried by a node.
5305 * The ns structure must be in scope, this is not checked.
5307 * Returns the attribute pointer.
5310 xmlSetNsProp(xmlNodePtr node
, xmlNsPtr ns
, const xmlChar
*name
,
5311 const xmlChar
*value
) {
5314 if ((node
== NULL
) || (name
== NULL
))
5318 return(xmlSetProp(node
, name
, value
));
5319 if (ns
->href
== NULL
)
5321 prop
= node
->properties
;
5323 while (prop
!= NULL
) {
5326 * - same attribute names
5327 * - and the attribute carrying that namespace
5329 if ((xmlStrEqual(prop
->name
, name
)) &&
5330 (prop
->ns
!= NULL
) && (xmlStrEqual(prop
->ns
->href
, ns
->href
))) {
5331 if (prop
->children
!= NULL
)
5332 xmlFreeNodeList(prop
->children
);
5333 prop
->children
= NULL
;
5336 if (value
!= NULL
) {
5340 buffer
= xmlEncodeEntitiesReentrant(node
->doc
, value
);
5341 prop
->children
= xmlStringGetNodeList(node
->doc
, buffer
);
5343 tmp
= prop
->children
;
5344 while (tmp
!= NULL
) {
5345 tmp
->parent
= (xmlNodePtr
) prop
;
5346 if (tmp
->next
== NULL
)
5356 prop
= xmlNewNsProp(node
, ns
, name
, value
);
5363 * @ns: the namespace definition
5364 * @name: the attribute name
5366 * Remove an attribute carried by a node.
5367 * Returns 0 if successful, -1 if not found
5370 xmlUnsetNsProp(xmlNodePtr node
, xmlNsPtr ns
, const xmlChar
*name
) {
5371 xmlAttrPtr prop
= node
->properties
, prev
= NULL
;;
5373 if ((node
== NULL
) || (name
== NULL
))
5376 return(xmlUnsetProp(node
, name
));
5377 if (ns
->href
== NULL
)
5379 while (prop
!= NULL
) {
5380 if ((xmlStrEqual(prop
->name
, name
)) &&
5381 (prop
->ns
!= NULL
) && (xmlStrEqual(prop
->ns
->href
, ns
->href
))) {
5383 node
->properties
= prop
->next
;
5385 prev
->next
= prop
->next
;
5399 * Is this node a Text node ?
5400 * Returns 1 yes, 0 no
5403 xmlNodeIsText(xmlNodePtr node
) {
5404 if (node
== NULL
) return(0);
5406 if (node
->type
== XML_TEXT_NODE
) return(1);
5414 * Checks whether this node is an empty or whitespace only
5415 * (and possibly ignorable) text-node.
5417 * Returns 1 yes, 0 no
5420 xmlIsBlankNode(xmlNodePtr node
) {
5422 if (node
== NULL
) return(0);
5424 if ((node
->type
!= XML_TEXT_NODE
) &&
5425 (node
->type
!= XML_CDATA_SECTION_NODE
))
5427 if (node
->content
== NULL
) return(1);
5428 cur
= node
->content
;
5430 if (!IS_BLANK(*cur
)) return(0);
5440 * @content: the content
5441 * @len: @content length
5443 * Concat the given string at the end of the existing node content
5447 xmlTextConcat(xmlNodePtr node
, const xmlChar
*content
, int len
) {
5448 if (node
== NULL
) return;
5450 if ((node
->type
!= XML_TEXT_NODE
) &&
5451 (node
->type
!= XML_CDATA_SECTION_NODE
)) {
5453 xmlGenericError(xmlGenericErrorContext
,
5454 "xmlTextConcat: node is not text nor CDATA\n");
5458 node
->content
= xmlStrncat(node
->content
, content
, len
);
5461 /************************************************************************
5463 * Output : to a FILE or in memory *
5465 ************************************************************************/
5470 * routine to create an XML buffer.
5471 * returns the new structure.
5474 xmlBufferCreate(void) {
5477 ret
= (xmlBufferPtr
) xmlMalloc(sizeof(xmlBuffer
));
5479 xmlGenericError(xmlGenericErrorContext
,
5480 "xmlBufferCreate : out of memory!\n");
5484 ret
->size
= xmlDefaultBufferSize
;
5485 ret
->alloc
= xmlBufferAllocScheme
;
5486 ret
->content
= (xmlChar
*) xmlMalloc(ret
->size
* sizeof(xmlChar
));
5487 if (ret
->content
== NULL
) {
5488 xmlGenericError(xmlGenericErrorContext
,
5489 "xmlBufferCreate : out of memory!\n");
5493 ret
->content
[0] = 0;
5498 * xmlBufferCreateSize:
5499 * @size: initial size of buffer
5501 * routine to create an XML buffer.
5502 * returns the new structure.
5505 xmlBufferCreateSize(size_t size
) {
5508 ret
= (xmlBufferPtr
) xmlMalloc(sizeof(xmlBuffer
));
5510 xmlGenericError(xmlGenericErrorContext
,
5511 "xmlBufferCreate : out of memory!\n");
5515 ret
->alloc
= xmlBufferAllocScheme
;
5516 ret
->size
= (size
? size
+2 : 0); /* +1 for ending null */
5518 ret
->content
= (xmlChar
*) xmlMalloc(ret
->size
* sizeof(xmlChar
));
5519 if (ret
->content
== NULL
) {
5520 xmlGenericError(xmlGenericErrorContext
,
5521 "xmlBufferCreate : out of memory!\n");
5525 ret
->content
[0] = 0;
5527 ret
->content
= NULL
;
5532 * xmlBufferSetAllocationScheme:
5533 * @buf: the buffer to tune
5534 * @scheme: allocation scheme to use
5536 * Sets the allocation scheme for this buffer
5539 xmlBufferSetAllocationScheme(xmlBufferPtr buf
,
5540 xmlBufferAllocationScheme scheme
) {
5543 xmlGenericError(xmlGenericErrorContext
,
5544 "xmlBufferSetAllocationScheme: buf == NULL\n");
5549 buf
->alloc
= scheme
;
5554 * @buf: the buffer to free
5556 * Frees an XML buffer. It frees both the content and the structure which
5560 xmlBufferFree(xmlBufferPtr buf
) {
5563 xmlGenericError(xmlGenericErrorContext
,
5564 "xmlBufferFree: buf == NULL\n");
5568 if (buf
->content
!= NULL
) {
5569 xmlFree(buf
->content
);
5581 xmlBufferEmpty(xmlBufferPtr buf
) {
5582 if (buf
->content
== NULL
) return;
5584 memset(buf
->content
, 0, buf
->size
);
5589 * @buf: the buffer to dump
5590 * @len: the number of xmlChar to remove
5592 * Remove the beginning of an XML buffer.
5594 * Returns the number of #xmlChar removed, or -1 in case of failure.
5597 xmlBufferShrink(xmlBufferPtr buf
, unsigned int len
) {
5598 if (len
== 0) return(0);
5599 if (len
> buf
->use
) return(-1);
5602 memmove(buf
->content
, &buf
->content
[len
], buf
->use
* sizeof(xmlChar
));
5604 buf
->content
[buf
->use
] = 0;
5611 * @len: the minimum free size to allocate
5613 * Grow the available space of an XML buffer.
5615 * Returns the new available space or -1 in case of error
5618 xmlBufferGrow(xmlBufferPtr buf
, unsigned int len
) {
5622 if (len
+ buf
->use
< buf
->size
) return(0);
5624 size
= buf
->use
+ len
+ 100;
5626 newbuf
= (xmlChar
*) xmlRealloc(buf
->content
, size
);
5627 if (newbuf
== NULL
) return(-1);
5628 buf
->content
= newbuf
;
5630 return(buf
->size
- buf
->use
);
5635 * @file: the file output
5636 * @buf: the buffer to dump
5638 * Dumps an XML buffer to a FILE *.
5639 * Returns the number of #xmlChar written
5642 xmlBufferDump(FILE *file
, xmlBufferPtr buf
) {
5647 xmlGenericError(xmlGenericErrorContext
,
5648 "xmlBufferDump: buf == NULL\n");
5652 if (buf
->content
== NULL
) {
5654 xmlGenericError(xmlGenericErrorContext
,
5655 "xmlBufferDump: buf->content == NULL\n");
5661 ret
= fwrite(buf
->content
, sizeof(xmlChar
), buf
->use
, file
);
5669 * Function to extract the content of a buffer
5671 * Returns the internal content
5675 xmlBufferContent(const xmlBufferPtr buf
)
5680 return buf
->content
;
5687 * Function to get the length of a buffer
5689 * Returns the length of data in the internal content
5693 xmlBufferLength(const xmlBufferPtr buf
)
5703 * @buf: the buffer to resize
5704 * @size: the desired size
5706 * Resize a buffer to accommodate minimum size of @size.
5708 * Returns 0 in case of problems, 1 otherwise
5711 xmlBufferResize(xmlBufferPtr buf
, unsigned int size
)
5713 unsigned int newSize
;
5714 xmlChar
* rebuf
= NULL
;
5716 /*take care of empty case*/
5717 newSize
= (buf
->size
? buf
->size
*2 : size
);
5719 /* Don't resize if we don't have to */
5720 if (size
< buf
->size
)
5723 /* figure out new size */
5724 switch (buf
->alloc
){
5725 case XML_BUFFER_ALLOC_DOUBLEIT
:
5726 while (size
> newSize
) newSize
*= 2;
5728 case XML_BUFFER_ALLOC_EXACT
:
5736 if (buf
->content
== NULL
)
5737 rebuf
= (xmlChar
*) xmlMalloc(newSize
* sizeof(xmlChar
));
5739 rebuf
= (xmlChar
*) xmlRealloc(buf
->content
,
5740 newSize
* sizeof(xmlChar
));
5741 if (rebuf
== NULL
) {
5742 xmlGenericError(xmlGenericErrorContext
,
5743 "xmlBufferResize : out of memory!\n");
5746 buf
->content
= rebuf
;
5747 buf
->size
= newSize
;
5754 * @buf: the buffer to dump
5755 * @str: the #xmlChar string
5756 * @len: the number of #xmlChar to add
5758 * Add a string range to an XML buffer. if len == -1, the length of
5759 * str is recomputed.
5762 xmlBufferAdd(xmlBufferPtr buf
, const xmlChar
*str
, int len
) {
5763 unsigned int needSize
;
5767 xmlGenericError(xmlGenericErrorContext
,
5768 "xmlBufferAdd: str == NULL\n");
5774 xmlGenericError(xmlGenericErrorContext
,
5775 "xmlBufferAdd: len < 0\n");
5779 if (len
== 0) return;
5782 len
= xmlStrlen(str
);
5784 if (len
<= 0) return;
5786 needSize
= buf
->use
+ len
+ 2;
5787 if (needSize
> buf
->size
){
5788 if (!xmlBufferResize(buf
, needSize
)){
5789 xmlGenericError(xmlGenericErrorContext
,
5790 "xmlBufferAdd : out of memory!\n");
5795 memmove(&buf
->content
[buf
->use
], str
, len
*sizeof(xmlChar
));
5797 buf
->content
[buf
->use
] = 0;
5803 * @str: the #xmlChar string
5804 * @len: the number of #xmlChar to add
5806 * Add a string range to the beginning of an XML buffer.
5807 * if len == -1, the length of @str is recomputed.
5810 xmlBufferAddHead(xmlBufferPtr buf
, const xmlChar
*str
, int len
) {
5811 unsigned int needSize
;
5815 xmlGenericError(xmlGenericErrorContext
,
5816 "xmlBufferAddHead: str == NULL\n");
5822 xmlGenericError(xmlGenericErrorContext
,
5823 "xmlBufferAddHead: len < 0\n");
5827 if (len
== 0) return;
5830 len
= xmlStrlen(str
);
5832 if (len
<= 0) return;
5834 needSize
= buf
->use
+ len
+ 2;
5835 if (needSize
> buf
->size
){
5836 if (!xmlBufferResize(buf
, needSize
)){
5837 xmlGenericError(xmlGenericErrorContext
,
5838 "xmlBufferAddHead : out of memory!\n");
5843 memmove(&buf
->content
[len
], &buf
->content
[0], buf
->use
* sizeof(xmlChar
));
5844 memmove(&buf
->content
[0], str
, len
* sizeof(xmlChar
));
5846 buf
->content
[buf
->use
] = 0;
5851 * @buf: the buffer to dump
5852 * @str: the #xmlChar string
5854 * Append a zero terminated string to an XML buffer.
5857 xmlBufferCat(xmlBufferPtr buf
, const xmlChar
*str
) {
5859 xmlBufferAdd(buf
, str
, -1);
5864 * @buf: the buffer to dump
5865 * @str: the C char string
5867 * Append a zero terminated C string to an XML buffer.
5870 xmlBufferCCat(xmlBufferPtr buf
, const char *str
) {
5875 xmlGenericError(xmlGenericErrorContext
,
5876 "xmlBufferCCat: str == NULL\n");
5880 for (cur
= str
;*cur
!= 0;cur
++) {
5881 if (buf
->use
+ 10 >= buf
->size
) {
5882 if (!xmlBufferResize(buf
, buf
->use
+10)){
5883 xmlGenericError(xmlGenericErrorContext
,
5884 "xmlBufferCCat : out of memory!\n");
5888 buf
->content
[buf
->use
++] = *cur
;
5890 buf
->content
[buf
->use
] = 0;
5894 * xmlBufferWriteCHAR:
5895 * @buf: the XML buffer
5896 * @string: the string to add
5898 * routine which manages and grows an output buffer. This one adds
5899 * xmlChars at the end of the buffer.
5903 (xmlBufferPtr buf
, const xmlChar
*string
) {
5904 xmlBufferCat(buf
, string
);
5908 * xmlBufferWriteChar:
5909 * @buf: the XML buffer output
5910 * @string: the string to add
5912 * routine which manage and grows an output buffer. This one add
5913 * C chars at the end of the array.
5916 xmlBufferWriteChar(xmlBufferPtr buf
, const char *string
) {
5917 xmlBufferCCat(buf
, string
);
5922 * xmlBufferWriteQuotedString:
5923 * @buf: the XML buffer output
5924 * @string: the string to add
5926 * routine which manage and grows an output buffer. This one writes
5927 * a quoted or double quoted #xmlChar string, checking first if it holds
5928 * quote or double-quotes internally
5931 xmlBufferWriteQuotedString(xmlBufferPtr buf
, const xmlChar
*string
) {
5932 if (xmlStrchr(string
, '"')) {
5933 if (xmlStrchr(string
, '\'')) {
5935 xmlGenericError(xmlGenericErrorContext
,
5936 "xmlBufferWriteQuotedString: string contains quote and double-quotes !\n");
5939 xmlBufferCCat(buf
, "'");
5940 xmlBufferCat(buf
, string
);
5941 xmlBufferCCat(buf
, "'");
5943 xmlBufferCCat(buf
, "\"");
5944 xmlBufferCat(buf
, string
);
5945 xmlBufferCCat(buf
, "\"");
5950 /************************************************************************
5952 * Dumping XML tree content to a simple buffer *
5954 ************************************************************************/
5957 xmlNodeListDump(xmlBufferPtr buf
, xmlDocPtr doc
, xmlNodePtr cur
, int level
,
5962 * @buf: the XML buffer output
5965 * Dump a local Namespace definition.
5966 * Should be called in the context of attributes dumps.
5969 xmlNsDump(xmlBufferPtr buf
, xmlNsPtr cur
) {
5972 xmlGenericError(xmlGenericErrorContext
,
5973 "xmlNsDump : Ns == NULL\n");
5977 if (cur
->type
== XML_LOCAL_NAMESPACE
) {
5978 if (xmlStrEqual(cur
->prefix
, BAD_CAST
"xml"))
5981 /* Within the context of an element attributes */
5982 if (cur
->prefix
!= NULL
) {
5983 xmlBufferWriteChar(buf
, " xmlns:");
5984 xmlBufferWriteCHAR(buf
, cur
->prefix
);
5986 xmlBufferWriteChar(buf
, " xmlns");
5987 xmlBufferWriteChar(buf
, "=");
5988 xmlBufferWriteQuotedString(buf
, cur
->href
);
5994 * @buf: the XML buffer output
5995 * @cur: the first namespace
5997 * Dump a list of local Namespace definitions.
5998 * Should be called in the context of attributes dumps.
6001 xmlNsListDump(xmlBufferPtr buf
, xmlNsPtr cur
) {
6002 while (cur
!= NULL
) {
6003 xmlNsDump(buf
, cur
);
6010 * @buf: the XML buffer output
6013 * Dump the XML document DTD, if any.
6016 xmlDtdDump(xmlBufferPtr buf
, xmlDtdPtr dtd
) {
6019 xmlGenericError(xmlGenericErrorContext
,
6020 "xmlDtdDump : no internal subset\n");
6024 xmlBufferWriteChar(buf
, "<!DOCTYPE ");
6025 xmlBufferWriteCHAR(buf
, dtd
->name
);
6026 if (dtd
->ExternalID
!= NULL
) {
6027 xmlBufferWriteChar(buf
, " PUBLIC ");
6028 xmlBufferWriteQuotedString(buf
, dtd
->ExternalID
);
6029 xmlBufferWriteChar(buf
, " ");
6030 xmlBufferWriteQuotedString(buf
, dtd
->SystemID
);
6031 } else if (dtd
->SystemID
!= NULL
) {
6032 xmlBufferWriteChar(buf
, " SYSTEM ");
6033 xmlBufferWriteQuotedString(buf
, dtd
->SystemID
);
6035 if ((dtd
->entities
== NULL
) && (dtd
->elements
== NULL
) &&
6036 (dtd
->attributes
== NULL
) && (dtd
->notations
== NULL
)) {
6037 xmlBufferWriteChar(buf
, ">");
6040 xmlBufferWriteChar(buf
, " [\n");
6041 xmlNodeListDump(buf
, dtd
->doc
, dtd
->children
, -1, 0);
6043 if (dtd
->entities
!= NULL
)
6044 xmlDumpEntitiesTable(buf
, (xmlEntitiesTablePtr
) dtd
->entities
);
6045 if (dtd
->notations
!= NULL
)
6046 xmlDumpNotationTable(buf
, (xmlNotationTablePtr
) dtd
->notations
);
6047 if (dtd
->elements
!= NULL
)
6048 xmlDumpElementTable(buf
, (xmlElementTablePtr
) dtd
->elements
);
6049 if (dtd
->attributes
!= NULL
)
6050 xmlDumpAttributeTable(buf
, (xmlAttributeTablePtr
) dtd
->attributes
);
6052 xmlBufferWriteChar(buf
, "]>");
6056 * xmlAttrSerializeContent:
6057 * @buf: the XML buffer output
6058 * @doc: the document
6059 * @attr: the attribute pointer
6061 * Serialize the attribute in the buffer
6064 xmlAttrSerializeContent(xmlBufferPtr buf
, xmlDocPtr doc
, xmlAttrPtr attr
) {
6065 const xmlChar
*cur
, *base
;
6066 xmlNodePtr children
;
6068 children
= attr
->children
;
6069 while (children
!= NULL
) {
6070 switch (children
->type
) {
6072 base
= cur
= children
->content
;
6076 xmlBufferAdd(buf
, base
, cur
- base
);
6077 xmlBufferAdd(buf
, BAD_CAST
" ", 5);
6081 } else if (*cur
== '\'') {
6083 xmlBufferAdd(buf
, base
, cur
- base
);
6084 xmlBufferAdd(buf
, BAD_CAST
"'", 6);
6088 } else if (*cur
== '"') {
6090 xmlBufferAdd(buf
, base
, cur
- base
);
6091 xmlBufferAdd(buf
, BAD_CAST
""", 6);
6094 } else if (*cur
== '<') {
6096 xmlBufferAdd(buf
, base
, cur
- base
);
6097 xmlBufferAdd(buf
, BAD_CAST
"<", 4);
6100 } else if (*cur
== '>') {
6102 xmlBufferAdd(buf
, base
, cur
- base
);
6103 xmlBufferAdd(buf
, BAD_CAST
">", 4);
6106 } else if (*cur
== '&') {
6108 xmlBufferAdd(buf
, base
, cur
- base
);
6109 xmlBufferAdd(buf
, BAD_CAST
"&", 5);
6112 } else if ((*cur
>= 0x80) && ((doc
== NULL
) ||
6113 (doc
->encoding
== NULL
))) {
6115 * We assume we have UTF-8 content.
6121 xmlBufferAdd(buf
, base
, cur
- base
);
6123 xmlGenericError(xmlGenericErrorContext
,
6124 "xmlAttrSerializeContent : input not UTF-8\n");
6126 doc
->encoding
= xmlStrdup(BAD_CAST
"ISO-8859-1");
6127 snprintf(tmp
, sizeof(tmp
), "&#%d;", *cur
);
6128 tmp
[sizeof(tmp
) - 1] = 0;
6129 xmlBufferAdd(buf
, (xmlChar
*) tmp
, -1);
6133 } else if (*cur
< 0xE0) {
6134 val
= (cur
[0]) & 0x1F;
6136 val
|= (cur
[1]) & 0x3F;
6138 } else if (*cur
< 0xF0) {
6139 val
= (cur
[0]) & 0x0F;
6141 val
|= (cur
[1]) & 0x3F;
6143 val
|= (cur
[2]) & 0x3F;
6145 } else if (*cur
< 0xF8) {
6146 val
= (cur
[0]) & 0x07;
6148 val
|= (cur
[1]) & 0x3F;
6150 val
|= (cur
[2]) & 0x3F;
6152 val
|= (cur
[3]) & 0x3F;
6155 if ((l
== 1) || (!IS_CHAR(val
))) {
6156 xmlGenericError(xmlGenericErrorContext
,
6157 "xmlAttrSerializeContent : char out of range\n");
6159 doc
->encoding
= xmlStrdup(BAD_CAST
"ISO-8859-1");
6160 snprintf(tmp
, sizeof(tmp
), "&#%d;", *cur
);
6161 tmp
[sizeof(tmp
) - 1] = 0;
6162 xmlBufferAdd(buf
, (xmlChar
*) tmp
, -1);
6168 * We could do multiple things here. Just save
6171 snprintf(tmp
, sizeof(tmp
), "&#x%X;", val
);
6172 tmp
[sizeof(tmp
) - 1] = 0;
6173 xmlBufferAdd(buf
, (xmlChar
*) tmp
, -1);
6181 xmlBufferAdd(buf
, base
, cur
- base
);
6183 case XML_ENTITY_REF_NODE
:
6184 xmlBufferAdd(buf
, BAD_CAST
"&", 1);
6185 xmlBufferAdd(buf
, children
->name
, xmlStrlen(children
->name
));
6186 xmlBufferAdd(buf
, BAD_CAST
";", 1);
6189 /* should not happen unless we have a badly built tree */
6192 children
= children
->next
;
6198 * @buf: the XML buffer output
6199 * @doc: the document
6200 * @cur: the attribute pointer
6202 * Dump an XML attribute
6205 xmlAttrDump(xmlBufferPtr buf
, xmlDocPtr doc
, xmlAttrPtr cur
) {
6208 xmlGenericError(xmlGenericErrorContext
,
6209 "xmlAttrDump : property == NULL\n");
6213 xmlBufferWriteChar(buf
, " ");
6214 if ((cur
->ns
!= NULL
) && (cur
->ns
->prefix
!= NULL
)) {
6215 xmlBufferWriteCHAR(buf
, cur
->ns
->prefix
);
6216 xmlBufferWriteChar(buf
, ":");
6218 xmlBufferWriteCHAR(buf
, cur
->name
);
6219 xmlBufferWriteChar(buf
, "=\"");
6220 xmlAttrSerializeContent(buf
, doc
, cur
);
6221 xmlBufferWriteChar(buf
, "\"");
6226 * @buf: the XML buffer output
6227 * @doc: the document
6228 * @cur: the first attribute pointer
6230 * Dump a list of XML attributes
6233 xmlAttrListDump(xmlBufferPtr buf
, xmlDocPtr doc
, xmlAttrPtr cur
) {
6236 xmlGenericError(xmlGenericErrorContext
,
6237 "xmlAttrListDump : property == NULL\n");
6241 while (cur
!= NULL
) {
6242 xmlAttrDump(buf
, doc
, cur
);
6251 * @buf: the XML buffer output
6252 * @doc: the document
6253 * @cur: the first node
6254 * @level: the imbrication level for indenting
6255 * @format: is formatting allowed
6257 * Dump an XML node list, recursive behaviour,children are printed too.
6258 * Note that format = 1 provide node indenting only if xmlIndentTreeOutput = 1
6259 * or xmlKeepBlanksDefault(0) was called
6262 xmlNodeListDump(xmlBufferPtr buf
, xmlDocPtr doc
, xmlNodePtr cur
, int level
,
6268 xmlGenericError(xmlGenericErrorContext
,
6269 "xmlNodeListDump : node == NULL\n");
6273 while (cur
!= NULL
) {
6274 if ((format
) && (xmlIndentTreeOutput
) &&
6275 (cur
->type
== XML_ELEMENT_NODE
))
6276 for (i
= 0;i
< level
;i
++)
6277 xmlBufferWriteChar(buf
, xmlTreeIndentString
);
6278 xmlNodeDump(buf
, doc
, cur
, level
, format
);
6280 xmlBufferWriteChar(buf
, "\n");
6288 * @buf: the XML buffer output
6289 * @doc: the document
6290 * @cur: the current node
6291 * @level: the imbrication level for indenting
6292 * @format: is formatting allowed
6294 * Dump an XML node, recursive behaviour,children are printed too.
6295 * Note that format = 1 provide node indenting only if xmlIndentTreeOutput = 1
6296 * or xmlKeepBlanksDefault(0) was called
6299 xmlNodeDump(xmlBufferPtr buf
, xmlDocPtr doc
, xmlNodePtr cur
, int level
,
6306 xmlGenericError(xmlGenericErrorContext
,
6307 "xmlNodeDump : node == NULL\n");
6311 if (cur
->type
== XML_XINCLUDE_START
)
6313 if (cur
->type
== XML_XINCLUDE_END
)
6315 if (cur
->type
== XML_DTD_NODE
) {
6316 xmlDtdDump(buf
, (xmlDtdPtr
) cur
);
6319 if (cur
->type
== XML_ELEMENT_DECL
) {
6320 xmlDumpElementDecl(buf
, (xmlElementPtr
) cur
);
6323 if (cur
->type
== XML_ATTRIBUTE_NODE
){
6324 xmlAttrDump(buf
, doc
, (xmlAttrPtr
)cur
);
6327 if (cur
->type
== XML_ATTRIBUTE_DECL
) {
6328 xmlDumpAttributeDecl(buf
, (xmlAttributePtr
) cur
);
6331 if (cur
->type
== XML_ENTITY_DECL
) {
6332 xmlDumpEntityDecl(buf
, (xmlEntityPtr
) cur
);
6335 if (cur
->type
== XML_TEXT_NODE
) {
6336 if (cur
->content
!= NULL
) {
6337 if ((cur
->name
== xmlStringText
) ||
6338 (cur
->name
!= xmlStringTextNoenc
)) {
6341 buffer
= xmlEncodeEntitiesReentrant(doc
, cur
->content
);
6342 if (buffer
!= NULL
) {
6343 xmlBufferWriteCHAR(buf
, buffer
);
6348 * Disable escaping, needed for XSLT
6350 xmlBufferWriteCHAR(buf
, cur
->content
);
6355 if (cur
->type
== XML_PI_NODE
) {
6356 xmlBufferWriteChar(buf
, "<?");
6357 xmlBufferWriteCHAR(buf
, cur
->name
);
6358 if (cur
->content
!= NULL
) {
6359 xmlBufferWriteChar(buf
, " ");
6360 xmlBufferWriteCHAR(buf
, cur
->content
);
6362 xmlBufferWriteChar(buf
, "?>");
6365 if (cur
->type
== XML_COMMENT_NODE
) {
6366 if (cur
->content
!= NULL
) {
6367 xmlBufferWriteChar(buf
, "<!--");
6368 xmlBufferWriteCHAR(buf
, cur
->content
);
6369 xmlBufferWriteChar(buf
, "-->");
6373 if (cur
->type
== XML_ENTITY_REF_NODE
) {
6374 xmlBufferWriteChar(buf
, "&");
6375 xmlBufferWriteCHAR(buf
, cur
->name
);
6376 xmlBufferWriteChar(buf
, ";");
6379 if (cur
->type
== XML_CDATA_SECTION_NODE
) {
6380 xmlBufferWriteChar(buf
, "<![CDATA[");
6381 if (cur
->content
!= NULL
)
6382 xmlBufferWriteCHAR(buf
, cur
->content
);
6383 xmlBufferWriteChar(buf
, "]]>");
6388 tmp
= cur
->children
;
6389 while (tmp
!= NULL
) {
6390 if ((tmp
->type
== XML_TEXT_NODE
) ||
6391 (tmp
->type
== XML_ENTITY_REF_NODE
)) {
6398 xmlBufferWriteChar(buf
, "<");
6399 if ((cur
->ns
!= NULL
) && (cur
->ns
->prefix
!= NULL
)) {
6400 xmlBufferWriteCHAR(buf
, cur
->ns
->prefix
);
6401 xmlBufferWriteChar(buf
, ":");
6404 xmlBufferWriteCHAR(buf
, cur
->name
);
6406 xmlNsListDump(buf
, cur
->nsDef
);
6407 if (cur
->properties
!= NULL
)
6408 xmlAttrListDump(buf
, doc
, cur
->properties
);
6410 if (((cur
->type
== XML_ELEMENT_NODE
) || (cur
->content
== NULL
)) &&
6411 (cur
->children
== NULL
) &&
6412 (!xmlSaveNoEmptyTags
)) {
6413 xmlBufferWriteChar(buf
, "/>");
6416 xmlBufferWriteChar(buf
, ">");
6417 if ((cur
->type
!= XML_ELEMENT_NODE
) && (cur
->content
!= NULL
)) {
6420 buffer
= xmlEncodeEntitiesReentrant(doc
, cur
->content
);
6421 if (buffer
!= NULL
) {
6422 xmlBufferWriteCHAR(buf
, buffer
);
6426 if (cur
->children
!= NULL
) {
6427 if (format
) xmlBufferWriteChar(buf
, "\n");
6428 xmlNodeListDump(buf
, doc
, cur
->children
,
6429 (level
>= 0?level
+1:-1), format
);
6430 if ((xmlIndentTreeOutput
) && (format
))
6431 for (i
= 0;i
< level
;i
++)
6432 xmlBufferWriteChar(buf
, xmlTreeIndentString
);
6434 xmlBufferWriteChar(buf
, "</");
6435 if ((cur
->ns
!= NULL
) && (cur
->ns
->prefix
!= NULL
)) {
6436 xmlBufferWriteCHAR(buf
, cur
->ns
->prefix
);
6437 xmlBufferWriteChar(buf
, ":");
6440 xmlBufferWriteCHAR(buf
, cur
->name
);
6441 xmlBufferWriteChar(buf
, ">");
6446 * @f: the FILE * for the output
6447 * @doc: the document
6448 * @cur: the current node
6450 * Dump an XML/HTML node, recursive behaviour, children are printed too.
6453 xmlElemDump(FILE *f
, xmlDocPtr doc
, xmlNodePtr cur
) {
6458 xmlGenericError(xmlGenericErrorContext
,
6459 "xmlElemDump : cur == NULL\n");
6465 xmlGenericError(xmlGenericErrorContext
,
6466 "xmlElemDump : doc == NULL\n");
6470 buf
= xmlBufferCreate();
6471 if (buf
== NULL
) return;
6472 if ((doc
!= NULL
) &&
6473 (doc
->type
== XML_HTML_DOCUMENT_NODE
)) {
6474 #ifdef LIBXML_HTML_ENABLED
6475 htmlNodeDump(buf
, doc
, cur
);
6477 xmlGenericError(xmlGenericErrorContext
,
6478 "HTML support not compiled in\n");
6479 #endif /* LIBXML_HTML_ENABLED */
6481 xmlNodeDump(buf
, doc
, cur
, 0, 1);
6482 xmlBufferDump(f
, buf
);
6486 /************************************************************************
6488 * Dumping XML tree content to an I/O output buffer *
6490 ************************************************************************/
6493 xhtmlNodeDumpOutput(xmlOutputBufferPtr buf
, xmlDocPtr doc
, xmlNodePtr cur
,
6494 int level
, int format
, const char *encoding
);
6496 xmlNodeListDumpOutput(xmlOutputBufferPtr buf
, xmlDocPtr doc
, xmlNodePtr cur
,
6497 int level
, int format
, const char *encoding
);
6499 xmlNodeDumpOutputInternal(xmlOutputBufferPtr buf
, xmlDocPtr doc
,
6500 xmlNodePtr cur
, int level
, int format
, const char *encoding
);
6504 * @buf: the XML buffer output
6507 * Dump a local Namespace definition.
6508 * Should be called in the context of attributes dumps.
6511 xmlNsDumpOutput(xmlOutputBufferPtr buf
, xmlNsPtr cur
) {
6514 xmlGenericError(xmlGenericErrorContext
,
6515 "xmlNsDumpOutput : Ns == NULL\n");
6519 if ((cur
->type
== XML_LOCAL_NAMESPACE
) && (cur
->href
!= NULL
)) {
6520 if (xmlStrEqual(cur
->prefix
, BAD_CAST
"xml"))
6523 /* Within the context of an element attributes */
6524 if (cur
->prefix
!= NULL
) {
6525 xmlOutputBufferWriteString(buf
, " xmlns:");
6526 xmlOutputBufferWriteString(buf
, (const char *)cur
->prefix
);
6528 xmlOutputBufferWriteString(buf
, " xmlns");
6529 xmlOutputBufferWriteString(buf
, "=");
6530 xmlBufferWriteQuotedString(buf
->buffer
, cur
->href
);
6535 * xmlNsListDumpOutput:
6536 * @buf: the XML buffer output
6537 * @cur: the first namespace
6539 * Dump a list of local Namespace definitions.
6540 * Should be called in the context of attributes dumps.
6543 xmlNsListDumpOutput(xmlOutputBufferPtr buf
, xmlNsPtr cur
) {
6544 while (cur
!= NULL
) {
6545 xmlNsDumpOutput(buf
, cur
);
6552 * @buf: the XML buffer output
6553 * @doc: the document
6554 * @encoding: an optional encoding string
6556 * Dump the XML document DTD, if any.
6559 xmlDtdDumpOutput(xmlOutputBufferPtr buf
, xmlDtdPtr dtd
, const char *encoding
) {
6562 xmlGenericError(xmlGenericErrorContext
,
6563 "xmlDtdDumpOutput : no internal subset\n");
6567 xmlOutputBufferWriteString(buf
, "<!DOCTYPE ");
6568 xmlOutputBufferWriteString(buf
, (const char *)dtd
->name
);
6569 if (dtd
->ExternalID
!= NULL
) {
6570 xmlOutputBufferWriteString(buf
, " PUBLIC ");
6571 xmlBufferWriteQuotedString(buf
->buffer
, dtd
->ExternalID
);
6572 xmlOutputBufferWriteString(buf
, " ");
6573 xmlBufferWriteQuotedString(buf
->buffer
, dtd
->SystemID
);
6574 } else if (dtd
->SystemID
!= NULL
) {
6575 xmlOutputBufferWriteString(buf
, " SYSTEM ");
6576 xmlBufferWriteQuotedString(buf
->buffer
, dtd
->SystemID
);
6578 if ((dtd
->entities
== NULL
) && (dtd
->elements
== NULL
) &&
6579 (dtd
->attributes
== NULL
) && (dtd
->notations
== NULL
)) {
6580 xmlOutputBufferWriteString(buf
, ">");
6583 xmlOutputBufferWriteString(buf
, " [\n");
6584 xmlNodeListDumpOutput(buf
, dtd
->doc
, dtd
->children
, -1, 0, encoding
);
6585 xmlOutputBufferWriteString(buf
, "]>");
6589 * xmlAttrDumpOutput:
6590 * @buf: the XML buffer output
6591 * @doc: the document
6592 * @cur: the attribute pointer
6593 * @encoding: an optional encoding string
6595 * Dump an XML attribute
6598 xmlAttrDumpOutput(xmlOutputBufferPtr buf
, xmlDocPtr doc
, xmlAttrPtr cur
,
6599 const char *encoding ATTRIBUTE_UNUSED
) {
6602 xmlGenericError(xmlGenericErrorContext
,
6603 "xmlAttrDumpOutput : property == NULL\n");
6607 xmlOutputBufferWriteString(buf
, " ");
6608 if ((cur
->ns
!= NULL
) && (cur
->ns
->prefix
!= NULL
)) {
6609 xmlOutputBufferWriteString(buf
, (const char *)cur
->ns
->prefix
);
6610 xmlOutputBufferWriteString(buf
, ":");
6612 xmlOutputBufferWriteString(buf
, (const char *)cur
->name
);
6613 xmlOutputBufferWriteString(buf
, "=\"");
6614 xmlAttrSerializeContent(buf
->buffer
, doc
, cur
);
6615 xmlOutputBufferWriteString(buf
, "\"");
6619 * xmlAttrListDumpOutput:
6620 * @buf: the XML buffer output
6621 * @doc: the document
6622 * @cur: the first attribute pointer
6623 * @encoding: an optional encoding string
6625 * Dump a list of XML attributes
6628 xmlAttrListDumpOutput(xmlOutputBufferPtr buf
, xmlDocPtr doc
,
6629 xmlAttrPtr cur
, const char *encoding
) {
6632 xmlGenericError(xmlGenericErrorContext
,
6633 "xmlAttrListDumpOutput : property == NULL\n");
6637 while (cur
!= NULL
) {
6638 xmlAttrDumpOutput(buf
, doc
, cur
, encoding
);
6646 * xmlNodeListDumpOutput:
6647 * @buf: the XML buffer output
6648 * @doc: the document
6649 * @cur: the first node
6650 * @level: the imbrication level for indenting
6651 * @format: is formatting allowed
6652 * @encoding: an optional encoding string
6654 * Dump an XML node list, recursive behaviour, children are printed too.
6655 * Note that format = 1 provide node indenting only if xmlIndentTreeOutput = 1
6656 * or xmlKeepBlanksDefault(0) was called
6659 xmlNodeListDumpOutput(xmlOutputBufferPtr buf
, xmlDocPtr doc
,
6660 xmlNodePtr cur
, int level
, int format
, const char *encoding
) {
6665 xmlGenericError(xmlGenericErrorContext
,
6666 "xmlNodeListDumpOutput : node == NULL\n");
6670 while (cur
!= NULL
) {
6671 if ((format
) && (xmlIndentTreeOutput
) &&
6672 (cur
->type
== XML_ELEMENT_NODE
))
6673 for (i
= 0;i
< level
;i
++)
6674 xmlOutputBufferWriteString(buf
, xmlTreeIndentString
);
6675 xmlNodeDumpOutputInternal(buf
, doc
, cur
, level
, format
, encoding
);
6677 xmlOutputBufferWriteString(buf
, "\n");
6684 * xmlNodeDumpOutputInternal:
6685 * @buf: the XML buffer output
6686 * @doc: the document
6687 * @cur: the current node
6688 * @level: the imbrication level for indenting
6689 * @format: is formatting allowed
6690 * @encoding: an optional encoding string
6692 * Dump an XML node, recursive behaviour, children are printed too.
6693 * Note that format = 1 provide node indenting only if xmlIndentTreeOutput = 1
6694 * or xmlKeepBlanksDefault(0) was called
6697 xmlNodeDumpOutputInternal(xmlOutputBufferPtr buf
, xmlDocPtr doc
,
6698 xmlNodePtr cur
, int level
, int format
, const char *encoding
) {
6704 xmlGenericError(xmlGenericErrorContext
,
6705 "xmlNodeDumpOutput : node == NULL\n");
6709 if (cur
->type
== XML_XINCLUDE_START
)
6711 if (cur
->type
== XML_XINCLUDE_END
)
6713 if (cur
->type
== XML_DTD_NODE
) {
6714 xmlDtdDumpOutput(buf
, (xmlDtdPtr
) cur
, encoding
);
6717 if (cur
->type
== XML_ELEMENT_DECL
) {
6718 xmlDumpElementDecl(buf
->buffer
, (xmlElementPtr
) cur
);
6721 if (cur
->type
== XML_ATTRIBUTE_DECL
) {
6722 xmlDumpAttributeDecl(buf
->buffer
, (xmlAttributePtr
) cur
);
6725 if (cur
->type
== XML_ENTITY_DECL
) {
6726 xmlDumpEntityDecl(buf
->buffer
, (xmlEntityPtr
) cur
);
6729 if (cur
->type
== XML_TEXT_NODE
) {
6730 if (cur
->content
!= NULL
) {
6731 if ((cur
->name
== xmlStringText
) ||
6732 (cur
->name
!= xmlStringTextNoenc
)) {
6735 if (encoding
== NULL
)
6736 buffer
= xmlEncodeEntitiesReentrant(doc
, cur
->content
);
6738 buffer
= xmlEncodeSpecialChars(doc
, cur
->content
);
6739 if (buffer
!= NULL
) {
6740 xmlOutputBufferWriteString(buf
, (const char *)buffer
);
6745 * Disable escaping, needed for XSLT
6747 xmlOutputBufferWriteString(buf
, (const char *) cur
->content
);
6753 if (cur
->type
== XML_PI_NODE
) {
6754 if (cur
->content
!= NULL
) {
6755 xmlOutputBufferWriteString(buf
, "<?");
6756 xmlOutputBufferWriteString(buf
, (const char *)cur
->name
);
6757 if (cur
->content
!= NULL
) {
6758 xmlOutputBufferWriteString(buf
, " ");
6759 xmlOutputBufferWriteString(buf
, (const char *)cur
->content
);
6761 xmlOutputBufferWriteString(buf
, "?>");
6763 xmlOutputBufferWriteString(buf
, "<?");
6764 xmlOutputBufferWriteString(buf
, (const char *)cur
->name
);
6765 xmlOutputBufferWriteString(buf
, "?>");
6769 if (cur
->type
== XML_COMMENT_NODE
) {
6770 if (cur
->content
!= NULL
) {
6771 xmlOutputBufferWriteString(buf
, "<!--");
6772 xmlOutputBufferWriteString(buf
, (const char *)cur
->content
);
6773 xmlOutputBufferWriteString(buf
, "-->");
6777 if (cur
->type
== XML_ENTITY_REF_NODE
) {
6778 xmlOutputBufferWriteString(buf
, "&");
6779 xmlOutputBufferWriteString(buf
, (const char *)cur
->name
);
6780 xmlOutputBufferWriteString(buf
, ";");
6783 if (cur
->type
== XML_CDATA_SECTION_NODE
) {
6784 xmlOutputBufferWriteString(buf
, "<![CDATA[");
6785 if (cur
->content
!= NULL
)
6786 xmlOutputBufferWriteString(buf
, (const char *)cur
->content
);
6787 xmlOutputBufferWriteString(buf
, "]]>");
6792 tmp
= cur
->children
;
6793 while (tmp
!= NULL
) {
6794 if ((tmp
->type
== XML_TEXT_NODE
) ||
6795 (tmp
->type
== XML_ENTITY_REF_NODE
)) {
6802 xmlOutputBufferWriteString(buf
, "<");
6803 if ((cur
->ns
!= NULL
) && (cur
->ns
->prefix
!= NULL
)) {
6804 xmlOutputBufferWriteString(buf
, (const char *)cur
->ns
->prefix
);
6805 xmlOutputBufferWriteString(buf
, ":");
6808 xmlOutputBufferWriteString(buf
, (const char *)cur
->name
);
6810 xmlNsListDumpOutput(buf
, cur
->nsDef
);
6811 if (cur
->properties
!= NULL
)
6812 xmlAttrListDumpOutput(buf
, doc
, cur
->properties
, encoding
);
6814 if (((cur
->type
== XML_ELEMENT_NODE
) || (cur
->content
== NULL
)) &&
6815 (cur
->children
== NULL
) && (!xmlSaveNoEmptyTags
)) {
6816 xmlOutputBufferWriteString(buf
, "/>");
6819 xmlOutputBufferWriteString(buf
, ">");
6820 if ((cur
->type
!= XML_ELEMENT_NODE
) && (cur
->content
!= NULL
)) {
6823 if (encoding
== NULL
)
6824 buffer
= xmlEncodeEntitiesReentrant(doc
, cur
->content
);
6826 buffer
= xmlEncodeSpecialChars(doc
, cur
->content
);
6827 if (buffer
!= NULL
) {
6828 xmlOutputBufferWriteString(buf
, (const char *)buffer
);
6832 if (cur
->children
!= NULL
) {
6833 if (format
) xmlOutputBufferWriteString(buf
, "\n");
6834 xmlNodeListDumpOutput(buf
, doc
, cur
->children
,
6835 (level
>= 0?level
+1:-1), format
, encoding
);
6836 if ((xmlIndentTreeOutput
) && (format
))
6837 for (i
= 0;i
< level
;i
++)
6838 xmlOutputBufferWriteString(buf
, xmlTreeIndentString
);
6840 xmlOutputBufferWriteString(buf
, "</");
6841 if ((cur
->ns
!= NULL
) && (cur
->ns
->prefix
!= NULL
)) {
6842 xmlOutputBufferWriteString(buf
, (const char *)cur
->ns
->prefix
);
6843 xmlOutputBufferWriteString(buf
, ":");
6846 xmlOutputBufferWriteString(buf
, (const char *)cur
->name
);
6847 xmlOutputBufferWriteString(buf
, ">");
6851 * xmlNodeDumpOutput:
6852 * @buf: the XML buffer output
6853 * @doc: the document
6854 * @cur: the current node
6855 * @level: the imbrication level for indenting
6856 * @format: is formatting allowed
6857 * @encoding: an optional encoding string
6859 * Dump an XML node, recursive behaviour, children are printed too.
6860 * Note that format = 1 provide node indenting only if xmlIndentTreeOutput = 1
6861 * or xmlKeepBlanksDefault(0) was called
6864 xmlNodeDumpOutput(xmlOutputBufferPtr buf
, xmlDocPtr doc
, xmlNodePtr cur
,
6865 int level
, int format
, const char *encoding
) {
6866 #ifdef LIBXML_HTML_ENABLED
6870 dtd
= xmlGetIntSubset(doc
);
6872 is_xhtml
= xmlIsXHTML(dtd
->SystemID
, dtd
->ExternalID
);
6873 if (is_xhtml
< 0) is_xhtml
= 0;
6874 if ((is_xhtml
) && (cur
->parent
== (xmlNodePtr
) doc
) &&
6875 (cur
->type
== XML_ELEMENT_NODE
) &&
6876 (xmlStrEqual(cur
->name
, BAD_CAST
"html"))) {
6877 if (encoding
!= NULL
)
6878 htmlSetMetaEncoding(cur
, (const xmlChar
*) encoding
);
6880 htmlSetMetaEncoding(cur
, BAD_CAST
"UTF-8");
6885 xhtmlNodeDumpOutput(buf
, doc
, cur
, level
, format
, encoding
);
6888 xmlNodeDumpOutputInternal(buf
, doc
, cur
, level
, format
, encoding
);
6892 * xmlDocContentDumpOutput:
6893 * @buf: the XML buffer output
6894 * @cur: the document
6895 * @encoding: an optional encoding string
6896 * @format: should formatting spaces been added
6898 * Dump an XML document.
6899 * Note that format = 1 provide node indenting only if xmlIndentTreeOutput = 1
6900 * or xmlKeepBlanksDefault(0) was called
6903 xmlDocContentDumpOutput(xmlOutputBufferPtr buf
, xmlDocPtr cur
,
6904 const char *encoding
, int format
) {
6905 #ifdef LIBXML_HTML_ENABLED
6910 xmlOutputBufferWriteString(buf
, "<?xml version=");
6911 if (cur
->version
!= NULL
)
6912 xmlBufferWriteQuotedString(buf
->buffer
, cur
->version
);
6914 xmlOutputBufferWriteString(buf
, "\"1.0\"");
6915 if (encoding
== NULL
) {
6916 if (cur
->encoding
!= NULL
)
6917 encoding
= (const char *) cur
->encoding
;
6918 else if (cur
->charset
!= XML_CHAR_ENCODING_UTF8
)
6919 encoding
= xmlGetCharEncodingName((xmlCharEncoding
) cur
->charset
);
6921 if (encoding
!= NULL
) {
6922 xmlOutputBufferWriteString(buf
, " encoding=");
6923 xmlBufferWriteQuotedString(buf
->buffer
, (xmlChar
*) encoding
);
6925 switch (cur
->standalone
) {
6927 xmlOutputBufferWriteString(buf
, " standalone=\"no\"");
6930 xmlOutputBufferWriteString(buf
, " standalone=\"yes\"");
6933 xmlOutputBufferWriteString(buf
, "?>\n");
6935 #ifdef LIBXML_HTML_ENABLED
6936 dtd
= xmlGetIntSubset(cur
);
6938 is_xhtml
= xmlIsXHTML(dtd
->SystemID
, dtd
->ExternalID
);
6939 if (is_xhtml
< 0) is_xhtml
= 0;
6942 if (encoding
!= NULL
)
6943 htmlSetMetaEncoding(cur
, (const xmlChar
*) encoding
);
6945 htmlSetMetaEncoding(cur
, BAD_CAST
"UTF-8");
6948 if (cur
->children
!= NULL
) {
6949 xmlNodePtr child
= cur
->children
;
6951 while (child
!= NULL
) {
6952 #ifdef LIBXML_HTML_ENABLED
6954 xhtmlNodeDumpOutput(buf
, cur
, child
, 0, format
, encoding
);
6957 xmlNodeDumpOutputInternal(buf
, cur
, child
, 0, format
, encoding
);
6958 xmlOutputBufferWriteString(buf
, "\n");
6959 child
= child
->next
;
6964 #ifdef LIBXML_HTML_ENABLED
6965 /************************************************************************
6967 * Functions specific to XHTML serialization *
6969 ************************************************************************/
6971 #define XHTML_STRICT_PUBLIC_ID BAD_CAST \
6972 "-//W3C//DTD XHTML 1.0 Strict//EN"
6973 #define XHTML_STRICT_SYSTEM_ID BAD_CAST \
6974 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
6975 #define XHTML_FRAME_PUBLIC_ID BAD_CAST \
6976 "-//W3C//DTD XHTML 1.0 Frameset//EN"
6977 #define XHTML_FRAME_SYSTEM_ID BAD_CAST \
6978 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd"
6979 #define XHTML_TRANS_PUBLIC_ID BAD_CAST \
6980 "-//W3C//DTD XHTML 1.0 Transitional//EN"
6981 #define XHTML_TRANS_SYSTEM_ID BAD_CAST \
6982 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
6984 #define XHTML_NS_NAME BAD_CAST "http://www.w3.org/1999/xhtml"
6987 * @systemID: the system identifier
6988 * @publicID: the public identifier
6990 * Try to find if the document correspond to an XHTML DTD
6992 * Returns 1 if true, 0 if not and -1 in case of error
6995 xmlIsXHTML(const xmlChar
*systemID
, const xmlChar
*publicID
) {
6996 if ((systemID
== NULL
) && (publicID
== NULL
))
6998 if (publicID
!= NULL
) {
6999 if (xmlStrEqual(publicID
, XHTML_STRICT_PUBLIC_ID
)) return(1);
7000 if (xmlStrEqual(publicID
, XHTML_FRAME_PUBLIC_ID
)) return(1);
7001 if (xmlStrEqual(publicID
, XHTML_TRANS_PUBLIC_ID
)) return(1);
7003 if (systemID
!= NULL
) {
7004 if (xmlStrEqual(systemID
, XHTML_STRICT_SYSTEM_ID
)) return(1);
7005 if (xmlStrEqual(systemID
, XHTML_FRAME_SYSTEM_ID
)) return(1);
7006 if (xmlStrEqual(systemID
, XHTML_TRANS_SYSTEM_ID
)) return(1);
7015 * Check if a node is an empty xhtml node
7017 * Returns 1 if the node is an empty node, 0 if not and -1 in case of error
7020 xhtmlIsEmpty(xmlNodePtr node
) {
7023 if (node
->type
!= XML_ELEMENT_NODE
)
7025 if ((node
->ns
!= NULL
) && (!xmlStrEqual(node
->ns
->href
, XHTML_NS_NAME
)))
7027 if (node
->children
!= NULL
)
7029 switch (node
->name
[0]) {
7031 if (xmlStrEqual(node
->name
, BAD_CAST
"area"))
7035 if (xmlStrEqual(node
->name
, BAD_CAST
"br"))
7037 if (xmlStrEqual(node
->name
, BAD_CAST
"base"))
7039 if (xmlStrEqual(node
->name
, BAD_CAST
"basefont"))
7043 if (xmlStrEqual(node
->name
, BAD_CAST
"col"))
7047 if (xmlStrEqual(node
->name
, BAD_CAST
"frame"))
7051 if (xmlStrEqual(node
->name
, BAD_CAST
"hr"))
7055 if (xmlStrEqual(node
->name
, BAD_CAST
"img"))
7057 if (xmlStrEqual(node
->name
, BAD_CAST
"input"))
7059 if (xmlStrEqual(node
->name
, BAD_CAST
"isindex"))
7063 if (xmlStrEqual(node
->name
, BAD_CAST
"link"))
7067 if (xmlStrEqual(node
->name
, BAD_CAST
"meta"))
7071 if (xmlStrEqual(node
->name
, BAD_CAST
"param"))
7079 * xhtmlAttrListDumpOutput:
7080 * @buf: the XML buffer output
7081 * @doc: the document
7082 * @cur: the first attribute pointer
7083 * @encoding: an optional encoding string
7085 * Dump a list of XML attributes
7088 xhtmlAttrListDumpOutput(xmlOutputBufferPtr buf
, xmlDocPtr doc
,
7089 xmlAttrPtr cur
, const char *encoding
) {
7090 xmlAttrPtr xml_lang
= NULL
;
7091 xmlAttrPtr lang
= NULL
;
7092 xmlAttrPtr name
= NULL
;
7093 xmlAttrPtr id
= NULL
;
7097 xmlGenericError(xmlGenericErrorContext
,
7098 "xmlAttrListDumpOutput : property == NULL\n");
7102 while (cur
!= NULL
) {
7103 if ((cur
->ns
== NULL
) && (xmlStrEqual(cur
->name
, BAD_CAST
"id")))
7106 if ((cur
->ns
== NULL
) && (xmlStrEqual(cur
->name
, BAD_CAST
"name")))
7109 if ((cur
->ns
== NULL
) && (xmlStrEqual(cur
->name
, BAD_CAST
"lang")))
7112 if ((cur
->ns
!= NULL
) && (xmlStrEqual(cur
->name
, BAD_CAST
"lang")) &&
7113 (xmlStrEqual(cur
->ns
->prefix
, BAD_CAST
"xml")))
7115 else if ((cur
->ns
== NULL
) &&
7116 ((cur
->children
== NULL
) ||
7117 (cur
->children
->content
== NULL
) ||
7118 (cur
->children
->content
[0] == 0)) &&
7119 (htmlIsBooleanAttr(cur
->name
))) {
7120 if (cur
->children
!= NULL
)
7121 xmlFreeNode(cur
->children
);
7122 cur
->children
= xmlNewText(cur
->name
);
7123 if (cur
->children
!= NULL
)
7124 cur
->children
->parent
= (xmlNodePtr
) cur
;
7126 xmlAttrDumpOutput(buf
, doc
, cur
, encoding
);
7132 if ((name
!= NULL
) && (id
== NULL
)) {
7133 xmlOutputBufferWriteString(buf
, " id=\"");
7134 xmlAttrSerializeContent(buf
->buffer
, doc
, name
);
7135 xmlOutputBufferWriteString(buf
, "\"");
7140 if ((lang
!= NULL
) && (xml_lang
== NULL
)) {
7141 xmlOutputBufferWriteString(buf
, " xml:lang=\"");
7142 xmlAttrSerializeContent(buf
->buffer
, doc
, lang
);
7143 xmlOutputBufferWriteString(buf
, "\"");
7145 if ((xml_lang
!= NULL
) && (lang
== NULL
)) {
7146 xmlOutputBufferWriteString(buf
, " lang=\"");
7147 xmlAttrSerializeContent(buf
->buffer
, doc
, xml_lang
);
7148 xmlOutputBufferWriteString(buf
, "\"");
7153 * xhtmlNodeListDumpOutput:
7154 * @buf: the XML buffer output
7155 * @doc: the XHTML document
7156 * @cur: the first node
7157 * @level: the imbrication level for indenting
7158 * @format: is formatting allowed
7159 * @encoding: an optional encoding string
7161 * Dump an XML node list, recursive behaviour, children are printed too.
7162 * Note that format = 1 provide node indenting only if xmlIndentTreeOutput = 1
7163 * or xmlKeepBlanksDefault(0) was called
7166 xhtmlNodeListDumpOutput(xmlOutputBufferPtr buf
, xmlDocPtr doc
,
7167 xmlNodePtr cur
, int level
, int format
, const char *encoding
) {
7172 xmlGenericError(xmlGenericErrorContext
,
7173 "xhtmlNodeListDumpOutput : node == NULL\n");
7177 while (cur
!= NULL
) {
7178 if ((format
) && (xmlIndentTreeOutput
) &&
7179 (cur
->type
== XML_ELEMENT_NODE
))
7180 for (i
= 0;i
< level
;i
++)
7181 xmlOutputBufferWriteString(buf
, xmlTreeIndentString
);
7182 xhtmlNodeDumpOutput(buf
, doc
, cur
, level
, format
, encoding
);
7184 xmlOutputBufferWriteString(buf
, "\n");
7191 * xhtmlNodeDumpOutput:
7192 * @buf: the XML buffer output
7193 * @doc: the XHTML document
7194 * @cur: the current node
7195 * @level: the imbrication level for indenting
7196 * @format: is formatting allowed
7197 * @encoding: an optional encoding string
7199 * Dump an XHTML node, recursive behaviour, children are printed too.
7200 * Note that format = 1 provide node indenting only if xmlIndentTreeOutput = 1
7201 * or xmlKeepBlanksDefault(0) was called
7204 xhtmlNodeDumpOutput(xmlOutputBufferPtr buf
, xmlDocPtr doc
, xmlNodePtr cur
,
7205 int level
, int format
, const char *encoding
) {
7211 xmlGenericError(xmlGenericErrorContext
,
7212 "xmlNodeDumpOutput : node == NULL\n");
7216 if (cur
->type
== XML_XINCLUDE_START
)
7218 if (cur
->type
== XML_XINCLUDE_END
)
7220 if (cur
->type
== XML_DTD_NODE
) {
7221 xmlDtdDumpOutput(buf
, (xmlDtdPtr
) cur
, encoding
);
7224 if (cur
->type
== XML_ELEMENT_DECL
) {
7225 xmlDumpElementDecl(buf
->buffer
, (xmlElementPtr
) cur
);
7228 if (cur
->type
== XML_ATTRIBUTE_DECL
) {
7229 xmlDumpAttributeDecl(buf
->buffer
, (xmlAttributePtr
) cur
);
7232 if (cur
->type
== XML_ENTITY_DECL
) {
7233 xmlDumpEntityDecl(buf
->buffer
, (xmlEntityPtr
) cur
);
7236 if (cur
->type
== XML_TEXT_NODE
) {
7237 if (cur
->content
!= NULL
) {
7238 if ((cur
->name
== xmlStringText
) ||
7239 (cur
->name
!= xmlStringTextNoenc
)) {
7242 if (encoding
== NULL
)
7243 buffer
= xmlEncodeEntitiesReentrant(doc
, cur
->content
);
7245 buffer
= xmlEncodeSpecialChars(doc
, cur
->content
);
7246 if (buffer
!= NULL
) {
7247 xmlOutputBufferWriteString(buf
, (const char *)buffer
);
7252 * Disable escaping, needed for XSLT
7254 xmlOutputBufferWriteString(buf
, (const char *) cur
->content
);
7260 if (cur
->type
== XML_PI_NODE
) {
7261 if (cur
->content
!= NULL
) {
7262 xmlOutputBufferWriteString(buf
, "<?");
7263 xmlOutputBufferWriteString(buf
, (const char *)cur
->name
);
7264 if (cur
->content
!= NULL
) {
7265 xmlOutputBufferWriteString(buf
, " ");
7266 xmlOutputBufferWriteString(buf
, (const char *)cur
->content
);
7268 xmlOutputBufferWriteString(buf
, "?>");
7270 xmlOutputBufferWriteString(buf
, "<?");
7271 xmlOutputBufferWriteString(buf
, (const char *)cur
->name
);
7272 xmlOutputBufferWriteString(buf
, "?>");
7276 if (cur
->type
== XML_COMMENT_NODE
) {
7277 if (cur
->content
!= NULL
) {
7278 xmlOutputBufferWriteString(buf
, "<!--");
7279 xmlOutputBufferWriteString(buf
, (const char *)cur
->content
);
7280 xmlOutputBufferWriteString(buf
, "-->");
7284 if (cur
->type
== XML_ENTITY_REF_NODE
) {
7285 xmlOutputBufferWriteString(buf
, "&");
7286 xmlOutputBufferWriteString(buf
, (const char *)cur
->name
);
7287 xmlOutputBufferWriteString(buf
, ";");
7290 if (cur
->type
== XML_CDATA_SECTION_NODE
) {
7291 xmlOutputBufferWriteString(buf
, "<![CDATA[");
7292 if (cur
->content
!= NULL
)
7293 xmlOutputBufferWriteString(buf
, (const char *)cur
->content
);
7294 xmlOutputBufferWriteString(buf
, "]]>");
7299 tmp
= cur
->children
;
7300 while (tmp
!= NULL
) {
7301 if ((tmp
->type
== XML_TEXT_NODE
) ||
7302 (tmp
->type
== XML_ENTITY_REF_NODE
)) {
7309 xmlOutputBufferWriteString(buf
, "<");
7310 if ((cur
->ns
!= NULL
) && (cur
->ns
->prefix
!= NULL
)) {
7311 xmlOutputBufferWriteString(buf
, (const char *)cur
->ns
->prefix
);
7312 xmlOutputBufferWriteString(buf
, ":");
7315 xmlOutputBufferWriteString(buf
, (const char *)cur
->name
);
7317 xmlNsListDumpOutput(buf
, cur
->nsDef
);
7318 if ((xmlStrEqual(cur
->name
, BAD_CAST
"html") &&
7319 (cur
->ns
== NULL
) && (cur
->nsDef
== NULL
))) {
7321 * 3.1.1. Strictly Conforming Documents A.3.1.1 3/
7323 xmlOutputBufferWriteString(buf
,
7324 " xmlns=\"http://www.w3.org/1999/xhtml\"");
7326 if (cur
->properties
!= NULL
)
7327 xhtmlAttrListDumpOutput(buf
, doc
, cur
->properties
, encoding
);
7329 if ((cur
->type
== XML_ELEMENT_NODE
) && (cur
->children
== NULL
)) {
7330 if (((cur
->ns
== NULL
) || (cur
->ns
->prefix
== NULL
)) &&
7331 (xhtmlIsEmpty(cur
) == 1)) {
7333 * C.2. Empty Elements
7335 xmlOutputBufferWriteString(buf
, " />");
7338 * C.3. Element Minimization and Empty Element Content
7340 xmlOutputBufferWriteString(buf
, "></");
7341 if ((cur
->ns
!= NULL
) && (cur
->ns
->prefix
!= NULL
)) {
7342 xmlOutputBufferWriteString(buf
, (const char *)cur
->ns
->prefix
);
7343 xmlOutputBufferWriteString(buf
, ":");
7345 xmlOutputBufferWriteString(buf
, (const char *)cur
->name
);
7346 xmlOutputBufferWriteString(buf
, ">");
7350 xmlOutputBufferWriteString(buf
, ">");
7351 if ((cur
->type
!= XML_ELEMENT_NODE
) && (cur
->content
!= NULL
)) {
7354 if (encoding
== NULL
)
7355 buffer
= xmlEncodeEntitiesReentrant(doc
, cur
->content
);
7357 buffer
= xmlEncodeSpecialChars(doc
, cur
->content
);
7358 if (buffer
!= NULL
) {
7359 xmlOutputBufferWriteString(buf
, (const char *)buffer
);
7365 * 4.8. Script and Style elements
7367 if ((cur
->type
== XML_ELEMENT_NODE
) &&
7368 ((xmlStrEqual(cur
->name
, BAD_CAST
"script")) ||
7369 (xmlStrEqual(cur
->name
, BAD_CAST
"style"))) &&
7370 ((cur
->ns
== NULL
) ||
7371 (xmlStrEqual(cur
->ns
->href
, XHTML_NS_NAME
)))) {
7372 xmlNodePtr child
= cur
->children
;
7374 while (child
!= NULL
) {
7375 if ((child
->type
== XML_TEXT_NODE
) ||
7376 (child
->type
== XML_CDATA_SECTION_NODE
)) {
7377 xmlOutputBufferWriteString(buf
, "<![CDATA[");
7378 if (child
->content
!= NULL
)
7379 xmlOutputBufferWriteString(buf
,
7380 (const char *)child
->content
);
7381 xmlOutputBufferWriteString(buf
, "]]>");
7383 xhtmlNodeDumpOutput(buf
, doc
, child
, 0, 0, encoding
);
7385 child
= child
->next
;
7387 } else if (cur
->children
!= NULL
) {
7388 if (format
) xmlOutputBufferWriteString(buf
, "\n");
7389 xhtmlNodeListDumpOutput(buf
, doc
, cur
->children
,
7390 (level
>= 0?level
+1:-1), format
, encoding
);
7391 if ((xmlIndentTreeOutput
) && (format
))
7392 for (i
= 0;i
< level
;i
++)
7393 xmlOutputBufferWriteString(buf
, xmlTreeIndentString
);
7395 xmlOutputBufferWriteString(buf
, "</");
7396 if ((cur
->ns
!= NULL
) && (cur
->ns
->prefix
!= NULL
)) {
7397 xmlOutputBufferWriteString(buf
, (const char *)cur
->ns
->prefix
);
7398 xmlOutputBufferWriteString(buf
, ":");
7401 xmlOutputBufferWriteString(buf
, (const char *)cur
->name
);
7402 xmlOutputBufferWriteString(buf
, ">");
7406 /************************************************************************
7408 * Saving functions front-ends *
7410 ************************************************************************/
7413 * xmlDocDumpFormatMemoryEnc:
7414 * @out_doc: Document to generate XML text from
7415 * @doc_txt_ptr: Memory pointer for allocated XML text
7416 * @doc_txt_len: Length of the generated XML text
7417 * @txt_encoding: Character encoding to use when generating XML text
7418 * @format: should formatting spaces been added
7420 * Dump the current DOM tree into memory using the character encoding specified
7421 * by the caller. Note it is up to the caller of this function to free the
7422 * allocated memory with xmlFree().
7423 * Note that format = 1 provide node indenting only if xmlIndentTreeOutput = 1
7424 * or xmlKeepBlanksDefault(0) was called
7428 xmlDocDumpFormatMemoryEnc(xmlDocPtr out_doc
, xmlChar
**doc_txt_ptr
,
7429 int * doc_txt_len
, const char * txt_encoding
,
7433 xmlCharEncoding doc_charset
;
7434 xmlOutputBufferPtr out_buff
= NULL
;
7435 xmlCharEncodingHandlerPtr conv_hdlr
= NULL
;
7437 if (doc_txt_len
== NULL
) {
7438 doc_txt_len
= &dummy
; /* Continue, caller just won't get length */
7441 if (doc_txt_ptr
== NULL
) {
7443 xmlGenericError(xmlGenericErrorContext
,
7444 "xmlDocDumpFormatMemoryEnc: Null return buffer pointer.");
7448 *doc_txt_ptr
= NULL
;
7451 if (out_doc
== NULL
) {
7452 /* No document, no output */
7453 xmlGenericError(xmlGenericErrorContext
,
7454 "xmlDocDumpFormatMemoryEnc: Null DOM tree document pointer.\n");
7459 * Validate the encoding value, if provided.
7460 * This logic is copied from xmlSaveFileEnc.
7463 if (txt_encoding
== NULL
)
7464 txt_encoding
= (const char *) out_doc
->encoding
;
7465 if (txt_encoding
!= NULL
) {
7466 doc_charset
= xmlParseCharEncoding(txt_encoding
);
7468 if (out_doc
->charset
!= XML_CHAR_ENCODING_UTF8
) {
7469 xmlGenericError(xmlGenericErrorContext
,
7470 "xmlDocDumpFormatMemoryEnc: Source document not in UTF8\n");
7473 } else if (doc_charset
!= XML_CHAR_ENCODING_UTF8
) {
7474 conv_hdlr
= xmlFindCharEncodingHandler(txt_encoding
);
7475 if ( conv_hdlr
== NULL
) {
7476 xmlGenericError(xmlGenericErrorContext
,
7478 "xmlDocDumpFormatMemoryEnc",
7479 "Failed to identify encoding handler for",
7487 if ((out_buff
= xmlAllocOutputBuffer(conv_hdlr
)) == NULL
) {
7488 xmlGenericError(xmlGenericErrorContext
,
7489 "xmlDocDumpFormatMemoryEnc: Failed to allocate output buffer.\n");
7493 xmlDocContentDumpOutput(out_buff
, out_doc
, txt_encoding
, format
);
7494 xmlOutputBufferFlush(out_buff
);
7495 if (out_buff
->conv
!= NULL
) {
7496 *doc_txt_len
= out_buff
->conv
->use
;
7497 *doc_txt_ptr
= xmlStrndup(out_buff
->conv
->content
, *doc_txt_len
);
7499 *doc_txt_len
= out_buff
->buffer
->use
;
7500 *doc_txt_ptr
= xmlStrndup(out_buff
->buffer
->content
, *doc_txt_len
);
7502 (void)xmlOutputBufferClose(out_buff
);
7504 if ((*doc_txt_ptr
== NULL
) && (*doc_txt_len
> 0)) {
7506 xmlGenericError(xmlGenericErrorContext
,
7507 "xmlDocDumpFormatMemoryEnc: %s\n",
7508 "Failed to allocate memory for document text representation.");
7516 * @cur: the document
7517 * @mem: OUT: the memory pointer
7518 * @size: OUT: the memory length
7520 * Dump an XML document in memory and return the #xmlChar * and it's size.
7521 * It's up to the caller to free the memory with xmlFree().
7524 xmlDocDumpMemory(xmlDocPtr cur
, xmlChar
**mem
, int *size
) {
7525 xmlDocDumpFormatMemoryEnc(cur
, mem
, size
, NULL
, 0);
7529 * xmlDocDumpFormatMemory:
7530 * @cur: the document
7531 * @mem: OUT: the memory pointer
7532 * @size: OUT: the memory length
7533 * @format: should formatting spaces been added
7536 * Dump an XML document in memory and return the #xmlChar * and it's size.
7537 * It's up to the caller to free the memory with xmlFree().
7538 * Note that format = 1 provide node indenting only if xmlIndentTreeOutput = 1
7539 * or xmlKeepBlanksDefault(0) was called
7542 xmlDocDumpFormatMemory(xmlDocPtr cur
, xmlChar
**mem
, int *size
, int format
) {
7543 xmlDocDumpFormatMemoryEnc(cur
, mem
, size
, NULL
, format
);
7547 * xmlDocDumpMemoryEnc:
7548 * @out_doc: Document to generate XML text from
7549 * @doc_txt_ptr: Memory pointer for allocated XML text
7550 * @doc_txt_len: Length of the generated XML text
7551 * @txt_encoding: Character encoding to use when generating XML text
7553 * Dump the current DOM tree into memory using the character encoding specified
7554 * by the caller. Note it is up to the caller of this function to free the
7555 * allocated memory with xmlFree().
7559 xmlDocDumpMemoryEnc(xmlDocPtr out_doc
, xmlChar
**doc_txt_ptr
,
7560 int * doc_txt_len
, const char * txt_encoding
) {
7561 xmlDocDumpFormatMemoryEnc(out_doc
, doc_txt_ptr
, doc_txt_len
,
7566 * xmlGetDocCompressMode:
7567 * @doc: the document
7569 * get the compression ratio for a document, ZLIB based
7570 * Returns 0 (uncompressed) to 9 (max compression)
7573 xmlGetDocCompressMode (xmlDocPtr doc
) {
7574 if (doc
== NULL
) return(-1);
7575 return(doc
->compression
);
7579 * xmlSetDocCompressMode:
7580 * @doc: the document
7581 * @mode: the compression ratio
7583 * set the compression ratio for a document, ZLIB based
7584 * Correct values: 0 (uncompressed) to 9 (max compression)
7587 xmlSetDocCompressMode (xmlDocPtr doc
, int mode
) {
7588 if (doc
== NULL
) return;
7589 if (mode
< 0) doc
->compression
= 0;
7590 else if (mode
> 9) doc
->compression
= 9;
7591 else doc
->compression
= mode
;
7595 * xmlGetCompressMode:
7597 * get the default compression mode used, ZLIB based.
7598 * Returns 0 (uncompressed) to 9 (max compression)
7601 xmlGetCompressMode(void)
7603 return (xmlCompressMode
);
7607 * xmlSetCompressMode:
7608 * @mode: the compression ratio
7610 * set the default compression mode used, ZLIB based
7611 * Correct values: 0 (uncompressed) to 9 (max compression)
7614 xmlSetCompressMode(int mode
) {
7615 if (mode
< 0) xmlCompressMode
= 0;
7616 else if (mode
> 9) xmlCompressMode
= 9;
7617 else xmlCompressMode
= mode
;
7623 * @cur: the document
7624 * @format: should formatting spaces been added
7626 * Dump an XML document to an open FILE.
7628 * returns: the number of bytes written or -1 in case of failure.
7631 xmlDocFormatDump(FILE *f
, xmlDocPtr cur
, int format
) {
7632 xmlOutputBufferPtr buf
;
7633 const char * encoding
;
7634 xmlCharEncodingHandlerPtr handler
= NULL
;
7639 xmlGenericError(xmlGenericErrorContext
,
7640 "xmlDocDump : document == NULL\n");
7644 encoding
= (const char *) cur
->encoding
;
7646 if (encoding
!= NULL
) {
7647 xmlCharEncoding enc
;
7649 enc
= xmlParseCharEncoding(encoding
);
7651 if (cur
->charset
!= XML_CHAR_ENCODING_UTF8
) {
7652 xmlGenericError(xmlGenericErrorContext
,
7653 "xmlDocDump: document not in UTF8\n");
7656 if (enc
!= XML_CHAR_ENCODING_UTF8
) {
7657 handler
= xmlFindCharEncodingHandler(encoding
);
7658 if (handler
== NULL
) {
7659 xmlFree((char *) cur
->encoding
);
7660 cur
->encoding
= NULL
;
7664 buf
= xmlOutputBufferCreateFile(f
, handler
);
7665 if (buf
== NULL
) return(-1);
7666 xmlDocContentDumpOutput(buf
, cur
, NULL
, format
);
7668 ret
= xmlOutputBufferClose(buf
);
7675 * @cur: the document
7677 * Dump an XML document to an open FILE.
7679 * returns: the number of bytes written or -1 in case of failure.
7682 xmlDocDump(FILE *f
, xmlDocPtr cur
) {
7683 return(xmlDocFormatDump (f
, cur
, 0));
7688 * @buf: an output I/O buffer
7689 * @cur: the document
7690 * @encoding: the encoding if any assuming the I/O layer handles the trancoding
7692 * Dump an XML document to an I/O buffer.
7694 * returns: the number of bytes written or -1 in case of failure.
7697 xmlSaveFileTo(xmlOutputBufferPtr buf
, xmlDocPtr cur
, const char *encoding
) {
7700 if (buf
== NULL
) return(0);
7701 xmlDocContentDumpOutput(buf
, cur
, encoding
, 0);
7702 ret
= xmlOutputBufferClose(buf
);
7707 * xmlSaveFormatFileTo:
7708 * @buf: an output I/O buffer
7709 * @cur: the document
7710 * @encoding: the encoding if any assuming the I/O layer handles the trancoding
7711 * @format: should formatting spaces been added
7713 * Dump an XML document to an I/O buffer.
7715 * returns: the number of bytes written or -1 in case of failure.
7718 xmlSaveFormatFileTo(xmlOutputBufferPtr buf
, xmlDocPtr cur
, const char *encoding
, int format
) {
7721 if (buf
== NULL
) return(0);
7722 xmlDocContentDumpOutput(buf
, cur
, encoding
, format
);
7723 ret
= xmlOutputBufferClose(buf
);
7728 * xmlSaveFormatFileEnc
7729 * @filename: the filename or URL to output
7730 * @cur: the document being saved
7731 * @encoding: the name of the encoding to use or NULL.
7732 * @format: should formatting spaces be added.
7734 * Returns the number of bytes written or -1 in case of error.
7737 xmlSaveFormatFileEnc( const char * filename
, xmlDocPtr cur
,
7738 const char * encoding
, int format
) {
7739 xmlOutputBufferPtr buf
;
7740 xmlCharEncodingHandlerPtr handler
= NULL
;
7741 xmlCharEncoding enc
;
7744 if (encoding
== NULL
)
7745 encoding
= (const char *) cur
->encoding
;
7747 if (encoding
!= NULL
) {
7749 enc
= xmlParseCharEncoding(encoding
);
7750 if (cur
->charset
!= XML_CHAR_ENCODING_UTF8
) {
7751 xmlGenericError(xmlGenericErrorContext
,
7752 "xmlSaveFormatFileEnc: document not in UTF8\n");
7755 if (enc
!= XML_CHAR_ENCODING_UTF8
) {
7756 handler
= xmlFindCharEncodingHandler(encoding
);
7757 if (handler
== NULL
)
7763 if (cur
->compression
< 0) cur
->compression
= xmlCompressMode
;
7766 * save the content to a temp buffer.
7768 buf
= xmlOutputBufferCreateFilename(filename
, handler
, cur
->compression
);
7769 if (buf
== NULL
) return(-1);
7771 xmlDocContentDumpOutput(buf
, cur
, encoding
, format
);
7773 ret
= xmlOutputBufferClose(buf
);
7780 * @filename: the filename (or URL)
7781 * @cur: the document
7782 * @encoding: the name of an encoding (or NULL)
7784 * Dump an XML document, converting it to the given encoding
7786 * returns: the number of bytes written or -1 in case of failure.
7789 xmlSaveFileEnc(const char *filename
, xmlDocPtr cur
, const char *encoding
) {
7790 return ( xmlSaveFormatFileEnc( filename
, cur
, encoding
, 0 ) );
7794 * xmlSaveFormatFile:
7795 * @filename: the filename (or URL)
7796 * @cur: the document
7797 * @format: should formatting spaces been added
7799 * Dump an XML document to a file. Will use compression if
7800 * compiled in and enabled. If @filename is "-" the stdout file is
7801 * used. If @format is set then the document will be indented on output.
7803 * returns: the number of bytes written or -1 in case of failure.
7806 xmlSaveFormatFile(const char *filename
, xmlDocPtr cur
, int format
) {
7807 return ( xmlSaveFormatFileEnc( filename
, cur
, NULL
, format
) );
7812 * @filename: the filename (or URL)
7813 * @cur: the document
7815 * Dump an XML document to a file. Will use compression if
7816 * compiled in and enabled. If @filename is "-" the stdout file is
7818 * returns: the number of bytes written or -1 in case of failure.
7821 xmlSaveFile(const char *filename
, xmlDocPtr cur
) {
7822 return(xmlSaveFormatFileEnc(filename
, cur
, NULL
, 0));