blob: 0aeff3ce13cccb397234cf76d48f9c0a9dd70439 [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 Veillard260a68f1998-08-13 03:39:55 +000042void xmlUpgradeOldNs(xmlDocPtr doc) {
43 xmlNsPtr cur;
44
45 if ((doc == NULL) || (doc->oldNs == NULL)) return;
46 if (doc->root == NULL) {
47 fprintf(stderr, "xmlUpgradeOldNs: failed no root !\n");
48 return;
49 }
50
51 cur = doc->oldNs;
52 while (cur->next != NULL) {
53 cur->type = XML_LOCAL_NAMESPACE;
54 cur = cur->next;
55 }
56 cur->type = XML_LOCAL_NAMESPACE;
57 cur->next = doc->root->nsDef;
58 doc->root->nsDef = doc->oldNs;
59 doc->oldNs = NULL;
60}
61
Daniel Veillard97b58771998-10-20 06:14:16 +000062/**
63 * xmlNewNs:
64 * @node: the element carrying the namespace
65 * @href: the URI associated
66 * @prefix: the prefix for the namespace
67 *
Daniel Veillard260a68f1998-08-13 03:39:55 +000068 * Creation of a new Namespace.
Daniel Veillard97b58771998-10-20 06:14:16 +000069 * return values: returns a new namespace pointer
Daniel Veillard260a68f1998-08-13 03:39:55 +000070 */
71xmlNsPtr xmlNewNs(xmlNodePtr node, const CHAR *href, const CHAR *prefix) {
72 xmlNsPtr cur;
73
74 if (href == NULL) {
75 fprintf(stderr, "xmlNewNs: href == NULL !\n");
76 return(NULL);
77 }
78
79 /*
80 * Allocate a new DTD and fill the fields.
81 */
82 cur = (xmlNsPtr) malloc(sizeof(xmlNs));
83 if (cur == NULL) {
84 fprintf(stderr, "xmlNewNs : malloc failed\n");
85 return(NULL);
86 }
87
88 cur->type = XML_LOCAL_NAMESPACE;
89 if (href != NULL)
90 cur->href = xmlStrdup(href);
91 else
92 cur->href = NULL;
93 if (prefix != NULL)
94 cur->prefix = xmlStrdup(prefix);
95 else
96 cur->prefix = NULL;
97
98 /*
99 * Add it at the end to preserve parsing order ...
100 */
101 cur->next = NULL;
102 if (node != NULL) {
103 if (node->nsDef == NULL) {
104 node->nsDef = cur;
105 } else {
106 xmlNsPtr prev = node->nsDef;
107
108 while (prev->next != NULL) prev = prev->next;
109 prev->next = cur;
110 }
111 }
112
113 return(cur);
114}
115
Daniel Veillard97b58771998-10-20 06:14:16 +0000116/**
117 * xmlNewGlobalNs:
118 * @doc: the document carrying the namespace
119 * @href: the URI associated
120 * @prefix: the prefix for the namespace
121 *
122 * Creation of a Namespace, the old way using PI and without scoping, to AVOID.
123 * return values: returns a new namespace pointer
Daniel Veillard260a68f1998-08-13 03:39:55 +0000124 */
125xmlNsPtr xmlNewGlobalNs(xmlDocPtr doc, const CHAR *href, const CHAR *prefix) {
126 xmlNsPtr cur;
127
128 /*
129 * Allocate a new DTD and fill the fields.
130 */
131 cur = (xmlNsPtr) malloc(sizeof(xmlNs));
132 if (cur == NULL) {
133 fprintf(stderr, "xmlNewNs : malloc failed\n");
134 return(NULL);
135 }
136
137 cur->type = XML_GLOBAL_NAMESPACE;
138 if (href != NULL)
139 cur->href = xmlStrdup(href);
140 else
141 cur->href = NULL;
142 if (prefix != NULL)
143 cur->prefix = xmlStrdup(prefix);
144 else
145 cur->prefix = NULL;
146
147 /*
148 * Add it at the end to preserve parsing order ...
149 */
150 cur->next = NULL;
151 if (doc != NULL) {
152 if (doc->oldNs == NULL) {
153 doc->oldNs = cur;
154 } else {
155 xmlNsPtr prev = doc->oldNs;
156
157 while (prev->next != NULL) prev = prev->next;
158 prev->next = cur;
159 }
160 }
161
162 return(cur);
163}
164
Daniel Veillard97b58771998-10-20 06:14:16 +0000165/**
166 * xmlSetNs:
167 * @node: a node in the document
168 * @ns: a namespace pointer
169 *
170 * Associate a namespace to a node, a posteriori.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000171 */
172void xmlSetNs(xmlNodePtr node, xmlNsPtr ns) {
173 if (node == NULL) {
174 fprintf(stderr, "xmlSetNs: node == NULL\n");
175 return;
176 }
177 node->ns = ns;
178}
179
Daniel Veillard97b58771998-10-20 06:14:16 +0000180/**
181 * xmlFreeNs:
182 * @cur: the namespace pointer
183 *
184 * Free up the structures associated to a namespace
Daniel Veillard260a68f1998-08-13 03:39:55 +0000185 */
186void xmlFreeNs(xmlNsPtr cur) {
187 if (cur == NULL) {
188 fprintf(stderr, "xmlFreeNs : ns == NULL\n");
189 return;
190 }
191 if (cur->href != NULL) free((char *) cur->href);
192 if (cur->prefix != NULL) free((char *) cur->prefix);
193 memset(cur, -1, sizeof(xmlNs));
194 free(cur);
195}
196
Daniel Veillard97b58771998-10-20 06:14:16 +0000197/**
198 * xmlFreeNsList:
199 * @cur: the first namespace pointer
200 *
201 * Free up all the structures associated to the chained namespaces.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000202 */
203void xmlFreeNsList(xmlNsPtr cur) {
204 xmlNsPtr next;
205 if (cur == NULL) {
206 fprintf(stderr, "xmlFreeNsList : ns == NULL\n");
207 return;
208 }
209 while (cur != NULL) {
210 next = cur->next;
211 xmlFreeNs(cur);
212 cur = next;
213 }
214}
215
Daniel Veillard97b58771998-10-20 06:14:16 +0000216/**
217 * xmlNewDtd:
218 * @doc: the document pointer
219 * @name: the DTD name
220 * @ExternalID: the external ID
221 * @SystemID: the system ID
222 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000223 * Creation of a new DTD.
Daniel Veillard97b58771998-10-20 06:14:16 +0000224 * return values: a pointer to the new DTD structure
Daniel Veillard260a68f1998-08-13 03:39:55 +0000225 */
226xmlDtdPtr xmlNewDtd(xmlDocPtr doc, const CHAR *name,
227 const CHAR *ExternalID, const CHAR *SystemID) {
228 xmlDtdPtr cur;
229
230 if (doc->dtd != NULL) {
231 fprintf(stderr, "xmlNewDtd(%s): document %s already have a DTD %s\n",
232 /* !!! */ (char *) name, doc->name, /* !!! */ (char *)doc->dtd->name);
233 }
234
235 /*
236 * Allocate a new DTD and fill the fields.
237 */
238 cur = (xmlDtdPtr) malloc(sizeof(xmlDtd));
239 if (cur == NULL) {
240 fprintf(stderr, "xmlNewNs : malloc failed\n");
241 return(NULL);
242 }
243
244 if (name != NULL)
245 cur->name = xmlStrdup(name);
246 else
247 cur->name = NULL;
248 if (ExternalID != NULL)
249 cur->ExternalID = xmlStrdup(ExternalID);
250 else
251 cur->ExternalID = NULL;
252 if (SystemID != NULL)
253 cur->SystemID = xmlStrdup(SystemID);
254 else
255 cur->SystemID = NULL;
256 cur->elements = NULL;
257 cur->entities = NULL;
258 doc->dtd = cur;
259
260 return(cur);
261}
262
Daniel Veillard97b58771998-10-20 06:14:16 +0000263/**
264 * xmlFreeDtd:
265 * @cur: the DTD structure to free up
266 *
267 * Free a DTD structure.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000268 */
269void xmlFreeDtd(xmlDtdPtr cur) {
270 if (cur == NULL) {
271 fprintf(stderr, "xmlFreeDtd : DTD == NULL\n");
272 return;
273 }
274 if (cur->name != NULL) free((char *) cur->name);
275 if (cur->SystemID != NULL) free((char *) cur->SystemID);
276 if (cur->ExternalID != NULL) free((char *) cur->ExternalID);
277 if (cur->elements != NULL)
278 fprintf(stderr, "xmlFreeDtd: cur->elements != NULL !!! \n");
279 if (cur->entities != NULL)
280 xmlFreeEntitiesTable((xmlEntitiesTablePtr) cur->entities);
281 memset(cur, -1, sizeof(xmlDtd));
282 free(cur);
283}
284
Daniel Veillard97b58771998-10-20 06:14:16 +0000285/**
286 * xmlNewDoc:
287 * @version: CHAR string giving the version of XML "1.0"
288 *
289 * Create a new document
Daniel Veillard260a68f1998-08-13 03:39:55 +0000290 */
291xmlDocPtr xmlNewDoc(const CHAR *version) {
292 xmlDocPtr cur;
293
294 if (version == NULL) {
295 fprintf(stderr, "xmlNewDoc : version == NULL\n");
296 return(NULL);
297 }
298
299 /*
300 * Allocate a new document and fill the fields.
301 */
302 cur = (xmlDocPtr) malloc(sizeof(xmlDoc));
303 if (cur == NULL) {
304 fprintf(stderr, "xmlNewDoc : malloc failed\n");
305 return(NULL);
306 }
307
Daniel Veillard33942841998-10-18 19:12:41 +0000308 cur->type = XML_DOCUMENT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000309 cur->version = xmlStrdup(version);
310 cur->name = NULL;
311 cur->root = NULL;
312 cur->dtd = NULL;
313 cur->oldNs = NULL;
314 cur->encoding = NULL;
315 cur->entities = NULL;
316 cur->standalone = -1;
Daniel Veillard15a8df41998-09-24 19:15:06 +0000317 cur->compression = xmlCompressMode;
Daniel Veillard27fb0751998-10-17 06:47:46 +0000318#ifndef WITHOUT_CORBA
319 cur->_private = NULL;
320 cur->vepv = NULL;
321#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000322 return(cur);
323}
324
Daniel Veillard97b58771998-10-20 06:14:16 +0000325/**
326 * xmlFreeDoc:
327 * @cur: pointer to the document
328 * @:
329 *
330 * Free up all the structures used by a document, tree included.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000331 */
332void xmlFreeDoc(xmlDocPtr cur) {
333 if (cur == NULL) {
334 fprintf(stderr, "xmlFreeDoc : document == NULL\n");
335 return;
336 }
337 free((char *) cur->version);
338 if (cur->name != NULL) free((char *) cur->name);
339 if (cur->encoding != NULL) free((char *) cur->encoding);
340 if (cur->root != NULL) xmlFreeNode(cur->root);
341 if (cur->dtd != NULL) xmlFreeDtd(cur->dtd);
342 if (cur->entities != NULL)
343 xmlFreeEntitiesTable((xmlEntitiesTablePtr) cur->entities);
344 memset(cur, -1, sizeof(xmlDoc));
345 free(cur);
346}
347
Daniel Veillard97b58771998-10-20 06:14:16 +0000348/**
349 * xmlNewProp:
350 * @node: the holding node
351 * @name: the name of the attribute
352 * @value: the value of the attribute
353 *
354 * Create a new property carried by a node.
355 * return values: a pointer to the attribute
Daniel Veillard260a68f1998-08-13 03:39:55 +0000356 */
357xmlAttrPtr xmlNewProp(xmlNodePtr node, const CHAR *name, const CHAR *value) {
358 xmlAttrPtr cur;
359
360 if (name == NULL) {
361 fprintf(stderr, "xmlNewProp : name == NULL\n");
362 return(NULL);
363 }
364
365 /*
366 * Allocate a new property and fill the fields.
367 */
368 cur = (xmlAttrPtr) malloc(sizeof(xmlAttr));
369 if (cur == NULL) {
370 fprintf(stderr, "xmlNewProp : malloc failed\n");
371 return(NULL);
372 }
373
Daniel Veillard33942841998-10-18 19:12:41 +0000374 cur->type = XML_ATTRIBUTE_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000375 cur->node = node;
376 cur->name = xmlStrdup(name);
377 if (value != NULL)
378 cur->value = xmlStrdup(value);
379 else
380 cur->value = NULL;
Daniel Veillard27fb0751998-10-17 06:47:46 +0000381#ifndef WITHOUT_CORBA
382 cur->_private = NULL;
383 cur->vepv = NULL;
384#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000385
386 /*
387 * Add it at the end to preserve parsing order ...
388 */
389 cur->next = NULL;
390 if (node != NULL) {
391 if (node->properties == NULL) {
392 node->properties = cur;
393 } else {
394 xmlAttrPtr prev = node->properties;
395
396 while (prev->next != NULL) prev = prev->next;
397 prev->next = cur;
398 }
399 }
400 return(cur);
401}
402
Daniel Veillard97b58771998-10-20 06:14:16 +0000403/**
404 * xmlFreePropList:
405 * @cur: the first property in the list
406 *
407 * Free a property and all its siblings, all the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000408 */
409void xmlFreePropList(xmlAttrPtr cur) {
410 xmlAttrPtr next;
411 if (cur == NULL) {
412 fprintf(stderr, "xmlFreePropList : property == NULL\n");
413 return;
414 }
415 while (cur != NULL) {
416 next = cur->next;
417 xmlFreeProp(cur);
418 cur = next;
419 }
420}
421
Daniel Veillard97b58771998-10-20 06:14:16 +0000422/**
423 * xmlFreeProp:
424 * @cur: the first property in the list
425 *
426 * Free one property, all the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000427 */
428void xmlFreeProp(xmlAttrPtr cur) {
429 if (cur == NULL) {
430 fprintf(stderr, "xmlFreeProp : property == NULL\n");
431 return;
432 }
433 if (cur->name != NULL) free((char *) cur->name);
434 if (cur->value != NULL) free((char *) cur->value);
435 memset(cur, -1, sizeof(xmlAttr));
436 free(cur);
437}
438
Daniel Veillard97b58771998-10-20 06:14:16 +0000439/**
440 * xmlNewNode:
441 * @ns: namespace if any
442 * @name: the node name
443 * @content: the text content if any
444 *
445 * Creation of a new node element. @ns and @content are optionnal (NULL).
446 * return values: a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000447 */
448xmlNodePtr xmlNewNode(xmlNsPtr ns, const CHAR *name, CHAR *content) {
449 xmlNodePtr cur;
450
451 if (name == NULL) {
452 fprintf(stderr, "xmlNewNode : name == NULL\n");
453 return(NULL);
454 }
455
456 /*
457 * Allocate a new node and fill the fields.
458 */
459 cur = (xmlNodePtr) malloc(sizeof(xmlNode));
460 if (cur == NULL) {
461 fprintf(stderr, "xmlNewNode : malloc failed\n");
462 return(NULL);
463 }
464
Daniel Veillard33942841998-10-18 19:12:41 +0000465 cur->type = XML_ELEMENT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000466 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000467 cur->parent = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000468 cur->next = NULL;
469 cur->prev = NULL;
470 cur->childs = NULL;
471 cur->properties = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000472 cur->type = 0;
473 cur->name = xmlStrdup(name);
474 cur->ns = ns;
475 cur->nsDef = NULL;
Daniel Veillard27fb0751998-10-17 06:47:46 +0000476#ifndef WITHOUT_CORBA
477 cur->_private = NULL;
478 cur->vepv = NULL;
479#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000480 if (content != NULL)
481 cur->content = xmlStrdup(content);
482 else
483 cur->content = NULL;
484 return(cur);
485}
486
Daniel Veillard97b58771998-10-20 06:14:16 +0000487/**
488 * xmlNewDocNode:
489 * @doc: the document
490 * @ns: namespace if any
491 * @name: the node name
492 * @content: the text content if any
493 *
494 * Creation of a new node element within a document. @ns and @content
495 * are optionnal (NULL).
496 * return values: a pointer to the new node object.
497 */
Daniel Veillard0bef1311998-10-14 02:36:47 +0000498xmlNodePtr xmlNewDocNode(xmlDocPtr doc, xmlNsPtr ns,
499 const CHAR *name, CHAR *content) {
500 xmlNodePtr cur;
501
502 cur = xmlNewNode(ns, name, content);
503 if (cur != NULL) cur->doc = doc;
504 return(cur);
505}
506
507
Daniel Veillard97b58771998-10-20 06:14:16 +0000508/**
509 * xmlNewText:
510 * @content: the text content
511 *
512 * Creation of a new text node.
513 * return values: a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000514 */
515xmlNodePtr xmlNewText(const CHAR *content) {
516 xmlNodePtr cur;
517
518 /*
519 * Allocate a new node and fill the fields.
520 */
521 cur = (xmlNodePtr) malloc(sizeof(xmlNode));
522 if (cur == NULL) {
523 fprintf(stderr, "xmlNewText : malloc failed\n");
524 return(NULL);
525 }
526
Daniel Veillard33942841998-10-18 19:12:41 +0000527 cur->type = XML_TEXT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000528 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000529 cur->parent = NULL;
530 cur->next = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000531 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000532 cur->childs = NULL;
533 cur->properties = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000534 cur->type = XML_TEXT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000535 cur->name = xmlStrdup(xmlStringText);
536 cur->ns = NULL;
537 cur->nsDef = NULL;
538 if (content != NULL)
539 cur->content = xmlStrdup(content);
540 else
541 cur->content = NULL;
542 return(cur);
543}
544
Daniel Veillard97b58771998-10-20 06:14:16 +0000545/**
546 * xmlNewDocText:
547 * @doc: the document
548 * @content: the text content
549 *
550 * Creation of a new text node within a document.
551 * return values: a pointer to the new node object.
552 */
Daniel Veillard0bef1311998-10-14 02:36:47 +0000553xmlNodePtr xmlNewDocText(xmlDocPtr doc, const CHAR *content) {
554 xmlNodePtr cur;
555
556 cur = xmlNewText(content);
557 if (cur != NULL) cur->doc = doc;
558 return(cur);
559}
560
Daniel Veillard97b58771998-10-20 06:14:16 +0000561/**
562 * xmlNewText:
563 * @content: the text content
564 * @len: the text len.
565 *
566 * Creation of a new text node with an extra parameter for the content's lenght
567 * return values: a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000568 */
569xmlNodePtr xmlNewTextLen(const CHAR *content, int len) {
570 xmlNodePtr cur;
571
572 /*
573 * Allocate a new node and fill the fields.
574 */
575 cur = (xmlNodePtr) malloc(sizeof(xmlNode));
576 if (cur == NULL) {
577 fprintf(stderr, "xmlNewText : malloc failed\n");
578 return(NULL);
579 }
580
Daniel Veillard33942841998-10-18 19:12:41 +0000581 cur->type = XML_TEXT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000582 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000583 cur->parent = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000584 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000585 cur->next = NULL;
586 cur->childs = NULL;
587 cur->properties = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000588 cur->type = XML_TEXT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000589 cur->name = xmlStrdup(xmlStringText);
590 cur->ns = NULL;
591 cur->nsDef = NULL;
592 if (content != NULL)
593 cur->content = xmlStrndup(content, len);
594 else
595 cur->content = NULL;
596 return(cur);
597}
598
Daniel Veillard97b58771998-10-20 06:14:16 +0000599/**
600 * xmlNewDocTextLen:
601 * @doc: the document
602 * @content: the text content
603 * @len: the text len.
604 *
605 * Creation of a new text node with an extra content lenght parameter. The
606 * text node pertain to a given document.
607 * return values: a pointer to the new node object.
608 */
Daniel Veillard0bef1311998-10-14 02:36:47 +0000609xmlNodePtr xmlNewDocTextLen(xmlDocPtr doc, const CHAR *content, int len) {
610 xmlNodePtr cur;
611
612 cur = xmlNewTextLen(content, len);
613 if (cur != NULL) cur->doc = doc;
614 return(cur);
615}
616
Daniel Veillard97b58771998-10-20 06:14:16 +0000617/**
618 * xmlNewComment:
619 * @content: the comment content
620 *
621 * Creation of a new node containing a comment.
622 * return values: a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000623 */
624xmlNodePtr xmlNewComment(CHAR *content) {
625 xmlNodePtr cur;
626
627 /*
628 * Allocate a new node and fill the fields.
629 */
630 cur = (xmlNodePtr) malloc(sizeof(xmlNode));
631 if (cur == NULL) {
632 fprintf(stderr, "xmlNewComment : malloc failed\n");
633 return(NULL);
634 }
635
Daniel Veillard33942841998-10-18 19:12:41 +0000636 cur->type = XML_COMMENT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000637 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000638 cur->parent = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000639 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000640 cur->next = NULL;
641 cur->childs = NULL;
642 cur->properties = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000643 cur->type = XML_COMMENT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000644 cur->name = xmlStrdup(xmlStringText);
645 cur->ns = NULL;
646 cur->nsDef = NULL;
647 if (content != NULL)
648 cur->content = xmlStrdup(content);
649 else
650 cur->content = NULL;
651 return(cur);
652}
653
Daniel Veillard97b58771998-10-20 06:14:16 +0000654/**
655 * xmlNewComment:
656 * @doc: the document
657 * @content: the comment content
658 *
659 * Creation of a new node containing a commentwithin a document.
660 * return values: a pointer to the new node object.
661 */
Daniel Veillard0bef1311998-10-14 02:36:47 +0000662xmlNodePtr xmlNewDocComment(xmlDocPtr doc, CHAR *content) {
663 xmlNodePtr cur;
664
665 cur = xmlNewComment(content);
666 if (cur != NULL) cur->doc = doc;
667 return(cur);
668}
669
Daniel Veillard97b58771998-10-20 06:14:16 +0000670/**
671 * xmlNewChild:
672 * @parent: the parent node
673 * @ns: a namespace if any
674 * @name: the name of the child
675 * @content: the content of the child if any.
676 *
677 *
678 * Creation of a new child element, added at the end of @parent childs list.
679 * @ns and @content parameters are optionnal (NULL).
680 * return values: a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000681 */
682xmlNodePtr xmlNewChild(xmlNodePtr parent, xmlNsPtr ns,
683 const CHAR *name, CHAR *content) {
684 xmlNodePtr cur, prev;
685
686 if (parent == NULL) {
687 fprintf(stderr, "xmlNewChild : parent == NULL\n");
688 return(NULL);
689 }
690
691 if (name == NULL) {
692 fprintf(stderr, "xmlNewChild : name == NULL\n");
693 return(NULL);
694 }
695
696 /*
697 * Allocate a new node
698 */
699 if (ns == NULL)
700 cur = xmlNewNode(parent->ns, name, content);
701 else
702 cur = xmlNewNode(ns, name, content);
703 if (cur == NULL) return(NULL);
704
705 /*
706 * add the new element at the end of the childs list.
707 */
Daniel Veillard33942841998-10-18 19:12:41 +0000708 if (content == NULL)
709 cur->type = XML_ELEMENT_NODE;
710 else
711 cur->type = XML_TEXT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000712 cur->parent = parent;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000713 cur->doc = parent->doc;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000714 if (parent->childs == NULL) {
715 parent->childs = cur;
716 } else {
717 prev = parent->childs;
718 while (prev->next != NULL) prev = prev->next;
719 prev->next = cur;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000720 cur->prev = prev;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000721 }
722
723 return(cur);
724}
725
Daniel Veillard97b58771998-10-20 06:14:16 +0000726/**
727 * xmlAddChild:
728 * @parent: the parent node
729 * @cur: the child node
730 *
731 * Add a new child element, to @parent, at the end of the child list.
732 * return values: the child or NULL in case of error.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000733 */
734xmlNodePtr xmlAddChild(xmlNodePtr parent, xmlNodePtr cur) {
735 xmlNodePtr prev;
736
737 if (parent == NULL) {
738 fprintf(stderr, "xmladdChild : parent == NULL\n");
739 return(NULL);
740 }
741
742 if (cur == NULL) {
743 fprintf(stderr, "xmladdChild : child == NULL\n");
744 return(NULL);
745 }
746
Daniel Veillard0bef1311998-10-14 02:36:47 +0000747 if ((cur->doc != NULL) && (parent->doc != NULL) &&
748 (cur->doc != parent->doc)) {
749 fprintf(stderr, "Elements moved to a different document\n");
750 }
751
Daniel Veillard260a68f1998-08-13 03:39:55 +0000752 /*
753 * add the new element at the end of the childs list.
754 */
755 cur->parent = parent;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000756 cur->doc = parent->doc; /* the parent may not be linked to a doc ! */
Daniel Veillard260a68f1998-08-13 03:39:55 +0000757 if (parent->childs == NULL) {
758 parent->childs = cur;
759 } else {
760 prev = parent->childs;
761 while (prev->next != NULL) prev = prev->next;
762 prev->next = cur;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000763 cur->prev = prev;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000764 }
765
766 return(cur);
767}
768
Daniel Veillard97b58771998-10-20 06:14:16 +0000769/**
770 * xmlGetLastChild:
771 * @parent: the parent node
772 *
773 * Search the last child of a node.
774 * return values: the last child or NULL if none.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000775 */
776xmlNodePtr xmlGetLastChild(xmlNodePtr parent) {
777 xmlNodePtr last;
778
779 if (parent == NULL) {
780 fprintf(stderr, "xmlGetLastChild : parent == NULL\n");
781 return(NULL);
782 }
783
784 /*
785 * add the new element at the end of the childs list.
786 */
787 if (parent->childs == NULL) {
788 return(NULL);
789 } else {
790 last = parent->childs;
791 while (last->next != NULL) last = last->next;
792 }
793 return(last);
794}
795
Daniel Veillard97b58771998-10-20 06:14:16 +0000796/**
797 * xmlFreeNodeList:
798 * @cur: the first node in the list
799 *
800 * Free a node and all its siblings, this is a recursive behaviour, all
801 * the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000802 */
803void xmlFreeNodeList(xmlNodePtr cur) {
804 xmlNodePtr next;
805 if (cur == NULL) {
806 fprintf(stderr, "xmlFreeNodeList : node == NULL\n");
807 return;
808 }
809 while (cur != NULL) {
810 next = cur->next;
811 xmlFreeNode(cur);
812 cur = next;
813 }
814}
815
Daniel Veillard97b58771998-10-20 06:14:16 +0000816/**
817 * xmlFreeNode:
818 * @cur: the node
819 *
820 * Free a node, this is a recursive behaviour, all the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000821 */
822void xmlFreeNode(xmlNodePtr cur) {
823 if (cur == NULL) {
824 fprintf(stderr, "xmlFreeNode : node == NULL\n");
825 return;
826 }
827 if (cur->properties != NULL) xmlFreePropList(cur->properties);
828 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
829 if (cur->content != NULL) free(cur->content);
830 if (cur->name != NULL) free((char *) cur->name);
831 if (cur->nsDef != NULL) xmlFreeNsList(cur->nsDef);
832 memset(cur, -1, sizeof(xmlNode));
833 free(cur);
834}
835
836/************************************************************************
837 * *
838 * Content access functions *
839 * *
840 ************************************************************************/
841
Daniel Veillard97b58771998-10-20 06:14:16 +0000842/**
843 * xmlNodeSetContent:
844 * @cur: the node being modified
845 * @content: the new value of the content
846 *
847 * Replace the content of a node.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000848 */
849void xmlNodeSetContent(xmlNodePtr cur, const CHAR *content) {
850 if (cur == NULL) {
851 fprintf(stderr, "xmlNodeSetContent : node == NULL\n");
852 return;
853 }
854 if (cur->content != NULL) free(cur->content);
855 if (content != NULL)
856 cur->content = xmlStrdup(content);
857 else
858 cur->content = NULL;
859}
860
Daniel Veillard97b58771998-10-20 06:14:16 +0000861/**
862 * xmlNodeSetContentLen:
863 * @cur: the node being modified
864 * @content: the new value of the content
865 * @len: the size of @content
866 *
867 * Replace the content of a node.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000868 */
869void xmlNodeSetContentLen(xmlNodePtr cur, const CHAR *content, int len) {
870 if (cur == NULL) {
871 fprintf(stderr, "xmlNodeSetContent : node == NULL\n");
872 return;
873 }
874 if (cur->content != NULL) free(cur->content);
875 if (content != NULL)
876 cur->content = xmlStrndup(content, len);
877 else
878 cur->content = NULL;
879}
880
Daniel Veillard97b58771998-10-20 06:14:16 +0000881/**
882 * xmlNodeAddContent:
883 * @cur: the node being modified
884 * @content: extra content
885 *
886 * Append the extra substring to the node content.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000887 */
888void xmlNodeAddContent(xmlNodePtr cur, const CHAR *content) {
889 if (cur == NULL) {
890 fprintf(stderr, "xmlNodeAddContent : node == NULL\n");
891 return;
892 }
893 cur->content = xmlStrcat(cur->content, content);
894}
895
Daniel Veillard97b58771998-10-20 06:14:16 +0000896/**
897 * xmlNodeAddContentLen:
898 * @cur: the node being modified
899 * @content: extra content
900 * @len: the size of @content
901 *
902 * Append the extra substring to the node content.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000903 */
904void xmlNodeAddContentLen(xmlNodePtr cur, const CHAR *content, int len) {
905 if (cur == NULL) {
906 fprintf(stderr, "xmlNodeAddContent : node == NULL\n");
907 return;
908 }
909 cur->content = xmlStrncat(cur->content, content, len);
910}
911
Daniel Veillard97b58771998-10-20 06:14:16 +0000912/**
913 * xmlSearchNs:
914 * @doc: the document
915 * @node: the current node
916 * @nameSpace: the namespace string
Daniel Veillard260a68f1998-08-13 03:39:55 +0000917 *
Daniel Veillard97b58771998-10-20 06:14:16 +0000918 * Search a Ns registered under a given name space for a document.
919 * recurse on the parents until it finds the defined namespace
920 * or return NULL otherwise.
921 * @nameSpace can be NULL, this is a search for the default namespace.
922 * return values: the namespace pointer or NULL.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000923 */
924xmlNsPtr xmlSearchNs(xmlDocPtr doc, xmlNodePtr node, const CHAR *nameSpace) {
925 xmlNsPtr cur;
926
927 while (node != NULL) {
928 cur = node->nsDef;
929 while (cur != NULL) {
930 if ((cur->prefix == NULL) && (nameSpace == NULL))
931 return(cur);
932 if ((cur->prefix != NULL) && (nameSpace != NULL) &&
933 (!xmlStrcmp(cur->prefix, nameSpace)))
934 return(cur);
935 cur = cur->next;
936 }
937 node = node->parent;
938 }
939 if (doc != NULL) {
940 cur = doc->oldNs;
941 while (cur != NULL) {
942 if ((cur->prefix != NULL) && (nameSpace != NULL) &&
943 (!xmlStrcmp(cur->prefix, nameSpace)))
944 return(cur);
945 cur = cur->next;
946 }
947 }
948 return(NULL);
949}
950
Daniel Veillard97b58771998-10-20 06:14:16 +0000951/**
952 * xmlSearchNsByHref:
953 * @doc: the document
954 * @node: the current node
955 * @href: the namespace value
956 *
957 * Search a Ns aliasing a given URI. Recurse on the parents until it finds
958 * the defined namespace or return NULL otherwise.
959 * return values: the namespace pointer or NULL.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000960 */
961xmlNsPtr xmlSearchNsByHref(xmlDocPtr doc, xmlNodePtr node, const CHAR *href) {
962 xmlNsPtr cur;
963
964 while (node != NULL) {
965 cur = node->nsDef;
966 while (cur != NULL) {
967 if ((cur->href != NULL) && (href != NULL) &&
968 (!xmlStrcmp(cur->href, href)))
969 return(cur);
970 cur = cur->next;
971 }
972 node = node->parent;
973 }
974 if (doc != NULL) {
975 cur = doc->oldNs;
976 while (cur != NULL) {
977 if ((cur->href != NULL) && (href != NULL) &&
978 (!xmlStrcmp(cur->href, href)))
979 return(cur);
980 cur = cur->next;
981 }
982 }
983 return(NULL);
984}
985
Daniel Veillard97b58771998-10-20 06:14:16 +0000986/**
987 * xmlGetProp:
988 * @node: the node
989 * @name: the attribute name
990 *
991 * Search and get the value of an attribute associated to a node
992 * return values: the attribute value or NULL if not found.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000993 */
994const CHAR *xmlGetProp(xmlNodePtr node, const CHAR *name) {
995 xmlAttrPtr prop = node->properties;
996
997 while (prop != NULL) {
998 if (!xmlStrcmp(prop->name, name)) return(prop->value);
999 prop = prop->next;
1000 }
1001 return(NULL);
1002}
1003
Daniel Veillard97b58771998-10-20 06:14:16 +00001004/**
1005 * xmlGetProp:
1006 * @node: the node
1007 * @name: the attribute name
1008 * @value: the attribute value
1009 *
1010 * Set (or reset) an attribute carried by a node.
1011 * return values: the attribute pointer.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001012 */
1013xmlAttrPtr xmlSetProp(xmlNodePtr node, const CHAR *name, const CHAR *value) {
1014 xmlAttrPtr prop = node->properties;
1015
1016 while (prop != NULL) {
1017 if (!xmlStrcmp(prop->name, name)) {
1018 if (prop->value != NULL)
1019 free((char *) prop->value);
1020 prop->value = NULL;
1021 if (value != NULL)
1022 prop->value = xmlStrdup(value);
1023 return(prop);
1024 }
1025 prop = prop->next;
1026 }
1027 prop = xmlNewProp(node, name, value);
1028 return(prop);
1029}
1030
Daniel Veillard97b58771998-10-20 06:14:16 +00001031/**
1032 * xmlNodeIsText:
1033 * @node: the node
1034 *
1035 * Is this node a Text node ?
1036 * return values: 1 yes, 0 no
Daniel Veillard260a68f1998-08-13 03:39:55 +00001037 */
1038int xmlNodeIsText(xmlNodePtr node) {
1039 if (node == NULL) return(0);
1040
Daniel Veillard0bef1311998-10-14 02:36:47 +00001041 if (node->type == XML_TEXT_NODE) return(1);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001042 return(0);
1043}
1044
Daniel Veillard97b58771998-10-20 06:14:16 +00001045/**
1046 * xmlNodeIsText:
1047 * @node: the node
1048 * @content: the content
1049 * @len: @content lenght
1050 *
1051 * Concat the given string at the end of the existing node content
Daniel Veillard260a68f1998-08-13 03:39:55 +00001052 */
Daniel Veillard97b58771998-10-20 06:14:16 +00001053
Daniel Veillard260a68f1998-08-13 03:39:55 +00001054void xmlTextConcat(xmlNodePtr node, const CHAR *content, int len) {
1055 if (node == NULL) return;
1056
Daniel Veillard0bef1311998-10-14 02:36:47 +00001057 if (node->type != XML_TEXT_NODE) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001058 fprintf(stderr, "xmlTextConcat: node is not text\n");
1059 return;
1060 }
1061 node->content = xmlStrncat(node->content, content, len);
1062}
1063
1064/************************************************************************
1065 * *
1066 * Output : to a FILE or in memory *
1067 * *
1068 ************************************************************************/
1069
Daniel Veillard260a68f1998-08-13 03:39:55 +00001070static CHAR *buffer = NULL;
1071static int buffer_index = 0;
1072static int buffer_size = 0;
1073
Daniel Veillard97b58771998-10-20 06:14:16 +00001074/**
1075 * xmlBufferWriteCHAR:
1076 * @string: the string to add
1077 *
1078 * routine which manage and grows an output buffer. This one add
1079 * CHARs at the end of the array.
1080 */
Daniel Veillard260a68f1998-08-13 03:39:55 +00001081void xmlBufferWriteCHAR(const CHAR *string) {
1082 const CHAR *cur;
1083
1084 if (buffer == NULL) {
1085 buffer_size = 50000;
1086 buffer = (CHAR *) malloc(buffer_size * sizeof(CHAR));
1087 if (buffer == NULL) {
1088 fprintf(stderr, "xmlBufferWrite : out of memory!\n");
1089 exit(1);
1090 }
1091 }
1092
1093 if (string == NULL) return;
1094 for (cur = string;*cur != 0;cur++) {
1095 if (buffer_index + 10 >= buffer_size) {
1096 buffer_size *= 2;
1097 buffer = (CHAR *) realloc(buffer, buffer_size * sizeof(CHAR));
1098 if (buffer == NULL) {
1099 fprintf(stderr, "xmlBufferWrite : out of memory!\n");
1100 exit(1);
1101 }
1102 }
1103 buffer[buffer_index++] = *cur;
1104 }
1105 buffer[buffer_index] = 0;
1106}
1107
Daniel Veillard97b58771998-10-20 06:14:16 +00001108/**
1109 * xmlBufferWriteChar:
1110 * @string: the string to add
1111 *
1112 * routine which manage and grows an output buffer. This one add
1113 * C chars at the end of the array.
1114 */
Daniel Veillard260a68f1998-08-13 03:39:55 +00001115void xmlBufferWriteChar(const char *string) {
1116 const char *cur;
1117
1118 if (buffer == NULL) {
1119 buffer_size = 50000;
1120 buffer = (CHAR *) malloc(buffer_size * sizeof(CHAR));
1121 if (buffer == NULL) {
1122 fprintf(stderr, "xmlBufferWrite : out of memory!\n");
1123 exit(1);
1124 }
1125 }
1126
1127 if (string == NULL) return;
1128 for (cur = string;*cur != 0;cur++) {
1129 if (buffer_index + 10 >= buffer_size) {
1130 buffer_size *= 2;
1131 buffer = (CHAR *) realloc(buffer, buffer_size * sizeof(CHAR));
1132 if (buffer == NULL) {
1133 fprintf(stderr, "xmlBufferWrite : out of memory!\n");
1134 exit(1);
1135 }
1136 }
1137 buffer[buffer_index++] = *cur;
1138 }
1139 buffer[buffer_index] = 0;
1140}
1141
Daniel Veillard97b58771998-10-20 06:14:16 +00001142/**
1143 * xmlGlobalNsDump:
1144 * @cur: a namespace
1145 *
1146 * Dump a global Namespace, this is the old version based on PIs.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001147 */
1148static void xmlGlobalNsDump(xmlNsPtr cur) {
1149 if (cur == NULL) {
1150 fprintf(stderr, "xmlGlobalNsDump : Ns == NULL\n");
1151 return;
1152 }
1153 if (cur->type == XML_GLOBAL_NAMESPACE) {
1154 xmlBufferWriteChar("<?namespace");
1155 if (cur->href != NULL) {
1156 xmlBufferWriteChar(" href=\"");
1157 xmlBufferWriteCHAR(cur->href);
1158 xmlBufferWriteChar("\"");
1159 }
1160 if (cur->prefix != NULL) {
1161 xmlBufferWriteChar(" AS=\"");
1162 xmlBufferWriteCHAR(cur->prefix);
1163 xmlBufferWriteChar("\"");
1164 }
1165 xmlBufferWriteChar("?>\n");
1166 }
1167}
1168
Daniel Veillard97b58771998-10-20 06:14:16 +00001169/**
1170 * xmlGlobalNsListDump:
1171 * @cur: the first namespace
1172 *
1173 * Dump a list of global Namespace, this is the old version based on PIs.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001174 */
Daniel Veillard260a68f1998-08-13 03:39:55 +00001175static void xmlGlobalNsListDump(xmlNsPtr cur) {
1176 while (cur != NULL) {
1177 xmlGlobalNsDump(cur);
1178 cur = cur->next;
1179 }
1180}
1181
Daniel Veillard97b58771998-10-20 06:14:16 +00001182/**
1183 * xmlNsDump:
1184 * @cur: a namespace
1185 *
Daniel Veillard260a68f1998-08-13 03:39:55 +00001186 * Dump a local Namespace definition.
Daniel Veillard97b58771998-10-20 06:14:16 +00001187 * Should be called in the context of attributes dumps.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001188 */
1189static void xmlNsDump(xmlNsPtr cur) {
1190 if (cur == NULL) {
1191 fprintf(stderr, "xmlNsDump : Ns == NULL\n");
1192 return;
1193 }
1194 if (cur->type == XML_LOCAL_NAMESPACE) {
1195 /* Within the context of an element attributes */
1196 if (cur->prefix != NULL) {
1197 xmlBufferWriteChar(" xmlns:");
1198 xmlBufferWriteCHAR(cur->prefix);
1199 } else
1200 xmlBufferWriteChar(" xmlns");
1201 xmlBufferWriteChar("=\"");
1202 xmlBufferWriteCHAR(cur->href);
1203 xmlBufferWriteChar("\"");
1204 }
1205}
1206
Daniel Veillard97b58771998-10-20 06:14:16 +00001207/**
1208 * xmlNsListDump:
1209 * @cur: the first namespace
1210 *
1211 * Dump a list of local Namespace definitions.
1212 * Should be called in the context of attributes dumps.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001213 */
Daniel Veillard260a68f1998-08-13 03:39:55 +00001214static void xmlNsListDump(xmlNsPtr cur) {
1215 while (cur != NULL) {
1216 xmlNsDump(cur);
1217 cur = cur->next;
1218 }
1219}
1220
Daniel Veillard97b58771998-10-20 06:14:16 +00001221/**
1222 * xmlDtdDump:
1223 * @doc: the document
1224 *
1225 * Dump the XML document DTD, if any.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001226 */
Daniel Veillard260a68f1998-08-13 03:39:55 +00001227static void xmlDtdDump(xmlDocPtr doc) {
1228 xmlDtdPtr cur = doc->dtd;
1229
1230 if (cur == NULL) {
1231 fprintf(stderr, "xmlDtdDump : DTD == NULL\n");
1232 return;
1233 }
1234 xmlBufferWriteChar("<!DOCTYPE ");
1235 xmlBufferWriteCHAR(cur->name);
1236 if (cur->ExternalID != NULL) {
1237 xmlBufferWriteChar(" PUBLIC \"");
1238 xmlBufferWriteCHAR(cur->ExternalID);
1239 xmlBufferWriteChar("\" \"");
1240 xmlBufferWriteCHAR(cur->SystemID);
1241 xmlBufferWriteChar("\"");
1242 } else if (cur->SystemID != NULL) {
1243 xmlBufferWriteChar(" SYSTEM \"");
1244 xmlBufferWriteCHAR(cur->SystemID);
1245 xmlBufferWriteChar("\"");
1246 }
1247 if ((cur->entities == NULL) && (doc->entities == NULL)) {
1248 xmlBufferWriteChar(">\n");
1249 return;
1250 }
1251 xmlBufferWriteChar(" [\n");
1252 if (cur->entities != NULL)
1253 xmlDumpEntitiesTable((xmlEntitiesTablePtr) cur->entities);
1254 if (doc->entities != NULL)
1255 xmlDumpEntitiesTable((xmlEntitiesTablePtr) doc->entities);
1256 xmlBufferWriteChar("]");
1257
1258 /* TODO !!! a lot more things to dump ... */
1259 xmlBufferWriteChar(">\n");
1260}
1261
Daniel Veillard97b58771998-10-20 06:14:16 +00001262/**
1263 * xmlAttrDump:
1264 * @doc: the document
1265 * @cur: the attribute pointer
1266 *
1267 * Dump an XML attribute
Daniel Veillard260a68f1998-08-13 03:39:55 +00001268 */
Daniel Veillard260a68f1998-08-13 03:39:55 +00001269static void xmlAttrDump(xmlDocPtr doc, xmlAttrPtr cur) {
1270 if (cur == NULL) {
1271 fprintf(stderr, "xmlAttrDump : property == NULL\n");
1272 return;
1273 }
1274 xmlBufferWriteChar(" ");
1275 xmlBufferWriteCHAR(cur->name);
1276 if (cur->value) {
1277 xmlBufferWriteChar("=\"");
1278 xmlBufferWriteCHAR(xmlEncodeEntities(doc, cur->value));
1279 xmlBufferWriteChar("\"");
1280 }
1281}
1282
Daniel Veillard97b58771998-10-20 06:14:16 +00001283/**
1284 * xmlAttrListDump:
1285 * @doc: the document
1286 * @cur: the first attribute pointer
1287 *
1288 * Dump a list of XML attributes
Daniel Veillard260a68f1998-08-13 03:39:55 +00001289 */
Daniel Veillard260a68f1998-08-13 03:39:55 +00001290static void xmlAttrListDump(xmlDocPtr doc, xmlAttrPtr cur) {
1291 if (cur == NULL) {
1292 fprintf(stderr, "xmlAttrListDump : property == NULL\n");
1293 return;
1294 }
1295 while (cur != NULL) {
1296 xmlAttrDump(doc, cur);
1297 cur = cur->next;
1298 }
1299}
1300
Daniel Veillard260a68f1998-08-13 03:39:55 +00001301
1302static void xmlNodeDump(xmlDocPtr doc, xmlNodePtr cur, int level);
Daniel Veillard97b58771998-10-20 06:14:16 +00001303/**
1304 * xmlNodeListDump:
1305 * @doc: the document
1306 * @cur: the first node
1307 * @level: the imbrication level for indenting
1308 *
1309 * Dump an XML node list, recursive behaviour,children are printed too.
1310 */
Daniel Veillard260a68f1998-08-13 03:39:55 +00001311static void xmlNodeListDump(xmlDocPtr doc, xmlNodePtr cur, int level) {
1312 if (cur == NULL) {
1313 fprintf(stderr, "xmlNodeListDump : node == NULL\n");
1314 return;
1315 }
1316 while (cur != NULL) {
1317 xmlNodeDump(doc, cur, level);
1318 cur = cur->next;
1319 }
1320}
1321
Daniel Veillard97b58771998-10-20 06:14:16 +00001322/**
1323 * xmlNodeListDump:
1324 * @doc: the document
1325 * @cur: the current node
1326 * @level: the imbrication level for indenting
1327 *
1328 * Dump an XML node, recursive behaviour,children are printed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001329 */
Daniel Veillard260a68f1998-08-13 03:39:55 +00001330static void xmlNodeDump(xmlDocPtr doc, xmlNodePtr cur, int level) {
1331 int i;
1332
1333 if (cur == NULL) {
1334 fprintf(stderr, "xmlNodeDump : node == NULL\n");
1335 return;
1336 }
Daniel Veillard0bef1311998-10-14 02:36:47 +00001337 if (cur->type == XML_TEXT_NODE) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001338 if (cur->content != NULL)
1339 xmlBufferWriteCHAR(xmlEncodeEntities(doc, cur->content));
1340 return;
1341 }
Daniel Veillard0bef1311998-10-14 02:36:47 +00001342 if (cur->type == XML_COMMENT_NODE) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001343 if (cur->content != NULL) {
1344 xmlBufferWriteChar("<!--");
1345 xmlBufferWriteCHAR(cur->content);
1346 xmlBufferWriteChar("-->");
1347 }
1348 return;
1349 }
1350 if (xmlIndentTreeOutput)
1351 for (i = 0;i < level;i++)
1352 xmlBufferWriteChar(" ");
1353
1354 xmlBufferWriteChar("<");
1355 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
1356 xmlBufferWriteCHAR(cur->ns->prefix);
1357 xmlBufferWriteChar(":");
1358 }
1359
1360 xmlBufferWriteCHAR(cur->name);
1361 if (cur->nsDef)
1362 xmlNsListDump(cur->nsDef);
1363 if (cur->properties != NULL)
1364 xmlAttrListDump(doc, cur->properties);
1365
1366 if ((cur->content == NULL) && (cur->childs == NULL)) {
1367 xmlBufferWriteChar("/>\n");
1368 return;
1369 }
1370 xmlBufferWriteChar(">");
1371 if (cur->content != NULL)
1372 xmlBufferWriteCHAR(xmlEncodeEntities(doc, cur->content));
1373 if (cur->childs != NULL) {
1374 xmlBufferWriteChar("\n");
1375 xmlNodeListDump(doc, cur->childs, level + 1);
1376 if (xmlIndentTreeOutput)
1377 for (i = 0;i < level;i++)
1378 xmlBufferWriteChar(" ");
1379 }
1380 xmlBufferWriteChar("</");
1381 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
1382 xmlBufferWriteCHAR(cur->ns->prefix);
1383 xmlBufferWriteChar(":");
1384 }
1385
1386 xmlBufferWriteCHAR(cur->name);
1387 xmlBufferWriteChar(">\n");
1388}
1389
Daniel Veillard97b58771998-10-20 06:14:16 +00001390/**
1391 * xmlDocContentDump:
1392 * @cur: the document
1393 *
1394 * Dump an XML document.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001395 */
1396static void xmlDocContentDump(xmlDocPtr cur) {
1397 if (oldXMLWDcompatibility)
1398 xmlBufferWriteChar("<?XML version=\"");
1399 else
1400 xmlBufferWriteChar("<?xml version=\"");
1401 xmlBufferWriteCHAR(cur->version);
1402 xmlBufferWriteChar("\"");
1403 if (cur->encoding != NULL) {
1404 xmlBufferWriteChar(" encoding=\"");
1405 xmlBufferWriteCHAR(cur->encoding);
1406 xmlBufferWriteChar("\"");
1407 }
1408 switch (cur->standalone) {
1409 case 0:
1410 xmlBufferWriteChar(" standalone=\"no\"");
1411 break;
1412 case 1:
1413 xmlBufferWriteChar(" standalone=\"yes\"");
1414 break;
1415 }
1416 xmlBufferWriteChar("?>\n");
1417 if ((cur->dtd != NULL) || (cur->entities != NULL))
1418 xmlDtdDump(cur);
1419 if (cur->root != NULL) {
1420 /* global namespace definitions, the old way */
1421 if (oldXMLWDcompatibility)
1422 xmlGlobalNsListDump(cur->oldNs);
1423 else
1424 xmlUpgradeOldNs(cur);
1425 xmlNodeDump(cur, cur->root, 0);
1426 }
1427}
1428
Daniel Veillard97b58771998-10-20 06:14:16 +00001429/**
1430 * xmlDocDumpMemory:
1431 * @cur: the document
1432 * @mem: OUT: the memory pointer
1433 * @size: OUT: the memory lenght
1434 *
1435 * Dump an XML document in memory and return the CHAR * and it's size.
1436 * It's up to the caller to free the memory.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001437 */
Daniel Veillard260a68f1998-08-13 03:39:55 +00001438void xmlDocDumpMemory(xmlDocPtr cur, CHAR**mem, int *size) {
1439 if (cur == NULL) {
1440 fprintf(stderr, "xmlDocDump : document == NULL\n");
1441 *mem = NULL;
1442 *size = 0;
1443 return;
1444 }
1445 buffer_index = 0;
1446 xmlDocContentDump(cur);
1447
1448 *mem = buffer;
1449 *size = buffer_index;
1450}
1451
Daniel Veillard97b58771998-10-20 06:14:16 +00001452/**
1453 * xmlGetDocCompressMode:
1454 * @doc: the document
1455 *
1456 * get the compression ratio for a document, ZLIB based
1457 * return values: 0 (uncompressed) to 9 (max compression)
Daniel Veillard151b1b01998-09-23 00:49:46 +00001458 */
Daniel Veillard15a8df41998-09-24 19:15:06 +00001459int xmlGetDocCompressMode (xmlDocPtr doc) {
1460 if (doc == NULL) return(-1);
1461 return(doc->compression);
1462}
1463
Daniel Veillard97b58771998-10-20 06:14:16 +00001464/**
1465 * xmlSetDocCompressMode:
1466 * @doc: the document
1467 * @mode: the compression ratio
1468 *
1469 * set the compression ratio for a document, ZLIB based
1470 * Correct values: 0 (uncompressed) to 9 (max compression)
1471 */
Daniel Veillard15a8df41998-09-24 19:15:06 +00001472void xmlSetDocCompressMode (xmlDocPtr doc, int mode) {
1473 if (doc == NULL) return;
1474 if (mode < 0) doc->compression = 0;
1475 else if (mode > 9) doc->compression = 9;
1476 else doc->compression = mode;
1477}
1478
Daniel Veillard97b58771998-10-20 06:14:16 +00001479/**
1480 * xmlGetCompressMode:
1481 *
1482 * get the default compression mode used, ZLIB based.
1483 * return values: 0 (uncompressed) to 9 (max compression)
Daniel Veillard15a8df41998-09-24 19:15:06 +00001484 */
Daniel Veillard151b1b01998-09-23 00:49:46 +00001485int xmlGetCompressMode(void) {
1486 return(xmlCompressMode);
1487}
Daniel Veillard97b58771998-10-20 06:14:16 +00001488
1489/**
1490 * xmlSetCompressMode:
1491 * @mode: the compression ratio
1492 *
1493 * set the default compression mode used, ZLIB based
1494 * Correct values: 0 (uncompressed) to 9 (max compression)
1495 */
Daniel Veillard151b1b01998-09-23 00:49:46 +00001496void xmlSetCompressMode(int mode) {
1497 if (mode < 0) xmlCompressMode = 0;
Daniel Veillard15a8df41998-09-24 19:15:06 +00001498 else if (mode > 9) xmlCompressMode = 9;
Daniel Veillard151b1b01998-09-23 00:49:46 +00001499 else xmlCompressMode = mode;
1500}
1501
Daniel Veillard97b58771998-10-20 06:14:16 +00001502/**
1503 * xmlDocDump:
1504 * @f: the FILE*
1505 * @cur: the document
1506 *
1507 * Dump an XML document to an open FILE.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001508 */
Daniel Veillard260a68f1998-08-13 03:39:55 +00001509void xmlDocDump(FILE *f, xmlDocPtr cur) {
1510 if (cur == NULL) {
1511 fprintf(stderr, "xmlDocDump : document == NULL\n");
1512 return;
1513 }
1514 buffer_index = 0;
1515 xmlDocContentDump(cur);
1516
1517 fwrite(buffer, sizeof(CHAR), buffer_index, f);
1518}
1519
Daniel Veillard97b58771998-10-20 06:14:16 +00001520/**
1521 * xmlSaveFile:
1522 * @filename: the filename
1523 * @cur: the document
1524 *
1525 * Dump an XML document to a file. Will use compression if
1526 * compiled in and enabled.
1527 * returns: the number of file written or -1 in case of failure.
Daniel Veillard151b1b01998-09-23 00:49:46 +00001528 */
Daniel Veillard151b1b01998-09-23 00:49:46 +00001529int xmlSaveFile(const char *filename, xmlDocPtr cur) {
1530#ifdef HAVE_ZLIB_H
1531 gzFile zoutput = NULL;
1532 char mode[15];
1533#endif
1534 FILE *output;
1535 int ret;
1536
1537#ifdef HAVE_ZLIB_H
Daniel Veillarddc3dd9d1998-09-24 19:25:54 +00001538 if ((cur->compression > 0) && (cur->compression <= 9)) {
1539 sprintf(mode, "w%d", cur->compression);
Daniel Veillard151b1b01998-09-23 00:49:46 +00001540 zoutput = gzopen(filename, mode);
1541 }
1542 if (zoutput == NULL) {
1543#endif
1544 output = fopen(filename, "w");
1545 if (output == NULL) return(-1);
1546#ifdef HAVE_ZLIB_H
1547 }
1548#endif
1549
1550 /*
1551 * save the content to a temp buffer.
1552 */
1553 buffer_index = 0;
1554 xmlDocContentDump(cur);
1555
1556#ifdef HAVE_ZLIB_H
1557 if (zoutput != NULL) {
1558 ret = gzwrite(zoutput, buffer, sizeof(CHAR) * buffer_index);
1559 gzclose(zoutput);
1560 return(ret);
1561 }
1562#endif
1563 ret = fwrite(buffer, sizeof(CHAR), buffer_index, output);
1564 fclose(output);
1565 return(ret * sizeof(CHAR));
1566}
1567
Daniel Veillard260a68f1998-08-13 03:39:55 +00001568/************************************************************************
1569 * *
1570 * Debug *
1571 * *
1572 ************************************************************************/
1573
1574#ifdef STANDALONE
1575int main(void) {
1576 xmlDocPtr doc;
1577 xmlNodePtr tree, subtree;
1578 xmlNsPtr ns1;
1579 xmlNsPtr ns2;
1580
1581 /*
1582 * build a fake XML document
1583 */
1584 doc = xmlNewDoc("1.0");
1585 ns1 = xmlNewNs(doc, "http://www.ietf.org/standards/dav/", "D");
1586 ns2 = xmlNewNs(doc, "http://www.w3.com/standards/z39.50/", "Z");
1587 doc->root = xmlNewNode(ns1, "multistatus", NULL);
1588 tree = xmlNewChild(doc->root, NULL, "response", NULL);
1589 subtree = xmlNewChild(tree, NULL, "prop", NULL);
1590 xmlNewChild(subtree, ns2, "Authors", NULL);
1591 subtree = xmlNewChild(tree, NULL, "status", "HTTP/1.1 420 Method Failure");
1592 tree = xmlNewChild(doc->root, NULL, "response", NULL);
1593 subtree = xmlNewChild(tree, NULL, "prop", NULL);
1594 xmlNewChild(subtree, ns2, "Copyright-Owner", NULL);
1595 subtree = xmlNewChild(tree, NULL, "status", "HTTP/1.1 409 Conflict");
1596 tree = xmlNewChild(doc->root, NULL, "responsedescription",
1597 "Copyright Owner can not be deleted or altered");
1598
1599 /*
1600 * print it.
1601 */
1602 xmlDocDump(stdout, doc);
1603
1604 /*
1605 * free it.
1606 */
1607 xmlFreeDoc(doc);
1608 return(0);
1609}
1610#endif