blob: 825177524c519f489157f412f380cdd70eb267da [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 *
6 * $Id$
7 *
8 * TODO Cleanup the Dump mechanism.
9 */
10
Daniel Veillard151b1b01998-09-23 00:49:46 +000011#include "config.h"
Daniel Veillard260a68f1998-08-13 03:39:55 +000012#include <stdio.h>
13#include <ctype.h>
Seth Alvese7f12e61998-10-01 20:51:15 +000014#include <stdlib.h>
Daniel Veillard260a68f1998-08-13 03:39:55 +000015#include <string.h> /* for memset() only ! */
16
Daniel Veillard151b1b01998-09-23 00:49:46 +000017#ifdef HAVE_ZLIB_H
18#include <zlib.h>
19#endif
20
Daniel Veillard260a68f1998-08-13 03:39:55 +000021#include "tree.h"
22#include "entities.h"
23
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 Veillard260a68f1998-08-13 03:39:55 +000030/************************************************************************
31 * *
32 * Allocation and deallocation of basic structures *
33 * *
34 ************************************************************************/
35
Daniel Veillard97b58771998-10-20 06:14:16 +000036/**
37 * xmlUpgradeOldNs:
38 * @doc: a document pointer
39 *
40 * Upgrade old style Namespaces (PI) and move them to the root of the document.
Daniel Veillard260a68f1998-08-13 03:39:55 +000041 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +000042void
43xmlUpgradeOldNs(xmlDocPtr doc) {
Daniel Veillard260a68f1998-08-13 03:39:55 +000044 xmlNsPtr cur;
45
46 if ((doc == NULL) || (doc->oldNs == NULL)) return;
47 if (doc->root == NULL) {
48 fprintf(stderr, "xmlUpgradeOldNs: failed no root !\n");
49 return;
50 }
51
52 cur = doc->oldNs;
53 while (cur->next != NULL) {
54 cur->type = XML_LOCAL_NAMESPACE;
55 cur = cur->next;
56 }
57 cur->type = XML_LOCAL_NAMESPACE;
58 cur->next = doc->root->nsDef;
59 doc->root->nsDef = doc->oldNs;
60 doc->oldNs = NULL;
61}
62
Daniel Veillard97b58771998-10-20 06:14:16 +000063/**
64 * xmlNewNs:
65 * @node: the element carrying the namespace
66 * @href: the URI associated
67 * @prefix: the prefix for the namespace
68 *
Daniel Veillard260a68f1998-08-13 03:39:55 +000069 * Creation of a new Namespace.
Daniel Veillard97b58771998-10-20 06:14:16 +000070 * return values: returns a new namespace pointer
Daniel Veillard260a68f1998-08-13 03:39:55 +000071 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +000072xmlNsPtr
73xmlNewNs(xmlNodePtr node, const CHAR *href, const CHAR *prefix) {
Daniel Veillard260a68f1998-08-13 03:39:55 +000074 xmlNsPtr cur;
75
76 if (href == NULL) {
77 fprintf(stderr, "xmlNewNs: href == NULL !\n");
78 return(NULL);
79 }
80
81 /*
82 * Allocate a new DTD and fill the fields.
83 */
84 cur = (xmlNsPtr) malloc(sizeof(xmlNs));
85 if (cur == NULL) {
86 fprintf(stderr, "xmlNewNs : malloc failed\n");
87 return(NULL);
88 }
89
90 cur->type = XML_LOCAL_NAMESPACE;
91 if (href != NULL)
92 cur->href = xmlStrdup(href);
93 else
94 cur->href = NULL;
95 if (prefix != NULL)
96 cur->prefix = xmlStrdup(prefix);
97 else
98 cur->prefix = NULL;
99
100 /*
101 * Add it at the end to preserve parsing order ...
102 */
103 cur->next = NULL;
104 if (node != NULL) {
105 if (node->nsDef == NULL) {
106 node->nsDef = cur;
107 } else {
108 xmlNsPtr prev = node->nsDef;
109
110 while (prev->next != NULL) prev = prev->next;
111 prev->next = cur;
112 }
113 }
114
115 return(cur);
116}
117
Daniel Veillard97b58771998-10-20 06:14:16 +0000118/**
119 * xmlNewGlobalNs:
120 * @doc: the document carrying the namespace
121 * @href: the URI associated
122 * @prefix: the prefix for the namespace
123 *
124 * Creation of a Namespace, the old way using PI and without scoping, to AVOID.
125 * return values: returns a new namespace pointer
Daniel Veillard260a68f1998-08-13 03:39:55 +0000126 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000127xmlNsPtr
128xmlNewGlobalNs(xmlDocPtr doc, const CHAR *href, const CHAR *prefix) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000129 xmlNsPtr cur;
130
131 /*
132 * Allocate a new DTD and fill the fields.
133 */
134 cur = (xmlNsPtr) malloc(sizeof(xmlNs));
135 if (cur == NULL) {
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000136 fprintf(stderr, "xmlNewGlobalNs : malloc failed\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +0000137 return(NULL);
138 }
139
140 cur->type = XML_GLOBAL_NAMESPACE;
141 if (href != NULL)
142 cur->href = xmlStrdup(href);
143 else
144 cur->href = NULL;
145 if (prefix != NULL)
146 cur->prefix = xmlStrdup(prefix);
147 else
148 cur->prefix = NULL;
149
150 /*
151 * Add it at the end to preserve parsing order ...
152 */
153 cur->next = NULL;
154 if (doc != NULL) {
155 if (doc->oldNs == NULL) {
156 doc->oldNs = cur;
157 } else {
158 xmlNsPtr prev = doc->oldNs;
159
160 while (prev->next != NULL) prev = prev->next;
161 prev->next = cur;
162 }
163 }
164
165 return(cur);
166}
167
Daniel Veillard97b58771998-10-20 06:14:16 +0000168/**
169 * xmlSetNs:
170 * @node: a node in the document
171 * @ns: a namespace pointer
172 *
173 * Associate a namespace to a node, a posteriori.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000174 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000175void
176xmlSetNs(xmlNodePtr node, xmlNsPtr ns) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000177 if (node == NULL) {
178 fprintf(stderr, "xmlSetNs: node == NULL\n");
179 return;
180 }
181 node->ns = ns;
182}
183
Daniel Veillard97b58771998-10-20 06:14:16 +0000184/**
185 * xmlFreeNs:
186 * @cur: the namespace pointer
187 *
188 * Free up the structures associated to a namespace
Daniel Veillard260a68f1998-08-13 03:39:55 +0000189 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000190void
191xmlFreeNs(xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000192 if (cur == NULL) {
193 fprintf(stderr, "xmlFreeNs : ns == NULL\n");
194 return;
195 }
196 if (cur->href != NULL) free((char *) cur->href);
197 if (cur->prefix != NULL) free((char *) cur->prefix);
198 memset(cur, -1, sizeof(xmlNs));
199 free(cur);
200}
201
Daniel Veillard97b58771998-10-20 06:14:16 +0000202/**
203 * xmlFreeNsList:
204 * @cur: the first namespace pointer
205 *
206 * Free up all the structures associated to the chained namespaces.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000207 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000208void
209xmlFreeNsList(xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000210 xmlNsPtr next;
211 if (cur == NULL) {
212 fprintf(stderr, "xmlFreeNsList : ns == NULL\n");
213 return;
214 }
215 while (cur != NULL) {
216 next = cur->next;
217 xmlFreeNs(cur);
218 cur = next;
219 }
220}
221
Daniel Veillard97b58771998-10-20 06:14:16 +0000222/**
223 * xmlNewDtd:
224 * @doc: the document pointer
225 * @name: the DTD name
226 * @ExternalID: the external ID
227 * @SystemID: the system ID
228 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000229 * Creation of a new DTD.
Daniel Veillard97b58771998-10-20 06:14:16 +0000230 * return values: a pointer to the new DTD structure
Daniel Veillard260a68f1998-08-13 03:39:55 +0000231 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000232xmlDtdPtr
233xmlNewDtd(xmlDocPtr doc, const CHAR *name,
Daniel Veillard260a68f1998-08-13 03:39:55 +0000234 const CHAR *ExternalID, const CHAR *SystemID) {
235 xmlDtdPtr cur;
236
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000237 if ((doc != NULL) && (doc->dtd != NULL)) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000238 fprintf(stderr, "xmlNewDtd(%s): document %s already have a DTD %s\n",
239 /* !!! */ (char *) name, doc->name, /* !!! */ (char *)doc->dtd->name);
240 }
241
242 /*
243 * Allocate a new DTD and fill the fields.
244 */
245 cur = (xmlDtdPtr) malloc(sizeof(xmlDtd));
246 if (cur == NULL) {
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000247 fprintf(stderr, "xmlNewDtd : malloc failed\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +0000248 return(NULL);
249 }
250
251 if (name != NULL)
252 cur->name = xmlStrdup(name);
253 else
254 cur->name = NULL;
255 if (ExternalID != NULL)
256 cur->ExternalID = xmlStrdup(ExternalID);
257 else
258 cur->ExternalID = NULL;
259 if (SystemID != NULL)
260 cur->SystemID = xmlStrdup(SystemID);
261 else
262 cur->SystemID = NULL;
263 cur->elements = NULL;
264 cur->entities = NULL;
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000265 if (doc != NULL)
266 doc->dtd = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000267
268 return(cur);
269}
270
Daniel Veillard97b58771998-10-20 06:14:16 +0000271/**
272 * xmlFreeDtd:
273 * @cur: the DTD structure to free up
274 *
275 * Free a DTD structure.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000276 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000277void
278xmlFreeDtd(xmlDtdPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000279 if (cur == NULL) {
280 fprintf(stderr, "xmlFreeDtd : DTD == NULL\n");
281 return;
282 }
283 if (cur->name != NULL) free((char *) cur->name);
284 if (cur->SystemID != NULL) free((char *) cur->SystemID);
285 if (cur->ExternalID != NULL) free((char *) cur->ExternalID);
286 if (cur->elements != NULL)
287 fprintf(stderr, "xmlFreeDtd: cur->elements != NULL !!! \n");
288 if (cur->entities != NULL)
289 xmlFreeEntitiesTable((xmlEntitiesTablePtr) cur->entities);
290 memset(cur, -1, sizeof(xmlDtd));
291 free(cur);
292}
293
Daniel Veillard97b58771998-10-20 06:14:16 +0000294/**
295 * xmlNewDoc:
296 * @version: CHAR string giving the version of XML "1.0"
297 *
298 * Create a new document
Daniel Veillard260a68f1998-08-13 03:39:55 +0000299 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000300xmlDocPtr
301xmlNewDoc(const CHAR *version) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000302 xmlDocPtr cur;
303
304 if (version == NULL) {
305 fprintf(stderr, "xmlNewDoc : version == NULL\n");
306 return(NULL);
307 }
308
309 /*
310 * Allocate a new document and fill the fields.
311 */
312 cur = (xmlDocPtr) malloc(sizeof(xmlDoc));
313 if (cur == NULL) {
314 fprintf(stderr, "xmlNewDoc : malloc failed\n");
315 return(NULL);
316 }
317
Daniel Veillard33942841998-10-18 19:12:41 +0000318 cur->type = XML_DOCUMENT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000319 cur->version = xmlStrdup(version);
320 cur->name = NULL;
321 cur->root = NULL;
322 cur->dtd = NULL;
323 cur->oldNs = NULL;
324 cur->encoding = NULL;
325 cur->entities = NULL;
326 cur->standalone = -1;
Daniel Veillard15a8df41998-09-24 19:15:06 +0000327 cur->compression = xmlCompressMode;
Daniel Veillard27fb0751998-10-17 06:47:46 +0000328#ifndef WITHOUT_CORBA
329 cur->_private = NULL;
330 cur->vepv = NULL;
331#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000332 return(cur);
333}
334
Daniel Veillard97b58771998-10-20 06:14:16 +0000335/**
336 * xmlFreeDoc:
337 * @cur: pointer to the document
338 * @:
339 *
340 * Free up all the structures used by a document, tree included.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000341 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000342void
343xmlFreeDoc(xmlDocPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000344 if (cur == NULL) {
345 fprintf(stderr, "xmlFreeDoc : document == NULL\n");
346 return;
347 }
348 free((char *) cur->version);
349 if (cur->name != NULL) free((char *) cur->name);
350 if (cur->encoding != NULL) free((char *) cur->encoding);
351 if (cur->root != NULL) xmlFreeNode(cur->root);
352 if (cur->dtd != NULL) xmlFreeDtd(cur->dtd);
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000353 if (cur->oldNs != NULL) xmlFreeNsList(cur->oldNs);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000354 if (cur->entities != NULL)
355 xmlFreeEntitiesTable((xmlEntitiesTablePtr) cur->entities);
356 memset(cur, -1, sizeof(xmlDoc));
357 free(cur);
358}
359
Daniel Veillard97b58771998-10-20 06:14:16 +0000360/**
Daniel Veillard16253641998-10-28 22:58:05 +0000361 * xmlStringLenGetNodeList:
362 * @doc: the document
363 * @value: the value of the text
364 * @int len: the length of the string value
365 *
366 * Parse the value string and build the node list associated. Should
367 * produce a flat tree with only TEXTs and ENTITY_REFs.
368 * return values: a pointer to the first child
369 */
370xmlNodePtr
371xmlStringLenGetNodeList(xmlDocPtr doc, const CHAR *value, int len) {
372 xmlNodePtr ret = NULL, last = NULL;
373 xmlNodePtr node;
374 CHAR *val;
375 const CHAR *cur = value;
376 const CHAR *q;
Daniel Veillard25940b71998-10-29 05:51:30 +0000377 xmlEntityPtr ent;
Daniel Veillard16253641998-10-28 22:58:05 +0000378
379 if (value == NULL) return(NULL);
380
381 q = cur;
382 while ((*cur != 0) && (cur - value < len)) {
383 if (*cur == '&') {
Daniel Veillard25940b71998-10-29 05:51:30 +0000384 /*
385 * Save the current text.
386 */
Daniel Veillard16253641998-10-28 22:58:05 +0000387 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000388 if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
389 xmlNodeAddContentLen(last, q, cur - q);
390 } else {
391 node = xmlNewDocTextLen(doc, q, cur - q);
392 if (node == NULL) return(ret);
393 if (last == NULL)
394 last = ret = node;
395 else {
396 last->next = node;
397 node->prev = last;
398 last = node;
399 }
Daniel Veillard16253641998-10-28 22:58:05 +0000400 }
401 }
Daniel Veillard25940b71998-10-29 05:51:30 +0000402 /*
403 * Read the entity string
404 */
Daniel Veillard16253641998-10-28 22:58:05 +0000405 cur++;
406 q = cur;
407 while ((*cur != 0) && (cur - value < len) && (*cur != ';')) cur++;
408 if ((*cur == 0) || (cur - value >= len)) {
409 fprintf(stderr,
410 "xmlStringGetNodeList: unterminated entity %30s\n", q);
411 return(ret);
412 }
413 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000414 /*
415 * Predefined entities don't generate nodes
416 */
Daniel Veillard16253641998-10-28 22:58:05 +0000417 val = xmlStrndup(q, cur - q);
Daniel Veillard25940b71998-10-29 05:51:30 +0000418 ent = xmlGetDocEntity(doc, val);
419 if ((ent != NULL) &&
420 (ent->type == XML_INTERNAL_PREDEFINED_ENTITY)) {
421 if (last == NULL) {
422 node = xmlNewDocText(doc, ent->content);
423 last = ret = node;
424 } else
425 xmlNodeAddContent(last, ent->content);
426
427 } else {
428 /*
429 * Create a new REFERENCE_REF node
430 */
431 node = xmlNewReference(doc, val);
Daniel Veillard242590e1998-11-13 18:04:35 +0000432 if (node == NULL) {
433 if (val != NULL) free(val);
434 return(ret);
435 }
Daniel Veillard25940b71998-10-29 05:51:30 +0000436 if (last == NULL)
437 last = ret = node;
438 else {
439 last->next = node;
440 node->prev = last;
441 last = node;
442 }
Daniel Veillard16253641998-10-28 22:58:05 +0000443 }
444 free(val);
445 }
446 cur++;
447 q = cur;
448 } else
449 cur++;
450 }
451 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000452 /*
453 * Handle the last piece of text.
454 */
455 if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
456 xmlNodeAddContentLen(last, q, cur - q);
457 } else {
458 node = xmlNewDocTextLen(doc, q, cur - q);
459 if (node == NULL) return(ret);
460 if (last == NULL)
461 last = ret = node;
462 else {
463 last->next = node;
464 node->prev = last;
465 last = node;
466 }
Daniel Veillard16253641998-10-28 22:58:05 +0000467 }
468 }
469 return(ret);
470}
471
472/**
Daniel Veillardccb09631998-10-27 06:21:04 +0000473 * xmlStringGetNodeList:
474 * @doc: the document
475 * @value: the value of the attribute
476 *
477 * Parse the value string and build the node list associated. Should
478 * produce a flat tree with only TEXTs and ENTITY_REFs.
479 * return values: a pointer to the first child
480 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000481xmlNodePtr
482xmlStringGetNodeList(xmlDocPtr doc, const CHAR *value) {
Daniel Veillardccb09631998-10-27 06:21:04 +0000483 xmlNodePtr ret = NULL, last = NULL;
484 xmlNodePtr node;
485 CHAR *val;
486 const CHAR *cur = value;
487 const CHAR *q;
Daniel Veillard25940b71998-10-29 05:51:30 +0000488 xmlEntityPtr ent;
Daniel Veillardccb09631998-10-27 06:21:04 +0000489
490 if (value == NULL) return(NULL);
491
492 q = cur;
493 while (*cur != 0) {
494 if (*cur == '&') {
Daniel Veillard25940b71998-10-29 05:51:30 +0000495 /*
496 * Save the current text.
497 */
Daniel Veillardccb09631998-10-27 06:21:04 +0000498 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000499 if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
500 xmlNodeAddContentLen(last, q, cur - q);
501 } else {
502 node = xmlNewDocTextLen(doc, q, cur - q);
503 if (node == NULL) return(ret);
504 if (last == NULL)
505 last = ret = node;
506 else {
507 last->next = node;
508 node->prev = last;
509 last = node;
510 }
Daniel Veillardccb09631998-10-27 06:21:04 +0000511 }
512 }
Daniel Veillard25940b71998-10-29 05:51:30 +0000513 /*
514 * Read the entity string
515 */
Daniel Veillardccb09631998-10-27 06:21:04 +0000516 cur++;
517 q = cur;
518 while ((*cur != 0) && (*cur != ';')) cur++;
519 if (*cur == 0) {
520 fprintf(stderr,
521 "xmlStringGetNodeList: unterminated entity %30s\n", q);
522 return(ret);
523 }
524 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000525 /*
526 * Predefined entities don't generate nodes
527 */
Daniel Veillardccb09631998-10-27 06:21:04 +0000528 val = xmlStrndup(q, cur - q);
Daniel Veillard25940b71998-10-29 05:51:30 +0000529 ent = xmlGetDocEntity(doc, val);
530 if ((ent != NULL) &&
531 (ent->type == XML_INTERNAL_PREDEFINED_ENTITY)) {
532 if (last == NULL) {
533 node = xmlNewDocText(doc, ent->content);
534 last = ret = node;
535 } else
536 xmlNodeAddContent(last, ent->content);
537
538 } else {
539 /*
540 * Create a new REFERENCE_REF node
541 */
Daniel Veillard25940b71998-10-29 05:51:30 +0000542 node = xmlNewReference(doc, val);
Daniel Veillard242590e1998-11-13 18:04:35 +0000543 if (node == NULL) {
544 if (val != NULL) free(val);
545 return(ret);
546 }
Daniel Veillard25940b71998-10-29 05:51:30 +0000547 if (last == NULL)
548 last = ret = node;
549 else {
550 last->next = node;
551 node->prev = last;
552 last = node;
553 }
Daniel Veillardccb09631998-10-27 06:21:04 +0000554 }
555 free(val);
556 }
557 cur++;
558 q = cur;
559 } else
560 cur++;
561 }
562 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000563 /*
564 * Handle the last piece of text.
565 */
566 if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
567 xmlNodeAddContentLen(last, q, cur - q);
568 } else {
569 node = xmlNewDocTextLen(doc, q, cur - q);
570 if (node == NULL) return(ret);
571 if (last == NULL)
572 last = ret = node;
573 else {
574 last->next = node;
575 node->prev = last;
576 last = node;
577 }
Daniel Veillardccb09631998-10-27 06:21:04 +0000578 }
579 }
580 return(ret);
581}
582
583/**
584 * xmlNodeListGetString:
585 * @doc: the document
586 * @list: a Node list
587 * @inLine: should we replace entity contents or show their external form
588 *
589 * Returns the string equivalent to the text contained in the Node list
590 * made of TEXTs and ENTITY_REFs
591 * return values: a pointer to the string copy, the calller must free it.
592 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000593CHAR *
594xmlNodeListGetString(xmlDocPtr doc, xmlNodePtr list, int inLine) {
Daniel Veillardccb09631998-10-27 06:21:04 +0000595 xmlNodePtr node = list;
596 CHAR *ret = NULL;
597 xmlEntityPtr ent;
598
599 if (list == NULL) return(NULL);
600
601 while (node != NULL) {
602 if (node->type == XML_TEXT_NODE) {
603 if (inLine)
604 ret = xmlStrcat(ret, node->content);
605 else
606 ret = xmlStrcat(ret, xmlEncodeEntities(doc, node->content));
607 } else if (node->type == XML_ENTITY_REF_NODE) {
608 if (inLine) {
609 ent = xmlGetDocEntity(doc, node->name);
610 if (ent != NULL)
611 ret = xmlStrcat(ret, ent->content);
612 else
613 ret = xmlStrcat(ret, node->content);
614 } else {
615 CHAR buf[2];
616 buf[0] = '&'; buf[1] = 0;
617 ret = xmlStrncat(ret, buf, 1);
618 ret = xmlStrcat(ret, node->name);
619 buf[0] = ';'; buf[1] = 0;
620 ret = xmlStrncat(ret, buf, 1);
621 }
622 }
623#if 0
624 else {
625 fprintf(stderr, "xmlGetNodeListString : invalide node type %d\n",
626 node->type);
627 }
628#endif
629 node = node->next;
630 }
631 return(ret);
632}
633
634/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000635 * xmlNewProp:
636 * @node: the holding node
637 * @name: the name of the attribute
638 * @value: the value of the attribute
639 *
640 * Create a new property carried by a node.
641 * return values: a pointer to the attribute
Daniel Veillard260a68f1998-08-13 03:39:55 +0000642 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000643xmlAttrPtr
644xmlNewProp(xmlNodePtr node, const CHAR *name, const CHAR *value) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000645 xmlAttrPtr cur;
646
647 if (name == NULL) {
648 fprintf(stderr, "xmlNewProp : name == NULL\n");
649 return(NULL);
650 }
651
652 /*
653 * Allocate a new property and fill the fields.
654 */
655 cur = (xmlAttrPtr) malloc(sizeof(xmlAttr));
656 if (cur == NULL) {
657 fprintf(stderr, "xmlNewProp : malloc failed\n");
658 return(NULL);
659 }
660
Daniel Veillard33942841998-10-18 19:12:41 +0000661 cur->type = XML_ATTRIBUTE_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000662 cur->node = node;
663 cur->name = xmlStrdup(name);
664 if (value != NULL)
Daniel Veillardccb09631998-10-27 06:21:04 +0000665 cur->val = xmlStringGetNodeList(node->doc, value);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000666 else
Daniel Veillardccb09631998-10-27 06:21:04 +0000667 cur->val = NULL;
Daniel Veillard27fb0751998-10-17 06:47:46 +0000668#ifndef WITHOUT_CORBA
669 cur->_private = NULL;
670 cur->vepv = NULL;
671#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000672
673 /*
674 * Add it at the end to preserve parsing order ...
675 */
676 cur->next = NULL;
677 if (node != NULL) {
678 if (node->properties == NULL) {
679 node->properties = cur;
680 } else {
681 xmlAttrPtr prev = node->properties;
682
683 while (prev->next != NULL) prev = prev->next;
684 prev->next = cur;
685 }
686 }
687 return(cur);
688}
689
Daniel Veillard97b58771998-10-20 06:14:16 +0000690/**
Daniel Veillardccb09631998-10-27 06:21:04 +0000691 * xmlNewDocProp:
692 * @doc: the document
693 * @name: the name of the attribute
694 * @value: the value of the attribute
695 *
696 * Create a new property carried by a document.
697 * return values: a pointer to the attribute
698 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000699xmlAttrPtr
700xmlNewDocProp(xmlDocPtr doc, const CHAR *name, const CHAR *value) {
Daniel Veillardccb09631998-10-27 06:21:04 +0000701 xmlAttrPtr cur;
702
703 if (name == NULL) {
704 fprintf(stderr, "xmlNewProp : name == NULL\n");
705 return(NULL);
706 }
707
708 /*
709 * Allocate a new property and fill the fields.
710 */
711 cur = (xmlAttrPtr) malloc(sizeof(xmlAttr));
712 if (cur == NULL) {
713 fprintf(stderr, "xmlNewProp : malloc failed\n");
714 return(NULL);
715 }
716
717 cur->type = XML_ATTRIBUTE_NODE;
718 cur->node = NULL;
719 cur->name = xmlStrdup(name);
720 if (value != NULL)
721 cur->val = xmlStringGetNodeList(doc, value);
722 else
723 cur->val = NULL;
724#ifndef WITHOUT_CORBA
725 cur->_private = NULL;
726 cur->vepv = NULL;
727#endif
728
729 cur->next = NULL;
730 return(cur);
731}
732
733/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000734 * xmlFreePropList:
735 * @cur: the first property in the list
736 *
737 * Free a property and all its siblings, all the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000738 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000739void
740xmlFreePropList(xmlAttrPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000741 xmlAttrPtr next;
742 if (cur == NULL) {
743 fprintf(stderr, "xmlFreePropList : property == NULL\n");
744 return;
745 }
746 while (cur != NULL) {
747 next = cur->next;
748 xmlFreeProp(cur);
749 cur = next;
750 }
751}
752
Daniel Veillard97b58771998-10-20 06:14:16 +0000753/**
754 * xmlFreeProp:
755 * @cur: the first property in the list
756 *
757 * Free one property, all the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000758 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000759void
760xmlFreeProp(xmlAttrPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000761 if (cur == NULL) {
762 fprintf(stderr, "xmlFreeProp : property == NULL\n");
763 return;
764 }
765 if (cur->name != NULL) free((char *) cur->name);
Daniel Veillardccb09631998-10-27 06:21:04 +0000766 if (cur->val != NULL) xmlFreeNodeList(cur->val);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000767 memset(cur, -1, sizeof(xmlAttr));
768 free(cur);
769}
770
Daniel Veillard97b58771998-10-20 06:14:16 +0000771/**
772 * xmlNewNode:
773 * @ns: namespace if any
774 * @name: the node name
775 * @content: the text content if any
776 *
777 * Creation of a new node element. @ns and @content are optionnal (NULL).
Daniel Veillardccb09631998-10-27 06:21:04 +0000778 * If content is non NULL, a child list containing the TEXTs and
779 * ENTITY_REFs node will be created.
Daniel Veillard97b58771998-10-20 06:14:16 +0000780 * return values: a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000781 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000782xmlNodePtr
783xmlNewNode(xmlNsPtr ns, const CHAR *name) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000784 xmlNodePtr cur;
785
786 if (name == NULL) {
787 fprintf(stderr, "xmlNewNode : name == NULL\n");
788 return(NULL);
789 }
790
791 /*
792 * Allocate a new node and fill the fields.
793 */
794 cur = (xmlNodePtr) malloc(sizeof(xmlNode));
795 if (cur == NULL) {
796 fprintf(stderr, "xmlNewNode : malloc failed\n");
797 return(NULL);
798 }
799
Daniel Veillard33942841998-10-18 19:12:41 +0000800 cur->type = XML_ELEMENT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000801 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000802 cur->parent = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000803 cur->next = NULL;
804 cur->prev = NULL;
805 cur->childs = NULL;
806 cur->properties = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000807 cur->name = xmlStrdup(name);
808 cur->ns = ns;
809 cur->nsDef = NULL;
Daniel Veillardccb09631998-10-27 06:21:04 +0000810 cur->content = NULL;
Daniel Veillard27fb0751998-10-17 06:47:46 +0000811#ifndef WITHOUT_CORBA
812 cur->_private = NULL;
813 cur->vepv = NULL;
814#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000815 return(cur);
816}
817
Daniel Veillard97b58771998-10-20 06:14:16 +0000818/**
819 * xmlNewDocNode:
820 * @doc: the document
821 * @ns: namespace if any
822 * @name: the node name
823 * @content: the text content if any
824 *
825 * Creation of a new node element within a document. @ns and @content
826 * are optionnal (NULL).
827 * return values: a pointer to the new node object.
828 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000829xmlNodePtr
830xmlNewDocNode(xmlDocPtr doc, xmlNsPtr ns,
Daniel Veillard0bef1311998-10-14 02:36:47 +0000831 const CHAR *name, CHAR *content) {
832 xmlNodePtr cur;
833
Daniel Veillardccb09631998-10-27 06:21:04 +0000834 cur = xmlNewNode(ns, name);
835 if (cur != NULL) {
836 cur->doc = doc;
837 if (content != NULL)
838 cur->childs = xmlStringGetNodeList(doc, content);
839 }
Daniel Veillard0bef1311998-10-14 02:36:47 +0000840 return(cur);
841}
842
843
Daniel Veillard97b58771998-10-20 06:14:16 +0000844/**
845 * xmlNewText:
846 * @content: the text content
847 *
848 * Creation of a new text node.
849 * return values: a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000850 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000851xmlNodePtr
852xmlNewText(const CHAR *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000853 xmlNodePtr cur;
854
855 /*
856 * Allocate a new node and fill the fields.
857 */
858 cur = (xmlNodePtr) malloc(sizeof(xmlNode));
859 if (cur == NULL) {
860 fprintf(stderr, "xmlNewText : malloc failed\n");
861 return(NULL);
862 }
863
Daniel Veillard33942841998-10-18 19:12:41 +0000864 cur->type = XML_TEXT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000865 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000866 cur->parent = NULL;
867 cur->next = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000868 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000869 cur->childs = NULL;
870 cur->properties = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000871 cur->type = XML_TEXT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000872 cur->name = xmlStrdup(xmlStringText);
873 cur->ns = NULL;
874 cur->nsDef = NULL;
875 if (content != NULL)
876 cur->content = xmlStrdup(content);
877 else
878 cur->content = NULL;
879 return(cur);
880}
881
Daniel Veillard97b58771998-10-20 06:14:16 +0000882/**
Daniel Veillardccb09631998-10-27 06:21:04 +0000883 * xmlNewReference:
884 * @doc: the document
885 * @name: the reference name, or the reference string with & and ;
886 *
887 * Creation of a new reference node.
888 * return values: a pointer to the new node object.
889 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000890xmlNodePtr
891xmlNewReference(xmlDocPtr doc, const CHAR *name) {
Daniel Veillardccb09631998-10-27 06:21:04 +0000892 xmlNodePtr cur;
893 xmlEntityPtr ent;
894
895 /*
896 * Allocate a new node and fill the fields.
897 */
898 cur = (xmlNodePtr) malloc(sizeof(xmlNode));
899 if (cur == NULL) {
900 fprintf(stderr, "xmlNewText : malloc failed\n");
901 return(NULL);
902 }
903
904 cur->type = XML_ENTITY_REF_NODE;
Daniel Veillard10c6a8f1998-10-28 01:00:12 +0000905 cur->doc = doc;
Daniel Veillardccb09631998-10-27 06:21:04 +0000906 cur->parent = NULL;
907 cur->next = NULL;
908 cur->prev = NULL;
909 cur->childs = NULL;
910 cur->properties = NULL;
911 if (name[0] == '&') {
912 int len;
913 name++;
914 len = xmlStrlen(name);
915 if (name[len - 1] == ';')
916 cur->name = xmlStrndup(name, len - 1);
917 else
918 cur->name = xmlStrndup(name, len);
919 } else
920 cur->name = xmlStrdup(name);
921 cur->ns = NULL;
922 cur->nsDef = NULL;
923
924 ent = xmlGetDocEntity(doc, cur->name);
925 if (ent != NULL)
926 cur->content = ent->content;
927 else
928 cur->content = NULL;
929 return(cur);
930}
931
932/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000933 * xmlNewDocText:
934 * @doc: the document
935 * @content: the text content
936 *
937 * Creation of a new text node within a document.
938 * return values: a pointer to the new node object.
939 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000940xmlNodePtr
941xmlNewDocText(xmlDocPtr doc, const CHAR *content) {
Daniel Veillard0bef1311998-10-14 02:36:47 +0000942 xmlNodePtr cur;
943
944 cur = xmlNewText(content);
945 if (cur != NULL) cur->doc = doc;
946 return(cur);
947}
948
Daniel Veillard97b58771998-10-20 06:14:16 +0000949/**
Daniel Veillardccb09631998-10-27 06:21:04 +0000950 * xmlNewTextLen:
Daniel Veillard97b58771998-10-20 06:14:16 +0000951 * @content: the text content
952 * @len: the text len.
953 *
954 * Creation of a new text node with an extra parameter for the content's lenght
955 * return values: a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000956 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000957xmlNodePtr
958xmlNewTextLen(const CHAR *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000959 xmlNodePtr cur;
960
961 /*
962 * Allocate a new node and fill the fields.
963 */
964 cur = (xmlNodePtr) malloc(sizeof(xmlNode));
965 if (cur == NULL) {
966 fprintf(stderr, "xmlNewText : malloc failed\n");
967 return(NULL);
968 }
969
Daniel Veillard33942841998-10-18 19:12:41 +0000970 cur->type = XML_TEXT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000971 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000972 cur->parent = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000973 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000974 cur->next = NULL;
975 cur->childs = NULL;
976 cur->properties = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000977 cur->type = XML_TEXT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000978 cur->name = xmlStrdup(xmlStringText);
979 cur->ns = NULL;
980 cur->nsDef = NULL;
981 if (content != NULL)
982 cur->content = xmlStrndup(content, len);
983 else
984 cur->content = NULL;
985 return(cur);
986}
987
Daniel Veillard97b58771998-10-20 06:14:16 +0000988/**
989 * xmlNewDocTextLen:
990 * @doc: the document
991 * @content: the text content
992 * @len: the text len.
993 *
994 * Creation of a new text node with an extra content lenght parameter. The
995 * text node pertain to a given document.
996 * return values: a pointer to the new node object.
997 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000998xmlNodePtr
999xmlNewDocTextLen(xmlDocPtr doc, const CHAR *content, int len) {
Daniel Veillard0bef1311998-10-14 02:36:47 +00001000 xmlNodePtr cur;
1001
1002 cur = xmlNewTextLen(content, len);
1003 if (cur != NULL) cur->doc = doc;
1004 return(cur);
1005}
1006
Daniel Veillard97b58771998-10-20 06:14:16 +00001007/**
1008 * xmlNewComment:
1009 * @content: the comment content
1010 *
1011 * Creation of a new node containing a comment.
1012 * return values: a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001013 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001014xmlNodePtr
1015xmlNewComment(CHAR *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001016 xmlNodePtr cur;
1017
1018 /*
1019 * Allocate a new node and fill the fields.
1020 */
1021 cur = (xmlNodePtr) malloc(sizeof(xmlNode));
1022 if (cur == NULL) {
1023 fprintf(stderr, "xmlNewComment : malloc failed\n");
1024 return(NULL);
1025 }
1026
Daniel Veillard33942841998-10-18 19:12:41 +00001027 cur->type = XML_COMMENT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001028 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001029 cur->parent = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001030 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001031 cur->next = NULL;
1032 cur->childs = NULL;
1033 cur->properties = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001034 cur->type = XML_COMMENT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001035 cur->name = xmlStrdup(xmlStringText);
1036 cur->ns = NULL;
1037 cur->nsDef = NULL;
1038 if (content != NULL)
1039 cur->content = xmlStrdup(content);
1040 else
1041 cur->content = NULL;
1042 return(cur);
1043}
1044
Daniel Veillard97b58771998-10-20 06:14:16 +00001045/**
1046 * xmlNewComment:
1047 * @doc: the document
1048 * @content: the comment content
1049 *
1050 * Creation of a new node containing a commentwithin a document.
1051 * return values: a pointer to the new node object.
1052 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001053xmlNodePtr
1054xmlNewDocComment(xmlDocPtr doc, CHAR *content) {
Daniel Veillard0bef1311998-10-14 02:36:47 +00001055 xmlNodePtr cur;
1056
1057 cur = xmlNewComment(content);
1058 if (cur != NULL) cur->doc = doc;
1059 return(cur);
1060}
1061
Daniel Veillard97b58771998-10-20 06:14:16 +00001062/**
1063 * xmlNewChild:
1064 * @parent: the parent node
1065 * @ns: a namespace if any
1066 * @name: the name of the child
1067 * @content: the content of the child if any.
1068 *
1069 *
1070 * Creation of a new child element, added at the end of @parent childs list.
Daniel Veillardccb09631998-10-27 06:21:04 +00001071 * @ns and @content parameters are optionnal (NULL). If content is non NULL,
1072 * a child list containing the TEXTs and ENTITY_REFs node will be created.
Daniel Veillard97b58771998-10-20 06:14:16 +00001073 * return values: a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001074 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001075xmlNodePtr
1076xmlNewChild(xmlNodePtr parent, xmlNsPtr ns,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001077 const CHAR *name, CHAR *content) {
1078 xmlNodePtr cur, prev;
1079
1080 if (parent == NULL) {
1081 fprintf(stderr, "xmlNewChild : parent == NULL\n");
1082 return(NULL);
1083 }
1084
1085 if (name == NULL) {
1086 fprintf(stderr, "xmlNewChild : name == NULL\n");
1087 return(NULL);
1088 }
1089
1090 /*
1091 * Allocate a new node
1092 */
1093 if (ns == NULL)
Daniel Veillardccb09631998-10-27 06:21:04 +00001094 cur = xmlNewDocNode(parent->doc, parent->ns, name, content);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001095 else
Daniel Veillardccb09631998-10-27 06:21:04 +00001096 cur = xmlNewDocNode(parent->doc, ns, name, content);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001097 if (cur == NULL) return(NULL);
1098
1099 /*
1100 * add the new element at the end of the childs list.
1101 */
Daniel Veillardccb09631998-10-27 06:21:04 +00001102 cur->type = XML_ELEMENT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001103 cur->parent = parent;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001104 cur->doc = parent->doc;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001105 if (parent->childs == NULL) {
1106 parent->childs = cur;
1107 } else {
1108 prev = parent->childs;
1109 while (prev->next != NULL) prev = prev->next;
1110 prev->next = cur;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001111 cur->prev = prev;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001112 }
1113
1114 return(cur);
1115}
1116
Daniel Veillard97b58771998-10-20 06:14:16 +00001117/**
1118 * xmlAddChild:
1119 * @parent: the parent node
1120 * @cur: the child node
1121 *
1122 * Add a new child element, to @parent, at the end of the child list.
1123 * return values: the child or NULL in case of error.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001124 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001125xmlNodePtr
1126xmlAddChild(xmlNodePtr parent, xmlNodePtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001127 xmlNodePtr prev;
1128
1129 if (parent == NULL) {
1130 fprintf(stderr, "xmladdChild : parent == NULL\n");
1131 return(NULL);
1132 }
1133
1134 if (cur == NULL) {
1135 fprintf(stderr, "xmladdChild : child == NULL\n");
1136 return(NULL);
1137 }
1138
Daniel Veillard0bef1311998-10-14 02:36:47 +00001139 if ((cur->doc != NULL) && (parent->doc != NULL) &&
1140 (cur->doc != parent->doc)) {
1141 fprintf(stderr, "Elements moved to a different document\n");
1142 }
1143
Daniel Veillard260a68f1998-08-13 03:39:55 +00001144 /*
1145 * add the new element at the end of the childs list.
1146 */
1147 cur->parent = parent;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001148 cur->doc = parent->doc; /* the parent may not be linked to a doc ! */
Daniel Veillardccb09631998-10-27 06:21:04 +00001149 /*
1150 * Handle the case where parent->content != NULL, in that case it will
1151 * create a intermediate TEXT node.
1152 */
1153 if (parent->content != NULL) {
1154 xmlNodePtr text;
1155
1156 text = xmlNewDocText(parent->doc, parent->content);
1157 if (text != NULL) {
1158 text->next = parent->childs;
1159 if (text->next != NULL)
1160 text->next->prev = text;
1161 parent->childs = text;
1162 free(parent->content);
1163 parent->content = NULL;
1164 }
1165 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00001166 if (parent->childs == NULL) {
1167 parent->childs = cur;
1168 } else {
1169 prev = parent->childs;
1170 while (prev->next != NULL) prev = prev->next;
1171 prev->next = cur;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001172 cur->prev = prev;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001173 }
1174
1175 return(cur);
1176}
1177
Daniel Veillard97b58771998-10-20 06:14:16 +00001178/**
1179 * xmlGetLastChild:
1180 * @parent: the parent node
1181 *
1182 * Search the last child of a node.
1183 * return values: the last child or NULL if none.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001184 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001185xmlNodePtr
1186xmlGetLastChild(xmlNodePtr parent) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001187 xmlNodePtr last;
1188
1189 if (parent == NULL) {
1190 fprintf(stderr, "xmlGetLastChild : parent == NULL\n");
1191 return(NULL);
1192 }
1193
1194 /*
1195 * add the new element at the end of the childs list.
1196 */
1197 if (parent->childs == NULL) {
1198 return(NULL);
1199 } else {
1200 last = parent->childs;
1201 while (last->next != NULL) last = last->next;
1202 }
1203 return(last);
1204}
1205
Daniel Veillard97b58771998-10-20 06:14:16 +00001206/**
1207 * xmlFreeNodeList:
1208 * @cur: the first node in the list
1209 *
1210 * Free a node and all its siblings, this is a recursive behaviour, all
1211 * the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001212 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001213void
1214xmlFreeNodeList(xmlNodePtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001215 xmlNodePtr next;
1216 if (cur == NULL) {
1217 fprintf(stderr, "xmlFreeNodeList : node == NULL\n");
1218 return;
1219 }
1220 while (cur != NULL) {
1221 next = cur->next;
1222 xmlFreeNode(cur);
1223 cur = next;
1224 }
1225}
1226
Daniel Veillard97b58771998-10-20 06:14:16 +00001227/**
1228 * xmlFreeNode:
1229 * @cur: the node
1230 *
1231 * Free a node, this is a recursive behaviour, all the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001232 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001233void
1234xmlFreeNode(xmlNodePtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001235 if (cur == NULL) {
1236 fprintf(stderr, "xmlFreeNode : node == NULL\n");
1237 return;
1238 }
Daniel Veillardccb09631998-10-27 06:21:04 +00001239 cur->doc = NULL;
1240 cur->parent = NULL;
1241 cur->next = NULL;
1242 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001243 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillardccb09631998-10-27 06:21:04 +00001244 if (cur->properties != NULL) xmlFreePropList(cur->properties);
1245 if (cur->type != XML_ENTITY_REF_NODE)
1246 if (cur->content != NULL) free(cur->content);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001247 if (cur->name != NULL) free((char *) cur->name);
1248 if (cur->nsDef != NULL) xmlFreeNsList(cur->nsDef);
1249 memset(cur, -1, sizeof(xmlNode));
1250 free(cur);
1251}
1252
Daniel Veillard16253641998-10-28 22:58:05 +00001253/**
1254 * xmlUnlinkNode:
1255 * @cur: the node
1256 *
1257 * Unlink a node from it's current context, the node is not freed
1258 */
1259void
1260xmlUnlinkNode(xmlNodePtr cur) {
1261 if (cur == NULL) {
1262 fprintf(stderr, "xmlUnlinkNode : node == NULL\n");
1263 return;
1264 }
1265 if ((cur->parent != NULL) && (cur->parent->childs == cur))
1266 cur->parent->childs = cur->next;
1267 if (cur->next != NULL)
1268 cur->next->prev = cur->prev;
1269 if (cur->prev != NULL)
1270 cur->prev->next = cur->next;
1271 cur->next = cur->prev = NULL;
1272 cur->parent = NULL;
1273}
1274
Daniel Veillard260a68f1998-08-13 03:39:55 +00001275/************************************************************************
1276 * *
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001277 * Copy operations *
1278 * *
1279 ************************************************************************/
1280
1281/**
1282 * xmlCopyNamespace:
1283 * @cur: the namespace
1284 *
1285 * Do a copy of the namespace.
1286 *
1287 * Returns: a new xmlNsPtr, or NULL in case of error.
1288 */
1289xmlNsPtr
1290xmlCopyNamespace(xmlNsPtr cur) {
1291 xmlNsPtr ret;
1292
1293 if (cur == NULL) return(NULL);
1294 switch (cur->type) {
1295 case XML_GLOBAL_NAMESPACE:
1296 ret = xmlNewGlobalNs(NULL, cur->href, cur->prefix);
1297 break;
1298 case XML_LOCAL_NAMESPACE:
1299 ret = xmlNewNs(NULL, cur->href, cur->prefix);
1300 break;
1301 default:
1302 fprintf(stderr, "xmlCopyNamespace: unknown type %d\n", cur->type);
1303 return(NULL);
1304 }
1305 return(ret);
1306}
1307
1308/**
1309 * xmlCopyNamespaceList:
1310 * @cur: the first namespace
1311 *
1312 * Do a copy of an namespace list.
1313 *
1314 * Returns: a new xmlNsPtr, or NULL in case of error.
1315 */
1316xmlNsPtr
1317xmlCopyNamespaceList(xmlNsPtr cur) {
1318 xmlNsPtr ret = NULL;
1319 xmlNsPtr p = NULL,q;
1320
1321 while (cur != NULL) {
1322 q = xmlCopyNamespace(cur);
1323 if (p == NULL) {
1324 ret = p = q;
1325 } else {
1326 p->next = q;
1327 p = q;
1328 }
1329 cur = cur->next;
1330 }
1331 return(ret);
1332}
1333
1334/**
1335 * xmlCopyProp:
1336 * @cur: the attribute
1337 *
1338 * Do a copy of the attribute.
1339 *
1340 * Returns: a new xmlAttrPtr, or NULL in case of error.
1341 */
1342xmlAttrPtr
1343xmlCopyProp(xmlAttrPtr cur) {
1344 xmlAttrPtr ret;
1345
1346 if (cur == NULL) return(NULL);
1347 if (cur->val != NULL)
1348 ret = xmlNewDocProp(cur->val->doc, cur->name, NULL);
1349 else
1350 ret = xmlNewDocProp(NULL, cur->name, NULL);
1351 if (ret == NULL) return(NULL);
1352 if (cur->val != NULL)
1353 ret->val = xmlCopyNodeList(cur->val);
1354 return(ret);
1355}
1356
1357/**
1358 * xmlCopyPropList:
1359 * @cur: the first attribute
1360 *
1361 * Do a copy of an attribute list.
1362 *
1363 * Returns: a new xmlAttrPtr, or NULL in case of error.
1364 */
1365xmlAttrPtr
1366xmlCopyPropList(xmlAttrPtr cur) {
1367 xmlAttrPtr ret = NULL;
1368 xmlAttrPtr p = NULL,q;
1369
1370 while (cur != NULL) {
1371 q = xmlCopyProp(cur);
1372 if (p == NULL) {
1373 ret = p = q;
1374 } else {
1375 p->next = q;
1376 p = q;
1377 }
1378 cur = cur->next;
1379 }
1380 return(ret);
1381}
1382
1383/*
1384 * NOTE about the CopyNode operations !
1385 *
1386 * They are splitted into external and internal parts for one
1387 * tricky reason: namespaces. Doing a direct copy of a node
1388 * say RPM:Copyright without changing the namespace pointer to
1389 * something else can produce stale links. One way to do it is
1390 * to keep a reference counter but this doesn't work as soon
1391 * as one move the element or the subtree out of the scope of
1392 * the existing namespace. The actual solution seems to add
1393 * a copy of the namespace at the top of the copied tree if
1394 * not available in the subtree.
1395 * Hence two functions, the public front-end call the inner ones
1396 */
1397
1398static xmlNodePtr
1399xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent);
1400
1401static xmlNodePtr
1402xmlStaticCopyNode(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent,
1403 int recursive) {
1404 xmlNodePtr ret;
1405
1406 if (node == NULL) return(NULL);
1407 /*
1408 * Allocate a new node and fill the fields.
1409 */
1410 ret = (xmlNodePtr) malloc(sizeof(xmlNode));
1411 if (ret == NULL) {
1412 fprintf(stderr, "xmlStaticCopyNode : malloc failed\n");
1413 return(NULL);
1414 }
1415
1416 ret->type = node->type;
1417 ret->doc = doc;
1418 ret->parent = parent;
1419 ret->next = NULL;
1420 ret->prev = NULL;
1421 ret->childs = NULL;
1422 ret->properties = NULL;
1423 if (node->name != NULL)
1424 ret->name = xmlStrdup(node->name);
1425 else
1426 ret->name = NULL;
1427 ret->ns = NULL;
1428 ret->nsDef = NULL;
1429 if ((node->content != NULL) && (node->type != XML_ENTITY_REF_NODE))
1430 ret->content = xmlStrdup(node->content);
1431 else
1432 ret->content = NULL;
1433#ifndef WITHOUT_CORBA
1434 ret->_private = NULL;
1435 ret->vepv = NULL;
1436#endif
1437 if (parent != NULL)
1438 xmlAddChild(parent, ret);
1439
1440 if (!recursive) return(ret);
1441 if (node->properties != NULL)
1442 ret->properties = xmlCopyPropList(node->properties);
1443 if (node->nsDef != NULL)
1444 ret->nsDef = xmlCopyNamespaceList(node->nsDef);
1445
1446 if (node->ns != NULL) {
1447 xmlNsPtr ns;
1448
1449 ns = xmlSearchNs(doc, ret, node->ns->prefix);
1450 if (ns == NULL) {
1451 /*
1452 * Humm, we are copying an element whose namespace is defined
1453 * out of the new tree scope. Search it in the original tree
1454 * and add it at the top of the new tree
1455 */
1456 ns = xmlSearchNs(node->doc, node, node->ns->prefix);
1457 if (ns != NULL) {
1458 xmlNodePtr root = ret;
1459
1460 while (root->parent != NULL) root = root->parent;
1461 xmlNewNs(root, ns->href, ns->prefix);
1462 }
1463 } else {
1464 /*
1465 * reference the existing namespace definition in our own tree.
1466 */
1467 ret->ns = ns;
1468 }
1469 }
1470 if (node->childs != NULL)
1471 ret->childs = xmlStaticCopyNodeList(node->childs, doc, ret);
1472 return(ret);
1473}
1474
1475static xmlNodePtr
1476xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent) {
1477 xmlNodePtr ret = NULL;
1478 xmlNodePtr p = NULL,q;
1479
1480 while (node != NULL) {
1481 q = xmlStaticCopyNode(node, doc, parent, 1);
1482 if (parent == NULL) {
1483 if (ret == NULL) ret = q;
1484 } else {
1485 if (ret == NULL) {
1486 q->prev = NULL;
1487 ret = p = q;
1488 } else {
1489 p->next = q;
1490 q->prev = p;
1491 p = q;
1492 }
1493 }
1494 node = node->next;
1495 }
1496 return(ret);
1497}
1498
1499/**
1500 * xmlCopyNode:
1501 * @node: the node
1502 * @recursive: if 1 do a recursive copy.
1503 *
1504 * Do a copy of the node.
1505 *
1506 * Returns: a new xmlNodePtr, or NULL in case of error.
1507 */
1508xmlNodePtr
1509xmlCopyNode(xmlNodePtr node, int recursive) {
1510 xmlNodePtr ret;
1511
1512 ret = xmlStaticCopyNode(node, NULL, NULL, recursive);
1513 return(ret);
1514}
1515
1516/**
1517 * xmlCopyNodeList:
1518 * @node: the first node in the list.
1519 *
1520 * Do a recursive copy of the node list.
1521 *
1522 * Returns: a new xmlNodePtr, or NULL in case of error.
1523 */
1524xmlNodePtr xmlCopyNodeList(xmlNodePtr node) {
1525 xmlNodePtr ret = xmlStaticCopyNodeList(node, NULL, NULL);
1526 return(ret);
1527}
1528
1529/**
1530 * xmlCopyElement:
1531 * @elem: the element
1532 *
1533 * Do a copy of the element definition.
1534 *
1535 * Returns: a new xmlElementPtr, or NULL in case of error.
1536xmlElementPtr
1537xmlCopyElement(xmlElementPtr elem) {
1538 xmlElementPtr ret;
1539
1540 if (elem == NULL) return(NULL);
1541 ret = xmlNewDocElement(elem->doc, elem->ns, elem->name, elem->content);
1542 if (ret == NULL) return(NULL);
1543 if (!recursive) return(ret);
1544 if (elem->properties != NULL)
1545 ret->properties = xmlCopyPropList(elem->properties);
1546
1547 if (elem->nsDef != NULL)
1548 ret->nsDef = xmlCopyNamespaceList(elem->nsDef);
1549 if (elem->childs != NULL)
1550 ret->childs = xmlCopyElementList(elem->childs);
1551 return(ret);
1552}
1553 */
1554
1555/**
1556 * xmlCopyDtd:
1557 * @dtd: the dtd
1558 *
1559 * Do a copy of the dtd.
1560 *
1561 * Returns: a new xmlDtdPtr, or NULL in case of error.
1562 */
1563xmlDtdPtr
1564xmlCopyDtd(xmlDtdPtr dtd) {
1565 xmlDtdPtr ret;
1566
1567 if (dtd == NULL) return(NULL);
1568 ret = xmlNewDtd(NULL, dtd->name, dtd->ExternalID, dtd->SystemID);
1569 if (ret == NULL) return(NULL);
1570 if (dtd->entities != NULL)
1571 ret->entities = (void *) xmlCopyEntitiesTable(
1572 (xmlEntitiesTablePtr) dtd->entities);
1573 /*
1574 * TODO: support for Element definitions.
1575 */
1576 return(ret);
1577}
1578
1579/**
1580 * xmlCopyDoc:
1581 * @doc: the document
1582 * @recursive: if 1 do a recursive copy.
1583 *
1584 * Do a copy of the document info. If recursive, the content tree will
1585 * be copied too as well as Dtd, namespaces and entities.
1586 *
1587 * Returns: a new xmlDocPtr, or NULL in case of error.
1588 */
1589xmlDocPtr
1590xmlCopyDoc(xmlDocPtr doc, int recursive) {
1591 xmlDocPtr ret;
1592
1593 if (doc == NULL) return(NULL);
1594 ret = xmlNewDoc(doc->version);
1595 if (ret == NULL) return(NULL);
1596 if (doc->name != NULL)
1597 ret->name = strdup(doc->name);
1598 if (doc->encoding != NULL)
1599 ret->encoding = xmlStrdup(doc->encoding);
1600 ret->compression = doc->compression;
1601 ret->standalone = doc->standalone;
1602 if (!recursive) return(ret);
1603
1604 if (doc->dtd != NULL)
1605 ret->dtd = xmlCopyDtd(doc->dtd);
1606 if (doc->entities != NULL)
1607 ret->entities = (void *) xmlCopyEntitiesTable(
1608 (xmlEntitiesTablePtr) doc->entities);
1609 if (doc->oldNs != NULL)
1610 ret->oldNs = xmlCopyNamespaceList(doc->oldNs);
1611 if (doc->root != NULL)
1612 ret->root = xmlStaticCopyNodeList(doc->root, ret, NULL);
1613 return(ret);
1614}
1615
1616/************************************************************************
1617 * *
Daniel Veillard260a68f1998-08-13 03:39:55 +00001618 * Content access functions *
1619 * *
1620 ************************************************************************/
1621
Daniel Veillard97b58771998-10-20 06:14:16 +00001622/**
Daniel Veillard16253641998-10-28 22:58:05 +00001623 * xmlNodeGetContent:
1624 * @cur: the node being read
1625 *
1626 * Read the value of a node, this can be either the text carried
1627 * directly by this node if it's a TEXT node or the aggregate string
1628 * of the values carried by this node child's (TEXT and ENTITY_REF).
1629 * Entity references are substitued.
1630 * Return value: a new CHAR * or NULL if no content is available.
1631 */
1632CHAR *
1633xmlNodeGetContent(xmlNodePtr cur) {
1634 if (cur == NULL) return(NULL);
1635 switch (cur->type) {
1636 case XML_DOCUMENT_FRAG_NODE:
1637 case XML_ELEMENT_NODE:
1638 return(xmlNodeListGetString(cur->doc, cur->childs, 1));
1639 break;
1640 case XML_ATTRIBUTE_NODE:
1641 case XML_CDATA_SECTION_NODE:
1642 case XML_ENTITY_REF_NODE:
1643 case XML_ENTITY_NODE:
1644 case XML_PI_NODE:
1645 case XML_COMMENT_NODE:
1646 case XML_DOCUMENT_NODE:
1647 case XML_DOCUMENT_TYPE_NODE:
1648 case XML_NOTATION_NODE:
1649 return(NULL);
1650 case XML_TEXT_NODE:
1651 if (cur->content != NULL)
1652 return(xmlStrdup(cur->content));
1653 return(NULL);
1654 }
1655 return(NULL);
1656}
1657
1658/**
Daniel Veillard97b58771998-10-20 06:14:16 +00001659 * xmlNodeSetContent:
1660 * @cur: the node being modified
1661 * @content: the new value of the content
1662 *
1663 * Replace the content of a node.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001664 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001665void
1666xmlNodeSetContent(xmlNodePtr cur, const CHAR *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001667 if (cur == NULL) {
1668 fprintf(stderr, "xmlNodeSetContent : node == NULL\n");
1669 return;
1670 }
Daniel Veillard16253641998-10-28 22:58:05 +00001671 switch (cur->type) {
1672 case XML_DOCUMENT_FRAG_NODE:
1673 case XML_ELEMENT_NODE:
1674 if (cur->content != NULL) {
1675 free(cur->content);
1676 cur->content = NULL;
1677 }
1678 if (cur->childs != NULL) xmlFreeNode(cur->childs);
1679 cur->childs = xmlStringGetNodeList(cur->doc, content);
1680 break;
1681 case XML_ATTRIBUTE_NODE:
1682 break;
1683 case XML_TEXT_NODE:
1684 case XML_CDATA_SECTION_NODE:
1685 case XML_ENTITY_REF_NODE:
1686 case XML_ENTITY_NODE:
1687 case XML_PI_NODE:
1688 case XML_COMMENT_NODE:
1689 if (cur->content != NULL) free(cur->content);
1690 if (cur->childs != NULL) xmlFreeNode(cur->childs);
1691 if (content != NULL)
1692 cur->content = xmlStrdup(content);
1693 else
1694 cur->content = NULL;
1695 case XML_DOCUMENT_NODE:
1696 case XML_DOCUMENT_TYPE_NODE:
1697 break;
1698 case XML_NOTATION_NODE:
1699 break;
1700 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00001701}
1702
Daniel Veillard97b58771998-10-20 06:14:16 +00001703/**
1704 * xmlNodeSetContentLen:
1705 * @cur: the node being modified
1706 * @content: the new value of the content
1707 * @len: the size of @content
1708 *
1709 * Replace the content of a node.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001710 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001711void
1712xmlNodeSetContentLen(xmlNodePtr cur, const CHAR *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001713 if (cur == NULL) {
Daniel Veillard16253641998-10-28 22:58:05 +00001714 fprintf(stderr, "xmlNodeSetContentLen : node == NULL\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00001715 return;
1716 }
Daniel Veillard16253641998-10-28 22:58:05 +00001717 switch (cur->type) {
1718 case XML_DOCUMENT_FRAG_NODE:
1719 case XML_ELEMENT_NODE:
1720 if (cur->content != NULL) {
1721 free(cur->content);
1722 cur->content = NULL;
1723 }
1724 if (cur->childs != NULL) xmlFreeNode(cur->childs);
1725 cur->childs = xmlStringLenGetNodeList(cur->doc, content, len);
1726 break;
1727 case XML_ATTRIBUTE_NODE:
1728 break;
1729 case XML_TEXT_NODE:
1730 case XML_CDATA_SECTION_NODE:
1731 case XML_ENTITY_REF_NODE:
1732 case XML_ENTITY_NODE:
1733 case XML_PI_NODE:
1734 case XML_COMMENT_NODE:
1735 if (cur->content != NULL) free(cur->content);
1736 if (cur->childs != NULL) xmlFreeNode(cur->childs);
1737 if (content != NULL)
1738 cur->content = xmlStrndup(content, len);
1739 else
1740 cur->content = NULL;
1741 case XML_DOCUMENT_NODE:
1742 case XML_DOCUMENT_TYPE_NODE:
1743 break;
1744 case XML_NOTATION_NODE:
1745 if (cur->content != NULL) free(cur->content);
1746 if (content != NULL)
1747 cur->content = xmlStrndup(content, len);
1748 else
1749 cur->content = NULL;
1750 break;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001751 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00001752}
1753
Daniel Veillard97b58771998-10-20 06:14:16 +00001754/**
1755 * xmlNodeAddContentLen:
1756 * @cur: the node being modified
1757 * @content: extra content
1758 * @len: the size of @content
1759 *
1760 * Append the extra substring to the node content.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001761 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001762void
1763xmlNodeAddContentLen(xmlNodePtr cur, const CHAR *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001764 if (cur == NULL) {
Daniel Veillard16253641998-10-28 22:58:05 +00001765 fprintf(stderr, "xmlNodeAddContentLen : node == NULL\n");
1766 return;
1767 }
1768 if (len <= 0) return;
1769 switch (cur->type) {
1770 case XML_DOCUMENT_FRAG_NODE:
1771 case XML_ELEMENT_NODE: {
1772 xmlNodePtr last = NULL, new;
1773
1774 if (cur->childs != NULL) {
1775 last = cur->childs;
1776 while (last->next != NULL) last = last->next;
1777 } else {
1778 if (cur->content != NULL) {
1779 cur->childs = xmlStringGetNodeList(cur->doc, cur->content);
1780 free(cur->content);
1781 cur->content = NULL;
1782 if (cur->childs != NULL) {
1783 last = cur->childs;
1784 while (last->next != NULL) last = last->next;
1785 }
1786 }
1787 }
1788 new = xmlStringLenGetNodeList(cur->doc, content, len);
1789 if (new != NULL) {
1790 xmlAddChild(cur, new);
1791 if ((last != NULL) && (last->next == new))
1792 xmlTextMerge(last, new);
1793 }
1794 break;
1795 }
1796 case XML_ATTRIBUTE_NODE:
1797 break;
1798 case XML_TEXT_NODE:
1799 case XML_CDATA_SECTION_NODE:
1800 case XML_ENTITY_REF_NODE:
1801 case XML_ENTITY_NODE:
1802 case XML_PI_NODE:
1803 case XML_COMMENT_NODE:
1804 if (content != NULL)
1805 cur->content = xmlStrncat(cur->content, content, len);
1806 case XML_DOCUMENT_NODE:
1807 case XML_DOCUMENT_TYPE_NODE:
1808 break;
1809 case XML_NOTATION_NODE:
1810 if (content != NULL)
1811 cur->content = xmlStrncat(cur->content, content, len);
1812 break;
1813 }
1814}
1815
1816/**
1817 * xmlNodeAddContent:
1818 * @cur: the node being modified
1819 * @content: extra content
1820 *
1821 * Append the extra substring to the node content.
1822 */
1823void
1824xmlNodeAddContent(xmlNodePtr cur, const CHAR *content) {
1825 int len;
1826
1827 if (cur == NULL) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001828 fprintf(stderr, "xmlNodeAddContent : node == NULL\n");
1829 return;
1830 }
Daniel Veillard16253641998-10-28 22:58:05 +00001831 if (content == NULL) return;
1832 len = xmlStrlen(content);
1833 xmlNodeAddContentLen(cur, content, len);
1834}
1835
1836/**
1837 * xmlTextMerge:
1838 * @first: the first text node
1839 * @second: the second text node being merged
1840 *
1841 * Merge two text nodes into one
1842 * Return values: the first text node augmented
1843 */
1844xmlNodePtr
1845xmlTextMerge(xmlNodePtr first, xmlNodePtr second) {
1846 if (first == NULL) return(second);
1847 if (second == NULL) return(first);
1848 if (first->type != XML_TEXT_NODE) return(first);
1849 if (second->type != XML_TEXT_NODE) return(first);
1850 xmlNodeAddContent(first, second->content);
1851 xmlUnlinkNode(second);
1852 xmlFreeNode(second);
1853 return(first);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001854}
1855
Daniel Veillard97b58771998-10-20 06:14:16 +00001856/**
1857 * xmlSearchNs:
1858 * @doc: the document
1859 * @node: the current node
1860 * @nameSpace: the namespace string
Daniel Veillard260a68f1998-08-13 03:39:55 +00001861 *
Daniel Veillard97b58771998-10-20 06:14:16 +00001862 * Search a Ns registered under a given name space for a document.
1863 * recurse on the parents until it finds the defined namespace
1864 * or return NULL otherwise.
1865 * @nameSpace can be NULL, this is a search for the default namespace.
1866 * return values: the namespace pointer or NULL.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001867 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001868xmlNsPtr
1869xmlSearchNs(xmlDocPtr doc, xmlNodePtr node, const CHAR *nameSpace) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001870 xmlNsPtr cur;
1871
1872 while (node != NULL) {
1873 cur = node->nsDef;
1874 while (cur != NULL) {
1875 if ((cur->prefix == NULL) && (nameSpace == NULL))
1876 return(cur);
1877 if ((cur->prefix != NULL) && (nameSpace != NULL) &&
1878 (!xmlStrcmp(cur->prefix, nameSpace)))
1879 return(cur);
1880 cur = cur->next;
1881 }
1882 node = node->parent;
1883 }
1884 if (doc != NULL) {
1885 cur = doc->oldNs;
1886 while (cur != NULL) {
1887 if ((cur->prefix != NULL) && (nameSpace != NULL) &&
1888 (!xmlStrcmp(cur->prefix, nameSpace)))
1889 return(cur);
1890 cur = cur->next;
1891 }
1892 }
1893 return(NULL);
1894}
1895
Daniel Veillard97b58771998-10-20 06:14:16 +00001896/**
1897 * xmlSearchNsByHref:
1898 * @doc: the document
1899 * @node: the current node
1900 * @href: the namespace value
1901 *
1902 * Search a Ns aliasing a given URI. Recurse on the parents until it finds
1903 * the defined namespace or return NULL otherwise.
1904 * return values: the namespace pointer or NULL.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001905 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001906xmlNsPtr
1907xmlSearchNsByHref(xmlDocPtr doc, xmlNodePtr node, const CHAR *href) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001908 xmlNsPtr cur;
1909
1910 while (node != NULL) {
1911 cur = node->nsDef;
1912 while (cur != NULL) {
1913 if ((cur->href != NULL) && (href != NULL) &&
1914 (!xmlStrcmp(cur->href, href)))
1915 return(cur);
1916 cur = cur->next;
1917 }
1918 node = node->parent;
1919 }
1920 if (doc != NULL) {
1921 cur = doc->oldNs;
1922 while (cur != NULL) {
1923 if ((cur->href != NULL) && (href != NULL) &&
1924 (!xmlStrcmp(cur->href, href)))
1925 return(cur);
1926 cur = cur->next;
1927 }
1928 }
1929 return(NULL);
1930}
1931
Daniel Veillard97b58771998-10-20 06:14:16 +00001932/**
1933 * xmlGetProp:
1934 * @node: the node
1935 * @name: the attribute name
1936 *
1937 * Search and get the value of an attribute associated to a node
Daniel Veillardccb09631998-10-27 06:21:04 +00001938 * This does the entity substitution.
Daniel Veillard97b58771998-10-20 06:14:16 +00001939 * return values: the attribute value or NULL if not found.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001940 */
1941const CHAR *xmlGetProp(xmlNodePtr node, const CHAR *name) {
1942 xmlAttrPtr prop = node->properties;
1943
1944 while (prop != NULL) {
Daniel Veillardccb09631998-10-27 06:21:04 +00001945 if (!xmlStrcmp(prop->name, name))
1946 return(xmlNodeListGetString(node->doc, prop->val, 1));
Daniel Veillard260a68f1998-08-13 03:39:55 +00001947 prop = prop->next;
1948 }
1949 return(NULL);
1950}
1951
Daniel Veillard97b58771998-10-20 06:14:16 +00001952/**
Daniel Veillardccb09631998-10-27 06:21:04 +00001953 * xmlSetProp:
Daniel Veillard97b58771998-10-20 06:14:16 +00001954 * @node: the node
1955 * @name: the attribute name
1956 * @value: the attribute value
1957 *
1958 * Set (or reset) an attribute carried by a node.
1959 * return values: the attribute pointer.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001960 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001961xmlAttrPtr
1962xmlSetProp(xmlNodePtr node, const CHAR *name, const CHAR *value) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001963 xmlAttrPtr prop = node->properties;
1964
1965 while (prop != NULL) {
1966 if (!xmlStrcmp(prop->name, name)) {
Daniel Veillardccb09631998-10-27 06:21:04 +00001967 if (prop->val != NULL)
1968 xmlFreeNode(prop->val);
1969 prop->val = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001970 if (value != NULL)
Daniel Veillardccb09631998-10-27 06:21:04 +00001971 prop->val = xmlStringGetNodeList(node->doc, value);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001972 return(prop);
1973 }
1974 prop = prop->next;
1975 }
1976 prop = xmlNewProp(node, name, value);
1977 return(prop);
1978}
1979
Daniel Veillard97b58771998-10-20 06:14:16 +00001980/**
1981 * xmlNodeIsText:
1982 * @node: the node
1983 *
1984 * Is this node a Text node ?
1985 * return values: 1 yes, 0 no
Daniel Veillard260a68f1998-08-13 03:39:55 +00001986 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001987int
1988xmlNodeIsText(xmlNodePtr node) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001989 if (node == NULL) return(0);
1990
Daniel Veillard0bef1311998-10-14 02:36:47 +00001991 if (node->type == XML_TEXT_NODE) return(1);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001992 return(0);
1993}
1994
Daniel Veillard97b58771998-10-20 06:14:16 +00001995/**
1996 * xmlNodeIsText:
1997 * @node: the node
1998 * @content: the content
1999 * @len: @content lenght
2000 *
2001 * Concat the given string at the end of the existing node content
Daniel Veillard260a68f1998-08-13 03:39:55 +00002002 */
Daniel Veillard97b58771998-10-20 06:14:16 +00002003
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002004void
2005xmlTextConcat(xmlNodePtr node, const CHAR *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002006 if (node == NULL) return;
2007
Daniel Veillard0bef1311998-10-14 02:36:47 +00002008 if (node->type != XML_TEXT_NODE) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002009 fprintf(stderr, "xmlTextConcat: node is not text\n");
2010 return;
2011 }
2012 node->content = xmlStrncat(node->content, content, len);
2013}
2014
2015/************************************************************************
2016 * *
2017 * Output : to a FILE or in memory *
2018 * *
2019 ************************************************************************/
2020
Daniel Veillard260a68f1998-08-13 03:39:55 +00002021static CHAR *buffer = NULL;
2022static int buffer_index = 0;
2023static int buffer_size = 0;
2024
Daniel Veillard97b58771998-10-20 06:14:16 +00002025/**
2026 * xmlBufferWriteCHAR:
2027 * @string: the string to add
2028 *
2029 * routine which manage and grows an output buffer. This one add
2030 * CHARs at the end of the array.
2031 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002032void
2033xmlBufferWriteCHAR(const CHAR *string) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002034 const CHAR *cur;
2035
2036 if (buffer == NULL) {
2037 buffer_size = 50000;
2038 buffer = (CHAR *) malloc(buffer_size * sizeof(CHAR));
2039 if (buffer == NULL) {
2040 fprintf(stderr, "xmlBufferWrite : out of memory!\n");
2041 exit(1);
2042 }
2043 }
2044
2045 if (string == NULL) return;
2046 for (cur = string;*cur != 0;cur++) {
2047 if (buffer_index + 10 >= buffer_size) {
2048 buffer_size *= 2;
2049 buffer = (CHAR *) realloc(buffer, buffer_size * sizeof(CHAR));
2050 if (buffer == NULL) {
2051 fprintf(stderr, "xmlBufferWrite : out of memory!\n");
2052 exit(1);
2053 }
2054 }
2055 buffer[buffer_index++] = *cur;
2056 }
2057 buffer[buffer_index] = 0;
2058}
2059
Daniel Veillard97b58771998-10-20 06:14:16 +00002060/**
2061 * xmlBufferWriteChar:
2062 * @string: the string to add
2063 *
2064 * routine which manage and grows an output buffer. This one add
2065 * C chars at the end of the array.
2066 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002067void
2068xmlBufferWriteChar(const char *string) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002069 const char *cur;
2070
2071 if (buffer == NULL) {
2072 buffer_size = 50000;
2073 buffer = (CHAR *) malloc(buffer_size * sizeof(CHAR));
2074 if (buffer == NULL) {
2075 fprintf(stderr, "xmlBufferWrite : out of memory!\n");
2076 exit(1);
2077 }
2078 }
2079
2080 if (string == NULL) return;
2081 for (cur = string;*cur != 0;cur++) {
2082 if (buffer_index + 10 >= buffer_size) {
2083 buffer_size *= 2;
2084 buffer = (CHAR *) realloc(buffer, buffer_size * sizeof(CHAR));
2085 if (buffer == NULL) {
2086 fprintf(stderr, "xmlBufferWrite : out of memory!\n");
2087 exit(1);
2088 }
2089 }
2090 buffer[buffer_index++] = *cur;
2091 }
2092 buffer[buffer_index] = 0;
2093}
2094
Daniel Veillard97b58771998-10-20 06:14:16 +00002095/**
2096 * xmlGlobalNsDump:
2097 * @cur: a namespace
2098 *
2099 * Dump a global Namespace, this is the old version based on PIs.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002100 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002101static void
2102xmlGlobalNsDump(xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002103 if (cur == NULL) {
2104 fprintf(stderr, "xmlGlobalNsDump : Ns == NULL\n");
2105 return;
2106 }
2107 if (cur->type == XML_GLOBAL_NAMESPACE) {
2108 xmlBufferWriteChar("<?namespace");
2109 if (cur->href != NULL) {
2110 xmlBufferWriteChar(" href=\"");
2111 xmlBufferWriteCHAR(cur->href);
2112 xmlBufferWriteChar("\"");
2113 }
2114 if (cur->prefix != NULL) {
2115 xmlBufferWriteChar(" AS=\"");
2116 xmlBufferWriteCHAR(cur->prefix);
2117 xmlBufferWriteChar("\"");
2118 }
2119 xmlBufferWriteChar("?>\n");
2120 }
2121}
2122
Daniel Veillard97b58771998-10-20 06:14:16 +00002123/**
2124 * xmlGlobalNsListDump:
2125 * @cur: the first namespace
2126 *
2127 * Dump a list of global Namespace, this is the old version based on PIs.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002128 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002129static void
2130xmlGlobalNsListDump(xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002131 while (cur != NULL) {
2132 xmlGlobalNsDump(cur);
2133 cur = cur->next;
2134 }
2135}
2136
Daniel Veillard97b58771998-10-20 06:14:16 +00002137/**
2138 * xmlNsDump:
2139 * @cur: a namespace
2140 *
Daniel Veillard260a68f1998-08-13 03:39:55 +00002141 * Dump a local Namespace definition.
Daniel Veillard97b58771998-10-20 06:14:16 +00002142 * Should be called in the context of attributes dumps.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002143 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002144static void
2145xmlNsDump(xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002146 if (cur == NULL) {
2147 fprintf(stderr, "xmlNsDump : Ns == NULL\n");
2148 return;
2149 }
2150 if (cur->type == XML_LOCAL_NAMESPACE) {
2151 /* Within the context of an element attributes */
2152 if (cur->prefix != NULL) {
2153 xmlBufferWriteChar(" xmlns:");
2154 xmlBufferWriteCHAR(cur->prefix);
2155 } else
2156 xmlBufferWriteChar(" xmlns");
2157 xmlBufferWriteChar("=\"");
2158 xmlBufferWriteCHAR(cur->href);
2159 xmlBufferWriteChar("\"");
2160 }
2161}
2162
Daniel Veillard97b58771998-10-20 06:14:16 +00002163/**
2164 * xmlNsListDump:
2165 * @cur: the first namespace
2166 *
2167 * Dump a list of local Namespace definitions.
2168 * Should be called in the context of attributes dumps.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002169 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002170static void
2171xmlNsListDump(xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002172 while (cur != NULL) {
2173 xmlNsDump(cur);
2174 cur = cur->next;
2175 }
2176}
2177
Daniel Veillard97b58771998-10-20 06:14:16 +00002178/**
2179 * xmlDtdDump:
2180 * @doc: the document
2181 *
2182 * Dump the XML document DTD, if any.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002183 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002184static void
2185xmlDtdDump(xmlDocPtr doc) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002186 xmlDtdPtr cur = doc->dtd;
2187
2188 if (cur == NULL) {
2189 fprintf(stderr, "xmlDtdDump : DTD == NULL\n");
2190 return;
2191 }
2192 xmlBufferWriteChar("<!DOCTYPE ");
2193 xmlBufferWriteCHAR(cur->name);
2194 if (cur->ExternalID != NULL) {
2195 xmlBufferWriteChar(" PUBLIC \"");
2196 xmlBufferWriteCHAR(cur->ExternalID);
2197 xmlBufferWriteChar("\" \"");
2198 xmlBufferWriteCHAR(cur->SystemID);
2199 xmlBufferWriteChar("\"");
2200 } else if (cur->SystemID != NULL) {
2201 xmlBufferWriteChar(" SYSTEM \"");
2202 xmlBufferWriteCHAR(cur->SystemID);
2203 xmlBufferWriteChar("\"");
2204 }
2205 if ((cur->entities == NULL) && (doc->entities == NULL)) {
2206 xmlBufferWriteChar(">\n");
2207 return;
2208 }
2209 xmlBufferWriteChar(" [\n");
2210 if (cur->entities != NULL)
2211 xmlDumpEntitiesTable((xmlEntitiesTablePtr) cur->entities);
2212 if (doc->entities != NULL)
2213 xmlDumpEntitiesTable((xmlEntitiesTablePtr) doc->entities);
2214 xmlBufferWriteChar("]");
2215
2216 /* TODO !!! a lot more things to dump ... */
2217 xmlBufferWriteChar(">\n");
2218}
2219
Daniel Veillard97b58771998-10-20 06:14:16 +00002220/**
2221 * xmlAttrDump:
2222 * @doc: the document
2223 * @cur: the attribute pointer
2224 *
2225 * Dump an XML attribute
Daniel Veillard260a68f1998-08-13 03:39:55 +00002226 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002227static void
2228xmlAttrDump(xmlDocPtr doc, xmlAttrPtr cur) {
Daniel Veillardccb09631998-10-27 06:21:04 +00002229 CHAR *value;
2230
Daniel Veillard260a68f1998-08-13 03:39:55 +00002231 if (cur == NULL) {
2232 fprintf(stderr, "xmlAttrDump : property == NULL\n");
2233 return;
2234 }
2235 xmlBufferWriteChar(" ");
2236 xmlBufferWriteCHAR(cur->name);
Daniel Veillardccb09631998-10-27 06:21:04 +00002237 value = xmlNodeListGetString(doc, cur->val, 0);
2238 if (value) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002239 xmlBufferWriteChar("=\"");
Daniel Veillardccb09631998-10-27 06:21:04 +00002240 xmlBufferWriteCHAR(value);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002241 xmlBufferWriteChar("\"");
Daniel Veillardccb09631998-10-27 06:21:04 +00002242 free(value);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002243 }
2244}
2245
Daniel Veillard97b58771998-10-20 06:14:16 +00002246/**
2247 * xmlAttrListDump:
2248 * @doc: the document
2249 * @cur: the first attribute pointer
2250 *
2251 * Dump a list of XML attributes
Daniel Veillard260a68f1998-08-13 03:39:55 +00002252 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002253static void
2254xmlAttrListDump(xmlDocPtr doc, xmlAttrPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002255 if (cur == NULL) {
2256 fprintf(stderr, "xmlAttrListDump : property == NULL\n");
2257 return;
2258 }
2259 while (cur != NULL) {
2260 xmlAttrDump(doc, cur);
2261 cur = cur->next;
2262 }
2263}
2264
Daniel Veillard260a68f1998-08-13 03:39:55 +00002265
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002266static void
2267xmlNodeDump(xmlDocPtr doc, xmlNodePtr cur, int level);
Daniel Veillard97b58771998-10-20 06:14:16 +00002268/**
2269 * xmlNodeListDump:
2270 * @doc: the document
2271 * @cur: the first node
2272 * @level: the imbrication level for indenting
2273 *
2274 * Dump an XML node list, recursive behaviour,children are printed too.
2275 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002276static void
2277xmlNodeListDump(xmlDocPtr doc, xmlNodePtr cur, int level) {
Daniel Veillardccb09631998-10-27 06:21:04 +00002278 int needIndent = 0, i;
2279
Daniel Veillard260a68f1998-08-13 03:39:55 +00002280 if (cur == NULL) {
2281 fprintf(stderr, "xmlNodeListDump : node == NULL\n");
2282 return;
2283 }
2284 while (cur != NULL) {
Daniel Veillardccb09631998-10-27 06:21:04 +00002285 if ((cur->type != XML_TEXT_NODE) &&
2286 (cur->type != XML_ENTITY_REF_NODE)) {
2287 if (!needIndent) {
2288 needIndent = 1;
2289 xmlBufferWriteChar("\n");
2290 }
2291 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002292 xmlNodeDump(doc, cur, level);
2293 cur = cur->next;
2294 }
Daniel Veillardccb09631998-10-27 06:21:04 +00002295 if ((xmlIndentTreeOutput) && (needIndent))
2296 for (i = 1;i < level;i++)
2297 xmlBufferWriteChar(" ");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002298}
2299
Daniel Veillard97b58771998-10-20 06:14:16 +00002300/**
Daniel Veillardccb09631998-10-27 06:21:04 +00002301 * xmlNodeDump:
Daniel Veillard97b58771998-10-20 06:14:16 +00002302 * @doc: the document
2303 * @cur: the current node
2304 * @level: the imbrication level for indenting
2305 *
2306 * Dump an XML node, recursive behaviour,children are printed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002307 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002308static void
2309xmlNodeDump(xmlDocPtr doc, xmlNodePtr cur, int level) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002310 int i;
2311
2312 if (cur == NULL) {
2313 fprintf(stderr, "xmlNodeDump : node == NULL\n");
2314 return;
2315 }
Daniel Veillard0bef1311998-10-14 02:36:47 +00002316 if (cur->type == XML_TEXT_NODE) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002317 if (cur->content != NULL)
2318 xmlBufferWriteCHAR(xmlEncodeEntities(doc, cur->content));
2319 return;
2320 }
Daniel Veillard0bef1311998-10-14 02:36:47 +00002321 if (cur->type == XML_COMMENT_NODE) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002322 if (cur->content != NULL) {
2323 xmlBufferWriteChar("<!--");
2324 xmlBufferWriteCHAR(cur->content);
2325 xmlBufferWriteChar("-->");
2326 }
2327 return;
2328 }
Daniel Veillardccb09631998-10-27 06:21:04 +00002329 if (cur->type == XML_ENTITY_REF_NODE) {
2330 xmlBufferWriteChar("&");
2331 xmlBufferWriteCHAR(cur->name);
2332 xmlBufferWriteChar(";");
2333 return;
2334 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002335 if (xmlIndentTreeOutput)
2336 for (i = 0;i < level;i++)
2337 xmlBufferWriteChar(" ");
2338
2339 xmlBufferWriteChar("<");
2340 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
2341 xmlBufferWriteCHAR(cur->ns->prefix);
2342 xmlBufferWriteChar(":");
2343 }
2344
2345 xmlBufferWriteCHAR(cur->name);
2346 if (cur->nsDef)
2347 xmlNsListDump(cur->nsDef);
2348 if (cur->properties != NULL)
2349 xmlAttrListDump(doc, cur->properties);
2350
2351 if ((cur->content == NULL) && (cur->childs == NULL)) {
2352 xmlBufferWriteChar("/>\n");
2353 return;
2354 }
2355 xmlBufferWriteChar(">");
2356 if (cur->content != NULL)
2357 xmlBufferWriteCHAR(xmlEncodeEntities(doc, cur->content));
2358 if (cur->childs != NULL) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002359 xmlNodeListDump(doc, cur->childs, level + 1);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002360 }
2361 xmlBufferWriteChar("</");
2362 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
2363 xmlBufferWriteCHAR(cur->ns->prefix);
2364 xmlBufferWriteChar(":");
2365 }
2366
2367 xmlBufferWriteCHAR(cur->name);
2368 xmlBufferWriteChar(">\n");
2369}
2370
Daniel Veillard97b58771998-10-20 06:14:16 +00002371/**
2372 * xmlDocContentDump:
2373 * @cur: the document
2374 *
2375 * Dump an XML document.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002376 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002377static void
2378xmlDocContentDump(xmlDocPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002379 if (oldXMLWDcompatibility)
2380 xmlBufferWriteChar("<?XML version=\"");
2381 else
2382 xmlBufferWriteChar("<?xml version=\"");
2383 xmlBufferWriteCHAR(cur->version);
2384 xmlBufferWriteChar("\"");
2385 if (cur->encoding != NULL) {
2386 xmlBufferWriteChar(" encoding=\"");
2387 xmlBufferWriteCHAR(cur->encoding);
2388 xmlBufferWriteChar("\"");
2389 }
2390 switch (cur->standalone) {
2391 case 0:
2392 xmlBufferWriteChar(" standalone=\"no\"");
2393 break;
2394 case 1:
2395 xmlBufferWriteChar(" standalone=\"yes\"");
2396 break;
2397 }
2398 xmlBufferWriteChar("?>\n");
2399 if ((cur->dtd != NULL) || (cur->entities != NULL))
2400 xmlDtdDump(cur);
2401 if (cur->root != NULL) {
2402 /* global namespace definitions, the old way */
2403 if (oldXMLWDcompatibility)
2404 xmlGlobalNsListDump(cur->oldNs);
2405 else
2406 xmlUpgradeOldNs(cur);
2407 xmlNodeDump(cur, cur->root, 0);
2408 }
2409}
2410
Daniel Veillard97b58771998-10-20 06:14:16 +00002411/**
2412 * xmlDocDumpMemory:
2413 * @cur: the document
2414 * @mem: OUT: the memory pointer
2415 * @size: OUT: the memory lenght
2416 *
2417 * Dump an XML document in memory and return the CHAR * and it's size.
2418 * It's up to the caller to free the memory.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002419 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002420void
2421xmlDocDumpMemory(xmlDocPtr cur, CHAR**mem, int *size) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002422 if (cur == NULL) {
2423 fprintf(stderr, "xmlDocDump : document == NULL\n");
2424 *mem = NULL;
2425 *size = 0;
2426 return;
2427 }
2428 buffer_index = 0;
2429 xmlDocContentDump(cur);
2430
2431 *mem = buffer;
2432 *size = buffer_index;
2433}
2434
Daniel Veillard97b58771998-10-20 06:14:16 +00002435/**
2436 * xmlGetDocCompressMode:
2437 * @doc: the document
2438 *
2439 * get the compression ratio for a document, ZLIB based
2440 * return values: 0 (uncompressed) to 9 (max compression)
Daniel Veillard151b1b01998-09-23 00:49:46 +00002441 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002442int
2443 xmlGetDocCompressMode (xmlDocPtr doc) {
Daniel Veillard15a8df41998-09-24 19:15:06 +00002444 if (doc == NULL) return(-1);
2445 return(doc->compression);
2446}
2447
Daniel Veillard97b58771998-10-20 06:14:16 +00002448/**
2449 * xmlSetDocCompressMode:
2450 * @doc: the document
2451 * @mode: the compression ratio
2452 *
2453 * set the compression ratio for a document, ZLIB based
2454 * Correct values: 0 (uncompressed) to 9 (max compression)
2455 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002456void
2457xmlSetDocCompressMode (xmlDocPtr doc, int mode) {
Daniel Veillard15a8df41998-09-24 19:15:06 +00002458 if (doc == NULL) return;
2459 if (mode < 0) doc->compression = 0;
2460 else if (mode > 9) doc->compression = 9;
2461 else doc->compression = mode;
2462}
2463
Daniel Veillard97b58771998-10-20 06:14:16 +00002464/**
2465 * xmlGetCompressMode:
2466 *
2467 * get the default compression mode used, ZLIB based.
2468 * return values: 0 (uncompressed) to 9 (max compression)
Daniel Veillard15a8df41998-09-24 19:15:06 +00002469 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002470int
2471 xmlGetCompressMode(void) {
Daniel Veillard151b1b01998-09-23 00:49:46 +00002472 return(xmlCompressMode);
2473}
Daniel Veillard97b58771998-10-20 06:14:16 +00002474
2475/**
2476 * xmlSetCompressMode:
2477 * @mode: the compression ratio
2478 *
2479 * set the default compression mode used, ZLIB based
2480 * Correct values: 0 (uncompressed) to 9 (max compression)
2481 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002482void
2483xmlSetCompressMode(int mode) {
Daniel Veillard151b1b01998-09-23 00:49:46 +00002484 if (mode < 0) xmlCompressMode = 0;
Daniel Veillard15a8df41998-09-24 19:15:06 +00002485 else if (mode > 9) xmlCompressMode = 9;
Daniel Veillard151b1b01998-09-23 00:49:46 +00002486 else xmlCompressMode = mode;
2487}
2488
Daniel Veillard97b58771998-10-20 06:14:16 +00002489/**
2490 * xmlDocDump:
2491 * @f: the FILE*
2492 * @cur: the document
2493 *
2494 * Dump an XML document to an open FILE.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002495 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002496void
2497xmlDocDump(FILE *f, xmlDocPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002498 if (cur == NULL) {
2499 fprintf(stderr, "xmlDocDump : document == NULL\n");
2500 return;
2501 }
2502 buffer_index = 0;
2503 xmlDocContentDump(cur);
2504
2505 fwrite(buffer, sizeof(CHAR), buffer_index, f);
2506}
2507
Daniel Veillard97b58771998-10-20 06:14:16 +00002508/**
2509 * xmlSaveFile:
2510 * @filename: the filename
2511 * @cur: the document
2512 *
2513 * Dump an XML document to a file. Will use compression if
2514 * compiled in and enabled.
2515 * returns: the number of file written or -1 in case of failure.
Daniel Veillard151b1b01998-09-23 00:49:46 +00002516 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002517int
2518xmlSaveFile(const char *filename, xmlDocPtr cur) {
Daniel Veillard151b1b01998-09-23 00:49:46 +00002519#ifdef HAVE_ZLIB_H
2520 gzFile zoutput = NULL;
2521 char mode[15];
2522#endif
Daniel Veillardccb09631998-10-27 06:21:04 +00002523 FILE *output = NULL;
Daniel Veillard151b1b01998-09-23 00:49:46 +00002524 int ret;
2525
2526#ifdef HAVE_ZLIB_H
Daniel Veillarddc3dd9d1998-09-24 19:25:54 +00002527 if ((cur->compression > 0) && (cur->compression <= 9)) {
2528 sprintf(mode, "w%d", cur->compression);
Daniel Veillard151b1b01998-09-23 00:49:46 +00002529 zoutput = gzopen(filename, mode);
2530 }
2531 if (zoutput == NULL) {
2532#endif
2533 output = fopen(filename, "w");
2534 if (output == NULL) return(-1);
2535#ifdef HAVE_ZLIB_H
2536 }
2537#endif
2538
2539 /*
2540 * save the content to a temp buffer.
2541 */
2542 buffer_index = 0;
2543 xmlDocContentDump(cur);
2544
2545#ifdef HAVE_ZLIB_H
2546 if (zoutput != NULL) {
2547 ret = gzwrite(zoutput, buffer, sizeof(CHAR) * buffer_index);
2548 gzclose(zoutput);
2549 return(ret);
2550 }
2551#endif
2552 ret = fwrite(buffer, sizeof(CHAR), buffer_index, output);
2553 fclose(output);
2554 return(ret * sizeof(CHAR));
2555}
2556