blob: 83bed92b35548c6c1e54ff6b990be43e8f55f608 [file] [log] [blame]
Daniel Veillard260a68f1998-08-13 03:39:55 +00001/*
2 * tree.c : implemetation of access function for an XML tree.
3 *
4 * See Copyright for the status of this software.
5 *
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00006 * Daniel.Veillard@w3.org
Daniel Veillard260a68f1998-08-13 03:39:55 +00007 */
8
Daniel Veillard7f7d1111999-09-22 09:46:25 +00009#ifdef WIN32
10#define HAVE_FCNTL_H
11#include <io.h>
12#else
Daniel Veillard151b1b01998-09-23 00:49:46 +000013#include "config.h"
Daniel Veillard7f7d1111999-09-22 09:46:25 +000014#endif
15
Daniel Veillard260a68f1998-08-13 03:39:55 +000016#include <stdio.h>
Daniel Veillard260a68f1998-08-13 03:39:55 +000017#include <string.h> /* for memset() only ! */
18
Daniel Veillard7f7d1111999-09-22 09:46:25 +000019#ifdef HAVE_CTYPE_H
20#include <ctype.h>
21#endif
22#ifdef HAVE_STDLIB_H
23#include <stdlib.h>
24#endif
Daniel Veillard151b1b01998-09-23 00:49:46 +000025#ifdef HAVE_ZLIB_H
26#include <zlib.h>
27#endif
28
Daniel Veillard6454aec1999-09-02 22:04:43 +000029#include "xmlmemory.h"
Daniel Veillard260a68f1998-08-13 03:39:55 +000030#include "tree.h"
Daniel Veillard37846c61999-12-16 17:52:19 +000031#include "parser.h"
Daniel Veillard260a68f1998-08-13 03:39:55 +000032#include "entities.h"
Daniel Veillard3b9def11999-01-31 22:15:06 +000033#include "valid.h"
Daniel Veillard260a68f1998-08-13 03:39:55 +000034
Daniel Veillarddd6b3671999-09-23 22:19:22 +000035static xmlChar xmlStringText[] = { 't', 'e', 'x', 't', 0 };
Daniel Veillard260a68f1998-08-13 03:39:55 +000036int oldXMLWDcompatibility = 0;
37int xmlIndentTreeOutput = 1;
Daniel Veillardf5c2c871999-12-01 09:51:45 +000038xmlBufferAllocationScheme xmlBufferAllocScheme = XML_BUFFER_ALLOC_EXACT;
Daniel Veillard260a68f1998-08-13 03:39:55 +000039
Daniel Veillard15a8df41998-09-24 19:15:06 +000040static int xmlCompressMode = 0;
Daniel Veillard10a2c651999-12-12 13:03:50 +000041static int xmlCheckDTD = 1;
Daniel Veillard15a8df41998-09-24 19:15:06 +000042
Daniel Veillard39a1f9a1999-01-17 19:11:59 +000043#define UPDATE_LAST_CHILD(n) if ((n) != NULL) { \
44 xmlNodePtr ulccur = (n)->childs; \
45 if (ulccur == NULL) { \
46 (n)->last = NULL; \
47 } else { \
48 while (ulccur->next != NULL) ulccur = ulccur->next; \
49 (n)->last = ulccur; \
Daniel Veillard1e346af1999-02-22 10:33:01 +000050}}
Daniel Veillard39a1f9a1999-01-17 19:11:59 +000051
Daniel Veillard260a68f1998-08-13 03:39:55 +000052/************************************************************************
53 * *
54 * Allocation and deallocation of basic structures *
55 * *
56 ************************************************************************/
57
Daniel Veillard97b58771998-10-20 06:14:16 +000058/**
Daniel Veillardf5c2c871999-12-01 09:51:45 +000059 * xmlSetBufferAllocationScheme:
60 * @scheme: allocation method to use
61 *
62 * Set the buffer allocation method. Types are
63 * XML_BUFFER_ALLOC_EXACT - use exact sizes, keeps memory usage down
64 * XML_BUFFER_ALLOC_DOUBLEIT - double buffer when extra needed,
65 * improves performance
66 */
67void
68xmlSetBufferAllocationScheme(xmlBufferAllocationScheme scheme) {
69 xmlBufferAllocScheme = scheme;
70}
71
72/**
73 * xmlGetBufferAllocationScheme:
74 *
75 * Types are
76 * XML_BUFFER_ALLOC_EXACT - use exact sizes, keeps memory usage down
77 * XML_BUFFER_ALLOC_DOUBLEIT - double buffer when extra needed,
78 * improves performance
79 *
80 * Returns the current allocation scheme
81 */
82xmlBufferAllocationScheme
83xmlGetBufferAllocationScheme() {
84 return xmlBufferAllocScheme;
85}
86
87/**
Daniel Veillard97b58771998-10-20 06:14:16 +000088 * xmlUpgradeOldNs:
89 * @doc: a document pointer
90 *
91 * Upgrade old style Namespaces (PI) and move them to the root of the document.
Daniel Veillard260a68f1998-08-13 03:39:55 +000092 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +000093void
94xmlUpgradeOldNs(xmlDocPtr doc) {
Daniel Veillard260a68f1998-08-13 03:39:55 +000095 xmlNsPtr cur;
96
97 if ((doc == NULL) || (doc->oldNs == NULL)) return;
98 if (doc->root == NULL) {
99 fprintf(stderr, "xmlUpgradeOldNs: failed no root !\n");
100 return;
101 }
102
103 cur = doc->oldNs;
104 while (cur->next != NULL) {
105 cur->type = XML_LOCAL_NAMESPACE;
106 cur = cur->next;
107 }
108 cur->type = XML_LOCAL_NAMESPACE;
109 cur->next = doc->root->nsDef;
110 doc->root->nsDef = doc->oldNs;
111 doc->oldNs = NULL;
112}
113
Daniel Veillard97b58771998-10-20 06:14:16 +0000114/**
115 * xmlNewNs:
116 * @node: the element carrying the namespace
117 * @href: the URI associated
118 * @prefix: the prefix for the namespace
119 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000120 * Creation of a new Namespace.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000121 * Returns returns a new namespace pointer
Daniel Veillard260a68f1998-08-13 03:39:55 +0000122 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000123xmlNsPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000124xmlNewNs(xmlNodePtr node, const xmlChar *href, const xmlChar *prefix) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000125 xmlNsPtr cur;
126
127 if (href == NULL) {
128 fprintf(stderr, "xmlNewNs: href == NULL !\n");
129 return(NULL);
130 }
131
132 /*
133 * Allocate a new DTD and fill the fields.
134 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000135 cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000136 if (cur == NULL) {
137 fprintf(stderr, "xmlNewNs : malloc failed\n");
138 return(NULL);
139 }
140
141 cur->type = XML_LOCAL_NAMESPACE;
142 if (href != NULL)
143 cur->href = xmlStrdup(href);
144 else
145 cur->href = NULL;
146 if (prefix != NULL)
147 cur->prefix = xmlStrdup(prefix);
148 else
149 cur->prefix = NULL;
150
151 /*
152 * Add it at the end to preserve parsing order ...
153 */
154 cur->next = NULL;
155 if (node != NULL) {
156 if (node->nsDef == NULL) {
157 node->nsDef = cur;
158 } else {
159 xmlNsPtr prev = node->nsDef;
160
161 while (prev->next != NULL) prev = prev->next;
162 prev->next = cur;
163 }
164 }
165
166 return(cur);
167}
168
Daniel Veillard97b58771998-10-20 06:14:16 +0000169/**
170 * xmlNewGlobalNs:
171 * @doc: the document carrying the namespace
172 * @href: the URI associated
173 * @prefix: the prefix for the namespace
174 *
175 * Creation of a Namespace, the old way using PI and without scoping, to AVOID.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000176 * Returns returns a new namespace pointer
Daniel Veillard260a68f1998-08-13 03:39:55 +0000177 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000178xmlNsPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000179xmlNewGlobalNs(xmlDocPtr doc, const xmlChar *href, const xmlChar *prefix) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000180 xmlNsPtr cur;
181
182 /*
183 * Allocate a new DTD and fill the fields.
184 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000185 cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000186 if (cur == NULL) {
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000187 fprintf(stderr, "xmlNewGlobalNs : malloc failed\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +0000188 return(NULL);
189 }
190
191 cur->type = XML_GLOBAL_NAMESPACE;
192 if (href != NULL)
193 cur->href = xmlStrdup(href);
194 else
195 cur->href = NULL;
196 if (prefix != NULL)
197 cur->prefix = xmlStrdup(prefix);
198 else
199 cur->prefix = NULL;
200
201 /*
202 * Add it at the end to preserve parsing order ...
203 */
204 cur->next = NULL;
205 if (doc != NULL) {
206 if (doc->oldNs == NULL) {
207 doc->oldNs = cur;
208 } else {
209 xmlNsPtr prev = doc->oldNs;
210
211 while (prev->next != NULL) prev = prev->next;
212 prev->next = cur;
213 }
214 }
215
216 return(cur);
217}
218
Daniel Veillard97b58771998-10-20 06:14:16 +0000219/**
220 * xmlSetNs:
221 * @node: a node in the document
222 * @ns: a namespace pointer
223 *
224 * Associate a namespace to a node, a posteriori.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000225 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000226void
227xmlSetNs(xmlNodePtr node, xmlNsPtr ns) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000228 if (node == NULL) {
229 fprintf(stderr, "xmlSetNs: node == NULL\n");
230 return;
231 }
232 node->ns = ns;
233}
234
Daniel Veillard97b58771998-10-20 06:14:16 +0000235/**
236 * xmlFreeNs:
237 * @cur: the namespace pointer
238 *
239 * Free up the structures associated to a namespace
Daniel Veillard260a68f1998-08-13 03:39:55 +0000240 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000241void
242xmlFreeNs(xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000243 if (cur == NULL) {
244 fprintf(stderr, "xmlFreeNs : ns == NULL\n");
245 return;
246 }
Daniel Veillard6454aec1999-09-02 22:04:43 +0000247 if (cur->href != NULL) xmlFree((char *) cur->href);
248 if (cur->prefix != NULL) xmlFree((char *) cur->prefix);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000249 memset(cur, -1, sizeof(xmlNs));
Daniel Veillard6454aec1999-09-02 22:04:43 +0000250 xmlFree(cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000251}
252
Daniel Veillard97b58771998-10-20 06:14:16 +0000253/**
254 * xmlFreeNsList:
255 * @cur: the first namespace pointer
256 *
257 * Free up all the structures associated to the chained namespaces.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000258 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000259void
260xmlFreeNsList(xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000261 xmlNsPtr next;
262 if (cur == NULL) {
263 fprintf(stderr, "xmlFreeNsList : ns == NULL\n");
264 return;
265 }
266 while (cur != NULL) {
267 next = cur->next;
268 xmlFreeNs(cur);
269 cur = next;
270 }
271}
272
Daniel Veillard97b58771998-10-20 06:14:16 +0000273/**
274 * xmlNewDtd:
275 * @doc: the document pointer
276 * @name: the DTD name
277 * @ExternalID: the external ID
278 * @SystemID: the system ID
279 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000280 * Creation of a new DTD.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000281 * Returns a pointer to the new DTD structure
Daniel Veillard260a68f1998-08-13 03:39:55 +0000282 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000283xmlDtdPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000284xmlNewDtd(xmlDocPtr doc, const xmlChar *name,
285 const xmlChar *ExternalID, const xmlChar *SystemID) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000286 xmlDtdPtr cur;
287
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000288 if ((doc != NULL) && (doc->extSubset != NULL)) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000289 fprintf(stderr, "xmlNewDtd(%s): document %s already have a DTD %s\n",
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000290 /* !!! */ (char *) name, doc->name,
291 /* !!! */ (char *)doc->extSubset->name);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000292 }
293
294 /*
295 * Allocate a new DTD and fill the fields.
296 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000297 cur = (xmlDtdPtr) xmlMalloc(sizeof(xmlDtd));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000298 if (cur == NULL) {
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000299 fprintf(stderr, "xmlNewDtd : malloc failed\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +0000300 return(NULL);
301 }
302
303 if (name != NULL)
304 cur->name = xmlStrdup(name);
305 else
306 cur->name = NULL;
307 if (ExternalID != NULL)
308 cur->ExternalID = xmlStrdup(ExternalID);
309 else
310 cur->ExternalID = NULL;
311 if (SystemID != NULL)
312 cur->SystemID = xmlStrdup(SystemID);
313 else
314 cur->SystemID = NULL;
Daniel Veillard1e346af1999-02-22 10:33:01 +0000315 cur->notations = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000316 cur->elements = NULL;
Daniel Veillard1e346af1999-02-22 10:33:01 +0000317 cur->attributes = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000318 cur->entities = NULL;
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000319 if (doc != NULL)
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000320 doc->extSubset = cur;
321
322 return(cur);
323}
324
325/**
326 * xmlCreateIntSubset:
327 * @doc: the document pointer
328 * @name: the DTD name
329 * @ExternalID: the external ID
330 * @SystemID: the system ID
331 *
Daniel Veillard1e346af1999-02-22 10:33:01 +0000332 * Create the internal subset of a document
333 * Returns a pointer to the new DTD structure
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000334 */
335xmlDtdPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000336xmlCreateIntSubset(xmlDocPtr doc, const xmlChar *name,
337 const xmlChar *ExternalID, const xmlChar *SystemID) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000338 xmlDtdPtr cur;
339
340 if ((doc != NULL) && (doc->intSubset != NULL)) {
341 fprintf(stderr,
342 "xmlCreateIntSubset(): document %s already have an internal subset\n",
343 doc->name);
344 return(NULL);
345 }
346
347 /*
348 * Allocate a new DTD and fill the fields.
349 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000350 cur = (xmlDtdPtr) xmlMalloc(sizeof(xmlDtd));
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000351 if (cur == NULL) {
352 fprintf(stderr, "xmlNewDtd : malloc failed\n");
353 return(NULL);
354 }
355
356 if (name != NULL)
357 cur->name = xmlStrdup(name);
358 else
359 cur->name = NULL;
360 if (ExternalID != NULL)
361 cur->ExternalID = xmlStrdup(ExternalID);
362 else
363 cur->ExternalID = NULL;
364 if (SystemID != NULL)
365 cur->SystemID = xmlStrdup(SystemID);
366 else
367 cur->SystemID = NULL;
Daniel Veillard1e346af1999-02-22 10:33:01 +0000368 cur->notations = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000369 cur->elements = NULL;
Daniel Veillard1e346af1999-02-22 10:33:01 +0000370 cur->attributes = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000371 cur->entities = NULL;
372 if (doc != NULL)
373 doc->intSubset = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000374
375 return(cur);
376}
377
Daniel Veillard97b58771998-10-20 06:14:16 +0000378/**
379 * xmlFreeDtd:
380 * @cur: the DTD structure to free up
381 *
382 * Free a DTD structure.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000383 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000384void
385xmlFreeDtd(xmlDtdPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000386 if (cur == NULL) {
387 fprintf(stderr, "xmlFreeDtd : DTD == NULL\n");
388 return;
389 }
Daniel Veillard6454aec1999-09-02 22:04:43 +0000390 if (cur->name != NULL) xmlFree((char *) cur->name);
391 if (cur->SystemID != NULL) xmlFree((char *) cur->SystemID);
392 if (cur->ExternalID != NULL) xmlFree((char *) cur->ExternalID);
Daniel Veillard1e346af1999-02-22 10:33:01 +0000393 if (cur->notations != NULL)
394 xmlFreeNotationTable((xmlNotationTablePtr) cur->notations);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000395 if (cur->elements != NULL)
Daniel Veillard3b9def11999-01-31 22:15:06 +0000396 xmlFreeElementTable((xmlElementTablePtr) cur->elements);
Daniel Veillard1e346af1999-02-22 10:33:01 +0000397 if (cur->attributes != NULL)
398 xmlFreeAttributeTable((xmlAttributeTablePtr) cur->attributes);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000399 if (cur->entities != NULL)
400 xmlFreeEntitiesTable((xmlEntitiesTablePtr) cur->entities);
401 memset(cur, -1, sizeof(xmlDtd));
Daniel Veillard6454aec1999-09-02 22:04:43 +0000402 xmlFree(cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000403}
404
Daniel Veillard97b58771998-10-20 06:14:16 +0000405/**
406 * xmlNewDoc:
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000407 * @version: xmlChar string giving the version of XML "1.0"
Daniel Veillard97b58771998-10-20 06:14:16 +0000408 *
Daniel Veillard1e346af1999-02-22 10:33:01 +0000409 * Returns a new document
Daniel Veillard260a68f1998-08-13 03:39:55 +0000410 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000411xmlDocPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000412xmlNewDoc(const xmlChar *version) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000413 xmlDocPtr cur;
414
415 if (version == NULL) {
416 fprintf(stderr, "xmlNewDoc : version == NULL\n");
417 return(NULL);
418 }
419
420 /*
421 * Allocate a new document and fill the fields.
422 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000423 cur = (xmlDocPtr) xmlMalloc(sizeof(xmlDoc));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000424 if (cur == NULL) {
425 fprintf(stderr, "xmlNewDoc : malloc failed\n");
426 return(NULL);
427 }
428
Daniel Veillard33942841998-10-18 19:12:41 +0000429 cur->type = XML_DOCUMENT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000430 cur->version = xmlStrdup(version);
431 cur->name = NULL;
432 cur->root = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000433 cur->intSubset = NULL;
434 cur->extSubset = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000435 cur->oldNs = NULL;
436 cur->encoding = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000437 cur->standalone = -1;
Daniel Veillard11a48ec1999-11-23 10:40:46 +0000438 cur->compression = -1; /* not initialized */
Daniel Veillardb96e6431999-08-29 21:02:19 +0000439 cur->ids = NULL;
Daniel Veillardc08a2c61999-09-08 21:35:25 +0000440 cur->refs = NULL;
Daniel Veillard27d88741999-05-29 11:51:49 +0000441#ifndef XML_WITHOUT_CORBA
Daniel Veillard27fb0751998-10-17 06:47:46 +0000442 cur->_private = NULL;
443 cur->vepv = NULL;
444#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000445 return(cur);
446}
447
Daniel Veillard97b58771998-10-20 06:14:16 +0000448/**
449 * xmlFreeDoc:
450 * @cur: pointer to the document
451 * @:
452 *
453 * Free up all the structures used by a document, tree included.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000454 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000455void
456xmlFreeDoc(xmlDocPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000457 if (cur == NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000458#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +0000459 fprintf(stderr, "xmlFreeDoc : document == NULL\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000460#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000461 return;
462 }
Daniel Veillard6454aec1999-09-02 22:04:43 +0000463 if (cur->version != NULL) xmlFree((char *) cur->version);
464 if (cur->name != NULL) xmlFree((char *) cur->name);
465 if (cur->encoding != NULL) xmlFree((char *) cur->encoding);
466 if (cur->root != NULL) xmlFreeNodeList(cur->root);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000467 if (cur->intSubset != NULL) xmlFreeDtd(cur->intSubset);
468 if (cur->extSubset != NULL) xmlFreeDtd(cur->extSubset);
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000469 if (cur->oldNs != NULL) xmlFreeNsList(cur->oldNs);
Daniel Veillardb96e6431999-08-29 21:02:19 +0000470 if (cur->ids != NULL) xmlFreeIDTable((xmlIDTablePtr) cur->ids);
Daniel Veillardc08a2c61999-09-08 21:35:25 +0000471 if (cur->refs != NULL) xmlFreeRefTable((xmlRefTablePtr) cur->refs);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000472 memset(cur, -1, sizeof(xmlDoc));
Daniel Veillard6454aec1999-09-02 22:04:43 +0000473 xmlFree(cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000474}
475
Daniel Veillard97b58771998-10-20 06:14:16 +0000476/**
Daniel Veillard16253641998-10-28 22:58:05 +0000477 * xmlStringLenGetNodeList:
478 * @doc: the document
479 * @value: the value of the text
Daniel Veillard1e346af1999-02-22 10:33:01 +0000480 * @len: the length of the string value
Daniel Veillard16253641998-10-28 22:58:05 +0000481 *
482 * Parse the value string and build the node list associated. Should
483 * produce a flat tree with only TEXTs and ENTITY_REFs.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000484 * Returns a pointer to the first child
Daniel Veillard16253641998-10-28 22:58:05 +0000485 */
486xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000487xmlStringLenGetNodeList(xmlDocPtr doc, const xmlChar *value, int len) {
Daniel Veillard16253641998-10-28 22:58:05 +0000488 xmlNodePtr ret = NULL, last = NULL;
489 xmlNodePtr node;
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000490 xmlChar *val;
491 const xmlChar *cur = value;
492 const xmlChar *q;
Daniel Veillard25940b71998-10-29 05:51:30 +0000493 xmlEntityPtr ent;
Daniel Veillard16253641998-10-28 22:58:05 +0000494
495 if (value == NULL) return(NULL);
496
497 q = cur;
498 while ((*cur != 0) && (cur - value < len)) {
499 if (*cur == '&') {
Daniel Veillard25940b71998-10-29 05:51:30 +0000500 /*
501 * Save the current text.
502 */
Daniel Veillard16253641998-10-28 22:58:05 +0000503 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000504 if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
505 xmlNodeAddContentLen(last, q, cur - q);
506 } else {
507 node = xmlNewDocTextLen(doc, q, cur - q);
508 if (node == NULL) return(ret);
509 if (last == NULL)
510 last = ret = node;
511 else {
512 last->next = node;
513 node->prev = last;
514 last = node;
515 }
Daniel Veillard16253641998-10-28 22:58:05 +0000516 }
517 }
Daniel Veillard25940b71998-10-29 05:51:30 +0000518 /*
519 * Read the entity string
520 */
Daniel Veillard16253641998-10-28 22:58:05 +0000521 cur++;
522 q = cur;
523 while ((*cur != 0) && (cur - value < len) && (*cur != ';')) cur++;
524 if ((*cur == 0) || (cur - value >= len)) {
525 fprintf(stderr,
Daniel Veillard011b63c1999-06-02 17:44:04 +0000526 "xmlStringLenGetNodeList: unterminated entity %30s\n", q);
Daniel Veillard16253641998-10-28 22:58:05 +0000527 return(ret);
528 }
529 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000530 /*
531 * Predefined entities don't generate nodes
532 */
Daniel Veillard16253641998-10-28 22:58:05 +0000533 val = xmlStrndup(q, cur - q);
Daniel Veillard25940b71998-10-29 05:51:30 +0000534 ent = xmlGetDocEntity(doc, val);
535 if ((ent != NULL) &&
536 (ent->type == XML_INTERNAL_PREDEFINED_ENTITY)) {
537 if (last == NULL) {
538 node = xmlNewDocText(doc, ent->content);
539 last = ret = node;
540 } else
541 xmlNodeAddContent(last, ent->content);
542
543 } else {
544 /*
545 * Create a new REFERENCE_REF node
546 */
547 node = xmlNewReference(doc, val);
Daniel Veillard242590e1998-11-13 18:04:35 +0000548 if (node == NULL) {
Daniel Veillard6454aec1999-09-02 22:04:43 +0000549 if (val != NULL) xmlFree(val);
Daniel Veillard242590e1998-11-13 18:04:35 +0000550 return(ret);
551 }
Daniel Veillard25940b71998-10-29 05:51:30 +0000552 if (last == NULL)
553 last = ret = node;
554 else {
555 last->next = node;
556 node->prev = last;
557 last = node;
558 }
Daniel Veillard16253641998-10-28 22:58:05 +0000559 }
Daniel Veillard6454aec1999-09-02 22:04:43 +0000560 xmlFree(val);
Daniel Veillard16253641998-10-28 22:58:05 +0000561 }
562 cur++;
563 q = cur;
564 } else
565 cur++;
566 }
567 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000568 /*
569 * Handle the last piece of text.
570 */
571 if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
572 xmlNodeAddContentLen(last, q, cur - q);
573 } else {
574 node = xmlNewDocTextLen(doc, q, cur - q);
575 if (node == NULL) return(ret);
576 if (last == NULL)
577 last = ret = node;
578 else {
579 last->next = node;
580 node->prev = last;
581 last = node;
582 }
Daniel Veillard16253641998-10-28 22:58:05 +0000583 }
584 }
585 return(ret);
586}
587
588/**
Daniel Veillardccb09631998-10-27 06:21:04 +0000589 * xmlStringGetNodeList:
590 * @doc: the document
591 * @value: the value of the attribute
592 *
593 * Parse the value string and build the node list associated. Should
594 * produce a flat tree with only TEXTs and ENTITY_REFs.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000595 * Returns a pointer to the first child
Daniel Veillardccb09631998-10-27 06:21:04 +0000596 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000597xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000598xmlStringGetNodeList(xmlDocPtr doc, const xmlChar *value) {
Daniel Veillardccb09631998-10-27 06:21:04 +0000599 xmlNodePtr ret = NULL, last = NULL;
600 xmlNodePtr node;
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000601 xmlChar *val;
602 const xmlChar *cur = value;
603 const xmlChar *q;
Daniel Veillard25940b71998-10-29 05:51:30 +0000604 xmlEntityPtr ent;
Daniel Veillardccb09631998-10-27 06:21:04 +0000605
606 if (value == NULL) return(NULL);
607
608 q = cur;
609 while (*cur != 0) {
610 if (*cur == '&') {
Daniel Veillard25940b71998-10-29 05:51:30 +0000611 /*
612 * Save the current text.
613 */
Daniel Veillardccb09631998-10-27 06:21:04 +0000614 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000615 if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
616 xmlNodeAddContentLen(last, q, cur - q);
617 } else {
618 node = xmlNewDocTextLen(doc, q, cur - q);
619 if (node == NULL) return(ret);
620 if (last == NULL)
621 last = ret = node;
622 else {
623 last->next = node;
624 node->prev = last;
625 last = node;
626 }
Daniel Veillardccb09631998-10-27 06:21:04 +0000627 }
628 }
Daniel Veillard25940b71998-10-29 05:51:30 +0000629 /*
630 * Read the entity string
631 */
Daniel Veillardccb09631998-10-27 06:21:04 +0000632 cur++;
633 q = cur;
634 while ((*cur != 0) && (*cur != ';')) cur++;
635 if (*cur == 0) {
636 fprintf(stderr,
637 "xmlStringGetNodeList: unterminated entity %30s\n", q);
638 return(ret);
639 }
640 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000641 /*
642 * Predefined entities don't generate nodes
643 */
Daniel Veillardccb09631998-10-27 06:21:04 +0000644 val = xmlStrndup(q, cur - q);
Daniel Veillard25940b71998-10-29 05:51:30 +0000645 ent = xmlGetDocEntity(doc, val);
646 if ((ent != NULL) &&
647 (ent->type == XML_INTERNAL_PREDEFINED_ENTITY)) {
648 if (last == NULL) {
649 node = xmlNewDocText(doc, ent->content);
650 last = ret = node;
651 } else
652 xmlNodeAddContent(last, ent->content);
653
654 } else {
655 /*
656 * Create a new REFERENCE_REF node
657 */
Daniel Veillard25940b71998-10-29 05:51:30 +0000658 node = xmlNewReference(doc, val);
Daniel Veillard242590e1998-11-13 18:04:35 +0000659 if (node == NULL) {
Daniel Veillard6454aec1999-09-02 22:04:43 +0000660 if (val != NULL) xmlFree(val);
Daniel Veillard242590e1998-11-13 18:04:35 +0000661 return(ret);
662 }
Daniel Veillard25940b71998-10-29 05:51:30 +0000663 if (last == NULL)
664 last = ret = node;
665 else {
666 last->next = node;
667 node->prev = last;
668 last = node;
669 }
Daniel Veillardccb09631998-10-27 06:21:04 +0000670 }
Daniel Veillard6454aec1999-09-02 22:04:43 +0000671 xmlFree(val);
Daniel Veillardccb09631998-10-27 06:21:04 +0000672 }
673 cur++;
674 q = cur;
675 } else
676 cur++;
677 }
678 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000679 /*
680 * Handle the last piece of text.
681 */
682 if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
683 xmlNodeAddContentLen(last, q, cur - q);
684 } else {
685 node = xmlNewDocTextLen(doc, q, cur - q);
686 if (node == NULL) return(ret);
687 if (last == NULL)
688 last = ret = node;
689 else {
690 last->next = node;
691 node->prev = last;
692 last = node;
693 }
Daniel Veillardccb09631998-10-27 06:21:04 +0000694 }
695 }
696 return(ret);
697}
698
699/**
700 * xmlNodeListGetString:
701 * @doc: the document
702 * @list: a Node list
703 * @inLine: should we replace entity contents or show their external form
704 *
705 * Returns the string equivalent to the text contained in the Node list
706 * made of TEXTs and ENTITY_REFs
Daniel Veillard1e346af1999-02-22 10:33:01 +0000707 * Returns a pointer to the string copy, the calller must free it.
Daniel Veillardccb09631998-10-27 06:21:04 +0000708 */
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000709xmlChar *
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000710xmlNodeListGetString(xmlDocPtr doc, xmlNodePtr list, int inLine) {
Daniel Veillardccb09631998-10-27 06:21:04 +0000711 xmlNodePtr node = list;
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000712 xmlChar *ret = NULL;
Daniel Veillardccb09631998-10-27 06:21:04 +0000713 xmlEntityPtr ent;
714
715 if (list == NULL) return(NULL);
716
717 while (node != NULL) {
718 if (node->type == XML_TEXT_NODE) {
Daniel Veillardf5c2c871999-12-01 09:51:45 +0000719 if ((inLine) || (doc->type == XML_HTML_DOCUMENT_NODE)) {
720#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardccb09631998-10-27 06:21:04 +0000721 ret = xmlStrcat(ret, node->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +0000722#else
723 ret = xmlStrcat(ret, xmlBufferContent(node->content));
724#endif
725 } else {
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000726 xmlChar *buffer;
Daniel Veillard14fff061999-06-22 21:49:07 +0000727
Daniel Veillardf5c2c871999-12-01 09:51:45 +0000728#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard14fff061999-06-22 21:49:07 +0000729 buffer = xmlEncodeEntitiesReentrant(doc, node->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +0000730#else
731 buffer = xmlEncodeEntitiesReentrant(doc,
732 xmlBufferContent(node->content));
733#endif
Daniel Veillard14fff061999-06-22 21:49:07 +0000734 if (buffer != NULL) {
735 ret = xmlStrcat(ret, buffer);
Daniel Veillard6454aec1999-09-02 22:04:43 +0000736 xmlFree(buffer);
Daniel Veillard14fff061999-06-22 21:49:07 +0000737 }
738 }
Daniel Veillardccb09631998-10-27 06:21:04 +0000739 } else if (node->type == XML_ENTITY_REF_NODE) {
740 if (inLine) {
741 ent = xmlGetDocEntity(doc, node->name);
742 if (ent != NULL)
743 ret = xmlStrcat(ret, ent->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +0000744 else {
745#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardccb09631998-10-27 06:21:04 +0000746 ret = xmlStrcat(ret, node->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +0000747#else
748 ret = xmlStrcat(ret, xmlBufferContent(node->content));
749#endif
750 }
Daniel Veillardccb09631998-10-27 06:21:04 +0000751 } else {
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000752 xmlChar buf[2];
Daniel Veillardccb09631998-10-27 06:21:04 +0000753 buf[0] = '&'; buf[1] = 0;
754 ret = xmlStrncat(ret, buf, 1);
755 ret = xmlStrcat(ret, node->name);
756 buf[0] = ';'; buf[1] = 0;
757 ret = xmlStrncat(ret, buf, 1);
758 }
759 }
760#if 0
761 else {
762 fprintf(stderr, "xmlGetNodeListString : invalide node type %d\n",
763 node->type);
764 }
765#endif
766 node = node->next;
767 }
768 return(ret);
769}
770
771/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000772 * xmlNewProp:
773 * @node: the holding node
774 * @name: the name of the attribute
775 * @value: the value of the attribute
776 *
777 * Create a new property carried by a node.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000778 * Returns a pointer to the attribute
Daniel Veillard260a68f1998-08-13 03:39:55 +0000779 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000780xmlAttrPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000781xmlNewProp(xmlNodePtr node, const xmlChar *name, const xmlChar *value) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000782 xmlAttrPtr cur;
783
784 if (name == NULL) {
785 fprintf(stderr, "xmlNewProp : name == NULL\n");
786 return(NULL);
787 }
788
789 /*
790 * Allocate a new property and fill the fields.
791 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000792 cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000793 if (cur == NULL) {
794 fprintf(stderr, "xmlNewProp : malloc failed\n");
795 return(NULL);
796 }
797
Daniel Veillard33942841998-10-18 19:12:41 +0000798 cur->type = XML_ATTRIBUTE_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000799 cur->node = node;
Daniel Veillardb96e6431999-08-29 21:02:19 +0000800 cur->ns = NULL;
801 cur->name = xmlStrdup(name);
Daniel Veillard51e3b151999-11-12 17:02:31 +0000802 if (value != NULL) {
803 xmlChar *buffer;
804 buffer = xmlEncodeEntitiesReentrant(node->doc, value);
805 cur->val = xmlStringGetNodeList(node->doc, buffer);
806 xmlFree(buffer);
807 }
Daniel Veillardb96e6431999-08-29 21:02:19 +0000808 else
809 cur->val = NULL;
810#ifndef XML_WITHOUT_CORBA
811 cur->_private = NULL;
812 cur->vepv = NULL;
813#endif
814
815 /*
816 * Add it at the end to preserve parsing order ...
817 */
818 cur->next = NULL;
819 if (node != NULL) {
820 if (node->properties == NULL) {
821 node->properties = cur;
822 } else {
823 xmlAttrPtr prev = node->properties;
824
825 while (prev->next != NULL) prev = prev->next;
826 prev->next = cur;
827 }
828 }
Daniel Veillard00fdf371999-10-08 09:40:39 +0000829#ifndef XML_WITHOUT_CORBA
830 cur->_private = NULL;
831 cur->vepv = NULL;
832#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +0000833 return(cur);
834}
835
836/**
837 * xmlNewNsProp:
838 * @node: the holding node
839 * @ns: the namespace
840 * @name: the name of the attribute
841 * @value: the value of the attribute
842 *
843 * Create a new property tagged with a namespace and carried by a node.
844 * Returns a pointer to the attribute
845 */
846xmlAttrPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000847xmlNewNsProp(xmlNodePtr node, xmlNsPtr ns, const xmlChar *name,
848 const xmlChar *value) {
Daniel Veillardb96e6431999-08-29 21:02:19 +0000849 xmlAttrPtr cur;
850
851 if (name == NULL) {
852 fprintf(stderr, "xmlNewProp : name == NULL\n");
853 return(NULL);
854 }
855
856 /*
857 * Allocate a new property and fill the fields.
858 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000859 cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr));
Daniel Veillardb96e6431999-08-29 21:02:19 +0000860 if (cur == NULL) {
861 fprintf(stderr, "xmlNewProp : malloc failed\n");
862 return(NULL);
863 }
864
865 cur->type = XML_ATTRIBUTE_NODE;
866 cur->node = node;
867 cur->ns = ns;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000868 cur->name = xmlStrdup(name);
869 if (value != NULL)
Daniel Veillardccb09631998-10-27 06:21:04 +0000870 cur->val = xmlStringGetNodeList(node->doc, value);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000871 else
Daniel Veillardccb09631998-10-27 06:21:04 +0000872 cur->val = NULL;
Daniel Veillard27d88741999-05-29 11:51:49 +0000873#ifndef XML_WITHOUT_CORBA
Daniel Veillard27fb0751998-10-17 06:47:46 +0000874 cur->_private = NULL;
875 cur->vepv = NULL;
876#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000877
878 /*
879 * Add it at the end to preserve parsing order ...
880 */
881 cur->next = NULL;
882 if (node != NULL) {
883 if (node->properties == NULL) {
884 node->properties = cur;
885 } else {
886 xmlAttrPtr prev = node->properties;
887
888 while (prev->next != NULL) prev = prev->next;
889 prev->next = cur;
890 }
891 }
892 return(cur);
893}
894
Daniel Veillard97b58771998-10-20 06:14:16 +0000895/**
Daniel Veillardccb09631998-10-27 06:21:04 +0000896 * xmlNewDocProp:
897 * @doc: the document
898 * @name: the name of the attribute
899 * @value: the value of the attribute
900 *
901 * Create a new property carried by a document.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000902 * Returns a pointer to the attribute
Daniel Veillardccb09631998-10-27 06:21:04 +0000903 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000904xmlAttrPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000905xmlNewDocProp(xmlDocPtr doc, const xmlChar *name, const xmlChar *value) {
Daniel Veillardccb09631998-10-27 06:21:04 +0000906 xmlAttrPtr cur;
907
908 if (name == NULL) {
909 fprintf(stderr, "xmlNewProp : name == NULL\n");
910 return(NULL);
911 }
912
913 /*
914 * Allocate a new property and fill the fields.
915 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000916 cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr));
Daniel Veillardccb09631998-10-27 06:21:04 +0000917 if (cur == NULL) {
918 fprintf(stderr, "xmlNewProp : malloc failed\n");
919 return(NULL);
920 }
921
922 cur->type = XML_ATTRIBUTE_NODE;
923 cur->node = NULL;
924 cur->name = xmlStrdup(name);
925 if (value != NULL)
926 cur->val = xmlStringGetNodeList(doc, value);
927 else
928 cur->val = NULL;
Daniel Veillard27d88741999-05-29 11:51:49 +0000929#ifndef XML_WITHOUT_CORBA
Daniel Veillardccb09631998-10-27 06:21:04 +0000930 cur->_private = NULL;
931 cur->vepv = NULL;
932#endif
933
934 cur->next = NULL;
935 return(cur);
936}
937
938/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000939 * xmlFreePropList:
940 * @cur: the first property in the list
941 *
942 * Free a property and all its siblings, all the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000943 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000944void
945xmlFreePropList(xmlAttrPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000946 xmlAttrPtr next;
947 if (cur == NULL) {
948 fprintf(stderr, "xmlFreePropList : property == NULL\n");
949 return;
950 }
951 while (cur != NULL) {
952 next = cur->next;
953 xmlFreeProp(cur);
954 cur = next;
955 }
956}
957
Daniel Veillard97b58771998-10-20 06:14:16 +0000958/**
959 * xmlFreeProp:
960 * @cur: the first property in the list
961 *
962 * Free one property, all the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000963 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000964void
965xmlFreeProp(xmlAttrPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000966 if (cur == NULL) {
967 fprintf(stderr, "xmlFreeProp : property == NULL\n");
968 return;
969 }
Daniel Veillard6454aec1999-09-02 22:04:43 +0000970 if (cur->name != NULL) xmlFree((char *) cur->name);
Daniel Veillardccb09631998-10-27 06:21:04 +0000971 if (cur->val != NULL) xmlFreeNodeList(cur->val);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000972 memset(cur, -1, sizeof(xmlAttr));
Daniel Veillard6454aec1999-09-02 22:04:43 +0000973 xmlFree(cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000974}
975
Daniel Veillard97b58771998-10-20 06:14:16 +0000976/**
Daniel Veillardb96e6431999-08-29 21:02:19 +0000977 * xmlNewPI:
978 * @name: the processing instruction name
979 * @content: the PI content
980 *
981 * Creation of a processing instruction element.
982 * Returns a pointer to the new node object.
983 */
984xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000985xmlNewPI(const xmlChar *name, const xmlChar *content) {
Daniel Veillardb96e6431999-08-29 21:02:19 +0000986 xmlNodePtr cur;
987
988 if (name == NULL) {
989 fprintf(stderr, "xmlNewPI : name == NULL\n");
990 return(NULL);
991 }
992
993 /*
994 * Allocate a new node and fill the fields.
995 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000996 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillardb96e6431999-08-29 21:02:19 +0000997 if (cur == NULL) {
998 fprintf(stderr, "xmlNewPI : malloc failed\n");
999 return(NULL);
1000 }
1001
1002 cur->type = XML_PI_NODE;
1003 cur->doc = NULL;
1004 cur->parent = NULL;
1005 cur->next = NULL;
1006 cur->prev = NULL;
1007 cur->childs = NULL;
1008 cur->last = NULL;
1009 cur->properties = NULL;
1010 cur->name = xmlStrdup(name);
1011 cur->ns = NULL;
1012 cur->nsDef = NULL;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001013 if (content != NULL) {
1014#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardb96e6431999-08-29 21:02:19 +00001015 cur->content = xmlStrdup(content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001016#else
1017 cur->content = xmlBufferCreateSize(0);
1018 xmlBufferSetAllocationScheme(cur->content,
1019 xmlGetBufferAllocationScheme());
1020 xmlBufferAdd(cur->content, content, -1);
1021#endif
1022 } else
Daniel Veillardb96e6431999-08-29 21:02:19 +00001023 cur->content = NULL;
1024#ifndef XML_WITHOUT_CORBA
1025 cur->_private = NULL;
1026 cur->vepv = NULL;
1027#endif
1028 return(cur);
1029}
1030
1031/**
Daniel Veillard97b58771998-10-20 06:14:16 +00001032 * xmlNewNode:
1033 * @ns: namespace if any
1034 * @name: the node name
Daniel Veillard97b58771998-10-20 06:14:16 +00001035 *
1036 * Creation of a new node element. @ns and @content are optionnal (NULL).
Daniel Veillardccb09631998-10-27 06:21:04 +00001037 * If content is non NULL, a child list containing the TEXTs and
1038 * ENTITY_REFs node will be created.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001039 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001040 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001041xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001042xmlNewNode(xmlNsPtr ns, const xmlChar *name) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001043 xmlNodePtr cur;
1044
1045 if (name == NULL) {
1046 fprintf(stderr, "xmlNewNode : name == NULL\n");
1047 return(NULL);
1048 }
1049
1050 /*
1051 * Allocate a new node and fill the fields.
1052 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001053 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillard260a68f1998-08-13 03:39:55 +00001054 if (cur == NULL) {
1055 fprintf(stderr, "xmlNewNode : malloc failed\n");
1056 return(NULL);
1057 }
1058
Daniel Veillard33942841998-10-18 19:12:41 +00001059 cur->type = XML_ELEMENT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001060 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001061 cur->parent = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001062 cur->next = NULL;
1063 cur->prev = NULL;
1064 cur->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001065 cur->last = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001066 cur->properties = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001067 cur->name = xmlStrdup(name);
1068 cur->ns = ns;
1069 cur->nsDef = NULL;
Daniel Veillardccb09631998-10-27 06:21:04 +00001070 cur->content = NULL;
Daniel Veillard27d88741999-05-29 11:51:49 +00001071#ifndef XML_WITHOUT_CORBA
Daniel Veillard27fb0751998-10-17 06:47:46 +00001072 cur->_private = NULL;
1073 cur->vepv = NULL;
1074#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001075 return(cur);
1076}
1077
Daniel Veillard97b58771998-10-20 06:14:16 +00001078/**
1079 * xmlNewDocNode:
1080 * @doc: the document
1081 * @ns: namespace if any
1082 * @name: the node name
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001083 * @content: the XML text content if any
Daniel Veillard97b58771998-10-20 06:14:16 +00001084 *
1085 * Creation of a new node element within a document. @ns and @content
1086 * are optionnal (NULL).
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001087 * NOTE: @content is supposed to be a piece of XML CDATA, so it allow entities
1088 * references, but XML special chars need to be escaped first by using
1089 * xmlEncodeEntitiesReentrant(). Use xmlNewDocRawNode() if you don't
1090 * need entities support.
1091 *
Daniel Veillard1e346af1999-02-22 10:33:01 +00001092 * Returns a pointer to the new node object.
Daniel Veillard97b58771998-10-20 06:14:16 +00001093 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001094xmlNodePtr
1095xmlNewDocNode(xmlDocPtr doc, xmlNsPtr ns,
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001096 const xmlChar *name, const xmlChar *content) {
Daniel Veillard0bef1311998-10-14 02:36:47 +00001097 xmlNodePtr cur;
1098
Daniel Veillardccb09631998-10-27 06:21:04 +00001099 cur = xmlNewNode(ns, name);
1100 if (cur != NULL) {
1101 cur->doc = doc;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001102 if (content != NULL) {
Daniel Veillardccb09631998-10-27 06:21:04 +00001103 cur->childs = xmlStringGetNodeList(doc, content);
Daniel Veillard1e346af1999-02-22 10:33:01 +00001104 UPDATE_LAST_CHILD(cur)
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001105 }
Daniel Veillardccb09631998-10-27 06:21:04 +00001106 }
Daniel Veillard0bef1311998-10-14 02:36:47 +00001107 return(cur);
1108}
1109
1110
Daniel Veillard97b58771998-10-20 06:14:16 +00001111/**
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001112 * xmlNewDocRawNode:
1113 * @doc: the document
1114 * @ns: namespace if any
1115 * @name: the node name
1116 * @content: the text content if any
1117 *
1118 * Creation of a new node element within a document. @ns and @content
1119 * are optionnal (NULL).
1120 *
1121 * Returns a pointer to the new node object.
1122 */
1123xmlNodePtr
1124xmlNewDocRawNode(xmlDocPtr doc, xmlNsPtr ns,
1125 const xmlChar *name, const xmlChar *content) {
1126 xmlNodePtr cur;
1127
1128 cur = xmlNewNode(ns, name);
1129 if (cur != NULL) {
1130 cur->doc = doc;
1131 if (content != NULL) {
1132 cur->childs = xmlNewDocText(doc, content);
1133 UPDATE_LAST_CHILD(cur)
1134 }
1135 }
1136 return(cur);
1137}
1138
1139
1140/**
Daniel Veillard97b58771998-10-20 06:14:16 +00001141 * xmlNewText:
1142 * @content: the text content
1143 *
1144 * Creation of a new text node.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001145 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001146 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001147xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001148xmlNewText(const xmlChar *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001149 xmlNodePtr cur;
1150
1151 /*
1152 * Allocate a new node and fill the fields.
1153 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001154 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillard260a68f1998-08-13 03:39:55 +00001155 if (cur == NULL) {
1156 fprintf(stderr, "xmlNewText : malloc failed\n");
1157 return(NULL);
1158 }
1159
Daniel Veillard33942841998-10-18 19:12:41 +00001160 cur->type = XML_TEXT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001161 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001162 cur->parent = NULL;
1163 cur->next = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001164 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001165 cur->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001166 cur->last = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001167 cur->properties = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001168 cur->type = XML_TEXT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001169 cur->name = xmlStrdup(xmlStringText);
1170 cur->ns = NULL;
1171 cur->nsDef = NULL;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001172 if (content != NULL) {
1173#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard260a68f1998-08-13 03:39:55 +00001174 cur->content = xmlStrdup(content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001175#else
1176 cur->content = xmlBufferCreateSize(0);
1177 xmlBufferSetAllocationScheme(cur->content,
1178 xmlGetBufferAllocationScheme());
1179 xmlBufferAdd(cur->content, content, -1);
1180#endif
1181 } else
Daniel Veillard260a68f1998-08-13 03:39:55 +00001182 cur->content = NULL;
Daniel Veillard00fdf371999-10-08 09:40:39 +00001183#ifndef XML_WITHOUT_CORBA
1184 cur->_private = NULL;
1185 cur->vepv = NULL;
1186#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001187 return(cur);
1188}
1189
Daniel Veillard97b58771998-10-20 06:14:16 +00001190/**
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001191 * xmlNewTextChild:
1192 * @parent: the parent node
1193 * @ns: a namespace if any
1194 * @name: the name of the child
1195 * @content: the text content of the child if any.
1196 *
1197 * Creation of a new child element, added at the end of @parent childs list.
1198 * @ns and @content parameters are optionnal (NULL). If content is non NULL,
1199 * a child TEXT node will be created containing the string content.
1200 *
1201 * Returns a pointer to the new node object.
1202 */
1203xmlNodePtr
1204xmlNewTextChild(xmlNodePtr parent, xmlNsPtr ns,
1205 const xmlChar *name, const xmlChar *content) {
1206 xmlNodePtr cur, prev;
1207
1208 if (parent == NULL) {
1209 fprintf(stderr, "xmlNewTextChild : parent == NULL\n");
1210 return(NULL);
1211 }
1212
1213 if (name == NULL) {
1214 fprintf(stderr, "xmlNewTextChild : name == NULL\n");
1215 return(NULL);
1216 }
1217
1218 /*
1219 * Allocate a new node
1220 */
1221 if (ns == NULL)
1222 cur = xmlNewDocRawNode(parent->doc, parent->ns, name, content);
1223 else
1224 cur = xmlNewDocRawNode(parent->doc, ns, name, content);
1225 if (cur == NULL) return(NULL);
1226
1227 /*
1228 * add the new element at the end of the childs list.
1229 */
1230 cur->type = XML_ELEMENT_NODE;
1231 cur->parent = parent;
1232 cur->doc = parent->doc;
1233 if (parent->childs == NULL) {
1234 parent->childs = cur;
1235 parent->last = cur;
1236 } else {
1237 prev = parent->last;
1238 prev->next = cur;
1239 cur->prev = prev;
1240 parent->last = cur;
1241 }
1242
1243 return(cur);
1244}
1245
1246/**
Daniel Veillardccb09631998-10-27 06:21:04 +00001247 * xmlNewReference:
1248 * @doc: the document
1249 * @name: the reference name, or the reference string with & and ;
1250 *
1251 * Creation of a new reference node.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001252 * Returns a pointer to the new node object.
Daniel Veillardccb09631998-10-27 06:21:04 +00001253 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001254xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001255xmlNewReference(xmlDocPtr doc, const xmlChar *name) {
Daniel Veillardccb09631998-10-27 06:21:04 +00001256 xmlNodePtr cur;
1257 xmlEntityPtr ent;
1258
1259 /*
1260 * Allocate a new node and fill the fields.
1261 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001262 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillardccb09631998-10-27 06:21:04 +00001263 if (cur == NULL) {
1264 fprintf(stderr, "xmlNewText : malloc failed\n");
1265 return(NULL);
1266 }
1267
1268 cur->type = XML_ENTITY_REF_NODE;
Daniel Veillard10c6a8f1998-10-28 01:00:12 +00001269 cur->doc = doc;
Daniel Veillardccb09631998-10-27 06:21:04 +00001270 cur->parent = NULL;
1271 cur->next = NULL;
1272 cur->prev = NULL;
1273 cur->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001274 cur->last = NULL;
Daniel Veillardccb09631998-10-27 06:21:04 +00001275 cur->properties = NULL;
1276 if (name[0] == '&') {
1277 int len;
1278 name++;
1279 len = xmlStrlen(name);
1280 if (name[len - 1] == ';')
1281 cur->name = xmlStrndup(name, len - 1);
1282 else
1283 cur->name = xmlStrndup(name, len);
1284 } else
1285 cur->name = xmlStrdup(name);
1286 cur->ns = NULL;
1287 cur->nsDef = NULL;
1288
1289 ent = xmlGetDocEntity(doc, cur->name);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001290 if (ent != NULL) {
1291#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardccb09631998-10-27 06:21:04 +00001292 cur->content = ent->content;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001293#else
1294 /*
1295 * CJN 11.18.99 this might be a problem, since the xmlBuffer gets
1296 * a copy of this pointer. Let's hope we don't manipulate it
1297 * later
1298 */
1299 cur->content = xmlBufferCreateSize(0);
1300 xmlBufferSetAllocationScheme(cur->content,
1301 xmlGetBufferAllocationScheme());
1302 if (ent->content != NULL)
1303 xmlBufferAdd(cur->content, ent->content, -1);
1304#endif
1305 } else
Daniel Veillardccb09631998-10-27 06:21:04 +00001306 cur->content = NULL;
Daniel Veillard00fdf371999-10-08 09:40:39 +00001307#ifndef XML_WITHOUT_CORBA
1308 cur->_private = NULL;
1309 cur->vepv = NULL;
1310#endif
Daniel Veillardccb09631998-10-27 06:21:04 +00001311 return(cur);
1312}
1313
1314/**
Daniel Veillard97b58771998-10-20 06:14:16 +00001315 * xmlNewDocText:
1316 * @doc: the document
1317 * @content: the text content
1318 *
1319 * Creation of a new text node within a document.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001320 * Returns a pointer to the new node object.
Daniel Veillard97b58771998-10-20 06:14:16 +00001321 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001322xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001323xmlNewDocText(xmlDocPtr doc, const xmlChar *content) {
Daniel Veillard0bef1311998-10-14 02:36:47 +00001324 xmlNodePtr cur;
1325
1326 cur = xmlNewText(content);
1327 if (cur != NULL) cur->doc = doc;
1328 return(cur);
1329}
1330
Daniel Veillard97b58771998-10-20 06:14:16 +00001331/**
Daniel Veillardccb09631998-10-27 06:21:04 +00001332 * xmlNewTextLen:
Daniel Veillard97b58771998-10-20 06:14:16 +00001333 * @content: the text content
1334 * @len: the text len.
1335 *
1336 * Creation of a new text node with an extra parameter for the content's lenght
Daniel Veillard1e346af1999-02-22 10:33:01 +00001337 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001338 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001339xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001340xmlNewTextLen(const xmlChar *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001341 xmlNodePtr cur;
1342
1343 /*
1344 * Allocate a new node and fill the fields.
1345 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001346 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillard260a68f1998-08-13 03:39:55 +00001347 if (cur == NULL) {
1348 fprintf(stderr, "xmlNewText : malloc failed\n");
1349 return(NULL);
1350 }
1351
Daniel Veillard33942841998-10-18 19:12:41 +00001352 cur->type = XML_TEXT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001353 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001354 cur->parent = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001355 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001356 cur->next = NULL;
1357 cur->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001358 cur->last = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001359 cur->properties = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001360 cur->type = XML_TEXT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001361 cur->name = xmlStrdup(xmlStringText);
1362 cur->ns = NULL;
1363 cur->nsDef = NULL;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001364 if (content != NULL) {
1365#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard260a68f1998-08-13 03:39:55 +00001366 cur->content = xmlStrndup(content, len);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001367#else
1368 cur->content = xmlBufferCreateSize(len);
1369 xmlBufferSetAllocationScheme(cur->content,
1370 xmlGetBufferAllocationScheme());
1371 xmlBufferAdd(cur->content, content, len);
1372#endif
1373 } else
Daniel Veillard260a68f1998-08-13 03:39:55 +00001374 cur->content = NULL;
Daniel Veillard00fdf371999-10-08 09:40:39 +00001375#ifndef XML_WITHOUT_CORBA
1376 cur->_private = NULL;
1377 cur->vepv = NULL;
1378#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001379 return(cur);
1380}
1381
Daniel Veillard97b58771998-10-20 06:14:16 +00001382/**
1383 * xmlNewDocTextLen:
1384 * @doc: the document
1385 * @content: the text content
1386 * @len: the text len.
1387 *
1388 * Creation of a new text node with an extra content lenght parameter. The
1389 * text node pertain to a given document.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001390 * Returns a pointer to the new node object.
Daniel Veillard97b58771998-10-20 06:14:16 +00001391 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001392xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001393xmlNewDocTextLen(xmlDocPtr doc, const xmlChar *content, int len) {
Daniel Veillard0bef1311998-10-14 02:36:47 +00001394 xmlNodePtr cur;
1395
1396 cur = xmlNewTextLen(content, len);
1397 if (cur != NULL) cur->doc = doc;
1398 return(cur);
1399}
1400
Daniel Veillard97b58771998-10-20 06:14:16 +00001401/**
1402 * xmlNewComment:
1403 * @content: the comment content
1404 *
1405 * Creation of a new node containing a comment.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001406 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001407 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001408xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001409xmlNewComment(const xmlChar *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001410 xmlNodePtr cur;
1411
1412 /*
1413 * Allocate a new node and fill the fields.
1414 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001415 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillard260a68f1998-08-13 03:39:55 +00001416 if (cur == NULL) {
1417 fprintf(stderr, "xmlNewComment : malloc failed\n");
1418 return(NULL);
1419 }
1420
Daniel Veillard33942841998-10-18 19:12:41 +00001421 cur->type = XML_COMMENT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001422 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001423 cur->parent = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001424 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001425 cur->next = NULL;
1426 cur->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001427 cur->last = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001428 cur->properties = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001429 cur->type = XML_COMMENT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001430 cur->name = xmlStrdup(xmlStringText);
1431 cur->ns = NULL;
1432 cur->nsDef = NULL;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001433 if (content != NULL) {
1434#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard260a68f1998-08-13 03:39:55 +00001435 cur->content = xmlStrdup(content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001436#else
1437 cur->content = xmlBufferCreateSize(0);
1438 xmlBufferSetAllocationScheme(cur->content,
1439 xmlGetBufferAllocationScheme());
1440 xmlBufferAdd(cur->content, content, -1);
1441#endif
1442 } else
Daniel Veillard260a68f1998-08-13 03:39:55 +00001443 cur->content = NULL;
Daniel Veillard00fdf371999-10-08 09:40:39 +00001444#ifndef XML_WITHOUT_CORBA
1445 cur->_private = NULL;
1446 cur->vepv = NULL;
1447#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001448 return(cur);
1449}
1450
Daniel Veillard97b58771998-10-20 06:14:16 +00001451/**
Daniel Veillardb05deb71999-08-10 19:04:08 +00001452 * xmlNewCDataBlock:
1453 * @doc: the document
1454 * @content: the CData block content content
1455 * @len: the length of the block
1456 *
1457 * Creation of a new node containing a CData block.
1458 * Returns a pointer to the new node object.
1459 */
1460xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001461xmlNewCDataBlock(xmlDocPtr doc, const xmlChar *content, int len) {
Daniel Veillardb05deb71999-08-10 19:04:08 +00001462 xmlNodePtr cur;
1463
1464 /*
1465 * Allocate a new node and fill the fields.
1466 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001467 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillardb05deb71999-08-10 19:04:08 +00001468 if (cur == NULL) {
1469 fprintf(stderr, "xmlNewCDataBlock : malloc failed\n");
1470 return(NULL);
1471 }
1472
1473 cur->type = XML_CDATA_SECTION_NODE;
1474 cur->doc = NULL;
1475 cur->parent = NULL;
1476 cur->prev = NULL;
1477 cur->next = NULL;
1478 cur->childs = NULL;
1479 cur->last = NULL;
1480 cur->properties = NULL;
1481 cur->name = xmlStrdup(xmlStringText);
1482 cur->ns = NULL;
1483 cur->nsDef = NULL;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001484 if (content != NULL) {
1485#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardb05deb71999-08-10 19:04:08 +00001486 cur->content = xmlStrndup(content, len);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001487#else
1488 cur->content = xmlBufferCreateSize(len);
1489 xmlBufferSetAllocationScheme(cur->content,
1490 xmlGetBufferAllocationScheme());
1491 xmlBufferAdd(cur->content, content, len);
1492#endif
Daniel Veillardb05deb71999-08-10 19:04:08 +00001493 } else
1494 cur->content = NULL;
Daniel Veillard00fdf371999-10-08 09:40:39 +00001495#ifndef XML_WITHOUT_CORBA
1496 cur->_private = NULL;
1497 cur->vepv = NULL;
1498#endif
Daniel Veillardb05deb71999-08-10 19:04:08 +00001499 return(cur);
1500}
1501
1502/**
Daniel Veillard1e346af1999-02-22 10:33:01 +00001503 * xmlNewDocComment:
Daniel Veillard97b58771998-10-20 06:14:16 +00001504 * @doc: the document
1505 * @content: the comment content
1506 *
1507 * Creation of a new node containing a commentwithin a document.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001508 * Returns a pointer to the new node object.
Daniel Veillard97b58771998-10-20 06:14:16 +00001509 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001510xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001511xmlNewDocComment(xmlDocPtr doc, const xmlChar *content) {
Daniel Veillard0bef1311998-10-14 02:36:47 +00001512 xmlNodePtr cur;
1513
1514 cur = xmlNewComment(content);
1515 if (cur != NULL) cur->doc = doc;
1516 return(cur);
1517}
1518
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001519
Daniel Veillard97b58771998-10-20 06:14:16 +00001520/**
1521 * xmlNewChild:
1522 * @parent: the parent node
1523 * @ns: a namespace if any
1524 * @name: the name of the child
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001525 * @content: the XML content of the child if any.
Daniel Veillard97b58771998-10-20 06:14:16 +00001526 *
Daniel Veillard97b58771998-10-20 06:14:16 +00001527 * Creation of a new child element, added at the end of @parent childs list.
Daniel Veillardccb09631998-10-27 06:21:04 +00001528 * @ns and @content parameters are optionnal (NULL). If content is non NULL,
1529 * a child list containing the TEXTs and ENTITY_REFs node will be created.
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001530 * NOTE: @content is supposed to be a piece of XML CDATA, so it allow entities
1531 * references, but XML special chars need to be escaped first by using
1532 * xmlEncodeEntitiesReentrant(). Use xmlNewTextChild() if entities
1533 * support is not needed.
1534 *
Daniel Veillard1e346af1999-02-22 10:33:01 +00001535 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001536 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001537xmlNodePtr
1538xmlNewChild(xmlNodePtr parent, xmlNsPtr ns,
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001539 const xmlChar *name, const xmlChar *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001540 xmlNodePtr cur, prev;
1541
1542 if (parent == NULL) {
1543 fprintf(stderr, "xmlNewChild : parent == NULL\n");
1544 return(NULL);
1545 }
1546
1547 if (name == NULL) {
1548 fprintf(stderr, "xmlNewChild : name == NULL\n");
1549 return(NULL);
1550 }
1551
1552 /*
1553 * Allocate a new node
1554 */
1555 if (ns == NULL)
Daniel Veillardccb09631998-10-27 06:21:04 +00001556 cur = xmlNewDocNode(parent->doc, parent->ns, name, content);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001557 else
Daniel Veillardccb09631998-10-27 06:21:04 +00001558 cur = xmlNewDocNode(parent->doc, ns, name, content);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001559 if (cur == NULL) return(NULL);
1560
1561 /*
1562 * add the new element at the end of the childs list.
1563 */
Daniel Veillardccb09631998-10-27 06:21:04 +00001564 cur->type = XML_ELEMENT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001565 cur->parent = parent;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001566 cur->doc = parent->doc;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001567 if (parent->childs == NULL) {
1568 parent->childs = cur;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001569 parent->last = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001570 } else {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001571 prev = parent->last;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001572 prev->next = cur;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001573 cur->prev = prev;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001574 parent->last = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001575 }
1576
1577 return(cur);
1578}
1579
Daniel Veillard97b58771998-10-20 06:14:16 +00001580/**
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00001581 * xmlAddNextSibling:
1582 * @cur: the child node
1583 * @elem: the new node
1584 *
1585 * Add a new element @elem as the next siblings of @cur
1586 * If the new element was already inserted in a document it is
1587 * first unlinked from its existing context.
1588 *
1589 * Returns the new element or NULL in case of error.
1590 */
1591xmlNodePtr
1592xmlAddNextSibling(xmlNodePtr cur, xmlNodePtr elem) {
1593 if (cur == NULL) {
1594 fprintf(stderr, "xmlAddNextSibling : cur == NULL\n");
1595 return(NULL);
1596 }
1597 if (elem == NULL) {
1598 fprintf(stderr, "xmlAddNextSibling : elem == NULL\n");
1599 return(NULL);
1600 }
1601
1602 xmlUnlinkNode(elem);
1603 elem->doc = cur->doc;
1604 elem->parent = cur->parent;
1605 elem->next = cur;
1606 elem->prev = cur->prev;
1607 cur->prev = elem;
1608 if (elem->prev != NULL)
1609 elem->prev->next = elem;
1610 if ((elem->parent != NULL) && (elem->parent->childs == cur))
1611 elem->parent->childs = elem;
1612 return(elem);
1613}
1614
1615/**
1616 * xmlAddPrevSibling:
1617 * @cur: the child node
1618 * @elem: the new node
1619 *
1620 * Add a new element @elem as the previous siblings of @cur
1621 * If the new element was already inserted in a document it is
1622 * first unlinked from its existing context.
1623 *
1624 * Returns the new element or NULL in case of error.
1625 */
1626xmlNodePtr
1627xmlAddPrevSibling(xmlNodePtr cur, xmlNodePtr elem) {
1628 if (cur == NULL) {
1629 fprintf(stderr, "xmlAddPrevSibling : cur == NULL\n");
1630 return(NULL);
1631 }
1632 if (elem == NULL) {
1633 fprintf(stderr, "xmlAddPrevSibling : elem == NULL\n");
1634 return(NULL);
1635 }
1636
1637 xmlUnlinkNode(elem);
1638 elem->doc = cur->doc;
1639 elem->parent = cur->parent;
1640 elem->prev = cur;
1641 elem->next = cur->next;
1642 cur->next = elem;
1643 if (elem->next != NULL)
1644 elem->next->prev = elem;
1645 if ((elem->parent != NULL) && (elem->parent->last == cur))
1646 elem->parent->last = elem;
1647 return(elem);
1648}
1649
1650/**
Daniel Veillardb96e6431999-08-29 21:02:19 +00001651 * xmlAddSibling:
1652 * @cur: the child node
1653 * @elem: the new node
1654 *
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00001655 * Add a new element @elem to the list of siblings of @cur
1656 * If the new element was already inserted in a document it is
1657 * first unlinked from its existing context.
1658 *
1659 * Returns the new element or NULL in case of error.
Daniel Veillardb96e6431999-08-29 21:02:19 +00001660 */
1661xmlNodePtr
1662xmlAddSibling(xmlNodePtr cur, xmlNodePtr elem) {
1663 xmlNodePtr parent;
1664
1665 if (cur == NULL) {
1666 fprintf(stderr, "xmlAddSibling : cur == NULL\n");
1667 return(NULL);
1668 }
1669
1670 if (elem == NULL) {
1671 fprintf(stderr, "xmlAddSibling : elem == NULL\n");
1672 return(NULL);
1673 }
1674
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00001675 /*
1676 * Constant time is we can rely on the ->parent->last to find
1677 * the last sibling.
1678 */
1679 if ((cur->parent != NULL) &&
1680 (cur->parent->childs != NULL) &&
1681 (cur->parent->last != NULL) &&
1682 (cur->parent->last->next == NULL)) {
1683 cur = cur->parent->last;
1684 } else {
1685 while (cur->next != NULL) cur = cur->next;
Daniel Veillardb96e6431999-08-29 21:02:19 +00001686 }
1687
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00001688 xmlUnlinkNode(elem);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001689 if (elem->doc == NULL)
1690 elem->doc = cur->doc; /* the parent may not be linked to a doc ! */
1691
1692 parent = cur->parent;
1693 elem->prev = cur;
1694 elem->next = NULL;
1695 elem->parent = parent;
1696 cur->next = elem;
1697 if (parent != NULL)
1698 parent->last = elem;
1699
1700 return(elem);
1701}
1702
1703/**
Daniel Veillard97b58771998-10-20 06:14:16 +00001704 * xmlAddChild:
1705 * @parent: the parent node
1706 * @cur: the child node
1707 *
1708 * Add a new child element, to @parent, at the end of the child list.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001709 * Returns the child or NULL in case of error.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001710 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001711xmlNodePtr
1712xmlAddChild(xmlNodePtr parent, xmlNodePtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001713 xmlNodePtr prev;
1714
1715 if (parent == NULL) {
Daniel Veillard10a2c651999-12-12 13:03:50 +00001716 fprintf(stderr, "xmlAddChild : parent == NULL\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00001717 return(NULL);
1718 }
1719
1720 if (cur == NULL) {
Daniel Veillard10a2c651999-12-12 13:03:50 +00001721 fprintf(stderr, "xmlAddChild : child == NULL\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00001722 return(NULL);
1723 }
1724
Daniel Veillard0bef1311998-10-14 02:36:47 +00001725 if ((cur->doc != NULL) && (parent->doc != NULL) &&
1726 (cur->doc != parent->doc)) {
1727 fprintf(stderr, "Elements moved to a different document\n");
1728 }
1729
Daniel Veillard260a68f1998-08-13 03:39:55 +00001730 /*
1731 * add the new element at the end of the childs list.
1732 */
1733 cur->parent = parent;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001734 cur->doc = parent->doc; /* the parent may not be linked to a doc ! */
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001735
Daniel Veillardccb09631998-10-27 06:21:04 +00001736 /*
1737 * Handle the case where parent->content != NULL, in that case it will
1738 * create a intermediate TEXT node.
1739 */
1740 if (parent->content != NULL) {
1741 xmlNodePtr text;
1742
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001743#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardccb09631998-10-27 06:21:04 +00001744 text = xmlNewDocText(parent->doc, parent->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001745#else
1746 text = xmlNewDocText(parent->doc, xmlBufferContent(parent->content));
1747#endif
Daniel Veillardccb09631998-10-27 06:21:04 +00001748 if (text != NULL) {
1749 text->next = parent->childs;
1750 if (text->next != NULL)
1751 text->next->prev = text;
1752 parent->childs = text;
Daniel Veillard1e346af1999-02-22 10:33:01 +00001753 UPDATE_LAST_CHILD(parent)
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001754#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard6454aec1999-09-02 22:04:43 +00001755 xmlFree(parent->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001756#else
1757 xmlBufferFree(parent->content);
1758#endif
Daniel Veillardccb09631998-10-27 06:21:04 +00001759 parent->content = NULL;
1760 }
1761 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00001762 if (parent->childs == NULL) {
1763 parent->childs = cur;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001764 parent->last = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001765 } else {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001766 prev = parent->last;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001767 prev->next = cur;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001768 cur->prev = prev;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001769 parent->last = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001770 }
1771
1772 return(cur);
1773}
1774
Daniel Veillard97b58771998-10-20 06:14:16 +00001775/**
1776 * xmlGetLastChild:
1777 * @parent: the parent node
1778 *
1779 * Search the last child of a node.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001780 * Returns the last child or NULL if none.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001781 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001782xmlNodePtr
1783xmlGetLastChild(xmlNodePtr parent) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001784 if (parent == NULL) {
1785 fprintf(stderr, "xmlGetLastChild : parent == NULL\n");
1786 return(NULL);
1787 }
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001788 return(parent->last);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001789}
1790
Daniel Veillard97b58771998-10-20 06:14:16 +00001791/**
1792 * xmlFreeNodeList:
1793 * @cur: the first node in the list
1794 *
1795 * Free a node and all its siblings, this is a recursive behaviour, all
1796 * the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001797 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001798void
1799xmlFreeNodeList(xmlNodePtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001800 xmlNodePtr next;
1801 if (cur == NULL) {
1802 fprintf(stderr, "xmlFreeNodeList : node == NULL\n");
1803 return;
1804 }
1805 while (cur != NULL) {
1806 next = cur->next;
1807 xmlFreeNode(cur);
1808 cur = next;
1809 }
1810}
1811
Daniel Veillard97b58771998-10-20 06:14:16 +00001812/**
1813 * xmlFreeNode:
1814 * @cur: the node
1815 *
1816 * Free a node, this is a recursive behaviour, all the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001817 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001818void
1819xmlFreeNode(xmlNodePtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001820 if (cur == NULL) {
1821 fprintf(stderr, "xmlFreeNode : node == NULL\n");
1822 return;
1823 }
Daniel Veillardccb09631998-10-27 06:21:04 +00001824 cur->doc = NULL;
1825 cur->parent = NULL;
1826 cur->next = NULL;
1827 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001828 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillardccb09631998-10-27 06:21:04 +00001829 if (cur->properties != NULL) xmlFreePropList(cur->properties);
1830 if (cur->type != XML_ENTITY_REF_NODE)
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001831#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard6454aec1999-09-02 22:04:43 +00001832 if (cur->content != NULL) xmlFree(cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001833#else
1834 if (cur->content != NULL) xmlBufferFree(cur->content);
1835#endif
Daniel Veillard6454aec1999-09-02 22:04:43 +00001836 if (cur->name != NULL) xmlFree((char *) cur->name);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001837 if (cur->nsDef != NULL) xmlFreeNsList(cur->nsDef);
1838 memset(cur, -1, sizeof(xmlNode));
Daniel Veillard6454aec1999-09-02 22:04:43 +00001839 xmlFree(cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001840}
1841
Daniel Veillard16253641998-10-28 22:58:05 +00001842/**
1843 * xmlUnlinkNode:
1844 * @cur: the node
1845 *
1846 * Unlink a node from it's current context, the node is not freed
1847 */
1848void
1849xmlUnlinkNode(xmlNodePtr cur) {
1850 if (cur == NULL) {
1851 fprintf(stderr, "xmlUnlinkNode : node == NULL\n");
1852 return;
1853 }
1854 if ((cur->parent != NULL) && (cur->parent->childs == cur))
1855 cur->parent->childs = cur->next;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001856 if ((cur->parent != NULL) && (cur->parent->last == cur))
1857 cur->parent->last = cur->prev;
Daniel Veillard16253641998-10-28 22:58:05 +00001858 if (cur->next != NULL)
1859 cur->next->prev = cur->prev;
1860 if (cur->prev != NULL)
1861 cur->prev->next = cur->next;
1862 cur->next = cur->prev = NULL;
1863 cur->parent = NULL;
1864}
1865
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00001866/**
1867 * xmlReplaceNode:
1868 * @old: the old node
1869 * @cur: the node
1870 *
1871 * Unlink the old node from it's current context, prune the new one
1872 * at the same place. If cur was already inserted in a document it is
1873 * first unlinked from its existing context.
1874 *
1875 * Returns the old node
1876 */
1877xmlNodePtr
1878xmlReplaceNode(xmlNodePtr old, xmlNodePtr cur) {
1879 if (old == NULL) {
1880 fprintf(stderr, "xmlReplaceNode : old == NULL\n");
1881 return(NULL);
1882 }
1883 if (cur == NULL) {
1884 xmlUnlinkNode(old);
1885 return(old);
1886 }
1887 xmlUnlinkNode(cur);
1888 cur->doc = old->doc;
1889 cur->parent = old->parent;
1890 cur->next = old->next;
1891 if (cur->next != NULL)
1892 cur->next->prev = cur;
1893 cur->prev = old->prev;
1894 if (cur->prev != NULL)
1895 cur->prev->next = cur;
1896 if (cur->parent != NULL) {
1897 if (cur->parent->childs == old)
1898 cur->parent->childs = cur;
1899 if (cur->parent->last == old)
1900 cur->parent->last = cur;
1901 }
1902 old->next = old->prev = NULL;
1903 old->parent = NULL;
1904 return(old);
1905}
1906
Daniel Veillard260a68f1998-08-13 03:39:55 +00001907/************************************************************************
1908 * *
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001909 * Copy operations *
1910 * *
1911 ************************************************************************/
1912
1913/**
1914 * xmlCopyNamespace:
1915 * @cur: the namespace
1916 *
1917 * Do a copy of the namespace.
1918 *
1919 * Returns: a new xmlNsPtr, or NULL in case of error.
1920 */
1921xmlNsPtr
1922xmlCopyNamespace(xmlNsPtr cur) {
1923 xmlNsPtr ret;
1924
1925 if (cur == NULL) return(NULL);
1926 switch (cur->type) {
1927 case XML_GLOBAL_NAMESPACE:
1928 ret = xmlNewGlobalNs(NULL, cur->href, cur->prefix);
1929 break;
1930 case XML_LOCAL_NAMESPACE:
1931 ret = xmlNewNs(NULL, cur->href, cur->prefix);
1932 break;
1933 default:
1934 fprintf(stderr, "xmlCopyNamespace: unknown type %d\n", cur->type);
1935 return(NULL);
1936 }
1937 return(ret);
1938}
1939
1940/**
1941 * xmlCopyNamespaceList:
1942 * @cur: the first namespace
1943 *
1944 * Do a copy of an namespace list.
1945 *
1946 * Returns: a new xmlNsPtr, or NULL in case of error.
1947 */
1948xmlNsPtr
1949xmlCopyNamespaceList(xmlNsPtr cur) {
1950 xmlNsPtr ret = NULL;
1951 xmlNsPtr p = NULL,q;
1952
1953 while (cur != NULL) {
1954 q = xmlCopyNamespace(cur);
1955 if (p == NULL) {
1956 ret = p = q;
1957 } else {
1958 p->next = q;
1959 p = q;
1960 }
1961 cur = cur->next;
1962 }
1963 return(ret);
1964}
1965
1966/**
1967 * xmlCopyProp:
Daniel Veillardb96e6431999-08-29 21:02:19 +00001968 * @target: the element where the attribute will be grafted
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001969 * @cur: the attribute
1970 *
1971 * Do a copy of the attribute.
1972 *
1973 * Returns: a new xmlAttrPtr, or NULL in case of error.
1974 */
1975xmlAttrPtr
Daniel Veillardb96e6431999-08-29 21:02:19 +00001976xmlCopyProp(xmlNodePtr target, xmlAttrPtr cur) {
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001977 xmlAttrPtr ret;
1978
1979 if (cur == NULL) return(NULL);
1980 if (cur->val != NULL)
1981 ret = xmlNewDocProp(cur->val->doc, cur->name, NULL);
1982 else
1983 ret = xmlNewDocProp(NULL, cur->name, NULL);
1984 if (ret == NULL) return(NULL);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001985
1986 if ((cur->ns != NULL) && (target != NULL)) {
1987 xmlNsPtr ns;
1988
1989 ns = xmlSearchNs(target->doc, target, cur->ns->prefix);
1990 ret->ns = ns;
1991 } else
1992 ret->ns = NULL;
1993
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001994 if (cur->val != NULL)
1995 ret->val = xmlCopyNodeList(cur->val);
1996 return(ret);
1997}
1998
1999/**
2000 * xmlCopyPropList:
Daniel Veillardb96e6431999-08-29 21:02:19 +00002001 * @target: the element where the attributes will be grafted
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002002 * @cur: the first attribute
2003 *
2004 * Do a copy of an attribute list.
2005 *
2006 * Returns: a new xmlAttrPtr, or NULL in case of error.
2007 */
2008xmlAttrPtr
Daniel Veillardb96e6431999-08-29 21:02:19 +00002009xmlCopyPropList(xmlNodePtr target, xmlAttrPtr cur) {
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002010 xmlAttrPtr ret = NULL;
2011 xmlAttrPtr p = NULL,q;
2012
2013 while (cur != NULL) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00002014 q = xmlCopyProp(target, cur);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002015 if (p == NULL) {
2016 ret = p = q;
2017 } else {
2018 p->next = q;
2019 p = q;
2020 }
2021 cur = cur->next;
2022 }
2023 return(ret);
2024}
2025
2026/*
Daniel Veillard11a48ec1999-11-23 10:40:46 +00002027 * NOTE abeut the CopyNode operations !
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002028 *
2029 * They are splitted into external and internal parts for one
2030 * tricky reason: namespaces. Doing a direct copy of a node
2031 * say RPM:Copyright without changing the namespace pointer to
2032 * something else can produce stale links. One way to do it is
2033 * to keep a reference counter but this doesn't work as soon
2034 * as one move the element or the subtree out of the scope of
2035 * the existing namespace. The actual solution seems to add
2036 * a copy of the namespace at the top of the copied tree if
2037 * not available in the subtree.
2038 * Hence two functions, the public front-end call the inner ones
2039 */
2040
2041static xmlNodePtr
2042xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent);
2043
2044static xmlNodePtr
2045xmlStaticCopyNode(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent,
2046 int recursive) {
2047 xmlNodePtr ret;
2048
2049 if (node == NULL) return(NULL);
2050 /*
2051 * Allocate a new node and fill the fields.
2052 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00002053 ret = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002054 if (ret == NULL) {
2055 fprintf(stderr, "xmlStaticCopyNode : malloc failed\n");
2056 return(NULL);
2057 }
2058
2059 ret->type = node->type;
2060 ret->doc = doc;
2061 ret->parent = parent;
2062 ret->next = NULL;
2063 ret->prev = NULL;
2064 ret->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002065 ret->last = NULL;
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002066 ret->properties = NULL;
2067 if (node->name != NULL)
2068 ret->name = xmlStrdup(node->name);
2069 else
2070 ret->name = NULL;
2071 ret->ns = NULL;
2072 ret->nsDef = NULL;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002073 if ((node->content != NULL) && (node->type != XML_ENTITY_REF_NODE)) {
2074#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002075 ret->content = xmlStrdup(node->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002076#else
2077 ret->content = xmlBufferCreateSize(xmlBufferLength(node->content));
2078 xmlBufferSetAllocationScheme(ret->content,
2079 xmlGetBufferAllocationScheme());
2080 xmlBufferAdd(ret->content,
2081 xmlBufferContent(node->content),
2082 xmlBufferLength(node->content));
2083#endif
2084 } else
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002085 ret->content = NULL;
Daniel Veillard27d88741999-05-29 11:51:49 +00002086#ifndef XML_WITHOUT_CORBA
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002087 ret->_private = NULL;
2088 ret->vepv = NULL;
2089#endif
2090 if (parent != NULL)
2091 xmlAddChild(parent, ret);
2092
2093 if (!recursive) return(ret);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002094 if (node->nsDef != NULL)
2095 ret->nsDef = xmlCopyNamespaceList(node->nsDef);
2096
2097 if (node->ns != NULL) {
2098 xmlNsPtr ns;
2099
2100 ns = xmlSearchNs(doc, ret, node->ns->prefix);
2101 if (ns == NULL) {
2102 /*
2103 * Humm, we are copying an element whose namespace is defined
2104 * out of the new tree scope. Search it in the original tree
2105 * and add it at the top of the new tree
2106 */
2107 ns = xmlSearchNs(node->doc, node, node->ns->prefix);
2108 if (ns != NULL) {
2109 xmlNodePtr root = ret;
2110
2111 while (root->parent != NULL) root = root->parent;
2112 xmlNewNs(root, ns->href, ns->prefix);
2113 }
2114 } else {
2115 /*
2116 * reference the existing namespace definition in our own tree.
2117 */
2118 ret->ns = ns;
2119 }
2120 }
Daniel Veillardb96e6431999-08-29 21:02:19 +00002121 if (node->properties != NULL)
2122 ret->properties = xmlCopyPropList(ret, node->properties);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002123 if (node->childs != NULL)
2124 ret->childs = xmlStaticCopyNodeList(node->childs, doc, ret);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002125 UPDATE_LAST_CHILD(ret)
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002126 return(ret);
2127}
2128
2129static xmlNodePtr
2130xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent) {
2131 xmlNodePtr ret = NULL;
2132 xmlNodePtr p = NULL,q;
2133
2134 while (node != NULL) {
2135 q = xmlStaticCopyNode(node, doc, parent, 1);
2136 if (parent == NULL) {
2137 if (ret == NULL) ret = q;
2138 } else {
2139 if (ret == NULL) {
2140 q->prev = NULL;
2141 ret = p = q;
2142 } else {
2143 p->next = q;
2144 q->prev = p;
2145 p = q;
2146 }
2147 }
2148 node = node->next;
2149 }
2150 return(ret);
2151}
2152
2153/**
2154 * xmlCopyNode:
2155 * @node: the node
2156 * @recursive: if 1 do a recursive copy.
2157 *
2158 * Do a copy of the node.
2159 *
2160 * Returns: a new xmlNodePtr, or NULL in case of error.
2161 */
2162xmlNodePtr
2163xmlCopyNode(xmlNodePtr node, int recursive) {
2164 xmlNodePtr ret;
2165
2166 ret = xmlStaticCopyNode(node, NULL, NULL, recursive);
2167 return(ret);
2168}
2169
2170/**
2171 * xmlCopyNodeList:
2172 * @node: the first node in the list.
2173 *
2174 * Do a recursive copy of the node list.
2175 *
2176 * Returns: a new xmlNodePtr, or NULL in case of error.
2177 */
2178xmlNodePtr xmlCopyNodeList(xmlNodePtr node) {
2179 xmlNodePtr ret = xmlStaticCopyNodeList(node, NULL, NULL);
2180 return(ret);
2181}
2182
2183/**
2184 * xmlCopyElement:
2185 * @elem: the element
2186 *
2187 * Do a copy of the element definition.
2188 *
2189 * Returns: a new xmlElementPtr, or NULL in case of error.
2190xmlElementPtr
2191xmlCopyElement(xmlElementPtr elem) {
2192 xmlElementPtr ret;
2193
2194 if (elem == NULL) return(NULL);
2195 ret = xmlNewDocElement(elem->doc, elem->ns, elem->name, elem->content);
2196 if (ret == NULL) return(NULL);
2197 if (!recursive) return(ret);
2198 if (elem->properties != NULL)
2199 ret->properties = xmlCopyPropList(elem->properties);
2200
2201 if (elem->nsDef != NULL)
2202 ret->nsDef = xmlCopyNamespaceList(elem->nsDef);
2203 if (elem->childs != NULL)
2204 ret->childs = xmlCopyElementList(elem->childs);
2205 return(ret);
2206}
2207 */
2208
2209/**
2210 * xmlCopyDtd:
2211 * @dtd: the dtd
2212 *
2213 * Do a copy of the dtd.
2214 *
2215 * Returns: a new xmlDtdPtr, or NULL in case of error.
2216 */
2217xmlDtdPtr
2218xmlCopyDtd(xmlDtdPtr dtd) {
2219 xmlDtdPtr ret;
2220
2221 if (dtd == NULL) return(NULL);
2222 ret = xmlNewDtd(NULL, dtd->name, dtd->ExternalID, dtd->SystemID);
2223 if (ret == NULL) return(NULL);
2224 if (dtd->entities != NULL)
2225 ret->entities = (void *) xmlCopyEntitiesTable(
2226 (xmlEntitiesTablePtr) dtd->entities);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002227 if (dtd->notations != NULL)
2228 ret->notations = (void *) xmlCopyNotationTable(
2229 (xmlNotationTablePtr) dtd->notations);
2230 if (dtd->elements != NULL)
2231 ret->elements = (void *) xmlCopyElementTable(
2232 (xmlElementTablePtr) dtd->elements);
2233 if (dtd->attributes != NULL)
2234 ret->attributes = (void *) xmlCopyAttributeTable(
2235 (xmlAttributeTablePtr) dtd->attributes);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002236 return(ret);
2237}
2238
2239/**
2240 * xmlCopyDoc:
2241 * @doc: the document
2242 * @recursive: if 1 do a recursive copy.
2243 *
2244 * Do a copy of the document info. If recursive, the content tree will
2245 * be copied too as well as Dtd, namespaces and entities.
2246 *
2247 * Returns: a new xmlDocPtr, or NULL in case of error.
2248 */
2249xmlDocPtr
2250xmlCopyDoc(xmlDocPtr doc, int recursive) {
2251 xmlDocPtr ret;
2252
2253 if (doc == NULL) return(NULL);
2254 ret = xmlNewDoc(doc->version);
2255 if (ret == NULL) return(NULL);
2256 if (doc->name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +00002257 ret->name = xmlMemStrdup(doc->name);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002258 if (doc->encoding != NULL)
2259 ret->encoding = xmlStrdup(doc->encoding);
2260 ret->compression = doc->compression;
2261 ret->standalone = doc->standalone;
2262 if (!recursive) return(ret);
2263
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002264 if (doc->intSubset != NULL)
2265 ret->intSubset = xmlCopyDtd(doc->intSubset);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002266 if (doc->oldNs != NULL)
2267 ret->oldNs = xmlCopyNamespaceList(doc->oldNs);
2268 if (doc->root != NULL)
2269 ret->root = xmlStaticCopyNodeList(doc->root, ret, NULL);
2270 return(ret);
2271}
2272
2273/************************************************************************
2274 * *
Daniel Veillard260a68f1998-08-13 03:39:55 +00002275 * Content access functions *
2276 * *
2277 ************************************************************************/
2278
Daniel Veillard97b58771998-10-20 06:14:16 +00002279/**
Daniel Veillard944b5ff1999-12-15 19:08:24 +00002280 * xmlDocGetRootElement:
2281 * @doc: the document
2282 *
2283 * Get the root element of the document (doc->root is a list
2284 * containing possibly comments, PIs, etc ...).
2285 *
2286 * Returns the xmlNodePtr for the root or NULL
2287 */
2288xmlNodePtr
2289xmlDocGetRootElement(xmlDocPtr doc) {
2290 xmlNodePtr ret;
2291
2292 if (doc == NULL) return(NULL);
2293 ret = doc->root;
2294 while (ret != NULL) {
2295 if (ret->type == XML_ELEMENT_NODE)
2296 return(ret);
2297 ret = ret->next;
2298 }
2299 return(ret);
2300}
2301
2302/**
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00002303 * xmlDocSetRootElement:
2304 * @doc: the document
2305 * @root: the new document root element
2306 *
2307 * Set the root element of the document (doc->root is a list
2308 * containing possibly comments, PIs, etc ...).
2309 *
2310 * Returns the old root element if any was found
2311 */
2312xmlNodePtr
2313xmlDocSetRootElement(xmlDocPtr doc, xmlNodePtr root) {
2314 xmlNodePtr old = NULL;
2315
2316 if (doc == NULL) return(NULL);
2317 old = doc->root;
2318 while (old != NULL) {
2319 if (old->type == XML_ELEMENT_NODE)
2320 break;
2321 old = old->next;
2322 }
2323 if (old == NULL) {
2324 if (doc->root == NULL) {
2325 doc->root = root;
2326 } else {
2327 xmlAddSibling(doc->root, root);
2328 }
2329 } else {
2330 xmlReplaceNode(old, root);
2331 }
2332 return(old);
2333}
2334
2335/**
Daniel Veillardb96e6431999-08-29 21:02:19 +00002336 * xmlNodeSetLang:
2337 * @cur: the node being changed
2338 * @lang: the langage description
2339 *
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00002340 * Set the language of a node, i.e. the values of the xml:lang
2341 * attribute.
Daniel Veillardb96e6431999-08-29 21:02:19 +00002342 */
2343void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002344xmlNodeSetLang(xmlNodePtr cur, const xmlChar *lang) {
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00002345 if (cur == NULL) return;
2346 switch(cur->type) {
2347 case XML_TEXT_NODE:
2348 case XML_CDATA_SECTION_NODE:
2349 case XML_COMMENT_NODE:
2350 case XML_DOCUMENT_NODE:
2351 case XML_DOCUMENT_TYPE_NODE:
2352 case XML_DOCUMENT_FRAG_NODE:
2353 case XML_NOTATION_NODE:
2354 case XML_HTML_DOCUMENT_NODE:
2355 return;
2356 case XML_ELEMENT_NODE:
2357 case XML_ATTRIBUTE_NODE:
2358 case XML_PI_NODE:
2359 case XML_ENTITY_REF_NODE:
2360 case XML_ENTITY_NODE:
2361 break;
2362 }
Daniel Veillardb96e6431999-08-29 21:02:19 +00002363 xmlSetProp(cur, BAD_CAST "xml:lang", lang);
2364}
2365
2366/**
2367 * xmlNodeGetLang:
2368 * @cur: the node being checked
2369 *
2370 * Searches the language of a node, i.e. the values of the xml:lang
2371 * attribute or the one carried by the nearest ancestor.
2372 *
2373 * Returns a pointer to the lang value, or NULL if not found
Daniel Veillarda819dac1999-11-24 18:04:22 +00002374 * It's up to the caller to free the memory.
Daniel Veillardb96e6431999-08-29 21:02:19 +00002375 */
Daniel Veillarda819dac1999-11-24 18:04:22 +00002376xmlChar *
Daniel Veillardb96e6431999-08-29 21:02:19 +00002377xmlNodeGetLang(xmlNodePtr cur) {
Daniel Veillarda819dac1999-11-24 18:04:22 +00002378 xmlChar *lang;
Daniel Veillardb96e6431999-08-29 21:02:19 +00002379
2380 while (cur != NULL) {
2381 lang = xmlGetProp(cur, BAD_CAST "xml:lang");
2382 if (lang != NULL)
2383 return(lang);
2384 cur = cur->parent;
2385 }
2386 return(NULL);
2387}
2388
2389/**
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00002390 * xmlNodeSetName:
2391 * @cur: the node being changed
2392 * @name: the new tag name
2393 *
2394 * Searches the language of a node, i.e. the values of the xml:lang
2395 * attribute or the one carried by the nearest ancestor.
2396 */
2397void
2398xmlNodeSetName(xmlNodePtr cur, const xmlChar *name) {
2399 if (cur == NULL) return;
2400 if (name == NULL) return;
2401 switch(cur->type) {
2402 case XML_TEXT_NODE:
2403 case XML_CDATA_SECTION_NODE:
2404 case XML_COMMENT_NODE:
2405 case XML_DOCUMENT_NODE:
2406 case XML_DOCUMENT_TYPE_NODE:
2407 case XML_DOCUMENT_FRAG_NODE:
2408 case XML_NOTATION_NODE:
2409 case XML_HTML_DOCUMENT_NODE:
2410 return;
2411 case XML_ELEMENT_NODE:
2412 case XML_ATTRIBUTE_NODE:
2413 case XML_PI_NODE:
2414 case XML_ENTITY_REF_NODE:
2415 case XML_ENTITY_NODE:
2416 break;
2417 }
2418 if (cur->name != NULL) xmlFree((xmlChar *) cur->name);
2419 cur->name = xmlStrdup(name);
2420}
2421
2422/**
Daniel Veillard10a2c651999-12-12 13:03:50 +00002423 * xmlNodeGetBase:
2424 * @doc: the document the node pertains to
2425 * @cur: the node being checked
2426 *
2427 * Searches for the BASE URL. The code should work on both XML
2428 * and HTML document even if base mechanisms are completely different.
2429 *
2430 * Returns a pointer to the base URL, or NULL if not found
2431 * It's up to the caller to free the memory.
2432 */
2433xmlChar *
2434xmlNodeGetBase(xmlDocPtr doc, xmlNodePtr cur) {
2435 xmlChar *base;
2436
2437 if ((cur == NULL) && (doc == NULL))
2438 return(NULL);
2439 if (doc == NULL) doc = cur->doc;
2440 if ((doc != NULL) && (doc->type == XML_HTML_DOCUMENT_NODE)) {
2441 cur = doc->root;
2442 while ((cur != NULL) && (cur->name != NULL)) {
2443 if (cur->type != XML_ELEMENT_NODE) {
2444 cur = cur->next;
2445 continue;
2446 }
2447 if ((!xmlStrcmp(cur->name, BAD_CAST "html")) ||
2448 (!xmlStrcmp(cur->name, BAD_CAST "HTML"))) {
2449 cur = cur->childs;
2450 continue;
2451 }
2452 if ((!xmlStrcmp(cur->name, BAD_CAST "head")) ||
2453 (!xmlStrcmp(cur->name, BAD_CAST "HEAD"))) {
2454 cur = cur->childs;
2455 continue;
2456 }
2457 if ((!xmlStrcmp(cur->name, BAD_CAST "base")) ||
2458 (!xmlStrcmp(cur->name, BAD_CAST "BASE"))) {
2459 base = xmlGetProp(cur, BAD_CAST "href");
2460 if (base != NULL) return(base);
2461 return(xmlGetProp(cur, BAD_CAST "HREF"));
2462 }
2463 }
2464 return(NULL);
2465 }
2466 while (cur != NULL) {
2467 base = xmlGetProp(cur, BAD_CAST "xml:base");
2468 if (base != NULL)
2469 return(base);
2470 cur = cur->parent;
2471 }
2472 return(NULL);
2473}
2474
2475/**
Daniel Veillard16253641998-10-28 22:58:05 +00002476 * xmlNodeGetContent:
2477 * @cur: the node being read
2478 *
2479 * Read the value of a node, this can be either the text carried
2480 * directly by this node if it's a TEXT node or the aggregate string
2481 * of the values carried by this node child's (TEXT and ENTITY_REF).
2482 * Entity references are substitued.
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002483 * Returns a new xmlChar * or NULL if no content is available.
Daniel Veillard5099ae81999-04-21 20:12:07 +00002484 * It's up to the caller to free the memory.
Daniel Veillard16253641998-10-28 22:58:05 +00002485 */
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002486xmlChar *
Daniel Veillard16253641998-10-28 22:58:05 +00002487xmlNodeGetContent(xmlNodePtr cur) {
2488 if (cur == NULL) return(NULL);
2489 switch (cur->type) {
2490 case XML_DOCUMENT_FRAG_NODE:
2491 case XML_ELEMENT_NODE:
2492 return(xmlNodeListGetString(cur->doc, cur->childs, 1));
2493 break;
Daniel Veillardb96e6431999-08-29 21:02:19 +00002494 case XML_ATTRIBUTE_NODE: {
2495 xmlAttrPtr attr = (xmlAttrPtr) cur;
2496 if (attr->node != NULL)
2497 return(xmlNodeListGetString(attr->node->doc, attr->val, 1));
2498 else
2499 return(xmlNodeListGetString(NULL, attr->val, 1));
2500 break;
2501 }
2502 case XML_PI_NODE:
2503 if (cur->content != NULL)
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002504#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardb96e6431999-08-29 21:02:19 +00002505 return(xmlStrdup(cur->content));
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002506#else
2507 return(xmlStrdup(xmlBufferContent(cur->content)));
2508#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +00002509 return(NULL);
Daniel Veillard16253641998-10-28 22:58:05 +00002510 case XML_ENTITY_REF_NODE:
2511 case XML_ENTITY_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002512 case XML_COMMENT_NODE:
2513 case XML_DOCUMENT_NODE:
Daniel Veillard7c1206f1999-10-14 09:10:25 +00002514 case XML_HTML_DOCUMENT_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002515 case XML_DOCUMENT_TYPE_NODE:
2516 case XML_NOTATION_NODE:
2517 return(NULL);
Daniel Veillardb05deb71999-08-10 19:04:08 +00002518 case XML_CDATA_SECTION_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002519 case XML_TEXT_NODE:
2520 if (cur->content != NULL)
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002521#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard16253641998-10-28 22:58:05 +00002522 return(xmlStrdup(cur->content));
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002523#else
2524 return(xmlStrdup(xmlBufferContent(cur->content)));
2525#endif
Daniel Veillard16253641998-10-28 22:58:05 +00002526 return(NULL);
2527 }
2528 return(NULL);
2529}
2530
2531/**
Daniel Veillard97b58771998-10-20 06:14:16 +00002532 * xmlNodeSetContent:
2533 * @cur: the node being modified
2534 * @content: the new value of the content
2535 *
2536 * Replace the content of a node.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002537 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002538void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002539xmlNodeSetContent(xmlNodePtr cur, const xmlChar *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002540 if (cur == NULL) {
2541 fprintf(stderr, "xmlNodeSetContent : node == NULL\n");
2542 return;
2543 }
Daniel Veillard16253641998-10-28 22:58:05 +00002544 switch (cur->type) {
2545 case XML_DOCUMENT_FRAG_NODE:
2546 case XML_ELEMENT_NODE:
2547 if (cur->content != NULL) {
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002548#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard6454aec1999-09-02 22:04:43 +00002549 xmlFree(cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002550#else
2551 xmlBufferFree(cur->content);
2552#endif
Daniel Veillard16253641998-10-28 22:58:05 +00002553 cur->content = NULL;
2554 }
Daniel Veillard6454aec1999-09-02 22:04:43 +00002555 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillard16253641998-10-28 22:58:05 +00002556 cur->childs = xmlStringGetNodeList(cur->doc, content);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002557 UPDATE_LAST_CHILD(cur)
Daniel Veillard16253641998-10-28 22:58:05 +00002558 break;
2559 case XML_ATTRIBUTE_NODE:
2560 break;
2561 case XML_TEXT_NODE:
2562 case XML_CDATA_SECTION_NODE:
2563 case XML_ENTITY_REF_NODE:
2564 case XML_ENTITY_NODE:
2565 case XML_PI_NODE:
2566 case XML_COMMENT_NODE:
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002567 if (cur->content != NULL) {
2568#ifndef XML_USE_BUFFER_CONTENT
2569 xmlFree(cur->content);
2570#else
2571 xmlBufferFree(cur->content);
2572#endif
2573 }
Daniel Veillard6454aec1999-09-02 22:04:43 +00002574 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002575 cur->last = cur->childs = NULL;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002576 if (content != NULL) {
2577#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard16253641998-10-28 22:58:05 +00002578 cur->content = xmlStrdup(content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002579#else
2580 cur->content = xmlBufferCreateSize(0);
2581 xmlBufferSetAllocationScheme(cur->content,
2582 xmlGetBufferAllocationScheme());
2583 xmlBufferAdd(cur->content, content, -1);
2584#endif
2585 } else
Daniel Veillard16253641998-10-28 22:58:05 +00002586 cur->content = NULL;
Daniel Veillardb96e6431999-08-29 21:02:19 +00002587 break;
Daniel Veillard16253641998-10-28 22:58:05 +00002588 case XML_DOCUMENT_NODE:
Daniel Veillard7c1206f1999-10-14 09:10:25 +00002589 case XML_HTML_DOCUMENT_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002590 case XML_DOCUMENT_TYPE_NODE:
2591 break;
2592 case XML_NOTATION_NODE:
2593 break;
2594 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002595}
2596
Daniel Veillard97b58771998-10-20 06:14:16 +00002597/**
2598 * xmlNodeSetContentLen:
2599 * @cur: the node being modified
2600 * @content: the new value of the content
2601 * @len: the size of @content
2602 *
2603 * Replace the content of a node.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002604 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002605void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002606xmlNodeSetContentLen(xmlNodePtr cur, const xmlChar *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002607 if (cur == NULL) {
Daniel Veillard16253641998-10-28 22:58:05 +00002608 fprintf(stderr, "xmlNodeSetContentLen : node == NULL\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002609 return;
2610 }
Daniel Veillard16253641998-10-28 22:58:05 +00002611 switch (cur->type) {
2612 case XML_DOCUMENT_FRAG_NODE:
2613 case XML_ELEMENT_NODE:
2614 if (cur->content != NULL) {
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002615#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard6454aec1999-09-02 22:04:43 +00002616 xmlFree(cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002617#else
2618 xmlBufferFree(cur->content);
2619#endif
Daniel Veillard16253641998-10-28 22:58:05 +00002620 cur->content = NULL;
2621 }
Daniel Veillard6454aec1999-09-02 22:04:43 +00002622 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillard16253641998-10-28 22:58:05 +00002623 cur->childs = xmlStringLenGetNodeList(cur->doc, content, len);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002624 UPDATE_LAST_CHILD(cur)
Daniel Veillard16253641998-10-28 22:58:05 +00002625 break;
2626 case XML_ATTRIBUTE_NODE:
2627 break;
2628 case XML_TEXT_NODE:
2629 case XML_CDATA_SECTION_NODE:
2630 case XML_ENTITY_REF_NODE:
2631 case XML_ENTITY_NODE:
2632 case XML_PI_NODE:
2633 case XML_COMMENT_NODE:
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002634 case XML_NOTATION_NODE:
2635 if (cur->content != NULL) {
2636#ifndef XML_USE_BUFFER_CONTENT
2637 xmlFree(cur->content);
2638#else
2639 xmlBufferFree(cur->content);
2640#endif
2641 }
Daniel Veillard6454aec1999-09-02 22:04:43 +00002642 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002643 cur->childs = cur->last = NULL;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002644 if (content != NULL) {
2645#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard16253641998-10-28 22:58:05 +00002646 cur->content = xmlStrndup(content, len);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002647#else
2648 cur->content = xmlBufferCreateSize(len);
2649 xmlBufferSetAllocationScheme(cur->content,
2650 xmlGetBufferAllocationScheme());
2651 xmlBufferAdd(cur->content, content, len);
2652#endif
2653 } else
Daniel Veillard16253641998-10-28 22:58:05 +00002654 cur->content = NULL;
Daniel Veillardb96e6431999-08-29 21:02:19 +00002655 break;
Daniel Veillard16253641998-10-28 22:58:05 +00002656 case XML_DOCUMENT_NODE:
Daniel Veillard7c1206f1999-10-14 09:10:25 +00002657 case XML_HTML_DOCUMENT_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002658 case XML_DOCUMENT_TYPE_NODE:
2659 break;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002660 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002661}
2662
Daniel Veillard97b58771998-10-20 06:14:16 +00002663/**
2664 * xmlNodeAddContentLen:
2665 * @cur: the node being modified
2666 * @content: extra content
2667 * @len: the size of @content
2668 *
2669 * Append the extra substring to the node content.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002670 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002671void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002672xmlNodeAddContentLen(xmlNodePtr cur, const xmlChar *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002673 if (cur == NULL) {
Daniel Veillard16253641998-10-28 22:58:05 +00002674 fprintf(stderr, "xmlNodeAddContentLen : node == NULL\n");
2675 return;
2676 }
2677 if (len <= 0) return;
2678 switch (cur->type) {
2679 case XML_DOCUMENT_FRAG_NODE:
2680 case XML_ELEMENT_NODE: {
2681 xmlNodePtr last = NULL, new;
2682
2683 if (cur->childs != NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002684 last = cur->last;
Daniel Veillard16253641998-10-28 22:58:05 +00002685 } else {
2686 if (cur->content != NULL) {
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002687#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard16253641998-10-28 22:58:05 +00002688 cur->childs = xmlStringGetNodeList(cur->doc, cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002689#else
2690 cur->childs = xmlStringGetNodeList(cur->doc,
2691 xmlBufferContent(cur->content));
2692#endif
Daniel Veillard1e346af1999-02-22 10:33:01 +00002693 UPDATE_LAST_CHILD(cur)
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002694#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard6454aec1999-09-02 22:04:43 +00002695 xmlFree(cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002696#else
2697 xmlBufferFree(cur->content);
2698#endif
Daniel Veillard16253641998-10-28 22:58:05 +00002699 cur->content = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002700 last = cur->last;
Daniel Veillard16253641998-10-28 22:58:05 +00002701 }
2702 }
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002703 new = xmlNewTextLen(content, len);
Daniel Veillard16253641998-10-28 22:58:05 +00002704 if (new != NULL) {
2705 xmlAddChild(cur, new);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002706 if ((last != NULL) && (last->next == new)) {
Daniel Veillard16253641998-10-28 22:58:05 +00002707 xmlTextMerge(last, new);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002708 }
Daniel Veillard16253641998-10-28 22:58:05 +00002709 }
2710 break;
2711 }
2712 case XML_ATTRIBUTE_NODE:
2713 break;
2714 case XML_TEXT_NODE:
2715 case XML_CDATA_SECTION_NODE:
2716 case XML_ENTITY_REF_NODE:
2717 case XML_ENTITY_NODE:
2718 case XML_PI_NODE:
2719 case XML_COMMENT_NODE:
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002720 case XML_NOTATION_NODE:
2721 if (content != NULL) {
2722#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard16253641998-10-28 22:58:05 +00002723 cur->content = xmlStrncat(cur->content, content, len);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002724#else
2725 xmlBufferAdd(cur->content, content, len);
2726#endif
2727 }
Daniel Veillard16253641998-10-28 22:58:05 +00002728 case XML_DOCUMENT_NODE:
Daniel Veillard7c1206f1999-10-14 09:10:25 +00002729 case XML_HTML_DOCUMENT_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002730 case XML_DOCUMENT_TYPE_NODE:
2731 break;
Daniel Veillard16253641998-10-28 22:58:05 +00002732 }
2733}
2734
2735/**
2736 * xmlNodeAddContent:
2737 * @cur: the node being modified
2738 * @content: extra content
2739 *
2740 * Append the extra substring to the node content.
2741 */
2742void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002743xmlNodeAddContent(xmlNodePtr cur, const xmlChar *content) {
Daniel Veillard16253641998-10-28 22:58:05 +00002744 int len;
2745
2746 if (cur == NULL) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002747 fprintf(stderr, "xmlNodeAddContent : node == NULL\n");
2748 return;
2749 }
Daniel Veillard16253641998-10-28 22:58:05 +00002750 if (content == NULL) return;
2751 len = xmlStrlen(content);
2752 xmlNodeAddContentLen(cur, content, len);
2753}
2754
2755/**
2756 * xmlTextMerge:
2757 * @first: the first text node
2758 * @second: the second text node being merged
2759 *
2760 * Merge two text nodes into one
Daniel Veillard1e346af1999-02-22 10:33:01 +00002761 * Returns the first text node augmented
Daniel Veillard16253641998-10-28 22:58:05 +00002762 */
2763xmlNodePtr
2764xmlTextMerge(xmlNodePtr first, xmlNodePtr second) {
2765 if (first == NULL) return(second);
2766 if (second == NULL) return(first);
2767 if (first->type != XML_TEXT_NODE) return(first);
2768 if (second->type != XML_TEXT_NODE) return(first);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002769#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard16253641998-10-28 22:58:05 +00002770 xmlNodeAddContent(first, second->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002771#else
2772 xmlNodeAddContent(first, xmlBufferContent(second->content));
2773#endif
Daniel Veillard16253641998-10-28 22:58:05 +00002774 xmlUnlinkNode(second);
2775 xmlFreeNode(second);
2776 return(first);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002777}
2778
Daniel Veillard97b58771998-10-20 06:14:16 +00002779/**
Daniel Veillardb96e6431999-08-29 21:02:19 +00002780 * xmlGetNsList:
2781 * @doc: the document
2782 * @node: the current node
2783 *
2784 * Search all the namespace applying to a given element.
2785 * Returns an NULL terminated array of all the xmlNsPtr found
2786 * that need to be freed by the caller or NULL if no
2787 * namespace if defined
2788 */
2789xmlNsPtr *
2790xmlGetNsList(xmlDocPtr doc, xmlNodePtr node) {
2791 xmlNsPtr cur;
2792 xmlNsPtr *ret = NULL;
2793 int nbns = 0;
2794 int maxns = 10;
2795 int i;
2796
2797 while (node != NULL) {
2798 cur = node->nsDef;
2799 while (cur != NULL) {
2800 if (ret == NULL) {
Daniel Veillard6454aec1999-09-02 22:04:43 +00002801 ret = (xmlNsPtr *) xmlMalloc((maxns + 1) * sizeof(xmlNsPtr));
Daniel Veillardb96e6431999-08-29 21:02:19 +00002802 if (ret == NULL) {
2803 fprintf(stderr, "xmlGetNsList : out of memory!\n");
2804 return(NULL);
2805 }
2806 ret[nbns] = NULL;
2807 }
2808 for (i = 0;i < nbns;i++) {
2809 if ((cur->prefix == ret[i]->prefix) ||
2810 (!xmlStrcmp(cur->prefix, ret[i]->prefix))) break;
2811 }
2812 if (i >= nbns) {
2813 if (nbns >= maxns) {
2814 maxns *= 2;
Daniel Veillard6454aec1999-09-02 22:04:43 +00002815 ret = (xmlNsPtr *) xmlRealloc(ret,
Daniel Veillardb96e6431999-08-29 21:02:19 +00002816 (maxns + 1) * sizeof(xmlNsPtr));
2817 if (ret == NULL) {
2818 fprintf(stderr, "xmlGetNsList : realloc failed!\n");
2819 return(NULL);
2820 }
2821 }
2822 ret[nbns++] = cur;
2823 ret[nbns] = NULL;
2824 }
2825
2826 cur = cur->next;
2827 }
2828 node = node->parent;
2829 }
2830 return(ret);
2831}
2832
2833/**
Daniel Veillard97b58771998-10-20 06:14:16 +00002834 * xmlSearchNs:
2835 * @doc: the document
2836 * @node: the current node
2837 * @nameSpace: the namespace string
Daniel Veillard260a68f1998-08-13 03:39:55 +00002838 *
Daniel Veillard97b58771998-10-20 06:14:16 +00002839 * Search a Ns registered under a given name space for a document.
2840 * recurse on the parents until it finds the defined namespace
2841 * or return NULL otherwise.
2842 * @nameSpace can be NULL, this is a search for the default namespace.
Daniel Veillard1e346af1999-02-22 10:33:01 +00002843 * Returns the namespace pointer or NULL.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002844 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002845xmlNsPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002846xmlSearchNs(xmlDocPtr doc, xmlNodePtr node, const xmlChar *nameSpace) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002847 xmlNsPtr cur;
2848
Daniel Veillard62ba71e1999-12-16 17:52:19 +00002849 if (node == NULL) return(NULL);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002850 while (node != NULL) {
2851 cur = node->nsDef;
2852 while (cur != NULL) {
2853 if ((cur->prefix == NULL) && (nameSpace == NULL))
2854 return(cur);
2855 if ((cur->prefix != NULL) && (nameSpace != NULL) &&
2856 (!xmlStrcmp(cur->prefix, nameSpace)))
2857 return(cur);
2858 cur = cur->next;
2859 }
2860 node = node->parent;
2861 }
Daniel Veillard10a2c651999-12-12 13:03:50 +00002862#if 0
2863 /* Removed support for old namespaces */
Daniel Veillard260a68f1998-08-13 03:39:55 +00002864 if (doc != NULL) {
2865 cur = doc->oldNs;
2866 while (cur != NULL) {
2867 if ((cur->prefix != NULL) && (nameSpace != NULL) &&
2868 (!xmlStrcmp(cur->prefix, nameSpace)))
2869 return(cur);
2870 cur = cur->next;
2871 }
2872 }
Daniel Veillard10a2c651999-12-12 13:03:50 +00002873#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00002874 return(NULL);
2875}
2876
Daniel Veillard97b58771998-10-20 06:14:16 +00002877/**
2878 * xmlSearchNsByHref:
2879 * @doc: the document
2880 * @node: the current node
2881 * @href: the namespace value
2882 *
2883 * Search a Ns aliasing a given URI. Recurse on the parents until it finds
2884 * the defined namespace or return NULL otherwise.
Daniel Veillard1e346af1999-02-22 10:33:01 +00002885 * Returns the namespace pointer or NULL.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002886 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002887xmlNsPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002888xmlSearchNsByHref(xmlDocPtr doc, xmlNodePtr node, const xmlChar *href) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002889 xmlNsPtr cur;
2890
Daniel Veillard10a2c651999-12-12 13:03:50 +00002891 if ((node == NULL) || (href == NULL)) return(NULL);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002892 while (node != NULL) {
2893 cur = node->nsDef;
2894 while (cur != NULL) {
2895 if ((cur->href != NULL) && (href != NULL) &&
2896 (!xmlStrcmp(cur->href, href)))
2897 return(cur);
2898 cur = cur->next;
2899 }
2900 node = node->parent;
2901 }
Daniel Veillard10a2c651999-12-12 13:03:50 +00002902#if 0
2903 /* Removed support for old namespaces */
Daniel Veillard260a68f1998-08-13 03:39:55 +00002904 if (doc != NULL) {
2905 cur = doc->oldNs;
2906 while (cur != NULL) {
2907 if ((cur->href != NULL) && (href != NULL) &&
2908 (!xmlStrcmp(cur->href, href)))
2909 return(cur);
2910 cur = cur->next;
2911 }
2912 }
Daniel Veillard10a2c651999-12-12 13:03:50 +00002913#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00002914 return(NULL);
2915}
2916
Daniel Veillard97b58771998-10-20 06:14:16 +00002917/**
2918 * xmlGetProp:
2919 * @node: the node
2920 * @name: the attribute name
2921 *
2922 * Search and get the value of an attribute associated to a node
Daniel Veillardccb09631998-10-27 06:21:04 +00002923 * This does the entity substitution.
Daniel Veillard10a2c651999-12-12 13:03:50 +00002924 * This function looks in DTD attribute declaration for #FIXED or
2925 * default declaration values unless DTD use has been turned off.
2926 *
Daniel Veillard1e346af1999-02-22 10:33:01 +00002927 * Returns the attribute value or NULL if not found.
Daniel Veillarda819dac1999-11-24 18:04:22 +00002928 * It's up to the caller to free the memory.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002929 */
Daniel Veillarda819dac1999-11-24 18:04:22 +00002930xmlChar *
2931xmlGetProp(xmlNodePtr node, const xmlChar *name) {
Daniel Veillard10a2c651999-12-12 13:03:50 +00002932 xmlAttrPtr prop;
2933 xmlDocPtr doc;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002934
Daniel Veillard10a2c651999-12-12 13:03:50 +00002935 if ((node == NULL) || (name == NULL)) return(NULL);
2936 /*
2937 * Check on the properties attached to the node
2938 */
2939 prop = node->properties;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002940 while (prop != NULL) {
Daniel Veillard68178931999-02-08 18:34:36 +00002941 if (!xmlStrcmp(prop->name, name)) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002942 xmlChar *ret;
Daniel Veillard6800ef31999-02-08 18:33:22 +00002943
2944 ret = xmlNodeListGetString(node->doc, prop->val, 1);
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002945 if (ret == NULL) return(xmlStrdup((xmlChar *)""));
Daniel Veillard6800ef31999-02-08 18:33:22 +00002946 return(ret);
Daniel Veillard68178931999-02-08 18:34:36 +00002947 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002948 prop = prop->next;
2949 }
Daniel Veillard10a2c651999-12-12 13:03:50 +00002950 if (!xmlCheckDTD) return(NULL);
2951
2952 /*
2953 * Check if there is a default declaration in the internal
2954 * or external subsets
2955 */
2956 doc = node->doc;
2957 if (doc != NULL) {
2958 xmlAttributePtr attrDecl;
2959 if (doc->intSubset != NULL) {
2960 attrDecl = xmlGetDtdAttrDesc(doc->intSubset, node->name, name);
2961 if ((attrDecl == NULL) && (doc->extSubset != NULL))
2962 attrDecl = xmlGetDtdAttrDesc(doc->extSubset, node->name, name);
2963 return(xmlStrdup(attrDecl->defaultValue));
2964 }
2965 }
2966 return(NULL);
2967}
2968
2969/**
2970 * xmlGetNsProp:
2971 * @node: the node
2972 * @name: the attribute name
2973 * @namespace: the URI of the namespace
2974 *
2975 * Search and get the value of an attribute associated to a node
2976 * This attribute has to be anchored in the namespace specified.
2977 * This does the entity substitution.
2978 * This function looks in DTD attribute declaration for #FIXED or
2979 * default declaration values unless DTD use has been turned off.
2980 *
2981 * Returns the attribute value or NULL if not found.
2982 * It's up to the caller to free the memory.
2983 */
2984xmlChar *
2985xmlGetNsProp(xmlNodePtr node, const xmlChar *name, const xmlChar *namespace) {
2986 xmlAttrPtr prop = node->properties;
2987 xmlDocPtr doc;
2988 xmlNsPtr ns;
2989
2990 if (namespace == NULL)
2991 return(xmlGetProp(node, name));
2992 while (prop != NULL) {
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00002993 /*
2994 * One need to have
2995 * - same attribute names
2996 * - and the attribute carrying that namespace
2997 * or
2998 * no namespace on the attribute and the element carrying it
2999 */
Daniel Veillard10a2c651999-12-12 13:03:50 +00003000 if ((!xmlStrcmp(prop->name, name)) &&
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00003001 (((prop->ns == NULL) && (node->ns != NULL) &&
3002 (!xmlStrcmp(node->ns->href, namespace))) ||
3003 (prop->ns != NULL) && (!xmlStrcmp(prop->ns->href, namespace)))) {
Daniel Veillard10a2c651999-12-12 13:03:50 +00003004 xmlChar *ret;
3005
3006 ret = xmlNodeListGetString(node->doc, prop->val, 1);
3007 if (ret == NULL) return(xmlStrdup((xmlChar *)""));
3008 return(ret);
3009 }
3010 prop = prop->next;
3011 }
3012 if (!xmlCheckDTD) return(NULL);
3013
3014 /*
3015 * Check if there is a default declaration in the internal
3016 * or external subsets
3017 */
3018 doc = node->doc;
3019 if (doc != NULL) {
3020 xmlAttributePtr attrDecl;
3021 if (doc->intSubset != NULL) {
3022 attrDecl = xmlGetDtdAttrDesc(doc->intSubset, node->name, name);
3023 if ((attrDecl == NULL) && (doc->extSubset != NULL))
3024 attrDecl = xmlGetDtdAttrDesc(doc->extSubset, node->name, name);
3025
3026 if (attrDecl->prefix != NULL) {
3027 /*
3028 * The DTD declaration only allows a prefix search
3029 */
3030 ns = xmlSearchNs(doc, node, attrDecl->prefix);
3031 if ((ns != NULL) && (!xmlStrcmp(ns->href, namespace)))
3032 return(xmlStrdup(attrDecl->defaultValue));
3033 }
3034 }
3035 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003036 return(NULL);
3037}
3038
Daniel Veillard97b58771998-10-20 06:14:16 +00003039/**
Daniel Veillardccb09631998-10-27 06:21:04 +00003040 * xmlSetProp:
Daniel Veillard97b58771998-10-20 06:14:16 +00003041 * @node: the node
3042 * @name: the attribute name
3043 * @value: the attribute value
3044 *
3045 * Set (or reset) an attribute carried by a node.
Daniel Veillard1e346af1999-02-22 10:33:01 +00003046 * Returns the attribute pointer.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003047 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003048xmlAttrPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003049xmlSetProp(xmlNodePtr node, const xmlChar *name, const xmlChar *value) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003050 xmlAttrPtr prop = node->properties;
3051
3052 while (prop != NULL) {
3053 if (!xmlStrcmp(prop->name, name)) {
Daniel Veillardccb09631998-10-27 06:21:04 +00003054 if (prop->val != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +00003055 xmlFreeNodeList(prop->val);
Daniel Veillardccb09631998-10-27 06:21:04 +00003056 prop->val = NULL;
Daniel Veillard51e3b151999-11-12 17:02:31 +00003057 if (value != NULL) {
3058 xmlChar *buffer;
3059 buffer = xmlEncodeEntitiesReentrant(node->doc, value);
3060 prop->val = xmlStringGetNodeList(node->doc, buffer);
3061 xmlFree(buffer);
3062 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003063 return(prop);
3064 }
3065 prop = prop->next;
3066 }
3067 prop = xmlNewProp(node, name, value);
3068 return(prop);
3069}
3070
Daniel Veillard97b58771998-10-20 06:14:16 +00003071/**
3072 * xmlNodeIsText:
3073 * @node: the node
3074 *
3075 * Is this node a Text node ?
Daniel Veillard1e346af1999-02-22 10:33:01 +00003076 * Returns 1 yes, 0 no
Daniel Veillard260a68f1998-08-13 03:39:55 +00003077 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003078int
3079xmlNodeIsText(xmlNodePtr node) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003080 if (node == NULL) return(0);
3081
Daniel Veillard0bef1311998-10-14 02:36:47 +00003082 if (node->type == XML_TEXT_NODE) return(1);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003083 return(0);
3084}
3085
Daniel Veillard97b58771998-10-20 06:14:16 +00003086/**
Daniel Veillard1e346af1999-02-22 10:33:01 +00003087 * xmlTextConcat:
Daniel Veillard97b58771998-10-20 06:14:16 +00003088 * @node: the node
3089 * @content: the content
3090 * @len: @content lenght
3091 *
3092 * Concat the given string at the end of the existing node content
Daniel Veillard260a68f1998-08-13 03:39:55 +00003093 */
Daniel Veillard97b58771998-10-20 06:14:16 +00003094
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003095void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003096xmlTextConcat(xmlNodePtr node, const xmlChar *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003097 if (node == NULL) return;
3098
Daniel Veillard0bef1311998-10-14 02:36:47 +00003099 if (node->type != XML_TEXT_NODE) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003100 fprintf(stderr, "xmlTextConcat: node is not text\n");
3101 return;
3102 }
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003103#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard260a68f1998-08-13 03:39:55 +00003104 node->content = xmlStrncat(node->content, content, len);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003105#else
3106 xmlBufferAdd(node->content, content, len);
3107#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00003108}
3109
3110/************************************************************************
3111 * *
3112 * Output : to a FILE or in memory *
3113 * *
3114 ************************************************************************/
3115
Daniel Veillard5099ae81999-04-21 20:12:07 +00003116#define BASE_BUFFER_SIZE 4000
3117
3118/**
3119 * xmlBufferCreate:
3120 *
3121 * routine to create an XML buffer.
3122 * returns the new structure.
3123 */
3124xmlBufferPtr
3125xmlBufferCreate(void) {
3126 xmlBufferPtr ret;
3127
Daniel Veillard6454aec1999-09-02 22:04:43 +00003128 ret = (xmlBufferPtr) xmlMalloc(sizeof(xmlBuffer));
Daniel Veillard5099ae81999-04-21 20:12:07 +00003129 if (ret == NULL) {
3130 fprintf(stderr, "xmlBufferCreate : out of memory!\n");
3131 return(NULL);
3132 }
3133 ret->use = 0;
3134 ret->size = BASE_BUFFER_SIZE;
Daniel Veillard10a2c651999-12-12 13:03:50 +00003135 ret->alloc = xmlBufferAllocScheme;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003136 ret->content = (xmlChar *) xmlMalloc(ret->size * sizeof(xmlChar));
Daniel Veillard5099ae81999-04-21 20:12:07 +00003137 if (ret->content == NULL) {
3138 fprintf(stderr, "xmlBufferCreate : out of memory!\n");
Daniel Veillard6454aec1999-09-02 22:04:43 +00003139 xmlFree(ret);
Daniel Veillard5099ae81999-04-21 20:12:07 +00003140 return(NULL);
3141 }
3142 ret->content[0] = 0;
3143 return(ret);
3144}
3145
3146/**
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003147 * xmlBufferCreateSize:
3148 * @size: initial size of buffer
3149 *
3150 * routine to create an XML buffer.
3151 * returns the new structure.
3152 */
3153xmlBufferPtr
3154xmlBufferCreateSize(size_t size) {
3155 xmlBufferPtr ret;
3156
3157 ret = (xmlBufferPtr) xmlMalloc(sizeof(xmlBuffer));
3158 if (ret == NULL) {
3159 fprintf(stderr, "xmlBufferCreate : out of memory!\n");
3160 return(NULL);
3161 }
3162 ret->use = 0;
Daniel Veillard10a2c651999-12-12 13:03:50 +00003163 ret->alloc = xmlBufferAllocScheme;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003164 ret->size = (size ? size+2 : 0); /* +1 for ending null */
Daniel Veillard10a2c651999-12-12 13:03:50 +00003165 if (ret->size){
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003166 ret->content = (xmlChar *) xmlMalloc(ret->size * sizeof(xmlChar));
3167 if (ret->content == NULL) {
3168 fprintf(stderr, "xmlBufferCreate : out of memory!\n");
3169 xmlFree(ret);
3170 return(NULL);
3171 }
3172 ret->content[0] = 0;
3173 } else
3174 ret->content = NULL;
3175 return(ret);
3176}
3177
3178/**
3179 * xmlBufferAllocationScheme:
3180 * @buf: the buffer to free
3181 * @scheme: allocation scheme to use
3182 *
3183 * Sets the allocation scheme for this buffer
3184 */
3185void
3186xmlBufferSetAllocationScheme(xmlBufferPtr buf,
3187 xmlBufferAllocationScheme scheme) {
3188 if (buf == NULL) {
3189 fprintf(stderr, "xmlBufferSetAllocationScheme: buf == NULL\n");
3190 return;
3191 }
3192
3193 buf->alloc = scheme;
3194}
3195
3196/**
Daniel Veillard5099ae81999-04-21 20:12:07 +00003197 * xmlBufferFree:
3198 * @buf: the buffer to free
3199 *
3200 * Frees an XML buffer.
3201 */
3202void
3203xmlBufferFree(xmlBufferPtr buf) {
3204 if (buf == NULL) {
3205 fprintf(stderr, "xmlBufferFree: buf == NULL\n");
3206 return;
3207 }
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003208 if (buf->content != NULL) {
3209#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard5099ae81999-04-21 20:12:07 +00003210 memset(buf->content, -1, BASE_BUFFER_SIZE);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003211#else
3212 memset(buf->content, -1, buf->size);
3213#endif
Daniel Veillard6454aec1999-09-02 22:04:43 +00003214 xmlFree(buf->content);
Daniel Veillard5099ae81999-04-21 20:12:07 +00003215 }
3216 memset(buf, -1, sizeof(xmlBuffer));
Daniel Veillard6454aec1999-09-02 22:04:43 +00003217 xmlFree(buf);
Daniel Veillard5099ae81999-04-21 20:12:07 +00003218}
3219
3220/**
Daniel Veillarde2d034d1999-07-27 19:52:06 +00003221 * xmlBufferEmpty:
3222 * @buf: the buffer
3223 *
3224 * empty a buffer.
3225 */
3226void
3227xmlBufferEmpty(xmlBufferPtr buf) {
3228 buf->use = 0;
3229 memset(buf->content, -1, buf->size);/* just for debug */
3230}
3231
3232/**
3233 * xmlBufferShrink:
3234 * @buf: the buffer to dump
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003235 * @len: the number of xmlChar to remove
Daniel Veillarde2d034d1999-07-27 19:52:06 +00003236 *
3237 * Remove the beginning of an XML buffer.
3238 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003239 * Returns the number of xmlChar removed, or -1 in case of failure.
Daniel Veillarde2d034d1999-07-27 19:52:06 +00003240 */
3241int
3242xmlBufferShrink(xmlBufferPtr buf, int len) {
3243 if (len == 0) return(0);
3244 if (len > buf->use) return(-1);
3245
3246 buf->use -= len;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003247 memmove(buf->content, &buf->content[len], buf->use * sizeof(xmlChar));
Daniel Veillarde2d034d1999-07-27 19:52:06 +00003248
3249 buf->content[buf->use] = 0;
3250 return(len);
3251}
3252
3253/**
Daniel Veillard5099ae81999-04-21 20:12:07 +00003254 * xmlBufferDump:
3255 * @file: the file output
3256 * @buf: the buffer to dump
3257 *
3258 * Dumps an XML buffer to a FILE *.
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003259 * Returns the number of xmlChar written
Daniel Veillard5099ae81999-04-21 20:12:07 +00003260 */
3261int
3262xmlBufferDump(FILE *file, xmlBufferPtr buf) {
3263 int ret;
3264
3265 if (buf == NULL) {
3266 fprintf(stderr, "xmlBufferDump: buf == NULL\n");
3267 return(0);
3268 }
3269 if (buf->content == NULL) {
3270 fprintf(stderr, "xmlBufferDump: buf->content == NULL\n");
3271 return(0);
3272 }
3273 if (file == NULL) file = stdout;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003274 ret = fwrite(buf->content, sizeof(xmlChar), buf->use, file);
Daniel Veillard5099ae81999-04-21 20:12:07 +00003275 return(ret);
3276}
3277
3278/**
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003279 * xmlBufferContent:
3280 * @buf: the buffer to resize
3281 *
3282 * Returns the internal content
3283 */
3284
3285const xmlChar*
3286xmlBufferContent(const xmlBufferPtr buf)
3287{
3288 if(!buf)
3289 return NULL;
3290
3291 return buf->content;
3292}
3293
3294/**
3295 * xmlBufferLength:
3296 * @buf: the buffer
3297 *
3298 * Returns the length of data in the internal content
3299 */
3300
3301int
3302xmlBufferLength(const xmlBufferPtr buf)
3303{
3304 if(!buf)
3305 return 0;
3306
3307 return buf->use;
3308}
3309
3310/**
3311 * xmlBufferResize:
3312 * @buf: the buffer to resize
3313 * @len: the desired size
3314 *
3315 * Resize a buffer to accomodate minimum size of <len>.
3316 *
3317 * Returns 0 in case of problems, 1 otherwise
3318 */
3319int
3320xmlBufferResize(xmlBufferPtr buf, int size)
3321{
3322 int newSize = (buf->size ? buf->size*2 : size);/*take care of empty case*/
3323 xmlChar* rebuf = NULL;
3324
3325 /* Don't resize if we don't have to */
3326 if(size < buf->size)
3327 return 1;
3328
3329 /* figure out new size */
3330 switch(buf->alloc){
3331 case XML_BUFFER_ALLOC_DOUBLEIT:
3332 while(size > newSize) newSize *= 2;
3333 break;
3334 case XML_BUFFER_ALLOC_EXACT:
3335 newSize = size+10;
3336 break;
3337 default:
3338 newSize = size+10;
3339 break;
3340 }
3341
3342 if (buf->content == NULL)
3343 rebuf = (xmlChar *) xmlMalloc(newSize * sizeof(xmlChar));
3344 else
3345 rebuf = (xmlChar *) xmlRealloc(buf->content,
3346 newSize * sizeof(xmlChar));
3347 if (rebuf == NULL) {
3348 fprintf(stderr, "xmlBufferAdd : out of memory!\n");
3349 return 0;
3350 }
3351 buf->content = rebuf;
3352 buf->size = newSize;
3353
3354 return 1;
3355}
3356/**
Daniel Veillard5099ae81999-04-21 20:12:07 +00003357 * xmlBufferAdd:
3358 * @buf: the buffer to dump
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003359 * @str: the xmlChar string
3360 * @len: the number of xmlChar to add
Daniel Veillard5099ae81999-04-21 20:12:07 +00003361 *
Daniel Veillard10a2c651999-12-12 13:03:50 +00003362 * Add a string range to an XML buffer. if len == -1, the lenght of
3363 * str is recomputed.
Daniel Veillard5099ae81999-04-21 20:12:07 +00003364 */
3365void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003366xmlBufferAdd(xmlBufferPtr buf, const xmlChar *str, int len) {
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003367 int l, needSize;
Daniel Veillard5099ae81999-04-21 20:12:07 +00003368
3369 if (str == NULL) {
3370 fprintf(stderr, "xmlBufferAdd: str == NULL\n");
3371 return;
3372 }
Daniel Veillard10a2c651999-12-12 13:03:50 +00003373 if (len < -1) {
3374 fprintf(stderr, "xmlBufferAdd: len < 0\n");
3375 return;
3376 }
3377 if (len == 0) return;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003378
3379 /* CJN What's this for??? */
Daniel Veillarde2d034d1999-07-27 19:52:06 +00003380 l = xmlStrlen(str);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003381 if (l < len){ len = l; printf("xmlBufferAdd bad length\n"); }
3382
3383 /* CJN 11.18.99 okay, now I'm using the length */
3384 if(len == -1) len = l;
3385
3386
Daniel Veillarde2d034d1999-07-27 19:52:06 +00003387 if (len <= 0) return;
Daniel Veillard5099ae81999-04-21 20:12:07 +00003388
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003389 needSize = buf->use + len + 2;
3390 if(needSize > buf->size){
3391 if(!xmlBufferResize(buf, needSize)){
3392 fprintf(stderr, "xmlBufferAdd : out of memory!\n");
3393 return;
3394 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003395 }
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003396
3397 memmove(&buf->content[buf->use], str, len*sizeof(xmlChar));
Daniel Veillarde2d034d1999-07-27 19:52:06 +00003398 buf->use += len;
3399 buf->content[buf->use] = 0;
Daniel Veillard5099ae81999-04-21 20:12:07 +00003400}
3401
3402/**
3403 * xmlBufferCat:
3404 * @buf: the buffer to dump
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003405 * @str: the xmlChar string
Daniel Veillard5099ae81999-04-21 20:12:07 +00003406 *
3407 * Append a zero terminated string to an XML buffer.
3408 */
3409void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003410xmlBufferCat(xmlBufferPtr buf, const xmlChar *str) {
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003411 if (str != NULL)
3412 xmlBufferAdd(buf, str, -1);
Daniel Veillard5099ae81999-04-21 20:12:07 +00003413}
3414
3415/**
3416 * xmlBufferCCat:
3417 * @buf: the buffer to dump
3418 * @str: the C char string
3419 *
3420 * Append a zero terminated C string to an XML buffer.
3421 */
3422void
3423xmlBufferCCat(xmlBufferPtr buf, const char *str) {
3424 const char *cur;
3425
3426 if (str == NULL) {
3427 fprintf(stderr, "xmlBufferAdd: str == NULL\n");
3428 return;
3429 }
3430 for (cur = str;*cur != 0;cur++) {
3431 if (buf->use + 10 >= buf->size) {
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003432 if(!xmlBufferResize(buf, buf->use+10)){
3433 fprintf(stderr, "xmlBufferCCat : out of memory!\n");
3434 return;
3435 }
3436 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003437 buf->content[buf->use++] = *cur;
3438 }
3439}
Daniel Veillard260a68f1998-08-13 03:39:55 +00003440
Daniel Veillard97b58771998-10-20 06:14:16 +00003441/**
3442 * xmlBufferWriteCHAR:
Daniel Veillard5099ae81999-04-21 20:12:07 +00003443 * @buf: the XML buffer
Daniel Veillard97b58771998-10-20 06:14:16 +00003444 * @string: the string to add
3445 *
3446 * routine which manage and grows an output buffer. This one add
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003447 * xmlChars at the end of the buffer.
Daniel Veillard97b58771998-10-20 06:14:16 +00003448 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003449void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003450xmlBufferWriteCHAR(xmlBufferPtr buf, const xmlChar *string) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003451 xmlBufferCat(buf, string);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003452}
3453
Daniel Veillard97b58771998-10-20 06:14:16 +00003454/**
3455 * xmlBufferWriteChar:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003456 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003457 * @string: the string to add
3458 *
3459 * routine which manage and grows an output buffer. This one add
3460 * C chars at the end of the array.
3461 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003462void
Daniel Veillard5099ae81999-04-21 20:12:07 +00003463xmlBufferWriteChar(xmlBufferPtr buf, const char *string) {
3464 xmlBufferCCat(buf, string);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003465}
3466
Daniel Veillard5099ae81999-04-21 20:12:07 +00003467
Daniel Veillard97b58771998-10-20 06:14:16 +00003468/**
Daniel Veillard011b63c1999-06-02 17:44:04 +00003469 * xmlBufferWriteQuotedString:
3470 * @buf: the XML buffer output
3471 * @string: the string to add
3472 *
3473 * routine which manage and grows an output buffer. This one writes
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003474 * a quoted or double quoted xmlChar string, checking first if it holds
Daniel Veillard011b63c1999-06-02 17:44:04 +00003475 * quote or double-quotes internally
3476 */
3477void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003478xmlBufferWriteQuotedString(xmlBufferPtr buf, const xmlChar *string) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00003479 if (xmlStrchr(string, '"')) {
3480 if (xmlStrchr(string, '\'')) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00003481 fprintf(stderr,
3482 "xmlBufferWriteQuotedString: string contains quote and double-quotes !\n");
3483 }
3484 xmlBufferCCat(buf, "'");
3485 xmlBufferCat(buf, string);
3486 xmlBufferCCat(buf, "'");
3487 } else {
3488 xmlBufferCCat(buf, "\"");
3489 xmlBufferCat(buf, string);
3490 xmlBufferCCat(buf, "\"");
3491 }
3492}
3493
3494
3495/**
Daniel Veillard97b58771998-10-20 06:14:16 +00003496 * xmlGlobalNsDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003497 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003498 * @cur: a namespace
3499 *
3500 * Dump a global Namespace, this is the old version based on PIs.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003501 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003502static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00003503xmlGlobalNsDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003504 if (cur == NULL) {
3505 fprintf(stderr, "xmlGlobalNsDump : Ns == NULL\n");
3506 return;
3507 }
3508 if (cur->type == XML_GLOBAL_NAMESPACE) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003509 xmlBufferWriteChar(buf, "<?namespace");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003510 if (cur->href != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00003511 xmlBufferWriteChar(buf, " href=");
3512 xmlBufferWriteQuotedString(buf, cur->href);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003513 }
3514 if (cur->prefix != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00003515 xmlBufferWriteChar(buf, " AS=");
3516 xmlBufferWriteQuotedString(buf, cur->prefix);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003517 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003518 xmlBufferWriteChar(buf, "?>\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003519 }
3520}
3521
Daniel Veillard97b58771998-10-20 06:14:16 +00003522/**
3523 * xmlGlobalNsListDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003524 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003525 * @cur: the first namespace
3526 *
3527 * Dump a list of global Namespace, this is the old version based on PIs.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003528 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003529static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00003530xmlGlobalNsListDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003531 while (cur != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003532 xmlGlobalNsDump(buf, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003533 cur = cur->next;
3534 }
3535}
3536
Daniel Veillard97b58771998-10-20 06:14:16 +00003537/**
3538 * xmlNsDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003539 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003540 * @cur: a namespace
3541 *
Daniel Veillard260a68f1998-08-13 03:39:55 +00003542 * Dump a local Namespace definition.
Daniel Veillard97b58771998-10-20 06:14:16 +00003543 * Should be called in the context of attributes dumps.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003544 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003545static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00003546xmlNsDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003547 if (cur == NULL) {
3548 fprintf(stderr, "xmlNsDump : Ns == NULL\n");
3549 return;
3550 }
3551 if (cur->type == XML_LOCAL_NAMESPACE) {
3552 /* Within the context of an element attributes */
3553 if (cur->prefix != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003554 xmlBufferWriteChar(buf, " xmlns:");
3555 xmlBufferWriteCHAR(buf, cur->prefix);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003556 } else
Daniel Veillard5099ae81999-04-21 20:12:07 +00003557 xmlBufferWriteChar(buf, " xmlns");
Daniel Veillard011b63c1999-06-02 17:44:04 +00003558 xmlBufferWriteChar(buf, "=");
3559 xmlBufferWriteQuotedString(buf, cur->href);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003560 }
3561}
3562
Daniel Veillard97b58771998-10-20 06:14:16 +00003563/**
3564 * xmlNsListDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003565 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003566 * @cur: the first namespace
3567 *
3568 * Dump a list of local Namespace definitions.
3569 * Should be called in the context of attributes dumps.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003570 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003571static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00003572xmlNsListDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003573 while (cur != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003574 xmlNsDump(buf, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003575 cur = cur->next;
3576 }
3577}
3578
Daniel Veillard97b58771998-10-20 06:14:16 +00003579/**
3580 * xmlDtdDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003581 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003582 * @doc: the document
3583 *
3584 * Dump the XML document DTD, if any.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003585 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003586static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00003587xmlDtdDump(xmlBufferPtr buf, xmlDocPtr doc) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003588 xmlDtdPtr cur = doc->intSubset;
Daniel Veillard260a68f1998-08-13 03:39:55 +00003589
3590 if (cur == NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003591 fprintf(stderr, "xmlDtdDump : no internal subset\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003592 return;
3593 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003594 xmlBufferWriteChar(buf, "<!DOCTYPE ");
3595 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003596 if (cur->ExternalID != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00003597 xmlBufferWriteChar(buf, " PUBLIC ");
3598 xmlBufferWriteQuotedString(buf, cur->ExternalID);
3599 xmlBufferWriteChar(buf, " ");
3600 xmlBufferWriteQuotedString(buf, cur->SystemID);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003601 } else if (cur->SystemID != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00003602 xmlBufferWriteChar(buf, " SYSTEM ");
3603 xmlBufferWriteQuotedString(buf, cur->SystemID);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003604 }
Daniel Veillard1e346af1999-02-22 10:33:01 +00003605 if ((cur->entities == NULL) && (cur->elements == NULL) &&
3606 (cur->attributes == NULL) && (cur->notations == NULL)) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003607 xmlBufferWriteChar(buf, ">\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003608 return;
3609 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003610 xmlBufferWriteChar(buf, " [\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003611 if (cur->entities != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00003612 xmlDumpEntitiesTable(buf, (xmlEntitiesTablePtr) cur->entities);
Daniel Veillard1e346af1999-02-22 10:33:01 +00003613 if (cur->notations != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00003614 xmlDumpNotationTable(buf, (xmlNotationTablePtr) cur->notations);
Daniel Veillard3b9def11999-01-31 22:15:06 +00003615 if (cur->elements != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00003616 xmlDumpElementTable(buf, (xmlElementTablePtr) cur->elements);
Daniel Veillard1e346af1999-02-22 10:33:01 +00003617 if (cur->attributes != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00003618 xmlDumpAttributeTable(buf, (xmlAttributeTablePtr) cur->attributes);
3619 xmlBufferWriteChar(buf, "]");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003620
Daniel Veillard5099ae81999-04-21 20:12:07 +00003621 xmlBufferWriteChar(buf, ">\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003622}
3623
Daniel Veillard97b58771998-10-20 06:14:16 +00003624/**
3625 * xmlAttrDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003626 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003627 * @doc: the document
3628 * @cur: the attribute pointer
3629 *
3630 * Dump an XML attribute
Daniel Veillard260a68f1998-08-13 03:39:55 +00003631 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003632static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00003633xmlAttrDump(xmlBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003634 xmlChar *value;
Daniel Veillardccb09631998-10-27 06:21:04 +00003635
Daniel Veillard260a68f1998-08-13 03:39:55 +00003636 if (cur == NULL) {
3637 fprintf(stderr, "xmlAttrDump : property == NULL\n");
3638 return;
3639 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003640 xmlBufferWriteChar(buf, " ");
Daniel Veillardb96e6431999-08-29 21:02:19 +00003641 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
3642 xmlBufferWriteCHAR(buf, cur->ns->prefix);
3643 xmlBufferWriteChar(buf, ":");
3644 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003645 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillardccb09631998-10-27 06:21:04 +00003646 value = xmlNodeListGetString(doc, cur->val, 0);
3647 if (value) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00003648 xmlBufferWriteChar(buf, "=");
3649 xmlBufferWriteQuotedString(buf, value);
Daniel Veillard6454aec1999-09-02 22:04:43 +00003650 xmlFree(value);
Daniel Veillard726c7e31999-02-08 15:13:10 +00003651 } else {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003652 xmlBufferWriteChar(buf, "=\"\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003653 }
3654}
3655
Daniel Veillard97b58771998-10-20 06:14:16 +00003656/**
3657 * xmlAttrListDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003658 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003659 * @doc: the document
3660 * @cur: the first attribute pointer
3661 *
3662 * Dump a list of XML attributes
Daniel Veillard260a68f1998-08-13 03:39:55 +00003663 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003664static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00003665xmlAttrListDump(xmlBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003666 if (cur == NULL) {
3667 fprintf(stderr, "xmlAttrListDump : property == NULL\n");
3668 return;
3669 }
3670 while (cur != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003671 xmlAttrDump(buf, doc, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003672 cur = cur->next;
3673 }
3674}
3675
Daniel Veillard260a68f1998-08-13 03:39:55 +00003676
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003677static void
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003678xmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
3679 int format);
Daniel Veillard97b58771998-10-20 06:14:16 +00003680/**
3681 * xmlNodeListDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003682 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003683 * @doc: the document
3684 * @cur: the first node
3685 * @level: the imbrication level for indenting
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003686 * @format: is formatting allowed
Daniel Veillard97b58771998-10-20 06:14:16 +00003687 *
3688 * Dump an XML node list, recursive behaviour,children are printed too.
3689 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003690static void
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003691xmlNodeListDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
3692 int format) {
3693 int i;
Daniel Veillardccb09631998-10-27 06:21:04 +00003694
Daniel Veillard260a68f1998-08-13 03:39:55 +00003695 if (cur == NULL) {
3696 fprintf(stderr, "xmlNodeListDump : node == NULL\n");
3697 return;
3698 }
3699 while (cur != NULL) {
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003700 if ((format) && (xmlIndentTreeOutput) &&
3701 (cur->type == XML_ELEMENT_NODE))
3702 for (i = 0;i < level;i++)
3703 xmlBufferWriteChar(buf, " ");
3704 xmlNodeDump(buf, doc, cur, level, format);
3705 if (format) {
3706 xmlBufferWriteChar(buf, "\n");
Daniel Veillardccb09631998-10-27 06:21:04 +00003707 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003708 cur = cur->next;
3709 }
3710}
3711
Daniel Veillard97b58771998-10-20 06:14:16 +00003712/**
Daniel Veillardccb09631998-10-27 06:21:04 +00003713 * xmlNodeDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003714 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003715 * @doc: the document
3716 * @cur: the current node
3717 * @level: the imbrication level for indenting
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003718 * @format: is formatting allowed
Daniel Veillard97b58771998-10-20 06:14:16 +00003719 *
3720 * Dump an XML node, recursive behaviour,children are printed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003721 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003722static void
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003723xmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
3724 int format) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003725 int i;
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003726 xmlNodePtr tmp;
Daniel Veillard260a68f1998-08-13 03:39:55 +00003727
3728 if (cur == NULL) {
3729 fprintf(stderr, "xmlNodeDump : node == NULL\n");
3730 return;
3731 }
Daniel Veillard0bef1311998-10-14 02:36:47 +00003732 if (cur->type == XML_TEXT_NODE) {
Daniel Veillard14fff061999-06-22 21:49:07 +00003733 if (cur->content != NULL) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003734 xmlChar *buffer;
Daniel Veillard14fff061999-06-22 21:49:07 +00003735
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003736#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard14fff061999-06-22 21:49:07 +00003737 buffer = xmlEncodeEntitiesReentrant(doc, cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003738#else
3739 buffer = xmlEncodeEntitiesReentrant(doc,
3740 xmlBufferContent(cur->content));
3741#endif
Daniel Veillard14fff061999-06-22 21:49:07 +00003742 if (buffer != NULL) {
3743 xmlBufferWriteCHAR(buf, buffer);
Daniel Veillard6454aec1999-09-02 22:04:43 +00003744 xmlFree(buffer);
Daniel Veillard14fff061999-06-22 21:49:07 +00003745 }
3746 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003747 return;
3748 }
Daniel Veillardb96e6431999-08-29 21:02:19 +00003749 if (cur->type == XML_PI_NODE) {
3750 if (cur->content != NULL) {
3751 xmlBufferWriteChar(buf, "<?");
3752 xmlBufferWriteCHAR(buf, cur->name);
3753 if (cur->content != NULL) {
3754 xmlBufferWriteChar(buf, " ");
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003755#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardb96e6431999-08-29 21:02:19 +00003756 xmlBufferWriteCHAR(buf, cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003757#else
3758 xmlBufferWriteCHAR(buf, xmlBufferContent(cur->content));
3759#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +00003760 }
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003761 xmlBufferWriteChar(buf, "?>");
Daniel Veillardb96e6431999-08-29 21:02:19 +00003762 }
3763 return;
3764 }
Daniel Veillard0bef1311998-10-14 02:36:47 +00003765 if (cur->type == XML_COMMENT_NODE) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003766 if (cur->content != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003767 xmlBufferWriteChar(buf, "<!--");
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003768#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard5099ae81999-04-21 20:12:07 +00003769 xmlBufferWriteCHAR(buf, cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003770#else
3771 xmlBufferWriteCHAR(buf, xmlBufferContent(cur->content));
3772#endif
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003773 xmlBufferWriteChar(buf, "-->");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003774 }
3775 return;
3776 }
Daniel Veillardccb09631998-10-27 06:21:04 +00003777 if (cur->type == XML_ENTITY_REF_NODE) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003778 xmlBufferWriteChar(buf, "&");
3779 xmlBufferWriteCHAR(buf, cur->name);
3780 xmlBufferWriteChar(buf, ";");
Daniel Veillardccb09631998-10-27 06:21:04 +00003781 return;
3782 }
Daniel Veillardb05deb71999-08-10 19:04:08 +00003783 if (cur->type == XML_CDATA_SECTION_NODE) {
3784 xmlBufferWriteChar(buf, "<![CDATA[");
3785 if (cur->content != NULL)
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003786#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardb05deb71999-08-10 19:04:08 +00003787 xmlBufferWriteCHAR(buf, cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003788#else
3789 xmlBufferWriteCHAR(buf, xmlBufferContent(cur->content));
3790#endif
Daniel Veillardb05deb71999-08-10 19:04:08 +00003791 xmlBufferWriteChar(buf, "]]>");
3792 return;
3793 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003794
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003795 if (format == 1) {
3796 tmp = cur->childs;
3797 while (tmp != NULL) {
3798 if ((tmp->type == XML_TEXT_NODE) ||
3799 (tmp->type == XML_ENTITY_REF_NODE)) {
3800 format = 0;
3801 break;
3802 }
3803 tmp = tmp->next;
3804 }
3805 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003806 xmlBufferWriteChar(buf, "<");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003807 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003808 xmlBufferWriteCHAR(buf, cur->ns->prefix);
3809 xmlBufferWriteChar(buf, ":");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003810 }
3811
Daniel Veillard5099ae81999-04-21 20:12:07 +00003812 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003813 if (cur->nsDef)
Daniel Veillard5099ae81999-04-21 20:12:07 +00003814 xmlNsListDump(buf, cur->nsDef);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003815 if (cur->properties != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00003816 xmlAttrListDump(buf, doc, cur->properties);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003817
3818 if ((cur->content == NULL) && (cur->childs == NULL)) {
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003819 xmlBufferWriteChar(buf, "/>");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003820 return;
3821 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003822 xmlBufferWriteChar(buf, ">");
Daniel Veillard14fff061999-06-22 21:49:07 +00003823 if (cur->content != NULL) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003824 xmlChar *buffer;
Daniel Veillard14fff061999-06-22 21:49:07 +00003825
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003826#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard14fff061999-06-22 21:49:07 +00003827 buffer = xmlEncodeEntitiesReentrant(doc, cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003828#else
3829 buffer = xmlEncodeEntitiesReentrant(doc,
3830 xmlBufferContent(cur->content));
3831#endif
Daniel Veillard14fff061999-06-22 21:49:07 +00003832 if (buffer != NULL) {
3833 xmlBufferWriteCHAR(buf, buffer);
Daniel Veillard6454aec1999-09-02 22:04:43 +00003834 xmlFree(buffer);
Daniel Veillard14fff061999-06-22 21:49:07 +00003835 }
3836 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003837 if (cur->childs != NULL) {
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003838 if (format) xmlBufferWriteChar(buf, "\n");
3839 xmlNodeListDump(buf, doc, cur->childs, level + 1, format);
3840 if ((xmlIndentTreeOutput) && (format))
3841 for (i = 0;i < level;i++)
3842 xmlBufferWriteChar(buf, " ");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003843 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003844 xmlBufferWriteChar(buf, "</");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003845 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003846 xmlBufferWriteCHAR(buf, cur->ns->prefix);
3847 xmlBufferWriteChar(buf, ":");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003848 }
3849
Daniel Veillard5099ae81999-04-21 20:12:07 +00003850 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003851 xmlBufferWriteChar(buf, ">");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003852}
3853
Daniel Veillard97b58771998-10-20 06:14:16 +00003854/**
3855 * xmlDocContentDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003856 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003857 * @cur: the document
3858 *
3859 * Dump an XML document.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003860 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003861static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00003862xmlDocContentDump(xmlBufferPtr buf, xmlDocPtr cur) {
Daniel Veillardbe70ff71999-07-05 16:50:46 +00003863 xmlBufferWriteChar(buf, "<?xml version=");
3864 if (cur->version != NULL)
3865 xmlBufferWriteQuotedString(buf, cur->version);
3866 else
3867 xmlBufferWriteChar(buf, "\"1.0\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003868 if (cur->encoding != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00003869 xmlBufferWriteChar(buf, " encoding=");
3870 xmlBufferWriteQuotedString(buf, cur->encoding);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003871 }
3872 switch (cur->standalone) {
3873 case 0:
Daniel Veillard5099ae81999-04-21 20:12:07 +00003874 xmlBufferWriteChar(buf, " standalone=\"no\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003875 break;
3876 case 1:
Daniel Veillard5099ae81999-04-21 20:12:07 +00003877 xmlBufferWriteChar(buf, " standalone=\"yes\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003878 break;
3879 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003880 xmlBufferWriteChar(buf, "?>\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003881 if (cur->intSubset != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00003882 xmlDtdDump(buf, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003883 if (cur->root != NULL) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00003884 xmlNodePtr child = cur->root;
3885
Daniel Veillard260a68f1998-08-13 03:39:55 +00003886 /* global namespace definitions, the old way */
3887 if (oldXMLWDcompatibility)
Daniel Veillard5099ae81999-04-21 20:12:07 +00003888 xmlGlobalNsListDump(buf, cur->oldNs);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003889 else
3890 xmlUpgradeOldNs(cur);
Daniel Veillardb96e6431999-08-29 21:02:19 +00003891
3892 while (child != NULL) {
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003893 xmlNodeDump(buf, cur, child, 0, 1);
3894 xmlBufferWriteChar(buf, "\n");
Daniel Veillardb96e6431999-08-29 21:02:19 +00003895 child = child->next;
3896 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003897 }
3898}
3899
Daniel Veillard97b58771998-10-20 06:14:16 +00003900/**
3901 * xmlDocDumpMemory:
3902 * @cur: the document
3903 * @mem: OUT: the memory pointer
3904 * @size: OUT: the memory lenght
3905 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003906 * Dump an XML document in memory and return the xmlChar * and it's size.
Daniel Veillard97b58771998-10-20 06:14:16 +00003907 * It's up to the caller to free the memory.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003908 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003909void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003910xmlDocDumpMemory(xmlDocPtr cur, xmlChar**mem, int *size) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003911 xmlBufferPtr buf;
3912
Daniel Veillard260a68f1998-08-13 03:39:55 +00003913 if (cur == NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003914#ifdef DEBUG_TREE
3915 fprintf(stderr, "xmlDocDumpMemory : document == NULL\n");
3916#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00003917 *mem = NULL;
3918 *size = 0;
3919 return;
3920 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003921 buf = xmlBufferCreate();
3922 if (buf == NULL) {
3923 *mem = NULL;
3924 *size = 0;
3925 return;
3926 }
3927 xmlDocContentDump(buf, cur);
Daniel Veillardb05deb71999-08-10 19:04:08 +00003928 *mem = xmlStrndup(buf->content, buf->use);
Daniel Veillard5099ae81999-04-21 20:12:07 +00003929 *size = buf->use;
Daniel Veillardb05deb71999-08-10 19:04:08 +00003930 xmlBufferFree(buf);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003931}
3932
Daniel Veillard97b58771998-10-20 06:14:16 +00003933/**
3934 * xmlGetDocCompressMode:
3935 * @doc: the document
3936 *
3937 * get the compression ratio for a document, ZLIB based
Daniel Veillard1e346af1999-02-22 10:33:01 +00003938 * Returns 0 (uncompressed) to 9 (max compression)
Daniel Veillard151b1b01998-09-23 00:49:46 +00003939 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003940int
3941 xmlGetDocCompressMode (xmlDocPtr doc) {
Daniel Veillard15a8df41998-09-24 19:15:06 +00003942 if (doc == NULL) return(-1);
3943 return(doc->compression);
3944}
3945
Daniel Veillard97b58771998-10-20 06:14:16 +00003946/**
3947 * xmlSetDocCompressMode:
3948 * @doc: the document
3949 * @mode: the compression ratio
3950 *
3951 * set the compression ratio for a document, ZLIB based
3952 * Correct values: 0 (uncompressed) to 9 (max compression)
3953 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003954void
3955xmlSetDocCompressMode (xmlDocPtr doc, int mode) {
Daniel Veillard15a8df41998-09-24 19:15:06 +00003956 if (doc == NULL) return;
3957 if (mode < 0) doc->compression = 0;
3958 else if (mode > 9) doc->compression = 9;
3959 else doc->compression = mode;
3960}
3961
Daniel Veillard97b58771998-10-20 06:14:16 +00003962/**
3963 * xmlGetCompressMode:
3964 *
3965 * get the default compression mode used, ZLIB based.
Daniel Veillard1e346af1999-02-22 10:33:01 +00003966 * Returns 0 (uncompressed) to 9 (max compression)
Daniel Veillard15a8df41998-09-24 19:15:06 +00003967 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003968int
3969 xmlGetCompressMode(void) {
Daniel Veillard151b1b01998-09-23 00:49:46 +00003970 return(xmlCompressMode);
3971}
Daniel Veillard97b58771998-10-20 06:14:16 +00003972
3973/**
3974 * xmlSetCompressMode:
3975 * @mode: the compression ratio
3976 *
3977 * set the default compression mode used, ZLIB based
3978 * Correct values: 0 (uncompressed) to 9 (max compression)
3979 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003980void
3981xmlSetCompressMode(int mode) {
Daniel Veillard151b1b01998-09-23 00:49:46 +00003982 if (mode < 0) xmlCompressMode = 0;
Daniel Veillard15a8df41998-09-24 19:15:06 +00003983 else if (mode > 9) xmlCompressMode = 9;
Daniel Veillard151b1b01998-09-23 00:49:46 +00003984 else xmlCompressMode = mode;
3985}
3986
Daniel Veillard97b58771998-10-20 06:14:16 +00003987/**
3988 * xmlDocDump:
3989 * @f: the FILE*
3990 * @cur: the document
3991 *
3992 * Dump an XML document to an open FILE.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003993 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003994void
3995xmlDocDump(FILE *f, xmlDocPtr cur) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003996 xmlBufferPtr buf;
3997
Daniel Veillard260a68f1998-08-13 03:39:55 +00003998 if (cur == NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003999#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00004000 fprintf(stderr, "xmlDocDump : document == NULL\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004001#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00004002 return;
4003 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00004004 buf = xmlBufferCreate();
4005 if (buf == NULL) return;
4006 xmlDocContentDump(buf, cur);
4007 xmlBufferDump(f, buf);
4008 xmlBufferFree(buf);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004009}
4010
Daniel Veillard97b58771998-10-20 06:14:16 +00004011/**
4012 * xmlSaveFile:
4013 * @filename: the filename
4014 * @cur: the document
4015 *
4016 * Dump an XML document to a file. Will use compression if
Daniel Veillard11a48ec1999-11-23 10:40:46 +00004017 * compiled in and enabled. If @filename is "-" the stdout file is
4018 * used.
Daniel Veillard97b58771998-10-20 06:14:16 +00004019 * returns: the number of file written or -1 in case of failure.
Daniel Veillard151b1b01998-09-23 00:49:46 +00004020 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00004021int
4022xmlSaveFile(const char *filename, xmlDocPtr cur) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00004023 xmlBufferPtr buf;
Daniel Veillard151b1b01998-09-23 00:49:46 +00004024#ifdef HAVE_ZLIB_H
4025 gzFile zoutput = NULL;
4026 char mode[15];
4027#endif
Daniel Veillardccb09631998-10-27 06:21:04 +00004028 FILE *output = NULL;
Daniel Veillard151b1b01998-09-23 00:49:46 +00004029 int ret;
4030
Daniel Veillard5099ae81999-04-21 20:12:07 +00004031 /*
4032 * save the content to a temp buffer.
4033 */
4034 buf = xmlBufferCreate();
4035 if (buf == NULL) return(0);
4036 xmlDocContentDump(buf, cur);
4037
Daniel Veillard151b1b01998-09-23 00:49:46 +00004038#ifdef HAVE_ZLIB_H
Daniel Veillard11a48ec1999-11-23 10:40:46 +00004039 if (cur->compression < 0) cur->compression = xmlCompressMode;
Daniel Veillarddc3dd9d1998-09-24 19:25:54 +00004040 if ((cur->compression > 0) && (cur->compression <= 9)) {
4041 sprintf(mode, "w%d", cur->compression);
Daniel Veillard11a48ec1999-11-23 10:40:46 +00004042 if (!strcmp(filename, "-"))
4043 zoutput = gzdopen(1, mode);
4044 else
4045 zoutput = gzopen(filename, mode);
Daniel Veillard151b1b01998-09-23 00:49:46 +00004046 }
4047 if (zoutput == NULL) {
4048#endif
4049 output = fopen(filename, "w");
Daniel Veillard10a2c651999-12-12 13:03:50 +00004050 if (output == NULL) {
4051 xmlBufferFree(buf);
4052 return(-1);
4053 }
Daniel Veillard151b1b01998-09-23 00:49:46 +00004054#ifdef HAVE_ZLIB_H
4055 }
Daniel Veillard151b1b01998-09-23 00:49:46 +00004056
Daniel Veillard151b1b01998-09-23 00:49:46 +00004057 if (zoutput != NULL) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004058 ret = gzwrite(zoutput, buf->content, sizeof(xmlChar) * buf->use);
Daniel Veillard151b1b01998-09-23 00:49:46 +00004059 gzclose(zoutput);
Daniel Veillard5099ae81999-04-21 20:12:07 +00004060 } else {
4061#endif
4062 ret = xmlBufferDump(output, buf);
4063 fclose(output);
4064#ifdef HAVE_ZLIB_H
Daniel Veillard151b1b01998-09-23 00:49:46 +00004065 }
4066#endif
Manish Vachharajani5e60f5a1999-05-29 03:04:30 +00004067 xmlBufferFree(buf);
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004068 return(ret * sizeof(xmlChar));
Daniel Veillard151b1b01998-09-23 00:49:46 +00004069}
4070