blob: 4de4ee57b53310c6f7474b3e65c7c7faaf170867 [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) {
136 fprintf(stderr, "xmlNewNs : malloc failed\n");
137 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
237 if (doc->dtd != NULL) {
238 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) {
247 fprintf(stderr, "xmlNewNs : malloc failed\n");
248 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;
265 doc->dtd = cur;
266
267 return(cur);
268}
269
Daniel Veillard97b58771998-10-20 06:14:16 +0000270/**
271 * xmlFreeDtd:
272 * @cur: the DTD structure to free up
273 *
274 * Free a DTD structure.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000275 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000276void
277xmlFreeDtd(xmlDtdPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000278 if (cur == NULL) {
279 fprintf(stderr, "xmlFreeDtd : DTD == NULL\n");
280 return;
281 }
282 if (cur->name != NULL) free((char *) cur->name);
283 if (cur->SystemID != NULL) free((char *) cur->SystemID);
284 if (cur->ExternalID != NULL) free((char *) cur->ExternalID);
285 if (cur->elements != NULL)
286 fprintf(stderr, "xmlFreeDtd: cur->elements != NULL !!! \n");
287 if (cur->entities != NULL)
288 xmlFreeEntitiesTable((xmlEntitiesTablePtr) cur->entities);
289 memset(cur, -1, sizeof(xmlDtd));
290 free(cur);
291}
292
Daniel Veillard97b58771998-10-20 06:14:16 +0000293/**
294 * xmlNewDoc:
295 * @version: CHAR string giving the version of XML "1.0"
296 *
297 * Create a new document
Daniel Veillard260a68f1998-08-13 03:39:55 +0000298 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000299xmlDocPtr
300xmlNewDoc(const CHAR *version) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000301 xmlDocPtr cur;
302
303 if (version == NULL) {
304 fprintf(stderr, "xmlNewDoc : version == NULL\n");
305 return(NULL);
306 }
307
308 /*
309 * Allocate a new document and fill the fields.
310 */
311 cur = (xmlDocPtr) malloc(sizeof(xmlDoc));
312 if (cur == NULL) {
313 fprintf(stderr, "xmlNewDoc : malloc failed\n");
314 return(NULL);
315 }
316
Daniel Veillard33942841998-10-18 19:12:41 +0000317 cur->type = XML_DOCUMENT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000318 cur->version = xmlStrdup(version);
319 cur->name = NULL;
320 cur->root = NULL;
321 cur->dtd = NULL;
322 cur->oldNs = NULL;
323 cur->encoding = NULL;
324 cur->entities = NULL;
325 cur->standalone = -1;
Daniel Veillard15a8df41998-09-24 19:15:06 +0000326 cur->compression = xmlCompressMode;
Daniel Veillard27fb0751998-10-17 06:47:46 +0000327#ifndef WITHOUT_CORBA
328 cur->_private = NULL;
329 cur->vepv = NULL;
330#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000331 return(cur);
332}
333
Daniel Veillard97b58771998-10-20 06:14:16 +0000334/**
335 * xmlFreeDoc:
336 * @cur: pointer to the document
337 * @:
338 *
339 * Free up all the structures used by a document, tree included.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000340 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000341void
342xmlFreeDoc(xmlDocPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000343 if (cur == NULL) {
344 fprintf(stderr, "xmlFreeDoc : document == NULL\n");
345 return;
346 }
347 free((char *) cur->version);
348 if (cur->name != NULL) free((char *) cur->name);
349 if (cur->encoding != NULL) free((char *) cur->encoding);
350 if (cur->root != NULL) xmlFreeNode(cur->root);
351 if (cur->dtd != NULL) xmlFreeDtd(cur->dtd);
352 if (cur->entities != NULL)
353 xmlFreeEntitiesTable((xmlEntitiesTablePtr) cur->entities);
354 memset(cur, -1, sizeof(xmlDoc));
355 free(cur);
356}
357
Daniel Veillard97b58771998-10-20 06:14:16 +0000358/**
Daniel Veillardccb09631998-10-27 06:21:04 +0000359 * xmlStringGetNodeList:
360 * @doc: the document
361 * @value: the value of the attribute
362 *
363 * Parse the value string and build the node list associated. Should
364 * produce a flat tree with only TEXTs and ENTITY_REFs.
365 * return values: a pointer to the first child
366 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000367xmlNodePtr
368xmlStringGetNodeList(xmlDocPtr doc, const CHAR *value) {
Daniel Veillardccb09631998-10-27 06:21:04 +0000369 xmlNodePtr ret = NULL, last = NULL;
370 xmlNodePtr node;
371 CHAR *val;
372 const CHAR *cur = value;
373 const CHAR *q;
374
375 if (value == NULL) return(NULL);
376
377 q = cur;
378 while (*cur != 0) {
379 if (*cur == '&') {
380 if (cur != q) {
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000381 node = xmlNewDocTextLen(doc, q, cur - q);
Daniel Veillardccb09631998-10-27 06:21:04 +0000382 if (node == NULL) return(ret);
383 if (last == NULL)
384 last = ret = node;
385 else {
386 last->next = node;
387 last = node;
388 }
389 }
390 cur++;
391 q = cur;
392 while ((*cur != 0) && (*cur != ';')) cur++;
393 if (*cur == 0) {
394 fprintf(stderr,
395 "xmlStringGetNodeList: unterminated entity %30s\n", q);
396 return(ret);
397 }
398 if (cur != q) {
399 val = xmlStrndup(q, cur - q);
400 node = xmlNewReference(doc, val);
401 if (node == NULL) return(ret);
402 if (last == NULL)
403 last = ret = node;
404 else {
405 last->next = node;
406 last = node;
407 }
408 free(val);
409 }
410 cur++;
411 q = cur;
412 } else
413 cur++;
414 }
415 if (cur != q) {
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000416 node = xmlNewDocTextLen(doc, q, cur - q);
Daniel Veillardccb09631998-10-27 06:21:04 +0000417 if (node == NULL) return(ret);
418 if (last == NULL)
419 last = ret = node;
420 else {
421 last->next = node;
422 last = node;
423 }
424 }
425 return(ret);
426}
427
428/**
429 * xmlNodeListGetString:
430 * @doc: the document
431 * @list: a Node list
432 * @inLine: should we replace entity contents or show their external form
433 *
434 * Returns the string equivalent to the text contained in the Node list
435 * made of TEXTs and ENTITY_REFs
436 * return values: a pointer to the string copy, the calller must free it.
437 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000438CHAR *
439xmlNodeListGetString(xmlDocPtr doc, xmlNodePtr list, int inLine) {
Daniel Veillardccb09631998-10-27 06:21:04 +0000440 xmlNodePtr node = list;
441 CHAR *ret = NULL;
442 xmlEntityPtr ent;
443
444 if (list == NULL) return(NULL);
445
446 while (node != NULL) {
447 if (node->type == XML_TEXT_NODE) {
448 if (inLine)
449 ret = xmlStrcat(ret, node->content);
450 else
451 ret = xmlStrcat(ret, xmlEncodeEntities(doc, node->content));
452 } else if (node->type == XML_ENTITY_REF_NODE) {
453 if (inLine) {
454 ent = xmlGetDocEntity(doc, node->name);
455 if (ent != NULL)
456 ret = xmlStrcat(ret, ent->content);
457 else
458 ret = xmlStrcat(ret, node->content);
459 } else {
460 CHAR buf[2];
461 buf[0] = '&'; buf[1] = 0;
462 ret = xmlStrncat(ret, buf, 1);
463 ret = xmlStrcat(ret, node->name);
464 buf[0] = ';'; buf[1] = 0;
465 ret = xmlStrncat(ret, buf, 1);
466 }
467 }
468#if 0
469 else {
470 fprintf(stderr, "xmlGetNodeListString : invalide node type %d\n",
471 node->type);
472 }
473#endif
474 node = node->next;
475 }
476 return(ret);
477}
478
479/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000480 * xmlNewProp:
481 * @node: the holding node
482 * @name: the name of the attribute
483 * @value: the value of the attribute
484 *
485 * Create a new property carried by a node.
486 * return values: a pointer to the attribute
Daniel Veillard260a68f1998-08-13 03:39:55 +0000487 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000488xmlAttrPtr
489xmlNewProp(xmlNodePtr node, const CHAR *name, const CHAR *value) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000490 xmlAttrPtr cur;
491
492 if (name == NULL) {
493 fprintf(stderr, "xmlNewProp : name == NULL\n");
494 return(NULL);
495 }
496
497 /*
498 * Allocate a new property and fill the fields.
499 */
500 cur = (xmlAttrPtr) malloc(sizeof(xmlAttr));
501 if (cur == NULL) {
502 fprintf(stderr, "xmlNewProp : malloc failed\n");
503 return(NULL);
504 }
505
Daniel Veillard33942841998-10-18 19:12:41 +0000506 cur->type = XML_ATTRIBUTE_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000507 cur->node = node;
508 cur->name = xmlStrdup(name);
509 if (value != NULL)
Daniel Veillardccb09631998-10-27 06:21:04 +0000510 cur->val = xmlStringGetNodeList(node->doc, value);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000511 else
Daniel Veillardccb09631998-10-27 06:21:04 +0000512 cur->val = NULL;
Daniel Veillard27fb0751998-10-17 06:47:46 +0000513#ifndef WITHOUT_CORBA
514 cur->_private = NULL;
515 cur->vepv = NULL;
516#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000517
518 /*
519 * Add it at the end to preserve parsing order ...
520 */
521 cur->next = NULL;
522 if (node != NULL) {
523 if (node->properties == NULL) {
524 node->properties = cur;
525 } else {
526 xmlAttrPtr prev = node->properties;
527
528 while (prev->next != NULL) prev = prev->next;
529 prev->next = cur;
530 }
531 }
532 return(cur);
533}
534
Daniel Veillard97b58771998-10-20 06:14:16 +0000535/**
Daniel Veillardccb09631998-10-27 06:21:04 +0000536 * xmlNewDocProp:
537 * @doc: the document
538 * @name: the name of the attribute
539 * @value: the value of the attribute
540 *
541 * Create a new property carried by a document.
542 * return values: a pointer to the attribute
543 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000544xmlAttrPtr
545xmlNewDocProp(xmlDocPtr doc, const CHAR *name, const CHAR *value) {
Daniel Veillardccb09631998-10-27 06:21:04 +0000546 xmlAttrPtr cur;
547
548 if (name == NULL) {
549 fprintf(stderr, "xmlNewProp : name == NULL\n");
550 return(NULL);
551 }
552
553 /*
554 * Allocate a new property and fill the fields.
555 */
556 cur = (xmlAttrPtr) malloc(sizeof(xmlAttr));
557 if (cur == NULL) {
558 fprintf(stderr, "xmlNewProp : malloc failed\n");
559 return(NULL);
560 }
561
562 cur->type = XML_ATTRIBUTE_NODE;
563 cur->node = NULL;
564 cur->name = xmlStrdup(name);
565 if (value != NULL)
566 cur->val = xmlStringGetNodeList(doc, value);
567 else
568 cur->val = NULL;
569#ifndef WITHOUT_CORBA
570 cur->_private = NULL;
571 cur->vepv = NULL;
572#endif
573
574 cur->next = NULL;
575 return(cur);
576}
577
578/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000579 * xmlFreePropList:
580 * @cur: the first property in the list
581 *
582 * Free a property and all its siblings, all the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000583 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000584void
585xmlFreePropList(xmlAttrPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000586 xmlAttrPtr next;
587 if (cur == NULL) {
588 fprintf(stderr, "xmlFreePropList : property == NULL\n");
589 return;
590 }
591 while (cur != NULL) {
592 next = cur->next;
593 xmlFreeProp(cur);
594 cur = next;
595 }
596}
597
Daniel Veillard97b58771998-10-20 06:14:16 +0000598/**
599 * xmlFreeProp:
600 * @cur: the first property in the list
601 *
602 * Free one property, all the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000603 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000604void
605xmlFreeProp(xmlAttrPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000606 if (cur == NULL) {
607 fprintf(stderr, "xmlFreeProp : property == NULL\n");
608 return;
609 }
610 if (cur->name != NULL) free((char *) cur->name);
Daniel Veillardccb09631998-10-27 06:21:04 +0000611 if (cur->val != NULL) xmlFreeNodeList(cur->val);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000612 memset(cur, -1, sizeof(xmlAttr));
613 free(cur);
614}
615
Daniel Veillard97b58771998-10-20 06:14:16 +0000616/**
617 * xmlNewNode:
618 * @ns: namespace if any
619 * @name: the node name
620 * @content: the text content if any
621 *
622 * Creation of a new node element. @ns and @content are optionnal (NULL).
Daniel Veillardccb09631998-10-27 06:21:04 +0000623 * If content is non NULL, a child list containing the TEXTs and
624 * ENTITY_REFs node will be created.
Daniel Veillard97b58771998-10-20 06:14:16 +0000625 * return values: a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000626 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000627xmlNodePtr
628xmlNewNode(xmlNsPtr ns, const CHAR *name) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000629 xmlNodePtr cur;
630
631 if (name == NULL) {
632 fprintf(stderr, "xmlNewNode : name == NULL\n");
633 return(NULL);
634 }
635
636 /*
637 * Allocate a new node and fill the fields.
638 */
639 cur = (xmlNodePtr) malloc(sizeof(xmlNode));
640 if (cur == NULL) {
641 fprintf(stderr, "xmlNewNode : malloc failed\n");
642 return(NULL);
643 }
644
Daniel Veillard33942841998-10-18 19:12:41 +0000645 cur->type = XML_ELEMENT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000646 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000647 cur->parent = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000648 cur->next = NULL;
649 cur->prev = NULL;
650 cur->childs = NULL;
651 cur->properties = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000652 cur->name = xmlStrdup(name);
653 cur->ns = ns;
654 cur->nsDef = NULL;
Daniel Veillardccb09631998-10-27 06:21:04 +0000655 cur->content = NULL;
Daniel Veillard27fb0751998-10-17 06:47:46 +0000656#ifndef WITHOUT_CORBA
657 cur->_private = NULL;
658 cur->vepv = NULL;
659#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000660 return(cur);
661}
662
Daniel Veillard97b58771998-10-20 06:14:16 +0000663/**
664 * xmlNewDocNode:
665 * @doc: the document
666 * @ns: namespace if any
667 * @name: the node name
668 * @content: the text content if any
669 *
670 * Creation of a new node element within a document. @ns and @content
671 * are optionnal (NULL).
672 * return values: a pointer to the new node object.
673 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000674xmlNodePtr
675xmlNewDocNode(xmlDocPtr doc, xmlNsPtr ns,
Daniel Veillard0bef1311998-10-14 02:36:47 +0000676 const CHAR *name, CHAR *content) {
677 xmlNodePtr cur;
678
Daniel Veillardccb09631998-10-27 06:21:04 +0000679 cur = xmlNewNode(ns, name);
680 if (cur != NULL) {
681 cur->doc = doc;
682 if (content != NULL)
683 cur->childs = xmlStringGetNodeList(doc, content);
684 }
Daniel Veillard0bef1311998-10-14 02:36:47 +0000685 return(cur);
686}
687
688
Daniel Veillard97b58771998-10-20 06:14:16 +0000689/**
690 * xmlNewText:
691 * @content: the text content
692 *
693 * Creation of a new text node.
694 * return values: a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000695 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000696xmlNodePtr
697xmlNewText(const CHAR *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000698 xmlNodePtr cur;
699
700 /*
701 * Allocate a new node and fill the fields.
702 */
703 cur = (xmlNodePtr) malloc(sizeof(xmlNode));
704 if (cur == NULL) {
705 fprintf(stderr, "xmlNewText : malloc failed\n");
706 return(NULL);
707 }
708
Daniel Veillard33942841998-10-18 19:12:41 +0000709 cur->type = XML_TEXT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000710 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000711 cur->parent = NULL;
712 cur->next = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000713 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000714 cur->childs = NULL;
715 cur->properties = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000716 cur->type = XML_TEXT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000717 cur->name = xmlStrdup(xmlStringText);
718 cur->ns = NULL;
719 cur->nsDef = NULL;
720 if (content != NULL)
721 cur->content = xmlStrdup(content);
722 else
723 cur->content = NULL;
724 return(cur);
725}
726
Daniel Veillard97b58771998-10-20 06:14:16 +0000727/**
Daniel Veillardccb09631998-10-27 06:21:04 +0000728 * xmlNewReference:
729 * @doc: the document
730 * @name: the reference name, or the reference string with & and ;
731 *
732 * Creation of a new reference node.
733 * return values: a pointer to the new node object.
734 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000735xmlNodePtr
736xmlNewReference(xmlDocPtr doc, const CHAR *name) {
Daniel Veillardccb09631998-10-27 06:21:04 +0000737 xmlNodePtr cur;
738 xmlEntityPtr ent;
739
740 /*
741 * Allocate a new node and fill the fields.
742 */
743 cur = (xmlNodePtr) malloc(sizeof(xmlNode));
744 if (cur == NULL) {
745 fprintf(stderr, "xmlNewText : malloc failed\n");
746 return(NULL);
747 }
748
749 cur->type = XML_ENTITY_REF_NODE;
750 cur->doc = NULL;
751 cur->parent = NULL;
752 cur->next = NULL;
753 cur->prev = NULL;
754 cur->childs = NULL;
755 cur->properties = NULL;
756 if (name[0] == '&') {
757 int len;
758 name++;
759 len = xmlStrlen(name);
760 if (name[len - 1] == ';')
761 cur->name = xmlStrndup(name, len - 1);
762 else
763 cur->name = xmlStrndup(name, len);
764 } else
765 cur->name = xmlStrdup(name);
766 cur->ns = NULL;
767 cur->nsDef = NULL;
768
769 ent = xmlGetDocEntity(doc, cur->name);
770 if (ent != NULL)
771 cur->content = ent->content;
772 else
773 cur->content = NULL;
774 return(cur);
775}
776
777/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000778 * xmlNewDocText:
779 * @doc: the document
780 * @content: the text content
781 *
782 * Creation of a new text node within a document.
783 * return values: a pointer to the new node object.
784 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000785xmlNodePtr
786xmlNewDocText(xmlDocPtr doc, const CHAR *content) {
Daniel Veillard0bef1311998-10-14 02:36:47 +0000787 xmlNodePtr cur;
788
789 cur = xmlNewText(content);
790 if (cur != NULL) cur->doc = doc;
791 return(cur);
792}
793
Daniel Veillard97b58771998-10-20 06:14:16 +0000794/**
Daniel Veillardccb09631998-10-27 06:21:04 +0000795 * xmlNewTextLen:
Daniel Veillard97b58771998-10-20 06:14:16 +0000796 * @content: the text content
797 * @len: the text len.
798 *
799 * Creation of a new text node with an extra parameter for the content's lenght
800 * return values: a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000801 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000802xmlNodePtr
803xmlNewTextLen(const CHAR *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000804 xmlNodePtr cur;
805
806 /*
807 * Allocate a new node and fill the fields.
808 */
809 cur = (xmlNodePtr) malloc(sizeof(xmlNode));
810 if (cur == NULL) {
811 fprintf(stderr, "xmlNewText : malloc failed\n");
812 return(NULL);
813 }
814
Daniel Veillard33942841998-10-18 19:12:41 +0000815 cur->type = XML_TEXT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000816 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000817 cur->parent = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000818 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000819 cur->next = NULL;
820 cur->childs = NULL;
821 cur->properties = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000822 cur->type = XML_TEXT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000823 cur->name = xmlStrdup(xmlStringText);
824 cur->ns = NULL;
825 cur->nsDef = NULL;
826 if (content != NULL)
827 cur->content = xmlStrndup(content, len);
828 else
829 cur->content = NULL;
830 return(cur);
831}
832
Daniel Veillard97b58771998-10-20 06:14:16 +0000833/**
834 * xmlNewDocTextLen:
835 * @doc: the document
836 * @content: the text content
837 * @len: the text len.
838 *
839 * Creation of a new text node with an extra content lenght parameter. The
840 * text node pertain to a given document.
841 * return values: a pointer to the new node object.
842 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000843xmlNodePtr
844xmlNewDocTextLen(xmlDocPtr doc, const CHAR *content, int len) {
Daniel Veillard0bef1311998-10-14 02:36:47 +0000845 xmlNodePtr cur;
846
847 cur = xmlNewTextLen(content, len);
848 if (cur != NULL) cur->doc = doc;
849 return(cur);
850}
851
Daniel Veillard97b58771998-10-20 06:14:16 +0000852/**
853 * xmlNewComment:
854 * @content: the comment content
855 *
856 * Creation of a new node containing a comment.
857 * return values: a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000858 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000859xmlNodePtr
860xmlNewComment(CHAR *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000861 xmlNodePtr cur;
862
863 /*
864 * Allocate a new node and fill the fields.
865 */
866 cur = (xmlNodePtr) malloc(sizeof(xmlNode));
867 if (cur == NULL) {
868 fprintf(stderr, "xmlNewComment : malloc failed\n");
869 return(NULL);
870 }
871
Daniel Veillard33942841998-10-18 19:12:41 +0000872 cur->type = XML_COMMENT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000873 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000874 cur->parent = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000875 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000876 cur->next = NULL;
877 cur->childs = NULL;
878 cur->properties = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000879 cur->type = XML_COMMENT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000880 cur->name = xmlStrdup(xmlStringText);
881 cur->ns = NULL;
882 cur->nsDef = NULL;
883 if (content != NULL)
884 cur->content = xmlStrdup(content);
885 else
886 cur->content = NULL;
887 return(cur);
888}
889
Daniel Veillard97b58771998-10-20 06:14:16 +0000890/**
891 * xmlNewComment:
892 * @doc: the document
893 * @content: the comment content
894 *
895 * Creation of a new node containing a commentwithin a document.
896 * return values: a pointer to the new node object.
897 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000898xmlNodePtr
899xmlNewDocComment(xmlDocPtr doc, CHAR *content) {
Daniel Veillard0bef1311998-10-14 02:36:47 +0000900 xmlNodePtr cur;
901
902 cur = xmlNewComment(content);
903 if (cur != NULL) cur->doc = doc;
904 return(cur);
905}
906
Daniel Veillard97b58771998-10-20 06:14:16 +0000907/**
908 * xmlNewChild:
909 * @parent: the parent node
910 * @ns: a namespace if any
911 * @name: the name of the child
912 * @content: the content of the child if any.
913 *
914 *
915 * Creation of a new child element, added at the end of @parent childs list.
Daniel Veillardccb09631998-10-27 06:21:04 +0000916 * @ns and @content parameters are optionnal (NULL). If content is non NULL,
917 * a child list containing the TEXTs and ENTITY_REFs node will be created.
Daniel Veillard97b58771998-10-20 06:14:16 +0000918 * return values: a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000919 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000920xmlNodePtr
921xmlNewChild(xmlNodePtr parent, xmlNsPtr ns,
Daniel Veillard260a68f1998-08-13 03:39:55 +0000922 const CHAR *name, CHAR *content) {
923 xmlNodePtr cur, prev;
924
925 if (parent == NULL) {
926 fprintf(stderr, "xmlNewChild : parent == NULL\n");
927 return(NULL);
928 }
929
930 if (name == NULL) {
931 fprintf(stderr, "xmlNewChild : name == NULL\n");
932 return(NULL);
933 }
934
935 /*
936 * Allocate a new node
937 */
938 if (ns == NULL)
Daniel Veillardccb09631998-10-27 06:21:04 +0000939 cur = xmlNewDocNode(parent->doc, parent->ns, name, content);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000940 else
Daniel Veillardccb09631998-10-27 06:21:04 +0000941 cur = xmlNewDocNode(parent->doc, ns, name, content);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000942 if (cur == NULL) return(NULL);
943
944 /*
945 * add the new element at the end of the childs list.
946 */
Daniel Veillardccb09631998-10-27 06:21:04 +0000947 cur->type = XML_ELEMENT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000948 cur->parent = parent;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000949 cur->doc = parent->doc;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000950 if (parent->childs == NULL) {
951 parent->childs = cur;
952 } else {
953 prev = parent->childs;
954 while (prev->next != NULL) prev = prev->next;
955 prev->next = cur;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000956 cur->prev = prev;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000957 }
958
959 return(cur);
960}
961
Daniel Veillard97b58771998-10-20 06:14:16 +0000962/**
963 * xmlAddChild:
964 * @parent: the parent node
965 * @cur: the child node
966 *
967 * Add a new child element, to @parent, at the end of the child list.
968 * return values: the child or NULL in case of error.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000969 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000970xmlNodePtr
971xmlAddChild(xmlNodePtr parent, xmlNodePtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000972 xmlNodePtr prev;
973
974 if (parent == NULL) {
975 fprintf(stderr, "xmladdChild : parent == NULL\n");
976 return(NULL);
977 }
978
979 if (cur == NULL) {
980 fprintf(stderr, "xmladdChild : child == NULL\n");
981 return(NULL);
982 }
983
Daniel Veillard0bef1311998-10-14 02:36:47 +0000984 if ((cur->doc != NULL) && (parent->doc != NULL) &&
985 (cur->doc != parent->doc)) {
986 fprintf(stderr, "Elements moved to a different document\n");
987 }
988
Daniel Veillard260a68f1998-08-13 03:39:55 +0000989 /*
990 * add the new element at the end of the childs list.
991 */
992 cur->parent = parent;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000993 cur->doc = parent->doc; /* the parent may not be linked to a doc ! */
Daniel Veillardccb09631998-10-27 06:21:04 +0000994 /*
995 * Handle the case where parent->content != NULL, in that case it will
996 * create a intermediate TEXT node.
997 */
998 if (parent->content != NULL) {
999 xmlNodePtr text;
1000
1001 text = xmlNewDocText(parent->doc, parent->content);
1002 if (text != NULL) {
1003 text->next = parent->childs;
1004 if (text->next != NULL)
1005 text->next->prev = text;
1006 parent->childs = text;
1007 free(parent->content);
1008 parent->content = NULL;
1009 }
1010 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00001011 if (parent->childs == NULL) {
1012 parent->childs = cur;
1013 } else {
1014 prev = parent->childs;
1015 while (prev->next != NULL) prev = prev->next;
1016 prev->next = cur;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001017 cur->prev = prev;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001018 }
1019
1020 return(cur);
1021}
1022
Daniel Veillard97b58771998-10-20 06:14:16 +00001023/**
1024 * xmlGetLastChild:
1025 * @parent: the parent node
1026 *
1027 * Search the last child of a node.
1028 * return values: the last child or NULL if none.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001029 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001030xmlNodePtr
1031xmlGetLastChild(xmlNodePtr parent) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001032 xmlNodePtr last;
1033
1034 if (parent == NULL) {
1035 fprintf(stderr, "xmlGetLastChild : parent == NULL\n");
1036 return(NULL);
1037 }
1038
1039 /*
1040 * add the new element at the end of the childs list.
1041 */
1042 if (parent->childs == NULL) {
1043 return(NULL);
1044 } else {
1045 last = parent->childs;
1046 while (last->next != NULL) last = last->next;
1047 }
1048 return(last);
1049}
1050
Daniel Veillard97b58771998-10-20 06:14:16 +00001051/**
1052 * xmlFreeNodeList:
1053 * @cur: the first node in the list
1054 *
1055 * Free a node and all its siblings, this is a recursive behaviour, all
1056 * the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001057 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001058void
1059xmlFreeNodeList(xmlNodePtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001060 xmlNodePtr next;
1061 if (cur == NULL) {
1062 fprintf(stderr, "xmlFreeNodeList : node == NULL\n");
1063 return;
1064 }
1065 while (cur != NULL) {
1066 next = cur->next;
1067 xmlFreeNode(cur);
1068 cur = next;
1069 }
1070}
1071
Daniel Veillard97b58771998-10-20 06:14:16 +00001072/**
1073 * xmlFreeNode:
1074 * @cur: the node
1075 *
1076 * Free a node, this is a recursive behaviour, all the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001077 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001078void
1079xmlFreeNode(xmlNodePtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001080 if (cur == NULL) {
1081 fprintf(stderr, "xmlFreeNode : node == NULL\n");
1082 return;
1083 }
Daniel Veillardccb09631998-10-27 06:21:04 +00001084 cur->doc = NULL;
1085 cur->parent = NULL;
1086 cur->next = NULL;
1087 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001088 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillardccb09631998-10-27 06:21:04 +00001089 if (cur->properties != NULL) xmlFreePropList(cur->properties);
1090 if (cur->type != XML_ENTITY_REF_NODE)
1091 if (cur->content != NULL) free(cur->content);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001092 if (cur->name != NULL) free((char *) cur->name);
1093 if (cur->nsDef != NULL) xmlFreeNsList(cur->nsDef);
1094 memset(cur, -1, sizeof(xmlNode));
1095 free(cur);
1096}
1097
1098/************************************************************************
1099 * *
1100 * Content access functions *
1101 * *
1102 ************************************************************************/
1103
Daniel Veillard97b58771998-10-20 06:14:16 +00001104/**
1105 * xmlNodeSetContent:
1106 * @cur: the node being modified
1107 * @content: the new value of the content
1108 *
1109 * Replace the content of a node.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001110 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001111void
1112xmlNodeSetContent(xmlNodePtr cur, const CHAR *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001113 if (cur == NULL) {
1114 fprintf(stderr, "xmlNodeSetContent : node == NULL\n");
1115 return;
1116 }
1117 if (cur->content != NULL) free(cur->content);
1118 if (content != NULL)
1119 cur->content = xmlStrdup(content);
1120 else
1121 cur->content = NULL;
1122}
1123
Daniel Veillard97b58771998-10-20 06:14:16 +00001124/**
1125 * xmlNodeSetContentLen:
1126 * @cur: the node being modified
1127 * @content: the new value of the content
1128 * @len: the size of @content
1129 *
1130 * Replace the content of a node.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001131 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001132void
1133xmlNodeSetContentLen(xmlNodePtr cur, const CHAR *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001134 if (cur == NULL) {
1135 fprintf(stderr, "xmlNodeSetContent : node == NULL\n");
1136 return;
1137 }
1138 if (cur->content != NULL) free(cur->content);
1139 if (content != NULL)
1140 cur->content = xmlStrndup(content, len);
1141 else
1142 cur->content = NULL;
1143}
1144
Daniel Veillard97b58771998-10-20 06:14:16 +00001145/**
1146 * xmlNodeAddContent:
1147 * @cur: the node being modified
1148 * @content: extra content
1149 *
1150 * Append the extra substring to the node content.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001151 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001152void
1153xmlNodeAddContent(xmlNodePtr cur, const CHAR *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001154 if (cur == NULL) {
1155 fprintf(stderr, "xmlNodeAddContent : node == NULL\n");
1156 return;
1157 }
1158 cur->content = xmlStrcat(cur->content, content);
1159}
1160
Daniel Veillard97b58771998-10-20 06:14:16 +00001161/**
1162 * xmlNodeAddContentLen:
1163 * @cur: the node being modified
1164 * @content: extra content
1165 * @len: the size of @content
1166 *
1167 * Append the extra substring to the node content.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001168 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001169void
1170xmlNodeAddContentLen(xmlNodePtr cur, const CHAR *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001171 if (cur == NULL) {
1172 fprintf(stderr, "xmlNodeAddContent : node == NULL\n");
1173 return;
1174 }
1175 cur->content = xmlStrncat(cur->content, content, len);
1176}
1177
Daniel Veillard97b58771998-10-20 06:14:16 +00001178/**
1179 * xmlSearchNs:
1180 * @doc: the document
1181 * @node: the current node
1182 * @nameSpace: the namespace string
Daniel Veillard260a68f1998-08-13 03:39:55 +00001183 *
Daniel Veillard97b58771998-10-20 06:14:16 +00001184 * Search a Ns registered under a given name space for a document.
1185 * recurse on the parents until it finds the defined namespace
1186 * or return NULL otherwise.
1187 * @nameSpace can be NULL, this is a search for the default namespace.
1188 * return values: the namespace pointer or NULL.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001189 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001190xmlNsPtr
1191xmlSearchNs(xmlDocPtr doc, xmlNodePtr node, const CHAR *nameSpace) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001192 xmlNsPtr cur;
1193
1194 while (node != NULL) {
1195 cur = node->nsDef;
1196 while (cur != NULL) {
1197 if ((cur->prefix == NULL) && (nameSpace == NULL))
1198 return(cur);
1199 if ((cur->prefix != NULL) && (nameSpace != NULL) &&
1200 (!xmlStrcmp(cur->prefix, nameSpace)))
1201 return(cur);
1202 cur = cur->next;
1203 }
1204 node = node->parent;
1205 }
1206 if (doc != NULL) {
1207 cur = doc->oldNs;
1208 while (cur != NULL) {
1209 if ((cur->prefix != NULL) && (nameSpace != NULL) &&
1210 (!xmlStrcmp(cur->prefix, nameSpace)))
1211 return(cur);
1212 cur = cur->next;
1213 }
1214 }
1215 return(NULL);
1216}
1217
Daniel Veillard97b58771998-10-20 06:14:16 +00001218/**
1219 * xmlSearchNsByHref:
1220 * @doc: the document
1221 * @node: the current node
1222 * @href: the namespace value
1223 *
1224 * Search a Ns aliasing a given URI. Recurse on the parents until it finds
1225 * the defined namespace or return NULL otherwise.
1226 * return values: the namespace pointer or NULL.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001227 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001228xmlNsPtr
1229xmlSearchNsByHref(xmlDocPtr doc, xmlNodePtr node, const CHAR *href) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001230 xmlNsPtr cur;
1231
1232 while (node != NULL) {
1233 cur = node->nsDef;
1234 while (cur != NULL) {
1235 if ((cur->href != NULL) && (href != NULL) &&
1236 (!xmlStrcmp(cur->href, href)))
1237 return(cur);
1238 cur = cur->next;
1239 }
1240 node = node->parent;
1241 }
1242 if (doc != NULL) {
1243 cur = doc->oldNs;
1244 while (cur != NULL) {
1245 if ((cur->href != NULL) && (href != NULL) &&
1246 (!xmlStrcmp(cur->href, href)))
1247 return(cur);
1248 cur = cur->next;
1249 }
1250 }
1251 return(NULL);
1252}
1253
Daniel Veillard97b58771998-10-20 06:14:16 +00001254/**
1255 * xmlGetProp:
1256 * @node: the node
1257 * @name: the attribute name
1258 *
1259 * Search and get the value of an attribute associated to a node
Daniel Veillardccb09631998-10-27 06:21:04 +00001260 * This does the entity substitution.
Daniel Veillard97b58771998-10-20 06:14:16 +00001261 * return values: the attribute value or NULL if not found.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001262 */
1263const CHAR *xmlGetProp(xmlNodePtr node, const CHAR *name) {
1264 xmlAttrPtr prop = node->properties;
1265
1266 while (prop != NULL) {
Daniel Veillardccb09631998-10-27 06:21:04 +00001267 if (!xmlStrcmp(prop->name, name))
1268 return(xmlNodeListGetString(node->doc, prop->val, 1));
Daniel Veillard260a68f1998-08-13 03:39:55 +00001269 prop = prop->next;
1270 }
1271 return(NULL);
1272}
1273
Daniel Veillard97b58771998-10-20 06:14:16 +00001274/**
Daniel Veillardccb09631998-10-27 06:21:04 +00001275 * xmlSetProp:
Daniel Veillard97b58771998-10-20 06:14:16 +00001276 * @node: the node
1277 * @name: the attribute name
1278 * @value: the attribute value
1279 *
1280 * Set (or reset) an attribute carried by a node.
1281 * return values: the attribute pointer.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001282 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001283xmlAttrPtr
1284xmlSetProp(xmlNodePtr node, const CHAR *name, const CHAR *value) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001285 xmlAttrPtr prop = node->properties;
1286
1287 while (prop != NULL) {
1288 if (!xmlStrcmp(prop->name, name)) {
Daniel Veillardccb09631998-10-27 06:21:04 +00001289 if (prop->val != NULL)
1290 xmlFreeNode(prop->val);
1291 prop->val = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001292 if (value != NULL)
Daniel Veillardccb09631998-10-27 06:21:04 +00001293 prop->val = xmlStringGetNodeList(node->doc, value);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001294 return(prop);
1295 }
1296 prop = prop->next;
1297 }
1298 prop = xmlNewProp(node, name, value);
1299 return(prop);
1300}
1301
Daniel Veillard97b58771998-10-20 06:14:16 +00001302/**
1303 * xmlNodeIsText:
1304 * @node: the node
1305 *
1306 * Is this node a Text node ?
1307 * return values: 1 yes, 0 no
Daniel Veillard260a68f1998-08-13 03:39:55 +00001308 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001309int
1310xmlNodeIsText(xmlNodePtr node) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001311 if (node == NULL) return(0);
1312
Daniel Veillard0bef1311998-10-14 02:36:47 +00001313 if (node->type == XML_TEXT_NODE) return(1);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001314 return(0);
1315}
1316
Daniel Veillard97b58771998-10-20 06:14:16 +00001317/**
1318 * xmlNodeIsText:
1319 * @node: the node
1320 * @content: the content
1321 * @len: @content lenght
1322 *
1323 * Concat the given string at the end of the existing node content
Daniel Veillard260a68f1998-08-13 03:39:55 +00001324 */
Daniel Veillard97b58771998-10-20 06:14:16 +00001325
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001326void
1327xmlTextConcat(xmlNodePtr node, const CHAR *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001328 if (node == NULL) return;
1329
Daniel Veillard0bef1311998-10-14 02:36:47 +00001330 if (node->type != XML_TEXT_NODE) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001331 fprintf(stderr, "xmlTextConcat: node is not text\n");
1332 return;
1333 }
1334 node->content = xmlStrncat(node->content, content, len);
1335}
1336
1337/************************************************************************
1338 * *
1339 * Output : to a FILE or in memory *
1340 * *
1341 ************************************************************************/
1342
Daniel Veillard260a68f1998-08-13 03:39:55 +00001343static CHAR *buffer = NULL;
1344static int buffer_index = 0;
1345static int buffer_size = 0;
1346
Daniel Veillard97b58771998-10-20 06:14:16 +00001347/**
1348 * xmlBufferWriteCHAR:
1349 * @string: the string to add
1350 *
1351 * routine which manage and grows an output buffer. This one add
1352 * CHARs at the end of the array.
1353 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001354void
1355xmlBufferWriteCHAR(const CHAR *string) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001356 const CHAR *cur;
1357
1358 if (buffer == NULL) {
1359 buffer_size = 50000;
1360 buffer = (CHAR *) malloc(buffer_size * sizeof(CHAR));
1361 if (buffer == NULL) {
1362 fprintf(stderr, "xmlBufferWrite : out of memory!\n");
1363 exit(1);
1364 }
1365 }
1366
1367 if (string == NULL) return;
1368 for (cur = string;*cur != 0;cur++) {
1369 if (buffer_index + 10 >= buffer_size) {
1370 buffer_size *= 2;
1371 buffer = (CHAR *) realloc(buffer, buffer_size * sizeof(CHAR));
1372 if (buffer == NULL) {
1373 fprintf(stderr, "xmlBufferWrite : out of memory!\n");
1374 exit(1);
1375 }
1376 }
1377 buffer[buffer_index++] = *cur;
1378 }
1379 buffer[buffer_index] = 0;
1380}
1381
Daniel Veillard97b58771998-10-20 06:14:16 +00001382/**
1383 * xmlBufferWriteChar:
1384 * @string: the string to add
1385 *
1386 * routine which manage and grows an output buffer. This one add
1387 * C chars at the end of the array.
1388 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001389void
1390xmlBufferWriteChar(const char *string) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001391 const char *cur;
1392
1393 if (buffer == NULL) {
1394 buffer_size = 50000;
1395 buffer = (CHAR *) malloc(buffer_size * sizeof(CHAR));
1396 if (buffer == NULL) {
1397 fprintf(stderr, "xmlBufferWrite : out of memory!\n");
1398 exit(1);
1399 }
1400 }
1401
1402 if (string == NULL) return;
1403 for (cur = string;*cur != 0;cur++) {
1404 if (buffer_index + 10 >= buffer_size) {
1405 buffer_size *= 2;
1406 buffer = (CHAR *) realloc(buffer, buffer_size * sizeof(CHAR));
1407 if (buffer == NULL) {
1408 fprintf(stderr, "xmlBufferWrite : out of memory!\n");
1409 exit(1);
1410 }
1411 }
1412 buffer[buffer_index++] = *cur;
1413 }
1414 buffer[buffer_index] = 0;
1415}
1416
Daniel Veillard97b58771998-10-20 06:14:16 +00001417/**
1418 * xmlGlobalNsDump:
1419 * @cur: a namespace
1420 *
1421 * Dump a global Namespace, this is the old version based on PIs.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001422 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001423static void
1424xmlGlobalNsDump(xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001425 if (cur == NULL) {
1426 fprintf(stderr, "xmlGlobalNsDump : Ns == NULL\n");
1427 return;
1428 }
1429 if (cur->type == XML_GLOBAL_NAMESPACE) {
1430 xmlBufferWriteChar("<?namespace");
1431 if (cur->href != NULL) {
1432 xmlBufferWriteChar(" href=\"");
1433 xmlBufferWriteCHAR(cur->href);
1434 xmlBufferWriteChar("\"");
1435 }
1436 if (cur->prefix != NULL) {
1437 xmlBufferWriteChar(" AS=\"");
1438 xmlBufferWriteCHAR(cur->prefix);
1439 xmlBufferWriteChar("\"");
1440 }
1441 xmlBufferWriteChar("?>\n");
1442 }
1443}
1444
Daniel Veillard97b58771998-10-20 06:14:16 +00001445/**
1446 * xmlGlobalNsListDump:
1447 * @cur: the first namespace
1448 *
1449 * Dump a list of global Namespace, this is the old version based on PIs.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001450 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001451static void
1452xmlGlobalNsListDump(xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001453 while (cur != NULL) {
1454 xmlGlobalNsDump(cur);
1455 cur = cur->next;
1456 }
1457}
1458
Daniel Veillard97b58771998-10-20 06:14:16 +00001459/**
1460 * xmlNsDump:
1461 * @cur: a namespace
1462 *
Daniel Veillard260a68f1998-08-13 03:39:55 +00001463 * Dump a local Namespace definition.
Daniel Veillard97b58771998-10-20 06:14:16 +00001464 * Should be called in the context of attributes dumps.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001465 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001466static void
1467xmlNsDump(xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001468 if (cur == NULL) {
1469 fprintf(stderr, "xmlNsDump : Ns == NULL\n");
1470 return;
1471 }
1472 if (cur->type == XML_LOCAL_NAMESPACE) {
1473 /* Within the context of an element attributes */
1474 if (cur->prefix != NULL) {
1475 xmlBufferWriteChar(" xmlns:");
1476 xmlBufferWriteCHAR(cur->prefix);
1477 } else
1478 xmlBufferWriteChar(" xmlns");
1479 xmlBufferWriteChar("=\"");
1480 xmlBufferWriteCHAR(cur->href);
1481 xmlBufferWriteChar("\"");
1482 }
1483}
1484
Daniel Veillard97b58771998-10-20 06:14:16 +00001485/**
1486 * xmlNsListDump:
1487 * @cur: the first namespace
1488 *
1489 * Dump a list of local Namespace definitions.
1490 * Should be called in the context of attributes dumps.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001491 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001492static void
1493xmlNsListDump(xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001494 while (cur != NULL) {
1495 xmlNsDump(cur);
1496 cur = cur->next;
1497 }
1498}
1499
Daniel Veillard97b58771998-10-20 06:14:16 +00001500/**
1501 * xmlDtdDump:
1502 * @doc: the document
1503 *
1504 * Dump the XML document DTD, if any.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001505 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001506static void
1507xmlDtdDump(xmlDocPtr doc) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001508 xmlDtdPtr cur = doc->dtd;
1509
1510 if (cur == NULL) {
1511 fprintf(stderr, "xmlDtdDump : DTD == NULL\n");
1512 return;
1513 }
1514 xmlBufferWriteChar("<!DOCTYPE ");
1515 xmlBufferWriteCHAR(cur->name);
1516 if (cur->ExternalID != NULL) {
1517 xmlBufferWriteChar(" PUBLIC \"");
1518 xmlBufferWriteCHAR(cur->ExternalID);
1519 xmlBufferWriteChar("\" \"");
1520 xmlBufferWriteCHAR(cur->SystemID);
1521 xmlBufferWriteChar("\"");
1522 } else if (cur->SystemID != NULL) {
1523 xmlBufferWriteChar(" SYSTEM \"");
1524 xmlBufferWriteCHAR(cur->SystemID);
1525 xmlBufferWriteChar("\"");
1526 }
1527 if ((cur->entities == NULL) && (doc->entities == NULL)) {
1528 xmlBufferWriteChar(">\n");
1529 return;
1530 }
1531 xmlBufferWriteChar(" [\n");
1532 if (cur->entities != NULL)
1533 xmlDumpEntitiesTable((xmlEntitiesTablePtr) cur->entities);
1534 if (doc->entities != NULL)
1535 xmlDumpEntitiesTable((xmlEntitiesTablePtr) doc->entities);
1536 xmlBufferWriteChar("]");
1537
1538 /* TODO !!! a lot more things to dump ... */
1539 xmlBufferWriteChar(">\n");
1540}
1541
Daniel Veillard97b58771998-10-20 06:14:16 +00001542/**
1543 * xmlAttrDump:
1544 * @doc: the document
1545 * @cur: the attribute pointer
1546 *
1547 * Dump an XML attribute
Daniel Veillard260a68f1998-08-13 03:39:55 +00001548 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001549static void
1550xmlAttrDump(xmlDocPtr doc, xmlAttrPtr cur) {
Daniel Veillardccb09631998-10-27 06:21:04 +00001551 CHAR *value;
1552
Daniel Veillard260a68f1998-08-13 03:39:55 +00001553 if (cur == NULL) {
1554 fprintf(stderr, "xmlAttrDump : property == NULL\n");
1555 return;
1556 }
1557 xmlBufferWriteChar(" ");
1558 xmlBufferWriteCHAR(cur->name);
Daniel Veillardccb09631998-10-27 06:21:04 +00001559 value = xmlNodeListGetString(doc, cur->val, 0);
1560 if (value) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001561 xmlBufferWriteChar("=\"");
Daniel Veillardccb09631998-10-27 06:21:04 +00001562 xmlBufferWriteCHAR(value);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001563 xmlBufferWriteChar("\"");
Daniel Veillardccb09631998-10-27 06:21:04 +00001564 free(value);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001565 }
1566}
1567
Daniel Veillard97b58771998-10-20 06:14:16 +00001568/**
1569 * xmlAttrListDump:
1570 * @doc: the document
1571 * @cur: the first attribute pointer
1572 *
1573 * Dump a list of XML attributes
Daniel Veillard260a68f1998-08-13 03:39:55 +00001574 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001575static void
1576xmlAttrListDump(xmlDocPtr doc, xmlAttrPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001577 if (cur == NULL) {
1578 fprintf(stderr, "xmlAttrListDump : property == NULL\n");
1579 return;
1580 }
1581 while (cur != NULL) {
1582 xmlAttrDump(doc, cur);
1583 cur = cur->next;
1584 }
1585}
1586
Daniel Veillard260a68f1998-08-13 03:39:55 +00001587
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001588static void
1589xmlNodeDump(xmlDocPtr doc, xmlNodePtr cur, int level);
Daniel Veillard97b58771998-10-20 06:14:16 +00001590/**
1591 * xmlNodeListDump:
1592 * @doc: the document
1593 * @cur: the first node
1594 * @level: the imbrication level for indenting
1595 *
1596 * Dump an XML node list, recursive behaviour,children are printed too.
1597 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001598static void
1599xmlNodeListDump(xmlDocPtr doc, xmlNodePtr cur, int level) {
Daniel Veillardccb09631998-10-27 06:21:04 +00001600 int needIndent = 0, i;
1601
Daniel Veillard260a68f1998-08-13 03:39:55 +00001602 if (cur == NULL) {
1603 fprintf(stderr, "xmlNodeListDump : node == NULL\n");
1604 return;
1605 }
1606 while (cur != NULL) {
Daniel Veillardccb09631998-10-27 06:21:04 +00001607 if ((cur->type != XML_TEXT_NODE) &&
1608 (cur->type != XML_ENTITY_REF_NODE)) {
1609 if (!needIndent) {
1610 needIndent = 1;
1611 xmlBufferWriteChar("\n");
1612 }
1613 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00001614 xmlNodeDump(doc, cur, level);
1615 cur = cur->next;
1616 }
Daniel Veillardccb09631998-10-27 06:21:04 +00001617 if ((xmlIndentTreeOutput) && (needIndent))
1618 for (i = 1;i < level;i++)
1619 xmlBufferWriteChar(" ");
Daniel Veillard260a68f1998-08-13 03:39:55 +00001620}
1621
Daniel Veillard97b58771998-10-20 06:14:16 +00001622/**
Daniel Veillardccb09631998-10-27 06:21:04 +00001623 * xmlNodeDump:
Daniel Veillard97b58771998-10-20 06:14:16 +00001624 * @doc: the document
1625 * @cur: the current node
1626 * @level: the imbrication level for indenting
1627 *
1628 * Dump an XML node, recursive behaviour,children are printed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001629 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001630static void
1631xmlNodeDump(xmlDocPtr doc, xmlNodePtr cur, int level) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001632 int i;
1633
1634 if (cur == NULL) {
1635 fprintf(stderr, "xmlNodeDump : node == NULL\n");
1636 return;
1637 }
Daniel Veillard0bef1311998-10-14 02:36:47 +00001638 if (cur->type == XML_TEXT_NODE) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001639 if (cur->content != NULL)
1640 xmlBufferWriteCHAR(xmlEncodeEntities(doc, cur->content));
1641 return;
1642 }
Daniel Veillard0bef1311998-10-14 02:36:47 +00001643 if (cur->type == XML_COMMENT_NODE) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001644 if (cur->content != NULL) {
1645 xmlBufferWriteChar("<!--");
1646 xmlBufferWriteCHAR(cur->content);
1647 xmlBufferWriteChar("-->");
1648 }
1649 return;
1650 }
Daniel Veillardccb09631998-10-27 06:21:04 +00001651 if (cur->type == XML_ENTITY_REF_NODE) {
1652 xmlBufferWriteChar("&");
1653 xmlBufferWriteCHAR(cur->name);
1654 xmlBufferWriteChar(";");
1655 return;
1656 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00001657 if (xmlIndentTreeOutput)
1658 for (i = 0;i < level;i++)
1659 xmlBufferWriteChar(" ");
1660
1661 xmlBufferWriteChar("<");
1662 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
1663 xmlBufferWriteCHAR(cur->ns->prefix);
1664 xmlBufferWriteChar(":");
1665 }
1666
1667 xmlBufferWriteCHAR(cur->name);
1668 if (cur->nsDef)
1669 xmlNsListDump(cur->nsDef);
1670 if (cur->properties != NULL)
1671 xmlAttrListDump(doc, cur->properties);
1672
1673 if ((cur->content == NULL) && (cur->childs == NULL)) {
1674 xmlBufferWriteChar("/>\n");
1675 return;
1676 }
1677 xmlBufferWriteChar(">");
1678 if (cur->content != NULL)
1679 xmlBufferWriteCHAR(xmlEncodeEntities(doc, cur->content));
1680 if (cur->childs != NULL) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001681 xmlNodeListDump(doc, cur->childs, level + 1);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001682 }
1683 xmlBufferWriteChar("</");
1684 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
1685 xmlBufferWriteCHAR(cur->ns->prefix);
1686 xmlBufferWriteChar(":");
1687 }
1688
1689 xmlBufferWriteCHAR(cur->name);
1690 xmlBufferWriteChar(">\n");
1691}
1692
Daniel Veillard97b58771998-10-20 06:14:16 +00001693/**
1694 * xmlDocContentDump:
1695 * @cur: the document
1696 *
1697 * Dump an XML document.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001698 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001699static void
1700xmlDocContentDump(xmlDocPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001701 if (oldXMLWDcompatibility)
1702 xmlBufferWriteChar("<?XML version=\"");
1703 else
1704 xmlBufferWriteChar("<?xml version=\"");
1705 xmlBufferWriteCHAR(cur->version);
1706 xmlBufferWriteChar("\"");
1707 if (cur->encoding != NULL) {
1708 xmlBufferWriteChar(" encoding=\"");
1709 xmlBufferWriteCHAR(cur->encoding);
1710 xmlBufferWriteChar("\"");
1711 }
1712 switch (cur->standalone) {
1713 case 0:
1714 xmlBufferWriteChar(" standalone=\"no\"");
1715 break;
1716 case 1:
1717 xmlBufferWriteChar(" standalone=\"yes\"");
1718 break;
1719 }
1720 xmlBufferWriteChar("?>\n");
1721 if ((cur->dtd != NULL) || (cur->entities != NULL))
1722 xmlDtdDump(cur);
1723 if (cur->root != NULL) {
1724 /* global namespace definitions, the old way */
1725 if (oldXMLWDcompatibility)
1726 xmlGlobalNsListDump(cur->oldNs);
1727 else
1728 xmlUpgradeOldNs(cur);
1729 xmlNodeDump(cur, cur->root, 0);
1730 }
1731}
1732
Daniel Veillard97b58771998-10-20 06:14:16 +00001733/**
1734 * xmlDocDumpMemory:
1735 * @cur: the document
1736 * @mem: OUT: the memory pointer
1737 * @size: OUT: the memory lenght
1738 *
1739 * Dump an XML document in memory and return the CHAR * and it's size.
1740 * It's up to the caller to free the memory.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001741 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001742void
1743xmlDocDumpMemory(xmlDocPtr cur, CHAR**mem, int *size) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001744 if (cur == NULL) {
1745 fprintf(stderr, "xmlDocDump : document == NULL\n");
1746 *mem = NULL;
1747 *size = 0;
1748 return;
1749 }
1750 buffer_index = 0;
1751 xmlDocContentDump(cur);
1752
1753 *mem = buffer;
1754 *size = buffer_index;
1755}
1756
Daniel Veillard97b58771998-10-20 06:14:16 +00001757/**
1758 * xmlGetDocCompressMode:
1759 * @doc: the document
1760 *
1761 * get the compression ratio for a document, ZLIB based
1762 * return values: 0 (uncompressed) to 9 (max compression)
Daniel Veillard151b1b01998-09-23 00:49:46 +00001763 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001764int
1765 xmlGetDocCompressMode (xmlDocPtr doc) {
Daniel Veillard15a8df41998-09-24 19:15:06 +00001766 if (doc == NULL) return(-1);
1767 return(doc->compression);
1768}
1769
Daniel Veillard97b58771998-10-20 06:14:16 +00001770/**
1771 * xmlSetDocCompressMode:
1772 * @doc: the document
1773 * @mode: the compression ratio
1774 *
1775 * set the compression ratio for a document, ZLIB based
1776 * Correct values: 0 (uncompressed) to 9 (max compression)
1777 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001778void
1779xmlSetDocCompressMode (xmlDocPtr doc, int mode) {
Daniel Veillard15a8df41998-09-24 19:15:06 +00001780 if (doc == NULL) return;
1781 if (mode < 0) doc->compression = 0;
1782 else if (mode > 9) doc->compression = 9;
1783 else doc->compression = mode;
1784}
1785
Daniel Veillard97b58771998-10-20 06:14:16 +00001786/**
1787 * xmlGetCompressMode:
1788 *
1789 * get the default compression mode used, ZLIB based.
1790 * return values: 0 (uncompressed) to 9 (max compression)
Daniel Veillard15a8df41998-09-24 19:15:06 +00001791 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001792int
1793 xmlGetCompressMode(void) {
Daniel Veillard151b1b01998-09-23 00:49:46 +00001794 return(xmlCompressMode);
1795}
Daniel Veillard97b58771998-10-20 06:14:16 +00001796
1797/**
1798 * xmlSetCompressMode:
1799 * @mode: the compression ratio
1800 *
1801 * set the default compression mode used, ZLIB based
1802 * Correct values: 0 (uncompressed) to 9 (max compression)
1803 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001804void
1805xmlSetCompressMode(int mode) {
Daniel Veillard151b1b01998-09-23 00:49:46 +00001806 if (mode < 0) xmlCompressMode = 0;
Daniel Veillard15a8df41998-09-24 19:15:06 +00001807 else if (mode > 9) xmlCompressMode = 9;
Daniel Veillard151b1b01998-09-23 00:49:46 +00001808 else xmlCompressMode = mode;
1809}
1810
Daniel Veillard97b58771998-10-20 06:14:16 +00001811/**
1812 * xmlDocDump:
1813 * @f: the FILE*
1814 * @cur: the document
1815 *
1816 * Dump an XML document to an open FILE.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001817 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001818void
1819xmlDocDump(FILE *f, xmlDocPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001820 if (cur == NULL) {
1821 fprintf(stderr, "xmlDocDump : document == NULL\n");
1822 return;
1823 }
1824 buffer_index = 0;
1825 xmlDocContentDump(cur);
1826
1827 fwrite(buffer, sizeof(CHAR), buffer_index, f);
1828}
1829
Daniel Veillard97b58771998-10-20 06:14:16 +00001830/**
1831 * xmlSaveFile:
1832 * @filename: the filename
1833 * @cur: the document
1834 *
1835 * Dump an XML document to a file. Will use compression if
1836 * compiled in and enabled.
1837 * returns: the number of file written or -1 in case of failure.
Daniel Veillard151b1b01998-09-23 00:49:46 +00001838 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001839int
1840xmlSaveFile(const char *filename, xmlDocPtr cur) {
Daniel Veillard151b1b01998-09-23 00:49:46 +00001841#ifdef HAVE_ZLIB_H
1842 gzFile zoutput = NULL;
1843 char mode[15];
1844#endif
Daniel Veillardccb09631998-10-27 06:21:04 +00001845 FILE *output = NULL;
Daniel Veillard151b1b01998-09-23 00:49:46 +00001846 int ret;
1847
1848#ifdef HAVE_ZLIB_H
Daniel Veillarddc3dd9d1998-09-24 19:25:54 +00001849 if ((cur->compression > 0) && (cur->compression <= 9)) {
1850 sprintf(mode, "w%d", cur->compression);
Daniel Veillard151b1b01998-09-23 00:49:46 +00001851 zoutput = gzopen(filename, mode);
1852 }
1853 if (zoutput == NULL) {
1854#endif
1855 output = fopen(filename, "w");
1856 if (output == NULL) return(-1);
1857#ifdef HAVE_ZLIB_H
1858 }
1859#endif
1860
1861 /*
1862 * save the content to a temp buffer.
1863 */
1864 buffer_index = 0;
1865 xmlDocContentDump(cur);
1866
1867#ifdef HAVE_ZLIB_H
1868 if (zoutput != NULL) {
1869 ret = gzwrite(zoutput, buffer, sizeof(CHAR) * buffer_index);
1870 gzclose(zoutput);
1871 return(ret);
1872 }
1873#endif
1874 ret = fwrite(buffer, sizeof(CHAR), buffer_index, output);
1875 fclose(output);
1876 return(ret * sizeof(CHAR));
1877}
1878
Daniel Veillard260a68f1998-08-13 03:39:55 +00001879/************************************************************************
1880 * *
1881 * Debug *
1882 * *
1883 ************************************************************************/
1884
1885#ifdef STANDALONE
1886int main(void) {
1887 xmlDocPtr doc;
1888 xmlNodePtr tree, subtree;
1889 xmlNsPtr ns1;
1890 xmlNsPtr ns2;
1891
1892 /*
1893 * build a fake XML document
1894 */
1895 doc = xmlNewDoc("1.0");
1896 ns1 = xmlNewNs(doc, "http://www.ietf.org/standards/dav/", "D");
1897 ns2 = xmlNewNs(doc, "http://www.w3.com/standards/z39.50/", "Z");
Daniel Veillardccb09631998-10-27 06:21:04 +00001898 doc->root = xmlNewDocNode(doc, ns1, "multistatus", NULL);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001899 tree = xmlNewChild(doc->root, NULL, "response", NULL);
1900 subtree = xmlNewChild(tree, NULL, "prop", NULL);
1901 xmlNewChild(subtree, ns2, "Authors", NULL);
1902 subtree = xmlNewChild(tree, NULL, "status", "HTTP/1.1 420 Method Failure");
1903 tree = xmlNewChild(doc->root, NULL, "response", NULL);
1904 subtree = xmlNewChild(tree, NULL, "prop", NULL);
1905 xmlNewChild(subtree, ns2, "Copyright-Owner", NULL);
1906 subtree = xmlNewChild(tree, NULL, "status", "HTTP/1.1 409 Conflict");
1907 tree = xmlNewChild(doc->root, NULL, "responsedescription",
1908 "Copyright Owner can not be deleted or altered");
1909
1910 /*
1911 * print it.
1912 */
1913 xmlDocDump(stdout, doc);
1914
1915 /*
1916 * free it.
1917 */
1918 xmlFreeDoc(doc);
1919 return(0);
1920}
1921#endif