blob: 3242aecedaa01a479d2adefe8afd7b97c4093fea [file] [log] [blame]
Daniel Veillard260a68f1998-08-13 03:39:55 +00001/*
2 * tree.c : implemetation of access function for an XML tree.
3 *
4 * See Copyright for the status of this software.
5 *
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00006 * Daniel.Veillard@w3.org
Daniel Veillard260a68f1998-08-13 03:39:55 +00007 */
8
Daniel Veillard7f7d1111999-09-22 09:46:25 +00009#ifdef WIN32
Daniel Veillard3c558c31999-12-22 11:30:41 +000010#include "win32config.h"
Daniel Veillard7f7d1111999-09-22 09:46:25 +000011#else
Daniel Veillard151b1b01998-09-23 00:49:46 +000012#include "config.h"
Daniel Veillard7f7d1111999-09-22 09:46:25 +000013#endif
14
Daniel Veillard260a68f1998-08-13 03:39:55 +000015#include <stdio.h>
Daniel Veillard260a68f1998-08-13 03:39:55 +000016#include <string.h> /* for memset() only ! */
17
Daniel Veillard7f7d1111999-09-22 09:46:25 +000018#ifdef HAVE_CTYPE_H
19#include <ctype.h>
20#endif
21#ifdef HAVE_STDLIB_H
22#include <stdlib.h>
23#endif
Daniel Veillard151b1b01998-09-23 00:49:46 +000024#ifdef HAVE_ZLIB_H
25#include <zlib.h>
26#endif
27
Daniel Veillard6454aec1999-09-02 22:04:43 +000028#include "xmlmemory.h"
Daniel Veillard260a68f1998-08-13 03:39:55 +000029#include "tree.h"
Daniel Veillard37846c61999-12-16 17:52:19 +000030#include "parser.h"
Daniel Veillard260a68f1998-08-13 03:39:55 +000031#include "entities.h"
Daniel Veillard3b9def11999-01-31 22:15:06 +000032#include "valid.h"
Daniel Veillard260a68f1998-08-13 03:39:55 +000033
Daniel Veillarddd6b3671999-09-23 22:19:22 +000034static xmlChar xmlStringText[] = { 't', 'e', 'x', 't', 0 };
Daniel Veillard260a68f1998-08-13 03:39:55 +000035int oldXMLWDcompatibility = 0;
36int xmlIndentTreeOutput = 1;
Daniel Veillardf5c2c871999-12-01 09:51:45 +000037xmlBufferAllocationScheme xmlBufferAllocScheme = XML_BUFFER_ALLOC_EXACT;
Daniel Veillard260a68f1998-08-13 03:39:55 +000038
Daniel Veillard15a8df41998-09-24 19:15:06 +000039static int xmlCompressMode = 0;
Daniel Veillard10a2c651999-12-12 13:03:50 +000040static int xmlCheckDTD = 1;
Daniel Veillard15a8df41998-09-24 19:15:06 +000041
Daniel Veillard39a1f9a1999-01-17 19:11:59 +000042#define UPDATE_LAST_CHILD(n) if ((n) != NULL) { \
43 xmlNodePtr ulccur = (n)->childs; \
44 if (ulccur == NULL) { \
45 (n)->last = NULL; \
46 } else { \
47 while (ulccur->next != NULL) ulccur = ulccur->next; \
48 (n)->last = ulccur; \
Daniel Veillard1e346af1999-02-22 10:33:01 +000049}}
Daniel Veillard39a1f9a1999-01-17 19:11:59 +000050
Daniel Veillard260a68f1998-08-13 03:39:55 +000051/************************************************************************
52 * *
53 * Allocation and deallocation of basic structures *
54 * *
55 ************************************************************************/
56
Daniel Veillard97b58771998-10-20 06:14:16 +000057/**
Daniel Veillardf5c2c871999-12-01 09:51:45 +000058 * xmlSetBufferAllocationScheme:
59 * @scheme: allocation method to use
60 *
61 * Set the buffer allocation method. Types are
62 * XML_BUFFER_ALLOC_EXACT - use exact sizes, keeps memory usage down
63 * XML_BUFFER_ALLOC_DOUBLEIT - double buffer when extra needed,
64 * improves performance
65 */
66void
67xmlSetBufferAllocationScheme(xmlBufferAllocationScheme scheme) {
68 xmlBufferAllocScheme = scheme;
69}
70
71/**
72 * xmlGetBufferAllocationScheme:
73 *
74 * Types are
75 * XML_BUFFER_ALLOC_EXACT - use exact sizes, keeps memory usage down
76 * XML_BUFFER_ALLOC_DOUBLEIT - double buffer when extra needed,
77 * improves performance
78 *
79 * Returns the current allocation scheme
80 */
81xmlBufferAllocationScheme
82xmlGetBufferAllocationScheme() {
83 return xmlBufferAllocScheme;
84}
85
86/**
Daniel Veillard97b58771998-10-20 06:14:16 +000087 * xmlUpgradeOldNs:
88 * @doc: a document pointer
89 *
90 * Upgrade old style Namespaces (PI) and move them to the root of the document.
Daniel Veillard260a68f1998-08-13 03:39:55 +000091 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +000092void
93xmlUpgradeOldNs(xmlDocPtr doc) {
Daniel Veillard260a68f1998-08-13 03:39:55 +000094 xmlNsPtr cur;
95
96 if ((doc == NULL) || (doc->oldNs == NULL)) return;
97 if (doc->root == NULL) {
98 fprintf(stderr, "xmlUpgradeOldNs: failed no root !\n");
99 return;
100 }
101
102 cur = doc->oldNs;
103 while (cur->next != NULL) {
104 cur->type = XML_LOCAL_NAMESPACE;
105 cur = cur->next;
106 }
107 cur->type = XML_LOCAL_NAMESPACE;
108 cur->next = doc->root->nsDef;
109 doc->root->nsDef = doc->oldNs;
110 doc->oldNs = NULL;
111}
112
Daniel Veillard97b58771998-10-20 06:14:16 +0000113/**
114 * xmlNewNs:
115 * @node: the element carrying the namespace
116 * @href: the URI associated
117 * @prefix: the prefix for the namespace
118 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000119 * Creation of a new Namespace.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000120 * Returns returns a new namespace pointer
Daniel Veillard260a68f1998-08-13 03:39:55 +0000121 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000122xmlNsPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000123xmlNewNs(xmlNodePtr node, const xmlChar *href, const xmlChar *prefix) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000124 xmlNsPtr cur;
125
126 if (href == NULL) {
127 fprintf(stderr, "xmlNewNs: href == NULL !\n");
128 return(NULL);
129 }
130
131 /*
132 * Allocate a new DTD and fill the fields.
133 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000134 cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000135 if (cur == NULL) {
136 fprintf(stderr, "xmlNewNs : malloc failed\n");
137 return(NULL);
138 }
139
140 cur->type = XML_LOCAL_NAMESPACE;
141 if (href != NULL)
142 cur->href = xmlStrdup(href);
143 else
144 cur->href = NULL;
145 if (prefix != NULL)
146 cur->prefix = xmlStrdup(prefix);
147 else
148 cur->prefix = NULL;
149
150 /*
151 * Add it at the end to preserve parsing order ...
152 */
153 cur->next = NULL;
154 if (node != NULL) {
155 if (node->nsDef == NULL) {
156 node->nsDef = cur;
157 } else {
158 xmlNsPtr prev = node->nsDef;
159
160 while (prev->next != NULL) prev = prev->next;
161 prev->next = cur;
162 }
163 }
164
165 return(cur);
166}
167
Daniel Veillard97b58771998-10-20 06:14:16 +0000168/**
169 * xmlNewGlobalNs:
170 * @doc: the document carrying the namespace
171 * @href: the URI associated
172 * @prefix: the prefix for the namespace
173 *
174 * Creation of a Namespace, the old way using PI and without scoping, to AVOID.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000175 * Returns returns a new namespace pointer
Daniel Veillard260a68f1998-08-13 03:39:55 +0000176 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000177xmlNsPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000178xmlNewGlobalNs(xmlDocPtr doc, const xmlChar *href, const xmlChar *prefix) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000179 xmlNsPtr cur;
180
181 /*
182 * Allocate a new DTD and fill the fields.
183 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000184 cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000185 if (cur == NULL) {
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000186 fprintf(stderr, "xmlNewGlobalNs : malloc failed\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +0000187 return(NULL);
188 }
189
190 cur->type = XML_GLOBAL_NAMESPACE;
191 if (href != NULL)
192 cur->href = xmlStrdup(href);
193 else
194 cur->href = NULL;
195 if (prefix != NULL)
196 cur->prefix = xmlStrdup(prefix);
197 else
198 cur->prefix = NULL;
199
200 /*
201 * Add it at the end to preserve parsing order ...
202 */
203 cur->next = NULL;
204 if (doc != NULL) {
205 if (doc->oldNs == NULL) {
206 doc->oldNs = cur;
207 } else {
208 xmlNsPtr prev = doc->oldNs;
209
210 while (prev->next != NULL) prev = prev->next;
211 prev->next = cur;
212 }
213 }
214
215 return(cur);
216}
217
Daniel Veillard97b58771998-10-20 06:14:16 +0000218/**
219 * xmlSetNs:
220 * @node: a node in the document
221 * @ns: a namespace pointer
222 *
223 * Associate a namespace to a node, a posteriori.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000224 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000225void
226xmlSetNs(xmlNodePtr node, xmlNsPtr ns) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000227 if (node == NULL) {
228 fprintf(stderr, "xmlSetNs: node == NULL\n");
229 return;
230 }
231 node->ns = ns;
232}
233
Daniel Veillard97b58771998-10-20 06:14:16 +0000234/**
235 * xmlFreeNs:
236 * @cur: the namespace pointer
237 *
238 * Free up the structures associated to a namespace
Daniel Veillard260a68f1998-08-13 03:39:55 +0000239 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000240void
241xmlFreeNs(xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000242 if (cur == NULL) {
243 fprintf(stderr, "xmlFreeNs : ns == NULL\n");
244 return;
245 }
Daniel Veillard6454aec1999-09-02 22:04:43 +0000246 if (cur->href != NULL) xmlFree((char *) cur->href);
247 if (cur->prefix != NULL) xmlFree((char *) cur->prefix);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000248 memset(cur, -1, sizeof(xmlNs));
Daniel Veillard6454aec1999-09-02 22:04:43 +0000249 xmlFree(cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000250}
251
Daniel Veillard97b58771998-10-20 06:14:16 +0000252/**
253 * xmlFreeNsList:
254 * @cur: the first namespace pointer
255 *
256 * Free up all the structures associated to the chained namespaces.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000257 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000258void
259xmlFreeNsList(xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000260 xmlNsPtr next;
261 if (cur == NULL) {
262 fprintf(stderr, "xmlFreeNsList : ns == NULL\n");
263 return;
264 }
265 while (cur != NULL) {
266 next = cur->next;
267 xmlFreeNs(cur);
268 cur = next;
269 }
270}
271
Daniel Veillard97b58771998-10-20 06:14:16 +0000272/**
273 * xmlNewDtd:
274 * @doc: the document pointer
275 * @name: the DTD name
276 * @ExternalID: the external ID
277 * @SystemID: the system ID
278 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000279 * Creation of a new DTD.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000280 * Returns a pointer to the new DTD structure
Daniel Veillard260a68f1998-08-13 03:39:55 +0000281 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000282xmlDtdPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000283xmlNewDtd(xmlDocPtr doc, const xmlChar *name,
284 const xmlChar *ExternalID, const xmlChar *SystemID) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000285 xmlDtdPtr cur;
286
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000287 if ((doc != NULL) && (doc->extSubset != NULL)) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000288 fprintf(stderr, "xmlNewDtd(%s): document %s already have a DTD %s\n",
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000289 /* !!! */ (char *) name, doc->name,
290 /* !!! */ (char *)doc->extSubset->name);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000291 }
292
293 /*
294 * Allocate a new DTD and fill the fields.
295 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000296 cur = (xmlDtdPtr) xmlMalloc(sizeof(xmlDtd));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000297 if (cur == NULL) {
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000298 fprintf(stderr, "xmlNewDtd : malloc failed\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +0000299 return(NULL);
300 }
301
302 if (name != NULL)
303 cur->name = xmlStrdup(name);
304 else
305 cur->name = NULL;
306 if (ExternalID != NULL)
307 cur->ExternalID = xmlStrdup(ExternalID);
308 else
309 cur->ExternalID = NULL;
310 if (SystemID != NULL)
311 cur->SystemID = xmlStrdup(SystemID);
312 else
313 cur->SystemID = NULL;
Daniel Veillard1e346af1999-02-22 10:33:01 +0000314 cur->notations = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000315 cur->elements = NULL;
Daniel Veillard1e346af1999-02-22 10:33:01 +0000316 cur->attributes = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000317 cur->entities = NULL;
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000318 if (doc != NULL)
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000319 doc->extSubset = cur;
320
321 return(cur);
322}
323
324/**
325 * xmlCreateIntSubset:
326 * @doc: the document pointer
327 * @name: the DTD name
328 * @ExternalID: the external ID
329 * @SystemID: the system ID
330 *
Daniel Veillard1e346af1999-02-22 10:33:01 +0000331 * Create the internal subset of a document
332 * Returns a pointer to the new DTD structure
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000333 */
334xmlDtdPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000335xmlCreateIntSubset(xmlDocPtr doc, const xmlChar *name,
336 const xmlChar *ExternalID, const xmlChar *SystemID) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000337 xmlDtdPtr cur;
338
339 if ((doc != NULL) && (doc->intSubset != NULL)) {
340 fprintf(stderr,
341 "xmlCreateIntSubset(): document %s already have an internal subset\n",
342 doc->name);
343 return(NULL);
344 }
345
346 /*
347 * Allocate a new DTD and fill the fields.
348 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000349 cur = (xmlDtdPtr) xmlMalloc(sizeof(xmlDtd));
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000350 if (cur == NULL) {
351 fprintf(stderr, "xmlNewDtd : malloc failed\n");
352 return(NULL);
353 }
354
355 if (name != NULL)
356 cur->name = xmlStrdup(name);
357 else
358 cur->name = NULL;
359 if (ExternalID != NULL)
360 cur->ExternalID = xmlStrdup(ExternalID);
361 else
362 cur->ExternalID = NULL;
363 if (SystemID != NULL)
364 cur->SystemID = xmlStrdup(SystemID);
365 else
366 cur->SystemID = NULL;
Daniel Veillard1e346af1999-02-22 10:33:01 +0000367 cur->notations = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000368 cur->elements = NULL;
Daniel Veillard1e346af1999-02-22 10:33:01 +0000369 cur->attributes = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000370 cur->entities = NULL;
371 if (doc != NULL)
372 doc->intSubset = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000373
374 return(cur);
375}
376
Daniel Veillard97b58771998-10-20 06:14:16 +0000377/**
378 * xmlFreeDtd:
379 * @cur: the DTD structure to free up
380 *
381 * Free a DTD structure.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000382 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000383void
384xmlFreeDtd(xmlDtdPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000385 if (cur == NULL) {
386 fprintf(stderr, "xmlFreeDtd : DTD == NULL\n");
387 return;
388 }
Daniel Veillard6454aec1999-09-02 22:04:43 +0000389 if (cur->name != NULL) xmlFree((char *) cur->name);
390 if (cur->SystemID != NULL) xmlFree((char *) cur->SystemID);
391 if (cur->ExternalID != NULL) xmlFree((char *) cur->ExternalID);
Daniel Veillard1e346af1999-02-22 10:33:01 +0000392 if (cur->notations != NULL)
393 xmlFreeNotationTable((xmlNotationTablePtr) cur->notations);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000394 if (cur->elements != NULL)
Daniel Veillard3b9def11999-01-31 22:15:06 +0000395 xmlFreeElementTable((xmlElementTablePtr) cur->elements);
Daniel Veillard1e346af1999-02-22 10:33:01 +0000396 if (cur->attributes != NULL)
397 xmlFreeAttributeTable((xmlAttributeTablePtr) cur->attributes);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000398 if (cur->entities != NULL)
399 xmlFreeEntitiesTable((xmlEntitiesTablePtr) cur->entities);
400 memset(cur, -1, sizeof(xmlDtd));
Daniel Veillard6454aec1999-09-02 22:04:43 +0000401 xmlFree(cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000402}
403
Daniel Veillard97b58771998-10-20 06:14:16 +0000404/**
405 * xmlNewDoc:
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000406 * @version: xmlChar string giving the version of XML "1.0"
Daniel Veillard97b58771998-10-20 06:14:16 +0000407 *
Daniel Veillard1e346af1999-02-22 10:33:01 +0000408 * Returns a new document
Daniel Veillard260a68f1998-08-13 03:39:55 +0000409 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000410xmlDocPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000411xmlNewDoc(const xmlChar *version) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000412 xmlDocPtr cur;
413
414 if (version == NULL) {
415 fprintf(stderr, "xmlNewDoc : version == NULL\n");
416 return(NULL);
417 }
418
419 /*
420 * Allocate a new document and fill the fields.
421 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000422 cur = (xmlDocPtr) xmlMalloc(sizeof(xmlDoc));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000423 if (cur == NULL) {
424 fprintf(stderr, "xmlNewDoc : malloc failed\n");
425 return(NULL);
426 }
427
Daniel Veillard33942841998-10-18 19:12:41 +0000428 cur->type = XML_DOCUMENT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000429 cur->version = xmlStrdup(version);
430 cur->name = NULL;
431 cur->root = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000432 cur->intSubset = NULL;
433 cur->extSubset = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000434 cur->oldNs = NULL;
435 cur->encoding = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000436 cur->standalone = -1;
Daniel Veillard11a48ec1999-11-23 10:40:46 +0000437 cur->compression = -1; /* not initialized */
Daniel Veillardb96e6431999-08-29 21:02:19 +0000438 cur->ids = NULL;
Daniel Veillardc08a2c61999-09-08 21:35:25 +0000439 cur->refs = NULL;
Daniel Veillard27d88741999-05-29 11:51:49 +0000440#ifndef XML_WITHOUT_CORBA
Daniel Veillard27fb0751998-10-17 06:47:46 +0000441 cur->_private = NULL;
442 cur->vepv = NULL;
443#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000444 return(cur);
445}
446
Daniel Veillard97b58771998-10-20 06:14:16 +0000447/**
448 * xmlFreeDoc:
449 * @cur: pointer to the document
450 * @:
451 *
452 * Free up all the structures used by a document, tree included.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000453 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000454void
455xmlFreeDoc(xmlDocPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000456 if (cur == NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000457#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +0000458 fprintf(stderr, "xmlFreeDoc : document == NULL\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000459#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000460 return;
461 }
Daniel Veillard6454aec1999-09-02 22:04:43 +0000462 if (cur->version != NULL) xmlFree((char *) cur->version);
463 if (cur->name != NULL) xmlFree((char *) cur->name);
464 if (cur->encoding != NULL) xmlFree((char *) cur->encoding);
465 if (cur->root != NULL) xmlFreeNodeList(cur->root);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000466 if (cur->intSubset != NULL) xmlFreeDtd(cur->intSubset);
467 if (cur->extSubset != NULL) xmlFreeDtd(cur->extSubset);
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000468 if (cur->oldNs != NULL) xmlFreeNsList(cur->oldNs);
Daniel Veillardb96e6431999-08-29 21:02:19 +0000469 if (cur->ids != NULL) xmlFreeIDTable((xmlIDTablePtr) cur->ids);
Daniel Veillardc08a2c61999-09-08 21:35:25 +0000470 if (cur->refs != NULL) xmlFreeRefTable((xmlRefTablePtr) cur->refs);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000471 memset(cur, -1, sizeof(xmlDoc));
Daniel Veillard6454aec1999-09-02 22:04:43 +0000472 xmlFree(cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000473}
474
Daniel Veillard97b58771998-10-20 06:14:16 +0000475/**
Daniel Veillard16253641998-10-28 22:58:05 +0000476 * xmlStringLenGetNodeList:
477 * @doc: the document
478 * @value: the value of the text
Daniel Veillard1e346af1999-02-22 10:33:01 +0000479 * @len: the length of the string value
Daniel Veillard16253641998-10-28 22:58:05 +0000480 *
481 * Parse the value string and build the node list associated. Should
482 * produce a flat tree with only TEXTs and ENTITY_REFs.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000483 * Returns a pointer to the first child
Daniel Veillard16253641998-10-28 22:58:05 +0000484 */
485xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000486xmlStringLenGetNodeList(xmlDocPtr doc, const xmlChar *value, int len) {
Daniel Veillard16253641998-10-28 22:58:05 +0000487 xmlNodePtr ret = NULL, last = NULL;
488 xmlNodePtr node;
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000489 xmlChar *val;
490 const xmlChar *cur = value;
491 const xmlChar *q;
Daniel Veillard25940b71998-10-29 05:51:30 +0000492 xmlEntityPtr ent;
Daniel Veillard16253641998-10-28 22:58:05 +0000493
494 if (value == NULL) return(NULL);
495
496 q = cur;
497 while ((*cur != 0) && (cur - value < len)) {
498 if (*cur == '&') {
Daniel Veillard25940b71998-10-29 05:51:30 +0000499 /*
500 * Save the current text.
501 */
Daniel Veillard16253641998-10-28 22:58:05 +0000502 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000503 if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
504 xmlNodeAddContentLen(last, q, cur - q);
505 } else {
506 node = xmlNewDocTextLen(doc, q, cur - q);
507 if (node == NULL) return(ret);
508 if (last == NULL)
509 last = ret = node;
510 else {
511 last->next = node;
512 node->prev = last;
513 last = node;
514 }
Daniel Veillard16253641998-10-28 22:58:05 +0000515 }
516 }
Daniel Veillard25940b71998-10-29 05:51:30 +0000517 /*
518 * Read the entity string
519 */
Daniel Veillard16253641998-10-28 22:58:05 +0000520 cur++;
521 q = cur;
522 while ((*cur != 0) && (cur - value < len) && (*cur != ';')) cur++;
523 if ((*cur == 0) || (cur - value >= len)) {
524 fprintf(stderr,
Daniel Veillard011b63c1999-06-02 17:44:04 +0000525 "xmlStringLenGetNodeList: unterminated entity %30s\n", q);
Daniel Veillard16253641998-10-28 22:58:05 +0000526 return(ret);
527 }
528 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000529 /*
530 * Predefined entities don't generate nodes
531 */
Daniel Veillard16253641998-10-28 22:58:05 +0000532 val = xmlStrndup(q, cur - q);
Daniel Veillard25940b71998-10-29 05:51:30 +0000533 ent = xmlGetDocEntity(doc, val);
534 if ((ent != NULL) &&
535 (ent->type == XML_INTERNAL_PREDEFINED_ENTITY)) {
536 if (last == NULL) {
537 node = xmlNewDocText(doc, ent->content);
538 last = ret = node;
539 } else
540 xmlNodeAddContent(last, ent->content);
541
542 } else {
543 /*
544 * Create a new REFERENCE_REF node
545 */
546 node = xmlNewReference(doc, val);
Daniel Veillard242590e1998-11-13 18:04:35 +0000547 if (node == NULL) {
Daniel Veillard6454aec1999-09-02 22:04:43 +0000548 if (val != NULL) xmlFree(val);
Daniel Veillard242590e1998-11-13 18:04:35 +0000549 return(ret);
550 }
Daniel Veillard25940b71998-10-29 05:51:30 +0000551 if (last == NULL)
552 last = ret = node;
553 else {
554 last->next = node;
555 node->prev = last;
556 last = node;
557 }
Daniel Veillard16253641998-10-28 22:58:05 +0000558 }
Daniel Veillard6454aec1999-09-02 22:04:43 +0000559 xmlFree(val);
Daniel Veillard16253641998-10-28 22:58:05 +0000560 }
561 cur++;
562 q = cur;
563 } else
564 cur++;
565 }
566 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000567 /*
568 * Handle the last piece of text.
569 */
570 if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
571 xmlNodeAddContentLen(last, q, cur - q);
572 } else {
573 node = xmlNewDocTextLen(doc, q, cur - q);
574 if (node == NULL) return(ret);
575 if (last == NULL)
576 last = ret = node;
577 else {
578 last->next = node;
579 node->prev = last;
580 last = node;
581 }
Daniel Veillard16253641998-10-28 22:58:05 +0000582 }
583 }
584 return(ret);
585}
586
587/**
Daniel Veillardccb09631998-10-27 06:21:04 +0000588 * xmlStringGetNodeList:
589 * @doc: the document
590 * @value: the value of the attribute
591 *
592 * Parse the value string and build the node list associated. Should
593 * produce a flat tree with only TEXTs and ENTITY_REFs.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000594 * Returns a pointer to the first child
Daniel Veillardccb09631998-10-27 06:21:04 +0000595 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000596xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000597xmlStringGetNodeList(xmlDocPtr doc, const xmlChar *value) {
Daniel Veillardccb09631998-10-27 06:21:04 +0000598 xmlNodePtr ret = NULL, last = NULL;
599 xmlNodePtr node;
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000600 xmlChar *val;
601 const xmlChar *cur = value;
602 const xmlChar *q;
Daniel Veillard25940b71998-10-29 05:51:30 +0000603 xmlEntityPtr ent;
Daniel Veillardccb09631998-10-27 06:21:04 +0000604
605 if (value == NULL) return(NULL);
606
607 q = cur;
608 while (*cur != 0) {
609 if (*cur == '&') {
Daniel Veillard25940b71998-10-29 05:51:30 +0000610 /*
611 * Save the current text.
612 */
Daniel Veillardccb09631998-10-27 06:21:04 +0000613 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000614 if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
615 xmlNodeAddContentLen(last, q, cur - q);
616 } else {
617 node = xmlNewDocTextLen(doc, q, cur - q);
618 if (node == NULL) return(ret);
619 if (last == NULL)
620 last = ret = node;
621 else {
622 last->next = node;
623 node->prev = last;
624 last = node;
625 }
Daniel Veillardccb09631998-10-27 06:21:04 +0000626 }
627 }
Daniel Veillard25940b71998-10-29 05:51:30 +0000628 /*
629 * Read the entity string
630 */
Daniel Veillardccb09631998-10-27 06:21:04 +0000631 cur++;
632 q = cur;
633 while ((*cur != 0) && (*cur != ';')) cur++;
634 if (*cur == 0) {
635 fprintf(stderr,
636 "xmlStringGetNodeList: unterminated entity %30s\n", q);
637 return(ret);
638 }
639 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000640 /*
641 * Predefined entities don't generate nodes
642 */
Daniel Veillardccb09631998-10-27 06:21:04 +0000643 val = xmlStrndup(q, cur - q);
Daniel Veillard25940b71998-10-29 05:51:30 +0000644 ent = xmlGetDocEntity(doc, val);
645 if ((ent != NULL) &&
646 (ent->type == XML_INTERNAL_PREDEFINED_ENTITY)) {
647 if (last == NULL) {
648 node = xmlNewDocText(doc, ent->content);
649 last = ret = node;
650 } else
651 xmlNodeAddContent(last, ent->content);
652
653 } else {
654 /*
655 * Create a new REFERENCE_REF node
656 */
Daniel Veillard25940b71998-10-29 05:51:30 +0000657 node = xmlNewReference(doc, val);
Daniel Veillard242590e1998-11-13 18:04:35 +0000658 if (node == NULL) {
Daniel Veillard6454aec1999-09-02 22:04:43 +0000659 if (val != NULL) xmlFree(val);
Daniel Veillard242590e1998-11-13 18:04:35 +0000660 return(ret);
661 }
Daniel Veillard25940b71998-10-29 05:51:30 +0000662 if (last == NULL)
663 last = ret = node;
664 else {
665 last->next = node;
666 node->prev = last;
667 last = node;
668 }
Daniel Veillardccb09631998-10-27 06:21:04 +0000669 }
Daniel Veillard6454aec1999-09-02 22:04:43 +0000670 xmlFree(val);
Daniel Veillardccb09631998-10-27 06:21:04 +0000671 }
672 cur++;
673 q = cur;
674 } else
675 cur++;
676 }
677 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000678 /*
679 * Handle the last piece of text.
680 */
681 if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
682 xmlNodeAddContentLen(last, q, cur - q);
683 } else {
684 node = xmlNewDocTextLen(doc, q, cur - q);
685 if (node == NULL) return(ret);
686 if (last == NULL)
687 last = ret = node;
688 else {
689 last->next = node;
690 node->prev = last;
691 last = node;
692 }
Daniel Veillardccb09631998-10-27 06:21:04 +0000693 }
694 }
695 return(ret);
696}
697
698/**
699 * xmlNodeListGetString:
700 * @doc: the document
701 * @list: a Node list
702 * @inLine: should we replace entity contents or show their external form
703 *
704 * Returns the string equivalent to the text contained in the Node list
705 * made of TEXTs and ENTITY_REFs
Daniel Veillard1e346af1999-02-22 10:33:01 +0000706 * Returns a pointer to the string copy, the calller must free it.
Daniel Veillardccb09631998-10-27 06:21:04 +0000707 */
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000708xmlChar *
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000709xmlNodeListGetString(xmlDocPtr doc, xmlNodePtr list, int inLine) {
Daniel Veillardccb09631998-10-27 06:21:04 +0000710 xmlNodePtr node = list;
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000711 xmlChar *ret = NULL;
Daniel Veillardccb09631998-10-27 06:21:04 +0000712 xmlEntityPtr ent;
713
714 if (list == NULL) return(NULL);
715
716 while (node != NULL) {
717 if (node->type == XML_TEXT_NODE) {
Daniel Veillardf5c2c871999-12-01 09:51:45 +0000718 if ((inLine) || (doc->type == XML_HTML_DOCUMENT_NODE)) {
719#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardccb09631998-10-27 06:21:04 +0000720 ret = xmlStrcat(ret, node->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +0000721#else
722 ret = xmlStrcat(ret, xmlBufferContent(node->content));
723#endif
724 } else {
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000725 xmlChar *buffer;
Daniel Veillard14fff061999-06-22 21:49:07 +0000726
Daniel Veillardf5c2c871999-12-01 09:51:45 +0000727#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard14fff061999-06-22 21:49:07 +0000728 buffer = xmlEncodeEntitiesReentrant(doc, node->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +0000729#else
730 buffer = xmlEncodeEntitiesReentrant(doc,
731 xmlBufferContent(node->content));
732#endif
Daniel Veillard14fff061999-06-22 21:49:07 +0000733 if (buffer != NULL) {
734 ret = xmlStrcat(ret, buffer);
Daniel Veillard6454aec1999-09-02 22:04:43 +0000735 xmlFree(buffer);
Daniel Veillard14fff061999-06-22 21:49:07 +0000736 }
737 }
Daniel Veillardccb09631998-10-27 06:21:04 +0000738 } else if (node->type == XML_ENTITY_REF_NODE) {
739 if (inLine) {
740 ent = xmlGetDocEntity(doc, node->name);
741 if (ent != NULL)
742 ret = xmlStrcat(ret, ent->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +0000743 else {
744#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardccb09631998-10-27 06:21:04 +0000745 ret = xmlStrcat(ret, node->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +0000746#else
747 ret = xmlStrcat(ret, xmlBufferContent(node->content));
748#endif
749 }
Daniel Veillardccb09631998-10-27 06:21:04 +0000750 } else {
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000751 xmlChar buf[2];
Daniel Veillardccb09631998-10-27 06:21:04 +0000752 buf[0] = '&'; buf[1] = 0;
753 ret = xmlStrncat(ret, buf, 1);
754 ret = xmlStrcat(ret, node->name);
755 buf[0] = ';'; buf[1] = 0;
756 ret = xmlStrncat(ret, buf, 1);
757 }
758 }
759#if 0
760 else {
761 fprintf(stderr, "xmlGetNodeListString : invalide node type %d\n",
762 node->type);
763 }
764#endif
765 node = node->next;
766 }
767 return(ret);
768}
769
770/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000771 * xmlNewProp:
772 * @node: the holding node
773 * @name: the name of the attribute
774 * @value: the value of the attribute
775 *
776 * Create a new property carried by a node.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000777 * Returns a pointer to the attribute
Daniel Veillard260a68f1998-08-13 03:39:55 +0000778 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000779xmlAttrPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000780xmlNewProp(xmlNodePtr node, const xmlChar *name, const xmlChar *value) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000781 xmlAttrPtr cur;
782
783 if (name == NULL) {
784 fprintf(stderr, "xmlNewProp : name == NULL\n");
785 return(NULL);
786 }
787
788 /*
789 * Allocate a new property and fill the fields.
790 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000791 cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000792 if (cur == NULL) {
793 fprintf(stderr, "xmlNewProp : malloc failed\n");
794 return(NULL);
795 }
796
Daniel Veillard33942841998-10-18 19:12:41 +0000797 cur->type = XML_ATTRIBUTE_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000798 cur->node = node;
Daniel Veillardb96e6431999-08-29 21:02:19 +0000799 cur->ns = NULL;
800 cur->name = xmlStrdup(name);
Daniel Veillard51e3b151999-11-12 17:02:31 +0000801 if (value != NULL) {
802 xmlChar *buffer;
803 buffer = xmlEncodeEntitiesReentrant(node->doc, value);
804 cur->val = xmlStringGetNodeList(node->doc, buffer);
805 xmlFree(buffer);
806 }
Daniel Veillardb96e6431999-08-29 21:02:19 +0000807 else
808 cur->val = NULL;
809#ifndef XML_WITHOUT_CORBA
810 cur->_private = NULL;
811 cur->vepv = NULL;
812#endif
813
814 /*
815 * Add it at the end to preserve parsing order ...
816 */
817 cur->next = NULL;
818 if (node != NULL) {
819 if (node->properties == NULL) {
820 node->properties = cur;
821 } else {
822 xmlAttrPtr prev = node->properties;
823
824 while (prev->next != NULL) prev = prev->next;
825 prev->next = cur;
826 }
827 }
Daniel Veillard00fdf371999-10-08 09:40:39 +0000828#ifndef XML_WITHOUT_CORBA
829 cur->_private = NULL;
830 cur->vepv = NULL;
831#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +0000832 return(cur);
833}
834
835/**
836 * xmlNewNsProp:
837 * @node: the holding node
838 * @ns: the namespace
839 * @name: the name of the attribute
840 * @value: the value of the attribute
841 *
842 * Create a new property tagged with a namespace and carried by a node.
843 * Returns a pointer to the attribute
844 */
845xmlAttrPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000846xmlNewNsProp(xmlNodePtr node, xmlNsPtr ns, const xmlChar *name,
847 const xmlChar *value) {
Daniel Veillardb96e6431999-08-29 21:02:19 +0000848 xmlAttrPtr cur;
849
850 if (name == NULL) {
851 fprintf(stderr, "xmlNewProp : name == NULL\n");
852 return(NULL);
853 }
854
855 /*
856 * Allocate a new property and fill the fields.
857 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000858 cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr));
Daniel Veillardb96e6431999-08-29 21:02:19 +0000859 if (cur == NULL) {
860 fprintf(stderr, "xmlNewProp : malloc failed\n");
861 return(NULL);
862 }
863
864 cur->type = XML_ATTRIBUTE_NODE;
865 cur->node = node;
866 cur->ns = ns;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000867 cur->name = xmlStrdup(name);
868 if (value != NULL)
Daniel Veillardccb09631998-10-27 06:21:04 +0000869 cur->val = xmlStringGetNodeList(node->doc, value);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000870 else
Daniel Veillardccb09631998-10-27 06:21:04 +0000871 cur->val = NULL;
Daniel Veillard27d88741999-05-29 11:51:49 +0000872#ifndef XML_WITHOUT_CORBA
Daniel Veillard27fb0751998-10-17 06:47:46 +0000873 cur->_private = NULL;
874 cur->vepv = NULL;
875#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000876
877 /*
878 * Add it at the end to preserve parsing order ...
879 */
880 cur->next = NULL;
881 if (node != NULL) {
882 if (node->properties == NULL) {
883 node->properties = cur;
884 } else {
885 xmlAttrPtr prev = node->properties;
886
887 while (prev->next != NULL) prev = prev->next;
888 prev->next = cur;
889 }
890 }
891 return(cur);
892}
893
Daniel Veillard97b58771998-10-20 06:14:16 +0000894/**
Daniel Veillardccb09631998-10-27 06:21:04 +0000895 * xmlNewDocProp:
896 * @doc: the document
897 * @name: the name of the attribute
898 * @value: the value of the attribute
899 *
900 * Create a new property carried by a document.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000901 * Returns a pointer to the attribute
Daniel Veillardccb09631998-10-27 06:21:04 +0000902 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000903xmlAttrPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000904xmlNewDocProp(xmlDocPtr doc, const xmlChar *name, const xmlChar *value) {
Daniel Veillardccb09631998-10-27 06:21:04 +0000905 xmlAttrPtr cur;
906
907 if (name == NULL) {
908 fprintf(stderr, "xmlNewProp : name == NULL\n");
909 return(NULL);
910 }
911
912 /*
913 * Allocate a new property and fill the fields.
914 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000915 cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr));
Daniel Veillardccb09631998-10-27 06:21:04 +0000916 if (cur == NULL) {
917 fprintf(stderr, "xmlNewProp : malloc failed\n");
918 return(NULL);
919 }
920
921 cur->type = XML_ATTRIBUTE_NODE;
922 cur->node = NULL;
923 cur->name = xmlStrdup(name);
924 if (value != NULL)
925 cur->val = xmlStringGetNodeList(doc, value);
926 else
927 cur->val = NULL;
Daniel Veillard27d88741999-05-29 11:51:49 +0000928#ifndef XML_WITHOUT_CORBA
Daniel Veillardccb09631998-10-27 06:21:04 +0000929 cur->_private = NULL;
930 cur->vepv = NULL;
931#endif
932
933 cur->next = NULL;
934 return(cur);
935}
936
937/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000938 * xmlFreePropList:
939 * @cur: the first property in the list
940 *
941 * Free a property and all its siblings, all the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000942 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000943void
944xmlFreePropList(xmlAttrPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000945 xmlAttrPtr next;
946 if (cur == NULL) {
947 fprintf(stderr, "xmlFreePropList : property == NULL\n");
948 return;
949 }
950 while (cur != NULL) {
951 next = cur->next;
952 xmlFreeProp(cur);
953 cur = next;
954 }
955}
956
Daniel Veillard97b58771998-10-20 06:14:16 +0000957/**
958 * xmlFreeProp:
959 * @cur: the first property in the list
960 *
961 * Free one property, all the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000962 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000963void
964xmlFreeProp(xmlAttrPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000965 if (cur == NULL) {
966 fprintf(stderr, "xmlFreeProp : property == NULL\n");
967 return;
968 }
Daniel Veillard6454aec1999-09-02 22:04:43 +0000969 if (cur->name != NULL) xmlFree((char *) cur->name);
Daniel Veillardccb09631998-10-27 06:21:04 +0000970 if (cur->val != NULL) xmlFreeNodeList(cur->val);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000971 memset(cur, -1, sizeof(xmlAttr));
Daniel Veillard6454aec1999-09-02 22:04:43 +0000972 xmlFree(cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000973}
974
Daniel Veillard97b58771998-10-20 06:14:16 +0000975/**
Daniel Veillardb96e6431999-08-29 21:02:19 +0000976 * xmlNewPI:
977 * @name: the processing instruction name
978 * @content: the PI content
979 *
980 * Creation of a processing instruction element.
981 * Returns a pointer to the new node object.
982 */
983xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000984xmlNewPI(const xmlChar *name, const xmlChar *content) {
Daniel Veillardb96e6431999-08-29 21:02:19 +0000985 xmlNodePtr cur;
986
987 if (name == NULL) {
988 fprintf(stderr, "xmlNewPI : name == NULL\n");
989 return(NULL);
990 }
991
992 /*
993 * Allocate a new node and fill the fields.
994 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000995 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillardb96e6431999-08-29 21:02:19 +0000996 if (cur == NULL) {
997 fprintf(stderr, "xmlNewPI : malloc failed\n");
998 return(NULL);
999 }
1000
1001 cur->type = XML_PI_NODE;
1002 cur->doc = NULL;
1003 cur->parent = NULL;
1004 cur->next = NULL;
1005 cur->prev = NULL;
1006 cur->childs = NULL;
1007 cur->last = NULL;
1008 cur->properties = NULL;
1009 cur->name = xmlStrdup(name);
1010 cur->ns = NULL;
1011 cur->nsDef = NULL;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001012 if (content != NULL) {
1013#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardb96e6431999-08-29 21:02:19 +00001014 cur->content = xmlStrdup(content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001015#else
1016 cur->content = xmlBufferCreateSize(0);
1017 xmlBufferSetAllocationScheme(cur->content,
1018 xmlGetBufferAllocationScheme());
1019 xmlBufferAdd(cur->content, content, -1);
1020#endif
1021 } else
Daniel Veillardb96e6431999-08-29 21:02:19 +00001022 cur->content = NULL;
1023#ifndef XML_WITHOUT_CORBA
1024 cur->_private = NULL;
1025 cur->vepv = NULL;
1026#endif
1027 return(cur);
1028}
1029
1030/**
Daniel Veillard97b58771998-10-20 06:14:16 +00001031 * xmlNewNode:
1032 * @ns: namespace if any
1033 * @name: the node name
Daniel Veillard97b58771998-10-20 06:14:16 +00001034 *
1035 * Creation of a new node element. @ns and @content are optionnal (NULL).
Daniel Veillardccb09631998-10-27 06:21:04 +00001036 * If content is non NULL, a child list containing the TEXTs and
1037 * ENTITY_REFs node will be created.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001038 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001039 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001040xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001041xmlNewNode(xmlNsPtr ns, const xmlChar *name) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001042 xmlNodePtr cur;
1043
1044 if (name == NULL) {
1045 fprintf(stderr, "xmlNewNode : name == NULL\n");
1046 return(NULL);
1047 }
1048
1049 /*
1050 * Allocate a new node and fill the fields.
1051 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001052 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillard260a68f1998-08-13 03:39:55 +00001053 if (cur == NULL) {
1054 fprintf(stderr, "xmlNewNode : malloc failed\n");
1055 return(NULL);
1056 }
1057
Daniel Veillard33942841998-10-18 19:12:41 +00001058 cur->type = XML_ELEMENT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001059 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001060 cur->parent = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001061 cur->next = NULL;
1062 cur->prev = NULL;
1063 cur->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001064 cur->last = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001065 cur->properties = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001066 cur->name = xmlStrdup(name);
1067 cur->ns = ns;
1068 cur->nsDef = NULL;
Daniel Veillardccb09631998-10-27 06:21:04 +00001069 cur->content = NULL;
Daniel Veillard27d88741999-05-29 11:51:49 +00001070#ifndef XML_WITHOUT_CORBA
Daniel Veillard27fb0751998-10-17 06:47:46 +00001071 cur->_private = NULL;
1072 cur->vepv = NULL;
1073#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001074 return(cur);
1075}
1076
Daniel Veillard97b58771998-10-20 06:14:16 +00001077/**
1078 * xmlNewDocNode:
1079 * @doc: the document
1080 * @ns: namespace if any
1081 * @name: the node name
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001082 * @content: the XML text content if any
Daniel Veillard97b58771998-10-20 06:14:16 +00001083 *
1084 * Creation of a new node element within a document. @ns and @content
1085 * are optionnal (NULL).
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001086 * NOTE: @content is supposed to be a piece of XML CDATA, so it allow entities
1087 * references, but XML special chars need to be escaped first by using
1088 * xmlEncodeEntitiesReentrant(). Use xmlNewDocRawNode() if you don't
1089 * need entities support.
1090 *
Daniel Veillard1e346af1999-02-22 10:33:01 +00001091 * Returns a pointer to the new node object.
Daniel Veillard97b58771998-10-20 06:14:16 +00001092 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001093xmlNodePtr
1094xmlNewDocNode(xmlDocPtr doc, xmlNsPtr ns,
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001095 const xmlChar *name, const xmlChar *content) {
Daniel Veillard0bef1311998-10-14 02:36:47 +00001096 xmlNodePtr cur;
1097
Daniel Veillardccb09631998-10-27 06:21:04 +00001098 cur = xmlNewNode(ns, name);
1099 if (cur != NULL) {
1100 cur->doc = doc;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001101 if (content != NULL) {
Daniel Veillardccb09631998-10-27 06:21:04 +00001102 cur->childs = xmlStringGetNodeList(doc, content);
Daniel Veillard1e346af1999-02-22 10:33:01 +00001103 UPDATE_LAST_CHILD(cur)
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001104 }
Daniel Veillardccb09631998-10-27 06:21:04 +00001105 }
Daniel Veillard0bef1311998-10-14 02:36:47 +00001106 return(cur);
1107}
1108
1109
Daniel Veillard97b58771998-10-20 06:14:16 +00001110/**
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001111 * xmlNewDocRawNode:
1112 * @doc: the document
1113 * @ns: namespace if any
1114 * @name: the node name
1115 * @content: the text content if any
1116 *
1117 * Creation of a new node element within a document. @ns and @content
1118 * are optionnal (NULL).
1119 *
1120 * Returns a pointer to the new node object.
1121 */
1122xmlNodePtr
1123xmlNewDocRawNode(xmlDocPtr doc, xmlNsPtr ns,
1124 const xmlChar *name, const xmlChar *content) {
1125 xmlNodePtr cur;
1126
1127 cur = xmlNewNode(ns, name);
1128 if (cur != NULL) {
1129 cur->doc = doc;
1130 if (content != NULL) {
1131 cur->childs = xmlNewDocText(doc, content);
1132 UPDATE_LAST_CHILD(cur)
1133 }
1134 }
1135 return(cur);
1136}
1137
1138
1139/**
Daniel Veillard97b58771998-10-20 06:14:16 +00001140 * xmlNewText:
1141 * @content: the text content
1142 *
1143 * Creation of a new text node.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001144 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001145 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001146xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001147xmlNewText(const xmlChar *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001148 xmlNodePtr cur;
1149
1150 /*
1151 * Allocate a new node and fill the fields.
1152 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001153 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillard260a68f1998-08-13 03:39:55 +00001154 if (cur == NULL) {
1155 fprintf(stderr, "xmlNewText : malloc failed\n");
1156 return(NULL);
1157 }
1158
Daniel Veillard33942841998-10-18 19:12:41 +00001159 cur->type = XML_TEXT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001160 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001161 cur->parent = NULL;
1162 cur->next = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001163 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001164 cur->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001165 cur->last = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001166 cur->properties = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001167 cur->type = XML_TEXT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001168 cur->name = xmlStrdup(xmlStringText);
1169 cur->ns = NULL;
1170 cur->nsDef = NULL;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001171 if (content != NULL) {
1172#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard260a68f1998-08-13 03:39:55 +00001173 cur->content = xmlStrdup(content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001174#else
1175 cur->content = xmlBufferCreateSize(0);
1176 xmlBufferSetAllocationScheme(cur->content,
1177 xmlGetBufferAllocationScheme());
1178 xmlBufferAdd(cur->content, content, -1);
1179#endif
1180 } else
Daniel Veillard260a68f1998-08-13 03:39:55 +00001181 cur->content = NULL;
Daniel Veillard00fdf371999-10-08 09:40:39 +00001182#ifndef XML_WITHOUT_CORBA
1183 cur->_private = NULL;
1184 cur->vepv = NULL;
1185#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001186 return(cur);
1187}
1188
Daniel Veillard97b58771998-10-20 06:14:16 +00001189/**
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001190 * xmlNewTextChild:
1191 * @parent: the parent node
1192 * @ns: a namespace if any
1193 * @name: the name of the child
1194 * @content: the text content of the child if any.
1195 *
1196 * Creation of a new child element, added at the end of @parent childs list.
1197 * @ns and @content parameters are optionnal (NULL). If content is non NULL,
1198 * a child TEXT node will be created containing the string content.
1199 *
1200 * Returns a pointer to the new node object.
1201 */
1202xmlNodePtr
1203xmlNewTextChild(xmlNodePtr parent, xmlNsPtr ns,
1204 const xmlChar *name, const xmlChar *content) {
1205 xmlNodePtr cur, prev;
1206
1207 if (parent == NULL) {
1208 fprintf(stderr, "xmlNewTextChild : parent == NULL\n");
1209 return(NULL);
1210 }
1211
1212 if (name == NULL) {
1213 fprintf(stderr, "xmlNewTextChild : name == NULL\n");
1214 return(NULL);
1215 }
1216
1217 /*
1218 * Allocate a new node
1219 */
1220 if (ns == NULL)
1221 cur = xmlNewDocRawNode(parent->doc, parent->ns, name, content);
1222 else
1223 cur = xmlNewDocRawNode(parent->doc, ns, name, content);
1224 if (cur == NULL) return(NULL);
1225
1226 /*
1227 * add the new element at the end of the childs list.
1228 */
1229 cur->type = XML_ELEMENT_NODE;
1230 cur->parent = parent;
1231 cur->doc = parent->doc;
1232 if (parent->childs == NULL) {
1233 parent->childs = cur;
1234 parent->last = cur;
1235 } else {
1236 prev = parent->last;
1237 prev->next = cur;
1238 cur->prev = prev;
1239 parent->last = cur;
1240 }
1241
1242 return(cur);
1243}
1244
1245/**
Daniel Veillardccb09631998-10-27 06:21:04 +00001246 * xmlNewReference:
1247 * @doc: the document
1248 * @name: the reference name, or the reference string with & and ;
1249 *
1250 * Creation of a new reference node.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001251 * Returns a pointer to the new node object.
Daniel Veillardccb09631998-10-27 06:21:04 +00001252 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001253xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001254xmlNewReference(xmlDocPtr doc, const xmlChar *name) {
Daniel Veillardccb09631998-10-27 06:21:04 +00001255 xmlNodePtr cur;
1256 xmlEntityPtr ent;
1257
1258 /*
1259 * Allocate a new node and fill the fields.
1260 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001261 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillardccb09631998-10-27 06:21:04 +00001262 if (cur == NULL) {
1263 fprintf(stderr, "xmlNewText : malloc failed\n");
1264 return(NULL);
1265 }
1266
1267 cur->type = XML_ENTITY_REF_NODE;
Daniel Veillard10c6a8f1998-10-28 01:00:12 +00001268 cur->doc = doc;
Daniel Veillardccb09631998-10-27 06:21:04 +00001269 cur->parent = NULL;
1270 cur->next = NULL;
1271 cur->prev = NULL;
1272 cur->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001273 cur->last = NULL;
Daniel Veillardccb09631998-10-27 06:21:04 +00001274 cur->properties = NULL;
1275 if (name[0] == '&') {
1276 int len;
1277 name++;
1278 len = xmlStrlen(name);
1279 if (name[len - 1] == ';')
1280 cur->name = xmlStrndup(name, len - 1);
1281 else
1282 cur->name = xmlStrndup(name, len);
1283 } else
1284 cur->name = xmlStrdup(name);
1285 cur->ns = NULL;
1286 cur->nsDef = NULL;
1287
1288 ent = xmlGetDocEntity(doc, cur->name);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001289 if (ent != NULL) {
1290#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardccb09631998-10-27 06:21:04 +00001291 cur->content = ent->content;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001292#else
1293 /*
1294 * CJN 11.18.99 this might be a problem, since the xmlBuffer gets
1295 * a copy of this pointer. Let's hope we don't manipulate it
1296 * later
1297 */
1298 cur->content = xmlBufferCreateSize(0);
1299 xmlBufferSetAllocationScheme(cur->content,
1300 xmlGetBufferAllocationScheme());
1301 if (ent->content != NULL)
1302 xmlBufferAdd(cur->content, ent->content, -1);
1303#endif
1304 } else
Daniel Veillardccb09631998-10-27 06:21:04 +00001305 cur->content = NULL;
Daniel Veillard00fdf371999-10-08 09:40:39 +00001306#ifndef XML_WITHOUT_CORBA
1307 cur->_private = NULL;
1308 cur->vepv = NULL;
1309#endif
Daniel Veillardccb09631998-10-27 06:21:04 +00001310 return(cur);
1311}
1312
1313/**
Daniel Veillard97b58771998-10-20 06:14:16 +00001314 * xmlNewDocText:
1315 * @doc: the document
1316 * @content: the text content
1317 *
1318 * Creation of a new text node within a document.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001319 * Returns a pointer to the new node object.
Daniel Veillard97b58771998-10-20 06:14:16 +00001320 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001321xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001322xmlNewDocText(xmlDocPtr doc, const xmlChar *content) {
Daniel Veillard0bef1311998-10-14 02:36:47 +00001323 xmlNodePtr cur;
1324
1325 cur = xmlNewText(content);
1326 if (cur != NULL) cur->doc = doc;
1327 return(cur);
1328}
1329
Daniel Veillard97b58771998-10-20 06:14:16 +00001330/**
Daniel Veillardccb09631998-10-27 06:21:04 +00001331 * xmlNewTextLen:
Daniel Veillard97b58771998-10-20 06:14:16 +00001332 * @content: the text content
1333 * @len: the text len.
1334 *
1335 * Creation of a new text node with an extra parameter for the content's lenght
Daniel Veillard1e346af1999-02-22 10:33:01 +00001336 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001337 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001338xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001339xmlNewTextLen(const xmlChar *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001340 xmlNodePtr cur;
1341
1342 /*
1343 * Allocate a new node and fill the fields.
1344 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001345 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillard260a68f1998-08-13 03:39:55 +00001346 if (cur == NULL) {
1347 fprintf(stderr, "xmlNewText : malloc failed\n");
1348 return(NULL);
1349 }
1350
Daniel Veillard33942841998-10-18 19:12:41 +00001351 cur->type = XML_TEXT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001352 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001353 cur->parent = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001354 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001355 cur->next = NULL;
1356 cur->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001357 cur->last = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001358 cur->properties = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001359 cur->type = XML_TEXT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001360 cur->name = xmlStrdup(xmlStringText);
1361 cur->ns = NULL;
1362 cur->nsDef = NULL;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001363 if (content != NULL) {
1364#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard260a68f1998-08-13 03:39:55 +00001365 cur->content = xmlStrndup(content, len);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001366#else
1367 cur->content = xmlBufferCreateSize(len);
1368 xmlBufferSetAllocationScheme(cur->content,
1369 xmlGetBufferAllocationScheme());
1370 xmlBufferAdd(cur->content, content, len);
1371#endif
1372 } else
Daniel Veillard260a68f1998-08-13 03:39:55 +00001373 cur->content = NULL;
Daniel Veillard00fdf371999-10-08 09:40:39 +00001374#ifndef XML_WITHOUT_CORBA
1375 cur->_private = NULL;
1376 cur->vepv = NULL;
1377#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001378 return(cur);
1379}
1380
Daniel Veillard97b58771998-10-20 06:14:16 +00001381/**
1382 * xmlNewDocTextLen:
1383 * @doc: the document
1384 * @content: the text content
1385 * @len: the text len.
1386 *
1387 * Creation of a new text node with an extra content lenght parameter. The
1388 * text node pertain to a given document.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001389 * Returns a pointer to the new node object.
Daniel Veillard97b58771998-10-20 06:14:16 +00001390 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001391xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001392xmlNewDocTextLen(xmlDocPtr doc, const xmlChar *content, int len) {
Daniel Veillard0bef1311998-10-14 02:36:47 +00001393 xmlNodePtr cur;
1394
1395 cur = xmlNewTextLen(content, len);
1396 if (cur != NULL) cur->doc = doc;
1397 return(cur);
1398}
1399
Daniel Veillard97b58771998-10-20 06:14:16 +00001400/**
1401 * xmlNewComment:
1402 * @content: the comment content
1403 *
1404 * Creation of a new node containing a comment.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001405 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001406 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001407xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001408xmlNewComment(const xmlChar *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001409 xmlNodePtr cur;
1410
1411 /*
1412 * Allocate a new node and fill the fields.
1413 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001414 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillard260a68f1998-08-13 03:39:55 +00001415 if (cur == NULL) {
1416 fprintf(stderr, "xmlNewComment : malloc failed\n");
1417 return(NULL);
1418 }
1419
Daniel Veillard33942841998-10-18 19:12:41 +00001420 cur->type = XML_COMMENT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001421 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001422 cur->parent = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001423 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001424 cur->next = NULL;
1425 cur->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001426 cur->last = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001427 cur->properties = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001428 cur->type = XML_COMMENT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001429 cur->name = xmlStrdup(xmlStringText);
1430 cur->ns = NULL;
1431 cur->nsDef = NULL;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001432 if (content != NULL) {
1433#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard260a68f1998-08-13 03:39:55 +00001434 cur->content = xmlStrdup(content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001435#else
1436 cur->content = xmlBufferCreateSize(0);
1437 xmlBufferSetAllocationScheme(cur->content,
1438 xmlGetBufferAllocationScheme());
1439 xmlBufferAdd(cur->content, content, -1);
1440#endif
1441 } else
Daniel Veillard260a68f1998-08-13 03:39:55 +00001442 cur->content = NULL;
Daniel Veillard00fdf371999-10-08 09:40:39 +00001443#ifndef XML_WITHOUT_CORBA
1444 cur->_private = NULL;
1445 cur->vepv = NULL;
1446#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001447 return(cur);
1448}
1449
Daniel Veillard97b58771998-10-20 06:14:16 +00001450/**
Daniel Veillardb05deb71999-08-10 19:04:08 +00001451 * xmlNewCDataBlock:
1452 * @doc: the document
1453 * @content: the CData block content content
1454 * @len: the length of the block
1455 *
1456 * Creation of a new node containing a CData block.
1457 * Returns a pointer to the new node object.
1458 */
1459xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001460xmlNewCDataBlock(xmlDocPtr doc, const xmlChar *content, int len) {
Daniel Veillardb05deb71999-08-10 19:04:08 +00001461 xmlNodePtr cur;
1462
1463 /*
1464 * Allocate a new node and fill the fields.
1465 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001466 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillardb05deb71999-08-10 19:04:08 +00001467 if (cur == NULL) {
1468 fprintf(stderr, "xmlNewCDataBlock : malloc failed\n");
1469 return(NULL);
1470 }
1471
1472 cur->type = XML_CDATA_SECTION_NODE;
1473 cur->doc = NULL;
1474 cur->parent = NULL;
1475 cur->prev = NULL;
1476 cur->next = NULL;
1477 cur->childs = NULL;
1478 cur->last = NULL;
1479 cur->properties = NULL;
1480 cur->name = xmlStrdup(xmlStringText);
1481 cur->ns = NULL;
1482 cur->nsDef = NULL;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001483 if (content != NULL) {
1484#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardb05deb71999-08-10 19:04:08 +00001485 cur->content = xmlStrndup(content, len);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001486#else
1487 cur->content = xmlBufferCreateSize(len);
1488 xmlBufferSetAllocationScheme(cur->content,
1489 xmlGetBufferAllocationScheme());
1490 xmlBufferAdd(cur->content, content, len);
1491#endif
Daniel Veillardb05deb71999-08-10 19:04:08 +00001492 } else
1493 cur->content = NULL;
Daniel Veillard00fdf371999-10-08 09:40:39 +00001494#ifndef XML_WITHOUT_CORBA
1495 cur->_private = NULL;
1496 cur->vepv = NULL;
1497#endif
Daniel Veillardb05deb71999-08-10 19:04:08 +00001498 return(cur);
1499}
1500
1501/**
Daniel Veillard1e346af1999-02-22 10:33:01 +00001502 * xmlNewDocComment:
Daniel Veillard97b58771998-10-20 06:14:16 +00001503 * @doc: the document
1504 * @content: the comment content
1505 *
1506 * Creation of a new node containing a commentwithin a document.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001507 * Returns a pointer to the new node object.
Daniel Veillard97b58771998-10-20 06:14:16 +00001508 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001509xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001510xmlNewDocComment(xmlDocPtr doc, const xmlChar *content) {
Daniel Veillard0bef1311998-10-14 02:36:47 +00001511 xmlNodePtr cur;
1512
1513 cur = xmlNewComment(content);
1514 if (cur != NULL) cur->doc = doc;
1515 return(cur);
1516}
1517
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001518
Daniel Veillard97b58771998-10-20 06:14:16 +00001519/**
1520 * xmlNewChild:
1521 * @parent: the parent node
1522 * @ns: a namespace if any
1523 * @name: the name of the child
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001524 * @content: the XML content of the child if any.
Daniel Veillard97b58771998-10-20 06:14:16 +00001525 *
Daniel Veillard97b58771998-10-20 06:14:16 +00001526 * Creation of a new child element, added at the end of @parent childs list.
Daniel Veillardccb09631998-10-27 06:21:04 +00001527 * @ns and @content parameters are optionnal (NULL). If content is non NULL,
1528 * a child list containing the TEXTs and ENTITY_REFs node will be created.
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001529 * NOTE: @content is supposed to be a piece of XML CDATA, so it allow entities
1530 * references, but XML special chars need to be escaped first by using
1531 * xmlEncodeEntitiesReentrant(). Use xmlNewTextChild() if entities
1532 * support is not needed.
1533 *
Daniel Veillard1e346af1999-02-22 10:33:01 +00001534 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001535 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001536xmlNodePtr
1537xmlNewChild(xmlNodePtr parent, xmlNsPtr ns,
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001538 const xmlChar *name, const xmlChar *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001539 xmlNodePtr cur, prev;
1540
1541 if (parent == NULL) {
1542 fprintf(stderr, "xmlNewChild : parent == NULL\n");
1543 return(NULL);
1544 }
1545
1546 if (name == NULL) {
1547 fprintf(stderr, "xmlNewChild : name == NULL\n");
1548 return(NULL);
1549 }
1550
1551 /*
1552 * Allocate a new node
1553 */
1554 if (ns == NULL)
Daniel Veillardccb09631998-10-27 06:21:04 +00001555 cur = xmlNewDocNode(parent->doc, parent->ns, name, content);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001556 else
Daniel Veillardccb09631998-10-27 06:21:04 +00001557 cur = xmlNewDocNode(parent->doc, ns, name, content);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001558 if (cur == NULL) return(NULL);
1559
1560 /*
1561 * add the new element at the end of the childs list.
1562 */
Daniel Veillardccb09631998-10-27 06:21:04 +00001563 cur->type = XML_ELEMENT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001564 cur->parent = parent;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001565 cur->doc = parent->doc;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001566 if (parent->childs == NULL) {
1567 parent->childs = cur;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001568 parent->last = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001569 } else {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001570 prev = parent->last;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001571 prev->next = cur;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001572 cur->prev = prev;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001573 parent->last = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001574 }
1575
1576 return(cur);
1577}
1578
Daniel Veillard97b58771998-10-20 06:14:16 +00001579/**
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00001580 * xmlAddNextSibling:
1581 * @cur: the child node
1582 * @elem: the new node
1583 *
1584 * Add a new element @elem as the next siblings of @cur
1585 * If the new element was already inserted in a document it is
1586 * first unlinked from its existing context.
1587 *
1588 * Returns the new element or NULL in case of error.
1589 */
1590xmlNodePtr
1591xmlAddNextSibling(xmlNodePtr cur, xmlNodePtr elem) {
1592 if (cur == NULL) {
1593 fprintf(stderr, "xmlAddNextSibling : cur == NULL\n");
1594 return(NULL);
1595 }
1596 if (elem == NULL) {
1597 fprintf(stderr, "xmlAddNextSibling : elem == NULL\n");
1598 return(NULL);
1599 }
1600
1601 xmlUnlinkNode(elem);
1602 elem->doc = cur->doc;
1603 elem->parent = cur->parent;
1604 elem->next = cur;
1605 elem->prev = cur->prev;
1606 cur->prev = elem;
1607 if (elem->prev != NULL)
1608 elem->prev->next = elem;
1609 if ((elem->parent != NULL) && (elem->parent->childs == cur))
1610 elem->parent->childs = elem;
1611 return(elem);
1612}
1613
1614/**
1615 * xmlAddPrevSibling:
1616 * @cur: the child node
1617 * @elem: the new node
1618 *
1619 * Add a new element @elem as the previous siblings of @cur
1620 * If the new element was already inserted in a document it is
1621 * first unlinked from its existing context.
1622 *
1623 * Returns the new element or NULL in case of error.
1624 */
1625xmlNodePtr
1626xmlAddPrevSibling(xmlNodePtr cur, xmlNodePtr elem) {
1627 if (cur == NULL) {
1628 fprintf(stderr, "xmlAddPrevSibling : cur == NULL\n");
1629 return(NULL);
1630 }
1631 if (elem == NULL) {
1632 fprintf(stderr, "xmlAddPrevSibling : elem == NULL\n");
1633 return(NULL);
1634 }
1635
1636 xmlUnlinkNode(elem);
1637 elem->doc = cur->doc;
1638 elem->parent = cur->parent;
1639 elem->prev = cur;
1640 elem->next = cur->next;
1641 cur->next = elem;
1642 if (elem->next != NULL)
1643 elem->next->prev = elem;
1644 if ((elem->parent != NULL) && (elem->parent->last == cur))
1645 elem->parent->last = elem;
1646 return(elem);
1647}
1648
1649/**
Daniel Veillardb96e6431999-08-29 21:02:19 +00001650 * xmlAddSibling:
1651 * @cur: the child node
1652 * @elem: the new node
1653 *
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00001654 * Add a new element @elem to the list of siblings of @cur
1655 * If the new element was already inserted in a document it is
1656 * first unlinked from its existing context.
1657 *
1658 * Returns the new element or NULL in case of error.
Daniel Veillardb96e6431999-08-29 21:02:19 +00001659 */
1660xmlNodePtr
1661xmlAddSibling(xmlNodePtr cur, xmlNodePtr elem) {
1662 xmlNodePtr parent;
1663
1664 if (cur == NULL) {
1665 fprintf(stderr, "xmlAddSibling : cur == NULL\n");
1666 return(NULL);
1667 }
1668
1669 if (elem == NULL) {
1670 fprintf(stderr, "xmlAddSibling : elem == NULL\n");
1671 return(NULL);
1672 }
1673
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00001674 /*
1675 * Constant time is we can rely on the ->parent->last to find
1676 * the last sibling.
1677 */
1678 if ((cur->parent != NULL) &&
1679 (cur->parent->childs != NULL) &&
1680 (cur->parent->last != NULL) &&
1681 (cur->parent->last->next == NULL)) {
1682 cur = cur->parent->last;
1683 } else {
1684 while (cur->next != NULL) cur = cur->next;
Daniel Veillardb96e6431999-08-29 21:02:19 +00001685 }
1686
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00001687 xmlUnlinkNode(elem);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001688 if (elem->doc == NULL)
1689 elem->doc = cur->doc; /* the parent may not be linked to a doc ! */
1690
1691 parent = cur->parent;
1692 elem->prev = cur;
1693 elem->next = NULL;
1694 elem->parent = parent;
1695 cur->next = elem;
1696 if (parent != NULL)
1697 parent->last = elem;
1698
1699 return(elem);
1700}
1701
1702/**
Daniel Veillard97b58771998-10-20 06:14:16 +00001703 * xmlAddChild:
1704 * @parent: the parent node
1705 * @cur: the child node
1706 *
1707 * Add a new child element, to @parent, at the end of the child list.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001708 * Returns the child or NULL in case of error.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001709 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001710xmlNodePtr
1711xmlAddChild(xmlNodePtr parent, xmlNodePtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001712 xmlNodePtr prev;
1713
1714 if (parent == NULL) {
Daniel Veillard10a2c651999-12-12 13:03:50 +00001715 fprintf(stderr, "xmlAddChild : parent == NULL\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00001716 return(NULL);
1717 }
1718
1719 if (cur == NULL) {
Daniel Veillard10a2c651999-12-12 13:03:50 +00001720 fprintf(stderr, "xmlAddChild : child == NULL\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00001721 return(NULL);
1722 }
1723
Daniel Veillard0bef1311998-10-14 02:36:47 +00001724 if ((cur->doc != NULL) && (parent->doc != NULL) &&
1725 (cur->doc != parent->doc)) {
1726 fprintf(stderr, "Elements moved to a different document\n");
1727 }
1728
Daniel Veillard260a68f1998-08-13 03:39:55 +00001729 /*
1730 * add the new element at the end of the childs list.
1731 */
1732 cur->parent = parent;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001733 cur->doc = parent->doc; /* the parent may not be linked to a doc ! */
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001734
Daniel Veillardccb09631998-10-27 06:21:04 +00001735 /*
1736 * Handle the case where parent->content != NULL, in that case it will
1737 * create a intermediate TEXT node.
1738 */
1739 if (parent->content != NULL) {
1740 xmlNodePtr text;
1741
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001742#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardccb09631998-10-27 06:21:04 +00001743 text = xmlNewDocText(parent->doc, parent->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001744#else
1745 text = xmlNewDocText(parent->doc, xmlBufferContent(parent->content));
1746#endif
Daniel Veillardccb09631998-10-27 06:21:04 +00001747 if (text != NULL) {
1748 text->next = parent->childs;
1749 if (text->next != NULL)
1750 text->next->prev = text;
1751 parent->childs = text;
Daniel Veillard1e346af1999-02-22 10:33:01 +00001752 UPDATE_LAST_CHILD(parent)
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001753#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard6454aec1999-09-02 22:04:43 +00001754 xmlFree(parent->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001755#else
1756 xmlBufferFree(parent->content);
1757#endif
Daniel Veillardccb09631998-10-27 06:21:04 +00001758 parent->content = NULL;
1759 }
1760 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00001761 if (parent->childs == NULL) {
1762 parent->childs = cur;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001763 parent->last = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001764 } else {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001765 prev = parent->last;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001766 prev->next = cur;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001767 cur->prev = prev;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001768 parent->last = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001769 }
1770
1771 return(cur);
1772}
1773
Daniel Veillard97b58771998-10-20 06:14:16 +00001774/**
1775 * xmlGetLastChild:
1776 * @parent: the parent node
1777 *
1778 * Search the last child of a node.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001779 * Returns the last child or NULL if none.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001780 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001781xmlNodePtr
1782xmlGetLastChild(xmlNodePtr parent) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001783 if (parent == NULL) {
1784 fprintf(stderr, "xmlGetLastChild : parent == NULL\n");
1785 return(NULL);
1786 }
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001787 return(parent->last);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001788}
1789
Daniel Veillard97b58771998-10-20 06:14:16 +00001790/**
1791 * xmlFreeNodeList:
1792 * @cur: the first node in the list
1793 *
1794 * Free a node and all its siblings, this is a recursive behaviour, all
1795 * the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001796 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001797void
1798xmlFreeNodeList(xmlNodePtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001799 xmlNodePtr next;
1800 if (cur == NULL) {
1801 fprintf(stderr, "xmlFreeNodeList : node == NULL\n");
1802 return;
1803 }
1804 while (cur != NULL) {
1805 next = cur->next;
1806 xmlFreeNode(cur);
1807 cur = next;
1808 }
1809}
1810
Daniel Veillard97b58771998-10-20 06:14:16 +00001811/**
1812 * xmlFreeNode:
1813 * @cur: the node
1814 *
1815 * Free a node, this is a recursive behaviour, all the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001816 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001817void
1818xmlFreeNode(xmlNodePtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001819 if (cur == NULL) {
1820 fprintf(stderr, "xmlFreeNode : node == NULL\n");
1821 return;
1822 }
Daniel Veillardccb09631998-10-27 06:21:04 +00001823 cur->doc = NULL;
1824 cur->parent = NULL;
1825 cur->next = NULL;
1826 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001827 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillardccb09631998-10-27 06:21:04 +00001828 if (cur->properties != NULL) xmlFreePropList(cur->properties);
1829 if (cur->type != XML_ENTITY_REF_NODE)
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001830#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard6454aec1999-09-02 22:04:43 +00001831 if (cur->content != NULL) xmlFree(cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001832#else
1833 if (cur->content != NULL) xmlBufferFree(cur->content);
1834#endif
Daniel Veillard6454aec1999-09-02 22:04:43 +00001835 if (cur->name != NULL) xmlFree((char *) cur->name);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001836 if (cur->nsDef != NULL) xmlFreeNsList(cur->nsDef);
1837 memset(cur, -1, sizeof(xmlNode));
Daniel Veillard6454aec1999-09-02 22:04:43 +00001838 xmlFree(cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001839}
1840
Daniel Veillard16253641998-10-28 22:58:05 +00001841/**
1842 * xmlUnlinkNode:
1843 * @cur: the node
1844 *
1845 * Unlink a node from it's current context, the node is not freed
1846 */
1847void
1848xmlUnlinkNode(xmlNodePtr cur) {
1849 if (cur == NULL) {
1850 fprintf(stderr, "xmlUnlinkNode : node == NULL\n");
1851 return;
1852 }
1853 if ((cur->parent != NULL) && (cur->parent->childs == cur))
1854 cur->parent->childs = cur->next;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001855 if ((cur->parent != NULL) && (cur->parent->last == cur))
1856 cur->parent->last = cur->prev;
Daniel Veillard16253641998-10-28 22:58:05 +00001857 if (cur->next != NULL)
1858 cur->next->prev = cur->prev;
1859 if (cur->prev != NULL)
1860 cur->prev->next = cur->next;
1861 cur->next = cur->prev = NULL;
1862 cur->parent = NULL;
1863}
1864
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00001865/**
1866 * xmlReplaceNode:
1867 * @old: the old node
1868 * @cur: the node
1869 *
1870 * Unlink the old node from it's current context, prune the new one
1871 * at the same place. If cur was already inserted in a document it is
1872 * first unlinked from its existing context.
1873 *
1874 * Returns the old node
1875 */
1876xmlNodePtr
1877xmlReplaceNode(xmlNodePtr old, xmlNodePtr cur) {
1878 if (old == NULL) {
1879 fprintf(stderr, "xmlReplaceNode : old == NULL\n");
1880 return(NULL);
1881 }
1882 if (cur == NULL) {
1883 xmlUnlinkNode(old);
1884 return(old);
1885 }
1886 xmlUnlinkNode(cur);
1887 cur->doc = old->doc;
1888 cur->parent = old->parent;
1889 cur->next = old->next;
1890 if (cur->next != NULL)
1891 cur->next->prev = cur;
1892 cur->prev = old->prev;
1893 if (cur->prev != NULL)
1894 cur->prev->next = cur;
1895 if (cur->parent != NULL) {
1896 if (cur->parent->childs == old)
1897 cur->parent->childs = cur;
1898 if (cur->parent->last == old)
1899 cur->parent->last = cur;
1900 }
1901 old->next = old->prev = NULL;
1902 old->parent = NULL;
1903 return(old);
1904}
1905
Daniel Veillard260a68f1998-08-13 03:39:55 +00001906/************************************************************************
1907 * *
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001908 * Copy operations *
1909 * *
1910 ************************************************************************/
1911
1912/**
1913 * xmlCopyNamespace:
1914 * @cur: the namespace
1915 *
1916 * Do a copy of the namespace.
1917 *
1918 * Returns: a new xmlNsPtr, or NULL in case of error.
1919 */
1920xmlNsPtr
1921xmlCopyNamespace(xmlNsPtr cur) {
1922 xmlNsPtr ret;
1923
1924 if (cur == NULL) return(NULL);
1925 switch (cur->type) {
1926 case XML_GLOBAL_NAMESPACE:
1927 ret = xmlNewGlobalNs(NULL, cur->href, cur->prefix);
1928 break;
1929 case XML_LOCAL_NAMESPACE:
1930 ret = xmlNewNs(NULL, cur->href, cur->prefix);
1931 break;
1932 default:
1933 fprintf(stderr, "xmlCopyNamespace: unknown type %d\n", cur->type);
1934 return(NULL);
1935 }
1936 return(ret);
1937}
1938
1939/**
1940 * xmlCopyNamespaceList:
1941 * @cur: the first namespace
1942 *
1943 * Do a copy of an namespace list.
1944 *
1945 * Returns: a new xmlNsPtr, or NULL in case of error.
1946 */
1947xmlNsPtr
1948xmlCopyNamespaceList(xmlNsPtr cur) {
1949 xmlNsPtr ret = NULL;
1950 xmlNsPtr p = NULL,q;
1951
1952 while (cur != NULL) {
1953 q = xmlCopyNamespace(cur);
1954 if (p == NULL) {
1955 ret = p = q;
1956 } else {
1957 p->next = q;
1958 p = q;
1959 }
1960 cur = cur->next;
1961 }
1962 return(ret);
1963}
1964
1965/**
1966 * xmlCopyProp:
Daniel Veillardb96e6431999-08-29 21:02:19 +00001967 * @target: the element where the attribute will be grafted
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001968 * @cur: the attribute
1969 *
1970 * Do a copy of the attribute.
1971 *
1972 * Returns: a new xmlAttrPtr, or NULL in case of error.
1973 */
1974xmlAttrPtr
Daniel Veillardb96e6431999-08-29 21:02:19 +00001975xmlCopyProp(xmlNodePtr target, xmlAttrPtr cur) {
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001976 xmlAttrPtr ret;
1977
1978 if (cur == NULL) return(NULL);
1979 if (cur->val != NULL)
1980 ret = xmlNewDocProp(cur->val->doc, cur->name, NULL);
1981 else
1982 ret = xmlNewDocProp(NULL, cur->name, NULL);
1983 if (ret == NULL) return(NULL);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001984
1985 if ((cur->ns != NULL) && (target != NULL)) {
1986 xmlNsPtr ns;
1987
1988 ns = xmlSearchNs(target->doc, target, cur->ns->prefix);
1989 ret->ns = ns;
1990 } else
1991 ret->ns = NULL;
1992
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001993 if (cur->val != NULL)
1994 ret->val = xmlCopyNodeList(cur->val);
1995 return(ret);
1996}
1997
1998/**
1999 * xmlCopyPropList:
Daniel Veillardb96e6431999-08-29 21:02:19 +00002000 * @target: the element where the attributes will be grafted
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002001 * @cur: the first attribute
2002 *
2003 * Do a copy of an attribute list.
2004 *
2005 * Returns: a new xmlAttrPtr, or NULL in case of error.
2006 */
2007xmlAttrPtr
Daniel Veillardb96e6431999-08-29 21:02:19 +00002008xmlCopyPropList(xmlNodePtr target, xmlAttrPtr cur) {
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002009 xmlAttrPtr ret = NULL;
2010 xmlAttrPtr p = NULL,q;
2011
2012 while (cur != NULL) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00002013 q = xmlCopyProp(target, cur);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002014 if (p == NULL) {
2015 ret = p = q;
2016 } else {
2017 p->next = q;
2018 p = q;
2019 }
2020 cur = cur->next;
2021 }
2022 return(ret);
2023}
2024
2025/*
Daniel Veillard11a48ec1999-11-23 10:40:46 +00002026 * NOTE abeut the CopyNode operations !
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002027 *
2028 * They are splitted into external and internal parts for one
2029 * tricky reason: namespaces. Doing a direct copy of a node
2030 * say RPM:Copyright without changing the namespace pointer to
2031 * something else can produce stale links. One way to do it is
2032 * to keep a reference counter but this doesn't work as soon
2033 * as one move the element or the subtree out of the scope of
2034 * the existing namespace. The actual solution seems to add
2035 * a copy of the namespace at the top of the copied tree if
2036 * not available in the subtree.
2037 * Hence two functions, the public front-end call the inner ones
2038 */
2039
2040static xmlNodePtr
2041xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent);
2042
2043static xmlNodePtr
2044xmlStaticCopyNode(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent,
2045 int recursive) {
2046 xmlNodePtr ret;
2047
2048 if (node == NULL) return(NULL);
2049 /*
2050 * Allocate a new node and fill the fields.
2051 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00002052 ret = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002053 if (ret == NULL) {
2054 fprintf(stderr, "xmlStaticCopyNode : malloc failed\n");
2055 return(NULL);
2056 }
2057
2058 ret->type = node->type;
2059 ret->doc = doc;
2060 ret->parent = parent;
2061 ret->next = NULL;
2062 ret->prev = NULL;
2063 ret->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002064 ret->last = NULL;
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002065 ret->properties = NULL;
2066 if (node->name != NULL)
2067 ret->name = xmlStrdup(node->name);
2068 else
2069 ret->name = NULL;
2070 ret->ns = NULL;
2071 ret->nsDef = NULL;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002072 if ((node->content != NULL) && (node->type != XML_ENTITY_REF_NODE)) {
2073#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002074 ret->content = xmlStrdup(node->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002075#else
2076 ret->content = xmlBufferCreateSize(xmlBufferLength(node->content));
2077 xmlBufferSetAllocationScheme(ret->content,
2078 xmlGetBufferAllocationScheme());
2079 xmlBufferAdd(ret->content,
2080 xmlBufferContent(node->content),
2081 xmlBufferLength(node->content));
2082#endif
2083 } else
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002084 ret->content = NULL;
Daniel Veillard27d88741999-05-29 11:51:49 +00002085#ifndef XML_WITHOUT_CORBA
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002086 ret->_private = NULL;
2087 ret->vepv = NULL;
2088#endif
2089 if (parent != NULL)
2090 xmlAddChild(parent, ret);
2091
2092 if (!recursive) return(ret);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002093 if (node->nsDef != NULL)
2094 ret->nsDef = xmlCopyNamespaceList(node->nsDef);
2095
2096 if (node->ns != NULL) {
2097 xmlNsPtr ns;
2098
2099 ns = xmlSearchNs(doc, ret, node->ns->prefix);
2100 if (ns == NULL) {
2101 /*
2102 * Humm, we are copying an element whose namespace is defined
2103 * out of the new tree scope. Search it in the original tree
2104 * and add it at the top of the new tree
2105 */
2106 ns = xmlSearchNs(node->doc, node, node->ns->prefix);
2107 if (ns != NULL) {
2108 xmlNodePtr root = ret;
2109
2110 while (root->parent != NULL) root = root->parent;
2111 xmlNewNs(root, ns->href, ns->prefix);
2112 }
2113 } else {
2114 /*
2115 * reference the existing namespace definition in our own tree.
2116 */
2117 ret->ns = ns;
2118 }
2119 }
Daniel Veillardb96e6431999-08-29 21:02:19 +00002120 if (node->properties != NULL)
2121 ret->properties = xmlCopyPropList(ret, node->properties);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002122 if (node->childs != NULL)
2123 ret->childs = xmlStaticCopyNodeList(node->childs, doc, ret);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002124 UPDATE_LAST_CHILD(ret)
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002125 return(ret);
2126}
2127
2128static xmlNodePtr
2129xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent) {
2130 xmlNodePtr ret = NULL;
2131 xmlNodePtr p = NULL,q;
2132
2133 while (node != NULL) {
2134 q = xmlStaticCopyNode(node, doc, parent, 1);
2135 if (parent == NULL) {
2136 if (ret == NULL) ret = q;
2137 } else {
2138 if (ret == NULL) {
2139 q->prev = NULL;
2140 ret = p = q;
2141 } else {
2142 p->next = q;
2143 q->prev = p;
2144 p = q;
2145 }
2146 }
2147 node = node->next;
2148 }
2149 return(ret);
2150}
2151
2152/**
2153 * xmlCopyNode:
2154 * @node: the node
2155 * @recursive: if 1 do a recursive copy.
2156 *
2157 * Do a copy of the node.
2158 *
2159 * Returns: a new xmlNodePtr, or NULL in case of error.
2160 */
2161xmlNodePtr
2162xmlCopyNode(xmlNodePtr node, int recursive) {
2163 xmlNodePtr ret;
2164
2165 ret = xmlStaticCopyNode(node, NULL, NULL, recursive);
2166 return(ret);
2167}
2168
2169/**
2170 * xmlCopyNodeList:
2171 * @node: the first node in the list.
2172 *
2173 * Do a recursive copy of the node list.
2174 *
2175 * Returns: a new xmlNodePtr, or NULL in case of error.
2176 */
2177xmlNodePtr xmlCopyNodeList(xmlNodePtr node) {
2178 xmlNodePtr ret = xmlStaticCopyNodeList(node, NULL, NULL);
2179 return(ret);
2180}
2181
2182/**
2183 * xmlCopyElement:
2184 * @elem: the element
2185 *
2186 * Do a copy of the element definition.
2187 *
2188 * Returns: a new xmlElementPtr, or NULL in case of error.
2189xmlElementPtr
2190xmlCopyElement(xmlElementPtr elem) {
2191 xmlElementPtr ret;
2192
2193 if (elem == NULL) return(NULL);
2194 ret = xmlNewDocElement(elem->doc, elem->ns, elem->name, elem->content);
2195 if (ret == NULL) return(NULL);
2196 if (!recursive) return(ret);
2197 if (elem->properties != NULL)
2198 ret->properties = xmlCopyPropList(elem->properties);
2199
2200 if (elem->nsDef != NULL)
2201 ret->nsDef = xmlCopyNamespaceList(elem->nsDef);
2202 if (elem->childs != NULL)
2203 ret->childs = xmlCopyElementList(elem->childs);
2204 return(ret);
2205}
2206 */
2207
2208/**
2209 * xmlCopyDtd:
2210 * @dtd: the dtd
2211 *
2212 * Do a copy of the dtd.
2213 *
2214 * Returns: a new xmlDtdPtr, or NULL in case of error.
2215 */
2216xmlDtdPtr
2217xmlCopyDtd(xmlDtdPtr dtd) {
2218 xmlDtdPtr ret;
2219
2220 if (dtd == NULL) return(NULL);
2221 ret = xmlNewDtd(NULL, dtd->name, dtd->ExternalID, dtd->SystemID);
2222 if (ret == NULL) return(NULL);
2223 if (dtd->entities != NULL)
2224 ret->entities = (void *) xmlCopyEntitiesTable(
2225 (xmlEntitiesTablePtr) dtd->entities);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002226 if (dtd->notations != NULL)
2227 ret->notations = (void *) xmlCopyNotationTable(
2228 (xmlNotationTablePtr) dtd->notations);
2229 if (dtd->elements != NULL)
2230 ret->elements = (void *) xmlCopyElementTable(
2231 (xmlElementTablePtr) dtd->elements);
2232 if (dtd->attributes != NULL)
2233 ret->attributes = (void *) xmlCopyAttributeTable(
2234 (xmlAttributeTablePtr) dtd->attributes);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002235 return(ret);
2236}
2237
2238/**
2239 * xmlCopyDoc:
2240 * @doc: the document
2241 * @recursive: if 1 do a recursive copy.
2242 *
2243 * Do a copy of the document info. If recursive, the content tree will
2244 * be copied too as well as Dtd, namespaces and entities.
2245 *
2246 * Returns: a new xmlDocPtr, or NULL in case of error.
2247 */
2248xmlDocPtr
2249xmlCopyDoc(xmlDocPtr doc, int recursive) {
2250 xmlDocPtr ret;
2251
2252 if (doc == NULL) return(NULL);
2253 ret = xmlNewDoc(doc->version);
2254 if (ret == NULL) return(NULL);
2255 if (doc->name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +00002256 ret->name = xmlMemStrdup(doc->name);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002257 if (doc->encoding != NULL)
2258 ret->encoding = xmlStrdup(doc->encoding);
2259 ret->compression = doc->compression;
2260 ret->standalone = doc->standalone;
2261 if (!recursive) return(ret);
2262
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002263 if (doc->intSubset != NULL)
2264 ret->intSubset = xmlCopyDtd(doc->intSubset);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002265 if (doc->oldNs != NULL)
2266 ret->oldNs = xmlCopyNamespaceList(doc->oldNs);
2267 if (doc->root != NULL)
2268 ret->root = xmlStaticCopyNodeList(doc->root, ret, NULL);
2269 return(ret);
2270}
2271
2272/************************************************************************
2273 * *
Daniel Veillard260a68f1998-08-13 03:39:55 +00002274 * Content access functions *
2275 * *
2276 ************************************************************************/
2277
Daniel Veillard97b58771998-10-20 06:14:16 +00002278/**
Daniel Veillard944b5ff1999-12-15 19:08:24 +00002279 * xmlDocGetRootElement:
2280 * @doc: the document
2281 *
2282 * Get the root element of the document (doc->root is a list
2283 * containing possibly comments, PIs, etc ...).
2284 *
2285 * Returns the xmlNodePtr for the root or NULL
2286 */
2287xmlNodePtr
2288xmlDocGetRootElement(xmlDocPtr doc) {
2289 xmlNodePtr ret;
2290
2291 if (doc == NULL) return(NULL);
2292 ret = doc->root;
2293 while (ret != NULL) {
2294 if (ret->type == XML_ELEMENT_NODE)
2295 return(ret);
2296 ret = ret->next;
2297 }
2298 return(ret);
2299}
2300
2301/**
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00002302 * xmlDocSetRootElement:
2303 * @doc: the document
2304 * @root: the new document root element
2305 *
2306 * Set the root element of the document (doc->root is a list
2307 * containing possibly comments, PIs, etc ...).
2308 *
2309 * Returns the old root element if any was found
2310 */
2311xmlNodePtr
2312xmlDocSetRootElement(xmlDocPtr doc, xmlNodePtr root) {
2313 xmlNodePtr old = NULL;
2314
2315 if (doc == NULL) return(NULL);
2316 old = doc->root;
2317 while (old != NULL) {
2318 if (old->type == XML_ELEMENT_NODE)
2319 break;
2320 old = old->next;
2321 }
2322 if (old == NULL) {
2323 if (doc->root == NULL) {
2324 doc->root = root;
2325 } else {
2326 xmlAddSibling(doc->root, root);
2327 }
2328 } else {
2329 xmlReplaceNode(old, root);
2330 }
2331 return(old);
2332}
2333
2334/**
Daniel Veillardb96e6431999-08-29 21:02:19 +00002335 * xmlNodeSetLang:
2336 * @cur: the node being changed
2337 * @lang: the langage description
2338 *
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00002339 * Set the language of a node, i.e. the values of the xml:lang
2340 * attribute.
Daniel Veillardb96e6431999-08-29 21:02:19 +00002341 */
2342void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002343xmlNodeSetLang(xmlNodePtr cur, const xmlChar *lang) {
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00002344 if (cur == NULL) return;
2345 switch(cur->type) {
2346 case XML_TEXT_NODE:
2347 case XML_CDATA_SECTION_NODE:
2348 case XML_COMMENT_NODE:
2349 case XML_DOCUMENT_NODE:
2350 case XML_DOCUMENT_TYPE_NODE:
2351 case XML_DOCUMENT_FRAG_NODE:
2352 case XML_NOTATION_NODE:
2353 case XML_HTML_DOCUMENT_NODE:
2354 return;
2355 case XML_ELEMENT_NODE:
2356 case XML_ATTRIBUTE_NODE:
2357 case XML_PI_NODE:
2358 case XML_ENTITY_REF_NODE:
2359 case XML_ENTITY_NODE:
2360 break;
2361 }
Daniel Veillardb96e6431999-08-29 21:02:19 +00002362 xmlSetProp(cur, BAD_CAST "xml:lang", lang);
2363}
2364
2365/**
2366 * xmlNodeGetLang:
2367 * @cur: the node being checked
2368 *
2369 * Searches the language of a node, i.e. the values of the xml:lang
2370 * attribute or the one carried by the nearest ancestor.
2371 *
2372 * Returns a pointer to the lang value, or NULL if not found
Daniel Veillarda819dac1999-11-24 18:04:22 +00002373 * It's up to the caller to free the memory.
Daniel Veillardb96e6431999-08-29 21:02:19 +00002374 */
Daniel Veillarda819dac1999-11-24 18:04:22 +00002375xmlChar *
Daniel Veillardb96e6431999-08-29 21:02:19 +00002376xmlNodeGetLang(xmlNodePtr cur) {
Daniel Veillarda819dac1999-11-24 18:04:22 +00002377 xmlChar *lang;
Daniel Veillardb96e6431999-08-29 21:02:19 +00002378
2379 while (cur != NULL) {
2380 lang = xmlGetProp(cur, BAD_CAST "xml:lang");
2381 if (lang != NULL)
2382 return(lang);
2383 cur = cur->parent;
2384 }
2385 return(NULL);
2386}
2387
2388/**
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00002389 * xmlNodeSetName:
2390 * @cur: the node being changed
2391 * @name: the new tag name
2392 *
2393 * Searches the language of a node, i.e. the values of the xml:lang
2394 * attribute or the one carried by the nearest ancestor.
2395 */
2396void
2397xmlNodeSetName(xmlNodePtr cur, const xmlChar *name) {
2398 if (cur == NULL) return;
2399 if (name == NULL) return;
2400 switch(cur->type) {
2401 case XML_TEXT_NODE:
2402 case XML_CDATA_SECTION_NODE:
2403 case XML_COMMENT_NODE:
2404 case XML_DOCUMENT_NODE:
2405 case XML_DOCUMENT_TYPE_NODE:
2406 case XML_DOCUMENT_FRAG_NODE:
2407 case XML_NOTATION_NODE:
2408 case XML_HTML_DOCUMENT_NODE:
2409 return;
2410 case XML_ELEMENT_NODE:
2411 case XML_ATTRIBUTE_NODE:
2412 case XML_PI_NODE:
2413 case XML_ENTITY_REF_NODE:
2414 case XML_ENTITY_NODE:
2415 break;
2416 }
2417 if (cur->name != NULL) xmlFree((xmlChar *) cur->name);
2418 cur->name = xmlStrdup(name);
2419}
2420
2421/**
Daniel Veillard10a2c651999-12-12 13:03:50 +00002422 * xmlNodeGetBase:
2423 * @doc: the document the node pertains to
2424 * @cur: the node being checked
2425 *
2426 * Searches for the BASE URL. The code should work on both XML
2427 * and HTML document even if base mechanisms are completely different.
2428 *
2429 * Returns a pointer to the base URL, or NULL if not found
2430 * It's up to the caller to free the memory.
2431 */
2432xmlChar *
2433xmlNodeGetBase(xmlDocPtr doc, xmlNodePtr cur) {
2434 xmlChar *base;
2435
2436 if ((cur == NULL) && (doc == NULL))
2437 return(NULL);
2438 if (doc == NULL) doc = cur->doc;
2439 if ((doc != NULL) && (doc->type == XML_HTML_DOCUMENT_NODE)) {
2440 cur = doc->root;
2441 while ((cur != NULL) && (cur->name != NULL)) {
2442 if (cur->type != XML_ELEMENT_NODE) {
2443 cur = cur->next;
2444 continue;
2445 }
2446 if ((!xmlStrcmp(cur->name, BAD_CAST "html")) ||
2447 (!xmlStrcmp(cur->name, BAD_CAST "HTML"))) {
2448 cur = cur->childs;
2449 continue;
2450 }
2451 if ((!xmlStrcmp(cur->name, BAD_CAST "head")) ||
2452 (!xmlStrcmp(cur->name, BAD_CAST "HEAD"))) {
2453 cur = cur->childs;
2454 continue;
2455 }
2456 if ((!xmlStrcmp(cur->name, BAD_CAST "base")) ||
2457 (!xmlStrcmp(cur->name, BAD_CAST "BASE"))) {
2458 base = xmlGetProp(cur, BAD_CAST "href");
2459 if (base != NULL) return(base);
2460 return(xmlGetProp(cur, BAD_CAST "HREF"));
2461 }
2462 }
2463 return(NULL);
2464 }
2465 while (cur != NULL) {
2466 base = xmlGetProp(cur, BAD_CAST "xml:base");
2467 if (base != NULL)
2468 return(base);
2469 cur = cur->parent;
2470 }
2471 return(NULL);
2472}
2473
2474/**
Daniel Veillard16253641998-10-28 22:58:05 +00002475 * xmlNodeGetContent:
2476 * @cur: the node being read
2477 *
2478 * Read the value of a node, this can be either the text carried
2479 * directly by this node if it's a TEXT node or the aggregate string
2480 * of the values carried by this node child's (TEXT and ENTITY_REF).
2481 * Entity references are substitued.
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002482 * Returns a new xmlChar * or NULL if no content is available.
Daniel Veillard5099ae81999-04-21 20:12:07 +00002483 * It's up to the caller to free the memory.
Daniel Veillard16253641998-10-28 22:58:05 +00002484 */
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002485xmlChar *
Daniel Veillard16253641998-10-28 22:58:05 +00002486xmlNodeGetContent(xmlNodePtr cur) {
2487 if (cur == NULL) return(NULL);
2488 switch (cur->type) {
2489 case XML_DOCUMENT_FRAG_NODE:
2490 case XML_ELEMENT_NODE:
2491 return(xmlNodeListGetString(cur->doc, cur->childs, 1));
2492 break;
Daniel Veillardb96e6431999-08-29 21:02:19 +00002493 case XML_ATTRIBUTE_NODE: {
2494 xmlAttrPtr attr = (xmlAttrPtr) cur;
2495 if (attr->node != NULL)
2496 return(xmlNodeListGetString(attr->node->doc, attr->val, 1));
2497 else
2498 return(xmlNodeListGetString(NULL, attr->val, 1));
2499 break;
2500 }
2501 case XML_PI_NODE:
2502 if (cur->content != NULL)
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002503#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardb96e6431999-08-29 21:02:19 +00002504 return(xmlStrdup(cur->content));
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002505#else
2506 return(xmlStrdup(xmlBufferContent(cur->content)));
2507#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +00002508 return(NULL);
Daniel Veillard16253641998-10-28 22:58:05 +00002509 case XML_ENTITY_REF_NODE:
2510 case XML_ENTITY_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002511 case XML_COMMENT_NODE:
2512 case XML_DOCUMENT_NODE:
Daniel Veillard7c1206f1999-10-14 09:10:25 +00002513 case XML_HTML_DOCUMENT_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002514 case XML_DOCUMENT_TYPE_NODE:
2515 case XML_NOTATION_NODE:
2516 return(NULL);
Daniel Veillardb05deb71999-08-10 19:04:08 +00002517 case XML_CDATA_SECTION_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002518 case XML_TEXT_NODE:
2519 if (cur->content != NULL)
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002520#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard16253641998-10-28 22:58:05 +00002521 return(xmlStrdup(cur->content));
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002522#else
2523 return(xmlStrdup(xmlBufferContent(cur->content)));
2524#endif
Daniel Veillard16253641998-10-28 22:58:05 +00002525 return(NULL);
2526 }
2527 return(NULL);
2528}
2529
2530/**
Daniel Veillard97b58771998-10-20 06:14:16 +00002531 * xmlNodeSetContent:
2532 * @cur: the node being modified
2533 * @content: the new value of the content
2534 *
2535 * Replace the content of a node.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002536 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002537void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002538xmlNodeSetContent(xmlNodePtr cur, const xmlChar *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002539 if (cur == NULL) {
2540 fprintf(stderr, "xmlNodeSetContent : node == NULL\n");
2541 return;
2542 }
Daniel Veillard16253641998-10-28 22:58:05 +00002543 switch (cur->type) {
2544 case XML_DOCUMENT_FRAG_NODE:
2545 case XML_ELEMENT_NODE:
2546 if (cur->content != NULL) {
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002547#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard6454aec1999-09-02 22:04:43 +00002548 xmlFree(cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002549#else
2550 xmlBufferFree(cur->content);
2551#endif
Daniel Veillard16253641998-10-28 22:58:05 +00002552 cur->content = NULL;
2553 }
Daniel Veillard6454aec1999-09-02 22:04:43 +00002554 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillard16253641998-10-28 22:58:05 +00002555 cur->childs = xmlStringGetNodeList(cur->doc, content);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002556 UPDATE_LAST_CHILD(cur)
Daniel Veillard16253641998-10-28 22:58:05 +00002557 break;
2558 case XML_ATTRIBUTE_NODE:
2559 break;
2560 case XML_TEXT_NODE:
2561 case XML_CDATA_SECTION_NODE:
2562 case XML_ENTITY_REF_NODE:
2563 case XML_ENTITY_NODE:
2564 case XML_PI_NODE:
2565 case XML_COMMENT_NODE:
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002566 if (cur->content != NULL) {
2567#ifndef XML_USE_BUFFER_CONTENT
2568 xmlFree(cur->content);
2569#else
2570 xmlBufferFree(cur->content);
2571#endif
2572 }
Daniel Veillard6454aec1999-09-02 22:04:43 +00002573 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002574 cur->last = cur->childs = NULL;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002575 if (content != NULL) {
2576#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard16253641998-10-28 22:58:05 +00002577 cur->content = xmlStrdup(content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002578#else
2579 cur->content = xmlBufferCreateSize(0);
2580 xmlBufferSetAllocationScheme(cur->content,
2581 xmlGetBufferAllocationScheme());
2582 xmlBufferAdd(cur->content, content, -1);
2583#endif
2584 } else
Daniel Veillard16253641998-10-28 22:58:05 +00002585 cur->content = NULL;
Daniel Veillardb96e6431999-08-29 21:02:19 +00002586 break;
Daniel Veillard16253641998-10-28 22:58:05 +00002587 case XML_DOCUMENT_NODE:
Daniel Veillard7c1206f1999-10-14 09:10:25 +00002588 case XML_HTML_DOCUMENT_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002589 case XML_DOCUMENT_TYPE_NODE:
2590 break;
2591 case XML_NOTATION_NODE:
2592 break;
2593 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002594}
2595
Daniel Veillard97b58771998-10-20 06:14:16 +00002596/**
2597 * xmlNodeSetContentLen:
2598 * @cur: the node being modified
2599 * @content: the new value of the content
2600 * @len: the size of @content
2601 *
2602 * Replace the content of a node.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002603 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002604void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002605xmlNodeSetContentLen(xmlNodePtr cur, const xmlChar *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002606 if (cur == NULL) {
Daniel Veillard16253641998-10-28 22:58:05 +00002607 fprintf(stderr, "xmlNodeSetContentLen : node == NULL\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002608 return;
2609 }
Daniel Veillard16253641998-10-28 22:58:05 +00002610 switch (cur->type) {
2611 case XML_DOCUMENT_FRAG_NODE:
2612 case XML_ELEMENT_NODE:
2613 if (cur->content != NULL) {
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002614#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard6454aec1999-09-02 22:04:43 +00002615 xmlFree(cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002616#else
2617 xmlBufferFree(cur->content);
2618#endif
Daniel Veillard16253641998-10-28 22:58:05 +00002619 cur->content = NULL;
2620 }
Daniel Veillard6454aec1999-09-02 22:04:43 +00002621 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillard16253641998-10-28 22:58:05 +00002622 cur->childs = xmlStringLenGetNodeList(cur->doc, content, len);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002623 UPDATE_LAST_CHILD(cur)
Daniel Veillard16253641998-10-28 22:58:05 +00002624 break;
2625 case XML_ATTRIBUTE_NODE:
2626 break;
2627 case XML_TEXT_NODE:
2628 case XML_CDATA_SECTION_NODE:
2629 case XML_ENTITY_REF_NODE:
2630 case XML_ENTITY_NODE:
2631 case XML_PI_NODE:
2632 case XML_COMMENT_NODE:
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002633 case XML_NOTATION_NODE:
2634 if (cur->content != NULL) {
2635#ifndef XML_USE_BUFFER_CONTENT
2636 xmlFree(cur->content);
2637#else
2638 xmlBufferFree(cur->content);
2639#endif
2640 }
Daniel Veillard6454aec1999-09-02 22:04:43 +00002641 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002642 cur->childs = cur->last = NULL;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002643 if (content != NULL) {
2644#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard16253641998-10-28 22:58:05 +00002645 cur->content = xmlStrndup(content, len);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002646#else
2647 cur->content = xmlBufferCreateSize(len);
2648 xmlBufferSetAllocationScheme(cur->content,
2649 xmlGetBufferAllocationScheme());
2650 xmlBufferAdd(cur->content, content, len);
2651#endif
2652 } else
Daniel Veillard16253641998-10-28 22:58:05 +00002653 cur->content = NULL;
Daniel Veillardb96e6431999-08-29 21:02:19 +00002654 break;
Daniel Veillard16253641998-10-28 22:58:05 +00002655 case XML_DOCUMENT_NODE:
Daniel Veillard7c1206f1999-10-14 09:10:25 +00002656 case XML_HTML_DOCUMENT_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002657 case XML_DOCUMENT_TYPE_NODE:
2658 break;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002659 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002660}
2661
Daniel Veillard97b58771998-10-20 06:14:16 +00002662/**
2663 * xmlNodeAddContentLen:
2664 * @cur: the node being modified
2665 * @content: extra content
2666 * @len: the size of @content
2667 *
2668 * Append the extra substring to the node content.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002669 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002670void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002671xmlNodeAddContentLen(xmlNodePtr cur, const xmlChar *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002672 if (cur == NULL) {
Daniel Veillard16253641998-10-28 22:58:05 +00002673 fprintf(stderr, "xmlNodeAddContentLen : node == NULL\n");
2674 return;
2675 }
2676 if (len <= 0) return;
2677 switch (cur->type) {
2678 case XML_DOCUMENT_FRAG_NODE:
2679 case XML_ELEMENT_NODE: {
2680 xmlNodePtr last = NULL, new;
2681
2682 if (cur->childs != NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002683 last = cur->last;
Daniel Veillard16253641998-10-28 22:58:05 +00002684 } else {
2685 if (cur->content != NULL) {
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002686#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard16253641998-10-28 22:58:05 +00002687 cur->childs = xmlStringGetNodeList(cur->doc, cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002688#else
2689 cur->childs = xmlStringGetNodeList(cur->doc,
2690 xmlBufferContent(cur->content));
2691#endif
Daniel Veillard1e346af1999-02-22 10:33:01 +00002692 UPDATE_LAST_CHILD(cur)
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002693#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard6454aec1999-09-02 22:04:43 +00002694 xmlFree(cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002695#else
2696 xmlBufferFree(cur->content);
2697#endif
Daniel Veillard16253641998-10-28 22:58:05 +00002698 cur->content = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002699 last = cur->last;
Daniel Veillard16253641998-10-28 22:58:05 +00002700 }
2701 }
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002702 new = xmlNewTextLen(content, len);
Daniel Veillard16253641998-10-28 22:58:05 +00002703 if (new != NULL) {
2704 xmlAddChild(cur, new);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002705 if ((last != NULL) && (last->next == new)) {
Daniel Veillard16253641998-10-28 22:58:05 +00002706 xmlTextMerge(last, new);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002707 }
Daniel Veillard16253641998-10-28 22:58:05 +00002708 }
2709 break;
2710 }
2711 case XML_ATTRIBUTE_NODE:
2712 break;
2713 case XML_TEXT_NODE:
2714 case XML_CDATA_SECTION_NODE:
2715 case XML_ENTITY_REF_NODE:
2716 case XML_ENTITY_NODE:
2717 case XML_PI_NODE:
2718 case XML_COMMENT_NODE:
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002719 case XML_NOTATION_NODE:
2720 if (content != NULL) {
2721#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard16253641998-10-28 22:58:05 +00002722 cur->content = xmlStrncat(cur->content, content, len);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002723#else
2724 xmlBufferAdd(cur->content, content, len);
2725#endif
2726 }
Daniel Veillard16253641998-10-28 22:58:05 +00002727 case XML_DOCUMENT_NODE:
Daniel Veillard7c1206f1999-10-14 09:10:25 +00002728 case XML_HTML_DOCUMENT_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002729 case XML_DOCUMENT_TYPE_NODE:
2730 break;
Daniel Veillard16253641998-10-28 22:58:05 +00002731 }
2732}
2733
2734/**
2735 * xmlNodeAddContent:
2736 * @cur: the node being modified
2737 * @content: extra content
2738 *
2739 * Append the extra substring to the node content.
2740 */
2741void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002742xmlNodeAddContent(xmlNodePtr cur, const xmlChar *content) {
Daniel Veillard16253641998-10-28 22:58:05 +00002743 int len;
2744
2745 if (cur == NULL) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002746 fprintf(stderr, "xmlNodeAddContent : node == NULL\n");
2747 return;
2748 }
Daniel Veillard16253641998-10-28 22:58:05 +00002749 if (content == NULL) return;
2750 len = xmlStrlen(content);
2751 xmlNodeAddContentLen(cur, content, len);
2752}
2753
2754/**
2755 * xmlTextMerge:
2756 * @first: the first text node
2757 * @second: the second text node being merged
2758 *
2759 * Merge two text nodes into one
Daniel Veillard1e346af1999-02-22 10:33:01 +00002760 * Returns the first text node augmented
Daniel Veillard16253641998-10-28 22:58:05 +00002761 */
2762xmlNodePtr
2763xmlTextMerge(xmlNodePtr first, xmlNodePtr second) {
2764 if (first == NULL) return(second);
2765 if (second == NULL) return(first);
2766 if (first->type != XML_TEXT_NODE) return(first);
2767 if (second->type != XML_TEXT_NODE) return(first);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002768#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard16253641998-10-28 22:58:05 +00002769 xmlNodeAddContent(first, second->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002770#else
2771 xmlNodeAddContent(first, xmlBufferContent(second->content));
2772#endif
Daniel Veillard16253641998-10-28 22:58:05 +00002773 xmlUnlinkNode(second);
2774 xmlFreeNode(second);
2775 return(first);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002776}
2777
Daniel Veillard97b58771998-10-20 06:14:16 +00002778/**
Daniel Veillardb96e6431999-08-29 21:02:19 +00002779 * xmlGetNsList:
2780 * @doc: the document
2781 * @node: the current node
2782 *
2783 * Search all the namespace applying to a given element.
2784 * Returns an NULL terminated array of all the xmlNsPtr found
2785 * that need to be freed by the caller or NULL if no
2786 * namespace if defined
2787 */
2788xmlNsPtr *
2789xmlGetNsList(xmlDocPtr doc, xmlNodePtr node) {
2790 xmlNsPtr cur;
2791 xmlNsPtr *ret = NULL;
2792 int nbns = 0;
2793 int maxns = 10;
2794 int i;
2795
2796 while (node != NULL) {
2797 cur = node->nsDef;
2798 while (cur != NULL) {
2799 if (ret == NULL) {
Daniel Veillard6454aec1999-09-02 22:04:43 +00002800 ret = (xmlNsPtr *) xmlMalloc((maxns + 1) * sizeof(xmlNsPtr));
Daniel Veillardb96e6431999-08-29 21:02:19 +00002801 if (ret == NULL) {
2802 fprintf(stderr, "xmlGetNsList : out of memory!\n");
2803 return(NULL);
2804 }
2805 ret[nbns] = NULL;
2806 }
2807 for (i = 0;i < nbns;i++) {
2808 if ((cur->prefix == ret[i]->prefix) ||
2809 (!xmlStrcmp(cur->prefix, ret[i]->prefix))) break;
2810 }
2811 if (i >= nbns) {
2812 if (nbns >= maxns) {
2813 maxns *= 2;
Daniel Veillard6454aec1999-09-02 22:04:43 +00002814 ret = (xmlNsPtr *) xmlRealloc(ret,
Daniel Veillardb96e6431999-08-29 21:02:19 +00002815 (maxns + 1) * sizeof(xmlNsPtr));
2816 if (ret == NULL) {
2817 fprintf(stderr, "xmlGetNsList : realloc failed!\n");
2818 return(NULL);
2819 }
2820 }
2821 ret[nbns++] = cur;
2822 ret[nbns] = NULL;
2823 }
2824
2825 cur = cur->next;
2826 }
2827 node = node->parent;
2828 }
2829 return(ret);
2830}
2831
2832/**
Daniel Veillard97b58771998-10-20 06:14:16 +00002833 * xmlSearchNs:
2834 * @doc: the document
2835 * @node: the current node
2836 * @nameSpace: the namespace string
Daniel Veillard260a68f1998-08-13 03:39:55 +00002837 *
Daniel Veillard97b58771998-10-20 06:14:16 +00002838 * Search a Ns registered under a given name space for a document.
2839 * recurse on the parents until it finds the defined namespace
2840 * or return NULL otherwise.
2841 * @nameSpace can be NULL, this is a search for the default namespace.
Daniel Veillard1e346af1999-02-22 10:33:01 +00002842 * Returns the namespace pointer or NULL.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002843 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002844xmlNsPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002845xmlSearchNs(xmlDocPtr doc, xmlNodePtr node, const xmlChar *nameSpace) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002846 xmlNsPtr cur;
2847
Daniel Veillard62ba71e1999-12-16 17:52:19 +00002848 if (node == NULL) return(NULL);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002849 while (node != NULL) {
2850 cur = node->nsDef;
2851 while (cur != NULL) {
2852 if ((cur->prefix == NULL) && (nameSpace == NULL))
2853 return(cur);
2854 if ((cur->prefix != NULL) && (nameSpace != NULL) &&
2855 (!xmlStrcmp(cur->prefix, nameSpace)))
2856 return(cur);
2857 cur = cur->next;
2858 }
2859 node = node->parent;
2860 }
Daniel Veillard10a2c651999-12-12 13:03:50 +00002861#if 0
2862 /* Removed support for old namespaces */
Daniel Veillard260a68f1998-08-13 03:39:55 +00002863 if (doc != NULL) {
2864 cur = doc->oldNs;
2865 while (cur != NULL) {
2866 if ((cur->prefix != NULL) && (nameSpace != NULL) &&
2867 (!xmlStrcmp(cur->prefix, nameSpace)))
2868 return(cur);
2869 cur = cur->next;
2870 }
2871 }
Daniel Veillard10a2c651999-12-12 13:03:50 +00002872#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00002873 return(NULL);
2874}
2875
Daniel Veillard97b58771998-10-20 06:14:16 +00002876/**
2877 * xmlSearchNsByHref:
2878 * @doc: the document
2879 * @node: the current node
2880 * @href: the namespace value
2881 *
2882 * Search a Ns aliasing a given URI. Recurse on the parents until it finds
2883 * the defined namespace or return NULL otherwise.
Daniel Veillard1e346af1999-02-22 10:33:01 +00002884 * Returns the namespace pointer or NULL.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002885 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002886xmlNsPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002887xmlSearchNsByHref(xmlDocPtr doc, xmlNodePtr node, const xmlChar *href) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002888 xmlNsPtr cur;
2889
Daniel Veillard10a2c651999-12-12 13:03:50 +00002890 if ((node == NULL) || (href == NULL)) return(NULL);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002891 while (node != NULL) {
2892 cur = node->nsDef;
2893 while (cur != NULL) {
2894 if ((cur->href != NULL) && (href != NULL) &&
2895 (!xmlStrcmp(cur->href, href)))
2896 return(cur);
2897 cur = cur->next;
2898 }
2899 node = node->parent;
2900 }
Daniel Veillard10a2c651999-12-12 13:03:50 +00002901#if 0
2902 /* Removed support for old namespaces */
Daniel Veillard260a68f1998-08-13 03:39:55 +00002903 if (doc != NULL) {
2904 cur = doc->oldNs;
2905 while (cur != NULL) {
2906 if ((cur->href != NULL) && (href != NULL) &&
2907 (!xmlStrcmp(cur->href, href)))
2908 return(cur);
2909 cur = cur->next;
2910 }
2911 }
Daniel Veillard10a2c651999-12-12 13:03:50 +00002912#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00002913 return(NULL);
2914}
2915
Daniel Veillard97b58771998-10-20 06:14:16 +00002916/**
2917 * xmlGetProp:
2918 * @node: the node
2919 * @name: the attribute name
2920 *
2921 * Search and get the value of an attribute associated to a node
Daniel Veillardccb09631998-10-27 06:21:04 +00002922 * This does the entity substitution.
Daniel Veillard10a2c651999-12-12 13:03:50 +00002923 * This function looks in DTD attribute declaration for #FIXED or
2924 * default declaration values unless DTD use has been turned off.
2925 *
Daniel Veillard1e346af1999-02-22 10:33:01 +00002926 * Returns the attribute value or NULL if not found.
Daniel Veillarda819dac1999-11-24 18:04:22 +00002927 * It's up to the caller to free the memory.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002928 */
Daniel Veillarda819dac1999-11-24 18:04:22 +00002929xmlChar *
2930xmlGetProp(xmlNodePtr node, const xmlChar *name) {
Daniel Veillard10a2c651999-12-12 13:03:50 +00002931 xmlAttrPtr prop;
2932 xmlDocPtr doc;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002933
Daniel Veillard10a2c651999-12-12 13:03:50 +00002934 if ((node == NULL) || (name == NULL)) return(NULL);
2935 /*
2936 * Check on the properties attached to the node
2937 */
2938 prop = node->properties;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002939 while (prop != NULL) {
Daniel Veillard68178931999-02-08 18:34:36 +00002940 if (!xmlStrcmp(prop->name, name)) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002941 xmlChar *ret;
Daniel Veillard6800ef31999-02-08 18:33:22 +00002942
2943 ret = xmlNodeListGetString(node->doc, prop->val, 1);
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002944 if (ret == NULL) return(xmlStrdup((xmlChar *)""));
Daniel Veillard6800ef31999-02-08 18:33:22 +00002945 return(ret);
Daniel Veillard68178931999-02-08 18:34:36 +00002946 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002947 prop = prop->next;
2948 }
Daniel Veillard10a2c651999-12-12 13:03:50 +00002949 if (!xmlCheckDTD) return(NULL);
2950
2951 /*
2952 * Check if there is a default declaration in the internal
2953 * or external subsets
2954 */
2955 doc = node->doc;
2956 if (doc != NULL) {
2957 xmlAttributePtr attrDecl;
2958 if (doc->intSubset != NULL) {
2959 attrDecl = xmlGetDtdAttrDesc(doc->intSubset, node->name, name);
2960 if ((attrDecl == NULL) && (doc->extSubset != NULL))
2961 attrDecl = xmlGetDtdAttrDesc(doc->extSubset, node->name, name);
2962 return(xmlStrdup(attrDecl->defaultValue));
2963 }
2964 }
2965 return(NULL);
2966}
2967
2968/**
2969 * xmlGetNsProp:
2970 * @node: the node
2971 * @name: the attribute name
2972 * @namespace: the URI of the namespace
2973 *
2974 * Search and get the value of an attribute associated to a node
2975 * This attribute has to be anchored in the namespace specified.
2976 * This does the entity substitution.
2977 * This function looks in DTD attribute declaration for #FIXED or
2978 * default declaration values unless DTD use has been turned off.
2979 *
2980 * Returns the attribute value or NULL if not found.
2981 * It's up to the caller to free the memory.
2982 */
2983xmlChar *
2984xmlGetNsProp(xmlNodePtr node, const xmlChar *name, const xmlChar *namespace) {
2985 xmlAttrPtr prop = node->properties;
2986 xmlDocPtr doc;
2987 xmlNsPtr ns;
2988
2989 if (namespace == NULL)
2990 return(xmlGetProp(node, name));
2991 while (prop != NULL) {
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00002992 /*
2993 * One need to have
2994 * - same attribute names
2995 * - and the attribute carrying that namespace
2996 * or
2997 * no namespace on the attribute and the element carrying it
2998 */
Daniel Veillard10a2c651999-12-12 13:03:50 +00002999 if ((!xmlStrcmp(prop->name, name)) &&
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00003000 (((prop->ns == NULL) && (node->ns != NULL) &&
3001 (!xmlStrcmp(node->ns->href, namespace))) ||
Daniel Veillard3c558c31999-12-22 11:30:41 +00003002 ((prop->ns != NULL) && (!xmlStrcmp(prop->ns->href, namespace))))) {
Daniel Veillard10a2c651999-12-12 13:03:50 +00003003 xmlChar *ret;
3004
3005 ret = xmlNodeListGetString(node->doc, prop->val, 1);
3006 if (ret == NULL) return(xmlStrdup((xmlChar *)""));
3007 return(ret);
3008 }
3009 prop = prop->next;
3010 }
3011 if (!xmlCheckDTD) return(NULL);
3012
3013 /*
3014 * Check if there is a default declaration in the internal
3015 * or external subsets
3016 */
3017 doc = node->doc;
3018 if (doc != NULL) {
3019 xmlAttributePtr attrDecl;
3020 if (doc->intSubset != NULL) {
3021 attrDecl = xmlGetDtdAttrDesc(doc->intSubset, node->name, name);
3022 if ((attrDecl == NULL) && (doc->extSubset != NULL))
3023 attrDecl = xmlGetDtdAttrDesc(doc->extSubset, node->name, name);
3024
3025 if (attrDecl->prefix != NULL) {
3026 /*
3027 * The DTD declaration only allows a prefix search
3028 */
3029 ns = xmlSearchNs(doc, node, attrDecl->prefix);
3030 if ((ns != NULL) && (!xmlStrcmp(ns->href, namespace)))
3031 return(xmlStrdup(attrDecl->defaultValue));
3032 }
3033 }
3034 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003035 return(NULL);
3036}
3037
Daniel Veillard97b58771998-10-20 06:14:16 +00003038/**
Daniel Veillardccb09631998-10-27 06:21:04 +00003039 * xmlSetProp:
Daniel Veillard97b58771998-10-20 06:14:16 +00003040 * @node: the node
3041 * @name: the attribute name
3042 * @value: the attribute value
3043 *
3044 * Set (or reset) an attribute carried by a node.
Daniel Veillard1e346af1999-02-22 10:33:01 +00003045 * Returns the attribute pointer.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003046 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003047xmlAttrPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003048xmlSetProp(xmlNodePtr node, const xmlChar *name, const xmlChar *value) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003049 xmlAttrPtr prop = node->properties;
3050
3051 while (prop != NULL) {
3052 if (!xmlStrcmp(prop->name, name)) {
Daniel Veillardccb09631998-10-27 06:21:04 +00003053 if (prop->val != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +00003054 xmlFreeNodeList(prop->val);
Daniel Veillardccb09631998-10-27 06:21:04 +00003055 prop->val = NULL;
Daniel Veillard51e3b151999-11-12 17:02:31 +00003056 if (value != NULL) {
3057 xmlChar *buffer;
3058 buffer = xmlEncodeEntitiesReentrant(node->doc, value);
3059 prop->val = xmlStringGetNodeList(node->doc, buffer);
3060 xmlFree(buffer);
3061 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003062 return(prop);
3063 }
3064 prop = prop->next;
3065 }
3066 prop = xmlNewProp(node, name, value);
3067 return(prop);
3068}
3069
Daniel Veillard97b58771998-10-20 06:14:16 +00003070/**
3071 * xmlNodeIsText:
3072 * @node: the node
3073 *
3074 * Is this node a Text node ?
Daniel Veillard1e346af1999-02-22 10:33:01 +00003075 * Returns 1 yes, 0 no
Daniel Veillard260a68f1998-08-13 03:39:55 +00003076 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003077int
3078xmlNodeIsText(xmlNodePtr node) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003079 if (node == NULL) return(0);
3080
Daniel Veillard0bef1311998-10-14 02:36:47 +00003081 if (node->type == XML_TEXT_NODE) return(1);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003082 return(0);
3083}
3084
Daniel Veillard97b58771998-10-20 06:14:16 +00003085/**
Daniel Veillard1e346af1999-02-22 10:33:01 +00003086 * xmlTextConcat:
Daniel Veillard97b58771998-10-20 06:14:16 +00003087 * @node: the node
3088 * @content: the content
3089 * @len: @content lenght
3090 *
3091 * Concat the given string at the end of the existing node content
Daniel Veillard260a68f1998-08-13 03:39:55 +00003092 */
Daniel Veillard97b58771998-10-20 06:14:16 +00003093
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003094void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003095xmlTextConcat(xmlNodePtr node, const xmlChar *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003096 if (node == NULL) return;
3097
Daniel Veillard0bef1311998-10-14 02:36:47 +00003098 if (node->type != XML_TEXT_NODE) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003099 fprintf(stderr, "xmlTextConcat: node is not text\n");
3100 return;
3101 }
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003102#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard260a68f1998-08-13 03:39:55 +00003103 node->content = xmlStrncat(node->content, content, len);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003104#else
3105 xmlBufferAdd(node->content, content, len);
3106#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00003107}
3108
3109/************************************************************************
3110 * *
3111 * Output : to a FILE or in memory *
3112 * *
3113 ************************************************************************/
3114
Daniel Veillard5099ae81999-04-21 20:12:07 +00003115#define BASE_BUFFER_SIZE 4000
3116
3117/**
3118 * xmlBufferCreate:
3119 *
3120 * routine to create an XML buffer.
3121 * returns the new structure.
3122 */
3123xmlBufferPtr
3124xmlBufferCreate(void) {
3125 xmlBufferPtr ret;
3126
Daniel Veillard6454aec1999-09-02 22:04:43 +00003127 ret = (xmlBufferPtr) xmlMalloc(sizeof(xmlBuffer));
Daniel Veillard5099ae81999-04-21 20:12:07 +00003128 if (ret == NULL) {
3129 fprintf(stderr, "xmlBufferCreate : out of memory!\n");
3130 return(NULL);
3131 }
3132 ret->use = 0;
3133 ret->size = BASE_BUFFER_SIZE;
Daniel Veillard10a2c651999-12-12 13:03:50 +00003134 ret->alloc = xmlBufferAllocScheme;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003135 ret->content = (xmlChar *) xmlMalloc(ret->size * sizeof(xmlChar));
Daniel Veillard5099ae81999-04-21 20:12:07 +00003136 if (ret->content == NULL) {
3137 fprintf(stderr, "xmlBufferCreate : out of memory!\n");
Daniel Veillard6454aec1999-09-02 22:04:43 +00003138 xmlFree(ret);
Daniel Veillard5099ae81999-04-21 20:12:07 +00003139 return(NULL);
3140 }
3141 ret->content[0] = 0;
3142 return(ret);
3143}
3144
3145/**
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003146 * xmlBufferCreateSize:
3147 * @size: initial size of buffer
3148 *
3149 * routine to create an XML buffer.
3150 * returns the new structure.
3151 */
3152xmlBufferPtr
3153xmlBufferCreateSize(size_t size) {
3154 xmlBufferPtr ret;
3155
3156 ret = (xmlBufferPtr) xmlMalloc(sizeof(xmlBuffer));
3157 if (ret == NULL) {
3158 fprintf(stderr, "xmlBufferCreate : out of memory!\n");
3159 return(NULL);
3160 }
3161 ret->use = 0;
Daniel Veillard10a2c651999-12-12 13:03:50 +00003162 ret->alloc = xmlBufferAllocScheme;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003163 ret->size = (size ? size+2 : 0); /* +1 for ending null */
Daniel Veillard10a2c651999-12-12 13:03:50 +00003164 if (ret->size){
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003165 ret->content = (xmlChar *) xmlMalloc(ret->size * sizeof(xmlChar));
3166 if (ret->content == NULL) {
3167 fprintf(stderr, "xmlBufferCreate : out of memory!\n");
3168 xmlFree(ret);
3169 return(NULL);
3170 }
3171 ret->content[0] = 0;
3172 } else
3173 ret->content = NULL;
3174 return(ret);
3175}
3176
3177/**
3178 * xmlBufferAllocationScheme:
3179 * @buf: the buffer to free
3180 * @scheme: allocation scheme to use
3181 *
3182 * Sets the allocation scheme for this buffer
3183 */
3184void
3185xmlBufferSetAllocationScheme(xmlBufferPtr buf,
3186 xmlBufferAllocationScheme scheme) {
3187 if (buf == NULL) {
3188 fprintf(stderr, "xmlBufferSetAllocationScheme: buf == NULL\n");
3189 return;
3190 }
3191
3192 buf->alloc = scheme;
3193}
3194
3195/**
Daniel Veillard5099ae81999-04-21 20:12:07 +00003196 * xmlBufferFree:
3197 * @buf: the buffer to free
3198 *
3199 * Frees an XML buffer.
3200 */
3201void
3202xmlBufferFree(xmlBufferPtr buf) {
3203 if (buf == NULL) {
3204 fprintf(stderr, "xmlBufferFree: buf == NULL\n");
3205 return;
3206 }
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003207 if (buf->content != NULL) {
3208#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard5099ae81999-04-21 20:12:07 +00003209 memset(buf->content, -1, BASE_BUFFER_SIZE);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003210#else
3211 memset(buf->content, -1, buf->size);
3212#endif
Daniel Veillard6454aec1999-09-02 22:04:43 +00003213 xmlFree(buf->content);
Daniel Veillard5099ae81999-04-21 20:12:07 +00003214 }
3215 memset(buf, -1, sizeof(xmlBuffer));
Daniel Veillard6454aec1999-09-02 22:04:43 +00003216 xmlFree(buf);
Daniel Veillard5099ae81999-04-21 20:12:07 +00003217}
3218
3219/**
Daniel Veillarde2d034d1999-07-27 19:52:06 +00003220 * xmlBufferEmpty:
3221 * @buf: the buffer
3222 *
3223 * empty a buffer.
3224 */
3225void
3226xmlBufferEmpty(xmlBufferPtr buf) {
3227 buf->use = 0;
3228 memset(buf->content, -1, buf->size);/* just for debug */
3229}
3230
3231/**
3232 * xmlBufferShrink:
3233 * @buf: the buffer to dump
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003234 * @len: the number of xmlChar to remove
Daniel Veillarde2d034d1999-07-27 19:52:06 +00003235 *
3236 * Remove the beginning of an XML buffer.
3237 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003238 * Returns the number of xmlChar removed, or -1 in case of failure.
Daniel Veillarde2d034d1999-07-27 19:52:06 +00003239 */
3240int
3241xmlBufferShrink(xmlBufferPtr buf, int len) {
3242 if (len == 0) return(0);
3243 if (len > buf->use) return(-1);
3244
3245 buf->use -= len;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003246 memmove(buf->content, &buf->content[len], buf->use * sizeof(xmlChar));
Daniel Veillarde2d034d1999-07-27 19:52:06 +00003247
3248 buf->content[buf->use] = 0;
3249 return(len);
3250}
3251
3252/**
Daniel Veillard5099ae81999-04-21 20:12:07 +00003253 * xmlBufferDump:
3254 * @file: the file output
3255 * @buf: the buffer to dump
3256 *
3257 * Dumps an XML buffer to a FILE *.
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003258 * Returns the number of xmlChar written
Daniel Veillard5099ae81999-04-21 20:12:07 +00003259 */
3260int
3261xmlBufferDump(FILE *file, xmlBufferPtr buf) {
3262 int ret;
3263
3264 if (buf == NULL) {
3265 fprintf(stderr, "xmlBufferDump: buf == NULL\n");
3266 return(0);
3267 }
3268 if (buf->content == NULL) {
3269 fprintf(stderr, "xmlBufferDump: buf->content == NULL\n");
3270 return(0);
3271 }
3272 if (file == NULL) file = stdout;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003273 ret = fwrite(buf->content, sizeof(xmlChar), buf->use, file);
Daniel Veillard5099ae81999-04-21 20:12:07 +00003274 return(ret);
3275}
3276
3277/**
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003278 * xmlBufferContent:
3279 * @buf: the buffer to resize
3280 *
3281 * Returns the internal content
3282 */
3283
3284const xmlChar*
3285xmlBufferContent(const xmlBufferPtr buf)
3286{
3287 if(!buf)
3288 return NULL;
3289
3290 return buf->content;
3291}
3292
3293/**
3294 * xmlBufferLength:
3295 * @buf: the buffer
3296 *
3297 * Returns the length of data in the internal content
3298 */
3299
3300int
3301xmlBufferLength(const xmlBufferPtr buf)
3302{
3303 if(!buf)
3304 return 0;
3305
3306 return buf->use;
3307}
3308
3309/**
3310 * xmlBufferResize:
3311 * @buf: the buffer to resize
3312 * @len: the desired size
3313 *
3314 * Resize a buffer to accomodate minimum size of <len>.
3315 *
3316 * Returns 0 in case of problems, 1 otherwise
3317 */
3318int
3319xmlBufferResize(xmlBufferPtr buf, int size)
3320{
3321 int newSize = (buf->size ? buf->size*2 : size);/*take care of empty case*/
3322 xmlChar* rebuf = NULL;
3323
3324 /* Don't resize if we don't have to */
3325 if(size < buf->size)
3326 return 1;
3327
3328 /* figure out new size */
3329 switch(buf->alloc){
3330 case XML_BUFFER_ALLOC_DOUBLEIT:
3331 while(size > newSize) newSize *= 2;
3332 break;
3333 case XML_BUFFER_ALLOC_EXACT:
3334 newSize = size+10;
3335 break;
3336 default:
3337 newSize = size+10;
3338 break;
3339 }
3340
3341 if (buf->content == NULL)
3342 rebuf = (xmlChar *) xmlMalloc(newSize * sizeof(xmlChar));
3343 else
3344 rebuf = (xmlChar *) xmlRealloc(buf->content,
3345 newSize * sizeof(xmlChar));
3346 if (rebuf == NULL) {
3347 fprintf(stderr, "xmlBufferAdd : out of memory!\n");
3348 return 0;
3349 }
3350 buf->content = rebuf;
3351 buf->size = newSize;
3352
3353 return 1;
3354}
3355/**
Daniel Veillard5099ae81999-04-21 20:12:07 +00003356 * xmlBufferAdd:
3357 * @buf: the buffer to dump
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003358 * @str: the xmlChar string
3359 * @len: the number of xmlChar to add
Daniel Veillard5099ae81999-04-21 20:12:07 +00003360 *
Daniel Veillard10a2c651999-12-12 13:03:50 +00003361 * Add a string range to an XML buffer. if len == -1, the lenght of
3362 * str is recomputed.
Daniel Veillard5099ae81999-04-21 20:12:07 +00003363 */
3364void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003365xmlBufferAdd(xmlBufferPtr buf, const xmlChar *str, int len) {
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003366 int l, needSize;
Daniel Veillard5099ae81999-04-21 20:12:07 +00003367
3368 if (str == NULL) {
3369 fprintf(stderr, "xmlBufferAdd: str == NULL\n");
3370 return;
3371 }
Daniel Veillard10a2c651999-12-12 13:03:50 +00003372 if (len < -1) {
3373 fprintf(stderr, "xmlBufferAdd: len < 0\n");
3374 return;
3375 }
3376 if (len == 0) return;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003377
3378 /* CJN What's this for??? */
Daniel Veillarde2d034d1999-07-27 19:52:06 +00003379 l = xmlStrlen(str);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003380 if (l < len){ len = l; printf("xmlBufferAdd bad length\n"); }
3381
3382 /* CJN 11.18.99 okay, now I'm using the length */
3383 if(len == -1) len = l;
3384
3385
Daniel Veillarde2d034d1999-07-27 19:52:06 +00003386 if (len <= 0) return;
Daniel Veillard5099ae81999-04-21 20:12:07 +00003387
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003388 needSize = buf->use + len + 2;
3389 if(needSize > buf->size){
3390 if(!xmlBufferResize(buf, needSize)){
3391 fprintf(stderr, "xmlBufferAdd : out of memory!\n");
3392 return;
3393 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003394 }
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003395
3396 memmove(&buf->content[buf->use], str, len*sizeof(xmlChar));
Daniel Veillarde2d034d1999-07-27 19:52:06 +00003397 buf->use += len;
3398 buf->content[buf->use] = 0;
Daniel Veillard5099ae81999-04-21 20:12:07 +00003399}
3400
3401/**
3402 * xmlBufferCat:
3403 * @buf: the buffer to dump
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003404 * @str: the xmlChar string
Daniel Veillard5099ae81999-04-21 20:12:07 +00003405 *
3406 * Append a zero terminated string to an XML buffer.
3407 */
3408void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003409xmlBufferCat(xmlBufferPtr buf, const xmlChar *str) {
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003410 if (str != NULL)
3411 xmlBufferAdd(buf, str, -1);
Daniel Veillard5099ae81999-04-21 20:12:07 +00003412}
3413
3414/**
3415 * xmlBufferCCat:
3416 * @buf: the buffer to dump
3417 * @str: the C char string
3418 *
3419 * Append a zero terminated C string to an XML buffer.
3420 */
3421void
3422xmlBufferCCat(xmlBufferPtr buf, const char *str) {
3423 const char *cur;
3424
3425 if (str == NULL) {
3426 fprintf(stderr, "xmlBufferAdd: str == NULL\n");
3427 return;
3428 }
3429 for (cur = str;*cur != 0;cur++) {
3430 if (buf->use + 10 >= buf->size) {
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003431 if(!xmlBufferResize(buf, buf->use+10)){
3432 fprintf(stderr, "xmlBufferCCat : out of memory!\n");
3433 return;
3434 }
3435 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003436 buf->content[buf->use++] = *cur;
3437 }
3438}
Daniel Veillard260a68f1998-08-13 03:39:55 +00003439
Daniel Veillard97b58771998-10-20 06:14:16 +00003440/**
3441 * xmlBufferWriteCHAR:
Daniel Veillard5099ae81999-04-21 20:12:07 +00003442 * @buf: the XML buffer
Daniel Veillard97b58771998-10-20 06:14:16 +00003443 * @string: the string to add
3444 *
3445 * routine which manage and grows an output buffer. This one add
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003446 * xmlChars at the end of the buffer.
Daniel Veillard97b58771998-10-20 06:14:16 +00003447 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003448void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003449xmlBufferWriteCHAR(xmlBufferPtr buf, const xmlChar *string) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003450 xmlBufferCat(buf, string);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003451}
3452
Daniel Veillard97b58771998-10-20 06:14:16 +00003453/**
3454 * xmlBufferWriteChar:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003455 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003456 * @string: the string to add
3457 *
3458 * routine which manage and grows an output buffer. This one add
3459 * C chars at the end of the array.
3460 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003461void
Daniel Veillard5099ae81999-04-21 20:12:07 +00003462xmlBufferWriteChar(xmlBufferPtr buf, const char *string) {
3463 xmlBufferCCat(buf, string);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003464}
3465
Daniel Veillard5099ae81999-04-21 20:12:07 +00003466
Daniel Veillard97b58771998-10-20 06:14:16 +00003467/**
Daniel Veillard011b63c1999-06-02 17:44:04 +00003468 * xmlBufferWriteQuotedString:
3469 * @buf: the XML buffer output
3470 * @string: the string to add
3471 *
3472 * routine which manage and grows an output buffer. This one writes
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003473 * a quoted or double quoted xmlChar string, checking first if it holds
Daniel Veillard011b63c1999-06-02 17:44:04 +00003474 * quote or double-quotes internally
3475 */
3476void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003477xmlBufferWriteQuotedString(xmlBufferPtr buf, const xmlChar *string) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00003478 if (xmlStrchr(string, '"')) {
3479 if (xmlStrchr(string, '\'')) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00003480 fprintf(stderr,
3481 "xmlBufferWriteQuotedString: string contains quote and double-quotes !\n");
3482 }
3483 xmlBufferCCat(buf, "'");
3484 xmlBufferCat(buf, string);
3485 xmlBufferCCat(buf, "'");
3486 } else {
3487 xmlBufferCCat(buf, "\"");
3488 xmlBufferCat(buf, string);
3489 xmlBufferCCat(buf, "\"");
3490 }
3491}
3492
3493
3494/**
Daniel Veillard97b58771998-10-20 06:14:16 +00003495 * xmlGlobalNsDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003496 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003497 * @cur: a namespace
3498 *
3499 * Dump a global Namespace, this is the old version based on PIs.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003500 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003501static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00003502xmlGlobalNsDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003503 if (cur == NULL) {
3504 fprintf(stderr, "xmlGlobalNsDump : Ns == NULL\n");
3505 return;
3506 }
3507 if (cur->type == XML_GLOBAL_NAMESPACE) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003508 xmlBufferWriteChar(buf, "<?namespace");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003509 if (cur->href != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00003510 xmlBufferWriteChar(buf, " href=");
3511 xmlBufferWriteQuotedString(buf, cur->href);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003512 }
3513 if (cur->prefix != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00003514 xmlBufferWriteChar(buf, " AS=");
3515 xmlBufferWriteQuotedString(buf, cur->prefix);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003516 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003517 xmlBufferWriteChar(buf, "?>\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003518 }
3519}
3520
Daniel Veillard97b58771998-10-20 06:14:16 +00003521/**
3522 * xmlGlobalNsListDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003523 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003524 * @cur: the first namespace
3525 *
3526 * Dump a list of global Namespace, this is the old version based on PIs.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003527 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003528static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00003529xmlGlobalNsListDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003530 while (cur != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003531 xmlGlobalNsDump(buf, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003532 cur = cur->next;
3533 }
3534}
3535
Daniel Veillard97b58771998-10-20 06:14:16 +00003536/**
3537 * xmlNsDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003538 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003539 * @cur: a namespace
3540 *
Daniel Veillard260a68f1998-08-13 03:39:55 +00003541 * Dump a local Namespace definition.
Daniel Veillard97b58771998-10-20 06:14:16 +00003542 * Should be called in the context of attributes dumps.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003543 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003544static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00003545xmlNsDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003546 if (cur == NULL) {
3547 fprintf(stderr, "xmlNsDump : Ns == NULL\n");
3548 return;
3549 }
3550 if (cur->type == XML_LOCAL_NAMESPACE) {
3551 /* Within the context of an element attributes */
3552 if (cur->prefix != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003553 xmlBufferWriteChar(buf, " xmlns:");
3554 xmlBufferWriteCHAR(buf, cur->prefix);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003555 } else
Daniel Veillard5099ae81999-04-21 20:12:07 +00003556 xmlBufferWriteChar(buf, " xmlns");
Daniel Veillard011b63c1999-06-02 17:44:04 +00003557 xmlBufferWriteChar(buf, "=");
3558 xmlBufferWriteQuotedString(buf, cur->href);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003559 }
3560}
3561
Daniel Veillard97b58771998-10-20 06:14:16 +00003562/**
3563 * xmlNsListDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003564 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003565 * @cur: the first namespace
3566 *
3567 * Dump a list of local Namespace definitions.
3568 * Should be called in the context of attributes dumps.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003569 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003570static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00003571xmlNsListDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003572 while (cur != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003573 xmlNsDump(buf, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003574 cur = cur->next;
3575 }
3576}
3577
Daniel Veillard97b58771998-10-20 06:14:16 +00003578/**
3579 * xmlDtdDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003580 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003581 * @doc: the document
3582 *
3583 * Dump the XML document DTD, if any.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003584 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003585static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00003586xmlDtdDump(xmlBufferPtr buf, xmlDocPtr doc) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003587 xmlDtdPtr cur = doc->intSubset;
Daniel Veillard260a68f1998-08-13 03:39:55 +00003588
3589 if (cur == NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003590 fprintf(stderr, "xmlDtdDump : no internal subset\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003591 return;
3592 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003593 xmlBufferWriteChar(buf, "<!DOCTYPE ");
3594 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003595 if (cur->ExternalID != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00003596 xmlBufferWriteChar(buf, " PUBLIC ");
3597 xmlBufferWriteQuotedString(buf, cur->ExternalID);
3598 xmlBufferWriteChar(buf, " ");
3599 xmlBufferWriteQuotedString(buf, cur->SystemID);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003600 } else if (cur->SystemID != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00003601 xmlBufferWriteChar(buf, " SYSTEM ");
3602 xmlBufferWriteQuotedString(buf, cur->SystemID);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003603 }
Daniel Veillard1e346af1999-02-22 10:33:01 +00003604 if ((cur->entities == NULL) && (cur->elements == NULL) &&
3605 (cur->attributes == NULL) && (cur->notations == NULL)) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003606 xmlBufferWriteChar(buf, ">\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003607 return;
3608 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003609 xmlBufferWriteChar(buf, " [\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003610 if (cur->entities != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00003611 xmlDumpEntitiesTable(buf, (xmlEntitiesTablePtr) cur->entities);
Daniel Veillard1e346af1999-02-22 10:33:01 +00003612 if (cur->notations != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00003613 xmlDumpNotationTable(buf, (xmlNotationTablePtr) cur->notations);
Daniel Veillard3b9def11999-01-31 22:15:06 +00003614 if (cur->elements != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00003615 xmlDumpElementTable(buf, (xmlElementTablePtr) cur->elements);
Daniel Veillard1e346af1999-02-22 10:33:01 +00003616 if (cur->attributes != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00003617 xmlDumpAttributeTable(buf, (xmlAttributeTablePtr) cur->attributes);
3618 xmlBufferWriteChar(buf, "]");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003619
Daniel Veillard5099ae81999-04-21 20:12:07 +00003620 xmlBufferWriteChar(buf, ">\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003621}
3622
Daniel Veillard97b58771998-10-20 06:14:16 +00003623/**
3624 * xmlAttrDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003625 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003626 * @doc: the document
3627 * @cur: the attribute pointer
3628 *
3629 * Dump an XML attribute
Daniel Veillard260a68f1998-08-13 03:39:55 +00003630 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003631static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00003632xmlAttrDump(xmlBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003633 xmlChar *value;
Daniel Veillardccb09631998-10-27 06:21:04 +00003634
Daniel Veillard260a68f1998-08-13 03:39:55 +00003635 if (cur == NULL) {
3636 fprintf(stderr, "xmlAttrDump : property == NULL\n");
3637 return;
3638 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003639 xmlBufferWriteChar(buf, " ");
Daniel Veillardb96e6431999-08-29 21:02:19 +00003640 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
3641 xmlBufferWriteCHAR(buf, cur->ns->prefix);
3642 xmlBufferWriteChar(buf, ":");
3643 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003644 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillardccb09631998-10-27 06:21:04 +00003645 value = xmlNodeListGetString(doc, cur->val, 0);
3646 if (value) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00003647 xmlBufferWriteChar(buf, "=");
3648 xmlBufferWriteQuotedString(buf, value);
Daniel Veillard6454aec1999-09-02 22:04:43 +00003649 xmlFree(value);
Daniel Veillard726c7e31999-02-08 15:13:10 +00003650 } else {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003651 xmlBufferWriteChar(buf, "=\"\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003652 }
3653}
3654
Daniel Veillard97b58771998-10-20 06:14:16 +00003655/**
3656 * xmlAttrListDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003657 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003658 * @doc: the document
3659 * @cur: the first attribute pointer
3660 *
3661 * Dump a list of XML attributes
Daniel Veillard260a68f1998-08-13 03:39:55 +00003662 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003663static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00003664xmlAttrListDump(xmlBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003665 if (cur == NULL) {
3666 fprintf(stderr, "xmlAttrListDump : property == NULL\n");
3667 return;
3668 }
3669 while (cur != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003670 xmlAttrDump(buf, doc, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003671 cur = cur->next;
3672 }
3673}
3674
Daniel Veillard260a68f1998-08-13 03:39:55 +00003675
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003676static void
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003677xmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
3678 int format);
Daniel Veillard97b58771998-10-20 06:14:16 +00003679/**
3680 * xmlNodeListDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003681 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003682 * @doc: the document
3683 * @cur: the first node
3684 * @level: the imbrication level for indenting
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003685 * @format: is formatting allowed
Daniel Veillard97b58771998-10-20 06:14:16 +00003686 *
3687 * Dump an XML node list, recursive behaviour,children are printed too.
3688 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003689static void
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003690xmlNodeListDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
3691 int format) {
3692 int i;
Daniel Veillardccb09631998-10-27 06:21:04 +00003693
Daniel Veillard260a68f1998-08-13 03:39:55 +00003694 if (cur == NULL) {
3695 fprintf(stderr, "xmlNodeListDump : node == NULL\n");
3696 return;
3697 }
3698 while (cur != NULL) {
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003699 if ((format) && (xmlIndentTreeOutput) &&
3700 (cur->type == XML_ELEMENT_NODE))
3701 for (i = 0;i < level;i++)
3702 xmlBufferWriteChar(buf, " ");
3703 xmlNodeDump(buf, doc, cur, level, format);
3704 if (format) {
3705 xmlBufferWriteChar(buf, "\n");
Daniel Veillardccb09631998-10-27 06:21:04 +00003706 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003707 cur = cur->next;
3708 }
3709}
3710
Daniel Veillard97b58771998-10-20 06:14:16 +00003711/**
Daniel Veillardccb09631998-10-27 06:21:04 +00003712 * xmlNodeDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003713 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003714 * @doc: the document
3715 * @cur: the current node
3716 * @level: the imbrication level for indenting
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003717 * @format: is formatting allowed
Daniel Veillard97b58771998-10-20 06:14:16 +00003718 *
3719 * Dump an XML node, recursive behaviour,children are printed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003720 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003721static void
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003722xmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
3723 int format) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003724 int i;
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003725 xmlNodePtr tmp;
Daniel Veillard260a68f1998-08-13 03:39:55 +00003726
3727 if (cur == NULL) {
3728 fprintf(stderr, "xmlNodeDump : node == NULL\n");
3729 return;
3730 }
Daniel Veillard0bef1311998-10-14 02:36:47 +00003731 if (cur->type == XML_TEXT_NODE) {
Daniel Veillard14fff061999-06-22 21:49:07 +00003732 if (cur->content != NULL) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003733 xmlChar *buffer;
Daniel Veillard14fff061999-06-22 21:49:07 +00003734
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003735#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard14fff061999-06-22 21:49:07 +00003736 buffer = xmlEncodeEntitiesReentrant(doc, cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003737#else
3738 buffer = xmlEncodeEntitiesReentrant(doc,
3739 xmlBufferContent(cur->content));
3740#endif
Daniel Veillard14fff061999-06-22 21:49:07 +00003741 if (buffer != NULL) {
3742 xmlBufferWriteCHAR(buf, buffer);
Daniel Veillard6454aec1999-09-02 22:04:43 +00003743 xmlFree(buffer);
Daniel Veillard14fff061999-06-22 21:49:07 +00003744 }
3745 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003746 return;
3747 }
Daniel Veillardb96e6431999-08-29 21:02:19 +00003748 if (cur->type == XML_PI_NODE) {
3749 if (cur->content != NULL) {
3750 xmlBufferWriteChar(buf, "<?");
3751 xmlBufferWriteCHAR(buf, cur->name);
3752 if (cur->content != NULL) {
3753 xmlBufferWriteChar(buf, " ");
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003754#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardb96e6431999-08-29 21:02:19 +00003755 xmlBufferWriteCHAR(buf, cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003756#else
3757 xmlBufferWriteCHAR(buf, xmlBufferContent(cur->content));
3758#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +00003759 }
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003760 xmlBufferWriteChar(buf, "?>");
Daniel Veillardb96e6431999-08-29 21:02:19 +00003761 }
3762 return;
3763 }
Daniel Veillard0bef1311998-10-14 02:36:47 +00003764 if (cur->type == XML_COMMENT_NODE) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003765 if (cur->content != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003766 xmlBufferWriteChar(buf, "<!--");
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003767#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard5099ae81999-04-21 20:12:07 +00003768 xmlBufferWriteCHAR(buf, cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003769#else
3770 xmlBufferWriteCHAR(buf, xmlBufferContent(cur->content));
3771#endif
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003772 xmlBufferWriteChar(buf, "-->");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003773 }
3774 return;
3775 }
Daniel Veillardccb09631998-10-27 06:21:04 +00003776 if (cur->type == XML_ENTITY_REF_NODE) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003777 xmlBufferWriteChar(buf, "&");
3778 xmlBufferWriteCHAR(buf, cur->name);
3779 xmlBufferWriteChar(buf, ";");
Daniel Veillardccb09631998-10-27 06:21:04 +00003780 return;
3781 }
Daniel Veillardb05deb71999-08-10 19:04:08 +00003782 if (cur->type == XML_CDATA_SECTION_NODE) {
3783 xmlBufferWriteChar(buf, "<![CDATA[");
3784 if (cur->content != NULL)
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003785#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardb05deb71999-08-10 19:04:08 +00003786 xmlBufferWriteCHAR(buf, cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003787#else
3788 xmlBufferWriteCHAR(buf, xmlBufferContent(cur->content));
3789#endif
Daniel Veillardb05deb71999-08-10 19:04:08 +00003790 xmlBufferWriteChar(buf, "]]>");
3791 return;
3792 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003793
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003794 if (format == 1) {
3795 tmp = cur->childs;
3796 while (tmp != NULL) {
3797 if ((tmp->type == XML_TEXT_NODE) ||
3798 (tmp->type == XML_ENTITY_REF_NODE)) {
3799 format = 0;
3800 break;
3801 }
3802 tmp = tmp->next;
3803 }
3804 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003805 xmlBufferWriteChar(buf, "<");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003806 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003807 xmlBufferWriteCHAR(buf, cur->ns->prefix);
3808 xmlBufferWriteChar(buf, ":");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003809 }
3810
Daniel Veillard5099ae81999-04-21 20:12:07 +00003811 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003812 if (cur->nsDef)
Daniel Veillard5099ae81999-04-21 20:12:07 +00003813 xmlNsListDump(buf, cur->nsDef);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003814 if (cur->properties != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00003815 xmlAttrListDump(buf, doc, cur->properties);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003816
3817 if ((cur->content == NULL) && (cur->childs == NULL)) {
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003818 xmlBufferWriteChar(buf, "/>");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003819 return;
3820 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003821 xmlBufferWriteChar(buf, ">");
Daniel Veillard14fff061999-06-22 21:49:07 +00003822 if (cur->content != NULL) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003823 xmlChar *buffer;
Daniel Veillard14fff061999-06-22 21:49:07 +00003824
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003825#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard14fff061999-06-22 21:49:07 +00003826 buffer = xmlEncodeEntitiesReentrant(doc, cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003827#else
3828 buffer = xmlEncodeEntitiesReentrant(doc,
3829 xmlBufferContent(cur->content));
3830#endif
Daniel Veillard14fff061999-06-22 21:49:07 +00003831 if (buffer != NULL) {
3832 xmlBufferWriteCHAR(buf, buffer);
Daniel Veillard6454aec1999-09-02 22:04:43 +00003833 xmlFree(buffer);
Daniel Veillard14fff061999-06-22 21:49:07 +00003834 }
3835 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003836 if (cur->childs != NULL) {
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003837 if (format) xmlBufferWriteChar(buf, "\n");
3838 xmlNodeListDump(buf, doc, cur->childs, level + 1, format);
3839 if ((xmlIndentTreeOutput) && (format))
3840 for (i = 0;i < level;i++)
3841 xmlBufferWriteChar(buf, " ");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003842 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003843 xmlBufferWriteChar(buf, "</");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003844 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003845 xmlBufferWriteCHAR(buf, cur->ns->prefix);
3846 xmlBufferWriteChar(buf, ":");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003847 }
3848
Daniel Veillard5099ae81999-04-21 20:12:07 +00003849 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003850 xmlBufferWriteChar(buf, ">");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003851}
3852
Daniel Veillard97b58771998-10-20 06:14:16 +00003853/**
3854 * xmlDocContentDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003855 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003856 * @cur: the document
3857 *
3858 * Dump an XML document.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003859 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003860static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00003861xmlDocContentDump(xmlBufferPtr buf, xmlDocPtr cur) {
Daniel Veillardbe70ff71999-07-05 16:50:46 +00003862 xmlBufferWriteChar(buf, "<?xml version=");
3863 if (cur->version != NULL)
3864 xmlBufferWriteQuotedString(buf, cur->version);
3865 else
3866 xmlBufferWriteChar(buf, "\"1.0\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003867 if (cur->encoding != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00003868 xmlBufferWriteChar(buf, " encoding=");
3869 xmlBufferWriteQuotedString(buf, cur->encoding);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003870 }
3871 switch (cur->standalone) {
3872 case 0:
Daniel Veillard5099ae81999-04-21 20:12:07 +00003873 xmlBufferWriteChar(buf, " standalone=\"no\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003874 break;
3875 case 1:
Daniel Veillard5099ae81999-04-21 20:12:07 +00003876 xmlBufferWriteChar(buf, " standalone=\"yes\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003877 break;
3878 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003879 xmlBufferWriteChar(buf, "?>\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003880 if (cur->intSubset != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00003881 xmlDtdDump(buf, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003882 if (cur->root != NULL) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00003883 xmlNodePtr child = cur->root;
3884
Daniel Veillard260a68f1998-08-13 03:39:55 +00003885 /* global namespace definitions, the old way */
3886 if (oldXMLWDcompatibility)
Daniel Veillard5099ae81999-04-21 20:12:07 +00003887 xmlGlobalNsListDump(buf, cur->oldNs);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003888 else
3889 xmlUpgradeOldNs(cur);
Daniel Veillardb96e6431999-08-29 21:02:19 +00003890
3891 while (child != NULL) {
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003892 xmlNodeDump(buf, cur, child, 0, 1);
3893 xmlBufferWriteChar(buf, "\n");
Daniel Veillardb96e6431999-08-29 21:02:19 +00003894 child = child->next;
3895 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003896 }
3897}
3898
Daniel Veillard97b58771998-10-20 06:14:16 +00003899/**
3900 * xmlDocDumpMemory:
3901 * @cur: the document
3902 * @mem: OUT: the memory pointer
3903 * @size: OUT: the memory lenght
3904 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003905 * Dump an XML document in memory and return the xmlChar * and it's size.
Daniel Veillard97b58771998-10-20 06:14:16 +00003906 * It's up to the caller to free the memory.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003907 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003908void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003909xmlDocDumpMemory(xmlDocPtr cur, xmlChar**mem, int *size) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003910 xmlBufferPtr buf;
3911
Daniel Veillard260a68f1998-08-13 03:39:55 +00003912 if (cur == NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003913#ifdef DEBUG_TREE
3914 fprintf(stderr, "xmlDocDumpMemory : document == NULL\n");
3915#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00003916 *mem = NULL;
3917 *size = 0;
3918 return;
3919 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003920 buf = xmlBufferCreate();
3921 if (buf == NULL) {
3922 *mem = NULL;
3923 *size = 0;
3924 return;
3925 }
3926 xmlDocContentDump(buf, cur);
Daniel Veillardb05deb71999-08-10 19:04:08 +00003927 *mem = xmlStrndup(buf->content, buf->use);
Daniel Veillard5099ae81999-04-21 20:12:07 +00003928 *size = buf->use;
Daniel Veillardb05deb71999-08-10 19:04:08 +00003929 xmlBufferFree(buf);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003930}
3931
Daniel Veillard97b58771998-10-20 06:14:16 +00003932/**
3933 * xmlGetDocCompressMode:
3934 * @doc: the document
3935 *
3936 * get the compression ratio for a document, ZLIB based
Daniel Veillard1e346af1999-02-22 10:33:01 +00003937 * Returns 0 (uncompressed) to 9 (max compression)
Daniel Veillard151b1b01998-09-23 00:49:46 +00003938 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003939int
3940 xmlGetDocCompressMode (xmlDocPtr doc) {
Daniel Veillard15a8df41998-09-24 19:15:06 +00003941 if (doc == NULL) return(-1);
3942 return(doc->compression);
3943}
3944
Daniel Veillard97b58771998-10-20 06:14:16 +00003945/**
3946 * xmlSetDocCompressMode:
3947 * @doc: the document
3948 * @mode: the compression ratio
3949 *
3950 * set the compression ratio for a document, ZLIB based
3951 * Correct values: 0 (uncompressed) to 9 (max compression)
3952 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003953void
3954xmlSetDocCompressMode (xmlDocPtr doc, int mode) {
Daniel Veillard15a8df41998-09-24 19:15:06 +00003955 if (doc == NULL) return;
3956 if (mode < 0) doc->compression = 0;
3957 else if (mode > 9) doc->compression = 9;
3958 else doc->compression = mode;
3959}
3960
Daniel Veillard97b58771998-10-20 06:14:16 +00003961/**
3962 * xmlGetCompressMode:
3963 *
3964 * get the default compression mode used, ZLIB based.
Daniel Veillard1e346af1999-02-22 10:33:01 +00003965 * Returns 0 (uncompressed) to 9 (max compression)
Daniel Veillard15a8df41998-09-24 19:15:06 +00003966 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003967int
3968 xmlGetCompressMode(void) {
Daniel Veillard151b1b01998-09-23 00:49:46 +00003969 return(xmlCompressMode);
3970}
Daniel Veillard97b58771998-10-20 06:14:16 +00003971
3972/**
3973 * xmlSetCompressMode:
3974 * @mode: the compression ratio
3975 *
3976 * set the default compression mode used, ZLIB based
3977 * Correct values: 0 (uncompressed) to 9 (max compression)
3978 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003979void
3980xmlSetCompressMode(int mode) {
Daniel Veillard151b1b01998-09-23 00:49:46 +00003981 if (mode < 0) xmlCompressMode = 0;
Daniel Veillard15a8df41998-09-24 19:15:06 +00003982 else if (mode > 9) xmlCompressMode = 9;
Daniel Veillard151b1b01998-09-23 00:49:46 +00003983 else xmlCompressMode = mode;
3984}
3985
Daniel Veillard97b58771998-10-20 06:14:16 +00003986/**
3987 * xmlDocDump:
3988 * @f: the FILE*
3989 * @cur: the document
3990 *
3991 * Dump an XML document to an open FILE.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003992 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003993void
3994xmlDocDump(FILE *f, xmlDocPtr cur) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003995 xmlBufferPtr buf;
3996
Daniel Veillard260a68f1998-08-13 03:39:55 +00003997 if (cur == NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003998#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00003999 fprintf(stderr, "xmlDocDump : document == NULL\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004000#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00004001 return;
4002 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00004003 buf = xmlBufferCreate();
4004 if (buf == NULL) return;
4005 xmlDocContentDump(buf, cur);
4006 xmlBufferDump(f, buf);
4007 xmlBufferFree(buf);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004008}
4009
Daniel Veillard97b58771998-10-20 06:14:16 +00004010/**
4011 * xmlSaveFile:
4012 * @filename: the filename
4013 * @cur: the document
4014 *
4015 * Dump an XML document to a file. Will use compression if
Daniel Veillard11a48ec1999-11-23 10:40:46 +00004016 * compiled in and enabled. If @filename is "-" the stdout file is
4017 * used.
Daniel Veillard97b58771998-10-20 06:14:16 +00004018 * returns: the number of file written or -1 in case of failure.
Daniel Veillard151b1b01998-09-23 00:49:46 +00004019 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00004020int
4021xmlSaveFile(const char *filename, xmlDocPtr cur) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00004022 xmlBufferPtr buf;
Daniel Veillard151b1b01998-09-23 00:49:46 +00004023#ifdef HAVE_ZLIB_H
4024 gzFile zoutput = NULL;
4025 char mode[15];
4026#endif
Daniel Veillardccb09631998-10-27 06:21:04 +00004027 FILE *output = NULL;
Daniel Veillard151b1b01998-09-23 00:49:46 +00004028 int ret;
4029
Daniel Veillard5099ae81999-04-21 20:12:07 +00004030 /*
4031 * save the content to a temp buffer.
4032 */
4033 buf = xmlBufferCreate();
4034 if (buf == NULL) return(0);
4035 xmlDocContentDump(buf, cur);
4036
Daniel Veillard151b1b01998-09-23 00:49:46 +00004037#ifdef HAVE_ZLIB_H
Daniel Veillard11a48ec1999-11-23 10:40:46 +00004038 if (cur->compression < 0) cur->compression = xmlCompressMode;
Daniel Veillarddc3dd9d1998-09-24 19:25:54 +00004039 if ((cur->compression > 0) && (cur->compression <= 9)) {
4040 sprintf(mode, "w%d", cur->compression);
Daniel Veillard11a48ec1999-11-23 10:40:46 +00004041 if (!strcmp(filename, "-"))
4042 zoutput = gzdopen(1, mode);
4043 else
4044 zoutput = gzopen(filename, mode);
Daniel Veillard151b1b01998-09-23 00:49:46 +00004045 }
4046 if (zoutput == NULL) {
4047#endif
4048 output = fopen(filename, "w");
Daniel Veillard10a2c651999-12-12 13:03:50 +00004049 if (output == NULL) {
4050 xmlBufferFree(buf);
4051 return(-1);
4052 }
Daniel Veillard151b1b01998-09-23 00:49:46 +00004053#ifdef HAVE_ZLIB_H
4054 }
Daniel Veillard151b1b01998-09-23 00:49:46 +00004055
Daniel Veillard151b1b01998-09-23 00:49:46 +00004056 if (zoutput != NULL) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004057 ret = gzwrite(zoutput, buf->content, sizeof(xmlChar) * buf->use);
Daniel Veillard151b1b01998-09-23 00:49:46 +00004058 gzclose(zoutput);
Daniel Veillard5099ae81999-04-21 20:12:07 +00004059 } else {
4060#endif
4061 ret = xmlBufferDump(output, buf);
4062 fclose(output);
4063#ifdef HAVE_ZLIB_H
Daniel Veillard151b1b01998-09-23 00:49:46 +00004064 }
4065#endif
Manish Vachharajani5e60f5a1999-05-29 03:04:30 +00004066 xmlBufferFree(buf);
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004067 return(ret * sizeof(xmlChar));
Daniel Veillard151b1b01998-09-23 00:49:46 +00004068}
4069