blob: b5e116ca6f1e95b2d1b2520ae10a66fa918c4769 [file] [log] [blame]
Daniel Veillard260a68f1998-08-13 03:39:55 +00001/*
2 * tree.c : implemetation of access function for an XML tree.
3 *
4 * See Copyright for the status of this software.
5 *
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00006 * Daniel.Veillard@w3.org
Daniel Veillard260a68f1998-08-13 03:39:55 +00007 */
8
Daniel Veillard7f7d1111999-09-22 09:46:25 +00009#ifdef WIN32
Daniel Veillard3c558c31999-12-22 11:30:41 +000010#include "win32config.h"
Daniel Veillard7f7d1111999-09-22 09:46:25 +000011#else
Daniel Veillard151b1b01998-09-23 00:49:46 +000012#include "config.h"
Daniel Veillard7f7d1111999-09-22 09:46:25 +000013#endif
14
Daniel Veillard260a68f1998-08-13 03:39:55 +000015#include <stdio.h>
Daniel Veillard260a68f1998-08-13 03:39:55 +000016#include <string.h> /* for memset() only ! */
17
Daniel Veillard7f7d1111999-09-22 09:46:25 +000018#ifdef HAVE_CTYPE_H
19#include <ctype.h>
20#endif
21#ifdef HAVE_STDLIB_H
22#include <stdlib.h>
23#endif
Daniel Veillard151b1b01998-09-23 00:49:46 +000024#ifdef HAVE_ZLIB_H
25#include <zlib.h>
26#endif
27
Daniel Veillard361d8452000-04-03 19:48:13 +000028#include <libxml/xmlmemory.h>
29#include <libxml/tree.h>
30#include <libxml/parser.h>
31#include <libxml/entities.h>
32#include <libxml/valid.h>
Daniel Veillard260a68f1998-08-13 03:39:55 +000033
Daniel Veillarddd6b3671999-09-23 22:19:22 +000034static xmlChar xmlStringText[] = { 't', 'e', 'x', 't', 0 };
Daniel Veillardcf461992000-03-14 18:30:20 +000035static xmlChar xmlStringComment[] = { 'c', 'o', 'm', 'm', 'e', 'n', 't', 0 };
Daniel Veillard260a68f1998-08-13 03:39:55 +000036int oldXMLWDcompatibility = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +000037int xmlIndentTreeOutput = 0;
Daniel Veillardf5c2c871999-12-01 09:51:45 +000038xmlBufferAllocationScheme xmlBufferAllocScheme = XML_BUFFER_ALLOC_EXACT;
Daniel Veillard260a68f1998-08-13 03:39:55 +000039
Daniel Veillard15a8df41998-09-24 19:15:06 +000040static int xmlCompressMode = 0;
Daniel Veillard10a2c651999-12-12 13:03:50 +000041static int xmlCheckDTD = 1;
Daniel Veillarde41f2b72000-01-30 20:00:07 +000042int xmlSaveNoEmptyTags = 0;
Daniel Veillard3e6d2372000-03-04 11:39:43 +000043
44#define IS_BLANK(c) \
45 (((c) == '\n') || ((c) == '\r') || ((c) == '\t') || ((c) == ' '))
Daniel Veillard15a8df41998-09-24 19:15:06 +000046
Daniel Veillard39a1f9a1999-01-17 19:11:59 +000047#define UPDATE_LAST_CHILD(n) if ((n) != NULL) { \
Daniel Veillardcf461992000-03-14 18:30:20 +000048 xmlNodePtr ulccur = (n)->children; \
Daniel Veillard39a1f9a1999-01-17 19:11:59 +000049 if (ulccur == NULL) { \
50 (n)->last = NULL; \
51 } else { \
52 while (ulccur->next != NULL) ulccur = ulccur->next; \
53 (n)->last = ulccur; \
Daniel Veillard1e346af1999-02-22 10:33:01 +000054}}
Daniel Veillard39a1f9a1999-01-17 19:11:59 +000055
Daniel Veillardad8f99d2000-01-15 14:20:03 +000056/* #define DEBUG_BUFFER */
57/* #define DEBUG_TREE */
58
Daniel Veillard260a68f1998-08-13 03:39:55 +000059/************************************************************************
60 * *
61 * Allocation and deallocation of basic structures *
62 * *
63 ************************************************************************/
64
Daniel Veillard97b58771998-10-20 06:14:16 +000065/**
Daniel Veillardf5c2c871999-12-01 09:51:45 +000066 * xmlSetBufferAllocationScheme:
67 * @scheme: allocation method to use
68 *
69 * Set the buffer allocation method. Types are
70 * XML_BUFFER_ALLOC_EXACT - use exact sizes, keeps memory usage down
71 * XML_BUFFER_ALLOC_DOUBLEIT - double buffer when extra needed,
72 * improves performance
73 */
74void
75xmlSetBufferAllocationScheme(xmlBufferAllocationScheme scheme) {
76 xmlBufferAllocScheme = scheme;
77}
78
79/**
80 * xmlGetBufferAllocationScheme:
81 *
82 * Types are
83 * XML_BUFFER_ALLOC_EXACT - use exact sizes, keeps memory usage down
84 * XML_BUFFER_ALLOC_DOUBLEIT - double buffer when extra needed,
85 * improves performance
86 *
87 * Returns the current allocation scheme
88 */
89xmlBufferAllocationScheme
90xmlGetBufferAllocationScheme() {
91 return xmlBufferAllocScheme;
92}
93
94/**
Daniel Veillard97b58771998-10-20 06:14:16 +000095 * xmlUpgradeOldNs:
96 * @doc: a document pointer
97 *
98 * Upgrade old style Namespaces (PI) and move them to the root of the document.
Daniel Veillard260a68f1998-08-13 03:39:55 +000099 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000100void
101xmlUpgradeOldNs(xmlDocPtr doc) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000102 xmlNsPtr cur;
103
104 if ((doc == NULL) || (doc->oldNs == NULL)) return;
Daniel Veillardcf461992000-03-14 18:30:20 +0000105 if (doc->children == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000106#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +0000107 fprintf(stderr, "xmlUpgradeOldNs: failed no root !\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000108#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000109 return;
110 }
111
112 cur = doc->oldNs;
113 while (cur->next != NULL) {
114 cur->type = XML_LOCAL_NAMESPACE;
115 cur = cur->next;
116 }
117 cur->type = XML_LOCAL_NAMESPACE;
Daniel Veillardcf461992000-03-14 18:30:20 +0000118 cur->next = doc->children->nsDef;
119 doc->children->nsDef = doc->oldNs;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000120 doc->oldNs = NULL;
121}
122
Daniel Veillard97b58771998-10-20 06:14:16 +0000123/**
124 * xmlNewNs:
125 * @node: the element carrying the namespace
126 * @href: the URI associated
127 * @prefix: the prefix for the namespace
128 *
Daniel Veillard686d6b62000-01-03 11:08:02 +0000129 * Creation of a new Namespace. This function will refuse to create
130 * a namespace with a similar prefix than an existing one present on this
131 * node.
132 * Returns returns a new namespace pointer or NULL
Daniel Veillard260a68f1998-08-13 03:39:55 +0000133 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000134xmlNsPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000135xmlNewNs(xmlNodePtr node, const xmlChar *href, const xmlChar *prefix) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000136 xmlNsPtr cur;
137
138 if (href == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000139#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +0000140 fprintf(stderr, "xmlNewNs: href == NULL !\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000141#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000142 return(NULL);
143 }
144
145 /*
Daniel Veillardcf461992000-03-14 18:30:20 +0000146 * Allocate a new Namespace and fill the fields.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000147 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000148 cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000149 if (cur == NULL) {
150 fprintf(stderr, "xmlNewNs : malloc failed\n");
151 return(NULL);
152 }
Daniel Veillardcf461992000-03-14 18:30:20 +0000153 memset(cur, 0, sizeof(xmlNs));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000154 cur->type = XML_LOCAL_NAMESPACE;
Daniel Veillardcf461992000-03-14 18:30:20 +0000155
Daniel Veillard260a68f1998-08-13 03:39:55 +0000156 if (href != NULL)
157 cur->href = xmlStrdup(href);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000158 if (prefix != NULL)
159 cur->prefix = xmlStrdup(prefix);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000160
161 /*
162 * Add it at the end to preserve parsing order ...
Daniel Veillard686d6b62000-01-03 11:08:02 +0000163 * and checks for existing use of the prefix
Daniel Veillard260a68f1998-08-13 03:39:55 +0000164 */
Daniel Veillard260a68f1998-08-13 03:39:55 +0000165 if (node != NULL) {
166 if (node->nsDef == NULL) {
167 node->nsDef = cur;
168 } else {
169 xmlNsPtr prev = node->nsDef;
170
Daniel Veillard0142b842000-01-14 14:45:24 +0000171 if (((prev->prefix == NULL) && (cur->prefix == NULL)) ||
172 (!xmlStrcmp(prev->prefix, cur->prefix))) {
173 xmlFreeNs(cur);
174 return(NULL);
175 }
Daniel Veillard686d6b62000-01-03 11:08:02 +0000176 while (prev->next != NULL) {
Daniel Veillard0142b842000-01-14 14:45:24 +0000177 prev = prev->next;
Daniel Veillard686d6b62000-01-03 11:08:02 +0000178 if (((prev->prefix == NULL) && (cur->prefix == NULL)) ||
179 (!xmlStrcmp(prev->prefix, cur->prefix))) {
180 xmlFreeNs(cur);
181 return(NULL);
182 }
Daniel Veillard686d6b62000-01-03 11:08:02 +0000183 }
Daniel Veillard260a68f1998-08-13 03:39:55 +0000184 prev->next = cur;
185 }
186 }
Daniel Veillard260a68f1998-08-13 03:39:55 +0000187 return(cur);
188}
189
Daniel Veillard97b58771998-10-20 06:14:16 +0000190/**
191 * xmlNewGlobalNs:
192 * @doc: the document carrying the namespace
193 * @href: the URI associated
194 * @prefix: the prefix for the namespace
195 *
Daniel Veillard686d6b62000-01-03 11:08:02 +0000196 * Creation of a Namespace, the old way using PI and without scoping
197 * DEPRECATED !!!
Daniel Veillard0142b842000-01-14 14:45:24 +0000198 * It now create a namespace on the root element of the document if found.
Daniel Veillard686d6b62000-01-03 11:08:02 +0000199 * Returns NULL this functionnality had been removed
Daniel Veillard260a68f1998-08-13 03:39:55 +0000200 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000201xmlNsPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000202xmlNewGlobalNs(xmlDocPtr doc, const xmlChar *href, const xmlChar *prefix) {
Daniel Veillard0142b842000-01-14 14:45:24 +0000203 xmlNodePtr root;
204
205 xmlNsPtr cur;
206
207 root = xmlDocGetRootElement(doc);
208 if (root != NULL)
209 return(xmlNewNs(root, href, prefix));
210
211 /*
212 * if there is no root element yet, create an old Namespace type
213 * and it will be moved to the root at save time.
214 */
215 cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
216 if (cur == NULL) {
217 fprintf(stderr, "xmlNewGlobalNs : malloc failed\n");
218 return(NULL);
219 }
Daniel Veillardcf461992000-03-14 18:30:20 +0000220 memset(cur, 0, sizeof(xmlNs));
Daniel Veillard0142b842000-01-14 14:45:24 +0000221 cur->type = XML_GLOBAL_NAMESPACE;
Daniel Veillardcf461992000-03-14 18:30:20 +0000222
Daniel Veillard0142b842000-01-14 14:45:24 +0000223 if (href != NULL)
224 cur->href = xmlStrdup(href);
Daniel Veillard0142b842000-01-14 14:45:24 +0000225 if (prefix != NULL)
226 cur->prefix = xmlStrdup(prefix);
Daniel Veillard0142b842000-01-14 14:45:24 +0000227
228 /*
229 * Add it at the end to preserve parsing order ...
230 */
Daniel Veillard0142b842000-01-14 14:45:24 +0000231 if (doc != NULL) {
232 if (doc->oldNs == NULL) {
233 doc->oldNs = cur;
234 } else {
235 xmlNsPtr prev = doc->oldNs;
236
237 while (prev->next != NULL) prev = prev->next;
238 prev->next = cur;
239 }
240 }
241
242 return(NULL);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000243}
244
Daniel Veillard97b58771998-10-20 06:14:16 +0000245/**
246 * xmlSetNs:
247 * @node: a node in the document
248 * @ns: a namespace pointer
249 *
250 * Associate a namespace to a node, a posteriori.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000251 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000252void
253xmlSetNs(xmlNodePtr node, xmlNsPtr ns) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000254 if (node == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000255#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +0000256 fprintf(stderr, "xmlSetNs: node == NULL\n");
Daniel Veillardcf461992000-03-14 18:30:20 +0000257#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000258 return;
259 }
260 node->ns = ns;
261}
262
Daniel Veillard97b58771998-10-20 06:14:16 +0000263/**
264 * xmlFreeNs:
265 * @cur: the namespace pointer
266 *
267 * Free up the structures associated to a namespace
Daniel Veillard260a68f1998-08-13 03:39:55 +0000268 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000269void
270xmlFreeNs(xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000271 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000272#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +0000273 fprintf(stderr, "xmlFreeNs : ns == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000274#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000275 return;
276 }
Daniel Veillard6454aec1999-09-02 22:04:43 +0000277 if (cur->href != NULL) xmlFree((char *) cur->href);
278 if (cur->prefix != NULL) xmlFree((char *) cur->prefix);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000279 memset(cur, -1, sizeof(xmlNs));
Daniel Veillard6454aec1999-09-02 22:04:43 +0000280 xmlFree(cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000281}
282
Daniel Veillard97b58771998-10-20 06:14:16 +0000283/**
284 * xmlFreeNsList:
285 * @cur: the first namespace pointer
286 *
287 * Free up all the structures associated to the chained namespaces.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000288 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000289void
290xmlFreeNsList(xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000291 xmlNsPtr next;
292 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000293#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +0000294 fprintf(stderr, "xmlFreeNsList : ns == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000295#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000296 return;
297 }
298 while (cur != NULL) {
299 next = cur->next;
300 xmlFreeNs(cur);
301 cur = next;
302 }
303}
304
Daniel Veillard97b58771998-10-20 06:14:16 +0000305/**
306 * xmlNewDtd:
307 * @doc: the document pointer
308 * @name: the DTD name
309 * @ExternalID: the external ID
310 * @SystemID: the system ID
311 *
Daniel Veillardcf461992000-03-14 18:30:20 +0000312 * Creation of a new DTD for the external subset. To create an
313 * internal subset, use xmlCreateIntSubset().
314 *
Daniel Veillard1e346af1999-02-22 10:33:01 +0000315 * Returns a pointer to the new DTD structure
Daniel Veillard260a68f1998-08-13 03:39:55 +0000316 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000317xmlDtdPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000318xmlNewDtd(xmlDocPtr doc, const xmlChar *name,
319 const xmlChar *ExternalID, const xmlChar *SystemID) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000320 xmlDtdPtr cur;
321
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000322 if ((doc != NULL) && (doc->extSubset != NULL)) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000323#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +0000324 fprintf(stderr, "xmlNewDtd(%s): document %s already have a DTD %s\n",
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000325 /* !!! */ (char *) name, doc->name,
326 /* !!! */ (char *)doc->extSubset->name);
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000327#endif
328 return(NULL);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000329 }
330
331 /*
332 * Allocate a new DTD and fill the fields.
333 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000334 cur = (xmlDtdPtr) xmlMalloc(sizeof(xmlDtd));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000335 if (cur == NULL) {
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000336 fprintf(stderr, "xmlNewDtd : malloc failed\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +0000337 return(NULL);
338 }
Daniel Veillardcf461992000-03-14 18:30:20 +0000339 memset(cur, 0 , sizeof(xmlDtd));
340 cur->type = XML_DTD_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000341
342 if (name != NULL)
343 cur->name = xmlStrdup(name);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000344 if (ExternalID != NULL)
345 cur->ExternalID = xmlStrdup(ExternalID);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000346 if (SystemID != NULL)
347 cur->SystemID = xmlStrdup(SystemID);
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000348 if (doc != NULL)
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000349 doc->extSubset = cur;
Daniel Veillardcf461992000-03-14 18:30:20 +0000350 cur->doc = doc;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000351
352 return(cur);
353}
354
355/**
Daniel Veillardcf461992000-03-14 18:30:20 +0000356 * xmlGetIntSubset:
357 * @doc: the document pointer
358 *
359 * Get the internal subset of a document
360 * Returns a pointer to the DTD structure or NULL if not found
361 */
362
363xmlDtdPtr
364xmlGetIntSubset(xmlDocPtr doc) {
365 xmlNodePtr cur;
366
367 if (doc == NULL)
368 return(NULL);
369 cur = doc->children;
370 while (cur != NULL) {
371 if (cur->type == XML_DTD_NODE)
372 return((xmlDtdPtr) cur);
373 cur = cur->next;
374 }
375 return((xmlDtdPtr) doc->intSubset);
376}
377
378/**
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000379 * xmlCreateIntSubset:
380 * @doc: the document pointer
381 * @name: the DTD name
382 * @ExternalID: the external ID
383 * @SystemID: the system ID
384 *
Daniel Veillard1e346af1999-02-22 10:33:01 +0000385 * Create the internal subset of a document
386 * Returns a pointer to the new DTD structure
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000387 */
388xmlDtdPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000389xmlCreateIntSubset(xmlDocPtr doc, const xmlChar *name,
390 const xmlChar *ExternalID, const xmlChar *SystemID) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000391 xmlDtdPtr cur;
392
Daniel Veillardcf461992000-03-14 18:30:20 +0000393 if ((doc != NULL) && (xmlGetIntSubset(doc) != NULL)) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000394#ifdef DEBUG_TREE
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000395 fprintf(stderr,
396 "xmlCreateIntSubset(): document %s already have an internal subset\n",
397 doc->name);
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000398#endif
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000399 return(NULL);
400 }
401
402 /*
403 * Allocate a new DTD and fill the fields.
404 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000405 cur = (xmlDtdPtr) xmlMalloc(sizeof(xmlDtd));
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000406 if (cur == NULL) {
407 fprintf(stderr, "xmlNewDtd : malloc failed\n");
408 return(NULL);
409 }
Daniel Veillardcf461992000-03-14 18:30:20 +0000410 memset(cur, 0, sizeof(xmlDtd));
411 cur->type = XML_DTD_NODE;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000412
413 if (name != NULL)
414 cur->name = xmlStrdup(name);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000415 if (ExternalID != NULL)
416 cur->ExternalID = xmlStrdup(ExternalID);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000417 if (SystemID != NULL)
418 cur->SystemID = xmlStrdup(SystemID);
Daniel Veillardcf461992000-03-14 18:30:20 +0000419 if (doc != NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000420 doc->intSubset = cur;
Daniel Veillardcf461992000-03-14 18:30:20 +0000421 cur->parent = doc;
422 cur->doc = doc;
423 if (doc->children == NULL) {
424 doc->children = (xmlNodePtr) cur;
425 doc->last = (xmlNodePtr) cur;
426 } else {
427 xmlNodePtr prev;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000428
Daniel Veillardb8f25c92000-08-19 19:52:36 +0000429 if (doc->type == XML_HTML_DOCUMENT_NODE) {
430 prev = doc->children;
431 prev->prev = (xmlNodePtr) cur;
432 cur->next = prev;
433 doc->children = (xmlNodePtr) cur;
434 } else {
435 prev = doc->last;
436 prev->next = (xmlNodePtr) cur;
437 cur->prev = prev;
438 doc->last = (xmlNodePtr) cur;
439 }
Daniel Veillardcf461992000-03-14 18:30:20 +0000440 }
441 }
Daniel Veillard260a68f1998-08-13 03:39:55 +0000442 return(cur);
443}
444
Daniel Veillard97b58771998-10-20 06:14:16 +0000445/**
446 * xmlFreeDtd:
447 * @cur: the DTD structure to free up
448 *
449 * Free a DTD structure.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000450 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000451void
452xmlFreeDtd(xmlDtdPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000453 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000454#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +0000455 fprintf(stderr, "xmlFreeDtd : DTD == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000456#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000457 return;
458 }
Daniel Veillardcf461992000-03-14 18:30:20 +0000459 if (cur->children != NULL) {
460 xmlNodePtr next, c = cur->children;
461
462 /*
463 * Cleanup all the DTD comments they are not in the Dtd
464 * indexes.
465 */
466 while (c != NULL) {
467 next = c->next;
468 if (c->type == XML_COMMENT_NODE) {
469 xmlUnlinkNode(c);
470 xmlFreeNode(c);
471 }
472 c = next;
473 }
474 }
Daniel Veillard6454aec1999-09-02 22:04:43 +0000475 if (cur->name != NULL) xmlFree((char *) cur->name);
476 if (cur->SystemID != NULL) xmlFree((char *) cur->SystemID);
477 if (cur->ExternalID != NULL) xmlFree((char *) cur->ExternalID);
Daniel Veillardcf461992000-03-14 18:30:20 +0000478 /* TODO !!! */
Daniel Veillard1e346af1999-02-22 10:33:01 +0000479 if (cur->notations != NULL)
480 xmlFreeNotationTable((xmlNotationTablePtr) cur->notations);
Daniel Veillardcf461992000-03-14 18:30:20 +0000481
Daniel Veillard260a68f1998-08-13 03:39:55 +0000482 if (cur->elements != NULL)
Daniel Veillard3b9def11999-01-31 22:15:06 +0000483 xmlFreeElementTable((xmlElementTablePtr) cur->elements);
Daniel Veillard1e346af1999-02-22 10:33:01 +0000484 if (cur->attributes != NULL)
485 xmlFreeAttributeTable((xmlAttributeTablePtr) cur->attributes);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000486 if (cur->entities != NULL)
487 xmlFreeEntitiesTable((xmlEntitiesTablePtr) cur->entities);
Daniel Veillardcf461992000-03-14 18:30:20 +0000488
Daniel Veillard260a68f1998-08-13 03:39:55 +0000489 memset(cur, -1, sizeof(xmlDtd));
Daniel Veillard6454aec1999-09-02 22:04:43 +0000490 xmlFree(cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000491}
492
Daniel Veillard97b58771998-10-20 06:14:16 +0000493/**
494 * xmlNewDoc:
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000495 * @version: xmlChar string giving the version of XML "1.0"
Daniel Veillard97b58771998-10-20 06:14:16 +0000496 *
Daniel Veillard1e346af1999-02-22 10:33:01 +0000497 * Returns a new document
Daniel Veillard260a68f1998-08-13 03:39:55 +0000498 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000499xmlDocPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000500xmlNewDoc(const xmlChar *version) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000501 xmlDocPtr cur;
502
503 if (version == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000504#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +0000505 fprintf(stderr, "xmlNewDoc : version == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000506#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000507 return(NULL);
508 }
509
510 /*
511 * Allocate a new document and fill the fields.
512 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000513 cur = (xmlDocPtr) xmlMalloc(sizeof(xmlDoc));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000514 if (cur == NULL) {
515 fprintf(stderr, "xmlNewDoc : malloc failed\n");
516 return(NULL);
517 }
Daniel Veillardcf461992000-03-14 18:30:20 +0000518 memset(cur, 0, sizeof(xmlDoc));
Daniel Veillard33942841998-10-18 19:12:41 +0000519 cur->type = XML_DOCUMENT_NODE;
Daniel Veillardcf461992000-03-14 18:30:20 +0000520
Daniel Veillard260a68f1998-08-13 03:39:55 +0000521 cur->version = xmlStrdup(version);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000522 cur->standalone = -1;
Daniel Veillard11a48ec1999-11-23 10:40:46 +0000523 cur->compression = -1; /* not initialized */
Daniel Veillardcf461992000-03-14 18:30:20 +0000524 cur->doc = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000525 return(cur);
526}
527
Daniel Veillard97b58771998-10-20 06:14:16 +0000528/**
529 * xmlFreeDoc:
530 * @cur: pointer to the document
531 * @:
532 *
533 * Free up all the structures used by a document, tree included.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000534 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000535void
536xmlFreeDoc(xmlDocPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000537 if (cur == NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000538#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +0000539 fprintf(stderr, "xmlFreeDoc : document == NULL\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000540#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000541 return;
542 }
Daniel Veillard6454aec1999-09-02 22:04:43 +0000543 if (cur->version != NULL) xmlFree((char *) cur->version);
544 if (cur->name != NULL) xmlFree((char *) cur->name);
545 if (cur->encoding != NULL) xmlFree((char *) cur->encoding);
Daniel Veillardcf461992000-03-14 18:30:20 +0000546 if (cur->children != NULL) xmlFreeNodeList(cur->children);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000547 if (cur->intSubset != NULL) xmlFreeDtd(cur->intSubset);
548 if (cur->extSubset != NULL) xmlFreeDtd(cur->extSubset);
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000549 if (cur->oldNs != NULL) xmlFreeNsList(cur->oldNs);
Daniel Veillardb96e6431999-08-29 21:02:19 +0000550 if (cur->ids != NULL) xmlFreeIDTable((xmlIDTablePtr) cur->ids);
Daniel Veillardc08a2c61999-09-08 21:35:25 +0000551 if (cur->refs != NULL) xmlFreeRefTable((xmlRefTablePtr) cur->refs);
Daniel Veillardcf461992000-03-14 18:30:20 +0000552 if (cur->URL != NULL) xmlFree((char *) cur->URL);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000553 memset(cur, -1, sizeof(xmlDoc));
Daniel Veillard6454aec1999-09-02 22:04:43 +0000554 xmlFree(cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000555}
556
Daniel Veillard97b58771998-10-20 06:14:16 +0000557/**
Daniel Veillard16253641998-10-28 22:58:05 +0000558 * xmlStringLenGetNodeList:
559 * @doc: the document
560 * @value: the value of the text
Daniel Veillard1e346af1999-02-22 10:33:01 +0000561 * @len: the length of the string value
Daniel Veillard16253641998-10-28 22:58:05 +0000562 *
563 * Parse the value string and build the node list associated. Should
564 * produce a flat tree with only TEXTs and ENTITY_REFs.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000565 * Returns a pointer to the first child
Daniel Veillard16253641998-10-28 22:58:05 +0000566 */
567xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000568xmlStringLenGetNodeList(xmlDocPtr doc, const xmlChar *value, int len) {
Daniel Veillard16253641998-10-28 22:58:05 +0000569 xmlNodePtr ret = NULL, last = NULL;
570 xmlNodePtr node;
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000571 xmlChar *val;
572 const xmlChar *cur = value;
573 const xmlChar *q;
Daniel Veillard25940b71998-10-29 05:51:30 +0000574 xmlEntityPtr ent;
Daniel Veillard16253641998-10-28 22:58:05 +0000575
576 if (value == NULL) return(NULL);
577
578 q = cur;
579 while ((*cur != 0) && (cur - value < len)) {
580 if (*cur == '&') {
Daniel Veillard25940b71998-10-29 05:51:30 +0000581 /*
582 * Save the current text.
583 */
Daniel Veillard16253641998-10-28 22:58:05 +0000584 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000585 if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
586 xmlNodeAddContentLen(last, q, cur - q);
587 } else {
588 node = xmlNewDocTextLen(doc, q, cur - q);
589 if (node == NULL) return(ret);
590 if (last == NULL)
591 last = ret = node;
592 else {
593 last->next = node;
594 node->prev = last;
595 last = node;
596 }
Daniel Veillard16253641998-10-28 22:58:05 +0000597 }
598 }
Daniel Veillard25940b71998-10-29 05:51:30 +0000599 /*
600 * Read the entity string
601 */
Daniel Veillard16253641998-10-28 22:58:05 +0000602 cur++;
603 q = cur;
604 while ((*cur != 0) && (cur - value < len) && (*cur != ';')) cur++;
605 if ((*cur == 0) || (cur - value >= len)) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000606#ifdef DEBUG_TREE
Daniel Veillard16253641998-10-28 22:58:05 +0000607 fprintf(stderr,
Daniel Veillard011b63c1999-06-02 17:44:04 +0000608 "xmlStringLenGetNodeList: unterminated entity %30s\n", q);
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000609#endif
Daniel Veillard16253641998-10-28 22:58:05 +0000610 return(ret);
611 }
612 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000613 /*
614 * Predefined entities don't generate nodes
615 */
Daniel Veillard16253641998-10-28 22:58:05 +0000616 val = xmlStrndup(q, cur - q);
Daniel Veillard25940b71998-10-29 05:51:30 +0000617 ent = xmlGetDocEntity(doc, val);
618 if ((ent != NULL) &&
Daniel Veillardcf461992000-03-14 18:30:20 +0000619 (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000620 if (last == NULL) {
621 node = xmlNewDocText(doc, ent->content);
622 last = ret = node;
623 } else
624 xmlNodeAddContent(last, ent->content);
625
626 } else {
627 /*
628 * Create a new REFERENCE_REF node
629 */
630 node = xmlNewReference(doc, val);
Daniel Veillard242590e1998-11-13 18:04:35 +0000631 if (node == NULL) {
Daniel Veillard6454aec1999-09-02 22:04:43 +0000632 if (val != NULL) xmlFree(val);
Daniel Veillard242590e1998-11-13 18:04:35 +0000633 return(ret);
634 }
Daniel Veillard25940b71998-10-29 05:51:30 +0000635 if (last == NULL)
636 last = ret = node;
637 else {
638 last->next = node;
639 node->prev = last;
640 last = node;
641 }
Daniel Veillard16253641998-10-28 22:58:05 +0000642 }
Daniel Veillard6454aec1999-09-02 22:04:43 +0000643 xmlFree(val);
Daniel Veillard16253641998-10-28 22:58:05 +0000644 }
645 cur++;
646 q = cur;
647 } else
648 cur++;
649 }
650 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000651 /*
652 * Handle the last piece of text.
653 */
654 if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
655 xmlNodeAddContentLen(last, q, cur - q);
656 } else {
657 node = xmlNewDocTextLen(doc, q, cur - q);
658 if (node == NULL) return(ret);
659 if (last == NULL)
660 last = ret = node;
661 else {
662 last->next = node;
663 node->prev = last;
664 last = node;
665 }
Daniel Veillard16253641998-10-28 22:58:05 +0000666 }
667 }
668 return(ret);
669}
670
671/**
Daniel Veillardccb09631998-10-27 06:21:04 +0000672 * xmlStringGetNodeList:
673 * @doc: the document
674 * @value: the value of the attribute
675 *
676 * Parse the value string and build the node list associated. Should
677 * produce a flat tree with only TEXTs and ENTITY_REFs.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000678 * Returns a pointer to the first child
Daniel Veillardccb09631998-10-27 06:21:04 +0000679 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000680xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000681xmlStringGetNodeList(xmlDocPtr doc, const xmlChar *value) {
Daniel Veillardccb09631998-10-27 06:21:04 +0000682 xmlNodePtr ret = NULL, last = NULL;
683 xmlNodePtr node;
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000684 xmlChar *val;
685 const xmlChar *cur = value;
686 const xmlChar *q;
Daniel Veillard25940b71998-10-29 05:51:30 +0000687 xmlEntityPtr ent;
Daniel Veillardccb09631998-10-27 06:21:04 +0000688
689 if (value == NULL) return(NULL);
690
691 q = cur;
692 while (*cur != 0) {
693 if (*cur == '&') {
Daniel Veillard25940b71998-10-29 05:51:30 +0000694 /*
695 * Save the current text.
696 */
Daniel Veillardccb09631998-10-27 06:21:04 +0000697 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000698 if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
699 xmlNodeAddContentLen(last, q, cur - q);
700 } else {
701 node = xmlNewDocTextLen(doc, q, cur - q);
702 if (node == NULL) return(ret);
703 if (last == NULL)
704 last = ret = node;
705 else {
706 last->next = node;
707 node->prev = last;
708 last = node;
709 }
Daniel Veillardccb09631998-10-27 06:21:04 +0000710 }
711 }
Daniel Veillard25940b71998-10-29 05:51:30 +0000712 /*
713 * Read the entity string
714 */
Daniel Veillardccb09631998-10-27 06:21:04 +0000715 cur++;
716 q = cur;
717 while ((*cur != 0) && (*cur != ';')) cur++;
718 if (*cur == 0) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000719#ifdef DEBUG_TREE
Daniel Veillardccb09631998-10-27 06:21:04 +0000720 fprintf(stderr,
721 "xmlStringGetNodeList: unterminated entity %30s\n", q);
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000722#endif
Daniel Veillardccb09631998-10-27 06:21:04 +0000723 return(ret);
724 }
725 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000726 /*
727 * Predefined entities don't generate nodes
728 */
Daniel Veillardccb09631998-10-27 06:21:04 +0000729 val = xmlStrndup(q, cur - q);
Daniel Veillard25940b71998-10-29 05:51:30 +0000730 ent = xmlGetDocEntity(doc, val);
731 if ((ent != NULL) &&
Daniel Veillardcf461992000-03-14 18:30:20 +0000732 (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000733 if (last == NULL) {
734 node = xmlNewDocText(doc, ent->content);
735 last = ret = node;
736 } else
737 xmlNodeAddContent(last, ent->content);
738
739 } else {
740 /*
741 * Create a new REFERENCE_REF node
742 */
Daniel Veillard25940b71998-10-29 05:51:30 +0000743 node = xmlNewReference(doc, val);
Daniel Veillard242590e1998-11-13 18:04:35 +0000744 if (node == NULL) {
Daniel Veillard6454aec1999-09-02 22:04:43 +0000745 if (val != NULL) xmlFree(val);
Daniel Veillard242590e1998-11-13 18:04:35 +0000746 return(ret);
747 }
Daniel Veillard25940b71998-10-29 05:51:30 +0000748 if (last == NULL)
749 last = ret = node;
750 else {
751 last->next = node;
752 node->prev = last;
753 last = node;
754 }
Daniel Veillardccb09631998-10-27 06:21:04 +0000755 }
Daniel Veillard6454aec1999-09-02 22:04:43 +0000756 xmlFree(val);
Daniel Veillardccb09631998-10-27 06:21:04 +0000757 }
758 cur++;
759 q = cur;
760 } else
761 cur++;
762 }
763 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000764 /*
765 * Handle the last piece of text.
766 */
767 if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
768 xmlNodeAddContentLen(last, q, cur - q);
769 } else {
770 node = xmlNewDocTextLen(doc, q, cur - q);
771 if (node == NULL) return(ret);
772 if (last == NULL)
773 last = ret = node;
774 else {
775 last->next = node;
776 node->prev = last;
777 last = node;
778 }
Daniel Veillardccb09631998-10-27 06:21:04 +0000779 }
780 }
781 return(ret);
782}
783
784/**
785 * xmlNodeListGetString:
786 * @doc: the document
787 * @list: a Node list
788 * @inLine: should we replace entity contents or show their external form
789 *
790 * Returns the string equivalent to the text contained in the Node list
791 * made of TEXTs and ENTITY_REFs
Daniel Veillard1e346af1999-02-22 10:33:01 +0000792 * Returns a pointer to the string copy, the calller must free it.
Daniel Veillardccb09631998-10-27 06:21:04 +0000793 */
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000794xmlChar *
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000795xmlNodeListGetString(xmlDocPtr doc, xmlNodePtr list, int inLine) {
Daniel Veillardccb09631998-10-27 06:21:04 +0000796 xmlNodePtr node = list;
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000797 xmlChar *ret = NULL;
Daniel Veillardccb09631998-10-27 06:21:04 +0000798 xmlEntityPtr ent;
799
800 if (list == NULL) return(NULL);
801
802 while (node != NULL) {
Daniel Veillard87b95392000-08-12 21:12:04 +0000803 if ((node->type == XML_TEXT_NODE) ||
804 (node->type == XML_CDATA_SECTION_NODE)) {
Daniel Veillard71b656e2000-01-05 14:46:17 +0000805 if (inLine) {
Daniel Veillardf5c2c871999-12-01 09:51:45 +0000806#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardccb09631998-10-27 06:21:04 +0000807 ret = xmlStrcat(ret, node->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +0000808#else
809 ret = xmlStrcat(ret, xmlBufferContent(node->content));
810#endif
811 } else {
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000812 xmlChar *buffer;
Daniel Veillard14fff061999-06-22 21:49:07 +0000813
Daniel Veillardf5c2c871999-12-01 09:51:45 +0000814#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard14fff061999-06-22 21:49:07 +0000815 buffer = xmlEncodeEntitiesReentrant(doc, node->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +0000816#else
817 buffer = xmlEncodeEntitiesReentrant(doc,
818 xmlBufferContent(node->content));
819#endif
Daniel Veillard14fff061999-06-22 21:49:07 +0000820 if (buffer != NULL) {
821 ret = xmlStrcat(ret, buffer);
Daniel Veillard6454aec1999-09-02 22:04:43 +0000822 xmlFree(buffer);
Daniel Veillard14fff061999-06-22 21:49:07 +0000823 }
824 }
Daniel Veillardccb09631998-10-27 06:21:04 +0000825 } else if (node->type == XML_ENTITY_REF_NODE) {
826 if (inLine) {
827 ent = xmlGetDocEntity(doc, node->name);
828 if (ent != NULL)
829 ret = xmlStrcat(ret, ent->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +0000830 else {
831#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardccb09631998-10-27 06:21:04 +0000832 ret = xmlStrcat(ret, node->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +0000833#else
834 ret = xmlStrcat(ret, xmlBufferContent(node->content));
835#endif
836 }
Daniel Veillardccb09631998-10-27 06:21:04 +0000837 } else {
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000838 xmlChar buf[2];
Daniel Veillardccb09631998-10-27 06:21:04 +0000839 buf[0] = '&'; buf[1] = 0;
840 ret = xmlStrncat(ret, buf, 1);
841 ret = xmlStrcat(ret, node->name);
842 buf[0] = ';'; buf[1] = 0;
843 ret = xmlStrncat(ret, buf, 1);
844 }
845 }
846#if 0
847 else {
848 fprintf(stderr, "xmlGetNodeListString : invalide node type %d\n",
849 node->type);
850 }
851#endif
852 node = node->next;
853 }
854 return(ret);
855}
856
857/**
Daniel Veillardbe803962000-06-28 23:40:59 +0000858 * xmlNodeListGetRawString:
859 * @doc: the document
860 * @list: a Node list
861 * @inLine: should we replace entity contents or show their external form
862 *
863 * Returns the string equivalent to the text contained in the Node list
864 * made of TEXTs and ENTITY_REFs, contrary to xmlNodeListGetString()
865 * this function doesn't do any character encoding handling.
866 *
867 * Returns a pointer to the string copy, the calller must free it.
868 */
869xmlChar *
870xmlNodeListGetRawString(xmlDocPtr doc, xmlNodePtr list, int inLine) {
871 xmlNodePtr node = list;
872 xmlChar *ret = NULL;
873 xmlEntityPtr ent;
874
875 if (list == NULL) return(NULL);
876
877 while (node != NULL) {
878 if (node->type == XML_TEXT_NODE) {
879 if (inLine) {
880#ifndef XML_USE_BUFFER_CONTENT
881 ret = xmlStrcat(ret, node->content);
882#else
883 ret = xmlStrcat(ret, xmlBufferContent(node->content));
884#endif
885 } else {
886 xmlChar *buffer;
887
888#ifndef XML_USE_BUFFER_CONTENT
889 buffer = xmlEncodeSpecialChars(doc, node->content);
890#else
891 buffer = xmlEncodeSpecialChars(doc,
892 xmlBufferContent(node->content));
893#endif
894 if (buffer != NULL) {
895 ret = xmlStrcat(ret, buffer);
896 xmlFree(buffer);
897 }
898 }
899 } else if (node->type == XML_ENTITY_REF_NODE) {
900 if (inLine) {
901 ent = xmlGetDocEntity(doc, node->name);
902 if (ent != NULL)
903 ret = xmlStrcat(ret, ent->content);
904 else {
905#ifndef XML_USE_BUFFER_CONTENT
906 ret = xmlStrcat(ret, node->content);
907#else
908 ret = xmlStrcat(ret, xmlBufferContent(node->content));
909#endif
910 }
911 } else {
912 xmlChar buf[2];
913 buf[0] = '&'; buf[1] = 0;
914 ret = xmlStrncat(ret, buf, 1);
915 ret = xmlStrcat(ret, node->name);
916 buf[0] = ';'; buf[1] = 0;
917 ret = xmlStrncat(ret, buf, 1);
918 }
919 }
920#if 0
921 else {
922 fprintf(stderr, "xmlGetNodeListString : invalide node type %d\n",
923 node->type);
924 }
925#endif
926 node = node->next;
927 }
928 return(ret);
929}
930
931/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000932 * xmlNewProp:
933 * @node: the holding node
934 * @name: the name of the attribute
935 * @value: the value of the attribute
936 *
937 * Create a new property carried by a node.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000938 * Returns a pointer to the attribute
Daniel Veillard260a68f1998-08-13 03:39:55 +0000939 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000940xmlAttrPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000941xmlNewProp(xmlNodePtr node, const xmlChar *name, const xmlChar *value) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000942 xmlAttrPtr cur;
943
944 if (name == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000945#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +0000946 fprintf(stderr, "xmlNewProp : name == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000947#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000948 return(NULL);
949 }
950
951 /*
952 * Allocate a new property and fill the fields.
953 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000954 cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000955 if (cur == NULL) {
956 fprintf(stderr, "xmlNewProp : malloc failed\n");
957 return(NULL);
958 }
Daniel Veillardcf461992000-03-14 18:30:20 +0000959 memset(cur, 0, sizeof(xmlAttr));
Daniel Veillard33942841998-10-18 19:12:41 +0000960 cur->type = XML_ATTRIBUTE_NODE;
Daniel Veillardcf461992000-03-14 18:30:20 +0000961
962 cur->parent = node;
Daniel Veillardb96e6431999-08-29 21:02:19 +0000963 cur->name = xmlStrdup(name);
Daniel Veillard51e3b151999-11-12 17:02:31 +0000964 if (value != NULL) {
965 xmlChar *buffer;
Daniel Veillardcf461992000-03-14 18:30:20 +0000966 xmlNodePtr tmp;
967
Daniel Veillard51e3b151999-11-12 17:02:31 +0000968 buffer = xmlEncodeEntitiesReentrant(node->doc, value);
Daniel Veillardcf461992000-03-14 18:30:20 +0000969 cur->children = xmlStringGetNodeList(node->doc, buffer);
970 tmp = cur->children;
971 while (tmp != NULL) {
972 tmp->parent = (xmlNodePtr) cur;
973 if (tmp->next == NULL)
974 cur->last = tmp;
975 tmp = tmp->next;
976 }
Daniel Veillard51e3b151999-11-12 17:02:31 +0000977 xmlFree(buffer);
978 }
Daniel Veillardb96e6431999-08-29 21:02:19 +0000979
980 /*
981 * Add it at the end to preserve parsing order ...
982 */
Daniel Veillardb96e6431999-08-29 21:02:19 +0000983 if (node != NULL) {
984 if (node->properties == NULL) {
985 node->properties = cur;
986 } else {
987 xmlAttrPtr prev = node->properties;
988
989 while (prev->next != NULL) prev = prev->next;
990 prev->next = cur;
Daniel Veillardcf461992000-03-14 18:30:20 +0000991 cur->prev = prev;
Daniel Veillardb96e6431999-08-29 21:02:19 +0000992 }
993 }
994 return(cur);
995}
996
997/**
998 * xmlNewNsProp:
999 * @node: the holding node
1000 * @ns: the namespace
1001 * @name: the name of the attribute
1002 * @value: the value of the attribute
1003 *
1004 * Create a new property tagged with a namespace and carried by a node.
1005 * Returns a pointer to the attribute
1006 */
1007xmlAttrPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001008xmlNewNsProp(xmlNodePtr node, xmlNsPtr ns, const xmlChar *name,
1009 const xmlChar *value) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00001010 xmlAttrPtr cur;
1011
1012 if (name == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001013#ifdef DEBUG_TREE
Daniel Veillardb96e6431999-08-29 21:02:19 +00001014 fprintf(stderr, "xmlNewProp : name == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001015#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +00001016 return(NULL);
1017 }
1018
1019 /*
1020 * Allocate a new property and fill the fields.
1021 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001022 cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr));
Daniel Veillardb96e6431999-08-29 21:02:19 +00001023 if (cur == NULL) {
1024 fprintf(stderr, "xmlNewProp : malloc failed\n");
1025 return(NULL);
1026 }
Daniel Veillardcf461992000-03-14 18:30:20 +00001027 memset(cur, 0, sizeof(xmlAttr));
Daniel Veillardb96e6431999-08-29 21:02:19 +00001028 cur->type = XML_ATTRIBUTE_NODE;
Daniel Veillardcf461992000-03-14 18:30:20 +00001029
1030 cur->parent = node;
1031 if (node != NULL)
1032 cur->doc = node->doc;
Daniel Veillardb96e6431999-08-29 21:02:19 +00001033 cur->ns = ns;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001034 cur->name = xmlStrdup(name);
Daniel Veillardcf461992000-03-14 18:30:20 +00001035 if (value != NULL) {
1036 xmlChar *buffer;
1037 xmlNodePtr tmp;
1038
1039 buffer = xmlEncodeEntitiesReentrant(node->doc, value);
1040 cur->children = xmlStringGetNodeList(node->doc, buffer);
1041 tmp = cur->children;
1042 while (tmp != NULL) {
1043 tmp->parent = (xmlNodePtr) cur;
1044 if (tmp->next == NULL)
1045 cur->last = tmp;
1046 tmp = tmp->next;
1047 }
1048 xmlFree(buffer);
1049 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00001050
1051 /*
1052 * Add it at the end to preserve parsing order ...
1053 */
Daniel Veillard260a68f1998-08-13 03:39:55 +00001054 if (node != NULL) {
1055 if (node->properties == NULL) {
1056 node->properties = cur;
1057 } else {
1058 xmlAttrPtr prev = node->properties;
1059
1060 while (prev->next != NULL) prev = prev->next;
1061 prev->next = cur;
Daniel Veillardcf461992000-03-14 18:30:20 +00001062 cur->prev = prev;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001063 }
1064 }
1065 return(cur);
1066}
1067
Daniel Veillard97b58771998-10-20 06:14:16 +00001068/**
Daniel Veillardccb09631998-10-27 06:21:04 +00001069 * xmlNewDocProp:
1070 * @doc: the document
1071 * @name: the name of the attribute
1072 * @value: the value of the attribute
1073 *
1074 * Create a new property carried by a document.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001075 * Returns a pointer to the attribute
Daniel Veillardccb09631998-10-27 06:21:04 +00001076 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001077xmlAttrPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001078xmlNewDocProp(xmlDocPtr doc, const xmlChar *name, const xmlChar *value) {
Daniel Veillardccb09631998-10-27 06:21:04 +00001079 xmlAttrPtr cur;
1080
1081 if (name == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001082#ifdef DEBUG_TREE
Daniel Veillardccb09631998-10-27 06:21:04 +00001083 fprintf(stderr, "xmlNewProp : name == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001084#endif
Daniel Veillardccb09631998-10-27 06:21:04 +00001085 return(NULL);
1086 }
1087
1088 /*
1089 * Allocate a new property and fill the fields.
1090 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001091 cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr));
Daniel Veillardccb09631998-10-27 06:21:04 +00001092 if (cur == NULL) {
1093 fprintf(stderr, "xmlNewProp : malloc failed\n");
1094 return(NULL);
1095 }
Daniel Veillardcf461992000-03-14 18:30:20 +00001096 memset(cur, 0, sizeof(xmlAttr));
Daniel Veillardccb09631998-10-27 06:21:04 +00001097 cur->type = XML_ATTRIBUTE_NODE;
Daniel Veillardccb09631998-10-27 06:21:04 +00001098
Daniel Veillardcf461992000-03-14 18:30:20 +00001099 cur->name = xmlStrdup(name);
1100 cur->doc = doc;
1101 if (value != NULL)
1102 cur->children = xmlStringGetNodeList(doc, value);
Daniel Veillardccb09631998-10-27 06:21:04 +00001103 return(cur);
1104}
1105
1106/**
Daniel Veillard97b58771998-10-20 06:14:16 +00001107 * xmlFreePropList:
1108 * @cur: the first property in the list
1109 *
Daniel Veillardcf461992000-03-14 18:30:20 +00001110 * Free a property and all its siblings, all the children are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001111 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001112void
1113xmlFreePropList(xmlAttrPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001114 xmlAttrPtr next;
1115 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001116#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00001117 fprintf(stderr, "xmlFreePropList : property == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001118#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001119 return;
1120 }
1121 while (cur != NULL) {
1122 next = cur->next;
1123 xmlFreeProp(cur);
1124 cur = next;
1125 }
1126}
1127
Daniel Veillard97b58771998-10-20 06:14:16 +00001128/**
1129 * xmlFreeProp:
Daniel Veillard686d6b62000-01-03 11:08:02 +00001130 * @cur: an attribute
Daniel Veillard97b58771998-10-20 06:14:16 +00001131 *
Daniel Veillard686d6b62000-01-03 11:08:02 +00001132 * Free one attribute, all the content is freed too
Daniel Veillard260a68f1998-08-13 03:39:55 +00001133 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001134void
1135xmlFreeProp(xmlAttrPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001136 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001137#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00001138 fprintf(stderr, "xmlFreeProp : property == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001139#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001140 return;
1141 }
Daniel Veillard71b656e2000-01-05 14:46:17 +00001142 /* Check for ID removal -> leading to invalid references ! */
Daniel Veillardcf461992000-03-14 18:30:20 +00001143 if ((cur->parent != NULL) &&
1144 (xmlIsID(cur->parent->doc, cur->parent, cur)))
1145 xmlRemoveID(cur->parent->doc, cur);
Daniel Veillard6454aec1999-09-02 22:04:43 +00001146 if (cur->name != NULL) xmlFree((char *) cur->name);
Daniel Veillardcf461992000-03-14 18:30:20 +00001147 if (cur->children != NULL) xmlFreeNodeList(cur->children);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001148 memset(cur, -1, sizeof(xmlAttr));
Daniel Veillard6454aec1999-09-02 22:04:43 +00001149 xmlFree(cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001150}
1151
Daniel Veillard97b58771998-10-20 06:14:16 +00001152/**
Daniel Veillard686d6b62000-01-03 11:08:02 +00001153 * xmlRemoveProp:
1154 * @cur: an attribute
1155 *
1156 * Unlink and free one attribute, all the content is freed too
1157 * Note this doesn't work for namespace definition attributes
1158 *
1159 * Returns 0 if success and -1 in case of error.
1160 */
1161int
1162xmlRemoveProp(xmlAttrPtr cur) {
1163 xmlAttrPtr tmp;
1164 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001165#ifdef DEBUG_TREE
Daniel Veillard686d6b62000-01-03 11:08:02 +00001166 fprintf(stderr, "xmlRemoveProp : cur == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001167#endif
Daniel Veillard686d6b62000-01-03 11:08:02 +00001168 return(-1);
1169 }
Daniel Veillardcf461992000-03-14 18:30:20 +00001170 if (cur->parent == NULL) {
1171#ifdef DEBUG_TREE
1172 fprintf(stderr, "xmlRemoveProp : cur->parent == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001173#endif
Daniel Veillard686d6b62000-01-03 11:08:02 +00001174 return(-1);
1175 }
Daniel Veillardcf461992000-03-14 18:30:20 +00001176 tmp = cur->parent->properties;
Daniel Veillard686d6b62000-01-03 11:08:02 +00001177 if (tmp == cur) {
Daniel Veillardcf461992000-03-14 18:30:20 +00001178 cur->parent->properties = cur->next;
Daniel Veillard686d6b62000-01-03 11:08:02 +00001179 xmlFreeProp(cur);
1180 return(0);
1181 }
1182 while (tmp != NULL) {
1183 if (tmp->next == cur) {
1184 tmp->next = cur->next;
Daniel Veillardcf461992000-03-14 18:30:20 +00001185 if (tmp->next != NULL)
1186 tmp->next->prev = tmp;
Daniel Veillard686d6b62000-01-03 11:08:02 +00001187 xmlFreeProp(cur);
1188 return(0);
1189 }
1190 tmp = tmp->next;
1191 }
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001192#ifdef DEBUG_TREE
Daniel Veillard686d6b62000-01-03 11:08:02 +00001193 fprintf(stderr, "xmlRemoveProp : attribute not owned by its node\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001194#endif
Daniel Veillard686d6b62000-01-03 11:08:02 +00001195 return(-1);
1196}
1197
1198/**
Daniel Veillardb96e6431999-08-29 21:02:19 +00001199 * xmlNewPI:
1200 * @name: the processing instruction name
1201 * @content: the PI content
1202 *
1203 * Creation of a processing instruction element.
1204 * Returns a pointer to the new node object.
1205 */
1206xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001207xmlNewPI(const xmlChar *name, const xmlChar *content) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00001208 xmlNodePtr cur;
1209
1210 if (name == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001211#ifdef DEBUG_TREE
Daniel Veillardb96e6431999-08-29 21:02:19 +00001212 fprintf(stderr, "xmlNewPI : name == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001213#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +00001214 return(NULL);
1215 }
1216
1217 /*
1218 * Allocate a new node and fill the fields.
1219 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001220 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillardb96e6431999-08-29 21:02:19 +00001221 if (cur == NULL) {
1222 fprintf(stderr, "xmlNewPI : malloc failed\n");
1223 return(NULL);
1224 }
Daniel Veillardcf461992000-03-14 18:30:20 +00001225 memset(cur, 0, sizeof(xmlNode));
Daniel Veillardb96e6431999-08-29 21:02:19 +00001226 cur->type = XML_PI_NODE;
Daniel Veillardcf461992000-03-14 18:30:20 +00001227
Daniel Veillardb96e6431999-08-29 21:02:19 +00001228 cur->name = xmlStrdup(name);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001229 if (content != NULL) {
1230#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardb96e6431999-08-29 21:02:19 +00001231 cur->content = xmlStrdup(content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001232#else
1233 cur->content = xmlBufferCreateSize(0);
1234 xmlBufferSetAllocationScheme(cur->content,
1235 xmlGetBufferAllocationScheme());
1236 xmlBufferAdd(cur->content, content, -1);
1237#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00001238 }
Daniel Veillardb96e6431999-08-29 21:02:19 +00001239 return(cur);
1240}
1241
1242/**
Daniel Veillard97b58771998-10-20 06:14:16 +00001243 * xmlNewNode:
1244 * @ns: namespace if any
1245 * @name: the node name
Daniel Veillard97b58771998-10-20 06:14:16 +00001246 *
1247 * Creation of a new node element. @ns and @content are optionnal (NULL).
Daniel Veillardccb09631998-10-27 06:21:04 +00001248 * If content is non NULL, a child list containing the TEXTs and
1249 * ENTITY_REFs node will be created.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001250 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001251 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001252xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001253xmlNewNode(xmlNsPtr ns, const xmlChar *name) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001254 xmlNodePtr cur;
1255
1256 if (name == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001257#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00001258 fprintf(stderr, "xmlNewNode : name == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001259#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001260 return(NULL);
1261 }
1262
1263 /*
1264 * Allocate a new node and fill the fields.
1265 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001266 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillard260a68f1998-08-13 03:39:55 +00001267 if (cur == NULL) {
1268 fprintf(stderr, "xmlNewNode : malloc failed\n");
1269 return(NULL);
1270 }
Daniel Veillardcf461992000-03-14 18:30:20 +00001271 memset(cur, 0, sizeof(xmlNode));
Daniel Veillard33942841998-10-18 19:12:41 +00001272 cur->type = XML_ELEMENT_NODE;
Daniel Veillardcf461992000-03-14 18:30:20 +00001273
Daniel Veillard260a68f1998-08-13 03:39:55 +00001274 cur->name = xmlStrdup(name);
1275 cur->ns = ns;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001276 return(cur);
1277}
1278
Daniel Veillard97b58771998-10-20 06:14:16 +00001279/**
1280 * xmlNewDocNode:
1281 * @doc: the document
1282 * @ns: namespace if any
1283 * @name: the node name
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001284 * @content: the XML text content if any
Daniel Veillard97b58771998-10-20 06:14:16 +00001285 *
1286 * Creation of a new node element within a document. @ns and @content
1287 * are optionnal (NULL).
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001288 * NOTE: @content is supposed to be a piece of XML CDATA, so it allow entities
1289 * references, but XML special chars need to be escaped first by using
1290 * xmlEncodeEntitiesReentrant(). Use xmlNewDocRawNode() if you don't
1291 * need entities support.
1292 *
Daniel Veillard1e346af1999-02-22 10:33:01 +00001293 * Returns a pointer to the new node object.
Daniel Veillard97b58771998-10-20 06:14:16 +00001294 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001295xmlNodePtr
1296xmlNewDocNode(xmlDocPtr doc, xmlNsPtr ns,
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001297 const xmlChar *name, const xmlChar *content) {
Daniel Veillard0bef1311998-10-14 02:36:47 +00001298 xmlNodePtr cur;
1299
Daniel Veillardccb09631998-10-27 06:21:04 +00001300 cur = xmlNewNode(ns, name);
1301 if (cur != NULL) {
1302 cur->doc = doc;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001303 if (content != NULL) {
Daniel Veillardcf461992000-03-14 18:30:20 +00001304 cur->children = xmlStringGetNodeList(doc, content);
Daniel Veillard1e346af1999-02-22 10:33:01 +00001305 UPDATE_LAST_CHILD(cur)
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001306 }
Daniel Veillardccb09631998-10-27 06:21:04 +00001307 }
Daniel Veillard0bef1311998-10-14 02:36:47 +00001308 return(cur);
1309}
1310
1311
Daniel Veillard97b58771998-10-20 06:14:16 +00001312/**
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001313 * xmlNewDocRawNode:
1314 * @doc: the document
1315 * @ns: namespace if any
1316 * @name: the node name
1317 * @content: the text content if any
1318 *
1319 * Creation of a new node element within a document. @ns and @content
1320 * are optionnal (NULL).
1321 *
1322 * Returns a pointer to the new node object.
1323 */
1324xmlNodePtr
1325xmlNewDocRawNode(xmlDocPtr doc, xmlNsPtr ns,
1326 const xmlChar *name, const xmlChar *content) {
1327 xmlNodePtr cur;
1328
1329 cur = xmlNewNode(ns, name);
1330 if (cur != NULL) {
1331 cur->doc = doc;
1332 if (content != NULL) {
Daniel Veillardcf461992000-03-14 18:30:20 +00001333 cur->children = xmlNewDocText(doc, content);
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001334 UPDATE_LAST_CHILD(cur)
1335 }
1336 }
1337 return(cur);
1338}
1339
Daniel Veillard2eac5032000-01-09 21:08:56 +00001340/**
1341 * xmlNewDocFragment:
1342 * @doc: the document owning the fragment
1343 *
1344 * Creation of a new Fragment node.
1345 * Returns a pointer to the new node object.
1346 */
1347xmlNodePtr
1348xmlNewDocFragment(xmlDocPtr doc) {
1349 xmlNodePtr cur;
1350
1351 /*
1352 * Allocate a new DocumentFragment node and fill the fields.
1353 */
1354 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
1355 if (cur == NULL) {
1356 fprintf(stderr, "xmlNewDocFragment : malloc failed\n");
1357 return(NULL);
1358 }
Daniel Veillardcf461992000-03-14 18:30:20 +00001359 memset(cur, 0, sizeof(xmlNode));
Daniel Veillard2eac5032000-01-09 21:08:56 +00001360 cur->type = XML_DOCUMENT_FRAG_NODE;
Daniel Veillardcf461992000-03-14 18:30:20 +00001361
Daniel Veillard2eac5032000-01-09 21:08:56 +00001362 cur->doc = doc;
Daniel Veillard2eac5032000-01-09 21:08:56 +00001363 return(cur);
1364}
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001365
1366/**
Daniel Veillard97b58771998-10-20 06:14:16 +00001367 * xmlNewText:
1368 * @content: the text content
1369 *
1370 * Creation of a new text node.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001371 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001372 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001373xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001374xmlNewText(const xmlChar *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001375 xmlNodePtr cur;
1376
1377 /*
1378 * Allocate a new node and fill the fields.
1379 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001380 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillard260a68f1998-08-13 03:39:55 +00001381 if (cur == NULL) {
1382 fprintf(stderr, "xmlNewText : malloc failed\n");
1383 return(NULL);
1384 }
Daniel Veillardcf461992000-03-14 18:30:20 +00001385 memset(cur, 0, sizeof(xmlNode));
1386 cur->type = XML_TEXT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001387
Daniel Veillard260a68f1998-08-13 03:39:55 +00001388 cur->name = xmlStrdup(xmlStringText);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001389 if (content != NULL) {
1390#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard260a68f1998-08-13 03:39:55 +00001391 cur->content = xmlStrdup(content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001392#else
1393 cur->content = xmlBufferCreateSize(0);
1394 xmlBufferSetAllocationScheme(cur->content,
1395 xmlGetBufferAllocationScheme());
1396 xmlBufferAdd(cur->content, content, -1);
1397#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00001398 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00001399 return(cur);
1400}
1401
Daniel Veillard97b58771998-10-20 06:14:16 +00001402/**
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001403 * xmlNewTextChild:
1404 * @parent: the parent node
1405 * @ns: a namespace if any
1406 * @name: the name of the child
1407 * @content: the text content of the child if any.
1408 *
Daniel Veillardcf461992000-03-14 18:30:20 +00001409 * Creation of a new child element, added at the end of @parent children list.
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001410 * @ns and @content parameters are optionnal (NULL). If content is non NULL,
1411 * a child TEXT node will be created containing the string content.
1412 *
1413 * Returns a pointer to the new node object.
1414 */
1415xmlNodePtr
1416xmlNewTextChild(xmlNodePtr parent, xmlNsPtr ns,
1417 const xmlChar *name, const xmlChar *content) {
1418 xmlNodePtr cur, prev;
1419
1420 if (parent == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001421#ifdef DEBUG_TREE
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001422 fprintf(stderr, "xmlNewTextChild : parent == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001423#endif
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001424 return(NULL);
1425 }
1426
1427 if (name == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001428#ifdef DEBUG_TREE
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001429 fprintf(stderr, "xmlNewTextChild : name == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001430#endif
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001431 return(NULL);
1432 }
1433
1434 /*
1435 * Allocate a new node
1436 */
1437 if (ns == NULL)
1438 cur = xmlNewDocRawNode(parent->doc, parent->ns, name, content);
1439 else
1440 cur = xmlNewDocRawNode(parent->doc, ns, name, content);
1441 if (cur == NULL) return(NULL);
1442
1443 /*
Daniel Veillardcf461992000-03-14 18:30:20 +00001444 * add the new element at the end of the children list.
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001445 */
1446 cur->type = XML_ELEMENT_NODE;
1447 cur->parent = parent;
1448 cur->doc = parent->doc;
Daniel Veillardcf461992000-03-14 18:30:20 +00001449 if (parent->children == NULL) {
1450 parent->children = cur;
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001451 parent->last = cur;
1452 } else {
1453 prev = parent->last;
1454 prev->next = cur;
1455 cur->prev = prev;
1456 parent->last = cur;
1457 }
1458
1459 return(cur);
1460}
1461
1462/**
Daniel Veillardcf461992000-03-14 18:30:20 +00001463 * xmlNewCharRef:
1464 * @doc: the document
1465 * @name: the char ref string, starting with # or "&# ... ;"
1466 *
1467 * Creation of a new character reference node.
1468 * Returns a pointer to the new node object.
1469 */
1470xmlNodePtr
1471xmlNewCharRef(xmlDocPtr doc, const xmlChar *name) {
1472 xmlNodePtr cur;
1473
1474 /*
1475 * Allocate a new node and fill the fields.
1476 */
1477 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
1478 if (cur == NULL) {
1479 fprintf(stderr, "xmlNewText : malloc failed\n");
1480 return(NULL);
1481 }
1482 memset(cur, 0, sizeof(xmlNode));
1483 cur->type = XML_ENTITY_REF_NODE;
1484
1485 cur->doc = doc;
1486 if (name[0] == '&') {
1487 int len;
1488 name++;
1489 len = xmlStrlen(name);
1490 if (name[len - 1] == ';')
1491 cur->name = xmlStrndup(name, len - 1);
1492 else
1493 cur->name = xmlStrndup(name, len);
1494 } else
1495 cur->name = xmlStrdup(name);
1496 return(cur);
1497}
1498
1499/**
Daniel Veillardccb09631998-10-27 06:21:04 +00001500 * xmlNewReference:
1501 * @doc: the document
1502 * @name: the reference name, or the reference string with & and ;
1503 *
1504 * Creation of a new reference node.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001505 * Returns a pointer to the new node object.
Daniel Veillardccb09631998-10-27 06:21:04 +00001506 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001507xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001508xmlNewReference(xmlDocPtr doc, const xmlChar *name) {
Daniel Veillardccb09631998-10-27 06:21:04 +00001509 xmlNodePtr cur;
1510 xmlEntityPtr ent;
1511
1512 /*
1513 * Allocate a new node and fill the fields.
1514 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001515 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillardccb09631998-10-27 06:21:04 +00001516 if (cur == NULL) {
1517 fprintf(stderr, "xmlNewText : malloc failed\n");
1518 return(NULL);
1519 }
Daniel Veillardcf461992000-03-14 18:30:20 +00001520 memset(cur, 0, sizeof(xmlNode));
Daniel Veillardccb09631998-10-27 06:21:04 +00001521 cur->type = XML_ENTITY_REF_NODE;
Daniel Veillardcf461992000-03-14 18:30:20 +00001522
Daniel Veillard10c6a8f1998-10-28 01:00:12 +00001523 cur->doc = doc;
Daniel Veillardccb09631998-10-27 06:21:04 +00001524 if (name[0] == '&') {
1525 int len;
1526 name++;
1527 len = xmlStrlen(name);
1528 if (name[len - 1] == ';')
1529 cur->name = xmlStrndup(name, len - 1);
1530 else
1531 cur->name = xmlStrndup(name, len);
1532 } else
1533 cur->name = xmlStrdup(name);
Daniel Veillardccb09631998-10-27 06:21:04 +00001534
1535 ent = xmlGetDocEntity(doc, cur->name);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001536 if (ent != NULL) {
1537#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardccb09631998-10-27 06:21:04 +00001538 cur->content = ent->content;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001539#else
1540 /*
1541 * CJN 11.18.99 this might be a problem, since the xmlBuffer gets
1542 * a copy of this pointer. Let's hope we don't manipulate it
1543 * later
1544 */
1545 cur->content = xmlBufferCreateSize(0);
1546 xmlBufferSetAllocationScheme(cur->content,
1547 xmlGetBufferAllocationScheme());
1548 if (ent->content != NULL)
1549 xmlBufferAdd(cur->content, ent->content, -1);
1550#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00001551 cur->children = (xmlNodePtr) ent;
1552 }
Daniel Veillardccb09631998-10-27 06:21:04 +00001553 return(cur);
1554}
1555
1556/**
Daniel Veillard97b58771998-10-20 06:14:16 +00001557 * xmlNewDocText:
1558 * @doc: the document
1559 * @content: the text content
1560 *
1561 * Creation of a new text node within a document.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001562 * Returns a pointer to the new node object.
Daniel Veillard97b58771998-10-20 06:14:16 +00001563 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001564xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001565xmlNewDocText(xmlDocPtr doc, const xmlChar *content) {
Daniel Veillard0bef1311998-10-14 02:36:47 +00001566 xmlNodePtr cur;
1567
1568 cur = xmlNewText(content);
1569 if (cur != NULL) cur->doc = doc;
1570 return(cur);
1571}
1572
Daniel Veillard97b58771998-10-20 06:14:16 +00001573/**
Daniel Veillardccb09631998-10-27 06:21:04 +00001574 * xmlNewTextLen:
Daniel Veillard97b58771998-10-20 06:14:16 +00001575 * @content: the text content
1576 * @len: the text len.
1577 *
1578 * Creation of a new text node with an extra parameter for the content's lenght
Daniel Veillard1e346af1999-02-22 10:33:01 +00001579 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001580 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001581xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001582xmlNewTextLen(const xmlChar *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001583 xmlNodePtr cur;
1584
1585 /*
1586 * Allocate a new node and fill the fields.
1587 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001588 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillard260a68f1998-08-13 03:39:55 +00001589 if (cur == NULL) {
1590 fprintf(stderr, "xmlNewText : malloc failed\n");
1591 return(NULL);
1592 }
Daniel Veillardcf461992000-03-14 18:30:20 +00001593 memset(cur, 0, sizeof(xmlNode));
1594 cur->type = XML_TEXT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001595
Daniel Veillard260a68f1998-08-13 03:39:55 +00001596 cur->name = xmlStrdup(xmlStringText);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001597 if (content != NULL) {
1598#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard260a68f1998-08-13 03:39:55 +00001599 cur->content = xmlStrndup(content, len);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001600#else
1601 cur->content = xmlBufferCreateSize(len);
1602 xmlBufferSetAllocationScheme(cur->content,
1603 xmlGetBufferAllocationScheme());
1604 xmlBufferAdd(cur->content, content, len);
1605#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00001606 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00001607 return(cur);
1608}
1609
Daniel Veillard97b58771998-10-20 06:14:16 +00001610/**
1611 * xmlNewDocTextLen:
1612 * @doc: the document
1613 * @content: the text content
1614 * @len: the text len.
1615 *
1616 * Creation of a new text node with an extra content lenght parameter. The
1617 * text node pertain to a given document.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001618 * Returns a pointer to the new node object.
Daniel Veillard97b58771998-10-20 06:14:16 +00001619 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001620xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001621xmlNewDocTextLen(xmlDocPtr doc, const xmlChar *content, int len) {
Daniel Veillard0bef1311998-10-14 02:36:47 +00001622 xmlNodePtr cur;
1623
1624 cur = xmlNewTextLen(content, len);
1625 if (cur != NULL) cur->doc = doc;
1626 return(cur);
1627}
1628
Daniel Veillard97b58771998-10-20 06:14:16 +00001629/**
1630 * xmlNewComment:
1631 * @content: the comment content
1632 *
1633 * Creation of a new node containing a comment.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001634 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001635 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001636xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001637xmlNewComment(const xmlChar *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001638 xmlNodePtr cur;
1639
1640 /*
1641 * Allocate a new node and fill the fields.
1642 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001643 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillard260a68f1998-08-13 03:39:55 +00001644 if (cur == NULL) {
1645 fprintf(stderr, "xmlNewComment : malloc failed\n");
1646 return(NULL);
1647 }
Daniel Veillardcf461992000-03-14 18:30:20 +00001648 memset(cur, 0, sizeof(xmlNode));
1649 cur->type = XML_COMMENT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001650
Daniel Veillardcf461992000-03-14 18:30:20 +00001651 cur->name = xmlStrdup(xmlStringComment);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001652 if (content != NULL) {
1653#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard260a68f1998-08-13 03:39:55 +00001654 cur->content = xmlStrdup(content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001655#else
1656 cur->content = xmlBufferCreateSize(0);
1657 xmlBufferSetAllocationScheme(cur->content,
1658 xmlGetBufferAllocationScheme());
1659 xmlBufferAdd(cur->content, content, -1);
1660#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00001661 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00001662 return(cur);
1663}
1664
Daniel Veillard97b58771998-10-20 06:14:16 +00001665/**
Daniel Veillardb05deb71999-08-10 19:04:08 +00001666 * xmlNewCDataBlock:
1667 * @doc: the document
1668 * @content: the CData block content content
1669 * @len: the length of the block
1670 *
1671 * Creation of a new node containing a CData block.
1672 * Returns a pointer to the new node object.
1673 */
1674xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001675xmlNewCDataBlock(xmlDocPtr doc, const xmlChar *content, int len) {
Daniel Veillardb05deb71999-08-10 19:04:08 +00001676 xmlNodePtr cur;
1677
1678 /*
1679 * Allocate a new node and fill the fields.
1680 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001681 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillardb05deb71999-08-10 19:04:08 +00001682 if (cur == NULL) {
1683 fprintf(stderr, "xmlNewCDataBlock : malloc failed\n");
1684 return(NULL);
1685 }
Daniel Veillardcf461992000-03-14 18:30:20 +00001686 memset(cur, 0, sizeof(xmlNode));
Daniel Veillardb05deb71999-08-10 19:04:08 +00001687 cur->type = XML_CDATA_SECTION_NODE;
Daniel Veillardcf461992000-03-14 18:30:20 +00001688
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001689 if (content != NULL) {
1690#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardb05deb71999-08-10 19:04:08 +00001691 cur->content = xmlStrndup(content, len);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001692#else
1693 cur->content = xmlBufferCreateSize(len);
1694 xmlBufferSetAllocationScheme(cur->content,
1695 xmlGetBufferAllocationScheme());
1696 xmlBufferAdd(cur->content, content, len);
1697#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00001698 }
Daniel Veillardb05deb71999-08-10 19:04:08 +00001699 return(cur);
1700}
1701
1702/**
Daniel Veillard1e346af1999-02-22 10:33:01 +00001703 * xmlNewDocComment:
Daniel Veillard97b58771998-10-20 06:14:16 +00001704 * @doc: the document
1705 * @content: the comment content
1706 *
1707 * Creation of a new node containing a commentwithin a document.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001708 * Returns a pointer to the new node object.
Daniel Veillard97b58771998-10-20 06:14:16 +00001709 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001710xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001711xmlNewDocComment(xmlDocPtr doc, const xmlChar *content) {
Daniel Veillard0bef1311998-10-14 02:36:47 +00001712 xmlNodePtr cur;
1713
1714 cur = xmlNewComment(content);
1715 if (cur != NULL) cur->doc = doc;
1716 return(cur);
1717}
1718
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001719
Daniel Veillard97b58771998-10-20 06:14:16 +00001720/**
1721 * xmlNewChild:
1722 * @parent: the parent node
1723 * @ns: a namespace if any
1724 * @name: the name of the child
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001725 * @content: the XML content of the child if any.
Daniel Veillard97b58771998-10-20 06:14:16 +00001726 *
Daniel Veillardcf461992000-03-14 18:30:20 +00001727 * Creation of a new child element, added at the end of @parent children list.
Daniel Veillardccb09631998-10-27 06:21:04 +00001728 * @ns and @content parameters are optionnal (NULL). If content is non NULL,
1729 * a child list containing the TEXTs and ENTITY_REFs node will be created.
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001730 * NOTE: @content is supposed to be a piece of XML CDATA, so it allow entities
1731 * references, but XML special chars need to be escaped first by using
1732 * xmlEncodeEntitiesReentrant(). Use xmlNewTextChild() if entities
1733 * support is not needed.
1734 *
Daniel Veillard1e346af1999-02-22 10:33:01 +00001735 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001736 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001737xmlNodePtr
1738xmlNewChild(xmlNodePtr parent, xmlNsPtr ns,
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001739 const xmlChar *name, const xmlChar *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001740 xmlNodePtr cur, prev;
1741
1742 if (parent == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001743#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00001744 fprintf(stderr, "xmlNewChild : parent == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001745#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001746 return(NULL);
1747 }
1748
1749 if (name == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001750#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00001751 fprintf(stderr, "xmlNewChild : name == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001752#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001753 return(NULL);
1754 }
1755
1756 /*
1757 * Allocate a new node
1758 */
1759 if (ns == NULL)
Daniel Veillardccb09631998-10-27 06:21:04 +00001760 cur = xmlNewDocNode(parent->doc, parent->ns, name, content);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001761 else
Daniel Veillardccb09631998-10-27 06:21:04 +00001762 cur = xmlNewDocNode(parent->doc, ns, name, content);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001763 if (cur == NULL) return(NULL);
1764
1765 /*
Daniel Veillardcf461992000-03-14 18:30:20 +00001766 * add the new element at the end of the children list.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001767 */
Daniel Veillardccb09631998-10-27 06:21:04 +00001768 cur->type = XML_ELEMENT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001769 cur->parent = parent;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001770 cur->doc = parent->doc;
Daniel Veillardcf461992000-03-14 18:30:20 +00001771 if (parent->children == NULL) {
1772 parent->children = cur;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001773 parent->last = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001774 } else {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001775 prev = parent->last;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001776 prev->next = cur;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001777 cur->prev = prev;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001778 parent->last = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001779 }
1780
1781 return(cur);
1782}
1783
Daniel Veillard97b58771998-10-20 06:14:16 +00001784/**
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00001785 * xmlAddNextSibling:
1786 * @cur: the child node
1787 * @elem: the new node
1788 *
1789 * Add a new element @elem as the next siblings of @cur
1790 * If the new element was already inserted in a document it is
1791 * first unlinked from its existing context.
1792 *
1793 * Returns the new element or NULL in case of error.
1794 */
1795xmlNodePtr
1796xmlAddNextSibling(xmlNodePtr cur, xmlNodePtr elem) {
1797 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001798#ifdef DEBUG_TREE
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00001799 fprintf(stderr, "xmlAddNextSibling : cur == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001800#endif
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00001801 return(NULL);
1802 }
1803 if (elem == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001804#ifdef DEBUG_TREE
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00001805 fprintf(stderr, "xmlAddNextSibling : elem == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001806#endif
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00001807 return(NULL);
1808 }
1809
1810 xmlUnlinkNode(elem);
1811 elem->doc = cur->doc;
1812 elem->parent = cur->parent;
Daniel Veillard5d211f42000-04-07 17:00:24 +00001813 elem->prev = cur;
1814 elem->next = cur->next;
1815 cur->next = elem;
1816 if (elem->next != NULL)
1817 elem->next->prev = elem;
1818 if ((elem->parent != NULL) && (elem->parent->last == cur))
1819 elem->parent->last = elem;
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00001820 return(elem);
1821}
1822
1823/**
1824 * xmlAddPrevSibling:
1825 * @cur: the child node
1826 * @elem: the new node
1827 *
1828 * Add a new element @elem as the previous siblings of @cur
1829 * If the new element was already inserted in a document it is
1830 * first unlinked from its existing context.
1831 *
1832 * Returns the new element or NULL in case of error.
1833 */
1834xmlNodePtr
1835xmlAddPrevSibling(xmlNodePtr cur, xmlNodePtr elem) {
1836 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001837#ifdef DEBUG_TREE
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00001838 fprintf(stderr, "xmlAddPrevSibling : cur == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001839#endif
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00001840 return(NULL);
1841 }
1842 if (elem == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001843#ifdef DEBUG_TREE
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00001844 fprintf(stderr, "xmlAddPrevSibling : elem == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001845#endif
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00001846 return(NULL);
1847 }
1848
1849 xmlUnlinkNode(elem);
1850 elem->doc = cur->doc;
1851 elem->parent = cur->parent;
Daniel Veillard5d211f42000-04-07 17:00:24 +00001852 elem->next = cur;
1853 elem->prev = cur->prev;
1854 cur->prev = elem;
1855 if (elem->prev != NULL)
1856 elem->prev->next = elem;
1857 if ((elem->parent != NULL) && (elem->parent->children == cur))
1858 elem->parent->children = elem;
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00001859 return(elem);
1860}
1861
1862/**
Daniel Veillardb96e6431999-08-29 21:02:19 +00001863 * xmlAddSibling:
1864 * @cur: the child node
1865 * @elem: the new node
1866 *
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00001867 * Add a new element @elem to the list of siblings of @cur
1868 * If the new element was already inserted in a document it is
1869 * first unlinked from its existing context.
1870 *
1871 * Returns the new element or NULL in case of error.
Daniel Veillardb96e6431999-08-29 21:02:19 +00001872 */
1873xmlNodePtr
1874xmlAddSibling(xmlNodePtr cur, xmlNodePtr elem) {
1875 xmlNodePtr parent;
1876
1877 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001878#ifdef DEBUG_TREE
Daniel Veillardb96e6431999-08-29 21:02:19 +00001879 fprintf(stderr, "xmlAddSibling : cur == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001880#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +00001881 return(NULL);
1882 }
1883
1884 if (elem == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001885#ifdef DEBUG_TREE
Daniel Veillardb96e6431999-08-29 21:02:19 +00001886 fprintf(stderr, "xmlAddSibling : elem == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001887#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +00001888 return(NULL);
1889 }
1890
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00001891 /*
1892 * Constant time is we can rely on the ->parent->last to find
1893 * the last sibling.
1894 */
1895 if ((cur->parent != NULL) &&
Daniel Veillardcf461992000-03-14 18:30:20 +00001896 (cur->parent->children != NULL) &&
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00001897 (cur->parent->last != NULL) &&
1898 (cur->parent->last->next == NULL)) {
1899 cur = cur->parent->last;
1900 } else {
1901 while (cur->next != NULL) cur = cur->next;
Daniel Veillardb96e6431999-08-29 21:02:19 +00001902 }
1903
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00001904 xmlUnlinkNode(elem);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001905 if (elem->doc == NULL)
1906 elem->doc = cur->doc; /* the parent may not be linked to a doc ! */
1907
1908 parent = cur->parent;
1909 elem->prev = cur;
1910 elem->next = NULL;
1911 elem->parent = parent;
1912 cur->next = elem;
1913 if (parent != NULL)
1914 parent->last = elem;
1915
1916 return(elem);
1917}
1918
1919/**
Daniel Veillard87b95392000-08-12 21:12:04 +00001920 * xmlAddChildList:
1921 * @parent: the parent node
1922 * @cur: the first node in the list
1923 *
1924 * Add a list of node at the end of the child list of the parent
1925 *
1926 * Returns the last child or NULL in case of error.
1927 */
1928xmlNodePtr
1929xmlAddChildList(xmlNodePtr parent, xmlNodePtr cur) {
1930 xmlNodePtr prev;
1931
1932 if (parent == NULL) {
1933#ifdef DEBUG_TREE
1934 fprintf(stderr, "xmlAddChild : parent == NULL\n");
1935#endif
1936 return(NULL);
1937 }
1938
1939 if (cur == NULL) {
1940#ifdef DEBUG_TREE
1941 fprintf(stderr, "xmlAddChild : child == NULL\n");
1942#endif
1943 return(NULL);
1944 }
1945
1946 if ((cur->doc != NULL) && (parent->doc != NULL) &&
1947 (cur->doc != parent->doc)) {
1948#ifdef DEBUG_TREE
1949 fprintf(stderr, "Elements moved to a different document\n");
1950#endif
1951 }
1952
1953 /*
1954 * add the first element at the end of the children list.
1955 */
1956 if (parent->children == NULL) {
1957 parent->children = cur;
1958 } else {
1959 prev = parent->last;
1960 prev->next = cur;
1961 cur->prev = prev;
1962 }
1963 while (cur->next != NULL) {
1964 cur->parent = parent;
1965 cur->doc = parent->doc; /* the parent may not be linked to a doc ! */
1966 cur = cur->next;
1967 }
1968 cur->parent = parent;
1969 cur->doc = parent->doc; /* the parent may not be linked to a doc ! */
1970 parent->last = cur;
1971
1972 return(cur);
1973}
1974
1975/**
Daniel Veillard97b58771998-10-20 06:14:16 +00001976 * xmlAddChild:
1977 * @parent: the parent node
1978 * @cur: the child node
1979 *
1980 * Add a new child element, to @parent, at the end of the child list.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001981 * Returns the child or NULL in case of error.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001982 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001983xmlNodePtr
1984xmlAddChild(xmlNodePtr parent, xmlNodePtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001985 xmlNodePtr prev;
1986
1987 if (parent == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001988#ifdef DEBUG_TREE
Daniel Veillard10a2c651999-12-12 13:03:50 +00001989 fprintf(stderr, "xmlAddChild : parent == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001990#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001991 return(NULL);
1992 }
1993
1994 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001995#ifdef DEBUG_TREE
Daniel Veillard10a2c651999-12-12 13:03:50 +00001996 fprintf(stderr, "xmlAddChild : child == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001997#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001998 return(NULL);
1999 }
2000
Daniel Veillard0bef1311998-10-14 02:36:47 +00002001 if ((cur->doc != NULL) && (parent->doc != NULL) &&
2002 (cur->doc != parent->doc)) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00002003#ifdef DEBUG_TREE
Daniel Veillard0bef1311998-10-14 02:36:47 +00002004 fprintf(stderr, "Elements moved to a different document\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00002005#endif
Daniel Veillard0bef1311998-10-14 02:36:47 +00002006 }
2007
Daniel Veillard260a68f1998-08-13 03:39:55 +00002008 /*
Daniel Veillardcf461992000-03-14 18:30:20 +00002009 * add the new element at the end of the children list.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002010 */
2011 cur->parent = parent;
Daniel Veillard0bef1311998-10-14 02:36:47 +00002012 cur->doc = parent->doc; /* the parent may not be linked to a doc ! */
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002013
Daniel Veillardccb09631998-10-27 06:21:04 +00002014 /*
2015 * Handle the case where parent->content != NULL, in that case it will
2016 * create a intermediate TEXT node.
2017 */
Daniel Veillardcf461992000-03-14 18:30:20 +00002018 if (((parent->type == XML_ELEMENT_NODE) || (parent->type == XML_TEXT_NODE)) &&
2019 (parent->content != NULL)) {
Daniel Veillardccb09631998-10-27 06:21:04 +00002020 xmlNodePtr text;
2021
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002022#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardccb09631998-10-27 06:21:04 +00002023 text = xmlNewDocText(parent->doc, parent->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002024#else
2025 text = xmlNewDocText(parent->doc, xmlBufferContent(parent->content));
2026#endif
Daniel Veillardccb09631998-10-27 06:21:04 +00002027 if (text != NULL) {
Daniel Veillardcf461992000-03-14 18:30:20 +00002028 text->next = parent->children;
Daniel Veillardccb09631998-10-27 06:21:04 +00002029 if (text->next != NULL)
2030 text->next->prev = text;
Daniel Veillardcf461992000-03-14 18:30:20 +00002031 parent->children = text;
Daniel Veillard1e346af1999-02-22 10:33:01 +00002032 UPDATE_LAST_CHILD(parent)
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002033#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard6454aec1999-09-02 22:04:43 +00002034 xmlFree(parent->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002035#else
2036 xmlBufferFree(parent->content);
2037#endif
Daniel Veillardccb09631998-10-27 06:21:04 +00002038 parent->content = NULL;
2039 }
2040 }
Daniel Veillardcf461992000-03-14 18:30:20 +00002041 if (parent->children == NULL) {
2042 parent->children = cur;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002043 parent->last = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002044 } else {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002045 prev = parent->last;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002046 prev->next = cur;
Daniel Veillard0bef1311998-10-14 02:36:47 +00002047 cur->prev = prev;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002048 parent->last = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002049 }
2050
2051 return(cur);
2052}
2053
Daniel Veillard97b58771998-10-20 06:14:16 +00002054/**
2055 * xmlGetLastChild:
2056 * @parent: the parent node
2057 *
2058 * Search the last child of a node.
Daniel Veillard1e346af1999-02-22 10:33:01 +00002059 * Returns the last child or NULL if none.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002060 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002061xmlNodePtr
2062xmlGetLastChild(xmlNodePtr parent) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002063 if (parent == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00002064#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00002065 fprintf(stderr, "xmlGetLastChild : parent == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00002066#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00002067 return(NULL);
2068 }
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002069 return(parent->last);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002070}
2071
Daniel Veillard97b58771998-10-20 06:14:16 +00002072/**
2073 * xmlFreeNodeList:
2074 * @cur: the first node in the list
2075 *
2076 * Free a node and all its siblings, this is a recursive behaviour, all
Daniel Veillardcf461992000-03-14 18:30:20 +00002077 * the children are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002078 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002079void
2080xmlFreeNodeList(xmlNodePtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002081 xmlNodePtr next;
2082 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00002083#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00002084 fprintf(stderr, "xmlFreeNodeList : node == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00002085#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00002086 return;
2087 }
2088 while (cur != NULL) {
2089 next = cur->next;
2090 xmlFreeNode(cur);
2091 cur = next;
2092 }
2093}
2094
Daniel Veillard97b58771998-10-20 06:14:16 +00002095/**
2096 * xmlFreeNode:
2097 * @cur: the node
2098 *
Daniel Veillardcf461992000-03-14 18:30:20 +00002099 * Free a node, this is a recursive behaviour, all the children are freed too.
2100 * This doesn't unlink the child from the list, use xmlUnlinkNode() first.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002101 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002102void
2103xmlFreeNode(xmlNodePtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002104 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00002105#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00002106 fprintf(stderr, "xmlFreeNode : node == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00002107#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00002108 return;
2109 }
Daniel Veillardcf461992000-03-14 18:30:20 +00002110 if (cur->type == XML_DTD_NODE)
2111 return;
Daniel Veillardccb09631998-10-27 06:21:04 +00002112 cur->doc = NULL;
2113 cur->parent = NULL;
2114 cur->next = NULL;
2115 cur->prev = NULL;
Daniel Veillardcf461992000-03-14 18:30:20 +00002116 if ((cur->children != NULL) &&
2117 (cur->type != XML_ENTITY_REF_NODE))
2118 xmlFreeNodeList(cur->children);
Daniel Veillardccb09631998-10-27 06:21:04 +00002119 if (cur->properties != NULL) xmlFreePropList(cur->properties);
2120 if (cur->type != XML_ENTITY_REF_NODE)
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002121#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard6454aec1999-09-02 22:04:43 +00002122 if (cur->content != NULL) xmlFree(cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002123#else
2124 if (cur->content != NULL) xmlBufferFree(cur->content);
2125#endif
Daniel Veillard6454aec1999-09-02 22:04:43 +00002126 if (cur->name != NULL) xmlFree((char *) cur->name);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002127 if (cur->nsDef != NULL) xmlFreeNsList(cur->nsDef);
2128 memset(cur, -1, sizeof(xmlNode));
Daniel Veillard6454aec1999-09-02 22:04:43 +00002129 xmlFree(cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002130}
2131
Daniel Veillard16253641998-10-28 22:58:05 +00002132/**
2133 * xmlUnlinkNode:
2134 * @cur: the node
2135 *
2136 * Unlink a node from it's current context, the node is not freed
2137 */
2138void
2139xmlUnlinkNode(xmlNodePtr cur) {
2140 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00002141#ifdef DEBUG_TREE
Daniel Veillard16253641998-10-28 22:58:05 +00002142 fprintf(stderr, "xmlUnlinkNode : node == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00002143#endif
Daniel Veillard16253641998-10-28 22:58:05 +00002144 return;
2145 }
Daniel Veillardcf461992000-03-14 18:30:20 +00002146 if ((cur->parent != NULL) && (cur->parent->children == cur))
2147 cur->parent->children = cur->next;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002148 if ((cur->parent != NULL) && (cur->parent->last == cur))
2149 cur->parent->last = cur->prev;
Daniel Veillard16253641998-10-28 22:58:05 +00002150 if (cur->next != NULL)
2151 cur->next->prev = cur->prev;
2152 if (cur->prev != NULL)
2153 cur->prev->next = cur->next;
2154 cur->next = cur->prev = NULL;
2155 cur->parent = NULL;
2156}
2157
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00002158/**
2159 * xmlReplaceNode:
2160 * @old: the old node
2161 * @cur: the node
2162 *
2163 * Unlink the old node from it's current context, prune the new one
2164 * at the same place. If cur was already inserted in a document it is
2165 * first unlinked from its existing context.
2166 *
2167 * Returns the old node
2168 */
2169xmlNodePtr
2170xmlReplaceNode(xmlNodePtr old, xmlNodePtr cur) {
2171 if (old == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00002172#ifdef DEBUG_TREE
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00002173 fprintf(stderr, "xmlReplaceNode : old == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00002174#endif
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00002175 return(NULL);
2176 }
2177 if (cur == NULL) {
2178 xmlUnlinkNode(old);
2179 return(old);
2180 }
2181 xmlUnlinkNode(cur);
2182 cur->doc = old->doc;
2183 cur->parent = old->parent;
2184 cur->next = old->next;
2185 if (cur->next != NULL)
2186 cur->next->prev = cur;
2187 cur->prev = old->prev;
2188 if (cur->prev != NULL)
2189 cur->prev->next = cur;
2190 if (cur->parent != NULL) {
Daniel Veillardcf461992000-03-14 18:30:20 +00002191 if (cur->parent->children == old)
2192 cur->parent->children = cur;
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00002193 if (cur->parent->last == old)
2194 cur->parent->last = cur;
2195 }
2196 old->next = old->prev = NULL;
2197 old->parent = NULL;
2198 return(old);
2199}
2200
Daniel Veillard260a68f1998-08-13 03:39:55 +00002201/************************************************************************
2202 * *
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002203 * Copy operations *
2204 * *
2205 ************************************************************************/
2206
2207/**
2208 * xmlCopyNamespace:
2209 * @cur: the namespace
2210 *
2211 * Do a copy of the namespace.
2212 *
2213 * Returns: a new xmlNsPtr, or NULL in case of error.
2214 */
2215xmlNsPtr
2216xmlCopyNamespace(xmlNsPtr cur) {
2217 xmlNsPtr ret;
2218
2219 if (cur == NULL) return(NULL);
2220 switch (cur->type) {
2221 case XML_GLOBAL_NAMESPACE:
2222 ret = xmlNewGlobalNs(NULL, cur->href, cur->prefix);
2223 break;
2224 case XML_LOCAL_NAMESPACE:
2225 ret = xmlNewNs(NULL, cur->href, cur->prefix);
2226 break;
2227 default:
Daniel Veillardad8f99d2000-01-15 14:20:03 +00002228#ifdef DEBUG_TREE
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002229 fprintf(stderr, "xmlCopyNamespace: unknown type %d\n", cur->type);
Daniel Veillardad8f99d2000-01-15 14:20:03 +00002230#endif
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002231 return(NULL);
2232 }
2233 return(ret);
2234}
2235
2236/**
2237 * xmlCopyNamespaceList:
2238 * @cur: the first namespace
2239 *
2240 * Do a copy of an namespace list.
2241 *
2242 * Returns: a new xmlNsPtr, or NULL in case of error.
2243 */
2244xmlNsPtr
2245xmlCopyNamespaceList(xmlNsPtr cur) {
2246 xmlNsPtr ret = NULL;
2247 xmlNsPtr p = NULL,q;
2248
2249 while (cur != NULL) {
2250 q = xmlCopyNamespace(cur);
2251 if (p == NULL) {
2252 ret = p = q;
2253 } else {
2254 p->next = q;
2255 p = q;
2256 }
2257 cur = cur->next;
2258 }
2259 return(ret);
2260}
2261
2262/**
2263 * xmlCopyProp:
Daniel Veillardb96e6431999-08-29 21:02:19 +00002264 * @target: the element where the attribute will be grafted
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002265 * @cur: the attribute
2266 *
2267 * Do a copy of the attribute.
2268 *
2269 * Returns: a new xmlAttrPtr, or NULL in case of error.
2270 */
2271xmlAttrPtr
Daniel Veillardb96e6431999-08-29 21:02:19 +00002272xmlCopyProp(xmlNodePtr target, xmlAttrPtr cur) {
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002273 xmlAttrPtr ret;
2274
2275 if (cur == NULL) return(NULL);
Daniel Veillardcf461992000-03-14 18:30:20 +00002276 if (cur->parent != NULL)
2277 ret = xmlNewDocProp(cur->parent->doc, cur->name, NULL);
2278 else if (cur->children != NULL)
2279 ret = xmlNewDocProp(cur->children->doc, cur->name, NULL);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002280 else
2281 ret = xmlNewDocProp(NULL, cur->name, NULL);
2282 if (ret == NULL) return(NULL);
Daniel Veillardcf461992000-03-14 18:30:20 +00002283 ret->parent = target;
Daniel Veillardb96e6431999-08-29 21:02:19 +00002284
2285 if ((cur->ns != NULL) && (target != NULL)) {
2286 xmlNsPtr ns;
2287
2288 ns = xmlSearchNs(target->doc, target, cur->ns->prefix);
2289 ret->ns = ns;
2290 } else
2291 ret->ns = NULL;
2292
Daniel Veillardcf461992000-03-14 18:30:20 +00002293 if (cur->children != NULL)
2294 ret->children = xmlCopyNodeList(cur->children);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002295 return(ret);
2296}
2297
2298/**
2299 * xmlCopyPropList:
Daniel Veillardb96e6431999-08-29 21:02:19 +00002300 * @target: the element where the attributes will be grafted
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002301 * @cur: the first attribute
2302 *
2303 * Do a copy of an attribute list.
2304 *
2305 * Returns: a new xmlAttrPtr, or NULL in case of error.
2306 */
2307xmlAttrPtr
Daniel Veillardb96e6431999-08-29 21:02:19 +00002308xmlCopyPropList(xmlNodePtr target, xmlAttrPtr cur) {
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002309 xmlAttrPtr ret = NULL;
2310 xmlAttrPtr p = NULL,q;
2311
2312 while (cur != NULL) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00002313 q = xmlCopyProp(target, cur);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002314 if (p == NULL) {
2315 ret = p = q;
2316 } else {
2317 p->next = q;
Daniel Veillardcf461992000-03-14 18:30:20 +00002318 q->prev = p;
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002319 p = q;
2320 }
2321 cur = cur->next;
2322 }
2323 return(ret);
2324}
2325
2326/*
Daniel Veillard11a48ec1999-11-23 10:40:46 +00002327 * NOTE abeut the CopyNode operations !
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002328 *
2329 * They are splitted into external and internal parts for one
2330 * tricky reason: namespaces. Doing a direct copy of a node
2331 * say RPM:Copyright without changing the namespace pointer to
2332 * something else can produce stale links. One way to do it is
2333 * to keep a reference counter but this doesn't work as soon
2334 * as one move the element or the subtree out of the scope of
2335 * the existing namespace. The actual solution seems to add
2336 * a copy of the namespace at the top of the copied tree if
2337 * not available in the subtree.
2338 * Hence two functions, the public front-end call the inner ones
2339 */
2340
2341static xmlNodePtr
2342xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent);
2343
2344static xmlNodePtr
2345xmlStaticCopyNode(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent,
2346 int recursive) {
2347 xmlNodePtr ret;
2348
2349 if (node == NULL) return(NULL);
2350 /*
2351 * Allocate a new node and fill the fields.
2352 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00002353 ret = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002354 if (ret == NULL) {
2355 fprintf(stderr, "xmlStaticCopyNode : malloc failed\n");
2356 return(NULL);
2357 }
Daniel Veillardcf461992000-03-14 18:30:20 +00002358 memset(ret, 0, sizeof(xmlNode));
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002359 ret->type = node->type;
Daniel Veillardcf461992000-03-14 18:30:20 +00002360
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002361 ret->doc = doc;
2362 ret->parent = parent;
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002363 if (node->name != NULL)
2364 ret->name = xmlStrdup(node->name);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002365 if ((node->content != NULL) && (node->type != XML_ENTITY_REF_NODE)) {
2366#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002367 ret->content = xmlStrdup(node->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002368#else
2369 ret->content = xmlBufferCreateSize(xmlBufferLength(node->content));
2370 xmlBufferSetAllocationScheme(ret->content,
2371 xmlGetBufferAllocationScheme());
2372 xmlBufferAdd(ret->content,
2373 xmlBufferContent(node->content),
2374 xmlBufferLength(node->content));
2375#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00002376 }
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002377 if (parent != NULL)
2378 xmlAddChild(parent, ret);
2379
2380 if (!recursive) return(ret);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002381 if (node->nsDef != NULL)
2382 ret->nsDef = xmlCopyNamespaceList(node->nsDef);
2383
2384 if (node->ns != NULL) {
2385 xmlNsPtr ns;
2386
2387 ns = xmlSearchNs(doc, ret, node->ns->prefix);
2388 if (ns == NULL) {
2389 /*
2390 * Humm, we are copying an element whose namespace is defined
2391 * out of the new tree scope. Search it in the original tree
2392 * and add it at the top of the new tree
2393 */
2394 ns = xmlSearchNs(node->doc, node, node->ns->prefix);
2395 if (ns != NULL) {
2396 xmlNodePtr root = ret;
2397
2398 while (root->parent != NULL) root = root->parent;
2399 xmlNewNs(root, ns->href, ns->prefix);
2400 }
2401 } else {
2402 /*
2403 * reference the existing namespace definition in our own tree.
2404 */
2405 ret->ns = ns;
2406 }
2407 }
Daniel Veillardb96e6431999-08-29 21:02:19 +00002408 if (node->properties != NULL)
2409 ret->properties = xmlCopyPropList(ret, node->properties);
Daniel Veillardcf461992000-03-14 18:30:20 +00002410 if (node->children != NULL)
2411 ret->children = xmlStaticCopyNodeList(node->children, doc, ret);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002412 UPDATE_LAST_CHILD(ret)
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002413 return(ret);
2414}
2415
2416static xmlNodePtr
2417xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent) {
2418 xmlNodePtr ret = NULL;
2419 xmlNodePtr p = NULL,q;
2420
2421 while (node != NULL) {
2422 q = xmlStaticCopyNode(node, doc, parent, 1);
Daniel Veillard06047432000-04-24 11:33:38 +00002423 if (ret == NULL) {
2424 q->prev = NULL;
2425 ret = p = q;
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002426 } else {
Daniel Veillard06047432000-04-24 11:33:38 +00002427 p->next = q;
2428 q->prev = p;
2429 p = q;
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002430 }
2431 node = node->next;
2432 }
2433 return(ret);
2434}
2435
2436/**
2437 * xmlCopyNode:
2438 * @node: the node
2439 * @recursive: if 1 do a recursive copy.
2440 *
2441 * Do a copy of the node.
2442 *
2443 * Returns: a new xmlNodePtr, or NULL in case of error.
2444 */
2445xmlNodePtr
2446xmlCopyNode(xmlNodePtr node, int recursive) {
2447 xmlNodePtr ret;
2448
2449 ret = xmlStaticCopyNode(node, NULL, NULL, recursive);
2450 return(ret);
2451}
2452
2453/**
2454 * xmlCopyNodeList:
2455 * @node: the first node in the list.
2456 *
2457 * Do a recursive copy of the node list.
2458 *
2459 * Returns: a new xmlNodePtr, or NULL in case of error.
2460 */
2461xmlNodePtr xmlCopyNodeList(xmlNodePtr node) {
2462 xmlNodePtr ret = xmlStaticCopyNodeList(node, NULL, NULL);
2463 return(ret);
2464}
2465
2466/**
2467 * xmlCopyElement:
2468 * @elem: the element
2469 *
2470 * Do a copy of the element definition.
2471 *
2472 * Returns: a new xmlElementPtr, or NULL in case of error.
2473xmlElementPtr
2474xmlCopyElement(xmlElementPtr elem) {
2475 xmlElementPtr ret;
2476
2477 if (elem == NULL) return(NULL);
2478 ret = xmlNewDocElement(elem->doc, elem->ns, elem->name, elem->content);
2479 if (ret == NULL) return(NULL);
2480 if (!recursive) return(ret);
2481 if (elem->properties != NULL)
2482 ret->properties = xmlCopyPropList(elem->properties);
2483
2484 if (elem->nsDef != NULL)
2485 ret->nsDef = xmlCopyNamespaceList(elem->nsDef);
Daniel Veillardcf461992000-03-14 18:30:20 +00002486 if (elem->children != NULL)
2487 ret->children = xmlCopyElementList(elem->children);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002488 return(ret);
2489}
2490 */
2491
2492/**
2493 * xmlCopyDtd:
2494 * @dtd: the dtd
2495 *
2496 * Do a copy of the dtd.
2497 *
2498 * Returns: a new xmlDtdPtr, or NULL in case of error.
2499 */
2500xmlDtdPtr
2501xmlCopyDtd(xmlDtdPtr dtd) {
2502 xmlDtdPtr ret;
2503
2504 if (dtd == NULL) return(NULL);
2505 ret = xmlNewDtd(NULL, dtd->name, dtd->ExternalID, dtd->SystemID);
2506 if (ret == NULL) return(NULL);
2507 if (dtd->entities != NULL)
2508 ret->entities = (void *) xmlCopyEntitiesTable(
2509 (xmlEntitiesTablePtr) dtd->entities);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002510 if (dtd->notations != NULL)
2511 ret->notations = (void *) xmlCopyNotationTable(
2512 (xmlNotationTablePtr) dtd->notations);
2513 if (dtd->elements != NULL)
2514 ret->elements = (void *) xmlCopyElementTable(
2515 (xmlElementTablePtr) dtd->elements);
2516 if (dtd->attributes != NULL)
2517 ret->attributes = (void *) xmlCopyAttributeTable(
2518 (xmlAttributeTablePtr) dtd->attributes);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002519 return(ret);
2520}
2521
2522/**
2523 * xmlCopyDoc:
2524 * @doc: the document
2525 * @recursive: if 1 do a recursive copy.
2526 *
2527 * Do a copy of the document info. If recursive, the content tree will
2528 * be copied too as well as Dtd, namespaces and entities.
2529 *
2530 * Returns: a new xmlDocPtr, or NULL in case of error.
2531 */
2532xmlDocPtr
2533xmlCopyDoc(xmlDocPtr doc, int recursive) {
2534 xmlDocPtr ret;
2535
2536 if (doc == NULL) return(NULL);
2537 ret = xmlNewDoc(doc->version);
2538 if (ret == NULL) return(NULL);
2539 if (doc->name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +00002540 ret->name = xmlMemStrdup(doc->name);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002541 if (doc->encoding != NULL)
2542 ret->encoding = xmlStrdup(doc->encoding);
2543 ret->compression = doc->compression;
2544 ret->standalone = doc->standalone;
2545 if (!recursive) return(ret);
2546
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002547 if (doc->intSubset != NULL)
2548 ret->intSubset = xmlCopyDtd(doc->intSubset);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002549 if (doc->oldNs != NULL)
2550 ret->oldNs = xmlCopyNamespaceList(doc->oldNs);
Daniel Veillardcf461992000-03-14 18:30:20 +00002551 if (doc->children != NULL)
Daniel Veillard06047432000-04-24 11:33:38 +00002552 ret->children = xmlStaticCopyNodeList(doc->children, ret,
2553 (xmlNodePtr)ret);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002554 return(ret);
2555}
2556
2557/************************************************************************
2558 * *
Daniel Veillard260a68f1998-08-13 03:39:55 +00002559 * Content access functions *
2560 * *
2561 ************************************************************************/
2562
Daniel Veillard97b58771998-10-20 06:14:16 +00002563/**
Daniel Veillard944b5ff1999-12-15 19:08:24 +00002564 * xmlDocGetRootElement:
2565 * @doc: the document
2566 *
Daniel Veillardcf461992000-03-14 18:30:20 +00002567 * Get the root element of the document (doc->children is a list
Daniel Veillard944b5ff1999-12-15 19:08:24 +00002568 * containing possibly comments, PIs, etc ...).
2569 *
2570 * Returns the xmlNodePtr for the root or NULL
2571 */
2572xmlNodePtr
2573xmlDocGetRootElement(xmlDocPtr doc) {
2574 xmlNodePtr ret;
2575
2576 if (doc == NULL) return(NULL);
Daniel Veillardcf461992000-03-14 18:30:20 +00002577 ret = doc->children;
Daniel Veillard944b5ff1999-12-15 19:08:24 +00002578 while (ret != NULL) {
2579 if (ret->type == XML_ELEMENT_NODE)
2580 return(ret);
2581 ret = ret->next;
2582 }
2583 return(ret);
2584}
2585
2586/**
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00002587 * xmlDocSetRootElement:
2588 * @doc: the document
2589 * @root: the new document root element
2590 *
Daniel Veillardcf461992000-03-14 18:30:20 +00002591 * Set the root element of the document (doc->children is a list
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00002592 * containing possibly comments, PIs, etc ...).
2593 *
2594 * Returns the old root element if any was found
2595 */
2596xmlNodePtr
2597xmlDocSetRootElement(xmlDocPtr doc, xmlNodePtr root) {
2598 xmlNodePtr old = NULL;
2599
2600 if (doc == NULL) return(NULL);
Daniel Veillardcf461992000-03-14 18:30:20 +00002601 old = doc->children;
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00002602 while (old != NULL) {
2603 if (old->type == XML_ELEMENT_NODE)
2604 break;
2605 old = old->next;
2606 }
2607 if (old == NULL) {
Daniel Veillardcf461992000-03-14 18:30:20 +00002608 if (doc->children == NULL) {
2609 doc->children = root;
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00002610 } else {
Daniel Veillardcf461992000-03-14 18:30:20 +00002611 xmlAddSibling(doc->children, root);
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00002612 }
2613 } else {
2614 xmlReplaceNode(old, root);
2615 }
2616 return(old);
2617}
2618
2619/**
Daniel Veillardb96e6431999-08-29 21:02:19 +00002620 * xmlNodeSetLang:
2621 * @cur: the node being changed
2622 * @lang: the langage description
2623 *
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00002624 * Set the language of a node, i.e. the values of the xml:lang
2625 * attribute.
Daniel Veillardb96e6431999-08-29 21:02:19 +00002626 */
2627void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002628xmlNodeSetLang(xmlNodePtr cur, const xmlChar *lang) {
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00002629 if (cur == NULL) return;
2630 switch(cur->type) {
2631 case XML_TEXT_NODE:
2632 case XML_CDATA_SECTION_NODE:
2633 case XML_COMMENT_NODE:
2634 case XML_DOCUMENT_NODE:
2635 case XML_DOCUMENT_TYPE_NODE:
2636 case XML_DOCUMENT_FRAG_NODE:
2637 case XML_NOTATION_NODE:
2638 case XML_HTML_DOCUMENT_NODE:
Daniel Veillardcf461992000-03-14 18:30:20 +00002639 case XML_DTD_NODE:
2640 case XML_ELEMENT_DECL:
2641 case XML_ATTRIBUTE_DECL:
2642 case XML_ENTITY_DECL:
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00002643 return;
2644 case XML_ELEMENT_NODE:
2645 case XML_ATTRIBUTE_NODE:
2646 case XML_PI_NODE:
2647 case XML_ENTITY_REF_NODE:
2648 case XML_ENTITY_NODE:
2649 break;
2650 }
Daniel Veillardb96e6431999-08-29 21:02:19 +00002651 xmlSetProp(cur, BAD_CAST "xml:lang", lang);
2652}
2653
2654/**
2655 * xmlNodeGetLang:
2656 * @cur: the node being checked
2657 *
2658 * Searches the language of a node, i.e. the values of the xml:lang
2659 * attribute or the one carried by the nearest ancestor.
2660 *
2661 * Returns a pointer to the lang value, or NULL if not found
Daniel Veillarda819dac1999-11-24 18:04:22 +00002662 * It's up to the caller to free the memory.
Daniel Veillardb96e6431999-08-29 21:02:19 +00002663 */
Daniel Veillarda819dac1999-11-24 18:04:22 +00002664xmlChar *
Daniel Veillardb96e6431999-08-29 21:02:19 +00002665xmlNodeGetLang(xmlNodePtr cur) {
Daniel Veillarda819dac1999-11-24 18:04:22 +00002666 xmlChar *lang;
Daniel Veillardb96e6431999-08-29 21:02:19 +00002667
2668 while (cur != NULL) {
2669 lang = xmlGetProp(cur, BAD_CAST "xml:lang");
2670 if (lang != NULL)
2671 return(lang);
2672 cur = cur->parent;
2673 }
2674 return(NULL);
2675}
2676
2677/**
Daniel Veillardcf461992000-03-14 18:30:20 +00002678 * xmlNodeGetSpacePreserve:
2679 * @cur: the node being checked
2680 *
2681 * Searches the language of a node, i.e. the values of the xml:space
2682 * attribute or the one carried by the nearest ancestor.
2683 *
2684 * Returns -1 if xml:space is not inheried, 0 if "default", 1 if "preserve"
2685 */
2686int
2687xmlNodeGetSpacePreserve(xmlNodePtr cur) {
2688 xmlChar *space;
2689
2690 while (cur != NULL) {
2691 space = xmlGetProp(cur, BAD_CAST "xml:space");
2692 if (space != NULL) {
2693 if (!xmlStrcmp(space, BAD_CAST "preserve")) {
2694 xmlFree(space);
2695 return(1);
2696 }
2697 if (!xmlStrcmp(space, BAD_CAST "default")) {
2698 xmlFree(space);
2699 return(0);
2700 }
2701 xmlFree(space);
2702 }
2703 cur = cur->parent;
2704 }
2705 return(-1);
2706}
2707
2708/**
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00002709 * xmlNodeSetName:
2710 * @cur: the node being changed
2711 * @name: the new tag name
2712 *
2713 * Searches the language of a node, i.e. the values of the xml:lang
2714 * attribute or the one carried by the nearest ancestor.
2715 */
2716void
2717xmlNodeSetName(xmlNodePtr cur, const xmlChar *name) {
2718 if (cur == NULL) return;
2719 if (name == NULL) return;
2720 switch(cur->type) {
2721 case XML_TEXT_NODE:
2722 case XML_CDATA_SECTION_NODE:
2723 case XML_COMMENT_NODE:
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00002724 case XML_DOCUMENT_TYPE_NODE:
2725 case XML_DOCUMENT_FRAG_NODE:
2726 case XML_NOTATION_NODE:
2727 case XML_HTML_DOCUMENT_NODE:
2728 return;
2729 case XML_ELEMENT_NODE:
2730 case XML_ATTRIBUTE_NODE:
2731 case XML_PI_NODE:
2732 case XML_ENTITY_REF_NODE:
2733 case XML_ENTITY_NODE:
Daniel Veillardcf461992000-03-14 18:30:20 +00002734 case XML_DTD_NODE:
2735 case XML_DOCUMENT_NODE:
2736 case XML_ELEMENT_DECL:
2737 case XML_ATTRIBUTE_DECL:
2738 case XML_ENTITY_DECL:
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00002739 break;
2740 }
2741 if (cur->name != NULL) xmlFree((xmlChar *) cur->name);
2742 cur->name = xmlStrdup(name);
2743}
2744
2745/**
Daniel Veillard10a2c651999-12-12 13:03:50 +00002746 * xmlNodeGetBase:
2747 * @doc: the document the node pertains to
2748 * @cur: the node being checked
2749 *
2750 * Searches for the BASE URL. The code should work on both XML
2751 * and HTML document even if base mechanisms are completely different.
2752 *
2753 * Returns a pointer to the base URL, or NULL if not found
2754 * It's up to the caller to free the memory.
2755 */
2756xmlChar *
2757xmlNodeGetBase(xmlDocPtr doc, xmlNodePtr cur) {
2758 xmlChar *base;
2759
2760 if ((cur == NULL) && (doc == NULL))
2761 return(NULL);
2762 if (doc == NULL) doc = cur->doc;
2763 if ((doc != NULL) && (doc->type == XML_HTML_DOCUMENT_NODE)) {
Daniel Veillardcf461992000-03-14 18:30:20 +00002764 cur = doc->children;
Daniel Veillard10a2c651999-12-12 13:03:50 +00002765 while ((cur != NULL) && (cur->name != NULL)) {
2766 if (cur->type != XML_ELEMENT_NODE) {
2767 cur = cur->next;
2768 continue;
2769 }
2770 if ((!xmlStrcmp(cur->name, BAD_CAST "html")) ||
2771 (!xmlStrcmp(cur->name, BAD_CAST "HTML"))) {
Daniel Veillardcf461992000-03-14 18:30:20 +00002772 cur = cur->children;
Daniel Veillard10a2c651999-12-12 13:03:50 +00002773 continue;
2774 }
2775 if ((!xmlStrcmp(cur->name, BAD_CAST "head")) ||
2776 (!xmlStrcmp(cur->name, BAD_CAST "HEAD"))) {
Daniel Veillardcf461992000-03-14 18:30:20 +00002777 cur = cur->children;
Daniel Veillard10a2c651999-12-12 13:03:50 +00002778 continue;
2779 }
2780 if ((!xmlStrcmp(cur->name, BAD_CAST "base")) ||
2781 (!xmlStrcmp(cur->name, BAD_CAST "BASE"))) {
2782 base = xmlGetProp(cur, BAD_CAST "href");
2783 if (base != NULL) return(base);
2784 return(xmlGetProp(cur, BAD_CAST "HREF"));
2785 }
Daniel Veillardcf461992000-03-14 18:30:20 +00002786 cur = cur->next;
Daniel Veillard10a2c651999-12-12 13:03:50 +00002787 }
Daniel Veillardcf461992000-03-14 18:30:20 +00002788 if ((doc != NULL) && (doc->URL != NULL))
2789 return(xmlStrdup(doc->URL));
Daniel Veillard10a2c651999-12-12 13:03:50 +00002790 return(NULL);
2791 }
2792 while (cur != NULL) {
2793 base = xmlGetProp(cur, BAD_CAST "xml:base");
2794 if (base != NULL)
2795 return(base);
2796 cur = cur->parent;
2797 }
Daniel Veillardcf461992000-03-14 18:30:20 +00002798 if ((doc != NULL) && (doc->URL != NULL))
2799 return(xmlStrdup(doc->URL));
Daniel Veillard10a2c651999-12-12 13:03:50 +00002800 return(NULL);
2801}
2802
2803/**
Daniel Veillard16253641998-10-28 22:58:05 +00002804 * xmlNodeGetContent:
2805 * @cur: the node being read
2806 *
2807 * Read the value of a node, this can be either the text carried
2808 * directly by this node if it's a TEXT node or the aggregate string
2809 * of the values carried by this node child's (TEXT and ENTITY_REF).
2810 * Entity references are substitued.
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002811 * Returns a new xmlChar * or NULL if no content is available.
Daniel Veillard5099ae81999-04-21 20:12:07 +00002812 * It's up to the caller to free the memory.
Daniel Veillard16253641998-10-28 22:58:05 +00002813 */
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002814xmlChar *
Daniel Veillard16253641998-10-28 22:58:05 +00002815xmlNodeGetContent(xmlNodePtr cur) {
2816 if (cur == NULL) return(NULL);
2817 switch (cur->type) {
2818 case XML_DOCUMENT_FRAG_NODE:
2819 case XML_ELEMENT_NODE:
Daniel Veillardcf461992000-03-14 18:30:20 +00002820 return(xmlNodeListGetString(cur->doc, cur->children, 1));
Daniel Veillard16253641998-10-28 22:58:05 +00002821 break;
Daniel Veillardb96e6431999-08-29 21:02:19 +00002822 case XML_ATTRIBUTE_NODE: {
2823 xmlAttrPtr attr = (xmlAttrPtr) cur;
Daniel Veillardcf461992000-03-14 18:30:20 +00002824 if (attr->parent != NULL)
2825 return(xmlNodeListGetString(attr->parent->doc, attr->children, 1));
Daniel Veillardb96e6431999-08-29 21:02:19 +00002826 else
Daniel Veillardcf461992000-03-14 18:30:20 +00002827 return(xmlNodeListGetString(NULL, attr->children, 1));
Daniel Veillardb96e6431999-08-29 21:02:19 +00002828 break;
2829 }
Daniel Veillarddbfd6411999-12-28 16:35:14 +00002830 case XML_COMMENT_NODE:
Daniel Veillardb96e6431999-08-29 21:02:19 +00002831 case XML_PI_NODE:
2832 if (cur->content != NULL)
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002833#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardb96e6431999-08-29 21:02:19 +00002834 return(xmlStrdup(cur->content));
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002835#else
2836 return(xmlStrdup(xmlBufferContent(cur->content)));
2837#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +00002838 return(NULL);
Daniel Veillard16253641998-10-28 22:58:05 +00002839 case XML_ENTITY_REF_NODE:
Daniel Veillarddbfd6411999-12-28 16:35:14 +00002840 /*
2841 * Locate the entity, and get it's content
2842 * @@@
2843 */
2844 return(NULL);
Daniel Veillard16253641998-10-28 22:58:05 +00002845 case XML_ENTITY_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002846 case XML_DOCUMENT_NODE:
Daniel Veillard7c1206f1999-10-14 09:10:25 +00002847 case XML_HTML_DOCUMENT_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002848 case XML_DOCUMENT_TYPE_NODE:
2849 case XML_NOTATION_NODE:
Daniel Veillardcf461992000-03-14 18:30:20 +00002850 case XML_DTD_NODE:
2851 return(NULL);
2852 case XML_ELEMENT_DECL:
2853 /* TODO !!! */
2854 return(NULL);
2855 case XML_ATTRIBUTE_DECL:
2856 /* TODO !!! */
2857 return(NULL);
2858 case XML_ENTITY_DECL:
2859 /* TODO !!! */
Daniel Veillard16253641998-10-28 22:58:05 +00002860 return(NULL);
Daniel Veillardb05deb71999-08-10 19:04:08 +00002861 case XML_CDATA_SECTION_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002862 case XML_TEXT_NODE:
2863 if (cur->content != NULL)
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002864#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard16253641998-10-28 22:58:05 +00002865 return(xmlStrdup(cur->content));
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002866#else
2867 return(xmlStrdup(xmlBufferContent(cur->content)));
2868#endif
Daniel Veillard16253641998-10-28 22:58:05 +00002869 return(NULL);
2870 }
2871 return(NULL);
2872}
2873
2874/**
Daniel Veillard97b58771998-10-20 06:14:16 +00002875 * xmlNodeSetContent:
2876 * @cur: the node being modified
2877 * @content: the new value of the content
2878 *
2879 * Replace the content of a node.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002880 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002881void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002882xmlNodeSetContent(xmlNodePtr cur, const xmlChar *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002883 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00002884#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00002885 fprintf(stderr, "xmlNodeSetContent : node == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00002886#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00002887 return;
2888 }
Daniel Veillard16253641998-10-28 22:58:05 +00002889 switch (cur->type) {
2890 case XML_DOCUMENT_FRAG_NODE:
2891 case XML_ELEMENT_NODE:
2892 if (cur->content != NULL) {
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002893#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard6454aec1999-09-02 22:04:43 +00002894 xmlFree(cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002895#else
2896 xmlBufferFree(cur->content);
2897#endif
Daniel Veillard16253641998-10-28 22:58:05 +00002898 cur->content = NULL;
2899 }
Daniel Veillardcf461992000-03-14 18:30:20 +00002900 if (cur->children != NULL) xmlFreeNodeList(cur->children);
2901 cur->children = xmlStringGetNodeList(cur->doc, content);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002902 UPDATE_LAST_CHILD(cur)
Daniel Veillard16253641998-10-28 22:58:05 +00002903 break;
2904 case XML_ATTRIBUTE_NODE:
2905 break;
2906 case XML_TEXT_NODE:
2907 case XML_CDATA_SECTION_NODE:
2908 case XML_ENTITY_REF_NODE:
2909 case XML_ENTITY_NODE:
2910 case XML_PI_NODE:
2911 case XML_COMMENT_NODE:
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002912 if (cur->content != NULL) {
2913#ifndef XML_USE_BUFFER_CONTENT
2914 xmlFree(cur->content);
2915#else
2916 xmlBufferFree(cur->content);
2917#endif
2918 }
Daniel Veillardcf461992000-03-14 18:30:20 +00002919 if (cur->children != NULL) xmlFreeNodeList(cur->children);
2920 cur->last = cur->children = NULL;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002921 if (content != NULL) {
2922#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard16253641998-10-28 22:58:05 +00002923 cur->content = xmlStrdup(content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002924#else
2925 cur->content = xmlBufferCreateSize(0);
2926 xmlBufferSetAllocationScheme(cur->content,
2927 xmlGetBufferAllocationScheme());
2928 xmlBufferAdd(cur->content, content, -1);
2929#endif
2930 } else
Daniel Veillard16253641998-10-28 22:58:05 +00002931 cur->content = NULL;
Daniel Veillardb96e6431999-08-29 21:02:19 +00002932 break;
Daniel Veillard16253641998-10-28 22:58:05 +00002933 case XML_DOCUMENT_NODE:
Daniel Veillard7c1206f1999-10-14 09:10:25 +00002934 case XML_HTML_DOCUMENT_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002935 case XML_DOCUMENT_TYPE_NODE:
2936 break;
2937 case XML_NOTATION_NODE:
2938 break;
Daniel Veillardcf461992000-03-14 18:30:20 +00002939 case XML_DTD_NODE:
2940 break;
2941 case XML_ELEMENT_DECL:
2942 /* TODO !!! */
2943 break;
2944 case XML_ATTRIBUTE_DECL:
2945 /* TODO !!! */
2946 break;
2947 case XML_ENTITY_DECL:
2948 /* TODO !!! */
2949 break;
Daniel Veillard16253641998-10-28 22:58:05 +00002950 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002951}
2952
Daniel Veillard97b58771998-10-20 06:14:16 +00002953/**
2954 * xmlNodeSetContentLen:
2955 * @cur: the node being modified
2956 * @content: the new value of the content
2957 * @len: the size of @content
2958 *
2959 * Replace the content of a node.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002960 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002961void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002962xmlNodeSetContentLen(xmlNodePtr cur, const xmlChar *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002963 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00002964#ifdef DEBUG_TREE
Daniel Veillard16253641998-10-28 22:58:05 +00002965 fprintf(stderr, "xmlNodeSetContentLen : node == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00002966#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00002967 return;
2968 }
Daniel Veillard16253641998-10-28 22:58:05 +00002969 switch (cur->type) {
2970 case XML_DOCUMENT_FRAG_NODE:
2971 case XML_ELEMENT_NODE:
2972 if (cur->content != NULL) {
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002973#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard6454aec1999-09-02 22:04:43 +00002974 xmlFree(cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002975#else
2976 xmlBufferFree(cur->content);
2977#endif
Daniel Veillard16253641998-10-28 22:58:05 +00002978 cur->content = NULL;
2979 }
Daniel Veillardcf461992000-03-14 18:30:20 +00002980 if (cur->children != NULL) xmlFreeNodeList(cur->children);
2981 cur->children = xmlStringLenGetNodeList(cur->doc, content, len);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002982 UPDATE_LAST_CHILD(cur)
Daniel Veillard16253641998-10-28 22:58:05 +00002983 break;
2984 case XML_ATTRIBUTE_NODE:
2985 break;
2986 case XML_TEXT_NODE:
2987 case XML_CDATA_SECTION_NODE:
2988 case XML_ENTITY_REF_NODE:
2989 case XML_ENTITY_NODE:
2990 case XML_PI_NODE:
2991 case XML_COMMENT_NODE:
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002992 case XML_NOTATION_NODE:
2993 if (cur->content != NULL) {
2994#ifndef XML_USE_BUFFER_CONTENT
2995 xmlFree(cur->content);
2996#else
2997 xmlBufferFree(cur->content);
2998#endif
2999 }
Daniel Veillardcf461992000-03-14 18:30:20 +00003000 if (cur->children != NULL) xmlFreeNodeList(cur->children);
3001 cur->children = cur->last = NULL;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003002 if (content != NULL) {
3003#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard16253641998-10-28 22:58:05 +00003004 cur->content = xmlStrndup(content, len);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003005#else
3006 cur->content = xmlBufferCreateSize(len);
3007 xmlBufferSetAllocationScheme(cur->content,
3008 xmlGetBufferAllocationScheme());
3009 xmlBufferAdd(cur->content, content, len);
3010#endif
3011 } else
Daniel Veillard16253641998-10-28 22:58:05 +00003012 cur->content = NULL;
Daniel Veillardb96e6431999-08-29 21:02:19 +00003013 break;
Daniel Veillard16253641998-10-28 22:58:05 +00003014 case XML_DOCUMENT_NODE:
Daniel Veillardcf461992000-03-14 18:30:20 +00003015 case XML_DTD_NODE:
Daniel Veillard7c1206f1999-10-14 09:10:25 +00003016 case XML_HTML_DOCUMENT_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00003017 case XML_DOCUMENT_TYPE_NODE:
3018 break;
Daniel Veillardcf461992000-03-14 18:30:20 +00003019 case XML_ELEMENT_DECL:
3020 /* TODO !!! */
3021 break;
3022 case XML_ATTRIBUTE_DECL:
3023 /* TODO !!! */
3024 break;
3025 case XML_ENTITY_DECL:
3026 /* TODO !!! */
3027 break;
Daniel Veillard260a68f1998-08-13 03:39:55 +00003028 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003029}
3030
Daniel Veillard97b58771998-10-20 06:14:16 +00003031/**
3032 * xmlNodeAddContentLen:
3033 * @cur: the node being modified
3034 * @content: extra content
3035 * @len: the size of @content
3036 *
3037 * Append the extra substring to the node content.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003038 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003039void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003040xmlNodeAddContentLen(xmlNodePtr cur, const xmlChar *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003041 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00003042#ifdef DEBUG_TREE
Daniel Veillard16253641998-10-28 22:58:05 +00003043 fprintf(stderr, "xmlNodeAddContentLen : node == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00003044#endif
Daniel Veillard16253641998-10-28 22:58:05 +00003045 return;
3046 }
3047 if (len <= 0) return;
3048 switch (cur->type) {
3049 case XML_DOCUMENT_FRAG_NODE:
3050 case XML_ELEMENT_NODE: {
Daniel Veillard32bc74e2000-07-14 14:49:25 +00003051 xmlNodePtr last = NULL, newNode;
Daniel Veillard16253641998-10-28 22:58:05 +00003052
Daniel Veillardcf461992000-03-14 18:30:20 +00003053 if (cur->children != NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003054 last = cur->last;
Daniel Veillard16253641998-10-28 22:58:05 +00003055 } else {
3056 if (cur->content != NULL) {
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003057#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardcf461992000-03-14 18:30:20 +00003058 cur->children = xmlStringGetNodeList(cur->doc, cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003059#else
Daniel Veillardcf461992000-03-14 18:30:20 +00003060 cur->children = xmlStringGetNodeList(cur->doc,
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003061 xmlBufferContent(cur->content));
3062#endif
Daniel Veillard1e346af1999-02-22 10:33:01 +00003063 UPDATE_LAST_CHILD(cur)
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003064#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard6454aec1999-09-02 22:04:43 +00003065 xmlFree(cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003066#else
3067 xmlBufferFree(cur->content);
3068#endif
Daniel Veillard16253641998-10-28 22:58:05 +00003069 cur->content = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003070 last = cur->last;
Daniel Veillard16253641998-10-28 22:58:05 +00003071 }
3072 }
Daniel Veillard32bc74e2000-07-14 14:49:25 +00003073 newNode = xmlNewTextLen(content, len);
3074 if (newNode != NULL) {
3075 xmlAddChild(cur, newNode);
3076 if ((last != NULL) && (last->next == newNode)) {
3077 xmlTextMerge(last, newNode);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003078 }
Daniel Veillard16253641998-10-28 22:58:05 +00003079 }
3080 break;
3081 }
3082 case XML_ATTRIBUTE_NODE:
3083 break;
3084 case XML_TEXT_NODE:
3085 case XML_CDATA_SECTION_NODE:
3086 case XML_ENTITY_REF_NODE:
3087 case XML_ENTITY_NODE:
3088 case XML_PI_NODE:
3089 case XML_COMMENT_NODE:
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003090 case XML_NOTATION_NODE:
3091 if (content != NULL) {
3092#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard16253641998-10-28 22:58:05 +00003093 cur->content = xmlStrncat(cur->content, content, len);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003094#else
3095 xmlBufferAdd(cur->content, content, len);
3096#endif
3097 }
Daniel Veillard16253641998-10-28 22:58:05 +00003098 case XML_DOCUMENT_NODE:
Daniel Veillardcf461992000-03-14 18:30:20 +00003099 case XML_DTD_NODE:
Daniel Veillard7c1206f1999-10-14 09:10:25 +00003100 case XML_HTML_DOCUMENT_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00003101 case XML_DOCUMENT_TYPE_NODE:
3102 break;
Daniel Veillardcf461992000-03-14 18:30:20 +00003103 case XML_ELEMENT_DECL:
3104 case XML_ATTRIBUTE_DECL:
3105 case XML_ENTITY_DECL:
3106 break;
Daniel Veillard16253641998-10-28 22:58:05 +00003107 }
3108}
3109
3110/**
3111 * xmlNodeAddContent:
3112 * @cur: the node being modified
3113 * @content: extra content
3114 *
3115 * Append the extra substring to the node content.
3116 */
3117void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003118xmlNodeAddContent(xmlNodePtr cur, const xmlChar *content) {
Daniel Veillard16253641998-10-28 22:58:05 +00003119 int len;
3120
3121 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00003122#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00003123 fprintf(stderr, "xmlNodeAddContent : node == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00003124#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00003125 return;
3126 }
Daniel Veillard16253641998-10-28 22:58:05 +00003127 if (content == NULL) return;
3128 len = xmlStrlen(content);
3129 xmlNodeAddContentLen(cur, content, len);
3130}
3131
3132/**
3133 * xmlTextMerge:
3134 * @first: the first text node
3135 * @second: the second text node being merged
3136 *
3137 * Merge two text nodes into one
Daniel Veillard1e346af1999-02-22 10:33:01 +00003138 * Returns the first text node augmented
Daniel Veillard16253641998-10-28 22:58:05 +00003139 */
3140xmlNodePtr
3141xmlTextMerge(xmlNodePtr first, xmlNodePtr second) {
3142 if (first == NULL) return(second);
3143 if (second == NULL) return(first);
3144 if (first->type != XML_TEXT_NODE) return(first);
3145 if (second->type != XML_TEXT_NODE) return(first);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003146#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard16253641998-10-28 22:58:05 +00003147 xmlNodeAddContent(first, second->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003148#else
3149 xmlNodeAddContent(first, xmlBufferContent(second->content));
3150#endif
Daniel Veillard16253641998-10-28 22:58:05 +00003151 xmlUnlinkNode(second);
3152 xmlFreeNode(second);
3153 return(first);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003154}
3155
Daniel Veillard97b58771998-10-20 06:14:16 +00003156/**
Daniel Veillardb96e6431999-08-29 21:02:19 +00003157 * xmlGetNsList:
3158 * @doc: the document
3159 * @node: the current node
3160 *
3161 * Search all the namespace applying to a given element.
3162 * Returns an NULL terminated array of all the xmlNsPtr found
3163 * that need to be freed by the caller or NULL if no
3164 * namespace if defined
3165 */
3166xmlNsPtr *
3167xmlGetNsList(xmlDocPtr doc, xmlNodePtr node) {
3168 xmlNsPtr cur;
3169 xmlNsPtr *ret = NULL;
3170 int nbns = 0;
3171 int maxns = 10;
3172 int i;
3173
3174 while (node != NULL) {
3175 cur = node->nsDef;
3176 while (cur != NULL) {
3177 if (ret == NULL) {
Daniel Veillard6454aec1999-09-02 22:04:43 +00003178 ret = (xmlNsPtr *) xmlMalloc((maxns + 1) * sizeof(xmlNsPtr));
Daniel Veillardb96e6431999-08-29 21:02:19 +00003179 if (ret == NULL) {
3180 fprintf(stderr, "xmlGetNsList : out of memory!\n");
3181 return(NULL);
3182 }
3183 ret[nbns] = NULL;
3184 }
3185 for (i = 0;i < nbns;i++) {
3186 if ((cur->prefix == ret[i]->prefix) ||
3187 (!xmlStrcmp(cur->prefix, ret[i]->prefix))) break;
3188 }
3189 if (i >= nbns) {
3190 if (nbns >= maxns) {
3191 maxns *= 2;
Daniel Veillard6454aec1999-09-02 22:04:43 +00003192 ret = (xmlNsPtr *) xmlRealloc(ret,
Daniel Veillardb96e6431999-08-29 21:02:19 +00003193 (maxns + 1) * sizeof(xmlNsPtr));
3194 if (ret == NULL) {
3195 fprintf(stderr, "xmlGetNsList : realloc failed!\n");
3196 return(NULL);
3197 }
3198 }
3199 ret[nbns++] = cur;
3200 ret[nbns] = NULL;
3201 }
3202
3203 cur = cur->next;
3204 }
3205 node = node->parent;
3206 }
3207 return(ret);
3208}
3209
3210/**
Daniel Veillard97b58771998-10-20 06:14:16 +00003211 * xmlSearchNs:
3212 * @doc: the document
3213 * @node: the current node
3214 * @nameSpace: the namespace string
Daniel Veillard260a68f1998-08-13 03:39:55 +00003215 *
Daniel Veillard97b58771998-10-20 06:14:16 +00003216 * Search a Ns registered under a given name space for a document.
3217 * recurse on the parents until it finds the defined namespace
3218 * or return NULL otherwise.
3219 * @nameSpace can be NULL, this is a search for the default namespace.
Daniel Veillard1e346af1999-02-22 10:33:01 +00003220 * Returns the namespace pointer or NULL.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003221 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003222xmlNsPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003223xmlSearchNs(xmlDocPtr doc, xmlNodePtr node, const xmlChar *nameSpace) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003224 xmlNsPtr cur;
3225
Daniel Veillard62ba71e1999-12-16 17:52:19 +00003226 if (node == NULL) return(NULL);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003227 while (node != NULL) {
Daniel Veillardcf461992000-03-14 18:30:20 +00003228 if (node->type == XML_ELEMENT_NODE) {
3229 cur = node->nsDef;
3230 while (cur != NULL) {
3231 if ((cur->prefix == NULL) && (nameSpace == NULL))
3232 return(cur);
3233 if ((cur->prefix != NULL) && (nameSpace != NULL) &&
3234 (!xmlStrcmp(cur->prefix, nameSpace)))
3235 return(cur);
3236 cur = cur->next;
3237 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003238 }
3239 node = node->parent;
3240 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003241 return(NULL);
3242}
3243
Daniel Veillard97b58771998-10-20 06:14:16 +00003244/**
3245 * xmlSearchNsByHref:
3246 * @doc: the document
3247 * @node: the current node
3248 * @href: the namespace value
3249 *
3250 * Search a Ns aliasing a given URI. Recurse on the parents until it finds
3251 * the defined namespace or return NULL otherwise.
Daniel Veillard1e346af1999-02-22 10:33:01 +00003252 * Returns the namespace pointer or NULL.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003253 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003254xmlNsPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003255xmlSearchNsByHref(xmlDocPtr doc, xmlNodePtr node, const xmlChar *href) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003256 xmlNsPtr cur;
Daniel Veillarddbfd6411999-12-28 16:35:14 +00003257 xmlNodePtr orig = node;
Daniel Veillard260a68f1998-08-13 03:39:55 +00003258
Daniel Veillard10a2c651999-12-12 13:03:50 +00003259 if ((node == NULL) || (href == NULL)) return(NULL);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003260 while (node != NULL) {
3261 cur = node->nsDef;
3262 while (cur != NULL) {
3263 if ((cur->href != NULL) && (href != NULL) &&
Daniel Veillarddbfd6411999-12-28 16:35:14 +00003264 (!xmlStrcmp(cur->href, href))) {
3265 /*
3266 * Check that the prefix is not shadowed between orig and node
3267 */
3268 xmlNodePtr check = orig;
3269 xmlNsPtr tst;
3270
3271 while (check != node) {
3272 tst = check->nsDef;
3273 while (tst != NULL) {
3274 if ((tst->prefix == NULL) && (cur->prefix == NULL))
3275 goto shadowed;
3276 if ((tst->prefix != NULL) && (cur->prefix != NULL) &&
3277 (!xmlStrcmp(tst->prefix, cur->prefix)))
3278 goto shadowed;
3279 tst = tst->next;
3280 }
3281 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003282 return(cur);
Daniel Veillarddbfd6411999-12-28 16:35:14 +00003283 }
3284shadowed:
Daniel Veillard260a68f1998-08-13 03:39:55 +00003285 cur = cur->next;
3286 }
3287 node = node->parent;
3288 }
Daniel Veillarddbfd6411999-12-28 16:35:14 +00003289 return(NULL);
3290}
3291
3292/**
3293 * xmlNewReconciliedNs
3294 * @doc: the document
3295 * @tree: a node expected to hold the new namespace
3296 * @ns: the original namespace
3297 *
3298 * This function tries to locate a namespace definition in a tree
3299 * ancestors, or create a new namespace definition node similar to
3300 * @ns trying to reuse the same prefix. However if the given prefix is
3301 * null (default namespace) or reused within the subtree defined by
3302 * @tree or on one of its ancestors then a new prefix is generated.
3303 * Returns the (new) namespace definition or NULL in case of error
3304 */
3305xmlNsPtr
3306xmlNewReconciliedNs(xmlDocPtr doc, xmlNodePtr tree, xmlNsPtr ns) {
3307 xmlNsPtr def;
3308 xmlChar prefix[50];
3309 int counter = 1;
3310
3311 if (tree == NULL) {
3312#ifdef DEBUG_TREE
3313 fprintf(stderr, "xmlNewReconciliedNs : tree == NULL\n");
3314#endif
3315 return(NULL);
3316 }
3317 if (ns == NULL) {
3318#ifdef DEBUG_TREE
3319 fprintf(stderr, "xmlNewReconciliedNs : ns == NULL\n");
3320#endif
3321 return(NULL);
3322 }
3323 /*
3324 * Search an existing namespace definition inherited.
3325 */
3326 def = xmlSearchNsByHref(doc, tree, ns->href);
3327 if (def != NULL)
3328 return(def);
3329
3330 /*
3331 * Find a close prefix which is not already in use.
3332 * Let's strip namespace prefixes longer than 20 chars !
3333 */
3334 sprintf((char *) prefix, "%.20s", ns->prefix);
3335 def = xmlSearchNs(doc, tree, prefix);
3336 while (def != NULL) {
3337 if (counter > 1000) return(NULL);
3338 sprintf((char *) prefix, "%.20s%d", ns->prefix, counter++);
3339 def = xmlSearchNs(doc, tree, prefix);
3340 }
3341
3342 /*
3343 * Ok, now we are ready to create a new one.
3344 */
3345 def = xmlNewNs(tree, ns->href, prefix);
3346 return(def);
3347}
3348
3349/**
3350 * xmlReconciliateNs
3351 * @doc: the document
3352 * @tree: a node defining the subtree to reconciliate
3353 *
3354 * This function checks that all the namespaces declared within the given
3355 * tree are properly declared. This is needed for example after Copy or Cut
3356 * and then paste operations. The subtree may still hold pointers to
3357 * namespace declarations outside the subtree or invalid/masked. As much
3358 * as possible the function try tu reuse the existing namespaces found in
3359 * the new environment. If not possible the new namespaces are redeclared
3360 * on @tree at the top of the given subtree.
3361 * Returns the number of namespace declarations created or -1 in case of error.
3362 */
3363int
3364xmlReconciliateNs(xmlDocPtr doc, xmlNodePtr tree) {
3365 xmlNsPtr *oldNs = NULL;
3366 xmlNsPtr *newNs = NULL;
3367 int sizeCache = 0;
3368 int nbCache = 0;
3369
3370 xmlNsPtr n;
3371 xmlNodePtr node = tree;
3372 xmlAttrPtr attr;
3373 int ret = 0, i;
3374
3375 while (node != NULL) {
3376 /*
3377 * Reconciliate the node namespace
3378 */
3379 if (node->ns != NULL) {
3380 /*
3381 * initialize the cache if needed
3382 */
3383 if (sizeCache == 0) {
3384 sizeCache = 10;
3385 oldNs = (xmlNsPtr *) xmlMalloc(sizeCache *
3386 sizeof(xmlNsPtr));
3387 if (oldNs == NULL) {
3388 fprintf(stderr, "xmlReconciliateNs : memory pbm\n");
3389 return(-1);
3390 }
3391 newNs = (xmlNsPtr *) xmlMalloc(sizeCache *
3392 sizeof(xmlNsPtr));
3393 if (newNs == NULL) {
3394 fprintf(stderr, "xmlReconciliateNs : memory pbm\n");
3395 xmlFree(oldNs);
3396 return(-1);
3397 }
3398 }
3399 for (i = 0;i < nbCache;i++) {
3400 if (oldNs[i] == node->ns) {
3401 node->ns = newNs[i];
3402 break;
3403 }
3404 }
3405 if (i == nbCache) {
3406 /*
3407 * Ok we need to recreate a new namespace definition
3408 */
3409 n = xmlNewReconciliedNs(doc, tree, node->ns);
3410 if (n != NULL) { /* :-( what if else ??? */
3411 /*
3412 * check if we need to grow the cache buffers.
3413 */
3414 if (sizeCache <= nbCache) {
3415 sizeCache *= 2;
3416 oldNs = (xmlNsPtr *) xmlRealloc(oldNs, sizeCache *
3417 sizeof(xmlNsPtr));
3418 if (oldNs == NULL) {
3419 fprintf(stderr, "xmlReconciliateNs : memory pbm\n");
3420 xmlFree(newNs);
3421 return(-1);
3422 }
3423 newNs = (xmlNsPtr *) xmlRealloc(newNs, sizeCache *
3424 sizeof(xmlNsPtr));
3425 if (newNs == NULL) {
3426 fprintf(stderr, "xmlReconciliateNs : memory pbm\n");
3427 xmlFree(oldNs);
3428 return(-1);
3429 }
3430 }
3431 newNs[nbCache] = n;
3432 oldNs[nbCache++] = node->ns;
3433 node->ns = n;
3434 }
3435 }
3436 }
3437 /*
3438 * now check for namespace hold by attributes on the node.
3439 */
3440 attr = node->properties;
3441 while (attr != NULL) {
3442 if (attr->ns != NULL) {
3443 /*
3444 * initialize the cache if needed
3445 */
3446 if (sizeCache == 0) {
3447 sizeCache = 10;
3448 oldNs = (xmlNsPtr *) xmlMalloc(sizeCache *
3449 sizeof(xmlNsPtr));
3450 if (oldNs == NULL) {
3451 fprintf(stderr, "xmlReconciliateNs : memory pbm\n");
3452 return(-1);
3453 }
3454 newNs = (xmlNsPtr *) xmlMalloc(sizeCache *
3455 sizeof(xmlNsPtr));
3456 if (newNs == NULL) {
3457 fprintf(stderr, "xmlReconciliateNs : memory pbm\n");
3458 xmlFree(oldNs);
3459 return(-1);
3460 }
3461 }
3462 for (i = 0;i < nbCache;i++) {
3463 if (oldNs[i] == attr->ns) {
3464 node->ns = newNs[i];
3465 break;
3466 }
3467 }
3468 if (i == nbCache) {
3469 /*
3470 * Ok we need to recreate a new namespace definition
3471 */
3472 n = xmlNewReconciliedNs(doc, tree, attr->ns);
3473 if (n != NULL) { /* :-( what if else ??? */
3474 /*
3475 * check if we need to grow the cache buffers.
3476 */
3477 if (sizeCache <= nbCache) {
3478 sizeCache *= 2;
3479 oldNs = (xmlNsPtr *) xmlRealloc(oldNs, sizeCache *
3480 sizeof(xmlNsPtr));
3481 if (oldNs == NULL) {
3482 fprintf(stderr,
3483 "xmlReconciliateNs : memory pbm\n");
3484 xmlFree(newNs);
3485 return(-1);
3486 }
3487 newNs = (xmlNsPtr *) xmlRealloc(newNs, sizeCache *
3488 sizeof(xmlNsPtr));
3489 if (newNs == NULL) {
3490 fprintf(stderr,
3491 "xmlReconciliateNs : memory pbm\n");
3492 xmlFree(oldNs);
3493 return(-1);
3494 }
3495 }
3496 newNs[nbCache] = n;
3497 oldNs[nbCache++] = attr->ns;
3498 attr->ns = n;
3499 }
3500 }
3501 }
3502 attr = attr->next;
3503 }
3504
3505 /*
3506 * Browse the full subtree, deep first
3507 */
Daniel Veillardcf461992000-03-14 18:30:20 +00003508 if (node->children != NULL) {
Daniel Veillarddbfd6411999-12-28 16:35:14 +00003509 /* deep first */
Daniel Veillardcf461992000-03-14 18:30:20 +00003510 node = node->children;
Daniel Veillarddbfd6411999-12-28 16:35:14 +00003511 } else if ((node != tree) && (node->next != NULL)) {
3512 /* then siblings */
3513 node = node->next;
3514 } else if (node != tree) {
3515 /* go up to parents->next if needed */
3516 while (node != tree) {
3517 if (node->parent != NULL)
3518 node = node->parent;
3519 if ((node != tree) && (node->next != NULL)) {
3520 node = node->next;
3521 break;
3522 }
3523 if (node->parent == NULL) {
3524 node = NULL;
3525 break;
3526 }
3527 }
3528 /* exit condition */
3529 if (node == tree)
3530 node = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00003531 }
3532 }
Daniel Veillarddbfd6411999-12-28 16:35:14 +00003533 return(ret);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003534}
3535
Daniel Veillard97b58771998-10-20 06:14:16 +00003536/**
Daniel Veillard32bc74e2000-07-14 14:49:25 +00003537 * xmlHasProp:
3538 * @node: the node
3539 * @name: the attribute name
3540 *
3541 * Search an attribute associated to a node
3542 * This function also looks in DTD attribute declaration for #FIXED or
3543 * default declaration values unless DTD use has been turned off.
3544 *
3545 * Returns the attribute or the attribute declaration or NULL if
3546 * neither was found.
3547 */
3548xmlAttrPtr
3549xmlHasProp(xmlNodePtr node, const xmlChar *name) {
3550 xmlAttrPtr prop;
3551 xmlDocPtr doc;
3552
3553 if ((node == NULL) || (name == NULL)) return(NULL);
3554 /*
3555 * Check on the properties attached to the node
3556 */
3557 prop = node->properties;
3558 while (prop != NULL) {
3559 if (!xmlStrcmp(prop->name, name)) {
3560 return(prop);
3561 }
3562 prop = prop->next;
3563 }
3564 if (!xmlCheckDTD) return(NULL);
3565
3566 /*
3567 * Check if there is a default declaration in the internal
3568 * or external subsets
3569 */
3570 doc = node->doc;
3571 if (doc != NULL) {
3572 xmlAttributePtr attrDecl;
3573 if (doc->intSubset != NULL) {
3574 attrDecl = xmlGetDtdAttrDesc(doc->intSubset, node->name, name);
3575 if ((attrDecl == NULL) && (doc->extSubset != NULL))
3576 attrDecl = xmlGetDtdAttrDesc(doc->extSubset, node->name, name);
3577 if (attrDecl != NULL)
3578 return((xmlAttrPtr) attrDecl);
3579 }
3580 }
3581 return(NULL);
3582}
3583
3584/**
Daniel Veillard97b58771998-10-20 06:14:16 +00003585 * xmlGetProp:
3586 * @node: the node
3587 * @name: the attribute name
3588 *
3589 * Search and get the value of an attribute associated to a node
Daniel Veillardccb09631998-10-27 06:21:04 +00003590 * This does the entity substitution.
Daniel Veillard10a2c651999-12-12 13:03:50 +00003591 * This function looks in DTD attribute declaration for #FIXED or
3592 * default declaration values unless DTD use has been turned off.
3593 *
Daniel Veillard1e346af1999-02-22 10:33:01 +00003594 * Returns the attribute value or NULL if not found.
Daniel Veillarda819dac1999-11-24 18:04:22 +00003595 * It's up to the caller to free the memory.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003596 */
Daniel Veillarda819dac1999-11-24 18:04:22 +00003597xmlChar *
3598xmlGetProp(xmlNodePtr node, const xmlChar *name) {
Daniel Veillard10a2c651999-12-12 13:03:50 +00003599 xmlAttrPtr prop;
3600 xmlDocPtr doc;
Daniel Veillard260a68f1998-08-13 03:39:55 +00003601
Daniel Veillard10a2c651999-12-12 13:03:50 +00003602 if ((node == NULL) || (name == NULL)) return(NULL);
3603 /*
3604 * Check on the properties attached to the node
3605 */
3606 prop = node->properties;
Daniel Veillard260a68f1998-08-13 03:39:55 +00003607 while (prop != NULL) {
Daniel Veillard68178931999-02-08 18:34:36 +00003608 if (!xmlStrcmp(prop->name, name)) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003609 xmlChar *ret;
Daniel Veillard6800ef31999-02-08 18:33:22 +00003610
Daniel Veillardcf461992000-03-14 18:30:20 +00003611 ret = xmlNodeListGetString(node->doc, prop->children, 1);
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003612 if (ret == NULL) return(xmlStrdup((xmlChar *)""));
Daniel Veillard6800ef31999-02-08 18:33:22 +00003613 return(ret);
Daniel Veillard68178931999-02-08 18:34:36 +00003614 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003615 prop = prop->next;
3616 }
Daniel Veillard10a2c651999-12-12 13:03:50 +00003617 if (!xmlCheckDTD) return(NULL);
3618
3619 /*
3620 * Check if there is a default declaration in the internal
3621 * or external subsets
3622 */
3623 doc = node->doc;
3624 if (doc != NULL) {
3625 xmlAttributePtr attrDecl;
3626 if (doc->intSubset != NULL) {
3627 attrDecl = xmlGetDtdAttrDesc(doc->intSubset, node->name, name);
3628 if ((attrDecl == NULL) && (doc->extSubset != NULL))
3629 attrDecl = xmlGetDtdAttrDesc(doc->extSubset, node->name, name);
Daniel Veillardf967b902000-01-17 16:06:10 +00003630 if (attrDecl != NULL)
3631 return(xmlStrdup(attrDecl->defaultValue));
Daniel Veillard10a2c651999-12-12 13:03:50 +00003632 }
3633 }
3634 return(NULL);
3635}
3636
3637/**
3638 * xmlGetNsProp:
3639 * @node: the node
3640 * @name: the attribute name
3641 * @namespace: the URI of the namespace
3642 *
3643 * Search and get the value of an attribute associated to a node
3644 * This attribute has to be anchored in the namespace specified.
3645 * This does the entity substitution.
3646 * This function looks in DTD attribute declaration for #FIXED or
3647 * default declaration values unless DTD use has been turned off.
3648 *
3649 * Returns the attribute value or NULL if not found.
3650 * It's up to the caller to free the memory.
3651 */
3652xmlChar *
3653xmlGetNsProp(xmlNodePtr node, const xmlChar *name, const xmlChar *namespace) {
3654 xmlAttrPtr prop = node->properties;
3655 xmlDocPtr doc;
3656 xmlNsPtr ns;
3657
3658 if (namespace == NULL)
3659 return(xmlGetProp(node, name));
3660 while (prop != NULL) {
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00003661 /*
3662 * One need to have
3663 * - same attribute names
3664 * - and the attribute carrying that namespace
3665 * or
3666 * no namespace on the attribute and the element carrying it
3667 */
Daniel Veillard10a2c651999-12-12 13:03:50 +00003668 if ((!xmlStrcmp(prop->name, name)) &&
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00003669 (((prop->ns == NULL) && (node->ns != NULL) &&
3670 (!xmlStrcmp(node->ns->href, namespace))) ||
Daniel Veillard3c558c31999-12-22 11:30:41 +00003671 ((prop->ns != NULL) && (!xmlStrcmp(prop->ns->href, namespace))))) {
Daniel Veillard10a2c651999-12-12 13:03:50 +00003672 xmlChar *ret;
3673
Daniel Veillardcf461992000-03-14 18:30:20 +00003674 ret = xmlNodeListGetString(node->doc, prop->children, 1);
Daniel Veillard10a2c651999-12-12 13:03:50 +00003675 if (ret == NULL) return(xmlStrdup((xmlChar *)""));
3676 return(ret);
3677 }
3678 prop = prop->next;
3679 }
3680 if (!xmlCheckDTD) return(NULL);
3681
3682 /*
3683 * Check if there is a default declaration in the internal
3684 * or external subsets
3685 */
3686 doc = node->doc;
3687 if (doc != NULL) {
3688 xmlAttributePtr attrDecl;
3689 if (doc->intSubset != NULL) {
3690 attrDecl = xmlGetDtdAttrDesc(doc->intSubset, node->name, name);
3691 if ((attrDecl == NULL) && (doc->extSubset != NULL))
3692 attrDecl = xmlGetDtdAttrDesc(doc->extSubset, node->name, name);
3693
3694 if (attrDecl->prefix != NULL) {
3695 /*
3696 * The DTD declaration only allows a prefix search
3697 */
3698 ns = xmlSearchNs(doc, node, attrDecl->prefix);
3699 if ((ns != NULL) && (!xmlStrcmp(ns->href, namespace)))
3700 return(xmlStrdup(attrDecl->defaultValue));
3701 }
3702 }
3703 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003704 return(NULL);
3705}
3706
Daniel Veillard97b58771998-10-20 06:14:16 +00003707/**
Daniel Veillardccb09631998-10-27 06:21:04 +00003708 * xmlSetProp:
Daniel Veillard97b58771998-10-20 06:14:16 +00003709 * @node: the node
3710 * @name: the attribute name
3711 * @value: the attribute value
3712 *
3713 * Set (or reset) an attribute carried by a node.
Daniel Veillard1e346af1999-02-22 10:33:01 +00003714 * Returns the attribute pointer.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003715 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003716xmlAttrPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003717xmlSetProp(xmlNodePtr node, const xmlChar *name, const xmlChar *value) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003718 xmlAttrPtr prop = node->properties;
3719
3720 while (prop != NULL) {
3721 if (!xmlStrcmp(prop->name, name)) {
Daniel Veillardcf461992000-03-14 18:30:20 +00003722 if (prop->children != NULL)
3723 xmlFreeNodeList(prop->children);
3724 prop->children = NULL;
Daniel Veillard51e3b151999-11-12 17:02:31 +00003725 if (value != NULL) {
3726 xmlChar *buffer;
Daniel Veillardcf461992000-03-14 18:30:20 +00003727 xmlNodePtr tmp;
3728
Daniel Veillard51e3b151999-11-12 17:02:31 +00003729 buffer = xmlEncodeEntitiesReentrant(node->doc, value);
Daniel Veillardcf461992000-03-14 18:30:20 +00003730 prop->children = xmlStringGetNodeList(node->doc, buffer);
3731 tmp = prop->children;
3732 while (tmp != NULL) {
3733 tmp->parent = (xmlNodePtr) prop;
3734 if (tmp->next == NULL)
3735 prop->last = tmp;
3736 tmp = tmp->next;
3737 }
Daniel Veillard51e3b151999-11-12 17:02:31 +00003738 xmlFree(buffer);
3739 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003740 return(prop);
3741 }
3742 prop = prop->next;
3743 }
3744 prop = xmlNewProp(node, name, value);
3745 return(prop);
3746}
3747
Daniel Veillard97b58771998-10-20 06:14:16 +00003748/**
3749 * xmlNodeIsText:
3750 * @node: the node
3751 *
3752 * Is this node a Text node ?
Daniel Veillard1e346af1999-02-22 10:33:01 +00003753 * Returns 1 yes, 0 no
Daniel Veillard260a68f1998-08-13 03:39:55 +00003754 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003755int
3756xmlNodeIsText(xmlNodePtr node) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003757 if (node == NULL) return(0);
3758
Daniel Veillard0bef1311998-10-14 02:36:47 +00003759 if (node->type == XML_TEXT_NODE) return(1);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003760 return(0);
3761}
3762
Daniel Veillard97b58771998-10-20 06:14:16 +00003763/**
Daniel Veillard3e6d2372000-03-04 11:39:43 +00003764 * xmlIsBlankNode:
3765 * @node: the node
3766 *
Daniel Veillard32bc74e2000-07-14 14:49:25 +00003767 * Checks whether this node is an empty or whitespace only
3768 * (and possibly ignorable) text-node.
3769 *
Daniel Veillard3e6d2372000-03-04 11:39:43 +00003770 * Returns 1 yes, 0 no
3771 */
3772int
3773xmlIsBlankNode(xmlNodePtr node) {
3774 xmlChar *cur;
3775 if (node == NULL) return(0);
3776
3777 if (node->type != XML_TEXT_NODE) return(0);
3778 if (node->content == NULL) return(0);
3779 cur = node->content;
3780 while (*cur != 0) {
3781 if (!IS_BLANK(*cur)) return(0);
3782 cur++;
3783 }
3784
3785 return(1);
3786}
3787
3788/**
Daniel Veillard1e346af1999-02-22 10:33:01 +00003789 * xmlTextConcat:
Daniel Veillard97b58771998-10-20 06:14:16 +00003790 * @node: the node
3791 * @content: the content
3792 * @len: @content lenght
3793 *
3794 * Concat the given string at the end of the existing node content
Daniel Veillard260a68f1998-08-13 03:39:55 +00003795 */
Daniel Veillard97b58771998-10-20 06:14:16 +00003796
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003797void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003798xmlTextConcat(xmlNodePtr node, const xmlChar *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003799 if (node == NULL) return;
3800
Daniel Veillarddbfd6411999-12-28 16:35:14 +00003801 if ((node->type != XML_TEXT_NODE) &&
3802 (node->type != XML_CDATA_SECTION_NODE)) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00003803#ifdef DEBUG_TREE
Daniel Veillarddbfd6411999-12-28 16:35:14 +00003804 fprintf(stderr, "xmlTextConcat: node is not text nor cdata\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00003805#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00003806 return;
3807 }
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003808#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard260a68f1998-08-13 03:39:55 +00003809 node->content = xmlStrncat(node->content, content, len);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003810#else
3811 xmlBufferAdd(node->content, content, len);
3812#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00003813}
3814
3815/************************************************************************
3816 * *
3817 * Output : to a FILE or in memory *
3818 * *
3819 ************************************************************************/
3820
Daniel Veillard5099ae81999-04-21 20:12:07 +00003821#define BASE_BUFFER_SIZE 4000
3822
3823/**
3824 * xmlBufferCreate:
3825 *
3826 * routine to create an XML buffer.
3827 * returns the new structure.
3828 */
3829xmlBufferPtr
3830xmlBufferCreate(void) {
3831 xmlBufferPtr ret;
3832
Daniel Veillard6454aec1999-09-02 22:04:43 +00003833 ret = (xmlBufferPtr) xmlMalloc(sizeof(xmlBuffer));
Daniel Veillard5099ae81999-04-21 20:12:07 +00003834 if (ret == NULL) {
3835 fprintf(stderr, "xmlBufferCreate : out of memory!\n");
3836 return(NULL);
3837 }
3838 ret->use = 0;
3839 ret->size = BASE_BUFFER_SIZE;
Daniel Veillard10a2c651999-12-12 13:03:50 +00003840 ret->alloc = xmlBufferAllocScheme;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003841 ret->content = (xmlChar *) xmlMalloc(ret->size * sizeof(xmlChar));
Daniel Veillard5099ae81999-04-21 20:12:07 +00003842 if (ret->content == NULL) {
3843 fprintf(stderr, "xmlBufferCreate : out of memory!\n");
Daniel Veillard6454aec1999-09-02 22:04:43 +00003844 xmlFree(ret);
Daniel Veillard5099ae81999-04-21 20:12:07 +00003845 return(NULL);
3846 }
3847 ret->content[0] = 0;
3848 return(ret);
3849}
3850
3851/**
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003852 * xmlBufferCreateSize:
3853 * @size: initial size of buffer
3854 *
3855 * routine to create an XML buffer.
3856 * returns the new structure.
3857 */
3858xmlBufferPtr
3859xmlBufferCreateSize(size_t size) {
3860 xmlBufferPtr ret;
3861
3862 ret = (xmlBufferPtr) xmlMalloc(sizeof(xmlBuffer));
3863 if (ret == NULL) {
3864 fprintf(stderr, "xmlBufferCreate : out of memory!\n");
3865 return(NULL);
3866 }
3867 ret->use = 0;
Daniel Veillard10a2c651999-12-12 13:03:50 +00003868 ret->alloc = xmlBufferAllocScheme;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003869 ret->size = (size ? size+2 : 0); /* +1 for ending null */
Daniel Veillard10a2c651999-12-12 13:03:50 +00003870 if (ret->size){
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003871 ret->content = (xmlChar *) xmlMalloc(ret->size * sizeof(xmlChar));
3872 if (ret->content == NULL) {
3873 fprintf(stderr, "xmlBufferCreate : out of memory!\n");
3874 xmlFree(ret);
3875 return(NULL);
3876 }
3877 ret->content[0] = 0;
3878 } else
3879 ret->content = NULL;
3880 return(ret);
3881}
3882
3883/**
Daniel Veillard06047432000-04-24 11:33:38 +00003884 * xmlBufferSetAllocationScheme:
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003885 * @buf: the buffer to free
3886 * @scheme: allocation scheme to use
3887 *
3888 * Sets the allocation scheme for this buffer
3889 */
3890void
3891xmlBufferSetAllocationScheme(xmlBufferPtr buf,
3892 xmlBufferAllocationScheme scheme) {
3893 if (buf == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00003894#ifdef DEBUG_BUFFER
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003895 fprintf(stderr, "xmlBufferSetAllocationScheme: buf == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00003896#endif
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003897 return;
3898 }
3899
3900 buf->alloc = scheme;
3901}
3902
3903/**
Daniel Veillard5099ae81999-04-21 20:12:07 +00003904 * xmlBufferFree:
3905 * @buf: the buffer to free
3906 *
3907 * Frees an XML buffer.
3908 */
3909void
3910xmlBufferFree(xmlBufferPtr buf) {
3911 if (buf == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00003912#ifdef DEBUG_BUFFER
Daniel Veillard5099ae81999-04-21 20:12:07 +00003913 fprintf(stderr, "xmlBufferFree: buf == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00003914#endif
Daniel Veillard5099ae81999-04-21 20:12:07 +00003915 return;
3916 }
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003917 if (buf->content != NULL) {
3918#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard5099ae81999-04-21 20:12:07 +00003919 memset(buf->content, -1, BASE_BUFFER_SIZE);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003920#else
3921 memset(buf->content, -1, buf->size);
3922#endif
Daniel Veillard6454aec1999-09-02 22:04:43 +00003923 xmlFree(buf->content);
Daniel Veillard5099ae81999-04-21 20:12:07 +00003924 }
3925 memset(buf, -1, sizeof(xmlBuffer));
Daniel Veillard6454aec1999-09-02 22:04:43 +00003926 xmlFree(buf);
Daniel Veillard5099ae81999-04-21 20:12:07 +00003927}
3928
3929/**
Daniel Veillarde2d034d1999-07-27 19:52:06 +00003930 * xmlBufferEmpty:
3931 * @buf: the buffer
3932 *
3933 * empty a buffer.
3934 */
3935void
3936xmlBufferEmpty(xmlBufferPtr buf) {
3937 buf->use = 0;
3938 memset(buf->content, -1, buf->size);/* just for debug */
3939}
3940
3941/**
3942 * xmlBufferShrink:
3943 * @buf: the buffer to dump
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003944 * @len: the number of xmlChar to remove
Daniel Veillarde2d034d1999-07-27 19:52:06 +00003945 *
3946 * Remove the beginning of an XML buffer.
3947 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003948 * Returns the number of xmlChar removed, or -1 in case of failure.
Daniel Veillarde2d034d1999-07-27 19:52:06 +00003949 */
3950int
3951xmlBufferShrink(xmlBufferPtr buf, int len) {
3952 if (len == 0) return(0);
3953 if (len > buf->use) return(-1);
3954
3955 buf->use -= len;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003956 memmove(buf->content, &buf->content[len], buf->use * sizeof(xmlChar));
Daniel Veillarde2d034d1999-07-27 19:52:06 +00003957
3958 buf->content[buf->use] = 0;
3959 return(len);
3960}
3961
3962/**
Daniel Veillard496a1cf2000-05-03 14:20:55 +00003963 * xmlBufferGrow:
3964 * @buf: the buffer
3965 * @len: the minimum free sie to allocate
3966 *
3967 * Grow the available space of an XML buffer.
3968 *
3969 * Returns the new available space or -1 in case of error
3970 */
3971int
3972xmlBufferGrow(xmlBufferPtr buf, int len) {
3973 int size;
3974 xmlChar *newbuf;
3975
3976 if (len <= buf->use) return(0);
3977
Daniel Veillardbe803962000-06-28 23:40:59 +00003978 size = buf->use + len + 100;
Daniel Veillard496a1cf2000-05-03 14:20:55 +00003979
Daniel Veillard32bc74e2000-07-14 14:49:25 +00003980 newbuf = (xmlChar *) xmlRealloc(buf->content, size);
Daniel Veillard496a1cf2000-05-03 14:20:55 +00003981 if (newbuf == NULL) return(-1);
3982 buf->content = newbuf;
3983 buf->size = size;
3984 return(buf->size - buf->use);
3985}
3986
3987/**
Daniel Veillard5099ae81999-04-21 20:12:07 +00003988 * xmlBufferDump:
3989 * @file: the file output
3990 * @buf: the buffer to dump
3991 *
3992 * Dumps an XML buffer to a FILE *.
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003993 * Returns the number of xmlChar written
Daniel Veillard5099ae81999-04-21 20:12:07 +00003994 */
3995int
3996xmlBufferDump(FILE *file, xmlBufferPtr buf) {
3997 int ret;
3998
3999 if (buf == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004000#ifdef DEBUG_BUFFER
Daniel Veillard5099ae81999-04-21 20:12:07 +00004001 fprintf(stderr, "xmlBufferDump: buf == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004002#endif
Daniel Veillard5099ae81999-04-21 20:12:07 +00004003 return(0);
4004 }
4005 if (buf->content == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004006#ifdef DEBUG_BUFFER
Daniel Veillard5099ae81999-04-21 20:12:07 +00004007 fprintf(stderr, "xmlBufferDump: buf->content == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004008#endif
Daniel Veillard5099ae81999-04-21 20:12:07 +00004009 return(0);
4010 }
4011 if (file == NULL) file = stdout;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004012 ret = fwrite(buf->content, sizeof(xmlChar), buf->use, file);
Daniel Veillard5099ae81999-04-21 20:12:07 +00004013 return(ret);
4014}
4015
4016/**
Daniel Veillardf5c2c871999-12-01 09:51:45 +00004017 * xmlBufferContent:
4018 * @buf: the buffer to resize
4019 *
4020 * Returns the internal content
4021 */
4022
4023const xmlChar*
4024xmlBufferContent(const xmlBufferPtr buf)
4025{
4026 if(!buf)
4027 return NULL;
4028
4029 return buf->content;
4030}
4031
4032/**
4033 * xmlBufferLength:
4034 * @buf: the buffer
4035 *
4036 * Returns the length of data in the internal content
4037 */
4038
4039int
4040xmlBufferLength(const xmlBufferPtr buf)
4041{
4042 if(!buf)
4043 return 0;
4044
4045 return buf->use;
4046}
4047
4048/**
4049 * xmlBufferResize:
4050 * @buf: the buffer to resize
4051 * @len: the desired size
4052 *
4053 * Resize a buffer to accomodate minimum size of <len>.
4054 *
4055 * Returns 0 in case of problems, 1 otherwise
4056 */
4057int
4058xmlBufferResize(xmlBufferPtr buf, int size)
4059{
4060 int newSize = (buf->size ? buf->size*2 : size);/*take care of empty case*/
4061 xmlChar* rebuf = NULL;
4062
4063 /* Don't resize if we don't have to */
4064 if(size < buf->size)
4065 return 1;
4066
4067 /* figure out new size */
4068 switch(buf->alloc){
4069 case XML_BUFFER_ALLOC_DOUBLEIT:
4070 while(size > newSize) newSize *= 2;
4071 break;
4072 case XML_BUFFER_ALLOC_EXACT:
4073 newSize = size+10;
4074 break;
4075 default:
4076 newSize = size+10;
4077 break;
4078 }
4079
4080 if (buf->content == NULL)
4081 rebuf = (xmlChar *) xmlMalloc(newSize * sizeof(xmlChar));
4082 else
4083 rebuf = (xmlChar *) xmlRealloc(buf->content,
4084 newSize * sizeof(xmlChar));
4085 if (rebuf == NULL) {
4086 fprintf(stderr, "xmlBufferAdd : out of memory!\n");
4087 return 0;
4088 }
4089 buf->content = rebuf;
4090 buf->size = newSize;
4091
4092 return 1;
4093}
4094/**
Daniel Veillard5099ae81999-04-21 20:12:07 +00004095 * xmlBufferAdd:
4096 * @buf: the buffer to dump
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004097 * @str: the xmlChar string
4098 * @len: the number of xmlChar to add
Daniel Veillard5099ae81999-04-21 20:12:07 +00004099 *
Daniel Veillard10a2c651999-12-12 13:03:50 +00004100 * Add a string range to an XML buffer. if len == -1, the lenght of
4101 * str is recomputed.
Daniel Veillard5099ae81999-04-21 20:12:07 +00004102 */
4103void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004104xmlBufferAdd(xmlBufferPtr buf, const xmlChar *str, int len) {
Daniel Veillardcf461992000-03-14 18:30:20 +00004105 int needSize;
Daniel Veillard5099ae81999-04-21 20:12:07 +00004106
4107 if (str == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004108#ifdef DEBUG_BUFFER
Daniel Veillard5099ae81999-04-21 20:12:07 +00004109 fprintf(stderr, "xmlBufferAdd: str == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004110#endif
Daniel Veillard5099ae81999-04-21 20:12:07 +00004111 return;
4112 }
Daniel Veillard10a2c651999-12-12 13:03:50 +00004113 if (len < -1) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004114#ifdef DEBUG_BUFFER
Daniel Veillard10a2c651999-12-12 13:03:50 +00004115 fprintf(stderr, "xmlBufferAdd: len < 0\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004116#endif
Daniel Veillard10a2c651999-12-12 13:03:50 +00004117 return;
4118 }
4119 if (len == 0) return;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00004120
Daniel Veillarddbfd6411999-12-28 16:35:14 +00004121 if (len < 0)
Daniel Veillardcf461992000-03-14 18:30:20 +00004122 len = xmlStrlen(str);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00004123
Daniel Veillarde2d034d1999-07-27 19:52:06 +00004124 if (len <= 0) return;
Daniel Veillard5099ae81999-04-21 20:12:07 +00004125
Daniel Veillardf5c2c871999-12-01 09:51:45 +00004126 needSize = buf->use + len + 2;
4127 if(needSize > buf->size){
4128 if(!xmlBufferResize(buf, needSize)){
4129 fprintf(stderr, "xmlBufferAdd : out of memory!\n");
4130 return;
4131 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00004132 }
Daniel Veillardf5c2c871999-12-01 09:51:45 +00004133
4134 memmove(&buf->content[buf->use], str, len*sizeof(xmlChar));
Daniel Veillarde2d034d1999-07-27 19:52:06 +00004135 buf->use += len;
4136 buf->content[buf->use] = 0;
Daniel Veillard5099ae81999-04-21 20:12:07 +00004137}
4138
4139/**
Daniel Veillardbe803962000-06-28 23:40:59 +00004140 * xmlBufferAddHead:
4141 * @buf: the buffer
4142 * @str: the xmlChar string
4143 * @len: the number of xmlChar to add
4144 *
4145 * Add a string range to the beginning of an XML buffer.
4146 * if len == -1, the lenght of @str is recomputed.
4147 */
4148void
4149xmlBufferAddHead(xmlBufferPtr buf, const xmlChar *str, int len) {
4150 int needSize;
4151
4152 if (str == NULL) {
4153#ifdef DEBUG_BUFFER
4154 fprintf(stderr, "xmlBufferAdd: str == NULL\n");
4155#endif
4156 return;
4157 }
4158 if (len < -1) {
4159#ifdef DEBUG_BUFFER
4160 fprintf(stderr, "xmlBufferAdd: len < 0\n");
4161#endif
4162 return;
4163 }
4164 if (len == 0) return;
4165
4166 if (len < 0)
4167 len = xmlStrlen(str);
4168
4169 if (len <= 0) return;
4170
4171 needSize = buf->use + len + 2;
4172 if(needSize > buf->size){
4173 if(!xmlBufferResize(buf, needSize)){
4174 fprintf(stderr, "xmlBufferAddHead : out of memory!\n");
4175 return;
4176 }
4177 }
4178
4179 memmove(&buf->content[len], &buf->content[0], buf->use * sizeof(xmlChar));
4180 memmove(&buf->content[0], str, len * sizeof(xmlChar));
4181 buf->use += len;
4182 buf->content[buf->use] = 0;
4183}
4184
4185/**
Daniel Veillard5099ae81999-04-21 20:12:07 +00004186 * xmlBufferCat:
4187 * @buf: the buffer to dump
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004188 * @str: the xmlChar string
Daniel Veillard5099ae81999-04-21 20:12:07 +00004189 *
4190 * Append a zero terminated string to an XML buffer.
4191 */
4192void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004193xmlBufferCat(xmlBufferPtr buf, const xmlChar *str) {
Daniel Veillardf5c2c871999-12-01 09:51:45 +00004194 if (str != NULL)
4195 xmlBufferAdd(buf, str, -1);
Daniel Veillard5099ae81999-04-21 20:12:07 +00004196}
4197
4198/**
4199 * xmlBufferCCat:
4200 * @buf: the buffer to dump
4201 * @str: the C char string
4202 *
4203 * Append a zero terminated C string to an XML buffer.
4204 */
4205void
4206xmlBufferCCat(xmlBufferPtr buf, const char *str) {
4207 const char *cur;
4208
4209 if (str == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004210#ifdef DEBUG_BUFFER
Daniel Veillard5099ae81999-04-21 20:12:07 +00004211 fprintf(stderr, "xmlBufferAdd: str == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004212#endif
Daniel Veillard5099ae81999-04-21 20:12:07 +00004213 return;
4214 }
4215 for (cur = str;*cur != 0;cur++) {
4216 if (buf->use + 10 >= buf->size) {
Daniel Veillardf5c2c871999-12-01 09:51:45 +00004217 if(!xmlBufferResize(buf, buf->use+10)){
4218 fprintf(stderr, "xmlBufferCCat : out of memory!\n");
4219 return;
4220 }
4221 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00004222 buf->content[buf->use++] = *cur;
4223 }
4224}
Daniel Veillard260a68f1998-08-13 03:39:55 +00004225
Daniel Veillard97b58771998-10-20 06:14:16 +00004226/**
4227 * xmlBufferWriteCHAR:
Daniel Veillard5099ae81999-04-21 20:12:07 +00004228 * @buf: the XML buffer
Daniel Veillard97b58771998-10-20 06:14:16 +00004229 * @string: the string to add
4230 *
4231 * routine which manage and grows an output buffer. This one add
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004232 * xmlChars at the end of the buffer.
Daniel Veillard97b58771998-10-20 06:14:16 +00004233 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00004234void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004235xmlBufferWriteCHAR(xmlBufferPtr buf, const xmlChar *string) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00004236 xmlBufferCat(buf, string);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004237}
4238
Daniel Veillard97b58771998-10-20 06:14:16 +00004239/**
4240 * xmlBufferWriteChar:
Daniel Veillard011b63c1999-06-02 17:44:04 +00004241 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00004242 * @string: the string to add
4243 *
4244 * routine which manage and grows an output buffer. This one add
4245 * C chars at the end of the array.
4246 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00004247void
Daniel Veillard5099ae81999-04-21 20:12:07 +00004248xmlBufferWriteChar(xmlBufferPtr buf, const char *string) {
4249 xmlBufferCCat(buf, string);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004250}
4251
Daniel Veillard5099ae81999-04-21 20:12:07 +00004252
Daniel Veillard97b58771998-10-20 06:14:16 +00004253/**
Daniel Veillard011b63c1999-06-02 17:44:04 +00004254 * xmlBufferWriteQuotedString:
4255 * @buf: the XML buffer output
4256 * @string: the string to add
4257 *
4258 * routine which manage and grows an output buffer. This one writes
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004259 * a quoted or double quoted xmlChar string, checking first if it holds
Daniel Veillard011b63c1999-06-02 17:44:04 +00004260 * quote or double-quotes internally
4261 */
4262void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004263xmlBufferWriteQuotedString(xmlBufferPtr buf, const xmlChar *string) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00004264 if (xmlStrchr(string, '"')) {
4265 if (xmlStrchr(string, '\'')) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004266#ifdef DEBUG_BUFFER
Daniel Veillard011b63c1999-06-02 17:44:04 +00004267 fprintf(stderr,
4268 "xmlBufferWriteQuotedString: string contains quote and double-quotes !\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004269#endif
Daniel Veillard011b63c1999-06-02 17:44:04 +00004270 }
4271 xmlBufferCCat(buf, "'");
4272 xmlBufferCat(buf, string);
4273 xmlBufferCCat(buf, "'");
4274 } else {
4275 xmlBufferCCat(buf, "\"");
4276 xmlBufferCat(buf, string);
4277 xmlBufferCCat(buf, "\"");
4278 }
4279}
4280
4281
Daniel Veillardbe803962000-06-28 23:40:59 +00004282/************************************************************************
4283 * *
4284 * Dumping XML tree content to a simple buffer *
4285 * *
4286 ************************************************************************/
4287
Daniel Veillardcf461992000-03-14 18:30:20 +00004288static void
4289xmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
4290 int format);
4291static void
4292xmlNodeListDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
4293 int format);
4294void
4295htmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur);
4296
Daniel Veillard011b63c1999-06-02 17:44:04 +00004297/**
Daniel Veillard97b58771998-10-20 06:14:16 +00004298 * xmlGlobalNsDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00004299 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00004300 * @cur: a namespace
4301 *
4302 * Dump a global Namespace, this is the old version based on PIs.
Daniel Veillard260a68f1998-08-13 03:39:55 +00004303 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00004304static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00004305xmlGlobalNsDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00004306 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004307#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00004308 fprintf(stderr, "xmlGlobalNsDump : Ns == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004309#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00004310 return;
4311 }
4312 if (cur->type == XML_GLOBAL_NAMESPACE) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00004313 xmlBufferWriteChar(buf, "<?namespace");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004314 if (cur->href != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00004315 xmlBufferWriteChar(buf, " href=");
4316 xmlBufferWriteQuotedString(buf, cur->href);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004317 }
4318 if (cur->prefix != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00004319 xmlBufferWriteChar(buf, " AS=");
4320 xmlBufferWriteQuotedString(buf, cur->prefix);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004321 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00004322 xmlBufferWriteChar(buf, "?>\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004323 }
4324}
4325
Daniel Veillard97b58771998-10-20 06:14:16 +00004326/**
4327 * xmlGlobalNsListDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00004328 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00004329 * @cur: the first namespace
4330 *
4331 * Dump a list of global Namespace, this is the old version based on PIs.
Daniel Veillard260a68f1998-08-13 03:39:55 +00004332 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00004333static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00004334xmlGlobalNsListDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00004335 while (cur != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00004336 xmlGlobalNsDump(buf, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004337 cur = cur->next;
4338 }
4339}
4340
Daniel Veillard97b58771998-10-20 06:14:16 +00004341/**
4342 * xmlNsDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00004343 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00004344 * @cur: a namespace
4345 *
Daniel Veillard260a68f1998-08-13 03:39:55 +00004346 * Dump a local Namespace definition.
Daniel Veillard97b58771998-10-20 06:14:16 +00004347 * Should be called in the context of attributes dumps.
Daniel Veillard260a68f1998-08-13 03:39:55 +00004348 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00004349static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00004350xmlNsDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00004351 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004352#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00004353 fprintf(stderr, "xmlNsDump : Ns == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004354#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00004355 return;
4356 }
4357 if (cur->type == XML_LOCAL_NAMESPACE) {
4358 /* Within the context of an element attributes */
4359 if (cur->prefix != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00004360 xmlBufferWriteChar(buf, " xmlns:");
4361 xmlBufferWriteCHAR(buf, cur->prefix);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004362 } else
Daniel Veillard5099ae81999-04-21 20:12:07 +00004363 xmlBufferWriteChar(buf, " xmlns");
Daniel Veillard011b63c1999-06-02 17:44:04 +00004364 xmlBufferWriteChar(buf, "=");
4365 xmlBufferWriteQuotedString(buf, cur->href);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004366 }
4367}
4368
Daniel Veillard97b58771998-10-20 06:14:16 +00004369/**
4370 * xmlNsListDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00004371 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00004372 * @cur: the first namespace
4373 *
4374 * Dump a list of local Namespace definitions.
4375 * Should be called in the context of attributes dumps.
Daniel Veillard260a68f1998-08-13 03:39:55 +00004376 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00004377static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00004378xmlNsListDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00004379 while (cur != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00004380 xmlNsDump(buf, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004381 cur = cur->next;
4382 }
4383}
4384
Daniel Veillard97b58771998-10-20 06:14:16 +00004385/**
4386 * xmlDtdDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00004387 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00004388 * @doc: the document
4389 *
4390 * Dump the XML document DTD, if any.
Daniel Veillard260a68f1998-08-13 03:39:55 +00004391 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00004392static void
Daniel Veillardcf461992000-03-14 18:30:20 +00004393xmlDtdDump(xmlBufferPtr buf, xmlDtdPtr dtd) {
4394 if (dtd == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004395#ifdef DEBUG_TREE
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004396 fprintf(stderr, "xmlDtdDump : no internal subset\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004397#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00004398 return;
4399 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00004400 xmlBufferWriteChar(buf, "<!DOCTYPE ");
Daniel Veillardcf461992000-03-14 18:30:20 +00004401 xmlBufferWriteCHAR(buf, dtd->name);
4402 if (dtd->ExternalID != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00004403 xmlBufferWriteChar(buf, " PUBLIC ");
Daniel Veillardcf461992000-03-14 18:30:20 +00004404 xmlBufferWriteQuotedString(buf, dtd->ExternalID);
Daniel Veillard011b63c1999-06-02 17:44:04 +00004405 xmlBufferWriteChar(buf, " ");
Daniel Veillardcf461992000-03-14 18:30:20 +00004406 xmlBufferWriteQuotedString(buf, dtd->SystemID);
4407 } else if (dtd->SystemID != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00004408 xmlBufferWriteChar(buf, " SYSTEM ");
Daniel Veillardcf461992000-03-14 18:30:20 +00004409 xmlBufferWriteQuotedString(buf, dtd->SystemID);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004410 }
Daniel Veillardcf461992000-03-14 18:30:20 +00004411 if ((dtd->entities == NULL) && (dtd->elements == NULL) &&
4412 (dtd->attributes == NULL) && (dtd->notations == NULL)) {
4413 xmlBufferWriteChar(buf, ">");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004414 return;
4415 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00004416 xmlBufferWriteChar(buf, " [\n");
Daniel Veillardcf461992000-03-14 18:30:20 +00004417 xmlNodeListDump(buf, dtd->doc, dtd->children, -1, 0);
4418#if 0
4419 if (dtd->entities != NULL)
4420 xmlDumpEntitiesTable(buf, (xmlEntitiesTablePtr) dtd->entities);
4421 if (dtd->notations != NULL)
4422 xmlDumpNotationTable(buf, (xmlNotationTablePtr) dtd->notations);
4423 if (dtd->elements != NULL)
4424 xmlDumpElementTable(buf, (xmlElementTablePtr) dtd->elements);
4425 if (dtd->attributes != NULL)
4426 xmlDumpAttributeTable(buf, (xmlAttributeTablePtr) dtd->attributes);
4427#endif
4428 xmlBufferWriteChar(buf, "]>");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004429}
4430
Daniel Veillard97b58771998-10-20 06:14:16 +00004431/**
4432 * xmlAttrDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00004433 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00004434 * @doc: the document
4435 * @cur: the attribute pointer
4436 *
4437 * Dump an XML attribute
Daniel Veillard260a68f1998-08-13 03:39:55 +00004438 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00004439static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00004440xmlAttrDump(xmlBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004441 xmlChar *value;
Daniel Veillardccb09631998-10-27 06:21:04 +00004442
Daniel Veillard260a68f1998-08-13 03:39:55 +00004443 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004444#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00004445 fprintf(stderr, "xmlAttrDump : property == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004446#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00004447 return;
4448 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00004449 xmlBufferWriteChar(buf, " ");
Daniel Veillardb96e6431999-08-29 21:02:19 +00004450 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
4451 xmlBufferWriteCHAR(buf, cur->ns->prefix);
4452 xmlBufferWriteChar(buf, ":");
4453 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00004454 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillardcf461992000-03-14 18:30:20 +00004455 value = xmlNodeListGetString(doc, cur->children, 0);
Daniel Veillardccb09631998-10-27 06:21:04 +00004456 if (value) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00004457 xmlBufferWriteChar(buf, "=");
4458 xmlBufferWriteQuotedString(buf, value);
Daniel Veillard6454aec1999-09-02 22:04:43 +00004459 xmlFree(value);
Daniel Veillard726c7e31999-02-08 15:13:10 +00004460 } else {
Daniel Veillard5099ae81999-04-21 20:12:07 +00004461 xmlBufferWriteChar(buf, "=\"\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004462 }
4463}
4464
Daniel Veillard97b58771998-10-20 06:14:16 +00004465/**
4466 * xmlAttrListDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00004467 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00004468 * @doc: the document
4469 * @cur: the first attribute pointer
4470 *
4471 * Dump a list of XML attributes
Daniel Veillard260a68f1998-08-13 03:39:55 +00004472 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00004473static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00004474xmlAttrListDump(xmlBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00004475 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004476#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00004477 fprintf(stderr, "xmlAttrListDump : property == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004478#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00004479 return;
4480 }
4481 while (cur != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00004482 xmlAttrDump(buf, doc, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004483 cur = cur->next;
4484 }
4485}
4486
Daniel Veillard260a68f1998-08-13 03:39:55 +00004487
Daniel Veillarddbfd6411999-12-28 16:35:14 +00004488
Daniel Veillard97b58771998-10-20 06:14:16 +00004489/**
4490 * xmlNodeListDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00004491 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00004492 * @doc: the document
4493 * @cur: the first node
Daniel Veillardcf461992000-03-14 18:30:20 +00004494 * @level: the imbrication level for indenting
Daniel Veillard7d2c2761999-10-11 15:09:51 +00004495 * @format: is formatting allowed
Daniel Veillard97b58771998-10-20 06:14:16 +00004496 *
4497 * Dump an XML node list, recursive behaviour,children are printed too.
4498 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00004499static void
Daniel Veillard7d2c2761999-10-11 15:09:51 +00004500xmlNodeListDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
4501 int format) {
4502 int i;
Daniel Veillardccb09631998-10-27 06:21:04 +00004503
Daniel Veillard260a68f1998-08-13 03:39:55 +00004504 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004505#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00004506 fprintf(stderr, "xmlNodeListDump : node == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004507#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00004508 return;
4509 }
4510 while (cur != NULL) {
Daniel Veillard7d2c2761999-10-11 15:09:51 +00004511 if ((format) && (xmlIndentTreeOutput) &&
4512 (cur->type == XML_ELEMENT_NODE))
4513 for (i = 0;i < level;i++)
4514 xmlBufferWriteChar(buf, " ");
4515 xmlNodeDump(buf, doc, cur, level, format);
4516 if (format) {
4517 xmlBufferWriteChar(buf, "\n");
Daniel Veillardccb09631998-10-27 06:21:04 +00004518 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00004519 cur = cur->next;
4520 }
4521}
4522
Daniel Veillard97b58771998-10-20 06:14:16 +00004523/**
Daniel Veillardccb09631998-10-27 06:21:04 +00004524 * xmlNodeDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00004525 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00004526 * @doc: the document
4527 * @cur: the current node
Daniel Veillardcf461992000-03-14 18:30:20 +00004528 * @level: the imbrication level for indenting
Daniel Veillard7d2c2761999-10-11 15:09:51 +00004529 * @format: is formatting allowed
Daniel Veillard97b58771998-10-20 06:14:16 +00004530 *
4531 * Dump an XML node, recursive behaviour,children are printed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +00004532 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00004533static void
Daniel Veillard7d2c2761999-10-11 15:09:51 +00004534xmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
4535 int format) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00004536 int i;
Daniel Veillard7d2c2761999-10-11 15:09:51 +00004537 xmlNodePtr tmp;
Daniel Veillard260a68f1998-08-13 03:39:55 +00004538
4539 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004540#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00004541 fprintf(stderr, "xmlNodeDump : node == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004542#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00004543 return;
4544 }
Daniel Veillardcf461992000-03-14 18:30:20 +00004545 if (cur->type == XML_DTD_NODE) {
4546 xmlDtdDump(buf, (xmlDtdPtr) cur);
4547 return;
4548 }
4549 if (cur->type == XML_ELEMENT_DECL) {
4550 xmlDumpElementDecl(buf, (xmlElementPtr) cur);
4551 return;
4552 }
4553 if (cur->type == XML_ATTRIBUTE_DECL) {
4554 xmlDumpAttributeDecl(buf, (xmlAttributePtr) cur);
4555 return;
4556 }
4557 if (cur->type == XML_ENTITY_DECL) {
4558 xmlDumpEntityDecl(buf, (xmlEntityPtr) cur);
4559 return;
4560 }
Daniel Veillard0bef1311998-10-14 02:36:47 +00004561 if (cur->type == XML_TEXT_NODE) {
Daniel Veillard14fff061999-06-22 21:49:07 +00004562 if (cur->content != NULL) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004563 xmlChar *buffer;
Daniel Veillard14fff061999-06-22 21:49:07 +00004564
Daniel Veillardf5c2c871999-12-01 09:51:45 +00004565#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard14fff061999-06-22 21:49:07 +00004566 buffer = xmlEncodeEntitiesReentrant(doc, cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00004567#else
4568 buffer = xmlEncodeEntitiesReentrant(doc,
4569 xmlBufferContent(cur->content));
4570#endif
Daniel Veillard14fff061999-06-22 21:49:07 +00004571 if (buffer != NULL) {
4572 xmlBufferWriteCHAR(buf, buffer);
Daniel Veillard6454aec1999-09-02 22:04:43 +00004573 xmlFree(buffer);
Daniel Veillard14fff061999-06-22 21:49:07 +00004574 }
4575 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00004576 return;
4577 }
Daniel Veillardb96e6431999-08-29 21:02:19 +00004578 if (cur->type == XML_PI_NODE) {
4579 if (cur->content != NULL) {
4580 xmlBufferWriteChar(buf, "<?");
4581 xmlBufferWriteCHAR(buf, cur->name);
4582 if (cur->content != NULL) {
4583 xmlBufferWriteChar(buf, " ");
Daniel Veillardf5c2c871999-12-01 09:51:45 +00004584#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardb96e6431999-08-29 21:02:19 +00004585 xmlBufferWriteCHAR(buf, cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00004586#else
4587 xmlBufferWriteCHAR(buf, xmlBufferContent(cur->content));
4588#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +00004589 }
Daniel Veillard7d2c2761999-10-11 15:09:51 +00004590 xmlBufferWriteChar(buf, "?>");
Daniel Veillardcf461992000-03-14 18:30:20 +00004591 } else {
4592 xmlBufferWriteChar(buf, "<?");
4593 xmlBufferWriteCHAR(buf, cur->name);
4594 xmlBufferWriteChar(buf, "?>");
Daniel Veillardb96e6431999-08-29 21:02:19 +00004595 }
4596 return;
4597 }
Daniel Veillard0bef1311998-10-14 02:36:47 +00004598 if (cur->type == XML_COMMENT_NODE) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00004599 if (cur->content != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00004600 xmlBufferWriteChar(buf, "<!--");
Daniel Veillardf5c2c871999-12-01 09:51:45 +00004601#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard5099ae81999-04-21 20:12:07 +00004602 xmlBufferWriteCHAR(buf, cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00004603#else
4604 xmlBufferWriteCHAR(buf, xmlBufferContent(cur->content));
4605#endif
Daniel Veillard7d2c2761999-10-11 15:09:51 +00004606 xmlBufferWriteChar(buf, "-->");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004607 }
4608 return;
4609 }
Daniel Veillardccb09631998-10-27 06:21:04 +00004610 if (cur->type == XML_ENTITY_REF_NODE) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00004611 xmlBufferWriteChar(buf, "&");
4612 xmlBufferWriteCHAR(buf, cur->name);
4613 xmlBufferWriteChar(buf, ";");
Daniel Veillardccb09631998-10-27 06:21:04 +00004614 return;
4615 }
Daniel Veillardb05deb71999-08-10 19:04:08 +00004616 if (cur->type == XML_CDATA_SECTION_NODE) {
4617 xmlBufferWriteChar(buf, "<![CDATA[");
4618 if (cur->content != NULL)
Daniel Veillardf5c2c871999-12-01 09:51:45 +00004619#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardb05deb71999-08-10 19:04:08 +00004620 xmlBufferWriteCHAR(buf, cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00004621#else
4622 xmlBufferWriteCHAR(buf, xmlBufferContent(cur->content));
4623#endif
Daniel Veillardb05deb71999-08-10 19:04:08 +00004624 xmlBufferWriteChar(buf, "]]>");
4625 return;
4626 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00004627
Daniel Veillard7d2c2761999-10-11 15:09:51 +00004628 if (format == 1) {
Daniel Veillardcf461992000-03-14 18:30:20 +00004629 tmp = cur->children;
Daniel Veillard7d2c2761999-10-11 15:09:51 +00004630 while (tmp != NULL) {
4631 if ((tmp->type == XML_TEXT_NODE) ||
4632 (tmp->type == XML_ENTITY_REF_NODE)) {
4633 format = 0;
4634 break;
4635 }
4636 tmp = tmp->next;
4637 }
4638 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00004639 xmlBufferWriteChar(buf, "<");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004640 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00004641 xmlBufferWriteCHAR(buf, cur->ns->prefix);
4642 xmlBufferWriteChar(buf, ":");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004643 }
4644
Daniel Veillard5099ae81999-04-21 20:12:07 +00004645 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004646 if (cur->nsDef)
Daniel Veillard5099ae81999-04-21 20:12:07 +00004647 xmlNsListDump(buf, cur->nsDef);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004648 if (cur->properties != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00004649 xmlAttrListDump(buf, doc, cur->properties);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004650
Daniel Veillardcf461992000-03-14 18:30:20 +00004651 if ((cur->content == NULL) && (cur->children == NULL) &&
Daniel Veillarde41f2b72000-01-30 20:00:07 +00004652 (!xmlSaveNoEmptyTags)) {
Daniel Veillard7d2c2761999-10-11 15:09:51 +00004653 xmlBufferWriteChar(buf, "/>");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004654 return;
4655 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00004656 xmlBufferWriteChar(buf, ">");
Daniel Veillard14fff061999-06-22 21:49:07 +00004657 if (cur->content != NULL) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004658 xmlChar *buffer;
Daniel Veillard14fff061999-06-22 21:49:07 +00004659
Daniel Veillardf5c2c871999-12-01 09:51:45 +00004660#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard14fff061999-06-22 21:49:07 +00004661 buffer = xmlEncodeEntitiesReentrant(doc, cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00004662#else
4663 buffer = xmlEncodeEntitiesReentrant(doc,
4664 xmlBufferContent(cur->content));
4665#endif
Daniel Veillard14fff061999-06-22 21:49:07 +00004666 if (buffer != NULL) {
4667 xmlBufferWriteCHAR(buf, buffer);
Daniel Veillard6454aec1999-09-02 22:04:43 +00004668 xmlFree(buffer);
Daniel Veillard14fff061999-06-22 21:49:07 +00004669 }
4670 }
Daniel Veillardcf461992000-03-14 18:30:20 +00004671 if (cur->children != NULL) {
Daniel Veillard7d2c2761999-10-11 15:09:51 +00004672 if (format) xmlBufferWriteChar(buf, "\n");
Daniel Veillardcf461992000-03-14 18:30:20 +00004673 xmlNodeListDump(buf, doc, cur->children,
Daniel Veillard3e6d2372000-03-04 11:39:43 +00004674 (level >= 0?level+1:-1), format);
Daniel Veillard7d2c2761999-10-11 15:09:51 +00004675 if ((xmlIndentTreeOutput) && (format))
4676 for (i = 0;i < level;i++)
4677 xmlBufferWriteChar(buf, " ");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004678 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00004679 xmlBufferWriteChar(buf, "</");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004680 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00004681 xmlBufferWriteCHAR(buf, cur->ns->prefix);
4682 xmlBufferWriteChar(buf, ":");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004683 }
4684
Daniel Veillard5099ae81999-04-21 20:12:07 +00004685 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillard7d2c2761999-10-11 15:09:51 +00004686 xmlBufferWriteChar(buf, ">");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004687}
4688
Daniel Veillard97b58771998-10-20 06:14:16 +00004689/**
Daniel Veillarddbfd6411999-12-28 16:35:14 +00004690 * xmlElemDump:
Daniel Veillard06047432000-04-24 11:33:38 +00004691 * @f: the FILE * for the output
Daniel Veillarddbfd6411999-12-28 16:35:14 +00004692 * @doc: the document
4693 * @cur: the current node
4694 *
4695 * Dump an XML/HTML node, recursive behaviour,children are printed too.
4696 */
4697void
4698xmlElemDump(FILE *f, xmlDocPtr doc, xmlNodePtr cur) {
4699 xmlBufferPtr buf;
4700
4701 if (cur == NULL) {
4702#ifdef DEBUG_TREE
4703 fprintf(stderr, "xmlElemDump : cur == NULL\n");
4704#endif
4705 return;
4706 }
4707 if (doc == NULL) {
4708#ifdef DEBUG_TREE
4709 fprintf(stderr, "xmlElemDump : doc == NULL\n");
4710#endif
4711 }
4712 buf = xmlBufferCreate();
4713 if (buf == NULL) return;
4714 if ((doc != NULL) &&
4715 (doc->type == XML_HTML_DOCUMENT_NODE)) {
Daniel Veillard361d8452000-04-03 19:48:13 +00004716#ifdef LIBXML_HTML_ENABLED
Daniel Veillarddbfd6411999-12-28 16:35:14 +00004717 htmlNodeDump(buf, doc, cur);
Daniel Veillard361d8452000-04-03 19:48:13 +00004718#else
4719 printf("HTML support not compiled in\n");
4720#endif /* LIBXML_HTML_ENABLED */
Daniel Veillarddbfd6411999-12-28 16:35:14 +00004721 } else
4722 xmlNodeDump(buf, doc, cur, 0, 1);
4723 xmlBufferDump(f, buf);
4724 xmlBufferFree(buf);
4725}
4726
4727/**
Daniel Veillard97b58771998-10-20 06:14:16 +00004728 * xmlDocContentDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00004729 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00004730 * @cur: the document
4731 *
4732 * Dump an XML document.
Daniel Veillard260a68f1998-08-13 03:39:55 +00004733 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00004734static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00004735xmlDocContentDump(xmlBufferPtr buf, xmlDocPtr cur) {
Daniel Veillardbe70ff71999-07-05 16:50:46 +00004736 xmlBufferWriteChar(buf, "<?xml version=");
4737 if (cur->version != NULL)
4738 xmlBufferWriteQuotedString(buf, cur->version);
4739 else
4740 xmlBufferWriteChar(buf, "\"1.0\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004741 if (cur->encoding != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00004742 xmlBufferWriteChar(buf, " encoding=");
4743 xmlBufferWriteQuotedString(buf, cur->encoding);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004744 }
4745 switch (cur->standalone) {
4746 case 0:
Daniel Veillard5099ae81999-04-21 20:12:07 +00004747 xmlBufferWriteChar(buf, " standalone=\"no\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004748 break;
4749 case 1:
Daniel Veillard5099ae81999-04-21 20:12:07 +00004750 xmlBufferWriteChar(buf, " standalone=\"yes\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004751 break;
4752 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00004753 xmlBufferWriteChar(buf, "?>\n");
Daniel Veillardcf461992000-03-14 18:30:20 +00004754 if (cur->children != NULL) {
4755 xmlNodePtr child = cur->children;
Daniel Veillardb96e6431999-08-29 21:02:19 +00004756
Daniel Veillard260a68f1998-08-13 03:39:55 +00004757 /* global namespace definitions, the old way */
4758 if (oldXMLWDcompatibility)
Daniel Veillard5099ae81999-04-21 20:12:07 +00004759 xmlGlobalNsListDump(buf, cur->oldNs);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004760 else
4761 xmlUpgradeOldNs(cur);
Daniel Veillardb96e6431999-08-29 21:02:19 +00004762
4763 while (child != NULL) {
Daniel Veillard7d2c2761999-10-11 15:09:51 +00004764 xmlNodeDump(buf, cur, child, 0, 1);
4765 xmlBufferWriteChar(buf, "\n");
Daniel Veillardb96e6431999-08-29 21:02:19 +00004766 child = child->next;
4767 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00004768 }
4769}
4770
Daniel Veillardbe803962000-06-28 23:40:59 +00004771/************************************************************************
4772 * *
4773 * Dumping XML tree content to an I/O output buffer *
4774 * *
4775 ************************************************************************/
4776
4777static void
4778xmlNodeDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur,
4779 int level, int format, const char *encoding);
4780static void
4781xmlNodeListDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur,
4782 int level, int format, const char *encoding);
4783/**
4784 * xmlGlobalNsDumpOutput:
4785 * @buf: the XML buffer output
4786 * @cur: a namespace
4787 *
4788 * Dump a global Namespace, this is the old version based on PIs.
4789 */
4790static void
4791xmlGlobalNsDumpOutput(xmlOutputBufferPtr buf, xmlNsPtr cur) {
4792 if (cur == NULL) {
4793#ifdef DEBUG_TREE
4794 fprintf(stderr, "xmlGlobalNsDump : Ns == NULL\n");
4795#endif
4796 return;
4797 }
4798 if (cur->type == XML_GLOBAL_NAMESPACE) {
4799 xmlOutputBufferWriteString(buf, "<?namespace");
4800 if (cur->href != NULL) {
4801 xmlOutputBufferWriteString(buf, " href=");
4802 xmlBufferWriteQuotedString(buf->buffer, cur->href);
4803 }
4804 if (cur->prefix != NULL) {
4805 xmlOutputBufferWriteString(buf, " AS=");
4806 xmlBufferWriteQuotedString(buf->buffer, cur->prefix);
4807 }
4808 xmlOutputBufferWriteString(buf, "?>\n");
4809 }
4810}
4811
4812/**
4813 * xmlGlobalNsListDumpOutput:
4814 * @buf: the XML buffer output
4815 * @cur: the first namespace
4816 *
4817 * Dump a list of global Namespace, this is the old version based on PIs.
4818 */
4819static void
4820xmlGlobalNsListDumpOutput(xmlOutputBufferPtr buf, xmlNsPtr cur) {
4821 while (cur != NULL) {
4822 xmlGlobalNsDumpOutput(buf, cur);
4823 cur = cur->next;
4824 }
4825}
4826
4827/**
4828 * xmlNsDumpOutput:
4829 * @buf: the XML buffer output
4830 * @cur: a namespace
4831 *
4832 * Dump a local Namespace definition.
4833 * Should be called in the context of attributes dumps.
4834 */
4835static void
4836xmlNsDumpOutput(xmlOutputBufferPtr buf, xmlNsPtr cur) {
4837 if (cur == NULL) {
4838#ifdef DEBUG_TREE
4839 fprintf(stderr, "xmlNsDump : Ns == NULL\n");
4840#endif
4841 return;
4842 }
4843 if (cur->type == XML_LOCAL_NAMESPACE) {
4844 /* Within the context of an element attributes */
4845 if (cur->prefix != NULL) {
4846 xmlOutputBufferWriteString(buf, " xmlns:");
4847 xmlOutputBufferWriteString(buf, (const char *)cur->prefix);
4848 } else
4849 xmlOutputBufferWriteString(buf, " xmlns");
4850 xmlOutputBufferWriteString(buf, "=");
4851 xmlBufferWriteQuotedString(buf->buffer, cur->href);
4852 }
4853}
4854
4855/**
4856 * xmlNsListDumpOutput:
4857 * @buf: the XML buffer output
4858 * @cur: the first namespace
4859 *
4860 * Dump a list of local Namespace definitions.
4861 * Should be called in the context of attributes dumps.
4862 */
4863static void
4864xmlNsListDumpOutput(xmlOutputBufferPtr buf, xmlNsPtr cur) {
4865 while (cur != NULL) {
4866 xmlNsDumpOutput(buf, cur);
4867 cur = cur->next;
4868 }
4869}
4870
4871/**
4872 * xmlDtdDumpOutput:
4873 * @buf: the XML buffer output
4874 * @doc: the document
4875 * @encoding: an optional encoding string
4876 *
4877 * Dump the XML document DTD, if any.
4878 */
4879static void
4880xmlDtdDumpOutput(xmlOutputBufferPtr buf, xmlDtdPtr dtd, const char *encoding) {
4881 if (dtd == NULL) {
4882#ifdef DEBUG_TREE
4883 fprintf(stderr, "xmlDtdDump : no internal subset\n");
4884#endif
4885 return;
4886 }
4887 xmlOutputBufferWriteString(buf, "<!DOCTYPE ");
4888 xmlOutputBufferWriteString(buf, (const char *)dtd->name);
4889 if (dtd->ExternalID != NULL) {
4890 xmlOutputBufferWriteString(buf, " PUBLIC ");
4891 xmlBufferWriteQuotedString(buf->buffer, dtd->ExternalID);
4892 xmlOutputBufferWriteString(buf, " ");
4893 xmlBufferWriteQuotedString(buf->buffer, dtd->SystemID);
4894 } else if (dtd->SystemID != NULL) {
4895 xmlOutputBufferWriteString(buf, " SYSTEM ");
4896 xmlBufferWriteQuotedString(buf->buffer, dtd->SystemID);
4897 }
4898 if ((dtd->entities == NULL) && (dtd->elements == NULL) &&
4899 (dtd->attributes == NULL) && (dtd->notations == NULL)) {
4900 xmlOutputBufferWriteString(buf, ">");
4901 return;
4902 }
4903 xmlOutputBufferWriteString(buf, " [\n");
4904 xmlNodeListDumpOutput(buf, dtd->doc, dtd->children, -1, 0, encoding);
4905#if 0
4906 if (dtd->entities != NULL)
4907 xmlDumpEntitiesTable(buf, (xmlEntitiesTablePtr) dtd->entities);
4908 if (dtd->notations != NULL)
4909 xmlDumpNotationTable(buf, (xmlNotationTablePtr) dtd->notations);
4910 if (dtd->elements != NULL)
4911 xmlDumpElementTable(buf, (xmlElementTablePtr) dtd->elements);
4912 if (dtd->attributes != NULL)
4913 xmlDumpAttributeTable(buf, (xmlAttributeTablePtr) dtd->attributes);
4914#endif
4915 xmlOutputBufferWriteString(buf, "]>");
4916}
4917
4918/**
4919 * xmlAttrDumpOutput:
4920 * @buf: the XML buffer output
4921 * @doc: the document
4922 * @cur: the attribute pointer
4923 * @encoding: an optional encoding string
4924 *
4925 * Dump an XML attribute
4926 */
4927static void
4928xmlAttrDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur,
4929 const char *encoding) {
4930 xmlChar *value;
4931
4932 if (cur == NULL) {
4933#ifdef DEBUG_TREE
4934 fprintf(stderr, "xmlAttrDump : property == NULL\n");
4935#endif
4936 return;
4937 }
4938 xmlOutputBufferWriteString(buf, " ");
4939 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
4940 xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
4941 xmlOutputBufferWriteString(buf, ":");
4942 }
4943 xmlOutputBufferWriteString(buf, (const char *)cur->name);
4944 value = xmlNodeListGetString(doc, cur->children, 0);
4945 if (value) {
4946 xmlOutputBufferWriteString(buf, "=");
4947 xmlBufferWriteQuotedString(buf->buffer, value);
4948 xmlFree(value);
4949 } else {
4950 xmlOutputBufferWriteString(buf, "=\"\"");
4951 }
4952}
4953
4954/**
4955 * xmlAttrListDumpOutput:
4956 * @buf: the XML buffer output
4957 * @doc: the document
4958 * @cur: the first attribute pointer
4959 * @encoding: an optional encoding string
4960 *
4961 * Dump a list of XML attributes
4962 */
4963static void
4964xmlAttrListDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc,
4965 xmlAttrPtr cur, const char *encoding) {
4966 if (cur == NULL) {
4967#ifdef DEBUG_TREE
4968 fprintf(stderr, "xmlAttrListDump : property == NULL\n");
4969#endif
4970 return;
4971 }
4972 while (cur != NULL) {
4973 xmlAttrDumpOutput(buf, doc, cur, encoding);
4974 cur = cur->next;
4975 }
4976}
4977
4978
4979
4980/**
4981 * xmlNodeListDumpOutput:
4982 * @buf: the XML buffer output
4983 * @doc: the document
4984 * @cur: the first node
4985 * @level: the imbrication level for indenting
4986 * @format: is formatting allowed
4987 * @encoding: an optional encoding string
4988 *
4989 * Dump an XML node list, recursive behaviour,children are printed too.
4990 */
4991static void
4992xmlNodeListDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc,
4993 xmlNodePtr cur, int level, int format, const char *encoding) {
4994 int i;
4995
4996 if (cur == NULL) {
4997#ifdef DEBUG_TREE
4998 fprintf(stderr, "xmlNodeListDump : node == NULL\n");
4999#endif
5000 return;
5001 }
5002 while (cur != NULL) {
5003 if ((format) && (xmlIndentTreeOutput) &&
5004 (cur->type == XML_ELEMENT_NODE))
5005 for (i = 0;i < level;i++)
5006 xmlOutputBufferWriteString(buf, " ");
5007 xmlNodeDumpOutput(buf, doc, cur, level, format, encoding);
5008 if (format) {
5009 xmlOutputBufferWriteString(buf, "\n");
5010 }
5011 cur = cur->next;
5012 }
5013}
5014
5015/**
5016 * xmlNodeDumpOutput:
5017 * @buf: the XML buffer output
5018 * @doc: the document
5019 * @cur: the current node
5020 * @level: the imbrication level for indenting
5021 * @format: is formatting allowed
5022 * @encoding: an optional encoding string
5023 *
5024 * Dump an XML node, recursive behaviour,children are printed too.
5025 */
5026static void
5027xmlNodeDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur,
5028 int level, int format, const char *encoding) {
5029 int i;
5030 xmlNodePtr tmp;
5031
5032 if (cur == NULL) {
5033#ifdef DEBUG_TREE
5034 fprintf(stderr, "xmlNodeDump : node == NULL\n");
5035#endif
5036 return;
5037 }
5038 if (cur->type == XML_DTD_NODE) {
5039 xmlDtdDumpOutput(buf, (xmlDtdPtr) cur, encoding);
5040 return;
5041 }
5042 if (cur->type == XML_ELEMENT_DECL) {
5043 xmlDumpElementDecl(buf->buffer, (xmlElementPtr) cur);
5044 return;
5045 }
5046 if (cur->type == XML_ATTRIBUTE_DECL) {
5047 xmlDumpAttributeDecl(buf->buffer, (xmlAttributePtr) cur);
5048 return;
5049 }
5050 if (cur->type == XML_ENTITY_DECL) {
5051 xmlDumpEntityDecl(buf->buffer, (xmlEntityPtr) cur);
5052 return;
5053 }
5054 if (cur->type == XML_TEXT_NODE) {
5055 if (cur->content != NULL) {
5056 xmlChar *buffer;
5057
5058#ifndef XML_USE_BUFFER_CONTENT
5059 if (encoding == NULL)
5060 buffer = xmlEncodeEntitiesReentrant(doc, cur->content);
5061 else
5062 buffer = xmlEncodeSpecialChars(doc, cur->content);
5063#else
5064 if (encoding == NULL)
5065 buffer = xmlEncodeEntitiesReentrant(doc,
5066 xmlBufferContent(cur->content));
5067 else
5068 buffer = xmlEncodeSpecialChars(doc,
5069 xmlBufferContent(cur->content));
5070#endif
5071 if (buffer != NULL) {
5072 xmlOutputBufferWriteString(buf, (const char *)buffer);
5073 xmlFree(buffer);
5074 }
5075 }
5076 return;
5077 }
5078 if (cur->type == XML_PI_NODE) {
5079 if (cur->content != NULL) {
5080 xmlOutputBufferWriteString(buf, "<?");
5081 xmlOutputBufferWriteString(buf, (const char *)cur->name);
5082 if (cur->content != NULL) {
5083 xmlOutputBufferWriteString(buf, " ");
5084#ifndef XML_USE_BUFFER_CONTENT
5085 xmlOutputBufferWriteString(buf, (const char *)cur->content);
5086#else
5087 xmlOutputBufferWriteString(buf, (const char *)xmlBufferContent(cur->content));
5088#endif
5089 }
5090 xmlOutputBufferWriteString(buf, "?>");
5091 } else {
5092 xmlOutputBufferWriteString(buf, "<?");
5093 xmlOutputBufferWriteString(buf, (const char *)cur->name);
5094 xmlOutputBufferWriteString(buf, "?>");
5095 }
5096 return;
5097 }
5098 if (cur->type == XML_COMMENT_NODE) {
5099 if (cur->content != NULL) {
5100 xmlOutputBufferWriteString(buf, "<!--");
5101#ifndef XML_USE_BUFFER_CONTENT
5102 xmlOutputBufferWriteString(buf, (const char *)cur->content);
5103#else
5104 xmlOutputBufferWriteString(buf, (const char *)xmlBufferContent(cur->content));
5105#endif
5106 xmlOutputBufferWriteString(buf, "-->");
5107 }
5108 return;
5109 }
5110 if (cur->type == XML_ENTITY_REF_NODE) {
5111 xmlOutputBufferWriteString(buf, "&");
5112 xmlOutputBufferWriteString(buf, (const char *)cur->name);
5113 xmlOutputBufferWriteString(buf, ";");
5114 return;
5115 }
5116 if (cur->type == XML_CDATA_SECTION_NODE) {
5117 xmlOutputBufferWriteString(buf, "<![CDATA[");
5118 if (cur->content != NULL)
5119#ifndef XML_USE_BUFFER_CONTENT
5120 xmlOutputBufferWriteString(buf, (const char *)cur->content);
5121#else
5122 xmlOutputBufferWriteString(buf, (const char *)xmlBufferContent(cur->content));
5123#endif
5124 xmlOutputBufferWriteString(buf, "]]>");
5125 return;
5126 }
5127
5128 if (format == 1) {
5129 tmp = cur->children;
5130 while (tmp != NULL) {
5131 if ((tmp->type == XML_TEXT_NODE) ||
5132 (tmp->type == XML_ENTITY_REF_NODE)) {
5133 format = 0;
5134 break;
5135 }
5136 tmp = tmp->next;
5137 }
5138 }
5139 xmlOutputBufferWriteString(buf, "<");
5140 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
5141 xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
5142 xmlOutputBufferWriteString(buf, ":");
5143 }
5144
5145 xmlOutputBufferWriteString(buf, (const char *)cur->name);
5146 if (cur->nsDef)
5147 xmlNsListDumpOutput(buf, cur->nsDef);
5148 if (cur->properties != NULL)
5149 xmlAttrListDumpOutput(buf, doc, cur->properties, encoding);
5150
5151 if ((cur->content == NULL) && (cur->children == NULL) &&
5152 (!xmlSaveNoEmptyTags)) {
5153 xmlOutputBufferWriteString(buf, "/>");
5154 return;
5155 }
5156 xmlOutputBufferWriteString(buf, ">");
5157 if (cur->content != NULL) {
5158 xmlChar *buffer;
5159
5160#ifndef XML_USE_BUFFER_CONTENT
5161 if (encoding == NULL)
5162 buffer = xmlEncodeEntitiesReentrant(doc, cur->content);
5163 else
5164 buffer = xmlEncodeSpecialChars(doc, cur->content);
5165#else
5166 if (encoding == NULL)
5167 buffer = xmlEncodeEntitiesReentrant(doc,
5168 xmlBufferContent(cur->content));
5169 else
5170 buffer = xmlEncodeSpecialChars(doc,
5171 xmlBufferContent(cur->content));
5172#endif
5173 if (buffer != NULL) {
5174 xmlOutputBufferWriteString(buf, (const char *)buffer);
5175 xmlFree(buffer);
5176 }
5177 }
5178 if (cur->children != NULL) {
5179 if (format) xmlOutputBufferWriteString(buf, "\n");
5180 xmlNodeListDumpOutput(buf, doc, cur->children,
5181 (level >= 0?level+1:-1), format, encoding);
5182 if ((xmlIndentTreeOutput) && (format))
5183 for (i = 0;i < level;i++)
5184 xmlOutputBufferWriteString(buf, " ");
5185 }
5186 xmlOutputBufferWriteString(buf, "</");
5187 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
5188 xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
5189 xmlOutputBufferWriteString(buf, ":");
5190 }
5191
5192 xmlOutputBufferWriteString(buf, (const char *)cur->name);
5193 xmlOutputBufferWriteString(buf, ">");
5194}
5195
5196/**
5197 * xmlDocContentDumpOutput:
5198 * @buf: the XML buffer output
5199 * @cur: the document
5200 * @encoding: an optional encoding string
5201 *
5202 * Dump an XML document.
5203 */
5204static void
5205xmlDocContentDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr cur,
5206 const char *encoding) {
5207 xmlOutputBufferWriteString(buf, "<?xml version=");
5208 if (cur->version != NULL)
5209 xmlBufferWriteQuotedString(buf->buffer, cur->version);
5210 else
5211 xmlOutputBufferWriteString(buf, "\"1.0\"");
5212 if (encoding == NULL) {
5213 if (cur->encoding != NULL)
5214 encoding = (const char *) cur->encoding;
5215 else if (cur->charset != XML_CHAR_ENCODING_UTF8)
Daniel Veillard32bc74e2000-07-14 14:49:25 +00005216 encoding = xmlGetCharEncodingName((xmlCharEncoding) cur->charset);
Daniel Veillardbe803962000-06-28 23:40:59 +00005217 }
5218 if (encoding != NULL) {
5219 xmlOutputBufferWriteString(buf, " encoding=");
5220 xmlBufferWriteQuotedString(buf->buffer, (xmlChar *) encoding);
5221 }
5222 switch (cur->standalone) {
5223 case 0:
5224 xmlOutputBufferWriteString(buf, " standalone=\"no\"");
5225 break;
5226 case 1:
5227 xmlOutputBufferWriteString(buf, " standalone=\"yes\"");
5228 break;
5229 }
5230 xmlOutputBufferWriteString(buf, "?>\n");
5231 if (cur->children != NULL) {
5232 xmlNodePtr child = cur->children;
5233
5234 /* global namespace definitions, the old way */
5235 if (oldXMLWDcompatibility)
5236 xmlGlobalNsListDumpOutput(buf, cur->oldNs);
5237 else
5238 xmlUpgradeOldNs(cur);
5239
5240 while (child != NULL) {
5241 xmlNodeDumpOutput(buf, cur, child, 0, 1, encoding);
5242 xmlOutputBufferWriteString(buf, "\n");
5243 child = child->next;
5244 }
5245 }
5246}
5247
5248/************************************************************************
5249 * *
5250 * Saving functions front-ends *
5251 * *
5252 ************************************************************************/
5253
Daniel Veillard97b58771998-10-20 06:14:16 +00005254/**
5255 * xmlDocDumpMemory:
5256 * @cur: the document
5257 * @mem: OUT: the memory pointer
5258 * @size: OUT: the memory lenght
5259 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +00005260 * Dump an XML document in memory and return the xmlChar * and it's size.
Daniel Veillard97b58771998-10-20 06:14:16 +00005261 * It's up to the caller to free the memory.
Daniel Veillard260a68f1998-08-13 03:39:55 +00005262 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00005263void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00005264xmlDocDumpMemory(xmlDocPtr cur, xmlChar**mem, int *size) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00005265 xmlBufferPtr buf;
5266
Daniel Veillard260a68f1998-08-13 03:39:55 +00005267 if (cur == NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00005268#ifdef DEBUG_TREE
5269 fprintf(stderr, "xmlDocDumpMemory : document == NULL\n");
5270#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00005271 *mem = NULL;
5272 *size = 0;
5273 return;
5274 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00005275 buf = xmlBufferCreate();
5276 if (buf == NULL) {
5277 *mem = NULL;
5278 *size = 0;
5279 return;
5280 }
5281 xmlDocContentDump(buf, cur);
Daniel Veillardb05deb71999-08-10 19:04:08 +00005282 *mem = xmlStrndup(buf->content, buf->use);
Daniel Veillard5099ae81999-04-21 20:12:07 +00005283 *size = buf->use;
Daniel Veillardb05deb71999-08-10 19:04:08 +00005284 xmlBufferFree(buf);
Daniel Veillard260a68f1998-08-13 03:39:55 +00005285}
5286
Daniel Veillard97b58771998-10-20 06:14:16 +00005287/**
5288 * xmlGetDocCompressMode:
5289 * @doc: the document
5290 *
5291 * get the compression ratio for a document, ZLIB based
Daniel Veillard1e346af1999-02-22 10:33:01 +00005292 * Returns 0 (uncompressed) to 9 (max compression)
Daniel Veillard151b1b01998-09-23 00:49:46 +00005293 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00005294int
Daniel Veillarddbfd6411999-12-28 16:35:14 +00005295xmlGetDocCompressMode (xmlDocPtr doc) {
Daniel Veillard15a8df41998-09-24 19:15:06 +00005296 if (doc == NULL) return(-1);
5297 return(doc->compression);
5298}
5299
Daniel Veillard97b58771998-10-20 06:14:16 +00005300/**
5301 * xmlSetDocCompressMode:
5302 * @doc: the document
5303 * @mode: the compression ratio
5304 *
5305 * set the compression ratio for a document, ZLIB based
5306 * Correct values: 0 (uncompressed) to 9 (max compression)
5307 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00005308void
5309xmlSetDocCompressMode (xmlDocPtr doc, int mode) {
Daniel Veillard15a8df41998-09-24 19:15:06 +00005310 if (doc == NULL) return;
5311 if (mode < 0) doc->compression = 0;
5312 else if (mode > 9) doc->compression = 9;
5313 else doc->compression = mode;
5314}
5315
Daniel Veillard97b58771998-10-20 06:14:16 +00005316/**
5317 * xmlGetCompressMode:
5318 *
5319 * get the default compression mode used, ZLIB based.
Daniel Veillard1e346af1999-02-22 10:33:01 +00005320 * Returns 0 (uncompressed) to 9 (max compression)
Daniel Veillard15a8df41998-09-24 19:15:06 +00005321 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00005322int
5323 xmlGetCompressMode(void) {
Daniel Veillard151b1b01998-09-23 00:49:46 +00005324 return(xmlCompressMode);
5325}
Daniel Veillard97b58771998-10-20 06:14:16 +00005326
5327/**
5328 * xmlSetCompressMode:
5329 * @mode: the compression ratio
5330 *
5331 * set the default compression mode used, ZLIB based
5332 * Correct values: 0 (uncompressed) to 9 (max compression)
5333 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00005334void
5335xmlSetCompressMode(int mode) {
Daniel Veillard151b1b01998-09-23 00:49:46 +00005336 if (mode < 0) xmlCompressMode = 0;
Daniel Veillard15a8df41998-09-24 19:15:06 +00005337 else if (mode > 9) xmlCompressMode = 9;
Daniel Veillard151b1b01998-09-23 00:49:46 +00005338 else xmlCompressMode = mode;
5339}
5340
Daniel Veillardbe803962000-06-28 23:40:59 +00005341/**
5342 * xmlDocDump:
5343 * @f: the FILE*
5344 * @cur: the document
5345 *
5346 * Dump an XML document to an open FILE.
5347 *
Daniel Veillard32bc74e2000-07-14 14:49:25 +00005348 * returns: the number of byte written or -1 in case of failure.
Daniel Veillardbe803962000-06-28 23:40:59 +00005349 */
5350int
5351xmlDocDump(FILE *f, xmlDocPtr cur) {
5352 xmlOutputBufferPtr buf;
Daniel Veillard32bc74e2000-07-14 14:49:25 +00005353 const char * encoding;
5354 xmlCharEncodingHandlerPtr handler = NULL;
Daniel Veillardbe803962000-06-28 23:40:59 +00005355 int ret;
Daniel Veillard151b1b01998-09-23 00:49:46 +00005356
Daniel Veillardbe803962000-06-28 23:40:59 +00005357 if (cur == NULL) {
5358#ifdef DEBUG_TREE
5359 fprintf(stderr, "xmlDocDump : document == NULL\n");
5360#endif
5361 return(-1);
5362 }
Daniel Veillard32bc74e2000-07-14 14:49:25 +00005363 encoding = (const char *) cur->encoding;
5364
5365 if (encoding != NULL) {
5366 xmlCharEncoding enc;
5367
5368 enc = xmlParseCharEncoding(encoding);
5369
5370 if (cur->charset != XML_CHAR_ENCODING_UTF8) {
5371 fprintf(stderr, "xmlDocDump: document not in UTF8\n");
5372 return(-1);
5373 }
5374 if (enc != XML_CHAR_ENCODING_UTF8) {
5375 handler = xmlFindCharEncodingHandler(encoding);
5376 if (handler == NULL) {
5377 xmlFree((char *) cur->encoding);
5378 cur->encoding = NULL;
5379 }
5380 }
5381 }
5382 buf = xmlOutputBufferCreateFile(f, handler);
Daniel Veillardbe803962000-06-28 23:40:59 +00005383 if (buf == NULL) return(-1);
5384 xmlDocContentDumpOutput(buf, cur, NULL);
5385
5386 ret = xmlOutputBufferClose(buf);
5387 return(ret);
5388}
5389
5390/**
Daniel Veillardbe803962000-06-28 23:40:59 +00005391 * xmlSaveFileTo:
5392 * @buf: an output I/O buffer
5393 * @cur: the document
5394 * @encoding: the encoding if any assuming the i/O layer handles the trancoding
5395 *
5396 * Dump an XML document to an I/O buffer.
5397 *
Daniel Veillard32bc74e2000-07-14 14:49:25 +00005398 * returns: the number of byte written or -1 in case of failure.
Daniel Veillardbe803962000-06-28 23:40:59 +00005399 */
5400int
5401xmlSaveFileTo(xmlOutputBuffer *buf, xmlDocPtr cur, const char *encoding) {
5402 int ret;
5403
5404 if (buf == NULL) return(0);
5405 xmlDocContentDumpOutput(buf, cur, encoding);
5406 ret = xmlOutputBufferClose(buf);
5407 return(ret);
5408}
5409
5410/**
5411 * xmlSaveFileEnc:
5412 * @filename: the filename (or URL)
5413 * @cur: the document
5414 * @encoding: the name of an encoding (or NULL)
5415 *
5416 * Dump an XML document, converting it to the given encoding
5417 *
Daniel Veillard32bc74e2000-07-14 14:49:25 +00005418 * returns: the number of byte written or -1 in case of failure.
Daniel Veillardbe803962000-06-28 23:40:59 +00005419 */
5420int
5421xmlSaveFileEnc(const char *filename, xmlDocPtr cur, const char *encoding) {
5422 xmlOutputBufferPtr buf;
5423 xmlCharEncodingHandlerPtr handler = NULL;
5424 int ret;
5425
5426 if (encoding != NULL) {
5427 xmlCharEncoding enc;
5428
5429 enc = xmlParseCharEncoding(encoding);
Daniel Veillard32bc74e2000-07-14 14:49:25 +00005430 if (cur->charset != XML_CHAR_ENCODING_UTF8) {
5431 fprintf(stderr, "xmlSaveFileEnc: document not in UTF8\n");
5432 return(-1);
5433 }
5434 if (enc != XML_CHAR_ENCODING_UTF8) {
5435 handler = xmlFindCharEncodingHandler(encoding);
5436 if (handler == NULL) {
Daniel Veillardbe803962000-06-28 23:40:59 +00005437 return(-1);
5438 }
Daniel Veillardbe803962000-06-28 23:40:59 +00005439 }
5440 }
5441
5442 /*
5443 * save the content to a temp buffer.
5444 */
5445 buf = xmlOutputBufferCreateFilename(filename, handler, 0);
5446 if (buf == NULL) return(0);
5447
5448 xmlDocContentDumpOutput(buf, cur, encoding);
5449
5450 ret = xmlOutputBufferClose(buf);
5451 return(ret);
5452}
Daniel Veillard32bc74e2000-07-14 14:49:25 +00005453
5454/**
5455 * xmlSaveFile:
5456 * @filename: the filename (or URL)
5457 * @cur: the document
5458 *
5459 * Dump an XML document to a file. Will use compression if
5460 * compiled in and enabled. If @filename is "-" the stdout file is
5461 * used.
5462 * returns: the number of byte written or -1 in case of failure.
5463 */
5464int
5465xmlSaveFile(const char *filename, xmlDocPtr cur) {
5466 xmlOutputBufferPtr buf;
5467 const char *encoding;
5468 xmlCharEncodingHandlerPtr handler = NULL;
5469 int ret;
5470
5471 if (cur == NULL)
5472 return(-1);
5473 encoding = (const char *) cur->encoding;
5474
5475 /*
5476 * save the content to a temp buffer.
5477 */
5478#ifdef HAVE_ZLIB_H
5479 if (cur->compression < 0) cur->compression = xmlCompressMode;
Daniel Veillardbe803962000-06-28 23:40:59 +00005480#endif
Daniel Veillard32bc74e2000-07-14 14:49:25 +00005481 if (encoding != NULL) {
5482 xmlCharEncoding enc;
5483
5484 enc = xmlParseCharEncoding(encoding);
5485
5486 if (cur->charset != XML_CHAR_ENCODING_UTF8) {
5487 fprintf(stderr, "xmlSaveFile: document not in UTF8\n");
5488 return(-1);
5489 }
5490 if (enc != XML_CHAR_ENCODING_UTF8) {
5491 handler = xmlFindCharEncodingHandler(encoding);
5492 if (handler == NULL) {
5493 xmlFree((char *) cur->encoding);
5494 cur->encoding = NULL;
5495 }
5496 }
5497 }
5498
5499 buf = xmlOutputBufferCreateFilename(filename, handler, cur->compression);
5500 if (buf == NULL) return(0);
5501
5502 xmlDocContentDumpOutput(buf, cur, NULL);
5503
5504 ret = xmlOutputBufferClose(buf);
5505 return(ret);
5506}
5507