blob: 4945ed121a833dd1e79e646575026ce714cd13a1 [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
2066 */
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002067const xmlChar *
Daniel Veillardb96e6431999-08-29 21:02:19 +00002068xmlNodeGetLang(xmlNodePtr cur) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002069 const xmlChar *lang;
Daniel Veillardb96e6431999-08-29 21:02:19 +00002070
2071 while (cur != NULL) {
2072 lang = xmlGetProp(cur, BAD_CAST "xml:lang");
2073 if (lang != NULL)
2074 return(lang);
2075 cur = cur->parent;
2076 }
2077 return(NULL);
2078}
2079
2080/**
Daniel Veillard16253641998-10-28 22:58:05 +00002081 * xmlNodeGetContent:
2082 * @cur: the node being read
2083 *
2084 * Read the value of a node, this can be either the text carried
2085 * directly by this node if it's a TEXT node or the aggregate string
2086 * of the values carried by this node child's (TEXT and ENTITY_REF).
2087 * Entity references are substitued.
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002088 * Returns a new xmlChar * or NULL if no content is available.
Daniel Veillard5099ae81999-04-21 20:12:07 +00002089 * It's up to the caller to free the memory.
Daniel Veillard16253641998-10-28 22:58:05 +00002090 */
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002091xmlChar *
Daniel Veillard16253641998-10-28 22:58:05 +00002092xmlNodeGetContent(xmlNodePtr cur) {
2093 if (cur == NULL) return(NULL);
2094 switch (cur->type) {
2095 case XML_DOCUMENT_FRAG_NODE:
2096 case XML_ELEMENT_NODE:
2097 return(xmlNodeListGetString(cur->doc, cur->childs, 1));
2098 break;
Daniel Veillardb96e6431999-08-29 21:02:19 +00002099 case XML_ATTRIBUTE_NODE: {
2100 xmlAttrPtr attr = (xmlAttrPtr) cur;
2101 if (attr->node != NULL)
2102 return(xmlNodeListGetString(attr->node->doc, attr->val, 1));
2103 else
2104 return(xmlNodeListGetString(NULL, attr->val, 1));
2105 break;
2106 }
2107 case XML_PI_NODE:
2108 if (cur->content != NULL)
2109 return(xmlStrdup(cur->content));
2110 return(NULL);
Daniel Veillard16253641998-10-28 22:58:05 +00002111 case XML_ENTITY_REF_NODE:
2112 case XML_ENTITY_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002113 case XML_COMMENT_NODE:
2114 case XML_DOCUMENT_NODE:
Daniel Veillard7c1206f1999-10-14 09:10:25 +00002115 case XML_HTML_DOCUMENT_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002116 case XML_DOCUMENT_TYPE_NODE:
2117 case XML_NOTATION_NODE:
2118 return(NULL);
Daniel Veillardb05deb71999-08-10 19:04:08 +00002119 case XML_CDATA_SECTION_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002120 case XML_TEXT_NODE:
2121 if (cur->content != NULL)
2122 return(xmlStrdup(cur->content));
2123 return(NULL);
2124 }
2125 return(NULL);
2126}
2127
2128/**
Daniel Veillard97b58771998-10-20 06:14:16 +00002129 * xmlNodeSetContent:
2130 * @cur: the node being modified
2131 * @content: the new value of the content
2132 *
2133 * Replace the content of a node.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002134 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002135void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002136xmlNodeSetContent(xmlNodePtr cur, const xmlChar *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002137 if (cur == NULL) {
2138 fprintf(stderr, "xmlNodeSetContent : node == NULL\n");
2139 return;
2140 }
Daniel Veillard16253641998-10-28 22:58:05 +00002141 switch (cur->type) {
2142 case XML_DOCUMENT_FRAG_NODE:
2143 case XML_ELEMENT_NODE:
2144 if (cur->content != NULL) {
Daniel Veillard6454aec1999-09-02 22:04:43 +00002145 xmlFree(cur->content);
Daniel Veillard16253641998-10-28 22:58:05 +00002146 cur->content = NULL;
2147 }
Daniel Veillard6454aec1999-09-02 22:04:43 +00002148 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillard16253641998-10-28 22:58:05 +00002149 cur->childs = xmlStringGetNodeList(cur->doc, content);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002150 UPDATE_LAST_CHILD(cur)
Daniel Veillard16253641998-10-28 22:58:05 +00002151 break;
2152 case XML_ATTRIBUTE_NODE:
2153 break;
2154 case XML_TEXT_NODE:
2155 case XML_CDATA_SECTION_NODE:
2156 case XML_ENTITY_REF_NODE:
2157 case XML_ENTITY_NODE:
2158 case XML_PI_NODE:
2159 case XML_COMMENT_NODE:
Daniel Veillard6454aec1999-09-02 22:04:43 +00002160 if (cur->content != NULL) xmlFree(cur->content);
2161 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002162 cur->last = cur->childs = NULL;
Daniel Veillard16253641998-10-28 22:58:05 +00002163 if (content != NULL)
2164 cur->content = xmlStrdup(content);
2165 else
2166 cur->content = NULL;
Daniel Veillardb96e6431999-08-29 21:02:19 +00002167 break;
Daniel Veillard16253641998-10-28 22:58:05 +00002168 case XML_DOCUMENT_NODE:
Daniel Veillard7c1206f1999-10-14 09:10:25 +00002169 case XML_HTML_DOCUMENT_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002170 case XML_DOCUMENT_TYPE_NODE:
2171 break;
2172 case XML_NOTATION_NODE:
2173 break;
2174 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002175}
2176
Daniel Veillard97b58771998-10-20 06:14:16 +00002177/**
2178 * xmlNodeSetContentLen:
2179 * @cur: the node being modified
2180 * @content: the new value of the content
2181 * @len: the size of @content
2182 *
2183 * Replace the content of a node.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002184 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002185void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002186xmlNodeSetContentLen(xmlNodePtr cur, const xmlChar *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002187 if (cur == NULL) {
Daniel Veillard16253641998-10-28 22:58:05 +00002188 fprintf(stderr, "xmlNodeSetContentLen : node == NULL\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002189 return;
2190 }
Daniel Veillard16253641998-10-28 22:58:05 +00002191 switch (cur->type) {
2192 case XML_DOCUMENT_FRAG_NODE:
2193 case XML_ELEMENT_NODE:
2194 if (cur->content != NULL) {
Daniel Veillard6454aec1999-09-02 22:04:43 +00002195 xmlFree(cur->content);
Daniel Veillard16253641998-10-28 22:58:05 +00002196 cur->content = NULL;
2197 }
Daniel Veillard6454aec1999-09-02 22:04:43 +00002198 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillard16253641998-10-28 22:58:05 +00002199 cur->childs = xmlStringLenGetNodeList(cur->doc, content, len);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002200 UPDATE_LAST_CHILD(cur)
Daniel Veillard16253641998-10-28 22:58:05 +00002201 break;
2202 case XML_ATTRIBUTE_NODE:
2203 break;
2204 case XML_TEXT_NODE:
2205 case XML_CDATA_SECTION_NODE:
2206 case XML_ENTITY_REF_NODE:
2207 case XML_ENTITY_NODE:
2208 case XML_PI_NODE:
2209 case XML_COMMENT_NODE:
Daniel Veillard6454aec1999-09-02 22:04:43 +00002210 if (cur->content != NULL) xmlFree(cur->content);
2211 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002212 cur->childs = cur->last = NULL;
Daniel Veillard16253641998-10-28 22:58:05 +00002213 if (content != NULL)
2214 cur->content = xmlStrndup(content, len);
2215 else
2216 cur->content = NULL;
Daniel Veillardb96e6431999-08-29 21:02:19 +00002217 break;
Daniel Veillard16253641998-10-28 22:58:05 +00002218 case XML_DOCUMENT_NODE:
Daniel Veillard7c1206f1999-10-14 09:10:25 +00002219 case XML_HTML_DOCUMENT_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002220 case XML_DOCUMENT_TYPE_NODE:
2221 break;
2222 case XML_NOTATION_NODE:
Daniel Veillard6454aec1999-09-02 22:04:43 +00002223 if (cur->content != NULL) xmlFree(cur->content);
2224 if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002225 cur->childs = cur->last = NULL;
Daniel Veillard16253641998-10-28 22:58:05 +00002226 if (content != NULL)
2227 cur->content = xmlStrndup(content, len);
2228 else
2229 cur->content = NULL;
2230 break;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002231 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002232}
2233
Daniel Veillard97b58771998-10-20 06:14:16 +00002234/**
2235 * xmlNodeAddContentLen:
2236 * @cur: the node being modified
2237 * @content: extra content
2238 * @len: the size of @content
2239 *
2240 * Append the extra substring to the node content.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002241 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002242void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002243xmlNodeAddContentLen(xmlNodePtr cur, const xmlChar *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002244 if (cur == NULL) {
Daniel Veillard16253641998-10-28 22:58:05 +00002245 fprintf(stderr, "xmlNodeAddContentLen : node == NULL\n");
2246 return;
2247 }
2248 if (len <= 0) return;
2249 switch (cur->type) {
2250 case XML_DOCUMENT_FRAG_NODE:
2251 case XML_ELEMENT_NODE: {
2252 xmlNodePtr last = NULL, new;
2253
2254 if (cur->childs != NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002255 last = cur->last;
Daniel Veillard16253641998-10-28 22:58:05 +00002256 } else {
2257 if (cur->content != NULL) {
2258 cur->childs = xmlStringGetNodeList(cur->doc, cur->content);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002259 UPDATE_LAST_CHILD(cur)
Daniel Veillard6454aec1999-09-02 22:04:43 +00002260 xmlFree(cur->content);
Daniel Veillard16253641998-10-28 22:58:05 +00002261 cur->content = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002262 last = cur->last;
Daniel Veillard16253641998-10-28 22:58:05 +00002263 }
2264 }
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002265 new = xmlNewTextLen(content, len);
Daniel Veillard16253641998-10-28 22:58:05 +00002266 if (new != NULL) {
2267 xmlAddChild(cur, new);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002268 if ((last != NULL) && (last->next == new)) {
Daniel Veillard16253641998-10-28 22:58:05 +00002269 xmlTextMerge(last, new);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002270 }
Daniel Veillard16253641998-10-28 22:58:05 +00002271 }
2272 break;
2273 }
2274 case XML_ATTRIBUTE_NODE:
2275 break;
2276 case XML_TEXT_NODE:
2277 case XML_CDATA_SECTION_NODE:
2278 case XML_ENTITY_REF_NODE:
2279 case XML_ENTITY_NODE:
2280 case XML_PI_NODE:
2281 case XML_COMMENT_NODE:
2282 if (content != NULL)
2283 cur->content = xmlStrncat(cur->content, content, len);
2284 case XML_DOCUMENT_NODE:
Daniel Veillard7c1206f1999-10-14 09:10:25 +00002285 case XML_HTML_DOCUMENT_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002286 case XML_DOCUMENT_TYPE_NODE:
2287 break;
2288 case XML_NOTATION_NODE:
2289 if (content != NULL)
2290 cur->content = xmlStrncat(cur->content, content, len);
2291 break;
2292 }
2293}
2294
2295/**
2296 * xmlNodeAddContent:
2297 * @cur: the node being modified
2298 * @content: extra content
2299 *
2300 * Append the extra substring to the node content.
2301 */
2302void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002303xmlNodeAddContent(xmlNodePtr cur, const xmlChar *content) {
Daniel Veillard16253641998-10-28 22:58:05 +00002304 int len;
2305
2306 if (cur == NULL) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002307 fprintf(stderr, "xmlNodeAddContent : node == NULL\n");
2308 return;
2309 }
Daniel Veillard16253641998-10-28 22:58:05 +00002310 if (content == NULL) return;
2311 len = xmlStrlen(content);
2312 xmlNodeAddContentLen(cur, content, len);
2313}
2314
2315/**
2316 * xmlTextMerge:
2317 * @first: the first text node
2318 * @second: the second text node being merged
2319 *
2320 * Merge two text nodes into one
Daniel Veillard1e346af1999-02-22 10:33:01 +00002321 * Returns the first text node augmented
Daniel Veillard16253641998-10-28 22:58:05 +00002322 */
2323xmlNodePtr
2324xmlTextMerge(xmlNodePtr first, xmlNodePtr second) {
2325 if (first == NULL) return(second);
2326 if (second == NULL) return(first);
2327 if (first->type != XML_TEXT_NODE) return(first);
2328 if (second->type != XML_TEXT_NODE) return(first);
2329 xmlNodeAddContent(first, second->content);
2330 xmlUnlinkNode(second);
2331 xmlFreeNode(second);
2332 return(first);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002333}
2334
Daniel Veillard97b58771998-10-20 06:14:16 +00002335/**
Daniel Veillardb96e6431999-08-29 21:02:19 +00002336 * xmlGetNsList:
2337 * @doc: the document
2338 * @node: the current node
2339 *
2340 * Search all the namespace applying to a given element.
2341 * Returns an NULL terminated array of all the xmlNsPtr found
2342 * that need to be freed by the caller or NULL if no
2343 * namespace if defined
2344 */
2345xmlNsPtr *
2346xmlGetNsList(xmlDocPtr doc, xmlNodePtr node) {
2347 xmlNsPtr cur;
2348 xmlNsPtr *ret = NULL;
2349 int nbns = 0;
2350 int maxns = 10;
2351 int i;
2352
2353 while (node != NULL) {
2354 cur = node->nsDef;
2355 while (cur != NULL) {
2356 if (ret == NULL) {
Daniel Veillard6454aec1999-09-02 22:04:43 +00002357 ret = (xmlNsPtr *) xmlMalloc((maxns + 1) * sizeof(xmlNsPtr));
Daniel Veillardb96e6431999-08-29 21:02:19 +00002358 if (ret == NULL) {
2359 fprintf(stderr, "xmlGetNsList : out of memory!\n");
2360 return(NULL);
2361 }
2362 ret[nbns] = NULL;
2363 }
2364 for (i = 0;i < nbns;i++) {
2365 if ((cur->prefix == ret[i]->prefix) ||
2366 (!xmlStrcmp(cur->prefix, ret[i]->prefix))) break;
2367 }
2368 if (i >= nbns) {
2369 if (nbns >= maxns) {
2370 maxns *= 2;
Daniel Veillard6454aec1999-09-02 22:04:43 +00002371 ret = (xmlNsPtr *) xmlRealloc(ret,
Daniel Veillardb96e6431999-08-29 21:02:19 +00002372 (maxns + 1) * sizeof(xmlNsPtr));
2373 if (ret == NULL) {
2374 fprintf(stderr, "xmlGetNsList : realloc failed!\n");
2375 return(NULL);
2376 }
2377 }
2378 ret[nbns++] = cur;
2379 ret[nbns] = NULL;
2380 }
2381
2382 cur = cur->next;
2383 }
2384 node = node->parent;
2385 }
2386 return(ret);
2387}
2388
2389/**
Daniel Veillard97b58771998-10-20 06:14:16 +00002390 * xmlSearchNs:
2391 * @doc: the document
2392 * @node: the current node
2393 * @nameSpace: the namespace string
Daniel Veillard260a68f1998-08-13 03:39:55 +00002394 *
Daniel Veillard97b58771998-10-20 06:14:16 +00002395 * Search a Ns registered under a given name space for a document.
2396 * recurse on the parents until it finds the defined namespace
2397 * or return NULL otherwise.
2398 * @nameSpace can be NULL, this is a search for the default namespace.
Daniel Veillard1e346af1999-02-22 10:33:01 +00002399 * Returns the namespace pointer or NULL.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002400 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002401xmlNsPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002402xmlSearchNs(xmlDocPtr doc, xmlNodePtr node, const xmlChar *nameSpace) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002403 xmlNsPtr cur;
2404
2405 while (node != NULL) {
2406 cur = node->nsDef;
2407 while (cur != NULL) {
2408 if ((cur->prefix == NULL) && (nameSpace == NULL))
2409 return(cur);
2410 if ((cur->prefix != NULL) && (nameSpace != NULL) &&
2411 (!xmlStrcmp(cur->prefix, nameSpace)))
2412 return(cur);
2413 cur = cur->next;
2414 }
2415 node = node->parent;
2416 }
2417 if (doc != NULL) {
2418 cur = doc->oldNs;
2419 while (cur != NULL) {
2420 if ((cur->prefix != NULL) && (nameSpace != NULL) &&
2421 (!xmlStrcmp(cur->prefix, nameSpace)))
2422 return(cur);
2423 cur = cur->next;
2424 }
2425 }
2426 return(NULL);
2427}
2428
Daniel Veillard97b58771998-10-20 06:14:16 +00002429/**
2430 * xmlSearchNsByHref:
2431 * @doc: the document
2432 * @node: the current node
2433 * @href: the namespace value
2434 *
2435 * Search a Ns aliasing a given URI. Recurse on the parents until it finds
2436 * the defined namespace or return NULL otherwise.
Daniel Veillard1e346af1999-02-22 10:33:01 +00002437 * Returns the namespace pointer or NULL.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002438 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002439xmlNsPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002440xmlSearchNsByHref(xmlDocPtr doc, xmlNodePtr node, const xmlChar *href) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002441 xmlNsPtr cur;
2442
2443 while (node != NULL) {
2444 cur = node->nsDef;
2445 while (cur != NULL) {
2446 if ((cur->href != NULL) && (href != NULL) &&
2447 (!xmlStrcmp(cur->href, href)))
2448 return(cur);
2449 cur = cur->next;
2450 }
2451 node = node->parent;
2452 }
2453 if (doc != NULL) {
2454 cur = doc->oldNs;
2455 while (cur != NULL) {
2456 if ((cur->href != NULL) && (href != NULL) &&
2457 (!xmlStrcmp(cur->href, href)))
2458 return(cur);
2459 cur = cur->next;
2460 }
2461 }
2462 return(NULL);
2463}
2464
Daniel Veillard97b58771998-10-20 06:14:16 +00002465/**
2466 * xmlGetProp:
2467 * @node: the node
2468 * @name: the attribute name
2469 *
2470 * Search and get the value of an attribute associated to a node
Daniel Veillardccb09631998-10-27 06:21:04 +00002471 * This does the entity substitution.
Daniel Veillard1e346af1999-02-22 10:33:01 +00002472 * Returns the attribute value or NULL if not found.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002473 */
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002474xmlChar *xmlGetProp(xmlNodePtr node, const xmlChar *name) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002475 xmlAttrPtr prop = node->properties;
2476
2477 while (prop != NULL) {
Daniel Veillard68178931999-02-08 18:34:36 +00002478 if (!xmlStrcmp(prop->name, name)) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002479 xmlChar *ret;
Daniel Veillard6800ef31999-02-08 18:33:22 +00002480
2481 ret = xmlNodeListGetString(node->doc, prop->val, 1);
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002482 if (ret == NULL) return(xmlStrdup((xmlChar *)""));
Daniel Veillard6800ef31999-02-08 18:33:22 +00002483 return(ret);
Daniel Veillard68178931999-02-08 18:34:36 +00002484 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002485 prop = prop->next;
2486 }
2487 return(NULL);
2488}
2489
Daniel Veillard97b58771998-10-20 06:14:16 +00002490/**
Daniel Veillardccb09631998-10-27 06:21:04 +00002491 * xmlSetProp:
Daniel Veillard97b58771998-10-20 06:14:16 +00002492 * @node: the node
2493 * @name: the attribute name
2494 * @value: the attribute value
2495 *
2496 * Set (or reset) an attribute carried by a node.
Daniel Veillard1e346af1999-02-22 10:33:01 +00002497 * Returns the attribute pointer.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002498 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002499xmlAttrPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002500xmlSetProp(xmlNodePtr node, const xmlChar *name, const xmlChar *value) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002501 xmlAttrPtr prop = node->properties;
2502
2503 while (prop != NULL) {
2504 if (!xmlStrcmp(prop->name, name)) {
Daniel Veillardccb09631998-10-27 06:21:04 +00002505 if (prop->val != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +00002506 xmlFreeNodeList(prop->val);
Daniel Veillardccb09631998-10-27 06:21:04 +00002507 prop->val = NULL;
Daniel Veillard51e3b151999-11-12 17:02:31 +00002508 if (value != NULL) {
2509 xmlChar *buffer;
2510 buffer = xmlEncodeEntitiesReentrant(node->doc, value);
2511 prop->val = xmlStringGetNodeList(node->doc, buffer);
2512 xmlFree(buffer);
2513 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002514 return(prop);
2515 }
2516 prop = prop->next;
2517 }
2518 prop = xmlNewProp(node, name, value);
2519 return(prop);
2520}
2521
Daniel Veillard97b58771998-10-20 06:14:16 +00002522/**
2523 * xmlNodeIsText:
2524 * @node: the node
2525 *
2526 * Is this node a Text node ?
Daniel Veillard1e346af1999-02-22 10:33:01 +00002527 * Returns 1 yes, 0 no
Daniel Veillard260a68f1998-08-13 03:39:55 +00002528 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002529int
2530xmlNodeIsText(xmlNodePtr node) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002531 if (node == NULL) return(0);
2532
Daniel Veillard0bef1311998-10-14 02:36:47 +00002533 if (node->type == XML_TEXT_NODE) return(1);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002534 return(0);
2535}
2536
Daniel Veillard97b58771998-10-20 06:14:16 +00002537/**
Daniel Veillard1e346af1999-02-22 10:33:01 +00002538 * xmlTextConcat:
Daniel Veillard97b58771998-10-20 06:14:16 +00002539 * @node: the node
2540 * @content: the content
2541 * @len: @content lenght
2542 *
2543 * Concat the given string at the end of the existing node content
Daniel Veillard260a68f1998-08-13 03:39:55 +00002544 */
Daniel Veillard97b58771998-10-20 06:14:16 +00002545
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002546void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002547xmlTextConcat(xmlNodePtr node, const xmlChar *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002548 if (node == NULL) return;
2549
Daniel Veillard0bef1311998-10-14 02:36:47 +00002550 if (node->type != XML_TEXT_NODE) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002551 fprintf(stderr, "xmlTextConcat: node is not text\n");
2552 return;
2553 }
2554 node->content = xmlStrncat(node->content, content, len);
2555}
2556
2557/************************************************************************
2558 * *
2559 * Output : to a FILE or in memory *
2560 * *
2561 ************************************************************************/
2562
Daniel Veillard5099ae81999-04-21 20:12:07 +00002563#define BASE_BUFFER_SIZE 4000
2564
2565/**
2566 * xmlBufferCreate:
2567 *
2568 * routine to create an XML buffer.
2569 * returns the new structure.
2570 */
2571xmlBufferPtr
2572xmlBufferCreate(void) {
2573 xmlBufferPtr ret;
2574
Daniel Veillard6454aec1999-09-02 22:04:43 +00002575 ret = (xmlBufferPtr) xmlMalloc(sizeof(xmlBuffer));
Daniel Veillard5099ae81999-04-21 20:12:07 +00002576 if (ret == NULL) {
2577 fprintf(stderr, "xmlBufferCreate : out of memory!\n");
2578 return(NULL);
2579 }
2580 ret->use = 0;
2581 ret->size = BASE_BUFFER_SIZE;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002582 ret->content = (xmlChar *) xmlMalloc(ret->size * sizeof(xmlChar));
Daniel Veillard5099ae81999-04-21 20:12:07 +00002583 if (ret->content == NULL) {
2584 fprintf(stderr, "xmlBufferCreate : out of memory!\n");
Daniel Veillard6454aec1999-09-02 22:04:43 +00002585 xmlFree(ret);
Daniel Veillard5099ae81999-04-21 20:12:07 +00002586 return(NULL);
2587 }
2588 ret->content[0] = 0;
2589 return(ret);
2590}
2591
2592/**
2593 * xmlBufferFree:
2594 * @buf: the buffer to free
2595 *
2596 * Frees an XML buffer.
2597 */
2598void
2599xmlBufferFree(xmlBufferPtr buf) {
2600 if (buf == NULL) {
2601 fprintf(stderr, "xmlBufferFree: buf == NULL\n");
2602 return;
2603 }
2604 if (buf->content == NULL) {
2605 fprintf(stderr, "xmlBufferFree: buf->content == NULL\n");
2606 } else {
2607 memset(buf->content, -1, BASE_BUFFER_SIZE);
Daniel Veillard6454aec1999-09-02 22:04:43 +00002608 xmlFree(buf->content);
Daniel Veillard5099ae81999-04-21 20:12:07 +00002609 }
2610 memset(buf, -1, sizeof(xmlBuffer));
Daniel Veillard6454aec1999-09-02 22:04:43 +00002611 xmlFree(buf);
Daniel Veillard5099ae81999-04-21 20:12:07 +00002612}
2613
2614/**
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002615 * xmlBufferEmpty:
2616 * @buf: the buffer
2617 *
2618 * empty a buffer.
2619 */
2620void
2621xmlBufferEmpty(xmlBufferPtr buf) {
2622 buf->use = 0;
2623 memset(buf->content, -1, buf->size);/* just for debug */
2624}
2625
2626/**
2627 * xmlBufferShrink:
2628 * @buf: the buffer to dump
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002629 * @len: the number of xmlChar to remove
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002630 *
2631 * Remove the beginning of an XML buffer.
2632 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002633 * Returns the number of xmlChar removed, or -1 in case of failure.
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002634 */
2635int
2636xmlBufferShrink(xmlBufferPtr buf, int len) {
2637 if (len == 0) return(0);
2638 if (len > buf->use) return(-1);
2639
2640 buf->use -= len;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002641 memmove(buf->content, &buf->content[len], buf->use * sizeof(xmlChar));
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002642
2643 buf->content[buf->use] = 0;
2644 return(len);
2645}
2646
2647/**
Daniel Veillard5099ae81999-04-21 20:12:07 +00002648 * xmlBufferDump:
2649 * @file: the file output
2650 * @buf: the buffer to dump
2651 *
2652 * Dumps an XML buffer to a FILE *.
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002653 * Returns the number of xmlChar written
Daniel Veillard5099ae81999-04-21 20:12:07 +00002654 */
2655int
2656xmlBufferDump(FILE *file, xmlBufferPtr buf) {
2657 int ret;
2658
2659 if (buf == NULL) {
2660 fprintf(stderr, "xmlBufferDump: buf == NULL\n");
2661 return(0);
2662 }
2663 if (buf->content == NULL) {
2664 fprintf(stderr, "xmlBufferDump: buf->content == NULL\n");
2665 return(0);
2666 }
2667 if (file == NULL) file = stdout;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002668 ret = fwrite(buf->content, sizeof(xmlChar), buf->use, file);
Daniel Veillard5099ae81999-04-21 20:12:07 +00002669 return(ret);
2670}
2671
2672/**
2673 * xmlBufferAdd:
2674 * @buf: the buffer to dump
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002675 * @str: the xmlChar string
2676 * @len: the number of xmlChar to add
Daniel Veillard5099ae81999-04-21 20:12:07 +00002677 *
2678 * Add a string range to an XML buffer.
2679 */
2680void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002681xmlBufferAdd(xmlBufferPtr buf, const xmlChar *str, int len) {
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002682 int l;
Daniel Veillard5099ae81999-04-21 20:12:07 +00002683
2684 if (str == NULL) {
2685 fprintf(stderr, "xmlBufferAdd: str == NULL\n");
2686 return;
2687 }
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002688 l = xmlStrlen(str);
2689 if (l < len) len = l;
2690 if (len <= 0) return;
Daniel Veillard5099ae81999-04-21 20:12:07 +00002691
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002692 if (buf->use + len + 10 >= buf->size) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002693 xmlChar *rebuf;
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002694
2695 buf->size *= 2;
2696 if (buf->use + len + 10 > buf->size)
2697 buf->size = buf->use + len + 10;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002698 rebuf = (xmlChar *) xmlRealloc(buf->content, buf->size * sizeof(xmlChar));
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002699 if (rebuf == NULL) {
2700 fprintf(stderr, "xmlBufferAdd : out of memory!\n");
2701 return;
Daniel Veillard5099ae81999-04-21 20:12:07 +00002702 }
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002703 buf->content = rebuf;
Daniel Veillard5099ae81999-04-21 20:12:07 +00002704 }
Daniel Veillarde2d034d1999-07-27 19:52:06 +00002705 memmove(&buf->content[buf->use], str, len);
2706 buf->use += len;
2707 buf->content[buf->use] = 0;
Daniel Veillard5099ae81999-04-21 20:12:07 +00002708}
2709
2710/**
2711 * xmlBufferCat:
2712 * @buf: the buffer to dump
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002713 * @str: the xmlChar string
Daniel Veillard5099ae81999-04-21 20:12:07 +00002714 *
2715 * Append a zero terminated string to an XML buffer.
2716 */
2717void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002718xmlBufferCat(xmlBufferPtr buf, const xmlChar *str) {
2719 const xmlChar *cur;
Daniel Veillard5099ae81999-04-21 20:12:07 +00002720
2721 if (str == NULL) {
2722 fprintf(stderr, "xmlBufferAdd: str == NULL\n");
2723 return;
2724 }
2725 for (cur = str;*cur != 0;cur++) {
2726 if (buf->use + 10 >= buf->size) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002727 xmlChar *rebuf;
Daniel Veillard5099ae81999-04-21 20:12:07 +00002728
2729 buf->size *= 2;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002730 rebuf = (xmlChar *) xmlRealloc(buf->content, buf->size * sizeof(xmlChar));
Daniel Veillard5099ae81999-04-21 20:12:07 +00002731 if (rebuf == NULL) {
2732 fprintf(stderr, "xmlBufferAdd : out of memory!\n");
2733 return;
2734 }
2735 buf->content = rebuf;
2736 }
2737 buf->content[buf->use++] = *cur;
2738 }
2739}
2740
2741/**
2742 * xmlBufferCCat:
2743 * @buf: the buffer to dump
2744 * @str: the C char string
2745 *
2746 * Append a zero terminated C string to an XML buffer.
2747 */
2748void
2749xmlBufferCCat(xmlBufferPtr buf, const char *str) {
2750 const char *cur;
2751
2752 if (str == NULL) {
2753 fprintf(stderr, "xmlBufferAdd: str == NULL\n");
2754 return;
2755 }
2756 for (cur = str;*cur != 0;cur++) {
2757 if (buf->use + 10 >= buf->size) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002758 xmlChar *rebuf;
Daniel Veillard5099ae81999-04-21 20:12:07 +00002759
2760 buf->size *= 2;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002761 rebuf = (xmlChar *) xmlRealloc(buf->content, buf->size * sizeof(xmlChar));
Daniel Veillard5099ae81999-04-21 20:12:07 +00002762 if (rebuf == NULL) {
2763 fprintf(stderr, "xmlBufferAdd : out of memory!\n");
2764 return;
2765 }
2766 buf->content = rebuf;
2767 }
2768 buf->content[buf->use++] = *cur;
2769 }
2770}
Daniel Veillard260a68f1998-08-13 03:39:55 +00002771
Daniel Veillard97b58771998-10-20 06:14:16 +00002772/**
Daniel Veillard7d2c2761999-10-11 15:09:51 +00002773 * xmlBufferLastChar:
2774 * @buf: the buffer to dump
2775 *
2776 * Get the last char of the buffer
2777 *
2778 * Returns the last char from the buffer or 0 if empty
2779 */
2780xmlChar
2781xmlBufferLastChar(xmlBufferPtr buf) {
2782 if ((buf == NULL) || (buf->use <= 0)) return(0);
2783 return(buf->content[buf->use - 1]);
2784}
2785
2786/**
Daniel Veillard97b58771998-10-20 06:14:16 +00002787 * xmlBufferWriteCHAR:
Daniel Veillard5099ae81999-04-21 20:12:07 +00002788 * @buf: the XML buffer
Daniel Veillard97b58771998-10-20 06:14:16 +00002789 * @string: the string to add
2790 *
2791 * routine which manage and grows an output buffer. This one add
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002792 * xmlChars at the end of the buffer.
Daniel Veillard97b58771998-10-20 06:14:16 +00002793 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002794void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002795xmlBufferWriteCHAR(xmlBufferPtr buf, const xmlChar *string) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002796 xmlBufferCat(buf, string);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002797}
2798
Daniel Veillard97b58771998-10-20 06:14:16 +00002799/**
2800 * xmlBufferWriteChar:
Daniel Veillard011b63c1999-06-02 17:44:04 +00002801 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00002802 * @string: the string to add
2803 *
2804 * routine which manage and grows an output buffer. This one add
2805 * C chars at the end of the array.
2806 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002807void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002808xmlBufferWriteChar(xmlBufferPtr buf, const char *string) {
2809 xmlBufferCCat(buf, string);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002810}
2811
Daniel Veillard5099ae81999-04-21 20:12:07 +00002812
Daniel Veillard97b58771998-10-20 06:14:16 +00002813/**
Daniel Veillard011b63c1999-06-02 17:44:04 +00002814 * xmlBufferWriteQuotedString:
2815 * @buf: the XML buffer output
2816 * @string: the string to add
2817 *
2818 * routine which manage and grows an output buffer. This one writes
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002819 * a quoted or double quoted xmlChar string, checking first if it holds
Daniel Veillard011b63c1999-06-02 17:44:04 +00002820 * quote or double-quotes internally
2821 */
2822void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002823xmlBufferWriteQuotedString(xmlBufferPtr buf, const xmlChar *string) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00002824 if (xmlStrchr(string, '"')) {
2825 if (xmlStrchr(string, '\'')) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00002826 fprintf(stderr,
2827 "xmlBufferWriteQuotedString: string contains quote and double-quotes !\n");
2828 }
2829 xmlBufferCCat(buf, "'");
2830 xmlBufferCat(buf, string);
2831 xmlBufferCCat(buf, "'");
2832 } else {
2833 xmlBufferCCat(buf, "\"");
2834 xmlBufferCat(buf, string);
2835 xmlBufferCCat(buf, "\"");
2836 }
2837}
2838
2839
2840/**
Daniel Veillard97b58771998-10-20 06:14:16 +00002841 * xmlGlobalNsDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00002842 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00002843 * @cur: a namespace
2844 *
2845 * Dump a global Namespace, this is the old version based on PIs.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002846 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002847static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002848xmlGlobalNsDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002849 if (cur == NULL) {
2850 fprintf(stderr, "xmlGlobalNsDump : Ns == NULL\n");
2851 return;
2852 }
2853 if (cur->type == XML_GLOBAL_NAMESPACE) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002854 xmlBufferWriteChar(buf, "<?namespace");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002855 if (cur->href != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00002856 xmlBufferWriteChar(buf, " href=");
2857 xmlBufferWriteQuotedString(buf, cur->href);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002858 }
2859 if (cur->prefix != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00002860 xmlBufferWriteChar(buf, " AS=");
2861 xmlBufferWriteQuotedString(buf, cur->prefix);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002862 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00002863 xmlBufferWriteChar(buf, "?>\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002864 }
2865}
2866
Daniel Veillard97b58771998-10-20 06:14:16 +00002867/**
2868 * xmlGlobalNsListDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00002869 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00002870 * @cur: the first namespace
2871 *
2872 * Dump a list of global Namespace, this is the old version based on PIs.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002873 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002874static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002875xmlGlobalNsListDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002876 while (cur != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002877 xmlGlobalNsDump(buf, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002878 cur = cur->next;
2879 }
2880}
2881
Daniel Veillard97b58771998-10-20 06:14:16 +00002882/**
2883 * xmlNsDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00002884 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00002885 * @cur: a namespace
2886 *
Daniel Veillard260a68f1998-08-13 03:39:55 +00002887 * Dump a local Namespace definition.
Daniel Veillard97b58771998-10-20 06:14:16 +00002888 * Should be called in the context of attributes dumps.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002889 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002890static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002891xmlNsDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002892 if (cur == NULL) {
2893 fprintf(stderr, "xmlNsDump : Ns == NULL\n");
2894 return;
2895 }
2896 if (cur->type == XML_LOCAL_NAMESPACE) {
2897 /* Within the context of an element attributes */
2898 if (cur->prefix != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002899 xmlBufferWriteChar(buf, " xmlns:");
2900 xmlBufferWriteCHAR(buf, cur->prefix);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002901 } else
Daniel Veillard5099ae81999-04-21 20:12:07 +00002902 xmlBufferWriteChar(buf, " xmlns");
Daniel Veillard011b63c1999-06-02 17:44:04 +00002903 xmlBufferWriteChar(buf, "=");
2904 xmlBufferWriteQuotedString(buf, cur->href);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002905 }
2906}
2907
Daniel Veillard97b58771998-10-20 06:14:16 +00002908/**
2909 * xmlNsListDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00002910 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00002911 * @cur: the first namespace
2912 *
2913 * Dump a list of local Namespace definitions.
2914 * Should be called in the context of attributes dumps.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002915 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002916static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002917xmlNsListDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002918 while (cur != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002919 xmlNsDump(buf, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002920 cur = cur->next;
2921 }
2922}
2923
Daniel Veillard97b58771998-10-20 06:14:16 +00002924/**
2925 * xmlDtdDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00002926 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00002927 * @doc: the document
2928 *
2929 * Dump the XML document DTD, if any.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002930 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002931static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002932xmlDtdDump(xmlBufferPtr buf, xmlDocPtr doc) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002933 xmlDtdPtr cur = doc->intSubset;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002934
2935 if (cur == NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002936 fprintf(stderr, "xmlDtdDump : no internal subset\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002937 return;
2938 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00002939 xmlBufferWriteChar(buf, "<!DOCTYPE ");
2940 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002941 if (cur->ExternalID != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00002942 xmlBufferWriteChar(buf, " PUBLIC ");
2943 xmlBufferWriteQuotedString(buf, cur->ExternalID);
2944 xmlBufferWriteChar(buf, " ");
2945 xmlBufferWriteQuotedString(buf, cur->SystemID);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002946 } else if (cur->SystemID != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00002947 xmlBufferWriteChar(buf, " SYSTEM ");
2948 xmlBufferWriteQuotedString(buf, cur->SystemID);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002949 }
Daniel Veillard1e346af1999-02-22 10:33:01 +00002950 if ((cur->entities == NULL) && (cur->elements == NULL) &&
2951 (cur->attributes == NULL) && (cur->notations == NULL)) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002952 xmlBufferWriteChar(buf, ">\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002953 return;
2954 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00002955 xmlBufferWriteChar(buf, " [\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002956 if (cur->entities != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00002957 xmlDumpEntitiesTable(buf, (xmlEntitiesTablePtr) cur->entities);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002958 if (cur->notations != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00002959 xmlDumpNotationTable(buf, (xmlNotationTablePtr) cur->notations);
Daniel Veillard3b9def11999-01-31 22:15:06 +00002960 if (cur->elements != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00002961 xmlDumpElementTable(buf, (xmlElementTablePtr) cur->elements);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002962 if (cur->attributes != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00002963 xmlDumpAttributeTable(buf, (xmlAttributeTablePtr) cur->attributes);
2964 xmlBufferWriteChar(buf, "]");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002965
Daniel Veillard5099ae81999-04-21 20:12:07 +00002966 xmlBufferWriteChar(buf, ">\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002967}
2968
Daniel Veillard97b58771998-10-20 06:14:16 +00002969/**
2970 * xmlAttrDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00002971 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00002972 * @doc: the document
2973 * @cur: the attribute pointer
2974 *
2975 * Dump an XML attribute
Daniel Veillard260a68f1998-08-13 03:39:55 +00002976 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002977static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00002978xmlAttrDump(xmlBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002979 xmlChar *value;
Daniel Veillardccb09631998-10-27 06:21:04 +00002980
Daniel Veillard260a68f1998-08-13 03:39:55 +00002981 if (cur == NULL) {
2982 fprintf(stderr, "xmlAttrDump : property == NULL\n");
2983 return;
2984 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00002985 xmlBufferWriteChar(buf, " ");
Daniel Veillardb96e6431999-08-29 21:02:19 +00002986 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
2987 xmlBufferWriteCHAR(buf, cur->ns->prefix);
2988 xmlBufferWriteChar(buf, ":");
2989 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00002990 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillardccb09631998-10-27 06:21:04 +00002991 value = xmlNodeListGetString(doc, cur->val, 0);
2992 if (value) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00002993 xmlBufferWriteChar(buf, "=");
2994 xmlBufferWriteQuotedString(buf, value);
Daniel Veillard6454aec1999-09-02 22:04:43 +00002995 xmlFree(value);
Daniel Veillard726c7e31999-02-08 15:13:10 +00002996 } else {
Daniel Veillard5099ae81999-04-21 20:12:07 +00002997 xmlBufferWriteChar(buf, "=\"\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00002998 }
2999}
3000
Daniel Veillard97b58771998-10-20 06:14:16 +00003001/**
3002 * xmlAttrListDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003003 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003004 * @doc: the document
3005 * @cur: the first attribute pointer
3006 *
3007 * Dump a list of XML attributes
Daniel Veillard260a68f1998-08-13 03:39:55 +00003008 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003009static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00003010xmlAttrListDump(xmlBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003011 if (cur == NULL) {
3012 fprintf(stderr, "xmlAttrListDump : property == NULL\n");
3013 return;
3014 }
3015 while (cur != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003016 xmlAttrDump(buf, doc, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003017 cur = cur->next;
3018 }
3019}
3020
Daniel Veillard260a68f1998-08-13 03:39:55 +00003021
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003022static void
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003023xmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
3024 int format);
Daniel Veillard97b58771998-10-20 06:14:16 +00003025/**
3026 * xmlNodeListDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003027 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003028 * @doc: the document
3029 * @cur: the first node
3030 * @level: the imbrication level for indenting
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003031 * @format: is formatting allowed
Daniel Veillard97b58771998-10-20 06:14:16 +00003032 *
3033 * Dump an XML node list, recursive behaviour,children are printed too.
3034 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003035static void
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003036xmlNodeListDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
3037 int format) {
3038 int i;
Daniel Veillardccb09631998-10-27 06:21:04 +00003039
Daniel Veillard260a68f1998-08-13 03:39:55 +00003040 if (cur == NULL) {
3041 fprintf(stderr, "xmlNodeListDump : node == NULL\n");
3042 return;
3043 }
3044 while (cur != NULL) {
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003045 if ((format) && (xmlIndentTreeOutput) &&
3046 (cur->type == XML_ELEMENT_NODE))
3047 for (i = 0;i < level;i++)
3048 xmlBufferWriteChar(buf, " ");
3049 xmlNodeDump(buf, doc, cur, level, format);
3050 if (format) {
3051 xmlBufferWriteChar(buf, "\n");
Daniel Veillardccb09631998-10-27 06:21:04 +00003052 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003053 cur = cur->next;
3054 }
3055}
3056
Daniel Veillard97b58771998-10-20 06:14:16 +00003057/**
Daniel Veillardccb09631998-10-27 06:21:04 +00003058 * xmlNodeDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003059 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003060 * @doc: the document
3061 * @cur: the current node
3062 * @level: the imbrication level for indenting
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003063 * @format: is formatting allowed
Daniel Veillard97b58771998-10-20 06:14:16 +00003064 *
3065 * Dump an XML node, recursive behaviour,children are printed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003066 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003067static void
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003068xmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
3069 int format) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003070 int i;
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003071 xmlNodePtr tmp;
Daniel Veillard260a68f1998-08-13 03:39:55 +00003072
3073 if (cur == NULL) {
3074 fprintf(stderr, "xmlNodeDump : node == NULL\n");
3075 return;
3076 }
Daniel Veillard0bef1311998-10-14 02:36:47 +00003077 if (cur->type == XML_TEXT_NODE) {
Daniel Veillard14fff061999-06-22 21:49:07 +00003078 if (cur->content != NULL) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003079 xmlChar *buffer;
Daniel Veillard14fff061999-06-22 21:49:07 +00003080
3081 buffer = xmlEncodeEntitiesReentrant(doc, cur->content);
3082 if (buffer != NULL) {
3083 xmlBufferWriteCHAR(buf, buffer);
Daniel Veillard6454aec1999-09-02 22:04:43 +00003084 xmlFree(buffer);
Daniel Veillard14fff061999-06-22 21:49:07 +00003085 }
3086 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003087 return;
3088 }
Daniel Veillardb96e6431999-08-29 21:02:19 +00003089 if (cur->type == XML_PI_NODE) {
3090 if (cur->content != NULL) {
3091 xmlBufferWriteChar(buf, "<?");
3092 xmlBufferWriteCHAR(buf, cur->name);
3093 if (cur->content != NULL) {
3094 xmlBufferWriteChar(buf, " ");
3095 xmlBufferWriteCHAR(buf, cur->content);
3096 }
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003097 xmlBufferWriteChar(buf, "?>");
Daniel Veillardb96e6431999-08-29 21:02:19 +00003098 }
3099 return;
3100 }
Daniel Veillard0bef1311998-10-14 02:36:47 +00003101 if (cur->type == XML_COMMENT_NODE) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003102 if (cur->content != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003103 xmlBufferWriteChar(buf, "<!--");
3104 xmlBufferWriteCHAR(buf, cur->content);
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003105 xmlBufferWriteChar(buf, "-->");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003106 }
3107 return;
3108 }
Daniel Veillardccb09631998-10-27 06:21:04 +00003109 if (cur->type == XML_ENTITY_REF_NODE) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003110 xmlBufferWriteChar(buf, "&");
3111 xmlBufferWriteCHAR(buf, cur->name);
3112 xmlBufferWriteChar(buf, ";");
Daniel Veillardccb09631998-10-27 06:21:04 +00003113 return;
3114 }
Daniel Veillardb05deb71999-08-10 19:04:08 +00003115 if (cur->type == XML_CDATA_SECTION_NODE) {
3116 xmlBufferWriteChar(buf, "<![CDATA[");
3117 if (cur->content != NULL)
3118 xmlBufferWriteCHAR(buf, cur->content);
3119 xmlBufferWriteChar(buf, "]]>");
3120 return;
3121 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003122
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003123 if (format == 1) {
3124 tmp = cur->childs;
3125 while (tmp != NULL) {
3126 if ((tmp->type == XML_TEXT_NODE) ||
3127 (tmp->type == XML_ENTITY_REF_NODE)) {
3128 format = 0;
3129 break;
3130 }
3131 tmp = tmp->next;
3132 }
3133 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003134 xmlBufferWriteChar(buf, "<");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003135 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003136 xmlBufferWriteCHAR(buf, cur->ns->prefix);
3137 xmlBufferWriteChar(buf, ":");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003138 }
3139
Daniel Veillard5099ae81999-04-21 20:12:07 +00003140 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003141 if (cur->nsDef)
Daniel Veillard5099ae81999-04-21 20:12:07 +00003142 xmlNsListDump(buf, cur->nsDef);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003143 if (cur->properties != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00003144 xmlAttrListDump(buf, doc, cur->properties);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003145
3146 if ((cur->content == NULL) && (cur->childs == NULL)) {
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003147 xmlBufferWriteChar(buf, "/>");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003148 return;
3149 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003150 xmlBufferWriteChar(buf, ">");
Daniel Veillard14fff061999-06-22 21:49:07 +00003151 if (cur->content != NULL) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003152 xmlChar *buffer;
Daniel Veillard14fff061999-06-22 21:49:07 +00003153
3154 buffer = xmlEncodeEntitiesReentrant(doc, cur->content);
3155 if (buffer != NULL) {
3156 xmlBufferWriteCHAR(buf, buffer);
Daniel Veillard6454aec1999-09-02 22:04:43 +00003157 xmlFree(buffer);
Daniel Veillard14fff061999-06-22 21:49:07 +00003158 }
3159 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003160 if (cur->childs != NULL) {
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003161 if (format) xmlBufferWriteChar(buf, "\n");
3162 xmlNodeListDump(buf, doc, cur->childs, level + 1, format);
3163 if ((xmlIndentTreeOutput) && (format))
3164 for (i = 0;i < level;i++)
3165 xmlBufferWriteChar(buf, " ");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003166 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003167 xmlBufferWriteChar(buf, "</");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003168 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003169 xmlBufferWriteCHAR(buf, cur->ns->prefix);
3170 xmlBufferWriteChar(buf, ":");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003171 }
3172
Daniel Veillard5099ae81999-04-21 20:12:07 +00003173 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003174 xmlBufferWriteChar(buf, ">");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003175}
3176
Daniel Veillard97b58771998-10-20 06:14:16 +00003177/**
3178 * xmlDocContentDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00003179 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00003180 * @cur: the document
3181 *
3182 * Dump an XML document.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003183 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003184static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00003185xmlDocContentDump(xmlBufferPtr buf, xmlDocPtr cur) {
Daniel Veillardbe70ff71999-07-05 16:50:46 +00003186 xmlBufferWriteChar(buf, "<?xml version=");
3187 if (cur->version != NULL)
3188 xmlBufferWriteQuotedString(buf, cur->version);
3189 else
3190 xmlBufferWriteChar(buf, "\"1.0\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003191 if (cur->encoding != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00003192 xmlBufferWriteChar(buf, " encoding=");
3193 xmlBufferWriteQuotedString(buf, cur->encoding);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003194 }
3195 switch (cur->standalone) {
3196 case 0:
Daniel Veillard5099ae81999-04-21 20:12:07 +00003197 xmlBufferWriteChar(buf, " standalone=\"no\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003198 break;
3199 case 1:
Daniel Veillard5099ae81999-04-21 20:12:07 +00003200 xmlBufferWriteChar(buf, " standalone=\"yes\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00003201 break;
3202 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003203 xmlBufferWriteChar(buf, "?>\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003204 if (cur->intSubset != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00003205 xmlDtdDump(buf, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003206 if (cur->root != NULL) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00003207 xmlNodePtr child = cur->root;
3208
Daniel Veillard260a68f1998-08-13 03:39:55 +00003209 /* global namespace definitions, the old way */
3210 if (oldXMLWDcompatibility)
Daniel Veillard5099ae81999-04-21 20:12:07 +00003211 xmlGlobalNsListDump(buf, cur->oldNs);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003212 else
3213 xmlUpgradeOldNs(cur);
Daniel Veillardb96e6431999-08-29 21:02:19 +00003214
3215 while (child != NULL) {
Daniel Veillard7d2c2761999-10-11 15:09:51 +00003216 xmlNodeDump(buf, cur, child, 0, 1);
3217 xmlBufferWriteChar(buf, "\n");
Daniel Veillardb96e6431999-08-29 21:02:19 +00003218 child = child->next;
3219 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003220 }
3221}
3222
Daniel Veillard97b58771998-10-20 06:14:16 +00003223/**
3224 * xmlDocDumpMemory:
3225 * @cur: the document
3226 * @mem: OUT: the memory pointer
3227 * @size: OUT: the memory lenght
3228 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003229 * Dump an XML document in memory and return the xmlChar * and it's size.
Daniel Veillard97b58771998-10-20 06:14:16 +00003230 * It's up to the caller to free the memory.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003231 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003232void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003233xmlDocDumpMemory(xmlDocPtr cur, xmlChar**mem, int *size) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003234 xmlBufferPtr buf;
3235
Daniel Veillard260a68f1998-08-13 03:39:55 +00003236 if (cur == NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003237#ifdef DEBUG_TREE
3238 fprintf(stderr, "xmlDocDumpMemory : document == NULL\n");
3239#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00003240 *mem = NULL;
3241 *size = 0;
3242 return;
3243 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003244 buf = xmlBufferCreate();
3245 if (buf == NULL) {
3246 *mem = NULL;
3247 *size = 0;
3248 return;
3249 }
3250 xmlDocContentDump(buf, cur);
Daniel Veillardb05deb71999-08-10 19:04:08 +00003251 *mem = xmlStrndup(buf->content, buf->use);
Daniel Veillard5099ae81999-04-21 20:12:07 +00003252 *size = buf->use;
Daniel Veillardb05deb71999-08-10 19:04:08 +00003253 xmlBufferFree(buf);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003254}
3255
Daniel Veillard97b58771998-10-20 06:14:16 +00003256/**
3257 * xmlGetDocCompressMode:
3258 * @doc: the document
3259 *
3260 * get the compression ratio for a document, ZLIB based
Daniel Veillard1e346af1999-02-22 10:33:01 +00003261 * Returns 0 (uncompressed) to 9 (max compression)
Daniel Veillard151b1b01998-09-23 00:49:46 +00003262 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003263int
3264 xmlGetDocCompressMode (xmlDocPtr doc) {
Daniel Veillard15a8df41998-09-24 19:15:06 +00003265 if (doc == NULL) return(-1);
3266 return(doc->compression);
3267}
3268
Daniel Veillard97b58771998-10-20 06:14:16 +00003269/**
3270 * xmlSetDocCompressMode:
3271 * @doc: the document
3272 * @mode: the compression ratio
3273 *
3274 * set the compression ratio for a document, ZLIB based
3275 * Correct values: 0 (uncompressed) to 9 (max compression)
3276 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003277void
3278xmlSetDocCompressMode (xmlDocPtr doc, int mode) {
Daniel Veillard15a8df41998-09-24 19:15:06 +00003279 if (doc == NULL) return;
3280 if (mode < 0) doc->compression = 0;
3281 else if (mode > 9) doc->compression = 9;
3282 else doc->compression = mode;
3283}
3284
Daniel Veillard97b58771998-10-20 06:14:16 +00003285/**
3286 * xmlGetCompressMode:
3287 *
3288 * get the default compression mode used, ZLIB based.
Daniel Veillard1e346af1999-02-22 10:33:01 +00003289 * Returns 0 (uncompressed) to 9 (max compression)
Daniel Veillard15a8df41998-09-24 19:15:06 +00003290 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003291int
3292 xmlGetCompressMode(void) {
Daniel Veillard151b1b01998-09-23 00:49:46 +00003293 return(xmlCompressMode);
3294}
Daniel Veillard97b58771998-10-20 06:14:16 +00003295
3296/**
3297 * xmlSetCompressMode:
3298 * @mode: the compression ratio
3299 *
3300 * set the default compression mode used, ZLIB based
3301 * Correct values: 0 (uncompressed) to 9 (max compression)
3302 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003303void
3304xmlSetCompressMode(int mode) {
Daniel Veillard151b1b01998-09-23 00:49:46 +00003305 if (mode < 0) xmlCompressMode = 0;
Daniel Veillard15a8df41998-09-24 19:15:06 +00003306 else if (mode > 9) xmlCompressMode = 9;
Daniel Veillard151b1b01998-09-23 00:49:46 +00003307 else xmlCompressMode = mode;
3308}
3309
Daniel Veillard97b58771998-10-20 06:14:16 +00003310/**
3311 * xmlDocDump:
3312 * @f: the FILE*
3313 * @cur: the document
3314 *
3315 * Dump an XML document to an open FILE.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003316 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003317void
3318xmlDocDump(FILE *f, xmlDocPtr cur) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003319 xmlBufferPtr buf;
3320
Daniel Veillard260a68f1998-08-13 03:39:55 +00003321 if (cur == NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003322#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00003323 fprintf(stderr, "xmlDocDump : document == NULL\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003324#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00003325 return;
3326 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00003327 buf = xmlBufferCreate();
3328 if (buf == NULL) return;
3329 xmlDocContentDump(buf, cur);
3330 xmlBufferDump(f, buf);
3331 xmlBufferFree(buf);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003332}
3333
Daniel Veillard97b58771998-10-20 06:14:16 +00003334/**
3335 * xmlSaveFile:
3336 * @filename: the filename
3337 * @cur: the document
3338 *
3339 * Dump an XML document to a file. Will use compression if
Daniel Veillard11a48ec1999-11-23 10:40:46 +00003340 * compiled in and enabled. If @filename is "-" the stdout file is
3341 * used.
Daniel Veillard97b58771998-10-20 06:14:16 +00003342 * returns: the number of file written or -1 in case of failure.
Daniel Veillard151b1b01998-09-23 00:49:46 +00003343 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003344int
3345xmlSaveFile(const char *filename, xmlDocPtr cur) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00003346 xmlBufferPtr buf;
Daniel Veillard151b1b01998-09-23 00:49:46 +00003347#ifdef HAVE_ZLIB_H
3348 gzFile zoutput = NULL;
3349 char mode[15];
3350#endif
Daniel Veillardccb09631998-10-27 06:21:04 +00003351 FILE *output = NULL;
Daniel Veillard151b1b01998-09-23 00:49:46 +00003352 int ret;
3353
Daniel Veillard5099ae81999-04-21 20:12:07 +00003354 /*
3355 * save the content to a temp buffer.
3356 */
3357 buf = xmlBufferCreate();
3358 if (buf == NULL) return(0);
3359 xmlDocContentDump(buf, cur);
3360
Daniel Veillard151b1b01998-09-23 00:49:46 +00003361#ifdef HAVE_ZLIB_H
Daniel Veillard11a48ec1999-11-23 10:40:46 +00003362 if (cur->compression < 0) cur->compression = xmlCompressMode;
Daniel Veillarddc3dd9d1998-09-24 19:25:54 +00003363 if ((cur->compression > 0) && (cur->compression <= 9)) {
3364 sprintf(mode, "w%d", cur->compression);
Daniel Veillard11a48ec1999-11-23 10:40:46 +00003365 if (!strcmp(filename, "-"))
3366 zoutput = gzdopen(1, mode);
3367 else
3368 zoutput = gzopen(filename, mode);
Daniel Veillard151b1b01998-09-23 00:49:46 +00003369 }
3370 if (zoutput == NULL) {
3371#endif
3372 output = fopen(filename, "w");
3373 if (output == NULL) return(-1);
3374#ifdef HAVE_ZLIB_H
3375 }
Daniel Veillard151b1b01998-09-23 00:49:46 +00003376
Daniel Veillard151b1b01998-09-23 00:49:46 +00003377 if (zoutput != NULL) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003378 ret = gzwrite(zoutput, buf->content, sizeof(xmlChar) * buf->use);
Daniel Veillard151b1b01998-09-23 00:49:46 +00003379 gzclose(zoutput);
Daniel Veillard5099ae81999-04-21 20:12:07 +00003380 } else {
3381#endif
3382 ret = xmlBufferDump(output, buf);
3383 fclose(output);
3384#ifdef HAVE_ZLIB_H
Daniel Veillard151b1b01998-09-23 00:49:46 +00003385 }
3386#endif
Manish Vachharajani5e60f5a1999-05-29 03:04:30 +00003387 xmlBufferFree(buf);
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003388 return(ret * sizeof(xmlChar));
Daniel Veillard151b1b01998-09-23 00:49:46 +00003389}
3390