blob: c6685eaf8928bd346e2a3bab09a0edc0d405339a [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 Veillard6454aec1999-09-02 22:04:43 +000028#include "xmlmemory.h"
Daniel Veillard260a68f1998-08-13 03:39:55 +000029#include "tree.h"
Daniel Veillard37846c61999-12-16 17:52:19 +000030#include "parser.h"
Daniel Veillard260a68f1998-08-13 03:39:55 +000031#include "entities.h"
Daniel Veillard3b9def11999-01-31 22:15:06 +000032#include "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 Veillard260a68f1998-08-13 03:39:55 +000035int oldXMLWDcompatibility = 0;
36int xmlIndentTreeOutput = 1;
Daniel Veillardf5c2c871999-12-01 09:51:45 +000037xmlBufferAllocationScheme xmlBufferAllocScheme = XML_BUFFER_ALLOC_EXACT;
Daniel Veillard260a68f1998-08-13 03:39:55 +000038
Daniel Veillard15a8df41998-09-24 19:15:06 +000039static int xmlCompressMode = 0;
Daniel Veillard10a2c651999-12-12 13:03:50 +000040static int xmlCheckDTD = 1;
Daniel Veillard15a8df41998-09-24 19:15:06 +000041
Daniel Veillard39a1f9a1999-01-17 19:11:59 +000042#define UPDATE_LAST_CHILD(n) if ((n) != NULL) { \
43 xmlNodePtr ulccur = (n)->childs; \
44 if (ulccur == NULL) { \
45 (n)->last = NULL; \
46 } else { \
47 while (ulccur->next != NULL) ulccur = ulccur->next; \
48 (n)->last = ulccur; \
Daniel Veillard1e346af1999-02-22 10:33:01 +000049}}
Daniel Veillard39a1f9a1999-01-17 19:11:59 +000050
Daniel Veillard260a68f1998-08-13 03:39:55 +000051/************************************************************************
52 * *
53 * Allocation and deallocation of basic structures *
54 * *
55 ************************************************************************/
56
Daniel Veillard97b58771998-10-20 06:14:16 +000057/**
Daniel Veillardf5c2c871999-12-01 09:51:45 +000058 * xmlSetBufferAllocationScheme:
59 * @scheme: allocation method to use
60 *
61 * Set the buffer allocation method. Types are
62 * XML_BUFFER_ALLOC_EXACT - use exact sizes, keeps memory usage down
63 * XML_BUFFER_ALLOC_DOUBLEIT - double buffer when extra needed,
64 * improves performance
65 */
66void
67xmlSetBufferAllocationScheme(xmlBufferAllocationScheme scheme) {
68 xmlBufferAllocScheme = scheme;
69}
70
71/**
72 * xmlGetBufferAllocationScheme:
73 *
74 * Types are
75 * XML_BUFFER_ALLOC_EXACT - use exact sizes, keeps memory usage down
76 * XML_BUFFER_ALLOC_DOUBLEIT - double buffer when extra needed,
77 * improves performance
78 *
79 * Returns the current allocation scheme
80 */
81xmlBufferAllocationScheme
82xmlGetBufferAllocationScheme() {
83 return xmlBufferAllocScheme;
84}
85
86/**
Daniel Veillard97b58771998-10-20 06:14:16 +000087 * xmlUpgradeOldNs:
88 * @doc: a document pointer
89 *
90 * Upgrade old style Namespaces (PI) and move them to the root of the document.
Daniel Veillard260a68f1998-08-13 03:39:55 +000091 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +000092void
93xmlUpgradeOldNs(xmlDocPtr doc) {
Daniel Veillard260a68f1998-08-13 03:39:55 +000094 xmlNsPtr cur;
95
96 if ((doc == NULL) || (doc->oldNs == NULL)) return;
97 if (doc->root == NULL) {
98 fprintf(stderr, "xmlUpgradeOldNs: failed no root !\n");
99 return;
100 }
101
102 cur = doc->oldNs;
103 while (cur->next != NULL) {
104 cur->type = XML_LOCAL_NAMESPACE;
105 cur = cur->next;
106 }
107 cur->type = XML_LOCAL_NAMESPACE;
108 cur->next = doc->root->nsDef;
109 doc->root->nsDef = doc->oldNs;
110 doc->oldNs = NULL;
111}
112
Daniel Veillard97b58771998-10-20 06:14:16 +0000113/**
114 * xmlNewNs:
115 * @node: the element carrying the namespace
116 * @href: the URI associated
117 * @prefix: the prefix for the namespace
118 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000119 * Creation of a new Namespace.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000120 * Returns returns a new namespace pointer
Daniel Veillard260a68f1998-08-13 03:39:55 +0000121 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000122xmlNsPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000123xmlNewNs(xmlNodePtr node, const xmlChar *href, const xmlChar *prefix) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000124 xmlNsPtr cur;
125
126 if (href == NULL) {
127 fprintf(stderr, "xmlNewNs: href == NULL !\n");
128 return(NULL);
129 }
130
131 /*
132 * Allocate a new DTD and fill the fields.
133 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000134 cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000135 if (cur == NULL) {
136 fprintf(stderr, "xmlNewNs : malloc failed\n");
137 return(NULL);
138 }
139
140 cur->type = XML_LOCAL_NAMESPACE;
141 if (href != NULL)
142 cur->href = xmlStrdup(href);
143 else
144 cur->href = NULL;
145 if (prefix != NULL)
146 cur->prefix = xmlStrdup(prefix);
147 else
148 cur->prefix = NULL;
149
150 /*
151 * Add it at the end to preserve parsing order ...
152 */
153 cur->next = NULL;
154 if (node != NULL) {
155 if (node->nsDef == NULL) {
156 node->nsDef = cur;
157 } else {
158 xmlNsPtr prev = node->nsDef;
159
160 while (prev->next != NULL) prev = prev->next;
161 prev->next = cur;
162 }
163 }
164
165 return(cur);
166}
167
Daniel Veillard97b58771998-10-20 06:14:16 +0000168/**
169 * xmlNewGlobalNs:
170 * @doc: the document carrying the namespace
171 * @href: the URI associated
172 * @prefix: the prefix for the namespace
173 *
174 * Creation of a Namespace, the old way using PI and without scoping, to AVOID.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000175 * Returns returns a new namespace pointer
Daniel Veillard260a68f1998-08-13 03:39:55 +0000176 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000177xmlNsPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000178xmlNewGlobalNs(xmlDocPtr doc, const xmlChar *href, const xmlChar *prefix) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000179 xmlNsPtr cur;
180
181 /*
182 * Allocate a new DTD and fill the fields.
183 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000184 cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000185 if (cur == NULL) {
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000186 fprintf(stderr, "xmlNewGlobalNs : malloc failed\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +0000187 return(NULL);
188 }
189
190 cur->type = XML_GLOBAL_NAMESPACE;
191 if (href != NULL)
192 cur->href = xmlStrdup(href);
193 else
194 cur->href = NULL;
195 if (prefix != NULL)
196 cur->prefix = xmlStrdup(prefix);
197 else
198 cur->prefix = NULL;
199
200 /*
201 * Add it at the end to preserve parsing order ...
202 */
203 cur->next = NULL;
204 if (doc != NULL) {
205 if (doc->oldNs == NULL) {
206 doc->oldNs = cur;
207 } else {
208 xmlNsPtr prev = doc->oldNs;
209
210 while (prev->next != NULL) prev = prev->next;
211 prev->next = cur;
212 }
213 }
214
215 return(cur);
216}
217
Daniel Veillard97b58771998-10-20 06:14:16 +0000218/**
219 * xmlSetNs:
220 * @node: a node in the document
221 * @ns: a namespace pointer
222 *
223 * Associate a namespace to a node, a posteriori.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000224 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000225void
226xmlSetNs(xmlNodePtr node, xmlNsPtr ns) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000227 if (node == NULL) {
228 fprintf(stderr, "xmlSetNs: node == NULL\n");
229 return;
230 }
231 node->ns = ns;
232}
233
Daniel Veillard97b58771998-10-20 06:14:16 +0000234/**
235 * xmlFreeNs:
236 * @cur: the namespace pointer
237 *
238 * Free up the structures associated to a namespace
Daniel Veillard260a68f1998-08-13 03:39:55 +0000239 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000240void
241xmlFreeNs(xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000242 if (cur == NULL) {
243 fprintf(stderr, "xmlFreeNs : ns == NULL\n");
244 return;
245 }
Daniel Veillard6454aec1999-09-02 22:04:43 +0000246 if (cur->href != NULL) xmlFree((char *) cur->href);
247 if (cur->prefix != NULL) xmlFree((char *) cur->prefix);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000248 memset(cur, -1, sizeof(xmlNs));
Daniel Veillard6454aec1999-09-02 22:04:43 +0000249 xmlFree(cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000250}
251
Daniel Veillard97b58771998-10-20 06:14:16 +0000252/**
253 * xmlFreeNsList:
254 * @cur: the first namespace pointer
255 *
256 * Free up all the structures associated to the chained namespaces.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000257 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000258void
259xmlFreeNsList(xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000260 xmlNsPtr next;
261 if (cur == NULL) {
262 fprintf(stderr, "xmlFreeNsList : ns == NULL\n");
263 return;
264 }
265 while (cur != NULL) {
266 next = cur->next;
267 xmlFreeNs(cur);
268 cur = next;
269 }
270}
271
Daniel Veillard97b58771998-10-20 06:14:16 +0000272/**
273 * xmlNewDtd:
274 * @doc: the document pointer
275 * @name: the DTD name
276 * @ExternalID: the external ID
277 * @SystemID: the system ID
278 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000279 * Creation of a new DTD.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000280 * Returns a pointer to the new DTD structure
Daniel Veillard260a68f1998-08-13 03:39:55 +0000281 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000282xmlDtdPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000283xmlNewDtd(xmlDocPtr doc, const xmlChar *name,
284 const xmlChar *ExternalID, const xmlChar *SystemID) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000285 xmlDtdPtr cur;
286
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000287 if ((doc != NULL) && (doc->extSubset != NULL)) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000288 fprintf(stderr, "xmlNewDtd(%s): document %s already have a DTD %s\n",
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000289 /* !!! */ (char *) name, doc->name,
290 /* !!! */ (char *)doc->extSubset->name);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000291 }
292
293 /*
294 * Allocate a new DTD and fill the fields.
295 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000296 cur = (xmlDtdPtr) xmlMalloc(sizeof(xmlDtd));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000297 if (cur == NULL) {
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000298 fprintf(stderr, "xmlNewDtd : malloc failed\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +0000299 return(NULL);
300 }
301
302 if (name != NULL)
303 cur->name = xmlStrdup(name);
304 else
305 cur->name = NULL;
306 if (ExternalID != NULL)
307 cur->ExternalID = xmlStrdup(ExternalID);
308 else
309 cur->ExternalID = NULL;
310 if (SystemID != NULL)
311 cur->SystemID = xmlStrdup(SystemID);
312 else
313 cur->SystemID = NULL;
Daniel Veillard1e346af1999-02-22 10:33:01 +0000314 cur->notations = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000315 cur->elements = NULL;
Daniel Veillard1e346af1999-02-22 10:33:01 +0000316 cur->attributes = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000317 cur->entities = NULL;
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000318 if (doc != NULL)
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000319 doc->extSubset = cur;
320
321 return(cur);
322}
323
324/**
325 * xmlCreateIntSubset:
326 * @doc: the document pointer
327 * @name: the DTD name
328 * @ExternalID: the external ID
329 * @SystemID: the system ID
330 *
Daniel Veillard1e346af1999-02-22 10:33:01 +0000331 * Create the internal subset of a document
332 * Returns a pointer to the new DTD structure
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000333 */
334xmlDtdPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000335xmlCreateIntSubset(xmlDocPtr doc, const xmlChar *name,
336 const xmlChar *ExternalID, const xmlChar *SystemID) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000337 xmlDtdPtr cur;
338
339 if ((doc != NULL) && (doc->intSubset != NULL)) {
340 fprintf(stderr,
341 "xmlCreateIntSubset(): document %s already have an internal subset\n",
342 doc->name);
343 return(NULL);
344 }
345
346 /*
347 * Allocate a new DTD and fill the fields.
348 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000349 cur = (xmlDtdPtr) xmlMalloc(sizeof(xmlDtd));
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000350 if (cur == NULL) {
351 fprintf(stderr, "xmlNewDtd : malloc failed\n");
352 return(NULL);
353 }
354
355 if (name != NULL)
356 cur->name = xmlStrdup(name);
357 else
358 cur->name = NULL;
359 if (ExternalID != NULL)
360 cur->ExternalID = xmlStrdup(ExternalID);
361 else
362 cur->ExternalID = NULL;
363 if (SystemID != NULL)
364 cur->SystemID = xmlStrdup(SystemID);
365 else
366 cur->SystemID = NULL;
Daniel Veillard1e346af1999-02-22 10:33:01 +0000367 cur->notations = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000368 cur->elements = NULL;
Daniel Veillard1e346af1999-02-22 10:33:01 +0000369 cur->attributes = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000370 cur->entities = NULL;
371 if (doc != NULL)
372 doc->intSubset = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000373
374 return(cur);
375}
376
Daniel Veillard97b58771998-10-20 06:14:16 +0000377/**
378 * xmlFreeDtd:
379 * @cur: the DTD structure to free up
380 *
381 * Free a DTD structure.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000382 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000383void
384xmlFreeDtd(xmlDtdPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000385 if (cur == NULL) {
386 fprintf(stderr, "xmlFreeDtd : DTD == NULL\n");
387 return;
388 }
Daniel Veillard6454aec1999-09-02 22:04:43 +0000389 if (cur->name != NULL) xmlFree((char *) cur->name);
390 if (cur->SystemID != NULL) xmlFree((char *) cur->SystemID);
391 if (cur->ExternalID != NULL) xmlFree((char *) cur->ExternalID);
Daniel Veillard1e346af1999-02-22 10:33:01 +0000392 if (cur->notations != NULL)
393 xmlFreeNotationTable((xmlNotationTablePtr) cur->notations);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000394 if (cur->elements != NULL)
Daniel Veillard3b9def11999-01-31 22:15:06 +0000395 xmlFreeElementTable((xmlElementTablePtr) cur->elements);
Daniel Veillard1e346af1999-02-22 10:33:01 +0000396 if (cur->attributes != NULL)
397 xmlFreeAttributeTable((xmlAttributeTablePtr) cur->attributes);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000398 if (cur->entities != NULL)
399 xmlFreeEntitiesTable((xmlEntitiesTablePtr) cur->entities);
400 memset(cur, -1, sizeof(xmlDtd));
Daniel Veillard6454aec1999-09-02 22:04:43 +0000401 xmlFree(cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000402}
403
Daniel Veillard97b58771998-10-20 06:14:16 +0000404/**
405 * xmlNewDoc:
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000406 * @version: xmlChar string giving the version of XML "1.0"
Daniel Veillard97b58771998-10-20 06:14:16 +0000407 *
Daniel Veillard1e346af1999-02-22 10:33:01 +0000408 * Returns a new document
Daniel Veillard260a68f1998-08-13 03:39:55 +0000409 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000410xmlDocPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000411xmlNewDoc(const xmlChar *version) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000412 xmlDocPtr cur;
413
414 if (version == NULL) {
415 fprintf(stderr, "xmlNewDoc : version == NULL\n");
416 return(NULL);
417 }
418
419 /*
420 * Allocate a new document and fill the fields.
421 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000422 cur = (xmlDocPtr) xmlMalloc(sizeof(xmlDoc));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000423 if (cur == NULL) {
424 fprintf(stderr, "xmlNewDoc : malloc failed\n");
425 return(NULL);
426 }
427
Daniel Veillard33942841998-10-18 19:12:41 +0000428 cur->type = XML_DOCUMENT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000429 cur->version = xmlStrdup(version);
430 cur->name = NULL;
431 cur->root = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000432 cur->intSubset = NULL;
433 cur->extSubset = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000434 cur->oldNs = NULL;
435 cur->encoding = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000436 cur->standalone = -1;
Daniel Veillard11a48ec1999-11-23 10:40:46 +0000437 cur->compression = -1; /* not initialized */
Daniel Veillardb96e6431999-08-29 21:02:19 +0000438 cur->ids = NULL;
Daniel Veillardc08a2c61999-09-08 21:35:25 +0000439 cur->refs = NULL;
Daniel Veillard27d88741999-05-29 11:51:49 +0000440#ifndef XML_WITHOUT_CORBA
Daniel Veillard27fb0751998-10-17 06:47:46 +0000441 cur->_private = NULL;
442 cur->vepv = NULL;
443#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000444 return(cur);
445}
446
Daniel Veillard97b58771998-10-20 06:14:16 +0000447/**
448 * xmlFreeDoc:
449 * @cur: pointer to the document
450 * @:
451 *
452 * Free up all the structures used by a document, tree included.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000453 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000454void
455xmlFreeDoc(xmlDocPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000456 if (cur == NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000457#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +0000458 fprintf(stderr, "xmlFreeDoc : document == NULL\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000459#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000460 return;
461 }
Daniel Veillard6454aec1999-09-02 22:04:43 +0000462 if (cur->version != NULL) xmlFree((char *) cur->version);
463 if (cur->name != NULL) xmlFree((char *) cur->name);
464 if (cur->encoding != NULL) xmlFree((char *) cur->encoding);
465 if (cur->root != NULL) xmlFreeNodeList(cur->root);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000466 if (cur->intSubset != NULL) xmlFreeDtd(cur->intSubset);
467 if (cur->extSubset != NULL) xmlFreeDtd(cur->extSubset);
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000468 if (cur->oldNs != NULL) xmlFreeNsList(cur->oldNs);
Daniel Veillardb96e6431999-08-29 21:02:19 +0000469 if (cur->ids != NULL) xmlFreeIDTable((xmlIDTablePtr) cur->ids);
Daniel Veillardc08a2c61999-09-08 21:35:25 +0000470 if (cur->refs != NULL) xmlFreeRefTable((xmlRefTablePtr) cur->refs);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000471 memset(cur, -1, sizeof(xmlDoc));
Daniel Veillard6454aec1999-09-02 22:04:43 +0000472 xmlFree(cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000473}
474
Daniel Veillard97b58771998-10-20 06:14:16 +0000475/**
Daniel Veillard16253641998-10-28 22:58:05 +0000476 * xmlStringLenGetNodeList:
477 * @doc: the document
478 * @value: the value of the text
Daniel Veillard1e346af1999-02-22 10:33:01 +0000479 * @len: the length of the string value
Daniel Veillard16253641998-10-28 22:58:05 +0000480 *
481 * Parse the value string and build the node list associated. Should
482 * produce a flat tree with only TEXTs and ENTITY_REFs.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000483 * Returns a pointer to the first child
Daniel Veillard16253641998-10-28 22:58:05 +0000484 */
485xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000486xmlStringLenGetNodeList(xmlDocPtr doc, const xmlChar *value, int len) {
Daniel Veillard16253641998-10-28 22:58:05 +0000487 xmlNodePtr ret = NULL, last = NULL;
488 xmlNodePtr node;
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000489 xmlChar *val;
490 const xmlChar *cur = value;
491 const xmlChar *q;
Daniel Veillard25940b71998-10-29 05:51:30 +0000492 xmlEntityPtr ent;
Daniel Veillard16253641998-10-28 22:58:05 +0000493
494 if (value == NULL) return(NULL);
495
496 q = cur;
497 while ((*cur != 0) && (cur - value < len)) {
498 if (*cur == '&') {
Daniel Veillard25940b71998-10-29 05:51:30 +0000499 /*
500 * Save the current text.
501 */
Daniel Veillard16253641998-10-28 22:58:05 +0000502 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000503 if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
504 xmlNodeAddContentLen(last, q, cur - q);
505 } else {
506 node = xmlNewDocTextLen(doc, q, cur - q);
507 if (node == NULL) return(ret);
508 if (last == NULL)
509 last = ret = node;
510 else {
511 last->next = node;
512 node->prev = last;
513 last = node;
514 }
Daniel Veillard16253641998-10-28 22:58:05 +0000515 }
516 }
Daniel Veillard25940b71998-10-29 05:51:30 +0000517 /*
518 * Read the entity string
519 */
Daniel Veillard16253641998-10-28 22:58:05 +0000520 cur++;
521 q = cur;
522 while ((*cur != 0) && (cur - value < len) && (*cur != ';')) cur++;
523 if ((*cur == 0) || (cur - value >= len)) {
524 fprintf(stderr,
Daniel Veillard011b63c1999-06-02 17:44:04 +0000525 "xmlStringLenGetNodeList: unterminated entity %30s\n", q);
Daniel Veillard16253641998-10-28 22:58:05 +0000526 return(ret);
527 }
528 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000529 /*
530 * Predefined entities don't generate nodes
531 */
Daniel Veillard16253641998-10-28 22:58:05 +0000532 val = xmlStrndup(q, cur - q);
Daniel Veillard25940b71998-10-29 05:51:30 +0000533 ent = xmlGetDocEntity(doc, val);
534 if ((ent != NULL) &&
535 (ent->type == XML_INTERNAL_PREDEFINED_ENTITY)) {
536 if (last == NULL) {
537 node = xmlNewDocText(doc, ent->content);
538 last = ret = node;
539 } else
540 xmlNodeAddContent(last, ent->content);
541
542 } else {
543 /*
544 * Create a new REFERENCE_REF node
545 */
546 node = xmlNewReference(doc, val);
Daniel Veillard242590e1998-11-13 18:04:35 +0000547 if (node == NULL) {
Daniel Veillard6454aec1999-09-02 22:04:43 +0000548 if (val != NULL) xmlFree(val);
Daniel Veillard242590e1998-11-13 18:04:35 +0000549 return(ret);
550 }
Daniel Veillard25940b71998-10-29 05:51:30 +0000551 if (last == NULL)
552 last = ret = node;
553 else {
554 last->next = node;
555 node->prev = last;
556 last = node;
557 }
Daniel Veillard16253641998-10-28 22:58:05 +0000558 }
Daniel Veillard6454aec1999-09-02 22:04:43 +0000559 xmlFree(val);
Daniel Veillard16253641998-10-28 22:58:05 +0000560 }
561 cur++;
562 q = cur;
563 } else
564 cur++;
565 }
566 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000567 /*
568 * Handle the last piece of text.
569 */
570 if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
571 xmlNodeAddContentLen(last, q, cur - q);
572 } else {
573 node = xmlNewDocTextLen(doc, q, cur - q);
574 if (node == NULL) return(ret);
575 if (last == NULL)
576 last = ret = node;
577 else {
578 last->next = node;
579 node->prev = last;
580 last = node;
581 }
Daniel Veillard16253641998-10-28 22:58:05 +0000582 }
583 }
584 return(ret);
585}
586
587/**
Daniel Veillardccb09631998-10-27 06:21:04 +0000588 * xmlStringGetNodeList:
589 * @doc: the document
590 * @value: the value of the attribute
591 *
592 * Parse the value string and build the node list associated. Should
593 * produce a flat tree with only TEXTs and ENTITY_REFs.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000594 * Returns a pointer to the first child
Daniel Veillardccb09631998-10-27 06:21:04 +0000595 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000596xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000597xmlStringGetNodeList(xmlDocPtr doc, const xmlChar *value) {
Daniel Veillardccb09631998-10-27 06:21:04 +0000598 xmlNodePtr ret = NULL, last = NULL;
599 xmlNodePtr node;
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000600 xmlChar *val;
601 const xmlChar *cur = value;
602 const xmlChar *q;
Daniel Veillard25940b71998-10-29 05:51:30 +0000603 xmlEntityPtr ent;
Daniel Veillardccb09631998-10-27 06:21:04 +0000604
605 if (value == NULL) return(NULL);
606
607 q = cur;
608 while (*cur != 0) {
609 if (*cur == '&') {
Daniel Veillard25940b71998-10-29 05:51:30 +0000610 /*
611 * Save the current text.
612 */
Daniel Veillardccb09631998-10-27 06:21:04 +0000613 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000614 if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
615 xmlNodeAddContentLen(last, q, cur - q);
616 } else {
617 node = xmlNewDocTextLen(doc, q, cur - q);
618 if (node == NULL) return(ret);
619 if (last == NULL)
620 last = ret = node;
621 else {
622 last->next = node;
623 node->prev = last;
624 last = node;
625 }
Daniel Veillardccb09631998-10-27 06:21:04 +0000626 }
627 }
Daniel Veillard25940b71998-10-29 05:51:30 +0000628 /*
629 * Read the entity string
630 */
Daniel Veillardccb09631998-10-27 06:21:04 +0000631 cur++;
632 q = cur;
633 while ((*cur != 0) && (*cur != ';')) cur++;
634 if (*cur == 0) {
635 fprintf(stderr,
636 "xmlStringGetNodeList: unterminated entity %30s\n", q);
637 return(ret);
638 }
639 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000640 /*
641 * Predefined entities don't generate nodes
642 */
Daniel Veillardccb09631998-10-27 06:21:04 +0000643 val = xmlStrndup(q, cur - q);
Daniel Veillard25940b71998-10-29 05:51:30 +0000644 ent = xmlGetDocEntity(doc, val);
645 if ((ent != NULL) &&
646 (ent->type == XML_INTERNAL_PREDEFINED_ENTITY)) {
647 if (last == NULL) {
648 node = xmlNewDocText(doc, ent->content);
649 last = ret = node;
650 } else
651 xmlNodeAddContent(last, ent->content);
652
653 } else {
654 /*
655 * Create a new REFERENCE_REF node
656 */
Daniel Veillard25940b71998-10-29 05:51:30 +0000657 node = xmlNewReference(doc, val);
Daniel Veillard242590e1998-11-13 18:04:35 +0000658 if (node == NULL) {
Daniel Veillard6454aec1999-09-02 22:04:43 +0000659 if (val != NULL) xmlFree(val);
Daniel Veillard242590e1998-11-13 18:04:35 +0000660 return(ret);
661 }
Daniel Veillard25940b71998-10-29 05:51:30 +0000662 if (last == NULL)
663 last = ret = node;
664 else {
665 last->next = node;
666 node->prev = last;
667 last = node;
668 }
Daniel Veillardccb09631998-10-27 06:21:04 +0000669 }
Daniel Veillard6454aec1999-09-02 22:04:43 +0000670 xmlFree(val);
Daniel Veillardccb09631998-10-27 06:21:04 +0000671 }
672 cur++;
673 q = cur;
674 } else
675 cur++;
676 }
677 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000678 /*
679 * Handle the last piece of text.
680 */
681 if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
682 xmlNodeAddContentLen(last, q, cur - q);
683 } else {
684 node = xmlNewDocTextLen(doc, q, cur - q);
685 if (node == NULL) return(ret);
686 if (last == NULL)
687 last = ret = node;
688 else {
689 last->next = node;
690 node->prev = last;
691 last = node;
692 }
Daniel Veillardccb09631998-10-27 06:21:04 +0000693 }
694 }
695 return(ret);
696}
697
698/**
699 * xmlNodeListGetString:
700 * @doc: the document
701 * @list: a Node list
702 * @inLine: should we replace entity contents or show their external form
703 *
704 * Returns the string equivalent to the text contained in the Node list
705 * made of TEXTs and ENTITY_REFs
Daniel Veillard1e346af1999-02-22 10:33:01 +0000706 * Returns a pointer to the string copy, the calller must free it.
Daniel Veillardccb09631998-10-27 06:21:04 +0000707 */
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000708xmlChar *
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000709xmlNodeListGetString(xmlDocPtr doc, xmlNodePtr list, int inLine) {
Daniel Veillardccb09631998-10-27 06:21:04 +0000710 xmlNodePtr node = list;
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000711 xmlChar *ret = NULL;
Daniel Veillardccb09631998-10-27 06:21:04 +0000712 xmlEntityPtr ent;
713
714 if (list == NULL) return(NULL);
715
716 while (node != NULL) {
717 if (node->type == XML_TEXT_NODE) {
Daniel Veillardf5c2c871999-12-01 09:51:45 +0000718 if ((inLine) || (doc->type == XML_HTML_DOCUMENT_NODE)) {
719#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardccb09631998-10-27 06:21:04 +0000720 ret = xmlStrcat(ret, node->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +0000721#else
722 ret = xmlStrcat(ret, xmlBufferContent(node->content));
723#endif
724 } else {
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000725 xmlChar *buffer;
Daniel Veillard14fff061999-06-22 21:49:07 +0000726
Daniel Veillardf5c2c871999-12-01 09:51:45 +0000727#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard14fff061999-06-22 21:49:07 +0000728 buffer = xmlEncodeEntitiesReentrant(doc, node->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +0000729#else
730 buffer = xmlEncodeEntitiesReentrant(doc,
731 xmlBufferContent(node->content));
732#endif
Daniel Veillard14fff061999-06-22 21:49:07 +0000733 if (buffer != NULL) {
734 ret = xmlStrcat(ret, buffer);
Daniel Veillard6454aec1999-09-02 22:04:43 +0000735 xmlFree(buffer);
Daniel Veillard14fff061999-06-22 21:49:07 +0000736 }
737 }
Daniel Veillardccb09631998-10-27 06:21:04 +0000738 } else if (node->type == XML_ENTITY_REF_NODE) {
739 if (inLine) {
740 ent = xmlGetDocEntity(doc, node->name);
741 if (ent != NULL)
742 ret = xmlStrcat(ret, ent->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +0000743 else {
744#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardccb09631998-10-27 06:21:04 +0000745 ret = xmlStrcat(ret, node->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +0000746#else
747 ret = xmlStrcat(ret, xmlBufferContent(node->content));
748#endif
749 }
Daniel Veillardccb09631998-10-27 06:21:04 +0000750 } else {
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000751 xmlChar buf[2];
Daniel Veillardccb09631998-10-27 06:21:04 +0000752 buf[0] = '&'; buf[1] = 0;
753 ret = xmlStrncat(ret, buf, 1);
754 ret = xmlStrcat(ret, node->name);
755 buf[0] = ';'; buf[1] = 0;
756 ret = xmlStrncat(ret, buf, 1);
757 }
758 }
759#if 0
760 else {
761 fprintf(stderr, "xmlGetNodeListString : invalide node type %d\n",
762 node->type);
763 }
764#endif
765 node = node->next;
766 }
767 return(ret);
768}
769
770/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000771 * xmlNewProp:
772 * @node: the holding node
773 * @name: the name of the attribute
774 * @value: the value of the attribute
775 *
776 * Create a new property carried by a node.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000777 * Returns a pointer to the attribute
Daniel Veillard260a68f1998-08-13 03:39:55 +0000778 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000779xmlAttrPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000780xmlNewProp(xmlNodePtr node, const xmlChar *name, const xmlChar *value) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000781 xmlAttrPtr cur;
782
783 if (name == NULL) {
784 fprintf(stderr, "xmlNewProp : name == NULL\n");
785 return(NULL);
786 }
787
788 /*
789 * Allocate a new property and fill the fields.
790 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000791 cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000792 if (cur == NULL) {
793 fprintf(stderr, "xmlNewProp : malloc failed\n");
794 return(NULL);
795 }
796
Daniel Veillard33942841998-10-18 19:12:41 +0000797 cur->type = XML_ATTRIBUTE_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000798 cur->node = node;
Daniel Veillardb96e6431999-08-29 21:02:19 +0000799 cur->ns = NULL;
800 cur->name = xmlStrdup(name);
Daniel Veillard51e3b151999-11-12 17:02:31 +0000801 if (value != NULL) {
802 xmlChar *buffer;
803 buffer = xmlEncodeEntitiesReentrant(node->doc, value);
804 cur->val = xmlStringGetNodeList(node->doc, buffer);
805 xmlFree(buffer);
806 }
Daniel Veillardb96e6431999-08-29 21:02:19 +0000807 else
808 cur->val = NULL;
809#ifndef XML_WITHOUT_CORBA
810 cur->_private = NULL;
811 cur->vepv = NULL;
812#endif
813
814 /*
815 * Add it at the end to preserve parsing order ...
816 */
817 cur->next = NULL;
818 if (node != NULL) {
819 if (node->properties == NULL) {
820 node->properties = cur;
821 } else {
822 xmlAttrPtr prev = node->properties;
823
824 while (prev->next != NULL) prev = prev->next;
825 prev->next = cur;
826 }
827 }
Daniel Veillard00fdf371999-10-08 09:40:39 +0000828#ifndef XML_WITHOUT_CORBA
829 cur->_private = NULL;
830 cur->vepv = NULL;
831#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +0000832 return(cur);
833}
834
835/**
836 * xmlNewNsProp:
837 * @node: the holding node
838 * @ns: the namespace
839 * @name: the name of the attribute
840 * @value: the value of the attribute
841 *
842 * Create a new property tagged with a namespace and carried by a node.
843 * Returns a pointer to the attribute
844 */
845xmlAttrPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000846xmlNewNsProp(xmlNodePtr node, xmlNsPtr ns, const xmlChar *name,
847 const xmlChar *value) {
Daniel Veillardb96e6431999-08-29 21:02:19 +0000848 xmlAttrPtr cur;
849
850 if (name == NULL) {
851 fprintf(stderr, "xmlNewProp : name == NULL\n");
852 return(NULL);
853 }
854
855 /*
856 * Allocate a new property and fill the fields.
857 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000858 cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr));
Daniel Veillardb96e6431999-08-29 21:02:19 +0000859 if (cur == NULL) {
860 fprintf(stderr, "xmlNewProp : malloc failed\n");
861 return(NULL);
862 }
863
864 cur->type = XML_ATTRIBUTE_NODE;
865 cur->node = node;
866 cur->ns = ns;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000867 cur->name = xmlStrdup(name);
868 if (value != NULL)
Daniel Veillardccb09631998-10-27 06:21:04 +0000869 cur->val = xmlStringGetNodeList(node->doc, value);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000870 else
Daniel Veillardccb09631998-10-27 06:21:04 +0000871 cur->val = NULL;
Daniel Veillard27d88741999-05-29 11:51:49 +0000872#ifndef XML_WITHOUT_CORBA
Daniel Veillard27fb0751998-10-17 06:47:46 +0000873 cur->_private = NULL;
874 cur->vepv = NULL;
875#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000876
877 /*
878 * Add it at the end to preserve parsing order ...
879 */
880 cur->next = NULL;
881 if (node != NULL) {
882 if (node->properties == NULL) {
883 node->properties = cur;
884 } else {
885 xmlAttrPtr prev = node->properties;
886
887 while (prev->next != NULL) prev = prev->next;
888 prev->next = cur;
889 }
890 }
891 return(cur);
892}
893
Daniel Veillard97b58771998-10-20 06:14:16 +0000894/**
Daniel Veillardccb09631998-10-27 06:21:04 +0000895 * xmlNewDocProp:
896 * @doc: the document
897 * @name: the name of the attribute
898 * @value: the value of the attribute
899 *
900 * Create a new property carried by a document.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000901 * Returns a pointer to the attribute
Daniel Veillardccb09631998-10-27 06:21:04 +0000902 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000903xmlAttrPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000904xmlNewDocProp(xmlDocPtr doc, const xmlChar *name, const xmlChar *value) {
Daniel Veillardccb09631998-10-27 06:21:04 +0000905 xmlAttrPtr cur;
906
907 if (name == NULL) {
908 fprintf(stderr, "xmlNewProp : name == NULL\n");
909 return(NULL);
910 }
911
912 /*
913 * Allocate a new property and fill the fields.
914 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000915 cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr));
Daniel Veillardccb09631998-10-27 06:21:04 +0000916 if (cur == NULL) {
917 fprintf(stderr, "xmlNewProp : malloc failed\n");
918 return(NULL);
919 }
920
921 cur->type = XML_ATTRIBUTE_NODE;
922 cur->node = NULL;
923 cur->name = xmlStrdup(name);
924 if (value != NULL)
925 cur->val = xmlStringGetNodeList(doc, value);
926 else
927 cur->val = NULL;
Daniel Veillard27d88741999-05-29 11:51:49 +0000928#ifndef XML_WITHOUT_CORBA
Daniel Veillardccb09631998-10-27 06:21:04 +0000929 cur->_private = NULL;
930 cur->vepv = NULL;
931#endif
932
933 cur->next = NULL;
934 return(cur);
935}
936
937/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000938 * xmlFreePropList:
939 * @cur: the first property in the list
940 *
941 * Free a property and all its siblings, all the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000942 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000943void
944xmlFreePropList(xmlAttrPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000945 xmlAttrPtr next;
946 if (cur == NULL) {
947 fprintf(stderr, "xmlFreePropList : property == NULL\n");
948 return;
949 }
950 while (cur != NULL) {
951 next = cur->next;
952 xmlFreeProp(cur);
953 cur = next;
954 }
955}
956
Daniel Veillard97b58771998-10-20 06:14:16 +0000957/**
958 * xmlFreeProp:
959 * @cur: the first property in the list
960 *
961 * Free one property, all the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000962 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000963void
964xmlFreeProp(xmlAttrPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000965 if (cur == NULL) {
966 fprintf(stderr, "xmlFreeProp : property == NULL\n");
967 return;
968 }
Daniel Veillard6454aec1999-09-02 22:04:43 +0000969 if (cur->name != NULL) xmlFree((char *) cur->name);
Daniel Veillardccb09631998-10-27 06:21:04 +0000970 if (cur->val != NULL) xmlFreeNodeList(cur->val);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000971 memset(cur, -1, sizeof(xmlAttr));
Daniel Veillard6454aec1999-09-02 22:04:43 +0000972 xmlFree(cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000973}
974
Daniel Veillard97b58771998-10-20 06:14:16 +0000975/**
Daniel Veillardb96e6431999-08-29 21:02:19 +0000976 * xmlNewPI:
977 * @name: the processing instruction name
978 * @content: the PI content
979 *
980 * Creation of a processing instruction element.
981 * Returns a pointer to the new node object.
982 */
983xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000984xmlNewPI(const xmlChar *name, const xmlChar *content) {
Daniel Veillardb96e6431999-08-29 21:02:19 +0000985 xmlNodePtr cur;
986
987 if (name == NULL) {
988 fprintf(stderr, "xmlNewPI : name == NULL\n");
989 return(NULL);
990 }
991
992 /*
993 * Allocate a new node and fill the fields.
994 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000995 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillardb96e6431999-08-29 21:02:19 +0000996 if (cur == NULL) {
997 fprintf(stderr, "xmlNewPI : malloc failed\n");
998 return(NULL);
999 }
1000
1001 cur->type = XML_PI_NODE;
1002 cur->doc = NULL;
1003 cur->parent = NULL;
1004 cur->next = NULL;
1005 cur->prev = NULL;
1006 cur->childs = NULL;
1007 cur->last = NULL;
1008 cur->properties = NULL;
1009 cur->name = xmlStrdup(name);
1010 cur->ns = NULL;
1011 cur->nsDef = NULL;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001012 if (content != NULL) {
1013#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardb96e6431999-08-29 21:02:19 +00001014 cur->content = xmlStrdup(content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001015#else
1016 cur->content = xmlBufferCreateSize(0);
1017 xmlBufferSetAllocationScheme(cur->content,
1018 xmlGetBufferAllocationScheme());
1019 xmlBufferAdd(cur->content, content, -1);
1020#endif
1021 } else
Daniel Veillardb96e6431999-08-29 21:02:19 +00001022 cur->content = NULL;
1023#ifndef XML_WITHOUT_CORBA
1024 cur->_private = NULL;
1025 cur->vepv = NULL;
1026#endif
1027 return(cur);
1028}
1029
1030/**
Daniel Veillard97b58771998-10-20 06:14:16 +00001031 * xmlNewNode:
1032 * @ns: namespace if any
1033 * @name: the node name
Daniel Veillard97b58771998-10-20 06:14:16 +00001034 *
1035 * Creation of a new node element. @ns and @content are optionnal (NULL).
Daniel Veillardccb09631998-10-27 06:21:04 +00001036 * If content is non NULL, a child list containing the TEXTs and
1037 * ENTITY_REFs node will be created.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001038 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001039 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001040xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001041xmlNewNode(xmlNsPtr ns, const xmlChar *name) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001042 xmlNodePtr cur;
1043
1044 if (name == NULL) {
1045 fprintf(stderr, "xmlNewNode : name == NULL\n");
1046 return(NULL);
1047 }
1048
1049 /*
1050 * Allocate a new node and fill the fields.
1051 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001052 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillard260a68f1998-08-13 03:39:55 +00001053 if (cur == NULL) {
1054 fprintf(stderr, "xmlNewNode : malloc failed\n");
1055 return(NULL);
1056 }
1057
Daniel Veillard33942841998-10-18 19:12:41 +00001058 cur->type = XML_ELEMENT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001059 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001060 cur->parent = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001061 cur->next = NULL;
1062 cur->prev = NULL;
1063 cur->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001064 cur->last = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001065 cur->properties = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001066 cur->name = xmlStrdup(name);
1067 cur->ns = ns;
1068 cur->nsDef = NULL;
Daniel Veillardccb09631998-10-27 06:21:04 +00001069 cur->content = NULL;
Daniel Veillard27d88741999-05-29 11:51:49 +00001070#ifndef XML_WITHOUT_CORBA
Daniel Veillard27fb0751998-10-17 06:47:46 +00001071 cur->_private = NULL;
1072 cur->vepv = NULL;
1073#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001074 return(cur);
1075}
1076
Daniel Veillard97b58771998-10-20 06:14:16 +00001077/**
1078 * xmlNewDocNode:
1079 * @doc: the document
1080 * @ns: namespace if any
1081 * @name: the node name
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001082 * @content: the XML text content if any
Daniel Veillard97b58771998-10-20 06:14:16 +00001083 *
1084 * Creation of a new node element within a document. @ns and @content
1085 * are optionnal (NULL).
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001086 * NOTE: @content is supposed to be a piece of XML CDATA, so it allow entities
1087 * references, but XML special chars need to be escaped first by using
1088 * xmlEncodeEntitiesReentrant(). Use xmlNewDocRawNode() if you don't
1089 * need entities support.
1090 *
Daniel Veillard1e346af1999-02-22 10:33:01 +00001091 * Returns a pointer to the new node object.
Daniel Veillard97b58771998-10-20 06:14:16 +00001092 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001093xmlNodePtr
1094xmlNewDocNode(xmlDocPtr doc, xmlNsPtr ns,
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001095 const xmlChar *name, const xmlChar *content) {
Daniel Veillard0bef1311998-10-14 02:36:47 +00001096 xmlNodePtr cur;
1097
Daniel Veillardccb09631998-10-27 06:21:04 +00001098 cur = xmlNewNode(ns, name);
1099 if (cur != NULL) {
1100 cur->doc = doc;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001101 if (content != NULL) {
Daniel Veillardccb09631998-10-27 06:21:04 +00001102 cur->childs = xmlStringGetNodeList(doc, content);
Daniel Veillard1e346af1999-02-22 10:33:01 +00001103 UPDATE_LAST_CHILD(cur)
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001104 }
Daniel Veillardccb09631998-10-27 06:21:04 +00001105 }
Daniel Veillard0bef1311998-10-14 02:36:47 +00001106 return(cur);
1107}
1108
1109
Daniel Veillard97b58771998-10-20 06:14:16 +00001110/**
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001111 * xmlNewDocRawNode:
1112 * @doc: the document
1113 * @ns: namespace if any
1114 * @name: the node name
1115 * @content: the text content if any
1116 *
1117 * Creation of a new node element within a document. @ns and @content
1118 * are optionnal (NULL).
1119 *
1120 * Returns a pointer to the new node object.
1121 */
1122xmlNodePtr
1123xmlNewDocRawNode(xmlDocPtr doc, xmlNsPtr ns,
1124 const xmlChar *name, const xmlChar *content) {
1125 xmlNodePtr cur;
1126
1127 cur = xmlNewNode(ns, name);
1128 if (cur != NULL) {
1129 cur->doc = doc;
1130 if (content != NULL) {
1131 cur->childs = xmlNewDocText(doc, content);
1132 UPDATE_LAST_CHILD(cur)
1133 }
1134 }
1135 return(cur);
1136}
1137
1138
1139/**
Daniel Veillard97b58771998-10-20 06:14:16 +00001140 * xmlNewText:
1141 * @content: the text content
1142 *
1143 * Creation of a new text node.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001144 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001145 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001146xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001147xmlNewText(const xmlChar *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001148 xmlNodePtr cur;
1149
1150 /*
1151 * Allocate a new node and fill the fields.
1152 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001153 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillard260a68f1998-08-13 03:39:55 +00001154 if (cur == NULL) {
1155 fprintf(stderr, "xmlNewText : malloc failed\n");
1156 return(NULL);
1157 }
1158
Daniel Veillard33942841998-10-18 19:12:41 +00001159 cur->type = XML_TEXT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001160 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001161 cur->parent = NULL;
1162 cur->next = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001163 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001164 cur->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001165 cur->last = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001166 cur->properties = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001167 cur->type = XML_TEXT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001168 cur->name = xmlStrdup(xmlStringText);
1169 cur->ns = NULL;
1170 cur->nsDef = NULL;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001171 if (content != NULL) {
1172#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard260a68f1998-08-13 03:39:55 +00001173 cur->content = xmlStrdup(content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001174#else
1175 cur->content = xmlBufferCreateSize(0);
1176 xmlBufferSetAllocationScheme(cur->content,
1177 xmlGetBufferAllocationScheme());
1178 xmlBufferAdd(cur->content, content, -1);
1179#endif
1180 } else
Daniel Veillard260a68f1998-08-13 03:39:55 +00001181 cur->content = NULL;
Daniel Veillard00fdf371999-10-08 09:40:39 +00001182#ifndef XML_WITHOUT_CORBA
1183 cur->_private = NULL;
1184 cur->vepv = NULL;
1185#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001186 return(cur);
1187}
1188
Daniel Veillard97b58771998-10-20 06:14:16 +00001189/**
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001190 * xmlNewTextChild:
1191 * @parent: the parent node
1192 * @ns: a namespace if any
1193 * @name: the name of the child
1194 * @content: the text content of the child if any.
1195 *
1196 * Creation of a new child element, added at the end of @parent childs list.
1197 * @ns and @content parameters are optionnal (NULL). If content is non NULL,
1198 * a child TEXT node will be created containing the string content.
1199 *
1200 * Returns a pointer to the new node object.
1201 */
1202xmlNodePtr
1203xmlNewTextChild(xmlNodePtr parent, xmlNsPtr ns,
1204 const xmlChar *name, const xmlChar *content) {
1205 xmlNodePtr cur, prev;
1206
1207 if (parent == NULL) {
1208 fprintf(stderr, "xmlNewTextChild : parent == NULL\n");
1209 return(NULL);
1210 }
1211
1212 if (name == NULL) {
1213 fprintf(stderr, "xmlNewTextChild : name == NULL\n");
1214 return(NULL);
1215 }
1216
1217 /*
1218 * Allocate a new node
1219 */
1220 if (ns == NULL)
1221 cur = xmlNewDocRawNode(parent->doc, parent->ns, name, content);
1222 else
1223 cur = xmlNewDocRawNode(parent->doc, ns, name, content);
1224 if (cur == NULL) return(NULL);
1225
1226 /*
1227 * add the new element at the end of the childs list.
1228 */
1229 cur->type = XML_ELEMENT_NODE;
1230 cur->parent = parent;
1231 cur->doc = parent->doc;
1232 if (parent->childs == NULL) {
1233 parent->childs = cur;
1234 parent->last = cur;
1235 } else {
1236 prev = parent->last;
1237 prev->next = cur;
1238 cur->prev = prev;
1239 parent->last = cur;
1240 }
1241
1242 return(cur);
1243}
1244
1245/**
Daniel Veillardccb09631998-10-27 06:21:04 +00001246 * xmlNewReference:
1247 * @doc: the document
1248 * @name: the reference name, or the reference string with & and ;
1249 *
1250 * Creation of a new reference node.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001251 * Returns a pointer to the new node object.
Daniel Veillardccb09631998-10-27 06:21:04 +00001252 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001253xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001254xmlNewReference(xmlDocPtr doc, const xmlChar *name) {
Daniel Veillardccb09631998-10-27 06:21:04 +00001255 xmlNodePtr cur;
1256 xmlEntityPtr ent;
1257
1258 /*
1259 * Allocate a new node and fill the fields.
1260 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001261 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillardccb09631998-10-27 06:21:04 +00001262 if (cur == NULL) {
1263 fprintf(stderr, "xmlNewText : malloc failed\n");
1264 return(NULL);
1265 }
1266
1267 cur->type = XML_ENTITY_REF_NODE;
Daniel Veillard10c6a8f1998-10-28 01:00:12 +00001268 cur->doc = doc;
Daniel Veillardccb09631998-10-27 06:21:04 +00001269 cur->parent = NULL;
1270 cur->next = NULL;
1271 cur->prev = NULL;
1272 cur->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001273 cur->last = NULL;
Daniel Veillardccb09631998-10-27 06:21:04 +00001274 cur->properties = NULL;
1275 if (name[0] == '&') {
1276 int len;
1277 name++;
1278 len = xmlStrlen(name);
1279 if (name[len - 1] == ';')
1280 cur->name = xmlStrndup(name, len - 1);
1281 else
1282 cur->name = xmlStrndup(name, len);
1283 } else
1284 cur->name = xmlStrdup(name);
1285 cur->ns = NULL;
1286 cur->nsDef = NULL;
1287
1288 ent = xmlGetDocEntity(doc, cur->name);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001289 if (ent != NULL) {
1290#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardccb09631998-10-27 06:21:04 +00001291 cur->content = ent->content;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001292#else
1293 /*
1294 * CJN 11.18.99 this might be a problem, since the xmlBuffer gets
1295 * a copy of this pointer. Let's hope we don't manipulate it
1296 * later
1297 */
1298 cur->content = xmlBufferCreateSize(0);
1299 xmlBufferSetAllocationScheme(cur->content,
1300 xmlGetBufferAllocationScheme());
1301 if (ent->content != NULL)
1302 xmlBufferAdd(cur->content, ent->content, -1);
1303#endif
1304 } else
Daniel Veillardccb09631998-10-27 06:21:04 +00001305 cur->content = NULL;
Daniel Veillard00fdf371999-10-08 09:40:39 +00001306#ifndef XML_WITHOUT_CORBA
1307 cur->_private = NULL;
1308 cur->vepv = NULL;
1309#endif
Daniel Veillardccb09631998-10-27 06:21:04 +00001310 return(cur);
1311}
1312
1313/**
Daniel Veillard97b58771998-10-20 06:14:16 +00001314 * xmlNewDocText:
1315 * @doc: the document
1316 * @content: the text content
1317 *
1318 * Creation of a new text node within a document.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001319 * Returns a pointer to the new node object.
Daniel Veillard97b58771998-10-20 06:14:16 +00001320 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001321xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001322xmlNewDocText(xmlDocPtr doc, const xmlChar *content) {
Daniel Veillard0bef1311998-10-14 02:36:47 +00001323 xmlNodePtr cur;
1324
1325 cur = xmlNewText(content);
1326 if (cur != NULL) cur->doc = doc;
1327 return(cur);
1328}
1329
Daniel Veillard97b58771998-10-20 06:14:16 +00001330/**
Daniel Veillardccb09631998-10-27 06:21:04 +00001331 * xmlNewTextLen:
Daniel Veillard97b58771998-10-20 06:14:16 +00001332 * @content: the text content
1333 * @len: the text len.
1334 *
1335 * Creation of a new text node with an extra parameter for the content's lenght
Daniel Veillard1e346af1999-02-22 10:33:01 +00001336 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001337 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001338xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001339xmlNewTextLen(const xmlChar *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001340 xmlNodePtr cur;
1341
1342 /*
1343 * Allocate a new node and fill the fields.
1344 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001345 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillard260a68f1998-08-13 03:39:55 +00001346 if (cur == NULL) {
1347 fprintf(stderr, "xmlNewText : malloc failed\n");
1348 return(NULL);
1349 }
1350
Daniel Veillard33942841998-10-18 19:12:41 +00001351 cur->type = XML_TEXT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001352 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001353 cur->parent = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001354 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001355 cur->next = NULL;
1356 cur->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001357 cur->last = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001358 cur->properties = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001359 cur->type = XML_TEXT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001360 cur->name = xmlStrdup(xmlStringText);
1361 cur->ns = NULL;
1362 cur->nsDef = NULL;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001363 if (content != NULL) {
1364#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard260a68f1998-08-13 03:39:55 +00001365 cur->content = xmlStrndup(content, len);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001366#else
1367 cur->content = xmlBufferCreateSize(len);
1368 xmlBufferSetAllocationScheme(cur->content,
1369 xmlGetBufferAllocationScheme());
1370 xmlBufferAdd(cur->content, content, len);
1371#endif
1372 } else
Daniel Veillard260a68f1998-08-13 03:39:55 +00001373 cur->content = NULL;
Daniel Veillard00fdf371999-10-08 09:40:39 +00001374#ifndef XML_WITHOUT_CORBA
1375 cur->_private = NULL;
1376 cur->vepv = NULL;
1377#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001378 return(cur);
1379}
1380
Daniel Veillard97b58771998-10-20 06:14:16 +00001381/**
1382 * xmlNewDocTextLen:
1383 * @doc: the document
1384 * @content: the text content
1385 * @len: the text len.
1386 *
1387 * Creation of a new text node with an extra content lenght parameter. The
1388 * text node pertain to a given document.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001389 * Returns a pointer to the new node object.
Daniel Veillard97b58771998-10-20 06:14:16 +00001390 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001391xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001392xmlNewDocTextLen(xmlDocPtr doc, const xmlChar *content, int len) {
Daniel Veillard0bef1311998-10-14 02:36:47 +00001393 xmlNodePtr cur;
1394
1395 cur = xmlNewTextLen(content, len);
1396 if (cur != NULL) cur->doc = doc;
1397 return(cur);
1398}
1399
Daniel Veillard97b58771998-10-20 06:14:16 +00001400/**
1401 * xmlNewComment:
1402 * @content: the comment content
1403 *
1404 * Creation of a new node containing a comment.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001405 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001406 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001407xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001408xmlNewComment(const xmlChar *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001409 xmlNodePtr cur;
1410
1411 /*
1412 * Allocate a new node and fill the fields.
1413 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001414 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillard260a68f1998-08-13 03:39:55 +00001415 if (cur == NULL) {
1416 fprintf(stderr, "xmlNewComment : malloc failed\n");
1417 return(NULL);
1418 }
1419
Daniel Veillard33942841998-10-18 19:12:41 +00001420 cur->type = XML_COMMENT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001421 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001422 cur->parent = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001423 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001424 cur->next = NULL;
1425 cur->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001426 cur->last = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001427 cur->properties = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001428 cur->type = XML_COMMENT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001429 cur->name = xmlStrdup(xmlStringText);
1430 cur->ns = NULL;
1431 cur->nsDef = NULL;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001432 if (content != NULL) {
1433#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard260a68f1998-08-13 03:39:55 +00001434 cur->content = xmlStrdup(content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001435#else
1436 cur->content = xmlBufferCreateSize(0);
1437 xmlBufferSetAllocationScheme(cur->content,
1438 xmlGetBufferAllocationScheme());
1439 xmlBufferAdd(cur->content, content, -1);
1440#endif
1441 } else
Daniel Veillard260a68f1998-08-13 03:39:55 +00001442 cur->content = NULL;
Daniel Veillard00fdf371999-10-08 09:40:39 +00001443#ifndef XML_WITHOUT_CORBA
1444 cur->_private = NULL;
1445 cur->vepv = NULL;
1446#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001447 return(cur);
1448}
1449
Daniel Veillard97b58771998-10-20 06:14:16 +00001450/**
Daniel Veillardb05deb71999-08-10 19:04:08 +00001451 * xmlNewCDataBlock:
1452 * @doc: the document
1453 * @content: the CData block content content
1454 * @len: the length of the block
1455 *
1456 * Creation of a new node containing a CData block.
1457 * Returns a pointer to the new node object.
1458 */
1459xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001460xmlNewCDataBlock(xmlDocPtr doc, const xmlChar *content, int len) {
Daniel Veillardb05deb71999-08-10 19:04:08 +00001461 xmlNodePtr cur;
1462
1463 /*
1464 * Allocate a new node and fill the fields.
1465 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001466 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillardb05deb71999-08-10 19:04:08 +00001467 if (cur == NULL) {
1468 fprintf(stderr, "xmlNewCDataBlock : malloc failed\n");
1469 return(NULL);
1470 }
1471
1472 cur->type = XML_CDATA_SECTION_NODE;
1473 cur->doc = NULL;
1474 cur->parent = NULL;
1475 cur->prev = NULL;
1476 cur->next = NULL;
1477 cur->childs = NULL;
1478 cur->last = NULL;
1479 cur->properties = NULL;
1480 cur->name = xmlStrdup(xmlStringText);
1481 cur->ns = NULL;
1482 cur->nsDef = NULL;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001483 if (content != NULL) {
1484#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardb05deb71999-08-10 19:04:08 +00001485 cur->content = xmlStrndup(content, len);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001486#else
1487 cur->content = xmlBufferCreateSize(len);
1488 xmlBufferSetAllocationScheme(cur->content,
1489 xmlGetBufferAllocationScheme());
1490 xmlBufferAdd(cur->content, content, len);
1491#endif
Daniel Veillardb05deb71999-08-10 19:04:08 +00001492 } else
1493 cur->content = NULL;
Daniel Veillard00fdf371999-10-08 09:40:39 +00001494#ifndef XML_WITHOUT_CORBA
1495 cur->_private = NULL;
1496 cur->vepv = NULL;
1497#endif
Daniel Veillardb05deb71999-08-10 19:04:08 +00001498 return(cur);
1499}
1500
1501/**
Daniel Veillard1e346af1999-02-22 10:33:01 +00001502 * xmlNewDocComment:
Daniel Veillard97b58771998-10-20 06:14:16 +00001503 * @doc: the document
1504 * @content: the comment content
1505 *
1506 * Creation of a new node containing a commentwithin a document.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001507 * Returns a pointer to the new node object.
Daniel Veillard97b58771998-10-20 06:14:16 +00001508 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001509xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001510xmlNewDocComment(xmlDocPtr doc, const xmlChar *content) {
Daniel Veillard0bef1311998-10-14 02:36:47 +00001511 xmlNodePtr cur;
1512
1513 cur = xmlNewComment(content);
1514 if (cur != NULL) cur->doc = doc;
1515 return(cur);
1516}
1517
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001518
Daniel Veillard97b58771998-10-20 06:14:16 +00001519/**
1520 * xmlNewChild:
1521 * @parent: the parent node
1522 * @ns: a namespace if any
1523 * @name: the name of the child
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001524 * @content: the XML content of the child if any.
Daniel Veillard97b58771998-10-20 06:14:16 +00001525 *
Daniel Veillard97b58771998-10-20 06:14:16 +00001526 * Creation of a new child element, added at the end of @parent childs list.
Daniel Veillardccb09631998-10-27 06:21:04 +00001527 * @ns and @content parameters are optionnal (NULL). If content is non NULL,
1528 * a child list containing the TEXTs and ENTITY_REFs node will be created.
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001529 * NOTE: @content is supposed to be a piece of XML CDATA, so it allow entities
1530 * references, but XML special chars need to be escaped first by using
1531 * xmlEncodeEntitiesReentrant(). Use xmlNewTextChild() if entities
1532 * support is not needed.
1533 *
Daniel Veillard1e346af1999-02-22 10:33:01 +00001534 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001535 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001536xmlNodePtr
1537xmlNewChild(xmlNodePtr parent, xmlNsPtr ns,
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001538 const xmlChar *name, const xmlChar *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001539 xmlNodePtr cur, prev;
1540
1541 if (parent == NULL) {
1542 fprintf(stderr, "xmlNewChild : parent == NULL\n");
1543 return(NULL);
1544 }
1545
1546 if (name == NULL) {
1547 fprintf(stderr, "xmlNewChild : name == NULL\n");
1548 return(NULL);
1549 }
1550
1551 /*
1552 * Allocate a new node
1553 */
1554 if (ns == NULL)
Daniel Veillardccb09631998-10-27 06:21:04 +00001555 cur = xmlNewDocNode(parent->doc, parent->ns, name, content);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001556 else
Daniel Veillardccb09631998-10-27 06:21:04 +00001557 cur = xmlNewDocNode(parent->doc, ns, name, content);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001558 if (cur == NULL) return(NULL);
1559
1560 /*
1561 * add the new element at the end of the childs list.
1562 */
Daniel Veillardccb09631998-10-27 06:21:04 +00001563 cur->type = XML_ELEMENT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001564 cur->parent = parent;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001565 cur->doc = parent->doc;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001566 if (parent->childs == NULL) {
1567 parent->childs = cur;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001568 parent->last = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001569 } else {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001570 prev = parent->last;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001571 prev->next = cur;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001572 cur->prev = prev;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001573 parent->last = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001574 }
1575
1576 return(cur);
1577}
1578
Daniel Veillard97b58771998-10-20 06:14:16 +00001579/**
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00001580 * xmlAddNextSibling:
1581 * @cur: the child node
1582 * @elem: the new node
1583 *
1584 * Add a new element @elem as the next siblings of @cur
1585 * If the new element was already inserted in a document it is
1586 * first unlinked from its existing context.
1587 *
1588 * Returns the new element or NULL in case of error.
1589 */
1590xmlNodePtr
1591xmlAddNextSibling(xmlNodePtr cur, xmlNodePtr elem) {
1592 if (cur == NULL) {
1593 fprintf(stderr, "xmlAddNextSibling : cur == NULL\n");
1594 return(NULL);
1595 }
1596 if (elem == NULL) {
1597 fprintf(stderr, "xmlAddNextSibling : elem == NULL\n");
1598 return(NULL);
1599 }
1600
1601 xmlUnlinkNode(elem);
1602 elem->doc = cur->doc;
1603 elem->parent = cur->parent;
1604 elem->next = cur;
1605 elem->prev = cur->prev;
1606 cur->prev = elem;
1607 if (elem->prev != NULL)
1608 elem->prev->next = elem;
1609 if ((elem->parent != NULL) && (elem->parent->childs == cur))
1610 elem->parent->childs = elem;
1611 return(elem);
1612}
1613
1614/**
1615 * xmlAddPrevSibling:
1616 * @cur: the child node
1617 * @elem: the new node
1618 *
1619 * Add a new element @elem as the previous siblings of @cur
1620 * If the new element was already inserted in a document it is
1621 * first unlinked from its existing context.
1622 *
1623 * Returns the new element or NULL in case of error.
1624 */
1625xmlNodePtr
1626xmlAddPrevSibling(xmlNodePtr cur, xmlNodePtr elem) {
1627 if (cur == NULL) {
1628 fprintf(stderr, "xmlAddPrevSibling : cur == NULL\n");
1629 return(NULL);
1630 }
1631 if (elem == NULL) {
1632 fprintf(stderr, "xmlAddPrevSibling : elem == NULL\n");
1633 return(NULL);
1634 }
1635
1636 xmlUnlinkNode(elem);
1637 elem->doc = cur->doc;
1638 elem->parent = cur->parent;
1639 elem->prev = cur;
1640 elem->next = cur->next;
1641 cur->next = elem;
1642 if (elem->next != NULL)
1643 elem->next->prev = elem;
1644 if ((elem->parent != NULL) && (elem->parent->last == cur))
1645 elem->parent->last = elem;
1646 return(elem);
1647}
1648
1649/**
Daniel Veillardb96e6431999-08-29 21:02:19 +00001650 * xmlAddSibling:
1651 * @cur: the child node
1652 * @elem: the new node
1653 *
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00001654 * Add a new element @elem to the list of siblings of @cur
1655 * If the new element was already inserted in a document it is
1656 * first unlinked from its existing context.
1657 *
1658 * Returns the new element or NULL in case of error.
Daniel Veillardb96e6431999-08-29 21:02:19 +00001659 */
1660xmlNodePtr
1661xmlAddSibling(xmlNodePtr cur, xmlNodePtr elem) {
1662 xmlNodePtr parent;
1663
1664 if (cur == NULL) {
1665 fprintf(stderr, "xmlAddSibling : cur == NULL\n");
1666 return(NULL);
1667 }
1668
1669 if (elem == NULL) {
1670 fprintf(stderr, "xmlAddSibling : elem == NULL\n");
1671 return(NULL);
1672 }
1673
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00001674 /*
1675 * Constant time is we can rely on the ->parent->last to find
1676 * the last sibling.
1677 */
1678 if ((cur->parent != NULL) &&
1679 (cur->parent->childs != NULL) &&
1680 (cur->parent->last != NULL) &&
1681 (cur->parent->last->next == NULL)) {
1682 cur = cur->parent->last;
1683 } else {
1684 while (cur->next != NULL) cur = cur->next;
Daniel Veillardb96e6431999-08-29 21:02:19 +00001685 }
1686
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00001687 xmlUnlinkNode(elem);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001688 if (elem->doc == NULL)
1689 elem->doc = cur->doc; /* the parent may not be linked to a doc ! */
1690
1691 parent = cur->parent;
1692 elem->prev = cur;
1693 elem->next = NULL;
1694 elem->parent = parent;
1695 cur->next = elem;
1696 if (parent != NULL)
1697 parent->last = elem;
1698
1699 return(elem);
1700}
1701
1702/**
Daniel Veillard97b58771998-10-20 06:14:16 +00001703 * xmlAddChild:
1704 * @parent: the parent node
1705 * @cur: the child node
1706 *
1707 * Add a new child element, to @parent, at the end of the child list.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001708 * Returns the child or NULL in case of error.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001709 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001710xmlNodePtr
1711xmlAddChild(xmlNodePtr parent, xmlNodePtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001712 xmlNodePtr prev;
1713
1714 if (parent == NULL) {
Daniel Veillard10a2c651999-12-12 13:03:50 +00001715 fprintf(stderr, "xmlAddChild : parent == NULL\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00001716 return(NULL);
1717 }
1718
1719 if (cur == NULL) {
Daniel Veillard10a2c651999-12-12 13:03:50 +00001720 fprintf(stderr, "xmlAddChild : child == NULL\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00001721 return(NULL);
1722 }
1723
Daniel Veillard0bef1311998-10-14 02:36:47 +00001724 if ((cur->doc != NULL) && (parent->doc != NULL) &&
1725 (cur->doc != parent->doc)) {
1726 fprintf(stderr, "Elements moved to a different document\n");
1727 }
1728
Daniel Veillard260a68f1998-08-13 03:39:55 +00001729 /*
1730 * add the new element at the end of the childs list.
1731 */
1732 cur->parent = parent;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001733 cur->doc = parent->doc; /* the parent may not be linked to a doc ! */
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001734
Daniel Veillardccb09631998-10-27 06:21:04 +00001735 /*
1736 * Handle the case where parent->content != NULL, in that case it will
1737 * create a intermediate TEXT node.
1738 */
1739 if (parent->content != NULL) {
1740 xmlNodePtr text;
1741
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001742#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardccb09631998-10-27 06:21:04 +00001743 text = xmlNewDocText(parent->doc, parent->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001744#else
1745 text = xmlNewDocText(parent->doc, xmlBufferContent(parent->content));
1746#endif
Daniel Veillardccb09631998-10-27 06:21:04 +00001747 if (text != NULL) {
1748 text->next = parent->childs;
1749 if (text->next != NULL)
1750 text->next->prev = text;
1751 parent->childs = text;
Daniel Veillard1e346af1999-02-22 10:33:01 +00001752 UPDATE_LAST_CHILD(parent)
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001753#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard6454aec1999-09-02 22:04:43 +00001754 xmlFree(parent->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001755#else
1756 xmlBufferFree(parent->content);
1757#endif
Daniel Veillardccb09631998-10-27 06:21:04 +00001758 parent->content = NULL;
1759 }
1760 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00001761 if (parent->childs == NULL) {
1762 parent->childs = cur;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001763 parent->last = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001764 } else {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001765 prev = parent->last;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001766 prev->next = cur;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001767 cur->prev = prev;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001768 parent->last = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001769 }
1770
1771 return(cur);
1772}
1773
Daniel Veillard97b58771998-10-20 06:14:16 +00001774/**
1775 * xmlGetLastChild:
1776 * @parent: the parent node
1777 *
1778 * Search the last child of a node.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001779 * Returns the last child or NULL if none.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001780 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001781xmlNodePtr
1782xmlGetLastChild(xmlNodePtr parent) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001783 if (parent == NULL) {
1784 fprintf(stderr, "xmlGetLastChild : parent == NULL\n");
1785 return(NULL);
1786 }
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001787 return(parent->last);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001788}
1789
Daniel Veillard97b58771998-10-20 06:14:16 +00001790/**
1791 * xmlFreeNodeList:
1792 * @cur: the first node in the list
1793 *
1794 * Free a node and all its siblings, this is a recursive behaviour, all
1795 * the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001796 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001797void
1798xmlFreeNodeList(xmlNodePtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001799 xmlNodePtr next;
1800 if (cur == NULL) {
1801 fprintf(stderr, "xmlFreeNodeList : node == NULL\n");
1802 return;
1803 }
1804 while (cur != NULL) {
1805 next = cur->next;
1806 xmlFreeNode(cur);
1807 cur = next;
1808 }
1809}
1810
Daniel Veillard97b58771998-10-20 06:14:16 +00001811/**
1812 * xmlFreeNode:
1813 * @cur: the node
1814 *
1815 * Free a node, this is a recursive behaviour, all the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001816 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001817void
1818xmlFreeNode(xmlNodePtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001819 if (cur == NULL) {
1820 fprintf(stderr, "xmlFreeNode : node == NULL\n");
1821 return;
1822 }
Daniel Veillardccb09631998-10-27 06:21:04 +00001823 cur->doc = NULL;
1824 cur->parent = NULL;
1825 cur->next = NULL;
1826 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001827 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillardccb09631998-10-27 06:21:04 +00001828 if (cur->properties != NULL) xmlFreePropList(cur->properties);
1829 if (cur->type != XML_ENTITY_REF_NODE)
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001830#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard6454aec1999-09-02 22:04:43 +00001831 if (cur->content != NULL) xmlFree(cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001832#else
1833 if (cur->content != NULL) xmlBufferFree(cur->content);
1834#endif
Daniel Veillard6454aec1999-09-02 22:04:43 +00001835 if (cur->name != NULL) xmlFree((char *) cur->name);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001836 if (cur->nsDef != NULL) xmlFreeNsList(cur->nsDef);
1837 memset(cur, -1, sizeof(xmlNode));
Daniel Veillard6454aec1999-09-02 22:04:43 +00001838 xmlFree(cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001839}
1840
Daniel Veillard16253641998-10-28 22:58:05 +00001841/**
1842 * xmlUnlinkNode:
1843 * @cur: the node
1844 *
1845 * Unlink a node from it's current context, the node is not freed
1846 */
1847void
1848xmlUnlinkNode(xmlNodePtr cur) {
1849 if (cur == NULL) {
1850 fprintf(stderr, "xmlUnlinkNode : node == NULL\n");
1851 return;
1852 }
1853 if ((cur->parent != NULL) && (cur->parent->childs == cur))
1854 cur->parent->childs = cur->next;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001855 if ((cur->parent != NULL) && (cur->parent->last == cur))
1856 cur->parent->last = cur->prev;
Daniel Veillard16253641998-10-28 22:58:05 +00001857 if (cur->next != NULL)
1858 cur->next->prev = cur->prev;
1859 if (cur->prev != NULL)
1860 cur->prev->next = cur->next;
1861 cur->next = cur->prev = NULL;
1862 cur->parent = NULL;
1863}
1864
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00001865/**
1866 * xmlReplaceNode:
1867 * @old: the old node
1868 * @cur: the node
1869 *
1870 * Unlink the old node from it's current context, prune the new one
1871 * at the same place. If cur was already inserted in a document it is
1872 * first unlinked from its existing context.
1873 *
1874 * Returns the old node
1875 */
1876xmlNodePtr
1877xmlReplaceNode(xmlNodePtr old, xmlNodePtr cur) {
1878 if (old == NULL) {
1879 fprintf(stderr, "xmlReplaceNode : old == NULL\n");
1880 return(NULL);
1881 }
1882 if (cur == NULL) {
1883 xmlUnlinkNode(old);
1884 return(old);
1885 }
1886 xmlUnlinkNode(cur);
1887 cur->doc = old->doc;
1888 cur->parent = old->parent;
1889 cur->next = old->next;
1890 if (cur->next != NULL)
1891 cur->next->prev = cur;
1892 cur->prev = old->prev;
1893 if (cur->prev != NULL)
1894 cur->prev->next = cur;
1895 if (cur->parent != NULL) {
1896 if (cur->parent->childs == old)
1897 cur->parent->childs = cur;
1898 if (cur->parent->last == old)
1899 cur->parent->last = cur;
1900 }
1901 old->next = old->prev = NULL;
1902 old->parent = NULL;
1903 return(old);
1904}
1905
Daniel Veillard260a68f1998-08-13 03:39:55 +00001906/************************************************************************
1907 * *
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001908 * Copy operations *
1909 * *
1910 ************************************************************************/
1911
1912/**
1913 * xmlCopyNamespace:
1914 * @cur: the namespace
1915 *
1916 * Do a copy of the namespace.
1917 *
1918 * Returns: a new xmlNsPtr, or NULL in case of error.
1919 */
1920xmlNsPtr
1921xmlCopyNamespace(xmlNsPtr cur) {
1922 xmlNsPtr ret;
1923
1924 if (cur == NULL) return(NULL);
1925 switch (cur->type) {
1926 case XML_GLOBAL_NAMESPACE:
1927 ret = xmlNewGlobalNs(NULL, cur->href, cur->prefix);
1928 break;
1929 case XML_LOCAL_NAMESPACE:
1930 ret = xmlNewNs(NULL, cur->href, cur->prefix);
1931 break;
1932 default:
1933 fprintf(stderr, "xmlCopyNamespace: unknown type %d\n", cur->type);
1934 return(NULL);
1935 }
1936 return(ret);
1937}
1938
1939/**
1940 * xmlCopyNamespaceList:
1941 * @cur: the first namespace
1942 *
1943 * Do a copy of an namespace list.
1944 *
1945 * Returns: a new xmlNsPtr, or NULL in case of error.
1946 */
1947xmlNsPtr
1948xmlCopyNamespaceList(xmlNsPtr cur) {
1949 xmlNsPtr ret = NULL;
1950 xmlNsPtr p = NULL,q;
1951
1952 while (cur != NULL) {
1953 q = xmlCopyNamespace(cur);
1954 if (p == NULL) {
1955 ret = p = q;
1956 } else {
1957 p->next = q;
1958 p = q;
1959 }
1960 cur = cur->next;
1961 }
1962 return(ret);
1963}
1964
1965/**
1966 * xmlCopyProp:
Daniel Veillardb96e6431999-08-29 21:02:19 +00001967 * @target: the element where the attribute will be grafted
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001968 * @cur: the attribute
1969 *
1970 * Do a copy of the attribute.
1971 *
1972 * Returns: a new xmlAttrPtr, or NULL in case of error.
1973 */
1974xmlAttrPtr
Daniel Veillardb96e6431999-08-29 21:02:19 +00001975xmlCopyProp(xmlNodePtr target, xmlAttrPtr cur) {
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001976 xmlAttrPtr ret;
1977
1978 if (cur == NULL) return(NULL);
1979 if (cur->val != NULL)
1980 ret = xmlNewDocProp(cur->val->doc, cur->name, NULL);
1981 else
1982 ret = xmlNewDocProp(NULL, cur->name, NULL);
1983 if (ret == NULL) return(NULL);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001984
1985 if ((cur->ns != NULL) && (target != NULL)) {
1986 xmlNsPtr ns;
1987
1988 ns = xmlSearchNs(target->doc, target, cur->ns->prefix);
1989 ret->ns = ns;
1990 } else
1991 ret->ns = NULL;
1992
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001993 if (cur->val != NULL)
1994 ret->val = xmlCopyNodeList(cur->val);
1995 return(ret);
1996}
1997
1998/**
1999 * xmlCopyPropList:
Daniel Veillardb96e6431999-08-29 21:02:19 +00002000 * @target: the element where the attributes will be grafted
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002001 * @cur: the first attribute
2002 *
2003 * Do a copy of an attribute list.
2004 *
2005 * Returns: a new xmlAttrPtr, or NULL in case of error.
2006 */
2007xmlAttrPtr
Daniel Veillardb96e6431999-08-29 21:02:19 +00002008xmlCopyPropList(xmlNodePtr target, xmlAttrPtr cur) {
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002009 xmlAttrPtr ret = NULL;
2010 xmlAttrPtr p = NULL,q;
2011
2012 while (cur != NULL) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00002013 q = xmlCopyProp(target, cur);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002014 if (p == NULL) {
2015 ret = p = q;
2016 } else {
2017 p->next = q;
2018 p = q;
2019 }
2020 cur = cur->next;
2021 }
2022 return(ret);
2023}
2024
2025/*
Daniel Veillard11a48ec1999-11-23 10:40:46 +00002026 * NOTE abeut the CopyNode operations !
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002027 *
2028 * They are splitted into external and internal parts for one
2029 * tricky reason: namespaces. Doing a direct copy of a node
2030 * say RPM:Copyright without changing the namespace pointer to
2031 * something else can produce stale links. One way to do it is
2032 * to keep a reference counter but this doesn't work as soon
2033 * as one move the element or the subtree out of the scope of
2034 * the existing namespace. The actual solution seems to add
2035 * a copy of the namespace at the top of the copied tree if
2036 * not available in the subtree.
2037 * Hence two functions, the public front-end call the inner ones
2038 */
2039
2040static xmlNodePtr
2041xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent);
2042
2043static xmlNodePtr
2044xmlStaticCopyNode(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent,
2045 int recursive) {
2046 xmlNodePtr ret;
2047
2048 if (node == NULL) return(NULL);
2049 /*
2050 * Allocate a new node and fill the fields.
2051 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00002052 ret = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002053 if (ret == NULL) {
2054 fprintf(stderr, "xmlStaticCopyNode : malloc failed\n");
2055 return(NULL);
2056 }
2057
2058 ret->type = node->type;
2059 ret->doc = doc;
2060 ret->parent = parent;
2061 ret->next = NULL;
2062 ret->prev = NULL;
2063 ret->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002064 ret->last = NULL;
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002065 ret->properties = NULL;
2066 if (node->name != NULL)
2067 ret->name = xmlStrdup(node->name);
2068 else
2069 ret->name = NULL;
2070 ret->ns = NULL;
2071 ret->nsDef = NULL;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002072 if ((node->content != NULL) && (node->type != XML_ENTITY_REF_NODE)) {
2073#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002074 ret->content = xmlStrdup(node->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002075#else
2076 ret->content = xmlBufferCreateSize(xmlBufferLength(node->content));
2077 xmlBufferSetAllocationScheme(ret->content,
2078 xmlGetBufferAllocationScheme());
2079 xmlBufferAdd(ret->content,
2080 xmlBufferContent(node->content),
2081 xmlBufferLength(node->content));
2082#endif
2083 } else
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002084 ret->content = NULL;
Daniel Veillard27d88741999-05-29 11:51:49 +00002085#ifndef XML_WITHOUT_CORBA
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002086 ret->_private = NULL;
2087 ret->vepv = NULL;
2088#endif
2089 if (parent != NULL)
2090 xmlAddChild(parent, ret);
2091
2092 if (!recursive) return(ret);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002093 if (node->nsDef != NULL)
2094 ret->nsDef = xmlCopyNamespaceList(node->nsDef);
2095
2096 if (node->ns != NULL) {
2097 xmlNsPtr ns;
2098
2099 ns = xmlSearchNs(doc, ret, node->ns->prefix);
2100 if (ns == NULL) {
2101 /*
2102 * Humm, we are copying an element whose namespace is defined
2103 * out of the new tree scope. Search it in the original tree
2104 * and add it at the top of the new tree
2105 */
2106 ns = xmlSearchNs(node->doc, node, node->ns->prefix);
2107 if (ns != NULL) {
2108 xmlNodePtr root = ret;
2109
2110 while (root->parent != NULL) root = root->parent;
2111 xmlNewNs(root, ns->href, ns->prefix);
2112 }
2113 } else {
2114 /*
2115 * reference the existing namespace definition in our own tree.
2116 */
2117 ret->ns = ns;
2118 }
2119 }
Daniel Veillardb96e6431999-08-29 21:02:19 +00002120 if (node->properties != NULL)
2121 ret->properties = xmlCopyPropList(ret, node->properties);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002122 if (node->childs != NULL)
2123 ret->childs = xmlStaticCopyNodeList(node->childs, doc, ret);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002124 UPDATE_LAST_CHILD(ret)
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002125 return(ret);
2126}
2127
2128static xmlNodePtr
2129xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent) {
2130 xmlNodePtr ret = NULL;
2131 xmlNodePtr p = NULL,q;
2132
2133 while (node != NULL) {
2134 q = xmlStaticCopyNode(node, doc, parent, 1);
2135 if (parent == NULL) {
2136 if (ret == NULL) ret = q;
2137 } else {
2138 if (ret == NULL) {
2139 q->prev = NULL;
2140 ret = p = q;
2141 } else {
2142 p->next = q;
2143 q->prev = p;
2144 p = q;
2145 }
2146 }
2147 node = node->next;
2148 }
2149 return(ret);
2150}
2151
2152/**
2153 * xmlCopyNode:
2154 * @node: the node
2155 * @recursive: if 1 do a recursive copy.
2156 *
2157 * Do a copy of the node.
2158 *
2159 * Returns: a new xmlNodePtr, or NULL in case of error.
2160 */
2161xmlNodePtr
2162xmlCopyNode(xmlNodePtr node, int recursive) {
2163 xmlNodePtr ret;
2164
2165 ret = xmlStaticCopyNode(node, NULL, NULL, recursive);
2166 return(ret);
2167}
2168
2169/**
2170 * xmlCopyNodeList:
2171 * @node: the first node in the list.
2172 *
2173 * Do a recursive copy of the node list.
2174 *
2175 * Returns: a new xmlNodePtr, or NULL in case of error.
2176 */
2177xmlNodePtr xmlCopyNodeList(xmlNodePtr node) {
2178 xmlNodePtr ret = xmlStaticCopyNodeList(node, NULL, NULL);
2179 return(ret);
2180}
2181
2182/**
2183 * xmlCopyElement:
2184 * @elem: the element
2185 *
2186 * Do a copy of the element definition.
2187 *
2188 * Returns: a new xmlElementPtr, or NULL in case of error.
2189xmlElementPtr
2190xmlCopyElement(xmlElementPtr elem) {
2191 xmlElementPtr ret;
2192
2193 if (elem == NULL) return(NULL);
2194 ret = xmlNewDocElement(elem->doc, elem->ns, elem->name, elem->content);
2195 if (ret == NULL) return(NULL);
2196 if (!recursive) return(ret);
2197 if (elem->properties != NULL)
2198 ret->properties = xmlCopyPropList(elem->properties);
2199
2200 if (elem->nsDef != NULL)
2201 ret->nsDef = xmlCopyNamespaceList(elem->nsDef);
2202 if (elem->childs != NULL)
2203 ret->childs = xmlCopyElementList(elem->childs);
2204 return(ret);
2205}
2206 */
2207
2208/**
2209 * xmlCopyDtd:
2210 * @dtd: the dtd
2211 *
2212 * Do a copy of the dtd.
2213 *
2214 * Returns: a new xmlDtdPtr, or NULL in case of error.
2215 */
2216xmlDtdPtr
2217xmlCopyDtd(xmlDtdPtr dtd) {
2218 xmlDtdPtr ret;
2219
2220 if (dtd == NULL) return(NULL);
2221 ret = xmlNewDtd(NULL, dtd->name, dtd->ExternalID, dtd->SystemID);
2222 if (ret == NULL) return(NULL);
2223 if (dtd->entities != NULL)
2224 ret->entities = (void *) xmlCopyEntitiesTable(
2225 (xmlEntitiesTablePtr) dtd->entities);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002226 if (dtd->notations != NULL)
2227 ret->notations = (void *) xmlCopyNotationTable(
2228 (xmlNotationTablePtr) dtd->notations);
2229 if (dtd->elements != NULL)
2230 ret->elements = (void *) xmlCopyElementTable(
2231 (xmlElementTablePtr) dtd->elements);
2232 if (dtd->attributes != NULL)
2233 ret->attributes = (void *) xmlCopyAttributeTable(
2234 (xmlAttributeTablePtr) dtd->attributes);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002235 return(ret);
2236}
2237
2238/**
2239 * xmlCopyDoc:
2240 * @doc: the document
2241 * @recursive: if 1 do a recursive copy.
2242 *
2243 * Do a copy of the document info. If recursive, the content tree will
2244 * be copied too as well as Dtd, namespaces and entities.
2245 *
2246 * Returns: a new xmlDocPtr, or NULL in case of error.
2247 */
2248xmlDocPtr
2249xmlCopyDoc(xmlDocPtr doc, int recursive) {
2250 xmlDocPtr ret;
2251
2252 if (doc == NULL) return(NULL);
2253 ret = xmlNewDoc(doc->version);
2254 if (ret == NULL) return(NULL);
2255 if (doc->name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +00002256 ret->name = xmlMemStrdup(doc->name);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002257 if (doc->encoding != NULL)
2258 ret->encoding = xmlStrdup(doc->encoding);
2259 ret->compression = doc->compression;
2260 ret->standalone = doc->standalone;
2261 if (!recursive) return(ret);
2262
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002263 if (doc->intSubset != NULL)
2264 ret->intSubset = xmlCopyDtd(doc->intSubset);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002265 if (doc->oldNs != NULL)
2266 ret->oldNs = xmlCopyNamespaceList(doc->oldNs);
2267 if (doc->root != NULL)
2268 ret->root = xmlStaticCopyNodeList(doc->root, ret, NULL);
2269 return(ret);
2270}
2271
2272/************************************************************************
2273 * *
Daniel Veillard260a68f1998-08-13 03:39:55 +00002274 * Content access functions *
2275 * *
2276 ************************************************************************/
2277
Daniel Veillard97b58771998-10-20 06:14:16 +00002278/**
Daniel Veillard944b5ff1999-12-15 19:08:24 +00002279 * xmlDocGetRootElement:
2280 * @doc: the document
2281 *
2282 * Get the root element of the document (doc->root is a list
2283 * containing possibly comments, PIs, etc ...).
2284 *
2285 * Returns the xmlNodePtr for the root or NULL
2286 */
2287xmlNodePtr
2288xmlDocGetRootElement(xmlDocPtr doc) {
2289 xmlNodePtr ret;
2290
2291 if (doc == NULL) return(NULL);
2292 ret = doc->root;
2293 while (ret != NULL) {
2294 if (ret->type == XML_ELEMENT_NODE)
2295 return(ret);
2296 ret = ret->next;
2297 }
2298 return(ret);
2299}
2300
2301/**
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00002302 * xmlDocSetRootElement:
2303 * @doc: the document
2304 * @root: the new document root element
2305 *
2306 * Set the root element of the document (doc->root is a list
2307 * containing possibly comments, PIs, etc ...).
2308 *
2309 * Returns the old root element if any was found
2310 */
2311xmlNodePtr
2312xmlDocSetRootElement(xmlDocPtr doc, xmlNodePtr root) {
2313 xmlNodePtr old = NULL;
2314
2315 if (doc == NULL) return(NULL);
2316 old = doc->root;
2317 while (old != NULL) {
2318 if (old->type == XML_ELEMENT_NODE)
2319 break;
2320 old = old->next;
2321 }
2322 if (old == NULL) {
2323 if (doc->root == NULL) {
2324 doc->root = root;
2325 } else {
2326 xmlAddSibling(doc->root, root);
2327 }
2328 } else {
2329 xmlReplaceNode(old, root);
2330 }
2331 return(old);
2332}
2333
2334/**
Daniel Veillardb96e6431999-08-29 21:02:19 +00002335 * xmlNodeSetLang:
2336 * @cur: the node being changed
2337 * @lang: the langage description
2338 *
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00002339 * Set the language of a node, i.e. the values of the xml:lang
2340 * attribute.
Daniel Veillardb96e6431999-08-29 21:02:19 +00002341 */
2342void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002343xmlNodeSetLang(xmlNodePtr cur, const xmlChar *lang) {
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00002344 if (cur == NULL) return;
2345 switch(cur->type) {
2346 case XML_TEXT_NODE:
2347 case XML_CDATA_SECTION_NODE:
2348 case XML_COMMENT_NODE:
2349 case XML_DOCUMENT_NODE:
2350 case XML_DOCUMENT_TYPE_NODE:
2351 case XML_DOCUMENT_FRAG_NODE:
2352 case XML_NOTATION_NODE:
2353 case XML_HTML_DOCUMENT_NODE:
2354 return;
2355 case XML_ELEMENT_NODE:
2356 case XML_ATTRIBUTE_NODE:
2357 case XML_PI_NODE:
2358 case XML_ENTITY_REF_NODE:
2359 case XML_ENTITY_NODE:
2360 break;
2361 }
Daniel Veillardb96e6431999-08-29 21:02:19 +00002362 xmlSetProp(cur, BAD_CAST "xml:lang", lang);
2363}
2364
2365/**
2366 * xmlNodeGetLang:
2367 * @cur: the node being checked
2368 *
2369 * Searches the language of a node, i.e. the values of the xml:lang
2370 * attribute or the one carried by the nearest ancestor.
2371 *
2372 * Returns a pointer to the lang value, or NULL if not found
Daniel Veillarda819dac1999-11-24 18:04:22 +00002373 * It's up to the caller to free the memory.
Daniel Veillardb96e6431999-08-29 21:02:19 +00002374 */
Daniel Veillarda819dac1999-11-24 18:04:22 +00002375xmlChar *
Daniel Veillardb96e6431999-08-29 21:02:19 +00002376xmlNodeGetLang(xmlNodePtr cur) {
Daniel Veillarda819dac1999-11-24 18:04:22 +00002377 xmlChar *lang;
Daniel Veillardb96e6431999-08-29 21:02:19 +00002378
2379 while (cur != NULL) {
2380 lang = xmlGetProp(cur, BAD_CAST "xml:lang");
2381 if (lang != NULL)
2382 return(lang);
2383 cur = cur->parent;
2384 }
2385 return(NULL);
2386}
2387
2388/**
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00002389 * xmlNodeSetName:
2390 * @cur: the node being changed
2391 * @name: the new tag name
2392 *
2393 * Searches the language of a node, i.e. the values of the xml:lang
2394 * attribute or the one carried by the nearest ancestor.
2395 */
2396void
2397xmlNodeSetName(xmlNodePtr cur, const xmlChar *name) {
2398 if (cur == NULL) return;
2399 if (name == NULL) return;
2400 switch(cur->type) {
2401 case XML_TEXT_NODE:
2402 case XML_CDATA_SECTION_NODE:
2403 case XML_COMMENT_NODE:
2404 case XML_DOCUMENT_NODE:
2405 case XML_DOCUMENT_TYPE_NODE:
2406 case XML_DOCUMENT_FRAG_NODE:
2407 case XML_NOTATION_NODE:
2408 case XML_HTML_DOCUMENT_NODE:
2409 return;
2410 case XML_ELEMENT_NODE:
2411 case XML_ATTRIBUTE_NODE:
2412 case XML_PI_NODE:
2413 case XML_ENTITY_REF_NODE:
2414 case XML_ENTITY_NODE:
2415 break;
2416 }
2417 if (cur->name != NULL) xmlFree((xmlChar *) cur->name);
2418 cur->name = xmlStrdup(name);
2419}
2420
2421/**
Daniel Veillard10a2c651999-12-12 13:03:50 +00002422 * xmlNodeGetBase:
2423 * @doc: the document the node pertains to
2424 * @cur: the node being checked
2425 *
2426 * Searches for the BASE URL. The code should work on both XML
2427 * and HTML document even if base mechanisms are completely different.
2428 *
2429 * Returns a pointer to the base URL, or NULL if not found
2430 * It's up to the caller to free the memory.
2431 */
2432xmlChar *
2433xmlNodeGetBase(xmlDocPtr doc, xmlNodePtr cur) {
2434 xmlChar *base;
2435
2436 if ((cur == NULL) && (doc == NULL))
2437 return(NULL);
2438 if (doc == NULL) doc = cur->doc;
2439 if ((doc != NULL) && (doc->type == XML_HTML_DOCUMENT_NODE)) {
2440 cur = doc->root;
2441 while ((cur != NULL) && (cur->name != NULL)) {
2442 if (cur->type != XML_ELEMENT_NODE) {
2443 cur = cur->next;
2444 continue;
2445 }
2446 if ((!xmlStrcmp(cur->name, BAD_CAST "html")) ||
2447 (!xmlStrcmp(cur->name, BAD_CAST "HTML"))) {
2448 cur = cur->childs;
2449 continue;
2450 }
2451 if ((!xmlStrcmp(cur->name, BAD_CAST "head")) ||
2452 (!xmlStrcmp(cur->name, BAD_CAST "HEAD"))) {
2453 cur = cur->childs;
2454 continue;
2455 }
2456 if ((!xmlStrcmp(cur->name, BAD_CAST "base")) ||
2457 (!xmlStrcmp(cur->name, BAD_CAST "BASE"))) {
2458 base = xmlGetProp(cur, BAD_CAST "href");
2459 if (base != NULL) return(base);
2460 return(xmlGetProp(cur, BAD_CAST "HREF"));
2461 }
2462 }
2463 return(NULL);
2464 }
2465 while (cur != NULL) {
2466 base = xmlGetProp(cur, BAD_CAST "xml:base");
2467 if (base != NULL)
2468 return(base);
2469 cur = cur->parent;
2470 }
2471 return(NULL);
2472}
2473
2474/**
Daniel Veillard16253641998-10-28 22:58:05 +00002475 * xmlNodeGetContent:
2476 * @cur: the node being read
2477 *
2478 * Read the value of a node, this can be either the text carried
2479 * directly by this node if it's a TEXT node or the aggregate string
2480 * of the values carried by this node child's (TEXT and ENTITY_REF).
2481 * Entity references are substitued.
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002482 * Returns a new xmlChar * or NULL if no content is available.
Daniel Veillard5099ae81999-04-21 20:12:07 +00002483 * It's up to the caller to free the memory.
Daniel Veillard16253641998-10-28 22:58:05 +00002484 */
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002485xmlChar *
Daniel Veillard16253641998-10-28 22:58:05 +00002486xmlNodeGetContent(xmlNodePtr cur) {
2487 if (cur == NULL) return(NULL);
2488 switch (cur->type) {
2489 case XML_DOCUMENT_FRAG_NODE:
2490 case XML_ELEMENT_NODE:
2491 return(xmlNodeListGetString(cur->doc, cur->childs, 1));
2492 break;
Daniel Veillardb96e6431999-08-29 21:02:19 +00002493 case XML_ATTRIBUTE_NODE: {
2494 xmlAttrPtr attr = (xmlAttrPtr) cur;
2495 if (attr->node != NULL)
2496 return(xmlNodeListGetString(attr->node->doc, attr->val, 1));
2497 else
2498 return(xmlNodeListGetString(NULL, attr->val, 1));
2499 break;
2500 }
Daniel Veillarddbfd6411999-12-28 16:35:14 +00002501 case XML_COMMENT_NODE:
Daniel Veillardb96e6431999-08-29 21:02:19 +00002502 case XML_PI_NODE:
2503 if (cur->content != NULL)
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002504#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardb96e6431999-08-29 21:02:19 +00002505 return(xmlStrdup(cur->content));
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002506#else
2507 return(xmlStrdup(xmlBufferContent(cur->content)));
2508#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +00002509 return(NULL);
Daniel Veillard16253641998-10-28 22:58:05 +00002510 case XML_ENTITY_REF_NODE:
Daniel Veillarddbfd6411999-12-28 16:35:14 +00002511 /*
2512 * Locate the entity, and get it's content
2513 * @@@
2514 */
2515 return(NULL);
Daniel Veillard16253641998-10-28 22:58:05 +00002516 case XML_ENTITY_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002517 case XML_DOCUMENT_NODE:
Daniel Veillard7c1206f1999-10-14 09:10:25 +00002518 case XML_HTML_DOCUMENT_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002519 case XML_DOCUMENT_TYPE_NODE:
2520 case XML_NOTATION_NODE:
2521 return(NULL);
Daniel Veillardb05deb71999-08-10 19:04:08 +00002522 case XML_CDATA_SECTION_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002523 case XML_TEXT_NODE:
2524 if (cur->content != NULL)
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002525#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard16253641998-10-28 22:58:05 +00002526 return(xmlStrdup(cur->content));
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002527#else
2528 return(xmlStrdup(xmlBufferContent(cur->content)));
2529#endif
Daniel Veillard16253641998-10-28 22:58:05 +00002530 return(NULL);
2531 }
2532 return(NULL);
2533}
2534
2535/**
Daniel Veillard97b58771998-10-20 06:14:16 +00002536 * xmlNodeSetContent:
2537 * @cur: the node being modified
2538 * @content: the new value of the content
2539 *
2540 * Replace the content of a node.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002541 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002542void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002543xmlNodeSetContent(xmlNodePtr cur, const xmlChar *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002544 if (cur == NULL) {
2545 fprintf(stderr, "xmlNodeSetContent : node == NULL\n");
2546 return;
2547 }
Daniel Veillard16253641998-10-28 22:58:05 +00002548 switch (cur->type) {
2549 case XML_DOCUMENT_FRAG_NODE:
2550 case XML_ELEMENT_NODE:
2551 if (cur->content != NULL) {
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002552#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard6454aec1999-09-02 22:04:43 +00002553 xmlFree(cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002554#else
2555 xmlBufferFree(cur->content);
2556#endif
Daniel Veillard16253641998-10-28 22:58:05 +00002557 cur->content = NULL;
2558 }
Daniel Veillard6454aec1999-09-02 22:04:43 +00002559 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillard16253641998-10-28 22:58:05 +00002560 cur->childs = xmlStringGetNodeList(cur->doc, content);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002561 UPDATE_LAST_CHILD(cur)
Daniel Veillard16253641998-10-28 22:58:05 +00002562 break;
2563 case XML_ATTRIBUTE_NODE:
2564 break;
2565 case XML_TEXT_NODE:
2566 case XML_CDATA_SECTION_NODE:
2567 case XML_ENTITY_REF_NODE:
2568 case XML_ENTITY_NODE:
2569 case XML_PI_NODE:
2570 case XML_COMMENT_NODE:
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002571 if (cur->content != NULL) {
2572#ifndef XML_USE_BUFFER_CONTENT
2573 xmlFree(cur->content);
2574#else
2575 xmlBufferFree(cur->content);
2576#endif
2577 }
Daniel Veillard6454aec1999-09-02 22:04:43 +00002578 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002579 cur->last = cur->childs = NULL;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002580 if (content != NULL) {
2581#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard16253641998-10-28 22:58:05 +00002582 cur->content = xmlStrdup(content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002583#else
2584 cur->content = xmlBufferCreateSize(0);
2585 xmlBufferSetAllocationScheme(cur->content,
2586 xmlGetBufferAllocationScheme());
2587 xmlBufferAdd(cur->content, content, -1);
2588#endif
2589 } else
Daniel Veillard16253641998-10-28 22:58:05 +00002590 cur->content = NULL;
Daniel Veillardb96e6431999-08-29 21:02:19 +00002591 break;
Daniel Veillard16253641998-10-28 22:58:05 +00002592 case XML_DOCUMENT_NODE:
Daniel Veillard7c1206f1999-10-14 09:10:25 +00002593 case XML_HTML_DOCUMENT_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002594 case XML_DOCUMENT_TYPE_NODE:
2595 break;
2596 case XML_NOTATION_NODE:
2597 break;
2598 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002599}
2600
Daniel Veillard97b58771998-10-20 06:14:16 +00002601/**
2602 * xmlNodeSetContentLen:
2603 * @cur: the node being modified
2604 * @content: the new value of the content
2605 * @len: the size of @content
2606 *
2607 * Replace the content of a node.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002608 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002609void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002610xmlNodeSetContentLen(xmlNodePtr cur, const xmlChar *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002611 if (cur == NULL) {
Daniel Veillard16253641998-10-28 22:58:05 +00002612 fprintf(stderr, "xmlNodeSetContentLen : node == NULL\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002613 return;
2614 }
Daniel Veillard16253641998-10-28 22:58:05 +00002615 switch (cur->type) {
2616 case XML_DOCUMENT_FRAG_NODE:
2617 case XML_ELEMENT_NODE:
2618 if (cur->content != NULL) {
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002619#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard6454aec1999-09-02 22:04:43 +00002620 xmlFree(cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002621#else
2622 xmlBufferFree(cur->content);
2623#endif
Daniel Veillard16253641998-10-28 22:58:05 +00002624 cur->content = NULL;
2625 }
Daniel Veillard6454aec1999-09-02 22:04:43 +00002626 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillard16253641998-10-28 22:58:05 +00002627 cur->childs = xmlStringLenGetNodeList(cur->doc, content, len);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002628 UPDATE_LAST_CHILD(cur)
Daniel Veillard16253641998-10-28 22:58:05 +00002629 break;
2630 case XML_ATTRIBUTE_NODE:
2631 break;
2632 case XML_TEXT_NODE:
2633 case XML_CDATA_SECTION_NODE:
2634 case XML_ENTITY_REF_NODE:
2635 case XML_ENTITY_NODE:
2636 case XML_PI_NODE:
2637 case XML_COMMENT_NODE:
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002638 case XML_NOTATION_NODE:
2639 if (cur->content != NULL) {
2640#ifndef XML_USE_BUFFER_CONTENT
2641 xmlFree(cur->content);
2642#else
2643 xmlBufferFree(cur->content);
2644#endif
2645 }
Daniel Veillard6454aec1999-09-02 22:04:43 +00002646 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002647 cur->childs = cur->last = NULL;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002648 if (content != NULL) {
2649#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard16253641998-10-28 22:58:05 +00002650 cur->content = xmlStrndup(content, len);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002651#else
2652 cur->content = xmlBufferCreateSize(len);
2653 xmlBufferSetAllocationScheme(cur->content,
2654 xmlGetBufferAllocationScheme());
2655 xmlBufferAdd(cur->content, content, len);
2656#endif
2657 } else
Daniel Veillard16253641998-10-28 22:58:05 +00002658 cur->content = NULL;
Daniel Veillardb96e6431999-08-29 21:02:19 +00002659 break;
Daniel Veillard16253641998-10-28 22:58:05 +00002660 case XML_DOCUMENT_NODE:
Daniel Veillard7c1206f1999-10-14 09:10:25 +00002661 case XML_HTML_DOCUMENT_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002662 case XML_DOCUMENT_TYPE_NODE:
2663 break;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002664 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002665}
2666
Daniel Veillard97b58771998-10-20 06:14:16 +00002667/**
2668 * xmlNodeAddContentLen:
2669 * @cur: the node being modified
2670 * @content: extra content
2671 * @len: the size of @content
2672 *
2673 * Append the extra substring to the node content.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002674 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002675void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002676xmlNodeAddContentLen(xmlNodePtr cur, const xmlChar *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002677 if (cur == NULL) {
Daniel Veillard16253641998-10-28 22:58:05 +00002678 fprintf(stderr, "xmlNodeAddContentLen : node == NULL\n");
2679 return;
2680 }
2681 if (len <= 0) return;
2682 switch (cur->type) {
2683 case XML_DOCUMENT_FRAG_NODE:
2684 case XML_ELEMENT_NODE: {
2685 xmlNodePtr last = NULL, new;
2686
2687 if (cur->childs != NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002688 last = cur->last;
Daniel Veillard16253641998-10-28 22:58:05 +00002689 } else {
2690 if (cur->content != NULL) {
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002691#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard16253641998-10-28 22:58:05 +00002692 cur->childs = xmlStringGetNodeList(cur->doc, cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002693#else
2694 cur->childs = xmlStringGetNodeList(cur->doc,
2695 xmlBufferContent(cur->content));
2696#endif
Daniel Veillard1e346af1999-02-22 10:33:01 +00002697 UPDATE_LAST_CHILD(cur)
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002698#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard6454aec1999-09-02 22:04:43 +00002699 xmlFree(cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002700#else
2701 xmlBufferFree(cur->content);
2702#endif
Daniel Veillard16253641998-10-28 22:58:05 +00002703 cur->content = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002704 last = cur->last;
Daniel Veillard16253641998-10-28 22:58:05 +00002705 }
2706 }
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002707 new = xmlNewTextLen(content, len);
Daniel Veillard16253641998-10-28 22:58:05 +00002708 if (new != NULL) {
2709 xmlAddChild(cur, new);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002710 if ((last != NULL) && (last->next == new)) {
Daniel Veillard16253641998-10-28 22:58:05 +00002711 xmlTextMerge(last, new);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002712 }
Daniel Veillard16253641998-10-28 22:58:05 +00002713 }
2714 break;
2715 }
2716 case XML_ATTRIBUTE_NODE:
2717 break;
2718 case XML_TEXT_NODE:
2719 case XML_CDATA_SECTION_NODE:
2720 case XML_ENTITY_REF_NODE:
2721 case XML_ENTITY_NODE:
2722 case XML_PI_NODE:
2723 case XML_COMMENT_NODE:
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002724 case XML_NOTATION_NODE:
2725 if (content != NULL) {
2726#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard16253641998-10-28 22:58:05 +00002727 cur->content = xmlStrncat(cur->content, content, len);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002728#else
2729 xmlBufferAdd(cur->content, content, len);
2730#endif
2731 }
Daniel Veillard16253641998-10-28 22:58:05 +00002732 case XML_DOCUMENT_NODE:
Daniel Veillard7c1206f1999-10-14 09:10:25 +00002733 case XML_HTML_DOCUMENT_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002734 case XML_DOCUMENT_TYPE_NODE:
2735 break;
Daniel Veillard16253641998-10-28 22:58:05 +00002736 }
2737}
2738
2739/**
2740 * xmlNodeAddContent:
2741 * @cur: the node being modified
2742 * @content: extra content
2743 *
2744 * Append the extra substring to the node content.
2745 */
2746void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002747xmlNodeAddContent(xmlNodePtr cur, const xmlChar *content) {
Daniel Veillard16253641998-10-28 22:58:05 +00002748 int len;
2749
2750 if (cur == NULL) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002751 fprintf(stderr, "xmlNodeAddContent : node == NULL\n");
2752 return;
2753 }
Daniel Veillard16253641998-10-28 22:58:05 +00002754 if (content == NULL) return;
2755 len = xmlStrlen(content);
2756 xmlNodeAddContentLen(cur, content, len);
2757}
2758
2759/**
2760 * xmlTextMerge:
2761 * @first: the first text node
2762 * @second: the second text node being merged
2763 *
2764 * Merge two text nodes into one
Daniel Veillard1e346af1999-02-22 10:33:01 +00002765 * Returns the first text node augmented
Daniel Veillard16253641998-10-28 22:58:05 +00002766 */
2767xmlNodePtr
2768xmlTextMerge(xmlNodePtr first, xmlNodePtr second) {
2769 if (first == NULL) return(second);
2770 if (second == NULL) return(first);
2771 if (first->type != XML_TEXT_NODE) return(first);
2772 if (second->type != XML_TEXT_NODE) return(first);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002773#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard16253641998-10-28 22:58:05 +00002774 xmlNodeAddContent(first, second->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002775#else
2776 xmlNodeAddContent(first, xmlBufferContent(second->content));
2777#endif
Daniel Veillard16253641998-10-28 22:58:05 +00002778 xmlUnlinkNode(second);
2779 xmlFreeNode(second);
2780 return(first);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002781}
2782
Daniel Veillard97b58771998-10-20 06:14:16 +00002783/**
Daniel Veillardb96e6431999-08-29 21:02:19 +00002784 * xmlGetNsList:
2785 * @doc: the document
2786 * @node: the current node
2787 *
2788 * Search all the namespace applying to a given element.
2789 * Returns an NULL terminated array of all the xmlNsPtr found
2790 * that need to be freed by the caller or NULL if no
2791 * namespace if defined
2792 */
2793xmlNsPtr *
2794xmlGetNsList(xmlDocPtr doc, xmlNodePtr node) {
2795 xmlNsPtr cur;
2796 xmlNsPtr *ret = NULL;
2797 int nbns = 0;
2798 int maxns = 10;
2799 int i;
2800
2801 while (node != NULL) {
2802 cur = node->nsDef;
2803 while (cur != NULL) {
2804 if (ret == NULL) {
Daniel Veillard6454aec1999-09-02 22:04:43 +00002805 ret = (xmlNsPtr *) xmlMalloc((maxns + 1) * sizeof(xmlNsPtr));
Daniel Veillardb96e6431999-08-29 21:02:19 +00002806 if (ret == NULL) {
2807 fprintf(stderr, "xmlGetNsList : out of memory!\n");
2808 return(NULL);
2809 }
2810 ret[nbns] = NULL;
2811 }
2812 for (i = 0;i < nbns;i++) {
2813 if ((cur->prefix == ret[i]->prefix) ||
2814 (!xmlStrcmp(cur->prefix, ret[i]->prefix))) break;
2815 }
2816 if (i >= nbns) {
2817 if (nbns >= maxns) {
2818 maxns *= 2;
Daniel Veillard6454aec1999-09-02 22:04:43 +00002819 ret = (xmlNsPtr *) xmlRealloc(ret,
Daniel Veillardb96e6431999-08-29 21:02:19 +00002820 (maxns + 1) * sizeof(xmlNsPtr));
2821 if (ret == NULL) {
2822 fprintf(stderr, "xmlGetNsList : realloc failed!\n");
2823 return(NULL);
2824 }
2825 }
2826 ret[nbns++] = cur;
2827 ret[nbns] = NULL;
2828 }
2829
2830 cur = cur->next;
2831 }
2832 node = node->parent;
2833 }
2834 return(ret);
2835}
2836
2837/**
Daniel Veillard97b58771998-10-20 06:14:16 +00002838 * xmlSearchNs:
2839 * @doc: the document
2840 * @node: the current node
2841 * @nameSpace: the namespace string
Daniel Veillard260a68f1998-08-13 03:39:55 +00002842 *
Daniel Veillard97b58771998-10-20 06:14:16 +00002843 * Search a Ns registered under a given name space for a document.
2844 * recurse on the parents until it finds the defined namespace
2845 * or return NULL otherwise.
2846 * @nameSpace can be NULL, this is a search for the default namespace.
Daniel Veillard1e346af1999-02-22 10:33:01 +00002847 * Returns the namespace pointer or NULL.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002848 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002849xmlNsPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002850xmlSearchNs(xmlDocPtr doc, xmlNodePtr node, const xmlChar *nameSpace) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002851 xmlNsPtr cur;
2852
Daniel Veillard62ba71e1999-12-16 17:52:19 +00002853 if (node == NULL) return(NULL);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002854 while (node != NULL) {
2855 cur = node->nsDef;
2856 while (cur != NULL) {
2857 if ((cur->prefix == NULL) && (nameSpace == NULL))
2858 return(cur);
2859 if ((cur->prefix != NULL) && (nameSpace != NULL) &&
2860 (!xmlStrcmp(cur->prefix, nameSpace)))
2861 return(cur);
2862 cur = cur->next;
2863 }
2864 node = node->parent;
2865 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002866 return(NULL);
2867}
2868
Daniel Veillard97b58771998-10-20 06:14:16 +00002869/**
2870 * xmlSearchNsByHref:
2871 * @doc: the document
2872 * @node: the current node
2873 * @href: the namespace value
2874 *
2875 * Search a Ns aliasing a given URI. Recurse on the parents until it finds
2876 * the defined namespace or return NULL otherwise.
Daniel Veillard1e346af1999-02-22 10:33:01 +00002877 * Returns the namespace pointer or NULL.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002878 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002879xmlNsPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002880xmlSearchNsByHref(xmlDocPtr doc, xmlNodePtr node, const xmlChar *href) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002881 xmlNsPtr cur;
Daniel Veillarddbfd6411999-12-28 16:35:14 +00002882 xmlNodePtr orig = node;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002883
Daniel Veillard10a2c651999-12-12 13:03:50 +00002884 if ((node == NULL) || (href == NULL)) return(NULL);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002885 while (node != NULL) {
2886 cur = node->nsDef;
2887 while (cur != NULL) {
2888 if ((cur->href != NULL) && (href != NULL) &&
Daniel Veillarddbfd6411999-12-28 16:35:14 +00002889 (!xmlStrcmp(cur->href, href))) {
2890 /*
2891 * Check that the prefix is not shadowed between orig and node
2892 */
2893 xmlNodePtr check = orig;
2894 xmlNsPtr tst;
2895
2896 while (check != node) {
2897 tst = check->nsDef;
2898 while (tst != NULL) {
2899 if ((tst->prefix == NULL) && (cur->prefix == NULL))
2900 goto shadowed;
2901 if ((tst->prefix != NULL) && (cur->prefix != NULL) &&
2902 (!xmlStrcmp(tst->prefix, cur->prefix)))
2903 goto shadowed;
2904 tst = tst->next;
2905 }
2906 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002907 return(cur);
Daniel Veillarddbfd6411999-12-28 16:35:14 +00002908 }
2909shadowed:
Daniel Veillard260a68f1998-08-13 03:39:55 +00002910 cur = cur->next;
2911 }
2912 node = node->parent;
2913 }
Daniel Veillarddbfd6411999-12-28 16:35:14 +00002914 return(NULL);
2915}
2916
2917/**
2918 * xmlNewReconciliedNs
2919 * @doc: the document
2920 * @tree: a node expected to hold the new namespace
2921 * @ns: the original namespace
2922 *
2923 * This function tries to locate a namespace definition in a tree
2924 * ancestors, or create a new namespace definition node similar to
2925 * @ns trying to reuse the same prefix. However if the given prefix is
2926 * null (default namespace) or reused within the subtree defined by
2927 * @tree or on one of its ancestors then a new prefix is generated.
2928 * Returns the (new) namespace definition or NULL in case of error
2929 */
2930xmlNsPtr
2931xmlNewReconciliedNs(xmlDocPtr doc, xmlNodePtr tree, xmlNsPtr ns) {
2932 xmlNsPtr def;
2933 xmlChar prefix[50];
2934 int counter = 1;
2935
2936 if (tree == NULL) {
2937#ifdef DEBUG_TREE
2938 fprintf(stderr, "xmlNewReconciliedNs : tree == NULL\n");
2939#endif
2940 return(NULL);
2941 }
2942 if (ns == NULL) {
2943#ifdef DEBUG_TREE
2944 fprintf(stderr, "xmlNewReconciliedNs : ns == NULL\n");
2945#endif
2946 return(NULL);
2947 }
2948 /*
2949 * Search an existing namespace definition inherited.
2950 */
2951 def = xmlSearchNsByHref(doc, tree, ns->href);
2952 if (def != NULL)
2953 return(def);
2954
2955 /*
2956 * Find a close prefix which is not already in use.
2957 * Let's strip namespace prefixes longer than 20 chars !
2958 */
2959 sprintf((char *) prefix, "%.20s", ns->prefix);
2960 def = xmlSearchNs(doc, tree, prefix);
2961 while (def != NULL) {
2962 if (counter > 1000) return(NULL);
2963 sprintf((char *) prefix, "%.20s%d", ns->prefix, counter++);
2964 def = xmlSearchNs(doc, tree, prefix);
2965 }
2966
2967 /*
2968 * Ok, now we are ready to create a new one.
2969 */
2970 def = xmlNewNs(tree, ns->href, prefix);
2971 return(def);
2972}
2973
2974/**
2975 * xmlReconciliateNs
2976 * @doc: the document
2977 * @tree: a node defining the subtree to reconciliate
2978 *
2979 * This function checks that all the namespaces declared within the given
2980 * tree are properly declared. This is needed for example after Copy or Cut
2981 * and then paste operations. The subtree may still hold pointers to
2982 * namespace declarations outside the subtree or invalid/masked. As much
2983 * as possible the function try tu reuse the existing namespaces found in
2984 * the new environment. If not possible the new namespaces are redeclared
2985 * on @tree at the top of the given subtree.
2986 * Returns the number of namespace declarations created or -1 in case of error.
2987 */
2988int
2989xmlReconciliateNs(xmlDocPtr doc, xmlNodePtr tree) {
2990 xmlNsPtr *oldNs = NULL;
2991 xmlNsPtr *newNs = NULL;
2992 int sizeCache = 0;
2993 int nbCache = 0;
2994
2995 xmlNsPtr n;
2996 xmlNodePtr node = tree;
2997 xmlAttrPtr attr;
2998 int ret = 0, i;
2999
3000 while (node != NULL) {
3001 /*
3002 * Reconciliate the node namespace
3003 */
3004 if (node->ns != NULL) {
3005 /*
3006 * initialize the cache if needed
3007 */
3008 if (sizeCache == 0) {
3009 sizeCache = 10;
3010 oldNs = (xmlNsPtr *) xmlMalloc(sizeCache *
3011 sizeof(xmlNsPtr));
3012 if (oldNs == NULL) {
3013 fprintf(stderr, "xmlReconciliateNs : memory pbm\n");
3014 return(-1);
3015 }
3016 newNs = (xmlNsPtr *) xmlMalloc(sizeCache *
3017 sizeof(xmlNsPtr));
3018 if (newNs == NULL) {
3019 fprintf(stderr, "xmlReconciliateNs : memory pbm\n");
3020 xmlFree(oldNs);
3021 return(-1);
3022 }
3023 }
3024 for (i = 0;i < nbCache;i++) {
3025 if (oldNs[i] == node->ns) {
3026 node->ns = newNs[i];
3027 break;
3028 }
3029 }
3030 if (i == nbCache) {
3031 /*
3032 * Ok we need to recreate a new namespace definition
3033 */
3034 n = xmlNewReconciliedNs(doc, tree, node->ns);
3035 if (n != NULL) { /* :-( what if else ??? */
3036 /*
3037 * check if we need to grow the cache buffers.
3038 */
3039 if (sizeCache <= nbCache) {
3040 sizeCache *= 2;
3041 oldNs = (xmlNsPtr *) xmlRealloc(oldNs, sizeCache *
3042 sizeof(xmlNsPtr));
3043 if (oldNs == NULL) {
3044 fprintf(stderr, "xmlReconciliateNs : memory pbm\n");
3045 xmlFree(newNs);
3046 return(-1);
3047 }
3048 newNs = (xmlNsPtr *) xmlRealloc(newNs, sizeCache *
3049 sizeof(xmlNsPtr));
3050 if (newNs == NULL) {
3051 fprintf(stderr, "xmlReconciliateNs : memory pbm\n");
3052 xmlFree(oldNs);
3053 return(-1);
3054 }
3055 }
3056 newNs[nbCache] = n;
3057 oldNs[nbCache++] = node->ns;
3058 node->ns = n;
3059 }
3060 }
3061 }
3062 /*
3063 * now check for namespace hold by attributes on the node.
3064 */
3065 attr = node->properties;
3066 while (attr != NULL) {
3067 if (attr->ns != NULL) {
3068 /*
3069 * initialize the cache if needed
3070 */
3071 if (sizeCache == 0) {
3072 sizeCache = 10;
3073 oldNs = (xmlNsPtr *) xmlMalloc(sizeCache *
3074 sizeof(xmlNsPtr));
3075 if (oldNs == NULL) {
3076 fprintf(stderr, "xmlReconciliateNs : memory pbm\n");
3077 return(-1);
3078 }
3079 newNs = (xmlNsPtr *) xmlMalloc(sizeCache *
3080 sizeof(xmlNsPtr));
3081 if (newNs == NULL) {
3082 fprintf(stderr, "xmlReconciliateNs : memory pbm\n");
3083 xmlFree(oldNs);
3084 return(-1);
3085 }
3086 }
3087 for (i = 0;i < nbCache;i++) {
3088 if (oldNs[i] == attr->ns) {
3089 node->ns = newNs[i];
3090 break;
3091 }
3092 }
3093 if (i == nbCache) {
3094 /*
3095 * Ok we need to recreate a new namespace definition
3096 */
3097 n = xmlNewReconciliedNs(doc, tree, attr->ns);
3098 if (n != NULL) { /* :-( what if else ??? */
3099 /*
3100 * check if we need to grow the cache buffers.
3101 */
3102 if (sizeCache <= nbCache) {
3103 sizeCache *= 2;
3104 oldNs = (xmlNsPtr *) xmlRealloc(oldNs, sizeCache *
3105 sizeof(xmlNsPtr));
3106 if (oldNs == NULL) {
3107 fprintf(stderr,
3108 "xmlReconciliateNs : memory pbm\n");
3109 xmlFree(newNs);
3110 return(-1);
3111 }
3112 newNs = (xmlNsPtr *) xmlRealloc(newNs, sizeCache *
3113 sizeof(xmlNsPtr));
3114 if (newNs == NULL) {
3115 fprintf(stderr,
3116 "xmlReconciliateNs : memory pbm\n");
3117 xmlFree(oldNs);
3118 return(-1);
3119 }
3120 }
3121 newNs[nbCache] = n;
3122 oldNs[nbCache++] = attr->ns;
3123 attr->ns = n;
3124 }
3125 }
3126 }
3127 attr = attr->next;
3128 }
3129
3130 /*
3131 * Browse the full subtree, deep first
3132 */
3133 if (node->childs != NULL) {
3134 /* deep first */
3135 node = node->childs;
3136 } else if ((node != tree) && (node->next != NULL)) {
3137 /* then siblings */
3138 node = node->next;
3139 } else if (node != tree) {
3140 /* go up to parents->next if needed */
3141 while (node != tree) {
3142 if (node->parent != NULL)
3143 node = node->parent;
3144 if ((node != tree) && (node->next != NULL)) {
3145 node = node->next;
3146 break;
3147 }
3148 if (node->parent == NULL) {
3149 node = NULL;
3150 break;
3151 }
3152 }
3153 /* exit condition */
3154 if (node == tree)
3155 node = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00003156 }
3157 }
Daniel Veillarddbfd6411999-12-28 16:35:14 +00003158 return(ret);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003159}
3160
Daniel Veillard97b58771998-10-20 06:14:16 +00003161/**
3162 * xmlGetProp:
3163 * @node: the node
3164 * @name: the attribute name
3165 *
3166 * Search and get the value of an attribute associated to a node
Daniel Veillardccb09631998-10-27 06:21:04 +00003167 * This does the entity substitution.
Daniel Veillard10a2c651999-12-12 13:03:50 +00003168 * This function looks in DTD attribute declaration for #FIXED or
3169 * default declaration values unless DTD use has been turned off.
3170 *
Daniel Veillard1e346af1999-02-22 10:33:01 +00003171 * Returns the attribute value or NULL if not found.
Daniel Veillarda819dac1999-11-24 18:04:22 +00003172 * It's up to the caller to free the memory.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003173 */
Daniel Veillarda819dac1999-11-24 18:04:22 +00003174xmlChar *
3175xmlGetProp(xmlNodePtr node, const xmlChar *name) {
Daniel Veillard10a2c651999-12-12 13:03:50 +00003176 xmlAttrPtr prop;
3177 xmlDocPtr doc;
Daniel Veillard260a68f1998-08-13 03:39:55 +00003178
Daniel Veillard10a2c651999-12-12 13:03:50 +00003179 if ((node == NULL) || (name == NULL)) return(NULL);
3180 /*
3181 * Check on the properties attached to the node
3182 */
3183 prop = node->properties;
Daniel Veillard260a68f1998-08-13 03:39:55 +00003184 while (prop != NULL) {
Daniel Veillard68178931999-02-08 18:34:36 +00003185 if (!xmlStrcmp(prop->name, name)) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003186 xmlChar *ret;
Daniel Veillard6800ef31999-02-08 18:33:22 +00003187
3188 ret = xmlNodeListGetString(node->doc, prop->val, 1);
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003189 if (ret == NULL) return(xmlStrdup((xmlChar *)""));
Daniel Veillard6800ef31999-02-08 18:33:22 +00003190 return(ret);
Daniel Veillard68178931999-02-08 18:34:36 +00003191 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003192 prop = prop->next;
3193 }
Daniel Veillard10a2c651999-12-12 13:03:50 +00003194 if (!xmlCheckDTD) return(NULL);
3195
3196 /*
3197 * Check if there is a default declaration in the internal
3198 * or external subsets
3199 */
3200 doc = node->doc;
3201 if (doc != NULL) {
3202 xmlAttributePtr attrDecl;
3203 if (doc->intSubset != NULL) {
3204 attrDecl = xmlGetDtdAttrDesc(doc->intSubset, node->name, name);
3205 if ((attrDecl == NULL) && (doc->extSubset != NULL))
3206 attrDecl = xmlGetDtdAttrDesc(doc->extSubset, node->name, name);
3207 return(xmlStrdup(attrDecl->defaultValue));
3208 }
3209 }
3210 return(NULL);
3211}
3212
3213/**
3214 * xmlGetNsProp:
3215 * @node: the node
3216 * @name: the attribute name
3217 * @namespace: the URI of the namespace
3218 *
3219 * Search and get the value of an attribute associated to a node
3220 * This attribute has to be anchored in the namespace specified.
3221 * This does the entity substitution.
3222 * This function looks in DTD attribute declaration for #FIXED or
3223 * default declaration values unless DTD use has been turned off.
3224 *
3225 * Returns the attribute value or NULL if not found.
3226 * It's up to the caller to free the memory.
3227 */
3228xmlChar *
3229xmlGetNsProp(xmlNodePtr node, const xmlChar *name, const xmlChar *namespace) {
3230 xmlAttrPtr prop = node->properties;
3231 xmlDocPtr doc;
3232 xmlNsPtr ns;
3233
3234 if (namespace == NULL)
3235 return(xmlGetProp(node, name));
3236 while (prop != NULL) {
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00003237 /*
3238 * One need to have
3239 * - same attribute names
3240 * - and the attribute carrying that namespace
3241 * or
3242 * no namespace on the attribute and the element carrying it
3243 */
Daniel Veillard10a2c651999-12-12 13:03:50 +00003244 if ((!xmlStrcmp(prop->name, name)) &&
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00003245 (((prop->ns == NULL) && (node->ns != NULL) &&
3246 (!xmlStrcmp(node->ns->href, namespace))) ||
Daniel Veillard3c558c31999-12-22 11:30:41 +00003247 ((prop->ns != NULL) && (!xmlStrcmp(prop->ns->href, namespace))))) {
Daniel Veillard10a2c651999-12-12 13:03:50 +00003248 xmlChar *ret;
3249
3250 ret = xmlNodeListGetString(node->doc, prop->val, 1);
3251 if (ret == NULL) return(xmlStrdup((xmlChar *)""));
3252 return(ret);
3253 }
3254 prop = prop->next;
3255 }
3256 if (!xmlCheckDTD) return(NULL);
3257
3258 /*
3259 * Check if there is a default declaration in the internal
3260 * or external subsets
3261 */
3262 doc = node->doc;
3263 if (doc != NULL) {
3264 xmlAttributePtr attrDecl;
3265 if (doc->intSubset != NULL) {
3266 attrDecl = xmlGetDtdAttrDesc(doc->intSubset, node->name, name);
3267 if ((attrDecl == NULL) && (doc->extSubset != NULL))
3268 attrDecl = xmlGetDtdAttrDesc(doc->extSubset, node->name, name);
3269
3270 if (attrDecl->prefix != NULL) {
3271 /*
3272 * The DTD declaration only allows a prefix search
3273 */
3274 ns = xmlSearchNs(doc, node, attrDecl->prefix);
3275 if ((ns != NULL) && (!xmlStrcmp(ns->href, namespace)))
3276 return(xmlStrdup(attrDecl->defaultValue));
3277 }
3278 }
3279 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003280 return(NULL);
3281}
3282
Daniel Veillard97b58771998-10-20 06:14:16 +00003283/**
Daniel Veillardccb09631998-10-27 06:21:04 +00003284 * xmlSetProp:
Daniel Veillard97b58771998-10-20 06:14:16 +00003285 * @node: the node
3286 * @name: the attribute name
3287 * @value: the attribute value
3288 *
3289 * Set (or reset) an attribute carried by a node.
Daniel Veillard1e346af1999-02-22 10:33:01 +00003290 * Returns the attribute pointer.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003291 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003292xmlAttrPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003293xmlSetProp(xmlNodePtr node, const xmlChar *name, const xmlChar *value) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003294 xmlAttrPtr prop = node->properties;
3295
3296 while (prop != NULL) {
3297 if (!xmlStrcmp(prop->name, name)) {
Daniel Veillardccb09631998-10-27 06:21:04 +00003298 if (prop->val != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +00003299 xmlFreeNodeList(prop->val);
Daniel Veillardccb09631998-10-27 06:21:04 +00003300 prop->val = NULL;
Daniel Veillard51e3b151999-11-12 17:02:31 +00003301 if (value != NULL) {
3302 xmlChar *buffer;
3303 buffer = xmlEncodeEntitiesReentrant(node->doc, value);
3304 prop->val = xmlStringGetNodeList(node->doc, buffer);
3305 xmlFree(buffer);
3306 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003307 return(prop);
3308 }
3309 prop = prop->next;
3310 }
3311 prop = xmlNewProp(node, name, value);
3312 return(prop);
3313}
3314
Daniel Veillard97b58771998-10-20 06:14:16 +00003315/**
3316 * xmlNodeIsText:
3317 * @node: the node
3318 *
3319 * Is this node a Text node ?
Daniel Veillard1e346af1999-02-22 10:33:01 +00003320 * Returns 1 yes, 0 no
Daniel Veillard260a68f1998-08-13 03:39:55 +00003321 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003322int
3323xmlNodeIsText(xmlNodePtr node) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003324 if (node == NULL) return(0);
3325
Daniel Veillard0bef1311998-10-14 02:36:47 +00003326 if (node->type == XML_TEXT_NODE) return(1);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003327 return(0);
3328}
3329
Daniel Veillard97b58771998-10-20 06:14:16 +00003330/**
Daniel Veillard1e346af1999-02-22 10:33:01 +00003331 * xmlTextConcat:
Daniel Veillard97b58771998-10-20 06:14:16 +00003332 * @node: the node
3333 * @content: the content
3334 * @len: @content lenght
3335 *
3336 * Concat the given string at the end of the existing node content
Daniel Veillard260a68f1998-08-13 03:39:55 +00003337 */
Daniel Veillard97b58771998-10-20 06:14:16 +00003338
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003339void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003340xmlTextConcat(xmlNodePtr node, const xmlChar *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003341 if (node == NULL) return;
3342
Daniel Veillarddbfd6411999-12-28 16:35:14 +00003343 if ((node->type != XML_TEXT_NODE) &&
3344 (node->type != XML_CDATA_SECTION_NODE)) {
3345 fprintf(stderr, "xmlTextConcat: node is not text nor cdata\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003346 return;
3347 }
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003348#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard260a68f1998-08-13 03:39:55 +00003349 node->content = xmlStrncat(node->content, content, len);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003350#else
3351 xmlBufferAdd(node->content, content, len);
3352#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00003353}
3354
3355/************************************************************************
3356 * *
3357 * Output : to a FILE or in memory *
3358 * *
3359 ************************************************************************/
3360
Daniel Veillard5099ae81999-04-21 20:12:07 +00003361#define BASE_BUFFER_SIZE 4000
3362
3363/**
3364 * xmlBufferCreate:
3365 *
3366 * routine to create an XML buffer.
3367 * returns the new structure.
3368 */
3369xmlBufferPtr
3370xmlBufferCreate(void) {
3371 xmlBufferPtr ret;
3372
Daniel Veillard6454aec1999-09-02 22:04:43 +00003373 ret = (xmlBufferPtr) xmlMalloc(sizeof(xmlBuffer));
Daniel Veillard5099ae81999-04-21 20:12:07 +00003374 if (ret == NULL) {
3375 fprintf(stderr, "xmlBufferCreate : out of memory!\n");
3376 return(NULL);
3377 }
3378 ret->use = 0;
3379 ret->size = BASE_BUFFER_SIZE;
Daniel Veillard10a2c651999-12-12 13:03:50 +00003380 ret->alloc = xmlBufferAllocScheme;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003381 ret->content = (xmlChar *) xmlMalloc(ret->size * sizeof(xmlChar));
Daniel Veillard5099ae81999-04-21 20:12:07 +00003382 if (ret->content == NULL) {
3383 fprintf(stderr, "xmlBufferCreate : out of memory!\n");
Daniel Veillard6454aec1999-09-02 22:04:43 +00003384 xmlFree(ret);
Daniel Veillard5099ae81999-04-21 20:12:07 +00003385 return(NULL);
3386 }
3387 ret->content[0] = 0;
3388 return(ret);
3389}
3390
3391/**
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003392 * xmlBufferCreateSize:
3393 * @size: initial size of buffer
3394 *
3395 * routine to create an XML buffer.
3396 * returns the new structure.
3397 */
3398xmlBufferPtr
3399xmlBufferCreateSize(size_t size) {
3400 xmlBufferPtr ret;
3401
3402 ret = (xmlBufferPtr) xmlMalloc(sizeof(xmlBuffer));
3403 if (ret == NULL) {
3404 fprintf(stderr, "xmlBufferCreate : out of memory!\n");
3405 return(NULL);
3406 }
3407 ret->use = 0;
Daniel Veillard10a2c651999-12-12 13:03:50 +00003408 ret->alloc = xmlBufferAllocScheme;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003409 ret->size = (size ? size+2 : 0); /* +1 for ending null */
Daniel Veillard10a2c651999-12-12 13:03:50 +00003410 if (ret->size){
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003411 ret->content = (xmlChar *) xmlMalloc(ret->size * sizeof(xmlChar));
3412 if (ret->content == NULL) {
3413 fprintf(stderr, "xmlBufferCreate : out of memory!\n");
3414 xmlFree(ret);
3415 return(NULL);
3416 }
3417 ret->content[0] = 0;
3418 } else
3419 ret->content = NULL;
3420 return(ret);
3421}
3422
3423/**
3424 * xmlBufferAllocationScheme:
3425 * @buf: the buffer to free
3426 * @scheme: allocation scheme to use
3427 *
3428 * Sets the allocation scheme for this buffer
3429 */
3430void
3431xmlBufferSetAllocationScheme(xmlBufferPtr buf,
3432 xmlBufferAllocationScheme scheme) {
3433 if (buf == NULL) {
3434 fprintf(stderr, "xmlBufferSetAllocationScheme: buf == NULL\n");
3435 return;
3436 }
3437
3438 buf->alloc = scheme;
3439}
3440
3441/**
Daniel Veillard5099ae81999-04-21 20:12:07 +00003442 * xmlBufferFree:
3443 * @buf: the buffer to free
3444 *
3445 * Frees an XML buffer.
3446 */
3447void
3448xmlBufferFree(xmlBufferPtr buf) {
3449 if (buf == NULL) {
3450 fprintf(stderr, "xmlBufferFree: buf == NULL\n");
3451 return;
3452 }
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003453 if (buf->content != NULL) {
3454#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard5099ae81999-04-21 20:12:07 +00003455 memset(buf->content, -1, BASE_BUFFER_SIZE);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003456#else
3457 memset(buf->content, -1, buf->size);
3458#endif
Daniel Veillard6454aec1999-09-02 22:04:43 +00003459 xmlFree(buf->content);
Daniel Veillard5099ae81999-04-21 20:12:07 +00003460 }
3461 memset(buf, -1, sizeof(xmlBuffer));
Daniel Veillard6454aec1999-09-02 22:04:43 +00003462 xmlFree(buf);
Daniel Veillard5099ae81999-04-21 20:12:07 +00003463}
3464
3465/**
Daniel Veillarde2d034d1999-07-27 19:52:06 +00003466 * xmlBufferEmpty:
3467 * @buf: the buffer
3468 *
3469 * empty a buffer.
3470 */
3471void
3472xmlBufferEmpty(xmlBufferPtr buf) {
3473 buf->use = 0;
3474 memset(buf->content, -1, buf->size);/* just for debug */
3475}
3476
3477/**
3478 * xmlBufferShrink:
3479 * @buf: the buffer to dump
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003480 * @len: the number of xmlChar to remove
Daniel Veillarde2d034d1999-07-27 19:52:06 +00003481 *
3482 * Remove the beginning of an XML buffer.
3483 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003484 * Returns the number of xmlChar removed, or -1 in case of failure.
Daniel Veillarde2d034d1999-07-27 19:52:06 +00003485 */
3486int
3487xmlBufferShrink(xmlBufferPtr buf, int len) {
3488 if (len == 0) return(0);
3489 if (len > buf->use) return(-1);
3490
3491 buf->use -= len;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003492 memmove(buf->content, &buf->content[len], buf->use * sizeof(xmlChar));
Daniel Veillarde2d034d1999-07-27 19:52:06 +00003493
3494 buf->content[buf->use] = 0;
3495 return(len);
3496}
3497
3498/**
Daniel Veillard5099ae81999-04-21 20:12:07 +00003499 * xmlBufferDump:
3500 * @file: the file output
3501 * @buf: the buffer to dump
3502 *
3503 * Dumps an XML buffer to a FILE *.
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003504 * Returns the number of xmlChar written
Daniel Veillard5099ae81999-04-21 20:12:07 +00003505 */
3506int
3507xmlBufferDump(FILE *file, xmlBufferPtr buf) {
3508 int ret;
3509
3510 if (buf == NULL) {
3511 fprintf(stderr, "xmlBufferDump: buf == NULL\n");
3512 return(0);
3513 }
3514 if (buf->content == NULL) {
3515 fprintf(stderr, "xmlBufferDump: buf->content == NULL\n");
3516 return(0);
3517 }
3518 if (file == NULL) file = stdout;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003519 ret = fwrite(buf->content, sizeof(xmlChar), buf->use, file);
Daniel Veillard5099ae81999-04-21 20:12:07 +00003520 return(ret);
3521}
3522
3523/**
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003524 * xmlBufferContent:
3525 * @buf: the buffer to resize
3526 *
3527 * Returns the internal content
3528 */
3529
3530const xmlChar*
3531xmlBufferContent(const xmlBufferPtr buf)
3532{
3533 if(!buf)
3534 return NULL;
3535
3536 return buf->content;
3537}
3538
3539/**
3540 * xmlBufferLength:
3541 * @buf: the buffer
3542 *
3543 * Returns the length of data in the internal content
3544 */
3545
3546int
3547xmlBufferLength(const xmlBufferPtr buf)
3548{
3549 if(!buf)
3550 return 0;
3551
3552 return buf->use;
3553}
3554
3555/**
3556 * xmlBufferResize:
3557 * @buf: the buffer to resize
3558 * @len: the desired size
3559 *
3560 * Resize a buffer to accomodate minimum size of <len>.
3561 *
3562 * Returns 0 in case of problems, 1 otherwise
3563 */
3564int
3565xmlBufferResize(xmlBufferPtr buf, int size)
3566{
3567 int newSize = (buf->size ? buf->size*2 : size);/*take care of empty case*/
3568 xmlChar* rebuf = NULL;
3569
3570 /* Don't resize if we don't have to */
3571 if(size < buf->size)
3572 return 1;
3573
3574 /* figure out new size */
3575 switch(buf->alloc){
3576 case XML_BUFFER_ALLOC_DOUBLEIT:
3577 while(size > newSize) newSize *= 2;
3578 break;
3579 case XML_BUFFER_ALLOC_EXACT:
3580 newSize = size+10;
3581 break;
3582 default:
3583 newSize = size+10;
3584 break;
3585 }
3586
3587 if (buf->content == NULL)
3588 rebuf = (xmlChar *) xmlMalloc(newSize * sizeof(xmlChar));
3589 else
3590 rebuf = (xmlChar *) xmlRealloc(buf->content,
3591 newSize * sizeof(xmlChar));
3592 if (rebuf == NULL) {
3593 fprintf(stderr, "xmlBufferAdd : out of memory!\n");
3594 return 0;
3595 }
3596 buf->content = rebuf;
3597 buf->size = newSize;
3598
3599 return 1;
3600}
3601/**
Daniel Veillard5099ae81999-04-21 20:12:07 +00003602 * xmlBufferAdd:
3603 * @buf: the buffer to dump
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003604 * @str: the xmlChar string
3605 * @len: the number of xmlChar to add
Daniel Veillard5099ae81999-04-21 20:12:07 +00003606 *
Daniel Veillard10a2c651999-12-12 13:03:50 +00003607 * Add a string range to an XML buffer. if len == -1, the lenght of
3608 * str is recomputed.
Daniel Veillard5099ae81999-04-21 20:12:07 +00003609 */
3610void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003611xmlBufferAdd(xmlBufferPtr buf, const xmlChar *str, int len) {
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003612 int l, needSize;
Daniel Veillard5099ae81999-04-21 20:12:07 +00003613
3614 if (str == NULL) {
3615 fprintf(stderr, "xmlBufferAdd: str == NULL\n");
3616 return;
3617 }
Daniel Veillard10a2c651999-12-12 13:03:50 +00003618 if (len < -1) {
3619 fprintf(stderr, "xmlBufferAdd: len < 0\n");
3620 return;
3621 }
3622 if (len == 0) return;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003623
3624 /* CJN What's this for??? */
Daniel Veillarddbfd6411999-12-28 16:35:14 +00003625 if (len < 0)
3626 l = xmlStrlen(str);
3627 else
3628 for (l = 0;l < len;l++)
3629 if (str[l] == 0) break;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003630 if (l < len){ len = l; printf("xmlBufferAdd bad length\n"); }
3631
3632 /* CJN 11.18.99 okay, now I'm using the length */
3633 if(len == -1) len = l;
3634
3635
Daniel Veillarde2d034d1999-07-27 19:52:06 +00003636 if (len <= 0) return;
Daniel Veillard5099ae81999-04-21 20:12:07 +00003637
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003638 needSize = buf->use + len + 2;
3639 if(needSize > buf->size){
3640 if(!xmlBufferResize(buf, needSize)){
3641 fprintf(stderr, "xmlBufferAdd : out of memory!\n");
3642 return;
3643 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003644 }
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003645
3646 memmove(&buf->content[buf->use], str, len*sizeof(xmlChar));
Daniel Veillarde2d034d1999-07-27 19:52:06 +00003647 buf->use += len;
3648 buf->content[buf->use] = 0;
Daniel Veillard5099ae81999-04-21 20:12:07 +00003649}
3650
3651/**
3652 * xmlBufferCat:
3653 * @buf: the buffer to dump
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003654 * @str: the xmlChar string
Daniel Veillard5099ae81999-04-21 20:12:07 +00003655 *
3656 * Append a zero terminated string to an XML buffer.
3657 */
3658void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003659xmlBufferCat(xmlBufferPtr buf, const xmlChar *str) {
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003660 if (str != NULL)
3661 xmlBufferAdd(buf, str, -1);
Daniel Veillard5099ae81999-04-21 20:12:07 +00003662}
3663
3664/**
3665 * xmlBufferCCat:
3666 * @buf: the buffer to dump
3667 * @str: the C char string
3668 *
3669 * Append a zero terminated C string to an XML buffer.
3670 */
3671void
3672xmlBufferCCat(xmlBufferPtr buf, const char *str) {
3673 const char *cur;
3674
3675 if (str == NULL) {
3676 fprintf(stderr, "xmlBufferAdd: str == NULL\n");
3677 return;
3678 }
3679 for (cur = str;*cur != 0;cur++) {
3680 if (buf->use + 10 >= buf->size) {
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003681 if(!xmlBufferResize(buf, buf->use+10)){
3682 fprintf(stderr, "xmlBufferCCat : out of memory!\n");
3683 return;
3684 }
3685 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003686 buf->content[buf->use++] = *cur;
3687 }
3688}
Daniel Veillard260a68f1998-08-13 03:39:55 +00003689
Daniel Veillard97b58771998-10-20 06:14:16 +00003690/**
3691 * xmlBufferWriteCHAR:
Daniel Veillard5099ae81999-04-21 20:12:07 +00003692 * @buf: the XML buffer
Daniel Veillard97b58771998-10-20 06:14:16 +00003693 * @string: the string to add
3694 *
3695 * routine which manage and grows an output buffer. This one add
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003696 * xmlChars at the end of the buffer.
Daniel Veillard97b58771998-10-20 06:14:16 +00003697 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003698void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003699xmlBufferWriteCHAR(xmlBufferPtr buf, const xmlChar *string) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003700 xmlBufferCat(buf, string);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003701}
3702
Daniel Veillard97b58771998-10-20 06:14:16 +00003703/**
3704 * xmlBufferWriteChar:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003705 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003706 * @string: the string to add
3707 *
3708 * routine which manage and grows an output buffer. This one add
3709 * C chars at the end of the array.
3710 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003711void
Daniel Veillard5099ae81999-04-21 20:12:07 +00003712xmlBufferWriteChar(xmlBufferPtr buf, const char *string) {
3713 xmlBufferCCat(buf, string);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003714}
3715
Daniel Veillard5099ae81999-04-21 20:12:07 +00003716
Daniel Veillard97b58771998-10-20 06:14:16 +00003717/**
Daniel Veillard011b63c1999-06-02 17:44:04 +00003718 * xmlBufferWriteQuotedString:
3719 * @buf: the XML buffer output
3720 * @string: the string to add
3721 *
3722 * routine which manage and grows an output buffer. This one writes
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003723 * a quoted or double quoted xmlChar string, checking first if it holds
Daniel Veillard011b63c1999-06-02 17:44:04 +00003724 * quote or double-quotes internally
3725 */
3726void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003727xmlBufferWriteQuotedString(xmlBufferPtr buf, const xmlChar *string) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00003728 if (xmlStrchr(string, '"')) {
3729 if (xmlStrchr(string, '\'')) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00003730 fprintf(stderr,
3731 "xmlBufferWriteQuotedString: string contains quote and double-quotes !\n");
3732 }
3733 xmlBufferCCat(buf, "'");
3734 xmlBufferCat(buf, string);
3735 xmlBufferCCat(buf, "'");
3736 } else {
3737 xmlBufferCCat(buf, "\"");
3738 xmlBufferCat(buf, string);
3739 xmlBufferCCat(buf, "\"");
3740 }
3741}
3742
3743
3744/**
Daniel Veillard97b58771998-10-20 06:14:16 +00003745 * xmlGlobalNsDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003746 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003747 * @cur: a namespace
3748 *
3749 * Dump a global Namespace, this is the old version based on PIs.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003750 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003751static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00003752xmlGlobalNsDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003753 if (cur == NULL) {
3754 fprintf(stderr, "xmlGlobalNsDump : Ns == NULL\n");
3755 return;
3756 }
3757 if (cur->type == XML_GLOBAL_NAMESPACE) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003758 xmlBufferWriteChar(buf, "<?namespace");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003759 if (cur->href != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00003760 xmlBufferWriteChar(buf, " href=");
3761 xmlBufferWriteQuotedString(buf, cur->href);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003762 }
3763 if (cur->prefix != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00003764 xmlBufferWriteChar(buf, " AS=");
3765 xmlBufferWriteQuotedString(buf, cur->prefix);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003766 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003767 xmlBufferWriteChar(buf, "?>\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003768 }
3769}
3770
Daniel Veillard97b58771998-10-20 06:14:16 +00003771/**
3772 * xmlGlobalNsListDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003773 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003774 * @cur: the first namespace
3775 *
3776 * Dump a list of global Namespace, this is the old version based on PIs.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003777 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003778static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00003779xmlGlobalNsListDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003780 while (cur != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003781 xmlGlobalNsDump(buf, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003782 cur = cur->next;
3783 }
3784}
3785
Daniel Veillard97b58771998-10-20 06:14:16 +00003786/**
3787 * xmlNsDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003788 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003789 * @cur: a namespace
3790 *
Daniel Veillard260a68f1998-08-13 03:39:55 +00003791 * Dump a local Namespace definition.
Daniel Veillard97b58771998-10-20 06:14:16 +00003792 * Should be called in the context of attributes dumps.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003793 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003794static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00003795xmlNsDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003796 if (cur == NULL) {
3797 fprintf(stderr, "xmlNsDump : Ns == NULL\n");
3798 return;
3799 }
3800 if (cur->type == XML_LOCAL_NAMESPACE) {
3801 /* Within the context of an element attributes */
3802 if (cur->prefix != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003803 xmlBufferWriteChar(buf, " xmlns:");
3804 xmlBufferWriteCHAR(buf, cur->prefix);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003805 } else
Daniel Veillard5099ae81999-04-21 20:12:07 +00003806 xmlBufferWriteChar(buf, " xmlns");
Daniel Veillard011b63c1999-06-02 17:44:04 +00003807 xmlBufferWriteChar(buf, "=");
3808 xmlBufferWriteQuotedString(buf, cur->href);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003809 }
3810}
3811
Daniel Veillard97b58771998-10-20 06:14:16 +00003812/**
3813 * xmlNsListDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003814 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003815 * @cur: the first namespace
3816 *
3817 * Dump a list of local Namespace definitions.
3818 * Should be called in the context of attributes dumps.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003819 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003820static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00003821xmlNsListDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003822 while (cur != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003823 xmlNsDump(buf, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003824 cur = cur->next;
3825 }
3826}
3827
Daniel Veillard97b58771998-10-20 06:14:16 +00003828/**
3829 * xmlDtdDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003830 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003831 * @doc: the document
3832 *
3833 * Dump the XML document DTD, if any.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003834 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003835static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00003836xmlDtdDump(xmlBufferPtr buf, xmlDocPtr doc) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003837 xmlDtdPtr cur = doc->intSubset;
Daniel Veillard260a68f1998-08-13 03:39:55 +00003838
3839 if (cur == NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003840 fprintf(stderr, "xmlDtdDump : no internal subset\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003841 return;
3842 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003843 xmlBufferWriteChar(buf, "<!DOCTYPE ");
3844 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003845 if (cur->ExternalID != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00003846 xmlBufferWriteChar(buf, " PUBLIC ");
3847 xmlBufferWriteQuotedString(buf, cur->ExternalID);
3848 xmlBufferWriteChar(buf, " ");
3849 xmlBufferWriteQuotedString(buf, cur->SystemID);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003850 } else if (cur->SystemID != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00003851 xmlBufferWriteChar(buf, " SYSTEM ");
3852 xmlBufferWriteQuotedString(buf, cur->SystemID);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003853 }
Daniel Veillard1e346af1999-02-22 10:33:01 +00003854 if ((cur->entities == NULL) && (cur->elements == NULL) &&
3855 (cur->attributes == NULL) && (cur->notations == NULL)) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003856 xmlBufferWriteChar(buf, ">\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003857 return;
3858 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003859 xmlBufferWriteChar(buf, " [\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003860 if (cur->entities != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00003861 xmlDumpEntitiesTable(buf, (xmlEntitiesTablePtr) cur->entities);
Daniel Veillard1e346af1999-02-22 10:33:01 +00003862 if (cur->notations != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00003863 xmlDumpNotationTable(buf, (xmlNotationTablePtr) cur->notations);
Daniel Veillard3b9def11999-01-31 22:15:06 +00003864 if (cur->elements != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00003865 xmlDumpElementTable(buf, (xmlElementTablePtr) cur->elements);
Daniel Veillard1e346af1999-02-22 10:33:01 +00003866 if (cur->attributes != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00003867 xmlDumpAttributeTable(buf, (xmlAttributeTablePtr) cur->attributes);
3868 xmlBufferWriteChar(buf, "]");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003869
Daniel Veillard5099ae81999-04-21 20:12:07 +00003870 xmlBufferWriteChar(buf, ">\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003871}
3872
Daniel Veillard97b58771998-10-20 06:14:16 +00003873/**
3874 * xmlAttrDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003875 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003876 * @doc: the document
3877 * @cur: the attribute pointer
3878 *
3879 * Dump an XML attribute
Daniel Veillard260a68f1998-08-13 03:39:55 +00003880 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003881static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00003882xmlAttrDump(xmlBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003883 xmlChar *value;
Daniel Veillardccb09631998-10-27 06:21:04 +00003884
Daniel Veillard260a68f1998-08-13 03:39:55 +00003885 if (cur == NULL) {
3886 fprintf(stderr, "xmlAttrDump : property == NULL\n");
3887 return;
3888 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003889 xmlBufferWriteChar(buf, " ");
Daniel Veillardb96e6431999-08-29 21:02:19 +00003890 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
3891 xmlBufferWriteCHAR(buf, cur->ns->prefix);
3892 xmlBufferWriteChar(buf, ":");
3893 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003894 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillardccb09631998-10-27 06:21:04 +00003895 value = xmlNodeListGetString(doc, cur->val, 0);
3896 if (value) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00003897 xmlBufferWriteChar(buf, "=");
3898 xmlBufferWriteQuotedString(buf, value);
Daniel Veillard6454aec1999-09-02 22:04:43 +00003899 xmlFree(value);
Daniel Veillard726c7e31999-02-08 15:13:10 +00003900 } else {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003901 xmlBufferWriteChar(buf, "=\"\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003902 }
3903}
3904
Daniel Veillard97b58771998-10-20 06:14:16 +00003905/**
3906 * xmlAttrListDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003907 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003908 * @doc: the document
3909 * @cur: the first attribute pointer
3910 *
3911 * Dump a list of XML attributes
Daniel Veillard260a68f1998-08-13 03:39:55 +00003912 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003913static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00003914xmlAttrListDump(xmlBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003915 if (cur == NULL) {
3916 fprintf(stderr, "xmlAttrListDump : property == NULL\n");
3917 return;
3918 }
3919 while (cur != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003920 xmlAttrDump(buf, doc, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003921 cur = cur->next;
3922 }
3923}
3924
Daniel Veillard260a68f1998-08-13 03:39:55 +00003925
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003926static void
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003927xmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
3928 int format);
Daniel Veillarddbfd6411999-12-28 16:35:14 +00003929void
3930htmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur);
3931
Daniel Veillard97b58771998-10-20 06:14:16 +00003932/**
3933 * xmlNodeListDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003934 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003935 * @doc: the document
3936 * @cur: the first node
3937 * @level: the imbrication level for indenting
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003938 * @format: is formatting allowed
Daniel Veillard97b58771998-10-20 06:14:16 +00003939 *
3940 * Dump an XML node list, recursive behaviour,children are printed too.
3941 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003942static void
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003943xmlNodeListDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
3944 int format) {
3945 int i;
Daniel Veillardccb09631998-10-27 06:21:04 +00003946
Daniel Veillard260a68f1998-08-13 03:39:55 +00003947 if (cur == NULL) {
3948 fprintf(stderr, "xmlNodeListDump : node == NULL\n");
3949 return;
3950 }
3951 while (cur != NULL) {
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003952 if ((format) && (xmlIndentTreeOutput) &&
3953 (cur->type == XML_ELEMENT_NODE))
3954 for (i = 0;i < level;i++)
3955 xmlBufferWriteChar(buf, " ");
3956 xmlNodeDump(buf, doc, cur, level, format);
3957 if (format) {
3958 xmlBufferWriteChar(buf, "\n");
Daniel Veillardccb09631998-10-27 06:21:04 +00003959 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003960 cur = cur->next;
3961 }
3962}
3963
Daniel Veillard97b58771998-10-20 06:14:16 +00003964/**
Daniel Veillardccb09631998-10-27 06:21:04 +00003965 * xmlNodeDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003966 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003967 * @doc: the document
3968 * @cur: the current node
3969 * @level: the imbrication level for indenting
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003970 * @format: is formatting allowed
Daniel Veillard97b58771998-10-20 06:14:16 +00003971 *
3972 * Dump an XML node, recursive behaviour,children are printed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003973 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003974static void
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003975xmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
3976 int format) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003977 int i;
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003978 xmlNodePtr tmp;
Daniel Veillard260a68f1998-08-13 03:39:55 +00003979
3980 if (cur == NULL) {
3981 fprintf(stderr, "xmlNodeDump : node == NULL\n");
3982 return;
3983 }
Daniel Veillard0bef1311998-10-14 02:36:47 +00003984 if (cur->type == XML_TEXT_NODE) {
Daniel Veillard14fff061999-06-22 21:49:07 +00003985 if (cur->content != NULL) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003986 xmlChar *buffer;
Daniel Veillard14fff061999-06-22 21:49:07 +00003987
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003988#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard14fff061999-06-22 21:49:07 +00003989 buffer = xmlEncodeEntitiesReentrant(doc, cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003990#else
3991 buffer = xmlEncodeEntitiesReentrant(doc,
3992 xmlBufferContent(cur->content));
3993#endif
Daniel Veillard14fff061999-06-22 21:49:07 +00003994 if (buffer != NULL) {
3995 xmlBufferWriteCHAR(buf, buffer);
Daniel Veillard6454aec1999-09-02 22:04:43 +00003996 xmlFree(buffer);
Daniel Veillard14fff061999-06-22 21:49:07 +00003997 }
3998 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003999 return;
4000 }
Daniel Veillardb96e6431999-08-29 21:02:19 +00004001 if (cur->type == XML_PI_NODE) {
4002 if (cur->content != NULL) {
4003 xmlBufferWriteChar(buf, "<?");
4004 xmlBufferWriteCHAR(buf, cur->name);
4005 if (cur->content != NULL) {
4006 xmlBufferWriteChar(buf, " ");
Daniel Veillardf5c2c871999-12-01 09:51:45 +00004007#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardb96e6431999-08-29 21:02:19 +00004008 xmlBufferWriteCHAR(buf, cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00004009#else
4010 xmlBufferWriteCHAR(buf, xmlBufferContent(cur->content));
4011#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +00004012 }
Daniel Veillard7d2c2761999-10-11 15:09:51 +00004013 xmlBufferWriteChar(buf, "?>");
Daniel Veillardb96e6431999-08-29 21:02:19 +00004014 }
4015 return;
4016 }
Daniel Veillard0bef1311998-10-14 02:36:47 +00004017 if (cur->type == XML_COMMENT_NODE) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00004018 if (cur->content != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00004019 xmlBufferWriteChar(buf, "<!--");
Daniel Veillardf5c2c871999-12-01 09:51:45 +00004020#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard5099ae81999-04-21 20:12:07 +00004021 xmlBufferWriteCHAR(buf, cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00004022#else
4023 xmlBufferWriteCHAR(buf, xmlBufferContent(cur->content));
4024#endif
Daniel Veillard7d2c2761999-10-11 15:09:51 +00004025 xmlBufferWriteChar(buf, "-->");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004026 }
4027 return;
4028 }
Daniel Veillardccb09631998-10-27 06:21:04 +00004029 if (cur->type == XML_ENTITY_REF_NODE) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00004030 xmlBufferWriteChar(buf, "&");
4031 xmlBufferWriteCHAR(buf, cur->name);
4032 xmlBufferWriteChar(buf, ";");
Daniel Veillardccb09631998-10-27 06:21:04 +00004033 return;
4034 }
Daniel Veillardb05deb71999-08-10 19:04:08 +00004035 if (cur->type == XML_CDATA_SECTION_NODE) {
4036 xmlBufferWriteChar(buf, "<![CDATA[");
4037 if (cur->content != NULL)
Daniel Veillardf5c2c871999-12-01 09:51:45 +00004038#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardb05deb71999-08-10 19:04:08 +00004039 xmlBufferWriteCHAR(buf, cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00004040#else
4041 xmlBufferWriteCHAR(buf, xmlBufferContent(cur->content));
4042#endif
Daniel Veillardb05deb71999-08-10 19:04:08 +00004043 xmlBufferWriteChar(buf, "]]>");
4044 return;
4045 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00004046
Daniel Veillard7d2c2761999-10-11 15:09:51 +00004047 if (format == 1) {
4048 tmp = cur->childs;
4049 while (tmp != NULL) {
4050 if ((tmp->type == XML_TEXT_NODE) ||
4051 (tmp->type == XML_ENTITY_REF_NODE)) {
4052 format = 0;
4053 break;
4054 }
4055 tmp = tmp->next;
4056 }
4057 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00004058 xmlBufferWriteChar(buf, "<");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004059 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00004060 xmlBufferWriteCHAR(buf, cur->ns->prefix);
4061 xmlBufferWriteChar(buf, ":");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004062 }
4063
Daniel Veillard5099ae81999-04-21 20:12:07 +00004064 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004065 if (cur->nsDef)
Daniel Veillard5099ae81999-04-21 20:12:07 +00004066 xmlNsListDump(buf, cur->nsDef);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004067 if (cur->properties != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00004068 xmlAttrListDump(buf, doc, cur->properties);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004069
4070 if ((cur->content == NULL) && (cur->childs == NULL)) {
Daniel Veillard7d2c2761999-10-11 15:09:51 +00004071 xmlBufferWriteChar(buf, "/>");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004072 return;
4073 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00004074 xmlBufferWriteChar(buf, ">");
Daniel Veillard14fff061999-06-22 21:49:07 +00004075 if (cur->content != NULL) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004076 xmlChar *buffer;
Daniel Veillard14fff061999-06-22 21:49:07 +00004077
Daniel Veillardf5c2c871999-12-01 09:51:45 +00004078#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard14fff061999-06-22 21:49:07 +00004079 buffer = xmlEncodeEntitiesReentrant(doc, cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00004080#else
4081 buffer = xmlEncodeEntitiesReentrant(doc,
4082 xmlBufferContent(cur->content));
4083#endif
Daniel Veillard14fff061999-06-22 21:49:07 +00004084 if (buffer != NULL) {
4085 xmlBufferWriteCHAR(buf, buffer);
Daniel Veillard6454aec1999-09-02 22:04:43 +00004086 xmlFree(buffer);
Daniel Veillard14fff061999-06-22 21:49:07 +00004087 }
4088 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00004089 if (cur->childs != NULL) {
Daniel Veillard7d2c2761999-10-11 15:09:51 +00004090 if (format) xmlBufferWriteChar(buf, "\n");
4091 xmlNodeListDump(buf, doc, cur->childs, level + 1, format);
4092 if ((xmlIndentTreeOutput) && (format))
4093 for (i = 0;i < level;i++)
4094 xmlBufferWriteChar(buf, " ");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004095 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00004096 xmlBufferWriteChar(buf, "</");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004097 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00004098 xmlBufferWriteCHAR(buf, cur->ns->prefix);
4099 xmlBufferWriteChar(buf, ":");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004100 }
4101
Daniel Veillard5099ae81999-04-21 20:12:07 +00004102 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillard7d2c2761999-10-11 15:09:51 +00004103 xmlBufferWriteChar(buf, ">");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004104}
4105
Daniel Veillard97b58771998-10-20 06:14:16 +00004106/**
Daniel Veillarddbfd6411999-12-28 16:35:14 +00004107 * xmlElemDump:
4108 * @buf: the XML buffer output
4109 * @doc: the document
4110 * @cur: the current node
4111 *
4112 * Dump an XML/HTML node, recursive behaviour,children are printed too.
4113 */
4114void
4115xmlElemDump(FILE *f, xmlDocPtr doc, xmlNodePtr cur) {
4116 xmlBufferPtr buf;
4117
4118 if (cur == NULL) {
4119#ifdef DEBUG_TREE
4120 fprintf(stderr, "xmlElemDump : cur == NULL\n");
4121#endif
4122 return;
4123 }
4124 if (doc == NULL) {
4125#ifdef DEBUG_TREE
4126 fprintf(stderr, "xmlElemDump : doc == NULL\n");
4127#endif
4128 }
4129 buf = xmlBufferCreate();
4130 if (buf == NULL) return;
4131 if ((doc != NULL) &&
4132 (doc->type == XML_HTML_DOCUMENT_NODE)) {
4133 htmlNodeDump(buf, doc, cur);
4134 } else
4135 xmlNodeDump(buf, doc, cur, 0, 1);
4136 xmlBufferDump(f, buf);
4137 xmlBufferFree(buf);
4138}
4139
4140/**
Daniel Veillard97b58771998-10-20 06:14:16 +00004141 * xmlDocContentDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00004142 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00004143 * @cur: the document
4144 *
4145 * Dump an XML document.
Daniel Veillard260a68f1998-08-13 03:39:55 +00004146 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00004147static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00004148xmlDocContentDump(xmlBufferPtr buf, xmlDocPtr cur) {
Daniel Veillardbe70ff71999-07-05 16:50:46 +00004149 xmlBufferWriteChar(buf, "<?xml version=");
4150 if (cur->version != NULL)
4151 xmlBufferWriteQuotedString(buf, cur->version);
4152 else
4153 xmlBufferWriteChar(buf, "\"1.0\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004154 if (cur->encoding != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00004155 xmlBufferWriteChar(buf, " encoding=");
4156 xmlBufferWriteQuotedString(buf, cur->encoding);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004157 }
4158 switch (cur->standalone) {
4159 case 0:
Daniel Veillard5099ae81999-04-21 20:12:07 +00004160 xmlBufferWriteChar(buf, " standalone=\"no\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004161 break;
4162 case 1:
Daniel Veillard5099ae81999-04-21 20:12:07 +00004163 xmlBufferWriteChar(buf, " standalone=\"yes\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004164 break;
4165 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00004166 xmlBufferWriteChar(buf, "?>\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004167 if (cur->intSubset != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00004168 xmlDtdDump(buf, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004169 if (cur->root != NULL) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00004170 xmlNodePtr child = cur->root;
4171
Daniel Veillard260a68f1998-08-13 03:39:55 +00004172 /* global namespace definitions, the old way */
4173 if (oldXMLWDcompatibility)
Daniel Veillard5099ae81999-04-21 20:12:07 +00004174 xmlGlobalNsListDump(buf, cur->oldNs);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004175 else
4176 xmlUpgradeOldNs(cur);
Daniel Veillardb96e6431999-08-29 21:02:19 +00004177
4178 while (child != NULL) {
Daniel Veillard7d2c2761999-10-11 15:09:51 +00004179 xmlNodeDump(buf, cur, child, 0, 1);
4180 xmlBufferWriteChar(buf, "\n");
Daniel Veillardb96e6431999-08-29 21:02:19 +00004181 child = child->next;
4182 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00004183 }
4184}
4185
Daniel Veillard97b58771998-10-20 06:14:16 +00004186/**
4187 * xmlDocDumpMemory:
4188 * @cur: the document
4189 * @mem: OUT: the memory pointer
4190 * @size: OUT: the memory lenght
4191 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004192 * Dump an XML document in memory and return the xmlChar * and it's size.
Daniel Veillard97b58771998-10-20 06:14:16 +00004193 * It's up to the caller to free the memory.
Daniel Veillard260a68f1998-08-13 03:39:55 +00004194 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00004195void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004196xmlDocDumpMemory(xmlDocPtr cur, xmlChar**mem, int *size) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00004197 xmlBufferPtr buf;
4198
Daniel Veillard260a68f1998-08-13 03:39:55 +00004199 if (cur == NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004200#ifdef DEBUG_TREE
4201 fprintf(stderr, "xmlDocDumpMemory : document == NULL\n");
4202#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00004203 *mem = NULL;
4204 *size = 0;
4205 return;
4206 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00004207 buf = xmlBufferCreate();
4208 if (buf == NULL) {
4209 *mem = NULL;
4210 *size = 0;
4211 return;
4212 }
4213 xmlDocContentDump(buf, cur);
Daniel Veillardb05deb71999-08-10 19:04:08 +00004214 *mem = xmlStrndup(buf->content, buf->use);
Daniel Veillard5099ae81999-04-21 20:12:07 +00004215 *size = buf->use;
Daniel Veillardb05deb71999-08-10 19:04:08 +00004216 xmlBufferFree(buf);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004217}
4218
Daniel Veillard97b58771998-10-20 06:14:16 +00004219/**
4220 * xmlGetDocCompressMode:
4221 * @doc: the document
4222 *
4223 * get the compression ratio for a document, ZLIB based
Daniel Veillard1e346af1999-02-22 10:33:01 +00004224 * Returns 0 (uncompressed) to 9 (max compression)
Daniel Veillard151b1b01998-09-23 00:49:46 +00004225 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00004226int
Daniel Veillarddbfd6411999-12-28 16:35:14 +00004227xmlGetDocCompressMode (xmlDocPtr doc) {
Daniel Veillard15a8df41998-09-24 19:15:06 +00004228 if (doc == NULL) return(-1);
4229 return(doc->compression);
4230}
4231
Daniel Veillard97b58771998-10-20 06:14:16 +00004232/**
4233 * xmlSetDocCompressMode:
4234 * @doc: the document
4235 * @mode: the compression ratio
4236 *
4237 * set the compression ratio for a document, ZLIB based
4238 * Correct values: 0 (uncompressed) to 9 (max compression)
4239 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00004240void
4241xmlSetDocCompressMode (xmlDocPtr doc, int mode) {
Daniel Veillard15a8df41998-09-24 19:15:06 +00004242 if (doc == NULL) return;
4243 if (mode < 0) doc->compression = 0;
4244 else if (mode > 9) doc->compression = 9;
4245 else doc->compression = mode;
4246}
4247
Daniel Veillard97b58771998-10-20 06:14:16 +00004248/**
4249 * xmlGetCompressMode:
4250 *
4251 * get the default compression mode used, ZLIB based.
Daniel Veillard1e346af1999-02-22 10:33:01 +00004252 * Returns 0 (uncompressed) to 9 (max compression)
Daniel Veillard15a8df41998-09-24 19:15:06 +00004253 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00004254int
4255 xmlGetCompressMode(void) {
Daniel Veillard151b1b01998-09-23 00:49:46 +00004256 return(xmlCompressMode);
4257}
Daniel Veillard97b58771998-10-20 06:14:16 +00004258
4259/**
4260 * xmlSetCompressMode:
4261 * @mode: the compression ratio
4262 *
4263 * set the default compression mode used, ZLIB based
4264 * Correct values: 0 (uncompressed) to 9 (max compression)
4265 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00004266void
4267xmlSetCompressMode(int mode) {
Daniel Veillard151b1b01998-09-23 00:49:46 +00004268 if (mode < 0) xmlCompressMode = 0;
Daniel Veillard15a8df41998-09-24 19:15:06 +00004269 else if (mode > 9) xmlCompressMode = 9;
Daniel Veillard151b1b01998-09-23 00:49:46 +00004270 else xmlCompressMode = mode;
4271}
4272
Daniel Veillard97b58771998-10-20 06:14:16 +00004273/**
4274 * xmlDocDump:
4275 * @f: the FILE*
4276 * @cur: the document
4277 *
4278 * Dump an XML document to an open FILE.
Daniel Veillard260a68f1998-08-13 03:39:55 +00004279 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00004280void
4281xmlDocDump(FILE *f, xmlDocPtr cur) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00004282 xmlBufferPtr buf;
4283
Daniel Veillard260a68f1998-08-13 03:39:55 +00004284 if (cur == NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004285#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00004286 fprintf(stderr, "xmlDocDump : document == NULL\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004287#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00004288 return;
4289 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00004290 buf = xmlBufferCreate();
4291 if (buf == NULL) return;
4292 xmlDocContentDump(buf, cur);
4293 xmlBufferDump(f, buf);
4294 xmlBufferFree(buf);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004295}
4296
Daniel Veillard97b58771998-10-20 06:14:16 +00004297/**
4298 * xmlSaveFile:
4299 * @filename: the filename
4300 * @cur: the document
4301 *
4302 * Dump an XML document to a file. Will use compression if
Daniel Veillard11a48ec1999-11-23 10:40:46 +00004303 * compiled in and enabled. If @filename is "-" the stdout file is
4304 * used.
Daniel Veillard97b58771998-10-20 06:14:16 +00004305 * returns: the number of file written or -1 in case of failure.
Daniel Veillard151b1b01998-09-23 00:49:46 +00004306 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00004307int
4308xmlSaveFile(const char *filename, xmlDocPtr cur) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00004309 xmlBufferPtr buf;
Daniel Veillard151b1b01998-09-23 00:49:46 +00004310#ifdef HAVE_ZLIB_H
4311 gzFile zoutput = NULL;
4312 char mode[15];
4313#endif
Daniel Veillardccb09631998-10-27 06:21:04 +00004314 FILE *output = NULL;
Daniel Veillard151b1b01998-09-23 00:49:46 +00004315 int ret;
4316
Daniel Veillard5099ae81999-04-21 20:12:07 +00004317 /*
4318 * save the content to a temp buffer.
4319 */
4320 buf = xmlBufferCreate();
4321 if (buf == NULL) return(0);
4322 xmlDocContentDump(buf, cur);
4323
Daniel Veillard151b1b01998-09-23 00:49:46 +00004324#ifdef HAVE_ZLIB_H
Daniel Veillard11a48ec1999-11-23 10:40:46 +00004325 if (cur->compression < 0) cur->compression = xmlCompressMode;
Daniel Veillarddc3dd9d1998-09-24 19:25:54 +00004326 if ((cur->compression > 0) && (cur->compression <= 9)) {
4327 sprintf(mode, "w%d", cur->compression);
Daniel Veillard11a48ec1999-11-23 10:40:46 +00004328 if (!strcmp(filename, "-"))
4329 zoutput = gzdopen(1, mode);
4330 else
4331 zoutput = gzopen(filename, mode);
Daniel Veillard151b1b01998-09-23 00:49:46 +00004332 }
4333 if (zoutput == NULL) {
4334#endif
4335 output = fopen(filename, "w");
Daniel Veillard10a2c651999-12-12 13:03:50 +00004336 if (output == NULL) {
4337 xmlBufferFree(buf);
4338 return(-1);
4339 }
Daniel Veillard151b1b01998-09-23 00:49:46 +00004340#ifdef HAVE_ZLIB_H
4341 }
Daniel Veillard151b1b01998-09-23 00:49:46 +00004342
Daniel Veillard151b1b01998-09-23 00:49:46 +00004343 if (zoutput != NULL) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004344 ret = gzwrite(zoutput, buf->content, sizeof(xmlChar) * buf->use);
Daniel Veillard151b1b01998-09-23 00:49:46 +00004345 gzclose(zoutput);
Daniel Veillard5099ae81999-04-21 20:12:07 +00004346 } else {
4347#endif
4348 ret = xmlBufferDump(output, buf);
4349 fclose(output);
4350#ifdef HAVE_ZLIB_H
Daniel Veillard151b1b01998-09-23 00:49:46 +00004351 }
4352#endif
Manish Vachharajani5e60f5a1999-05-29 03:04:30 +00004353 xmlBufferFree(buf);
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004354 return(ret * sizeof(xmlChar));
Daniel Veillard151b1b01998-09-23 00:49:46 +00004355}
4356