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