blob: 605119e0d2cc47a329b4391c68a815f86a107f71 [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 Veillard7f7d1111999-09-22 09:46:25 +00009#ifdef WIN32
10#define HAVE_FCNTL_H
11#include <io.h>
12#else
Daniel Veillard151b1b01998-09-23 00:49:46 +000013#include "config.h"
Daniel Veillard7f7d1111999-09-22 09:46:25 +000014#endif
15
Daniel Veillard260a68f1998-08-13 03:39:55 +000016#include <stdio.h>
Daniel Veillard260a68f1998-08-13 03:39:55 +000017#include <string.h> /* for memset() only ! */
18
Daniel Veillard7f7d1111999-09-22 09:46:25 +000019#ifdef HAVE_CTYPE_H
20#include <ctype.h>
21#endif
22#ifdef HAVE_STDLIB_H
23#include <stdlib.h>
24#endif
Daniel Veillard151b1b01998-09-23 00:49:46 +000025#ifdef HAVE_ZLIB_H
26#include <zlib.h>
27#endif
28
Daniel Veillard6454aec1999-09-02 22:04:43 +000029#include "xmlmemory.h"
Daniel Veillard260a68f1998-08-13 03:39:55 +000030#include "tree.h"
31#include "entities.h"
Daniel Veillard3b9def11999-01-31 22:15:06 +000032#include "valid.h"
Daniel Veillard260a68f1998-08-13 03:39:55 +000033
Daniel Veillarddd6b3671999-09-23 22:19:22 +000034static xmlChar xmlStringText[] = { 't', 'e', 'x', 't', 0 };
Daniel Veillard260a68f1998-08-13 03:39:55 +000035int oldXMLWDcompatibility = 0;
36int xmlIndentTreeOutput = 1;
37
Daniel Veillard15a8df41998-09-24 19:15:06 +000038static int xmlCompressMode = 0;
39
Daniel Veillard39a1f9a1999-01-17 19:11:59 +000040#define UPDATE_LAST_CHILD(n) if ((n) != NULL) { \
41 xmlNodePtr ulccur = (n)->childs; \
42 if (ulccur == NULL) { \
43 (n)->last = NULL; \
44 } else { \
45 while (ulccur->next != NULL) ulccur = ulccur->next; \
46 (n)->last = ulccur; \
Daniel Veillard1e346af1999-02-22 10:33:01 +000047}}
Daniel Veillard39a1f9a1999-01-17 19:11:59 +000048
Daniel Veillard260a68f1998-08-13 03:39:55 +000049/************************************************************************
50 * *
51 * Allocation and deallocation of basic structures *
52 * *
53 ************************************************************************/
54
Daniel Veillard97b58771998-10-20 06:14:16 +000055/**
56 * xmlUpgradeOldNs:
57 * @doc: a document pointer
58 *
59 * Upgrade old style Namespaces (PI) and move them to the root of the document.
Daniel Veillard260a68f1998-08-13 03:39:55 +000060 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +000061void
62xmlUpgradeOldNs(xmlDocPtr doc) {
Daniel Veillard260a68f1998-08-13 03:39:55 +000063 xmlNsPtr cur;
64
65 if ((doc == NULL) || (doc->oldNs == NULL)) return;
66 if (doc->root == NULL) {
67 fprintf(stderr, "xmlUpgradeOldNs: failed no root !\n");
68 return;
69 }
70
71 cur = doc->oldNs;
72 while (cur->next != NULL) {
73 cur->type = XML_LOCAL_NAMESPACE;
74 cur = cur->next;
75 }
76 cur->type = XML_LOCAL_NAMESPACE;
77 cur->next = doc->root->nsDef;
78 doc->root->nsDef = doc->oldNs;
79 doc->oldNs = NULL;
80}
81
Daniel Veillard97b58771998-10-20 06:14:16 +000082/**
83 * xmlNewNs:
84 * @node: the element carrying the namespace
85 * @href: the URI associated
86 * @prefix: the prefix for the namespace
87 *
Daniel Veillard260a68f1998-08-13 03:39:55 +000088 * Creation of a new Namespace.
Daniel Veillard1e346af1999-02-22 10:33:01 +000089 * Returns returns a new namespace pointer
Daniel Veillard260a68f1998-08-13 03:39:55 +000090 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +000091xmlNsPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +000092xmlNewNs(xmlNodePtr node, const xmlChar *href, const xmlChar *prefix) {
Daniel Veillard260a68f1998-08-13 03:39:55 +000093 xmlNsPtr cur;
94
95 if (href == NULL) {
96 fprintf(stderr, "xmlNewNs: href == NULL !\n");
97 return(NULL);
98 }
99
100 /*
101 * Allocate a new DTD and fill the fields.
102 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000103 cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000104 if (cur == NULL) {
105 fprintf(stderr, "xmlNewNs : malloc failed\n");
106 return(NULL);
107 }
108
109 cur->type = XML_LOCAL_NAMESPACE;
110 if (href != NULL)
111 cur->href = xmlStrdup(href);
112 else
113 cur->href = NULL;
114 if (prefix != NULL)
115 cur->prefix = xmlStrdup(prefix);
116 else
117 cur->prefix = NULL;
118
119 /*
120 * Add it at the end to preserve parsing order ...
121 */
122 cur->next = NULL;
123 if (node != NULL) {
124 if (node->nsDef == NULL) {
125 node->nsDef = cur;
126 } else {
127 xmlNsPtr prev = node->nsDef;
128
129 while (prev->next != NULL) prev = prev->next;
130 prev->next = cur;
131 }
132 }
133
134 return(cur);
135}
136
Daniel Veillard97b58771998-10-20 06:14:16 +0000137/**
138 * xmlNewGlobalNs:
139 * @doc: the document carrying the namespace
140 * @href: the URI associated
141 * @prefix: the prefix for the namespace
142 *
143 * Creation of a Namespace, the old way using PI and without scoping, to AVOID.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000144 * Returns returns a new namespace pointer
Daniel Veillard260a68f1998-08-13 03:39:55 +0000145 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000146xmlNsPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000147xmlNewGlobalNs(xmlDocPtr doc, const xmlChar *href, const xmlChar *prefix) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000148 xmlNsPtr cur;
149
150 /*
151 * Allocate a new DTD and fill the fields.
152 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000153 cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000154 if (cur == NULL) {
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000155 fprintf(stderr, "xmlNewGlobalNs : malloc failed\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +0000156 return(NULL);
157 }
158
159 cur->type = XML_GLOBAL_NAMESPACE;
160 if (href != NULL)
161 cur->href = xmlStrdup(href);
162 else
163 cur->href = NULL;
164 if (prefix != NULL)
165 cur->prefix = xmlStrdup(prefix);
166 else
167 cur->prefix = NULL;
168
169 /*
170 * Add it at the end to preserve parsing order ...
171 */
172 cur->next = NULL;
173 if (doc != NULL) {
174 if (doc->oldNs == NULL) {
175 doc->oldNs = cur;
176 } else {
177 xmlNsPtr prev = doc->oldNs;
178
179 while (prev->next != NULL) prev = prev->next;
180 prev->next = cur;
181 }
182 }
183
184 return(cur);
185}
186
Daniel Veillard97b58771998-10-20 06:14:16 +0000187/**
188 * xmlSetNs:
189 * @node: a node in the document
190 * @ns: a namespace pointer
191 *
192 * Associate a namespace to a node, a posteriori.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000193 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000194void
195xmlSetNs(xmlNodePtr node, xmlNsPtr ns) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000196 if (node == NULL) {
197 fprintf(stderr, "xmlSetNs: node == NULL\n");
198 return;
199 }
200 node->ns = ns;
201}
202
Daniel Veillard97b58771998-10-20 06:14:16 +0000203/**
204 * xmlFreeNs:
205 * @cur: the namespace pointer
206 *
207 * Free up the structures associated to a namespace
Daniel Veillard260a68f1998-08-13 03:39:55 +0000208 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000209void
210xmlFreeNs(xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000211 if (cur == NULL) {
212 fprintf(stderr, "xmlFreeNs : ns == NULL\n");
213 return;
214 }
Daniel Veillard6454aec1999-09-02 22:04:43 +0000215 if (cur->href != NULL) xmlFree((char *) cur->href);
216 if (cur->prefix != NULL) xmlFree((char *) cur->prefix);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000217 memset(cur, -1, sizeof(xmlNs));
Daniel Veillard6454aec1999-09-02 22:04:43 +0000218 xmlFree(cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000219}
220
Daniel Veillard97b58771998-10-20 06:14:16 +0000221/**
222 * xmlFreeNsList:
223 * @cur: the first namespace pointer
224 *
225 * Free up all the structures associated to the chained namespaces.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000226 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000227void
228xmlFreeNsList(xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000229 xmlNsPtr next;
230 if (cur == NULL) {
231 fprintf(stderr, "xmlFreeNsList : ns == NULL\n");
232 return;
233 }
234 while (cur != NULL) {
235 next = cur->next;
236 xmlFreeNs(cur);
237 cur = next;
238 }
239}
240
Daniel Veillard97b58771998-10-20 06:14:16 +0000241/**
242 * xmlNewDtd:
243 * @doc: the document pointer
244 * @name: the DTD name
245 * @ExternalID: the external ID
246 * @SystemID: the system ID
247 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000248 * Creation of a new DTD.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000249 * Returns a pointer to the new DTD structure
Daniel Veillard260a68f1998-08-13 03:39:55 +0000250 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000251xmlDtdPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000252xmlNewDtd(xmlDocPtr doc, const xmlChar *name,
253 const xmlChar *ExternalID, const xmlChar *SystemID) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000254 xmlDtdPtr cur;
255
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000256 if ((doc != NULL) && (doc->extSubset != NULL)) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000257 fprintf(stderr, "xmlNewDtd(%s): document %s already have a DTD %s\n",
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000258 /* !!! */ (char *) name, doc->name,
259 /* !!! */ (char *)doc->extSubset->name);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000260 }
261
262 /*
263 * Allocate a new DTD and fill the fields.
264 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000265 cur = (xmlDtdPtr) xmlMalloc(sizeof(xmlDtd));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000266 if (cur == NULL) {
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000267 fprintf(stderr, "xmlNewDtd : malloc failed\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +0000268 return(NULL);
269 }
270
271 if (name != NULL)
272 cur->name = xmlStrdup(name);
273 else
274 cur->name = NULL;
275 if (ExternalID != NULL)
276 cur->ExternalID = xmlStrdup(ExternalID);
277 else
278 cur->ExternalID = NULL;
279 if (SystemID != NULL)
280 cur->SystemID = xmlStrdup(SystemID);
281 else
282 cur->SystemID = NULL;
Daniel Veillard1e346af1999-02-22 10:33:01 +0000283 cur->notations = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000284 cur->elements = NULL;
Daniel Veillard1e346af1999-02-22 10:33:01 +0000285 cur->attributes = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000286 cur->entities = NULL;
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000287 if (doc != NULL)
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000288 doc->extSubset = cur;
289
290 return(cur);
291}
292
293/**
294 * xmlCreateIntSubset:
295 * @doc: the document pointer
296 * @name: the DTD name
297 * @ExternalID: the external ID
298 * @SystemID: the system ID
299 *
Daniel Veillard1e346af1999-02-22 10:33:01 +0000300 * Create the internal subset of a document
301 * Returns a pointer to the new DTD structure
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000302 */
303xmlDtdPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000304xmlCreateIntSubset(xmlDocPtr doc, const xmlChar *name,
305 const xmlChar *ExternalID, const xmlChar *SystemID) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000306 xmlDtdPtr cur;
307
308 if ((doc != NULL) && (doc->intSubset != NULL)) {
309 fprintf(stderr,
310 "xmlCreateIntSubset(): document %s already have an internal subset\n",
311 doc->name);
312 return(NULL);
313 }
314
315 /*
316 * Allocate a new DTD and fill the fields.
317 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000318 cur = (xmlDtdPtr) xmlMalloc(sizeof(xmlDtd));
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000319 if (cur == NULL) {
320 fprintf(stderr, "xmlNewDtd : malloc failed\n");
321 return(NULL);
322 }
323
324 if (name != NULL)
325 cur->name = xmlStrdup(name);
326 else
327 cur->name = NULL;
328 if (ExternalID != NULL)
329 cur->ExternalID = xmlStrdup(ExternalID);
330 else
331 cur->ExternalID = NULL;
332 if (SystemID != NULL)
333 cur->SystemID = xmlStrdup(SystemID);
334 else
335 cur->SystemID = NULL;
Daniel Veillard1e346af1999-02-22 10:33:01 +0000336 cur->notations = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000337 cur->elements = NULL;
Daniel Veillard1e346af1999-02-22 10:33:01 +0000338 cur->attributes = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000339 cur->entities = NULL;
340 if (doc != NULL)
341 doc->intSubset = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000342
343 return(cur);
344}
345
Daniel Veillard97b58771998-10-20 06:14:16 +0000346/**
347 * xmlFreeDtd:
348 * @cur: the DTD structure to free up
349 *
350 * Free a DTD structure.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000351 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000352void
353xmlFreeDtd(xmlDtdPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000354 if (cur == NULL) {
355 fprintf(stderr, "xmlFreeDtd : DTD == NULL\n");
356 return;
357 }
Daniel Veillard6454aec1999-09-02 22:04:43 +0000358 if (cur->name != NULL) xmlFree((char *) cur->name);
359 if (cur->SystemID != NULL) xmlFree((char *) cur->SystemID);
360 if (cur->ExternalID != NULL) xmlFree((char *) cur->ExternalID);
Daniel Veillard1e346af1999-02-22 10:33:01 +0000361 if (cur->notations != NULL)
362 xmlFreeNotationTable((xmlNotationTablePtr) cur->notations);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000363 if (cur->elements != NULL)
Daniel Veillard3b9def11999-01-31 22:15:06 +0000364 xmlFreeElementTable((xmlElementTablePtr) cur->elements);
Daniel Veillard1e346af1999-02-22 10:33:01 +0000365 if (cur->attributes != NULL)
366 xmlFreeAttributeTable((xmlAttributeTablePtr) cur->attributes);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000367 if (cur->entities != NULL)
368 xmlFreeEntitiesTable((xmlEntitiesTablePtr) cur->entities);
369 memset(cur, -1, sizeof(xmlDtd));
Daniel Veillard6454aec1999-09-02 22:04:43 +0000370 xmlFree(cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000371}
372
Daniel Veillard97b58771998-10-20 06:14:16 +0000373/**
374 * xmlNewDoc:
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000375 * @version: xmlChar string giving the version of XML "1.0"
Daniel Veillard97b58771998-10-20 06:14:16 +0000376 *
Daniel Veillard1e346af1999-02-22 10:33:01 +0000377 * Returns a new document
Daniel Veillard260a68f1998-08-13 03:39:55 +0000378 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000379xmlDocPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000380xmlNewDoc(const xmlChar *version) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000381 xmlDocPtr cur;
382
383 if (version == NULL) {
384 fprintf(stderr, "xmlNewDoc : version == NULL\n");
385 return(NULL);
386 }
387
388 /*
389 * Allocate a new document and fill the fields.
390 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000391 cur = (xmlDocPtr) xmlMalloc(sizeof(xmlDoc));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000392 if (cur == NULL) {
393 fprintf(stderr, "xmlNewDoc : malloc failed\n");
394 return(NULL);
395 }
396
Daniel Veillard33942841998-10-18 19:12:41 +0000397 cur->type = XML_DOCUMENT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000398 cur->version = xmlStrdup(version);
399 cur->name = NULL;
400 cur->root = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000401 cur->intSubset = NULL;
402 cur->extSubset = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000403 cur->oldNs = NULL;
404 cur->encoding = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000405 cur->standalone = -1;
Daniel Veillard11a48ec1999-11-23 10:40:46 +0000406 cur->compression = -1; /* not initialized */
Daniel Veillardb96e6431999-08-29 21:02:19 +0000407 cur->ids = NULL;
Daniel Veillardc08a2c61999-09-08 21:35:25 +0000408 cur->refs = NULL;
Daniel Veillard27d88741999-05-29 11:51:49 +0000409#ifndef XML_WITHOUT_CORBA
Daniel Veillard27fb0751998-10-17 06:47:46 +0000410 cur->_private = NULL;
411 cur->vepv = NULL;
412#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000413 return(cur);
414}
415
Daniel Veillard97b58771998-10-20 06:14:16 +0000416/**
417 * xmlFreeDoc:
418 * @cur: pointer to the document
419 * @:
420 *
421 * Free up all the structures used by a document, tree included.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000422 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000423void
424xmlFreeDoc(xmlDocPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000425 if (cur == NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000426#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +0000427 fprintf(stderr, "xmlFreeDoc : document == NULL\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000428#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000429 return;
430 }
Daniel Veillard6454aec1999-09-02 22:04:43 +0000431 if (cur->version != NULL) xmlFree((char *) cur->version);
432 if (cur->name != NULL) xmlFree((char *) cur->name);
433 if (cur->encoding != NULL) xmlFree((char *) cur->encoding);
434 if (cur->root != NULL) xmlFreeNodeList(cur->root);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000435 if (cur->intSubset != NULL) xmlFreeDtd(cur->intSubset);
436 if (cur->extSubset != NULL) xmlFreeDtd(cur->extSubset);
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000437 if (cur->oldNs != NULL) xmlFreeNsList(cur->oldNs);
Daniel Veillardb96e6431999-08-29 21:02:19 +0000438 if (cur->ids != NULL) xmlFreeIDTable((xmlIDTablePtr) cur->ids);
Daniel Veillardc08a2c61999-09-08 21:35:25 +0000439 if (cur->refs != NULL) xmlFreeRefTable((xmlRefTablePtr) cur->refs);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000440 memset(cur, -1, sizeof(xmlDoc));
Daniel Veillard6454aec1999-09-02 22:04:43 +0000441 xmlFree(cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000442}
443
Daniel Veillard97b58771998-10-20 06:14:16 +0000444/**
Daniel Veillard16253641998-10-28 22:58:05 +0000445 * xmlStringLenGetNodeList:
446 * @doc: the document
447 * @value: the value of the text
Daniel Veillard1e346af1999-02-22 10:33:01 +0000448 * @len: the length of the string value
Daniel Veillard16253641998-10-28 22:58:05 +0000449 *
450 * Parse the value string and build the node list associated. Should
451 * produce a flat tree with only TEXTs and ENTITY_REFs.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000452 * Returns a pointer to the first child
Daniel Veillard16253641998-10-28 22:58:05 +0000453 */
454xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000455xmlStringLenGetNodeList(xmlDocPtr doc, const xmlChar *value, int len) {
Daniel Veillard16253641998-10-28 22:58:05 +0000456 xmlNodePtr ret = NULL, last = NULL;
457 xmlNodePtr node;
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000458 xmlChar *val;
459 const xmlChar *cur = value;
460 const xmlChar *q;
Daniel Veillard25940b71998-10-29 05:51:30 +0000461 xmlEntityPtr ent;
Daniel Veillard16253641998-10-28 22:58:05 +0000462
463 if (value == NULL) return(NULL);
464
465 q = cur;
466 while ((*cur != 0) && (cur - value < len)) {
467 if (*cur == '&') {
Daniel Veillard25940b71998-10-29 05:51:30 +0000468 /*
469 * Save the current text.
470 */
Daniel Veillard16253641998-10-28 22:58:05 +0000471 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000472 if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
473 xmlNodeAddContentLen(last, q, cur - q);
474 } else {
475 node = xmlNewDocTextLen(doc, q, cur - q);
476 if (node == NULL) return(ret);
477 if (last == NULL)
478 last = ret = node;
479 else {
480 last->next = node;
481 node->prev = last;
482 last = node;
483 }
Daniel Veillard16253641998-10-28 22:58:05 +0000484 }
485 }
Daniel Veillard25940b71998-10-29 05:51:30 +0000486 /*
487 * Read the entity string
488 */
Daniel Veillard16253641998-10-28 22:58:05 +0000489 cur++;
490 q = cur;
491 while ((*cur != 0) && (cur - value < len) && (*cur != ';')) cur++;
492 if ((*cur == 0) || (cur - value >= len)) {
493 fprintf(stderr,
Daniel Veillard011b63c1999-06-02 17:44:04 +0000494 "xmlStringLenGetNodeList: unterminated entity %30s\n", q);
Daniel Veillard16253641998-10-28 22:58:05 +0000495 return(ret);
496 }
497 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000498 /*
499 * Predefined entities don't generate nodes
500 */
Daniel Veillard16253641998-10-28 22:58:05 +0000501 val = xmlStrndup(q, cur - q);
Daniel Veillard25940b71998-10-29 05:51:30 +0000502 ent = xmlGetDocEntity(doc, val);
503 if ((ent != NULL) &&
504 (ent->type == XML_INTERNAL_PREDEFINED_ENTITY)) {
505 if (last == NULL) {
506 node = xmlNewDocText(doc, ent->content);
507 last = ret = node;
508 } else
509 xmlNodeAddContent(last, ent->content);
510
511 } else {
512 /*
513 * Create a new REFERENCE_REF node
514 */
515 node = xmlNewReference(doc, val);
Daniel Veillard242590e1998-11-13 18:04:35 +0000516 if (node == NULL) {
Daniel Veillard6454aec1999-09-02 22:04:43 +0000517 if (val != NULL) xmlFree(val);
Daniel Veillard242590e1998-11-13 18:04:35 +0000518 return(ret);
519 }
Daniel Veillard25940b71998-10-29 05:51:30 +0000520 if (last == NULL)
521 last = ret = node;
522 else {
523 last->next = node;
524 node->prev = last;
525 last = node;
526 }
Daniel Veillard16253641998-10-28 22:58:05 +0000527 }
Daniel Veillard6454aec1999-09-02 22:04:43 +0000528 xmlFree(val);
Daniel Veillard16253641998-10-28 22:58:05 +0000529 }
530 cur++;
531 q = cur;
532 } else
533 cur++;
534 }
535 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000536 /*
537 * Handle the last piece of text.
538 */
539 if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
540 xmlNodeAddContentLen(last, q, cur - q);
541 } else {
542 node = xmlNewDocTextLen(doc, q, cur - q);
543 if (node == NULL) return(ret);
544 if (last == NULL)
545 last = ret = node;
546 else {
547 last->next = node;
548 node->prev = last;
549 last = node;
550 }
Daniel Veillard16253641998-10-28 22:58:05 +0000551 }
552 }
553 return(ret);
554}
555
556/**
Daniel Veillardccb09631998-10-27 06:21:04 +0000557 * xmlStringGetNodeList:
558 * @doc: the document
559 * @value: the value of the attribute
560 *
561 * Parse the value string and build the node list associated. Should
562 * produce a flat tree with only TEXTs and ENTITY_REFs.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000563 * Returns a pointer to the first child
Daniel Veillardccb09631998-10-27 06:21:04 +0000564 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000565xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000566xmlStringGetNodeList(xmlDocPtr doc, const xmlChar *value) {
Daniel Veillardccb09631998-10-27 06:21:04 +0000567 xmlNodePtr ret = NULL, last = NULL;
568 xmlNodePtr node;
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000569 xmlChar *val;
570 const xmlChar *cur = value;
571 const xmlChar *q;
Daniel Veillard25940b71998-10-29 05:51:30 +0000572 xmlEntityPtr ent;
Daniel Veillardccb09631998-10-27 06:21:04 +0000573
574 if (value == NULL) return(NULL);
575
576 q = cur;
577 while (*cur != 0) {
578 if (*cur == '&') {
Daniel Veillard25940b71998-10-29 05:51:30 +0000579 /*
580 * Save the current text.
581 */
Daniel Veillardccb09631998-10-27 06:21:04 +0000582 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000583 if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
584 xmlNodeAddContentLen(last, q, cur - q);
585 } else {
586 node = xmlNewDocTextLen(doc, q, cur - q);
587 if (node == NULL) return(ret);
588 if (last == NULL)
589 last = ret = node;
590 else {
591 last->next = node;
592 node->prev = last;
593 last = node;
594 }
Daniel Veillardccb09631998-10-27 06:21:04 +0000595 }
596 }
Daniel Veillard25940b71998-10-29 05:51:30 +0000597 /*
598 * Read the entity string
599 */
Daniel Veillardccb09631998-10-27 06:21:04 +0000600 cur++;
601 q = cur;
602 while ((*cur != 0) && (*cur != ';')) cur++;
603 if (*cur == 0) {
604 fprintf(stderr,
605 "xmlStringGetNodeList: unterminated entity %30s\n", q);
606 return(ret);
607 }
608 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000609 /*
610 * Predefined entities don't generate nodes
611 */
Daniel Veillardccb09631998-10-27 06:21:04 +0000612 val = xmlStrndup(q, cur - q);
Daniel Veillard25940b71998-10-29 05:51:30 +0000613 ent = xmlGetDocEntity(doc, val);
614 if ((ent != NULL) &&
615 (ent->type == XML_INTERNAL_PREDEFINED_ENTITY)) {
616 if (last == NULL) {
617 node = xmlNewDocText(doc, ent->content);
618 last = ret = node;
619 } else
620 xmlNodeAddContent(last, ent->content);
621
622 } else {
623 /*
624 * Create a new REFERENCE_REF node
625 */
Daniel Veillard25940b71998-10-29 05:51:30 +0000626 node = xmlNewReference(doc, val);
Daniel Veillard242590e1998-11-13 18:04:35 +0000627 if (node == NULL) {
Daniel Veillard6454aec1999-09-02 22:04:43 +0000628 if (val != NULL) xmlFree(val);
Daniel Veillard242590e1998-11-13 18:04:35 +0000629 return(ret);
630 }
Daniel Veillard25940b71998-10-29 05:51:30 +0000631 if (last == NULL)
632 last = ret = node;
633 else {
634 last->next = node;
635 node->prev = last;
636 last = node;
637 }
Daniel Veillardccb09631998-10-27 06:21:04 +0000638 }
Daniel Veillard6454aec1999-09-02 22:04:43 +0000639 xmlFree(val);
Daniel Veillardccb09631998-10-27 06:21:04 +0000640 }
641 cur++;
642 q = cur;
643 } else
644 cur++;
645 }
646 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000647 /*
648 * Handle the last piece of text.
649 */
650 if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
651 xmlNodeAddContentLen(last, q, cur - q);
652 } else {
653 node = xmlNewDocTextLen(doc, q, cur - q);
654 if (node == NULL) return(ret);
655 if (last == NULL)
656 last = ret = node;
657 else {
658 last->next = node;
659 node->prev = last;
660 last = node;
661 }
Daniel Veillardccb09631998-10-27 06:21:04 +0000662 }
663 }
664 return(ret);
665}
666
667/**
668 * xmlNodeListGetString:
669 * @doc: the document
670 * @list: a Node list
671 * @inLine: should we replace entity contents or show their external form
672 *
673 * Returns the string equivalent to the text contained in the Node list
674 * made of TEXTs and ENTITY_REFs
Daniel Veillard1e346af1999-02-22 10:33:01 +0000675 * Returns a pointer to the string copy, the calller must free it.
Daniel Veillardccb09631998-10-27 06:21:04 +0000676 */
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000677xmlChar *
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000678xmlNodeListGetString(xmlDocPtr doc, xmlNodePtr list, int inLine) {
Daniel Veillardccb09631998-10-27 06:21:04 +0000679 xmlNodePtr node = list;
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000680 xmlChar *ret = NULL;
Daniel Veillardccb09631998-10-27 06:21:04 +0000681 xmlEntityPtr ent;
682
683 if (list == NULL) return(NULL);
684
685 while (node != NULL) {
686 if (node->type == XML_TEXT_NODE) {
Daniel Veillard35008381999-10-25 13:15:52 +0000687 if ((inLine) || (doc->type == XML_HTML_DOCUMENT_NODE))
Daniel Veillardccb09631998-10-27 06:21:04 +0000688 ret = xmlStrcat(ret, node->content);
Daniel Veillard14fff061999-06-22 21:49:07 +0000689 else {
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000690 xmlChar *buffer;
Daniel Veillard14fff061999-06-22 21:49:07 +0000691
692 buffer = xmlEncodeEntitiesReentrant(doc, node->content);
693 if (buffer != NULL) {
694 ret = xmlStrcat(ret, buffer);
Daniel Veillard6454aec1999-09-02 22:04:43 +0000695 xmlFree(buffer);
Daniel Veillard14fff061999-06-22 21:49:07 +0000696 }
697 }
Daniel Veillardccb09631998-10-27 06:21:04 +0000698 } else if (node->type == XML_ENTITY_REF_NODE) {
699 if (inLine) {
700 ent = xmlGetDocEntity(doc, node->name);
701 if (ent != NULL)
702 ret = xmlStrcat(ret, ent->content);
703 else
704 ret = xmlStrcat(ret, node->content);
705 } else {
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000706 xmlChar buf[2];
Daniel Veillardccb09631998-10-27 06:21:04 +0000707 buf[0] = '&'; buf[1] = 0;
708 ret = xmlStrncat(ret, buf, 1);
709 ret = xmlStrcat(ret, node->name);
710 buf[0] = ';'; buf[1] = 0;
711 ret = xmlStrncat(ret, buf, 1);
712 }
713 }
714#if 0
715 else {
716 fprintf(stderr, "xmlGetNodeListString : invalide node type %d\n",
717 node->type);
718 }
719#endif
720 node = node->next;
721 }
722 return(ret);
723}
724
725/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000726 * xmlNewProp:
727 * @node: the holding node
728 * @name: the name of the attribute
729 * @value: the value of the attribute
730 *
731 * Create a new property carried by a node.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000732 * Returns a pointer to the attribute
Daniel Veillard260a68f1998-08-13 03:39:55 +0000733 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000734xmlAttrPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000735xmlNewProp(xmlNodePtr node, const xmlChar *name, const xmlChar *value) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000736 xmlAttrPtr cur;
737
738 if (name == NULL) {
739 fprintf(stderr, "xmlNewProp : name == NULL\n");
740 return(NULL);
741 }
742
743 /*
744 * Allocate a new property and fill the fields.
745 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000746 cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000747 if (cur == NULL) {
748 fprintf(stderr, "xmlNewProp : malloc failed\n");
749 return(NULL);
750 }
751
Daniel Veillard33942841998-10-18 19:12:41 +0000752 cur->type = XML_ATTRIBUTE_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000753 cur->node = node;
Daniel Veillardb96e6431999-08-29 21:02:19 +0000754 cur->ns = NULL;
755 cur->name = xmlStrdup(name);
Daniel Veillard51e3b151999-11-12 17:02:31 +0000756 if (value != NULL) {
757 xmlChar *buffer;
758 buffer = xmlEncodeEntitiesReentrant(node->doc, value);
759 cur->val = xmlStringGetNodeList(node->doc, buffer);
760 xmlFree(buffer);
761 }
Daniel Veillardb96e6431999-08-29 21:02:19 +0000762 else
763 cur->val = NULL;
764#ifndef XML_WITHOUT_CORBA
765 cur->_private = NULL;
766 cur->vepv = NULL;
767#endif
768
769 /*
770 * Add it at the end to preserve parsing order ...
771 */
772 cur->next = NULL;
773 if (node != NULL) {
774 if (node->properties == NULL) {
775 node->properties = cur;
776 } else {
777 xmlAttrPtr prev = node->properties;
778
779 while (prev->next != NULL) prev = prev->next;
780 prev->next = cur;
781 }
782 }
Daniel Veillard00fdf371999-10-08 09:40:39 +0000783#ifndef XML_WITHOUT_CORBA
784 cur->_private = NULL;
785 cur->vepv = NULL;
786#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +0000787 return(cur);
788}
789
790/**
791 * xmlNewNsProp:
792 * @node: the holding node
793 * @ns: the namespace
794 * @name: the name of the attribute
795 * @value: the value of the attribute
796 *
797 * Create a new property tagged with a namespace and carried by a node.
798 * Returns a pointer to the attribute
799 */
800xmlAttrPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000801xmlNewNsProp(xmlNodePtr node, xmlNsPtr ns, const xmlChar *name,
802 const xmlChar *value) {
Daniel Veillardb96e6431999-08-29 21:02:19 +0000803 xmlAttrPtr cur;
804
805 if (name == NULL) {
806 fprintf(stderr, "xmlNewProp : name == NULL\n");
807 return(NULL);
808 }
809
810 /*
811 * Allocate a new property and fill the fields.
812 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000813 cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr));
Daniel Veillardb96e6431999-08-29 21:02:19 +0000814 if (cur == NULL) {
815 fprintf(stderr, "xmlNewProp : malloc failed\n");
816 return(NULL);
817 }
818
819 cur->type = XML_ATTRIBUTE_NODE;
820 cur->node = node;
821 cur->ns = ns;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000822 cur->name = xmlStrdup(name);
823 if (value != NULL)
Daniel Veillardccb09631998-10-27 06:21:04 +0000824 cur->val = xmlStringGetNodeList(node->doc, value);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000825 else
Daniel Veillardccb09631998-10-27 06:21:04 +0000826 cur->val = NULL;
Daniel Veillard27d88741999-05-29 11:51:49 +0000827#ifndef XML_WITHOUT_CORBA
Daniel Veillard27fb0751998-10-17 06:47:46 +0000828 cur->_private = NULL;
829 cur->vepv = NULL;
830#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000831
832 /*
833 * Add it at the end to preserve parsing order ...
834 */
835 cur->next = NULL;
836 if (node != NULL) {
837 if (node->properties == NULL) {
838 node->properties = cur;
839 } else {
840 xmlAttrPtr prev = node->properties;
841
842 while (prev->next != NULL) prev = prev->next;
843 prev->next = cur;
844 }
845 }
846 return(cur);
847}
848
Daniel Veillard97b58771998-10-20 06:14:16 +0000849/**
Daniel Veillardccb09631998-10-27 06:21:04 +0000850 * xmlNewDocProp:
851 * @doc: the document
852 * @name: the name of the attribute
853 * @value: the value of the attribute
854 *
855 * Create a new property carried by a document.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000856 * Returns a pointer to the attribute
Daniel Veillardccb09631998-10-27 06:21:04 +0000857 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000858xmlAttrPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000859xmlNewDocProp(xmlDocPtr doc, const xmlChar *name, const xmlChar *value) {
Daniel Veillardccb09631998-10-27 06:21:04 +0000860 xmlAttrPtr cur;
861
862 if (name == NULL) {
863 fprintf(stderr, "xmlNewProp : name == NULL\n");
864 return(NULL);
865 }
866
867 /*
868 * Allocate a new property and fill the fields.
869 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000870 cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr));
Daniel Veillardccb09631998-10-27 06:21:04 +0000871 if (cur == NULL) {
872 fprintf(stderr, "xmlNewProp : malloc failed\n");
873 return(NULL);
874 }
875
876 cur->type = XML_ATTRIBUTE_NODE;
877 cur->node = NULL;
878 cur->name = xmlStrdup(name);
879 if (value != NULL)
880 cur->val = xmlStringGetNodeList(doc, value);
881 else
882 cur->val = NULL;
Daniel Veillard27d88741999-05-29 11:51:49 +0000883#ifndef XML_WITHOUT_CORBA
Daniel Veillardccb09631998-10-27 06:21:04 +0000884 cur->_private = NULL;
885 cur->vepv = NULL;
886#endif
887
888 cur->next = NULL;
889 return(cur);
890}
891
892/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000893 * xmlFreePropList:
894 * @cur: the first property in the list
895 *
896 * Free a property and all its siblings, all the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000897 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000898void
899xmlFreePropList(xmlAttrPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000900 xmlAttrPtr next;
901 if (cur == NULL) {
902 fprintf(stderr, "xmlFreePropList : property == NULL\n");
903 return;
904 }
905 while (cur != NULL) {
906 next = cur->next;
907 xmlFreeProp(cur);
908 cur = next;
909 }
910}
911
Daniel Veillard97b58771998-10-20 06:14:16 +0000912/**
913 * xmlFreeProp:
914 * @cur: the first property in the list
915 *
916 * Free one property, all the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000917 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000918void
919xmlFreeProp(xmlAttrPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000920 if (cur == NULL) {
921 fprintf(stderr, "xmlFreeProp : property == NULL\n");
922 return;
923 }
Daniel Veillard6454aec1999-09-02 22:04:43 +0000924 if (cur->name != NULL) xmlFree((char *) cur->name);
Daniel Veillardccb09631998-10-27 06:21:04 +0000925 if (cur->val != NULL) xmlFreeNodeList(cur->val);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000926 memset(cur, -1, sizeof(xmlAttr));
Daniel Veillard6454aec1999-09-02 22:04:43 +0000927 xmlFree(cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000928}
929
Daniel Veillard97b58771998-10-20 06:14:16 +0000930/**
Daniel Veillardb96e6431999-08-29 21:02:19 +0000931 * xmlNewPI:
932 * @name: the processing instruction name
933 * @content: the PI content
934 *
935 * Creation of a processing instruction element.
936 * Returns a pointer to the new node object.
937 */
938xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000939xmlNewPI(const xmlChar *name, const xmlChar *content) {
Daniel Veillardb96e6431999-08-29 21:02:19 +0000940 xmlNodePtr cur;
941
942 if (name == NULL) {
943 fprintf(stderr, "xmlNewPI : name == NULL\n");
944 return(NULL);
945 }
946
947 /*
948 * Allocate a new node and fill the fields.
949 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000950 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillardb96e6431999-08-29 21:02:19 +0000951 if (cur == NULL) {
952 fprintf(stderr, "xmlNewPI : malloc failed\n");
953 return(NULL);
954 }
955
956 cur->type = XML_PI_NODE;
957 cur->doc = NULL;
958 cur->parent = NULL;
959 cur->next = NULL;
960 cur->prev = NULL;
961 cur->childs = NULL;
962 cur->last = NULL;
963 cur->properties = NULL;
964 cur->name = xmlStrdup(name);
965 cur->ns = NULL;
966 cur->nsDef = NULL;
967 if (content != NULL)
968 cur->content = xmlStrdup(content);
969 else
970 cur->content = NULL;
971#ifndef XML_WITHOUT_CORBA
972 cur->_private = NULL;
973 cur->vepv = NULL;
974#endif
975 return(cur);
976}
977
978/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000979 * xmlNewNode:
980 * @ns: namespace if any
981 * @name: the node name
Daniel Veillard97b58771998-10-20 06:14:16 +0000982 *
983 * Creation of a new node element. @ns and @content are optionnal (NULL).
Daniel Veillardccb09631998-10-27 06:21:04 +0000984 * If content is non NULL, a child list containing the TEXTs and
985 * ENTITY_REFs node will be created.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000986 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000987 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000988xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000989xmlNewNode(xmlNsPtr ns, const xmlChar *name) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000990 xmlNodePtr cur;
991
992 if (name == NULL) {
993 fprintf(stderr, "xmlNewNode : name == NULL\n");
994 return(NULL);
995 }
996
997 /*
998 * Allocate a new node and fill the fields.
999 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001000 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillard260a68f1998-08-13 03:39:55 +00001001 if (cur == NULL) {
1002 fprintf(stderr, "xmlNewNode : malloc failed\n");
1003 return(NULL);
1004 }
1005
Daniel Veillard33942841998-10-18 19:12:41 +00001006 cur->type = XML_ELEMENT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001007 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001008 cur->parent = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001009 cur->next = NULL;
1010 cur->prev = NULL;
1011 cur->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001012 cur->last = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001013 cur->properties = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001014 cur->name = xmlStrdup(name);
1015 cur->ns = ns;
1016 cur->nsDef = NULL;
Daniel Veillardccb09631998-10-27 06:21:04 +00001017 cur->content = NULL;
Daniel Veillard27d88741999-05-29 11:51:49 +00001018#ifndef XML_WITHOUT_CORBA
Daniel Veillard27fb0751998-10-17 06:47:46 +00001019 cur->_private = NULL;
1020 cur->vepv = NULL;
1021#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001022 return(cur);
1023}
1024
Daniel Veillard97b58771998-10-20 06:14:16 +00001025/**
1026 * xmlNewDocNode:
1027 * @doc: the document
1028 * @ns: namespace if any
1029 * @name: the node name
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001030 * @content: the XML text content if any
Daniel Veillard97b58771998-10-20 06:14:16 +00001031 *
1032 * Creation of a new node element within a document. @ns and @content
1033 * are optionnal (NULL).
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001034 * NOTE: @content is supposed to be a piece of XML CDATA, so it allow entities
1035 * references, but XML special chars need to be escaped first by using
1036 * xmlEncodeEntitiesReentrant(). Use xmlNewDocRawNode() if you don't
1037 * need entities support.
1038 *
Daniel Veillard1e346af1999-02-22 10:33:01 +00001039 * Returns a pointer to the new node object.
Daniel Veillard97b58771998-10-20 06:14:16 +00001040 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001041xmlNodePtr
1042xmlNewDocNode(xmlDocPtr doc, xmlNsPtr ns,
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001043 const xmlChar *name, const xmlChar *content) {
Daniel Veillard0bef1311998-10-14 02:36:47 +00001044 xmlNodePtr cur;
1045
Daniel Veillardccb09631998-10-27 06:21:04 +00001046 cur = xmlNewNode(ns, name);
1047 if (cur != NULL) {
1048 cur->doc = doc;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001049 if (content != NULL) {
Daniel Veillardccb09631998-10-27 06:21:04 +00001050 cur->childs = xmlStringGetNodeList(doc, content);
Daniel Veillard1e346af1999-02-22 10:33:01 +00001051 UPDATE_LAST_CHILD(cur)
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001052 }
Daniel Veillardccb09631998-10-27 06:21:04 +00001053 }
Daniel Veillard0bef1311998-10-14 02:36:47 +00001054 return(cur);
1055}
1056
1057
Daniel Veillard97b58771998-10-20 06:14:16 +00001058/**
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001059 * xmlNewDocRawNode:
1060 * @doc: the document
1061 * @ns: namespace if any
1062 * @name: the node name
1063 * @content: the text content if any
1064 *
1065 * Creation of a new node element within a document. @ns and @content
1066 * are optionnal (NULL).
1067 *
1068 * Returns a pointer to the new node object.
1069 */
1070xmlNodePtr
1071xmlNewDocRawNode(xmlDocPtr doc, xmlNsPtr ns,
1072 const xmlChar *name, const xmlChar *content) {
1073 xmlNodePtr cur;
1074
1075 cur = xmlNewNode(ns, name);
1076 if (cur != NULL) {
1077 cur->doc = doc;
1078 if (content != NULL) {
1079 cur->childs = xmlNewDocText(doc, content);
1080 UPDATE_LAST_CHILD(cur)
1081 }
1082 }
1083 return(cur);
1084}
1085
1086
1087/**
Daniel Veillard97b58771998-10-20 06:14:16 +00001088 * xmlNewText:
1089 * @content: the text content
1090 *
1091 * Creation of a new text node.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001092 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001093 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001094xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001095xmlNewText(const xmlChar *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001096 xmlNodePtr cur;
1097
1098 /*
1099 * Allocate a new node and fill the fields.
1100 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001101 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillard260a68f1998-08-13 03:39:55 +00001102 if (cur == NULL) {
1103 fprintf(stderr, "xmlNewText : malloc failed\n");
1104 return(NULL);
1105 }
1106
Daniel Veillard33942841998-10-18 19:12:41 +00001107 cur->type = XML_TEXT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001108 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001109 cur->parent = NULL;
1110 cur->next = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001111 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001112 cur->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001113 cur->last = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001114 cur->properties = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001115 cur->type = XML_TEXT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001116 cur->name = xmlStrdup(xmlStringText);
1117 cur->ns = NULL;
1118 cur->nsDef = NULL;
1119 if (content != NULL)
1120 cur->content = xmlStrdup(content);
1121 else
1122 cur->content = NULL;
Daniel Veillard00fdf371999-10-08 09:40:39 +00001123#ifndef XML_WITHOUT_CORBA
1124 cur->_private = NULL;
1125 cur->vepv = NULL;
1126#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001127 return(cur);
1128}
1129
Daniel Veillard97b58771998-10-20 06:14:16 +00001130/**
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001131 * xmlNewTextChild:
1132 * @parent: the parent node
1133 * @ns: a namespace if any
1134 * @name: the name of the child
1135 * @content: the text content of the child if any.
1136 *
1137 * Creation of a new child element, added at the end of @parent childs list.
1138 * @ns and @content parameters are optionnal (NULL). If content is non NULL,
1139 * a child TEXT node will be created containing the string content.
1140 *
1141 * Returns a pointer to the new node object.
1142 */
1143xmlNodePtr
1144xmlNewTextChild(xmlNodePtr parent, xmlNsPtr ns,
1145 const xmlChar *name, const xmlChar *content) {
1146 xmlNodePtr cur, prev;
1147
1148 if (parent == NULL) {
1149 fprintf(stderr, "xmlNewTextChild : parent == NULL\n");
1150 return(NULL);
1151 }
1152
1153 if (name == NULL) {
1154 fprintf(stderr, "xmlNewTextChild : name == NULL\n");
1155 return(NULL);
1156 }
1157
1158 /*
1159 * Allocate a new node
1160 */
1161 if (ns == NULL)
1162 cur = xmlNewDocRawNode(parent->doc, parent->ns, name, content);
1163 else
1164 cur = xmlNewDocRawNode(parent->doc, ns, name, content);
1165 if (cur == NULL) return(NULL);
1166
1167 /*
1168 * add the new element at the end of the childs list.
1169 */
1170 cur->type = XML_ELEMENT_NODE;
1171 cur->parent = parent;
1172 cur->doc = parent->doc;
1173 if (parent->childs == NULL) {
1174 parent->childs = cur;
1175 parent->last = cur;
1176 } else {
1177 prev = parent->last;
1178 prev->next = cur;
1179 cur->prev = prev;
1180 parent->last = cur;
1181 }
1182
1183 return(cur);
1184}
1185
1186/**
Daniel Veillardccb09631998-10-27 06:21:04 +00001187 * xmlNewReference:
1188 * @doc: the document
1189 * @name: the reference name, or the reference string with & and ;
1190 *
1191 * Creation of a new reference node.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001192 * Returns a pointer to the new node object.
Daniel Veillardccb09631998-10-27 06:21:04 +00001193 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001194xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001195xmlNewReference(xmlDocPtr doc, const xmlChar *name) {
Daniel Veillardccb09631998-10-27 06:21:04 +00001196 xmlNodePtr cur;
1197 xmlEntityPtr ent;
1198
1199 /*
1200 * Allocate a new node and fill the fields.
1201 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001202 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillardccb09631998-10-27 06:21:04 +00001203 if (cur == NULL) {
1204 fprintf(stderr, "xmlNewText : malloc failed\n");
1205 return(NULL);
1206 }
1207
1208 cur->type = XML_ENTITY_REF_NODE;
Daniel Veillard10c6a8f1998-10-28 01:00:12 +00001209 cur->doc = doc;
Daniel Veillardccb09631998-10-27 06:21:04 +00001210 cur->parent = NULL;
1211 cur->next = NULL;
1212 cur->prev = NULL;
1213 cur->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001214 cur->last = NULL;
Daniel Veillardccb09631998-10-27 06:21:04 +00001215 cur->properties = NULL;
1216 if (name[0] == '&') {
1217 int len;
1218 name++;
1219 len = xmlStrlen(name);
1220 if (name[len - 1] == ';')
1221 cur->name = xmlStrndup(name, len - 1);
1222 else
1223 cur->name = xmlStrndup(name, len);
1224 } else
1225 cur->name = xmlStrdup(name);
1226 cur->ns = NULL;
1227 cur->nsDef = NULL;
1228
1229 ent = xmlGetDocEntity(doc, cur->name);
1230 if (ent != NULL)
1231 cur->content = ent->content;
1232 else
1233 cur->content = NULL;
Daniel Veillard00fdf371999-10-08 09:40:39 +00001234#ifndef XML_WITHOUT_CORBA
1235 cur->_private = NULL;
1236 cur->vepv = NULL;
1237#endif
Daniel Veillardccb09631998-10-27 06:21:04 +00001238 return(cur);
1239}
1240
1241/**
Daniel Veillard97b58771998-10-20 06:14:16 +00001242 * xmlNewDocText:
1243 * @doc: the document
1244 * @content: the text content
1245 *
1246 * Creation of a new text node within a document.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001247 * Returns a pointer to the new node object.
Daniel Veillard97b58771998-10-20 06:14:16 +00001248 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001249xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001250xmlNewDocText(xmlDocPtr doc, const xmlChar *content) {
Daniel Veillard0bef1311998-10-14 02:36:47 +00001251 xmlNodePtr cur;
1252
1253 cur = xmlNewText(content);
1254 if (cur != NULL) cur->doc = doc;
1255 return(cur);
1256}
1257
Daniel Veillard97b58771998-10-20 06:14:16 +00001258/**
Daniel Veillardccb09631998-10-27 06:21:04 +00001259 * xmlNewTextLen:
Daniel Veillard97b58771998-10-20 06:14:16 +00001260 * @content: the text content
1261 * @len: the text len.
1262 *
1263 * Creation of a new text node with an extra parameter for the content's lenght
Daniel Veillard1e346af1999-02-22 10:33:01 +00001264 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001265 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001266xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001267xmlNewTextLen(const xmlChar *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001268 xmlNodePtr cur;
1269
1270 /*
1271 * Allocate a new node and fill the fields.
1272 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001273 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillard260a68f1998-08-13 03:39:55 +00001274 if (cur == NULL) {
1275 fprintf(stderr, "xmlNewText : malloc failed\n");
1276 return(NULL);
1277 }
1278
Daniel Veillard33942841998-10-18 19:12:41 +00001279 cur->type = XML_TEXT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001280 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001281 cur->parent = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001282 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001283 cur->next = NULL;
1284 cur->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001285 cur->last = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001286 cur->properties = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001287 cur->type = XML_TEXT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001288 cur->name = xmlStrdup(xmlStringText);
1289 cur->ns = NULL;
1290 cur->nsDef = NULL;
1291 if (content != NULL)
1292 cur->content = xmlStrndup(content, len);
1293 else
1294 cur->content = NULL;
Daniel Veillard00fdf371999-10-08 09:40:39 +00001295#ifndef XML_WITHOUT_CORBA
1296 cur->_private = NULL;
1297 cur->vepv = NULL;
1298#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001299 return(cur);
1300}
1301
Daniel Veillard97b58771998-10-20 06:14:16 +00001302/**
1303 * xmlNewDocTextLen:
1304 * @doc: the document
1305 * @content: the text content
1306 * @len: the text len.
1307 *
1308 * Creation of a new text node with an extra content lenght parameter. The
1309 * text node pertain to a given document.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001310 * Returns a pointer to the new node object.
Daniel Veillard97b58771998-10-20 06:14:16 +00001311 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001312xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001313xmlNewDocTextLen(xmlDocPtr doc, const xmlChar *content, int len) {
Daniel Veillard0bef1311998-10-14 02:36:47 +00001314 xmlNodePtr cur;
1315
1316 cur = xmlNewTextLen(content, len);
1317 if (cur != NULL) cur->doc = doc;
1318 return(cur);
1319}
1320
Daniel Veillard97b58771998-10-20 06:14:16 +00001321/**
1322 * xmlNewComment:
1323 * @content: the comment content
1324 *
1325 * Creation of a new node containing a comment.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001326 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001327 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001328xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001329xmlNewComment(const xmlChar *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001330 xmlNodePtr cur;
1331
1332 /*
1333 * Allocate a new node and fill the fields.
1334 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001335 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillard260a68f1998-08-13 03:39:55 +00001336 if (cur == NULL) {
1337 fprintf(stderr, "xmlNewComment : malloc failed\n");
1338 return(NULL);
1339 }
1340
Daniel Veillard33942841998-10-18 19:12:41 +00001341 cur->type = XML_COMMENT_NODE;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001342 cur->doc = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001343 cur->parent = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001344 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001345 cur->next = NULL;
1346 cur->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001347 cur->last = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001348 cur->properties = NULL;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001349 cur->type = XML_COMMENT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001350 cur->name = xmlStrdup(xmlStringText);
1351 cur->ns = NULL;
1352 cur->nsDef = NULL;
1353 if (content != NULL)
1354 cur->content = xmlStrdup(content);
1355 else
1356 cur->content = NULL;
Daniel Veillard00fdf371999-10-08 09:40:39 +00001357#ifndef XML_WITHOUT_CORBA
1358 cur->_private = NULL;
1359 cur->vepv = NULL;
1360#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001361 return(cur);
1362}
1363
Daniel Veillard97b58771998-10-20 06:14:16 +00001364/**
Daniel Veillardb05deb71999-08-10 19:04:08 +00001365 * xmlNewCDataBlock:
1366 * @doc: the document
1367 * @content: the CData block content content
1368 * @len: the length of the block
1369 *
1370 * Creation of a new node containing a CData block.
1371 * Returns a pointer to the new node object.
1372 */
1373xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001374xmlNewCDataBlock(xmlDocPtr doc, const xmlChar *content, int len) {
Daniel Veillardb05deb71999-08-10 19:04:08 +00001375 xmlNodePtr cur;
1376
1377 /*
1378 * Allocate a new node and fill the fields.
1379 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001380 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillardb05deb71999-08-10 19:04:08 +00001381 if (cur == NULL) {
1382 fprintf(stderr, "xmlNewCDataBlock : malloc failed\n");
1383 return(NULL);
1384 }
1385
1386 cur->type = XML_CDATA_SECTION_NODE;
1387 cur->doc = NULL;
1388 cur->parent = NULL;
1389 cur->prev = NULL;
1390 cur->next = NULL;
1391 cur->childs = NULL;
1392 cur->last = NULL;
1393 cur->properties = NULL;
1394 cur->name = xmlStrdup(xmlStringText);
1395 cur->ns = NULL;
1396 cur->nsDef = NULL;
1397 if ((content != NULL) && (len > 0)) {
1398 cur->content = xmlStrndup(content, len);
1399 } else
1400 cur->content = NULL;
Daniel Veillard00fdf371999-10-08 09:40:39 +00001401#ifndef XML_WITHOUT_CORBA
1402 cur->_private = NULL;
1403 cur->vepv = NULL;
1404#endif
Daniel Veillardb05deb71999-08-10 19:04:08 +00001405 return(cur);
1406}
1407
1408/**
Daniel Veillard1e346af1999-02-22 10:33:01 +00001409 * xmlNewDocComment:
Daniel Veillard97b58771998-10-20 06:14:16 +00001410 * @doc: the document
1411 * @content: the comment content
1412 *
1413 * Creation of a new node containing a commentwithin a document.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001414 * Returns a pointer to the new node object.
Daniel Veillard97b58771998-10-20 06:14:16 +00001415 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001416xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001417xmlNewDocComment(xmlDocPtr doc, const xmlChar *content) {
Daniel Veillard0bef1311998-10-14 02:36:47 +00001418 xmlNodePtr cur;
1419
1420 cur = xmlNewComment(content);
1421 if (cur != NULL) cur->doc = doc;
1422 return(cur);
1423}
1424
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001425
Daniel Veillard97b58771998-10-20 06:14:16 +00001426/**
1427 * xmlNewChild:
1428 * @parent: the parent node
1429 * @ns: a namespace if any
1430 * @name: the name of the child
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001431 * @content: the XML content of the child if any.
Daniel Veillard97b58771998-10-20 06:14:16 +00001432 *
Daniel Veillard97b58771998-10-20 06:14:16 +00001433 * Creation of a new child element, added at the end of @parent childs list.
Daniel Veillardccb09631998-10-27 06:21:04 +00001434 * @ns and @content parameters are optionnal (NULL). If content is non NULL,
1435 * a child list containing the TEXTs and ENTITY_REFs node will be created.
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001436 * NOTE: @content is supposed to be a piece of XML CDATA, so it allow entities
1437 * references, but XML special chars need to be escaped first by using
1438 * xmlEncodeEntitiesReentrant(). Use xmlNewTextChild() if entities
1439 * support is not needed.
1440 *
Daniel Veillard1e346af1999-02-22 10:33:01 +00001441 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001442 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001443xmlNodePtr
1444xmlNewChild(xmlNodePtr parent, xmlNsPtr ns,
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001445 const xmlChar *name, const xmlChar *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001446 xmlNodePtr cur, prev;
1447
1448 if (parent == NULL) {
1449 fprintf(stderr, "xmlNewChild : parent == NULL\n");
1450 return(NULL);
1451 }
1452
1453 if (name == NULL) {
1454 fprintf(stderr, "xmlNewChild : name == NULL\n");
1455 return(NULL);
1456 }
1457
1458 /*
1459 * Allocate a new node
1460 */
1461 if (ns == NULL)
Daniel Veillardccb09631998-10-27 06:21:04 +00001462 cur = xmlNewDocNode(parent->doc, parent->ns, name, content);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001463 else
Daniel Veillardccb09631998-10-27 06:21:04 +00001464 cur = xmlNewDocNode(parent->doc, ns, name, content);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001465 if (cur == NULL) return(NULL);
1466
1467 /*
1468 * add the new element at the end of the childs list.
1469 */
Daniel Veillardccb09631998-10-27 06:21:04 +00001470 cur->type = XML_ELEMENT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001471 cur->parent = parent;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001472 cur->doc = parent->doc;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001473 if (parent->childs == NULL) {
1474 parent->childs = cur;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001475 parent->last = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001476 } else {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001477 prev = parent->last;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001478 prev->next = cur;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001479 cur->prev = prev;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001480 parent->last = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001481 }
1482
1483 return(cur);
1484}
1485
Daniel Veillard97b58771998-10-20 06:14:16 +00001486/**
Daniel Veillardb96e6431999-08-29 21:02:19 +00001487 * xmlAddSibling:
1488 * @cur: the child node
1489 * @elem: the new node
1490 *
1491 * Add a new element to the list of siblings of @cur
1492 * Returns the element or NULL in case of error.
1493 */
1494xmlNodePtr
1495xmlAddSibling(xmlNodePtr cur, xmlNodePtr elem) {
1496 xmlNodePtr parent;
1497
1498 if (cur == NULL) {
1499 fprintf(stderr, "xmlAddSibling : cur == NULL\n");
1500 return(NULL);
1501 }
1502
1503 if (elem == NULL) {
1504 fprintf(stderr, "xmlAddSibling : elem == NULL\n");
1505 return(NULL);
1506 }
1507
1508 if ((cur->doc != NULL) && (elem->doc != NULL) &&
1509 (cur->doc != elem->doc)) {
1510 fprintf(stderr,
1511 "xmlAddSibling: Elements moved to a different document\n");
1512 }
1513
1514 while (cur->next != NULL) cur = cur->next;
1515
1516 if (elem->doc == NULL)
1517 elem->doc = cur->doc; /* the parent may not be linked to a doc ! */
1518
1519 parent = cur->parent;
1520 elem->prev = cur;
1521 elem->next = NULL;
1522 elem->parent = parent;
1523 cur->next = elem;
1524 if (parent != NULL)
1525 parent->last = elem;
1526
1527 return(elem);
1528}
1529
1530/**
Daniel Veillard97b58771998-10-20 06:14:16 +00001531 * xmlAddChild:
1532 * @parent: the parent node
1533 * @cur: the child node
1534 *
1535 * Add a new child element, to @parent, at the end of the child list.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001536 * Returns the child or NULL in case of error.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001537 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001538xmlNodePtr
1539xmlAddChild(xmlNodePtr parent, xmlNodePtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001540 xmlNodePtr prev;
1541
1542 if (parent == NULL) {
1543 fprintf(stderr, "xmladdChild : parent == NULL\n");
1544 return(NULL);
1545 }
1546
1547 if (cur == NULL) {
1548 fprintf(stderr, "xmladdChild : child == NULL\n");
1549 return(NULL);
1550 }
1551
Daniel Veillard0bef1311998-10-14 02:36:47 +00001552 if ((cur->doc != NULL) && (parent->doc != NULL) &&
1553 (cur->doc != parent->doc)) {
1554 fprintf(stderr, "Elements moved to a different document\n");
1555 }
1556
Daniel Veillard260a68f1998-08-13 03:39:55 +00001557 /*
1558 * add the new element at the end of the childs list.
1559 */
1560 cur->parent = parent;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001561 cur->doc = parent->doc; /* the parent may not be linked to a doc ! */
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001562
Daniel Veillardccb09631998-10-27 06:21:04 +00001563 /*
1564 * Handle the case where parent->content != NULL, in that case it will
1565 * create a intermediate TEXT node.
1566 */
1567 if (parent->content != NULL) {
1568 xmlNodePtr text;
1569
1570 text = xmlNewDocText(parent->doc, parent->content);
1571 if (text != NULL) {
1572 text->next = parent->childs;
1573 if (text->next != NULL)
1574 text->next->prev = text;
1575 parent->childs = text;
Daniel Veillard1e346af1999-02-22 10:33:01 +00001576 UPDATE_LAST_CHILD(parent)
Daniel Veillard6454aec1999-09-02 22:04:43 +00001577 xmlFree(parent->content);
Daniel Veillardccb09631998-10-27 06:21:04 +00001578 parent->content = NULL;
1579 }
1580 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00001581 if (parent->childs == NULL) {
1582 parent->childs = cur;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001583 parent->last = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001584 } else {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001585 prev = parent->last;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001586 prev->next = cur;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001587 cur->prev = prev;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001588 parent->last = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001589 }
1590
1591 return(cur);
1592}
1593
Daniel Veillard97b58771998-10-20 06:14:16 +00001594/**
1595 * xmlGetLastChild:
1596 * @parent: the parent node
1597 *
1598 * Search the last child of a node.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001599 * Returns the last child or NULL if none.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001600 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001601xmlNodePtr
1602xmlGetLastChild(xmlNodePtr parent) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001603 if (parent == NULL) {
1604 fprintf(stderr, "xmlGetLastChild : parent == NULL\n");
1605 return(NULL);
1606 }
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001607 return(parent->last);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001608}
1609
Daniel Veillard97b58771998-10-20 06:14:16 +00001610/**
1611 * xmlFreeNodeList:
1612 * @cur: the first node in the list
1613 *
1614 * Free a node and all its siblings, this is a recursive behaviour, all
1615 * the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001616 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001617void
1618xmlFreeNodeList(xmlNodePtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001619 xmlNodePtr next;
1620 if (cur == NULL) {
1621 fprintf(stderr, "xmlFreeNodeList : node == NULL\n");
1622 return;
1623 }
1624 while (cur != NULL) {
1625 next = cur->next;
1626 xmlFreeNode(cur);
1627 cur = next;
1628 }
1629}
1630
Daniel Veillard97b58771998-10-20 06:14:16 +00001631/**
1632 * xmlFreeNode:
1633 * @cur: the node
1634 *
1635 * Free a node, this is a recursive behaviour, all the childs are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001636 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001637void
1638xmlFreeNode(xmlNodePtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001639 if (cur == NULL) {
1640 fprintf(stderr, "xmlFreeNode : node == NULL\n");
1641 return;
1642 }
Daniel Veillardccb09631998-10-27 06:21:04 +00001643 cur->doc = NULL;
1644 cur->parent = NULL;
1645 cur->next = NULL;
1646 cur->prev = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001647 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillardccb09631998-10-27 06:21:04 +00001648 if (cur->properties != NULL) xmlFreePropList(cur->properties);
1649 if (cur->type != XML_ENTITY_REF_NODE)
Daniel Veillard6454aec1999-09-02 22:04:43 +00001650 if (cur->content != NULL) xmlFree(cur->content);
1651 if (cur->name != NULL) xmlFree((char *) cur->name);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001652 if (cur->nsDef != NULL) xmlFreeNsList(cur->nsDef);
1653 memset(cur, -1, sizeof(xmlNode));
Daniel Veillard6454aec1999-09-02 22:04:43 +00001654 xmlFree(cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001655}
1656
Daniel Veillard16253641998-10-28 22:58:05 +00001657/**
1658 * xmlUnlinkNode:
1659 * @cur: the node
1660 *
1661 * Unlink a node from it's current context, the node is not freed
1662 */
1663void
1664xmlUnlinkNode(xmlNodePtr cur) {
1665 if (cur == NULL) {
1666 fprintf(stderr, "xmlUnlinkNode : node == NULL\n");
1667 return;
1668 }
1669 if ((cur->parent != NULL) && (cur->parent->childs == cur))
1670 cur->parent->childs = cur->next;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001671 if ((cur->parent != NULL) && (cur->parent->last == cur))
1672 cur->parent->last = cur->prev;
Daniel Veillard16253641998-10-28 22:58:05 +00001673 if (cur->next != NULL)
1674 cur->next->prev = cur->prev;
1675 if (cur->prev != NULL)
1676 cur->prev->next = cur->next;
1677 cur->next = cur->prev = NULL;
1678 cur->parent = NULL;
1679}
1680
Daniel Veillard260a68f1998-08-13 03:39:55 +00001681/************************************************************************
1682 * *
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001683 * Copy operations *
1684 * *
1685 ************************************************************************/
1686
1687/**
1688 * xmlCopyNamespace:
1689 * @cur: the namespace
1690 *
1691 * Do a copy of the namespace.
1692 *
1693 * Returns: a new xmlNsPtr, or NULL in case of error.
1694 */
1695xmlNsPtr
1696xmlCopyNamespace(xmlNsPtr cur) {
1697 xmlNsPtr ret;
1698
1699 if (cur == NULL) return(NULL);
1700 switch (cur->type) {
1701 case XML_GLOBAL_NAMESPACE:
1702 ret = xmlNewGlobalNs(NULL, cur->href, cur->prefix);
1703 break;
1704 case XML_LOCAL_NAMESPACE:
1705 ret = xmlNewNs(NULL, cur->href, cur->prefix);
1706 break;
1707 default:
1708 fprintf(stderr, "xmlCopyNamespace: unknown type %d\n", cur->type);
1709 return(NULL);
1710 }
1711 return(ret);
1712}
1713
1714/**
1715 * xmlCopyNamespaceList:
1716 * @cur: the first namespace
1717 *
1718 * Do a copy of an namespace list.
1719 *
1720 * Returns: a new xmlNsPtr, or NULL in case of error.
1721 */
1722xmlNsPtr
1723xmlCopyNamespaceList(xmlNsPtr cur) {
1724 xmlNsPtr ret = NULL;
1725 xmlNsPtr p = NULL,q;
1726
1727 while (cur != NULL) {
1728 q = xmlCopyNamespace(cur);
1729 if (p == NULL) {
1730 ret = p = q;
1731 } else {
1732 p->next = q;
1733 p = q;
1734 }
1735 cur = cur->next;
1736 }
1737 return(ret);
1738}
1739
1740/**
1741 * xmlCopyProp:
Daniel Veillardb96e6431999-08-29 21:02:19 +00001742 * @target: the element where the attribute will be grafted
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001743 * @cur: the attribute
1744 *
1745 * Do a copy of the attribute.
1746 *
1747 * Returns: a new xmlAttrPtr, or NULL in case of error.
1748 */
1749xmlAttrPtr
Daniel Veillardb96e6431999-08-29 21:02:19 +00001750xmlCopyProp(xmlNodePtr target, xmlAttrPtr cur) {
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001751 xmlAttrPtr ret;
1752
1753 if (cur == NULL) return(NULL);
1754 if (cur->val != NULL)
1755 ret = xmlNewDocProp(cur->val->doc, cur->name, NULL);
1756 else
1757 ret = xmlNewDocProp(NULL, cur->name, NULL);
1758 if (ret == NULL) return(NULL);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001759
1760 if ((cur->ns != NULL) && (target != NULL)) {
1761 xmlNsPtr ns;
1762
1763 ns = xmlSearchNs(target->doc, target, cur->ns->prefix);
1764 ret->ns = ns;
1765 } else
1766 ret->ns = NULL;
1767
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001768 if (cur->val != NULL)
1769 ret->val = xmlCopyNodeList(cur->val);
1770 return(ret);
1771}
1772
1773/**
1774 * xmlCopyPropList:
Daniel Veillardb96e6431999-08-29 21:02:19 +00001775 * @target: the element where the attributes will be grafted
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001776 * @cur: the first attribute
1777 *
1778 * Do a copy of an attribute list.
1779 *
1780 * Returns: a new xmlAttrPtr, or NULL in case of error.
1781 */
1782xmlAttrPtr
Daniel Veillardb96e6431999-08-29 21:02:19 +00001783xmlCopyPropList(xmlNodePtr target, xmlAttrPtr cur) {
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001784 xmlAttrPtr ret = NULL;
1785 xmlAttrPtr p = NULL,q;
1786
1787 while (cur != NULL) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00001788 q = xmlCopyProp(target, cur);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001789 if (p == NULL) {
1790 ret = p = q;
1791 } else {
1792 p->next = q;
1793 p = q;
1794 }
1795 cur = cur->next;
1796 }
1797 return(ret);
1798}
1799
1800/*
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001801 * NOTE abeut the CopyNode operations !
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001802 *
1803 * They are splitted into external and internal parts for one
1804 * tricky reason: namespaces. Doing a direct copy of a node
1805 * say RPM:Copyright without changing the namespace pointer to
1806 * something else can produce stale links. One way to do it is
1807 * to keep a reference counter but this doesn't work as soon
1808 * as one move the element or the subtree out of the scope of
1809 * the existing namespace. The actual solution seems to add
1810 * a copy of the namespace at the top of the copied tree if
1811 * not available in the subtree.
1812 * Hence two functions, the public front-end call the inner ones
1813 */
1814
1815static xmlNodePtr
1816xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent);
1817
1818static xmlNodePtr
1819xmlStaticCopyNode(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent,
1820 int recursive) {
1821 xmlNodePtr ret;
1822
1823 if (node == NULL) return(NULL);
1824 /*
1825 * Allocate a new node and fill the fields.
1826 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001827 ret = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001828 if (ret == NULL) {
1829 fprintf(stderr, "xmlStaticCopyNode : malloc failed\n");
1830 return(NULL);
1831 }
1832
1833 ret->type = node->type;
1834 ret->doc = doc;
1835 ret->parent = parent;
1836 ret->next = NULL;
1837 ret->prev = NULL;
1838 ret->childs = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001839 ret->last = NULL;
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001840 ret->properties = NULL;
1841 if (node->name != NULL)
1842 ret->name = xmlStrdup(node->name);
1843 else
1844 ret->name = NULL;
1845 ret->ns = NULL;
1846 ret->nsDef = NULL;
1847 if ((node->content != NULL) && (node->type != XML_ENTITY_REF_NODE))
1848 ret->content = xmlStrdup(node->content);
1849 else
1850 ret->content = NULL;
Daniel Veillard27d88741999-05-29 11:51:49 +00001851#ifndef XML_WITHOUT_CORBA
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001852 ret->_private = NULL;
1853 ret->vepv = NULL;
1854#endif
1855 if (parent != NULL)
1856 xmlAddChild(parent, ret);
1857
1858 if (!recursive) return(ret);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001859 if (node->nsDef != NULL)
1860 ret->nsDef = xmlCopyNamespaceList(node->nsDef);
1861
1862 if (node->ns != NULL) {
1863 xmlNsPtr ns;
1864
1865 ns = xmlSearchNs(doc, ret, node->ns->prefix);
1866 if (ns == NULL) {
1867 /*
1868 * Humm, we are copying an element whose namespace is defined
1869 * out of the new tree scope. Search it in the original tree
1870 * and add it at the top of the new tree
1871 */
1872 ns = xmlSearchNs(node->doc, node, node->ns->prefix);
1873 if (ns != NULL) {
1874 xmlNodePtr root = ret;
1875
1876 while (root->parent != NULL) root = root->parent;
1877 xmlNewNs(root, ns->href, ns->prefix);
1878 }
1879 } else {
1880 /*
1881 * reference the existing namespace definition in our own tree.
1882 */
1883 ret->ns = ns;
1884 }
1885 }
Daniel Veillardb96e6431999-08-29 21:02:19 +00001886 if (node->properties != NULL)
1887 ret->properties = xmlCopyPropList(ret, node->properties);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001888 if (node->childs != NULL)
1889 ret->childs = xmlStaticCopyNodeList(node->childs, doc, ret);
Daniel Veillard1e346af1999-02-22 10:33:01 +00001890 UPDATE_LAST_CHILD(ret)
Daniel Veillardbe36afe1998-11-27 06:39:50 +00001891 return(ret);
1892}
1893
1894static xmlNodePtr
1895xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent) {
1896 xmlNodePtr ret = NULL;
1897 xmlNodePtr p = NULL,q;
1898
1899 while (node != NULL) {
1900 q = xmlStaticCopyNode(node, doc, parent, 1);
1901 if (parent == NULL) {
1902 if (ret == NULL) ret = q;
1903 } else {
1904 if (ret == NULL) {
1905 q->prev = NULL;
1906 ret = p = q;
1907 } else {
1908 p->next = q;
1909 q->prev = p;
1910 p = q;
1911 }
1912 }
1913 node = node->next;
1914 }
1915 return(ret);
1916}
1917
1918/**
1919 * xmlCopyNode:
1920 * @node: the node
1921 * @recursive: if 1 do a recursive copy.
1922 *
1923 * Do a copy of the node.
1924 *
1925 * Returns: a new xmlNodePtr, or NULL in case of error.
1926 */
1927xmlNodePtr
1928xmlCopyNode(xmlNodePtr node, int recursive) {
1929 xmlNodePtr ret;
1930
1931 ret = xmlStaticCopyNode(node, NULL, NULL, recursive);
1932 return(ret);
1933}
1934
1935/**
1936 * xmlCopyNodeList:
1937 * @node: the first node in the list.
1938 *
1939 * Do a recursive copy of the node list.
1940 *
1941 * Returns: a new xmlNodePtr, or NULL in case of error.
1942 */
1943xmlNodePtr xmlCopyNodeList(xmlNodePtr node) {
1944 xmlNodePtr ret = xmlStaticCopyNodeList(node, NULL, NULL);
1945 return(ret);
1946}
1947
1948/**
1949 * xmlCopyElement:
1950 * @elem: the element
1951 *
1952 * Do a copy of the element definition.
1953 *
1954 * Returns: a new xmlElementPtr, or NULL in case of error.
1955xmlElementPtr
1956xmlCopyElement(xmlElementPtr elem) {
1957 xmlElementPtr ret;
1958
1959 if (elem == NULL) return(NULL);
1960 ret = xmlNewDocElement(elem->doc, elem->ns, elem->name, elem->content);
1961 if (ret == NULL) return(NULL);
1962 if (!recursive) return(ret);
1963 if (elem->properties != NULL)
1964 ret->properties = xmlCopyPropList(elem->properties);
1965
1966 if (elem->nsDef != NULL)
1967 ret->nsDef = xmlCopyNamespaceList(elem->nsDef);
1968 if (elem->childs != NULL)
1969 ret->childs = xmlCopyElementList(elem->childs);
1970 return(ret);
1971}
1972 */
1973
1974/**
1975 * xmlCopyDtd:
1976 * @dtd: the dtd
1977 *
1978 * Do a copy of the dtd.
1979 *
1980 * Returns: a new xmlDtdPtr, or NULL in case of error.
1981 */
1982xmlDtdPtr
1983xmlCopyDtd(xmlDtdPtr dtd) {
1984 xmlDtdPtr ret;
1985
1986 if (dtd == NULL) return(NULL);
1987 ret = xmlNewDtd(NULL, dtd->name, dtd->ExternalID, dtd->SystemID);
1988 if (ret == NULL) return(NULL);
1989 if (dtd->entities != NULL)
1990 ret->entities = (void *) xmlCopyEntitiesTable(
1991 (xmlEntitiesTablePtr) dtd->entities);
Daniel Veillard1e346af1999-02-22 10:33:01 +00001992 if (dtd->notations != NULL)
1993 ret->notations = (void *) xmlCopyNotationTable(
1994 (xmlNotationTablePtr) dtd->notations);
1995 if (dtd->elements != NULL)
1996 ret->elements = (void *) xmlCopyElementTable(
1997 (xmlElementTablePtr) dtd->elements);
1998 if (dtd->attributes != NULL)
1999 ret->attributes = (void *) xmlCopyAttributeTable(
2000 (xmlAttributeTablePtr) dtd->attributes);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002001 return(ret);
2002}
2003
2004/**
2005 * xmlCopyDoc:
2006 * @doc: the document
2007 * @recursive: if 1 do a recursive copy.
2008 *
2009 * Do a copy of the document info. If recursive, the content tree will
2010 * be copied too as well as Dtd, namespaces and entities.
2011 *
2012 * Returns: a new xmlDocPtr, or NULL in case of error.
2013 */
2014xmlDocPtr
2015xmlCopyDoc(xmlDocPtr doc, int recursive) {
2016 xmlDocPtr ret;
2017
2018 if (doc == NULL) return(NULL);
2019 ret = xmlNewDoc(doc->version);
2020 if (ret == NULL) return(NULL);
2021 if (doc->name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +00002022 ret->name = xmlMemStrdup(doc->name);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002023 if (doc->encoding != NULL)
2024 ret->encoding = xmlStrdup(doc->encoding);
2025 ret->compression = doc->compression;
2026 ret->standalone = doc->standalone;
2027 if (!recursive) return(ret);
2028
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002029 if (doc->intSubset != NULL)
2030 ret->intSubset = xmlCopyDtd(doc->intSubset);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002031 if (doc->oldNs != NULL)
2032 ret->oldNs = xmlCopyNamespaceList(doc->oldNs);
2033 if (doc->root != NULL)
2034 ret->root = xmlStaticCopyNodeList(doc->root, ret, NULL);
2035 return(ret);
2036}
2037
2038/************************************************************************
2039 * *
Daniel Veillard260a68f1998-08-13 03:39:55 +00002040 * Content access functions *
2041 * *
2042 ************************************************************************/
2043
Daniel Veillard97b58771998-10-20 06:14:16 +00002044/**
Daniel Veillardb96e6431999-08-29 21:02:19 +00002045 * xmlNodeSetLang:
2046 * @cur: the node being changed
2047 * @lang: the langage description
2048 *
2049 * Searches the language of a node, i.e. the values of the xml:lang
2050 * attribute or the one carried by the nearest ancestor.
Daniel Veillardb96e6431999-08-29 21:02:19 +00002051 */
2052void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002053xmlNodeSetLang(xmlNodePtr cur, const xmlChar *lang) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00002054 /* TODO xmlNodeSetLang check against the production [33] LanguageID */
2055 xmlSetProp(cur, BAD_CAST "xml:lang", lang);
2056}
2057
2058/**
2059 * xmlNodeGetLang:
2060 * @cur: the node being checked
2061 *
2062 * Searches the language of a node, i.e. the values of the xml:lang
2063 * attribute or the one carried by the nearest ancestor.
2064 *
2065 * Returns a pointer to the lang value, or NULL if not found
Daniel Veillarda819dac1999-11-24 18:04:22 +00002066 * It's up to the caller to free the memory.
Daniel Veillardb96e6431999-08-29 21:02:19 +00002067 */
Daniel Veillarda819dac1999-11-24 18:04:22 +00002068xmlChar *
Daniel Veillardb96e6431999-08-29 21:02:19 +00002069xmlNodeGetLang(xmlNodePtr cur) {
Daniel Veillarda819dac1999-11-24 18:04:22 +00002070 xmlChar *lang;
Daniel Veillardb96e6431999-08-29 21:02:19 +00002071
2072 while (cur != NULL) {
2073 lang = xmlGetProp(cur, BAD_CAST "xml:lang");
2074 if (lang != NULL)
2075 return(lang);
2076 cur = cur->parent;
2077 }
2078 return(NULL);
2079}
2080
2081/**
Daniel Veillard16253641998-10-28 22:58:05 +00002082 * xmlNodeGetContent:
2083 * @cur: the node being read
2084 *
2085 * Read the value of a node, this can be either the text carried
2086 * directly by this node if it's a TEXT node or the aggregate string
2087 * of the values carried by this node child's (TEXT and ENTITY_REF).
2088 * Entity references are substitued.
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002089 * Returns a new xmlChar * or NULL if no content is available.
Daniel Veillard5099ae81999-04-21 20:12:07 +00002090 * It's up to the caller to free the memory.
Daniel Veillard16253641998-10-28 22:58:05 +00002091 */
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002092xmlChar *
Daniel Veillard16253641998-10-28 22:58:05 +00002093xmlNodeGetContent(xmlNodePtr cur) {
2094 if (cur == NULL) return(NULL);
2095 switch (cur->type) {
2096 case XML_DOCUMENT_FRAG_NODE:
2097 case XML_ELEMENT_NODE:
2098 return(xmlNodeListGetString(cur->doc, cur->childs, 1));
2099 break;
Daniel Veillardb96e6431999-08-29 21:02:19 +00002100 case XML_ATTRIBUTE_NODE: {
2101 xmlAttrPtr attr = (xmlAttrPtr) cur;
2102 if (attr->node != NULL)
2103 return(xmlNodeListGetString(attr->node->doc, attr->val, 1));
2104 else
2105 return(xmlNodeListGetString(NULL, attr->val, 1));
2106 break;
2107 }
2108 case XML_PI_NODE:
2109 if (cur->content != NULL)
2110 return(xmlStrdup(cur->content));
2111 return(NULL);
Daniel Veillard16253641998-10-28 22:58:05 +00002112 case XML_ENTITY_REF_NODE:
2113 case XML_ENTITY_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002114 case XML_COMMENT_NODE:
2115 case XML_DOCUMENT_NODE:
Daniel Veillard7c1206f1999-10-14 09:10:25 +00002116 case XML_HTML_DOCUMENT_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002117 case XML_DOCUMENT_TYPE_NODE:
2118 case XML_NOTATION_NODE:
2119 return(NULL);
Daniel Veillardb05deb71999-08-10 19:04:08 +00002120 case XML_CDATA_SECTION_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002121 case XML_TEXT_NODE:
2122 if (cur->content != NULL)
2123 return(xmlStrdup(cur->content));
2124 return(NULL);
2125 }
2126 return(NULL);
2127}
2128
2129/**
Daniel Veillard97b58771998-10-20 06:14:16 +00002130 * xmlNodeSetContent:
2131 * @cur: the node being modified
2132 * @content: the new value of the content
2133 *
2134 * Replace the content of a node.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002135 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002136void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002137xmlNodeSetContent(xmlNodePtr cur, const xmlChar *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002138 if (cur == NULL) {
2139 fprintf(stderr, "xmlNodeSetContent : node == NULL\n");
2140 return;
2141 }
Daniel Veillard16253641998-10-28 22:58:05 +00002142 switch (cur->type) {
2143 case XML_DOCUMENT_FRAG_NODE:
2144 case XML_ELEMENT_NODE:
2145 if (cur->content != NULL) {
Daniel Veillard6454aec1999-09-02 22:04:43 +00002146 xmlFree(cur->content);
Daniel Veillard16253641998-10-28 22:58:05 +00002147 cur->content = NULL;
2148 }
Daniel Veillard6454aec1999-09-02 22:04:43 +00002149 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillard16253641998-10-28 22:58:05 +00002150 cur->childs = xmlStringGetNodeList(cur->doc, content);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002151 UPDATE_LAST_CHILD(cur)
Daniel Veillard16253641998-10-28 22:58:05 +00002152 break;
2153 case XML_ATTRIBUTE_NODE:
2154 break;
2155 case XML_TEXT_NODE:
2156 case XML_CDATA_SECTION_NODE:
2157 case XML_ENTITY_REF_NODE:
2158 case XML_ENTITY_NODE:
2159 case XML_PI_NODE:
2160 case XML_COMMENT_NODE:
Daniel Veillard6454aec1999-09-02 22:04:43 +00002161 if (cur->content != NULL) xmlFree(cur->content);
2162 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002163 cur->last = cur->childs = NULL;
Daniel Veillard16253641998-10-28 22:58:05 +00002164 if (content != NULL)
2165 cur->content = xmlStrdup(content);
2166 else
2167 cur->content = NULL;
Daniel Veillardb96e6431999-08-29 21:02:19 +00002168 break;
Daniel Veillard16253641998-10-28 22:58:05 +00002169 case XML_DOCUMENT_NODE:
Daniel Veillard7c1206f1999-10-14 09:10:25 +00002170 case XML_HTML_DOCUMENT_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002171 case XML_DOCUMENT_TYPE_NODE:
2172 break;
2173 case XML_NOTATION_NODE:
2174 break;
2175 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002176}
2177
Daniel Veillard97b58771998-10-20 06:14:16 +00002178/**
2179 * xmlNodeSetContentLen:
2180 * @cur: the node being modified
2181 * @content: the new value of the content
2182 * @len: the size of @content
2183 *
2184 * Replace the content of a node.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002185 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002186void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002187xmlNodeSetContentLen(xmlNodePtr cur, const xmlChar *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002188 if (cur == NULL) {
Daniel Veillard16253641998-10-28 22:58:05 +00002189 fprintf(stderr, "xmlNodeSetContentLen : node == NULL\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002190 return;
2191 }
Daniel Veillard16253641998-10-28 22:58:05 +00002192 switch (cur->type) {
2193 case XML_DOCUMENT_FRAG_NODE:
2194 case XML_ELEMENT_NODE:
2195 if (cur->content != NULL) {
Daniel Veillard6454aec1999-09-02 22:04:43 +00002196 xmlFree(cur->content);
Daniel Veillard16253641998-10-28 22:58:05 +00002197 cur->content = NULL;
2198 }
Daniel Veillard6454aec1999-09-02 22:04:43 +00002199 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillard16253641998-10-28 22:58:05 +00002200 cur->childs = xmlStringLenGetNodeList(cur->doc, content, len);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002201 UPDATE_LAST_CHILD(cur)
Daniel Veillard16253641998-10-28 22:58:05 +00002202 break;
2203 case XML_ATTRIBUTE_NODE:
2204 break;
2205 case XML_TEXT_NODE:
2206 case XML_CDATA_SECTION_NODE:
2207 case XML_ENTITY_REF_NODE:
2208 case XML_ENTITY_NODE:
2209 case XML_PI_NODE:
2210 case XML_COMMENT_NODE:
Daniel Veillard6454aec1999-09-02 22:04:43 +00002211 if (cur->content != NULL) xmlFree(cur->content);
2212 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002213 cur->childs = cur->last = NULL;
Daniel Veillard16253641998-10-28 22:58:05 +00002214 if (content != NULL)
2215 cur->content = xmlStrndup(content, len);
2216 else
2217 cur->content = NULL;
Daniel Veillardb96e6431999-08-29 21:02:19 +00002218 break;
Daniel Veillard16253641998-10-28 22:58:05 +00002219 case XML_DOCUMENT_NODE:
Daniel Veillard7c1206f1999-10-14 09:10:25 +00002220 case XML_HTML_DOCUMENT_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002221 case XML_DOCUMENT_TYPE_NODE:
2222 break;
2223 case XML_NOTATION_NODE:
Daniel Veillard6454aec1999-09-02 22:04:43 +00002224 if (cur->content != NULL) xmlFree(cur->content);
2225 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002226 cur->childs = cur->last = NULL;
Daniel Veillard16253641998-10-28 22:58:05 +00002227 if (content != NULL)
2228 cur->content = xmlStrndup(content, len);
2229 else
2230 cur->content = NULL;
2231 break;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002232 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002233}
2234
Daniel Veillard97b58771998-10-20 06:14:16 +00002235/**
2236 * xmlNodeAddContentLen:
2237 * @cur: the node being modified
2238 * @content: extra content
2239 * @len: the size of @content
2240 *
2241 * Append the extra substring to the node content.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002242 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002243void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002244xmlNodeAddContentLen(xmlNodePtr cur, const xmlChar *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002245 if (cur == NULL) {
Daniel Veillard16253641998-10-28 22:58:05 +00002246 fprintf(stderr, "xmlNodeAddContentLen : node == NULL\n");
2247 return;
2248 }
2249 if (len <= 0) return;
2250 switch (cur->type) {
2251 case XML_DOCUMENT_FRAG_NODE:
2252 case XML_ELEMENT_NODE: {
2253 xmlNodePtr last = NULL, new;
2254
2255 if (cur->childs != NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002256 last = cur->last;
Daniel Veillard16253641998-10-28 22:58:05 +00002257 } else {
2258 if (cur->content != NULL) {
2259 cur->childs = xmlStringGetNodeList(cur->doc, cur->content);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002260 UPDATE_LAST_CHILD(cur)
Daniel Veillard6454aec1999-09-02 22:04:43 +00002261 xmlFree(cur->content);
Daniel Veillard16253641998-10-28 22:58:05 +00002262 cur->content = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002263 last = cur->last;
Daniel Veillard16253641998-10-28 22:58:05 +00002264 }
2265 }
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002266 new = xmlNewTextLen(content, len);
Daniel Veillard16253641998-10-28 22:58:05 +00002267 if (new != NULL) {
2268 xmlAddChild(cur, new);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002269 if ((last != NULL) && (last->next == new)) {
Daniel Veillard16253641998-10-28 22:58:05 +00002270 xmlTextMerge(last, new);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002271 }
Daniel Veillard16253641998-10-28 22:58:05 +00002272 }
2273 break;
2274 }
2275 case XML_ATTRIBUTE_NODE:
2276 break;
2277 case XML_TEXT_NODE:
2278 case XML_CDATA_SECTION_NODE:
2279 case XML_ENTITY_REF_NODE:
2280 case XML_ENTITY_NODE:
2281 case XML_PI_NODE:
2282 case XML_COMMENT_NODE:
2283 if (content != NULL)
2284 cur->content = xmlStrncat(cur->content, content, len);
2285 case XML_DOCUMENT_NODE:
Daniel Veillard7c1206f1999-10-14 09:10:25 +00002286 case XML_HTML_DOCUMENT_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002287 case XML_DOCUMENT_TYPE_NODE:
2288 break;
2289 case XML_NOTATION_NODE:
2290 if (content != NULL)
2291 cur->content = xmlStrncat(cur->content, content, len);
2292 break;
2293 }
2294}
2295
2296/**
2297 * xmlNodeAddContent:
2298 * @cur: the node being modified
2299 * @content: extra content
2300 *
2301 * Append the extra substring to the node content.
2302 */
2303void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002304xmlNodeAddContent(xmlNodePtr cur, const xmlChar *content) {
Daniel Veillard16253641998-10-28 22:58:05 +00002305 int len;
2306
2307 if (cur == NULL) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002308 fprintf(stderr, "xmlNodeAddContent : node == NULL\n");
2309 return;
2310 }
Daniel Veillard16253641998-10-28 22:58:05 +00002311 if (content == NULL) return;
2312 len = xmlStrlen(content);
2313 xmlNodeAddContentLen(cur, content, len);
2314}
2315
2316/**
2317 * xmlTextMerge:
2318 * @first: the first text node
2319 * @second: the second text node being merged
2320 *
2321 * Merge two text nodes into one
Daniel Veillard1e346af1999-02-22 10:33:01 +00002322 * Returns the first text node augmented
Daniel Veillard16253641998-10-28 22:58:05 +00002323 */
2324xmlNodePtr
2325xmlTextMerge(xmlNodePtr first, xmlNodePtr second) {
2326 if (first == NULL) return(second);
2327 if (second == NULL) return(first);
2328 if (first->type != XML_TEXT_NODE) return(first);
2329 if (second->type != XML_TEXT_NODE) return(first);
2330 xmlNodeAddContent(first, second->content);
2331 xmlUnlinkNode(second);
2332 xmlFreeNode(second);
2333 return(first);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002334}
2335
Daniel Veillard97b58771998-10-20 06:14:16 +00002336/**
Daniel Veillardb96e6431999-08-29 21:02:19 +00002337 * xmlGetNsList:
2338 * @doc: the document
2339 * @node: the current node
2340 *
2341 * Search all the namespace applying to a given element.
2342 * Returns an NULL terminated array of all the xmlNsPtr found
2343 * that need to be freed by the caller or NULL if no
2344 * namespace if defined
2345 */
2346xmlNsPtr *
2347xmlGetNsList(xmlDocPtr doc, xmlNodePtr node) {
2348 xmlNsPtr cur;
2349 xmlNsPtr *ret = NULL;
2350 int nbns = 0;
2351 int maxns = 10;
2352 int i;
2353
2354 while (node != NULL) {
2355 cur = node->nsDef;
2356 while (cur != NULL) {
2357 if (ret == NULL) {
Daniel Veillard6454aec1999-09-02 22:04:43 +00002358 ret = (xmlNsPtr *) xmlMalloc((maxns + 1) * sizeof(xmlNsPtr));
Daniel Veillardb96e6431999-08-29 21:02:19 +00002359 if (ret == NULL) {
2360 fprintf(stderr, "xmlGetNsList : out of memory!\n");
2361 return(NULL);
2362 }
2363 ret[nbns] = NULL;
2364 }
2365 for (i = 0;i < nbns;i++) {
2366 if ((cur->prefix == ret[i]->prefix) ||
2367 (!xmlStrcmp(cur->prefix, ret[i]->prefix))) break;
2368 }
2369 if (i >= nbns) {
2370 if (nbns >= maxns) {
2371 maxns *= 2;
Daniel Veillard6454aec1999-09-02 22:04:43 +00002372 ret = (xmlNsPtr *) xmlRealloc(ret,
Daniel Veillardb96e6431999-08-29 21:02:19 +00002373 (maxns + 1) * sizeof(xmlNsPtr));
2374 if (ret == NULL) {
2375 fprintf(stderr, "xmlGetNsList : realloc failed!\n");
2376 return(NULL);
2377 }
2378 }
2379 ret[nbns++] = cur;
2380 ret[nbns] = NULL;
2381 }
2382
2383 cur = cur->next;
2384 }
2385 node = node->parent;
2386 }
2387 return(ret);
2388}
2389
2390/**
Daniel Veillard97b58771998-10-20 06:14:16 +00002391 * xmlSearchNs:
2392 * @doc: the document
2393 * @node: the current node
2394 * @nameSpace: the namespace string
Daniel Veillard260a68f1998-08-13 03:39:55 +00002395 *
Daniel Veillard97b58771998-10-20 06:14:16 +00002396 * Search a Ns registered under a given name space for a document.
2397 * recurse on the parents until it finds the defined namespace
2398 * or return NULL otherwise.
2399 * @nameSpace can be NULL, this is a search for the default namespace.
Daniel Veillard1e346af1999-02-22 10:33:01 +00002400 * Returns the namespace pointer or NULL.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002401 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002402xmlNsPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002403xmlSearchNs(xmlDocPtr doc, xmlNodePtr node, const xmlChar *nameSpace) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002404 xmlNsPtr cur;
2405
2406 while (node != NULL) {
2407 cur = node->nsDef;
2408 while (cur != NULL) {
2409 if ((cur->prefix == NULL) && (nameSpace == NULL))
2410 return(cur);
2411 if ((cur->prefix != NULL) && (nameSpace != NULL) &&
2412 (!xmlStrcmp(cur->prefix, nameSpace)))
2413 return(cur);
2414 cur = cur->next;
2415 }
2416 node = node->parent;
2417 }
2418 if (doc != NULL) {
2419 cur = doc->oldNs;
2420 while (cur != NULL) {
2421 if ((cur->prefix != NULL) && (nameSpace != NULL) &&
2422 (!xmlStrcmp(cur->prefix, nameSpace)))
2423 return(cur);
2424 cur = cur->next;
2425 }
2426 }
2427 return(NULL);
2428}
2429
Daniel Veillard97b58771998-10-20 06:14:16 +00002430/**
2431 * xmlSearchNsByHref:
2432 * @doc: the document
2433 * @node: the current node
2434 * @href: the namespace value
2435 *
2436 * Search a Ns aliasing a given URI. Recurse on the parents until it finds
2437 * the defined namespace or return NULL otherwise.
Daniel Veillard1e346af1999-02-22 10:33:01 +00002438 * Returns the namespace pointer or NULL.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002439 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002440xmlNsPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002441xmlSearchNsByHref(xmlDocPtr doc, xmlNodePtr node, const xmlChar *href) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002442 xmlNsPtr cur;
2443
2444 while (node != NULL) {
2445 cur = node->nsDef;
2446 while (cur != NULL) {
2447 if ((cur->href != NULL) && (href != NULL) &&
2448 (!xmlStrcmp(cur->href, href)))
2449 return(cur);
2450 cur = cur->next;
2451 }
2452 node = node->parent;
2453 }
2454 if (doc != NULL) {
2455 cur = doc->oldNs;
2456 while (cur != NULL) {
2457 if ((cur->href != NULL) && (href != NULL) &&
2458 (!xmlStrcmp(cur->href, href)))
2459 return(cur);
2460 cur = cur->next;
2461 }
2462 }
2463 return(NULL);
2464}
2465
Daniel Veillard97b58771998-10-20 06:14:16 +00002466/**
2467 * xmlGetProp:
2468 * @node: the node
2469 * @name: the attribute name
2470 *
2471 * Search and get the value of an attribute associated to a node
Daniel Veillardccb09631998-10-27 06:21:04 +00002472 * This does the entity substitution.
Daniel Veillard1e346af1999-02-22 10:33:01 +00002473 * Returns the attribute value or NULL if not found.
Daniel Veillarda819dac1999-11-24 18:04:22 +00002474 * It's up to the caller to free the memory.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002475 */
Daniel Veillarda819dac1999-11-24 18:04:22 +00002476xmlChar *
2477xmlGetProp(xmlNodePtr node, const xmlChar *name) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002478 xmlAttrPtr prop = node->properties;
2479
2480 while (prop != NULL) {
Daniel Veillard68178931999-02-08 18:34:36 +00002481 if (!xmlStrcmp(prop->name, name)) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002482 xmlChar *ret;
Daniel Veillard6800ef31999-02-08 18:33:22 +00002483
2484 ret = xmlNodeListGetString(node->doc, prop->val, 1);
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002485 if (ret == NULL) return(xmlStrdup((xmlChar *)""));
Daniel Veillard6800ef31999-02-08 18:33:22 +00002486 return(ret);
Daniel Veillard68178931999-02-08 18:34:36 +00002487 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002488 prop = prop->next;
2489 }
2490 return(NULL);
2491}
2492
Daniel Veillard97b58771998-10-20 06:14:16 +00002493/**
Daniel Veillardccb09631998-10-27 06:21:04 +00002494 * xmlSetProp:
Daniel Veillard97b58771998-10-20 06:14:16 +00002495 * @node: the node
2496 * @name: the attribute name
2497 * @value: the attribute value
2498 *
2499 * Set (or reset) an attribute carried by a node.
Daniel Veillard1e346af1999-02-22 10:33:01 +00002500 * Returns the attribute pointer.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002501 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002502xmlAttrPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002503xmlSetProp(xmlNodePtr node, const xmlChar *name, const xmlChar *value) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002504 xmlAttrPtr prop = node->properties;
2505
2506 while (prop != NULL) {
2507 if (!xmlStrcmp(prop->name, name)) {
Daniel Veillardccb09631998-10-27 06:21:04 +00002508 if (prop->val != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +00002509 xmlFreeNodeList(prop->val);
Daniel Veillardccb09631998-10-27 06:21:04 +00002510 prop->val = NULL;
Daniel Veillard51e3b151999-11-12 17:02:31 +00002511 if (value != NULL) {
2512 xmlChar *buffer;
2513 buffer = xmlEncodeEntitiesReentrant(node->doc, value);
2514 prop->val = xmlStringGetNodeList(node->doc, buffer);
2515 xmlFree(buffer);
2516 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002517 return(prop);
2518 }
2519 prop = prop->next;
2520 }
2521 prop = xmlNewProp(node, name, value);
2522 return(prop);
2523}
2524
Daniel Veillard97b58771998-10-20 06:14:16 +00002525/**
2526 * xmlNodeIsText:
2527 * @node: the node
2528 *
2529 * Is this node a Text node ?
Daniel Veillard1e346af1999-02-22 10:33:01 +00002530 * Returns 1 yes, 0 no
Daniel Veillard260a68f1998-08-13 03:39:55 +00002531 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002532int
2533xmlNodeIsText(xmlNodePtr node) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002534 if (node == NULL) return(0);
2535
Daniel Veillard0bef1311998-10-14 02:36:47 +00002536 if (node->type == XML_TEXT_NODE) return(1);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002537 return(0);
2538}
2539
Daniel Veillard97b58771998-10-20 06:14:16 +00002540/**
Daniel Veillard1e346af1999-02-22 10:33:01 +00002541 * xmlTextConcat:
Daniel Veillard97b58771998-10-20 06:14:16 +00002542 * @node: the node
2543 * @content: the content
2544 * @len: @content lenght
2545 *
2546 * Concat the given string at the end of the existing node content
Daniel Veillard260a68f1998-08-13 03:39:55 +00002547 */
Daniel Veillard97b58771998-10-20 06:14:16 +00002548
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002549void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002550xmlTextConcat(xmlNodePtr node, const xmlChar *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002551 if (node == NULL) return;
2552
Daniel Veillard0bef1311998-10-14 02:36:47 +00002553 if (node->type != XML_TEXT_NODE) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002554 fprintf(stderr, "xmlTextConcat: node is not text\n");
2555 return;
2556 }
2557 node->content = xmlStrncat(node->content, content, len);
2558}
2559
2560/************************************************************************
2561 * *
2562 * Output : to a FILE or in memory *
2563 * *
2564 ************************************************************************/
2565
Daniel Veillard5099ae81999-04-21 20:12:07 +00002566#define BASE_BUFFER_SIZE 4000
2567
2568/**
2569 * xmlBufferCreate:
2570 *
2571 * routine to create an XML buffer.
2572 * returns the new structure.
2573 */
2574xmlBufferPtr
2575xmlBufferCreate(void) {
2576 xmlBufferPtr ret;
2577
Daniel Veillard6454aec1999-09-02 22:04:43 +00002578 ret = (xmlBufferPtr) xmlMalloc(sizeof(xmlBuffer));
Daniel Veillard5099ae81999-04-21 20:12:07 +00002579 if (ret == NULL) {
2580 fprintf(stderr, "xmlBufferCreate : out of memory!\n");
2581 return(NULL);
2582 }
2583 ret->use = 0;
2584 ret->size = BASE_BUFFER_SIZE;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002585 ret->content = (xmlChar *) xmlMalloc(ret->size * sizeof(xmlChar));
Daniel Veillard5099ae81999-04-21 20:12:07 +00002586 if (ret->content == NULL) {
2587 fprintf(stderr, "xmlBufferCreate : out of memory!\n");
Daniel Veillard6454aec1999-09-02 22:04:43 +00002588 xmlFree(ret);
Daniel Veillard5099ae81999-04-21 20:12:07 +00002589 return(NULL);
2590 }
2591 ret->content[0] = 0;
2592 return(ret);
2593}
2594
2595/**
2596 * xmlBufferFree:
2597 * @buf: the buffer to free
2598 *
2599 * Frees an XML buffer.
2600 */
2601void
2602xmlBufferFree(xmlBufferPtr buf) {
2603 if (buf == NULL) {
2604 fprintf(stderr, "xmlBufferFree: buf == NULL\n");
2605 return;
2606 }
2607 if (buf->content == NULL) {
2608 fprintf(stderr, "xmlBufferFree: buf->content == NULL\n");
2609 } else {
2610 memset(buf->content, -1, BASE_BUFFER_SIZE);
Daniel Veillard6454aec1999-09-02 22:04:43 +00002611 xmlFree(buf->content);
Daniel Veillard5099ae81999-04-21 20:12:07 +00002612 }
2613 memset(buf, -1, sizeof(xmlBuffer));
Daniel Veillard6454aec1999-09-02 22:04:43 +00002614 xmlFree(buf);
Daniel Veillard5099ae81999-04-21 20:12:07 +00002615}
2616
2617/**
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002618 * xmlBufferEmpty:
2619 * @buf: the buffer
2620 *
2621 * empty a buffer.
2622 */
2623void
2624xmlBufferEmpty(xmlBufferPtr buf) {
2625 buf->use = 0;
2626 memset(buf->content, -1, buf->size);/* just for debug */
2627}
2628
2629/**
2630 * xmlBufferShrink:
2631 * @buf: the buffer to dump
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002632 * @len: the number of xmlChar to remove
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002633 *
2634 * Remove the beginning of an XML buffer.
2635 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002636 * Returns the number of xmlChar removed, or -1 in case of failure.
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002637 */
2638int
2639xmlBufferShrink(xmlBufferPtr buf, int len) {
2640 if (len == 0) return(0);
2641 if (len > buf->use) return(-1);
2642
2643 buf->use -= len;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002644 memmove(buf->content, &buf->content[len], buf->use * sizeof(xmlChar));
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002645
2646 buf->content[buf->use] = 0;
2647 return(len);
2648}
2649
2650/**
Daniel Veillard5099ae81999-04-21 20:12:07 +00002651 * xmlBufferDump:
2652 * @file: the file output
2653 * @buf: the buffer to dump
2654 *
2655 * Dumps an XML buffer to a FILE *.
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002656 * Returns the number of xmlChar written
Daniel Veillard5099ae81999-04-21 20:12:07 +00002657 */
2658int
2659xmlBufferDump(FILE *file, xmlBufferPtr buf) {
2660 int ret;
2661
2662 if (buf == NULL) {
2663 fprintf(stderr, "xmlBufferDump: buf == NULL\n");
2664 return(0);
2665 }
2666 if (buf->content == NULL) {
2667 fprintf(stderr, "xmlBufferDump: buf->content == NULL\n");
2668 return(0);
2669 }
2670 if (file == NULL) file = stdout;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002671 ret = fwrite(buf->content, sizeof(xmlChar), buf->use, file);
Daniel Veillard5099ae81999-04-21 20:12:07 +00002672 return(ret);
2673}
2674
2675/**
2676 * xmlBufferAdd:
2677 * @buf: the buffer to dump
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002678 * @str: the xmlChar string
2679 * @len: the number of xmlChar to add
Daniel Veillard5099ae81999-04-21 20:12:07 +00002680 *
2681 * Add a string range to an XML buffer.
2682 */
2683void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002684xmlBufferAdd(xmlBufferPtr buf, const xmlChar *str, int len) {
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002685 int l;
Daniel Veillard5099ae81999-04-21 20:12:07 +00002686
2687 if (str == NULL) {
2688 fprintf(stderr, "xmlBufferAdd: str == NULL\n");
2689 return;
2690 }
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002691 l = xmlStrlen(str);
2692 if (l < len) len = l;
2693 if (len <= 0) return;
Daniel Veillard5099ae81999-04-21 20:12:07 +00002694
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002695 if (buf->use + len + 10 >= buf->size) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002696 xmlChar *rebuf;
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002697
2698 buf->size *= 2;
2699 if (buf->use + len + 10 > buf->size)
2700 buf->size = buf->use + len + 10;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002701 rebuf = (xmlChar *) xmlRealloc(buf->content, buf->size * sizeof(xmlChar));
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002702 if (rebuf == NULL) {
2703 fprintf(stderr, "xmlBufferAdd : out of memory!\n");
2704 return;
Daniel Veillard5099ae81999-04-21 20:12:07 +00002705 }
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002706 buf->content = rebuf;
Daniel Veillard5099ae81999-04-21 20:12:07 +00002707 }
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002708 memmove(&buf->content[buf->use], str, len);
2709 buf->use += len;
2710 buf->content[buf->use] = 0;
Daniel Veillard5099ae81999-04-21 20:12:07 +00002711}
2712
2713/**
2714 * xmlBufferCat:
2715 * @buf: the buffer to dump
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002716 * @str: the xmlChar string
Daniel Veillard5099ae81999-04-21 20:12:07 +00002717 *
2718 * Append a zero terminated string to an XML buffer.
2719 */
2720void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002721xmlBufferCat(xmlBufferPtr buf, const xmlChar *str) {
2722 const xmlChar *cur;
Daniel Veillard5099ae81999-04-21 20:12:07 +00002723
2724 if (str == NULL) {
2725 fprintf(stderr, "xmlBufferAdd: str == NULL\n");
2726 return;
2727 }
2728 for (cur = str;*cur != 0;cur++) {
2729 if (buf->use + 10 >= buf->size) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002730 xmlChar *rebuf;
Daniel Veillard5099ae81999-04-21 20:12:07 +00002731
2732 buf->size *= 2;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002733 rebuf = (xmlChar *) xmlRealloc(buf->content, buf->size * sizeof(xmlChar));
Daniel Veillard5099ae81999-04-21 20:12:07 +00002734 if (rebuf == NULL) {
2735 fprintf(stderr, "xmlBufferAdd : out of memory!\n");
2736 return;
2737 }
2738 buf->content = rebuf;
2739 }
2740 buf->content[buf->use++] = *cur;
2741 }
2742}
2743
2744/**
2745 * xmlBufferCCat:
2746 * @buf: the buffer to dump
2747 * @str: the C char string
2748 *
2749 * Append a zero terminated C string to an XML buffer.
2750 */
2751void
2752xmlBufferCCat(xmlBufferPtr buf, const char *str) {
2753 const char *cur;
2754
2755 if (str == NULL) {
2756 fprintf(stderr, "xmlBufferAdd: str == NULL\n");
2757 return;
2758 }
2759 for (cur = str;*cur != 0;cur++) {
2760 if (buf->use + 10 >= buf->size) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002761 xmlChar *rebuf;
Daniel Veillard5099ae81999-04-21 20:12:07 +00002762
2763 buf->size *= 2;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002764 rebuf = (xmlChar *) xmlRealloc(buf->content, buf->size * sizeof(xmlChar));
Daniel Veillard5099ae81999-04-21 20:12:07 +00002765 if (rebuf == NULL) {
2766 fprintf(stderr, "xmlBufferAdd : out of memory!\n");
2767 return;
2768 }
2769 buf->content = rebuf;
2770 }
2771 buf->content[buf->use++] = *cur;
2772 }
2773}
Daniel Veillard260a68f1998-08-13 03:39:55 +00002774
Daniel Veillard97b58771998-10-20 06:14:16 +00002775/**
Daniel Veillard7d2c2761999-10-11 15:09:51 +00002776 * xmlBufferLastChar:
2777 * @buf: the buffer to dump
2778 *
2779 * Get the last char of the buffer
2780 *
2781 * Returns the last char from the buffer or 0 if empty
2782 */
2783xmlChar
2784xmlBufferLastChar(xmlBufferPtr buf) {
2785 if ((buf == NULL) || (buf->use <= 0)) return(0);
2786 return(buf->content[buf->use - 1]);
2787}
2788
2789/**
Daniel Veillard97b58771998-10-20 06:14:16 +00002790 * xmlBufferWriteCHAR:
Daniel Veillard5099ae81999-04-21 20:12:07 +00002791 * @buf: the XML buffer
Daniel Veillard97b58771998-10-20 06:14:16 +00002792 * @string: the string to add
2793 *
2794 * routine which manage and grows an output buffer. This one add
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002795 * xmlChars at the end of the buffer.
Daniel Veillard97b58771998-10-20 06:14:16 +00002796 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002797void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002798xmlBufferWriteCHAR(xmlBufferPtr buf, const xmlChar *string) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002799 xmlBufferCat(buf, string);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002800}
2801
Daniel Veillard97b58771998-10-20 06:14:16 +00002802/**
2803 * xmlBufferWriteChar:
Daniel Veillard011b63c1999-06-02 17:44:04 +00002804 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00002805 * @string: the string to add
2806 *
2807 * routine which manage and grows an output buffer. This one add
2808 * C chars at the end of the array.
2809 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002810void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002811xmlBufferWriteChar(xmlBufferPtr buf, const char *string) {
2812 xmlBufferCCat(buf, string);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002813}
2814
Daniel Veillard5099ae81999-04-21 20:12:07 +00002815
Daniel Veillard97b58771998-10-20 06:14:16 +00002816/**
Daniel Veillard011b63c1999-06-02 17:44:04 +00002817 * xmlBufferWriteQuotedString:
2818 * @buf: the XML buffer output
2819 * @string: the string to add
2820 *
2821 * routine which manage and grows an output buffer. This one writes
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002822 * a quoted or double quoted xmlChar string, checking first if it holds
Daniel Veillard011b63c1999-06-02 17:44:04 +00002823 * quote or double-quotes internally
2824 */
2825void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002826xmlBufferWriteQuotedString(xmlBufferPtr buf, const xmlChar *string) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00002827 if (xmlStrchr(string, '"')) {
2828 if (xmlStrchr(string, '\'')) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00002829 fprintf(stderr,
2830 "xmlBufferWriteQuotedString: string contains quote and double-quotes !\n");
2831 }
2832 xmlBufferCCat(buf, "'");
2833 xmlBufferCat(buf, string);
2834 xmlBufferCCat(buf, "'");
2835 } else {
2836 xmlBufferCCat(buf, "\"");
2837 xmlBufferCat(buf, string);
2838 xmlBufferCCat(buf, "\"");
2839 }
2840}
2841
2842
2843/**
Daniel Veillard97b58771998-10-20 06:14:16 +00002844 * xmlGlobalNsDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00002845 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00002846 * @cur: a namespace
2847 *
2848 * Dump a global Namespace, this is the old version based on PIs.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002849 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002850static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002851xmlGlobalNsDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002852 if (cur == NULL) {
2853 fprintf(stderr, "xmlGlobalNsDump : Ns == NULL\n");
2854 return;
2855 }
2856 if (cur->type == XML_GLOBAL_NAMESPACE) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002857 xmlBufferWriteChar(buf, "<?namespace");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002858 if (cur->href != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00002859 xmlBufferWriteChar(buf, " href=");
2860 xmlBufferWriteQuotedString(buf, cur->href);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002861 }
2862 if (cur->prefix != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00002863 xmlBufferWriteChar(buf, " AS=");
2864 xmlBufferWriteQuotedString(buf, cur->prefix);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002865 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00002866 xmlBufferWriteChar(buf, "?>\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002867 }
2868}
2869
Daniel Veillard97b58771998-10-20 06:14:16 +00002870/**
2871 * xmlGlobalNsListDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00002872 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00002873 * @cur: the first namespace
2874 *
2875 * Dump a list of global Namespace, this is the old version based on PIs.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002876 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002877static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002878xmlGlobalNsListDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002879 while (cur != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002880 xmlGlobalNsDump(buf, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002881 cur = cur->next;
2882 }
2883}
2884
Daniel Veillard97b58771998-10-20 06:14:16 +00002885/**
2886 * xmlNsDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00002887 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00002888 * @cur: a namespace
2889 *
Daniel Veillard260a68f1998-08-13 03:39:55 +00002890 * Dump a local Namespace definition.
Daniel Veillard97b58771998-10-20 06:14:16 +00002891 * Should be called in the context of attributes dumps.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002892 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002893static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002894xmlNsDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002895 if (cur == NULL) {
2896 fprintf(stderr, "xmlNsDump : Ns == NULL\n");
2897 return;
2898 }
2899 if (cur->type == XML_LOCAL_NAMESPACE) {
2900 /* Within the context of an element attributes */
2901 if (cur->prefix != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002902 xmlBufferWriteChar(buf, " xmlns:");
2903 xmlBufferWriteCHAR(buf, cur->prefix);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002904 } else
Daniel Veillard5099ae81999-04-21 20:12:07 +00002905 xmlBufferWriteChar(buf, " xmlns");
Daniel Veillard011b63c1999-06-02 17:44:04 +00002906 xmlBufferWriteChar(buf, "=");
2907 xmlBufferWriteQuotedString(buf, cur->href);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002908 }
2909}
2910
Daniel Veillard97b58771998-10-20 06:14:16 +00002911/**
2912 * xmlNsListDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00002913 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00002914 * @cur: the first namespace
2915 *
2916 * Dump a list of local Namespace definitions.
2917 * Should be called in the context of attributes dumps.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002918 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002919static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002920xmlNsListDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002921 while (cur != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002922 xmlNsDump(buf, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002923 cur = cur->next;
2924 }
2925}
2926
Daniel Veillard97b58771998-10-20 06:14:16 +00002927/**
2928 * xmlDtdDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00002929 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00002930 * @doc: the document
2931 *
2932 * Dump the XML document DTD, if any.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002933 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002934static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002935xmlDtdDump(xmlBufferPtr buf, xmlDocPtr doc) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002936 xmlDtdPtr cur = doc->intSubset;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002937
2938 if (cur == NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002939 fprintf(stderr, "xmlDtdDump : no internal subset\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002940 return;
2941 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00002942 xmlBufferWriteChar(buf, "<!DOCTYPE ");
2943 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002944 if (cur->ExternalID != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00002945 xmlBufferWriteChar(buf, " PUBLIC ");
2946 xmlBufferWriteQuotedString(buf, cur->ExternalID);
2947 xmlBufferWriteChar(buf, " ");
2948 xmlBufferWriteQuotedString(buf, cur->SystemID);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002949 } else if (cur->SystemID != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00002950 xmlBufferWriteChar(buf, " SYSTEM ");
2951 xmlBufferWriteQuotedString(buf, cur->SystemID);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002952 }
Daniel Veillard1e346af1999-02-22 10:33:01 +00002953 if ((cur->entities == NULL) && (cur->elements == NULL) &&
2954 (cur->attributes == NULL) && (cur->notations == NULL)) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002955 xmlBufferWriteChar(buf, ">\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002956 return;
2957 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00002958 xmlBufferWriteChar(buf, " [\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002959 if (cur->entities != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00002960 xmlDumpEntitiesTable(buf, (xmlEntitiesTablePtr) cur->entities);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002961 if (cur->notations != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00002962 xmlDumpNotationTable(buf, (xmlNotationTablePtr) cur->notations);
Daniel Veillard3b9def11999-01-31 22:15:06 +00002963 if (cur->elements != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00002964 xmlDumpElementTable(buf, (xmlElementTablePtr) cur->elements);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002965 if (cur->attributes != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00002966 xmlDumpAttributeTable(buf, (xmlAttributeTablePtr) cur->attributes);
2967 xmlBufferWriteChar(buf, "]");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002968
Daniel Veillard5099ae81999-04-21 20:12:07 +00002969 xmlBufferWriteChar(buf, ">\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002970}
2971
Daniel Veillard97b58771998-10-20 06:14:16 +00002972/**
2973 * xmlAttrDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00002974 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00002975 * @doc: the document
2976 * @cur: the attribute pointer
2977 *
2978 * Dump an XML attribute
Daniel Veillard260a68f1998-08-13 03:39:55 +00002979 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002980static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002981xmlAttrDump(xmlBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002982 xmlChar *value;
Daniel Veillardccb09631998-10-27 06:21:04 +00002983
Daniel Veillard260a68f1998-08-13 03:39:55 +00002984 if (cur == NULL) {
2985 fprintf(stderr, "xmlAttrDump : property == NULL\n");
2986 return;
2987 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00002988 xmlBufferWriteChar(buf, " ");
Daniel Veillardb96e6431999-08-29 21:02:19 +00002989 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
2990 xmlBufferWriteCHAR(buf, cur->ns->prefix);
2991 xmlBufferWriteChar(buf, ":");
2992 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00002993 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillardccb09631998-10-27 06:21:04 +00002994 value = xmlNodeListGetString(doc, cur->val, 0);
2995 if (value) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00002996 xmlBufferWriteChar(buf, "=");
2997 xmlBufferWriteQuotedString(buf, value);
Daniel Veillard6454aec1999-09-02 22:04:43 +00002998 xmlFree(value);
Daniel Veillard726c7e31999-02-08 15:13:10 +00002999 } else {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003000 xmlBufferWriteChar(buf, "=\"\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003001 }
3002}
3003
Daniel Veillard97b58771998-10-20 06:14:16 +00003004/**
3005 * xmlAttrListDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003006 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003007 * @doc: the document
3008 * @cur: the first attribute pointer
3009 *
3010 * Dump a list of XML attributes
Daniel Veillard260a68f1998-08-13 03:39:55 +00003011 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003012static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00003013xmlAttrListDump(xmlBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003014 if (cur == NULL) {
3015 fprintf(stderr, "xmlAttrListDump : property == NULL\n");
3016 return;
3017 }
3018 while (cur != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003019 xmlAttrDump(buf, doc, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003020 cur = cur->next;
3021 }
3022}
3023
Daniel Veillard260a68f1998-08-13 03:39:55 +00003024
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003025static void
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003026xmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
3027 int format);
Daniel Veillard97b58771998-10-20 06:14:16 +00003028/**
3029 * xmlNodeListDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003030 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003031 * @doc: the document
3032 * @cur: the first node
3033 * @level: the imbrication level for indenting
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003034 * @format: is formatting allowed
Daniel Veillard97b58771998-10-20 06:14:16 +00003035 *
3036 * Dump an XML node list, recursive behaviour,children are printed too.
3037 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003038static void
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003039xmlNodeListDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
3040 int format) {
3041 int i;
Daniel Veillardccb09631998-10-27 06:21:04 +00003042
Daniel Veillard260a68f1998-08-13 03:39:55 +00003043 if (cur == NULL) {
3044 fprintf(stderr, "xmlNodeListDump : node == NULL\n");
3045 return;
3046 }
3047 while (cur != NULL) {
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003048 if ((format) && (xmlIndentTreeOutput) &&
3049 (cur->type == XML_ELEMENT_NODE))
3050 for (i = 0;i < level;i++)
3051 xmlBufferWriteChar(buf, " ");
3052 xmlNodeDump(buf, doc, cur, level, format);
3053 if (format) {
3054 xmlBufferWriteChar(buf, "\n");
Daniel Veillardccb09631998-10-27 06:21:04 +00003055 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003056 cur = cur->next;
3057 }
3058}
3059
Daniel Veillard97b58771998-10-20 06:14:16 +00003060/**
Daniel Veillardccb09631998-10-27 06:21:04 +00003061 * xmlNodeDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003062 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003063 * @doc: the document
3064 * @cur: the current node
3065 * @level: the imbrication level for indenting
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003066 * @format: is formatting allowed
Daniel Veillard97b58771998-10-20 06:14:16 +00003067 *
3068 * Dump an XML node, recursive behaviour,children are printed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003069 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003070static void
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003071xmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
3072 int format) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003073 int i;
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003074 xmlNodePtr tmp;
Daniel Veillard260a68f1998-08-13 03:39:55 +00003075
3076 if (cur == NULL) {
3077 fprintf(stderr, "xmlNodeDump : node == NULL\n");
3078 return;
3079 }
Daniel Veillard0bef1311998-10-14 02:36:47 +00003080 if (cur->type == XML_TEXT_NODE) {
Daniel Veillard14fff061999-06-22 21:49:07 +00003081 if (cur->content != NULL) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003082 xmlChar *buffer;
Daniel Veillard14fff061999-06-22 21:49:07 +00003083
3084 buffer = xmlEncodeEntitiesReentrant(doc, cur->content);
3085 if (buffer != NULL) {
3086 xmlBufferWriteCHAR(buf, buffer);
Daniel Veillard6454aec1999-09-02 22:04:43 +00003087 xmlFree(buffer);
Daniel Veillard14fff061999-06-22 21:49:07 +00003088 }
3089 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003090 return;
3091 }
Daniel Veillardb96e6431999-08-29 21:02:19 +00003092 if (cur->type == XML_PI_NODE) {
3093 if (cur->content != NULL) {
3094 xmlBufferWriteChar(buf, "<?");
3095 xmlBufferWriteCHAR(buf, cur->name);
3096 if (cur->content != NULL) {
3097 xmlBufferWriteChar(buf, " ");
3098 xmlBufferWriteCHAR(buf, cur->content);
3099 }
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003100 xmlBufferWriteChar(buf, "?>");
Daniel Veillardb96e6431999-08-29 21:02:19 +00003101 }
3102 return;
3103 }
Daniel Veillard0bef1311998-10-14 02:36:47 +00003104 if (cur->type == XML_COMMENT_NODE) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003105 if (cur->content != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003106 xmlBufferWriteChar(buf, "<!--");
3107 xmlBufferWriteCHAR(buf, cur->content);
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003108 xmlBufferWriteChar(buf, "-->");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003109 }
3110 return;
3111 }
Daniel Veillardccb09631998-10-27 06:21:04 +00003112 if (cur->type == XML_ENTITY_REF_NODE) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003113 xmlBufferWriteChar(buf, "&");
3114 xmlBufferWriteCHAR(buf, cur->name);
3115 xmlBufferWriteChar(buf, ";");
Daniel Veillardccb09631998-10-27 06:21:04 +00003116 return;
3117 }
Daniel Veillardb05deb71999-08-10 19:04:08 +00003118 if (cur->type == XML_CDATA_SECTION_NODE) {
3119 xmlBufferWriteChar(buf, "<![CDATA[");
3120 if (cur->content != NULL)
3121 xmlBufferWriteCHAR(buf, cur->content);
3122 xmlBufferWriteChar(buf, "]]>");
3123 return;
3124 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003125
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003126 if (format == 1) {
3127 tmp = cur->childs;
3128 while (tmp != NULL) {
3129 if ((tmp->type == XML_TEXT_NODE) ||
3130 (tmp->type == XML_ENTITY_REF_NODE)) {
3131 format = 0;
3132 break;
3133 }
3134 tmp = tmp->next;
3135 }
3136 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003137 xmlBufferWriteChar(buf, "<");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003138 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003139 xmlBufferWriteCHAR(buf, cur->ns->prefix);
3140 xmlBufferWriteChar(buf, ":");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003141 }
3142
Daniel Veillard5099ae81999-04-21 20:12:07 +00003143 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003144 if (cur->nsDef)
Daniel Veillard5099ae81999-04-21 20:12:07 +00003145 xmlNsListDump(buf, cur->nsDef);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003146 if (cur->properties != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00003147 xmlAttrListDump(buf, doc, cur->properties);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003148
3149 if ((cur->content == NULL) && (cur->childs == NULL)) {
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003150 xmlBufferWriteChar(buf, "/>");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003151 return;
3152 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003153 xmlBufferWriteChar(buf, ">");
Daniel Veillard14fff061999-06-22 21:49:07 +00003154 if (cur->content != NULL) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003155 xmlChar *buffer;
Daniel Veillard14fff061999-06-22 21:49:07 +00003156
3157 buffer = xmlEncodeEntitiesReentrant(doc, cur->content);
3158 if (buffer != NULL) {
3159 xmlBufferWriteCHAR(buf, buffer);
Daniel Veillard6454aec1999-09-02 22:04:43 +00003160 xmlFree(buffer);
Daniel Veillard14fff061999-06-22 21:49:07 +00003161 }
3162 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003163 if (cur->childs != NULL) {
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003164 if (format) xmlBufferWriteChar(buf, "\n");
3165 xmlNodeListDump(buf, doc, cur->childs, level + 1, format);
3166 if ((xmlIndentTreeOutput) && (format))
3167 for (i = 0;i < level;i++)
3168 xmlBufferWriteChar(buf, " ");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003169 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003170 xmlBufferWriteChar(buf, "</");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003171 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003172 xmlBufferWriteCHAR(buf, cur->ns->prefix);
3173 xmlBufferWriteChar(buf, ":");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003174 }
3175
Daniel Veillard5099ae81999-04-21 20:12:07 +00003176 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003177 xmlBufferWriteChar(buf, ">");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003178}
3179
Daniel Veillard97b58771998-10-20 06:14:16 +00003180/**
3181 * xmlDocContentDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003182 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003183 * @cur: the document
3184 *
3185 * Dump an XML document.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003186 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003187static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00003188xmlDocContentDump(xmlBufferPtr buf, xmlDocPtr cur) {
Daniel Veillardbe70ff71999-07-05 16:50:46 +00003189 xmlBufferWriteChar(buf, "<?xml version=");
3190 if (cur->version != NULL)
3191 xmlBufferWriteQuotedString(buf, cur->version);
3192 else
3193 xmlBufferWriteChar(buf, "\"1.0\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003194 if (cur->encoding != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00003195 xmlBufferWriteChar(buf, " encoding=");
3196 xmlBufferWriteQuotedString(buf, cur->encoding);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003197 }
3198 switch (cur->standalone) {
3199 case 0:
Daniel Veillard5099ae81999-04-21 20:12:07 +00003200 xmlBufferWriteChar(buf, " standalone=\"no\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003201 break;
3202 case 1:
Daniel Veillard5099ae81999-04-21 20:12:07 +00003203 xmlBufferWriteChar(buf, " standalone=\"yes\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003204 break;
3205 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003206 xmlBufferWriteChar(buf, "?>\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003207 if (cur->intSubset != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00003208 xmlDtdDump(buf, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003209 if (cur->root != NULL) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00003210 xmlNodePtr child = cur->root;
3211
Daniel Veillard260a68f1998-08-13 03:39:55 +00003212 /* global namespace definitions, the old way */
3213 if (oldXMLWDcompatibility)
Daniel Veillard5099ae81999-04-21 20:12:07 +00003214 xmlGlobalNsListDump(buf, cur->oldNs);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003215 else
3216 xmlUpgradeOldNs(cur);
Daniel Veillardb96e6431999-08-29 21:02:19 +00003217
3218 while (child != NULL) {
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003219 xmlNodeDump(buf, cur, child, 0, 1);
3220 xmlBufferWriteChar(buf, "\n");
Daniel Veillardb96e6431999-08-29 21:02:19 +00003221 child = child->next;
3222 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003223 }
3224}
3225
Daniel Veillard97b58771998-10-20 06:14:16 +00003226/**
3227 * xmlDocDumpMemory:
3228 * @cur: the document
3229 * @mem: OUT: the memory pointer
3230 * @size: OUT: the memory lenght
3231 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003232 * Dump an XML document in memory and return the xmlChar * and it's size.
Daniel Veillard97b58771998-10-20 06:14:16 +00003233 * It's up to the caller to free the memory.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003234 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003235void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003236xmlDocDumpMemory(xmlDocPtr cur, xmlChar**mem, int *size) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003237 xmlBufferPtr buf;
3238
Daniel Veillard260a68f1998-08-13 03:39:55 +00003239 if (cur == NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003240#ifdef DEBUG_TREE
3241 fprintf(stderr, "xmlDocDumpMemory : document == NULL\n");
3242#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00003243 *mem = NULL;
3244 *size = 0;
3245 return;
3246 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003247 buf = xmlBufferCreate();
3248 if (buf == NULL) {
3249 *mem = NULL;
3250 *size = 0;
3251 return;
3252 }
3253 xmlDocContentDump(buf, cur);
Daniel Veillardb05deb71999-08-10 19:04:08 +00003254 *mem = xmlStrndup(buf->content, buf->use);
Daniel Veillard5099ae81999-04-21 20:12:07 +00003255 *size = buf->use;
Daniel Veillardb05deb71999-08-10 19:04:08 +00003256 xmlBufferFree(buf);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003257}
3258
Daniel Veillard97b58771998-10-20 06:14:16 +00003259/**
3260 * xmlGetDocCompressMode:
3261 * @doc: the document
3262 *
3263 * get the compression ratio for a document, ZLIB based
Daniel Veillard1e346af1999-02-22 10:33:01 +00003264 * Returns 0 (uncompressed) to 9 (max compression)
Daniel Veillard151b1b01998-09-23 00:49:46 +00003265 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003266int
3267 xmlGetDocCompressMode (xmlDocPtr doc) {
Daniel Veillard15a8df41998-09-24 19:15:06 +00003268 if (doc == NULL) return(-1);
3269 return(doc->compression);
3270}
3271
Daniel Veillard97b58771998-10-20 06:14:16 +00003272/**
3273 * xmlSetDocCompressMode:
3274 * @doc: the document
3275 * @mode: the compression ratio
3276 *
3277 * set the compression ratio for a document, ZLIB based
3278 * Correct values: 0 (uncompressed) to 9 (max compression)
3279 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003280void
3281xmlSetDocCompressMode (xmlDocPtr doc, int mode) {
Daniel Veillard15a8df41998-09-24 19:15:06 +00003282 if (doc == NULL) return;
3283 if (mode < 0) doc->compression = 0;
3284 else if (mode > 9) doc->compression = 9;
3285 else doc->compression = mode;
3286}
3287
Daniel Veillard97b58771998-10-20 06:14:16 +00003288/**
3289 * xmlGetCompressMode:
3290 *
3291 * get the default compression mode used, ZLIB based.
Daniel Veillard1e346af1999-02-22 10:33:01 +00003292 * Returns 0 (uncompressed) to 9 (max compression)
Daniel Veillard15a8df41998-09-24 19:15:06 +00003293 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003294int
3295 xmlGetCompressMode(void) {
Daniel Veillard151b1b01998-09-23 00:49:46 +00003296 return(xmlCompressMode);
3297}
Daniel Veillard97b58771998-10-20 06:14:16 +00003298
3299/**
3300 * xmlSetCompressMode:
3301 * @mode: the compression ratio
3302 *
3303 * set the default compression mode used, ZLIB based
3304 * Correct values: 0 (uncompressed) to 9 (max compression)
3305 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003306void
3307xmlSetCompressMode(int mode) {
Daniel Veillard151b1b01998-09-23 00:49:46 +00003308 if (mode < 0) xmlCompressMode = 0;
Daniel Veillard15a8df41998-09-24 19:15:06 +00003309 else if (mode > 9) xmlCompressMode = 9;
Daniel Veillard151b1b01998-09-23 00:49:46 +00003310 else xmlCompressMode = mode;
3311}
3312
Daniel Veillard97b58771998-10-20 06:14:16 +00003313/**
3314 * xmlDocDump:
3315 * @f: the FILE*
3316 * @cur: the document
3317 *
3318 * Dump an XML document to an open FILE.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003319 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003320void
3321xmlDocDump(FILE *f, xmlDocPtr cur) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003322 xmlBufferPtr buf;
3323
Daniel Veillard260a68f1998-08-13 03:39:55 +00003324 if (cur == NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003325#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00003326 fprintf(stderr, "xmlDocDump : document == NULL\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003327#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00003328 return;
3329 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003330 buf = xmlBufferCreate();
3331 if (buf == NULL) return;
3332 xmlDocContentDump(buf, cur);
3333 xmlBufferDump(f, buf);
3334 xmlBufferFree(buf);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003335}
3336
Daniel Veillard97b58771998-10-20 06:14:16 +00003337/**
3338 * xmlSaveFile:
3339 * @filename: the filename
3340 * @cur: the document
3341 *
3342 * Dump an XML document to a file. Will use compression if
Daniel Veillard11a48ec1999-11-23 10:40:46 +00003343 * compiled in and enabled. If @filename is "-" the stdout file is
3344 * used.
Daniel Veillard97b58771998-10-20 06:14:16 +00003345 * returns: the number of file written or -1 in case of failure.
Daniel Veillard151b1b01998-09-23 00:49:46 +00003346 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003347int
3348xmlSaveFile(const char *filename, xmlDocPtr cur) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003349 xmlBufferPtr buf;
Daniel Veillard151b1b01998-09-23 00:49:46 +00003350#ifdef HAVE_ZLIB_H
3351 gzFile zoutput = NULL;
3352 char mode[15];
3353#endif
Daniel Veillardccb09631998-10-27 06:21:04 +00003354 FILE *output = NULL;
Daniel Veillard151b1b01998-09-23 00:49:46 +00003355 int ret;
3356
Daniel Veillard5099ae81999-04-21 20:12:07 +00003357 /*
3358 * save the content to a temp buffer.
3359 */
3360 buf = xmlBufferCreate();
3361 if (buf == NULL) return(0);
3362 xmlDocContentDump(buf, cur);
3363
Daniel Veillard151b1b01998-09-23 00:49:46 +00003364#ifdef HAVE_ZLIB_H
Daniel Veillard11a48ec1999-11-23 10:40:46 +00003365 if (cur->compression < 0) cur->compression = xmlCompressMode;
Daniel Veillarddc3dd9d1998-09-24 19:25:54 +00003366 if ((cur->compression > 0) && (cur->compression <= 9)) {
3367 sprintf(mode, "w%d", cur->compression);
Daniel Veillard11a48ec1999-11-23 10:40:46 +00003368 if (!strcmp(filename, "-"))
3369 zoutput = gzdopen(1, mode);
3370 else
3371 zoutput = gzopen(filename, mode);
Daniel Veillard151b1b01998-09-23 00:49:46 +00003372 }
3373 if (zoutput == NULL) {
3374#endif
3375 output = fopen(filename, "w");
3376 if (output == NULL) return(-1);
3377#ifdef HAVE_ZLIB_H
3378 }
Daniel Veillard151b1b01998-09-23 00:49:46 +00003379
Daniel Veillard151b1b01998-09-23 00:49:46 +00003380 if (zoutput != NULL) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003381 ret = gzwrite(zoutput, buf->content, sizeof(xmlChar) * buf->use);
Daniel Veillard151b1b01998-09-23 00:49:46 +00003382 gzclose(zoutput);
Daniel Veillard5099ae81999-04-21 20:12:07 +00003383 } else {
3384#endif
3385 ret = xmlBufferDump(output, buf);
3386 fclose(output);
3387#ifdef HAVE_ZLIB_H
Daniel Veillard151b1b01998-09-23 00:49:46 +00003388 }
3389#endif
Manish Vachharajani5e60f5a1999-05-29 03:04:30 +00003390 xmlBufferFree(buf);
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003391 return(ret * sizeof(xmlChar));
Daniel Veillard151b1b01998-09-23 00:49:46 +00003392}
3393