blob: c7eba5a0e9e247212e251e39ce18c1f9ce7ddb6b [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>
14#include <malloc.h>
15#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
28/************************************************************************
29 * *
30 * Allocation and deallocation of basic structures *
31 * *
32 ************************************************************************/
33
34/*
35 * Upgrade old Namespace and move them to the root of the document.
36 */
37
38void xmlUpgradeOldNs(xmlDocPtr doc) {
39 xmlNsPtr cur;
40
41 if ((doc == NULL) || (doc->oldNs == NULL)) return;
42 if (doc->root == NULL) {
43 fprintf(stderr, "xmlUpgradeOldNs: failed no root !\n");
44 return;
45 }
46
47 cur = doc->oldNs;
48 while (cur->next != NULL) {
49 cur->type = XML_LOCAL_NAMESPACE;
50 cur = cur->next;
51 }
52 cur->type = XML_LOCAL_NAMESPACE;
53 cur->next = doc->root->nsDef;
54 doc->root->nsDef = doc->oldNs;
55 doc->oldNs = NULL;
56}
57
58/*
59 * Creation of a new Namespace.
60 */
61xmlNsPtr xmlNewNs(xmlNodePtr node, const CHAR *href, const CHAR *prefix) {
62 xmlNsPtr cur;
63
64 if (href == NULL) {
65 fprintf(stderr, "xmlNewNs: href == NULL !\n");
66 return(NULL);
67 }
68
69 /*
70 * Allocate a new DTD and fill the fields.
71 */
72 cur = (xmlNsPtr) malloc(sizeof(xmlNs));
73 if (cur == NULL) {
74 fprintf(stderr, "xmlNewNs : malloc failed\n");
75 return(NULL);
76 }
77
78 cur->type = XML_LOCAL_NAMESPACE;
79 if (href != NULL)
80 cur->href = xmlStrdup(href);
81 else
82 cur->href = NULL;
83 if (prefix != NULL)
84 cur->prefix = xmlStrdup(prefix);
85 else
86 cur->prefix = NULL;
87
88 /*
89 * Add it at the end to preserve parsing order ...
90 */
91 cur->next = NULL;
92 if (node != NULL) {
93 if (node->nsDef == NULL) {
94 node->nsDef = cur;
95 } else {
96 xmlNsPtr prev = node->nsDef;
97
98 while (prev->next != NULL) prev = prev->next;
99 prev->next = cur;
100 }
101 }
102
103 return(cur);
104}
105
106/*
107 * Creation of a new global namespace (the old way ...).
108 */
109xmlNsPtr xmlNewGlobalNs(xmlDocPtr doc, const CHAR *href, const CHAR *prefix) {
110 xmlNsPtr cur;
111
112 /*
113 * Allocate a new DTD and fill the fields.
114 */
115 cur = (xmlNsPtr) malloc(sizeof(xmlNs));
116 if (cur == NULL) {
117 fprintf(stderr, "xmlNewNs : malloc failed\n");
118 return(NULL);
119 }
120
121 cur->type = XML_GLOBAL_NAMESPACE;
122 if (href != NULL)
123 cur->href = xmlStrdup(href);
124 else
125 cur->href = NULL;
126 if (prefix != NULL)
127 cur->prefix = xmlStrdup(prefix);
128 else
129 cur->prefix = NULL;
130
131 /*
132 * Add it at the end to preserve parsing order ...
133 */
134 cur->next = NULL;
135 if (doc != NULL) {
136 if (doc->oldNs == NULL) {
137 doc->oldNs = cur;
138 } else {
139 xmlNsPtr prev = doc->oldNs;
140
141 while (prev->next != NULL) prev = prev->next;
142 prev->next = cur;
143 }
144 }
145
146 return(cur);
147}
148
149/*
150 * Set the node namespace a posteriori
151 */
152void xmlSetNs(xmlNodePtr node, xmlNsPtr ns) {
153 if (node == NULL) {
154 fprintf(stderr, "xmlSetNs: node == NULL\n");
155 return;
156 }
157 node->ns = ns;
158}
159
160/*
161 * Freeing a Namespace
162 */
163void xmlFreeNs(xmlNsPtr cur) {
164 if (cur == NULL) {
165 fprintf(stderr, "xmlFreeNs : ns == NULL\n");
166 return;
167 }
168 if (cur->href != NULL) free((char *) cur->href);
169 if (cur->prefix != NULL) free((char *) cur->prefix);
170 memset(cur, -1, sizeof(xmlNs));
171 free(cur);
172}
173
174/*
175 * Freeing a Namespace list
176 */
177void xmlFreeNsList(xmlNsPtr cur) {
178 xmlNsPtr next;
179 if (cur == NULL) {
180 fprintf(stderr, "xmlFreeNsList : ns == NULL\n");
181 return;
182 }
183 while (cur != NULL) {
184 next = cur->next;
185 xmlFreeNs(cur);
186 cur = next;
187 }
188}
189
190/*
191 * Creation of a new DTD.
192 */
193xmlDtdPtr xmlNewDtd(xmlDocPtr doc, const CHAR *name,
194 const CHAR *ExternalID, const CHAR *SystemID) {
195 xmlDtdPtr cur;
196
197 if (doc->dtd != NULL) {
198 fprintf(stderr, "xmlNewDtd(%s): document %s already have a DTD %s\n",
199 /* !!! */ (char *) name, doc->name, /* !!! */ (char *)doc->dtd->name);
200 }
201
202 /*
203 * Allocate a new DTD and fill the fields.
204 */
205 cur = (xmlDtdPtr) malloc(sizeof(xmlDtd));
206 if (cur == NULL) {
207 fprintf(stderr, "xmlNewNs : malloc failed\n");
208 return(NULL);
209 }
210
211 if (name != NULL)
212 cur->name = xmlStrdup(name);
213 else
214 cur->name = NULL;
215 if (ExternalID != NULL)
216 cur->ExternalID = xmlStrdup(ExternalID);
217 else
218 cur->ExternalID = NULL;
219 if (SystemID != NULL)
220 cur->SystemID = xmlStrdup(SystemID);
221 else
222 cur->SystemID = NULL;
223 cur->elements = NULL;
224 cur->entities = NULL;
225 doc->dtd = cur;
226
227 return(cur);
228}
229
230/*
231 * Freeing a DTD
232 */
233void xmlFreeDtd(xmlDtdPtr cur) {
234 if (cur == NULL) {
235 fprintf(stderr, "xmlFreeDtd : DTD == NULL\n");
236 return;
237 }
238 if (cur->name != NULL) free((char *) cur->name);
239 if (cur->SystemID != NULL) free((char *) cur->SystemID);
240 if (cur->ExternalID != NULL) free((char *) cur->ExternalID);
241 if (cur->elements != NULL)
242 fprintf(stderr, "xmlFreeDtd: cur->elements != NULL !!! \n");
243 if (cur->entities != NULL)
244 xmlFreeEntitiesTable((xmlEntitiesTablePtr) cur->entities);
245 memset(cur, -1, sizeof(xmlDtd));
246 free(cur);
247}
248
249/*
250 * Creation of a new document
251 */
252xmlDocPtr xmlNewDoc(const CHAR *version) {
253 xmlDocPtr cur;
254
255 if (version == NULL) {
256 fprintf(stderr, "xmlNewDoc : version == NULL\n");
257 return(NULL);
258 }
259
260 /*
261 * Allocate a new document and fill the fields.
262 */
263 cur = (xmlDocPtr) malloc(sizeof(xmlDoc));
264 if (cur == NULL) {
265 fprintf(stderr, "xmlNewDoc : malloc failed\n");
266 return(NULL);
267 }
268
269 cur->version = xmlStrdup(version);
270 cur->name = NULL;
271 cur->root = NULL;
272 cur->dtd = NULL;
273 cur->oldNs = NULL;
274 cur->encoding = NULL;
275 cur->entities = NULL;
276 cur->standalone = -1;
277 return(cur);
278}
279
280/*
281 * Freeing a document : all the tree is freed too.
282 */
283void xmlFreeDoc(xmlDocPtr cur) {
284 if (cur == NULL) {
285 fprintf(stderr, "xmlFreeDoc : document == NULL\n");
286 return;
287 }
288 free((char *) cur->version);
289 if (cur->name != NULL) free((char *) cur->name);
290 if (cur->encoding != NULL) free((char *) cur->encoding);
291 if (cur->root != NULL) xmlFreeNode(cur->root);
292 if (cur->dtd != NULL) xmlFreeDtd(cur->dtd);
293 if (cur->entities != NULL)
294 xmlFreeEntitiesTable((xmlEntitiesTablePtr) cur->entities);
295 memset(cur, -1, sizeof(xmlDoc));
296 free(cur);
297}
298
299/*
300 * Creation of a new property of a node.
301 */
302xmlAttrPtr xmlNewProp(xmlNodePtr node, const CHAR *name, const CHAR *value) {
303 xmlAttrPtr cur;
304
305 if (name == NULL) {
306 fprintf(stderr, "xmlNewProp : name == NULL\n");
307 return(NULL);
308 }
309
310 /*
311 * Allocate a new property and fill the fields.
312 */
313 cur = (xmlAttrPtr) malloc(sizeof(xmlAttr));
314 if (cur == NULL) {
315 fprintf(stderr, "xmlNewProp : malloc failed\n");
316 return(NULL);
317 }
318
319 cur->node = node;
320 cur->name = xmlStrdup(name);
321 if (value != NULL)
322 cur->value = xmlStrdup(value);
323 else
324 cur->value = NULL;
325
326 /*
327 * Add it at the end to preserve parsing order ...
328 */
329 cur->next = NULL;
330 if (node != NULL) {
331 if (node->properties == NULL) {
332 node->properties = cur;
333 } else {
334 xmlAttrPtr prev = node->properties;
335
336 while (prev->next != NULL) prev = prev->next;
337 prev->next = cur;
338 }
339 }
340 return(cur);
341}
342
343/*
344 * Freeing a property list : Free a property and all its siblings,
345 * this is a recursive behaviour, all the childs
346 * are freed too.
347 */
348void xmlFreePropList(xmlAttrPtr cur) {
349 xmlAttrPtr next;
350 if (cur == NULL) {
351 fprintf(stderr, "xmlFreePropList : property == NULL\n");
352 return;
353 }
354 while (cur != NULL) {
355 next = cur->next;
356 xmlFreeProp(cur);
357 cur = next;
358 }
359}
360
361/*
362 * Freeing a property.
363 */
364void xmlFreeProp(xmlAttrPtr cur) {
365 if (cur == NULL) {
366 fprintf(stderr, "xmlFreeProp : property == NULL\n");
367 return;
368 }
369 if (cur->name != NULL) free((char *) cur->name);
370 if (cur->value != NULL) free((char *) cur->value);
371 memset(cur, -1, sizeof(xmlAttr));
372 free(cur);
373}
374
375/*
376 * Creation of a new node element in a given DTD.
377 * We assume that the "name" has already being strdup'd !
378 */
379xmlNodePtr xmlNewNode(xmlNsPtr ns, const CHAR *name, CHAR *content) {
380 xmlNodePtr cur;
381
382 if (name == NULL) {
383 fprintf(stderr, "xmlNewNode : name == NULL\n");
384 return(NULL);
385 }
386
387 /*
388 * Allocate a new node and fill the fields.
389 */
390 cur = (xmlNodePtr) malloc(sizeof(xmlNode));
391 if (cur == NULL) {
392 fprintf(stderr, "xmlNewNode : malloc failed\n");
393 return(NULL);
394 }
395
396 cur->parent = NULL;
397 cur->next = NULL;
398 cur->childs = NULL;
399 cur->properties = NULL;
400 cur->type = 0;
401 cur->name = xmlStrdup(name);
402 cur->ns = ns;
403 cur->nsDef = NULL;
404 if (content != NULL)
405 cur->content = xmlStrdup(content);
406 else
407 cur->content = NULL;
408 return(cur);
409}
410
411/*
412 * Creation of a new node contening text.
413 */
414xmlNodePtr xmlNewText(const CHAR *content) {
415 xmlNodePtr cur;
416
417 /*
418 * Allocate a new node and fill the fields.
419 */
420 cur = (xmlNodePtr) malloc(sizeof(xmlNode));
421 if (cur == NULL) {
422 fprintf(stderr, "xmlNewText : malloc failed\n");
423 return(NULL);
424 }
425
426 cur->parent = NULL;
427 cur->next = NULL;
428 cur->childs = NULL;
429 cur->properties = NULL;
430 cur->type = XML_TYPE_TEXT;
431 cur->name = xmlStrdup(xmlStringText);
432 cur->ns = NULL;
433 cur->nsDef = NULL;
434 if (content != NULL)
435 cur->content = xmlStrdup(content);
436 else
437 cur->content = NULL;
438 return(cur);
439}
440
441/*
442 * Creation of a new node contening text.
443 */
444xmlNodePtr xmlNewTextLen(const CHAR *content, int len) {
445 xmlNodePtr cur;
446
447 /*
448 * Allocate a new node and fill the fields.
449 */
450 cur = (xmlNodePtr) malloc(sizeof(xmlNode));
451 if (cur == NULL) {
452 fprintf(stderr, "xmlNewText : malloc failed\n");
453 return(NULL);
454 }
455
456 cur->parent = NULL;
457 cur->next = NULL;
458 cur->childs = NULL;
459 cur->properties = NULL;
460 cur->type = XML_TYPE_TEXT;
461 cur->name = xmlStrdup(xmlStringText);
462 cur->ns = NULL;
463 cur->nsDef = NULL;
464 if (content != NULL)
465 cur->content = xmlStrndup(content, len);
466 else
467 cur->content = NULL;
468 return(cur);
469}
470
471/*
472 * Creation of a new node contening a comment.
473 */
474xmlNodePtr xmlNewComment(CHAR *content) {
475 xmlNodePtr cur;
476
477 /*
478 * Allocate a new node and fill the fields.
479 */
480 cur = (xmlNodePtr) malloc(sizeof(xmlNode));
481 if (cur == NULL) {
482 fprintf(stderr, "xmlNewComment : malloc failed\n");
483 return(NULL);
484 }
485
486 cur->parent = NULL;
487 cur->next = NULL;
488 cur->childs = NULL;
489 cur->properties = NULL;
490 cur->type = XML_TYPE_COMMENT;
491 cur->name = xmlStrdup(xmlStringText);
492 cur->ns = NULL;
493 cur->nsDef = NULL;
494 if (content != NULL)
495 cur->content = xmlStrdup(content);
496 else
497 cur->content = NULL;
498 return(cur);
499}
500
501/*
502 * Creation of a new child element, added at the end.
503 */
504xmlNodePtr xmlNewChild(xmlNodePtr parent, xmlNsPtr ns,
505 const CHAR *name, CHAR *content) {
506 xmlNodePtr cur, prev;
507
508 if (parent == NULL) {
509 fprintf(stderr, "xmlNewChild : parent == NULL\n");
510 return(NULL);
511 }
512
513 if (name == NULL) {
514 fprintf(stderr, "xmlNewChild : name == NULL\n");
515 return(NULL);
516 }
517
518 /*
519 * Allocate a new node
520 */
521 if (ns == NULL)
522 cur = xmlNewNode(parent->ns, name, content);
523 else
524 cur = xmlNewNode(ns, name, content);
525 if (cur == NULL) return(NULL);
526
527 /*
528 * add the new element at the end of the childs list.
529 */
530 cur->parent = parent;
531 if (parent->childs == NULL) {
532 parent->childs = cur;
533 } else {
534 prev = parent->childs;
535 while (prev->next != NULL) prev = prev->next;
536 prev->next = cur;
537 }
538
539 return(cur);
540}
541
542/*
543 * Add a new child element, added at the end.
544 */
545xmlNodePtr xmlAddChild(xmlNodePtr parent, xmlNodePtr cur) {
546 xmlNodePtr prev;
547
548 if (parent == NULL) {
549 fprintf(stderr, "xmladdChild : parent == NULL\n");
550 return(NULL);
551 }
552
553 if (cur == NULL) {
554 fprintf(stderr, "xmladdChild : child == NULL\n");
555 return(NULL);
556 }
557
558 /*
559 * add the new element at the end of the childs list.
560 */
561 cur->parent = parent;
562 if (parent->childs == NULL) {
563 parent->childs = cur;
564 } else {
565 prev = parent->childs;
566 while (prev->next != NULL) prev = prev->next;
567 prev->next = cur;
568 }
569
570 return(cur);
571}
572
573/*
574 * Search the last child, if any.
575 */
576xmlNodePtr xmlGetLastChild(xmlNodePtr parent) {
577 xmlNodePtr last;
578
579 if (parent == NULL) {
580 fprintf(stderr, "xmlGetLastChild : parent == NULL\n");
581 return(NULL);
582 }
583
584 /*
585 * add the new element at the end of the childs list.
586 */
587 if (parent->childs == NULL) {
588 return(NULL);
589 } else {
590 last = parent->childs;
591 while (last->next != NULL) last = last->next;
592 }
593 return(last);
594}
595
596/*
597 * Freeing a node list : Free a node and all its siblings,
598 * this is a recursive behaviour, all the childs
599 * are freed too.
600 */
601void xmlFreeNodeList(xmlNodePtr cur) {
602 xmlNodePtr next;
603 if (cur == NULL) {
604 fprintf(stderr, "xmlFreeNodeList : node == NULL\n");
605 return;
606 }
607 while (cur != NULL) {
608 next = cur->next;
609 xmlFreeNode(cur);
610 cur = next;
611 }
612}
613
614/*
615 * Freeing a node : this is a recursive behaviour, all the childs
616 * are freed too.
617 */
618void xmlFreeNode(xmlNodePtr cur) {
619 if (cur == NULL) {
620 fprintf(stderr, "xmlFreeNode : node == NULL\n");
621 return;
622 }
623 if (cur->properties != NULL) xmlFreePropList(cur->properties);
624 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
625 if (cur->content != NULL) free(cur->content);
626 if (cur->name != NULL) free((char *) cur->name);
627 if (cur->nsDef != NULL) xmlFreeNsList(cur->nsDef);
628 memset(cur, -1, sizeof(xmlNode));
629 free(cur);
630}
631
632/************************************************************************
633 * *
634 * Content access functions *
635 * *
636 ************************************************************************/
637
638/*
639 * Changing the content of a node.
640 */
641void xmlNodeSetContent(xmlNodePtr cur, const CHAR *content) {
642 if (cur == NULL) {
643 fprintf(stderr, "xmlNodeSetContent : node == NULL\n");
644 return;
645 }
646 if (cur->content != NULL) free(cur->content);
647 if (content != NULL)
648 cur->content = xmlStrdup(content);
649 else
650 cur->content = NULL;
651}
652
653/*
654 * Changing the content of a node.
655 */
656void xmlNodeSetContentLen(xmlNodePtr cur, const CHAR *content, int len) {
657 if (cur == NULL) {
658 fprintf(stderr, "xmlNodeSetContent : node == NULL\n");
659 return;
660 }
661 if (cur->content != NULL) free(cur->content);
662 if (content != NULL)
663 cur->content = xmlStrndup(content, len);
664 else
665 cur->content = NULL;
666}
667
668/*
669 * Adding content to a node.
670 */
671void xmlNodeAddContent(xmlNodePtr cur, const CHAR *content) {
672 if (cur == NULL) {
673 fprintf(stderr, "xmlNodeAddContent : node == NULL\n");
674 return;
675 }
676 cur->content = xmlStrcat(cur->content, content);
677}
678
679/*
680 * Adding content to a node.
681 */
682void xmlNodeAddContentLen(xmlNodePtr cur, const CHAR *content, int len) {
683 if (cur == NULL) {
684 fprintf(stderr, "xmlNodeAddContent : node == NULL\n");
685 return;
686 }
687 cur->content = xmlStrncat(cur->content, content, len);
688}
689
690/*
691 * Search a Ns registered under a given name space for a document.
692 * recurse on the parents until it finds the defined namespace
693 * or return NULL otherwise.
694 *
695 * Note : nameSpace == NULL is valid, this is a search for the default
696 * namespace.
697 */
698xmlNsPtr xmlSearchNs(xmlDocPtr doc, xmlNodePtr node, const CHAR *nameSpace) {
699 xmlNsPtr cur;
700
701 while (node != NULL) {
702 cur = node->nsDef;
703 while (cur != NULL) {
704 if ((cur->prefix == NULL) && (nameSpace == NULL))
705 return(cur);
706 if ((cur->prefix != NULL) && (nameSpace != NULL) &&
707 (!xmlStrcmp(cur->prefix, nameSpace)))
708 return(cur);
709 cur = cur->next;
710 }
711 node = node->parent;
712 }
713 if (doc != NULL) {
714 cur = doc->oldNs;
715 while (cur != NULL) {
716 if ((cur->prefix != NULL) && (nameSpace != NULL) &&
717 (!xmlStrcmp(cur->prefix, nameSpace)))
718 return(cur);
719 cur = cur->next;
720 }
721 }
722 return(NULL);
723}
724
725/*
726 * Search a Ns aliasing a given URI
727 * recurse on the parents until it finds the defined namespace
728 * or return NULL otherwise.
729 */
730xmlNsPtr xmlSearchNsByHref(xmlDocPtr doc, xmlNodePtr node, const CHAR *href) {
731 xmlNsPtr cur;
732
733 while (node != NULL) {
734 cur = node->nsDef;
735 while (cur != NULL) {
736 if ((cur->href != NULL) && (href != NULL) &&
737 (!xmlStrcmp(cur->href, href)))
738 return(cur);
739 cur = cur->next;
740 }
741 node = node->parent;
742 }
743 if (doc != NULL) {
744 cur = doc->oldNs;
745 while (cur != NULL) {
746 if ((cur->href != NULL) && (href != NULL) &&
747 (!xmlStrcmp(cur->href, href)))
748 return(cur);
749 cur = cur->next;
750 }
751 }
752 return(NULL);
753}
754
755/*
756 * Reading the content of a given property.
757 */
758const CHAR *xmlGetProp(xmlNodePtr node, const CHAR *name) {
759 xmlAttrPtr prop = node->properties;
760
761 while (prop != NULL) {
762 if (!xmlStrcmp(prop->name, name)) return(prop->value);
763 prop = prop->next;
764 }
765 return(NULL);
766}
767
768/*
769 * Setting the content of a given property.
770 */
771xmlAttrPtr xmlSetProp(xmlNodePtr node, const CHAR *name, const CHAR *value) {
772 xmlAttrPtr prop = node->properties;
773
774 while (prop != NULL) {
775 if (!xmlStrcmp(prop->name, name)) {
776 if (prop->value != NULL)
777 free((char *) prop->value);
778 prop->value = NULL;
779 if (value != NULL)
780 prop->value = xmlStrdup(value);
781 return(prop);
782 }
783 prop = prop->next;
784 }
785 prop = xmlNewProp(node, name, value);
786 return(prop);
787}
788
789/*
790 * Is this node a piece of text
791 */
792int xmlNodeIsText(xmlNodePtr node) {
793 if (node == NULL) return(0);
794
795 if (node->type == XML_TYPE_TEXT) return(1);
796 return(0);
797}
798
799/*
800 * Concat a piece of text to an existing text node
801 *
802 * TODO !!! Should be optimized with a bit of preallocation.
803 */
804void xmlTextConcat(xmlNodePtr node, const CHAR *content, int len) {
805 if (node == NULL) return;
806
807 if (node->type != XML_TYPE_TEXT) {
808 fprintf(stderr, "xmlTextConcat: node is not text\n");
809 return;
810 }
811 node->content = xmlStrncat(node->content, content, len);
812}
813
814/************************************************************************
815 * *
816 * Output : to a FILE or in memory *
817 * *
818 ************************************************************************/
819
820/*
821 * routine which manage and grows an output buffer. One can write
822 * standard char array's (8 bits char) or CHAR's arrays.
823 */
824static CHAR *buffer = NULL;
825static int buffer_index = 0;
826static int buffer_size = 0;
827
828void xmlBufferWriteCHAR(const CHAR *string) {
829 const CHAR *cur;
830
831 if (buffer == NULL) {
832 buffer_size = 50000;
833 buffer = (CHAR *) malloc(buffer_size * sizeof(CHAR));
834 if (buffer == NULL) {
835 fprintf(stderr, "xmlBufferWrite : out of memory!\n");
836 exit(1);
837 }
838 }
839
840 if (string == NULL) return;
841 for (cur = string;*cur != 0;cur++) {
842 if (buffer_index + 10 >= buffer_size) {
843 buffer_size *= 2;
844 buffer = (CHAR *) realloc(buffer, buffer_size * sizeof(CHAR));
845 if (buffer == NULL) {
846 fprintf(stderr, "xmlBufferWrite : out of memory!\n");
847 exit(1);
848 }
849 }
850 buffer[buffer_index++] = *cur;
851 }
852 buffer[buffer_index] = 0;
853}
854
855void xmlBufferWriteChar(const char *string) {
856 const char *cur;
857
858 if (buffer == NULL) {
859 buffer_size = 50000;
860 buffer = (CHAR *) malloc(buffer_size * sizeof(CHAR));
861 if (buffer == NULL) {
862 fprintf(stderr, "xmlBufferWrite : out of memory!\n");
863 exit(1);
864 }
865 }
866
867 if (string == NULL) return;
868 for (cur = string;*cur != 0;cur++) {
869 if (buffer_index + 10 >= buffer_size) {
870 buffer_size *= 2;
871 buffer = (CHAR *) realloc(buffer, buffer_size * sizeof(CHAR));
872 if (buffer == NULL) {
873 fprintf(stderr, "xmlBufferWrite : out of memory!\n");
874 exit(1);
875 }
876 }
877 buffer[buffer_index++] = *cur;
878 }
879 buffer[buffer_index] = 0;
880}
881
882/*
883 * Dump the global Namespace inherited from the old WD.
884 * Within the context of the document header.
885 */
886static void xmlGlobalNsDump(xmlNsPtr cur) {
887 if (cur == NULL) {
888 fprintf(stderr, "xmlGlobalNsDump : Ns == NULL\n");
889 return;
890 }
891 if (cur->type == XML_GLOBAL_NAMESPACE) {
892 xmlBufferWriteChar("<?namespace");
893 if (cur->href != NULL) {
894 xmlBufferWriteChar(" href=\"");
895 xmlBufferWriteCHAR(cur->href);
896 xmlBufferWriteChar("\"");
897 }
898 if (cur->prefix != NULL) {
899 xmlBufferWriteChar(" AS=\"");
900 xmlBufferWriteCHAR(cur->prefix);
901 xmlBufferWriteChar("\"");
902 }
903 xmlBufferWriteChar("?>\n");
904 }
905}
906
907/*
908 * Dump an old global XML Namespace list
909 */
910
911static void xmlGlobalNsListDump(xmlNsPtr cur) {
912 while (cur != NULL) {
913 xmlGlobalNsDump(cur);
914 cur = cur->next;
915 }
916}
917
918/*
919 * Dump a local Namespace definition.
920 * Within the context of an element attributes.
921 */
922static void xmlNsDump(xmlNsPtr cur) {
923 if (cur == NULL) {
924 fprintf(stderr, "xmlNsDump : Ns == NULL\n");
925 return;
926 }
927 if (cur->type == XML_LOCAL_NAMESPACE) {
928 /* Within the context of an element attributes */
929 if (cur->prefix != NULL) {
930 xmlBufferWriteChar(" xmlns:");
931 xmlBufferWriteCHAR(cur->prefix);
932 } else
933 xmlBufferWriteChar(" xmlns");
934 xmlBufferWriteChar("=\"");
935 xmlBufferWriteCHAR(cur->href);
936 xmlBufferWriteChar("\"");
937 }
938}
939
940/*
941 * Dump an XML Namespace list
942 */
943
944static void xmlNsListDump(xmlNsPtr cur) {
945 while (cur != NULL) {
946 xmlNsDump(cur);
947 cur = cur->next;
948 }
949}
950
951/*
952 * Dump an XML DTD
953 */
954
955static void xmlDtdDump(xmlDocPtr doc) {
956 xmlDtdPtr cur = doc->dtd;
957
958 if (cur == NULL) {
959 fprintf(stderr, "xmlDtdDump : DTD == NULL\n");
960 return;
961 }
962 xmlBufferWriteChar("<!DOCTYPE ");
963 xmlBufferWriteCHAR(cur->name);
964 if (cur->ExternalID != NULL) {
965 xmlBufferWriteChar(" PUBLIC \"");
966 xmlBufferWriteCHAR(cur->ExternalID);
967 xmlBufferWriteChar("\" \"");
968 xmlBufferWriteCHAR(cur->SystemID);
969 xmlBufferWriteChar("\"");
970 } else if (cur->SystemID != NULL) {
971 xmlBufferWriteChar(" SYSTEM \"");
972 xmlBufferWriteCHAR(cur->SystemID);
973 xmlBufferWriteChar("\"");
974 }
975 if ((cur->entities == NULL) && (doc->entities == NULL)) {
976 xmlBufferWriteChar(">\n");
977 return;
978 }
979 xmlBufferWriteChar(" [\n");
980 if (cur->entities != NULL)
981 xmlDumpEntitiesTable((xmlEntitiesTablePtr) cur->entities);
982 if (doc->entities != NULL)
983 xmlDumpEntitiesTable((xmlEntitiesTablePtr) doc->entities);
984 xmlBufferWriteChar("]");
985
986 /* TODO !!! a lot more things to dump ... */
987 xmlBufferWriteChar(">\n");
988}
989
990/*
991 * Dump an XML property
992 */
993
994static void xmlAttrDump(xmlDocPtr doc, xmlAttrPtr cur) {
995 if (cur == NULL) {
996 fprintf(stderr, "xmlAttrDump : property == NULL\n");
997 return;
998 }
999 xmlBufferWriteChar(" ");
1000 xmlBufferWriteCHAR(cur->name);
1001 if (cur->value) {
1002 xmlBufferWriteChar("=\"");
1003 xmlBufferWriteCHAR(xmlEncodeEntities(doc, cur->value));
1004 xmlBufferWriteChar("\"");
1005 }
1006}
1007
1008/*
1009 * Dump an XML property list
1010 */
1011
1012static void xmlAttrListDump(xmlDocPtr doc, xmlAttrPtr cur) {
1013 if (cur == NULL) {
1014 fprintf(stderr, "xmlAttrListDump : property == NULL\n");
1015 return;
1016 }
1017 while (cur != NULL) {
1018 xmlAttrDump(doc, cur);
1019 cur = cur->next;
1020 }
1021}
1022
1023/*
1024 * Dump an XML node list
1025 */
1026
1027static void xmlNodeDump(xmlDocPtr doc, xmlNodePtr cur, int level);
1028static void xmlNodeListDump(xmlDocPtr doc, xmlNodePtr cur, int level) {
1029 if (cur == NULL) {
1030 fprintf(stderr, "xmlNodeListDump : node == NULL\n");
1031 return;
1032 }
1033 while (cur != NULL) {
1034 xmlNodeDump(doc, cur, level);
1035 cur = cur->next;
1036 }
1037}
1038
1039/*
1040 * Dump an XML node
1041 */
1042
1043static void xmlNodeDump(xmlDocPtr doc, xmlNodePtr cur, int level) {
1044 int i;
1045
1046 if (cur == NULL) {
1047 fprintf(stderr, "xmlNodeDump : node == NULL\n");
1048 return;
1049 }
1050 if (cur->type == XML_TYPE_TEXT) {
1051 if (cur->content != NULL)
1052 xmlBufferWriteCHAR(xmlEncodeEntities(doc, cur->content));
1053 return;
1054 }
1055 if (cur->type == XML_TYPE_COMMENT) {
1056 if (cur->content != NULL) {
1057 xmlBufferWriteChar("<!--");
1058 xmlBufferWriteCHAR(cur->content);
1059 xmlBufferWriteChar("-->");
1060 }
1061 return;
1062 }
1063 if (xmlIndentTreeOutput)
1064 for (i = 0;i < level;i++)
1065 xmlBufferWriteChar(" ");
1066
1067 xmlBufferWriteChar("<");
1068 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
1069 xmlBufferWriteCHAR(cur->ns->prefix);
1070 xmlBufferWriteChar(":");
1071 }
1072
1073 xmlBufferWriteCHAR(cur->name);
1074 if (cur->nsDef)
1075 xmlNsListDump(cur->nsDef);
1076 if (cur->properties != NULL)
1077 xmlAttrListDump(doc, cur->properties);
1078
1079 if ((cur->content == NULL) && (cur->childs == NULL)) {
1080 xmlBufferWriteChar("/>\n");
1081 return;
1082 }
1083 xmlBufferWriteChar(">");
1084 if (cur->content != NULL)
1085 xmlBufferWriteCHAR(xmlEncodeEntities(doc, cur->content));
1086 if (cur->childs != NULL) {
1087 xmlBufferWriteChar("\n");
1088 xmlNodeListDump(doc, cur->childs, level + 1);
1089 if (xmlIndentTreeOutput)
1090 for (i = 0;i < level;i++)
1091 xmlBufferWriteChar(" ");
1092 }
1093 xmlBufferWriteChar("</");
1094 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
1095 xmlBufferWriteCHAR(cur->ns->prefix);
1096 xmlBufferWriteChar(":");
1097 }
1098
1099 xmlBufferWriteCHAR(cur->name);
1100 xmlBufferWriteChar(">\n");
1101}
1102
1103/*
1104 * Dump an XML document
1105 */
1106static void xmlDocContentDump(xmlDocPtr cur) {
1107 if (oldXMLWDcompatibility)
1108 xmlBufferWriteChar("<?XML version=\"");
1109 else
1110 xmlBufferWriteChar("<?xml version=\"");
1111 xmlBufferWriteCHAR(cur->version);
1112 xmlBufferWriteChar("\"");
1113 if (cur->encoding != NULL) {
1114 xmlBufferWriteChar(" encoding=\"");
1115 xmlBufferWriteCHAR(cur->encoding);
1116 xmlBufferWriteChar("\"");
1117 }
1118 switch (cur->standalone) {
1119 case 0:
1120 xmlBufferWriteChar(" standalone=\"no\"");
1121 break;
1122 case 1:
1123 xmlBufferWriteChar(" standalone=\"yes\"");
1124 break;
1125 }
1126 xmlBufferWriteChar("?>\n");
1127 if ((cur->dtd != NULL) || (cur->entities != NULL))
1128 xmlDtdDump(cur);
1129 if (cur->root != NULL) {
1130 /* global namespace definitions, the old way */
1131 if (oldXMLWDcompatibility)
1132 xmlGlobalNsListDump(cur->oldNs);
1133 else
1134 xmlUpgradeOldNs(cur);
1135 xmlNodeDump(cur, cur->root, 0);
1136 }
1137}
1138
1139/*
1140 * Dump an XML document to memory.
1141 */
1142
1143void xmlDocDumpMemory(xmlDocPtr cur, CHAR**mem, int *size) {
1144 if (cur == NULL) {
1145 fprintf(stderr, "xmlDocDump : document == NULL\n");
1146 *mem = NULL;
1147 *size = 0;
1148 return;
1149 }
1150 buffer_index = 0;
1151 xmlDocContentDump(cur);
1152
1153 *mem = buffer;
1154 *size = buffer_index;
1155}
1156
1157/*
Daniel Veillard151b1b01998-09-23 00:49:46 +00001158 * Get the compression mode
1159 */
1160
1161static int xmlCompressMode = 0;
1162
1163int xmlGetCompressMode(void) {
1164 return(xmlCompressMode);
1165}
1166void xmlSetCompressMode(int mode) {
1167 if (mode < 0) xmlCompressMode = 0;
1168 if (mode > 9) xmlCompressMode = 9;
1169 else xmlCompressMode = mode;
1170}
1171
1172/*
Daniel Veillard260a68f1998-08-13 03:39:55 +00001173 * Dump an XML document to the given FD
1174 */
1175
1176void xmlDocDump(FILE *f, xmlDocPtr cur) {
1177 if (cur == NULL) {
1178 fprintf(stderr, "xmlDocDump : document == NULL\n");
1179 return;
1180 }
1181 buffer_index = 0;
1182 xmlDocContentDump(cur);
1183
1184 fwrite(buffer, sizeof(CHAR), buffer_index, f);
1185}
1186
Daniel Veillard151b1b01998-09-23 00:49:46 +00001187/*
1188 * Dump an XML document to a file.
1189 */
1190
1191int xmlSaveFile(const char *filename, xmlDocPtr cur) {
1192#ifdef HAVE_ZLIB_H
1193 gzFile zoutput = NULL;
1194 char mode[15];
1195#endif
1196 FILE *output;
1197 int ret;
1198
1199#ifdef HAVE_ZLIB_H
1200 if ((xmlCompressMode > 0) && (xmlCompressMode <= 9)) {
1201 sprintf(mode, "w%d", xmlCompressMode);
1202 zoutput = gzopen(filename, mode);
1203 }
1204 if (zoutput == NULL) {
1205#endif
1206 output = fopen(filename, "w");
1207 if (output == NULL) return(-1);
1208#ifdef HAVE_ZLIB_H
1209 }
1210#endif
1211
1212 /*
1213 * save the content to a temp buffer.
1214 */
1215 buffer_index = 0;
1216 xmlDocContentDump(cur);
1217
1218#ifdef HAVE_ZLIB_H
1219 if (zoutput != NULL) {
1220 ret = gzwrite(zoutput, buffer, sizeof(CHAR) * buffer_index);
1221 gzclose(zoutput);
1222 return(ret);
1223 }
1224#endif
1225 ret = fwrite(buffer, sizeof(CHAR), buffer_index, output);
1226 fclose(output);
1227 return(ret * sizeof(CHAR));
1228}
1229
Daniel Veillard260a68f1998-08-13 03:39:55 +00001230/************************************************************************
1231 * *
1232 * Debug *
1233 * *
1234 ************************************************************************/
1235
1236#ifdef STANDALONE
1237int main(void) {
1238 xmlDocPtr doc;
1239 xmlNodePtr tree, subtree;
1240 xmlNsPtr ns1;
1241 xmlNsPtr ns2;
1242
1243 /*
1244 * build a fake XML document
1245 */
1246 doc = xmlNewDoc("1.0");
1247 ns1 = xmlNewNs(doc, "http://www.ietf.org/standards/dav/", "D");
1248 ns2 = xmlNewNs(doc, "http://www.w3.com/standards/z39.50/", "Z");
1249 doc->root = xmlNewNode(ns1, "multistatus", NULL);
1250 tree = xmlNewChild(doc->root, NULL, "response", NULL);
1251 subtree = xmlNewChild(tree, NULL, "prop", NULL);
1252 xmlNewChild(subtree, ns2, "Authors", NULL);
1253 subtree = xmlNewChild(tree, NULL, "status", "HTTP/1.1 420 Method Failure");
1254 tree = xmlNewChild(doc->root, NULL, "response", NULL);
1255 subtree = xmlNewChild(tree, NULL, "prop", NULL);
1256 xmlNewChild(subtree, ns2, "Copyright-Owner", NULL);
1257 subtree = xmlNewChild(tree, NULL, "status", "HTTP/1.1 409 Conflict");
1258 tree = xmlNewChild(doc->root, NULL, "responsedescription",
1259 "Copyright Owner can not be deleted or altered");
1260
1261 /*
1262 * print it.
1263 */
1264 xmlDocDump(stdout, doc);
1265
1266 /*
1267 * free it.
1268 */
1269 xmlFreeDoc(doc);
1270 return(0);
1271}
1272#endif