blob: 466c11f35de6eaef1e9752ffd6912960b7bb9997 [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 Veillard15a8df41998-09-24 19:15:06 +000042
Daniel Veillard39a1f9a1999-01-17 19:11:59 +000043#define UPDATE_LAST_CHILD(n) if ((n) != NULL) { \
44 xmlNodePtr ulccur = (n)->childs; \
45 if (ulccur == NULL) { \
46 (n)->last = NULL; \
47 } else { \
48 while (ulccur->next != NULL) ulccur = ulccur->next; \
49 (n)->last = ulccur; \
Daniel Veillard1e346af1999-02-22 10:33:01 +000050}}
Daniel Veillard39a1f9a1999-01-17 19:11:59 +000051
Daniel Veillardad8f99d2000-01-15 14:20:03 +000052/* #define DEBUG_BUFFER */
53/* #define DEBUG_TREE */
54
Daniel Veillard260a68f1998-08-13 03:39:55 +000055/************************************************************************
56 * *
57 * Allocation and deallocation of basic structures *
58 * *
59 ************************************************************************/
60
Daniel Veillard97b58771998-10-20 06:14:16 +000061/**
Daniel Veillardf5c2c871999-12-01 09:51:45 +000062 * xmlSetBufferAllocationScheme:
63 * @scheme: allocation method to use
64 *
65 * Set the buffer allocation method. Types are
66 * XML_BUFFER_ALLOC_EXACT - use exact sizes, keeps memory usage down
67 * XML_BUFFER_ALLOC_DOUBLEIT - double buffer when extra needed,
68 * improves performance
69 */
70void
71xmlSetBufferAllocationScheme(xmlBufferAllocationScheme scheme) {
72 xmlBufferAllocScheme = scheme;
73}
74
75/**
76 * xmlGetBufferAllocationScheme:
77 *
78 * Types are
79 * XML_BUFFER_ALLOC_EXACT - use exact sizes, keeps memory usage down
80 * XML_BUFFER_ALLOC_DOUBLEIT - double buffer when extra needed,
81 * improves performance
82 *
83 * Returns the current allocation scheme
84 */
85xmlBufferAllocationScheme
86xmlGetBufferAllocationScheme() {
87 return xmlBufferAllocScheme;
88}
89
90/**
Daniel Veillard97b58771998-10-20 06:14:16 +000091 * xmlUpgradeOldNs:
92 * @doc: a document pointer
93 *
94 * Upgrade old style Namespaces (PI) and move them to the root of the document.
Daniel Veillard260a68f1998-08-13 03:39:55 +000095 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +000096void
97xmlUpgradeOldNs(xmlDocPtr doc) {
Daniel Veillard260a68f1998-08-13 03:39:55 +000098 xmlNsPtr cur;
99
100 if ((doc == NULL) || (doc->oldNs == NULL)) return;
101 if (doc->root == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000102#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +0000103 fprintf(stderr, "xmlUpgradeOldNs: failed no root !\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000104#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000105 return;
106 }
107
108 cur = doc->oldNs;
109 while (cur->next != NULL) {
110 cur->type = XML_LOCAL_NAMESPACE;
111 cur = cur->next;
112 }
113 cur->type = XML_LOCAL_NAMESPACE;
114 cur->next = doc->root->nsDef;
115 doc->root->nsDef = doc->oldNs;
116 doc->oldNs = NULL;
117}
118
Daniel Veillard97b58771998-10-20 06:14:16 +0000119/**
120 * xmlNewNs:
121 * @node: the element carrying the namespace
122 * @href: the URI associated
123 * @prefix: the prefix for the namespace
124 *
Daniel Veillard686d6b62000-01-03 11:08:02 +0000125 * Creation of a new Namespace. This function will refuse to create
126 * a namespace with a similar prefix than an existing one present on this
127 * node.
128 * Returns returns a new namespace pointer or NULL
Daniel Veillard260a68f1998-08-13 03:39:55 +0000129 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000130xmlNsPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000131xmlNewNs(xmlNodePtr node, const xmlChar *href, const xmlChar *prefix) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000132 xmlNsPtr cur;
133
134 if (href == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000135#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +0000136 fprintf(stderr, "xmlNewNs: href == NULL !\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000137#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000138 return(NULL);
139 }
140
141 /*
142 * Allocate a new DTD and fill the fields.
143 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000144 cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000145 if (cur == NULL) {
146 fprintf(stderr, "xmlNewNs : malloc failed\n");
147 return(NULL);
148 }
149
150 cur->type = XML_LOCAL_NAMESPACE;
151 if (href != NULL)
152 cur->href = xmlStrdup(href);
153 else
154 cur->href = NULL;
155 if (prefix != NULL)
156 cur->prefix = xmlStrdup(prefix);
157 else
158 cur->prefix = NULL;
159
160 /*
161 * Add it at the end to preserve parsing order ...
Daniel Veillard686d6b62000-01-03 11:08:02 +0000162 * and checks for existing use of the prefix
Daniel Veillard260a68f1998-08-13 03:39:55 +0000163 */
164 cur->next = NULL;
165 if (node != NULL) {
166 if (node->nsDef == NULL) {
167 node->nsDef = cur;
168 } else {
169 xmlNsPtr prev = node->nsDef;
170
Daniel Veillard0142b842000-01-14 14:45:24 +0000171 if (((prev->prefix == NULL) && (cur->prefix == NULL)) ||
172 (!xmlStrcmp(prev->prefix, cur->prefix))) {
173 xmlFreeNs(cur);
174 return(NULL);
175 }
Daniel Veillard686d6b62000-01-03 11:08:02 +0000176 while (prev->next != NULL) {
Daniel Veillard0142b842000-01-14 14:45:24 +0000177 prev = prev->next;
Daniel Veillard686d6b62000-01-03 11:08:02 +0000178 if (((prev->prefix == NULL) && (cur->prefix == NULL)) ||
179 (!xmlStrcmp(prev->prefix, cur->prefix))) {
180 xmlFreeNs(cur);
181 return(NULL);
182 }
Daniel Veillard686d6b62000-01-03 11:08:02 +0000183 }
Daniel Veillard260a68f1998-08-13 03:39:55 +0000184 prev->next = cur;
185 }
186 }
Daniel Veillard260a68f1998-08-13 03:39:55 +0000187 return(cur);
188}
189
Daniel Veillard97b58771998-10-20 06:14:16 +0000190/**
191 * xmlNewGlobalNs:
192 * @doc: the document carrying the namespace
193 * @href: the URI associated
194 * @prefix: the prefix for the namespace
195 *
Daniel Veillard686d6b62000-01-03 11:08:02 +0000196 * Creation of a Namespace, the old way using PI and without scoping
197 * DEPRECATED !!!
Daniel Veillard0142b842000-01-14 14:45:24 +0000198 * It now create a namespace on the root element of the document if found.
Daniel Veillard686d6b62000-01-03 11:08:02 +0000199 * Returns NULL this functionnality had been removed
Daniel Veillard260a68f1998-08-13 03:39:55 +0000200 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000201xmlNsPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000202xmlNewGlobalNs(xmlDocPtr doc, const xmlChar *href, const xmlChar *prefix) {
Daniel Veillard0142b842000-01-14 14:45:24 +0000203 xmlNodePtr root;
204
205 xmlNsPtr cur;
206
207 root = xmlDocGetRootElement(doc);
208 if (root != NULL)
209 return(xmlNewNs(root, href, prefix));
210
211 /*
212 * if there is no root element yet, create an old Namespace type
213 * and it will be moved to the root at save time.
214 */
215 cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
216 if (cur == NULL) {
217 fprintf(stderr, "xmlNewGlobalNs : malloc failed\n");
218 return(NULL);
219 }
220
221 cur->type = XML_GLOBAL_NAMESPACE;
222 if (href != NULL)
223 cur->href = xmlStrdup(href);
224 else
225 cur->href = NULL;
226 if (prefix != NULL)
227 cur->prefix = xmlStrdup(prefix);
228 else
229 cur->prefix = NULL;
230
231 /*
232 * Add it at the end to preserve parsing order ...
233 */
234 cur->next = NULL;
235 if (doc != NULL) {
236 if (doc->oldNs == NULL) {
237 doc->oldNs = cur;
238 } else {
239 xmlNsPtr prev = doc->oldNs;
240
241 while (prev->next != NULL) prev = prev->next;
242 prev->next = cur;
243 }
244 }
245
246 return(NULL);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000247}
248
Daniel Veillard97b58771998-10-20 06:14:16 +0000249/**
250 * xmlSetNs:
251 * @node: a node in the document
252 * @ns: a namespace pointer
253 *
254 * Associate a namespace to a node, a posteriori.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000255 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000256void
257xmlSetNs(xmlNodePtr node, xmlNsPtr ns) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000258 if (node == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000259#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +0000260 fprintf(stderr, "xmlSetNs: node == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000261#else
Daniel Veillard260a68f1998-08-13 03:39:55 +0000262 return;
263 }
264 node->ns = ns;
265}
266
Daniel Veillard97b58771998-10-20 06:14:16 +0000267/**
268 * xmlFreeNs:
269 * @cur: the namespace pointer
270 *
271 * Free up the structures associated to a namespace
Daniel Veillard260a68f1998-08-13 03:39:55 +0000272 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000273void
274xmlFreeNs(xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000275 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000276#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +0000277 fprintf(stderr, "xmlFreeNs : ns == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000278#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000279 return;
280 }
Daniel Veillard6454aec1999-09-02 22:04:43 +0000281 if (cur->href != NULL) xmlFree((char *) cur->href);
282 if (cur->prefix != NULL) xmlFree((char *) cur->prefix);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000283 memset(cur, -1, sizeof(xmlNs));
Daniel Veillard6454aec1999-09-02 22:04:43 +0000284 xmlFree(cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000285}
286
Daniel Veillard97b58771998-10-20 06:14:16 +0000287/**
288 * xmlFreeNsList:
289 * @cur: the first namespace pointer
290 *
291 * Free up all the structures associated to the chained namespaces.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000292 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000293void
294xmlFreeNsList(xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000295 xmlNsPtr next;
296 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000297#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +0000298 fprintf(stderr, "xmlFreeNsList : ns == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000299#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000300 return;
301 }
302 while (cur != NULL) {
303 next = cur->next;
304 xmlFreeNs(cur);
305 cur = next;
306 }
307}
308
Daniel Veillard97b58771998-10-20 06:14:16 +0000309/**
310 * xmlNewDtd:
311 * @doc: the document pointer
312 * @name: the DTD name
313 * @ExternalID: the external ID
314 * @SystemID: the system ID
315 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000316 * Creation of a new DTD.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000317 * Returns a pointer to the new DTD structure
Daniel Veillard260a68f1998-08-13 03:39:55 +0000318 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000319xmlDtdPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000320xmlNewDtd(xmlDocPtr doc, const xmlChar *name,
321 const xmlChar *ExternalID, const xmlChar *SystemID) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000322 xmlDtdPtr cur;
323
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000324 if ((doc != NULL) && (doc->extSubset != NULL)) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000325#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +0000326 fprintf(stderr, "xmlNewDtd(%s): document %s already have a DTD %s\n",
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000327 /* !!! */ (char *) name, doc->name,
328 /* !!! */ (char *)doc->extSubset->name);
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000329#endif
330 return(NULL);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000331 }
332
333 /*
334 * Allocate a new DTD and fill the fields.
335 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000336 cur = (xmlDtdPtr) xmlMalloc(sizeof(xmlDtd));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000337 if (cur == NULL) {
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000338 fprintf(stderr, "xmlNewDtd : malloc failed\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +0000339 return(NULL);
340 }
341
342 if (name != NULL)
343 cur->name = xmlStrdup(name);
344 else
345 cur->name = NULL;
346 if (ExternalID != NULL)
347 cur->ExternalID = xmlStrdup(ExternalID);
348 else
349 cur->ExternalID = NULL;
350 if (SystemID != NULL)
351 cur->SystemID = xmlStrdup(SystemID);
352 else
353 cur->SystemID = NULL;
Daniel Veillard1e346af1999-02-22 10:33:01 +0000354 cur->notations = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000355 cur->elements = NULL;
Daniel Veillard1e346af1999-02-22 10:33:01 +0000356 cur->attributes = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000357 cur->entities = NULL;
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000358 if (doc != NULL)
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000359 doc->extSubset = cur;
360
361 return(cur);
362}
363
364/**
365 * xmlCreateIntSubset:
366 * @doc: the document pointer
367 * @name: the DTD name
368 * @ExternalID: the external ID
369 * @SystemID: the system ID
370 *
Daniel Veillard1e346af1999-02-22 10:33:01 +0000371 * Create the internal subset of a document
372 * Returns a pointer to the new DTD structure
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000373 */
374xmlDtdPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000375xmlCreateIntSubset(xmlDocPtr doc, const xmlChar *name,
376 const xmlChar *ExternalID, const xmlChar *SystemID) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000377 xmlDtdPtr cur;
378
379 if ((doc != NULL) && (doc->intSubset != NULL)) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000380#ifdef DEBUG_TREE
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000381 fprintf(stderr,
382 "xmlCreateIntSubset(): document %s already have an internal subset\n",
383 doc->name);
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000384#endif
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000385 return(NULL);
386 }
387
388 /*
389 * Allocate a new DTD and fill the fields.
390 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000391 cur = (xmlDtdPtr) xmlMalloc(sizeof(xmlDtd));
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000392 if (cur == NULL) {
393 fprintf(stderr, "xmlNewDtd : malloc failed\n");
394 return(NULL);
395 }
396
397 if (name != NULL)
398 cur->name = xmlStrdup(name);
399 else
400 cur->name = NULL;
401 if (ExternalID != NULL)
402 cur->ExternalID = xmlStrdup(ExternalID);
403 else
404 cur->ExternalID = NULL;
405 if (SystemID != NULL)
406 cur->SystemID = xmlStrdup(SystemID);
407 else
408 cur->SystemID = NULL;
Daniel Veillard1e346af1999-02-22 10:33:01 +0000409 cur->notations = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000410 cur->elements = NULL;
Daniel Veillard1e346af1999-02-22 10:33:01 +0000411 cur->attributes = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000412 cur->entities = NULL;
413 if (doc != NULL)
414 doc->intSubset = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000415
416 return(cur);
417}
418
Daniel Veillard97b58771998-10-20 06:14:16 +0000419/**
420 * xmlFreeDtd:
421 * @cur: the DTD structure to free up
422 *
423 * Free a DTD structure.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000424 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000425void
426xmlFreeDtd(xmlDtdPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000427 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000428#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +0000429 fprintf(stderr, "xmlFreeDtd : DTD == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000430#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000431 return;
432 }
Daniel Veillard6454aec1999-09-02 22:04:43 +0000433 if (cur->name != NULL) xmlFree((char *) cur->name);
434 if (cur->SystemID != NULL) xmlFree((char *) cur->SystemID);
435 if (cur->ExternalID != NULL) xmlFree((char *) cur->ExternalID);
Daniel Veillard1e346af1999-02-22 10:33:01 +0000436 if (cur->notations != NULL)
437 xmlFreeNotationTable((xmlNotationTablePtr) cur->notations);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000438 if (cur->elements != NULL)
Daniel Veillard3b9def11999-01-31 22:15:06 +0000439 xmlFreeElementTable((xmlElementTablePtr) cur->elements);
Daniel Veillard1e346af1999-02-22 10:33:01 +0000440 if (cur->attributes != NULL)
441 xmlFreeAttributeTable((xmlAttributeTablePtr) cur->attributes);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000442 if (cur->entities != NULL)
443 xmlFreeEntitiesTable((xmlEntitiesTablePtr) cur->entities);
444 memset(cur, -1, sizeof(xmlDtd));
Daniel Veillard6454aec1999-09-02 22:04:43 +0000445 xmlFree(cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000446}
447
Daniel Veillard97b58771998-10-20 06:14:16 +0000448/**
449 * xmlNewDoc:
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000450 * @version: xmlChar string giving the version of XML "1.0"
Daniel Veillard97b58771998-10-20 06:14:16 +0000451 *
Daniel Veillard1e346af1999-02-22 10:33:01 +0000452 * Returns a new document
Daniel Veillard260a68f1998-08-13 03:39:55 +0000453 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000454xmlDocPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000455xmlNewDoc(const xmlChar *version) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000456 xmlDocPtr cur;
457
458 if (version == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000459#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +0000460 fprintf(stderr, "xmlNewDoc : version == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000461#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000462 return(NULL);
463 }
464
465 /*
466 * Allocate a new document and fill the fields.
467 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000468 cur = (xmlDocPtr) xmlMalloc(sizeof(xmlDoc));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000469 if (cur == NULL) {
470 fprintf(stderr, "xmlNewDoc : malloc failed\n");
471 return(NULL);
472 }
473
Daniel Veillard33942841998-10-18 19:12:41 +0000474 cur->type = XML_DOCUMENT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000475 cur->version = xmlStrdup(version);
476 cur->name = NULL;
477 cur->root = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000478 cur->intSubset = NULL;
479 cur->extSubset = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000480 cur->oldNs = NULL;
481 cur->encoding = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000482 cur->standalone = -1;
Daniel Veillard11a48ec1999-11-23 10:40:46 +0000483 cur->compression = -1; /* not initialized */
Daniel Veillardb96e6431999-08-29 21:02:19 +0000484 cur->ids = NULL;
Daniel Veillardc08a2c61999-09-08 21:35:25 +0000485 cur->refs = NULL;
Daniel Veillard27d88741999-05-29 11:51:49 +0000486#ifndef XML_WITHOUT_CORBA
Daniel Veillard27fb0751998-10-17 06:47:46 +0000487 cur->_private = NULL;
488 cur->vepv = NULL;
489#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000490 return(cur);
491}
492
Daniel Veillard97b58771998-10-20 06:14:16 +0000493/**
494 * xmlFreeDoc:
495 * @cur: pointer to the document
496 * @:
497 *
498 * Free up all the structures used by a document, tree included.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000499 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000500void
501xmlFreeDoc(xmlDocPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000502 if (cur == NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000503#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +0000504 fprintf(stderr, "xmlFreeDoc : document == NULL\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000505#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000506 return;
507 }
Daniel Veillard6454aec1999-09-02 22:04:43 +0000508 if (cur->version != NULL) xmlFree((char *) cur->version);
509 if (cur->name != NULL) xmlFree((char *) cur->name);
510 if (cur->encoding != NULL) xmlFree((char *) cur->encoding);
511 if (cur->root != NULL) xmlFreeNodeList(cur->root);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000512 if (cur->intSubset != NULL) xmlFreeDtd(cur->intSubset);
513 if (cur->extSubset != NULL) xmlFreeDtd(cur->extSubset);
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000514 if (cur->oldNs != NULL) xmlFreeNsList(cur->oldNs);
Daniel Veillardb96e6431999-08-29 21:02:19 +0000515 if (cur->ids != NULL) xmlFreeIDTable((xmlIDTablePtr) cur->ids);
Daniel Veillardc08a2c61999-09-08 21:35:25 +0000516 if (cur->refs != NULL) xmlFreeRefTable((xmlRefTablePtr) cur->refs);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000517 memset(cur, -1, sizeof(xmlDoc));
Daniel Veillard6454aec1999-09-02 22:04:43 +0000518 xmlFree(cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000519}
520
Daniel Veillard97b58771998-10-20 06:14:16 +0000521/**
Daniel Veillard16253641998-10-28 22:58:05 +0000522 * xmlStringLenGetNodeList:
523 * @doc: the document
524 * @value: the value of the text
Daniel Veillard1e346af1999-02-22 10:33:01 +0000525 * @len: the length of the string value
Daniel Veillard16253641998-10-28 22:58:05 +0000526 *
527 * Parse the value string and build the node list associated. Should
528 * produce a flat tree with only TEXTs and ENTITY_REFs.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000529 * Returns a pointer to the first child
Daniel Veillard16253641998-10-28 22:58:05 +0000530 */
531xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000532xmlStringLenGetNodeList(xmlDocPtr doc, const xmlChar *value, int len) {
Daniel Veillard16253641998-10-28 22:58:05 +0000533 xmlNodePtr ret = NULL, last = NULL;
534 xmlNodePtr node;
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000535 xmlChar *val;
536 const xmlChar *cur = value;
537 const xmlChar *q;
Daniel Veillard25940b71998-10-29 05:51:30 +0000538 xmlEntityPtr ent;
Daniel Veillard16253641998-10-28 22:58:05 +0000539
540 if (value == NULL) return(NULL);
541
542 q = cur;
543 while ((*cur != 0) && (cur - value < len)) {
544 if (*cur == '&') {
Daniel Veillard25940b71998-10-29 05:51:30 +0000545 /*
546 * Save the current text.
547 */
Daniel Veillard16253641998-10-28 22:58:05 +0000548 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000549 if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
550 xmlNodeAddContentLen(last, q, cur - q);
551 } else {
552 node = xmlNewDocTextLen(doc, q, cur - q);
553 if (node == NULL) return(ret);
554 if (last == NULL)
555 last = ret = node;
556 else {
557 last->next = node;
558 node->prev = last;
559 last = node;
560 }
Daniel Veillard16253641998-10-28 22:58:05 +0000561 }
562 }
Daniel Veillard25940b71998-10-29 05:51:30 +0000563 /*
564 * Read the entity string
565 */
Daniel Veillard16253641998-10-28 22:58:05 +0000566 cur++;
567 q = cur;
568 while ((*cur != 0) && (cur - value < len) && (*cur != ';')) cur++;
569 if ((*cur == 0) || (cur - value >= len)) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000570#ifdef DEBUG_TREE
Daniel Veillard16253641998-10-28 22:58:05 +0000571 fprintf(stderr,
Daniel Veillard011b63c1999-06-02 17:44:04 +0000572 "xmlStringLenGetNodeList: unterminated entity %30s\n", q);
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000573#endif
Daniel Veillard16253641998-10-28 22:58:05 +0000574 return(ret);
575 }
576 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000577 /*
578 * Predefined entities don't generate nodes
579 */
Daniel Veillard16253641998-10-28 22:58:05 +0000580 val = xmlStrndup(q, cur - q);
Daniel Veillard25940b71998-10-29 05:51:30 +0000581 ent = xmlGetDocEntity(doc, val);
582 if ((ent != NULL) &&
583 (ent->type == XML_INTERNAL_PREDEFINED_ENTITY)) {
584 if (last == NULL) {
585 node = xmlNewDocText(doc, ent->content);
586 last = ret = node;
587 } else
588 xmlNodeAddContent(last, ent->content);
589
590 } else {
591 /*
592 * Create a new REFERENCE_REF node
593 */
594 node = xmlNewReference(doc, val);
Daniel Veillard242590e1998-11-13 18:04:35 +0000595 if (node == NULL) {
Daniel Veillard6454aec1999-09-02 22:04:43 +0000596 if (val != NULL) xmlFree(val);
Daniel Veillard242590e1998-11-13 18:04:35 +0000597 return(ret);
598 }
Daniel Veillard25940b71998-10-29 05:51:30 +0000599 if (last == NULL)
600 last = ret = node;
601 else {
602 last->next = node;
603 node->prev = last;
604 last = node;
605 }
Daniel Veillard16253641998-10-28 22:58:05 +0000606 }
Daniel Veillard6454aec1999-09-02 22:04:43 +0000607 xmlFree(val);
Daniel Veillard16253641998-10-28 22:58:05 +0000608 }
609 cur++;
610 q = cur;
611 } else
612 cur++;
613 }
614 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000615 /*
616 * Handle the last piece of text.
617 */
618 if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
619 xmlNodeAddContentLen(last, q, cur - q);
620 } else {
621 node = xmlNewDocTextLen(doc, q, cur - q);
622 if (node == NULL) return(ret);
623 if (last == NULL)
624 last = ret = node;
625 else {
626 last->next = node;
627 node->prev = last;
628 last = node;
629 }
Daniel Veillard16253641998-10-28 22:58:05 +0000630 }
631 }
632 return(ret);
633}
634
635/**
Daniel Veillardccb09631998-10-27 06:21:04 +0000636 * xmlStringGetNodeList:
637 * @doc: the document
638 * @value: the value of the attribute
639 *
640 * Parse the value string and build the node list associated. Should
641 * produce a flat tree with only TEXTs and ENTITY_REFs.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000642 * Returns a pointer to the first child
Daniel Veillardccb09631998-10-27 06:21:04 +0000643 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000644xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000645xmlStringGetNodeList(xmlDocPtr doc, const xmlChar *value) {
Daniel Veillardccb09631998-10-27 06:21:04 +0000646 xmlNodePtr ret = NULL, last = NULL;
647 xmlNodePtr node;
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000648 xmlChar *val;
649 const xmlChar *cur = value;
650 const xmlChar *q;
Daniel Veillard25940b71998-10-29 05:51:30 +0000651 xmlEntityPtr ent;
Daniel Veillardccb09631998-10-27 06:21:04 +0000652
653 if (value == NULL) return(NULL);
654
655 q = cur;
656 while (*cur != 0) {
657 if (*cur == '&') {
Daniel Veillard25940b71998-10-29 05:51:30 +0000658 /*
659 * Save the current text.
660 */
Daniel Veillardccb09631998-10-27 06:21:04 +0000661 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000662 if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
663 xmlNodeAddContentLen(last, q, cur - q);
664 } else {
665 node = xmlNewDocTextLen(doc, q, cur - q);
666 if (node == NULL) return(ret);
667 if (last == NULL)
668 last = ret = node;
669 else {
670 last->next = node;
671 node->prev = last;
672 last = node;
673 }
Daniel Veillardccb09631998-10-27 06:21:04 +0000674 }
675 }
Daniel Veillard25940b71998-10-29 05:51:30 +0000676 /*
677 * Read the entity string
678 */
Daniel Veillardccb09631998-10-27 06:21:04 +0000679 cur++;
680 q = cur;
681 while ((*cur != 0) && (*cur != ';')) cur++;
682 if (*cur == 0) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000683#ifdef DEBUG_TREE
Daniel Veillardccb09631998-10-27 06:21:04 +0000684 fprintf(stderr,
685 "xmlStringGetNodeList: unterminated entity %30s\n", q);
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000686#endif
Daniel Veillardccb09631998-10-27 06:21:04 +0000687 return(ret);
688 }
689 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000690 /*
691 * Predefined entities don't generate nodes
692 */
Daniel Veillardccb09631998-10-27 06:21:04 +0000693 val = xmlStrndup(q, cur - q);
Daniel Veillard25940b71998-10-29 05:51:30 +0000694 ent = xmlGetDocEntity(doc, val);
695 if ((ent != NULL) &&
696 (ent->type == XML_INTERNAL_PREDEFINED_ENTITY)) {
697 if (last == NULL) {
698 node = xmlNewDocText(doc, ent->content);
699 last = ret = node;
700 } else
701 xmlNodeAddContent(last, ent->content);
702
703 } else {
704 /*
705 * Create a new REFERENCE_REF node
706 */
Daniel Veillard25940b71998-10-29 05:51:30 +0000707 node = xmlNewReference(doc, val);
Daniel Veillard242590e1998-11-13 18:04:35 +0000708 if (node == NULL) {
Daniel Veillard6454aec1999-09-02 22:04:43 +0000709 if (val != NULL) xmlFree(val);
Daniel Veillard242590e1998-11-13 18:04:35 +0000710 return(ret);
711 }
Daniel Veillard25940b71998-10-29 05:51:30 +0000712 if (last == NULL)
713 last = ret = node;
714 else {
715 last->next = node;
716 node->prev = last;
717 last = node;
718 }
Daniel Veillardccb09631998-10-27 06:21:04 +0000719 }
Daniel Veillard6454aec1999-09-02 22:04:43 +0000720 xmlFree(val);
Daniel Veillardccb09631998-10-27 06:21:04 +0000721 }
722 cur++;
723 q = cur;
724 } else
725 cur++;
726 }
727 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000728 /*
729 * Handle the last piece of text.
730 */
731 if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
732 xmlNodeAddContentLen(last, q, cur - q);
733 } else {
734 node = xmlNewDocTextLen(doc, q, cur - q);
735 if (node == NULL) return(ret);
736 if (last == NULL)
737 last = ret = node;
738 else {
739 last->next = node;
740 node->prev = last;
741 last = node;
742 }
Daniel Veillardccb09631998-10-27 06:21:04 +0000743 }
744 }
745 return(ret);
746}
747
748/**
749 * xmlNodeListGetString:
750 * @doc: the document
751 * @list: a Node list
752 * @inLine: should we replace entity contents or show their external form
753 *
754 * Returns the string equivalent to the text contained in the Node list
755 * made of TEXTs and ENTITY_REFs
Daniel Veillard1e346af1999-02-22 10:33:01 +0000756 * Returns a pointer to the string copy, the calller must free it.
Daniel Veillardccb09631998-10-27 06:21:04 +0000757 */
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000758xmlChar *
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000759xmlNodeListGetString(xmlDocPtr doc, xmlNodePtr list, int inLine) {
Daniel Veillardccb09631998-10-27 06:21:04 +0000760 xmlNodePtr node = list;
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000761 xmlChar *ret = NULL;
Daniel Veillardccb09631998-10-27 06:21:04 +0000762 xmlEntityPtr ent;
763
764 if (list == NULL) return(NULL);
765
766 while (node != NULL) {
767 if (node->type == XML_TEXT_NODE) {
Daniel Veillard71b656e2000-01-05 14:46:17 +0000768 if (inLine) {
Daniel Veillardf5c2c871999-12-01 09:51:45 +0000769#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardccb09631998-10-27 06:21:04 +0000770 ret = xmlStrcat(ret, node->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +0000771#else
772 ret = xmlStrcat(ret, xmlBufferContent(node->content));
773#endif
774 } else {
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000775 xmlChar *buffer;
Daniel Veillard14fff061999-06-22 21:49:07 +0000776
Daniel Veillardf5c2c871999-12-01 09:51:45 +0000777#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard14fff061999-06-22 21:49:07 +0000778 buffer = xmlEncodeEntitiesReentrant(doc, node->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +0000779#else
780 buffer = xmlEncodeEntitiesReentrant(doc,
781 xmlBufferContent(node->content));
782#endif
Daniel Veillard14fff061999-06-22 21:49:07 +0000783 if (buffer != NULL) {
784 ret = xmlStrcat(ret, buffer);
Daniel Veillard6454aec1999-09-02 22:04:43 +0000785 xmlFree(buffer);
Daniel Veillard14fff061999-06-22 21:49:07 +0000786 }
787 }
Daniel Veillardccb09631998-10-27 06:21:04 +0000788 } else if (node->type == XML_ENTITY_REF_NODE) {
789 if (inLine) {
790 ent = xmlGetDocEntity(doc, node->name);
791 if (ent != NULL)
792 ret = xmlStrcat(ret, ent->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +0000793 else {
794#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardccb09631998-10-27 06:21:04 +0000795 ret = xmlStrcat(ret, node->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +0000796#else
797 ret = xmlStrcat(ret, xmlBufferContent(node->content));
798#endif
799 }
Daniel Veillardccb09631998-10-27 06:21:04 +0000800 } else {
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000801 xmlChar buf[2];
Daniel Veillardccb09631998-10-27 06:21:04 +0000802 buf[0] = '&'; buf[1] = 0;
803 ret = xmlStrncat(ret, buf, 1);
804 ret = xmlStrcat(ret, node->name);
805 buf[0] = ';'; buf[1] = 0;
806 ret = xmlStrncat(ret, buf, 1);
807 }
808 }
809#if 0
810 else {
811 fprintf(stderr, "xmlGetNodeListString : invalide node type %d\n",
812 node->type);
813 }
814#endif
815 node = node->next;
816 }
817 return(ret);
818}
819
820/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000821 * xmlNewProp:
822 * @node: the holding node
823 * @name: the name of the attribute
824 * @value: the value of the attribute
825 *
826 * Create a new property carried by a node.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000827 * Returns a pointer to the attribute
Daniel Veillard260a68f1998-08-13 03:39:55 +0000828 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000829xmlAttrPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000830xmlNewProp(xmlNodePtr node, const xmlChar *name, const xmlChar *value) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000831 xmlAttrPtr cur;
832
833 if (name == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000834#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +0000835 fprintf(stderr, "xmlNewProp : name == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000836#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000837 return(NULL);
838 }
839
840 /*
841 * Allocate a new property and fill the fields.
842 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000843 cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000844 if (cur == NULL) {
845 fprintf(stderr, "xmlNewProp : malloc failed\n");
846 return(NULL);
847 }
848
Daniel Veillard33942841998-10-18 19:12:41 +0000849 cur->type = XML_ATTRIBUTE_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000850 cur->node = node;
Daniel Veillardb96e6431999-08-29 21:02:19 +0000851 cur->ns = NULL;
852 cur->name = xmlStrdup(name);
Daniel Veillard51e3b151999-11-12 17:02:31 +0000853 if (value != NULL) {
854 xmlChar *buffer;
855 buffer = xmlEncodeEntitiesReentrant(node->doc, value);
856 cur->val = xmlStringGetNodeList(node->doc, buffer);
857 xmlFree(buffer);
858 }
Daniel Veillardb96e6431999-08-29 21:02:19 +0000859 else
860 cur->val = NULL;
861#ifndef XML_WITHOUT_CORBA
862 cur->_private = NULL;
863 cur->vepv = NULL;
864#endif
865
866 /*
867 * Add it at the end to preserve parsing order ...
868 */
869 cur->next = NULL;
870 if (node != NULL) {
871 if (node->properties == NULL) {
872 node->properties = cur;
873 } else {
874 xmlAttrPtr prev = node->properties;
875
876 while (prev->next != NULL) prev = prev->next;
877 prev->next = cur;
878 }
879 }
Daniel Veillard00fdf371999-10-08 09:40:39 +0000880#ifndef XML_WITHOUT_CORBA
881 cur->_private = NULL;
882 cur->vepv = NULL;
883#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +0000884 return(cur);
885}
886
887/**
888 * xmlNewNsProp:
889 * @node: the holding node
890 * @ns: the namespace
891 * @name: the name of the attribute
892 * @value: the value of the attribute
893 *
894 * Create a new property tagged with a namespace and carried by a node.
895 * Returns a pointer to the attribute
896 */
897xmlAttrPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000898xmlNewNsProp(xmlNodePtr node, xmlNsPtr ns, const xmlChar *name,
899 const xmlChar *value) {
Daniel Veillardb96e6431999-08-29 21:02:19 +0000900 xmlAttrPtr cur;
901
902 if (name == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000903#ifdef DEBUG_TREE
Daniel Veillardb96e6431999-08-29 21:02:19 +0000904 fprintf(stderr, "xmlNewProp : name == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000905#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +0000906 return(NULL);
907 }
908
909 /*
910 * Allocate a new property and fill the fields.
911 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000912 cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr));
Daniel Veillardb96e6431999-08-29 21:02:19 +0000913 if (cur == NULL) {
914 fprintf(stderr, "xmlNewProp : malloc failed\n");
915 return(NULL);
916 }
917
918 cur->type = XML_ATTRIBUTE_NODE;
919 cur->node = node;
920 cur->ns = ns;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000921 cur->name = xmlStrdup(name);
922 if (value != NULL)
Daniel Veillardccb09631998-10-27 06:21:04 +0000923 cur->val = xmlStringGetNodeList(node->doc, value);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000924 else
Daniel Veillardccb09631998-10-27 06:21:04 +0000925 cur->val = NULL;
Daniel Veillard27d88741999-05-29 11:51:49 +0000926#ifndef XML_WITHOUT_CORBA
Daniel Veillard27fb0751998-10-17 06:47:46 +0000927 cur->_private = NULL;
928 cur->vepv = NULL;
929#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000930
931 /*
932 * Add it at the end to preserve parsing order ...
933 */
934 cur->next = NULL;
935 if (node != NULL) {
936 if (node->properties == NULL) {
937 node->properties = cur;
938 } else {
939 xmlAttrPtr prev = node->properties;
940
941 while (prev->next != NULL) prev = prev->next;
942 prev->next = cur;
943 }
944 }
945 return(cur);
946}
947
Daniel Veillard97b58771998-10-20 06:14:16 +0000948/**
Daniel Veillardccb09631998-10-27 06:21:04 +0000949 * xmlNewDocProp:
950 * @doc: the document
951 * @name: the name of the attribute
952 * @value: the value of the attribute
953 *
954 * Create a new property carried by a document.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000955 * Returns a pointer to the attribute
Daniel Veillardccb09631998-10-27 06:21:04 +0000956 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000957xmlAttrPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000958xmlNewDocProp(xmlDocPtr doc, const xmlChar *name, const xmlChar *value) {
Daniel Veillardccb09631998-10-27 06:21:04 +0000959 xmlAttrPtr cur;
960
961 if (name == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000962#ifdef DEBUG_TREE
Daniel Veillardccb09631998-10-27 06:21:04 +0000963 fprintf(stderr, "xmlNewProp : name == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000964#endif
Daniel Veillardccb09631998-10-27 06:21:04 +0000965 return(NULL);
966 }
967
968 /*
969 * Allocate a new property and fill the fields.
970 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000971 cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr));
Daniel Veillardccb09631998-10-27 06:21:04 +0000972 if (cur == NULL) {
973 fprintf(stderr, "xmlNewProp : malloc failed\n");
974 return(NULL);
975 }
976
977 cur->type = XML_ATTRIBUTE_NODE;
978 cur->node = NULL;
979 cur->name = xmlStrdup(name);
980 if (value != NULL)
981 cur->val = xmlStringGetNodeList(doc, value);
982 else
983 cur->val = NULL;
Daniel Veillard27d88741999-05-29 11:51:49 +0000984#ifndef XML_WITHOUT_CORBA
Daniel Veillardccb09631998-10-27 06:21:04 +0000985 cur->_private = NULL;
986 cur->vepv = NULL;
987#endif
988
989 cur->next = NULL;
990 return(cur);
991}
992
993/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000994 * xmlFreePropList:
995 * @cur: the first property in the list
996 *
997 * Free a property and all its siblings, all the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000998 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000999void
1000xmlFreePropList(xmlAttrPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001001 xmlAttrPtr next;
1002 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001003#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00001004 fprintf(stderr, "xmlFreePropList : property == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001005#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001006 return;
1007 }
1008 while (cur != NULL) {
1009 next = cur->next;
1010 xmlFreeProp(cur);
1011 cur = next;
1012 }
1013}
1014
Daniel Veillard97b58771998-10-20 06:14:16 +00001015/**
1016 * xmlFreeProp:
Daniel Veillard686d6b62000-01-03 11:08:02 +00001017 * @cur: an attribute
Daniel Veillard97b58771998-10-20 06:14:16 +00001018 *
Daniel Veillard686d6b62000-01-03 11:08:02 +00001019 * Free one attribute, all the content is freed too
Daniel Veillard260a68f1998-08-13 03:39:55 +00001020 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001021void
1022xmlFreeProp(xmlAttrPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001023 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001024#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00001025 fprintf(stderr, "xmlFreeProp : property == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001026#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001027 return;
1028 }
Daniel Veillard71b656e2000-01-05 14:46:17 +00001029 /* Check for ID removal -> leading to invalid references ! */
1030 if ((cur->node != NULL) &&
1031 (xmlIsID(cur->node->doc, cur->node, cur)))
1032 xmlRemoveID(cur->node->doc, cur);
Daniel Veillard6454aec1999-09-02 22:04:43 +00001033 if (cur->name != NULL) xmlFree((char *) cur->name);
Daniel Veillardccb09631998-10-27 06:21:04 +00001034 if (cur->val != NULL) xmlFreeNodeList(cur->val);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001035 memset(cur, -1, sizeof(xmlAttr));
Daniel Veillard6454aec1999-09-02 22:04:43 +00001036 xmlFree(cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001037}
1038
Daniel Veillard97b58771998-10-20 06:14:16 +00001039/**
Daniel Veillard686d6b62000-01-03 11:08:02 +00001040 * xmlRemoveProp:
1041 * @cur: an attribute
1042 *
1043 * Unlink and free one attribute, all the content is freed too
1044 * Note this doesn't work for namespace definition attributes
1045 *
1046 * Returns 0 if success and -1 in case of error.
1047 */
1048int
1049xmlRemoveProp(xmlAttrPtr cur) {
1050 xmlAttrPtr tmp;
1051 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001052#ifdef DEBUG_TREE
Daniel Veillard686d6b62000-01-03 11:08:02 +00001053 fprintf(stderr, "xmlRemoveProp : cur == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001054#endif
Daniel Veillard686d6b62000-01-03 11:08:02 +00001055 return(-1);
1056 }
1057 if (cur->node == NULL) {
1058 fprintf(stderr, "xmlRemoveProp : cur->node == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001059#endif
Daniel Veillard686d6b62000-01-03 11:08:02 +00001060 return(-1);
1061 }
1062 tmp = cur->node->properties;
1063 if (tmp == cur) {
1064 cur->node->properties = cur->next;
1065 xmlFreeProp(cur);
1066 return(0);
1067 }
1068 while (tmp != NULL) {
1069 if (tmp->next == cur) {
1070 tmp->next = cur->next;
1071 xmlFreeProp(cur);
1072 return(0);
1073 }
1074 tmp = tmp->next;
1075 }
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001076#ifdef DEBUG_TREE
Daniel Veillard686d6b62000-01-03 11:08:02 +00001077 fprintf(stderr, "xmlRemoveProp : attribute not owned by its node\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001078#endif
Daniel Veillard686d6b62000-01-03 11:08:02 +00001079 return(-1);
1080}
1081
1082/**
Daniel Veillardb96e6431999-08-29 21:02:19 +00001083 * xmlNewPI:
1084 * @name: the processing instruction name
1085 * @content: the PI content
1086 *
1087 * Creation of a processing instruction element.
1088 * Returns a pointer to the new node object.
1089 */
1090xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001091xmlNewPI(const xmlChar *name, const xmlChar *content) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00001092 xmlNodePtr cur;
1093
1094 if (name == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001095#ifdef DEBUG_TREE
Daniel Veillardb96e6431999-08-29 21:02:19 +00001096 fprintf(stderr, "xmlNewPI : name == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001097#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +00001098 return(NULL);
1099 }
1100
1101 /*
1102 * Allocate a new node and fill the fields.
1103 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001104 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillardb96e6431999-08-29 21:02:19 +00001105 if (cur == NULL) {
1106 fprintf(stderr, "xmlNewPI : malloc failed\n");
1107 return(NULL);
1108 }
1109
1110 cur->type = XML_PI_NODE;
1111 cur->doc = NULL;
1112 cur->parent = NULL;
1113 cur->next = NULL;
1114 cur->prev = NULL;
1115 cur->childs = NULL;
1116 cur->last = NULL;
1117 cur->properties = NULL;
1118 cur->name = xmlStrdup(name);
1119 cur->ns = NULL;
1120 cur->nsDef = NULL;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001121 if (content != NULL) {
1122#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardb96e6431999-08-29 21:02:19 +00001123 cur->content = xmlStrdup(content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001124#else
1125 cur->content = xmlBufferCreateSize(0);
1126 xmlBufferSetAllocationScheme(cur->content,
1127 xmlGetBufferAllocationScheme());
1128 xmlBufferAdd(cur->content, content, -1);
1129#endif
1130 } else
Daniel Veillardb96e6431999-08-29 21:02:19 +00001131 cur->content = NULL;
1132#ifndef XML_WITHOUT_CORBA
1133 cur->_private = NULL;
1134 cur->vepv = NULL;
1135#endif
1136 return(cur);
1137}
1138
1139/**
Daniel Veillard97b58771998-10-20 06:14:16 +00001140 * xmlNewNode:
1141 * @ns: namespace if any
1142 * @name: the node name
Daniel Veillard97b58771998-10-20 06:14:16 +00001143 *
1144 * Creation of a new node element. @ns and @content are optionnal (NULL).
Daniel Veillardccb09631998-10-27 06:21:04 +00001145 * If content is non NULL, a child list containing the TEXTs and
1146 * ENTITY_REFs node will be created.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001147 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001148 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001149xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001150xmlNewNode(xmlNsPtr ns, const xmlChar *name) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001151 xmlNodePtr cur;
1152
1153 if (name == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001154#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00001155 fprintf(stderr, "xmlNewNode : name == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001156#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001157 return(NULL);
1158 }
1159
1160 /*
1161 * Allocate a new node and fill the fields.
1162 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001163 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillard260a68f1998-08-13 03:39:55 +00001164 if (cur == NULL) {
1165 fprintf(stderr, "xmlNewNode : malloc failed\n");
1166 return(NULL);
1167 }
1168
Daniel Veillard33942841998-10-18 19:12:41 +00001169 cur->type = XML_ELEMENT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001170 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001171 cur->parent = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001172 cur->next = NULL;
1173 cur->prev = NULL;
1174 cur->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001175 cur->last = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001176 cur->properties = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001177 cur->name = xmlStrdup(name);
1178 cur->ns = ns;
1179 cur->nsDef = NULL;
Daniel Veillardccb09631998-10-27 06:21:04 +00001180 cur->content = NULL;
Daniel Veillard27d88741999-05-29 11:51:49 +00001181#ifndef XML_WITHOUT_CORBA
Daniel Veillard27fb0751998-10-17 06:47:46 +00001182 cur->_private = NULL;
1183 cur->vepv = NULL;
1184#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001185 return(cur);
1186}
1187
Daniel Veillard97b58771998-10-20 06:14:16 +00001188/**
1189 * xmlNewDocNode:
1190 * @doc: the document
1191 * @ns: namespace if any
1192 * @name: the node name
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001193 * @content: the XML text content if any
Daniel Veillard97b58771998-10-20 06:14:16 +00001194 *
1195 * Creation of a new node element within a document. @ns and @content
1196 * are optionnal (NULL).
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001197 * NOTE: @content is supposed to be a piece of XML CDATA, so it allow entities
1198 * references, but XML special chars need to be escaped first by using
1199 * xmlEncodeEntitiesReentrant(). Use xmlNewDocRawNode() if you don't
1200 * need entities support.
1201 *
Daniel Veillard1e346af1999-02-22 10:33:01 +00001202 * Returns a pointer to the new node object.
Daniel Veillard97b58771998-10-20 06:14:16 +00001203 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001204xmlNodePtr
1205xmlNewDocNode(xmlDocPtr doc, xmlNsPtr ns,
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001206 const xmlChar *name, const xmlChar *content) {
Daniel Veillard0bef1311998-10-14 02:36:47 +00001207 xmlNodePtr cur;
1208
Daniel Veillardccb09631998-10-27 06:21:04 +00001209 cur = xmlNewNode(ns, name);
1210 if (cur != NULL) {
1211 cur->doc = doc;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001212 if (content != NULL) {
Daniel Veillardccb09631998-10-27 06:21:04 +00001213 cur->childs = xmlStringGetNodeList(doc, content);
Daniel Veillard1e346af1999-02-22 10:33:01 +00001214 UPDATE_LAST_CHILD(cur)
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001215 }
Daniel Veillardccb09631998-10-27 06:21:04 +00001216 }
Daniel Veillard0bef1311998-10-14 02:36:47 +00001217 return(cur);
1218}
1219
1220
Daniel Veillard97b58771998-10-20 06:14:16 +00001221/**
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001222 * xmlNewDocRawNode:
1223 * @doc: the document
1224 * @ns: namespace if any
1225 * @name: the node name
1226 * @content: the text content if any
1227 *
1228 * Creation of a new node element within a document. @ns and @content
1229 * are optionnal (NULL).
1230 *
1231 * Returns a pointer to the new node object.
1232 */
1233xmlNodePtr
1234xmlNewDocRawNode(xmlDocPtr doc, xmlNsPtr ns,
1235 const xmlChar *name, const xmlChar *content) {
1236 xmlNodePtr cur;
1237
1238 cur = xmlNewNode(ns, name);
1239 if (cur != NULL) {
1240 cur->doc = doc;
1241 if (content != NULL) {
1242 cur->childs = xmlNewDocText(doc, content);
1243 UPDATE_LAST_CHILD(cur)
1244 }
1245 }
1246 return(cur);
1247}
1248
Daniel Veillard2eac5032000-01-09 21:08:56 +00001249/**
1250 * xmlNewDocFragment:
1251 * @doc: the document owning the fragment
1252 *
1253 * Creation of a new Fragment node.
1254 * Returns a pointer to the new node object.
1255 */
1256xmlNodePtr
1257xmlNewDocFragment(xmlDocPtr doc) {
1258 xmlNodePtr cur;
1259
1260 /*
1261 * Allocate a new DocumentFragment node and fill the fields.
1262 */
1263 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
1264 if (cur == NULL) {
1265 fprintf(stderr, "xmlNewDocFragment : malloc failed\n");
1266 return(NULL);
1267 }
1268
1269 cur->type = XML_DOCUMENT_FRAG_NODE;
1270 cur->doc = doc;
1271 cur->parent = NULL;
1272 cur->next = NULL;
1273 cur->prev = NULL;
1274 cur->childs = NULL;
1275 cur->last = NULL;
1276 cur->properties = NULL;
1277 cur->name = NULL;
1278 cur->ns = NULL;
1279 cur->nsDef = NULL;
1280 cur->content = NULL;
1281#ifndef XML_WITHOUT_CORBA
1282 cur->_private = NULL;
1283 cur->vepv = NULL;
1284#endif
1285 return(cur);
1286}
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001287
1288/**
Daniel Veillard97b58771998-10-20 06:14:16 +00001289 * xmlNewText:
1290 * @content: the text content
1291 *
1292 * Creation of a new text node.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001293 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001294 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001295xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001296xmlNewText(const xmlChar *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001297 xmlNodePtr cur;
1298
1299 /*
1300 * Allocate a new node and fill the fields.
1301 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001302 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillard260a68f1998-08-13 03:39:55 +00001303 if (cur == NULL) {
1304 fprintf(stderr, "xmlNewText : malloc failed\n");
1305 return(NULL);
1306 }
1307
Daniel Veillard33942841998-10-18 19:12:41 +00001308 cur->type = XML_TEXT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001309 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001310 cur->parent = NULL;
1311 cur->next = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001312 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001313 cur->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001314 cur->last = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001315 cur->properties = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001316 cur->type = XML_TEXT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001317 cur->name = xmlStrdup(xmlStringText);
1318 cur->ns = NULL;
1319 cur->nsDef = NULL;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001320 if (content != NULL) {
1321#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard260a68f1998-08-13 03:39:55 +00001322 cur->content = xmlStrdup(content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001323#else
1324 cur->content = xmlBufferCreateSize(0);
1325 xmlBufferSetAllocationScheme(cur->content,
1326 xmlGetBufferAllocationScheme());
1327 xmlBufferAdd(cur->content, content, -1);
1328#endif
1329 } else
Daniel Veillard260a68f1998-08-13 03:39:55 +00001330 cur->content = NULL;
Daniel Veillard00fdf371999-10-08 09:40:39 +00001331#ifndef XML_WITHOUT_CORBA
1332 cur->_private = NULL;
1333 cur->vepv = NULL;
1334#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001335 return(cur);
1336}
1337
Daniel Veillard97b58771998-10-20 06:14:16 +00001338/**
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001339 * xmlNewTextChild:
1340 * @parent: the parent node
1341 * @ns: a namespace if any
1342 * @name: the name of the child
1343 * @content: the text content of the child if any.
1344 *
1345 * Creation of a new child element, added at the end of @parent childs list.
1346 * @ns and @content parameters are optionnal (NULL). If content is non NULL,
1347 * a child TEXT node will be created containing the string content.
1348 *
1349 * Returns a pointer to the new node object.
1350 */
1351xmlNodePtr
1352xmlNewTextChild(xmlNodePtr parent, xmlNsPtr ns,
1353 const xmlChar *name, const xmlChar *content) {
1354 xmlNodePtr cur, prev;
1355
1356 if (parent == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001357#ifdef DEBUG_TREE
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001358 fprintf(stderr, "xmlNewTextChild : parent == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001359#endif
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001360 return(NULL);
1361 }
1362
1363 if (name == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001364#ifdef DEBUG_TREE
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001365 fprintf(stderr, "xmlNewTextChild : name == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001366#endif
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001367 return(NULL);
1368 }
1369
1370 /*
1371 * Allocate a new node
1372 */
1373 if (ns == NULL)
1374 cur = xmlNewDocRawNode(parent->doc, parent->ns, name, content);
1375 else
1376 cur = xmlNewDocRawNode(parent->doc, ns, name, content);
1377 if (cur == NULL) return(NULL);
1378
1379 /*
1380 * add the new element at the end of the childs list.
1381 */
1382 cur->type = XML_ELEMENT_NODE;
1383 cur->parent = parent;
1384 cur->doc = parent->doc;
1385 if (parent->childs == NULL) {
1386 parent->childs = cur;
1387 parent->last = cur;
1388 } else {
1389 prev = parent->last;
1390 prev->next = cur;
1391 cur->prev = prev;
1392 parent->last = cur;
1393 }
1394
1395 return(cur);
1396}
1397
1398/**
Daniel Veillardccb09631998-10-27 06:21:04 +00001399 * xmlNewReference:
1400 * @doc: the document
1401 * @name: the reference name, or the reference string with & and ;
1402 *
1403 * Creation of a new reference node.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001404 * Returns a pointer to the new node object.
Daniel Veillardccb09631998-10-27 06:21:04 +00001405 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001406xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001407xmlNewReference(xmlDocPtr doc, const xmlChar *name) {
Daniel Veillardccb09631998-10-27 06:21:04 +00001408 xmlNodePtr cur;
1409 xmlEntityPtr ent;
1410
1411 /*
1412 * Allocate a new node and fill the fields.
1413 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001414 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillardccb09631998-10-27 06:21:04 +00001415 if (cur == NULL) {
1416 fprintf(stderr, "xmlNewText : malloc failed\n");
1417 return(NULL);
1418 }
1419
1420 cur->type = XML_ENTITY_REF_NODE;
Daniel Veillard10c6a8f1998-10-28 01:00:12 +00001421 cur->doc = doc;
Daniel Veillardccb09631998-10-27 06:21:04 +00001422 cur->parent = NULL;
1423 cur->next = NULL;
1424 cur->prev = NULL;
1425 cur->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001426 cur->last = NULL;
Daniel Veillardccb09631998-10-27 06:21:04 +00001427 cur->properties = NULL;
1428 if (name[0] == '&') {
1429 int len;
1430 name++;
1431 len = xmlStrlen(name);
1432 if (name[len - 1] == ';')
1433 cur->name = xmlStrndup(name, len - 1);
1434 else
1435 cur->name = xmlStrndup(name, len);
1436 } else
1437 cur->name = xmlStrdup(name);
1438 cur->ns = NULL;
1439 cur->nsDef = NULL;
1440
1441 ent = xmlGetDocEntity(doc, cur->name);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001442 if (ent != NULL) {
1443#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardccb09631998-10-27 06:21:04 +00001444 cur->content = ent->content;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001445#else
1446 /*
1447 * CJN 11.18.99 this might be a problem, since the xmlBuffer gets
1448 * a copy of this pointer. Let's hope we don't manipulate it
1449 * later
1450 */
1451 cur->content = xmlBufferCreateSize(0);
1452 xmlBufferSetAllocationScheme(cur->content,
1453 xmlGetBufferAllocationScheme());
1454 if (ent->content != NULL)
1455 xmlBufferAdd(cur->content, ent->content, -1);
1456#endif
1457 } else
Daniel Veillardccb09631998-10-27 06:21:04 +00001458 cur->content = NULL;
Daniel Veillard00fdf371999-10-08 09:40:39 +00001459#ifndef XML_WITHOUT_CORBA
1460 cur->_private = NULL;
1461 cur->vepv = NULL;
1462#endif
Daniel Veillardccb09631998-10-27 06:21:04 +00001463 return(cur);
1464}
1465
1466/**
Daniel Veillard97b58771998-10-20 06:14:16 +00001467 * xmlNewDocText:
1468 * @doc: the document
1469 * @content: the text content
1470 *
1471 * Creation of a new text node within a document.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001472 * Returns a pointer to the new node object.
Daniel Veillard97b58771998-10-20 06:14:16 +00001473 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001474xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001475xmlNewDocText(xmlDocPtr doc, const xmlChar *content) {
Daniel Veillard0bef1311998-10-14 02:36:47 +00001476 xmlNodePtr cur;
1477
1478 cur = xmlNewText(content);
1479 if (cur != NULL) cur->doc = doc;
1480 return(cur);
1481}
1482
Daniel Veillard97b58771998-10-20 06:14:16 +00001483/**
Daniel Veillardccb09631998-10-27 06:21:04 +00001484 * xmlNewTextLen:
Daniel Veillard97b58771998-10-20 06:14:16 +00001485 * @content: the text content
1486 * @len: the text len.
1487 *
1488 * Creation of a new text node with an extra parameter for the content's lenght
Daniel Veillard1e346af1999-02-22 10:33:01 +00001489 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001490 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001491xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001492xmlNewTextLen(const xmlChar *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001493 xmlNodePtr cur;
1494
1495 /*
1496 * Allocate a new node and fill the fields.
1497 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001498 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillard260a68f1998-08-13 03:39:55 +00001499 if (cur == NULL) {
1500 fprintf(stderr, "xmlNewText : malloc failed\n");
1501 return(NULL);
1502 }
1503
Daniel Veillard33942841998-10-18 19:12:41 +00001504 cur->type = XML_TEXT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001505 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001506 cur->parent = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001507 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001508 cur->next = NULL;
1509 cur->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001510 cur->last = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001511 cur->properties = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001512 cur->type = XML_TEXT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001513 cur->name = xmlStrdup(xmlStringText);
1514 cur->ns = NULL;
1515 cur->nsDef = NULL;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001516 if (content != NULL) {
1517#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard260a68f1998-08-13 03:39:55 +00001518 cur->content = xmlStrndup(content, len);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001519#else
1520 cur->content = xmlBufferCreateSize(len);
1521 xmlBufferSetAllocationScheme(cur->content,
1522 xmlGetBufferAllocationScheme());
1523 xmlBufferAdd(cur->content, content, len);
1524#endif
1525 } else
Daniel Veillard260a68f1998-08-13 03:39:55 +00001526 cur->content = NULL;
Daniel Veillard00fdf371999-10-08 09:40:39 +00001527#ifndef XML_WITHOUT_CORBA
1528 cur->_private = NULL;
1529 cur->vepv = NULL;
1530#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001531 return(cur);
1532}
1533
Daniel Veillard97b58771998-10-20 06:14:16 +00001534/**
1535 * xmlNewDocTextLen:
1536 * @doc: the document
1537 * @content: the text content
1538 * @len: the text len.
1539 *
1540 * Creation of a new text node with an extra content lenght parameter. The
1541 * text node pertain to a given document.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001542 * Returns a pointer to the new node object.
Daniel Veillard97b58771998-10-20 06:14:16 +00001543 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001544xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001545xmlNewDocTextLen(xmlDocPtr doc, const xmlChar *content, int len) {
Daniel Veillard0bef1311998-10-14 02:36:47 +00001546 xmlNodePtr cur;
1547
1548 cur = xmlNewTextLen(content, len);
1549 if (cur != NULL) cur->doc = doc;
1550 return(cur);
1551}
1552
Daniel Veillard97b58771998-10-20 06:14:16 +00001553/**
1554 * xmlNewComment:
1555 * @content: the comment content
1556 *
1557 * Creation of a new node containing a comment.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001558 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001559 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001560xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001561xmlNewComment(const xmlChar *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001562 xmlNodePtr cur;
1563
1564 /*
1565 * Allocate a new node and fill the fields.
1566 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001567 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillard260a68f1998-08-13 03:39:55 +00001568 if (cur == NULL) {
1569 fprintf(stderr, "xmlNewComment : malloc failed\n");
1570 return(NULL);
1571 }
1572
Daniel Veillard33942841998-10-18 19:12:41 +00001573 cur->type = XML_COMMENT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001574 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001575 cur->parent = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001576 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001577 cur->next = NULL;
1578 cur->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001579 cur->last = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001580 cur->properties = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001581 cur->type = XML_COMMENT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001582 cur->name = xmlStrdup(xmlStringText);
1583 cur->ns = NULL;
1584 cur->nsDef = NULL;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001585 if (content != NULL) {
1586#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard260a68f1998-08-13 03:39:55 +00001587 cur->content = xmlStrdup(content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001588#else
1589 cur->content = xmlBufferCreateSize(0);
1590 xmlBufferSetAllocationScheme(cur->content,
1591 xmlGetBufferAllocationScheme());
1592 xmlBufferAdd(cur->content, content, -1);
1593#endif
1594 } else
Daniel Veillard260a68f1998-08-13 03:39:55 +00001595 cur->content = NULL;
Daniel Veillard00fdf371999-10-08 09:40:39 +00001596#ifndef XML_WITHOUT_CORBA
1597 cur->_private = NULL;
1598 cur->vepv = NULL;
1599#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001600 return(cur);
1601}
1602
Daniel Veillard97b58771998-10-20 06:14:16 +00001603/**
Daniel Veillardb05deb71999-08-10 19:04:08 +00001604 * xmlNewCDataBlock:
1605 * @doc: the document
1606 * @content: the CData block content content
1607 * @len: the length of the block
1608 *
1609 * Creation of a new node containing a CData block.
1610 * Returns a pointer to the new node object.
1611 */
1612xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001613xmlNewCDataBlock(xmlDocPtr doc, const xmlChar *content, int len) {
Daniel Veillardb05deb71999-08-10 19:04:08 +00001614 xmlNodePtr cur;
1615
1616 /*
1617 * Allocate a new node and fill the fields.
1618 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001619 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillardb05deb71999-08-10 19:04:08 +00001620 if (cur == NULL) {
1621 fprintf(stderr, "xmlNewCDataBlock : malloc failed\n");
1622 return(NULL);
1623 }
1624
1625 cur->type = XML_CDATA_SECTION_NODE;
1626 cur->doc = NULL;
1627 cur->parent = NULL;
1628 cur->prev = NULL;
1629 cur->next = NULL;
1630 cur->childs = NULL;
1631 cur->last = NULL;
1632 cur->properties = NULL;
1633 cur->name = xmlStrdup(xmlStringText);
1634 cur->ns = NULL;
1635 cur->nsDef = NULL;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001636 if (content != NULL) {
1637#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardb05deb71999-08-10 19:04:08 +00001638 cur->content = xmlStrndup(content, len);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001639#else
1640 cur->content = xmlBufferCreateSize(len);
1641 xmlBufferSetAllocationScheme(cur->content,
1642 xmlGetBufferAllocationScheme());
1643 xmlBufferAdd(cur->content, content, len);
1644#endif
Daniel Veillardb05deb71999-08-10 19:04:08 +00001645 } else
1646 cur->content = NULL;
Daniel Veillard00fdf371999-10-08 09:40:39 +00001647#ifndef XML_WITHOUT_CORBA
1648 cur->_private = NULL;
1649 cur->vepv = NULL;
1650#endif
Daniel Veillardb05deb71999-08-10 19:04:08 +00001651 return(cur);
1652}
1653
1654/**
Daniel Veillard1e346af1999-02-22 10:33:01 +00001655 * xmlNewDocComment:
Daniel Veillard97b58771998-10-20 06:14:16 +00001656 * @doc: the document
1657 * @content: the comment content
1658 *
1659 * Creation of a new node containing a commentwithin a document.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001660 * Returns a pointer to the new node object.
Daniel Veillard97b58771998-10-20 06:14:16 +00001661 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001662xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001663xmlNewDocComment(xmlDocPtr doc, const xmlChar *content) {
Daniel Veillard0bef1311998-10-14 02:36:47 +00001664 xmlNodePtr cur;
1665
1666 cur = xmlNewComment(content);
1667 if (cur != NULL) cur->doc = doc;
1668 return(cur);
1669}
1670
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001671
Daniel Veillard97b58771998-10-20 06:14:16 +00001672/**
1673 * xmlNewChild:
1674 * @parent: the parent node
1675 * @ns: a namespace if any
1676 * @name: the name of the child
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001677 * @content: the XML content of the child if any.
Daniel Veillard97b58771998-10-20 06:14:16 +00001678 *
Daniel Veillard97b58771998-10-20 06:14:16 +00001679 * Creation of a new child element, added at the end of @parent childs list.
Daniel Veillardccb09631998-10-27 06:21:04 +00001680 * @ns and @content parameters are optionnal (NULL). If content is non NULL,
1681 * a child list containing the TEXTs and ENTITY_REFs node will be created.
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001682 * NOTE: @content is supposed to be a piece of XML CDATA, so it allow entities
1683 * references, but XML special chars need to be escaped first by using
1684 * xmlEncodeEntitiesReentrant(). Use xmlNewTextChild() if entities
1685 * support is not needed.
1686 *
Daniel Veillard1e346af1999-02-22 10:33:01 +00001687 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001688 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001689xmlNodePtr
1690xmlNewChild(xmlNodePtr parent, xmlNsPtr ns,
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001691 const xmlChar *name, const xmlChar *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001692 xmlNodePtr cur, prev;
1693
1694 if (parent == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001695#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00001696 fprintf(stderr, "xmlNewChild : parent == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001697#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001698 return(NULL);
1699 }
1700
1701 if (name == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001702#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00001703 fprintf(stderr, "xmlNewChild : name == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001704#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001705 return(NULL);
1706 }
1707
1708 /*
1709 * Allocate a new node
1710 */
1711 if (ns == NULL)
Daniel Veillardccb09631998-10-27 06:21:04 +00001712 cur = xmlNewDocNode(parent->doc, parent->ns, name, content);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001713 else
Daniel Veillardccb09631998-10-27 06:21:04 +00001714 cur = xmlNewDocNode(parent->doc, ns, name, content);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001715 if (cur == NULL) return(NULL);
1716
1717 /*
1718 * add the new element at the end of the childs list.
1719 */
Daniel Veillardccb09631998-10-27 06:21:04 +00001720 cur->type = XML_ELEMENT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001721 cur->parent = parent;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001722 cur->doc = parent->doc;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001723 if (parent->childs == NULL) {
1724 parent->childs = cur;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001725 parent->last = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001726 } else {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001727 prev = parent->last;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001728 prev->next = cur;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001729 cur->prev = prev;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001730 parent->last = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001731 }
1732
1733 return(cur);
1734}
1735
Daniel Veillard97b58771998-10-20 06:14:16 +00001736/**
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00001737 * xmlAddNextSibling:
1738 * @cur: the child node
1739 * @elem: the new node
1740 *
1741 * Add a new element @elem as the next siblings of @cur
1742 * If the new element was already inserted in a document it is
1743 * first unlinked from its existing context.
1744 *
1745 * Returns the new element or NULL in case of error.
1746 */
1747xmlNodePtr
1748xmlAddNextSibling(xmlNodePtr cur, xmlNodePtr elem) {
1749 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001750#ifdef DEBUG_TREE
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00001751 fprintf(stderr, "xmlAddNextSibling : cur == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001752#endif
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00001753 return(NULL);
1754 }
1755 if (elem == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001756#ifdef DEBUG_TREE
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00001757 fprintf(stderr, "xmlAddNextSibling : elem == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001758#endif
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00001759 return(NULL);
1760 }
1761
1762 xmlUnlinkNode(elem);
1763 elem->doc = cur->doc;
1764 elem->parent = cur->parent;
1765 elem->next = cur;
1766 elem->prev = cur->prev;
1767 cur->prev = elem;
1768 if (elem->prev != NULL)
1769 elem->prev->next = elem;
1770 if ((elem->parent != NULL) && (elem->parent->childs == cur))
1771 elem->parent->childs = elem;
1772 return(elem);
1773}
1774
1775/**
1776 * xmlAddPrevSibling:
1777 * @cur: the child node
1778 * @elem: the new node
1779 *
1780 * Add a new element @elem as the previous siblings of @cur
1781 * If the new element was already inserted in a document it is
1782 * first unlinked from its existing context.
1783 *
1784 * Returns the new element or NULL in case of error.
1785 */
1786xmlNodePtr
1787xmlAddPrevSibling(xmlNodePtr cur, xmlNodePtr elem) {
1788 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001789#ifdef DEBUG_TREE
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00001790 fprintf(stderr, "xmlAddPrevSibling : cur == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001791#endif
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00001792 return(NULL);
1793 }
1794 if (elem == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001795#ifdef DEBUG_TREE
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00001796 fprintf(stderr, "xmlAddPrevSibling : elem == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001797#endif
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00001798 return(NULL);
1799 }
1800
1801 xmlUnlinkNode(elem);
1802 elem->doc = cur->doc;
1803 elem->parent = cur->parent;
1804 elem->prev = cur;
1805 elem->next = cur->next;
1806 cur->next = elem;
1807 if (elem->next != NULL)
1808 elem->next->prev = elem;
1809 if ((elem->parent != NULL) && (elem->parent->last == cur))
1810 elem->parent->last = elem;
1811 return(elem);
1812}
1813
1814/**
Daniel Veillardb96e6431999-08-29 21:02:19 +00001815 * xmlAddSibling:
1816 * @cur: the child node
1817 * @elem: the new node
1818 *
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00001819 * Add a new element @elem to the list of siblings of @cur
1820 * If the new element was already inserted in a document it is
1821 * first unlinked from its existing context.
1822 *
1823 * Returns the new element or NULL in case of error.
Daniel Veillardb96e6431999-08-29 21:02:19 +00001824 */
1825xmlNodePtr
1826xmlAddSibling(xmlNodePtr cur, xmlNodePtr elem) {
1827 xmlNodePtr parent;
1828
1829 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001830#ifdef DEBUG_TREE
Daniel Veillardb96e6431999-08-29 21:02:19 +00001831 fprintf(stderr, "xmlAddSibling : cur == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001832#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +00001833 return(NULL);
1834 }
1835
1836 if (elem == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001837#ifdef DEBUG_TREE
Daniel Veillardb96e6431999-08-29 21:02:19 +00001838 fprintf(stderr, "xmlAddSibling : elem == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001839#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +00001840 return(NULL);
1841 }
1842
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00001843 /*
1844 * Constant time is we can rely on the ->parent->last to find
1845 * the last sibling.
1846 */
1847 if ((cur->parent != NULL) &&
1848 (cur->parent->childs != NULL) &&
1849 (cur->parent->last != NULL) &&
1850 (cur->parent->last->next == NULL)) {
1851 cur = cur->parent->last;
1852 } else {
1853 while (cur->next != NULL) cur = cur->next;
Daniel Veillardb96e6431999-08-29 21:02:19 +00001854 }
1855
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00001856 xmlUnlinkNode(elem);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001857 if (elem->doc == NULL)
1858 elem->doc = cur->doc; /* the parent may not be linked to a doc ! */
1859
1860 parent = cur->parent;
1861 elem->prev = cur;
1862 elem->next = NULL;
1863 elem->parent = parent;
1864 cur->next = elem;
1865 if (parent != NULL)
1866 parent->last = elem;
1867
1868 return(elem);
1869}
1870
1871/**
Daniel Veillard97b58771998-10-20 06:14:16 +00001872 * xmlAddChild:
1873 * @parent: the parent node
1874 * @cur: the child node
1875 *
1876 * Add a new child element, to @parent, at the end of the child list.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001877 * Returns the child or NULL in case of error.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001878 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001879xmlNodePtr
1880xmlAddChild(xmlNodePtr parent, xmlNodePtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001881 xmlNodePtr prev;
1882
1883 if (parent == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001884#ifdef DEBUG_TREE
Daniel Veillard10a2c651999-12-12 13:03:50 +00001885 fprintf(stderr, "xmlAddChild : parent == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001886#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001887 return(NULL);
1888 }
1889
1890 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001891#ifdef DEBUG_TREE
Daniel Veillard10a2c651999-12-12 13:03:50 +00001892 fprintf(stderr, "xmlAddChild : child == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001893#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001894 return(NULL);
1895 }
1896
Daniel Veillard0bef1311998-10-14 02:36:47 +00001897 if ((cur->doc != NULL) && (parent->doc != NULL) &&
1898 (cur->doc != parent->doc)) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001899#ifdef DEBUG_TREE
Daniel Veillard0bef1311998-10-14 02:36:47 +00001900 fprintf(stderr, "Elements moved to a different document\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001901#endif
Daniel Veillard0bef1311998-10-14 02:36:47 +00001902 }
1903
Daniel Veillard260a68f1998-08-13 03:39:55 +00001904 /*
1905 * add the new element at the end of the childs list.
1906 */
1907 cur->parent = parent;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001908 cur->doc = parent->doc; /* the parent may not be linked to a doc ! */
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001909
Daniel Veillardccb09631998-10-27 06:21:04 +00001910 /*
1911 * Handle the case where parent->content != NULL, in that case it will
1912 * create a intermediate TEXT node.
1913 */
1914 if (parent->content != NULL) {
1915 xmlNodePtr text;
1916
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001917#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardccb09631998-10-27 06:21:04 +00001918 text = xmlNewDocText(parent->doc, parent->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001919#else
1920 text = xmlNewDocText(parent->doc, xmlBufferContent(parent->content));
1921#endif
Daniel Veillardccb09631998-10-27 06:21:04 +00001922 if (text != NULL) {
1923 text->next = parent->childs;
1924 if (text->next != NULL)
1925 text->next->prev = text;
1926 parent->childs = text;
Daniel Veillard1e346af1999-02-22 10:33:01 +00001927 UPDATE_LAST_CHILD(parent)
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001928#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard6454aec1999-09-02 22:04:43 +00001929 xmlFree(parent->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001930#else
1931 xmlBufferFree(parent->content);
1932#endif
Daniel Veillardccb09631998-10-27 06:21:04 +00001933 parent->content = NULL;
1934 }
1935 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00001936 if (parent->childs == NULL) {
1937 parent->childs = cur;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001938 parent->last = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001939 } else {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001940 prev = parent->last;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001941 prev->next = cur;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001942 cur->prev = prev;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001943 parent->last = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001944 }
1945
1946 return(cur);
1947}
1948
Daniel Veillard97b58771998-10-20 06:14:16 +00001949/**
1950 * xmlGetLastChild:
1951 * @parent: the parent node
1952 *
1953 * Search the last child of a node.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001954 * Returns the last child or NULL if none.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001955 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001956xmlNodePtr
1957xmlGetLastChild(xmlNodePtr parent) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001958 if (parent == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001959#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00001960 fprintf(stderr, "xmlGetLastChild : parent == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001961#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001962 return(NULL);
1963 }
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001964 return(parent->last);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001965}
1966
Daniel Veillard97b58771998-10-20 06:14:16 +00001967/**
1968 * xmlFreeNodeList:
1969 * @cur: the first node in the list
1970 *
1971 * Free a node and all its siblings, this is a recursive behaviour, all
1972 * the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001973 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001974void
1975xmlFreeNodeList(xmlNodePtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001976 xmlNodePtr next;
1977 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001978#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00001979 fprintf(stderr, "xmlFreeNodeList : node == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001980#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001981 return;
1982 }
1983 while (cur != NULL) {
1984 next = cur->next;
1985 xmlFreeNode(cur);
1986 cur = next;
1987 }
1988}
1989
Daniel Veillard97b58771998-10-20 06:14:16 +00001990/**
1991 * xmlFreeNode:
1992 * @cur: the node
1993 *
1994 * Free a node, this is a recursive behaviour, all the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001995 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001996void
1997xmlFreeNode(xmlNodePtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001998 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001999#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00002000 fprintf(stderr, "xmlFreeNode : node == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00002001#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00002002 return;
2003 }
Daniel Veillardccb09631998-10-27 06:21:04 +00002004 cur->doc = NULL;
2005 cur->parent = NULL;
2006 cur->next = NULL;
2007 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002008 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillardccb09631998-10-27 06:21:04 +00002009 if (cur->properties != NULL) xmlFreePropList(cur->properties);
2010 if (cur->type != XML_ENTITY_REF_NODE)
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002011#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard6454aec1999-09-02 22:04:43 +00002012 if (cur->content != NULL) xmlFree(cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002013#else
2014 if (cur->content != NULL) xmlBufferFree(cur->content);
2015#endif
Daniel Veillard6454aec1999-09-02 22:04:43 +00002016 if (cur->name != NULL) xmlFree((char *) cur->name);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002017 if (cur->nsDef != NULL) xmlFreeNsList(cur->nsDef);
2018 memset(cur, -1, sizeof(xmlNode));
Daniel Veillard6454aec1999-09-02 22:04:43 +00002019 xmlFree(cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002020}
2021
Daniel Veillard16253641998-10-28 22:58:05 +00002022/**
2023 * xmlUnlinkNode:
2024 * @cur: the node
2025 *
2026 * Unlink a node from it's current context, the node is not freed
2027 */
2028void
2029xmlUnlinkNode(xmlNodePtr cur) {
2030 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00002031#ifdef DEBUG_TREE
Daniel Veillard16253641998-10-28 22:58:05 +00002032 fprintf(stderr, "xmlUnlinkNode : node == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00002033#endif
Daniel Veillard16253641998-10-28 22:58:05 +00002034 return;
2035 }
2036 if ((cur->parent != NULL) && (cur->parent->childs == cur))
2037 cur->parent->childs = cur->next;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002038 if ((cur->parent != NULL) && (cur->parent->last == cur))
2039 cur->parent->last = cur->prev;
Daniel Veillard16253641998-10-28 22:58:05 +00002040 if (cur->next != NULL)
2041 cur->next->prev = cur->prev;
2042 if (cur->prev != NULL)
2043 cur->prev->next = cur->next;
2044 cur->next = cur->prev = NULL;
2045 cur->parent = NULL;
2046}
2047
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00002048/**
2049 * xmlReplaceNode:
2050 * @old: the old node
2051 * @cur: the node
2052 *
2053 * Unlink the old node from it's current context, prune the new one
2054 * at the same place. If cur was already inserted in a document it is
2055 * first unlinked from its existing context.
2056 *
2057 * Returns the old node
2058 */
2059xmlNodePtr
2060xmlReplaceNode(xmlNodePtr old, xmlNodePtr cur) {
2061 if (old == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00002062#ifdef DEBUG_TREE
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00002063 fprintf(stderr, "xmlReplaceNode : old == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00002064#endif
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00002065 return(NULL);
2066 }
2067 if (cur == NULL) {
2068 xmlUnlinkNode(old);
2069 return(old);
2070 }
2071 xmlUnlinkNode(cur);
2072 cur->doc = old->doc;
2073 cur->parent = old->parent;
2074 cur->next = old->next;
2075 if (cur->next != NULL)
2076 cur->next->prev = cur;
2077 cur->prev = old->prev;
2078 if (cur->prev != NULL)
2079 cur->prev->next = cur;
2080 if (cur->parent != NULL) {
2081 if (cur->parent->childs == old)
2082 cur->parent->childs = cur;
2083 if (cur->parent->last == old)
2084 cur->parent->last = cur;
2085 }
2086 old->next = old->prev = NULL;
2087 old->parent = NULL;
2088 return(old);
2089}
2090
Daniel Veillard260a68f1998-08-13 03:39:55 +00002091/************************************************************************
2092 * *
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002093 * Copy operations *
2094 * *
2095 ************************************************************************/
2096
2097/**
2098 * xmlCopyNamespace:
2099 * @cur: the namespace
2100 *
2101 * Do a copy of the namespace.
2102 *
2103 * Returns: a new xmlNsPtr, or NULL in case of error.
2104 */
2105xmlNsPtr
2106xmlCopyNamespace(xmlNsPtr cur) {
2107 xmlNsPtr ret;
2108
2109 if (cur == NULL) return(NULL);
2110 switch (cur->type) {
2111 case XML_GLOBAL_NAMESPACE:
2112 ret = xmlNewGlobalNs(NULL, cur->href, cur->prefix);
2113 break;
2114 case XML_LOCAL_NAMESPACE:
2115 ret = xmlNewNs(NULL, cur->href, cur->prefix);
2116 break;
2117 default:
Daniel Veillardad8f99d2000-01-15 14:20:03 +00002118#ifdef DEBUG_TREE
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002119 fprintf(stderr, "xmlCopyNamespace: unknown type %d\n", cur->type);
Daniel Veillardad8f99d2000-01-15 14:20:03 +00002120#endif
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002121 return(NULL);
2122 }
2123 return(ret);
2124}
2125
2126/**
2127 * xmlCopyNamespaceList:
2128 * @cur: the first namespace
2129 *
2130 * Do a copy of an namespace list.
2131 *
2132 * Returns: a new xmlNsPtr, or NULL in case of error.
2133 */
2134xmlNsPtr
2135xmlCopyNamespaceList(xmlNsPtr cur) {
2136 xmlNsPtr ret = NULL;
2137 xmlNsPtr p = NULL,q;
2138
2139 while (cur != NULL) {
2140 q = xmlCopyNamespace(cur);
2141 if (p == NULL) {
2142 ret = p = q;
2143 } else {
2144 p->next = q;
2145 p = q;
2146 }
2147 cur = cur->next;
2148 }
2149 return(ret);
2150}
2151
2152/**
2153 * xmlCopyProp:
Daniel Veillardb96e6431999-08-29 21:02:19 +00002154 * @target: the element where the attribute will be grafted
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002155 * @cur: the attribute
2156 *
2157 * Do a copy of the attribute.
2158 *
2159 * Returns: a new xmlAttrPtr, or NULL in case of error.
2160 */
2161xmlAttrPtr
Daniel Veillardb96e6431999-08-29 21:02:19 +00002162xmlCopyProp(xmlNodePtr target, xmlAttrPtr cur) {
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002163 xmlAttrPtr ret;
2164
2165 if (cur == NULL) return(NULL);
2166 if (cur->val != NULL)
2167 ret = xmlNewDocProp(cur->val->doc, cur->name, NULL);
2168 else
2169 ret = xmlNewDocProp(NULL, cur->name, NULL);
2170 if (ret == NULL) return(NULL);
Daniel Veillardb96e6431999-08-29 21:02:19 +00002171
2172 if ((cur->ns != NULL) && (target != NULL)) {
2173 xmlNsPtr ns;
2174
2175 ns = xmlSearchNs(target->doc, target, cur->ns->prefix);
2176 ret->ns = ns;
2177 } else
2178 ret->ns = NULL;
2179
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002180 if (cur->val != NULL)
2181 ret->val = xmlCopyNodeList(cur->val);
2182 return(ret);
2183}
2184
2185/**
2186 * xmlCopyPropList:
Daniel Veillardb96e6431999-08-29 21:02:19 +00002187 * @target: the element where the attributes will be grafted
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002188 * @cur: the first attribute
2189 *
2190 * Do a copy of an attribute list.
2191 *
2192 * Returns: a new xmlAttrPtr, or NULL in case of error.
2193 */
2194xmlAttrPtr
Daniel Veillardb96e6431999-08-29 21:02:19 +00002195xmlCopyPropList(xmlNodePtr target, xmlAttrPtr cur) {
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002196 xmlAttrPtr ret = NULL;
2197 xmlAttrPtr p = NULL,q;
2198
2199 while (cur != NULL) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00002200 q = xmlCopyProp(target, cur);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002201 if (p == NULL) {
2202 ret = p = q;
2203 } else {
2204 p->next = q;
2205 p = q;
2206 }
2207 cur = cur->next;
2208 }
2209 return(ret);
2210}
2211
2212/*
Daniel Veillard11a48ec1999-11-23 10:40:46 +00002213 * NOTE abeut the CopyNode operations !
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002214 *
2215 * They are splitted into external and internal parts for one
2216 * tricky reason: namespaces. Doing a direct copy of a node
2217 * say RPM:Copyright without changing the namespace pointer to
2218 * something else can produce stale links. One way to do it is
2219 * to keep a reference counter but this doesn't work as soon
2220 * as one move the element or the subtree out of the scope of
2221 * the existing namespace. The actual solution seems to add
2222 * a copy of the namespace at the top of the copied tree if
2223 * not available in the subtree.
2224 * Hence two functions, the public front-end call the inner ones
2225 */
2226
2227static xmlNodePtr
2228xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent);
2229
2230static xmlNodePtr
2231xmlStaticCopyNode(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent,
2232 int recursive) {
2233 xmlNodePtr ret;
2234
2235 if (node == NULL) return(NULL);
2236 /*
2237 * Allocate a new node and fill the fields.
2238 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00002239 ret = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002240 if (ret == NULL) {
2241 fprintf(stderr, "xmlStaticCopyNode : malloc failed\n");
2242 return(NULL);
2243 }
2244
2245 ret->type = node->type;
2246 ret->doc = doc;
2247 ret->parent = parent;
2248 ret->next = NULL;
2249 ret->prev = NULL;
2250 ret->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002251 ret->last = NULL;
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002252 ret->properties = NULL;
2253 if (node->name != NULL)
2254 ret->name = xmlStrdup(node->name);
2255 else
2256 ret->name = NULL;
2257 ret->ns = NULL;
2258 ret->nsDef = NULL;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002259 if ((node->content != NULL) && (node->type != XML_ENTITY_REF_NODE)) {
2260#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002261 ret->content = xmlStrdup(node->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002262#else
2263 ret->content = xmlBufferCreateSize(xmlBufferLength(node->content));
2264 xmlBufferSetAllocationScheme(ret->content,
2265 xmlGetBufferAllocationScheme());
2266 xmlBufferAdd(ret->content,
2267 xmlBufferContent(node->content),
2268 xmlBufferLength(node->content));
2269#endif
2270 } else
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002271 ret->content = NULL;
Daniel Veillard27d88741999-05-29 11:51:49 +00002272#ifndef XML_WITHOUT_CORBA
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002273 ret->_private = NULL;
2274 ret->vepv = NULL;
2275#endif
2276 if (parent != NULL)
2277 xmlAddChild(parent, ret);
2278
2279 if (!recursive) return(ret);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002280 if (node->nsDef != NULL)
2281 ret->nsDef = xmlCopyNamespaceList(node->nsDef);
2282
2283 if (node->ns != NULL) {
2284 xmlNsPtr ns;
2285
2286 ns = xmlSearchNs(doc, ret, node->ns->prefix);
2287 if (ns == NULL) {
2288 /*
2289 * Humm, we are copying an element whose namespace is defined
2290 * out of the new tree scope. Search it in the original tree
2291 * and add it at the top of the new tree
2292 */
2293 ns = xmlSearchNs(node->doc, node, node->ns->prefix);
2294 if (ns != NULL) {
2295 xmlNodePtr root = ret;
2296
2297 while (root->parent != NULL) root = root->parent;
2298 xmlNewNs(root, ns->href, ns->prefix);
2299 }
2300 } else {
2301 /*
2302 * reference the existing namespace definition in our own tree.
2303 */
2304 ret->ns = ns;
2305 }
2306 }
Daniel Veillardb96e6431999-08-29 21:02:19 +00002307 if (node->properties != NULL)
2308 ret->properties = xmlCopyPropList(ret, node->properties);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002309 if (node->childs != NULL)
2310 ret->childs = xmlStaticCopyNodeList(node->childs, doc, ret);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002311 UPDATE_LAST_CHILD(ret)
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002312 return(ret);
2313}
2314
2315static xmlNodePtr
2316xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent) {
2317 xmlNodePtr ret = NULL;
2318 xmlNodePtr p = NULL,q;
2319
2320 while (node != NULL) {
2321 q = xmlStaticCopyNode(node, doc, parent, 1);
2322 if (parent == NULL) {
2323 if (ret == NULL) ret = q;
2324 } else {
2325 if (ret == NULL) {
2326 q->prev = NULL;
2327 ret = p = q;
2328 } else {
2329 p->next = q;
2330 q->prev = p;
2331 p = q;
2332 }
2333 }
2334 node = node->next;
2335 }
2336 return(ret);
2337}
2338
2339/**
2340 * xmlCopyNode:
2341 * @node: the node
2342 * @recursive: if 1 do a recursive copy.
2343 *
2344 * Do a copy of the node.
2345 *
2346 * Returns: a new xmlNodePtr, or NULL in case of error.
2347 */
2348xmlNodePtr
2349xmlCopyNode(xmlNodePtr node, int recursive) {
2350 xmlNodePtr ret;
2351
2352 ret = xmlStaticCopyNode(node, NULL, NULL, recursive);
2353 return(ret);
2354}
2355
2356/**
2357 * xmlCopyNodeList:
2358 * @node: the first node in the list.
2359 *
2360 * Do a recursive copy of the node list.
2361 *
2362 * Returns: a new xmlNodePtr, or NULL in case of error.
2363 */
2364xmlNodePtr xmlCopyNodeList(xmlNodePtr node) {
2365 xmlNodePtr ret = xmlStaticCopyNodeList(node, NULL, NULL);
2366 return(ret);
2367}
2368
2369/**
2370 * xmlCopyElement:
2371 * @elem: the element
2372 *
2373 * Do a copy of the element definition.
2374 *
2375 * Returns: a new xmlElementPtr, or NULL in case of error.
2376xmlElementPtr
2377xmlCopyElement(xmlElementPtr elem) {
2378 xmlElementPtr ret;
2379
2380 if (elem == NULL) return(NULL);
2381 ret = xmlNewDocElement(elem->doc, elem->ns, elem->name, elem->content);
2382 if (ret == NULL) return(NULL);
2383 if (!recursive) return(ret);
2384 if (elem->properties != NULL)
2385 ret->properties = xmlCopyPropList(elem->properties);
2386
2387 if (elem->nsDef != NULL)
2388 ret->nsDef = xmlCopyNamespaceList(elem->nsDef);
2389 if (elem->childs != NULL)
2390 ret->childs = xmlCopyElementList(elem->childs);
2391 return(ret);
2392}
2393 */
2394
2395/**
2396 * xmlCopyDtd:
2397 * @dtd: the dtd
2398 *
2399 * Do a copy of the dtd.
2400 *
2401 * Returns: a new xmlDtdPtr, or NULL in case of error.
2402 */
2403xmlDtdPtr
2404xmlCopyDtd(xmlDtdPtr dtd) {
2405 xmlDtdPtr ret;
2406
2407 if (dtd == NULL) return(NULL);
2408 ret = xmlNewDtd(NULL, dtd->name, dtd->ExternalID, dtd->SystemID);
2409 if (ret == NULL) return(NULL);
2410 if (dtd->entities != NULL)
2411 ret->entities = (void *) xmlCopyEntitiesTable(
2412 (xmlEntitiesTablePtr) dtd->entities);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002413 if (dtd->notations != NULL)
2414 ret->notations = (void *) xmlCopyNotationTable(
2415 (xmlNotationTablePtr) dtd->notations);
2416 if (dtd->elements != NULL)
2417 ret->elements = (void *) xmlCopyElementTable(
2418 (xmlElementTablePtr) dtd->elements);
2419 if (dtd->attributes != NULL)
2420 ret->attributes = (void *) xmlCopyAttributeTable(
2421 (xmlAttributeTablePtr) dtd->attributes);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002422 return(ret);
2423}
2424
2425/**
2426 * xmlCopyDoc:
2427 * @doc: the document
2428 * @recursive: if 1 do a recursive copy.
2429 *
2430 * Do a copy of the document info. If recursive, the content tree will
2431 * be copied too as well as Dtd, namespaces and entities.
2432 *
2433 * Returns: a new xmlDocPtr, or NULL in case of error.
2434 */
2435xmlDocPtr
2436xmlCopyDoc(xmlDocPtr doc, int recursive) {
2437 xmlDocPtr ret;
2438
2439 if (doc == NULL) return(NULL);
2440 ret = xmlNewDoc(doc->version);
2441 if (ret == NULL) return(NULL);
2442 if (doc->name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +00002443 ret->name = xmlMemStrdup(doc->name);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002444 if (doc->encoding != NULL)
2445 ret->encoding = xmlStrdup(doc->encoding);
2446 ret->compression = doc->compression;
2447 ret->standalone = doc->standalone;
2448 if (!recursive) return(ret);
2449
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002450 if (doc->intSubset != NULL)
2451 ret->intSubset = xmlCopyDtd(doc->intSubset);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002452 if (doc->oldNs != NULL)
2453 ret->oldNs = xmlCopyNamespaceList(doc->oldNs);
2454 if (doc->root != NULL)
2455 ret->root = xmlStaticCopyNodeList(doc->root, ret, NULL);
2456 return(ret);
2457}
2458
2459/************************************************************************
2460 * *
Daniel Veillard260a68f1998-08-13 03:39:55 +00002461 * Content access functions *
2462 * *
2463 ************************************************************************/
2464
Daniel Veillard97b58771998-10-20 06:14:16 +00002465/**
Daniel Veillard944b5ff1999-12-15 19:08:24 +00002466 * xmlDocGetRootElement:
2467 * @doc: the document
2468 *
2469 * Get the root element of the document (doc->root is a list
2470 * containing possibly comments, PIs, etc ...).
2471 *
2472 * Returns the xmlNodePtr for the root or NULL
2473 */
2474xmlNodePtr
2475xmlDocGetRootElement(xmlDocPtr doc) {
2476 xmlNodePtr ret;
2477
2478 if (doc == NULL) return(NULL);
2479 ret = doc->root;
2480 while (ret != NULL) {
2481 if (ret->type == XML_ELEMENT_NODE)
2482 return(ret);
2483 ret = ret->next;
2484 }
2485 return(ret);
2486}
2487
2488/**
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00002489 * xmlDocSetRootElement:
2490 * @doc: the document
2491 * @root: the new document root element
2492 *
2493 * Set the root element of the document (doc->root is a list
2494 * containing possibly comments, PIs, etc ...).
2495 *
2496 * Returns the old root element if any was found
2497 */
2498xmlNodePtr
2499xmlDocSetRootElement(xmlDocPtr doc, xmlNodePtr root) {
2500 xmlNodePtr old = NULL;
2501
2502 if (doc == NULL) return(NULL);
2503 old = doc->root;
2504 while (old != NULL) {
2505 if (old->type == XML_ELEMENT_NODE)
2506 break;
2507 old = old->next;
2508 }
2509 if (old == NULL) {
2510 if (doc->root == NULL) {
2511 doc->root = root;
2512 } else {
2513 xmlAddSibling(doc->root, root);
2514 }
2515 } else {
2516 xmlReplaceNode(old, root);
2517 }
2518 return(old);
2519}
2520
2521/**
Daniel Veillardb96e6431999-08-29 21:02:19 +00002522 * xmlNodeSetLang:
2523 * @cur: the node being changed
2524 * @lang: the langage description
2525 *
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00002526 * Set the language of a node, i.e. the values of the xml:lang
2527 * attribute.
Daniel Veillardb96e6431999-08-29 21:02:19 +00002528 */
2529void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002530xmlNodeSetLang(xmlNodePtr cur, const xmlChar *lang) {
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00002531 if (cur == NULL) return;
2532 switch(cur->type) {
2533 case XML_TEXT_NODE:
2534 case XML_CDATA_SECTION_NODE:
2535 case XML_COMMENT_NODE:
2536 case XML_DOCUMENT_NODE:
2537 case XML_DOCUMENT_TYPE_NODE:
2538 case XML_DOCUMENT_FRAG_NODE:
2539 case XML_NOTATION_NODE:
2540 case XML_HTML_DOCUMENT_NODE:
2541 return;
2542 case XML_ELEMENT_NODE:
2543 case XML_ATTRIBUTE_NODE:
2544 case XML_PI_NODE:
2545 case XML_ENTITY_REF_NODE:
2546 case XML_ENTITY_NODE:
2547 break;
2548 }
Daniel Veillardb96e6431999-08-29 21:02:19 +00002549 xmlSetProp(cur, BAD_CAST "xml:lang", lang);
2550}
2551
2552/**
2553 * xmlNodeGetLang:
2554 * @cur: the node being checked
2555 *
2556 * Searches the language of a node, i.e. the values of the xml:lang
2557 * attribute or the one carried by the nearest ancestor.
2558 *
2559 * Returns a pointer to the lang value, or NULL if not found
Daniel Veillarda819dac1999-11-24 18:04:22 +00002560 * It's up to the caller to free the memory.
Daniel Veillardb96e6431999-08-29 21:02:19 +00002561 */
Daniel Veillarda819dac1999-11-24 18:04:22 +00002562xmlChar *
Daniel Veillardb96e6431999-08-29 21:02:19 +00002563xmlNodeGetLang(xmlNodePtr cur) {
Daniel Veillarda819dac1999-11-24 18:04:22 +00002564 xmlChar *lang;
Daniel Veillardb96e6431999-08-29 21:02:19 +00002565
2566 while (cur != NULL) {
2567 lang = xmlGetProp(cur, BAD_CAST "xml:lang");
2568 if (lang != NULL)
2569 return(lang);
2570 cur = cur->parent;
2571 }
2572 return(NULL);
2573}
2574
2575/**
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00002576 * xmlNodeSetName:
2577 * @cur: the node being changed
2578 * @name: the new tag name
2579 *
2580 * Searches the language of a node, i.e. the values of the xml:lang
2581 * attribute or the one carried by the nearest ancestor.
2582 */
2583void
2584xmlNodeSetName(xmlNodePtr cur, const xmlChar *name) {
2585 if (cur == NULL) return;
2586 if (name == NULL) return;
2587 switch(cur->type) {
2588 case XML_TEXT_NODE:
2589 case XML_CDATA_SECTION_NODE:
2590 case XML_COMMENT_NODE:
2591 case XML_DOCUMENT_NODE:
2592 case XML_DOCUMENT_TYPE_NODE:
2593 case XML_DOCUMENT_FRAG_NODE:
2594 case XML_NOTATION_NODE:
2595 case XML_HTML_DOCUMENT_NODE:
2596 return;
2597 case XML_ELEMENT_NODE:
2598 case XML_ATTRIBUTE_NODE:
2599 case XML_PI_NODE:
2600 case XML_ENTITY_REF_NODE:
2601 case XML_ENTITY_NODE:
2602 break;
2603 }
2604 if (cur->name != NULL) xmlFree((xmlChar *) cur->name);
2605 cur->name = xmlStrdup(name);
2606}
2607
2608/**
Daniel Veillard10a2c651999-12-12 13:03:50 +00002609 * xmlNodeGetBase:
2610 * @doc: the document the node pertains to
2611 * @cur: the node being checked
2612 *
2613 * Searches for the BASE URL. The code should work on both XML
2614 * and HTML document even if base mechanisms are completely different.
2615 *
2616 * Returns a pointer to the base URL, or NULL if not found
2617 * It's up to the caller to free the memory.
2618 */
2619xmlChar *
2620xmlNodeGetBase(xmlDocPtr doc, xmlNodePtr cur) {
2621 xmlChar *base;
2622
2623 if ((cur == NULL) && (doc == NULL))
2624 return(NULL);
2625 if (doc == NULL) doc = cur->doc;
2626 if ((doc != NULL) && (doc->type == XML_HTML_DOCUMENT_NODE)) {
2627 cur = doc->root;
2628 while ((cur != NULL) && (cur->name != NULL)) {
2629 if (cur->type != XML_ELEMENT_NODE) {
2630 cur = cur->next;
2631 continue;
2632 }
2633 if ((!xmlStrcmp(cur->name, BAD_CAST "html")) ||
2634 (!xmlStrcmp(cur->name, BAD_CAST "HTML"))) {
2635 cur = cur->childs;
2636 continue;
2637 }
2638 if ((!xmlStrcmp(cur->name, BAD_CAST "head")) ||
2639 (!xmlStrcmp(cur->name, BAD_CAST "HEAD"))) {
2640 cur = cur->childs;
2641 continue;
2642 }
2643 if ((!xmlStrcmp(cur->name, BAD_CAST "base")) ||
2644 (!xmlStrcmp(cur->name, BAD_CAST "BASE"))) {
2645 base = xmlGetProp(cur, BAD_CAST "href");
2646 if (base != NULL) return(base);
2647 return(xmlGetProp(cur, BAD_CAST "HREF"));
2648 }
2649 }
2650 return(NULL);
2651 }
2652 while (cur != NULL) {
2653 base = xmlGetProp(cur, BAD_CAST "xml:base");
2654 if (base != NULL)
2655 return(base);
2656 cur = cur->parent;
2657 }
2658 return(NULL);
2659}
2660
2661/**
Daniel Veillard16253641998-10-28 22:58:05 +00002662 * xmlNodeGetContent:
2663 * @cur: the node being read
2664 *
2665 * Read the value of a node, this can be either the text carried
2666 * directly by this node if it's a TEXT node or the aggregate string
2667 * of the values carried by this node child's (TEXT and ENTITY_REF).
2668 * Entity references are substitued.
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002669 * Returns a new xmlChar * or NULL if no content is available.
Daniel Veillard5099ae81999-04-21 20:12:07 +00002670 * It's up to the caller to free the memory.
Daniel Veillard16253641998-10-28 22:58:05 +00002671 */
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002672xmlChar *
Daniel Veillard16253641998-10-28 22:58:05 +00002673xmlNodeGetContent(xmlNodePtr cur) {
2674 if (cur == NULL) return(NULL);
2675 switch (cur->type) {
2676 case XML_DOCUMENT_FRAG_NODE:
2677 case XML_ELEMENT_NODE:
2678 return(xmlNodeListGetString(cur->doc, cur->childs, 1));
2679 break;
Daniel Veillardb96e6431999-08-29 21:02:19 +00002680 case XML_ATTRIBUTE_NODE: {
2681 xmlAttrPtr attr = (xmlAttrPtr) cur;
2682 if (attr->node != NULL)
2683 return(xmlNodeListGetString(attr->node->doc, attr->val, 1));
2684 else
2685 return(xmlNodeListGetString(NULL, attr->val, 1));
2686 break;
2687 }
Daniel Veillarddbfd6411999-12-28 16:35:14 +00002688 case XML_COMMENT_NODE:
Daniel Veillardb96e6431999-08-29 21:02:19 +00002689 case XML_PI_NODE:
2690 if (cur->content != NULL)
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002691#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardb96e6431999-08-29 21:02:19 +00002692 return(xmlStrdup(cur->content));
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002693#else
2694 return(xmlStrdup(xmlBufferContent(cur->content)));
2695#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +00002696 return(NULL);
Daniel Veillard16253641998-10-28 22:58:05 +00002697 case XML_ENTITY_REF_NODE:
Daniel Veillarddbfd6411999-12-28 16:35:14 +00002698 /*
2699 * Locate the entity, and get it's content
2700 * @@@
2701 */
2702 return(NULL);
Daniel Veillard16253641998-10-28 22:58:05 +00002703 case XML_ENTITY_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002704 case XML_DOCUMENT_NODE:
Daniel Veillard7c1206f1999-10-14 09:10:25 +00002705 case XML_HTML_DOCUMENT_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002706 case XML_DOCUMENT_TYPE_NODE:
2707 case XML_NOTATION_NODE:
2708 return(NULL);
Daniel Veillardb05deb71999-08-10 19:04:08 +00002709 case XML_CDATA_SECTION_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002710 case XML_TEXT_NODE:
2711 if (cur->content != NULL)
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002712#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard16253641998-10-28 22:58:05 +00002713 return(xmlStrdup(cur->content));
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002714#else
2715 return(xmlStrdup(xmlBufferContent(cur->content)));
2716#endif
Daniel Veillard16253641998-10-28 22:58:05 +00002717 return(NULL);
2718 }
2719 return(NULL);
2720}
2721
2722/**
Daniel Veillard97b58771998-10-20 06:14:16 +00002723 * xmlNodeSetContent:
2724 * @cur: the node being modified
2725 * @content: the new value of the content
2726 *
2727 * Replace the content of a node.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002728 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002729void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002730xmlNodeSetContent(xmlNodePtr cur, const xmlChar *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002731 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00002732#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00002733 fprintf(stderr, "xmlNodeSetContent : node == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00002734#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00002735 return;
2736 }
Daniel Veillard16253641998-10-28 22:58:05 +00002737 switch (cur->type) {
2738 case XML_DOCUMENT_FRAG_NODE:
2739 case XML_ELEMENT_NODE:
2740 if (cur->content != NULL) {
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002741#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard6454aec1999-09-02 22:04:43 +00002742 xmlFree(cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002743#else
2744 xmlBufferFree(cur->content);
2745#endif
Daniel Veillard16253641998-10-28 22:58:05 +00002746 cur->content = NULL;
2747 }
Daniel Veillard6454aec1999-09-02 22:04:43 +00002748 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillard16253641998-10-28 22:58:05 +00002749 cur->childs = xmlStringGetNodeList(cur->doc, content);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002750 UPDATE_LAST_CHILD(cur)
Daniel Veillard16253641998-10-28 22:58:05 +00002751 break;
2752 case XML_ATTRIBUTE_NODE:
2753 break;
2754 case XML_TEXT_NODE:
2755 case XML_CDATA_SECTION_NODE:
2756 case XML_ENTITY_REF_NODE:
2757 case XML_ENTITY_NODE:
2758 case XML_PI_NODE:
2759 case XML_COMMENT_NODE:
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002760 if (cur->content != NULL) {
2761#ifndef XML_USE_BUFFER_CONTENT
2762 xmlFree(cur->content);
2763#else
2764 xmlBufferFree(cur->content);
2765#endif
2766 }
Daniel Veillard6454aec1999-09-02 22:04:43 +00002767 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002768 cur->last = cur->childs = NULL;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002769 if (content != NULL) {
2770#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard16253641998-10-28 22:58:05 +00002771 cur->content = xmlStrdup(content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002772#else
2773 cur->content = xmlBufferCreateSize(0);
2774 xmlBufferSetAllocationScheme(cur->content,
2775 xmlGetBufferAllocationScheme());
2776 xmlBufferAdd(cur->content, content, -1);
2777#endif
2778 } else
Daniel Veillard16253641998-10-28 22:58:05 +00002779 cur->content = NULL;
Daniel Veillardb96e6431999-08-29 21:02:19 +00002780 break;
Daniel Veillard16253641998-10-28 22:58:05 +00002781 case XML_DOCUMENT_NODE:
Daniel Veillard7c1206f1999-10-14 09:10:25 +00002782 case XML_HTML_DOCUMENT_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002783 case XML_DOCUMENT_TYPE_NODE:
2784 break;
2785 case XML_NOTATION_NODE:
2786 break;
2787 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002788}
2789
Daniel Veillard97b58771998-10-20 06:14:16 +00002790/**
2791 * xmlNodeSetContentLen:
2792 * @cur: the node being modified
2793 * @content: the new value of the content
2794 * @len: the size of @content
2795 *
2796 * Replace the content of a node.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002797 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002798void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002799xmlNodeSetContentLen(xmlNodePtr cur, const xmlChar *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002800 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00002801#ifdef DEBUG_TREE
Daniel Veillard16253641998-10-28 22:58:05 +00002802 fprintf(stderr, "xmlNodeSetContentLen : node == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00002803#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00002804 return;
2805 }
Daniel Veillard16253641998-10-28 22:58:05 +00002806 switch (cur->type) {
2807 case XML_DOCUMENT_FRAG_NODE:
2808 case XML_ELEMENT_NODE:
2809 if (cur->content != NULL) {
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002810#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard6454aec1999-09-02 22:04:43 +00002811 xmlFree(cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002812#else
2813 xmlBufferFree(cur->content);
2814#endif
Daniel Veillard16253641998-10-28 22:58:05 +00002815 cur->content = NULL;
2816 }
Daniel Veillard6454aec1999-09-02 22:04:43 +00002817 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillard16253641998-10-28 22:58:05 +00002818 cur->childs = xmlStringLenGetNodeList(cur->doc, content, len);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002819 UPDATE_LAST_CHILD(cur)
Daniel Veillard16253641998-10-28 22:58:05 +00002820 break;
2821 case XML_ATTRIBUTE_NODE:
2822 break;
2823 case XML_TEXT_NODE:
2824 case XML_CDATA_SECTION_NODE:
2825 case XML_ENTITY_REF_NODE:
2826 case XML_ENTITY_NODE:
2827 case XML_PI_NODE:
2828 case XML_COMMENT_NODE:
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002829 case XML_NOTATION_NODE:
2830 if (cur->content != NULL) {
2831#ifndef XML_USE_BUFFER_CONTENT
2832 xmlFree(cur->content);
2833#else
2834 xmlBufferFree(cur->content);
2835#endif
2836 }
Daniel Veillard6454aec1999-09-02 22:04:43 +00002837 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002838 cur->childs = cur->last = NULL;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002839 if (content != NULL) {
2840#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard16253641998-10-28 22:58:05 +00002841 cur->content = xmlStrndup(content, len);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002842#else
2843 cur->content = xmlBufferCreateSize(len);
2844 xmlBufferSetAllocationScheme(cur->content,
2845 xmlGetBufferAllocationScheme());
2846 xmlBufferAdd(cur->content, content, len);
2847#endif
2848 } else
Daniel Veillard16253641998-10-28 22:58:05 +00002849 cur->content = NULL;
Daniel Veillardb96e6431999-08-29 21:02:19 +00002850 break;
Daniel Veillard16253641998-10-28 22:58:05 +00002851 case XML_DOCUMENT_NODE:
Daniel Veillard7c1206f1999-10-14 09:10:25 +00002852 case XML_HTML_DOCUMENT_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002853 case XML_DOCUMENT_TYPE_NODE:
2854 break;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002855 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002856}
2857
Daniel Veillard97b58771998-10-20 06:14:16 +00002858/**
2859 * xmlNodeAddContentLen:
2860 * @cur: the node being modified
2861 * @content: extra content
2862 * @len: the size of @content
2863 *
2864 * Append the extra substring to the node content.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002865 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002866void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002867xmlNodeAddContentLen(xmlNodePtr cur, const xmlChar *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002868 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00002869#ifdef DEBUG_TREE
Daniel Veillard16253641998-10-28 22:58:05 +00002870 fprintf(stderr, "xmlNodeAddContentLen : node == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00002871#endif
Daniel Veillard16253641998-10-28 22:58:05 +00002872 return;
2873 }
2874 if (len <= 0) return;
2875 switch (cur->type) {
2876 case XML_DOCUMENT_FRAG_NODE:
2877 case XML_ELEMENT_NODE: {
2878 xmlNodePtr last = NULL, new;
2879
2880 if (cur->childs != NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002881 last = cur->last;
Daniel Veillard16253641998-10-28 22:58:05 +00002882 } else {
2883 if (cur->content != NULL) {
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002884#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard16253641998-10-28 22:58:05 +00002885 cur->childs = xmlStringGetNodeList(cur->doc, cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002886#else
2887 cur->childs = xmlStringGetNodeList(cur->doc,
2888 xmlBufferContent(cur->content));
2889#endif
Daniel Veillard1e346af1999-02-22 10:33:01 +00002890 UPDATE_LAST_CHILD(cur)
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002891#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard6454aec1999-09-02 22:04:43 +00002892 xmlFree(cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002893#else
2894 xmlBufferFree(cur->content);
2895#endif
Daniel Veillard16253641998-10-28 22:58:05 +00002896 cur->content = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002897 last = cur->last;
Daniel Veillard16253641998-10-28 22:58:05 +00002898 }
2899 }
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002900 new = xmlNewTextLen(content, len);
Daniel Veillard16253641998-10-28 22:58:05 +00002901 if (new != NULL) {
2902 xmlAddChild(cur, new);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002903 if ((last != NULL) && (last->next == new)) {
Daniel Veillard16253641998-10-28 22:58:05 +00002904 xmlTextMerge(last, new);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002905 }
Daniel Veillard16253641998-10-28 22:58:05 +00002906 }
2907 break;
2908 }
2909 case XML_ATTRIBUTE_NODE:
2910 break;
2911 case XML_TEXT_NODE:
2912 case XML_CDATA_SECTION_NODE:
2913 case XML_ENTITY_REF_NODE:
2914 case XML_ENTITY_NODE:
2915 case XML_PI_NODE:
2916 case XML_COMMENT_NODE:
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002917 case XML_NOTATION_NODE:
2918 if (content != NULL) {
2919#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard16253641998-10-28 22:58:05 +00002920 cur->content = xmlStrncat(cur->content, content, len);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002921#else
2922 xmlBufferAdd(cur->content, content, len);
2923#endif
2924 }
Daniel Veillard16253641998-10-28 22:58:05 +00002925 case XML_DOCUMENT_NODE:
Daniel Veillard7c1206f1999-10-14 09:10:25 +00002926 case XML_HTML_DOCUMENT_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002927 case XML_DOCUMENT_TYPE_NODE:
2928 break;
Daniel Veillard16253641998-10-28 22:58:05 +00002929 }
2930}
2931
2932/**
2933 * xmlNodeAddContent:
2934 * @cur: the node being modified
2935 * @content: extra content
2936 *
2937 * Append the extra substring to the node content.
2938 */
2939void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002940xmlNodeAddContent(xmlNodePtr cur, const xmlChar *content) {
Daniel Veillard16253641998-10-28 22:58:05 +00002941 int len;
2942
2943 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00002944#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00002945 fprintf(stderr, "xmlNodeAddContent : node == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00002946#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00002947 return;
2948 }
Daniel Veillard16253641998-10-28 22:58:05 +00002949 if (content == NULL) return;
2950 len = xmlStrlen(content);
2951 xmlNodeAddContentLen(cur, content, len);
2952}
2953
2954/**
2955 * xmlTextMerge:
2956 * @first: the first text node
2957 * @second: the second text node being merged
2958 *
2959 * Merge two text nodes into one
Daniel Veillard1e346af1999-02-22 10:33:01 +00002960 * Returns the first text node augmented
Daniel Veillard16253641998-10-28 22:58:05 +00002961 */
2962xmlNodePtr
2963xmlTextMerge(xmlNodePtr first, xmlNodePtr second) {
2964 if (first == NULL) return(second);
2965 if (second == NULL) return(first);
2966 if (first->type != XML_TEXT_NODE) return(first);
2967 if (second->type != XML_TEXT_NODE) return(first);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002968#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard16253641998-10-28 22:58:05 +00002969 xmlNodeAddContent(first, second->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002970#else
2971 xmlNodeAddContent(first, xmlBufferContent(second->content));
2972#endif
Daniel Veillard16253641998-10-28 22:58:05 +00002973 xmlUnlinkNode(second);
2974 xmlFreeNode(second);
2975 return(first);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002976}
2977
Daniel Veillard97b58771998-10-20 06:14:16 +00002978/**
Daniel Veillardb96e6431999-08-29 21:02:19 +00002979 * xmlGetNsList:
2980 * @doc: the document
2981 * @node: the current node
2982 *
2983 * Search all the namespace applying to a given element.
2984 * Returns an NULL terminated array of all the xmlNsPtr found
2985 * that need to be freed by the caller or NULL if no
2986 * namespace if defined
2987 */
2988xmlNsPtr *
2989xmlGetNsList(xmlDocPtr doc, xmlNodePtr node) {
2990 xmlNsPtr cur;
2991 xmlNsPtr *ret = NULL;
2992 int nbns = 0;
2993 int maxns = 10;
2994 int i;
2995
2996 while (node != NULL) {
2997 cur = node->nsDef;
2998 while (cur != NULL) {
2999 if (ret == NULL) {
Daniel Veillard6454aec1999-09-02 22:04:43 +00003000 ret = (xmlNsPtr *) xmlMalloc((maxns + 1) * sizeof(xmlNsPtr));
Daniel Veillardb96e6431999-08-29 21:02:19 +00003001 if (ret == NULL) {
3002 fprintf(stderr, "xmlGetNsList : out of memory!\n");
3003 return(NULL);
3004 }
3005 ret[nbns] = NULL;
3006 }
3007 for (i = 0;i < nbns;i++) {
3008 if ((cur->prefix == ret[i]->prefix) ||
3009 (!xmlStrcmp(cur->prefix, ret[i]->prefix))) break;
3010 }
3011 if (i >= nbns) {
3012 if (nbns >= maxns) {
3013 maxns *= 2;
Daniel Veillard6454aec1999-09-02 22:04:43 +00003014 ret = (xmlNsPtr *) xmlRealloc(ret,
Daniel Veillardb96e6431999-08-29 21:02:19 +00003015 (maxns + 1) * sizeof(xmlNsPtr));
3016 if (ret == NULL) {
3017 fprintf(stderr, "xmlGetNsList : realloc failed!\n");
3018 return(NULL);
3019 }
3020 }
3021 ret[nbns++] = cur;
3022 ret[nbns] = NULL;
3023 }
3024
3025 cur = cur->next;
3026 }
3027 node = node->parent;
3028 }
3029 return(ret);
3030}
3031
3032/**
Daniel Veillard97b58771998-10-20 06:14:16 +00003033 * xmlSearchNs:
3034 * @doc: the document
3035 * @node: the current node
3036 * @nameSpace: the namespace string
Daniel Veillard260a68f1998-08-13 03:39:55 +00003037 *
Daniel Veillard97b58771998-10-20 06:14:16 +00003038 * Search a Ns registered under a given name space for a document.
3039 * recurse on the parents until it finds the defined namespace
3040 * or return NULL otherwise.
3041 * @nameSpace can be NULL, this is a search for the default namespace.
Daniel Veillard1e346af1999-02-22 10:33:01 +00003042 * Returns the namespace pointer or NULL.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003043 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003044xmlNsPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003045xmlSearchNs(xmlDocPtr doc, xmlNodePtr node, const xmlChar *nameSpace) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003046 xmlNsPtr cur;
3047
Daniel Veillard62ba71e1999-12-16 17:52:19 +00003048 if (node == NULL) return(NULL);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003049 while (node != NULL) {
3050 cur = node->nsDef;
3051 while (cur != NULL) {
3052 if ((cur->prefix == NULL) && (nameSpace == NULL))
3053 return(cur);
3054 if ((cur->prefix != NULL) && (nameSpace != NULL) &&
3055 (!xmlStrcmp(cur->prefix, nameSpace)))
3056 return(cur);
3057 cur = cur->next;
3058 }
3059 node = node->parent;
3060 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003061 return(NULL);
3062}
3063
Daniel Veillard97b58771998-10-20 06:14:16 +00003064/**
3065 * xmlSearchNsByHref:
3066 * @doc: the document
3067 * @node: the current node
3068 * @href: the namespace value
3069 *
3070 * Search a Ns aliasing a given URI. Recurse on the parents until it finds
3071 * the defined namespace or return NULL otherwise.
Daniel Veillard1e346af1999-02-22 10:33:01 +00003072 * Returns the namespace pointer or NULL.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003073 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003074xmlNsPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003075xmlSearchNsByHref(xmlDocPtr doc, xmlNodePtr node, const xmlChar *href) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003076 xmlNsPtr cur;
Daniel Veillarddbfd6411999-12-28 16:35:14 +00003077 xmlNodePtr orig = node;
Daniel Veillard260a68f1998-08-13 03:39:55 +00003078
Daniel Veillard10a2c651999-12-12 13:03:50 +00003079 if ((node == NULL) || (href == NULL)) return(NULL);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003080 while (node != NULL) {
3081 cur = node->nsDef;
3082 while (cur != NULL) {
3083 if ((cur->href != NULL) && (href != NULL) &&
Daniel Veillarddbfd6411999-12-28 16:35:14 +00003084 (!xmlStrcmp(cur->href, href))) {
3085 /*
3086 * Check that the prefix is not shadowed between orig and node
3087 */
3088 xmlNodePtr check = orig;
3089 xmlNsPtr tst;
3090
3091 while (check != node) {
3092 tst = check->nsDef;
3093 while (tst != NULL) {
3094 if ((tst->prefix == NULL) && (cur->prefix == NULL))
3095 goto shadowed;
3096 if ((tst->prefix != NULL) && (cur->prefix != NULL) &&
3097 (!xmlStrcmp(tst->prefix, cur->prefix)))
3098 goto shadowed;
3099 tst = tst->next;
3100 }
3101 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003102 return(cur);
Daniel Veillarddbfd6411999-12-28 16:35:14 +00003103 }
3104shadowed:
Daniel Veillard260a68f1998-08-13 03:39:55 +00003105 cur = cur->next;
3106 }
3107 node = node->parent;
3108 }
Daniel Veillarddbfd6411999-12-28 16:35:14 +00003109 return(NULL);
3110}
3111
3112/**
3113 * xmlNewReconciliedNs
3114 * @doc: the document
3115 * @tree: a node expected to hold the new namespace
3116 * @ns: the original namespace
3117 *
3118 * This function tries to locate a namespace definition in a tree
3119 * ancestors, or create a new namespace definition node similar to
3120 * @ns trying to reuse the same prefix. However if the given prefix is
3121 * null (default namespace) or reused within the subtree defined by
3122 * @tree or on one of its ancestors then a new prefix is generated.
3123 * Returns the (new) namespace definition or NULL in case of error
3124 */
3125xmlNsPtr
3126xmlNewReconciliedNs(xmlDocPtr doc, xmlNodePtr tree, xmlNsPtr ns) {
3127 xmlNsPtr def;
3128 xmlChar prefix[50];
3129 int counter = 1;
3130
3131 if (tree == NULL) {
3132#ifdef DEBUG_TREE
3133 fprintf(stderr, "xmlNewReconciliedNs : tree == NULL\n");
3134#endif
3135 return(NULL);
3136 }
3137 if (ns == NULL) {
3138#ifdef DEBUG_TREE
3139 fprintf(stderr, "xmlNewReconciliedNs : ns == NULL\n");
3140#endif
3141 return(NULL);
3142 }
3143 /*
3144 * Search an existing namespace definition inherited.
3145 */
3146 def = xmlSearchNsByHref(doc, tree, ns->href);
3147 if (def != NULL)
3148 return(def);
3149
3150 /*
3151 * Find a close prefix which is not already in use.
3152 * Let's strip namespace prefixes longer than 20 chars !
3153 */
3154 sprintf((char *) prefix, "%.20s", ns->prefix);
3155 def = xmlSearchNs(doc, tree, prefix);
3156 while (def != NULL) {
3157 if (counter > 1000) return(NULL);
3158 sprintf((char *) prefix, "%.20s%d", ns->prefix, counter++);
3159 def = xmlSearchNs(doc, tree, prefix);
3160 }
3161
3162 /*
3163 * Ok, now we are ready to create a new one.
3164 */
3165 def = xmlNewNs(tree, ns->href, prefix);
3166 return(def);
3167}
3168
3169/**
3170 * xmlReconciliateNs
3171 * @doc: the document
3172 * @tree: a node defining the subtree to reconciliate
3173 *
3174 * This function checks that all the namespaces declared within the given
3175 * tree are properly declared. This is needed for example after Copy or Cut
3176 * and then paste operations. The subtree may still hold pointers to
3177 * namespace declarations outside the subtree or invalid/masked. As much
3178 * as possible the function try tu reuse the existing namespaces found in
3179 * the new environment. If not possible the new namespaces are redeclared
3180 * on @tree at the top of the given subtree.
3181 * Returns the number of namespace declarations created or -1 in case of error.
3182 */
3183int
3184xmlReconciliateNs(xmlDocPtr doc, xmlNodePtr tree) {
3185 xmlNsPtr *oldNs = NULL;
3186 xmlNsPtr *newNs = NULL;
3187 int sizeCache = 0;
3188 int nbCache = 0;
3189
3190 xmlNsPtr n;
3191 xmlNodePtr node = tree;
3192 xmlAttrPtr attr;
3193 int ret = 0, i;
3194
3195 while (node != NULL) {
3196 /*
3197 * Reconciliate the node namespace
3198 */
3199 if (node->ns != NULL) {
3200 /*
3201 * initialize the cache if needed
3202 */
3203 if (sizeCache == 0) {
3204 sizeCache = 10;
3205 oldNs = (xmlNsPtr *) xmlMalloc(sizeCache *
3206 sizeof(xmlNsPtr));
3207 if (oldNs == NULL) {
3208 fprintf(stderr, "xmlReconciliateNs : memory pbm\n");
3209 return(-1);
3210 }
3211 newNs = (xmlNsPtr *) xmlMalloc(sizeCache *
3212 sizeof(xmlNsPtr));
3213 if (newNs == NULL) {
3214 fprintf(stderr, "xmlReconciliateNs : memory pbm\n");
3215 xmlFree(oldNs);
3216 return(-1);
3217 }
3218 }
3219 for (i = 0;i < nbCache;i++) {
3220 if (oldNs[i] == node->ns) {
3221 node->ns = newNs[i];
3222 break;
3223 }
3224 }
3225 if (i == nbCache) {
3226 /*
3227 * Ok we need to recreate a new namespace definition
3228 */
3229 n = xmlNewReconciliedNs(doc, tree, node->ns);
3230 if (n != NULL) { /* :-( what if else ??? */
3231 /*
3232 * check if we need to grow the cache buffers.
3233 */
3234 if (sizeCache <= nbCache) {
3235 sizeCache *= 2;
3236 oldNs = (xmlNsPtr *) xmlRealloc(oldNs, sizeCache *
3237 sizeof(xmlNsPtr));
3238 if (oldNs == NULL) {
3239 fprintf(stderr, "xmlReconciliateNs : memory pbm\n");
3240 xmlFree(newNs);
3241 return(-1);
3242 }
3243 newNs = (xmlNsPtr *) xmlRealloc(newNs, sizeCache *
3244 sizeof(xmlNsPtr));
3245 if (newNs == NULL) {
3246 fprintf(stderr, "xmlReconciliateNs : memory pbm\n");
3247 xmlFree(oldNs);
3248 return(-1);
3249 }
3250 }
3251 newNs[nbCache] = n;
3252 oldNs[nbCache++] = node->ns;
3253 node->ns = n;
3254 }
3255 }
3256 }
3257 /*
3258 * now check for namespace hold by attributes on the node.
3259 */
3260 attr = node->properties;
3261 while (attr != NULL) {
3262 if (attr->ns != NULL) {
3263 /*
3264 * initialize the cache if needed
3265 */
3266 if (sizeCache == 0) {
3267 sizeCache = 10;
3268 oldNs = (xmlNsPtr *) xmlMalloc(sizeCache *
3269 sizeof(xmlNsPtr));
3270 if (oldNs == NULL) {
3271 fprintf(stderr, "xmlReconciliateNs : memory pbm\n");
3272 return(-1);
3273 }
3274 newNs = (xmlNsPtr *) xmlMalloc(sizeCache *
3275 sizeof(xmlNsPtr));
3276 if (newNs == NULL) {
3277 fprintf(stderr, "xmlReconciliateNs : memory pbm\n");
3278 xmlFree(oldNs);
3279 return(-1);
3280 }
3281 }
3282 for (i = 0;i < nbCache;i++) {
3283 if (oldNs[i] == attr->ns) {
3284 node->ns = newNs[i];
3285 break;
3286 }
3287 }
3288 if (i == nbCache) {
3289 /*
3290 * Ok we need to recreate a new namespace definition
3291 */
3292 n = xmlNewReconciliedNs(doc, tree, attr->ns);
3293 if (n != NULL) { /* :-( what if else ??? */
3294 /*
3295 * check if we need to grow the cache buffers.
3296 */
3297 if (sizeCache <= nbCache) {
3298 sizeCache *= 2;
3299 oldNs = (xmlNsPtr *) xmlRealloc(oldNs, sizeCache *
3300 sizeof(xmlNsPtr));
3301 if (oldNs == NULL) {
3302 fprintf(stderr,
3303 "xmlReconciliateNs : memory pbm\n");
3304 xmlFree(newNs);
3305 return(-1);
3306 }
3307 newNs = (xmlNsPtr *) xmlRealloc(newNs, sizeCache *
3308 sizeof(xmlNsPtr));
3309 if (newNs == NULL) {
3310 fprintf(stderr,
3311 "xmlReconciliateNs : memory pbm\n");
3312 xmlFree(oldNs);
3313 return(-1);
3314 }
3315 }
3316 newNs[nbCache] = n;
3317 oldNs[nbCache++] = attr->ns;
3318 attr->ns = n;
3319 }
3320 }
3321 }
3322 attr = attr->next;
3323 }
3324
3325 /*
3326 * Browse the full subtree, deep first
3327 */
3328 if (node->childs != NULL) {
3329 /* deep first */
3330 node = node->childs;
3331 } else if ((node != tree) && (node->next != NULL)) {
3332 /* then siblings */
3333 node = node->next;
3334 } else if (node != tree) {
3335 /* go up to parents->next if needed */
3336 while (node != tree) {
3337 if (node->parent != NULL)
3338 node = node->parent;
3339 if ((node != tree) && (node->next != NULL)) {
3340 node = node->next;
3341 break;
3342 }
3343 if (node->parent == NULL) {
3344 node = NULL;
3345 break;
3346 }
3347 }
3348 /* exit condition */
3349 if (node == tree)
3350 node = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00003351 }
3352 }
Daniel Veillarddbfd6411999-12-28 16:35:14 +00003353 return(ret);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003354}
3355
Daniel Veillard97b58771998-10-20 06:14:16 +00003356/**
3357 * xmlGetProp:
3358 * @node: the node
3359 * @name: the attribute name
3360 *
3361 * Search and get the value of an attribute associated to a node
Daniel Veillardccb09631998-10-27 06:21:04 +00003362 * This does the entity substitution.
Daniel Veillard10a2c651999-12-12 13:03:50 +00003363 * This function looks in DTD attribute declaration for #FIXED or
3364 * default declaration values unless DTD use has been turned off.
3365 *
Daniel Veillard1e346af1999-02-22 10:33:01 +00003366 * Returns the attribute value or NULL if not found.
Daniel Veillarda819dac1999-11-24 18:04:22 +00003367 * It's up to the caller to free the memory.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003368 */
Daniel Veillarda819dac1999-11-24 18:04:22 +00003369xmlChar *
3370xmlGetProp(xmlNodePtr node, const xmlChar *name) {
Daniel Veillard10a2c651999-12-12 13:03:50 +00003371 xmlAttrPtr prop;
3372 xmlDocPtr doc;
Daniel Veillard260a68f1998-08-13 03:39:55 +00003373
Daniel Veillard10a2c651999-12-12 13:03:50 +00003374 if ((node == NULL) || (name == NULL)) return(NULL);
3375 /*
3376 * Check on the properties attached to the node
3377 */
3378 prop = node->properties;
Daniel Veillard260a68f1998-08-13 03:39:55 +00003379 while (prop != NULL) {
Daniel Veillard68178931999-02-08 18:34:36 +00003380 if (!xmlStrcmp(prop->name, name)) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003381 xmlChar *ret;
Daniel Veillard6800ef31999-02-08 18:33:22 +00003382
3383 ret = xmlNodeListGetString(node->doc, prop->val, 1);
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003384 if (ret == NULL) return(xmlStrdup((xmlChar *)""));
Daniel Veillard6800ef31999-02-08 18:33:22 +00003385 return(ret);
Daniel Veillard68178931999-02-08 18:34:36 +00003386 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003387 prop = prop->next;
3388 }
Daniel Veillard10a2c651999-12-12 13:03:50 +00003389 if (!xmlCheckDTD) return(NULL);
3390
3391 /*
3392 * Check if there is a default declaration in the internal
3393 * or external subsets
3394 */
3395 doc = node->doc;
3396 if (doc != NULL) {
3397 xmlAttributePtr attrDecl;
3398 if (doc->intSubset != NULL) {
3399 attrDecl = xmlGetDtdAttrDesc(doc->intSubset, node->name, name);
3400 if ((attrDecl == NULL) && (doc->extSubset != NULL))
3401 attrDecl = xmlGetDtdAttrDesc(doc->extSubset, node->name, name);
Daniel Veillardf967b902000-01-17 16:06:10 +00003402 if (attrDecl != NULL)
3403 return(xmlStrdup(attrDecl->defaultValue));
Daniel Veillard10a2c651999-12-12 13:03:50 +00003404 }
3405 }
3406 return(NULL);
3407}
3408
3409/**
3410 * xmlGetNsProp:
3411 * @node: the node
3412 * @name: the attribute name
3413 * @namespace: the URI of the namespace
3414 *
3415 * Search and get the value of an attribute associated to a node
3416 * This attribute has to be anchored in the namespace specified.
3417 * This does the entity substitution.
3418 * This function looks in DTD attribute declaration for #FIXED or
3419 * default declaration values unless DTD use has been turned off.
3420 *
3421 * Returns the attribute value or NULL if not found.
3422 * It's up to the caller to free the memory.
3423 */
3424xmlChar *
3425xmlGetNsProp(xmlNodePtr node, const xmlChar *name, const xmlChar *namespace) {
3426 xmlAttrPtr prop = node->properties;
3427 xmlDocPtr doc;
3428 xmlNsPtr ns;
3429
3430 if (namespace == NULL)
3431 return(xmlGetProp(node, name));
3432 while (prop != NULL) {
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00003433 /*
3434 * One need to have
3435 * - same attribute names
3436 * - and the attribute carrying that namespace
3437 * or
3438 * no namespace on the attribute and the element carrying it
3439 */
Daniel Veillard10a2c651999-12-12 13:03:50 +00003440 if ((!xmlStrcmp(prop->name, name)) &&
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00003441 (((prop->ns == NULL) && (node->ns != NULL) &&
3442 (!xmlStrcmp(node->ns->href, namespace))) ||
Daniel Veillard3c558c31999-12-22 11:30:41 +00003443 ((prop->ns != NULL) && (!xmlStrcmp(prop->ns->href, namespace))))) {
Daniel Veillard10a2c651999-12-12 13:03:50 +00003444 xmlChar *ret;
3445
3446 ret = xmlNodeListGetString(node->doc, prop->val, 1);
3447 if (ret == NULL) return(xmlStrdup((xmlChar *)""));
3448 return(ret);
3449 }
3450 prop = prop->next;
3451 }
3452 if (!xmlCheckDTD) return(NULL);
3453
3454 /*
3455 * Check if there is a default declaration in the internal
3456 * or external subsets
3457 */
3458 doc = node->doc;
3459 if (doc != NULL) {
3460 xmlAttributePtr attrDecl;
3461 if (doc->intSubset != NULL) {
3462 attrDecl = xmlGetDtdAttrDesc(doc->intSubset, node->name, name);
3463 if ((attrDecl == NULL) && (doc->extSubset != NULL))
3464 attrDecl = xmlGetDtdAttrDesc(doc->extSubset, node->name, name);
3465
3466 if (attrDecl->prefix != NULL) {
3467 /*
3468 * The DTD declaration only allows a prefix search
3469 */
3470 ns = xmlSearchNs(doc, node, attrDecl->prefix);
3471 if ((ns != NULL) && (!xmlStrcmp(ns->href, namespace)))
3472 return(xmlStrdup(attrDecl->defaultValue));
3473 }
3474 }
3475 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003476 return(NULL);
3477}
3478
Daniel Veillard97b58771998-10-20 06:14:16 +00003479/**
Daniel Veillardccb09631998-10-27 06:21:04 +00003480 * xmlSetProp:
Daniel Veillard97b58771998-10-20 06:14:16 +00003481 * @node: the node
3482 * @name: the attribute name
3483 * @value: the attribute value
3484 *
3485 * Set (or reset) an attribute carried by a node.
Daniel Veillard1e346af1999-02-22 10:33:01 +00003486 * Returns the attribute pointer.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003487 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003488xmlAttrPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003489xmlSetProp(xmlNodePtr node, const xmlChar *name, const xmlChar *value) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003490 xmlAttrPtr prop = node->properties;
3491
3492 while (prop != NULL) {
3493 if (!xmlStrcmp(prop->name, name)) {
Daniel Veillardccb09631998-10-27 06:21:04 +00003494 if (prop->val != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +00003495 xmlFreeNodeList(prop->val);
Daniel Veillardccb09631998-10-27 06:21:04 +00003496 prop->val = NULL;
Daniel Veillard51e3b151999-11-12 17:02:31 +00003497 if (value != NULL) {
3498 xmlChar *buffer;
3499 buffer = xmlEncodeEntitiesReentrant(node->doc, value);
3500 prop->val = xmlStringGetNodeList(node->doc, buffer);
3501 xmlFree(buffer);
3502 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003503 return(prop);
3504 }
3505 prop = prop->next;
3506 }
3507 prop = xmlNewProp(node, name, value);
3508 return(prop);
3509}
3510
Daniel Veillard97b58771998-10-20 06:14:16 +00003511/**
3512 * xmlNodeIsText:
3513 * @node: the node
3514 *
3515 * Is this node a Text node ?
Daniel Veillard1e346af1999-02-22 10:33:01 +00003516 * Returns 1 yes, 0 no
Daniel Veillard260a68f1998-08-13 03:39:55 +00003517 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003518int
3519xmlNodeIsText(xmlNodePtr node) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003520 if (node == NULL) return(0);
3521
Daniel Veillard0bef1311998-10-14 02:36:47 +00003522 if (node->type == XML_TEXT_NODE) return(1);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003523 return(0);
3524}
3525
Daniel Veillard97b58771998-10-20 06:14:16 +00003526/**
Daniel Veillard1e346af1999-02-22 10:33:01 +00003527 * xmlTextConcat:
Daniel Veillard97b58771998-10-20 06:14:16 +00003528 * @node: the node
3529 * @content: the content
3530 * @len: @content lenght
3531 *
3532 * Concat the given string at the end of the existing node content
Daniel Veillard260a68f1998-08-13 03:39:55 +00003533 */
Daniel Veillard97b58771998-10-20 06:14:16 +00003534
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003535void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003536xmlTextConcat(xmlNodePtr node, const xmlChar *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003537 if (node == NULL) return;
3538
Daniel Veillarddbfd6411999-12-28 16:35:14 +00003539 if ((node->type != XML_TEXT_NODE) &&
3540 (node->type != XML_CDATA_SECTION_NODE)) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00003541#ifdef DEBUG_TREE
Daniel Veillarddbfd6411999-12-28 16:35:14 +00003542 fprintf(stderr, "xmlTextConcat: node is not text nor cdata\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00003543#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00003544 return;
3545 }
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003546#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard260a68f1998-08-13 03:39:55 +00003547 node->content = xmlStrncat(node->content, content, len);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003548#else
3549 xmlBufferAdd(node->content, content, len);
3550#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00003551}
3552
3553/************************************************************************
3554 * *
3555 * Output : to a FILE or in memory *
3556 * *
3557 ************************************************************************/
3558
Daniel Veillard5099ae81999-04-21 20:12:07 +00003559#define BASE_BUFFER_SIZE 4000
3560
3561/**
3562 * xmlBufferCreate:
3563 *
3564 * routine to create an XML buffer.
3565 * returns the new structure.
3566 */
3567xmlBufferPtr
3568xmlBufferCreate(void) {
3569 xmlBufferPtr ret;
3570
Daniel Veillard6454aec1999-09-02 22:04:43 +00003571 ret = (xmlBufferPtr) xmlMalloc(sizeof(xmlBuffer));
Daniel Veillard5099ae81999-04-21 20:12:07 +00003572 if (ret == NULL) {
3573 fprintf(stderr, "xmlBufferCreate : out of memory!\n");
3574 return(NULL);
3575 }
3576 ret->use = 0;
3577 ret->size = BASE_BUFFER_SIZE;
Daniel Veillard10a2c651999-12-12 13:03:50 +00003578 ret->alloc = xmlBufferAllocScheme;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003579 ret->content = (xmlChar *) xmlMalloc(ret->size * sizeof(xmlChar));
Daniel Veillard5099ae81999-04-21 20:12:07 +00003580 if (ret->content == NULL) {
3581 fprintf(stderr, "xmlBufferCreate : out of memory!\n");
Daniel Veillard6454aec1999-09-02 22:04:43 +00003582 xmlFree(ret);
Daniel Veillard5099ae81999-04-21 20:12:07 +00003583 return(NULL);
3584 }
3585 ret->content[0] = 0;
3586 return(ret);
3587}
3588
3589/**
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003590 * xmlBufferCreateSize:
3591 * @size: initial size of buffer
3592 *
3593 * routine to create an XML buffer.
3594 * returns the new structure.
3595 */
3596xmlBufferPtr
3597xmlBufferCreateSize(size_t size) {
3598 xmlBufferPtr ret;
3599
3600 ret = (xmlBufferPtr) xmlMalloc(sizeof(xmlBuffer));
3601 if (ret == NULL) {
3602 fprintf(stderr, "xmlBufferCreate : out of memory!\n");
3603 return(NULL);
3604 }
3605 ret->use = 0;
Daniel Veillard10a2c651999-12-12 13:03:50 +00003606 ret->alloc = xmlBufferAllocScheme;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003607 ret->size = (size ? size+2 : 0); /* +1 for ending null */
Daniel Veillard10a2c651999-12-12 13:03:50 +00003608 if (ret->size){
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003609 ret->content = (xmlChar *) xmlMalloc(ret->size * sizeof(xmlChar));
3610 if (ret->content == NULL) {
3611 fprintf(stderr, "xmlBufferCreate : out of memory!\n");
3612 xmlFree(ret);
3613 return(NULL);
3614 }
3615 ret->content[0] = 0;
3616 } else
3617 ret->content = NULL;
3618 return(ret);
3619}
3620
3621/**
3622 * xmlBufferAllocationScheme:
3623 * @buf: the buffer to free
3624 * @scheme: allocation scheme to use
3625 *
3626 * Sets the allocation scheme for this buffer
3627 */
3628void
3629xmlBufferSetAllocationScheme(xmlBufferPtr buf,
3630 xmlBufferAllocationScheme scheme) {
3631 if (buf == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00003632#ifdef DEBUG_BUFFER
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003633 fprintf(stderr, "xmlBufferSetAllocationScheme: buf == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00003634#endif
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003635 return;
3636 }
3637
3638 buf->alloc = scheme;
3639}
3640
3641/**
Daniel Veillard5099ae81999-04-21 20:12:07 +00003642 * xmlBufferFree:
3643 * @buf: the buffer to free
3644 *
3645 * Frees an XML buffer.
3646 */
3647void
3648xmlBufferFree(xmlBufferPtr buf) {
3649 if (buf == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00003650#ifdef DEBUG_BUFFER
Daniel Veillard5099ae81999-04-21 20:12:07 +00003651 fprintf(stderr, "xmlBufferFree: buf == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00003652#endif
Daniel Veillard5099ae81999-04-21 20:12:07 +00003653 return;
3654 }
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003655 if (buf->content != NULL) {
3656#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard5099ae81999-04-21 20:12:07 +00003657 memset(buf->content, -1, BASE_BUFFER_SIZE);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003658#else
3659 memset(buf->content, -1, buf->size);
3660#endif
Daniel Veillard6454aec1999-09-02 22:04:43 +00003661 xmlFree(buf->content);
Daniel Veillard5099ae81999-04-21 20:12:07 +00003662 }
3663 memset(buf, -1, sizeof(xmlBuffer));
Daniel Veillard6454aec1999-09-02 22:04:43 +00003664 xmlFree(buf);
Daniel Veillard5099ae81999-04-21 20:12:07 +00003665}
3666
3667/**
Daniel Veillarde2d034d1999-07-27 19:52:06 +00003668 * xmlBufferEmpty:
3669 * @buf: the buffer
3670 *
3671 * empty a buffer.
3672 */
3673void
3674xmlBufferEmpty(xmlBufferPtr buf) {
3675 buf->use = 0;
3676 memset(buf->content, -1, buf->size);/* just for debug */
3677}
3678
3679/**
3680 * xmlBufferShrink:
3681 * @buf: the buffer to dump
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003682 * @len: the number of xmlChar to remove
Daniel Veillarde2d034d1999-07-27 19:52:06 +00003683 *
3684 * Remove the beginning of an XML buffer.
3685 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003686 * Returns the number of xmlChar removed, or -1 in case of failure.
Daniel Veillarde2d034d1999-07-27 19:52:06 +00003687 */
3688int
3689xmlBufferShrink(xmlBufferPtr buf, int len) {
3690 if (len == 0) return(0);
3691 if (len > buf->use) return(-1);
3692
3693 buf->use -= len;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003694 memmove(buf->content, &buf->content[len], buf->use * sizeof(xmlChar));
Daniel Veillarde2d034d1999-07-27 19:52:06 +00003695
3696 buf->content[buf->use] = 0;
3697 return(len);
3698}
3699
3700/**
Daniel Veillard5099ae81999-04-21 20:12:07 +00003701 * xmlBufferDump:
3702 * @file: the file output
3703 * @buf: the buffer to dump
3704 *
3705 * Dumps an XML buffer to a FILE *.
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003706 * Returns the number of xmlChar written
Daniel Veillard5099ae81999-04-21 20:12:07 +00003707 */
3708int
3709xmlBufferDump(FILE *file, xmlBufferPtr buf) {
3710 int ret;
3711
3712 if (buf == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00003713#ifdef DEBUG_BUFFER
Daniel Veillard5099ae81999-04-21 20:12:07 +00003714 fprintf(stderr, "xmlBufferDump: buf == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00003715#endif
Daniel Veillard5099ae81999-04-21 20:12:07 +00003716 return(0);
3717 }
3718 if (buf->content == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00003719#ifdef DEBUG_BUFFER
Daniel Veillard5099ae81999-04-21 20:12:07 +00003720 fprintf(stderr, "xmlBufferDump: buf->content == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00003721#endif
Daniel Veillard5099ae81999-04-21 20:12:07 +00003722 return(0);
3723 }
3724 if (file == NULL) file = stdout;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003725 ret = fwrite(buf->content, sizeof(xmlChar), buf->use, file);
Daniel Veillard5099ae81999-04-21 20:12:07 +00003726 return(ret);
3727}
3728
3729/**
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003730 * xmlBufferContent:
3731 * @buf: the buffer to resize
3732 *
3733 * Returns the internal content
3734 */
3735
3736const xmlChar*
3737xmlBufferContent(const xmlBufferPtr buf)
3738{
3739 if(!buf)
3740 return NULL;
3741
3742 return buf->content;
3743}
3744
3745/**
3746 * xmlBufferLength:
3747 * @buf: the buffer
3748 *
3749 * Returns the length of data in the internal content
3750 */
3751
3752int
3753xmlBufferLength(const xmlBufferPtr buf)
3754{
3755 if(!buf)
3756 return 0;
3757
3758 return buf->use;
3759}
3760
3761/**
3762 * xmlBufferResize:
3763 * @buf: the buffer to resize
3764 * @len: the desired size
3765 *
3766 * Resize a buffer to accomodate minimum size of <len>.
3767 *
3768 * Returns 0 in case of problems, 1 otherwise
3769 */
3770int
3771xmlBufferResize(xmlBufferPtr buf, int size)
3772{
3773 int newSize = (buf->size ? buf->size*2 : size);/*take care of empty case*/
3774 xmlChar* rebuf = NULL;
3775
3776 /* Don't resize if we don't have to */
3777 if(size < buf->size)
3778 return 1;
3779
3780 /* figure out new size */
3781 switch(buf->alloc){
3782 case XML_BUFFER_ALLOC_DOUBLEIT:
3783 while(size > newSize) newSize *= 2;
3784 break;
3785 case XML_BUFFER_ALLOC_EXACT:
3786 newSize = size+10;
3787 break;
3788 default:
3789 newSize = size+10;
3790 break;
3791 }
3792
3793 if (buf->content == NULL)
3794 rebuf = (xmlChar *) xmlMalloc(newSize * sizeof(xmlChar));
3795 else
3796 rebuf = (xmlChar *) xmlRealloc(buf->content,
3797 newSize * sizeof(xmlChar));
3798 if (rebuf == NULL) {
3799 fprintf(stderr, "xmlBufferAdd : out of memory!\n");
3800 return 0;
3801 }
3802 buf->content = rebuf;
3803 buf->size = newSize;
3804
3805 return 1;
3806}
3807/**
Daniel Veillard5099ae81999-04-21 20:12:07 +00003808 * xmlBufferAdd:
3809 * @buf: the buffer to dump
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003810 * @str: the xmlChar string
3811 * @len: the number of xmlChar to add
Daniel Veillard5099ae81999-04-21 20:12:07 +00003812 *
Daniel Veillard10a2c651999-12-12 13:03:50 +00003813 * Add a string range to an XML buffer. if len == -1, the lenght of
3814 * str is recomputed.
Daniel Veillard5099ae81999-04-21 20:12:07 +00003815 */
3816void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003817xmlBufferAdd(xmlBufferPtr buf, const xmlChar *str, int len) {
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003818 int l, needSize;
Daniel Veillard5099ae81999-04-21 20:12:07 +00003819
3820 if (str == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00003821#ifdef DEBUG_BUFFER
Daniel Veillard5099ae81999-04-21 20:12:07 +00003822 fprintf(stderr, "xmlBufferAdd: str == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00003823#endif
Daniel Veillard5099ae81999-04-21 20:12:07 +00003824 return;
3825 }
Daniel Veillard10a2c651999-12-12 13:03:50 +00003826 if (len < -1) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00003827#ifdef DEBUG_BUFFER
Daniel Veillard10a2c651999-12-12 13:03:50 +00003828 fprintf(stderr, "xmlBufferAdd: len < 0\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00003829#endif
Daniel Veillard10a2c651999-12-12 13:03:50 +00003830 return;
3831 }
3832 if (len == 0) return;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003833
3834 /* CJN What's this for??? */
Daniel Veillarddbfd6411999-12-28 16:35:14 +00003835 if (len < 0)
3836 l = xmlStrlen(str);
3837 else
3838 for (l = 0;l < len;l++)
3839 if (str[l] == 0) break;
Daniel Veillardad8f99d2000-01-15 14:20:03 +00003840 if (l < len){
3841 len = l;
3842#ifdef DEBUG_BUFFER
3843 printf("xmlBufferAdd bad length\n");
3844#endif
3845 }
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003846
3847 /* CJN 11.18.99 okay, now I'm using the length */
3848 if(len == -1) len = l;
3849
3850
Daniel Veillarde2d034d1999-07-27 19:52:06 +00003851 if (len <= 0) return;
Daniel Veillard5099ae81999-04-21 20:12:07 +00003852
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003853 needSize = buf->use + len + 2;
3854 if(needSize > buf->size){
3855 if(!xmlBufferResize(buf, needSize)){
3856 fprintf(stderr, "xmlBufferAdd : out of memory!\n");
3857 return;
3858 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003859 }
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003860
3861 memmove(&buf->content[buf->use], str, len*sizeof(xmlChar));
Daniel Veillarde2d034d1999-07-27 19:52:06 +00003862 buf->use += len;
3863 buf->content[buf->use] = 0;
Daniel Veillard5099ae81999-04-21 20:12:07 +00003864}
3865
3866/**
3867 * xmlBufferCat:
3868 * @buf: the buffer to dump
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003869 * @str: the xmlChar string
Daniel Veillard5099ae81999-04-21 20:12:07 +00003870 *
3871 * Append a zero terminated string to an XML buffer.
3872 */
3873void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003874xmlBufferCat(xmlBufferPtr buf, const xmlChar *str) {
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003875 if (str != NULL)
3876 xmlBufferAdd(buf, str, -1);
Daniel Veillard5099ae81999-04-21 20:12:07 +00003877}
3878
3879/**
3880 * xmlBufferCCat:
3881 * @buf: the buffer to dump
3882 * @str: the C char string
3883 *
3884 * Append a zero terminated C string to an XML buffer.
3885 */
3886void
3887xmlBufferCCat(xmlBufferPtr buf, const char *str) {
3888 const char *cur;
3889
3890 if (str == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00003891#ifdef DEBUG_BUFFER
Daniel Veillard5099ae81999-04-21 20:12:07 +00003892 fprintf(stderr, "xmlBufferAdd: str == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00003893#endif
Daniel Veillard5099ae81999-04-21 20:12:07 +00003894 return;
3895 }
3896 for (cur = str;*cur != 0;cur++) {
3897 if (buf->use + 10 >= buf->size) {
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003898 if(!xmlBufferResize(buf, buf->use+10)){
3899 fprintf(stderr, "xmlBufferCCat : out of memory!\n");
3900 return;
3901 }
3902 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003903 buf->content[buf->use++] = *cur;
3904 }
3905}
Daniel Veillard260a68f1998-08-13 03:39:55 +00003906
Daniel Veillard97b58771998-10-20 06:14:16 +00003907/**
3908 * xmlBufferWriteCHAR:
Daniel Veillard5099ae81999-04-21 20:12:07 +00003909 * @buf: the XML buffer
Daniel Veillard97b58771998-10-20 06:14:16 +00003910 * @string: the string to add
3911 *
3912 * routine which manage and grows an output buffer. This one add
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003913 * xmlChars at the end of the buffer.
Daniel Veillard97b58771998-10-20 06:14:16 +00003914 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003915void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003916xmlBufferWriteCHAR(xmlBufferPtr buf, const xmlChar *string) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003917 xmlBufferCat(buf, string);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003918}
3919
Daniel Veillard97b58771998-10-20 06:14:16 +00003920/**
3921 * xmlBufferWriteChar:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003922 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003923 * @string: the string to add
3924 *
3925 * routine which manage and grows an output buffer. This one add
3926 * C chars at the end of the array.
3927 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003928void
Daniel Veillard5099ae81999-04-21 20:12:07 +00003929xmlBufferWriteChar(xmlBufferPtr buf, const char *string) {
3930 xmlBufferCCat(buf, string);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003931}
3932
Daniel Veillard5099ae81999-04-21 20:12:07 +00003933
Daniel Veillard97b58771998-10-20 06:14:16 +00003934/**
Daniel Veillard011b63c1999-06-02 17:44:04 +00003935 * xmlBufferWriteQuotedString:
3936 * @buf: the XML buffer output
3937 * @string: the string to add
3938 *
3939 * routine which manage and grows an output buffer. This one writes
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003940 * a quoted or double quoted xmlChar string, checking first if it holds
Daniel Veillard011b63c1999-06-02 17:44:04 +00003941 * quote or double-quotes internally
3942 */
3943void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003944xmlBufferWriteQuotedString(xmlBufferPtr buf, const xmlChar *string) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00003945 if (xmlStrchr(string, '"')) {
3946 if (xmlStrchr(string, '\'')) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00003947#ifdef DEBUG_BUFFER
Daniel Veillard011b63c1999-06-02 17:44:04 +00003948 fprintf(stderr,
3949 "xmlBufferWriteQuotedString: string contains quote and double-quotes !\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00003950#endif
Daniel Veillard011b63c1999-06-02 17:44:04 +00003951 }
3952 xmlBufferCCat(buf, "'");
3953 xmlBufferCat(buf, string);
3954 xmlBufferCCat(buf, "'");
3955 } else {
3956 xmlBufferCCat(buf, "\"");
3957 xmlBufferCat(buf, string);
3958 xmlBufferCCat(buf, "\"");
3959 }
3960}
3961
3962
3963/**
Daniel Veillard97b58771998-10-20 06:14:16 +00003964 * xmlGlobalNsDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003965 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003966 * @cur: a namespace
3967 *
3968 * Dump a global Namespace, this is the old version based on PIs.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003969 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003970static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00003971xmlGlobalNsDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003972 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00003973#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00003974 fprintf(stderr, "xmlGlobalNsDump : Ns == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00003975#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00003976 return;
3977 }
3978 if (cur->type == XML_GLOBAL_NAMESPACE) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003979 xmlBufferWriteChar(buf, "<?namespace");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003980 if (cur->href != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00003981 xmlBufferWriteChar(buf, " href=");
3982 xmlBufferWriteQuotedString(buf, cur->href);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003983 }
3984 if (cur->prefix != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00003985 xmlBufferWriteChar(buf, " AS=");
3986 xmlBufferWriteQuotedString(buf, cur->prefix);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003987 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003988 xmlBufferWriteChar(buf, "?>\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003989 }
3990}
3991
Daniel Veillard97b58771998-10-20 06:14:16 +00003992/**
3993 * xmlGlobalNsListDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003994 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003995 * @cur: the first namespace
3996 *
3997 * Dump a list of global Namespace, this is the old version based on PIs.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003998 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003999static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00004000xmlGlobalNsListDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00004001 while (cur != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00004002 xmlGlobalNsDump(buf, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004003 cur = cur->next;
4004 }
4005}
4006
Daniel Veillard97b58771998-10-20 06:14:16 +00004007/**
4008 * xmlNsDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00004009 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00004010 * @cur: a namespace
4011 *
Daniel Veillard260a68f1998-08-13 03:39:55 +00004012 * Dump a local Namespace definition.
Daniel Veillard97b58771998-10-20 06:14:16 +00004013 * Should be called in the context of attributes dumps.
Daniel Veillard260a68f1998-08-13 03:39:55 +00004014 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00004015static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00004016xmlNsDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00004017 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004018#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00004019 fprintf(stderr, "xmlNsDump : Ns == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004020#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00004021 return;
4022 }
4023 if (cur->type == XML_LOCAL_NAMESPACE) {
4024 /* Within the context of an element attributes */
4025 if (cur->prefix != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00004026 xmlBufferWriteChar(buf, " xmlns:");
4027 xmlBufferWriteCHAR(buf, cur->prefix);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004028 } else
Daniel Veillard5099ae81999-04-21 20:12:07 +00004029 xmlBufferWriteChar(buf, " xmlns");
Daniel Veillard011b63c1999-06-02 17:44:04 +00004030 xmlBufferWriteChar(buf, "=");
4031 xmlBufferWriteQuotedString(buf, cur->href);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004032 }
4033}
4034
Daniel Veillard97b58771998-10-20 06:14:16 +00004035/**
4036 * xmlNsListDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00004037 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00004038 * @cur: the first namespace
4039 *
4040 * Dump a list of local Namespace definitions.
4041 * Should be called in the context of attributes dumps.
Daniel Veillard260a68f1998-08-13 03:39:55 +00004042 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00004043static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00004044xmlNsListDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00004045 while (cur != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00004046 xmlNsDump(buf, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004047 cur = cur->next;
4048 }
4049}
4050
Daniel Veillard97b58771998-10-20 06:14:16 +00004051/**
4052 * xmlDtdDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00004053 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00004054 * @doc: the document
4055 *
4056 * Dump the XML document DTD, if any.
Daniel Veillard260a68f1998-08-13 03:39:55 +00004057 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00004058static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00004059xmlDtdDump(xmlBufferPtr buf, xmlDocPtr doc) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004060 xmlDtdPtr cur = doc->intSubset;
Daniel Veillard260a68f1998-08-13 03:39:55 +00004061
4062 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004063#ifdef DEBUG_TREE
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004064 fprintf(stderr, "xmlDtdDump : no internal subset\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004065#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00004066 return;
4067 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00004068 xmlBufferWriteChar(buf, "<!DOCTYPE ");
4069 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004070 if (cur->ExternalID != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00004071 xmlBufferWriteChar(buf, " PUBLIC ");
4072 xmlBufferWriteQuotedString(buf, cur->ExternalID);
4073 xmlBufferWriteChar(buf, " ");
4074 xmlBufferWriteQuotedString(buf, cur->SystemID);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004075 } else if (cur->SystemID != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00004076 xmlBufferWriteChar(buf, " SYSTEM ");
4077 xmlBufferWriteQuotedString(buf, cur->SystemID);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004078 }
Daniel Veillard1e346af1999-02-22 10:33:01 +00004079 if ((cur->entities == NULL) && (cur->elements == NULL) &&
4080 (cur->attributes == NULL) && (cur->notations == NULL)) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00004081 xmlBufferWriteChar(buf, ">\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004082 return;
4083 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00004084 xmlBufferWriteChar(buf, " [\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004085 if (cur->entities != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00004086 xmlDumpEntitiesTable(buf, (xmlEntitiesTablePtr) cur->entities);
Daniel Veillard1e346af1999-02-22 10:33:01 +00004087 if (cur->notations != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00004088 xmlDumpNotationTable(buf, (xmlNotationTablePtr) cur->notations);
Daniel Veillard3b9def11999-01-31 22:15:06 +00004089 if (cur->elements != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00004090 xmlDumpElementTable(buf, (xmlElementTablePtr) cur->elements);
Daniel Veillard1e346af1999-02-22 10:33:01 +00004091 if (cur->attributes != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00004092 xmlDumpAttributeTable(buf, (xmlAttributeTablePtr) cur->attributes);
4093 xmlBufferWriteChar(buf, "]");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004094
Daniel Veillard5099ae81999-04-21 20:12:07 +00004095 xmlBufferWriteChar(buf, ">\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004096}
4097
Daniel Veillard97b58771998-10-20 06:14:16 +00004098/**
4099 * xmlAttrDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00004100 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00004101 * @doc: the document
4102 * @cur: the attribute pointer
4103 *
4104 * Dump an XML attribute
Daniel Veillard260a68f1998-08-13 03:39:55 +00004105 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00004106static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00004107xmlAttrDump(xmlBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004108 xmlChar *value;
Daniel Veillardccb09631998-10-27 06:21:04 +00004109
Daniel Veillard260a68f1998-08-13 03:39:55 +00004110 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004111#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00004112 fprintf(stderr, "xmlAttrDump : property == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004113#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00004114 return;
4115 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00004116 xmlBufferWriteChar(buf, " ");
Daniel Veillardb96e6431999-08-29 21:02:19 +00004117 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
4118 xmlBufferWriteCHAR(buf, cur->ns->prefix);
4119 xmlBufferWriteChar(buf, ":");
4120 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00004121 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillardccb09631998-10-27 06:21:04 +00004122 value = xmlNodeListGetString(doc, cur->val, 0);
4123 if (value) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00004124 xmlBufferWriteChar(buf, "=");
4125 xmlBufferWriteQuotedString(buf, value);
Daniel Veillard6454aec1999-09-02 22:04:43 +00004126 xmlFree(value);
Daniel Veillard726c7e31999-02-08 15:13:10 +00004127 } else {
Daniel Veillard5099ae81999-04-21 20:12:07 +00004128 xmlBufferWriteChar(buf, "=\"\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004129 }
4130}
4131
Daniel Veillard97b58771998-10-20 06:14:16 +00004132/**
4133 * xmlAttrListDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00004134 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00004135 * @doc: the document
4136 * @cur: the first attribute pointer
4137 *
4138 * Dump a list of XML attributes
Daniel Veillard260a68f1998-08-13 03:39:55 +00004139 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00004140static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00004141xmlAttrListDump(xmlBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00004142 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004143#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00004144 fprintf(stderr, "xmlAttrListDump : property == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004145#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00004146 return;
4147 }
4148 while (cur != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00004149 xmlAttrDump(buf, doc, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004150 cur = cur->next;
4151 }
4152}
4153
Daniel Veillard260a68f1998-08-13 03:39:55 +00004154
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00004155static void
Daniel Veillard7d2c2761999-10-11 15:09:51 +00004156xmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
4157 int format);
Daniel Veillarddbfd6411999-12-28 16:35:14 +00004158void
4159htmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur);
4160
Daniel Veillard97b58771998-10-20 06:14:16 +00004161/**
4162 * xmlNodeListDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00004163 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00004164 * @doc: the document
4165 * @cur: the first node
4166 * @level: the imbrication level for indenting
Daniel Veillard7d2c2761999-10-11 15:09:51 +00004167 * @format: is formatting allowed
Daniel Veillard97b58771998-10-20 06:14:16 +00004168 *
4169 * Dump an XML node list, recursive behaviour,children are printed too.
4170 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00004171static void
Daniel Veillard7d2c2761999-10-11 15:09:51 +00004172xmlNodeListDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
4173 int format) {
4174 int i;
Daniel Veillardccb09631998-10-27 06:21:04 +00004175
Daniel Veillard260a68f1998-08-13 03:39:55 +00004176 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004177#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00004178 fprintf(stderr, "xmlNodeListDump : node == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004179#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00004180 return;
4181 }
4182 while (cur != NULL) {
Daniel Veillard7d2c2761999-10-11 15:09:51 +00004183 if ((format) && (xmlIndentTreeOutput) &&
4184 (cur->type == XML_ELEMENT_NODE))
4185 for (i = 0;i < level;i++)
4186 xmlBufferWriteChar(buf, " ");
4187 xmlNodeDump(buf, doc, cur, level, format);
4188 if (format) {
4189 xmlBufferWriteChar(buf, "\n");
Daniel Veillardccb09631998-10-27 06:21:04 +00004190 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00004191 cur = cur->next;
4192 }
4193}
4194
Daniel Veillard97b58771998-10-20 06:14:16 +00004195/**
Daniel Veillardccb09631998-10-27 06:21:04 +00004196 * xmlNodeDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00004197 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00004198 * @doc: the document
4199 * @cur: the current node
4200 * @level: the imbrication level for indenting
Daniel Veillard7d2c2761999-10-11 15:09:51 +00004201 * @format: is formatting allowed
Daniel Veillard97b58771998-10-20 06:14:16 +00004202 *
4203 * Dump an XML node, recursive behaviour,children are printed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +00004204 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00004205static void
Daniel Veillard7d2c2761999-10-11 15:09:51 +00004206xmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
4207 int format) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00004208 int i;
Daniel Veillard7d2c2761999-10-11 15:09:51 +00004209 xmlNodePtr tmp;
Daniel Veillard260a68f1998-08-13 03:39:55 +00004210
4211 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004212#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00004213 fprintf(stderr, "xmlNodeDump : node == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004214#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00004215 return;
4216 }
Daniel Veillard0bef1311998-10-14 02:36:47 +00004217 if (cur->type == XML_TEXT_NODE) {
Daniel Veillard14fff061999-06-22 21:49:07 +00004218 if (cur->content != NULL) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004219 xmlChar *buffer;
Daniel Veillard14fff061999-06-22 21:49:07 +00004220
Daniel Veillardf5c2c871999-12-01 09:51:45 +00004221#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard14fff061999-06-22 21:49:07 +00004222 buffer = xmlEncodeEntitiesReentrant(doc, cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00004223#else
4224 buffer = xmlEncodeEntitiesReentrant(doc,
4225 xmlBufferContent(cur->content));
4226#endif
Daniel Veillard14fff061999-06-22 21:49:07 +00004227 if (buffer != NULL) {
4228 xmlBufferWriteCHAR(buf, buffer);
Daniel Veillard6454aec1999-09-02 22:04:43 +00004229 xmlFree(buffer);
Daniel Veillard14fff061999-06-22 21:49:07 +00004230 }
4231 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00004232 return;
4233 }
Daniel Veillardb96e6431999-08-29 21:02:19 +00004234 if (cur->type == XML_PI_NODE) {
4235 if (cur->content != NULL) {
4236 xmlBufferWriteChar(buf, "<?");
4237 xmlBufferWriteCHAR(buf, cur->name);
4238 if (cur->content != NULL) {
4239 xmlBufferWriteChar(buf, " ");
Daniel Veillardf5c2c871999-12-01 09:51:45 +00004240#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardb96e6431999-08-29 21:02:19 +00004241 xmlBufferWriteCHAR(buf, cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00004242#else
4243 xmlBufferWriteCHAR(buf, xmlBufferContent(cur->content));
4244#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +00004245 }
Daniel Veillard7d2c2761999-10-11 15:09:51 +00004246 xmlBufferWriteChar(buf, "?>");
Daniel Veillardb96e6431999-08-29 21:02:19 +00004247 }
4248 return;
4249 }
Daniel Veillard0bef1311998-10-14 02:36:47 +00004250 if (cur->type == XML_COMMENT_NODE) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00004251 if (cur->content != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00004252 xmlBufferWriteChar(buf, "<!--");
Daniel Veillardf5c2c871999-12-01 09:51:45 +00004253#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard5099ae81999-04-21 20:12:07 +00004254 xmlBufferWriteCHAR(buf, cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00004255#else
4256 xmlBufferWriteCHAR(buf, xmlBufferContent(cur->content));
4257#endif
Daniel Veillard7d2c2761999-10-11 15:09:51 +00004258 xmlBufferWriteChar(buf, "-->");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004259 }
4260 return;
4261 }
Daniel Veillardccb09631998-10-27 06:21:04 +00004262 if (cur->type == XML_ENTITY_REF_NODE) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00004263 xmlBufferWriteChar(buf, "&");
4264 xmlBufferWriteCHAR(buf, cur->name);
4265 xmlBufferWriteChar(buf, ";");
Daniel Veillardccb09631998-10-27 06:21:04 +00004266 return;
4267 }
Daniel Veillardb05deb71999-08-10 19:04:08 +00004268 if (cur->type == XML_CDATA_SECTION_NODE) {
4269 xmlBufferWriteChar(buf, "<![CDATA[");
4270 if (cur->content != NULL)
Daniel Veillardf5c2c871999-12-01 09:51:45 +00004271#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardb05deb71999-08-10 19:04:08 +00004272 xmlBufferWriteCHAR(buf, cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00004273#else
4274 xmlBufferWriteCHAR(buf, xmlBufferContent(cur->content));
4275#endif
Daniel Veillardb05deb71999-08-10 19:04:08 +00004276 xmlBufferWriteChar(buf, "]]>");
4277 return;
4278 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00004279
Daniel Veillard7d2c2761999-10-11 15:09:51 +00004280 if (format == 1) {
4281 tmp = cur->childs;
4282 while (tmp != NULL) {
4283 if ((tmp->type == XML_TEXT_NODE) ||
4284 (tmp->type == XML_ENTITY_REF_NODE)) {
4285 format = 0;
4286 break;
4287 }
4288 tmp = tmp->next;
4289 }
4290 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00004291 xmlBufferWriteChar(buf, "<");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004292 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00004293 xmlBufferWriteCHAR(buf, cur->ns->prefix);
4294 xmlBufferWriteChar(buf, ":");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004295 }
4296
Daniel Veillard5099ae81999-04-21 20:12:07 +00004297 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004298 if (cur->nsDef)
Daniel Veillard5099ae81999-04-21 20:12:07 +00004299 xmlNsListDump(buf, cur->nsDef);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004300 if (cur->properties != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00004301 xmlAttrListDump(buf, doc, cur->properties);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004302
Daniel Veillarde41f2b72000-01-30 20:00:07 +00004303 if ((cur->content == NULL) && (cur->childs == NULL) &&
4304 (!xmlSaveNoEmptyTags)) {
Daniel Veillard7d2c2761999-10-11 15:09:51 +00004305 xmlBufferWriteChar(buf, "/>");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004306 return;
4307 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00004308 xmlBufferWriteChar(buf, ">");
Daniel Veillard14fff061999-06-22 21:49:07 +00004309 if (cur->content != NULL) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004310 xmlChar *buffer;
Daniel Veillard14fff061999-06-22 21:49:07 +00004311
Daniel Veillardf5c2c871999-12-01 09:51:45 +00004312#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard14fff061999-06-22 21:49:07 +00004313 buffer = xmlEncodeEntitiesReentrant(doc, cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00004314#else
4315 buffer = xmlEncodeEntitiesReentrant(doc,
4316 xmlBufferContent(cur->content));
4317#endif
Daniel Veillard14fff061999-06-22 21:49:07 +00004318 if (buffer != NULL) {
4319 xmlBufferWriteCHAR(buf, buffer);
Daniel Veillard6454aec1999-09-02 22:04:43 +00004320 xmlFree(buffer);
Daniel Veillard14fff061999-06-22 21:49:07 +00004321 }
4322 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00004323 if (cur->childs != NULL) {
Daniel Veillard7d2c2761999-10-11 15:09:51 +00004324 if (format) xmlBufferWriteChar(buf, "\n");
4325 xmlNodeListDump(buf, doc, cur->childs, level + 1, format);
4326 if ((xmlIndentTreeOutput) && (format))
4327 for (i = 0;i < level;i++)
4328 xmlBufferWriteChar(buf, " ");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004329 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00004330 xmlBufferWriteChar(buf, "</");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004331 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00004332 xmlBufferWriteCHAR(buf, cur->ns->prefix);
4333 xmlBufferWriteChar(buf, ":");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004334 }
4335
Daniel Veillard5099ae81999-04-21 20:12:07 +00004336 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillard7d2c2761999-10-11 15:09:51 +00004337 xmlBufferWriteChar(buf, ">");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004338}
4339
Daniel Veillard97b58771998-10-20 06:14:16 +00004340/**
Daniel Veillarddbfd6411999-12-28 16:35:14 +00004341 * xmlElemDump:
4342 * @buf: the XML buffer output
4343 * @doc: the document
4344 * @cur: the current node
4345 *
4346 * Dump an XML/HTML node, recursive behaviour,children are printed too.
4347 */
4348void
4349xmlElemDump(FILE *f, xmlDocPtr doc, xmlNodePtr cur) {
4350 xmlBufferPtr buf;
4351
4352 if (cur == NULL) {
4353#ifdef DEBUG_TREE
4354 fprintf(stderr, "xmlElemDump : cur == NULL\n");
4355#endif
4356 return;
4357 }
4358 if (doc == NULL) {
4359#ifdef DEBUG_TREE
4360 fprintf(stderr, "xmlElemDump : doc == NULL\n");
4361#endif
4362 }
4363 buf = xmlBufferCreate();
4364 if (buf == NULL) return;
4365 if ((doc != NULL) &&
4366 (doc->type == XML_HTML_DOCUMENT_NODE)) {
4367 htmlNodeDump(buf, doc, cur);
4368 } else
4369 xmlNodeDump(buf, doc, cur, 0, 1);
4370 xmlBufferDump(f, buf);
4371 xmlBufferFree(buf);
4372}
4373
4374/**
Daniel Veillard97b58771998-10-20 06:14:16 +00004375 * xmlDocContentDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00004376 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00004377 * @cur: the document
4378 *
4379 * Dump an XML document.
Daniel Veillard260a68f1998-08-13 03:39:55 +00004380 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00004381static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00004382xmlDocContentDump(xmlBufferPtr buf, xmlDocPtr cur) {
Daniel Veillardbe70ff71999-07-05 16:50:46 +00004383 xmlBufferWriteChar(buf, "<?xml version=");
4384 if (cur->version != NULL)
4385 xmlBufferWriteQuotedString(buf, cur->version);
4386 else
4387 xmlBufferWriteChar(buf, "\"1.0\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004388 if (cur->encoding != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00004389 xmlBufferWriteChar(buf, " encoding=");
4390 xmlBufferWriteQuotedString(buf, cur->encoding);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004391 }
4392 switch (cur->standalone) {
4393 case 0:
Daniel Veillard5099ae81999-04-21 20:12:07 +00004394 xmlBufferWriteChar(buf, " standalone=\"no\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004395 break;
4396 case 1:
Daniel Veillard5099ae81999-04-21 20:12:07 +00004397 xmlBufferWriteChar(buf, " standalone=\"yes\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004398 break;
4399 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00004400 xmlBufferWriteChar(buf, "?>\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004401 if (cur->intSubset != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00004402 xmlDtdDump(buf, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004403 if (cur->root != NULL) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00004404 xmlNodePtr child = cur->root;
4405
Daniel Veillard260a68f1998-08-13 03:39:55 +00004406 /* global namespace definitions, the old way */
4407 if (oldXMLWDcompatibility)
Daniel Veillard5099ae81999-04-21 20:12:07 +00004408 xmlGlobalNsListDump(buf, cur->oldNs);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004409 else
4410 xmlUpgradeOldNs(cur);
Daniel Veillardb96e6431999-08-29 21:02:19 +00004411
4412 while (child != NULL) {
Daniel Veillard7d2c2761999-10-11 15:09:51 +00004413 xmlNodeDump(buf, cur, child, 0, 1);
4414 xmlBufferWriteChar(buf, "\n");
Daniel Veillardb96e6431999-08-29 21:02:19 +00004415 child = child->next;
4416 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00004417 }
4418}
4419
Daniel Veillard97b58771998-10-20 06:14:16 +00004420/**
4421 * xmlDocDumpMemory:
4422 * @cur: the document
4423 * @mem: OUT: the memory pointer
4424 * @size: OUT: the memory lenght
4425 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004426 * Dump an XML document in memory and return the xmlChar * and it's size.
Daniel Veillard97b58771998-10-20 06:14:16 +00004427 * It's up to the caller to free the memory.
Daniel Veillard260a68f1998-08-13 03:39:55 +00004428 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00004429void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004430xmlDocDumpMemory(xmlDocPtr cur, xmlChar**mem, int *size) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00004431 xmlBufferPtr buf;
4432
Daniel Veillard260a68f1998-08-13 03:39:55 +00004433 if (cur == NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004434#ifdef DEBUG_TREE
4435 fprintf(stderr, "xmlDocDumpMemory : document == NULL\n");
4436#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00004437 *mem = NULL;
4438 *size = 0;
4439 return;
4440 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00004441 buf = xmlBufferCreate();
4442 if (buf == NULL) {
4443 *mem = NULL;
4444 *size = 0;
4445 return;
4446 }
4447 xmlDocContentDump(buf, cur);
Daniel Veillardb05deb71999-08-10 19:04:08 +00004448 *mem = xmlStrndup(buf->content, buf->use);
Daniel Veillard5099ae81999-04-21 20:12:07 +00004449 *size = buf->use;
Daniel Veillardb05deb71999-08-10 19:04:08 +00004450 xmlBufferFree(buf);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004451}
4452
Daniel Veillard97b58771998-10-20 06:14:16 +00004453/**
4454 * xmlGetDocCompressMode:
4455 * @doc: the document
4456 *
4457 * get the compression ratio for a document, ZLIB based
Daniel Veillard1e346af1999-02-22 10:33:01 +00004458 * Returns 0 (uncompressed) to 9 (max compression)
Daniel Veillard151b1b01998-09-23 00:49:46 +00004459 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00004460int
Daniel Veillarddbfd6411999-12-28 16:35:14 +00004461xmlGetDocCompressMode (xmlDocPtr doc) {
Daniel Veillard15a8df41998-09-24 19:15:06 +00004462 if (doc == NULL) return(-1);
4463 return(doc->compression);
4464}
4465
Daniel Veillard97b58771998-10-20 06:14:16 +00004466/**
4467 * xmlSetDocCompressMode:
4468 * @doc: the document
4469 * @mode: the compression ratio
4470 *
4471 * set the compression ratio for a document, ZLIB based
4472 * Correct values: 0 (uncompressed) to 9 (max compression)
4473 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00004474void
4475xmlSetDocCompressMode (xmlDocPtr doc, int mode) {
Daniel Veillard15a8df41998-09-24 19:15:06 +00004476 if (doc == NULL) return;
4477 if (mode < 0) doc->compression = 0;
4478 else if (mode > 9) doc->compression = 9;
4479 else doc->compression = mode;
4480}
4481
Daniel Veillard97b58771998-10-20 06:14:16 +00004482/**
4483 * xmlGetCompressMode:
4484 *
4485 * get the default compression mode used, ZLIB based.
Daniel Veillard1e346af1999-02-22 10:33:01 +00004486 * Returns 0 (uncompressed) to 9 (max compression)
Daniel Veillard15a8df41998-09-24 19:15:06 +00004487 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00004488int
4489 xmlGetCompressMode(void) {
Daniel Veillard151b1b01998-09-23 00:49:46 +00004490 return(xmlCompressMode);
4491}
Daniel Veillard97b58771998-10-20 06:14:16 +00004492
4493/**
4494 * xmlSetCompressMode:
4495 * @mode: the compression ratio
4496 *
4497 * set the default compression mode used, ZLIB based
4498 * Correct values: 0 (uncompressed) to 9 (max compression)
4499 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00004500void
4501xmlSetCompressMode(int mode) {
Daniel Veillard151b1b01998-09-23 00:49:46 +00004502 if (mode < 0) xmlCompressMode = 0;
Daniel Veillard15a8df41998-09-24 19:15:06 +00004503 else if (mode > 9) xmlCompressMode = 9;
Daniel Veillard151b1b01998-09-23 00:49:46 +00004504 else xmlCompressMode = mode;
4505}
4506
Daniel Veillard97b58771998-10-20 06:14:16 +00004507/**
4508 * xmlDocDump:
4509 * @f: the FILE*
4510 * @cur: the document
4511 *
4512 * Dump an XML document to an open FILE.
Daniel Veillard260a68f1998-08-13 03:39:55 +00004513 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00004514void
4515xmlDocDump(FILE *f, xmlDocPtr cur) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00004516 xmlBufferPtr buf;
4517
Daniel Veillard260a68f1998-08-13 03:39:55 +00004518 if (cur == NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004519#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00004520 fprintf(stderr, "xmlDocDump : document == NULL\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004521#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00004522 return;
4523 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00004524 buf = xmlBufferCreate();
4525 if (buf == NULL) return;
4526 xmlDocContentDump(buf, cur);
4527 xmlBufferDump(f, buf);
4528 xmlBufferFree(buf);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004529}
4530
Daniel Veillard97b58771998-10-20 06:14:16 +00004531/**
4532 * xmlSaveFile:
4533 * @filename: the filename
4534 * @cur: the document
4535 *
4536 * Dump an XML document to a file. Will use compression if
Daniel Veillard11a48ec1999-11-23 10:40:46 +00004537 * compiled in and enabled. If @filename is "-" the stdout file is
4538 * used.
Daniel Veillard97b58771998-10-20 06:14:16 +00004539 * returns: the number of file written or -1 in case of failure.
Daniel Veillard151b1b01998-09-23 00:49:46 +00004540 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00004541int
4542xmlSaveFile(const char *filename, xmlDocPtr cur) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00004543 xmlBufferPtr buf;
Daniel Veillard151b1b01998-09-23 00:49:46 +00004544#ifdef HAVE_ZLIB_H
4545 gzFile zoutput = NULL;
4546 char mode[15];
4547#endif
Daniel Veillardccb09631998-10-27 06:21:04 +00004548 FILE *output = NULL;
Daniel Veillard151b1b01998-09-23 00:49:46 +00004549 int ret;
4550
Daniel Veillard5099ae81999-04-21 20:12:07 +00004551 /*
4552 * save the content to a temp buffer.
4553 */
4554 buf = xmlBufferCreate();
4555 if (buf == NULL) return(0);
4556 xmlDocContentDump(buf, cur);
4557
Daniel Veillard151b1b01998-09-23 00:49:46 +00004558#ifdef HAVE_ZLIB_H
Daniel Veillard11a48ec1999-11-23 10:40:46 +00004559 if (cur->compression < 0) cur->compression = xmlCompressMode;
Daniel Veillarddc3dd9d1998-09-24 19:25:54 +00004560 if ((cur->compression > 0) && (cur->compression <= 9)) {
4561 sprintf(mode, "w%d", cur->compression);
Daniel Veillard11a48ec1999-11-23 10:40:46 +00004562 if (!strcmp(filename, "-"))
4563 zoutput = gzdopen(1, mode);
4564 else
4565 zoutput = gzopen(filename, mode);
Daniel Veillard151b1b01998-09-23 00:49:46 +00004566 }
4567 if (zoutput == NULL) {
4568#endif
4569 output = fopen(filename, "w");
Daniel Veillard10a2c651999-12-12 13:03:50 +00004570 if (output == NULL) {
4571 xmlBufferFree(buf);
4572 return(-1);
4573 }
Daniel Veillard151b1b01998-09-23 00:49:46 +00004574#ifdef HAVE_ZLIB_H
4575 }
Daniel Veillard151b1b01998-09-23 00:49:46 +00004576
Daniel Veillard151b1b01998-09-23 00:49:46 +00004577 if (zoutput != NULL) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004578 ret = gzwrite(zoutput, buf->content, sizeof(xmlChar) * buf->use);
Daniel Veillard151b1b01998-09-23 00:49:46 +00004579 gzclose(zoutput);
Daniel Veillard5099ae81999-04-21 20:12:07 +00004580 } else {
4581#endif
4582 ret = xmlBufferDump(output, buf);
4583 fclose(output);
4584#ifdef HAVE_ZLIB_H
Daniel Veillard151b1b01998-09-23 00:49:46 +00004585 }
4586#endif
Manish Vachharajani5e60f5a1999-05-29 03:04:30 +00004587 xmlBufferFree(buf);
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004588 return(ret * sizeof(xmlChar));
Daniel Veillard151b1b01998-09-23 00:49:46 +00004589}
4590