blob: 1142b9b8a44d7fb555aa9517812a3ccb96baa582 [file] [log] [blame]
Daniel Veillard260a68f1998-08-13 03:39:55 +00001/*
2 * tree.c : implemetation of access function for an XML tree.
3 *
4 * See Copyright for the status of this software.
5 *
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00006 * Daniel.Veillard@w3.org
Daniel Veillard260a68f1998-08-13 03:39:55 +00007 */
8
Daniel Veillard7f7d1111999-09-22 09:46:25 +00009#ifdef WIN32
Daniel Veillard3c558c31999-12-22 11:30:41 +000010#include "win32config.h"
Daniel Veillard7f7d1111999-09-22 09:46:25 +000011#else
Daniel Veillard151b1b01998-09-23 00:49:46 +000012#include "config.h"
Daniel Veillard7f7d1111999-09-22 09:46:25 +000013#endif
14
Daniel Veillard260a68f1998-08-13 03:39:55 +000015#include <stdio.h>
Daniel Veillard260a68f1998-08-13 03:39:55 +000016#include <string.h> /* for memset() only ! */
17
Daniel Veillard7f7d1111999-09-22 09:46:25 +000018#ifdef HAVE_CTYPE_H
19#include <ctype.h>
20#endif
21#ifdef HAVE_STDLIB_H
22#include <stdlib.h>
23#endif
Daniel Veillard151b1b01998-09-23 00:49:46 +000024#ifdef HAVE_ZLIB_H
25#include <zlib.h>
26#endif
27
Daniel Veillard6454aec1999-09-02 22:04:43 +000028#include "xmlmemory.h"
Daniel Veillard260a68f1998-08-13 03:39:55 +000029#include "tree.h"
Daniel Veillard37846c61999-12-16 17:52:19 +000030#include "parser.h"
Daniel Veillard260a68f1998-08-13 03:39:55 +000031#include "entities.h"
Daniel Veillard3b9def11999-01-31 22:15:06 +000032#include "valid.h"
Daniel Veillard260a68f1998-08-13 03:39:55 +000033
Daniel Veillarddd6b3671999-09-23 22:19:22 +000034static xmlChar xmlStringText[] = { 't', 'e', 'x', 't', 0 };
Daniel Veillard260a68f1998-08-13 03:39:55 +000035int oldXMLWDcompatibility = 0;
36int xmlIndentTreeOutput = 1;
Daniel Veillardf5c2c871999-12-01 09:51:45 +000037xmlBufferAllocationScheme xmlBufferAllocScheme = XML_BUFFER_ALLOC_EXACT;
Daniel Veillard260a68f1998-08-13 03:39:55 +000038
Daniel Veillard15a8df41998-09-24 19:15:06 +000039static int xmlCompressMode = 0;
Daniel Veillard10a2c651999-12-12 13:03:50 +000040static int xmlCheckDTD = 1;
Daniel Veillarde41f2b72000-01-30 20:00:07 +000041int xmlSaveNoEmptyTags = 0;
Daniel Veillard3e6d2372000-03-04 11:39:43 +000042extern int xmlKeepBlanksDefaultValue;
43
44#define IS_BLANK(c) \
45 (((c) == '\n') || ((c) == '\r') || ((c) == '\t') || ((c) == ' '))
Daniel Veillard15a8df41998-09-24 19:15:06 +000046
Daniel Veillard39a1f9a1999-01-17 19:11:59 +000047#define UPDATE_LAST_CHILD(n) if ((n) != NULL) { \
48 xmlNodePtr ulccur = (n)->childs; \
49 if (ulccur == NULL) { \
50 (n)->last = NULL; \
51 } else { \
52 while (ulccur->next != NULL) ulccur = ulccur->next; \
53 (n)->last = ulccur; \
Daniel Veillard1e346af1999-02-22 10:33:01 +000054}}
Daniel Veillard39a1f9a1999-01-17 19:11:59 +000055
Daniel Veillardad8f99d2000-01-15 14:20:03 +000056/* #define DEBUG_BUFFER */
57/* #define DEBUG_TREE */
58
Daniel Veillard260a68f1998-08-13 03:39:55 +000059/************************************************************************
60 * *
61 * Allocation and deallocation of basic structures *
62 * *
63 ************************************************************************/
64
Daniel Veillard97b58771998-10-20 06:14:16 +000065/**
Daniel Veillardf5c2c871999-12-01 09:51:45 +000066 * xmlSetBufferAllocationScheme:
67 * @scheme: allocation method to use
68 *
69 * Set the buffer allocation method. Types are
70 * XML_BUFFER_ALLOC_EXACT - use exact sizes, keeps memory usage down
71 * XML_BUFFER_ALLOC_DOUBLEIT - double buffer when extra needed,
72 * improves performance
73 */
74void
75xmlSetBufferAllocationScheme(xmlBufferAllocationScheme scheme) {
76 xmlBufferAllocScheme = scheme;
77}
78
79/**
80 * xmlGetBufferAllocationScheme:
81 *
82 * Types are
83 * XML_BUFFER_ALLOC_EXACT - use exact sizes, keeps memory usage down
84 * XML_BUFFER_ALLOC_DOUBLEIT - double buffer when extra needed,
85 * improves performance
86 *
87 * Returns the current allocation scheme
88 */
89xmlBufferAllocationScheme
90xmlGetBufferAllocationScheme() {
91 return xmlBufferAllocScheme;
92}
93
94/**
Daniel Veillard97b58771998-10-20 06:14:16 +000095 * xmlUpgradeOldNs:
96 * @doc: a document pointer
97 *
98 * Upgrade old style Namespaces (PI) and move them to the root of the document.
Daniel Veillard260a68f1998-08-13 03:39:55 +000099 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000100void
101xmlUpgradeOldNs(xmlDocPtr doc) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000102 xmlNsPtr cur;
103
104 if ((doc == NULL) || (doc->oldNs == NULL)) return;
105 if (doc->root == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000106#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +0000107 fprintf(stderr, "xmlUpgradeOldNs: failed no root !\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000108#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000109 return;
110 }
111
112 cur = doc->oldNs;
113 while (cur->next != NULL) {
114 cur->type = XML_LOCAL_NAMESPACE;
115 cur = cur->next;
116 }
117 cur->type = XML_LOCAL_NAMESPACE;
118 cur->next = doc->root->nsDef;
119 doc->root->nsDef = doc->oldNs;
120 doc->oldNs = NULL;
121}
122
Daniel Veillard97b58771998-10-20 06:14:16 +0000123/**
124 * xmlNewNs:
125 * @node: the element carrying the namespace
126 * @href: the URI associated
127 * @prefix: the prefix for the namespace
128 *
Daniel Veillard686d6b62000-01-03 11:08:02 +0000129 * Creation of a new Namespace. This function will refuse to create
130 * a namespace with a similar prefix than an existing one present on this
131 * node.
132 * Returns returns a new namespace pointer or NULL
Daniel Veillard260a68f1998-08-13 03:39:55 +0000133 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000134xmlNsPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000135xmlNewNs(xmlNodePtr node, const xmlChar *href, const xmlChar *prefix) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000136 xmlNsPtr cur;
137
138 if (href == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000139#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +0000140 fprintf(stderr, "xmlNewNs: href == NULL !\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000141#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000142 return(NULL);
143 }
144
145 /*
146 * Allocate a new DTD and fill the fields.
147 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000148 cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000149 if (cur == NULL) {
150 fprintf(stderr, "xmlNewNs : malloc failed\n");
151 return(NULL);
152 }
153
154 cur->type = XML_LOCAL_NAMESPACE;
155 if (href != NULL)
156 cur->href = xmlStrdup(href);
157 else
158 cur->href = NULL;
159 if (prefix != NULL)
160 cur->prefix = xmlStrdup(prefix);
161 else
162 cur->prefix = NULL;
163
164 /*
165 * Add it at the end to preserve parsing order ...
Daniel Veillard686d6b62000-01-03 11:08:02 +0000166 * and checks for existing use of the prefix
Daniel Veillard260a68f1998-08-13 03:39:55 +0000167 */
168 cur->next = NULL;
169 if (node != NULL) {
170 if (node->nsDef == NULL) {
171 node->nsDef = cur;
172 } else {
173 xmlNsPtr prev = node->nsDef;
174
Daniel Veillard0142b842000-01-14 14:45:24 +0000175 if (((prev->prefix == NULL) && (cur->prefix == NULL)) ||
176 (!xmlStrcmp(prev->prefix, cur->prefix))) {
177 xmlFreeNs(cur);
178 return(NULL);
179 }
Daniel Veillard686d6b62000-01-03 11:08:02 +0000180 while (prev->next != NULL) {
Daniel Veillard0142b842000-01-14 14:45:24 +0000181 prev = prev->next;
Daniel Veillard686d6b62000-01-03 11:08:02 +0000182 if (((prev->prefix == NULL) && (cur->prefix == NULL)) ||
183 (!xmlStrcmp(prev->prefix, cur->prefix))) {
184 xmlFreeNs(cur);
185 return(NULL);
186 }
Daniel Veillard686d6b62000-01-03 11:08:02 +0000187 }
Daniel Veillard260a68f1998-08-13 03:39:55 +0000188 prev->next = cur;
189 }
190 }
Daniel Veillard260a68f1998-08-13 03:39:55 +0000191 return(cur);
192}
193
Daniel Veillard97b58771998-10-20 06:14:16 +0000194/**
195 * xmlNewGlobalNs:
196 * @doc: the document carrying the namespace
197 * @href: the URI associated
198 * @prefix: the prefix for the namespace
199 *
Daniel Veillard686d6b62000-01-03 11:08:02 +0000200 * Creation of a Namespace, the old way using PI and without scoping
201 * DEPRECATED !!!
Daniel Veillard0142b842000-01-14 14:45:24 +0000202 * It now create a namespace on the root element of the document if found.
Daniel Veillard686d6b62000-01-03 11:08:02 +0000203 * Returns NULL this functionnality had been removed
Daniel Veillard260a68f1998-08-13 03:39:55 +0000204 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000205xmlNsPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000206xmlNewGlobalNs(xmlDocPtr doc, const xmlChar *href, const xmlChar *prefix) {
Daniel Veillard0142b842000-01-14 14:45:24 +0000207 xmlNodePtr root;
208
209 xmlNsPtr cur;
210
211 root = xmlDocGetRootElement(doc);
212 if (root != NULL)
213 return(xmlNewNs(root, href, prefix));
214
215 /*
216 * if there is no root element yet, create an old Namespace type
217 * and it will be moved to the root at save time.
218 */
219 cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
220 if (cur == NULL) {
221 fprintf(stderr, "xmlNewGlobalNs : malloc failed\n");
222 return(NULL);
223 }
224
225 cur->type = XML_GLOBAL_NAMESPACE;
226 if (href != NULL)
227 cur->href = xmlStrdup(href);
228 else
229 cur->href = NULL;
230 if (prefix != NULL)
231 cur->prefix = xmlStrdup(prefix);
232 else
233 cur->prefix = NULL;
234
235 /*
236 * Add it at the end to preserve parsing order ...
237 */
238 cur->next = NULL;
239 if (doc != NULL) {
240 if (doc->oldNs == NULL) {
241 doc->oldNs = cur;
242 } else {
243 xmlNsPtr prev = doc->oldNs;
244
245 while (prev->next != NULL) prev = prev->next;
246 prev->next = cur;
247 }
248 }
249
250 return(NULL);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000251}
252
Daniel Veillard97b58771998-10-20 06:14:16 +0000253/**
254 * xmlSetNs:
255 * @node: a node in the document
256 * @ns: a namespace pointer
257 *
258 * Associate a namespace to a node, a posteriori.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000259 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000260void
261xmlSetNs(xmlNodePtr node, xmlNsPtr ns) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000262 if (node == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000263#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +0000264 fprintf(stderr, "xmlSetNs: node == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000265#else
Daniel Veillard260a68f1998-08-13 03:39:55 +0000266 return;
267 }
268 node->ns = ns;
269}
270
Daniel Veillard97b58771998-10-20 06:14:16 +0000271/**
272 * xmlFreeNs:
273 * @cur: the namespace pointer
274 *
275 * Free up the structures associated to a namespace
Daniel Veillard260a68f1998-08-13 03:39:55 +0000276 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000277void
278xmlFreeNs(xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000279 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000280#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +0000281 fprintf(stderr, "xmlFreeNs : ns == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000282#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000283 return;
284 }
Daniel Veillard6454aec1999-09-02 22:04:43 +0000285 if (cur->href != NULL) xmlFree((char *) cur->href);
286 if (cur->prefix != NULL) xmlFree((char *) cur->prefix);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000287 memset(cur, -1, sizeof(xmlNs));
Daniel Veillard6454aec1999-09-02 22:04:43 +0000288 xmlFree(cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000289}
290
Daniel Veillard97b58771998-10-20 06:14:16 +0000291/**
292 * xmlFreeNsList:
293 * @cur: the first namespace pointer
294 *
295 * Free up all the structures associated to the chained namespaces.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000296 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000297void
298xmlFreeNsList(xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000299 xmlNsPtr next;
300 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000301#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +0000302 fprintf(stderr, "xmlFreeNsList : ns == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000303#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000304 return;
305 }
306 while (cur != NULL) {
307 next = cur->next;
308 xmlFreeNs(cur);
309 cur = next;
310 }
311}
312
Daniel Veillard97b58771998-10-20 06:14:16 +0000313/**
314 * xmlNewDtd:
315 * @doc: the document pointer
316 * @name: the DTD name
317 * @ExternalID: the external ID
318 * @SystemID: the system ID
319 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000320 * Creation of a new DTD.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000321 * Returns a pointer to the new DTD structure
Daniel Veillard260a68f1998-08-13 03:39:55 +0000322 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000323xmlDtdPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000324xmlNewDtd(xmlDocPtr doc, const xmlChar *name,
325 const xmlChar *ExternalID, const xmlChar *SystemID) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000326 xmlDtdPtr cur;
327
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000328 if ((doc != NULL) && (doc->extSubset != NULL)) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000329#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +0000330 fprintf(stderr, "xmlNewDtd(%s): document %s already have a DTD %s\n",
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000331 /* !!! */ (char *) name, doc->name,
332 /* !!! */ (char *)doc->extSubset->name);
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000333#endif
334 return(NULL);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000335 }
336
337 /*
338 * Allocate a new DTD and fill the fields.
339 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000340 cur = (xmlDtdPtr) xmlMalloc(sizeof(xmlDtd));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000341 if (cur == NULL) {
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000342 fprintf(stderr, "xmlNewDtd : malloc failed\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +0000343 return(NULL);
344 }
345
346 if (name != NULL)
347 cur->name = xmlStrdup(name);
348 else
349 cur->name = NULL;
350 if (ExternalID != NULL)
351 cur->ExternalID = xmlStrdup(ExternalID);
352 else
353 cur->ExternalID = NULL;
354 if (SystemID != NULL)
355 cur->SystemID = xmlStrdup(SystemID);
356 else
357 cur->SystemID = NULL;
Daniel Veillard1e346af1999-02-22 10:33:01 +0000358 cur->notations = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000359 cur->elements = NULL;
Daniel Veillard1e346af1999-02-22 10:33:01 +0000360 cur->attributes = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000361 cur->entities = NULL;
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000362 if (doc != NULL)
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000363 doc->extSubset = cur;
364
365 return(cur);
366}
367
368/**
369 * xmlCreateIntSubset:
370 * @doc: the document pointer
371 * @name: the DTD name
372 * @ExternalID: the external ID
373 * @SystemID: the system ID
374 *
Daniel Veillard1e346af1999-02-22 10:33:01 +0000375 * Create the internal subset of a document
376 * Returns a pointer to the new DTD structure
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000377 */
378xmlDtdPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000379xmlCreateIntSubset(xmlDocPtr doc, const xmlChar *name,
380 const xmlChar *ExternalID, const xmlChar *SystemID) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000381 xmlDtdPtr cur;
382
383 if ((doc != NULL) && (doc->intSubset != NULL)) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000384#ifdef DEBUG_TREE
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000385 fprintf(stderr,
386 "xmlCreateIntSubset(): document %s already have an internal subset\n",
387 doc->name);
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000388#endif
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000389 return(NULL);
390 }
391
392 /*
393 * Allocate a new DTD and fill the fields.
394 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000395 cur = (xmlDtdPtr) xmlMalloc(sizeof(xmlDtd));
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000396 if (cur == NULL) {
397 fprintf(stderr, "xmlNewDtd : malloc failed\n");
398 return(NULL);
399 }
400
401 if (name != NULL)
402 cur->name = xmlStrdup(name);
403 else
404 cur->name = NULL;
405 if (ExternalID != NULL)
406 cur->ExternalID = xmlStrdup(ExternalID);
407 else
408 cur->ExternalID = NULL;
409 if (SystemID != NULL)
410 cur->SystemID = xmlStrdup(SystemID);
411 else
412 cur->SystemID = NULL;
Daniel Veillard1e346af1999-02-22 10:33:01 +0000413 cur->notations = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000414 cur->elements = NULL;
Daniel Veillard1e346af1999-02-22 10:33:01 +0000415 cur->attributes = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000416 cur->entities = NULL;
417 if (doc != NULL)
418 doc->intSubset = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000419
420 return(cur);
421}
422
Daniel Veillard97b58771998-10-20 06:14:16 +0000423/**
424 * xmlFreeDtd:
425 * @cur: the DTD structure to free up
426 *
427 * Free a DTD structure.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000428 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000429void
430xmlFreeDtd(xmlDtdPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000431 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000432#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +0000433 fprintf(stderr, "xmlFreeDtd : DTD == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000434#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000435 return;
436 }
Daniel Veillard6454aec1999-09-02 22:04:43 +0000437 if (cur->name != NULL) xmlFree((char *) cur->name);
438 if (cur->SystemID != NULL) xmlFree((char *) cur->SystemID);
439 if (cur->ExternalID != NULL) xmlFree((char *) cur->ExternalID);
Daniel Veillard1e346af1999-02-22 10:33:01 +0000440 if (cur->notations != NULL)
441 xmlFreeNotationTable((xmlNotationTablePtr) cur->notations);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000442 if (cur->elements != NULL)
Daniel Veillard3b9def11999-01-31 22:15:06 +0000443 xmlFreeElementTable((xmlElementTablePtr) cur->elements);
Daniel Veillard1e346af1999-02-22 10:33:01 +0000444 if (cur->attributes != NULL)
445 xmlFreeAttributeTable((xmlAttributeTablePtr) cur->attributes);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000446 if (cur->entities != NULL)
447 xmlFreeEntitiesTable((xmlEntitiesTablePtr) cur->entities);
448 memset(cur, -1, sizeof(xmlDtd));
Daniel Veillard6454aec1999-09-02 22:04:43 +0000449 xmlFree(cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000450}
451
Daniel Veillard97b58771998-10-20 06:14:16 +0000452/**
453 * xmlNewDoc:
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000454 * @version: xmlChar string giving the version of XML "1.0"
Daniel Veillard97b58771998-10-20 06:14:16 +0000455 *
Daniel Veillard1e346af1999-02-22 10:33:01 +0000456 * Returns a new document
Daniel Veillard260a68f1998-08-13 03:39:55 +0000457 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000458xmlDocPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000459xmlNewDoc(const xmlChar *version) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000460 xmlDocPtr cur;
461
462 if (version == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000463#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +0000464 fprintf(stderr, "xmlNewDoc : version == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000465#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000466 return(NULL);
467 }
468
469 /*
470 * Allocate a new document and fill the fields.
471 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000472 cur = (xmlDocPtr) xmlMalloc(sizeof(xmlDoc));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000473 if (cur == NULL) {
474 fprintf(stderr, "xmlNewDoc : malloc failed\n");
475 return(NULL);
476 }
477
Daniel Veillard33942841998-10-18 19:12:41 +0000478 cur->type = XML_DOCUMENT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000479 cur->version = xmlStrdup(version);
480 cur->name = NULL;
481 cur->root = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000482 cur->intSubset = NULL;
483 cur->extSubset = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000484 cur->oldNs = NULL;
485 cur->encoding = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000486 cur->standalone = -1;
Daniel Veillard11a48ec1999-11-23 10:40:46 +0000487 cur->compression = -1; /* not initialized */
Daniel Veillardb96e6431999-08-29 21:02:19 +0000488 cur->ids = NULL;
Daniel Veillardc08a2c61999-09-08 21:35:25 +0000489 cur->refs = NULL;
Daniel Veillard27d88741999-05-29 11:51:49 +0000490#ifndef XML_WITHOUT_CORBA
Daniel Veillard27fb0751998-10-17 06:47:46 +0000491 cur->_private = NULL;
492 cur->vepv = NULL;
493#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000494 return(cur);
495}
496
Daniel Veillard97b58771998-10-20 06:14:16 +0000497/**
498 * xmlFreeDoc:
499 * @cur: pointer to the document
500 * @:
501 *
502 * Free up all the structures used by a document, tree included.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000503 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000504void
505xmlFreeDoc(xmlDocPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000506 if (cur == NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000507#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +0000508 fprintf(stderr, "xmlFreeDoc : document == NULL\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000509#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000510 return;
511 }
Daniel Veillard6454aec1999-09-02 22:04:43 +0000512 if (cur->version != NULL) xmlFree((char *) cur->version);
513 if (cur->name != NULL) xmlFree((char *) cur->name);
514 if (cur->encoding != NULL) xmlFree((char *) cur->encoding);
515 if (cur->root != NULL) xmlFreeNodeList(cur->root);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000516 if (cur->intSubset != NULL) xmlFreeDtd(cur->intSubset);
517 if (cur->extSubset != NULL) xmlFreeDtd(cur->extSubset);
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000518 if (cur->oldNs != NULL) xmlFreeNsList(cur->oldNs);
Daniel Veillardb96e6431999-08-29 21:02:19 +0000519 if (cur->ids != NULL) xmlFreeIDTable((xmlIDTablePtr) cur->ids);
Daniel Veillardc08a2c61999-09-08 21:35:25 +0000520 if (cur->refs != NULL) xmlFreeRefTable((xmlRefTablePtr) cur->refs);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000521 memset(cur, -1, sizeof(xmlDoc));
Daniel Veillard6454aec1999-09-02 22:04:43 +0000522 xmlFree(cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000523}
524
Daniel Veillard97b58771998-10-20 06:14:16 +0000525/**
Daniel Veillard16253641998-10-28 22:58:05 +0000526 * xmlStringLenGetNodeList:
527 * @doc: the document
528 * @value: the value of the text
Daniel Veillard1e346af1999-02-22 10:33:01 +0000529 * @len: the length of the string value
Daniel Veillard16253641998-10-28 22:58:05 +0000530 *
531 * Parse the value string and build the node list associated. Should
532 * produce a flat tree with only TEXTs and ENTITY_REFs.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000533 * Returns a pointer to the first child
Daniel Veillard16253641998-10-28 22:58:05 +0000534 */
535xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000536xmlStringLenGetNodeList(xmlDocPtr doc, const xmlChar *value, int len) {
Daniel Veillard16253641998-10-28 22:58:05 +0000537 xmlNodePtr ret = NULL, last = NULL;
538 xmlNodePtr node;
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000539 xmlChar *val;
540 const xmlChar *cur = value;
541 const xmlChar *q;
Daniel Veillard25940b71998-10-29 05:51:30 +0000542 xmlEntityPtr ent;
Daniel Veillard16253641998-10-28 22:58:05 +0000543
544 if (value == NULL) return(NULL);
545
546 q = cur;
547 while ((*cur != 0) && (cur - value < len)) {
548 if (*cur == '&') {
Daniel Veillard25940b71998-10-29 05:51:30 +0000549 /*
550 * Save the current text.
551 */
Daniel Veillard16253641998-10-28 22:58:05 +0000552 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000553 if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
554 xmlNodeAddContentLen(last, q, cur - q);
555 } else {
556 node = xmlNewDocTextLen(doc, q, cur - q);
557 if (node == NULL) return(ret);
558 if (last == NULL)
559 last = ret = node;
560 else {
561 last->next = node;
562 node->prev = last;
563 last = node;
564 }
Daniel Veillard16253641998-10-28 22:58:05 +0000565 }
566 }
Daniel Veillard25940b71998-10-29 05:51:30 +0000567 /*
568 * Read the entity string
569 */
Daniel Veillard16253641998-10-28 22:58:05 +0000570 cur++;
571 q = cur;
572 while ((*cur != 0) && (cur - value < len) && (*cur != ';')) cur++;
573 if ((*cur == 0) || (cur - value >= len)) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000574#ifdef DEBUG_TREE
Daniel Veillard16253641998-10-28 22:58:05 +0000575 fprintf(stderr,
Daniel Veillard011b63c1999-06-02 17:44:04 +0000576 "xmlStringLenGetNodeList: unterminated entity %30s\n", q);
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000577#endif
Daniel Veillard16253641998-10-28 22:58:05 +0000578 return(ret);
579 }
580 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000581 /*
582 * Predefined entities don't generate nodes
583 */
Daniel Veillard16253641998-10-28 22:58:05 +0000584 val = xmlStrndup(q, cur - q);
Daniel Veillard25940b71998-10-29 05:51:30 +0000585 ent = xmlGetDocEntity(doc, val);
586 if ((ent != NULL) &&
587 (ent->type == XML_INTERNAL_PREDEFINED_ENTITY)) {
588 if (last == NULL) {
589 node = xmlNewDocText(doc, ent->content);
590 last = ret = node;
591 } else
592 xmlNodeAddContent(last, ent->content);
593
594 } else {
595 /*
596 * Create a new REFERENCE_REF node
597 */
598 node = xmlNewReference(doc, val);
Daniel Veillard242590e1998-11-13 18:04:35 +0000599 if (node == NULL) {
Daniel Veillard6454aec1999-09-02 22:04:43 +0000600 if (val != NULL) xmlFree(val);
Daniel Veillard242590e1998-11-13 18:04:35 +0000601 return(ret);
602 }
Daniel Veillard25940b71998-10-29 05:51:30 +0000603 if (last == NULL)
604 last = ret = node;
605 else {
606 last->next = node;
607 node->prev = last;
608 last = node;
609 }
Daniel Veillard16253641998-10-28 22:58:05 +0000610 }
Daniel Veillard6454aec1999-09-02 22:04:43 +0000611 xmlFree(val);
Daniel Veillard16253641998-10-28 22:58:05 +0000612 }
613 cur++;
614 q = cur;
615 } else
616 cur++;
617 }
618 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000619 /*
620 * Handle the last piece of text.
621 */
622 if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
623 xmlNodeAddContentLen(last, q, cur - q);
624 } else {
625 node = xmlNewDocTextLen(doc, q, cur - q);
626 if (node == NULL) return(ret);
627 if (last == NULL)
628 last = ret = node;
629 else {
630 last->next = node;
631 node->prev = last;
632 last = node;
633 }
Daniel Veillard16253641998-10-28 22:58:05 +0000634 }
635 }
636 return(ret);
637}
638
639/**
Daniel Veillardccb09631998-10-27 06:21:04 +0000640 * xmlStringGetNodeList:
641 * @doc: the document
642 * @value: the value of the attribute
643 *
644 * Parse the value string and build the node list associated. Should
645 * produce a flat tree with only TEXTs and ENTITY_REFs.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000646 * Returns a pointer to the first child
Daniel Veillardccb09631998-10-27 06:21:04 +0000647 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000648xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000649xmlStringGetNodeList(xmlDocPtr doc, const xmlChar *value) {
Daniel Veillardccb09631998-10-27 06:21:04 +0000650 xmlNodePtr ret = NULL, last = NULL;
651 xmlNodePtr node;
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000652 xmlChar *val;
653 const xmlChar *cur = value;
654 const xmlChar *q;
Daniel Veillard25940b71998-10-29 05:51:30 +0000655 xmlEntityPtr ent;
Daniel Veillardccb09631998-10-27 06:21:04 +0000656
657 if (value == NULL) return(NULL);
658
659 q = cur;
660 while (*cur != 0) {
661 if (*cur == '&') {
Daniel Veillard25940b71998-10-29 05:51:30 +0000662 /*
663 * Save the current text.
664 */
Daniel Veillardccb09631998-10-27 06:21:04 +0000665 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000666 if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
667 xmlNodeAddContentLen(last, q, cur - q);
668 } else {
669 node = xmlNewDocTextLen(doc, q, cur - q);
670 if (node == NULL) return(ret);
671 if (last == NULL)
672 last = ret = node;
673 else {
674 last->next = node;
675 node->prev = last;
676 last = node;
677 }
Daniel Veillardccb09631998-10-27 06:21:04 +0000678 }
679 }
Daniel Veillard25940b71998-10-29 05:51:30 +0000680 /*
681 * Read the entity string
682 */
Daniel Veillardccb09631998-10-27 06:21:04 +0000683 cur++;
684 q = cur;
685 while ((*cur != 0) && (*cur != ';')) cur++;
686 if (*cur == 0) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000687#ifdef DEBUG_TREE
Daniel Veillardccb09631998-10-27 06:21:04 +0000688 fprintf(stderr,
689 "xmlStringGetNodeList: unterminated entity %30s\n", q);
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000690#endif
Daniel Veillardccb09631998-10-27 06:21:04 +0000691 return(ret);
692 }
693 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000694 /*
695 * Predefined entities don't generate nodes
696 */
Daniel Veillardccb09631998-10-27 06:21:04 +0000697 val = xmlStrndup(q, cur - q);
Daniel Veillard25940b71998-10-29 05:51:30 +0000698 ent = xmlGetDocEntity(doc, val);
699 if ((ent != NULL) &&
700 (ent->type == XML_INTERNAL_PREDEFINED_ENTITY)) {
701 if (last == NULL) {
702 node = xmlNewDocText(doc, ent->content);
703 last = ret = node;
704 } else
705 xmlNodeAddContent(last, ent->content);
706
707 } else {
708 /*
709 * Create a new REFERENCE_REF node
710 */
Daniel Veillard25940b71998-10-29 05:51:30 +0000711 node = xmlNewReference(doc, val);
Daniel Veillard242590e1998-11-13 18:04:35 +0000712 if (node == NULL) {
Daniel Veillard6454aec1999-09-02 22:04:43 +0000713 if (val != NULL) xmlFree(val);
Daniel Veillard242590e1998-11-13 18:04:35 +0000714 return(ret);
715 }
Daniel Veillard25940b71998-10-29 05:51:30 +0000716 if (last == NULL)
717 last = ret = node;
718 else {
719 last->next = node;
720 node->prev = last;
721 last = node;
722 }
Daniel Veillardccb09631998-10-27 06:21:04 +0000723 }
Daniel Veillard6454aec1999-09-02 22:04:43 +0000724 xmlFree(val);
Daniel Veillardccb09631998-10-27 06:21:04 +0000725 }
726 cur++;
727 q = cur;
728 } else
729 cur++;
730 }
731 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000732 /*
733 * Handle the last piece of text.
734 */
735 if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
736 xmlNodeAddContentLen(last, q, cur - q);
737 } else {
738 node = xmlNewDocTextLen(doc, q, cur - q);
739 if (node == NULL) return(ret);
740 if (last == NULL)
741 last = ret = node;
742 else {
743 last->next = node;
744 node->prev = last;
745 last = node;
746 }
Daniel Veillardccb09631998-10-27 06:21:04 +0000747 }
748 }
749 return(ret);
750}
751
752/**
753 * xmlNodeListGetString:
754 * @doc: the document
755 * @list: a Node list
756 * @inLine: should we replace entity contents or show their external form
757 *
758 * Returns the string equivalent to the text contained in the Node list
759 * made of TEXTs and ENTITY_REFs
Daniel Veillard1e346af1999-02-22 10:33:01 +0000760 * Returns a pointer to the string copy, the calller must free it.
Daniel Veillardccb09631998-10-27 06:21:04 +0000761 */
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000762xmlChar *
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000763xmlNodeListGetString(xmlDocPtr doc, xmlNodePtr list, int inLine) {
Daniel Veillardccb09631998-10-27 06:21:04 +0000764 xmlNodePtr node = list;
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000765 xmlChar *ret = NULL;
Daniel Veillardccb09631998-10-27 06:21:04 +0000766 xmlEntityPtr ent;
767
768 if (list == NULL) return(NULL);
769
770 while (node != NULL) {
771 if (node->type == XML_TEXT_NODE) {
Daniel Veillard71b656e2000-01-05 14:46:17 +0000772 if (inLine) {
Daniel Veillardf5c2c871999-12-01 09:51:45 +0000773#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardccb09631998-10-27 06:21:04 +0000774 ret = xmlStrcat(ret, node->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +0000775#else
776 ret = xmlStrcat(ret, xmlBufferContent(node->content));
777#endif
778 } else {
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000779 xmlChar *buffer;
Daniel Veillard14fff061999-06-22 21:49:07 +0000780
Daniel Veillardf5c2c871999-12-01 09:51:45 +0000781#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard14fff061999-06-22 21:49:07 +0000782 buffer = xmlEncodeEntitiesReentrant(doc, node->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +0000783#else
784 buffer = xmlEncodeEntitiesReentrant(doc,
785 xmlBufferContent(node->content));
786#endif
Daniel Veillard14fff061999-06-22 21:49:07 +0000787 if (buffer != NULL) {
788 ret = xmlStrcat(ret, buffer);
Daniel Veillard6454aec1999-09-02 22:04:43 +0000789 xmlFree(buffer);
Daniel Veillard14fff061999-06-22 21:49:07 +0000790 }
791 }
Daniel Veillardccb09631998-10-27 06:21:04 +0000792 } else if (node->type == XML_ENTITY_REF_NODE) {
793 if (inLine) {
794 ent = xmlGetDocEntity(doc, node->name);
795 if (ent != NULL)
796 ret = xmlStrcat(ret, ent->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +0000797 else {
798#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardccb09631998-10-27 06:21:04 +0000799 ret = xmlStrcat(ret, node->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +0000800#else
801 ret = xmlStrcat(ret, xmlBufferContent(node->content));
802#endif
803 }
Daniel Veillardccb09631998-10-27 06:21:04 +0000804 } else {
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000805 xmlChar buf[2];
Daniel Veillardccb09631998-10-27 06:21:04 +0000806 buf[0] = '&'; buf[1] = 0;
807 ret = xmlStrncat(ret, buf, 1);
808 ret = xmlStrcat(ret, node->name);
809 buf[0] = ';'; buf[1] = 0;
810 ret = xmlStrncat(ret, buf, 1);
811 }
812 }
813#if 0
814 else {
815 fprintf(stderr, "xmlGetNodeListString : invalide node type %d\n",
816 node->type);
817 }
818#endif
819 node = node->next;
820 }
821 return(ret);
822}
823
824/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000825 * xmlNewProp:
826 * @node: the holding node
827 * @name: the name of the attribute
828 * @value: the value of the attribute
829 *
830 * Create a new property carried by a node.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000831 * Returns a pointer to the attribute
Daniel Veillard260a68f1998-08-13 03:39:55 +0000832 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000833xmlAttrPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000834xmlNewProp(xmlNodePtr node, const xmlChar *name, const xmlChar *value) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000835 xmlAttrPtr cur;
836
837 if (name == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000838#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +0000839 fprintf(stderr, "xmlNewProp : name == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000840#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000841 return(NULL);
842 }
843
844 /*
845 * Allocate a new property and fill the fields.
846 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000847 cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000848 if (cur == NULL) {
849 fprintf(stderr, "xmlNewProp : malloc failed\n");
850 return(NULL);
851 }
852
Daniel Veillard33942841998-10-18 19:12:41 +0000853 cur->type = XML_ATTRIBUTE_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000854 cur->node = node;
Daniel Veillardb96e6431999-08-29 21:02:19 +0000855 cur->ns = NULL;
856 cur->name = xmlStrdup(name);
Daniel Veillard51e3b151999-11-12 17:02:31 +0000857 if (value != NULL) {
858 xmlChar *buffer;
859 buffer = xmlEncodeEntitiesReentrant(node->doc, value);
860 cur->val = xmlStringGetNodeList(node->doc, buffer);
861 xmlFree(buffer);
862 }
Daniel Veillardb96e6431999-08-29 21:02:19 +0000863 else
864 cur->val = NULL;
865#ifndef XML_WITHOUT_CORBA
866 cur->_private = NULL;
867 cur->vepv = NULL;
868#endif
869
870 /*
871 * Add it at the end to preserve parsing order ...
872 */
873 cur->next = NULL;
874 if (node != NULL) {
875 if (node->properties == NULL) {
876 node->properties = cur;
877 } else {
878 xmlAttrPtr prev = node->properties;
879
880 while (prev->next != NULL) prev = prev->next;
881 prev->next = cur;
882 }
883 }
Daniel Veillard00fdf371999-10-08 09:40:39 +0000884#ifndef XML_WITHOUT_CORBA
885 cur->_private = NULL;
886 cur->vepv = NULL;
887#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +0000888 return(cur);
889}
890
891/**
892 * xmlNewNsProp:
893 * @node: the holding node
894 * @ns: the namespace
895 * @name: the name of the attribute
896 * @value: the value of the attribute
897 *
898 * Create a new property tagged with a namespace and carried by a node.
899 * Returns a pointer to the attribute
900 */
901xmlAttrPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000902xmlNewNsProp(xmlNodePtr node, xmlNsPtr ns, const xmlChar *name,
903 const xmlChar *value) {
Daniel Veillardb96e6431999-08-29 21:02:19 +0000904 xmlAttrPtr cur;
905
906 if (name == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000907#ifdef DEBUG_TREE
Daniel Veillardb96e6431999-08-29 21:02:19 +0000908 fprintf(stderr, "xmlNewProp : name == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000909#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +0000910 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 Veillardb96e6431999-08-29 21:02:19 +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 = node;
924 cur->ns = ns;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000925 cur->name = xmlStrdup(name);
926 if (value != NULL)
Daniel Veillardccb09631998-10-27 06:21:04 +0000927 cur->val = xmlStringGetNodeList(node->doc, value);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000928 else
Daniel Veillardccb09631998-10-27 06:21:04 +0000929 cur->val = NULL;
Daniel Veillard27d88741999-05-29 11:51:49 +0000930#ifndef XML_WITHOUT_CORBA
Daniel Veillard27fb0751998-10-17 06:47:46 +0000931 cur->_private = NULL;
932 cur->vepv = NULL;
933#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000934
935 /*
936 * Add it at the end to preserve parsing order ...
937 */
938 cur->next = NULL;
939 if (node != NULL) {
940 if (node->properties == NULL) {
941 node->properties = cur;
942 } else {
943 xmlAttrPtr prev = node->properties;
944
945 while (prev->next != NULL) prev = prev->next;
946 prev->next = cur;
947 }
948 }
949 return(cur);
950}
951
Daniel Veillard97b58771998-10-20 06:14:16 +0000952/**
Daniel Veillardccb09631998-10-27 06:21:04 +0000953 * xmlNewDocProp:
954 * @doc: the document
955 * @name: the name of the attribute
956 * @value: the value of the attribute
957 *
958 * Create a new property carried by a document.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000959 * Returns a pointer to the attribute
Daniel Veillardccb09631998-10-27 06:21:04 +0000960 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000961xmlAttrPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000962xmlNewDocProp(xmlDocPtr doc, const xmlChar *name, const xmlChar *value) {
Daniel Veillardccb09631998-10-27 06:21:04 +0000963 xmlAttrPtr cur;
964
965 if (name == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000966#ifdef DEBUG_TREE
Daniel Veillardccb09631998-10-27 06:21:04 +0000967 fprintf(stderr, "xmlNewProp : name == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000968#endif
Daniel Veillardccb09631998-10-27 06:21:04 +0000969 return(NULL);
970 }
971
972 /*
973 * Allocate a new property and fill the fields.
974 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000975 cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr));
Daniel Veillardccb09631998-10-27 06:21:04 +0000976 if (cur == NULL) {
977 fprintf(stderr, "xmlNewProp : malloc failed\n");
978 return(NULL);
979 }
980
981 cur->type = XML_ATTRIBUTE_NODE;
982 cur->node = NULL;
983 cur->name = xmlStrdup(name);
984 if (value != NULL)
985 cur->val = xmlStringGetNodeList(doc, value);
986 else
987 cur->val = NULL;
Daniel Veillard27d88741999-05-29 11:51:49 +0000988#ifndef XML_WITHOUT_CORBA
Daniel Veillardccb09631998-10-27 06:21:04 +0000989 cur->_private = NULL;
990 cur->vepv = NULL;
991#endif
992
993 cur->next = NULL;
994 return(cur);
995}
996
997/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000998 * xmlFreePropList:
999 * @cur: the first property in the list
1000 *
1001 * Free a property and all its siblings, all the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001002 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001003void
1004xmlFreePropList(xmlAttrPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001005 xmlAttrPtr next;
1006 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001007#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00001008 fprintf(stderr, "xmlFreePropList : property == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001009#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001010 return;
1011 }
1012 while (cur != NULL) {
1013 next = cur->next;
1014 xmlFreeProp(cur);
1015 cur = next;
1016 }
1017}
1018
Daniel Veillard97b58771998-10-20 06:14:16 +00001019/**
1020 * xmlFreeProp:
Daniel Veillard686d6b62000-01-03 11:08:02 +00001021 * @cur: an attribute
Daniel Veillard97b58771998-10-20 06:14:16 +00001022 *
Daniel Veillard686d6b62000-01-03 11:08:02 +00001023 * Free one attribute, all the content is freed too
Daniel Veillard260a68f1998-08-13 03:39:55 +00001024 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001025void
1026xmlFreeProp(xmlAttrPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001027 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001028#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00001029 fprintf(stderr, "xmlFreeProp : property == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001030#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001031 return;
1032 }
Daniel Veillard71b656e2000-01-05 14:46:17 +00001033 /* Check for ID removal -> leading to invalid references ! */
1034 if ((cur->node != NULL) &&
1035 (xmlIsID(cur->node->doc, cur->node, cur)))
1036 xmlRemoveID(cur->node->doc, cur);
Daniel Veillard6454aec1999-09-02 22:04:43 +00001037 if (cur->name != NULL) xmlFree((char *) cur->name);
Daniel Veillardccb09631998-10-27 06:21:04 +00001038 if (cur->val != NULL) xmlFreeNodeList(cur->val);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001039 memset(cur, -1, sizeof(xmlAttr));
Daniel Veillard6454aec1999-09-02 22:04:43 +00001040 xmlFree(cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001041}
1042
Daniel Veillard97b58771998-10-20 06:14:16 +00001043/**
Daniel Veillard686d6b62000-01-03 11:08:02 +00001044 * xmlRemoveProp:
1045 * @cur: an attribute
1046 *
1047 * Unlink and free one attribute, all the content is freed too
1048 * Note this doesn't work for namespace definition attributes
1049 *
1050 * Returns 0 if success and -1 in case of error.
1051 */
1052int
1053xmlRemoveProp(xmlAttrPtr cur) {
1054 xmlAttrPtr tmp;
1055 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001056#ifdef DEBUG_TREE
Daniel Veillard686d6b62000-01-03 11:08:02 +00001057 fprintf(stderr, "xmlRemoveProp : cur == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001058#endif
Daniel Veillard686d6b62000-01-03 11:08:02 +00001059 return(-1);
1060 }
1061 if (cur->node == NULL) {
1062 fprintf(stderr, "xmlRemoveProp : cur->node == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001063#endif
Daniel Veillard686d6b62000-01-03 11:08:02 +00001064 return(-1);
1065 }
1066 tmp = cur->node->properties;
1067 if (tmp == cur) {
1068 cur->node->properties = cur->next;
1069 xmlFreeProp(cur);
1070 return(0);
1071 }
1072 while (tmp != NULL) {
1073 if (tmp->next == cur) {
1074 tmp->next = cur->next;
1075 xmlFreeProp(cur);
1076 return(0);
1077 }
1078 tmp = tmp->next;
1079 }
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001080#ifdef DEBUG_TREE
Daniel Veillard686d6b62000-01-03 11:08:02 +00001081 fprintf(stderr, "xmlRemoveProp : attribute not owned by its node\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001082#endif
Daniel Veillard686d6b62000-01-03 11:08:02 +00001083 return(-1);
1084}
1085
1086/**
Daniel Veillardb96e6431999-08-29 21:02:19 +00001087 * xmlNewPI:
1088 * @name: the processing instruction name
1089 * @content: the PI content
1090 *
1091 * Creation of a processing instruction element.
1092 * Returns a pointer to the new node object.
1093 */
1094xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001095xmlNewPI(const xmlChar *name, const xmlChar *content) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00001096 xmlNodePtr cur;
1097
1098 if (name == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001099#ifdef DEBUG_TREE
Daniel Veillardb96e6431999-08-29 21:02:19 +00001100 fprintf(stderr, "xmlNewPI : name == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001101#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +00001102 return(NULL);
1103 }
1104
1105 /*
1106 * Allocate a new node and fill the fields.
1107 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001108 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillardb96e6431999-08-29 21:02:19 +00001109 if (cur == NULL) {
1110 fprintf(stderr, "xmlNewPI : malloc failed\n");
1111 return(NULL);
1112 }
1113
1114 cur->type = XML_PI_NODE;
1115 cur->doc = NULL;
1116 cur->parent = NULL;
1117 cur->next = NULL;
1118 cur->prev = NULL;
1119 cur->childs = NULL;
1120 cur->last = NULL;
1121 cur->properties = NULL;
1122 cur->name = xmlStrdup(name);
1123 cur->ns = NULL;
1124 cur->nsDef = NULL;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001125 if (content != NULL) {
1126#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardb96e6431999-08-29 21:02:19 +00001127 cur->content = xmlStrdup(content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001128#else
1129 cur->content = xmlBufferCreateSize(0);
1130 xmlBufferSetAllocationScheme(cur->content,
1131 xmlGetBufferAllocationScheme());
1132 xmlBufferAdd(cur->content, content, -1);
1133#endif
1134 } else
Daniel Veillardb96e6431999-08-29 21:02:19 +00001135 cur->content = NULL;
1136#ifndef XML_WITHOUT_CORBA
1137 cur->_private = NULL;
1138 cur->vepv = NULL;
1139#endif
1140 return(cur);
1141}
1142
1143/**
Daniel Veillard97b58771998-10-20 06:14:16 +00001144 * xmlNewNode:
1145 * @ns: namespace if any
1146 * @name: the node name
Daniel Veillard97b58771998-10-20 06:14:16 +00001147 *
1148 * Creation of a new node element. @ns and @content are optionnal (NULL).
Daniel Veillardccb09631998-10-27 06:21:04 +00001149 * If content is non NULL, a child list containing the TEXTs and
1150 * ENTITY_REFs node will be created.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001151 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001152 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001153xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001154xmlNewNode(xmlNsPtr ns, const xmlChar *name) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001155 xmlNodePtr cur;
1156
1157 if (name == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001158#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00001159 fprintf(stderr, "xmlNewNode : name == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001160#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001161 return(NULL);
1162 }
1163
1164 /*
1165 * Allocate a new node and fill the fields.
1166 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001167 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillard260a68f1998-08-13 03:39:55 +00001168 if (cur == NULL) {
1169 fprintf(stderr, "xmlNewNode : malloc failed\n");
1170 return(NULL);
1171 }
1172
Daniel Veillard33942841998-10-18 19:12:41 +00001173 cur->type = XML_ELEMENT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001174 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001175 cur->parent = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001176 cur->next = NULL;
1177 cur->prev = NULL;
1178 cur->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001179 cur->last = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001180 cur->properties = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001181 cur->name = xmlStrdup(name);
1182 cur->ns = ns;
1183 cur->nsDef = NULL;
Daniel Veillardccb09631998-10-27 06:21:04 +00001184 cur->content = NULL;
Daniel Veillard27d88741999-05-29 11:51:49 +00001185#ifndef XML_WITHOUT_CORBA
Daniel Veillard27fb0751998-10-17 06:47:46 +00001186 cur->_private = NULL;
1187 cur->vepv = NULL;
1188#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001189 return(cur);
1190}
1191
Daniel Veillard97b58771998-10-20 06:14:16 +00001192/**
1193 * xmlNewDocNode:
1194 * @doc: the document
1195 * @ns: namespace if any
1196 * @name: the node name
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001197 * @content: the XML text content if any
Daniel Veillard97b58771998-10-20 06:14:16 +00001198 *
1199 * Creation of a new node element within a document. @ns and @content
1200 * are optionnal (NULL).
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001201 * NOTE: @content is supposed to be a piece of XML CDATA, so it allow entities
1202 * references, but XML special chars need to be escaped first by using
1203 * xmlEncodeEntitiesReentrant(). Use xmlNewDocRawNode() if you don't
1204 * need entities support.
1205 *
Daniel Veillard1e346af1999-02-22 10:33:01 +00001206 * Returns a pointer to the new node object.
Daniel Veillard97b58771998-10-20 06:14:16 +00001207 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001208xmlNodePtr
1209xmlNewDocNode(xmlDocPtr doc, xmlNsPtr ns,
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001210 const xmlChar *name, const xmlChar *content) {
Daniel Veillard0bef1311998-10-14 02:36:47 +00001211 xmlNodePtr cur;
1212
Daniel Veillardccb09631998-10-27 06:21:04 +00001213 cur = xmlNewNode(ns, name);
1214 if (cur != NULL) {
1215 cur->doc = doc;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001216 if (content != NULL) {
Daniel Veillardccb09631998-10-27 06:21:04 +00001217 cur->childs = xmlStringGetNodeList(doc, content);
Daniel Veillard1e346af1999-02-22 10:33:01 +00001218 UPDATE_LAST_CHILD(cur)
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001219 }
Daniel Veillardccb09631998-10-27 06:21:04 +00001220 }
Daniel Veillard0bef1311998-10-14 02:36:47 +00001221 return(cur);
1222}
1223
1224
Daniel Veillard97b58771998-10-20 06:14:16 +00001225/**
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001226 * xmlNewDocRawNode:
1227 * @doc: the document
1228 * @ns: namespace if any
1229 * @name: the node name
1230 * @content: the text content if any
1231 *
1232 * Creation of a new node element within a document. @ns and @content
1233 * are optionnal (NULL).
1234 *
1235 * Returns a pointer to the new node object.
1236 */
1237xmlNodePtr
1238xmlNewDocRawNode(xmlDocPtr doc, xmlNsPtr ns,
1239 const xmlChar *name, const xmlChar *content) {
1240 xmlNodePtr cur;
1241
1242 cur = xmlNewNode(ns, name);
1243 if (cur != NULL) {
1244 cur->doc = doc;
1245 if (content != NULL) {
1246 cur->childs = xmlNewDocText(doc, content);
1247 UPDATE_LAST_CHILD(cur)
1248 }
1249 }
1250 return(cur);
1251}
1252
Daniel Veillard2eac5032000-01-09 21:08:56 +00001253/**
1254 * xmlNewDocFragment:
1255 * @doc: the document owning the fragment
1256 *
1257 * Creation of a new Fragment node.
1258 * Returns a pointer to the new node object.
1259 */
1260xmlNodePtr
1261xmlNewDocFragment(xmlDocPtr doc) {
1262 xmlNodePtr cur;
1263
1264 /*
1265 * Allocate a new DocumentFragment node and fill the fields.
1266 */
1267 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
1268 if (cur == NULL) {
1269 fprintf(stderr, "xmlNewDocFragment : malloc failed\n");
1270 return(NULL);
1271 }
1272
1273 cur->type = XML_DOCUMENT_FRAG_NODE;
1274 cur->doc = doc;
1275 cur->parent = NULL;
1276 cur->next = NULL;
1277 cur->prev = NULL;
1278 cur->childs = NULL;
1279 cur->last = NULL;
1280 cur->properties = NULL;
1281 cur->name = NULL;
1282 cur->ns = NULL;
1283 cur->nsDef = NULL;
1284 cur->content = NULL;
1285#ifndef XML_WITHOUT_CORBA
1286 cur->_private = NULL;
1287 cur->vepv = NULL;
1288#endif
1289 return(cur);
1290}
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001291
1292/**
Daniel Veillard97b58771998-10-20 06:14:16 +00001293 * xmlNewText:
1294 * @content: the text content
1295 *
1296 * Creation of a new text node.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001297 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001298 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001299xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001300xmlNewText(const xmlChar *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001301 xmlNodePtr cur;
1302
1303 /*
1304 * Allocate a new node and fill the fields.
1305 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001306 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillard260a68f1998-08-13 03:39:55 +00001307 if (cur == NULL) {
1308 fprintf(stderr, "xmlNewText : malloc failed\n");
1309 return(NULL);
1310 }
1311
Daniel Veillard33942841998-10-18 19:12:41 +00001312 cur->type = XML_TEXT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001313 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001314 cur->parent = NULL;
1315 cur->next = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001316 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001317 cur->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001318 cur->last = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001319 cur->properties = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001320 cur->type = XML_TEXT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001321 cur->name = xmlStrdup(xmlStringText);
1322 cur->ns = NULL;
1323 cur->nsDef = NULL;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001324 if (content != NULL) {
1325#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard260a68f1998-08-13 03:39:55 +00001326 cur->content = xmlStrdup(content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001327#else
1328 cur->content = xmlBufferCreateSize(0);
1329 xmlBufferSetAllocationScheme(cur->content,
1330 xmlGetBufferAllocationScheme());
1331 xmlBufferAdd(cur->content, content, -1);
1332#endif
1333 } else
Daniel Veillard260a68f1998-08-13 03:39:55 +00001334 cur->content = NULL;
Daniel Veillard00fdf371999-10-08 09:40:39 +00001335#ifndef XML_WITHOUT_CORBA
1336 cur->_private = NULL;
1337 cur->vepv = NULL;
1338#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001339 return(cur);
1340}
1341
Daniel Veillard97b58771998-10-20 06:14:16 +00001342/**
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001343 * xmlNewTextChild:
1344 * @parent: the parent node
1345 * @ns: a namespace if any
1346 * @name: the name of the child
1347 * @content: the text content of the child if any.
1348 *
1349 * Creation of a new child element, added at the end of @parent childs list.
1350 * @ns and @content parameters are optionnal (NULL). If content is non NULL,
1351 * a child TEXT node will be created containing the string content.
1352 *
1353 * Returns a pointer to the new node object.
1354 */
1355xmlNodePtr
1356xmlNewTextChild(xmlNodePtr parent, xmlNsPtr ns,
1357 const xmlChar *name, const xmlChar *content) {
1358 xmlNodePtr cur, prev;
1359
1360 if (parent == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001361#ifdef DEBUG_TREE
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001362 fprintf(stderr, "xmlNewTextChild : parent == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001363#endif
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001364 return(NULL);
1365 }
1366
1367 if (name == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001368#ifdef DEBUG_TREE
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001369 fprintf(stderr, "xmlNewTextChild : name == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001370#endif
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001371 return(NULL);
1372 }
1373
1374 /*
1375 * Allocate a new node
1376 */
1377 if (ns == NULL)
1378 cur = xmlNewDocRawNode(parent->doc, parent->ns, name, content);
1379 else
1380 cur = xmlNewDocRawNode(parent->doc, ns, name, content);
1381 if (cur == NULL) return(NULL);
1382
1383 /*
1384 * add the new element at the end of the childs list.
1385 */
1386 cur->type = XML_ELEMENT_NODE;
1387 cur->parent = parent;
1388 cur->doc = parent->doc;
1389 if (parent->childs == NULL) {
1390 parent->childs = cur;
1391 parent->last = cur;
1392 } else {
1393 prev = parent->last;
1394 prev->next = cur;
1395 cur->prev = prev;
1396 parent->last = cur;
1397 }
1398
1399 return(cur);
1400}
1401
1402/**
Daniel Veillardccb09631998-10-27 06:21:04 +00001403 * xmlNewReference:
1404 * @doc: the document
1405 * @name: the reference name, or the reference string with & and ;
1406 *
1407 * Creation of a new reference node.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001408 * Returns a pointer to the new node object.
Daniel Veillardccb09631998-10-27 06:21:04 +00001409 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001410xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001411xmlNewReference(xmlDocPtr doc, const xmlChar *name) {
Daniel Veillardccb09631998-10-27 06:21:04 +00001412 xmlNodePtr cur;
1413 xmlEntityPtr ent;
1414
1415 /*
1416 * Allocate a new node and fill the fields.
1417 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001418 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillardccb09631998-10-27 06:21:04 +00001419 if (cur == NULL) {
1420 fprintf(stderr, "xmlNewText : malloc failed\n");
1421 return(NULL);
1422 }
1423
1424 cur->type = XML_ENTITY_REF_NODE;
Daniel Veillard10c6a8f1998-10-28 01:00:12 +00001425 cur->doc = doc;
Daniel Veillardccb09631998-10-27 06:21:04 +00001426 cur->parent = NULL;
1427 cur->next = NULL;
1428 cur->prev = NULL;
1429 cur->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001430 cur->last = NULL;
Daniel Veillardccb09631998-10-27 06:21:04 +00001431 cur->properties = NULL;
1432 if (name[0] == '&') {
1433 int len;
1434 name++;
1435 len = xmlStrlen(name);
1436 if (name[len - 1] == ';')
1437 cur->name = xmlStrndup(name, len - 1);
1438 else
1439 cur->name = xmlStrndup(name, len);
1440 } else
1441 cur->name = xmlStrdup(name);
1442 cur->ns = NULL;
1443 cur->nsDef = NULL;
1444
1445 ent = xmlGetDocEntity(doc, cur->name);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001446 if (ent != NULL) {
1447#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardccb09631998-10-27 06:21:04 +00001448 cur->content = ent->content;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001449#else
1450 /*
1451 * CJN 11.18.99 this might be a problem, since the xmlBuffer gets
1452 * a copy of this pointer. Let's hope we don't manipulate it
1453 * later
1454 */
1455 cur->content = xmlBufferCreateSize(0);
1456 xmlBufferSetAllocationScheme(cur->content,
1457 xmlGetBufferAllocationScheme());
1458 if (ent->content != NULL)
1459 xmlBufferAdd(cur->content, ent->content, -1);
1460#endif
1461 } else
Daniel Veillardccb09631998-10-27 06:21:04 +00001462 cur->content = NULL;
Daniel Veillard00fdf371999-10-08 09:40:39 +00001463#ifndef XML_WITHOUT_CORBA
1464 cur->_private = NULL;
1465 cur->vepv = NULL;
1466#endif
Daniel Veillardccb09631998-10-27 06:21:04 +00001467 return(cur);
1468}
1469
1470/**
Daniel Veillard97b58771998-10-20 06:14:16 +00001471 * xmlNewDocText:
1472 * @doc: the document
1473 * @content: the text content
1474 *
1475 * Creation of a new text node within a document.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001476 * Returns a pointer to the new node object.
Daniel Veillard97b58771998-10-20 06:14:16 +00001477 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001478xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001479xmlNewDocText(xmlDocPtr doc, const xmlChar *content) {
Daniel Veillard0bef1311998-10-14 02:36:47 +00001480 xmlNodePtr cur;
1481
1482 cur = xmlNewText(content);
1483 if (cur != NULL) cur->doc = doc;
1484 return(cur);
1485}
1486
Daniel Veillard97b58771998-10-20 06:14:16 +00001487/**
Daniel Veillardccb09631998-10-27 06:21:04 +00001488 * xmlNewTextLen:
Daniel Veillard97b58771998-10-20 06:14:16 +00001489 * @content: the text content
1490 * @len: the text len.
1491 *
1492 * Creation of a new text node with an extra parameter for the content's lenght
Daniel Veillard1e346af1999-02-22 10:33:01 +00001493 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001494 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001495xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001496xmlNewTextLen(const xmlChar *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001497 xmlNodePtr cur;
1498
1499 /*
1500 * Allocate a new node and fill the fields.
1501 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001502 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillard260a68f1998-08-13 03:39:55 +00001503 if (cur == NULL) {
1504 fprintf(stderr, "xmlNewText : malloc failed\n");
1505 return(NULL);
1506 }
1507
Daniel Veillard33942841998-10-18 19:12:41 +00001508 cur->type = XML_TEXT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001509 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001510 cur->parent = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001511 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001512 cur->next = NULL;
1513 cur->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001514 cur->last = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001515 cur->properties = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001516 cur->type = XML_TEXT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001517 cur->name = xmlStrdup(xmlStringText);
1518 cur->ns = NULL;
1519 cur->nsDef = NULL;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001520 if (content != NULL) {
1521#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard260a68f1998-08-13 03:39:55 +00001522 cur->content = xmlStrndup(content, len);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001523#else
1524 cur->content = xmlBufferCreateSize(len);
1525 xmlBufferSetAllocationScheme(cur->content,
1526 xmlGetBufferAllocationScheme());
1527 xmlBufferAdd(cur->content, content, len);
1528#endif
1529 } else
Daniel Veillard260a68f1998-08-13 03:39:55 +00001530 cur->content = NULL;
Daniel Veillard00fdf371999-10-08 09:40:39 +00001531#ifndef XML_WITHOUT_CORBA
1532 cur->_private = NULL;
1533 cur->vepv = NULL;
1534#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001535 return(cur);
1536}
1537
Daniel Veillard97b58771998-10-20 06:14:16 +00001538/**
1539 * xmlNewDocTextLen:
1540 * @doc: the document
1541 * @content: the text content
1542 * @len: the text len.
1543 *
1544 * Creation of a new text node with an extra content lenght parameter. The
1545 * text node pertain to a given document.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001546 * Returns a pointer to the new node object.
Daniel Veillard97b58771998-10-20 06:14:16 +00001547 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001548xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001549xmlNewDocTextLen(xmlDocPtr doc, const xmlChar *content, int len) {
Daniel Veillard0bef1311998-10-14 02:36:47 +00001550 xmlNodePtr cur;
1551
1552 cur = xmlNewTextLen(content, len);
1553 if (cur != NULL) cur->doc = doc;
1554 return(cur);
1555}
1556
Daniel Veillard97b58771998-10-20 06:14:16 +00001557/**
1558 * xmlNewComment:
1559 * @content: the comment content
1560 *
1561 * Creation of a new node containing a comment.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001562 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001563 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001564xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001565xmlNewComment(const xmlChar *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001566 xmlNodePtr cur;
1567
1568 /*
1569 * Allocate a new node and fill the fields.
1570 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001571 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillard260a68f1998-08-13 03:39:55 +00001572 if (cur == NULL) {
1573 fprintf(stderr, "xmlNewComment : malloc failed\n");
1574 return(NULL);
1575 }
1576
Daniel Veillard33942841998-10-18 19:12:41 +00001577 cur->type = XML_COMMENT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001578 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001579 cur->parent = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001580 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001581 cur->next = NULL;
1582 cur->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001583 cur->last = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001584 cur->properties = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001585 cur->type = XML_COMMENT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001586 cur->name = xmlStrdup(xmlStringText);
1587 cur->ns = NULL;
1588 cur->nsDef = NULL;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001589 if (content != NULL) {
1590#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard260a68f1998-08-13 03:39:55 +00001591 cur->content = xmlStrdup(content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001592#else
1593 cur->content = xmlBufferCreateSize(0);
1594 xmlBufferSetAllocationScheme(cur->content,
1595 xmlGetBufferAllocationScheme());
1596 xmlBufferAdd(cur->content, content, -1);
1597#endif
1598 } else
Daniel Veillard260a68f1998-08-13 03:39:55 +00001599 cur->content = NULL;
Daniel Veillard00fdf371999-10-08 09:40:39 +00001600#ifndef XML_WITHOUT_CORBA
1601 cur->_private = NULL;
1602 cur->vepv = NULL;
1603#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001604 return(cur);
1605}
1606
Daniel Veillard97b58771998-10-20 06:14:16 +00001607/**
Daniel Veillardb05deb71999-08-10 19:04:08 +00001608 * xmlNewCDataBlock:
1609 * @doc: the document
1610 * @content: the CData block content content
1611 * @len: the length of the block
1612 *
1613 * Creation of a new node containing a CData block.
1614 * Returns a pointer to the new node object.
1615 */
1616xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001617xmlNewCDataBlock(xmlDocPtr doc, const xmlChar *content, int len) {
Daniel Veillardb05deb71999-08-10 19:04:08 +00001618 xmlNodePtr cur;
1619
1620 /*
1621 * Allocate a new node and fill the fields.
1622 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001623 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillardb05deb71999-08-10 19:04:08 +00001624 if (cur == NULL) {
1625 fprintf(stderr, "xmlNewCDataBlock : malloc failed\n");
1626 return(NULL);
1627 }
1628
1629 cur->type = XML_CDATA_SECTION_NODE;
1630 cur->doc = NULL;
1631 cur->parent = NULL;
1632 cur->prev = NULL;
1633 cur->next = NULL;
1634 cur->childs = NULL;
1635 cur->last = NULL;
1636 cur->properties = NULL;
1637 cur->name = xmlStrdup(xmlStringText);
1638 cur->ns = NULL;
1639 cur->nsDef = NULL;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001640 if (content != NULL) {
1641#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardb05deb71999-08-10 19:04:08 +00001642 cur->content = xmlStrndup(content, len);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001643#else
1644 cur->content = xmlBufferCreateSize(len);
1645 xmlBufferSetAllocationScheme(cur->content,
1646 xmlGetBufferAllocationScheme());
1647 xmlBufferAdd(cur->content, content, len);
1648#endif
Daniel Veillardb05deb71999-08-10 19:04:08 +00001649 } else
1650 cur->content = NULL;
Daniel Veillard00fdf371999-10-08 09:40:39 +00001651#ifndef XML_WITHOUT_CORBA
1652 cur->_private = NULL;
1653 cur->vepv = NULL;
1654#endif
Daniel Veillardb05deb71999-08-10 19:04:08 +00001655 return(cur);
1656}
1657
1658/**
Daniel Veillard1e346af1999-02-22 10:33:01 +00001659 * xmlNewDocComment:
Daniel Veillard97b58771998-10-20 06:14:16 +00001660 * @doc: the document
1661 * @content: the comment content
1662 *
1663 * Creation of a new node containing a commentwithin a document.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001664 * Returns a pointer to the new node object.
Daniel Veillard97b58771998-10-20 06:14:16 +00001665 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001666xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001667xmlNewDocComment(xmlDocPtr doc, const xmlChar *content) {
Daniel Veillard0bef1311998-10-14 02:36:47 +00001668 xmlNodePtr cur;
1669
1670 cur = xmlNewComment(content);
1671 if (cur != NULL) cur->doc = doc;
1672 return(cur);
1673}
1674
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001675
Daniel Veillard97b58771998-10-20 06:14:16 +00001676/**
1677 * xmlNewChild:
1678 * @parent: the parent node
1679 * @ns: a namespace if any
1680 * @name: the name of the child
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001681 * @content: the XML content of the child if any.
Daniel Veillard97b58771998-10-20 06:14:16 +00001682 *
Daniel Veillard97b58771998-10-20 06:14:16 +00001683 * Creation of a new child element, added at the end of @parent childs list.
Daniel Veillardccb09631998-10-27 06:21:04 +00001684 * @ns and @content parameters are optionnal (NULL). If content is non NULL,
1685 * a child list containing the TEXTs and ENTITY_REFs node will be created.
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001686 * NOTE: @content is supposed to be a piece of XML CDATA, so it allow entities
1687 * references, but XML special chars need to be escaped first by using
1688 * xmlEncodeEntitiesReentrant(). Use xmlNewTextChild() if entities
1689 * support is not needed.
1690 *
Daniel Veillard1e346af1999-02-22 10:33:01 +00001691 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001692 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001693xmlNodePtr
1694xmlNewChild(xmlNodePtr parent, xmlNsPtr ns,
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001695 const xmlChar *name, const xmlChar *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001696 xmlNodePtr cur, prev;
1697
1698 if (parent == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001699#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00001700 fprintf(stderr, "xmlNewChild : parent == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001701#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001702 return(NULL);
1703 }
1704
1705 if (name == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001706#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00001707 fprintf(stderr, "xmlNewChild : name == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001708#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001709 return(NULL);
1710 }
1711
1712 /*
1713 * Allocate a new node
1714 */
1715 if (ns == NULL)
Daniel Veillardccb09631998-10-27 06:21:04 +00001716 cur = xmlNewDocNode(parent->doc, parent->ns, name, content);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001717 else
Daniel Veillardccb09631998-10-27 06:21:04 +00001718 cur = xmlNewDocNode(parent->doc, ns, name, content);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001719 if (cur == NULL) return(NULL);
1720
1721 /*
1722 * add the new element at the end of the childs list.
1723 */
Daniel Veillardccb09631998-10-27 06:21:04 +00001724 cur->type = XML_ELEMENT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001725 cur->parent = parent;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001726 cur->doc = parent->doc;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001727 if (parent->childs == NULL) {
1728 parent->childs = cur;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001729 parent->last = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001730 } else {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001731 prev = parent->last;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001732 prev->next = cur;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001733 cur->prev = prev;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001734 parent->last = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001735 }
1736
1737 return(cur);
1738}
1739
Daniel Veillard97b58771998-10-20 06:14:16 +00001740/**
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00001741 * xmlAddNextSibling:
1742 * @cur: the child node
1743 * @elem: the new node
1744 *
1745 * Add a new element @elem as the next siblings of @cur
1746 * If the new element was already inserted in a document it is
1747 * first unlinked from its existing context.
1748 *
1749 * Returns the new element or NULL in case of error.
1750 */
1751xmlNodePtr
1752xmlAddNextSibling(xmlNodePtr cur, xmlNodePtr elem) {
1753 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001754#ifdef DEBUG_TREE
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00001755 fprintf(stderr, "xmlAddNextSibling : cur == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001756#endif
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00001757 return(NULL);
1758 }
1759 if (elem == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001760#ifdef DEBUG_TREE
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00001761 fprintf(stderr, "xmlAddNextSibling : elem == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001762#endif
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00001763 return(NULL);
1764 }
1765
1766 xmlUnlinkNode(elem);
1767 elem->doc = cur->doc;
1768 elem->parent = cur->parent;
1769 elem->next = cur;
1770 elem->prev = cur->prev;
1771 cur->prev = elem;
1772 if (elem->prev != NULL)
1773 elem->prev->next = elem;
1774 if ((elem->parent != NULL) && (elem->parent->childs == cur))
1775 elem->parent->childs = elem;
1776 return(elem);
1777}
1778
1779/**
1780 * xmlAddPrevSibling:
1781 * @cur: the child node
1782 * @elem: the new node
1783 *
1784 * Add a new element @elem as the previous siblings of @cur
1785 * If the new element was already inserted in a document it is
1786 * first unlinked from its existing context.
1787 *
1788 * Returns the new element or NULL in case of error.
1789 */
1790xmlNodePtr
1791xmlAddPrevSibling(xmlNodePtr cur, xmlNodePtr elem) {
1792 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001793#ifdef DEBUG_TREE
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00001794 fprintf(stderr, "xmlAddPrevSibling : cur == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001795#endif
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00001796 return(NULL);
1797 }
1798 if (elem == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001799#ifdef DEBUG_TREE
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00001800 fprintf(stderr, "xmlAddPrevSibling : elem == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001801#endif
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00001802 return(NULL);
1803 }
1804
1805 xmlUnlinkNode(elem);
1806 elem->doc = cur->doc;
1807 elem->parent = cur->parent;
1808 elem->prev = cur;
1809 elem->next = cur->next;
1810 cur->next = elem;
1811 if (elem->next != NULL)
1812 elem->next->prev = elem;
1813 if ((elem->parent != NULL) && (elem->parent->last == cur))
1814 elem->parent->last = elem;
1815 return(elem);
1816}
1817
1818/**
Daniel Veillardb96e6431999-08-29 21:02:19 +00001819 * xmlAddSibling:
1820 * @cur: the child node
1821 * @elem: the new node
1822 *
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00001823 * Add a new element @elem to the list of siblings of @cur
1824 * If the new element was already inserted in a document it is
1825 * first unlinked from its existing context.
1826 *
1827 * Returns the new element or NULL in case of error.
Daniel Veillardb96e6431999-08-29 21:02:19 +00001828 */
1829xmlNodePtr
1830xmlAddSibling(xmlNodePtr cur, xmlNodePtr elem) {
1831 xmlNodePtr parent;
1832
1833 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001834#ifdef DEBUG_TREE
Daniel Veillardb96e6431999-08-29 21:02:19 +00001835 fprintf(stderr, "xmlAddSibling : cur == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001836#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +00001837 return(NULL);
1838 }
1839
1840 if (elem == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001841#ifdef DEBUG_TREE
Daniel Veillardb96e6431999-08-29 21:02:19 +00001842 fprintf(stderr, "xmlAddSibling : elem == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001843#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +00001844 return(NULL);
1845 }
1846
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00001847 /*
1848 * Constant time is we can rely on the ->parent->last to find
1849 * the last sibling.
1850 */
1851 if ((cur->parent != NULL) &&
1852 (cur->parent->childs != NULL) &&
1853 (cur->parent->last != NULL) &&
1854 (cur->parent->last->next == NULL)) {
1855 cur = cur->parent->last;
1856 } else {
1857 while (cur->next != NULL) cur = cur->next;
Daniel Veillardb96e6431999-08-29 21:02:19 +00001858 }
1859
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00001860 xmlUnlinkNode(elem);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001861 if (elem->doc == NULL)
1862 elem->doc = cur->doc; /* the parent may not be linked to a doc ! */
1863
1864 parent = cur->parent;
1865 elem->prev = cur;
1866 elem->next = NULL;
1867 elem->parent = parent;
1868 cur->next = elem;
1869 if (parent != NULL)
1870 parent->last = elem;
1871
1872 return(elem);
1873}
1874
1875/**
Daniel Veillard97b58771998-10-20 06:14:16 +00001876 * xmlAddChild:
1877 * @parent: the parent node
1878 * @cur: the child node
1879 *
1880 * Add a new child element, to @parent, at the end of the child list.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001881 * Returns the child or NULL in case of error.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001882 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001883xmlNodePtr
1884xmlAddChild(xmlNodePtr parent, xmlNodePtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001885 xmlNodePtr prev;
1886
1887 if (parent == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001888#ifdef DEBUG_TREE
Daniel Veillard10a2c651999-12-12 13:03:50 +00001889 fprintf(stderr, "xmlAddChild : parent == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001890#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001891 return(NULL);
1892 }
1893
1894 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001895#ifdef DEBUG_TREE
Daniel Veillard10a2c651999-12-12 13:03:50 +00001896 fprintf(stderr, "xmlAddChild : child == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001897#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001898 return(NULL);
1899 }
1900
Daniel Veillard0bef1311998-10-14 02:36:47 +00001901 if ((cur->doc != NULL) && (parent->doc != NULL) &&
1902 (cur->doc != parent->doc)) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001903#ifdef DEBUG_TREE
Daniel Veillard0bef1311998-10-14 02:36:47 +00001904 fprintf(stderr, "Elements moved to a different document\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001905#endif
Daniel Veillard0bef1311998-10-14 02:36:47 +00001906 }
1907
Daniel Veillard260a68f1998-08-13 03:39:55 +00001908 /*
1909 * add the new element at the end of the childs list.
1910 */
1911 cur->parent = parent;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001912 cur->doc = parent->doc; /* the parent may not be linked to a doc ! */
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001913
Daniel Veillardccb09631998-10-27 06:21:04 +00001914 /*
1915 * Handle the case where parent->content != NULL, in that case it will
1916 * create a intermediate TEXT node.
1917 */
1918 if (parent->content != NULL) {
1919 xmlNodePtr text;
1920
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001921#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardccb09631998-10-27 06:21:04 +00001922 text = xmlNewDocText(parent->doc, parent->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001923#else
1924 text = xmlNewDocText(parent->doc, xmlBufferContent(parent->content));
1925#endif
Daniel Veillardccb09631998-10-27 06:21:04 +00001926 if (text != NULL) {
1927 text->next = parent->childs;
1928 if (text->next != NULL)
1929 text->next->prev = text;
1930 parent->childs = text;
Daniel Veillard1e346af1999-02-22 10:33:01 +00001931 UPDATE_LAST_CHILD(parent)
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001932#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard6454aec1999-09-02 22:04:43 +00001933 xmlFree(parent->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001934#else
1935 xmlBufferFree(parent->content);
1936#endif
Daniel Veillardccb09631998-10-27 06:21:04 +00001937 parent->content = NULL;
1938 }
1939 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00001940 if (parent->childs == NULL) {
1941 parent->childs = cur;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001942 parent->last = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001943 } else {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001944 prev = parent->last;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001945 prev->next = cur;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001946 cur->prev = prev;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001947 parent->last = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001948 }
1949
1950 return(cur);
1951}
1952
Daniel Veillard97b58771998-10-20 06:14:16 +00001953/**
1954 * xmlGetLastChild:
1955 * @parent: the parent node
1956 *
1957 * Search the last child of a node.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001958 * Returns the last child or NULL if none.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001959 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001960xmlNodePtr
1961xmlGetLastChild(xmlNodePtr parent) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001962 if (parent == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001963#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00001964 fprintf(stderr, "xmlGetLastChild : parent == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001965#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001966 return(NULL);
1967 }
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001968 return(parent->last);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001969}
1970
Daniel Veillard97b58771998-10-20 06:14:16 +00001971/**
1972 * xmlFreeNodeList:
1973 * @cur: the first node in the list
1974 *
1975 * Free a node and all its siblings, this is a recursive behaviour, all
1976 * the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001977 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001978void
1979xmlFreeNodeList(xmlNodePtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001980 xmlNodePtr next;
1981 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001982#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00001983 fprintf(stderr, "xmlFreeNodeList : node == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001984#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001985 return;
1986 }
1987 while (cur != NULL) {
1988 next = cur->next;
1989 xmlFreeNode(cur);
1990 cur = next;
1991 }
1992}
1993
Daniel Veillard97b58771998-10-20 06:14:16 +00001994/**
1995 * xmlFreeNode:
1996 * @cur: the node
1997 *
1998 * Free a node, this is a recursive behaviour, all the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001999 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002000void
2001xmlFreeNode(xmlNodePtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002002 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00002003#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00002004 fprintf(stderr, "xmlFreeNode : node == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00002005#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00002006 return;
2007 }
Daniel Veillardccb09631998-10-27 06:21:04 +00002008 cur->doc = NULL;
2009 cur->parent = NULL;
2010 cur->next = NULL;
2011 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002012 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillardccb09631998-10-27 06:21:04 +00002013 if (cur->properties != NULL) xmlFreePropList(cur->properties);
2014 if (cur->type != XML_ENTITY_REF_NODE)
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002015#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard6454aec1999-09-02 22:04:43 +00002016 if (cur->content != NULL) xmlFree(cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002017#else
2018 if (cur->content != NULL) xmlBufferFree(cur->content);
2019#endif
Daniel Veillard6454aec1999-09-02 22:04:43 +00002020 if (cur->name != NULL) xmlFree((char *) cur->name);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002021 if (cur->nsDef != NULL) xmlFreeNsList(cur->nsDef);
2022 memset(cur, -1, sizeof(xmlNode));
Daniel Veillard6454aec1999-09-02 22:04:43 +00002023 xmlFree(cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002024}
2025
Daniel Veillard16253641998-10-28 22:58:05 +00002026/**
2027 * xmlUnlinkNode:
2028 * @cur: the node
2029 *
2030 * Unlink a node from it's current context, the node is not freed
2031 */
2032void
2033xmlUnlinkNode(xmlNodePtr cur) {
2034 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00002035#ifdef DEBUG_TREE
Daniel Veillard16253641998-10-28 22:58:05 +00002036 fprintf(stderr, "xmlUnlinkNode : node == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00002037#endif
Daniel Veillard16253641998-10-28 22:58:05 +00002038 return;
2039 }
2040 if ((cur->parent != NULL) && (cur->parent->childs == cur))
2041 cur->parent->childs = cur->next;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002042 if ((cur->parent != NULL) && (cur->parent->last == cur))
2043 cur->parent->last = cur->prev;
Daniel Veillard16253641998-10-28 22:58:05 +00002044 if (cur->next != NULL)
2045 cur->next->prev = cur->prev;
2046 if (cur->prev != NULL)
2047 cur->prev->next = cur->next;
2048 cur->next = cur->prev = NULL;
2049 cur->parent = NULL;
2050}
2051
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00002052/**
2053 * xmlReplaceNode:
2054 * @old: the old node
2055 * @cur: the node
2056 *
2057 * Unlink the old node from it's current context, prune the new one
2058 * at the same place. If cur was already inserted in a document it is
2059 * first unlinked from its existing context.
2060 *
2061 * Returns the old node
2062 */
2063xmlNodePtr
2064xmlReplaceNode(xmlNodePtr old, xmlNodePtr cur) {
2065 if (old == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00002066#ifdef DEBUG_TREE
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00002067 fprintf(stderr, "xmlReplaceNode : old == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00002068#endif
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00002069 return(NULL);
2070 }
2071 if (cur == NULL) {
2072 xmlUnlinkNode(old);
2073 return(old);
2074 }
2075 xmlUnlinkNode(cur);
2076 cur->doc = old->doc;
2077 cur->parent = old->parent;
2078 cur->next = old->next;
2079 if (cur->next != NULL)
2080 cur->next->prev = cur;
2081 cur->prev = old->prev;
2082 if (cur->prev != NULL)
2083 cur->prev->next = cur;
2084 if (cur->parent != NULL) {
2085 if (cur->parent->childs == old)
2086 cur->parent->childs = cur;
2087 if (cur->parent->last == old)
2088 cur->parent->last = cur;
2089 }
2090 old->next = old->prev = NULL;
2091 old->parent = NULL;
2092 return(old);
2093}
2094
Daniel Veillard260a68f1998-08-13 03:39:55 +00002095/************************************************************************
2096 * *
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002097 * Copy operations *
2098 * *
2099 ************************************************************************/
2100
2101/**
2102 * xmlCopyNamespace:
2103 * @cur: the namespace
2104 *
2105 * Do a copy of the namespace.
2106 *
2107 * Returns: a new xmlNsPtr, or NULL in case of error.
2108 */
2109xmlNsPtr
2110xmlCopyNamespace(xmlNsPtr cur) {
2111 xmlNsPtr ret;
2112
2113 if (cur == NULL) return(NULL);
2114 switch (cur->type) {
2115 case XML_GLOBAL_NAMESPACE:
2116 ret = xmlNewGlobalNs(NULL, cur->href, cur->prefix);
2117 break;
2118 case XML_LOCAL_NAMESPACE:
2119 ret = xmlNewNs(NULL, cur->href, cur->prefix);
2120 break;
2121 default:
Daniel Veillardad8f99d2000-01-15 14:20:03 +00002122#ifdef DEBUG_TREE
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002123 fprintf(stderr, "xmlCopyNamespace: unknown type %d\n", cur->type);
Daniel Veillardad8f99d2000-01-15 14:20:03 +00002124#endif
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002125 return(NULL);
2126 }
2127 return(ret);
2128}
2129
2130/**
2131 * xmlCopyNamespaceList:
2132 * @cur: the first namespace
2133 *
2134 * Do a copy of an namespace list.
2135 *
2136 * Returns: a new xmlNsPtr, or NULL in case of error.
2137 */
2138xmlNsPtr
2139xmlCopyNamespaceList(xmlNsPtr cur) {
2140 xmlNsPtr ret = NULL;
2141 xmlNsPtr p = NULL,q;
2142
2143 while (cur != NULL) {
2144 q = xmlCopyNamespace(cur);
2145 if (p == NULL) {
2146 ret = p = q;
2147 } else {
2148 p->next = q;
2149 p = q;
2150 }
2151 cur = cur->next;
2152 }
2153 return(ret);
2154}
2155
2156/**
2157 * xmlCopyProp:
Daniel Veillardb96e6431999-08-29 21:02:19 +00002158 * @target: the element where the attribute will be grafted
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002159 * @cur: the attribute
2160 *
2161 * Do a copy of the attribute.
2162 *
2163 * Returns: a new xmlAttrPtr, or NULL in case of error.
2164 */
2165xmlAttrPtr
Daniel Veillardb96e6431999-08-29 21:02:19 +00002166xmlCopyProp(xmlNodePtr target, xmlAttrPtr cur) {
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002167 xmlAttrPtr ret;
2168
2169 if (cur == NULL) return(NULL);
2170 if (cur->val != NULL)
2171 ret = xmlNewDocProp(cur->val->doc, cur->name, NULL);
2172 else
2173 ret = xmlNewDocProp(NULL, cur->name, NULL);
2174 if (ret == NULL) return(NULL);
Daniel Veillardb96e6431999-08-29 21:02:19 +00002175
2176 if ((cur->ns != NULL) && (target != NULL)) {
2177 xmlNsPtr ns;
2178
2179 ns = xmlSearchNs(target->doc, target, cur->ns->prefix);
2180 ret->ns = ns;
2181 } else
2182 ret->ns = NULL;
2183
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002184 if (cur->val != NULL)
2185 ret->val = xmlCopyNodeList(cur->val);
2186 return(ret);
2187}
2188
2189/**
2190 * xmlCopyPropList:
Daniel Veillardb96e6431999-08-29 21:02:19 +00002191 * @target: the element where the attributes will be grafted
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002192 * @cur: the first attribute
2193 *
2194 * Do a copy of an attribute list.
2195 *
2196 * Returns: a new xmlAttrPtr, or NULL in case of error.
2197 */
2198xmlAttrPtr
Daniel Veillardb96e6431999-08-29 21:02:19 +00002199xmlCopyPropList(xmlNodePtr target, xmlAttrPtr cur) {
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002200 xmlAttrPtr ret = NULL;
2201 xmlAttrPtr p = NULL,q;
2202
2203 while (cur != NULL) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00002204 q = xmlCopyProp(target, cur);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002205 if (p == NULL) {
2206 ret = p = q;
2207 } else {
2208 p->next = q;
2209 p = q;
2210 }
2211 cur = cur->next;
2212 }
2213 return(ret);
2214}
2215
2216/*
Daniel Veillard11a48ec1999-11-23 10:40:46 +00002217 * NOTE abeut the CopyNode operations !
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002218 *
2219 * They are splitted into external and internal parts for one
2220 * tricky reason: namespaces. Doing a direct copy of a node
2221 * say RPM:Copyright without changing the namespace pointer to
2222 * something else can produce stale links. One way to do it is
2223 * to keep a reference counter but this doesn't work as soon
2224 * as one move the element or the subtree out of the scope of
2225 * the existing namespace. The actual solution seems to add
2226 * a copy of the namespace at the top of the copied tree if
2227 * not available in the subtree.
2228 * Hence two functions, the public front-end call the inner ones
2229 */
2230
2231static xmlNodePtr
2232xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent);
2233
2234static xmlNodePtr
2235xmlStaticCopyNode(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent,
2236 int recursive) {
2237 xmlNodePtr ret;
2238
2239 if (node == NULL) return(NULL);
2240 /*
2241 * Allocate a new node and fill the fields.
2242 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00002243 ret = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002244 if (ret == NULL) {
2245 fprintf(stderr, "xmlStaticCopyNode : malloc failed\n");
2246 return(NULL);
2247 }
2248
2249 ret->type = node->type;
2250 ret->doc = doc;
2251 ret->parent = parent;
2252 ret->next = NULL;
2253 ret->prev = NULL;
2254 ret->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002255 ret->last = NULL;
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002256 ret->properties = NULL;
2257 if (node->name != NULL)
2258 ret->name = xmlStrdup(node->name);
2259 else
2260 ret->name = NULL;
2261 ret->ns = NULL;
2262 ret->nsDef = NULL;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002263 if ((node->content != NULL) && (node->type != XML_ENTITY_REF_NODE)) {
2264#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002265 ret->content = xmlStrdup(node->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002266#else
2267 ret->content = xmlBufferCreateSize(xmlBufferLength(node->content));
2268 xmlBufferSetAllocationScheme(ret->content,
2269 xmlGetBufferAllocationScheme());
2270 xmlBufferAdd(ret->content,
2271 xmlBufferContent(node->content),
2272 xmlBufferLength(node->content));
2273#endif
2274 } else
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002275 ret->content = NULL;
Daniel Veillard27d88741999-05-29 11:51:49 +00002276#ifndef XML_WITHOUT_CORBA
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002277 ret->_private = NULL;
2278 ret->vepv = NULL;
2279#endif
2280 if (parent != NULL)
2281 xmlAddChild(parent, ret);
2282
2283 if (!recursive) return(ret);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002284 if (node->nsDef != NULL)
2285 ret->nsDef = xmlCopyNamespaceList(node->nsDef);
2286
2287 if (node->ns != NULL) {
2288 xmlNsPtr ns;
2289
2290 ns = xmlSearchNs(doc, ret, node->ns->prefix);
2291 if (ns == NULL) {
2292 /*
2293 * Humm, we are copying an element whose namespace is defined
2294 * out of the new tree scope. Search it in the original tree
2295 * and add it at the top of the new tree
2296 */
2297 ns = xmlSearchNs(node->doc, node, node->ns->prefix);
2298 if (ns != NULL) {
2299 xmlNodePtr root = ret;
2300
2301 while (root->parent != NULL) root = root->parent;
2302 xmlNewNs(root, ns->href, ns->prefix);
2303 }
2304 } else {
2305 /*
2306 * reference the existing namespace definition in our own tree.
2307 */
2308 ret->ns = ns;
2309 }
2310 }
Daniel Veillardb96e6431999-08-29 21:02:19 +00002311 if (node->properties != NULL)
2312 ret->properties = xmlCopyPropList(ret, node->properties);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002313 if (node->childs != NULL)
2314 ret->childs = xmlStaticCopyNodeList(node->childs, doc, ret);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002315 UPDATE_LAST_CHILD(ret)
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002316 return(ret);
2317}
2318
2319static xmlNodePtr
2320xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent) {
2321 xmlNodePtr ret = NULL;
2322 xmlNodePtr p = NULL,q;
2323
2324 while (node != NULL) {
2325 q = xmlStaticCopyNode(node, doc, parent, 1);
2326 if (parent == NULL) {
2327 if (ret == NULL) ret = q;
2328 } else {
2329 if (ret == NULL) {
2330 q->prev = NULL;
2331 ret = p = q;
2332 } else {
2333 p->next = q;
2334 q->prev = p;
2335 p = q;
2336 }
2337 }
2338 node = node->next;
2339 }
2340 return(ret);
2341}
2342
2343/**
2344 * xmlCopyNode:
2345 * @node: the node
2346 * @recursive: if 1 do a recursive copy.
2347 *
2348 * Do a copy of the node.
2349 *
2350 * Returns: a new xmlNodePtr, or NULL in case of error.
2351 */
2352xmlNodePtr
2353xmlCopyNode(xmlNodePtr node, int recursive) {
2354 xmlNodePtr ret;
2355
2356 ret = xmlStaticCopyNode(node, NULL, NULL, recursive);
2357 return(ret);
2358}
2359
2360/**
2361 * xmlCopyNodeList:
2362 * @node: the first node in the list.
2363 *
2364 * Do a recursive copy of the node list.
2365 *
2366 * Returns: a new xmlNodePtr, or NULL in case of error.
2367 */
2368xmlNodePtr xmlCopyNodeList(xmlNodePtr node) {
2369 xmlNodePtr ret = xmlStaticCopyNodeList(node, NULL, NULL);
2370 return(ret);
2371}
2372
2373/**
2374 * xmlCopyElement:
2375 * @elem: the element
2376 *
2377 * Do a copy of the element definition.
2378 *
2379 * Returns: a new xmlElementPtr, or NULL in case of error.
2380xmlElementPtr
2381xmlCopyElement(xmlElementPtr elem) {
2382 xmlElementPtr ret;
2383
2384 if (elem == NULL) return(NULL);
2385 ret = xmlNewDocElement(elem->doc, elem->ns, elem->name, elem->content);
2386 if (ret == NULL) return(NULL);
2387 if (!recursive) return(ret);
2388 if (elem->properties != NULL)
2389 ret->properties = xmlCopyPropList(elem->properties);
2390
2391 if (elem->nsDef != NULL)
2392 ret->nsDef = xmlCopyNamespaceList(elem->nsDef);
2393 if (elem->childs != NULL)
2394 ret->childs = xmlCopyElementList(elem->childs);
2395 return(ret);
2396}
2397 */
2398
2399/**
2400 * xmlCopyDtd:
2401 * @dtd: the dtd
2402 *
2403 * Do a copy of the dtd.
2404 *
2405 * Returns: a new xmlDtdPtr, or NULL in case of error.
2406 */
2407xmlDtdPtr
2408xmlCopyDtd(xmlDtdPtr dtd) {
2409 xmlDtdPtr ret;
2410
2411 if (dtd == NULL) return(NULL);
2412 ret = xmlNewDtd(NULL, dtd->name, dtd->ExternalID, dtd->SystemID);
2413 if (ret == NULL) return(NULL);
2414 if (dtd->entities != NULL)
2415 ret->entities = (void *) xmlCopyEntitiesTable(
2416 (xmlEntitiesTablePtr) dtd->entities);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002417 if (dtd->notations != NULL)
2418 ret->notations = (void *) xmlCopyNotationTable(
2419 (xmlNotationTablePtr) dtd->notations);
2420 if (dtd->elements != NULL)
2421 ret->elements = (void *) xmlCopyElementTable(
2422 (xmlElementTablePtr) dtd->elements);
2423 if (dtd->attributes != NULL)
2424 ret->attributes = (void *) xmlCopyAttributeTable(
2425 (xmlAttributeTablePtr) dtd->attributes);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002426 return(ret);
2427}
2428
2429/**
2430 * xmlCopyDoc:
2431 * @doc: the document
2432 * @recursive: if 1 do a recursive copy.
2433 *
2434 * Do a copy of the document info. If recursive, the content tree will
2435 * be copied too as well as Dtd, namespaces and entities.
2436 *
2437 * Returns: a new xmlDocPtr, or NULL in case of error.
2438 */
2439xmlDocPtr
2440xmlCopyDoc(xmlDocPtr doc, int recursive) {
2441 xmlDocPtr ret;
2442
2443 if (doc == NULL) return(NULL);
2444 ret = xmlNewDoc(doc->version);
2445 if (ret == NULL) return(NULL);
2446 if (doc->name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +00002447 ret->name = xmlMemStrdup(doc->name);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002448 if (doc->encoding != NULL)
2449 ret->encoding = xmlStrdup(doc->encoding);
2450 ret->compression = doc->compression;
2451 ret->standalone = doc->standalone;
2452 if (!recursive) return(ret);
2453
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002454 if (doc->intSubset != NULL)
2455 ret->intSubset = xmlCopyDtd(doc->intSubset);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002456 if (doc->oldNs != NULL)
2457 ret->oldNs = xmlCopyNamespaceList(doc->oldNs);
2458 if (doc->root != NULL)
2459 ret->root = xmlStaticCopyNodeList(doc->root, ret, NULL);
2460 return(ret);
2461}
2462
2463/************************************************************************
2464 * *
Daniel Veillard260a68f1998-08-13 03:39:55 +00002465 * Content access functions *
2466 * *
2467 ************************************************************************/
2468
Daniel Veillard97b58771998-10-20 06:14:16 +00002469/**
Daniel Veillard944b5ff1999-12-15 19:08:24 +00002470 * xmlDocGetRootElement:
2471 * @doc: the document
2472 *
2473 * Get the root element of the document (doc->root is a list
2474 * containing possibly comments, PIs, etc ...).
2475 *
2476 * Returns the xmlNodePtr for the root or NULL
2477 */
2478xmlNodePtr
2479xmlDocGetRootElement(xmlDocPtr doc) {
2480 xmlNodePtr ret;
2481
2482 if (doc == NULL) return(NULL);
2483 ret = doc->root;
2484 while (ret != NULL) {
2485 if (ret->type == XML_ELEMENT_NODE)
2486 return(ret);
2487 ret = ret->next;
2488 }
2489 return(ret);
2490}
2491
2492/**
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00002493 * xmlDocSetRootElement:
2494 * @doc: the document
2495 * @root: the new document root element
2496 *
2497 * Set the root element of the document (doc->root is a list
2498 * containing possibly comments, PIs, etc ...).
2499 *
2500 * Returns the old root element if any was found
2501 */
2502xmlNodePtr
2503xmlDocSetRootElement(xmlDocPtr doc, xmlNodePtr root) {
2504 xmlNodePtr old = NULL;
2505
2506 if (doc == NULL) return(NULL);
2507 old = doc->root;
2508 while (old != NULL) {
2509 if (old->type == XML_ELEMENT_NODE)
2510 break;
2511 old = old->next;
2512 }
2513 if (old == NULL) {
2514 if (doc->root == NULL) {
2515 doc->root = root;
2516 } else {
2517 xmlAddSibling(doc->root, root);
2518 }
2519 } else {
2520 xmlReplaceNode(old, root);
2521 }
2522 return(old);
2523}
2524
2525/**
Daniel Veillardb96e6431999-08-29 21:02:19 +00002526 * xmlNodeSetLang:
2527 * @cur: the node being changed
2528 * @lang: the langage description
2529 *
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00002530 * Set the language of a node, i.e. the values of the xml:lang
2531 * attribute.
Daniel Veillardb96e6431999-08-29 21:02:19 +00002532 */
2533void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002534xmlNodeSetLang(xmlNodePtr cur, const xmlChar *lang) {
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00002535 if (cur == NULL) return;
2536 switch(cur->type) {
2537 case XML_TEXT_NODE:
2538 case XML_CDATA_SECTION_NODE:
2539 case XML_COMMENT_NODE:
2540 case XML_DOCUMENT_NODE:
2541 case XML_DOCUMENT_TYPE_NODE:
2542 case XML_DOCUMENT_FRAG_NODE:
2543 case XML_NOTATION_NODE:
2544 case XML_HTML_DOCUMENT_NODE:
2545 return;
2546 case XML_ELEMENT_NODE:
2547 case XML_ATTRIBUTE_NODE:
2548 case XML_PI_NODE:
2549 case XML_ENTITY_REF_NODE:
2550 case XML_ENTITY_NODE:
2551 break;
2552 }
Daniel Veillardb96e6431999-08-29 21:02:19 +00002553 xmlSetProp(cur, BAD_CAST "xml:lang", lang);
2554}
2555
2556/**
2557 * xmlNodeGetLang:
2558 * @cur: the node being checked
2559 *
2560 * Searches the language of a node, i.e. the values of the xml:lang
2561 * attribute or the one carried by the nearest ancestor.
2562 *
2563 * Returns a pointer to the lang value, or NULL if not found
Daniel Veillarda819dac1999-11-24 18:04:22 +00002564 * It's up to the caller to free the memory.
Daniel Veillardb96e6431999-08-29 21:02:19 +00002565 */
Daniel Veillarda819dac1999-11-24 18:04:22 +00002566xmlChar *
Daniel Veillardb96e6431999-08-29 21:02:19 +00002567xmlNodeGetLang(xmlNodePtr cur) {
Daniel Veillarda819dac1999-11-24 18:04:22 +00002568 xmlChar *lang;
Daniel Veillardb96e6431999-08-29 21:02:19 +00002569
2570 while (cur != NULL) {
2571 lang = xmlGetProp(cur, BAD_CAST "xml:lang");
2572 if (lang != NULL)
2573 return(lang);
2574 cur = cur->parent;
2575 }
2576 return(NULL);
2577}
2578
2579/**
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00002580 * xmlNodeSetName:
2581 * @cur: the node being changed
2582 * @name: the new tag name
2583 *
2584 * Searches the language of a node, i.e. the values of the xml:lang
2585 * attribute or the one carried by the nearest ancestor.
2586 */
2587void
2588xmlNodeSetName(xmlNodePtr cur, const xmlChar *name) {
2589 if (cur == NULL) return;
2590 if (name == NULL) return;
2591 switch(cur->type) {
2592 case XML_TEXT_NODE:
2593 case XML_CDATA_SECTION_NODE:
2594 case XML_COMMENT_NODE:
2595 case XML_DOCUMENT_NODE:
2596 case XML_DOCUMENT_TYPE_NODE:
2597 case XML_DOCUMENT_FRAG_NODE:
2598 case XML_NOTATION_NODE:
2599 case XML_HTML_DOCUMENT_NODE:
2600 return;
2601 case XML_ELEMENT_NODE:
2602 case XML_ATTRIBUTE_NODE:
2603 case XML_PI_NODE:
2604 case XML_ENTITY_REF_NODE:
2605 case XML_ENTITY_NODE:
2606 break;
2607 }
2608 if (cur->name != NULL) xmlFree((xmlChar *) cur->name);
2609 cur->name = xmlStrdup(name);
2610}
2611
2612/**
Daniel Veillard10a2c651999-12-12 13:03:50 +00002613 * xmlNodeGetBase:
2614 * @doc: the document the node pertains to
2615 * @cur: the node being checked
2616 *
2617 * Searches for the BASE URL. The code should work on both XML
2618 * and HTML document even if base mechanisms are completely different.
2619 *
2620 * Returns a pointer to the base URL, or NULL if not found
2621 * It's up to the caller to free the memory.
2622 */
2623xmlChar *
2624xmlNodeGetBase(xmlDocPtr doc, xmlNodePtr cur) {
2625 xmlChar *base;
2626
2627 if ((cur == NULL) && (doc == NULL))
2628 return(NULL);
2629 if (doc == NULL) doc = cur->doc;
2630 if ((doc != NULL) && (doc->type == XML_HTML_DOCUMENT_NODE)) {
2631 cur = doc->root;
2632 while ((cur != NULL) && (cur->name != NULL)) {
2633 if (cur->type != XML_ELEMENT_NODE) {
2634 cur = cur->next;
2635 continue;
2636 }
2637 if ((!xmlStrcmp(cur->name, BAD_CAST "html")) ||
2638 (!xmlStrcmp(cur->name, BAD_CAST "HTML"))) {
2639 cur = cur->childs;
2640 continue;
2641 }
2642 if ((!xmlStrcmp(cur->name, BAD_CAST "head")) ||
2643 (!xmlStrcmp(cur->name, BAD_CAST "HEAD"))) {
2644 cur = cur->childs;
2645 continue;
2646 }
2647 if ((!xmlStrcmp(cur->name, BAD_CAST "base")) ||
2648 (!xmlStrcmp(cur->name, BAD_CAST "BASE"))) {
2649 base = xmlGetProp(cur, BAD_CAST "href");
2650 if (base != NULL) return(base);
2651 return(xmlGetProp(cur, BAD_CAST "HREF"));
2652 }
2653 }
2654 return(NULL);
2655 }
2656 while (cur != NULL) {
2657 base = xmlGetProp(cur, BAD_CAST "xml:base");
2658 if (base != NULL)
2659 return(base);
2660 cur = cur->parent;
2661 }
2662 return(NULL);
2663}
2664
2665/**
Daniel Veillard16253641998-10-28 22:58:05 +00002666 * xmlNodeGetContent:
2667 * @cur: the node being read
2668 *
2669 * Read the value of a node, this can be either the text carried
2670 * directly by this node if it's a TEXT node or the aggregate string
2671 * of the values carried by this node child's (TEXT and ENTITY_REF).
2672 * Entity references are substitued.
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002673 * Returns a new xmlChar * or NULL if no content is available.
Daniel Veillard5099ae81999-04-21 20:12:07 +00002674 * It's up to the caller to free the memory.
Daniel Veillard16253641998-10-28 22:58:05 +00002675 */
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002676xmlChar *
Daniel Veillard16253641998-10-28 22:58:05 +00002677xmlNodeGetContent(xmlNodePtr cur) {
2678 if (cur == NULL) return(NULL);
2679 switch (cur->type) {
2680 case XML_DOCUMENT_FRAG_NODE:
2681 case XML_ELEMENT_NODE:
2682 return(xmlNodeListGetString(cur->doc, cur->childs, 1));
2683 break;
Daniel Veillardb96e6431999-08-29 21:02:19 +00002684 case XML_ATTRIBUTE_NODE: {
2685 xmlAttrPtr attr = (xmlAttrPtr) cur;
2686 if (attr->node != NULL)
2687 return(xmlNodeListGetString(attr->node->doc, attr->val, 1));
2688 else
2689 return(xmlNodeListGetString(NULL, attr->val, 1));
2690 break;
2691 }
Daniel Veillarddbfd6411999-12-28 16:35:14 +00002692 case XML_COMMENT_NODE:
Daniel Veillardb96e6431999-08-29 21:02:19 +00002693 case XML_PI_NODE:
2694 if (cur->content != NULL)
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002695#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardb96e6431999-08-29 21:02:19 +00002696 return(xmlStrdup(cur->content));
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002697#else
2698 return(xmlStrdup(xmlBufferContent(cur->content)));
2699#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +00002700 return(NULL);
Daniel Veillard16253641998-10-28 22:58:05 +00002701 case XML_ENTITY_REF_NODE:
Daniel Veillarddbfd6411999-12-28 16:35:14 +00002702 /*
2703 * Locate the entity, and get it's content
2704 * @@@
2705 */
2706 return(NULL);
Daniel Veillard16253641998-10-28 22:58:05 +00002707 case XML_ENTITY_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002708 case XML_DOCUMENT_NODE:
Daniel Veillard7c1206f1999-10-14 09:10:25 +00002709 case XML_HTML_DOCUMENT_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002710 case XML_DOCUMENT_TYPE_NODE:
2711 case XML_NOTATION_NODE:
2712 return(NULL);
Daniel Veillardb05deb71999-08-10 19:04:08 +00002713 case XML_CDATA_SECTION_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002714 case XML_TEXT_NODE:
2715 if (cur->content != NULL)
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002716#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard16253641998-10-28 22:58:05 +00002717 return(xmlStrdup(cur->content));
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002718#else
2719 return(xmlStrdup(xmlBufferContent(cur->content)));
2720#endif
Daniel Veillard16253641998-10-28 22:58:05 +00002721 return(NULL);
2722 }
2723 return(NULL);
2724}
2725
2726/**
Daniel Veillard97b58771998-10-20 06:14:16 +00002727 * xmlNodeSetContent:
2728 * @cur: the node being modified
2729 * @content: the new value of the content
2730 *
2731 * Replace the content of a node.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002732 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002733void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002734xmlNodeSetContent(xmlNodePtr cur, const xmlChar *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002735 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00002736#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00002737 fprintf(stderr, "xmlNodeSetContent : node == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00002738#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00002739 return;
2740 }
Daniel Veillard16253641998-10-28 22:58:05 +00002741 switch (cur->type) {
2742 case XML_DOCUMENT_FRAG_NODE:
2743 case XML_ELEMENT_NODE:
2744 if (cur->content != NULL) {
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002745#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard6454aec1999-09-02 22:04:43 +00002746 xmlFree(cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002747#else
2748 xmlBufferFree(cur->content);
2749#endif
Daniel Veillard16253641998-10-28 22:58:05 +00002750 cur->content = NULL;
2751 }
Daniel Veillard6454aec1999-09-02 22:04:43 +00002752 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillard16253641998-10-28 22:58:05 +00002753 cur->childs = xmlStringGetNodeList(cur->doc, content);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002754 UPDATE_LAST_CHILD(cur)
Daniel Veillard16253641998-10-28 22:58:05 +00002755 break;
2756 case XML_ATTRIBUTE_NODE:
2757 break;
2758 case XML_TEXT_NODE:
2759 case XML_CDATA_SECTION_NODE:
2760 case XML_ENTITY_REF_NODE:
2761 case XML_ENTITY_NODE:
2762 case XML_PI_NODE:
2763 case XML_COMMENT_NODE:
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002764 if (cur->content != NULL) {
2765#ifndef XML_USE_BUFFER_CONTENT
2766 xmlFree(cur->content);
2767#else
2768 xmlBufferFree(cur->content);
2769#endif
2770 }
Daniel Veillard6454aec1999-09-02 22:04:43 +00002771 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002772 cur->last = cur->childs = NULL;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002773 if (content != NULL) {
2774#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard16253641998-10-28 22:58:05 +00002775 cur->content = xmlStrdup(content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002776#else
2777 cur->content = xmlBufferCreateSize(0);
2778 xmlBufferSetAllocationScheme(cur->content,
2779 xmlGetBufferAllocationScheme());
2780 xmlBufferAdd(cur->content, content, -1);
2781#endif
2782 } else
Daniel Veillard16253641998-10-28 22:58:05 +00002783 cur->content = NULL;
Daniel Veillardb96e6431999-08-29 21:02:19 +00002784 break;
Daniel Veillard16253641998-10-28 22:58:05 +00002785 case XML_DOCUMENT_NODE:
Daniel Veillard7c1206f1999-10-14 09:10:25 +00002786 case XML_HTML_DOCUMENT_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002787 case XML_DOCUMENT_TYPE_NODE:
2788 break;
2789 case XML_NOTATION_NODE:
2790 break;
2791 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002792}
2793
Daniel Veillard97b58771998-10-20 06:14:16 +00002794/**
2795 * xmlNodeSetContentLen:
2796 * @cur: the node being modified
2797 * @content: the new value of the content
2798 * @len: the size of @content
2799 *
2800 * Replace the content of a node.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002801 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002802void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002803xmlNodeSetContentLen(xmlNodePtr cur, const xmlChar *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002804 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00002805#ifdef DEBUG_TREE
Daniel Veillard16253641998-10-28 22:58:05 +00002806 fprintf(stderr, "xmlNodeSetContentLen : node == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00002807#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00002808 return;
2809 }
Daniel Veillard16253641998-10-28 22:58:05 +00002810 switch (cur->type) {
2811 case XML_DOCUMENT_FRAG_NODE:
2812 case XML_ELEMENT_NODE:
2813 if (cur->content != NULL) {
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002814#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard6454aec1999-09-02 22:04:43 +00002815 xmlFree(cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002816#else
2817 xmlBufferFree(cur->content);
2818#endif
Daniel Veillard16253641998-10-28 22:58:05 +00002819 cur->content = NULL;
2820 }
Daniel Veillard6454aec1999-09-02 22:04:43 +00002821 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillard16253641998-10-28 22:58:05 +00002822 cur->childs = xmlStringLenGetNodeList(cur->doc, content, len);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002823 UPDATE_LAST_CHILD(cur)
Daniel Veillard16253641998-10-28 22:58:05 +00002824 break;
2825 case XML_ATTRIBUTE_NODE:
2826 break;
2827 case XML_TEXT_NODE:
2828 case XML_CDATA_SECTION_NODE:
2829 case XML_ENTITY_REF_NODE:
2830 case XML_ENTITY_NODE:
2831 case XML_PI_NODE:
2832 case XML_COMMENT_NODE:
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002833 case XML_NOTATION_NODE:
2834 if (cur->content != NULL) {
2835#ifndef XML_USE_BUFFER_CONTENT
2836 xmlFree(cur->content);
2837#else
2838 xmlBufferFree(cur->content);
2839#endif
2840 }
Daniel Veillard6454aec1999-09-02 22:04:43 +00002841 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002842 cur->childs = cur->last = NULL;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002843 if (content != NULL) {
2844#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard16253641998-10-28 22:58:05 +00002845 cur->content = xmlStrndup(content, len);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002846#else
2847 cur->content = xmlBufferCreateSize(len);
2848 xmlBufferSetAllocationScheme(cur->content,
2849 xmlGetBufferAllocationScheme());
2850 xmlBufferAdd(cur->content, content, len);
2851#endif
2852 } else
Daniel Veillard16253641998-10-28 22:58:05 +00002853 cur->content = NULL;
Daniel Veillardb96e6431999-08-29 21:02:19 +00002854 break;
Daniel Veillard16253641998-10-28 22:58:05 +00002855 case XML_DOCUMENT_NODE:
Daniel Veillard7c1206f1999-10-14 09:10:25 +00002856 case XML_HTML_DOCUMENT_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002857 case XML_DOCUMENT_TYPE_NODE:
2858 break;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002859 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002860}
2861
Daniel Veillard97b58771998-10-20 06:14:16 +00002862/**
2863 * xmlNodeAddContentLen:
2864 * @cur: the node being modified
2865 * @content: extra content
2866 * @len: the size of @content
2867 *
2868 * Append the extra substring to the node content.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002869 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002870void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002871xmlNodeAddContentLen(xmlNodePtr cur, const xmlChar *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002872 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00002873#ifdef DEBUG_TREE
Daniel Veillard16253641998-10-28 22:58:05 +00002874 fprintf(stderr, "xmlNodeAddContentLen : node == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00002875#endif
Daniel Veillard16253641998-10-28 22:58:05 +00002876 return;
2877 }
2878 if (len <= 0) return;
2879 switch (cur->type) {
2880 case XML_DOCUMENT_FRAG_NODE:
2881 case XML_ELEMENT_NODE: {
2882 xmlNodePtr last = NULL, new;
2883
2884 if (cur->childs != NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002885 last = cur->last;
Daniel Veillard16253641998-10-28 22:58:05 +00002886 } else {
2887 if (cur->content != NULL) {
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002888#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard16253641998-10-28 22:58:05 +00002889 cur->childs = xmlStringGetNodeList(cur->doc, cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002890#else
2891 cur->childs = xmlStringGetNodeList(cur->doc,
2892 xmlBufferContent(cur->content));
2893#endif
Daniel Veillard1e346af1999-02-22 10:33:01 +00002894 UPDATE_LAST_CHILD(cur)
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002895#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard6454aec1999-09-02 22:04:43 +00002896 xmlFree(cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002897#else
2898 xmlBufferFree(cur->content);
2899#endif
Daniel Veillard16253641998-10-28 22:58:05 +00002900 cur->content = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002901 last = cur->last;
Daniel Veillard16253641998-10-28 22:58:05 +00002902 }
2903 }
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002904 new = xmlNewTextLen(content, len);
Daniel Veillard16253641998-10-28 22:58:05 +00002905 if (new != NULL) {
2906 xmlAddChild(cur, new);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002907 if ((last != NULL) && (last->next == new)) {
Daniel Veillard16253641998-10-28 22:58:05 +00002908 xmlTextMerge(last, new);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002909 }
Daniel Veillard16253641998-10-28 22:58:05 +00002910 }
2911 break;
2912 }
2913 case XML_ATTRIBUTE_NODE:
2914 break;
2915 case XML_TEXT_NODE:
2916 case XML_CDATA_SECTION_NODE:
2917 case XML_ENTITY_REF_NODE:
2918 case XML_ENTITY_NODE:
2919 case XML_PI_NODE:
2920 case XML_COMMENT_NODE:
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002921 case XML_NOTATION_NODE:
2922 if (content != NULL) {
2923#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard16253641998-10-28 22:58:05 +00002924 cur->content = xmlStrncat(cur->content, content, len);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002925#else
2926 xmlBufferAdd(cur->content, content, len);
2927#endif
2928 }
Daniel Veillard16253641998-10-28 22:58:05 +00002929 case XML_DOCUMENT_NODE:
Daniel Veillard7c1206f1999-10-14 09:10:25 +00002930 case XML_HTML_DOCUMENT_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002931 case XML_DOCUMENT_TYPE_NODE:
2932 break;
Daniel Veillard16253641998-10-28 22:58:05 +00002933 }
2934}
2935
2936/**
2937 * xmlNodeAddContent:
2938 * @cur: the node being modified
2939 * @content: extra content
2940 *
2941 * Append the extra substring to the node content.
2942 */
2943void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002944xmlNodeAddContent(xmlNodePtr cur, const xmlChar *content) {
Daniel Veillard16253641998-10-28 22:58:05 +00002945 int len;
2946
2947 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00002948#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00002949 fprintf(stderr, "xmlNodeAddContent : node == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00002950#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00002951 return;
2952 }
Daniel Veillard16253641998-10-28 22:58:05 +00002953 if (content == NULL) return;
2954 len = xmlStrlen(content);
2955 xmlNodeAddContentLen(cur, content, len);
2956}
2957
2958/**
2959 * xmlTextMerge:
2960 * @first: the first text node
2961 * @second: the second text node being merged
2962 *
2963 * Merge two text nodes into one
Daniel Veillard1e346af1999-02-22 10:33:01 +00002964 * Returns the first text node augmented
Daniel Veillard16253641998-10-28 22:58:05 +00002965 */
2966xmlNodePtr
2967xmlTextMerge(xmlNodePtr first, xmlNodePtr second) {
2968 if (first == NULL) return(second);
2969 if (second == NULL) return(first);
2970 if (first->type != XML_TEXT_NODE) return(first);
2971 if (second->type != XML_TEXT_NODE) return(first);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002972#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard16253641998-10-28 22:58:05 +00002973 xmlNodeAddContent(first, second->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002974#else
2975 xmlNodeAddContent(first, xmlBufferContent(second->content));
2976#endif
Daniel Veillard16253641998-10-28 22:58:05 +00002977 xmlUnlinkNode(second);
2978 xmlFreeNode(second);
2979 return(first);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002980}
2981
Daniel Veillard97b58771998-10-20 06:14:16 +00002982/**
Daniel Veillardb96e6431999-08-29 21:02:19 +00002983 * xmlGetNsList:
2984 * @doc: the document
2985 * @node: the current node
2986 *
2987 * Search all the namespace applying to a given element.
2988 * Returns an NULL terminated array of all the xmlNsPtr found
2989 * that need to be freed by the caller or NULL if no
2990 * namespace if defined
2991 */
2992xmlNsPtr *
2993xmlGetNsList(xmlDocPtr doc, xmlNodePtr node) {
2994 xmlNsPtr cur;
2995 xmlNsPtr *ret = NULL;
2996 int nbns = 0;
2997 int maxns = 10;
2998 int i;
2999
3000 while (node != NULL) {
3001 cur = node->nsDef;
3002 while (cur != NULL) {
3003 if (ret == NULL) {
Daniel Veillard6454aec1999-09-02 22:04:43 +00003004 ret = (xmlNsPtr *) xmlMalloc((maxns + 1) * sizeof(xmlNsPtr));
Daniel Veillardb96e6431999-08-29 21:02:19 +00003005 if (ret == NULL) {
3006 fprintf(stderr, "xmlGetNsList : out of memory!\n");
3007 return(NULL);
3008 }
3009 ret[nbns] = NULL;
3010 }
3011 for (i = 0;i < nbns;i++) {
3012 if ((cur->prefix == ret[i]->prefix) ||
3013 (!xmlStrcmp(cur->prefix, ret[i]->prefix))) break;
3014 }
3015 if (i >= nbns) {
3016 if (nbns >= maxns) {
3017 maxns *= 2;
Daniel Veillard6454aec1999-09-02 22:04:43 +00003018 ret = (xmlNsPtr *) xmlRealloc(ret,
Daniel Veillardb96e6431999-08-29 21:02:19 +00003019 (maxns + 1) * sizeof(xmlNsPtr));
3020 if (ret == NULL) {
3021 fprintf(stderr, "xmlGetNsList : realloc failed!\n");
3022 return(NULL);
3023 }
3024 }
3025 ret[nbns++] = cur;
3026 ret[nbns] = NULL;
3027 }
3028
3029 cur = cur->next;
3030 }
3031 node = node->parent;
3032 }
3033 return(ret);
3034}
3035
3036/**
Daniel Veillard97b58771998-10-20 06:14:16 +00003037 * xmlSearchNs:
3038 * @doc: the document
3039 * @node: the current node
3040 * @nameSpace: the namespace string
Daniel Veillard260a68f1998-08-13 03:39:55 +00003041 *
Daniel Veillard97b58771998-10-20 06:14:16 +00003042 * Search a Ns registered under a given name space for a document.
3043 * recurse on the parents until it finds the defined namespace
3044 * or return NULL otherwise.
3045 * @nameSpace can be NULL, this is a search for the default namespace.
Daniel Veillard1e346af1999-02-22 10:33:01 +00003046 * Returns the namespace pointer or NULL.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003047 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003048xmlNsPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003049xmlSearchNs(xmlDocPtr doc, xmlNodePtr node, const xmlChar *nameSpace) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003050 xmlNsPtr cur;
3051
Daniel Veillard62ba71e1999-12-16 17:52:19 +00003052 if (node == NULL) return(NULL);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003053 while (node != NULL) {
3054 cur = node->nsDef;
3055 while (cur != NULL) {
3056 if ((cur->prefix == NULL) && (nameSpace == NULL))
3057 return(cur);
3058 if ((cur->prefix != NULL) && (nameSpace != NULL) &&
3059 (!xmlStrcmp(cur->prefix, nameSpace)))
3060 return(cur);
3061 cur = cur->next;
3062 }
3063 node = node->parent;
3064 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003065 return(NULL);
3066}
3067
Daniel Veillard97b58771998-10-20 06:14:16 +00003068/**
3069 * xmlSearchNsByHref:
3070 * @doc: the document
3071 * @node: the current node
3072 * @href: the namespace value
3073 *
3074 * Search a Ns aliasing a given URI. Recurse on the parents until it finds
3075 * the defined namespace or return NULL otherwise.
Daniel Veillard1e346af1999-02-22 10:33:01 +00003076 * Returns the namespace pointer or NULL.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003077 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003078xmlNsPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003079xmlSearchNsByHref(xmlDocPtr doc, xmlNodePtr node, const xmlChar *href) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003080 xmlNsPtr cur;
Daniel Veillarddbfd6411999-12-28 16:35:14 +00003081 xmlNodePtr orig = node;
Daniel Veillard260a68f1998-08-13 03:39:55 +00003082
Daniel Veillard10a2c651999-12-12 13:03:50 +00003083 if ((node == NULL) || (href == NULL)) return(NULL);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003084 while (node != NULL) {
3085 cur = node->nsDef;
3086 while (cur != NULL) {
3087 if ((cur->href != NULL) && (href != NULL) &&
Daniel Veillarddbfd6411999-12-28 16:35:14 +00003088 (!xmlStrcmp(cur->href, href))) {
3089 /*
3090 * Check that the prefix is not shadowed between orig and node
3091 */
3092 xmlNodePtr check = orig;
3093 xmlNsPtr tst;
3094
3095 while (check != node) {
3096 tst = check->nsDef;
3097 while (tst != NULL) {
3098 if ((tst->prefix == NULL) && (cur->prefix == NULL))
3099 goto shadowed;
3100 if ((tst->prefix != NULL) && (cur->prefix != NULL) &&
3101 (!xmlStrcmp(tst->prefix, cur->prefix)))
3102 goto shadowed;
3103 tst = tst->next;
3104 }
3105 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003106 return(cur);
Daniel Veillarddbfd6411999-12-28 16:35:14 +00003107 }
3108shadowed:
Daniel Veillard260a68f1998-08-13 03:39:55 +00003109 cur = cur->next;
3110 }
3111 node = node->parent;
3112 }
Daniel Veillarddbfd6411999-12-28 16:35:14 +00003113 return(NULL);
3114}
3115
3116/**
3117 * xmlNewReconciliedNs
3118 * @doc: the document
3119 * @tree: a node expected to hold the new namespace
3120 * @ns: the original namespace
3121 *
3122 * This function tries to locate a namespace definition in a tree
3123 * ancestors, or create a new namespace definition node similar to
3124 * @ns trying to reuse the same prefix. However if the given prefix is
3125 * null (default namespace) or reused within the subtree defined by
3126 * @tree or on one of its ancestors then a new prefix is generated.
3127 * Returns the (new) namespace definition or NULL in case of error
3128 */
3129xmlNsPtr
3130xmlNewReconciliedNs(xmlDocPtr doc, xmlNodePtr tree, xmlNsPtr ns) {
3131 xmlNsPtr def;
3132 xmlChar prefix[50];
3133 int counter = 1;
3134
3135 if (tree == NULL) {
3136#ifdef DEBUG_TREE
3137 fprintf(stderr, "xmlNewReconciliedNs : tree == NULL\n");
3138#endif
3139 return(NULL);
3140 }
3141 if (ns == NULL) {
3142#ifdef DEBUG_TREE
3143 fprintf(stderr, "xmlNewReconciliedNs : ns == NULL\n");
3144#endif
3145 return(NULL);
3146 }
3147 /*
3148 * Search an existing namespace definition inherited.
3149 */
3150 def = xmlSearchNsByHref(doc, tree, ns->href);
3151 if (def != NULL)
3152 return(def);
3153
3154 /*
3155 * Find a close prefix which is not already in use.
3156 * Let's strip namespace prefixes longer than 20 chars !
3157 */
3158 sprintf((char *) prefix, "%.20s", ns->prefix);
3159 def = xmlSearchNs(doc, tree, prefix);
3160 while (def != NULL) {
3161 if (counter > 1000) return(NULL);
3162 sprintf((char *) prefix, "%.20s%d", ns->prefix, counter++);
3163 def = xmlSearchNs(doc, tree, prefix);
3164 }
3165
3166 /*
3167 * Ok, now we are ready to create a new one.
3168 */
3169 def = xmlNewNs(tree, ns->href, prefix);
3170 return(def);
3171}
3172
3173/**
3174 * xmlReconciliateNs
3175 * @doc: the document
3176 * @tree: a node defining the subtree to reconciliate
3177 *
3178 * This function checks that all the namespaces declared within the given
3179 * tree are properly declared. This is needed for example after Copy or Cut
3180 * and then paste operations. The subtree may still hold pointers to
3181 * namespace declarations outside the subtree or invalid/masked. As much
3182 * as possible the function try tu reuse the existing namespaces found in
3183 * the new environment. If not possible the new namespaces are redeclared
3184 * on @tree at the top of the given subtree.
3185 * Returns the number of namespace declarations created or -1 in case of error.
3186 */
3187int
3188xmlReconciliateNs(xmlDocPtr doc, xmlNodePtr tree) {
3189 xmlNsPtr *oldNs = NULL;
3190 xmlNsPtr *newNs = NULL;
3191 int sizeCache = 0;
3192 int nbCache = 0;
3193
3194 xmlNsPtr n;
3195 xmlNodePtr node = tree;
3196 xmlAttrPtr attr;
3197 int ret = 0, i;
3198
3199 while (node != NULL) {
3200 /*
3201 * Reconciliate the node namespace
3202 */
3203 if (node->ns != NULL) {
3204 /*
3205 * initialize the cache if needed
3206 */
3207 if (sizeCache == 0) {
3208 sizeCache = 10;
3209 oldNs = (xmlNsPtr *) xmlMalloc(sizeCache *
3210 sizeof(xmlNsPtr));
3211 if (oldNs == NULL) {
3212 fprintf(stderr, "xmlReconciliateNs : memory pbm\n");
3213 return(-1);
3214 }
3215 newNs = (xmlNsPtr *) xmlMalloc(sizeCache *
3216 sizeof(xmlNsPtr));
3217 if (newNs == NULL) {
3218 fprintf(stderr, "xmlReconciliateNs : memory pbm\n");
3219 xmlFree(oldNs);
3220 return(-1);
3221 }
3222 }
3223 for (i = 0;i < nbCache;i++) {
3224 if (oldNs[i] == node->ns) {
3225 node->ns = newNs[i];
3226 break;
3227 }
3228 }
3229 if (i == nbCache) {
3230 /*
3231 * Ok we need to recreate a new namespace definition
3232 */
3233 n = xmlNewReconciliedNs(doc, tree, node->ns);
3234 if (n != NULL) { /* :-( what if else ??? */
3235 /*
3236 * check if we need to grow the cache buffers.
3237 */
3238 if (sizeCache <= nbCache) {
3239 sizeCache *= 2;
3240 oldNs = (xmlNsPtr *) xmlRealloc(oldNs, sizeCache *
3241 sizeof(xmlNsPtr));
3242 if (oldNs == NULL) {
3243 fprintf(stderr, "xmlReconciliateNs : memory pbm\n");
3244 xmlFree(newNs);
3245 return(-1);
3246 }
3247 newNs = (xmlNsPtr *) xmlRealloc(newNs, sizeCache *
3248 sizeof(xmlNsPtr));
3249 if (newNs == NULL) {
3250 fprintf(stderr, "xmlReconciliateNs : memory pbm\n");
3251 xmlFree(oldNs);
3252 return(-1);
3253 }
3254 }
3255 newNs[nbCache] = n;
3256 oldNs[nbCache++] = node->ns;
3257 node->ns = n;
3258 }
3259 }
3260 }
3261 /*
3262 * now check for namespace hold by attributes on the node.
3263 */
3264 attr = node->properties;
3265 while (attr != NULL) {
3266 if (attr->ns != NULL) {
3267 /*
3268 * initialize the cache if needed
3269 */
3270 if (sizeCache == 0) {
3271 sizeCache = 10;
3272 oldNs = (xmlNsPtr *) xmlMalloc(sizeCache *
3273 sizeof(xmlNsPtr));
3274 if (oldNs == NULL) {
3275 fprintf(stderr, "xmlReconciliateNs : memory pbm\n");
3276 return(-1);
3277 }
3278 newNs = (xmlNsPtr *) xmlMalloc(sizeCache *
3279 sizeof(xmlNsPtr));
3280 if (newNs == NULL) {
3281 fprintf(stderr, "xmlReconciliateNs : memory pbm\n");
3282 xmlFree(oldNs);
3283 return(-1);
3284 }
3285 }
3286 for (i = 0;i < nbCache;i++) {
3287 if (oldNs[i] == attr->ns) {
3288 node->ns = newNs[i];
3289 break;
3290 }
3291 }
3292 if (i == nbCache) {
3293 /*
3294 * Ok we need to recreate a new namespace definition
3295 */
3296 n = xmlNewReconciliedNs(doc, tree, attr->ns);
3297 if (n != NULL) { /* :-( what if else ??? */
3298 /*
3299 * check if we need to grow the cache buffers.
3300 */
3301 if (sizeCache <= nbCache) {
3302 sizeCache *= 2;
3303 oldNs = (xmlNsPtr *) xmlRealloc(oldNs, sizeCache *
3304 sizeof(xmlNsPtr));
3305 if (oldNs == NULL) {
3306 fprintf(stderr,
3307 "xmlReconciliateNs : memory pbm\n");
3308 xmlFree(newNs);
3309 return(-1);
3310 }
3311 newNs = (xmlNsPtr *) xmlRealloc(newNs, sizeCache *
3312 sizeof(xmlNsPtr));
3313 if (newNs == NULL) {
3314 fprintf(stderr,
3315 "xmlReconciliateNs : memory pbm\n");
3316 xmlFree(oldNs);
3317 return(-1);
3318 }
3319 }
3320 newNs[nbCache] = n;
3321 oldNs[nbCache++] = attr->ns;
3322 attr->ns = n;
3323 }
3324 }
3325 }
3326 attr = attr->next;
3327 }
3328
3329 /*
3330 * Browse the full subtree, deep first
3331 */
3332 if (node->childs != NULL) {
3333 /* deep first */
3334 node = node->childs;
3335 } else if ((node != tree) && (node->next != NULL)) {
3336 /* then siblings */
3337 node = node->next;
3338 } else if (node != tree) {
3339 /* go up to parents->next if needed */
3340 while (node != tree) {
3341 if (node->parent != NULL)
3342 node = node->parent;
3343 if ((node != tree) && (node->next != NULL)) {
3344 node = node->next;
3345 break;
3346 }
3347 if (node->parent == NULL) {
3348 node = NULL;
3349 break;
3350 }
3351 }
3352 /* exit condition */
3353 if (node == tree)
3354 node = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00003355 }
3356 }
Daniel Veillarddbfd6411999-12-28 16:35:14 +00003357 return(ret);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003358}
3359
Daniel Veillard97b58771998-10-20 06:14:16 +00003360/**
3361 * xmlGetProp:
3362 * @node: the node
3363 * @name: the attribute name
3364 *
3365 * Search and get the value of an attribute associated to a node
Daniel Veillardccb09631998-10-27 06:21:04 +00003366 * This does the entity substitution.
Daniel Veillard10a2c651999-12-12 13:03:50 +00003367 * This function looks in DTD attribute declaration for #FIXED or
3368 * default declaration values unless DTD use has been turned off.
3369 *
Daniel Veillard1e346af1999-02-22 10:33:01 +00003370 * Returns the attribute value or NULL if not found.
Daniel Veillarda819dac1999-11-24 18:04:22 +00003371 * It's up to the caller to free the memory.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003372 */
Daniel Veillarda819dac1999-11-24 18:04:22 +00003373xmlChar *
3374xmlGetProp(xmlNodePtr node, const xmlChar *name) {
Daniel Veillard10a2c651999-12-12 13:03:50 +00003375 xmlAttrPtr prop;
3376 xmlDocPtr doc;
Daniel Veillard260a68f1998-08-13 03:39:55 +00003377
Daniel Veillard10a2c651999-12-12 13:03:50 +00003378 if ((node == NULL) || (name == NULL)) return(NULL);
3379 /*
3380 * Check on the properties attached to the node
3381 */
3382 prop = node->properties;
Daniel Veillard260a68f1998-08-13 03:39:55 +00003383 while (prop != NULL) {
Daniel Veillard68178931999-02-08 18:34:36 +00003384 if (!xmlStrcmp(prop->name, name)) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003385 xmlChar *ret;
Daniel Veillard6800ef31999-02-08 18:33:22 +00003386
3387 ret = xmlNodeListGetString(node->doc, prop->val, 1);
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003388 if (ret == NULL) return(xmlStrdup((xmlChar *)""));
Daniel Veillard6800ef31999-02-08 18:33:22 +00003389 return(ret);
Daniel Veillard68178931999-02-08 18:34:36 +00003390 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003391 prop = prop->next;
3392 }
Daniel Veillard10a2c651999-12-12 13:03:50 +00003393 if (!xmlCheckDTD) return(NULL);
3394
3395 /*
3396 * Check if there is a default declaration in the internal
3397 * or external subsets
3398 */
3399 doc = node->doc;
3400 if (doc != NULL) {
3401 xmlAttributePtr attrDecl;
3402 if (doc->intSubset != NULL) {
3403 attrDecl = xmlGetDtdAttrDesc(doc->intSubset, node->name, name);
3404 if ((attrDecl == NULL) && (doc->extSubset != NULL))
3405 attrDecl = xmlGetDtdAttrDesc(doc->extSubset, node->name, name);
Daniel Veillardf967b902000-01-17 16:06:10 +00003406 if (attrDecl != NULL)
3407 return(xmlStrdup(attrDecl->defaultValue));
Daniel Veillard10a2c651999-12-12 13:03:50 +00003408 }
3409 }
3410 return(NULL);
3411}
3412
3413/**
3414 * xmlGetNsProp:
3415 * @node: the node
3416 * @name: the attribute name
3417 * @namespace: the URI of the namespace
3418 *
3419 * Search and get the value of an attribute associated to a node
3420 * This attribute has to be anchored in the namespace specified.
3421 * This does the entity substitution.
3422 * This function looks in DTD attribute declaration for #FIXED or
3423 * default declaration values unless DTD use has been turned off.
3424 *
3425 * Returns the attribute value or NULL if not found.
3426 * It's up to the caller to free the memory.
3427 */
3428xmlChar *
3429xmlGetNsProp(xmlNodePtr node, const xmlChar *name, const xmlChar *namespace) {
3430 xmlAttrPtr prop = node->properties;
3431 xmlDocPtr doc;
3432 xmlNsPtr ns;
3433
3434 if (namespace == NULL)
3435 return(xmlGetProp(node, name));
3436 while (prop != NULL) {
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00003437 /*
3438 * One need to have
3439 * - same attribute names
3440 * - and the attribute carrying that namespace
3441 * or
3442 * no namespace on the attribute and the element carrying it
3443 */
Daniel Veillard10a2c651999-12-12 13:03:50 +00003444 if ((!xmlStrcmp(prop->name, name)) &&
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00003445 (((prop->ns == NULL) && (node->ns != NULL) &&
3446 (!xmlStrcmp(node->ns->href, namespace))) ||
Daniel Veillard3c558c31999-12-22 11:30:41 +00003447 ((prop->ns != NULL) && (!xmlStrcmp(prop->ns->href, namespace))))) {
Daniel Veillard10a2c651999-12-12 13:03:50 +00003448 xmlChar *ret;
3449
3450 ret = xmlNodeListGetString(node->doc, prop->val, 1);
3451 if (ret == NULL) return(xmlStrdup((xmlChar *)""));
3452 return(ret);
3453 }
3454 prop = prop->next;
3455 }
3456 if (!xmlCheckDTD) return(NULL);
3457
3458 /*
3459 * Check if there is a default declaration in the internal
3460 * or external subsets
3461 */
3462 doc = node->doc;
3463 if (doc != NULL) {
3464 xmlAttributePtr attrDecl;
3465 if (doc->intSubset != NULL) {
3466 attrDecl = xmlGetDtdAttrDesc(doc->intSubset, node->name, name);
3467 if ((attrDecl == NULL) && (doc->extSubset != NULL))
3468 attrDecl = xmlGetDtdAttrDesc(doc->extSubset, node->name, name);
3469
3470 if (attrDecl->prefix != NULL) {
3471 /*
3472 * The DTD declaration only allows a prefix search
3473 */
3474 ns = xmlSearchNs(doc, node, attrDecl->prefix);
3475 if ((ns != NULL) && (!xmlStrcmp(ns->href, namespace)))
3476 return(xmlStrdup(attrDecl->defaultValue));
3477 }
3478 }
3479 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003480 return(NULL);
3481}
3482
Daniel Veillard97b58771998-10-20 06:14:16 +00003483/**
Daniel Veillardccb09631998-10-27 06:21:04 +00003484 * xmlSetProp:
Daniel Veillard97b58771998-10-20 06:14:16 +00003485 * @node: the node
3486 * @name: the attribute name
3487 * @value: the attribute value
3488 *
3489 * Set (or reset) an attribute carried by a node.
Daniel Veillard1e346af1999-02-22 10:33:01 +00003490 * Returns the attribute pointer.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003491 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003492xmlAttrPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003493xmlSetProp(xmlNodePtr node, const xmlChar *name, const xmlChar *value) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003494 xmlAttrPtr prop = node->properties;
3495
3496 while (prop != NULL) {
3497 if (!xmlStrcmp(prop->name, name)) {
Daniel Veillardccb09631998-10-27 06:21:04 +00003498 if (prop->val != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +00003499 xmlFreeNodeList(prop->val);
Daniel Veillardccb09631998-10-27 06:21:04 +00003500 prop->val = NULL;
Daniel Veillard51e3b151999-11-12 17:02:31 +00003501 if (value != NULL) {
3502 xmlChar *buffer;
3503 buffer = xmlEncodeEntitiesReentrant(node->doc, value);
3504 prop->val = xmlStringGetNodeList(node->doc, buffer);
3505 xmlFree(buffer);
3506 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003507 return(prop);
3508 }
3509 prop = prop->next;
3510 }
3511 prop = xmlNewProp(node, name, value);
3512 return(prop);
3513}
3514
Daniel Veillard97b58771998-10-20 06:14:16 +00003515/**
3516 * xmlNodeIsText:
3517 * @node: the node
3518 *
3519 * Is this node a Text node ?
Daniel Veillard1e346af1999-02-22 10:33:01 +00003520 * Returns 1 yes, 0 no
Daniel Veillard260a68f1998-08-13 03:39:55 +00003521 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003522int
3523xmlNodeIsText(xmlNodePtr node) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003524 if (node == NULL) return(0);
3525
Daniel Veillard0bef1311998-10-14 02:36:47 +00003526 if (node->type == XML_TEXT_NODE) return(1);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003527 return(0);
3528}
3529
Daniel Veillard97b58771998-10-20 06:14:16 +00003530/**
Daniel Veillard3e6d2372000-03-04 11:39:43 +00003531 * xmlIsBlankNode:
3532 * @node: the node
3533 *
3534 * Is this node a Text node ?
3535 * Returns 1 yes, 0 no
3536 */
3537int
3538xmlIsBlankNode(xmlNodePtr node) {
3539 xmlChar *cur;
3540 if (node == NULL) return(0);
3541
3542 if (node->type != XML_TEXT_NODE) return(0);
3543 if (node->content == NULL) return(0);
3544 cur = node->content;
3545 while (*cur != 0) {
3546 if (!IS_BLANK(*cur)) return(0);
3547 cur++;
3548 }
3549
3550 return(1);
3551}
3552
3553/**
Daniel Veillard1e346af1999-02-22 10:33:01 +00003554 * xmlTextConcat:
Daniel Veillard97b58771998-10-20 06:14:16 +00003555 * @node: the node
3556 * @content: the content
3557 * @len: @content lenght
3558 *
3559 * Concat the given string at the end of the existing node content
Daniel Veillard260a68f1998-08-13 03:39:55 +00003560 */
Daniel Veillard97b58771998-10-20 06:14:16 +00003561
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003562void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003563xmlTextConcat(xmlNodePtr node, const xmlChar *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003564 if (node == NULL) return;
3565
Daniel Veillarddbfd6411999-12-28 16:35:14 +00003566 if ((node->type != XML_TEXT_NODE) &&
3567 (node->type != XML_CDATA_SECTION_NODE)) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00003568#ifdef DEBUG_TREE
Daniel Veillarddbfd6411999-12-28 16:35:14 +00003569 fprintf(stderr, "xmlTextConcat: node is not text nor cdata\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00003570#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00003571 return;
3572 }
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003573#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard260a68f1998-08-13 03:39:55 +00003574 node->content = xmlStrncat(node->content, content, len);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003575#else
3576 xmlBufferAdd(node->content, content, len);
3577#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00003578}
3579
3580/************************************************************************
3581 * *
3582 * Output : to a FILE or in memory *
3583 * *
3584 ************************************************************************/
3585
Daniel Veillard5099ae81999-04-21 20:12:07 +00003586#define BASE_BUFFER_SIZE 4000
3587
3588/**
3589 * xmlBufferCreate:
3590 *
3591 * routine to create an XML buffer.
3592 * returns the new structure.
3593 */
3594xmlBufferPtr
3595xmlBufferCreate(void) {
3596 xmlBufferPtr ret;
3597
Daniel Veillard6454aec1999-09-02 22:04:43 +00003598 ret = (xmlBufferPtr) xmlMalloc(sizeof(xmlBuffer));
Daniel Veillard5099ae81999-04-21 20:12:07 +00003599 if (ret == NULL) {
3600 fprintf(stderr, "xmlBufferCreate : out of memory!\n");
3601 return(NULL);
3602 }
3603 ret->use = 0;
3604 ret->size = BASE_BUFFER_SIZE;
Daniel Veillard10a2c651999-12-12 13:03:50 +00003605 ret->alloc = xmlBufferAllocScheme;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003606 ret->content = (xmlChar *) xmlMalloc(ret->size * sizeof(xmlChar));
Daniel Veillard5099ae81999-04-21 20:12:07 +00003607 if (ret->content == NULL) {
3608 fprintf(stderr, "xmlBufferCreate : out of memory!\n");
Daniel Veillard6454aec1999-09-02 22:04:43 +00003609 xmlFree(ret);
Daniel Veillard5099ae81999-04-21 20:12:07 +00003610 return(NULL);
3611 }
3612 ret->content[0] = 0;
3613 return(ret);
3614}
3615
3616/**
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003617 * xmlBufferCreateSize:
3618 * @size: initial size of buffer
3619 *
3620 * routine to create an XML buffer.
3621 * returns the new structure.
3622 */
3623xmlBufferPtr
3624xmlBufferCreateSize(size_t size) {
3625 xmlBufferPtr ret;
3626
3627 ret = (xmlBufferPtr) xmlMalloc(sizeof(xmlBuffer));
3628 if (ret == NULL) {
3629 fprintf(stderr, "xmlBufferCreate : out of memory!\n");
3630 return(NULL);
3631 }
3632 ret->use = 0;
Daniel Veillard10a2c651999-12-12 13:03:50 +00003633 ret->alloc = xmlBufferAllocScheme;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003634 ret->size = (size ? size+2 : 0); /* +1 for ending null */
Daniel Veillard10a2c651999-12-12 13:03:50 +00003635 if (ret->size){
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003636 ret->content = (xmlChar *) xmlMalloc(ret->size * sizeof(xmlChar));
3637 if (ret->content == NULL) {
3638 fprintf(stderr, "xmlBufferCreate : out of memory!\n");
3639 xmlFree(ret);
3640 return(NULL);
3641 }
3642 ret->content[0] = 0;
3643 } else
3644 ret->content = NULL;
3645 return(ret);
3646}
3647
3648/**
3649 * xmlBufferAllocationScheme:
3650 * @buf: the buffer to free
3651 * @scheme: allocation scheme to use
3652 *
3653 * Sets the allocation scheme for this buffer
3654 */
3655void
3656xmlBufferSetAllocationScheme(xmlBufferPtr buf,
3657 xmlBufferAllocationScheme scheme) {
3658 if (buf == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00003659#ifdef DEBUG_BUFFER
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003660 fprintf(stderr, "xmlBufferSetAllocationScheme: buf == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00003661#endif
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003662 return;
3663 }
3664
3665 buf->alloc = scheme;
3666}
3667
3668/**
Daniel Veillard5099ae81999-04-21 20:12:07 +00003669 * xmlBufferFree:
3670 * @buf: the buffer to free
3671 *
3672 * Frees an XML buffer.
3673 */
3674void
3675xmlBufferFree(xmlBufferPtr buf) {
3676 if (buf == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00003677#ifdef DEBUG_BUFFER
Daniel Veillard5099ae81999-04-21 20:12:07 +00003678 fprintf(stderr, "xmlBufferFree: buf == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00003679#endif
Daniel Veillard5099ae81999-04-21 20:12:07 +00003680 return;
3681 }
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003682 if (buf->content != NULL) {
3683#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard5099ae81999-04-21 20:12:07 +00003684 memset(buf->content, -1, BASE_BUFFER_SIZE);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003685#else
3686 memset(buf->content, -1, buf->size);
3687#endif
Daniel Veillard6454aec1999-09-02 22:04:43 +00003688 xmlFree(buf->content);
Daniel Veillard5099ae81999-04-21 20:12:07 +00003689 }
3690 memset(buf, -1, sizeof(xmlBuffer));
Daniel Veillard6454aec1999-09-02 22:04:43 +00003691 xmlFree(buf);
Daniel Veillard5099ae81999-04-21 20:12:07 +00003692}
3693
3694/**
Daniel Veillarde2d034d1999-07-27 19:52:06 +00003695 * xmlBufferEmpty:
3696 * @buf: the buffer
3697 *
3698 * empty a buffer.
3699 */
3700void
3701xmlBufferEmpty(xmlBufferPtr buf) {
3702 buf->use = 0;
3703 memset(buf->content, -1, buf->size);/* just for debug */
3704}
3705
3706/**
3707 * xmlBufferShrink:
3708 * @buf: the buffer to dump
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003709 * @len: the number of xmlChar to remove
Daniel Veillarde2d034d1999-07-27 19:52:06 +00003710 *
3711 * Remove the beginning of an XML buffer.
3712 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003713 * Returns the number of xmlChar removed, or -1 in case of failure.
Daniel Veillarde2d034d1999-07-27 19:52:06 +00003714 */
3715int
3716xmlBufferShrink(xmlBufferPtr buf, int len) {
3717 if (len == 0) return(0);
3718 if (len > buf->use) return(-1);
3719
3720 buf->use -= len;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003721 memmove(buf->content, &buf->content[len], buf->use * sizeof(xmlChar));
Daniel Veillarde2d034d1999-07-27 19:52:06 +00003722
3723 buf->content[buf->use] = 0;
3724 return(len);
3725}
3726
3727/**
Daniel Veillard5099ae81999-04-21 20:12:07 +00003728 * xmlBufferDump:
3729 * @file: the file output
3730 * @buf: the buffer to dump
3731 *
3732 * Dumps an XML buffer to a FILE *.
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003733 * Returns the number of xmlChar written
Daniel Veillard5099ae81999-04-21 20:12:07 +00003734 */
3735int
3736xmlBufferDump(FILE *file, xmlBufferPtr buf) {
3737 int ret;
3738
3739 if (buf == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00003740#ifdef DEBUG_BUFFER
Daniel Veillard5099ae81999-04-21 20:12:07 +00003741 fprintf(stderr, "xmlBufferDump: buf == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00003742#endif
Daniel Veillard5099ae81999-04-21 20:12:07 +00003743 return(0);
3744 }
3745 if (buf->content == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00003746#ifdef DEBUG_BUFFER
Daniel Veillard5099ae81999-04-21 20:12:07 +00003747 fprintf(stderr, "xmlBufferDump: buf->content == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00003748#endif
Daniel Veillard5099ae81999-04-21 20:12:07 +00003749 return(0);
3750 }
3751 if (file == NULL) file = stdout;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003752 ret = fwrite(buf->content, sizeof(xmlChar), buf->use, file);
Daniel Veillard5099ae81999-04-21 20:12:07 +00003753 return(ret);
3754}
3755
3756/**
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003757 * xmlBufferContent:
3758 * @buf: the buffer to resize
3759 *
3760 * Returns the internal content
3761 */
3762
3763const xmlChar*
3764xmlBufferContent(const xmlBufferPtr buf)
3765{
3766 if(!buf)
3767 return NULL;
3768
3769 return buf->content;
3770}
3771
3772/**
3773 * xmlBufferLength:
3774 * @buf: the buffer
3775 *
3776 * Returns the length of data in the internal content
3777 */
3778
3779int
3780xmlBufferLength(const xmlBufferPtr buf)
3781{
3782 if(!buf)
3783 return 0;
3784
3785 return buf->use;
3786}
3787
3788/**
3789 * xmlBufferResize:
3790 * @buf: the buffer to resize
3791 * @len: the desired size
3792 *
3793 * Resize a buffer to accomodate minimum size of <len>.
3794 *
3795 * Returns 0 in case of problems, 1 otherwise
3796 */
3797int
3798xmlBufferResize(xmlBufferPtr buf, int size)
3799{
3800 int newSize = (buf->size ? buf->size*2 : size);/*take care of empty case*/
3801 xmlChar* rebuf = NULL;
3802
3803 /* Don't resize if we don't have to */
3804 if(size < buf->size)
3805 return 1;
3806
3807 /* figure out new size */
3808 switch(buf->alloc){
3809 case XML_BUFFER_ALLOC_DOUBLEIT:
3810 while(size > newSize) newSize *= 2;
3811 break;
3812 case XML_BUFFER_ALLOC_EXACT:
3813 newSize = size+10;
3814 break;
3815 default:
3816 newSize = size+10;
3817 break;
3818 }
3819
3820 if (buf->content == NULL)
3821 rebuf = (xmlChar *) xmlMalloc(newSize * sizeof(xmlChar));
3822 else
3823 rebuf = (xmlChar *) xmlRealloc(buf->content,
3824 newSize * sizeof(xmlChar));
3825 if (rebuf == NULL) {
3826 fprintf(stderr, "xmlBufferAdd : out of memory!\n");
3827 return 0;
3828 }
3829 buf->content = rebuf;
3830 buf->size = newSize;
3831
3832 return 1;
3833}
3834/**
Daniel Veillard5099ae81999-04-21 20:12:07 +00003835 * xmlBufferAdd:
3836 * @buf: the buffer to dump
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003837 * @str: the xmlChar string
3838 * @len: the number of xmlChar to add
Daniel Veillard5099ae81999-04-21 20:12:07 +00003839 *
Daniel Veillard10a2c651999-12-12 13:03:50 +00003840 * Add a string range to an XML buffer. if len == -1, the lenght of
3841 * str is recomputed.
Daniel Veillard5099ae81999-04-21 20:12:07 +00003842 */
3843void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003844xmlBufferAdd(xmlBufferPtr buf, const xmlChar *str, int len) {
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003845 int l, needSize;
Daniel Veillard5099ae81999-04-21 20:12:07 +00003846
3847 if (str == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00003848#ifdef DEBUG_BUFFER
Daniel Veillard5099ae81999-04-21 20:12:07 +00003849 fprintf(stderr, "xmlBufferAdd: str == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00003850#endif
Daniel Veillard5099ae81999-04-21 20:12:07 +00003851 return;
3852 }
Daniel Veillard10a2c651999-12-12 13:03:50 +00003853 if (len < -1) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00003854#ifdef DEBUG_BUFFER
Daniel Veillard10a2c651999-12-12 13:03:50 +00003855 fprintf(stderr, "xmlBufferAdd: len < 0\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00003856#endif
Daniel Veillard10a2c651999-12-12 13:03:50 +00003857 return;
3858 }
3859 if (len == 0) return;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003860
3861 /* CJN What's this for??? */
Daniel Veillarddbfd6411999-12-28 16:35:14 +00003862 if (len < 0)
3863 l = xmlStrlen(str);
3864 else
3865 for (l = 0;l < len;l++)
3866 if (str[l] == 0) break;
Daniel Veillardad8f99d2000-01-15 14:20:03 +00003867 if (l < len){
3868 len = l;
3869#ifdef DEBUG_BUFFER
3870 printf("xmlBufferAdd bad length\n");
3871#endif
3872 }
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003873
3874 /* CJN 11.18.99 okay, now I'm using the length */
3875 if(len == -1) len = l;
3876
3877
Daniel Veillarde2d034d1999-07-27 19:52:06 +00003878 if (len <= 0) return;
Daniel Veillard5099ae81999-04-21 20:12:07 +00003879
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003880 needSize = buf->use + len + 2;
3881 if(needSize > buf->size){
3882 if(!xmlBufferResize(buf, needSize)){
3883 fprintf(stderr, "xmlBufferAdd : out of memory!\n");
3884 return;
3885 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003886 }
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003887
3888 memmove(&buf->content[buf->use], str, len*sizeof(xmlChar));
Daniel Veillarde2d034d1999-07-27 19:52:06 +00003889 buf->use += len;
3890 buf->content[buf->use] = 0;
Daniel Veillard5099ae81999-04-21 20:12:07 +00003891}
3892
3893/**
3894 * xmlBufferCat:
3895 * @buf: the buffer to dump
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003896 * @str: the xmlChar string
Daniel Veillard5099ae81999-04-21 20:12:07 +00003897 *
3898 * Append a zero terminated string to an XML buffer.
3899 */
3900void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003901xmlBufferCat(xmlBufferPtr buf, const xmlChar *str) {
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003902 if (str != NULL)
3903 xmlBufferAdd(buf, str, -1);
Daniel Veillard5099ae81999-04-21 20:12:07 +00003904}
3905
3906/**
3907 * xmlBufferCCat:
3908 * @buf: the buffer to dump
3909 * @str: the C char string
3910 *
3911 * Append a zero terminated C string to an XML buffer.
3912 */
3913void
3914xmlBufferCCat(xmlBufferPtr buf, const char *str) {
3915 const char *cur;
3916
3917 if (str == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00003918#ifdef DEBUG_BUFFER
Daniel Veillard5099ae81999-04-21 20:12:07 +00003919 fprintf(stderr, "xmlBufferAdd: str == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00003920#endif
Daniel Veillard5099ae81999-04-21 20:12:07 +00003921 return;
3922 }
3923 for (cur = str;*cur != 0;cur++) {
3924 if (buf->use + 10 >= buf->size) {
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003925 if(!xmlBufferResize(buf, buf->use+10)){
3926 fprintf(stderr, "xmlBufferCCat : out of memory!\n");
3927 return;
3928 }
3929 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003930 buf->content[buf->use++] = *cur;
3931 }
3932}
Daniel Veillard260a68f1998-08-13 03:39:55 +00003933
Daniel Veillard97b58771998-10-20 06:14:16 +00003934/**
3935 * xmlBufferWriteCHAR:
Daniel Veillard5099ae81999-04-21 20:12:07 +00003936 * @buf: the XML buffer
Daniel Veillard97b58771998-10-20 06:14:16 +00003937 * @string: the string to add
3938 *
3939 * routine which manage and grows an output buffer. This one add
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003940 * xmlChars at the end of the buffer.
Daniel Veillard97b58771998-10-20 06:14:16 +00003941 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003942void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003943xmlBufferWriteCHAR(xmlBufferPtr buf, const xmlChar *string) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003944 xmlBufferCat(buf, string);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003945}
3946
Daniel Veillard97b58771998-10-20 06:14:16 +00003947/**
3948 * xmlBufferWriteChar:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003949 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003950 * @string: the string to add
3951 *
3952 * routine which manage and grows an output buffer. This one add
3953 * C chars at the end of the array.
3954 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003955void
Daniel Veillard5099ae81999-04-21 20:12:07 +00003956xmlBufferWriteChar(xmlBufferPtr buf, const char *string) {
3957 xmlBufferCCat(buf, string);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003958}
3959
Daniel Veillard5099ae81999-04-21 20:12:07 +00003960
Daniel Veillard97b58771998-10-20 06:14:16 +00003961/**
Daniel Veillard011b63c1999-06-02 17:44:04 +00003962 * xmlBufferWriteQuotedString:
3963 * @buf: the XML buffer output
3964 * @string: the string to add
3965 *
3966 * routine which manage and grows an output buffer. This one writes
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003967 * a quoted or double quoted xmlChar string, checking first if it holds
Daniel Veillard011b63c1999-06-02 17:44:04 +00003968 * quote or double-quotes internally
3969 */
3970void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003971xmlBufferWriteQuotedString(xmlBufferPtr buf, const xmlChar *string) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00003972 if (xmlStrchr(string, '"')) {
3973 if (xmlStrchr(string, '\'')) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00003974#ifdef DEBUG_BUFFER
Daniel Veillard011b63c1999-06-02 17:44:04 +00003975 fprintf(stderr,
3976 "xmlBufferWriteQuotedString: string contains quote and double-quotes !\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00003977#endif
Daniel Veillard011b63c1999-06-02 17:44:04 +00003978 }
3979 xmlBufferCCat(buf, "'");
3980 xmlBufferCat(buf, string);
3981 xmlBufferCCat(buf, "'");
3982 } else {
3983 xmlBufferCCat(buf, "\"");
3984 xmlBufferCat(buf, string);
3985 xmlBufferCCat(buf, "\"");
3986 }
3987}
3988
3989
3990/**
Daniel Veillard97b58771998-10-20 06:14:16 +00003991 * xmlGlobalNsDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003992 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003993 * @cur: a namespace
3994 *
3995 * Dump a global Namespace, this is the old version based on PIs.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003996 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003997static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00003998xmlGlobalNsDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003999 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004000#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00004001 fprintf(stderr, "xmlGlobalNsDump : Ns == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004002#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00004003 return;
4004 }
4005 if (cur->type == XML_GLOBAL_NAMESPACE) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00004006 xmlBufferWriteChar(buf, "<?namespace");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004007 if (cur->href != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00004008 xmlBufferWriteChar(buf, " href=");
4009 xmlBufferWriteQuotedString(buf, cur->href);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004010 }
4011 if (cur->prefix != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00004012 xmlBufferWriteChar(buf, " AS=");
4013 xmlBufferWriteQuotedString(buf, cur->prefix);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004014 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00004015 xmlBufferWriteChar(buf, "?>\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004016 }
4017}
4018
Daniel Veillard97b58771998-10-20 06:14:16 +00004019/**
4020 * xmlGlobalNsListDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00004021 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00004022 * @cur: the first namespace
4023 *
4024 * Dump a list of global Namespace, this is the old version based on PIs.
Daniel Veillard260a68f1998-08-13 03:39:55 +00004025 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00004026static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00004027xmlGlobalNsListDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00004028 while (cur != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00004029 xmlGlobalNsDump(buf, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004030 cur = cur->next;
4031 }
4032}
4033
Daniel Veillard97b58771998-10-20 06:14:16 +00004034/**
4035 * xmlNsDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00004036 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00004037 * @cur: a namespace
4038 *
Daniel Veillard260a68f1998-08-13 03:39:55 +00004039 * Dump a local Namespace definition.
Daniel Veillard97b58771998-10-20 06:14:16 +00004040 * Should be called in the context of attributes dumps.
Daniel Veillard260a68f1998-08-13 03:39:55 +00004041 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00004042static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00004043xmlNsDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00004044 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004045#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00004046 fprintf(stderr, "xmlNsDump : Ns == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004047#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00004048 return;
4049 }
4050 if (cur->type == XML_LOCAL_NAMESPACE) {
4051 /* Within the context of an element attributes */
4052 if (cur->prefix != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00004053 xmlBufferWriteChar(buf, " xmlns:");
4054 xmlBufferWriteCHAR(buf, cur->prefix);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004055 } else
Daniel Veillard5099ae81999-04-21 20:12:07 +00004056 xmlBufferWriteChar(buf, " xmlns");
Daniel Veillard011b63c1999-06-02 17:44:04 +00004057 xmlBufferWriteChar(buf, "=");
4058 xmlBufferWriteQuotedString(buf, cur->href);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004059 }
4060}
4061
Daniel Veillard97b58771998-10-20 06:14:16 +00004062/**
4063 * xmlNsListDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00004064 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00004065 * @cur: the first namespace
4066 *
4067 * Dump a list of local Namespace definitions.
4068 * Should be called in the context of attributes dumps.
Daniel Veillard260a68f1998-08-13 03:39:55 +00004069 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00004070static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00004071xmlNsListDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00004072 while (cur != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00004073 xmlNsDump(buf, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004074 cur = cur->next;
4075 }
4076}
4077
Daniel Veillard97b58771998-10-20 06:14:16 +00004078/**
4079 * xmlDtdDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00004080 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00004081 * @doc: the document
4082 *
4083 * Dump the XML document DTD, if any.
Daniel Veillard260a68f1998-08-13 03:39:55 +00004084 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00004085static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00004086xmlDtdDump(xmlBufferPtr buf, xmlDocPtr doc) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004087 xmlDtdPtr cur = doc->intSubset;
Daniel Veillard260a68f1998-08-13 03:39:55 +00004088
4089 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004090#ifdef DEBUG_TREE
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004091 fprintf(stderr, "xmlDtdDump : no internal subset\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004092#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00004093 return;
4094 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00004095 xmlBufferWriteChar(buf, "<!DOCTYPE ");
4096 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004097 if (cur->ExternalID != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00004098 xmlBufferWriteChar(buf, " PUBLIC ");
4099 xmlBufferWriteQuotedString(buf, cur->ExternalID);
4100 xmlBufferWriteChar(buf, " ");
4101 xmlBufferWriteQuotedString(buf, cur->SystemID);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004102 } else if (cur->SystemID != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00004103 xmlBufferWriteChar(buf, " SYSTEM ");
4104 xmlBufferWriteQuotedString(buf, cur->SystemID);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004105 }
Daniel Veillard1e346af1999-02-22 10:33:01 +00004106 if ((cur->entities == NULL) && (cur->elements == NULL) &&
4107 (cur->attributes == NULL) && (cur->notations == NULL)) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00004108 xmlBufferWriteChar(buf, ">\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004109 return;
4110 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00004111 xmlBufferWriteChar(buf, " [\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004112 if (cur->entities != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00004113 xmlDumpEntitiesTable(buf, (xmlEntitiesTablePtr) cur->entities);
Daniel Veillard1e346af1999-02-22 10:33:01 +00004114 if (cur->notations != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00004115 xmlDumpNotationTable(buf, (xmlNotationTablePtr) cur->notations);
Daniel Veillard3b9def11999-01-31 22:15:06 +00004116 if (cur->elements != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00004117 xmlDumpElementTable(buf, (xmlElementTablePtr) cur->elements);
Daniel Veillard1e346af1999-02-22 10:33:01 +00004118 if (cur->attributes != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00004119 xmlDumpAttributeTable(buf, (xmlAttributeTablePtr) cur->attributes);
4120 xmlBufferWriteChar(buf, "]");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004121
Daniel Veillard5099ae81999-04-21 20:12:07 +00004122 xmlBufferWriteChar(buf, ">\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004123}
4124
Daniel Veillard97b58771998-10-20 06:14:16 +00004125/**
4126 * xmlAttrDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00004127 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00004128 * @doc: the document
4129 * @cur: the attribute pointer
4130 *
4131 * Dump an XML attribute
Daniel Veillard260a68f1998-08-13 03:39:55 +00004132 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00004133static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00004134xmlAttrDump(xmlBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004135 xmlChar *value;
Daniel Veillardccb09631998-10-27 06:21:04 +00004136
Daniel Veillard260a68f1998-08-13 03:39:55 +00004137 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004138#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00004139 fprintf(stderr, "xmlAttrDump : property == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004140#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00004141 return;
4142 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00004143 xmlBufferWriteChar(buf, " ");
Daniel Veillardb96e6431999-08-29 21:02:19 +00004144 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
4145 xmlBufferWriteCHAR(buf, cur->ns->prefix);
4146 xmlBufferWriteChar(buf, ":");
4147 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00004148 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillardccb09631998-10-27 06:21:04 +00004149 value = xmlNodeListGetString(doc, cur->val, 0);
4150 if (value) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00004151 xmlBufferWriteChar(buf, "=");
4152 xmlBufferWriteQuotedString(buf, value);
Daniel Veillard6454aec1999-09-02 22:04:43 +00004153 xmlFree(value);
Daniel Veillard726c7e31999-02-08 15:13:10 +00004154 } else {
Daniel Veillard5099ae81999-04-21 20:12:07 +00004155 xmlBufferWriteChar(buf, "=\"\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004156 }
4157}
4158
Daniel Veillard97b58771998-10-20 06:14:16 +00004159/**
4160 * xmlAttrListDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00004161 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00004162 * @doc: the document
4163 * @cur: the first attribute pointer
4164 *
4165 * Dump a list of XML attributes
Daniel Veillard260a68f1998-08-13 03:39:55 +00004166 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00004167static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00004168xmlAttrListDump(xmlBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00004169 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004170#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00004171 fprintf(stderr, "xmlAttrListDump : property == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004172#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00004173 return;
4174 }
4175 while (cur != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00004176 xmlAttrDump(buf, doc, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004177 cur = cur->next;
4178 }
4179}
4180
Daniel Veillard260a68f1998-08-13 03:39:55 +00004181
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00004182static void
Daniel Veillard7d2c2761999-10-11 15:09:51 +00004183xmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
4184 int format);
Daniel Veillarddbfd6411999-12-28 16:35:14 +00004185void
4186htmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur);
4187
Daniel Veillard97b58771998-10-20 06:14:16 +00004188/**
4189 * xmlNodeListDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00004190 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00004191 * @doc: the document
4192 * @cur: the first node
Daniel Veillard3e6d2372000-03-04 11:39:43 +00004193 * @level: the imbrication level for indenting, -1 to disable it
Daniel Veillard7d2c2761999-10-11 15:09:51 +00004194 * @format: is formatting allowed
Daniel Veillard97b58771998-10-20 06:14:16 +00004195 *
4196 * Dump an XML node list, recursive behaviour,children are printed too.
4197 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00004198static void
Daniel Veillard7d2c2761999-10-11 15:09:51 +00004199xmlNodeListDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
4200 int format) {
4201 int i;
Daniel Veillardccb09631998-10-27 06:21:04 +00004202
Daniel Veillard260a68f1998-08-13 03:39:55 +00004203 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004204#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00004205 fprintf(stderr, "xmlNodeListDump : node == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004206#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00004207 return;
4208 }
4209 while (cur != NULL) {
Daniel Veillard7d2c2761999-10-11 15:09:51 +00004210 if ((format) && (xmlIndentTreeOutput) &&
4211 (cur->type == XML_ELEMENT_NODE))
4212 for (i = 0;i < level;i++)
4213 xmlBufferWriteChar(buf, " ");
4214 xmlNodeDump(buf, doc, cur, level, format);
4215 if (format) {
4216 xmlBufferWriteChar(buf, "\n");
Daniel Veillardccb09631998-10-27 06:21:04 +00004217 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00004218 cur = cur->next;
4219 }
4220}
4221
Daniel Veillard97b58771998-10-20 06:14:16 +00004222/**
Daniel Veillardccb09631998-10-27 06:21:04 +00004223 * xmlNodeDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00004224 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00004225 * @doc: the document
4226 * @cur: the current node
Daniel Veillard3e6d2372000-03-04 11:39:43 +00004227 * @level: the imbrication level for indenting, -1 to disable it
Daniel Veillard7d2c2761999-10-11 15:09:51 +00004228 * @format: is formatting allowed
Daniel Veillard97b58771998-10-20 06:14:16 +00004229 *
4230 * Dump an XML node, recursive behaviour,children are printed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +00004231 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00004232static void
Daniel Veillard7d2c2761999-10-11 15:09:51 +00004233xmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
4234 int format) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00004235 int i;
Daniel Veillard7d2c2761999-10-11 15:09:51 +00004236 xmlNodePtr tmp;
Daniel Veillard260a68f1998-08-13 03:39:55 +00004237
4238 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004239#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00004240 fprintf(stderr, "xmlNodeDump : node == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004241#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00004242 return;
4243 }
Daniel Veillard0bef1311998-10-14 02:36:47 +00004244 if (cur->type == XML_TEXT_NODE) {
Daniel Veillard14fff061999-06-22 21:49:07 +00004245 if (cur->content != NULL) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004246 xmlChar *buffer;
Daniel Veillard14fff061999-06-22 21:49:07 +00004247
Daniel Veillardf5c2c871999-12-01 09:51:45 +00004248#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard14fff061999-06-22 21:49:07 +00004249 buffer = xmlEncodeEntitiesReentrant(doc, cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00004250#else
4251 buffer = xmlEncodeEntitiesReentrant(doc,
4252 xmlBufferContent(cur->content));
4253#endif
Daniel Veillard14fff061999-06-22 21:49:07 +00004254 if (buffer != NULL) {
4255 xmlBufferWriteCHAR(buf, buffer);
Daniel Veillard6454aec1999-09-02 22:04:43 +00004256 xmlFree(buffer);
Daniel Veillard14fff061999-06-22 21:49:07 +00004257 }
4258 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00004259 return;
4260 }
Daniel Veillardb96e6431999-08-29 21:02:19 +00004261 if (cur->type == XML_PI_NODE) {
4262 if (cur->content != NULL) {
4263 xmlBufferWriteChar(buf, "<?");
4264 xmlBufferWriteCHAR(buf, cur->name);
4265 if (cur->content != NULL) {
4266 xmlBufferWriteChar(buf, " ");
Daniel Veillardf5c2c871999-12-01 09:51:45 +00004267#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardb96e6431999-08-29 21:02:19 +00004268 xmlBufferWriteCHAR(buf, cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00004269#else
4270 xmlBufferWriteCHAR(buf, xmlBufferContent(cur->content));
4271#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +00004272 }
Daniel Veillard7d2c2761999-10-11 15:09:51 +00004273 xmlBufferWriteChar(buf, "?>");
Daniel Veillardb96e6431999-08-29 21:02:19 +00004274 }
4275 return;
4276 }
Daniel Veillard0bef1311998-10-14 02:36:47 +00004277 if (cur->type == XML_COMMENT_NODE) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00004278 if (cur->content != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00004279 xmlBufferWriteChar(buf, "<!--");
Daniel Veillardf5c2c871999-12-01 09:51:45 +00004280#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard5099ae81999-04-21 20:12:07 +00004281 xmlBufferWriteCHAR(buf, cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00004282#else
4283 xmlBufferWriteCHAR(buf, xmlBufferContent(cur->content));
4284#endif
Daniel Veillard7d2c2761999-10-11 15:09:51 +00004285 xmlBufferWriteChar(buf, "-->");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004286 }
4287 return;
4288 }
Daniel Veillardccb09631998-10-27 06:21:04 +00004289 if (cur->type == XML_ENTITY_REF_NODE) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00004290 xmlBufferWriteChar(buf, "&");
4291 xmlBufferWriteCHAR(buf, cur->name);
4292 xmlBufferWriteChar(buf, ";");
Daniel Veillardccb09631998-10-27 06:21:04 +00004293 return;
4294 }
Daniel Veillardb05deb71999-08-10 19:04:08 +00004295 if (cur->type == XML_CDATA_SECTION_NODE) {
4296 xmlBufferWriteChar(buf, "<![CDATA[");
4297 if (cur->content != NULL)
Daniel Veillardf5c2c871999-12-01 09:51:45 +00004298#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardb05deb71999-08-10 19:04:08 +00004299 xmlBufferWriteCHAR(buf, cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00004300#else
4301 xmlBufferWriteCHAR(buf, xmlBufferContent(cur->content));
4302#endif
Daniel Veillardb05deb71999-08-10 19:04:08 +00004303 xmlBufferWriteChar(buf, "]]>");
4304 return;
4305 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00004306
Daniel Veillard7d2c2761999-10-11 15:09:51 +00004307 if (format == 1) {
4308 tmp = cur->childs;
4309 while (tmp != NULL) {
4310 if ((tmp->type == XML_TEXT_NODE) ||
4311 (tmp->type == XML_ENTITY_REF_NODE)) {
4312 format = 0;
4313 break;
4314 }
4315 tmp = tmp->next;
4316 }
4317 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00004318 xmlBufferWriteChar(buf, "<");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004319 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00004320 xmlBufferWriteCHAR(buf, cur->ns->prefix);
4321 xmlBufferWriteChar(buf, ":");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004322 }
4323
Daniel Veillard5099ae81999-04-21 20:12:07 +00004324 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004325 if (cur->nsDef)
Daniel Veillard5099ae81999-04-21 20:12:07 +00004326 xmlNsListDump(buf, cur->nsDef);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004327 if (cur->properties != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00004328 xmlAttrListDump(buf, doc, cur->properties);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004329
Daniel Veillarde41f2b72000-01-30 20:00:07 +00004330 if ((cur->content == NULL) && (cur->childs == NULL) &&
4331 (!xmlSaveNoEmptyTags)) {
Daniel Veillard7d2c2761999-10-11 15:09:51 +00004332 xmlBufferWriteChar(buf, "/>");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004333 return;
4334 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00004335 xmlBufferWriteChar(buf, ">");
Daniel Veillard14fff061999-06-22 21:49:07 +00004336 if (cur->content != NULL) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004337 xmlChar *buffer;
Daniel Veillard14fff061999-06-22 21:49:07 +00004338
Daniel Veillardf5c2c871999-12-01 09:51:45 +00004339#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard14fff061999-06-22 21:49:07 +00004340 buffer = xmlEncodeEntitiesReentrant(doc, cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00004341#else
4342 buffer = xmlEncodeEntitiesReentrant(doc,
4343 xmlBufferContent(cur->content));
4344#endif
Daniel Veillard14fff061999-06-22 21:49:07 +00004345 if (buffer != NULL) {
4346 xmlBufferWriteCHAR(buf, buffer);
Daniel Veillard6454aec1999-09-02 22:04:43 +00004347 xmlFree(buffer);
Daniel Veillard14fff061999-06-22 21:49:07 +00004348 }
4349 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00004350 if (cur->childs != NULL) {
Daniel Veillard7d2c2761999-10-11 15:09:51 +00004351 if (format) xmlBufferWriteChar(buf, "\n");
Daniel Veillard3e6d2372000-03-04 11:39:43 +00004352 xmlNodeListDump(buf, doc, cur->childs,
4353 (level >= 0?level+1:-1), format);
Daniel Veillard7d2c2761999-10-11 15:09:51 +00004354 if ((xmlIndentTreeOutput) && (format))
4355 for (i = 0;i < level;i++)
4356 xmlBufferWriteChar(buf, " ");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004357 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00004358 xmlBufferWriteChar(buf, "</");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004359 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00004360 xmlBufferWriteCHAR(buf, cur->ns->prefix);
4361 xmlBufferWriteChar(buf, ":");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004362 }
4363
Daniel Veillard5099ae81999-04-21 20:12:07 +00004364 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillard7d2c2761999-10-11 15:09:51 +00004365 xmlBufferWriteChar(buf, ">");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004366}
4367
Daniel Veillard97b58771998-10-20 06:14:16 +00004368/**
Daniel Veillarddbfd6411999-12-28 16:35:14 +00004369 * xmlElemDump:
4370 * @buf: the XML buffer output
4371 * @doc: the document
4372 * @cur: the current node
4373 *
4374 * Dump an XML/HTML node, recursive behaviour,children are printed too.
4375 */
4376void
4377xmlElemDump(FILE *f, xmlDocPtr doc, xmlNodePtr cur) {
4378 xmlBufferPtr buf;
4379
4380 if (cur == NULL) {
4381#ifdef DEBUG_TREE
4382 fprintf(stderr, "xmlElemDump : cur == NULL\n");
4383#endif
4384 return;
4385 }
4386 if (doc == NULL) {
4387#ifdef DEBUG_TREE
4388 fprintf(stderr, "xmlElemDump : doc == NULL\n");
4389#endif
4390 }
4391 buf = xmlBufferCreate();
4392 if (buf == NULL) return;
4393 if ((doc != NULL) &&
4394 (doc->type == XML_HTML_DOCUMENT_NODE)) {
4395 htmlNodeDump(buf, doc, cur);
4396 } else
4397 xmlNodeDump(buf, doc, cur, 0, 1);
4398 xmlBufferDump(f, buf);
4399 xmlBufferFree(buf);
4400}
4401
4402/**
Daniel Veillard97b58771998-10-20 06:14:16 +00004403 * xmlDocContentDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00004404 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00004405 * @cur: the document
4406 *
4407 * Dump an XML document.
Daniel Veillard260a68f1998-08-13 03:39:55 +00004408 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00004409static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00004410xmlDocContentDump(xmlBufferPtr buf, xmlDocPtr cur) {
Daniel Veillardbe70ff71999-07-05 16:50:46 +00004411 xmlBufferWriteChar(buf, "<?xml version=");
4412 if (cur->version != NULL)
4413 xmlBufferWriteQuotedString(buf, cur->version);
4414 else
4415 xmlBufferWriteChar(buf, "\"1.0\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004416 if (cur->encoding != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00004417 xmlBufferWriteChar(buf, " encoding=");
4418 xmlBufferWriteQuotedString(buf, cur->encoding);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004419 }
4420 switch (cur->standalone) {
4421 case 0:
Daniel Veillard5099ae81999-04-21 20:12:07 +00004422 xmlBufferWriteChar(buf, " standalone=\"no\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004423 break;
4424 case 1:
Daniel Veillard5099ae81999-04-21 20:12:07 +00004425 xmlBufferWriteChar(buf, " standalone=\"yes\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004426 break;
4427 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00004428 xmlBufferWriteChar(buf, "?>\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004429 if (cur->intSubset != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00004430 xmlDtdDump(buf, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004431 if (cur->root != NULL) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00004432 xmlNodePtr child = cur->root;
4433
Daniel Veillard260a68f1998-08-13 03:39:55 +00004434 /* global namespace definitions, the old way */
4435 if (oldXMLWDcompatibility)
Daniel Veillard5099ae81999-04-21 20:12:07 +00004436 xmlGlobalNsListDump(buf, cur->oldNs);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004437 else
4438 xmlUpgradeOldNs(cur);
Daniel Veillardb96e6431999-08-29 21:02:19 +00004439
4440 while (child != NULL) {
Daniel Veillard7d2c2761999-10-11 15:09:51 +00004441 xmlNodeDump(buf, cur, child, 0, 1);
4442 xmlBufferWriteChar(buf, "\n");
Daniel Veillardb96e6431999-08-29 21:02:19 +00004443 child = child->next;
4444 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00004445 }
4446}
4447
Daniel Veillard97b58771998-10-20 06:14:16 +00004448/**
4449 * xmlDocDumpMemory:
4450 * @cur: the document
4451 * @mem: OUT: the memory pointer
4452 * @size: OUT: the memory lenght
4453 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004454 * Dump an XML document in memory and return the xmlChar * and it's size.
Daniel Veillard97b58771998-10-20 06:14:16 +00004455 * It's up to the caller to free the memory.
Daniel Veillard260a68f1998-08-13 03:39:55 +00004456 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00004457void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004458xmlDocDumpMemory(xmlDocPtr cur, xmlChar**mem, int *size) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00004459 xmlBufferPtr buf;
4460
Daniel Veillard260a68f1998-08-13 03:39:55 +00004461 if (cur == NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004462#ifdef DEBUG_TREE
4463 fprintf(stderr, "xmlDocDumpMemory : document == NULL\n");
4464#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00004465 *mem = NULL;
4466 *size = 0;
4467 return;
4468 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00004469 buf = xmlBufferCreate();
4470 if (buf == NULL) {
4471 *mem = NULL;
4472 *size = 0;
4473 return;
4474 }
4475 xmlDocContentDump(buf, cur);
Daniel Veillardb05deb71999-08-10 19:04:08 +00004476 *mem = xmlStrndup(buf->content, buf->use);
Daniel Veillard5099ae81999-04-21 20:12:07 +00004477 *size = buf->use;
Daniel Veillardb05deb71999-08-10 19:04:08 +00004478 xmlBufferFree(buf);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004479}
4480
Daniel Veillard97b58771998-10-20 06:14:16 +00004481/**
4482 * xmlGetDocCompressMode:
4483 * @doc: the document
4484 *
4485 * get the compression ratio for a document, ZLIB based
Daniel Veillard1e346af1999-02-22 10:33:01 +00004486 * Returns 0 (uncompressed) to 9 (max compression)
Daniel Veillard151b1b01998-09-23 00:49:46 +00004487 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00004488int
Daniel Veillarddbfd6411999-12-28 16:35:14 +00004489xmlGetDocCompressMode (xmlDocPtr doc) {
Daniel Veillard15a8df41998-09-24 19:15:06 +00004490 if (doc == NULL) return(-1);
4491 return(doc->compression);
4492}
4493
Daniel Veillard97b58771998-10-20 06:14:16 +00004494/**
4495 * xmlSetDocCompressMode:
4496 * @doc: the document
4497 * @mode: the compression ratio
4498 *
4499 * set the compression ratio for a document, ZLIB based
4500 * Correct values: 0 (uncompressed) to 9 (max compression)
4501 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00004502void
4503xmlSetDocCompressMode (xmlDocPtr doc, int mode) {
Daniel Veillard15a8df41998-09-24 19:15:06 +00004504 if (doc == NULL) return;
4505 if (mode < 0) doc->compression = 0;
4506 else if (mode > 9) doc->compression = 9;
4507 else doc->compression = mode;
4508}
4509
Daniel Veillard97b58771998-10-20 06:14:16 +00004510/**
4511 * xmlGetCompressMode:
4512 *
4513 * get the default compression mode used, ZLIB based.
Daniel Veillard1e346af1999-02-22 10:33:01 +00004514 * Returns 0 (uncompressed) to 9 (max compression)
Daniel Veillard15a8df41998-09-24 19:15:06 +00004515 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00004516int
4517 xmlGetCompressMode(void) {
Daniel Veillard151b1b01998-09-23 00:49:46 +00004518 return(xmlCompressMode);
4519}
Daniel Veillard97b58771998-10-20 06:14:16 +00004520
4521/**
4522 * xmlSetCompressMode:
4523 * @mode: the compression ratio
4524 *
4525 * set the default compression mode used, ZLIB based
4526 * Correct values: 0 (uncompressed) to 9 (max compression)
4527 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00004528void
4529xmlSetCompressMode(int mode) {
Daniel Veillard151b1b01998-09-23 00:49:46 +00004530 if (mode < 0) xmlCompressMode = 0;
Daniel Veillard15a8df41998-09-24 19:15:06 +00004531 else if (mode > 9) xmlCompressMode = 9;
Daniel Veillard151b1b01998-09-23 00:49:46 +00004532 else xmlCompressMode = mode;
4533}
4534
Daniel Veillard97b58771998-10-20 06:14:16 +00004535/**
4536 * xmlDocDump:
4537 * @f: the FILE*
4538 * @cur: the document
4539 *
4540 * Dump an XML document to an open FILE.
Daniel Veillard260a68f1998-08-13 03:39:55 +00004541 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00004542void
4543xmlDocDump(FILE *f, xmlDocPtr cur) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00004544 xmlBufferPtr buf;
4545
Daniel Veillard260a68f1998-08-13 03:39:55 +00004546 if (cur == NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004547#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00004548 fprintf(stderr, "xmlDocDump : document == NULL\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004549#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00004550 return;
4551 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00004552 buf = xmlBufferCreate();
4553 if (buf == NULL) return;
4554 xmlDocContentDump(buf, cur);
4555 xmlBufferDump(f, buf);
4556 xmlBufferFree(buf);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004557}
4558
Daniel Veillard97b58771998-10-20 06:14:16 +00004559/**
4560 * xmlSaveFile:
4561 * @filename: the filename
4562 * @cur: the document
4563 *
4564 * Dump an XML document to a file. Will use compression if
Daniel Veillard11a48ec1999-11-23 10:40:46 +00004565 * compiled in and enabled. If @filename is "-" the stdout file is
4566 * used.
Daniel Veillard97b58771998-10-20 06:14:16 +00004567 * returns: the number of file written or -1 in case of failure.
Daniel Veillard151b1b01998-09-23 00:49:46 +00004568 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00004569int
4570xmlSaveFile(const char *filename, xmlDocPtr cur) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00004571 xmlBufferPtr buf;
Daniel Veillard151b1b01998-09-23 00:49:46 +00004572#ifdef HAVE_ZLIB_H
4573 gzFile zoutput = NULL;
4574 char mode[15];
4575#endif
Daniel Veillardccb09631998-10-27 06:21:04 +00004576 FILE *output = NULL;
Daniel Veillard151b1b01998-09-23 00:49:46 +00004577 int ret;
4578
Daniel Veillard5099ae81999-04-21 20:12:07 +00004579 /*
4580 * save the content to a temp buffer.
4581 */
4582 buf = xmlBufferCreate();
4583 if (buf == NULL) return(0);
4584 xmlDocContentDump(buf, cur);
4585
Daniel Veillard151b1b01998-09-23 00:49:46 +00004586#ifdef HAVE_ZLIB_H
Daniel Veillard11a48ec1999-11-23 10:40:46 +00004587 if (cur->compression < 0) cur->compression = xmlCompressMode;
Daniel Veillarddc3dd9d1998-09-24 19:25:54 +00004588 if ((cur->compression > 0) && (cur->compression <= 9)) {
4589 sprintf(mode, "w%d", cur->compression);
Daniel Veillard11a48ec1999-11-23 10:40:46 +00004590 if (!strcmp(filename, "-"))
4591 zoutput = gzdopen(1, mode);
4592 else
4593 zoutput = gzopen(filename, mode);
Daniel Veillard151b1b01998-09-23 00:49:46 +00004594 }
4595 if (zoutput == NULL) {
4596#endif
4597 output = fopen(filename, "w");
Daniel Veillard10a2c651999-12-12 13:03:50 +00004598 if (output == NULL) {
4599 xmlBufferFree(buf);
4600 return(-1);
4601 }
Daniel Veillard151b1b01998-09-23 00:49:46 +00004602#ifdef HAVE_ZLIB_H
4603 }
Daniel Veillard151b1b01998-09-23 00:49:46 +00004604
Daniel Veillard151b1b01998-09-23 00:49:46 +00004605 if (zoutput != NULL) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004606 ret = gzwrite(zoutput, buf->content, sizeof(xmlChar) * buf->use);
Daniel Veillard151b1b01998-09-23 00:49:46 +00004607 gzclose(zoutput);
Daniel Veillard5099ae81999-04-21 20:12:07 +00004608 } else {
4609#endif
4610 ret = xmlBufferDump(output, buf);
4611 fclose(output);
4612#ifdef HAVE_ZLIB_H
Daniel Veillard151b1b01998-09-23 00:49:46 +00004613 }
4614#endif
Manish Vachharajani5e60f5a1999-05-29 03:04:30 +00004615 xmlBufferFree(buf);
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004616 return(ret * sizeof(xmlChar));
Daniel Veillard151b1b01998-09-23 00:49:46 +00004617}
4618