blob: 34c927a3065508ee1db44e14ff7ca38938c3e873 [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 Veillard39a1f9a1999-01-17 19:11:59 +00006 * Daniel.Veillard@w3.org
Daniel Veillard260a68f1998-08-13 03:39:55 +00007 */
8
Daniel Veillard151b1b01998-09-23 00:49:46 +00009#include "config.h"
Daniel Veillard260a68f1998-08-13 03:39:55 +000010#include <stdio.h>
11#include <ctype.h>
Seth Alvese7f12e61998-10-01 20:51:15 +000012#include <stdlib.h>
Daniel Veillard260a68f1998-08-13 03:39:55 +000013#include <string.h> /* for memset() only ! */
14
Daniel Veillard151b1b01998-09-23 00:49:46 +000015#ifdef HAVE_ZLIB_H
16#include <zlib.h>
17#endif
18
Daniel Veillard260a68f1998-08-13 03:39:55 +000019#include "tree.h"
20#include "entities.h"
Daniel Veillard3b9def11999-01-31 22:15:06 +000021#include "valid.h"
Daniel Veillard260a68f1998-08-13 03:39:55 +000022
23static CHAR xmlStringText[] = { 't', 'e', 'x', 't', 0 };
24int oldXMLWDcompatibility = 0;
25int xmlIndentTreeOutput = 1;
26
Daniel Veillard15a8df41998-09-24 19:15:06 +000027static int xmlCompressMode = 0;
28
Daniel Veillard39a1f9a1999-01-17 19:11:59 +000029#define UPDATE_LAST_CHILD(n) if ((n) != NULL) { \
30 xmlNodePtr ulccur = (n)->childs; \
31 if (ulccur == NULL) { \
32 (n)->last = NULL; \
33 } else { \
34 while (ulccur->next != NULL) ulccur = ulccur->next; \
35 (n)->last = ulccur; \
Daniel Veillard1e346af1999-02-22 10:33:01 +000036}}
Daniel Veillard39a1f9a1999-01-17 19:11:59 +000037
Daniel Veillard260a68f1998-08-13 03:39:55 +000038/************************************************************************
39 * *
40 * Allocation and deallocation of basic structures *
41 * *
42 ************************************************************************/
43
Daniel Veillard97b58771998-10-20 06:14:16 +000044/**
45 * xmlUpgradeOldNs:
46 * @doc: a document pointer
47 *
48 * Upgrade old style Namespaces (PI) and move them to the root of the document.
Daniel Veillard260a68f1998-08-13 03:39:55 +000049 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +000050void
51xmlUpgradeOldNs(xmlDocPtr doc) {
Daniel Veillard260a68f1998-08-13 03:39:55 +000052 xmlNsPtr cur;
53
54 if ((doc == NULL) || (doc->oldNs == NULL)) return;
55 if (doc->root == NULL) {
56 fprintf(stderr, "xmlUpgradeOldNs: failed no root !\n");
57 return;
58 }
59
60 cur = doc->oldNs;
61 while (cur->next != NULL) {
62 cur->type = XML_LOCAL_NAMESPACE;
63 cur = cur->next;
64 }
65 cur->type = XML_LOCAL_NAMESPACE;
66 cur->next = doc->root->nsDef;
67 doc->root->nsDef = doc->oldNs;
68 doc->oldNs = NULL;
69}
70
Daniel Veillard97b58771998-10-20 06:14:16 +000071/**
72 * xmlNewNs:
73 * @node: the element carrying the namespace
74 * @href: the URI associated
75 * @prefix: the prefix for the namespace
76 *
Daniel Veillard260a68f1998-08-13 03:39:55 +000077 * Creation of a new Namespace.
Daniel Veillard1e346af1999-02-22 10:33:01 +000078 * Returns returns a new namespace pointer
Daniel Veillard260a68f1998-08-13 03:39:55 +000079 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +000080xmlNsPtr
81xmlNewNs(xmlNodePtr node, const CHAR *href, const CHAR *prefix) {
Daniel Veillard260a68f1998-08-13 03:39:55 +000082 xmlNsPtr cur;
83
84 if (href == NULL) {
85 fprintf(stderr, "xmlNewNs: href == NULL !\n");
86 return(NULL);
87 }
88
89 /*
90 * Allocate a new DTD and fill the fields.
91 */
92 cur = (xmlNsPtr) malloc(sizeof(xmlNs));
93 if (cur == NULL) {
94 fprintf(stderr, "xmlNewNs : malloc failed\n");
95 return(NULL);
96 }
97
98 cur->type = XML_LOCAL_NAMESPACE;
99 if (href != NULL)
100 cur->href = xmlStrdup(href);
101 else
102 cur->href = NULL;
103 if (prefix != NULL)
104 cur->prefix = xmlStrdup(prefix);
105 else
106 cur->prefix = NULL;
107
108 /*
109 * Add it at the end to preserve parsing order ...
110 */
111 cur->next = NULL;
112 if (node != NULL) {
113 if (node->nsDef == NULL) {
114 node->nsDef = cur;
115 } else {
116 xmlNsPtr prev = node->nsDef;
117
118 while (prev->next != NULL) prev = prev->next;
119 prev->next = cur;
120 }
121 }
122
123 return(cur);
124}
125
Daniel Veillard97b58771998-10-20 06:14:16 +0000126/**
127 * xmlNewGlobalNs:
128 * @doc: the document carrying the namespace
129 * @href: the URI associated
130 * @prefix: the prefix for the namespace
131 *
132 * Creation of a Namespace, the old way using PI and without scoping, to AVOID.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000133 * Returns returns a new namespace pointer
Daniel Veillard260a68f1998-08-13 03:39:55 +0000134 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000135xmlNsPtr
136xmlNewGlobalNs(xmlDocPtr doc, const CHAR *href, const CHAR *prefix) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000137 xmlNsPtr cur;
138
139 /*
140 * Allocate a new DTD and fill the fields.
141 */
142 cur = (xmlNsPtr) malloc(sizeof(xmlNs));
143 if (cur == NULL) {
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000144 fprintf(stderr, "xmlNewGlobalNs : malloc failed\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +0000145 return(NULL);
146 }
147
148 cur->type = XML_GLOBAL_NAMESPACE;
149 if (href != NULL)
150 cur->href = xmlStrdup(href);
151 else
152 cur->href = NULL;
153 if (prefix != NULL)
154 cur->prefix = xmlStrdup(prefix);
155 else
156 cur->prefix = NULL;
157
158 /*
159 * Add it at the end to preserve parsing order ...
160 */
161 cur->next = NULL;
162 if (doc != NULL) {
163 if (doc->oldNs == NULL) {
164 doc->oldNs = cur;
165 } else {
166 xmlNsPtr prev = doc->oldNs;
167
168 while (prev->next != NULL) prev = prev->next;
169 prev->next = cur;
170 }
171 }
172
173 return(cur);
174}
175
Daniel Veillard97b58771998-10-20 06:14:16 +0000176/**
177 * xmlSetNs:
178 * @node: a node in the document
179 * @ns: a namespace pointer
180 *
181 * Associate a namespace to a node, a posteriori.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000182 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000183void
184xmlSetNs(xmlNodePtr node, xmlNsPtr ns) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000185 if (node == NULL) {
186 fprintf(stderr, "xmlSetNs: node == NULL\n");
187 return;
188 }
189 node->ns = ns;
190}
191
Daniel Veillard97b58771998-10-20 06:14:16 +0000192/**
193 * xmlFreeNs:
194 * @cur: the namespace pointer
195 *
196 * Free up the structures associated to a namespace
Daniel Veillard260a68f1998-08-13 03:39:55 +0000197 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000198void
199xmlFreeNs(xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000200 if (cur == NULL) {
201 fprintf(stderr, "xmlFreeNs : ns == NULL\n");
202 return;
203 }
204 if (cur->href != NULL) free((char *) cur->href);
205 if (cur->prefix != NULL) free((char *) cur->prefix);
206 memset(cur, -1, sizeof(xmlNs));
207 free(cur);
208}
209
Daniel Veillard97b58771998-10-20 06:14:16 +0000210/**
211 * xmlFreeNsList:
212 * @cur: the first namespace pointer
213 *
214 * Free up all the structures associated to the chained namespaces.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000215 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000216void
217xmlFreeNsList(xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000218 xmlNsPtr next;
219 if (cur == NULL) {
220 fprintf(stderr, "xmlFreeNsList : ns == NULL\n");
221 return;
222 }
223 while (cur != NULL) {
224 next = cur->next;
225 xmlFreeNs(cur);
226 cur = next;
227 }
228}
229
Daniel Veillard97b58771998-10-20 06:14:16 +0000230/**
231 * xmlNewDtd:
232 * @doc: the document pointer
233 * @name: the DTD name
234 * @ExternalID: the external ID
235 * @SystemID: the system ID
236 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000237 * Creation of a new DTD.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000238 * Returns a pointer to the new DTD structure
Daniel Veillard260a68f1998-08-13 03:39:55 +0000239 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000240xmlDtdPtr
241xmlNewDtd(xmlDocPtr doc, const CHAR *name,
Daniel Veillard260a68f1998-08-13 03:39:55 +0000242 const CHAR *ExternalID, const CHAR *SystemID) {
243 xmlDtdPtr cur;
244
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000245 if ((doc != NULL) && (doc->extSubset != NULL)) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000246 fprintf(stderr, "xmlNewDtd(%s): document %s already have a DTD %s\n",
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000247 /* !!! */ (char *) name, doc->name,
248 /* !!! */ (char *)doc->extSubset->name);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000249 }
250
251 /*
252 * Allocate a new DTD and fill the fields.
253 */
254 cur = (xmlDtdPtr) malloc(sizeof(xmlDtd));
255 if (cur == NULL) {
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000256 fprintf(stderr, "xmlNewDtd : malloc failed\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +0000257 return(NULL);
258 }
259
260 if (name != NULL)
261 cur->name = xmlStrdup(name);
262 else
263 cur->name = NULL;
264 if (ExternalID != NULL)
265 cur->ExternalID = xmlStrdup(ExternalID);
266 else
267 cur->ExternalID = NULL;
268 if (SystemID != NULL)
269 cur->SystemID = xmlStrdup(SystemID);
270 else
271 cur->SystemID = NULL;
Daniel Veillard1e346af1999-02-22 10:33:01 +0000272 cur->notations = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000273 cur->elements = NULL;
Daniel Veillard1e346af1999-02-22 10:33:01 +0000274 cur->attributes = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000275 cur->entities = NULL;
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000276 if (doc != NULL)
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000277 doc->extSubset = cur;
278
279 return(cur);
280}
281
282/**
283 * xmlCreateIntSubset:
284 * @doc: the document pointer
285 * @name: the DTD name
286 * @ExternalID: the external ID
287 * @SystemID: the system ID
288 *
Daniel Veillard1e346af1999-02-22 10:33:01 +0000289 * Create the internal subset of a document
290 * Returns a pointer to the new DTD structure
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000291 */
292xmlDtdPtr
293xmlCreateIntSubset(xmlDocPtr doc, const CHAR *name,
294 const CHAR *ExternalID, const CHAR *SystemID) {
295 xmlDtdPtr cur;
296
297 if ((doc != NULL) && (doc->intSubset != NULL)) {
298 fprintf(stderr,
299 "xmlCreateIntSubset(): document %s already have an internal subset\n",
300 doc->name);
301 return(NULL);
302 }
303
304 /*
305 * Allocate a new DTD and fill the fields.
306 */
307 cur = (xmlDtdPtr) malloc(sizeof(xmlDtd));
308 if (cur == NULL) {
309 fprintf(stderr, "xmlNewDtd : malloc failed\n");
310 return(NULL);
311 }
312
313 if (name != NULL)
314 cur->name = xmlStrdup(name);
315 else
316 cur->name = NULL;
317 if (ExternalID != NULL)
318 cur->ExternalID = xmlStrdup(ExternalID);
319 else
320 cur->ExternalID = NULL;
321 if (SystemID != NULL)
322 cur->SystemID = xmlStrdup(SystemID);
323 else
324 cur->SystemID = NULL;
Daniel Veillard1e346af1999-02-22 10:33:01 +0000325 cur->notations = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000326 cur->elements = NULL;
Daniel Veillard1e346af1999-02-22 10:33:01 +0000327 cur->attributes = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000328 cur->entities = NULL;
329 if (doc != NULL)
330 doc->intSubset = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000331
332 return(cur);
333}
334
Daniel Veillard97b58771998-10-20 06:14:16 +0000335/**
336 * xmlFreeDtd:
337 * @cur: the DTD structure to free up
338 *
339 * Free a DTD structure.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000340 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000341void
342xmlFreeDtd(xmlDtdPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000343 if (cur == NULL) {
344 fprintf(stderr, "xmlFreeDtd : DTD == NULL\n");
345 return;
346 }
347 if (cur->name != NULL) free((char *) cur->name);
348 if (cur->SystemID != NULL) free((char *) cur->SystemID);
349 if (cur->ExternalID != NULL) free((char *) cur->ExternalID);
Daniel Veillard1e346af1999-02-22 10:33:01 +0000350 if (cur->notations != NULL)
351 xmlFreeNotationTable((xmlNotationTablePtr) cur->notations);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000352 if (cur->elements != NULL)
Daniel Veillard3b9def11999-01-31 22:15:06 +0000353 xmlFreeElementTable((xmlElementTablePtr) cur->elements);
Daniel Veillard1e346af1999-02-22 10:33:01 +0000354 if (cur->attributes != NULL)
355 xmlFreeAttributeTable((xmlAttributeTablePtr) cur->attributes);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000356 if (cur->entities != NULL)
357 xmlFreeEntitiesTable((xmlEntitiesTablePtr) cur->entities);
358 memset(cur, -1, sizeof(xmlDtd));
359 free(cur);
360}
361
Daniel Veillard97b58771998-10-20 06:14:16 +0000362/**
363 * xmlNewDoc:
364 * @version: CHAR string giving the version of XML "1.0"
365 *
Daniel Veillard1e346af1999-02-22 10:33:01 +0000366 * Returns a new document
Daniel Veillard260a68f1998-08-13 03:39:55 +0000367 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000368xmlDocPtr
369xmlNewDoc(const CHAR *version) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000370 xmlDocPtr cur;
371
372 if (version == NULL) {
373 fprintf(stderr, "xmlNewDoc : version == NULL\n");
374 return(NULL);
375 }
376
377 /*
378 * Allocate a new document and fill the fields.
379 */
380 cur = (xmlDocPtr) malloc(sizeof(xmlDoc));
381 if (cur == NULL) {
382 fprintf(stderr, "xmlNewDoc : malloc failed\n");
383 return(NULL);
384 }
385
Daniel Veillard33942841998-10-18 19:12:41 +0000386 cur->type = XML_DOCUMENT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000387 cur->version = xmlStrdup(version);
388 cur->name = NULL;
389 cur->root = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000390 cur->intSubset = NULL;
391 cur->extSubset = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000392 cur->oldNs = NULL;
393 cur->encoding = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000394 cur->standalone = -1;
Daniel Veillard15a8df41998-09-24 19:15:06 +0000395 cur->compression = xmlCompressMode;
Daniel Veillardb96e6431999-08-29 21:02:19 +0000396 cur->ids = NULL;
Daniel Veillard27d88741999-05-29 11:51:49 +0000397#ifndef XML_WITHOUT_CORBA
Daniel Veillard27fb0751998-10-17 06:47:46 +0000398 cur->_private = NULL;
399 cur->vepv = NULL;
400#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000401 return(cur);
402}
403
Daniel Veillard97b58771998-10-20 06:14:16 +0000404/**
405 * xmlFreeDoc:
406 * @cur: pointer to the document
407 * @:
408 *
409 * Free up all the structures used by a document, tree included.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000410 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000411void
412xmlFreeDoc(xmlDocPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000413 if (cur == NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000414#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +0000415 fprintf(stderr, "xmlFreeDoc : document == NULL\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000416#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000417 return;
418 }
Daniel Veillarde2d034d1999-07-27 19:52:06 +0000419 if (cur->version != NULL) free((char *) cur->version);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000420 if (cur->name != NULL) free((char *) cur->name);
421 if (cur->encoding != NULL) free((char *) cur->encoding);
422 if (cur->root != NULL) xmlFreeNode(cur->root);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000423 if (cur->intSubset != NULL) xmlFreeDtd(cur->intSubset);
424 if (cur->extSubset != NULL) xmlFreeDtd(cur->extSubset);
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000425 if (cur->oldNs != NULL) xmlFreeNsList(cur->oldNs);
Daniel Veillardb96e6431999-08-29 21:02:19 +0000426 if (cur->ids != NULL) xmlFreeIDTable((xmlIDTablePtr) cur->ids);
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,
Daniel Veillard011b63c1999-06-02 17:44:04 +0000481 "xmlStringLenGetNodeList: unterminated entity %30s\n", q);
Daniel Veillard16253641998-10-28 22:58:05 +0000482 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);
Daniel Veillard14fff061999-06-22 21:49:07 +0000676 else {
677 CHAR *buffer;
678
679 buffer = xmlEncodeEntitiesReentrant(doc, node->content);
680 if (buffer != NULL) {
681 ret = xmlStrcat(ret, buffer);
682 free(buffer);
683 }
684 }
Daniel Veillardccb09631998-10-27 06:21:04 +0000685 } else if (node->type == XML_ENTITY_REF_NODE) {
686 if (inLine) {
687 ent = xmlGetDocEntity(doc, node->name);
688 if (ent != NULL)
689 ret = xmlStrcat(ret, ent->content);
690 else
691 ret = xmlStrcat(ret, node->content);
692 } else {
693 CHAR buf[2];
694 buf[0] = '&'; buf[1] = 0;
695 ret = xmlStrncat(ret, buf, 1);
696 ret = xmlStrcat(ret, node->name);
697 buf[0] = ';'; buf[1] = 0;
698 ret = xmlStrncat(ret, buf, 1);
699 }
700 }
701#if 0
702 else {
703 fprintf(stderr, "xmlGetNodeListString : invalide node type %d\n",
704 node->type);
705 }
706#endif
707 node = node->next;
708 }
709 return(ret);
710}
711
712/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000713 * xmlNewProp:
714 * @node: the holding node
715 * @name: the name of the attribute
716 * @value: the value of the attribute
717 *
718 * Create a new property carried by a node.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000719 * Returns a pointer to the attribute
Daniel Veillard260a68f1998-08-13 03:39:55 +0000720 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000721xmlAttrPtr
722xmlNewProp(xmlNodePtr node, const CHAR *name, const CHAR *value) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000723 xmlAttrPtr cur;
724
725 if (name == NULL) {
726 fprintf(stderr, "xmlNewProp : name == NULL\n");
727 return(NULL);
728 }
729
730 /*
731 * Allocate a new property and fill the fields.
732 */
733 cur = (xmlAttrPtr) malloc(sizeof(xmlAttr));
734 if (cur == NULL) {
735 fprintf(stderr, "xmlNewProp : malloc failed\n");
736 return(NULL);
737 }
738
Daniel Veillard33942841998-10-18 19:12:41 +0000739 cur->type = XML_ATTRIBUTE_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000740 cur->node = node;
Daniel Veillardb96e6431999-08-29 21:02:19 +0000741 cur->ns = NULL;
742 cur->name = xmlStrdup(name);
743 if (value != NULL)
744 cur->val = xmlStringGetNodeList(node->doc, value);
745 else
746 cur->val = NULL;
747#ifndef XML_WITHOUT_CORBA
748 cur->_private = NULL;
749 cur->vepv = NULL;
750#endif
751
752 /*
753 * Add it at the end to preserve parsing order ...
754 */
755 cur->next = NULL;
756 if (node != NULL) {
757 if (node->properties == NULL) {
758 node->properties = cur;
759 } else {
760 xmlAttrPtr prev = node->properties;
761
762 while (prev->next != NULL) prev = prev->next;
763 prev->next = cur;
764 }
765 }
766 return(cur);
767}
768
769/**
770 * xmlNewNsProp:
771 * @node: the holding node
772 * @ns: the namespace
773 * @name: the name of the attribute
774 * @value: the value of the attribute
775 *
776 * Create a new property tagged with a namespace and carried by a node.
777 * Returns a pointer to the attribute
778 */
779xmlAttrPtr
780xmlNewNsProp(xmlNodePtr node, xmlNsPtr ns, const CHAR *name,
781 const CHAR *value) {
782 xmlAttrPtr cur;
783
784 if (name == NULL) {
785 fprintf(stderr, "xmlNewProp : name == NULL\n");
786 return(NULL);
787 }
788
789 /*
790 * Allocate a new property and fill the fields.
791 */
792 cur = (xmlAttrPtr) malloc(sizeof(xmlAttr));
793 if (cur == NULL) {
794 fprintf(stderr, "xmlNewProp : malloc failed\n");
795 return(NULL);
796 }
797
798 cur->type = XML_ATTRIBUTE_NODE;
799 cur->node = node;
800 cur->ns = ns;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000801 cur->name = xmlStrdup(name);
802 if (value != NULL)
Daniel Veillardccb09631998-10-27 06:21:04 +0000803 cur->val = xmlStringGetNodeList(node->doc, value);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000804 else
Daniel Veillardccb09631998-10-27 06:21:04 +0000805 cur->val = NULL;
Daniel Veillard27d88741999-05-29 11:51:49 +0000806#ifndef XML_WITHOUT_CORBA
Daniel Veillard27fb0751998-10-17 06:47:46 +0000807 cur->_private = NULL;
808 cur->vepv = NULL;
809#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000810
811 /*
812 * Add it at the end to preserve parsing order ...
813 */
814 cur->next = NULL;
815 if (node != NULL) {
816 if (node->properties == NULL) {
817 node->properties = cur;
818 } else {
819 xmlAttrPtr prev = node->properties;
820
821 while (prev->next != NULL) prev = prev->next;
822 prev->next = cur;
823 }
824 }
825 return(cur);
826}
827
Daniel Veillard97b58771998-10-20 06:14:16 +0000828/**
Daniel Veillardccb09631998-10-27 06:21:04 +0000829 * xmlNewDocProp:
830 * @doc: the document
831 * @name: the name of the attribute
832 * @value: the value of the attribute
833 *
834 * Create a new property carried by a document.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000835 * Returns a pointer to the attribute
Daniel Veillardccb09631998-10-27 06:21:04 +0000836 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000837xmlAttrPtr
838xmlNewDocProp(xmlDocPtr doc, const CHAR *name, const CHAR *value) {
Daniel Veillardccb09631998-10-27 06:21:04 +0000839 xmlAttrPtr cur;
840
841 if (name == NULL) {
842 fprintf(stderr, "xmlNewProp : name == NULL\n");
843 return(NULL);
844 }
845
846 /*
847 * Allocate a new property and fill the fields.
848 */
849 cur = (xmlAttrPtr) malloc(sizeof(xmlAttr));
850 if (cur == NULL) {
851 fprintf(stderr, "xmlNewProp : malloc failed\n");
852 return(NULL);
853 }
854
855 cur->type = XML_ATTRIBUTE_NODE;
856 cur->node = NULL;
857 cur->name = xmlStrdup(name);
858 if (value != NULL)
859 cur->val = xmlStringGetNodeList(doc, value);
860 else
861 cur->val = NULL;
Daniel Veillard27d88741999-05-29 11:51:49 +0000862#ifndef XML_WITHOUT_CORBA
Daniel Veillardccb09631998-10-27 06:21:04 +0000863 cur->_private = NULL;
864 cur->vepv = NULL;
865#endif
866
867 cur->next = NULL;
868 return(cur);
869}
870
871/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000872 * xmlFreePropList:
873 * @cur: the first property in the list
874 *
875 * Free a property and all its siblings, all the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000876 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000877void
878xmlFreePropList(xmlAttrPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000879 xmlAttrPtr next;
880 if (cur == NULL) {
881 fprintf(stderr, "xmlFreePropList : property == NULL\n");
882 return;
883 }
884 while (cur != NULL) {
885 next = cur->next;
886 xmlFreeProp(cur);
887 cur = next;
888 }
889}
890
Daniel Veillard97b58771998-10-20 06:14:16 +0000891/**
892 * xmlFreeProp:
893 * @cur: the first property in the list
894 *
895 * Free one property, all the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000896 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000897void
898xmlFreeProp(xmlAttrPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000899 if (cur == NULL) {
900 fprintf(stderr, "xmlFreeProp : property == NULL\n");
901 return;
902 }
903 if (cur->name != NULL) free((char *) cur->name);
Daniel Veillardccb09631998-10-27 06:21:04 +0000904 if (cur->val != NULL) xmlFreeNodeList(cur->val);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000905 memset(cur, -1, sizeof(xmlAttr));
906 free(cur);
907}
908
Daniel Veillard97b58771998-10-20 06:14:16 +0000909/**
Daniel Veillardb96e6431999-08-29 21:02:19 +0000910 * xmlNewPI:
911 * @name: the processing instruction name
912 * @content: the PI content
913 *
914 * Creation of a processing instruction element.
915 * Returns a pointer to the new node object.
916 */
917xmlNodePtr
918xmlNewPI(const CHAR *name, const CHAR *content) {
919 xmlNodePtr cur;
920
921 if (name == NULL) {
922 fprintf(stderr, "xmlNewPI : name == NULL\n");
923 return(NULL);
924 }
925
926 /*
927 * Allocate a new node and fill the fields.
928 */
929 cur = (xmlNodePtr) malloc(sizeof(xmlNode));
930 if (cur == NULL) {
931 fprintf(stderr, "xmlNewPI : malloc failed\n");
932 return(NULL);
933 }
934
935 cur->type = XML_PI_NODE;
936 cur->doc = NULL;
937 cur->parent = NULL;
938 cur->next = NULL;
939 cur->prev = NULL;
940 cur->childs = NULL;
941 cur->last = NULL;
942 cur->properties = NULL;
943 cur->name = xmlStrdup(name);
944 cur->ns = NULL;
945 cur->nsDef = NULL;
946 if (content != NULL)
947 cur->content = xmlStrdup(content);
948 else
949 cur->content = NULL;
950#ifndef XML_WITHOUT_CORBA
951 cur->_private = NULL;
952 cur->vepv = NULL;
953#endif
954 return(cur);
955}
956
957/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000958 * xmlNewNode:
959 * @ns: namespace if any
960 * @name: the node name
Daniel Veillard97b58771998-10-20 06:14:16 +0000961 *
962 * Creation of a new node element. @ns and @content are optionnal (NULL).
Daniel Veillardccb09631998-10-27 06:21:04 +0000963 * If content is non NULL, a child list containing the TEXTs and
964 * ENTITY_REFs node will be created.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000965 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000966 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000967xmlNodePtr
968xmlNewNode(xmlNsPtr ns, const CHAR *name) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000969 xmlNodePtr cur;
970
971 if (name == NULL) {
972 fprintf(stderr, "xmlNewNode : name == NULL\n");
973 return(NULL);
974 }
975
976 /*
977 * Allocate a new node and fill the fields.
978 */
979 cur = (xmlNodePtr) malloc(sizeof(xmlNode));
980 if (cur == NULL) {
981 fprintf(stderr, "xmlNewNode : malloc failed\n");
982 return(NULL);
983 }
984
Daniel Veillard33942841998-10-18 19:12:41 +0000985 cur->type = XML_ELEMENT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000986 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000987 cur->parent = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000988 cur->next = NULL;
989 cur->prev = NULL;
990 cur->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000991 cur->last = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +0000992 cur->properties = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000993 cur->name = xmlStrdup(name);
994 cur->ns = ns;
995 cur->nsDef = NULL;
Daniel Veillardccb09631998-10-27 06:21:04 +0000996 cur->content = NULL;
Daniel Veillard27d88741999-05-29 11:51:49 +0000997#ifndef XML_WITHOUT_CORBA
Daniel Veillard27fb0751998-10-17 06:47:46 +0000998 cur->_private = NULL;
999 cur->vepv = NULL;
1000#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001001 return(cur);
1002}
1003
Daniel Veillard97b58771998-10-20 06:14:16 +00001004/**
1005 * xmlNewDocNode:
1006 * @doc: the document
1007 * @ns: namespace if any
1008 * @name: the node name
1009 * @content: the text content if any
1010 *
1011 * Creation of a new node element within a document. @ns and @content
1012 * are optionnal (NULL).
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
1016xmlNewDocNode(xmlDocPtr doc, xmlNsPtr ns,
Daniel Veillard15b75af1999-07-26 16:42:37 +00001017 const CHAR *name, const CHAR *content) {
Daniel Veillard0bef1311998-10-14 02:36:47 +00001018 xmlNodePtr cur;
1019
Daniel Veillardccb09631998-10-27 06:21:04 +00001020 cur = xmlNewNode(ns, name);
1021 if (cur != NULL) {
1022 cur->doc = doc;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001023 if (content != NULL) {
Daniel Veillardccb09631998-10-27 06:21:04 +00001024 cur->childs = xmlStringGetNodeList(doc, content);
Daniel Veillard1e346af1999-02-22 10:33:01 +00001025 UPDATE_LAST_CHILD(cur)
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001026 }
Daniel Veillardccb09631998-10-27 06:21:04 +00001027 }
Daniel Veillard0bef1311998-10-14 02:36:47 +00001028 return(cur);
1029}
1030
1031
Daniel Veillard97b58771998-10-20 06:14:16 +00001032/**
1033 * xmlNewText:
1034 * @content: the text content
1035 *
1036 * Creation of a new text node.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001037 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001038 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001039xmlNodePtr
1040xmlNewText(const CHAR *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001041 xmlNodePtr cur;
1042
1043 /*
1044 * Allocate a new node and fill the fields.
1045 */
1046 cur = (xmlNodePtr) malloc(sizeof(xmlNode));
1047 if (cur == NULL) {
1048 fprintf(stderr, "xmlNewText : malloc failed\n");
1049 return(NULL);
1050 }
1051
Daniel Veillard33942841998-10-18 19:12:41 +00001052 cur->type = XML_TEXT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001053 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001054 cur->parent = NULL;
1055 cur->next = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001056 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001057 cur->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001058 cur->last = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001059 cur->properties = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001060 cur->type = XML_TEXT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001061 cur->name = xmlStrdup(xmlStringText);
1062 cur->ns = NULL;
1063 cur->nsDef = NULL;
1064 if (content != NULL)
1065 cur->content = xmlStrdup(content);
1066 else
1067 cur->content = NULL;
1068 return(cur);
1069}
1070
Daniel Veillard97b58771998-10-20 06:14:16 +00001071/**
Daniel Veillardccb09631998-10-27 06:21:04 +00001072 * xmlNewReference:
1073 * @doc: the document
1074 * @name: the reference name, or the reference string with & and ;
1075 *
1076 * Creation of a new reference node.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001077 * Returns a pointer to the new node object.
Daniel Veillardccb09631998-10-27 06:21:04 +00001078 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001079xmlNodePtr
1080xmlNewReference(xmlDocPtr doc, const CHAR *name) {
Daniel Veillardccb09631998-10-27 06:21:04 +00001081 xmlNodePtr cur;
1082 xmlEntityPtr ent;
1083
1084 /*
1085 * Allocate a new node and fill the fields.
1086 */
1087 cur = (xmlNodePtr) malloc(sizeof(xmlNode));
1088 if (cur == NULL) {
1089 fprintf(stderr, "xmlNewText : malloc failed\n");
1090 return(NULL);
1091 }
1092
1093 cur->type = XML_ENTITY_REF_NODE;
Daniel Veillard10c6a8f1998-10-28 01:00:12 +00001094 cur->doc = doc;
Daniel Veillardccb09631998-10-27 06:21:04 +00001095 cur->parent = NULL;
1096 cur->next = NULL;
1097 cur->prev = NULL;
1098 cur->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001099 cur->last = NULL;
Daniel Veillardccb09631998-10-27 06:21:04 +00001100 cur->properties = NULL;
1101 if (name[0] == '&') {
1102 int len;
1103 name++;
1104 len = xmlStrlen(name);
1105 if (name[len - 1] == ';')
1106 cur->name = xmlStrndup(name, len - 1);
1107 else
1108 cur->name = xmlStrndup(name, len);
1109 } else
1110 cur->name = xmlStrdup(name);
1111 cur->ns = NULL;
1112 cur->nsDef = NULL;
1113
1114 ent = xmlGetDocEntity(doc, cur->name);
1115 if (ent != NULL)
1116 cur->content = ent->content;
1117 else
1118 cur->content = NULL;
1119 return(cur);
1120}
1121
1122/**
Daniel Veillard97b58771998-10-20 06:14:16 +00001123 * xmlNewDocText:
1124 * @doc: the document
1125 * @content: the text content
1126 *
1127 * Creation of a new text node within 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
1131xmlNewDocText(xmlDocPtr doc, const CHAR *content) {
Daniel Veillard0bef1311998-10-14 02:36:47 +00001132 xmlNodePtr cur;
1133
1134 cur = xmlNewText(content);
1135 if (cur != NULL) cur->doc = doc;
1136 return(cur);
1137}
1138
Daniel Veillard97b58771998-10-20 06:14:16 +00001139/**
Daniel Veillardccb09631998-10-27 06:21:04 +00001140 * xmlNewTextLen:
Daniel Veillard97b58771998-10-20 06:14:16 +00001141 * @content: the text content
1142 * @len: the text len.
1143 *
1144 * Creation of a new text node with an extra parameter for the content's lenght
Daniel Veillard1e346af1999-02-22 10:33:01 +00001145 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001146 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001147xmlNodePtr
1148xmlNewTextLen(const CHAR *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001149 xmlNodePtr cur;
1150
1151 /*
1152 * Allocate a new node and fill the fields.
1153 */
1154 cur = (xmlNodePtr) malloc(sizeof(xmlNode));
1155 if (cur == NULL) {
1156 fprintf(stderr, "xmlNewText : malloc failed\n");
1157 return(NULL);
1158 }
1159
Daniel Veillard33942841998-10-18 19:12:41 +00001160 cur->type = XML_TEXT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001161 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001162 cur->parent = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001163 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001164 cur->next = NULL;
1165 cur->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001166 cur->last = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001167 cur->properties = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001168 cur->type = XML_TEXT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001169 cur->name = xmlStrdup(xmlStringText);
1170 cur->ns = NULL;
1171 cur->nsDef = NULL;
1172 if (content != NULL)
1173 cur->content = xmlStrndup(content, len);
1174 else
1175 cur->content = NULL;
1176 return(cur);
1177}
1178
Daniel Veillard97b58771998-10-20 06:14:16 +00001179/**
1180 * xmlNewDocTextLen:
1181 * @doc: the document
1182 * @content: the text content
1183 * @len: the text len.
1184 *
1185 * Creation of a new text node with an extra content lenght parameter. The
1186 * text node pertain to a given document.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001187 * Returns a pointer to the new node object.
Daniel Veillard97b58771998-10-20 06:14:16 +00001188 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001189xmlNodePtr
1190xmlNewDocTextLen(xmlDocPtr doc, const CHAR *content, int len) {
Daniel Veillard0bef1311998-10-14 02:36:47 +00001191 xmlNodePtr cur;
1192
1193 cur = xmlNewTextLen(content, len);
1194 if (cur != NULL) cur->doc = doc;
1195 return(cur);
1196}
1197
Daniel Veillard97b58771998-10-20 06:14:16 +00001198/**
1199 * xmlNewComment:
1200 * @content: the comment content
1201 *
1202 * Creation of a new node containing a comment.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001203 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001204 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001205xmlNodePtr
Daniel Veillard517752b1999-04-05 12:20:10 +00001206xmlNewComment(const CHAR *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001207 xmlNodePtr cur;
1208
1209 /*
1210 * Allocate a new node and fill the fields.
1211 */
1212 cur = (xmlNodePtr) malloc(sizeof(xmlNode));
1213 if (cur == NULL) {
1214 fprintf(stderr, "xmlNewComment : malloc failed\n");
1215 return(NULL);
1216 }
1217
Daniel Veillard33942841998-10-18 19:12:41 +00001218 cur->type = XML_COMMENT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001219 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001220 cur->parent = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001221 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001222 cur->next = NULL;
1223 cur->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001224 cur->last = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001225 cur->properties = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001226 cur->type = XML_COMMENT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001227 cur->name = xmlStrdup(xmlStringText);
1228 cur->ns = NULL;
1229 cur->nsDef = NULL;
1230 if (content != NULL)
1231 cur->content = xmlStrdup(content);
1232 else
1233 cur->content = NULL;
1234 return(cur);
1235}
1236
Daniel Veillard97b58771998-10-20 06:14:16 +00001237/**
Daniel Veillardb05deb71999-08-10 19:04:08 +00001238 * xmlNewCDataBlock:
1239 * @doc: the document
1240 * @content: the CData block content content
1241 * @len: the length of the block
1242 *
1243 * Creation of a new node containing a CData block.
1244 * Returns a pointer to the new node object.
1245 */
1246xmlNodePtr
1247xmlNewCDataBlock(xmlDocPtr doc, const CHAR *content, int len) {
1248 xmlNodePtr cur;
1249
1250 /*
1251 * Allocate a new node and fill the fields.
1252 */
1253 cur = (xmlNodePtr) malloc(sizeof(xmlNode));
1254 if (cur == NULL) {
1255 fprintf(stderr, "xmlNewCDataBlock : malloc failed\n");
1256 return(NULL);
1257 }
1258
1259 cur->type = XML_CDATA_SECTION_NODE;
1260 cur->doc = NULL;
1261 cur->parent = NULL;
1262 cur->prev = NULL;
1263 cur->next = NULL;
1264 cur->childs = NULL;
1265 cur->last = NULL;
1266 cur->properties = NULL;
1267 cur->name = xmlStrdup(xmlStringText);
1268 cur->ns = NULL;
1269 cur->nsDef = NULL;
1270 if ((content != NULL) && (len > 0)) {
1271 cur->content = xmlStrndup(content, len);
1272 } else
1273 cur->content = NULL;
1274 return(cur);
1275}
1276
1277/**
Daniel Veillard1e346af1999-02-22 10:33:01 +00001278 * xmlNewDocComment:
Daniel Veillard97b58771998-10-20 06:14:16 +00001279 * @doc: the document
1280 * @content: the comment content
1281 *
1282 * Creation of a new node containing a commentwithin a document.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001283 * Returns a pointer to the new node object.
Daniel Veillard97b58771998-10-20 06:14:16 +00001284 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001285xmlNodePtr
Daniel Veillard517752b1999-04-05 12:20:10 +00001286xmlNewDocComment(xmlDocPtr doc, const CHAR *content) {
Daniel Veillard0bef1311998-10-14 02:36:47 +00001287 xmlNodePtr cur;
1288
1289 cur = xmlNewComment(content);
1290 if (cur != NULL) cur->doc = doc;
1291 return(cur);
1292}
1293
Daniel Veillard97b58771998-10-20 06:14:16 +00001294/**
1295 * xmlNewChild:
1296 * @parent: the parent node
1297 * @ns: a namespace if any
1298 * @name: the name of the child
1299 * @content: the content of the child if any.
1300 *
1301 *
1302 * Creation of a new child element, added at the end of @parent childs list.
Daniel Veillardccb09631998-10-27 06:21:04 +00001303 * @ns and @content parameters are optionnal (NULL). If content is non NULL,
1304 * a child list containing the TEXTs and ENTITY_REFs node will be created.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001305 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001306 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001307xmlNodePtr
1308xmlNewChild(xmlNodePtr parent, xmlNsPtr ns,
Daniel Veillard15b75af1999-07-26 16:42:37 +00001309 const CHAR *name, const CHAR *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001310 xmlNodePtr cur, prev;
1311
1312 if (parent == NULL) {
1313 fprintf(stderr, "xmlNewChild : parent == NULL\n");
1314 return(NULL);
1315 }
1316
1317 if (name == NULL) {
1318 fprintf(stderr, "xmlNewChild : name == NULL\n");
1319 return(NULL);
1320 }
1321
1322 /*
1323 * Allocate a new node
1324 */
1325 if (ns == NULL)
Daniel Veillardccb09631998-10-27 06:21:04 +00001326 cur = xmlNewDocNode(parent->doc, parent->ns, name, content);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001327 else
Daniel Veillardccb09631998-10-27 06:21:04 +00001328 cur = xmlNewDocNode(parent->doc, ns, name, content);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001329 if (cur == NULL) return(NULL);
1330
1331 /*
1332 * add the new element at the end of the childs list.
1333 */
Daniel Veillardccb09631998-10-27 06:21:04 +00001334 cur->type = XML_ELEMENT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001335 cur->parent = parent;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001336 cur->doc = parent->doc;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001337 if (parent->childs == NULL) {
1338 parent->childs = cur;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001339 parent->last = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001340 } else {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001341 prev = parent->last;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001342 prev->next = cur;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001343 cur->prev = prev;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001344 parent->last = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001345 }
1346
1347 return(cur);
1348}
1349
Daniel Veillard97b58771998-10-20 06:14:16 +00001350/**
Daniel Veillardb96e6431999-08-29 21:02:19 +00001351 * xmlAddSibling:
1352 * @cur: the child node
1353 * @elem: the new node
1354 *
1355 * Add a new element to the list of siblings of @cur
1356 * Returns the element or NULL in case of error.
1357 */
1358xmlNodePtr
1359xmlAddSibling(xmlNodePtr cur, xmlNodePtr elem) {
1360 xmlNodePtr parent;
1361
1362 if (cur == NULL) {
1363 fprintf(stderr, "xmlAddSibling : cur == NULL\n");
1364 return(NULL);
1365 }
1366
1367 if (elem == NULL) {
1368 fprintf(stderr, "xmlAddSibling : elem == NULL\n");
1369 return(NULL);
1370 }
1371
1372 if ((cur->doc != NULL) && (elem->doc != NULL) &&
1373 (cur->doc != elem->doc)) {
1374 fprintf(stderr,
1375 "xmlAddSibling: Elements moved to a different document\n");
1376 }
1377
1378 while (cur->next != NULL) cur = cur->next;
1379
1380 if (elem->doc == NULL)
1381 elem->doc = cur->doc; /* the parent may not be linked to a doc ! */
1382
1383 parent = cur->parent;
1384 elem->prev = cur;
1385 elem->next = NULL;
1386 elem->parent = parent;
1387 cur->next = elem;
1388 if (parent != NULL)
1389 parent->last = elem;
1390
1391 return(elem);
1392}
1393
1394/**
Daniel Veillard97b58771998-10-20 06:14:16 +00001395 * xmlAddChild:
1396 * @parent: the parent node
1397 * @cur: the child node
1398 *
1399 * Add a new child element, to @parent, at the end of the child list.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001400 * Returns the child or NULL in case of error.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001401 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001402xmlNodePtr
1403xmlAddChild(xmlNodePtr parent, xmlNodePtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001404 xmlNodePtr prev;
1405
1406 if (parent == NULL) {
1407 fprintf(stderr, "xmladdChild : parent == NULL\n");
1408 return(NULL);
1409 }
1410
1411 if (cur == NULL) {
1412 fprintf(stderr, "xmladdChild : child == NULL\n");
1413 return(NULL);
1414 }
1415
Daniel Veillard0bef1311998-10-14 02:36:47 +00001416 if ((cur->doc != NULL) && (parent->doc != NULL) &&
1417 (cur->doc != parent->doc)) {
1418 fprintf(stderr, "Elements moved to a different document\n");
1419 }
1420
Daniel Veillard260a68f1998-08-13 03:39:55 +00001421 /*
1422 * add the new element at the end of the childs list.
1423 */
1424 cur->parent = parent;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001425 cur->doc = parent->doc; /* the parent may not be linked to a doc ! */
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001426
Daniel Veillardccb09631998-10-27 06:21:04 +00001427 /*
1428 * Handle the case where parent->content != NULL, in that case it will
1429 * create a intermediate TEXT node.
1430 */
1431 if (parent->content != NULL) {
1432 xmlNodePtr text;
1433
1434 text = xmlNewDocText(parent->doc, parent->content);
1435 if (text != NULL) {
1436 text->next = parent->childs;
1437 if (text->next != NULL)
1438 text->next->prev = text;
1439 parent->childs = text;
Daniel Veillard1e346af1999-02-22 10:33:01 +00001440 UPDATE_LAST_CHILD(parent)
Daniel Veillardccb09631998-10-27 06:21:04 +00001441 free(parent->content);
1442 parent->content = NULL;
1443 }
1444 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00001445 if (parent->childs == NULL) {
1446 parent->childs = cur;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001447 parent->last = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001448 } else {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001449 prev = parent->last;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001450 prev->next = cur;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001451 cur->prev = prev;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001452 parent->last = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001453 }
1454
1455 return(cur);
1456}
1457
Daniel Veillard97b58771998-10-20 06:14:16 +00001458/**
1459 * xmlGetLastChild:
1460 * @parent: the parent node
1461 *
1462 * Search the last child of a node.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001463 * Returns the last child or NULL if none.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001464 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001465xmlNodePtr
1466xmlGetLastChild(xmlNodePtr parent) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001467 if (parent == NULL) {
1468 fprintf(stderr, "xmlGetLastChild : parent == NULL\n");
1469 return(NULL);
1470 }
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001471 return(parent->last);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001472}
1473
Daniel Veillard97b58771998-10-20 06:14:16 +00001474/**
1475 * xmlFreeNodeList:
1476 * @cur: the first node in the list
1477 *
1478 * Free a node and all its siblings, this is a recursive behaviour, all
1479 * the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001480 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001481void
1482xmlFreeNodeList(xmlNodePtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001483 xmlNodePtr next;
1484 if (cur == NULL) {
1485 fprintf(stderr, "xmlFreeNodeList : node == NULL\n");
1486 return;
1487 }
1488 while (cur != NULL) {
1489 next = cur->next;
1490 xmlFreeNode(cur);
1491 cur = next;
1492 }
1493}
1494
Daniel Veillard97b58771998-10-20 06:14:16 +00001495/**
1496 * xmlFreeNode:
1497 * @cur: the node
1498 *
1499 * Free a node, this is a recursive behaviour, all the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001500 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001501void
1502xmlFreeNode(xmlNodePtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001503 if (cur == NULL) {
1504 fprintf(stderr, "xmlFreeNode : node == NULL\n");
1505 return;
1506 }
Daniel Veillardccb09631998-10-27 06:21:04 +00001507 cur->doc = NULL;
1508 cur->parent = NULL;
1509 cur->next = NULL;
1510 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001511 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillardccb09631998-10-27 06:21:04 +00001512 if (cur->properties != NULL) xmlFreePropList(cur->properties);
1513 if (cur->type != XML_ENTITY_REF_NODE)
1514 if (cur->content != NULL) free(cur->content);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001515 if (cur->name != NULL) free((char *) cur->name);
1516 if (cur->nsDef != NULL) xmlFreeNsList(cur->nsDef);
1517 memset(cur, -1, sizeof(xmlNode));
1518 free(cur);
1519}
1520
Daniel Veillard16253641998-10-28 22:58:05 +00001521/**
1522 * xmlUnlinkNode:
1523 * @cur: the node
1524 *
1525 * Unlink a node from it's current context, the node is not freed
1526 */
1527void
1528xmlUnlinkNode(xmlNodePtr cur) {
1529 if (cur == NULL) {
1530 fprintf(stderr, "xmlUnlinkNode : node == NULL\n");
1531 return;
1532 }
1533 if ((cur->parent != NULL) && (cur->parent->childs == cur))
1534 cur->parent->childs = cur->next;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001535 if ((cur->parent != NULL) && (cur->parent->last == cur))
1536 cur->parent->last = cur->prev;
Daniel Veillard16253641998-10-28 22:58:05 +00001537 if (cur->next != NULL)
1538 cur->next->prev = cur->prev;
1539 if (cur->prev != NULL)
1540 cur->prev->next = cur->next;
1541 cur->next = cur->prev = NULL;
1542 cur->parent = NULL;
1543}
1544
Daniel Veillard260a68f1998-08-13 03:39:55 +00001545/************************************************************************
1546 * *
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001547 * Copy operations *
1548 * *
1549 ************************************************************************/
1550
1551/**
1552 * xmlCopyNamespace:
1553 * @cur: the namespace
1554 *
1555 * Do a copy of the namespace.
1556 *
1557 * Returns: a new xmlNsPtr, or NULL in case of error.
1558 */
1559xmlNsPtr
1560xmlCopyNamespace(xmlNsPtr cur) {
1561 xmlNsPtr ret;
1562
1563 if (cur == NULL) return(NULL);
1564 switch (cur->type) {
1565 case XML_GLOBAL_NAMESPACE:
1566 ret = xmlNewGlobalNs(NULL, cur->href, cur->prefix);
1567 break;
1568 case XML_LOCAL_NAMESPACE:
1569 ret = xmlNewNs(NULL, cur->href, cur->prefix);
1570 break;
1571 default:
1572 fprintf(stderr, "xmlCopyNamespace: unknown type %d\n", cur->type);
1573 return(NULL);
1574 }
1575 return(ret);
1576}
1577
1578/**
1579 * xmlCopyNamespaceList:
1580 * @cur: the first namespace
1581 *
1582 * Do a copy of an namespace list.
1583 *
1584 * Returns: a new xmlNsPtr, or NULL in case of error.
1585 */
1586xmlNsPtr
1587xmlCopyNamespaceList(xmlNsPtr cur) {
1588 xmlNsPtr ret = NULL;
1589 xmlNsPtr p = NULL,q;
1590
1591 while (cur != NULL) {
1592 q = xmlCopyNamespace(cur);
1593 if (p == NULL) {
1594 ret = p = q;
1595 } else {
1596 p->next = q;
1597 p = q;
1598 }
1599 cur = cur->next;
1600 }
1601 return(ret);
1602}
1603
1604/**
1605 * xmlCopyProp:
Daniel Veillardb96e6431999-08-29 21:02:19 +00001606 * @target: the element where the attribute will be grafted
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001607 * @cur: the attribute
1608 *
1609 * Do a copy of the attribute.
1610 *
1611 * Returns: a new xmlAttrPtr, or NULL in case of error.
1612 */
1613xmlAttrPtr
Daniel Veillardb96e6431999-08-29 21:02:19 +00001614xmlCopyProp(xmlNodePtr target, xmlAttrPtr cur) {
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001615 xmlAttrPtr ret;
1616
1617 if (cur == NULL) return(NULL);
1618 if (cur->val != NULL)
1619 ret = xmlNewDocProp(cur->val->doc, cur->name, NULL);
1620 else
1621 ret = xmlNewDocProp(NULL, cur->name, NULL);
1622 if (ret == NULL) return(NULL);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001623
1624 if ((cur->ns != NULL) && (target != NULL)) {
1625 xmlNsPtr ns;
1626
1627 ns = xmlSearchNs(target->doc, target, cur->ns->prefix);
1628 ret->ns = ns;
1629 } else
1630 ret->ns = NULL;
1631
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001632 if (cur->val != NULL)
1633 ret->val = xmlCopyNodeList(cur->val);
1634 return(ret);
1635}
1636
1637/**
1638 * xmlCopyPropList:
Daniel Veillardb96e6431999-08-29 21:02:19 +00001639 * @target: the element where the attributes will be grafted
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001640 * @cur: the first attribute
1641 *
1642 * Do a copy of an attribute list.
1643 *
1644 * Returns: a new xmlAttrPtr, or NULL in case of error.
1645 */
1646xmlAttrPtr
Daniel Veillardb96e6431999-08-29 21:02:19 +00001647xmlCopyPropList(xmlNodePtr target, xmlAttrPtr cur) {
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001648 xmlAttrPtr ret = NULL;
1649 xmlAttrPtr p = NULL,q;
1650
1651 while (cur != NULL) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00001652 q = xmlCopyProp(target, cur);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001653 if (p == NULL) {
1654 ret = p = q;
1655 } else {
1656 p->next = q;
1657 p = q;
1658 }
1659 cur = cur->next;
1660 }
1661 return(ret);
1662}
1663
1664/*
1665 * NOTE about the CopyNode operations !
1666 *
1667 * They are splitted into external and internal parts for one
1668 * tricky reason: namespaces. Doing a direct copy of a node
1669 * say RPM:Copyright without changing the namespace pointer to
1670 * something else can produce stale links. One way to do it is
1671 * to keep a reference counter but this doesn't work as soon
1672 * as one move the element or the subtree out of the scope of
1673 * the existing namespace. The actual solution seems to add
1674 * a copy of the namespace at the top of the copied tree if
1675 * not available in the subtree.
1676 * Hence two functions, the public front-end call the inner ones
1677 */
1678
1679static xmlNodePtr
1680xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent);
1681
1682static xmlNodePtr
1683xmlStaticCopyNode(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent,
1684 int recursive) {
1685 xmlNodePtr ret;
1686
1687 if (node == NULL) return(NULL);
1688 /*
1689 * Allocate a new node and fill the fields.
1690 */
1691 ret = (xmlNodePtr) malloc(sizeof(xmlNode));
1692 if (ret == NULL) {
1693 fprintf(stderr, "xmlStaticCopyNode : malloc failed\n");
1694 return(NULL);
1695 }
1696
1697 ret->type = node->type;
1698 ret->doc = doc;
1699 ret->parent = parent;
1700 ret->next = NULL;
1701 ret->prev = NULL;
1702 ret->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001703 ret->last = NULL;
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001704 ret->properties = NULL;
1705 if (node->name != NULL)
1706 ret->name = xmlStrdup(node->name);
1707 else
1708 ret->name = NULL;
1709 ret->ns = NULL;
1710 ret->nsDef = NULL;
1711 if ((node->content != NULL) && (node->type != XML_ENTITY_REF_NODE))
1712 ret->content = xmlStrdup(node->content);
1713 else
1714 ret->content = NULL;
Daniel Veillard27d88741999-05-29 11:51:49 +00001715#ifndef XML_WITHOUT_CORBA
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001716 ret->_private = NULL;
1717 ret->vepv = NULL;
1718#endif
1719 if (parent != NULL)
1720 xmlAddChild(parent, ret);
1721
1722 if (!recursive) return(ret);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001723 if (node->nsDef != NULL)
1724 ret->nsDef = xmlCopyNamespaceList(node->nsDef);
1725
1726 if (node->ns != NULL) {
1727 xmlNsPtr ns;
1728
1729 ns = xmlSearchNs(doc, ret, node->ns->prefix);
1730 if (ns == NULL) {
1731 /*
1732 * Humm, we are copying an element whose namespace is defined
1733 * out of the new tree scope. Search it in the original tree
1734 * and add it at the top of the new tree
1735 */
1736 ns = xmlSearchNs(node->doc, node, node->ns->prefix);
1737 if (ns != NULL) {
1738 xmlNodePtr root = ret;
1739
1740 while (root->parent != NULL) root = root->parent;
1741 xmlNewNs(root, ns->href, ns->prefix);
1742 }
1743 } else {
1744 /*
1745 * reference the existing namespace definition in our own tree.
1746 */
1747 ret->ns = ns;
1748 }
1749 }
Daniel Veillardb96e6431999-08-29 21:02:19 +00001750 if (node->properties != NULL)
1751 ret->properties = xmlCopyPropList(ret, node->properties);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001752 if (node->childs != NULL)
1753 ret->childs = xmlStaticCopyNodeList(node->childs, doc, ret);
Daniel Veillard1e346af1999-02-22 10:33:01 +00001754 UPDATE_LAST_CHILD(ret)
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001755 return(ret);
1756}
1757
1758static xmlNodePtr
1759xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent) {
1760 xmlNodePtr ret = NULL;
1761 xmlNodePtr p = NULL,q;
1762
1763 while (node != NULL) {
1764 q = xmlStaticCopyNode(node, doc, parent, 1);
1765 if (parent == NULL) {
1766 if (ret == NULL) ret = q;
1767 } else {
1768 if (ret == NULL) {
1769 q->prev = NULL;
1770 ret = p = q;
1771 } else {
1772 p->next = q;
1773 q->prev = p;
1774 p = q;
1775 }
1776 }
1777 node = node->next;
1778 }
1779 return(ret);
1780}
1781
1782/**
1783 * xmlCopyNode:
1784 * @node: the node
1785 * @recursive: if 1 do a recursive copy.
1786 *
1787 * Do a copy of the node.
1788 *
1789 * Returns: a new xmlNodePtr, or NULL in case of error.
1790 */
1791xmlNodePtr
1792xmlCopyNode(xmlNodePtr node, int recursive) {
1793 xmlNodePtr ret;
1794
1795 ret = xmlStaticCopyNode(node, NULL, NULL, recursive);
1796 return(ret);
1797}
1798
1799/**
1800 * xmlCopyNodeList:
1801 * @node: the first node in the list.
1802 *
1803 * Do a recursive copy of the node list.
1804 *
1805 * Returns: a new xmlNodePtr, or NULL in case of error.
1806 */
1807xmlNodePtr xmlCopyNodeList(xmlNodePtr node) {
1808 xmlNodePtr ret = xmlStaticCopyNodeList(node, NULL, NULL);
1809 return(ret);
1810}
1811
1812/**
1813 * xmlCopyElement:
1814 * @elem: the element
1815 *
1816 * Do a copy of the element definition.
1817 *
1818 * Returns: a new xmlElementPtr, or NULL in case of error.
1819xmlElementPtr
1820xmlCopyElement(xmlElementPtr elem) {
1821 xmlElementPtr ret;
1822
1823 if (elem == NULL) return(NULL);
1824 ret = xmlNewDocElement(elem->doc, elem->ns, elem->name, elem->content);
1825 if (ret == NULL) return(NULL);
1826 if (!recursive) return(ret);
1827 if (elem->properties != NULL)
1828 ret->properties = xmlCopyPropList(elem->properties);
1829
1830 if (elem->nsDef != NULL)
1831 ret->nsDef = xmlCopyNamespaceList(elem->nsDef);
1832 if (elem->childs != NULL)
1833 ret->childs = xmlCopyElementList(elem->childs);
1834 return(ret);
1835}
1836 */
1837
1838/**
1839 * xmlCopyDtd:
1840 * @dtd: the dtd
1841 *
1842 * Do a copy of the dtd.
1843 *
1844 * Returns: a new xmlDtdPtr, or NULL in case of error.
1845 */
1846xmlDtdPtr
1847xmlCopyDtd(xmlDtdPtr dtd) {
1848 xmlDtdPtr ret;
1849
1850 if (dtd == NULL) return(NULL);
1851 ret = xmlNewDtd(NULL, dtd->name, dtd->ExternalID, dtd->SystemID);
1852 if (ret == NULL) return(NULL);
1853 if (dtd->entities != NULL)
1854 ret->entities = (void *) xmlCopyEntitiesTable(
1855 (xmlEntitiesTablePtr) dtd->entities);
Daniel Veillard1e346af1999-02-22 10:33:01 +00001856 if (dtd->notations != NULL)
1857 ret->notations = (void *) xmlCopyNotationTable(
1858 (xmlNotationTablePtr) dtd->notations);
1859 if (dtd->elements != NULL)
1860 ret->elements = (void *) xmlCopyElementTable(
1861 (xmlElementTablePtr) dtd->elements);
1862 if (dtd->attributes != NULL)
1863 ret->attributes = (void *) xmlCopyAttributeTable(
1864 (xmlAttributeTablePtr) dtd->attributes);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001865 return(ret);
1866}
1867
1868/**
1869 * xmlCopyDoc:
1870 * @doc: the document
1871 * @recursive: if 1 do a recursive copy.
1872 *
1873 * Do a copy of the document info. If recursive, the content tree will
1874 * be copied too as well as Dtd, namespaces and entities.
1875 *
1876 * Returns: a new xmlDocPtr, or NULL in case of error.
1877 */
1878xmlDocPtr
1879xmlCopyDoc(xmlDocPtr doc, int recursive) {
1880 xmlDocPtr ret;
1881
1882 if (doc == NULL) return(NULL);
1883 ret = xmlNewDoc(doc->version);
1884 if (ret == NULL) return(NULL);
1885 if (doc->name != NULL)
1886 ret->name = strdup(doc->name);
1887 if (doc->encoding != NULL)
1888 ret->encoding = xmlStrdup(doc->encoding);
1889 ret->compression = doc->compression;
1890 ret->standalone = doc->standalone;
1891 if (!recursive) return(ret);
1892
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001893 if (doc->intSubset != NULL)
1894 ret->intSubset = xmlCopyDtd(doc->intSubset);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001895 if (doc->oldNs != NULL)
1896 ret->oldNs = xmlCopyNamespaceList(doc->oldNs);
1897 if (doc->root != NULL)
1898 ret->root = xmlStaticCopyNodeList(doc->root, ret, NULL);
1899 return(ret);
1900}
1901
1902/************************************************************************
1903 * *
Daniel Veillard260a68f1998-08-13 03:39:55 +00001904 * Content access functions *
1905 * *
1906 ************************************************************************/
1907
Daniel Veillard97b58771998-10-20 06:14:16 +00001908/**
Daniel Veillardb96e6431999-08-29 21:02:19 +00001909 * xmlNodeSetLang:
1910 * @cur: the node being changed
1911 * @lang: the langage description
1912 *
1913 * Searches the language of a node, i.e. the values of the xml:lang
1914 * attribute or the one carried by the nearest ancestor.
1915 *
1916 * Returns a pointer to the lang value, or NULL if not found
1917 */
1918void
1919xmlNodeSetLang(xmlNodePtr cur, const CHAR *lang) {
1920 /* TODO xmlNodeSetLang check against the production [33] LanguageID */
1921 xmlSetProp(cur, BAD_CAST "xml:lang", lang);
1922}
1923
1924/**
1925 * xmlNodeGetLang:
1926 * @cur: the node being checked
1927 *
1928 * Searches the language of a node, i.e. the values of the xml:lang
1929 * attribute or the one carried by the nearest ancestor.
1930 *
1931 * Returns a pointer to the lang value, or NULL if not found
1932 */
1933const CHAR *
1934xmlNodeGetLang(xmlNodePtr cur) {
1935 const CHAR *lang;
1936
1937 while (cur != NULL) {
1938 lang = xmlGetProp(cur, BAD_CAST "xml:lang");
1939 if (lang != NULL)
1940 return(lang);
1941 cur = cur->parent;
1942 }
1943 return(NULL);
1944}
1945
1946/**
Daniel Veillard16253641998-10-28 22:58:05 +00001947 * xmlNodeGetContent:
1948 * @cur: the node being read
1949 *
1950 * Read the value of a node, this can be either the text carried
1951 * directly by this node if it's a TEXT node or the aggregate string
1952 * of the values carried by this node child's (TEXT and ENTITY_REF).
1953 * Entity references are substitued.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001954 * Returns a new CHAR * or NULL if no content is available.
Daniel Veillard5099ae81999-04-21 20:12:07 +00001955 * It's up to the caller to free the memory.
Daniel Veillard16253641998-10-28 22:58:05 +00001956 */
1957CHAR *
1958xmlNodeGetContent(xmlNodePtr cur) {
1959 if (cur == NULL) return(NULL);
1960 switch (cur->type) {
1961 case XML_DOCUMENT_FRAG_NODE:
1962 case XML_ELEMENT_NODE:
1963 return(xmlNodeListGetString(cur->doc, cur->childs, 1));
1964 break;
Daniel Veillardb96e6431999-08-29 21:02:19 +00001965 case XML_ATTRIBUTE_NODE: {
1966 xmlAttrPtr attr = (xmlAttrPtr) cur;
1967 if (attr->node != NULL)
1968 return(xmlNodeListGetString(attr->node->doc, attr->val, 1));
1969 else
1970 return(xmlNodeListGetString(NULL, attr->val, 1));
1971 break;
1972 }
1973 case XML_PI_NODE:
1974 if (cur->content != NULL)
1975 return(xmlStrdup(cur->content));
1976 return(NULL);
Daniel Veillard16253641998-10-28 22:58:05 +00001977 case XML_ENTITY_REF_NODE:
1978 case XML_ENTITY_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00001979 case XML_COMMENT_NODE:
1980 case XML_DOCUMENT_NODE:
1981 case XML_DOCUMENT_TYPE_NODE:
1982 case XML_NOTATION_NODE:
1983 return(NULL);
Daniel Veillardb05deb71999-08-10 19:04:08 +00001984 case XML_CDATA_SECTION_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00001985 case XML_TEXT_NODE:
1986 if (cur->content != NULL)
1987 return(xmlStrdup(cur->content));
1988 return(NULL);
1989 }
1990 return(NULL);
1991}
1992
1993/**
Daniel Veillard97b58771998-10-20 06:14:16 +00001994 * xmlNodeSetContent:
1995 * @cur: the node being modified
1996 * @content: the new value of the content
1997 *
1998 * Replace the content of a node.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001999 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002000void
2001xmlNodeSetContent(xmlNodePtr cur, const CHAR *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002002 if (cur == NULL) {
2003 fprintf(stderr, "xmlNodeSetContent : node == NULL\n");
2004 return;
2005 }
Daniel Veillard16253641998-10-28 22:58:05 +00002006 switch (cur->type) {
2007 case XML_DOCUMENT_FRAG_NODE:
2008 case XML_ELEMENT_NODE:
2009 if (cur->content != NULL) {
2010 free(cur->content);
2011 cur->content = NULL;
2012 }
2013 if (cur->childs != NULL) xmlFreeNode(cur->childs);
2014 cur->childs = xmlStringGetNodeList(cur->doc, content);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002015 UPDATE_LAST_CHILD(cur)
Daniel Veillard16253641998-10-28 22:58:05 +00002016 break;
2017 case XML_ATTRIBUTE_NODE:
2018 break;
2019 case XML_TEXT_NODE:
2020 case XML_CDATA_SECTION_NODE:
2021 case XML_ENTITY_REF_NODE:
2022 case XML_ENTITY_NODE:
2023 case XML_PI_NODE:
2024 case XML_COMMENT_NODE:
2025 if (cur->content != NULL) free(cur->content);
2026 if (cur->childs != NULL) xmlFreeNode(cur->childs);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002027 cur->last = cur->childs = NULL;
Daniel Veillard16253641998-10-28 22:58:05 +00002028 if (content != NULL)
2029 cur->content = xmlStrdup(content);
2030 else
2031 cur->content = NULL;
Daniel Veillardb96e6431999-08-29 21:02:19 +00002032 break;
Daniel Veillard16253641998-10-28 22:58:05 +00002033 case XML_DOCUMENT_NODE:
2034 case XML_DOCUMENT_TYPE_NODE:
2035 break;
2036 case XML_NOTATION_NODE:
2037 break;
2038 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002039}
2040
Daniel Veillard97b58771998-10-20 06:14:16 +00002041/**
2042 * xmlNodeSetContentLen:
2043 * @cur: the node being modified
2044 * @content: the new value of the content
2045 * @len: the size of @content
2046 *
2047 * Replace the content of a node.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002048 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002049void
2050xmlNodeSetContentLen(xmlNodePtr cur, const CHAR *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002051 if (cur == NULL) {
Daniel Veillard16253641998-10-28 22:58:05 +00002052 fprintf(stderr, "xmlNodeSetContentLen : node == NULL\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002053 return;
2054 }
Daniel Veillard16253641998-10-28 22:58:05 +00002055 switch (cur->type) {
2056 case XML_DOCUMENT_FRAG_NODE:
2057 case XML_ELEMENT_NODE:
2058 if (cur->content != NULL) {
2059 free(cur->content);
2060 cur->content = NULL;
2061 }
2062 if (cur->childs != NULL) xmlFreeNode(cur->childs);
2063 cur->childs = xmlStringLenGetNodeList(cur->doc, content, len);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002064 UPDATE_LAST_CHILD(cur)
Daniel Veillard16253641998-10-28 22:58:05 +00002065 break;
2066 case XML_ATTRIBUTE_NODE:
2067 break;
2068 case XML_TEXT_NODE:
2069 case XML_CDATA_SECTION_NODE:
2070 case XML_ENTITY_REF_NODE:
2071 case XML_ENTITY_NODE:
2072 case XML_PI_NODE:
2073 case XML_COMMENT_NODE:
2074 if (cur->content != NULL) free(cur->content);
2075 if (cur->childs != NULL) xmlFreeNode(cur->childs);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002076 cur->childs = cur->last = NULL;
Daniel Veillard16253641998-10-28 22:58:05 +00002077 if (content != NULL)
2078 cur->content = xmlStrndup(content, len);
2079 else
2080 cur->content = NULL;
Daniel Veillardb96e6431999-08-29 21:02:19 +00002081 break;
Daniel Veillard16253641998-10-28 22:58:05 +00002082 case XML_DOCUMENT_NODE:
2083 case XML_DOCUMENT_TYPE_NODE:
2084 break;
2085 case XML_NOTATION_NODE:
2086 if (cur->content != NULL) free(cur->content);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002087 if (cur->childs != NULL) xmlFreeNode(cur->childs);
2088 cur->childs = cur->last = NULL;
Daniel Veillard16253641998-10-28 22:58:05 +00002089 if (content != NULL)
2090 cur->content = xmlStrndup(content, len);
2091 else
2092 cur->content = NULL;
2093 break;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002094 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002095}
2096
Daniel Veillard97b58771998-10-20 06:14:16 +00002097/**
2098 * xmlNodeAddContentLen:
2099 * @cur: the node being modified
2100 * @content: extra content
2101 * @len: the size of @content
2102 *
2103 * Append the extra substring to the node content.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002104 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002105void
2106xmlNodeAddContentLen(xmlNodePtr cur, const CHAR *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002107 if (cur == NULL) {
Daniel Veillard16253641998-10-28 22:58:05 +00002108 fprintf(stderr, "xmlNodeAddContentLen : node == NULL\n");
2109 return;
2110 }
2111 if (len <= 0) return;
2112 switch (cur->type) {
2113 case XML_DOCUMENT_FRAG_NODE:
2114 case XML_ELEMENT_NODE: {
2115 xmlNodePtr last = NULL, new;
2116
2117 if (cur->childs != NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002118 last = cur->last;
Daniel Veillard16253641998-10-28 22:58:05 +00002119 } else {
2120 if (cur->content != NULL) {
2121 cur->childs = xmlStringGetNodeList(cur->doc, cur->content);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002122 UPDATE_LAST_CHILD(cur)
Daniel Veillard16253641998-10-28 22:58:05 +00002123 free(cur->content);
2124 cur->content = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002125 last = cur->last;
Daniel Veillard16253641998-10-28 22:58:05 +00002126 }
2127 }
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002128 new = xmlNewTextLen(content, len);
Daniel Veillard16253641998-10-28 22:58:05 +00002129 if (new != NULL) {
2130 xmlAddChild(cur, new);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002131 if ((last != NULL) && (last->next == new)) {
Daniel Veillard16253641998-10-28 22:58:05 +00002132 xmlTextMerge(last, new);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002133 }
Daniel Veillard16253641998-10-28 22:58:05 +00002134 }
2135 break;
2136 }
2137 case XML_ATTRIBUTE_NODE:
2138 break;
2139 case XML_TEXT_NODE:
2140 case XML_CDATA_SECTION_NODE:
2141 case XML_ENTITY_REF_NODE:
2142 case XML_ENTITY_NODE:
2143 case XML_PI_NODE:
2144 case XML_COMMENT_NODE:
2145 if (content != NULL)
2146 cur->content = xmlStrncat(cur->content, content, len);
2147 case XML_DOCUMENT_NODE:
2148 case XML_DOCUMENT_TYPE_NODE:
2149 break;
2150 case XML_NOTATION_NODE:
2151 if (content != NULL)
2152 cur->content = xmlStrncat(cur->content, content, len);
2153 break;
2154 }
2155}
2156
2157/**
2158 * xmlNodeAddContent:
2159 * @cur: the node being modified
2160 * @content: extra content
2161 *
2162 * Append the extra substring to the node content.
2163 */
2164void
2165xmlNodeAddContent(xmlNodePtr cur, const CHAR *content) {
2166 int len;
2167
2168 if (cur == NULL) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002169 fprintf(stderr, "xmlNodeAddContent : node == NULL\n");
2170 return;
2171 }
Daniel Veillard16253641998-10-28 22:58:05 +00002172 if (content == NULL) return;
2173 len = xmlStrlen(content);
2174 xmlNodeAddContentLen(cur, content, len);
2175}
2176
2177/**
2178 * xmlTextMerge:
2179 * @first: the first text node
2180 * @second: the second text node being merged
2181 *
2182 * Merge two text nodes into one
Daniel Veillard1e346af1999-02-22 10:33:01 +00002183 * Returns the first text node augmented
Daniel Veillard16253641998-10-28 22:58:05 +00002184 */
2185xmlNodePtr
2186xmlTextMerge(xmlNodePtr first, xmlNodePtr second) {
2187 if (first == NULL) return(second);
2188 if (second == NULL) return(first);
2189 if (first->type != XML_TEXT_NODE) return(first);
2190 if (second->type != XML_TEXT_NODE) return(first);
2191 xmlNodeAddContent(first, second->content);
2192 xmlUnlinkNode(second);
2193 xmlFreeNode(second);
2194 return(first);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002195}
2196
Daniel Veillard97b58771998-10-20 06:14:16 +00002197/**
Daniel Veillardb96e6431999-08-29 21:02:19 +00002198 * xmlGetNsList:
2199 * @doc: the document
2200 * @node: the current node
2201 *
2202 * Search all the namespace applying to a given element.
2203 * Returns an NULL terminated array of all the xmlNsPtr found
2204 * that need to be freed by the caller or NULL if no
2205 * namespace if defined
2206 */
2207xmlNsPtr *
2208xmlGetNsList(xmlDocPtr doc, xmlNodePtr node) {
2209 xmlNsPtr cur;
2210 xmlNsPtr *ret = NULL;
2211 int nbns = 0;
2212 int maxns = 10;
2213 int i;
2214
2215 while (node != NULL) {
2216 cur = node->nsDef;
2217 while (cur != NULL) {
2218 if (ret == NULL) {
2219 ret = (xmlNsPtr *) malloc((maxns + 1) * sizeof(xmlNsPtr));
2220 if (ret == NULL) {
2221 fprintf(stderr, "xmlGetNsList : out of memory!\n");
2222 return(NULL);
2223 }
2224 ret[nbns] = NULL;
2225 }
2226 for (i = 0;i < nbns;i++) {
2227 if ((cur->prefix == ret[i]->prefix) ||
2228 (!xmlStrcmp(cur->prefix, ret[i]->prefix))) break;
2229 }
2230 if (i >= nbns) {
2231 if (nbns >= maxns) {
2232 maxns *= 2;
2233 ret = (xmlNsPtr *) realloc(ret,
2234 (maxns + 1) * sizeof(xmlNsPtr));
2235 if (ret == NULL) {
2236 fprintf(stderr, "xmlGetNsList : realloc failed!\n");
2237 return(NULL);
2238 }
2239 }
2240 ret[nbns++] = cur;
2241 ret[nbns] = NULL;
2242 }
2243
2244 cur = cur->next;
2245 }
2246 node = node->parent;
2247 }
2248 return(ret);
2249}
2250
2251/**
Daniel Veillard97b58771998-10-20 06:14:16 +00002252 * xmlSearchNs:
2253 * @doc: the document
2254 * @node: the current node
2255 * @nameSpace: the namespace string
Daniel Veillard260a68f1998-08-13 03:39:55 +00002256 *
Daniel Veillard97b58771998-10-20 06:14:16 +00002257 * Search a Ns registered under a given name space for a document.
2258 * recurse on the parents until it finds the defined namespace
2259 * or return NULL otherwise.
2260 * @nameSpace can be NULL, this is a search for the default namespace.
Daniel Veillard1e346af1999-02-22 10:33:01 +00002261 * Returns the namespace pointer or NULL.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002262 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002263xmlNsPtr
2264xmlSearchNs(xmlDocPtr doc, xmlNodePtr node, const CHAR *nameSpace) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002265 xmlNsPtr cur;
2266
2267 while (node != NULL) {
2268 cur = node->nsDef;
2269 while (cur != NULL) {
2270 if ((cur->prefix == NULL) && (nameSpace == NULL))
2271 return(cur);
2272 if ((cur->prefix != NULL) && (nameSpace != NULL) &&
2273 (!xmlStrcmp(cur->prefix, nameSpace)))
2274 return(cur);
2275 cur = cur->next;
2276 }
2277 node = node->parent;
2278 }
2279 if (doc != NULL) {
2280 cur = doc->oldNs;
2281 while (cur != NULL) {
2282 if ((cur->prefix != NULL) && (nameSpace != NULL) &&
2283 (!xmlStrcmp(cur->prefix, nameSpace)))
2284 return(cur);
2285 cur = cur->next;
2286 }
2287 }
2288 return(NULL);
2289}
2290
Daniel Veillard97b58771998-10-20 06:14:16 +00002291/**
2292 * xmlSearchNsByHref:
2293 * @doc: the document
2294 * @node: the current node
2295 * @href: the namespace value
2296 *
2297 * Search a Ns aliasing a given URI. Recurse on the parents until it finds
2298 * the defined namespace or return NULL otherwise.
Daniel Veillard1e346af1999-02-22 10:33:01 +00002299 * Returns the namespace pointer or NULL.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002300 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002301xmlNsPtr
2302xmlSearchNsByHref(xmlDocPtr doc, xmlNodePtr node, const CHAR *href) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002303 xmlNsPtr cur;
2304
2305 while (node != NULL) {
2306 cur = node->nsDef;
2307 while (cur != NULL) {
2308 if ((cur->href != NULL) && (href != NULL) &&
2309 (!xmlStrcmp(cur->href, href)))
2310 return(cur);
2311 cur = cur->next;
2312 }
2313 node = node->parent;
2314 }
2315 if (doc != NULL) {
2316 cur = doc->oldNs;
2317 while (cur != NULL) {
2318 if ((cur->href != NULL) && (href != NULL) &&
2319 (!xmlStrcmp(cur->href, href)))
2320 return(cur);
2321 cur = cur->next;
2322 }
2323 }
2324 return(NULL);
2325}
2326
Daniel Veillard97b58771998-10-20 06:14:16 +00002327/**
2328 * xmlGetProp:
2329 * @node: the node
2330 * @name: the attribute name
2331 *
2332 * Search and get the value of an attribute associated to a node
Daniel Veillardccb09631998-10-27 06:21:04 +00002333 * This does the entity substitution.
Daniel Veillard1e346af1999-02-22 10:33:01 +00002334 * Returns the attribute value or NULL if not found.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002335 */
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002336CHAR *xmlGetProp(xmlNodePtr node, const CHAR *name) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002337 xmlAttrPtr prop = node->properties;
2338
2339 while (prop != NULL) {
Daniel Veillard68178931999-02-08 18:34:36 +00002340 if (!xmlStrcmp(prop->name, name)) {
Daniel Veillard6800ef31999-02-08 18:33:22 +00002341 CHAR *ret;
2342
2343 ret = xmlNodeListGetString(node->doc, prop->val, 1);
Daniel Veillardb96e6431999-08-29 21:02:19 +00002344 if (ret == NULL) return(xmlStrdup((CHAR *)""));
Daniel Veillard6800ef31999-02-08 18:33:22 +00002345 return(ret);
Daniel Veillard68178931999-02-08 18:34:36 +00002346 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002347 prop = prop->next;
2348 }
2349 return(NULL);
2350}
2351
Daniel Veillard97b58771998-10-20 06:14:16 +00002352/**
Daniel Veillardccb09631998-10-27 06:21:04 +00002353 * xmlSetProp:
Daniel Veillard97b58771998-10-20 06:14:16 +00002354 * @node: the node
2355 * @name: the attribute name
2356 * @value: the attribute value
2357 *
2358 * Set (or reset) an attribute carried by a node.
Daniel Veillard1e346af1999-02-22 10:33:01 +00002359 * Returns the attribute pointer.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002360 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002361xmlAttrPtr
2362xmlSetProp(xmlNodePtr node, const CHAR *name, const CHAR *value) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002363 xmlAttrPtr prop = node->properties;
2364
2365 while (prop != NULL) {
2366 if (!xmlStrcmp(prop->name, name)) {
Daniel Veillardccb09631998-10-27 06:21:04 +00002367 if (prop->val != NULL)
2368 xmlFreeNode(prop->val);
2369 prop->val = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002370 if (value != NULL)
Daniel Veillardccb09631998-10-27 06:21:04 +00002371 prop->val = xmlStringGetNodeList(node->doc, value);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002372 return(prop);
2373 }
2374 prop = prop->next;
2375 }
2376 prop = xmlNewProp(node, name, value);
2377 return(prop);
2378}
2379
Daniel Veillard97b58771998-10-20 06:14:16 +00002380/**
2381 * xmlNodeIsText:
2382 * @node: the node
2383 *
2384 * Is this node a Text node ?
Daniel Veillard1e346af1999-02-22 10:33:01 +00002385 * Returns 1 yes, 0 no
Daniel Veillard260a68f1998-08-13 03:39:55 +00002386 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002387int
2388xmlNodeIsText(xmlNodePtr node) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002389 if (node == NULL) return(0);
2390
Daniel Veillard0bef1311998-10-14 02:36:47 +00002391 if (node->type == XML_TEXT_NODE) return(1);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002392 return(0);
2393}
2394
Daniel Veillard97b58771998-10-20 06:14:16 +00002395/**
Daniel Veillard1e346af1999-02-22 10:33:01 +00002396 * xmlTextConcat:
Daniel Veillard97b58771998-10-20 06:14:16 +00002397 * @node: the node
2398 * @content: the content
2399 * @len: @content lenght
2400 *
2401 * Concat the given string at the end of the existing node content
Daniel Veillard260a68f1998-08-13 03:39:55 +00002402 */
Daniel Veillard97b58771998-10-20 06:14:16 +00002403
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002404void
2405xmlTextConcat(xmlNodePtr node, const CHAR *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002406 if (node == NULL) return;
2407
Daniel Veillard0bef1311998-10-14 02:36:47 +00002408 if (node->type != XML_TEXT_NODE) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002409 fprintf(stderr, "xmlTextConcat: node is not text\n");
2410 return;
2411 }
2412 node->content = xmlStrncat(node->content, content, len);
2413}
2414
2415/************************************************************************
2416 * *
2417 * Output : to a FILE or in memory *
2418 * *
2419 ************************************************************************/
2420
Daniel Veillard5099ae81999-04-21 20:12:07 +00002421#define BASE_BUFFER_SIZE 4000
2422
2423/**
2424 * xmlBufferCreate:
2425 *
2426 * routine to create an XML buffer.
2427 * returns the new structure.
2428 */
2429xmlBufferPtr
2430xmlBufferCreate(void) {
2431 xmlBufferPtr ret;
2432
2433 ret = (xmlBufferPtr) malloc(sizeof(xmlBuffer));
2434 if (ret == NULL) {
2435 fprintf(stderr, "xmlBufferCreate : out of memory!\n");
2436 return(NULL);
2437 }
2438 ret->use = 0;
2439 ret->size = BASE_BUFFER_SIZE;
2440 ret->content = (CHAR *) malloc(ret->size * sizeof(CHAR));
2441 if (ret->content == NULL) {
2442 fprintf(stderr, "xmlBufferCreate : out of memory!\n");
2443 free(ret);
2444 return(NULL);
2445 }
2446 ret->content[0] = 0;
2447 return(ret);
2448}
2449
2450/**
2451 * xmlBufferFree:
2452 * @buf: the buffer to free
2453 *
2454 * Frees an XML buffer.
2455 */
2456void
2457xmlBufferFree(xmlBufferPtr buf) {
2458 if (buf == NULL) {
2459 fprintf(stderr, "xmlBufferFree: buf == NULL\n");
2460 return;
2461 }
2462 if (buf->content == NULL) {
2463 fprintf(stderr, "xmlBufferFree: buf->content == NULL\n");
2464 } else {
2465 memset(buf->content, -1, BASE_BUFFER_SIZE);
2466 free(buf->content);
2467 }
2468 memset(buf, -1, sizeof(xmlBuffer));
2469 free(buf);
2470}
2471
2472/**
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002473 * xmlBufferEmpty:
2474 * @buf: the buffer
2475 *
2476 * empty a buffer.
2477 */
2478void
2479xmlBufferEmpty(xmlBufferPtr buf) {
2480 buf->use = 0;
2481 memset(buf->content, -1, buf->size);/* just for debug */
2482}
2483
2484/**
2485 * xmlBufferShrink:
2486 * @buf: the buffer to dump
2487 * @len: the number of CHAR to remove
2488 *
2489 * Remove the beginning of an XML buffer.
2490 *
2491 * Returns the number of CHAR removed, or -1 in case of failure.
2492 */
2493int
2494xmlBufferShrink(xmlBufferPtr buf, int len) {
2495 if (len == 0) return(0);
2496 if (len > buf->use) return(-1);
2497
2498 buf->use -= len;
2499 memmove(buf->content, &buf->content[len], buf->use * sizeof(CHAR));
2500
2501 buf->content[buf->use] = 0;
2502 return(len);
2503}
2504
2505/**
Daniel Veillard5099ae81999-04-21 20:12:07 +00002506 * xmlBufferDump:
2507 * @file: the file output
2508 * @buf: the buffer to dump
2509 *
2510 * Dumps an XML buffer to a FILE *.
2511 * Returns the number of CHAR written
2512 */
2513int
2514xmlBufferDump(FILE *file, xmlBufferPtr buf) {
2515 int ret;
2516
2517 if (buf == NULL) {
2518 fprintf(stderr, "xmlBufferDump: buf == NULL\n");
2519 return(0);
2520 }
2521 if (buf->content == NULL) {
2522 fprintf(stderr, "xmlBufferDump: buf->content == NULL\n");
2523 return(0);
2524 }
2525 if (file == NULL) file = stdout;
2526 ret = fwrite(buf->content, sizeof(CHAR), buf->use, file);
2527 return(ret);
2528}
2529
2530/**
2531 * xmlBufferAdd:
2532 * @buf: the buffer to dump
2533 * @str: the CHAR string
2534 * @len: the number of CHAR to add
2535 *
2536 * Add a string range to an XML buffer.
2537 */
2538void
2539xmlBufferAdd(xmlBufferPtr buf, const CHAR *str, int len) {
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002540 int l;
Daniel Veillard5099ae81999-04-21 20:12:07 +00002541
2542 if (str == NULL) {
2543 fprintf(stderr, "xmlBufferAdd: str == NULL\n");
2544 return;
2545 }
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002546 l = xmlStrlen(str);
2547 if (l < len) len = l;
2548 if (len <= 0) return;
Daniel Veillard5099ae81999-04-21 20:12:07 +00002549
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002550 if (buf->use + len + 10 >= buf->size) {
2551 CHAR *rebuf;
2552
2553 buf->size *= 2;
2554 if (buf->use + len + 10 > buf->size)
2555 buf->size = buf->use + len + 10;
2556 rebuf = (CHAR *) realloc(buf->content, buf->size * sizeof(CHAR));
2557 if (rebuf == NULL) {
2558 fprintf(stderr, "xmlBufferAdd : out of memory!\n");
2559 return;
Daniel Veillard5099ae81999-04-21 20:12:07 +00002560 }
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002561 buf->content = rebuf;
Daniel Veillard5099ae81999-04-21 20:12:07 +00002562 }
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002563 memmove(&buf->content[buf->use], str, len);
2564 buf->use += len;
2565 buf->content[buf->use] = 0;
Daniel Veillard5099ae81999-04-21 20:12:07 +00002566}
2567
2568/**
2569 * xmlBufferCat:
2570 * @buf: the buffer to dump
2571 * @str: the CHAR string
2572 *
2573 * Append a zero terminated string to an XML buffer.
2574 */
2575void
2576xmlBufferCat(xmlBufferPtr buf, const CHAR *str) {
2577 const CHAR *cur;
2578
2579 if (str == NULL) {
2580 fprintf(stderr, "xmlBufferAdd: str == NULL\n");
2581 return;
2582 }
2583 for (cur = str;*cur != 0;cur++) {
2584 if (buf->use + 10 >= buf->size) {
2585 CHAR *rebuf;
2586
2587 buf->size *= 2;
2588 rebuf = (CHAR *) realloc(buf->content, buf->size * sizeof(CHAR));
2589 if (rebuf == NULL) {
2590 fprintf(stderr, "xmlBufferAdd : out of memory!\n");
2591 return;
2592 }
2593 buf->content = rebuf;
2594 }
2595 buf->content[buf->use++] = *cur;
2596 }
2597}
2598
2599/**
2600 * xmlBufferCCat:
2601 * @buf: the buffer to dump
2602 * @str: the C char string
2603 *
2604 * Append a zero terminated C string to an XML buffer.
2605 */
2606void
2607xmlBufferCCat(xmlBufferPtr buf, const char *str) {
2608 const char *cur;
2609
2610 if (str == NULL) {
2611 fprintf(stderr, "xmlBufferAdd: str == NULL\n");
2612 return;
2613 }
2614 for (cur = str;*cur != 0;cur++) {
2615 if (buf->use + 10 >= buf->size) {
2616 CHAR *rebuf;
2617
2618 buf->size *= 2;
2619 rebuf = (CHAR *) realloc(buf->content, buf->size * sizeof(CHAR));
2620 if (rebuf == NULL) {
2621 fprintf(stderr, "xmlBufferAdd : out of memory!\n");
2622 return;
2623 }
2624 buf->content = rebuf;
2625 }
2626 buf->content[buf->use++] = *cur;
2627 }
2628}
Daniel Veillard260a68f1998-08-13 03:39:55 +00002629
Daniel Veillard97b58771998-10-20 06:14:16 +00002630/**
2631 * xmlBufferWriteCHAR:
Daniel Veillard5099ae81999-04-21 20:12:07 +00002632 * @buf: the XML buffer
Daniel Veillard97b58771998-10-20 06:14:16 +00002633 * @string: the string to add
2634 *
2635 * routine which manage and grows an output buffer. This one add
Daniel Veillard5099ae81999-04-21 20:12:07 +00002636 * CHARs at the end of the buffer.
Daniel Veillard97b58771998-10-20 06:14:16 +00002637 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002638void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002639xmlBufferWriteCHAR(xmlBufferPtr buf, const CHAR *string) {
2640 xmlBufferCat(buf, string);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002641}
2642
Daniel Veillard97b58771998-10-20 06:14:16 +00002643/**
2644 * xmlBufferWriteChar:
Daniel Veillard011b63c1999-06-02 17:44:04 +00002645 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00002646 * @string: the string to add
2647 *
2648 * routine which manage and grows an output buffer. This one add
2649 * C chars at the end of the array.
2650 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002651void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002652xmlBufferWriteChar(xmlBufferPtr buf, const char *string) {
2653 xmlBufferCCat(buf, string);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002654}
2655
Daniel Veillard5099ae81999-04-21 20:12:07 +00002656
Daniel Veillard97b58771998-10-20 06:14:16 +00002657/**
Daniel Veillard011b63c1999-06-02 17:44:04 +00002658 * xmlBufferWriteQuotedString:
2659 * @buf: the XML buffer output
2660 * @string: the string to add
2661 *
2662 * routine which manage and grows an output buffer. This one writes
2663 * a quoted or double quoted CHAR string, checking first if it holds
2664 * quote or double-quotes internally
2665 */
2666void
2667xmlBufferWriteQuotedString(xmlBufferPtr buf, const CHAR *string) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00002668 if (xmlStrchr(string, '"')) {
2669 if (xmlStrchr(string, '\'')) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00002670 fprintf(stderr,
2671 "xmlBufferWriteQuotedString: string contains quote and double-quotes !\n");
2672 }
2673 xmlBufferCCat(buf, "'");
2674 xmlBufferCat(buf, string);
2675 xmlBufferCCat(buf, "'");
2676 } else {
2677 xmlBufferCCat(buf, "\"");
2678 xmlBufferCat(buf, string);
2679 xmlBufferCCat(buf, "\"");
2680 }
2681}
2682
2683
2684/**
Daniel Veillard97b58771998-10-20 06:14:16 +00002685 * xmlGlobalNsDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00002686 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00002687 * @cur: a namespace
2688 *
2689 * Dump a global Namespace, this is the old version based on PIs.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002690 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002691static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002692xmlGlobalNsDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002693 if (cur == NULL) {
2694 fprintf(stderr, "xmlGlobalNsDump : Ns == NULL\n");
2695 return;
2696 }
2697 if (cur->type == XML_GLOBAL_NAMESPACE) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002698 xmlBufferWriteChar(buf, "<?namespace");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002699 if (cur->href != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00002700 xmlBufferWriteChar(buf, " href=");
2701 xmlBufferWriteQuotedString(buf, cur->href);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002702 }
2703 if (cur->prefix != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00002704 xmlBufferWriteChar(buf, " AS=");
2705 xmlBufferWriteQuotedString(buf, cur->prefix);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002706 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00002707 xmlBufferWriteChar(buf, "?>\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002708 }
2709}
2710
Daniel Veillard97b58771998-10-20 06:14:16 +00002711/**
2712 * xmlGlobalNsListDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00002713 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00002714 * @cur: the first namespace
2715 *
2716 * Dump a list of global Namespace, this is the old version based on PIs.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002717 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002718static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002719xmlGlobalNsListDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002720 while (cur != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002721 xmlGlobalNsDump(buf, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002722 cur = cur->next;
2723 }
2724}
2725
Daniel Veillard97b58771998-10-20 06:14:16 +00002726/**
2727 * xmlNsDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00002728 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00002729 * @cur: a namespace
2730 *
Daniel Veillard260a68f1998-08-13 03:39:55 +00002731 * Dump a local Namespace definition.
Daniel Veillard97b58771998-10-20 06:14:16 +00002732 * Should be called in the context of attributes dumps.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002733 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002734static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002735xmlNsDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002736 if (cur == NULL) {
2737 fprintf(stderr, "xmlNsDump : Ns == NULL\n");
2738 return;
2739 }
2740 if (cur->type == XML_LOCAL_NAMESPACE) {
2741 /* Within the context of an element attributes */
2742 if (cur->prefix != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002743 xmlBufferWriteChar(buf, " xmlns:");
2744 xmlBufferWriteCHAR(buf, cur->prefix);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002745 } else
Daniel Veillard5099ae81999-04-21 20:12:07 +00002746 xmlBufferWriteChar(buf, " xmlns");
Daniel Veillard011b63c1999-06-02 17:44:04 +00002747 xmlBufferWriteChar(buf, "=");
2748 xmlBufferWriteQuotedString(buf, cur->href);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002749 }
2750}
2751
Daniel Veillard97b58771998-10-20 06:14:16 +00002752/**
2753 * xmlNsListDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00002754 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00002755 * @cur: the first namespace
2756 *
2757 * Dump a list of local Namespace definitions.
2758 * Should be called in the context of attributes dumps.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002759 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002760static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002761xmlNsListDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002762 while (cur != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002763 xmlNsDump(buf, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002764 cur = cur->next;
2765 }
2766}
2767
Daniel Veillard97b58771998-10-20 06:14:16 +00002768/**
2769 * xmlDtdDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00002770 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00002771 * @doc: the document
2772 *
2773 * Dump the XML document DTD, if any.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002774 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002775static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002776xmlDtdDump(xmlBufferPtr buf, xmlDocPtr doc) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002777 xmlDtdPtr cur = doc->intSubset;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002778
2779 if (cur == NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002780 fprintf(stderr, "xmlDtdDump : no internal subset\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002781 return;
2782 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00002783 xmlBufferWriteChar(buf, "<!DOCTYPE ");
2784 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002785 if (cur->ExternalID != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00002786 xmlBufferWriteChar(buf, " PUBLIC ");
2787 xmlBufferWriteQuotedString(buf, cur->ExternalID);
2788 xmlBufferWriteChar(buf, " ");
2789 xmlBufferWriteQuotedString(buf, cur->SystemID);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002790 } else if (cur->SystemID != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00002791 xmlBufferWriteChar(buf, " SYSTEM ");
2792 xmlBufferWriteQuotedString(buf, cur->SystemID);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002793 }
Daniel Veillard1e346af1999-02-22 10:33:01 +00002794 if ((cur->entities == NULL) && (cur->elements == NULL) &&
2795 (cur->attributes == NULL) && (cur->notations == NULL)) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002796 xmlBufferWriteChar(buf, ">\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002797 return;
2798 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00002799 xmlBufferWriteChar(buf, " [\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002800 if (cur->entities != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00002801 xmlDumpEntitiesTable(buf, (xmlEntitiesTablePtr) cur->entities);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002802 if (cur->notations != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00002803 xmlDumpNotationTable(buf, (xmlNotationTablePtr) cur->notations);
Daniel Veillard3b9def11999-01-31 22:15:06 +00002804 if (cur->elements != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00002805 xmlDumpElementTable(buf, (xmlElementTablePtr) cur->elements);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002806 if (cur->attributes != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00002807 xmlDumpAttributeTable(buf, (xmlAttributeTablePtr) cur->attributes);
2808 xmlBufferWriteChar(buf, "]");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002809
Daniel Veillard5099ae81999-04-21 20:12:07 +00002810 xmlBufferWriteChar(buf, ">\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002811}
2812
Daniel Veillard97b58771998-10-20 06:14:16 +00002813/**
2814 * xmlAttrDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00002815 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00002816 * @doc: the document
2817 * @cur: the attribute pointer
2818 *
2819 * Dump an XML attribute
Daniel Veillard260a68f1998-08-13 03:39:55 +00002820 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002821static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002822xmlAttrDump(xmlBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur) {
Daniel Veillardccb09631998-10-27 06:21:04 +00002823 CHAR *value;
2824
Daniel Veillard260a68f1998-08-13 03:39:55 +00002825 if (cur == NULL) {
2826 fprintf(stderr, "xmlAttrDump : property == NULL\n");
2827 return;
2828 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00002829 xmlBufferWriteChar(buf, " ");
Daniel Veillardb96e6431999-08-29 21:02:19 +00002830 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
2831 xmlBufferWriteCHAR(buf, cur->ns->prefix);
2832 xmlBufferWriteChar(buf, ":");
2833 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00002834 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillardccb09631998-10-27 06:21:04 +00002835 value = xmlNodeListGetString(doc, cur->val, 0);
2836 if (value) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00002837 xmlBufferWriteChar(buf, "=");
2838 xmlBufferWriteQuotedString(buf, value);
Daniel Veillardccb09631998-10-27 06:21:04 +00002839 free(value);
Daniel Veillard726c7e31999-02-08 15:13:10 +00002840 } else {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002841 xmlBufferWriteChar(buf, "=\"\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002842 }
2843}
2844
Daniel Veillard97b58771998-10-20 06:14:16 +00002845/**
2846 * xmlAttrListDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00002847 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00002848 * @doc: the document
2849 * @cur: the first attribute pointer
2850 *
2851 * Dump a list of XML attributes
Daniel Veillard260a68f1998-08-13 03:39:55 +00002852 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002853static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002854xmlAttrListDump(xmlBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002855 if (cur == NULL) {
2856 fprintf(stderr, "xmlAttrListDump : property == NULL\n");
2857 return;
2858 }
2859 while (cur != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002860 xmlAttrDump(buf, doc, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002861 cur = cur->next;
2862 }
2863}
2864
Daniel Veillard260a68f1998-08-13 03:39:55 +00002865
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002866static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002867xmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level);
Daniel Veillard97b58771998-10-20 06:14:16 +00002868/**
2869 * xmlNodeListDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00002870 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00002871 * @doc: the document
2872 * @cur: the first node
2873 * @level: the imbrication level for indenting
2874 *
2875 * Dump an XML node list, recursive behaviour,children are printed too.
2876 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002877static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002878xmlNodeListDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level) {
Daniel Veillardccb09631998-10-27 06:21:04 +00002879 int needIndent = 0, i;
2880
Daniel Veillard260a68f1998-08-13 03:39:55 +00002881 if (cur == NULL) {
2882 fprintf(stderr, "xmlNodeListDump : node == NULL\n");
2883 return;
2884 }
2885 while (cur != NULL) {
Daniel Veillardccb09631998-10-27 06:21:04 +00002886 if ((cur->type != XML_TEXT_NODE) &&
2887 (cur->type != XML_ENTITY_REF_NODE)) {
2888 if (!needIndent) {
2889 needIndent = 1;
Daniel Veillard5099ae81999-04-21 20:12:07 +00002890 xmlBufferWriteChar(buf, "\n");
Daniel Veillardccb09631998-10-27 06:21:04 +00002891 }
2892 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00002893 xmlNodeDump(buf, doc, cur, level);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002894 cur = cur->next;
2895 }
Daniel Veillardccb09631998-10-27 06:21:04 +00002896 if ((xmlIndentTreeOutput) && (needIndent))
2897 for (i = 1;i < level;i++)
Daniel Veillard5099ae81999-04-21 20:12:07 +00002898 xmlBufferWriteChar(buf, " ");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002899}
2900
Daniel Veillard97b58771998-10-20 06:14:16 +00002901/**
Daniel Veillardccb09631998-10-27 06:21:04 +00002902 * xmlNodeDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00002903 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00002904 * @doc: the document
2905 * @cur: the current node
2906 * @level: the imbrication level for indenting
2907 *
2908 * Dump an XML node, recursive behaviour,children are printed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002909 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002910static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002911xmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002912 int i;
2913
2914 if (cur == NULL) {
2915 fprintf(stderr, "xmlNodeDump : node == NULL\n");
2916 return;
2917 }
Daniel Veillard0bef1311998-10-14 02:36:47 +00002918 if (cur->type == XML_TEXT_NODE) {
Daniel Veillard14fff061999-06-22 21:49:07 +00002919 if (cur->content != NULL) {
2920 CHAR *buffer;
2921
2922 buffer = xmlEncodeEntitiesReentrant(doc, cur->content);
2923 if (buffer != NULL) {
2924 xmlBufferWriteCHAR(buf, buffer);
2925 free(buffer);
2926 }
2927 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002928 return;
2929 }
Daniel Veillardb96e6431999-08-29 21:02:19 +00002930 if (cur->type == XML_PI_NODE) {
2931 if (cur->content != NULL) {
2932 xmlBufferWriteChar(buf, "<?");
2933 xmlBufferWriteCHAR(buf, cur->name);
2934 if (cur->content != NULL) {
2935 xmlBufferWriteChar(buf, " ");
2936 xmlBufferWriteCHAR(buf, cur->content);
2937 }
2938 xmlBufferWriteChar(buf, "?>\n");
2939 }
2940 return;
2941 }
Daniel Veillard0bef1311998-10-14 02:36:47 +00002942 if (cur->type == XML_COMMENT_NODE) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002943 if (cur->content != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002944 xmlBufferWriteChar(buf, "<!--");
2945 xmlBufferWriteCHAR(buf, cur->content);
Daniel Veillardb96e6431999-08-29 21:02:19 +00002946 xmlBufferWriteChar(buf, "-->\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002947 }
2948 return;
2949 }
Daniel Veillardccb09631998-10-27 06:21:04 +00002950 if (cur->type == XML_ENTITY_REF_NODE) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002951 xmlBufferWriteChar(buf, "&");
2952 xmlBufferWriteCHAR(buf, cur->name);
2953 xmlBufferWriteChar(buf, ";");
Daniel Veillardccb09631998-10-27 06:21:04 +00002954 return;
2955 }
Daniel Veillardb05deb71999-08-10 19:04:08 +00002956 if (cur->type == XML_CDATA_SECTION_NODE) {
2957 xmlBufferWriteChar(buf, "<![CDATA[");
2958 if (cur->content != NULL)
2959 xmlBufferWriteCHAR(buf, cur->content);
2960 xmlBufferWriteChar(buf, "]]>");
2961 return;
2962 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002963 if (xmlIndentTreeOutput)
2964 for (i = 0;i < level;i++)
Daniel Veillard5099ae81999-04-21 20:12:07 +00002965 xmlBufferWriteChar(buf, " ");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002966
Daniel Veillard5099ae81999-04-21 20:12:07 +00002967 xmlBufferWriteChar(buf, "<");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002968 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002969 xmlBufferWriteCHAR(buf, cur->ns->prefix);
2970 xmlBufferWriteChar(buf, ":");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002971 }
2972
Daniel Veillard5099ae81999-04-21 20:12:07 +00002973 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002974 if (cur->nsDef)
Daniel Veillard5099ae81999-04-21 20:12:07 +00002975 xmlNsListDump(buf, cur->nsDef);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002976 if (cur->properties != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00002977 xmlAttrListDump(buf, doc, cur->properties);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002978
2979 if ((cur->content == NULL) && (cur->childs == NULL)) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002980 xmlBufferWriteChar(buf, "/>\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002981 return;
2982 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00002983 xmlBufferWriteChar(buf, ">");
Daniel Veillard14fff061999-06-22 21:49:07 +00002984 if (cur->content != NULL) {
2985 CHAR *buffer;
2986
2987 buffer = xmlEncodeEntitiesReentrant(doc, cur->content);
2988 if (buffer != NULL) {
2989 xmlBufferWriteCHAR(buf, buffer);
2990 free(buffer);
2991 }
2992 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002993 if (cur->childs != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002994 xmlNodeListDump(buf, doc, cur->childs, level + 1);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002995 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00002996 xmlBufferWriteChar(buf, "</");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002997 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002998 xmlBufferWriteCHAR(buf, cur->ns->prefix);
2999 xmlBufferWriteChar(buf, ":");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003000 }
3001
Daniel Veillard5099ae81999-04-21 20:12:07 +00003002 xmlBufferWriteCHAR(buf, cur->name);
3003 xmlBufferWriteChar(buf, ">\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003004}
3005
Daniel Veillard97b58771998-10-20 06:14:16 +00003006/**
3007 * xmlDocContentDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003008 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003009 * @cur: the document
3010 *
3011 * Dump an XML document.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003012 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003013static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00003014xmlDocContentDump(xmlBufferPtr buf, xmlDocPtr cur) {
Daniel Veillardbe70ff71999-07-05 16:50:46 +00003015 xmlBufferWriteChar(buf, "<?xml version=");
3016 if (cur->version != NULL)
3017 xmlBufferWriteQuotedString(buf, cur->version);
3018 else
3019 xmlBufferWriteChar(buf, "\"1.0\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003020 if (cur->encoding != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00003021 xmlBufferWriteChar(buf, " encoding=");
3022 xmlBufferWriteQuotedString(buf, cur->encoding);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003023 }
3024 switch (cur->standalone) {
3025 case 0:
Daniel Veillard5099ae81999-04-21 20:12:07 +00003026 xmlBufferWriteChar(buf, " standalone=\"no\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003027 break;
3028 case 1:
Daniel Veillard5099ae81999-04-21 20:12:07 +00003029 xmlBufferWriteChar(buf, " standalone=\"yes\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003030 break;
3031 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003032 xmlBufferWriteChar(buf, "?>\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003033 if (cur->intSubset != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00003034 xmlDtdDump(buf, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003035 if (cur->root != NULL) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00003036 xmlNodePtr child = cur->root;
3037
Daniel Veillard260a68f1998-08-13 03:39:55 +00003038 /* global namespace definitions, the old way */
3039 if (oldXMLWDcompatibility)
Daniel Veillard5099ae81999-04-21 20:12:07 +00003040 xmlGlobalNsListDump(buf, cur->oldNs);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003041 else
3042 xmlUpgradeOldNs(cur);
Daniel Veillardb96e6431999-08-29 21:02:19 +00003043
3044 while (child != NULL) {
3045 xmlNodeDump(buf, cur, child, 0);
3046 child = child->next;
3047 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003048 }
3049}
3050
Daniel Veillard97b58771998-10-20 06:14:16 +00003051/**
3052 * xmlDocDumpMemory:
3053 * @cur: the document
3054 * @mem: OUT: the memory pointer
3055 * @size: OUT: the memory lenght
3056 *
3057 * Dump an XML document in memory and return the CHAR * and it's size.
3058 * It's up to the caller to free the memory.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003059 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003060void
3061xmlDocDumpMemory(xmlDocPtr cur, CHAR**mem, int *size) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003062 xmlBufferPtr buf;
3063
Daniel Veillard260a68f1998-08-13 03:39:55 +00003064 if (cur == NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003065#ifdef DEBUG_TREE
3066 fprintf(stderr, "xmlDocDumpMemory : document == NULL\n");
3067#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00003068 *mem = NULL;
3069 *size = 0;
3070 return;
3071 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003072 buf = xmlBufferCreate();
3073 if (buf == NULL) {
3074 *mem = NULL;
3075 *size = 0;
3076 return;
3077 }
3078 xmlDocContentDump(buf, cur);
Daniel Veillardb05deb71999-08-10 19:04:08 +00003079 *mem = xmlStrndup(buf->content, buf->use);
Daniel Veillard5099ae81999-04-21 20:12:07 +00003080 *size = buf->use;
Daniel Veillardb05deb71999-08-10 19:04:08 +00003081 xmlBufferFree(buf);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003082}
3083
Daniel Veillard97b58771998-10-20 06:14:16 +00003084/**
3085 * xmlGetDocCompressMode:
3086 * @doc: the document
3087 *
3088 * get the compression ratio for a document, ZLIB based
Daniel Veillard1e346af1999-02-22 10:33:01 +00003089 * Returns 0 (uncompressed) to 9 (max compression)
Daniel Veillard151b1b01998-09-23 00:49:46 +00003090 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003091int
3092 xmlGetDocCompressMode (xmlDocPtr doc) {
Daniel Veillard15a8df41998-09-24 19:15:06 +00003093 if (doc == NULL) return(-1);
3094 return(doc->compression);
3095}
3096
Daniel Veillard97b58771998-10-20 06:14:16 +00003097/**
3098 * xmlSetDocCompressMode:
3099 * @doc: the document
3100 * @mode: the compression ratio
3101 *
3102 * set the compression ratio for a document, ZLIB based
3103 * Correct values: 0 (uncompressed) to 9 (max compression)
3104 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003105void
3106xmlSetDocCompressMode (xmlDocPtr doc, int mode) {
Daniel Veillard15a8df41998-09-24 19:15:06 +00003107 if (doc == NULL) return;
3108 if (mode < 0) doc->compression = 0;
3109 else if (mode > 9) doc->compression = 9;
3110 else doc->compression = mode;
3111}
3112
Daniel Veillard97b58771998-10-20 06:14:16 +00003113/**
3114 * xmlGetCompressMode:
3115 *
3116 * get the default compression mode used, ZLIB based.
Daniel Veillard1e346af1999-02-22 10:33:01 +00003117 * Returns 0 (uncompressed) to 9 (max compression)
Daniel Veillard15a8df41998-09-24 19:15:06 +00003118 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003119int
3120 xmlGetCompressMode(void) {
Daniel Veillard151b1b01998-09-23 00:49:46 +00003121 return(xmlCompressMode);
3122}
Daniel Veillard97b58771998-10-20 06:14:16 +00003123
3124/**
3125 * xmlSetCompressMode:
3126 * @mode: the compression ratio
3127 *
3128 * set the default compression mode used, ZLIB based
3129 * Correct values: 0 (uncompressed) to 9 (max compression)
3130 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003131void
3132xmlSetCompressMode(int mode) {
Daniel Veillard151b1b01998-09-23 00:49:46 +00003133 if (mode < 0) xmlCompressMode = 0;
Daniel Veillard15a8df41998-09-24 19:15:06 +00003134 else if (mode > 9) xmlCompressMode = 9;
Daniel Veillard151b1b01998-09-23 00:49:46 +00003135 else xmlCompressMode = mode;
3136}
3137
Daniel Veillard97b58771998-10-20 06:14:16 +00003138/**
3139 * xmlDocDump:
3140 * @f: the FILE*
3141 * @cur: the document
3142 *
3143 * Dump an XML document to an open FILE.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003144 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003145void
3146xmlDocDump(FILE *f, xmlDocPtr cur) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003147 xmlBufferPtr buf;
3148
Daniel Veillard260a68f1998-08-13 03:39:55 +00003149 if (cur == NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003150#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00003151 fprintf(stderr, "xmlDocDump : document == NULL\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003152#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00003153 return;
3154 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003155 buf = xmlBufferCreate();
3156 if (buf == NULL) return;
3157 xmlDocContentDump(buf, cur);
3158 xmlBufferDump(f, buf);
3159 xmlBufferFree(buf);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003160}
3161
Daniel Veillard97b58771998-10-20 06:14:16 +00003162/**
3163 * xmlSaveFile:
3164 * @filename: the filename
3165 * @cur: the document
3166 *
3167 * Dump an XML document to a file. Will use compression if
3168 * compiled in and enabled.
3169 * returns: the number of file written or -1 in case of failure.
Daniel Veillard151b1b01998-09-23 00:49:46 +00003170 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003171int
3172xmlSaveFile(const char *filename, xmlDocPtr cur) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003173 xmlBufferPtr buf;
Daniel Veillard151b1b01998-09-23 00:49:46 +00003174#ifdef HAVE_ZLIB_H
3175 gzFile zoutput = NULL;
3176 char mode[15];
3177#endif
Daniel Veillardccb09631998-10-27 06:21:04 +00003178 FILE *output = NULL;
Daniel Veillard151b1b01998-09-23 00:49:46 +00003179 int ret;
3180
Daniel Veillard5099ae81999-04-21 20:12:07 +00003181 /*
3182 * save the content to a temp buffer.
3183 */
3184 buf = xmlBufferCreate();
3185 if (buf == NULL) return(0);
3186 xmlDocContentDump(buf, cur);
3187
Daniel Veillard151b1b01998-09-23 00:49:46 +00003188#ifdef HAVE_ZLIB_H
Daniel Veillarddc3dd9d1998-09-24 19:25:54 +00003189 if ((cur->compression > 0) && (cur->compression <= 9)) {
3190 sprintf(mode, "w%d", cur->compression);
Daniel Veillard151b1b01998-09-23 00:49:46 +00003191 zoutput = gzopen(filename, mode);
3192 }
3193 if (zoutput == NULL) {
3194#endif
3195 output = fopen(filename, "w");
3196 if (output == NULL) return(-1);
3197#ifdef HAVE_ZLIB_H
3198 }
Daniel Veillard151b1b01998-09-23 00:49:46 +00003199
Daniel Veillard151b1b01998-09-23 00:49:46 +00003200 if (zoutput != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003201 ret = gzwrite(zoutput, buf->content, sizeof(CHAR) * buf->use);
Daniel Veillard151b1b01998-09-23 00:49:46 +00003202 gzclose(zoutput);
Daniel Veillard5099ae81999-04-21 20:12:07 +00003203 } else {
3204#endif
3205 ret = xmlBufferDump(output, buf);
3206 fclose(output);
3207#ifdef HAVE_ZLIB_H
Daniel Veillard151b1b01998-09-23 00:49:46 +00003208 }
3209#endif
Manish Vachharajani5e60f5a1999-05-29 03:04:30 +00003210 xmlBufferFree(buf);
Daniel Veillard151b1b01998-09-23 00:49:46 +00003211 return(ret * sizeof(CHAR));
3212}
3213