blob: a920d400602f7469df694464fa9b7589932a0a64 [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
10#define HAVE_FCNTL_H
11#include <io.h>
12#else
Daniel Veillard151b1b01998-09-23 00:49:46 +000013#include "config.h"
Daniel Veillard7f7d1111999-09-22 09:46:25 +000014#endif
15
Daniel Veillard260a68f1998-08-13 03:39:55 +000016#include <stdio.h>
Daniel Veillard260a68f1998-08-13 03:39:55 +000017#include <string.h> /* for memset() only ! */
18
Daniel Veillard7f7d1111999-09-22 09:46:25 +000019#ifdef HAVE_CTYPE_H
20#include <ctype.h>
21#endif
22#ifdef HAVE_STDLIB_H
23#include <stdlib.h>
24#endif
Daniel Veillard151b1b01998-09-23 00:49:46 +000025#ifdef HAVE_ZLIB_H
26#include <zlib.h>
27#endif
28
Daniel Veillard6454aec1999-09-02 22:04:43 +000029#include "xmlmemory.h"
Daniel Veillard260a68f1998-08-13 03:39:55 +000030#include "tree.h"
31#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 Veillardb96e6431999-08-29 21:02:19 +00001580 * xmlAddSibling:
1581 * @cur: the child node
1582 * @elem: the new node
1583 *
1584 * Add a new element to the list of siblings of @cur
1585 * Returns the element or NULL in case of error.
1586 */
1587xmlNodePtr
1588xmlAddSibling(xmlNodePtr cur, xmlNodePtr elem) {
1589 xmlNodePtr parent;
1590
1591 if (cur == NULL) {
1592 fprintf(stderr, "xmlAddSibling : cur == NULL\n");
1593 return(NULL);
1594 }
1595
1596 if (elem == NULL) {
1597 fprintf(stderr, "xmlAddSibling : elem == NULL\n");
1598 return(NULL);
1599 }
1600
1601 if ((cur->doc != NULL) && (elem->doc != NULL) &&
1602 (cur->doc != elem->doc)) {
1603 fprintf(stderr,
1604 "xmlAddSibling: Elements moved to a different document\n");
1605 }
1606
1607 while (cur->next != NULL) cur = cur->next;
1608
1609 if (elem->doc == NULL)
1610 elem->doc = cur->doc; /* the parent may not be linked to a doc ! */
1611
1612 parent = cur->parent;
1613 elem->prev = cur;
1614 elem->next = NULL;
1615 elem->parent = parent;
1616 cur->next = elem;
1617 if (parent != NULL)
1618 parent->last = elem;
1619
1620 return(elem);
1621}
1622
1623/**
Daniel Veillard97b58771998-10-20 06:14:16 +00001624 * xmlAddChild:
1625 * @parent: the parent node
1626 * @cur: the child node
1627 *
1628 * Add a new child element, to @parent, at the end of the child list.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001629 * Returns the child or NULL in case of error.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001630 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001631xmlNodePtr
1632xmlAddChild(xmlNodePtr parent, xmlNodePtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001633 xmlNodePtr prev;
1634
1635 if (parent == NULL) {
Daniel Veillard10a2c651999-12-12 13:03:50 +00001636 fprintf(stderr, "xmlAddChild : parent == NULL\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00001637 return(NULL);
1638 }
1639
1640 if (cur == NULL) {
Daniel Veillard10a2c651999-12-12 13:03:50 +00001641 fprintf(stderr, "xmlAddChild : child == NULL\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00001642 return(NULL);
1643 }
1644
Daniel Veillard0bef1311998-10-14 02:36:47 +00001645 if ((cur->doc != NULL) && (parent->doc != NULL) &&
1646 (cur->doc != parent->doc)) {
1647 fprintf(stderr, "Elements moved to a different document\n");
1648 }
1649
Daniel Veillard260a68f1998-08-13 03:39:55 +00001650 /*
1651 * add the new element at the end of the childs list.
1652 */
1653 cur->parent = parent;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001654 cur->doc = parent->doc; /* the parent may not be linked to a doc ! */
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001655
Daniel Veillardccb09631998-10-27 06:21:04 +00001656 /*
1657 * Handle the case where parent->content != NULL, in that case it will
1658 * create a intermediate TEXT node.
1659 */
1660 if (parent->content != NULL) {
1661 xmlNodePtr text;
1662
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001663#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardccb09631998-10-27 06:21:04 +00001664 text = xmlNewDocText(parent->doc, parent->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001665#else
1666 text = xmlNewDocText(parent->doc, xmlBufferContent(parent->content));
1667#endif
Daniel Veillardccb09631998-10-27 06:21:04 +00001668 if (text != NULL) {
1669 text->next = parent->childs;
1670 if (text->next != NULL)
1671 text->next->prev = text;
1672 parent->childs = text;
Daniel Veillard1e346af1999-02-22 10:33:01 +00001673 UPDATE_LAST_CHILD(parent)
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001674#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard6454aec1999-09-02 22:04:43 +00001675 xmlFree(parent->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001676#else
1677 xmlBufferFree(parent->content);
1678#endif
Daniel Veillardccb09631998-10-27 06:21:04 +00001679 parent->content = NULL;
1680 }
1681 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00001682 if (parent->childs == NULL) {
1683 parent->childs = cur;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001684 parent->last = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001685 } else {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001686 prev = parent->last;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001687 prev->next = cur;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001688 cur->prev = prev;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001689 parent->last = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001690 }
1691
1692 return(cur);
1693}
1694
Daniel Veillard97b58771998-10-20 06:14:16 +00001695/**
1696 * xmlGetLastChild:
1697 * @parent: the parent node
1698 *
1699 * Search the last child of a node.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001700 * Returns the last child or NULL if none.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001701 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001702xmlNodePtr
1703xmlGetLastChild(xmlNodePtr parent) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001704 if (parent == NULL) {
1705 fprintf(stderr, "xmlGetLastChild : parent == NULL\n");
1706 return(NULL);
1707 }
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001708 return(parent->last);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001709}
1710
Daniel Veillard97b58771998-10-20 06:14:16 +00001711/**
1712 * xmlFreeNodeList:
1713 * @cur: the first node in the list
1714 *
1715 * Free a node and all its siblings, this is a recursive behaviour, all
1716 * the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001717 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001718void
1719xmlFreeNodeList(xmlNodePtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001720 xmlNodePtr next;
1721 if (cur == NULL) {
1722 fprintf(stderr, "xmlFreeNodeList : node == NULL\n");
1723 return;
1724 }
1725 while (cur != NULL) {
1726 next = cur->next;
1727 xmlFreeNode(cur);
1728 cur = next;
1729 }
1730}
1731
Daniel Veillard97b58771998-10-20 06:14:16 +00001732/**
1733 * xmlFreeNode:
1734 * @cur: the node
1735 *
1736 * Free a node, this is a recursive behaviour, all the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001737 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001738void
1739xmlFreeNode(xmlNodePtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001740 if (cur == NULL) {
1741 fprintf(stderr, "xmlFreeNode : node == NULL\n");
1742 return;
1743 }
Daniel Veillardccb09631998-10-27 06:21:04 +00001744 cur->doc = NULL;
1745 cur->parent = NULL;
1746 cur->next = NULL;
1747 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001748 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillardccb09631998-10-27 06:21:04 +00001749 if (cur->properties != NULL) xmlFreePropList(cur->properties);
1750 if (cur->type != XML_ENTITY_REF_NODE)
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001751#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard6454aec1999-09-02 22:04:43 +00001752 if (cur->content != NULL) xmlFree(cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001753#else
1754 if (cur->content != NULL) xmlBufferFree(cur->content);
1755#endif
Daniel Veillard6454aec1999-09-02 22:04:43 +00001756 if (cur->name != NULL) xmlFree((char *) cur->name);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001757 if (cur->nsDef != NULL) xmlFreeNsList(cur->nsDef);
1758 memset(cur, -1, sizeof(xmlNode));
Daniel Veillard6454aec1999-09-02 22:04:43 +00001759 xmlFree(cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001760}
1761
Daniel Veillard16253641998-10-28 22:58:05 +00001762/**
1763 * xmlUnlinkNode:
1764 * @cur: the node
1765 *
1766 * Unlink a node from it's current context, the node is not freed
1767 */
1768void
1769xmlUnlinkNode(xmlNodePtr cur) {
1770 if (cur == NULL) {
1771 fprintf(stderr, "xmlUnlinkNode : node == NULL\n");
1772 return;
1773 }
1774 if ((cur->parent != NULL) && (cur->parent->childs == cur))
1775 cur->parent->childs = cur->next;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001776 if ((cur->parent != NULL) && (cur->parent->last == cur))
1777 cur->parent->last = cur->prev;
Daniel Veillard16253641998-10-28 22:58:05 +00001778 if (cur->next != NULL)
1779 cur->next->prev = cur->prev;
1780 if (cur->prev != NULL)
1781 cur->prev->next = cur->next;
1782 cur->next = cur->prev = NULL;
1783 cur->parent = NULL;
1784}
1785
Daniel Veillard260a68f1998-08-13 03:39:55 +00001786/************************************************************************
1787 * *
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001788 * Copy operations *
1789 * *
1790 ************************************************************************/
1791
1792/**
1793 * xmlCopyNamespace:
1794 * @cur: the namespace
1795 *
1796 * Do a copy of the namespace.
1797 *
1798 * Returns: a new xmlNsPtr, or NULL in case of error.
1799 */
1800xmlNsPtr
1801xmlCopyNamespace(xmlNsPtr cur) {
1802 xmlNsPtr ret;
1803
1804 if (cur == NULL) return(NULL);
1805 switch (cur->type) {
1806 case XML_GLOBAL_NAMESPACE:
1807 ret = xmlNewGlobalNs(NULL, cur->href, cur->prefix);
1808 break;
1809 case XML_LOCAL_NAMESPACE:
1810 ret = xmlNewNs(NULL, cur->href, cur->prefix);
1811 break;
1812 default:
1813 fprintf(stderr, "xmlCopyNamespace: unknown type %d\n", cur->type);
1814 return(NULL);
1815 }
1816 return(ret);
1817}
1818
1819/**
1820 * xmlCopyNamespaceList:
1821 * @cur: the first namespace
1822 *
1823 * Do a copy of an namespace list.
1824 *
1825 * Returns: a new xmlNsPtr, or NULL in case of error.
1826 */
1827xmlNsPtr
1828xmlCopyNamespaceList(xmlNsPtr cur) {
1829 xmlNsPtr ret = NULL;
1830 xmlNsPtr p = NULL,q;
1831
1832 while (cur != NULL) {
1833 q = xmlCopyNamespace(cur);
1834 if (p == NULL) {
1835 ret = p = q;
1836 } else {
1837 p->next = q;
1838 p = q;
1839 }
1840 cur = cur->next;
1841 }
1842 return(ret);
1843}
1844
1845/**
1846 * xmlCopyProp:
Daniel Veillardb96e6431999-08-29 21:02:19 +00001847 * @target: the element where the attribute will be grafted
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001848 * @cur: the attribute
1849 *
1850 * Do a copy of the attribute.
1851 *
1852 * Returns: a new xmlAttrPtr, or NULL in case of error.
1853 */
1854xmlAttrPtr
Daniel Veillardb96e6431999-08-29 21:02:19 +00001855xmlCopyProp(xmlNodePtr target, xmlAttrPtr cur) {
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001856 xmlAttrPtr ret;
1857
1858 if (cur == NULL) return(NULL);
1859 if (cur->val != NULL)
1860 ret = xmlNewDocProp(cur->val->doc, cur->name, NULL);
1861 else
1862 ret = xmlNewDocProp(NULL, cur->name, NULL);
1863 if (ret == NULL) return(NULL);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001864
1865 if ((cur->ns != NULL) && (target != NULL)) {
1866 xmlNsPtr ns;
1867
1868 ns = xmlSearchNs(target->doc, target, cur->ns->prefix);
1869 ret->ns = ns;
1870 } else
1871 ret->ns = NULL;
1872
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001873 if (cur->val != NULL)
1874 ret->val = xmlCopyNodeList(cur->val);
1875 return(ret);
1876}
1877
1878/**
1879 * xmlCopyPropList:
Daniel Veillardb96e6431999-08-29 21:02:19 +00001880 * @target: the element where the attributes will be grafted
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001881 * @cur: the first attribute
1882 *
1883 * Do a copy of an attribute list.
1884 *
1885 * Returns: a new xmlAttrPtr, or NULL in case of error.
1886 */
1887xmlAttrPtr
Daniel Veillardb96e6431999-08-29 21:02:19 +00001888xmlCopyPropList(xmlNodePtr target, xmlAttrPtr cur) {
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001889 xmlAttrPtr ret = NULL;
1890 xmlAttrPtr p = NULL,q;
1891
1892 while (cur != NULL) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00001893 q = xmlCopyProp(target, cur);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001894 if (p == NULL) {
1895 ret = p = q;
1896 } else {
1897 p->next = q;
1898 p = q;
1899 }
1900 cur = cur->next;
1901 }
1902 return(ret);
1903}
1904
1905/*
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001906 * NOTE abeut the CopyNode operations !
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001907 *
1908 * They are splitted into external and internal parts for one
1909 * tricky reason: namespaces. Doing a direct copy of a node
1910 * say RPM:Copyright without changing the namespace pointer to
1911 * something else can produce stale links. One way to do it is
1912 * to keep a reference counter but this doesn't work as soon
1913 * as one move the element or the subtree out of the scope of
1914 * the existing namespace. The actual solution seems to add
1915 * a copy of the namespace at the top of the copied tree if
1916 * not available in the subtree.
1917 * Hence two functions, the public front-end call the inner ones
1918 */
1919
1920static xmlNodePtr
1921xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent);
1922
1923static xmlNodePtr
1924xmlStaticCopyNode(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent,
1925 int recursive) {
1926 xmlNodePtr ret;
1927
1928 if (node == NULL) return(NULL);
1929 /*
1930 * Allocate a new node and fill the fields.
1931 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001932 ret = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001933 if (ret == NULL) {
1934 fprintf(stderr, "xmlStaticCopyNode : malloc failed\n");
1935 return(NULL);
1936 }
1937
1938 ret->type = node->type;
1939 ret->doc = doc;
1940 ret->parent = parent;
1941 ret->next = NULL;
1942 ret->prev = NULL;
1943 ret->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001944 ret->last = NULL;
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001945 ret->properties = NULL;
1946 if (node->name != NULL)
1947 ret->name = xmlStrdup(node->name);
1948 else
1949 ret->name = NULL;
1950 ret->ns = NULL;
1951 ret->nsDef = NULL;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001952 if ((node->content != NULL) && (node->type != XML_ENTITY_REF_NODE)) {
1953#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001954 ret->content = xmlStrdup(node->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001955#else
1956 ret->content = xmlBufferCreateSize(xmlBufferLength(node->content));
1957 xmlBufferSetAllocationScheme(ret->content,
1958 xmlGetBufferAllocationScheme());
1959 xmlBufferAdd(ret->content,
1960 xmlBufferContent(node->content),
1961 xmlBufferLength(node->content));
1962#endif
1963 } else
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001964 ret->content = NULL;
Daniel Veillard27d88741999-05-29 11:51:49 +00001965#ifndef XML_WITHOUT_CORBA
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001966 ret->_private = NULL;
1967 ret->vepv = NULL;
1968#endif
1969 if (parent != NULL)
1970 xmlAddChild(parent, ret);
1971
1972 if (!recursive) return(ret);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001973 if (node->nsDef != NULL)
1974 ret->nsDef = xmlCopyNamespaceList(node->nsDef);
1975
1976 if (node->ns != NULL) {
1977 xmlNsPtr ns;
1978
1979 ns = xmlSearchNs(doc, ret, node->ns->prefix);
1980 if (ns == NULL) {
1981 /*
1982 * Humm, we are copying an element whose namespace is defined
1983 * out of the new tree scope. Search it in the original tree
1984 * and add it at the top of the new tree
1985 */
1986 ns = xmlSearchNs(node->doc, node, node->ns->prefix);
1987 if (ns != NULL) {
1988 xmlNodePtr root = ret;
1989
1990 while (root->parent != NULL) root = root->parent;
1991 xmlNewNs(root, ns->href, ns->prefix);
1992 }
1993 } else {
1994 /*
1995 * reference the existing namespace definition in our own tree.
1996 */
1997 ret->ns = ns;
1998 }
1999 }
Daniel Veillardb96e6431999-08-29 21:02:19 +00002000 if (node->properties != NULL)
2001 ret->properties = xmlCopyPropList(ret, node->properties);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002002 if (node->childs != NULL)
2003 ret->childs = xmlStaticCopyNodeList(node->childs, doc, ret);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002004 UPDATE_LAST_CHILD(ret)
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002005 return(ret);
2006}
2007
2008static xmlNodePtr
2009xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent) {
2010 xmlNodePtr ret = NULL;
2011 xmlNodePtr p = NULL,q;
2012
2013 while (node != NULL) {
2014 q = xmlStaticCopyNode(node, doc, parent, 1);
2015 if (parent == NULL) {
2016 if (ret == NULL) ret = q;
2017 } else {
2018 if (ret == NULL) {
2019 q->prev = NULL;
2020 ret = p = q;
2021 } else {
2022 p->next = q;
2023 q->prev = p;
2024 p = q;
2025 }
2026 }
2027 node = node->next;
2028 }
2029 return(ret);
2030}
2031
2032/**
2033 * xmlCopyNode:
2034 * @node: the node
2035 * @recursive: if 1 do a recursive copy.
2036 *
2037 * Do a copy of the node.
2038 *
2039 * Returns: a new xmlNodePtr, or NULL in case of error.
2040 */
2041xmlNodePtr
2042xmlCopyNode(xmlNodePtr node, int recursive) {
2043 xmlNodePtr ret;
2044
2045 ret = xmlStaticCopyNode(node, NULL, NULL, recursive);
2046 return(ret);
2047}
2048
2049/**
2050 * xmlCopyNodeList:
2051 * @node: the first node in the list.
2052 *
2053 * Do a recursive copy of the node list.
2054 *
2055 * Returns: a new xmlNodePtr, or NULL in case of error.
2056 */
2057xmlNodePtr xmlCopyNodeList(xmlNodePtr node) {
2058 xmlNodePtr ret = xmlStaticCopyNodeList(node, NULL, NULL);
2059 return(ret);
2060}
2061
2062/**
2063 * xmlCopyElement:
2064 * @elem: the element
2065 *
2066 * Do a copy of the element definition.
2067 *
2068 * Returns: a new xmlElementPtr, or NULL in case of error.
2069xmlElementPtr
2070xmlCopyElement(xmlElementPtr elem) {
2071 xmlElementPtr ret;
2072
2073 if (elem == NULL) return(NULL);
2074 ret = xmlNewDocElement(elem->doc, elem->ns, elem->name, elem->content);
2075 if (ret == NULL) return(NULL);
2076 if (!recursive) return(ret);
2077 if (elem->properties != NULL)
2078 ret->properties = xmlCopyPropList(elem->properties);
2079
2080 if (elem->nsDef != NULL)
2081 ret->nsDef = xmlCopyNamespaceList(elem->nsDef);
2082 if (elem->childs != NULL)
2083 ret->childs = xmlCopyElementList(elem->childs);
2084 return(ret);
2085}
2086 */
2087
2088/**
2089 * xmlCopyDtd:
2090 * @dtd: the dtd
2091 *
2092 * Do a copy of the dtd.
2093 *
2094 * Returns: a new xmlDtdPtr, or NULL in case of error.
2095 */
2096xmlDtdPtr
2097xmlCopyDtd(xmlDtdPtr dtd) {
2098 xmlDtdPtr ret;
2099
2100 if (dtd == NULL) return(NULL);
2101 ret = xmlNewDtd(NULL, dtd->name, dtd->ExternalID, dtd->SystemID);
2102 if (ret == NULL) return(NULL);
2103 if (dtd->entities != NULL)
2104 ret->entities = (void *) xmlCopyEntitiesTable(
2105 (xmlEntitiesTablePtr) dtd->entities);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002106 if (dtd->notations != NULL)
2107 ret->notations = (void *) xmlCopyNotationTable(
2108 (xmlNotationTablePtr) dtd->notations);
2109 if (dtd->elements != NULL)
2110 ret->elements = (void *) xmlCopyElementTable(
2111 (xmlElementTablePtr) dtd->elements);
2112 if (dtd->attributes != NULL)
2113 ret->attributes = (void *) xmlCopyAttributeTable(
2114 (xmlAttributeTablePtr) dtd->attributes);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002115 return(ret);
2116}
2117
2118/**
2119 * xmlCopyDoc:
2120 * @doc: the document
2121 * @recursive: if 1 do a recursive copy.
2122 *
2123 * Do a copy of the document info. If recursive, the content tree will
2124 * be copied too as well as Dtd, namespaces and entities.
2125 *
2126 * Returns: a new xmlDocPtr, or NULL in case of error.
2127 */
2128xmlDocPtr
2129xmlCopyDoc(xmlDocPtr doc, int recursive) {
2130 xmlDocPtr ret;
2131
2132 if (doc == NULL) return(NULL);
2133 ret = xmlNewDoc(doc->version);
2134 if (ret == NULL) return(NULL);
2135 if (doc->name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +00002136 ret->name = xmlMemStrdup(doc->name);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002137 if (doc->encoding != NULL)
2138 ret->encoding = xmlStrdup(doc->encoding);
2139 ret->compression = doc->compression;
2140 ret->standalone = doc->standalone;
2141 if (!recursive) return(ret);
2142
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002143 if (doc->intSubset != NULL)
2144 ret->intSubset = xmlCopyDtd(doc->intSubset);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002145 if (doc->oldNs != NULL)
2146 ret->oldNs = xmlCopyNamespaceList(doc->oldNs);
2147 if (doc->root != NULL)
2148 ret->root = xmlStaticCopyNodeList(doc->root, ret, NULL);
2149 return(ret);
2150}
2151
2152/************************************************************************
2153 * *
Daniel Veillard260a68f1998-08-13 03:39:55 +00002154 * Content access functions *
2155 * *
2156 ************************************************************************/
2157
Daniel Veillard97b58771998-10-20 06:14:16 +00002158/**
Daniel Veillard944b5ff1999-12-15 19:08:24 +00002159 * xmlDocGetRootElement:
2160 * @doc: the document
2161 *
2162 * Get the root element of the document (doc->root is a list
2163 * containing possibly comments, PIs, etc ...).
2164 *
2165 * Returns the xmlNodePtr for the root or NULL
2166 */
2167xmlNodePtr
2168xmlDocGetRootElement(xmlDocPtr doc) {
2169 xmlNodePtr ret;
2170
2171 if (doc == NULL) return(NULL);
2172 ret = doc->root;
2173 while (ret != NULL) {
2174 if (ret->type == XML_ELEMENT_NODE)
2175 return(ret);
2176 ret = ret->next;
2177 }
2178 return(ret);
2179}
2180
2181/**
Daniel Veillardb96e6431999-08-29 21:02:19 +00002182 * xmlNodeSetLang:
2183 * @cur: the node being changed
2184 * @lang: the langage description
2185 *
2186 * Searches the language of a node, i.e. the values of the xml:lang
2187 * attribute or the one carried by the nearest ancestor.
Daniel Veillardb96e6431999-08-29 21:02:19 +00002188 */
2189void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002190xmlNodeSetLang(xmlNodePtr cur, const xmlChar *lang) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00002191 /* TODO xmlNodeSetLang check against the production [33] LanguageID */
2192 xmlSetProp(cur, BAD_CAST "xml:lang", lang);
2193}
2194
2195/**
2196 * xmlNodeGetLang:
2197 * @cur: the node being checked
2198 *
2199 * Searches the language of a node, i.e. the values of the xml:lang
2200 * attribute or the one carried by the nearest ancestor.
2201 *
2202 * Returns a pointer to the lang value, or NULL if not found
Daniel Veillarda819dac1999-11-24 18:04:22 +00002203 * It's up to the caller to free the memory.
Daniel Veillardb96e6431999-08-29 21:02:19 +00002204 */
Daniel Veillarda819dac1999-11-24 18:04:22 +00002205xmlChar *
Daniel Veillardb96e6431999-08-29 21:02:19 +00002206xmlNodeGetLang(xmlNodePtr cur) {
Daniel Veillarda819dac1999-11-24 18:04:22 +00002207 xmlChar *lang;
Daniel Veillardb96e6431999-08-29 21:02:19 +00002208
2209 while (cur != NULL) {
2210 lang = xmlGetProp(cur, BAD_CAST "xml:lang");
2211 if (lang != NULL)
2212 return(lang);
2213 cur = cur->parent;
2214 }
2215 return(NULL);
2216}
2217
2218/**
Daniel Veillard10a2c651999-12-12 13:03:50 +00002219 * xmlNodeGetBase:
2220 * @doc: the document the node pertains to
2221 * @cur: the node being checked
2222 *
2223 * Searches for the BASE URL. The code should work on both XML
2224 * and HTML document even if base mechanisms are completely different.
2225 *
2226 * Returns a pointer to the base URL, or NULL if not found
2227 * It's up to the caller to free the memory.
2228 */
2229xmlChar *
2230xmlNodeGetBase(xmlDocPtr doc, xmlNodePtr cur) {
2231 xmlChar *base;
2232
2233 if ((cur == NULL) && (doc == NULL))
2234 return(NULL);
2235 if (doc == NULL) doc = cur->doc;
2236 if ((doc != NULL) && (doc->type == XML_HTML_DOCUMENT_NODE)) {
2237 cur = doc->root;
2238 while ((cur != NULL) && (cur->name != NULL)) {
2239 if (cur->type != XML_ELEMENT_NODE) {
2240 cur = cur->next;
2241 continue;
2242 }
2243 if ((!xmlStrcmp(cur->name, BAD_CAST "html")) ||
2244 (!xmlStrcmp(cur->name, BAD_CAST "HTML"))) {
2245 cur = cur->childs;
2246 continue;
2247 }
2248 if ((!xmlStrcmp(cur->name, BAD_CAST "head")) ||
2249 (!xmlStrcmp(cur->name, BAD_CAST "HEAD"))) {
2250 cur = cur->childs;
2251 continue;
2252 }
2253 if ((!xmlStrcmp(cur->name, BAD_CAST "base")) ||
2254 (!xmlStrcmp(cur->name, BAD_CAST "BASE"))) {
2255 base = xmlGetProp(cur, BAD_CAST "href");
2256 if (base != NULL) return(base);
2257 return(xmlGetProp(cur, BAD_CAST "HREF"));
2258 }
2259 }
2260 return(NULL);
2261 }
2262 while (cur != NULL) {
2263 base = xmlGetProp(cur, BAD_CAST "xml:base");
2264 if (base != NULL)
2265 return(base);
2266 cur = cur->parent;
2267 }
2268 return(NULL);
2269}
2270
2271/**
Daniel Veillard16253641998-10-28 22:58:05 +00002272 * xmlNodeGetContent:
2273 * @cur: the node being read
2274 *
2275 * Read the value of a node, this can be either the text carried
2276 * directly by this node if it's a TEXT node or the aggregate string
2277 * of the values carried by this node child's (TEXT and ENTITY_REF).
2278 * Entity references are substitued.
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002279 * Returns a new xmlChar * or NULL if no content is available.
Daniel Veillard5099ae81999-04-21 20:12:07 +00002280 * It's up to the caller to free the memory.
Daniel Veillard16253641998-10-28 22:58:05 +00002281 */
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002282xmlChar *
Daniel Veillard16253641998-10-28 22:58:05 +00002283xmlNodeGetContent(xmlNodePtr cur) {
2284 if (cur == NULL) return(NULL);
2285 switch (cur->type) {
2286 case XML_DOCUMENT_FRAG_NODE:
2287 case XML_ELEMENT_NODE:
2288 return(xmlNodeListGetString(cur->doc, cur->childs, 1));
2289 break;
Daniel Veillardb96e6431999-08-29 21:02:19 +00002290 case XML_ATTRIBUTE_NODE: {
2291 xmlAttrPtr attr = (xmlAttrPtr) cur;
2292 if (attr->node != NULL)
2293 return(xmlNodeListGetString(attr->node->doc, attr->val, 1));
2294 else
2295 return(xmlNodeListGetString(NULL, attr->val, 1));
2296 break;
2297 }
2298 case XML_PI_NODE:
2299 if (cur->content != NULL)
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002300#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardb96e6431999-08-29 21:02:19 +00002301 return(xmlStrdup(cur->content));
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002302#else
2303 return(xmlStrdup(xmlBufferContent(cur->content)));
2304#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +00002305 return(NULL);
Daniel Veillard16253641998-10-28 22:58:05 +00002306 case XML_ENTITY_REF_NODE:
2307 case XML_ENTITY_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002308 case XML_COMMENT_NODE:
2309 case XML_DOCUMENT_NODE:
Daniel Veillard7c1206f1999-10-14 09:10:25 +00002310 case XML_HTML_DOCUMENT_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002311 case XML_DOCUMENT_TYPE_NODE:
2312 case XML_NOTATION_NODE:
2313 return(NULL);
Daniel Veillardb05deb71999-08-10 19:04:08 +00002314 case XML_CDATA_SECTION_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002315 case XML_TEXT_NODE:
2316 if (cur->content != NULL)
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002317#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard16253641998-10-28 22:58:05 +00002318 return(xmlStrdup(cur->content));
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002319#else
2320 return(xmlStrdup(xmlBufferContent(cur->content)));
2321#endif
Daniel Veillard16253641998-10-28 22:58:05 +00002322 return(NULL);
2323 }
2324 return(NULL);
2325}
2326
2327/**
Daniel Veillard97b58771998-10-20 06:14:16 +00002328 * xmlNodeSetContent:
2329 * @cur: the node being modified
2330 * @content: the new value of the content
2331 *
2332 * Replace the content of a node.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002333 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002334void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002335xmlNodeSetContent(xmlNodePtr cur, const xmlChar *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002336 if (cur == NULL) {
2337 fprintf(stderr, "xmlNodeSetContent : node == NULL\n");
2338 return;
2339 }
Daniel Veillard16253641998-10-28 22:58:05 +00002340 switch (cur->type) {
2341 case XML_DOCUMENT_FRAG_NODE:
2342 case XML_ELEMENT_NODE:
2343 if (cur->content != NULL) {
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002344#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard6454aec1999-09-02 22:04:43 +00002345 xmlFree(cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002346#else
2347 xmlBufferFree(cur->content);
2348#endif
Daniel Veillard16253641998-10-28 22:58:05 +00002349 cur->content = NULL;
2350 }
Daniel Veillard6454aec1999-09-02 22:04:43 +00002351 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillard16253641998-10-28 22:58:05 +00002352 cur->childs = xmlStringGetNodeList(cur->doc, content);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002353 UPDATE_LAST_CHILD(cur)
Daniel Veillard16253641998-10-28 22:58:05 +00002354 break;
2355 case XML_ATTRIBUTE_NODE:
2356 break;
2357 case XML_TEXT_NODE:
2358 case XML_CDATA_SECTION_NODE:
2359 case XML_ENTITY_REF_NODE:
2360 case XML_ENTITY_NODE:
2361 case XML_PI_NODE:
2362 case XML_COMMENT_NODE:
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002363 if (cur->content != NULL) {
2364#ifndef XML_USE_BUFFER_CONTENT
2365 xmlFree(cur->content);
2366#else
2367 xmlBufferFree(cur->content);
2368#endif
2369 }
Daniel Veillard6454aec1999-09-02 22:04:43 +00002370 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002371 cur->last = cur->childs = NULL;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002372 if (content != NULL) {
2373#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard16253641998-10-28 22:58:05 +00002374 cur->content = xmlStrdup(content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002375#else
2376 cur->content = xmlBufferCreateSize(0);
2377 xmlBufferSetAllocationScheme(cur->content,
2378 xmlGetBufferAllocationScheme());
2379 xmlBufferAdd(cur->content, content, -1);
2380#endif
2381 } else
Daniel Veillard16253641998-10-28 22:58:05 +00002382 cur->content = NULL;
Daniel Veillardb96e6431999-08-29 21:02:19 +00002383 break;
Daniel Veillard16253641998-10-28 22:58:05 +00002384 case XML_DOCUMENT_NODE:
Daniel Veillard7c1206f1999-10-14 09:10:25 +00002385 case XML_HTML_DOCUMENT_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002386 case XML_DOCUMENT_TYPE_NODE:
2387 break;
2388 case XML_NOTATION_NODE:
2389 break;
2390 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002391}
2392
Daniel Veillard97b58771998-10-20 06:14:16 +00002393/**
2394 * xmlNodeSetContentLen:
2395 * @cur: the node being modified
2396 * @content: the new value of the content
2397 * @len: the size of @content
2398 *
2399 * Replace the content of a node.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002400 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002401void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002402xmlNodeSetContentLen(xmlNodePtr cur, const xmlChar *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002403 if (cur == NULL) {
Daniel Veillard16253641998-10-28 22:58:05 +00002404 fprintf(stderr, "xmlNodeSetContentLen : node == NULL\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002405 return;
2406 }
Daniel Veillard16253641998-10-28 22:58:05 +00002407 switch (cur->type) {
2408 case XML_DOCUMENT_FRAG_NODE:
2409 case XML_ELEMENT_NODE:
2410 if (cur->content != NULL) {
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002411#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard6454aec1999-09-02 22:04:43 +00002412 xmlFree(cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002413#else
2414 xmlBufferFree(cur->content);
2415#endif
Daniel Veillard16253641998-10-28 22:58:05 +00002416 cur->content = NULL;
2417 }
Daniel Veillard6454aec1999-09-02 22:04:43 +00002418 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillard16253641998-10-28 22:58:05 +00002419 cur->childs = xmlStringLenGetNodeList(cur->doc, content, len);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002420 UPDATE_LAST_CHILD(cur)
Daniel Veillard16253641998-10-28 22:58:05 +00002421 break;
2422 case XML_ATTRIBUTE_NODE:
2423 break;
2424 case XML_TEXT_NODE:
2425 case XML_CDATA_SECTION_NODE:
2426 case XML_ENTITY_REF_NODE:
2427 case XML_ENTITY_NODE:
2428 case XML_PI_NODE:
2429 case XML_COMMENT_NODE:
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002430 case XML_NOTATION_NODE:
2431 if (cur->content != NULL) {
2432#ifndef XML_USE_BUFFER_CONTENT
2433 xmlFree(cur->content);
2434#else
2435 xmlBufferFree(cur->content);
2436#endif
2437 }
Daniel Veillard6454aec1999-09-02 22:04:43 +00002438 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002439 cur->childs = cur->last = NULL;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002440 if (content != NULL) {
2441#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard16253641998-10-28 22:58:05 +00002442 cur->content = xmlStrndup(content, len);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002443#else
2444 cur->content = xmlBufferCreateSize(len);
2445 xmlBufferSetAllocationScheme(cur->content,
2446 xmlGetBufferAllocationScheme());
2447 xmlBufferAdd(cur->content, content, len);
2448#endif
2449 } else
Daniel Veillard16253641998-10-28 22:58:05 +00002450 cur->content = NULL;
Daniel Veillardb96e6431999-08-29 21:02:19 +00002451 break;
Daniel Veillard16253641998-10-28 22:58:05 +00002452 case XML_DOCUMENT_NODE:
Daniel Veillard7c1206f1999-10-14 09:10:25 +00002453 case XML_HTML_DOCUMENT_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002454 case XML_DOCUMENT_TYPE_NODE:
2455 break;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002456 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002457}
2458
Daniel Veillard97b58771998-10-20 06:14:16 +00002459/**
2460 * xmlNodeAddContentLen:
2461 * @cur: the node being modified
2462 * @content: extra content
2463 * @len: the size of @content
2464 *
2465 * Append the extra substring to the node content.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002466 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002467void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002468xmlNodeAddContentLen(xmlNodePtr cur, const xmlChar *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002469 if (cur == NULL) {
Daniel Veillard16253641998-10-28 22:58:05 +00002470 fprintf(stderr, "xmlNodeAddContentLen : node == NULL\n");
2471 return;
2472 }
2473 if (len <= 0) return;
2474 switch (cur->type) {
2475 case XML_DOCUMENT_FRAG_NODE:
2476 case XML_ELEMENT_NODE: {
2477 xmlNodePtr last = NULL, new;
2478
2479 if (cur->childs != NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002480 last = cur->last;
Daniel Veillard16253641998-10-28 22:58:05 +00002481 } else {
2482 if (cur->content != NULL) {
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002483#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard16253641998-10-28 22:58:05 +00002484 cur->childs = xmlStringGetNodeList(cur->doc, cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002485#else
2486 cur->childs = xmlStringGetNodeList(cur->doc,
2487 xmlBufferContent(cur->content));
2488#endif
Daniel Veillard1e346af1999-02-22 10:33:01 +00002489 UPDATE_LAST_CHILD(cur)
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002490#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard6454aec1999-09-02 22:04:43 +00002491 xmlFree(cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002492#else
2493 xmlBufferFree(cur->content);
2494#endif
Daniel Veillard16253641998-10-28 22:58:05 +00002495 cur->content = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002496 last = cur->last;
Daniel Veillard16253641998-10-28 22:58:05 +00002497 }
2498 }
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002499 new = xmlNewTextLen(content, len);
Daniel Veillard16253641998-10-28 22:58:05 +00002500 if (new != NULL) {
2501 xmlAddChild(cur, new);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002502 if ((last != NULL) && (last->next == new)) {
Daniel Veillard16253641998-10-28 22:58:05 +00002503 xmlTextMerge(last, new);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002504 }
Daniel Veillard16253641998-10-28 22:58:05 +00002505 }
2506 break;
2507 }
2508 case XML_ATTRIBUTE_NODE:
2509 break;
2510 case XML_TEXT_NODE:
2511 case XML_CDATA_SECTION_NODE:
2512 case XML_ENTITY_REF_NODE:
2513 case XML_ENTITY_NODE:
2514 case XML_PI_NODE:
2515 case XML_COMMENT_NODE:
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002516 case XML_NOTATION_NODE:
2517 if (content != NULL) {
2518#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard16253641998-10-28 22:58:05 +00002519 cur->content = xmlStrncat(cur->content, content, len);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002520#else
2521 xmlBufferAdd(cur->content, content, len);
2522#endif
2523 }
Daniel Veillard16253641998-10-28 22:58:05 +00002524 case XML_DOCUMENT_NODE:
Daniel Veillard7c1206f1999-10-14 09:10:25 +00002525 case XML_HTML_DOCUMENT_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002526 case XML_DOCUMENT_TYPE_NODE:
2527 break;
Daniel Veillard16253641998-10-28 22:58:05 +00002528 }
2529}
2530
2531/**
2532 * xmlNodeAddContent:
2533 * @cur: the node being modified
2534 * @content: extra content
2535 *
2536 * Append the extra substring to the node content.
2537 */
2538void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002539xmlNodeAddContent(xmlNodePtr cur, const xmlChar *content) {
Daniel Veillard16253641998-10-28 22:58:05 +00002540 int len;
2541
2542 if (cur == NULL) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002543 fprintf(stderr, "xmlNodeAddContent : node == NULL\n");
2544 return;
2545 }
Daniel Veillard16253641998-10-28 22:58:05 +00002546 if (content == NULL) return;
2547 len = xmlStrlen(content);
2548 xmlNodeAddContentLen(cur, content, len);
2549}
2550
2551/**
2552 * xmlTextMerge:
2553 * @first: the first text node
2554 * @second: the second text node being merged
2555 *
2556 * Merge two text nodes into one
Daniel Veillard1e346af1999-02-22 10:33:01 +00002557 * Returns the first text node augmented
Daniel Veillard16253641998-10-28 22:58:05 +00002558 */
2559xmlNodePtr
2560xmlTextMerge(xmlNodePtr first, xmlNodePtr second) {
2561 if (first == NULL) return(second);
2562 if (second == NULL) return(first);
2563 if (first->type != XML_TEXT_NODE) return(first);
2564 if (second->type != XML_TEXT_NODE) return(first);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002565#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard16253641998-10-28 22:58:05 +00002566 xmlNodeAddContent(first, second->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002567#else
2568 xmlNodeAddContent(first, xmlBufferContent(second->content));
2569#endif
Daniel Veillard16253641998-10-28 22:58:05 +00002570 xmlUnlinkNode(second);
2571 xmlFreeNode(second);
2572 return(first);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002573}
2574
Daniel Veillard97b58771998-10-20 06:14:16 +00002575/**
Daniel Veillardb96e6431999-08-29 21:02:19 +00002576 * xmlGetNsList:
2577 * @doc: the document
2578 * @node: the current node
2579 *
2580 * Search all the namespace applying to a given element.
2581 * Returns an NULL terminated array of all the xmlNsPtr found
2582 * that need to be freed by the caller or NULL if no
2583 * namespace if defined
2584 */
2585xmlNsPtr *
2586xmlGetNsList(xmlDocPtr doc, xmlNodePtr node) {
2587 xmlNsPtr cur;
2588 xmlNsPtr *ret = NULL;
2589 int nbns = 0;
2590 int maxns = 10;
2591 int i;
2592
2593 while (node != NULL) {
2594 cur = node->nsDef;
2595 while (cur != NULL) {
2596 if (ret == NULL) {
Daniel Veillard6454aec1999-09-02 22:04:43 +00002597 ret = (xmlNsPtr *) xmlMalloc((maxns + 1) * sizeof(xmlNsPtr));
Daniel Veillardb96e6431999-08-29 21:02:19 +00002598 if (ret == NULL) {
2599 fprintf(stderr, "xmlGetNsList : out of memory!\n");
2600 return(NULL);
2601 }
2602 ret[nbns] = NULL;
2603 }
2604 for (i = 0;i < nbns;i++) {
2605 if ((cur->prefix == ret[i]->prefix) ||
2606 (!xmlStrcmp(cur->prefix, ret[i]->prefix))) break;
2607 }
2608 if (i >= nbns) {
2609 if (nbns >= maxns) {
2610 maxns *= 2;
Daniel Veillard6454aec1999-09-02 22:04:43 +00002611 ret = (xmlNsPtr *) xmlRealloc(ret,
Daniel Veillardb96e6431999-08-29 21:02:19 +00002612 (maxns + 1) * sizeof(xmlNsPtr));
2613 if (ret == NULL) {
2614 fprintf(stderr, "xmlGetNsList : realloc failed!\n");
2615 return(NULL);
2616 }
2617 }
2618 ret[nbns++] = cur;
2619 ret[nbns] = NULL;
2620 }
2621
2622 cur = cur->next;
2623 }
2624 node = node->parent;
2625 }
2626 return(ret);
2627}
2628
2629/**
Daniel Veillard97b58771998-10-20 06:14:16 +00002630 * xmlSearchNs:
2631 * @doc: the document
2632 * @node: the current node
2633 * @nameSpace: the namespace string
Daniel Veillard260a68f1998-08-13 03:39:55 +00002634 *
Daniel Veillard97b58771998-10-20 06:14:16 +00002635 * Search a Ns registered under a given name space for a document.
2636 * recurse on the parents until it finds the defined namespace
2637 * or return NULL otherwise.
2638 * @nameSpace can be NULL, this is a search for the default namespace.
Daniel Veillard1e346af1999-02-22 10:33:01 +00002639 * Returns the namespace pointer or NULL.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002640 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002641xmlNsPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002642xmlSearchNs(xmlDocPtr doc, xmlNodePtr node, const xmlChar *nameSpace) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002643 xmlNsPtr cur;
2644
Daniel Veillard10a2c651999-12-12 13:03:50 +00002645 if ((node == NULL) || (nameSpace == NULL)) return(NULL);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002646 while (node != NULL) {
2647 cur = node->nsDef;
2648 while (cur != NULL) {
2649 if ((cur->prefix == NULL) && (nameSpace == NULL))
2650 return(cur);
2651 if ((cur->prefix != NULL) && (nameSpace != NULL) &&
2652 (!xmlStrcmp(cur->prefix, nameSpace)))
2653 return(cur);
2654 cur = cur->next;
2655 }
2656 node = node->parent;
2657 }
Daniel Veillard10a2c651999-12-12 13:03:50 +00002658#if 0
2659 /* Removed support for old namespaces */
Daniel Veillard260a68f1998-08-13 03:39:55 +00002660 if (doc != NULL) {
2661 cur = doc->oldNs;
2662 while (cur != NULL) {
2663 if ((cur->prefix != NULL) && (nameSpace != NULL) &&
2664 (!xmlStrcmp(cur->prefix, nameSpace)))
2665 return(cur);
2666 cur = cur->next;
2667 }
2668 }
Daniel Veillard10a2c651999-12-12 13:03:50 +00002669#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00002670 return(NULL);
2671}
2672
Daniel Veillard97b58771998-10-20 06:14:16 +00002673/**
2674 * xmlSearchNsByHref:
2675 * @doc: the document
2676 * @node: the current node
2677 * @href: the namespace value
2678 *
2679 * Search a Ns aliasing a given URI. Recurse on the parents until it finds
2680 * the defined namespace or return NULL otherwise.
Daniel Veillard1e346af1999-02-22 10:33:01 +00002681 * Returns the namespace pointer or NULL.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002682 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002683xmlNsPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002684xmlSearchNsByHref(xmlDocPtr doc, xmlNodePtr node, const xmlChar *href) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002685 xmlNsPtr cur;
2686
Daniel Veillard10a2c651999-12-12 13:03:50 +00002687 if ((node == NULL) || (href == NULL)) return(NULL);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002688 while (node != NULL) {
2689 cur = node->nsDef;
2690 while (cur != NULL) {
2691 if ((cur->href != NULL) && (href != NULL) &&
2692 (!xmlStrcmp(cur->href, href)))
2693 return(cur);
2694 cur = cur->next;
2695 }
2696 node = node->parent;
2697 }
Daniel Veillard10a2c651999-12-12 13:03:50 +00002698#if 0
2699 /* Removed support for old namespaces */
Daniel Veillard260a68f1998-08-13 03:39:55 +00002700 if (doc != NULL) {
2701 cur = doc->oldNs;
2702 while (cur != NULL) {
2703 if ((cur->href != NULL) && (href != NULL) &&
2704 (!xmlStrcmp(cur->href, href)))
2705 return(cur);
2706 cur = cur->next;
2707 }
2708 }
Daniel Veillard10a2c651999-12-12 13:03:50 +00002709#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00002710 return(NULL);
2711}
2712
Daniel Veillard97b58771998-10-20 06:14:16 +00002713/**
2714 * xmlGetProp:
2715 * @node: the node
2716 * @name: the attribute name
2717 *
2718 * Search and get the value of an attribute associated to a node
Daniel Veillardccb09631998-10-27 06:21:04 +00002719 * This does the entity substitution.
Daniel Veillard10a2c651999-12-12 13:03:50 +00002720 * This function looks in DTD attribute declaration for #FIXED or
2721 * default declaration values unless DTD use has been turned off.
2722 *
Daniel Veillard1e346af1999-02-22 10:33:01 +00002723 * Returns the attribute value or NULL if not found.
Daniel Veillarda819dac1999-11-24 18:04:22 +00002724 * It's up to the caller to free the memory.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002725 */
Daniel Veillarda819dac1999-11-24 18:04:22 +00002726xmlChar *
2727xmlGetProp(xmlNodePtr node, const xmlChar *name) {
Daniel Veillard10a2c651999-12-12 13:03:50 +00002728 xmlAttrPtr prop;
2729 xmlDocPtr doc;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002730
Daniel Veillard10a2c651999-12-12 13:03:50 +00002731 if ((node == NULL) || (name == NULL)) return(NULL);
2732 /*
2733 * Check on the properties attached to the node
2734 */
2735 prop = node->properties;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002736 while (prop != NULL) {
Daniel Veillard68178931999-02-08 18:34:36 +00002737 if (!xmlStrcmp(prop->name, name)) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002738 xmlChar *ret;
Daniel Veillard6800ef31999-02-08 18:33:22 +00002739
2740 ret = xmlNodeListGetString(node->doc, prop->val, 1);
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002741 if (ret == NULL) return(xmlStrdup((xmlChar *)""));
Daniel Veillard6800ef31999-02-08 18:33:22 +00002742 return(ret);
Daniel Veillard68178931999-02-08 18:34:36 +00002743 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002744 prop = prop->next;
2745 }
Daniel Veillard10a2c651999-12-12 13:03:50 +00002746 if (!xmlCheckDTD) return(NULL);
2747
2748 /*
2749 * Check if there is a default declaration in the internal
2750 * or external subsets
2751 */
2752 doc = node->doc;
2753 if (doc != NULL) {
2754 xmlAttributePtr attrDecl;
2755 if (doc->intSubset != NULL) {
2756 attrDecl = xmlGetDtdAttrDesc(doc->intSubset, node->name, name);
2757 if ((attrDecl == NULL) && (doc->extSubset != NULL))
2758 attrDecl = xmlGetDtdAttrDesc(doc->extSubset, node->name, name);
2759 return(xmlStrdup(attrDecl->defaultValue));
2760 }
2761 }
2762 return(NULL);
2763}
2764
2765/**
2766 * xmlGetNsProp:
2767 * @node: the node
2768 * @name: the attribute name
2769 * @namespace: the URI of the namespace
2770 *
2771 * Search and get the value of an attribute associated to a node
2772 * This attribute has to be anchored in the namespace specified.
2773 * This does the entity substitution.
2774 * This function looks in DTD attribute declaration for #FIXED or
2775 * default declaration values unless DTD use has been turned off.
2776 *
2777 * Returns the attribute value or NULL if not found.
2778 * It's up to the caller to free the memory.
2779 */
2780xmlChar *
2781xmlGetNsProp(xmlNodePtr node, const xmlChar *name, const xmlChar *namespace) {
2782 xmlAttrPtr prop = node->properties;
2783 xmlDocPtr doc;
2784 xmlNsPtr ns;
2785
2786 if (namespace == NULL)
2787 return(xmlGetProp(node, name));
2788 while (prop != NULL) {
2789 if ((!xmlStrcmp(prop->name, name)) &&
2790 (prop->ns != NULL) && (!xmlStrcmp(prop->ns->href, namespace))) {
2791 xmlChar *ret;
2792
2793 ret = xmlNodeListGetString(node->doc, prop->val, 1);
2794 if (ret == NULL) return(xmlStrdup((xmlChar *)""));
2795 return(ret);
2796 }
2797 prop = prop->next;
2798 }
2799 if (!xmlCheckDTD) return(NULL);
2800
2801 /*
2802 * Check if there is a default declaration in the internal
2803 * or external subsets
2804 */
2805 doc = node->doc;
2806 if (doc != NULL) {
2807 xmlAttributePtr attrDecl;
2808 if (doc->intSubset != NULL) {
2809 attrDecl = xmlGetDtdAttrDesc(doc->intSubset, node->name, name);
2810 if ((attrDecl == NULL) && (doc->extSubset != NULL))
2811 attrDecl = xmlGetDtdAttrDesc(doc->extSubset, node->name, name);
2812
2813 if (attrDecl->prefix != NULL) {
2814 /*
2815 * The DTD declaration only allows a prefix search
2816 */
2817 ns = xmlSearchNs(doc, node, attrDecl->prefix);
2818 if ((ns != NULL) && (!xmlStrcmp(ns->href, namespace)))
2819 return(xmlStrdup(attrDecl->defaultValue));
2820 }
2821 }
2822 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002823 return(NULL);
2824}
2825
Daniel Veillard97b58771998-10-20 06:14:16 +00002826/**
Daniel Veillardccb09631998-10-27 06:21:04 +00002827 * xmlSetProp:
Daniel Veillard97b58771998-10-20 06:14:16 +00002828 * @node: the node
2829 * @name: the attribute name
2830 * @value: the attribute value
2831 *
2832 * Set (or reset) an attribute carried by a node.
Daniel Veillard1e346af1999-02-22 10:33:01 +00002833 * Returns the attribute pointer.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002834 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002835xmlAttrPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002836xmlSetProp(xmlNodePtr node, const xmlChar *name, const xmlChar *value) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002837 xmlAttrPtr prop = node->properties;
2838
2839 while (prop != NULL) {
2840 if (!xmlStrcmp(prop->name, name)) {
Daniel Veillardccb09631998-10-27 06:21:04 +00002841 if (prop->val != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +00002842 xmlFreeNodeList(prop->val);
Daniel Veillardccb09631998-10-27 06:21:04 +00002843 prop->val = NULL;
Daniel Veillard51e3b151999-11-12 17:02:31 +00002844 if (value != NULL) {
2845 xmlChar *buffer;
2846 buffer = xmlEncodeEntitiesReentrant(node->doc, value);
2847 prop->val = xmlStringGetNodeList(node->doc, buffer);
2848 xmlFree(buffer);
2849 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002850 return(prop);
2851 }
2852 prop = prop->next;
2853 }
2854 prop = xmlNewProp(node, name, value);
2855 return(prop);
2856}
2857
Daniel Veillard97b58771998-10-20 06:14:16 +00002858/**
2859 * xmlNodeIsText:
2860 * @node: the node
2861 *
2862 * Is this node a Text node ?
Daniel Veillard1e346af1999-02-22 10:33:01 +00002863 * Returns 1 yes, 0 no
Daniel Veillard260a68f1998-08-13 03:39:55 +00002864 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002865int
2866xmlNodeIsText(xmlNodePtr node) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002867 if (node == NULL) return(0);
2868
Daniel Veillard0bef1311998-10-14 02:36:47 +00002869 if (node->type == XML_TEXT_NODE) return(1);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002870 return(0);
2871}
2872
Daniel Veillard97b58771998-10-20 06:14:16 +00002873/**
Daniel Veillard1e346af1999-02-22 10:33:01 +00002874 * xmlTextConcat:
Daniel Veillard97b58771998-10-20 06:14:16 +00002875 * @node: the node
2876 * @content: the content
2877 * @len: @content lenght
2878 *
2879 * Concat the given string at the end of the existing node content
Daniel Veillard260a68f1998-08-13 03:39:55 +00002880 */
Daniel Veillard97b58771998-10-20 06:14:16 +00002881
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002882void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002883xmlTextConcat(xmlNodePtr node, const xmlChar *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002884 if (node == NULL) return;
2885
Daniel Veillard0bef1311998-10-14 02:36:47 +00002886 if (node->type != XML_TEXT_NODE) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002887 fprintf(stderr, "xmlTextConcat: node is not text\n");
2888 return;
2889 }
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002890#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard260a68f1998-08-13 03:39:55 +00002891 node->content = xmlStrncat(node->content, content, len);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002892#else
2893 xmlBufferAdd(node->content, content, len);
2894#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00002895}
2896
2897/************************************************************************
2898 * *
2899 * Output : to a FILE or in memory *
2900 * *
2901 ************************************************************************/
2902
Daniel Veillard5099ae81999-04-21 20:12:07 +00002903#define BASE_BUFFER_SIZE 4000
2904
2905/**
2906 * xmlBufferCreate:
2907 *
2908 * routine to create an XML buffer.
2909 * returns the new structure.
2910 */
2911xmlBufferPtr
2912xmlBufferCreate(void) {
2913 xmlBufferPtr ret;
2914
Daniel Veillard6454aec1999-09-02 22:04:43 +00002915 ret = (xmlBufferPtr) xmlMalloc(sizeof(xmlBuffer));
Daniel Veillard5099ae81999-04-21 20:12:07 +00002916 if (ret == NULL) {
2917 fprintf(stderr, "xmlBufferCreate : out of memory!\n");
2918 return(NULL);
2919 }
2920 ret->use = 0;
2921 ret->size = BASE_BUFFER_SIZE;
Daniel Veillard10a2c651999-12-12 13:03:50 +00002922 ret->alloc = xmlBufferAllocScheme;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002923 ret->content = (xmlChar *) xmlMalloc(ret->size * sizeof(xmlChar));
Daniel Veillard5099ae81999-04-21 20:12:07 +00002924 if (ret->content == NULL) {
2925 fprintf(stderr, "xmlBufferCreate : out of memory!\n");
Daniel Veillard6454aec1999-09-02 22:04:43 +00002926 xmlFree(ret);
Daniel Veillard5099ae81999-04-21 20:12:07 +00002927 return(NULL);
2928 }
2929 ret->content[0] = 0;
2930 return(ret);
2931}
2932
2933/**
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002934 * xmlBufferCreateSize:
2935 * @size: initial size of buffer
2936 *
2937 * routine to create an XML buffer.
2938 * returns the new structure.
2939 */
2940xmlBufferPtr
2941xmlBufferCreateSize(size_t size) {
2942 xmlBufferPtr ret;
2943
2944 ret = (xmlBufferPtr) xmlMalloc(sizeof(xmlBuffer));
2945 if (ret == NULL) {
2946 fprintf(stderr, "xmlBufferCreate : out of memory!\n");
2947 return(NULL);
2948 }
2949 ret->use = 0;
Daniel Veillard10a2c651999-12-12 13:03:50 +00002950 ret->alloc = xmlBufferAllocScheme;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002951 ret->size = (size ? size+2 : 0); /* +1 for ending null */
Daniel Veillard10a2c651999-12-12 13:03:50 +00002952 if (ret->size){
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002953 ret->content = (xmlChar *) xmlMalloc(ret->size * sizeof(xmlChar));
2954 if (ret->content == NULL) {
2955 fprintf(stderr, "xmlBufferCreate : out of memory!\n");
2956 xmlFree(ret);
2957 return(NULL);
2958 }
2959 ret->content[0] = 0;
2960 } else
2961 ret->content = NULL;
2962 return(ret);
2963}
2964
2965/**
2966 * xmlBufferAllocationScheme:
2967 * @buf: the buffer to free
2968 * @scheme: allocation scheme to use
2969 *
2970 * Sets the allocation scheme for this buffer
2971 */
2972void
2973xmlBufferSetAllocationScheme(xmlBufferPtr buf,
2974 xmlBufferAllocationScheme scheme) {
2975 if (buf == NULL) {
2976 fprintf(stderr, "xmlBufferSetAllocationScheme: buf == NULL\n");
2977 return;
2978 }
2979
2980 buf->alloc = scheme;
2981}
2982
2983/**
Daniel Veillard5099ae81999-04-21 20:12:07 +00002984 * xmlBufferFree:
2985 * @buf: the buffer to free
2986 *
2987 * Frees an XML buffer.
2988 */
2989void
2990xmlBufferFree(xmlBufferPtr buf) {
2991 if (buf == NULL) {
2992 fprintf(stderr, "xmlBufferFree: buf == NULL\n");
2993 return;
2994 }
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002995 if (buf->content != NULL) {
2996#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard5099ae81999-04-21 20:12:07 +00002997 memset(buf->content, -1, BASE_BUFFER_SIZE);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002998#else
2999 memset(buf->content, -1, buf->size);
3000#endif
Daniel Veillard6454aec1999-09-02 22:04:43 +00003001 xmlFree(buf->content);
Daniel Veillard5099ae81999-04-21 20:12:07 +00003002 }
3003 memset(buf, -1, sizeof(xmlBuffer));
Daniel Veillard6454aec1999-09-02 22:04:43 +00003004 xmlFree(buf);
Daniel Veillard5099ae81999-04-21 20:12:07 +00003005}
3006
3007/**
Daniel Veillarde2d034d1999-07-27 19:52:06 +00003008 * xmlBufferEmpty:
3009 * @buf: the buffer
3010 *
3011 * empty a buffer.
3012 */
3013void
3014xmlBufferEmpty(xmlBufferPtr buf) {
3015 buf->use = 0;
3016 memset(buf->content, -1, buf->size);/* just for debug */
3017}
3018
3019/**
3020 * xmlBufferShrink:
3021 * @buf: the buffer to dump
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003022 * @len: the number of xmlChar to remove
Daniel Veillarde2d034d1999-07-27 19:52:06 +00003023 *
3024 * Remove the beginning of an XML buffer.
3025 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003026 * Returns the number of xmlChar removed, or -1 in case of failure.
Daniel Veillarde2d034d1999-07-27 19:52:06 +00003027 */
3028int
3029xmlBufferShrink(xmlBufferPtr buf, int len) {
3030 if (len == 0) return(0);
3031 if (len > buf->use) return(-1);
3032
3033 buf->use -= len;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003034 memmove(buf->content, &buf->content[len], buf->use * sizeof(xmlChar));
Daniel Veillarde2d034d1999-07-27 19:52:06 +00003035
3036 buf->content[buf->use] = 0;
3037 return(len);
3038}
3039
3040/**
Daniel Veillard5099ae81999-04-21 20:12:07 +00003041 * xmlBufferDump:
3042 * @file: the file output
3043 * @buf: the buffer to dump
3044 *
3045 * Dumps an XML buffer to a FILE *.
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003046 * Returns the number of xmlChar written
Daniel Veillard5099ae81999-04-21 20:12:07 +00003047 */
3048int
3049xmlBufferDump(FILE *file, xmlBufferPtr buf) {
3050 int ret;
3051
3052 if (buf == NULL) {
3053 fprintf(stderr, "xmlBufferDump: buf == NULL\n");
3054 return(0);
3055 }
3056 if (buf->content == NULL) {
3057 fprintf(stderr, "xmlBufferDump: buf->content == NULL\n");
3058 return(0);
3059 }
3060 if (file == NULL) file = stdout;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003061 ret = fwrite(buf->content, sizeof(xmlChar), buf->use, file);
Daniel Veillard5099ae81999-04-21 20:12:07 +00003062 return(ret);
3063}
3064
3065/**
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003066 * xmlBufferContent:
3067 * @buf: the buffer to resize
3068 *
3069 * Returns the internal content
3070 */
3071
3072const xmlChar*
3073xmlBufferContent(const xmlBufferPtr buf)
3074{
3075 if(!buf)
3076 return NULL;
3077
3078 return buf->content;
3079}
3080
3081/**
3082 * xmlBufferLength:
3083 * @buf: the buffer
3084 *
3085 * Returns the length of data in the internal content
3086 */
3087
3088int
3089xmlBufferLength(const xmlBufferPtr buf)
3090{
3091 if(!buf)
3092 return 0;
3093
3094 return buf->use;
3095}
3096
3097/**
3098 * xmlBufferResize:
3099 * @buf: the buffer to resize
3100 * @len: the desired size
3101 *
3102 * Resize a buffer to accomodate minimum size of <len>.
3103 *
3104 * Returns 0 in case of problems, 1 otherwise
3105 */
3106int
3107xmlBufferResize(xmlBufferPtr buf, int size)
3108{
3109 int newSize = (buf->size ? buf->size*2 : size);/*take care of empty case*/
3110 xmlChar* rebuf = NULL;
3111
3112 /* Don't resize if we don't have to */
3113 if(size < buf->size)
3114 return 1;
3115
3116 /* figure out new size */
3117 switch(buf->alloc){
3118 case XML_BUFFER_ALLOC_DOUBLEIT:
3119 while(size > newSize) newSize *= 2;
3120 break;
3121 case XML_BUFFER_ALLOC_EXACT:
3122 newSize = size+10;
3123 break;
3124 default:
3125 newSize = size+10;
3126 break;
3127 }
3128
3129 if (buf->content == NULL)
3130 rebuf = (xmlChar *) xmlMalloc(newSize * sizeof(xmlChar));
3131 else
3132 rebuf = (xmlChar *) xmlRealloc(buf->content,
3133 newSize * sizeof(xmlChar));
3134 if (rebuf == NULL) {
3135 fprintf(stderr, "xmlBufferAdd : out of memory!\n");
3136 return 0;
3137 }
3138 buf->content = rebuf;
3139 buf->size = newSize;
3140
3141 return 1;
3142}
3143/**
Daniel Veillard5099ae81999-04-21 20:12:07 +00003144 * xmlBufferAdd:
3145 * @buf: the buffer to dump
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003146 * @str: the xmlChar string
3147 * @len: the number of xmlChar to add
Daniel Veillard5099ae81999-04-21 20:12:07 +00003148 *
Daniel Veillard10a2c651999-12-12 13:03:50 +00003149 * Add a string range to an XML buffer. if len == -1, the lenght of
3150 * str is recomputed.
Daniel Veillard5099ae81999-04-21 20:12:07 +00003151 */
3152void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003153xmlBufferAdd(xmlBufferPtr buf, const xmlChar *str, int len) {
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003154 int l, needSize;
Daniel Veillard5099ae81999-04-21 20:12:07 +00003155
3156 if (str == NULL) {
3157 fprintf(stderr, "xmlBufferAdd: str == NULL\n");
3158 return;
3159 }
Daniel Veillard10a2c651999-12-12 13:03:50 +00003160 if (len < -1) {
3161 fprintf(stderr, "xmlBufferAdd: len < 0\n");
3162 return;
3163 }
3164 if (len == 0) return;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003165
3166 /* CJN What's this for??? */
Daniel Veillarde2d034d1999-07-27 19:52:06 +00003167 l = xmlStrlen(str);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003168 if (l < len){ len = l; printf("xmlBufferAdd bad length\n"); }
3169
3170 /* CJN 11.18.99 okay, now I'm using the length */
3171 if(len == -1) len = l;
3172
3173
Daniel Veillarde2d034d1999-07-27 19:52:06 +00003174 if (len <= 0) return;
Daniel Veillard5099ae81999-04-21 20:12:07 +00003175
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003176 needSize = buf->use + len + 2;
3177 if(needSize > buf->size){
3178 if(!xmlBufferResize(buf, needSize)){
3179 fprintf(stderr, "xmlBufferAdd : out of memory!\n");
3180 return;
3181 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003182 }
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003183
3184 memmove(&buf->content[buf->use], str, len*sizeof(xmlChar));
Daniel Veillarde2d034d1999-07-27 19:52:06 +00003185 buf->use += len;
3186 buf->content[buf->use] = 0;
Daniel Veillard5099ae81999-04-21 20:12:07 +00003187}
3188
3189/**
3190 * xmlBufferCat:
3191 * @buf: the buffer to dump
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003192 * @str: the xmlChar string
Daniel Veillard5099ae81999-04-21 20:12:07 +00003193 *
3194 * Append a zero terminated string to an XML buffer.
3195 */
3196void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003197xmlBufferCat(xmlBufferPtr buf, const xmlChar *str) {
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003198 if (str != NULL)
3199 xmlBufferAdd(buf, str, -1);
Daniel Veillard5099ae81999-04-21 20:12:07 +00003200}
3201
3202/**
3203 * xmlBufferCCat:
3204 * @buf: the buffer to dump
3205 * @str: the C char string
3206 *
3207 * Append a zero terminated C string to an XML buffer.
3208 */
3209void
3210xmlBufferCCat(xmlBufferPtr buf, const char *str) {
3211 const char *cur;
3212
3213 if (str == NULL) {
3214 fprintf(stderr, "xmlBufferAdd: str == NULL\n");
3215 return;
3216 }
3217 for (cur = str;*cur != 0;cur++) {
3218 if (buf->use + 10 >= buf->size) {
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003219 if(!xmlBufferResize(buf, buf->use+10)){
3220 fprintf(stderr, "xmlBufferCCat : out of memory!\n");
3221 return;
3222 }
3223 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003224 buf->content[buf->use++] = *cur;
3225 }
3226}
Daniel Veillard260a68f1998-08-13 03:39:55 +00003227
Daniel Veillard97b58771998-10-20 06:14:16 +00003228/**
3229 * xmlBufferWriteCHAR:
Daniel Veillard5099ae81999-04-21 20:12:07 +00003230 * @buf: the XML buffer
Daniel Veillard97b58771998-10-20 06:14:16 +00003231 * @string: the string to add
3232 *
3233 * routine which manage and grows an output buffer. This one add
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003234 * xmlChars at the end of the buffer.
Daniel Veillard97b58771998-10-20 06:14:16 +00003235 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003236void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003237xmlBufferWriteCHAR(xmlBufferPtr buf, const xmlChar *string) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003238 xmlBufferCat(buf, string);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003239}
3240
Daniel Veillard97b58771998-10-20 06:14:16 +00003241/**
3242 * xmlBufferWriteChar:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003243 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003244 * @string: the string to add
3245 *
3246 * routine which manage and grows an output buffer. This one add
3247 * C chars at the end of the array.
3248 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003249void
Daniel Veillard5099ae81999-04-21 20:12:07 +00003250xmlBufferWriteChar(xmlBufferPtr buf, const char *string) {
3251 xmlBufferCCat(buf, string);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003252}
3253
Daniel Veillard5099ae81999-04-21 20:12:07 +00003254
Daniel Veillard97b58771998-10-20 06:14:16 +00003255/**
Daniel Veillard011b63c1999-06-02 17:44:04 +00003256 * xmlBufferWriteQuotedString:
3257 * @buf: the XML buffer output
3258 * @string: the string to add
3259 *
3260 * routine which manage and grows an output buffer. This one writes
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003261 * a quoted or double quoted xmlChar string, checking first if it holds
Daniel Veillard011b63c1999-06-02 17:44:04 +00003262 * quote or double-quotes internally
3263 */
3264void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003265xmlBufferWriteQuotedString(xmlBufferPtr buf, const xmlChar *string) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00003266 if (xmlStrchr(string, '"')) {
3267 if (xmlStrchr(string, '\'')) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00003268 fprintf(stderr,
3269 "xmlBufferWriteQuotedString: string contains quote and double-quotes !\n");
3270 }
3271 xmlBufferCCat(buf, "'");
3272 xmlBufferCat(buf, string);
3273 xmlBufferCCat(buf, "'");
3274 } else {
3275 xmlBufferCCat(buf, "\"");
3276 xmlBufferCat(buf, string);
3277 xmlBufferCCat(buf, "\"");
3278 }
3279}
3280
3281
3282/**
Daniel Veillard97b58771998-10-20 06:14:16 +00003283 * xmlGlobalNsDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003284 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003285 * @cur: a namespace
3286 *
3287 * Dump a global Namespace, this is the old version based on PIs.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003288 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003289static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00003290xmlGlobalNsDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003291 if (cur == NULL) {
3292 fprintf(stderr, "xmlGlobalNsDump : Ns == NULL\n");
3293 return;
3294 }
3295 if (cur->type == XML_GLOBAL_NAMESPACE) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003296 xmlBufferWriteChar(buf, "<?namespace");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003297 if (cur->href != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00003298 xmlBufferWriteChar(buf, " href=");
3299 xmlBufferWriteQuotedString(buf, cur->href);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003300 }
3301 if (cur->prefix != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00003302 xmlBufferWriteChar(buf, " AS=");
3303 xmlBufferWriteQuotedString(buf, cur->prefix);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003304 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003305 xmlBufferWriteChar(buf, "?>\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003306 }
3307}
3308
Daniel Veillard97b58771998-10-20 06:14:16 +00003309/**
3310 * xmlGlobalNsListDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003311 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003312 * @cur: the first namespace
3313 *
3314 * Dump a list of global Namespace, this is the old version based on PIs.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003315 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003316static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00003317xmlGlobalNsListDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003318 while (cur != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003319 xmlGlobalNsDump(buf, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003320 cur = cur->next;
3321 }
3322}
3323
Daniel Veillard97b58771998-10-20 06:14:16 +00003324/**
3325 * xmlNsDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003326 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003327 * @cur: a namespace
3328 *
Daniel Veillard260a68f1998-08-13 03:39:55 +00003329 * Dump a local Namespace definition.
Daniel Veillard97b58771998-10-20 06:14:16 +00003330 * Should be called in the context of attributes dumps.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003331 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003332static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00003333xmlNsDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003334 if (cur == NULL) {
3335 fprintf(stderr, "xmlNsDump : Ns == NULL\n");
3336 return;
3337 }
3338 if (cur->type == XML_LOCAL_NAMESPACE) {
3339 /* Within the context of an element attributes */
3340 if (cur->prefix != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003341 xmlBufferWriteChar(buf, " xmlns:");
3342 xmlBufferWriteCHAR(buf, cur->prefix);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003343 } else
Daniel Veillard5099ae81999-04-21 20:12:07 +00003344 xmlBufferWriteChar(buf, " xmlns");
Daniel Veillard011b63c1999-06-02 17:44:04 +00003345 xmlBufferWriteChar(buf, "=");
3346 xmlBufferWriteQuotedString(buf, cur->href);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003347 }
3348}
3349
Daniel Veillard97b58771998-10-20 06:14:16 +00003350/**
3351 * xmlNsListDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003352 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003353 * @cur: the first namespace
3354 *
3355 * Dump a list of local Namespace definitions.
3356 * Should be called in the context of attributes dumps.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003357 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003358static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00003359xmlNsListDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003360 while (cur != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003361 xmlNsDump(buf, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003362 cur = cur->next;
3363 }
3364}
3365
Daniel Veillard97b58771998-10-20 06:14:16 +00003366/**
3367 * xmlDtdDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003368 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003369 * @doc: the document
3370 *
3371 * Dump the XML document DTD, if any.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003372 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003373static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00003374xmlDtdDump(xmlBufferPtr buf, xmlDocPtr doc) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003375 xmlDtdPtr cur = doc->intSubset;
Daniel Veillard260a68f1998-08-13 03:39:55 +00003376
3377 if (cur == NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003378 fprintf(stderr, "xmlDtdDump : no internal subset\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003379 return;
3380 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003381 xmlBufferWriteChar(buf, "<!DOCTYPE ");
3382 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003383 if (cur->ExternalID != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00003384 xmlBufferWriteChar(buf, " PUBLIC ");
3385 xmlBufferWriteQuotedString(buf, cur->ExternalID);
3386 xmlBufferWriteChar(buf, " ");
3387 xmlBufferWriteQuotedString(buf, cur->SystemID);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003388 } else if (cur->SystemID != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00003389 xmlBufferWriteChar(buf, " SYSTEM ");
3390 xmlBufferWriteQuotedString(buf, cur->SystemID);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003391 }
Daniel Veillard1e346af1999-02-22 10:33:01 +00003392 if ((cur->entities == NULL) && (cur->elements == NULL) &&
3393 (cur->attributes == NULL) && (cur->notations == NULL)) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003394 xmlBufferWriteChar(buf, ">\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003395 return;
3396 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003397 xmlBufferWriteChar(buf, " [\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003398 if (cur->entities != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00003399 xmlDumpEntitiesTable(buf, (xmlEntitiesTablePtr) cur->entities);
Daniel Veillard1e346af1999-02-22 10:33:01 +00003400 if (cur->notations != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00003401 xmlDumpNotationTable(buf, (xmlNotationTablePtr) cur->notations);
Daniel Veillard3b9def11999-01-31 22:15:06 +00003402 if (cur->elements != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00003403 xmlDumpElementTable(buf, (xmlElementTablePtr) cur->elements);
Daniel Veillard1e346af1999-02-22 10:33:01 +00003404 if (cur->attributes != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00003405 xmlDumpAttributeTable(buf, (xmlAttributeTablePtr) cur->attributes);
3406 xmlBufferWriteChar(buf, "]");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003407
Daniel Veillard5099ae81999-04-21 20:12:07 +00003408 xmlBufferWriteChar(buf, ">\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003409}
3410
Daniel Veillard97b58771998-10-20 06:14:16 +00003411/**
3412 * xmlAttrDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003413 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003414 * @doc: the document
3415 * @cur: the attribute pointer
3416 *
3417 * Dump an XML attribute
Daniel Veillard260a68f1998-08-13 03:39:55 +00003418 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003419static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00003420xmlAttrDump(xmlBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003421 xmlChar *value;
Daniel Veillardccb09631998-10-27 06:21:04 +00003422
Daniel Veillard260a68f1998-08-13 03:39:55 +00003423 if (cur == NULL) {
3424 fprintf(stderr, "xmlAttrDump : property == NULL\n");
3425 return;
3426 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003427 xmlBufferWriteChar(buf, " ");
Daniel Veillardb96e6431999-08-29 21:02:19 +00003428 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
3429 xmlBufferWriteCHAR(buf, cur->ns->prefix);
3430 xmlBufferWriteChar(buf, ":");
3431 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003432 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillardccb09631998-10-27 06:21:04 +00003433 value = xmlNodeListGetString(doc, cur->val, 0);
3434 if (value) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00003435 xmlBufferWriteChar(buf, "=");
3436 xmlBufferWriteQuotedString(buf, value);
Daniel Veillard6454aec1999-09-02 22:04:43 +00003437 xmlFree(value);
Daniel Veillard726c7e31999-02-08 15:13:10 +00003438 } else {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003439 xmlBufferWriteChar(buf, "=\"\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003440 }
3441}
3442
Daniel Veillard97b58771998-10-20 06:14:16 +00003443/**
3444 * xmlAttrListDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003445 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003446 * @doc: the document
3447 * @cur: the first attribute pointer
3448 *
3449 * Dump a list of XML attributes
Daniel Veillard260a68f1998-08-13 03:39:55 +00003450 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003451static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00003452xmlAttrListDump(xmlBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003453 if (cur == NULL) {
3454 fprintf(stderr, "xmlAttrListDump : property == NULL\n");
3455 return;
3456 }
3457 while (cur != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003458 xmlAttrDump(buf, doc, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003459 cur = cur->next;
3460 }
3461}
3462
Daniel Veillard260a68f1998-08-13 03:39:55 +00003463
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003464static void
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003465xmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
3466 int format);
Daniel Veillard97b58771998-10-20 06:14:16 +00003467/**
3468 * xmlNodeListDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003469 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003470 * @doc: the document
3471 * @cur: the first node
3472 * @level: the imbrication level for indenting
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003473 * @format: is formatting allowed
Daniel Veillard97b58771998-10-20 06:14:16 +00003474 *
3475 * Dump an XML node list, recursive behaviour,children are printed too.
3476 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003477static void
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003478xmlNodeListDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
3479 int format) {
3480 int i;
Daniel Veillardccb09631998-10-27 06:21:04 +00003481
Daniel Veillard260a68f1998-08-13 03:39:55 +00003482 if (cur == NULL) {
3483 fprintf(stderr, "xmlNodeListDump : node == NULL\n");
3484 return;
3485 }
3486 while (cur != NULL) {
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003487 if ((format) && (xmlIndentTreeOutput) &&
3488 (cur->type == XML_ELEMENT_NODE))
3489 for (i = 0;i < level;i++)
3490 xmlBufferWriteChar(buf, " ");
3491 xmlNodeDump(buf, doc, cur, level, format);
3492 if (format) {
3493 xmlBufferWriteChar(buf, "\n");
Daniel Veillardccb09631998-10-27 06:21:04 +00003494 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003495 cur = cur->next;
3496 }
3497}
3498
Daniel Veillard97b58771998-10-20 06:14:16 +00003499/**
Daniel Veillardccb09631998-10-27 06:21:04 +00003500 * xmlNodeDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003501 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003502 * @doc: the document
3503 * @cur: the current node
3504 * @level: the imbrication level for indenting
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003505 * @format: is formatting allowed
Daniel Veillard97b58771998-10-20 06:14:16 +00003506 *
3507 * Dump an XML node, recursive behaviour,children are printed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003508 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003509static void
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003510xmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
3511 int format) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003512 int i;
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003513 xmlNodePtr tmp;
Daniel Veillard260a68f1998-08-13 03:39:55 +00003514
3515 if (cur == NULL) {
3516 fprintf(stderr, "xmlNodeDump : node == NULL\n");
3517 return;
3518 }
Daniel Veillard0bef1311998-10-14 02:36:47 +00003519 if (cur->type == XML_TEXT_NODE) {
Daniel Veillard14fff061999-06-22 21:49:07 +00003520 if (cur->content != NULL) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003521 xmlChar *buffer;
Daniel Veillard14fff061999-06-22 21:49:07 +00003522
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003523#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard14fff061999-06-22 21:49:07 +00003524 buffer = xmlEncodeEntitiesReentrant(doc, cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003525#else
3526 buffer = xmlEncodeEntitiesReentrant(doc,
3527 xmlBufferContent(cur->content));
3528#endif
Daniel Veillard14fff061999-06-22 21:49:07 +00003529 if (buffer != NULL) {
3530 xmlBufferWriteCHAR(buf, buffer);
Daniel Veillard6454aec1999-09-02 22:04:43 +00003531 xmlFree(buffer);
Daniel Veillard14fff061999-06-22 21:49:07 +00003532 }
3533 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003534 return;
3535 }
Daniel Veillardb96e6431999-08-29 21:02:19 +00003536 if (cur->type == XML_PI_NODE) {
3537 if (cur->content != NULL) {
3538 xmlBufferWriteChar(buf, "<?");
3539 xmlBufferWriteCHAR(buf, cur->name);
3540 if (cur->content != NULL) {
3541 xmlBufferWriteChar(buf, " ");
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003542#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardb96e6431999-08-29 21:02:19 +00003543 xmlBufferWriteCHAR(buf, cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003544#else
3545 xmlBufferWriteCHAR(buf, xmlBufferContent(cur->content));
3546#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +00003547 }
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003548 xmlBufferWriteChar(buf, "?>");
Daniel Veillardb96e6431999-08-29 21:02:19 +00003549 }
3550 return;
3551 }
Daniel Veillard0bef1311998-10-14 02:36:47 +00003552 if (cur->type == XML_COMMENT_NODE) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003553 if (cur->content != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003554 xmlBufferWriteChar(buf, "<!--");
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003555#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard5099ae81999-04-21 20:12:07 +00003556 xmlBufferWriteCHAR(buf, cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003557#else
3558 xmlBufferWriteCHAR(buf, xmlBufferContent(cur->content));
3559#endif
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003560 xmlBufferWriteChar(buf, "-->");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003561 }
3562 return;
3563 }
Daniel Veillardccb09631998-10-27 06:21:04 +00003564 if (cur->type == XML_ENTITY_REF_NODE) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003565 xmlBufferWriteChar(buf, "&");
3566 xmlBufferWriteCHAR(buf, cur->name);
3567 xmlBufferWriteChar(buf, ";");
Daniel Veillardccb09631998-10-27 06:21:04 +00003568 return;
3569 }
Daniel Veillardb05deb71999-08-10 19:04:08 +00003570 if (cur->type == XML_CDATA_SECTION_NODE) {
3571 xmlBufferWriteChar(buf, "<![CDATA[");
3572 if (cur->content != NULL)
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003573#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardb05deb71999-08-10 19:04:08 +00003574 xmlBufferWriteCHAR(buf, cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003575#else
3576 xmlBufferWriteCHAR(buf, xmlBufferContent(cur->content));
3577#endif
Daniel Veillardb05deb71999-08-10 19:04:08 +00003578 xmlBufferWriteChar(buf, "]]>");
3579 return;
3580 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003581
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003582 if (format == 1) {
3583 tmp = cur->childs;
3584 while (tmp != NULL) {
3585 if ((tmp->type == XML_TEXT_NODE) ||
3586 (tmp->type == XML_ENTITY_REF_NODE)) {
3587 format = 0;
3588 break;
3589 }
3590 tmp = tmp->next;
3591 }
3592 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003593 xmlBufferWriteChar(buf, "<");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003594 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003595 xmlBufferWriteCHAR(buf, cur->ns->prefix);
3596 xmlBufferWriteChar(buf, ":");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003597 }
3598
Daniel Veillard5099ae81999-04-21 20:12:07 +00003599 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003600 if (cur->nsDef)
Daniel Veillard5099ae81999-04-21 20:12:07 +00003601 xmlNsListDump(buf, cur->nsDef);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003602 if (cur->properties != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00003603 xmlAttrListDump(buf, doc, cur->properties);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003604
3605 if ((cur->content == NULL) && (cur->childs == NULL)) {
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003606 xmlBufferWriteChar(buf, "/>");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003607 return;
3608 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003609 xmlBufferWriteChar(buf, ">");
Daniel Veillard14fff061999-06-22 21:49:07 +00003610 if (cur->content != NULL) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003611 xmlChar *buffer;
Daniel Veillard14fff061999-06-22 21:49:07 +00003612
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003613#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard14fff061999-06-22 21:49:07 +00003614 buffer = xmlEncodeEntitiesReentrant(doc, cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003615#else
3616 buffer = xmlEncodeEntitiesReentrant(doc,
3617 xmlBufferContent(cur->content));
3618#endif
Daniel Veillard14fff061999-06-22 21:49:07 +00003619 if (buffer != NULL) {
3620 xmlBufferWriteCHAR(buf, buffer);
Daniel Veillard6454aec1999-09-02 22:04:43 +00003621 xmlFree(buffer);
Daniel Veillard14fff061999-06-22 21:49:07 +00003622 }
3623 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003624 if (cur->childs != NULL) {
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003625 if (format) xmlBufferWriteChar(buf, "\n");
3626 xmlNodeListDump(buf, doc, cur->childs, level + 1, format);
3627 if ((xmlIndentTreeOutput) && (format))
3628 for (i = 0;i < level;i++)
3629 xmlBufferWriteChar(buf, " ");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003630 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003631 xmlBufferWriteChar(buf, "</");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003632 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003633 xmlBufferWriteCHAR(buf, cur->ns->prefix);
3634 xmlBufferWriteChar(buf, ":");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003635 }
3636
Daniel Veillard5099ae81999-04-21 20:12:07 +00003637 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003638 xmlBufferWriteChar(buf, ">");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003639}
3640
Daniel Veillard97b58771998-10-20 06:14:16 +00003641/**
3642 * xmlDocContentDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003643 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003644 * @cur: the document
3645 *
3646 * Dump an XML document.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003647 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003648static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00003649xmlDocContentDump(xmlBufferPtr buf, xmlDocPtr cur) {
Daniel Veillardbe70ff71999-07-05 16:50:46 +00003650 xmlBufferWriteChar(buf, "<?xml version=");
3651 if (cur->version != NULL)
3652 xmlBufferWriteQuotedString(buf, cur->version);
3653 else
3654 xmlBufferWriteChar(buf, "\"1.0\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003655 if (cur->encoding != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00003656 xmlBufferWriteChar(buf, " encoding=");
3657 xmlBufferWriteQuotedString(buf, cur->encoding);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003658 }
3659 switch (cur->standalone) {
3660 case 0:
Daniel Veillard5099ae81999-04-21 20:12:07 +00003661 xmlBufferWriteChar(buf, " standalone=\"no\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003662 break;
3663 case 1:
Daniel Veillard5099ae81999-04-21 20:12:07 +00003664 xmlBufferWriteChar(buf, " standalone=\"yes\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003665 break;
3666 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003667 xmlBufferWriteChar(buf, "?>\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003668 if (cur->intSubset != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00003669 xmlDtdDump(buf, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003670 if (cur->root != NULL) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00003671 xmlNodePtr child = cur->root;
3672
Daniel Veillard260a68f1998-08-13 03:39:55 +00003673 /* global namespace definitions, the old way */
3674 if (oldXMLWDcompatibility)
Daniel Veillard5099ae81999-04-21 20:12:07 +00003675 xmlGlobalNsListDump(buf, cur->oldNs);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003676 else
3677 xmlUpgradeOldNs(cur);
Daniel Veillardb96e6431999-08-29 21:02:19 +00003678
3679 while (child != NULL) {
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003680 xmlNodeDump(buf, cur, child, 0, 1);
3681 xmlBufferWriteChar(buf, "\n");
Daniel Veillardb96e6431999-08-29 21:02:19 +00003682 child = child->next;
3683 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003684 }
3685}
3686
Daniel Veillard97b58771998-10-20 06:14:16 +00003687/**
3688 * xmlDocDumpMemory:
3689 * @cur: the document
3690 * @mem: OUT: the memory pointer
3691 * @size: OUT: the memory lenght
3692 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003693 * Dump an XML document in memory and return the xmlChar * and it's size.
Daniel Veillard97b58771998-10-20 06:14:16 +00003694 * It's up to the caller to free the memory.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003695 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003696void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003697xmlDocDumpMemory(xmlDocPtr cur, xmlChar**mem, int *size) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003698 xmlBufferPtr buf;
3699
Daniel Veillard260a68f1998-08-13 03:39:55 +00003700 if (cur == NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003701#ifdef DEBUG_TREE
3702 fprintf(stderr, "xmlDocDumpMemory : document == NULL\n");
3703#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00003704 *mem = NULL;
3705 *size = 0;
3706 return;
3707 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003708 buf = xmlBufferCreate();
3709 if (buf == NULL) {
3710 *mem = NULL;
3711 *size = 0;
3712 return;
3713 }
3714 xmlDocContentDump(buf, cur);
Daniel Veillardb05deb71999-08-10 19:04:08 +00003715 *mem = xmlStrndup(buf->content, buf->use);
Daniel Veillard5099ae81999-04-21 20:12:07 +00003716 *size = buf->use;
Daniel Veillardb05deb71999-08-10 19:04:08 +00003717 xmlBufferFree(buf);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003718}
3719
Daniel Veillard97b58771998-10-20 06:14:16 +00003720/**
3721 * xmlGetDocCompressMode:
3722 * @doc: the document
3723 *
3724 * get the compression ratio for a document, ZLIB based
Daniel Veillard1e346af1999-02-22 10:33:01 +00003725 * Returns 0 (uncompressed) to 9 (max compression)
Daniel Veillard151b1b01998-09-23 00:49:46 +00003726 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003727int
3728 xmlGetDocCompressMode (xmlDocPtr doc) {
Daniel Veillard15a8df41998-09-24 19:15:06 +00003729 if (doc == NULL) return(-1);
3730 return(doc->compression);
3731}
3732
Daniel Veillard97b58771998-10-20 06:14:16 +00003733/**
3734 * xmlSetDocCompressMode:
3735 * @doc: the document
3736 * @mode: the compression ratio
3737 *
3738 * set the compression ratio for a document, ZLIB based
3739 * Correct values: 0 (uncompressed) to 9 (max compression)
3740 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003741void
3742xmlSetDocCompressMode (xmlDocPtr doc, int mode) {
Daniel Veillard15a8df41998-09-24 19:15:06 +00003743 if (doc == NULL) return;
3744 if (mode < 0) doc->compression = 0;
3745 else if (mode > 9) doc->compression = 9;
3746 else doc->compression = mode;
3747}
3748
Daniel Veillard97b58771998-10-20 06:14:16 +00003749/**
3750 * xmlGetCompressMode:
3751 *
3752 * get the default compression mode used, ZLIB based.
Daniel Veillard1e346af1999-02-22 10:33:01 +00003753 * Returns 0 (uncompressed) to 9 (max compression)
Daniel Veillard15a8df41998-09-24 19:15:06 +00003754 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003755int
3756 xmlGetCompressMode(void) {
Daniel Veillard151b1b01998-09-23 00:49:46 +00003757 return(xmlCompressMode);
3758}
Daniel Veillard97b58771998-10-20 06:14:16 +00003759
3760/**
3761 * xmlSetCompressMode:
3762 * @mode: the compression ratio
3763 *
3764 * set the default compression mode used, ZLIB based
3765 * Correct values: 0 (uncompressed) to 9 (max compression)
3766 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003767void
3768xmlSetCompressMode(int mode) {
Daniel Veillard151b1b01998-09-23 00:49:46 +00003769 if (mode < 0) xmlCompressMode = 0;
Daniel Veillard15a8df41998-09-24 19:15:06 +00003770 else if (mode > 9) xmlCompressMode = 9;
Daniel Veillard151b1b01998-09-23 00:49:46 +00003771 else xmlCompressMode = mode;
3772}
3773
Daniel Veillard97b58771998-10-20 06:14:16 +00003774/**
3775 * xmlDocDump:
3776 * @f: the FILE*
3777 * @cur: the document
3778 *
3779 * Dump an XML document to an open FILE.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003780 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003781void
3782xmlDocDump(FILE *f, xmlDocPtr cur) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003783 xmlBufferPtr buf;
3784
Daniel Veillard260a68f1998-08-13 03:39:55 +00003785 if (cur == NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003786#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00003787 fprintf(stderr, "xmlDocDump : document == NULL\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003788#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00003789 return;
3790 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003791 buf = xmlBufferCreate();
3792 if (buf == NULL) return;
3793 xmlDocContentDump(buf, cur);
3794 xmlBufferDump(f, buf);
3795 xmlBufferFree(buf);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003796}
3797
Daniel Veillard97b58771998-10-20 06:14:16 +00003798/**
3799 * xmlSaveFile:
3800 * @filename: the filename
3801 * @cur: the document
3802 *
3803 * Dump an XML document to a file. Will use compression if
Daniel Veillard11a48ec1999-11-23 10:40:46 +00003804 * compiled in and enabled. If @filename is "-" the stdout file is
3805 * used.
Daniel Veillard97b58771998-10-20 06:14:16 +00003806 * returns: the number of file written or -1 in case of failure.
Daniel Veillard151b1b01998-09-23 00:49:46 +00003807 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003808int
3809xmlSaveFile(const char *filename, xmlDocPtr cur) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003810 xmlBufferPtr buf;
Daniel Veillard151b1b01998-09-23 00:49:46 +00003811#ifdef HAVE_ZLIB_H
3812 gzFile zoutput = NULL;
3813 char mode[15];
3814#endif
Daniel Veillardccb09631998-10-27 06:21:04 +00003815 FILE *output = NULL;
Daniel Veillard151b1b01998-09-23 00:49:46 +00003816 int ret;
3817
Daniel Veillard5099ae81999-04-21 20:12:07 +00003818 /*
3819 * save the content to a temp buffer.
3820 */
3821 buf = xmlBufferCreate();
3822 if (buf == NULL) return(0);
3823 xmlDocContentDump(buf, cur);
3824
Daniel Veillard151b1b01998-09-23 00:49:46 +00003825#ifdef HAVE_ZLIB_H
Daniel Veillard11a48ec1999-11-23 10:40:46 +00003826 if (cur->compression < 0) cur->compression = xmlCompressMode;
Daniel Veillarddc3dd9d1998-09-24 19:25:54 +00003827 if ((cur->compression > 0) && (cur->compression <= 9)) {
3828 sprintf(mode, "w%d", cur->compression);
Daniel Veillard11a48ec1999-11-23 10:40:46 +00003829 if (!strcmp(filename, "-"))
3830 zoutput = gzdopen(1, mode);
3831 else
3832 zoutput = gzopen(filename, mode);
Daniel Veillard151b1b01998-09-23 00:49:46 +00003833 }
3834 if (zoutput == NULL) {
3835#endif
3836 output = fopen(filename, "w");
Daniel Veillard10a2c651999-12-12 13:03:50 +00003837 if (output == NULL) {
3838 xmlBufferFree(buf);
3839 return(-1);
3840 }
Daniel Veillard151b1b01998-09-23 00:49:46 +00003841#ifdef HAVE_ZLIB_H
3842 }
Daniel Veillard151b1b01998-09-23 00:49:46 +00003843
Daniel Veillard151b1b01998-09-23 00:49:46 +00003844 if (zoutput != NULL) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003845 ret = gzwrite(zoutput, buf->content, sizeof(xmlChar) * buf->use);
Daniel Veillard151b1b01998-09-23 00:49:46 +00003846 gzclose(zoutput);
Daniel Veillard5099ae81999-04-21 20:12:07 +00003847 } else {
3848#endif
3849 ret = xmlBufferDump(output, buf);
3850 fclose(output);
3851#ifdef HAVE_ZLIB_H
Daniel Veillard151b1b01998-09-23 00:49:46 +00003852 }
3853#endif
Manish Vachharajani5e60f5a1999-05-29 03:04:30 +00003854 xmlBufferFree(buf);
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003855 return(ret * sizeof(xmlChar));
Daniel Veillard151b1b01998-09-23 00:49:46 +00003856}
3857