blob: 5451f5325cf04751b3f542fc96fe5172cf891706 [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 Veillardb96e6431999-08-29 21:02:19 +00002159 * xmlNodeSetLang:
2160 * @cur: the node being changed
2161 * @lang: the langage description
2162 *
2163 * Searches the language of a node, i.e. the values of the xml:lang
2164 * attribute or the one carried by the nearest ancestor.
Daniel Veillardb96e6431999-08-29 21:02:19 +00002165 */
2166void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002167xmlNodeSetLang(xmlNodePtr cur, const xmlChar *lang) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00002168 /* TODO xmlNodeSetLang check against the production [33] LanguageID */
2169 xmlSetProp(cur, BAD_CAST "xml:lang", lang);
2170}
2171
2172/**
2173 * xmlNodeGetLang:
2174 * @cur: the node being checked
2175 *
2176 * Searches the language of a node, i.e. the values of the xml:lang
2177 * attribute or the one carried by the nearest ancestor.
2178 *
2179 * Returns a pointer to the lang value, or NULL if not found
Daniel Veillarda819dac1999-11-24 18:04:22 +00002180 * It's up to the caller to free the memory.
Daniel Veillardb96e6431999-08-29 21:02:19 +00002181 */
Daniel Veillarda819dac1999-11-24 18:04:22 +00002182xmlChar *
Daniel Veillardb96e6431999-08-29 21:02:19 +00002183xmlNodeGetLang(xmlNodePtr cur) {
Daniel Veillarda819dac1999-11-24 18:04:22 +00002184 xmlChar *lang;
Daniel Veillardb96e6431999-08-29 21:02:19 +00002185
2186 while (cur != NULL) {
2187 lang = xmlGetProp(cur, BAD_CAST "xml:lang");
2188 if (lang != NULL)
2189 return(lang);
2190 cur = cur->parent;
2191 }
2192 return(NULL);
2193}
2194
2195/**
Daniel Veillard10a2c651999-12-12 13:03:50 +00002196 * xmlNodeGetBase:
2197 * @doc: the document the node pertains to
2198 * @cur: the node being checked
2199 *
2200 * Searches for the BASE URL. The code should work on both XML
2201 * and HTML document even if base mechanisms are completely different.
2202 *
2203 * Returns a pointer to the base URL, or NULL if not found
2204 * It's up to the caller to free the memory.
2205 */
2206xmlChar *
2207xmlNodeGetBase(xmlDocPtr doc, xmlNodePtr cur) {
2208 xmlChar *base;
2209
2210 if ((cur == NULL) && (doc == NULL))
2211 return(NULL);
2212 if (doc == NULL) doc = cur->doc;
2213 if ((doc != NULL) && (doc->type == XML_HTML_DOCUMENT_NODE)) {
2214 cur = doc->root;
2215 while ((cur != NULL) && (cur->name != NULL)) {
2216 if (cur->type != XML_ELEMENT_NODE) {
2217 cur = cur->next;
2218 continue;
2219 }
2220 if ((!xmlStrcmp(cur->name, BAD_CAST "html")) ||
2221 (!xmlStrcmp(cur->name, BAD_CAST "HTML"))) {
2222 cur = cur->childs;
2223 continue;
2224 }
2225 if ((!xmlStrcmp(cur->name, BAD_CAST "head")) ||
2226 (!xmlStrcmp(cur->name, BAD_CAST "HEAD"))) {
2227 cur = cur->childs;
2228 continue;
2229 }
2230 if ((!xmlStrcmp(cur->name, BAD_CAST "base")) ||
2231 (!xmlStrcmp(cur->name, BAD_CAST "BASE"))) {
2232 base = xmlGetProp(cur, BAD_CAST "href");
2233 if (base != NULL) return(base);
2234 return(xmlGetProp(cur, BAD_CAST "HREF"));
2235 }
2236 }
2237 return(NULL);
2238 }
2239 while (cur != NULL) {
2240 base = xmlGetProp(cur, BAD_CAST "xml:base");
2241 if (base != NULL)
2242 return(base);
2243 cur = cur->parent;
2244 }
2245 return(NULL);
2246}
2247
2248/**
Daniel Veillard16253641998-10-28 22:58:05 +00002249 * xmlNodeGetContent:
2250 * @cur: the node being read
2251 *
2252 * Read the value of a node, this can be either the text carried
2253 * directly by this node if it's a TEXT node or the aggregate string
2254 * of the values carried by this node child's (TEXT and ENTITY_REF).
2255 * Entity references are substitued.
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002256 * Returns a new xmlChar * or NULL if no content is available.
Daniel Veillard5099ae81999-04-21 20:12:07 +00002257 * It's up to the caller to free the memory.
Daniel Veillard16253641998-10-28 22:58:05 +00002258 */
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002259xmlChar *
Daniel Veillard16253641998-10-28 22:58:05 +00002260xmlNodeGetContent(xmlNodePtr cur) {
2261 if (cur == NULL) return(NULL);
2262 switch (cur->type) {
2263 case XML_DOCUMENT_FRAG_NODE:
2264 case XML_ELEMENT_NODE:
2265 return(xmlNodeListGetString(cur->doc, cur->childs, 1));
2266 break;
Daniel Veillardb96e6431999-08-29 21:02:19 +00002267 case XML_ATTRIBUTE_NODE: {
2268 xmlAttrPtr attr = (xmlAttrPtr) cur;
2269 if (attr->node != NULL)
2270 return(xmlNodeListGetString(attr->node->doc, attr->val, 1));
2271 else
2272 return(xmlNodeListGetString(NULL, attr->val, 1));
2273 break;
2274 }
2275 case XML_PI_NODE:
2276 if (cur->content != NULL)
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002277#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardb96e6431999-08-29 21:02:19 +00002278 return(xmlStrdup(cur->content));
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002279#else
2280 return(xmlStrdup(xmlBufferContent(cur->content)));
2281#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +00002282 return(NULL);
Daniel Veillard16253641998-10-28 22:58:05 +00002283 case XML_ENTITY_REF_NODE:
2284 case XML_ENTITY_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002285 case XML_COMMENT_NODE:
2286 case XML_DOCUMENT_NODE:
Daniel Veillard7c1206f1999-10-14 09:10:25 +00002287 case XML_HTML_DOCUMENT_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002288 case XML_DOCUMENT_TYPE_NODE:
2289 case XML_NOTATION_NODE:
2290 return(NULL);
Daniel Veillardb05deb71999-08-10 19:04:08 +00002291 case XML_CDATA_SECTION_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002292 case XML_TEXT_NODE:
2293 if (cur->content != NULL)
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002294#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard16253641998-10-28 22:58:05 +00002295 return(xmlStrdup(cur->content));
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002296#else
2297 return(xmlStrdup(xmlBufferContent(cur->content)));
2298#endif
Daniel Veillard16253641998-10-28 22:58:05 +00002299 return(NULL);
2300 }
2301 return(NULL);
2302}
2303
2304/**
Daniel Veillard97b58771998-10-20 06:14:16 +00002305 * xmlNodeSetContent:
2306 * @cur: the node being modified
2307 * @content: the new value of the content
2308 *
2309 * Replace the content of a node.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002310 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002311void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002312xmlNodeSetContent(xmlNodePtr cur, const xmlChar *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002313 if (cur == NULL) {
2314 fprintf(stderr, "xmlNodeSetContent : node == NULL\n");
2315 return;
2316 }
Daniel Veillard16253641998-10-28 22:58:05 +00002317 switch (cur->type) {
2318 case XML_DOCUMENT_FRAG_NODE:
2319 case XML_ELEMENT_NODE:
2320 if (cur->content != NULL) {
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002321#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard6454aec1999-09-02 22:04:43 +00002322 xmlFree(cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002323#else
2324 xmlBufferFree(cur->content);
2325#endif
Daniel Veillard16253641998-10-28 22:58:05 +00002326 cur->content = NULL;
2327 }
Daniel Veillard6454aec1999-09-02 22:04:43 +00002328 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillard16253641998-10-28 22:58:05 +00002329 cur->childs = xmlStringGetNodeList(cur->doc, content);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002330 UPDATE_LAST_CHILD(cur)
Daniel Veillard16253641998-10-28 22:58:05 +00002331 break;
2332 case XML_ATTRIBUTE_NODE:
2333 break;
2334 case XML_TEXT_NODE:
2335 case XML_CDATA_SECTION_NODE:
2336 case XML_ENTITY_REF_NODE:
2337 case XML_ENTITY_NODE:
2338 case XML_PI_NODE:
2339 case XML_COMMENT_NODE:
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002340 if (cur->content != NULL) {
2341#ifndef XML_USE_BUFFER_CONTENT
2342 xmlFree(cur->content);
2343#else
2344 xmlBufferFree(cur->content);
2345#endif
2346 }
Daniel Veillard6454aec1999-09-02 22:04:43 +00002347 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002348 cur->last = cur->childs = NULL;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002349 if (content != NULL) {
2350#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard16253641998-10-28 22:58:05 +00002351 cur->content = xmlStrdup(content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002352#else
2353 cur->content = xmlBufferCreateSize(0);
2354 xmlBufferSetAllocationScheme(cur->content,
2355 xmlGetBufferAllocationScheme());
2356 xmlBufferAdd(cur->content, content, -1);
2357#endif
2358 } else
Daniel Veillard16253641998-10-28 22:58:05 +00002359 cur->content = NULL;
Daniel Veillardb96e6431999-08-29 21:02:19 +00002360 break;
Daniel Veillard16253641998-10-28 22:58:05 +00002361 case XML_DOCUMENT_NODE:
Daniel Veillard7c1206f1999-10-14 09:10:25 +00002362 case XML_HTML_DOCUMENT_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002363 case XML_DOCUMENT_TYPE_NODE:
2364 break;
2365 case XML_NOTATION_NODE:
2366 break;
2367 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002368}
2369
Daniel Veillard97b58771998-10-20 06:14:16 +00002370/**
2371 * xmlNodeSetContentLen:
2372 * @cur: the node being modified
2373 * @content: the new value of the content
2374 * @len: the size of @content
2375 *
2376 * Replace the content of a node.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002377 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002378void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002379xmlNodeSetContentLen(xmlNodePtr cur, const xmlChar *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002380 if (cur == NULL) {
Daniel Veillard16253641998-10-28 22:58:05 +00002381 fprintf(stderr, "xmlNodeSetContentLen : node == NULL\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002382 return;
2383 }
Daniel Veillard16253641998-10-28 22:58:05 +00002384 switch (cur->type) {
2385 case XML_DOCUMENT_FRAG_NODE:
2386 case XML_ELEMENT_NODE:
2387 if (cur->content != NULL) {
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002388#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard6454aec1999-09-02 22:04:43 +00002389 xmlFree(cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002390#else
2391 xmlBufferFree(cur->content);
2392#endif
Daniel Veillard16253641998-10-28 22:58:05 +00002393 cur->content = NULL;
2394 }
Daniel Veillard6454aec1999-09-02 22:04:43 +00002395 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillard16253641998-10-28 22:58:05 +00002396 cur->childs = xmlStringLenGetNodeList(cur->doc, content, len);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002397 UPDATE_LAST_CHILD(cur)
Daniel Veillard16253641998-10-28 22:58:05 +00002398 break;
2399 case XML_ATTRIBUTE_NODE:
2400 break;
2401 case XML_TEXT_NODE:
2402 case XML_CDATA_SECTION_NODE:
2403 case XML_ENTITY_REF_NODE:
2404 case XML_ENTITY_NODE:
2405 case XML_PI_NODE:
2406 case XML_COMMENT_NODE:
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002407 case XML_NOTATION_NODE:
2408 if (cur->content != NULL) {
2409#ifndef XML_USE_BUFFER_CONTENT
2410 xmlFree(cur->content);
2411#else
2412 xmlBufferFree(cur->content);
2413#endif
2414 }
Daniel Veillard6454aec1999-09-02 22:04:43 +00002415 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002416 cur->childs = cur->last = NULL;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002417 if (content != NULL) {
2418#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard16253641998-10-28 22:58:05 +00002419 cur->content = xmlStrndup(content, len);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002420#else
2421 cur->content = xmlBufferCreateSize(len);
2422 xmlBufferSetAllocationScheme(cur->content,
2423 xmlGetBufferAllocationScheme());
2424 xmlBufferAdd(cur->content, content, len);
2425#endif
2426 } else
Daniel Veillard16253641998-10-28 22:58:05 +00002427 cur->content = NULL;
Daniel Veillardb96e6431999-08-29 21:02:19 +00002428 break;
Daniel Veillard16253641998-10-28 22:58:05 +00002429 case XML_DOCUMENT_NODE:
Daniel Veillard7c1206f1999-10-14 09:10:25 +00002430 case XML_HTML_DOCUMENT_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002431 case XML_DOCUMENT_TYPE_NODE:
2432 break;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002433 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002434}
2435
Daniel Veillard97b58771998-10-20 06:14:16 +00002436/**
2437 * xmlNodeAddContentLen:
2438 * @cur: the node being modified
2439 * @content: extra content
2440 * @len: the size of @content
2441 *
2442 * Append the extra substring to the node content.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002443 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002444void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002445xmlNodeAddContentLen(xmlNodePtr cur, const xmlChar *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002446 if (cur == NULL) {
Daniel Veillard16253641998-10-28 22:58:05 +00002447 fprintf(stderr, "xmlNodeAddContentLen : node == NULL\n");
2448 return;
2449 }
2450 if (len <= 0) return;
2451 switch (cur->type) {
2452 case XML_DOCUMENT_FRAG_NODE:
2453 case XML_ELEMENT_NODE: {
2454 xmlNodePtr last = NULL, new;
2455
2456 if (cur->childs != NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002457 last = cur->last;
Daniel Veillard16253641998-10-28 22:58:05 +00002458 } else {
2459 if (cur->content != NULL) {
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002460#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard16253641998-10-28 22:58:05 +00002461 cur->childs = xmlStringGetNodeList(cur->doc, cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002462#else
2463 cur->childs = xmlStringGetNodeList(cur->doc,
2464 xmlBufferContent(cur->content));
2465#endif
Daniel Veillard1e346af1999-02-22 10:33:01 +00002466 UPDATE_LAST_CHILD(cur)
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002467#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard6454aec1999-09-02 22:04:43 +00002468 xmlFree(cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002469#else
2470 xmlBufferFree(cur->content);
2471#endif
Daniel Veillard16253641998-10-28 22:58:05 +00002472 cur->content = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002473 last = cur->last;
Daniel Veillard16253641998-10-28 22:58:05 +00002474 }
2475 }
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002476 new = xmlNewTextLen(content, len);
Daniel Veillard16253641998-10-28 22:58:05 +00002477 if (new != NULL) {
2478 xmlAddChild(cur, new);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002479 if ((last != NULL) && (last->next == new)) {
Daniel Veillard16253641998-10-28 22:58:05 +00002480 xmlTextMerge(last, new);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002481 }
Daniel Veillard16253641998-10-28 22:58:05 +00002482 }
2483 break;
2484 }
2485 case XML_ATTRIBUTE_NODE:
2486 break;
2487 case XML_TEXT_NODE:
2488 case XML_CDATA_SECTION_NODE:
2489 case XML_ENTITY_REF_NODE:
2490 case XML_ENTITY_NODE:
2491 case XML_PI_NODE:
2492 case XML_COMMENT_NODE:
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002493 case XML_NOTATION_NODE:
2494 if (content != NULL) {
2495#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard16253641998-10-28 22:58:05 +00002496 cur->content = xmlStrncat(cur->content, content, len);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002497#else
2498 xmlBufferAdd(cur->content, content, len);
2499#endif
2500 }
Daniel Veillard16253641998-10-28 22:58:05 +00002501 case XML_DOCUMENT_NODE:
Daniel Veillard7c1206f1999-10-14 09:10:25 +00002502 case XML_HTML_DOCUMENT_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002503 case XML_DOCUMENT_TYPE_NODE:
2504 break;
Daniel Veillard16253641998-10-28 22:58:05 +00002505 }
2506}
2507
2508/**
2509 * xmlNodeAddContent:
2510 * @cur: the node being modified
2511 * @content: extra content
2512 *
2513 * Append the extra substring to the node content.
2514 */
2515void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002516xmlNodeAddContent(xmlNodePtr cur, const xmlChar *content) {
Daniel Veillard16253641998-10-28 22:58:05 +00002517 int len;
2518
2519 if (cur == NULL) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002520 fprintf(stderr, "xmlNodeAddContent : node == NULL\n");
2521 return;
2522 }
Daniel Veillard16253641998-10-28 22:58:05 +00002523 if (content == NULL) return;
2524 len = xmlStrlen(content);
2525 xmlNodeAddContentLen(cur, content, len);
2526}
2527
2528/**
2529 * xmlTextMerge:
2530 * @first: the first text node
2531 * @second: the second text node being merged
2532 *
2533 * Merge two text nodes into one
Daniel Veillard1e346af1999-02-22 10:33:01 +00002534 * Returns the first text node augmented
Daniel Veillard16253641998-10-28 22:58:05 +00002535 */
2536xmlNodePtr
2537xmlTextMerge(xmlNodePtr first, xmlNodePtr second) {
2538 if (first == NULL) return(second);
2539 if (second == NULL) return(first);
2540 if (first->type != XML_TEXT_NODE) return(first);
2541 if (second->type != XML_TEXT_NODE) return(first);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002542#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard16253641998-10-28 22:58:05 +00002543 xmlNodeAddContent(first, second->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002544#else
2545 xmlNodeAddContent(first, xmlBufferContent(second->content));
2546#endif
Daniel Veillard16253641998-10-28 22:58:05 +00002547 xmlUnlinkNode(second);
2548 xmlFreeNode(second);
2549 return(first);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002550}
2551
Daniel Veillard97b58771998-10-20 06:14:16 +00002552/**
Daniel Veillardb96e6431999-08-29 21:02:19 +00002553 * xmlGetNsList:
2554 * @doc: the document
2555 * @node: the current node
2556 *
2557 * Search all the namespace applying to a given element.
2558 * Returns an NULL terminated array of all the xmlNsPtr found
2559 * that need to be freed by the caller or NULL if no
2560 * namespace if defined
2561 */
2562xmlNsPtr *
2563xmlGetNsList(xmlDocPtr doc, xmlNodePtr node) {
2564 xmlNsPtr cur;
2565 xmlNsPtr *ret = NULL;
2566 int nbns = 0;
2567 int maxns = 10;
2568 int i;
2569
2570 while (node != NULL) {
2571 cur = node->nsDef;
2572 while (cur != NULL) {
2573 if (ret == NULL) {
Daniel Veillard6454aec1999-09-02 22:04:43 +00002574 ret = (xmlNsPtr *) xmlMalloc((maxns + 1) * sizeof(xmlNsPtr));
Daniel Veillardb96e6431999-08-29 21:02:19 +00002575 if (ret == NULL) {
2576 fprintf(stderr, "xmlGetNsList : out of memory!\n");
2577 return(NULL);
2578 }
2579 ret[nbns] = NULL;
2580 }
2581 for (i = 0;i < nbns;i++) {
2582 if ((cur->prefix == ret[i]->prefix) ||
2583 (!xmlStrcmp(cur->prefix, ret[i]->prefix))) break;
2584 }
2585 if (i >= nbns) {
2586 if (nbns >= maxns) {
2587 maxns *= 2;
Daniel Veillard6454aec1999-09-02 22:04:43 +00002588 ret = (xmlNsPtr *) xmlRealloc(ret,
Daniel Veillardb96e6431999-08-29 21:02:19 +00002589 (maxns + 1) * sizeof(xmlNsPtr));
2590 if (ret == NULL) {
2591 fprintf(stderr, "xmlGetNsList : realloc failed!\n");
2592 return(NULL);
2593 }
2594 }
2595 ret[nbns++] = cur;
2596 ret[nbns] = NULL;
2597 }
2598
2599 cur = cur->next;
2600 }
2601 node = node->parent;
2602 }
2603 return(ret);
2604}
2605
2606/**
Daniel Veillard97b58771998-10-20 06:14:16 +00002607 * xmlSearchNs:
2608 * @doc: the document
2609 * @node: the current node
2610 * @nameSpace: the namespace string
Daniel Veillard260a68f1998-08-13 03:39:55 +00002611 *
Daniel Veillard97b58771998-10-20 06:14:16 +00002612 * Search a Ns registered under a given name space for a document.
2613 * recurse on the parents until it finds the defined namespace
2614 * or return NULL otherwise.
2615 * @nameSpace can be NULL, this is a search for the default namespace.
Daniel Veillard1e346af1999-02-22 10:33:01 +00002616 * Returns the namespace pointer or NULL.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002617 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002618xmlNsPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002619xmlSearchNs(xmlDocPtr doc, xmlNodePtr node, const xmlChar *nameSpace) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002620 xmlNsPtr cur;
2621
Daniel Veillard10a2c651999-12-12 13:03:50 +00002622 if ((node == NULL) || (nameSpace == NULL)) return(NULL);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002623 while (node != NULL) {
2624 cur = node->nsDef;
2625 while (cur != NULL) {
2626 if ((cur->prefix == NULL) && (nameSpace == NULL))
2627 return(cur);
2628 if ((cur->prefix != NULL) && (nameSpace != NULL) &&
2629 (!xmlStrcmp(cur->prefix, nameSpace)))
2630 return(cur);
2631 cur = cur->next;
2632 }
2633 node = node->parent;
2634 }
Daniel Veillard10a2c651999-12-12 13:03:50 +00002635#if 0
2636 /* Removed support for old namespaces */
Daniel Veillard260a68f1998-08-13 03:39:55 +00002637 if (doc != NULL) {
2638 cur = doc->oldNs;
2639 while (cur != NULL) {
2640 if ((cur->prefix != NULL) && (nameSpace != NULL) &&
2641 (!xmlStrcmp(cur->prefix, nameSpace)))
2642 return(cur);
2643 cur = cur->next;
2644 }
2645 }
Daniel Veillard10a2c651999-12-12 13:03:50 +00002646#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00002647 return(NULL);
2648}
2649
Daniel Veillard97b58771998-10-20 06:14:16 +00002650/**
2651 * xmlSearchNsByHref:
2652 * @doc: the document
2653 * @node: the current node
2654 * @href: the namespace value
2655 *
2656 * Search a Ns aliasing a given URI. Recurse on the parents until it finds
2657 * the defined namespace or return NULL otherwise.
Daniel Veillard1e346af1999-02-22 10:33:01 +00002658 * Returns the namespace pointer or NULL.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002659 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002660xmlNsPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002661xmlSearchNsByHref(xmlDocPtr doc, xmlNodePtr node, const xmlChar *href) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002662 xmlNsPtr cur;
2663
Daniel Veillard10a2c651999-12-12 13:03:50 +00002664 if ((node == NULL) || (href == NULL)) return(NULL);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002665 while (node != NULL) {
2666 cur = node->nsDef;
2667 while (cur != NULL) {
2668 if ((cur->href != NULL) && (href != NULL) &&
2669 (!xmlStrcmp(cur->href, href)))
2670 return(cur);
2671 cur = cur->next;
2672 }
2673 node = node->parent;
2674 }
Daniel Veillard10a2c651999-12-12 13:03:50 +00002675#if 0
2676 /* Removed support for old namespaces */
Daniel Veillard260a68f1998-08-13 03:39:55 +00002677 if (doc != NULL) {
2678 cur = doc->oldNs;
2679 while (cur != NULL) {
2680 if ((cur->href != NULL) && (href != NULL) &&
2681 (!xmlStrcmp(cur->href, href)))
2682 return(cur);
2683 cur = cur->next;
2684 }
2685 }
Daniel Veillard10a2c651999-12-12 13:03:50 +00002686#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00002687 return(NULL);
2688}
2689
Daniel Veillard97b58771998-10-20 06:14:16 +00002690/**
2691 * xmlGetProp:
2692 * @node: the node
2693 * @name: the attribute name
2694 *
2695 * Search and get the value of an attribute associated to a node
Daniel Veillardccb09631998-10-27 06:21:04 +00002696 * This does the entity substitution.
Daniel Veillard10a2c651999-12-12 13:03:50 +00002697 * This function looks in DTD attribute declaration for #FIXED or
2698 * default declaration values unless DTD use has been turned off.
2699 *
Daniel Veillard1e346af1999-02-22 10:33:01 +00002700 * Returns the attribute value or NULL if not found.
Daniel Veillarda819dac1999-11-24 18:04:22 +00002701 * It's up to the caller to free the memory.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002702 */
Daniel Veillarda819dac1999-11-24 18:04:22 +00002703xmlChar *
2704xmlGetProp(xmlNodePtr node, const xmlChar *name) {
Daniel Veillard10a2c651999-12-12 13:03:50 +00002705 xmlAttrPtr prop;
2706 xmlDocPtr doc;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002707
Daniel Veillard10a2c651999-12-12 13:03:50 +00002708 if ((node == NULL) || (name == NULL)) return(NULL);
2709 /*
2710 * Check on the properties attached to the node
2711 */
2712 prop = node->properties;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002713 while (prop != NULL) {
Daniel Veillard68178931999-02-08 18:34:36 +00002714 if (!xmlStrcmp(prop->name, name)) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002715 xmlChar *ret;
Daniel Veillard6800ef31999-02-08 18:33:22 +00002716
2717 ret = xmlNodeListGetString(node->doc, prop->val, 1);
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002718 if (ret == NULL) return(xmlStrdup((xmlChar *)""));
Daniel Veillard6800ef31999-02-08 18:33:22 +00002719 return(ret);
Daniel Veillard68178931999-02-08 18:34:36 +00002720 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002721 prop = prop->next;
2722 }
Daniel Veillard10a2c651999-12-12 13:03:50 +00002723 if (!xmlCheckDTD) return(NULL);
2724
2725 /*
2726 * Check if there is a default declaration in the internal
2727 * or external subsets
2728 */
2729 doc = node->doc;
2730 if (doc != NULL) {
2731 xmlAttributePtr attrDecl;
2732 if (doc->intSubset != NULL) {
2733 attrDecl = xmlGetDtdAttrDesc(doc->intSubset, node->name, name);
2734 if ((attrDecl == NULL) && (doc->extSubset != NULL))
2735 attrDecl = xmlGetDtdAttrDesc(doc->extSubset, node->name, name);
2736 return(xmlStrdup(attrDecl->defaultValue));
2737 }
2738 }
2739 return(NULL);
2740}
2741
2742/**
2743 * xmlGetNsProp:
2744 * @node: the node
2745 * @name: the attribute name
2746 * @namespace: the URI of the namespace
2747 *
2748 * Search and get the value of an attribute associated to a node
2749 * This attribute has to be anchored in the namespace specified.
2750 * This does the entity substitution.
2751 * This function looks in DTD attribute declaration for #FIXED or
2752 * default declaration values unless DTD use has been turned off.
2753 *
2754 * Returns the attribute value or NULL if not found.
2755 * It's up to the caller to free the memory.
2756 */
2757xmlChar *
2758xmlGetNsProp(xmlNodePtr node, const xmlChar *name, const xmlChar *namespace) {
2759 xmlAttrPtr prop = node->properties;
2760 xmlDocPtr doc;
2761 xmlNsPtr ns;
2762
2763 if (namespace == NULL)
2764 return(xmlGetProp(node, name));
2765 while (prop != NULL) {
2766 if ((!xmlStrcmp(prop->name, name)) &&
2767 (prop->ns != NULL) && (!xmlStrcmp(prop->ns->href, namespace))) {
2768 xmlChar *ret;
2769
2770 ret = xmlNodeListGetString(node->doc, prop->val, 1);
2771 if (ret == NULL) return(xmlStrdup((xmlChar *)""));
2772 return(ret);
2773 }
2774 prop = prop->next;
2775 }
2776 if (!xmlCheckDTD) return(NULL);
2777
2778 /*
2779 * Check if there is a default declaration in the internal
2780 * or external subsets
2781 */
2782 doc = node->doc;
2783 if (doc != NULL) {
2784 xmlAttributePtr attrDecl;
2785 if (doc->intSubset != NULL) {
2786 attrDecl = xmlGetDtdAttrDesc(doc->intSubset, node->name, name);
2787 if ((attrDecl == NULL) && (doc->extSubset != NULL))
2788 attrDecl = xmlGetDtdAttrDesc(doc->extSubset, node->name, name);
2789
2790 if (attrDecl->prefix != NULL) {
2791 /*
2792 * The DTD declaration only allows a prefix search
2793 */
2794 ns = xmlSearchNs(doc, node, attrDecl->prefix);
2795 if ((ns != NULL) && (!xmlStrcmp(ns->href, namespace)))
2796 return(xmlStrdup(attrDecl->defaultValue));
2797 }
2798 }
2799 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002800 return(NULL);
2801}
2802
Daniel Veillard97b58771998-10-20 06:14:16 +00002803/**
Daniel Veillardccb09631998-10-27 06:21:04 +00002804 * xmlSetProp:
Daniel Veillard97b58771998-10-20 06:14:16 +00002805 * @node: the node
2806 * @name: the attribute name
2807 * @value: the attribute value
2808 *
2809 * Set (or reset) an attribute carried by a node.
Daniel Veillard1e346af1999-02-22 10:33:01 +00002810 * Returns the attribute pointer.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002811 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002812xmlAttrPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002813xmlSetProp(xmlNodePtr node, const xmlChar *name, const xmlChar *value) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002814 xmlAttrPtr prop = node->properties;
2815
2816 while (prop != NULL) {
2817 if (!xmlStrcmp(prop->name, name)) {
Daniel Veillardccb09631998-10-27 06:21:04 +00002818 if (prop->val != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +00002819 xmlFreeNodeList(prop->val);
Daniel Veillardccb09631998-10-27 06:21:04 +00002820 prop->val = NULL;
Daniel Veillard51e3b151999-11-12 17:02:31 +00002821 if (value != NULL) {
2822 xmlChar *buffer;
2823 buffer = xmlEncodeEntitiesReentrant(node->doc, value);
2824 prop->val = xmlStringGetNodeList(node->doc, buffer);
2825 xmlFree(buffer);
2826 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002827 return(prop);
2828 }
2829 prop = prop->next;
2830 }
2831 prop = xmlNewProp(node, name, value);
2832 return(prop);
2833}
2834
Daniel Veillard97b58771998-10-20 06:14:16 +00002835/**
2836 * xmlNodeIsText:
2837 * @node: the node
2838 *
2839 * Is this node a Text node ?
Daniel Veillard1e346af1999-02-22 10:33:01 +00002840 * Returns 1 yes, 0 no
Daniel Veillard260a68f1998-08-13 03:39:55 +00002841 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002842int
2843xmlNodeIsText(xmlNodePtr node) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002844 if (node == NULL) return(0);
2845
Daniel Veillard0bef1311998-10-14 02:36:47 +00002846 if (node->type == XML_TEXT_NODE) return(1);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002847 return(0);
2848}
2849
Daniel Veillard97b58771998-10-20 06:14:16 +00002850/**
Daniel Veillard1e346af1999-02-22 10:33:01 +00002851 * xmlTextConcat:
Daniel Veillard97b58771998-10-20 06:14:16 +00002852 * @node: the node
2853 * @content: the content
2854 * @len: @content lenght
2855 *
2856 * Concat the given string at the end of the existing node content
Daniel Veillard260a68f1998-08-13 03:39:55 +00002857 */
Daniel Veillard97b58771998-10-20 06:14:16 +00002858
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002859void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002860xmlTextConcat(xmlNodePtr node, const xmlChar *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002861 if (node == NULL) return;
2862
Daniel Veillard0bef1311998-10-14 02:36:47 +00002863 if (node->type != XML_TEXT_NODE) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002864 fprintf(stderr, "xmlTextConcat: node is not text\n");
2865 return;
2866 }
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002867#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard260a68f1998-08-13 03:39:55 +00002868 node->content = xmlStrncat(node->content, content, len);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002869#else
2870 xmlBufferAdd(node->content, content, len);
2871#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00002872}
2873
2874/************************************************************************
2875 * *
2876 * Output : to a FILE or in memory *
2877 * *
2878 ************************************************************************/
2879
Daniel Veillard5099ae81999-04-21 20:12:07 +00002880#define BASE_BUFFER_SIZE 4000
2881
2882/**
2883 * xmlBufferCreate:
2884 *
2885 * routine to create an XML buffer.
2886 * returns the new structure.
2887 */
2888xmlBufferPtr
2889xmlBufferCreate(void) {
2890 xmlBufferPtr ret;
2891
Daniel Veillard6454aec1999-09-02 22:04:43 +00002892 ret = (xmlBufferPtr) xmlMalloc(sizeof(xmlBuffer));
Daniel Veillard5099ae81999-04-21 20:12:07 +00002893 if (ret == NULL) {
2894 fprintf(stderr, "xmlBufferCreate : out of memory!\n");
2895 return(NULL);
2896 }
2897 ret->use = 0;
2898 ret->size = BASE_BUFFER_SIZE;
Daniel Veillard10a2c651999-12-12 13:03:50 +00002899 ret->alloc = xmlBufferAllocScheme;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002900 ret->content = (xmlChar *) xmlMalloc(ret->size * sizeof(xmlChar));
Daniel Veillard5099ae81999-04-21 20:12:07 +00002901 if (ret->content == NULL) {
2902 fprintf(stderr, "xmlBufferCreate : out of memory!\n");
Daniel Veillard6454aec1999-09-02 22:04:43 +00002903 xmlFree(ret);
Daniel Veillard5099ae81999-04-21 20:12:07 +00002904 return(NULL);
2905 }
2906 ret->content[0] = 0;
2907 return(ret);
2908}
2909
2910/**
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002911 * xmlBufferCreateSize:
2912 * @size: initial size of buffer
2913 *
2914 * routine to create an XML buffer.
2915 * returns the new structure.
2916 */
2917xmlBufferPtr
2918xmlBufferCreateSize(size_t size) {
2919 xmlBufferPtr ret;
2920
2921 ret = (xmlBufferPtr) xmlMalloc(sizeof(xmlBuffer));
2922 if (ret == NULL) {
2923 fprintf(stderr, "xmlBufferCreate : out of memory!\n");
2924 return(NULL);
2925 }
2926 ret->use = 0;
Daniel Veillard10a2c651999-12-12 13:03:50 +00002927 ret->alloc = xmlBufferAllocScheme;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002928 ret->size = (size ? size+2 : 0); /* +1 for ending null */
Daniel Veillard10a2c651999-12-12 13:03:50 +00002929 if (ret->size){
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002930 ret->content = (xmlChar *) xmlMalloc(ret->size * sizeof(xmlChar));
2931 if (ret->content == NULL) {
2932 fprintf(stderr, "xmlBufferCreate : out of memory!\n");
2933 xmlFree(ret);
2934 return(NULL);
2935 }
2936 ret->content[0] = 0;
2937 } else
2938 ret->content = NULL;
2939 return(ret);
2940}
2941
2942/**
2943 * xmlBufferAllocationScheme:
2944 * @buf: the buffer to free
2945 * @scheme: allocation scheme to use
2946 *
2947 * Sets the allocation scheme for this buffer
2948 */
2949void
2950xmlBufferSetAllocationScheme(xmlBufferPtr buf,
2951 xmlBufferAllocationScheme scheme) {
2952 if (buf == NULL) {
2953 fprintf(stderr, "xmlBufferSetAllocationScheme: buf == NULL\n");
2954 return;
2955 }
2956
2957 buf->alloc = scheme;
2958}
2959
2960/**
Daniel Veillard5099ae81999-04-21 20:12:07 +00002961 * xmlBufferFree:
2962 * @buf: the buffer to free
2963 *
2964 * Frees an XML buffer.
2965 */
2966void
2967xmlBufferFree(xmlBufferPtr buf) {
2968 if (buf == NULL) {
2969 fprintf(stderr, "xmlBufferFree: buf == NULL\n");
2970 return;
2971 }
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002972 if (buf->content != NULL) {
2973#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard5099ae81999-04-21 20:12:07 +00002974 memset(buf->content, -1, BASE_BUFFER_SIZE);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002975#else
2976 memset(buf->content, -1, buf->size);
2977#endif
Daniel Veillard6454aec1999-09-02 22:04:43 +00002978 xmlFree(buf->content);
Daniel Veillard5099ae81999-04-21 20:12:07 +00002979 }
2980 memset(buf, -1, sizeof(xmlBuffer));
Daniel Veillard6454aec1999-09-02 22:04:43 +00002981 xmlFree(buf);
Daniel Veillard5099ae81999-04-21 20:12:07 +00002982}
2983
2984/**
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002985 * xmlBufferEmpty:
2986 * @buf: the buffer
2987 *
2988 * empty a buffer.
2989 */
2990void
2991xmlBufferEmpty(xmlBufferPtr buf) {
2992 buf->use = 0;
2993 memset(buf->content, -1, buf->size);/* just for debug */
2994}
2995
2996/**
2997 * xmlBufferShrink:
2998 * @buf: the buffer to dump
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002999 * @len: the number of xmlChar to remove
Daniel Veillarde2d034d1999-07-27 19:52:06 +00003000 *
3001 * Remove the beginning of an XML buffer.
3002 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003003 * Returns the number of xmlChar removed, or -1 in case of failure.
Daniel Veillarde2d034d1999-07-27 19:52:06 +00003004 */
3005int
3006xmlBufferShrink(xmlBufferPtr buf, int len) {
3007 if (len == 0) return(0);
3008 if (len > buf->use) return(-1);
3009
3010 buf->use -= len;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003011 memmove(buf->content, &buf->content[len], buf->use * sizeof(xmlChar));
Daniel Veillarde2d034d1999-07-27 19:52:06 +00003012
3013 buf->content[buf->use] = 0;
3014 return(len);
3015}
3016
3017/**
Daniel Veillard5099ae81999-04-21 20:12:07 +00003018 * xmlBufferDump:
3019 * @file: the file output
3020 * @buf: the buffer to dump
3021 *
3022 * Dumps an XML buffer to a FILE *.
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003023 * Returns the number of xmlChar written
Daniel Veillard5099ae81999-04-21 20:12:07 +00003024 */
3025int
3026xmlBufferDump(FILE *file, xmlBufferPtr buf) {
3027 int ret;
3028
3029 if (buf == NULL) {
3030 fprintf(stderr, "xmlBufferDump: buf == NULL\n");
3031 return(0);
3032 }
3033 if (buf->content == NULL) {
3034 fprintf(stderr, "xmlBufferDump: buf->content == NULL\n");
3035 return(0);
3036 }
3037 if (file == NULL) file = stdout;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003038 ret = fwrite(buf->content, sizeof(xmlChar), buf->use, file);
Daniel Veillard5099ae81999-04-21 20:12:07 +00003039 return(ret);
3040}
3041
3042/**
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003043 * xmlBufferContent:
3044 * @buf: the buffer to resize
3045 *
3046 * Returns the internal content
3047 */
3048
3049const xmlChar*
3050xmlBufferContent(const xmlBufferPtr buf)
3051{
3052 if(!buf)
3053 return NULL;
3054
3055 return buf->content;
3056}
3057
3058/**
3059 * xmlBufferLength:
3060 * @buf: the buffer
3061 *
3062 * Returns the length of data in the internal content
3063 */
3064
3065int
3066xmlBufferLength(const xmlBufferPtr buf)
3067{
3068 if(!buf)
3069 return 0;
3070
3071 return buf->use;
3072}
3073
3074/**
3075 * xmlBufferResize:
3076 * @buf: the buffer to resize
3077 * @len: the desired size
3078 *
3079 * Resize a buffer to accomodate minimum size of <len>.
3080 *
3081 * Returns 0 in case of problems, 1 otherwise
3082 */
3083int
3084xmlBufferResize(xmlBufferPtr buf, int size)
3085{
3086 int newSize = (buf->size ? buf->size*2 : size);/*take care of empty case*/
3087 xmlChar* rebuf = NULL;
3088
3089 /* Don't resize if we don't have to */
3090 if(size < buf->size)
3091 return 1;
3092
3093 /* figure out new size */
3094 switch(buf->alloc){
3095 case XML_BUFFER_ALLOC_DOUBLEIT:
3096 while(size > newSize) newSize *= 2;
3097 break;
3098 case XML_BUFFER_ALLOC_EXACT:
3099 newSize = size+10;
3100 break;
3101 default:
3102 newSize = size+10;
3103 break;
3104 }
3105
3106 if (buf->content == NULL)
3107 rebuf = (xmlChar *) xmlMalloc(newSize * sizeof(xmlChar));
3108 else
3109 rebuf = (xmlChar *) xmlRealloc(buf->content,
3110 newSize * sizeof(xmlChar));
3111 if (rebuf == NULL) {
3112 fprintf(stderr, "xmlBufferAdd : out of memory!\n");
3113 return 0;
3114 }
3115 buf->content = rebuf;
3116 buf->size = newSize;
3117
3118 return 1;
3119}
3120/**
Daniel Veillard5099ae81999-04-21 20:12:07 +00003121 * xmlBufferAdd:
3122 * @buf: the buffer to dump
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003123 * @str: the xmlChar string
3124 * @len: the number of xmlChar to add
Daniel Veillard5099ae81999-04-21 20:12:07 +00003125 *
Daniel Veillard10a2c651999-12-12 13:03:50 +00003126 * Add a string range to an XML buffer. if len == -1, the lenght of
3127 * str is recomputed.
Daniel Veillard5099ae81999-04-21 20:12:07 +00003128 */
3129void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003130xmlBufferAdd(xmlBufferPtr buf, const xmlChar *str, int len) {
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003131 int l, needSize;
Daniel Veillard5099ae81999-04-21 20:12:07 +00003132
3133 if (str == NULL) {
3134 fprintf(stderr, "xmlBufferAdd: str == NULL\n");
3135 return;
3136 }
Daniel Veillard10a2c651999-12-12 13:03:50 +00003137 if (len < -1) {
3138 fprintf(stderr, "xmlBufferAdd: len < 0\n");
3139 return;
3140 }
3141 if (len == 0) return;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003142
3143 /* CJN What's this for??? */
Daniel Veillarde2d034d1999-07-27 19:52:06 +00003144 l = xmlStrlen(str);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003145 if (l < len){ len = l; printf("xmlBufferAdd bad length\n"); }
3146
3147 /* CJN 11.18.99 okay, now I'm using the length */
3148 if(len == -1) len = l;
3149
3150
Daniel Veillarde2d034d1999-07-27 19:52:06 +00003151 if (len <= 0) return;
Daniel Veillard5099ae81999-04-21 20:12:07 +00003152
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003153 needSize = buf->use + len + 2;
3154 if(needSize > buf->size){
3155 if(!xmlBufferResize(buf, needSize)){
3156 fprintf(stderr, "xmlBufferAdd : out of memory!\n");
3157 return;
3158 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003159 }
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003160
3161 memmove(&buf->content[buf->use], str, len*sizeof(xmlChar));
Daniel Veillarde2d034d1999-07-27 19:52:06 +00003162 buf->use += len;
3163 buf->content[buf->use] = 0;
Daniel Veillard5099ae81999-04-21 20:12:07 +00003164}
3165
3166/**
3167 * xmlBufferCat:
3168 * @buf: the buffer to dump
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003169 * @str: the xmlChar string
Daniel Veillard5099ae81999-04-21 20:12:07 +00003170 *
3171 * Append a zero terminated string to an XML buffer.
3172 */
3173void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003174xmlBufferCat(xmlBufferPtr buf, const xmlChar *str) {
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003175 if (str != NULL)
3176 xmlBufferAdd(buf, str, -1);
Daniel Veillard5099ae81999-04-21 20:12:07 +00003177}
3178
3179/**
3180 * xmlBufferCCat:
3181 * @buf: the buffer to dump
3182 * @str: the C char string
3183 *
3184 * Append a zero terminated C string to an XML buffer.
3185 */
3186void
3187xmlBufferCCat(xmlBufferPtr buf, const char *str) {
3188 const char *cur;
3189
3190 if (str == NULL) {
3191 fprintf(stderr, "xmlBufferAdd: str == NULL\n");
3192 return;
3193 }
3194 for (cur = str;*cur != 0;cur++) {
3195 if (buf->use + 10 >= buf->size) {
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003196 if(!xmlBufferResize(buf, buf->use+10)){
3197 fprintf(stderr, "xmlBufferCCat : out of memory!\n");
3198 return;
3199 }
3200 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003201 buf->content[buf->use++] = *cur;
3202 }
3203}
Daniel Veillard260a68f1998-08-13 03:39:55 +00003204
Daniel Veillard97b58771998-10-20 06:14:16 +00003205/**
3206 * xmlBufferWriteCHAR:
Daniel Veillard5099ae81999-04-21 20:12:07 +00003207 * @buf: the XML buffer
Daniel Veillard97b58771998-10-20 06:14:16 +00003208 * @string: the string to add
3209 *
3210 * routine which manage and grows an output buffer. This one add
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003211 * xmlChars at the end of the buffer.
Daniel Veillard97b58771998-10-20 06:14:16 +00003212 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003213void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003214xmlBufferWriteCHAR(xmlBufferPtr buf, const xmlChar *string) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003215 xmlBufferCat(buf, string);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003216}
3217
Daniel Veillard97b58771998-10-20 06:14:16 +00003218/**
3219 * xmlBufferWriteChar:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003220 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003221 * @string: the string to add
3222 *
3223 * routine which manage and grows an output buffer. This one add
3224 * C chars at the end of the array.
3225 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003226void
Daniel Veillard5099ae81999-04-21 20:12:07 +00003227xmlBufferWriteChar(xmlBufferPtr buf, const char *string) {
3228 xmlBufferCCat(buf, string);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003229}
3230
Daniel Veillard5099ae81999-04-21 20:12:07 +00003231
Daniel Veillard97b58771998-10-20 06:14:16 +00003232/**
Daniel Veillard011b63c1999-06-02 17:44:04 +00003233 * xmlBufferWriteQuotedString:
3234 * @buf: the XML buffer output
3235 * @string: the string to add
3236 *
3237 * routine which manage and grows an output buffer. This one writes
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003238 * a quoted or double quoted xmlChar string, checking first if it holds
Daniel Veillard011b63c1999-06-02 17:44:04 +00003239 * quote or double-quotes internally
3240 */
3241void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003242xmlBufferWriteQuotedString(xmlBufferPtr buf, const xmlChar *string) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00003243 if (xmlStrchr(string, '"')) {
3244 if (xmlStrchr(string, '\'')) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00003245 fprintf(stderr,
3246 "xmlBufferWriteQuotedString: string contains quote and double-quotes !\n");
3247 }
3248 xmlBufferCCat(buf, "'");
3249 xmlBufferCat(buf, string);
3250 xmlBufferCCat(buf, "'");
3251 } else {
3252 xmlBufferCCat(buf, "\"");
3253 xmlBufferCat(buf, string);
3254 xmlBufferCCat(buf, "\"");
3255 }
3256}
3257
3258
3259/**
Daniel Veillard97b58771998-10-20 06:14:16 +00003260 * xmlGlobalNsDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003261 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003262 * @cur: a namespace
3263 *
3264 * Dump a global Namespace, this is the old version based on PIs.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003265 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003266static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00003267xmlGlobalNsDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003268 if (cur == NULL) {
3269 fprintf(stderr, "xmlGlobalNsDump : Ns == NULL\n");
3270 return;
3271 }
3272 if (cur->type == XML_GLOBAL_NAMESPACE) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003273 xmlBufferWriteChar(buf, "<?namespace");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003274 if (cur->href != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00003275 xmlBufferWriteChar(buf, " href=");
3276 xmlBufferWriteQuotedString(buf, cur->href);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003277 }
3278 if (cur->prefix != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00003279 xmlBufferWriteChar(buf, " AS=");
3280 xmlBufferWriteQuotedString(buf, cur->prefix);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003281 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003282 xmlBufferWriteChar(buf, "?>\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003283 }
3284}
3285
Daniel Veillard97b58771998-10-20 06:14:16 +00003286/**
3287 * xmlGlobalNsListDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003288 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003289 * @cur: the first namespace
3290 *
3291 * Dump a list of global Namespace, this is the old version based on PIs.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003292 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003293static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00003294xmlGlobalNsListDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003295 while (cur != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003296 xmlGlobalNsDump(buf, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003297 cur = cur->next;
3298 }
3299}
3300
Daniel Veillard97b58771998-10-20 06:14:16 +00003301/**
3302 * xmlNsDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003303 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003304 * @cur: a namespace
3305 *
Daniel Veillard260a68f1998-08-13 03:39:55 +00003306 * Dump a local Namespace definition.
Daniel Veillard97b58771998-10-20 06:14:16 +00003307 * Should be called in the context of attributes dumps.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003308 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003309static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00003310xmlNsDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003311 if (cur == NULL) {
3312 fprintf(stderr, "xmlNsDump : Ns == NULL\n");
3313 return;
3314 }
3315 if (cur->type == XML_LOCAL_NAMESPACE) {
3316 /* Within the context of an element attributes */
3317 if (cur->prefix != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003318 xmlBufferWriteChar(buf, " xmlns:");
3319 xmlBufferWriteCHAR(buf, cur->prefix);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003320 } else
Daniel Veillard5099ae81999-04-21 20:12:07 +00003321 xmlBufferWriteChar(buf, " xmlns");
Daniel Veillard011b63c1999-06-02 17:44:04 +00003322 xmlBufferWriteChar(buf, "=");
3323 xmlBufferWriteQuotedString(buf, cur->href);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003324 }
3325}
3326
Daniel Veillard97b58771998-10-20 06:14:16 +00003327/**
3328 * xmlNsListDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003329 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003330 * @cur: the first namespace
3331 *
3332 * Dump a list of local Namespace definitions.
3333 * Should be called in the context of attributes dumps.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003334 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003335static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00003336xmlNsListDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003337 while (cur != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003338 xmlNsDump(buf, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003339 cur = cur->next;
3340 }
3341}
3342
Daniel Veillard97b58771998-10-20 06:14:16 +00003343/**
3344 * xmlDtdDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003345 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003346 * @doc: the document
3347 *
3348 * Dump the XML document DTD, if any.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003349 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003350static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00003351xmlDtdDump(xmlBufferPtr buf, xmlDocPtr doc) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003352 xmlDtdPtr cur = doc->intSubset;
Daniel Veillard260a68f1998-08-13 03:39:55 +00003353
3354 if (cur == NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003355 fprintf(stderr, "xmlDtdDump : no internal subset\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003356 return;
3357 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003358 xmlBufferWriteChar(buf, "<!DOCTYPE ");
3359 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003360 if (cur->ExternalID != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00003361 xmlBufferWriteChar(buf, " PUBLIC ");
3362 xmlBufferWriteQuotedString(buf, cur->ExternalID);
3363 xmlBufferWriteChar(buf, " ");
3364 xmlBufferWriteQuotedString(buf, cur->SystemID);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003365 } else if (cur->SystemID != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00003366 xmlBufferWriteChar(buf, " SYSTEM ");
3367 xmlBufferWriteQuotedString(buf, cur->SystemID);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003368 }
Daniel Veillard1e346af1999-02-22 10:33:01 +00003369 if ((cur->entities == NULL) && (cur->elements == NULL) &&
3370 (cur->attributes == NULL) && (cur->notations == NULL)) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003371 xmlBufferWriteChar(buf, ">\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003372 return;
3373 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003374 xmlBufferWriteChar(buf, " [\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003375 if (cur->entities != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00003376 xmlDumpEntitiesTable(buf, (xmlEntitiesTablePtr) cur->entities);
Daniel Veillard1e346af1999-02-22 10:33:01 +00003377 if (cur->notations != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00003378 xmlDumpNotationTable(buf, (xmlNotationTablePtr) cur->notations);
Daniel Veillard3b9def11999-01-31 22:15:06 +00003379 if (cur->elements != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00003380 xmlDumpElementTable(buf, (xmlElementTablePtr) cur->elements);
Daniel Veillard1e346af1999-02-22 10:33:01 +00003381 if (cur->attributes != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00003382 xmlDumpAttributeTable(buf, (xmlAttributeTablePtr) cur->attributes);
3383 xmlBufferWriteChar(buf, "]");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003384
Daniel Veillard5099ae81999-04-21 20:12:07 +00003385 xmlBufferWriteChar(buf, ">\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003386}
3387
Daniel Veillard97b58771998-10-20 06:14:16 +00003388/**
3389 * xmlAttrDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003390 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003391 * @doc: the document
3392 * @cur: the attribute pointer
3393 *
3394 * Dump an XML attribute
Daniel Veillard260a68f1998-08-13 03:39:55 +00003395 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003396static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00003397xmlAttrDump(xmlBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003398 xmlChar *value;
Daniel Veillardccb09631998-10-27 06:21:04 +00003399
Daniel Veillard260a68f1998-08-13 03:39:55 +00003400 if (cur == NULL) {
3401 fprintf(stderr, "xmlAttrDump : property == NULL\n");
3402 return;
3403 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003404 xmlBufferWriteChar(buf, " ");
Daniel Veillardb96e6431999-08-29 21:02:19 +00003405 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
3406 xmlBufferWriteCHAR(buf, cur->ns->prefix);
3407 xmlBufferWriteChar(buf, ":");
3408 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003409 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillardccb09631998-10-27 06:21:04 +00003410 value = xmlNodeListGetString(doc, cur->val, 0);
3411 if (value) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00003412 xmlBufferWriteChar(buf, "=");
3413 xmlBufferWriteQuotedString(buf, value);
Daniel Veillard6454aec1999-09-02 22:04:43 +00003414 xmlFree(value);
Daniel Veillard726c7e31999-02-08 15:13:10 +00003415 } else {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003416 xmlBufferWriteChar(buf, "=\"\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003417 }
3418}
3419
Daniel Veillard97b58771998-10-20 06:14:16 +00003420/**
3421 * xmlAttrListDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003422 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003423 * @doc: the document
3424 * @cur: the first attribute pointer
3425 *
3426 * Dump a list of XML attributes
Daniel Veillard260a68f1998-08-13 03:39:55 +00003427 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003428static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00003429xmlAttrListDump(xmlBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003430 if (cur == NULL) {
3431 fprintf(stderr, "xmlAttrListDump : property == NULL\n");
3432 return;
3433 }
3434 while (cur != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003435 xmlAttrDump(buf, doc, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003436 cur = cur->next;
3437 }
3438}
3439
Daniel Veillard260a68f1998-08-13 03:39:55 +00003440
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003441static void
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003442xmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
3443 int format);
Daniel Veillard97b58771998-10-20 06:14:16 +00003444/**
3445 * xmlNodeListDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003446 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003447 * @doc: the document
3448 * @cur: the first node
3449 * @level: the imbrication level for indenting
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003450 * @format: is formatting allowed
Daniel Veillard97b58771998-10-20 06:14:16 +00003451 *
3452 * Dump an XML node list, recursive behaviour,children are printed too.
3453 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003454static void
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003455xmlNodeListDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
3456 int format) {
3457 int i;
Daniel Veillardccb09631998-10-27 06:21:04 +00003458
Daniel Veillard260a68f1998-08-13 03:39:55 +00003459 if (cur == NULL) {
3460 fprintf(stderr, "xmlNodeListDump : node == NULL\n");
3461 return;
3462 }
3463 while (cur != NULL) {
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003464 if ((format) && (xmlIndentTreeOutput) &&
3465 (cur->type == XML_ELEMENT_NODE))
3466 for (i = 0;i < level;i++)
3467 xmlBufferWriteChar(buf, " ");
3468 xmlNodeDump(buf, doc, cur, level, format);
3469 if (format) {
3470 xmlBufferWriteChar(buf, "\n");
Daniel Veillardccb09631998-10-27 06:21:04 +00003471 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003472 cur = cur->next;
3473 }
3474}
3475
Daniel Veillard97b58771998-10-20 06:14:16 +00003476/**
Daniel Veillardccb09631998-10-27 06:21:04 +00003477 * xmlNodeDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003478 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003479 * @doc: the document
3480 * @cur: the current node
3481 * @level: the imbrication level for indenting
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003482 * @format: is formatting allowed
Daniel Veillard97b58771998-10-20 06:14:16 +00003483 *
3484 * Dump an XML node, recursive behaviour,children are printed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003485 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003486static void
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003487xmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
3488 int format) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003489 int i;
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003490 xmlNodePtr tmp;
Daniel Veillard260a68f1998-08-13 03:39:55 +00003491
3492 if (cur == NULL) {
3493 fprintf(stderr, "xmlNodeDump : node == NULL\n");
3494 return;
3495 }
Daniel Veillard0bef1311998-10-14 02:36:47 +00003496 if (cur->type == XML_TEXT_NODE) {
Daniel Veillard14fff061999-06-22 21:49:07 +00003497 if (cur->content != NULL) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003498 xmlChar *buffer;
Daniel Veillard14fff061999-06-22 21:49:07 +00003499
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003500#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard14fff061999-06-22 21:49:07 +00003501 buffer = xmlEncodeEntitiesReentrant(doc, cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003502#else
3503 buffer = xmlEncodeEntitiesReentrant(doc,
3504 xmlBufferContent(cur->content));
3505#endif
Daniel Veillard14fff061999-06-22 21:49:07 +00003506 if (buffer != NULL) {
3507 xmlBufferWriteCHAR(buf, buffer);
Daniel Veillard6454aec1999-09-02 22:04:43 +00003508 xmlFree(buffer);
Daniel Veillard14fff061999-06-22 21:49:07 +00003509 }
3510 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003511 return;
3512 }
Daniel Veillardb96e6431999-08-29 21:02:19 +00003513 if (cur->type == XML_PI_NODE) {
3514 if (cur->content != NULL) {
3515 xmlBufferWriteChar(buf, "<?");
3516 xmlBufferWriteCHAR(buf, cur->name);
3517 if (cur->content != NULL) {
3518 xmlBufferWriteChar(buf, " ");
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003519#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardb96e6431999-08-29 21:02:19 +00003520 xmlBufferWriteCHAR(buf, cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003521#else
3522 xmlBufferWriteCHAR(buf, xmlBufferContent(cur->content));
3523#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +00003524 }
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003525 xmlBufferWriteChar(buf, "?>");
Daniel Veillardb96e6431999-08-29 21:02:19 +00003526 }
3527 return;
3528 }
Daniel Veillard0bef1311998-10-14 02:36:47 +00003529 if (cur->type == XML_COMMENT_NODE) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003530 if (cur->content != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003531 xmlBufferWriteChar(buf, "<!--");
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003532#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard5099ae81999-04-21 20:12:07 +00003533 xmlBufferWriteCHAR(buf, cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003534#else
3535 xmlBufferWriteCHAR(buf, xmlBufferContent(cur->content));
3536#endif
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003537 xmlBufferWriteChar(buf, "-->");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003538 }
3539 return;
3540 }
Daniel Veillardccb09631998-10-27 06:21:04 +00003541 if (cur->type == XML_ENTITY_REF_NODE) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003542 xmlBufferWriteChar(buf, "&");
3543 xmlBufferWriteCHAR(buf, cur->name);
3544 xmlBufferWriteChar(buf, ";");
Daniel Veillardccb09631998-10-27 06:21:04 +00003545 return;
3546 }
Daniel Veillardb05deb71999-08-10 19:04:08 +00003547 if (cur->type == XML_CDATA_SECTION_NODE) {
3548 xmlBufferWriteChar(buf, "<![CDATA[");
3549 if (cur->content != NULL)
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003550#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardb05deb71999-08-10 19:04:08 +00003551 xmlBufferWriteCHAR(buf, cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003552#else
3553 xmlBufferWriteCHAR(buf, xmlBufferContent(cur->content));
3554#endif
Daniel Veillardb05deb71999-08-10 19:04:08 +00003555 xmlBufferWriteChar(buf, "]]>");
3556 return;
3557 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003558
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003559 if (format == 1) {
3560 tmp = cur->childs;
3561 while (tmp != NULL) {
3562 if ((tmp->type == XML_TEXT_NODE) ||
3563 (tmp->type == XML_ENTITY_REF_NODE)) {
3564 format = 0;
3565 break;
3566 }
3567 tmp = tmp->next;
3568 }
3569 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003570 xmlBufferWriteChar(buf, "<");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003571 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003572 xmlBufferWriteCHAR(buf, cur->ns->prefix);
3573 xmlBufferWriteChar(buf, ":");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003574 }
3575
Daniel Veillard5099ae81999-04-21 20:12:07 +00003576 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003577 if (cur->nsDef)
Daniel Veillard5099ae81999-04-21 20:12:07 +00003578 xmlNsListDump(buf, cur->nsDef);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003579 if (cur->properties != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00003580 xmlAttrListDump(buf, doc, cur->properties);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003581
3582 if ((cur->content == NULL) && (cur->childs == NULL)) {
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003583 xmlBufferWriteChar(buf, "/>");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003584 return;
3585 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003586 xmlBufferWriteChar(buf, ">");
Daniel Veillard14fff061999-06-22 21:49:07 +00003587 if (cur->content != NULL) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003588 xmlChar *buffer;
Daniel Veillard14fff061999-06-22 21:49:07 +00003589
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003590#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard14fff061999-06-22 21:49:07 +00003591 buffer = xmlEncodeEntitiesReentrant(doc, cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003592#else
3593 buffer = xmlEncodeEntitiesReentrant(doc,
3594 xmlBufferContent(cur->content));
3595#endif
Daniel Veillard14fff061999-06-22 21:49:07 +00003596 if (buffer != NULL) {
3597 xmlBufferWriteCHAR(buf, buffer);
Daniel Veillard6454aec1999-09-02 22:04:43 +00003598 xmlFree(buffer);
Daniel Veillard14fff061999-06-22 21:49:07 +00003599 }
3600 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003601 if (cur->childs != NULL) {
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003602 if (format) xmlBufferWriteChar(buf, "\n");
3603 xmlNodeListDump(buf, doc, cur->childs, level + 1, format);
3604 if ((xmlIndentTreeOutput) && (format))
3605 for (i = 0;i < level;i++)
3606 xmlBufferWriteChar(buf, " ");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003607 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003608 xmlBufferWriteChar(buf, "</");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003609 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003610 xmlBufferWriteCHAR(buf, cur->ns->prefix);
3611 xmlBufferWriteChar(buf, ":");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003612 }
3613
Daniel Veillard5099ae81999-04-21 20:12:07 +00003614 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003615 xmlBufferWriteChar(buf, ">");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003616}
3617
Daniel Veillard97b58771998-10-20 06:14:16 +00003618/**
3619 * xmlDocContentDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003620 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003621 * @cur: the document
3622 *
3623 * Dump an XML document.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003624 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003625static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00003626xmlDocContentDump(xmlBufferPtr buf, xmlDocPtr cur) {
Daniel Veillardbe70ff71999-07-05 16:50:46 +00003627 xmlBufferWriteChar(buf, "<?xml version=");
3628 if (cur->version != NULL)
3629 xmlBufferWriteQuotedString(buf, cur->version);
3630 else
3631 xmlBufferWriteChar(buf, "\"1.0\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003632 if (cur->encoding != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00003633 xmlBufferWriteChar(buf, " encoding=");
3634 xmlBufferWriteQuotedString(buf, cur->encoding);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003635 }
3636 switch (cur->standalone) {
3637 case 0:
Daniel Veillard5099ae81999-04-21 20:12:07 +00003638 xmlBufferWriteChar(buf, " standalone=\"no\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003639 break;
3640 case 1:
Daniel Veillard5099ae81999-04-21 20:12:07 +00003641 xmlBufferWriteChar(buf, " standalone=\"yes\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003642 break;
3643 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003644 xmlBufferWriteChar(buf, "?>\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003645 if (cur->intSubset != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00003646 xmlDtdDump(buf, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003647 if (cur->root != NULL) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00003648 xmlNodePtr child = cur->root;
3649
Daniel Veillard260a68f1998-08-13 03:39:55 +00003650 /* global namespace definitions, the old way */
3651 if (oldXMLWDcompatibility)
Daniel Veillard5099ae81999-04-21 20:12:07 +00003652 xmlGlobalNsListDump(buf, cur->oldNs);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003653 else
3654 xmlUpgradeOldNs(cur);
Daniel Veillardb96e6431999-08-29 21:02:19 +00003655
3656 while (child != NULL) {
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003657 xmlNodeDump(buf, cur, child, 0, 1);
3658 xmlBufferWriteChar(buf, "\n");
Daniel Veillardb96e6431999-08-29 21:02:19 +00003659 child = child->next;
3660 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003661 }
3662}
3663
Daniel Veillard97b58771998-10-20 06:14:16 +00003664/**
3665 * xmlDocDumpMemory:
3666 * @cur: the document
3667 * @mem: OUT: the memory pointer
3668 * @size: OUT: the memory lenght
3669 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003670 * Dump an XML document in memory and return the xmlChar * and it's size.
Daniel Veillard97b58771998-10-20 06:14:16 +00003671 * It's up to the caller to free the memory.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003672 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003673void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003674xmlDocDumpMemory(xmlDocPtr cur, xmlChar**mem, int *size) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003675 xmlBufferPtr buf;
3676
Daniel Veillard260a68f1998-08-13 03:39:55 +00003677 if (cur == NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003678#ifdef DEBUG_TREE
3679 fprintf(stderr, "xmlDocDumpMemory : document == NULL\n");
3680#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00003681 *mem = NULL;
3682 *size = 0;
3683 return;
3684 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003685 buf = xmlBufferCreate();
3686 if (buf == NULL) {
3687 *mem = NULL;
3688 *size = 0;
3689 return;
3690 }
3691 xmlDocContentDump(buf, cur);
Daniel Veillardb05deb71999-08-10 19:04:08 +00003692 *mem = xmlStrndup(buf->content, buf->use);
Daniel Veillard5099ae81999-04-21 20:12:07 +00003693 *size = buf->use;
Daniel Veillardb05deb71999-08-10 19:04:08 +00003694 xmlBufferFree(buf);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003695}
3696
Daniel Veillard97b58771998-10-20 06:14:16 +00003697/**
3698 * xmlGetDocCompressMode:
3699 * @doc: the document
3700 *
3701 * get the compression ratio for a document, ZLIB based
Daniel Veillard1e346af1999-02-22 10:33:01 +00003702 * Returns 0 (uncompressed) to 9 (max compression)
Daniel Veillard151b1b01998-09-23 00:49:46 +00003703 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003704int
3705 xmlGetDocCompressMode (xmlDocPtr doc) {
Daniel Veillard15a8df41998-09-24 19:15:06 +00003706 if (doc == NULL) return(-1);
3707 return(doc->compression);
3708}
3709
Daniel Veillard97b58771998-10-20 06:14:16 +00003710/**
3711 * xmlSetDocCompressMode:
3712 * @doc: the document
3713 * @mode: the compression ratio
3714 *
3715 * set the compression ratio for a document, ZLIB based
3716 * Correct values: 0 (uncompressed) to 9 (max compression)
3717 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003718void
3719xmlSetDocCompressMode (xmlDocPtr doc, int mode) {
Daniel Veillard15a8df41998-09-24 19:15:06 +00003720 if (doc == NULL) return;
3721 if (mode < 0) doc->compression = 0;
3722 else if (mode > 9) doc->compression = 9;
3723 else doc->compression = mode;
3724}
3725
Daniel Veillard97b58771998-10-20 06:14:16 +00003726/**
3727 * xmlGetCompressMode:
3728 *
3729 * get the default compression mode used, ZLIB based.
Daniel Veillard1e346af1999-02-22 10:33:01 +00003730 * Returns 0 (uncompressed) to 9 (max compression)
Daniel Veillard15a8df41998-09-24 19:15:06 +00003731 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003732int
3733 xmlGetCompressMode(void) {
Daniel Veillard151b1b01998-09-23 00:49:46 +00003734 return(xmlCompressMode);
3735}
Daniel Veillard97b58771998-10-20 06:14:16 +00003736
3737/**
3738 * xmlSetCompressMode:
3739 * @mode: the compression ratio
3740 *
3741 * set the default compression mode used, ZLIB based
3742 * Correct values: 0 (uncompressed) to 9 (max compression)
3743 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003744void
3745xmlSetCompressMode(int mode) {
Daniel Veillard151b1b01998-09-23 00:49:46 +00003746 if (mode < 0) xmlCompressMode = 0;
Daniel Veillard15a8df41998-09-24 19:15:06 +00003747 else if (mode > 9) xmlCompressMode = 9;
Daniel Veillard151b1b01998-09-23 00:49:46 +00003748 else xmlCompressMode = mode;
3749}
3750
Daniel Veillard97b58771998-10-20 06:14:16 +00003751/**
3752 * xmlDocDump:
3753 * @f: the FILE*
3754 * @cur: the document
3755 *
3756 * Dump an XML document to an open FILE.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003757 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003758void
3759xmlDocDump(FILE *f, xmlDocPtr cur) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003760 xmlBufferPtr buf;
3761
Daniel Veillard260a68f1998-08-13 03:39:55 +00003762 if (cur == NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003763#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00003764 fprintf(stderr, "xmlDocDump : document == NULL\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003765#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00003766 return;
3767 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003768 buf = xmlBufferCreate();
3769 if (buf == NULL) return;
3770 xmlDocContentDump(buf, cur);
3771 xmlBufferDump(f, buf);
3772 xmlBufferFree(buf);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003773}
3774
Daniel Veillard97b58771998-10-20 06:14:16 +00003775/**
3776 * xmlSaveFile:
3777 * @filename: the filename
3778 * @cur: the document
3779 *
3780 * Dump an XML document to a file. Will use compression if
Daniel Veillard11a48ec1999-11-23 10:40:46 +00003781 * compiled in and enabled. If @filename is "-" the stdout file is
3782 * used.
Daniel Veillard97b58771998-10-20 06:14:16 +00003783 * returns: the number of file written or -1 in case of failure.
Daniel Veillard151b1b01998-09-23 00:49:46 +00003784 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003785int
3786xmlSaveFile(const char *filename, xmlDocPtr cur) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003787 xmlBufferPtr buf;
Daniel Veillard151b1b01998-09-23 00:49:46 +00003788#ifdef HAVE_ZLIB_H
3789 gzFile zoutput = NULL;
3790 char mode[15];
3791#endif
Daniel Veillardccb09631998-10-27 06:21:04 +00003792 FILE *output = NULL;
Daniel Veillard151b1b01998-09-23 00:49:46 +00003793 int ret;
3794
Daniel Veillard5099ae81999-04-21 20:12:07 +00003795 /*
3796 * save the content to a temp buffer.
3797 */
3798 buf = xmlBufferCreate();
3799 if (buf == NULL) return(0);
3800 xmlDocContentDump(buf, cur);
3801
Daniel Veillard151b1b01998-09-23 00:49:46 +00003802#ifdef HAVE_ZLIB_H
Daniel Veillard11a48ec1999-11-23 10:40:46 +00003803 if (cur->compression < 0) cur->compression = xmlCompressMode;
Daniel Veillarddc3dd9d1998-09-24 19:25:54 +00003804 if ((cur->compression > 0) && (cur->compression <= 9)) {
3805 sprintf(mode, "w%d", cur->compression);
Daniel Veillard11a48ec1999-11-23 10:40:46 +00003806 if (!strcmp(filename, "-"))
3807 zoutput = gzdopen(1, mode);
3808 else
3809 zoutput = gzopen(filename, mode);
Daniel Veillard151b1b01998-09-23 00:49:46 +00003810 }
3811 if (zoutput == NULL) {
3812#endif
3813 output = fopen(filename, "w");
Daniel Veillard10a2c651999-12-12 13:03:50 +00003814 if (output == NULL) {
3815 xmlBufferFree(buf);
3816 return(-1);
3817 }
Daniel Veillard151b1b01998-09-23 00:49:46 +00003818#ifdef HAVE_ZLIB_H
3819 }
Daniel Veillard151b1b01998-09-23 00:49:46 +00003820
Daniel Veillard151b1b01998-09-23 00:49:46 +00003821 if (zoutput != NULL) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003822 ret = gzwrite(zoutput, buf->content, sizeof(xmlChar) * buf->use);
Daniel Veillard151b1b01998-09-23 00:49:46 +00003823 gzclose(zoutput);
Daniel Veillard5099ae81999-04-21 20:12:07 +00003824 } else {
3825#endif
3826 ret = xmlBufferDump(output, buf);
3827 fclose(output);
3828#ifdef HAVE_ZLIB_H
Daniel Veillard151b1b01998-09-23 00:49:46 +00003829 }
3830#endif
Manish Vachharajani5e60f5a1999-05-29 03:04:30 +00003831 xmlBufferFree(buf);
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003832 return(ret * sizeof(xmlChar));
Daniel Veillard151b1b01998-09-23 00:49:46 +00003833}
3834