blob: 23819a1649474fd05d7c537925ebdf6061bd0a3c [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) {
Daniel Veillard35008381999-10-25 13:15:52 +0000687 if ((inLine) || (doc->type == XML_HTML_DOCUMENT_NODE))
Daniel Veillardccb09631998-10-27 06:21:04 +0000688 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);
Daniel Veillard51e3b151999-11-12 17:02:31 +0000756 if (value != NULL) {
757 xmlChar *buffer;
758 buffer = xmlEncodeEntitiesReentrant(node->doc, value);
759 cur->val = xmlStringGetNodeList(node->doc, buffer);
760 xmlFree(buffer);
761 }
Daniel Veillardb96e6431999-08-29 21:02:19 +0000762 else
763 cur->val = NULL;
764#ifndef XML_WITHOUT_CORBA
765 cur->_private = NULL;
766 cur->vepv = NULL;
767#endif
768
769 /*
770 * Add it at the end to preserve parsing order ...
771 */
772 cur->next = NULL;
773 if (node != NULL) {
774 if (node->properties == NULL) {
775 node->properties = cur;
776 } else {
777 xmlAttrPtr prev = node->properties;
778
779 while (prev->next != NULL) prev = prev->next;
780 prev->next = cur;
781 }
782 }
Daniel Veillard00fdf371999-10-08 09:40:39 +0000783#ifndef XML_WITHOUT_CORBA
784 cur->_private = NULL;
785 cur->vepv = NULL;
786#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +0000787 return(cur);
788}
789
790/**
791 * xmlNewNsProp:
792 * @node: the holding node
793 * @ns: the namespace
794 * @name: the name of the attribute
795 * @value: the value of the attribute
796 *
797 * Create a new property tagged with a namespace and carried by a node.
798 * Returns a pointer to the attribute
799 */
800xmlAttrPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000801xmlNewNsProp(xmlNodePtr node, xmlNsPtr ns, const xmlChar *name,
802 const xmlChar *value) {
Daniel Veillardb96e6431999-08-29 21:02:19 +0000803 xmlAttrPtr cur;
804
805 if (name == NULL) {
806 fprintf(stderr, "xmlNewProp : name == NULL\n");
807 return(NULL);
808 }
809
810 /*
811 * Allocate a new property and fill the fields.
812 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000813 cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr));
Daniel Veillardb96e6431999-08-29 21:02:19 +0000814 if (cur == NULL) {
815 fprintf(stderr, "xmlNewProp : malloc failed\n");
816 return(NULL);
817 }
818
819 cur->type = XML_ATTRIBUTE_NODE;
820 cur->node = node;
821 cur->ns = ns;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000822 cur->name = xmlStrdup(name);
823 if (value != NULL)
Daniel Veillardccb09631998-10-27 06:21:04 +0000824 cur->val = xmlStringGetNodeList(node->doc, value);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000825 else
Daniel Veillardccb09631998-10-27 06:21:04 +0000826 cur->val = NULL;
Daniel Veillard27d88741999-05-29 11:51:49 +0000827#ifndef XML_WITHOUT_CORBA
Daniel Veillard27fb0751998-10-17 06:47:46 +0000828 cur->_private = NULL;
829 cur->vepv = NULL;
830#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000831
832 /*
833 * Add it at the end to preserve parsing order ...
834 */
835 cur->next = NULL;
836 if (node != NULL) {
837 if (node->properties == NULL) {
838 node->properties = cur;
839 } else {
840 xmlAttrPtr prev = node->properties;
841
842 while (prev->next != NULL) prev = prev->next;
843 prev->next = cur;
844 }
845 }
846 return(cur);
847}
848
Daniel Veillard97b58771998-10-20 06:14:16 +0000849/**
Daniel Veillardccb09631998-10-27 06:21:04 +0000850 * xmlNewDocProp:
851 * @doc: the document
852 * @name: the name of the attribute
853 * @value: the value of the attribute
854 *
855 * Create a new property carried by a document.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000856 * Returns a pointer to the attribute
Daniel Veillardccb09631998-10-27 06:21:04 +0000857 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000858xmlAttrPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000859xmlNewDocProp(xmlDocPtr doc, const xmlChar *name, const xmlChar *value) {
Daniel Veillardccb09631998-10-27 06:21:04 +0000860 xmlAttrPtr cur;
861
862 if (name == NULL) {
863 fprintf(stderr, "xmlNewProp : name == NULL\n");
864 return(NULL);
865 }
866
867 /*
868 * Allocate a new property and fill the fields.
869 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000870 cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr));
Daniel Veillardccb09631998-10-27 06:21:04 +0000871 if (cur == NULL) {
872 fprintf(stderr, "xmlNewProp : malloc failed\n");
873 return(NULL);
874 }
875
876 cur->type = XML_ATTRIBUTE_NODE;
877 cur->node = NULL;
878 cur->name = xmlStrdup(name);
879 if (value != NULL)
880 cur->val = xmlStringGetNodeList(doc, value);
881 else
882 cur->val = NULL;
Daniel Veillard27d88741999-05-29 11:51:49 +0000883#ifndef XML_WITHOUT_CORBA
Daniel Veillardccb09631998-10-27 06:21:04 +0000884 cur->_private = NULL;
885 cur->vepv = NULL;
886#endif
887
888 cur->next = NULL;
889 return(cur);
890}
891
892/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000893 * xmlFreePropList:
894 * @cur: the first property in the list
895 *
896 * Free a property and all its siblings, all the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000897 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000898void
899xmlFreePropList(xmlAttrPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000900 xmlAttrPtr next;
901 if (cur == NULL) {
902 fprintf(stderr, "xmlFreePropList : property == NULL\n");
903 return;
904 }
905 while (cur != NULL) {
906 next = cur->next;
907 xmlFreeProp(cur);
908 cur = next;
909 }
910}
911
Daniel Veillard97b58771998-10-20 06:14:16 +0000912/**
913 * xmlFreeProp:
914 * @cur: the first property in the list
915 *
916 * Free one property, all the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000917 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000918void
919xmlFreeProp(xmlAttrPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000920 if (cur == NULL) {
921 fprintf(stderr, "xmlFreeProp : property == NULL\n");
922 return;
923 }
Daniel Veillard6454aec1999-09-02 22:04:43 +0000924 if (cur->name != NULL) xmlFree((char *) cur->name);
Daniel Veillardccb09631998-10-27 06:21:04 +0000925 if (cur->val != NULL) xmlFreeNodeList(cur->val);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000926 memset(cur, -1, sizeof(xmlAttr));
Daniel Veillard6454aec1999-09-02 22:04:43 +0000927 xmlFree(cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000928}
929
Daniel Veillard97b58771998-10-20 06:14:16 +0000930/**
Daniel Veillardb96e6431999-08-29 21:02:19 +0000931 * xmlNewPI:
932 * @name: the processing instruction name
933 * @content: the PI content
934 *
935 * Creation of a processing instruction element.
936 * Returns a pointer to the new node object.
937 */
938xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000939xmlNewPI(const xmlChar *name, const xmlChar *content) {
Daniel Veillardb96e6431999-08-29 21:02:19 +0000940 xmlNodePtr cur;
941
942 if (name == NULL) {
943 fprintf(stderr, "xmlNewPI : name == NULL\n");
944 return(NULL);
945 }
946
947 /*
948 * Allocate a new node and fill the fields.
949 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000950 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillardb96e6431999-08-29 21:02:19 +0000951 if (cur == NULL) {
952 fprintf(stderr, "xmlNewPI : malloc failed\n");
953 return(NULL);
954 }
955
956 cur->type = XML_PI_NODE;
957 cur->doc = NULL;
958 cur->parent = NULL;
959 cur->next = NULL;
960 cur->prev = NULL;
961 cur->childs = NULL;
962 cur->last = NULL;
963 cur->properties = NULL;
964 cur->name = xmlStrdup(name);
965 cur->ns = NULL;
966 cur->nsDef = NULL;
967 if (content != NULL)
968 cur->content = xmlStrdup(content);
969 else
970 cur->content = NULL;
971#ifndef XML_WITHOUT_CORBA
972 cur->_private = NULL;
973 cur->vepv = NULL;
974#endif
975 return(cur);
976}
977
978/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000979 * xmlNewNode:
980 * @ns: namespace if any
981 * @name: the node name
Daniel Veillard97b58771998-10-20 06:14:16 +0000982 *
983 * Creation of a new node element. @ns and @content are optionnal (NULL).
Daniel Veillardccb09631998-10-27 06:21:04 +0000984 * If content is non NULL, a child list containing the TEXTs and
985 * ENTITY_REFs node will be created.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000986 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000987 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000988xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000989xmlNewNode(xmlNsPtr ns, const xmlChar *name) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000990 xmlNodePtr cur;
991
992 if (name == NULL) {
993 fprintf(stderr, "xmlNewNode : name == NULL\n");
994 return(NULL);
995 }
996
997 /*
998 * Allocate a new node and fill the fields.
999 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001000 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillard260a68f1998-08-13 03:39:55 +00001001 if (cur == NULL) {
1002 fprintf(stderr, "xmlNewNode : malloc failed\n");
1003 return(NULL);
1004 }
1005
Daniel Veillard33942841998-10-18 19:12:41 +00001006 cur->type = XML_ELEMENT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001007 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001008 cur->parent = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001009 cur->next = NULL;
1010 cur->prev = NULL;
1011 cur->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001012 cur->last = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001013 cur->properties = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001014 cur->name = xmlStrdup(name);
1015 cur->ns = ns;
1016 cur->nsDef = NULL;
Daniel Veillardccb09631998-10-27 06:21:04 +00001017 cur->content = NULL;
Daniel Veillard27d88741999-05-29 11:51:49 +00001018#ifndef XML_WITHOUT_CORBA
Daniel Veillard27fb0751998-10-17 06:47:46 +00001019 cur->_private = NULL;
1020 cur->vepv = NULL;
1021#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001022 return(cur);
1023}
1024
Daniel Veillard97b58771998-10-20 06:14:16 +00001025/**
1026 * xmlNewDocNode:
1027 * @doc: the document
1028 * @ns: namespace if any
1029 * @name: the node name
1030 * @content: the text content if any
1031 *
1032 * Creation of a new node element within a document. @ns and @content
1033 * are optionnal (NULL).
Daniel Veillard1e346af1999-02-22 10:33:01 +00001034 * Returns a pointer to the new node object.
Daniel Veillard97b58771998-10-20 06:14:16 +00001035 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001036xmlNodePtr
1037xmlNewDocNode(xmlDocPtr doc, xmlNsPtr ns,
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001038 const xmlChar *name, const xmlChar *content) {
Daniel Veillard0bef1311998-10-14 02:36:47 +00001039 xmlNodePtr cur;
1040
Daniel Veillardccb09631998-10-27 06:21:04 +00001041 cur = xmlNewNode(ns, name);
1042 if (cur != NULL) {
1043 cur->doc = doc;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001044 if (content != NULL) {
Daniel Veillardccb09631998-10-27 06:21:04 +00001045 cur->childs = xmlStringGetNodeList(doc, content);
Daniel Veillard1e346af1999-02-22 10:33:01 +00001046 UPDATE_LAST_CHILD(cur)
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001047 }
Daniel Veillardccb09631998-10-27 06:21:04 +00001048 }
Daniel Veillard0bef1311998-10-14 02:36:47 +00001049 return(cur);
1050}
1051
1052
Daniel Veillard97b58771998-10-20 06:14:16 +00001053/**
1054 * xmlNewText:
1055 * @content: the text content
1056 *
1057 * Creation of a new text node.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001058 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001059 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001060xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001061xmlNewText(const xmlChar *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001062 xmlNodePtr cur;
1063
1064 /*
1065 * Allocate a new node and fill the fields.
1066 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001067 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillard260a68f1998-08-13 03:39:55 +00001068 if (cur == NULL) {
1069 fprintf(stderr, "xmlNewText : malloc failed\n");
1070 return(NULL);
1071 }
1072
Daniel Veillard33942841998-10-18 19:12:41 +00001073 cur->type = XML_TEXT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001074 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001075 cur->parent = NULL;
1076 cur->next = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001077 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001078 cur->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001079 cur->last = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001080 cur->properties = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001081 cur->type = XML_TEXT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001082 cur->name = xmlStrdup(xmlStringText);
1083 cur->ns = NULL;
1084 cur->nsDef = NULL;
1085 if (content != NULL)
1086 cur->content = xmlStrdup(content);
1087 else
1088 cur->content = NULL;
Daniel Veillard00fdf371999-10-08 09:40:39 +00001089#ifndef XML_WITHOUT_CORBA
1090 cur->_private = NULL;
1091 cur->vepv = NULL;
1092#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001093 return(cur);
1094}
1095
Daniel Veillard97b58771998-10-20 06:14:16 +00001096/**
Daniel Veillardccb09631998-10-27 06:21:04 +00001097 * xmlNewReference:
1098 * @doc: the document
1099 * @name: the reference name, or the reference string with & and ;
1100 *
1101 * Creation of a new reference node.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001102 * Returns a pointer to the new node object.
Daniel Veillardccb09631998-10-27 06:21:04 +00001103 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001104xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001105xmlNewReference(xmlDocPtr doc, const xmlChar *name) {
Daniel Veillardccb09631998-10-27 06:21:04 +00001106 xmlNodePtr cur;
1107 xmlEntityPtr ent;
1108
1109 /*
1110 * Allocate a new node and fill the fields.
1111 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001112 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillardccb09631998-10-27 06:21:04 +00001113 if (cur == NULL) {
1114 fprintf(stderr, "xmlNewText : malloc failed\n");
1115 return(NULL);
1116 }
1117
1118 cur->type = XML_ENTITY_REF_NODE;
Daniel Veillard10c6a8f1998-10-28 01:00:12 +00001119 cur->doc = doc;
Daniel Veillardccb09631998-10-27 06:21:04 +00001120 cur->parent = NULL;
1121 cur->next = NULL;
1122 cur->prev = NULL;
1123 cur->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001124 cur->last = NULL;
Daniel Veillardccb09631998-10-27 06:21:04 +00001125 cur->properties = NULL;
1126 if (name[0] == '&') {
1127 int len;
1128 name++;
1129 len = xmlStrlen(name);
1130 if (name[len - 1] == ';')
1131 cur->name = xmlStrndup(name, len - 1);
1132 else
1133 cur->name = xmlStrndup(name, len);
1134 } else
1135 cur->name = xmlStrdup(name);
1136 cur->ns = NULL;
1137 cur->nsDef = NULL;
1138
1139 ent = xmlGetDocEntity(doc, cur->name);
1140 if (ent != NULL)
1141 cur->content = ent->content;
1142 else
1143 cur->content = NULL;
Daniel Veillard00fdf371999-10-08 09:40:39 +00001144#ifndef XML_WITHOUT_CORBA
1145 cur->_private = NULL;
1146 cur->vepv = NULL;
1147#endif
Daniel Veillardccb09631998-10-27 06:21:04 +00001148 return(cur);
1149}
1150
1151/**
Daniel Veillard97b58771998-10-20 06:14:16 +00001152 * xmlNewDocText:
1153 * @doc: the document
1154 * @content: the text content
1155 *
1156 * Creation of a new text node within a document.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001157 * Returns a pointer to the new node object.
Daniel Veillard97b58771998-10-20 06:14:16 +00001158 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001159xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001160xmlNewDocText(xmlDocPtr doc, const xmlChar *content) {
Daniel Veillard0bef1311998-10-14 02:36:47 +00001161 xmlNodePtr cur;
1162
1163 cur = xmlNewText(content);
1164 if (cur != NULL) cur->doc = doc;
1165 return(cur);
1166}
1167
Daniel Veillard97b58771998-10-20 06:14:16 +00001168/**
Daniel Veillardccb09631998-10-27 06:21:04 +00001169 * xmlNewTextLen:
Daniel Veillard97b58771998-10-20 06:14:16 +00001170 * @content: the text content
1171 * @len: the text len.
1172 *
1173 * Creation of a new text node with an extra parameter for the content's lenght
Daniel Veillard1e346af1999-02-22 10:33:01 +00001174 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001175 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001176xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001177xmlNewTextLen(const xmlChar *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001178 xmlNodePtr cur;
1179
1180 /*
1181 * Allocate a new node and fill the fields.
1182 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001183 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillard260a68f1998-08-13 03:39:55 +00001184 if (cur == NULL) {
1185 fprintf(stderr, "xmlNewText : malloc failed\n");
1186 return(NULL);
1187 }
1188
Daniel Veillard33942841998-10-18 19:12:41 +00001189 cur->type = XML_TEXT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001190 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001191 cur->parent = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001192 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001193 cur->next = NULL;
1194 cur->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001195 cur->last = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001196 cur->properties = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001197 cur->type = XML_TEXT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001198 cur->name = xmlStrdup(xmlStringText);
1199 cur->ns = NULL;
1200 cur->nsDef = NULL;
1201 if (content != NULL)
1202 cur->content = xmlStrndup(content, len);
1203 else
1204 cur->content = NULL;
Daniel Veillard00fdf371999-10-08 09:40:39 +00001205#ifndef XML_WITHOUT_CORBA
1206 cur->_private = NULL;
1207 cur->vepv = NULL;
1208#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001209 return(cur);
1210}
1211
Daniel Veillard97b58771998-10-20 06:14:16 +00001212/**
1213 * xmlNewDocTextLen:
1214 * @doc: the document
1215 * @content: the text content
1216 * @len: the text len.
1217 *
1218 * Creation of a new text node with an extra content lenght parameter. The
1219 * text node pertain to a given document.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001220 * Returns a pointer to the new node object.
Daniel Veillard97b58771998-10-20 06:14:16 +00001221 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001222xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001223xmlNewDocTextLen(xmlDocPtr doc, const xmlChar *content, int len) {
Daniel Veillard0bef1311998-10-14 02:36:47 +00001224 xmlNodePtr cur;
1225
1226 cur = xmlNewTextLen(content, len);
1227 if (cur != NULL) cur->doc = doc;
1228 return(cur);
1229}
1230
Daniel Veillard97b58771998-10-20 06:14:16 +00001231/**
1232 * xmlNewComment:
1233 * @content: the comment content
1234 *
1235 * Creation of a new node containing a comment.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001236 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001237 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001238xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001239xmlNewComment(const xmlChar *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001240 xmlNodePtr cur;
1241
1242 /*
1243 * Allocate a new node and fill the fields.
1244 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001245 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillard260a68f1998-08-13 03:39:55 +00001246 if (cur == NULL) {
1247 fprintf(stderr, "xmlNewComment : malloc failed\n");
1248 return(NULL);
1249 }
1250
Daniel Veillard33942841998-10-18 19:12:41 +00001251 cur->type = XML_COMMENT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001252 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001253 cur->parent = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001254 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001255 cur->next = NULL;
1256 cur->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001257 cur->last = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001258 cur->properties = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001259 cur->type = XML_COMMENT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001260 cur->name = xmlStrdup(xmlStringText);
1261 cur->ns = NULL;
1262 cur->nsDef = NULL;
1263 if (content != NULL)
1264 cur->content = xmlStrdup(content);
1265 else
1266 cur->content = NULL;
Daniel Veillard00fdf371999-10-08 09:40:39 +00001267#ifndef XML_WITHOUT_CORBA
1268 cur->_private = NULL;
1269 cur->vepv = NULL;
1270#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001271 return(cur);
1272}
1273
Daniel Veillard97b58771998-10-20 06:14:16 +00001274/**
Daniel Veillardb05deb71999-08-10 19:04:08 +00001275 * xmlNewCDataBlock:
1276 * @doc: the document
1277 * @content: the CData block content content
1278 * @len: the length of the block
1279 *
1280 * Creation of a new node containing a CData block.
1281 * Returns a pointer to the new node object.
1282 */
1283xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001284xmlNewCDataBlock(xmlDocPtr doc, const xmlChar *content, int len) {
Daniel Veillardb05deb71999-08-10 19:04:08 +00001285 xmlNodePtr cur;
1286
1287 /*
1288 * Allocate a new node and fill the fields.
1289 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001290 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillardb05deb71999-08-10 19:04:08 +00001291 if (cur == NULL) {
1292 fprintf(stderr, "xmlNewCDataBlock : malloc failed\n");
1293 return(NULL);
1294 }
1295
1296 cur->type = XML_CDATA_SECTION_NODE;
1297 cur->doc = NULL;
1298 cur->parent = NULL;
1299 cur->prev = NULL;
1300 cur->next = NULL;
1301 cur->childs = NULL;
1302 cur->last = NULL;
1303 cur->properties = NULL;
1304 cur->name = xmlStrdup(xmlStringText);
1305 cur->ns = NULL;
1306 cur->nsDef = NULL;
1307 if ((content != NULL) && (len > 0)) {
1308 cur->content = xmlStrndup(content, len);
1309 } else
1310 cur->content = NULL;
Daniel Veillard00fdf371999-10-08 09:40:39 +00001311#ifndef XML_WITHOUT_CORBA
1312 cur->_private = NULL;
1313 cur->vepv = NULL;
1314#endif
Daniel Veillardb05deb71999-08-10 19:04:08 +00001315 return(cur);
1316}
1317
1318/**
Daniel Veillard1e346af1999-02-22 10:33:01 +00001319 * xmlNewDocComment:
Daniel Veillard97b58771998-10-20 06:14:16 +00001320 * @doc: the document
1321 * @content: the comment content
1322 *
1323 * Creation of a new node containing a commentwithin a document.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001324 * Returns a pointer to the new node object.
Daniel Veillard97b58771998-10-20 06:14:16 +00001325 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001326xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001327xmlNewDocComment(xmlDocPtr doc, const xmlChar *content) {
Daniel Veillard0bef1311998-10-14 02:36:47 +00001328 xmlNodePtr cur;
1329
1330 cur = xmlNewComment(content);
1331 if (cur != NULL) cur->doc = doc;
1332 return(cur);
1333}
1334
Daniel Veillard97b58771998-10-20 06:14:16 +00001335/**
1336 * xmlNewChild:
1337 * @parent: the parent node
1338 * @ns: a namespace if any
1339 * @name: the name of the child
1340 * @content: the content of the child if any.
1341 *
1342 *
1343 * Creation of a new child element, added at the end of @parent childs list.
Daniel Veillardccb09631998-10-27 06:21:04 +00001344 * @ns and @content parameters are optionnal (NULL). If content is non NULL,
1345 * a child list containing the TEXTs and ENTITY_REFs node will be created.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001346 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001347 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001348xmlNodePtr
1349xmlNewChild(xmlNodePtr parent, xmlNsPtr ns,
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001350 const xmlChar *name, const xmlChar *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001351 xmlNodePtr cur, prev;
1352
1353 if (parent == NULL) {
1354 fprintf(stderr, "xmlNewChild : parent == NULL\n");
1355 return(NULL);
1356 }
1357
1358 if (name == NULL) {
1359 fprintf(stderr, "xmlNewChild : name == NULL\n");
1360 return(NULL);
1361 }
1362
1363 /*
1364 * Allocate a new node
1365 */
1366 if (ns == NULL)
Daniel Veillardccb09631998-10-27 06:21:04 +00001367 cur = xmlNewDocNode(parent->doc, parent->ns, name, content);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001368 else
Daniel Veillardccb09631998-10-27 06:21:04 +00001369 cur = xmlNewDocNode(parent->doc, ns, name, content);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001370 if (cur == NULL) return(NULL);
1371
1372 /*
1373 * add the new element at the end of the childs list.
1374 */
Daniel Veillardccb09631998-10-27 06:21:04 +00001375 cur->type = XML_ELEMENT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001376 cur->parent = parent;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001377 cur->doc = parent->doc;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001378 if (parent->childs == NULL) {
1379 parent->childs = cur;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001380 parent->last = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001381 } else {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001382 prev = parent->last;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001383 prev->next = cur;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001384 cur->prev = prev;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001385 parent->last = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001386 }
1387
1388 return(cur);
1389}
1390
Daniel Veillard97b58771998-10-20 06:14:16 +00001391/**
Daniel Veillardb96e6431999-08-29 21:02:19 +00001392 * xmlAddSibling:
1393 * @cur: the child node
1394 * @elem: the new node
1395 *
1396 * Add a new element to the list of siblings of @cur
1397 * Returns the element or NULL in case of error.
1398 */
1399xmlNodePtr
1400xmlAddSibling(xmlNodePtr cur, xmlNodePtr elem) {
1401 xmlNodePtr parent;
1402
1403 if (cur == NULL) {
1404 fprintf(stderr, "xmlAddSibling : cur == NULL\n");
1405 return(NULL);
1406 }
1407
1408 if (elem == NULL) {
1409 fprintf(stderr, "xmlAddSibling : elem == NULL\n");
1410 return(NULL);
1411 }
1412
1413 if ((cur->doc != NULL) && (elem->doc != NULL) &&
1414 (cur->doc != elem->doc)) {
1415 fprintf(stderr,
1416 "xmlAddSibling: Elements moved to a different document\n");
1417 }
1418
1419 while (cur->next != NULL) cur = cur->next;
1420
1421 if (elem->doc == NULL)
1422 elem->doc = cur->doc; /* the parent may not be linked to a doc ! */
1423
1424 parent = cur->parent;
1425 elem->prev = cur;
1426 elem->next = NULL;
1427 elem->parent = parent;
1428 cur->next = elem;
1429 if (parent != NULL)
1430 parent->last = elem;
1431
1432 return(elem);
1433}
1434
1435/**
Daniel Veillard97b58771998-10-20 06:14:16 +00001436 * xmlAddChild:
1437 * @parent: the parent node
1438 * @cur: the child node
1439 *
1440 * Add a new child element, to @parent, at the end of the child list.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001441 * Returns the child or NULL in case of error.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001442 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001443xmlNodePtr
1444xmlAddChild(xmlNodePtr parent, xmlNodePtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001445 xmlNodePtr prev;
1446
1447 if (parent == NULL) {
1448 fprintf(stderr, "xmladdChild : parent == NULL\n");
1449 return(NULL);
1450 }
1451
1452 if (cur == NULL) {
1453 fprintf(stderr, "xmladdChild : child == NULL\n");
1454 return(NULL);
1455 }
1456
Daniel Veillard0bef1311998-10-14 02:36:47 +00001457 if ((cur->doc != NULL) && (parent->doc != NULL) &&
1458 (cur->doc != parent->doc)) {
1459 fprintf(stderr, "Elements moved to a different document\n");
1460 }
1461
Daniel Veillard260a68f1998-08-13 03:39:55 +00001462 /*
1463 * add the new element at the end of the childs list.
1464 */
1465 cur->parent = parent;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001466 cur->doc = parent->doc; /* the parent may not be linked to a doc ! */
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001467
Daniel Veillardccb09631998-10-27 06:21:04 +00001468 /*
1469 * Handle the case where parent->content != NULL, in that case it will
1470 * create a intermediate TEXT node.
1471 */
1472 if (parent->content != NULL) {
1473 xmlNodePtr text;
1474
1475 text = xmlNewDocText(parent->doc, parent->content);
1476 if (text != NULL) {
1477 text->next = parent->childs;
1478 if (text->next != NULL)
1479 text->next->prev = text;
1480 parent->childs = text;
Daniel Veillard1e346af1999-02-22 10:33:01 +00001481 UPDATE_LAST_CHILD(parent)
Daniel Veillard6454aec1999-09-02 22:04:43 +00001482 xmlFree(parent->content);
Daniel Veillardccb09631998-10-27 06:21:04 +00001483 parent->content = NULL;
1484 }
1485 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00001486 if (parent->childs == NULL) {
1487 parent->childs = cur;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001488 parent->last = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001489 } else {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001490 prev = parent->last;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001491 prev->next = cur;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001492 cur->prev = prev;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001493 parent->last = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001494 }
1495
1496 return(cur);
1497}
1498
Daniel Veillard97b58771998-10-20 06:14:16 +00001499/**
1500 * xmlGetLastChild:
1501 * @parent: the parent node
1502 *
1503 * Search the last child of a node.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001504 * Returns the last child or NULL if none.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001505 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001506xmlNodePtr
1507xmlGetLastChild(xmlNodePtr parent) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001508 if (parent == NULL) {
1509 fprintf(stderr, "xmlGetLastChild : parent == NULL\n");
1510 return(NULL);
1511 }
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001512 return(parent->last);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001513}
1514
Daniel Veillard97b58771998-10-20 06:14:16 +00001515/**
1516 * xmlFreeNodeList:
1517 * @cur: the first node in the list
1518 *
1519 * Free a node and all its siblings, this is a recursive behaviour, all
1520 * the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001521 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001522void
1523xmlFreeNodeList(xmlNodePtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001524 xmlNodePtr next;
1525 if (cur == NULL) {
1526 fprintf(stderr, "xmlFreeNodeList : node == NULL\n");
1527 return;
1528 }
1529 while (cur != NULL) {
1530 next = cur->next;
1531 xmlFreeNode(cur);
1532 cur = next;
1533 }
1534}
1535
Daniel Veillard97b58771998-10-20 06:14:16 +00001536/**
1537 * xmlFreeNode:
1538 * @cur: the node
1539 *
1540 * Free a node, this is a recursive behaviour, all the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001541 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001542void
1543xmlFreeNode(xmlNodePtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001544 if (cur == NULL) {
1545 fprintf(stderr, "xmlFreeNode : node == NULL\n");
1546 return;
1547 }
Daniel Veillardccb09631998-10-27 06:21:04 +00001548 cur->doc = NULL;
1549 cur->parent = NULL;
1550 cur->next = NULL;
1551 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001552 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillardccb09631998-10-27 06:21:04 +00001553 if (cur->properties != NULL) xmlFreePropList(cur->properties);
1554 if (cur->type != XML_ENTITY_REF_NODE)
Daniel Veillard6454aec1999-09-02 22:04:43 +00001555 if (cur->content != NULL) xmlFree(cur->content);
1556 if (cur->name != NULL) xmlFree((char *) cur->name);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001557 if (cur->nsDef != NULL) xmlFreeNsList(cur->nsDef);
1558 memset(cur, -1, sizeof(xmlNode));
Daniel Veillard6454aec1999-09-02 22:04:43 +00001559 xmlFree(cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001560}
1561
Daniel Veillard16253641998-10-28 22:58:05 +00001562/**
1563 * xmlUnlinkNode:
1564 * @cur: the node
1565 *
1566 * Unlink a node from it's current context, the node is not freed
1567 */
1568void
1569xmlUnlinkNode(xmlNodePtr cur) {
1570 if (cur == NULL) {
1571 fprintf(stderr, "xmlUnlinkNode : node == NULL\n");
1572 return;
1573 }
1574 if ((cur->parent != NULL) && (cur->parent->childs == cur))
1575 cur->parent->childs = cur->next;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001576 if ((cur->parent != NULL) && (cur->parent->last == cur))
1577 cur->parent->last = cur->prev;
Daniel Veillard16253641998-10-28 22:58:05 +00001578 if (cur->next != NULL)
1579 cur->next->prev = cur->prev;
1580 if (cur->prev != NULL)
1581 cur->prev->next = cur->next;
1582 cur->next = cur->prev = NULL;
1583 cur->parent = NULL;
1584}
1585
Daniel Veillard260a68f1998-08-13 03:39:55 +00001586/************************************************************************
1587 * *
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001588 * Copy operations *
1589 * *
1590 ************************************************************************/
1591
1592/**
1593 * xmlCopyNamespace:
1594 * @cur: the namespace
1595 *
1596 * Do a copy of the namespace.
1597 *
1598 * Returns: a new xmlNsPtr, or NULL in case of error.
1599 */
1600xmlNsPtr
1601xmlCopyNamespace(xmlNsPtr cur) {
1602 xmlNsPtr ret;
1603
1604 if (cur == NULL) return(NULL);
1605 switch (cur->type) {
1606 case XML_GLOBAL_NAMESPACE:
1607 ret = xmlNewGlobalNs(NULL, cur->href, cur->prefix);
1608 break;
1609 case XML_LOCAL_NAMESPACE:
1610 ret = xmlNewNs(NULL, cur->href, cur->prefix);
1611 break;
1612 default:
1613 fprintf(stderr, "xmlCopyNamespace: unknown type %d\n", cur->type);
1614 return(NULL);
1615 }
1616 return(ret);
1617}
1618
1619/**
1620 * xmlCopyNamespaceList:
1621 * @cur: the first namespace
1622 *
1623 * Do a copy of an namespace list.
1624 *
1625 * Returns: a new xmlNsPtr, or NULL in case of error.
1626 */
1627xmlNsPtr
1628xmlCopyNamespaceList(xmlNsPtr cur) {
1629 xmlNsPtr ret = NULL;
1630 xmlNsPtr p = NULL,q;
1631
1632 while (cur != NULL) {
1633 q = xmlCopyNamespace(cur);
1634 if (p == NULL) {
1635 ret = p = q;
1636 } else {
1637 p->next = q;
1638 p = q;
1639 }
1640 cur = cur->next;
1641 }
1642 return(ret);
1643}
1644
1645/**
1646 * xmlCopyProp:
Daniel Veillardb96e6431999-08-29 21:02:19 +00001647 * @target: the element where the attribute will be grafted
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001648 * @cur: the attribute
1649 *
1650 * Do a copy of the attribute.
1651 *
1652 * Returns: a new xmlAttrPtr, or NULL in case of error.
1653 */
1654xmlAttrPtr
Daniel Veillardb96e6431999-08-29 21:02:19 +00001655xmlCopyProp(xmlNodePtr target, xmlAttrPtr cur) {
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001656 xmlAttrPtr ret;
1657
1658 if (cur == NULL) return(NULL);
1659 if (cur->val != NULL)
1660 ret = xmlNewDocProp(cur->val->doc, cur->name, NULL);
1661 else
1662 ret = xmlNewDocProp(NULL, cur->name, NULL);
1663 if (ret == NULL) return(NULL);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001664
1665 if ((cur->ns != NULL) && (target != NULL)) {
1666 xmlNsPtr ns;
1667
1668 ns = xmlSearchNs(target->doc, target, cur->ns->prefix);
1669 ret->ns = ns;
1670 } else
1671 ret->ns = NULL;
1672
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001673 if (cur->val != NULL)
1674 ret->val = xmlCopyNodeList(cur->val);
1675 return(ret);
1676}
1677
1678/**
1679 * xmlCopyPropList:
Daniel Veillardb96e6431999-08-29 21:02:19 +00001680 * @target: the element where the attributes will be grafted
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001681 * @cur: the first attribute
1682 *
1683 * Do a copy of an attribute list.
1684 *
1685 * Returns: a new xmlAttrPtr, or NULL in case of error.
1686 */
1687xmlAttrPtr
Daniel Veillardb96e6431999-08-29 21:02:19 +00001688xmlCopyPropList(xmlNodePtr target, xmlAttrPtr cur) {
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001689 xmlAttrPtr ret = NULL;
1690 xmlAttrPtr p = NULL,q;
1691
1692 while (cur != NULL) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00001693 q = xmlCopyProp(target, cur);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001694 if (p == NULL) {
1695 ret = p = q;
1696 } else {
1697 p->next = q;
1698 p = q;
1699 }
1700 cur = cur->next;
1701 }
1702 return(ret);
1703}
1704
1705/*
1706 * NOTE about the CopyNode operations !
1707 *
1708 * They are splitted into external and internal parts for one
1709 * tricky reason: namespaces. Doing a direct copy of a node
1710 * say RPM:Copyright without changing the namespace pointer to
1711 * something else can produce stale links. One way to do it is
1712 * to keep a reference counter but this doesn't work as soon
1713 * as one move the element or the subtree out of the scope of
1714 * the existing namespace. The actual solution seems to add
1715 * a copy of the namespace at the top of the copied tree if
1716 * not available in the subtree.
1717 * Hence two functions, the public front-end call the inner ones
1718 */
1719
1720static xmlNodePtr
1721xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent);
1722
1723static xmlNodePtr
1724xmlStaticCopyNode(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent,
1725 int recursive) {
1726 xmlNodePtr ret;
1727
1728 if (node == NULL) return(NULL);
1729 /*
1730 * Allocate a new node and fill the fields.
1731 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001732 ret = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001733 if (ret == NULL) {
1734 fprintf(stderr, "xmlStaticCopyNode : malloc failed\n");
1735 return(NULL);
1736 }
1737
1738 ret->type = node->type;
1739 ret->doc = doc;
1740 ret->parent = parent;
1741 ret->next = NULL;
1742 ret->prev = NULL;
1743 ret->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001744 ret->last = NULL;
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001745 ret->properties = NULL;
1746 if (node->name != NULL)
1747 ret->name = xmlStrdup(node->name);
1748 else
1749 ret->name = NULL;
1750 ret->ns = NULL;
1751 ret->nsDef = NULL;
1752 if ((node->content != NULL) && (node->type != XML_ENTITY_REF_NODE))
1753 ret->content = xmlStrdup(node->content);
1754 else
1755 ret->content = NULL;
Daniel Veillard27d88741999-05-29 11:51:49 +00001756#ifndef XML_WITHOUT_CORBA
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001757 ret->_private = NULL;
1758 ret->vepv = NULL;
1759#endif
1760 if (parent != NULL)
1761 xmlAddChild(parent, ret);
1762
1763 if (!recursive) return(ret);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001764 if (node->nsDef != NULL)
1765 ret->nsDef = xmlCopyNamespaceList(node->nsDef);
1766
1767 if (node->ns != NULL) {
1768 xmlNsPtr ns;
1769
1770 ns = xmlSearchNs(doc, ret, node->ns->prefix);
1771 if (ns == NULL) {
1772 /*
1773 * Humm, we are copying an element whose namespace is defined
1774 * out of the new tree scope. Search it in the original tree
1775 * and add it at the top of the new tree
1776 */
1777 ns = xmlSearchNs(node->doc, node, node->ns->prefix);
1778 if (ns != NULL) {
1779 xmlNodePtr root = ret;
1780
1781 while (root->parent != NULL) root = root->parent;
1782 xmlNewNs(root, ns->href, ns->prefix);
1783 }
1784 } else {
1785 /*
1786 * reference the existing namespace definition in our own tree.
1787 */
1788 ret->ns = ns;
1789 }
1790 }
Daniel Veillardb96e6431999-08-29 21:02:19 +00001791 if (node->properties != NULL)
1792 ret->properties = xmlCopyPropList(ret, node->properties);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001793 if (node->childs != NULL)
1794 ret->childs = xmlStaticCopyNodeList(node->childs, doc, ret);
Daniel Veillard1e346af1999-02-22 10:33:01 +00001795 UPDATE_LAST_CHILD(ret)
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001796 return(ret);
1797}
1798
1799static xmlNodePtr
1800xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent) {
1801 xmlNodePtr ret = NULL;
1802 xmlNodePtr p = NULL,q;
1803
1804 while (node != NULL) {
1805 q = xmlStaticCopyNode(node, doc, parent, 1);
1806 if (parent == NULL) {
1807 if (ret == NULL) ret = q;
1808 } else {
1809 if (ret == NULL) {
1810 q->prev = NULL;
1811 ret = p = q;
1812 } else {
1813 p->next = q;
1814 q->prev = p;
1815 p = q;
1816 }
1817 }
1818 node = node->next;
1819 }
1820 return(ret);
1821}
1822
1823/**
1824 * xmlCopyNode:
1825 * @node: the node
1826 * @recursive: if 1 do a recursive copy.
1827 *
1828 * Do a copy of the node.
1829 *
1830 * Returns: a new xmlNodePtr, or NULL in case of error.
1831 */
1832xmlNodePtr
1833xmlCopyNode(xmlNodePtr node, int recursive) {
1834 xmlNodePtr ret;
1835
1836 ret = xmlStaticCopyNode(node, NULL, NULL, recursive);
1837 return(ret);
1838}
1839
1840/**
1841 * xmlCopyNodeList:
1842 * @node: the first node in the list.
1843 *
1844 * Do a recursive copy of the node list.
1845 *
1846 * Returns: a new xmlNodePtr, or NULL in case of error.
1847 */
1848xmlNodePtr xmlCopyNodeList(xmlNodePtr node) {
1849 xmlNodePtr ret = xmlStaticCopyNodeList(node, NULL, NULL);
1850 return(ret);
1851}
1852
1853/**
1854 * xmlCopyElement:
1855 * @elem: the element
1856 *
1857 * Do a copy of the element definition.
1858 *
1859 * Returns: a new xmlElementPtr, or NULL in case of error.
1860xmlElementPtr
1861xmlCopyElement(xmlElementPtr elem) {
1862 xmlElementPtr ret;
1863
1864 if (elem == NULL) return(NULL);
1865 ret = xmlNewDocElement(elem->doc, elem->ns, elem->name, elem->content);
1866 if (ret == NULL) return(NULL);
1867 if (!recursive) return(ret);
1868 if (elem->properties != NULL)
1869 ret->properties = xmlCopyPropList(elem->properties);
1870
1871 if (elem->nsDef != NULL)
1872 ret->nsDef = xmlCopyNamespaceList(elem->nsDef);
1873 if (elem->childs != NULL)
1874 ret->childs = xmlCopyElementList(elem->childs);
1875 return(ret);
1876}
1877 */
1878
1879/**
1880 * xmlCopyDtd:
1881 * @dtd: the dtd
1882 *
1883 * Do a copy of the dtd.
1884 *
1885 * Returns: a new xmlDtdPtr, or NULL in case of error.
1886 */
1887xmlDtdPtr
1888xmlCopyDtd(xmlDtdPtr dtd) {
1889 xmlDtdPtr ret;
1890
1891 if (dtd == NULL) return(NULL);
1892 ret = xmlNewDtd(NULL, dtd->name, dtd->ExternalID, dtd->SystemID);
1893 if (ret == NULL) return(NULL);
1894 if (dtd->entities != NULL)
1895 ret->entities = (void *) xmlCopyEntitiesTable(
1896 (xmlEntitiesTablePtr) dtd->entities);
Daniel Veillard1e346af1999-02-22 10:33:01 +00001897 if (dtd->notations != NULL)
1898 ret->notations = (void *) xmlCopyNotationTable(
1899 (xmlNotationTablePtr) dtd->notations);
1900 if (dtd->elements != NULL)
1901 ret->elements = (void *) xmlCopyElementTable(
1902 (xmlElementTablePtr) dtd->elements);
1903 if (dtd->attributes != NULL)
1904 ret->attributes = (void *) xmlCopyAttributeTable(
1905 (xmlAttributeTablePtr) dtd->attributes);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001906 return(ret);
1907}
1908
1909/**
1910 * xmlCopyDoc:
1911 * @doc: the document
1912 * @recursive: if 1 do a recursive copy.
1913 *
1914 * Do a copy of the document info. If recursive, the content tree will
1915 * be copied too as well as Dtd, namespaces and entities.
1916 *
1917 * Returns: a new xmlDocPtr, or NULL in case of error.
1918 */
1919xmlDocPtr
1920xmlCopyDoc(xmlDocPtr doc, int recursive) {
1921 xmlDocPtr ret;
1922
1923 if (doc == NULL) return(NULL);
1924 ret = xmlNewDoc(doc->version);
1925 if (ret == NULL) return(NULL);
1926 if (doc->name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +00001927 ret->name = xmlMemStrdup(doc->name);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001928 if (doc->encoding != NULL)
1929 ret->encoding = xmlStrdup(doc->encoding);
1930 ret->compression = doc->compression;
1931 ret->standalone = doc->standalone;
1932 if (!recursive) return(ret);
1933
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001934 if (doc->intSubset != NULL)
1935 ret->intSubset = xmlCopyDtd(doc->intSubset);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001936 if (doc->oldNs != NULL)
1937 ret->oldNs = xmlCopyNamespaceList(doc->oldNs);
1938 if (doc->root != NULL)
1939 ret->root = xmlStaticCopyNodeList(doc->root, ret, NULL);
1940 return(ret);
1941}
1942
1943/************************************************************************
1944 * *
Daniel Veillard260a68f1998-08-13 03:39:55 +00001945 * Content access functions *
1946 * *
1947 ************************************************************************/
1948
Daniel Veillard97b58771998-10-20 06:14:16 +00001949/**
Daniel Veillardb96e6431999-08-29 21:02:19 +00001950 * xmlNodeSetLang:
1951 * @cur: the node being changed
1952 * @lang: the langage description
1953 *
1954 * Searches the language of a node, i.e. the values of the xml:lang
1955 * attribute or the one carried by the nearest ancestor.
Daniel Veillardb96e6431999-08-29 21:02:19 +00001956 */
1957void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001958xmlNodeSetLang(xmlNodePtr cur, const xmlChar *lang) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00001959 /* TODO xmlNodeSetLang check against the production [33] LanguageID */
1960 xmlSetProp(cur, BAD_CAST "xml:lang", lang);
1961}
1962
1963/**
1964 * xmlNodeGetLang:
1965 * @cur: the node being checked
1966 *
1967 * Searches the language of a node, i.e. the values of the xml:lang
1968 * attribute or the one carried by the nearest ancestor.
1969 *
1970 * Returns a pointer to the lang value, or NULL if not found
1971 */
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001972const xmlChar *
Daniel Veillardb96e6431999-08-29 21:02:19 +00001973xmlNodeGetLang(xmlNodePtr cur) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001974 const xmlChar *lang;
Daniel Veillardb96e6431999-08-29 21:02:19 +00001975
1976 while (cur != NULL) {
1977 lang = xmlGetProp(cur, BAD_CAST "xml:lang");
1978 if (lang != NULL)
1979 return(lang);
1980 cur = cur->parent;
1981 }
1982 return(NULL);
1983}
1984
1985/**
Daniel Veillard16253641998-10-28 22:58:05 +00001986 * xmlNodeGetContent:
1987 * @cur: the node being read
1988 *
1989 * Read the value of a node, this can be either the text carried
1990 * directly by this node if it's a TEXT node or the aggregate string
1991 * of the values carried by this node child's (TEXT and ENTITY_REF).
1992 * Entity references are substitued.
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001993 * Returns a new xmlChar * or NULL if no content is available.
Daniel Veillard5099ae81999-04-21 20:12:07 +00001994 * It's up to the caller to free the memory.
Daniel Veillard16253641998-10-28 22:58:05 +00001995 */
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001996xmlChar *
Daniel Veillard16253641998-10-28 22:58:05 +00001997xmlNodeGetContent(xmlNodePtr cur) {
1998 if (cur == NULL) return(NULL);
1999 switch (cur->type) {
2000 case XML_DOCUMENT_FRAG_NODE:
2001 case XML_ELEMENT_NODE:
2002 return(xmlNodeListGetString(cur->doc, cur->childs, 1));
2003 break;
Daniel Veillardb96e6431999-08-29 21:02:19 +00002004 case XML_ATTRIBUTE_NODE: {
2005 xmlAttrPtr attr = (xmlAttrPtr) cur;
2006 if (attr->node != NULL)
2007 return(xmlNodeListGetString(attr->node->doc, attr->val, 1));
2008 else
2009 return(xmlNodeListGetString(NULL, attr->val, 1));
2010 break;
2011 }
2012 case XML_PI_NODE:
2013 if (cur->content != NULL)
2014 return(xmlStrdup(cur->content));
2015 return(NULL);
Daniel Veillard16253641998-10-28 22:58:05 +00002016 case XML_ENTITY_REF_NODE:
2017 case XML_ENTITY_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002018 case XML_COMMENT_NODE:
2019 case XML_DOCUMENT_NODE:
Daniel Veillard7c1206f1999-10-14 09:10:25 +00002020 case XML_HTML_DOCUMENT_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002021 case XML_DOCUMENT_TYPE_NODE:
2022 case XML_NOTATION_NODE:
2023 return(NULL);
Daniel Veillardb05deb71999-08-10 19:04:08 +00002024 case XML_CDATA_SECTION_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002025 case XML_TEXT_NODE:
2026 if (cur->content != NULL)
2027 return(xmlStrdup(cur->content));
2028 return(NULL);
2029 }
2030 return(NULL);
2031}
2032
2033/**
Daniel Veillard97b58771998-10-20 06:14:16 +00002034 * xmlNodeSetContent:
2035 * @cur: the node being modified
2036 * @content: the new value of the content
2037 *
2038 * Replace the content of a node.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002039 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002040void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002041xmlNodeSetContent(xmlNodePtr cur, const xmlChar *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002042 if (cur == NULL) {
2043 fprintf(stderr, "xmlNodeSetContent : node == NULL\n");
2044 return;
2045 }
Daniel Veillard16253641998-10-28 22:58:05 +00002046 switch (cur->type) {
2047 case XML_DOCUMENT_FRAG_NODE:
2048 case XML_ELEMENT_NODE:
2049 if (cur->content != NULL) {
Daniel Veillard6454aec1999-09-02 22:04:43 +00002050 xmlFree(cur->content);
Daniel Veillard16253641998-10-28 22:58:05 +00002051 cur->content = NULL;
2052 }
Daniel Veillard6454aec1999-09-02 22:04:43 +00002053 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillard16253641998-10-28 22:58:05 +00002054 cur->childs = xmlStringGetNodeList(cur->doc, content);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002055 UPDATE_LAST_CHILD(cur)
Daniel Veillard16253641998-10-28 22:58:05 +00002056 break;
2057 case XML_ATTRIBUTE_NODE:
2058 break;
2059 case XML_TEXT_NODE:
2060 case XML_CDATA_SECTION_NODE:
2061 case XML_ENTITY_REF_NODE:
2062 case XML_ENTITY_NODE:
2063 case XML_PI_NODE:
2064 case XML_COMMENT_NODE:
Daniel Veillard6454aec1999-09-02 22:04:43 +00002065 if (cur->content != NULL) xmlFree(cur->content);
2066 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002067 cur->last = cur->childs = NULL;
Daniel Veillard16253641998-10-28 22:58:05 +00002068 if (content != NULL)
2069 cur->content = xmlStrdup(content);
2070 else
2071 cur->content = NULL;
Daniel Veillardb96e6431999-08-29 21:02:19 +00002072 break;
Daniel Veillard16253641998-10-28 22:58:05 +00002073 case XML_DOCUMENT_NODE:
Daniel Veillard7c1206f1999-10-14 09:10:25 +00002074 case XML_HTML_DOCUMENT_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002075 case XML_DOCUMENT_TYPE_NODE:
2076 break;
2077 case XML_NOTATION_NODE:
2078 break;
2079 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002080}
2081
Daniel Veillard97b58771998-10-20 06:14:16 +00002082/**
2083 * xmlNodeSetContentLen:
2084 * @cur: the node being modified
2085 * @content: the new value of the content
2086 * @len: the size of @content
2087 *
2088 * Replace the content of a node.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002089 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002090void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002091xmlNodeSetContentLen(xmlNodePtr cur, const xmlChar *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002092 if (cur == NULL) {
Daniel Veillard16253641998-10-28 22:58:05 +00002093 fprintf(stderr, "xmlNodeSetContentLen : node == NULL\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002094 return;
2095 }
Daniel Veillard16253641998-10-28 22:58:05 +00002096 switch (cur->type) {
2097 case XML_DOCUMENT_FRAG_NODE:
2098 case XML_ELEMENT_NODE:
2099 if (cur->content != NULL) {
Daniel Veillard6454aec1999-09-02 22:04:43 +00002100 xmlFree(cur->content);
Daniel Veillard16253641998-10-28 22:58:05 +00002101 cur->content = NULL;
2102 }
Daniel Veillard6454aec1999-09-02 22:04:43 +00002103 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillard16253641998-10-28 22:58:05 +00002104 cur->childs = xmlStringLenGetNodeList(cur->doc, content, len);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002105 UPDATE_LAST_CHILD(cur)
Daniel Veillard16253641998-10-28 22:58:05 +00002106 break;
2107 case XML_ATTRIBUTE_NODE:
2108 break;
2109 case XML_TEXT_NODE:
2110 case XML_CDATA_SECTION_NODE:
2111 case XML_ENTITY_REF_NODE:
2112 case XML_ENTITY_NODE:
2113 case XML_PI_NODE:
2114 case XML_COMMENT_NODE:
Daniel Veillard6454aec1999-09-02 22:04:43 +00002115 if (cur->content != NULL) xmlFree(cur->content);
2116 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002117 cur->childs = cur->last = NULL;
Daniel Veillard16253641998-10-28 22:58:05 +00002118 if (content != NULL)
2119 cur->content = xmlStrndup(content, len);
2120 else
2121 cur->content = NULL;
Daniel Veillardb96e6431999-08-29 21:02:19 +00002122 break;
Daniel Veillard16253641998-10-28 22:58:05 +00002123 case XML_DOCUMENT_NODE:
Daniel Veillard7c1206f1999-10-14 09:10:25 +00002124 case XML_HTML_DOCUMENT_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002125 case XML_DOCUMENT_TYPE_NODE:
2126 break;
2127 case XML_NOTATION_NODE:
Daniel Veillard6454aec1999-09-02 22:04:43 +00002128 if (cur->content != NULL) xmlFree(cur->content);
2129 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002130 cur->childs = cur->last = NULL;
Daniel Veillard16253641998-10-28 22:58:05 +00002131 if (content != NULL)
2132 cur->content = xmlStrndup(content, len);
2133 else
2134 cur->content = NULL;
2135 break;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002136 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002137}
2138
Daniel Veillard97b58771998-10-20 06:14:16 +00002139/**
2140 * xmlNodeAddContentLen:
2141 * @cur: the node being modified
2142 * @content: extra content
2143 * @len: the size of @content
2144 *
2145 * Append the extra substring to the node content.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002146 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002147void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002148xmlNodeAddContentLen(xmlNodePtr cur, const xmlChar *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002149 if (cur == NULL) {
Daniel Veillard16253641998-10-28 22:58:05 +00002150 fprintf(stderr, "xmlNodeAddContentLen : node == NULL\n");
2151 return;
2152 }
2153 if (len <= 0) return;
2154 switch (cur->type) {
2155 case XML_DOCUMENT_FRAG_NODE:
2156 case XML_ELEMENT_NODE: {
2157 xmlNodePtr last = NULL, new;
2158
2159 if (cur->childs != NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002160 last = cur->last;
Daniel Veillard16253641998-10-28 22:58:05 +00002161 } else {
2162 if (cur->content != NULL) {
2163 cur->childs = xmlStringGetNodeList(cur->doc, cur->content);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002164 UPDATE_LAST_CHILD(cur)
Daniel Veillard6454aec1999-09-02 22:04:43 +00002165 xmlFree(cur->content);
Daniel Veillard16253641998-10-28 22:58:05 +00002166 cur->content = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002167 last = cur->last;
Daniel Veillard16253641998-10-28 22:58:05 +00002168 }
2169 }
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002170 new = xmlNewTextLen(content, len);
Daniel Veillard16253641998-10-28 22:58:05 +00002171 if (new != NULL) {
2172 xmlAddChild(cur, new);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002173 if ((last != NULL) && (last->next == new)) {
Daniel Veillard16253641998-10-28 22:58:05 +00002174 xmlTextMerge(last, new);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002175 }
Daniel Veillard16253641998-10-28 22:58:05 +00002176 }
2177 break;
2178 }
2179 case XML_ATTRIBUTE_NODE:
2180 break;
2181 case XML_TEXT_NODE:
2182 case XML_CDATA_SECTION_NODE:
2183 case XML_ENTITY_REF_NODE:
2184 case XML_ENTITY_NODE:
2185 case XML_PI_NODE:
2186 case XML_COMMENT_NODE:
2187 if (content != NULL)
2188 cur->content = xmlStrncat(cur->content, content, len);
2189 case XML_DOCUMENT_NODE:
Daniel Veillard7c1206f1999-10-14 09:10:25 +00002190 case XML_HTML_DOCUMENT_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002191 case XML_DOCUMENT_TYPE_NODE:
2192 break;
2193 case XML_NOTATION_NODE:
2194 if (content != NULL)
2195 cur->content = xmlStrncat(cur->content, content, len);
2196 break;
2197 }
2198}
2199
2200/**
2201 * xmlNodeAddContent:
2202 * @cur: the node being modified
2203 * @content: extra content
2204 *
2205 * Append the extra substring to the node content.
2206 */
2207void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002208xmlNodeAddContent(xmlNodePtr cur, const xmlChar *content) {
Daniel Veillard16253641998-10-28 22:58:05 +00002209 int len;
2210
2211 if (cur == NULL) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002212 fprintf(stderr, "xmlNodeAddContent : node == NULL\n");
2213 return;
2214 }
Daniel Veillard16253641998-10-28 22:58:05 +00002215 if (content == NULL) return;
2216 len = xmlStrlen(content);
2217 xmlNodeAddContentLen(cur, content, len);
2218}
2219
2220/**
2221 * xmlTextMerge:
2222 * @first: the first text node
2223 * @second: the second text node being merged
2224 *
2225 * Merge two text nodes into one
Daniel Veillard1e346af1999-02-22 10:33:01 +00002226 * Returns the first text node augmented
Daniel Veillard16253641998-10-28 22:58:05 +00002227 */
2228xmlNodePtr
2229xmlTextMerge(xmlNodePtr first, xmlNodePtr second) {
2230 if (first == NULL) return(second);
2231 if (second == NULL) return(first);
2232 if (first->type != XML_TEXT_NODE) return(first);
2233 if (second->type != XML_TEXT_NODE) return(first);
2234 xmlNodeAddContent(first, second->content);
2235 xmlUnlinkNode(second);
2236 xmlFreeNode(second);
2237 return(first);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002238}
2239
Daniel Veillard97b58771998-10-20 06:14:16 +00002240/**
Daniel Veillardb96e6431999-08-29 21:02:19 +00002241 * xmlGetNsList:
2242 * @doc: the document
2243 * @node: the current node
2244 *
2245 * Search all the namespace applying to a given element.
2246 * Returns an NULL terminated array of all the xmlNsPtr found
2247 * that need to be freed by the caller or NULL if no
2248 * namespace if defined
2249 */
2250xmlNsPtr *
2251xmlGetNsList(xmlDocPtr doc, xmlNodePtr node) {
2252 xmlNsPtr cur;
2253 xmlNsPtr *ret = NULL;
2254 int nbns = 0;
2255 int maxns = 10;
2256 int i;
2257
2258 while (node != NULL) {
2259 cur = node->nsDef;
2260 while (cur != NULL) {
2261 if (ret == NULL) {
Daniel Veillard6454aec1999-09-02 22:04:43 +00002262 ret = (xmlNsPtr *) xmlMalloc((maxns + 1) * sizeof(xmlNsPtr));
Daniel Veillardb96e6431999-08-29 21:02:19 +00002263 if (ret == NULL) {
2264 fprintf(stderr, "xmlGetNsList : out of memory!\n");
2265 return(NULL);
2266 }
2267 ret[nbns] = NULL;
2268 }
2269 for (i = 0;i < nbns;i++) {
2270 if ((cur->prefix == ret[i]->prefix) ||
2271 (!xmlStrcmp(cur->prefix, ret[i]->prefix))) break;
2272 }
2273 if (i >= nbns) {
2274 if (nbns >= maxns) {
2275 maxns *= 2;
Daniel Veillard6454aec1999-09-02 22:04:43 +00002276 ret = (xmlNsPtr *) xmlRealloc(ret,
Daniel Veillardb96e6431999-08-29 21:02:19 +00002277 (maxns + 1) * sizeof(xmlNsPtr));
2278 if (ret == NULL) {
2279 fprintf(stderr, "xmlGetNsList : realloc failed!\n");
2280 return(NULL);
2281 }
2282 }
2283 ret[nbns++] = cur;
2284 ret[nbns] = NULL;
2285 }
2286
2287 cur = cur->next;
2288 }
2289 node = node->parent;
2290 }
2291 return(ret);
2292}
2293
2294/**
Daniel Veillard97b58771998-10-20 06:14:16 +00002295 * xmlSearchNs:
2296 * @doc: the document
2297 * @node: the current node
2298 * @nameSpace: the namespace string
Daniel Veillard260a68f1998-08-13 03:39:55 +00002299 *
Daniel Veillard97b58771998-10-20 06:14:16 +00002300 * Search a Ns registered under a given name space for a document.
2301 * recurse on the parents until it finds the defined namespace
2302 * or return NULL otherwise.
2303 * @nameSpace can be NULL, this is a search for the default namespace.
Daniel Veillard1e346af1999-02-22 10:33:01 +00002304 * Returns the namespace pointer or NULL.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002305 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002306xmlNsPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002307xmlSearchNs(xmlDocPtr doc, xmlNodePtr node, const xmlChar *nameSpace) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002308 xmlNsPtr cur;
2309
2310 while (node != NULL) {
2311 cur = node->nsDef;
2312 while (cur != NULL) {
2313 if ((cur->prefix == NULL) && (nameSpace == NULL))
2314 return(cur);
2315 if ((cur->prefix != NULL) && (nameSpace != NULL) &&
2316 (!xmlStrcmp(cur->prefix, nameSpace)))
2317 return(cur);
2318 cur = cur->next;
2319 }
2320 node = node->parent;
2321 }
2322 if (doc != NULL) {
2323 cur = doc->oldNs;
2324 while (cur != NULL) {
2325 if ((cur->prefix != NULL) && (nameSpace != NULL) &&
2326 (!xmlStrcmp(cur->prefix, nameSpace)))
2327 return(cur);
2328 cur = cur->next;
2329 }
2330 }
2331 return(NULL);
2332}
2333
Daniel Veillard97b58771998-10-20 06:14:16 +00002334/**
2335 * xmlSearchNsByHref:
2336 * @doc: the document
2337 * @node: the current node
2338 * @href: the namespace value
2339 *
2340 * Search a Ns aliasing a given URI. Recurse on the parents until it finds
2341 * the defined namespace or return NULL otherwise.
Daniel Veillard1e346af1999-02-22 10:33:01 +00002342 * Returns the namespace pointer or NULL.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002343 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002344xmlNsPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002345xmlSearchNsByHref(xmlDocPtr doc, xmlNodePtr node, const xmlChar *href) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002346 xmlNsPtr cur;
2347
2348 while (node != NULL) {
2349 cur = node->nsDef;
2350 while (cur != NULL) {
2351 if ((cur->href != NULL) && (href != NULL) &&
2352 (!xmlStrcmp(cur->href, href)))
2353 return(cur);
2354 cur = cur->next;
2355 }
2356 node = node->parent;
2357 }
2358 if (doc != NULL) {
2359 cur = doc->oldNs;
2360 while (cur != NULL) {
2361 if ((cur->href != NULL) && (href != NULL) &&
2362 (!xmlStrcmp(cur->href, href)))
2363 return(cur);
2364 cur = cur->next;
2365 }
2366 }
2367 return(NULL);
2368}
2369
Daniel Veillard97b58771998-10-20 06:14:16 +00002370/**
2371 * xmlGetProp:
2372 * @node: the node
2373 * @name: the attribute name
2374 *
2375 * Search and get the value of an attribute associated to a node
Daniel Veillardccb09631998-10-27 06:21:04 +00002376 * This does the entity substitution.
Daniel Veillard1e346af1999-02-22 10:33:01 +00002377 * Returns the attribute value or NULL if not found.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002378 */
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002379xmlChar *xmlGetProp(xmlNodePtr node, const xmlChar *name) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002380 xmlAttrPtr prop = node->properties;
2381
2382 while (prop != NULL) {
Daniel Veillard68178931999-02-08 18:34:36 +00002383 if (!xmlStrcmp(prop->name, name)) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002384 xmlChar *ret;
Daniel Veillard6800ef31999-02-08 18:33:22 +00002385
2386 ret = xmlNodeListGetString(node->doc, prop->val, 1);
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002387 if (ret == NULL) return(xmlStrdup((xmlChar *)""));
Daniel Veillard6800ef31999-02-08 18:33:22 +00002388 return(ret);
Daniel Veillard68178931999-02-08 18:34:36 +00002389 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002390 prop = prop->next;
2391 }
2392 return(NULL);
2393}
2394
Daniel Veillard97b58771998-10-20 06:14:16 +00002395/**
Daniel Veillardccb09631998-10-27 06:21:04 +00002396 * xmlSetProp:
Daniel Veillard97b58771998-10-20 06:14:16 +00002397 * @node: the node
2398 * @name: the attribute name
2399 * @value: the attribute value
2400 *
2401 * Set (or reset) an attribute carried by a node.
Daniel Veillard1e346af1999-02-22 10:33:01 +00002402 * Returns the attribute pointer.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002403 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002404xmlAttrPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002405xmlSetProp(xmlNodePtr node, const xmlChar *name, const xmlChar *value) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002406 xmlAttrPtr prop = node->properties;
2407
2408 while (prop != NULL) {
2409 if (!xmlStrcmp(prop->name, name)) {
Daniel Veillardccb09631998-10-27 06:21:04 +00002410 if (prop->val != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +00002411 xmlFreeNodeList(prop->val);
Daniel Veillardccb09631998-10-27 06:21:04 +00002412 prop->val = NULL;
Daniel Veillard51e3b151999-11-12 17:02:31 +00002413 if (value != NULL) {
2414 xmlChar *buffer;
2415 buffer = xmlEncodeEntitiesReentrant(node->doc, value);
2416 prop->val = xmlStringGetNodeList(node->doc, buffer);
2417 xmlFree(buffer);
2418 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002419 return(prop);
2420 }
2421 prop = prop->next;
2422 }
2423 prop = xmlNewProp(node, name, value);
2424 return(prop);
2425}
2426
Daniel Veillard97b58771998-10-20 06:14:16 +00002427/**
2428 * xmlNodeIsText:
2429 * @node: the node
2430 *
2431 * Is this node a Text node ?
Daniel Veillard1e346af1999-02-22 10:33:01 +00002432 * Returns 1 yes, 0 no
Daniel Veillard260a68f1998-08-13 03:39:55 +00002433 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002434int
2435xmlNodeIsText(xmlNodePtr node) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002436 if (node == NULL) return(0);
2437
Daniel Veillard0bef1311998-10-14 02:36:47 +00002438 if (node->type == XML_TEXT_NODE) return(1);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002439 return(0);
2440}
2441
Daniel Veillard97b58771998-10-20 06:14:16 +00002442/**
Daniel Veillard1e346af1999-02-22 10:33:01 +00002443 * xmlTextConcat:
Daniel Veillard97b58771998-10-20 06:14:16 +00002444 * @node: the node
2445 * @content: the content
2446 * @len: @content lenght
2447 *
2448 * Concat the given string at the end of the existing node content
Daniel Veillard260a68f1998-08-13 03:39:55 +00002449 */
Daniel Veillard97b58771998-10-20 06:14:16 +00002450
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002451void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002452xmlTextConcat(xmlNodePtr node, const xmlChar *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002453 if (node == NULL) return;
2454
Daniel Veillard0bef1311998-10-14 02:36:47 +00002455 if (node->type != XML_TEXT_NODE) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002456 fprintf(stderr, "xmlTextConcat: node is not text\n");
2457 return;
2458 }
2459 node->content = xmlStrncat(node->content, content, len);
2460}
2461
2462/************************************************************************
2463 * *
2464 * Output : to a FILE or in memory *
2465 * *
2466 ************************************************************************/
2467
Daniel Veillard5099ae81999-04-21 20:12:07 +00002468#define BASE_BUFFER_SIZE 4000
2469
2470/**
2471 * xmlBufferCreate:
2472 *
2473 * routine to create an XML buffer.
2474 * returns the new structure.
2475 */
2476xmlBufferPtr
2477xmlBufferCreate(void) {
2478 xmlBufferPtr ret;
2479
Daniel Veillard6454aec1999-09-02 22:04:43 +00002480 ret = (xmlBufferPtr) xmlMalloc(sizeof(xmlBuffer));
Daniel Veillard5099ae81999-04-21 20:12:07 +00002481 if (ret == NULL) {
2482 fprintf(stderr, "xmlBufferCreate : out of memory!\n");
2483 return(NULL);
2484 }
2485 ret->use = 0;
2486 ret->size = BASE_BUFFER_SIZE;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002487 ret->content = (xmlChar *) xmlMalloc(ret->size * sizeof(xmlChar));
Daniel Veillard5099ae81999-04-21 20:12:07 +00002488 if (ret->content == NULL) {
2489 fprintf(stderr, "xmlBufferCreate : out of memory!\n");
Daniel Veillard6454aec1999-09-02 22:04:43 +00002490 xmlFree(ret);
Daniel Veillard5099ae81999-04-21 20:12:07 +00002491 return(NULL);
2492 }
2493 ret->content[0] = 0;
2494 return(ret);
2495}
2496
2497/**
2498 * xmlBufferFree:
2499 * @buf: the buffer to free
2500 *
2501 * Frees an XML buffer.
2502 */
2503void
2504xmlBufferFree(xmlBufferPtr buf) {
2505 if (buf == NULL) {
2506 fprintf(stderr, "xmlBufferFree: buf == NULL\n");
2507 return;
2508 }
2509 if (buf->content == NULL) {
2510 fprintf(stderr, "xmlBufferFree: buf->content == NULL\n");
2511 } else {
2512 memset(buf->content, -1, BASE_BUFFER_SIZE);
Daniel Veillard6454aec1999-09-02 22:04:43 +00002513 xmlFree(buf->content);
Daniel Veillard5099ae81999-04-21 20:12:07 +00002514 }
2515 memset(buf, -1, sizeof(xmlBuffer));
Daniel Veillard6454aec1999-09-02 22:04:43 +00002516 xmlFree(buf);
Daniel Veillard5099ae81999-04-21 20:12:07 +00002517}
2518
2519/**
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002520 * xmlBufferEmpty:
2521 * @buf: the buffer
2522 *
2523 * empty a buffer.
2524 */
2525void
2526xmlBufferEmpty(xmlBufferPtr buf) {
2527 buf->use = 0;
2528 memset(buf->content, -1, buf->size);/* just for debug */
2529}
2530
2531/**
2532 * xmlBufferShrink:
2533 * @buf: the buffer to dump
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002534 * @len: the number of xmlChar to remove
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002535 *
2536 * Remove the beginning of an XML buffer.
2537 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002538 * Returns the number of xmlChar removed, or -1 in case of failure.
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002539 */
2540int
2541xmlBufferShrink(xmlBufferPtr buf, int len) {
2542 if (len == 0) return(0);
2543 if (len > buf->use) return(-1);
2544
2545 buf->use -= len;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002546 memmove(buf->content, &buf->content[len], buf->use * sizeof(xmlChar));
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002547
2548 buf->content[buf->use] = 0;
2549 return(len);
2550}
2551
2552/**
Daniel Veillard5099ae81999-04-21 20:12:07 +00002553 * xmlBufferDump:
2554 * @file: the file output
2555 * @buf: the buffer to dump
2556 *
2557 * Dumps an XML buffer to a FILE *.
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002558 * Returns the number of xmlChar written
Daniel Veillard5099ae81999-04-21 20:12:07 +00002559 */
2560int
2561xmlBufferDump(FILE *file, xmlBufferPtr buf) {
2562 int ret;
2563
2564 if (buf == NULL) {
2565 fprintf(stderr, "xmlBufferDump: buf == NULL\n");
2566 return(0);
2567 }
2568 if (buf->content == NULL) {
2569 fprintf(stderr, "xmlBufferDump: buf->content == NULL\n");
2570 return(0);
2571 }
2572 if (file == NULL) file = stdout;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002573 ret = fwrite(buf->content, sizeof(xmlChar), buf->use, file);
Daniel Veillard5099ae81999-04-21 20:12:07 +00002574 return(ret);
2575}
2576
2577/**
2578 * xmlBufferAdd:
2579 * @buf: the buffer to dump
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002580 * @str: the xmlChar string
2581 * @len: the number of xmlChar to add
Daniel Veillard5099ae81999-04-21 20:12:07 +00002582 *
2583 * Add a string range to an XML buffer.
2584 */
2585void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002586xmlBufferAdd(xmlBufferPtr buf, const xmlChar *str, int len) {
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002587 int l;
Daniel Veillard5099ae81999-04-21 20:12:07 +00002588
2589 if (str == NULL) {
2590 fprintf(stderr, "xmlBufferAdd: str == NULL\n");
2591 return;
2592 }
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002593 l = xmlStrlen(str);
2594 if (l < len) len = l;
2595 if (len <= 0) return;
Daniel Veillard5099ae81999-04-21 20:12:07 +00002596
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002597 if (buf->use + len + 10 >= buf->size) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002598 xmlChar *rebuf;
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002599
2600 buf->size *= 2;
2601 if (buf->use + len + 10 > buf->size)
2602 buf->size = buf->use + len + 10;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002603 rebuf = (xmlChar *) xmlRealloc(buf->content, buf->size * sizeof(xmlChar));
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002604 if (rebuf == NULL) {
2605 fprintf(stderr, "xmlBufferAdd : out of memory!\n");
2606 return;
Daniel Veillard5099ae81999-04-21 20:12:07 +00002607 }
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002608 buf->content = rebuf;
Daniel Veillard5099ae81999-04-21 20:12:07 +00002609 }
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002610 memmove(&buf->content[buf->use], str, len);
2611 buf->use += len;
2612 buf->content[buf->use] = 0;
Daniel Veillard5099ae81999-04-21 20:12:07 +00002613}
2614
2615/**
2616 * xmlBufferCat:
2617 * @buf: the buffer to dump
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002618 * @str: the xmlChar string
Daniel Veillard5099ae81999-04-21 20:12:07 +00002619 *
2620 * Append a zero terminated string to an XML buffer.
2621 */
2622void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002623xmlBufferCat(xmlBufferPtr buf, const xmlChar *str) {
2624 const xmlChar *cur;
Daniel Veillard5099ae81999-04-21 20:12:07 +00002625
2626 if (str == NULL) {
2627 fprintf(stderr, "xmlBufferAdd: str == NULL\n");
2628 return;
2629 }
2630 for (cur = str;*cur != 0;cur++) {
2631 if (buf->use + 10 >= buf->size) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002632 xmlChar *rebuf;
Daniel Veillard5099ae81999-04-21 20:12:07 +00002633
2634 buf->size *= 2;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002635 rebuf = (xmlChar *) xmlRealloc(buf->content, buf->size * sizeof(xmlChar));
Daniel Veillard5099ae81999-04-21 20:12:07 +00002636 if (rebuf == NULL) {
2637 fprintf(stderr, "xmlBufferAdd : out of memory!\n");
2638 return;
2639 }
2640 buf->content = rebuf;
2641 }
2642 buf->content[buf->use++] = *cur;
2643 }
2644}
2645
2646/**
2647 * xmlBufferCCat:
2648 * @buf: the buffer to dump
2649 * @str: the C char string
2650 *
2651 * Append a zero terminated C string to an XML buffer.
2652 */
2653void
2654xmlBufferCCat(xmlBufferPtr buf, const char *str) {
2655 const char *cur;
2656
2657 if (str == NULL) {
2658 fprintf(stderr, "xmlBufferAdd: str == NULL\n");
2659 return;
2660 }
2661 for (cur = str;*cur != 0;cur++) {
2662 if (buf->use + 10 >= buf->size) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002663 xmlChar *rebuf;
Daniel Veillard5099ae81999-04-21 20:12:07 +00002664
2665 buf->size *= 2;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002666 rebuf = (xmlChar *) xmlRealloc(buf->content, buf->size * sizeof(xmlChar));
Daniel Veillard5099ae81999-04-21 20:12:07 +00002667 if (rebuf == NULL) {
2668 fprintf(stderr, "xmlBufferAdd : out of memory!\n");
2669 return;
2670 }
2671 buf->content = rebuf;
2672 }
2673 buf->content[buf->use++] = *cur;
2674 }
2675}
Daniel Veillard260a68f1998-08-13 03:39:55 +00002676
Daniel Veillard97b58771998-10-20 06:14:16 +00002677/**
Daniel Veillard7d2c2761999-10-11 15:09:51 +00002678 * xmlBufferLastChar:
2679 * @buf: the buffer to dump
2680 *
2681 * Get the last char of the buffer
2682 *
2683 * Returns the last char from the buffer or 0 if empty
2684 */
2685xmlChar
2686xmlBufferLastChar(xmlBufferPtr buf) {
2687 if ((buf == NULL) || (buf->use <= 0)) return(0);
2688 return(buf->content[buf->use - 1]);
2689}
2690
2691/**
Daniel Veillard97b58771998-10-20 06:14:16 +00002692 * xmlBufferWriteCHAR:
Daniel Veillard5099ae81999-04-21 20:12:07 +00002693 * @buf: the XML buffer
Daniel Veillard97b58771998-10-20 06:14:16 +00002694 * @string: the string to add
2695 *
2696 * routine which manage and grows an output buffer. This one add
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002697 * xmlChars at the end of the buffer.
Daniel Veillard97b58771998-10-20 06:14:16 +00002698 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002699void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002700xmlBufferWriteCHAR(xmlBufferPtr buf, const xmlChar *string) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002701 xmlBufferCat(buf, string);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002702}
2703
Daniel Veillard97b58771998-10-20 06:14:16 +00002704/**
2705 * xmlBufferWriteChar:
Daniel Veillard011b63c1999-06-02 17:44:04 +00002706 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00002707 * @string: the string to add
2708 *
2709 * routine which manage and grows an output buffer. This one add
2710 * C chars at the end of the array.
2711 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002712void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002713xmlBufferWriteChar(xmlBufferPtr buf, const char *string) {
2714 xmlBufferCCat(buf, string);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002715}
2716
Daniel Veillard5099ae81999-04-21 20:12:07 +00002717
Daniel Veillard97b58771998-10-20 06:14:16 +00002718/**
Daniel Veillard011b63c1999-06-02 17:44:04 +00002719 * xmlBufferWriteQuotedString:
2720 * @buf: the XML buffer output
2721 * @string: the string to add
2722 *
2723 * routine which manage and grows an output buffer. This one writes
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002724 * a quoted or double quoted xmlChar string, checking first if it holds
Daniel Veillard011b63c1999-06-02 17:44:04 +00002725 * quote or double-quotes internally
2726 */
2727void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002728xmlBufferWriteQuotedString(xmlBufferPtr buf, const xmlChar *string) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00002729 if (xmlStrchr(string, '"')) {
2730 if (xmlStrchr(string, '\'')) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00002731 fprintf(stderr,
2732 "xmlBufferWriteQuotedString: string contains quote and double-quotes !\n");
2733 }
2734 xmlBufferCCat(buf, "'");
2735 xmlBufferCat(buf, string);
2736 xmlBufferCCat(buf, "'");
2737 } else {
2738 xmlBufferCCat(buf, "\"");
2739 xmlBufferCat(buf, string);
2740 xmlBufferCCat(buf, "\"");
2741 }
2742}
2743
2744
2745/**
Daniel Veillard97b58771998-10-20 06:14:16 +00002746 * xmlGlobalNsDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00002747 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00002748 * @cur: a namespace
2749 *
2750 * Dump a global Namespace, this is the old version based on PIs.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002751 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002752static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002753xmlGlobalNsDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002754 if (cur == NULL) {
2755 fprintf(stderr, "xmlGlobalNsDump : Ns == NULL\n");
2756 return;
2757 }
2758 if (cur->type == XML_GLOBAL_NAMESPACE) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002759 xmlBufferWriteChar(buf, "<?namespace");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002760 if (cur->href != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00002761 xmlBufferWriteChar(buf, " href=");
2762 xmlBufferWriteQuotedString(buf, cur->href);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002763 }
2764 if (cur->prefix != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00002765 xmlBufferWriteChar(buf, " AS=");
2766 xmlBufferWriteQuotedString(buf, cur->prefix);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002767 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00002768 xmlBufferWriteChar(buf, "?>\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002769 }
2770}
2771
Daniel Veillard97b58771998-10-20 06:14:16 +00002772/**
2773 * xmlGlobalNsListDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00002774 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00002775 * @cur: the first namespace
2776 *
2777 * Dump a list of global Namespace, this is the old version based on PIs.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002778 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002779static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002780xmlGlobalNsListDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002781 while (cur != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002782 xmlGlobalNsDump(buf, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002783 cur = cur->next;
2784 }
2785}
2786
Daniel Veillard97b58771998-10-20 06:14:16 +00002787/**
2788 * xmlNsDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00002789 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00002790 * @cur: a namespace
2791 *
Daniel Veillard260a68f1998-08-13 03:39:55 +00002792 * Dump a local Namespace definition.
Daniel Veillard97b58771998-10-20 06:14:16 +00002793 * Should be called in the context of attributes dumps.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002794 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002795static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002796xmlNsDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002797 if (cur == NULL) {
2798 fprintf(stderr, "xmlNsDump : Ns == NULL\n");
2799 return;
2800 }
2801 if (cur->type == XML_LOCAL_NAMESPACE) {
2802 /* Within the context of an element attributes */
2803 if (cur->prefix != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002804 xmlBufferWriteChar(buf, " xmlns:");
2805 xmlBufferWriteCHAR(buf, cur->prefix);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002806 } else
Daniel Veillard5099ae81999-04-21 20:12:07 +00002807 xmlBufferWriteChar(buf, " xmlns");
Daniel Veillard011b63c1999-06-02 17:44:04 +00002808 xmlBufferWriteChar(buf, "=");
2809 xmlBufferWriteQuotedString(buf, cur->href);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002810 }
2811}
2812
Daniel Veillard97b58771998-10-20 06:14:16 +00002813/**
2814 * xmlNsListDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00002815 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00002816 * @cur: the first namespace
2817 *
2818 * Dump a list of local Namespace definitions.
2819 * Should be called in the context of attributes dumps.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002820 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002821static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002822xmlNsListDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002823 while (cur != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002824 xmlNsDump(buf, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002825 cur = cur->next;
2826 }
2827}
2828
Daniel Veillard97b58771998-10-20 06:14:16 +00002829/**
2830 * xmlDtdDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00002831 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00002832 * @doc: the document
2833 *
2834 * Dump the XML document DTD, if any.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002835 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002836static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002837xmlDtdDump(xmlBufferPtr buf, xmlDocPtr doc) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002838 xmlDtdPtr cur = doc->intSubset;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002839
2840 if (cur == NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002841 fprintf(stderr, "xmlDtdDump : no internal subset\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002842 return;
2843 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00002844 xmlBufferWriteChar(buf, "<!DOCTYPE ");
2845 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002846 if (cur->ExternalID != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00002847 xmlBufferWriteChar(buf, " PUBLIC ");
2848 xmlBufferWriteQuotedString(buf, cur->ExternalID);
2849 xmlBufferWriteChar(buf, " ");
2850 xmlBufferWriteQuotedString(buf, cur->SystemID);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002851 } else if (cur->SystemID != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00002852 xmlBufferWriteChar(buf, " SYSTEM ");
2853 xmlBufferWriteQuotedString(buf, cur->SystemID);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002854 }
Daniel Veillard1e346af1999-02-22 10:33:01 +00002855 if ((cur->entities == NULL) && (cur->elements == NULL) &&
2856 (cur->attributes == NULL) && (cur->notations == NULL)) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002857 xmlBufferWriteChar(buf, ">\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002858 return;
2859 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00002860 xmlBufferWriteChar(buf, " [\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002861 if (cur->entities != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00002862 xmlDumpEntitiesTable(buf, (xmlEntitiesTablePtr) cur->entities);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002863 if (cur->notations != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00002864 xmlDumpNotationTable(buf, (xmlNotationTablePtr) cur->notations);
Daniel Veillard3b9def11999-01-31 22:15:06 +00002865 if (cur->elements != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00002866 xmlDumpElementTable(buf, (xmlElementTablePtr) cur->elements);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002867 if (cur->attributes != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00002868 xmlDumpAttributeTable(buf, (xmlAttributeTablePtr) cur->attributes);
2869 xmlBufferWriteChar(buf, "]");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002870
Daniel Veillard5099ae81999-04-21 20:12:07 +00002871 xmlBufferWriteChar(buf, ">\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002872}
2873
Daniel Veillard97b58771998-10-20 06:14:16 +00002874/**
2875 * xmlAttrDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00002876 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00002877 * @doc: the document
2878 * @cur: the attribute pointer
2879 *
2880 * Dump an XML attribute
Daniel Veillard260a68f1998-08-13 03:39:55 +00002881 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002882static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002883xmlAttrDump(xmlBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002884 xmlChar *value;
Daniel Veillardccb09631998-10-27 06:21:04 +00002885
Daniel Veillard260a68f1998-08-13 03:39:55 +00002886 if (cur == NULL) {
2887 fprintf(stderr, "xmlAttrDump : property == NULL\n");
2888 return;
2889 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00002890 xmlBufferWriteChar(buf, " ");
Daniel Veillardb96e6431999-08-29 21:02:19 +00002891 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
2892 xmlBufferWriteCHAR(buf, cur->ns->prefix);
2893 xmlBufferWriteChar(buf, ":");
2894 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00002895 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillardccb09631998-10-27 06:21:04 +00002896 value = xmlNodeListGetString(doc, cur->val, 0);
2897 if (value) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00002898 xmlBufferWriteChar(buf, "=");
2899 xmlBufferWriteQuotedString(buf, value);
Daniel Veillard6454aec1999-09-02 22:04:43 +00002900 xmlFree(value);
Daniel Veillard726c7e31999-02-08 15:13:10 +00002901 } else {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002902 xmlBufferWriteChar(buf, "=\"\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002903 }
2904}
2905
Daniel Veillard97b58771998-10-20 06:14:16 +00002906/**
2907 * xmlAttrListDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00002908 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00002909 * @doc: the document
2910 * @cur: the first attribute pointer
2911 *
2912 * Dump a list of XML attributes
Daniel Veillard260a68f1998-08-13 03:39:55 +00002913 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002914static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002915xmlAttrListDump(xmlBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002916 if (cur == NULL) {
2917 fprintf(stderr, "xmlAttrListDump : property == NULL\n");
2918 return;
2919 }
2920 while (cur != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002921 xmlAttrDump(buf, doc, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002922 cur = cur->next;
2923 }
2924}
2925
Daniel Veillard260a68f1998-08-13 03:39:55 +00002926
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002927static void
Daniel Veillard7d2c2761999-10-11 15:09:51 +00002928xmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
2929 int format);
Daniel Veillard97b58771998-10-20 06:14:16 +00002930/**
2931 * xmlNodeListDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00002932 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00002933 * @doc: the document
2934 * @cur: the first node
2935 * @level: the imbrication level for indenting
Daniel Veillard7d2c2761999-10-11 15:09:51 +00002936 * @format: is formatting allowed
Daniel Veillard97b58771998-10-20 06:14:16 +00002937 *
2938 * Dump an XML node list, recursive behaviour,children are printed too.
2939 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002940static void
Daniel Veillard7d2c2761999-10-11 15:09:51 +00002941xmlNodeListDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
2942 int format) {
2943 int i;
Daniel Veillardccb09631998-10-27 06:21:04 +00002944
Daniel Veillard260a68f1998-08-13 03:39:55 +00002945 if (cur == NULL) {
2946 fprintf(stderr, "xmlNodeListDump : node == NULL\n");
2947 return;
2948 }
2949 while (cur != NULL) {
Daniel Veillard7d2c2761999-10-11 15:09:51 +00002950 if ((format) && (xmlIndentTreeOutput) &&
2951 (cur->type == XML_ELEMENT_NODE))
2952 for (i = 0;i < level;i++)
2953 xmlBufferWriteChar(buf, " ");
2954 xmlNodeDump(buf, doc, cur, level, format);
2955 if (format) {
2956 xmlBufferWriteChar(buf, "\n");
Daniel Veillardccb09631998-10-27 06:21:04 +00002957 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002958 cur = cur->next;
2959 }
2960}
2961
Daniel Veillard97b58771998-10-20 06:14:16 +00002962/**
Daniel Veillardccb09631998-10-27 06:21:04 +00002963 * xmlNodeDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00002964 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00002965 * @doc: the document
2966 * @cur: the current node
2967 * @level: the imbrication level for indenting
Daniel Veillard7d2c2761999-10-11 15:09:51 +00002968 * @format: is formatting allowed
Daniel Veillard97b58771998-10-20 06:14:16 +00002969 *
2970 * Dump an XML node, recursive behaviour,children are printed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002971 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002972static void
Daniel Veillard7d2c2761999-10-11 15:09:51 +00002973xmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
2974 int format) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002975 int i;
Daniel Veillard7d2c2761999-10-11 15:09:51 +00002976 xmlNodePtr tmp;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002977
2978 if (cur == NULL) {
2979 fprintf(stderr, "xmlNodeDump : node == NULL\n");
2980 return;
2981 }
Daniel Veillard0bef1311998-10-14 02:36:47 +00002982 if (cur->type == XML_TEXT_NODE) {
Daniel Veillard14fff061999-06-22 21:49:07 +00002983 if (cur->content != NULL) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002984 xmlChar *buffer;
Daniel Veillard14fff061999-06-22 21:49:07 +00002985
2986 buffer = xmlEncodeEntitiesReentrant(doc, cur->content);
2987 if (buffer != NULL) {
2988 xmlBufferWriteCHAR(buf, buffer);
Daniel Veillard6454aec1999-09-02 22:04:43 +00002989 xmlFree(buffer);
Daniel Veillard14fff061999-06-22 21:49:07 +00002990 }
2991 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002992 return;
2993 }
Daniel Veillardb96e6431999-08-29 21:02:19 +00002994 if (cur->type == XML_PI_NODE) {
2995 if (cur->content != NULL) {
2996 xmlBufferWriteChar(buf, "<?");
2997 xmlBufferWriteCHAR(buf, cur->name);
2998 if (cur->content != NULL) {
2999 xmlBufferWriteChar(buf, " ");
3000 xmlBufferWriteCHAR(buf, cur->content);
3001 }
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003002 xmlBufferWriteChar(buf, "?>");
Daniel Veillardb96e6431999-08-29 21:02:19 +00003003 }
3004 return;
3005 }
Daniel Veillard0bef1311998-10-14 02:36:47 +00003006 if (cur->type == XML_COMMENT_NODE) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003007 if (cur->content != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003008 xmlBufferWriteChar(buf, "<!--");
3009 xmlBufferWriteCHAR(buf, cur->content);
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003010 xmlBufferWriteChar(buf, "-->");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003011 }
3012 return;
3013 }
Daniel Veillardccb09631998-10-27 06:21:04 +00003014 if (cur->type == XML_ENTITY_REF_NODE) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003015 xmlBufferWriteChar(buf, "&");
3016 xmlBufferWriteCHAR(buf, cur->name);
3017 xmlBufferWriteChar(buf, ";");
Daniel Veillardccb09631998-10-27 06:21:04 +00003018 return;
3019 }
Daniel Veillardb05deb71999-08-10 19:04:08 +00003020 if (cur->type == XML_CDATA_SECTION_NODE) {
3021 xmlBufferWriteChar(buf, "<![CDATA[");
3022 if (cur->content != NULL)
3023 xmlBufferWriteCHAR(buf, cur->content);
3024 xmlBufferWriteChar(buf, "]]>");
3025 return;
3026 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003027
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003028 if (format == 1) {
3029 tmp = cur->childs;
3030 while (tmp != NULL) {
3031 if ((tmp->type == XML_TEXT_NODE) ||
3032 (tmp->type == XML_ENTITY_REF_NODE)) {
3033 format = 0;
3034 break;
3035 }
3036 tmp = tmp->next;
3037 }
3038 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003039 xmlBufferWriteChar(buf, "<");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003040 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003041 xmlBufferWriteCHAR(buf, cur->ns->prefix);
3042 xmlBufferWriteChar(buf, ":");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003043 }
3044
Daniel Veillard5099ae81999-04-21 20:12:07 +00003045 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003046 if (cur->nsDef)
Daniel Veillard5099ae81999-04-21 20:12:07 +00003047 xmlNsListDump(buf, cur->nsDef);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003048 if (cur->properties != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00003049 xmlAttrListDump(buf, doc, cur->properties);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003050
3051 if ((cur->content == NULL) && (cur->childs == NULL)) {
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003052 xmlBufferWriteChar(buf, "/>");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003053 return;
3054 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003055 xmlBufferWriteChar(buf, ">");
Daniel Veillard14fff061999-06-22 21:49:07 +00003056 if (cur->content != NULL) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003057 xmlChar *buffer;
Daniel Veillard14fff061999-06-22 21:49:07 +00003058
3059 buffer = xmlEncodeEntitiesReentrant(doc, cur->content);
3060 if (buffer != NULL) {
3061 xmlBufferWriteCHAR(buf, buffer);
Daniel Veillard6454aec1999-09-02 22:04:43 +00003062 xmlFree(buffer);
Daniel Veillard14fff061999-06-22 21:49:07 +00003063 }
3064 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003065 if (cur->childs != NULL) {
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003066 if (format) xmlBufferWriteChar(buf, "\n");
3067 xmlNodeListDump(buf, doc, cur->childs, level + 1, format);
3068 if ((xmlIndentTreeOutput) && (format))
3069 for (i = 0;i < level;i++)
3070 xmlBufferWriteChar(buf, " ");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003071 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003072 xmlBufferWriteChar(buf, "</");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003073 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003074 xmlBufferWriteCHAR(buf, cur->ns->prefix);
3075 xmlBufferWriteChar(buf, ":");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003076 }
3077
Daniel Veillard5099ae81999-04-21 20:12:07 +00003078 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003079 xmlBufferWriteChar(buf, ">");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003080}
3081
Daniel Veillard97b58771998-10-20 06:14:16 +00003082/**
3083 * xmlDocContentDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003084 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003085 * @cur: the document
3086 *
3087 * Dump an XML document.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003088 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003089static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00003090xmlDocContentDump(xmlBufferPtr buf, xmlDocPtr cur) {
Daniel Veillardbe70ff71999-07-05 16:50:46 +00003091 xmlBufferWriteChar(buf, "<?xml version=");
3092 if (cur->version != NULL)
3093 xmlBufferWriteQuotedString(buf, cur->version);
3094 else
3095 xmlBufferWriteChar(buf, "\"1.0\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003096 if (cur->encoding != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00003097 xmlBufferWriteChar(buf, " encoding=");
3098 xmlBufferWriteQuotedString(buf, cur->encoding);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003099 }
3100 switch (cur->standalone) {
3101 case 0:
Daniel Veillard5099ae81999-04-21 20:12:07 +00003102 xmlBufferWriteChar(buf, " standalone=\"no\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003103 break;
3104 case 1:
Daniel Veillard5099ae81999-04-21 20:12:07 +00003105 xmlBufferWriteChar(buf, " standalone=\"yes\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003106 break;
3107 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003108 xmlBufferWriteChar(buf, "?>\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003109 if (cur->intSubset != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00003110 xmlDtdDump(buf, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003111 if (cur->root != NULL) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00003112 xmlNodePtr child = cur->root;
3113
Daniel Veillard260a68f1998-08-13 03:39:55 +00003114 /* global namespace definitions, the old way */
3115 if (oldXMLWDcompatibility)
Daniel Veillard5099ae81999-04-21 20:12:07 +00003116 xmlGlobalNsListDump(buf, cur->oldNs);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003117 else
3118 xmlUpgradeOldNs(cur);
Daniel Veillardb96e6431999-08-29 21:02:19 +00003119
3120 while (child != NULL) {
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003121 xmlNodeDump(buf, cur, child, 0, 1);
3122 xmlBufferWriteChar(buf, "\n");
Daniel Veillardb96e6431999-08-29 21:02:19 +00003123 child = child->next;
3124 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003125 }
3126}
3127
Daniel Veillard97b58771998-10-20 06:14:16 +00003128/**
3129 * xmlDocDumpMemory:
3130 * @cur: the document
3131 * @mem: OUT: the memory pointer
3132 * @size: OUT: the memory lenght
3133 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003134 * Dump an XML document in memory and return the xmlChar * and it's size.
Daniel Veillard97b58771998-10-20 06:14:16 +00003135 * It's up to the caller to free the memory.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003136 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003137void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003138xmlDocDumpMemory(xmlDocPtr cur, xmlChar**mem, int *size) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003139 xmlBufferPtr buf;
3140
Daniel Veillard260a68f1998-08-13 03:39:55 +00003141 if (cur == NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003142#ifdef DEBUG_TREE
3143 fprintf(stderr, "xmlDocDumpMemory : document == NULL\n");
3144#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00003145 *mem = NULL;
3146 *size = 0;
3147 return;
3148 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003149 buf = xmlBufferCreate();
3150 if (buf == NULL) {
3151 *mem = NULL;
3152 *size = 0;
3153 return;
3154 }
3155 xmlDocContentDump(buf, cur);
Daniel Veillardb05deb71999-08-10 19:04:08 +00003156 *mem = xmlStrndup(buf->content, buf->use);
Daniel Veillard5099ae81999-04-21 20:12:07 +00003157 *size = buf->use;
Daniel Veillardb05deb71999-08-10 19:04:08 +00003158 xmlBufferFree(buf);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003159}
3160
Daniel Veillard97b58771998-10-20 06:14:16 +00003161/**
3162 * xmlGetDocCompressMode:
3163 * @doc: the document
3164 *
3165 * get the compression ratio for a document, ZLIB based
Daniel Veillard1e346af1999-02-22 10:33:01 +00003166 * Returns 0 (uncompressed) to 9 (max compression)
Daniel Veillard151b1b01998-09-23 00:49:46 +00003167 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003168int
3169 xmlGetDocCompressMode (xmlDocPtr doc) {
Daniel Veillard15a8df41998-09-24 19:15:06 +00003170 if (doc == NULL) return(-1);
3171 return(doc->compression);
3172}
3173
Daniel Veillard97b58771998-10-20 06:14:16 +00003174/**
3175 * xmlSetDocCompressMode:
3176 * @doc: the document
3177 * @mode: the compression ratio
3178 *
3179 * set the compression ratio for a document, ZLIB based
3180 * Correct values: 0 (uncompressed) to 9 (max compression)
3181 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003182void
3183xmlSetDocCompressMode (xmlDocPtr doc, int mode) {
Daniel Veillard15a8df41998-09-24 19:15:06 +00003184 if (doc == NULL) return;
3185 if (mode < 0) doc->compression = 0;
3186 else if (mode > 9) doc->compression = 9;
3187 else doc->compression = mode;
3188}
3189
Daniel Veillard97b58771998-10-20 06:14:16 +00003190/**
3191 * xmlGetCompressMode:
3192 *
3193 * get the default compression mode used, ZLIB based.
Daniel Veillard1e346af1999-02-22 10:33:01 +00003194 * Returns 0 (uncompressed) to 9 (max compression)
Daniel Veillard15a8df41998-09-24 19:15:06 +00003195 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003196int
3197 xmlGetCompressMode(void) {
Daniel Veillard151b1b01998-09-23 00:49:46 +00003198 return(xmlCompressMode);
3199}
Daniel Veillard97b58771998-10-20 06:14:16 +00003200
3201/**
3202 * xmlSetCompressMode:
3203 * @mode: the compression ratio
3204 *
3205 * set the default compression mode used, ZLIB based
3206 * Correct values: 0 (uncompressed) to 9 (max compression)
3207 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003208void
3209xmlSetCompressMode(int mode) {
Daniel Veillard151b1b01998-09-23 00:49:46 +00003210 if (mode < 0) xmlCompressMode = 0;
Daniel Veillard15a8df41998-09-24 19:15:06 +00003211 else if (mode > 9) xmlCompressMode = 9;
Daniel Veillard151b1b01998-09-23 00:49:46 +00003212 else xmlCompressMode = mode;
3213}
3214
Daniel Veillard97b58771998-10-20 06:14:16 +00003215/**
3216 * xmlDocDump:
3217 * @f: the FILE*
3218 * @cur: the document
3219 *
3220 * Dump an XML document to an open FILE.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003221 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003222void
3223xmlDocDump(FILE *f, xmlDocPtr cur) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003224 xmlBufferPtr buf;
3225
Daniel Veillard260a68f1998-08-13 03:39:55 +00003226 if (cur == NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003227#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00003228 fprintf(stderr, "xmlDocDump : document == NULL\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003229#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00003230 return;
3231 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003232 buf = xmlBufferCreate();
3233 if (buf == NULL) return;
3234 xmlDocContentDump(buf, cur);
3235 xmlBufferDump(f, buf);
3236 xmlBufferFree(buf);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003237}
3238
Daniel Veillard97b58771998-10-20 06:14:16 +00003239/**
3240 * xmlSaveFile:
3241 * @filename: the filename
3242 * @cur: the document
3243 *
3244 * Dump an XML document to a file. Will use compression if
3245 * compiled in and enabled.
3246 * returns: the number of file written or -1 in case of failure.
Daniel Veillard151b1b01998-09-23 00:49:46 +00003247 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003248int
3249xmlSaveFile(const char *filename, xmlDocPtr cur) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003250 xmlBufferPtr buf;
Daniel Veillard151b1b01998-09-23 00:49:46 +00003251#ifdef HAVE_ZLIB_H
3252 gzFile zoutput = NULL;
3253 char mode[15];
3254#endif
Daniel Veillardccb09631998-10-27 06:21:04 +00003255 FILE *output = NULL;
Daniel Veillard151b1b01998-09-23 00:49:46 +00003256 int ret;
3257
Daniel Veillard5099ae81999-04-21 20:12:07 +00003258 /*
3259 * save the content to a temp buffer.
3260 */
3261 buf = xmlBufferCreate();
3262 if (buf == NULL) return(0);
3263 xmlDocContentDump(buf, cur);
3264
Daniel Veillard151b1b01998-09-23 00:49:46 +00003265#ifdef HAVE_ZLIB_H
Daniel Veillarddc3dd9d1998-09-24 19:25:54 +00003266 if ((cur->compression > 0) && (cur->compression <= 9)) {
3267 sprintf(mode, "w%d", cur->compression);
Daniel Veillard151b1b01998-09-23 00:49:46 +00003268 zoutput = gzopen(filename, mode);
3269 }
3270 if (zoutput == NULL) {
3271#endif
3272 output = fopen(filename, "w");
3273 if (output == NULL) return(-1);
3274#ifdef HAVE_ZLIB_H
3275 }
Daniel Veillard151b1b01998-09-23 00:49:46 +00003276
Daniel Veillard151b1b01998-09-23 00:49:46 +00003277 if (zoutput != NULL) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003278 ret = gzwrite(zoutput, buf->content, sizeof(xmlChar) * buf->use);
Daniel Veillard151b1b01998-09-23 00:49:46 +00003279 gzclose(zoutput);
Daniel Veillard5099ae81999-04-21 20:12:07 +00003280 } else {
3281#endif
3282 ret = xmlBufferDump(output, buf);
3283 fclose(output);
3284#ifdef HAVE_ZLIB_H
Daniel Veillard151b1b01998-09-23 00:49:46 +00003285 }
3286#endif
Manish Vachharajani5e60f5a1999-05-29 03:04:30 +00003287 xmlBufferFree(buf);
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003288 return(ret * sizeof(xmlChar));
Daniel Veillard151b1b01998-09-23 00:49:46 +00003289}
3290