blob: 006defeec194ae60d13b5ad82023d7d1c273efaf [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 Veillard151b1b01998-09-23 00:49:46 +00009#include "config.h"
Daniel Veillard260a68f1998-08-13 03:39:55 +000010#include <stdio.h>
11#include <ctype.h>
Seth Alvese7f12e61998-10-01 20:51:15 +000012#include <stdlib.h>
Daniel Veillard260a68f1998-08-13 03:39:55 +000013#include <string.h> /* for memset() only ! */
14
Daniel Veillard151b1b01998-09-23 00:49:46 +000015#ifdef HAVE_ZLIB_H
16#include <zlib.h>
17#endif
18
Daniel Veillard6454aec1999-09-02 22:04:43 +000019#include "xmlmemory.h"
Daniel Veillard260a68f1998-08-13 03:39:55 +000020#include "tree.h"
21#include "entities.h"
Daniel Veillard3b9def11999-01-31 22:15:06 +000022#include "valid.h"
Daniel Veillard260a68f1998-08-13 03:39:55 +000023
24static CHAR xmlStringText[] = { 't', 'e', 'x', 't', 0 };
25int oldXMLWDcompatibility = 0;
26int xmlIndentTreeOutput = 1;
27
Daniel Veillard15a8df41998-09-24 19:15:06 +000028static int xmlCompressMode = 0;
29
Daniel Veillard39a1f9a1999-01-17 19:11:59 +000030#define UPDATE_LAST_CHILD(n) if ((n) != NULL) { \
31 xmlNodePtr ulccur = (n)->childs; \
32 if (ulccur == NULL) { \
33 (n)->last = NULL; \
34 } else { \
35 while (ulccur->next != NULL) ulccur = ulccur->next; \
36 (n)->last = ulccur; \
Daniel Veillard1e346af1999-02-22 10:33:01 +000037}}
Daniel Veillard39a1f9a1999-01-17 19:11:59 +000038
Daniel Veillard260a68f1998-08-13 03:39:55 +000039/************************************************************************
40 * *
41 * Allocation and deallocation of basic structures *
42 * *
43 ************************************************************************/
44
Daniel Veillard97b58771998-10-20 06:14:16 +000045/**
46 * xmlUpgradeOldNs:
47 * @doc: a document pointer
48 *
49 * Upgrade old style Namespaces (PI) and move them to the root of the document.
Daniel Veillard260a68f1998-08-13 03:39:55 +000050 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +000051void
52xmlUpgradeOldNs(xmlDocPtr doc) {
Daniel Veillard260a68f1998-08-13 03:39:55 +000053 xmlNsPtr cur;
54
55 if ((doc == NULL) || (doc->oldNs == NULL)) return;
56 if (doc->root == NULL) {
57 fprintf(stderr, "xmlUpgradeOldNs: failed no root !\n");
58 return;
59 }
60
61 cur = doc->oldNs;
62 while (cur->next != NULL) {
63 cur->type = XML_LOCAL_NAMESPACE;
64 cur = cur->next;
65 }
66 cur->type = XML_LOCAL_NAMESPACE;
67 cur->next = doc->root->nsDef;
68 doc->root->nsDef = doc->oldNs;
69 doc->oldNs = NULL;
70}
71
Daniel Veillard97b58771998-10-20 06:14:16 +000072/**
73 * xmlNewNs:
74 * @node: the element carrying the namespace
75 * @href: the URI associated
76 * @prefix: the prefix for the namespace
77 *
Daniel Veillard260a68f1998-08-13 03:39:55 +000078 * Creation of a new Namespace.
Daniel Veillard1e346af1999-02-22 10:33:01 +000079 * Returns returns a new namespace pointer
Daniel Veillard260a68f1998-08-13 03:39:55 +000080 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +000081xmlNsPtr
82xmlNewNs(xmlNodePtr node, const CHAR *href, const CHAR *prefix) {
Daniel Veillard260a68f1998-08-13 03:39:55 +000083 xmlNsPtr cur;
84
85 if (href == NULL) {
86 fprintf(stderr, "xmlNewNs: href == NULL !\n");
87 return(NULL);
88 }
89
90 /*
91 * Allocate a new DTD and fill the fields.
92 */
Daniel Veillard6454aec1999-09-02 22:04:43 +000093 cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
Daniel Veillard260a68f1998-08-13 03:39:55 +000094 if (cur == NULL) {
95 fprintf(stderr, "xmlNewNs : malloc failed\n");
96 return(NULL);
97 }
98
99 cur->type = XML_LOCAL_NAMESPACE;
100 if (href != NULL)
101 cur->href = xmlStrdup(href);
102 else
103 cur->href = NULL;
104 if (prefix != NULL)
105 cur->prefix = xmlStrdup(prefix);
106 else
107 cur->prefix = NULL;
108
109 /*
110 * Add it at the end to preserve parsing order ...
111 */
112 cur->next = NULL;
113 if (node != NULL) {
114 if (node->nsDef == NULL) {
115 node->nsDef = cur;
116 } else {
117 xmlNsPtr prev = node->nsDef;
118
119 while (prev->next != NULL) prev = prev->next;
120 prev->next = cur;
121 }
122 }
123
124 return(cur);
125}
126
Daniel Veillard97b58771998-10-20 06:14:16 +0000127/**
128 * xmlNewGlobalNs:
129 * @doc: the document carrying the namespace
130 * @href: the URI associated
131 * @prefix: the prefix for the namespace
132 *
133 * Creation of a Namespace, the old way using PI and without scoping, to AVOID.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000134 * Returns returns a new namespace pointer
Daniel Veillard260a68f1998-08-13 03:39:55 +0000135 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000136xmlNsPtr
137xmlNewGlobalNs(xmlDocPtr doc, const CHAR *href, const CHAR *prefix) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000138 xmlNsPtr cur;
139
140 /*
141 * Allocate a new DTD and fill the fields.
142 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000143 cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000144 if (cur == NULL) {
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000145 fprintf(stderr, "xmlNewGlobalNs : malloc failed\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +0000146 return(NULL);
147 }
148
149 cur->type = XML_GLOBAL_NAMESPACE;
150 if (href != NULL)
151 cur->href = xmlStrdup(href);
152 else
153 cur->href = NULL;
154 if (prefix != NULL)
155 cur->prefix = xmlStrdup(prefix);
156 else
157 cur->prefix = NULL;
158
159 /*
160 * Add it at the end to preserve parsing order ...
161 */
162 cur->next = NULL;
163 if (doc != NULL) {
164 if (doc->oldNs == NULL) {
165 doc->oldNs = cur;
166 } else {
167 xmlNsPtr prev = doc->oldNs;
168
169 while (prev->next != NULL) prev = prev->next;
170 prev->next = cur;
171 }
172 }
173
174 return(cur);
175}
176
Daniel Veillard97b58771998-10-20 06:14:16 +0000177/**
178 * xmlSetNs:
179 * @node: a node in the document
180 * @ns: a namespace pointer
181 *
182 * Associate a namespace to a node, a posteriori.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000183 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000184void
185xmlSetNs(xmlNodePtr node, xmlNsPtr ns) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000186 if (node == NULL) {
187 fprintf(stderr, "xmlSetNs: node == NULL\n");
188 return;
189 }
190 node->ns = ns;
191}
192
Daniel Veillard97b58771998-10-20 06:14:16 +0000193/**
194 * xmlFreeNs:
195 * @cur: the namespace pointer
196 *
197 * Free up the structures associated to a namespace
Daniel Veillard260a68f1998-08-13 03:39:55 +0000198 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000199void
200xmlFreeNs(xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000201 if (cur == NULL) {
202 fprintf(stderr, "xmlFreeNs : ns == NULL\n");
203 return;
204 }
Daniel Veillard6454aec1999-09-02 22:04:43 +0000205 if (cur->href != NULL) xmlFree((char *) cur->href);
206 if (cur->prefix != NULL) xmlFree((char *) cur->prefix);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000207 memset(cur, -1, sizeof(xmlNs));
Daniel Veillard6454aec1999-09-02 22:04:43 +0000208 xmlFree(cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000209}
210
Daniel Veillard97b58771998-10-20 06:14:16 +0000211/**
212 * xmlFreeNsList:
213 * @cur: the first namespace pointer
214 *
215 * Free up all the structures associated to the chained namespaces.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000216 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000217void
218xmlFreeNsList(xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000219 xmlNsPtr next;
220 if (cur == NULL) {
221 fprintf(stderr, "xmlFreeNsList : ns == NULL\n");
222 return;
223 }
224 while (cur != NULL) {
225 next = cur->next;
226 xmlFreeNs(cur);
227 cur = next;
228 }
229}
230
Daniel Veillard97b58771998-10-20 06:14:16 +0000231/**
232 * xmlNewDtd:
233 * @doc: the document pointer
234 * @name: the DTD name
235 * @ExternalID: the external ID
236 * @SystemID: the system ID
237 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000238 * Creation of a new DTD.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000239 * Returns a pointer to the new DTD structure
Daniel Veillard260a68f1998-08-13 03:39:55 +0000240 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000241xmlDtdPtr
242xmlNewDtd(xmlDocPtr doc, const CHAR *name,
Daniel Veillard260a68f1998-08-13 03:39:55 +0000243 const CHAR *ExternalID, const CHAR *SystemID) {
244 xmlDtdPtr cur;
245
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000246 if ((doc != NULL) && (doc->extSubset != NULL)) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000247 fprintf(stderr, "xmlNewDtd(%s): document %s already have a DTD %s\n",
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000248 /* !!! */ (char *) name, doc->name,
249 /* !!! */ (char *)doc->extSubset->name);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000250 }
251
252 /*
253 * Allocate a new DTD and fill the fields.
254 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000255 cur = (xmlDtdPtr) xmlMalloc(sizeof(xmlDtd));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000256 if (cur == NULL) {
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000257 fprintf(stderr, "xmlNewDtd : malloc failed\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +0000258 return(NULL);
259 }
260
261 if (name != NULL)
262 cur->name = xmlStrdup(name);
263 else
264 cur->name = NULL;
265 if (ExternalID != NULL)
266 cur->ExternalID = xmlStrdup(ExternalID);
267 else
268 cur->ExternalID = NULL;
269 if (SystemID != NULL)
270 cur->SystemID = xmlStrdup(SystemID);
271 else
272 cur->SystemID = NULL;
Daniel Veillard1e346af1999-02-22 10:33:01 +0000273 cur->notations = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000274 cur->elements = NULL;
Daniel Veillard1e346af1999-02-22 10:33:01 +0000275 cur->attributes = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000276 cur->entities = NULL;
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000277 if (doc != NULL)
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000278 doc->extSubset = cur;
279
280 return(cur);
281}
282
283/**
284 * xmlCreateIntSubset:
285 * @doc: the document pointer
286 * @name: the DTD name
287 * @ExternalID: the external ID
288 * @SystemID: the system ID
289 *
Daniel Veillard1e346af1999-02-22 10:33:01 +0000290 * Create the internal subset of a document
291 * Returns a pointer to the new DTD structure
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000292 */
293xmlDtdPtr
294xmlCreateIntSubset(xmlDocPtr doc, const CHAR *name,
295 const CHAR *ExternalID, const CHAR *SystemID) {
296 xmlDtdPtr cur;
297
298 if ((doc != NULL) && (doc->intSubset != NULL)) {
299 fprintf(stderr,
300 "xmlCreateIntSubset(): document %s already have an internal subset\n",
301 doc->name);
302 return(NULL);
303 }
304
305 /*
306 * Allocate a new DTD and fill the fields.
307 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000308 cur = (xmlDtdPtr) xmlMalloc(sizeof(xmlDtd));
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000309 if (cur == NULL) {
310 fprintf(stderr, "xmlNewDtd : malloc failed\n");
311 return(NULL);
312 }
313
314 if (name != NULL)
315 cur->name = xmlStrdup(name);
316 else
317 cur->name = NULL;
318 if (ExternalID != NULL)
319 cur->ExternalID = xmlStrdup(ExternalID);
320 else
321 cur->ExternalID = NULL;
322 if (SystemID != NULL)
323 cur->SystemID = xmlStrdup(SystemID);
324 else
325 cur->SystemID = NULL;
Daniel Veillard1e346af1999-02-22 10:33:01 +0000326 cur->notations = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000327 cur->elements = NULL;
Daniel Veillard1e346af1999-02-22 10:33:01 +0000328 cur->attributes = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000329 cur->entities = NULL;
330 if (doc != NULL)
331 doc->intSubset = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000332
333 return(cur);
334}
335
Daniel Veillard97b58771998-10-20 06:14:16 +0000336/**
337 * xmlFreeDtd:
338 * @cur: the DTD structure to free up
339 *
340 * Free a DTD structure.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000341 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000342void
343xmlFreeDtd(xmlDtdPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000344 if (cur == NULL) {
345 fprintf(stderr, "xmlFreeDtd : DTD == NULL\n");
346 return;
347 }
Daniel Veillard6454aec1999-09-02 22:04:43 +0000348 if (cur->name != NULL) xmlFree((char *) cur->name);
349 if (cur->SystemID != NULL) xmlFree((char *) cur->SystemID);
350 if (cur->ExternalID != NULL) xmlFree((char *) cur->ExternalID);
Daniel Veillard1e346af1999-02-22 10:33:01 +0000351 if (cur->notations != NULL)
352 xmlFreeNotationTable((xmlNotationTablePtr) cur->notations);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000353 if (cur->elements != NULL)
Daniel Veillard3b9def11999-01-31 22:15:06 +0000354 xmlFreeElementTable((xmlElementTablePtr) cur->elements);
Daniel Veillard1e346af1999-02-22 10:33:01 +0000355 if (cur->attributes != NULL)
356 xmlFreeAttributeTable((xmlAttributeTablePtr) cur->attributes);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000357 if (cur->entities != NULL)
358 xmlFreeEntitiesTable((xmlEntitiesTablePtr) cur->entities);
359 memset(cur, -1, sizeof(xmlDtd));
Daniel Veillard6454aec1999-09-02 22:04:43 +0000360 xmlFree(cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000361}
362
Daniel Veillard97b58771998-10-20 06:14:16 +0000363/**
364 * xmlNewDoc:
365 * @version: CHAR string giving the version of XML "1.0"
366 *
Daniel Veillard1e346af1999-02-22 10:33:01 +0000367 * Returns a new document
Daniel Veillard260a68f1998-08-13 03:39:55 +0000368 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000369xmlDocPtr
370xmlNewDoc(const CHAR *version) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000371 xmlDocPtr cur;
372
373 if (version == NULL) {
374 fprintf(stderr, "xmlNewDoc : version == NULL\n");
375 return(NULL);
376 }
377
378 /*
379 * Allocate a new document and fill the fields.
380 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000381 cur = (xmlDocPtr) xmlMalloc(sizeof(xmlDoc));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000382 if (cur == NULL) {
383 fprintf(stderr, "xmlNewDoc : malloc failed\n");
384 return(NULL);
385 }
386
Daniel Veillard33942841998-10-18 19:12:41 +0000387 cur->type = XML_DOCUMENT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000388 cur->version = xmlStrdup(version);
389 cur->name = NULL;
390 cur->root = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000391 cur->intSubset = NULL;
392 cur->extSubset = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000393 cur->oldNs = NULL;
394 cur->encoding = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000395 cur->standalone = -1;
Daniel Veillard15a8df41998-09-24 19:15:06 +0000396 cur->compression = xmlCompressMode;
Daniel Veillardb96e6431999-08-29 21:02:19 +0000397 cur->ids = NULL;
Daniel Veillardc08a2c61999-09-08 21:35:25 +0000398 cur->refs = NULL;
Daniel Veillard27d88741999-05-29 11:51:49 +0000399#ifndef XML_WITHOUT_CORBA
Daniel Veillard27fb0751998-10-17 06:47:46 +0000400 cur->_private = NULL;
401 cur->vepv = NULL;
402#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000403 return(cur);
404}
405
Daniel Veillard97b58771998-10-20 06:14:16 +0000406/**
407 * xmlFreeDoc:
408 * @cur: pointer to the document
409 * @:
410 *
411 * Free up all the structures used by a document, tree included.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000412 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000413void
414xmlFreeDoc(xmlDocPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000415 if (cur == NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000416#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +0000417 fprintf(stderr, "xmlFreeDoc : document == NULL\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000418#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000419 return;
420 }
Daniel Veillard6454aec1999-09-02 22:04:43 +0000421 if (cur->version != NULL) xmlFree((char *) cur->version);
422 if (cur->name != NULL) xmlFree((char *) cur->name);
423 if (cur->encoding != NULL) xmlFree((char *) cur->encoding);
424 if (cur->root != NULL) xmlFreeNodeList(cur->root);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000425 if (cur->intSubset != NULL) xmlFreeDtd(cur->intSubset);
426 if (cur->extSubset != NULL) xmlFreeDtd(cur->extSubset);
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000427 if (cur->oldNs != NULL) xmlFreeNsList(cur->oldNs);
Daniel Veillardb96e6431999-08-29 21:02:19 +0000428 if (cur->ids != NULL) xmlFreeIDTable((xmlIDTablePtr) cur->ids);
Daniel Veillardc08a2c61999-09-08 21:35:25 +0000429 if (cur->refs != NULL) xmlFreeRefTable((xmlRefTablePtr) cur->refs);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000430 memset(cur, -1, sizeof(xmlDoc));
Daniel Veillard6454aec1999-09-02 22:04:43 +0000431 xmlFree(cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000432}
433
Daniel Veillard97b58771998-10-20 06:14:16 +0000434/**
Daniel Veillard16253641998-10-28 22:58:05 +0000435 * xmlStringLenGetNodeList:
436 * @doc: the document
437 * @value: the value of the text
Daniel Veillard1e346af1999-02-22 10:33:01 +0000438 * @len: the length of the string value
Daniel Veillard16253641998-10-28 22:58:05 +0000439 *
440 * Parse the value string and build the node list associated. Should
441 * produce a flat tree with only TEXTs and ENTITY_REFs.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000442 * Returns a pointer to the first child
Daniel Veillard16253641998-10-28 22:58:05 +0000443 */
444xmlNodePtr
445xmlStringLenGetNodeList(xmlDocPtr doc, const CHAR *value, int len) {
446 xmlNodePtr ret = NULL, last = NULL;
447 xmlNodePtr node;
448 CHAR *val;
449 const CHAR *cur = value;
450 const CHAR *q;
Daniel Veillard25940b71998-10-29 05:51:30 +0000451 xmlEntityPtr ent;
Daniel Veillard16253641998-10-28 22:58:05 +0000452
453 if (value == NULL) return(NULL);
454
455 q = cur;
456 while ((*cur != 0) && (cur - value < len)) {
457 if (*cur == '&') {
Daniel Veillard25940b71998-10-29 05:51:30 +0000458 /*
459 * Save the current text.
460 */
Daniel Veillard16253641998-10-28 22:58:05 +0000461 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000462 if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
463 xmlNodeAddContentLen(last, q, cur - q);
464 } else {
465 node = xmlNewDocTextLen(doc, q, cur - q);
466 if (node == NULL) return(ret);
467 if (last == NULL)
468 last = ret = node;
469 else {
470 last->next = node;
471 node->prev = last;
472 last = node;
473 }
Daniel Veillard16253641998-10-28 22:58:05 +0000474 }
475 }
Daniel Veillard25940b71998-10-29 05:51:30 +0000476 /*
477 * Read the entity string
478 */
Daniel Veillard16253641998-10-28 22:58:05 +0000479 cur++;
480 q = cur;
481 while ((*cur != 0) && (cur - value < len) && (*cur != ';')) cur++;
482 if ((*cur == 0) || (cur - value >= len)) {
483 fprintf(stderr,
Daniel Veillard011b63c1999-06-02 17:44:04 +0000484 "xmlStringLenGetNodeList: unterminated entity %30s\n", q);
Daniel Veillard16253641998-10-28 22:58:05 +0000485 return(ret);
486 }
487 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000488 /*
489 * Predefined entities don't generate nodes
490 */
Daniel Veillard16253641998-10-28 22:58:05 +0000491 val = xmlStrndup(q, cur - q);
Daniel Veillard25940b71998-10-29 05:51:30 +0000492 ent = xmlGetDocEntity(doc, val);
493 if ((ent != NULL) &&
494 (ent->type == XML_INTERNAL_PREDEFINED_ENTITY)) {
495 if (last == NULL) {
496 node = xmlNewDocText(doc, ent->content);
497 last = ret = node;
498 } else
499 xmlNodeAddContent(last, ent->content);
500
501 } else {
502 /*
503 * Create a new REFERENCE_REF node
504 */
505 node = xmlNewReference(doc, val);
Daniel Veillard242590e1998-11-13 18:04:35 +0000506 if (node == NULL) {
Daniel Veillard6454aec1999-09-02 22:04:43 +0000507 if (val != NULL) xmlFree(val);
Daniel Veillard242590e1998-11-13 18:04:35 +0000508 return(ret);
509 }
Daniel Veillard25940b71998-10-29 05:51:30 +0000510 if (last == NULL)
511 last = ret = node;
512 else {
513 last->next = node;
514 node->prev = last;
515 last = node;
516 }
Daniel Veillard16253641998-10-28 22:58:05 +0000517 }
Daniel Veillard6454aec1999-09-02 22:04:43 +0000518 xmlFree(val);
Daniel Veillard16253641998-10-28 22:58:05 +0000519 }
520 cur++;
521 q = cur;
522 } else
523 cur++;
524 }
525 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000526 /*
527 * Handle the last piece of text.
528 */
529 if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
530 xmlNodeAddContentLen(last, q, cur - q);
531 } else {
532 node = xmlNewDocTextLen(doc, q, cur - q);
533 if (node == NULL) return(ret);
534 if (last == NULL)
535 last = ret = node;
536 else {
537 last->next = node;
538 node->prev = last;
539 last = node;
540 }
Daniel Veillard16253641998-10-28 22:58:05 +0000541 }
542 }
543 return(ret);
544}
545
546/**
Daniel Veillardccb09631998-10-27 06:21:04 +0000547 * xmlStringGetNodeList:
548 * @doc: the document
549 * @value: the value of the attribute
550 *
551 * Parse the value string and build the node list associated. Should
552 * produce a flat tree with only TEXTs and ENTITY_REFs.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000553 * Returns a pointer to the first child
Daniel Veillardccb09631998-10-27 06:21:04 +0000554 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000555xmlNodePtr
556xmlStringGetNodeList(xmlDocPtr doc, const CHAR *value) {
Daniel Veillardccb09631998-10-27 06:21:04 +0000557 xmlNodePtr ret = NULL, last = NULL;
558 xmlNodePtr node;
559 CHAR *val;
560 const CHAR *cur = value;
561 const CHAR *q;
Daniel Veillard25940b71998-10-29 05:51:30 +0000562 xmlEntityPtr ent;
Daniel Veillardccb09631998-10-27 06:21:04 +0000563
564 if (value == NULL) return(NULL);
565
566 q = cur;
567 while (*cur != 0) {
568 if (*cur == '&') {
Daniel Veillard25940b71998-10-29 05:51:30 +0000569 /*
570 * Save the current text.
571 */
Daniel Veillardccb09631998-10-27 06:21:04 +0000572 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000573 if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
574 xmlNodeAddContentLen(last, q, cur - q);
575 } else {
576 node = xmlNewDocTextLen(doc, q, cur - q);
577 if (node == NULL) return(ret);
578 if (last == NULL)
579 last = ret = node;
580 else {
581 last->next = node;
582 node->prev = last;
583 last = node;
584 }
Daniel Veillardccb09631998-10-27 06:21:04 +0000585 }
586 }
Daniel Veillard25940b71998-10-29 05:51:30 +0000587 /*
588 * Read the entity string
589 */
Daniel Veillardccb09631998-10-27 06:21:04 +0000590 cur++;
591 q = cur;
592 while ((*cur != 0) && (*cur != ';')) cur++;
593 if (*cur == 0) {
594 fprintf(stderr,
595 "xmlStringGetNodeList: unterminated entity %30s\n", q);
596 return(ret);
597 }
598 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000599 /*
600 * Predefined entities don't generate nodes
601 */
Daniel Veillardccb09631998-10-27 06:21:04 +0000602 val = xmlStrndup(q, cur - q);
Daniel Veillard25940b71998-10-29 05:51:30 +0000603 ent = xmlGetDocEntity(doc, val);
604 if ((ent != NULL) &&
605 (ent->type == XML_INTERNAL_PREDEFINED_ENTITY)) {
606 if (last == NULL) {
607 node = xmlNewDocText(doc, ent->content);
608 last = ret = node;
609 } else
610 xmlNodeAddContent(last, ent->content);
611
612 } else {
613 /*
614 * Create a new REFERENCE_REF node
615 */
Daniel Veillard25940b71998-10-29 05:51:30 +0000616 node = xmlNewReference(doc, val);
Daniel Veillard242590e1998-11-13 18:04:35 +0000617 if (node == NULL) {
Daniel Veillard6454aec1999-09-02 22:04:43 +0000618 if (val != NULL) xmlFree(val);
Daniel Veillard242590e1998-11-13 18:04:35 +0000619 return(ret);
620 }
Daniel Veillard25940b71998-10-29 05:51:30 +0000621 if (last == NULL)
622 last = ret = node;
623 else {
624 last->next = node;
625 node->prev = last;
626 last = node;
627 }
Daniel Veillardccb09631998-10-27 06:21:04 +0000628 }
Daniel Veillard6454aec1999-09-02 22:04:43 +0000629 xmlFree(val);
Daniel Veillardccb09631998-10-27 06:21:04 +0000630 }
631 cur++;
632 q = cur;
633 } else
634 cur++;
635 }
636 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000637 /*
638 * Handle the last piece of text.
639 */
640 if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
641 xmlNodeAddContentLen(last, q, cur - q);
642 } else {
643 node = xmlNewDocTextLen(doc, q, cur - q);
644 if (node == NULL) return(ret);
645 if (last == NULL)
646 last = ret = node;
647 else {
648 last->next = node;
649 node->prev = last;
650 last = node;
651 }
Daniel Veillardccb09631998-10-27 06:21:04 +0000652 }
653 }
654 return(ret);
655}
656
657/**
658 * xmlNodeListGetString:
659 * @doc: the document
660 * @list: a Node list
661 * @inLine: should we replace entity contents or show their external form
662 *
663 * Returns the string equivalent to the text contained in the Node list
664 * made of TEXTs and ENTITY_REFs
Daniel Veillard1e346af1999-02-22 10:33:01 +0000665 * Returns a pointer to the string copy, the calller must free it.
Daniel Veillardccb09631998-10-27 06:21:04 +0000666 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000667CHAR *
668xmlNodeListGetString(xmlDocPtr doc, xmlNodePtr list, int inLine) {
Daniel Veillardccb09631998-10-27 06:21:04 +0000669 xmlNodePtr node = list;
670 CHAR *ret = NULL;
671 xmlEntityPtr ent;
672
673 if (list == NULL) return(NULL);
674
675 while (node != NULL) {
676 if (node->type == XML_TEXT_NODE) {
677 if (inLine)
678 ret = xmlStrcat(ret, node->content);
Daniel Veillard14fff061999-06-22 21:49:07 +0000679 else {
680 CHAR *buffer;
681
682 buffer = xmlEncodeEntitiesReentrant(doc, node->content);
683 if (buffer != NULL) {
684 ret = xmlStrcat(ret, buffer);
Daniel Veillard6454aec1999-09-02 22:04:43 +0000685 xmlFree(buffer);
Daniel Veillard14fff061999-06-22 21:49:07 +0000686 }
687 }
Daniel Veillardccb09631998-10-27 06:21:04 +0000688 } else if (node->type == XML_ENTITY_REF_NODE) {
689 if (inLine) {
690 ent = xmlGetDocEntity(doc, node->name);
691 if (ent != NULL)
692 ret = xmlStrcat(ret, ent->content);
693 else
694 ret = xmlStrcat(ret, node->content);
695 } else {
696 CHAR buf[2];
697 buf[0] = '&'; buf[1] = 0;
698 ret = xmlStrncat(ret, buf, 1);
699 ret = xmlStrcat(ret, node->name);
700 buf[0] = ';'; buf[1] = 0;
701 ret = xmlStrncat(ret, buf, 1);
702 }
703 }
704#if 0
705 else {
706 fprintf(stderr, "xmlGetNodeListString : invalide node type %d\n",
707 node->type);
708 }
709#endif
710 node = node->next;
711 }
712 return(ret);
713}
714
715/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000716 * xmlNewProp:
717 * @node: the holding node
718 * @name: the name of the attribute
719 * @value: the value of the attribute
720 *
721 * Create a new property carried by a node.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000722 * Returns a pointer to the attribute
Daniel Veillard260a68f1998-08-13 03:39:55 +0000723 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000724xmlAttrPtr
725xmlNewProp(xmlNodePtr node, const CHAR *name, const CHAR *value) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000726 xmlAttrPtr cur;
727
728 if (name == NULL) {
729 fprintf(stderr, "xmlNewProp : name == NULL\n");
730 return(NULL);
731 }
732
733 /*
734 * Allocate a new property and fill the fields.
735 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000736 cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000737 if (cur == NULL) {
738 fprintf(stderr, "xmlNewProp : malloc failed\n");
739 return(NULL);
740 }
741
Daniel Veillard33942841998-10-18 19:12:41 +0000742 cur->type = XML_ATTRIBUTE_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000743 cur->node = node;
Daniel Veillardb96e6431999-08-29 21:02:19 +0000744 cur->ns = NULL;
745 cur->name = xmlStrdup(name);
746 if (value != NULL)
747 cur->val = xmlStringGetNodeList(node->doc, value);
748 else
749 cur->val = NULL;
750#ifndef XML_WITHOUT_CORBA
751 cur->_private = NULL;
752 cur->vepv = NULL;
753#endif
754
755 /*
756 * Add it at the end to preserve parsing order ...
757 */
758 cur->next = NULL;
759 if (node != NULL) {
760 if (node->properties == NULL) {
761 node->properties = cur;
762 } else {
763 xmlAttrPtr prev = node->properties;
764
765 while (prev->next != NULL) prev = prev->next;
766 prev->next = cur;
767 }
768 }
769 return(cur);
770}
771
772/**
773 * xmlNewNsProp:
774 * @node: the holding node
775 * @ns: the namespace
776 * @name: the name of the attribute
777 * @value: the value of the attribute
778 *
779 * Create a new property tagged with a namespace and carried by a node.
780 * Returns a pointer to the attribute
781 */
782xmlAttrPtr
783xmlNewNsProp(xmlNodePtr node, xmlNsPtr ns, const CHAR *name,
784 const CHAR *value) {
785 xmlAttrPtr cur;
786
787 if (name == NULL) {
788 fprintf(stderr, "xmlNewProp : name == NULL\n");
789 return(NULL);
790 }
791
792 /*
793 * Allocate a new property and fill the fields.
794 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000795 cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr));
Daniel Veillardb96e6431999-08-29 21:02:19 +0000796 if (cur == NULL) {
797 fprintf(stderr, "xmlNewProp : malloc failed\n");
798 return(NULL);
799 }
800
801 cur->type = XML_ATTRIBUTE_NODE;
802 cur->node = node;
803 cur->ns = ns;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000804 cur->name = xmlStrdup(name);
805 if (value != NULL)
Daniel Veillardccb09631998-10-27 06:21:04 +0000806 cur->val = xmlStringGetNodeList(node->doc, value);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000807 else
Daniel Veillardccb09631998-10-27 06:21:04 +0000808 cur->val = NULL;
Daniel Veillard27d88741999-05-29 11:51:49 +0000809#ifndef XML_WITHOUT_CORBA
Daniel Veillard27fb0751998-10-17 06:47:46 +0000810 cur->_private = NULL;
811 cur->vepv = NULL;
812#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000813
814 /*
815 * Add it at the end to preserve parsing order ...
816 */
817 cur->next = NULL;
818 if (node != NULL) {
819 if (node->properties == NULL) {
820 node->properties = cur;
821 } else {
822 xmlAttrPtr prev = node->properties;
823
824 while (prev->next != NULL) prev = prev->next;
825 prev->next = cur;
826 }
827 }
828 return(cur);
829}
830
Daniel Veillard97b58771998-10-20 06:14:16 +0000831/**
Daniel Veillardccb09631998-10-27 06:21:04 +0000832 * xmlNewDocProp:
833 * @doc: the document
834 * @name: the name of the attribute
835 * @value: the value of the attribute
836 *
837 * Create a new property carried by a document.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000838 * Returns a pointer to the attribute
Daniel Veillardccb09631998-10-27 06:21:04 +0000839 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000840xmlAttrPtr
841xmlNewDocProp(xmlDocPtr doc, const CHAR *name, const CHAR *value) {
Daniel Veillardccb09631998-10-27 06:21:04 +0000842 xmlAttrPtr cur;
843
844 if (name == NULL) {
845 fprintf(stderr, "xmlNewProp : name == NULL\n");
846 return(NULL);
847 }
848
849 /*
850 * Allocate a new property and fill the fields.
851 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000852 cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr));
Daniel Veillardccb09631998-10-27 06:21:04 +0000853 if (cur == NULL) {
854 fprintf(stderr, "xmlNewProp : malloc failed\n");
855 return(NULL);
856 }
857
858 cur->type = XML_ATTRIBUTE_NODE;
859 cur->node = NULL;
860 cur->name = xmlStrdup(name);
861 if (value != NULL)
862 cur->val = xmlStringGetNodeList(doc, value);
863 else
864 cur->val = NULL;
Daniel Veillard27d88741999-05-29 11:51:49 +0000865#ifndef XML_WITHOUT_CORBA
Daniel Veillardccb09631998-10-27 06:21:04 +0000866 cur->_private = NULL;
867 cur->vepv = NULL;
868#endif
869
870 cur->next = NULL;
871 return(cur);
872}
873
874/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000875 * xmlFreePropList:
876 * @cur: the first property in the list
877 *
878 * Free a property and all its siblings, all the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000879 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000880void
881xmlFreePropList(xmlAttrPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000882 xmlAttrPtr next;
883 if (cur == NULL) {
884 fprintf(stderr, "xmlFreePropList : property == NULL\n");
885 return;
886 }
887 while (cur != NULL) {
888 next = cur->next;
889 xmlFreeProp(cur);
890 cur = next;
891 }
892}
893
Daniel Veillard97b58771998-10-20 06:14:16 +0000894/**
895 * xmlFreeProp:
896 * @cur: the first property in the list
897 *
898 * Free one property, all the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000899 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000900void
901xmlFreeProp(xmlAttrPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000902 if (cur == NULL) {
903 fprintf(stderr, "xmlFreeProp : property == NULL\n");
904 return;
905 }
Daniel Veillard6454aec1999-09-02 22:04:43 +0000906 if (cur->name != NULL) xmlFree((char *) cur->name);
Daniel Veillardccb09631998-10-27 06:21:04 +0000907 if (cur->val != NULL) xmlFreeNodeList(cur->val);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000908 memset(cur, -1, sizeof(xmlAttr));
Daniel Veillard6454aec1999-09-02 22:04:43 +0000909 xmlFree(cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000910}
911
Daniel Veillard97b58771998-10-20 06:14:16 +0000912/**
Daniel Veillardb96e6431999-08-29 21:02:19 +0000913 * xmlNewPI:
914 * @name: the processing instruction name
915 * @content: the PI content
916 *
917 * Creation of a processing instruction element.
918 * Returns a pointer to the new node object.
919 */
920xmlNodePtr
921xmlNewPI(const CHAR *name, const CHAR *content) {
922 xmlNodePtr cur;
923
924 if (name == NULL) {
925 fprintf(stderr, "xmlNewPI : name == NULL\n");
926 return(NULL);
927 }
928
929 /*
930 * Allocate a new node and fill the fields.
931 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000932 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillardb96e6431999-08-29 21:02:19 +0000933 if (cur == NULL) {
934 fprintf(stderr, "xmlNewPI : malloc failed\n");
935 return(NULL);
936 }
937
938 cur->type = XML_PI_NODE;
939 cur->doc = NULL;
940 cur->parent = NULL;
941 cur->next = NULL;
942 cur->prev = NULL;
943 cur->childs = NULL;
944 cur->last = NULL;
945 cur->properties = NULL;
946 cur->name = xmlStrdup(name);
947 cur->ns = NULL;
948 cur->nsDef = NULL;
949 if (content != NULL)
950 cur->content = xmlStrdup(content);
951 else
952 cur->content = NULL;
953#ifndef XML_WITHOUT_CORBA
954 cur->_private = NULL;
955 cur->vepv = NULL;
956#endif
957 return(cur);
958}
959
960/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000961 * xmlNewNode:
962 * @ns: namespace if any
963 * @name: the node name
Daniel Veillard97b58771998-10-20 06:14:16 +0000964 *
965 * Creation of a new node element. @ns and @content are optionnal (NULL).
Daniel Veillardccb09631998-10-27 06:21:04 +0000966 * If content is non NULL, a child list containing the TEXTs and
967 * ENTITY_REFs node will be created.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000968 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000969 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000970xmlNodePtr
971xmlNewNode(xmlNsPtr ns, const CHAR *name) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000972 xmlNodePtr cur;
973
974 if (name == NULL) {
975 fprintf(stderr, "xmlNewNode : name == NULL\n");
976 return(NULL);
977 }
978
979 /*
980 * Allocate a new node and fill the fields.
981 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000982 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000983 if (cur == NULL) {
984 fprintf(stderr, "xmlNewNode : malloc failed\n");
985 return(NULL);
986 }
987
Daniel Veillard33942841998-10-18 19:12:41 +0000988 cur->type = XML_ELEMENT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000989 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000990 cur->parent = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000991 cur->next = NULL;
992 cur->prev = NULL;
993 cur->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000994 cur->last = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000995 cur->properties = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000996 cur->name = xmlStrdup(name);
997 cur->ns = ns;
998 cur->nsDef = NULL;
Daniel Veillardccb09631998-10-27 06:21:04 +0000999 cur->content = NULL;
Daniel Veillard27d88741999-05-29 11:51:49 +00001000#ifndef XML_WITHOUT_CORBA
Daniel Veillard27fb0751998-10-17 06:47:46 +00001001 cur->_private = NULL;
1002 cur->vepv = NULL;
1003#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001004 return(cur);
1005}
1006
Daniel Veillard97b58771998-10-20 06:14:16 +00001007/**
1008 * xmlNewDocNode:
1009 * @doc: the document
1010 * @ns: namespace if any
1011 * @name: the node name
1012 * @content: the text content if any
1013 *
1014 * Creation of a new node element within a document. @ns and @content
1015 * are optionnal (NULL).
Daniel Veillard1e346af1999-02-22 10:33:01 +00001016 * Returns a pointer to the new node object.
Daniel Veillard97b58771998-10-20 06:14:16 +00001017 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001018xmlNodePtr
1019xmlNewDocNode(xmlDocPtr doc, xmlNsPtr ns,
Daniel Veillard15b75af1999-07-26 16:42:37 +00001020 const CHAR *name, const CHAR *content) {
Daniel Veillard0bef1311998-10-14 02:36:47 +00001021 xmlNodePtr cur;
1022
Daniel Veillardccb09631998-10-27 06:21:04 +00001023 cur = xmlNewNode(ns, name);
1024 if (cur != NULL) {
1025 cur->doc = doc;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001026 if (content != NULL) {
Daniel Veillardccb09631998-10-27 06:21:04 +00001027 cur->childs = xmlStringGetNodeList(doc, content);
Daniel Veillard1e346af1999-02-22 10:33:01 +00001028 UPDATE_LAST_CHILD(cur)
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001029 }
Daniel Veillardccb09631998-10-27 06:21:04 +00001030 }
Daniel Veillard0bef1311998-10-14 02:36:47 +00001031 return(cur);
1032}
1033
1034
Daniel Veillard97b58771998-10-20 06:14:16 +00001035/**
1036 * xmlNewText:
1037 * @content: the text content
1038 *
1039 * Creation of a new text node.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001040 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001041 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001042xmlNodePtr
1043xmlNewText(const CHAR *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001044 xmlNodePtr cur;
1045
1046 /*
1047 * Allocate a new node and fill the fields.
1048 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001049 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillard260a68f1998-08-13 03:39:55 +00001050 if (cur == NULL) {
1051 fprintf(stderr, "xmlNewText : malloc failed\n");
1052 return(NULL);
1053 }
1054
Daniel Veillard33942841998-10-18 19:12:41 +00001055 cur->type = XML_TEXT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001056 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001057 cur->parent = NULL;
1058 cur->next = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001059 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001060 cur->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001061 cur->last = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001062 cur->properties = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001063 cur->type = XML_TEXT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001064 cur->name = xmlStrdup(xmlStringText);
1065 cur->ns = NULL;
1066 cur->nsDef = NULL;
1067 if (content != NULL)
1068 cur->content = xmlStrdup(content);
1069 else
1070 cur->content = NULL;
1071 return(cur);
1072}
1073
Daniel Veillard97b58771998-10-20 06:14:16 +00001074/**
Daniel Veillardccb09631998-10-27 06:21:04 +00001075 * xmlNewReference:
1076 * @doc: the document
1077 * @name: the reference name, or the reference string with & and ;
1078 *
1079 * Creation of a new reference node.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001080 * Returns a pointer to the new node object.
Daniel Veillardccb09631998-10-27 06:21:04 +00001081 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001082xmlNodePtr
1083xmlNewReference(xmlDocPtr doc, const CHAR *name) {
Daniel Veillardccb09631998-10-27 06:21:04 +00001084 xmlNodePtr cur;
1085 xmlEntityPtr ent;
1086
1087 /*
1088 * Allocate a new node and fill the fields.
1089 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001090 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillardccb09631998-10-27 06:21:04 +00001091 if (cur == NULL) {
1092 fprintf(stderr, "xmlNewText : malloc failed\n");
1093 return(NULL);
1094 }
1095
1096 cur->type = XML_ENTITY_REF_NODE;
Daniel Veillard10c6a8f1998-10-28 01:00:12 +00001097 cur->doc = doc;
Daniel Veillardccb09631998-10-27 06:21:04 +00001098 cur->parent = NULL;
1099 cur->next = NULL;
1100 cur->prev = NULL;
1101 cur->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001102 cur->last = NULL;
Daniel Veillardccb09631998-10-27 06:21:04 +00001103 cur->properties = NULL;
1104 if (name[0] == '&') {
1105 int len;
1106 name++;
1107 len = xmlStrlen(name);
1108 if (name[len - 1] == ';')
1109 cur->name = xmlStrndup(name, len - 1);
1110 else
1111 cur->name = xmlStrndup(name, len);
1112 } else
1113 cur->name = xmlStrdup(name);
1114 cur->ns = NULL;
1115 cur->nsDef = NULL;
1116
1117 ent = xmlGetDocEntity(doc, cur->name);
1118 if (ent != NULL)
1119 cur->content = ent->content;
1120 else
1121 cur->content = NULL;
1122 return(cur);
1123}
1124
1125/**
Daniel Veillard97b58771998-10-20 06:14:16 +00001126 * xmlNewDocText:
1127 * @doc: the document
1128 * @content: the text content
1129 *
1130 * Creation of a new text node within a document.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001131 * Returns a pointer to the new node object.
Daniel Veillard97b58771998-10-20 06:14:16 +00001132 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001133xmlNodePtr
1134xmlNewDocText(xmlDocPtr doc, const CHAR *content) {
Daniel Veillard0bef1311998-10-14 02:36:47 +00001135 xmlNodePtr cur;
1136
1137 cur = xmlNewText(content);
1138 if (cur != NULL) cur->doc = doc;
1139 return(cur);
1140}
1141
Daniel Veillard97b58771998-10-20 06:14:16 +00001142/**
Daniel Veillardccb09631998-10-27 06:21:04 +00001143 * xmlNewTextLen:
Daniel Veillard97b58771998-10-20 06:14:16 +00001144 * @content: the text content
1145 * @len: the text len.
1146 *
1147 * Creation of a new text node with an extra parameter for the content's lenght
Daniel Veillard1e346af1999-02-22 10:33:01 +00001148 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001149 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001150xmlNodePtr
1151xmlNewTextLen(const CHAR *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001152 xmlNodePtr cur;
1153
1154 /*
1155 * Allocate a new node and fill the fields.
1156 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001157 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillard260a68f1998-08-13 03:39:55 +00001158 if (cur == NULL) {
1159 fprintf(stderr, "xmlNewText : malloc failed\n");
1160 return(NULL);
1161 }
1162
Daniel Veillard33942841998-10-18 19:12:41 +00001163 cur->type = XML_TEXT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001164 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001165 cur->parent = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001166 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001167 cur->next = NULL;
1168 cur->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001169 cur->last = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001170 cur->properties = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001171 cur->type = XML_TEXT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001172 cur->name = xmlStrdup(xmlStringText);
1173 cur->ns = NULL;
1174 cur->nsDef = NULL;
1175 if (content != NULL)
1176 cur->content = xmlStrndup(content, len);
1177 else
1178 cur->content = NULL;
1179 return(cur);
1180}
1181
Daniel Veillard97b58771998-10-20 06:14:16 +00001182/**
1183 * xmlNewDocTextLen:
1184 * @doc: the document
1185 * @content: the text content
1186 * @len: the text len.
1187 *
1188 * Creation of a new text node with an extra content lenght parameter. The
1189 * text node pertain to a given document.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001190 * Returns a pointer to the new node object.
Daniel Veillard97b58771998-10-20 06:14:16 +00001191 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001192xmlNodePtr
1193xmlNewDocTextLen(xmlDocPtr doc, const CHAR *content, int len) {
Daniel Veillard0bef1311998-10-14 02:36:47 +00001194 xmlNodePtr cur;
1195
1196 cur = xmlNewTextLen(content, len);
1197 if (cur != NULL) cur->doc = doc;
1198 return(cur);
1199}
1200
Daniel Veillard97b58771998-10-20 06:14:16 +00001201/**
1202 * xmlNewComment:
1203 * @content: the comment content
1204 *
1205 * Creation of a new node containing a comment.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001206 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001207 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001208xmlNodePtr
Daniel Veillard517752b1999-04-05 12:20:10 +00001209xmlNewComment(const CHAR *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001210 xmlNodePtr cur;
1211
1212 /*
1213 * Allocate a new node and fill the fields.
1214 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001215 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillard260a68f1998-08-13 03:39:55 +00001216 if (cur == NULL) {
1217 fprintf(stderr, "xmlNewComment : malloc failed\n");
1218 return(NULL);
1219 }
1220
Daniel Veillard33942841998-10-18 19:12:41 +00001221 cur->type = XML_COMMENT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001222 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001223 cur->parent = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001224 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001225 cur->next = NULL;
1226 cur->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001227 cur->last = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001228 cur->properties = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001229 cur->type = XML_COMMENT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001230 cur->name = xmlStrdup(xmlStringText);
1231 cur->ns = NULL;
1232 cur->nsDef = NULL;
1233 if (content != NULL)
1234 cur->content = xmlStrdup(content);
1235 else
1236 cur->content = NULL;
1237 return(cur);
1238}
1239
Daniel Veillard97b58771998-10-20 06:14:16 +00001240/**
Daniel Veillardb05deb71999-08-10 19:04:08 +00001241 * xmlNewCDataBlock:
1242 * @doc: the document
1243 * @content: the CData block content content
1244 * @len: the length of the block
1245 *
1246 * Creation of a new node containing a CData block.
1247 * Returns a pointer to the new node object.
1248 */
1249xmlNodePtr
1250xmlNewCDataBlock(xmlDocPtr doc, const CHAR *content, int len) {
1251 xmlNodePtr cur;
1252
1253 /*
1254 * Allocate a new node and fill the fields.
1255 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001256 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillardb05deb71999-08-10 19:04:08 +00001257 if (cur == NULL) {
1258 fprintf(stderr, "xmlNewCDataBlock : malloc failed\n");
1259 return(NULL);
1260 }
1261
1262 cur->type = XML_CDATA_SECTION_NODE;
1263 cur->doc = NULL;
1264 cur->parent = NULL;
1265 cur->prev = NULL;
1266 cur->next = NULL;
1267 cur->childs = NULL;
1268 cur->last = NULL;
1269 cur->properties = NULL;
1270 cur->name = xmlStrdup(xmlStringText);
1271 cur->ns = NULL;
1272 cur->nsDef = NULL;
1273 if ((content != NULL) && (len > 0)) {
1274 cur->content = xmlStrndup(content, len);
1275 } else
1276 cur->content = NULL;
1277 return(cur);
1278}
1279
1280/**
Daniel Veillard1e346af1999-02-22 10:33:01 +00001281 * xmlNewDocComment:
Daniel Veillard97b58771998-10-20 06:14:16 +00001282 * @doc: the document
1283 * @content: the comment content
1284 *
1285 * Creation of a new node containing a commentwithin a document.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001286 * Returns a pointer to the new node object.
Daniel Veillard97b58771998-10-20 06:14:16 +00001287 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001288xmlNodePtr
Daniel Veillard517752b1999-04-05 12:20:10 +00001289xmlNewDocComment(xmlDocPtr doc, const CHAR *content) {
Daniel Veillard0bef1311998-10-14 02:36:47 +00001290 xmlNodePtr cur;
1291
1292 cur = xmlNewComment(content);
1293 if (cur != NULL) cur->doc = doc;
1294 return(cur);
1295}
1296
Daniel Veillard97b58771998-10-20 06:14:16 +00001297/**
1298 * xmlNewChild:
1299 * @parent: the parent node
1300 * @ns: a namespace if any
1301 * @name: the name of the child
1302 * @content: the content of the child if any.
1303 *
1304 *
1305 * Creation of a new child element, added at the end of @parent childs list.
Daniel Veillardccb09631998-10-27 06:21:04 +00001306 * @ns and @content parameters are optionnal (NULL). If content is non NULL,
1307 * a child list containing the TEXTs and ENTITY_REFs node will be created.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001308 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001309 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001310xmlNodePtr
1311xmlNewChild(xmlNodePtr parent, xmlNsPtr ns,
Daniel Veillard15b75af1999-07-26 16:42:37 +00001312 const CHAR *name, const CHAR *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001313 xmlNodePtr cur, prev;
1314
1315 if (parent == NULL) {
1316 fprintf(stderr, "xmlNewChild : parent == NULL\n");
1317 return(NULL);
1318 }
1319
1320 if (name == NULL) {
1321 fprintf(stderr, "xmlNewChild : name == NULL\n");
1322 return(NULL);
1323 }
1324
1325 /*
1326 * Allocate a new node
1327 */
1328 if (ns == NULL)
Daniel Veillardccb09631998-10-27 06:21:04 +00001329 cur = xmlNewDocNode(parent->doc, parent->ns, name, content);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001330 else
Daniel Veillardccb09631998-10-27 06:21:04 +00001331 cur = xmlNewDocNode(parent->doc, ns, name, content);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001332 if (cur == NULL) return(NULL);
1333
1334 /*
1335 * add the new element at the end of the childs list.
1336 */
Daniel Veillardccb09631998-10-27 06:21:04 +00001337 cur->type = XML_ELEMENT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001338 cur->parent = parent;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001339 cur->doc = parent->doc;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001340 if (parent->childs == NULL) {
1341 parent->childs = cur;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001342 parent->last = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001343 } else {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001344 prev = parent->last;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001345 prev->next = cur;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001346 cur->prev = prev;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001347 parent->last = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001348 }
1349
1350 return(cur);
1351}
1352
Daniel Veillard97b58771998-10-20 06:14:16 +00001353/**
Daniel Veillardb96e6431999-08-29 21:02:19 +00001354 * xmlAddSibling:
1355 * @cur: the child node
1356 * @elem: the new node
1357 *
1358 * Add a new element to the list of siblings of @cur
1359 * Returns the element or NULL in case of error.
1360 */
1361xmlNodePtr
1362xmlAddSibling(xmlNodePtr cur, xmlNodePtr elem) {
1363 xmlNodePtr parent;
1364
1365 if (cur == NULL) {
1366 fprintf(stderr, "xmlAddSibling : cur == NULL\n");
1367 return(NULL);
1368 }
1369
1370 if (elem == NULL) {
1371 fprintf(stderr, "xmlAddSibling : elem == NULL\n");
1372 return(NULL);
1373 }
1374
1375 if ((cur->doc != NULL) && (elem->doc != NULL) &&
1376 (cur->doc != elem->doc)) {
1377 fprintf(stderr,
1378 "xmlAddSibling: Elements moved to a different document\n");
1379 }
1380
1381 while (cur->next != NULL) cur = cur->next;
1382
1383 if (elem->doc == NULL)
1384 elem->doc = cur->doc; /* the parent may not be linked to a doc ! */
1385
1386 parent = cur->parent;
1387 elem->prev = cur;
1388 elem->next = NULL;
1389 elem->parent = parent;
1390 cur->next = elem;
1391 if (parent != NULL)
1392 parent->last = elem;
1393
1394 return(elem);
1395}
1396
1397/**
Daniel Veillard97b58771998-10-20 06:14:16 +00001398 * xmlAddChild:
1399 * @parent: the parent node
1400 * @cur: the child node
1401 *
1402 * Add a new child element, to @parent, at the end of the child list.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001403 * Returns the child or NULL in case of error.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001404 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001405xmlNodePtr
1406xmlAddChild(xmlNodePtr parent, xmlNodePtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001407 xmlNodePtr prev;
1408
1409 if (parent == NULL) {
1410 fprintf(stderr, "xmladdChild : parent == NULL\n");
1411 return(NULL);
1412 }
1413
1414 if (cur == NULL) {
1415 fprintf(stderr, "xmladdChild : child == NULL\n");
1416 return(NULL);
1417 }
1418
Daniel Veillard0bef1311998-10-14 02:36:47 +00001419 if ((cur->doc != NULL) && (parent->doc != NULL) &&
1420 (cur->doc != parent->doc)) {
1421 fprintf(stderr, "Elements moved to a different document\n");
1422 }
1423
Daniel Veillard260a68f1998-08-13 03:39:55 +00001424 /*
1425 * add the new element at the end of the childs list.
1426 */
1427 cur->parent = parent;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001428 cur->doc = parent->doc; /* the parent may not be linked to a doc ! */
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001429
Daniel Veillardccb09631998-10-27 06:21:04 +00001430 /*
1431 * Handle the case where parent->content != NULL, in that case it will
1432 * create a intermediate TEXT node.
1433 */
1434 if (parent->content != NULL) {
1435 xmlNodePtr text;
1436
1437 text = xmlNewDocText(parent->doc, parent->content);
1438 if (text != NULL) {
1439 text->next = parent->childs;
1440 if (text->next != NULL)
1441 text->next->prev = text;
1442 parent->childs = text;
Daniel Veillard1e346af1999-02-22 10:33:01 +00001443 UPDATE_LAST_CHILD(parent)
Daniel Veillard6454aec1999-09-02 22:04:43 +00001444 xmlFree(parent->content);
Daniel Veillardccb09631998-10-27 06:21:04 +00001445 parent->content = NULL;
1446 }
1447 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00001448 if (parent->childs == NULL) {
1449 parent->childs = cur;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001450 parent->last = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001451 } else {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001452 prev = parent->last;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001453 prev->next = cur;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001454 cur->prev = prev;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001455 parent->last = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001456 }
1457
1458 return(cur);
1459}
1460
Daniel Veillard97b58771998-10-20 06:14:16 +00001461/**
1462 * xmlGetLastChild:
1463 * @parent: the parent node
1464 *
1465 * Search the last child of a node.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001466 * Returns the last child or NULL if none.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001467 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001468xmlNodePtr
1469xmlGetLastChild(xmlNodePtr parent) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001470 if (parent == NULL) {
1471 fprintf(stderr, "xmlGetLastChild : parent == NULL\n");
1472 return(NULL);
1473 }
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001474 return(parent->last);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001475}
1476
Daniel Veillard97b58771998-10-20 06:14:16 +00001477/**
1478 * xmlFreeNodeList:
1479 * @cur: the first node in the list
1480 *
1481 * Free a node and all its siblings, this is a recursive behaviour, all
1482 * the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001483 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001484void
1485xmlFreeNodeList(xmlNodePtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001486 xmlNodePtr next;
1487 if (cur == NULL) {
1488 fprintf(stderr, "xmlFreeNodeList : node == NULL\n");
1489 return;
1490 }
1491 while (cur != NULL) {
1492 next = cur->next;
1493 xmlFreeNode(cur);
1494 cur = next;
1495 }
1496}
1497
Daniel Veillard97b58771998-10-20 06:14:16 +00001498/**
1499 * xmlFreeNode:
1500 * @cur: the node
1501 *
1502 * Free a node, this is a recursive behaviour, all the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001503 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001504void
1505xmlFreeNode(xmlNodePtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001506 if (cur == NULL) {
1507 fprintf(stderr, "xmlFreeNode : node == NULL\n");
1508 return;
1509 }
Daniel Veillardccb09631998-10-27 06:21:04 +00001510 cur->doc = NULL;
1511 cur->parent = NULL;
1512 cur->next = NULL;
1513 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001514 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillardccb09631998-10-27 06:21:04 +00001515 if (cur->properties != NULL) xmlFreePropList(cur->properties);
1516 if (cur->type != XML_ENTITY_REF_NODE)
Daniel Veillard6454aec1999-09-02 22:04:43 +00001517 if (cur->content != NULL) xmlFree(cur->content);
1518 if (cur->name != NULL) xmlFree((char *) cur->name);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001519 if (cur->nsDef != NULL) xmlFreeNsList(cur->nsDef);
1520 memset(cur, -1, sizeof(xmlNode));
Daniel Veillard6454aec1999-09-02 22:04:43 +00001521 xmlFree(cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001522}
1523
Daniel Veillard16253641998-10-28 22:58:05 +00001524/**
1525 * xmlUnlinkNode:
1526 * @cur: the node
1527 *
1528 * Unlink a node from it's current context, the node is not freed
1529 */
1530void
1531xmlUnlinkNode(xmlNodePtr cur) {
1532 if (cur == NULL) {
1533 fprintf(stderr, "xmlUnlinkNode : node == NULL\n");
1534 return;
1535 }
1536 if ((cur->parent != NULL) && (cur->parent->childs == cur))
1537 cur->parent->childs = cur->next;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001538 if ((cur->parent != NULL) && (cur->parent->last == cur))
1539 cur->parent->last = cur->prev;
Daniel Veillard16253641998-10-28 22:58:05 +00001540 if (cur->next != NULL)
1541 cur->next->prev = cur->prev;
1542 if (cur->prev != NULL)
1543 cur->prev->next = cur->next;
1544 cur->next = cur->prev = NULL;
1545 cur->parent = NULL;
1546}
1547
Daniel Veillard260a68f1998-08-13 03:39:55 +00001548/************************************************************************
1549 * *
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001550 * Copy operations *
1551 * *
1552 ************************************************************************/
1553
1554/**
1555 * xmlCopyNamespace:
1556 * @cur: the namespace
1557 *
1558 * Do a copy of the namespace.
1559 *
1560 * Returns: a new xmlNsPtr, or NULL in case of error.
1561 */
1562xmlNsPtr
1563xmlCopyNamespace(xmlNsPtr cur) {
1564 xmlNsPtr ret;
1565
1566 if (cur == NULL) return(NULL);
1567 switch (cur->type) {
1568 case XML_GLOBAL_NAMESPACE:
1569 ret = xmlNewGlobalNs(NULL, cur->href, cur->prefix);
1570 break;
1571 case XML_LOCAL_NAMESPACE:
1572 ret = xmlNewNs(NULL, cur->href, cur->prefix);
1573 break;
1574 default:
1575 fprintf(stderr, "xmlCopyNamespace: unknown type %d\n", cur->type);
1576 return(NULL);
1577 }
1578 return(ret);
1579}
1580
1581/**
1582 * xmlCopyNamespaceList:
1583 * @cur: the first namespace
1584 *
1585 * Do a copy of an namespace list.
1586 *
1587 * Returns: a new xmlNsPtr, or NULL in case of error.
1588 */
1589xmlNsPtr
1590xmlCopyNamespaceList(xmlNsPtr cur) {
1591 xmlNsPtr ret = NULL;
1592 xmlNsPtr p = NULL,q;
1593
1594 while (cur != NULL) {
1595 q = xmlCopyNamespace(cur);
1596 if (p == NULL) {
1597 ret = p = q;
1598 } else {
1599 p->next = q;
1600 p = q;
1601 }
1602 cur = cur->next;
1603 }
1604 return(ret);
1605}
1606
1607/**
1608 * xmlCopyProp:
Daniel Veillardb96e6431999-08-29 21:02:19 +00001609 * @target: the element where the attribute will be grafted
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001610 * @cur: the attribute
1611 *
1612 * Do a copy of the attribute.
1613 *
1614 * Returns: a new xmlAttrPtr, or NULL in case of error.
1615 */
1616xmlAttrPtr
Daniel Veillardb96e6431999-08-29 21:02:19 +00001617xmlCopyProp(xmlNodePtr target, xmlAttrPtr cur) {
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001618 xmlAttrPtr ret;
1619
1620 if (cur == NULL) return(NULL);
1621 if (cur->val != NULL)
1622 ret = xmlNewDocProp(cur->val->doc, cur->name, NULL);
1623 else
1624 ret = xmlNewDocProp(NULL, cur->name, NULL);
1625 if (ret == NULL) return(NULL);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001626
1627 if ((cur->ns != NULL) && (target != NULL)) {
1628 xmlNsPtr ns;
1629
1630 ns = xmlSearchNs(target->doc, target, cur->ns->prefix);
1631 ret->ns = ns;
1632 } else
1633 ret->ns = NULL;
1634
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001635 if (cur->val != NULL)
1636 ret->val = xmlCopyNodeList(cur->val);
1637 return(ret);
1638}
1639
1640/**
1641 * xmlCopyPropList:
Daniel Veillardb96e6431999-08-29 21:02:19 +00001642 * @target: the element where the attributes will be grafted
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001643 * @cur: the first attribute
1644 *
1645 * Do a copy of an attribute list.
1646 *
1647 * Returns: a new xmlAttrPtr, or NULL in case of error.
1648 */
1649xmlAttrPtr
Daniel Veillardb96e6431999-08-29 21:02:19 +00001650xmlCopyPropList(xmlNodePtr target, xmlAttrPtr cur) {
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001651 xmlAttrPtr ret = NULL;
1652 xmlAttrPtr p = NULL,q;
1653
1654 while (cur != NULL) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00001655 q = xmlCopyProp(target, cur);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001656 if (p == NULL) {
1657 ret = p = q;
1658 } else {
1659 p->next = q;
1660 p = q;
1661 }
1662 cur = cur->next;
1663 }
1664 return(ret);
1665}
1666
1667/*
1668 * NOTE about the CopyNode operations !
1669 *
1670 * They are splitted into external and internal parts for one
1671 * tricky reason: namespaces. Doing a direct copy of a node
1672 * say RPM:Copyright without changing the namespace pointer to
1673 * something else can produce stale links. One way to do it is
1674 * to keep a reference counter but this doesn't work as soon
1675 * as one move the element or the subtree out of the scope of
1676 * the existing namespace. The actual solution seems to add
1677 * a copy of the namespace at the top of the copied tree if
1678 * not available in the subtree.
1679 * Hence two functions, the public front-end call the inner ones
1680 */
1681
1682static xmlNodePtr
1683xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent);
1684
1685static xmlNodePtr
1686xmlStaticCopyNode(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent,
1687 int recursive) {
1688 xmlNodePtr ret;
1689
1690 if (node == NULL) return(NULL);
1691 /*
1692 * Allocate a new node and fill the fields.
1693 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001694 ret = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001695 if (ret == NULL) {
1696 fprintf(stderr, "xmlStaticCopyNode : malloc failed\n");
1697 return(NULL);
1698 }
1699
1700 ret->type = node->type;
1701 ret->doc = doc;
1702 ret->parent = parent;
1703 ret->next = NULL;
1704 ret->prev = NULL;
1705 ret->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001706 ret->last = NULL;
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001707 ret->properties = NULL;
1708 if (node->name != NULL)
1709 ret->name = xmlStrdup(node->name);
1710 else
1711 ret->name = NULL;
1712 ret->ns = NULL;
1713 ret->nsDef = NULL;
1714 if ((node->content != NULL) && (node->type != XML_ENTITY_REF_NODE))
1715 ret->content = xmlStrdup(node->content);
1716 else
1717 ret->content = NULL;
Daniel Veillard27d88741999-05-29 11:51:49 +00001718#ifndef XML_WITHOUT_CORBA
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001719 ret->_private = NULL;
1720 ret->vepv = NULL;
1721#endif
1722 if (parent != NULL)
1723 xmlAddChild(parent, ret);
1724
1725 if (!recursive) return(ret);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001726 if (node->nsDef != NULL)
1727 ret->nsDef = xmlCopyNamespaceList(node->nsDef);
1728
1729 if (node->ns != NULL) {
1730 xmlNsPtr ns;
1731
1732 ns = xmlSearchNs(doc, ret, node->ns->prefix);
1733 if (ns == NULL) {
1734 /*
1735 * Humm, we are copying an element whose namespace is defined
1736 * out of the new tree scope. Search it in the original tree
1737 * and add it at the top of the new tree
1738 */
1739 ns = xmlSearchNs(node->doc, node, node->ns->prefix);
1740 if (ns != NULL) {
1741 xmlNodePtr root = ret;
1742
1743 while (root->parent != NULL) root = root->parent;
1744 xmlNewNs(root, ns->href, ns->prefix);
1745 }
1746 } else {
1747 /*
1748 * reference the existing namespace definition in our own tree.
1749 */
1750 ret->ns = ns;
1751 }
1752 }
Daniel Veillardb96e6431999-08-29 21:02:19 +00001753 if (node->properties != NULL)
1754 ret->properties = xmlCopyPropList(ret, node->properties);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001755 if (node->childs != NULL)
1756 ret->childs = xmlStaticCopyNodeList(node->childs, doc, ret);
Daniel Veillard1e346af1999-02-22 10:33:01 +00001757 UPDATE_LAST_CHILD(ret)
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001758 return(ret);
1759}
1760
1761static xmlNodePtr
1762xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent) {
1763 xmlNodePtr ret = NULL;
1764 xmlNodePtr p = NULL,q;
1765
1766 while (node != NULL) {
1767 q = xmlStaticCopyNode(node, doc, parent, 1);
1768 if (parent == NULL) {
1769 if (ret == NULL) ret = q;
1770 } else {
1771 if (ret == NULL) {
1772 q->prev = NULL;
1773 ret = p = q;
1774 } else {
1775 p->next = q;
1776 q->prev = p;
1777 p = q;
1778 }
1779 }
1780 node = node->next;
1781 }
1782 return(ret);
1783}
1784
1785/**
1786 * xmlCopyNode:
1787 * @node: the node
1788 * @recursive: if 1 do a recursive copy.
1789 *
1790 * Do a copy of the node.
1791 *
1792 * Returns: a new xmlNodePtr, or NULL in case of error.
1793 */
1794xmlNodePtr
1795xmlCopyNode(xmlNodePtr node, int recursive) {
1796 xmlNodePtr ret;
1797
1798 ret = xmlStaticCopyNode(node, NULL, NULL, recursive);
1799 return(ret);
1800}
1801
1802/**
1803 * xmlCopyNodeList:
1804 * @node: the first node in the list.
1805 *
1806 * Do a recursive copy of the node list.
1807 *
1808 * Returns: a new xmlNodePtr, or NULL in case of error.
1809 */
1810xmlNodePtr xmlCopyNodeList(xmlNodePtr node) {
1811 xmlNodePtr ret = xmlStaticCopyNodeList(node, NULL, NULL);
1812 return(ret);
1813}
1814
1815/**
1816 * xmlCopyElement:
1817 * @elem: the element
1818 *
1819 * Do a copy of the element definition.
1820 *
1821 * Returns: a new xmlElementPtr, or NULL in case of error.
1822xmlElementPtr
1823xmlCopyElement(xmlElementPtr elem) {
1824 xmlElementPtr ret;
1825
1826 if (elem == NULL) return(NULL);
1827 ret = xmlNewDocElement(elem->doc, elem->ns, elem->name, elem->content);
1828 if (ret == NULL) return(NULL);
1829 if (!recursive) return(ret);
1830 if (elem->properties != NULL)
1831 ret->properties = xmlCopyPropList(elem->properties);
1832
1833 if (elem->nsDef != NULL)
1834 ret->nsDef = xmlCopyNamespaceList(elem->nsDef);
1835 if (elem->childs != NULL)
1836 ret->childs = xmlCopyElementList(elem->childs);
1837 return(ret);
1838}
1839 */
1840
1841/**
1842 * xmlCopyDtd:
1843 * @dtd: the dtd
1844 *
1845 * Do a copy of the dtd.
1846 *
1847 * Returns: a new xmlDtdPtr, or NULL in case of error.
1848 */
1849xmlDtdPtr
1850xmlCopyDtd(xmlDtdPtr dtd) {
1851 xmlDtdPtr ret;
1852
1853 if (dtd == NULL) return(NULL);
1854 ret = xmlNewDtd(NULL, dtd->name, dtd->ExternalID, dtd->SystemID);
1855 if (ret == NULL) return(NULL);
1856 if (dtd->entities != NULL)
1857 ret->entities = (void *) xmlCopyEntitiesTable(
1858 (xmlEntitiesTablePtr) dtd->entities);
Daniel Veillard1e346af1999-02-22 10:33:01 +00001859 if (dtd->notations != NULL)
1860 ret->notations = (void *) xmlCopyNotationTable(
1861 (xmlNotationTablePtr) dtd->notations);
1862 if (dtd->elements != NULL)
1863 ret->elements = (void *) xmlCopyElementTable(
1864 (xmlElementTablePtr) dtd->elements);
1865 if (dtd->attributes != NULL)
1866 ret->attributes = (void *) xmlCopyAttributeTable(
1867 (xmlAttributeTablePtr) dtd->attributes);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001868 return(ret);
1869}
1870
1871/**
1872 * xmlCopyDoc:
1873 * @doc: the document
1874 * @recursive: if 1 do a recursive copy.
1875 *
1876 * Do a copy of the document info. If recursive, the content tree will
1877 * be copied too as well as Dtd, namespaces and entities.
1878 *
1879 * Returns: a new xmlDocPtr, or NULL in case of error.
1880 */
1881xmlDocPtr
1882xmlCopyDoc(xmlDocPtr doc, int recursive) {
1883 xmlDocPtr ret;
1884
1885 if (doc == NULL) return(NULL);
1886 ret = xmlNewDoc(doc->version);
1887 if (ret == NULL) return(NULL);
1888 if (doc->name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +00001889 ret->name = xmlMemStrdup(doc->name);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001890 if (doc->encoding != NULL)
1891 ret->encoding = xmlStrdup(doc->encoding);
1892 ret->compression = doc->compression;
1893 ret->standalone = doc->standalone;
1894 if (!recursive) return(ret);
1895
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001896 if (doc->intSubset != NULL)
1897 ret->intSubset = xmlCopyDtd(doc->intSubset);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001898 if (doc->oldNs != NULL)
1899 ret->oldNs = xmlCopyNamespaceList(doc->oldNs);
1900 if (doc->root != NULL)
1901 ret->root = xmlStaticCopyNodeList(doc->root, ret, NULL);
1902 return(ret);
1903}
1904
1905/************************************************************************
1906 * *
Daniel Veillard260a68f1998-08-13 03:39:55 +00001907 * Content access functions *
1908 * *
1909 ************************************************************************/
1910
Daniel Veillard97b58771998-10-20 06:14:16 +00001911/**
Daniel Veillardb96e6431999-08-29 21:02:19 +00001912 * xmlNodeSetLang:
1913 * @cur: the node being changed
1914 * @lang: the langage description
1915 *
1916 * Searches the language of a node, i.e. the values of the xml:lang
1917 * attribute or the one carried by the nearest ancestor.
1918 *
1919 * Returns a pointer to the lang value, or NULL if not found
1920 */
1921void
1922xmlNodeSetLang(xmlNodePtr cur, const CHAR *lang) {
1923 /* TODO xmlNodeSetLang check against the production [33] LanguageID */
1924 xmlSetProp(cur, BAD_CAST "xml:lang", lang);
1925}
1926
1927/**
1928 * xmlNodeGetLang:
1929 * @cur: the node being checked
1930 *
1931 * Searches the language of a node, i.e. the values of the xml:lang
1932 * attribute or the one carried by the nearest ancestor.
1933 *
1934 * Returns a pointer to the lang value, or NULL if not found
1935 */
1936const CHAR *
1937xmlNodeGetLang(xmlNodePtr cur) {
1938 const CHAR *lang;
1939
1940 while (cur != NULL) {
1941 lang = xmlGetProp(cur, BAD_CAST "xml:lang");
1942 if (lang != NULL)
1943 return(lang);
1944 cur = cur->parent;
1945 }
1946 return(NULL);
1947}
1948
1949/**
Daniel Veillard16253641998-10-28 22:58:05 +00001950 * xmlNodeGetContent:
1951 * @cur: the node being read
1952 *
1953 * Read the value of a node, this can be either the text carried
1954 * directly by this node if it's a TEXT node or the aggregate string
1955 * of the values carried by this node child's (TEXT and ENTITY_REF).
1956 * Entity references are substitued.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001957 * Returns a new CHAR * or NULL if no content is available.
Daniel Veillard5099ae81999-04-21 20:12:07 +00001958 * It's up to the caller to free the memory.
Daniel Veillard16253641998-10-28 22:58:05 +00001959 */
1960CHAR *
1961xmlNodeGetContent(xmlNodePtr cur) {
1962 if (cur == NULL) return(NULL);
1963 switch (cur->type) {
1964 case XML_DOCUMENT_FRAG_NODE:
1965 case XML_ELEMENT_NODE:
1966 return(xmlNodeListGetString(cur->doc, cur->childs, 1));
1967 break;
Daniel Veillardb96e6431999-08-29 21:02:19 +00001968 case XML_ATTRIBUTE_NODE: {
1969 xmlAttrPtr attr = (xmlAttrPtr) cur;
1970 if (attr->node != NULL)
1971 return(xmlNodeListGetString(attr->node->doc, attr->val, 1));
1972 else
1973 return(xmlNodeListGetString(NULL, attr->val, 1));
1974 break;
1975 }
1976 case XML_PI_NODE:
1977 if (cur->content != NULL)
1978 return(xmlStrdup(cur->content));
1979 return(NULL);
Daniel Veillard16253641998-10-28 22:58:05 +00001980 case XML_ENTITY_REF_NODE:
1981 case XML_ENTITY_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00001982 case XML_COMMENT_NODE:
1983 case XML_DOCUMENT_NODE:
1984 case XML_DOCUMENT_TYPE_NODE:
1985 case XML_NOTATION_NODE:
1986 return(NULL);
Daniel Veillardb05deb71999-08-10 19:04:08 +00001987 case XML_CDATA_SECTION_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00001988 case XML_TEXT_NODE:
1989 if (cur->content != NULL)
1990 return(xmlStrdup(cur->content));
1991 return(NULL);
1992 }
1993 return(NULL);
1994}
1995
1996/**
Daniel Veillard97b58771998-10-20 06:14:16 +00001997 * xmlNodeSetContent:
1998 * @cur: the node being modified
1999 * @content: the new value of the content
2000 *
2001 * Replace the content of a node.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002002 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002003void
2004xmlNodeSetContent(xmlNodePtr cur, const CHAR *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002005 if (cur == NULL) {
2006 fprintf(stderr, "xmlNodeSetContent : node == NULL\n");
2007 return;
2008 }
Daniel Veillard16253641998-10-28 22:58:05 +00002009 switch (cur->type) {
2010 case XML_DOCUMENT_FRAG_NODE:
2011 case XML_ELEMENT_NODE:
2012 if (cur->content != NULL) {
Daniel Veillard6454aec1999-09-02 22:04:43 +00002013 xmlFree(cur->content);
Daniel Veillard16253641998-10-28 22:58:05 +00002014 cur->content = NULL;
2015 }
Daniel Veillard6454aec1999-09-02 22:04:43 +00002016 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillard16253641998-10-28 22:58:05 +00002017 cur->childs = xmlStringGetNodeList(cur->doc, content);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002018 UPDATE_LAST_CHILD(cur)
Daniel Veillard16253641998-10-28 22:58:05 +00002019 break;
2020 case XML_ATTRIBUTE_NODE:
2021 break;
2022 case XML_TEXT_NODE:
2023 case XML_CDATA_SECTION_NODE:
2024 case XML_ENTITY_REF_NODE:
2025 case XML_ENTITY_NODE:
2026 case XML_PI_NODE:
2027 case XML_COMMENT_NODE:
Daniel Veillard6454aec1999-09-02 22:04:43 +00002028 if (cur->content != NULL) xmlFree(cur->content);
2029 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002030 cur->last = cur->childs = NULL;
Daniel Veillard16253641998-10-28 22:58:05 +00002031 if (content != NULL)
2032 cur->content = xmlStrdup(content);
2033 else
2034 cur->content = NULL;
Daniel Veillardb96e6431999-08-29 21:02:19 +00002035 break;
Daniel Veillard16253641998-10-28 22:58:05 +00002036 case XML_DOCUMENT_NODE:
2037 case XML_DOCUMENT_TYPE_NODE:
2038 break;
2039 case XML_NOTATION_NODE:
2040 break;
2041 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002042}
2043
Daniel Veillard97b58771998-10-20 06:14:16 +00002044/**
2045 * xmlNodeSetContentLen:
2046 * @cur: the node being modified
2047 * @content: the new value of the content
2048 * @len: the size of @content
2049 *
2050 * Replace the content of a node.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002051 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002052void
2053xmlNodeSetContentLen(xmlNodePtr cur, const CHAR *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002054 if (cur == NULL) {
Daniel Veillard16253641998-10-28 22:58:05 +00002055 fprintf(stderr, "xmlNodeSetContentLen : node == NULL\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002056 return;
2057 }
Daniel Veillard16253641998-10-28 22:58:05 +00002058 switch (cur->type) {
2059 case XML_DOCUMENT_FRAG_NODE:
2060 case XML_ELEMENT_NODE:
2061 if (cur->content != NULL) {
Daniel Veillard6454aec1999-09-02 22:04:43 +00002062 xmlFree(cur->content);
Daniel Veillard16253641998-10-28 22:58:05 +00002063 cur->content = NULL;
2064 }
Daniel Veillard6454aec1999-09-02 22:04:43 +00002065 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillard16253641998-10-28 22:58:05 +00002066 cur->childs = xmlStringLenGetNodeList(cur->doc, content, len);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002067 UPDATE_LAST_CHILD(cur)
Daniel Veillard16253641998-10-28 22:58:05 +00002068 break;
2069 case XML_ATTRIBUTE_NODE:
2070 break;
2071 case XML_TEXT_NODE:
2072 case XML_CDATA_SECTION_NODE:
2073 case XML_ENTITY_REF_NODE:
2074 case XML_ENTITY_NODE:
2075 case XML_PI_NODE:
2076 case XML_COMMENT_NODE:
Daniel Veillard6454aec1999-09-02 22:04:43 +00002077 if (cur->content != NULL) xmlFree(cur->content);
2078 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002079 cur->childs = cur->last = NULL;
Daniel Veillard16253641998-10-28 22:58:05 +00002080 if (content != NULL)
2081 cur->content = xmlStrndup(content, len);
2082 else
2083 cur->content = NULL;
Daniel Veillardb96e6431999-08-29 21:02:19 +00002084 break;
Daniel Veillard16253641998-10-28 22:58:05 +00002085 case XML_DOCUMENT_NODE:
2086 case XML_DOCUMENT_TYPE_NODE:
2087 break;
2088 case XML_NOTATION_NODE:
Daniel Veillard6454aec1999-09-02 22:04:43 +00002089 if (cur->content != NULL) xmlFree(cur->content);
2090 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002091 cur->childs = cur->last = NULL;
Daniel Veillard16253641998-10-28 22:58:05 +00002092 if (content != NULL)
2093 cur->content = xmlStrndup(content, len);
2094 else
2095 cur->content = NULL;
2096 break;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002097 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002098}
2099
Daniel Veillard97b58771998-10-20 06:14:16 +00002100/**
2101 * xmlNodeAddContentLen:
2102 * @cur: the node being modified
2103 * @content: extra content
2104 * @len: the size of @content
2105 *
2106 * Append the extra substring to the node content.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002107 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002108void
2109xmlNodeAddContentLen(xmlNodePtr cur, const CHAR *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002110 if (cur == NULL) {
Daniel Veillard16253641998-10-28 22:58:05 +00002111 fprintf(stderr, "xmlNodeAddContentLen : node == NULL\n");
2112 return;
2113 }
2114 if (len <= 0) return;
2115 switch (cur->type) {
2116 case XML_DOCUMENT_FRAG_NODE:
2117 case XML_ELEMENT_NODE: {
2118 xmlNodePtr last = NULL, new;
2119
2120 if (cur->childs != NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002121 last = cur->last;
Daniel Veillard16253641998-10-28 22:58:05 +00002122 } else {
2123 if (cur->content != NULL) {
2124 cur->childs = xmlStringGetNodeList(cur->doc, cur->content);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002125 UPDATE_LAST_CHILD(cur)
Daniel Veillard6454aec1999-09-02 22:04:43 +00002126 xmlFree(cur->content);
Daniel Veillard16253641998-10-28 22:58:05 +00002127 cur->content = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002128 last = cur->last;
Daniel Veillard16253641998-10-28 22:58:05 +00002129 }
2130 }
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002131 new = xmlNewTextLen(content, len);
Daniel Veillard16253641998-10-28 22:58:05 +00002132 if (new != NULL) {
2133 xmlAddChild(cur, new);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002134 if ((last != NULL) && (last->next == new)) {
Daniel Veillard16253641998-10-28 22:58:05 +00002135 xmlTextMerge(last, new);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002136 }
Daniel Veillard16253641998-10-28 22:58:05 +00002137 }
2138 break;
2139 }
2140 case XML_ATTRIBUTE_NODE:
2141 break;
2142 case XML_TEXT_NODE:
2143 case XML_CDATA_SECTION_NODE:
2144 case XML_ENTITY_REF_NODE:
2145 case XML_ENTITY_NODE:
2146 case XML_PI_NODE:
2147 case XML_COMMENT_NODE:
2148 if (content != NULL)
2149 cur->content = xmlStrncat(cur->content, content, len);
2150 case XML_DOCUMENT_NODE:
2151 case XML_DOCUMENT_TYPE_NODE:
2152 break;
2153 case XML_NOTATION_NODE:
2154 if (content != NULL)
2155 cur->content = xmlStrncat(cur->content, content, len);
2156 break;
2157 }
2158}
2159
2160/**
2161 * xmlNodeAddContent:
2162 * @cur: the node being modified
2163 * @content: extra content
2164 *
2165 * Append the extra substring to the node content.
2166 */
2167void
2168xmlNodeAddContent(xmlNodePtr cur, const CHAR *content) {
2169 int len;
2170
2171 if (cur == NULL) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002172 fprintf(stderr, "xmlNodeAddContent : node == NULL\n");
2173 return;
2174 }
Daniel Veillard16253641998-10-28 22:58:05 +00002175 if (content == NULL) return;
2176 len = xmlStrlen(content);
2177 xmlNodeAddContentLen(cur, content, len);
2178}
2179
2180/**
2181 * xmlTextMerge:
2182 * @first: the first text node
2183 * @second: the second text node being merged
2184 *
2185 * Merge two text nodes into one
Daniel Veillard1e346af1999-02-22 10:33:01 +00002186 * Returns the first text node augmented
Daniel Veillard16253641998-10-28 22:58:05 +00002187 */
2188xmlNodePtr
2189xmlTextMerge(xmlNodePtr first, xmlNodePtr second) {
2190 if (first == NULL) return(second);
2191 if (second == NULL) return(first);
2192 if (first->type != XML_TEXT_NODE) return(first);
2193 if (second->type != XML_TEXT_NODE) return(first);
2194 xmlNodeAddContent(first, second->content);
2195 xmlUnlinkNode(second);
2196 xmlFreeNode(second);
2197 return(first);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002198}
2199
Daniel Veillard97b58771998-10-20 06:14:16 +00002200/**
Daniel Veillardb96e6431999-08-29 21:02:19 +00002201 * xmlGetNsList:
2202 * @doc: the document
2203 * @node: the current node
2204 *
2205 * Search all the namespace applying to a given element.
2206 * Returns an NULL terminated array of all the xmlNsPtr found
2207 * that need to be freed by the caller or NULL if no
2208 * namespace if defined
2209 */
2210xmlNsPtr *
2211xmlGetNsList(xmlDocPtr doc, xmlNodePtr node) {
2212 xmlNsPtr cur;
2213 xmlNsPtr *ret = NULL;
2214 int nbns = 0;
2215 int maxns = 10;
2216 int i;
2217
2218 while (node != NULL) {
2219 cur = node->nsDef;
2220 while (cur != NULL) {
2221 if (ret == NULL) {
Daniel Veillard6454aec1999-09-02 22:04:43 +00002222 ret = (xmlNsPtr *) xmlMalloc((maxns + 1) * sizeof(xmlNsPtr));
Daniel Veillardb96e6431999-08-29 21:02:19 +00002223 if (ret == NULL) {
2224 fprintf(stderr, "xmlGetNsList : out of memory!\n");
2225 return(NULL);
2226 }
2227 ret[nbns] = NULL;
2228 }
2229 for (i = 0;i < nbns;i++) {
2230 if ((cur->prefix == ret[i]->prefix) ||
2231 (!xmlStrcmp(cur->prefix, ret[i]->prefix))) break;
2232 }
2233 if (i >= nbns) {
2234 if (nbns >= maxns) {
2235 maxns *= 2;
Daniel Veillard6454aec1999-09-02 22:04:43 +00002236 ret = (xmlNsPtr *) xmlRealloc(ret,
Daniel Veillardb96e6431999-08-29 21:02:19 +00002237 (maxns + 1) * sizeof(xmlNsPtr));
2238 if (ret == NULL) {
2239 fprintf(stderr, "xmlGetNsList : realloc failed!\n");
2240 return(NULL);
2241 }
2242 }
2243 ret[nbns++] = cur;
2244 ret[nbns] = NULL;
2245 }
2246
2247 cur = cur->next;
2248 }
2249 node = node->parent;
2250 }
2251 return(ret);
2252}
2253
2254/**
Daniel Veillard97b58771998-10-20 06:14:16 +00002255 * xmlSearchNs:
2256 * @doc: the document
2257 * @node: the current node
2258 * @nameSpace: the namespace string
Daniel Veillard260a68f1998-08-13 03:39:55 +00002259 *
Daniel Veillard97b58771998-10-20 06:14:16 +00002260 * Search a Ns registered under a given name space for a document.
2261 * recurse on the parents until it finds the defined namespace
2262 * or return NULL otherwise.
2263 * @nameSpace can be NULL, this is a search for the default namespace.
Daniel Veillard1e346af1999-02-22 10:33:01 +00002264 * Returns the namespace pointer or NULL.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002265 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002266xmlNsPtr
2267xmlSearchNs(xmlDocPtr doc, xmlNodePtr node, const CHAR *nameSpace) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002268 xmlNsPtr cur;
2269
2270 while (node != NULL) {
2271 cur = node->nsDef;
2272 while (cur != NULL) {
2273 if ((cur->prefix == NULL) && (nameSpace == NULL))
2274 return(cur);
2275 if ((cur->prefix != NULL) && (nameSpace != NULL) &&
2276 (!xmlStrcmp(cur->prefix, nameSpace)))
2277 return(cur);
2278 cur = cur->next;
2279 }
2280 node = node->parent;
2281 }
2282 if (doc != NULL) {
2283 cur = doc->oldNs;
2284 while (cur != NULL) {
2285 if ((cur->prefix != NULL) && (nameSpace != NULL) &&
2286 (!xmlStrcmp(cur->prefix, nameSpace)))
2287 return(cur);
2288 cur = cur->next;
2289 }
2290 }
2291 return(NULL);
2292}
2293
Daniel Veillard97b58771998-10-20 06:14:16 +00002294/**
2295 * xmlSearchNsByHref:
2296 * @doc: the document
2297 * @node: the current node
2298 * @href: the namespace value
2299 *
2300 * Search a Ns aliasing a given URI. Recurse on the parents until it finds
2301 * the defined namespace or return NULL otherwise.
Daniel Veillard1e346af1999-02-22 10:33:01 +00002302 * Returns the namespace pointer or NULL.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002303 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002304xmlNsPtr
2305xmlSearchNsByHref(xmlDocPtr doc, xmlNodePtr node, const CHAR *href) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002306 xmlNsPtr cur;
2307
2308 while (node != NULL) {
2309 cur = node->nsDef;
2310 while (cur != NULL) {
2311 if ((cur->href != NULL) && (href != NULL) &&
2312 (!xmlStrcmp(cur->href, href)))
2313 return(cur);
2314 cur = cur->next;
2315 }
2316 node = node->parent;
2317 }
2318 if (doc != NULL) {
2319 cur = doc->oldNs;
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 }
2327 return(NULL);
2328}
2329
Daniel Veillard97b58771998-10-20 06:14:16 +00002330/**
2331 * xmlGetProp:
2332 * @node: the node
2333 * @name: the attribute name
2334 *
2335 * Search and get the value of an attribute associated to a node
Daniel Veillardccb09631998-10-27 06:21:04 +00002336 * This does the entity substitution.
Daniel Veillard1e346af1999-02-22 10:33:01 +00002337 * Returns the attribute value or NULL if not found.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002338 */
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002339CHAR *xmlGetProp(xmlNodePtr node, const CHAR *name) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002340 xmlAttrPtr prop = node->properties;
2341
2342 while (prop != NULL) {
Daniel Veillard68178931999-02-08 18:34:36 +00002343 if (!xmlStrcmp(prop->name, name)) {
Daniel Veillard6800ef31999-02-08 18:33:22 +00002344 CHAR *ret;
2345
2346 ret = xmlNodeListGetString(node->doc, prop->val, 1);
Daniel Veillardb96e6431999-08-29 21:02:19 +00002347 if (ret == NULL) return(xmlStrdup((CHAR *)""));
Daniel Veillard6800ef31999-02-08 18:33:22 +00002348 return(ret);
Daniel Veillard68178931999-02-08 18:34:36 +00002349 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002350 prop = prop->next;
2351 }
2352 return(NULL);
2353}
2354
Daniel Veillard97b58771998-10-20 06:14:16 +00002355/**
Daniel Veillardccb09631998-10-27 06:21:04 +00002356 * xmlSetProp:
Daniel Veillard97b58771998-10-20 06:14:16 +00002357 * @node: the node
2358 * @name: the attribute name
2359 * @value: the attribute value
2360 *
2361 * Set (or reset) an attribute carried by a node.
Daniel Veillard1e346af1999-02-22 10:33:01 +00002362 * Returns the attribute pointer.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002363 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002364xmlAttrPtr
2365xmlSetProp(xmlNodePtr node, const CHAR *name, const CHAR *value) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002366 xmlAttrPtr prop = node->properties;
2367
2368 while (prop != NULL) {
2369 if (!xmlStrcmp(prop->name, name)) {
Daniel Veillardccb09631998-10-27 06:21:04 +00002370 if (prop->val != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +00002371 xmlFreeNodeList(prop->val);
Daniel Veillardccb09631998-10-27 06:21:04 +00002372 prop->val = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002373 if (value != NULL)
Daniel Veillardccb09631998-10-27 06:21:04 +00002374 prop->val = xmlStringGetNodeList(node->doc, value);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002375 return(prop);
2376 }
2377 prop = prop->next;
2378 }
2379 prop = xmlNewProp(node, name, value);
2380 return(prop);
2381}
2382
Daniel Veillard97b58771998-10-20 06:14:16 +00002383/**
2384 * xmlNodeIsText:
2385 * @node: the node
2386 *
2387 * Is this node a Text node ?
Daniel Veillard1e346af1999-02-22 10:33:01 +00002388 * Returns 1 yes, 0 no
Daniel Veillard260a68f1998-08-13 03:39:55 +00002389 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002390int
2391xmlNodeIsText(xmlNodePtr node) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002392 if (node == NULL) return(0);
2393
Daniel Veillard0bef1311998-10-14 02:36:47 +00002394 if (node->type == XML_TEXT_NODE) return(1);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002395 return(0);
2396}
2397
Daniel Veillard97b58771998-10-20 06:14:16 +00002398/**
Daniel Veillard1e346af1999-02-22 10:33:01 +00002399 * xmlTextConcat:
Daniel Veillard97b58771998-10-20 06:14:16 +00002400 * @node: the node
2401 * @content: the content
2402 * @len: @content lenght
2403 *
2404 * Concat the given string at the end of the existing node content
Daniel Veillard260a68f1998-08-13 03:39:55 +00002405 */
Daniel Veillard97b58771998-10-20 06:14:16 +00002406
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002407void
2408xmlTextConcat(xmlNodePtr node, const CHAR *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002409 if (node == NULL) return;
2410
Daniel Veillard0bef1311998-10-14 02:36:47 +00002411 if (node->type != XML_TEXT_NODE) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002412 fprintf(stderr, "xmlTextConcat: node is not text\n");
2413 return;
2414 }
2415 node->content = xmlStrncat(node->content, content, len);
2416}
2417
2418/************************************************************************
2419 * *
2420 * Output : to a FILE or in memory *
2421 * *
2422 ************************************************************************/
2423
Daniel Veillard5099ae81999-04-21 20:12:07 +00002424#define BASE_BUFFER_SIZE 4000
2425
2426/**
2427 * xmlBufferCreate:
2428 *
2429 * routine to create an XML buffer.
2430 * returns the new structure.
2431 */
2432xmlBufferPtr
2433xmlBufferCreate(void) {
2434 xmlBufferPtr ret;
2435
Daniel Veillard6454aec1999-09-02 22:04:43 +00002436 ret = (xmlBufferPtr) xmlMalloc(sizeof(xmlBuffer));
Daniel Veillard5099ae81999-04-21 20:12:07 +00002437 if (ret == NULL) {
2438 fprintf(stderr, "xmlBufferCreate : out of memory!\n");
2439 return(NULL);
2440 }
2441 ret->use = 0;
2442 ret->size = BASE_BUFFER_SIZE;
Daniel Veillard6454aec1999-09-02 22:04:43 +00002443 ret->content = (CHAR *) xmlMalloc(ret->size * sizeof(CHAR));
Daniel Veillard5099ae81999-04-21 20:12:07 +00002444 if (ret->content == NULL) {
2445 fprintf(stderr, "xmlBufferCreate : out of memory!\n");
Daniel Veillard6454aec1999-09-02 22:04:43 +00002446 xmlFree(ret);
Daniel Veillard5099ae81999-04-21 20:12:07 +00002447 return(NULL);
2448 }
2449 ret->content[0] = 0;
2450 return(ret);
2451}
2452
2453/**
2454 * xmlBufferFree:
2455 * @buf: the buffer to free
2456 *
2457 * Frees an XML buffer.
2458 */
2459void
2460xmlBufferFree(xmlBufferPtr buf) {
2461 if (buf == NULL) {
2462 fprintf(stderr, "xmlBufferFree: buf == NULL\n");
2463 return;
2464 }
2465 if (buf->content == NULL) {
2466 fprintf(stderr, "xmlBufferFree: buf->content == NULL\n");
2467 } else {
2468 memset(buf->content, -1, BASE_BUFFER_SIZE);
Daniel Veillard6454aec1999-09-02 22:04:43 +00002469 xmlFree(buf->content);
Daniel Veillard5099ae81999-04-21 20:12:07 +00002470 }
2471 memset(buf, -1, sizeof(xmlBuffer));
Daniel Veillard6454aec1999-09-02 22:04:43 +00002472 xmlFree(buf);
Daniel Veillard5099ae81999-04-21 20:12:07 +00002473}
2474
2475/**
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002476 * xmlBufferEmpty:
2477 * @buf: the buffer
2478 *
2479 * empty a buffer.
2480 */
2481void
2482xmlBufferEmpty(xmlBufferPtr buf) {
2483 buf->use = 0;
2484 memset(buf->content, -1, buf->size);/* just for debug */
2485}
2486
2487/**
2488 * xmlBufferShrink:
2489 * @buf: the buffer to dump
2490 * @len: the number of CHAR to remove
2491 *
2492 * Remove the beginning of an XML buffer.
2493 *
2494 * Returns the number of CHAR removed, or -1 in case of failure.
2495 */
2496int
2497xmlBufferShrink(xmlBufferPtr buf, int len) {
2498 if (len == 0) return(0);
2499 if (len > buf->use) return(-1);
2500
2501 buf->use -= len;
2502 memmove(buf->content, &buf->content[len], buf->use * sizeof(CHAR));
2503
2504 buf->content[buf->use] = 0;
2505 return(len);
2506}
2507
2508/**
Daniel Veillard5099ae81999-04-21 20:12:07 +00002509 * xmlBufferDump:
2510 * @file: the file output
2511 * @buf: the buffer to dump
2512 *
2513 * Dumps an XML buffer to a FILE *.
2514 * Returns the number of CHAR written
2515 */
2516int
2517xmlBufferDump(FILE *file, xmlBufferPtr buf) {
2518 int ret;
2519
2520 if (buf == NULL) {
2521 fprintf(stderr, "xmlBufferDump: buf == NULL\n");
2522 return(0);
2523 }
2524 if (buf->content == NULL) {
2525 fprintf(stderr, "xmlBufferDump: buf->content == NULL\n");
2526 return(0);
2527 }
2528 if (file == NULL) file = stdout;
2529 ret = fwrite(buf->content, sizeof(CHAR), buf->use, file);
2530 return(ret);
2531}
2532
2533/**
2534 * xmlBufferAdd:
2535 * @buf: the buffer to dump
2536 * @str: the CHAR string
2537 * @len: the number of CHAR to add
2538 *
2539 * Add a string range to an XML buffer.
2540 */
2541void
2542xmlBufferAdd(xmlBufferPtr buf, const CHAR *str, int len) {
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002543 int l;
Daniel Veillard5099ae81999-04-21 20:12:07 +00002544
2545 if (str == NULL) {
2546 fprintf(stderr, "xmlBufferAdd: str == NULL\n");
2547 return;
2548 }
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002549 l = xmlStrlen(str);
2550 if (l < len) len = l;
2551 if (len <= 0) return;
Daniel Veillard5099ae81999-04-21 20:12:07 +00002552
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002553 if (buf->use + len + 10 >= buf->size) {
2554 CHAR *rebuf;
2555
2556 buf->size *= 2;
2557 if (buf->use + len + 10 > buf->size)
2558 buf->size = buf->use + len + 10;
Daniel Veillard6454aec1999-09-02 22:04:43 +00002559 rebuf = (CHAR *) xmlRealloc(buf->content, buf->size * sizeof(CHAR));
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002560 if (rebuf == NULL) {
2561 fprintf(stderr, "xmlBufferAdd : out of memory!\n");
2562 return;
Daniel Veillard5099ae81999-04-21 20:12:07 +00002563 }
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002564 buf->content = rebuf;
Daniel Veillard5099ae81999-04-21 20:12:07 +00002565 }
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002566 memmove(&buf->content[buf->use], str, len);
2567 buf->use += len;
2568 buf->content[buf->use] = 0;
Daniel Veillard5099ae81999-04-21 20:12:07 +00002569}
2570
2571/**
2572 * xmlBufferCat:
2573 * @buf: the buffer to dump
2574 * @str: the CHAR string
2575 *
2576 * Append a zero terminated string to an XML buffer.
2577 */
2578void
2579xmlBufferCat(xmlBufferPtr buf, const CHAR *str) {
2580 const CHAR *cur;
2581
2582 if (str == NULL) {
2583 fprintf(stderr, "xmlBufferAdd: str == NULL\n");
2584 return;
2585 }
2586 for (cur = str;*cur != 0;cur++) {
2587 if (buf->use + 10 >= buf->size) {
2588 CHAR *rebuf;
2589
2590 buf->size *= 2;
Daniel Veillard6454aec1999-09-02 22:04:43 +00002591 rebuf = (CHAR *) xmlRealloc(buf->content, buf->size * sizeof(CHAR));
Daniel Veillard5099ae81999-04-21 20:12:07 +00002592 if (rebuf == NULL) {
2593 fprintf(stderr, "xmlBufferAdd : out of memory!\n");
2594 return;
2595 }
2596 buf->content = rebuf;
2597 }
2598 buf->content[buf->use++] = *cur;
2599 }
2600}
2601
2602/**
2603 * xmlBufferCCat:
2604 * @buf: the buffer to dump
2605 * @str: the C char string
2606 *
2607 * Append a zero terminated C string to an XML buffer.
2608 */
2609void
2610xmlBufferCCat(xmlBufferPtr buf, const char *str) {
2611 const char *cur;
2612
2613 if (str == NULL) {
2614 fprintf(stderr, "xmlBufferAdd: str == NULL\n");
2615 return;
2616 }
2617 for (cur = str;*cur != 0;cur++) {
2618 if (buf->use + 10 >= buf->size) {
2619 CHAR *rebuf;
2620
2621 buf->size *= 2;
Daniel Veillard6454aec1999-09-02 22:04:43 +00002622 rebuf = (CHAR *) xmlRealloc(buf->content, buf->size * sizeof(CHAR));
Daniel Veillard5099ae81999-04-21 20:12:07 +00002623 if (rebuf == NULL) {
2624 fprintf(stderr, "xmlBufferAdd : out of memory!\n");
2625 return;
2626 }
2627 buf->content = rebuf;
2628 }
2629 buf->content[buf->use++] = *cur;
2630 }
2631}
Daniel Veillard260a68f1998-08-13 03:39:55 +00002632
Daniel Veillard97b58771998-10-20 06:14:16 +00002633/**
2634 * xmlBufferWriteCHAR:
Daniel Veillard5099ae81999-04-21 20:12:07 +00002635 * @buf: the XML buffer
Daniel Veillard97b58771998-10-20 06:14:16 +00002636 * @string: the string to add
2637 *
2638 * routine which manage and grows an output buffer. This one add
Daniel Veillard5099ae81999-04-21 20:12:07 +00002639 * CHARs at the end of the buffer.
Daniel Veillard97b58771998-10-20 06:14:16 +00002640 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002641void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002642xmlBufferWriteCHAR(xmlBufferPtr buf, const CHAR *string) {
2643 xmlBufferCat(buf, string);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002644}
2645
Daniel Veillard97b58771998-10-20 06:14:16 +00002646/**
2647 * xmlBufferWriteChar:
Daniel Veillard011b63c1999-06-02 17:44:04 +00002648 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00002649 * @string: the string to add
2650 *
2651 * routine which manage and grows an output buffer. This one add
2652 * C chars at the end of the array.
2653 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002654void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002655xmlBufferWriteChar(xmlBufferPtr buf, const char *string) {
2656 xmlBufferCCat(buf, string);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002657}
2658
Daniel Veillard5099ae81999-04-21 20:12:07 +00002659
Daniel Veillard97b58771998-10-20 06:14:16 +00002660/**
Daniel Veillard011b63c1999-06-02 17:44:04 +00002661 * xmlBufferWriteQuotedString:
2662 * @buf: the XML buffer output
2663 * @string: the string to add
2664 *
2665 * routine which manage and grows an output buffer. This one writes
2666 * a quoted or double quoted CHAR string, checking first if it holds
2667 * quote or double-quotes internally
2668 */
2669void
2670xmlBufferWriteQuotedString(xmlBufferPtr buf, const CHAR *string) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00002671 if (xmlStrchr(string, '"')) {
2672 if (xmlStrchr(string, '\'')) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00002673 fprintf(stderr,
2674 "xmlBufferWriteQuotedString: string contains quote and double-quotes !\n");
2675 }
2676 xmlBufferCCat(buf, "'");
2677 xmlBufferCat(buf, string);
2678 xmlBufferCCat(buf, "'");
2679 } else {
2680 xmlBufferCCat(buf, "\"");
2681 xmlBufferCat(buf, string);
2682 xmlBufferCCat(buf, "\"");
2683 }
2684}
2685
2686
2687/**
Daniel Veillard97b58771998-10-20 06:14:16 +00002688 * xmlGlobalNsDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00002689 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00002690 * @cur: a namespace
2691 *
2692 * Dump a global Namespace, this is the old version based on PIs.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002693 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002694static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002695xmlGlobalNsDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002696 if (cur == NULL) {
2697 fprintf(stderr, "xmlGlobalNsDump : Ns == NULL\n");
2698 return;
2699 }
2700 if (cur->type == XML_GLOBAL_NAMESPACE) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002701 xmlBufferWriteChar(buf, "<?namespace");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002702 if (cur->href != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00002703 xmlBufferWriteChar(buf, " href=");
2704 xmlBufferWriteQuotedString(buf, cur->href);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002705 }
2706 if (cur->prefix != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00002707 xmlBufferWriteChar(buf, " AS=");
2708 xmlBufferWriteQuotedString(buf, cur->prefix);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002709 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00002710 xmlBufferWriteChar(buf, "?>\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002711 }
2712}
2713
Daniel Veillard97b58771998-10-20 06:14:16 +00002714/**
2715 * xmlGlobalNsListDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00002716 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00002717 * @cur: the first namespace
2718 *
2719 * Dump a list of global Namespace, this is the old version based on PIs.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002720 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002721static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002722xmlGlobalNsListDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002723 while (cur != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002724 xmlGlobalNsDump(buf, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002725 cur = cur->next;
2726 }
2727}
2728
Daniel Veillard97b58771998-10-20 06:14:16 +00002729/**
2730 * xmlNsDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00002731 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00002732 * @cur: a namespace
2733 *
Daniel Veillard260a68f1998-08-13 03:39:55 +00002734 * Dump a local Namespace definition.
Daniel Veillard97b58771998-10-20 06:14:16 +00002735 * Should be called in the context of attributes dumps.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002736 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002737static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002738xmlNsDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002739 if (cur == NULL) {
2740 fprintf(stderr, "xmlNsDump : Ns == NULL\n");
2741 return;
2742 }
2743 if (cur->type == XML_LOCAL_NAMESPACE) {
2744 /* Within the context of an element attributes */
2745 if (cur->prefix != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002746 xmlBufferWriteChar(buf, " xmlns:");
2747 xmlBufferWriteCHAR(buf, cur->prefix);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002748 } else
Daniel Veillard5099ae81999-04-21 20:12:07 +00002749 xmlBufferWriteChar(buf, " xmlns");
Daniel Veillard011b63c1999-06-02 17:44:04 +00002750 xmlBufferWriteChar(buf, "=");
2751 xmlBufferWriteQuotedString(buf, cur->href);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002752 }
2753}
2754
Daniel Veillard97b58771998-10-20 06:14:16 +00002755/**
2756 * xmlNsListDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00002757 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00002758 * @cur: the first namespace
2759 *
2760 * Dump a list of local Namespace definitions.
2761 * Should be called in the context of attributes dumps.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002762 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002763static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002764xmlNsListDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002765 while (cur != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002766 xmlNsDump(buf, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002767 cur = cur->next;
2768 }
2769}
2770
Daniel Veillard97b58771998-10-20 06:14:16 +00002771/**
2772 * xmlDtdDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00002773 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00002774 * @doc: the document
2775 *
2776 * Dump the XML document DTD, if any.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002777 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002778static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002779xmlDtdDump(xmlBufferPtr buf, xmlDocPtr doc) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002780 xmlDtdPtr cur = doc->intSubset;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002781
2782 if (cur == NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002783 fprintf(stderr, "xmlDtdDump : no internal subset\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002784 return;
2785 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00002786 xmlBufferWriteChar(buf, "<!DOCTYPE ");
2787 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002788 if (cur->ExternalID != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00002789 xmlBufferWriteChar(buf, " PUBLIC ");
2790 xmlBufferWriteQuotedString(buf, cur->ExternalID);
2791 xmlBufferWriteChar(buf, " ");
2792 xmlBufferWriteQuotedString(buf, cur->SystemID);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002793 } else if (cur->SystemID != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00002794 xmlBufferWriteChar(buf, " SYSTEM ");
2795 xmlBufferWriteQuotedString(buf, cur->SystemID);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002796 }
Daniel Veillard1e346af1999-02-22 10:33:01 +00002797 if ((cur->entities == NULL) && (cur->elements == NULL) &&
2798 (cur->attributes == NULL) && (cur->notations == NULL)) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002799 xmlBufferWriteChar(buf, ">\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002800 return;
2801 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00002802 xmlBufferWriteChar(buf, " [\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002803 if (cur->entities != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00002804 xmlDumpEntitiesTable(buf, (xmlEntitiesTablePtr) cur->entities);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002805 if (cur->notations != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00002806 xmlDumpNotationTable(buf, (xmlNotationTablePtr) cur->notations);
Daniel Veillard3b9def11999-01-31 22:15:06 +00002807 if (cur->elements != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00002808 xmlDumpElementTable(buf, (xmlElementTablePtr) cur->elements);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002809 if (cur->attributes != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00002810 xmlDumpAttributeTable(buf, (xmlAttributeTablePtr) cur->attributes);
2811 xmlBufferWriteChar(buf, "]");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002812
Daniel Veillard5099ae81999-04-21 20:12:07 +00002813 xmlBufferWriteChar(buf, ">\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002814}
2815
Daniel Veillard97b58771998-10-20 06:14:16 +00002816/**
2817 * xmlAttrDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00002818 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00002819 * @doc: the document
2820 * @cur: the attribute pointer
2821 *
2822 * Dump an XML attribute
Daniel Veillard260a68f1998-08-13 03:39:55 +00002823 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002824static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002825xmlAttrDump(xmlBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur) {
Daniel Veillardccb09631998-10-27 06:21:04 +00002826 CHAR *value;
2827
Daniel Veillard260a68f1998-08-13 03:39:55 +00002828 if (cur == NULL) {
2829 fprintf(stderr, "xmlAttrDump : property == NULL\n");
2830 return;
2831 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00002832 xmlBufferWriteChar(buf, " ");
Daniel Veillardb96e6431999-08-29 21:02:19 +00002833 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
2834 xmlBufferWriteCHAR(buf, cur->ns->prefix);
2835 xmlBufferWriteChar(buf, ":");
2836 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00002837 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillardccb09631998-10-27 06:21:04 +00002838 value = xmlNodeListGetString(doc, cur->val, 0);
2839 if (value) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00002840 xmlBufferWriteChar(buf, "=");
2841 xmlBufferWriteQuotedString(buf, value);
Daniel Veillard6454aec1999-09-02 22:04:43 +00002842 xmlFree(value);
Daniel Veillard726c7e31999-02-08 15:13:10 +00002843 } else {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002844 xmlBufferWriteChar(buf, "=\"\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002845 }
2846}
2847
Daniel Veillard97b58771998-10-20 06:14:16 +00002848/**
2849 * xmlAttrListDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00002850 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00002851 * @doc: the document
2852 * @cur: the first attribute pointer
2853 *
2854 * Dump a list of XML attributes
Daniel Veillard260a68f1998-08-13 03:39:55 +00002855 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002856static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002857xmlAttrListDump(xmlBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002858 if (cur == NULL) {
2859 fprintf(stderr, "xmlAttrListDump : property == NULL\n");
2860 return;
2861 }
2862 while (cur != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002863 xmlAttrDump(buf, doc, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002864 cur = cur->next;
2865 }
2866}
2867
Daniel Veillard260a68f1998-08-13 03:39:55 +00002868
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002869static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002870xmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level);
Daniel Veillard97b58771998-10-20 06:14:16 +00002871/**
2872 * xmlNodeListDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00002873 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00002874 * @doc: the document
2875 * @cur: the first node
2876 * @level: the imbrication level for indenting
2877 *
2878 * Dump an XML node list, recursive behaviour,children are printed too.
2879 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002880static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002881xmlNodeListDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level) {
Daniel Veillardccb09631998-10-27 06:21:04 +00002882 int needIndent = 0, i;
2883
Daniel Veillard260a68f1998-08-13 03:39:55 +00002884 if (cur == NULL) {
2885 fprintf(stderr, "xmlNodeListDump : node == NULL\n");
2886 return;
2887 }
2888 while (cur != NULL) {
Daniel Veillardccb09631998-10-27 06:21:04 +00002889 if ((cur->type != XML_TEXT_NODE) &&
2890 (cur->type != XML_ENTITY_REF_NODE)) {
2891 if (!needIndent) {
2892 needIndent = 1;
Daniel Veillard5099ae81999-04-21 20:12:07 +00002893 xmlBufferWriteChar(buf, "\n");
Daniel Veillardccb09631998-10-27 06:21:04 +00002894 }
2895 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00002896 xmlNodeDump(buf, doc, cur, level);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002897 cur = cur->next;
2898 }
Daniel Veillardccb09631998-10-27 06:21:04 +00002899 if ((xmlIndentTreeOutput) && (needIndent))
2900 for (i = 1;i < level;i++)
Daniel Veillard5099ae81999-04-21 20:12:07 +00002901 xmlBufferWriteChar(buf, " ");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002902}
2903
Daniel Veillard97b58771998-10-20 06:14:16 +00002904/**
Daniel Veillardccb09631998-10-27 06:21:04 +00002905 * xmlNodeDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00002906 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00002907 * @doc: the document
2908 * @cur: the current node
2909 * @level: the imbrication level for indenting
2910 *
2911 * Dump an XML node, recursive behaviour,children are printed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002912 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002913static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002914xmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002915 int i;
2916
2917 if (cur == NULL) {
2918 fprintf(stderr, "xmlNodeDump : node == NULL\n");
2919 return;
2920 }
Daniel Veillard0bef1311998-10-14 02:36:47 +00002921 if (cur->type == XML_TEXT_NODE) {
Daniel Veillard14fff061999-06-22 21:49:07 +00002922 if (cur->content != NULL) {
2923 CHAR *buffer;
2924
2925 buffer = xmlEncodeEntitiesReentrant(doc, cur->content);
2926 if (buffer != NULL) {
2927 xmlBufferWriteCHAR(buf, buffer);
Daniel Veillard6454aec1999-09-02 22:04:43 +00002928 xmlFree(buffer);
Daniel Veillard14fff061999-06-22 21:49:07 +00002929 }
2930 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002931 return;
2932 }
Daniel Veillardb96e6431999-08-29 21:02:19 +00002933 if (cur->type == XML_PI_NODE) {
2934 if (cur->content != NULL) {
2935 xmlBufferWriteChar(buf, "<?");
2936 xmlBufferWriteCHAR(buf, cur->name);
2937 if (cur->content != NULL) {
2938 xmlBufferWriteChar(buf, " ");
2939 xmlBufferWriteCHAR(buf, cur->content);
2940 }
2941 xmlBufferWriteChar(buf, "?>\n");
2942 }
2943 return;
2944 }
Daniel Veillard0bef1311998-10-14 02:36:47 +00002945 if (cur->type == XML_COMMENT_NODE) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002946 if (cur->content != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002947 xmlBufferWriteChar(buf, "<!--");
2948 xmlBufferWriteCHAR(buf, cur->content);
Daniel Veillardb96e6431999-08-29 21:02:19 +00002949 xmlBufferWriteChar(buf, "-->\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002950 }
2951 return;
2952 }
Daniel Veillardccb09631998-10-27 06:21:04 +00002953 if (cur->type == XML_ENTITY_REF_NODE) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002954 xmlBufferWriteChar(buf, "&");
2955 xmlBufferWriteCHAR(buf, cur->name);
2956 xmlBufferWriteChar(buf, ";");
Daniel Veillardccb09631998-10-27 06:21:04 +00002957 return;
2958 }
Daniel Veillardb05deb71999-08-10 19:04:08 +00002959 if (cur->type == XML_CDATA_SECTION_NODE) {
2960 xmlBufferWriteChar(buf, "<![CDATA[");
2961 if (cur->content != NULL)
2962 xmlBufferWriteCHAR(buf, cur->content);
2963 xmlBufferWriteChar(buf, "]]>");
2964 return;
2965 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002966 if (xmlIndentTreeOutput)
2967 for (i = 0;i < level;i++)
Daniel Veillard5099ae81999-04-21 20:12:07 +00002968 xmlBufferWriteChar(buf, " ");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002969
Daniel Veillard5099ae81999-04-21 20:12:07 +00002970 xmlBufferWriteChar(buf, "<");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002971 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002972 xmlBufferWriteCHAR(buf, cur->ns->prefix);
2973 xmlBufferWriteChar(buf, ":");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002974 }
2975
Daniel Veillard5099ae81999-04-21 20:12:07 +00002976 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002977 if (cur->nsDef)
Daniel Veillard5099ae81999-04-21 20:12:07 +00002978 xmlNsListDump(buf, cur->nsDef);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002979 if (cur->properties != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00002980 xmlAttrListDump(buf, doc, cur->properties);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002981
2982 if ((cur->content == NULL) && (cur->childs == NULL)) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002983 xmlBufferWriteChar(buf, "/>\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002984 return;
2985 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00002986 xmlBufferWriteChar(buf, ">");
Daniel Veillard14fff061999-06-22 21:49:07 +00002987 if (cur->content != NULL) {
2988 CHAR *buffer;
2989
2990 buffer = xmlEncodeEntitiesReentrant(doc, cur->content);
2991 if (buffer != NULL) {
2992 xmlBufferWriteCHAR(buf, buffer);
Daniel Veillard6454aec1999-09-02 22:04:43 +00002993 xmlFree(buffer);
Daniel Veillard14fff061999-06-22 21:49:07 +00002994 }
2995 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002996 if (cur->childs != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002997 xmlNodeListDump(buf, doc, cur->childs, level + 1);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002998 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00002999 xmlBufferWriteChar(buf, "</");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003000 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003001 xmlBufferWriteCHAR(buf, cur->ns->prefix);
3002 xmlBufferWriteChar(buf, ":");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003003 }
3004
Daniel Veillard5099ae81999-04-21 20:12:07 +00003005 xmlBufferWriteCHAR(buf, cur->name);
3006 xmlBufferWriteChar(buf, ">\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003007}
3008
Daniel Veillard97b58771998-10-20 06:14:16 +00003009/**
3010 * xmlDocContentDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003011 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003012 * @cur: the document
3013 *
3014 * Dump an XML document.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003015 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003016static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00003017xmlDocContentDump(xmlBufferPtr buf, xmlDocPtr cur) {
Daniel Veillardbe70ff71999-07-05 16:50:46 +00003018 xmlBufferWriteChar(buf, "<?xml version=");
3019 if (cur->version != NULL)
3020 xmlBufferWriteQuotedString(buf, cur->version);
3021 else
3022 xmlBufferWriteChar(buf, "\"1.0\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003023 if (cur->encoding != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00003024 xmlBufferWriteChar(buf, " encoding=");
3025 xmlBufferWriteQuotedString(buf, cur->encoding);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003026 }
3027 switch (cur->standalone) {
3028 case 0:
Daniel Veillard5099ae81999-04-21 20:12:07 +00003029 xmlBufferWriteChar(buf, " standalone=\"no\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003030 break;
3031 case 1:
Daniel Veillard5099ae81999-04-21 20:12:07 +00003032 xmlBufferWriteChar(buf, " standalone=\"yes\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003033 break;
3034 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003035 xmlBufferWriteChar(buf, "?>\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003036 if (cur->intSubset != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00003037 xmlDtdDump(buf, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003038 if (cur->root != NULL) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00003039 xmlNodePtr child = cur->root;
3040
Daniel Veillard260a68f1998-08-13 03:39:55 +00003041 /* global namespace definitions, the old way */
3042 if (oldXMLWDcompatibility)
Daniel Veillard5099ae81999-04-21 20:12:07 +00003043 xmlGlobalNsListDump(buf, cur->oldNs);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003044 else
3045 xmlUpgradeOldNs(cur);
Daniel Veillardb96e6431999-08-29 21:02:19 +00003046
3047 while (child != NULL) {
3048 xmlNodeDump(buf, cur, child, 0);
3049 child = child->next;
3050 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003051 }
3052}
3053
Daniel Veillard97b58771998-10-20 06:14:16 +00003054/**
3055 * xmlDocDumpMemory:
3056 * @cur: the document
3057 * @mem: OUT: the memory pointer
3058 * @size: OUT: the memory lenght
3059 *
3060 * Dump an XML document in memory and return the CHAR * and it's size.
3061 * It's up to the caller to free the memory.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003062 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003063void
3064xmlDocDumpMemory(xmlDocPtr cur, CHAR**mem, int *size) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003065 xmlBufferPtr buf;
3066
Daniel Veillard260a68f1998-08-13 03:39:55 +00003067 if (cur == NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003068#ifdef DEBUG_TREE
3069 fprintf(stderr, "xmlDocDumpMemory : document == NULL\n");
3070#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00003071 *mem = NULL;
3072 *size = 0;
3073 return;
3074 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003075 buf = xmlBufferCreate();
3076 if (buf == NULL) {
3077 *mem = NULL;
3078 *size = 0;
3079 return;
3080 }
3081 xmlDocContentDump(buf, cur);
Daniel Veillardb05deb71999-08-10 19:04:08 +00003082 *mem = xmlStrndup(buf->content, buf->use);
Daniel Veillard5099ae81999-04-21 20:12:07 +00003083 *size = buf->use;
Daniel Veillardb05deb71999-08-10 19:04:08 +00003084 xmlBufferFree(buf);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003085}
3086
Daniel Veillard97b58771998-10-20 06:14:16 +00003087/**
3088 * xmlGetDocCompressMode:
3089 * @doc: the document
3090 *
3091 * get the compression ratio for a document, ZLIB based
Daniel Veillard1e346af1999-02-22 10:33:01 +00003092 * Returns 0 (uncompressed) to 9 (max compression)
Daniel Veillard151b1b01998-09-23 00:49:46 +00003093 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003094int
3095 xmlGetDocCompressMode (xmlDocPtr doc) {
Daniel Veillard15a8df41998-09-24 19:15:06 +00003096 if (doc == NULL) return(-1);
3097 return(doc->compression);
3098}
3099
Daniel Veillard97b58771998-10-20 06:14:16 +00003100/**
3101 * xmlSetDocCompressMode:
3102 * @doc: the document
3103 * @mode: the compression ratio
3104 *
3105 * set the compression ratio for a document, ZLIB based
3106 * Correct values: 0 (uncompressed) to 9 (max compression)
3107 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003108void
3109xmlSetDocCompressMode (xmlDocPtr doc, int mode) {
Daniel Veillard15a8df41998-09-24 19:15:06 +00003110 if (doc == NULL) return;
3111 if (mode < 0) doc->compression = 0;
3112 else if (mode > 9) doc->compression = 9;
3113 else doc->compression = mode;
3114}
3115
Daniel Veillard97b58771998-10-20 06:14:16 +00003116/**
3117 * xmlGetCompressMode:
3118 *
3119 * get the default compression mode used, ZLIB based.
Daniel Veillard1e346af1999-02-22 10:33:01 +00003120 * Returns 0 (uncompressed) to 9 (max compression)
Daniel Veillard15a8df41998-09-24 19:15:06 +00003121 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003122int
3123 xmlGetCompressMode(void) {
Daniel Veillard151b1b01998-09-23 00:49:46 +00003124 return(xmlCompressMode);
3125}
Daniel Veillard97b58771998-10-20 06:14:16 +00003126
3127/**
3128 * xmlSetCompressMode:
3129 * @mode: the compression ratio
3130 *
3131 * set the default compression mode used, ZLIB based
3132 * Correct values: 0 (uncompressed) to 9 (max compression)
3133 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003134void
3135xmlSetCompressMode(int mode) {
Daniel Veillard151b1b01998-09-23 00:49:46 +00003136 if (mode < 0) xmlCompressMode = 0;
Daniel Veillard15a8df41998-09-24 19:15:06 +00003137 else if (mode > 9) xmlCompressMode = 9;
Daniel Veillard151b1b01998-09-23 00:49:46 +00003138 else xmlCompressMode = mode;
3139}
3140
Daniel Veillard97b58771998-10-20 06:14:16 +00003141/**
3142 * xmlDocDump:
3143 * @f: the FILE*
3144 * @cur: the document
3145 *
3146 * Dump an XML document to an open FILE.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003147 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003148void
3149xmlDocDump(FILE *f, xmlDocPtr cur) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003150 xmlBufferPtr buf;
3151
Daniel Veillard260a68f1998-08-13 03:39:55 +00003152 if (cur == NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003153#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00003154 fprintf(stderr, "xmlDocDump : document == NULL\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003155#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00003156 return;
3157 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003158 buf = xmlBufferCreate();
3159 if (buf == NULL) return;
3160 xmlDocContentDump(buf, cur);
3161 xmlBufferDump(f, buf);
3162 xmlBufferFree(buf);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003163}
3164
Daniel Veillard97b58771998-10-20 06:14:16 +00003165/**
3166 * xmlSaveFile:
3167 * @filename: the filename
3168 * @cur: the document
3169 *
3170 * Dump an XML document to a file. Will use compression if
3171 * compiled in and enabled.
3172 * returns: the number of file written or -1 in case of failure.
Daniel Veillard151b1b01998-09-23 00:49:46 +00003173 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003174int
3175xmlSaveFile(const char *filename, xmlDocPtr cur) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003176 xmlBufferPtr buf;
Daniel Veillard151b1b01998-09-23 00:49:46 +00003177#ifdef HAVE_ZLIB_H
3178 gzFile zoutput = NULL;
3179 char mode[15];
3180#endif
Daniel Veillardccb09631998-10-27 06:21:04 +00003181 FILE *output = NULL;
Daniel Veillard151b1b01998-09-23 00:49:46 +00003182 int ret;
3183
Daniel Veillard5099ae81999-04-21 20:12:07 +00003184 /*
3185 * save the content to a temp buffer.
3186 */
3187 buf = xmlBufferCreate();
3188 if (buf == NULL) return(0);
3189 xmlDocContentDump(buf, cur);
3190
Daniel Veillard151b1b01998-09-23 00:49:46 +00003191#ifdef HAVE_ZLIB_H
Daniel Veillarddc3dd9d1998-09-24 19:25:54 +00003192 if ((cur->compression > 0) && (cur->compression <= 9)) {
3193 sprintf(mode, "w%d", cur->compression);
Daniel Veillard151b1b01998-09-23 00:49:46 +00003194 zoutput = gzopen(filename, mode);
3195 }
3196 if (zoutput == NULL) {
3197#endif
3198 output = fopen(filename, "w");
3199 if (output == NULL) return(-1);
3200#ifdef HAVE_ZLIB_H
3201 }
Daniel Veillard151b1b01998-09-23 00:49:46 +00003202
Daniel Veillard151b1b01998-09-23 00:49:46 +00003203 if (zoutput != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003204 ret = gzwrite(zoutput, buf->content, sizeof(CHAR) * buf->use);
Daniel Veillard151b1b01998-09-23 00:49:46 +00003205 gzclose(zoutput);
Daniel Veillard5099ae81999-04-21 20:12:07 +00003206 } else {
3207#endif
3208 ret = xmlBufferDump(output, buf);
3209 fclose(output);
3210#ifdef HAVE_ZLIB_H
Daniel Veillard151b1b01998-09-23 00:49:46 +00003211 }
3212#endif
Manish Vachharajani5e60f5a1999-05-29 03:04:30 +00003213 xmlBufferFree(buf);
Daniel Veillard151b1b01998-09-23 00:49:46 +00003214 return(ret * sizeof(CHAR));
3215}
3216