blob: 202f0b83f2f12843de9142c056451d581f0b9f86 [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/**
Daniel Veillardccb09631998-10-27 06:21:04 +0000349 * xmlStringGetNodeList:
350 * @doc: the document
351 * @value: the value of the attribute
352 *
353 * Parse the value string and build the node list associated. Should
354 * produce a flat tree with only TEXTs and ENTITY_REFs.
355 * return values: a pointer to the first child
356 */
357xmlNodePtr xmlStringGetNodeList(xmlDocPtr doc, const CHAR *value) {
358 xmlNodePtr ret = NULL, last = NULL;
359 xmlNodePtr node;
360 CHAR *val;
361 const CHAR *cur = value;
362 const CHAR *q;
363
364 if (value == NULL) return(NULL);
365
366 q = cur;
367 while (*cur != 0) {
368 if (*cur == '&') {
369 if (cur != q) {
370 node = xmlNewTextLen(q, cur - q);
371 if (node == NULL) return(ret);
372 if (last == NULL)
373 last = ret = node;
374 else {
375 last->next = node;
376 last = node;
377 }
378 }
379 cur++;
380 q = cur;
381 while ((*cur != 0) && (*cur != ';')) cur++;
382 if (*cur == 0) {
383 fprintf(stderr,
384 "xmlStringGetNodeList: unterminated entity %30s\n", q);
385 return(ret);
386 }
387 if (cur != q) {
388 val = xmlStrndup(q, cur - q);
389 node = xmlNewReference(doc, val);
390 if (node == NULL) return(ret);
391 if (last == NULL)
392 last = ret = node;
393 else {
394 last->next = node;
395 last = node;
396 }
397 free(val);
398 }
399 cur++;
400 q = cur;
401 } else
402 cur++;
403 }
404 if (cur != q) {
405 node = xmlNewTextLen(q, cur - q);
406 if (node == NULL) return(ret);
407 if (last == NULL)
408 last = ret = node;
409 else {
410 last->next = node;
411 last = node;
412 }
413 }
414 return(ret);
415}
416
417/**
418 * xmlNodeListGetString:
419 * @doc: the document
420 * @list: a Node list
421 * @inLine: should we replace entity contents or show their external form
422 *
423 * Returns the string equivalent to the text contained in the Node list
424 * made of TEXTs and ENTITY_REFs
425 * return values: a pointer to the string copy, the calller must free it.
426 */
427CHAR *xmlNodeListGetString(xmlDocPtr doc, xmlNodePtr list, int inLine) {
428 xmlNodePtr node = list;
429 CHAR *ret = NULL;
430 xmlEntityPtr ent;
431
432 if (list == NULL) return(NULL);
433
434 while (node != NULL) {
435 if (node->type == XML_TEXT_NODE) {
436 if (inLine)
437 ret = xmlStrcat(ret, node->content);
438 else
439 ret = xmlStrcat(ret, xmlEncodeEntities(doc, node->content));
440 } else if (node->type == XML_ENTITY_REF_NODE) {
441 if (inLine) {
442 ent = xmlGetDocEntity(doc, node->name);
443 if (ent != NULL)
444 ret = xmlStrcat(ret, ent->content);
445 else
446 ret = xmlStrcat(ret, node->content);
447 } else {
448 CHAR buf[2];
449 buf[0] = '&'; buf[1] = 0;
450 ret = xmlStrncat(ret, buf, 1);
451 ret = xmlStrcat(ret, node->name);
452 buf[0] = ';'; buf[1] = 0;
453 ret = xmlStrncat(ret, buf, 1);
454 }
455 }
456#if 0
457 else {
458 fprintf(stderr, "xmlGetNodeListString : invalide node type %d\n",
459 node->type);
460 }
461#endif
462 node = node->next;
463 }
464 return(ret);
465}
466
467/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000468 * xmlNewProp:
469 * @node: the holding node
470 * @name: the name of the attribute
471 * @value: the value of the attribute
472 *
473 * Create a new property carried by a node.
474 * return values: a pointer to the attribute
Daniel Veillard260a68f1998-08-13 03:39:55 +0000475 */
476xmlAttrPtr xmlNewProp(xmlNodePtr node, const CHAR *name, const CHAR *value) {
477 xmlAttrPtr cur;
478
479 if (name == NULL) {
480 fprintf(stderr, "xmlNewProp : name == NULL\n");
481 return(NULL);
482 }
483
484 /*
485 * Allocate a new property and fill the fields.
486 */
487 cur = (xmlAttrPtr) malloc(sizeof(xmlAttr));
488 if (cur == NULL) {
489 fprintf(stderr, "xmlNewProp : malloc failed\n");
490 return(NULL);
491 }
492
Daniel Veillard33942841998-10-18 19:12:41 +0000493 cur->type = XML_ATTRIBUTE_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000494 cur->node = node;
495 cur->name = xmlStrdup(name);
496 if (value != NULL)
Daniel Veillardccb09631998-10-27 06:21:04 +0000497 cur->val = xmlStringGetNodeList(node->doc, value);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000498 else
Daniel Veillardccb09631998-10-27 06:21:04 +0000499 cur->val = NULL;
Daniel Veillard27fb0751998-10-17 06:47:46 +0000500#ifndef WITHOUT_CORBA
501 cur->_private = NULL;
502 cur->vepv = NULL;
503#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000504
505 /*
506 * Add it at the end to preserve parsing order ...
507 */
508 cur->next = NULL;
509 if (node != NULL) {
510 if (node->properties == NULL) {
511 node->properties = cur;
512 } else {
513 xmlAttrPtr prev = node->properties;
514
515 while (prev->next != NULL) prev = prev->next;
516 prev->next = cur;
517 }
518 }
519 return(cur);
520}
521
Daniel Veillard97b58771998-10-20 06:14:16 +0000522/**
Daniel Veillardccb09631998-10-27 06:21:04 +0000523 * xmlNewDocProp:
524 * @doc: the document
525 * @name: the name of the attribute
526 * @value: the value of the attribute
527 *
528 * Create a new property carried by a document.
529 * return values: a pointer to the attribute
530 */
531xmlAttrPtr xmlNewDocProp(xmlDocPtr doc, const CHAR *name, const CHAR *value) {
532 xmlAttrPtr cur;
533
534 if (name == NULL) {
535 fprintf(stderr, "xmlNewProp : name == NULL\n");
536 return(NULL);
537 }
538
539 /*
540 * Allocate a new property and fill the fields.
541 */
542 cur = (xmlAttrPtr) malloc(sizeof(xmlAttr));
543 if (cur == NULL) {
544 fprintf(stderr, "xmlNewProp : malloc failed\n");
545 return(NULL);
546 }
547
548 cur->type = XML_ATTRIBUTE_NODE;
549 cur->node = NULL;
550 cur->name = xmlStrdup(name);
551 if (value != NULL)
552 cur->val = xmlStringGetNodeList(doc, value);
553 else
554 cur->val = NULL;
555#ifndef WITHOUT_CORBA
556 cur->_private = NULL;
557 cur->vepv = NULL;
558#endif
559
560 cur->next = NULL;
561 return(cur);
562}
563
564/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000565 * xmlFreePropList:
566 * @cur: the first property in the list
567 *
568 * Free a property and all its siblings, all the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000569 */
570void xmlFreePropList(xmlAttrPtr cur) {
571 xmlAttrPtr next;
572 if (cur == NULL) {
573 fprintf(stderr, "xmlFreePropList : property == NULL\n");
574 return;
575 }
576 while (cur != NULL) {
577 next = cur->next;
578 xmlFreeProp(cur);
579 cur = next;
580 }
581}
582
Daniel Veillard97b58771998-10-20 06:14:16 +0000583/**
584 * xmlFreeProp:
585 * @cur: the first property in the list
586 *
587 * Free one property, all the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000588 */
589void xmlFreeProp(xmlAttrPtr cur) {
590 if (cur == NULL) {
591 fprintf(stderr, "xmlFreeProp : property == NULL\n");
592 return;
593 }
594 if (cur->name != NULL) free((char *) cur->name);
Daniel Veillardccb09631998-10-27 06:21:04 +0000595 if (cur->val != NULL) xmlFreeNodeList(cur->val);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000596 memset(cur, -1, sizeof(xmlAttr));
597 free(cur);
598}
599
Daniel Veillard97b58771998-10-20 06:14:16 +0000600/**
601 * xmlNewNode:
602 * @ns: namespace if any
603 * @name: the node name
604 * @content: the text content if any
605 *
606 * Creation of a new node element. @ns and @content are optionnal (NULL).
Daniel Veillardccb09631998-10-27 06:21:04 +0000607 * If content is non NULL, a child list containing the TEXTs and
608 * ENTITY_REFs node will be created.
Daniel Veillard97b58771998-10-20 06:14:16 +0000609 * return values: a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000610 */
Daniel Veillardccb09631998-10-27 06:21:04 +0000611xmlNodePtr xmlNewNode(xmlNsPtr ns, const CHAR *name) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000612 xmlNodePtr cur;
613
614 if (name == NULL) {
615 fprintf(stderr, "xmlNewNode : name == NULL\n");
616 return(NULL);
617 }
618
619 /*
620 * Allocate a new node and fill the fields.
621 */
622 cur = (xmlNodePtr) malloc(sizeof(xmlNode));
623 if (cur == NULL) {
624 fprintf(stderr, "xmlNewNode : malloc failed\n");
625 return(NULL);
626 }
627
Daniel Veillard33942841998-10-18 19:12:41 +0000628 cur->type = XML_ELEMENT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000629 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000630 cur->parent = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000631 cur->next = NULL;
632 cur->prev = NULL;
633 cur->childs = NULL;
634 cur->properties = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000635 cur->type = 0;
636 cur->name = xmlStrdup(name);
637 cur->ns = ns;
638 cur->nsDef = NULL;
Daniel Veillardccb09631998-10-27 06:21:04 +0000639 cur->content = NULL;
Daniel Veillard27fb0751998-10-17 06:47:46 +0000640#ifndef WITHOUT_CORBA
641 cur->_private = NULL;
642 cur->vepv = NULL;
643#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000644 return(cur);
645}
646
Daniel Veillard97b58771998-10-20 06:14:16 +0000647/**
648 * xmlNewDocNode:
649 * @doc: the document
650 * @ns: namespace if any
651 * @name: the node name
652 * @content: the text content if any
653 *
654 * Creation of a new node element within a document. @ns and @content
655 * are optionnal (NULL).
656 * return values: a pointer to the new node object.
657 */
Daniel Veillard0bef1311998-10-14 02:36:47 +0000658xmlNodePtr xmlNewDocNode(xmlDocPtr doc, xmlNsPtr ns,
659 const CHAR *name, CHAR *content) {
660 xmlNodePtr cur;
661
Daniel Veillardccb09631998-10-27 06:21:04 +0000662 cur = xmlNewNode(ns, name);
663 if (cur != NULL) {
664 cur->doc = doc;
665 if (content != NULL)
666 cur->childs = xmlStringGetNodeList(doc, content);
667 }
Daniel Veillard0bef1311998-10-14 02:36:47 +0000668 return(cur);
669}
670
671
Daniel Veillard97b58771998-10-20 06:14:16 +0000672/**
673 * xmlNewText:
674 * @content: the text content
675 *
676 * Creation of a new text node.
677 * return values: a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000678 */
679xmlNodePtr xmlNewText(const CHAR *content) {
680 xmlNodePtr cur;
681
682 /*
683 * Allocate a new node and fill the fields.
684 */
685 cur = (xmlNodePtr) malloc(sizeof(xmlNode));
686 if (cur == NULL) {
687 fprintf(stderr, "xmlNewText : malloc failed\n");
688 return(NULL);
689 }
690
Daniel Veillard33942841998-10-18 19:12:41 +0000691 cur->type = XML_TEXT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000692 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000693 cur->parent = NULL;
694 cur->next = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000695 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000696 cur->childs = NULL;
697 cur->properties = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000698 cur->type = XML_TEXT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000699 cur->name = xmlStrdup(xmlStringText);
700 cur->ns = NULL;
701 cur->nsDef = NULL;
702 if (content != NULL)
703 cur->content = xmlStrdup(content);
704 else
705 cur->content = NULL;
706 return(cur);
707}
708
Daniel Veillard97b58771998-10-20 06:14:16 +0000709/**
Daniel Veillardccb09631998-10-27 06:21:04 +0000710 * xmlNewReference:
711 * @doc: the document
712 * @name: the reference name, or the reference string with & and ;
713 *
714 * Creation of a new reference node.
715 * return values: a pointer to the new node object.
716 */
717xmlNodePtr xmlNewReference(xmlDocPtr doc, const CHAR *name) {
718 xmlNodePtr cur;
719 xmlEntityPtr ent;
720
721 /*
722 * Allocate a new node and fill the fields.
723 */
724 cur = (xmlNodePtr) malloc(sizeof(xmlNode));
725 if (cur == NULL) {
726 fprintf(stderr, "xmlNewText : malloc failed\n");
727 return(NULL);
728 }
729
730 cur->type = XML_ENTITY_REF_NODE;
731 cur->doc = NULL;
732 cur->parent = NULL;
733 cur->next = NULL;
734 cur->prev = NULL;
735 cur->childs = NULL;
736 cur->properties = NULL;
737 if (name[0] == '&') {
738 int len;
739 name++;
740 len = xmlStrlen(name);
741 if (name[len - 1] == ';')
742 cur->name = xmlStrndup(name, len - 1);
743 else
744 cur->name = xmlStrndup(name, len);
745 } else
746 cur->name = xmlStrdup(name);
747 cur->ns = NULL;
748 cur->nsDef = NULL;
749
750 ent = xmlGetDocEntity(doc, cur->name);
751 if (ent != NULL)
752 cur->content = ent->content;
753 else
754 cur->content = NULL;
755 return(cur);
756}
757
758/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000759 * xmlNewDocText:
760 * @doc: the document
761 * @content: the text content
762 *
763 * Creation of a new text node within a document.
764 * return values: a pointer to the new node object.
765 */
Daniel Veillard0bef1311998-10-14 02:36:47 +0000766xmlNodePtr xmlNewDocText(xmlDocPtr doc, const CHAR *content) {
767 xmlNodePtr cur;
768
769 cur = xmlNewText(content);
770 if (cur != NULL) cur->doc = doc;
771 return(cur);
772}
773
Daniel Veillard97b58771998-10-20 06:14:16 +0000774/**
Daniel Veillardccb09631998-10-27 06:21:04 +0000775 * xmlNewTextLen:
Daniel Veillard97b58771998-10-20 06:14:16 +0000776 * @content: the text content
777 * @len: the text len.
778 *
779 * Creation of a new text node with an extra parameter for the content's lenght
780 * return values: a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000781 */
782xmlNodePtr xmlNewTextLen(const CHAR *content, int len) {
783 xmlNodePtr cur;
784
785 /*
786 * Allocate a new node and fill the fields.
787 */
788 cur = (xmlNodePtr) malloc(sizeof(xmlNode));
789 if (cur == NULL) {
790 fprintf(stderr, "xmlNewText : malloc failed\n");
791 return(NULL);
792 }
793
Daniel Veillard33942841998-10-18 19:12:41 +0000794 cur->type = XML_TEXT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000795 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000796 cur->parent = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000797 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000798 cur->next = NULL;
799 cur->childs = NULL;
800 cur->properties = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000801 cur->type = XML_TEXT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000802 cur->name = xmlStrdup(xmlStringText);
803 cur->ns = NULL;
804 cur->nsDef = NULL;
805 if (content != NULL)
806 cur->content = xmlStrndup(content, len);
807 else
808 cur->content = NULL;
809 return(cur);
810}
811
Daniel Veillard97b58771998-10-20 06:14:16 +0000812/**
813 * xmlNewDocTextLen:
814 * @doc: the document
815 * @content: the text content
816 * @len: the text len.
817 *
818 * Creation of a new text node with an extra content lenght parameter. The
819 * text node pertain to a given document.
820 * return values: a pointer to the new node object.
821 */
Daniel Veillard0bef1311998-10-14 02:36:47 +0000822xmlNodePtr xmlNewDocTextLen(xmlDocPtr doc, const CHAR *content, int len) {
823 xmlNodePtr cur;
824
825 cur = xmlNewTextLen(content, len);
826 if (cur != NULL) cur->doc = doc;
827 return(cur);
828}
829
Daniel Veillard97b58771998-10-20 06:14:16 +0000830/**
831 * xmlNewComment:
832 * @content: the comment content
833 *
834 * Creation of a new node containing a comment.
835 * return values: a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000836 */
837xmlNodePtr xmlNewComment(CHAR *content) {
838 xmlNodePtr cur;
839
840 /*
841 * Allocate a new node and fill the fields.
842 */
843 cur = (xmlNodePtr) malloc(sizeof(xmlNode));
844 if (cur == NULL) {
845 fprintf(stderr, "xmlNewComment : malloc failed\n");
846 return(NULL);
847 }
848
Daniel Veillard33942841998-10-18 19:12:41 +0000849 cur->type = XML_COMMENT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000850 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000851 cur->parent = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000852 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000853 cur->next = NULL;
854 cur->childs = NULL;
855 cur->properties = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000856 cur->type = XML_COMMENT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000857 cur->name = xmlStrdup(xmlStringText);
858 cur->ns = NULL;
859 cur->nsDef = NULL;
860 if (content != NULL)
861 cur->content = xmlStrdup(content);
862 else
863 cur->content = NULL;
864 return(cur);
865}
866
Daniel Veillard97b58771998-10-20 06:14:16 +0000867/**
868 * xmlNewComment:
869 * @doc: the document
870 * @content: the comment content
871 *
872 * Creation of a new node containing a commentwithin a document.
873 * return values: a pointer to the new node object.
874 */
Daniel Veillard0bef1311998-10-14 02:36:47 +0000875xmlNodePtr xmlNewDocComment(xmlDocPtr doc, CHAR *content) {
876 xmlNodePtr cur;
877
878 cur = xmlNewComment(content);
879 if (cur != NULL) cur->doc = doc;
880 return(cur);
881}
882
Daniel Veillard97b58771998-10-20 06:14:16 +0000883/**
884 * xmlNewChild:
885 * @parent: the parent node
886 * @ns: a namespace if any
887 * @name: the name of the child
888 * @content: the content of the child if any.
889 *
890 *
891 * Creation of a new child element, added at the end of @parent childs list.
Daniel Veillardccb09631998-10-27 06:21:04 +0000892 * @ns and @content parameters are optionnal (NULL). If content is non NULL,
893 * a child list containing the TEXTs and ENTITY_REFs node will be created.
Daniel Veillard97b58771998-10-20 06:14:16 +0000894 * return values: a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000895 */
896xmlNodePtr xmlNewChild(xmlNodePtr parent, xmlNsPtr ns,
897 const CHAR *name, CHAR *content) {
898 xmlNodePtr cur, prev;
899
900 if (parent == NULL) {
901 fprintf(stderr, "xmlNewChild : parent == NULL\n");
902 return(NULL);
903 }
904
905 if (name == NULL) {
906 fprintf(stderr, "xmlNewChild : name == NULL\n");
907 return(NULL);
908 }
909
910 /*
911 * Allocate a new node
912 */
913 if (ns == NULL)
Daniel Veillardccb09631998-10-27 06:21:04 +0000914 cur = xmlNewDocNode(parent->doc, parent->ns, name, content);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000915 else
Daniel Veillardccb09631998-10-27 06:21:04 +0000916 cur = xmlNewDocNode(parent->doc, ns, name, content);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000917 if (cur == NULL) return(NULL);
918
919 /*
920 * add the new element at the end of the childs list.
921 */
Daniel Veillardccb09631998-10-27 06:21:04 +0000922 cur->type = XML_ELEMENT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000923 cur->parent = parent;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000924 cur->doc = parent->doc;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000925 if (parent->childs == NULL) {
926 parent->childs = cur;
927 } else {
928 prev = parent->childs;
929 while (prev->next != NULL) prev = prev->next;
930 prev->next = cur;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000931 cur->prev = prev;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000932 }
933
934 return(cur);
935}
936
Daniel Veillard97b58771998-10-20 06:14:16 +0000937/**
938 * xmlAddChild:
939 * @parent: the parent node
940 * @cur: the child node
941 *
942 * Add a new child element, to @parent, at the end of the child list.
943 * return values: the child or NULL in case of error.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000944 */
945xmlNodePtr xmlAddChild(xmlNodePtr parent, xmlNodePtr cur) {
946 xmlNodePtr prev;
947
948 if (parent == NULL) {
949 fprintf(stderr, "xmladdChild : parent == NULL\n");
950 return(NULL);
951 }
952
953 if (cur == NULL) {
954 fprintf(stderr, "xmladdChild : child == NULL\n");
955 return(NULL);
956 }
957
Daniel Veillard0bef1311998-10-14 02:36:47 +0000958 if ((cur->doc != NULL) && (parent->doc != NULL) &&
959 (cur->doc != parent->doc)) {
960 fprintf(stderr, "Elements moved to a different document\n");
961 }
962
Daniel Veillard260a68f1998-08-13 03:39:55 +0000963 /*
964 * add the new element at the end of the childs list.
965 */
966 cur->parent = parent;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000967 cur->doc = parent->doc; /* the parent may not be linked to a doc ! */
Daniel Veillardccb09631998-10-27 06:21:04 +0000968 /*
969 * Handle the case where parent->content != NULL, in that case it will
970 * create a intermediate TEXT node.
971 */
972 if (parent->content != NULL) {
973 xmlNodePtr text;
974
975 text = xmlNewDocText(parent->doc, parent->content);
976 if (text != NULL) {
977 text->next = parent->childs;
978 if (text->next != NULL)
979 text->next->prev = text;
980 parent->childs = text;
981 free(parent->content);
982 parent->content = NULL;
983 }
984 }
Daniel Veillard260a68f1998-08-13 03:39:55 +0000985 if (parent->childs == NULL) {
986 parent->childs = cur;
987 } else {
988 prev = parent->childs;
989 while (prev->next != NULL) prev = prev->next;
990 prev->next = cur;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000991 cur->prev = prev;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000992 }
993
994 return(cur);
995}
996
Daniel Veillard97b58771998-10-20 06:14:16 +0000997/**
998 * xmlGetLastChild:
999 * @parent: the parent node
1000 *
1001 * Search the last child of a node.
1002 * return values: the last child or NULL if none.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001003 */
1004xmlNodePtr xmlGetLastChild(xmlNodePtr parent) {
1005 xmlNodePtr last;
1006
1007 if (parent == NULL) {
1008 fprintf(stderr, "xmlGetLastChild : parent == NULL\n");
1009 return(NULL);
1010 }
1011
1012 /*
1013 * add the new element at the end of the childs list.
1014 */
1015 if (parent->childs == NULL) {
1016 return(NULL);
1017 } else {
1018 last = parent->childs;
1019 while (last->next != NULL) last = last->next;
1020 }
1021 return(last);
1022}
1023
Daniel Veillard97b58771998-10-20 06:14:16 +00001024/**
1025 * xmlFreeNodeList:
1026 * @cur: the first node in the list
1027 *
1028 * Free a node and all its siblings, this is a recursive behaviour, all
1029 * the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001030 */
1031void xmlFreeNodeList(xmlNodePtr cur) {
1032 xmlNodePtr next;
1033 if (cur == NULL) {
1034 fprintf(stderr, "xmlFreeNodeList : node == NULL\n");
1035 return;
1036 }
1037 while (cur != NULL) {
1038 next = cur->next;
1039 xmlFreeNode(cur);
1040 cur = next;
1041 }
1042}
1043
Daniel Veillard97b58771998-10-20 06:14:16 +00001044/**
1045 * xmlFreeNode:
1046 * @cur: the node
1047 *
1048 * Free a node, this is a recursive behaviour, all the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001049 */
1050void xmlFreeNode(xmlNodePtr cur) {
1051 if (cur == NULL) {
1052 fprintf(stderr, "xmlFreeNode : node == NULL\n");
1053 return;
1054 }
Daniel Veillardccb09631998-10-27 06:21:04 +00001055 cur->doc = NULL;
1056 cur->parent = NULL;
1057 cur->next = NULL;
1058 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001059 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillardccb09631998-10-27 06:21:04 +00001060 if (cur->properties != NULL) xmlFreePropList(cur->properties);
1061 if (cur->type != XML_ENTITY_REF_NODE)
1062 if (cur->content != NULL) free(cur->content);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001063 if (cur->name != NULL) free((char *) cur->name);
1064 if (cur->nsDef != NULL) xmlFreeNsList(cur->nsDef);
1065 memset(cur, -1, sizeof(xmlNode));
1066 free(cur);
1067}
1068
1069/************************************************************************
1070 * *
1071 * Content access functions *
1072 * *
1073 ************************************************************************/
1074
Daniel Veillard97b58771998-10-20 06:14:16 +00001075/**
1076 * xmlNodeSetContent:
1077 * @cur: the node being modified
1078 * @content: the new value of the content
1079 *
1080 * Replace the content of a node.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001081 */
1082void xmlNodeSetContent(xmlNodePtr cur, const CHAR *content) {
1083 if (cur == NULL) {
1084 fprintf(stderr, "xmlNodeSetContent : node == NULL\n");
1085 return;
1086 }
1087 if (cur->content != NULL) free(cur->content);
1088 if (content != NULL)
1089 cur->content = xmlStrdup(content);
1090 else
1091 cur->content = NULL;
1092}
1093
Daniel Veillard97b58771998-10-20 06:14:16 +00001094/**
1095 * xmlNodeSetContentLen:
1096 * @cur: the node being modified
1097 * @content: the new value of the content
1098 * @len: the size of @content
1099 *
1100 * Replace the content of a node.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001101 */
1102void xmlNodeSetContentLen(xmlNodePtr cur, const CHAR *content, int len) {
1103 if (cur == NULL) {
1104 fprintf(stderr, "xmlNodeSetContent : node == NULL\n");
1105 return;
1106 }
1107 if (cur->content != NULL) free(cur->content);
1108 if (content != NULL)
1109 cur->content = xmlStrndup(content, len);
1110 else
1111 cur->content = NULL;
1112}
1113
Daniel Veillard97b58771998-10-20 06:14:16 +00001114/**
1115 * xmlNodeAddContent:
1116 * @cur: the node being modified
1117 * @content: extra content
1118 *
1119 * Append the extra substring to the node content.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001120 */
1121void xmlNodeAddContent(xmlNodePtr cur, const CHAR *content) {
1122 if (cur == NULL) {
1123 fprintf(stderr, "xmlNodeAddContent : node == NULL\n");
1124 return;
1125 }
1126 cur->content = xmlStrcat(cur->content, content);
1127}
1128
Daniel Veillard97b58771998-10-20 06:14:16 +00001129/**
1130 * xmlNodeAddContentLen:
1131 * @cur: the node being modified
1132 * @content: extra content
1133 * @len: the size of @content
1134 *
1135 * Append the extra substring to the node content.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001136 */
1137void xmlNodeAddContentLen(xmlNodePtr cur, const CHAR *content, int len) {
1138 if (cur == NULL) {
1139 fprintf(stderr, "xmlNodeAddContent : node == NULL\n");
1140 return;
1141 }
1142 cur->content = xmlStrncat(cur->content, content, len);
1143}
1144
Daniel Veillard97b58771998-10-20 06:14:16 +00001145/**
1146 * xmlSearchNs:
1147 * @doc: the document
1148 * @node: the current node
1149 * @nameSpace: the namespace string
Daniel Veillard260a68f1998-08-13 03:39:55 +00001150 *
Daniel Veillard97b58771998-10-20 06:14:16 +00001151 * Search a Ns registered under a given name space for a document.
1152 * recurse on the parents until it finds the defined namespace
1153 * or return NULL otherwise.
1154 * @nameSpace can be NULL, this is a search for the default namespace.
1155 * return values: the namespace pointer or NULL.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001156 */
1157xmlNsPtr xmlSearchNs(xmlDocPtr doc, xmlNodePtr node, const CHAR *nameSpace) {
1158 xmlNsPtr cur;
1159
1160 while (node != NULL) {
1161 cur = node->nsDef;
1162 while (cur != NULL) {
1163 if ((cur->prefix == NULL) && (nameSpace == NULL))
1164 return(cur);
1165 if ((cur->prefix != NULL) && (nameSpace != NULL) &&
1166 (!xmlStrcmp(cur->prefix, nameSpace)))
1167 return(cur);
1168 cur = cur->next;
1169 }
1170 node = node->parent;
1171 }
1172 if (doc != NULL) {
1173 cur = doc->oldNs;
1174 while (cur != NULL) {
1175 if ((cur->prefix != NULL) && (nameSpace != NULL) &&
1176 (!xmlStrcmp(cur->prefix, nameSpace)))
1177 return(cur);
1178 cur = cur->next;
1179 }
1180 }
1181 return(NULL);
1182}
1183
Daniel Veillard97b58771998-10-20 06:14:16 +00001184/**
1185 * xmlSearchNsByHref:
1186 * @doc: the document
1187 * @node: the current node
1188 * @href: the namespace value
1189 *
1190 * Search a Ns aliasing a given URI. Recurse on the parents until it finds
1191 * the defined namespace or return NULL otherwise.
1192 * return values: the namespace pointer or NULL.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001193 */
1194xmlNsPtr xmlSearchNsByHref(xmlDocPtr doc, xmlNodePtr node, const CHAR *href) {
1195 xmlNsPtr cur;
1196
1197 while (node != NULL) {
1198 cur = node->nsDef;
1199 while (cur != NULL) {
1200 if ((cur->href != NULL) && (href != NULL) &&
1201 (!xmlStrcmp(cur->href, href)))
1202 return(cur);
1203 cur = cur->next;
1204 }
1205 node = node->parent;
1206 }
1207 if (doc != NULL) {
1208 cur = doc->oldNs;
1209 while (cur != NULL) {
1210 if ((cur->href != NULL) && (href != NULL) &&
1211 (!xmlStrcmp(cur->href, href)))
1212 return(cur);
1213 cur = cur->next;
1214 }
1215 }
1216 return(NULL);
1217}
1218
Daniel Veillard97b58771998-10-20 06:14:16 +00001219/**
1220 * xmlGetProp:
1221 * @node: the node
1222 * @name: the attribute name
1223 *
1224 * Search and get the value of an attribute associated to a node
Daniel Veillardccb09631998-10-27 06:21:04 +00001225 * This does the entity substitution.
Daniel Veillard97b58771998-10-20 06:14:16 +00001226 * return values: the attribute value or NULL if not found.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001227 */
1228const CHAR *xmlGetProp(xmlNodePtr node, const CHAR *name) {
1229 xmlAttrPtr prop = node->properties;
1230
1231 while (prop != NULL) {
Daniel Veillardccb09631998-10-27 06:21:04 +00001232 if (!xmlStrcmp(prop->name, name))
1233 return(xmlNodeListGetString(node->doc, prop->val, 1));
Daniel Veillard260a68f1998-08-13 03:39:55 +00001234 prop = prop->next;
1235 }
1236 return(NULL);
1237}
1238
Daniel Veillard97b58771998-10-20 06:14:16 +00001239/**
Daniel Veillardccb09631998-10-27 06:21:04 +00001240 * xmlSetProp:
Daniel Veillard97b58771998-10-20 06:14:16 +00001241 * @node: the node
1242 * @name: the attribute name
1243 * @value: the attribute value
1244 *
1245 * Set (or reset) an attribute carried by a node.
1246 * return values: the attribute pointer.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001247 */
1248xmlAttrPtr xmlSetProp(xmlNodePtr node, const CHAR *name, const CHAR *value) {
1249 xmlAttrPtr prop = node->properties;
1250
1251 while (prop != NULL) {
1252 if (!xmlStrcmp(prop->name, name)) {
Daniel Veillardccb09631998-10-27 06:21:04 +00001253 if (prop->val != NULL)
1254 xmlFreeNode(prop->val);
1255 prop->val = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001256 if (value != NULL)
Daniel Veillardccb09631998-10-27 06:21:04 +00001257 prop->val = xmlStringGetNodeList(node->doc, value);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001258 return(prop);
1259 }
1260 prop = prop->next;
1261 }
1262 prop = xmlNewProp(node, name, value);
1263 return(prop);
1264}
1265
Daniel Veillard97b58771998-10-20 06:14:16 +00001266/**
1267 * xmlNodeIsText:
1268 * @node: the node
1269 *
1270 * Is this node a Text node ?
1271 * return values: 1 yes, 0 no
Daniel Veillard260a68f1998-08-13 03:39:55 +00001272 */
1273int xmlNodeIsText(xmlNodePtr node) {
1274 if (node == NULL) return(0);
1275
Daniel Veillard0bef1311998-10-14 02:36:47 +00001276 if (node->type == XML_TEXT_NODE) return(1);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001277 return(0);
1278}
1279
Daniel Veillard97b58771998-10-20 06:14:16 +00001280/**
1281 * xmlNodeIsText:
1282 * @node: the node
1283 * @content: the content
1284 * @len: @content lenght
1285 *
1286 * Concat the given string at the end of the existing node content
Daniel Veillard260a68f1998-08-13 03:39:55 +00001287 */
Daniel Veillard97b58771998-10-20 06:14:16 +00001288
Daniel Veillard260a68f1998-08-13 03:39:55 +00001289void xmlTextConcat(xmlNodePtr node, const CHAR *content, int len) {
1290 if (node == NULL) return;
1291
Daniel Veillard0bef1311998-10-14 02:36:47 +00001292 if (node->type != XML_TEXT_NODE) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001293 fprintf(stderr, "xmlTextConcat: node is not text\n");
1294 return;
1295 }
1296 node->content = xmlStrncat(node->content, content, len);
1297}
1298
1299/************************************************************************
1300 * *
1301 * Output : to a FILE or in memory *
1302 * *
1303 ************************************************************************/
1304
Daniel Veillard260a68f1998-08-13 03:39:55 +00001305static CHAR *buffer = NULL;
1306static int buffer_index = 0;
1307static int buffer_size = 0;
1308
Daniel Veillard97b58771998-10-20 06:14:16 +00001309/**
1310 * xmlBufferWriteCHAR:
1311 * @string: the string to add
1312 *
1313 * routine which manage and grows an output buffer. This one add
1314 * CHARs at the end of the array.
1315 */
Daniel Veillard260a68f1998-08-13 03:39:55 +00001316void xmlBufferWriteCHAR(const CHAR *string) {
1317 const CHAR *cur;
1318
1319 if (buffer == NULL) {
1320 buffer_size = 50000;
1321 buffer = (CHAR *) malloc(buffer_size * sizeof(CHAR));
1322 if (buffer == NULL) {
1323 fprintf(stderr, "xmlBufferWrite : out of memory!\n");
1324 exit(1);
1325 }
1326 }
1327
1328 if (string == NULL) return;
1329 for (cur = string;*cur != 0;cur++) {
1330 if (buffer_index + 10 >= buffer_size) {
1331 buffer_size *= 2;
1332 buffer = (CHAR *) realloc(buffer, buffer_size * sizeof(CHAR));
1333 if (buffer == NULL) {
1334 fprintf(stderr, "xmlBufferWrite : out of memory!\n");
1335 exit(1);
1336 }
1337 }
1338 buffer[buffer_index++] = *cur;
1339 }
1340 buffer[buffer_index] = 0;
1341}
1342
Daniel Veillard97b58771998-10-20 06:14:16 +00001343/**
1344 * xmlBufferWriteChar:
1345 * @string: the string to add
1346 *
1347 * routine which manage and grows an output buffer. This one add
1348 * C chars at the end of the array.
1349 */
Daniel Veillard260a68f1998-08-13 03:39:55 +00001350void xmlBufferWriteChar(const char *string) {
1351 const char *cur;
1352
1353 if (buffer == NULL) {
1354 buffer_size = 50000;
1355 buffer = (CHAR *) malloc(buffer_size * sizeof(CHAR));
1356 if (buffer == NULL) {
1357 fprintf(stderr, "xmlBufferWrite : out of memory!\n");
1358 exit(1);
1359 }
1360 }
1361
1362 if (string == NULL) return;
1363 for (cur = string;*cur != 0;cur++) {
1364 if (buffer_index + 10 >= buffer_size) {
1365 buffer_size *= 2;
1366 buffer = (CHAR *) realloc(buffer, buffer_size * sizeof(CHAR));
1367 if (buffer == NULL) {
1368 fprintf(stderr, "xmlBufferWrite : out of memory!\n");
1369 exit(1);
1370 }
1371 }
1372 buffer[buffer_index++] = *cur;
1373 }
1374 buffer[buffer_index] = 0;
1375}
1376
Daniel Veillard97b58771998-10-20 06:14:16 +00001377/**
1378 * xmlGlobalNsDump:
1379 * @cur: a namespace
1380 *
1381 * Dump a global Namespace, this is the old version based on PIs.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001382 */
1383static void xmlGlobalNsDump(xmlNsPtr cur) {
1384 if (cur == NULL) {
1385 fprintf(stderr, "xmlGlobalNsDump : Ns == NULL\n");
1386 return;
1387 }
1388 if (cur->type == XML_GLOBAL_NAMESPACE) {
1389 xmlBufferWriteChar("<?namespace");
1390 if (cur->href != NULL) {
1391 xmlBufferWriteChar(" href=\"");
1392 xmlBufferWriteCHAR(cur->href);
1393 xmlBufferWriteChar("\"");
1394 }
1395 if (cur->prefix != NULL) {
1396 xmlBufferWriteChar(" AS=\"");
1397 xmlBufferWriteCHAR(cur->prefix);
1398 xmlBufferWriteChar("\"");
1399 }
1400 xmlBufferWriteChar("?>\n");
1401 }
1402}
1403
Daniel Veillard97b58771998-10-20 06:14:16 +00001404/**
1405 * xmlGlobalNsListDump:
1406 * @cur: the first namespace
1407 *
1408 * Dump a list of global Namespace, this is the old version based on PIs.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001409 */
Daniel Veillard260a68f1998-08-13 03:39:55 +00001410static void xmlGlobalNsListDump(xmlNsPtr cur) {
1411 while (cur != NULL) {
1412 xmlGlobalNsDump(cur);
1413 cur = cur->next;
1414 }
1415}
1416
Daniel Veillard97b58771998-10-20 06:14:16 +00001417/**
1418 * xmlNsDump:
1419 * @cur: a namespace
1420 *
Daniel Veillard260a68f1998-08-13 03:39:55 +00001421 * Dump a local Namespace definition.
Daniel Veillard97b58771998-10-20 06:14:16 +00001422 * Should be called in the context of attributes dumps.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001423 */
1424static void xmlNsDump(xmlNsPtr cur) {
1425 if (cur == NULL) {
1426 fprintf(stderr, "xmlNsDump : Ns == NULL\n");
1427 return;
1428 }
1429 if (cur->type == XML_LOCAL_NAMESPACE) {
1430 /* Within the context of an element attributes */
1431 if (cur->prefix != NULL) {
1432 xmlBufferWriteChar(" xmlns:");
1433 xmlBufferWriteCHAR(cur->prefix);
1434 } else
1435 xmlBufferWriteChar(" xmlns");
1436 xmlBufferWriteChar("=\"");
1437 xmlBufferWriteCHAR(cur->href);
1438 xmlBufferWriteChar("\"");
1439 }
1440}
1441
Daniel Veillard97b58771998-10-20 06:14:16 +00001442/**
1443 * xmlNsListDump:
1444 * @cur: the first namespace
1445 *
1446 * Dump a list of local Namespace definitions.
1447 * Should be called in the context of attributes dumps.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001448 */
Daniel Veillard260a68f1998-08-13 03:39:55 +00001449static void xmlNsListDump(xmlNsPtr cur) {
1450 while (cur != NULL) {
1451 xmlNsDump(cur);
1452 cur = cur->next;
1453 }
1454}
1455
Daniel Veillard97b58771998-10-20 06:14:16 +00001456/**
1457 * xmlDtdDump:
1458 * @doc: the document
1459 *
1460 * Dump the XML document DTD, if any.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001461 */
Daniel Veillard260a68f1998-08-13 03:39:55 +00001462static void xmlDtdDump(xmlDocPtr doc) {
1463 xmlDtdPtr cur = doc->dtd;
1464
1465 if (cur == NULL) {
1466 fprintf(stderr, "xmlDtdDump : DTD == NULL\n");
1467 return;
1468 }
1469 xmlBufferWriteChar("<!DOCTYPE ");
1470 xmlBufferWriteCHAR(cur->name);
1471 if (cur->ExternalID != NULL) {
1472 xmlBufferWriteChar(" PUBLIC \"");
1473 xmlBufferWriteCHAR(cur->ExternalID);
1474 xmlBufferWriteChar("\" \"");
1475 xmlBufferWriteCHAR(cur->SystemID);
1476 xmlBufferWriteChar("\"");
1477 } else if (cur->SystemID != NULL) {
1478 xmlBufferWriteChar(" SYSTEM \"");
1479 xmlBufferWriteCHAR(cur->SystemID);
1480 xmlBufferWriteChar("\"");
1481 }
1482 if ((cur->entities == NULL) && (doc->entities == NULL)) {
1483 xmlBufferWriteChar(">\n");
1484 return;
1485 }
1486 xmlBufferWriteChar(" [\n");
1487 if (cur->entities != NULL)
1488 xmlDumpEntitiesTable((xmlEntitiesTablePtr) cur->entities);
1489 if (doc->entities != NULL)
1490 xmlDumpEntitiesTable((xmlEntitiesTablePtr) doc->entities);
1491 xmlBufferWriteChar("]");
1492
1493 /* TODO !!! a lot more things to dump ... */
1494 xmlBufferWriteChar(">\n");
1495}
1496
Daniel Veillard97b58771998-10-20 06:14:16 +00001497/**
1498 * xmlAttrDump:
1499 * @doc: the document
1500 * @cur: the attribute pointer
1501 *
1502 * Dump an XML attribute
Daniel Veillard260a68f1998-08-13 03:39:55 +00001503 */
Daniel Veillard260a68f1998-08-13 03:39:55 +00001504static void xmlAttrDump(xmlDocPtr doc, xmlAttrPtr cur) {
Daniel Veillardccb09631998-10-27 06:21:04 +00001505 CHAR *value;
1506
Daniel Veillard260a68f1998-08-13 03:39:55 +00001507 if (cur == NULL) {
1508 fprintf(stderr, "xmlAttrDump : property == NULL\n");
1509 return;
1510 }
1511 xmlBufferWriteChar(" ");
1512 xmlBufferWriteCHAR(cur->name);
Daniel Veillardccb09631998-10-27 06:21:04 +00001513 value = xmlNodeListGetString(doc, cur->val, 0);
1514 if (value) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001515 xmlBufferWriteChar("=\"");
Daniel Veillardccb09631998-10-27 06:21:04 +00001516 xmlBufferWriteCHAR(value);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001517 xmlBufferWriteChar("\"");
Daniel Veillardccb09631998-10-27 06:21:04 +00001518 free(value);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001519 }
1520}
1521
Daniel Veillard97b58771998-10-20 06:14:16 +00001522/**
1523 * xmlAttrListDump:
1524 * @doc: the document
1525 * @cur: the first attribute pointer
1526 *
1527 * Dump a list of XML attributes
Daniel Veillard260a68f1998-08-13 03:39:55 +00001528 */
Daniel Veillard260a68f1998-08-13 03:39:55 +00001529static void xmlAttrListDump(xmlDocPtr doc, xmlAttrPtr cur) {
1530 if (cur == NULL) {
1531 fprintf(stderr, "xmlAttrListDump : property == NULL\n");
1532 return;
1533 }
1534 while (cur != NULL) {
1535 xmlAttrDump(doc, cur);
1536 cur = cur->next;
1537 }
1538}
1539
Daniel Veillard260a68f1998-08-13 03:39:55 +00001540
1541static void xmlNodeDump(xmlDocPtr doc, xmlNodePtr cur, int level);
Daniel Veillard97b58771998-10-20 06:14:16 +00001542/**
1543 * xmlNodeListDump:
1544 * @doc: the document
1545 * @cur: the first node
1546 * @level: the imbrication level for indenting
1547 *
1548 * Dump an XML node list, recursive behaviour,children are printed too.
1549 */
Daniel Veillard260a68f1998-08-13 03:39:55 +00001550static void xmlNodeListDump(xmlDocPtr doc, xmlNodePtr cur, int level) {
Daniel Veillardccb09631998-10-27 06:21:04 +00001551 int needIndent = 0, i;
1552
Daniel Veillard260a68f1998-08-13 03:39:55 +00001553 if (cur == NULL) {
1554 fprintf(stderr, "xmlNodeListDump : node == NULL\n");
1555 return;
1556 }
1557 while (cur != NULL) {
Daniel Veillardccb09631998-10-27 06:21:04 +00001558 if ((cur->type != XML_TEXT_NODE) &&
1559 (cur->type != XML_ENTITY_REF_NODE)) {
1560 if (!needIndent) {
1561 needIndent = 1;
1562 xmlBufferWriteChar("\n");
1563 }
1564 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00001565 xmlNodeDump(doc, cur, level);
1566 cur = cur->next;
1567 }
Daniel Veillardccb09631998-10-27 06:21:04 +00001568 if ((xmlIndentTreeOutput) && (needIndent))
1569 for (i = 1;i < level;i++)
1570 xmlBufferWriteChar(" ");
Daniel Veillard260a68f1998-08-13 03:39:55 +00001571}
1572
Daniel Veillard97b58771998-10-20 06:14:16 +00001573/**
Daniel Veillardccb09631998-10-27 06:21:04 +00001574 * xmlNodeDump:
Daniel Veillard97b58771998-10-20 06:14:16 +00001575 * @doc: the document
1576 * @cur: the current node
1577 * @level: the imbrication level for indenting
1578 *
1579 * Dump an XML node, recursive behaviour,children are printed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001580 */
Daniel Veillard260a68f1998-08-13 03:39:55 +00001581static void xmlNodeDump(xmlDocPtr doc, xmlNodePtr cur, int level) {
1582 int i;
1583
1584 if (cur == NULL) {
1585 fprintf(stderr, "xmlNodeDump : node == NULL\n");
1586 return;
1587 }
Daniel Veillard0bef1311998-10-14 02:36:47 +00001588 if (cur->type == XML_TEXT_NODE) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001589 if (cur->content != NULL)
1590 xmlBufferWriteCHAR(xmlEncodeEntities(doc, cur->content));
1591 return;
1592 }
Daniel Veillard0bef1311998-10-14 02:36:47 +00001593 if (cur->type == XML_COMMENT_NODE) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001594 if (cur->content != NULL) {
1595 xmlBufferWriteChar("<!--");
1596 xmlBufferWriteCHAR(cur->content);
1597 xmlBufferWriteChar("-->");
1598 }
1599 return;
1600 }
Daniel Veillardccb09631998-10-27 06:21:04 +00001601 if (cur->type == XML_ENTITY_REF_NODE) {
1602 xmlBufferWriteChar("&");
1603 xmlBufferWriteCHAR(cur->name);
1604 xmlBufferWriteChar(";");
1605 return;
1606 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00001607 if (xmlIndentTreeOutput)
1608 for (i = 0;i < level;i++)
1609 xmlBufferWriteChar(" ");
1610
1611 xmlBufferWriteChar("<");
1612 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
1613 xmlBufferWriteCHAR(cur->ns->prefix);
1614 xmlBufferWriteChar(":");
1615 }
1616
1617 xmlBufferWriteCHAR(cur->name);
1618 if (cur->nsDef)
1619 xmlNsListDump(cur->nsDef);
1620 if (cur->properties != NULL)
1621 xmlAttrListDump(doc, cur->properties);
1622
1623 if ((cur->content == NULL) && (cur->childs == NULL)) {
1624 xmlBufferWriteChar("/>\n");
1625 return;
1626 }
1627 xmlBufferWriteChar(">");
1628 if (cur->content != NULL)
1629 xmlBufferWriteCHAR(xmlEncodeEntities(doc, cur->content));
1630 if (cur->childs != NULL) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001631 xmlNodeListDump(doc, cur->childs, level + 1);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001632 }
1633 xmlBufferWriteChar("</");
1634 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
1635 xmlBufferWriteCHAR(cur->ns->prefix);
1636 xmlBufferWriteChar(":");
1637 }
1638
1639 xmlBufferWriteCHAR(cur->name);
1640 xmlBufferWriteChar(">\n");
1641}
1642
Daniel Veillard97b58771998-10-20 06:14:16 +00001643/**
1644 * xmlDocContentDump:
1645 * @cur: the document
1646 *
1647 * Dump an XML document.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001648 */
1649static void xmlDocContentDump(xmlDocPtr cur) {
1650 if (oldXMLWDcompatibility)
1651 xmlBufferWriteChar("<?XML version=\"");
1652 else
1653 xmlBufferWriteChar("<?xml version=\"");
1654 xmlBufferWriteCHAR(cur->version);
1655 xmlBufferWriteChar("\"");
1656 if (cur->encoding != NULL) {
1657 xmlBufferWriteChar(" encoding=\"");
1658 xmlBufferWriteCHAR(cur->encoding);
1659 xmlBufferWriteChar("\"");
1660 }
1661 switch (cur->standalone) {
1662 case 0:
1663 xmlBufferWriteChar(" standalone=\"no\"");
1664 break;
1665 case 1:
1666 xmlBufferWriteChar(" standalone=\"yes\"");
1667 break;
1668 }
1669 xmlBufferWriteChar("?>\n");
1670 if ((cur->dtd != NULL) || (cur->entities != NULL))
1671 xmlDtdDump(cur);
1672 if (cur->root != NULL) {
1673 /* global namespace definitions, the old way */
1674 if (oldXMLWDcompatibility)
1675 xmlGlobalNsListDump(cur->oldNs);
1676 else
1677 xmlUpgradeOldNs(cur);
1678 xmlNodeDump(cur, cur->root, 0);
1679 }
1680}
1681
Daniel Veillard97b58771998-10-20 06:14:16 +00001682/**
1683 * xmlDocDumpMemory:
1684 * @cur: the document
1685 * @mem: OUT: the memory pointer
1686 * @size: OUT: the memory lenght
1687 *
1688 * Dump an XML document in memory and return the CHAR * and it's size.
1689 * It's up to the caller to free the memory.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001690 */
Daniel Veillard260a68f1998-08-13 03:39:55 +00001691void xmlDocDumpMemory(xmlDocPtr cur, CHAR**mem, int *size) {
1692 if (cur == NULL) {
1693 fprintf(stderr, "xmlDocDump : document == NULL\n");
1694 *mem = NULL;
1695 *size = 0;
1696 return;
1697 }
1698 buffer_index = 0;
1699 xmlDocContentDump(cur);
1700
1701 *mem = buffer;
1702 *size = buffer_index;
1703}
1704
Daniel Veillard97b58771998-10-20 06:14:16 +00001705/**
1706 * xmlGetDocCompressMode:
1707 * @doc: the document
1708 *
1709 * get the compression ratio for a document, ZLIB based
1710 * return values: 0 (uncompressed) to 9 (max compression)
Daniel Veillard151b1b01998-09-23 00:49:46 +00001711 */
Daniel Veillard15a8df41998-09-24 19:15:06 +00001712int xmlGetDocCompressMode (xmlDocPtr doc) {
1713 if (doc == NULL) return(-1);
1714 return(doc->compression);
1715}
1716
Daniel Veillard97b58771998-10-20 06:14:16 +00001717/**
1718 * xmlSetDocCompressMode:
1719 * @doc: the document
1720 * @mode: the compression ratio
1721 *
1722 * set the compression ratio for a document, ZLIB based
1723 * Correct values: 0 (uncompressed) to 9 (max compression)
1724 */
Daniel Veillard15a8df41998-09-24 19:15:06 +00001725void xmlSetDocCompressMode (xmlDocPtr doc, int mode) {
1726 if (doc == NULL) return;
1727 if (mode < 0) doc->compression = 0;
1728 else if (mode > 9) doc->compression = 9;
1729 else doc->compression = mode;
1730}
1731
Daniel Veillard97b58771998-10-20 06:14:16 +00001732/**
1733 * xmlGetCompressMode:
1734 *
1735 * get the default compression mode used, ZLIB based.
1736 * return values: 0 (uncompressed) to 9 (max compression)
Daniel Veillard15a8df41998-09-24 19:15:06 +00001737 */
Daniel Veillard151b1b01998-09-23 00:49:46 +00001738int xmlGetCompressMode(void) {
1739 return(xmlCompressMode);
1740}
Daniel Veillard97b58771998-10-20 06:14:16 +00001741
1742/**
1743 * xmlSetCompressMode:
1744 * @mode: the compression ratio
1745 *
1746 * set the default compression mode used, ZLIB based
1747 * Correct values: 0 (uncompressed) to 9 (max compression)
1748 */
Daniel Veillard151b1b01998-09-23 00:49:46 +00001749void xmlSetCompressMode(int mode) {
1750 if (mode < 0) xmlCompressMode = 0;
Daniel Veillard15a8df41998-09-24 19:15:06 +00001751 else if (mode > 9) xmlCompressMode = 9;
Daniel Veillard151b1b01998-09-23 00:49:46 +00001752 else xmlCompressMode = mode;
1753}
1754
Daniel Veillard97b58771998-10-20 06:14:16 +00001755/**
1756 * xmlDocDump:
1757 * @f: the FILE*
1758 * @cur: the document
1759 *
1760 * Dump an XML document to an open FILE.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001761 */
Daniel Veillard260a68f1998-08-13 03:39:55 +00001762void xmlDocDump(FILE *f, xmlDocPtr cur) {
1763 if (cur == NULL) {
1764 fprintf(stderr, "xmlDocDump : document == NULL\n");
1765 return;
1766 }
1767 buffer_index = 0;
1768 xmlDocContentDump(cur);
1769
1770 fwrite(buffer, sizeof(CHAR), buffer_index, f);
1771}
1772
Daniel Veillard97b58771998-10-20 06:14:16 +00001773/**
1774 * xmlSaveFile:
1775 * @filename: the filename
1776 * @cur: the document
1777 *
1778 * Dump an XML document to a file. Will use compression if
1779 * compiled in and enabled.
1780 * returns: the number of file written or -1 in case of failure.
Daniel Veillard151b1b01998-09-23 00:49:46 +00001781 */
Daniel Veillard151b1b01998-09-23 00:49:46 +00001782int xmlSaveFile(const char *filename, xmlDocPtr cur) {
1783#ifdef HAVE_ZLIB_H
1784 gzFile zoutput = NULL;
1785 char mode[15];
1786#endif
Daniel Veillardccb09631998-10-27 06:21:04 +00001787 FILE *output = NULL;
Daniel Veillard151b1b01998-09-23 00:49:46 +00001788 int ret;
1789
1790#ifdef HAVE_ZLIB_H
Daniel Veillarddc3dd9d1998-09-24 19:25:54 +00001791 if ((cur->compression > 0) && (cur->compression <= 9)) {
1792 sprintf(mode, "w%d", cur->compression);
Daniel Veillard151b1b01998-09-23 00:49:46 +00001793 zoutput = gzopen(filename, mode);
1794 }
1795 if (zoutput == NULL) {
1796#endif
1797 output = fopen(filename, "w");
1798 if (output == NULL) return(-1);
1799#ifdef HAVE_ZLIB_H
1800 }
1801#endif
1802
1803 /*
1804 * save the content to a temp buffer.
1805 */
1806 buffer_index = 0;
1807 xmlDocContentDump(cur);
1808
1809#ifdef HAVE_ZLIB_H
1810 if (zoutput != NULL) {
1811 ret = gzwrite(zoutput, buffer, sizeof(CHAR) * buffer_index);
1812 gzclose(zoutput);
1813 return(ret);
1814 }
1815#endif
1816 ret = fwrite(buffer, sizeof(CHAR), buffer_index, output);
1817 fclose(output);
1818 return(ret * sizeof(CHAR));
1819}
1820
Daniel Veillard260a68f1998-08-13 03:39:55 +00001821/************************************************************************
1822 * *
1823 * Debug *
1824 * *
1825 ************************************************************************/
1826
1827#ifdef STANDALONE
1828int main(void) {
1829 xmlDocPtr doc;
1830 xmlNodePtr tree, subtree;
1831 xmlNsPtr ns1;
1832 xmlNsPtr ns2;
1833
1834 /*
1835 * build a fake XML document
1836 */
1837 doc = xmlNewDoc("1.0");
1838 ns1 = xmlNewNs(doc, "http://www.ietf.org/standards/dav/", "D");
1839 ns2 = xmlNewNs(doc, "http://www.w3.com/standards/z39.50/", "Z");
Daniel Veillardccb09631998-10-27 06:21:04 +00001840 doc->root = xmlNewDocNode(doc, ns1, "multistatus", NULL);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001841 tree = xmlNewChild(doc->root, NULL, "response", NULL);
1842 subtree = xmlNewChild(tree, NULL, "prop", NULL);
1843 xmlNewChild(subtree, ns2, "Authors", NULL);
1844 subtree = xmlNewChild(tree, NULL, "status", "HTTP/1.1 420 Method Failure");
1845 tree = xmlNewChild(doc->root, NULL, "response", NULL);
1846 subtree = xmlNewChild(tree, NULL, "prop", NULL);
1847 xmlNewChild(subtree, ns2, "Copyright-Owner", NULL);
1848 subtree = xmlNewChild(tree, NULL, "status", "HTTP/1.1 409 Conflict");
1849 tree = xmlNewChild(doc->root, NULL, "responsedescription",
1850 "Copyright Owner can not be deleted or altered");
1851
1852 /*
1853 * print it.
1854 */
1855 xmlDocDump(stdout, doc);
1856
1857 /*
1858 * free it.
1859 */
1860 xmlFreeDoc(doc);
1861 return(0);
1862}
1863#endif