blob: a3b378a0d3cdb525c80d0800d1fae90a34c52c2d [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 *
Daniel Veillard260a68f1998-08-13 03:39:55 +00006 * TODO Cleanup the Dump mechanism.
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00007 *
8 * Daniel.Veillard@w3.org
Daniel Veillard260a68f1998-08-13 03:39:55 +00009 */
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"
Daniel Veillard3b9def11999-01-31 22:15:06 +000023#include "valid.h"
Daniel Veillard260a68f1998-08-13 03:39:55 +000024
25static CHAR xmlStringText[] = { 't', 'e', 'x', 't', 0 };
26int oldXMLWDcompatibility = 0;
27int xmlIndentTreeOutput = 1;
28
Daniel Veillard15a8df41998-09-24 19:15:06 +000029static int xmlCompressMode = 0;
30
Daniel Veillard39a1f9a1999-01-17 19:11:59 +000031#define UPDATE_LAST_CHILD(n) if ((n) != NULL) { \
32 xmlNodePtr ulccur = (n)->childs; \
33 if (ulccur == NULL) { \
34 (n)->last = NULL; \
35 } else { \
36 while (ulccur->next != NULL) ulccur = ulccur->next; \
37 (n)->last = ulccur; \
Daniel Veillard1e346af1999-02-22 10:33:01 +000038}}
Daniel Veillard39a1f9a1999-01-17 19:11:59 +000039
Daniel Veillard260a68f1998-08-13 03:39:55 +000040/************************************************************************
41 * *
42 * Allocation and deallocation of basic structures *
43 * *
44 ************************************************************************/
45
Daniel Veillard97b58771998-10-20 06:14:16 +000046/**
47 * xmlUpgradeOldNs:
48 * @doc: a document pointer
49 *
50 * Upgrade old style Namespaces (PI) and move them to the root of the document.
Daniel Veillard260a68f1998-08-13 03:39:55 +000051 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +000052void
53xmlUpgradeOldNs(xmlDocPtr doc) {
Daniel Veillard260a68f1998-08-13 03:39:55 +000054 xmlNsPtr cur;
55
56 if ((doc == NULL) || (doc->oldNs == NULL)) return;
57 if (doc->root == NULL) {
58 fprintf(stderr, "xmlUpgradeOldNs: failed no root !\n");
59 return;
60 }
61
62 cur = doc->oldNs;
63 while (cur->next != NULL) {
64 cur->type = XML_LOCAL_NAMESPACE;
65 cur = cur->next;
66 }
67 cur->type = XML_LOCAL_NAMESPACE;
68 cur->next = doc->root->nsDef;
69 doc->root->nsDef = doc->oldNs;
70 doc->oldNs = NULL;
71}
72
Daniel Veillard97b58771998-10-20 06:14:16 +000073/**
74 * xmlNewNs:
75 * @node: the element carrying the namespace
76 * @href: the URI associated
77 * @prefix: the prefix for the namespace
78 *
Daniel Veillard260a68f1998-08-13 03:39:55 +000079 * Creation of a new Namespace.
Daniel Veillard1e346af1999-02-22 10:33:01 +000080 * Returns returns a new namespace pointer
Daniel Veillard260a68f1998-08-13 03:39:55 +000081 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +000082xmlNsPtr
83xmlNewNs(xmlNodePtr node, const CHAR *href, const CHAR *prefix) {
Daniel Veillard260a68f1998-08-13 03:39:55 +000084 xmlNsPtr cur;
85
86 if (href == NULL) {
87 fprintf(stderr, "xmlNewNs: href == NULL !\n");
88 return(NULL);
89 }
90
91 /*
92 * Allocate a new DTD and fill the fields.
93 */
94 cur = (xmlNsPtr) malloc(sizeof(xmlNs));
95 if (cur == NULL) {
96 fprintf(stderr, "xmlNewNs : malloc failed\n");
97 return(NULL);
98 }
99
100 cur->type = XML_LOCAL_NAMESPACE;
101 if (href != NULL)
102 cur->href = xmlStrdup(href);
103 else
104 cur->href = NULL;
105 if (prefix != NULL)
106 cur->prefix = xmlStrdup(prefix);
107 else
108 cur->prefix = NULL;
109
110 /*
111 * Add it at the end to preserve parsing order ...
112 */
113 cur->next = NULL;
114 if (node != NULL) {
115 if (node->nsDef == NULL) {
116 node->nsDef = cur;
117 } else {
118 xmlNsPtr prev = node->nsDef;
119
120 while (prev->next != NULL) prev = prev->next;
121 prev->next = cur;
122 }
123 }
124
125 return(cur);
126}
127
Daniel Veillard97b58771998-10-20 06:14:16 +0000128/**
129 * xmlNewGlobalNs:
130 * @doc: the document carrying the namespace
131 * @href: the URI associated
132 * @prefix: the prefix for the namespace
133 *
134 * Creation of a Namespace, the old way using PI and without scoping, to AVOID.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000135 * Returns returns a new namespace pointer
Daniel Veillard260a68f1998-08-13 03:39:55 +0000136 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000137xmlNsPtr
138xmlNewGlobalNs(xmlDocPtr doc, const CHAR *href, const CHAR *prefix) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000139 xmlNsPtr cur;
140
141 /*
142 * Allocate a new DTD and fill the fields.
143 */
144 cur = (xmlNsPtr) malloc(sizeof(xmlNs));
145 if (cur == NULL) {
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000146 fprintf(stderr, "xmlNewGlobalNs : malloc failed\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +0000147 return(NULL);
148 }
149
150 cur->type = XML_GLOBAL_NAMESPACE;
151 if (href != NULL)
152 cur->href = xmlStrdup(href);
153 else
154 cur->href = NULL;
155 if (prefix != NULL)
156 cur->prefix = xmlStrdup(prefix);
157 else
158 cur->prefix = NULL;
159
160 /*
161 * Add it at the end to preserve parsing order ...
162 */
163 cur->next = NULL;
164 if (doc != NULL) {
165 if (doc->oldNs == NULL) {
166 doc->oldNs = cur;
167 } else {
168 xmlNsPtr prev = doc->oldNs;
169
170 while (prev->next != NULL) prev = prev->next;
171 prev->next = cur;
172 }
173 }
174
175 return(cur);
176}
177
Daniel Veillard97b58771998-10-20 06:14:16 +0000178/**
179 * xmlSetNs:
180 * @node: a node in the document
181 * @ns: a namespace pointer
182 *
183 * Associate a namespace to a node, a posteriori.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000184 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000185void
186xmlSetNs(xmlNodePtr node, xmlNsPtr ns) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000187 if (node == NULL) {
188 fprintf(stderr, "xmlSetNs: node == NULL\n");
189 return;
190 }
191 node->ns = ns;
192}
193
Daniel Veillard97b58771998-10-20 06:14:16 +0000194/**
195 * xmlFreeNs:
196 * @cur: the namespace pointer
197 *
198 * Free up the structures associated to a namespace
Daniel Veillard260a68f1998-08-13 03:39:55 +0000199 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000200void
201xmlFreeNs(xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000202 if (cur == NULL) {
203 fprintf(stderr, "xmlFreeNs : ns == NULL\n");
204 return;
205 }
206 if (cur->href != NULL) free((char *) cur->href);
207 if (cur->prefix != NULL) free((char *) cur->prefix);
208 memset(cur, -1, sizeof(xmlNs));
209 free(cur);
210}
211
Daniel Veillard97b58771998-10-20 06:14:16 +0000212/**
213 * xmlFreeNsList:
214 * @cur: the first namespace pointer
215 *
216 * Free up all the structures associated to the chained namespaces.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000217 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000218void
219xmlFreeNsList(xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000220 xmlNsPtr next;
221 if (cur == NULL) {
222 fprintf(stderr, "xmlFreeNsList : ns == NULL\n");
223 return;
224 }
225 while (cur != NULL) {
226 next = cur->next;
227 xmlFreeNs(cur);
228 cur = next;
229 }
230}
231
Daniel Veillard97b58771998-10-20 06:14:16 +0000232/**
233 * xmlNewDtd:
234 * @doc: the document pointer
235 * @name: the DTD name
236 * @ExternalID: the external ID
237 * @SystemID: the system ID
238 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000239 * Creation of a new DTD.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000240 * Returns a pointer to the new DTD structure
Daniel Veillard260a68f1998-08-13 03:39:55 +0000241 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000242xmlDtdPtr
243xmlNewDtd(xmlDocPtr doc, const CHAR *name,
Daniel Veillard260a68f1998-08-13 03:39:55 +0000244 const CHAR *ExternalID, const CHAR *SystemID) {
245 xmlDtdPtr cur;
246
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000247 if ((doc != NULL) && (doc->extSubset != NULL)) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000248 fprintf(stderr, "xmlNewDtd(%s): document %s already have a DTD %s\n",
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000249 /* !!! */ (char *) name, doc->name,
250 /* !!! */ (char *)doc->extSubset->name);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000251 }
252
253 /*
254 * Allocate a new DTD and fill the fields.
255 */
256 cur = (xmlDtdPtr) malloc(sizeof(xmlDtd));
257 if (cur == NULL) {
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000258 fprintf(stderr, "xmlNewDtd : malloc failed\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +0000259 return(NULL);
260 }
261
262 if (name != NULL)
263 cur->name = xmlStrdup(name);
264 else
265 cur->name = NULL;
266 if (ExternalID != NULL)
267 cur->ExternalID = xmlStrdup(ExternalID);
268 else
269 cur->ExternalID = NULL;
270 if (SystemID != NULL)
271 cur->SystemID = xmlStrdup(SystemID);
272 else
273 cur->SystemID = NULL;
Daniel Veillard1e346af1999-02-22 10:33:01 +0000274 cur->notations = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000275 cur->elements = NULL;
Daniel Veillard1e346af1999-02-22 10:33:01 +0000276 cur->attributes = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000277 cur->entities = NULL;
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000278 if (doc != NULL)
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000279 doc->extSubset = cur;
280
281 return(cur);
282}
283
284/**
285 * xmlCreateIntSubset:
286 * @doc: the document pointer
287 * @name: the DTD name
288 * @ExternalID: the external ID
289 * @SystemID: the system ID
290 *
Daniel Veillard1e346af1999-02-22 10:33:01 +0000291 * Create the internal subset of a document
292 * Returns a pointer to the new DTD structure
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000293 */
294xmlDtdPtr
295xmlCreateIntSubset(xmlDocPtr doc, const CHAR *name,
296 const CHAR *ExternalID, const CHAR *SystemID) {
297 xmlDtdPtr cur;
298
299 if ((doc != NULL) && (doc->intSubset != NULL)) {
300 fprintf(stderr,
301 "xmlCreateIntSubset(): document %s already have an internal subset\n",
302 doc->name);
303 return(NULL);
304 }
305
306 /*
307 * Allocate a new DTD and fill the fields.
308 */
309 cur = (xmlDtdPtr) malloc(sizeof(xmlDtd));
310 if (cur == NULL) {
311 fprintf(stderr, "xmlNewDtd : malloc failed\n");
312 return(NULL);
313 }
314
315 if (name != NULL)
316 cur->name = xmlStrdup(name);
317 else
318 cur->name = NULL;
319 if (ExternalID != NULL)
320 cur->ExternalID = xmlStrdup(ExternalID);
321 else
322 cur->ExternalID = NULL;
323 if (SystemID != NULL)
324 cur->SystemID = xmlStrdup(SystemID);
325 else
326 cur->SystemID = NULL;
Daniel Veillard1e346af1999-02-22 10:33:01 +0000327 cur->notations = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000328 cur->elements = NULL;
Daniel Veillard1e346af1999-02-22 10:33:01 +0000329 cur->attributes = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000330 cur->entities = NULL;
331 if (doc != NULL)
332 doc->intSubset = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000333
334 return(cur);
335}
336
Daniel Veillard97b58771998-10-20 06:14:16 +0000337/**
338 * xmlFreeDtd:
339 * @cur: the DTD structure to free up
340 *
341 * Free a DTD structure.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000342 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000343void
344xmlFreeDtd(xmlDtdPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000345 if (cur == NULL) {
346 fprintf(stderr, "xmlFreeDtd : DTD == NULL\n");
347 return;
348 }
349 if (cur->name != NULL) free((char *) cur->name);
350 if (cur->SystemID != NULL) free((char *) cur->SystemID);
351 if (cur->ExternalID != NULL) free((char *) cur->ExternalID);
Daniel Veillard1e346af1999-02-22 10:33:01 +0000352 if (cur->notations != NULL)
353 xmlFreeNotationTable((xmlNotationTablePtr) cur->notations);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000354 if (cur->elements != NULL)
Daniel Veillard3b9def11999-01-31 22:15:06 +0000355 xmlFreeElementTable((xmlElementTablePtr) cur->elements);
Daniel Veillard1e346af1999-02-22 10:33:01 +0000356 if (cur->attributes != NULL)
357 xmlFreeAttributeTable((xmlAttributeTablePtr) cur->attributes);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000358 if (cur->entities != NULL)
359 xmlFreeEntitiesTable((xmlEntitiesTablePtr) cur->entities);
360 memset(cur, -1, sizeof(xmlDtd));
361 free(cur);
362}
363
Daniel Veillard97b58771998-10-20 06:14:16 +0000364/**
365 * xmlNewDoc:
366 * @version: CHAR string giving the version of XML "1.0"
367 *
Daniel Veillard1e346af1999-02-22 10:33:01 +0000368 * Returns a new document
Daniel Veillard260a68f1998-08-13 03:39:55 +0000369 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000370xmlDocPtr
371xmlNewDoc(const CHAR *version) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000372 xmlDocPtr cur;
373
374 if (version == NULL) {
375 fprintf(stderr, "xmlNewDoc : version == NULL\n");
376 return(NULL);
377 }
378
379 /*
380 * Allocate a new document and fill the fields.
381 */
382 cur = (xmlDocPtr) malloc(sizeof(xmlDoc));
383 if (cur == NULL) {
384 fprintf(stderr, "xmlNewDoc : malloc failed\n");
385 return(NULL);
386 }
387
Daniel Veillard33942841998-10-18 19:12:41 +0000388 cur->type = XML_DOCUMENT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000389 cur->version = xmlStrdup(version);
390 cur->name = NULL;
391 cur->root = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000392 cur->intSubset = NULL;
393 cur->extSubset = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000394 cur->oldNs = NULL;
395 cur->encoding = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000396 cur->standalone = -1;
Daniel Veillard15a8df41998-09-24 19:15:06 +0000397 cur->compression = xmlCompressMode;
Daniel Veillard27fb0751998-10-17 06:47:46 +0000398#ifndef WITHOUT_CORBA
399 cur->_private = NULL;
400 cur->vepv = NULL;
401#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000402 return(cur);
403}
404
Daniel Veillard97b58771998-10-20 06:14:16 +0000405/**
406 * xmlFreeDoc:
407 * @cur: pointer to the document
408 * @:
409 *
410 * Free up all the structures used by a document, tree included.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000411 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000412void
413xmlFreeDoc(xmlDocPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000414 if (cur == NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000415#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +0000416 fprintf(stderr, "xmlFreeDoc : document == NULL\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000417#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000418 return;
419 }
420 free((char *) cur->version);
421 if (cur->name != NULL) free((char *) cur->name);
422 if (cur->encoding != NULL) free((char *) cur->encoding);
423 if (cur->root != NULL) xmlFreeNode(cur->root);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000424 if (cur->intSubset != NULL) xmlFreeDtd(cur->intSubset);
425 if (cur->extSubset != NULL) xmlFreeDtd(cur->extSubset);
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000426 if (cur->oldNs != NULL) xmlFreeNsList(cur->oldNs);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000427 memset(cur, -1, sizeof(xmlDoc));
428 free(cur);
429}
430
Daniel Veillard97b58771998-10-20 06:14:16 +0000431/**
Daniel Veillard16253641998-10-28 22:58:05 +0000432 * xmlStringLenGetNodeList:
433 * @doc: the document
434 * @value: the value of the text
Daniel Veillard1e346af1999-02-22 10:33:01 +0000435 * @len: the length of the string value
Daniel Veillard16253641998-10-28 22:58:05 +0000436 *
437 * Parse the value string and build the node list associated. Should
438 * produce a flat tree with only TEXTs and ENTITY_REFs.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000439 * Returns a pointer to the first child
Daniel Veillard16253641998-10-28 22:58:05 +0000440 */
441xmlNodePtr
442xmlStringLenGetNodeList(xmlDocPtr doc, const CHAR *value, int len) {
443 xmlNodePtr ret = NULL, last = NULL;
444 xmlNodePtr node;
445 CHAR *val;
446 const CHAR *cur = value;
447 const CHAR *q;
Daniel Veillard25940b71998-10-29 05:51:30 +0000448 xmlEntityPtr ent;
Daniel Veillard16253641998-10-28 22:58:05 +0000449
450 if (value == NULL) return(NULL);
451
452 q = cur;
453 while ((*cur != 0) && (cur - value < len)) {
454 if (*cur == '&') {
Daniel Veillard25940b71998-10-29 05:51:30 +0000455 /*
456 * Save the current text.
457 */
Daniel Veillard16253641998-10-28 22:58:05 +0000458 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000459 if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
460 xmlNodeAddContentLen(last, q, cur - q);
461 } else {
462 node = xmlNewDocTextLen(doc, q, cur - q);
463 if (node == NULL) return(ret);
464 if (last == NULL)
465 last = ret = node;
466 else {
467 last->next = node;
468 node->prev = last;
469 last = node;
470 }
Daniel Veillard16253641998-10-28 22:58:05 +0000471 }
472 }
Daniel Veillard25940b71998-10-29 05:51:30 +0000473 /*
474 * Read the entity string
475 */
Daniel Veillard16253641998-10-28 22:58:05 +0000476 cur++;
477 q = cur;
478 while ((*cur != 0) && (cur - value < len) && (*cur != ';')) cur++;
479 if ((*cur == 0) || (cur - value >= len)) {
480 fprintf(stderr,
481 "xmlStringGetNodeList: unterminated entity %30s\n", q);
482 return(ret);
483 }
484 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000485 /*
486 * Predefined entities don't generate nodes
487 */
Daniel Veillard16253641998-10-28 22:58:05 +0000488 val = xmlStrndup(q, cur - q);
Daniel Veillard25940b71998-10-29 05:51:30 +0000489 ent = xmlGetDocEntity(doc, val);
490 if ((ent != NULL) &&
491 (ent->type == XML_INTERNAL_PREDEFINED_ENTITY)) {
492 if (last == NULL) {
493 node = xmlNewDocText(doc, ent->content);
494 last = ret = node;
495 } else
496 xmlNodeAddContent(last, ent->content);
497
498 } else {
499 /*
500 * Create a new REFERENCE_REF node
501 */
502 node = xmlNewReference(doc, val);
Daniel Veillard242590e1998-11-13 18:04:35 +0000503 if (node == NULL) {
504 if (val != NULL) free(val);
505 return(ret);
506 }
Daniel Veillard25940b71998-10-29 05:51:30 +0000507 if (last == NULL)
508 last = ret = node;
509 else {
510 last->next = node;
511 node->prev = last;
512 last = node;
513 }
Daniel Veillard16253641998-10-28 22:58:05 +0000514 }
515 free(val);
516 }
517 cur++;
518 q = cur;
519 } else
520 cur++;
521 }
522 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000523 /*
524 * Handle the last piece of text.
525 */
526 if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
527 xmlNodeAddContentLen(last, q, cur - q);
528 } else {
529 node = xmlNewDocTextLen(doc, q, cur - q);
530 if (node == NULL) return(ret);
531 if (last == NULL)
532 last = ret = node;
533 else {
534 last->next = node;
535 node->prev = last;
536 last = node;
537 }
Daniel Veillard16253641998-10-28 22:58:05 +0000538 }
539 }
540 return(ret);
541}
542
543/**
Daniel Veillardccb09631998-10-27 06:21:04 +0000544 * xmlStringGetNodeList:
545 * @doc: the document
546 * @value: the value of the attribute
547 *
548 * Parse the value string and build the node list associated. Should
549 * produce a flat tree with only TEXTs and ENTITY_REFs.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000550 * Returns a pointer to the first child
Daniel Veillardccb09631998-10-27 06:21:04 +0000551 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000552xmlNodePtr
553xmlStringGetNodeList(xmlDocPtr doc, const CHAR *value) {
Daniel Veillardccb09631998-10-27 06:21:04 +0000554 xmlNodePtr ret = NULL, last = NULL;
555 xmlNodePtr node;
556 CHAR *val;
557 const CHAR *cur = value;
558 const CHAR *q;
Daniel Veillard25940b71998-10-29 05:51:30 +0000559 xmlEntityPtr ent;
Daniel Veillardccb09631998-10-27 06:21:04 +0000560
561 if (value == NULL) return(NULL);
562
563 q = cur;
564 while (*cur != 0) {
565 if (*cur == '&') {
Daniel Veillard25940b71998-10-29 05:51:30 +0000566 /*
567 * Save the current text.
568 */
Daniel Veillardccb09631998-10-27 06:21:04 +0000569 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000570 if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
571 xmlNodeAddContentLen(last, q, cur - q);
572 } else {
573 node = xmlNewDocTextLen(doc, q, cur - q);
574 if (node == NULL) return(ret);
575 if (last == NULL)
576 last = ret = node;
577 else {
578 last->next = node;
579 node->prev = last;
580 last = node;
581 }
Daniel Veillardccb09631998-10-27 06:21:04 +0000582 }
583 }
Daniel Veillard25940b71998-10-29 05:51:30 +0000584 /*
585 * Read the entity string
586 */
Daniel Veillardccb09631998-10-27 06:21:04 +0000587 cur++;
588 q = cur;
589 while ((*cur != 0) && (*cur != ';')) cur++;
590 if (*cur == 0) {
591 fprintf(stderr,
592 "xmlStringGetNodeList: unterminated entity %30s\n", q);
593 return(ret);
594 }
595 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000596 /*
597 * Predefined entities don't generate nodes
598 */
Daniel Veillardccb09631998-10-27 06:21:04 +0000599 val = xmlStrndup(q, cur - q);
Daniel Veillard25940b71998-10-29 05:51:30 +0000600 ent = xmlGetDocEntity(doc, val);
601 if ((ent != NULL) &&
602 (ent->type == XML_INTERNAL_PREDEFINED_ENTITY)) {
603 if (last == NULL) {
604 node = xmlNewDocText(doc, ent->content);
605 last = ret = node;
606 } else
607 xmlNodeAddContent(last, ent->content);
608
609 } else {
610 /*
611 * Create a new REFERENCE_REF node
612 */
Daniel Veillard25940b71998-10-29 05:51:30 +0000613 node = xmlNewReference(doc, val);
Daniel Veillard242590e1998-11-13 18:04:35 +0000614 if (node == NULL) {
615 if (val != NULL) free(val);
616 return(ret);
617 }
Daniel Veillard25940b71998-10-29 05:51:30 +0000618 if (last == NULL)
619 last = ret = node;
620 else {
621 last->next = node;
622 node->prev = last;
623 last = node;
624 }
Daniel Veillardccb09631998-10-27 06:21:04 +0000625 }
626 free(val);
627 }
628 cur++;
629 q = cur;
630 } else
631 cur++;
632 }
633 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000634 /*
635 * Handle the last piece of text.
636 */
637 if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
638 xmlNodeAddContentLen(last, q, cur - q);
639 } else {
640 node = xmlNewDocTextLen(doc, q, cur - q);
641 if (node == NULL) return(ret);
642 if (last == NULL)
643 last = ret = node;
644 else {
645 last->next = node;
646 node->prev = last;
647 last = node;
648 }
Daniel Veillardccb09631998-10-27 06:21:04 +0000649 }
650 }
651 return(ret);
652}
653
654/**
655 * xmlNodeListGetString:
656 * @doc: the document
657 * @list: a Node list
658 * @inLine: should we replace entity contents or show their external form
659 *
660 * Returns the string equivalent to the text contained in the Node list
661 * made of TEXTs and ENTITY_REFs
Daniel Veillard1e346af1999-02-22 10:33:01 +0000662 * Returns a pointer to the string copy, the calller must free it.
Daniel Veillardccb09631998-10-27 06:21:04 +0000663 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000664CHAR *
665xmlNodeListGetString(xmlDocPtr doc, xmlNodePtr list, int inLine) {
Daniel Veillardccb09631998-10-27 06:21:04 +0000666 xmlNodePtr node = list;
667 CHAR *ret = NULL;
668 xmlEntityPtr ent;
669
670 if (list == NULL) return(NULL);
671
672 while (node != NULL) {
673 if (node->type == XML_TEXT_NODE) {
674 if (inLine)
675 ret = xmlStrcat(ret, node->content);
676 else
677 ret = xmlStrcat(ret, xmlEncodeEntities(doc, node->content));
678 } else if (node->type == XML_ENTITY_REF_NODE) {
679 if (inLine) {
680 ent = xmlGetDocEntity(doc, node->name);
681 if (ent != NULL)
682 ret = xmlStrcat(ret, ent->content);
683 else
684 ret = xmlStrcat(ret, node->content);
685 } else {
686 CHAR buf[2];
687 buf[0] = '&'; buf[1] = 0;
688 ret = xmlStrncat(ret, buf, 1);
689 ret = xmlStrcat(ret, node->name);
690 buf[0] = ';'; buf[1] = 0;
691 ret = xmlStrncat(ret, buf, 1);
692 }
693 }
694#if 0
695 else {
696 fprintf(stderr, "xmlGetNodeListString : invalide node type %d\n",
697 node->type);
698 }
699#endif
700 node = node->next;
701 }
702 return(ret);
703}
704
705/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000706 * xmlNewProp:
707 * @node: the holding node
708 * @name: the name of the attribute
709 * @value: the value of the attribute
710 *
711 * Create a new property carried by a node.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000712 * Returns a pointer to the attribute
Daniel Veillard260a68f1998-08-13 03:39:55 +0000713 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000714xmlAttrPtr
715xmlNewProp(xmlNodePtr node, const CHAR *name, const CHAR *value) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000716 xmlAttrPtr cur;
717
718 if (name == NULL) {
719 fprintf(stderr, "xmlNewProp : name == NULL\n");
720 return(NULL);
721 }
722
723 /*
724 * Allocate a new property and fill the fields.
725 */
726 cur = (xmlAttrPtr) malloc(sizeof(xmlAttr));
727 if (cur == NULL) {
728 fprintf(stderr, "xmlNewProp : malloc failed\n");
729 return(NULL);
730 }
731
Daniel Veillard33942841998-10-18 19:12:41 +0000732 cur->type = XML_ATTRIBUTE_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000733 cur->node = node;
734 cur->name = xmlStrdup(name);
735 if (value != NULL)
Daniel Veillardccb09631998-10-27 06:21:04 +0000736 cur->val = xmlStringGetNodeList(node->doc, value);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000737 else
Daniel Veillardccb09631998-10-27 06:21:04 +0000738 cur->val = NULL;
Daniel Veillard27fb0751998-10-17 06:47:46 +0000739#ifndef WITHOUT_CORBA
740 cur->_private = NULL;
741 cur->vepv = NULL;
742#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000743
744 /*
745 * Add it at the end to preserve parsing order ...
746 */
747 cur->next = NULL;
748 if (node != NULL) {
749 if (node->properties == NULL) {
750 node->properties = cur;
751 } else {
752 xmlAttrPtr prev = node->properties;
753
754 while (prev->next != NULL) prev = prev->next;
755 prev->next = cur;
756 }
757 }
758 return(cur);
759}
760
Daniel Veillard97b58771998-10-20 06:14:16 +0000761/**
Daniel Veillardccb09631998-10-27 06:21:04 +0000762 * xmlNewDocProp:
763 * @doc: the document
764 * @name: the name of the attribute
765 * @value: the value of the attribute
766 *
767 * Create a new property carried by a document.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000768 * Returns a pointer to the attribute
Daniel Veillardccb09631998-10-27 06:21:04 +0000769 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000770xmlAttrPtr
771xmlNewDocProp(xmlDocPtr doc, const CHAR *name, const CHAR *value) {
Daniel Veillardccb09631998-10-27 06:21:04 +0000772 xmlAttrPtr cur;
773
774 if (name == NULL) {
775 fprintf(stderr, "xmlNewProp : name == NULL\n");
776 return(NULL);
777 }
778
779 /*
780 * Allocate a new property and fill the fields.
781 */
782 cur = (xmlAttrPtr) malloc(sizeof(xmlAttr));
783 if (cur == NULL) {
784 fprintf(stderr, "xmlNewProp : malloc failed\n");
785 return(NULL);
786 }
787
788 cur->type = XML_ATTRIBUTE_NODE;
789 cur->node = NULL;
790 cur->name = xmlStrdup(name);
791 if (value != NULL)
792 cur->val = xmlStringGetNodeList(doc, value);
793 else
794 cur->val = NULL;
795#ifndef WITHOUT_CORBA
796 cur->_private = NULL;
797 cur->vepv = NULL;
798#endif
799
800 cur->next = NULL;
801 return(cur);
802}
803
804/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000805 * xmlFreePropList:
806 * @cur: the first property in the list
807 *
808 * Free a property and all its siblings, all the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000809 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000810void
811xmlFreePropList(xmlAttrPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000812 xmlAttrPtr next;
813 if (cur == NULL) {
814 fprintf(stderr, "xmlFreePropList : property == NULL\n");
815 return;
816 }
817 while (cur != NULL) {
818 next = cur->next;
819 xmlFreeProp(cur);
820 cur = next;
821 }
822}
823
Daniel Veillard97b58771998-10-20 06:14:16 +0000824/**
825 * xmlFreeProp:
826 * @cur: the first property in the list
827 *
828 * Free one property, all the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000829 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000830void
831xmlFreeProp(xmlAttrPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000832 if (cur == NULL) {
833 fprintf(stderr, "xmlFreeProp : property == NULL\n");
834 return;
835 }
836 if (cur->name != NULL) free((char *) cur->name);
Daniel Veillardccb09631998-10-27 06:21:04 +0000837 if (cur->val != NULL) xmlFreeNodeList(cur->val);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000838 memset(cur, -1, sizeof(xmlAttr));
839 free(cur);
840}
841
Daniel Veillard97b58771998-10-20 06:14:16 +0000842/**
843 * xmlNewNode:
844 * @ns: namespace if any
845 * @name: the node name
Daniel Veillard97b58771998-10-20 06:14:16 +0000846 *
847 * Creation of a new node element. @ns and @content are optionnal (NULL).
Daniel Veillardccb09631998-10-27 06:21:04 +0000848 * If content is non NULL, a child list containing the TEXTs and
849 * ENTITY_REFs node will be created.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000850 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000851 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000852xmlNodePtr
853xmlNewNode(xmlNsPtr ns, const CHAR *name) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000854 xmlNodePtr cur;
855
856 if (name == NULL) {
857 fprintf(stderr, "xmlNewNode : name == NULL\n");
858 return(NULL);
859 }
860
861 /*
862 * Allocate a new node and fill the fields.
863 */
864 cur = (xmlNodePtr) malloc(sizeof(xmlNode));
865 if (cur == NULL) {
866 fprintf(stderr, "xmlNewNode : malloc failed\n");
867 return(NULL);
868 }
869
Daniel Veillard33942841998-10-18 19:12:41 +0000870 cur->type = XML_ELEMENT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000871 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000872 cur->parent = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000873 cur->next = NULL;
874 cur->prev = NULL;
875 cur->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000876 cur->last = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000877 cur->properties = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000878 cur->name = xmlStrdup(name);
879 cur->ns = ns;
880 cur->nsDef = NULL;
Daniel Veillardccb09631998-10-27 06:21:04 +0000881 cur->content = NULL;
Daniel Veillard27fb0751998-10-17 06:47:46 +0000882#ifndef WITHOUT_CORBA
883 cur->_private = NULL;
884 cur->vepv = NULL;
885#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000886 return(cur);
887}
888
Daniel Veillard97b58771998-10-20 06:14:16 +0000889/**
890 * xmlNewDocNode:
891 * @doc: the document
892 * @ns: namespace if any
893 * @name: the node name
894 * @content: the text content if any
895 *
896 * Creation of a new node element within a document. @ns and @content
897 * are optionnal (NULL).
Daniel Veillard1e346af1999-02-22 10:33:01 +0000898 * Returns a pointer to the new node object.
Daniel Veillard97b58771998-10-20 06:14:16 +0000899 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000900xmlNodePtr
901xmlNewDocNode(xmlDocPtr doc, xmlNsPtr ns,
Daniel Veillard0bef1311998-10-14 02:36:47 +0000902 const CHAR *name, CHAR *content) {
903 xmlNodePtr cur;
904
Daniel Veillardccb09631998-10-27 06:21:04 +0000905 cur = xmlNewNode(ns, name);
906 if (cur != NULL) {
907 cur->doc = doc;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000908 if (content != NULL) {
Daniel Veillardccb09631998-10-27 06:21:04 +0000909 cur->childs = xmlStringGetNodeList(doc, content);
Daniel Veillard1e346af1999-02-22 10:33:01 +0000910 UPDATE_LAST_CHILD(cur)
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000911 }
Daniel Veillardccb09631998-10-27 06:21:04 +0000912 }
Daniel Veillard0bef1311998-10-14 02:36:47 +0000913 return(cur);
914}
915
916
Daniel Veillard97b58771998-10-20 06:14:16 +0000917/**
918 * xmlNewText:
919 * @content: the text content
920 *
921 * Creation of a new text node.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000922 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000923 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000924xmlNodePtr
925xmlNewText(const CHAR *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000926 xmlNodePtr cur;
927
928 /*
929 * Allocate a new node and fill the fields.
930 */
931 cur = (xmlNodePtr) malloc(sizeof(xmlNode));
932 if (cur == NULL) {
933 fprintf(stderr, "xmlNewText : malloc failed\n");
934 return(NULL);
935 }
936
Daniel Veillard33942841998-10-18 19:12:41 +0000937 cur->type = XML_TEXT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000938 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000939 cur->parent = NULL;
940 cur->next = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000941 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000942 cur->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000943 cur->last = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000944 cur->properties = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000945 cur->type = XML_TEXT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000946 cur->name = xmlStrdup(xmlStringText);
947 cur->ns = NULL;
948 cur->nsDef = NULL;
949 if (content != NULL)
950 cur->content = xmlStrdup(content);
951 else
952 cur->content = NULL;
953 return(cur);
954}
955
Daniel Veillard97b58771998-10-20 06:14:16 +0000956/**
Daniel Veillardccb09631998-10-27 06:21:04 +0000957 * xmlNewReference:
958 * @doc: the document
959 * @name: the reference name, or the reference string with & and ;
960 *
961 * Creation of a new reference node.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000962 * Returns a pointer to the new node object.
Daniel Veillardccb09631998-10-27 06:21:04 +0000963 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000964xmlNodePtr
965xmlNewReference(xmlDocPtr doc, const CHAR *name) {
Daniel Veillardccb09631998-10-27 06:21:04 +0000966 xmlNodePtr cur;
967 xmlEntityPtr ent;
968
969 /*
970 * Allocate a new node and fill the fields.
971 */
972 cur = (xmlNodePtr) malloc(sizeof(xmlNode));
973 if (cur == NULL) {
974 fprintf(stderr, "xmlNewText : malloc failed\n");
975 return(NULL);
976 }
977
978 cur->type = XML_ENTITY_REF_NODE;
Daniel Veillard10c6a8f1998-10-28 01:00:12 +0000979 cur->doc = doc;
Daniel Veillardccb09631998-10-27 06:21:04 +0000980 cur->parent = NULL;
981 cur->next = NULL;
982 cur->prev = NULL;
983 cur->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000984 cur->last = NULL;
Daniel Veillardccb09631998-10-27 06:21:04 +0000985 cur->properties = NULL;
986 if (name[0] == '&') {
987 int len;
988 name++;
989 len = xmlStrlen(name);
990 if (name[len - 1] == ';')
991 cur->name = xmlStrndup(name, len - 1);
992 else
993 cur->name = xmlStrndup(name, len);
994 } else
995 cur->name = xmlStrdup(name);
996 cur->ns = NULL;
997 cur->nsDef = NULL;
998
999 ent = xmlGetDocEntity(doc, cur->name);
1000 if (ent != NULL)
1001 cur->content = ent->content;
1002 else
1003 cur->content = NULL;
1004 return(cur);
1005}
1006
1007/**
Daniel Veillard97b58771998-10-20 06:14:16 +00001008 * xmlNewDocText:
1009 * @doc: the document
1010 * @content: the text content
1011 *
1012 * Creation of a new text node within a document.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001013 * Returns a pointer to the new node object.
Daniel Veillard97b58771998-10-20 06:14:16 +00001014 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001015xmlNodePtr
1016xmlNewDocText(xmlDocPtr doc, const CHAR *content) {
Daniel Veillard0bef1311998-10-14 02:36:47 +00001017 xmlNodePtr cur;
1018
1019 cur = xmlNewText(content);
1020 if (cur != NULL) cur->doc = doc;
1021 return(cur);
1022}
1023
Daniel Veillard97b58771998-10-20 06:14:16 +00001024/**
Daniel Veillardccb09631998-10-27 06:21:04 +00001025 * xmlNewTextLen:
Daniel Veillard97b58771998-10-20 06:14:16 +00001026 * @content: the text content
1027 * @len: the text len.
1028 *
1029 * Creation of a new text node with an extra parameter for the content's lenght
Daniel Veillard1e346af1999-02-22 10:33:01 +00001030 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001031 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001032xmlNodePtr
1033xmlNewTextLen(const CHAR *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001034 xmlNodePtr cur;
1035
1036 /*
1037 * Allocate a new node and fill the fields.
1038 */
1039 cur = (xmlNodePtr) malloc(sizeof(xmlNode));
1040 if (cur == NULL) {
1041 fprintf(stderr, "xmlNewText : malloc failed\n");
1042 return(NULL);
1043 }
1044
Daniel Veillard33942841998-10-18 19:12:41 +00001045 cur->type = XML_TEXT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001046 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001047 cur->parent = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001048 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001049 cur->next = NULL;
1050 cur->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001051 cur->last = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001052 cur->properties = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001053 cur->type = XML_TEXT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001054 cur->name = xmlStrdup(xmlStringText);
1055 cur->ns = NULL;
1056 cur->nsDef = NULL;
1057 if (content != NULL)
1058 cur->content = xmlStrndup(content, len);
1059 else
1060 cur->content = NULL;
1061 return(cur);
1062}
1063
Daniel Veillard97b58771998-10-20 06:14:16 +00001064/**
1065 * xmlNewDocTextLen:
1066 * @doc: the document
1067 * @content: the text content
1068 * @len: the text len.
1069 *
1070 * Creation of a new text node with an extra content lenght parameter. The
1071 * text node pertain to a given document.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001072 * Returns a pointer to the new node object.
Daniel Veillard97b58771998-10-20 06:14:16 +00001073 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001074xmlNodePtr
1075xmlNewDocTextLen(xmlDocPtr doc, const CHAR *content, int len) {
Daniel Veillard0bef1311998-10-14 02:36:47 +00001076 xmlNodePtr cur;
1077
1078 cur = xmlNewTextLen(content, len);
1079 if (cur != NULL) cur->doc = doc;
1080 return(cur);
1081}
1082
Daniel Veillard97b58771998-10-20 06:14:16 +00001083/**
1084 * xmlNewComment:
1085 * @content: the comment content
1086 *
1087 * Creation of a new node containing a comment.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001088 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001089 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001090xmlNodePtr
Daniel Veillard517752b1999-04-05 12:20:10 +00001091xmlNewComment(const CHAR *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001092 xmlNodePtr cur;
1093
1094 /*
1095 * Allocate a new node and fill the fields.
1096 */
1097 cur = (xmlNodePtr) malloc(sizeof(xmlNode));
1098 if (cur == NULL) {
1099 fprintf(stderr, "xmlNewComment : malloc failed\n");
1100 return(NULL);
1101 }
1102
Daniel Veillard33942841998-10-18 19:12:41 +00001103 cur->type = XML_COMMENT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001104 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001105 cur->parent = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001106 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001107 cur->next = NULL;
1108 cur->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001109 cur->last = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001110 cur->properties = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001111 cur->type = XML_COMMENT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001112 cur->name = xmlStrdup(xmlStringText);
1113 cur->ns = NULL;
1114 cur->nsDef = NULL;
1115 if (content != NULL)
1116 cur->content = xmlStrdup(content);
1117 else
1118 cur->content = NULL;
1119 return(cur);
1120}
1121
Daniel Veillard97b58771998-10-20 06:14:16 +00001122/**
Daniel Veillard1e346af1999-02-22 10:33:01 +00001123 * xmlNewDocComment:
Daniel Veillard97b58771998-10-20 06:14:16 +00001124 * @doc: the document
1125 * @content: the comment content
1126 *
1127 * Creation of a new node containing a commentwithin a document.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001128 * Returns a pointer to the new node object.
Daniel Veillard97b58771998-10-20 06:14:16 +00001129 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001130xmlNodePtr
Daniel Veillard517752b1999-04-05 12:20:10 +00001131xmlNewDocComment(xmlDocPtr doc, const CHAR *content) {
Daniel Veillard0bef1311998-10-14 02:36:47 +00001132 xmlNodePtr cur;
1133
1134 cur = xmlNewComment(content);
1135 if (cur != NULL) cur->doc = doc;
1136 return(cur);
1137}
1138
Daniel Veillard97b58771998-10-20 06:14:16 +00001139/**
1140 * xmlNewChild:
1141 * @parent: the parent node
1142 * @ns: a namespace if any
1143 * @name: the name of the child
1144 * @content: the content of the child if any.
1145 *
1146 *
1147 * Creation of a new child element, added at the end of @parent childs list.
Daniel Veillardccb09631998-10-27 06:21:04 +00001148 * @ns and @content parameters are optionnal (NULL). If content is non NULL,
1149 * a child list containing the TEXTs and ENTITY_REFs node will be created.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001150 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001151 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001152xmlNodePtr
1153xmlNewChild(xmlNodePtr parent, xmlNsPtr ns,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001154 const CHAR *name, CHAR *content) {
1155 xmlNodePtr cur, prev;
1156
1157 if (parent == NULL) {
1158 fprintf(stderr, "xmlNewChild : parent == NULL\n");
1159 return(NULL);
1160 }
1161
1162 if (name == NULL) {
1163 fprintf(stderr, "xmlNewChild : name == NULL\n");
1164 return(NULL);
1165 }
1166
1167 /*
1168 * Allocate a new node
1169 */
1170 if (ns == NULL)
Daniel Veillardccb09631998-10-27 06:21:04 +00001171 cur = xmlNewDocNode(parent->doc, parent->ns, name, content);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001172 else
Daniel Veillardccb09631998-10-27 06:21:04 +00001173 cur = xmlNewDocNode(parent->doc, ns, name, content);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001174 if (cur == NULL) return(NULL);
1175
1176 /*
1177 * add the new element at the end of the childs list.
1178 */
Daniel Veillardccb09631998-10-27 06:21:04 +00001179 cur->type = XML_ELEMENT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001180 cur->parent = parent;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001181 cur->doc = parent->doc;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001182 if (parent->childs == NULL) {
1183 parent->childs = cur;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001184 parent->last = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001185 } else {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001186 prev = parent->last;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001187 prev->next = cur;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001188 cur->prev = prev;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001189 parent->last = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001190 }
1191
1192 return(cur);
1193}
1194
Daniel Veillard97b58771998-10-20 06:14:16 +00001195/**
1196 * xmlAddChild:
1197 * @parent: the parent node
1198 * @cur: the child node
1199 *
1200 * Add a new child element, to @parent, at the end of the child list.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001201 * Returns the child or NULL in case of error.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001202 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001203xmlNodePtr
1204xmlAddChild(xmlNodePtr parent, xmlNodePtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001205 xmlNodePtr prev;
1206
1207 if (parent == NULL) {
1208 fprintf(stderr, "xmladdChild : parent == NULL\n");
1209 return(NULL);
1210 }
1211
1212 if (cur == NULL) {
1213 fprintf(stderr, "xmladdChild : child == NULL\n");
1214 return(NULL);
1215 }
1216
Daniel Veillard0bef1311998-10-14 02:36:47 +00001217 if ((cur->doc != NULL) && (parent->doc != NULL) &&
1218 (cur->doc != parent->doc)) {
1219 fprintf(stderr, "Elements moved to a different document\n");
1220 }
1221
Daniel Veillard260a68f1998-08-13 03:39:55 +00001222 /*
1223 * add the new element at the end of the childs list.
1224 */
1225 cur->parent = parent;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001226 cur->doc = parent->doc; /* the parent may not be linked to a doc ! */
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001227
Daniel Veillardccb09631998-10-27 06:21:04 +00001228 /*
1229 * Handle the case where parent->content != NULL, in that case it will
1230 * create a intermediate TEXT node.
1231 */
1232 if (parent->content != NULL) {
1233 xmlNodePtr text;
1234
1235 text = xmlNewDocText(parent->doc, parent->content);
1236 if (text != NULL) {
1237 text->next = parent->childs;
1238 if (text->next != NULL)
1239 text->next->prev = text;
1240 parent->childs = text;
Daniel Veillard1e346af1999-02-22 10:33:01 +00001241 UPDATE_LAST_CHILD(parent)
Daniel Veillardccb09631998-10-27 06:21:04 +00001242 free(parent->content);
1243 parent->content = NULL;
1244 }
1245 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00001246 if (parent->childs == NULL) {
1247 parent->childs = cur;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001248 parent->last = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001249 } else {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001250 prev = parent->last;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001251 prev->next = cur;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001252 cur->prev = prev;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001253 parent->last = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001254 }
1255
1256 return(cur);
1257}
1258
Daniel Veillard97b58771998-10-20 06:14:16 +00001259/**
1260 * xmlGetLastChild:
1261 * @parent: the parent node
1262 *
1263 * Search the last child of a node.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001264 * Returns the last child or NULL if none.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001265 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001266xmlNodePtr
1267xmlGetLastChild(xmlNodePtr parent) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001268 if (parent == NULL) {
1269 fprintf(stderr, "xmlGetLastChild : parent == NULL\n");
1270 return(NULL);
1271 }
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001272 return(parent->last);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001273}
1274
Daniel Veillard97b58771998-10-20 06:14:16 +00001275/**
1276 * xmlFreeNodeList:
1277 * @cur: the first node in the list
1278 *
1279 * Free a node and all its siblings, this is a recursive behaviour, all
1280 * the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001281 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001282void
1283xmlFreeNodeList(xmlNodePtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001284 xmlNodePtr next;
1285 if (cur == NULL) {
1286 fprintf(stderr, "xmlFreeNodeList : node == NULL\n");
1287 return;
1288 }
1289 while (cur != NULL) {
1290 next = cur->next;
1291 xmlFreeNode(cur);
1292 cur = next;
1293 }
1294}
1295
Daniel Veillard97b58771998-10-20 06:14:16 +00001296/**
1297 * xmlFreeNode:
1298 * @cur: the node
1299 *
1300 * Free a node, this is a recursive behaviour, all the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001301 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001302void
1303xmlFreeNode(xmlNodePtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001304 if (cur == NULL) {
1305 fprintf(stderr, "xmlFreeNode : node == NULL\n");
1306 return;
1307 }
Daniel Veillardccb09631998-10-27 06:21:04 +00001308 cur->doc = NULL;
1309 cur->parent = NULL;
1310 cur->next = NULL;
1311 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001312 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillardccb09631998-10-27 06:21:04 +00001313 if (cur->properties != NULL) xmlFreePropList(cur->properties);
1314 if (cur->type != XML_ENTITY_REF_NODE)
1315 if (cur->content != NULL) free(cur->content);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001316 if (cur->name != NULL) free((char *) cur->name);
1317 if (cur->nsDef != NULL) xmlFreeNsList(cur->nsDef);
1318 memset(cur, -1, sizeof(xmlNode));
1319 free(cur);
1320}
1321
Daniel Veillard16253641998-10-28 22:58:05 +00001322/**
1323 * xmlUnlinkNode:
1324 * @cur: the node
1325 *
1326 * Unlink a node from it's current context, the node is not freed
1327 */
1328void
1329xmlUnlinkNode(xmlNodePtr cur) {
1330 if (cur == NULL) {
1331 fprintf(stderr, "xmlUnlinkNode : node == NULL\n");
1332 return;
1333 }
1334 if ((cur->parent != NULL) && (cur->parent->childs == cur))
1335 cur->parent->childs = cur->next;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001336 if ((cur->parent != NULL) && (cur->parent->last == cur))
1337 cur->parent->last = cur->prev;
Daniel Veillard16253641998-10-28 22:58:05 +00001338 if (cur->next != NULL)
1339 cur->next->prev = cur->prev;
1340 if (cur->prev != NULL)
1341 cur->prev->next = cur->next;
1342 cur->next = cur->prev = NULL;
1343 cur->parent = NULL;
1344}
1345
Daniel Veillard260a68f1998-08-13 03:39:55 +00001346/************************************************************************
1347 * *
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001348 * Copy operations *
1349 * *
1350 ************************************************************************/
1351
1352/**
1353 * xmlCopyNamespace:
1354 * @cur: the namespace
1355 *
1356 * Do a copy of the namespace.
1357 *
1358 * Returns: a new xmlNsPtr, or NULL in case of error.
1359 */
1360xmlNsPtr
1361xmlCopyNamespace(xmlNsPtr cur) {
1362 xmlNsPtr ret;
1363
1364 if (cur == NULL) return(NULL);
1365 switch (cur->type) {
1366 case XML_GLOBAL_NAMESPACE:
1367 ret = xmlNewGlobalNs(NULL, cur->href, cur->prefix);
1368 break;
1369 case XML_LOCAL_NAMESPACE:
1370 ret = xmlNewNs(NULL, cur->href, cur->prefix);
1371 break;
1372 default:
1373 fprintf(stderr, "xmlCopyNamespace: unknown type %d\n", cur->type);
1374 return(NULL);
1375 }
1376 return(ret);
1377}
1378
1379/**
1380 * xmlCopyNamespaceList:
1381 * @cur: the first namespace
1382 *
1383 * Do a copy of an namespace list.
1384 *
1385 * Returns: a new xmlNsPtr, or NULL in case of error.
1386 */
1387xmlNsPtr
1388xmlCopyNamespaceList(xmlNsPtr cur) {
1389 xmlNsPtr ret = NULL;
1390 xmlNsPtr p = NULL,q;
1391
1392 while (cur != NULL) {
1393 q = xmlCopyNamespace(cur);
1394 if (p == NULL) {
1395 ret = p = q;
1396 } else {
1397 p->next = q;
1398 p = q;
1399 }
1400 cur = cur->next;
1401 }
1402 return(ret);
1403}
1404
1405/**
1406 * xmlCopyProp:
1407 * @cur: the attribute
1408 *
1409 * Do a copy of the attribute.
1410 *
1411 * Returns: a new xmlAttrPtr, or NULL in case of error.
1412 */
1413xmlAttrPtr
1414xmlCopyProp(xmlAttrPtr cur) {
1415 xmlAttrPtr ret;
1416
1417 if (cur == NULL) return(NULL);
1418 if (cur->val != NULL)
1419 ret = xmlNewDocProp(cur->val->doc, cur->name, NULL);
1420 else
1421 ret = xmlNewDocProp(NULL, cur->name, NULL);
1422 if (ret == NULL) return(NULL);
1423 if (cur->val != NULL)
1424 ret->val = xmlCopyNodeList(cur->val);
1425 return(ret);
1426}
1427
1428/**
1429 * xmlCopyPropList:
1430 * @cur: the first attribute
1431 *
1432 * Do a copy of an attribute list.
1433 *
1434 * Returns: a new xmlAttrPtr, or NULL in case of error.
1435 */
1436xmlAttrPtr
1437xmlCopyPropList(xmlAttrPtr cur) {
1438 xmlAttrPtr ret = NULL;
1439 xmlAttrPtr p = NULL,q;
1440
1441 while (cur != NULL) {
1442 q = xmlCopyProp(cur);
1443 if (p == NULL) {
1444 ret = p = q;
1445 } else {
1446 p->next = q;
1447 p = q;
1448 }
1449 cur = cur->next;
1450 }
1451 return(ret);
1452}
1453
1454/*
1455 * NOTE about the CopyNode operations !
1456 *
1457 * They are splitted into external and internal parts for one
1458 * tricky reason: namespaces. Doing a direct copy of a node
1459 * say RPM:Copyright without changing the namespace pointer to
1460 * something else can produce stale links. One way to do it is
1461 * to keep a reference counter but this doesn't work as soon
1462 * as one move the element or the subtree out of the scope of
1463 * the existing namespace. The actual solution seems to add
1464 * a copy of the namespace at the top of the copied tree if
1465 * not available in the subtree.
1466 * Hence two functions, the public front-end call the inner ones
1467 */
1468
1469static xmlNodePtr
1470xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent);
1471
1472static xmlNodePtr
1473xmlStaticCopyNode(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent,
1474 int recursive) {
1475 xmlNodePtr ret;
1476
1477 if (node == NULL) return(NULL);
1478 /*
1479 * Allocate a new node and fill the fields.
1480 */
1481 ret = (xmlNodePtr) malloc(sizeof(xmlNode));
1482 if (ret == NULL) {
1483 fprintf(stderr, "xmlStaticCopyNode : malloc failed\n");
1484 return(NULL);
1485 }
1486
1487 ret->type = node->type;
1488 ret->doc = doc;
1489 ret->parent = parent;
1490 ret->next = NULL;
1491 ret->prev = NULL;
1492 ret->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001493 ret->last = NULL;
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001494 ret->properties = NULL;
1495 if (node->name != NULL)
1496 ret->name = xmlStrdup(node->name);
1497 else
1498 ret->name = NULL;
1499 ret->ns = NULL;
1500 ret->nsDef = NULL;
1501 if ((node->content != NULL) && (node->type != XML_ENTITY_REF_NODE))
1502 ret->content = xmlStrdup(node->content);
1503 else
1504 ret->content = NULL;
1505#ifndef WITHOUT_CORBA
1506 ret->_private = NULL;
1507 ret->vepv = NULL;
1508#endif
1509 if (parent != NULL)
1510 xmlAddChild(parent, ret);
1511
1512 if (!recursive) return(ret);
1513 if (node->properties != NULL)
1514 ret->properties = xmlCopyPropList(node->properties);
1515 if (node->nsDef != NULL)
1516 ret->nsDef = xmlCopyNamespaceList(node->nsDef);
1517
1518 if (node->ns != NULL) {
1519 xmlNsPtr ns;
1520
1521 ns = xmlSearchNs(doc, ret, node->ns->prefix);
1522 if (ns == NULL) {
1523 /*
1524 * Humm, we are copying an element whose namespace is defined
1525 * out of the new tree scope. Search it in the original tree
1526 * and add it at the top of the new tree
1527 */
1528 ns = xmlSearchNs(node->doc, node, node->ns->prefix);
1529 if (ns != NULL) {
1530 xmlNodePtr root = ret;
1531
1532 while (root->parent != NULL) root = root->parent;
1533 xmlNewNs(root, ns->href, ns->prefix);
1534 }
1535 } else {
1536 /*
1537 * reference the existing namespace definition in our own tree.
1538 */
1539 ret->ns = ns;
1540 }
1541 }
1542 if (node->childs != NULL)
1543 ret->childs = xmlStaticCopyNodeList(node->childs, doc, ret);
Daniel Veillard1e346af1999-02-22 10:33:01 +00001544 UPDATE_LAST_CHILD(ret)
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001545 return(ret);
1546}
1547
1548static xmlNodePtr
1549xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent) {
1550 xmlNodePtr ret = NULL;
1551 xmlNodePtr p = NULL,q;
1552
1553 while (node != NULL) {
1554 q = xmlStaticCopyNode(node, doc, parent, 1);
1555 if (parent == NULL) {
1556 if (ret == NULL) ret = q;
1557 } else {
1558 if (ret == NULL) {
1559 q->prev = NULL;
1560 ret = p = q;
1561 } else {
1562 p->next = q;
1563 q->prev = p;
1564 p = q;
1565 }
1566 }
1567 node = node->next;
1568 }
1569 return(ret);
1570}
1571
1572/**
1573 * xmlCopyNode:
1574 * @node: the node
1575 * @recursive: if 1 do a recursive copy.
1576 *
1577 * Do a copy of the node.
1578 *
1579 * Returns: a new xmlNodePtr, or NULL in case of error.
1580 */
1581xmlNodePtr
1582xmlCopyNode(xmlNodePtr node, int recursive) {
1583 xmlNodePtr ret;
1584
1585 ret = xmlStaticCopyNode(node, NULL, NULL, recursive);
1586 return(ret);
1587}
1588
1589/**
1590 * xmlCopyNodeList:
1591 * @node: the first node in the list.
1592 *
1593 * Do a recursive copy of the node list.
1594 *
1595 * Returns: a new xmlNodePtr, or NULL in case of error.
1596 */
1597xmlNodePtr xmlCopyNodeList(xmlNodePtr node) {
1598 xmlNodePtr ret = xmlStaticCopyNodeList(node, NULL, NULL);
1599 return(ret);
1600}
1601
1602/**
1603 * xmlCopyElement:
1604 * @elem: the element
1605 *
1606 * Do a copy of the element definition.
1607 *
1608 * Returns: a new xmlElementPtr, or NULL in case of error.
1609xmlElementPtr
1610xmlCopyElement(xmlElementPtr elem) {
1611 xmlElementPtr ret;
1612
1613 if (elem == NULL) return(NULL);
1614 ret = xmlNewDocElement(elem->doc, elem->ns, elem->name, elem->content);
1615 if (ret == NULL) return(NULL);
1616 if (!recursive) return(ret);
1617 if (elem->properties != NULL)
1618 ret->properties = xmlCopyPropList(elem->properties);
1619
1620 if (elem->nsDef != NULL)
1621 ret->nsDef = xmlCopyNamespaceList(elem->nsDef);
1622 if (elem->childs != NULL)
1623 ret->childs = xmlCopyElementList(elem->childs);
1624 return(ret);
1625}
1626 */
1627
1628/**
1629 * xmlCopyDtd:
1630 * @dtd: the dtd
1631 *
1632 * Do a copy of the dtd.
1633 *
1634 * Returns: a new xmlDtdPtr, or NULL in case of error.
1635 */
1636xmlDtdPtr
1637xmlCopyDtd(xmlDtdPtr dtd) {
1638 xmlDtdPtr ret;
1639
1640 if (dtd == NULL) return(NULL);
1641 ret = xmlNewDtd(NULL, dtd->name, dtd->ExternalID, dtd->SystemID);
1642 if (ret == NULL) return(NULL);
1643 if (dtd->entities != NULL)
1644 ret->entities = (void *) xmlCopyEntitiesTable(
1645 (xmlEntitiesTablePtr) dtd->entities);
Daniel Veillard1e346af1999-02-22 10:33:01 +00001646 if (dtd->notations != NULL)
1647 ret->notations = (void *) xmlCopyNotationTable(
1648 (xmlNotationTablePtr) dtd->notations);
1649 if (dtd->elements != NULL)
1650 ret->elements = (void *) xmlCopyElementTable(
1651 (xmlElementTablePtr) dtd->elements);
1652 if (dtd->attributes != NULL)
1653 ret->attributes = (void *) xmlCopyAttributeTable(
1654 (xmlAttributeTablePtr) dtd->attributes);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001655 /*
1656 * TODO: support for Element definitions.
1657 */
1658 return(ret);
1659}
1660
1661/**
1662 * xmlCopyDoc:
1663 * @doc: the document
1664 * @recursive: if 1 do a recursive copy.
1665 *
1666 * Do a copy of the document info. If recursive, the content tree will
1667 * be copied too as well as Dtd, namespaces and entities.
1668 *
1669 * Returns: a new xmlDocPtr, or NULL in case of error.
1670 */
1671xmlDocPtr
1672xmlCopyDoc(xmlDocPtr doc, int recursive) {
1673 xmlDocPtr ret;
1674
1675 if (doc == NULL) return(NULL);
1676 ret = xmlNewDoc(doc->version);
1677 if (ret == NULL) return(NULL);
1678 if (doc->name != NULL)
1679 ret->name = strdup(doc->name);
1680 if (doc->encoding != NULL)
1681 ret->encoding = xmlStrdup(doc->encoding);
1682 ret->compression = doc->compression;
1683 ret->standalone = doc->standalone;
1684 if (!recursive) return(ret);
1685
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001686 if (doc->intSubset != NULL)
1687 ret->intSubset = xmlCopyDtd(doc->intSubset);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001688 if (doc->oldNs != NULL)
1689 ret->oldNs = xmlCopyNamespaceList(doc->oldNs);
1690 if (doc->root != NULL)
1691 ret->root = xmlStaticCopyNodeList(doc->root, ret, NULL);
1692 return(ret);
1693}
1694
1695/************************************************************************
1696 * *
Daniel Veillard260a68f1998-08-13 03:39:55 +00001697 * Content access functions *
1698 * *
1699 ************************************************************************/
1700
Daniel Veillard97b58771998-10-20 06:14:16 +00001701/**
Daniel Veillard16253641998-10-28 22:58:05 +00001702 * xmlNodeGetContent:
1703 * @cur: the node being read
1704 *
1705 * Read the value of a node, this can be either the text carried
1706 * directly by this node if it's a TEXT node or the aggregate string
1707 * of the values carried by this node child's (TEXT and ENTITY_REF).
1708 * Entity references are substitued.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001709 * Returns a new CHAR * or NULL if no content is available.
Daniel Veillard5099ae81999-04-21 20:12:07 +00001710 * It's up to the caller to free the memory.
Daniel Veillard16253641998-10-28 22:58:05 +00001711 */
1712CHAR *
1713xmlNodeGetContent(xmlNodePtr cur) {
1714 if (cur == NULL) return(NULL);
1715 switch (cur->type) {
1716 case XML_DOCUMENT_FRAG_NODE:
1717 case XML_ELEMENT_NODE:
1718 return(xmlNodeListGetString(cur->doc, cur->childs, 1));
1719 break;
1720 case XML_ATTRIBUTE_NODE:
1721 case XML_CDATA_SECTION_NODE:
1722 case XML_ENTITY_REF_NODE:
1723 case XML_ENTITY_NODE:
1724 case XML_PI_NODE:
1725 case XML_COMMENT_NODE:
1726 case XML_DOCUMENT_NODE:
1727 case XML_DOCUMENT_TYPE_NODE:
1728 case XML_NOTATION_NODE:
1729 return(NULL);
1730 case XML_TEXT_NODE:
1731 if (cur->content != NULL)
1732 return(xmlStrdup(cur->content));
1733 return(NULL);
1734 }
1735 return(NULL);
1736}
1737
1738/**
Daniel Veillard97b58771998-10-20 06:14:16 +00001739 * xmlNodeSetContent:
1740 * @cur: the node being modified
1741 * @content: the new value of the content
1742 *
1743 * Replace the content of a node.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001744 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001745void
1746xmlNodeSetContent(xmlNodePtr cur, const CHAR *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001747 if (cur == NULL) {
1748 fprintf(stderr, "xmlNodeSetContent : node == NULL\n");
1749 return;
1750 }
Daniel Veillard16253641998-10-28 22:58:05 +00001751 switch (cur->type) {
1752 case XML_DOCUMENT_FRAG_NODE:
1753 case XML_ELEMENT_NODE:
1754 if (cur->content != NULL) {
1755 free(cur->content);
1756 cur->content = NULL;
1757 }
1758 if (cur->childs != NULL) xmlFreeNode(cur->childs);
1759 cur->childs = xmlStringGetNodeList(cur->doc, content);
Daniel Veillard1e346af1999-02-22 10:33:01 +00001760 UPDATE_LAST_CHILD(cur)
Daniel Veillard16253641998-10-28 22:58:05 +00001761 break;
1762 case XML_ATTRIBUTE_NODE:
1763 break;
1764 case XML_TEXT_NODE:
1765 case XML_CDATA_SECTION_NODE:
1766 case XML_ENTITY_REF_NODE:
1767 case XML_ENTITY_NODE:
1768 case XML_PI_NODE:
1769 case XML_COMMENT_NODE:
1770 if (cur->content != NULL) free(cur->content);
1771 if (cur->childs != NULL) xmlFreeNode(cur->childs);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001772 cur->last = cur->childs = NULL;
Daniel Veillard16253641998-10-28 22:58:05 +00001773 if (content != NULL)
1774 cur->content = xmlStrdup(content);
1775 else
1776 cur->content = NULL;
1777 case XML_DOCUMENT_NODE:
1778 case XML_DOCUMENT_TYPE_NODE:
1779 break;
1780 case XML_NOTATION_NODE:
1781 break;
1782 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00001783}
1784
Daniel Veillard97b58771998-10-20 06:14:16 +00001785/**
1786 * xmlNodeSetContentLen:
1787 * @cur: the node being modified
1788 * @content: the new value of the content
1789 * @len: the size of @content
1790 *
1791 * Replace the content of a node.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001792 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001793void
1794xmlNodeSetContentLen(xmlNodePtr cur, const CHAR *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001795 if (cur == NULL) {
Daniel Veillard16253641998-10-28 22:58:05 +00001796 fprintf(stderr, "xmlNodeSetContentLen : node == NULL\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00001797 return;
1798 }
Daniel Veillard16253641998-10-28 22:58:05 +00001799 switch (cur->type) {
1800 case XML_DOCUMENT_FRAG_NODE:
1801 case XML_ELEMENT_NODE:
1802 if (cur->content != NULL) {
1803 free(cur->content);
1804 cur->content = NULL;
1805 }
1806 if (cur->childs != NULL) xmlFreeNode(cur->childs);
1807 cur->childs = xmlStringLenGetNodeList(cur->doc, content, len);
Daniel Veillard1e346af1999-02-22 10:33:01 +00001808 UPDATE_LAST_CHILD(cur)
Daniel Veillard16253641998-10-28 22:58:05 +00001809 break;
1810 case XML_ATTRIBUTE_NODE:
1811 break;
1812 case XML_TEXT_NODE:
1813 case XML_CDATA_SECTION_NODE:
1814 case XML_ENTITY_REF_NODE:
1815 case XML_ENTITY_NODE:
1816 case XML_PI_NODE:
1817 case XML_COMMENT_NODE:
1818 if (cur->content != NULL) free(cur->content);
1819 if (cur->childs != NULL) xmlFreeNode(cur->childs);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001820 cur->childs = cur->last = NULL;
Daniel Veillard16253641998-10-28 22:58:05 +00001821 if (content != NULL)
1822 cur->content = xmlStrndup(content, len);
1823 else
1824 cur->content = NULL;
1825 case XML_DOCUMENT_NODE:
1826 case XML_DOCUMENT_TYPE_NODE:
1827 break;
1828 case XML_NOTATION_NODE:
1829 if (cur->content != NULL) free(cur->content);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001830 if (cur->childs != NULL) xmlFreeNode(cur->childs);
1831 cur->childs = cur->last = NULL;
Daniel Veillard16253641998-10-28 22:58:05 +00001832 if (content != NULL)
1833 cur->content = xmlStrndup(content, len);
1834 else
1835 cur->content = NULL;
1836 break;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001837 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00001838}
1839
Daniel Veillard97b58771998-10-20 06:14:16 +00001840/**
1841 * xmlNodeAddContentLen:
1842 * @cur: the node being modified
1843 * @content: extra content
1844 * @len: the size of @content
1845 *
1846 * Append the extra substring to the node content.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001847 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001848void
1849xmlNodeAddContentLen(xmlNodePtr cur, const CHAR *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001850 if (cur == NULL) {
Daniel Veillard16253641998-10-28 22:58:05 +00001851 fprintf(stderr, "xmlNodeAddContentLen : node == NULL\n");
1852 return;
1853 }
1854 if (len <= 0) return;
1855 switch (cur->type) {
1856 case XML_DOCUMENT_FRAG_NODE:
1857 case XML_ELEMENT_NODE: {
1858 xmlNodePtr last = NULL, new;
1859
1860 if (cur->childs != NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001861 last = cur->last;
Daniel Veillard16253641998-10-28 22:58:05 +00001862 } else {
1863 if (cur->content != NULL) {
1864 cur->childs = xmlStringGetNodeList(cur->doc, cur->content);
Daniel Veillard1e346af1999-02-22 10:33:01 +00001865 UPDATE_LAST_CHILD(cur)
Daniel Veillard16253641998-10-28 22:58:05 +00001866 free(cur->content);
1867 cur->content = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001868 last = cur->last;
Daniel Veillard16253641998-10-28 22:58:05 +00001869 }
1870 }
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001871 new = xmlNewTextLen(content, len);
Daniel Veillard16253641998-10-28 22:58:05 +00001872 if (new != NULL) {
1873 xmlAddChild(cur, new);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001874 if ((last != NULL) && (last->next == new)) {
Daniel Veillard16253641998-10-28 22:58:05 +00001875 xmlTextMerge(last, new);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001876 }
Daniel Veillard16253641998-10-28 22:58:05 +00001877 }
1878 break;
1879 }
1880 case XML_ATTRIBUTE_NODE:
1881 break;
1882 case XML_TEXT_NODE:
1883 case XML_CDATA_SECTION_NODE:
1884 case XML_ENTITY_REF_NODE:
1885 case XML_ENTITY_NODE:
1886 case XML_PI_NODE:
1887 case XML_COMMENT_NODE:
1888 if (content != NULL)
1889 cur->content = xmlStrncat(cur->content, content, len);
1890 case XML_DOCUMENT_NODE:
1891 case XML_DOCUMENT_TYPE_NODE:
1892 break;
1893 case XML_NOTATION_NODE:
1894 if (content != NULL)
1895 cur->content = xmlStrncat(cur->content, content, len);
1896 break;
1897 }
1898}
1899
1900/**
1901 * xmlNodeAddContent:
1902 * @cur: the node being modified
1903 * @content: extra content
1904 *
1905 * Append the extra substring to the node content.
1906 */
1907void
1908xmlNodeAddContent(xmlNodePtr cur, const CHAR *content) {
1909 int len;
1910
1911 if (cur == NULL) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001912 fprintf(stderr, "xmlNodeAddContent : node == NULL\n");
1913 return;
1914 }
Daniel Veillard16253641998-10-28 22:58:05 +00001915 if (content == NULL) return;
1916 len = xmlStrlen(content);
1917 xmlNodeAddContentLen(cur, content, len);
1918}
1919
1920/**
1921 * xmlTextMerge:
1922 * @first: the first text node
1923 * @second: the second text node being merged
1924 *
1925 * Merge two text nodes into one
Daniel Veillard1e346af1999-02-22 10:33:01 +00001926 * Returns the first text node augmented
Daniel Veillard16253641998-10-28 22:58:05 +00001927 */
1928xmlNodePtr
1929xmlTextMerge(xmlNodePtr first, xmlNodePtr second) {
1930 if (first == NULL) return(second);
1931 if (second == NULL) return(first);
1932 if (first->type != XML_TEXT_NODE) return(first);
1933 if (second->type != XML_TEXT_NODE) return(first);
1934 xmlNodeAddContent(first, second->content);
1935 xmlUnlinkNode(second);
1936 xmlFreeNode(second);
1937 return(first);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001938}
1939
Daniel Veillard97b58771998-10-20 06:14:16 +00001940/**
1941 * xmlSearchNs:
1942 * @doc: the document
1943 * @node: the current node
1944 * @nameSpace: the namespace string
Daniel Veillard260a68f1998-08-13 03:39:55 +00001945 *
Daniel Veillard97b58771998-10-20 06:14:16 +00001946 * Search a Ns registered under a given name space for a document.
1947 * recurse on the parents until it finds the defined namespace
1948 * or return NULL otherwise.
1949 * @nameSpace can be NULL, this is a search for the default namespace.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001950 * Returns the namespace pointer or NULL.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001951 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001952xmlNsPtr
1953xmlSearchNs(xmlDocPtr doc, xmlNodePtr node, const CHAR *nameSpace) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001954 xmlNsPtr cur;
1955
1956 while (node != NULL) {
1957 cur = node->nsDef;
1958 while (cur != NULL) {
1959 if ((cur->prefix == NULL) && (nameSpace == NULL))
1960 return(cur);
1961 if ((cur->prefix != NULL) && (nameSpace != NULL) &&
1962 (!xmlStrcmp(cur->prefix, nameSpace)))
1963 return(cur);
1964 cur = cur->next;
1965 }
1966 node = node->parent;
1967 }
1968 if (doc != NULL) {
1969 cur = doc->oldNs;
1970 while (cur != NULL) {
1971 if ((cur->prefix != NULL) && (nameSpace != NULL) &&
1972 (!xmlStrcmp(cur->prefix, nameSpace)))
1973 return(cur);
1974 cur = cur->next;
1975 }
1976 }
1977 return(NULL);
1978}
1979
Daniel Veillard97b58771998-10-20 06:14:16 +00001980/**
1981 * xmlSearchNsByHref:
1982 * @doc: the document
1983 * @node: the current node
1984 * @href: the namespace value
1985 *
1986 * Search a Ns aliasing a given URI. Recurse on the parents until it finds
1987 * the defined namespace or return NULL otherwise.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001988 * Returns the namespace pointer or NULL.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001989 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001990xmlNsPtr
1991xmlSearchNsByHref(xmlDocPtr doc, xmlNodePtr node, const CHAR *href) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001992 xmlNsPtr cur;
1993
1994 while (node != NULL) {
1995 cur = node->nsDef;
1996 while (cur != NULL) {
1997 if ((cur->href != NULL) && (href != NULL) &&
1998 (!xmlStrcmp(cur->href, href)))
1999 return(cur);
2000 cur = cur->next;
2001 }
2002 node = node->parent;
2003 }
2004 if (doc != NULL) {
2005 cur = doc->oldNs;
2006 while (cur != NULL) {
2007 if ((cur->href != NULL) && (href != NULL) &&
2008 (!xmlStrcmp(cur->href, href)))
2009 return(cur);
2010 cur = cur->next;
2011 }
2012 }
2013 return(NULL);
2014}
2015
Daniel Veillard97b58771998-10-20 06:14:16 +00002016/**
2017 * xmlGetProp:
2018 * @node: the node
2019 * @name: the attribute name
2020 *
2021 * Search and get the value of an attribute associated to a node
Daniel Veillardccb09631998-10-27 06:21:04 +00002022 * This does the entity substitution.
Daniel Veillard1e346af1999-02-22 10:33:01 +00002023 * Returns the attribute value or NULL if not found.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002024 */
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002025CHAR *xmlGetProp(xmlNodePtr node, const CHAR *name) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002026 xmlAttrPtr prop = node->properties;
2027
2028 while (prop != NULL) {
Daniel Veillard68178931999-02-08 18:34:36 +00002029 if (!xmlStrcmp(prop->name, name)) {
Daniel Veillard6800ef31999-02-08 18:33:22 +00002030 CHAR *ret;
2031
2032 ret = xmlNodeListGetString(node->doc, prop->val, 1);
2033 if (ret == NULL) return(xmlStrdup(""));
2034 return(ret);
Daniel Veillard68178931999-02-08 18:34:36 +00002035 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002036 prop = prop->next;
2037 }
2038 return(NULL);
2039}
2040
Daniel Veillard97b58771998-10-20 06:14:16 +00002041/**
Daniel Veillardccb09631998-10-27 06:21:04 +00002042 * xmlSetProp:
Daniel Veillard97b58771998-10-20 06:14:16 +00002043 * @node: the node
2044 * @name: the attribute name
2045 * @value: the attribute value
2046 *
2047 * Set (or reset) an attribute carried by a node.
Daniel Veillard1e346af1999-02-22 10:33:01 +00002048 * Returns the attribute pointer.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002049 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002050xmlAttrPtr
2051xmlSetProp(xmlNodePtr node, const CHAR *name, const CHAR *value) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002052 xmlAttrPtr prop = node->properties;
2053
2054 while (prop != NULL) {
2055 if (!xmlStrcmp(prop->name, name)) {
Daniel Veillardccb09631998-10-27 06:21:04 +00002056 if (prop->val != NULL)
2057 xmlFreeNode(prop->val);
2058 prop->val = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002059 if (value != NULL)
Daniel Veillardccb09631998-10-27 06:21:04 +00002060 prop->val = xmlStringGetNodeList(node->doc, value);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002061 return(prop);
2062 }
2063 prop = prop->next;
2064 }
2065 prop = xmlNewProp(node, name, value);
2066 return(prop);
2067}
2068
Daniel Veillard97b58771998-10-20 06:14:16 +00002069/**
2070 * xmlNodeIsText:
2071 * @node: the node
2072 *
2073 * Is this node a Text node ?
Daniel Veillard1e346af1999-02-22 10:33:01 +00002074 * Returns 1 yes, 0 no
Daniel Veillard260a68f1998-08-13 03:39:55 +00002075 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002076int
2077xmlNodeIsText(xmlNodePtr node) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002078 if (node == NULL) return(0);
2079
Daniel Veillard0bef1311998-10-14 02:36:47 +00002080 if (node->type == XML_TEXT_NODE) return(1);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002081 return(0);
2082}
2083
Daniel Veillard97b58771998-10-20 06:14:16 +00002084/**
Daniel Veillard1e346af1999-02-22 10:33:01 +00002085 * xmlTextConcat:
Daniel Veillard97b58771998-10-20 06:14:16 +00002086 * @node: the node
2087 * @content: the content
2088 * @len: @content lenght
2089 *
2090 * Concat the given string at the end of the existing node content
Daniel Veillard260a68f1998-08-13 03:39:55 +00002091 */
Daniel Veillard97b58771998-10-20 06:14:16 +00002092
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002093void
2094xmlTextConcat(xmlNodePtr node, const CHAR *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002095 if (node == NULL) return;
2096
Daniel Veillard0bef1311998-10-14 02:36:47 +00002097 if (node->type != XML_TEXT_NODE) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002098 fprintf(stderr, "xmlTextConcat: node is not text\n");
2099 return;
2100 }
2101 node->content = xmlStrncat(node->content, content, len);
2102}
2103
2104/************************************************************************
2105 * *
2106 * Output : to a FILE or in memory *
2107 * *
2108 ************************************************************************/
2109
Daniel Veillard5099ae81999-04-21 20:12:07 +00002110#define BASE_BUFFER_SIZE 4000
2111
2112/**
2113 * xmlBufferCreate:
2114 *
2115 * routine to create an XML buffer.
2116 * returns the new structure.
2117 */
2118xmlBufferPtr
2119xmlBufferCreate(void) {
2120 xmlBufferPtr ret;
2121
2122 ret = (xmlBufferPtr) malloc(sizeof(xmlBuffer));
2123 if (ret == NULL) {
2124 fprintf(stderr, "xmlBufferCreate : out of memory!\n");
2125 return(NULL);
2126 }
2127 ret->use = 0;
2128 ret->size = BASE_BUFFER_SIZE;
2129 ret->content = (CHAR *) malloc(ret->size * sizeof(CHAR));
2130 if (ret->content == NULL) {
2131 fprintf(stderr, "xmlBufferCreate : out of memory!\n");
2132 free(ret);
2133 return(NULL);
2134 }
2135 ret->content[0] = 0;
2136 return(ret);
2137}
2138
2139/**
2140 * xmlBufferFree:
2141 * @buf: the buffer to free
2142 *
2143 * Frees an XML buffer.
2144 */
2145void
2146xmlBufferFree(xmlBufferPtr buf) {
2147 if (buf == NULL) {
2148 fprintf(stderr, "xmlBufferFree: buf == NULL\n");
2149 return;
2150 }
2151 if (buf->content == NULL) {
2152 fprintf(stderr, "xmlBufferFree: buf->content == NULL\n");
2153 } else {
2154 memset(buf->content, -1, BASE_BUFFER_SIZE);
2155 free(buf->content);
2156 }
2157 memset(buf, -1, sizeof(xmlBuffer));
2158 free(buf);
2159}
2160
2161/**
2162 * xmlBufferDump:
2163 * @file: the file output
2164 * @buf: the buffer to dump
2165 *
2166 * Dumps an XML buffer to a FILE *.
2167 * Returns the number of CHAR written
2168 */
2169int
2170xmlBufferDump(FILE *file, xmlBufferPtr buf) {
2171 int ret;
2172
2173 if (buf == NULL) {
2174 fprintf(stderr, "xmlBufferDump: buf == NULL\n");
2175 return(0);
2176 }
2177 if (buf->content == NULL) {
2178 fprintf(stderr, "xmlBufferDump: buf->content == NULL\n");
2179 return(0);
2180 }
2181 if (file == NULL) file = stdout;
2182 ret = fwrite(buf->content, sizeof(CHAR), buf->use, file);
2183 return(ret);
2184}
2185
2186/**
2187 * xmlBufferAdd:
2188 * @buf: the buffer to dump
2189 * @str: the CHAR string
2190 * @len: the number of CHAR to add
2191 *
2192 * Add a string range to an XML buffer.
2193 */
2194void
2195xmlBufferAdd(xmlBufferPtr buf, const CHAR *str, int len) {
2196 const CHAR *cur;
2197
2198 if (str == NULL) {
2199 fprintf(stderr, "xmlBufferAdd: str == NULL\n");
2200 return;
2201 }
2202 for (cur = str;(len > 0) && (*cur != 0);cur++, len--) {
2203 if (buf->use + 10 >= buf->size) {
2204 CHAR *rebuf;
2205
2206 buf->size *= 2;
2207 rebuf = (CHAR *) realloc(buf->content, buf->size * sizeof(CHAR));
2208 if (rebuf == NULL) {
2209 fprintf(stderr, "xmlBufferAdd : out of memory!\n");
2210 return;
2211 }
2212 buf->content = rebuf;
2213 }
2214 buf->content[buf->use++] = *cur;
2215 }
2216}
2217
2218/**
2219 * xmlBufferCat:
2220 * @buf: the buffer to dump
2221 * @str: the CHAR string
2222 *
2223 * Append a zero terminated string to an XML buffer.
2224 */
2225void
2226xmlBufferCat(xmlBufferPtr buf, const CHAR *str) {
2227 const CHAR *cur;
2228
2229 if (str == NULL) {
2230 fprintf(stderr, "xmlBufferAdd: str == NULL\n");
2231 return;
2232 }
2233 for (cur = str;*cur != 0;cur++) {
2234 if (buf->use + 10 >= buf->size) {
2235 CHAR *rebuf;
2236
2237 buf->size *= 2;
2238 rebuf = (CHAR *) realloc(buf->content, buf->size * sizeof(CHAR));
2239 if (rebuf == NULL) {
2240 fprintf(stderr, "xmlBufferAdd : out of memory!\n");
2241 return;
2242 }
2243 buf->content = rebuf;
2244 }
2245 buf->content[buf->use++] = *cur;
2246 }
2247}
2248
2249/**
2250 * xmlBufferCCat:
2251 * @buf: the buffer to dump
2252 * @str: the C char string
2253 *
2254 * Append a zero terminated C string to an XML buffer.
2255 */
2256void
2257xmlBufferCCat(xmlBufferPtr buf, const char *str) {
2258 const char *cur;
2259
2260 if (str == NULL) {
2261 fprintf(stderr, "xmlBufferAdd: str == NULL\n");
2262 return;
2263 }
2264 for (cur = str;*cur != 0;cur++) {
2265 if (buf->use + 10 >= buf->size) {
2266 CHAR *rebuf;
2267
2268 buf->size *= 2;
2269 rebuf = (CHAR *) realloc(buf->content, buf->size * sizeof(CHAR));
2270 if (rebuf == NULL) {
2271 fprintf(stderr, "xmlBufferAdd : out of memory!\n");
2272 return;
2273 }
2274 buf->content = rebuf;
2275 }
2276 buf->content[buf->use++] = *cur;
2277 }
2278}
Daniel Veillard260a68f1998-08-13 03:39:55 +00002279
Daniel Veillard97b58771998-10-20 06:14:16 +00002280/**
2281 * xmlBufferWriteCHAR:
Daniel Veillard5099ae81999-04-21 20:12:07 +00002282 * @buf: the XML buffer
Daniel Veillard97b58771998-10-20 06:14:16 +00002283 * @string: the string to add
2284 *
2285 * routine which manage and grows an output buffer. This one add
Daniel Veillard5099ae81999-04-21 20:12:07 +00002286 * CHARs at the end of the buffer.
Daniel Veillard97b58771998-10-20 06:14:16 +00002287 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002288void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002289xmlBufferWriteCHAR(xmlBufferPtr buf, const CHAR *string) {
2290 xmlBufferCat(buf, string);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002291}
2292
Daniel Veillard97b58771998-10-20 06:14:16 +00002293/**
2294 * xmlBufferWriteChar:
Daniel Veillard5099ae81999-04-21 20:12:07 +00002295 * @buf: the XML buffer
Daniel Veillard97b58771998-10-20 06:14:16 +00002296 * @string: the string to add
2297 *
2298 * routine which manage and grows an output buffer. This one add
2299 * C chars at the end of the array.
2300 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002301void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002302xmlBufferWriteChar(xmlBufferPtr buf, const char *string) {
2303 xmlBufferCCat(buf, string);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002304}
2305
Daniel Veillard5099ae81999-04-21 20:12:07 +00002306
Daniel Veillard97b58771998-10-20 06:14:16 +00002307/**
2308 * xmlGlobalNsDump:
2309 * @cur: a namespace
2310 *
2311 * Dump a global Namespace, this is the old version based on PIs.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002312 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002313static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002314xmlGlobalNsDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002315 if (cur == NULL) {
2316 fprintf(stderr, "xmlGlobalNsDump : Ns == NULL\n");
2317 return;
2318 }
2319 if (cur->type == XML_GLOBAL_NAMESPACE) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002320 xmlBufferWriteChar(buf, "<?namespace");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002321 if (cur->href != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002322 xmlBufferWriteChar(buf, " href=\"");
2323 xmlBufferWriteCHAR(buf, cur->href);
2324 xmlBufferWriteChar(buf, "\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002325 }
2326 if (cur->prefix != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002327 xmlBufferWriteChar(buf, " AS=\"");
2328 xmlBufferWriteCHAR(buf, cur->prefix);
2329 xmlBufferWriteChar(buf, "\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002330 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00002331 xmlBufferWriteChar(buf, "?>\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002332 }
2333}
2334
Daniel Veillard97b58771998-10-20 06:14:16 +00002335/**
2336 * xmlGlobalNsListDump:
2337 * @cur: the first namespace
2338 *
2339 * Dump a list of global Namespace, this is the old version based on PIs.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002340 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002341static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002342xmlGlobalNsListDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002343 while (cur != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002344 xmlGlobalNsDump(buf, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002345 cur = cur->next;
2346 }
2347}
2348
Daniel Veillard97b58771998-10-20 06:14:16 +00002349/**
2350 * xmlNsDump:
2351 * @cur: a namespace
2352 *
Daniel Veillard260a68f1998-08-13 03:39:55 +00002353 * Dump a local Namespace definition.
Daniel Veillard97b58771998-10-20 06:14:16 +00002354 * Should be called in the context of attributes dumps.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002355 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002356static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002357xmlNsDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002358 if (cur == NULL) {
2359 fprintf(stderr, "xmlNsDump : Ns == NULL\n");
2360 return;
2361 }
2362 if (cur->type == XML_LOCAL_NAMESPACE) {
2363 /* Within the context of an element attributes */
2364 if (cur->prefix != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002365 xmlBufferWriteChar(buf, " xmlns:");
2366 xmlBufferWriteCHAR(buf, cur->prefix);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002367 } else
Daniel Veillard5099ae81999-04-21 20:12:07 +00002368 xmlBufferWriteChar(buf, " xmlns");
2369 xmlBufferWriteChar(buf, "=\"");
2370 xmlBufferWriteCHAR(buf, cur->href);
2371 xmlBufferWriteChar(buf, "\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002372 }
2373}
2374
Daniel Veillard97b58771998-10-20 06:14:16 +00002375/**
2376 * xmlNsListDump:
2377 * @cur: the first namespace
2378 *
2379 * Dump a list of local Namespace definitions.
2380 * Should be called in the context of attributes dumps.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002381 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002382static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002383xmlNsListDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002384 while (cur != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002385 xmlNsDump(buf, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002386 cur = cur->next;
2387 }
2388}
2389
Daniel Veillard97b58771998-10-20 06:14:16 +00002390/**
2391 * xmlDtdDump:
2392 * @doc: the document
2393 *
2394 * Dump the XML document DTD, if any.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002395 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002396static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002397xmlDtdDump(xmlBufferPtr buf, xmlDocPtr doc) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002398 xmlDtdPtr cur = doc->intSubset;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002399
2400 if (cur == NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002401 fprintf(stderr, "xmlDtdDump : no internal subset\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002402 return;
2403 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00002404 xmlBufferWriteChar(buf, "<!DOCTYPE ");
2405 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002406 if (cur->ExternalID != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002407 xmlBufferWriteChar(buf, " PUBLIC \"");
2408 xmlBufferWriteCHAR(buf, cur->ExternalID);
2409 xmlBufferWriteChar(buf, "\" \"");
2410 xmlBufferWriteCHAR(buf, cur->SystemID);
2411 xmlBufferWriteChar(buf, "\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002412 } else if (cur->SystemID != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002413 xmlBufferWriteChar(buf, " SYSTEM \"");
2414 xmlBufferWriteCHAR(buf, cur->SystemID);
2415 xmlBufferWriteChar(buf, "\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002416 }
Daniel Veillard1e346af1999-02-22 10:33:01 +00002417 if ((cur->entities == NULL) && (cur->elements == NULL) &&
2418 (cur->attributes == NULL) && (cur->notations == NULL)) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002419 xmlBufferWriteChar(buf, ">\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002420 return;
2421 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00002422 xmlBufferWriteChar(buf, " [\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002423 if (cur->entities != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00002424 xmlDumpEntitiesTable(buf, (xmlEntitiesTablePtr) cur->entities);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002425 if (cur->notations != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00002426 xmlDumpNotationTable(buf, (xmlNotationTablePtr) cur->notations);
Daniel Veillard3b9def11999-01-31 22:15:06 +00002427 if (cur->elements != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00002428 xmlDumpElementTable(buf, (xmlElementTablePtr) cur->elements);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002429 if (cur->attributes != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00002430 xmlDumpAttributeTable(buf, (xmlAttributeTablePtr) cur->attributes);
2431 xmlBufferWriteChar(buf, "]");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002432
2433 /* TODO !!! a lot more things to dump ... */
Daniel Veillard5099ae81999-04-21 20:12:07 +00002434 xmlBufferWriteChar(buf, ">\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002435}
2436
Daniel Veillard97b58771998-10-20 06:14:16 +00002437/**
2438 * xmlAttrDump:
2439 * @doc: the document
2440 * @cur: the attribute pointer
2441 *
2442 * Dump an XML attribute
Daniel Veillard260a68f1998-08-13 03:39:55 +00002443 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002444static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002445xmlAttrDump(xmlBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur) {
Daniel Veillardccb09631998-10-27 06:21:04 +00002446 CHAR *value;
2447
Daniel Veillard260a68f1998-08-13 03:39:55 +00002448 if (cur == NULL) {
2449 fprintf(stderr, "xmlAttrDump : property == NULL\n");
2450 return;
2451 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00002452 xmlBufferWriteChar(buf, " ");
2453 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillardccb09631998-10-27 06:21:04 +00002454 value = xmlNodeListGetString(doc, cur->val, 0);
2455 if (value) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002456 xmlBufferWriteChar(buf, "=\"");
2457 xmlBufferWriteCHAR(buf, value);
2458 xmlBufferWriteChar(buf, "\"");
Daniel Veillardccb09631998-10-27 06:21:04 +00002459 free(value);
Daniel Veillard726c7e31999-02-08 15:13:10 +00002460 } else {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002461 xmlBufferWriteChar(buf, "=\"\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002462 }
2463}
2464
Daniel Veillard97b58771998-10-20 06:14:16 +00002465/**
2466 * xmlAttrListDump:
2467 * @doc: the document
2468 * @cur: the first attribute pointer
2469 *
2470 * Dump a list of XML attributes
Daniel Veillard260a68f1998-08-13 03:39:55 +00002471 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002472static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002473xmlAttrListDump(xmlBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002474 if (cur == NULL) {
2475 fprintf(stderr, "xmlAttrListDump : property == NULL\n");
2476 return;
2477 }
2478 while (cur != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002479 xmlAttrDump(buf, doc, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002480 cur = cur->next;
2481 }
2482}
2483
Daniel Veillard260a68f1998-08-13 03:39:55 +00002484
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002485static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002486xmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level);
Daniel Veillard97b58771998-10-20 06:14:16 +00002487/**
2488 * xmlNodeListDump:
2489 * @doc: the document
2490 * @cur: the first node
2491 * @level: the imbrication level for indenting
2492 *
2493 * Dump an XML node list, recursive behaviour,children are printed too.
2494 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002495static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002496xmlNodeListDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level) {
Daniel Veillardccb09631998-10-27 06:21:04 +00002497 int needIndent = 0, i;
2498
Daniel Veillard260a68f1998-08-13 03:39:55 +00002499 if (cur == NULL) {
2500 fprintf(stderr, "xmlNodeListDump : node == NULL\n");
2501 return;
2502 }
2503 while (cur != NULL) {
Daniel Veillardccb09631998-10-27 06:21:04 +00002504 if ((cur->type != XML_TEXT_NODE) &&
2505 (cur->type != XML_ENTITY_REF_NODE)) {
2506 if (!needIndent) {
2507 needIndent = 1;
Daniel Veillard5099ae81999-04-21 20:12:07 +00002508 xmlBufferWriteChar(buf, "\n");
Daniel Veillardccb09631998-10-27 06:21:04 +00002509 }
2510 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00002511 xmlNodeDump(buf, doc, cur, level);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002512 cur = cur->next;
2513 }
Daniel Veillardccb09631998-10-27 06:21:04 +00002514 if ((xmlIndentTreeOutput) && (needIndent))
2515 for (i = 1;i < level;i++)
Daniel Veillard5099ae81999-04-21 20:12:07 +00002516 xmlBufferWriteChar(buf, " ");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002517}
2518
Daniel Veillard97b58771998-10-20 06:14:16 +00002519/**
Daniel Veillardccb09631998-10-27 06:21:04 +00002520 * xmlNodeDump:
Daniel Veillard97b58771998-10-20 06:14:16 +00002521 * @doc: the document
2522 * @cur: the current node
2523 * @level: the imbrication level for indenting
2524 *
2525 * Dump an XML node, recursive behaviour,children are printed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002526 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002527static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002528xmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002529 int i;
2530
2531 if (cur == NULL) {
2532 fprintf(stderr, "xmlNodeDump : node == NULL\n");
2533 return;
2534 }
Daniel Veillard0bef1311998-10-14 02:36:47 +00002535 if (cur->type == XML_TEXT_NODE) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002536 if (cur->content != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00002537 xmlBufferWriteCHAR(buf, xmlEncodeEntities(doc, cur->content));
Daniel Veillard260a68f1998-08-13 03:39:55 +00002538 return;
2539 }
Daniel Veillard0bef1311998-10-14 02:36:47 +00002540 if (cur->type == XML_COMMENT_NODE) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002541 if (cur->content != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002542 xmlBufferWriteChar(buf, "<!--");
2543 xmlBufferWriteCHAR(buf, cur->content);
2544 xmlBufferWriteChar(buf, "-->");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002545 }
2546 return;
2547 }
Daniel Veillardccb09631998-10-27 06:21:04 +00002548 if (cur->type == XML_ENTITY_REF_NODE) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002549 xmlBufferWriteChar(buf, "&");
2550 xmlBufferWriteCHAR(buf, cur->name);
2551 xmlBufferWriteChar(buf, ";");
Daniel Veillardccb09631998-10-27 06:21:04 +00002552 return;
2553 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002554 if (xmlIndentTreeOutput)
2555 for (i = 0;i < level;i++)
Daniel Veillard5099ae81999-04-21 20:12:07 +00002556 xmlBufferWriteChar(buf, " ");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002557
Daniel Veillard5099ae81999-04-21 20:12:07 +00002558 xmlBufferWriteChar(buf, "<");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002559 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002560 xmlBufferWriteCHAR(buf, cur->ns->prefix);
2561 xmlBufferWriteChar(buf, ":");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002562 }
2563
Daniel Veillard5099ae81999-04-21 20:12:07 +00002564 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002565 if (cur->nsDef)
Daniel Veillard5099ae81999-04-21 20:12:07 +00002566 xmlNsListDump(buf, cur->nsDef);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002567 if (cur->properties != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00002568 xmlAttrListDump(buf, doc, cur->properties);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002569
2570 if ((cur->content == NULL) && (cur->childs == NULL)) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002571 xmlBufferWriteChar(buf, "/>\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002572 return;
2573 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00002574 xmlBufferWriteChar(buf, ">");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002575 if (cur->content != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00002576 xmlBufferWriteCHAR(buf, xmlEncodeEntities(doc, cur->content));
Daniel Veillard260a68f1998-08-13 03:39:55 +00002577 if (cur->childs != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002578 xmlNodeListDump(buf, doc, cur->childs, level + 1);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002579 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00002580 xmlBufferWriteChar(buf, "</");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002581 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002582 xmlBufferWriteCHAR(buf, cur->ns->prefix);
2583 xmlBufferWriteChar(buf, ":");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002584 }
2585
Daniel Veillard5099ae81999-04-21 20:12:07 +00002586 xmlBufferWriteCHAR(buf, cur->name);
2587 xmlBufferWriteChar(buf, ">\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002588}
2589
Daniel Veillard97b58771998-10-20 06:14:16 +00002590/**
2591 * xmlDocContentDump:
2592 * @cur: the document
2593 *
2594 * Dump an XML document.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002595 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002596static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002597xmlDocContentDump(xmlBufferPtr buf, xmlDocPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002598 if (oldXMLWDcompatibility)
Daniel Veillard5099ae81999-04-21 20:12:07 +00002599 xmlBufferWriteChar(buf, "<?XML version=\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002600 else
Daniel Veillard5099ae81999-04-21 20:12:07 +00002601 xmlBufferWriteChar(buf, "<?xml version=\"");
2602 xmlBufferWriteCHAR(buf, cur->version);
2603 xmlBufferWriteChar(buf, "\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002604 if (cur->encoding != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002605 xmlBufferWriteChar(buf, " encoding=\"");
2606 xmlBufferWriteCHAR(buf, cur->encoding);
2607 xmlBufferWriteChar(buf, "\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002608 }
2609 switch (cur->standalone) {
2610 case 0:
Daniel Veillard5099ae81999-04-21 20:12:07 +00002611 xmlBufferWriteChar(buf, " standalone=\"no\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002612 break;
2613 case 1:
Daniel Veillard5099ae81999-04-21 20:12:07 +00002614 xmlBufferWriteChar(buf, " standalone=\"yes\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002615 break;
2616 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00002617 xmlBufferWriteChar(buf, "?>\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002618 if (cur->intSubset != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00002619 xmlDtdDump(buf, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002620 if (cur->root != NULL) {
2621 /* global namespace definitions, the old way */
2622 if (oldXMLWDcompatibility)
Daniel Veillard5099ae81999-04-21 20:12:07 +00002623 xmlGlobalNsListDump(buf, cur->oldNs);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002624 else
2625 xmlUpgradeOldNs(cur);
Daniel Veillard5099ae81999-04-21 20:12:07 +00002626 xmlNodeDump(buf, cur, cur->root, 0);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002627 }
2628}
2629
Daniel Veillard97b58771998-10-20 06:14:16 +00002630/**
2631 * xmlDocDumpMemory:
2632 * @cur: the document
2633 * @mem: OUT: the memory pointer
2634 * @size: OUT: the memory lenght
2635 *
2636 * Dump an XML document in memory and return the CHAR * and it's size.
2637 * It's up to the caller to free the memory.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002638 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002639void
2640xmlDocDumpMemory(xmlDocPtr cur, CHAR**mem, int *size) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002641 xmlBufferPtr buf;
2642
Daniel Veillard260a68f1998-08-13 03:39:55 +00002643 if (cur == NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002644#ifdef DEBUG_TREE
2645 fprintf(stderr, "xmlDocDumpMemory : document == NULL\n");
2646#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00002647 *mem = NULL;
2648 *size = 0;
2649 return;
2650 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00002651 buf = xmlBufferCreate();
2652 if (buf == NULL) {
2653 *mem = NULL;
2654 *size = 0;
2655 return;
2656 }
2657 xmlDocContentDump(buf, cur);
2658 *mem = buf->content;
2659 *size = buf->use;
2660 memset(buf, -1, sizeof(xmlBuffer));
2661 free(buf);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002662}
2663
Daniel Veillard97b58771998-10-20 06:14:16 +00002664/**
2665 * xmlGetDocCompressMode:
2666 * @doc: the document
2667 *
2668 * get the compression ratio for a document, ZLIB based
Daniel Veillard1e346af1999-02-22 10:33:01 +00002669 * Returns 0 (uncompressed) to 9 (max compression)
Daniel Veillard151b1b01998-09-23 00:49:46 +00002670 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002671int
2672 xmlGetDocCompressMode (xmlDocPtr doc) {
Daniel Veillard15a8df41998-09-24 19:15:06 +00002673 if (doc == NULL) return(-1);
2674 return(doc->compression);
2675}
2676
Daniel Veillard97b58771998-10-20 06:14:16 +00002677/**
2678 * xmlSetDocCompressMode:
2679 * @doc: the document
2680 * @mode: the compression ratio
2681 *
2682 * set the compression ratio for a document, ZLIB based
2683 * Correct values: 0 (uncompressed) to 9 (max compression)
2684 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002685void
2686xmlSetDocCompressMode (xmlDocPtr doc, int mode) {
Daniel Veillard15a8df41998-09-24 19:15:06 +00002687 if (doc == NULL) return;
2688 if (mode < 0) doc->compression = 0;
2689 else if (mode > 9) doc->compression = 9;
2690 else doc->compression = mode;
2691}
2692
Daniel Veillard97b58771998-10-20 06:14:16 +00002693/**
2694 * xmlGetCompressMode:
2695 *
2696 * get the default compression mode used, ZLIB based.
Daniel Veillard1e346af1999-02-22 10:33:01 +00002697 * Returns 0 (uncompressed) to 9 (max compression)
Daniel Veillard15a8df41998-09-24 19:15:06 +00002698 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002699int
2700 xmlGetCompressMode(void) {
Daniel Veillard151b1b01998-09-23 00:49:46 +00002701 return(xmlCompressMode);
2702}
Daniel Veillard97b58771998-10-20 06:14:16 +00002703
2704/**
2705 * xmlSetCompressMode:
2706 * @mode: the compression ratio
2707 *
2708 * set the default compression mode used, ZLIB based
2709 * Correct values: 0 (uncompressed) to 9 (max compression)
2710 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002711void
2712xmlSetCompressMode(int mode) {
Daniel Veillard151b1b01998-09-23 00:49:46 +00002713 if (mode < 0) xmlCompressMode = 0;
Daniel Veillard15a8df41998-09-24 19:15:06 +00002714 else if (mode > 9) xmlCompressMode = 9;
Daniel Veillard151b1b01998-09-23 00:49:46 +00002715 else xmlCompressMode = mode;
2716}
2717
Daniel Veillard97b58771998-10-20 06:14:16 +00002718/**
2719 * xmlDocDump:
2720 * @f: the FILE*
2721 * @cur: the document
2722 *
2723 * Dump an XML document to an open FILE.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002724 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002725void
2726xmlDocDump(FILE *f, xmlDocPtr cur) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002727 xmlBufferPtr buf;
2728
Daniel Veillard260a68f1998-08-13 03:39:55 +00002729 if (cur == NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002730#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00002731 fprintf(stderr, "xmlDocDump : document == NULL\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002732#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00002733 return;
2734 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00002735 buf = xmlBufferCreate();
2736 if (buf == NULL) return;
2737 xmlDocContentDump(buf, cur);
2738 xmlBufferDump(f, buf);
2739 xmlBufferFree(buf);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002740}
2741
Daniel Veillard97b58771998-10-20 06:14:16 +00002742/**
2743 * xmlSaveFile:
2744 * @filename: the filename
2745 * @cur: the document
2746 *
2747 * Dump an XML document to a file. Will use compression if
2748 * compiled in and enabled.
2749 * returns: the number of file written or -1 in case of failure.
Daniel Veillard151b1b01998-09-23 00:49:46 +00002750 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002751int
2752xmlSaveFile(const char *filename, xmlDocPtr cur) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002753 xmlBufferPtr buf;
Daniel Veillard151b1b01998-09-23 00:49:46 +00002754#ifdef HAVE_ZLIB_H
2755 gzFile zoutput = NULL;
2756 char mode[15];
2757#endif
Daniel Veillardccb09631998-10-27 06:21:04 +00002758 FILE *output = NULL;
Daniel Veillard151b1b01998-09-23 00:49:46 +00002759 int ret;
2760
Daniel Veillard5099ae81999-04-21 20:12:07 +00002761 /*
2762 * save the content to a temp buffer.
2763 */
2764 buf = xmlBufferCreate();
2765 if (buf == NULL) return(0);
2766 xmlDocContentDump(buf, cur);
2767
Daniel Veillard151b1b01998-09-23 00:49:46 +00002768#ifdef HAVE_ZLIB_H
Daniel Veillarddc3dd9d1998-09-24 19:25:54 +00002769 if ((cur->compression > 0) && (cur->compression <= 9)) {
2770 sprintf(mode, "w%d", cur->compression);
Daniel Veillard151b1b01998-09-23 00:49:46 +00002771 zoutput = gzopen(filename, mode);
2772 }
2773 if (zoutput == NULL) {
2774#endif
2775 output = fopen(filename, "w");
2776 if (output == NULL) return(-1);
2777#ifdef HAVE_ZLIB_H
2778 }
2779#endif
2780
Daniel Veillard151b1b01998-09-23 00:49:46 +00002781#ifdef HAVE_ZLIB_H
2782 if (zoutput != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002783 ret = gzwrite(zoutput, buf->content, sizeof(CHAR) * buf->use);
Daniel Veillard151b1b01998-09-23 00:49:46 +00002784 gzclose(zoutput);
Daniel Veillard5099ae81999-04-21 20:12:07 +00002785 } else {
2786#endif
2787 ret = xmlBufferDump(output, buf);
2788 fclose(output);
2789#ifdef HAVE_ZLIB_H
Daniel Veillard151b1b01998-09-23 00:49:46 +00002790 }
2791#endif
Manish Vachharajani5e60f5a1999-05-29 03:04:30 +00002792 xmlBufferFree(buf);
Daniel Veillard151b1b01998-09-23 00:49:46 +00002793 return(ret * sizeof(CHAR));
2794}
2795