blob: d1caae9ef7f50aaacd48cae8dfa7d296ad268a9d [file] [log] [blame]
Daniel Veillard260a68f1998-08-13 03:39:55 +00001/*
2 * tree.c : implemetation of access function for an XML tree.
3 *
4 * See Copyright for the status of this software.
5 *
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00006 * Daniel.Veillard@w3.org
Daniel Veillard260a68f1998-08-13 03:39:55 +00007 */
8
Daniel Veillard7f7d1111999-09-22 09:46:25 +00009#ifdef WIN32
10#define HAVE_FCNTL_H
11#include <io.h>
12#else
Daniel Veillard151b1b01998-09-23 00:49:46 +000013#include "config.h"
Daniel Veillard7f7d1111999-09-22 09:46:25 +000014#endif
15
Daniel Veillard260a68f1998-08-13 03:39:55 +000016#include <stdio.h>
Daniel Veillard260a68f1998-08-13 03:39:55 +000017#include <string.h> /* for memset() only ! */
18
Daniel Veillard7f7d1111999-09-22 09:46:25 +000019#ifdef HAVE_CTYPE_H
20#include <ctype.h>
21#endif
22#ifdef HAVE_STDLIB_H
23#include <stdlib.h>
24#endif
Daniel Veillard151b1b01998-09-23 00:49:46 +000025#ifdef HAVE_ZLIB_H
26#include <zlib.h>
27#endif
28
Daniel Veillard6454aec1999-09-02 22:04:43 +000029#include "xmlmemory.h"
Daniel Veillard260a68f1998-08-13 03:39:55 +000030#include "tree.h"
31#include "entities.h"
Daniel Veillard3b9def11999-01-31 22:15:06 +000032#include "valid.h"
Daniel Veillard260a68f1998-08-13 03:39:55 +000033
Daniel Veillarddd6b3671999-09-23 22:19:22 +000034static xmlChar xmlStringText[] = { 't', 'e', 'x', 't', 0 };
Daniel Veillard260a68f1998-08-13 03:39:55 +000035int oldXMLWDcompatibility = 0;
36int xmlIndentTreeOutput = 1;
37
Daniel Veillard15a8df41998-09-24 19:15:06 +000038static int xmlCompressMode = 0;
39
Daniel Veillard39a1f9a1999-01-17 19:11:59 +000040#define UPDATE_LAST_CHILD(n) if ((n) != NULL) { \
41 xmlNodePtr ulccur = (n)->childs; \
42 if (ulccur == NULL) { \
43 (n)->last = NULL; \
44 } else { \
45 while (ulccur->next != NULL) ulccur = ulccur->next; \
46 (n)->last = ulccur; \
Daniel Veillard1e346af1999-02-22 10:33:01 +000047}}
Daniel Veillard39a1f9a1999-01-17 19:11:59 +000048
Daniel Veillard260a68f1998-08-13 03:39:55 +000049/************************************************************************
50 * *
51 * Allocation and deallocation of basic structures *
52 * *
53 ************************************************************************/
54
Daniel Veillard97b58771998-10-20 06:14:16 +000055/**
56 * xmlUpgradeOldNs:
57 * @doc: a document pointer
58 *
59 * Upgrade old style Namespaces (PI) and move them to the root of the document.
Daniel Veillard260a68f1998-08-13 03:39:55 +000060 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +000061void
62xmlUpgradeOldNs(xmlDocPtr doc) {
Daniel Veillard260a68f1998-08-13 03:39:55 +000063 xmlNsPtr cur;
64
65 if ((doc == NULL) || (doc->oldNs == NULL)) return;
66 if (doc->root == NULL) {
67 fprintf(stderr, "xmlUpgradeOldNs: failed no root !\n");
68 return;
69 }
70
71 cur = doc->oldNs;
72 while (cur->next != NULL) {
73 cur->type = XML_LOCAL_NAMESPACE;
74 cur = cur->next;
75 }
76 cur->type = XML_LOCAL_NAMESPACE;
77 cur->next = doc->root->nsDef;
78 doc->root->nsDef = doc->oldNs;
79 doc->oldNs = NULL;
80}
81
Daniel Veillard97b58771998-10-20 06:14:16 +000082/**
83 * xmlNewNs:
84 * @node: the element carrying the namespace
85 * @href: the URI associated
86 * @prefix: the prefix for the namespace
87 *
Daniel Veillard260a68f1998-08-13 03:39:55 +000088 * Creation of a new Namespace.
Daniel Veillard1e346af1999-02-22 10:33:01 +000089 * Returns returns a new namespace pointer
Daniel Veillard260a68f1998-08-13 03:39:55 +000090 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +000091xmlNsPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +000092xmlNewNs(xmlNodePtr node, const xmlChar *href, const xmlChar *prefix) {
Daniel Veillard260a68f1998-08-13 03:39:55 +000093 xmlNsPtr cur;
94
95 if (href == NULL) {
96 fprintf(stderr, "xmlNewNs: href == NULL !\n");
97 return(NULL);
98 }
99
100 /*
101 * Allocate a new DTD and fill the fields.
102 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000103 cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000104 if (cur == NULL) {
105 fprintf(stderr, "xmlNewNs : malloc failed\n");
106 return(NULL);
107 }
108
109 cur->type = XML_LOCAL_NAMESPACE;
110 if (href != NULL)
111 cur->href = xmlStrdup(href);
112 else
113 cur->href = NULL;
114 if (prefix != NULL)
115 cur->prefix = xmlStrdup(prefix);
116 else
117 cur->prefix = NULL;
118
119 /*
120 * Add it at the end to preserve parsing order ...
121 */
122 cur->next = NULL;
123 if (node != NULL) {
124 if (node->nsDef == NULL) {
125 node->nsDef = cur;
126 } else {
127 xmlNsPtr prev = node->nsDef;
128
129 while (prev->next != NULL) prev = prev->next;
130 prev->next = cur;
131 }
132 }
133
134 return(cur);
135}
136
Daniel Veillard97b58771998-10-20 06:14:16 +0000137/**
138 * xmlNewGlobalNs:
139 * @doc: the document carrying the namespace
140 * @href: the URI associated
141 * @prefix: the prefix for the namespace
142 *
143 * Creation of a Namespace, the old way using PI and without scoping, to AVOID.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000144 * Returns returns a new namespace pointer
Daniel Veillard260a68f1998-08-13 03:39:55 +0000145 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000146xmlNsPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000147xmlNewGlobalNs(xmlDocPtr doc, const xmlChar *href, const xmlChar *prefix) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000148 xmlNsPtr cur;
149
150 /*
151 * Allocate a new DTD and fill the fields.
152 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000153 cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000154 if (cur == NULL) {
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000155 fprintf(stderr, "xmlNewGlobalNs : malloc failed\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +0000156 return(NULL);
157 }
158
159 cur->type = XML_GLOBAL_NAMESPACE;
160 if (href != NULL)
161 cur->href = xmlStrdup(href);
162 else
163 cur->href = NULL;
164 if (prefix != NULL)
165 cur->prefix = xmlStrdup(prefix);
166 else
167 cur->prefix = NULL;
168
169 /*
170 * Add it at the end to preserve parsing order ...
171 */
172 cur->next = NULL;
173 if (doc != NULL) {
174 if (doc->oldNs == NULL) {
175 doc->oldNs = cur;
176 } else {
177 xmlNsPtr prev = doc->oldNs;
178
179 while (prev->next != NULL) prev = prev->next;
180 prev->next = cur;
181 }
182 }
183
184 return(cur);
185}
186
Daniel Veillard97b58771998-10-20 06:14:16 +0000187/**
188 * xmlSetNs:
189 * @node: a node in the document
190 * @ns: a namespace pointer
191 *
192 * Associate a namespace to a node, a posteriori.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000193 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000194void
195xmlSetNs(xmlNodePtr node, xmlNsPtr ns) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000196 if (node == NULL) {
197 fprintf(stderr, "xmlSetNs: node == NULL\n");
198 return;
199 }
200 node->ns = ns;
201}
202
Daniel Veillard97b58771998-10-20 06:14:16 +0000203/**
204 * xmlFreeNs:
205 * @cur: the namespace pointer
206 *
207 * Free up the structures associated to a namespace
Daniel Veillard260a68f1998-08-13 03:39:55 +0000208 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000209void
210xmlFreeNs(xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000211 if (cur == NULL) {
212 fprintf(stderr, "xmlFreeNs : ns == NULL\n");
213 return;
214 }
Daniel Veillard6454aec1999-09-02 22:04:43 +0000215 if (cur->href != NULL) xmlFree((char *) cur->href);
216 if (cur->prefix != NULL) xmlFree((char *) cur->prefix);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000217 memset(cur, -1, sizeof(xmlNs));
Daniel Veillard6454aec1999-09-02 22:04:43 +0000218 xmlFree(cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000219}
220
Daniel Veillard97b58771998-10-20 06:14:16 +0000221/**
222 * xmlFreeNsList:
223 * @cur: the first namespace pointer
224 *
225 * Free up all the structures associated to the chained namespaces.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000226 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000227void
228xmlFreeNsList(xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000229 xmlNsPtr next;
230 if (cur == NULL) {
231 fprintf(stderr, "xmlFreeNsList : ns == NULL\n");
232 return;
233 }
234 while (cur != NULL) {
235 next = cur->next;
236 xmlFreeNs(cur);
237 cur = next;
238 }
239}
240
Daniel Veillard97b58771998-10-20 06:14:16 +0000241/**
242 * xmlNewDtd:
243 * @doc: the document pointer
244 * @name: the DTD name
245 * @ExternalID: the external ID
246 * @SystemID: the system ID
247 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000248 * Creation of a new DTD.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000249 * Returns a pointer to the new DTD structure
Daniel Veillard260a68f1998-08-13 03:39:55 +0000250 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000251xmlDtdPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000252xmlNewDtd(xmlDocPtr doc, const xmlChar *name,
253 const xmlChar *ExternalID, const xmlChar *SystemID) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000254 xmlDtdPtr cur;
255
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000256 if ((doc != NULL) && (doc->extSubset != NULL)) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000257 fprintf(stderr, "xmlNewDtd(%s): document %s already have a DTD %s\n",
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000258 /* !!! */ (char *) name, doc->name,
259 /* !!! */ (char *)doc->extSubset->name);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000260 }
261
262 /*
263 * Allocate a new DTD and fill the fields.
264 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000265 cur = (xmlDtdPtr) xmlMalloc(sizeof(xmlDtd));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000266 if (cur == NULL) {
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000267 fprintf(stderr, "xmlNewDtd : malloc failed\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +0000268 return(NULL);
269 }
270
271 if (name != NULL)
272 cur->name = xmlStrdup(name);
273 else
274 cur->name = NULL;
275 if (ExternalID != NULL)
276 cur->ExternalID = xmlStrdup(ExternalID);
277 else
278 cur->ExternalID = NULL;
279 if (SystemID != NULL)
280 cur->SystemID = xmlStrdup(SystemID);
281 else
282 cur->SystemID = NULL;
Daniel Veillard1e346af1999-02-22 10:33:01 +0000283 cur->notations = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000284 cur->elements = NULL;
Daniel Veillard1e346af1999-02-22 10:33:01 +0000285 cur->attributes = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000286 cur->entities = NULL;
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000287 if (doc != NULL)
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000288 doc->extSubset = cur;
289
290 return(cur);
291}
292
293/**
294 * xmlCreateIntSubset:
295 * @doc: the document pointer
296 * @name: the DTD name
297 * @ExternalID: the external ID
298 * @SystemID: the system ID
299 *
Daniel Veillard1e346af1999-02-22 10:33:01 +0000300 * Create the internal subset of a document
301 * Returns a pointer to the new DTD structure
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000302 */
303xmlDtdPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000304xmlCreateIntSubset(xmlDocPtr doc, const xmlChar *name,
305 const xmlChar *ExternalID, const xmlChar *SystemID) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000306 xmlDtdPtr cur;
307
308 if ((doc != NULL) && (doc->intSubset != NULL)) {
309 fprintf(stderr,
310 "xmlCreateIntSubset(): document %s already have an internal subset\n",
311 doc->name);
312 return(NULL);
313 }
314
315 /*
316 * Allocate a new DTD and fill the fields.
317 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000318 cur = (xmlDtdPtr) xmlMalloc(sizeof(xmlDtd));
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000319 if (cur == NULL) {
320 fprintf(stderr, "xmlNewDtd : malloc failed\n");
321 return(NULL);
322 }
323
324 if (name != NULL)
325 cur->name = xmlStrdup(name);
326 else
327 cur->name = NULL;
328 if (ExternalID != NULL)
329 cur->ExternalID = xmlStrdup(ExternalID);
330 else
331 cur->ExternalID = NULL;
332 if (SystemID != NULL)
333 cur->SystemID = xmlStrdup(SystemID);
334 else
335 cur->SystemID = NULL;
Daniel Veillard1e346af1999-02-22 10:33:01 +0000336 cur->notations = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000337 cur->elements = NULL;
Daniel Veillard1e346af1999-02-22 10:33:01 +0000338 cur->attributes = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000339 cur->entities = NULL;
340 if (doc != NULL)
341 doc->intSubset = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000342
343 return(cur);
344}
345
Daniel Veillard97b58771998-10-20 06:14:16 +0000346/**
347 * xmlFreeDtd:
348 * @cur: the DTD structure to free up
349 *
350 * Free a DTD structure.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000351 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000352void
353xmlFreeDtd(xmlDtdPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000354 if (cur == NULL) {
355 fprintf(stderr, "xmlFreeDtd : DTD == NULL\n");
356 return;
357 }
Daniel Veillard6454aec1999-09-02 22:04:43 +0000358 if (cur->name != NULL) xmlFree((char *) cur->name);
359 if (cur->SystemID != NULL) xmlFree((char *) cur->SystemID);
360 if (cur->ExternalID != NULL) xmlFree((char *) cur->ExternalID);
Daniel Veillard1e346af1999-02-22 10:33:01 +0000361 if (cur->notations != NULL)
362 xmlFreeNotationTable((xmlNotationTablePtr) cur->notations);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000363 if (cur->elements != NULL)
Daniel Veillard3b9def11999-01-31 22:15:06 +0000364 xmlFreeElementTable((xmlElementTablePtr) cur->elements);
Daniel Veillard1e346af1999-02-22 10:33:01 +0000365 if (cur->attributes != NULL)
366 xmlFreeAttributeTable((xmlAttributeTablePtr) cur->attributes);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000367 if (cur->entities != NULL)
368 xmlFreeEntitiesTable((xmlEntitiesTablePtr) cur->entities);
369 memset(cur, -1, sizeof(xmlDtd));
Daniel Veillard6454aec1999-09-02 22:04:43 +0000370 xmlFree(cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000371}
372
Daniel Veillard97b58771998-10-20 06:14:16 +0000373/**
374 * xmlNewDoc:
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000375 * @version: xmlChar string giving the version of XML "1.0"
Daniel Veillard97b58771998-10-20 06:14:16 +0000376 *
Daniel Veillard1e346af1999-02-22 10:33:01 +0000377 * Returns a new document
Daniel Veillard260a68f1998-08-13 03:39:55 +0000378 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000379xmlDocPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000380xmlNewDoc(const xmlChar *version) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000381 xmlDocPtr cur;
382
383 if (version == NULL) {
384 fprintf(stderr, "xmlNewDoc : version == NULL\n");
385 return(NULL);
386 }
387
388 /*
389 * Allocate a new document and fill the fields.
390 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000391 cur = (xmlDocPtr) xmlMalloc(sizeof(xmlDoc));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000392 if (cur == NULL) {
393 fprintf(stderr, "xmlNewDoc : malloc failed\n");
394 return(NULL);
395 }
396
Daniel Veillard33942841998-10-18 19:12:41 +0000397 cur->type = XML_DOCUMENT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000398 cur->version = xmlStrdup(version);
399 cur->name = NULL;
400 cur->root = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000401 cur->intSubset = NULL;
402 cur->extSubset = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000403 cur->oldNs = NULL;
404 cur->encoding = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000405 cur->standalone = -1;
Daniel Veillard15a8df41998-09-24 19:15:06 +0000406 cur->compression = xmlCompressMode;
Daniel Veillardb96e6431999-08-29 21:02:19 +0000407 cur->ids = NULL;
Daniel Veillardc08a2c61999-09-08 21:35:25 +0000408 cur->refs = NULL;
Daniel Veillard27d88741999-05-29 11:51:49 +0000409#ifndef XML_WITHOUT_CORBA
Daniel Veillard27fb0751998-10-17 06:47:46 +0000410 cur->_private = NULL;
411 cur->vepv = NULL;
412#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000413 return(cur);
414}
415
Daniel Veillard97b58771998-10-20 06:14:16 +0000416/**
417 * xmlFreeDoc:
418 * @cur: pointer to the document
419 * @:
420 *
421 * Free up all the structures used by a document, tree included.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000422 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000423void
424xmlFreeDoc(xmlDocPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000425 if (cur == NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000426#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +0000427 fprintf(stderr, "xmlFreeDoc : document == NULL\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000428#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000429 return;
430 }
Daniel Veillard6454aec1999-09-02 22:04:43 +0000431 if (cur->version != NULL) xmlFree((char *) cur->version);
432 if (cur->name != NULL) xmlFree((char *) cur->name);
433 if (cur->encoding != NULL) xmlFree((char *) cur->encoding);
434 if (cur->root != NULL) xmlFreeNodeList(cur->root);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000435 if (cur->intSubset != NULL) xmlFreeDtd(cur->intSubset);
436 if (cur->extSubset != NULL) xmlFreeDtd(cur->extSubset);
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000437 if (cur->oldNs != NULL) xmlFreeNsList(cur->oldNs);
Daniel Veillardb96e6431999-08-29 21:02:19 +0000438 if (cur->ids != NULL) xmlFreeIDTable((xmlIDTablePtr) cur->ids);
Daniel Veillardc08a2c61999-09-08 21:35:25 +0000439 if (cur->refs != NULL) xmlFreeRefTable((xmlRefTablePtr) cur->refs);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000440 memset(cur, -1, sizeof(xmlDoc));
Daniel Veillard6454aec1999-09-02 22:04:43 +0000441 xmlFree(cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000442}
443
Daniel Veillard97b58771998-10-20 06:14:16 +0000444/**
Daniel Veillard16253641998-10-28 22:58:05 +0000445 * xmlStringLenGetNodeList:
446 * @doc: the document
447 * @value: the value of the text
Daniel Veillard1e346af1999-02-22 10:33:01 +0000448 * @len: the length of the string value
Daniel Veillard16253641998-10-28 22:58:05 +0000449 *
450 * Parse the value string and build the node list associated. Should
451 * produce a flat tree with only TEXTs and ENTITY_REFs.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000452 * Returns a pointer to the first child
Daniel Veillard16253641998-10-28 22:58:05 +0000453 */
454xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000455xmlStringLenGetNodeList(xmlDocPtr doc, const xmlChar *value, int len) {
Daniel Veillard16253641998-10-28 22:58:05 +0000456 xmlNodePtr ret = NULL, last = NULL;
457 xmlNodePtr node;
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000458 xmlChar *val;
459 const xmlChar *cur = value;
460 const xmlChar *q;
Daniel Veillard25940b71998-10-29 05:51:30 +0000461 xmlEntityPtr ent;
Daniel Veillard16253641998-10-28 22:58:05 +0000462
463 if (value == NULL) return(NULL);
464
465 q = cur;
466 while ((*cur != 0) && (cur - value < len)) {
467 if (*cur == '&') {
Daniel Veillard25940b71998-10-29 05:51:30 +0000468 /*
469 * Save the current text.
470 */
Daniel Veillard16253641998-10-28 22:58:05 +0000471 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000472 if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
473 xmlNodeAddContentLen(last, q, cur - q);
474 } else {
475 node = xmlNewDocTextLen(doc, q, cur - q);
476 if (node == NULL) return(ret);
477 if (last == NULL)
478 last = ret = node;
479 else {
480 last->next = node;
481 node->prev = last;
482 last = node;
483 }
Daniel Veillard16253641998-10-28 22:58:05 +0000484 }
485 }
Daniel Veillard25940b71998-10-29 05:51:30 +0000486 /*
487 * Read the entity string
488 */
Daniel Veillard16253641998-10-28 22:58:05 +0000489 cur++;
490 q = cur;
491 while ((*cur != 0) && (cur - value < len) && (*cur != ';')) cur++;
492 if ((*cur == 0) || (cur - value >= len)) {
493 fprintf(stderr,
Daniel Veillard011b63c1999-06-02 17:44:04 +0000494 "xmlStringLenGetNodeList: unterminated entity %30s\n", q);
Daniel Veillard16253641998-10-28 22:58:05 +0000495 return(ret);
496 }
497 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000498 /*
499 * Predefined entities don't generate nodes
500 */
Daniel Veillard16253641998-10-28 22:58:05 +0000501 val = xmlStrndup(q, cur - q);
Daniel Veillard25940b71998-10-29 05:51:30 +0000502 ent = xmlGetDocEntity(doc, val);
503 if ((ent != NULL) &&
504 (ent->type == XML_INTERNAL_PREDEFINED_ENTITY)) {
505 if (last == NULL) {
506 node = xmlNewDocText(doc, ent->content);
507 last = ret = node;
508 } else
509 xmlNodeAddContent(last, ent->content);
510
511 } else {
512 /*
513 * Create a new REFERENCE_REF node
514 */
515 node = xmlNewReference(doc, val);
Daniel Veillard242590e1998-11-13 18:04:35 +0000516 if (node == NULL) {
Daniel Veillard6454aec1999-09-02 22:04:43 +0000517 if (val != NULL) xmlFree(val);
Daniel Veillard242590e1998-11-13 18:04:35 +0000518 return(ret);
519 }
Daniel Veillard25940b71998-10-29 05:51:30 +0000520 if (last == NULL)
521 last = ret = node;
522 else {
523 last->next = node;
524 node->prev = last;
525 last = node;
526 }
Daniel Veillard16253641998-10-28 22:58:05 +0000527 }
Daniel Veillard6454aec1999-09-02 22:04:43 +0000528 xmlFree(val);
Daniel Veillard16253641998-10-28 22:58:05 +0000529 }
530 cur++;
531 q = cur;
532 } else
533 cur++;
534 }
535 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000536 /*
537 * Handle the last piece of text.
538 */
539 if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
540 xmlNodeAddContentLen(last, q, cur - q);
541 } else {
542 node = xmlNewDocTextLen(doc, q, cur - q);
543 if (node == NULL) return(ret);
544 if (last == NULL)
545 last = ret = node;
546 else {
547 last->next = node;
548 node->prev = last;
549 last = node;
550 }
Daniel Veillard16253641998-10-28 22:58:05 +0000551 }
552 }
553 return(ret);
554}
555
556/**
Daniel Veillardccb09631998-10-27 06:21:04 +0000557 * xmlStringGetNodeList:
558 * @doc: the document
559 * @value: the value of the attribute
560 *
561 * Parse the value string and build the node list associated. Should
562 * produce a flat tree with only TEXTs and ENTITY_REFs.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000563 * Returns a pointer to the first child
Daniel Veillardccb09631998-10-27 06:21:04 +0000564 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000565xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000566xmlStringGetNodeList(xmlDocPtr doc, const xmlChar *value) {
Daniel Veillardccb09631998-10-27 06:21:04 +0000567 xmlNodePtr ret = NULL, last = NULL;
568 xmlNodePtr node;
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000569 xmlChar *val;
570 const xmlChar *cur = value;
571 const xmlChar *q;
Daniel Veillard25940b71998-10-29 05:51:30 +0000572 xmlEntityPtr ent;
Daniel Veillardccb09631998-10-27 06:21:04 +0000573
574 if (value == NULL) return(NULL);
575
576 q = cur;
577 while (*cur != 0) {
578 if (*cur == '&') {
Daniel Veillard25940b71998-10-29 05:51:30 +0000579 /*
580 * Save the current text.
581 */
Daniel Veillardccb09631998-10-27 06:21:04 +0000582 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000583 if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
584 xmlNodeAddContentLen(last, q, cur - q);
585 } else {
586 node = xmlNewDocTextLen(doc, q, cur - q);
587 if (node == NULL) return(ret);
588 if (last == NULL)
589 last = ret = node;
590 else {
591 last->next = node;
592 node->prev = last;
593 last = node;
594 }
Daniel Veillardccb09631998-10-27 06:21:04 +0000595 }
596 }
Daniel Veillard25940b71998-10-29 05:51:30 +0000597 /*
598 * Read the entity string
599 */
Daniel Veillardccb09631998-10-27 06:21:04 +0000600 cur++;
601 q = cur;
602 while ((*cur != 0) && (*cur != ';')) cur++;
603 if (*cur == 0) {
604 fprintf(stderr,
605 "xmlStringGetNodeList: unterminated entity %30s\n", q);
606 return(ret);
607 }
608 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000609 /*
610 * Predefined entities don't generate nodes
611 */
Daniel Veillardccb09631998-10-27 06:21:04 +0000612 val = xmlStrndup(q, cur - q);
Daniel Veillard25940b71998-10-29 05:51:30 +0000613 ent = xmlGetDocEntity(doc, val);
614 if ((ent != NULL) &&
615 (ent->type == XML_INTERNAL_PREDEFINED_ENTITY)) {
616 if (last == NULL) {
617 node = xmlNewDocText(doc, ent->content);
618 last = ret = node;
619 } else
620 xmlNodeAddContent(last, ent->content);
621
622 } else {
623 /*
624 * Create a new REFERENCE_REF node
625 */
Daniel Veillard25940b71998-10-29 05:51:30 +0000626 node = xmlNewReference(doc, val);
Daniel Veillard242590e1998-11-13 18:04:35 +0000627 if (node == NULL) {
Daniel Veillard6454aec1999-09-02 22:04:43 +0000628 if (val != NULL) xmlFree(val);
Daniel Veillard242590e1998-11-13 18:04:35 +0000629 return(ret);
630 }
Daniel Veillard25940b71998-10-29 05:51:30 +0000631 if (last == NULL)
632 last = ret = node;
633 else {
634 last->next = node;
635 node->prev = last;
636 last = node;
637 }
Daniel Veillardccb09631998-10-27 06:21:04 +0000638 }
Daniel Veillard6454aec1999-09-02 22:04:43 +0000639 xmlFree(val);
Daniel Veillardccb09631998-10-27 06:21:04 +0000640 }
641 cur++;
642 q = cur;
643 } else
644 cur++;
645 }
646 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000647 /*
648 * Handle the last piece of text.
649 */
650 if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
651 xmlNodeAddContentLen(last, q, cur - q);
652 } else {
653 node = xmlNewDocTextLen(doc, q, cur - q);
654 if (node == NULL) return(ret);
655 if (last == NULL)
656 last = ret = node;
657 else {
658 last->next = node;
659 node->prev = last;
660 last = node;
661 }
Daniel Veillardccb09631998-10-27 06:21:04 +0000662 }
663 }
664 return(ret);
665}
666
667/**
668 * xmlNodeListGetString:
669 * @doc: the document
670 * @list: a Node list
671 * @inLine: should we replace entity contents or show their external form
672 *
673 * Returns the string equivalent to the text contained in the Node list
674 * made of TEXTs and ENTITY_REFs
Daniel Veillard1e346af1999-02-22 10:33:01 +0000675 * Returns a pointer to the string copy, the calller must free it.
Daniel Veillardccb09631998-10-27 06:21:04 +0000676 */
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000677xmlChar *
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000678xmlNodeListGetString(xmlDocPtr doc, xmlNodePtr list, int inLine) {
Daniel Veillardccb09631998-10-27 06:21:04 +0000679 xmlNodePtr node = list;
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000680 xmlChar *ret = NULL;
Daniel Veillardccb09631998-10-27 06:21:04 +0000681 xmlEntityPtr ent;
682
683 if (list == NULL) return(NULL);
684
685 while (node != NULL) {
686 if (node->type == XML_TEXT_NODE) {
687 if (inLine)
688 ret = xmlStrcat(ret, node->content);
Daniel Veillard14fff061999-06-22 21:49:07 +0000689 else {
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000690 xmlChar *buffer;
Daniel Veillard14fff061999-06-22 21:49:07 +0000691
692 buffer = xmlEncodeEntitiesReentrant(doc, node->content);
693 if (buffer != NULL) {
694 ret = xmlStrcat(ret, buffer);
Daniel Veillard6454aec1999-09-02 22:04:43 +0000695 xmlFree(buffer);
Daniel Veillard14fff061999-06-22 21:49:07 +0000696 }
697 }
Daniel Veillardccb09631998-10-27 06:21:04 +0000698 } else if (node->type == XML_ENTITY_REF_NODE) {
699 if (inLine) {
700 ent = xmlGetDocEntity(doc, node->name);
701 if (ent != NULL)
702 ret = xmlStrcat(ret, ent->content);
703 else
704 ret = xmlStrcat(ret, node->content);
705 } else {
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000706 xmlChar buf[2];
Daniel Veillardccb09631998-10-27 06:21:04 +0000707 buf[0] = '&'; buf[1] = 0;
708 ret = xmlStrncat(ret, buf, 1);
709 ret = xmlStrcat(ret, node->name);
710 buf[0] = ';'; buf[1] = 0;
711 ret = xmlStrncat(ret, buf, 1);
712 }
713 }
714#if 0
715 else {
716 fprintf(stderr, "xmlGetNodeListString : invalide node type %d\n",
717 node->type);
718 }
719#endif
720 node = node->next;
721 }
722 return(ret);
723}
724
725/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000726 * xmlNewProp:
727 * @node: the holding node
728 * @name: the name of the attribute
729 * @value: the value of the attribute
730 *
731 * Create a new property carried by a node.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000732 * Returns a pointer to the attribute
Daniel Veillard260a68f1998-08-13 03:39:55 +0000733 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000734xmlAttrPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000735xmlNewProp(xmlNodePtr node, const xmlChar *name, const xmlChar *value) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000736 xmlAttrPtr cur;
737
738 if (name == NULL) {
739 fprintf(stderr, "xmlNewProp : name == NULL\n");
740 return(NULL);
741 }
742
743 /*
744 * Allocate a new property and fill the fields.
745 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000746 cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000747 if (cur == NULL) {
748 fprintf(stderr, "xmlNewProp : malloc failed\n");
749 return(NULL);
750 }
751
Daniel Veillard33942841998-10-18 19:12:41 +0000752 cur->type = XML_ATTRIBUTE_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000753 cur->node = node;
Daniel Veillardb96e6431999-08-29 21:02:19 +0000754 cur->ns = NULL;
755 cur->name = xmlStrdup(name);
756 if (value != NULL)
757 cur->val = xmlStringGetNodeList(node->doc, value);
758 else
759 cur->val = NULL;
760#ifndef XML_WITHOUT_CORBA
761 cur->_private = NULL;
762 cur->vepv = NULL;
763#endif
764
765 /*
766 * Add it at the end to preserve parsing order ...
767 */
768 cur->next = NULL;
769 if (node != NULL) {
770 if (node->properties == NULL) {
771 node->properties = cur;
772 } else {
773 xmlAttrPtr prev = node->properties;
774
775 while (prev->next != NULL) prev = prev->next;
776 prev->next = cur;
777 }
778 }
Daniel Veillard00fdf371999-10-08 09:40:39 +0000779#ifndef XML_WITHOUT_CORBA
780 cur->_private = NULL;
781 cur->vepv = NULL;
782#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +0000783 return(cur);
784}
785
786/**
787 * xmlNewNsProp:
788 * @node: the holding node
789 * @ns: the namespace
790 * @name: the name of the attribute
791 * @value: the value of the attribute
792 *
793 * Create a new property tagged with a namespace and carried by a node.
794 * Returns a pointer to the attribute
795 */
796xmlAttrPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000797xmlNewNsProp(xmlNodePtr node, xmlNsPtr ns, const xmlChar *name,
798 const xmlChar *value) {
Daniel Veillardb96e6431999-08-29 21:02:19 +0000799 xmlAttrPtr cur;
800
801 if (name == NULL) {
802 fprintf(stderr, "xmlNewProp : name == NULL\n");
803 return(NULL);
804 }
805
806 /*
807 * Allocate a new property and fill the fields.
808 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000809 cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr));
Daniel Veillardb96e6431999-08-29 21:02:19 +0000810 if (cur == NULL) {
811 fprintf(stderr, "xmlNewProp : malloc failed\n");
812 return(NULL);
813 }
814
815 cur->type = XML_ATTRIBUTE_NODE;
816 cur->node = node;
817 cur->ns = ns;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000818 cur->name = xmlStrdup(name);
819 if (value != NULL)
Daniel Veillardccb09631998-10-27 06:21:04 +0000820 cur->val = xmlStringGetNodeList(node->doc, value);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000821 else
Daniel Veillardccb09631998-10-27 06:21:04 +0000822 cur->val = NULL;
Daniel Veillard27d88741999-05-29 11:51:49 +0000823#ifndef XML_WITHOUT_CORBA
Daniel Veillard27fb0751998-10-17 06:47:46 +0000824 cur->_private = NULL;
825 cur->vepv = NULL;
826#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000827
828 /*
829 * Add it at the end to preserve parsing order ...
830 */
831 cur->next = NULL;
832 if (node != NULL) {
833 if (node->properties == NULL) {
834 node->properties = cur;
835 } else {
836 xmlAttrPtr prev = node->properties;
837
838 while (prev->next != NULL) prev = prev->next;
839 prev->next = cur;
840 }
841 }
842 return(cur);
843}
844
Daniel Veillard97b58771998-10-20 06:14:16 +0000845/**
Daniel Veillardccb09631998-10-27 06:21:04 +0000846 * xmlNewDocProp:
847 * @doc: the document
848 * @name: the name of the attribute
849 * @value: the value of the attribute
850 *
851 * Create a new property carried by a document.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000852 * Returns a pointer to the attribute
Daniel Veillardccb09631998-10-27 06:21:04 +0000853 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000854xmlAttrPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000855xmlNewDocProp(xmlDocPtr doc, const xmlChar *name, const xmlChar *value) {
Daniel Veillardccb09631998-10-27 06:21:04 +0000856 xmlAttrPtr cur;
857
858 if (name == NULL) {
859 fprintf(stderr, "xmlNewProp : name == NULL\n");
860 return(NULL);
861 }
862
863 /*
864 * Allocate a new property and fill the fields.
865 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000866 cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr));
Daniel Veillardccb09631998-10-27 06:21:04 +0000867 if (cur == NULL) {
868 fprintf(stderr, "xmlNewProp : malloc failed\n");
869 return(NULL);
870 }
871
872 cur->type = XML_ATTRIBUTE_NODE;
873 cur->node = NULL;
874 cur->name = xmlStrdup(name);
875 if (value != NULL)
876 cur->val = xmlStringGetNodeList(doc, value);
877 else
878 cur->val = NULL;
Daniel Veillard27d88741999-05-29 11:51:49 +0000879#ifndef XML_WITHOUT_CORBA
Daniel Veillardccb09631998-10-27 06:21:04 +0000880 cur->_private = NULL;
881 cur->vepv = NULL;
882#endif
883
884 cur->next = NULL;
885 return(cur);
886}
887
888/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000889 * xmlFreePropList:
890 * @cur: the first property in the list
891 *
892 * Free a property and all its siblings, all the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000893 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000894void
895xmlFreePropList(xmlAttrPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000896 xmlAttrPtr next;
897 if (cur == NULL) {
898 fprintf(stderr, "xmlFreePropList : property == NULL\n");
899 return;
900 }
901 while (cur != NULL) {
902 next = cur->next;
903 xmlFreeProp(cur);
904 cur = next;
905 }
906}
907
Daniel Veillard97b58771998-10-20 06:14:16 +0000908/**
909 * xmlFreeProp:
910 * @cur: the first property in the list
911 *
912 * Free one property, all the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000913 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000914void
915xmlFreeProp(xmlAttrPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000916 if (cur == NULL) {
917 fprintf(stderr, "xmlFreeProp : property == NULL\n");
918 return;
919 }
Daniel Veillard6454aec1999-09-02 22:04:43 +0000920 if (cur->name != NULL) xmlFree((char *) cur->name);
Daniel Veillardccb09631998-10-27 06:21:04 +0000921 if (cur->val != NULL) xmlFreeNodeList(cur->val);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000922 memset(cur, -1, sizeof(xmlAttr));
Daniel Veillard6454aec1999-09-02 22:04:43 +0000923 xmlFree(cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000924}
925
Daniel Veillard97b58771998-10-20 06:14:16 +0000926/**
Daniel Veillardb96e6431999-08-29 21:02:19 +0000927 * xmlNewPI:
928 * @name: the processing instruction name
929 * @content: the PI content
930 *
931 * Creation of a processing instruction element.
932 * Returns a pointer to the new node object.
933 */
934xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000935xmlNewPI(const xmlChar *name, const xmlChar *content) {
Daniel Veillardb96e6431999-08-29 21:02:19 +0000936 xmlNodePtr cur;
937
938 if (name == NULL) {
939 fprintf(stderr, "xmlNewPI : name == NULL\n");
940 return(NULL);
941 }
942
943 /*
944 * Allocate a new node and fill the fields.
945 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000946 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillardb96e6431999-08-29 21:02:19 +0000947 if (cur == NULL) {
948 fprintf(stderr, "xmlNewPI : malloc failed\n");
949 return(NULL);
950 }
951
952 cur->type = XML_PI_NODE;
953 cur->doc = NULL;
954 cur->parent = NULL;
955 cur->next = NULL;
956 cur->prev = NULL;
957 cur->childs = NULL;
958 cur->last = NULL;
959 cur->properties = NULL;
960 cur->name = xmlStrdup(name);
961 cur->ns = NULL;
962 cur->nsDef = NULL;
963 if (content != NULL)
964 cur->content = xmlStrdup(content);
965 else
966 cur->content = NULL;
967#ifndef XML_WITHOUT_CORBA
968 cur->_private = NULL;
969 cur->vepv = NULL;
970#endif
971 return(cur);
972}
973
974/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000975 * xmlNewNode:
976 * @ns: namespace if any
977 * @name: the node name
Daniel Veillard97b58771998-10-20 06:14:16 +0000978 *
979 * Creation of a new node element. @ns and @content are optionnal (NULL).
Daniel Veillardccb09631998-10-27 06:21:04 +0000980 * If content is non NULL, a child list containing the TEXTs and
981 * ENTITY_REFs node will be created.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000982 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000983 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000984xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000985xmlNewNode(xmlNsPtr ns, const xmlChar *name) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000986 xmlNodePtr cur;
987
988 if (name == NULL) {
989 fprintf(stderr, "xmlNewNode : name == NULL\n");
990 return(NULL);
991 }
992
993 /*
994 * Allocate a new node and fill the fields.
995 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000996 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000997 if (cur == NULL) {
998 fprintf(stderr, "xmlNewNode : malloc failed\n");
999 return(NULL);
1000 }
1001
Daniel Veillard33942841998-10-18 19:12:41 +00001002 cur->type = XML_ELEMENT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001003 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001004 cur->parent = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001005 cur->next = NULL;
1006 cur->prev = NULL;
1007 cur->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001008 cur->last = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001009 cur->properties = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001010 cur->name = xmlStrdup(name);
1011 cur->ns = ns;
1012 cur->nsDef = NULL;
Daniel Veillardccb09631998-10-27 06:21:04 +00001013 cur->content = NULL;
Daniel Veillard27d88741999-05-29 11:51:49 +00001014#ifndef XML_WITHOUT_CORBA
Daniel Veillard27fb0751998-10-17 06:47:46 +00001015 cur->_private = NULL;
1016 cur->vepv = NULL;
1017#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001018 return(cur);
1019}
1020
Daniel Veillard97b58771998-10-20 06:14:16 +00001021/**
1022 * xmlNewDocNode:
1023 * @doc: the document
1024 * @ns: namespace if any
1025 * @name: the node name
1026 * @content: the text content if any
1027 *
1028 * Creation of a new node element within a document. @ns and @content
1029 * are optionnal (NULL).
Daniel Veillard1e346af1999-02-22 10:33:01 +00001030 * Returns a pointer to the new node object.
Daniel Veillard97b58771998-10-20 06:14:16 +00001031 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001032xmlNodePtr
1033xmlNewDocNode(xmlDocPtr doc, xmlNsPtr ns,
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001034 const xmlChar *name, const xmlChar *content) {
Daniel Veillard0bef1311998-10-14 02:36:47 +00001035 xmlNodePtr cur;
1036
Daniel Veillardccb09631998-10-27 06:21:04 +00001037 cur = xmlNewNode(ns, name);
1038 if (cur != NULL) {
1039 cur->doc = doc;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001040 if (content != NULL) {
Daniel Veillardccb09631998-10-27 06:21:04 +00001041 cur->childs = xmlStringGetNodeList(doc, content);
Daniel Veillard1e346af1999-02-22 10:33:01 +00001042 UPDATE_LAST_CHILD(cur)
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001043 }
Daniel Veillardccb09631998-10-27 06:21:04 +00001044 }
Daniel Veillard0bef1311998-10-14 02:36:47 +00001045 return(cur);
1046}
1047
1048
Daniel Veillard97b58771998-10-20 06:14:16 +00001049/**
1050 * xmlNewText:
1051 * @content: the text content
1052 *
1053 * Creation of a new text node.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001054 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001055 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001056xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001057xmlNewText(const xmlChar *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001058 xmlNodePtr cur;
1059
1060 /*
1061 * Allocate a new node and fill the fields.
1062 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001063 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillard260a68f1998-08-13 03:39:55 +00001064 if (cur == NULL) {
1065 fprintf(stderr, "xmlNewText : malloc failed\n");
1066 return(NULL);
1067 }
1068
Daniel Veillard33942841998-10-18 19:12:41 +00001069 cur->type = XML_TEXT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001070 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001071 cur->parent = NULL;
1072 cur->next = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001073 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001074 cur->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001075 cur->last = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001076 cur->properties = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001077 cur->type = XML_TEXT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001078 cur->name = xmlStrdup(xmlStringText);
1079 cur->ns = NULL;
1080 cur->nsDef = NULL;
1081 if (content != NULL)
1082 cur->content = xmlStrdup(content);
1083 else
1084 cur->content = NULL;
Daniel Veillard00fdf371999-10-08 09:40:39 +00001085#ifndef XML_WITHOUT_CORBA
1086 cur->_private = NULL;
1087 cur->vepv = NULL;
1088#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001089 return(cur);
1090}
1091
Daniel Veillard97b58771998-10-20 06:14:16 +00001092/**
Daniel Veillardccb09631998-10-27 06:21:04 +00001093 * xmlNewReference:
1094 * @doc: the document
1095 * @name: the reference name, or the reference string with & and ;
1096 *
1097 * Creation of a new reference node.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001098 * Returns a pointer to the new node object.
Daniel Veillardccb09631998-10-27 06:21:04 +00001099 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001100xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001101xmlNewReference(xmlDocPtr doc, const xmlChar *name) {
Daniel Veillardccb09631998-10-27 06:21:04 +00001102 xmlNodePtr cur;
1103 xmlEntityPtr ent;
1104
1105 /*
1106 * Allocate a new node and fill the fields.
1107 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001108 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillardccb09631998-10-27 06:21:04 +00001109 if (cur == NULL) {
1110 fprintf(stderr, "xmlNewText : malloc failed\n");
1111 return(NULL);
1112 }
1113
1114 cur->type = XML_ENTITY_REF_NODE;
Daniel Veillard10c6a8f1998-10-28 01:00:12 +00001115 cur->doc = doc;
Daniel Veillardccb09631998-10-27 06:21:04 +00001116 cur->parent = NULL;
1117 cur->next = NULL;
1118 cur->prev = NULL;
1119 cur->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001120 cur->last = NULL;
Daniel Veillardccb09631998-10-27 06:21:04 +00001121 cur->properties = NULL;
1122 if (name[0] == '&') {
1123 int len;
1124 name++;
1125 len = xmlStrlen(name);
1126 if (name[len - 1] == ';')
1127 cur->name = xmlStrndup(name, len - 1);
1128 else
1129 cur->name = xmlStrndup(name, len);
1130 } else
1131 cur->name = xmlStrdup(name);
1132 cur->ns = NULL;
1133 cur->nsDef = NULL;
1134
1135 ent = xmlGetDocEntity(doc, cur->name);
1136 if (ent != NULL)
1137 cur->content = ent->content;
1138 else
1139 cur->content = NULL;
Daniel Veillard00fdf371999-10-08 09:40:39 +00001140#ifndef XML_WITHOUT_CORBA
1141 cur->_private = NULL;
1142 cur->vepv = NULL;
1143#endif
Daniel Veillardccb09631998-10-27 06:21:04 +00001144 return(cur);
1145}
1146
1147/**
Daniel Veillard97b58771998-10-20 06:14:16 +00001148 * xmlNewDocText:
1149 * @doc: the document
1150 * @content: the text content
1151 *
1152 * Creation of a new text node within a document.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001153 * Returns a pointer to the new node object.
Daniel Veillard97b58771998-10-20 06:14:16 +00001154 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001155xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001156xmlNewDocText(xmlDocPtr doc, const xmlChar *content) {
Daniel Veillard0bef1311998-10-14 02:36:47 +00001157 xmlNodePtr cur;
1158
1159 cur = xmlNewText(content);
1160 if (cur != NULL) cur->doc = doc;
1161 return(cur);
1162}
1163
Daniel Veillard97b58771998-10-20 06:14:16 +00001164/**
Daniel Veillardccb09631998-10-27 06:21:04 +00001165 * xmlNewTextLen:
Daniel Veillard97b58771998-10-20 06:14:16 +00001166 * @content: the text content
1167 * @len: the text len.
1168 *
1169 * Creation of a new text node with an extra parameter for the content's lenght
Daniel Veillard1e346af1999-02-22 10:33:01 +00001170 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001171 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001172xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001173xmlNewTextLen(const xmlChar *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001174 xmlNodePtr cur;
1175
1176 /*
1177 * Allocate a new node and fill the fields.
1178 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001179 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillard260a68f1998-08-13 03:39:55 +00001180 if (cur == NULL) {
1181 fprintf(stderr, "xmlNewText : malloc failed\n");
1182 return(NULL);
1183 }
1184
Daniel Veillard33942841998-10-18 19:12:41 +00001185 cur->type = XML_TEXT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001186 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001187 cur->parent = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001188 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001189 cur->next = NULL;
1190 cur->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001191 cur->last = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001192 cur->properties = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001193 cur->type = XML_TEXT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001194 cur->name = xmlStrdup(xmlStringText);
1195 cur->ns = NULL;
1196 cur->nsDef = NULL;
1197 if (content != NULL)
1198 cur->content = xmlStrndup(content, len);
1199 else
1200 cur->content = NULL;
Daniel Veillard00fdf371999-10-08 09:40:39 +00001201#ifndef XML_WITHOUT_CORBA
1202 cur->_private = NULL;
1203 cur->vepv = NULL;
1204#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001205 return(cur);
1206}
1207
Daniel Veillard97b58771998-10-20 06:14:16 +00001208/**
1209 * xmlNewDocTextLen:
1210 * @doc: the document
1211 * @content: the text content
1212 * @len: the text len.
1213 *
1214 * Creation of a new text node with an extra content lenght parameter. The
1215 * text node pertain to a given document.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001216 * Returns a pointer to the new node object.
Daniel Veillard97b58771998-10-20 06:14:16 +00001217 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001218xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001219xmlNewDocTextLen(xmlDocPtr doc, const xmlChar *content, int len) {
Daniel Veillard0bef1311998-10-14 02:36:47 +00001220 xmlNodePtr cur;
1221
1222 cur = xmlNewTextLen(content, len);
1223 if (cur != NULL) cur->doc = doc;
1224 return(cur);
1225}
1226
Daniel Veillard97b58771998-10-20 06:14:16 +00001227/**
1228 * xmlNewComment:
1229 * @content: the comment content
1230 *
1231 * Creation of a new node containing a comment.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001232 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001233 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001234xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001235xmlNewComment(const xmlChar *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001236 xmlNodePtr cur;
1237
1238 /*
1239 * Allocate a new node and fill the fields.
1240 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001241 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillard260a68f1998-08-13 03:39:55 +00001242 if (cur == NULL) {
1243 fprintf(stderr, "xmlNewComment : malloc failed\n");
1244 return(NULL);
1245 }
1246
Daniel Veillard33942841998-10-18 19:12:41 +00001247 cur->type = XML_COMMENT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001248 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001249 cur->parent = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001250 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001251 cur->next = NULL;
1252 cur->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001253 cur->last = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001254 cur->properties = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001255 cur->type = XML_COMMENT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001256 cur->name = xmlStrdup(xmlStringText);
1257 cur->ns = NULL;
1258 cur->nsDef = NULL;
1259 if (content != NULL)
1260 cur->content = xmlStrdup(content);
1261 else
1262 cur->content = NULL;
Daniel Veillard00fdf371999-10-08 09:40:39 +00001263#ifndef XML_WITHOUT_CORBA
1264 cur->_private = NULL;
1265 cur->vepv = NULL;
1266#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001267 return(cur);
1268}
1269
Daniel Veillard97b58771998-10-20 06:14:16 +00001270/**
Daniel Veillardb05deb71999-08-10 19:04:08 +00001271 * xmlNewCDataBlock:
1272 * @doc: the document
1273 * @content: the CData block content content
1274 * @len: the length of the block
1275 *
1276 * Creation of a new node containing a CData block.
1277 * Returns a pointer to the new node object.
1278 */
1279xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001280xmlNewCDataBlock(xmlDocPtr doc, const xmlChar *content, int len) {
Daniel Veillardb05deb71999-08-10 19:04:08 +00001281 xmlNodePtr cur;
1282
1283 /*
1284 * Allocate a new node and fill the fields.
1285 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001286 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillardb05deb71999-08-10 19:04:08 +00001287 if (cur == NULL) {
1288 fprintf(stderr, "xmlNewCDataBlock : malloc failed\n");
1289 return(NULL);
1290 }
1291
1292 cur->type = XML_CDATA_SECTION_NODE;
1293 cur->doc = NULL;
1294 cur->parent = NULL;
1295 cur->prev = NULL;
1296 cur->next = NULL;
1297 cur->childs = NULL;
1298 cur->last = NULL;
1299 cur->properties = NULL;
1300 cur->name = xmlStrdup(xmlStringText);
1301 cur->ns = NULL;
1302 cur->nsDef = NULL;
1303 if ((content != NULL) && (len > 0)) {
1304 cur->content = xmlStrndup(content, len);
1305 } else
1306 cur->content = NULL;
Daniel Veillard00fdf371999-10-08 09:40:39 +00001307#ifndef XML_WITHOUT_CORBA
1308 cur->_private = NULL;
1309 cur->vepv = NULL;
1310#endif
Daniel Veillardb05deb71999-08-10 19:04:08 +00001311 return(cur);
1312}
1313
1314/**
Daniel Veillard1e346af1999-02-22 10:33:01 +00001315 * xmlNewDocComment:
Daniel Veillard97b58771998-10-20 06:14:16 +00001316 * @doc: the document
1317 * @content: the comment content
1318 *
1319 * Creation of a new node containing a commentwithin a document.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001320 * Returns a pointer to the new node object.
Daniel Veillard97b58771998-10-20 06:14:16 +00001321 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001322xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001323xmlNewDocComment(xmlDocPtr doc, const xmlChar *content) {
Daniel Veillard0bef1311998-10-14 02:36:47 +00001324 xmlNodePtr cur;
1325
1326 cur = xmlNewComment(content);
1327 if (cur != NULL) cur->doc = doc;
1328 return(cur);
1329}
1330
Daniel Veillard97b58771998-10-20 06:14:16 +00001331/**
1332 * xmlNewChild:
1333 * @parent: the parent node
1334 * @ns: a namespace if any
1335 * @name: the name of the child
1336 * @content: the content of the child if any.
1337 *
1338 *
1339 * Creation of a new child element, added at the end of @parent childs list.
Daniel Veillardccb09631998-10-27 06:21:04 +00001340 * @ns and @content parameters are optionnal (NULL). If content is non NULL,
1341 * a child list containing the TEXTs and ENTITY_REFs node will be created.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001342 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001343 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001344xmlNodePtr
1345xmlNewChild(xmlNodePtr parent, xmlNsPtr ns,
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001346 const xmlChar *name, const xmlChar *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001347 xmlNodePtr cur, prev;
1348
1349 if (parent == NULL) {
1350 fprintf(stderr, "xmlNewChild : parent == NULL\n");
1351 return(NULL);
1352 }
1353
1354 if (name == NULL) {
1355 fprintf(stderr, "xmlNewChild : name == NULL\n");
1356 return(NULL);
1357 }
1358
1359 /*
1360 * Allocate a new node
1361 */
1362 if (ns == NULL)
Daniel Veillardccb09631998-10-27 06:21:04 +00001363 cur = xmlNewDocNode(parent->doc, parent->ns, name, content);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001364 else
Daniel Veillardccb09631998-10-27 06:21:04 +00001365 cur = xmlNewDocNode(parent->doc, ns, name, content);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001366 if (cur == NULL) return(NULL);
1367
1368 /*
1369 * add the new element at the end of the childs list.
1370 */
Daniel Veillardccb09631998-10-27 06:21:04 +00001371 cur->type = XML_ELEMENT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001372 cur->parent = parent;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001373 cur->doc = parent->doc;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001374 if (parent->childs == NULL) {
1375 parent->childs = cur;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001376 parent->last = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001377 } else {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001378 prev = parent->last;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001379 prev->next = cur;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001380 cur->prev = prev;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001381 parent->last = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001382 }
1383
1384 return(cur);
1385}
1386
Daniel Veillard97b58771998-10-20 06:14:16 +00001387/**
Daniel Veillardb96e6431999-08-29 21:02:19 +00001388 * xmlAddSibling:
1389 * @cur: the child node
1390 * @elem: the new node
1391 *
1392 * Add a new element to the list of siblings of @cur
1393 * Returns the element or NULL in case of error.
1394 */
1395xmlNodePtr
1396xmlAddSibling(xmlNodePtr cur, xmlNodePtr elem) {
1397 xmlNodePtr parent;
1398
1399 if (cur == NULL) {
1400 fprintf(stderr, "xmlAddSibling : cur == NULL\n");
1401 return(NULL);
1402 }
1403
1404 if (elem == NULL) {
1405 fprintf(stderr, "xmlAddSibling : elem == NULL\n");
1406 return(NULL);
1407 }
1408
1409 if ((cur->doc != NULL) && (elem->doc != NULL) &&
1410 (cur->doc != elem->doc)) {
1411 fprintf(stderr,
1412 "xmlAddSibling: Elements moved to a different document\n");
1413 }
1414
1415 while (cur->next != NULL) cur = cur->next;
1416
1417 if (elem->doc == NULL)
1418 elem->doc = cur->doc; /* the parent may not be linked to a doc ! */
1419
1420 parent = cur->parent;
1421 elem->prev = cur;
1422 elem->next = NULL;
1423 elem->parent = parent;
1424 cur->next = elem;
1425 if (parent != NULL)
1426 parent->last = elem;
1427
1428 return(elem);
1429}
1430
1431/**
Daniel Veillard97b58771998-10-20 06:14:16 +00001432 * xmlAddChild:
1433 * @parent: the parent node
1434 * @cur: the child node
1435 *
1436 * Add a new child element, to @parent, at the end of the child list.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001437 * Returns the child or NULL in case of error.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001438 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001439xmlNodePtr
1440xmlAddChild(xmlNodePtr parent, xmlNodePtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001441 xmlNodePtr prev;
1442
1443 if (parent == NULL) {
1444 fprintf(stderr, "xmladdChild : parent == NULL\n");
1445 return(NULL);
1446 }
1447
1448 if (cur == NULL) {
1449 fprintf(stderr, "xmladdChild : child == NULL\n");
1450 return(NULL);
1451 }
1452
Daniel Veillard0bef1311998-10-14 02:36:47 +00001453 if ((cur->doc != NULL) && (parent->doc != NULL) &&
1454 (cur->doc != parent->doc)) {
1455 fprintf(stderr, "Elements moved to a different document\n");
1456 }
1457
Daniel Veillard260a68f1998-08-13 03:39:55 +00001458 /*
1459 * add the new element at the end of the childs list.
1460 */
1461 cur->parent = parent;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001462 cur->doc = parent->doc; /* the parent may not be linked to a doc ! */
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001463
Daniel Veillardccb09631998-10-27 06:21:04 +00001464 /*
1465 * Handle the case where parent->content != NULL, in that case it will
1466 * create a intermediate TEXT node.
1467 */
1468 if (parent->content != NULL) {
1469 xmlNodePtr text;
1470
1471 text = xmlNewDocText(parent->doc, parent->content);
1472 if (text != NULL) {
1473 text->next = parent->childs;
1474 if (text->next != NULL)
1475 text->next->prev = text;
1476 parent->childs = text;
Daniel Veillard1e346af1999-02-22 10:33:01 +00001477 UPDATE_LAST_CHILD(parent)
Daniel Veillard6454aec1999-09-02 22:04:43 +00001478 xmlFree(parent->content);
Daniel Veillardccb09631998-10-27 06:21:04 +00001479 parent->content = NULL;
1480 }
1481 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00001482 if (parent->childs == NULL) {
1483 parent->childs = cur;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001484 parent->last = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001485 } else {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001486 prev = parent->last;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001487 prev->next = cur;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001488 cur->prev = prev;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001489 parent->last = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001490 }
1491
1492 return(cur);
1493}
1494
Daniel Veillard97b58771998-10-20 06:14:16 +00001495/**
1496 * xmlGetLastChild:
1497 * @parent: the parent node
1498 *
1499 * Search the last child of a node.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001500 * Returns the last child or NULL if none.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001501 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001502xmlNodePtr
1503xmlGetLastChild(xmlNodePtr parent) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001504 if (parent == NULL) {
1505 fprintf(stderr, "xmlGetLastChild : parent == NULL\n");
1506 return(NULL);
1507 }
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001508 return(parent->last);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001509}
1510
Daniel Veillard97b58771998-10-20 06:14:16 +00001511/**
1512 * xmlFreeNodeList:
1513 * @cur: the first node in the list
1514 *
1515 * Free a node and all its siblings, this is a recursive behaviour, all
1516 * the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001517 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001518void
1519xmlFreeNodeList(xmlNodePtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001520 xmlNodePtr next;
1521 if (cur == NULL) {
1522 fprintf(stderr, "xmlFreeNodeList : node == NULL\n");
1523 return;
1524 }
1525 while (cur != NULL) {
1526 next = cur->next;
1527 xmlFreeNode(cur);
1528 cur = next;
1529 }
1530}
1531
Daniel Veillard97b58771998-10-20 06:14:16 +00001532/**
1533 * xmlFreeNode:
1534 * @cur: the node
1535 *
1536 * Free a node, this is a recursive behaviour, all the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001537 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001538void
1539xmlFreeNode(xmlNodePtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001540 if (cur == NULL) {
1541 fprintf(stderr, "xmlFreeNode : node == NULL\n");
1542 return;
1543 }
Daniel Veillardccb09631998-10-27 06:21:04 +00001544 cur->doc = NULL;
1545 cur->parent = NULL;
1546 cur->next = NULL;
1547 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001548 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillardccb09631998-10-27 06:21:04 +00001549 if (cur->properties != NULL) xmlFreePropList(cur->properties);
1550 if (cur->type != XML_ENTITY_REF_NODE)
Daniel Veillard6454aec1999-09-02 22:04:43 +00001551 if (cur->content != NULL) xmlFree(cur->content);
1552 if (cur->name != NULL) xmlFree((char *) cur->name);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001553 if (cur->nsDef != NULL) xmlFreeNsList(cur->nsDef);
1554 memset(cur, -1, sizeof(xmlNode));
Daniel Veillard6454aec1999-09-02 22:04:43 +00001555 xmlFree(cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001556}
1557
Daniel Veillard16253641998-10-28 22:58:05 +00001558/**
1559 * xmlUnlinkNode:
1560 * @cur: the node
1561 *
1562 * Unlink a node from it's current context, the node is not freed
1563 */
1564void
1565xmlUnlinkNode(xmlNodePtr cur) {
1566 if (cur == NULL) {
1567 fprintf(stderr, "xmlUnlinkNode : node == NULL\n");
1568 return;
1569 }
1570 if ((cur->parent != NULL) && (cur->parent->childs == cur))
1571 cur->parent->childs = cur->next;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001572 if ((cur->parent != NULL) && (cur->parent->last == cur))
1573 cur->parent->last = cur->prev;
Daniel Veillard16253641998-10-28 22:58:05 +00001574 if (cur->next != NULL)
1575 cur->next->prev = cur->prev;
1576 if (cur->prev != NULL)
1577 cur->prev->next = cur->next;
1578 cur->next = cur->prev = NULL;
1579 cur->parent = NULL;
1580}
1581
Daniel Veillard260a68f1998-08-13 03:39:55 +00001582/************************************************************************
1583 * *
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001584 * Copy operations *
1585 * *
1586 ************************************************************************/
1587
1588/**
1589 * xmlCopyNamespace:
1590 * @cur: the namespace
1591 *
1592 * Do a copy of the namespace.
1593 *
1594 * Returns: a new xmlNsPtr, or NULL in case of error.
1595 */
1596xmlNsPtr
1597xmlCopyNamespace(xmlNsPtr cur) {
1598 xmlNsPtr ret;
1599
1600 if (cur == NULL) return(NULL);
1601 switch (cur->type) {
1602 case XML_GLOBAL_NAMESPACE:
1603 ret = xmlNewGlobalNs(NULL, cur->href, cur->prefix);
1604 break;
1605 case XML_LOCAL_NAMESPACE:
1606 ret = xmlNewNs(NULL, cur->href, cur->prefix);
1607 break;
1608 default:
1609 fprintf(stderr, "xmlCopyNamespace: unknown type %d\n", cur->type);
1610 return(NULL);
1611 }
1612 return(ret);
1613}
1614
1615/**
1616 * xmlCopyNamespaceList:
1617 * @cur: the first namespace
1618 *
1619 * Do a copy of an namespace list.
1620 *
1621 * Returns: a new xmlNsPtr, or NULL in case of error.
1622 */
1623xmlNsPtr
1624xmlCopyNamespaceList(xmlNsPtr cur) {
1625 xmlNsPtr ret = NULL;
1626 xmlNsPtr p = NULL,q;
1627
1628 while (cur != NULL) {
1629 q = xmlCopyNamespace(cur);
1630 if (p == NULL) {
1631 ret = p = q;
1632 } else {
1633 p->next = q;
1634 p = q;
1635 }
1636 cur = cur->next;
1637 }
1638 return(ret);
1639}
1640
1641/**
1642 * xmlCopyProp:
Daniel Veillardb96e6431999-08-29 21:02:19 +00001643 * @target: the element where the attribute will be grafted
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001644 * @cur: the attribute
1645 *
1646 * Do a copy of the attribute.
1647 *
1648 * Returns: a new xmlAttrPtr, or NULL in case of error.
1649 */
1650xmlAttrPtr
Daniel Veillardb96e6431999-08-29 21:02:19 +00001651xmlCopyProp(xmlNodePtr target, xmlAttrPtr cur) {
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001652 xmlAttrPtr ret;
1653
1654 if (cur == NULL) return(NULL);
1655 if (cur->val != NULL)
1656 ret = xmlNewDocProp(cur->val->doc, cur->name, NULL);
1657 else
1658 ret = xmlNewDocProp(NULL, cur->name, NULL);
1659 if (ret == NULL) return(NULL);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001660
1661 if ((cur->ns != NULL) && (target != NULL)) {
1662 xmlNsPtr ns;
1663
1664 ns = xmlSearchNs(target->doc, target, cur->ns->prefix);
1665 ret->ns = ns;
1666 } else
1667 ret->ns = NULL;
1668
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001669 if (cur->val != NULL)
1670 ret->val = xmlCopyNodeList(cur->val);
1671 return(ret);
1672}
1673
1674/**
1675 * xmlCopyPropList:
Daniel Veillardb96e6431999-08-29 21:02:19 +00001676 * @target: the element where the attributes will be grafted
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001677 * @cur: the first attribute
1678 *
1679 * Do a copy of an attribute list.
1680 *
1681 * Returns: a new xmlAttrPtr, or NULL in case of error.
1682 */
1683xmlAttrPtr
Daniel Veillardb96e6431999-08-29 21:02:19 +00001684xmlCopyPropList(xmlNodePtr target, xmlAttrPtr cur) {
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001685 xmlAttrPtr ret = NULL;
1686 xmlAttrPtr p = NULL,q;
1687
1688 while (cur != NULL) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00001689 q = xmlCopyProp(target, cur);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001690 if (p == NULL) {
1691 ret = p = q;
1692 } else {
1693 p->next = q;
1694 p = q;
1695 }
1696 cur = cur->next;
1697 }
1698 return(ret);
1699}
1700
1701/*
1702 * NOTE about the CopyNode operations !
1703 *
1704 * They are splitted into external and internal parts for one
1705 * tricky reason: namespaces. Doing a direct copy of a node
1706 * say RPM:Copyright without changing the namespace pointer to
1707 * something else can produce stale links. One way to do it is
1708 * to keep a reference counter but this doesn't work as soon
1709 * as one move the element or the subtree out of the scope of
1710 * the existing namespace. The actual solution seems to add
1711 * a copy of the namespace at the top of the copied tree if
1712 * not available in the subtree.
1713 * Hence two functions, the public front-end call the inner ones
1714 */
1715
1716static xmlNodePtr
1717xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent);
1718
1719static xmlNodePtr
1720xmlStaticCopyNode(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent,
1721 int recursive) {
1722 xmlNodePtr ret;
1723
1724 if (node == NULL) return(NULL);
1725 /*
1726 * Allocate a new node and fill the fields.
1727 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001728 ret = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001729 if (ret == NULL) {
1730 fprintf(stderr, "xmlStaticCopyNode : malloc failed\n");
1731 return(NULL);
1732 }
1733
1734 ret->type = node->type;
1735 ret->doc = doc;
1736 ret->parent = parent;
1737 ret->next = NULL;
1738 ret->prev = NULL;
1739 ret->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001740 ret->last = NULL;
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001741 ret->properties = NULL;
1742 if (node->name != NULL)
1743 ret->name = xmlStrdup(node->name);
1744 else
1745 ret->name = NULL;
1746 ret->ns = NULL;
1747 ret->nsDef = NULL;
1748 if ((node->content != NULL) && (node->type != XML_ENTITY_REF_NODE))
1749 ret->content = xmlStrdup(node->content);
1750 else
1751 ret->content = NULL;
Daniel Veillard27d88741999-05-29 11:51:49 +00001752#ifndef XML_WITHOUT_CORBA
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001753 ret->_private = NULL;
1754 ret->vepv = NULL;
1755#endif
1756 if (parent != NULL)
1757 xmlAddChild(parent, ret);
1758
1759 if (!recursive) return(ret);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001760 if (node->nsDef != NULL)
1761 ret->nsDef = xmlCopyNamespaceList(node->nsDef);
1762
1763 if (node->ns != NULL) {
1764 xmlNsPtr ns;
1765
1766 ns = xmlSearchNs(doc, ret, node->ns->prefix);
1767 if (ns == NULL) {
1768 /*
1769 * Humm, we are copying an element whose namespace is defined
1770 * out of the new tree scope. Search it in the original tree
1771 * and add it at the top of the new tree
1772 */
1773 ns = xmlSearchNs(node->doc, node, node->ns->prefix);
1774 if (ns != NULL) {
1775 xmlNodePtr root = ret;
1776
1777 while (root->parent != NULL) root = root->parent;
1778 xmlNewNs(root, ns->href, ns->prefix);
1779 }
1780 } else {
1781 /*
1782 * reference the existing namespace definition in our own tree.
1783 */
1784 ret->ns = ns;
1785 }
1786 }
Daniel Veillardb96e6431999-08-29 21:02:19 +00001787 if (node->properties != NULL)
1788 ret->properties = xmlCopyPropList(ret, node->properties);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001789 if (node->childs != NULL)
1790 ret->childs = xmlStaticCopyNodeList(node->childs, doc, ret);
Daniel Veillard1e346af1999-02-22 10:33:01 +00001791 UPDATE_LAST_CHILD(ret)
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001792 return(ret);
1793}
1794
1795static xmlNodePtr
1796xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent) {
1797 xmlNodePtr ret = NULL;
1798 xmlNodePtr p = NULL,q;
1799
1800 while (node != NULL) {
1801 q = xmlStaticCopyNode(node, doc, parent, 1);
1802 if (parent == NULL) {
1803 if (ret == NULL) ret = q;
1804 } else {
1805 if (ret == NULL) {
1806 q->prev = NULL;
1807 ret = p = q;
1808 } else {
1809 p->next = q;
1810 q->prev = p;
1811 p = q;
1812 }
1813 }
1814 node = node->next;
1815 }
1816 return(ret);
1817}
1818
1819/**
1820 * xmlCopyNode:
1821 * @node: the node
1822 * @recursive: if 1 do a recursive copy.
1823 *
1824 * Do a copy of the node.
1825 *
1826 * Returns: a new xmlNodePtr, or NULL in case of error.
1827 */
1828xmlNodePtr
1829xmlCopyNode(xmlNodePtr node, int recursive) {
1830 xmlNodePtr ret;
1831
1832 ret = xmlStaticCopyNode(node, NULL, NULL, recursive);
1833 return(ret);
1834}
1835
1836/**
1837 * xmlCopyNodeList:
1838 * @node: the first node in the list.
1839 *
1840 * Do a recursive copy of the node list.
1841 *
1842 * Returns: a new xmlNodePtr, or NULL in case of error.
1843 */
1844xmlNodePtr xmlCopyNodeList(xmlNodePtr node) {
1845 xmlNodePtr ret = xmlStaticCopyNodeList(node, NULL, NULL);
1846 return(ret);
1847}
1848
1849/**
1850 * xmlCopyElement:
1851 * @elem: the element
1852 *
1853 * Do a copy of the element definition.
1854 *
1855 * Returns: a new xmlElementPtr, or NULL in case of error.
1856xmlElementPtr
1857xmlCopyElement(xmlElementPtr elem) {
1858 xmlElementPtr ret;
1859
1860 if (elem == NULL) return(NULL);
1861 ret = xmlNewDocElement(elem->doc, elem->ns, elem->name, elem->content);
1862 if (ret == NULL) return(NULL);
1863 if (!recursive) return(ret);
1864 if (elem->properties != NULL)
1865 ret->properties = xmlCopyPropList(elem->properties);
1866
1867 if (elem->nsDef != NULL)
1868 ret->nsDef = xmlCopyNamespaceList(elem->nsDef);
1869 if (elem->childs != NULL)
1870 ret->childs = xmlCopyElementList(elem->childs);
1871 return(ret);
1872}
1873 */
1874
1875/**
1876 * xmlCopyDtd:
1877 * @dtd: the dtd
1878 *
1879 * Do a copy of the dtd.
1880 *
1881 * Returns: a new xmlDtdPtr, or NULL in case of error.
1882 */
1883xmlDtdPtr
1884xmlCopyDtd(xmlDtdPtr dtd) {
1885 xmlDtdPtr ret;
1886
1887 if (dtd == NULL) return(NULL);
1888 ret = xmlNewDtd(NULL, dtd->name, dtd->ExternalID, dtd->SystemID);
1889 if (ret == NULL) return(NULL);
1890 if (dtd->entities != NULL)
1891 ret->entities = (void *) xmlCopyEntitiesTable(
1892 (xmlEntitiesTablePtr) dtd->entities);
Daniel Veillard1e346af1999-02-22 10:33:01 +00001893 if (dtd->notations != NULL)
1894 ret->notations = (void *) xmlCopyNotationTable(
1895 (xmlNotationTablePtr) dtd->notations);
1896 if (dtd->elements != NULL)
1897 ret->elements = (void *) xmlCopyElementTable(
1898 (xmlElementTablePtr) dtd->elements);
1899 if (dtd->attributes != NULL)
1900 ret->attributes = (void *) xmlCopyAttributeTable(
1901 (xmlAttributeTablePtr) dtd->attributes);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001902 return(ret);
1903}
1904
1905/**
1906 * xmlCopyDoc:
1907 * @doc: the document
1908 * @recursive: if 1 do a recursive copy.
1909 *
1910 * Do a copy of the document info. If recursive, the content tree will
1911 * be copied too as well as Dtd, namespaces and entities.
1912 *
1913 * Returns: a new xmlDocPtr, or NULL in case of error.
1914 */
1915xmlDocPtr
1916xmlCopyDoc(xmlDocPtr doc, int recursive) {
1917 xmlDocPtr ret;
1918
1919 if (doc == NULL) return(NULL);
1920 ret = xmlNewDoc(doc->version);
1921 if (ret == NULL) return(NULL);
1922 if (doc->name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +00001923 ret->name = xmlMemStrdup(doc->name);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001924 if (doc->encoding != NULL)
1925 ret->encoding = xmlStrdup(doc->encoding);
1926 ret->compression = doc->compression;
1927 ret->standalone = doc->standalone;
1928 if (!recursive) return(ret);
1929
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001930 if (doc->intSubset != NULL)
1931 ret->intSubset = xmlCopyDtd(doc->intSubset);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001932 if (doc->oldNs != NULL)
1933 ret->oldNs = xmlCopyNamespaceList(doc->oldNs);
1934 if (doc->root != NULL)
1935 ret->root = xmlStaticCopyNodeList(doc->root, ret, NULL);
1936 return(ret);
1937}
1938
1939/************************************************************************
1940 * *
Daniel Veillard260a68f1998-08-13 03:39:55 +00001941 * Content access functions *
1942 * *
1943 ************************************************************************/
1944
Daniel Veillard97b58771998-10-20 06:14:16 +00001945/**
Daniel Veillardb96e6431999-08-29 21:02:19 +00001946 * xmlNodeSetLang:
1947 * @cur: the node being changed
1948 * @lang: the langage description
1949 *
1950 * Searches the language of a node, i.e. the values of the xml:lang
1951 * attribute or the one carried by the nearest ancestor.
Daniel Veillardb96e6431999-08-29 21:02:19 +00001952 */
1953void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001954xmlNodeSetLang(xmlNodePtr cur, const xmlChar *lang) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00001955 /* TODO xmlNodeSetLang check against the production [33] LanguageID */
1956 xmlSetProp(cur, BAD_CAST "xml:lang", lang);
1957}
1958
1959/**
1960 * xmlNodeGetLang:
1961 * @cur: the node being checked
1962 *
1963 * Searches the language of a node, i.e. the values of the xml:lang
1964 * attribute or the one carried by the nearest ancestor.
1965 *
1966 * Returns a pointer to the lang value, or NULL if not found
1967 */
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001968const xmlChar *
Daniel Veillardb96e6431999-08-29 21:02:19 +00001969xmlNodeGetLang(xmlNodePtr cur) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001970 const xmlChar *lang;
Daniel Veillardb96e6431999-08-29 21:02:19 +00001971
1972 while (cur != NULL) {
1973 lang = xmlGetProp(cur, BAD_CAST "xml:lang");
1974 if (lang != NULL)
1975 return(lang);
1976 cur = cur->parent;
1977 }
1978 return(NULL);
1979}
1980
1981/**
Daniel Veillard16253641998-10-28 22:58:05 +00001982 * xmlNodeGetContent:
1983 * @cur: the node being read
1984 *
1985 * Read the value of a node, this can be either the text carried
1986 * directly by this node if it's a TEXT node or the aggregate string
1987 * of the values carried by this node child's (TEXT and ENTITY_REF).
1988 * Entity references are substitued.
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001989 * Returns a new xmlChar * or NULL if no content is available.
Daniel Veillard5099ae81999-04-21 20:12:07 +00001990 * It's up to the caller to free the memory.
Daniel Veillard16253641998-10-28 22:58:05 +00001991 */
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001992xmlChar *
Daniel Veillard16253641998-10-28 22:58:05 +00001993xmlNodeGetContent(xmlNodePtr cur) {
1994 if (cur == NULL) return(NULL);
1995 switch (cur->type) {
1996 case XML_DOCUMENT_FRAG_NODE:
1997 case XML_ELEMENT_NODE:
1998 return(xmlNodeListGetString(cur->doc, cur->childs, 1));
1999 break;
Daniel Veillardb96e6431999-08-29 21:02:19 +00002000 case XML_ATTRIBUTE_NODE: {
2001 xmlAttrPtr attr = (xmlAttrPtr) cur;
2002 if (attr->node != NULL)
2003 return(xmlNodeListGetString(attr->node->doc, attr->val, 1));
2004 else
2005 return(xmlNodeListGetString(NULL, attr->val, 1));
2006 break;
2007 }
2008 case XML_PI_NODE:
2009 if (cur->content != NULL)
2010 return(xmlStrdup(cur->content));
2011 return(NULL);
Daniel Veillard16253641998-10-28 22:58:05 +00002012 case XML_ENTITY_REF_NODE:
2013 case XML_ENTITY_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002014 case XML_COMMENT_NODE:
2015 case XML_DOCUMENT_NODE:
2016 case XML_DOCUMENT_TYPE_NODE:
2017 case XML_NOTATION_NODE:
2018 return(NULL);
Daniel Veillardb05deb71999-08-10 19:04:08 +00002019 case XML_CDATA_SECTION_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002020 case XML_TEXT_NODE:
2021 if (cur->content != NULL)
2022 return(xmlStrdup(cur->content));
2023 return(NULL);
2024 }
2025 return(NULL);
2026}
2027
2028/**
Daniel Veillard97b58771998-10-20 06:14:16 +00002029 * xmlNodeSetContent:
2030 * @cur: the node being modified
2031 * @content: the new value of the content
2032 *
2033 * Replace the content of a node.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002034 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002035void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002036xmlNodeSetContent(xmlNodePtr cur, const xmlChar *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002037 if (cur == NULL) {
2038 fprintf(stderr, "xmlNodeSetContent : node == NULL\n");
2039 return;
2040 }
Daniel Veillard16253641998-10-28 22:58:05 +00002041 switch (cur->type) {
2042 case XML_DOCUMENT_FRAG_NODE:
2043 case XML_ELEMENT_NODE:
2044 if (cur->content != NULL) {
Daniel Veillard6454aec1999-09-02 22:04:43 +00002045 xmlFree(cur->content);
Daniel Veillard16253641998-10-28 22:58:05 +00002046 cur->content = NULL;
2047 }
Daniel Veillard6454aec1999-09-02 22:04:43 +00002048 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillard16253641998-10-28 22:58:05 +00002049 cur->childs = xmlStringGetNodeList(cur->doc, content);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002050 UPDATE_LAST_CHILD(cur)
Daniel Veillard16253641998-10-28 22:58:05 +00002051 break;
2052 case XML_ATTRIBUTE_NODE:
2053 break;
2054 case XML_TEXT_NODE:
2055 case XML_CDATA_SECTION_NODE:
2056 case XML_ENTITY_REF_NODE:
2057 case XML_ENTITY_NODE:
2058 case XML_PI_NODE:
2059 case XML_COMMENT_NODE:
Daniel Veillard6454aec1999-09-02 22:04:43 +00002060 if (cur->content != NULL) xmlFree(cur->content);
2061 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002062 cur->last = cur->childs = NULL;
Daniel Veillard16253641998-10-28 22:58:05 +00002063 if (content != NULL)
2064 cur->content = xmlStrdup(content);
2065 else
2066 cur->content = NULL;
Daniel Veillardb96e6431999-08-29 21:02:19 +00002067 break;
Daniel Veillard16253641998-10-28 22:58:05 +00002068 case XML_DOCUMENT_NODE:
2069 case XML_DOCUMENT_TYPE_NODE:
2070 break;
2071 case XML_NOTATION_NODE:
2072 break;
2073 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002074}
2075
Daniel Veillard97b58771998-10-20 06:14:16 +00002076/**
2077 * xmlNodeSetContentLen:
2078 * @cur: the node being modified
2079 * @content: the new value of the content
2080 * @len: the size of @content
2081 *
2082 * Replace the content of a node.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002083 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002084void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002085xmlNodeSetContentLen(xmlNodePtr cur, const xmlChar *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002086 if (cur == NULL) {
Daniel Veillard16253641998-10-28 22:58:05 +00002087 fprintf(stderr, "xmlNodeSetContentLen : node == NULL\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002088 return;
2089 }
Daniel Veillard16253641998-10-28 22:58:05 +00002090 switch (cur->type) {
2091 case XML_DOCUMENT_FRAG_NODE:
2092 case XML_ELEMENT_NODE:
2093 if (cur->content != NULL) {
Daniel Veillard6454aec1999-09-02 22:04:43 +00002094 xmlFree(cur->content);
Daniel Veillard16253641998-10-28 22:58:05 +00002095 cur->content = NULL;
2096 }
Daniel Veillard6454aec1999-09-02 22:04:43 +00002097 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillard16253641998-10-28 22:58:05 +00002098 cur->childs = xmlStringLenGetNodeList(cur->doc, content, len);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002099 UPDATE_LAST_CHILD(cur)
Daniel Veillard16253641998-10-28 22:58:05 +00002100 break;
2101 case XML_ATTRIBUTE_NODE:
2102 break;
2103 case XML_TEXT_NODE:
2104 case XML_CDATA_SECTION_NODE:
2105 case XML_ENTITY_REF_NODE:
2106 case XML_ENTITY_NODE:
2107 case XML_PI_NODE:
2108 case XML_COMMENT_NODE:
Daniel Veillard6454aec1999-09-02 22:04:43 +00002109 if (cur->content != NULL) xmlFree(cur->content);
2110 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002111 cur->childs = cur->last = NULL;
Daniel Veillard16253641998-10-28 22:58:05 +00002112 if (content != NULL)
2113 cur->content = xmlStrndup(content, len);
2114 else
2115 cur->content = NULL;
Daniel Veillardb96e6431999-08-29 21:02:19 +00002116 break;
Daniel Veillard16253641998-10-28 22:58:05 +00002117 case XML_DOCUMENT_NODE:
2118 case XML_DOCUMENT_TYPE_NODE:
2119 break;
2120 case XML_NOTATION_NODE:
Daniel Veillard6454aec1999-09-02 22:04:43 +00002121 if (cur->content != NULL) xmlFree(cur->content);
2122 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002123 cur->childs = cur->last = NULL;
Daniel Veillard16253641998-10-28 22:58:05 +00002124 if (content != NULL)
2125 cur->content = xmlStrndup(content, len);
2126 else
2127 cur->content = NULL;
2128 break;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002129 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002130}
2131
Daniel Veillard97b58771998-10-20 06:14:16 +00002132/**
2133 * xmlNodeAddContentLen:
2134 * @cur: the node being modified
2135 * @content: extra content
2136 * @len: the size of @content
2137 *
2138 * Append the extra substring to the node content.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002139 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002140void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002141xmlNodeAddContentLen(xmlNodePtr cur, const xmlChar *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002142 if (cur == NULL) {
Daniel Veillard16253641998-10-28 22:58:05 +00002143 fprintf(stderr, "xmlNodeAddContentLen : node == NULL\n");
2144 return;
2145 }
2146 if (len <= 0) return;
2147 switch (cur->type) {
2148 case XML_DOCUMENT_FRAG_NODE:
2149 case XML_ELEMENT_NODE: {
2150 xmlNodePtr last = NULL, new;
2151
2152 if (cur->childs != NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002153 last = cur->last;
Daniel Veillard16253641998-10-28 22:58:05 +00002154 } else {
2155 if (cur->content != NULL) {
2156 cur->childs = xmlStringGetNodeList(cur->doc, cur->content);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002157 UPDATE_LAST_CHILD(cur)
Daniel Veillard6454aec1999-09-02 22:04:43 +00002158 xmlFree(cur->content);
Daniel Veillard16253641998-10-28 22:58:05 +00002159 cur->content = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002160 last = cur->last;
Daniel Veillard16253641998-10-28 22:58:05 +00002161 }
2162 }
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002163 new = xmlNewTextLen(content, len);
Daniel Veillard16253641998-10-28 22:58:05 +00002164 if (new != NULL) {
2165 xmlAddChild(cur, new);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002166 if ((last != NULL) && (last->next == new)) {
Daniel Veillard16253641998-10-28 22:58:05 +00002167 xmlTextMerge(last, new);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002168 }
Daniel Veillard16253641998-10-28 22:58:05 +00002169 }
2170 break;
2171 }
2172 case XML_ATTRIBUTE_NODE:
2173 break;
2174 case XML_TEXT_NODE:
2175 case XML_CDATA_SECTION_NODE:
2176 case XML_ENTITY_REF_NODE:
2177 case XML_ENTITY_NODE:
2178 case XML_PI_NODE:
2179 case XML_COMMENT_NODE:
2180 if (content != NULL)
2181 cur->content = xmlStrncat(cur->content, content, len);
2182 case XML_DOCUMENT_NODE:
2183 case XML_DOCUMENT_TYPE_NODE:
2184 break;
2185 case XML_NOTATION_NODE:
2186 if (content != NULL)
2187 cur->content = xmlStrncat(cur->content, content, len);
2188 break;
2189 }
2190}
2191
2192/**
2193 * xmlNodeAddContent:
2194 * @cur: the node being modified
2195 * @content: extra content
2196 *
2197 * Append the extra substring to the node content.
2198 */
2199void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002200xmlNodeAddContent(xmlNodePtr cur, const xmlChar *content) {
Daniel Veillard16253641998-10-28 22:58:05 +00002201 int len;
2202
2203 if (cur == NULL) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002204 fprintf(stderr, "xmlNodeAddContent : node == NULL\n");
2205 return;
2206 }
Daniel Veillard16253641998-10-28 22:58:05 +00002207 if (content == NULL) return;
2208 len = xmlStrlen(content);
2209 xmlNodeAddContentLen(cur, content, len);
2210}
2211
2212/**
2213 * xmlTextMerge:
2214 * @first: the first text node
2215 * @second: the second text node being merged
2216 *
2217 * Merge two text nodes into one
Daniel Veillard1e346af1999-02-22 10:33:01 +00002218 * Returns the first text node augmented
Daniel Veillard16253641998-10-28 22:58:05 +00002219 */
2220xmlNodePtr
2221xmlTextMerge(xmlNodePtr first, xmlNodePtr second) {
2222 if (first == NULL) return(second);
2223 if (second == NULL) return(first);
2224 if (first->type != XML_TEXT_NODE) return(first);
2225 if (second->type != XML_TEXT_NODE) return(first);
2226 xmlNodeAddContent(first, second->content);
2227 xmlUnlinkNode(second);
2228 xmlFreeNode(second);
2229 return(first);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002230}
2231
Daniel Veillard97b58771998-10-20 06:14:16 +00002232/**
Daniel Veillardb96e6431999-08-29 21:02:19 +00002233 * xmlGetNsList:
2234 * @doc: the document
2235 * @node: the current node
2236 *
2237 * Search all the namespace applying to a given element.
2238 * Returns an NULL terminated array of all the xmlNsPtr found
2239 * that need to be freed by the caller or NULL if no
2240 * namespace if defined
2241 */
2242xmlNsPtr *
2243xmlGetNsList(xmlDocPtr doc, xmlNodePtr node) {
2244 xmlNsPtr cur;
2245 xmlNsPtr *ret = NULL;
2246 int nbns = 0;
2247 int maxns = 10;
2248 int i;
2249
2250 while (node != NULL) {
2251 cur = node->nsDef;
2252 while (cur != NULL) {
2253 if (ret == NULL) {
Daniel Veillard6454aec1999-09-02 22:04:43 +00002254 ret = (xmlNsPtr *) xmlMalloc((maxns + 1) * sizeof(xmlNsPtr));
Daniel Veillardb96e6431999-08-29 21:02:19 +00002255 if (ret == NULL) {
2256 fprintf(stderr, "xmlGetNsList : out of memory!\n");
2257 return(NULL);
2258 }
2259 ret[nbns] = NULL;
2260 }
2261 for (i = 0;i < nbns;i++) {
2262 if ((cur->prefix == ret[i]->prefix) ||
2263 (!xmlStrcmp(cur->prefix, ret[i]->prefix))) break;
2264 }
2265 if (i >= nbns) {
2266 if (nbns >= maxns) {
2267 maxns *= 2;
Daniel Veillard6454aec1999-09-02 22:04:43 +00002268 ret = (xmlNsPtr *) xmlRealloc(ret,
Daniel Veillardb96e6431999-08-29 21:02:19 +00002269 (maxns + 1) * sizeof(xmlNsPtr));
2270 if (ret == NULL) {
2271 fprintf(stderr, "xmlGetNsList : realloc failed!\n");
2272 return(NULL);
2273 }
2274 }
2275 ret[nbns++] = cur;
2276 ret[nbns] = NULL;
2277 }
2278
2279 cur = cur->next;
2280 }
2281 node = node->parent;
2282 }
2283 return(ret);
2284}
2285
2286/**
Daniel Veillard97b58771998-10-20 06:14:16 +00002287 * xmlSearchNs:
2288 * @doc: the document
2289 * @node: the current node
2290 * @nameSpace: the namespace string
Daniel Veillard260a68f1998-08-13 03:39:55 +00002291 *
Daniel Veillard97b58771998-10-20 06:14:16 +00002292 * Search a Ns registered under a given name space for a document.
2293 * recurse on the parents until it finds the defined namespace
2294 * or return NULL otherwise.
2295 * @nameSpace can be NULL, this is a search for the default namespace.
Daniel Veillard1e346af1999-02-22 10:33:01 +00002296 * Returns the namespace pointer or NULL.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002297 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002298xmlNsPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002299xmlSearchNs(xmlDocPtr doc, xmlNodePtr node, const xmlChar *nameSpace) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002300 xmlNsPtr cur;
2301
2302 while (node != NULL) {
2303 cur = node->nsDef;
2304 while (cur != NULL) {
2305 if ((cur->prefix == NULL) && (nameSpace == NULL))
2306 return(cur);
2307 if ((cur->prefix != NULL) && (nameSpace != NULL) &&
2308 (!xmlStrcmp(cur->prefix, nameSpace)))
2309 return(cur);
2310 cur = cur->next;
2311 }
2312 node = node->parent;
2313 }
2314 if (doc != NULL) {
2315 cur = doc->oldNs;
2316 while (cur != NULL) {
2317 if ((cur->prefix != NULL) && (nameSpace != NULL) &&
2318 (!xmlStrcmp(cur->prefix, nameSpace)))
2319 return(cur);
2320 cur = cur->next;
2321 }
2322 }
2323 return(NULL);
2324}
2325
Daniel Veillard97b58771998-10-20 06:14:16 +00002326/**
2327 * xmlSearchNsByHref:
2328 * @doc: the document
2329 * @node: the current node
2330 * @href: the namespace value
2331 *
2332 * Search a Ns aliasing a given URI. Recurse on the parents until it finds
2333 * the defined namespace or return NULL otherwise.
Daniel Veillard1e346af1999-02-22 10:33:01 +00002334 * Returns the namespace pointer or NULL.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002335 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002336xmlNsPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002337xmlSearchNsByHref(xmlDocPtr doc, xmlNodePtr node, const xmlChar *href) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002338 xmlNsPtr cur;
2339
2340 while (node != NULL) {
2341 cur = node->nsDef;
2342 while (cur != NULL) {
2343 if ((cur->href != NULL) && (href != NULL) &&
2344 (!xmlStrcmp(cur->href, href)))
2345 return(cur);
2346 cur = cur->next;
2347 }
2348 node = node->parent;
2349 }
2350 if (doc != NULL) {
2351 cur = doc->oldNs;
2352 while (cur != NULL) {
2353 if ((cur->href != NULL) && (href != NULL) &&
2354 (!xmlStrcmp(cur->href, href)))
2355 return(cur);
2356 cur = cur->next;
2357 }
2358 }
2359 return(NULL);
2360}
2361
Daniel Veillard97b58771998-10-20 06:14:16 +00002362/**
2363 * xmlGetProp:
2364 * @node: the node
2365 * @name: the attribute name
2366 *
2367 * Search and get the value of an attribute associated to a node
Daniel Veillardccb09631998-10-27 06:21:04 +00002368 * This does the entity substitution.
Daniel Veillard1e346af1999-02-22 10:33:01 +00002369 * Returns the attribute value or NULL if not found.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002370 */
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002371xmlChar *xmlGetProp(xmlNodePtr node, const xmlChar *name) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002372 xmlAttrPtr prop = node->properties;
2373
2374 while (prop != NULL) {
Daniel Veillard68178931999-02-08 18:34:36 +00002375 if (!xmlStrcmp(prop->name, name)) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002376 xmlChar *ret;
Daniel Veillard6800ef31999-02-08 18:33:22 +00002377
2378 ret = xmlNodeListGetString(node->doc, prop->val, 1);
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002379 if (ret == NULL) return(xmlStrdup((xmlChar *)""));
Daniel Veillard6800ef31999-02-08 18:33:22 +00002380 return(ret);
Daniel Veillard68178931999-02-08 18:34:36 +00002381 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002382 prop = prop->next;
2383 }
2384 return(NULL);
2385}
2386
Daniel Veillard97b58771998-10-20 06:14:16 +00002387/**
Daniel Veillardccb09631998-10-27 06:21:04 +00002388 * xmlSetProp:
Daniel Veillard97b58771998-10-20 06:14:16 +00002389 * @node: the node
2390 * @name: the attribute name
2391 * @value: the attribute value
2392 *
2393 * Set (or reset) an attribute carried by a node.
Daniel Veillard1e346af1999-02-22 10:33:01 +00002394 * Returns the attribute pointer.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002395 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002396xmlAttrPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002397xmlSetProp(xmlNodePtr node, const xmlChar *name, const xmlChar *value) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002398 xmlAttrPtr prop = node->properties;
2399
2400 while (prop != NULL) {
2401 if (!xmlStrcmp(prop->name, name)) {
Daniel Veillardccb09631998-10-27 06:21:04 +00002402 if (prop->val != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +00002403 xmlFreeNodeList(prop->val);
Daniel Veillardccb09631998-10-27 06:21:04 +00002404 prop->val = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002405 if (value != NULL)
Daniel Veillardccb09631998-10-27 06:21:04 +00002406 prop->val = xmlStringGetNodeList(node->doc, value);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002407 return(prop);
2408 }
2409 prop = prop->next;
2410 }
2411 prop = xmlNewProp(node, name, value);
2412 return(prop);
2413}
2414
Daniel Veillard97b58771998-10-20 06:14:16 +00002415/**
2416 * xmlNodeIsText:
2417 * @node: the node
2418 *
2419 * Is this node a Text node ?
Daniel Veillard1e346af1999-02-22 10:33:01 +00002420 * Returns 1 yes, 0 no
Daniel Veillard260a68f1998-08-13 03:39:55 +00002421 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002422int
2423xmlNodeIsText(xmlNodePtr node) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002424 if (node == NULL) return(0);
2425
Daniel Veillard0bef1311998-10-14 02:36:47 +00002426 if (node->type == XML_TEXT_NODE) return(1);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002427 return(0);
2428}
2429
Daniel Veillard97b58771998-10-20 06:14:16 +00002430/**
Daniel Veillard1e346af1999-02-22 10:33:01 +00002431 * xmlTextConcat:
Daniel Veillard97b58771998-10-20 06:14:16 +00002432 * @node: the node
2433 * @content: the content
2434 * @len: @content lenght
2435 *
2436 * Concat the given string at the end of the existing node content
Daniel Veillard260a68f1998-08-13 03:39:55 +00002437 */
Daniel Veillard97b58771998-10-20 06:14:16 +00002438
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002439void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002440xmlTextConcat(xmlNodePtr node, const xmlChar *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002441 if (node == NULL) return;
2442
Daniel Veillard0bef1311998-10-14 02:36:47 +00002443 if (node->type != XML_TEXT_NODE) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002444 fprintf(stderr, "xmlTextConcat: node is not text\n");
2445 return;
2446 }
2447 node->content = xmlStrncat(node->content, content, len);
2448}
2449
2450/************************************************************************
2451 * *
2452 * Output : to a FILE or in memory *
2453 * *
2454 ************************************************************************/
2455
Daniel Veillard5099ae81999-04-21 20:12:07 +00002456#define BASE_BUFFER_SIZE 4000
2457
2458/**
2459 * xmlBufferCreate:
2460 *
2461 * routine to create an XML buffer.
2462 * returns the new structure.
2463 */
2464xmlBufferPtr
2465xmlBufferCreate(void) {
2466 xmlBufferPtr ret;
2467
Daniel Veillard6454aec1999-09-02 22:04:43 +00002468 ret = (xmlBufferPtr) xmlMalloc(sizeof(xmlBuffer));
Daniel Veillard5099ae81999-04-21 20:12:07 +00002469 if (ret == NULL) {
2470 fprintf(stderr, "xmlBufferCreate : out of memory!\n");
2471 return(NULL);
2472 }
2473 ret->use = 0;
2474 ret->size = BASE_BUFFER_SIZE;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002475 ret->content = (xmlChar *) xmlMalloc(ret->size * sizeof(xmlChar));
Daniel Veillard5099ae81999-04-21 20:12:07 +00002476 if (ret->content == NULL) {
2477 fprintf(stderr, "xmlBufferCreate : out of memory!\n");
Daniel Veillard6454aec1999-09-02 22:04:43 +00002478 xmlFree(ret);
Daniel Veillard5099ae81999-04-21 20:12:07 +00002479 return(NULL);
2480 }
2481 ret->content[0] = 0;
2482 return(ret);
2483}
2484
2485/**
2486 * xmlBufferFree:
2487 * @buf: the buffer to free
2488 *
2489 * Frees an XML buffer.
2490 */
2491void
2492xmlBufferFree(xmlBufferPtr buf) {
2493 if (buf == NULL) {
2494 fprintf(stderr, "xmlBufferFree: buf == NULL\n");
2495 return;
2496 }
2497 if (buf->content == NULL) {
2498 fprintf(stderr, "xmlBufferFree: buf->content == NULL\n");
2499 } else {
2500 memset(buf->content, -1, BASE_BUFFER_SIZE);
Daniel Veillard6454aec1999-09-02 22:04:43 +00002501 xmlFree(buf->content);
Daniel Veillard5099ae81999-04-21 20:12:07 +00002502 }
2503 memset(buf, -1, sizeof(xmlBuffer));
Daniel Veillard6454aec1999-09-02 22:04:43 +00002504 xmlFree(buf);
Daniel Veillard5099ae81999-04-21 20:12:07 +00002505}
2506
2507/**
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002508 * xmlBufferEmpty:
2509 * @buf: the buffer
2510 *
2511 * empty a buffer.
2512 */
2513void
2514xmlBufferEmpty(xmlBufferPtr buf) {
2515 buf->use = 0;
2516 memset(buf->content, -1, buf->size);/* just for debug */
2517}
2518
2519/**
2520 * xmlBufferShrink:
2521 * @buf: the buffer to dump
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002522 * @len: the number of xmlChar to remove
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002523 *
2524 * Remove the beginning of an XML buffer.
2525 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002526 * Returns the number of xmlChar removed, or -1 in case of failure.
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002527 */
2528int
2529xmlBufferShrink(xmlBufferPtr buf, int len) {
2530 if (len == 0) return(0);
2531 if (len > buf->use) return(-1);
2532
2533 buf->use -= len;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002534 memmove(buf->content, &buf->content[len], buf->use * sizeof(xmlChar));
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002535
2536 buf->content[buf->use] = 0;
2537 return(len);
2538}
2539
2540/**
Daniel Veillard5099ae81999-04-21 20:12:07 +00002541 * xmlBufferDump:
2542 * @file: the file output
2543 * @buf: the buffer to dump
2544 *
2545 * Dumps an XML buffer to a FILE *.
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002546 * Returns the number of xmlChar written
Daniel Veillard5099ae81999-04-21 20:12:07 +00002547 */
2548int
2549xmlBufferDump(FILE *file, xmlBufferPtr buf) {
2550 int ret;
2551
2552 if (buf == NULL) {
2553 fprintf(stderr, "xmlBufferDump: buf == NULL\n");
2554 return(0);
2555 }
2556 if (buf->content == NULL) {
2557 fprintf(stderr, "xmlBufferDump: buf->content == NULL\n");
2558 return(0);
2559 }
2560 if (file == NULL) file = stdout;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002561 ret = fwrite(buf->content, sizeof(xmlChar), buf->use, file);
Daniel Veillard5099ae81999-04-21 20:12:07 +00002562 return(ret);
2563}
2564
2565/**
2566 * xmlBufferAdd:
2567 * @buf: the buffer to dump
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002568 * @str: the xmlChar string
2569 * @len: the number of xmlChar to add
Daniel Veillard5099ae81999-04-21 20:12:07 +00002570 *
2571 * Add a string range to an XML buffer.
2572 */
2573void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002574xmlBufferAdd(xmlBufferPtr buf, const xmlChar *str, int len) {
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002575 int l;
Daniel Veillard5099ae81999-04-21 20:12:07 +00002576
2577 if (str == NULL) {
2578 fprintf(stderr, "xmlBufferAdd: str == NULL\n");
2579 return;
2580 }
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002581 l = xmlStrlen(str);
2582 if (l < len) len = l;
2583 if (len <= 0) return;
Daniel Veillard5099ae81999-04-21 20:12:07 +00002584
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002585 if (buf->use + len + 10 >= buf->size) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002586 xmlChar *rebuf;
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002587
2588 buf->size *= 2;
2589 if (buf->use + len + 10 > buf->size)
2590 buf->size = buf->use + len + 10;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002591 rebuf = (xmlChar *) xmlRealloc(buf->content, buf->size * sizeof(xmlChar));
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002592 if (rebuf == NULL) {
2593 fprintf(stderr, "xmlBufferAdd : out of memory!\n");
2594 return;
Daniel Veillard5099ae81999-04-21 20:12:07 +00002595 }
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002596 buf->content = rebuf;
Daniel Veillard5099ae81999-04-21 20:12:07 +00002597 }
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002598 memmove(&buf->content[buf->use], str, len);
2599 buf->use += len;
2600 buf->content[buf->use] = 0;
Daniel Veillard5099ae81999-04-21 20:12:07 +00002601}
2602
2603/**
2604 * xmlBufferCat:
2605 * @buf: the buffer to dump
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002606 * @str: the xmlChar string
Daniel Veillard5099ae81999-04-21 20:12:07 +00002607 *
2608 * Append a zero terminated string to an XML buffer.
2609 */
2610void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002611xmlBufferCat(xmlBufferPtr buf, const xmlChar *str) {
2612 const xmlChar *cur;
Daniel Veillard5099ae81999-04-21 20:12:07 +00002613
2614 if (str == NULL) {
2615 fprintf(stderr, "xmlBufferAdd: str == NULL\n");
2616 return;
2617 }
2618 for (cur = str;*cur != 0;cur++) {
2619 if (buf->use + 10 >= buf->size) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002620 xmlChar *rebuf;
Daniel Veillard5099ae81999-04-21 20:12:07 +00002621
2622 buf->size *= 2;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002623 rebuf = (xmlChar *) xmlRealloc(buf->content, buf->size * sizeof(xmlChar));
Daniel Veillard5099ae81999-04-21 20:12:07 +00002624 if (rebuf == NULL) {
2625 fprintf(stderr, "xmlBufferAdd : out of memory!\n");
2626 return;
2627 }
2628 buf->content = rebuf;
2629 }
2630 buf->content[buf->use++] = *cur;
2631 }
2632}
2633
2634/**
2635 * xmlBufferCCat:
2636 * @buf: the buffer to dump
2637 * @str: the C char string
2638 *
2639 * Append a zero terminated C string to an XML buffer.
2640 */
2641void
2642xmlBufferCCat(xmlBufferPtr buf, const char *str) {
2643 const char *cur;
2644
2645 if (str == NULL) {
2646 fprintf(stderr, "xmlBufferAdd: str == NULL\n");
2647 return;
2648 }
2649 for (cur = str;*cur != 0;cur++) {
2650 if (buf->use + 10 >= buf->size) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002651 xmlChar *rebuf;
Daniel Veillard5099ae81999-04-21 20:12:07 +00002652
2653 buf->size *= 2;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002654 rebuf = (xmlChar *) xmlRealloc(buf->content, buf->size * sizeof(xmlChar));
Daniel Veillard5099ae81999-04-21 20:12:07 +00002655 if (rebuf == NULL) {
2656 fprintf(stderr, "xmlBufferAdd : out of memory!\n");
2657 return;
2658 }
2659 buf->content = rebuf;
2660 }
2661 buf->content[buf->use++] = *cur;
2662 }
2663}
Daniel Veillard260a68f1998-08-13 03:39:55 +00002664
Daniel Veillard97b58771998-10-20 06:14:16 +00002665/**
Daniel Veillard7d2c2761999-10-11 15:09:51 +00002666 * xmlBufferLastChar:
2667 * @buf: the buffer to dump
2668 *
2669 * Get the last char of the buffer
2670 *
2671 * Returns the last char from the buffer or 0 if empty
2672 */
2673xmlChar
2674xmlBufferLastChar(xmlBufferPtr buf) {
2675 if ((buf == NULL) || (buf->use <= 0)) return(0);
2676 return(buf->content[buf->use - 1]);
2677}
2678
2679/**
Daniel Veillard97b58771998-10-20 06:14:16 +00002680 * xmlBufferWriteCHAR:
Daniel Veillard5099ae81999-04-21 20:12:07 +00002681 * @buf: the XML buffer
Daniel Veillard97b58771998-10-20 06:14:16 +00002682 * @string: the string to add
2683 *
2684 * routine which manage and grows an output buffer. This one add
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002685 * xmlChars at the end of the buffer.
Daniel Veillard97b58771998-10-20 06:14:16 +00002686 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002687void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002688xmlBufferWriteCHAR(xmlBufferPtr buf, const xmlChar *string) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002689 xmlBufferCat(buf, string);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002690}
2691
Daniel Veillard97b58771998-10-20 06:14:16 +00002692/**
2693 * xmlBufferWriteChar:
Daniel Veillard011b63c1999-06-02 17:44:04 +00002694 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00002695 * @string: the string to add
2696 *
2697 * routine which manage and grows an output buffer. This one add
2698 * C chars at the end of the array.
2699 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002700void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002701xmlBufferWriteChar(xmlBufferPtr buf, const char *string) {
2702 xmlBufferCCat(buf, string);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002703}
2704
Daniel Veillard5099ae81999-04-21 20:12:07 +00002705
Daniel Veillard97b58771998-10-20 06:14:16 +00002706/**
Daniel Veillard011b63c1999-06-02 17:44:04 +00002707 * xmlBufferWriteQuotedString:
2708 * @buf: the XML buffer output
2709 * @string: the string to add
2710 *
2711 * routine which manage and grows an output buffer. This one writes
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002712 * a quoted or double quoted xmlChar string, checking first if it holds
Daniel Veillard011b63c1999-06-02 17:44:04 +00002713 * quote or double-quotes internally
2714 */
2715void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002716xmlBufferWriteQuotedString(xmlBufferPtr buf, const xmlChar *string) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00002717 if (xmlStrchr(string, '"')) {
2718 if (xmlStrchr(string, '\'')) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00002719 fprintf(stderr,
2720 "xmlBufferWriteQuotedString: string contains quote and double-quotes !\n");
2721 }
2722 xmlBufferCCat(buf, "'");
2723 xmlBufferCat(buf, string);
2724 xmlBufferCCat(buf, "'");
2725 } else {
2726 xmlBufferCCat(buf, "\"");
2727 xmlBufferCat(buf, string);
2728 xmlBufferCCat(buf, "\"");
2729 }
2730}
2731
2732
2733/**
Daniel Veillard97b58771998-10-20 06:14:16 +00002734 * xmlGlobalNsDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00002735 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00002736 * @cur: a namespace
2737 *
2738 * Dump a global Namespace, this is the old version based on PIs.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002739 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002740static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002741xmlGlobalNsDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002742 if (cur == NULL) {
2743 fprintf(stderr, "xmlGlobalNsDump : Ns == NULL\n");
2744 return;
2745 }
2746 if (cur->type == XML_GLOBAL_NAMESPACE) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002747 xmlBufferWriteChar(buf, "<?namespace");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002748 if (cur->href != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00002749 xmlBufferWriteChar(buf, " href=");
2750 xmlBufferWriteQuotedString(buf, cur->href);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002751 }
2752 if (cur->prefix != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00002753 xmlBufferWriteChar(buf, " AS=");
2754 xmlBufferWriteQuotedString(buf, cur->prefix);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002755 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00002756 xmlBufferWriteChar(buf, "?>\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002757 }
2758}
2759
Daniel Veillard97b58771998-10-20 06:14:16 +00002760/**
2761 * xmlGlobalNsListDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00002762 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00002763 * @cur: the first namespace
2764 *
2765 * Dump a list of global Namespace, this is the old version based on PIs.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002766 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002767static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002768xmlGlobalNsListDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002769 while (cur != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002770 xmlGlobalNsDump(buf, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002771 cur = cur->next;
2772 }
2773}
2774
Daniel Veillard97b58771998-10-20 06:14:16 +00002775/**
2776 * xmlNsDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00002777 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00002778 * @cur: a namespace
2779 *
Daniel Veillard260a68f1998-08-13 03:39:55 +00002780 * Dump a local Namespace definition.
Daniel Veillard97b58771998-10-20 06:14:16 +00002781 * Should be called in the context of attributes dumps.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002782 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002783static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002784xmlNsDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002785 if (cur == NULL) {
2786 fprintf(stderr, "xmlNsDump : Ns == NULL\n");
2787 return;
2788 }
2789 if (cur->type == XML_LOCAL_NAMESPACE) {
2790 /* Within the context of an element attributes */
2791 if (cur->prefix != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002792 xmlBufferWriteChar(buf, " xmlns:");
2793 xmlBufferWriteCHAR(buf, cur->prefix);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002794 } else
Daniel Veillard5099ae81999-04-21 20:12:07 +00002795 xmlBufferWriteChar(buf, " xmlns");
Daniel Veillard011b63c1999-06-02 17:44:04 +00002796 xmlBufferWriteChar(buf, "=");
2797 xmlBufferWriteQuotedString(buf, cur->href);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002798 }
2799}
2800
Daniel Veillard97b58771998-10-20 06:14:16 +00002801/**
2802 * xmlNsListDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00002803 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00002804 * @cur: the first namespace
2805 *
2806 * Dump a list of local Namespace definitions.
2807 * Should be called in the context of attributes dumps.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002808 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002809static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002810xmlNsListDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002811 while (cur != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002812 xmlNsDump(buf, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002813 cur = cur->next;
2814 }
2815}
2816
Daniel Veillard97b58771998-10-20 06:14:16 +00002817/**
2818 * xmlDtdDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00002819 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00002820 * @doc: the document
2821 *
2822 * Dump the XML document DTD, if any.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002823 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002824static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002825xmlDtdDump(xmlBufferPtr buf, xmlDocPtr doc) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002826 xmlDtdPtr cur = doc->intSubset;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002827
2828 if (cur == NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002829 fprintf(stderr, "xmlDtdDump : no internal subset\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002830 return;
2831 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00002832 xmlBufferWriteChar(buf, "<!DOCTYPE ");
2833 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002834 if (cur->ExternalID != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00002835 xmlBufferWriteChar(buf, " PUBLIC ");
2836 xmlBufferWriteQuotedString(buf, cur->ExternalID);
2837 xmlBufferWriteChar(buf, " ");
2838 xmlBufferWriteQuotedString(buf, cur->SystemID);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002839 } else if (cur->SystemID != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00002840 xmlBufferWriteChar(buf, " SYSTEM ");
2841 xmlBufferWriteQuotedString(buf, cur->SystemID);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002842 }
Daniel Veillard1e346af1999-02-22 10:33:01 +00002843 if ((cur->entities == NULL) && (cur->elements == NULL) &&
2844 (cur->attributes == NULL) && (cur->notations == NULL)) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002845 xmlBufferWriteChar(buf, ">\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002846 return;
2847 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00002848 xmlBufferWriteChar(buf, " [\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002849 if (cur->entities != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00002850 xmlDumpEntitiesTable(buf, (xmlEntitiesTablePtr) cur->entities);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002851 if (cur->notations != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00002852 xmlDumpNotationTable(buf, (xmlNotationTablePtr) cur->notations);
Daniel Veillard3b9def11999-01-31 22:15:06 +00002853 if (cur->elements != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00002854 xmlDumpElementTable(buf, (xmlElementTablePtr) cur->elements);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002855 if (cur->attributes != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00002856 xmlDumpAttributeTable(buf, (xmlAttributeTablePtr) cur->attributes);
2857 xmlBufferWriteChar(buf, "]");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002858
Daniel Veillard5099ae81999-04-21 20:12:07 +00002859 xmlBufferWriteChar(buf, ">\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002860}
2861
Daniel Veillard97b58771998-10-20 06:14:16 +00002862/**
2863 * xmlAttrDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00002864 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00002865 * @doc: the document
2866 * @cur: the attribute pointer
2867 *
2868 * Dump an XML attribute
Daniel Veillard260a68f1998-08-13 03:39:55 +00002869 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002870static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002871xmlAttrDump(xmlBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002872 xmlChar *value;
Daniel Veillardccb09631998-10-27 06:21:04 +00002873
Daniel Veillard260a68f1998-08-13 03:39:55 +00002874 if (cur == NULL) {
2875 fprintf(stderr, "xmlAttrDump : property == NULL\n");
2876 return;
2877 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00002878 xmlBufferWriteChar(buf, " ");
Daniel Veillardb96e6431999-08-29 21:02:19 +00002879 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
2880 xmlBufferWriteCHAR(buf, cur->ns->prefix);
2881 xmlBufferWriteChar(buf, ":");
2882 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00002883 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillardccb09631998-10-27 06:21:04 +00002884 value = xmlNodeListGetString(doc, cur->val, 0);
2885 if (value) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00002886 xmlBufferWriteChar(buf, "=");
2887 xmlBufferWriteQuotedString(buf, value);
Daniel Veillard6454aec1999-09-02 22:04:43 +00002888 xmlFree(value);
Daniel Veillard726c7e31999-02-08 15:13:10 +00002889 } else {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002890 xmlBufferWriteChar(buf, "=\"\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002891 }
2892}
2893
Daniel Veillard97b58771998-10-20 06:14:16 +00002894/**
2895 * xmlAttrListDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00002896 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00002897 * @doc: the document
2898 * @cur: the first attribute pointer
2899 *
2900 * Dump a list of XML attributes
Daniel Veillard260a68f1998-08-13 03:39:55 +00002901 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002902static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002903xmlAttrListDump(xmlBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002904 if (cur == NULL) {
2905 fprintf(stderr, "xmlAttrListDump : property == NULL\n");
2906 return;
2907 }
2908 while (cur != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002909 xmlAttrDump(buf, doc, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002910 cur = cur->next;
2911 }
2912}
2913
Daniel Veillard260a68f1998-08-13 03:39:55 +00002914
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002915static void
Daniel Veillard7d2c2761999-10-11 15:09:51 +00002916xmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
2917 int format);
Daniel Veillard97b58771998-10-20 06:14:16 +00002918/**
2919 * xmlNodeListDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00002920 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00002921 * @doc: the document
2922 * @cur: the first node
2923 * @level: the imbrication level for indenting
Daniel Veillard7d2c2761999-10-11 15:09:51 +00002924 * @format: is formatting allowed
Daniel Veillard97b58771998-10-20 06:14:16 +00002925 *
2926 * Dump an XML node list, recursive behaviour,children are printed too.
2927 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002928static void
Daniel Veillard7d2c2761999-10-11 15:09:51 +00002929xmlNodeListDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
2930 int format) {
2931 int i;
Daniel Veillardccb09631998-10-27 06:21:04 +00002932
Daniel Veillard260a68f1998-08-13 03:39:55 +00002933 if (cur == NULL) {
2934 fprintf(stderr, "xmlNodeListDump : node == NULL\n");
2935 return;
2936 }
2937 while (cur != NULL) {
Daniel Veillard7d2c2761999-10-11 15:09:51 +00002938 if ((format) && (xmlIndentTreeOutput) &&
2939 (cur->type == XML_ELEMENT_NODE))
2940 for (i = 0;i < level;i++)
2941 xmlBufferWriteChar(buf, " ");
2942 xmlNodeDump(buf, doc, cur, level, format);
2943 if (format) {
2944 xmlBufferWriteChar(buf, "\n");
Daniel Veillardccb09631998-10-27 06:21:04 +00002945 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002946 cur = cur->next;
2947 }
2948}
2949
Daniel Veillard97b58771998-10-20 06:14:16 +00002950/**
Daniel Veillardccb09631998-10-27 06:21:04 +00002951 * xmlNodeDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00002952 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00002953 * @doc: the document
2954 * @cur: the current node
2955 * @level: the imbrication level for indenting
Daniel Veillard7d2c2761999-10-11 15:09:51 +00002956 * @format: is formatting allowed
Daniel Veillard97b58771998-10-20 06:14:16 +00002957 *
2958 * Dump an XML node, recursive behaviour,children are printed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002959 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002960static void
Daniel Veillard7d2c2761999-10-11 15:09:51 +00002961xmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
2962 int format) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002963 int i;
Daniel Veillard7d2c2761999-10-11 15:09:51 +00002964 xmlNodePtr tmp;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002965
2966 if (cur == NULL) {
2967 fprintf(stderr, "xmlNodeDump : node == NULL\n");
2968 return;
2969 }
Daniel Veillard0bef1311998-10-14 02:36:47 +00002970 if (cur->type == XML_TEXT_NODE) {
Daniel Veillard14fff061999-06-22 21:49:07 +00002971 if (cur->content != NULL) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002972 xmlChar *buffer;
Daniel Veillard14fff061999-06-22 21:49:07 +00002973
2974 buffer = xmlEncodeEntitiesReentrant(doc, cur->content);
2975 if (buffer != NULL) {
2976 xmlBufferWriteCHAR(buf, buffer);
Daniel Veillard6454aec1999-09-02 22:04:43 +00002977 xmlFree(buffer);
Daniel Veillard14fff061999-06-22 21:49:07 +00002978 }
2979 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002980 return;
2981 }
Daniel Veillardb96e6431999-08-29 21:02:19 +00002982 if (cur->type == XML_PI_NODE) {
2983 if (cur->content != NULL) {
2984 xmlBufferWriteChar(buf, "<?");
2985 xmlBufferWriteCHAR(buf, cur->name);
2986 if (cur->content != NULL) {
2987 xmlBufferWriteChar(buf, " ");
2988 xmlBufferWriteCHAR(buf, cur->content);
2989 }
Daniel Veillard7d2c2761999-10-11 15:09:51 +00002990 xmlBufferWriteChar(buf, "?>");
Daniel Veillardb96e6431999-08-29 21:02:19 +00002991 }
2992 return;
2993 }
Daniel Veillard0bef1311998-10-14 02:36:47 +00002994 if (cur->type == XML_COMMENT_NODE) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002995 if (cur->content != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002996 xmlBufferWriteChar(buf, "<!--");
2997 xmlBufferWriteCHAR(buf, cur->content);
Daniel Veillard7d2c2761999-10-11 15:09:51 +00002998 xmlBufferWriteChar(buf, "-->");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002999 }
3000 return;
3001 }
Daniel Veillardccb09631998-10-27 06:21:04 +00003002 if (cur->type == XML_ENTITY_REF_NODE) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003003 xmlBufferWriteChar(buf, "&");
3004 xmlBufferWriteCHAR(buf, cur->name);
3005 xmlBufferWriteChar(buf, ";");
Daniel Veillardccb09631998-10-27 06:21:04 +00003006 return;
3007 }
Daniel Veillardb05deb71999-08-10 19:04:08 +00003008 if (cur->type == XML_CDATA_SECTION_NODE) {
3009 xmlBufferWriteChar(buf, "<![CDATA[");
3010 if (cur->content != NULL)
3011 xmlBufferWriteCHAR(buf, cur->content);
3012 xmlBufferWriteChar(buf, "]]>");
3013 return;
3014 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003015
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003016 if (format == 1) {
3017 tmp = cur->childs;
3018 while (tmp != NULL) {
3019 if ((tmp->type == XML_TEXT_NODE) ||
3020 (tmp->type == XML_ENTITY_REF_NODE)) {
3021 format = 0;
3022 break;
3023 }
3024 tmp = tmp->next;
3025 }
3026 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003027 xmlBufferWriteChar(buf, "<");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003028 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003029 xmlBufferWriteCHAR(buf, cur->ns->prefix);
3030 xmlBufferWriteChar(buf, ":");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003031 }
3032
Daniel Veillard5099ae81999-04-21 20:12:07 +00003033 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003034 if (cur->nsDef)
Daniel Veillard5099ae81999-04-21 20:12:07 +00003035 xmlNsListDump(buf, cur->nsDef);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003036 if (cur->properties != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00003037 xmlAttrListDump(buf, doc, cur->properties);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003038
3039 if ((cur->content == NULL) && (cur->childs == NULL)) {
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003040 xmlBufferWriteChar(buf, "/>");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003041 return;
3042 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003043 xmlBufferWriteChar(buf, ">");
Daniel Veillard14fff061999-06-22 21:49:07 +00003044 if (cur->content != NULL) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003045 xmlChar *buffer;
Daniel Veillard14fff061999-06-22 21:49:07 +00003046
3047 buffer = xmlEncodeEntitiesReentrant(doc, cur->content);
3048 if (buffer != NULL) {
3049 xmlBufferWriteCHAR(buf, buffer);
Daniel Veillard6454aec1999-09-02 22:04:43 +00003050 xmlFree(buffer);
Daniel Veillard14fff061999-06-22 21:49:07 +00003051 }
3052 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003053 if (cur->childs != NULL) {
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003054 if (format) xmlBufferWriteChar(buf, "\n");
3055 xmlNodeListDump(buf, doc, cur->childs, level + 1, format);
3056 if ((xmlIndentTreeOutput) && (format))
3057 for (i = 0;i < level;i++)
3058 xmlBufferWriteChar(buf, " ");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003059 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003060 xmlBufferWriteChar(buf, "</");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003061 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003062 xmlBufferWriteCHAR(buf, cur->ns->prefix);
3063 xmlBufferWriteChar(buf, ":");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003064 }
3065
Daniel Veillard5099ae81999-04-21 20:12:07 +00003066 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003067 xmlBufferWriteChar(buf, ">");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003068}
3069
Daniel Veillard97b58771998-10-20 06:14:16 +00003070/**
3071 * xmlDocContentDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003072 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003073 * @cur: the document
3074 *
3075 * Dump an XML document.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003076 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003077static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00003078xmlDocContentDump(xmlBufferPtr buf, xmlDocPtr cur) {
Daniel Veillardbe70ff71999-07-05 16:50:46 +00003079 xmlBufferWriteChar(buf, "<?xml version=");
3080 if (cur->version != NULL)
3081 xmlBufferWriteQuotedString(buf, cur->version);
3082 else
3083 xmlBufferWriteChar(buf, "\"1.0\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003084 if (cur->encoding != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00003085 xmlBufferWriteChar(buf, " encoding=");
3086 xmlBufferWriteQuotedString(buf, cur->encoding);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003087 }
3088 switch (cur->standalone) {
3089 case 0:
Daniel Veillard5099ae81999-04-21 20:12:07 +00003090 xmlBufferWriteChar(buf, " standalone=\"no\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003091 break;
3092 case 1:
Daniel Veillard5099ae81999-04-21 20:12:07 +00003093 xmlBufferWriteChar(buf, " standalone=\"yes\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003094 break;
3095 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003096 xmlBufferWriteChar(buf, "?>\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003097 if (cur->intSubset != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00003098 xmlDtdDump(buf, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003099 if (cur->root != NULL) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00003100 xmlNodePtr child = cur->root;
3101
Daniel Veillard260a68f1998-08-13 03:39:55 +00003102 /* global namespace definitions, the old way */
3103 if (oldXMLWDcompatibility)
Daniel Veillard5099ae81999-04-21 20:12:07 +00003104 xmlGlobalNsListDump(buf, cur->oldNs);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003105 else
3106 xmlUpgradeOldNs(cur);
Daniel Veillardb96e6431999-08-29 21:02:19 +00003107
3108 while (child != NULL) {
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003109 xmlNodeDump(buf, cur, child, 0, 1);
3110 xmlBufferWriteChar(buf, "\n");
Daniel Veillardb96e6431999-08-29 21:02:19 +00003111 child = child->next;
3112 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003113 }
3114}
3115
Daniel Veillard97b58771998-10-20 06:14:16 +00003116/**
3117 * xmlDocDumpMemory:
3118 * @cur: the document
3119 * @mem: OUT: the memory pointer
3120 * @size: OUT: the memory lenght
3121 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003122 * Dump an XML document in memory and return the xmlChar * and it's size.
Daniel Veillard97b58771998-10-20 06:14:16 +00003123 * It's up to the caller to free the memory.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003124 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003125void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003126xmlDocDumpMemory(xmlDocPtr cur, xmlChar**mem, int *size) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003127 xmlBufferPtr buf;
3128
Daniel Veillard260a68f1998-08-13 03:39:55 +00003129 if (cur == NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003130#ifdef DEBUG_TREE
3131 fprintf(stderr, "xmlDocDumpMemory : document == NULL\n");
3132#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00003133 *mem = NULL;
3134 *size = 0;
3135 return;
3136 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003137 buf = xmlBufferCreate();
3138 if (buf == NULL) {
3139 *mem = NULL;
3140 *size = 0;
3141 return;
3142 }
3143 xmlDocContentDump(buf, cur);
Daniel Veillardb05deb71999-08-10 19:04:08 +00003144 *mem = xmlStrndup(buf->content, buf->use);
Daniel Veillard5099ae81999-04-21 20:12:07 +00003145 *size = buf->use;
Daniel Veillardb05deb71999-08-10 19:04:08 +00003146 xmlBufferFree(buf);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003147}
3148
Daniel Veillard97b58771998-10-20 06:14:16 +00003149/**
3150 * xmlGetDocCompressMode:
3151 * @doc: the document
3152 *
3153 * get the compression ratio for a document, ZLIB based
Daniel Veillard1e346af1999-02-22 10:33:01 +00003154 * Returns 0 (uncompressed) to 9 (max compression)
Daniel Veillard151b1b01998-09-23 00:49:46 +00003155 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003156int
3157 xmlGetDocCompressMode (xmlDocPtr doc) {
Daniel Veillard15a8df41998-09-24 19:15:06 +00003158 if (doc == NULL) return(-1);
3159 return(doc->compression);
3160}
3161
Daniel Veillard97b58771998-10-20 06:14:16 +00003162/**
3163 * xmlSetDocCompressMode:
3164 * @doc: the document
3165 * @mode: the compression ratio
3166 *
3167 * set the compression ratio for a document, ZLIB based
3168 * Correct values: 0 (uncompressed) to 9 (max compression)
3169 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003170void
3171xmlSetDocCompressMode (xmlDocPtr doc, int mode) {
Daniel Veillard15a8df41998-09-24 19:15:06 +00003172 if (doc == NULL) return;
3173 if (mode < 0) doc->compression = 0;
3174 else if (mode > 9) doc->compression = 9;
3175 else doc->compression = mode;
3176}
3177
Daniel Veillard97b58771998-10-20 06:14:16 +00003178/**
3179 * xmlGetCompressMode:
3180 *
3181 * get the default compression mode used, ZLIB based.
Daniel Veillard1e346af1999-02-22 10:33:01 +00003182 * Returns 0 (uncompressed) to 9 (max compression)
Daniel Veillard15a8df41998-09-24 19:15:06 +00003183 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003184int
3185 xmlGetCompressMode(void) {
Daniel Veillard151b1b01998-09-23 00:49:46 +00003186 return(xmlCompressMode);
3187}
Daniel Veillard97b58771998-10-20 06:14:16 +00003188
3189/**
3190 * xmlSetCompressMode:
3191 * @mode: the compression ratio
3192 *
3193 * set the default compression mode used, ZLIB based
3194 * Correct values: 0 (uncompressed) to 9 (max compression)
3195 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003196void
3197xmlSetCompressMode(int mode) {
Daniel Veillard151b1b01998-09-23 00:49:46 +00003198 if (mode < 0) xmlCompressMode = 0;
Daniel Veillard15a8df41998-09-24 19:15:06 +00003199 else if (mode > 9) xmlCompressMode = 9;
Daniel Veillard151b1b01998-09-23 00:49:46 +00003200 else xmlCompressMode = mode;
3201}
3202
Daniel Veillard97b58771998-10-20 06:14:16 +00003203/**
3204 * xmlDocDump:
3205 * @f: the FILE*
3206 * @cur: the document
3207 *
3208 * Dump an XML document to an open FILE.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003209 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003210void
3211xmlDocDump(FILE *f, xmlDocPtr cur) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003212 xmlBufferPtr buf;
3213
Daniel Veillard260a68f1998-08-13 03:39:55 +00003214 if (cur == NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003215#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00003216 fprintf(stderr, "xmlDocDump : document == NULL\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003217#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00003218 return;
3219 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003220 buf = xmlBufferCreate();
3221 if (buf == NULL) return;
3222 xmlDocContentDump(buf, cur);
3223 xmlBufferDump(f, buf);
3224 xmlBufferFree(buf);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003225}
3226
Daniel Veillard97b58771998-10-20 06:14:16 +00003227/**
3228 * xmlSaveFile:
3229 * @filename: the filename
3230 * @cur: the document
3231 *
3232 * Dump an XML document to a file. Will use compression if
3233 * compiled in and enabled.
3234 * returns: the number of file written or -1 in case of failure.
Daniel Veillard151b1b01998-09-23 00:49:46 +00003235 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003236int
3237xmlSaveFile(const char *filename, xmlDocPtr cur) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003238 xmlBufferPtr buf;
Daniel Veillard151b1b01998-09-23 00:49:46 +00003239#ifdef HAVE_ZLIB_H
3240 gzFile zoutput = NULL;
3241 char mode[15];
3242#endif
Daniel Veillardccb09631998-10-27 06:21:04 +00003243 FILE *output = NULL;
Daniel Veillard151b1b01998-09-23 00:49:46 +00003244 int ret;
3245
Daniel Veillard5099ae81999-04-21 20:12:07 +00003246 /*
3247 * save the content to a temp buffer.
3248 */
3249 buf = xmlBufferCreate();
3250 if (buf == NULL) return(0);
3251 xmlDocContentDump(buf, cur);
3252
Daniel Veillard151b1b01998-09-23 00:49:46 +00003253#ifdef HAVE_ZLIB_H
Daniel Veillarddc3dd9d1998-09-24 19:25:54 +00003254 if ((cur->compression > 0) && (cur->compression <= 9)) {
3255 sprintf(mode, "w%d", cur->compression);
Daniel Veillard151b1b01998-09-23 00:49:46 +00003256 zoutput = gzopen(filename, mode);
3257 }
3258 if (zoutput == NULL) {
3259#endif
3260 output = fopen(filename, "w");
3261 if (output == NULL) return(-1);
3262#ifdef HAVE_ZLIB_H
3263 }
Daniel Veillard151b1b01998-09-23 00:49:46 +00003264
Daniel Veillard151b1b01998-09-23 00:49:46 +00003265 if (zoutput != NULL) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003266 ret = gzwrite(zoutput, buf->content, sizeof(xmlChar) * buf->use);
Daniel Veillard151b1b01998-09-23 00:49:46 +00003267 gzclose(zoutput);
Daniel Veillard5099ae81999-04-21 20:12:07 +00003268 } else {
3269#endif
3270 ret = xmlBufferDump(output, buf);
3271 fclose(output);
3272#ifdef HAVE_ZLIB_H
Daniel Veillard151b1b01998-09-23 00:49:46 +00003273 }
3274#endif
Manish Vachharajani5e60f5a1999-05-29 03:04:30 +00003275 xmlBufferFree(buf);
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003276 return(ret * sizeof(xmlChar));
Daniel Veillard151b1b01998-09-23 00:49:46 +00003277}
3278