blob: f9cb877e8fb2d6788d6a8ab8a22c6b10049269c0 [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;
40
Daniel Veillard39a1f9a1999-01-17 19:11:59 +000041#define UPDATE_LAST_CHILD(n) if ((n) != NULL) { \
42 xmlNodePtr ulccur = (n)->childs; \
43 if (ulccur == NULL) { \
44 (n)->last = NULL; \
45 } else { \
46 while (ulccur->next != NULL) ulccur = ulccur->next; \
47 (n)->last = ulccur; \
Daniel Veillard1e346af1999-02-22 10:33:01 +000048}}
Daniel Veillard39a1f9a1999-01-17 19:11:59 +000049
Daniel Veillard260a68f1998-08-13 03:39:55 +000050/************************************************************************
51 * *
52 * Allocation and deallocation of basic structures *
53 * *
54 ************************************************************************/
55
Daniel Veillard97b58771998-10-20 06:14:16 +000056/**
Daniel Veillardf5c2c871999-12-01 09:51:45 +000057 * xmlSetBufferAllocationScheme:
58 * @scheme: allocation method to use
59 *
60 * Set the buffer allocation method. Types are
61 * XML_BUFFER_ALLOC_EXACT - use exact sizes, keeps memory usage down
62 * XML_BUFFER_ALLOC_DOUBLEIT - double buffer when extra needed,
63 * improves performance
64 */
65void
66xmlSetBufferAllocationScheme(xmlBufferAllocationScheme scheme) {
67 xmlBufferAllocScheme = scheme;
68}
69
70/**
71 * xmlGetBufferAllocationScheme:
72 *
73 * Types are
74 * XML_BUFFER_ALLOC_EXACT - use exact sizes, keeps memory usage down
75 * XML_BUFFER_ALLOC_DOUBLEIT - double buffer when extra needed,
76 * improves performance
77 *
78 * Returns the current allocation scheme
79 */
80xmlBufferAllocationScheme
81xmlGetBufferAllocationScheme() {
82 return xmlBufferAllocScheme;
83}
84
85/**
Daniel Veillard97b58771998-10-20 06:14:16 +000086 * xmlUpgradeOldNs:
87 * @doc: a document pointer
88 *
89 * Upgrade old style Namespaces (PI) and move them to the root of the document.
Daniel Veillard260a68f1998-08-13 03:39:55 +000090 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +000091void
92xmlUpgradeOldNs(xmlDocPtr doc) {
Daniel Veillard260a68f1998-08-13 03:39:55 +000093 xmlNsPtr cur;
94
95 if ((doc == NULL) || (doc->oldNs == NULL)) return;
96 if (doc->root == NULL) {
97 fprintf(stderr, "xmlUpgradeOldNs: failed no root !\n");
98 return;
99 }
100
101 cur = doc->oldNs;
102 while (cur->next != NULL) {
103 cur->type = XML_LOCAL_NAMESPACE;
104 cur = cur->next;
105 }
106 cur->type = XML_LOCAL_NAMESPACE;
107 cur->next = doc->root->nsDef;
108 doc->root->nsDef = doc->oldNs;
109 doc->oldNs = NULL;
110}
111
Daniel Veillard97b58771998-10-20 06:14:16 +0000112/**
113 * xmlNewNs:
114 * @node: the element carrying the namespace
115 * @href: the URI associated
116 * @prefix: the prefix for the namespace
117 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000118 * Creation of a new Namespace.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000119 * Returns returns a new namespace pointer
Daniel Veillard260a68f1998-08-13 03:39:55 +0000120 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000121xmlNsPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000122xmlNewNs(xmlNodePtr node, const xmlChar *href, const xmlChar *prefix) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000123 xmlNsPtr cur;
124
125 if (href == NULL) {
126 fprintf(stderr, "xmlNewNs: href == NULL !\n");
127 return(NULL);
128 }
129
130 /*
131 * Allocate a new DTD and fill the fields.
132 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000133 cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000134 if (cur == NULL) {
135 fprintf(stderr, "xmlNewNs : malloc failed\n");
136 return(NULL);
137 }
138
139 cur->type = XML_LOCAL_NAMESPACE;
140 if (href != NULL)
141 cur->href = xmlStrdup(href);
142 else
143 cur->href = NULL;
144 if (prefix != NULL)
145 cur->prefix = xmlStrdup(prefix);
146 else
147 cur->prefix = NULL;
148
149 /*
150 * Add it at the end to preserve parsing order ...
151 */
152 cur->next = NULL;
153 if (node != NULL) {
154 if (node->nsDef == NULL) {
155 node->nsDef = cur;
156 } else {
157 xmlNsPtr prev = node->nsDef;
158
159 while (prev->next != NULL) prev = prev->next;
160 prev->next = cur;
161 }
162 }
163
164 return(cur);
165}
166
Daniel Veillard97b58771998-10-20 06:14:16 +0000167/**
168 * xmlNewGlobalNs:
169 * @doc: the document carrying the namespace
170 * @href: the URI associated
171 * @prefix: the prefix for the namespace
172 *
173 * Creation of a Namespace, the old way using PI and without scoping, to AVOID.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000174 * Returns returns a new namespace pointer
Daniel Veillard260a68f1998-08-13 03:39:55 +0000175 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000176xmlNsPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000177xmlNewGlobalNs(xmlDocPtr doc, const xmlChar *href, const xmlChar *prefix) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000178 xmlNsPtr cur;
179
180 /*
181 * Allocate a new DTD and fill the fields.
182 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000183 cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000184 if (cur == NULL) {
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000185 fprintf(stderr, "xmlNewGlobalNs : malloc failed\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +0000186 return(NULL);
187 }
188
189 cur->type = XML_GLOBAL_NAMESPACE;
190 if (href != NULL)
191 cur->href = xmlStrdup(href);
192 else
193 cur->href = NULL;
194 if (prefix != NULL)
195 cur->prefix = xmlStrdup(prefix);
196 else
197 cur->prefix = NULL;
198
199 /*
200 * Add it at the end to preserve parsing order ...
201 */
202 cur->next = NULL;
203 if (doc != NULL) {
204 if (doc->oldNs == NULL) {
205 doc->oldNs = cur;
206 } else {
207 xmlNsPtr prev = doc->oldNs;
208
209 while (prev->next != NULL) prev = prev->next;
210 prev->next = cur;
211 }
212 }
213
214 return(cur);
215}
216
Daniel Veillard97b58771998-10-20 06:14:16 +0000217/**
218 * xmlSetNs:
219 * @node: a node in the document
220 * @ns: a namespace pointer
221 *
222 * Associate a namespace to a node, a posteriori.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000223 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000224void
225xmlSetNs(xmlNodePtr node, xmlNsPtr ns) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000226 if (node == NULL) {
227 fprintf(stderr, "xmlSetNs: node == NULL\n");
228 return;
229 }
230 node->ns = ns;
231}
232
Daniel Veillard97b58771998-10-20 06:14:16 +0000233/**
234 * xmlFreeNs:
235 * @cur: the namespace pointer
236 *
237 * Free up the structures associated to a namespace
Daniel Veillard260a68f1998-08-13 03:39:55 +0000238 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000239void
240xmlFreeNs(xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000241 if (cur == NULL) {
242 fprintf(stderr, "xmlFreeNs : ns == NULL\n");
243 return;
244 }
Daniel Veillard6454aec1999-09-02 22:04:43 +0000245 if (cur->href != NULL) xmlFree((char *) cur->href);
246 if (cur->prefix != NULL) xmlFree((char *) cur->prefix);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000247 memset(cur, -1, sizeof(xmlNs));
Daniel Veillard6454aec1999-09-02 22:04:43 +0000248 xmlFree(cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000249}
250
Daniel Veillard97b58771998-10-20 06:14:16 +0000251/**
252 * xmlFreeNsList:
253 * @cur: the first namespace pointer
254 *
255 * Free up all the structures associated to the chained namespaces.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000256 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000257void
258xmlFreeNsList(xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000259 xmlNsPtr next;
260 if (cur == NULL) {
261 fprintf(stderr, "xmlFreeNsList : ns == NULL\n");
262 return;
263 }
264 while (cur != NULL) {
265 next = cur->next;
266 xmlFreeNs(cur);
267 cur = next;
268 }
269}
270
Daniel Veillard97b58771998-10-20 06:14:16 +0000271/**
272 * xmlNewDtd:
273 * @doc: the document pointer
274 * @name: the DTD name
275 * @ExternalID: the external ID
276 * @SystemID: the system ID
277 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000278 * Creation of a new DTD.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000279 * Returns a pointer to the new DTD structure
Daniel Veillard260a68f1998-08-13 03:39:55 +0000280 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000281xmlDtdPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000282xmlNewDtd(xmlDocPtr doc, const xmlChar *name,
283 const xmlChar *ExternalID, const xmlChar *SystemID) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000284 xmlDtdPtr cur;
285
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000286 if ((doc != NULL) && (doc->extSubset != NULL)) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000287 fprintf(stderr, "xmlNewDtd(%s): document %s already have a DTD %s\n",
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000288 /* !!! */ (char *) name, doc->name,
289 /* !!! */ (char *)doc->extSubset->name);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000290 }
291
292 /*
293 * Allocate a new DTD and fill the fields.
294 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000295 cur = (xmlDtdPtr) xmlMalloc(sizeof(xmlDtd));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000296 if (cur == NULL) {
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000297 fprintf(stderr, "xmlNewDtd : malloc failed\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +0000298 return(NULL);
299 }
300
301 if (name != NULL)
302 cur->name = xmlStrdup(name);
303 else
304 cur->name = NULL;
305 if (ExternalID != NULL)
306 cur->ExternalID = xmlStrdup(ExternalID);
307 else
308 cur->ExternalID = NULL;
309 if (SystemID != NULL)
310 cur->SystemID = xmlStrdup(SystemID);
311 else
312 cur->SystemID = NULL;
Daniel Veillard1e346af1999-02-22 10:33:01 +0000313 cur->notations = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000314 cur->elements = NULL;
Daniel Veillard1e346af1999-02-22 10:33:01 +0000315 cur->attributes = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000316 cur->entities = NULL;
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000317 if (doc != NULL)
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000318 doc->extSubset = cur;
319
320 return(cur);
321}
322
323/**
324 * xmlCreateIntSubset:
325 * @doc: the document pointer
326 * @name: the DTD name
327 * @ExternalID: the external ID
328 * @SystemID: the system ID
329 *
Daniel Veillard1e346af1999-02-22 10:33:01 +0000330 * Create the internal subset of a document
331 * Returns a pointer to the new DTD structure
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000332 */
333xmlDtdPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000334xmlCreateIntSubset(xmlDocPtr doc, const xmlChar *name,
335 const xmlChar *ExternalID, const xmlChar *SystemID) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000336 xmlDtdPtr cur;
337
338 if ((doc != NULL) && (doc->intSubset != NULL)) {
339 fprintf(stderr,
340 "xmlCreateIntSubset(): document %s already have an internal subset\n",
341 doc->name);
342 return(NULL);
343 }
344
345 /*
346 * Allocate a new DTD and fill the fields.
347 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000348 cur = (xmlDtdPtr) xmlMalloc(sizeof(xmlDtd));
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000349 if (cur == NULL) {
350 fprintf(stderr, "xmlNewDtd : malloc failed\n");
351 return(NULL);
352 }
353
354 if (name != NULL)
355 cur->name = xmlStrdup(name);
356 else
357 cur->name = NULL;
358 if (ExternalID != NULL)
359 cur->ExternalID = xmlStrdup(ExternalID);
360 else
361 cur->ExternalID = NULL;
362 if (SystemID != NULL)
363 cur->SystemID = xmlStrdup(SystemID);
364 else
365 cur->SystemID = NULL;
Daniel Veillard1e346af1999-02-22 10:33:01 +0000366 cur->notations = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000367 cur->elements = NULL;
Daniel Veillard1e346af1999-02-22 10:33:01 +0000368 cur->attributes = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000369 cur->entities = NULL;
370 if (doc != NULL)
371 doc->intSubset = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000372
373 return(cur);
374}
375
Daniel Veillard97b58771998-10-20 06:14:16 +0000376/**
377 * xmlFreeDtd:
378 * @cur: the DTD structure to free up
379 *
380 * Free a DTD structure.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000381 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000382void
383xmlFreeDtd(xmlDtdPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000384 if (cur == NULL) {
385 fprintf(stderr, "xmlFreeDtd : DTD == NULL\n");
386 return;
387 }
Daniel Veillard6454aec1999-09-02 22:04:43 +0000388 if (cur->name != NULL) xmlFree((char *) cur->name);
389 if (cur->SystemID != NULL) xmlFree((char *) cur->SystemID);
390 if (cur->ExternalID != NULL) xmlFree((char *) cur->ExternalID);
Daniel Veillard1e346af1999-02-22 10:33:01 +0000391 if (cur->notations != NULL)
392 xmlFreeNotationTable((xmlNotationTablePtr) cur->notations);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000393 if (cur->elements != NULL)
Daniel Veillard3b9def11999-01-31 22:15:06 +0000394 xmlFreeElementTable((xmlElementTablePtr) cur->elements);
Daniel Veillard1e346af1999-02-22 10:33:01 +0000395 if (cur->attributes != NULL)
396 xmlFreeAttributeTable((xmlAttributeTablePtr) cur->attributes);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000397 if (cur->entities != NULL)
398 xmlFreeEntitiesTable((xmlEntitiesTablePtr) cur->entities);
399 memset(cur, -1, sizeof(xmlDtd));
Daniel Veillard6454aec1999-09-02 22:04:43 +0000400 xmlFree(cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000401}
402
Daniel Veillard97b58771998-10-20 06:14:16 +0000403/**
404 * xmlNewDoc:
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000405 * @version: xmlChar string giving the version of XML "1.0"
Daniel Veillard97b58771998-10-20 06:14:16 +0000406 *
Daniel Veillard1e346af1999-02-22 10:33:01 +0000407 * Returns a new document
Daniel Veillard260a68f1998-08-13 03:39:55 +0000408 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000409xmlDocPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000410xmlNewDoc(const xmlChar *version) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000411 xmlDocPtr cur;
412
413 if (version == NULL) {
414 fprintf(stderr, "xmlNewDoc : version == NULL\n");
415 return(NULL);
416 }
417
418 /*
419 * Allocate a new document and fill the fields.
420 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000421 cur = (xmlDocPtr) xmlMalloc(sizeof(xmlDoc));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000422 if (cur == NULL) {
423 fprintf(stderr, "xmlNewDoc : malloc failed\n");
424 return(NULL);
425 }
426
Daniel Veillard33942841998-10-18 19:12:41 +0000427 cur->type = XML_DOCUMENT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000428 cur->version = xmlStrdup(version);
429 cur->name = NULL;
430 cur->root = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000431 cur->intSubset = NULL;
432 cur->extSubset = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000433 cur->oldNs = NULL;
434 cur->encoding = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000435 cur->standalone = -1;
Daniel Veillard11a48ec1999-11-23 10:40:46 +0000436 cur->compression = -1; /* not initialized */
Daniel Veillardb96e6431999-08-29 21:02:19 +0000437 cur->ids = NULL;
Daniel Veillardc08a2c61999-09-08 21:35:25 +0000438 cur->refs = NULL;
Daniel Veillard27d88741999-05-29 11:51:49 +0000439#ifndef XML_WITHOUT_CORBA
Daniel Veillard27fb0751998-10-17 06:47:46 +0000440 cur->_private = NULL;
441 cur->vepv = NULL;
442#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000443 return(cur);
444}
445
Daniel Veillard97b58771998-10-20 06:14:16 +0000446/**
447 * xmlFreeDoc:
448 * @cur: pointer to the document
449 * @:
450 *
451 * Free up all the structures used by a document, tree included.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000452 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000453void
454xmlFreeDoc(xmlDocPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000455 if (cur == NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000456#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +0000457 fprintf(stderr, "xmlFreeDoc : document == NULL\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000458#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000459 return;
460 }
Daniel Veillard6454aec1999-09-02 22:04:43 +0000461 if (cur->version != NULL) xmlFree((char *) cur->version);
462 if (cur->name != NULL) xmlFree((char *) cur->name);
463 if (cur->encoding != NULL) xmlFree((char *) cur->encoding);
464 if (cur->root != NULL) xmlFreeNodeList(cur->root);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000465 if (cur->intSubset != NULL) xmlFreeDtd(cur->intSubset);
466 if (cur->extSubset != NULL) xmlFreeDtd(cur->extSubset);
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000467 if (cur->oldNs != NULL) xmlFreeNsList(cur->oldNs);
Daniel Veillardb96e6431999-08-29 21:02:19 +0000468 if (cur->ids != NULL) xmlFreeIDTable((xmlIDTablePtr) cur->ids);
Daniel Veillardc08a2c61999-09-08 21:35:25 +0000469 if (cur->refs != NULL) xmlFreeRefTable((xmlRefTablePtr) cur->refs);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000470 memset(cur, -1, sizeof(xmlDoc));
Daniel Veillard6454aec1999-09-02 22:04:43 +0000471 xmlFree(cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000472}
473
Daniel Veillard97b58771998-10-20 06:14:16 +0000474/**
Daniel Veillard16253641998-10-28 22:58:05 +0000475 * xmlStringLenGetNodeList:
476 * @doc: the document
477 * @value: the value of the text
Daniel Veillard1e346af1999-02-22 10:33:01 +0000478 * @len: the length of the string value
Daniel Veillard16253641998-10-28 22:58:05 +0000479 *
480 * Parse the value string and build the node list associated. Should
481 * produce a flat tree with only TEXTs and ENTITY_REFs.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000482 * Returns a pointer to the first child
Daniel Veillard16253641998-10-28 22:58:05 +0000483 */
484xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000485xmlStringLenGetNodeList(xmlDocPtr doc, const xmlChar *value, int len) {
Daniel Veillard16253641998-10-28 22:58:05 +0000486 xmlNodePtr ret = NULL, last = NULL;
487 xmlNodePtr node;
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000488 xmlChar *val;
489 const xmlChar *cur = value;
490 const xmlChar *q;
Daniel Veillard25940b71998-10-29 05:51:30 +0000491 xmlEntityPtr ent;
Daniel Veillard16253641998-10-28 22:58:05 +0000492
493 if (value == NULL) return(NULL);
494
495 q = cur;
496 while ((*cur != 0) && (cur - value < len)) {
497 if (*cur == '&') {
Daniel Veillard25940b71998-10-29 05:51:30 +0000498 /*
499 * Save the current text.
500 */
Daniel Veillard16253641998-10-28 22:58:05 +0000501 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000502 if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
503 xmlNodeAddContentLen(last, q, cur - q);
504 } else {
505 node = xmlNewDocTextLen(doc, q, cur - q);
506 if (node == NULL) return(ret);
507 if (last == NULL)
508 last = ret = node;
509 else {
510 last->next = node;
511 node->prev = last;
512 last = node;
513 }
Daniel Veillard16253641998-10-28 22:58:05 +0000514 }
515 }
Daniel Veillard25940b71998-10-29 05:51:30 +0000516 /*
517 * Read the entity string
518 */
Daniel Veillard16253641998-10-28 22:58:05 +0000519 cur++;
520 q = cur;
521 while ((*cur != 0) && (cur - value < len) && (*cur != ';')) cur++;
522 if ((*cur == 0) || (cur - value >= len)) {
523 fprintf(stderr,
Daniel Veillard011b63c1999-06-02 17:44:04 +0000524 "xmlStringLenGetNodeList: unterminated entity %30s\n", q);
Daniel Veillard16253641998-10-28 22:58:05 +0000525 return(ret);
526 }
527 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000528 /*
529 * Predefined entities don't generate nodes
530 */
Daniel Veillard16253641998-10-28 22:58:05 +0000531 val = xmlStrndup(q, cur - q);
Daniel Veillard25940b71998-10-29 05:51:30 +0000532 ent = xmlGetDocEntity(doc, val);
533 if ((ent != NULL) &&
534 (ent->type == XML_INTERNAL_PREDEFINED_ENTITY)) {
535 if (last == NULL) {
536 node = xmlNewDocText(doc, ent->content);
537 last = ret = node;
538 } else
539 xmlNodeAddContent(last, ent->content);
540
541 } else {
542 /*
543 * Create a new REFERENCE_REF node
544 */
545 node = xmlNewReference(doc, val);
Daniel Veillard242590e1998-11-13 18:04:35 +0000546 if (node == NULL) {
Daniel Veillard6454aec1999-09-02 22:04:43 +0000547 if (val != NULL) xmlFree(val);
Daniel Veillard242590e1998-11-13 18:04:35 +0000548 return(ret);
549 }
Daniel Veillard25940b71998-10-29 05:51:30 +0000550 if (last == NULL)
551 last = ret = node;
552 else {
553 last->next = node;
554 node->prev = last;
555 last = node;
556 }
Daniel Veillard16253641998-10-28 22:58:05 +0000557 }
Daniel Veillard6454aec1999-09-02 22:04:43 +0000558 xmlFree(val);
Daniel Veillard16253641998-10-28 22:58:05 +0000559 }
560 cur++;
561 q = cur;
562 } else
563 cur++;
564 }
565 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000566 /*
567 * Handle the last piece of text.
568 */
569 if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
570 xmlNodeAddContentLen(last, q, cur - q);
571 } else {
572 node = xmlNewDocTextLen(doc, q, cur - q);
573 if (node == NULL) return(ret);
574 if (last == NULL)
575 last = ret = node;
576 else {
577 last->next = node;
578 node->prev = last;
579 last = node;
580 }
Daniel Veillard16253641998-10-28 22:58:05 +0000581 }
582 }
583 return(ret);
584}
585
586/**
Daniel Veillardccb09631998-10-27 06:21:04 +0000587 * xmlStringGetNodeList:
588 * @doc: the document
589 * @value: the value of the attribute
590 *
591 * Parse the value string and build the node list associated. Should
592 * produce a flat tree with only TEXTs and ENTITY_REFs.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000593 * Returns a pointer to the first child
Daniel Veillardccb09631998-10-27 06:21:04 +0000594 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000595xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000596xmlStringGetNodeList(xmlDocPtr doc, const xmlChar *value) {
Daniel Veillardccb09631998-10-27 06:21:04 +0000597 xmlNodePtr ret = NULL, last = NULL;
598 xmlNodePtr node;
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000599 xmlChar *val;
600 const xmlChar *cur = value;
601 const xmlChar *q;
Daniel Veillard25940b71998-10-29 05:51:30 +0000602 xmlEntityPtr ent;
Daniel Veillardccb09631998-10-27 06:21:04 +0000603
604 if (value == NULL) return(NULL);
605
606 q = cur;
607 while (*cur != 0) {
608 if (*cur == '&') {
Daniel Veillard25940b71998-10-29 05:51:30 +0000609 /*
610 * Save the current text.
611 */
Daniel Veillardccb09631998-10-27 06:21:04 +0000612 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000613 if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
614 xmlNodeAddContentLen(last, q, cur - q);
615 } else {
616 node = xmlNewDocTextLen(doc, q, cur - q);
617 if (node == NULL) return(ret);
618 if (last == NULL)
619 last = ret = node;
620 else {
621 last->next = node;
622 node->prev = last;
623 last = node;
624 }
Daniel Veillardccb09631998-10-27 06:21:04 +0000625 }
626 }
Daniel Veillard25940b71998-10-29 05:51:30 +0000627 /*
628 * Read the entity string
629 */
Daniel Veillardccb09631998-10-27 06:21:04 +0000630 cur++;
631 q = cur;
632 while ((*cur != 0) && (*cur != ';')) cur++;
633 if (*cur == 0) {
634 fprintf(stderr,
635 "xmlStringGetNodeList: unterminated entity %30s\n", q);
636 return(ret);
637 }
638 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000639 /*
640 * Predefined entities don't generate nodes
641 */
Daniel Veillardccb09631998-10-27 06:21:04 +0000642 val = xmlStrndup(q, cur - q);
Daniel Veillard25940b71998-10-29 05:51:30 +0000643 ent = xmlGetDocEntity(doc, val);
644 if ((ent != NULL) &&
645 (ent->type == XML_INTERNAL_PREDEFINED_ENTITY)) {
646 if (last == NULL) {
647 node = xmlNewDocText(doc, ent->content);
648 last = ret = node;
649 } else
650 xmlNodeAddContent(last, ent->content);
651
652 } else {
653 /*
654 * Create a new REFERENCE_REF node
655 */
Daniel Veillard25940b71998-10-29 05:51:30 +0000656 node = xmlNewReference(doc, val);
Daniel Veillard242590e1998-11-13 18:04:35 +0000657 if (node == NULL) {
Daniel Veillard6454aec1999-09-02 22:04:43 +0000658 if (val != NULL) xmlFree(val);
Daniel Veillard242590e1998-11-13 18:04:35 +0000659 return(ret);
660 }
Daniel Veillard25940b71998-10-29 05:51:30 +0000661 if (last == NULL)
662 last = ret = node;
663 else {
664 last->next = node;
665 node->prev = last;
666 last = node;
667 }
Daniel Veillardccb09631998-10-27 06:21:04 +0000668 }
Daniel Veillard6454aec1999-09-02 22:04:43 +0000669 xmlFree(val);
Daniel Veillardccb09631998-10-27 06:21:04 +0000670 }
671 cur++;
672 q = cur;
673 } else
674 cur++;
675 }
676 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000677 /*
678 * Handle the last piece of text.
679 */
680 if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
681 xmlNodeAddContentLen(last, q, cur - q);
682 } else {
683 node = xmlNewDocTextLen(doc, q, cur - q);
684 if (node == NULL) return(ret);
685 if (last == NULL)
686 last = ret = node;
687 else {
688 last->next = node;
689 node->prev = last;
690 last = node;
691 }
Daniel Veillardccb09631998-10-27 06:21:04 +0000692 }
693 }
694 return(ret);
695}
696
697/**
698 * xmlNodeListGetString:
699 * @doc: the document
700 * @list: a Node list
701 * @inLine: should we replace entity contents or show their external form
702 *
703 * Returns the string equivalent to the text contained in the Node list
704 * made of TEXTs and ENTITY_REFs
Daniel Veillard1e346af1999-02-22 10:33:01 +0000705 * Returns a pointer to the string copy, the calller must free it.
Daniel Veillardccb09631998-10-27 06:21:04 +0000706 */
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000707xmlChar *
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000708xmlNodeListGetString(xmlDocPtr doc, xmlNodePtr list, int inLine) {
Daniel Veillardccb09631998-10-27 06:21:04 +0000709 xmlNodePtr node = list;
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000710 xmlChar *ret = NULL;
Daniel Veillardccb09631998-10-27 06:21:04 +0000711 xmlEntityPtr ent;
712
713 if (list == NULL) return(NULL);
714
715 while (node != NULL) {
716 if (node->type == XML_TEXT_NODE) {
Daniel Veillardf5c2c871999-12-01 09:51:45 +0000717 if ((inLine) || (doc->type == XML_HTML_DOCUMENT_NODE)) {
718#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardccb09631998-10-27 06:21:04 +0000719 ret = xmlStrcat(ret, node->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +0000720#else
721 ret = xmlStrcat(ret, xmlBufferContent(node->content));
722#endif
723 } else {
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000724 xmlChar *buffer;
Daniel Veillard14fff061999-06-22 21:49:07 +0000725
Daniel Veillardf5c2c871999-12-01 09:51:45 +0000726#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard14fff061999-06-22 21:49:07 +0000727 buffer = xmlEncodeEntitiesReentrant(doc, node->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +0000728#else
729 buffer = xmlEncodeEntitiesReentrant(doc,
730 xmlBufferContent(node->content));
731#endif
Daniel Veillard14fff061999-06-22 21:49:07 +0000732 if (buffer != NULL) {
733 ret = xmlStrcat(ret, buffer);
Daniel Veillard6454aec1999-09-02 22:04:43 +0000734 xmlFree(buffer);
Daniel Veillard14fff061999-06-22 21:49:07 +0000735 }
736 }
Daniel Veillardccb09631998-10-27 06:21:04 +0000737 } else if (node->type == XML_ENTITY_REF_NODE) {
738 if (inLine) {
739 ent = xmlGetDocEntity(doc, node->name);
740 if (ent != NULL)
741 ret = xmlStrcat(ret, ent->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +0000742 else {
743#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardccb09631998-10-27 06:21:04 +0000744 ret = xmlStrcat(ret, node->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +0000745#else
746 ret = xmlStrcat(ret, xmlBufferContent(node->content));
747#endif
748 }
Daniel Veillardccb09631998-10-27 06:21:04 +0000749 } else {
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000750 xmlChar buf[2];
Daniel Veillardccb09631998-10-27 06:21:04 +0000751 buf[0] = '&'; buf[1] = 0;
752 ret = xmlStrncat(ret, buf, 1);
753 ret = xmlStrcat(ret, node->name);
754 buf[0] = ';'; buf[1] = 0;
755 ret = xmlStrncat(ret, buf, 1);
756 }
757 }
758#if 0
759 else {
760 fprintf(stderr, "xmlGetNodeListString : invalide node type %d\n",
761 node->type);
762 }
763#endif
764 node = node->next;
765 }
766 return(ret);
767}
768
769/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000770 * xmlNewProp:
771 * @node: the holding node
772 * @name: the name of the attribute
773 * @value: the value of the attribute
774 *
775 * Create a new property carried by a node.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000776 * Returns a pointer to the attribute
Daniel Veillard260a68f1998-08-13 03:39:55 +0000777 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000778xmlAttrPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000779xmlNewProp(xmlNodePtr node, const xmlChar *name, const xmlChar *value) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000780 xmlAttrPtr cur;
781
782 if (name == NULL) {
783 fprintf(stderr, "xmlNewProp : name == NULL\n");
784 return(NULL);
785 }
786
787 /*
788 * Allocate a new property and fill the fields.
789 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000790 cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000791 if (cur == NULL) {
792 fprintf(stderr, "xmlNewProp : malloc failed\n");
793 return(NULL);
794 }
795
Daniel Veillard33942841998-10-18 19:12:41 +0000796 cur->type = XML_ATTRIBUTE_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000797 cur->node = node;
Daniel Veillardb96e6431999-08-29 21:02:19 +0000798 cur->ns = NULL;
799 cur->name = xmlStrdup(name);
Daniel Veillard51e3b151999-11-12 17:02:31 +0000800 if (value != NULL) {
801 xmlChar *buffer;
802 buffer = xmlEncodeEntitiesReentrant(node->doc, value);
803 cur->val = xmlStringGetNodeList(node->doc, buffer);
804 xmlFree(buffer);
805 }
Daniel Veillardb96e6431999-08-29 21:02:19 +0000806 else
807 cur->val = NULL;
808#ifndef XML_WITHOUT_CORBA
809 cur->_private = NULL;
810 cur->vepv = NULL;
811#endif
812
813 /*
814 * Add it at the end to preserve parsing order ...
815 */
816 cur->next = NULL;
817 if (node != NULL) {
818 if (node->properties == NULL) {
819 node->properties = cur;
820 } else {
821 xmlAttrPtr prev = node->properties;
822
823 while (prev->next != NULL) prev = prev->next;
824 prev->next = cur;
825 }
826 }
Daniel Veillard00fdf371999-10-08 09:40:39 +0000827#ifndef XML_WITHOUT_CORBA
828 cur->_private = NULL;
829 cur->vepv = NULL;
830#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +0000831 return(cur);
832}
833
834/**
835 * xmlNewNsProp:
836 * @node: the holding node
837 * @ns: the namespace
838 * @name: the name of the attribute
839 * @value: the value of the attribute
840 *
841 * Create a new property tagged with a namespace and carried by a node.
842 * Returns a pointer to the attribute
843 */
844xmlAttrPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000845xmlNewNsProp(xmlNodePtr node, xmlNsPtr ns, const xmlChar *name,
846 const xmlChar *value) {
Daniel Veillardb96e6431999-08-29 21:02:19 +0000847 xmlAttrPtr cur;
848
849 if (name == NULL) {
850 fprintf(stderr, "xmlNewProp : name == NULL\n");
851 return(NULL);
852 }
853
854 /*
855 * Allocate a new property and fill the fields.
856 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000857 cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr));
Daniel Veillardb96e6431999-08-29 21:02:19 +0000858 if (cur == NULL) {
859 fprintf(stderr, "xmlNewProp : malloc failed\n");
860 return(NULL);
861 }
862
863 cur->type = XML_ATTRIBUTE_NODE;
864 cur->node = node;
865 cur->ns = ns;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000866 cur->name = xmlStrdup(name);
867 if (value != NULL)
Daniel Veillardccb09631998-10-27 06:21:04 +0000868 cur->val = xmlStringGetNodeList(node->doc, value);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000869 else
Daniel Veillardccb09631998-10-27 06:21:04 +0000870 cur->val = NULL;
Daniel Veillard27d88741999-05-29 11:51:49 +0000871#ifndef XML_WITHOUT_CORBA
Daniel Veillard27fb0751998-10-17 06:47:46 +0000872 cur->_private = NULL;
873 cur->vepv = NULL;
874#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000875
876 /*
877 * Add it at the end to preserve parsing order ...
878 */
879 cur->next = NULL;
880 if (node != NULL) {
881 if (node->properties == NULL) {
882 node->properties = cur;
883 } else {
884 xmlAttrPtr prev = node->properties;
885
886 while (prev->next != NULL) prev = prev->next;
887 prev->next = cur;
888 }
889 }
890 return(cur);
891}
892
Daniel Veillard97b58771998-10-20 06:14:16 +0000893/**
Daniel Veillardccb09631998-10-27 06:21:04 +0000894 * xmlNewDocProp:
895 * @doc: the document
896 * @name: the name of the attribute
897 * @value: the value of the attribute
898 *
899 * Create a new property carried by a document.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000900 * Returns a pointer to the attribute
Daniel Veillardccb09631998-10-27 06:21:04 +0000901 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000902xmlAttrPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000903xmlNewDocProp(xmlDocPtr doc, const xmlChar *name, const xmlChar *value) {
Daniel Veillardccb09631998-10-27 06:21:04 +0000904 xmlAttrPtr cur;
905
906 if (name == NULL) {
907 fprintf(stderr, "xmlNewProp : name == NULL\n");
908 return(NULL);
909 }
910
911 /*
912 * Allocate a new property and fill the fields.
913 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000914 cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr));
Daniel Veillardccb09631998-10-27 06:21:04 +0000915 if (cur == NULL) {
916 fprintf(stderr, "xmlNewProp : malloc failed\n");
917 return(NULL);
918 }
919
920 cur->type = XML_ATTRIBUTE_NODE;
921 cur->node = NULL;
922 cur->name = xmlStrdup(name);
923 if (value != NULL)
924 cur->val = xmlStringGetNodeList(doc, value);
925 else
926 cur->val = NULL;
Daniel Veillard27d88741999-05-29 11:51:49 +0000927#ifndef XML_WITHOUT_CORBA
Daniel Veillardccb09631998-10-27 06:21:04 +0000928 cur->_private = NULL;
929 cur->vepv = NULL;
930#endif
931
932 cur->next = NULL;
933 return(cur);
934}
935
936/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000937 * xmlFreePropList:
938 * @cur: the first property in the list
939 *
940 * Free a property and all its siblings, all the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000941 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000942void
943xmlFreePropList(xmlAttrPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000944 xmlAttrPtr next;
945 if (cur == NULL) {
946 fprintf(stderr, "xmlFreePropList : property == NULL\n");
947 return;
948 }
949 while (cur != NULL) {
950 next = cur->next;
951 xmlFreeProp(cur);
952 cur = next;
953 }
954}
955
Daniel Veillard97b58771998-10-20 06:14:16 +0000956/**
957 * xmlFreeProp:
958 * @cur: the first property in the list
959 *
960 * Free one property, all the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000961 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000962void
963xmlFreeProp(xmlAttrPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000964 if (cur == NULL) {
965 fprintf(stderr, "xmlFreeProp : property == NULL\n");
966 return;
967 }
Daniel Veillard6454aec1999-09-02 22:04:43 +0000968 if (cur->name != NULL) xmlFree((char *) cur->name);
Daniel Veillardccb09631998-10-27 06:21:04 +0000969 if (cur->val != NULL) xmlFreeNodeList(cur->val);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000970 memset(cur, -1, sizeof(xmlAttr));
Daniel Veillard6454aec1999-09-02 22:04:43 +0000971 xmlFree(cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000972}
973
Daniel Veillard97b58771998-10-20 06:14:16 +0000974/**
Daniel Veillardb96e6431999-08-29 21:02:19 +0000975 * xmlNewPI:
976 * @name: the processing instruction name
977 * @content: the PI content
978 *
979 * Creation of a processing instruction element.
980 * Returns a pointer to the new node object.
981 */
982xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000983xmlNewPI(const xmlChar *name, const xmlChar *content) {
Daniel Veillardb96e6431999-08-29 21:02:19 +0000984 xmlNodePtr cur;
985
986 if (name == NULL) {
987 fprintf(stderr, "xmlNewPI : name == NULL\n");
988 return(NULL);
989 }
990
991 /*
992 * Allocate a new node and fill the fields.
993 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000994 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillardb96e6431999-08-29 21:02:19 +0000995 if (cur == NULL) {
996 fprintf(stderr, "xmlNewPI : malloc failed\n");
997 return(NULL);
998 }
999
1000 cur->type = XML_PI_NODE;
1001 cur->doc = NULL;
1002 cur->parent = NULL;
1003 cur->next = NULL;
1004 cur->prev = NULL;
1005 cur->childs = NULL;
1006 cur->last = NULL;
1007 cur->properties = NULL;
1008 cur->name = xmlStrdup(name);
1009 cur->ns = NULL;
1010 cur->nsDef = NULL;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001011 if (content != NULL) {
1012#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardb96e6431999-08-29 21:02:19 +00001013 cur->content = xmlStrdup(content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001014#else
1015 cur->content = xmlBufferCreateSize(0);
1016 xmlBufferSetAllocationScheme(cur->content,
1017 xmlGetBufferAllocationScheme());
1018 xmlBufferAdd(cur->content, content, -1);
1019#endif
1020 } else
Daniel Veillardb96e6431999-08-29 21:02:19 +00001021 cur->content = NULL;
1022#ifndef XML_WITHOUT_CORBA
1023 cur->_private = NULL;
1024 cur->vepv = NULL;
1025#endif
1026 return(cur);
1027}
1028
1029/**
Daniel Veillard97b58771998-10-20 06:14:16 +00001030 * xmlNewNode:
1031 * @ns: namespace if any
1032 * @name: the node name
Daniel Veillard97b58771998-10-20 06:14:16 +00001033 *
1034 * Creation of a new node element. @ns and @content are optionnal (NULL).
Daniel Veillardccb09631998-10-27 06:21:04 +00001035 * If content is non NULL, a child list containing the TEXTs and
1036 * ENTITY_REFs node will be created.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001037 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001038 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001039xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001040xmlNewNode(xmlNsPtr ns, const xmlChar *name) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001041 xmlNodePtr cur;
1042
1043 if (name == NULL) {
1044 fprintf(stderr, "xmlNewNode : name == NULL\n");
1045 return(NULL);
1046 }
1047
1048 /*
1049 * Allocate a new node and fill the fields.
1050 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001051 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillard260a68f1998-08-13 03:39:55 +00001052 if (cur == NULL) {
1053 fprintf(stderr, "xmlNewNode : malloc failed\n");
1054 return(NULL);
1055 }
1056
Daniel Veillard33942841998-10-18 19:12:41 +00001057 cur->type = XML_ELEMENT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001058 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001059 cur->parent = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001060 cur->next = NULL;
1061 cur->prev = NULL;
1062 cur->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001063 cur->last = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001064 cur->properties = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001065 cur->name = xmlStrdup(name);
1066 cur->ns = ns;
1067 cur->nsDef = NULL;
Daniel Veillardccb09631998-10-27 06:21:04 +00001068 cur->content = NULL;
Daniel Veillard27d88741999-05-29 11:51:49 +00001069#ifndef XML_WITHOUT_CORBA
Daniel Veillard27fb0751998-10-17 06:47:46 +00001070 cur->_private = NULL;
1071 cur->vepv = NULL;
1072#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001073 return(cur);
1074}
1075
Daniel Veillard97b58771998-10-20 06:14:16 +00001076/**
1077 * xmlNewDocNode:
1078 * @doc: the document
1079 * @ns: namespace if any
1080 * @name: the node name
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001081 * @content: the XML text content if any
Daniel Veillard97b58771998-10-20 06:14:16 +00001082 *
1083 * Creation of a new node element within a document. @ns and @content
1084 * are optionnal (NULL).
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001085 * NOTE: @content is supposed to be a piece of XML CDATA, so it allow entities
1086 * references, but XML special chars need to be escaped first by using
1087 * xmlEncodeEntitiesReentrant(). Use xmlNewDocRawNode() if you don't
1088 * need entities support.
1089 *
Daniel Veillard1e346af1999-02-22 10:33:01 +00001090 * Returns a pointer to the new node object.
Daniel Veillard97b58771998-10-20 06:14:16 +00001091 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001092xmlNodePtr
1093xmlNewDocNode(xmlDocPtr doc, xmlNsPtr ns,
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001094 const xmlChar *name, const xmlChar *content) {
Daniel Veillard0bef1311998-10-14 02:36:47 +00001095 xmlNodePtr cur;
1096
Daniel Veillardccb09631998-10-27 06:21:04 +00001097 cur = xmlNewNode(ns, name);
1098 if (cur != NULL) {
1099 cur->doc = doc;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001100 if (content != NULL) {
Daniel Veillardccb09631998-10-27 06:21:04 +00001101 cur->childs = xmlStringGetNodeList(doc, content);
Daniel Veillard1e346af1999-02-22 10:33:01 +00001102 UPDATE_LAST_CHILD(cur)
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001103 }
Daniel Veillardccb09631998-10-27 06:21:04 +00001104 }
Daniel Veillard0bef1311998-10-14 02:36:47 +00001105 return(cur);
1106}
1107
1108
Daniel Veillard97b58771998-10-20 06:14:16 +00001109/**
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001110 * xmlNewDocRawNode:
1111 * @doc: the document
1112 * @ns: namespace if any
1113 * @name: the node name
1114 * @content: the text content if any
1115 *
1116 * Creation of a new node element within a document. @ns and @content
1117 * are optionnal (NULL).
1118 *
1119 * Returns a pointer to the new node object.
1120 */
1121xmlNodePtr
1122xmlNewDocRawNode(xmlDocPtr doc, xmlNsPtr ns,
1123 const xmlChar *name, const xmlChar *content) {
1124 xmlNodePtr cur;
1125
1126 cur = xmlNewNode(ns, name);
1127 if (cur != NULL) {
1128 cur->doc = doc;
1129 if (content != NULL) {
1130 cur->childs = xmlNewDocText(doc, content);
1131 UPDATE_LAST_CHILD(cur)
1132 }
1133 }
1134 return(cur);
1135}
1136
1137
1138/**
Daniel Veillard97b58771998-10-20 06:14:16 +00001139 * xmlNewText:
1140 * @content: the text content
1141 *
1142 * Creation of a new text node.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001143 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001144 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001145xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001146xmlNewText(const xmlChar *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001147 xmlNodePtr cur;
1148
1149 /*
1150 * Allocate a new node and fill the fields.
1151 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001152 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillard260a68f1998-08-13 03:39:55 +00001153 if (cur == NULL) {
1154 fprintf(stderr, "xmlNewText : malloc failed\n");
1155 return(NULL);
1156 }
1157
Daniel Veillard33942841998-10-18 19:12:41 +00001158 cur->type = XML_TEXT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001159 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001160 cur->parent = NULL;
1161 cur->next = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001162 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001163 cur->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001164 cur->last = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001165 cur->properties = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001166 cur->type = XML_TEXT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001167 cur->name = xmlStrdup(xmlStringText);
1168 cur->ns = NULL;
1169 cur->nsDef = NULL;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001170 if (content != NULL) {
1171#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard260a68f1998-08-13 03:39:55 +00001172 cur->content = xmlStrdup(content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001173#else
1174 cur->content = xmlBufferCreateSize(0);
1175 xmlBufferSetAllocationScheme(cur->content,
1176 xmlGetBufferAllocationScheme());
1177 xmlBufferAdd(cur->content, content, -1);
1178#endif
1179 } else
Daniel Veillard260a68f1998-08-13 03:39:55 +00001180 cur->content = NULL;
Daniel Veillard00fdf371999-10-08 09:40:39 +00001181#ifndef XML_WITHOUT_CORBA
1182 cur->_private = NULL;
1183 cur->vepv = NULL;
1184#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001185 return(cur);
1186}
1187
Daniel Veillard97b58771998-10-20 06:14:16 +00001188/**
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001189 * xmlNewTextChild:
1190 * @parent: the parent node
1191 * @ns: a namespace if any
1192 * @name: the name of the child
1193 * @content: the text content of the child if any.
1194 *
1195 * Creation of a new child element, added at the end of @parent childs list.
1196 * @ns and @content parameters are optionnal (NULL). If content is non NULL,
1197 * a child TEXT node will be created containing the string content.
1198 *
1199 * Returns a pointer to the new node object.
1200 */
1201xmlNodePtr
1202xmlNewTextChild(xmlNodePtr parent, xmlNsPtr ns,
1203 const xmlChar *name, const xmlChar *content) {
1204 xmlNodePtr cur, prev;
1205
1206 if (parent == NULL) {
1207 fprintf(stderr, "xmlNewTextChild : parent == NULL\n");
1208 return(NULL);
1209 }
1210
1211 if (name == NULL) {
1212 fprintf(stderr, "xmlNewTextChild : name == NULL\n");
1213 return(NULL);
1214 }
1215
1216 /*
1217 * Allocate a new node
1218 */
1219 if (ns == NULL)
1220 cur = xmlNewDocRawNode(parent->doc, parent->ns, name, content);
1221 else
1222 cur = xmlNewDocRawNode(parent->doc, ns, name, content);
1223 if (cur == NULL) return(NULL);
1224
1225 /*
1226 * add the new element at the end of the childs list.
1227 */
1228 cur->type = XML_ELEMENT_NODE;
1229 cur->parent = parent;
1230 cur->doc = parent->doc;
1231 if (parent->childs == NULL) {
1232 parent->childs = cur;
1233 parent->last = cur;
1234 } else {
1235 prev = parent->last;
1236 prev->next = cur;
1237 cur->prev = prev;
1238 parent->last = cur;
1239 }
1240
1241 return(cur);
1242}
1243
1244/**
Daniel Veillardccb09631998-10-27 06:21:04 +00001245 * xmlNewReference:
1246 * @doc: the document
1247 * @name: the reference name, or the reference string with & and ;
1248 *
1249 * Creation of a new reference node.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001250 * Returns a pointer to the new node object.
Daniel Veillardccb09631998-10-27 06:21:04 +00001251 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001252xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001253xmlNewReference(xmlDocPtr doc, const xmlChar *name) {
Daniel Veillardccb09631998-10-27 06:21:04 +00001254 xmlNodePtr cur;
1255 xmlEntityPtr ent;
1256
1257 /*
1258 * Allocate a new node and fill the fields.
1259 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001260 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillardccb09631998-10-27 06:21:04 +00001261 if (cur == NULL) {
1262 fprintf(stderr, "xmlNewText : malloc failed\n");
1263 return(NULL);
1264 }
1265
1266 cur->type = XML_ENTITY_REF_NODE;
Daniel Veillard10c6a8f1998-10-28 01:00:12 +00001267 cur->doc = doc;
Daniel Veillardccb09631998-10-27 06:21:04 +00001268 cur->parent = NULL;
1269 cur->next = NULL;
1270 cur->prev = NULL;
1271 cur->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001272 cur->last = NULL;
Daniel Veillardccb09631998-10-27 06:21:04 +00001273 cur->properties = NULL;
1274 if (name[0] == '&') {
1275 int len;
1276 name++;
1277 len = xmlStrlen(name);
1278 if (name[len - 1] == ';')
1279 cur->name = xmlStrndup(name, len - 1);
1280 else
1281 cur->name = xmlStrndup(name, len);
1282 } else
1283 cur->name = xmlStrdup(name);
1284 cur->ns = NULL;
1285 cur->nsDef = NULL;
1286
1287 ent = xmlGetDocEntity(doc, cur->name);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001288 if (ent != NULL) {
1289#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardccb09631998-10-27 06:21:04 +00001290 cur->content = ent->content;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001291#else
1292 /*
1293 * CJN 11.18.99 this might be a problem, since the xmlBuffer gets
1294 * a copy of this pointer. Let's hope we don't manipulate it
1295 * later
1296 */
1297 cur->content = xmlBufferCreateSize(0);
1298 xmlBufferSetAllocationScheme(cur->content,
1299 xmlGetBufferAllocationScheme());
1300 if (ent->content != NULL)
1301 xmlBufferAdd(cur->content, ent->content, -1);
1302#endif
1303 } else
Daniel Veillardccb09631998-10-27 06:21:04 +00001304 cur->content = NULL;
Daniel Veillard00fdf371999-10-08 09:40:39 +00001305#ifndef XML_WITHOUT_CORBA
1306 cur->_private = NULL;
1307 cur->vepv = NULL;
1308#endif
Daniel Veillardccb09631998-10-27 06:21:04 +00001309 return(cur);
1310}
1311
1312/**
Daniel Veillard97b58771998-10-20 06:14:16 +00001313 * xmlNewDocText:
1314 * @doc: the document
1315 * @content: the text content
1316 *
1317 * Creation of a new text node within a document.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001318 * Returns a pointer to the new node object.
Daniel Veillard97b58771998-10-20 06:14:16 +00001319 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001320xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001321xmlNewDocText(xmlDocPtr doc, const xmlChar *content) {
Daniel Veillard0bef1311998-10-14 02:36:47 +00001322 xmlNodePtr cur;
1323
1324 cur = xmlNewText(content);
1325 if (cur != NULL) cur->doc = doc;
1326 return(cur);
1327}
1328
Daniel Veillard97b58771998-10-20 06:14:16 +00001329/**
Daniel Veillardccb09631998-10-27 06:21:04 +00001330 * xmlNewTextLen:
Daniel Veillard97b58771998-10-20 06:14:16 +00001331 * @content: the text content
1332 * @len: the text len.
1333 *
1334 * Creation of a new text node with an extra parameter for the content's lenght
Daniel Veillard1e346af1999-02-22 10:33:01 +00001335 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001336 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001337xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001338xmlNewTextLen(const xmlChar *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001339 xmlNodePtr cur;
1340
1341 /*
1342 * Allocate a new node and fill the fields.
1343 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001344 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillard260a68f1998-08-13 03:39:55 +00001345 if (cur == NULL) {
1346 fprintf(stderr, "xmlNewText : malloc failed\n");
1347 return(NULL);
1348 }
1349
Daniel Veillard33942841998-10-18 19:12:41 +00001350 cur->type = XML_TEXT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001351 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001352 cur->parent = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001353 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001354 cur->next = NULL;
1355 cur->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001356 cur->last = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001357 cur->properties = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001358 cur->type = XML_TEXT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001359 cur->name = xmlStrdup(xmlStringText);
1360 cur->ns = NULL;
1361 cur->nsDef = NULL;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001362 if (content != NULL) {
1363#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard260a68f1998-08-13 03:39:55 +00001364 cur->content = xmlStrndup(content, len);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001365#else
1366 cur->content = xmlBufferCreateSize(len);
1367 xmlBufferSetAllocationScheme(cur->content,
1368 xmlGetBufferAllocationScheme());
1369 xmlBufferAdd(cur->content, content, len);
1370#endif
1371 } else
Daniel Veillard260a68f1998-08-13 03:39:55 +00001372 cur->content = NULL;
Daniel Veillard00fdf371999-10-08 09:40:39 +00001373#ifndef XML_WITHOUT_CORBA
1374 cur->_private = NULL;
1375 cur->vepv = NULL;
1376#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001377 return(cur);
1378}
1379
Daniel Veillard97b58771998-10-20 06:14:16 +00001380/**
1381 * xmlNewDocTextLen:
1382 * @doc: the document
1383 * @content: the text content
1384 * @len: the text len.
1385 *
1386 * Creation of a new text node with an extra content lenght parameter. The
1387 * text node pertain to a given document.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001388 * Returns a pointer to the new node object.
Daniel Veillard97b58771998-10-20 06:14:16 +00001389 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001390xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001391xmlNewDocTextLen(xmlDocPtr doc, const xmlChar *content, int len) {
Daniel Veillard0bef1311998-10-14 02:36:47 +00001392 xmlNodePtr cur;
1393
1394 cur = xmlNewTextLen(content, len);
1395 if (cur != NULL) cur->doc = doc;
1396 return(cur);
1397}
1398
Daniel Veillard97b58771998-10-20 06:14:16 +00001399/**
1400 * xmlNewComment:
1401 * @content: the comment content
1402 *
1403 * Creation of a new node containing a comment.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001404 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001405 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001406xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001407xmlNewComment(const xmlChar *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001408 xmlNodePtr cur;
1409
1410 /*
1411 * Allocate a new node and fill the fields.
1412 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001413 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillard260a68f1998-08-13 03:39:55 +00001414 if (cur == NULL) {
1415 fprintf(stderr, "xmlNewComment : malloc failed\n");
1416 return(NULL);
1417 }
1418
Daniel Veillard33942841998-10-18 19:12:41 +00001419 cur->type = XML_COMMENT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001420 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001421 cur->parent = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001422 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001423 cur->next = NULL;
1424 cur->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001425 cur->last = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001426 cur->properties = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001427 cur->type = XML_COMMENT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001428 cur->name = xmlStrdup(xmlStringText);
1429 cur->ns = NULL;
1430 cur->nsDef = NULL;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001431 if (content != NULL) {
1432#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard260a68f1998-08-13 03:39:55 +00001433 cur->content = xmlStrdup(content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001434#else
1435 cur->content = xmlBufferCreateSize(0);
1436 xmlBufferSetAllocationScheme(cur->content,
1437 xmlGetBufferAllocationScheme());
1438 xmlBufferAdd(cur->content, content, -1);
1439#endif
1440 } else
Daniel Veillard260a68f1998-08-13 03:39:55 +00001441 cur->content = NULL;
Daniel Veillard00fdf371999-10-08 09:40:39 +00001442#ifndef XML_WITHOUT_CORBA
1443 cur->_private = NULL;
1444 cur->vepv = NULL;
1445#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001446 return(cur);
1447}
1448
Daniel Veillard97b58771998-10-20 06:14:16 +00001449/**
Daniel Veillardb05deb71999-08-10 19:04:08 +00001450 * xmlNewCDataBlock:
1451 * @doc: the document
1452 * @content: the CData block content content
1453 * @len: the length of the block
1454 *
1455 * Creation of a new node containing a CData block.
1456 * Returns a pointer to the new node object.
1457 */
1458xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001459xmlNewCDataBlock(xmlDocPtr doc, const xmlChar *content, int len) {
Daniel Veillardb05deb71999-08-10 19:04:08 +00001460 xmlNodePtr cur;
1461
1462 /*
1463 * Allocate a new node and fill the fields.
1464 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001465 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillardb05deb71999-08-10 19:04:08 +00001466 if (cur == NULL) {
1467 fprintf(stderr, "xmlNewCDataBlock : malloc failed\n");
1468 return(NULL);
1469 }
1470
1471 cur->type = XML_CDATA_SECTION_NODE;
1472 cur->doc = NULL;
1473 cur->parent = NULL;
1474 cur->prev = NULL;
1475 cur->next = NULL;
1476 cur->childs = NULL;
1477 cur->last = NULL;
1478 cur->properties = NULL;
1479 cur->name = xmlStrdup(xmlStringText);
1480 cur->ns = NULL;
1481 cur->nsDef = NULL;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001482 if (content != NULL) {
1483#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardb05deb71999-08-10 19:04:08 +00001484 cur->content = xmlStrndup(content, len);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001485#else
1486 cur->content = xmlBufferCreateSize(len);
1487 xmlBufferSetAllocationScheme(cur->content,
1488 xmlGetBufferAllocationScheme());
1489 xmlBufferAdd(cur->content, content, len);
1490#endif
Daniel Veillardb05deb71999-08-10 19:04:08 +00001491 } else
1492 cur->content = NULL;
Daniel Veillard00fdf371999-10-08 09:40:39 +00001493#ifndef XML_WITHOUT_CORBA
1494 cur->_private = NULL;
1495 cur->vepv = NULL;
1496#endif
Daniel Veillardb05deb71999-08-10 19:04:08 +00001497 return(cur);
1498}
1499
1500/**
Daniel Veillard1e346af1999-02-22 10:33:01 +00001501 * xmlNewDocComment:
Daniel Veillard97b58771998-10-20 06:14:16 +00001502 * @doc: the document
1503 * @content: the comment content
1504 *
1505 * Creation of a new node containing a commentwithin a document.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001506 * Returns a pointer to the new node object.
Daniel Veillard97b58771998-10-20 06:14:16 +00001507 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001508xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001509xmlNewDocComment(xmlDocPtr doc, const xmlChar *content) {
Daniel Veillard0bef1311998-10-14 02:36:47 +00001510 xmlNodePtr cur;
1511
1512 cur = xmlNewComment(content);
1513 if (cur != NULL) cur->doc = doc;
1514 return(cur);
1515}
1516
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001517
Daniel Veillard97b58771998-10-20 06:14:16 +00001518/**
1519 * xmlNewChild:
1520 * @parent: the parent node
1521 * @ns: a namespace if any
1522 * @name: the name of the child
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001523 * @content: the XML content of the child if any.
Daniel Veillard97b58771998-10-20 06:14:16 +00001524 *
Daniel Veillard97b58771998-10-20 06:14:16 +00001525 * Creation of a new child element, added at the end of @parent childs list.
Daniel Veillardccb09631998-10-27 06:21:04 +00001526 * @ns and @content parameters are optionnal (NULL). If content is non NULL,
1527 * a child list containing the TEXTs and ENTITY_REFs node will be created.
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001528 * NOTE: @content is supposed to be a piece of XML CDATA, so it allow entities
1529 * references, but XML special chars need to be escaped first by using
1530 * xmlEncodeEntitiesReentrant(). Use xmlNewTextChild() if entities
1531 * support is not needed.
1532 *
Daniel Veillard1e346af1999-02-22 10:33:01 +00001533 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001534 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001535xmlNodePtr
1536xmlNewChild(xmlNodePtr parent, xmlNsPtr ns,
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001537 const xmlChar *name, const xmlChar *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001538 xmlNodePtr cur, prev;
1539
1540 if (parent == NULL) {
1541 fprintf(stderr, "xmlNewChild : parent == NULL\n");
1542 return(NULL);
1543 }
1544
1545 if (name == NULL) {
1546 fprintf(stderr, "xmlNewChild : name == NULL\n");
1547 return(NULL);
1548 }
1549
1550 /*
1551 * Allocate a new node
1552 */
1553 if (ns == NULL)
Daniel Veillardccb09631998-10-27 06:21:04 +00001554 cur = xmlNewDocNode(parent->doc, parent->ns, name, content);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001555 else
Daniel Veillardccb09631998-10-27 06:21:04 +00001556 cur = xmlNewDocNode(parent->doc, ns, name, content);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001557 if (cur == NULL) return(NULL);
1558
1559 /*
1560 * add the new element at the end of the childs list.
1561 */
Daniel Veillardccb09631998-10-27 06:21:04 +00001562 cur->type = XML_ELEMENT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001563 cur->parent = parent;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001564 cur->doc = parent->doc;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001565 if (parent->childs == NULL) {
1566 parent->childs = cur;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001567 parent->last = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001568 } else {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001569 prev = parent->last;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001570 prev->next = cur;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001571 cur->prev = prev;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001572 parent->last = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001573 }
1574
1575 return(cur);
1576}
1577
Daniel Veillard97b58771998-10-20 06:14:16 +00001578/**
Daniel Veillardb96e6431999-08-29 21:02:19 +00001579 * xmlAddSibling:
1580 * @cur: the child node
1581 * @elem: the new node
1582 *
1583 * Add a new element to the list of siblings of @cur
1584 * Returns the element or NULL in case of error.
1585 */
1586xmlNodePtr
1587xmlAddSibling(xmlNodePtr cur, xmlNodePtr elem) {
1588 xmlNodePtr parent;
1589
1590 if (cur == NULL) {
1591 fprintf(stderr, "xmlAddSibling : cur == NULL\n");
1592 return(NULL);
1593 }
1594
1595 if (elem == NULL) {
1596 fprintf(stderr, "xmlAddSibling : elem == NULL\n");
1597 return(NULL);
1598 }
1599
1600 if ((cur->doc != NULL) && (elem->doc != NULL) &&
1601 (cur->doc != elem->doc)) {
1602 fprintf(stderr,
1603 "xmlAddSibling: Elements moved to a different document\n");
1604 }
1605
1606 while (cur->next != NULL) cur = cur->next;
1607
1608 if (elem->doc == NULL)
1609 elem->doc = cur->doc; /* the parent may not be linked to a doc ! */
1610
1611 parent = cur->parent;
1612 elem->prev = cur;
1613 elem->next = NULL;
1614 elem->parent = parent;
1615 cur->next = elem;
1616 if (parent != NULL)
1617 parent->last = elem;
1618
1619 return(elem);
1620}
1621
1622/**
Daniel Veillard97b58771998-10-20 06:14:16 +00001623 * xmlAddChild:
1624 * @parent: the parent node
1625 * @cur: the child node
1626 *
1627 * Add a new child element, to @parent, at the end of the child list.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001628 * Returns the child or NULL in case of error.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001629 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001630xmlNodePtr
1631xmlAddChild(xmlNodePtr parent, xmlNodePtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001632 xmlNodePtr prev;
1633
1634 if (parent == NULL) {
1635 fprintf(stderr, "xmladdChild : parent == NULL\n");
1636 return(NULL);
1637 }
1638
1639 if (cur == NULL) {
1640 fprintf(stderr, "xmladdChild : child == NULL\n");
1641 return(NULL);
1642 }
1643
Daniel Veillard0bef1311998-10-14 02:36:47 +00001644 if ((cur->doc != NULL) && (parent->doc != NULL) &&
1645 (cur->doc != parent->doc)) {
1646 fprintf(stderr, "Elements moved to a different document\n");
1647 }
1648
Daniel Veillard260a68f1998-08-13 03:39:55 +00001649 /*
1650 * add the new element at the end of the childs list.
1651 */
1652 cur->parent = parent;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001653 cur->doc = parent->doc; /* the parent may not be linked to a doc ! */
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001654
Daniel Veillardccb09631998-10-27 06:21:04 +00001655 /*
1656 * Handle the case where parent->content != NULL, in that case it will
1657 * create a intermediate TEXT node.
1658 */
1659 if (parent->content != NULL) {
1660 xmlNodePtr text;
1661
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001662#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardccb09631998-10-27 06:21:04 +00001663 text = xmlNewDocText(parent->doc, parent->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001664#else
1665 text = xmlNewDocText(parent->doc, xmlBufferContent(parent->content));
1666#endif
Daniel Veillardccb09631998-10-27 06:21:04 +00001667 if (text != NULL) {
1668 text->next = parent->childs;
1669 if (text->next != NULL)
1670 text->next->prev = text;
1671 parent->childs = text;
Daniel Veillard1e346af1999-02-22 10:33:01 +00001672 UPDATE_LAST_CHILD(parent)
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001673#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard6454aec1999-09-02 22:04:43 +00001674 xmlFree(parent->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001675#else
1676 xmlBufferFree(parent->content);
1677#endif
Daniel Veillardccb09631998-10-27 06:21:04 +00001678 parent->content = NULL;
1679 }
1680 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00001681 if (parent->childs == NULL) {
1682 parent->childs = cur;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001683 parent->last = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001684 } else {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001685 prev = parent->last;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001686 prev->next = cur;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001687 cur->prev = prev;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001688 parent->last = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001689 }
1690
1691 return(cur);
1692}
1693
Daniel Veillard97b58771998-10-20 06:14:16 +00001694/**
1695 * xmlGetLastChild:
1696 * @parent: the parent node
1697 *
1698 * Search the last child of a node.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001699 * Returns the last child or NULL if none.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001700 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001701xmlNodePtr
1702xmlGetLastChild(xmlNodePtr parent) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001703 if (parent == NULL) {
1704 fprintf(stderr, "xmlGetLastChild : parent == NULL\n");
1705 return(NULL);
1706 }
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001707 return(parent->last);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001708}
1709
Daniel Veillard97b58771998-10-20 06:14:16 +00001710/**
1711 * xmlFreeNodeList:
1712 * @cur: the first node in the list
1713 *
1714 * Free a node and all its siblings, this is a recursive behaviour, all
1715 * the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001716 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001717void
1718xmlFreeNodeList(xmlNodePtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001719 xmlNodePtr next;
1720 if (cur == NULL) {
1721 fprintf(stderr, "xmlFreeNodeList : node == NULL\n");
1722 return;
1723 }
1724 while (cur != NULL) {
1725 next = cur->next;
1726 xmlFreeNode(cur);
1727 cur = next;
1728 }
1729}
1730
Daniel Veillard97b58771998-10-20 06:14:16 +00001731/**
1732 * xmlFreeNode:
1733 * @cur: the node
1734 *
1735 * Free a node, this is a recursive behaviour, all the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001736 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001737void
1738xmlFreeNode(xmlNodePtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001739 if (cur == NULL) {
1740 fprintf(stderr, "xmlFreeNode : node == NULL\n");
1741 return;
1742 }
Daniel Veillardccb09631998-10-27 06:21:04 +00001743 cur->doc = NULL;
1744 cur->parent = NULL;
1745 cur->next = NULL;
1746 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001747 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillardccb09631998-10-27 06:21:04 +00001748 if (cur->properties != NULL) xmlFreePropList(cur->properties);
1749 if (cur->type != XML_ENTITY_REF_NODE)
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001750#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard6454aec1999-09-02 22:04:43 +00001751 if (cur->content != NULL) xmlFree(cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001752#else
1753 if (cur->content != NULL) xmlBufferFree(cur->content);
1754#endif
Daniel Veillard6454aec1999-09-02 22:04:43 +00001755 if (cur->name != NULL) xmlFree((char *) cur->name);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001756 if (cur->nsDef != NULL) xmlFreeNsList(cur->nsDef);
1757 memset(cur, -1, sizeof(xmlNode));
Daniel Veillard6454aec1999-09-02 22:04:43 +00001758 xmlFree(cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001759}
1760
Daniel Veillard16253641998-10-28 22:58:05 +00001761/**
1762 * xmlUnlinkNode:
1763 * @cur: the node
1764 *
1765 * Unlink a node from it's current context, the node is not freed
1766 */
1767void
1768xmlUnlinkNode(xmlNodePtr cur) {
1769 if (cur == NULL) {
1770 fprintf(stderr, "xmlUnlinkNode : node == NULL\n");
1771 return;
1772 }
1773 if ((cur->parent != NULL) && (cur->parent->childs == cur))
1774 cur->parent->childs = cur->next;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001775 if ((cur->parent != NULL) && (cur->parent->last == cur))
1776 cur->parent->last = cur->prev;
Daniel Veillard16253641998-10-28 22:58:05 +00001777 if (cur->next != NULL)
1778 cur->next->prev = cur->prev;
1779 if (cur->prev != NULL)
1780 cur->prev->next = cur->next;
1781 cur->next = cur->prev = NULL;
1782 cur->parent = NULL;
1783}
1784
Daniel Veillard260a68f1998-08-13 03:39:55 +00001785/************************************************************************
1786 * *
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001787 * Copy operations *
1788 * *
1789 ************************************************************************/
1790
1791/**
1792 * xmlCopyNamespace:
1793 * @cur: the namespace
1794 *
1795 * Do a copy of the namespace.
1796 *
1797 * Returns: a new xmlNsPtr, or NULL in case of error.
1798 */
1799xmlNsPtr
1800xmlCopyNamespace(xmlNsPtr cur) {
1801 xmlNsPtr ret;
1802
1803 if (cur == NULL) return(NULL);
1804 switch (cur->type) {
1805 case XML_GLOBAL_NAMESPACE:
1806 ret = xmlNewGlobalNs(NULL, cur->href, cur->prefix);
1807 break;
1808 case XML_LOCAL_NAMESPACE:
1809 ret = xmlNewNs(NULL, cur->href, cur->prefix);
1810 break;
1811 default:
1812 fprintf(stderr, "xmlCopyNamespace: unknown type %d\n", cur->type);
1813 return(NULL);
1814 }
1815 return(ret);
1816}
1817
1818/**
1819 * xmlCopyNamespaceList:
1820 * @cur: the first namespace
1821 *
1822 * Do a copy of an namespace list.
1823 *
1824 * Returns: a new xmlNsPtr, or NULL in case of error.
1825 */
1826xmlNsPtr
1827xmlCopyNamespaceList(xmlNsPtr cur) {
1828 xmlNsPtr ret = NULL;
1829 xmlNsPtr p = NULL,q;
1830
1831 while (cur != NULL) {
1832 q = xmlCopyNamespace(cur);
1833 if (p == NULL) {
1834 ret = p = q;
1835 } else {
1836 p->next = q;
1837 p = q;
1838 }
1839 cur = cur->next;
1840 }
1841 return(ret);
1842}
1843
1844/**
1845 * xmlCopyProp:
Daniel Veillardb96e6431999-08-29 21:02:19 +00001846 * @target: the element where the attribute will be grafted
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001847 * @cur: the attribute
1848 *
1849 * Do a copy of the attribute.
1850 *
1851 * Returns: a new xmlAttrPtr, or NULL in case of error.
1852 */
1853xmlAttrPtr
Daniel Veillardb96e6431999-08-29 21:02:19 +00001854xmlCopyProp(xmlNodePtr target, xmlAttrPtr cur) {
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001855 xmlAttrPtr ret;
1856
1857 if (cur == NULL) return(NULL);
1858 if (cur->val != NULL)
1859 ret = xmlNewDocProp(cur->val->doc, cur->name, NULL);
1860 else
1861 ret = xmlNewDocProp(NULL, cur->name, NULL);
1862 if (ret == NULL) return(NULL);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001863
1864 if ((cur->ns != NULL) && (target != NULL)) {
1865 xmlNsPtr ns;
1866
1867 ns = xmlSearchNs(target->doc, target, cur->ns->prefix);
1868 ret->ns = ns;
1869 } else
1870 ret->ns = NULL;
1871
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001872 if (cur->val != NULL)
1873 ret->val = xmlCopyNodeList(cur->val);
1874 return(ret);
1875}
1876
1877/**
1878 * xmlCopyPropList:
Daniel Veillardb96e6431999-08-29 21:02:19 +00001879 * @target: the element where the attributes will be grafted
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001880 * @cur: the first attribute
1881 *
1882 * Do a copy of an attribute list.
1883 *
1884 * Returns: a new xmlAttrPtr, or NULL in case of error.
1885 */
1886xmlAttrPtr
Daniel Veillardb96e6431999-08-29 21:02:19 +00001887xmlCopyPropList(xmlNodePtr target, xmlAttrPtr cur) {
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001888 xmlAttrPtr ret = NULL;
1889 xmlAttrPtr p = NULL,q;
1890
1891 while (cur != NULL) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00001892 q = xmlCopyProp(target, cur);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001893 if (p == NULL) {
1894 ret = p = q;
1895 } else {
1896 p->next = q;
1897 p = q;
1898 }
1899 cur = cur->next;
1900 }
1901 return(ret);
1902}
1903
1904/*
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001905 * NOTE abeut the CopyNode operations !
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001906 *
1907 * They are splitted into external and internal parts for one
1908 * tricky reason: namespaces. Doing a direct copy of a node
1909 * say RPM:Copyright without changing the namespace pointer to
1910 * something else can produce stale links. One way to do it is
1911 * to keep a reference counter but this doesn't work as soon
1912 * as one move the element or the subtree out of the scope of
1913 * the existing namespace. The actual solution seems to add
1914 * a copy of the namespace at the top of the copied tree if
1915 * not available in the subtree.
1916 * Hence two functions, the public front-end call the inner ones
1917 */
1918
1919static xmlNodePtr
1920xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent);
1921
1922static xmlNodePtr
1923xmlStaticCopyNode(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent,
1924 int recursive) {
1925 xmlNodePtr ret;
1926
1927 if (node == NULL) return(NULL);
1928 /*
1929 * Allocate a new node and fill the fields.
1930 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001931 ret = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001932 if (ret == NULL) {
1933 fprintf(stderr, "xmlStaticCopyNode : malloc failed\n");
1934 return(NULL);
1935 }
1936
1937 ret->type = node->type;
1938 ret->doc = doc;
1939 ret->parent = parent;
1940 ret->next = NULL;
1941 ret->prev = NULL;
1942 ret->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001943 ret->last = NULL;
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001944 ret->properties = NULL;
1945 if (node->name != NULL)
1946 ret->name = xmlStrdup(node->name);
1947 else
1948 ret->name = NULL;
1949 ret->ns = NULL;
1950 ret->nsDef = NULL;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001951 if ((node->content != NULL) && (node->type != XML_ENTITY_REF_NODE)) {
1952#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001953 ret->content = xmlStrdup(node->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001954#else
1955 ret->content = xmlBufferCreateSize(xmlBufferLength(node->content));
1956 xmlBufferSetAllocationScheme(ret->content,
1957 xmlGetBufferAllocationScheme());
1958 xmlBufferAdd(ret->content,
1959 xmlBufferContent(node->content),
1960 xmlBufferLength(node->content));
1961#endif
1962 } else
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001963 ret->content = NULL;
Daniel Veillard27d88741999-05-29 11:51:49 +00001964#ifndef XML_WITHOUT_CORBA
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001965 ret->_private = NULL;
1966 ret->vepv = NULL;
1967#endif
1968 if (parent != NULL)
1969 xmlAddChild(parent, ret);
1970
1971 if (!recursive) return(ret);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001972 if (node->nsDef != NULL)
1973 ret->nsDef = xmlCopyNamespaceList(node->nsDef);
1974
1975 if (node->ns != NULL) {
1976 xmlNsPtr ns;
1977
1978 ns = xmlSearchNs(doc, ret, node->ns->prefix);
1979 if (ns == NULL) {
1980 /*
1981 * Humm, we are copying an element whose namespace is defined
1982 * out of the new tree scope. Search it in the original tree
1983 * and add it at the top of the new tree
1984 */
1985 ns = xmlSearchNs(node->doc, node, node->ns->prefix);
1986 if (ns != NULL) {
1987 xmlNodePtr root = ret;
1988
1989 while (root->parent != NULL) root = root->parent;
1990 xmlNewNs(root, ns->href, ns->prefix);
1991 }
1992 } else {
1993 /*
1994 * reference the existing namespace definition in our own tree.
1995 */
1996 ret->ns = ns;
1997 }
1998 }
Daniel Veillardb96e6431999-08-29 21:02:19 +00001999 if (node->properties != NULL)
2000 ret->properties = xmlCopyPropList(ret, node->properties);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002001 if (node->childs != NULL)
2002 ret->childs = xmlStaticCopyNodeList(node->childs, doc, ret);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002003 UPDATE_LAST_CHILD(ret)
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002004 return(ret);
2005}
2006
2007static xmlNodePtr
2008xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent) {
2009 xmlNodePtr ret = NULL;
2010 xmlNodePtr p = NULL,q;
2011
2012 while (node != NULL) {
2013 q = xmlStaticCopyNode(node, doc, parent, 1);
2014 if (parent == NULL) {
2015 if (ret == NULL) ret = q;
2016 } else {
2017 if (ret == NULL) {
2018 q->prev = NULL;
2019 ret = p = q;
2020 } else {
2021 p->next = q;
2022 q->prev = p;
2023 p = q;
2024 }
2025 }
2026 node = node->next;
2027 }
2028 return(ret);
2029}
2030
2031/**
2032 * xmlCopyNode:
2033 * @node: the node
2034 * @recursive: if 1 do a recursive copy.
2035 *
2036 * Do a copy of the node.
2037 *
2038 * Returns: a new xmlNodePtr, or NULL in case of error.
2039 */
2040xmlNodePtr
2041xmlCopyNode(xmlNodePtr node, int recursive) {
2042 xmlNodePtr ret;
2043
2044 ret = xmlStaticCopyNode(node, NULL, NULL, recursive);
2045 return(ret);
2046}
2047
2048/**
2049 * xmlCopyNodeList:
2050 * @node: the first node in the list.
2051 *
2052 * Do a recursive copy of the node list.
2053 *
2054 * Returns: a new xmlNodePtr, or NULL in case of error.
2055 */
2056xmlNodePtr xmlCopyNodeList(xmlNodePtr node) {
2057 xmlNodePtr ret = xmlStaticCopyNodeList(node, NULL, NULL);
2058 return(ret);
2059}
2060
2061/**
2062 * xmlCopyElement:
2063 * @elem: the element
2064 *
2065 * Do a copy of the element definition.
2066 *
2067 * Returns: a new xmlElementPtr, or NULL in case of error.
2068xmlElementPtr
2069xmlCopyElement(xmlElementPtr elem) {
2070 xmlElementPtr ret;
2071
2072 if (elem == NULL) return(NULL);
2073 ret = xmlNewDocElement(elem->doc, elem->ns, elem->name, elem->content);
2074 if (ret == NULL) return(NULL);
2075 if (!recursive) return(ret);
2076 if (elem->properties != NULL)
2077 ret->properties = xmlCopyPropList(elem->properties);
2078
2079 if (elem->nsDef != NULL)
2080 ret->nsDef = xmlCopyNamespaceList(elem->nsDef);
2081 if (elem->childs != NULL)
2082 ret->childs = xmlCopyElementList(elem->childs);
2083 return(ret);
2084}
2085 */
2086
2087/**
2088 * xmlCopyDtd:
2089 * @dtd: the dtd
2090 *
2091 * Do a copy of the dtd.
2092 *
2093 * Returns: a new xmlDtdPtr, or NULL in case of error.
2094 */
2095xmlDtdPtr
2096xmlCopyDtd(xmlDtdPtr dtd) {
2097 xmlDtdPtr ret;
2098
2099 if (dtd == NULL) return(NULL);
2100 ret = xmlNewDtd(NULL, dtd->name, dtd->ExternalID, dtd->SystemID);
2101 if (ret == NULL) return(NULL);
2102 if (dtd->entities != NULL)
2103 ret->entities = (void *) xmlCopyEntitiesTable(
2104 (xmlEntitiesTablePtr) dtd->entities);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002105 if (dtd->notations != NULL)
2106 ret->notations = (void *) xmlCopyNotationTable(
2107 (xmlNotationTablePtr) dtd->notations);
2108 if (dtd->elements != NULL)
2109 ret->elements = (void *) xmlCopyElementTable(
2110 (xmlElementTablePtr) dtd->elements);
2111 if (dtd->attributes != NULL)
2112 ret->attributes = (void *) xmlCopyAttributeTable(
2113 (xmlAttributeTablePtr) dtd->attributes);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002114 return(ret);
2115}
2116
2117/**
2118 * xmlCopyDoc:
2119 * @doc: the document
2120 * @recursive: if 1 do a recursive copy.
2121 *
2122 * Do a copy of the document info. If recursive, the content tree will
2123 * be copied too as well as Dtd, namespaces and entities.
2124 *
2125 * Returns: a new xmlDocPtr, or NULL in case of error.
2126 */
2127xmlDocPtr
2128xmlCopyDoc(xmlDocPtr doc, int recursive) {
2129 xmlDocPtr ret;
2130
2131 if (doc == NULL) return(NULL);
2132 ret = xmlNewDoc(doc->version);
2133 if (ret == NULL) return(NULL);
2134 if (doc->name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +00002135 ret->name = xmlMemStrdup(doc->name);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002136 if (doc->encoding != NULL)
2137 ret->encoding = xmlStrdup(doc->encoding);
2138 ret->compression = doc->compression;
2139 ret->standalone = doc->standalone;
2140 if (!recursive) return(ret);
2141
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002142 if (doc->intSubset != NULL)
2143 ret->intSubset = xmlCopyDtd(doc->intSubset);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002144 if (doc->oldNs != NULL)
2145 ret->oldNs = xmlCopyNamespaceList(doc->oldNs);
2146 if (doc->root != NULL)
2147 ret->root = xmlStaticCopyNodeList(doc->root, ret, NULL);
2148 return(ret);
2149}
2150
2151/************************************************************************
2152 * *
Daniel Veillard260a68f1998-08-13 03:39:55 +00002153 * Content access functions *
2154 * *
2155 ************************************************************************/
2156
Daniel Veillard97b58771998-10-20 06:14:16 +00002157/**
Daniel Veillardb96e6431999-08-29 21:02:19 +00002158 * xmlNodeSetLang:
2159 * @cur: the node being changed
2160 * @lang: the langage description
2161 *
2162 * Searches the language of a node, i.e. the values of the xml:lang
2163 * attribute or the one carried by the nearest ancestor.
Daniel Veillardb96e6431999-08-29 21:02:19 +00002164 */
2165void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002166xmlNodeSetLang(xmlNodePtr cur, const xmlChar *lang) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00002167 /* TODO xmlNodeSetLang check against the production [33] LanguageID */
2168 xmlSetProp(cur, BAD_CAST "xml:lang", lang);
2169}
2170
2171/**
2172 * xmlNodeGetLang:
2173 * @cur: the node being checked
2174 *
2175 * Searches the language of a node, i.e. the values of the xml:lang
2176 * attribute or the one carried by the nearest ancestor.
2177 *
2178 * Returns a pointer to the lang value, or NULL if not found
Daniel Veillarda819dac1999-11-24 18:04:22 +00002179 * It's up to the caller to free the memory.
Daniel Veillardb96e6431999-08-29 21:02:19 +00002180 */
Daniel Veillarda819dac1999-11-24 18:04:22 +00002181xmlChar *
Daniel Veillardb96e6431999-08-29 21:02:19 +00002182xmlNodeGetLang(xmlNodePtr cur) {
Daniel Veillarda819dac1999-11-24 18:04:22 +00002183 xmlChar *lang;
Daniel Veillardb96e6431999-08-29 21:02:19 +00002184
2185 while (cur != NULL) {
2186 lang = xmlGetProp(cur, BAD_CAST "xml:lang");
2187 if (lang != NULL)
2188 return(lang);
2189 cur = cur->parent;
2190 }
2191 return(NULL);
2192}
2193
2194/**
Daniel Veillard16253641998-10-28 22:58:05 +00002195 * xmlNodeGetContent:
2196 * @cur: the node being read
2197 *
2198 * Read the value of a node, this can be either the text carried
2199 * directly by this node if it's a TEXT node or the aggregate string
2200 * of the values carried by this node child's (TEXT and ENTITY_REF).
2201 * Entity references are substitued.
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002202 * Returns a new xmlChar * or NULL if no content is available.
Daniel Veillard5099ae81999-04-21 20:12:07 +00002203 * It's up to the caller to free the memory.
Daniel Veillard16253641998-10-28 22:58:05 +00002204 */
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002205xmlChar *
Daniel Veillard16253641998-10-28 22:58:05 +00002206xmlNodeGetContent(xmlNodePtr cur) {
2207 if (cur == NULL) return(NULL);
2208 switch (cur->type) {
2209 case XML_DOCUMENT_FRAG_NODE:
2210 case XML_ELEMENT_NODE:
2211 return(xmlNodeListGetString(cur->doc, cur->childs, 1));
2212 break;
Daniel Veillardb96e6431999-08-29 21:02:19 +00002213 case XML_ATTRIBUTE_NODE: {
2214 xmlAttrPtr attr = (xmlAttrPtr) cur;
2215 if (attr->node != NULL)
2216 return(xmlNodeListGetString(attr->node->doc, attr->val, 1));
2217 else
2218 return(xmlNodeListGetString(NULL, attr->val, 1));
2219 break;
2220 }
2221 case XML_PI_NODE:
2222 if (cur->content != NULL)
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002223#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardb96e6431999-08-29 21:02:19 +00002224 return(xmlStrdup(cur->content));
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002225#else
2226 return(xmlStrdup(xmlBufferContent(cur->content)));
2227#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +00002228 return(NULL);
Daniel Veillard16253641998-10-28 22:58:05 +00002229 case XML_ENTITY_REF_NODE:
2230 case XML_ENTITY_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002231 case XML_COMMENT_NODE:
2232 case XML_DOCUMENT_NODE:
Daniel Veillard7c1206f1999-10-14 09:10:25 +00002233 case XML_HTML_DOCUMENT_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002234 case XML_DOCUMENT_TYPE_NODE:
2235 case XML_NOTATION_NODE:
2236 return(NULL);
Daniel Veillardb05deb71999-08-10 19:04:08 +00002237 case XML_CDATA_SECTION_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002238 case XML_TEXT_NODE:
2239 if (cur->content != NULL)
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002240#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard16253641998-10-28 22:58:05 +00002241 return(xmlStrdup(cur->content));
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002242#else
2243 return(xmlStrdup(xmlBufferContent(cur->content)));
2244#endif
Daniel Veillard16253641998-10-28 22:58:05 +00002245 return(NULL);
2246 }
2247 return(NULL);
2248}
2249
2250/**
Daniel Veillard97b58771998-10-20 06:14:16 +00002251 * xmlNodeSetContent:
2252 * @cur: the node being modified
2253 * @content: the new value of the content
2254 *
2255 * Replace the content of a node.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002256 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002257void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002258xmlNodeSetContent(xmlNodePtr cur, const xmlChar *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002259 if (cur == NULL) {
2260 fprintf(stderr, "xmlNodeSetContent : node == NULL\n");
2261 return;
2262 }
Daniel Veillard16253641998-10-28 22:58:05 +00002263 switch (cur->type) {
2264 case XML_DOCUMENT_FRAG_NODE:
2265 case XML_ELEMENT_NODE:
2266 if (cur->content != NULL) {
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002267#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard6454aec1999-09-02 22:04:43 +00002268 xmlFree(cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002269#else
2270 xmlBufferFree(cur->content);
2271#endif
Daniel Veillard16253641998-10-28 22:58:05 +00002272 cur->content = NULL;
2273 }
Daniel Veillard6454aec1999-09-02 22:04:43 +00002274 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillard16253641998-10-28 22:58:05 +00002275 cur->childs = xmlStringGetNodeList(cur->doc, content);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002276 UPDATE_LAST_CHILD(cur)
Daniel Veillard16253641998-10-28 22:58:05 +00002277 break;
2278 case XML_ATTRIBUTE_NODE:
2279 break;
2280 case XML_TEXT_NODE:
2281 case XML_CDATA_SECTION_NODE:
2282 case XML_ENTITY_REF_NODE:
2283 case XML_ENTITY_NODE:
2284 case XML_PI_NODE:
2285 case XML_COMMENT_NODE:
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002286 if (cur->content != NULL) {
2287#ifndef XML_USE_BUFFER_CONTENT
2288 xmlFree(cur->content);
2289#else
2290 xmlBufferFree(cur->content);
2291#endif
2292 }
Daniel Veillard6454aec1999-09-02 22:04:43 +00002293 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002294 cur->last = cur->childs = NULL;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002295 if (content != NULL) {
2296#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard16253641998-10-28 22:58:05 +00002297 cur->content = xmlStrdup(content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002298#else
2299 cur->content = xmlBufferCreateSize(0);
2300 xmlBufferSetAllocationScheme(cur->content,
2301 xmlGetBufferAllocationScheme());
2302 xmlBufferAdd(cur->content, content, -1);
2303#endif
2304 } else
Daniel Veillard16253641998-10-28 22:58:05 +00002305 cur->content = NULL;
Daniel Veillardb96e6431999-08-29 21:02:19 +00002306 break;
Daniel Veillard16253641998-10-28 22:58:05 +00002307 case XML_DOCUMENT_NODE:
Daniel Veillard7c1206f1999-10-14 09:10:25 +00002308 case XML_HTML_DOCUMENT_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002309 case XML_DOCUMENT_TYPE_NODE:
2310 break;
2311 case XML_NOTATION_NODE:
2312 break;
2313 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002314}
2315
Daniel Veillard97b58771998-10-20 06:14:16 +00002316/**
2317 * xmlNodeSetContentLen:
2318 * @cur: the node being modified
2319 * @content: the new value of the content
2320 * @len: the size of @content
2321 *
2322 * Replace the content of a node.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002323 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002324void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002325xmlNodeSetContentLen(xmlNodePtr cur, const xmlChar *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002326 if (cur == NULL) {
Daniel Veillard16253641998-10-28 22:58:05 +00002327 fprintf(stderr, "xmlNodeSetContentLen : node == NULL\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002328 return;
2329 }
Daniel Veillard16253641998-10-28 22:58:05 +00002330 switch (cur->type) {
2331 case XML_DOCUMENT_FRAG_NODE:
2332 case XML_ELEMENT_NODE:
2333 if (cur->content != NULL) {
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002334#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard6454aec1999-09-02 22:04:43 +00002335 xmlFree(cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002336#else
2337 xmlBufferFree(cur->content);
2338#endif
Daniel Veillard16253641998-10-28 22:58:05 +00002339 cur->content = NULL;
2340 }
Daniel Veillard6454aec1999-09-02 22:04:43 +00002341 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillard16253641998-10-28 22:58:05 +00002342 cur->childs = xmlStringLenGetNodeList(cur->doc, content, len);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002343 UPDATE_LAST_CHILD(cur)
Daniel Veillard16253641998-10-28 22:58:05 +00002344 break;
2345 case XML_ATTRIBUTE_NODE:
2346 break;
2347 case XML_TEXT_NODE:
2348 case XML_CDATA_SECTION_NODE:
2349 case XML_ENTITY_REF_NODE:
2350 case XML_ENTITY_NODE:
2351 case XML_PI_NODE:
2352 case XML_COMMENT_NODE:
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002353 case XML_NOTATION_NODE:
2354 if (cur->content != NULL) {
2355#ifndef XML_USE_BUFFER_CONTENT
2356 xmlFree(cur->content);
2357#else
2358 xmlBufferFree(cur->content);
2359#endif
2360 }
Daniel Veillard6454aec1999-09-02 22:04:43 +00002361 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002362 cur->childs = cur->last = NULL;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002363 if (content != NULL) {
2364#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard16253641998-10-28 22:58:05 +00002365 cur->content = xmlStrndup(content, len);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002366#else
2367 cur->content = xmlBufferCreateSize(len);
2368 xmlBufferSetAllocationScheme(cur->content,
2369 xmlGetBufferAllocationScheme());
2370 xmlBufferAdd(cur->content, content, len);
2371#endif
2372 } else
Daniel Veillard16253641998-10-28 22:58:05 +00002373 cur->content = NULL;
Daniel Veillardb96e6431999-08-29 21:02:19 +00002374 break;
Daniel Veillard16253641998-10-28 22:58:05 +00002375 case XML_DOCUMENT_NODE:
Daniel Veillard7c1206f1999-10-14 09:10:25 +00002376 case XML_HTML_DOCUMENT_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002377 case XML_DOCUMENT_TYPE_NODE:
2378 break;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002379 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002380}
2381
Daniel Veillard97b58771998-10-20 06:14:16 +00002382/**
2383 * xmlNodeAddContentLen:
2384 * @cur: the node being modified
2385 * @content: extra content
2386 * @len: the size of @content
2387 *
2388 * Append the extra substring to the node content.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002389 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002390void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002391xmlNodeAddContentLen(xmlNodePtr cur, const xmlChar *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002392 if (cur == NULL) {
Daniel Veillard16253641998-10-28 22:58:05 +00002393 fprintf(stderr, "xmlNodeAddContentLen : node == NULL\n");
2394 return;
2395 }
2396 if (len <= 0) return;
2397 switch (cur->type) {
2398 case XML_DOCUMENT_FRAG_NODE:
2399 case XML_ELEMENT_NODE: {
2400 xmlNodePtr last = NULL, new;
2401
2402 if (cur->childs != NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002403 last = cur->last;
Daniel Veillard16253641998-10-28 22:58:05 +00002404 } else {
2405 if (cur->content != NULL) {
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002406#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard16253641998-10-28 22:58:05 +00002407 cur->childs = xmlStringGetNodeList(cur->doc, cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002408#else
2409 cur->childs = xmlStringGetNodeList(cur->doc,
2410 xmlBufferContent(cur->content));
2411#endif
Daniel Veillard1e346af1999-02-22 10:33:01 +00002412 UPDATE_LAST_CHILD(cur)
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002413#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard6454aec1999-09-02 22:04:43 +00002414 xmlFree(cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002415#else
2416 xmlBufferFree(cur->content);
2417#endif
Daniel Veillard16253641998-10-28 22:58:05 +00002418 cur->content = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002419 last = cur->last;
Daniel Veillard16253641998-10-28 22:58:05 +00002420 }
2421 }
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002422 new = xmlNewTextLen(content, len);
Daniel Veillard16253641998-10-28 22:58:05 +00002423 if (new != NULL) {
2424 xmlAddChild(cur, new);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002425 if ((last != NULL) && (last->next == new)) {
Daniel Veillard16253641998-10-28 22:58:05 +00002426 xmlTextMerge(last, new);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002427 }
Daniel Veillard16253641998-10-28 22:58:05 +00002428 }
2429 break;
2430 }
2431 case XML_ATTRIBUTE_NODE:
2432 break;
2433 case XML_TEXT_NODE:
2434 case XML_CDATA_SECTION_NODE:
2435 case XML_ENTITY_REF_NODE:
2436 case XML_ENTITY_NODE:
2437 case XML_PI_NODE:
2438 case XML_COMMENT_NODE:
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002439 case XML_NOTATION_NODE:
2440 if (content != NULL) {
2441#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard16253641998-10-28 22:58:05 +00002442 cur->content = xmlStrncat(cur->content, content, len);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002443#else
2444 xmlBufferAdd(cur->content, content, len);
2445#endif
2446 }
Daniel Veillard16253641998-10-28 22:58:05 +00002447 case XML_DOCUMENT_NODE:
Daniel Veillard7c1206f1999-10-14 09:10:25 +00002448 case XML_HTML_DOCUMENT_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002449 case XML_DOCUMENT_TYPE_NODE:
2450 break;
Daniel Veillard16253641998-10-28 22:58:05 +00002451 }
2452}
2453
2454/**
2455 * xmlNodeAddContent:
2456 * @cur: the node being modified
2457 * @content: extra content
2458 *
2459 * Append the extra substring to the node content.
2460 */
2461void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002462xmlNodeAddContent(xmlNodePtr cur, const xmlChar *content) {
Daniel Veillard16253641998-10-28 22:58:05 +00002463 int len;
2464
2465 if (cur == NULL) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002466 fprintf(stderr, "xmlNodeAddContent : node == NULL\n");
2467 return;
2468 }
Daniel Veillard16253641998-10-28 22:58:05 +00002469 if (content == NULL) return;
2470 len = xmlStrlen(content);
2471 xmlNodeAddContentLen(cur, content, len);
2472}
2473
2474/**
2475 * xmlTextMerge:
2476 * @first: the first text node
2477 * @second: the second text node being merged
2478 *
2479 * Merge two text nodes into one
Daniel Veillard1e346af1999-02-22 10:33:01 +00002480 * Returns the first text node augmented
Daniel Veillard16253641998-10-28 22:58:05 +00002481 */
2482xmlNodePtr
2483xmlTextMerge(xmlNodePtr first, xmlNodePtr second) {
2484 if (first == NULL) return(second);
2485 if (second == NULL) return(first);
2486 if (first->type != XML_TEXT_NODE) return(first);
2487 if (second->type != XML_TEXT_NODE) return(first);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002488#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard16253641998-10-28 22:58:05 +00002489 xmlNodeAddContent(first, second->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002490#else
2491 xmlNodeAddContent(first, xmlBufferContent(second->content));
2492#endif
Daniel Veillard16253641998-10-28 22:58:05 +00002493 xmlUnlinkNode(second);
2494 xmlFreeNode(second);
2495 return(first);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002496}
2497
Daniel Veillard97b58771998-10-20 06:14:16 +00002498/**
Daniel Veillardb96e6431999-08-29 21:02:19 +00002499 * xmlGetNsList:
2500 * @doc: the document
2501 * @node: the current node
2502 *
2503 * Search all the namespace applying to a given element.
2504 * Returns an NULL terminated array of all the xmlNsPtr found
2505 * that need to be freed by the caller or NULL if no
2506 * namespace if defined
2507 */
2508xmlNsPtr *
2509xmlGetNsList(xmlDocPtr doc, xmlNodePtr node) {
2510 xmlNsPtr cur;
2511 xmlNsPtr *ret = NULL;
2512 int nbns = 0;
2513 int maxns = 10;
2514 int i;
2515
2516 while (node != NULL) {
2517 cur = node->nsDef;
2518 while (cur != NULL) {
2519 if (ret == NULL) {
Daniel Veillard6454aec1999-09-02 22:04:43 +00002520 ret = (xmlNsPtr *) xmlMalloc((maxns + 1) * sizeof(xmlNsPtr));
Daniel Veillardb96e6431999-08-29 21:02:19 +00002521 if (ret == NULL) {
2522 fprintf(stderr, "xmlGetNsList : out of memory!\n");
2523 return(NULL);
2524 }
2525 ret[nbns] = NULL;
2526 }
2527 for (i = 0;i < nbns;i++) {
2528 if ((cur->prefix == ret[i]->prefix) ||
2529 (!xmlStrcmp(cur->prefix, ret[i]->prefix))) break;
2530 }
2531 if (i >= nbns) {
2532 if (nbns >= maxns) {
2533 maxns *= 2;
Daniel Veillard6454aec1999-09-02 22:04:43 +00002534 ret = (xmlNsPtr *) xmlRealloc(ret,
Daniel Veillardb96e6431999-08-29 21:02:19 +00002535 (maxns + 1) * sizeof(xmlNsPtr));
2536 if (ret == NULL) {
2537 fprintf(stderr, "xmlGetNsList : realloc failed!\n");
2538 return(NULL);
2539 }
2540 }
2541 ret[nbns++] = cur;
2542 ret[nbns] = NULL;
2543 }
2544
2545 cur = cur->next;
2546 }
2547 node = node->parent;
2548 }
2549 return(ret);
2550}
2551
2552/**
Daniel Veillard97b58771998-10-20 06:14:16 +00002553 * xmlSearchNs:
2554 * @doc: the document
2555 * @node: the current node
2556 * @nameSpace: the namespace string
Daniel Veillard260a68f1998-08-13 03:39:55 +00002557 *
Daniel Veillard97b58771998-10-20 06:14:16 +00002558 * Search a Ns registered under a given name space for a document.
2559 * recurse on the parents until it finds the defined namespace
2560 * or return NULL otherwise.
2561 * @nameSpace can be NULL, this is a search for the default namespace.
Daniel Veillard1e346af1999-02-22 10:33:01 +00002562 * Returns the namespace pointer or NULL.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002563 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002564xmlNsPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002565xmlSearchNs(xmlDocPtr doc, xmlNodePtr node, const xmlChar *nameSpace) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002566 xmlNsPtr cur;
2567
2568 while (node != NULL) {
2569 cur = node->nsDef;
2570 while (cur != NULL) {
2571 if ((cur->prefix == NULL) && (nameSpace == NULL))
2572 return(cur);
2573 if ((cur->prefix != NULL) && (nameSpace != NULL) &&
2574 (!xmlStrcmp(cur->prefix, nameSpace)))
2575 return(cur);
2576 cur = cur->next;
2577 }
2578 node = node->parent;
2579 }
2580 if (doc != NULL) {
2581 cur = doc->oldNs;
2582 while (cur != NULL) {
2583 if ((cur->prefix != NULL) && (nameSpace != NULL) &&
2584 (!xmlStrcmp(cur->prefix, nameSpace)))
2585 return(cur);
2586 cur = cur->next;
2587 }
2588 }
2589 return(NULL);
2590}
2591
Daniel Veillard97b58771998-10-20 06:14:16 +00002592/**
2593 * xmlSearchNsByHref:
2594 * @doc: the document
2595 * @node: the current node
2596 * @href: the namespace value
2597 *
2598 * Search a Ns aliasing a given URI. Recurse on the parents until it finds
2599 * the defined namespace or return NULL otherwise.
Daniel Veillard1e346af1999-02-22 10:33:01 +00002600 * Returns the namespace pointer or NULL.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002601 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002602xmlNsPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002603xmlSearchNsByHref(xmlDocPtr doc, xmlNodePtr node, const xmlChar *href) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002604 xmlNsPtr cur;
2605
2606 while (node != NULL) {
2607 cur = node->nsDef;
2608 while (cur != NULL) {
2609 if ((cur->href != NULL) && (href != NULL) &&
2610 (!xmlStrcmp(cur->href, href)))
2611 return(cur);
2612 cur = cur->next;
2613 }
2614 node = node->parent;
2615 }
2616 if (doc != NULL) {
2617 cur = doc->oldNs;
2618 while (cur != NULL) {
2619 if ((cur->href != NULL) && (href != NULL) &&
2620 (!xmlStrcmp(cur->href, href)))
2621 return(cur);
2622 cur = cur->next;
2623 }
2624 }
2625 return(NULL);
2626}
2627
Daniel Veillard97b58771998-10-20 06:14:16 +00002628/**
2629 * xmlGetProp:
2630 * @node: the node
2631 * @name: the attribute name
2632 *
2633 * Search and get the value of an attribute associated to a node
Daniel Veillardccb09631998-10-27 06:21:04 +00002634 * This does the entity substitution.
Daniel Veillard1e346af1999-02-22 10:33:01 +00002635 * Returns the attribute value or NULL if not found.
Daniel Veillarda819dac1999-11-24 18:04:22 +00002636 * It's up to the caller to free the memory.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002637 */
Daniel Veillarda819dac1999-11-24 18:04:22 +00002638xmlChar *
2639xmlGetProp(xmlNodePtr node, const xmlChar *name) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002640 xmlAttrPtr prop = node->properties;
2641
2642 while (prop != NULL) {
Daniel Veillard68178931999-02-08 18:34:36 +00002643 if (!xmlStrcmp(prop->name, name)) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002644 xmlChar *ret;
Daniel Veillard6800ef31999-02-08 18:33:22 +00002645
2646 ret = xmlNodeListGetString(node->doc, prop->val, 1);
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002647 if (ret == NULL) return(xmlStrdup((xmlChar *)""));
Daniel Veillard6800ef31999-02-08 18:33:22 +00002648 return(ret);
Daniel Veillard68178931999-02-08 18:34:36 +00002649 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002650 prop = prop->next;
2651 }
2652 return(NULL);
2653}
2654
Daniel Veillard97b58771998-10-20 06:14:16 +00002655/**
Daniel Veillardccb09631998-10-27 06:21:04 +00002656 * xmlSetProp:
Daniel Veillard97b58771998-10-20 06:14:16 +00002657 * @node: the node
2658 * @name: the attribute name
2659 * @value: the attribute value
2660 *
2661 * Set (or reset) an attribute carried by a node.
Daniel Veillard1e346af1999-02-22 10:33:01 +00002662 * Returns the attribute pointer.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002663 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002664xmlAttrPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002665xmlSetProp(xmlNodePtr node, const xmlChar *name, const xmlChar *value) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002666 xmlAttrPtr prop = node->properties;
2667
2668 while (prop != NULL) {
2669 if (!xmlStrcmp(prop->name, name)) {
Daniel Veillardccb09631998-10-27 06:21:04 +00002670 if (prop->val != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +00002671 xmlFreeNodeList(prop->val);
Daniel Veillardccb09631998-10-27 06:21:04 +00002672 prop->val = NULL;
Daniel Veillard51e3b151999-11-12 17:02:31 +00002673 if (value != NULL) {
2674 xmlChar *buffer;
2675 buffer = xmlEncodeEntitiesReentrant(node->doc, value);
2676 prop->val = xmlStringGetNodeList(node->doc, buffer);
2677 xmlFree(buffer);
2678 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002679 return(prop);
2680 }
2681 prop = prop->next;
2682 }
2683 prop = xmlNewProp(node, name, value);
2684 return(prop);
2685}
2686
Daniel Veillard97b58771998-10-20 06:14:16 +00002687/**
2688 * xmlNodeIsText:
2689 * @node: the node
2690 *
2691 * Is this node a Text node ?
Daniel Veillard1e346af1999-02-22 10:33:01 +00002692 * Returns 1 yes, 0 no
Daniel Veillard260a68f1998-08-13 03:39:55 +00002693 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002694int
2695xmlNodeIsText(xmlNodePtr node) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002696 if (node == NULL) return(0);
2697
Daniel Veillard0bef1311998-10-14 02:36:47 +00002698 if (node->type == XML_TEXT_NODE) return(1);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002699 return(0);
2700}
2701
Daniel Veillard97b58771998-10-20 06:14:16 +00002702/**
Daniel Veillard1e346af1999-02-22 10:33:01 +00002703 * xmlTextConcat:
Daniel Veillard97b58771998-10-20 06:14:16 +00002704 * @node: the node
2705 * @content: the content
2706 * @len: @content lenght
2707 *
2708 * Concat the given string at the end of the existing node content
Daniel Veillard260a68f1998-08-13 03:39:55 +00002709 */
Daniel Veillard97b58771998-10-20 06:14:16 +00002710
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002711void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002712xmlTextConcat(xmlNodePtr node, const xmlChar *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002713 if (node == NULL) return;
2714
Daniel Veillard0bef1311998-10-14 02:36:47 +00002715 if (node->type != XML_TEXT_NODE) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002716 fprintf(stderr, "xmlTextConcat: node is not text\n");
2717 return;
2718 }
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002719#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard260a68f1998-08-13 03:39:55 +00002720 node->content = xmlStrncat(node->content, content, len);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002721#else
2722 xmlBufferAdd(node->content, content, len);
2723#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00002724}
2725
2726/************************************************************************
2727 * *
2728 * Output : to a FILE or in memory *
2729 * *
2730 ************************************************************************/
2731
Daniel Veillard5099ae81999-04-21 20:12:07 +00002732#define BASE_BUFFER_SIZE 4000
2733
2734/**
2735 * xmlBufferCreate:
2736 *
2737 * routine to create an XML buffer.
2738 * returns the new structure.
2739 */
2740xmlBufferPtr
2741xmlBufferCreate(void) {
2742 xmlBufferPtr ret;
2743
Daniel Veillard6454aec1999-09-02 22:04:43 +00002744 ret = (xmlBufferPtr) xmlMalloc(sizeof(xmlBuffer));
Daniel Veillard5099ae81999-04-21 20:12:07 +00002745 if (ret == NULL) {
2746 fprintf(stderr, "xmlBufferCreate : out of memory!\n");
2747 return(NULL);
2748 }
2749 ret->use = 0;
2750 ret->size = BASE_BUFFER_SIZE;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002751 ret->content = (xmlChar *) xmlMalloc(ret->size * sizeof(xmlChar));
Daniel Veillard5099ae81999-04-21 20:12:07 +00002752 if (ret->content == NULL) {
2753 fprintf(stderr, "xmlBufferCreate : out of memory!\n");
Daniel Veillard6454aec1999-09-02 22:04:43 +00002754 xmlFree(ret);
Daniel Veillard5099ae81999-04-21 20:12:07 +00002755 return(NULL);
2756 }
2757 ret->content[0] = 0;
2758 return(ret);
2759}
2760
2761/**
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002762 * xmlBufferCreateSize:
2763 * @size: initial size of buffer
2764 *
2765 * routine to create an XML buffer.
2766 * returns the new structure.
2767 */
2768xmlBufferPtr
2769xmlBufferCreateSize(size_t size) {
2770 xmlBufferPtr ret;
2771
2772 ret = (xmlBufferPtr) xmlMalloc(sizeof(xmlBuffer));
2773 if (ret == NULL) {
2774 fprintf(stderr, "xmlBufferCreate : out of memory!\n");
2775 return(NULL);
2776 }
2777 ret->use = 0;
2778 ret->size = (size ? size+2 : 0); /* +1 for ending null */
2779 if(ret->size){
2780 ret->content = (xmlChar *) xmlMalloc(ret->size * sizeof(xmlChar));
2781 if (ret->content == NULL) {
2782 fprintf(stderr, "xmlBufferCreate : out of memory!\n");
2783 xmlFree(ret);
2784 return(NULL);
2785 }
2786 ret->content[0] = 0;
2787 } else
2788 ret->content = NULL;
2789 return(ret);
2790}
2791
2792/**
2793 * xmlBufferAllocationScheme:
2794 * @buf: the buffer to free
2795 * @scheme: allocation scheme to use
2796 *
2797 * Sets the allocation scheme for this buffer
2798 */
2799void
2800xmlBufferSetAllocationScheme(xmlBufferPtr buf,
2801 xmlBufferAllocationScheme scheme) {
2802 if (buf == NULL) {
2803 fprintf(stderr, "xmlBufferSetAllocationScheme: buf == NULL\n");
2804 return;
2805 }
2806
2807 buf->alloc = scheme;
2808}
2809
2810/**
Daniel Veillard5099ae81999-04-21 20:12:07 +00002811 * xmlBufferFree:
2812 * @buf: the buffer to free
2813 *
2814 * Frees an XML buffer.
2815 */
2816void
2817xmlBufferFree(xmlBufferPtr buf) {
2818 if (buf == NULL) {
2819 fprintf(stderr, "xmlBufferFree: buf == NULL\n");
2820 return;
2821 }
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002822 if (buf->content != NULL) {
2823#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard5099ae81999-04-21 20:12:07 +00002824 memset(buf->content, -1, BASE_BUFFER_SIZE);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002825#else
2826 memset(buf->content, -1, buf->size);
2827#endif
Daniel Veillard6454aec1999-09-02 22:04:43 +00002828 xmlFree(buf->content);
Daniel Veillard5099ae81999-04-21 20:12:07 +00002829 }
2830 memset(buf, -1, sizeof(xmlBuffer));
Daniel Veillard6454aec1999-09-02 22:04:43 +00002831 xmlFree(buf);
Daniel Veillard5099ae81999-04-21 20:12:07 +00002832}
2833
2834/**
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002835 * xmlBufferEmpty:
2836 * @buf: the buffer
2837 *
2838 * empty a buffer.
2839 */
2840void
2841xmlBufferEmpty(xmlBufferPtr buf) {
2842 buf->use = 0;
2843 memset(buf->content, -1, buf->size);/* just for debug */
2844}
2845
2846/**
2847 * xmlBufferShrink:
2848 * @buf: the buffer to dump
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002849 * @len: the number of xmlChar to remove
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002850 *
2851 * Remove the beginning of an XML buffer.
2852 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002853 * Returns the number of xmlChar removed, or -1 in case of failure.
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002854 */
2855int
2856xmlBufferShrink(xmlBufferPtr buf, int len) {
2857 if (len == 0) return(0);
2858 if (len > buf->use) return(-1);
2859
2860 buf->use -= len;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002861 memmove(buf->content, &buf->content[len], buf->use * sizeof(xmlChar));
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002862
2863 buf->content[buf->use] = 0;
2864 return(len);
2865}
2866
2867/**
Daniel Veillard5099ae81999-04-21 20:12:07 +00002868 * xmlBufferDump:
2869 * @file: the file output
2870 * @buf: the buffer to dump
2871 *
2872 * Dumps an XML buffer to a FILE *.
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002873 * Returns the number of xmlChar written
Daniel Veillard5099ae81999-04-21 20:12:07 +00002874 */
2875int
2876xmlBufferDump(FILE *file, xmlBufferPtr buf) {
2877 int ret;
2878
2879 if (buf == NULL) {
2880 fprintf(stderr, "xmlBufferDump: buf == NULL\n");
2881 return(0);
2882 }
2883 if (buf->content == NULL) {
2884 fprintf(stderr, "xmlBufferDump: buf->content == NULL\n");
2885 return(0);
2886 }
2887 if (file == NULL) file = stdout;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002888 ret = fwrite(buf->content, sizeof(xmlChar), buf->use, file);
Daniel Veillard5099ae81999-04-21 20:12:07 +00002889 return(ret);
2890}
2891
2892/**
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002893 * xmlBufferContent:
2894 * @buf: the buffer to resize
2895 *
2896 * Returns the internal content
2897 */
2898
2899const xmlChar*
2900xmlBufferContent(const xmlBufferPtr buf)
2901{
2902 if(!buf)
2903 return NULL;
2904
2905 return buf->content;
2906}
2907
2908/**
2909 * xmlBufferLength:
2910 * @buf: the buffer
2911 *
2912 * Returns the length of data in the internal content
2913 */
2914
2915int
2916xmlBufferLength(const xmlBufferPtr buf)
2917{
2918 if(!buf)
2919 return 0;
2920
2921 return buf->use;
2922}
2923
2924/**
2925 * xmlBufferResize:
2926 * @buf: the buffer to resize
2927 * @len: the desired size
2928 *
2929 * Resize a buffer to accomodate minimum size of <len>.
2930 *
2931 * Returns 0 in case of problems, 1 otherwise
2932 */
2933int
2934xmlBufferResize(xmlBufferPtr buf, int size)
2935{
2936 int newSize = (buf->size ? buf->size*2 : size);/*take care of empty case*/
2937 xmlChar* rebuf = NULL;
2938
2939 /* Don't resize if we don't have to */
2940 if(size < buf->size)
2941 return 1;
2942
2943 /* figure out new size */
2944 switch(buf->alloc){
2945 case XML_BUFFER_ALLOC_DOUBLEIT:
2946 while(size > newSize) newSize *= 2;
2947 break;
2948 case XML_BUFFER_ALLOC_EXACT:
2949 newSize = size+10;
2950 break;
2951 default:
2952 newSize = size+10;
2953 break;
2954 }
2955
2956 if (buf->content == NULL)
2957 rebuf = (xmlChar *) xmlMalloc(newSize * sizeof(xmlChar));
2958 else
2959 rebuf = (xmlChar *) xmlRealloc(buf->content,
2960 newSize * sizeof(xmlChar));
2961 if (rebuf == NULL) {
2962 fprintf(stderr, "xmlBufferAdd : out of memory!\n");
2963 return 0;
2964 }
2965 buf->content = rebuf;
2966 buf->size = newSize;
2967
2968 return 1;
2969}
2970/**
Daniel Veillard5099ae81999-04-21 20:12:07 +00002971 * xmlBufferAdd:
2972 * @buf: the buffer to dump
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002973 * @str: the xmlChar string
2974 * @len: the number of xmlChar to add
Daniel Veillard5099ae81999-04-21 20:12:07 +00002975 *
2976 * Add a string range to an XML buffer.
2977 */
2978void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002979xmlBufferAdd(xmlBufferPtr buf, const xmlChar *str, int len) {
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002980 int l, needSize;
Daniel Veillard5099ae81999-04-21 20:12:07 +00002981
2982 if (str == NULL) {
2983 fprintf(stderr, "xmlBufferAdd: str == NULL\n");
2984 return;
2985 }
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002986
2987 /* CJN What's this for??? */
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002988 l = xmlStrlen(str);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002989 if (l < len){ len = l; printf("xmlBufferAdd bad length\n"); }
2990
2991 /* CJN 11.18.99 okay, now I'm using the length */
2992 if(len == -1) len = l;
2993
2994
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002995 if (len <= 0) return;
Daniel Veillard5099ae81999-04-21 20:12:07 +00002996
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002997 needSize = buf->use + len + 2;
2998 if(needSize > buf->size){
2999 if(!xmlBufferResize(buf, needSize)){
3000 fprintf(stderr, "xmlBufferAdd : out of memory!\n");
3001 return;
3002 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003003 }
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003004
3005 memmove(&buf->content[buf->use], str, len*sizeof(xmlChar));
Daniel Veillarde2d034d1999-07-27 19:52:06 +00003006 buf->use += len;
3007 buf->content[buf->use] = 0;
Daniel Veillard5099ae81999-04-21 20:12:07 +00003008}
3009
3010/**
3011 * xmlBufferCat:
3012 * @buf: the buffer to dump
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003013 * @str: the xmlChar string
Daniel Veillard5099ae81999-04-21 20:12:07 +00003014 *
3015 * Append a zero terminated string to an XML buffer.
3016 */
3017void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003018xmlBufferCat(xmlBufferPtr buf, const xmlChar *str) {
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003019 if (str != NULL)
3020 xmlBufferAdd(buf, str, -1);
Daniel Veillard5099ae81999-04-21 20:12:07 +00003021}
3022
3023/**
3024 * xmlBufferCCat:
3025 * @buf: the buffer to dump
3026 * @str: the C char string
3027 *
3028 * Append a zero terminated C string to an XML buffer.
3029 */
3030void
3031xmlBufferCCat(xmlBufferPtr buf, const char *str) {
3032 const char *cur;
3033
3034 if (str == NULL) {
3035 fprintf(stderr, "xmlBufferAdd: str == NULL\n");
3036 return;
3037 }
3038 for (cur = str;*cur != 0;cur++) {
3039 if (buf->use + 10 >= buf->size) {
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003040 if(!xmlBufferResize(buf, buf->use+10)){
3041 fprintf(stderr, "xmlBufferCCat : out of memory!\n");
3042 return;
3043 }
3044 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003045 buf->content[buf->use++] = *cur;
3046 }
3047}
Daniel Veillard260a68f1998-08-13 03:39:55 +00003048
Daniel Veillard97b58771998-10-20 06:14:16 +00003049/**
3050 * xmlBufferWriteCHAR:
Daniel Veillard5099ae81999-04-21 20:12:07 +00003051 * @buf: the XML buffer
Daniel Veillard97b58771998-10-20 06:14:16 +00003052 * @string: the string to add
3053 *
3054 * routine which manage and grows an output buffer. This one add
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003055 * xmlChars at the end of the buffer.
Daniel Veillard97b58771998-10-20 06:14:16 +00003056 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003057void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003058xmlBufferWriteCHAR(xmlBufferPtr buf, const xmlChar *string) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003059 xmlBufferCat(buf, string);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003060}
3061
Daniel Veillard97b58771998-10-20 06:14:16 +00003062/**
3063 * xmlBufferWriteChar:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003064 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003065 * @string: the string to add
3066 *
3067 * routine which manage and grows an output buffer. This one add
3068 * C chars at the end of the array.
3069 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003070void
Daniel Veillard5099ae81999-04-21 20:12:07 +00003071xmlBufferWriteChar(xmlBufferPtr buf, const char *string) {
3072 xmlBufferCCat(buf, string);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003073}
3074
Daniel Veillard5099ae81999-04-21 20:12:07 +00003075
Daniel Veillard97b58771998-10-20 06:14:16 +00003076/**
Daniel Veillard011b63c1999-06-02 17:44:04 +00003077 * xmlBufferWriteQuotedString:
3078 * @buf: the XML buffer output
3079 * @string: the string to add
3080 *
3081 * routine which manage and grows an output buffer. This one writes
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003082 * a quoted or double quoted xmlChar string, checking first if it holds
Daniel Veillard011b63c1999-06-02 17:44:04 +00003083 * quote or double-quotes internally
3084 */
3085void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003086xmlBufferWriteQuotedString(xmlBufferPtr buf, const xmlChar *string) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00003087 if (xmlStrchr(string, '"')) {
3088 if (xmlStrchr(string, '\'')) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00003089 fprintf(stderr,
3090 "xmlBufferWriteQuotedString: string contains quote and double-quotes !\n");
3091 }
3092 xmlBufferCCat(buf, "'");
3093 xmlBufferCat(buf, string);
3094 xmlBufferCCat(buf, "'");
3095 } else {
3096 xmlBufferCCat(buf, "\"");
3097 xmlBufferCat(buf, string);
3098 xmlBufferCCat(buf, "\"");
3099 }
3100}
3101
3102
3103/**
Daniel Veillard97b58771998-10-20 06:14:16 +00003104 * xmlGlobalNsDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003105 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003106 * @cur: a namespace
3107 *
3108 * Dump a global Namespace, this is the old version based on PIs.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003109 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003110static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00003111xmlGlobalNsDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003112 if (cur == NULL) {
3113 fprintf(stderr, "xmlGlobalNsDump : Ns == NULL\n");
3114 return;
3115 }
3116 if (cur->type == XML_GLOBAL_NAMESPACE) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003117 xmlBufferWriteChar(buf, "<?namespace");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003118 if (cur->href != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00003119 xmlBufferWriteChar(buf, " href=");
3120 xmlBufferWriteQuotedString(buf, cur->href);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003121 }
3122 if (cur->prefix != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00003123 xmlBufferWriteChar(buf, " AS=");
3124 xmlBufferWriteQuotedString(buf, cur->prefix);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003125 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003126 xmlBufferWriteChar(buf, "?>\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003127 }
3128}
3129
Daniel Veillard97b58771998-10-20 06:14:16 +00003130/**
3131 * xmlGlobalNsListDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003132 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003133 * @cur: the first namespace
3134 *
3135 * Dump a list of global Namespace, this is the old version based on PIs.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003136 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003137static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00003138xmlGlobalNsListDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003139 while (cur != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003140 xmlGlobalNsDump(buf, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003141 cur = cur->next;
3142 }
3143}
3144
Daniel Veillard97b58771998-10-20 06:14:16 +00003145/**
3146 * xmlNsDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003147 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003148 * @cur: a namespace
3149 *
Daniel Veillard260a68f1998-08-13 03:39:55 +00003150 * Dump a local Namespace definition.
Daniel Veillard97b58771998-10-20 06:14:16 +00003151 * Should be called in the context of attributes dumps.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003152 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003153static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00003154xmlNsDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003155 if (cur == NULL) {
3156 fprintf(stderr, "xmlNsDump : Ns == NULL\n");
3157 return;
3158 }
3159 if (cur->type == XML_LOCAL_NAMESPACE) {
3160 /* Within the context of an element attributes */
3161 if (cur->prefix != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003162 xmlBufferWriteChar(buf, " xmlns:");
3163 xmlBufferWriteCHAR(buf, cur->prefix);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003164 } else
Daniel Veillard5099ae81999-04-21 20:12:07 +00003165 xmlBufferWriteChar(buf, " xmlns");
Daniel Veillard011b63c1999-06-02 17:44:04 +00003166 xmlBufferWriteChar(buf, "=");
3167 xmlBufferWriteQuotedString(buf, cur->href);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003168 }
3169}
3170
Daniel Veillard97b58771998-10-20 06:14:16 +00003171/**
3172 * xmlNsListDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003173 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003174 * @cur: the first namespace
3175 *
3176 * Dump a list of local Namespace definitions.
3177 * Should be called in the context of attributes dumps.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003178 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003179static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00003180xmlNsListDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003181 while (cur != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003182 xmlNsDump(buf, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003183 cur = cur->next;
3184 }
3185}
3186
Daniel Veillard97b58771998-10-20 06:14:16 +00003187/**
3188 * xmlDtdDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003189 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003190 * @doc: the document
3191 *
3192 * Dump the XML document DTD, if any.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003193 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003194static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00003195xmlDtdDump(xmlBufferPtr buf, xmlDocPtr doc) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003196 xmlDtdPtr cur = doc->intSubset;
Daniel Veillard260a68f1998-08-13 03:39:55 +00003197
3198 if (cur == NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003199 fprintf(stderr, "xmlDtdDump : no internal subset\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003200 return;
3201 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003202 xmlBufferWriteChar(buf, "<!DOCTYPE ");
3203 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003204 if (cur->ExternalID != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00003205 xmlBufferWriteChar(buf, " PUBLIC ");
3206 xmlBufferWriteQuotedString(buf, cur->ExternalID);
3207 xmlBufferWriteChar(buf, " ");
3208 xmlBufferWriteQuotedString(buf, cur->SystemID);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003209 } else if (cur->SystemID != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00003210 xmlBufferWriteChar(buf, " SYSTEM ");
3211 xmlBufferWriteQuotedString(buf, cur->SystemID);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003212 }
Daniel Veillard1e346af1999-02-22 10:33:01 +00003213 if ((cur->entities == NULL) && (cur->elements == NULL) &&
3214 (cur->attributes == NULL) && (cur->notations == NULL)) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003215 xmlBufferWriteChar(buf, ">\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003216 return;
3217 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003218 xmlBufferWriteChar(buf, " [\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003219 if (cur->entities != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00003220 xmlDumpEntitiesTable(buf, (xmlEntitiesTablePtr) cur->entities);
Daniel Veillard1e346af1999-02-22 10:33:01 +00003221 if (cur->notations != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00003222 xmlDumpNotationTable(buf, (xmlNotationTablePtr) cur->notations);
Daniel Veillard3b9def11999-01-31 22:15:06 +00003223 if (cur->elements != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00003224 xmlDumpElementTable(buf, (xmlElementTablePtr) cur->elements);
Daniel Veillard1e346af1999-02-22 10:33:01 +00003225 if (cur->attributes != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00003226 xmlDumpAttributeTable(buf, (xmlAttributeTablePtr) cur->attributes);
3227 xmlBufferWriteChar(buf, "]");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003228
Daniel Veillard5099ae81999-04-21 20:12:07 +00003229 xmlBufferWriteChar(buf, ">\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003230}
3231
Daniel Veillard97b58771998-10-20 06:14:16 +00003232/**
3233 * xmlAttrDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003234 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003235 * @doc: the document
3236 * @cur: the attribute pointer
3237 *
3238 * Dump an XML attribute
Daniel Veillard260a68f1998-08-13 03:39:55 +00003239 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003240static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00003241xmlAttrDump(xmlBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003242 xmlChar *value;
Daniel Veillardccb09631998-10-27 06:21:04 +00003243
Daniel Veillard260a68f1998-08-13 03:39:55 +00003244 if (cur == NULL) {
3245 fprintf(stderr, "xmlAttrDump : property == NULL\n");
3246 return;
3247 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003248 xmlBufferWriteChar(buf, " ");
Daniel Veillardb96e6431999-08-29 21:02:19 +00003249 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
3250 xmlBufferWriteCHAR(buf, cur->ns->prefix);
3251 xmlBufferWriteChar(buf, ":");
3252 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003253 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillardccb09631998-10-27 06:21:04 +00003254 value = xmlNodeListGetString(doc, cur->val, 0);
3255 if (value) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00003256 xmlBufferWriteChar(buf, "=");
3257 xmlBufferWriteQuotedString(buf, value);
Daniel Veillard6454aec1999-09-02 22:04:43 +00003258 xmlFree(value);
Daniel Veillard726c7e31999-02-08 15:13:10 +00003259 } else {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003260 xmlBufferWriteChar(buf, "=\"\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003261 }
3262}
3263
Daniel Veillard97b58771998-10-20 06:14:16 +00003264/**
3265 * xmlAttrListDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003266 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003267 * @doc: the document
3268 * @cur: the first attribute pointer
3269 *
3270 * Dump a list of XML attributes
Daniel Veillard260a68f1998-08-13 03:39:55 +00003271 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003272static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00003273xmlAttrListDump(xmlBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003274 if (cur == NULL) {
3275 fprintf(stderr, "xmlAttrListDump : property == NULL\n");
3276 return;
3277 }
3278 while (cur != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003279 xmlAttrDump(buf, doc, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003280 cur = cur->next;
3281 }
3282}
3283
Daniel Veillard260a68f1998-08-13 03:39:55 +00003284
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003285static void
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003286xmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
3287 int format);
Daniel Veillard97b58771998-10-20 06:14:16 +00003288/**
3289 * xmlNodeListDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003290 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003291 * @doc: the document
3292 * @cur: the first node
3293 * @level: the imbrication level for indenting
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003294 * @format: is formatting allowed
Daniel Veillard97b58771998-10-20 06:14:16 +00003295 *
3296 * Dump an XML node list, recursive behaviour,children are printed too.
3297 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003298static void
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003299xmlNodeListDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
3300 int format) {
3301 int i;
Daniel Veillardccb09631998-10-27 06:21:04 +00003302
Daniel Veillard260a68f1998-08-13 03:39:55 +00003303 if (cur == NULL) {
3304 fprintf(stderr, "xmlNodeListDump : node == NULL\n");
3305 return;
3306 }
3307 while (cur != NULL) {
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003308 if ((format) && (xmlIndentTreeOutput) &&
3309 (cur->type == XML_ELEMENT_NODE))
3310 for (i = 0;i < level;i++)
3311 xmlBufferWriteChar(buf, " ");
3312 xmlNodeDump(buf, doc, cur, level, format);
3313 if (format) {
3314 xmlBufferWriteChar(buf, "\n");
Daniel Veillardccb09631998-10-27 06:21:04 +00003315 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003316 cur = cur->next;
3317 }
3318}
3319
Daniel Veillard97b58771998-10-20 06:14:16 +00003320/**
Daniel Veillardccb09631998-10-27 06:21:04 +00003321 * xmlNodeDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003322 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003323 * @doc: the document
3324 * @cur: the current node
3325 * @level: the imbrication level for indenting
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003326 * @format: is formatting allowed
Daniel Veillard97b58771998-10-20 06:14:16 +00003327 *
3328 * Dump an XML node, recursive behaviour,children are printed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003329 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003330static void
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003331xmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
3332 int format) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003333 int i;
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003334 xmlNodePtr tmp;
Daniel Veillard260a68f1998-08-13 03:39:55 +00003335
3336 if (cur == NULL) {
3337 fprintf(stderr, "xmlNodeDump : node == NULL\n");
3338 return;
3339 }
Daniel Veillard0bef1311998-10-14 02:36:47 +00003340 if (cur->type == XML_TEXT_NODE) {
Daniel Veillard14fff061999-06-22 21:49:07 +00003341 if (cur->content != NULL) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003342 xmlChar *buffer;
Daniel Veillard14fff061999-06-22 21:49:07 +00003343
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003344#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard14fff061999-06-22 21:49:07 +00003345 buffer = xmlEncodeEntitiesReentrant(doc, cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003346#else
3347 buffer = xmlEncodeEntitiesReentrant(doc,
3348 xmlBufferContent(cur->content));
3349#endif
Daniel Veillard14fff061999-06-22 21:49:07 +00003350 if (buffer != NULL) {
3351 xmlBufferWriteCHAR(buf, buffer);
Daniel Veillard6454aec1999-09-02 22:04:43 +00003352 xmlFree(buffer);
Daniel Veillard14fff061999-06-22 21:49:07 +00003353 }
3354 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003355 return;
3356 }
Daniel Veillardb96e6431999-08-29 21:02:19 +00003357 if (cur->type == XML_PI_NODE) {
3358 if (cur->content != NULL) {
3359 xmlBufferWriteChar(buf, "<?");
3360 xmlBufferWriteCHAR(buf, cur->name);
3361 if (cur->content != NULL) {
3362 xmlBufferWriteChar(buf, " ");
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003363#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardb96e6431999-08-29 21:02:19 +00003364 xmlBufferWriteCHAR(buf, cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003365#else
3366 xmlBufferWriteCHAR(buf, xmlBufferContent(cur->content));
3367#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +00003368 }
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003369 xmlBufferWriteChar(buf, "?>");
Daniel Veillardb96e6431999-08-29 21:02:19 +00003370 }
3371 return;
3372 }
Daniel Veillard0bef1311998-10-14 02:36:47 +00003373 if (cur->type == XML_COMMENT_NODE) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003374 if (cur->content != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003375 xmlBufferWriteChar(buf, "<!--");
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003376#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard5099ae81999-04-21 20:12:07 +00003377 xmlBufferWriteCHAR(buf, cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003378#else
3379 xmlBufferWriteCHAR(buf, xmlBufferContent(cur->content));
3380#endif
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003381 xmlBufferWriteChar(buf, "-->");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003382 }
3383 return;
3384 }
Daniel Veillardccb09631998-10-27 06:21:04 +00003385 if (cur->type == XML_ENTITY_REF_NODE) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003386 xmlBufferWriteChar(buf, "&");
3387 xmlBufferWriteCHAR(buf, cur->name);
3388 xmlBufferWriteChar(buf, ";");
Daniel Veillardccb09631998-10-27 06:21:04 +00003389 return;
3390 }
Daniel Veillardb05deb71999-08-10 19:04:08 +00003391 if (cur->type == XML_CDATA_SECTION_NODE) {
3392 xmlBufferWriteChar(buf, "<![CDATA[");
3393 if (cur->content != NULL)
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003394#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardb05deb71999-08-10 19:04:08 +00003395 xmlBufferWriteCHAR(buf, cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003396#else
3397 xmlBufferWriteCHAR(buf, xmlBufferContent(cur->content));
3398#endif
Daniel Veillardb05deb71999-08-10 19:04:08 +00003399 xmlBufferWriteChar(buf, "]]>");
3400 return;
3401 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003402
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003403 if (format == 1) {
3404 tmp = cur->childs;
3405 while (tmp != NULL) {
3406 if ((tmp->type == XML_TEXT_NODE) ||
3407 (tmp->type == XML_ENTITY_REF_NODE)) {
3408 format = 0;
3409 break;
3410 }
3411 tmp = tmp->next;
3412 }
3413 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003414 xmlBufferWriteChar(buf, "<");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003415 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003416 xmlBufferWriteCHAR(buf, cur->ns->prefix);
3417 xmlBufferWriteChar(buf, ":");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003418 }
3419
Daniel Veillard5099ae81999-04-21 20:12:07 +00003420 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003421 if (cur->nsDef)
Daniel Veillard5099ae81999-04-21 20:12:07 +00003422 xmlNsListDump(buf, cur->nsDef);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003423 if (cur->properties != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00003424 xmlAttrListDump(buf, doc, cur->properties);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003425
3426 if ((cur->content == NULL) && (cur->childs == NULL)) {
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003427 xmlBufferWriteChar(buf, "/>");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003428 return;
3429 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003430 xmlBufferWriteChar(buf, ">");
Daniel Veillard14fff061999-06-22 21:49:07 +00003431 if (cur->content != NULL) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003432 xmlChar *buffer;
Daniel Veillard14fff061999-06-22 21:49:07 +00003433
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003434#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard14fff061999-06-22 21:49:07 +00003435 buffer = xmlEncodeEntitiesReentrant(doc, cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003436#else
3437 buffer = xmlEncodeEntitiesReentrant(doc,
3438 xmlBufferContent(cur->content));
3439#endif
Daniel Veillard14fff061999-06-22 21:49:07 +00003440 if (buffer != NULL) {
3441 xmlBufferWriteCHAR(buf, buffer);
Daniel Veillard6454aec1999-09-02 22:04:43 +00003442 xmlFree(buffer);
Daniel Veillard14fff061999-06-22 21:49:07 +00003443 }
3444 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003445 if (cur->childs != NULL) {
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003446 if (format) xmlBufferWriteChar(buf, "\n");
3447 xmlNodeListDump(buf, doc, cur->childs, level + 1, format);
3448 if ((xmlIndentTreeOutput) && (format))
3449 for (i = 0;i < level;i++)
3450 xmlBufferWriteChar(buf, " ");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003451 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003452 xmlBufferWriteChar(buf, "</");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003453 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003454 xmlBufferWriteCHAR(buf, cur->ns->prefix);
3455 xmlBufferWriteChar(buf, ":");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003456 }
3457
Daniel Veillard5099ae81999-04-21 20:12:07 +00003458 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003459 xmlBufferWriteChar(buf, ">");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003460}
3461
Daniel Veillard97b58771998-10-20 06:14:16 +00003462/**
3463 * xmlDocContentDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003464 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003465 * @cur: the document
3466 *
3467 * Dump an XML document.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003468 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003469static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00003470xmlDocContentDump(xmlBufferPtr buf, xmlDocPtr cur) {
Daniel Veillardbe70ff71999-07-05 16:50:46 +00003471 xmlBufferWriteChar(buf, "<?xml version=");
3472 if (cur->version != NULL)
3473 xmlBufferWriteQuotedString(buf, cur->version);
3474 else
3475 xmlBufferWriteChar(buf, "\"1.0\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003476 if (cur->encoding != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00003477 xmlBufferWriteChar(buf, " encoding=");
3478 xmlBufferWriteQuotedString(buf, cur->encoding);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003479 }
3480 switch (cur->standalone) {
3481 case 0:
Daniel Veillard5099ae81999-04-21 20:12:07 +00003482 xmlBufferWriteChar(buf, " standalone=\"no\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003483 break;
3484 case 1:
Daniel Veillard5099ae81999-04-21 20:12:07 +00003485 xmlBufferWriteChar(buf, " standalone=\"yes\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003486 break;
3487 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003488 xmlBufferWriteChar(buf, "?>\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003489 if (cur->intSubset != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00003490 xmlDtdDump(buf, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003491 if (cur->root != NULL) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00003492 xmlNodePtr child = cur->root;
3493
Daniel Veillard260a68f1998-08-13 03:39:55 +00003494 /* global namespace definitions, the old way */
3495 if (oldXMLWDcompatibility)
Daniel Veillard5099ae81999-04-21 20:12:07 +00003496 xmlGlobalNsListDump(buf, cur->oldNs);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003497 else
3498 xmlUpgradeOldNs(cur);
Daniel Veillardb96e6431999-08-29 21:02:19 +00003499
3500 while (child != NULL) {
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003501 xmlNodeDump(buf, cur, child, 0, 1);
3502 xmlBufferWriteChar(buf, "\n");
Daniel Veillardb96e6431999-08-29 21:02:19 +00003503 child = child->next;
3504 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003505 }
3506}
3507
Daniel Veillard97b58771998-10-20 06:14:16 +00003508/**
3509 * xmlDocDumpMemory:
3510 * @cur: the document
3511 * @mem: OUT: the memory pointer
3512 * @size: OUT: the memory lenght
3513 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003514 * Dump an XML document in memory and return the xmlChar * and it's size.
Daniel Veillard97b58771998-10-20 06:14:16 +00003515 * It's up to the caller to free the memory.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003516 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003517void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003518xmlDocDumpMemory(xmlDocPtr cur, xmlChar**mem, int *size) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003519 xmlBufferPtr buf;
3520
Daniel Veillard260a68f1998-08-13 03:39:55 +00003521 if (cur == NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003522#ifdef DEBUG_TREE
3523 fprintf(stderr, "xmlDocDumpMemory : document == NULL\n");
3524#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00003525 *mem = NULL;
3526 *size = 0;
3527 return;
3528 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003529 buf = xmlBufferCreate();
3530 if (buf == NULL) {
3531 *mem = NULL;
3532 *size = 0;
3533 return;
3534 }
3535 xmlDocContentDump(buf, cur);
Daniel Veillardb05deb71999-08-10 19:04:08 +00003536 *mem = xmlStrndup(buf->content, buf->use);
Daniel Veillard5099ae81999-04-21 20:12:07 +00003537 *size = buf->use;
Daniel Veillardb05deb71999-08-10 19:04:08 +00003538 xmlBufferFree(buf);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003539}
3540
Daniel Veillard97b58771998-10-20 06:14:16 +00003541/**
3542 * xmlGetDocCompressMode:
3543 * @doc: the document
3544 *
3545 * get the compression ratio for a document, ZLIB based
Daniel Veillard1e346af1999-02-22 10:33:01 +00003546 * Returns 0 (uncompressed) to 9 (max compression)
Daniel Veillard151b1b01998-09-23 00:49:46 +00003547 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003548int
3549 xmlGetDocCompressMode (xmlDocPtr doc) {
Daniel Veillard15a8df41998-09-24 19:15:06 +00003550 if (doc == NULL) return(-1);
3551 return(doc->compression);
3552}
3553
Daniel Veillard97b58771998-10-20 06:14:16 +00003554/**
3555 * xmlSetDocCompressMode:
3556 * @doc: the document
3557 * @mode: the compression ratio
3558 *
3559 * set the compression ratio for a document, ZLIB based
3560 * Correct values: 0 (uncompressed) to 9 (max compression)
3561 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003562void
3563xmlSetDocCompressMode (xmlDocPtr doc, int mode) {
Daniel Veillard15a8df41998-09-24 19:15:06 +00003564 if (doc == NULL) return;
3565 if (mode < 0) doc->compression = 0;
3566 else if (mode > 9) doc->compression = 9;
3567 else doc->compression = mode;
3568}
3569
Daniel Veillard97b58771998-10-20 06:14:16 +00003570/**
3571 * xmlGetCompressMode:
3572 *
3573 * get the default compression mode used, ZLIB based.
Daniel Veillard1e346af1999-02-22 10:33:01 +00003574 * Returns 0 (uncompressed) to 9 (max compression)
Daniel Veillard15a8df41998-09-24 19:15:06 +00003575 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003576int
3577 xmlGetCompressMode(void) {
Daniel Veillard151b1b01998-09-23 00:49:46 +00003578 return(xmlCompressMode);
3579}
Daniel Veillard97b58771998-10-20 06:14:16 +00003580
3581/**
3582 * xmlSetCompressMode:
3583 * @mode: the compression ratio
3584 *
3585 * set the default compression mode used, ZLIB based
3586 * Correct values: 0 (uncompressed) to 9 (max compression)
3587 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003588void
3589xmlSetCompressMode(int mode) {
Daniel Veillard151b1b01998-09-23 00:49:46 +00003590 if (mode < 0) xmlCompressMode = 0;
Daniel Veillard15a8df41998-09-24 19:15:06 +00003591 else if (mode > 9) xmlCompressMode = 9;
Daniel Veillard151b1b01998-09-23 00:49:46 +00003592 else xmlCompressMode = mode;
3593}
3594
Daniel Veillard97b58771998-10-20 06:14:16 +00003595/**
3596 * xmlDocDump:
3597 * @f: the FILE*
3598 * @cur: the document
3599 *
3600 * Dump an XML document to an open FILE.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003601 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003602void
3603xmlDocDump(FILE *f, xmlDocPtr cur) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003604 xmlBufferPtr buf;
3605
Daniel Veillard260a68f1998-08-13 03:39:55 +00003606 if (cur == NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003607#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00003608 fprintf(stderr, "xmlDocDump : document == NULL\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003609#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00003610 return;
3611 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003612 buf = xmlBufferCreate();
3613 if (buf == NULL) return;
3614 xmlDocContentDump(buf, cur);
3615 xmlBufferDump(f, buf);
3616 xmlBufferFree(buf);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003617}
3618
Daniel Veillard97b58771998-10-20 06:14:16 +00003619/**
3620 * xmlSaveFile:
3621 * @filename: the filename
3622 * @cur: the document
3623 *
3624 * Dump an XML document to a file. Will use compression if
Daniel Veillard11a48ec1999-11-23 10:40:46 +00003625 * compiled in and enabled. If @filename is "-" the stdout file is
3626 * used.
Daniel Veillard97b58771998-10-20 06:14:16 +00003627 * returns: the number of file written or -1 in case of failure.
Daniel Veillard151b1b01998-09-23 00:49:46 +00003628 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003629int
3630xmlSaveFile(const char *filename, xmlDocPtr cur) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003631 xmlBufferPtr buf;
Daniel Veillard151b1b01998-09-23 00:49:46 +00003632#ifdef HAVE_ZLIB_H
3633 gzFile zoutput = NULL;
3634 char mode[15];
3635#endif
Daniel Veillardccb09631998-10-27 06:21:04 +00003636 FILE *output = NULL;
Daniel Veillard151b1b01998-09-23 00:49:46 +00003637 int ret;
3638
Daniel Veillard5099ae81999-04-21 20:12:07 +00003639 /*
3640 * save the content to a temp buffer.
3641 */
3642 buf = xmlBufferCreate();
3643 if (buf == NULL) return(0);
3644 xmlDocContentDump(buf, cur);
3645
Daniel Veillard151b1b01998-09-23 00:49:46 +00003646#ifdef HAVE_ZLIB_H
Daniel Veillard11a48ec1999-11-23 10:40:46 +00003647 if (cur->compression < 0) cur->compression = xmlCompressMode;
Daniel Veillarddc3dd9d1998-09-24 19:25:54 +00003648 if ((cur->compression > 0) && (cur->compression <= 9)) {
3649 sprintf(mode, "w%d", cur->compression);
Daniel Veillard11a48ec1999-11-23 10:40:46 +00003650 if (!strcmp(filename, "-"))
3651 zoutput = gzdopen(1, mode);
3652 else
3653 zoutput = gzopen(filename, mode);
Daniel Veillard151b1b01998-09-23 00:49:46 +00003654 }
3655 if (zoutput == NULL) {
3656#endif
3657 output = fopen(filename, "w");
3658 if (output == NULL) return(-1);
3659#ifdef HAVE_ZLIB_H
3660 }
Daniel Veillard151b1b01998-09-23 00:49:46 +00003661
Daniel Veillard151b1b01998-09-23 00:49:46 +00003662 if (zoutput != NULL) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003663 ret = gzwrite(zoutput, buf->content, sizeof(xmlChar) * buf->use);
Daniel Veillard151b1b01998-09-23 00:49:46 +00003664 gzclose(zoutput);
Daniel Veillard5099ae81999-04-21 20:12:07 +00003665 } else {
3666#endif
3667 ret = xmlBufferDump(output, buf);
3668 fclose(output);
3669#ifdef HAVE_ZLIB_H
Daniel Veillard151b1b01998-09-23 00:49:46 +00003670 }
3671#endif
Manish Vachharajani5e60f5a1999-05-29 03:04:30 +00003672 xmlBufferFree(buf);
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003673 return(ret * sizeof(xmlChar));
Daniel Veillard151b1b01998-09-23 00:49:46 +00003674}
3675