blob: c8738985b42b8828949f112a8a0b4da619ff30e6 [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
34static CHAR xmlStringText[] = { 't', 'e', 'x', 't', 0 };
35int 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
92xmlNewNs(xmlNodePtr node, const CHAR *href, const CHAR *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
147xmlNewGlobalNs(xmlDocPtr doc, const CHAR *href, const CHAR *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
252xmlNewDtd(xmlDocPtr doc, const CHAR *name,
Daniel Veillard260a68f1998-08-13 03:39:55 +0000253 const CHAR *ExternalID, const CHAR *SystemID) {
254 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
304xmlCreateIntSubset(xmlDocPtr doc, const CHAR *name,
305 const CHAR *ExternalID, const CHAR *SystemID) {
306 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:
375 * @version: CHAR string giving the version of XML "1.0"
376 *
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
380xmlNewDoc(const CHAR *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
455xmlStringLenGetNodeList(xmlDocPtr doc, const CHAR *value, int len) {
456 xmlNodePtr ret = NULL, last = NULL;
457 xmlNodePtr node;
458 CHAR *val;
459 const CHAR *cur = value;
460 const CHAR *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
566xmlStringGetNodeList(xmlDocPtr doc, const CHAR *value) {
Daniel Veillardccb09631998-10-27 06:21:04 +0000567 xmlNodePtr ret = NULL, last = NULL;
568 xmlNodePtr node;
569 CHAR *val;
570 const CHAR *cur = value;
571 const CHAR *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 Veillardbaf4cd51998-10-27 22:56:57 +0000677CHAR *
678xmlNodeListGetString(xmlDocPtr doc, xmlNodePtr list, int inLine) {
Daniel Veillardccb09631998-10-27 06:21:04 +0000679 xmlNodePtr node = list;
680 CHAR *ret = NULL;
681 xmlEntityPtr ent;
682
683 if (list == NULL) return(NULL);
684
685 while (node != NULL) {
686 if (node->type == XML_TEXT_NODE) {
687 if (inLine)
688 ret = xmlStrcat(ret, node->content);
Daniel Veillard14fff061999-06-22 21:49:07 +0000689 else {
690 CHAR *buffer;
691
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 {
706 CHAR buf[2];
707 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
735xmlNewProp(xmlNodePtr node, const CHAR *name, const CHAR *value) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000736 xmlAttrPtr cur;
737
738 if (name == NULL) {
739 fprintf(stderr, "xmlNewProp : name == NULL\n");
740 return(NULL);
741 }
742
743 /*
744 * Allocate a new property and fill the fields.
745 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000746 cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000747 if (cur == NULL) {
748 fprintf(stderr, "xmlNewProp : malloc failed\n");
749 return(NULL);
750 }
751
Daniel Veillard33942841998-10-18 19:12:41 +0000752 cur->type = XML_ATTRIBUTE_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000753 cur->node = node;
Daniel Veillardb96e6431999-08-29 21:02:19 +0000754 cur->ns = NULL;
755 cur->name = xmlStrdup(name);
756 if (value != NULL)
757 cur->val = xmlStringGetNodeList(node->doc, value);
758 else
759 cur->val = NULL;
760#ifndef XML_WITHOUT_CORBA
761 cur->_private = NULL;
762 cur->vepv = NULL;
763#endif
764
765 /*
766 * Add it at the end to preserve parsing order ...
767 */
768 cur->next = NULL;
769 if (node != NULL) {
770 if (node->properties == NULL) {
771 node->properties = cur;
772 } else {
773 xmlAttrPtr prev = node->properties;
774
775 while (prev->next != NULL) prev = prev->next;
776 prev->next = cur;
777 }
778 }
779 return(cur);
780}
781
782/**
783 * xmlNewNsProp:
784 * @node: the holding node
785 * @ns: the namespace
786 * @name: the name of the attribute
787 * @value: the value of the attribute
788 *
789 * Create a new property tagged with a namespace and carried by a node.
790 * Returns a pointer to the attribute
791 */
792xmlAttrPtr
793xmlNewNsProp(xmlNodePtr node, xmlNsPtr ns, const CHAR *name,
794 const CHAR *value) {
795 xmlAttrPtr cur;
796
797 if (name == NULL) {
798 fprintf(stderr, "xmlNewProp : name == NULL\n");
799 return(NULL);
800 }
801
802 /*
803 * Allocate a new property and fill the fields.
804 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000805 cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr));
Daniel Veillardb96e6431999-08-29 21:02:19 +0000806 if (cur == NULL) {
807 fprintf(stderr, "xmlNewProp : malloc failed\n");
808 return(NULL);
809 }
810
811 cur->type = XML_ATTRIBUTE_NODE;
812 cur->node = node;
813 cur->ns = ns;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000814 cur->name = xmlStrdup(name);
815 if (value != NULL)
Daniel Veillardccb09631998-10-27 06:21:04 +0000816 cur->val = xmlStringGetNodeList(node->doc, value);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000817 else
Daniel Veillardccb09631998-10-27 06:21:04 +0000818 cur->val = NULL;
Daniel Veillard27d88741999-05-29 11:51:49 +0000819#ifndef XML_WITHOUT_CORBA
Daniel Veillard27fb0751998-10-17 06:47:46 +0000820 cur->_private = NULL;
821 cur->vepv = NULL;
822#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000823
824 /*
825 * Add it at the end to preserve parsing order ...
826 */
827 cur->next = NULL;
828 if (node != NULL) {
829 if (node->properties == NULL) {
830 node->properties = cur;
831 } else {
832 xmlAttrPtr prev = node->properties;
833
834 while (prev->next != NULL) prev = prev->next;
835 prev->next = cur;
836 }
837 }
838 return(cur);
839}
840
Daniel Veillard97b58771998-10-20 06:14:16 +0000841/**
Daniel Veillardccb09631998-10-27 06:21:04 +0000842 * xmlNewDocProp:
843 * @doc: the document
844 * @name: the name of the attribute
845 * @value: the value of the attribute
846 *
847 * Create a new property carried by a document.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000848 * Returns a pointer to the attribute
Daniel Veillardccb09631998-10-27 06:21:04 +0000849 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000850xmlAttrPtr
851xmlNewDocProp(xmlDocPtr doc, const CHAR *name, const CHAR *value) {
Daniel Veillardccb09631998-10-27 06:21:04 +0000852 xmlAttrPtr cur;
853
854 if (name == NULL) {
855 fprintf(stderr, "xmlNewProp : name == NULL\n");
856 return(NULL);
857 }
858
859 /*
860 * Allocate a new property and fill the fields.
861 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000862 cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr));
Daniel Veillardccb09631998-10-27 06:21:04 +0000863 if (cur == NULL) {
864 fprintf(stderr, "xmlNewProp : malloc failed\n");
865 return(NULL);
866 }
867
868 cur->type = XML_ATTRIBUTE_NODE;
869 cur->node = NULL;
870 cur->name = xmlStrdup(name);
871 if (value != NULL)
872 cur->val = xmlStringGetNodeList(doc, value);
873 else
874 cur->val = NULL;
Daniel Veillard27d88741999-05-29 11:51:49 +0000875#ifndef XML_WITHOUT_CORBA
Daniel Veillardccb09631998-10-27 06:21:04 +0000876 cur->_private = NULL;
877 cur->vepv = NULL;
878#endif
879
880 cur->next = NULL;
881 return(cur);
882}
883
884/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000885 * xmlFreePropList:
886 * @cur: the first property in the list
887 *
888 * Free a property and all its siblings, all the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000889 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000890void
891xmlFreePropList(xmlAttrPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000892 xmlAttrPtr next;
893 if (cur == NULL) {
894 fprintf(stderr, "xmlFreePropList : property == NULL\n");
895 return;
896 }
897 while (cur != NULL) {
898 next = cur->next;
899 xmlFreeProp(cur);
900 cur = next;
901 }
902}
903
Daniel Veillard97b58771998-10-20 06:14:16 +0000904/**
905 * xmlFreeProp:
906 * @cur: the first property in the list
907 *
908 * Free one property, all the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000909 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000910void
911xmlFreeProp(xmlAttrPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000912 if (cur == NULL) {
913 fprintf(stderr, "xmlFreeProp : property == NULL\n");
914 return;
915 }
Daniel Veillard6454aec1999-09-02 22:04:43 +0000916 if (cur->name != NULL) xmlFree((char *) cur->name);
Daniel Veillardccb09631998-10-27 06:21:04 +0000917 if (cur->val != NULL) xmlFreeNodeList(cur->val);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000918 memset(cur, -1, sizeof(xmlAttr));
Daniel Veillard6454aec1999-09-02 22:04:43 +0000919 xmlFree(cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000920}
921
Daniel Veillard97b58771998-10-20 06:14:16 +0000922/**
Daniel Veillardb96e6431999-08-29 21:02:19 +0000923 * xmlNewPI:
924 * @name: the processing instruction name
925 * @content: the PI content
926 *
927 * Creation of a processing instruction element.
928 * Returns a pointer to the new node object.
929 */
930xmlNodePtr
931xmlNewPI(const CHAR *name, const CHAR *content) {
932 xmlNodePtr cur;
933
934 if (name == NULL) {
935 fprintf(stderr, "xmlNewPI : name == NULL\n");
936 return(NULL);
937 }
938
939 /*
940 * Allocate a new node and fill the fields.
941 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000942 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillardb96e6431999-08-29 21:02:19 +0000943 if (cur == NULL) {
944 fprintf(stderr, "xmlNewPI : malloc failed\n");
945 return(NULL);
946 }
947
948 cur->type = XML_PI_NODE;
949 cur->doc = NULL;
950 cur->parent = NULL;
951 cur->next = NULL;
952 cur->prev = NULL;
953 cur->childs = NULL;
954 cur->last = NULL;
955 cur->properties = NULL;
956 cur->name = xmlStrdup(name);
957 cur->ns = NULL;
958 cur->nsDef = NULL;
959 if (content != NULL)
960 cur->content = xmlStrdup(content);
961 else
962 cur->content = NULL;
963#ifndef XML_WITHOUT_CORBA
964 cur->_private = NULL;
965 cur->vepv = NULL;
966#endif
967 return(cur);
968}
969
970/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000971 * xmlNewNode:
972 * @ns: namespace if any
973 * @name: the node name
Daniel Veillard97b58771998-10-20 06:14:16 +0000974 *
975 * Creation of a new node element. @ns and @content are optionnal (NULL).
Daniel Veillardccb09631998-10-27 06:21:04 +0000976 * If content is non NULL, a child list containing the TEXTs and
977 * ENTITY_REFs node will be created.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000978 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000979 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000980xmlNodePtr
981xmlNewNode(xmlNsPtr ns, const CHAR *name) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000982 xmlNodePtr cur;
983
984 if (name == NULL) {
985 fprintf(stderr, "xmlNewNode : name == NULL\n");
986 return(NULL);
987 }
988
989 /*
990 * Allocate a new node and fill the fields.
991 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000992 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000993 if (cur == NULL) {
994 fprintf(stderr, "xmlNewNode : malloc failed\n");
995 return(NULL);
996 }
997
Daniel Veillard33942841998-10-18 19:12:41 +0000998 cur->type = XML_ELEMENT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000999 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001000 cur->parent = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001001 cur->next = NULL;
1002 cur->prev = NULL;
1003 cur->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001004 cur->last = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001005 cur->properties = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001006 cur->name = xmlStrdup(name);
1007 cur->ns = ns;
1008 cur->nsDef = NULL;
Daniel Veillardccb09631998-10-27 06:21:04 +00001009 cur->content = NULL;
Daniel Veillard27d88741999-05-29 11:51:49 +00001010#ifndef XML_WITHOUT_CORBA
Daniel Veillard27fb0751998-10-17 06:47:46 +00001011 cur->_private = NULL;
1012 cur->vepv = NULL;
1013#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001014 return(cur);
1015}
1016
Daniel Veillard97b58771998-10-20 06:14:16 +00001017/**
1018 * xmlNewDocNode:
1019 * @doc: the document
1020 * @ns: namespace if any
1021 * @name: the node name
1022 * @content: the text content if any
1023 *
1024 * Creation of a new node element within a document. @ns and @content
1025 * are optionnal (NULL).
Daniel Veillard1e346af1999-02-22 10:33:01 +00001026 * Returns a pointer to the new node object.
Daniel Veillard97b58771998-10-20 06:14:16 +00001027 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001028xmlNodePtr
1029xmlNewDocNode(xmlDocPtr doc, xmlNsPtr ns,
Daniel Veillard15b75af1999-07-26 16:42:37 +00001030 const CHAR *name, const CHAR *content) {
Daniel Veillard0bef1311998-10-14 02:36:47 +00001031 xmlNodePtr cur;
1032
Daniel Veillardccb09631998-10-27 06:21:04 +00001033 cur = xmlNewNode(ns, name);
1034 if (cur != NULL) {
1035 cur->doc = doc;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001036 if (content != NULL) {
Daniel Veillardccb09631998-10-27 06:21:04 +00001037 cur->childs = xmlStringGetNodeList(doc, content);
Daniel Veillard1e346af1999-02-22 10:33:01 +00001038 UPDATE_LAST_CHILD(cur)
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001039 }
Daniel Veillardccb09631998-10-27 06:21:04 +00001040 }
Daniel Veillard0bef1311998-10-14 02:36:47 +00001041 return(cur);
1042}
1043
1044
Daniel Veillard97b58771998-10-20 06:14:16 +00001045/**
1046 * xmlNewText:
1047 * @content: the text content
1048 *
1049 * Creation of a new text node.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001050 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001051 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001052xmlNodePtr
1053xmlNewText(const CHAR *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001054 xmlNodePtr cur;
1055
1056 /*
1057 * Allocate a new node and fill the fields.
1058 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001059 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillard260a68f1998-08-13 03:39:55 +00001060 if (cur == NULL) {
1061 fprintf(stderr, "xmlNewText : malloc failed\n");
1062 return(NULL);
1063 }
1064
Daniel Veillard33942841998-10-18 19:12:41 +00001065 cur->type = XML_TEXT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001066 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001067 cur->parent = NULL;
1068 cur->next = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001069 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001070 cur->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001071 cur->last = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001072 cur->properties = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001073 cur->type = XML_TEXT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001074 cur->name = xmlStrdup(xmlStringText);
1075 cur->ns = NULL;
1076 cur->nsDef = NULL;
1077 if (content != NULL)
1078 cur->content = xmlStrdup(content);
1079 else
1080 cur->content = NULL;
1081 return(cur);
1082}
1083
Daniel Veillard97b58771998-10-20 06:14:16 +00001084/**
Daniel Veillardccb09631998-10-27 06:21:04 +00001085 * xmlNewReference:
1086 * @doc: the document
1087 * @name: the reference name, or the reference string with & and ;
1088 *
1089 * Creation of a new reference node.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001090 * Returns a pointer to the new node object.
Daniel Veillardccb09631998-10-27 06:21:04 +00001091 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001092xmlNodePtr
1093xmlNewReference(xmlDocPtr doc, const CHAR *name) {
Daniel Veillardccb09631998-10-27 06:21:04 +00001094 xmlNodePtr cur;
1095 xmlEntityPtr ent;
1096
1097 /*
1098 * Allocate a new node and fill the fields.
1099 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001100 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillardccb09631998-10-27 06:21:04 +00001101 if (cur == NULL) {
1102 fprintf(stderr, "xmlNewText : malloc failed\n");
1103 return(NULL);
1104 }
1105
1106 cur->type = XML_ENTITY_REF_NODE;
Daniel Veillard10c6a8f1998-10-28 01:00:12 +00001107 cur->doc = doc;
Daniel Veillardccb09631998-10-27 06:21:04 +00001108 cur->parent = NULL;
1109 cur->next = NULL;
1110 cur->prev = NULL;
1111 cur->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001112 cur->last = NULL;
Daniel Veillardccb09631998-10-27 06:21:04 +00001113 cur->properties = NULL;
1114 if (name[0] == '&') {
1115 int len;
1116 name++;
1117 len = xmlStrlen(name);
1118 if (name[len - 1] == ';')
1119 cur->name = xmlStrndup(name, len - 1);
1120 else
1121 cur->name = xmlStrndup(name, len);
1122 } else
1123 cur->name = xmlStrdup(name);
1124 cur->ns = NULL;
1125 cur->nsDef = NULL;
1126
1127 ent = xmlGetDocEntity(doc, cur->name);
1128 if (ent != NULL)
1129 cur->content = ent->content;
1130 else
1131 cur->content = NULL;
1132 return(cur);
1133}
1134
1135/**
Daniel Veillard97b58771998-10-20 06:14:16 +00001136 * xmlNewDocText:
1137 * @doc: the document
1138 * @content: the text content
1139 *
1140 * Creation of a new text node within a document.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001141 * Returns a pointer to the new node object.
Daniel Veillard97b58771998-10-20 06:14:16 +00001142 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001143xmlNodePtr
1144xmlNewDocText(xmlDocPtr doc, const CHAR *content) {
Daniel Veillard0bef1311998-10-14 02:36:47 +00001145 xmlNodePtr cur;
1146
1147 cur = xmlNewText(content);
1148 if (cur != NULL) cur->doc = doc;
1149 return(cur);
1150}
1151
Daniel Veillard97b58771998-10-20 06:14:16 +00001152/**
Daniel Veillardccb09631998-10-27 06:21:04 +00001153 * xmlNewTextLen:
Daniel Veillard97b58771998-10-20 06:14:16 +00001154 * @content: the text content
1155 * @len: the text len.
1156 *
1157 * Creation of a new text node with an extra parameter for the content's lenght
Daniel Veillard1e346af1999-02-22 10:33:01 +00001158 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001159 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001160xmlNodePtr
1161xmlNewTextLen(const CHAR *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001162 xmlNodePtr cur;
1163
1164 /*
1165 * Allocate a new node and fill the fields.
1166 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001167 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillard260a68f1998-08-13 03:39:55 +00001168 if (cur == NULL) {
1169 fprintf(stderr, "xmlNewText : malloc failed\n");
1170 return(NULL);
1171 }
1172
Daniel Veillard33942841998-10-18 19:12:41 +00001173 cur->type = XML_TEXT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001174 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001175 cur->parent = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001176 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001177 cur->next = NULL;
1178 cur->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001179 cur->last = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001180 cur->properties = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001181 cur->type = XML_TEXT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001182 cur->name = xmlStrdup(xmlStringText);
1183 cur->ns = NULL;
1184 cur->nsDef = NULL;
1185 if (content != NULL)
1186 cur->content = xmlStrndup(content, len);
1187 else
1188 cur->content = NULL;
1189 return(cur);
1190}
1191
Daniel Veillard97b58771998-10-20 06:14:16 +00001192/**
1193 * xmlNewDocTextLen:
1194 * @doc: the document
1195 * @content: the text content
1196 * @len: the text len.
1197 *
1198 * Creation of a new text node with an extra content lenght parameter. The
1199 * text node pertain to a given document.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001200 * Returns a pointer to the new node object.
Daniel Veillard97b58771998-10-20 06:14:16 +00001201 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001202xmlNodePtr
1203xmlNewDocTextLen(xmlDocPtr doc, const CHAR *content, int len) {
Daniel Veillard0bef1311998-10-14 02:36:47 +00001204 xmlNodePtr cur;
1205
1206 cur = xmlNewTextLen(content, len);
1207 if (cur != NULL) cur->doc = doc;
1208 return(cur);
1209}
1210
Daniel Veillard97b58771998-10-20 06:14:16 +00001211/**
1212 * xmlNewComment:
1213 * @content: the comment content
1214 *
1215 * Creation of a new node containing a comment.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001216 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001217 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001218xmlNodePtr
Daniel Veillard517752b1999-04-05 12:20:10 +00001219xmlNewComment(const CHAR *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001220 xmlNodePtr cur;
1221
1222 /*
1223 * Allocate a new node and fill the fields.
1224 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001225 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillard260a68f1998-08-13 03:39:55 +00001226 if (cur == NULL) {
1227 fprintf(stderr, "xmlNewComment : malloc failed\n");
1228 return(NULL);
1229 }
1230
Daniel Veillard33942841998-10-18 19:12:41 +00001231 cur->type = XML_COMMENT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001232 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001233 cur->parent = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001234 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001235 cur->next = NULL;
1236 cur->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001237 cur->last = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001238 cur->properties = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001239 cur->type = XML_COMMENT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001240 cur->name = xmlStrdup(xmlStringText);
1241 cur->ns = NULL;
1242 cur->nsDef = NULL;
1243 if (content != NULL)
1244 cur->content = xmlStrdup(content);
1245 else
1246 cur->content = NULL;
1247 return(cur);
1248}
1249
Daniel Veillard97b58771998-10-20 06:14:16 +00001250/**
Daniel Veillardb05deb71999-08-10 19:04:08 +00001251 * xmlNewCDataBlock:
1252 * @doc: the document
1253 * @content: the CData block content content
1254 * @len: the length of the block
1255 *
1256 * Creation of a new node containing a CData block.
1257 * Returns a pointer to the new node object.
1258 */
1259xmlNodePtr
1260xmlNewCDataBlock(xmlDocPtr doc, const CHAR *content, int len) {
1261 xmlNodePtr cur;
1262
1263 /*
1264 * Allocate a new node and fill the fields.
1265 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001266 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillardb05deb71999-08-10 19:04:08 +00001267 if (cur == NULL) {
1268 fprintf(stderr, "xmlNewCDataBlock : malloc failed\n");
1269 return(NULL);
1270 }
1271
1272 cur->type = XML_CDATA_SECTION_NODE;
1273 cur->doc = NULL;
1274 cur->parent = NULL;
1275 cur->prev = NULL;
1276 cur->next = NULL;
1277 cur->childs = NULL;
1278 cur->last = NULL;
1279 cur->properties = NULL;
1280 cur->name = xmlStrdup(xmlStringText);
1281 cur->ns = NULL;
1282 cur->nsDef = NULL;
1283 if ((content != NULL) && (len > 0)) {
1284 cur->content = xmlStrndup(content, len);
1285 } else
1286 cur->content = NULL;
1287 return(cur);
1288}
1289
1290/**
Daniel Veillard1e346af1999-02-22 10:33:01 +00001291 * xmlNewDocComment:
Daniel Veillard97b58771998-10-20 06:14:16 +00001292 * @doc: the document
1293 * @content: the comment content
1294 *
1295 * Creation of a new node containing a commentwithin a document.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001296 * Returns a pointer to the new node object.
Daniel Veillard97b58771998-10-20 06:14:16 +00001297 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001298xmlNodePtr
Daniel Veillard517752b1999-04-05 12:20:10 +00001299xmlNewDocComment(xmlDocPtr doc, const CHAR *content) {
Daniel Veillard0bef1311998-10-14 02:36:47 +00001300 xmlNodePtr cur;
1301
1302 cur = xmlNewComment(content);
1303 if (cur != NULL) cur->doc = doc;
1304 return(cur);
1305}
1306
Daniel Veillard97b58771998-10-20 06:14:16 +00001307/**
1308 * xmlNewChild:
1309 * @parent: the parent node
1310 * @ns: a namespace if any
1311 * @name: the name of the child
1312 * @content: the content of the child if any.
1313 *
1314 *
1315 * Creation of a new child element, added at the end of @parent childs list.
Daniel Veillardccb09631998-10-27 06:21:04 +00001316 * @ns and @content parameters are optionnal (NULL). If content is non NULL,
1317 * a child list containing the TEXTs and ENTITY_REFs node will be created.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001318 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001319 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001320xmlNodePtr
1321xmlNewChild(xmlNodePtr parent, xmlNsPtr ns,
Daniel Veillard15b75af1999-07-26 16:42:37 +00001322 const CHAR *name, const CHAR *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001323 xmlNodePtr cur, prev;
1324
1325 if (parent == NULL) {
1326 fprintf(stderr, "xmlNewChild : parent == NULL\n");
1327 return(NULL);
1328 }
1329
1330 if (name == NULL) {
1331 fprintf(stderr, "xmlNewChild : name == NULL\n");
1332 return(NULL);
1333 }
1334
1335 /*
1336 * Allocate a new node
1337 */
1338 if (ns == NULL)
Daniel Veillardccb09631998-10-27 06:21:04 +00001339 cur = xmlNewDocNode(parent->doc, parent->ns, name, content);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001340 else
Daniel Veillardccb09631998-10-27 06:21:04 +00001341 cur = xmlNewDocNode(parent->doc, ns, name, content);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001342 if (cur == NULL) return(NULL);
1343
1344 /*
1345 * add the new element at the end of the childs list.
1346 */
Daniel Veillardccb09631998-10-27 06:21:04 +00001347 cur->type = XML_ELEMENT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001348 cur->parent = parent;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001349 cur->doc = parent->doc;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001350 if (parent->childs == NULL) {
1351 parent->childs = cur;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001352 parent->last = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001353 } else {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001354 prev = parent->last;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001355 prev->next = cur;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001356 cur->prev = prev;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001357 parent->last = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001358 }
1359
1360 return(cur);
1361}
1362
Daniel Veillard97b58771998-10-20 06:14:16 +00001363/**
Daniel Veillardb96e6431999-08-29 21:02:19 +00001364 * xmlAddSibling:
1365 * @cur: the child node
1366 * @elem: the new node
1367 *
1368 * Add a new element to the list of siblings of @cur
1369 * Returns the element or NULL in case of error.
1370 */
1371xmlNodePtr
1372xmlAddSibling(xmlNodePtr cur, xmlNodePtr elem) {
1373 xmlNodePtr parent;
1374
1375 if (cur == NULL) {
1376 fprintf(stderr, "xmlAddSibling : cur == NULL\n");
1377 return(NULL);
1378 }
1379
1380 if (elem == NULL) {
1381 fprintf(stderr, "xmlAddSibling : elem == NULL\n");
1382 return(NULL);
1383 }
1384
1385 if ((cur->doc != NULL) && (elem->doc != NULL) &&
1386 (cur->doc != elem->doc)) {
1387 fprintf(stderr,
1388 "xmlAddSibling: Elements moved to a different document\n");
1389 }
1390
1391 while (cur->next != NULL) cur = cur->next;
1392
1393 if (elem->doc == NULL)
1394 elem->doc = cur->doc; /* the parent may not be linked to a doc ! */
1395
1396 parent = cur->parent;
1397 elem->prev = cur;
1398 elem->next = NULL;
1399 elem->parent = parent;
1400 cur->next = elem;
1401 if (parent != NULL)
1402 parent->last = elem;
1403
1404 return(elem);
1405}
1406
1407/**
Daniel Veillard97b58771998-10-20 06:14:16 +00001408 * xmlAddChild:
1409 * @parent: the parent node
1410 * @cur: the child node
1411 *
1412 * Add a new child element, to @parent, at the end of the child list.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001413 * Returns the child or NULL in case of error.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001414 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001415xmlNodePtr
1416xmlAddChild(xmlNodePtr parent, xmlNodePtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001417 xmlNodePtr prev;
1418
1419 if (parent == NULL) {
1420 fprintf(stderr, "xmladdChild : parent == NULL\n");
1421 return(NULL);
1422 }
1423
1424 if (cur == NULL) {
1425 fprintf(stderr, "xmladdChild : child == NULL\n");
1426 return(NULL);
1427 }
1428
Daniel Veillard0bef1311998-10-14 02:36:47 +00001429 if ((cur->doc != NULL) && (parent->doc != NULL) &&
1430 (cur->doc != parent->doc)) {
1431 fprintf(stderr, "Elements moved to a different document\n");
1432 }
1433
Daniel Veillard260a68f1998-08-13 03:39:55 +00001434 /*
1435 * add the new element at the end of the childs list.
1436 */
1437 cur->parent = parent;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001438 cur->doc = parent->doc; /* the parent may not be linked to a doc ! */
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001439
Daniel Veillardccb09631998-10-27 06:21:04 +00001440 /*
1441 * Handle the case where parent->content != NULL, in that case it will
1442 * create a intermediate TEXT node.
1443 */
1444 if (parent->content != NULL) {
1445 xmlNodePtr text;
1446
1447 text = xmlNewDocText(parent->doc, parent->content);
1448 if (text != NULL) {
1449 text->next = parent->childs;
1450 if (text->next != NULL)
1451 text->next->prev = text;
1452 parent->childs = text;
Daniel Veillard1e346af1999-02-22 10:33:01 +00001453 UPDATE_LAST_CHILD(parent)
Daniel Veillard6454aec1999-09-02 22:04:43 +00001454 xmlFree(parent->content);
Daniel Veillardccb09631998-10-27 06:21:04 +00001455 parent->content = NULL;
1456 }
1457 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00001458 if (parent->childs == NULL) {
1459 parent->childs = cur;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001460 parent->last = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001461 } else {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001462 prev = parent->last;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001463 prev->next = cur;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001464 cur->prev = prev;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001465 parent->last = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001466 }
1467
1468 return(cur);
1469}
1470
Daniel Veillard97b58771998-10-20 06:14:16 +00001471/**
1472 * xmlGetLastChild:
1473 * @parent: the parent node
1474 *
1475 * Search the last child of a node.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001476 * Returns the last child or NULL if none.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001477 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001478xmlNodePtr
1479xmlGetLastChild(xmlNodePtr parent) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001480 if (parent == NULL) {
1481 fprintf(stderr, "xmlGetLastChild : parent == NULL\n");
1482 return(NULL);
1483 }
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001484 return(parent->last);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001485}
1486
Daniel Veillard97b58771998-10-20 06:14:16 +00001487/**
1488 * xmlFreeNodeList:
1489 * @cur: the first node in the list
1490 *
1491 * Free a node and all its siblings, this is a recursive behaviour, all
1492 * the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001493 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001494void
1495xmlFreeNodeList(xmlNodePtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001496 xmlNodePtr next;
1497 if (cur == NULL) {
1498 fprintf(stderr, "xmlFreeNodeList : node == NULL\n");
1499 return;
1500 }
1501 while (cur != NULL) {
1502 next = cur->next;
1503 xmlFreeNode(cur);
1504 cur = next;
1505 }
1506}
1507
Daniel Veillard97b58771998-10-20 06:14:16 +00001508/**
1509 * xmlFreeNode:
1510 * @cur: the node
1511 *
1512 * Free a node, this is a recursive behaviour, all the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001513 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001514void
1515xmlFreeNode(xmlNodePtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001516 if (cur == NULL) {
1517 fprintf(stderr, "xmlFreeNode : node == NULL\n");
1518 return;
1519 }
Daniel Veillardccb09631998-10-27 06:21:04 +00001520 cur->doc = NULL;
1521 cur->parent = NULL;
1522 cur->next = NULL;
1523 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001524 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillardccb09631998-10-27 06:21:04 +00001525 if (cur->properties != NULL) xmlFreePropList(cur->properties);
1526 if (cur->type != XML_ENTITY_REF_NODE)
Daniel Veillard6454aec1999-09-02 22:04:43 +00001527 if (cur->content != NULL) xmlFree(cur->content);
1528 if (cur->name != NULL) xmlFree((char *) cur->name);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001529 if (cur->nsDef != NULL) xmlFreeNsList(cur->nsDef);
1530 memset(cur, -1, sizeof(xmlNode));
Daniel Veillard6454aec1999-09-02 22:04:43 +00001531 xmlFree(cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001532}
1533
Daniel Veillard16253641998-10-28 22:58:05 +00001534/**
1535 * xmlUnlinkNode:
1536 * @cur: the node
1537 *
1538 * Unlink a node from it's current context, the node is not freed
1539 */
1540void
1541xmlUnlinkNode(xmlNodePtr cur) {
1542 if (cur == NULL) {
1543 fprintf(stderr, "xmlUnlinkNode : node == NULL\n");
1544 return;
1545 }
1546 if ((cur->parent != NULL) && (cur->parent->childs == cur))
1547 cur->parent->childs = cur->next;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001548 if ((cur->parent != NULL) && (cur->parent->last == cur))
1549 cur->parent->last = cur->prev;
Daniel Veillard16253641998-10-28 22:58:05 +00001550 if (cur->next != NULL)
1551 cur->next->prev = cur->prev;
1552 if (cur->prev != NULL)
1553 cur->prev->next = cur->next;
1554 cur->next = cur->prev = NULL;
1555 cur->parent = NULL;
1556}
1557
Daniel Veillard260a68f1998-08-13 03:39:55 +00001558/************************************************************************
1559 * *
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001560 * Copy operations *
1561 * *
1562 ************************************************************************/
1563
1564/**
1565 * xmlCopyNamespace:
1566 * @cur: the namespace
1567 *
1568 * Do a copy of the namespace.
1569 *
1570 * Returns: a new xmlNsPtr, or NULL in case of error.
1571 */
1572xmlNsPtr
1573xmlCopyNamespace(xmlNsPtr cur) {
1574 xmlNsPtr ret;
1575
1576 if (cur == NULL) return(NULL);
1577 switch (cur->type) {
1578 case XML_GLOBAL_NAMESPACE:
1579 ret = xmlNewGlobalNs(NULL, cur->href, cur->prefix);
1580 break;
1581 case XML_LOCAL_NAMESPACE:
1582 ret = xmlNewNs(NULL, cur->href, cur->prefix);
1583 break;
1584 default:
1585 fprintf(stderr, "xmlCopyNamespace: unknown type %d\n", cur->type);
1586 return(NULL);
1587 }
1588 return(ret);
1589}
1590
1591/**
1592 * xmlCopyNamespaceList:
1593 * @cur: the first namespace
1594 *
1595 * Do a copy of an namespace list.
1596 *
1597 * Returns: a new xmlNsPtr, or NULL in case of error.
1598 */
1599xmlNsPtr
1600xmlCopyNamespaceList(xmlNsPtr cur) {
1601 xmlNsPtr ret = NULL;
1602 xmlNsPtr p = NULL,q;
1603
1604 while (cur != NULL) {
1605 q = xmlCopyNamespace(cur);
1606 if (p == NULL) {
1607 ret = p = q;
1608 } else {
1609 p->next = q;
1610 p = q;
1611 }
1612 cur = cur->next;
1613 }
1614 return(ret);
1615}
1616
1617/**
1618 * xmlCopyProp:
Daniel Veillardb96e6431999-08-29 21:02:19 +00001619 * @target: the element where the attribute will be grafted
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001620 * @cur: the attribute
1621 *
1622 * Do a copy of the attribute.
1623 *
1624 * Returns: a new xmlAttrPtr, or NULL in case of error.
1625 */
1626xmlAttrPtr
Daniel Veillardb96e6431999-08-29 21:02:19 +00001627xmlCopyProp(xmlNodePtr target, xmlAttrPtr cur) {
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001628 xmlAttrPtr ret;
1629
1630 if (cur == NULL) return(NULL);
1631 if (cur->val != NULL)
1632 ret = xmlNewDocProp(cur->val->doc, cur->name, NULL);
1633 else
1634 ret = xmlNewDocProp(NULL, cur->name, NULL);
1635 if (ret == NULL) return(NULL);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001636
1637 if ((cur->ns != NULL) && (target != NULL)) {
1638 xmlNsPtr ns;
1639
1640 ns = xmlSearchNs(target->doc, target, cur->ns->prefix);
1641 ret->ns = ns;
1642 } else
1643 ret->ns = NULL;
1644
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001645 if (cur->val != NULL)
1646 ret->val = xmlCopyNodeList(cur->val);
1647 return(ret);
1648}
1649
1650/**
1651 * xmlCopyPropList:
Daniel Veillardb96e6431999-08-29 21:02:19 +00001652 * @target: the element where the attributes will be grafted
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001653 * @cur: the first attribute
1654 *
1655 * Do a copy of an attribute list.
1656 *
1657 * Returns: a new xmlAttrPtr, or NULL in case of error.
1658 */
1659xmlAttrPtr
Daniel Veillardb96e6431999-08-29 21:02:19 +00001660xmlCopyPropList(xmlNodePtr target, xmlAttrPtr cur) {
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001661 xmlAttrPtr ret = NULL;
1662 xmlAttrPtr p = NULL,q;
1663
1664 while (cur != NULL) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00001665 q = xmlCopyProp(target, cur);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001666 if (p == NULL) {
1667 ret = p = q;
1668 } else {
1669 p->next = q;
1670 p = q;
1671 }
1672 cur = cur->next;
1673 }
1674 return(ret);
1675}
1676
1677/*
1678 * NOTE about the CopyNode operations !
1679 *
1680 * They are splitted into external and internal parts for one
1681 * tricky reason: namespaces. Doing a direct copy of a node
1682 * say RPM:Copyright without changing the namespace pointer to
1683 * something else can produce stale links. One way to do it is
1684 * to keep a reference counter but this doesn't work as soon
1685 * as one move the element or the subtree out of the scope of
1686 * the existing namespace. The actual solution seems to add
1687 * a copy of the namespace at the top of the copied tree if
1688 * not available in the subtree.
1689 * Hence two functions, the public front-end call the inner ones
1690 */
1691
1692static xmlNodePtr
1693xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent);
1694
1695static xmlNodePtr
1696xmlStaticCopyNode(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent,
1697 int recursive) {
1698 xmlNodePtr ret;
1699
1700 if (node == NULL) return(NULL);
1701 /*
1702 * Allocate a new node and fill the fields.
1703 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001704 ret = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001705 if (ret == NULL) {
1706 fprintf(stderr, "xmlStaticCopyNode : malloc failed\n");
1707 return(NULL);
1708 }
1709
1710 ret->type = node->type;
1711 ret->doc = doc;
1712 ret->parent = parent;
1713 ret->next = NULL;
1714 ret->prev = NULL;
1715 ret->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001716 ret->last = NULL;
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001717 ret->properties = NULL;
1718 if (node->name != NULL)
1719 ret->name = xmlStrdup(node->name);
1720 else
1721 ret->name = NULL;
1722 ret->ns = NULL;
1723 ret->nsDef = NULL;
1724 if ((node->content != NULL) && (node->type != XML_ENTITY_REF_NODE))
1725 ret->content = xmlStrdup(node->content);
1726 else
1727 ret->content = NULL;
Daniel Veillard27d88741999-05-29 11:51:49 +00001728#ifndef XML_WITHOUT_CORBA
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001729 ret->_private = NULL;
1730 ret->vepv = NULL;
1731#endif
1732 if (parent != NULL)
1733 xmlAddChild(parent, ret);
1734
1735 if (!recursive) return(ret);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001736 if (node->nsDef != NULL)
1737 ret->nsDef = xmlCopyNamespaceList(node->nsDef);
1738
1739 if (node->ns != NULL) {
1740 xmlNsPtr ns;
1741
1742 ns = xmlSearchNs(doc, ret, node->ns->prefix);
1743 if (ns == NULL) {
1744 /*
1745 * Humm, we are copying an element whose namespace is defined
1746 * out of the new tree scope. Search it in the original tree
1747 * and add it at the top of the new tree
1748 */
1749 ns = xmlSearchNs(node->doc, node, node->ns->prefix);
1750 if (ns != NULL) {
1751 xmlNodePtr root = ret;
1752
1753 while (root->parent != NULL) root = root->parent;
1754 xmlNewNs(root, ns->href, ns->prefix);
1755 }
1756 } else {
1757 /*
1758 * reference the existing namespace definition in our own tree.
1759 */
1760 ret->ns = ns;
1761 }
1762 }
Daniel Veillardb96e6431999-08-29 21:02:19 +00001763 if (node->properties != NULL)
1764 ret->properties = xmlCopyPropList(ret, node->properties);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001765 if (node->childs != NULL)
1766 ret->childs = xmlStaticCopyNodeList(node->childs, doc, ret);
Daniel Veillard1e346af1999-02-22 10:33:01 +00001767 UPDATE_LAST_CHILD(ret)
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001768 return(ret);
1769}
1770
1771static xmlNodePtr
1772xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent) {
1773 xmlNodePtr ret = NULL;
1774 xmlNodePtr p = NULL,q;
1775
1776 while (node != NULL) {
1777 q = xmlStaticCopyNode(node, doc, parent, 1);
1778 if (parent == NULL) {
1779 if (ret == NULL) ret = q;
1780 } else {
1781 if (ret == NULL) {
1782 q->prev = NULL;
1783 ret = p = q;
1784 } else {
1785 p->next = q;
1786 q->prev = p;
1787 p = q;
1788 }
1789 }
1790 node = node->next;
1791 }
1792 return(ret);
1793}
1794
1795/**
1796 * xmlCopyNode:
1797 * @node: the node
1798 * @recursive: if 1 do a recursive copy.
1799 *
1800 * Do a copy of the node.
1801 *
1802 * Returns: a new xmlNodePtr, or NULL in case of error.
1803 */
1804xmlNodePtr
1805xmlCopyNode(xmlNodePtr node, int recursive) {
1806 xmlNodePtr ret;
1807
1808 ret = xmlStaticCopyNode(node, NULL, NULL, recursive);
1809 return(ret);
1810}
1811
1812/**
1813 * xmlCopyNodeList:
1814 * @node: the first node in the list.
1815 *
1816 * Do a recursive copy of the node list.
1817 *
1818 * Returns: a new xmlNodePtr, or NULL in case of error.
1819 */
1820xmlNodePtr xmlCopyNodeList(xmlNodePtr node) {
1821 xmlNodePtr ret = xmlStaticCopyNodeList(node, NULL, NULL);
1822 return(ret);
1823}
1824
1825/**
1826 * xmlCopyElement:
1827 * @elem: the element
1828 *
1829 * Do a copy of the element definition.
1830 *
1831 * Returns: a new xmlElementPtr, or NULL in case of error.
1832xmlElementPtr
1833xmlCopyElement(xmlElementPtr elem) {
1834 xmlElementPtr ret;
1835
1836 if (elem == NULL) return(NULL);
1837 ret = xmlNewDocElement(elem->doc, elem->ns, elem->name, elem->content);
1838 if (ret == NULL) return(NULL);
1839 if (!recursive) return(ret);
1840 if (elem->properties != NULL)
1841 ret->properties = xmlCopyPropList(elem->properties);
1842
1843 if (elem->nsDef != NULL)
1844 ret->nsDef = xmlCopyNamespaceList(elem->nsDef);
1845 if (elem->childs != NULL)
1846 ret->childs = xmlCopyElementList(elem->childs);
1847 return(ret);
1848}
1849 */
1850
1851/**
1852 * xmlCopyDtd:
1853 * @dtd: the dtd
1854 *
1855 * Do a copy of the dtd.
1856 *
1857 * Returns: a new xmlDtdPtr, or NULL in case of error.
1858 */
1859xmlDtdPtr
1860xmlCopyDtd(xmlDtdPtr dtd) {
1861 xmlDtdPtr ret;
1862
1863 if (dtd == NULL) return(NULL);
1864 ret = xmlNewDtd(NULL, dtd->name, dtd->ExternalID, dtd->SystemID);
1865 if (ret == NULL) return(NULL);
1866 if (dtd->entities != NULL)
1867 ret->entities = (void *) xmlCopyEntitiesTable(
1868 (xmlEntitiesTablePtr) dtd->entities);
Daniel Veillard1e346af1999-02-22 10:33:01 +00001869 if (dtd->notations != NULL)
1870 ret->notations = (void *) xmlCopyNotationTable(
1871 (xmlNotationTablePtr) dtd->notations);
1872 if (dtd->elements != NULL)
1873 ret->elements = (void *) xmlCopyElementTable(
1874 (xmlElementTablePtr) dtd->elements);
1875 if (dtd->attributes != NULL)
1876 ret->attributes = (void *) xmlCopyAttributeTable(
1877 (xmlAttributeTablePtr) dtd->attributes);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001878 return(ret);
1879}
1880
1881/**
1882 * xmlCopyDoc:
1883 * @doc: the document
1884 * @recursive: if 1 do a recursive copy.
1885 *
1886 * Do a copy of the document info. If recursive, the content tree will
1887 * be copied too as well as Dtd, namespaces and entities.
1888 *
1889 * Returns: a new xmlDocPtr, or NULL in case of error.
1890 */
1891xmlDocPtr
1892xmlCopyDoc(xmlDocPtr doc, int recursive) {
1893 xmlDocPtr ret;
1894
1895 if (doc == NULL) return(NULL);
1896 ret = xmlNewDoc(doc->version);
1897 if (ret == NULL) return(NULL);
1898 if (doc->name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +00001899 ret->name = xmlMemStrdup(doc->name);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001900 if (doc->encoding != NULL)
1901 ret->encoding = xmlStrdup(doc->encoding);
1902 ret->compression = doc->compression;
1903 ret->standalone = doc->standalone;
1904 if (!recursive) return(ret);
1905
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001906 if (doc->intSubset != NULL)
1907 ret->intSubset = xmlCopyDtd(doc->intSubset);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001908 if (doc->oldNs != NULL)
1909 ret->oldNs = xmlCopyNamespaceList(doc->oldNs);
1910 if (doc->root != NULL)
1911 ret->root = xmlStaticCopyNodeList(doc->root, ret, NULL);
1912 return(ret);
1913}
1914
1915/************************************************************************
1916 * *
Daniel Veillard260a68f1998-08-13 03:39:55 +00001917 * Content access functions *
1918 * *
1919 ************************************************************************/
1920
Daniel Veillard97b58771998-10-20 06:14:16 +00001921/**
Daniel Veillardb96e6431999-08-29 21:02:19 +00001922 * xmlNodeSetLang:
1923 * @cur: the node being changed
1924 * @lang: the langage description
1925 *
1926 * Searches the language of a node, i.e. the values of the xml:lang
1927 * attribute or the one carried by the nearest ancestor.
1928 *
1929 * Returns a pointer to the lang value, or NULL if not found
1930 */
1931void
1932xmlNodeSetLang(xmlNodePtr cur, const CHAR *lang) {
1933 /* TODO xmlNodeSetLang check against the production [33] LanguageID */
1934 xmlSetProp(cur, BAD_CAST "xml:lang", lang);
1935}
1936
1937/**
1938 * xmlNodeGetLang:
1939 * @cur: the node being checked
1940 *
1941 * Searches the language of a node, i.e. the values of the xml:lang
1942 * attribute or the one carried by the nearest ancestor.
1943 *
1944 * Returns a pointer to the lang value, or NULL if not found
1945 */
1946const CHAR *
1947xmlNodeGetLang(xmlNodePtr cur) {
1948 const CHAR *lang;
1949
1950 while (cur != NULL) {
1951 lang = xmlGetProp(cur, BAD_CAST "xml:lang");
1952 if (lang != NULL)
1953 return(lang);
1954 cur = cur->parent;
1955 }
1956 return(NULL);
1957}
1958
1959/**
Daniel Veillard16253641998-10-28 22:58:05 +00001960 * xmlNodeGetContent:
1961 * @cur: the node being read
1962 *
1963 * Read the value of a node, this can be either the text carried
1964 * directly by this node if it's a TEXT node or the aggregate string
1965 * of the values carried by this node child's (TEXT and ENTITY_REF).
1966 * Entity references are substitued.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001967 * Returns a new CHAR * or NULL if no content is available.
Daniel Veillard5099ae81999-04-21 20:12:07 +00001968 * It's up to the caller to free the memory.
Daniel Veillard16253641998-10-28 22:58:05 +00001969 */
1970CHAR *
1971xmlNodeGetContent(xmlNodePtr cur) {
1972 if (cur == NULL) return(NULL);
1973 switch (cur->type) {
1974 case XML_DOCUMENT_FRAG_NODE:
1975 case XML_ELEMENT_NODE:
1976 return(xmlNodeListGetString(cur->doc, cur->childs, 1));
1977 break;
Daniel Veillardb96e6431999-08-29 21:02:19 +00001978 case XML_ATTRIBUTE_NODE: {
1979 xmlAttrPtr attr = (xmlAttrPtr) cur;
1980 if (attr->node != NULL)
1981 return(xmlNodeListGetString(attr->node->doc, attr->val, 1));
1982 else
1983 return(xmlNodeListGetString(NULL, attr->val, 1));
1984 break;
1985 }
1986 case XML_PI_NODE:
1987 if (cur->content != NULL)
1988 return(xmlStrdup(cur->content));
1989 return(NULL);
Daniel Veillard16253641998-10-28 22:58:05 +00001990 case XML_ENTITY_REF_NODE:
1991 case XML_ENTITY_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00001992 case XML_COMMENT_NODE:
1993 case XML_DOCUMENT_NODE:
1994 case XML_DOCUMENT_TYPE_NODE:
1995 case XML_NOTATION_NODE:
1996 return(NULL);
Daniel Veillardb05deb71999-08-10 19:04:08 +00001997 case XML_CDATA_SECTION_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00001998 case XML_TEXT_NODE:
1999 if (cur->content != NULL)
2000 return(xmlStrdup(cur->content));
2001 return(NULL);
2002 }
2003 return(NULL);
2004}
2005
2006/**
Daniel Veillard97b58771998-10-20 06:14:16 +00002007 * xmlNodeSetContent:
2008 * @cur: the node being modified
2009 * @content: the new value of the content
2010 *
2011 * Replace the content of a node.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002012 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002013void
2014xmlNodeSetContent(xmlNodePtr cur, const CHAR *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002015 if (cur == NULL) {
2016 fprintf(stderr, "xmlNodeSetContent : node == NULL\n");
2017 return;
2018 }
Daniel Veillard16253641998-10-28 22:58:05 +00002019 switch (cur->type) {
2020 case XML_DOCUMENT_FRAG_NODE:
2021 case XML_ELEMENT_NODE:
2022 if (cur->content != NULL) {
Daniel Veillard6454aec1999-09-02 22:04:43 +00002023 xmlFree(cur->content);
Daniel Veillard16253641998-10-28 22:58:05 +00002024 cur->content = NULL;
2025 }
Daniel Veillard6454aec1999-09-02 22:04:43 +00002026 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillard16253641998-10-28 22:58:05 +00002027 cur->childs = xmlStringGetNodeList(cur->doc, content);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002028 UPDATE_LAST_CHILD(cur)
Daniel Veillard16253641998-10-28 22:58:05 +00002029 break;
2030 case XML_ATTRIBUTE_NODE:
2031 break;
2032 case XML_TEXT_NODE:
2033 case XML_CDATA_SECTION_NODE:
2034 case XML_ENTITY_REF_NODE:
2035 case XML_ENTITY_NODE:
2036 case XML_PI_NODE:
2037 case XML_COMMENT_NODE:
Daniel Veillard6454aec1999-09-02 22:04:43 +00002038 if (cur->content != NULL) xmlFree(cur->content);
2039 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002040 cur->last = cur->childs = NULL;
Daniel Veillard16253641998-10-28 22:58:05 +00002041 if (content != NULL)
2042 cur->content = xmlStrdup(content);
2043 else
2044 cur->content = NULL;
Daniel Veillardb96e6431999-08-29 21:02:19 +00002045 break;
Daniel Veillard16253641998-10-28 22:58:05 +00002046 case XML_DOCUMENT_NODE:
2047 case XML_DOCUMENT_TYPE_NODE:
2048 break;
2049 case XML_NOTATION_NODE:
2050 break;
2051 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002052}
2053
Daniel Veillard97b58771998-10-20 06:14:16 +00002054/**
2055 * xmlNodeSetContentLen:
2056 * @cur: the node being modified
2057 * @content: the new value of the content
2058 * @len: the size of @content
2059 *
2060 * Replace the content of a node.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002061 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002062void
2063xmlNodeSetContentLen(xmlNodePtr cur, const CHAR *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002064 if (cur == NULL) {
Daniel Veillard16253641998-10-28 22:58:05 +00002065 fprintf(stderr, "xmlNodeSetContentLen : node == NULL\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002066 return;
2067 }
Daniel Veillard16253641998-10-28 22:58:05 +00002068 switch (cur->type) {
2069 case XML_DOCUMENT_FRAG_NODE:
2070 case XML_ELEMENT_NODE:
2071 if (cur->content != NULL) {
Daniel Veillard6454aec1999-09-02 22:04:43 +00002072 xmlFree(cur->content);
Daniel Veillard16253641998-10-28 22:58:05 +00002073 cur->content = NULL;
2074 }
Daniel Veillard6454aec1999-09-02 22:04:43 +00002075 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillard16253641998-10-28 22:58:05 +00002076 cur->childs = xmlStringLenGetNodeList(cur->doc, content, len);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002077 UPDATE_LAST_CHILD(cur)
Daniel Veillard16253641998-10-28 22:58:05 +00002078 break;
2079 case XML_ATTRIBUTE_NODE:
2080 break;
2081 case XML_TEXT_NODE:
2082 case XML_CDATA_SECTION_NODE:
2083 case XML_ENTITY_REF_NODE:
2084 case XML_ENTITY_NODE:
2085 case XML_PI_NODE:
2086 case XML_COMMENT_NODE:
Daniel Veillard6454aec1999-09-02 22:04:43 +00002087 if (cur->content != NULL) xmlFree(cur->content);
2088 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002089 cur->childs = cur->last = NULL;
Daniel Veillard16253641998-10-28 22:58:05 +00002090 if (content != NULL)
2091 cur->content = xmlStrndup(content, len);
2092 else
2093 cur->content = NULL;
Daniel Veillardb96e6431999-08-29 21:02:19 +00002094 break;
Daniel Veillard16253641998-10-28 22:58:05 +00002095 case XML_DOCUMENT_NODE:
2096 case XML_DOCUMENT_TYPE_NODE:
2097 break;
2098 case XML_NOTATION_NODE:
Daniel Veillard6454aec1999-09-02 22:04:43 +00002099 if (cur->content != NULL) xmlFree(cur->content);
2100 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002101 cur->childs = cur->last = NULL;
Daniel Veillard16253641998-10-28 22:58:05 +00002102 if (content != NULL)
2103 cur->content = xmlStrndup(content, len);
2104 else
2105 cur->content = NULL;
2106 break;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002107 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002108}
2109
Daniel Veillard97b58771998-10-20 06:14:16 +00002110/**
2111 * xmlNodeAddContentLen:
2112 * @cur: the node being modified
2113 * @content: extra content
2114 * @len: the size of @content
2115 *
2116 * Append the extra substring to the node content.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002117 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002118void
2119xmlNodeAddContentLen(xmlNodePtr cur, const CHAR *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002120 if (cur == NULL) {
Daniel Veillard16253641998-10-28 22:58:05 +00002121 fprintf(stderr, "xmlNodeAddContentLen : node == NULL\n");
2122 return;
2123 }
2124 if (len <= 0) return;
2125 switch (cur->type) {
2126 case XML_DOCUMENT_FRAG_NODE:
2127 case XML_ELEMENT_NODE: {
2128 xmlNodePtr last = NULL, new;
2129
2130 if (cur->childs != NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002131 last = cur->last;
Daniel Veillard16253641998-10-28 22:58:05 +00002132 } else {
2133 if (cur->content != NULL) {
2134 cur->childs = xmlStringGetNodeList(cur->doc, cur->content);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002135 UPDATE_LAST_CHILD(cur)
Daniel Veillard6454aec1999-09-02 22:04:43 +00002136 xmlFree(cur->content);
Daniel Veillard16253641998-10-28 22:58:05 +00002137 cur->content = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002138 last = cur->last;
Daniel Veillard16253641998-10-28 22:58:05 +00002139 }
2140 }
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002141 new = xmlNewTextLen(content, len);
Daniel Veillard16253641998-10-28 22:58:05 +00002142 if (new != NULL) {
2143 xmlAddChild(cur, new);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002144 if ((last != NULL) && (last->next == new)) {
Daniel Veillard16253641998-10-28 22:58:05 +00002145 xmlTextMerge(last, new);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002146 }
Daniel Veillard16253641998-10-28 22:58:05 +00002147 }
2148 break;
2149 }
2150 case XML_ATTRIBUTE_NODE:
2151 break;
2152 case XML_TEXT_NODE:
2153 case XML_CDATA_SECTION_NODE:
2154 case XML_ENTITY_REF_NODE:
2155 case XML_ENTITY_NODE:
2156 case XML_PI_NODE:
2157 case XML_COMMENT_NODE:
2158 if (content != NULL)
2159 cur->content = xmlStrncat(cur->content, content, len);
2160 case XML_DOCUMENT_NODE:
2161 case XML_DOCUMENT_TYPE_NODE:
2162 break;
2163 case XML_NOTATION_NODE:
2164 if (content != NULL)
2165 cur->content = xmlStrncat(cur->content, content, len);
2166 break;
2167 }
2168}
2169
2170/**
2171 * xmlNodeAddContent:
2172 * @cur: the node being modified
2173 * @content: extra content
2174 *
2175 * Append the extra substring to the node content.
2176 */
2177void
2178xmlNodeAddContent(xmlNodePtr cur, const CHAR *content) {
2179 int len;
2180
2181 if (cur == NULL) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002182 fprintf(stderr, "xmlNodeAddContent : node == NULL\n");
2183 return;
2184 }
Daniel Veillard16253641998-10-28 22:58:05 +00002185 if (content == NULL) return;
2186 len = xmlStrlen(content);
2187 xmlNodeAddContentLen(cur, content, len);
2188}
2189
2190/**
2191 * xmlTextMerge:
2192 * @first: the first text node
2193 * @second: the second text node being merged
2194 *
2195 * Merge two text nodes into one
Daniel Veillard1e346af1999-02-22 10:33:01 +00002196 * Returns the first text node augmented
Daniel Veillard16253641998-10-28 22:58:05 +00002197 */
2198xmlNodePtr
2199xmlTextMerge(xmlNodePtr first, xmlNodePtr second) {
2200 if (first == NULL) return(second);
2201 if (second == NULL) return(first);
2202 if (first->type != XML_TEXT_NODE) return(first);
2203 if (second->type != XML_TEXT_NODE) return(first);
2204 xmlNodeAddContent(first, second->content);
2205 xmlUnlinkNode(second);
2206 xmlFreeNode(second);
2207 return(first);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002208}
2209
Daniel Veillard97b58771998-10-20 06:14:16 +00002210/**
Daniel Veillardb96e6431999-08-29 21:02:19 +00002211 * xmlGetNsList:
2212 * @doc: the document
2213 * @node: the current node
2214 *
2215 * Search all the namespace applying to a given element.
2216 * Returns an NULL terminated array of all the xmlNsPtr found
2217 * that need to be freed by the caller or NULL if no
2218 * namespace if defined
2219 */
2220xmlNsPtr *
2221xmlGetNsList(xmlDocPtr doc, xmlNodePtr node) {
2222 xmlNsPtr cur;
2223 xmlNsPtr *ret = NULL;
2224 int nbns = 0;
2225 int maxns = 10;
2226 int i;
2227
2228 while (node != NULL) {
2229 cur = node->nsDef;
2230 while (cur != NULL) {
2231 if (ret == NULL) {
Daniel Veillard6454aec1999-09-02 22:04:43 +00002232 ret = (xmlNsPtr *) xmlMalloc((maxns + 1) * sizeof(xmlNsPtr));
Daniel Veillardb96e6431999-08-29 21:02:19 +00002233 if (ret == NULL) {
2234 fprintf(stderr, "xmlGetNsList : out of memory!\n");
2235 return(NULL);
2236 }
2237 ret[nbns] = NULL;
2238 }
2239 for (i = 0;i < nbns;i++) {
2240 if ((cur->prefix == ret[i]->prefix) ||
2241 (!xmlStrcmp(cur->prefix, ret[i]->prefix))) break;
2242 }
2243 if (i >= nbns) {
2244 if (nbns >= maxns) {
2245 maxns *= 2;
Daniel Veillard6454aec1999-09-02 22:04:43 +00002246 ret = (xmlNsPtr *) xmlRealloc(ret,
Daniel Veillardb96e6431999-08-29 21:02:19 +00002247 (maxns + 1) * sizeof(xmlNsPtr));
2248 if (ret == NULL) {
2249 fprintf(stderr, "xmlGetNsList : realloc failed!\n");
2250 return(NULL);
2251 }
2252 }
2253 ret[nbns++] = cur;
2254 ret[nbns] = NULL;
2255 }
2256
2257 cur = cur->next;
2258 }
2259 node = node->parent;
2260 }
2261 return(ret);
2262}
2263
2264/**
Daniel Veillard97b58771998-10-20 06:14:16 +00002265 * xmlSearchNs:
2266 * @doc: the document
2267 * @node: the current node
2268 * @nameSpace: the namespace string
Daniel Veillard260a68f1998-08-13 03:39:55 +00002269 *
Daniel Veillard97b58771998-10-20 06:14:16 +00002270 * Search a Ns registered under a given name space for a document.
2271 * recurse on the parents until it finds the defined namespace
2272 * or return NULL otherwise.
2273 * @nameSpace can be NULL, this is a search for the default namespace.
Daniel Veillard1e346af1999-02-22 10:33:01 +00002274 * Returns the namespace pointer or NULL.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002275 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002276xmlNsPtr
2277xmlSearchNs(xmlDocPtr doc, xmlNodePtr node, const CHAR *nameSpace) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002278 xmlNsPtr cur;
2279
2280 while (node != NULL) {
2281 cur = node->nsDef;
2282 while (cur != NULL) {
2283 if ((cur->prefix == NULL) && (nameSpace == NULL))
2284 return(cur);
2285 if ((cur->prefix != NULL) && (nameSpace != NULL) &&
2286 (!xmlStrcmp(cur->prefix, nameSpace)))
2287 return(cur);
2288 cur = cur->next;
2289 }
2290 node = node->parent;
2291 }
2292 if (doc != NULL) {
2293 cur = doc->oldNs;
2294 while (cur != NULL) {
2295 if ((cur->prefix != NULL) && (nameSpace != NULL) &&
2296 (!xmlStrcmp(cur->prefix, nameSpace)))
2297 return(cur);
2298 cur = cur->next;
2299 }
2300 }
2301 return(NULL);
2302}
2303
Daniel Veillard97b58771998-10-20 06:14:16 +00002304/**
2305 * xmlSearchNsByHref:
2306 * @doc: the document
2307 * @node: the current node
2308 * @href: the namespace value
2309 *
2310 * Search a Ns aliasing a given URI. Recurse on the parents until it finds
2311 * the defined namespace or return NULL otherwise.
Daniel Veillard1e346af1999-02-22 10:33:01 +00002312 * Returns the namespace pointer or NULL.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002313 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002314xmlNsPtr
2315xmlSearchNsByHref(xmlDocPtr doc, xmlNodePtr node, const CHAR *href) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002316 xmlNsPtr cur;
2317
2318 while (node != NULL) {
2319 cur = node->nsDef;
2320 while (cur != NULL) {
2321 if ((cur->href != NULL) && (href != NULL) &&
2322 (!xmlStrcmp(cur->href, href)))
2323 return(cur);
2324 cur = cur->next;
2325 }
2326 node = node->parent;
2327 }
2328 if (doc != NULL) {
2329 cur = doc->oldNs;
2330 while (cur != NULL) {
2331 if ((cur->href != NULL) && (href != NULL) &&
2332 (!xmlStrcmp(cur->href, href)))
2333 return(cur);
2334 cur = cur->next;
2335 }
2336 }
2337 return(NULL);
2338}
2339
Daniel Veillard97b58771998-10-20 06:14:16 +00002340/**
2341 * xmlGetProp:
2342 * @node: the node
2343 * @name: the attribute name
2344 *
2345 * Search and get the value of an attribute associated to a node
Daniel Veillardccb09631998-10-27 06:21:04 +00002346 * This does the entity substitution.
Daniel Veillard1e346af1999-02-22 10:33:01 +00002347 * Returns the attribute value or NULL if not found.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002348 */
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002349CHAR *xmlGetProp(xmlNodePtr node, const CHAR *name) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002350 xmlAttrPtr prop = node->properties;
2351
2352 while (prop != NULL) {
Daniel Veillard68178931999-02-08 18:34:36 +00002353 if (!xmlStrcmp(prop->name, name)) {
Daniel Veillard6800ef31999-02-08 18:33:22 +00002354 CHAR *ret;
2355
2356 ret = xmlNodeListGetString(node->doc, prop->val, 1);
Daniel Veillardb96e6431999-08-29 21:02:19 +00002357 if (ret == NULL) return(xmlStrdup((CHAR *)""));
Daniel Veillard6800ef31999-02-08 18:33:22 +00002358 return(ret);
Daniel Veillard68178931999-02-08 18:34:36 +00002359 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002360 prop = prop->next;
2361 }
2362 return(NULL);
2363}
2364
Daniel Veillard97b58771998-10-20 06:14:16 +00002365/**
Daniel Veillardccb09631998-10-27 06:21:04 +00002366 * xmlSetProp:
Daniel Veillard97b58771998-10-20 06:14:16 +00002367 * @node: the node
2368 * @name: the attribute name
2369 * @value: the attribute value
2370 *
2371 * Set (or reset) an attribute carried by a node.
Daniel Veillard1e346af1999-02-22 10:33:01 +00002372 * Returns the attribute pointer.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002373 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002374xmlAttrPtr
2375xmlSetProp(xmlNodePtr node, const CHAR *name, const CHAR *value) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002376 xmlAttrPtr prop = node->properties;
2377
2378 while (prop != NULL) {
2379 if (!xmlStrcmp(prop->name, name)) {
Daniel Veillardccb09631998-10-27 06:21:04 +00002380 if (prop->val != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +00002381 xmlFreeNodeList(prop->val);
Daniel Veillardccb09631998-10-27 06:21:04 +00002382 prop->val = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002383 if (value != NULL)
Daniel Veillardccb09631998-10-27 06:21:04 +00002384 prop->val = xmlStringGetNodeList(node->doc, value);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002385 return(prop);
2386 }
2387 prop = prop->next;
2388 }
2389 prop = xmlNewProp(node, name, value);
2390 return(prop);
2391}
2392
Daniel Veillard97b58771998-10-20 06:14:16 +00002393/**
2394 * xmlNodeIsText:
2395 * @node: the node
2396 *
2397 * Is this node a Text node ?
Daniel Veillard1e346af1999-02-22 10:33:01 +00002398 * Returns 1 yes, 0 no
Daniel Veillard260a68f1998-08-13 03:39:55 +00002399 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002400int
2401xmlNodeIsText(xmlNodePtr node) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002402 if (node == NULL) return(0);
2403
Daniel Veillard0bef1311998-10-14 02:36:47 +00002404 if (node->type == XML_TEXT_NODE) return(1);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002405 return(0);
2406}
2407
Daniel Veillard97b58771998-10-20 06:14:16 +00002408/**
Daniel Veillard1e346af1999-02-22 10:33:01 +00002409 * xmlTextConcat:
Daniel Veillard97b58771998-10-20 06:14:16 +00002410 * @node: the node
2411 * @content: the content
2412 * @len: @content lenght
2413 *
2414 * Concat the given string at the end of the existing node content
Daniel Veillard260a68f1998-08-13 03:39:55 +00002415 */
Daniel Veillard97b58771998-10-20 06:14:16 +00002416
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002417void
2418xmlTextConcat(xmlNodePtr node, const CHAR *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002419 if (node == NULL) return;
2420
Daniel Veillard0bef1311998-10-14 02:36:47 +00002421 if (node->type != XML_TEXT_NODE) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002422 fprintf(stderr, "xmlTextConcat: node is not text\n");
2423 return;
2424 }
2425 node->content = xmlStrncat(node->content, content, len);
2426}
2427
2428/************************************************************************
2429 * *
2430 * Output : to a FILE or in memory *
2431 * *
2432 ************************************************************************/
2433
Daniel Veillard5099ae81999-04-21 20:12:07 +00002434#define BASE_BUFFER_SIZE 4000
2435
2436/**
2437 * xmlBufferCreate:
2438 *
2439 * routine to create an XML buffer.
2440 * returns the new structure.
2441 */
2442xmlBufferPtr
2443xmlBufferCreate(void) {
2444 xmlBufferPtr ret;
2445
Daniel Veillard6454aec1999-09-02 22:04:43 +00002446 ret = (xmlBufferPtr) xmlMalloc(sizeof(xmlBuffer));
Daniel Veillard5099ae81999-04-21 20:12:07 +00002447 if (ret == NULL) {
2448 fprintf(stderr, "xmlBufferCreate : out of memory!\n");
2449 return(NULL);
2450 }
2451 ret->use = 0;
2452 ret->size = BASE_BUFFER_SIZE;
Daniel Veillard6454aec1999-09-02 22:04:43 +00002453 ret->content = (CHAR *) xmlMalloc(ret->size * sizeof(CHAR));
Daniel Veillard5099ae81999-04-21 20:12:07 +00002454 if (ret->content == NULL) {
2455 fprintf(stderr, "xmlBufferCreate : out of memory!\n");
Daniel Veillard6454aec1999-09-02 22:04:43 +00002456 xmlFree(ret);
Daniel Veillard5099ae81999-04-21 20:12:07 +00002457 return(NULL);
2458 }
2459 ret->content[0] = 0;
2460 return(ret);
2461}
2462
2463/**
2464 * xmlBufferFree:
2465 * @buf: the buffer to free
2466 *
2467 * Frees an XML buffer.
2468 */
2469void
2470xmlBufferFree(xmlBufferPtr buf) {
2471 if (buf == NULL) {
2472 fprintf(stderr, "xmlBufferFree: buf == NULL\n");
2473 return;
2474 }
2475 if (buf->content == NULL) {
2476 fprintf(stderr, "xmlBufferFree: buf->content == NULL\n");
2477 } else {
2478 memset(buf->content, -1, BASE_BUFFER_SIZE);
Daniel Veillard6454aec1999-09-02 22:04:43 +00002479 xmlFree(buf->content);
Daniel Veillard5099ae81999-04-21 20:12:07 +00002480 }
2481 memset(buf, -1, sizeof(xmlBuffer));
Daniel Veillard6454aec1999-09-02 22:04:43 +00002482 xmlFree(buf);
Daniel Veillard5099ae81999-04-21 20:12:07 +00002483}
2484
2485/**
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002486 * xmlBufferEmpty:
2487 * @buf: the buffer
2488 *
2489 * empty a buffer.
2490 */
2491void
2492xmlBufferEmpty(xmlBufferPtr buf) {
2493 buf->use = 0;
2494 memset(buf->content, -1, buf->size);/* just for debug */
2495}
2496
2497/**
2498 * xmlBufferShrink:
2499 * @buf: the buffer to dump
2500 * @len: the number of CHAR to remove
2501 *
2502 * Remove the beginning of an XML buffer.
2503 *
2504 * Returns the number of CHAR removed, or -1 in case of failure.
2505 */
2506int
2507xmlBufferShrink(xmlBufferPtr buf, int len) {
2508 if (len == 0) return(0);
2509 if (len > buf->use) return(-1);
2510
2511 buf->use -= len;
2512 memmove(buf->content, &buf->content[len], buf->use * sizeof(CHAR));
2513
2514 buf->content[buf->use] = 0;
2515 return(len);
2516}
2517
2518/**
Daniel Veillard5099ae81999-04-21 20:12:07 +00002519 * xmlBufferDump:
2520 * @file: the file output
2521 * @buf: the buffer to dump
2522 *
2523 * Dumps an XML buffer to a FILE *.
2524 * Returns the number of CHAR written
2525 */
2526int
2527xmlBufferDump(FILE *file, xmlBufferPtr buf) {
2528 int ret;
2529
2530 if (buf == NULL) {
2531 fprintf(stderr, "xmlBufferDump: buf == NULL\n");
2532 return(0);
2533 }
2534 if (buf->content == NULL) {
2535 fprintf(stderr, "xmlBufferDump: buf->content == NULL\n");
2536 return(0);
2537 }
2538 if (file == NULL) file = stdout;
2539 ret = fwrite(buf->content, sizeof(CHAR), buf->use, file);
2540 return(ret);
2541}
2542
2543/**
2544 * xmlBufferAdd:
2545 * @buf: the buffer to dump
2546 * @str: the CHAR string
2547 * @len: the number of CHAR to add
2548 *
2549 * Add a string range to an XML buffer.
2550 */
2551void
2552xmlBufferAdd(xmlBufferPtr buf, const CHAR *str, int len) {
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002553 int l;
Daniel Veillard5099ae81999-04-21 20:12:07 +00002554
2555 if (str == NULL) {
2556 fprintf(stderr, "xmlBufferAdd: str == NULL\n");
2557 return;
2558 }
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002559 l = xmlStrlen(str);
2560 if (l < len) len = l;
2561 if (len <= 0) return;
Daniel Veillard5099ae81999-04-21 20:12:07 +00002562
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002563 if (buf->use + len + 10 >= buf->size) {
2564 CHAR *rebuf;
2565
2566 buf->size *= 2;
2567 if (buf->use + len + 10 > buf->size)
2568 buf->size = buf->use + len + 10;
Daniel Veillard6454aec1999-09-02 22:04:43 +00002569 rebuf = (CHAR *) xmlRealloc(buf->content, buf->size * sizeof(CHAR));
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002570 if (rebuf == NULL) {
2571 fprintf(stderr, "xmlBufferAdd : out of memory!\n");
2572 return;
Daniel Veillard5099ae81999-04-21 20:12:07 +00002573 }
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002574 buf->content = rebuf;
Daniel Veillard5099ae81999-04-21 20:12:07 +00002575 }
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002576 memmove(&buf->content[buf->use], str, len);
2577 buf->use += len;
2578 buf->content[buf->use] = 0;
Daniel Veillard5099ae81999-04-21 20:12:07 +00002579}
2580
2581/**
2582 * xmlBufferCat:
2583 * @buf: the buffer to dump
2584 * @str: the CHAR string
2585 *
2586 * Append a zero terminated string to an XML buffer.
2587 */
2588void
2589xmlBufferCat(xmlBufferPtr buf, const CHAR *str) {
2590 const CHAR *cur;
2591
2592 if (str == NULL) {
2593 fprintf(stderr, "xmlBufferAdd: str == NULL\n");
2594 return;
2595 }
2596 for (cur = str;*cur != 0;cur++) {
2597 if (buf->use + 10 >= buf->size) {
2598 CHAR *rebuf;
2599
2600 buf->size *= 2;
Daniel Veillard6454aec1999-09-02 22:04:43 +00002601 rebuf = (CHAR *) xmlRealloc(buf->content, buf->size * sizeof(CHAR));
Daniel Veillard5099ae81999-04-21 20:12:07 +00002602 if (rebuf == NULL) {
2603 fprintf(stderr, "xmlBufferAdd : out of memory!\n");
2604 return;
2605 }
2606 buf->content = rebuf;
2607 }
2608 buf->content[buf->use++] = *cur;
2609 }
2610}
2611
2612/**
2613 * xmlBufferCCat:
2614 * @buf: the buffer to dump
2615 * @str: the C char string
2616 *
2617 * Append a zero terminated C string to an XML buffer.
2618 */
2619void
2620xmlBufferCCat(xmlBufferPtr buf, const char *str) {
2621 const char *cur;
2622
2623 if (str == NULL) {
2624 fprintf(stderr, "xmlBufferAdd: str == NULL\n");
2625 return;
2626 }
2627 for (cur = str;*cur != 0;cur++) {
2628 if (buf->use + 10 >= buf->size) {
2629 CHAR *rebuf;
2630
2631 buf->size *= 2;
Daniel Veillard6454aec1999-09-02 22:04:43 +00002632 rebuf = (CHAR *) xmlRealloc(buf->content, buf->size * sizeof(CHAR));
Daniel Veillard5099ae81999-04-21 20:12:07 +00002633 if (rebuf == NULL) {
2634 fprintf(stderr, "xmlBufferAdd : out of memory!\n");
2635 return;
2636 }
2637 buf->content = rebuf;
2638 }
2639 buf->content[buf->use++] = *cur;
2640 }
2641}
Daniel Veillard260a68f1998-08-13 03:39:55 +00002642
Daniel Veillard97b58771998-10-20 06:14:16 +00002643/**
2644 * xmlBufferWriteCHAR:
Daniel Veillard5099ae81999-04-21 20:12:07 +00002645 * @buf: the XML buffer
Daniel Veillard97b58771998-10-20 06:14:16 +00002646 * @string: the string to add
2647 *
2648 * routine which manage and grows an output buffer. This one add
Daniel Veillard5099ae81999-04-21 20:12:07 +00002649 * CHARs at the end of the buffer.
Daniel Veillard97b58771998-10-20 06:14:16 +00002650 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002651void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002652xmlBufferWriteCHAR(xmlBufferPtr buf, const CHAR *string) {
2653 xmlBufferCat(buf, string);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002654}
2655
Daniel Veillard97b58771998-10-20 06:14:16 +00002656/**
2657 * xmlBufferWriteChar:
Daniel Veillard011b63c1999-06-02 17:44:04 +00002658 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00002659 * @string: the string to add
2660 *
2661 * routine which manage and grows an output buffer. This one add
2662 * C chars at the end of the array.
2663 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002664void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002665xmlBufferWriteChar(xmlBufferPtr buf, const char *string) {
2666 xmlBufferCCat(buf, string);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002667}
2668
Daniel Veillard5099ae81999-04-21 20:12:07 +00002669
Daniel Veillard97b58771998-10-20 06:14:16 +00002670/**
Daniel Veillard011b63c1999-06-02 17:44:04 +00002671 * xmlBufferWriteQuotedString:
2672 * @buf: the XML buffer output
2673 * @string: the string to add
2674 *
2675 * routine which manage and grows an output buffer. This one writes
2676 * a quoted or double quoted CHAR string, checking first if it holds
2677 * quote or double-quotes internally
2678 */
2679void
2680xmlBufferWriteQuotedString(xmlBufferPtr buf, const CHAR *string) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00002681 if (xmlStrchr(string, '"')) {
2682 if (xmlStrchr(string, '\'')) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00002683 fprintf(stderr,
2684 "xmlBufferWriteQuotedString: string contains quote and double-quotes !\n");
2685 }
2686 xmlBufferCCat(buf, "'");
2687 xmlBufferCat(buf, string);
2688 xmlBufferCCat(buf, "'");
2689 } else {
2690 xmlBufferCCat(buf, "\"");
2691 xmlBufferCat(buf, string);
2692 xmlBufferCCat(buf, "\"");
2693 }
2694}
2695
2696
2697/**
Daniel Veillard97b58771998-10-20 06:14:16 +00002698 * xmlGlobalNsDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00002699 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00002700 * @cur: a namespace
2701 *
2702 * Dump a global Namespace, this is the old version based on PIs.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002703 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002704static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002705xmlGlobalNsDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002706 if (cur == NULL) {
2707 fprintf(stderr, "xmlGlobalNsDump : Ns == NULL\n");
2708 return;
2709 }
2710 if (cur->type == XML_GLOBAL_NAMESPACE) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002711 xmlBufferWriteChar(buf, "<?namespace");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002712 if (cur->href != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00002713 xmlBufferWriteChar(buf, " href=");
2714 xmlBufferWriteQuotedString(buf, cur->href);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002715 }
2716 if (cur->prefix != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00002717 xmlBufferWriteChar(buf, " AS=");
2718 xmlBufferWriteQuotedString(buf, cur->prefix);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002719 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00002720 xmlBufferWriteChar(buf, "?>\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002721 }
2722}
2723
Daniel Veillard97b58771998-10-20 06:14:16 +00002724/**
2725 * xmlGlobalNsListDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00002726 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00002727 * @cur: the first namespace
2728 *
2729 * Dump a list of global Namespace, this is the old version based on PIs.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002730 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002731static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002732xmlGlobalNsListDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002733 while (cur != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002734 xmlGlobalNsDump(buf, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002735 cur = cur->next;
2736 }
2737}
2738
Daniel Veillard97b58771998-10-20 06:14:16 +00002739/**
2740 * xmlNsDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00002741 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00002742 * @cur: a namespace
2743 *
Daniel Veillard260a68f1998-08-13 03:39:55 +00002744 * Dump a local Namespace definition.
Daniel Veillard97b58771998-10-20 06:14:16 +00002745 * Should be called in the context of attributes dumps.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002746 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002747static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002748xmlNsDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002749 if (cur == NULL) {
2750 fprintf(stderr, "xmlNsDump : Ns == NULL\n");
2751 return;
2752 }
2753 if (cur->type == XML_LOCAL_NAMESPACE) {
2754 /* Within the context of an element attributes */
2755 if (cur->prefix != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002756 xmlBufferWriteChar(buf, " xmlns:");
2757 xmlBufferWriteCHAR(buf, cur->prefix);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002758 } else
Daniel Veillard5099ae81999-04-21 20:12:07 +00002759 xmlBufferWriteChar(buf, " xmlns");
Daniel Veillard011b63c1999-06-02 17:44:04 +00002760 xmlBufferWriteChar(buf, "=");
2761 xmlBufferWriteQuotedString(buf, cur->href);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002762 }
2763}
2764
Daniel Veillard97b58771998-10-20 06:14:16 +00002765/**
2766 * xmlNsListDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00002767 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00002768 * @cur: the first namespace
2769 *
2770 * Dump a list of local Namespace definitions.
2771 * Should be called in the context of attributes dumps.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002772 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002773static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002774xmlNsListDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002775 while (cur != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002776 xmlNsDump(buf, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002777 cur = cur->next;
2778 }
2779}
2780
Daniel Veillard97b58771998-10-20 06:14:16 +00002781/**
2782 * xmlDtdDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00002783 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00002784 * @doc: the document
2785 *
2786 * Dump the XML document DTD, if any.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002787 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002788static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002789xmlDtdDump(xmlBufferPtr buf, xmlDocPtr doc) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002790 xmlDtdPtr cur = doc->intSubset;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002791
2792 if (cur == NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002793 fprintf(stderr, "xmlDtdDump : no internal subset\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002794 return;
2795 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00002796 xmlBufferWriteChar(buf, "<!DOCTYPE ");
2797 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002798 if (cur->ExternalID != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00002799 xmlBufferWriteChar(buf, " PUBLIC ");
2800 xmlBufferWriteQuotedString(buf, cur->ExternalID);
2801 xmlBufferWriteChar(buf, " ");
2802 xmlBufferWriteQuotedString(buf, cur->SystemID);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002803 } else if (cur->SystemID != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00002804 xmlBufferWriteChar(buf, " SYSTEM ");
2805 xmlBufferWriteQuotedString(buf, cur->SystemID);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002806 }
Daniel Veillard1e346af1999-02-22 10:33:01 +00002807 if ((cur->entities == NULL) && (cur->elements == NULL) &&
2808 (cur->attributes == NULL) && (cur->notations == NULL)) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002809 xmlBufferWriteChar(buf, ">\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002810 return;
2811 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00002812 xmlBufferWriteChar(buf, " [\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002813 if (cur->entities != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00002814 xmlDumpEntitiesTable(buf, (xmlEntitiesTablePtr) cur->entities);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002815 if (cur->notations != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00002816 xmlDumpNotationTable(buf, (xmlNotationTablePtr) cur->notations);
Daniel Veillard3b9def11999-01-31 22:15:06 +00002817 if (cur->elements != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00002818 xmlDumpElementTable(buf, (xmlElementTablePtr) cur->elements);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002819 if (cur->attributes != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00002820 xmlDumpAttributeTable(buf, (xmlAttributeTablePtr) cur->attributes);
2821 xmlBufferWriteChar(buf, "]");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002822
Daniel Veillard5099ae81999-04-21 20:12:07 +00002823 xmlBufferWriteChar(buf, ">\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002824}
2825
Daniel Veillard97b58771998-10-20 06:14:16 +00002826/**
2827 * xmlAttrDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00002828 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00002829 * @doc: the document
2830 * @cur: the attribute pointer
2831 *
2832 * Dump an XML attribute
Daniel Veillard260a68f1998-08-13 03:39:55 +00002833 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002834static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002835xmlAttrDump(xmlBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur) {
Daniel Veillardccb09631998-10-27 06:21:04 +00002836 CHAR *value;
2837
Daniel Veillard260a68f1998-08-13 03:39:55 +00002838 if (cur == NULL) {
2839 fprintf(stderr, "xmlAttrDump : property == NULL\n");
2840 return;
2841 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00002842 xmlBufferWriteChar(buf, " ");
Daniel Veillardb96e6431999-08-29 21:02:19 +00002843 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
2844 xmlBufferWriteCHAR(buf, cur->ns->prefix);
2845 xmlBufferWriteChar(buf, ":");
2846 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00002847 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillardccb09631998-10-27 06:21:04 +00002848 value = xmlNodeListGetString(doc, cur->val, 0);
2849 if (value) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00002850 xmlBufferWriteChar(buf, "=");
2851 xmlBufferWriteQuotedString(buf, value);
Daniel Veillard6454aec1999-09-02 22:04:43 +00002852 xmlFree(value);
Daniel Veillard726c7e31999-02-08 15:13:10 +00002853 } else {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002854 xmlBufferWriteChar(buf, "=\"\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002855 }
2856}
2857
Daniel Veillard97b58771998-10-20 06:14:16 +00002858/**
2859 * xmlAttrListDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00002860 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00002861 * @doc: the document
2862 * @cur: the first attribute pointer
2863 *
2864 * Dump a list of XML attributes
Daniel Veillard260a68f1998-08-13 03:39:55 +00002865 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002866static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002867xmlAttrListDump(xmlBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002868 if (cur == NULL) {
2869 fprintf(stderr, "xmlAttrListDump : property == NULL\n");
2870 return;
2871 }
2872 while (cur != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002873 xmlAttrDump(buf, doc, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002874 cur = cur->next;
2875 }
2876}
2877
Daniel Veillard260a68f1998-08-13 03:39:55 +00002878
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002879static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002880xmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level);
Daniel Veillard97b58771998-10-20 06:14:16 +00002881/**
2882 * xmlNodeListDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00002883 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00002884 * @doc: the document
2885 * @cur: the first node
2886 * @level: the imbrication level for indenting
2887 *
2888 * Dump an XML node list, recursive behaviour,children are printed too.
2889 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002890static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002891xmlNodeListDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level) {
Daniel Veillardccb09631998-10-27 06:21:04 +00002892 int needIndent = 0, i;
2893
Daniel Veillard260a68f1998-08-13 03:39:55 +00002894 if (cur == NULL) {
2895 fprintf(stderr, "xmlNodeListDump : node == NULL\n");
2896 return;
2897 }
2898 while (cur != NULL) {
Daniel Veillardccb09631998-10-27 06:21:04 +00002899 if ((cur->type != XML_TEXT_NODE) &&
2900 (cur->type != XML_ENTITY_REF_NODE)) {
2901 if (!needIndent) {
2902 needIndent = 1;
Daniel Veillard5099ae81999-04-21 20:12:07 +00002903 xmlBufferWriteChar(buf, "\n");
Daniel Veillardccb09631998-10-27 06:21:04 +00002904 }
2905 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00002906 xmlNodeDump(buf, doc, cur, level);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002907 cur = cur->next;
2908 }
Daniel Veillardccb09631998-10-27 06:21:04 +00002909 if ((xmlIndentTreeOutput) && (needIndent))
2910 for (i = 1;i < level;i++)
Daniel Veillard5099ae81999-04-21 20:12:07 +00002911 xmlBufferWriteChar(buf, " ");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002912}
2913
Daniel Veillard97b58771998-10-20 06:14:16 +00002914/**
Daniel Veillardccb09631998-10-27 06:21:04 +00002915 * xmlNodeDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00002916 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00002917 * @doc: the document
2918 * @cur: the current node
2919 * @level: the imbrication level for indenting
2920 *
2921 * Dump an XML node, recursive behaviour,children are printed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002922 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002923static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002924xmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002925 int i;
2926
2927 if (cur == NULL) {
2928 fprintf(stderr, "xmlNodeDump : node == NULL\n");
2929 return;
2930 }
Daniel Veillard0bef1311998-10-14 02:36:47 +00002931 if (cur->type == XML_TEXT_NODE) {
Daniel Veillard14fff061999-06-22 21:49:07 +00002932 if (cur->content != NULL) {
2933 CHAR *buffer;
2934
2935 buffer = xmlEncodeEntitiesReentrant(doc, cur->content);
2936 if (buffer != NULL) {
2937 xmlBufferWriteCHAR(buf, buffer);
Daniel Veillard6454aec1999-09-02 22:04:43 +00002938 xmlFree(buffer);
Daniel Veillard14fff061999-06-22 21:49:07 +00002939 }
2940 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002941 return;
2942 }
Daniel Veillardb96e6431999-08-29 21:02:19 +00002943 if (cur->type == XML_PI_NODE) {
2944 if (cur->content != NULL) {
2945 xmlBufferWriteChar(buf, "<?");
2946 xmlBufferWriteCHAR(buf, cur->name);
2947 if (cur->content != NULL) {
2948 xmlBufferWriteChar(buf, " ");
2949 xmlBufferWriteCHAR(buf, cur->content);
2950 }
2951 xmlBufferWriteChar(buf, "?>\n");
2952 }
2953 return;
2954 }
Daniel Veillard0bef1311998-10-14 02:36:47 +00002955 if (cur->type == XML_COMMENT_NODE) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002956 if (cur->content != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002957 xmlBufferWriteChar(buf, "<!--");
2958 xmlBufferWriteCHAR(buf, cur->content);
Daniel Veillardb96e6431999-08-29 21:02:19 +00002959 xmlBufferWriteChar(buf, "-->\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002960 }
2961 return;
2962 }
Daniel Veillardccb09631998-10-27 06:21:04 +00002963 if (cur->type == XML_ENTITY_REF_NODE) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002964 xmlBufferWriteChar(buf, "&");
2965 xmlBufferWriteCHAR(buf, cur->name);
2966 xmlBufferWriteChar(buf, ";");
Daniel Veillardccb09631998-10-27 06:21:04 +00002967 return;
2968 }
Daniel Veillardb05deb71999-08-10 19:04:08 +00002969 if (cur->type == XML_CDATA_SECTION_NODE) {
2970 xmlBufferWriteChar(buf, "<![CDATA[");
2971 if (cur->content != NULL)
2972 xmlBufferWriteCHAR(buf, cur->content);
2973 xmlBufferWriteChar(buf, "]]>");
2974 return;
2975 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002976 if (xmlIndentTreeOutput)
2977 for (i = 0;i < level;i++)
Daniel Veillard5099ae81999-04-21 20:12:07 +00002978 xmlBufferWriteChar(buf, " ");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002979
Daniel Veillard5099ae81999-04-21 20:12:07 +00002980 xmlBufferWriteChar(buf, "<");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002981 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002982 xmlBufferWriteCHAR(buf, cur->ns->prefix);
2983 xmlBufferWriteChar(buf, ":");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002984 }
2985
Daniel Veillard5099ae81999-04-21 20:12:07 +00002986 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002987 if (cur->nsDef)
Daniel Veillard5099ae81999-04-21 20:12:07 +00002988 xmlNsListDump(buf, cur->nsDef);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002989 if (cur->properties != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00002990 xmlAttrListDump(buf, doc, cur->properties);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002991
2992 if ((cur->content == NULL) && (cur->childs == NULL)) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002993 xmlBufferWriteChar(buf, "/>\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002994 return;
2995 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00002996 xmlBufferWriteChar(buf, ">");
Daniel Veillard14fff061999-06-22 21:49:07 +00002997 if (cur->content != NULL) {
2998 CHAR *buffer;
2999
3000 buffer = xmlEncodeEntitiesReentrant(doc, cur->content);
3001 if (buffer != NULL) {
3002 xmlBufferWriteCHAR(buf, buffer);
Daniel Veillard6454aec1999-09-02 22:04:43 +00003003 xmlFree(buffer);
Daniel Veillard14fff061999-06-22 21:49:07 +00003004 }
3005 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003006 if (cur->childs != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003007 xmlNodeListDump(buf, doc, cur->childs, level + 1);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003008 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003009 xmlBufferWriteChar(buf, "</");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003010 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003011 xmlBufferWriteCHAR(buf, cur->ns->prefix);
3012 xmlBufferWriteChar(buf, ":");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003013 }
3014
Daniel Veillard5099ae81999-04-21 20:12:07 +00003015 xmlBufferWriteCHAR(buf, cur->name);
3016 xmlBufferWriteChar(buf, ">\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003017}
3018
Daniel Veillard97b58771998-10-20 06:14:16 +00003019/**
3020 * xmlDocContentDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003021 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003022 * @cur: the document
3023 *
3024 * Dump an XML document.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003025 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003026static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00003027xmlDocContentDump(xmlBufferPtr buf, xmlDocPtr cur) {
Daniel Veillardbe70ff71999-07-05 16:50:46 +00003028 xmlBufferWriteChar(buf, "<?xml version=");
3029 if (cur->version != NULL)
3030 xmlBufferWriteQuotedString(buf, cur->version);
3031 else
3032 xmlBufferWriteChar(buf, "\"1.0\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003033 if (cur->encoding != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00003034 xmlBufferWriteChar(buf, " encoding=");
3035 xmlBufferWriteQuotedString(buf, cur->encoding);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003036 }
3037 switch (cur->standalone) {
3038 case 0:
Daniel Veillard5099ae81999-04-21 20:12:07 +00003039 xmlBufferWriteChar(buf, " standalone=\"no\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003040 break;
3041 case 1:
Daniel Veillard5099ae81999-04-21 20:12:07 +00003042 xmlBufferWriteChar(buf, " standalone=\"yes\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003043 break;
3044 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003045 xmlBufferWriteChar(buf, "?>\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003046 if (cur->intSubset != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00003047 xmlDtdDump(buf, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003048 if (cur->root != NULL) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00003049 xmlNodePtr child = cur->root;
3050
Daniel Veillard260a68f1998-08-13 03:39:55 +00003051 /* global namespace definitions, the old way */
3052 if (oldXMLWDcompatibility)
Daniel Veillard5099ae81999-04-21 20:12:07 +00003053 xmlGlobalNsListDump(buf, cur->oldNs);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003054 else
3055 xmlUpgradeOldNs(cur);
Daniel Veillardb96e6431999-08-29 21:02:19 +00003056
3057 while (child != NULL) {
3058 xmlNodeDump(buf, cur, child, 0);
3059 child = child->next;
3060 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003061 }
3062}
3063
Daniel Veillard97b58771998-10-20 06:14:16 +00003064/**
3065 * xmlDocDumpMemory:
3066 * @cur: the document
3067 * @mem: OUT: the memory pointer
3068 * @size: OUT: the memory lenght
3069 *
3070 * Dump an XML document in memory and return the CHAR * and it's size.
3071 * It's up to the caller to free the memory.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003072 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003073void
3074xmlDocDumpMemory(xmlDocPtr cur, CHAR**mem, int *size) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003075 xmlBufferPtr buf;
3076
Daniel Veillard260a68f1998-08-13 03:39:55 +00003077 if (cur == NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003078#ifdef DEBUG_TREE
3079 fprintf(stderr, "xmlDocDumpMemory : document == NULL\n");
3080#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00003081 *mem = NULL;
3082 *size = 0;
3083 return;
3084 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003085 buf = xmlBufferCreate();
3086 if (buf == NULL) {
3087 *mem = NULL;
3088 *size = 0;
3089 return;
3090 }
3091 xmlDocContentDump(buf, cur);
Daniel Veillardb05deb71999-08-10 19:04:08 +00003092 *mem = xmlStrndup(buf->content, buf->use);
Daniel Veillard5099ae81999-04-21 20:12:07 +00003093 *size = buf->use;
Daniel Veillardb05deb71999-08-10 19:04:08 +00003094 xmlBufferFree(buf);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003095}
3096
Daniel Veillard97b58771998-10-20 06:14:16 +00003097/**
3098 * xmlGetDocCompressMode:
3099 * @doc: the document
3100 *
3101 * get the compression ratio for a document, ZLIB based
Daniel Veillard1e346af1999-02-22 10:33:01 +00003102 * Returns 0 (uncompressed) to 9 (max compression)
Daniel Veillard151b1b01998-09-23 00:49:46 +00003103 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003104int
3105 xmlGetDocCompressMode (xmlDocPtr doc) {
Daniel Veillard15a8df41998-09-24 19:15:06 +00003106 if (doc == NULL) return(-1);
3107 return(doc->compression);
3108}
3109
Daniel Veillard97b58771998-10-20 06:14:16 +00003110/**
3111 * xmlSetDocCompressMode:
3112 * @doc: the document
3113 * @mode: the compression ratio
3114 *
3115 * set the compression ratio for a document, ZLIB based
3116 * Correct values: 0 (uncompressed) to 9 (max compression)
3117 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003118void
3119xmlSetDocCompressMode (xmlDocPtr doc, int mode) {
Daniel Veillard15a8df41998-09-24 19:15:06 +00003120 if (doc == NULL) return;
3121 if (mode < 0) doc->compression = 0;
3122 else if (mode > 9) doc->compression = 9;
3123 else doc->compression = mode;
3124}
3125
Daniel Veillard97b58771998-10-20 06:14:16 +00003126/**
3127 * xmlGetCompressMode:
3128 *
3129 * get the default compression mode used, ZLIB based.
Daniel Veillard1e346af1999-02-22 10:33:01 +00003130 * Returns 0 (uncompressed) to 9 (max compression)
Daniel Veillard15a8df41998-09-24 19:15:06 +00003131 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003132int
3133 xmlGetCompressMode(void) {
Daniel Veillard151b1b01998-09-23 00:49:46 +00003134 return(xmlCompressMode);
3135}
Daniel Veillard97b58771998-10-20 06:14:16 +00003136
3137/**
3138 * xmlSetCompressMode:
3139 * @mode: the compression ratio
3140 *
3141 * set the default compression mode used, ZLIB based
3142 * Correct values: 0 (uncompressed) to 9 (max compression)
3143 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003144void
3145xmlSetCompressMode(int mode) {
Daniel Veillard151b1b01998-09-23 00:49:46 +00003146 if (mode < 0) xmlCompressMode = 0;
Daniel Veillard15a8df41998-09-24 19:15:06 +00003147 else if (mode > 9) xmlCompressMode = 9;
Daniel Veillard151b1b01998-09-23 00:49:46 +00003148 else xmlCompressMode = mode;
3149}
3150
Daniel Veillard97b58771998-10-20 06:14:16 +00003151/**
3152 * xmlDocDump:
3153 * @f: the FILE*
3154 * @cur: the document
3155 *
3156 * Dump an XML document to an open FILE.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003157 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003158void
3159xmlDocDump(FILE *f, xmlDocPtr cur) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003160 xmlBufferPtr buf;
3161
Daniel Veillard260a68f1998-08-13 03:39:55 +00003162 if (cur == NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003163#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00003164 fprintf(stderr, "xmlDocDump : document == NULL\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003165#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00003166 return;
3167 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003168 buf = xmlBufferCreate();
3169 if (buf == NULL) return;
3170 xmlDocContentDump(buf, cur);
3171 xmlBufferDump(f, buf);
3172 xmlBufferFree(buf);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003173}
3174
Daniel Veillard97b58771998-10-20 06:14:16 +00003175/**
3176 * xmlSaveFile:
3177 * @filename: the filename
3178 * @cur: the document
3179 *
3180 * Dump an XML document to a file. Will use compression if
3181 * compiled in and enabled.
3182 * returns: the number of file written or -1 in case of failure.
Daniel Veillard151b1b01998-09-23 00:49:46 +00003183 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003184int
3185xmlSaveFile(const char *filename, xmlDocPtr cur) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003186 xmlBufferPtr buf;
Daniel Veillard151b1b01998-09-23 00:49:46 +00003187#ifdef HAVE_ZLIB_H
3188 gzFile zoutput = NULL;
3189 char mode[15];
3190#endif
Daniel Veillardccb09631998-10-27 06:21:04 +00003191 FILE *output = NULL;
Daniel Veillard151b1b01998-09-23 00:49:46 +00003192 int ret;
3193
Daniel Veillard5099ae81999-04-21 20:12:07 +00003194 /*
3195 * save the content to a temp buffer.
3196 */
3197 buf = xmlBufferCreate();
3198 if (buf == NULL) return(0);
3199 xmlDocContentDump(buf, cur);
3200
Daniel Veillard151b1b01998-09-23 00:49:46 +00003201#ifdef HAVE_ZLIB_H
Daniel Veillarddc3dd9d1998-09-24 19:25:54 +00003202 if ((cur->compression > 0) && (cur->compression <= 9)) {
3203 sprintf(mode, "w%d", cur->compression);
Daniel Veillard151b1b01998-09-23 00:49:46 +00003204 zoutput = gzopen(filename, mode);
3205 }
3206 if (zoutput == NULL) {
3207#endif
3208 output = fopen(filename, "w");
3209 if (output == NULL) return(-1);
3210#ifdef HAVE_ZLIB_H
3211 }
Daniel Veillard151b1b01998-09-23 00:49:46 +00003212
Daniel Veillard151b1b01998-09-23 00:49:46 +00003213 if (zoutput != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003214 ret = gzwrite(zoutput, buf->content, sizeof(CHAR) * buf->use);
Daniel Veillard151b1b01998-09-23 00:49:46 +00003215 gzclose(zoutput);
Daniel Veillard5099ae81999-04-21 20:12:07 +00003216 } else {
3217#endif
3218 ret = xmlBufferDump(output, buf);
3219 fclose(output);
3220#ifdef HAVE_ZLIB_H
Daniel Veillard151b1b01998-09-23 00:49:46 +00003221 }
3222#endif
Manish Vachharajani5e60f5a1999-05-29 03:04:30 +00003223 xmlBufferFree(buf);
Daniel Veillard151b1b01998-09-23 00:49:46 +00003224 return(ret * sizeof(CHAR));
3225}
3226