blob: aae8dbe2a0a75d15310ac6d918f036e6c06919a2 [file] [log] [blame]
Daniel Veillard260a68f1998-08-13 03:39:55 +00001/*
2 * tree.c : implemetation of access function for an XML tree.
3 *
4 * See Copyright for the status of this software.
5 *
6 * $Id$
7 *
8 * TODO Cleanup the Dump mechanism.
9 */
10
Daniel Veillard151b1b01998-09-23 00:49:46 +000011#include "config.h"
Daniel Veillard260a68f1998-08-13 03:39:55 +000012#include <stdio.h>
13#include <ctype.h>
Seth Alvese7f12e61998-10-01 20:51:15 +000014#include <stdlib.h>
Daniel Veillard260a68f1998-08-13 03:39:55 +000015#include <string.h> /* for memset() only ! */
16
Daniel Veillard151b1b01998-09-23 00:49:46 +000017#ifdef HAVE_ZLIB_H
18#include <zlib.h>
19#endif
20
Daniel Veillard260a68f1998-08-13 03:39:55 +000021#include "tree.h"
22#include "entities.h"
23
24static CHAR xmlStringText[] = { 't', 'e', 'x', 't', 0 };
25int oldXMLWDcompatibility = 0;
26int xmlIndentTreeOutput = 1;
27
Daniel Veillard15a8df41998-09-24 19:15:06 +000028static int xmlCompressMode = 0;
29
Daniel Veillard260a68f1998-08-13 03:39:55 +000030/************************************************************************
31 * *
32 * Allocation and deallocation of basic structures *
33 * *
34 ************************************************************************/
35
Daniel Veillard97b58771998-10-20 06:14:16 +000036/**
37 * xmlUpgradeOldNs:
38 * @doc: a document pointer
39 *
40 * Upgrade old style Namespaces (PI) and move them to the root of the document.
Daniel Veillard260a68f1998-08-13 03:39:55 +000041 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +000042void
43xmlUpgradeOldNs(xmlDocPtr doc) {
Daniel Veillard260a68f1998-08-13 03:39:55 +000044 xmlNsPtr cur;
45
46 if ((doc == NULL) || (doc->oldNs == NULL)) return;
47 if (doc->root == NULL) {
48 fprintf(stderr, "xmlUpgradeOldNs: failed no root !\n");
49 return;
50 }
51
52 cur = doc->oldNs;
53 while (cur->next != NULL) {
54 cur->type = XML_LOCAL_NAMESPACE;
55 cur = cur->next;
56 }
57 cur->type = XML_LOCAL_NAMESPACE;
58 cur->next = doc->root->nsDef;
59 doc->root->nsDef = doc->oldNs;
60 doc->oldNs = NULL;
61}
62
Daniel Veillard97b58771998-10-20 06:14:16 +000063/**
64 * xmlNewNs:
65 * @node: the element carrying the namespace
66 * @href: the URI associated
67 * @prefix: the prefix for the namespace
68 *
Daniel Veillard260a68f1998-08-13 03:39:55 +000069 * Creation of a new Namespace.
Daniel Veillard97b58771998-10-20 06:14:16 +000070 * return values: returns a new namespace pointer
Daniel Veillard260a68f1998-08-13 03:39:55 +000071 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +000072xmlNsPtr
73xmlNewNs(xmlNodePtr node, const CHAR *href, const CHAR *prefix) {
Daniel Veillard260a68f1998-08-13 03:39:55 +000074 xmlNsPtr cur;
75
76 if (href == NULL) {
77 fprintf(stderr, "xmlNewNs: href == NULL !\n");
78 return(NULL);
79 }
80
81 /*
82 * Allocate a new DTD and fill the fields.
83 */
84 cur = (xmlNsPtr) malloc(sizeof(xmlNs));
85 if (cur == NULL) {
86 fprintf(stderr, "xmlNewNs : malloc failed\n");
87 return(NULL);
88 }
89
90 cur->type = XML_LOCAL_NAMESPACE;
91 if (href != NULL)
92 cur->href = xmlStrdup(href);
93 else
94 cur->href = NULL;
95 if (prefix != NULL)
96 cur->prefix = xmlStrdup(prefix);
97 else
98 cur->prefix = NULL;
99
100 /*
101 * Add it at the end to preserve parsing order ...
102 */
103 cur->next = NULL;
104 if (node != NULL) {
105 if (node->nsDef == NULL) {
106 node->nsDef = cur;
107 } else {
108 xmlNsPtr prev = node->nsDef;
109
110 while (prev->next != NULL) prev = prev->next;
111 prev->next = cur;
112 }
113 }
114
115 return(cur);
116}
117
Daniel Veillard97b58771998-10-20 06:14:16 +0000118/**
119 * xmlNewGlobalNs:
120 * @doc: the document carrying the namespace
121 * @href: the URI associated
122 * @prefix: the prefix for the namespace
123 *
124 * Creation of a Namespace, the old way using PI and without scoping, to AVOID.
125 * return values: returns a new namespace pointer
Daniel Veillard260a68f1998-08-13 03:39:55 +0000126 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000127xmlNsPtr
128xmlNewGlobalNs(xmlDocPtr doc, const CHAR *href, const CHAR *prefix) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000129 xmlNsPtr cur;
130
131 /*
132 * Allocate a new DTD and fill the fields.
133 */
134 cur = (xmlNsPtr) malloc(sizeof(xmlNs));
135 if (cur == NULL) {
136 fprintf(stderr, "xmlNewNs : malloc failed\n");
137 return(NULL);
138 }
139
140 cur->type = XML_GLOBAL_NAMESPACE;
141 if (href != NULL)
142 cur->href = xmlStrdup(href);
143 else
144 cur->href = NULL;
145 if (prefix != NULL)
146 cur->prefix = xmlStrdup(prefix);
147 else
148 cur->prefix = NULL;
149
150 /*
151 * Add it at the end to preserve parsing order ...
152 */
153 cur->next = NULL;
154 if (doc != NULL) {
155 if (doc->oldNs == NULL) {
156 doc->oldNs = cur;
157 } else {
158 xmlNsPtr prev = doc->oldNs;
159
160 while (prev->next != NULL) prev = prev->next;
161 prev->next = cur;
162 }
163 }
164
165 return(cur);
166}
167
Daniel Veillard97b58771998-10-20 06:14:16 +0000168/**
169 * xmlSetNs:
170 * @node: a node in the document
171 * @ns: a namespace pointer
172 *
173 * Associate a namespace to a node, a posteriori.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000174 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000175void
176xmlSetNs(xmlNodePtr node, xmlNsPtr ns) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000177 if (node == NULL) {
178 fprintf(stderr, "xmlSetNs: node == NULL\n");
179 return;
180 }
181 node->ns = ns;
182}
183
Daniel Veillard97b58771998-10-20 06:14:16 +0000184/**
185 * xmlFreeNs:
186 * @cur: the namespace pointer
187 *
188 * Free up the structures associated to a namespace
Daniel Veillard260a68f1998-08-13 03:39:55 +0000189 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000190void
191xmlFreeNs(xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000192 if (cur == NULL) {
193 fprintf(stderr, "xmlFreeNs : ns == NULL\n");
194 return;
195 }
196 if (cur->href != NULL) free((char *) cur->href);
197 if (cur->prefix != NULL) free((char *) cur->prefix);
198 memset(cur, -1, sizeof(xmlNs));
199 free(cur);
200}
201
Daniel Veillard97b58771998-10-20 06:14:16 +0000202/**
203 * xmlFreeNsList:
204 * @cur: the first namespace pointer
205 *
206 * Free up all the structures associated to the chained namespaces.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000207 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000208void
209xmlFreeNsList(xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000210 xmlNsPtr next;
211 if (cur == NULL) {
212 fprintf(stderr, "xmlFreeNsList : ns == NULL\n");
213 return;
214 }
215 while (cur != NULL) {
216 next = cur->next;
217 xmlFreeNs(cur);
218 cur = next;
219 }
220}
221
Daniel Veillard97b58771998-10-20 06:14:16 +0000222/**
223 * xmlNewDtd:
224 * @doc: the document pointer
225 * @name: the DTD name
226 * @ExternalID: the external ID
227 * @SystemID: the system ID
228 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000229 * Creation of a new DTD.
Daniel Veillard97b58771998-10-20 06:14:16 +0000230 * return values: a pointer to the new DTD structure
Daniel Veillard260a68f1998-08-13 03:39:55 +0000231 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000232xmlDtdPtr
233xmlNewDtd(xmlDocPtr doc, const CHAR *name,
Daniel Veillard260a68f1998-08-13 03:39:55 +0000234 const CHAR *ExternalID, const CHAR *SystemID) {
235 xmlDtdPtr cur;
236
237 if (doc->dtd != NULL) {
238 fprintf(stderr, "xmlNewDtd(%s): document %s already have a DTD %s\n",
239 /* !!! */ (char *) name, doc->name, /* !!! */ (char *)doc->dtd->name);
240 }
241
242 /*
243 * Allocate a new DTD and fill the fields.
244 */
245 cur = (xmlDtdPtr) malloc(sizeof(xmlDtd));
246 if (cur == NULL) {
247 fprintf(stderr, "xmlNewNs : malloc failed\n");
248 return(NULL);
249 }
250
251 if (name != NULL)
252 cur->name = xmlStrdup(name);
253 else
254 cur->name = NULL;
255 if (ExternalID != NULL)
256 cur->ExternalID = xmlStrdup(ExternalID);
257 else
258 cur->ExternalID = NULL;
259 if (SystemID != NULL)
260 cur->SystemID = xmlStrdup(SystemID);
261 else
262 cur->SystemID = NULL;
263 cur->elements = NULL;
264 cur->entities = NULL;
265 doc->dtd = cur;
266
267 return(cur);
268}
269
Daniel Veillard97b58771998-10-20 06:14:16 +0000270/**
271 * xmlFreeDtd:
272 * @cur: the DTD structure to free up
273 *
274 * Free a DTD structure.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000275 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000276void
277xmlFreeDtd(xmlDtdPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000278 if (cur == NULL) {
279 fprintf(stderr, "xmlFreeDtd : DTD == NULL\n");
280 return;
281 }
282 if (cur->name != NULL) free((char *) cur->name);
283 if (cur->SystemID != NULL) free((char *) cur->SystemID);
284 if (cur->ExternalID != NULL) free((char *) cur->ExternalID);
285 if (cur->elements != NULL)
286 fprintf(stderr, "xmlFreeDtd: cur->elements != NULL !!! \n");
287 if (cur->entities != NULL)
288 xmlFreeEntitiesTable((xmlEntitiesTablePtr) cur->entities);
289 memset(cur, -1, sizeof(xmlDtd));
290 free(cur);
291}
292
Daniel Veillard97b58771998-10-20 06:14:16 +0000293/**
294 * xmlNewDoc:
295 * @version: CHAR string giving the version of XML "1.0"
296 *
297 * Create a new document
Daniel Veillard260a68f1998-08-13 03:39:55 +0000298 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000299xmlDocPtr
300xmlNewDoc(const CHAR *version) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000301 xmlDocPtr cur;
302
303 if (version == NULL) {
304 fprintf(stderr, "xmlNewDoc : version == NULL\n");
305 return(NULL);
306 }
307
308 /*
309 * Allocate a new document and fill the fields.
310 */
311 cur = (xmlDocPtr) malloc(sizeof(xmlDoc));
312 if (cur == NULL) {
313 fprintf(stderr, "xmlNewDoc : malloc failed\n");
314 return(NULL);
315 }
316
Daniel Veillard33942841998-10-18 19:12:41 +0000317 cur->type = XML_DOCUMENT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000318 cur->version = xmlStrdup(version);
319 cur->name = NULL;
320 cur->root = NULL;
321 cur->dtd = NULL;
322 cur->oldNs = NULL;
323 cur->encoding = NULL;
324 cur->entities = NULL;
325 cur->standalone = -1;
Daniel Veillard15a8df41998-09-24 19:15:06 +0000326 cur->compression = xmlCompressMode;
Daniel Veillard27fb0751998-10-17 06:47:46 +0000327#ifndef WITHOUT_CORBA
328 cur->_private = NULL;
329 cur->vepv = NULL;
330#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000331 return(cur);
332}
333
Daniel Veillard97b58771998-10-20 06:14:16 +0000334/**
335 * xmlFreeDoc:
336 * @cur: pointer to the document
337 * @:
338 *
339 * Free up all the structures used by a document, tree included.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000340 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000341void
342xmlFreeDoc(xmlDocPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000343 if (cur == NULL) {
344 fprintf(stderr, "xmlFreeDoc : document == NULL\n");
345 return;
346 }
347 free((char *) cur->version);
348 if (cur->name != NULL) free((char *) cur->name);
349 if (cur->encoding != NULL) free((char *) cur->encoding);
350 if (cur->root != NULL) xmlFreeNode(cur->root);
351 if (cur->dtd != NULL) xmlFreeDtd(cur->dtd);
352 if (cur->entities != NULL)
353 xmlFreeEntitiesTable((xmlEntitiesTablePtr) cur->entities);
354 memset(cur, -1, sizeof(xmlDoc));
355 free(cur);
356}
357
Daniel Veillard97b58771998-10-20 06:14:16 +0000358/**
Daniel Veillard16253641998-10-28 22:58:05 +0000359 * xmlStringLenGetNodeList:
360 * @doc: the document
361 * @value: the value of the text
362 * @int len: the length of the string value
363 *
364 * Parse the value string and build the node list associated. Should
365 * produce a flat tree with only TEXTs and ENTITY_REFs.
366 * return values: a pointer to the first child
367 */
368xmlNodePtr
369xmlStringLenGetNodeList(xmlDocPtr doc, const CHAR *value, int len) {
370 xmlNodePtr ret = NULL, last = NULL;
371 xmlNodePtr node;
372 CHAR *val;
373 const CHAR *cur = value;
374 const CHAR *q;
375
376 if (value == NULL) return(NULL);
377
378 q = cur;
379 while ((*cur != 0) && (cur - value < len)) {
380 if (*cur == '&') {
381 if (cur != q) {
382 node = xmlNewDocTextLen(doc, q, cur - q);
383 if (node == NULL) return(ret);
384 if (last == NULL)
385 last = ret = node;
386 else {
387 last->next = node;
388 last = node;
389 }
390 }
391 cur++;
392 q = cur;
393 while ((*cur != 0) && (cur - value < len) && (*cur != ';')) cur++;
394 if ((*cur == 0) || (cur - value >= len)) {
395 fprintf(stderr,
396 "xmlStringGetNodeList: unterminated entity %30s\n", q);
397 return(ret);
398 }
399 if (cur != q) {
400 val = xmlStrndup(q, cur - q);
401 node = xmlNewReference(doc, val);
402 if (node == NULL) return(ret);
403 if (last == NULL)
404 last = ret = node;
405 else {
406 last->next = node;
407 last = node;
408 }
409 free(val);
410 }
411 cur++;
412 q = cur;
413 } else
414 cur++;
415 }
416 if (cur != q) {
417 node = xmlNewDocTextLen(doc, q, cur - q);
418 if (node == NULL) return(ret);
419 if (last == NULL)
420 last = ret = node;
421 else {
422 last->next = node;
423 last = node;
424 }
425 }
426 return(ret);
427}
428
429/**
Daniel Veillardccb09631998-10-27 06:21:04 +0000430 * xmlStringGetNodeList:
431 * @doc: the document
432 * @value: the value of the attribute
433 *
434 * Parse the value string and build the node list associated. Should
435 * produce a flat tree with only TEXTs and ENTITY_REFs.
436 * return values: a pointer to the first child
437 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000438xmlNodePtr
439xmlStringGetNodeList(xmlDocPtr doc, const CHAR *value) {
Daniel Veillardccb09631998-10-27 06:21:04 +0000440 xmlNodePtr ret = NULL, last = NULL;
441 xmlNodePtr node;
442 CHAR *val;
443 const CHAR *cur = value;
444 const CHAR *q;
445
446 if (value == NULL) return(NULL);
447
448 q = cur;
449 while (*cur != 0) {
450 if (*cur == '&') {
451 if (cur != q) {
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000452 node = xmlNewDocTextLen(doc, q, cur - q);
Daniel Veillardccb09631998-10-27 06:21:04 +0000453 if (node == NULL) return(ret);
454 if (last == NULL)
455 last = ret = node;
456 else {
457 last->next = node;
458 last = node;
459 }
460 }
461 cur++;
462 q = cur;
463 while ((*cur != 0) && (*cur != ';')) cur++;
464 if (*cur == 0) {
465 fprintf(stderr,
466 "xmlStringGetNodeList: unterminated entity %30s\n", q);
467 return(ret);
468 }
469 if (cur != q) {
470 val = xmlStrndup(q, cur - q);
471 node = xmlNewReference(doc, val);
472 if (node == NULL) return(ret);
473 if (last == NULL)
474 last = ret = node;
475 else {
476 last->next = node;
477 last = node;
478 }
479 free(val);
480 }
481 cur++;
482 q = cur;
483 } else
484 cur++;
485 }
486 if (cur != q) {
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000487 node = xmlNewDocTextLen(doc, q, cur - q);
Daniel Veillardccb09631998-10-27 06:21:04 +0000488 if (node == NULL) return(ret);
489 if (last == NULL)
490 last = ret = node;
491 else {
492 last->next = node;
493 last = node;
494 }
495 }
496 return(ret);
497}
498
499/**
500 * xmlNodeListGetString:
501 * @doc: the document
502 * @list: a Node list
503 * @inLine: should we replace entity contents or show their external form
504 *
505 * Returns the string equivalent to the text contained in the Node list
506 * made of TEXTs and ENTITY_REFs
507 * return values: a pointer to the string copy, the calller must free it.
508 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000509CHAR *
510xmlNodeListGetString(xmlDocPtr doc, xmlNodePtr list, int inLine) {
Daniel Veillardccb09631998-10-27 06:21:04 +0000511 xmlNodePtr node = list;
512 CHAR *ret = NULL;
513 xmlEntityPtr ent;
514
515 if (list == NULL) return(NULL);
516
517 while (node != NULL) {
518 if (node->type == XML_TEXT_NODE) {
519 if (inLine)
520 ret = xmlStrcat(ret, node->content);
521 else
522 ret = xmlStrcat(ret, xmlEncodeEntities(doc, node->content));
523 } else if (node->type == XML_ENTITY_REF_NODE) {
524 if (inLine) {
525 ent = xmlGetDocEntity(doc, node->name);
526 if (ent != NULL)
527 ret = xmlStrcat(ret, ent->content);
528 else
529 ret = xmlStrcat(ret, node->content);
530 } else {
531 CHAR buf[2];
532 buf[0] = '&'; buf[1] = 0;
533 ret = xmlStrncat(ret, buf, 1);
534 ret = xmlStrcat(ret, node->name);
535 buf[0] = ';'; buf[1] = 0;
536 ret = xmlStrncat(ret, buf, 1);
537 }
538 }
539#if 0
540 else {
541 fprintf(stderr, "xmlGetNodeListString : invalide node type %d\n",
542 node->type);
543 }
544#endif
545 node = node->next;
546 }
547 return(ret);
548}
549
550/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000551 * xmlNewProp:
552 * @node: the holding node
553 * @name: the name of the attribute
554 * @value: the value of the attribute
555 *
556 * Create a new property carried by a node.
557 * return values: a pointer to the attribute
Daniel Veillard260a68f1998-08-13 03:39:55 +0000558 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000559xmlAttrPtr
560xmlNewProp(xmlNodePtr node, const CHAR *name, const CHAR *value) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000561 xmlAttrPtr cur;
562
563 if (name == NULL) {
564 fprintf(stderr, "xmlNewProp : name == NULL\n");
565 return(NULL);
566 }
567
568 /*
569 * Allocate a new property and fill the fields.
570 */
571 cur = (xmlAttrPtr) malloc(sizeof(xmlAttr));
572 if (cur == NULL) {
573 fprintf(stderr, "xmlNewProp : malloc failed\n");
574 return(NULL);
575 }
576
Daniel Veillard33942841998-10-18 19:12:41 +0000577 cur->type = XML_ATTRIBUTE_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000578 cur->node = node;
579 cur->name = xmlStrdup(name);
580 if (value != NULL)
Daniel Veillardccb09631998-10-27 06:21:04 +0000581 cur->val = xmlStringGetNodeList(node->doc, value);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000582 else
Daniel Veillardccb09631998-10-27 06:21:04 +0000583 cur->val = NULL;
Daniel Veillard27fb0751998-10-17 06:47:46 +0000584#ifndef WITHOUT_CORBA
585 cur->_private = NULL;
586 cur->vepv = NULL;
587#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000588
589 /*
590 * Add it at the end to preserve parsing order ...
591 */
592 cur->next = NULL;
593 if (node != NULL) {
594 if (node->properties == NULL) {
595 node->properties = cur;
596 } else {
597 xmlAttrPtr prev = node->properties;
598
599 while (prev->next != NULL) prev = prev->next;
600 prev->next = cur;
601 }
602 }
603 return(cur);
604}
605
Daniel Veillard97b58771998-10-20 06:14:16 +0000606/**
Daniel Veillardccb09631998-10-27 06:21:04 +0000607 * xmlNewDocProp:
608 * @doc: the document
609 * @name: the name of the attribute
610 * @value: the value of the attribute
611 *
612 * Create a new property carried by a document.
613 * return values: a pointer to the attribute
614 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000615xmlAttrPtr
616xmlNewDocProp(xmlDocPtr doc, const CHAR *name, const CHAR *value) {
Daniel Veillardccb09631998-10-27 06:21:04 +0000617 xmlAttrPtr cur;
618
619 if (name == NULL) {
620 fprintf(stderr, "xmlNewProp : name == NULL\n");
621 return(NULL);
622 }
623
624 /*
625 * Allocate a new property and fill the fields.
626 */
627 cur = (xmlAttrPtr) malloc(sizeof(xmlAttr));
628 if (cur == NULL) {
629 fprintf(stderr, "xmlNewProp : malloc failed\n");
630 return(NULL);
631 }
632
633 cur->type = XML_ATTRIBUTE_NODE;
634 cur->node = NULL;
635 cur->name = xmlStrdup(name);
636 if (value != NULL)
637 cur->val = xmlStringGetNodeList(doc, value);
638 else
639 cur->val = NULL;
640#ifndef WITHOUT_CORBA
641 cur->_private = NULL;
642 cur->vepv = NULL;
643#endif
644
645 cur->next = NULL;
646 return(cur);
647}
648
649/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000650 * xmlFreePropList:
651 * @cur: the first property in the list
652 *
653 * Free a property and all its siblings, all the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000654 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000655void
656xmlFreePropList(xmlAttrPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000657 xmlAttrPtr next;
658 if (cur == NULL) {
659 fprintf(stderr, "xmlFreePropList : property == NULL\n");
660 return;
661 }
662 while (cur != NULL) {
663 next = cur->next;
664 xmlFreeProp(cur);
665 cur = next;
666 }
667}
668
Daniel Veillard97b58771998-10-20 06:14:16 +0000669/**
670 * xmlFreeProp:
671 * @cur: the first property in the list
672 *
673 * Free one property, all the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000674 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000675void
676xmlFreeProp(xmlAttrPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000677 if (cur == NULL) {
678 fprintf(stderr, "xmlFreeProp : property == NULL\n");
679 return;
680 }
681 if (cur->name != NULL) free((char *) cur->name);
Daniel Veillardccb09631998-10-27 06:21:04 +0000682 if (cur->val != NULL) xmlFreeNodeList(cur->val);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000683 memset(cur, -1, sizeof(xmlAttr));
684 free(cur);
685}
686
Daniel Veillard97b58771998-10-20 06:14:16 +0000687/**
688 * xmlNewNode:
689 * @ns: namespace if any
690 * @name: the node name
691 * @content: the text content if any
692 *
693 * Creation of a new node element. @ns and @content are optionnal (NULL).
Daniel Veillardccb09631998-10-27 06:21:04 +0000694 * If content is non NULL, a child list containing the TEXTs and
695 * ENTITY_REFs node will be created.
Daniel Veillard97b58771998-10-20 06:14:16 +0000696 * return values: a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000697 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000698xmlNodePtr
699xmlNewNode(xmlNsPtr ns, const CHAR *name) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000700 xmlNodePtr cur;
701
702 if (name == NULL) {
703 fprintf(stderr, "xmlNewNode : name == NULL\n");
704 return(NULL);
705 }
706
707 /*
708 * Allocate a new node and fill the fields.
709 */
710 cur = (xmlNodePtr) malloc(sizeof(xmlNode));
711 if (cur == NULL) {
712 fprintf(stderr, "xmlNewNode : malloc failed\n");
713 return(NULL);
714 }
715
Daniel Veillard33942841998-10-18 19:12:41 +0000716 cur->type = XML_ELEMENT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000717 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000718 cur->parent = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000719 cur->next = NULL;
720 cur->prev = NULL;
721 cur->childs = NULL;
722 cur->properties = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000723 cur->name = xmlStrdup(name);
724 cur->ns = ns;
725 cur->nsDef = NULL;
Daniel Veillardccb09631998-10-27 06:21:04 +0000726 cur->content = NULL;
Daniel Veillard27fb0751998-10-17 06:47:46 +0000727#ifndef WITHOUT_CORBA
728 cur->_private = NULL;
729 cur->vepv = NULL;
730#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000731 return(cur);
732}
733
Daniel Veillard97b58771998-10-20 06:14:16 +0000734/**
735 * xmlNewDocNode:
736 * @doc: the document
737 * @ns: namespace if any
738 * @name: the node name
739 * @content: the text content if any
740 *
741 * Creation of a new node element within a document. @ns and @content
742 * are optionnal (NULL).
743 * return values: a pointer to the new node object.
744 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000745xmlNodePtr
746xmlNewDocNode(xmlDocPtr doc, xmlNsPtr ns,
Daniel Veillard0bef1311998-10-14 02:36:47 +0000747 const CHAR *name, CHAR *content) {
748 xmlNodePtr cur;
749
Daniel Veillardccb09631998-10-27 06:21:04 +0000750 cur = xmlNewNode(ns, name);
751 if (cur != NULL) {
752 cur->doc = doc;
753 if (content != NULL)
754 cur->childs = xmlStringGetNodeList(doc, content);
755 }
Daniel Veillard0bef1311998-10-14 02:36:47 +0000756 return(cur);
757}
758
759
Daniel Veillard97b58771998-10-20 06:14:16 +0000760/**
761 * xmlNewText:
762 * @content: the text content
763 *
764 * Creation of a new text node.
765 * return values: a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000766 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000767xmlNodePtr
768xmlNewText(const CHAR *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000769 xmlNodePtr cur;
770
771 /*
772 * Allocate a new node and fill the fields.
773 */
774 cur = (xmlNodePtr) malloc(sizeof(xmlNode));
775 if (cur == NULL) {
776 fprintf(stderr, "xmlNewText : malloc failed\n");
777 return(NULL);
778 }
779
Daniel Veillard33942841998-10-18 19:12:41 +0000780 cur->type = XML_TEXT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000781 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000782 cur->parent = NULL;
783 cur->next = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000784 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000785 cur->childs = NULL;
786 cur->properties = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000787 cur->type = XML_TEXT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000788 cur->name = xmlStrdup(xmlStringText);
789 cur->ns = NULL;
790 cur->nsDef = NULL;
791 if (content != NULL)
792 cur->content = xmlStrdup(content);
793 else
794 cur->content = NULL;
795 return(cur);
796}
797
Daniel Veillard97b58771998-10-20 06:14:16 +0000798/**
Daniel Veillardccb09631998-10-27 06:21:04 +0000799 * xmlNewReference:
800 * @doc: the document
801 * @name: the reference name, or the reference string with & and ;
802 *
803 * Creation of a new reference node.
804 * return values: a pointer to the new node object.
805 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000806xmlNodePtr
807xmlNewReference(xmlDocPtr doc, const CHAR *name) {
Daniel Veillardccb09631998-10-27 06:21:04 +0000808 xmlNodePtr cur;
809 xmlEntityPtr ent;
810
811 /*
812 * Allocate a new node and fill the fields.
813 */
814 cur = (xmlNodePtr) malloc(sizeof(xmlNode));
815 if (cur == NULL) {
816 fprintf(stderr, "xmlNewText : malloc failed\n");
817 return(NULL);
818 }
819
820 cur->type = XML_ENTITY_REF_NODE;
Daniel Veillard10c6a8f1998-10-28 01:00:12 +0000821 cur->doc = doc;
Daniel Veillardccb09631998-10-27 06:21:04 +0000822 cur->parent = NULL;
823 cur->next = NULL;
824 cur->prev = NULL;
825 cur->childs = NULL;
826 cur->properties = NULL;
827 if (name[0] == '&') {
828 int len;
829 name++;
830 len = xmlStrlen(name);
831 if (name[len - 1] == ';')
832 cur->name = xmlStrndup(name, len - 1);
833 else
834 cur->name = xmlStrndup(name, len);
835 } else
836 cur->name = xmlStrdup(name);
837 cur->ns = NULL;
838 cur->nsDef = NULL;
839
840 ent = xmlGetDocEntity(doc, cur->name);
841 if (ent != NULL)
842 cur->content = ent->content;
843 else
844 cur->content = NULL;
845 return(cur);
846}
847
848/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000849 * xmlNewDocText:
850 * @doc: the document
851 * @content: the text content
852 *
853 * Creation of a new text node within a document.
854 * return values: a pointer to the new node object.
855 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000856xmlNodePtr
857xmlNewDocText(xmlDocPtr doc, const CHAR *content) {
Daniel Veillard0bef1311998-10-14 02:36:47 +0000858 xmlNodePtr cur;
859
860 cur = xmlNewText(content);
861 if (cur != NULL) cur->doc = doc;
862 return(cur);
863}
864
Daniel Veillard97b58771998-10-20 06:14:16 +0000865/**
Daniel Veillardccb09631998-10-27 06:21:04 +0000866 * xmlNewTextLen:
Daniel Veillard97b58771998-10-20 06:14:16 +0000867 * @content: the text content
868 * @len: the text len.
869 *
870 * Creation of a new text node with an extra parameter for the content's lenght
871 * return values: a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000872 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000873xmlNodePtr
874xmlNewTextLen(const CHAR *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000875 xmlNodePtr cur;
876
877 /*
878 * Allocate a new node and fill the fields.
879 */
880 cur = (xmlNodePtr) malloc(sizeof(xmlNode));
881 if (cur == NULL) {
882 fprintf(stderr, "xmlNewText : malloc failed\n");
883 return(NULL);
884 }
885
Daniel Veillard33942841998-10-18 19:12:41 +0000886 cur->type = XML_TEXT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000887 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000888 cur->parent = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000889 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000890 cur->next = NULL;
891 cur->childs = NULL;
892 cur->properties = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000893 cur->type = XML_TEXT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000894 cur->name = xmlStrdup(xmlStringText);
895 cur->ns = NULL;
896 cur->nsDef = NULL;
897 if (content != NULL)
898 cur->content = xmlStrndup(content, len);
899 else
900 cur->content = NULL;
901 return(cur);
902}
903
Daniel Veillard97b58771998-10-20 06:14:16 +0000904/**
905 * xmlNewDocTextLen:
906 * @doc: the document
907 * @content: the text content
908 * @len: the text len.
909 *
910 * Creation of a new text node with an extra content lenght parameter. The
911 * text node pertain to a given document.
912 * return values: a pointer to the new node object.
913 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000914xmlNodePtr
915xmlNewDocTextLen(xmlDocPtr doc, const CHAR *content, int len) {
Daniel Veillard0bef1311998-10-14 02:36:47 +0000916 xmlNodePtr cur;
917
918 cur = xmlNewTextLen(content, len);
919 if (cur != NULL) cur->doc = doc;
920 return(cur);
921}
922
Daniel Veillard97b58771998-10-20 06:14:16 +0000923/**
924 * xmlNewComment:
925 * @content: the comment content
926 *
927 * Creation of a new node containing a comment.
928 * return values: a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000929 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000930xmlNodePtr
931xmlNewComment(CHAR *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000932 xmlNodePtr cur;
933
934 /*
935 * Allocate a new node and fill the fields.
936 */
937 cur = (xmlNodePtr) malloc(sizeof(xmlNode));
938 if (cur == NULL) {
939 fprintf(stderr, "xmlNewComment : malloc failed\n");
940 return(NULL);
941 }
942
Daniel Veillard33942841998-10-18 19:12:41 +0000943 cur->type = XML_COMMENT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000944 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000945 cur->parent = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000946 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000947 cur->next = NULL;
948 cur->childs = NULL;
949 cur->properties = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000950 cur->type = XML_COMMENT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000951 cur->name = xmlStrdup(xmlStringText);
952 cur->ns = NULL;
953 cur->nsDef = NULL;
954 if (content != NULL)
955 cur->content = xmlStrdup(content);
956 else
957 cur->content = NULL;
958 return(cur);
959}
960
Daniel Veillard97b58771998-10-20 06:14:16 +0000961/**
962 * xmlNewComment:
963 * @doc: the document
964 * @content: the comment content
965 *
966 * Creation of a new node containing a commentwithin a document.
967 * return values: a pointer to the new node object.
968 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000969xmlNodePtr
970xmlNewDocComment(xmlDocPtr doc, CHAR *content) {
Daniel Veillard0bef1311998-10-14 02:36:47 +0000971 xmlNodePtr cur;
972
973 cur = xmlNewComment(content);
974 if (cur != NULL) cur->doc = doc;
975 return(cur);
976}
977
Daniel Veillard97b58771998-10-20 06:14:16 +0000978/**
979 * xmlNewChild:
980 * @parent: the parent node
981 * @ns: a namespace if any
982 * @name: the name of the child
983 * @content: the content of the child if any.
984 *
985 *
986 * Creation of a new child element, added at the end of @parent childs list.
Daniel Veillardccb09631998-10-27 06:21:04 +0000987 * @ns and @content parameters are optionnal (NULL). If content is non NULL,
988 * a child list containing the TEXTs and ENTITY_REFs node will be created.
Daniel Veillard97b58771998-10-20 06:14:16 +0000989 * return values: a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000990 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000991xmlNodePtr
992xmlNewChild(xmlNodePtr parent, xmlNsPtr ns,
Daniel Veillard260a68f1998-08-13 03:39:55 +0000993 const CHAR *name, CHAR *content) {
994 xmlNodePtr cur, prev;
995
996 if (parent == NULL) {
997 fprintf(stderr, "xmlNewChild : parent == NULL\n");
998 return(NULL);
999 }
1000
1001 if (name == NULL) {
1002 fprintf(stderr, "xmlNewChild : name == NULL\n");
1003 return(NULL);
1004 }
1005
1006 /*
1007 * Allocate a new node
1008 */
1009 if (ns == NULL)
Daniel Veillardccb09631998-10-27 06:21:04 +00001010 cur = xmlNewDocNode(parent->doc, parent->ns, name, content);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001011 else
Daniel Veillardccb09631998-10-27 06:21:04 +00001012 cur = xmlNewDocNode(parent->doc, ns, name, content);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001013 if (cur == NULL) return(NULL);
1014
1015 /*
1016 * add the new element at the end of the childs list.
1017 */
Daniel Veillardccb09631998-10-27 06:21:04 +00001018 cur->type = XML_ELEMENT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001019 cur->parent = parent;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001020 cur->doc = parent->doc;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001021 if (parent->childs == NULL) {
1022 parent->childs = cur;
1023 } else {
1024 prev = parent->childs;
1025 while (prev->next != NULL) prev = prev->next;
1026 prev->next = cur;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001027 cur->prev = prev;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001028 }
1029
1030 return(cur);
1031}
1032
Daniel Veillard97b58771998-10-20 06:14:16 +00001033/**
1034 * xmlAddChild:
1035 * @parent: the parent node
1036 * @cur: the child node
1037 *
1038 * Add a new child element, to @parent, at the end of the child list.
1039 * return values: the child or NULL in case of error.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001040 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001041xmlNodePtr
1042xmlAddChild(xmlNodePtr parent, xmlNodePtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001043 xmlNodePtr prev;
1044
1045 if (parent == NULL) {
1046 fprintf(stderr, "xmladdChild : parent == NULL\n");
1047 return(NULL);
1048 }
1049
1050 if (cur == NULL) {
1051 fprintf(stderr, "xmladdChild : child == NULL\n");
1052 return(NULL);
1053 }
1054
Daniel Veillard0bef1311998-10-14 02:36:47 +00001055 if ((cur->doc != NULL) && (parent->doc != NULL) &&
1056 (cur->doc != parent->doc)) {
1057 fprintf(stderr, "Elements moved to a different document\n");
1058 }
1059
Daniel Veillard260a68f1998-08-13 03:39:55 +00001060 /*
1061 * add the new element at the end of the childs list.
1062 */
1063 cur->parent = parent;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001064 cur->doc = parent->doc; /* the parent may not be linked to a doc ! */
Daniel Veillardccb09631998-10-27 06:21:04 +00001065 /*
1066 * Handle the case where parent->content != NULL, in that case it will
1067 * create a intermediate TEXT node.
1068 */
1069 if (parent->content != NULL) {
1070 xmlNodePtr text;
1071
1072 text = xmlNewDocText(parent->doc, parent->content);
1073 if (text != NULL) {
1074 text->next = parent->childs;
1075 if (text->next != NULL)
1076 text->next->prev = text;
1077 parent->childs = text;
1078 free(parent->content);
1079 parent->content = NULL;
1080 }
1081 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00001082 if (parent->childs == NULL) {
1083 parent->childs = cur;
1084 } else {
1085 prev = parent->childs;
1086 while (prev->next != NULL) prev = prev->next;
1087 prev->next = cur;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001088 cur->prev = prev;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001089 }
1090
1091 return(cur);
1092}
1093
Daniel Veillard97b58771998-10-20 06:14:16 +00001094/**
1095 * xmlGetLastChild:
1096 * @parent: the parent node
1097 *
1098 * Search the last child of a node.
1099 * return values: the last child or NULL if none.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001100 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001101xmlNodePtr
1102xmlGetLastChild(xmlNodePtr parent) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001103 xmlNodePtr last;
1104
1105 if (parent == NULL) {
1106 fprintf(stderr, "xmlGetLastChild : parent == NULL\n");
1107 return(NULL);
1108 }
1109
1110 /*
1111 * add the new element at the end of the childs list.
1112 */
1113 if (parent->childs == NULL) {
1114 return(NULL);
1115 } else {
1116 last = parent->childs;
1117 while (last->next != NULL) last = last->next;
1118 }
1119 return(last);
1120}
1121
Daniel Veillard97b58771998-10-20 06:14:16 +00001122/**
1123 * xmlFreeNodeList:
1124 * @cur: the first node in the list
1125 *
1126 * Free a node and all its siblings, this is a recursive behaviour, all
1127 * the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001128 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001129void
1130xmlFreeNodeList(xmlNodePtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001131 xmlNodePtr next;
1132 if (cur == NULL) {
1133 fprintf(stderr, "xmlFreeNodeList : node == NULL\n");
1134 return;
1135 }
1136 while (cur != NULL) {
1137 next = cur->next;
1138 xmlFreeNode(cur);
1139 cur = next;
1140 }
1141}
1142
Daniel Veillard97b58771998-10-20 06:14:16 +00001143/**
1144 * xmlFreeNode:
1145 * @cur: the node
1146 *
1147 * Free a node, this is a recursive behaviour, all the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001148 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001149void
1150xmlFreeNode(xmlNodePtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001151 if (cur == NULL) {
1152 fprintf(stderr, "xmlFreeNode : node == NULL\n");
1153 return;
1154 }
Daniel Veillardccb09631998-10-27 06:21:04 +00001155 cur->doc = NULL;
1156 cur->parent = NULL;
1157 cur->next = NULL;
1158 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001159 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillardccb09631998-10-27 06:21:04 +00001160 if (cur->properties != NULL) xmlFreePropList(cur->properties);
1161 if (cur->type != XML_ENTITY_REF_NODE)
1162 if (cur->content != NULL) free(cur->content);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001163 if (cur->name != NULL) free((char *) cur->name);
1164 if (cur->nsDef != NULL) xmlFreeNsList(cur->nsDef);
1165 memset(cur, -1, sizeof(xmlNode));
1166 free(cur);
1167}
1168
Daniel Veillard16253641998-10-28 22:58:05 +00001169/**
1170 * xmlUnlinkNode:
1171 * @cur: the node
1172 *
1173 * Unlink a node from it's current context, the node is not freed
1174 */
1175void
1176xmlUnlinkNode(xmlNodePtr cur) {
1177 if (cur == NULL) {
1178 fprintf(stderr, "xmlUnlinkNode : node == NULL\n");
1179 return;
1180 }
1181 if ((cur->parent != NULL) && (cur->parent->childs == cur))
1182 cur->parent->childs = cur->next;
1183 if (cur->next != NULL)
1184 cur->next->prev = cur->prev;
1185 if (cur->prev != NULL)
1186 cur->prev->next = cur->next;
1187 cur->next = cur->prev = NULL;
1188 cur->parent = NULL;
1189}
1190
Daniel Veillard260a68f1998-08-13 03:39:55 +00001191/************************************************************************
1192 * *
1193 * Content access functions *
1194 * *
1195 ************************************************************************/
1196
Daniel Veillard97b58771998-10-20 06:14:16 +00001197/**
Daniel Veillard16253641998-10-28 22:58:05 +00001198 * xmlNodeGetContent:
1199 * @cur: the node being read
1200 *
1201 * Read the value of a node, this can be either the text carried
1202 * directly by this node if it's a TEXT node or the aggregate string
1203 * of the values carried by this node child's (TEXT and ENTITY_REF).
1204 * Entity references are substitued.
1205 * Return value: a new CHAR * or NULL if no content is available.
1206 */
1207CHAR *
1208xmlNodeGetContent(xmlNodePtr cur) {
1209 if (cur == NULL) return(NULL);
1210 switch (cur->type) {
1211 case XML_DOCUMENT_FRAG_NODE:
1212 case XML_ELEMENT_NODE:
1213 return(xmlNodeListGetString(cur->doc, cur->childs, 1));
1214 break;
1215 case XML_ATTRIBUTE_NODE:
1216 case XML_CDATA_SECTION_NODE:
1217 case XML_ENTITY_REF_NODE:
1218 case XML_ENTITY_NODE:
1219 case XML_PI_NODE:
1220 case XML_COMMENT_NODE:
1221 case XML_DOCUMENT_NODE:
1222 case XML_DOCUMENT_TYPE_NODE:
1223 case XML_NOTATION_NODE:
1224 return(NULL);
1225 case XML_TEXT_NODE:
1226 if (cur->content != NULL)
1227 return(xmlStrdup(cur->content));
1228 return(NULL);
1229 }
1230 return(NULL);
1231}
1232
1233/**
Daniel Veillard97b58771998-10-20 06:14:16 +00001234 * xmlNodeSetContent:
1235 * @cur: the node being modified
1236 * @content: the new value of the content
1237 *
1238 * Replace the content of a node.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001239 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001240void
1241xmlNodeSetContent(xmlNodePtr cur, const CHAR *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001242 if (cur == NULL) {
1243 fprintf(stderr, "xmlNodeSetContent : node == NULL\n");
1244 return;
1245 }
Daniel Veillard16253641998-10-28 22:58:05 +00001246 switch (cur->type) {
1247 case XML_DOCUMENT_FRAG_NODE:
1248 case XML_ELEMENT_NODE:
1249 if (cur->content != NULL) {
1250 free(cur->content);
1251 cur->content = NULL;
1252 }
1253 if (cur->childs != NULL) xmlFreeNode(cur->childs);
1254 cur->childs = xmlStringGetNodeList(cur->doc, content);
1255 break;
1256 case XML_ATTRIBUTE_NODE:
1257 break;
1258 case XML_TEXT_NODE:
1259 case XML_CDATA_SECTION_NODE:
1260 case XML_ENTITY_REF_NODE:
1261 case XML_ENTITY_NODE:
1262 case XML_PI_NODE:
1263 case XML_COMMENT_NODE:
1264 if (cur->content != NULL) free(cur->content);
1265 if (cur->childs != NULL) xmlFreeNode(cur->childs);
1266 if (content != NULL)
1267 cur->content = xmlStrdup(content);
1268 else
1269 cur->content = NULL;
1270 case XML_DOCUMENT_NODE:
1271 case XML_DOCUMENT_TYPE_NODE:
1272 break;
1273 case XML_NOTATION_NODE:
1274 break;
1275 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00001276}
1277
Daniel Veillard97b58771998-10-20 06:14:16 +00001278/**
1279 * xmlNodeSetContentLen:
1280 * @cur: the node being modified
1281 * @content: the new value of the content
1282 * @len: the size of @content
1283 *
1284 * Replace the content of a node.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001285 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001286void
1287xmlNodeSetContentLen(xmlNodePtr cur, const CHAR *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001288 if (cur == NULL) {
Daniel Veillard16253641998-10-28 22:58:05 +00001289 fprintf(stderr, "xmlNodeSetContentLen : node == NULL\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00001290 return;
1291 }
Daniel Veillard16253641998-10-28 22:58:05 +00001292 switch (cur->type) {
1293 case XML_DOCUMENT_FRAG_NODE:
1294 case XML_ELEMENT_NODE:
1295 if (cur->content != NULL) {
1296 free(cur->content);
1297 cur->content = NULL;
1298 }
1299 if (cur->childs != NULL) xmlFreeNode(cur->childs);
1300 cur->childs = xmlStringLenGetNodeList(cur->doc, content, len);
1301 break;
1302 case XML_ATTRIBUTE_NODE:
1303 break;
1304 case XML_TEXT_NODE:
1305 case XML_CDATA_SECTION_NODE:
1306 case XML_ENTITY_REF_NODE:
1307 case XML_ENTITY_NODE:
1308 case XML_PI_NODE:
1309 case XML_COMMENT_NODE:
1310 if (cur->content != NULL) free(cur->content);
1311 if (cur->childs != NULL) xmlFreeNode(cur->childs);
1312 if (content != NULL)
1313 cur->content = xmlStrndup(content, len);
1314 else
1315 cur->content = NULL;
1316 case XML_DOCUMENT_NODE:
1317 case XML_DOCUMENT_TYPE_NODE:
1318 break;
1319 case XML_NOTATION_NODE:
1320 if (cur->content != NULL) free(cur->content);
1321 if (content != NULL)
1322 cur->content = xmlStrndup(content, len);
1323 else
1324 cur->content = NULL;
1325 break;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001326 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00001327}
1328
Daniel Veillard97b58771998-10-20 06:14:16 +00001329/**
1330 * xmlNodeAddContentLen:
1331 * @cur: the node being modified
1332 * @content: extra content
1333 * @len: the size of @content
1334 *
1335 * Append the extra substring to the node content.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001336 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001337void
1338xmlNodeAddContentLen(xmlNodePtr cur, const CHAR *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001339 if (cur == NULL) {
Daniel Veillard16253641998-10-28 22:58:05 +00001340 fprintf(stderr, "xmlNodeAddContentLen : node == NULL\n");
1341 return;
1342 }
1343 if (len <= 0) return;
1344 switch (cur->type) {
1345 case XML_DOCUMENT_FRAG_NODE:
1346 case XML_ELEMENT_NODE: {
1347 xmlNodePtr last = NULL, new;
1348
1349 if (cur->childs != NULL) {
1350 last = cur->childs;
1351 while (last->next != NULL) last = last->next;
1352 } else {
1353 if (cur->content != NULL) {
1354 cur->childs = xmlStringGetNodeList(cur->doc, cur->content);
1355 free(cur->content);
1356 cur->content = NULL;
1357 if (cur->childs != NULL) {
1358 last = cur->childs;
1359 while (last->next != NULL) last = last->next;
1360 }
1361 }
1362 }
1363 new = xmlStringLenGetNodeList(cur->doc, content, len);
1364 if (new != NULL) {
1365 xmlAddChild(cur, new);
1366 if ((last != NULL) && (last->next == new))
1367 xmlTextMerge(last, new);
1368 }
1369 break;
1370 }
1371 case XML_ATTRIBUTE_NODE:
1372 break;
1373 case XML_TEXT_NODE:
1374 case XML_CDATA_SECTION_NODE:
1375 case XML_ENTITY_REF_NODE:
1376 case XML_ENTITY_NODE:
1377 case XML_PI_NODE:
1378 case XML_COMMENT_NODE:
1379 if (content != NULL)
1380 cur->content = xmlStrncat(cur->content, content, len);
1381 case XML_DOCUMENT_NODE:
1382 case XML_DOCUMENT_TYPE_NODE:
1383 break;
1384 case XML_NOTATION_NODE:
1385 if (content != NULL)
1386 cur->content = xmlStrncat(cur->content, content, len);
1387 break;
1388 }
1389}
1390
1391/**
1392 * xmlNodeAddContent:
1393 * @cur: the node being modified
1394 * @content: extra content
1395 *
1396 * Append the extra substring to the node content.
1397 */
1398void
1399xmlNodeAddContent(xmlNodePtr cur, const CHAR *content) {
1400 int len;
1401
1402 if (cur == NULL) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001403 fprintf(stderr, "xmlNodeAddContent : node == NULL\n");
1404 return;
1405 }
Daniel Veillard16253641998-10-28 22:58:05 +00001406 if (content == NULL) return;
1407 len = xmlStrlen(content);
1408 xmlNodeAddContentLen(cur, content, len);
1409}
1410
1411/**
1412 * xmlTextMerge:
1413 * @first: the first text node
1414 * @second: the second text node being merged
1415 *
1416 * Merge two text nodes into one
1417 * Return values: the first text node augmented
1418 */
1419xmlNodePtr
1420xmlTextMerge(xmlNodePtr first, xmlNodePtr second) {
1421 if (first == NULL) return(second);
1422 if (second == NULL) return(first);
1423 if (first->type != XML_TEXT_NODE) return(first);
1424 if (second->type != XML_TEXT_NODE) return(first);
1425 xmlNodeAddContent(first, second->content);
1426 xmlUnlinkNode(second);
1427 xmlFreeNode(second);
1428 return(first);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001429}
1430
Daniel Veillard97b58771998-10-20 06:14:16 +00001431/**
1432 * xmlSearchNs:
1433 * @doc: the document
1434 * @node: the current node
1435 * @nameSpace: the namespace string
Daniel Veillard260a68f1998-08-13 03:39:55 +00001436 *
Daniel Veillard97b58771998-10-20 06:14:16 +00001437 * Search a Ns registered under a given name space for a document.
1438 * recurse on the parents until it finds the defined namespace
1439 * or return NULL otherwise.
1440 * @nameSpace can be NULL, this is a search for the default namespace.
1441 * return values: the namespace pointer or NULL.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001442 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001443xmlNsPtr
1444xmlSearchNs(xmlDocPtr doc, xmlNodePtr node, const CHAR *nameSpace) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001445 xmlNsPtr cur;
1446
1447 while (node != NULL) {
1448 cur = node->nsDef;
1449 while (cur != NULL) {
1450 if ((cur->prefix == NULL) && (nameSpace == NULL))
1451 return(cur);
1452 if ((cur->prefix != NULL) && (nameSpace != NULL) &&
1453 (!xmlStrcmp(cur->prefix, nameSpace)))
1454 return(cur);
1455 cur = cur->next;
1456 }
1457 node = node->parent;
1458 }
1459 if (doc != NULL) {
1460 cur = doc->oldNs;
1461 while (cur != NULL) {
1462 if ((cur->prefix != NULL) && (nameSpace != NULL) &&
1463 (!xmlStrcmp(cur->prefix, nameSpace)))
1464 return(cur);
1465 cur = cur->next;
1466 }
1467 }
1468 return(NULL);
1469}
1470
Daniel Veillard97b58771998-10-20 06:14:16 +00001471/**
1472 * xmlSearchNsByHref:
1473 * @doc: the document
1474 * @node: the current node
1475 * @href: the namespace value
1476 *
1477 * Search a Ns aliasing a given URI. Recurse on the parents until it finds
1478 * the defined namespace or return NULL otherwise.
1479 * return values: the namespace pointer or NULL.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001480 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001481xmlNsPtr
1482xmlSearchNsByHref(xmlDocPtr doc, xmlNodePtr node, const CHAR *href) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001483 xmlNsPtr cur;
1484
1485 while (node != NULL) {
1486 cur = node->nsDef;
1487 while (cur != NULL) {
1488 if ((cur->href != NULL) && (href != NULL) &&
1489 (!xmlStrcmp(cur->href, href)))
1490 return(cur);
1491 cur = cur->next;
1492 }
1493 node = node->parent;
1494 }
1495 if (doc != NULL) {
1496 cur = doc->oldNs;
1497 while (cur != NULL) {
1498 if ((cur->href != NULL) && (href != NULL) &&
1499 (!xmlStrcmp(cur->href, href)))
1500 return(cur);
1501 cur = cur->next;
1502 }
1503 }
1504 return(NULL);
1505}
1506
Daniel Veillard97b58771998-10-20 06:14:16 +00001507/**
1508 * xmlGetProp:
1509 * @node: the node
1510 * @name: the attribute name
1511 *
1512 * Search and get the value of an attribute associated to a node
Daniel Veillardccb09631998-10-27 06:21:04 +00001513 * This does the entity substitution.
Daniel Veillard97b58771998-10-20 06:14:16 +00001514 * return values: the attribute value or NULL if not found.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001515 */
1516const CHAR *xmlGetProp(xmlNodePtr node, const CHAR *name) {
1517 xmlAttrPtr prop = node->properties;
1518
1519 while (prop != NULL) {
Daniel Veillardccb09631998-10-27 06:21:04 +00001520 if (!xmlStrcmp(prop->name, name))
1521 return(xmlNodeListGetString(node->doc, prop->val, 1));
Daniel Veillard260a68f1998-08-13 03:39:55 +00001522 prop = prop->next;
1523 }
1524 return(NULL);
1525}
1526
Daniel Veillard97b58771998-10-20 06:14:16 +00001527/**
Daniel Veillardccb09631998-10-27 06:21:04 +00001528 * xmlSetProp:
Daniel Veillard97b58771998-10-20 06:14:16 +00001529 * @node: the node
1530 * @name: the attribute name
1531 * @value: the attribute value
1532 *
1533 * Set (or reset) an attribute carried by a node.
1534 * return values: the attribute pointer.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001535 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001536xmlAttrPtr
1537xmlSetProp(xmlNodePtr node, const CHAR *name, const CHAR *value) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001538 xmlAttrPtr prop = node->properties;
1539
1540 while (prop != NULL) {
1541 if (!xmlStrcmp(prop->name, name)) {
Daniel Veillardccb09631998-10-27 06:21:04 +00001542 if (prop->val != NULL)
1543 xmlFreeNode(prop->val);
1544 prop->val = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001545 if (value != NULL)
Daniel Veillardccb09631998-10-27 06:21:04 +00001546 prop->val = xmlStringGetNodeList(node->doc, value);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001547 return(prop);
1548 }
1549 prop = prop->next;
1550 }
1551 prop = xmlNewProp(node, name, value);
1552 return(prop);
1553}
1554
Daniel Veillard97b58771998-10-20 06:14:16 +00001555/**
1556 * xmlNodeIsText:
1557 * @node: the node
1558 *
1559 * Is this node a Text node ?
1560 * return values: 1 yes, 0 no
Daniel Veillard260a68f1998-08-13 03:39:55 +00001561 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001562int
1563xmlNodeIsText(xmlNodePtr node) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001564 if (node == NULL) return(0);
1565
Daniel Veillard0bef1311998-10-14 02:36:47 +00001566 if (node->type == XML_TEXT_NODE) return(1);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001567 return(0);
1568}
1569
Daniel Veillard97b58771998-10-20 06:14:16 +00001570/**
1571 * xmlNodeIsText:
1572 * @node: the node
1573 * @content: the content
1574 * @len: @content lenght
1575 *
1576 * Concat the given string at the end of the existing node content
Daniel Veillard260a68f1998-08-13 03:39:55 +00001577 */
Daniel Veillard97b58771998-10-20 06:14:16 +00001578
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001579void
1580xmlTextConcat(xmlNodePtr node, const CHAR *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001581 if (node == NULL) return;
1582
Daniel Veillard0bef1311998-10-14 02:36:47 +00001583 if (node->type != XML_TEXT_NODE) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001584 fprintf(stderr, "xmlTextConcat: node is not text\n");
1585 return;
1586 }
1587 node->content = xmlStrncat(node->content, content, len);
1588}
1589
1590/************************************************************************
1591 * *
1592 * Output : to a FILE or in memory *
1593 * *
1594 ************************************************************************/
1595
Daniel Veillard260a68f1998-08-13 03:39:55 +00001596static CHAR *buffer = NULL;
1597static int buffer_index = 0;
1598static int buffer_size = 0;
1599
Daniel Veillard97b58771998-10-20 06:14:16 +00001600/**
1601 * xmlBufferWriteCHAR:
1602 * @string: the string to add
1603 *
1604 * routine which manage and grows an output buffer. This one add
1605 * CHARs at the end of the array.
1606 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001607void
1608xmlBufferWriteCHAR(const CHAR *string) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001609 const CHAR *cur;
1610
1611 if (buffer == NULL) {
1612 buffer_size = 50000;
1613 buffer = (CHAR *) malloc(buffer_size * sizeof(CHAR));
1614 if (buffer == NULL) {
1615 fprintf(stderr, "xmlBufferWrite : out of memory!\n");
1616 exit(1);
1617 }
1618 }
1619
1620 if (string == NULL) return;
1621 for (cur = string;*cur != 0;cur++) {
1622 if (buffer_index + 10 >= buffer_size) {
1623 buffer_size *= 2;
1624 buffer = (CHAR *) realloc(buffer, buffer_size * sizeof(CHAR));
1625 if (buffer == NULL) {
1626 fprintf(stderr, "xmlBufferWrite : out of memory!\n");
1627 exit(1);
1628 }
1629 }
1630 buffer[buffer_index++] = *cur;
1631 }
1632 buffer[buffer_index] = 0;
1633}
1634
Daniel Veillard97b58771998-10-20 06:14:16 +00001635/**
1636 * xmlBufferWriteChar:
1637 * @string: the string to add
1638 *
1639 * routine which manage and grows an output buffer. This one add
1640 * C chars at the end of the array.
1641 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001642void
1643xmlBufferWriteChar(const char *string) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001644 const char *cur;
1645
1646 if (buffer == NULL) {
1647 buffer_size = 50000;
1648 buffer = (CHAR *) malloc(buffer_size * sizeof(CHAR));
1649 if (buffer == NULL) {
1650 fprintf(stderr, "xmlBufferWrite : out of memory!\n");
1651 exit(1);
1652 }
1653 }
1654
1655 if (string == NULL) return;
1656 for (cur = string;*cur != 0;cur++) {
1657 if (buffer_index + 10 >= buffer_size) {
1658 buffer_size *= 2;
1659 buffer = (CHAR *) realloc(buffer, buffer_size * sizeof(CHAR));
1660 if (buffer == NULL) {
1661 fprintf(stderr, "xmlBufferWrite : out of memory!\n");
1662 exit(1);
1663 }
1664 }
1665 buffer[buffer_index++] = *cur;
1666 }
1667 buffer[buffer_index] = 0;
1668}
1669
Daniel Veillard97b58771998-10-20 06:14:16 +00001670/**
1671 * xmlGlobalNsDump:
1672 * @cur: a namespace
1673 *
1674 * Dump a global Namespace, this is the old version based on PIs.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001675 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001676static void
1677xmlGlobalNsDump(xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001678 if (cur == NULL) {
1679 fprintf(stderr, "xmlGlobalNsDump : Ns == NULL\n");
1680 return;
1681 }
1682 if (cur->type == XML_GLOBAL_NAMESPACE) {
1683 xmlBufferWriteChar("<?namespace");
1684 if (cur->href != NULL) {
1685 xmlBufferWriteChar(" href=\"");
1686 xmlBufferWriteCHAR(cur->href);
1687 xmlBufferWriteChar("\"");
1688 }
1689 if (cur->prefix != NULL) {
1690 xmlBufferWriteChar(" AS=\"");
1691 xmlBufferWriteCHAR(cur->prefix);
1692 xmlBufferWriteChar("\"");
1693 }
1694 xmlBufferWriteChar("?>\n");
1695 }
1696}
1697
Daniel Veillard97b58771998-10-20 06:14:16 +00001698/**
1699 * xmlGlobalNsListDump:
1700 * @cur: the first namespace
1701 *
1702 * Dump a list of global Namespace, this is the old version based on PIs.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001703 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001704static void
1705xmlGlobalNsListDump(xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001706 while (cur != NULL) {
1707 xmlGlobalNsDump(cur);
1708 cur = cur->next;
1709 }
1710}
1711
Daniel Veillard97b58771998-10-20 06:14:16 +00001712/**
1713 * xmlNsDump:
1714 * @cur: a namespace
1715 *
Daniel Veillard260a68f1998-08-13 03:39:55 +00001716 * Dump a local Namespace definition.
Daniel Veillard97b58771998-10-20 06:14:16 +00001717 * Should be called in the context of attributes dumps.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001718 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001719static void
1720xmlNsDump(xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001721 if (cur == NULL) {
1722 fprintf(stderr, "xmlNsDump : Ns == NULL\n");
1723 return;
1724 }
1725 if (cur->type == XML_LOCAL_NAMESPACE) {
1726 /* Within the context of an element attributes */
1727 if (cur->prefix != NULL) {
1728 xmlBufferWriteChar(" xmlns:");
1729 xmlBufferWriteCHAR(cur->prefix);
1730 } else
1731 xmlBufferWriteChar(" xmlns");
1732 xmlBufferWriteChar("=\"");
1733 xmlBufferWriteCHAR(cur->href);
1734 xmlBufferWriteChar("\"");
1735 }
1736}
1737
Daniel Veillard97b58771998-10-20 06:14:16 +00001738/**
1739 * xmlNsListDump:
1740 * @cur: the first namespace
1741 *
1742 * Dump a list of local Namespace definitions.
1743 * Should be called in the context of attributes dumps.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001744 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001745static void
1746xmlNsListDump(xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001747 while (cur != NULL) {
1748 xmlNsDump(cur);
1749 cur = cur->next;
1750 }
1751}
1752
Daniel Veillard97b58771998-10-20 06:14:16 +00001753/**
1754 * xmlDtdDump:
1755 * @doc: the document
1756 *
1757 * Dump the XML document DTD, if any.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001758 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001759static void
1760xmlDtdDump(xmlDocPtr doc) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001761 xmlDtdPtr cur = doc->dtd;
1762
1763 if (cur == NULL) {
1764 fprintf(stderr, "xmlDtdDump : DTD == NULL\n");
1765 return;
1766 }
1767 xmlBufferWriteChar("<!DOCTYPE ");
1768 xmlBufferWriteCHAR(cur->name);
1769 if (cur->ExternalID != NULL) {
1770 xmlBufferWriteChar(" PUBLIC \"");
1771 xmlBufferWriteCHAR(cur->ExternalID);
1772 xmlBufferWriteChar("\" \"");
1773 xmlBufferWriteCHAR(cur->SystemID);
1774 xmlBufferWriteChar("\"");
1775 } else if (cur->SystemID != NULL) {
1776 xmlBufferWriteChar(" SYSTEM \"");
1777 xmlBufferWriteCHAR(cur->SystemID);
1778 xmlBufferWriteChar("\"");
1779 }
1780 if ((cur->entities == NULL) && (doc->entities == NULL)) {
1781 xmlBufferWriteChar(">\n");
1782 return;
1783 }
1784 xmlBufferWriteChar(" [\n");
1785 if (cur->entities != NULL)
1786 xmlDumpEntitiesTable((xmlEntitiesTablePtr) cur->entities);
1787 if (doc->entities != NULL)
1788 xmlDumpEntitiesTable((xmlEntitiesTablePtr) doc->entities);
1789 xmlBufferWriteChar("]");
1790
1791 /* TODO !!! a lot more things to dump ... */
1792 xmlBufferWriteChar(">\n");
1793}
1794
Daniel Veillard97b58771998-10-20 06:14:16 +00001795/**
1796 * xmlAttrDump:
1797 * @doc: the document
1798 * @cur: the attribute pointer
1799 *
1800 * Dump an XML attribute
Daniel Veillard260a68f1998-08-13 03:39:55 +00001801 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001802static void
1803xmlAttrDump(xmlDocPtr doc, xmlAttrPtr cur) {
Daniel Veillardccb09631998-10-27 06:21:04 +00001804 CHAR *value;
1805
Daniel Veillard260a68f1998-08-13 03:39:55 +00001806 if (cur == NULL) {
1807 fprintf(stderr, "xmlAttrDump : property == NULL\n");
1808 return;
1809 }
1810 xmlBufferWriteChar(" ");
1811 xmlBufferWriteCHAR(cur->name);
Daniel Veillardccb09631998-10-27 06:21:04 +00001812 value = xmlNodeListGetString(doc, cur->val, 0);
1813 if (value) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001814 xmlBufferWriteChar("=\"");
Daniel Veillardccb09631998-10-27 06:21:04 +00001815 xmlBufferWriteCHAR(value);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001816 xmlBufferWriteChar("\"");
Daniel Veillardccb09631998-10-27 06:21:04 +00001817 free(value);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001818 }
1819}
1820
Daniel Veillard97b58771998-10-20 06:14:16 +00001821/**
1822 * xmlAttrListDump:
1823 * @doc: the document
1824 * @cur: the first attribute pointer
1825 *
1826 * Dump a list of XML attributes
Daniel Veillard260a68f1998-08-13 03:39:55 +00001827 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001828static void
1829xmlAttrListDump(xmlDocPtr doc, xmlAttrPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001830 if (cur == NULL) {
1831 fprintf(stderr, "xmlAttrListDump : property == NULL\n");
1832 return;
1833 }
1834 while (cur != NULL) {
1835 xmlAttrDump(doc, cur);
1836 cur = cur->next;
1837 }
1838}
1839
Daniel Veillard260a68f1998-08-13 03:39:55 +00001840
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001841static void
1842xmlNodeDump(xmlDocPtr doc, xmlNodePtr cur, int level);
Daniel Veillard97b58771998-10-20 06:14:16 +00001843/**
1844 * xmlNodeListDump:
1845 * @doc: the document
1846 * @cur: the first node
1847 * @level: the imbrication level for indenting
1848 *
1849 * Dump an XML node list, recursive behaviour,children are printed too.
1850 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001851static void
1852xmlNodeListDump(xmlDocPtr doc, xmlNodePtr cur, int level) {
Daniel Veillardccb09631998-10-27 06:21:04 +00001853 int needIndent = 0, i;
1854
Daniel Veillard260a68f1998-08-13 03:39:55 +00001855 if (cur == NULL) {
1856 fprintf(stderr, "xmlNodeListDump : node == NULL\n");
1857 return;
1858 }
1859 while (cur != NULL) {
Daniel Veillardccb09631998-10-27 06:21:04 +00001860 if ((cur->type != XML_TEXT_NODE) &&
1861 (cur->type != XML_ENTITY_REF_NODE)) {
1862 if (!needIndent) {
1863 needIndent = 1;
1864 xmlBufferWriteChar("\n");
1865 }
1866 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00001867 xmlNodeDump(doc, cur, level);
1868 cur = cur->next;
1869 }
Daniel Veillardccb09631998-10-27 06:21:04 +00001870 if ((xmlIndentTreeOutput) && (needIndent))
1871 for (i = 1;i < level;i++)
1872 xmlBufferWriteChar(" ");
Daniel Veillard260a68f1998-08-13 03:39:55 +00001873}
1874
Daniel Veillard97b58771998-10-20 06:14:16 +00001875/**
Daniel Veillardccb09631998-10-27 06:21:04 +00001876 * xmlNodeDump:
Daniel Veillard97b58771998-10-20 06:14:16 +00001877 * @doc: the document
1878 * @cur: the current node
1879 * @level: the imbrication level for indenting
1880 *
1881 * Dump an XML node, recursive behaviour,children are printed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001882 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001883static void
1884xmlNodeDump(xmlDocPtr doc, xmlNodePtr cur, int level) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001885 int i;
1886
1887 if (cur == NULL) {
1888 fprintf(stderr, "xmlNodeDump : node == NULL\n");
1889 return;
1890 }
Daniel Veillard0bef1311998-10-14 02:36:47 +00001891 if (cur->type == XML_TEXT_NODE) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001892 if (cur->content != NULL)
1893 xmlBufferWriteCHAR(xmlEncodeEntities(doc, cur->content));
1894 return;
1895 }
Daniel Veillard0bef1311998-10-14 02:36:47 +00001896 if (cur->type == XML_COMMENT_NODE) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001897 if (cur->content != NULL) {
1898 xmlBufferWriteChar("<!--");
1899 xmlBufferWriteCHAR(cur->content);
1900 xmlBufferWriteChar("-->");
1901 }
1902 return;
1903 }
Daniel Veillardccb09631998-10-27 06:21:04 +00001904 if (cur->type == XML_ENTITY_REF_NODE) {
1905 xmlBufferWriteChar("&");
1906 xmlBufferWriteCHAR(cur->name);
1907 xmlBufferWriteChar(";");
1908 return;
1909 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00001910 if (xmlIndentTreeOutput)
1911 for (i = 0;i < level;i++)
1912 xmlBufferWriteChar(" ");
1913
1914 xmlBufferWriteChar("<");
1915 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
1916 xmlBufferWriteCHAR(cur->ns->prefix);
1917 xmlBufferWriteChar(":");
1918 }
1919
1920 xmlBufferWriteCHAR(cur->name);
1921 if (cur->nsDef)
1922 xmlNsListDump(cur->nsDef);
1923 if (cur->properties != NULL)
1924 xmlAttrListDump(doc, cur->properties);
1925
1926 if ((cur->content == NULL) && (cur->childs == NULL)) {
1927 xmlBufferWriteChar("/>\n");
1928 return;
1929 }
1930 xmlBufferWriteChar(">");
1931 if (cur->content != NULL)
1932 xmlBufferWriteCHAR(xmlEncodeEntities(doc, cur->content));
1933 if (cur->childs != NULL) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001934 xmlNodeListDump(doc, cur->childs, level + 1);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001935 }
1936 xmlBufferWriteChar("</");
1937 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
1938 xmlBufferWriteCHAR(cur->ns->prefix);
1939 xmlBufferWriteChar(":");
1940 }
1941
1942 xmlBufferWriteCHAR(cur->name);
1943 xmlBufferWriteChar(">\n");
1944}
1945
Daniel Veillard97b58771998-10-20 06:14:16 +00001946/**
1947 * xmlDocContentDump:
1948 * @cur: the document
1949 *
1950 * Dump an XML document.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001951 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001952static void
1953xmlDocContentDump(xmlDocPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001954 if (oldXMLWDcompatibility)
1955 xmlBufferWriteChar("<?XML version=\"");
1956 else
1957 xmlBufferWriteChar("<?xml version=\"");
1958 xmlBufferWriteCHAR(cur->version);
1959 xmlBufferWriteChar("\"");
1960 if (cur->encoding != NULL) {
1961 xmlBufferWriteChar(" encoding=\"");
1962 xmlBufferWriteCHAR(cur->encoding);
1963 xmlBufferWriteChar("\"");
1964 }
1965 switch (cur->standalone) {
1966 case 0:
1967 xmlBufferWriteChar(" standalone=\"no\"");
1968 break;
1969 case 1:
1970 xmlBufferWriteChar(" standalone=\"yes\"");
1971 break;
1972 }
1973 xmlBufferWriteChar("?>\n");
1974 if ((cur->dtd != NULL) || (cur->entities != NULL))
1975 xmlDtdDump(cur);
1976 if (cur->root != NULL) {
1977 /* global namespace definitions, the old way */
1978 if (oldXMLWDcompatibility)
1979 xmlGlobalNsListDump(cur->oldNs);
1980 else
1981 xmlUpgradeOldNs(cur);
1982 xmlNodeDump(cur, cur->root, 0);
1983 }
1984}
1985
Daniel Veillard97b58771998-10-20 06:14:16 +00001986/**
1987 * xmlDocDumpMemory:
1988 * @cur: the document
1989 * @mem: OUT: the memory pointer
1990 * @size: OUT: the memory lenght
1991 *
1992 * Dump an XML document in memory and return the CHAR * and it's size.
1993 * It's up to the caller to free the memory.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001994 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001995void
1996xmlDocDumpMemory(xmlDocPtr cur, CHAR**mem, int *size) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001997 if (cur == NULL) {
1998 fprintf(stderr, "xmlDocDump : document == NULL\n");
1999 *mem = NULL;
2000 *size = 0;
2001 return;
2002 }
2003 buffer_index = 0;
2004 xmlDocContentDump(cur);
2005
2006 *mem = buffer;
2007 *size = buffer_index;
2008}
2009
Daniel Veillard97b58771998-10-20 06:14:16 +00002010/**
2011 * xmlGetDocCompressMode:
2012 * @doc: the document
2013 *
2014 * get the compression ratio for a document, ZLIB based
2015 * return values: 0 (uncompressed) to 9 (max compression)
Daniel Veillard151b1b01998-09-23 00:49:46 +00002016 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002017int
2018 xmlGetDocCompressMode (xmlDocPtr doc) {
Daniel Veillard15a8df41998-09-24 19:15:06 +00002019 if (doc == NULL) return(-1);
2020 return(doc->compression);
2021}
2022
Daniel Veillard97b58771998-10-20 06:14:16 +00002023/**
2024 * xmlSetDocCompressMode:
2025 * @doc: the document
2026 * @mode: the compression ratio
2027 *
2028 * set the compression ratio for a document, ZLIB based
2029 * Correct values: 0 (uncompressed) to 9 (max compression)
2030 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002031void
2032xmlSetDocCompressMode (xmlDocPtr doc, int mode) {
Daniel Veillard15a8df41998-09-24 19:15:06 +00002033 if (doc == NULL) return;
2034 if (mode < 0) doc->compression = 0;
2035 else if (mode > 9) doc->compression = 9;
2036 else doc->compression = mode;
2037}
2038
Daniel Veillard97b58771998-10-20 06:14:16 +00002039/**
2040 * xmlGetCompressMode:
2041 *
2042 * get the default compression mode used, ZLIB based.
2043 * return values: 0 (uncompressed) to 9 (max compression)
Daniel Veillard15a8df41998-09-24 19:15:06 +00002044 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002045int
2046 xmlGetCompressMode(void) {
Daniel Veillard151b1b01998-09-23 00:49:46 +00002047 return(xmlCompressMode);
2048}
Daniel Veillard97b58771998-10-20 06:14:16 +00002049
2050/**
2051 * xmlSetCompressMode:
2052 * @mode: the compression ratio
2053 *
2054 * set the default compression mode used, ZLIB based
2055 * Correct values: 0 (uncompressed) to 9 (max compression)
2056 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002057void
2058xmlSetCompressMode(int mode) {
Daniel Veillard151b1b01998-09-23 00:49:46 +00002059 if (mode < 0) xmlCompressMode = 0;
Daniel Veillard15a8df41998-09-24 19:15:06 +00002060 else if (mode > 9) xmlCompressMode = 9;
Daniel Veillard151b1b01998-09-23 00:49:46 +00002061 else xmlCompressMode = mode;
2062}
2063
Daniel Veillard97b58771998-10-20 06:14:16 +00002064/**
2065 * xmlDocDump:
2066 * @f: the FILE*
2067 * @cur: the document
2068 *
2069 * Dump an XML document to an open FILE.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002070 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002071void
2072xmlDocDump(FILE *f, xmlDocPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002073 if (cur == NULL) {
2074 fprintf(stderr, "xmlDocDump : document == NULL\n");
2075 return;
2076 }
2077 buffer_index = 0;
2078 xmlDocContentDump(cur);
2079
2080 fwrite(buffer, sizeof(CHAR), buffer_index, f);
2081}
2082
Daniel Veillard97b58771998-10-20 06:14:16 +00002083/**
2084 * xmlSaveFile:
2085 * @filename: the filename
2086 * @cur: the document
2087 *
2088 * Dump an XML document to a file. Will use compression if
2089 * compiled in and enabled.
2090 * returns: the number of file written or -1 in case of failure.
Daniel Veillard151b1b01998-09-23 00:49:46 +00002091 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002092int
2093xmlSaveFile(const char *filename, xmlDocPtr cur) {
Daniel Veillard151b1b01998-09-23 00:49:46 +00002094#ifdef HAVE_ZLIB_H
2095 gzFile zoutput = NULL;
2096 char mode[15];
2097#endif
Daniel Veillardccb09631998-10-27 06:21:04 +00002098 FILE *output = NULL;
Daniel Veillard151b1b01998-09-23 00:49:46 +00002099 int ret;
2100
2101#ifdef HAVE_ZLIB_H
Daniel Veillarddc3dd9d1998-09-24 19:25:54 +00002102 if ((cur->compression > 0) && (cur->compression <= 9)) {
2103 sprintf(mode, "w%d", cur->compression);
Daniel Veillard151b1b01998-09-23 00:49:46 +00002104 zoutput = gzopen(filename, mode);
2105 }
2106 if (zoutput == NULL) {
2107#endif
2108 output = fopen(filename, "w");
2109 if (output == NULL) return(-1);
2110#ifdef HAVE_ZLIB_H
2111 }
2112#endif
2113
2114 /*
2115 * save the content to a temp buffer.
2116 */
2117 buffer_index = 0;
2118 xmlDocContentDump(cur);
2119
2120#ifdef HAVE_ZLIB_H
2121 if (zoutput != NULL) {
2122 ret = gzwrite(zoutput, buffer, sizeof(CHAR) * buffer_index);
2123 gzclose(zoutput);
2124 return(ret);
2125 }
2126#endif
2127 ret = fwrite(buffer, sizeof(CHAR), buffer_index, output);
2128 fclose(output);
2129 return(ret * sizeof(CHAR));
2130}
2131
Daniel Veillard260a68f1998-08-13 03:39:55 +00002132/************************************************************************
2133 * *
2134 * Debug *
2135 * *
2136 ************************************************************************/
2137
2138#ifdef STANDALONE
2139int main(void) {
2140 xmlDocPtr doc;
2141 xmlNodePtr tree, subtree;
2142 xmlNsPtr ns1;
2143 xmlNsPtr ns2;
2144
2145 /*
2146 * build a fake XML document
2147 */
2148 doc = xmlNewDoc("1.0");
2149 ns1 = xmlNewNs(doc, "http://www.ietf.org/standards/dav/", "D");
2150 ns2 = xmlNewNs(doc, "http://www.w3.com/standards/z39.50/", "Z");
Daniel Veillardccb09631998-10-27 06:21:04 +00002151 doc->root = xmlNewDocNode(doc, ns1, "multistatus", NULL);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002152 tree = xmlNewChild(doc->root, NULL, "response", NULL);
2153 subtree = xmlNewChild(tree, NULL, "prop", NULL);
2154 xmlNewChild(subtree, ns2, "Authors", NULL);
2155 subtree = xmlNewChild(tree, NULL, "status", "HTTP/1.1 420 Method Failure");
2156 tree = xmlNewChild(doc->root, NULL, "response", NULL);
2157 subtree = xmlNewChild(tree, NULL, "prop", NULL);
2158 xmlNewChild(subtree, ns2, "Copyright-Owner", NULL);
2159 subtree = xmlNewChild(tree, NULL, "status", "HTTP/1.1 409 Conflict");
2160 tree = xmlNewChild(doc->root, NULL, "responsedescription",
2161 "Copyright Owner can not be deleted or altered");
2162
2163 /*
2164 * print it.
2165 */
2166 xmlDocDump(stdout, doc);
2167
2168 /*
2169 * free it.
2170 */
2171 xmlFreeDoc(doc);
2172 return(0);
2173}
2174#endif