blob: 9e622ffe5c2de063d558cbd6e2a5336133c8840c [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 Veillard27d88741999-05-29 11:51:49 +0000398#ifndef XML_WITHOUT_CORBA
Daniel Veillard27fb0751998-10-17 06:47:46 +0000399 cur->_private = NULL;
400 cur->vepv = NULL;
401#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000402 return(cur);
403}
404
Daniel Veillard97b58771998-10-20 06:14:16 +0000405/**
406 * xmlFreeDoc:
407 * @cur: pointer to the document
408 * @:
409 *
410 * Free up all the structures used by a document, tree included.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000411 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000412void
413xmlFreeDoc(xmlDocPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000414 if (cur == NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000415#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +0000416 fprintf(stderr, "xmlFreeDoc : document == NULL\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000417#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000418 return;
419 }
Daniel Veillard6454aec1999-09-02 22:04:43 +0000420 if (cur->version != NULL) xmlFree((char *) cur->version);
421 if (cur->name != NULL) xmlFree((char *) cur->name);
422 if (cur->encoding != NULL) xmlFree((char *) cur->encoding);
423 if (cur->root != NULL) xmlFreeNodeList(cur->root);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000424 if (cur->intSubset != NULL) xmlFreeDtd(cur->intSubset);
425 if (cur->extSubset != NULL) xmlFreeDtd(cur->extSubset);
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000426 if (cur->oldNs != NULL) xmlFreeNsList(cur->oldNs);
Daniel Veillardb96e6431999-08-29 21:02:19 +0000427 if (cur->ids != NULL) xmlFreeIDTable((xmlIDTablePtr) cur->ids);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000428 memset(cur, -1, sizeof(xmlDoc));
Daniel Veillard6454aec1999-09-02 22:04:43 +0000429 xmlFree(cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000430}
431
Daniel Veillard97b58771998-10-20 06:14:16 +0000432/**
Daniel Veillard16253641998-10-28 22:58:05 +0000433 * xmlStringLenGetNodeList:
434 * @doc: the document
435 * @value: the value of the text
Daniel Veillard1e346af1999-02-22 10:33:01 +0000436 * @len: the length of the string value
Daniel Veillard16253641998-10-28 22:58:05 +0000437 *
438 * Parse the value string and build the node list associated. Should
439 * produce a flat tree with only TEXTs and ENTITY_REFs.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000440 * Returns a pointer to the first child
Daniel Veillard16253641998-10-28 22:58:05 +0000441 */
442xmlNodePtr
443xmlStringLenGetNodeList(xmlDocPtr doc, const CHAR *value, int len) {
444 xmlNodePtr ret = NULL, last = NULL;
445 xmlNodePtr node;
446 CHAR *val;
447 const CHAR *cur = value;
448 const CHAR *q;
Daniel Veillard25940b71998-10-29 05:51:30 +0000449 xmlEntityPtr ent;
Daniel Veillard16253641998-10-28 22:58:05 +0000450
451 if (value == NULL) return(NULL);
452
453 q = cur;
454 while ((*cur != 0) && (cur - value < len)) {
455 if (*cur == '&') {
Daniel Veillard25940b71998-10-29 05:51:30 +0000456 /*
457 * Save the current text.
458 */
Daniel Veillard16253641998-10-28 22:58:05 +0000459 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000460 if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
461 xmlNodeAddContentLen(last, q, cur - q);
462 } else {
463 node = xmlNewDocTextLen(doc, q, cur - q);
464 if (node == NULL) return(ret);
465 if (last == NULL)
466 last = ret = node;
467 else {
468 last->next = node;
469 node->prev = last;
470 last = node;
471 }
Daniel Veillard16253641998-10-28 22:58:05 +0000472 }
473 }
Daniel Veillard25940b71998-10-29 05:51:30 +0000474 /*
475 * Read the entity string
476 */
Daniel Veillard16253641998-10-28 22:58:05 +0000477 cur++;
478 q = cur;
479 while ((*cur != 0) && (cur - value < len) && (*cur != ';')) cur++;
480 if ((*cur == 0) || (cur - value >= len)) {
481 fprintf(stderr,
Daniel Veillard011b63c1999-06-02 17:44:04 +0000482 "xmlStringLenGetNodeList: unterminated entity %30s\n", q);
Daniel Veillard16253641998-10-28 22:58:05 +0000483 return(ret);
484 }
485 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000486 /*
487 * Predefined entities don't generate nodes
488 */
Daniel Veillard16253641998-10-28 22:58:05 +0000489 val = xmlStrndup(q, cur - q);
Daniel Veillard25940b71998-10-29 05:51:30 +0000490 ent = xmlGetDocEntity(doc, val);
491 if ((ent != NULL) &&
492 (ent->type == XML_INTERNAL_PREDEFINED_ENTITY)) {
493 if (last == NULL) {
494 node = xmlNewDocText(doc, ent->content);
495 last = ret = node;
496 } else
497 xmlNodeAddContent(last, ent->content);
498
499 } else {
500 /*
501 * Create a new REFERENCE_REF node
502 */
503 node = xmlNewReference(doc, val);
Daniel Veillard242590e1998-11-13 18:04:35 +0000504 if (node == NULL) {
Daniel Veillard6454aec1999-09-02 22:04:43 +0000505 if (val != NULL) xmlFree(val);
Daniel Veillard242590e1998-11-13 18:04:35 +0000506 return(ret);
507 }
Daniel Veillard25940b71998-10-29 05:51:30 +0000508 if (last == NULL)
509 last = ret = node;
510 else {
511 last->next = node;
512 node->prev = last;
513 last = node;
514 }
Daniel Veillard16253641998-10-28 22:58:05 +0000515 }
Daniel Veillard6454aec1999-09-02 22:04:43 +0000516 xmlFree(val);
Daniel Veillard16253641998-10-28 22:58:05 +0000517 }
518 cur++;
519 q = cur;
520 } else
521 cur++;
522 }
523 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000524 /*
525 * Handle the last piece of text.
526 */
527 if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
528 xmlNodeAddContentLen(last, q, cur - q);
529 } else {
530 node = xmlNewDocTextLen(doc, q, cur - q);
531 if (node == NULL) return(ret);
532 if (last == NULL)
533 last = ret = node;
534 else {
535 last->next = node;
536 node->prev = last;
537 last = node;
538 }
Daniel Veillard16253641998-10-28 22:58:05 +0000539 }
540 }
541 return(ret);
542}
543
544/**
Daniel Veillardccb09631998-10-27 06:21:04 +0000545 * xmlStringGetNodeList:
546 * @doc: the document
547 * @value: the value of the attribute
548 *
549 * Parse the value string and build the node list associated. Should
550 * produce a flat tree with only TEXTs and ENTITY_REFs.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000551 * Returns a pointer to the first child
Daniel Veillardccb09631998-10-27 06:21:04 +0000552 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000553xmlNodePtr
554xmlStringGetNodeList(xmlDocPtr doc, const CHAR *value) {
Daniel Veillardccb09631998-10-27 06:21:04 +0000555 xmlNodePtr ret = NULL, last = NULL;
556 xmlNodePtr node;
557 CHAR *val;
558 const CHAR *cur = value;
559 const CHAR *q;
Daniel Veillard25940b71998-10-29 05:51:30 +0000560 xmlEntityPtr ent;
Daniel Veillardccb09631998-10-27 06:21:04 +0000561
562 if (value == NULL) return(NULL);
563
564 q = cur;
565 while (*cur != 0) {
566 if (*cur == '&') {
Daniel Veillard25940b71998-10-29 05:51:30 +0000567 /*
568 * Save the current text.
569 */
Daniel Veillardccb09631998-10-27 06:21:04 +0000570 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000571 if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
572 xmlNodeAddContentLen(last, q, cur - q);
573 } else {
574 node = xmlNewDocTextLen(doc, q, cur - q);
575 if (node == NULL) return(ret);
576 if (last == NULL)
577 last = ret = node;
578 else {
579 last->next = node;
580 node->prev = last;
581 last = node;
582 }
Daniel Veillardccb09631998-10-27 06:21:04 +0000583 }
584 }
Daniel Veillard25940b71998-10-29 05:51:30 +0000585 /*
586 * Read the entity string
587 */
Daniel Veillardccb09631998-10-27 06:21:04 +0000588 cur++;
589 q = cur;
590 while ((*cur != 0) && (*cur != ';')) cur++;
591 if (*cur == 0) {
592 fprintf(stderr,
593 "xmlStringGetNodeList: unterminated entity %30s\n", q);
594 return(ret);
595 }
596 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000597 /*
598 * Predefined entities don't generate nodes
599 */
Daniel Veillardccb09631998-10-27 06:21:04 +0000600 val = xmlStrndup(q, cur - q);
Daniel Veillard25940b71998-10-29 05:51:30 +0000601 ent = xmlGetDocEntity(doc, val);
602 if ((ent != NULL) &&
603 (ent->type == XML_INTERNAL_PREDEFINED_ENTITY)) {
604 if (last == NULL) {
605 node = xmlNewDocText(doc, ent->content);
606 last = ret = node;
607 } else
608 xmlNodeAddContent(last, ent->content);
609
610 } else {
611 /*
612 * Create a new REFERENCE_REF node
613 */
Daniel Veillard25940b71998-10-29 05:51:30 +0000614 node = xmlNewReference(doc, val);
Daniel Veillard242590e1998-11-13 18:04:35 +0000615 if (node == NULL) {
Daniel Veillard6454aec1999-09-02 22:04:43 +0000616 if (val != NULL) xmlFree(val);
Daniel Veillard242590e1998-11-13 18:04:35 +0000617 return(ret);
618 }
Daniel Veillard25940b71998-10-29 05:51:30 +0000619 if (last == NULL)
620 last = ret = node;
621 else {
622 last->next = node;
623 node->prev = last;
624 last = node;
625 }
Daniel Veillardccb09631998-10-27 06:21:04 +0000626 }
Daniel Veillard6454aec1999-09-02 22:04:43 +0000627 xmlFree(val);
Daniel Veillardccb09631998-10-27 06:21:04 +0000628 }
629 cur++;
630 q = cur;
631 } else
632 cur++;
633 }
634 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000635 /*
636 * Handle the last piece of text.
637 */
638 if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
639 xmlNodeAddContentLen(last, q, cur - q);
640 } else {
641 node = xmlNewDocTextLen(doc, q, cur - q);
642 if (node == NULL) return(ret);
643 if (last == NULL)
644 last = ret = node;
645 else {
646 last->next = node;
647 node->prev = last;
648 last = node;
649 }
Daniel Veillardccb09631998-10-27 06:21:04 +0000650 }
651 }
652 return(ret);
653}
654
655/**
656 * xmlNodeListGetString:
657 * @doc: the document
658 * @list: a Node list
659 * @inLine: should we replace entity contents or show their external form
660 *
661 * Returns the string equivalent to the text contained in the Node list
662 * made of TEXTs and ENTITY_REFs
Daniel Veillard1e346af1999-02-22 10:33:01 +0000663 * Returns a pointer to the string copy, the calller must free it.
Daniel Veillardccb09631998-10-27 06:21:04 +0000664 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000665CHAR *
666xmlNodeListGetString(xmlDocPtr doc, xmlNodePtr list, int inLine) {
Daniel Veillardccb09631998-10-27 06:21:04 +0000667 xmlNodePtr node = list;
668 CHAR *ret = NULL;
669 xmlEntityPtr ent;
670
671 if (list == NULL) return(NULL);
672
673 while (node != NULL) {
674 if (node->type == XML_TEXT_NODE) {
675 if (inLine)
676 ret = xmlStrcat(ret, node->content);
Daniel Veillard14fff061999-06-22 21:49:07 +0000677 else {
678 CHAR *buffer;
679
680 buffer = xmlEncodeEntitiesReentrant(doc, node->content);
681 if (buffer != NULL) {
682 ret = xmlStrcat(ret, buffer);
Daniel Veillard6454aec1999-09-02 22:04:43 +0000683 xmlFree(buffer);
Daniel Veillard14fff061999-06-22 21:49:07 +0000684 }
685 }
Daniel Veillardccb09631998-10-27 06:21:04 +0000686 } else if (node->type == XML_ENTITY_REF_NODE) {
687 if (inLine) {
688 ent = xmlGetDocEntity(doc, node->name);
689 if (ent != NULL)
690 ret = xmlStrcat(ret, ent->content);
691 else
692 ret = xmlStrcat(ret, node->content);
693 } else {
694 CHAR buf[2];
695 buf[0] = '&'; buf[1] = 0;
696 ret = xmlStrncat(ret, buf, 1);
697 ret = xmlStrcat(ret, node->name);
698 buf[0] = ';'; buf[1] = 0;
699 ret = xmlStrncat(ret, buf, 1);
700 }
701 }
702#if 0
703 else {
704 fprintf(stderr, "xmlGetNodeListString : invalide node type %d\n",
705 node->type);
706 }
707#endif
708 node = node->next;
709 }
710 return(ret);
711}
712
713/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000714 * xmlNewProp:
715 * @node: the holding node
716 * @name: the name of the attribute
717 * @value: the value of the attribute
718 *
719 * Create a new property carried by a node.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000720 * Returns a pointer to the attribute
Daniel Veillard260a68f1998-08-13 03:39:55 +0000721 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000722xmlAttrPtr
723xmlNewProp(xmlNodePtr node, const CHAR *name, const CHAR *value) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000724 xmlAttrPtr cur;
725
726 if (name == NULL) {
727 fprintf(stderr, "xmlNewProp : name == NULL\n");
728 return(NULL);
729 }
730
731 /*
732 * Allocate a new property and fill the fields.
733 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000734 cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000735 if (cur == NULL) {
736 fprintf(stderr, "xmlNewProp : malloc failed\n");
737 return(NULL);
738 }
739
Daniel Veillard33942841998-10-18 19:12:41 +0000740 cur->type = XML_ATTRIBUTE_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000741 cur->node = node;
Daniel Veillardb96e6431999-08-29 21:02:19 +0000742 cur->ns = NULL;
743 cur->name = xmlStrdup(name);
744 if (value != NULL)
745 cur->val = xmlStringGetNodeList(node->doc, value);
746 else
747 cur->val = NULL;
748#ifndef XML_WITHOUT_CORBA
749 cur->_private = NULL;
750 cur->vepv = NULL;
751#endif
752
753 /*
754 * Add it at the end to preserve parsing order ...
755 */
756 cur->next = NULL;
757 if (node != NULL) {
758 if (node->properties == NULL) {
759 node->properties = cur;
760 } else {
761 xmlAttrPtr prev = node->properties;
762
763 while (prev->next != NULL) prev = prev->next;
764 prev->next = cur;
765 }
766 }
767 return(cur);
768}
769
770/**
771 * xmlNewNsProp:
772 * @node: the holding node
773 * @ns: the namespace
774 * @name: the name of the attribute
775 * @value: the value of the attribute
776 *
777 * Create a new property tagged with a namespace and carried by a node.
778 * Returns a pointer to the attribute
779 */
780xmlAttrPtr
781xmlNewNsProp(xmlNodePtr node, xmlNsPtr ns, const CHAR *name,
782 const CHAR *value) {
783 xmlAttrPtr cur;
784
785 if (name == NULL) {
786 fprintf(stderr, "xmlNewProp : name == NULL\n");
787 return(NULL);
788 }
789
790 /*
791 * Allocate a new property and fill the fields.
792 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000793 cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr));
Daniel Veillardb96e6431999-08-29 21:02:19 +0000794 if (cur == NULL) {
795 fprintf(stderr, "xmlNewProp : malloc failed\n");
796 return(NULL);
797 }
798
799 cur->type = XML_ATTRIBUTE_NODE;
800 cur->node = node;
801 cur->ns = ns;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000802 cur->name = xmlStrdup(name);
803 if (value != NULL)
Daniel Veillardccb09631998-10-27 06:21:04 +0000804 cur->val = xmlStringGetNodeList(node->doc, value);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000805 else
Daniel Veillardccb09631998-10-27 06:21:04 +0000806 cur->val = NULL;
Daniel Veillard27d88741999-05-29 11:51:49 +0000807#ifndef XML_WITHOUT_CORBA
Daniel Veillard27fb0751998-10-17 06:47:46 +0000808 cur->_private = NULL;
809 cur->vepv = NULL;
810#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000811
812 /*
813 * Add it at the end to preserve parsing order ...
814 */
815 cur->next = NULL;
816 if (node != NULL) {
817 if (node->properties == NULL) {
818 node->properties = cur;
819 } else {
820 xmlAttrPtr prev = node->properties;
821
822 while (prev->next != NULL) prev = prev->next;
823 prev->next = cur;
824 }
825 }
826 return(cur);
827}
828
Daniel Veillard97b58771998-10-20 06:14:16 +0000829/**
Daniel Veillardccb09631998-10-27 06:21:04 +0000830 * xmlNewDocProp:
831 * @doc: the document
832 * @name: the name of the attribute
833 * @value: the value of the attribute
834 *
835 * Create a new property carried by a document.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000836 * Returns a pointer to the attribute
Daniel Veillardccb09631998-10-27 06:21:04 +0000837 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000838xmlAttrPtr
839xmlNewDocProp(xmlDocPtr doc, const CHAR *name, const CHAR *value) {
Daniel Veillardccb09631998-10-27 06:21:04 +0000840 xmlAttrPtr cur;
841
842 if (name == NULL) {
843 fprintf(stderr, "xmlNewProp : name == NULL\n");
844 return(NULL);
845 }
846
847 /*
848 * Allocate a new property and fill the fields.
849 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000850 cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr));
Daniel Veillardccb09631998-10-27 06:21:04 +0000851 if (cur == NULL) {
852 fprintf(stderr, "xmlNewProp : malloc failed\n");
853 return(NULL);
854 }
855
856 cur->type = XML_ATTRIBUTE_NODE;
857 cur->node = NULL;
858 cur->name = xmlStrdup(name);
859 if (value != NULL)
860 cur->val = xmlStringGetNodeList(doc, value);
861 else
862 cur->val = NULL;
Daniel Veillard27d88741999-05-29 11:51:49 +0000863#ifndef XML_WITHOUT_CORBA
Daniel Veillardccb09631998-10-27 06:21:04 +0000864 cur->_private = NULL;
865 cur->vepv = NULL;
866#endif
867
868 cur->next = NULL;
869 return(cur);
870}
871
872/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000873 * xmlFreePropList:
874 * @cur: the first property in the list
875 *
876 * Free a property and all its siblings, all the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000877 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000878void
879xmlFreePropList(xmlAttrPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000880 xmlAttrPtr next;
881 if (cur == NULL) {
882 fprintf(stderr, "xmlFreePropList : property == NULL\n");
883 return;
884 }
885 while (cur != NULL) {
886 next = cur->next;
887 xmlFreeProp(cur);
888 cur = next;
889 }
890}
891
Daniel Veillard97b58771998-10-20 06:14:16 +0000892/**
893 * xmlFreeProp:
894 * @cur: the first property in the list
895 *
896 * Free one property, all the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000897 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000898void
899xmlFreeProp(xmlAttrPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000900 if (cur == NULL) {
901 fprintf(stderr, "xmlFreeProp : property == NULL\n");
902 return;
903 }
Daniel Veillard6454aec1999-09-02 22:04:43 +0000904 if (cur->name != NULL) xmlFree((char *) cur->name);
Daniel Veillardccb09631998-10-27 06:21:04 +0000905 if (cur->val != NULL) xmlFreeNodeList(cur->val);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000906 memset(cur, -1, sizeof(xmlAttr));
Daniel Veillard6454aec1999-09-02 22:04:43 +0000907 xmlFree(cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000908}
909
Daniel Veillard97b58771998-10-20 06:14:16 +0000910/**
Daniel Veillardb96e6431999-08-29 21:02:19 +0000911 * xmlNewPI:
912 * @name: the processing instruction name
913 * @content: the PI content
914 *
915 * Creation of a processing instruction element.
916 * Returns a pointer to the new node object.
917 */
918xmlNodePtr
919xmlNewPI(const CHAR *name, const CHAR *content) {
920 xmlNodePtr cur;
921
922 if (name == NULL) {
923 fprintf(stderr, "xmlNewPI : name == NULL\n");
924 return(NULL);
925 }
926
927 /*
928 * Allocate a new node and fill the fields.
929 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000930 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillardb96e6431999-08-29 21:02:19 +0000931 if (cur == NULL) {
932 fprintf(stderr, "xmlNewPI : malloc failed\n");
933 return(NULL);
934 }
935
936 cur->type = XML_PI_NODE;
937 cur->doc = NULL;
938 cur->parent = NULL;
939 cur->next = NULL;
940 cur->prev = NULL;
941 cur->childs = NULL;
942 cur->last = NULL;
943 cur->properties = NULL;
944 cur->name = xmlStrdup(name);
945 cur->ns = NULL;
946 cur->nsDef = NULL;
947 if (content != NULL)
948 cur->content = xmlStrdup(content);
949 else
950 cur->content = NULL;
951#ifndef XML_WITHOUT_CORBA
952 cur->_private = NULL;
953 cur->vepv = NULL;
954#endif
955 return(cur);
956}
957
958/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000959 * xmlNewNode:
960 * @ns: namespace if any
961 * @name: the node name
Daniel Veillard97b58771998-10-20 06:14:16 +0000962 *
963 * Creation of a new node element. @ns and @content are optionnal (NULL).
Daniel Veillardccb09631998-10-27 06:21:04 +0000964 * If content is non NULL, a child list containing the TEXTs and
965 * ENTITY_REFs node will be created.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000966 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000967 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000968xmlNodePtr
969xmlNewNode(xmlNsPtr ns, const CHAR *name) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000970 xmlNodePtr cur;
971
972 if (name == NULL) {
973 fprintf(stderr, "xmlNewNode : name == NULL\n");
974 return(NULL);
975 }
976
977 /*
978 * Allocate a new node and fill the fields.
979 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000980 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000981 if (cur == NULL) {
982 fprintf(stderr, "xmlNewNode : malloc failed\n");
983 return(NULL);
984 }
985
Daniel Veillard33942841998-10-18 19:12:41 +0000986 cur->type = XML_ELEMENT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000987 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000988 cur->parent = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000989 cur->next = NULL;
990 cur->prev = NULL;
991 cur->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000992 cur->last = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000993 cur->properties = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000994 cur->name = xmlStrdup(name);
995 cur->ns = ns;
996 cur->nsDef = NULL;
Daniel Veillardccb09631998-10-27 06:21:04 +0000997 cur->content = NULL;
Daniel Veillard27d88741999-05-29 11:51:49 +0000998#ifndef XML_WITHOUT_CORBA
Daniel Veillard27fb0751998-10-17 06:47:46 +0000999 cur->_private = NULL;
1000 cur->vepv = NULL;
1001#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001002 return(cur);
1003}
1004
Daniel Veillard97b58771998-10-20 06:14:16 +00001005/**
1006 * xmlNewDocNode:
1007 * @doc: the document
1008 * @ns: namespace if any
1009 * @name: the node name
1010 * @content: the text content if any
1011 *
1012 * Creation of a new node element within a document. @ns and @content
1013 * are optionnal (NULL).
Daniel Veillard1e346af1999-02-22 10:33:01 +00001014 * Returns a pointer to the new node object.
Daniel Veillard97b58771998-10-20 06:14:16 +00001015 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001016xmlNodePtr
1017xmlNewDocNode(xmlDocPtr doc, xmlNsPtr ns,
Daniel Veillard15b75af1999-07-26 16:42:37 +00001018 const CHAR *name, const CHAR *content) {
Daniel Veillard0bef1311998-10-14 02:36:47 +00001019 xmlNodePtr cur;
1020
Daniel Veillardccb09631998-10-27 06:21:04 +00001021 cur = xmlNewNode(ns, name);
1022 if (cur != NULL) {
1023 cur->doc = doc;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001024 if (content != NULL) {
Daniel Veillardccb09631998-10-27 06:21:04 +00001025 cur->childs = xmlStringGetNodeList(doc, content);
Daniel Veillard1e346af1999-02-22 10:33:01 +00001026 UPDATE_LAST_CHILD(cur)
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001027 }
Daniel Veillardccb09631998-10-27 06:21:04 +00001028 }
Daniel Veillard0bef1311998-10-14 02:36:47 +00001029 return(cur);
1030}
1031
1032
Daniel Veillard97b58771998-10-20 06:14:16 +00001033/**
1034 * xmlNewText:
1035 * @content: the text content
1036 *
1037 * Creation of a new text node.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001038 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001039 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001040xmlNodePtr
1041xmlNewText(const CHAR *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001042 xmlNodePtr cur;
1043
1044 /*
1045 * Allocate a new node and fill the fields.
1046 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001047 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillard260a68f1998-08-13 03:39:55 +00001048 if (cur == NULL) {
1049 fprintf(stderr, "xmlNewText : malloc failed\n");
1050 return(NULL);
1051 }
1052
Daniel Veillard33942841998-10-18 19:12:41 +00001053 cur->type = XML_TEXT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001054 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001055 cur->parent = NULL;
1056 cur->next = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001057 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001058 cur->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001059 cur->last = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001060 cur->properties = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001061 cur->type = XML_TEXT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001062 cur->name = xmlStrdup(xmlStringText);
1063 cur->ns = NULL;
1064 cur->nsDef = NULL;
1065 if (content != NULL)
1066 cur->content = xmlStrdup(content);
1067 else
1068 cur->content = NULL;
1069 return(cur);
1070}
1071
Daniel Veillard97b58771998-10-20 06:14:16 +00001072/**
Daniel Veillardccb09631998-10-27 06:21:04 +00001073 * xmlNewReference:
1074 * @doc: the document
1075 * @name: the reference name, or the reference string with & and ;
1076 *
1077 * Creation of a new reference node.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001078 * Returns a pointer to the new node object.
Daniel Veillardccb09631998-10-27 06:21:04 +00001079 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001080xmlNodePtr
1081xmlNewReference(xmlDocPtr doc, const CHAR *name) {
Daniel Veillardccb09631998-10-27 06:21:04 +00001082 xmlNodePtr cur;
1083 xmlEntityPtr ent;
1084
1085 /*
1086 * Allocate a new node and fill the fields.
1087 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001088 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillardccb09631998-10-27 06:21:04 +00001089 if (cur == NULL) {
1090 fprintf(stderr, "xmlNewText : malloc failed\n");
1091 return(NULL);
1092 }
1093
1094 cur->type = XML_ENTITY_REF_NODE;
Daniel Veillard10c6a8f1998-10-28 01:00:12 +00001095 cur->doc = doc;
Daniel Veillardccb09631998-10-27 06:21:04 +00001096 cur->parent = NULL;
1097 cur->next = NULL;
1098 cur->prev = NULL;
1099 cur->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001100 cur->last = NULL;
Daniel Veillardccb09631998-10-27 06:21:04 +00001101 cur->properties = NULL;
1102 if (name[0] == '&') {
1103 int len;
1104 name++;
1105 len = xmlStrlen(name);
1106 if (name[len - 1] == ';')
1107 cur->name = xmlStrndup(name, len - 1);
1108 else
1109 cur->name = xmlStrndup(name, len);
1110 } else
1111 cur->name = xmlStrdup(name);
1112 cur->ns = NULL;
1113 cur->nsDef = NULL;
1114
1115 ent = xmlGetDocEntity(doc, cur->name);
1116 if (ent != NULL)
1117 cur->content = ent->content;
1118 else
1119 cur->content = NULL;
1120 return(cur);
1121}
1122
1123/**
Daniel Veillard97b58771998-10-20 06:14:16 +00001124 * xmlNewDocText:
1125 * @doc: the document
1126 * @content: the text content
1127 *
1128 * Creation of a new text node within a document.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001129 * Returns a pointer to the new node object.
Daniel Veillard97b58771998-10-20 06:14:16 +00001130 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001131xmlNodePtr
1132xmlNewDocText(xmlDocPtr doc, const CHAR *content) {
Daniel Veillard0bef1311998-10-14 02:36:47 +00001133 xmlNodePtr cur;
1134
1135 cur = xmlNewText(content);
1136 if (cur != NULL) cur->doc = doc;
1137 return(cur);
1138}
1139
Daniel Veillard97b58771998-10-20 06:14:16 +00001140/**
Daniel Veillardccb09631998-10-27 06:21:04 +00001141 * xmlNewTextLen:
Daniel Veillard97b58771998-10-20 06:14:16 +00001142 * @content: the text content
1143 * @len: the text len.
1144 *
1145 * Creation of a new text node with an extra parameter for the content's lenght
Daniel Veillard1e346af1999-02-22 10:33:01 +00001146 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001147 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001148xmlNodePtr
1149xmlNewTextLen(const CHAR *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001150 xmlNodePtr cur;
1151
1152 /*
1153 * Allocate a new node and fill the fields.
1154 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001155 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillard260a68f1998-08-13 03:39:55 +00001156 if (cur == NULL) {
1157 fprintf(stderr, "xmlNewText : malloc failed\n");
1158 return(NULL);
1159 }
1160
Daniel Veillard33942841998-10-18 19:12:41 +00001161 cur->type = XML_TEXT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001162 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001163 cur->parent = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001164 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001165 cur->next = NULL;
1166 cur->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001167 cur->last = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001168 cur->properties = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001169 cur->type = XML_TEXT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001170 cur->name = xmlStrdup(xmlStringText);
1171 cur->ns = NULL;
1172 cur->nsDef = NULL;
1173 if (content != NULL)
1174 cur->content = xmlStrndup(content, len);
1175 else
1176 cur->content = NULL;
1177 return(cur);
1178}
1179
Daniel Veillard97b58771998-10-20 06:14:16 +00001180/**
1181 * xmlNewDocTextLen:
1182 * @doc: the document
1183 * @content: the text content
1184 * @len: the text len.
1185 *
1186 * Creation of a new text node with an extra content lenght parameter. The
1187 * text node pertain to a given document.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001188 * Returns a pointer to the new node object.
Daniel Veillard97b58771998-10-20 06:14:16 +00001189 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001190xmlNodePtr
1191xmlNewDocTextLen(xmlDocPtr doc, const CHAR *content, int len) {
Daniel Veillard0bef1311998-10-14 02:36:47 +00001192 xmlNodePtr cur;
1193
1194 cur = xmlNewTextLen(content, len);
1195 if (cur != NULL) cur->doc = doc;
1196 return(cur);
1197}
1198
Daniel Veillard97b58771998-10-20 06:14:16 +00001199/**
1200 * xmlNewComment:
1201 * @content: the comment content
1202 *
1203 * Creation of a new node containing a comment.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001204 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001205 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001206xmlNodePtr
Daniel Veillard517752b1999-04-05 12:20:10 +00001207xmlNewComment(const CHAR *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001208 xmlNodePtr cur;
1209
1210 /*
1211 * Allocate a new node and fill the fields.
1212 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001213 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillard260a68f1998-08-13 03:39:55 +00001214 if (cur == NULL) {
1215 fprintf(stderr, "xmlNewComment : malloc failed\n");
1216 return(NULL);
1217 }
1218
Daniel Veillard33942841998-10-18 19:12:41 +00001219 cur->type = XML_COMMENT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001220 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001221 cur->parent = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001222 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001223 cur->next = NULL;
1224 cur->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001225 cur->last = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001226 cur->properties = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001227 cur->type = XML_COMMENT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001228 cur->name = xmlStrdup(xmlStringText);
1229 cur->ns = NULL;
1230 cur->nsDef = NULL;
1231 if (content != NULL)
1232 cur->content = xmlStrdup(content);
1233 else
1234 cur->content = NULL;
1235 return(cur);
1236}
1237
Daniel Veillard97b58771998-10-20 06:14:16 +00001238/**
Daniel Veillardb05deb71999-08-10 19:04:08 +00001239 * xmlNewCDataBlock:
1240 * @doc: the document
1241 * @content: the CData block content content
1242 * @len: the length of the block
1243 *
1244 * Creation of a new node containing a CData block.
1245 * Returns a pointer to the new node object.
1246 */
1247xmlNodePtr
1248xmlNewCDataBlock(xmlDocPtr doc, const CHAR *content, int len) {
1249 xmlNodePtr cur;
1250
1251 /*
1252 * Allocate a new node and fill the fields.
1253 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001254 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillardb05deb71999-08-10 19:04:08 +00001255 if (cur == NULL) {
1256 fprintf(stderr, "xmlNewCDataBlock : malloc failed\n");
1257 return(NULL);
1258 }
1259
1260 cur->type = XML_CDATA_SECTION_NODE;
1261 cur->doc = NULL;
1262 cur->parent = NULL;
1263 cur->prev = NULL;
1264 cur->next = NULL;
1265 cur->childs = NULL;
1266 cur->last = NULL;
1267 cur->properties = NULL;
1268 cur->name = xmlStrdup(xmlStringText);
1269 cur->ns = NULL;
1270 cur->nsDef = NULL;
1271 if ((content != NULL) && (len > 0)) {
1272 cur->content = xmlStrndup(content, len);
1273 } else
1274 cur->content = NULL;
1275 return(cur);
1276}
1277
1278/**
Daniel Veillard1e346af1999-02-22 10:33:01 +00001279 * xmlNewDocComment:
Daniel Veillard97b58771998-10-20 06:14:16 +00001280 * @doc: the document
1281 * @content: the comment content
1282 *
1283 * Creation of a new node containing a commentwithin a document.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001284 * Returns a pointer to the new node object.
Daniel Veillard97b58771998-10-20 06:14:16 +00001285 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001286xmlNodePtr
Daniel Veillard517752b1999-04-05 12:20:10 +00001287xmlNewDocComment(xmlDocPtr doc, const CHAR *content) {
Daniel Veillard0bef1311998-10-14 02:36:47 +00001288 xmlNodePtr cur;
1289
1290 cur = xmlNewComment(content);
1291 if (cur != NULL) cur->doc = doc;
1292 return(cur);
1293}
1294
Daniel Veillard97b58771998-10-20 06:14:16 +00001295/**
1296 * xmlNewChild:
1297 * @parent: the parent node
1298 * @ns: a namespace if any
1299 * @name: the name of the child
1300 * @content: the content of the child if any.
1301 *
1302 *
1303 * Creation of a new child element, added at the end of @parent childs list.
Daniel Veillardccb09631998-10-27 06:21:04 +00001304 * @ns and @content parameters are optionnal (NULL). If content is non NULL,
1305 * a child list containing the TEXTs and ENTITY_REFs node will be created.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001306 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001307 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001308xmlNodePtr
1309xmlNewChild(xmlNodePtr parent, xmlNsPtr ns,
Daniel Veillard15b75af1999-07-26 16:42:37 +00001310 const CHAR *name, const CHAR *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001311 xmlNodePtr cur, prev;
1312
1313 if (parent == NULL) {
1314 fprintf(stderr, "xmlNewChild : parent == NULL\n");
1315 return(NULL);
1316 }
1317
1318 if (name == NULL) {
1319 fprintf(stderr, "xmlNewChild : name == NULL\n");
1320 return(NULL);
1321 }
1322
1323 /*
1324 * Allocate a new node
1325 */
1326 if (ns == NULL)
Daniel Veillardccb09631998-10-27 06:21:04 +00001327 cur = xmlNewDocNode(parent->doc, parent->ns, name, content);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001328 else
Daniel Veillardccb09631998-10-27 06:21:04 +00001329 cur = xmlNewDocNode(parent->doc, ns, name, content);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001330 if (cur == NULL) return(NULL);
1331
1332 /*
1333 * add the new element at the end of the childs list.
1334 */
Daniel Veillardccb09631998-10-27 06:21:04 +00001335 cur->type = XML_ELEMENT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001336 cur->parent = parent;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001337 cur->doc = parent->doc;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001338 if (parent->childs == NULL) {
1339 parent->childs = cur;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001340 parent->last = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001341 } else {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001342 prev = parent->last;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001343 prev->next = cur;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001344 cur->prev = prev;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001345 parent->last = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001346 }
1347
1348 return(cur);
1349}
1350
Daniel Veillard97b58771998-10-20 06:14:16 +00001351/**
Daniel Veillardb96e6431999-08-29 21:02:19 +00001352 * xmlAddSibling:
1353 * @cur: the child node
1354 * @elem: the new node
1355 *
1356 * Add a new element to the list of siblings of @cur
1357 * Returns the element or NULL in case of error.
1358 */
1359xmlNodePtr
1360xmlAddSibling(xmlNodePtr cur, xmlNodePtr elem) {
1361 xmlNodePtr parent;
1362
1363 if (cur == NULL) {
1364 fprintf(stderr, "xmlAddSibling : cur == NULL\n");
1365 return(NULL);
1366 }
1367
1368 if (elem == NULL) {
1369 fprintf(stderr, "xmlAddSibling : elem == NULL\n");
1370 return(NULL);
1371 }
1372
1373 if ((cur->doc != NULL) && (elem->doc != NULL) &&
1374 (cur->doc != elem->doc)) {
1375 fprintf(stderr,
1376 "xmlAddSibling: Elements moved to a different document\n");
1377 }
1378
1379 while (cur->next != NULL) cur = cur->next;
1380
1381 if (elem->doc == NULL)
1382 elem->doc = cur->doc; /* the parent may not be linked to a doc ! */
1383
1384 parent = cur->parent;
1385 elem->prev = cur;
1386 elem->next = NULL;
1387 elem->parent = parent;
1388 cur->next = elem;
1389 if (parent != NULL)
1390 parent->last = elem;
1391
1392 return(elem);
1393}
1394
1395/**
Daniel Veillard97b58771998-10-20 06:14:16 +00001396 * xmlAddChild:
1397 * @parent: the parent node
1398 * @cur: the child node
1399 *
1400 * Add a new child element, to @parent, at the end of the child list.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001401 * Returns the child or NULL in case of error.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001402 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001403xmlNodePtr
1404xmlAddChild(xmlNodePtr parent, xmlNodePtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001405 xmlNodePtr prev;
1406
1407 if (parent == NULL) {
1408 fprintf(stderr, "xmladdChild : parent == NULL\n");
1409 return(NULL);
1410 }
1411
1412 if (cur == NULL) {
1413 fprintf(stderr, "xmladdChild : child == NULL\n");
1414 return(NULL);
1415 }
1416
Daniel Veillard0bef1311998-10-14 02:36:47 +00001417 if ((cur->doc != NULL) && (parent->doc != NULL) &&
1418 (cur->doc != parent->doc)) {
1419 fprintf(stderr, "Elements moved to a different document\n");
1420 }
1421
Daniel Veillard260a68f1998-08-13 03:39:55 +00001422 /*
1423 * add the new element at the end of the childs list.
1424 */
1425 cur->parent = parent;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001426 cur->doc = parent->doc; /* the parent may not be linked to a doc ! */
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001427
Daniel Veillardccb09631998-10-27 06:21:04 +00001428 /*
1429 * Handle the case where parent->content != NULL, in that case it will
1430 * create a intermediate TEXT node.
1431 */
1432 if (parent->content != NULL) {
1433 xmlNodePtr text;
1434
1435 text = xmlNewDocText(parent->doc, parent->content);
1436 if (text != NULL) {
1437 text->next = parent->childs;
1438 if (text->next != NULL)
1439 text->next->prev = text;
1440 parent->childs = text;
Daniel Veillard1e346af1999-02-22 10:33:01 +00001441 UPDATE_LAST_CHILD(parent)
Daniel Veillard6454aec1999-09-02 22:04:43 +00001442 xmlFree(parent->content);
Daniel Veillardccb09631998-10-27 06:21:04 +00001443 parent->content = NULL;
1444 }
1445 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00001446 if (parent->childs == NULL) {
1447 parent->childs = cur;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001448 parent->last = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001449 } else {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001450 prev = parent->last;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001451 prev->next = cur;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001452 cur->prev = prev;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001453 parent->last = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001454 }
1455
1456 return(cur);
1457}
1458
Daniel Veillard97b58771998-10-20 06:14:16 +00001459/**
1460 * xmlGetLastChild:
1461 * @parent: the parent node
1462 *
1463 * Search the last child of a node.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001464 * Returns the last child or NULL if none.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001465 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001466xmlNodePtr
1467xmlGetLastChild(xmlNodePtr parent) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001468 if (parent == NULL) {
1469 fprintf(stderr, "xmlGetLastChild : parent == NULL\n");
1470 return(NULL);
1471 }
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001472 return(parent->last);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001473}
1474
Daniel Veillard97b58771998-10-20 06:14:16 +00001475/**
1476 * xmlFreeNodeList:
1477 * @cur: the first node in the list
1478 *
1479 * Free a node and all its siblings, this is a recursive behaviour, all
1480 * the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001481 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001482void
1483xmlFreeNodeList(xmlNodePtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001484 xmlNodePtr next;
1485 if (cur == NULL) {
1486 fprintf(stderr, "xmlFreeNodeList : node == NULL\n");
1487 return;
1488 }
1489 while (cur != NULL) {
1490 next = cur->next;
1491 xmlFreeNode(cur);
1492 cur = next;
1493 }
1494}
1495
Daniel Veillard97b58771998-10-20 06:14:16 +00001496/**
1497 * xmlFreeNode:
1498 * @cur: the node
1499 *
1500 * Free a node, this is a recursive behaviour, all the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001501 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001502void
1503xmlFreeNode(xmlNodePtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001504 if (cur == NULL) {
1505 fprintf(stderr, "xmlFreeNode : node == NULL\n");
1506 return;
1507 }
Daniel Veillardccb09631998-10-27 06:21:04 +00001508 cur->doc = NULL;
1509 cur->parent = NULL;
1510 cur->next = NULL;
1511 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001512 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillardccb09631998-10-27 06:21:04 +00001513 if (cur->properties != NULL) xmlFreePropList(cur->properties);
1514 if (cur->type != XML_ENTITY_REF_NODE)
Daniel Veillard6454aec1999-09-02 22:04:43 +00001515 if (cur->content != NULL) xmlFree(cur->content);
1516 if (cur->name != NULL) xmlFree((char *) cur->name);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001517 if (cur->nsDef != NULL) xmlFreeNsList(cur->nsDef);
1518 memset(cur, -1, sizeof(xmlNode));
Daniel Veillard6454aec1999-09-02 22:04:43 +00001519 xmlFree(cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001520}
1521
Daniel Veillard16253641998-10-28 22:58:05 +00001522/**
1523 * xmlUnlinkNode:
1524 * @cur: the node
1525 *
1526 * Unlink a node from it's current context, the node is not freed
1527 */
1528void
1529xmlUnlinkNode(xmlNodePtr cur) {
1530 if (cur == NULL) {
1531 fprintf(stderr, "xmlUnlinkNode : node == NULL\n");
1532 return;
1533 }
1534 if ((cur->parent != NULL) && (cur->parent->childs == cur))
1535 cur->parent->childs = cur->next;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001536 if ((cur->parent != NULL) && (cur->parent->last == cur))
1537 cur->parent->last = cur->prev;
Daniel Veillard16253641998-10-28 22:58:05 +00001538 if (cur->next != NULL)
1539 cur->next->prev = cur->prev;
1540 if (cur->prev != NULL)
1541 cur->prev->next = cur->next;
1542 cur->next = cur->prev = NULL;
1543 cur->parent = NULL;
1544}
1545
Daniel Veillard260a68f1998-08-13 03:39:55 +00001546/************************************************************************
1547 * *
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001548 * Copy operations *
1549 * *
1550 ************************************************************************/
1551
1552/**
1553 * xmlCopyNamespace:
1554 * @cur: the namespace
1555 *
1556 * Do a copy of the namespace.
1557 *
1558 * Returns: a new xmlNsPtr, or NULL in case of error.
1559 */
1560xmlNsPtr
1561xmlCopyNamespace(xmlNsPtr cur) {
1562 xmlNsPtr ret;
1563
1564 if (cur == NULL) return(NULL);
1565 switch (cur->type) {
1566 case XML_GLOBAL_NAMESPACE:
1567 ret = xmlNewGlobalNs(NULL, cur->href, cur->prefix);
1568 break;
1569 case XML_LOCAL_NAMESPACE:
1570 ret = xmlNewNs(NULL, cur->href, cur->prefix);
1571 break;
1572 default:
1573 fprintf(stderr, "xmlCopyNamespace: unknown type %d\n", cur->type);
1574 return(NULL);
1575 }
1576 return(ret);
1577}
1578
1579/**
1580 * xmlCopyNamespaceList:
1581 * @cur: the first namespace
1582 *
1583 * Do a copy of an namespace list.
1584 *
1585 * Returns: a new xmlNsPtr, or NULL in case of error.
1586 */
1587xmlNsPtr
1588xmlCopyNamespaceList(xmlNsPtr cur) {
1589 xmlNsPtr ret = NULL;
1590 xmlNsPtr p = NULL,q;
1591
1592 while (cur != NULL) {
1593 q = xmlCopyNamespace(cur);
1594 if (p == NULL) {
1595 ret = p = q;
1596 } else {
1597 p->next = q;
1598 p = q;
1599 }
1600 cur = cur->next;
1601 }
1602 return(ret);
1603}
1604
1605/**
1606 * xmlCopyProp:
Daniel Veillardb96e6431999-08-29 21:02:19 +00001607 * @target: the element where the attribute will be grafted
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001608 * @cur: the attribute
1609 *
1610 * Do a copy of the attribute.
1611 *
1612 * Returns: a new xmlAttrPtr, or NULL in case of error.
1613 */
1614xmlAttrPtr
Daniel Veillardb96e6431999-08-29 21:02:19 +00001615xmlCopyProp(xmlNodePtr target, xmlAttrPtr cur) {
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001616 xmlAttrPtr ret;
1617
1618 if (cur == NULL) return(NULL);
1619 if (cur->val != NULL)
1620 ret = xmlNewDocProp(cur->val->doc, cur->name, NULL);
1621 else
1622 ret = xmlNewDocProp(NULL, cur->name, NULL);
1623 if (ret == NULL) return(NULL);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001624
1625 if ((cur->ns != NULL) && (target != NULL)) {
1626 xmlNsPtr ns;
1627
1628 ns = xmlSearchNs(target->doc, target, cur->ns->prefix);
1629 ret->ns = ns;
1630 } else
1631 ret->ns = NULL;
1632
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001633 if (cur->val != NULL)
1634 ret->val = xmlCopyNodeList(cur->val);
1635 return(ret);
1636}
1637
1638/**
1639 * xmlCopyPropList:
Daniel Veillardb96e6431999-08-29 21:02:19 +00001640 * @target: the element where the attributes will be grafted
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001641 * @cur: the first attribute
1642 *
1643 * Do a copy of an attribute list.
1644 *
1645 * Returns: a new xmlAttrPtr, or NULL in case of error.
1646 */
1647xmlAttrPtr
Daniel Veillardb96e6431999-08-29 21:02:19 +00001648xmlCopyPropList(xmlNodePtr target, xmlAttrPtr cur) {
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001649 xmlAttrPtr ret = NULL;
1650 xmlAttrPtr p = NULL,q;
1651
1652 while (cur != NULL) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00001653 q = xmlCopyProp(target, cur);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001654 if (p == NULL) {
1655 ret = p = q;
1656 } else {
1657 p->next = q;
1658 p = q;
1659 }
1660 cur = cur->next;
1661 }
1662 return(ret);
1663}
1664
1665/*
1666 * NOTE about the CopyNode operations !
1667 *
1668 * They are splitted into external and internal parts for one
1669 * tricky reason: namespaces. Doing a direct copy of a node
1670 * say RPM:Copyright without changing the namespace pointer to
1671 * something else can produce stale links. One way to do it is
1672 * to keep a reference counter but this doesn't work as soon
1673 * as one move the element or the subtree out of the scope of
1674 * the existing namespace. The actual solution seems to add
1675 * a copy of the namespace at the top of the copied tree if
1676 * not available in the subtree.
1677 * Hence two functions, the public front-end call the inner ones
1678 */
1679
1680static xmlNodePtr
1681xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent);
1682
1683static xmlNodePtr
1684xmlStaticCopyNode(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent,
1685 int recursive) {
1686 xmlNodePtr ret;
1687
1688 if (node == NULL) return(NULL);
1689 /*
1690 * Allocate a new node and fill the fields.
1691 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001692 ret = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001693 if (ret == NULL) {
1694 fprintf(stderr, "xmlStaticCopyNode : malloc failed\n");
1695 return(NULL);
1696 }
1697
1698 ret->type = node->type;
1699 ret->doc = doc;
1700 ret->parent = parent;
1701 ret->next = NULL;
1702 ret->prev = NULL;
1703 ret->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001704 ret->last = NULL;
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001705 ret->properties = NULL;
1706 if (node->name != NULL)
1707 ret->name = xmlStrdup(node->name);
1708 else
1709 ret->name = NULL;
1710 ret->ns = NULL;
1711 ret->nsDef = NULL;
1712 if ((node->content != NULL) && (node->type != XML_ENTITY_REF_NODE))
1713 ret->content = xmlStrdup(node->content);
1714 else
1715 ret->content = NULL;
Daniel Veillard27d88741999-05-29 11:51:49 +00001716#ifndef XML_WITHOUT_CORBA
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001717 ret->_private = NULL;
1718 ret->vepv = NULL;
1719#endif
1720 if (parent != NULL)
1721 xmlAddChild(parent, ret);
1722
1723 if (!recursive) return(ret);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001724 if (node->nsDef != NULL)
1725 ret->nsDef = xmlCopyNamespaceList(node->nsDef);
1726
1727 if (node->ns != NULL) {
1728 xmlNsPtr ns;
1729
1730 ns = xmlSearchNs(doc, ret, node->ns->prefix);
1731 if (ns == NULL) {
1732 /*
1733 * Humm, we are copying an element whose namespace is defined
1734 * out of the new tree scope. Search it in the original tree
1735 * and add it at the top of the new tree
1736 */
1737 ns = xmlSearchNs(node->doc, node, node->ns->prefix);
1738 if (ns != NULL) {
1739 xmlNodePtr root = ret;
1740
1741 while (root->parent != NULL) root = root->parent;
1742 xmlNewNs(root, ns->href, ns->prefix);
1743 }
1744 } else {
1745 /*
1746 * reference the existing namespace definition in our own tree.
1747 */
1748 ret->ns = ns;
1749 }
1750 }
Daniel Veillardb96e6431999-08-29 21:02:19 +00001751 if (node->properties != NULL)
1752 ret->properties = xmlCopyPropList(ret, node->properties);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001753 if (node->childs != NULL)
1754 ret->childs = xmlStaticCopyNodeList(node->childs, doc, ret);
Daniel Veillard1e346af1999-02-22 10:33:01 +00001755 UPDATE_LAST_CHILD(ret)
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001756 return(ret);
1757}
1758
1759static xmlNodePtr
1760xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent) {
1761 xmlNodePtr ret = NULL;
1762 xmlNodePtr p = NULL,q;
1763
1764 while (node != NULL) {
1765 q = xmlStaticCopyNode(node, doc, parent, 1);
1766 if (parent == NULL) {
1767 if (ret == NULL) ret = q;
1768 } else {
1769 if (ret == NULL) {
1770 q->prev = NULL;
1771 ret = p = q;
1772 } else {
1773 p->next = q;
1774 q->prev = p;
1775 p = q;
1776 }
1777 }
1778 node = node->next;
1779 }
1780 return(ret);
1781}
1782
1783/**
1784 * xmlCopyNode:
1785 * @node: the node
1786 * @recursive: if 1 do a recursive copy.
1787 *
1788 * Do a copy of the node.
1789 *
1790 * Returns: a new xmlNodePtr, or NULL in case of error.
1791 */
1792xmlNodePtr
1793xmlCopyNode(xmlNodePtr node, int recursive) {
1794 xmlNodePtr ret;
1795
1796 ret = xmlStaticCopyNode(node, NULL, NULL, recursive);
1797 return(ret);
1798}
1799
1800/**
1801 * xmlCopyNodeList:
1802 * @node: the first node in the list.
1803 *
1804 * Do a recursive copy of the node list.
1805 *
1806 * Returns: a new xmlNodePtr, or NULL in case of error.
1807 */
1808xmlNodePtr xmlCopyNodeList(xmlNodePtr node) {
1809 xmlNodePtr ret = xmlStaticCopyNodeList(node, NULL, NULL);
1810 return(ret);
1811}
1812
1813/**
1814 * xmlCopyElement:
1815 * @elem: the element
1816 *
1817 * Do a copy of the element definition.
1818 *
1819 * Returns: a new xmlElementPtr, or NULL in case of error.
1820xmlElementPtr
1821xmlCopyElement(xmlElementPtr elem) {
1822 xmlElementPtr ret;
1823
1824 if (elem == NULL) return(NULL);
1825 ret = xmlNewDocElement(elem->doc, elem->ns, elem->name, elem->content);
1826 if (ret == NULL) return(NULL);
1827 if (!recursive) return(ret);
1828 if (elem->properties != NULL)
1829 ret->properties = xmlCopyPropList(elem->properties);
1830
1831 if (elem->nsDef != NULL)
1832 ret->nsDef = xmlCopyNamespaceList(elem->nsDef);
1833 if (elem->childs != NULL)
1834 ret->childs = xmlCopyElementList(elem->childs);
1835 return(ret);
1836}
1837 */
1838
1839/**
1840 * xmlCopyDtd:
1841 * @dtd: the dtd
1842 *
1843 * Do a copy of the dtd.
1844 *
1845 * Returns: a new xmlDtdPtr, or NULL in case of error.
1846 */
1847xmlDtdPtr
1848xmlCopyDtd(xmlDtdPtr dtd) {
1849 xmlDtdPtr ret;
1850
1851 if (dtd == NULL) return(NULL);
1852 ret = xmlNewDtd(NULL, dtd->name, dtd->ExternalID, dtd->SystemID);
1853 if (ret == NULL) return(NULL);
1854 if (dtd->entities != NULL)
1855 ret->entities = (void *) xmlCopyEntitiesTable(
1856 (xmlEntitiesTablePtr) dtd->entities);
Daniel Veillard1e346af1999-02-22 10:33:01 +00001857 if (dtd->notations != NULL)
1858 ret->notations = (void *) xmlCopyNotationTable(
1859 (xmlNotationTablePtr) dtd->notations);
1860 if (dtd->elements != NULL)
1861 ret->elements = (void *) xmlCopyElementTable(
1862 (xmlElementTablePtr) dtd->elements);
1863 if (dtd->attributes != NULL)
1864 ret->attributes = (void *) xmlCopyAttributeTable(
1865 (xmlAttributeTablePtr) dtd->attributes);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001866 return(ret);
1867}
1868
1869/**
1870 * xmlCopyDoc:
1871 * @doc: the document
1872 * @recursive: if 1 do a recursive copy.
1873 *
1874 * Do a copy of the document info. If recursive, the content tree will
1875 * be copied too as well as Dtd, namespaces and entities.
1876 *
1877 * Returns: a new xmlDocPtr, or NULL in case of error.
1878 */
1879xmlDocPtr
1880xmlCopyDoc(xmlDocPtr doc, int recursive) {
1881 xmlDocPtr ret;
1882
1883 if (doc == NULL) return(NULL);
1884 ret = xmlNewDoc(doc->version);
1885 if (ret == NULL) return(NULL);
1886 if (doc->name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +00001887 ret->name = xmlMemStrdup(doc->name);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001888 if (doc->encoding != NULL)
1889 ret->encoding = xmlStrdup(doc->encoding);
1890 ret->compression = doc->compression;
1891 ret->standalone = doc->standalone;
1892 if (!recursive) return(ret);
1893
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001894 if (doc->intSubset != NULL)
1895 ret->intSubset = xmlCopyDtd(doc->intSubset);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001896 if (doc->oldNs != NULL)
1897 ret->oldNs = xmlCopyNamespaceList(doc->oldNs);
1898 if (doc->root != NULL)
1899 ret->root = xmlStaticCopyNodeList(doc->root, ret, NULL);
1900 return(ret);
1901}
1902
1903/************************************************************************
1904 * *
Daniel Veillard260a68f1998-08-13 03:39:55 +00001905 * Content access functions *
1906 * *
1907 ************************************************************************/
1908
Daniel Veillard97b58771998-10-20 06:14:16 +00001909/**
Daniel Veillardb96e6431999-08-29 21:02:19 +00001910 * xmlNodeSetLang:
1911 * @cur: the node being changed
1912 * @lang: the langage description
1913 *
1914 * Searches the language of a node, i.e. the values of the xml:lang
1915 * attribute or the one carried by the nearest ancestor.
1916 *
1917 * Returns a pointer to the lang value, or NULL if not found
1918 */
1919void
1920xmlNodeSetLang(xmlNodePtr cur, const CHAR *lang) {
1921 /* TODO xmlNodeSetLang check against the production [33] LanguageID */
1922 xmlSetProp(cur, BAD_CAST "xml:lang", lang);
1923}
1924
1925/**
1926 * xmlNodeGetLang:
1927 * @cur: the node being checked
1928 *
1929 * Searches the language of a node, i.e. the values of the xml:lang
1930 * attribute or the one carried by the nearest ancestor.
1931 *
1932 * Returns a pointer to the lang value, or NULL if not found
1933 */
1934const CHAR *
1935xmlNodeGetLang(xmlNodePtr cur) {
1936 const CHAR *lang;
1937
1938 while (cur != NULL) {
1939 lang = xmlGetProp(cur, BAD_CAST "xml:lang");
1940 if (lang != NULL)
1941 return(lang);
1942 cur = cur->parent;
1943 }
1944 return(NULL);
1945}
1946
1947/**
Daniel Veillard16253641998-10-28 22:58:05 +00001948 * xmlNodeGetContent:
1949 * @cur: the node being read
1950 *
1951 * Read the value of a node, this can be either the text carried
1952 * directly by this node if it's a TEXT node or the aggregate string
1953 * of the values carried by this node child's (TEXT and ENTITY_REF).
1954 * Entity references are substitued.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001955 * Returns a new CHAR * or NULL if no content is available.
Daniel Veillard5099ae81999-04-21 20:12:07 +00001956 * It's up to the caller to free the memory.
Daniel Veillard16253641998-10-28 22:58:05 +00001957 */
1958CHAR *
1959xmlNodeGetContent(xmlNodePtr cur) {
1960 if (cur == NULL) return(NULL);
1961 switch (cur->type) {
1962 case XML_DOCUMENT_FRAG_NODE:
1963 case XML_ELEMENT_NODE:
1964 return(xmlNodeListGetString(cur->doc, cur->childs, 1));
1965 break;
Daniel Veillardb96e6431999-08-29 21:02:19 +00001966 case XML_ATTRIBUTE_NODE: {
1967 xmlAttrPtr attr = (xmlAttrPtr) cur;
1968 if (attr->node != NULL)
1969 return(xmlNodeListGetString(attr->node->doc, attr->val, 1));
1970 else
1971 return(xmlNodeListGetString(NULL, attr->val, 1));
1972 break;
1973 }
1974 case XML_PI_NODE:
1975 if (cur->content != NULL)
1976 return(xmlStrdup(cur->content));
1977 return(NULL);
Daniel Veillard16253641998-10-28 22:58:05 +00001978 case XML_ENTITY_REF_NODE:
1979 case XML_ENTITY_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00001980 case XML_COMMENT_NODE:
1981 case XML_DOCUMENT_NODE:
1982 case XML_DOCUMENT_TYPE_NODE:
1983 case XML_NOTATION_NODE:
1984 return(NULL);
Daniel Veillardb05deb71999-08-10 19:04:08 +00001985 case XML_CDATA_SECTION_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00001986 case XML_TEXT_NODE:
1987 if (cur->content != NULL)
1988 return(xmlStrdup(cur->content));
1989 return(NULL);
1990 }
1991 return(NULL);
1992}
1993
1994/**
Daniel Veillard97b58771998-10-20 06:14:16 +00001995 * xmlNodeSetContent:
1996 * @cur: the node being modified
1997 * @content: the new value of the content
1998 *
1999 * Replace the content of a node.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002000 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002001void
2002xmlNodeSetContent(xmlNodePtr cur, const CHAR *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002003 if (cur == NULL) {
2004 fprintf(stderr, "xmlNodeSetContent : node == NULL\n");
2005 return;
2006 }
Daniel Veillard16253641998-10-28 22:58:05 +00002007 switch (cur->type) {
2008 case XML_DOCUMENT_FRAG_NODE:
2009 case XML_ELEMENT_NODE:
2010 if (cur->content != NULL) {
Daniel Veillard6454aec1999-09-02 22:04:43 +00002011 xmlFree(cur->content);
Daniel Veillard16253641998-10-28 22:58:05 +00002012 cur->content = NULL;
2013 }
Daniel Veillard6454aec1999-09-02 22:04:43 +00002014 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillard16253641998-10-28 22:58:05 +00002015 cur->childs = xmlStringGetNodeList(cur->doc, content);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002016 UPDATE_LAST_CHILD(cur)
Daniel Veillard16253641998-10-28 22:58:05 +00002017 break;
2018 case XML_ATTRIBUTE_NODE:
2019 break;
2020 case XML_TEXT_NODE:
2021 case XML_CDATA_SECTION_NODE:
2022 case XML_ENTITY_REF_NODE:
2023 case XML_ENTITY_NODE:
2024 case XML_PI_NODE:
2025 case XML_COMMENT_NODE:
Daniel Veillard6454aec1999-09-02 22:04:43 +00002026 if (cur->content != NULL) xmlFree(cur->content);
2027 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002028 cur->last = cur->childs = NULL;
Daniel Veillard16253641998-10-28 22:58:05 +00002029 if (content != NULL)
2030 cur->content = xmlStrdup(content);
2031 else
2032 cur->content = NULL;
Daniel Veillardb96e6431999-08-29 21:02:19 +00002033 break;
Daniel Veillard16253641998-10-28 22:58:05 +00002034 case XML_DOCUMENT_NODE:
2035 case XML_DOCUMENT_TYPE_NODE:
2036 break;
2037 case XML_NOTATION_NODE:
2038 break;
2039 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002040}
2041
Daniel Veillard97b58771998-10-20 06:14:16 +00002042/**
2043 * xmlNodeSetContentLen:
2044 * @cur: the node being modified
2045 * @content: the new value of the content
2046 * @len: the size of @content
2047 *
2048 * Replace the content of a node.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002049 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002050void
2051xmlNodeSetContentLen(xmlNodePtr cur, const CHAR *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002052 if (cur == NULL) {
Daniel Veillard16253641998-10-28 22:58:05 +00002053 fprintf(stderr, "xmlNodeSetContentLen : node == NULL\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002054 return;
2055 }
Daniel Veillard16253641998-10-28 22:58:05 +00002056 switch (cur->type) {
2057 case XML_DOCUMENT_FRAG_NODE:
2058 case XML_ELEMENT_NODE:
2059 if (cur->content != NULL) {
Daniel Veillard6454aec1999-09-02 22:04:43 +00002060 xmlFree(cur->content);
Daniel Veillard16253641998-10-28 22:58:05 +00002061 cur->content = NULL;
2062 }
Daniel Veillard6454aec1999-09-02 22:04:43 +00002063 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillard16253641998-10-28 22:58:05 +00002064 cur->childs = xmlStringLenGetNodeList(cur->doc, content, len);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002065 UPDATE_LAST_CHILD(cur)
Daniel Veillard16253641998-10-28 22:58:05 +00002066 break;
2067 case XML_ATTRIBUTE_NODE:
2068 break;
2069 case XML_TEXT_NODE:
2070 case XML_CDATA_SECTION_NODE:
2071 case XML_ENTITY_REF_NODE:
2072 case XML_ENTITY_NODE:
2073 case XML_PI_NODE:
2074 case XML_COMMENT_NODE:
Daniel Veillard6454aec1999-09-02 22:04:43 +00002075 if (cur->content != NULL) xmlFree(cur->content);
2076 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002077 cur->childs = cur->last = NULL;
Daniel Veillard16253641998-10-28 22:58:05 +00002078 if (content != NULL)
2079 cur->content = xmlStrndup(content, len);
2080 else
2081 cur->content = NULL;
Daniel Veillardb96e6431999-08-29 21:02:19 +00002082 break;
Daniel Veillard16253641998-10-28 22:58:05 +00002083 case XML_DOCUMENT_NODE:
2084 case XML_DOCUMENT_TYPE_NODE:
2085 break;
2086 case XML_NOTATION_NODE:
Daniel Veillard6454aec1999-09-02 22:04:43 +00002087 if (cur->content != NULL) xmlFree(cur->content);
2088 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002089 cur->childs = cur->last = NULL;
Daniel Veillard16253641998-10-28 22:58:05 +00002090 if (content != NULL)
2091 cur->content = xmlStrndup(content, len);
2092 else
2093 cur->content = NULL;
2094 break;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002095 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002096}
2097
Daniel Veillard97b58771998-10-20 06:14:16 +00002098/**
2099 * xmlNodeAddContentLen:
2100 * @cur: the node being modified
2101 * @content: extra content
2102 * @len: the size of @content
2103 *
2104 * Append the extra substring to the node content.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002105 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002106void
2107xmlNodeAddContentLen(xmlNodePtr cur, const CHAR *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002108 if (cur == NULL) {
Daniel Veillard16253641998-10-28 22:58:05 +00002109 fprintf(stderr, "xmlNodeAddContentLen : node == NULL\n");
2110 return;
2111 }
2112 if (len <= 0) return;
2113 switch (cur->type) {
2114 case XML_DOCUMENT_FRAG_NODE:
2115 case XML_ELEMENT_NODE: {
2116 xmlNodePtr last = NULL, new;
2117
2118 if (cur->childs != NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002119 last = cur->last;
Daniel Veillard16253641998-10-28 22:58:05 +00002120 } else {
2121 if (cur->content != NULL) {
2122 cur->childs = xmlStringGetNodeList(cur->doc, cur->content);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002123 UPDATE_LAST_CHILD(cur)
Daniel Veillard6454aec1999-09-02 22:04:43 +00002124 xmlFree(cur->content);
Daniel Veillard16253641998-10-28 22:58:05 +00002125 cur->content = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002126 last = cur->last;
Daniel Veillard16253641998-10-28 22:58:05 +00002127 }
2128 }
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002129 new = xmlNewTextLen(content, len);
Daniel Veillard16253641998-10-28 22:58:05 +00002130 if (new != NULL) {
2131 xmlAddChild(cur, new);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002132 if ((last != NULL) && (last->next == new)) {
Daniel Veillard16253641998-10-28 22:58:05 +00002133 xmlTextMerge(last, new);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002134 }
Daniel Veillard16253641998-10-28 22:58:05 +00002135 }
2136 break;
2137 }
2138 case XML_ATTRIBUTE_NODE:
2139 break;
2140 case XML_TEXT_NODE:
2141 case XML_CDATA_SECTION_NODE:
2142 case XML_ENTITY_REF_NODE:
2143 case XML_ENTITY_NODE:
2144 case XML_PI_NODE:
2145 case XML_COMMENT_NODE:
2146 if (content != NULL)
2147 cur->content = xmlStrncat(cur->content, content, len);
2148 case XML_DOCUMENT_NODE:
2149 case XML_DOCUMENT_TYPE_NODE:
2150 break;
2151 case XML_NOTATION_NODE:
2152 if (content != NULL)
2153 cur->content = xmlStrncat(cur->content, content, len);
2154 break;
2155 }
2156}
2157
2158/**
2159 * xmlNodeAddContent:
2160 * @cur: the node being modified
2161 * @content: extra content
2162 *
2163 * Append the extra substring to the node content.
2164 */
2165void
2166xmlNodeAddContent(xmlNodePtr cur, const CHAR *content) {
2167 int len;
2168
2169 if (cur == NULL) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002170 fprintf(stderr, "xmlNodeAddContent : node == NULL\n");
2171 return;
2172 }
Daniel Veillard16253641998-10-28 22:58:05 +00002173 if (content == NULL) return;
2174 len = xmlStrlen(content);
2175 xmlNodeAddContentLen(cur, content, len);
2176}
2177
2178/**
2179 * xmlTextMerge:
2180 * @first: the first text node
2181 * @second: the second text node being merged
2182 *
2183 * Merge two text nodes into one
Daniel Veillard1e346af1999-02-22 10:33:01 +00002184 * Returns the first text node augmented
Daniel Veillard16253641998-10-28 22:58:05 +00002185 */
2186xmlNodePtr
2187xmlTextMerge(xmlNodePtr first, xmlNodePtr second) {
2188 if (first == NULL) return(second);
2189 if (second == NULL) return(first);
2190 if (first->type != XML_TEXT_NODE) return(first);
2191 if (second->type != XML_TEXT_NODE) return(first);
2192 xmlNodeAddContent(first, second->content);
2193 xmlUnlinkNode(second);
2194 xmlFreeNode(second);
2195 return(first);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002196}
2197
Daniel Veillard97b58771998-10-20 06:14:16 +00002198/**
Daniel Veillardb96e6431999-08-29 21:02:19 +00002199 * xmlGetNsList:
2200 * @doc: the document
2201 * @node: the current node
2202 *
2203 * Search all the namespace applying to a given element.
2204 * Returns an NULL terminated array of all the xmlNsPtr found
2205 * that need to be freed by the caller or NULL if no
2206 * namespace if defined
2207 */
2208xmlNsPtr *
2209xmlGetNsList(xmlDocPtr doc, xmlNodePtr node) {
2210 xmlNsPtr cur;
2211 xmlNsPtr *ret = NULL;
2212 int nbns = 0;
2213 int maxns = 10;
2214 int i;
2215
2216 while (node != NULL) {
2217 cur = node->nsDef;
2218 while (cur != NULL) {
2219 if (ret == NULL) {
Daniel Veillard6454aec1999-09-02 22:04:43 +00002220 ret = (xmlNsPtr *) xmlMalloc((maxns + 1) * sizeof(xmlNsPtr));
Daniel Veillardb96e6431999-08-29 21:02:19 +00002221 if (ret == NULL) {
2222 fprintf(stderr, "xmlGetNsList : out of memory!\n");
2223 return(NULL);
2224 }
2225 ret[nbns] = NULL;
2226 }
2227 for (i = 0;i < nbns;i++) {
2228 if ((cur->prefix == ret[i]->prefix) ||
2229 (!xmlStrcmp(cur->prefix, ret[i]->prefix))) break;
2230 }
2231 if (i >= nbns) {
2232 if (nbns >= maxns) {
2233 maxns *= 2;
Daniel Veillard6454aec1999-09-02 22:04:43 +00002234 ret = (xmlNsPtr *) xmlRealloc(ret,
Daniel Veillardb96e6431999-08-29 21:02:19 +00002235 (maxns + 1) * sizeof(xmlNsPtr));
2236 if (ret == NULL) {
2237 fprintf(stderr, "xmlGetNsList : realloc failed!\n");
2238 return(NULL);
2239 }
2240 }
2241 ret[nbns++] = cur;
2242 ret[nbns] = NULL;
2243 }
2244
2245 cur = cur->next;
2246 }
2247 node = node->parent;
2248 }
2249 return(ret);
2250}
2251
2252/**
Daniel Veillard97b58771998-10-20 06:14:16 +00002253 * xmlSearchNs:
2254 * @doc: the document
2255 * @node: the current node
2256 * @nameSpace: the namespace string
Daniel Veillard260a68f1998-08-13 03:39:55 +00002257 *
Daniel Veillard97b58771998-10-20 06:14:16 +00002258 * Search a Ns registered under a given name space for a document.
2259 * recurse on the parents until it finds the defined namespace
2260 * or return NULL otherwise.
2261 * @nameSpace can be NULL, this is a search for the default namespace.
Daniel Veillard1e346af1999-02-22 10:33:01 +00002262 * Returns the namespace pointer or NULL.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002263 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002264xmlNsPtr
2265xmlSearchNs(xmlDocPtr doc, xmlNodePtr node, const CHAR *nameSpace) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002266 xmlNsPtr cur;
2267
2268 while (node != NULL) {
2269 cur = node->nsDef;
2270 while (cur != NULL) {
2271 if ((cur->prefix == NULL) && (nameSpace == NULL))
2272 return(cur);
2273 if ((cur->prefix != NULL) && (nameSpace != NULL) &&
2274 (!xmlStrcmp(cur->prefix, nameSpace)))
2275 return(cur);
2276 cur = cur->next;
2277 }
2278 node = node->parent;
2279 }
2280 if (doc != NULL) {
2281 cur = doc->oldNs;
2282 while (cur != NULL) {
2283 if ((cur->prefix != NULL) && (nameSpace != NULL) &&
2284 (!xmlStrcmp(cur->prefix, nameSpace)))
2285 return(cur);
2286 cur = cur->next;
2287 }
2288 }
2289 return(NULL);
2290}
2291
Daniel Veillard97b58771998-10-20 06:14:16 +00002292/**
2293 * xmlSearchNsByHref:
2294 * @doc: the document
2295 * @node: the current node
2296 * @href: the namespace value
2297 *
2298 * Search a Ns aliasing a given URI. Recurse on the parents until it finds
2299 * the defined namespace or return NULL otherwise.
Daniel Veillard1e346af1999-02-22 10:33:01 +00002300 * Returns the namespace pointer or NULL.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002301 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002302xmlNsPtr
2303xmlSearchNsByHref(xmlDocPtr doc, xmlNodePtr node, const CHAR *href) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002304 xmlNsPtr cur;
2305
2306 while (node != NULL) {
2307 cur = node->nsDef;
2308 while (cur != NULL) {
2309 if ((cur->href != NULL) && (href != NULL) &&
2310 (!xmlStrcmp(cur->href, href)))
2311 return(cur);
2312 cur = cur->next;
2313 }
2314 node = node->parent;
2315 }
2316 if (doc != NULL) {
2317 cur = doc->oldNs;
2318 while (cur != NULL) {
2319 if ((cur->href != NULL) && (href != NULL) &&
2320 (!xmlStrcmp(cur->href, href)))
2321 return(cur);
2322 cur = cur->next;
2323 }
2324 }
2325 return(NULL);
2326}
2327
Daniel Veillard97b58771998-10-20 06:14:16 +00002328/**
2329 * xmlGetProp:
2330 * @node: the node
2331 * @name: the attribute name
2332 *
2333 * Search and get the value of an attribute associated to a node
Daniel Veillardccb09631998-10-27 06:21:04 +00002334 * This does the entity substitution.
Daniel Veillard1e346af1999-02-22 10:33:01 +00002335 * Returns the attribute value or NULL if not found.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002336 */
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002337CHAR *xmlGetProp(xmlNodePtr node, const CHAR *name) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002338 xmlAttrPtr prop = node->properties;
2339
2340 while (prop != NULL) {
Daniel Veillard68178931999-02-08 18:34:36 +00002341 if (!xmlStrcmp(prop->name, name)) {
Daniel Veillard6800ef31999-02-08 18:33:22 +00002342 CHAR *ret;
2343
2344 ret = xmlNodeListGetString(node->doc, prop->val, 1);
Daniel Veillardb96e6431999-08-29 21:02:19 +00002345 if (ret == NULL) return(xmlStrdup((CHAR *)""));
Daniel Veillard6800ef31999-02-08 18:33:22 +00002346 return(ret);
Daniel Veillard68178931999-02-08 18:34:36 +00002347 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002348 prop = prop->next;
2349 }
2350 return(NULL);
2351}
2352
Daniel Veillard97b58771998-10-20 06:14:16 +00002353/**
Daniel Veillardccb09631998-10-27 06:21:04 +00002354 * xmlSetProp:
Daniel Veillard97b58771998-10-20 06:14:16 +00002355 * @node: the node
2356 * @name: the attribute name
2357 * @value: the attribute value
2358 *
2359 * Set (or reset) an attribute carried by a node.
Daniel Veillard1e346af1999-02-22 10:33:01 +00002360 * Returns the attribute pointer.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002361 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002362xmlAttrPtr
2363xmlSetProp(xmlNodePtr node, const CHAR *name, const CHAR *value) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002364 xmlAttrPtr prop = node->properties;
2365
2366 while (prop != NULL) {
2367 if (!xmlStrcmp(prop->name, name)) {
Daniel Veillardccb09631998-10-27 06:21:04 +00002368 if (prop->val != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +00002369 xmlFreeNodeList(prop->val);
Daniel Veillardccb09631998-10-27 06:21:04 +00002370 prop->val = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002371 if (value != NULL)
Daniel Veillardccb09631998-10-27 06:21:04 +00002372 prop->val = xmlStringGetNodeList(node->doc, value);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002373 return(prop);
2374 }
2375 prop = prop->next;
2376 }
2377 prop = xmlNewProp(node, name, value);
2378 return(prop);
2379}
2380
Daniel Veillard97b58771998-10-20 06:14:16 +00002381/**
2382 * xmlNodeIsText:
2383 * @node: the node
2384 *
2385 * Is this node a Text node ?
Daniel Veillard1e346af1999-02-22 10:33:01 +00002386 * Returns 1 yes, 0 no
Daniel Veillard260a68f1998-08-13 03:39:55 +00002387 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002388int
2389xmlNodeIsText(xmlNodePtr node) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002390 if (node == NULL) return(0);
2391
Daniel Veillard0bef1311998-10-14 02:36:47 +00002392 if (node->type == XML_TEXT_NODE) return(1);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002393 return(0);
2394}
2395
Daniel Veillard97b58771998-10-20 06:14:16 +00002396/**
Daniel Veillard1e346af1999-02-22 10:33:01 +00002397 * xmlTextConcat:
Daniel Veillard97b58771998-10-20 06:14:16 +00002398 * @node: the node
2399 * @content: the content
2400 * @len: @content lenght
2401 *
2402 * Concat the given string at the end of the existing node content
Daniel Veillard260a68f1998-08-13 03:39:55 +00002403 */
Daniel Veillard97b58771998-10-20 06:14:16 +00002404
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002405void
2406xmlTextConcat(xmlNodePtr node, const CHAR *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002407 if (node == NULL) return;
2408
Daniel Veillard0bef1311998-10-14 02:36:47 +00002409 if (node->type != XML_TEXT_NODE) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002410 fprintf(stderr, "xmlTextConcat: node is not text\n");
2411 return;
2412 }
2413 node->content = xmlStrncat(node->content, content, len);
2414}
2415
2416/************************************************************************
2417 * *
2418 * Output : to a FILE or in memory *
2419 * *
2420 ************************************************************************/
2421
Daniel Veillard5099ae81999-04-21 20:12:07 +00002422#define BASE_BUFFER_SIZE 4000
2423
2424/**
2425 * xmlBufferCreate:
2426 *
2427 * routine to create an XML buffer.
2428 * returns the new structure.
2429 */
2430xmlBufferPtr
2431xmlBufferCreate(void) {
2432 xmlBufferPtr ret;
2433
Daniel Veillard6454aec1999-09-02 22:04:43 +00002434 ret = (xmlBufferPtr) xmlMalloc(sizeof(xmlBuffer));
Daniel Veillard5099ae81999-04-21 20:12:07 +00002435 if (ret == NULL) {
2436 fprintf(stderr, "xmlBufferCreate : out of memory!\n");
2437 return(NULL);
2438 }
2439 ret->use = 0;
2440 ret->size = BASE_BUFFER_SIZE;
Daniel Veillard6454aec1999-09-02 22:04:43 +00002441 ret->content = (CHAR *) xmlMalloc(ret->size * sizeof(CHAR));
Daniel Veillard5099ae81999-04-21 20:12:07 +00002442 if (ret->content == NULL) {
2443 fprintf(stderr, "xmlBufferCreate : out of memory!\n");
Daniel Veillard6454aec1999-09-02 22:04:43 +00002444 xmlFree(ret);
Daniel Veillard5099ae81999-04-21 20:12:07 +00002445 return(NULL);
2446 }
2447 ret->content[0] = 0;
2448 return(ret);
2449}
2450
2451/**
2452 * xmlBufferFree:
2453 * @buf: the buffer to free
2454 *
2455 * Frees an XML buffer.
2456 */
2457void
2458xmlBufferFree(xmlBufferPtr buf) {
2459 if (buf == NULL) {
2460 fprintf(stderr, "xmlBufferFree: buf == NULL\n");
2461 return;
2462 }
2463 if (buf->content == NULL) {
2464 fprintf(stderr, "xmlBufferFree: buf->content == NULL\n");
2465 } else {
2466 memset(buf->content, -1, BASE_BUFFER_SIZE);
Daniel Veillard6454aec1999-09-02 22:04:43 +00002467 xmlFree(buf->content);
Daniel Veillard5099ae81999-04-21 20:12:07 +00002468 }
2469 memset(buf, -1, sizeof(xmlBuffer));
Daniel Veillard6454aec1999-09-02 22:04:43 +00002470 xmlFree(buf);
Daniel Veillard5099ae81999-04-21 20:12:07 +00002471}
2472
2473/**
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002474 * xmlBufferEmpty:
2475 * @buf: the buffer
2476 *
2477 * empty a buffer.
2478 */
2479void
2480xmlBufferEmpty(xmlBufferPtr buf) {
2481 buf->use = 0;
2482 memset(buf->content, -1, buf->size);/* just for debug */
2483}
2484
2485/**
2486 * xmlBufferShrink:
2487 * @buf: the buffer to dump
2488 * @len: the number of CHAR to remove
2489 *
2490 * Remove the beginning of an XML buffer.
2491 *
2492 * Returns the number of CHAR removed, or -1 in case of failure.
2493 */
2494int
2495xmlBufferShrink(xmlBufferPtr buf, int len) {
2496 if (len == 0) return(0);
2497 if (len > buf->use) return(-1);
2498
2499 buf->use -= len;
2500 memmove(buf->content, &buf->content[len], buf->use * sizeof(CHAR));
2501
2502 buf->content[buf->use] = 0;
2503 return(len);
2504}
2505
2506/**
Daniel Veillard5099ae81999-04-21 20:12:07 +00002507 * xmlBufferDump:
2508 * @file: the file output
2509 * @buf: the buffer to dump
2510 *
2511 * Dumps an XML buffer to a FILE *.
2512 * Returns the number of CHAR written
2513 */
2514int
2515xmlBufferDump(FILE *file, xmlBufferPtr buf) {
2516 int ret;
2517
2518 if (buf == NULL) {
2519 fprintf(stderr, "xmlBufferDump: buf == NULL\n");
2520 return(0);
2521 }
2522 if (buf->content == NULL) {
2523 fprintf(stderr, "xmlBufferDump: buf->content == NULL\n");
2524 return(0);
2525 }
2526 if (file == NULL) file = stdout;
2527 ret = fwrite(buf->content, sizeof(CHAR), buf->use, file);
2528 return(ret);
2529}
2530
2531/**
2532 * xmlBufferAdd:
2533 * @buf: the buffer to dump
2534 * @str: the CHAR string
2535 * @len: the number of CHAR to add
2536 *
2537 * Add a string range to an XML buffer.
2538 */
2539void
2540xmlBufferAdd(xmlBufferPtr buf, const CHAR *str, int len) {
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002541 int l;
Daniel Veillard5099ae81999-04-21 20:12:07 +00002542
2543 if (str == NULL) {
2544 fprintf(stderr, "xmlBufferAdd: str == NULL\n");
2545 return;
2546 }
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002547 l = xmlStrlen(str);
2548 if (l < len) len = l;
2549 if (len <= 0) return;
Daniel Veillard5099ae81999-04-21 20:12:07 +00002550
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002551 if (buf->use + len + 10 >= buf->size) {
2552 CHAR *rebuf;
2553
2554 buf->size *= 2;
2555 if (buf->use + len + 10 > buf->size)
2556 buf->size = buf->use + len + 10;
Daniel Veillard6454aec1999-09-02 22:04:43 +00002557 rebuf = (CHAR *) xmlRealloc(buf->content, buf->size * sizeof(CHAR));
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002558 if (rebuf == NULL) {
2559 fprintf(stderr, "xmlBufferAdd : out of memory!\n");
2560 return;
Daniel Veillard5099ae81999-04-21 20:12:07 +00002561 }
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002562 buf->content = rebuf;
Daniel Veillard5099ae81999-04-21 20:12:07 +00002563 }
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002564 memmove(&buf->content[buf->use], str, len);
2565 buf->use += len;
2566 buf->content[buf->use] = 0;
Daniel Veillard5099ae81999-04-21 20:12:07 +00002567}
2568
2569/**
2570 * xmlBufferCat:
2571 * @buf: the buffer to dump
2572 * @str: the CHAR string
2573 *
2574 * Append a zero terminated string to an XML buffer.
2575 */
2576void
2577xmlBufferCat(xmlBufferPtr buf, const CHAR *str) {
2578 const CHAR *cur;
2579
2580 if (str == NULL) {
2581 fprintf(stderr, "xmlBufferAdd: str == NULL\n");
2582 return;
2583 }
2584 for (cur = str;*cur != 0;cur++) {
2585 if (buf->use + 10 >= buf->size) {
2586 CHAR *rebuf;
2587
2588 buf->size *= 2;
Daniel Veillard6454aec1999-09-02 22:04:43 +00002589 rebuf = (CHAR *) xmlRealloc(buf->content, buf->size * sizeof(CHAR));
Daniel Veillard5099ae81999-04-21 20:12:07 +00002590 if (rebuf == NULL) {
2591 fprintf(stderr, "xmlBufferAdd : out of memory!\n");
2592 return;
2593 }
2594 buf->content = rebuf;
2595 }
2596 buf->content[buf->use++] = *cur;
2597 }
2598}
2599
2600/**
2601 * xmlBufferCCat:
2602 * @buf: the buffer to dump
2603 * @str: the C char string
2604 *
2605 * Append a zero terminated C string to an XML buffer.
2606 */
2607void
2608xmlBufferCCat(xmlBufferPtr buf, const char *str) {
2609 const char *cur;
2610
2611 if (str == NULL) {
2612 fprintf(stderr, "xmlBufferAdd: str == NULL\n");
2613 return;
2614 }
2615 for (cur = str;*cur != 0;cur++) {
2616 if (buf->use + 10 >= buf->size) {
2617 CHAR *rebuf;
2618
2619 buf->size *= 2;
Daniel Veillard6454aec1999-09-02 22:04:43 +00002620 rebuf = (CHAR *) xmlRealloc(buf->content, buf->size * sizeof(CHAR));
Daniel Veillard5099ae81999-04-21 20:12:07 +00002621 if (rebuf == NULL) {
2622 fprintf(stderr, "xmlBufferAdd : out of memory!\n");
2623 return;
2624 }
2625 buf->content = rebuf;
2626 }
2627 buf->content[buf->use++] = *cur;
2628 }
2629}
Daniel Veillard260a68f1998-08-13 03:39:55 +00002630
Daniel Veillard97b58771998-10-20 06:14:16 +00002631/**
2632 * xmlBufferWriteCHAR:
Daniel Veillard5099ae81999-04-21 20:12:07 +00002633 * @buf: the XML buffer
Daniel Veillard97b58771998-10-20 06:14:16 +00002634 * @string: the string to add
2635 *
2636 * routine which manage and grows an output buffer. This one add
Daniel Veillard5099ae81999-04-21 20:12:07 +00002637 * CHARs at the end of the buffer.
Daniel Veillard97b58771998-10-20 06:14:16 +00002638 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002639void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002640xmlBufferWriteCHAR(xmlBufferPtr buf, const CHAR *string) {
2641 xmlBufferCat(buf, string);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002642}
2643
Daniel Veillard97b58771998-10-20 06:14:16 +00002644/**
2645 * xmlBufferWriteChar:
Daniel Veillard011b63c1999-06-02 17:44:04 +00002646 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00002647 * @string: the string to add
2648 *
2649 * routine which manage and grows an output buffer. This one add
2650 * C chars at the end of the array.
2651 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002652void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002653xmlBufferWriteChar(xmlBufferPtr buf, const char *string) {
2654 xmlBufferCCat(buf, string);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002655}
2656
Daniel Veillard5099ae81999-04-21 20:12:07 +00002657
Daniel Veillard97b58771998-10-20 06:14:16 +00002658/**
Daniel Veillard011b63c1999-06-02 17:44:04 +00002659 * xmlBufferWriteQuotedString:
2660 * @buf: the XML buffer output
2661 * @string: the string to add
2662 *
2663 * routine which manage and grows an output buffer. This one writes
2664 * a quoted or double quoted CHAR string, checking first if it holds
2665 * quote or double-quotes internally
2666 */
2667void
2668xmlBufferWriteQuotedString(xmlBufferPtr buf, const CHAR *string) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00002669 if (xmlStrchr(string, '"')) {
2670 if (xmlStrchr(string, '\'')) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00002671 fprintf(stderr,
2672 "xmlBufferWriteQuotedString: string contains quote and double-quotes !\n");
2673 }
2674 xmlBufferCCat(buf, "'");
2675 xmlBufferCat(buf, string);
2676 xmlBufferCCat(buf, "'");
2677 } else {
2678 xmlBufferCCat(buf, "\"");
2679 xmlBufferCat(buf, string);
2680 xmlBufferCCat(buf, "\"");
2681 }
2682}
2683
2684
2685/**
Daniel Veillard97b58771998-10-20 06:14:16 +00002686 * xmlGlobalNsDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00002687 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00002688 * @cur: a namespace
2689 *
2690 * Dump a global Namespace, this is the old version based on PIs.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002691 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002692static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002693xmlGlobalNsDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002694 if (cur == NULL) {
2695 fprintf(stderr, "xmlGlobalNsDump : Ns == NULL\n");
2696 return;
2697 }
2698 if (cur->type == XML_GLOBAL_NAMESPACE) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002699 xmlBufferWriteChar(buf, "<?namespace");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002700 if (cur->href != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00002701 xmlBufferWriteChar(buf, " href=");
2702 xmlBufferWriteQuotedString(buf, cur->href);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002703 }
2704 if (cur->prefix != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00002705 xmlBufferWriteChar(buf, " AS=");
2706 xmlBufferWriteQuotedString(buf, cur->prefix);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002707 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00002708 xmlBufferWriteChar(buf, "?>\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002709 }
2710}
2711
Daniel Veillard97b58771998-10-20 06:14:16 +00002712/**
2713 * xmlGlobalNsListDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00002714 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00002715 * @cur: the first namespace
2716 *
2717 * Dump a list of global Namespace, this is the old version based on PIs.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002718 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002719static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002720xmlGlobalNsListDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002721 while (cur != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002722 xmlGlobalNsDump(buf, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002723 cur = cur->next;
2724 }
2725}
2726
Daniel Veillard97b58771998-10-20 06:14:16 +00002727/**
2728 * xmlNsDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00002729 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00002730 * @cur: a namespace
2731 *
Daniel Veillard260a68f1998-08-13 03:39:55 +00002732 * Dump a local Namespace definition.
Daniel Veillard97b58771998-10-20 06:14:16 +00002733 * Should be called in the context of attributes dumps.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002734 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002735static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002736xmlNsDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002737 if (cur == NULL) {
2738 fprintf(stderr, "xmlNsDump : Ns == NULL\n");
2739 return;
2740 }
2741 if (cur->type == XML_LOCAL_NAMESPACE) {
2742 /* Within the context of an element attributes */
2743 if (cur->prefix != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002744 xmlBufferWriteChar(buf, " xmlns:");
2745 xmlBufferWriteCHAR(buf, cur->prefix);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002746 } else
Daniel Veillard5099ae81999-04-21 20:12:07 +00002747 xmlBufferWriteChar(buf, " xmlns");
Daniel Veillard011b63c1999-06-02 17:44:04 +00002748 xmlBufferWriteChar(buf, "=");
2749 xmlBufferWriteQuotedString(buf, cur->href);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002750 }
2751}
2752
Daniel Veillard97b58771998-10-20 06:14:16 +00002753/**
2754 * xmlNsListDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00002755 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00002756 * @cur: the first namespace
2757 *
2758 * Dump a list of local Namespace definitions.
2759 * Should be called in the context of attributes dumps.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002760 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002761static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002762xmlNsListDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002763 while (cur != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002764 xmlNsDump(buf, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002765 cur = cur->next;
2766 }
2767}
2768
Daniel Veillard97b58771998-10-20 06:14:16 +00002769/**
2770 * xmlDtdDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00002771 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00002772 * @doc: the document
2773 *
2774 * Dump the XML document DTD, if any.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002775 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002776static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002777xmlDtdDump(xmlBufferPtr buf, xmlDocPtr doc) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002778 xmlDtdPtr cur = doc->intSubset;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002779
2780 if (cur == NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002781 fprintf(stderr, "xmlDtdDump : no internal subset\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002782 return;
2783 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00002784 xmlBufferWriteChar(buf, "<!DOCTYPE ");
2785 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002786 if (cur->ExternalID != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00002787 xmlBufferWriteChar(buf, " PUBLIC ");
2788 xmlBufferWriteQuotedString(buf, cur->ExternalID);
2789 xmlBufferWriteChar(buf, " ");
2790 xmlBufferWriteQuotedString(buf, cur->SystemID);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002791 } else if (cur->SystemID != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00002792 xmlBufferWriteChar(buf, " SYSTEM ");
2793 xmlBufferWriteQuotedString(buf, cur->SystemID);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002794 }
Daniel Veillard1e346af1999-02-22 10:33:01 +00002795 if ((cur->entities == NULL) && (cur->elements == NULL) &&
2796 (cur->attributes == NULL) && (cur->notations == NULL)) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002797 xmlBufferWriteChar(buf, ">\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002798 return;
2799 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00002800 xmlBufferWriteChar(buf, " [\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002801 if (cur->entities != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00002802 xmlDumpEntitiesTable(buf, (xmlEntitiesTablePtr) cur->entities);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002803 if (cur->notations != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00002804 xmlDumpNotationTable(buf, (xmlNotationTablePtr) cur->notations);
Daniel Veillard3b9def11999-01-31 22:15:06 +00002805 if (cur->elements != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00002806 xmlDumpElementTable(buf, (xmlElementTablePtr) cur->elements);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002807 if (cur->attributes != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00002808 xmlDumpAttributeTable(buf, (xmlAttributeTablePtr) cur->attributes);
2809 xmlBufferWriteChar(buf, "]");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002810
Daniel Veillard5099ae81999-04-21 20:12:07 +00002811 xmlBufferWriteChar(buf, ">\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002812}
2813
Daniel Veillard97b58771998-10-20 06:14:16 +00002814/**
2815 * xmlAttrDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00002816 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00002817 * @doc: the document
2818 * @cur: the attribute pointer
2819 *
2820 * Dump an XML attribute
Daniel Veillard260a68f1998-08-13 03:39:55 +00002821 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002822static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002823xmlAttrDump(xmlBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur) {
Daniel Veillardccb09631998-10-27 06:21:04 +00002824 CHAR *value;
2825
Daniel Veillard260a68f1998-08-13 03:39:55 +00002826 if (cur == NULL) {
2827 fprintf(stderr, "xmlAttrDump : property == NULL\n");
2828 return;
2829 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00002830 xmlBufferWriteChar(buf, " ");
Daniel Veillardb96e6431999-08-29 21:02:19 +00002831 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
2832 xmlBufferWriteCHAR(buf, cur->ns->prefix);
2833 xmlBufferWriteChar(buf, ":");
2834 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00002835 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillardccb09631998-10-27 06:21:04 +00002836 value = xmlNodeListGetString(doc, cur->val, 0);
2837 if (value) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00002838 xmlBufferWriteChar(buf, "=");
2839 xmlBufferWriteQuotedString(buf, value);
Daniel Veillard6454aec1999-09-02 22:04:43 +00002840 xmlFree(value);
Daniel Veillard726c7e31999-02-08 15:13:10 +00002841 } else {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002842 xmlBufferWriteChar(buf, "=\"\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002843 }
2844}
2845
Daniel Veillard97b58771998-10-20 06:14:16 +00002846/**
2847 * xmlAttrListDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00002848 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00002849 * @doc: the document
2850 * @cur: the first attribute pointer
2851 *
2852 * Dump a list of XML attributes
Daniel Veillard260a68f1998-08-13 03:39:55 +00002853 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002854static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002855xmlAttrListDump(xmlBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002856 if (cur == NULL) {
2857 fprintf(stderr, "xmlAttrListDump : property == NULL\n");
2858 return;
2859 }
2860 while (cur != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002861 xmlAttrDump(buf, doc, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002862 cur = cur->next;
2863 }
2864}
2865
Daniel Veillard260a68f1998-08-13 03:39:55 +00002866
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002867static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002868xmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level);
Daniel Veillard97b58771998-10-20 06:14:16 +00002869/**
2870 * xmlNodeListDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00002871 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00002872 * @doc: the document
2873 * @cur: the first node
2874 * @level: the imbrication level for indenting
2875 *
2876 * Dump an XML node list, recursive behaviour,children are printed too.
2877 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002878static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002879xmlNodeListDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level) {
Daniel Veillardccb09631998-10-27 06:21:04 +00002880 int needIndent = 0, i;
2881
Daniel Veillard260a68f1998-08-13 03:39:55 +00002882 if (cur == NULL) {
2883 fprintf(stderr, "xmlNodeListDump : node == NULL\n");
2884 return;
2885 }
2886 while (cur != NULL) {
Daniel Veillardccb09631998-10-27 06:21:04 +00002887 if ((cur->type != XML_TEXT_NODE) &&
2888 (cur->type != XML_ENTITY_REF_NODE)) {
2889 if (!needIndent) {
2890 needIndent = 1;
Daniel Veillard5099ae81999-04-21 20:12:07 +00002891 xmlBufferWriteChar(buf, "\n");
Daniel Veillardccb09631998-10-27 06:21:04 +00002892 }
2893 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00002894 xmlNodeDump(buf, doc, cur, level);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002895 cur = cur->next;
2896 }
Daniel Veillardccb09631998-10-27 06:21:04 +00002897 if ((xmlIndentTreeOutput) && (needIndent))
2898 for (i = 1;i < level;i++)
Daniel Veillard5099ae81999-04-21 20:12:07 +00002899 xmlBufferWriteChar(buf, " ");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002900}
2901
Daniel Veillard97b58771998-10-20 06:14:16 +00002902/**
Daniel Veillardccb09631998-10-27 06:21:04 +00002903 * xmlNodeDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00002904 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00002905 * @doc: the document
2906 * @cur: the current node
2907 * @level: the imbrication level for indenting
2908 *
2909 * Dump an XML node, recursive behaviour,children are printed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002910 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002911static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002912xmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002913 int i;
2914
2915 if (cur == NULL) {
2916 fprintf(stderr, "xmlNodeDump : node == NULL\n");
2917 return;
2918 }
Daniel Veillard0bef1311998-10-14 02:36:47 +00002919 if (cur->type == XML_TEXT_NODE) {
Daniel Veillard14fff061999-06-22 21:49:07 +00002920 if (cur->content != NULL) {
2921 CHAR *buffer;
2922
2923 buffer = xmlEncodeEntitiesReentrant(doc, cur->content);
2924 if (buffer != NULL) {
2925 xmlBufferWriteCHAR(buf, buffer);
Daniel Veillard6454aec1999-09-02 22:04:43 +00002926 xmlFree(buffer);
Daniel Veillard14fff061999-06-22 21:49:07 +00002927 }
2928 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002929 return;
2930 }
Daniel Veillardb96e6431999-08-29 21:02:19 +00002931 if (cur->type == XML_PI_NODE) {
2932 if (cur->content != NULL) {
2933 xmlBufferWriteChar(buf, "<?");
2934 xmlBufferWriteCHAR(buf, cur->name);
2935 if (cur->content != NULL) {
2936 xmlBufferWriteChar(buf, " ");
2937 xmlBufferWriteCHAR(buf, cur->content);
2938 }
2939 xmlBufferWriteChar(buf, "?>\n");
2940 }
2941 return;
2942 }
Daniel Veillard0bef1311998-10-14 02:36:47 +00002943 if (cur->type == XML_COMMENT_NODE) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002944 if (cur->content != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002945 xmlBufferWriteChar(buf, "<!--");
2946 xmlBufferWriteCHAR(buf, cur->content);
Daniel Veillardb96e6431999-08-29 21:02:19 +00002947 xmlBufferWriteChar(buf, "-->\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002948 }
2949 return;
2950 }
Daniel Veillardccb09631998-10-27 06:21:04 +00002951 if (cur->type == XML_ENTITY_REF_NODE) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002952 xmlBufferWriteChar(buf, "&");
2953 xmlBufferWriteCHAR(buf, cur->name);
2954 xmlBufferWriteChar(buf, ";");
Daniel Veillardccb09631998-10-27 06:21:04 +00002955 return;
2956 }
Daniel Veillardb05deb71999-08-10 19:04:08 +00002957 if (cur->type == XML_CDATA_SECTION_NODE) {
2958 xmlBufferWriteChar(buf, "<![CDATA[");
2959 if (cur->content != NULL)
2960 xmlBufferWriteCHAR(buf, cur->content);
2961 xmlBufferWriteChar(buf, "]]>");
2962 return;
2963 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002964 if (xmlIndentTreeOutput)
2965 for (i = 0;i < level;i++)
Daniel Veillard5099ae81999-04-21 20:12:07 +00002966 xmlBufferWriteChar(buf, " ");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002967
Daniel Veillard5099ae81999-04-21 20:12:07 +00002968 xmlBufferWriteChar(buf, "<");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002969 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002970 xmlBufferWriteCHAR(buf, cur->ns->prefix);
2971 xmlBufferWriteChar(buf, ":");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002972 }
2973
Daniel Veillard5099ae81999-04-21 20:12:07 +00002974 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002975 if (cur->nsDef)
Daniel Veillard5099ae81999-04-21 20:12:07 +00002976 xmlNsListDump(buf, cur->nsDef);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002977 if (cur->properties != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00002978 xmlAttrListDump(buf, doc, cur->properties);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002979
2980 if ((cur->content == NULL) && (cur->childs == NULL)) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002981 xmlBufferWriteChar(buf, "/>\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002982 return;
2983 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00002984 xmlBufferWriteChar(buf, ">");
Daniel Veillard14fff061999-06-22 21:49:07 +00002985 if (cur->content != NULL) {
2986 CHAR *buffer;
2987
2988 buffer = xmlEncodeEntitiesReentrant(doc, cur->content);
2989 if (buffer != NULL) {
2990 xmlBufferWriteCHAR(buf, buffer);
Daniel Veillard6454aec1999-09-02 22:04:43 +00002991 xmlFree(buffer);
Daniel Veillard14fff061999-06-22 21:49:07 +00002992 }
2993 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002994 if (cur->childs != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002995 xmlNodeListDump(buf, doc, cur->childs, level + 1);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002996 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00002997 xmlBufferWriteChar(buf, "</");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002998 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002999 xmlBufferWriteCHAR(buf, cur->ns->prefix);
3000 xmlBufferWriteChar(buf, ":");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003001 }
3002
Daniel Veillard5099ae81999-04-21 20:12:07 +00003003 xmlBufferWriteCHAR(buf, cur->name);
3004 xmlBufferWriteChar(buf, ">\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003005}
3006
Daniel Veillard97b58771998-10-20 06:14:16 +00003007/**
3008 * xmlDocContentDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003009 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003010 * @cur: the document
3011 *
3012 * Dump an XML document.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003013 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003014static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00003015xmlDocContentDump(xmlBufferPtr buf, xmlDocPtr cur) {
Daniel Veillardbe70ff71999-07-05 16:50:46 +00003016 xmlBufferWriteChar(buf, "<?xml version=");
3017 if (cur->version != NULL)
3018 xmlBufferWriteQuotedString(buf, cur->version);
3019 else
3020 xmlBufferWriteChar(buf, "\"1.0\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003021 if (cur->encoding != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00003022 xmlBufferWriteChar(buf, " encoding=");
3023 xmlBufferWriteQuotedString(buf, cur->encoding);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003024 }
3025 switch (cur->standalone) {
3026 case 0:
Daniel Veillard5099ae81999-04-21 20:12:07 +00003027 xmlBufferWriteChar(buf, " standalone=\"no\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003028 break;
3029 case 1:
Daniel Veillard5099ae81999-04-21 20:12:07 +00003030 xmlBufferWriteChar(buf, " standalone=\"yes\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003031 break;
3032 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003033 xmlBufferWriteChar(buf, "?>\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003034 if (cur->intSubset != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00003035 xmlDtdDump(buf, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003036 if (cur->root != NULL) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00003037 xmlNodePtr child = cur->root;
3038
Daniel Veillard260a68f1998-08-13 03:39:55 +00003039 /* global namespace definitions, the old way */
3040 if (oldXMLWDcompatibility)
Daniel Veillard5099ae81999-04-21 20:12:07 +00003041 xmlGlobalNsListDump(buf, cur->oldNs);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003042 else
3043 xmlUpgradeOldNs(cur);
Daniel Veillardb96e6431999-08-29 21:02:19 +00003044
3045 while (child != NULL) {
3046 xmlNodeDump(buf, cur, child, 0);
3047 child = child->next;
3048 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003049 }
3050}
3051
Daniel Veillard97b58771998-10-20 06:14:16 +00003052/**
3053 * xmlDocDumpMemory:
3054 * @cur: the document
3055 * @mem: OUT: the memory pointer
3056 * @size: OUT: the memory lenght
3057 *
3058 * Dump an XML document in memory and return the CHAR * and it's size.
3059 * It's up to the caller to free the memory.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003060 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003061void
3062xmlDocDumpMemory(xmlDocPtr cur, CHAR**mem, int *size) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003063 xmlBufferPtr buf;
3064
Daniel Veillard260a68f1998-08-13 03:39:55 +00003065 if (cur == NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003066#ifdef DEBUG_TREE
3067 fprintf(stderr, "xmlDocDumpMemory : document == NULL\n");
3068#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00003069 *mem = NULL;
3070 *size = 0;
3071 return;
3072 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003073 buf = xmlBufferCreate();
3074 if (buf == NULL) {
3075 *mem = NULL;
3076 *size = 0;
3077 return;
3078 }
3079 xmlDocContentDump(buf, cur);
Daniel Veillardb05deb71999-08-10 19:04:08 +00003080 *mem = xmlStrndup(buf->content, buf->use);
Daniel Veillard5099ae81999-04-21 20:12:07 +00003081 *size = buf->use;
Daniel Veillardb05deb71999-08-10 19:04:08 +00003082 xmlBufferFree(buf);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003083}
3084
Daniel Veillard97b58771998-10-20 06:14:16 +00003085/**
3086 * xmlGetDocCompressMode:
3087 * @doc: the document
3088 *
3089 * get the compression ratio for a document, ZLIB based
Daniel Veillard1e346af1999-02-22 10:33:01 +00003090 * Returns 0 (uncompressed) to 9 (max compression)
Daniel Veillard151b1b01998-09-23 00:49:46 +00003091 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003092int
3093 xmlGetDocCompressMode (xmlDocPtr doc) {
Daniel Veillard15a8df41998-09-24 19:15:06 +00003094 if (doc == NULL) return(-1);
3095 return(doc->compression);
3096}
3097
Daniel Veillard97b58771998-10-20 06:14:16 +00003098/**
3099 * xmlSetDocCompressMode:
3100 * @doc: the document
3101 * @mode: the compression ratio
3102 *
3103 * set the compression ratio for a document, ZLIB based
3104 * Correct values: 0 (uncompressed) to 9 (max compression)
3105 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003106void
3107xmlSetDocCompressMode (xmlDocPtr doc, int mode) {
Daniel Veillard15a8df41998-09-24 19:15:06 +00003108 if (doc == NULL) return;
3109 if (mode < 0) doc->compression = 0;
3110 else if (mode > 9) doc->compression = 9;
3111 else doc->compression = mode;
3112}
3113
Daniel Veillard97b58771998-10-20 06:14:16 +00003114/**
3115 * xmlGetCompressMode:
3116 *
3117 * get the default compression mode used, ZLIB based.
Daniel Veillard1e346af1999-02-22 10:33:01 +00003118 * Returns 0 (uncompressed) to 9 (max compression)
Daniel Veillard15a8df41998-09-24 19:15:06 +00003119 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003120int
3121 xmlGetCompressMode(void) {
Daniel Veillard151b1b01998-09-23 00:49:46 +00003122 return(xmlCompressMode);
3123}
Daniel Veillard97b58771998-10-20 06:14:16 +00003124
3125/**
3126 * xmlSetCompressMode:
3127 * @mode: the compression ratio
3128 *
3129 * set the default compression mode used, ZLIB based
3130 * Correct values: 0 (uncompressed) to 9 (max compression)
3131 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003132void
3133xmlSetCompressMode(int mode) {
Daniel Veillard151b1b01998-09-23 00:49:46 +00003134 if (mode < 0) xmlCompressMode = 0;
Daniel Veillard15a8df41998-09-24 19:15:06 +00003135 else if (mode > 9) xmlCompressMode = 9;
Daniel Veillard151b1b01998-09-23 00:49:46 +00003136 else xmlCompressMode = mode;
3137}
3138
Daniel Veillard97b58771998-10-20 06:14:16 +00003139/**
3140 * xmlDocDump:
3141 * @f: the FILE*
3142 * @cur: the document
3143 *
3144 * Dump an XML document to an open FILE.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003145 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003146void
3147xmlDocDump(FILE *f, xmlDocPtr cur) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003148 xmlBufferPtr buf;
3149
Daniel Veillard260a68f1998-08-13 03:39:55 +00003150 if (cur == NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003151#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00003152 fprintf(stderr, "xmlDocDump : document == NULL\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003153#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00003154 return;
3155 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003156 buf = xmlBufferCreate();
3157 if (buf == NULL) return;
3158 xmlDocContentDump(buf, cur);
3159 xmlBufferDump(f, buf);
3160 xmlBufferFree(buf);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003161}
3162
Daniel Veillard97b58771998-10-20 06:14:16 +00003163/**
3164 * xmlSaveFile:
3165 * @filename: the filename
3166 * @cur: the document
3167 *
3168 * Dump an XML document to a file. Will use compression if
3169 * compiled in and enabled.
3170 * returns: the number of file written or -1 in case of failure.
Daniel Veillard151b1b01998-09-23 00:49:46 +00003171 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003172int
3173xmlSaveFile(const char *filename, xmlDocPtr cur) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003174 xmlBufferPtr buf;
Daniel Veillard151b1b01998-09-23 00:49:46 +00003175#ifdef HAVE_ZLIB_H
3176 gzFile zoutput = NULL;
3177 char mode[15];
3178#endif
Daniel Veillardccb09631998-10-27 06:21:04 +00003179 FILE *output = NULL;
Daniel Veillard151b1b01998-09-23 00:49:46 +00003180 int ret;
3181
Daniel Veillard5099ae81999-04-21 20:12:07 +00003182 /*
3183 * save the content to a temp buffer.
3184 */
3185 buf = xmlBufferCreate();
3186 if (buf == NULL) return(0);
3187 xmlDocContentDump(buf, cur);
3188
Daniel Veillard151b1b01998-09-23 00:49:46 +00003189#ifdef HAVE_ZLIB_H
Daniel Veillarddc3dd9d1998-09-24 19:25:54 +00003190 if ((cur->compression > 0) && (cur->compression <= 9)) {
3191 sprintf(mode, "w%d", cur->compression);
Daniel Veillard151b1b01998-09-23 00:49:46 +00003192 zoutput = gzopen(filename, mode);
3193 }
3194 if (zoutput == NULL) {
3195#endif
3196 output = fopen(filename, "w");
3197 if (output == NULL) return(-1);
3198#ifdef HAVE_ZLIB_H
3199 }
Daniel Veillard151b1b01998-09-23 00:49:46 +00003200
Daniel Veillard151b1b01998-09-23 00:49:46 +00003201 if (zoutput != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003202 ret = gzwrite(zoutput, buf->content, sizeof(CHAR) * buf->use);
Daniel Veillard151b1b01998-09-23 00:49:46 +00003203 gzclose(zoutput);
Daniel Veillard5099ae81999-04-21 20:12:07 +00003204 } else {
3205#endif
3206 ret = xmlBufferDump(output, buf);
3207 fclose(output);
3208#ifdef HAVE_ZLIB_H
Daniel Veillard151b1b01998-09-23 00:49:46 +00003209 }
3210#endif
Manish Vachharajani5e60f5a1999-05-29 03:04:30 +00003211 xmlBufferFree(buf);
Daniel Veillard151b1b01998-09-23 00:49:46 +00003212 return(ret * sizeof(CHAR));
3213}
3214